# 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: ```sh 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: ```sh 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 before `git-receive-pack`. The post-receive hook records a sanitized value in queue events. If unset, events record `unknown`. - `SIP_WORKFLOW_REF`: optional worker override for the protected workflow ref. The worker accepts only valid refs under `refs/workflows/*`; unsafe or malformed values are ignored. The default is `refs/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/*` except `refs/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: ```text $GIT_DIR/sip/queue/*.event ``` The worker initializes and uses these state directories: ```text $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: ```text $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/queue` with 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.