docs: lead decision 71, S4 round 2 scope and the notify journal's torn tail (sage)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
@@ -1359,3 +1359,40 @@ which stay with him. Each item names who decided it and what happened.
|
||||
fail-closed Vikunja checks, about 15 requests, before the boot
|
||||
reply, so the host waits 30 s for `{ok: true}`. A refusal comes
|
||||
back as `{ok: false, error}`.
|
||||
|
||||
71. **S4 round 2 scope and the notify journal's torn tail (2026-10-08).**
|
||||
Source: Filbert's round 1 verdict on #1521 (comment 26848, B1), and
|
||||
Rocko's point that a newline alone doesn't fix it.
|
||||
- A final line without its newline is a write that never finished.
|
||||
No confirmed record lives in it, so removing it doesn't rewrite
|
||||
evidence. Decision 70's append-only rule covers complete lines.
|
||||
- On open, a torn tail is handled in this order:
|
||||
1. Copy the torn bytes to
|
||||
`<dataRoot>/notify/<business>/torn-<UTC stamp>.bin` (0600, new
|
||||
file, fsync).
|
||||
2. Truncate `sent.jsonl` to its last newline and fsync.
|
||||
3. Log both steps.
|
||||
- A crash between steps 1 and 2 leaves the tail torn. The next open
|
||||
repeats both steps, and the second copy is harmless.
|
||||
- Appending a newline isn't enough: the fragment becomes a malformed
|
||||
middle line, and the next open refuses.
|
||||
- A malformed complete line still refuses with exit 3. Only the final
|
||||
unterminated line gets this treatment.
|
||||
- If the torn write was a send that reached Discord, the decision
|
||||
gets DM'd again. Decision 70 already prefers a duplicate DM to a
|
||||
missed one, and the per-decision nonce lets Discord dedupe it
|
||||
inside its window.
|
||||
- Round 2 must fix:
|
||||
- B1, with the rule above. Tests: open, append, reopen; and the
|
||||
state after a crash between steps 1 and 2.
|
||||
- F1. Refuse a journal directory looser than 0700, as the file
|
||||
mode is checked.
|
||||
- R2. A test that two decisions get different DM nonces.
|
||||
- D1. Put the business in the digest nonce.
|
||||
- The host startup race. Check each child's exit state after the
|
||||
listeners attach.
|
||||
- J3. Refuse a symlinked `sent.jsonl`.
|
||||
- F3. Drop `network-online.target` from the user unit.
|
||||
- Tests for mutants M22 to M24, M26 and M29.
|
||||
- Follow-ups, not round 2: F2 (a refused DM retries every 30 min with
|
||||
no limit) and J4 (loose types in confirmed lines).
|
||||
|
||||
Reference in New Issue
Block a user