Tier C key wiring
editorial(infrastructure): fix tier-c-key-wiring's per-provider-drop-in fabrication throughout (Track-B) — confirmed against local-doorman.env.example: real config is one shared operator-managed environment file (Anthropic/Gemini/OpenAI keys together, single EnvironmentFile= override), not one systemd drop-in per provider; per-provider rotation is NOT atomic as originally claimed; de-narrated a standing correction and applied the fix consistently across Where-keys-live/Provisioning/Rotation/Breach-response sections rather than leaving it flagged once at the top; ES pair (dated 2026-07-31, newer than EN) had the same wrong claim and had never been corrected at all; register-clean EN+ES
@@ -22,21 +22,21 @@ The universal principle is that API keys live at the gateway only — never in a ## Where keys live Provider API keys are held in systemd unit drop-in files on the workspace virtual machine. The drop-in path follows the standard systemd pattern for extending a service unit without modifying the unit file itself. Each provider may have its own drop-in file, which makes per-provider rotation atomic: rotating the key for one provider does not require touching any other provider's configuration. (Correction, 2026-08-02, verified against canonical `origin/main`: the real config, `service-slm/docs/deploy/local-doorman.env.example`, holds Anthropic, Gemini, and OpenAI keys together in one shared env file, loaded via a single `EnvironmentFile=` override applied to the whole unit — not one drop-in file per provider. Per-provider rotation is not atomic as described. The four permitted Tier C call purposes described elsewhere in this article — editorial refinement, citation grounding, entity disambiguation, initial knowledge graph construction — are independently confirmed accurate. Flagged, not resolved.) Provider API keys are held together in a single operator-managed environment file on the workspace virtual machine, loaded via one `EnvironmentFile=` override applied to the whole Doorman unit — Anthropic, Gemini, and OpenAI keys all live in that one file, not in separate per-provider drop-ins. Rotating one provider's key means editing that shared file and reloading the service; it isn't isolated from the other providers' configuration the way a true per-provider drop-in would be. Drop-in files are owned by root and readable by the service user running the Doorman. They are not tracked in any version-control repository, not included in any backup that publishes outside the virtual machine, and not present anywhere in the Git history. The `.gitignore` at the workspace root does not need to mention them because they live outside the repository entirely. The environment file is owned by root and readable by the service user running the Doorman. It is not tracked in any version-control repository, not included in any backup that publishes outside the virtual machine, and not present anywhere in the Git history. The `.gitignore` at the workspace root does not need to mention it because it lives outside the repository entirely. The Doorman binary reads keys from its environment at startup and holds them in process memory. Keys are never written to disk by the Doorman, never echoed in response bodies, and never included in log output at any log level. Audit-ledger entries record the provider name, not any portion of the key. A future strengthening of this posture, planned for a later milestone, will replace the plaintext drop-in with a sops-encrypted file that the Doorman decrypts into its runtime environment using an operator-held decryption key that is never present on the virtual machine in plaintext. The current systemd-tier approach is the operational baseline until that milestone lands. A future strengthening of this posture, planned for a later milestone, will replace the plaintext environment file with a sops-encrypted file that the Doorman decrypts into its runtime environment using an operator-held decryption key that is never present on the virtual machine in plaintext. The current systemd-tier approach is the operational baseline until that milestone lands. ## Provisioning a key Activating a new provider key requires operator presence for the steps that touch the key value, and proceeds through an eight-step sequence. The operator obtains the key from the provider's console and copies it to a temporary file on the virtual machine. The temporary file is created with restricted permissions before the key value is written to it. The Doorman's systemd drop-in is then written using the key from the temporary file, the service is reloaded, and the health endpoint is queried to confirm the service has picked up the new configuration. A low-cost test call verifies that the key routes correctly and that an audit-ledger entry is produced with the expected fields. The operator then removes the temporary file using a secure deletion tool. The final step is a workspace changelog entry recording the activation event: provider name, date, and the reference to the first audit-ledger entry. The key value does not appear in the changelog entry or in any commit message. Activating a new provider key requires operator presence for the steps that touch the key value, and proceeds through an eight-step sequence. The operator obtains the key from the provider's console and copies it to a temporary file on the virtual machine. The temporary file is created with restricted permissions before the key value is written to it. The new key is then added to the shared environment file using the value from the temporary file, the service is reloaded, and the health endpoint is queried to confirm the service has picked up the new configuration. A low-cost test call verifies that the key routes correctly and that an audit-ledger entry is produced with the expected fields. The operator then removes the temporary file using a secure deletion tool. The final step is a workspace changelog entry recording the activation event: provider name, date, and the reference to the first audit-ledger entry. The key value does not appear in the changelog entry or in any commit message. ## Rotation Quarterly rotation per provider is the default cadence, aligned with calendar quarters. The procedure generates a new key at the provider console while the old key remains active, replaces the drop-in with the new key, reloads the service, verifies operation, and retains the old key at the provider side for a forty-eight-hour window in case rollback is needed. A rotation event marker in the audit ledger delineates pre-rotation and post-rotation usage, supporting post-incident investigation. Quarterly rotation per provider is the default cadence, aligned with calendar quarters. The procedure generates a new key at the provider console while the old key remains active, replaces that provider's key line in the shared environment file, reloads the service, verifies operation, and retains the old key at the provider side for a forty-eight-hour window in case rollback is needed. A rotation event marker in the audit ledger delineates pre-rotation and post-rotation usage, supporting post-incident investigation. Accelerated rotation is appropriate when a compromise is suspected (see the breach response section), when the provider mandates rotation on its own schedule, or when the operator chooses a more frequent cadence for a high-volume deployment. @@ -54,7 +54,7 @@ Monthly review by the workspace Master-layer session aggregates prior-month usag ## Breach response A breach is any event that exposes a key value beyond the Doorman boundary: accidental logging, accidental commit to a repository, a panic stack trace that echoes environment variables, inclusion in an inbox or outbox message, or appearance in a chat transcript used as a reproduction step. The response sequence is fixed and the first step is non-negotiable: revoke the key at the provider console immediately, before cleaning up the source of the leak. Revocation makes the leaked key worthless and bounds any potential misuse window. The remaining steps — removing the drop-in, provisioning a fresh key through the standard eight-step runbook, sweeping the audit ledger for anomalous activity between the leak timestamp and revocation timestamp, and logging the incident — follow in order. A breach is any event that exposes a key value beyond the Doorman boundary: accidental logging, accidental commit to a repository, a panic stack trace that echoes environment variables, inclusion in an inbox or outbox message, or appearance in a chat transcript used as a reproduction step. The response sequence is fixed and the first step is non-negotiable: revoke the key at the provider console immediately, before cleaning up the source of the leak. Revocation makes the leaked key worthless and bounds any potential misuse window. The remaining steps — removing the compromised key from the shared environment file, provisioning a fresh key through the standard eight-step runbook, sweeping the audit ledger for anomalous activity between the leak timestamp and revocation timestamp, and logging the incident — follow in order. The incident log entry in the workspace cleanup log carries the leak source, the revocation timestamp, audit-ledger sweep findings, and the root cause and corrective action. This entry is part of the continuous-disclosure substrate: material operational events are recorded in signed, date-stamped commits that are suitable for review.