@legioncodeinc/hive 0.2.1 → 0.3.1

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 (132) hide show
  1. package/README.md +2 -2
  2. package/assets/brand/activeloop-full-mark-logo-on-dark.svg +209 -0
  3. package/assets/brand/activeloop-full-mark-logo.svg +208 -0
  4. package/assets/brand/divider-major.svg +1 -0
  5. package/assets/brand/divider-minor.svg +1 -0
  6. package/assets/brand/doctor-mark.svg +1 -0
  7. package/assets/brand/hive-mark.svg +1 -0
  8. package/assets/brand/hive-wordmark-black.svg +1 -0
  9. package/assets/brand/hive-wordmark-on-dark.svg +1 -0
  10. package/assets/brand/legion-logo-dark.svg +16 -0
  11. package/assets/brand/legion-logo-light.svg +16 -0
  12. package/assets/brand/nectar-mark.svg +1 -0
  13. package/assets/logos/fonts/Inter-Italic-VariableFont_opsz_wght.ttf +0 -0
  14. package/assets/logos/fonts/Inter-VariableFont_opsz_wght.ttf +0 -0
  15. package/assets/logos/fonts/JetBrainsMono-Bold.woff2 +0 -0
  16. package/assets/logos/fonts/JetBrainsMono-Medium.woff2 +0 -0
  17. package/assets/logos/fonts/JetBrainsMono-Regular.woff2 +0 -0
  18. package/assets/logos/fonts/JetBrainsMono-SemiBold.woff2 +0 -0
  19. package/assets/logos/honeycomb-memory-cluster.svg +17 -0
  20. package/assets/styles.css +11 -0
  21. package/assets/tokens/base.css +76 -0
  22. package/assets/tokens/colors.css +111 -0
  23. package/assets/tokens/fonts.css +32 -0
  24. package/assets/tokens/spacing.css +48 -0
  25. package/assets/tokens/typography.css +38 -0
  26. package/dist/daemon/dashboard/app.js +26 -25
  27. package/dist/daemon/dashboard/host.d.ts +7 -0
  28. package/dist/daemon/dashboard/host.js +16 -0
  29. package/dist/daemon/dashboard/host.js.map +1 -1
  30. package/dist/daemon/dashboard/web-assets.d.ts +2 -0
  31. package/dist/daemon/dashboard/web-assets.js +19 -0
  32. package/dist/daemon/dashboard/web-assets.js.map +1 -1
  33. package/dist/daemon/gate.d.ts +2 -2
  34. package/dist/daemon/gate.js +15 -4
  35. package/dist/daemon/gate.js.map +1 -1
  36. package/dist/daemon/installer/bin-resolver.d.ts +34 -0
  37. package/dist/daemon/installer/bin-resolver.js +107 -0
  38. package/dist/daemon/installer/bin-resolver.js.map +1 -0
  39. package/dist/daemon/installer/config.d.ts +63 -0
  40. package/dist/daemon/installer/config.js +74 -0
  41. package/dist/daemon/installer/config.js.map +1 -0
  42. package/dist/daemon/installer/detection.d.ts +20 -0
  43. package/dist/daemon/installer/detection.js +73 -0
  44. package/dist/daemon/installer/detection.js.map +1 -0
  45. package/dist/daemon/installer/funnel-telemetry.d.ts +54 -0
  46. package/dist/daemon/installer/funnel-telemetry.js +134 -0
  47. package/dist/daemon/installer/funnel-telemetry.js.map +1 -0
  48. package/dist/daemon/installer/index.d.ts +12 -0
  49. package/dist/daemon/installer/index.js +10 -0
  50. package/dist/daemon/installer/index.js.map +1 -0
  51. package/dist/daemon/installer/install-state.d.ts +56 -0
  52. package/dist/daemon/installer/install-state.js +159 -0
  53. package/dist/daemon/installer/install-state.js.map +1 -0
  54. package/dist/daemon/installer/manifest-snapshot.json +25 -0
  55. package/dist/daemon/installer/manifest.d.ts +47 -0
  56. package/dist/daemon/installer/manifest.js +103 -0
  57. package/dist/daemon/installer/manifest.js.map +1 -0
  58. package/dist/daemon/installer/products.d.ts +33 -0
  59. package/dist/daemon/installer/products.js +42 -0
  60. package/dist/daemon/installer/products.js.map +1 -0
  61. package/dist/daemon/installer/routes.d.ts +43 -0
  62. package/dist/daemon/installer/routes.js +201 -0
  63. package/dist/daemon/installer/routes.js.map +1 -0
  64. package/dist/daemon/installer/security.d.ts +33 -0
  65. package/dist/daemon/installer/security.js +80 -0
  66. package/dist/daemon/installer/security.js.map +1 -0
  67. package/dist/daemon/installer/spawn.d.ts +49 -0
  68. package/dist/daemon/installer/spawn.js +63 -0
  69. package/dist/daemon/installer/spawn.js.map +1 -0
  70. package/dist/daemon/installer/token.d.ts +23 -0
  71. package/dist/daemon/installer/token.js +56 -0
  72. package/dist/daemon/installer/token.js.map +1 -0
  73. package/dist/daemon/server.d.ts +6 -0
  74. package/dist/daemon/server.js +7 -0
  75. package/dist/daemon/server.js.map +1 -1
  76. package/dist/dashboard/web/app.js +42 -20
  77. package/dist/dashboard/web/app.js.map +1 -1
  78. package/dist/dashboard/web/boot-route.d.ts +11 -7
  79. package/dist/dashboard/web/boot-route.js +12 -6
  80. package/dist/dashboard/web/boot-route.js.map +1 -1
  81. package/dist/dashboard/web/main.js +2 -1
  82. package/dist/dashboard/web/main.js.map +1 -1
  83. package/dist/dashboard/web/onboarding/advanced-picker.d.ts +16 -0
  84. package/dist/dashboard/web/onboarding/advanced-picker.js +59 -0
  85. package/dist/dashboard/web/onboarding/advanced-picker.js.map +1 -0
  86. package/dist/dashboard/web/onboarding/contracts.d.ts +188 -0
  87. package/dist/dashboard/web/onboarding/contracts.js +161 -0
  88. package/dist/dashboard/web/onboarding/contracts.js.map +1 -0
  89. package/dist/dashboard/web/onboarding/health-view.d.ts +17 -0
  90. package/dist/dashboard/web/onboarding/health-view.js +79 -0
  91. package/dist/dashboard/web/onboarding/health-view.js.map +1 -0
  92. package/dist/dashboard/web/onboarding/install-card.d.ts +28 -0
  93. package/dist/dashboard/web/onboarding/install-card.js +171 -0
  94. package/dist/dashboard/web/onboarding/install-card.js.map +1 -0
  95. package/dist/dashboard/web/onboarding/login-step.d.ts +29 -0
  96. package/dist/dashboard/web/onboarding/login-step.js +104 -0
  97. package/dist/dashboard/web/onboarding/login-step.js.map +1 -0
  98. package/dist/dashboard/web/onboarding/onboarding-client.d.ts +52 -0
  99. package/dist/dashboard/web/onboarding/onboarding-client.js +133 -0
  100. package/dist/dashboard/web/onboarding/onboarding-client.js.map +1 -0
  101. package/dist/dashboard/web/onboarding/onboarding-hero.d.ts +24 -0
  102. package/dist/dashboard/web/onboarding/onboarding-hero.js +70 -0
  103. package/dist/dashboard/web/onboarding/onboarding-hero.js.map +1 -0
  104. package/dist/dashboard/web/onboarding/onboarding-screen.d.ts +43 -0
  105. package/dist/dashboard/web/onboarding/onboarding-screen.js +193 -0
  106. package/dist/dashboard/web/onboarding/onboarding-screen.js.map +1 -0
  107. package/dist/dashboard/web/onboarding/onboarding-selection-store.d.ts +20 -0
  108. package/dist/dashboard/web/onboarding/onboarding-selection-store.js +76 -0
  109. package/dist/dashboard/web/onboarding/onboarding-selection-store.js.map +1 -0
  110. package/dist/dashboard/web/onboarding/product-copy.d.ts +40 -0
  111. package/dist/dashboard/web/onboarding/product-copy.js +70 -0
  112. package/dist/dashboard/web/onboarding/product-copy.js.map +1 -0
  113. package/dist/dashboard/web/onboarding/use-install-dwell.d.ts +27 -0
  114. package/dist/dashboard/web/onboarding/use-install-dwell.js +42 -0
  115. package/dist/dashboard/web/onboarding/use-install-dwell.js.map +1 -0
  116. package/dist/dashboard/web/onboarding/use-onboarding-token.d.ts +14 -0
  117. package/dist/dashboard/web/onboarding/use-onboarding-token.js +41 -0
  118. package/dist/dashboard/web/onboarding/use-onboarding-token.js.map +1 -0
  119. package/dist/dashboard/web/route-daemon-owner.d.ts +7 -0
  120. package/dist/dashboard/web/route-daemon-owner.js +15 -0
  121. package/dist/dashboard/web/route-daemon-owner.js.map +1 -0
  122. package/dist/dashboard/web/wire.d.ts +1 -1
  123. package/dist/shared/onboarding-types.d.ts +79 -0
  124. package/dist/shared/onboarding-types.js +12 -0
  125. package/dist/shared/onboarding-types.js.map +1 -0
  126. package/dist/telemetry/emit.d.ts +30 -3
  127. package/dist/telemetry/emit.js +25 -2
  128. package/dist/telemetry/emit.js.map +1 -1
  129. package/dist/telemetry/onboarding-session-ledger.d.ts +31 -0
  130. package/dist/telemetry/onboarding-session-ledger.js +78 -0
  131. package/dist/telemetry/onboarding-session-ledger.js.map +1 -0
  132. package/package.json +6 -2
