Commit Graph
2228 Commits
Author SHA1 Message Date
Marc-André Bombeck dc343f434c docs(02-12.1): narrow two overstated claims
- the idempotency arm refuses only a wrongly-asserted context; an admin
  route behind unfenced requireAdmin still serves a headerless request
- the epoch trigger does not fire on a statement that names record_epoch
  without moving the selector; the source guard is what covers that
2026-08-06 20:48:50 +02:00
Marc-André Bombeck 8fcbdcc0df test(02-12.1): prove the record-session fence end to end
- give every acceptance case a stable id and assert the mapping from a
  runnable artifact, recording which cases execute in the ordinary gate
  and which await the browser stage
- add the browser spec for the cases no cooperative layer can reach:
  peers reconciling to an exact context, an aborted switch response, a
  closed initiator, a delayed response, and the offline disk layers
2026-08-06 19:33:15 +02:00
Marc-André Bombeck 31b4857d8b feat(02-12.1): carry and verify the record context from the browser
- attach the asserted context to every same-origin request inside the
  three fetch entries, so no call site classifies itself
- discard a response whose echoed context contradicts the adopted one;
  serve one that carries no echo, which is what keeps the public poll
  and every actor surface working
- adopt from /api/auth/me and the switch response, and from nothing else
- send the epoch on every switch and retry once after reconciling
- hold and reconcile on the 409 instead of leaving the record
2026-08-06 19:10:02 +02:00
Marc-André Bombeck 3a99de312e fix(02-12.1): check record context before an idempotent replay
- evaluate the fence in the wrapper above findCached, so a stale request
  neither replays a body, learns a cell exists, nor inserts a claim
- return the refusal rather than throwing: one route composes the
  wrapper outside apiHandler, where a throw escapes the envelope
- read the claim and the session's own context on one session lookup
2026-08-06 18:54:20 +02:00
Marc-André Bombeck 45fec0fc1b feat(02-12.1): refuse a record request whose context has moved
- both record resolvers check the fence after authentication and before
  the carrier, off the one session row that also decides the scope
- POST /api/account/switch takes an optional expectedEpoch and writes
  conditionally, so concurrent switchers resolve to one outcome
- GET /api/auth/me publishes the context a browser bootstraps from
- every response that resolved a record scope echoes it back
- regenerate the API contract
2026-08-06 18:21:40 +02:00
Marc-André Bombeck 59359738c8 feat(02-12.1): decide record-session context in one place
- add an import-free contract module both bundles can name, holding the
  header names, the parse and the verdict
- add the server fence: header read, wide-event stamp, and the refusal
- add RecordSessionChangedError as a third sibling on the existing
  sharing-error arm, so the 409 needs no new serialisation branch
2026-08-06 17:59:07 +02:00
Marc-André Bombeck 5c9befc0ae feat(02-12.1): stamp a record-context epoch on every session
- add sessions.record_epoch, owned by a BEFORE UPDATE trigger so the
  ON DELETE SET NULL path and raw SQL writes cannot skip it
