--- id: BB-SPEC-7KUSUPJF type: spec title: Luci SSH secret management --- # Luci SSH secret management ## Intent Let operators add, replace, and delete Luci job secrets through the confined SSH interface. Secret administration must not require host shell or filesystem access. ## Interface The SSH CLI provides: - `secret list [ []]`, showing sorted identifiers and last-updated timestamps; - `secret add --bytes `, failing when the target exists; - `secret update --bytes `, failing when the target is absent; - `secret delete `, failing when the target is absent. Splitting add from update prevents accidental replacement and typo-created updates. Delete requires the complete repository, job, and secret identity in one command. There is no SSH operation to read or export a secret. ## Input and output Secret bytes arrive only through standard input. Values never appear in command arguments, environment variables, output, errors, public logs, or audit records. The declared byte count is mandatory. Zero-length values, premature end of input, trailing input, and values larger than 64 KiB fail without changing stored data. Arbitrary non-zero bytes within the limit are preserved exactly. Success reports only the operation and target identifiers. Failures reveal no secret content, digest, size, or partial value. ## Authorization Secret mutation requires an SSH key explicitly designated as a Luci secret administrator. Ordinary Luci SSH keys retain read-only reporting and run-submission access but cannot list or mutate secrets. The forced-command boundary remains active. Shells, TTYs, forwarding, and arbitrary filesystem access remain unavailable. ## Storage behavior Repository, job, and secret identifiers are non-empty safe path segments. Traversal, separators, ambiguous names, symlinks, and non-regular targets are rejected. Add, update, and delete are atomic. Failure, interruption, concurrent mutation, or exhausted storage leaves the previous state intact and no partial target visible. Stored values remain readable only by the Luci service identity and host root. A successful mutation is available to subsequently started job children without restarting Luci. Already materialized children keep their existing value. ## Audit Every list, add, update, and delete attempt records timestamp, authenticated key identity, operation, target identifiers, and outcome in private operator-visible audit state. Audit data never enters the public web UI, run history, logs, or artifacts. ## Acceptance - An authorized administrator can add a new environment or file secret using the same stored value format consumed by jobs. - An authorized administrator can atomically replace or delete an existing secret. - Add cannot overwrite; update cannot create; delete cannot silently accept an absent target. - List exposes only identifiers and last-updated timestamps. - Truncated, oversized, empty, malformed, or extra input cannot alter stored state. - Unauthorized keys cannot discover secret names or mutate values. - No supported SSH command returns secret content or a reusable verifier. - Concurrent operations produce one complete value, never mixed or partial bytes. - Secret values remain absent from process arguments, diagnostics, public surfaces, and audit records. - Existing SSH reporting and manual-run behavior remains unchanged.