These docs are under active development and cover the v0.20 Kobicha security model.
On this page
§3.2

Definition Schema

Every service is defined by a registry key under Machine\System\Services\<name>. The key name is the service name. This section defines every field in the service definition and its semantics.

A schema version is stored at Machine\System\Services\SchemaVersion (dword, currently 1). peinit MUST be forward-compatible: unknown registry values MUST be ignored. A newer schema version MUST NOT prevent boot -- peinit logs a warning but continues. The schema evolves additively (new optional fields) without breaking older peinit versions.

§3.2.1 Fields

Field Type Required Default Description
ImagePath string yes -- Absolute path to the service binary.
Arguments multi_string no -- Command-line arguments passed to the binary.
Type dword no 0 (Simple) Service type. 0 = Simple, 1 = Oneshot.
Triggers multi_string no -- Trigger list. Each entry is type or type:argument. See §3.1. If absent, service is demand-only.
Disabled dword no 0 If 1, triggers MUST NOT activate this service. Manual start via control interface is still permitted.
SafeMode dword no 0 If 1, peinit MUST attempt to start this service in Safe mode. Best-effort -- failure does not block Safe mode. ErrorControl=Critical implies SafeMode.
Identity string no LocalService Principal name for the service token. See §3.3.
RequiredPrivileges multi_string no -- Privilege names. All other privileges are removed from the token before exec. If absent, the token's default privileges are used.
Requires multi_string no -- Hard dependencies. All MUST be satisfied before this service starts. If any fails, this service fails.
Wants multi_string no -- Soft dependencies. Started before this service if they exist. Failure does not prevent this service from starting.
BindsTo multi_string no -- Runtime coupling. If any of these stop (for any reason), this service is stopped.
Conflicts multi_string no -- Mutual exclusion. Starting this service stops conflicting services.
OnFailure string no -- Service name to start when this service enters Failed state.
ErrorControl dword no 0 (Normal) 0 = Normal (remain Failed). 1 = Critical (sync and reboot).
RemainAfterExit dword no 0 Oneshot only. If 1, service stays in Completed state after successful exit.
SuccessExitCodes multi_string no -- Non-zero exit codes treated as success.
ExecStartPre multi_string no -- Commands to run before the main binary. Run sequentially; any failure aborts service start.
ExecStartPost multi_string no -- Commands to run after readiness (Simple) or successful exit (Oneshot).
HookIdentity string no -- Principal name for ExecStartPre and ExecStartPost processes. If absent, hooks run as the service's Identity.
ExecReload string no -- Reload command or signal. Prefix with signal: for a signal (e.g., signal:SIGHUP); anything else is parsed as an argv command. If absent, reload sends SIGHUP.
StartTimeout dword no 30 Seconds. Covers the entire start sequence: pre-hooks, fork/exec, and readiness wait.
StopTimeout dword no 10 Seconds to wait after SIGTERM before sending SIGKILL.
WatchdogTimeout dword no 0 Seconds between expected WATCHDOG=1 pings. 0 = disabled.
HealthCheck string no -- Command to run periodically as an active health check. Exit 0 = healthy.
HealthCheckInterval dword no 30 Seconds between health check runs.
HealthCheckTimeout dword no 5 Seconds before a health check is killed and considered failed.
HealthCheckRetries dword no 3 Consecutive failures before the service is considered unhealthy.
RestartPolicy dword no 1 (OnFailure) 0 = Never, 1 = OnFailure, 2 = Always.
RestartMaxRetries dword no 5 Maximum consecutive restarts before entering Failed state. The counter resets after the service sustains RestartWindow of Active health (see RestartWindow).
RestartWindow dword no 120 Seconds. The restart counter resets to zero once the service stays Active this long without failing.
RestartDelay dword no 1 Seconds to wait before restarting. Doubles on each consecutive failure (exponential backoff), capped at 60 seconds.
Readiness dword no 0 (Notify) 0 = Notify (sd_notify READY=1), 1 = Alive (process exists). Ignored for Oneshot services.
NotifyAccess dword no 0 (Main) Who may send sd_notify messages. 0 = Main (tracked main PID only).
FdStoreMax dword no 0 Maximum number of file descriptors in the per-service fd store. 0 = fd store disabled.
TimerPersistent dword no 1 If 1, catch up missed timer runs after reboot.
TimerJitter dword no 0 Maximum random delay in seconds added to each timer firing.
Environment multi_string no -- KEY=VALUE pairs added to the service's environment.
WorkingDirectory string no / Working directory for the service process.
LimitNOFILE dword no -- RLIMIT_NOFILE (max open file descriptors).
LimitCORE dword no -- RLIMIT_CORE (core dump size in bytes).
Conditions multi_string no -- Start-time conditions. Each entry is type:argument. All MUST pass or the service is skipped.
Asserts multi_string no -- Start-time assertions. Same format as Conditions. If any fails, service enters Failed.
DisplayName string no -- Human-readable name for status display.
Description string no -- Description of what the service does.
ServiceSecurity binary no inherit parent Security Descriptor controlling runtime operations on this service. See §3.4.