- normalise pre-existing rows so epoch zero means never switched
- project the epoch off the row getSession already loads
2026-08-06 17:52:10 +02:00
Marc-André Bombeck a08e82d0be Merge commit '38214e472' into work/v137-record-session-fence 2026-08-06 17:10:56 +02:00
Marc-André Bombeck 38214e4726 fix(02-12): hold peer tabs during record switches
- Clear scoped reads before the server session changes
- Reconcile every tab with a fresh access response
2026-08-06 15:06:12 +02:00
Marc-André Bombeck c42df8cbc3 fix(02-12): gate record preload scope
- Wait for a validated account scope before warming record reads
- Abort scoped preloads and discard handoffs across record transitions
- Cover malformed scope reloads and fresh own-record recovery
2026-08-06 14:32:32 +02:00
Marc-André Bombeck 2ae3a66816 fix(02-11): bound APNs provider delivery
- Time out stalled provider sends without unhandled late rejections\n- Record a transient timeout outcome for cascade fallback\n- Cover timeout fallback with unit and integration tests
2026-08-06 14:10:28 +02:00
Marc-André Bombeck c56d1ca50b fix(02-11): protect guardian egress data lifecycle
- Exclude and erase egress claims with recipient-side lookup support\n- Serialize data wipes with managed-profile Guardian authorization\n- Cover last-Guardian and queued-claim wipe races
2026-08-06 14:05:59 +02:00
Marc-André Bombeck 21e111c06c fix(02-12): refuse malformed record access
- Preserve absent-server compatibility while rejecting published invalid blocks\n- Partition refused record reads and withhold protected presentation
2026-08-06 14:03:13 +02:00
Marc-André Bombeck 4b79f83cf7 fix(02-11): release guardian lock before provider egress
- Commit a final authorization claim under the lifecycle lock\n- Keep provider calls and retry outcomes outside database transactions\n- Retain authorization claims with notification delivery diagnostics
2026-08-06 13:46:42 +02:00
Marc-André Bombeck b844d04676 fix(02-12): reject divergent shared-record state
- Verify the active record matches its canonical switcher entry\n- Skip the owner OCR probe in delegated Labs records
2026-08-06 13:39:37 +02:00
Marc-André Bombeck 1818bd874b fix(02-11): authorize guardian egress under lock
- Hold the managed-profile lock through every provider send\n- Add the notification event retention index and race coverage
2026-08-06 09:42:47 +02:00
Marc-André Bombeck 358bb39465 fix(02-12): keep scoped record polls dormant
- suppress whole-record achievements reads for narrowed grants\n- stabilize record journey response assertions
2026-08-06 08:34:02 +02:00
Marc-André Bombeck 60b4845fea feat(02-11): secure guardian notification delivery
- Remove record-mutating affordances from Guardian channel payloads\n- Reject managed Telegram callbacks and verify channel attribution
2026-08-06 05:44:41 +02:00
Marc-André Bombeck accb98e223 test(02-11): cover guardian notification channel safety
- Cover non-interactive Guardian payloads across delivery channels\n- Reject Telegram callbacks tied to managed records
2026-08-06 05:37:05 +02:00
Marc-André Bombeck 59de92b62e fix: isolate guardian notification preferences 2026-08-06 05:33:02 +02:00
Marc-André Bombeck a78189b7f6 feat: add guardian notification fanout 2026-08-06 05:23:38 +02:00
Marc-André Bombeck 5e8b90bcc1 Merge notification delivery identity 2026-08-06 05:12:42 +02:00
Marc-André Bombeck f6b9c8e882 fix(02-12): fail closed in record presentation
- retain elevated chrome only for internally consistent payloads\n- fall back to the caller record on malformed access entries
2026-08-06 05:07:27 +02:00
Marc-André Bombeck 6c4dd2d96b feat(02-12): route scoped records to granted domains
- keep shared navigation independent of actor module preferences\n- open scoped records at their first allowed destination\n- announce record access and kind in doorway names
2026-08-06 05:02:37 +02:00
Marc-André Bombeck affd356677 test: retain sustained safety event claims
- exercise the shared notification claim boundary\n- preserve rolling sustained-run dedup coverage
2026-08-06 04:59:50 +02:00
Marc-André Bombeck 9eab70f032 feat(02-12): add scoped profile summary
- expose bounded read-only profile facts for shared records\n- keep profile navigation separate from Settings mutations
2026-08-06 04:59:25 +02:00
Marc-André Bombeck 9ba37342d7 fix: claim notification events atomically
- serialize rolling event claims before delivery\n- keep provider egress outside the transaction
2026-08-06 04:57:50 +02:00
Marc-André Bombeck ba7bf49fae test: cover atomic notification event claims
- race record event claims through PostgreSQL\n- require safety producers to honor the claim
2026-08-06 04:53:50 +02:00
Marc-André Bombeck 60f91d27d7 fix: validate account access payloads
- Share the closed access schema with OpenAPI\n- Fail closed on malformed or stale record metadata
2026-08-06 04:52:46 +02:00
Marc-André Bombeck 69f97b268c fix: erase notification anchors with record data
- remove record event anchors during data deletion\n- retain sustained safety dedup coverage
2026-08-06 04:48:47 +02:00
Marc-André Bombeck 9c4c7b2b7d fix: retain notification anchor boundaries
- classify local notification anchors outside backups\n- keep reminder dedup fixtures on record events
2026-08-06 04:46:45 +02:00
Marc-André Bombeck c6b5d5df63 test: cover account access payload parsing
- Preserve canonical shared and manage payloads\n- Reject malformed and stale access metadata
2026-08-06 04:46:15 +02:00
Marc-André Bombeck 10a58a7e6a test: cover recipient-scoped Telegram persistence
- retain independent recipient reminder slots\n- verify chat updates and recipient cascade cleanup
2026-08-06 04:44:08 +02:00
Marc-André Bombeck 027f2b4355 fix: suppress premature managed safety delivery
- keep direct safety notifications to ordinary self-delivery\n- move safety dedup anchors out of delivery diagnostics
2026-08-06 04:41:40 +02:00
Marc-André Bombeck ce94f4773f fix: reject partial notification attribution
- retain only complete delivery principal pairs\n- preserve legacy self-delivery records
2026-08-06 04:39:36 +02:00
Marc-André Bombeck 8b275c87db test: cover partial notification attribution
- reject one-sided delivery identities\n- avoid ambiguous push-attempt ledger writes
2026-08-06 04:38:48 +02:00
Marc-André Bombeck fa46f27b01 feat: scope Telegram reminder tracking to recipients
- keep delegated recipient slots independent\n- bind callback cleanup to the recipient account
2026-08-06 04:38:09 +02:00
Marc-André Bombeck 5807879439 test: cover recipient-scoped telegram reminders
- Keep identical slots separate for each recipient\n- Update one slot when a recipient changes chat
2026-08-06 04:33:35 +02:00
Marc-André Bombeck 9380ea0f18 feat: separate notification event anchors
- Store record-scoped scheduler events outside delivery attempts\n- Keep delivery diagnostics free of bookkeeping rows
2026-08-06 04:32:52 +02:00
Marc-André Bombeck 2999b75ea6 test: cover notification event anchors
- Require record-scoped reminder deduplication\n- Keep anchors independent of delivery recipients
2026-08-06 04:29:54 +02:00
Marc-André Bombeck 1ba73a4d51 fix: enforce notification delivery authority
- Require active Guardian authority before cross-record delivery\n- Serialize managed delivery checks with lifecycle changes
2026-08-06 04:29:18 +02:00
Marc-André Bombeck ba3be7ba9b feat: distinguish managed record access 2026-08-06 04:18:05 +02:00
Marc-André Bombeck afae57207c feat: scope shared record navigation 2026-08-06 04:13:59 +02:00
Marc-André Bombeck 2ccd022410 test: update notification sender attempt mocks
- Exercise identity-aware delivery attempt recording\n- Keep self-delivery assertions explicit
2026-08-06 04:05:33 +02:00
Marc-André Bombeck 201a24e404 Merge managed record settings 2026-08-06 04:05:16 +02:00
Marc-André Bombeck 437d916fc6 fix: guard managed setting label inventories
- Treat inherited property names as unavailable settings

- Preserve legacy tile aliases only for declared entries
2026-08-06 04:01:00 +02:00
Marc-André Bombeck 906118f86e fix: resolve notification delivery identity 2026-08-06 03:57:23 +02:00
Marc-André Bombeck 6108a71d80 feat: separate notification subjects and recipients 2026-08-06 03:46:57 +02:00
Marc-André Bombeck 247ac8494c fix: complete managed record settings
- Expose canonical defaults and reject invalid settings families\n- Localize Guardian controls and refresh dependent caches
2026-08-06 03:40:13 +02:00
Marc-André Bombeck e788675b82 feat: configure managed record settings
- Scope writable settings to the selected managed record\n- Render typed Guardian controls with separated audit attribution
2026-08-06 03:21:02 +02:00