fix(secrets): keep startup alive when TTS SecretRefs are missing#101265
Conversation
08066db to
cd67c9c
Compare
|
Codex review: needs maintainer review before merge. Reviewed July 17, 2026, 12:01 AM ET / 04:01 UTC. Summary PR surface: Source +615, Tests +1263, Docs +16. Total +1894 across 45 files. Reproducibility: yes. from source with high confidence: configure an enabled TTS provider with a missing environment SecretRef and start the Gateway; current main eagerly resolves the active ref and aborts startup. The linked issue includes the resulting SecretRefResolutionError, although this review did not execute the failing current-main setup locally. Review metrics: 2 noteworthy metrics.
Stored data model Root-cause cluster Members:
Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Risk before merge
Maintainer options:
Next step before merge
Security Review detailsBest possible solution: Rebase the owner-isolation design onto current main, rerun the exact-head live startup/no-fallback proof and required gates, then land it with Gateway ingress, unknown owners, malformed values, reload, and write preflight remaining fail-closed; add future owner classes only alongside complete request guards and diagnostic coverage. Do we have a high-confidence way to reproduce the issue? Yes from source with high confidence: configure an enabled TTS provider with a missing environment SecretRef and start the Gateway; current main eagerly resolves the active ref and aborts startup. The linked issue includes the resulting SecretRefResolutionError, although this review did not execute the failing current-main setup locally. Is this the best way to solve the issue? Yes. Owner-aware cold-start isolation is more maintainable than a TTS-only exception because it centralizes the fail-open decision, retains strict behavior for unmapped and Gateway-required surfaces, and prevents alternate credential fallback at the owner boundary. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against ff9b29167352. Label changesLabel changes:
Label justifications:
Evidence reviewedPR surface: Source +615, Tests +1263, Docs +16. Total +1894 across 45 files. View PR surface stats
What I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
Review history (17 earlier review cycles; latest 8 shown)
|
d94a892 to
2cb6b39
Compare
2cb6b39 to
5f3452a
Compare
5f3452a to
606539e
Compare
606539e to
4572dae
Compare
Co-authored-by: snowzlmbot <[email protected]>
|
Merged via squash.
|
First submitted: July 6, 2026, 10:00 PM (US Eastern Time) / 02:00 UTC.
Last body edit: July 17, 2026.
Latest head commit: July 17, 2026.
Closes #101204
What Problem This Solves
Fixes an issue where one missing SecretRef could abort the whole Gateway even when the credential belonged only to an optional capability or one model provider. A temporarily unavailable TTS key or unused model-provider key could therefore take unrelated chat, channels, tools, and plugins offline.
Why This Change Was Made
Secret assignments now carry explicit owner metadata: owner kind and id, whether Gateway ingress requires the value, and whether failure isolates the owner or fails closed. Cold startup isolates only known non-Gateway owners. The exact capability or provider becomes configured-unavailable, receives a typed redacted warning, and cannot silently fall back to environment or profile credentials.
Gateway ingress authentication remains required. Structurally invalid refs, unknown owners, and all unpartitioned surfaces still fail closed. Reload remains strict and preserves the last-known-good snapshot; expanding isolation to reload is intentionally deferred.
This bounded foundation partitions two current owner classes:
capability:tts;provider:<id>, covering API keys, headers, and request transport credentials.The previous TTS-only optional-assignment machinery is removed. TTS uses the same generic owner registry and throws
SecretSurfaceUnavailableErrorthrough direct SDK, injected runtime, tool, automatic TTS, and Gateway RPC paths. Model auth checks the cold-provider registry before any env/profile discovery.Degraded owners are process-local and visible in status and doctor output. Persistence and the remaining channel/account/route partition work are follow-ups, not part of this PR. No config option, environment variable, protocol version, dependency, or persisted schema is added.
User Impact
On first Gateway startup, a missing TTS ref or unused configured model-provider ref no longer takes the whole Gateway down. The Gateway starts, logs a redacted owner-specific warning, and reports the owner in status/doctor. Calls into that owner fail with a typed unavailable error.
A missing
gateway.authtoken or password still refuses startup. Unknown ownership and malformed configuration still refuse startup. A failed explicit provider ref never activates an implicit environment or profile fallback.Release-note context: Gateway startup now isolates missing SecretRefs to known optional TTS and model-provider owners while keeping ingress auth and unknown ownership fail-closed.
Evidence
node scripts/run-vitest.mjs src/secrets/runtime.test.ts src/secrets/resolve.test.ts src/secrets/runtime-config-collectors-tts.test.ts src/secrets/runtime-degraded-state.test.ts— 54 tests passed.node scripts/run-vitest.mjs src/gateway/server-startup-secret-owner-isolation.test.ts src/gateway/server-startup-config.secrets.test.ts src/gateway/server-methods/tts.test.ts— 37 tests passed.node scripts/run-vitest.mjs src/tts/tts.test.ts packages/speech-core/src/tts.test.ts src/commands/status.summary.test.ts src/commands/doctor-gateway-health.test.ts— 82 tests passed across three shards.node scripts/run-vitest.mjs src/agents/model-auth.test.ts -t 'does not fall back|keeps the whole provider cold'— 4 tests passed; 152 unrelated tests skipped.node --max-old-space-size=8192 --import tsx scripts/generate-plugin-sdk-api-baseline.ts --check— passed.node scripts/run-node.mjs gateway --port <free> --bind loopback:/readyzreturned ready,capability:ttsemittedSECRETS_OWNER_UNAVAILABLE, and a present implicit TTS environment credential was not used for the failed explicit ref.No visual surface changed, so screenshot evidence is not applicable.
Risk and rollback
The compatibility change is intentional: known non-required owners now fail locally instead of failing whole-Gateway cold startup. The strict boundaries are covered by regressions for Gateway auth, unknown owners, invalid refs, reload/config-write preflight, and implicit fallback prevention.
Rollback is a code revert only. No config or state migration is required.
Co-authored-by: @snowzlmbot