@@ -0,0 +1 @@
1
+ {"version":3,"file":"onboarding-hero.js","sourceRoot":"","sources":["../../../../src/dashboard/web/onboarding/onboarding-hero.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * The `/onboarding` route's TOP-LEVEL screen, PRD-009b. Mirrors `/buzzing`/`/login`'s posture
3
+ * (`buzzing-screen.tsx`, `setup-gate.tsx`): a single top-level component `main.tsx` mounts directly
4
+ * (via `boot-route.ts`), owning its own state machine rather than nesting inside the authenticated
5
+ * `<Shell>`. The state machine:
6
+ *
7
+ * detect (+ an upfront health read for ob-AC-3) ─┬─ all installed AND healthy → short-circuit
8
+ * ├─ a remaining product is mid-flight/failed →
9
+ * │ resume straight into "installing" (ob-AC-16/17)
10
+ * └─ otherwise → the first-run hero (ob-AC-4/5)
11
+ * hero ─ Standard → installing(all remaining, fixed order) (ob-AC-6)
12
+ * └ Advanced → picker → installing(exactly the chosen subset) (ob-AC-7)
13
+ * installing(queue, index) ── each card completes+dwells → advance → next index, else → health
14
+ * health ── polls until ready → login
15
+ * login ── device-code display, then a hard navigation to `/` on authenticated (ob-AC-14/15)
16
+ *
17
+ * Resume honesty (ob-AC-16): the Standard/Advanced choice is persisted client-side
18
+ * (onboarding-selection-store), so a resumed install uses `buildResumeQueue`, which excludes a
19
+ * not-installed product the operator explicitly deselected in Advanced. Without that memory, resume
20
+ * would fall back to only products that are genuinely mid-flight or failed, never silently
21
+ * reinstalling a deselected one.
22
+ */
23
+ import React from "react";
24
+ import { type OnboardingClient } from "./onboarding-client.js";
25
+ import type { WireClient } from "../wire.js";
26
+ export interface OnboardingScreenProps {
27
+ readonly assetBase?: string;
28
+ /** Test seam: inject a fake onboarding client, bypassing the real token + fetch wiring entirely. */
29
+ readonly client?: OnboardingClient;
30
+ /** Test seam: inject a fake proxied setup wire client for the login step. */
31
+ readonly wire?: WireClient;
32
+ /** Test seam: override the brief install dwell (ob-AC-11, revised). */
33
+ readonly minDwellMs?: number;
34
+ /** Test seam: override the health-check poll interval. */
35
+ readonly healthPollMs?: number;
36
+ /** Test seam: override the login step's `/setup/state` poll interval. */
37
+ readonly loginPollMs?: number;
38
+ /** Test seam: called instead of the real hard navigation from the short-circuit summary. */
39
+ readonly onShortCircuitNavigate?: () => void;
40
+ /** Test seam: called instead of the real hard navigation once login completes (ob-AC-15). */
41
+ readonly onAuthenticated?: () => void;
42
+ }
43
+ export declare function OnboardingScreen({ assetBase, client: clientOverride, wire, minDwellMs, healthPollMs, loginPollMs, onShortCircuitNavigate, onAuthenticated, }: OnboardingScreenProps): React.JSX.Element;
@@ -0,0 +1,193 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * The `/onboarding` route's TOP-LEVEL screen, PRD-009b. Mirrors `/buzzing`/`/login`'s posture
4
+ * (`buzzing-screen.tsx`, `setup-gate.tsx`): a single top-level component `main.tsx` mounts directly
5
+ * (via `boot-route.ts`), owning its own state machine rather than nesting inside the authenticated
6
+ * `<Shell>`. The state machine:
7
+ *
8
+ * detect (+ an upfront health read for ob-AC-3) ─┬─ all installed AND healthy → short-circuit
9
+ * ├─ a remaining product is mid-flight/failed →
10
+ * │ resume straight into "installing" (ob-AC-16/17)
11
+ * └─ otherwise → the first-run hero (ob-AC-4/5)
12
+ * hero ─ Standard → installing(all remaining, fixed order) (ob-AC-6)
13
+ * └ Advanced → picker → installing(exactly the chosen subset) (ob-AC-7)
14
+ * installing(queue, index) ── each card completes+dwells → advance → next index, else → health
15
+ * health ── polls until ready → login
16
+ * login ── device-code display, then a hard navigation to `/` on authenticated (ob-AC-14/15)
17
+ *
18
+ * Resume honesty (ob-AC-16): the Standard/Advanced choice is persisted client-side
19
+ * (onboarding-selection-store), so a resumed install uses `buildResumeQueue`, which excludes a
20
+ * not-installed product the operator explicitly deselected in Advanced. Without that memory, resume
21
+ * would fall back to only products that are genuinely mid-flight or failed, never silently
22
+ * reinstalling a deselected one.
23
+ */
24
+ import React from "react";
25
+ import { AdvancedPicker } from "./advanced-picker.js";
26
+ import { buildResumeQueue, DEFAULT_PRODUCT_DETECTION, detectionFor, hasResumableInstall, isFleetFullyInstalled, remainingProducts, } from "./contracts.js";
27
+ import { clearSelection, persistSelection, readSelection } from "./onboarding-selection-store.js";
28
+ import { HealthView } from "./health-view.js";
29
+ import { InstallCard } from "./install-card.js";
30
+ import { LoginStep } from "./login-step.js";
31
+ import { createOnboardingClient } from "./onboarding-client.js";
32
+ import { OnboardingHero } from "./onboarding-hero.js";
33
+ import { useOnboardingToken } from "./use-onboarding-token.js";
34
+ import { Button } from "../primitives.js";
35
+ /** An empty install queue means nothing more to do, skip straight to the health gate. */
36
+ function installingOrHealth(queue) {
37
+ return queue.length === 0 ? { kind: "health" } : { kind: "installing", queue, index: 0 };
38
+ }
39
+ /** ob-AC-3, the terminal "nothing to do" screen for an already-installed, healthy machine. */
40
+ function ShortCircuitSummary({ onGoToDashboard }) {
41
+ return (_jsx("div", { "data-testid": "onboarding-short-circuit", style: { display: "flex", alignItems: "center", justifyContent: "center", minHeight: "100vh", padding: 32, background: "var(--bg-canvas)", textAlign: "center" }, children: _jsxs("div", { style: {
42
+ display: "flex",
43
+ flexDirection: "column",
44
+ alignItems: "center",
45
+ gap: 18,
46
+ maxWidth: 440,
47
+ padding: "40px 32px",
48
+ background: "var(--bg-surface)",
49
+ border: "1px solid var(--border-default)",
50
+ borderRadius: "var(--radius-xl)",
51
+ }, children: [_jsx("h1", { style: { fontSize: "var(--text-xl)", fontWeight: 700, color: "var(--text-primary)", margin: 0, letterSpacing: "-0.02em" }, children: "Your fleet is already up" }), _jsx("p", { style: { fontFamily: "var(--font-sans)", fontSize: "var(--text-sm)", color: "var(--text-secondary)", margin: 0, lineHeight: 1.5 }, children: "Every product is installed and the fleet reads healthy. Nothing to install here." }), _jsx(Button, { variant: "primary", size: "lg", "data-testid": "onboarding-go-to-dashboard", onClick: onGoToDashboard, children: "Go to dashboard" })] }) }));
52
+ }
53
+ /**
54
+ * The terminal "no token" screen. The one-time token rides the opened URL (`/onboarding?t=...`) and
55
+ * is held in memory only, so landing here without one (a refresh after the URL scrub, the printed
56
+ * fallback link, a bookmark) can never recover on its own — the operator re-runs the installer,
57
+ * which mints a fresh token and reopens the portal.
58
+ */
59
+ function MissingTokenNotice() {
60
+ return (_jsx("div", { "data-testid": "onboarding-missing-token", style: { display: "flex", alignItems: "center", justifyContent: "center", minHeight: "100vh", padding: 32, background: "var(--bg-canvas)", textAlign: "center" }, children: _jsxs("div", { style: {
61
+ display: "flex",
62
+ flexDirection: "column",
63
+ alignItems: "center",
64
+ gap: 18,
65
+ maxWidth: 480,
66
+ padding: "40px 32px",
67
+ background: "var(--bg-surface)",
68
+ border: "1px solid var(--border-default)",
69
+ borderRadius: "var(--radius-xl)",
70
+ }, children: [_jsx("h1", { style: { fontSize: "var(--text-xl)", fontWeight: 700, color: "var(--text-primary)", margin: 0, letterSpacing: "-0.02em" }, children: "This setup link has expired" }), _jsx("p", { style: { fontFamily: "var(--font-sans)", fontSize: "var(--text-sm)", color: "var(--text-secondary)", margin: 0, lineHeight: 1.5 }, children: "The setup page needs the one-time link the installer opens for you, and this visit did not carry it (refreshing this page drops it too). Re-run the installer to get a fresh link:" }), _jsx("code", { style: {
71
+ fontFamily: "var(--font-mono)",
72
+ fontSize: "var(--text-xs)",
73
+ color: "var(--text-primary)",
74
+ background: "var(--bg-canvas)",
75
+ border: "1px solid var(--border-default)",
76
+ borderRadius: "var(--radius-md)",
77
+ padding: "10px 14px",
78
+ }, children: "curl -fsSL https://get.theapiary.sh | sh" })] }) }));
79
+ }
80
+ /** The brief pre-detection placeholder, visible only for the moment detect+health are in flight. */
81
+ function LoadingPlaceholder() {
82
+ return (_jsx("div", { "data-testid": "onboarding-loading", style: { display: "flex", alignItems: "center", justifyContent: "center", minHeight: "100vh", background: "var(--bg-canvas)" }, children: _jsx("p", { style: { fontFamily: "var(--font-mono)", fontSize: "var(--text-xs)", color: "var(--text-tertiary)" }, children: "Checking what is already installed\u2026" }) }));
83
+ }
84
+ export function OnboardingScreen({ assetBase = "assets", client: clientOverride, wire, minDwellMs, healthPollMs, loginPollMs, onShortCircuitNavigate, onAuthenticated, }) {
85
+ const token = useOnboardingToken();
86
+ // A test-injected client bypasses the token gate entirely (it never talks to the real token
87
+ // wiring); real usage waits for `useOnboardingToken` to resolve the `?t=` query param first.
88
+ // A RESOLVED-ABSENT token (`""`) is terminal: without it every installer call 401s, so the
89
+ // screen shows recovery guidance below instead of spinning on the loading placeholder forever.
90
+ const tokenReady = clientOverride !== undefined || (token !== null && token !== "");
91
+ const tokenMissing = clientOverride === undefined && token === "";
92
+ const client = React.useMemo(() => clientOverride ?? createOnboardingClient(token ?? ""), [clientOverride, token]);
93
+ const [phase, setPhase] = React.useState({ kind: "loading" });
94
+ const [detection, setDetection] = React.useState(null);
95
+ const startedEventFiredRef = React.useRef(false);
96
+ React.useEffect(() => {
97
+ if (!tokenReady || startedEventFiredRef.current)
98
+ return;
99
+ startedEventFiredRef.current = true;
100
+ client.sendEvent("onboarding_started");
101
+ }, [client, tokenReady]);
102
+ React.useEffect(() => {
103
+ if (!tokenReady)
104
+ return;
105
+ let alive = true;
106
+ void (async () => {
107
+ const [detectResult, healthResult] = await Promise.all([client.detect(), client.health()]);
108
+ if (!alive)
109
+ return;
110
+ setDetection(detectResult);
111
+ if (isFleetFullyInstalled(detectResult) && healthResult.ready) {
112
+ setPhase({ kind: "short-circuit" });
113
+ }
114
+ else if (hasResumableInstall(detectResult)) {
115
+ // Resume honors the operator's persisted subset so a deselected product is never
116
+ // silently reinstalled; falls back to only mid-flight/failed products when unknown.
117
+ setPhase(installingOrHealth(buildResumeQueue(detectResult, readSelection())));
118
+ }
119
+ else {
120
+ setPhase({ kind: "hero" });
121
+ }
122
+ })();
123
+ return () => {
124
+ alive = false;
125
+ };
126
+ }, [client, tokenReady]);
127
+ const chooseMode = React.useCallback((mode) => {
128
+ client.sendEvent("mode_selected", { mode });
129
+ if (mode === "standard") {
130
+ const queue = detection !== null ? remainingProducts(detection) : [];
131
+ persistSelection(queue);
132
+ setPhase(installingOrHealth(queue));
133
+ }
134
+ else {
135
+ setPhase({ kind: "picker" });
136
+ }
137
+ }, [client, detection]);
138
+ const confirmAdvanced = React.useCallback((selected) => {
139
+ persistSelection(selected);
140
+ setPhase(installingOrHealth(selected));
141
+ }, []);
142
+ const advanceInstall = React.useCallback(() => {
143
+ setPhase((current) => {
144
+ if (current.kind !== "installing")
145
+ return current;
146
+ const nextIndex = current.index + 1;
147
+ return nextIndex >= current.queue.length ? { kind: "health" } : { kind: "installing", queue: current.queue, index: nextIndex };
148
+ });
149
+ }, []);
150
+ const goToLogin = React.useCallback(() => setPhase({ kind: "login" }), []);
151
+ const handleShortCircuitNavigate = React.useCallback(() => {
152
+ clearSelection();
153
+ if (onShortCircuitNavigate !== undefined) {
154
+ onShortCircuitNavigate();
155
+ return;
156
+ }
157
+ if (typeof window !== "undefined")
158
+ window.location.assign("/");
159
+ }, [onShortCircuitNavigate]);
160
+ // Onboarding reached its terminal state (login complete): drop the persisted subset so a later
161
+ // visit starts clean rather than resuming against a stale choice.
162
+ const handleAuthenticated = React.useCallback(() => {
163
+ clearSelection();
164
+ if (onAuthenticated !== undefined)
165
+ onAuthenticated();
166
+ }, [onAuthenticated]);
167
+ if (tokenMissing)
168
+ return _jsx(MissingTokenNotice, {});
169
+ switch (phase.kind) {
170
+ case "loading":
171
+ return _jsx(LoadingPlaceholder, {});
172
+ case "short-circuit":
173
+ return _jsx(ShortCircuitSummary, { onGoToDashboard: handleShortCircuitNavigate });
174
+ case "hero":
175
+ return _jsx(OnboardingHero, { assetBase: assetBase, onChooseStandard: () => chooseMode("standard"), onChooseAdvanced: () => chooseMode("advanced") });
176
+ case "picker":
177
+ return _jsx(AdvancedPicker, { products: detection !== null ? remainingProducts(detection) : [], assetBase: assetBase, onConfirm: confirmAdvanced });
178
+ case "installing": {
179
+ const product = phase.queue[phase.index];
180
+ const initialDetection = detection !== null ? detectionFor(detection, product) : DEFAULT_PRODUCT_DETECTION;
181
+ return (_jsx(InstallCard, { product: product, initialDetection: initialDetection, client: client, assetBase: assetBase, onAdvance: advanceInstall, minDwellMs: minDwellMs }, product));
182
+ }
183
+ case "health":
184
+ return _jsx(HealthView, { client: client, onReady: goToLogin, pollMs: healthPollMs });
185
+ case "login":
186
+ return _jsx(LoginStep, { onboardingClient: client, wire: wire, onAuthenticated: handleAuthenticated, pollMs: loginPollMs });
187
+ default: {
188
+ const exhaustive = phase;
189
+ return exhaustive;
190
+ }
191
+ }
192
+ }
193
+ //# sourceMappingURL=onboarding-screen.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"onboarding-screen.js","sourceRoot":"","sources":["../../../../src/dashboard/web/onboarding/onboarding-screen.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Session-scoped memory of the product subset the operator chose (Standard = the whole fleet,
3
+ * Advanced = exactly the checked products). PRD-009b ob-AC-16 resume honesty: without this, an
4
+ * interrupted Advanced install resumes from `remainingProducts(detection)`, which is every
5
+ * not-installed product, so a product the operator explicitly DESELECTED would be silently
6
+ * reinstalled on re-entry. Persisting the choice lets `buildResumeQueue` exclude a not-installed
7
+ * product the operator never asked for, while still resuming any product that is genuinely
8
+ * mid-flight or failed (those are in-flight facts, not assumptions).
9
+ *
10
+ * Storage is `sessionStorage` (per browser session, cleared when the tab closes) and every access
11
+ * is guarded: a missing `window`, a storage exception (private mode, quota, disabled), or a
12
+ * malformed value all degrade to "no memory" rather than throwing into the onboarding flow.
13
+ */
14
+ import { type InstallableProduct } from "./contracts.js";
15
+ /** Persist the chosen installable subset (order-normalized to the fixed order, de-duplicated). */
16
+ export declare function persistSelection(selected: readonly InstallableProduct[]): void;
17
+ /** Read the persisted subset, or null when nothing valid is stored. */
18
+ export declare function readSelection(): readonly InstallableProduct[] | null;
19
+ /** Drop the persisted subset (call when onboarding reaches a terminal state). */
20
+ export declare function clearSelection(): void;
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Session-scoped memory of the product subset the operator chose (Standard = the whole fleet,
3
+ * Advanced = exactly the checked products). PRD-009b ob-AC-16 resume honesty: without this, an
4
+ * interrupted Advanced install resumes from `remainingProducts(detection)`, which is every
5
+ * not-installed product, so a product the operator explicitly DESELECTED would be silently
6
+ * reinstalled on re-entry. Persisting the choice lets `buildResumeQueue` exclude a not-installed
7
+ * product the operator never asked for, while still resuming any product that is genuinely
8
+ * mid-flight or failed (those are in-flight facts, not assumptions).
9
+ *
10
+ * Storage is `sessionStorage` (per browser session, cleared when the tab closes) and every access
11
+ * is guarded: a missing `window`, a storage exception (private mode, quota, disabled), or a
12
+ * malformed value all degrade to "no memory" rather than throwing into the onboarding flow.
13
+ */
14
+ import { FIXED_PRODUCT_ORDER, isInstallableProduct } from "./contracts.js";
15
+ const SELECTION_KEY = "hive-onboarding-selection";
16
+ function storage() {
17
+ try {
18
+ if (typeof window === "undefined")
19
+ return null;
20
+ return window.sessionStorage;
21
+ }
22
+ catch {
23
+ return null;
24
+ }
25
+ }
26
+ /** Persist the chosen installable subset (order-normalized to the fixed order, de-duplicated). */
27
+ export function persistSelection(selected) {
28
+ const store = storage();
29
+ if (store === null)
30
+ return;
31
+ const normalized = FIXED_PRODUCT_ORDER.filter((p) => selected.includes(p));
32
+ try {
33
+ store.setItem(SELECTION_KEY, JSON.stringify(normalized));
34
+ }
35
+ catch {
36
+ // A storage write failure is non-fatal: resume simply falls back to the conservative path.
37
+ }
38
+ }
39
+ /** Read the persisted subset, or null when nothing valid is stored. */
40
+ export function readSelection() {
41
+ const store = storage();
42
+ if (store === null)
43
+ return null;
44
+ let raw;
45
+ try {
46
+ raw = store.getItem(SELECTION_KEY);
47
+ }
48
+ catch {
49
+ return null;
50
+ }
51
+ if (raw === null)
52
+ return null;
53
+ try {
54
+ const parsed = JSON.parse(raw);
55
+ if (!Array.isArray(parsed))
56
+ return null;
57
+ const products = parsed.filter((v) => typeof v === "string" && isInstallableProduct(v));
58
+ return products.length > 0 ? FIXED_PRODUCT_ORDER.filter((p) => products.includes(p)) : null;
59
+ }
60
+ catch {
61
+ return null;
62
+ }
63
+ }
64
+ /** Drop the persisted subset (call when onboarding reaches a terminal state). */
65
+ export function clearSelection() {
66
+ const store = storage();
67
+ if (store === null)
68
+ return;
69
+ try {
70
+ store.removeItem(SELECTION_KEY);
71
+ }
72
+ catch {
73
+ // Non-fatal.
74
+ }
75
+ }
76
+ //# sourceMappingURL=onboarding-selection-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"onboarding-selection-store.js","sourceRoot":"","sources":["../../../../src/dashboard/web/onboarding/onboarding-selection-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAA2B,MAAM,gBAAgB,CAAC;AAEpG,MAAM,aAAa,GAAG,2BAA2B,CAAC;AAElD,SAAS,OAAO;IACf,IAAI,CAAC;QACJ,IAAI,OAAO,MAAM,KAAK,WAAW;YAAE,OAAO,IAAI,CAAC;QAC/C,OAAO,MAAM,CAAC,cAAc,CAAC;IAC9B,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,IAAI,CAAC;IACb,CAAC;AACF,CAAC;AAED,kGAAkG;AAClG,MAAM,UAAU,gBAAgB,CAAC,QAAuC;IACvE,MAAM,KAAK,GAAG,OAAO,EAAE,CAAC;IACxB,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO;IAC3B,MAAM,UAAU,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3E,IAAI,CAAC;QACJ,KAAK,CAAC,OAAO,CAAC,aAAa,EAAE,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC;IAC1D,CAAC;IAAC,MAAM,CAAC;QACR,2FAA2F;IAC5F,CAAC;AACF,CAAC;AAED,uEAAuE;AACvE,MAAM,UAAU,aAAa;IAC5B,MAAM,KAAK,GAAG,OAAO,EAAE,CAAC;IACxB,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAChC,IAAI,GAAkB,CAAC;IACvB,IAAI,CAAC;QACJ,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;IACpC,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,IAAI,CAAC;IACb,CAAC;IACD,IAAI,GAAG,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAC9B,IAAI,CAAC;QACJ,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACxC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;YAAE,OAAO,IAAI,CAAC;QACxC,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAA2B,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,oBAAoB,CAAC,CAAC,CAAC,CAAC,CAAC;QACjH,OAAO,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,mBAAmB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC7F,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,IAAI,CAAC;IACb,CAAC;AACF,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,cAAc;IAC7B,MAAM,KAAK,GAAG,OAAO,EAAE,CAAC;IACxB,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO;IAC3B,IAAI,CAAC;QACJ,KAAK,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;IACjC,CAAC;IAAC,MAAM,CAAC;QACR,aAAa;IACd,CAAC;AACF,CAAC"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * The onboarding CONTENT layer, PRD-009b ob-AC-8/ob-AC-10. Per-product benefit copy (drafted from
3
+ * each sibling repo's README voice: `honeycomb/README.md`, `doctor/README.md`, `nectar/README.md`)
4
+ * plus the npm-safety reassurance every install card carries and the Doctor-deselect warning the
5
+ * Advanced picker shows (ob-AC-7). Kept as data, not JSX, so copy review never touches a component.
6
+ */
7
+ import type { InstallableProduct, OnboardingProduct } from "./contracts.js";
8
+ export interface ProductCopy {
9
+ readonly title: string;
10
+ /** A punchy, honest headline (drafted from the product's README hero line). */
11
+ readonly headline: string;
12
+ /** Two short supporting lines, concrete, no invented claims. */
13
+ readonly lines: readonly [string, string];
14
+ /** Doctor carries the `Recommended` badge in the Advanced picker (ob-AC-7). */
15
+ readonly recommended: boolean;
16
+ }
17
+ /**
18
+ * Drafted verbatim from each product's README (see the task report for the source lines this
19
+ * copy distills): Doctor's "watchdog that keeps your agents' brain alive" + repair-ladder pitch,
20
+ * Honeycomb's "shared, persistent memory" + skillify/propagation pitch, Nectar's "stable identity
21
+ * that survives refactors" + the fourth-recall-arm pitch. Honest and concrete, no invented claims.
22
+ */
23
+ export declare const PRODUCT_COPY: Record<InstallableProduct, ProductCopy>;
24
+ /**
25
+ * ob-AC-10, the npm-safety reassurance every install card carries, verbatim. Checkably true for
26
+ * all four packages (`@legioncodeinc/{honeycomb,doctor,hive,nectar}` each publish with npm Trusted
27
+ * Publishing OIDC provenance per the parent PRD's overview), so this never overstates the claim.
28
+ */
29
+ export declare const NPM_SAFETY_COPY = "Installed straight from the public npm registry. Every package here is signed and provenance verified through npm Trusted Publishing (OIDC), so what installs is exactly what we published.";
30
+ /** ob-AC-7, shown when Doctor is deselected in the Advanced picker. */
31
+ export declare const DOCTOR_DESELECT_WARNING = "Without Doctor, nothing restarts your daemons after a crash or reboot.";
32
+ /**
33
+ * Resolve a product's brand mark URL. Honeycomb keeps its existing top-level, `assetBase`-relative
34
+ * route (`host.ts`'s `DASHBOARD_LOGO_PATH`, unchanged by this PRD); Doctor, Hive, and Nectar are
35
+ * served by the daemon agent at the new fixed `/assets/brand/<name>-mark.svg` route (see the task
36
+ * brief), independent of `assetBase`.
37
+ */
38
+ export declare function productLogoUrl(product: OnboardingProduct, assetBase: string): string;
39
+ /** The install-stage vocabulary (ob-AC-9): a short human label per stage, never a percentage. */
40
+ export declare const INSTALL_STAGE_LABEL: Record<"resolving" | "downloading" | "linking" | "registering_service" | "completed" | "failed", string>;
@@ -0,0 +1,70 @@
1
+ /**
2
+ * The onboarding CONTENT layer, PRD-009b ob-AC-8/ob-AC-10. Per-product benefit copy (drafted from
3
+ * each sibling repo's README voice: `honeycomb/README.md`, `doctor/README.md`, `nectar/README.md`)
4
+ * plus the npm-safety reassurance every install card carries and the Doctor-deselect warning the
5
+ * Advanced picker shows (ob-AC-7). Kept as data, not JSX, so copy review never touches a component.
6
+ */
7
+ /**
8
+ * Drafted verbatim from each product's README (see the task report for the source lines this
9
+ * copy distills): Doctor's "watchdog that keeps your agents' brain alive" + repair-ladder pitch,
10
+ * Honeycomb's "shared, persistent memory" + skillify/propagation pitch, Nectar's "stable identity
11
+ * that survives refactors" + the fourth-recall-arm pitch. Honest and concrete, no invented claims.
12
+ */
13
+ export const PRODUCT_COPY = {
14
+ doctor: {
15
+ title: "Doctor",
16
+ headline: "Doctor keeps your daemons alive while you are not looking.",
17
+ lines: [
18
+ "Restarts a crashed daemon, then climbs an escalating repair ladder if a plain restart is not enough.",
19
+ "Runs OS-supervised so it starts on boot and survives its own crashes too.",
20
+ ],
21
+ recommended: true,
22
+ },
23
+ honeycomb: {
24
+ title: "Honeycomb",
25
+ headline: "Honeycomb is the shared memory your agents keep across sessions.",
26
+ lines: [
27
+ "Captures what happens on every turn and recalls it in any harness, on any machine.",
28
+ "Mines reusable skills from real sessions and propagates them to your whole team automatically.",
29
+ ],
30
+ recommended: false,
31
+ },
32
+ nectar: {
33
+ title: "Nectar",
34
+ headline: "Nectar gives every file in your repo an identity that survives refactors.",
35
+ lines: [
36
+ "Tracks files through renames and moves, so memory tied to an old path never goes stale.",
37
+ "Feeds Honeycomb's recall a fourth arm, so asking where the login logic lives actually works.",
38
+ ],
39
+ recommended: false,
40
+ },
41
+ };
42
+ /**
43
+ * ob-AC-10, the npm-safety reassurance every install card carries, verbatim. Checkably true for
44
+ * all four packages (`@legioncodeinc/{honeycomb,doctor,hive,nectar}` each publish with npm Trusted
45
+ * Publishing OIDC provenance per the parent PRD's overview), so this never overstates the claim.
46
+ */
47
+ export const NPM_SAFETY_COPY = "Installed straight from the public npm registry. Every package here is signed and provenance verified through npm Trusted Publishing (OIDC), so what installs is exactly what we published.";
48
+ /** ob-AC-7, shown when Doctor is deselected in the Advanced picker. */
49
+ export const DOCTOR_DESELECT_WARNING = "Without Doctor, nothing restarts your daemons after a crash or reboot.";
50
+ /**
51
+ * Resolve a product's brand mark URL. Honeycomb keeps its existing top-level, `assetBase`-relative
52
+ * route (`host.ts`'s `DASHBOARD_LOGO_PATH`, unchanged by this PRD); Doctor, Hive, and Nectar are
53
+ * served by the daemon agent at the new fixed `/assets/brand/<name>-mark.svg` route (see the task
54
+ * brief), independent of `assetBase`.
55
+ */
56
+ export function productLogoUrl(product, assetBase) {
57
+ if (product === "honeycomb")
58
+ return `${assetBase}/honeycomb-memory-cluster.svg`;
59
+ return `/assets/brand/${product}-mark.svg`;
60
+ }
61
+ /** The install-stage vocabulary (ob-AC-9): a short human label per stage, never a percentage. */
62
+ export const INSTALL_STAGE_LABEL = {
63
+ resolving: "Resolving the package",
64
+ downloading: "Downloading from npm",
65
+ linking: "Linking the binary",
66
+ registering_service: "Registering the service",
67
+ completed: "Installed",
68
+ failed: "Installation failed",
69
+ };
70
+ //# sourceMappingURL=product-copy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"product-copy.js","sourceRoot":"","sources":["../../../../src/dashboard/web/onboarding/product-copy.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAcH;;;;;GAKG;AACH,MAAM,CAAC,MAAM,YAAY,GAA4C;IACpE,MAAM,EAAE;QACP,KAAK,EAAE,QAAQ;QACf,QAAQ,EAAE,4DAA4D;QACtE,KAAK,EAAE;YACN,sGAAsG;YACtG,2EAA2E;SAC3E;QACD,WAAW,EAAE,IAAI;KACjB;IACD,SAAS,EAAE;QACV,KAAK,EAAE,WAAW;QAClB,QAAQ,EAAE,kEAAkE;QAC5E,KAAK,EAAE;YACN,oFAAoF;YACpF,gGAAgG;SAChG;QACD,WAAW,EAAE,KAAK;KAClB;IACD,MAAM,EAAE;QACP,KAAK,EAAE,QAAQ;QACf,QAAQ,EAAE,2EAA2E;QACrF,KAAK,EAAE;YACN,yFAAyF;YACzF,8FAA8F;SAC9F;QACD,WAAW,EAAE,KAAK;KAClB;CACD,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,eAAe,GAC3B,6LAA6L,CAAC;AAE/L,uEAAuE;AACvE,MAAM,CAAC,MAAM,uBAAuB,GAAG,wEAAwE,CAAC;AAEhH;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,OAA0B,EAAE,SAAiB;IAC3E,IAAI,OAAO,KAAK,WAAW;QAAE,OAAO,GAAG,SAAS,+BAA+B,CAAC;IAChF,OAAO,iBAAiB,OAAO,WAAW,CAAC;AAC5C,CAAC;AAED,iGAAiG;AACjG,MAAM,CAAC,MAAM,mBAAmB,GAG5B;IACH,SAAS,EAAE,uBAAuB;IAClC,WAAW,EAAE,sBAAsB;IACnC,OAAO,EAAE,oBAAoB;IAC7B,mBAAmB,EAAE,yBAAyB;IAC9C,SAAS,EAAE,WAAW;IACtB,MAAM,EAAE,qBAAqB;CAC7B,CAAC"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * The install card's MINIMUM DWELL hook, PRD-009b ob-AC-11 (revised). The card advances as soon as
3
+ * the install actually completes, held only long enough for the completed state to visibly register
4
+ * (a sub-second flash-through would read as broken); a longer install simply holds the card until
5
+ * its own terminal state. The dwell timer NEVER masks a failure, this hook only ever gates the
6
+ * advance-on-SUCCESS path; a failed card renders its error immediately regardless of how much
7
+ * dwell time has elapsed (the caller never calls this hook's `ready` with a failure in mind).
8
+ */
9
+ /**
10
+ * The minimum time a card stays up after mount before a SUCCESSFUL install may advance. Short by
11
+ * design: the real install time drives the pace (originally ~30s per ob-AC-11, cut down because
12
+ * holding a finished install visibly idle reads as slowness, not polish). Overridable in tests.
13
+ */
14
+ export declare const DEFAULT_MIN_DWELL_MS = 2000;
15
+ export interface UseInstallDwellOptions {
16
+ /** Called exactly once, after `ready` has been true for the remaining minimum-dwell duration. */
17
+ readonly onDwellSatisfied: () => void;
18
+ /** Overrides {@link DEFAULT_MIN_DWELL_MS} (a test injects a short window). */
19
+ readonly minDwellMs?: number;
20
+ }
21
+ /**
22
+ * `ready` flips true once the install reaches its `completed` terminal state. The card's mount
23
+ * time is the dwell clock's start (installs begin the instant a card mounts), so a completion that
24
+ * lands at second 6 still holds the card until second 30; a completion that lands at second 40 has
25
+ * already satisfied the dwell and advances immediately.
26
+ */
27
+ export declare function useInstallDwell(ready: boolean, options: UseInstallDwellOptions): void;
@@ -0,0 +1,42 @@
1
+ /**
2
+ * The install card's MINIMUM DWELL hook, PRD-009b ob-AC-11 (revised). The card advances as soon as
3
+ * the install actually completes, held only long enough for the completed state to visibly register
4
+ * (a sub-second flash-through would read as broken); a longer install simply holds the card until
5
+ * its own terminal state. The dwell timer NEVER masks a failure, this hook only ever gates the
6
+ * advance-on-SUCCESS path; a failed card renders its error immediately regardless of how much
7
+ * dwell time has elapsed (the caller never calls this hook's `ready` with a failure in mind).
8
+ */
9
+ import React from "react";
10
+ /**
11
+ * The minimum time a card stays up after mount before a SUCCESSFUL install may advance. Short by
12
+ * design: the real install time drives the pace (originally ~30s per ob-AC-11, cut down because
13
+ * holding a finished install visibly idle reads as slowness, not polish). Overridable in tests.
14
+ */
15
+ export const DEFAULT_MIN_DWELL_MS = 2_000;
16
+ /**
17
+ * `ready` flips true once the install reaches its `completed` terminal state. The card's mount
18
+ * time is the dwell clock's start (installs begin the instant a card mounts), so a completion that
19
+ * lands at second 6 still holds the card until second 30; a completion that lands at second 40 has
20
+ * already satisfied the dwell and advances immediately.
21
+ */
22
+ export function useInstallDwell(ready, options) {
23
+ const { minDwellMs = DEFAULT_MIN_DWELL_MS } = options;
24
+ const startedAtRef = React.useRef(Date.now());
25
+ const firedRef = React.useRef(false);
26
+ // Read through a ref so a caller passing a fresh `onDwellSatisfied` closure every render never
27
+ // re-triggers the scheduling effect below (only `ready`/`minDwellMs` should do that).
28
+ const onDwellSatisfiedRef = React.useRef(options.onDwellSatisfied);
29
+ onDwellSatisfiedRef.current = options.onDwellSatisfied;
30
+ React.useEffect(() => {
31
+ if (!ready || firedRef.current)
32
+ return;
33
+ const elapsed = Date.now() - startedAtRef.current;
34
+ const remaining = Math.max(0, minDwellMs - elapsed);
35
+ const id = setTimeout(() => {
36
+ firedRef.current = true;
37
+ onDwellSatisfiedRef.current();
38
+ }, remaining);
39
+ return () => clearTimeout(id);
40
+ }, [ready, minDwellMs]);
41
+ }
42
+ //# sourceMappingURL=use-install-dwell.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-install-dwell.js","sourceRoot":"","sources":["../../../../src/dashboard/web/onboarding/use-install-dwell.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B;;;;GAIG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,KAAK,CAAC;AAS1C;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,KAAc,EAAE,OAA+B;IAC9E,MAAM,EAAE,UAAU,GAAG,oBAAoB,EAAE,GAAG,OAAO,CAAC;IACtD,MAAM,YAAY,GAAG,KAAK,CAAC,MAAM,CAAS,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IACtD,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAErC,+FAA+F;IAC/F,sFAAsF;IACtF,MAAM,mBAAmB,GAAG,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACnE,mBAAmB,CAAC,OAAO,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAEvD,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACpB,IAAI,CAAC,KAAK,IAAI,QAAQ,CAAC,OAAO;YAAE,OAAO;QACvC,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,YAAY,CAAC,OAAO,CAAC;QAClD,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,CAAC;QACpD,MAAM,EAAE,GAAG,UAAU,CAAC,GAAG,EAAE;YAC1B,QAAQ,CAAC,OAAO,GAAG,IAAI,CAAC;YACxB,mBAAmB,CAAC,OAAO,EAAE,CAAC;QAC/B,CAAC,EAAE,SAAS,CAAC,CAAC;QACd,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;IAC/B,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC;AACzB,CAAC"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * The one-time onboarding TOKEN hook, PRD-009b implementation note. The bootstrap mints the token
3
+ * and hands it to the browser via `/onboarding?t=...`; this hook reads it ONCE on mount, keeps it
4
+ * in React state (memory only) for the page's lifetime, and immediately strips it from the visible
5
+ * URL via `history.replaceState` so casual screen-sharing never exposes it. The read+strip is a side
6
+ * effect, so it runs inside `useEffect` (not a `useState` lazy initializer), render must stay pure.
7
+ */
8
+ /**
9
+ * Read `?t=` once, strip it from the visible URL, and return the token. Tri-state so the caller can
10
+ * distinguish "still resolving" from "resolved, absent": `null` until the mount effect has run,
11
+ * `""` when the URL carried no token (the caller shows recovery guidance rather than spinning
12
+ * forever), and the token string otherwise.
13
+ */
14
+ export declare function useOnboardingToken(): string | null;
@@ -0,0 +1,41 @@
1
+ /**
2
+ * The one-time onboarding TOKEN hook, PRD-009b implementation note. The bootstrap mints the token
3
+ * and hands it to the browser via `/onboarding?t=...`; this hook reads it ONCE on mount, keeps it
4
+ * in React state (memory only) for the page's lifetime, and immediately strips it from the visible
5
+ * URL via `history.replaceState` so casual screen-sharing never exposes it. The read+strip is a side
6
+ * effect, so it runs inside `useEffect` (not a `useState` lazy initializer), render must stay pure.
7
+ */
8
+ import React from "react";
9
+ const TOKEN_QUERY_PARAM = "t";
10
+ /**
11
+ * Read `?t=` once, strip it from the visible URL, and return the token. Tri-state so the caller can
12
+ * distinguish "still resolving" from "resolved, absent": `null` until the mount effect has run,
13
+ * `""` when the URL carried no token (the caller shows recovery guidance rather than spinning
14
+ * forever), and the token string otherwise.
15
+ */
16
+ export function useOnboardingToken() {
17
+ const [token, setToken] = React.useState(null);
18
+ React.useEffect(() => {
19
+ if (typeof window === "undefined")
20
+ return;
21
+ const params = new URLSearchParams(window.location.search);
22
+ const fromUrl = params.get(TOKEN_QUERY_PARAM);
23
+ if (fromUrl === null || fromUrl === "") {
24
+ setToken("");
25
+ return;
26
+ }
27
+ setToken(fromUrl);
28
+ // Move it out of the visible URL (PRD implementation note), the token stays in memory only.
29
+ try {
30
+ const url = new URL(window.location.href);
31
+ url.searchParams.delete(TOKEN_QUERY_PARAM);
32
+ window.history.replaceState(null, "", `${url.pathname}${url.search}${url.hash}`);
33
+ }
34
+ catch {
35
+ // A `history` API failure (e.g. an unusual embedding context) must never block the flow ,
36
+ // the token still landed in state; only the cosmetic URL scrub is skipped.
37
+ }
38
+ }, []);
39
+ return token;
40
+ }
41
+ //# sourceMappingURL=use-onboarding-token.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-onboarding-token.js","sourceRoot":"","sources":["../../../../src/dashboard/web/onboarding/use-onboarding-token.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,iBAAiB,GAAG,GAAY,CAAC;AAEvC;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB;IACjC,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAgB,IAAI,CAAC,CAAC;IAE9D,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACpB,IAAI,OAAO,MAAM,KAAK,WAAW;YAAE,OAAO;QAC1C,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QAC3D,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;QAC9C,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,KAAK,EAAE,EAAE,CAAC;YACxC,QAAQ,CAAC,EAAE,CAAC,CAAC;YACb,OAAO;QACR,CAAC;QAED,QAAQ,CAAC,OAAO,CAAC,CAAC;QAElB,4FAA4F;QAC5F,IAAI,CAAC;YACJ,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;YAC1C,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC;YAC3C,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,IAAI,EAAE,EAAE,EAAE,GAAG,GAAG,CAAC,QAAQ,GAAG,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;QAClF,CAAC;QAAC,MAAM,CAAC;YACR,0FAA0F;YAC1F,2EAA2E;QAC5E,CAAC;IACF,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO,KAAK,CAAC;AACd,CAAC"}