machine-grant design r6 (#436): duckworth-0063 C1 update-only undo after revoke, N1 start sweep of unrecorded key files
This commit is contained in:
1 parent
7686fd783e
commit
f9039682eb
1 file changed
+36
-7
@@ -1,16 +1,29 @@
|
||||
# Machine grant path, design draft r5 (Vikunja #436, row 210 follow-up)
|
||||
# Machine grant path, design draft r6 (Vikunja #436, row 210 follow-up)
|
||||
|
||||
Owner: Gizmoduck. Reviewer: Duckworth. Sizing and row assignment: Sage. Design only. Code starts when
|
||||
Duckworth approves the design and row 210 lands (sage-1527).
|
||||
|
||||
Sources: Q188 (DECISIONS.md:1642, jason-master-restart 8ecf252), mos-1115, mos-1120, mos-1125, mos-1127, mos-1131, mos-1133, mos-1139,
|
||||
sage-1527, Duckworth's r1 review (REVIEW-r1.md, duckworth/reviews d025ef492, corrected at 749080115), Duckworth's
|
||||
r3 and r4 review (REVIEW-r3.md, duckworth/reviews 9dceb2148, duckworth-0060),
|
||||
r3 and r4 review (REVIEW-r3.md, duckworth/reviews 9dceb2148, duckworth-0060), Duckworth's r5 diff check
|
||||
(REVIEW-r5.md, duckworth/reviews c3dc58f30, duckworth-0063),
|
||||
Honker's PRD 1.8 draft (honker/row194-b2 3c30f1036, REQ-TRUST-2 and REQ-GRANT-1 to -4), row 210 DESIGN r3
|
||||
(e021dfa26) and its approved candidate 455964f23. Code cites are `path:line` at origin/refactor f41729178
|
||||
unless they say "210:", which means the row 210 candidate 455964f23 (the same code as the branch head
|
||||
a2fd30390). Host facts come from ops-01's read-only check of .53 and .54 at 22:21Z (mos-1127).
|
||||
|
||||
## r6 changes (from r5 7686fd783)
|
||||
|
||||
Duckworth approved r5 with C1 and one note (duckworth-0063). The design is approved for code once row 210
|
||||
lands. r6 carries C1 and the note, for a diff check on those lines.
|
||||
|
||||
- C1: a revoke can't be undone by a commands-change undo. After step 5 commits, the executor ignores an
|
||||
abort (X5). Both undo paths that set a record back to `previous` only update a record that exists, never
|
||||
insert one, and do nothing when a `grant.revoked` is newer than the decision (X3). G28 and an upsert
|
||||
mutant cover it.
|
||||
- N1: a failed unlink at revoke step 2 no longer depends on the marker. At start, after the grant
|
||||
reconcile, the bus unlinks every `host.<id>` key file that has no `host_grants` record (section 6, G27).
|
||||
|
||||
## r5 changes (from r4 1c5705d6d)
|
||||
|
||||
Duckworth's review of r3 and r4 (duckworth-0060) asked for changes, B1 and B2, with notes N1 to N11. mos-1139
|
||||
@@ -540,6 +553,11 @@ The steps are ordered so a failure leaves nothing an agent can use:
|
||||
| 5 before `commit` | a line, a key file, no grant record | unlink the key file, unregister (X4), `remove` |
|
||||
| 5 after `commit` | a line, a grant record, a key file | the record back to `previous` (deleted for a new key), 210 `revoke`, `remove` |
|
||||
|
||||
Setting a record back to `previous`, here and in the restart table below, only updates a record that
|
||||
exists. It never inserts one, and it does nothing when a `grant.revoked` for the (agent, host) is newer than
|
||||
the decision. So a revoke that deleted the record stays done, and the next start loads no reference for it
|
||||
(C1).
|
||||
|
||||
A best-effort `remove` that fails adds `hostLineLeft: <tag>` to `grant.failed`, and `status` shows it until
|
||||
`mosaic hosts sweep <hostId>` (human or tester) succeeds. `sweep` runs `list <user>` and removes each line
|
||||
whose tag is in this business's recorded `grant.step` tags and has no live grant. A line with any other tag
|
||||
@@ -554,7 +572,7 @@ is left alone, so a sweep can't touch another business's line on the same user (
|
||||
| none | none (the tmp dir goes in 210's run-dir sweep) | none |
|
||||
| `install` | none | `remove <user> <tag>` |
|
||||
| `commit`, new key | unlink the key file if present, delete the grant record if present | `remove <user> <tag>` |
|
||||
| `commit`, commands change | set the record's `commands` back to `previous` | none, the key and line didn't change |
|
||||
| `commit`, commands change | set the record's `commands` back to `previous`, by the update-only rule above | none, the key and line didn't change |
|
||||
| enrollment `registry` | delete the installer key if present, delete the host record | none |
|
||||
|
||||
Then it records `grant.failed {code: 'interrupted', tag}` with the tag listed every time, and `hostLineLeft:
|
||||
@@ -610,7 +628,8 @@ it and returns the signal, and `release` deletes it.
|
||||
A mutant covers it.
|
||||
- On abort the executor undoes as X3's failure table does at that step, then ends
|
||||
`grant.failed {code: 'revoked'}`.
|
||||
- A revoke after step 5 is an ordinary revoke (section 6).
|
||||
- A revoke after step 5 is an ordinary revoke (section 6). Once step 5 commits, the executor ignores an
|
||||
abort and goes on to step 6, so its undo never runs against a revoke that came after the commit (C1).
|
||||
|
||||
While the executor holds the claim, a `host.run` for the same agent and host refuses `host-busy`. That only
|
||||
matters for a commands change on a live key, and it lasts until the executor ends.
|
||||
@@ -691,8 +710,8 @@ Order, local first so the part that matters can't wait on the network:
|
||||
2. Right after the commit, with no `await` between: 210 `revoke` if `Credentials` holds a reference
|
||||
(memory, abort the `host.run` or the executor in flight, unlink the key file), or `abortClaim` if it
|
||||
holds only a claim (X5). Steps 1 and 2 are the "instant" part, and neither touches the network. If the
|
||||
unlink fails, the verb reports it. The key is already out of memory, and the start reconcile unlinks the
|
||||
file.
|
||||
unlink fails, the verb reports it. The key is already out of memory, and the next start removes the
|
||||
file (below).
|
||||
3. `remove <user> <tag>` on the host through the installer. Success records `grant.revoke.closed {tag,
|
||||
hostLine: 'removed'}`. If the host can't be reached, it records `grant.revoke.closed {tag, hostLineLeft:
|
||||
<tag>}`, and `sweep` clears it later.
|
||||
@@ -702,6 +721,11 @@ A restart between the steps (N4) leaves a `grant.revoked` with `hostLine: 'pendi
|
||||
there. No reference loads for it, because the record is gone (X4). After the bus is up, the reconcile runs
|
||||
step 3 and closes the marker. `status` shows an open marker as a revoke in progress.
|
||||
|
||||
Step 3 closes the marker even when step 2's unlink failed. So the file doesn't wait on the marker: at every
|
||||
start, after the grant reconcile (X3) and before `Credentials` loads, the bus unlinks each `host.<id>` key
|
||||
file in the agent store that has no `host_grants` record (N1 of duckworth-0063). The grant reconcile runs
|
||||
first, so a key an interrupted executor wrote is already handled there.
|
||||
|
||||
Step 3 is defense in depth. After step 1 the stack holds no copy of the key. The line only matters if
|
||||
something copied the key file before the revoke, which section 9's same-user limit allows.
|
||||
|
||||
@@ -808,7 +832,8 @@ such argument. No real host is contacted.
|
||||
| G23 | a revoke during install (a scratch `mosaic-keys` that waits on a fifo) ends `grant.failed revoked` with no key file, no grant and no line. A revoke before the executor starts, with no reference and no claim, records `grant.revoked`, and step 1 then ends `grant.failed revoked`. A grant whose claim finds a running `host.run` ends `grant.failed host-busy` with its decision spent and a message (B2) |
|
||||
| G24 | agent and host names at 64 characters with `.` and `_` give distinct tags of the fixed length. `sweep` leaves another business's line and an unrecorded `mosaic-` line on the same user (B4) |
|
||||
| G25 | the writer refuses a symlinked `/etc/ssh/mosaic-keys`, a symlinked user file, a group-writable dir, and a tmp that is a symlink or not a regular file. A leftover regular tmp is unlinked and the write goes ahead. A first `add` creates the file. A written file is root-owned 0644 (B5, N6) |
|
||||
| G27 | `hosts.revoke` works for an agent whose business file has no credentials reference (N3). A restart after revoke step 1, and one after step 2, each end at start with no key file, no record, the line removed and the marker closed (N4) |
|
||||
| G27 | `hosts.revoke` works for an agent whose business file has no credentials reference (N3). A restart after revoke step 1, and one after step 2, each end at start with no key file, no record, the line removed and the marker closed (N4). A key file left by a failed step 2 unlink is gone after the next start, though the marker closed |
|
||||
| G28 | a commands change commits at step 5, a revoke follows before `grant.applied`, and the bus restarts: the start ends with no grant record, no reference and no key file. The same with a failure after step 5 in place of the restart (C1) |
|
||||
|
||||
Mutants, a first list. The row's BUILD.md numbers them and adds more:
|
||||
|
||||
@@ -851,6 +876,10 @@ Mutants, a first list. The row's BUILD.md numbers them and adds more:
|
||||
- make `commit` async
|
||||
- route `hosts.revoke` through `credential-verbs.mjs`
|
||||
- skip the revoke marker reconcile
|
||||
- let the undo to `previous` insert a record (an upsert)
|
||||
- let the undo to `previous` run past a newer `grant.revoked`
|
||||
- let the executor act on an abort after step 5 commits
|
||||
- skip the start sweep of key files with no record
|
||||
- treat a missing `bus.tester` as dev
|
||||
|
||||
## 11. Not in this draft
|
||||
|
||||
Reference in new issue
Block a user