row 281 design d3: a grant decision approved before a fire and executed after it, tests T6/T6b/T6c (sage-2574, #1786)

This commit is contained in:
jason.woltje committed 2026-10-22 04:58:09 -05:00
1 parent c746ce378c
commit 36c2d98b81
1 file changed
+18 -5
+18 -5
View File
@@ -1,7 +1,7 @@
# Row 281 build notes: a fire or a delete revokes the instance's grants (#1786) # Row 281 build notes: a fire or a delete revokes the instance's grants (#1786)
Builder Megavolt, reviewer Dewey, gate owner Sage. Design draft d2 for Dewey's approval. d2 adds Sage's Builder Megavolt, reviewer Dewey, gate owner Sage. Design draft d3 for Dewey's approval. d2 added Sage's
Q1/Q2 rulings (sage-2573) to d1 (dfebd16cc). No code until it is Q1/Q2 rulings (sage-2573) to d1 (dfebd16cc). d3 adds the approved-before-fire tests T6/T6b/T6c (sage-2574). No code until it is
approved. The results sections are filled in after the runs on Sage's gate. approved. The results sections are filled in after the runs on Sage's gate.
## Sources ## Sources
@@ -136,6 +136,13 @@ A host named only by an open decision has no record. Step 3a still runs `remove`
`#revokedSince` then ends that decision `revoked`. The Gitea side is the same through `#revokedSince` then ends that decision `revoked`. The Gitea side is the same through
`#giteaRevokedSince`. `#giteaRevokedSince`.
This is the case where a decision is approved before the fire and executed after it (sage-2574). Both checks
look for a `grant.revoked` of the agent recorded after the decision was raised (broker.mjs:1156 and :1678 at
47a35bf43). A fire's `grant.revoked` is always later than the approval, so the executor ends the decision
whenever it runs. The fired agent keeps its roles entry, so `#hostDefinition` and `#giteaRole` still pass, and
this check is the only thing that stops the decision. T6 and T6b test it. A delete also removes the roles
entry, so the executor refuses there as well.
## 4. A refusal (D4) ## 4. A refusal (D4)
Step G stops at the first grant that can't be revoked. Grants already revoked in this step G stay revoked and Step G stops at the first grant that can't be revoked. Grants already revoked in this step G stay revoked and
@@ -221,8 +228,14 @@ Bus, with the fake installer and the fake Gitea the row 235 and 236 tests use:
unrevoked. A repeat with B reachable completes and revokes only B and Gitea. unrevoked. A repeat with B reachable completes and revokes only B and Gitea.
- T5: Gitea's admin token can't be checked. The fire refuses with the Gitea grant intact. - T5: Gitea's admin token can't be checked. The fire refuses with the Gitea grant intact.
- T5b: a token DELETE fails. The fire refuses `gitea-left`. A repeat with Gitea back sweeps and completes. - T5b: a token DELETE fails. The fire refuses `gitea-left`. A repeat with Gitea back sweeps and completes.
- T6: an approved host grant decision that hasn't run yet, for the fired agent: the fire records - T6 (sage-2574): a host grant decision approved before the fire, executed after it. The fire records
`grant.revoked {granted: false}`, and the executor then ends that decision `revoked`. `grant.revoked {granted: false}` for (agent, host). The executor runs after `fire.done` and ends the decision
`revoked`: no `host_grants` row, no key file, no `add` sent to the host.
- T6b (sage-2574): the same for a Gitea grant decision. The executor ends it `revoked` before any Gitea call:
no `gitea_grants` row, no token file, and the fake Gitea saw no token create.
- T6c: a host or Gitea executor already in flight when step G starts. The host side aborts its claim (step
3a.1) and ends `revoked`. The Gitea side ends `revoked` at its step 8 check. Build-time check: a token the
in-flight executor created before that check must be deleted, or named in `serviceLeft`, and not left live.
- T7: an instance with no grant fires exactly as today. Same result keys, and the same events, counted. - T7: an instance with no grant fires exactly as today. Same result keys, and the same events, counted.
- T8: hosts.revoke and grants.revoke keep their records, their order and their tester refusals. - T8: hosts.revoke and grants.revoke keep their records, their order and their tester refusals.
@@ -237,7 +250,7 @@ G closes the request with `grant-revoke-failed`, if the launcher's tests stub `l
- M4: `lifecycleDelete` skips step G. Killed by T3. - M4: `lifecycleDelete` skips step G. Killed by T3.
- M5: the fire's host revoke goes local first (`lineFirst: false`). Killed by T4, because B's row is gone. - M5: the fire's host revoke goes local first (`lineFirst: false`). Killed by T4, because B's row is gone.
- M6: a Gitea revoke with something in `serviceLeft` counts as done. Killed by T5b. - M6: a Gitea revoke with something in `serviceLeft` counts as done. Killed by T5b.
- M7: open decisions left out of the set. Killed by T6. - M7: open decisions left out of the set. Killed by T6 and T6b.
- M8: step G skips the leftover-line retry. Killed by T4b. - M8: step G skips the leftover-line retry. Killed by T4b.
- M9: a failed leftover-line retry refuses the fire. Killed by T4b. - M9: a failed leftover-line retry refuses the fire. Killed by T4b.