Deployment and Trust Boundaries #
This document describes the current deployment model for sip. The project is
still a CI control-plane sketch, so treat these rules as the minimum safe shape
for development and test deployments rather than a production hardening guide.
Installed Components #
Install the server-side hooks into each bare repository that should emit CI events:
bin/sip-install-hooks.rc /path/to/bare.git
The installer writes:
hooks/pre-receive: rejects client writes to CI-controlled and unsupported ref namespaces.hooks/post-receive: queues accepted branch and tag events under$GIT_DIR/sip/queue, then invokes the worker when an orchestrator module is installed.
The worker and log reader are launched through thin wrappers:
bin/sip-worker.rc /path/to/bare.git
bin/sip-logs.rc /path/to/bare.git [job-id]
The worker currently shells out to git, sqlite3, and, for the unsafe shell
executor, sh. These commands must be available in the trusted server PATH.
Trusted Environment #
Only the Git server wrapper, repository administrator, or service manager should
set sip environment variables. Do not allow clients to control these values
through push options or arbitrary receive-pack environment passthrough.
SIP_ACTOR: set by the trusted Git SSH/HTTP wrapper beforegit-receive-pack. The post-receive hook records a sanitized value in queue events. If unset, events recordunknown.SIP_WORKFLOW_REF: optional worker override for the protected workflow ref. The worker accepts only valid refs underrefs/workflows/*; unsafe or malformed values are ignored. The default isrefs/workflows/default.SIP_EXECUTOR_MODULE: optional path to an executor WASM module. This is an administrator-controlled runtime setting. The current example executor can run host shell commands and must not be exposed to untrusted configuration.
The installer substitutes @SIP_ROOT@ in the post-receive hook with the local
checkout path. That path is trusted configuration because the hook uses it to
find bin/sip-worker.rc.
Privileged Refs #
Client pushes are accepted only for normal branch and tag activity. The pre-receive hook rejects direct client writes to:
refs/ci/*refs/workflows/*- all
refs/sip/*exceptrefs/sip/orchestrator refs/notes/*refs/replace/*- unknown top-level ref namespaces
Server-side maintenance for protected refs must happen outside the client
receive path, for example with local git update-ref or local git fetch
commands run by an administrator or service account on the Git server.
refs/workflows/* stores protected workflow definitions. When a valid protected
workflow ref exists and contains .sip/workflows, it wins over workflow files
from the pushed worktree and records workflow_trust=protected.
refs/sip/orchestrator stores the service-owned workflow WASM module as a Git
commit containing workflow.wasm or workflow.wat. Client pushes may update
this ref today, so deployments that need stricter separation should install it
only through trusted server-side maintenance or tighten the hook policy before
accepting untrusted users.
refs/ci/* is service-owned output. The worker writes run manifests under
refs/ci/runs/* and best-effort latest status refs under
refs/ci/status/heads/* and refs/ci/status/tags/*.
Queue and Worker Operation #
The post-receive hook writes one tab-delimited event file per accepted branch or tag update under:
$GIT_DIR/sip/queue/*.event
The worker initializes and uses these state directories:
$GIT_DIR/sip/queue
$GIT_DIR/sip/done
$GIT_DIR/sip/failed
$GIT_DIR/sip/logs
$GIT_DIR/sip/tmp
It processes queued events in filename order. Successful events move to
sip/done. Malformed events and events whose new object cannot resolve to a
commit move to sip/failed. If the worker exits with an error before moving an
event, the event remains in sip/queue and a later worker run will retry it.
Job state and logs live in:
$GIT_DIR/sip/logs/jobs.sqlite
Back up $GIT_DIR/sip with the bare repository. The queue, done, and
failed directories are part of the audit trail and retry state. The logs
directory contains workflow execution rows, job rows, dependency rows, and
searchable job logs. The tmp directory contains transient checkouts and module
copies and does not need durable backup.
Security Boundary #
The current boundary is split across three layers:
- Git hooks are trusted receive-path glue. They reject protected refs and create event records, but should stay small and avoid complex policy.
- The Rust worker is the trusted control plane. It validates queue records, resolves immutable object IDs, selects workflow sources, writes CI refs, records SQLite state, and embeds Wasmtime.
- User workflow WASM is untrusted code. It can read selected workflow files and declare jobs only through the host ABI exposed by the worker.
The current Wasmtime host does not expose ambient WASI. Host functions mediate workflow file reads and job declaration. Future host capabilities for artifacts, network access, status updates, and secrets must enforce policy in Rust using immutable event/workflow metadata, actor identity, workflow trust, and explicit capability grants.
The unsafe-host-shell executor is outside the safe boundary. It intentionally
runs declared commands with sh -c in an archived checkout and is suitable only
for trusted development or test deployments until executor isolation and policy
are added.
Current Gaps #
These are known deployment risks tracked as follow-up work:
- Queue events are shape-validated but not authenticated. Protect
$GIT_DIR/sip/queuewith service-owned permissions and add event signing or a MAC before relying on queue provenance. - Pull and merge namespaces should remain rejected until their system-owned semantics are defined.
- Wasmtime resource limits are not yet configured.