instar 1.3.400 → 1.3.402

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.
Files changed (37) hide show
  1. package/dashboard/index.html +48 -18
  2. package/dist/commands/server.d.ts.map +1 -1
  3. package/dist/commands/server.js +59 -1
  4. package/dist/commands/server.js.map +1 -1
  5. package/dist/core/EnrollmentWizard.d.ts +84 -0
  6. package/dist/core/EnrollmentWizard.d.ts.map +1 -0
  7. package/dist/core/EnrollmentWizard.js +107 -0
  8. package/dist/core/EnrollmentWizard.js.map +1 -0
  9. package/dist/core/FrameworkLoginDriver.d.ts +85 -0
  10. package/dist/core/FrameworkLoginDriver.d.ts.map +1 -0
  11. package/dist/core/FrameworkLoginDriver.js +110 -0
  12. package/dist/core/FrameworkLoginDriver.js.map +1 -0
  13. package/dist/core/PendingLoginStore.d.ts +118 -0
  14. package/dist/core/PendingLoginStore.d.ts.map +1 -0
  15. package/dist/core/PendingLoginStore.js +201 -0
  16. package/dist/core/PendingLoginStore.js.map +1 -0
  17. package/dist/core/types.d.ts +8 -0
  18. package/dist/core/types.d.ts.map +1 -1
  19. package/dist/core/types.js.map +1 -1
  20. package/dist/scaffold/templates.d.ts.map +1 -1
  21. package/dist/scaffold/templates.js +1 -0
  22. package/dist/scaffold/templates.js.map +1 -1
  23. package/dist/server/AgentServer.d.ts +1 -0
  24. package/dist/server/AgentServer.d.ts.map +1 -1
  25. package/dist/server/AgentServer.js +1 -0
  26. package/dist/server/AgentServer.js.map +1 -1
  27. package/dist/server/routes.d.ts +2 -0
  28. package/dist/server/routes.d.ts.map +1 -1
  29. package/dist/server/routes.js +59 -0
  30. package/dist/server/routes.js.map +1 -1
  31. package/package.json +1 -1
  32. package/src/data/builtin-manifest.json +47 -47
  33. package/src/scaffold/templates.ts +1 -0
  34. package/upgrades/1.3.401.md +30 -0
  35. package/upgrades/1.3.402.md +64 -0
  36. package/upgrades/side-effects/dashboard-stream-phase3-ui.md +58 -0
  37. package/upgrades/side-effects/subscription-auth-enrollment.md +91 -0
