You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Both share ciSigningDecision(ledger, signerPresent):
ledger in scope
signer present
decision
no
—
skip (a bare read/run outside a work-unit is unaffected)
yes
no
fail (exit 65, actionable message)
yes
yes
sign
So the unconfigured posture is intentionally fatal in-pipeline — that is the whole point of "everything should be signed." But it's only safe if signing config reaches a deployment before or with the binary that enforces it.
The risk
A deployed user who updates the home-manager-installed prx binary to the first release containing #396/#427before configuring a signer will see prx ci (and in-pipeline scout read) start failing with exit 65. The env carries no signer by default, so masterSource: dev-bootstrap + no PRX_PROVENANCE_KEY ⇒ unconfigured ⇒ fail.
Mitigation options (pick one before cutting the signing release)
Gate fail-closed behind a transition flag. Have ciSigningDecision treat unconfigured as skip (warn, don't fail) unless an opt-in (e.g. PRX_REQUIRE_SIGNED_DERIVATIONS=1) is set, then flip the default in a later release once deployments are known to carry signing config.
Option 1 keeps the gate strict and just makes sure the signer is present; option 2 keeps the binary tolerant until config catches up. They're not mutually exclusive.
Acceptance
A deployment that updates to the signing release without hand-configuring secrets does not start failing prx ci / in-pipeline scout read.
The path to the production posture (operator master, per-actor trust map, enforcement) is still discoverable via prx provenance status.
Why
The GH-352 provenance arc landed two fail-closed gates:
prx cihard-fails inside a work-unit when no signer is configured.scout read(one whose read is in a provenance ledger's scope) hard-fails the same way.Both share
ciSigningDecision(ledger, signerPresent):skip(a bare read/run outside a work-unit is unaffected)fail(exit 65, actionable message)signSo the unconfigured posture is intentionally fatal in-pipeline — that is the whole point of "everything should be signed." But it's only safe if signing config reaches a deployment before or with the binary that enforces it.
The risk
A deployed user who updates the home-manager-installed
prxbinary to the first release containing #396/#427 before configuring a signer will seeprx ci(and in-pipelinescout read) start failing with exit 65. The env carries no signer by default, somasterSource: dev-bootstrap+ noPRX_PROVENANCE_KEY⇒unconfigured⇒fail.Mitigation options (pick one before cutting the signing release)
programs.prx.provenance.enable(which exportsPRX_PROVENANCE_KEY=dev, and optionallyPRX_PROVENANCE_MASTER_FILE+PRX_REQUIRE_SIGNED_DERIVATIONS=1) to deployments at or before the release that carries feat(ci): fail-closed signing — local dev is the production surface (GH-352) #396/feat(scout): fail-closed signing for in-pipeline scout reads (GH-352) #427. The bootstrap dev master is zero-config, so even without an operator master the pipeline signs rather than fails.prx provenance statusthen nudges toward the operator-master production posture.ciSigningDecisiontreatunconfiguredasskip(warn, don't fail) unless an opt-in (e.g.PRX_REQUIRE_SIGNED_DERIVATIONS=1) is set, then flip the default in a later release once deployments are known to carry signing config.Option 1 keeps the gate strict and just makes sure the signer is present; option 2 keeps the binary tolerant until config catches up. They're not mutually exclusive.
Acceptance
prx ci/ in-pipelinescout read.prx provenance status.Related: #396, #427, GH-352. Companion: the release-cut + CI-secret tracking issue.
https://claude.ai/code/session_01LPzb9h4TgS7zCB4vWtNiS4