row 281 design d2: Q1/Q2 rulings (sage-2573), the finding in the Why, T3b/T4b and M8/M9 (#1786)
This commit is contained in:
1 parent
dfebd16cc1
commit
c746ce378c
1 file changed
+36
-10
@@ -1,6 +1,7 @@
|
||||
# Row 281 build notes: a fire or a delete revokes the instance's grants (#1786)
|
||||
|
||||
Builder Megavolt, reviewer Dewey, gate owner Sage. Design draft d1 for Dewey's approval. No code until it is
|
||||
Builder Megavolt, reviewer Dewey, gate owner Sage. Design draft d2 for Dewey's approval. d2 adds Sage's
|
||||
Q1/Q2 rulings (sage-2573) to d1 (dfebd16cc). No code until it is
|
||||
approved. The results sections are filled in after the runs on Sage's gate.
|
||||
|
||||
## Sources
|
||||
@@ -13,7 +14,11 @@ approved. The results sections are filled in after the runs on Sage's gate.
|
||||
goes through `lifecycleDelete` and the same `revoke()`, so this design covers it unchanged.
|
||||
- Row 235 r6 section 6 (host revoke) and #436b r5 section 6 (Gitea revoke and the fire steps).
|
||||
|
||||
## 1. What happens today (read from the code, to be pinned by a test before the change)
|
||||
## 1. Why: what happens today (read from the code, to be pinned by a test before the change)
|
||||
|
||||
In short: today a delete of a granted instance unlinks the key files but leaves both grant records, the host
|
||||
lines and the Gitea token live, and a fire refuses `credential-revoke-failed` (sage-2573 asked for this here
|
||||
and on #1786). The details:
|
||||
|
||||
- **Fire.** `revoke()` (runtime.mjs:151) revokes only the roles entry's `credentials` services, then lists the
|
||||
agent's store directory and refuses `credential-revoke-failed` if any file is left. A host grant's key is
|
||||
@@ -63,9 +68,7 @@ awaits the reply, and `process.mjs` already returns async ops (`mayLaunch`). A r
|
||||
launcher with the refusal. `remove()` returns `{refusal: e.code}`, and the launcher closes the request through
|
||||
`lifecycleDone` with that code, as it does today for a writer refusal. The request is then closed, so the
|
||||
"repeat" for a delete is the human's new delete request. Grants revoked before the refusal stay revoked, and
|
||||
the new request's step G goes on from there. Q2 for Sage: is it fine that a refused delete needs a new request?
|
||||
The other choice is leaving the request taken, which today's launcher pass doesn't do for any refusal. Also to
|
||||
check at build time: the launcher's `host.op` reply timeout against an SSH remove and the Gitea calls. If it's
|
||||
the new request's step G goes on from there (Q2, ruled by sage-2573 below). Also to check at build time: the launcher's `host.op` reply timeout against an SSH remove and the Gitea calls. If it's
|
||||
shorter than they can take, the design needs a change before code.
|
||||
|
||||
## 3. Step G: what it revokes, and how
|
||||
@@ -158,11 +161,26 @@ A repeat runs the whole fire again: the checks, step A (nothing left to stop), s
|
||||
`grant.swept` with `by` set to the firing chief. That's an internal caller of an existing method, not a new
|
||||
verb. An entry left by an earlier manual `mosaic grants revoke` of the same agent blocks the fire the same
|
||||
way. That's intended: no grant outlives its instance, whichever verb started its revoke.
|
||||
- A host line left by an earlier manual `hosts.revoke` (`hostLineLeft`, no row) doesn't block the fire. Its
|
||||
record is already gone and `mosaic hosts sweep` owns it. The fire's result names it (section 6), so the human
|
||||
sees it. **Question Q1 for Dewey and Sage:** should it block instead, as the Gitea leftovers do? Blocking would
|
||||
make the two halves match. It would also make a fire wait on a host the human may already have retired.
|
||||
I lean toward naming it without blocking.
|
||||
- A host line left by an earlier manual `hosts.revoke` doesn't block the fire (Q1 below). These are the
|
||||
agent's `grant.revoke.closed` records with `hostLineLeft` and no later line removal for that tag. For each
|
||||
one whose host record still exists, step G sends `remove <user> <tag>` once. On success it records
|
||||
`grant.revoke.closed {revoke: <the old revoke id>, hostLine: 'removed', fire: true}`, so a later fire doesn't
|
||||
find it again. On failure it records nothing new and the fire goes on. The host and the tag go in
|
||||
`grantsLeft` (section 6).
|
||||
|
||||
## Rulings
|
||||
|
||||
- **Q1 (sage-2573):** a leftover line doesn't block the fire. If the host is reachable, the fire tries the
|
||||
removal once, because a fired agent's key line still on a host is the exact risk this row closes. If that
|
||||
try fails, the fire doesn't refuse. It names the host and the leftover line in the result and in the event
|
||||
the human sees. The human accepted that residue when their manual `hosts.revoke` left it, so it shouldn't
|
||||
stop a fire forever on a dead host. Dewey may push back on the retry if it widens step G more than it's
|
||||
worth.
|
||||
- **Q2 (sage-2573):** a delete refused at step G closes its request through the launcher's normal refusal
|
||||
path, and the human raises it again. A request left taken would strand, which is the shape DEFERRED already
|
||||
records for the >64-stops done. Conditions: the refusal names the instance, the grant and the reason (the
|
||||
`grant.revoke.refused` event, section 4). The repeat delete skips grants already revoked, as the repeat fire
|
||||
does. T3b tests both.
|
||||
|
||||
## 6. The result and the event (D6)
|
||||
|
||||
@@ -191,6 +209,12 @@ Bus, with the fake installer and the fake Gitea the row 235 and 236 tests use:
|
||||
token deleted and login prohibited at the fake Gitea. Afterwards that agent's `host.run` and Gitea use both
|
||||
refuse.
|
||||
- T3: the same through the delete (`lifecycleTake` then `lifecycleDelete`).
|
||||
- T3b (Q2): a delete refused at step G closes its request with `grant-revoke-failed`. The file and the
|
||||
instance are unchanged, and `grant.revoke.refused` names the instance, the grant and the reason. A new
|
||||
delete request then completes and skips the grants the first one revoked.
|
||||
- T4b (Q1): an earlier manual `hosts.revoke` left a line on host C. A fire with C reachable removes it and
|
||||
records the close. With C unreachable, the fire completes and names C and the tag in `grantsLeft` and in
|
||||
`fire.done`.
|
||||
- T4: host B unreachable. The fire refuses `grant-revoke-failed`, and `grant.revoke.refused` names the agent,
|
||||
`host:B` and `host-remove-failed`. The file is unchanged. Host A is revoked and recorded, host B's row and key
|
||||
file are still there, the Gitea grant is untouched (it comes after B in the order), and the credentials are
|
||||
@@ -214,6 +238,8 @@ G closes the request with `grant-revoke-failed`, if the launcher's tests stub `l
|
||||
- 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.
|
||||
- M7: open decisions left out of the set. Killed by T6.
|
||||
- M8: step G skips the leftover-line retry. Killed by T4b.
|
||||
- M9: a failed leftover-line retry refuses the fire. Killed by T4b.
|
||||
|
||||
## 10. Order and rebase
|
||||
|
||||
|
||||
Reference in new issue
Block a user