instar 1.3.277 → 1.3.279

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,56 @@
1
+ # Side-effects review — Mandates dashboard tab + coordination awareness backfill
2
+
3
+ Spec: `docs/specs/coordination-mandate.md` (approved A/A/B; decision 2A makes the
4
+ dashboard-behind-PIN the issuance surface). Change: a new dashboard **Mandates** tab
5
+ (`dashboard/mandates.js` external module + index.html shim) + the Migration-Parity
6
+ CLAUDE.md backfill for the three coordination surfaces shipped in #788/#797/#799.
7
+
8
+ ## 1. Blast radius
9
+
10
+ - **Dashboard:** additive — one new tab button, panel, TAB_REGISTRY entry, lazy
11
+ module import (the process-health.js pattern), and scoped `.mnd-*` CSS. No existing
12
+ tab, function, or style is modified. The dashboard ships inside the npm package, so
13
+ existing agents receive the tab on their next update with no migration.
14
+ - **PostUpdateMigrator:** three new content-sniffed CLAUDE.md backfill blocks
15
+ (Coordination Mandate / ReviewExchange / Cutover Readiness), appended only when the
16
+ distinctive route marker is absent — idempotent, never rewrites existing content.
17
+ This closes a REAL parity gap: #788/#797/#799 added the template blurbs for new
18
+ agents but no backfill, so the deployed fleet would never have learned these
19
+ surfaces exist.
20
+ - **templates.ts:** one line sharpened (point the operator at the "Mandates tab"
21
+ rather than the generic dashboard).
22
+
23
+ ## 2. Security model (the PIN discipline, in the UI this time)
24
+
25
+ - The tab's issue/revoke forms collect the PIN in a `type="password"` input with
26
+ `autocomplete="off"`, send it ONCE in the request body to the already-PIN-gated
27
+ routes, and **clear the field immediately after the response — success or failure**.
28
+ It is never written to localStorage, module state, or logs (behaviorally tested).
29
+ - The Bearer token the dashboard holds cannot issue/revoke — that is the engine's
30
+ server-side design (#788); this tab is just the human surface decision 2A names.
31
+ - Rendering is XSS-safe: every dynamic field (ids, scopes, fingerprints, authority
32
+ bounds, audit reasons — all potentially attacker-influenced via the API) is escaped
33
+ (tested with hostile payloads).
34
+ - A broken audit chain (`chain.ok:false`) renders as a loud "CHAIN BROKEN — possible
35
+ tampering" badge, never silently.
36
+
37
+ ## 3. State / data
38
+
39
+ None on the server. The tab reads `/mandate` + `/mandate/audit` and writes only
40
+ through the existing PIN-gated routes. Browser-side, nothing persists beyond the
41
+ already-stored dashboard Bearer token (unchanged).
42
+
43
+ ## 4. Failure modes
44
+
45
+ - Older server without the engine → 503 → friendly "engine unavailable" copy.
46
+ - Module load failure → console error, tab simply shows nothing (no crash).
47
+ - Wrong PIN → the route's 403 + attempt limiting surface as an inline error; the
48
+ field still clears.
49
+
50
+ ## 5. Test coverage
51
+
52
+ 18 tests: 5 HTML-at-rest wiring (tab/panel/registry/lazy-import/plain-language), 4
53
+ renderer (deny-by-default copy, badges, XSS with hostile payloads, broken-chain), 6
54
+ controller (PIN required → no request; PIN sent once then CLEARED on success AND on
55
+ 403; template prefill; 503 state), 4 migration (backfill lands with port baked in,
56
+ security copy verbatim, idempotent, no double-patch on fresh agents).
@@ -0,0 +1,30 @@
1
+ # Side-effects review — parity-pass request-timeout fix
2
+
3
+ Live finding (2026-06-05, first real trigger of the just-deployed G2.4 surface): a
4
+ real parity pass fetches the FULL live Portal cluster set and takes ~3.5 minutes
5
+ (measured 204s). The 30s default request timeout 408'd every trigger; the handler
6
+ kept running, and a late failure's 409 crashed into ERR_HTTP_HEADERS_SENT with no
7
+ trace of the outcome anywhere.
8
+
9
+ ## 1. The change
10
+
11
+ - `middleware.ts`: `PARITY_PASS_TIMEOUT_MS = 360_000` + a `buildRequestTimeoutOverrides`
12
+ entry for `/cutover-readiness/parity-pass` — the exact `/spec/conformance-check`
13
+ precedent (single heavy call, per-path budget). Longest-prefix matching means the
14
+ read-only `GET /cutover-readiness` sibling keeps the 30s default (tested).
15
+ - `routes.ts` (trigger route): the outcome is now ALWAYS logged server-side
16
+ (recorded/failed + reason), and the response is skipped when `res.headersSent`
17
+ (a 408 already went out) — never a double-respond crash, never a silent outcome.
18
+
19
+ ## 2. Blast radius
20
+
21
+ Two files, additive. No other route's budget changes. T7 unchanged: the trigger
22
+ still computes server-side; failures still record nothing.
23
+
24
+ ## 3. Test coverage
25
+
26
+ 5 new tests: override resolves for the trigger (≥ the measured real-pass duration)
27
+ and ONLY the trigger; over real HTTP with a tiny budget — a slow SUCCESSFUL pass
28
+ still records after the 408 with the outcome logged and no crash; a slow FAILED
29
+ pass records nothing with the reason logged; the fast path still 200s. Existing
30
+ override wiring suite green (20 total).