@@ -0,0 +1,91 @@
1
+ # Side-Effects Review — Mobile-first enrollment wizard (P2.1)
2
+
3
+ ## Scope of change
4
+
5
+ - `src/core/PendingLoginStore.ts` (new) — durable ledger of in-flight logins (public artifacts only).
6
+ - `src/core/EnrollmentWizard.ts` (new) — orchestration: start + auto-reissue-on-expiry + complete.
7
+ - `src/core/FrameworkLoginDriver.ts` (new) — concrete LoginDriver: spawn framework login under the account's config home, scrape the public code/URL.
8
+ - `src/server/routes.ts` — RouteContext `enrollmentWizard` + 4 routes under `/subscription-pool`.
9
+ - `src/server/AgentServer.ts` — `enrollmentWizard?` option + private field + RouteContext plumbing.
10
+ - `src/commands/server.ts` — instantiate the store + driver + wizard; pass to AgentServer; background reissue tick (unref'd).
11
+ - tests (unit + integration + e2e) + api.md.
12
+
13
+ ## The concern: a wizard that spawns a login process + writes a durable store
14
+
15
+ The new authority here is (a) spawning a framework login command, and (b) writing
16
+ a durable store. The safety design:
17
+
18
+ - **Spawning is injected + scoped.** The interactive leg (driving the login CLI)
19
+ is the injected `LoginDriver`. The concrete `FrameworkLoginDriver` spawns the
20
+ framework's OWN login command under a per-account `CLAUDE_CONFIG_DIR` — it does
21
+ not extract, read, or transmit any credential. The credential is written by the
22
+ framework's own client into that config home; instar only reads the PUBLIC
23
+ artifact (verification URL + short code) the provider prints to be typed into
24
+ its own page.
25
+ - **No secret can enter the store by construction.** `PendingLoginStore`'s record
26
+ type has no token/secret field. There is nothing to smuggle a credential into —
27
+ the same structural guarantee P1.1 enforces for the account registry. The
28
+ integration test asserts no token-like field ever appears in a response body.
29
+ - **Dark + operator/internal.** The routes nest under `/subscription-pool`
30
+ (already INTERNAL, not surfaced in /capabilities until graduation) and do
31
+ nothing until an operator starts an enrollment. No live-session path is touched.
32
+ - **The background tick is inert + bounded.** The reissue sweep only re-drives
33
+ logins that are already EXPIRED; with no pending logins it is a no-op. The timer
34
+ is `unref()`'d so it never holds the process open.
35
+
36
+ ## Authority / autonomy analysis
37
+
38
+ - **Tier-2 by association** (spawns a process, writes a store) but ships dark +
39
+ operator-gated. The driving spec (`subscription-auth-p2.1-enrollment.md`) is
40
+ converged + `approved: true` (Justin, Telegram topic 20905, 2026-06-07 — blanket
41
+ approval of the remaining phases under the autonomy directive).
42
+ - **No autonomous credential handling.** The agent never holds a token; the
43
+ operator approves at the provider's own page. The wizard's only autonomy is
44
+ re-issuing an EXPIRED public code — which carries no secret and strands nothing.
45
+ - **Honest failure.** A driver failure during a reissue is logged + the login is
46
+ left expired for the next sweep (no false "reissued" claim); a scrape timeout
47
+ throws and the login is left for the operator (no fabricated artifact).
48
+
49
+ ## Failure modes considered
50
+
51
+ - Login code expires before the operator acts → auto-reissued on the next sweep (the headline fix).
52
+ - Driver/scrape failure → logged, login left expired, sweep continues (one bad login can't abort it).
53
+ - Server restart mid-enrollment → the pending login persisted to disk; it reloads and stays on the surface.
54
+ - Wizard unwired (dark) → list/sweep routes answer 200 `{ enabled:false }`, never 503.
55
+ - No pending logins → the background sweep is a no-op; the timer is unref'd.
56
+
57
+ ## Blast radius
58
+
59
+ Contained by the dark/operator-gated rollout + the credential-safety-by-construction
60
+ store. With no enrollment started (the default), none of this code executes beyond
61
+ an inert sweep over an empty store. The risk surface is the spawn-+-scrape path,
62
+ exercised only when an operator explicitly starts an enrollment.
63
+
64
+ ## Framework generality
65
+
66
+ The wizard is framework-agnostic in shape, framework-specific in effect:
67
+
68
+ - `EnrollmentWizard` + `PendingLoginStore` are fully generic — they carry
69
+ `provider` + `framework` fields and treat the login artifact uniformly. The
70
+ per-provider default flow kind (`defaultKind`) encodes the only branch: Codex/
71
+ OpenAI = device-code (its endorsed flow); everyone else = url-code-paste (the
72
+ phone-friendly Claude path). Adding a framework is a one-line default + a driver
73
+ case, not a structural change.
74
+ - `FrameworkLoginDriver` is where framework specificity lives, and it is honest
75
+ about it: the spawn command + the scrape patterns are per-flow (device-code vs
76
+ url-code-paste), and the pure `parseArtifact` handles both. The two real flows
77
+ (Codex device-code, Claude URL-paste) are implemented; gemini-cli / pi-cli slot
78
+ into the same `framework` union and reuse the same scrape patterns when their
79
+ login flows are wired — no Claude-only assumption is baked into the abstraction.
80
+ - Per the constitution's "Framework-Agnostic — and Framework-Optimizing": the
81
+ store + wizard stay neutral across providers; the optimization (which login flow,
82
+ what to scrape) is per-framework in the driver. This matches the standard's
83
+ Claude-first scope (Justin's decision 3) without foreclosing the others.
84
+
85
+ ## Migration / parity
86
+
87
+ All three new classes are additive (new files; the store is created lazily on
88
+ first enrollment). Routes stay under the already-classified `/subscription-pool`
89
+ INTERNAL prefix (no CapabilityIndex change until graduation). An optional
90
+ `subscriptionPool.enrollment` config block tunes TTL/sweep cadence; absent, shipped
91
+ defaults apply. No existing behaviour changes. Ships via dist.