settings: a cluster says when it wants to be asked - #42
Merged
Merged
Conversation
ADR 0011's second dial, accepted 2026-09-10 and until now only on paper. The level moved what may happen; nothing moved who must agree, so the configuration the ADR itself named as the one customers most want — "may restart a service, but always ask" — was inexpressible, as was its opposite. consent is a per-cluster file beside the action level: never, destructive, always. Unset means always, which is exactly today's behaviour, so no deployed cluster changes. A file others may write is refused for a sharper reason than the level's — whoever can write it can stop the cluster asking a person before it acts. The two dials are enforced at different points because they answer different questions. The executor can answer "does this cluster serve this class?" from its own state and trusts the SaaS for nothing. It cannot observe whether a person was asked, so the SaaS does the asking and reports it on the channel-open frame, and the executor refuses a call its own setting required a person for and did not get. That catches the honest failure — a stale mirror, a bug, an operator who changed the file a minute ago — and turns it into an audited refusal instead of an unattended call. It does not catch a SaaS that lies; the action level is the control that survives that, and the claim is audited so a customer sees an approval asserted for a call their own record never saw. Destructive is a declared property of a tool, not a fourth impact class. No tool sets it: creates create, reads read, probes clean up after themselves. So destructive currently asks for nothing, which the startup line says out loud — computed from the allowlist, so the caveat disappears by itself when someone adds one rather than becoming the next comment that outlived its subject. needsApproval's comment said approval was required "every time" and pointed at the ladder's later rungs as where it would become configurable. They are here; the comment is rewritten rather than left standing. Signed-off-by: Travis Wu <travis.wu@bigstack.co>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
ADR 0011's consent dial on the executor: a
consentfile besideaction-level(never/destructive/always), aRegistry.Consent()observable,Approvedon the channel-open frame, and a refusal for a call this cluster required a person for and did not get.Why
The level moved what may happen; nothing moved who must agree.
ActionApprovedecides who may approve, never whether approval is required — that was a fixed set in the SaaS'sneedsApproval. So "may restart a service, but always ask" was inexpressible, as was its opposite.Unset means
always, which is exactly what the gate already did, so no deployed cluster changes. No cluster has a consent file today, so the new refusal cannot break a working setup.Reviewer notes
Why the executor enforces at all. It cannot see the human — only the SaaS can ask one. But without a refusal here, a value on the node would change nothing: a SaaS with a stale mirror would skip the question and the cluster would never know. With it, that becomes an audited refusal. It does not survive a SaaS that lies —
approvedcomes over the tunnel — and that is stated in the field's own comment; the action level is the control that does, because this side answers it from its own state.The file's mode rule is the level's, for a sharper reason: whoever can write it can stop the cluster asking a person before it acts. Readability is unconstrained — a policy statement its customer should read without root.
destructiveasks for nothing today. No allowlist entry sets it.DestructiveToolsExist()is computed rather than written down, so the startup caveat disappears on its own when someone adds a destroying tool instead of becoming the next stale comment.A break that did not fail, and the test that now catches it. Hardcoding
truewhereserveToolreadsch.Open.Approvedpassed the entire suite — every consent test called the registry directly, so none crossed the tunnel.TestApprovalOnTheOpenFrameReachesTheRegistryruns the real session in both directions; the same break fails it.Two other breaks, each watched then restored: flipping
DefaultConsenttoneverfailed four tests including the ADR 0016 layer-2 wiring test; disablingrefusedWithoutAPersonfailed the refusal test.Callgained anapprovedparameter — the churn in the existing tests is that and nothing else.Docs
bigstack-handbook#639.