Known service-definition fields MUST NOT appear more than once in a collected definition. Duplicate known fields are validation errors. This is a defensive Peinit ingestion rule even when the LCS registry representation ordinarily provides at most one value per name. Unknown registry values are still ignored for forward compatibility.

§3.2.2 Field value formats

  • String fields -- when present, string fields MUST be non-empty unless this section explicitly defines empty-string handling for the field. An empty string for Identity is treated the same as an absent Identity and defaults to LocalService. An empty string for HookIdentity is treated the same as an absent HookIdentity and falls back to the service's Identity. DisplayName and Description use empty string as absence.

  • WorkingDirectory -- when present, MUST be a non-empty absolute path. If absent, it defaults to /. Filesystem existence, type, and access checks are performed by the later validation or runtime rules that consume the working directory.

  • SuccessExitCodes -- each entry is a decimal integer in the range 0-255 (a process exit code). Signal names and ranges are NOT accepted. Code 0 is always success implicitly and need not be listed.

  • Identity / HookIdentity -- either a well-known principal name (SYSTEM, LocalService, NetworkService, …), matched case-insensitively, or a literal SID string (S-1-5-18). authd resolves any other name (§3.3).

§3.2.3 Conditions and Asserts

Conditions and Asserts use the same type:argument format and the same check types:

Check type Format Passes when
path path:<path> Path exists (any type).
file file:<path> Regular file exists.
directory directory:<path> Directory exists.
registry registry:<key> Registry key exists.

Conditions: if any condition fails, the service is skipped (not failed). A skipped service satisfies its dependents -- it "succeeded" by not needing to run. All entries are AND'd.

Asserts: if any assert fails, the service enters Failed state with cause AssertionError. A failed assert means the service was expected to run but a required precondition is missing. All entries are AND'd.

Conditions are evaluated first. If all conditions pass, asserts are evaluated. Evaluation happens before dependency resolution and pre-exec hooks.

§3.2.3.1 Evaluation constraints

peinit is single-threaded PID 1 and MUST NOT block its event loop while evaluating checks. Two constraints follow:

  • registry: checks are cache-only. A registry:<key> check may only reference a key peinit already caches (under Machine\System\Services\ or Machine\System\Init\, §3.5); it is evaluated against the in-memory model, never via a live registry read. A registry: check naming any other key is a validation error -- the definition is rejected at load (cause ValidationError).
  • Filesystem checks (path:/file:/directory:) are evaluated off the main loop. A stat() can block uninterruptibly on hung I/O, so peinit evaluates these in a bounded forked helper rather than calling stat() from its event loop (see §4.1).

A check that cannot complete within its timeout is treated as not satisfied (fail-safe): the Condition skips the service, and the Assert fails it with cause AssertionError.

§3.2.4 Command string parsing

Fields that contain executable commands (ExecStartPre, ExecStartPost, ExecReload, HealthCheck) are parsed as follows: whitespace-split into argv, with double-quote grouping for arguments containing spaces. No shell expansion, no variable substitution, no glob expansion. peinit MUST NOT invoke a shell.

For command parsing, whitespace means ASCII space, horizontal tab, line feed, carriage return, form feed, and vertical tab. Other Unicode whitespace code points are ordinary argument characters.

Double quotes group text into a single argv element and are not retained in the resulting argument. Quote grouping MAY occur inside an argument; for example, --name="hello world" becomes one argv entry with the value --name=hello world. Empty quoted strings are preserved as empty argv entries.

Backslash has no escape semantics and is copied literally. Single quote is an ordinary character.

An empty or whitespace-only command string is invalid. An unclosed double quote is invalid. Invalid command strings are definition validation errors.

Command string parsing only produces argv. Executable path validation, if any, is performed by the service-definition validation or runtime execution rules that consume the parsed argv.

If a command requires shell features, a wrapper script MUST be used.

§3.2.5 Registry value types

Service definition fields map to registry value types as follows:

Spec type Registry type Description
string REG_SZ UTF-8 string.
multi_string REG_MULTI_SZ Ordered list of strings.
dword REG_DWORD 32-bit unsigned integer.
binary REG_BINARY Raw byte sequence.