- TestSet_RoundTripsThroughSecretbox: set → get → plaintext matches.
- TestSet_OverwriteOnSameName: UPSERT semantics.
- TestSet_InvalidNameRejected: regex enforcement (5 bad names).
- TestSet_EmptyValueRejected: nil/empty plaintext.
- TestSet_InvalidScopeRejected: zero AND both-set scope.
- TestList_NamesAndMetadataOnly: load-bearing — listing has no
plaintext or ciphertext exposed; the public surface can't leak.
- TestDelete_RemovesRow + TestDelete_MissingIsIdempotent.
- TestGet_CitextNameIsCaseInsensitive: pins citext semantics.
- TestCiphertext_IsActuallyEncryptedInDB: the spec called this out
explicitly. Reads the bytea column directly via SQL and asserts
the plaintext substring doesn't appear anywhere — would catch a
silent regression to plaintext-storage.
Set/Get/List/Delete over workflow_secrets. Plaintext is sealed via
internal/auth/secretbox (ChaCha20Poly1305 AEAD) before INSERT;
ciphertext + nonce live in the bytea columns. Plaintext never lives
in postgres.
Scope is a small XOR struct (RepoID xor OrgID); the table CHECK
mirrors it. Helpers RepoScope/OrgScope keep the XOR honest at call
sites — no struct-literal traps.
Public API:
Deps.Set(ctx, scope, name, plaintext, createdBy) error
Deps.Get(ctx, scope, name) ([]byte, error)
Deps.List(ctx, scope) ([]Meta, error) — names+metadata, no value
Deps.Delete(ctx, scope, name) error — idempotent
Get() is for the runner-side claim resolver only (S41c-2). Web UI
consumes List() — public listing surface deliberately can't reach
plaintext or ciphertext.
Errors mapped:
ErrInvalidScope — programmer error (zero or both scope fields)
ErrInvalidName — name regex/length cap mismatch (mirrors DB CHECK)
ErrEmptyValue — empty plaintext (operators usually mean delete)
ErrNotFound — no row for (scope, name)
- gofumpt fixes across the trigger package + dispatch handler
- drop the stale 'startedAtNow' placeholder var in enqueue.go that
the lint-unused script flagged as a dead 'silence unused import'
shim (it was originally a hint for S41c+, but never used)
- scripts/lint-unused.sh: ${ALLOWED_FILES[@]:-} so an empty
array doesn't trip set -u under macOS bash 3.2
Documents the three-layer flow (caller → worker → enqueue), the
trigger_event_id idempotency convention with the per-caller
construction table, the per-event-kind match semantics + glob
subset, the conservative collaborator gate decision, and the
workflow_dispatch HTTP surface. Calls out the S41b/S41b-2 split
and what's deliberately out of scope until S41c+.