Skip to content

Headless Service Contract

Assertions

SVC-001 - Installer configuration is complete and deterministic

Contract: The headless installer MUST expose and document every supported CLI option and environment override. CLI values MUST override environment values, current stable releases MUST be the default, unsupported intervals and port collisions MUST fail before installation, and non-interactive mode MUST never prompt.

Evidence:

SVC-002 - Installation is isolated and systemd units contain no secrets

Contract: Joplin Terminal, its profile, npm prefix, helper scripts, credentials, and the joplin-md-sync binary MUST use the managed per-user layout. Generated units MUST use absolute paths, contain no secret values, pass systemd verification where available, and retain reviewed sandbox exceptions for snap and filesystem sync targets.

Evidence:

SVC-003 - Service credentials are protected, distinct, and never leaked

Contract: Joplin, E2EE, MCP, Actions, and sync credentials MUST be read from protected regular files or bounded interactive prompts and MUST be removed from child environments, commands, logs, units, and reports. Generated MCP and Actions bearer tokens MUST be preserved across reruns and MUST be distinct from each other and from the Joplin token.

Evidence:

SVC-004 - Sync targets map to explicit Joplin settings

Contract: Every supported static sync target MUST map to its complete Joplin setting set. Browser-authorized targets MUST persist and verify browser authentication before service start; password-authorized and S3 targets MUST require their complete non-interactive credentials. Existing conflicting profile configuration MUST require explicit interactive or force approval.

Evidence:

SVC-005 - Release downloads are exact and verified

Contract: The installer MUST resolve stable release metadata, accept only the supported platform asset name at the expected GitHub Release URL, verify its exact SHA-256 entry before replacement, and refuse unknown existing binaries or malformed release tags. Installation MUST be idempotent.

Evidence:

SVC-006 - Upgrades preserve configuration and prove both APIs

Contract: Upgrade MUST update Joplin Terminal and joplin-md-sync independently without re-requesting stored sync secrets, preserve protected service tokens, restart both units in dependency order, and require bounded Joplin, MCP, and Actions smoke checks. Failed health checks MUST stop the restart loop and retain recoverable prior files.

Evidence:

SVC-007 - Purge is explicit, scoped, and idempotent

Contract: Purge MUST require exact interactive confirmation or explicit --yes in non-interactive mode, obtain the profile lock before deletion, remove only managed files and units, preserve unrelated user data, and be safe to repeat. Dry-run MUST delete nothing and MUST not require a working systemd bus.

Evidence:

SVC-008 - The supervisor fails closed and terminates cleanly

Contract: The Joplin Terminal supervisor MUST unlock E2EE without echoing the secret, bound sensitive child output, verify API readiness, propagate child failure through nonzero exit for systemd restart, terminate hung children, and reject port collisions, read-only profiles, and failed runtime self-checks before reporting readiness.

Evidence: