instar 1.3.627 → 1.3.628
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.
- package/dashboard/subscriptions.js +50 -0
- package/dist/core/EnrollmentWizard.d.ts +8 -0
- package/dist/core/EnrollmentWizard.d.ts.map +1 -1
- package/dist/core/EnrollmentWizard.js +12 -0
- package/dist/core/EnrollmentWizard.js.map +1 -1
- package/dist/core/PendingLoginStore.d.ts.map +1 -1
- package/dist/core/PendingLoginStore.js +21 -2
- package/dist/core/PendingLoginStore.js.map +1 -1
- package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
- package/dist/core/PostUpdateMigrator.js +18 -1
- package/dist/core/PostUpdateMigrator.js.map +1 -1
- package/dist/scaffold/templates.d.ts.map +1 -1
- package/dist/scaffold/templates.js +1 -0
- package/dist/scaffold/templates.js.map +1 -1
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/routes.js +112 -0
- package/dist/server/routes.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +63 -63
- package/src/scaffold/templates.ts +1 -0
- package/upgrades/1.3.628.md +23 -0
- package/upgrades/side-effects/matrix-cell-operator-cancel.md +151 -0
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
# Side-Effects Review — matrix-cell-operator-cancel
|
|
2
|
+
|
|
3
|
+
**Change:** Adds operator-cancel for an in-flight account×machine matrix cell — a
|
|
4
|
+
target-local route `POST /subscription-pool/follow-me/enroll/:id/cancel`, a fronting
|
|
5
|
+
relay `POST /subscription-pool/follow-me/cancel`, two `PendingLoginStore` hardening
|
|
6
|
+
tweaks, two `EnrollmentWizard` pass-throughs, a dashboard Cancel button, and a one-clause
|
|
7
|
+
CLAUDE.md awareness addition. Dark behind `multiMachine.accountFollowMe`.
|
|
8
|
+
|
|
9
|
+
**Spec:** `docs/specs/matrix-cell-operator-cancel.md` (converged iter 2, approved).
|
|
10
|
+
|
|
11
|
+
## 1. Over-block — what legitimate inputs does this reject that it shouldn't?
|
|
12
|
+
|
|
13
|
+
- A cancel against a `completed`/`abandoned` login returns a calm idempotent `200`
|
|
14
|
+
(`cancelled:false, alreadyTerminal:true`) — it does NOT reject; correct.
|
|
15
|
+
- A cancel while a `submit-code` is in flight returns `409` ("try again in a moment").
|
|
16
|
+
This is intentional and momentary (the ~2s credential-poll window) — the operator can
|
|
17
|
+
re-tap. It is the right call: cancelling mid-credential-write would strand a partial
|
|
18
|
+
credential. Not an over-block.
|
|
19
|
+
- Malformed id (`^[a-z0-9-]+$` fail) → `404`. The store's own `ID_RE` is identical, so a
|
|
20
|
+
malformed id could never name a real login anyway — no legitimate input rejected.
|
|
21
|
+
|
|
22
|
+
## 2. Under-block — what failure modes does this still miss?
|
|
23
|
+
|
|
24
|
+
- **Peer cancel when the peer is offline** → honest `502` (the relay can't reach it); the
|
|
25
|
+
peer's pane keeps running until that machine's next enroll pre-cleans it. Surfaced to the
|
|
26
|
+
operator, not silently swallowed.
|
|
27
|
+
- **Crash between abandon and pane-kill** → orphaned pane. Self-heals on the next enroll
|
|
28
|
+
(enroll-start pre-cleans the slot's pane before re-spawning). Accepted (D2).
|
|
29
|
+
- **Mandate not revoked** on cancel (D4) — a bounded, re-mint-only, 1h-expiring mandate
|
|
30
|
+
lingers. Grants no standing authority; accepted residual.
|
|
31
|
+
- **configHome slot not wiped** (D3) — a deliberate decision (wiping could clobber a valid
|
|
32
|
+
prior credential for the same account); stale-slot hygiene is the existing
|
|
33
|
+
credential-coherence path's job.
|
|
34
|
+
|
|
35
|
+
## 3. Level-of-abstraction fit
|
|
36
|
+
|
|
37
|
+
Correct layer. The route family already exists (`start-cell` mints; `submit-code` operates
|
|
38
|
+
on an in-flight login). Cancel is a peer of `submit-code` ("operate on an existing login")
|
|
39
|
+
and is placed in the same route closure, sharing the `followMeSubmitInFlight` guard. The
|
|
40
|
+
store-level terminal guard + `issue()` replace push correctness DOWN to the store (defense
|
|
41
|
+
in depth) rather than relying on route logic alone. The pane teardown uses the SAME raw
|
|
42
|
+
`tmux kill-session` the spawn (`server.ts:10713`) uses — not a higher-level helper that
|
|
43
|
+
turned out to be a no-op for these unregistered panes.
|
|
44
|
+
|
|
45
|
+
## 4. Signal vs authority compliance
|
|
46
|
+
|
|
47
|
+
The route holds de-escalating authority (kills a pane, abandons a record) gated by Bearer
|
|
48
|
+
auth + the dark flag. It is NOT a brittle detector with blocking teeth — it reuses the
|
|
49
|
+
existing structural API-edge gates (auth, `^[a-z0-9-]+$` validation, terminal-state
|
|
50
|
+
idempotent read, the in-flight 409). No content/intent judgment is made; the "should I
|
|
51
|
+
cancel?" decision is the operator's tap, not an inferred classifier. The `transition()`
|
|
52
|
+
terminal guard is pure mechanics (refuse a terminal→terminal flip), not a judgment gate.
|
|
53
|
+
Compliant with `docs/signal-vs-authority.md` (the exempted "structural guard at the edge /
|
|
54
|
+
idempotency mechanics" class).
|
|
55
|
+
|
|
56
|
+
## 5. Interactions
|
|
57
|
+
|
|
58
|
+
- **Shares `followMeSubmitInFlight` with submit-code** — cancel reads it (409 if held). It
|
|
59
|
+
never writes it, so it can't deadlock submit-code. Verified the cancel route is colocated
|
|
60
|
+
in submit-code's closure (it references the same `Set`).
|
|
61
|
+
- **`issue()` change touches ALL callers** — but the only production caller is
|
|
62
|
+
`EnrollmentWizard.start()` (verified: the other `.issue(` hits are the unrelated mandate
|
|
63
|
+
store). start-cell only reaches `issue()` after its reuse pre-check fails on a live-pending
|
|
64
|
+
record, so any same-id record at `issue()` is non-pending → safe to replace.
|
|
65
|
+
- **`transition()` terminal guard** affects `complete()` + `abandon()` (both route through
|
|
66
|
+
it). It only blocks terminal→terminal; normal `pending→completed`/`pending→abandoned`
|
|
67
|
+
unaffected. `reissue()` does not call `transition()` and already guards terminal states.
|
|
68
|
+
- **Cancel vs start-cell reuse** — abandon-first makes the record non-reusable before the
|
|
69
|
+
cell clears, so start-cell's reuse path can never hand out a cancelled login's URL.
|
|
70
|
+
- No double-fire / shadow: the relay and target-local route have distinct paths
|
|
71
|
+
(`/follow-me/cancel` vs `/follow-me/enroll/:id/cancel`); `:id` cannot match the literal
|
|
72
|
+
`start`/`cancel` segments.
|
|
73
|
+
|
|
74
|
+
## 6. External surfaces
|
|
75
|
+
|
|
76
|
+
- **Dashboard Cancel button** — a new operator-visible affordance on the in-progress (◷)
|
|
77
|
+
matrix cell, behind the dark dev-agent gate. Mobile-first (full-tap-target button,
|
|
78
|
+
optional native confirm that degrades to proceed under headless). Ships with the npm
|
|
79
|
+
package (no migration).
|
|
80
|
+
- **Two new HTTP routes** — dark behind `multiMachine.accountFollowMe` (503 when off). No
|
|
81
|
+
new config key.
|
|
82
|
+
- **No new external network egress** beyond the existing same-mesh relay hop (Bearer-authed,
|
|
83
|
+
to this agent's own paired machines only — `resolvePeerUrls`). No credential ever crosses.
|
|
84
|
+
- Timing/runtime dependence: only the momentary submit-in-flight 409 (a real, transient
|
|
85
|
+
condition the operator retries through).
|
|
86
|
+
|
|
87
|
+
## 6b. Operator-surface quality (Operator-Surface Quality standard)
|
|
88
|
+
|
|
89
|
+
This change touches an operator surface (`dashboard/subscriptions.js` — the Cancel
|
|
90
|
+
button on the in-progress matrix cell).
|
|
91
|
+
|
|
92
|
+
1. **Leads with the primary action?** Yes. The Cancel button is the single,
|
|
93
|
+
visible action on an in-progress (◷) cell — a full-tap-target `<button>Cancel</button>`
|
|
94
|
+
rendered inline beside the status glyph on every poll re-render (not collapsed,
|
|
95
|
+
not below the fold, no explanatory prose in front of it).
|
|
96
|
+
2. **Zero raw internals as primary content?** Yes. The cell shows the glyph + the
|
|
97
|
+
word "Signing in…" + the "Cancel" button; on tap, a plain status line
|
|
98
|
+
("Cancelling…" → "Cancelled — you can set this up again.") or the route's
|
|
99
|
+
plain-English error. No JSON, no fingerprints, no config paths, no slugs. The
|
|
100
|
+
`loginId`/`machineId` ride as `data-*` attributes (support metadata), never shown.
|
|
101
|
+
3. **Destructive actions de-emphasized?** N/A in the harmful sense — Cancel is
|
|
102
|
+
itself the *reversing* (de-escalating) action, fully reversible (re-tap "Set up"
|
|
103
|
+
to redo). It is a small single button, optionally guarded by a native confirm
|
|
104
|
+
("Cancel this in-progress setup?"). There is no separate destructive control to
|
|
105
|
+
demote; the constructive "Set up" path reappears after a cancel.
|
|
106
|
+
4. **Plain language + phone width?** Yes. "Cancel" / "Signing in…" / "Cancelled —
|
|
107
|
+
you can set this up again." read the way a non-engineer would say them; the
|
|
108
|
+
button is a real tap target in the existing mobile-responsive matrix grid (same
|
|
109
|
+
cell layout as the shipped "Set up"/"Submit" buttons), no horizontal scroll, no
|
|
110
|
+
truncated table hiding the action.
|
|
111
|
+
|
|
112
|
+
## 7. Multi-machine posture (Cross-Machine Coherence)
|
|
113
|
+
|
|
114
|
+
**Proxied-on-write (relay).** A `PendingLogin` + pane live on the machine running the login
|
|
115
|
+
subprocess; the target-local route is machine-local by necessity. Cross-machine reach is the
|
|
116
|
+
fronting relay `follow-me/cancel`, dispatching by `machineId` to self-loopback or the owning
|
|
117
|
+
peer over the authed mesh hop — the SAME proven pattern as `follow-me/submit-code`. The
|
|
118
|
+
dashboard always calls the relay, so a peer cell cancels correctly; an offline peer yields an
|
|
119
|
+
honest 502. No durable state strands on topic transfer (a PendingLogin is not topic-scoped);
|
|
120
|
+
no generated URL crosses a machine boundary. The earlier self-only draft (which would have
|
|
121
|
+
silently 404'd peer cells) was rejected in convergence — this is the corrected posture.
|
|
122
|
+
|
|
123
|
+
## 8. Rollback cost
|
|
124
|
+
|
|
125
|
+
Single `git revert`. Pure additive surface behind an existing dark flag. The two store
|
|
126
|
+
changes are backward-compatible (the terminal guard only PREVENTS a clobber that should
|
|
127
|
+
never happen; the `issue()` replace only RELAXES a throw). No data migration — `abandoned`
|
|
128
|
+
is already a valid terminal state the store + sweeps handle today. No agent-state repair. The
|
|
129
|
+
auto-merger handles the merge; a bad merge is one revert.
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## Second-pass review
|
|
134
|
+
|
|
135
|
+
_(High-risk: touches a block/allow decision surface — a kill path + a dark gate + the word
|
|
136
|
+
"gate". Reviewer appended below.)_
|
|
137
|
+
|
|
138
|
+
An independent second-pass reviewer audited the actual implementation code (not just the
|
|
139
|
+
spec) against the artifact, line by line. Findings: **all [OK]** — kill targets the correct
|
|
140
|
+
pane with no injection (derived from the stored record, not `req.params.id`; `id` regex-gated
|
|
141
|
+
`^[a-z0-9-]+$`; no shell); gate order exactly as specified with abandon-before-kill; the
|
|
142
|
+
`@silent-fallback-ok` tag is correct and both catch ratchets pass; the `transition()` terminal
|
|
143
|
+
guard cannot break `complete()`/`reissue()`/normal flows; `issue()` replace has a single
|
|
144
|
+
production caller (`EnrollmentWizard.start`) and still throws on a live-pending dup; the
|
|
145
|
+
dashboard Cancel is on the durable cell, no PIN, confirm degrades under jsdom; template↔migrator
|
|
146
|
+
parity + idempotency hold; the relay adds no SSRF surface beyond submit-code (own paired
|
|
147
|
+
machines only, `encodeURIComponent`'d id, no `code` body); no new CI ratchet trips. One
|
|
148
|
+
**[MINOR]**: the submit-in-flight 409 is a momentary retry-through window (documented in §1) —
|
|
149
|
+
not a defect. No blockers, no material issues, no signal-vs-authority violation.
|
|
150
|
+
|
|
151
|
+
**Verdict: Concur with the review.**
|