# Site Coordination — ordered commands and results Site Coordination owns the ordered instructions sent to Site Runtime. Execution Core owns Runs and Attempts. A caller supplies an already constructed instruction using the 1C contract. This context validates and stores it, allocates its sequence and records the result when the Runtime caller replies. ## Internal interface Compose `adaptors.postgres.PostgresSiteProtocolStore(database)` with a `Database("site_coordination", url)` using its restricted runtime credentials. It implements the provider-independent `application.protocol.SiteProtocolStore` port. - `append(draft)` assigns a sequence and returns the saved command. The draft is a validated 1C command envelope without its `sequence` field. - `pull(environment, after_sequence=0, limit=100)` reads pending commands in order. Pages contain the acknowledgement position, commands and continuation cursor. Reading a page does not acknowledge anything. - `acknowledge(outcome)` verifies the command and execution identity, then records the result and advances acknowledgement together. Gaps and conflicts fail. - `get_outcome(environment, command_id)` reads the saved result, or returns `None` while the command has no recorded result. - `report_progress(report)` saves why the stream's next command waits: a code from the Runtime, never provider text. Only the next unacknowledged command may report, each report has its own ID, and repeating one is a replay. - `progress(environment, command_id)` reads that reason for a pending command, `site-queue-busy` for a later command while the next one waits, or `None`. - `upload_run_logs(token, command_id, upload)` (#1056) takes the logs that one of the Runtime's own read commands (`queued-batch.read-logs`, `reconciled-service.read-logs`) asked for, through `POST /v1/site/commands/run-logs/{commandId}`, up to 5 MiB with a limit of its own. It reads the command and its result through the store, takes the permit from the command's `readPermitId` and hands the bytes to the `RunLogUploads` owner (Execution Core's copy of the permit), which this context never imports. The text never travels in a command's result, and nothing here keeps it. - `upload_final_run_logs(token, run_id, attempt_id, upload)` (#1056) takes the final logs of a failed service, which the Runtime read before it removed the service, through `POST /v1/site/commands/run-logs/final/{runId}/{attemptId}` with the same headers and limit. No command asks for them; the `FinalRunLogUploads` owner checks that the Attempt is a started service of the Runtime's environment that has not ended, and keeps the first copy. Kubernetes and Slurm each have one configured stream. The stream aggregate lives in `pharos.aggregates` with kind `site_stream`. Commands and results are immutable children in `pharos.site_commands` and `pharos.site_command_outcomes`. All belong to the private `pharos_site_coordination` database. The common transaction writer records versions and receipts. Progress reports live in their own aggregate, kind `site_progress`, one per environment, so they never change the stream or its evidence; a report whose command has since been acknowledged is no longer read. Older code refuses nothing in the stream, and a rollback only loses the reports. Database guards require child writes to accompany their root mutation and prevent changing stored command/result evidence. A repeated identical command keeps its ID and sequence. A repeated identical result returns the saved outcome. Reusing an identity with different data fails. Corrupt stored envelopes, cursor state or receipts fail restoration. Batch observations may carry a fixed `failureCode` for permanent member consent loss, only with failed state and confirmed cleanup. Deploy the updated receiving Site API and Execution Core before the Runtime that emits this field; older strict receivers reject it. Existing stored outcomes without the field remain valid. Batch and service observations of an unfinished workload may carry a `waiting` code for why it has not run yet (#1053). Deploy the receiving Site API and Execution Core before a Runtime that sends it, for the same reason. The generated transport schemas remain outside the application/domain layers. This context emits no browser updates. The authenticated Runtime API, supervisor invocation and native execution follow in later tasks. [Design and verification](../../docs/epics/instantiate-and-run/ordered-commands.md).