@openparachute/hub 0.5.14-rc.9 → 0.6.0
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/README.md +23 -0
- package/package.json +7 -3
- package/src/__tests__/account-home-ui.test.ts +251 -15
- package/src/__tests__/account-vault-token.test.ts +355 -0
- package/src/__tests__/admin-vaults.test.ts +70 -4
- package/src/__tests__/api-mint-token.test.ts +30 -21
- package/src/__tests__/api-modules-ops.test.ts +45 -0
- package/src/__tests__/api-users.test.ts +7 -2
- package/src/__tests__/auth.test.ts +157 -30
- package/src/__tests__/cli.test.ts +44 -5
- package/src/__tests__/expose-2fa-warning.test.ts +31 -17
- package/src/__tests__/expose-auth-preflight.test.ts +71 -72
- package/src/__tests__/expose-cloudflare.test.ts +482 -14
- package/src/__tests__/expose.test.ts +52 -2
- package/src/__tests__/hub-server.test.ts +97 -0
- package/src/__tests__/hub.test.ts +85 -6
- package/src/__tests__/init.test.ts +102 -1
- package/src/__tests__/lifecycle.test.ts +464 -2
- package/src/__tests__/oauth-handlers.test.ts +1252 -83
- package/src/__tests__/oauth-ui.test.ts +12 -1
- package/src/__tests__/operator-token-issuer-self-heal.test.ts +412 -0
- package/src/__tests__/resource-binding.test.ts +97 -0
- package/src/__tests__/scope-explanations.test.ts +41 -12
- package/src/__tests__/services-manifest.test.ts +122 -4
- package/src/__tests__/setup-wizard.test.ts +335 -15
- package/src/__tests__/status.test.ts +36 -0
- package/src/__tests__/two-factor-flow.test.ts +602 -0
- package/src/__tests__/two-factor.test.ts +183 -0
- package/src/__tests__/upgrade.test.ts +78 -1
- package/src/__tests__/users.test.ts +68 -0
- package/src/__tests__/vault-auth-status.test.ts +47 -6
- package/src/__tests__/vault-hub-origin-env.test.ts +263 -0
- package/src/account-home-ui.ts +488 -38
- package/src/account-vault-token.ts +282 -0
- package/src/admin-handlers.ts +159 -4
- package/src/admin-login-ui.ts +49 -5
- package/src/admin-vaults.ts +48 -15
- package/src/api-account.ts +14 -0
- package/src/api-modules-ops.ts +49 -11
- package/src/api-users.ts +29 -3
- package/src/cli.ts +26 -21
- package/src/clients.ts +18 -6
- package/src/cloudflare/config.ts +10 -4
- package/src/cloudflare/detect.ts +39 -44
- package/src/commands/auth.ts +165 -24
- package/src/commands/expose-2fa-warning.ts +34 -32
- package/src/commands/expose-auth-preflight.ts +89 -78
- package/src/commands/expose-cloudflare.ts +370 -12
- package/src/commands/expose.ts +8 -0
- package/src/commands/init.ts +33 -2
- package/src/commands/lifecycle.ts +386 -17
- package/src/commands/status.ts +22 -0
- package/src/commands/upgrade.ts +55 -11
- package/src/commands/wizard.ts +8 -4
- package/src/env-file.ts +10 -0
- package/src/help.ts +3 -1
- package/src/hub-db.ts +39 -1
- package/src/hub-server.ts +52 -0
- package/src/hub.ts +82 -14
- package/src/oauth-handlers.ts +298 -21
- package/src/oauth-ui.ts +10 -0
- package/src/operator-token.ts +151 -0
- package/src/pending-login.ts +116 -0
- package/src/rate-limit.ts +51 -0
- package/src/resource-binding.ts +134 -0
- package/src/scope-explanations.ts +46 -18
- package/src/services-manifest.ts +112 -0
- package/src/setup-wizard.ts +77 -7
- package/src/tailscale/run.ts +28 -11
- package/src/totp.ts +201 -0
- package/src/two-factor-handlers.ts +287 -0
- package/src/two-factor-store.ts +181 -0
- package/src/two-factor-ui.ts +462 -0
- package/src/users.ts +58 -0
- package/src/vault/auth-status.ts +71 -19
- package/src/vault-hub-origin-env.ts +163 -0
- package/web/ui/dist/assets/index-BiBlvEaj.css +1 -0
- package/web/ui/dist/assets/index-CIN3mnmf.js +61 -0
- package/web/ui/dist/index.html +2 -2
- package/src/__tests__/vault-tokens-create-interactive.test.ts +0 -183
- package/src/commands/vault-tokens-create-interactive.ts +0 -143
- package/web/ui/dist/assets/index-7DtAXz7y.css +0 -1
- package/web/ui/dist/assets/index-tRmPbbC7.js +0 -61
|
@@ -23,6 +23,7 @@ import {
|
|
|
23
23
|
getDefaultOperationsRegistry,
|
|
24
24
|
} from "../api-modules-ops.ts";
|
|
25
25
|
import { CSRF_COOKIE_NAME, CSRF_FIELD_NAME } from "../csrf.ts";
|
|
26
|
+
import { type ExposeState, readExposeState, writeExposeState } from "../expose-state.ts";
|
|
26
27
|
import { hubDbPath, openHubDb } from "../hub-db.ts";
|
|
27
28
|
import { hubFetch } from "../hub-server.ts";
|
|
28
29
|
import { getSetting, setSetting } from "../hub-settings.ts";
|
|
@@ -44,6 +45,20 @@ import { createUser, getUserByUsername, userCount } from "../users.ts";
|
|
|
44
45
|
interface Harness {
|
|
45
46
|
dir: string;
|
|
46
47
|
manifestPath: string;
|
|
48
|
+
/**
|
|
49
|
+
* Hermetic expose-state reader scoped to the harness's tmp dir. The
|
|
50
|
+
* production `readExposeState()` defaults to the operator's real
|
|
51
|
+
* `~/.parachute/expose-state.json` (a module-load constant), so a
|
|
52
|
+
* wizard test that omits an injected reader would auto-seed
|
|
53
|
+
* `setup_expose_mode` from the developer's LIVE exposure (hub#406) and
|
|
54
|
+
* flip expose-step assertions nondeterministically. Threading this
|
|
55
|
+
* harness reader keeps every wizard test isolated from the real
|
|
56
|
+
* filesystem — same isolation the harness already gives DB + manifest.
|
|
57
|
+
* Defaults to "no live exposure" (the tmp file doesn't exist) unless a
|
|
58
|
+
* test writes one via `writeExposeState(state, h.exposeStatePath)`.
|
|
59
|
+
*/
|
|
60
|
+
exposeStatePath: string;
|
|
61
|
+
readExposeStateFn: () => ExposeState | undefined;
|
|
47
62
|
cleanup: () => void;
|
|
48
63
|
}
|
|
49
64
|
|
|
@@ -52,9 +67,12 @@ function makeHarness(): Harness {
|
|
|
52
67
|
writeFileSync(join(dir, "hub.html"), "<html>discovery</html>");
|
|
53
68
|
const manifestPath = join(dir, "services.json");
|
|
54
69
|
writeManifest({ services: [] }, manifestPath);
|
|
70
|
+
const exposeStatePath = join(dir, "expose-state.json");
|
|
55
71
|
return {
|
|
56
72
|
dir,
|
|
57
73
|
manifestPath,
|
|
74
|
+
exposeStatePath,
|
|
75
|
+
readExposeStateFn: () => readExposeState(exposeStatePath),
|
|
58
76
|
cleanup: () => rmSync(dir, { recursive: true, force: true }),
|
|
59
77
|
};
|
|
60
78
|
}
|
|
@@ -124,7 +142,11 @@ describe("deriveWizardState", () => {
|
|
|
124
142
|
test("welcome step when no admin and no vault", () => {
|
|
125
143
|
const db = openHubDb(hubDbPath(h.dir));
|
|
126
144
|
try {
|
|
127
|
-
const s = deriveWizardState({
|
|
145
|
+
const s = deriveWizardState({
|
|
146
|
+
db,
|
|
147
|
+
manifestPath: h.manifestPath,
|
|
148
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
149
|
+
});
|
|
128
150
|
expect(s.step).toBe("welcome");
|
|
129
151
|
expect(s.hasAdmin).toBe(false);
|
|
130
152
|
expect(s.hasVault).toBe(false);
|
|
@@ -137,7 +159,11 @@ describe("deriveWizardState", () => {
|
|
|
137
159
|
const db = openHubDb(hubDbPath(h.dir));
|
|
138
160
|
try {
|
|
139
161
|
await createUser(db, "owner", "pw");
|
|
140
|
-
const s = deriveWizardState({
|
|
162
|
+
const s = deriveWizardState({
|
|
163
|
+
db,
|
|
164
|
+
manifestPath: h.manifestPath,
|
|
165
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
166
|
+
});
|
|
141
167
|
expect(s.step).toBe("vault");
|
|
142
168
|
expect(s.hasAdmin).toBe(true);
|
|
143
169
|
expect(s.hasVault).toBe(false);
|
|
@@ -164,7 +190,11 @@ describe("deriveWizardState", () => {
|
|
|
164
190
|
},
|
|
165
191
|
h.manifestPath,
|
|
166
192
|
);
|
|
167
|
-
const s = deriveWizardState({
|
|
193
|
+
const s = deriveWizardState({
|
|
194
|
+
db,
|
|
195
|
+
manifestPath: h.manifestPath,
|
|
196
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
197
|
+
});
|
|
168
198
|
expect(s.step).toBe("expose");
|
|
169
199
|
expect(s.hasAdmin).toBe(true);
|
|
170
200
|
expect(s.hasVault).toBe(true);
|
|
@@ -201,7 +231,12 @@ describe("deriveWizardState", () => {
|
|
|
201
231
|
);
|
|
202
232
|
// Simulate Render env. detectAutoExposeMode reads RENDER_EXTERNAL_URL.
|
|
203
233
|
const renderEnv = { RENDER_EXTERNAL_URL: "https://parachute-hub.onrender.com" };
|
|
204
|
-
const s = deriveWizardState({
|
|
234
|
+
const s = deriveWizardState({
|
|
235
|
+
db,
|
|
236
|
+
manifestPath: h.manifestPath,
|
|
237
|
+
env: renderEnv,
|
|
238
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
239
|
+
});
|
|
205
240
|
expect(s.step).toBe("done");
|
|
206
241
|
expect(s.hasExposeMode).toBe(true);
|
|
207
242
|
} finally {
|
|
@@ -227,7 +262,12 @@ describe("deriveWizardState", () => {
|
|
|
227
262
|
},
|
|
228
263
|
h.manifestPath,
|
|
229
264
|
);
|
|
230
|
-
const s = deriveWizardState({
|
|
265
|
+
const s = deriveWizardState({
|
|
266
|
+
db,
|
|
267
|
+
manifestPath: h.manifestPath,
|
|
268
|
+
env: {},
|
|
269
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
270
|
+
});
|
|
231
271
|
// Local install path — the operator still gets to choose
|
|
232
272
|
expect(s.step).toBe("expose");
|
|
233
273
|
expect(s.hasExposeMode).toBe(false);
|
|
@@ -236,6 +276,188 @@ describe("deriveWizardState", () => {
|
|
|
236
276
|
}
|
|
237
277
|
});
|
|
238
278
|
|
|
279
|
+
test("auto-seeds expose mode from a live `parachute expose tailnet` (hub#406 team-onboarding bug)", async () => {
|
|
280
|
+
// Team-onboarding bug: an operator ran `parachute expose tailnet`
|
|
281
|
+
// BEFORE opening the wizard. That writes expose-state.json
|
|
282
|
+
// (layer=tailnet) but never the `setup_expose_mode` hub_setting —
|
|
283
|
+
// the two are orthogonal axes. Pre-fix, the wizard consulted only
|
|
284
|
+
// the setting and re-rendered "How will this hub be reached?" though
|
|
285
|
+
// tailnet was already live. deriveWizardState now reads the live
|
|
286
|
+
// exposure layer and auto-seeds the setting, so the expose step is
|
|
287
|
+
// treated as satisfied and the wizard advances to done.
|
|
288
|
+
const db = openHubDb(hubDbPath(h.dir));
|
|
289
|
+
try {
|
|
290
|
+
await createUser(db, "owner", "pw");
|
|
291
|
+
writeManifest(
|
|
292
|
+
{
|
|
293
|
+
services: [
|
|
294
|
+
{
|
|
295
|
+
name: "parachute-vault",
|
|
296
|
+
version: "0.1.0",
|
|
297
|
+
port: 1940,
|
|
298
|
+
paths: ["/vault/default"],
|
|
299
|
+
health: "/health",
|
|
300
|
+
},
|
|
301
|
+
],
|
|
302
|
+
},
|
|
303
|
+
h.manifestPath,
|
|
304
|
+
);
|
|
305
|
+
// Simulate `parachute expose tailnet`: write a real expose-state
|
|
306
|
+
// file (round-trips through readExposeState's validator) into the
|
|
307
|
+
// harness tmp path. No env signal (not Render/Fly), no setting.
|
|
308
|
+
writeExposeState(
|
|
309
|
+
{
|
|
310
|
+
version: 1,
|
|
311
|
+
layer: "tailnet",
|
|
312
|
+
mode: "path",
|
|
313
|
+
canonicalFqdn: "my-mac.tailnet-name.ts.net",
|
|
314
|
+
port: 1939,
|
|
315
|
+
funnel: false,
|
|
316
|
+
entries: [],
|
|
317
|
+
},
|
|
318
|
+
h.exposeStatePath,
|
|
319
|
+
);
|
|
320
|
+
const s = deriveWizardState({
|
|
321
|
+
db,
|
|
322
|
+
manifestPath: h.manifestPath,
|
|
323
|
+
env: {},
|
|
324
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
325
|
+
});
|
|
326
|
+
expect(s.step).toBe("done");
|
|
327
|
+
expect(s.hasExposeMode).toBe(true);
|
|
328
|
+
// The setting was auto-seeded from the live exposure layer.
|
|
329
|
+
expect(getSetting(db, "setup_expose_mode")).toBe("tailnet");
|
|
330
|
+
} finally {
|
|
331
|
+
db.close();
|
|
332
|
+
}
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
test("auto-seeds expose mode = public from a live public exposure", async () => {
|
|
336
|
+
const db = openHubDb(hubDbPath(h.dir));
|
|
337
|
+
try {
|
|
338
|
+
await createUser(db, "owner", "pw");
|
|
339
|
+
writeManifest(
|
|
340
|
+
{
|
|
341
|
+
services: [
|
|
342
|
+
{
|
|
343
|
+
name: "parachute-vault",
|
|
344
|
+
version: "0.1.0",
|
|
345
|
+
port: 1940,
|
|
346
|
+
paths: ["/vault/default"],
|
|
347
|
+
health: "/health",
|
|
348
|
+
},
|
|
349
|
+
],
|
|
350
|
+
},
|
|
351
|
+
h.manifestPath,
|
|
352
|
+
);
|
|
353
|
+
writeExposeState(
|
|
354
|
+
{
|
|
355
|
+
version: 1,
|
|
356
|
+
layer: "public",
|
|
357
|
+
mode: "path",
|
|
358
|
+
canonicalFqdn: "hub.example.com",
|
|
359
|
+
port: 1939,
|
|
360
|
+
funnel: true,
|
|
361
|
+
entries: [],
|
|
362
|
+
},
|
|
363
|
+
h.exposeStatePath,
|
|
364
|
+
);
|
|
365
|
+
const s = deriveWizardState({
|
|
366
|
+
db,
|
|
367
|
+
manifestPath: h.manifestPath,
|
|
368
|
+
env: {},
|
|
369
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
370
|
+
});
|
|
371
|
+
expect(s.step).toBe("done");
|
|
372
|
+
expect(s.hasExposeMode).toBe(true);
|
|
373
|
+
expect(getSetting(db, "setup_expose_mode")).toBe("public");
|
|
374
|
+
} finally {
|
|
375
|
+
db.close();
|
|
376
|
+
}
|
|
377
|
+
});
|
|
378
|
+
|
|
379
|
+
test("still asks the expose step when no live exposure + no setting (unchanged)", async () => {
|
|
380
|
+
const db = openHubDb(hubDbPath(h.dir));
|
|
381
|
+
try {
|
|
382
|
+
await createUser(db, "owner", "pw");
|
|
383
|
+
writeManifest(
|
|
384
|
+
{
|
|
385
|
+
services: [
|
|
386
|
+
{
|
|
387
|
+
name: "parachute-vault",
|
|
388
|
+
version: "0.1.0",
|
|
389
|
+
port: 1940,
|
|
390
|
+
paths: ["/vault/default"],
|
|
391
|
+
health: "/health",
|
|
392
|
+
},
|
|
393
|
+
],
|
|
394
|
+
},
|
|
395
|
+
h.manifestPath,
|
|
396
|
+
);
|
|
397
|
+
// No env signal, no expose-state file written (reader returns
|
|
398
|
+
// undefined), no setting → the operator still gets the expose step.
|
|
399
|
+
const s = deriveWizardState({
|
|
400
|
+
db,
|
|
401
|
+
manifestPath: h.manifestPath,
|
|
402
|
+
env: {},
|
|
403
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
404
|
+
});
|
|
405
|
+
expect(s.step).toBe("expose");
|
|
406
|
+
expect(s.hasExposeMode).toBe(false);
|
|
407
|
+
expect(getSetting(db, "setup_expose_mode")).toBeUndefined();
|
|
408
|
+
} finally {
|
|
409
|
+
db.close();
|
|
410
|
+
}
|
|
411
|
+
});
|
|
412
|
+
|
|
413
|
+
test("an explicit setup_expose_mode wins over a live exposure (no clobber)", async () => {
|
|
414
|
+
// If the operator already answered the expose step (or it was seeded
|
|
415
|
+
// by a prior call), a later live-exposure read must not overwrite the
|
|
416
|
+
// recorded answer. Guards the `=== undefined` gate.
|
|
417
|
+
const db = openHubDb(hubDbPath(h.dir));
|
|
418
|
+
try {
|
|
419
|
+
await createUser(db, "owner", "pw");
|
|
420
|
+
writeManifest(
|
|
421
|
+
{
|
|
422
|
+
services: [
|
|
423
|
+
{
|
|
424
|
+
name: "parachute-vault",
|
|
425
|
+
version: "0.1.0",
|
|
426
|
+
port: 1940,
|
|
427
|
+
paths: ["/vault/default"],
|
|
428
|
+
health: "/health",
|
|
429
|
+
},
|
|
430
|
+
],
|
|
431
|
+
},
|
|
432
|
+
h.manifestPath,
|
|
433
|
+
);
|
|
434
|
+
setSetting(db, "setup_expose_mode", "localhost");
|
|
435
|
+
writeExposeState(
|
|
436
|
+
{
|
|
437
|
+
version: 1,
|
|
438
|
+
layer: "public",
|
|
439
|
+
mode: "path",
|
|
440
|
+
canonicalFqdn: "hub.example.com",
|
|
441
|
+
port: 1939,
|
|
442
|
+
funnel: true,
|
|
443
|
+
entries: [],
|
|
444
|
+
},
|
|
445
|
+
h.exposeStatePath,
|
|
446
|
+
);
|
|
447
|
+
const s = deriveWizardState({
|
|
448
|
+
db,
|
|
449
|
+
manifestPath: h.manifestPath,
|
|
450
|
+
env: {},
|
|
451
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
452
|
+
});
|
|
453
|
+
expect(s.step).toBe("done");
|
|
454
|
+
// Recorded answer is preserved, not overwritten by the live layer.
|
|
455
|
+
expect(getSetting(db, "setup_expose_mode")).toBe("localhost");
|
|
456
|
+
} finally {
|
|
457
|
+
db.close();
|
|
458
|
+
}
|
|
459
|
+
});
|
|
460
|
+
|
|
239
461
|
test("done step once admin + vault + expose mode all exist", async () => {
|
|
240
462
|
const db = openHubDb(hubDbPath(h.dir));
|
|
241
463
|
try {
|
|
@@ -255,7 +477,11 @@ describe("deriveWizardState", () => {
|
|
|
255
477
|
h.manifestPath,
|
|
256
478
|
);
|
|
257
479
|
setSetting(db, "setup_expose_mode", "localhost");
|
|
258
|
-
const s = deriveWizardState({
|
|
480
|
+
const s = deriveWizardState({
|
|
481
|
+
db,
|
|
482
|
+
manifestPath: h.manifestPath,
|
|
483
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
484
|
+
});
|
|
259
485
|
expect(s.step).toBe("done");
|
|
260
486
|
expect(s.hasAdmin).toBe(true);
|
|
261
487
|
expect(s.hasVault).toBe(true);
|
|
@@ -283,6 +509,7 @@ describe("handleSetupGet", () => {
|
|
|
283
509
|
db,
|
|
284
510
|
manifestPath: h.manifestPath,
|
|
285
511
|
configDir: h.dir,
|
|
512
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
286
513
|
issuer: "https://hub.example",
|
|
287
514
|
registry: getDefaultOperationsRegistry(),
|
|
288
515
|
});
|
|
@@ -304,6 +531,7 @@ describe("handleSetupGet", () => {
|
|
|
304
531
|
db,
|
|
305
532
|
manifestPath: h.manifestPath,
|
|
306
533
|
configDir: h.dir,
|
|
534
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
307
535
|
issuer: "https://hub.example",
|
|
308
536
|
registry: getDefaultOperationsRegistry(),
|
|
309
537
|
});
|
|
@@ -354,6 +582,7 @@ describe("handleSetupGet", () => {
|
|
|
354
582
|
db,
|
|
355
583
|
manifestPath: h.manifestPath,
|
|
356
584
|
configDir: h.dir,
|
|
585
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
357
586
|
issuer: "https://hub.example",
|
|
358
587
|
registry: getDefaultOperationsRegistry(),
|
|
359
588
|
});
|
|
@@ -386,6 +615,7 @@ describe("handleSetupGet", () => {
|
|
|
386
615
|
db,
|
|
387
616
|
manifestPath: h.manifestPath,
|
|
388
617
|
configDir: h.dir,
|
|
618
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
389
619
|
issuer: "https://hub.example",
|
|
390
620
|
registry: getDefaultOperationsRegistry(),
|
|
391
621
|
});
|
|
@@ -434,6 +664,7 @@ describe("handleSetupGet", () => {
|
|
|
434
664
|
db,
|
|
435
665
|
manifestPath: h.manifestPath,
|
|
436
666
|
configDir: h.dir,
|
|
667
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
437
668
|
issuer: "https://hub.example",
|
|
438
669
|
registry: getDefaultOperationsRegistry(),
|
|
439
670
|
},
|
|
@@ -483,6 +714,7 @@ describe("handleSetupGet", () => {
|
|
|
483
714
|
db,
|
|
484
715
|
manifestPath: h.manifestPath,
|
|
485
716
|
configDir: h.dir,
|
|
717
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
486
718
|
issuer: "https://hub.example",
|
|
487
719
|
registry: getDefaultOperationsRegistry(),
|
|
488
720
|
},
|
|
@@ -524,6 +756,7 @@ describe("handleSetupGet", () => {
|
|
|
524
756
|
db,
|
|
525
757
|
manifestPath: h.manifestPath,
|
|
526
758
|
configDir: h.dir,
|
|
759
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
527
760
|
issuer: "https://hub.example",
|
|
528
761
|
registry: getDefaultOperationsRegistry(),
|
|
529
762
|
},
|
|
@@ -548,6 +781,7 @@ describe("handleSetupGet", () => {
|
|
|
548
781
|
db,
|
|
549
782
|
manifestPath: h.manifestPath,
|
|
550
783
|
configDir: h.dir,
|
|
784
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
551
785
|
issuer: "https://hub.example",
|
|
552
786
|
registry: reg,
|
|
553
787
|
});
|
|
@@ -577,6 +811,7 @@ describe("handleSetupGet", () => {
|
|
|
577
811
|
db,
|
|
578
812
|
manifestPath: h.manifestPath,
|
|
579
813
|
configDir: h.dir,
|
|
814
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
580
815
|
issuer: "https://hub.example",
|
|
581
816
|
registry: reg,
|
|
582
817
|
});
|
|
@@ -608,6 +843,7 @@ describe("handleSetupAccountPost", () => {
|
|
|
608
843
|
db,
|
|
609
844
|
manifestPath: h.manifestPath,
|
|
610
845
|
configDir: h.dir,
|
|
846
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
611
847
|
issuer: "https://hub.example",
|
|
612
848
|
registry: getDefaultOperationsRegistry(),
|
|
613
849
|
});
|
|
@@ -632,6 +868,7 @@ describe("handleSetupAccountPost", () => {
|
|
|
632
868
|
db,
|
|
633
869
|
manifestPath: h.manifestPath,
|
|
634
870
|
configDir: h.dir,
|
|
871
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
635
872
|
issuer: "https://hub.example",
|
|
636
873
|
registry: getDefaultOperationsRegistry(),
|
|
637
874
|
},
|
|
@@ -660,6 +897,7 @@ describe("handleSetupAccountPost", () => {
|
|
|
660
897
|
db,
|
|
661
898
|
manifestPath: h.manifestPath,
|
|
662
899
|
configDir: h.dir,
|
|
900
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
663
901
|
issuer: "https://hub.example",
|
|
664
902
|
registry: getDefaultOperationsRegistry(),
|
|
665
903
|
});
|
|
@@ -680,6 +918,7 @@ describe("handleSetupAccountPost", () => {
|
|
|
680
918
|
db,
|
|
681
919
|
manifestPath: h.manifestPath,
|
|
682
920
|
configDir: h.dir,
|
|
921
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
683
922
|
issuer: "https://hub.example",
|
|
684
923
|
registry: getDefaultOperationsRegistry(),
|
|
685
924
|
},
|
|
@@ -712,6 +951,7 @@ describe("handleSetupAccountPost", () => {
|
|
|
712
951
|
db,
|
|
713
952
|
manifestPath: h.manifestPath,
|
|
714
953
|
configDir: h.dir,
|
|
954
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
715
955
|
issuer: "https://hub.example",
|
|
716
956
|
registry: getDefaultOperationsRegistry(),
|
|
717
957
|
},
|
|
@@ -731,6 +971,7 @@ describe("handleSetupAccountPost", () => {
|
|
|
731
971
|
db,
|
|
732
972
|
manifestPath: h.manifestPath,
|
|
733
973
|
configDir: h.dir,
|
|
974
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
734
975
|
issuer: "https://hub.example",
|
|
735
976
|
registry: getDefaultOperationsRegistry(),
|
|
736
977
|
});
|
|
@@ -751,6 +992,7 @@ describe("handleSetupAccountPost", () => {
|
|
|
751
992
|
db,
|
|
752
993
|
manifestPath: h.manifestPath,
|
|
753
994
|
configDir: h.dir,
|
|
995
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
754
996
|
issuer: "https://hub.example",
|
|
755
997
|
registry: getDefaultOperationsRegistry(),
|
|
756
998
|
},
|
|
@@ -794,6 +1036,7 @@ describe("handleSetupVaultPost", () => {
|
|
|
794
1036
|
db,
|
|
795
1037
|
manifestPath: h.manifestPath,
|
|
796
1038
|
configDir: h.dir,
|
|
1039
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
797
1040
|
issuer: "https://hub.example",
|
|
798
1041
|
registry: getDefaultOperationsRegistry(),
|
|
799
1042
|
},
|
|
@@ -815,6 +1058,7 @@ describe("handleSetupVaultPost", () => {
|
|
|
815
1058
|
db,
|
|
816
1059
|
manifestPath: h.manifestPath,
|
|
817
1060
|
configDir: h.dir,
|
|
1061
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
818
1062
|
issuer: "https://hub.example",
|
|
819
1063
|
registry: getDefaultOperationsRegistry(),
|
|
820
1064
|
});
|
|
@@ -834,6 +1078,7 @@ describe("handleSetupVaultPost", () => {
|
|
|
834
1078
|
db,
|
|
835
1079
|
manifestPath: h.manifestPath,
|
|
836
1080
|
configDir: h.dir,
|
|
1081
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
837
1082
|
issuer: "https://hub.example",
|
|
838
1083
|
supervisor: makeSupervisor(),
|
|
839
1084
|
registry: getDefaultOperationsRegistry(),
|
|
@@ -863,6 +1108,7 @@ describe("handleSetupVaultPost", () => {
|
|
|
863
1108
|
db,
|
|
864
1109
|
manifestPath: h.manifestPath,
|
|
865
1110
|
configDir: h.dir,
|
|
1111
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
866
1112
|
issuer: "https://hub.example",
|
|
867
1113
|
registry: getDefaultOperationsRegistry(),
|
|
868
1114
|
});
|
|
@@ -887,6 +1133,7 @@ describe("handleSetupVaultPost", () => {
|
|
|
887
1133
|
db,
|
|
888
1134
|
manifestPath: h.manifestPath,
|
|
889
1135
|
configDir: h.dir,
|
|
1136
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
890
1137
|
issuer: "https://hub.example",
|
|
891
1138
|
supervisor: makeSupervisor(),
|
|
892
1139
|
registry: getDefaultOperationsRegistry(),
|
|
@@ -940,6 +1187,7 @@ describe("handleSetupVaultPost", () => {
|
|
|
940
1187
|
db,
|
|
941
1188
|
manifestPath: h.manifestPath,
|
|
942
1189
|
configDir: h.dir,
|
|
1190
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
943
1191
|
issuer: "https://hub.example",
|
|
944
1192
|
registry: getDefaultOperationsRegistry(),
|
|
945
1193
|
});
|
|
@@ -966,6 +1214,7 @@ describe("handleSetupVaultPost", () => {
|
|
|
966
1214
|
db,
|
|
967
1215
|
manifestPath: h.manifestPath,
|
|
968
1216
|
configDir: h.dir,
|
|
1217
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
969
1218
|
issuer: "https://hub.example",
|
|
970
1219
|
supervisor: makeSupervisor(),
|
|
971
1220
|
registry: getDefaultOperationsRegistry(),
|
|
@@ -1009,6 +1258,7 @@ describe("handleSetupVaultPost", () => {
|
|
|
1009
1258
|
db,
|
|
1010
1259
|
manifestPath: h.manifestPath,
|
|
1011
1260
|
configDir: h.dir,
|
|
1261
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
1012
1262
|
issuer: "https://hub.example",
|
|
1013
1263
|
registry: getDefaultOperationsRegistry(),
|
|
1014
1264
|
});
|
|
@@ -1034,6 +1284,7 @@ describe("handleSetupVaultPost", () => {
|
|
|
1034
1284
|
db,
|
|
1035
1285
|
manifestPath: h.manifestPath,
|
|
1036
1286
|
configDir: h.dir,
|
|
1287
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
1037
1288
|
issuer: "https://hub.example",
|
|
1038
1289
|
supervisor: makeSupervisor(),
|
|
1039
1290
|
registry: getDefaultOperationsRegistry(),
|
|
@@ -1070,6 +1321,7 @@ describe("handleSetupVaultPost", () => {
|
|
|
1070
1321
|
db,
|
|
1071
1322
|
manifestPath: h.manifestPath,
|
|
1072
1323
|
configDir: h.dir,
|
|
1324
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
1073
1325
|
issuer: "https://hub.example",
|
|
1074
1326
|
registry: getDefaultOperationsRegistry(),
|
|
1075
1327
|
});
|
|
@@ -1099,6 +1351,7 @@ describe("handleSetupVaultPost", () => {
|
|
|
1099
1351
|
db,
|
|
1100
1352
|
manifestPath: h.manifestPath,
|
|
1101
1353
|
configDir: h.dir,
|
|
1354
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
1102
1355
|
issuer: "https://hub.example",
|
|
1103
1356
|
supervisor,
|
|
1104
1357
|
registry: getDefaultOperationsRegistry(),
|
|
@@ -1153,6 +1406,7 @@ describe("handleSetupVaultPost", () => {
|
|
|
1153
1406
|
db,
|
|
1154
1407
|
manifestPath: h.manifestPath,
|
|
1155
1408
|
configDir: h.dir,
|
|
1409
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
1156
1410
|
issuer: "https://hub.example",
|
|
1157
1411
|
registry: getDefaultOperationsRegistry(),
|
|
1158
1412
|
});
|
|
@@ -1178,6 +1432,7 @@ describe("handleSetupVaultPost", () => {
|
|
|
1178
1432
|
db,
|
|
1179
1433
|
manifestPath: h.manifestPath,
|
|
1180
1434
|
configDir: h.dir,
|
|
1435
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
1181
1436
|
issuer: "https://hub.example",
|
|
1182
1437
|
supervisor: makeSupervisor(),
|
|
1183
1438
|
registry: getDefaultOperationsRegistry(),
|
|
@@ -1432,6 +1687,7 @@ describe("handleSetupExposePost", () => {
|
|
|
1432
1687
|
db,
|
|
1433
1688
|
manifestPath: h.manifestPath,
|
|
1434
1689
|
configDir: h.dir,
|
|
1690
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
1435
1691
|
issuer: "https://hub.example",
|
|
1436
1692
|
registry: getDefaultOperationsRegistry(),
|
|
1437
1693
|
});
|
|
@@ -1460,6 +1716,7 @@ describe("handleSetupExposePost", () => {
|
|
|
1460
1716
|
db,
|
|
1461
1717
|
manifestPath: h.manifestPath,
|
|
1462
1718
|
configDir: h.dir,
|
|
1719
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
1463
1720
|
issuer: "https://hub.example",
|
|
1464
1721
|
registry: getDefaultOperationsRegistry(),
|
|
1465
1722
|
},
|
|
@@ -1495,6 +1752,7 @@ describe("handleSetupExposePost", () => {
|
|
|
1495
1752
|
db,
|
|
1496
1753
|
manifestPath: h.manifestPath,
|
|
1497
1754
|
configDir: h.dir,
|
|
1755
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
1498
1756
|
issuer: "https://hub.example",
|
|
1499
1757
|
registry: getDefaultOperationsRegistry(),
|
|
1500
1758
|
},
|
|
@@ -1533,6 +1791,7 @@ describe("handleSetupExposePost", () => {
|
|
|
1533
1791
|
db,
|
|
1534
1792
|
manifestPath: h.manifestPath,
|
|
1535
1793
|
configDir: h.dir,
|
|
1794
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
1536
1795
|
issuer: "https://hub.example",
|
|
1537
1796
|
registry: getDefaultOperationsRegistry(),
|
|
1538
1797
|
},
|
|
@@ -1567,6 +1826,7 @@ describe("handleSetupExposePost", () => {
|
|
|
1567
1826
|
db,
|
|
1568
1827
|
manifestPath: h.manifestPath,
|
|
1569
1828
|
configDir: h.dir,
|
|
1829
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
1570
1830
|
issuer: "https://hub.example",
|
|
1571
1831
|
registry: getDefaultOperationsRegistry(),
|
|
1572
1832
|
},
|
|
@@ -1603,6 +1863,7 @@ describe("handleSetupExposePost", () => {
|
|
|
1603
1863
|
db,
|
|
1604
1864
|
manifestPath: h.manifestPath,
|
|
1605
1865
|
configDir: h.dir,
|
|
1866
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
1606
1867
|
issuer: "https://hub.example",
|
|
1607
1868
|
registry: getDefaultOperationsRegistry(),
|
|
1608
1869
|
},
|
|
@@ -1653,6 +1914,7 @@ describe("done screen auto-minted token (hub#272 Item A)", () => {
|
|
|
1653
1914
|
db,
|
|
1654
1915
|
manifestPath: h.manifestPath,
|
|
1655
1916
|
configDir: h.dir,
|
|
1917
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
1656
1918
|
issuer: "https://hub.example",
|
|
1657
1919
|
registry: getDefaultOperationsRegistry(),
|
|
1658
1920
|
});
|
|
@@ -1681,6 +1943,7 @@ describe("done screen auto-minted token (hub#272 Item A)", () => {
|
|
|
1681
1943
|
db,
|
|
1682
1944
|
manifestPath: h.manifestPath,
|
|
1683
1945
|
configDir: h.dir,
|
|
1946
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
1684
1947
|
issuer: "https://hub.example",
|
|
1685
1948
|
registry: getDefaultOperationsRegistry(),
|
|
1686
1949
|
},
|
|
@@ -1727,6 +1990,7 @@ describe("done screen auto-minted token (hub#272 Item A)", () => {
|
|
|
1727
1990
|
db,
|
|
1728
1991
|
manifestPath: h.manifestPath,
|
|
1729
1992
|
configDir: h.dir,
|
|
1993
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
1730
1994
|
issuer: "https://hub.example",
|
|
1731
1995
|
registry: getDefaultOperationsRegistry(),
|
|
1732
1996
|
},
|
|
@@ -1792,16 +2056,21 @@ describe("done screen auto-minted token (hub#272 Item A)", () => {
|
|
|
1792
2056
|
db,
|
|
1793
2057
|
manifestPath: h.manifestPath,
|
|
1794
2058
|
configDir: h.dir,
|
|
2059
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
1795
2060
|
issuer: "https://hub.example",
|
|
1796
2061
|
registry: getDefaultOperationsRegistry(),
|
|
1797
2062
|
},
|
|
1798
2063
|
);
|
|
1799
2064
|
const html = await res.text();
|
|
1800
2065
|
expect(html).toContain("claude mcp add --transport http parachute-default");
|
|
1801
|
-
// The fallback explanatory text
|
|
1802
|
-
//
|
|
1803
|
-
//
|
|
1804
|
-
|
|
2066
|
+
// The fallback explanatory text leads with the OAuth path (no token
|
|
2067
|
+
// needed) and, for headless clients, references a hub JWT placeholder
|
|
2068
|
+
// — NOT the retired `pvt_*` format (gap #4). The `--header` flag must
|
|
2069
|
+
// also NOT be appended to the command line itself.
|
|
2070
|
+
expect(html).toContain("browser OAuth");
|
|
2071
|
+
expect(html).toContain("Bearer <token>");
|
|
2072
|
+
expect(html).not.toContain("pvt_");
|
|
2073
|
+
expect(html).toContain("parachute auth mint-token");
|
|
1805
2074
|
expect(html).toContain("/admin/tokens");
|
|
1806
2075
|
// Specifically no Copy button — that's a token-present surface.
|
|
1807
2076
|
expect(html).not.toContain('id="mcp-cmd"');
|
|
@@ -1836,6 +2105,7 @@ describe("done screen auto-minted token (hub#272 Item A)", () => {
|
|
|
1836
2105
|
db,
|
|
1837
2106
|
manifestPath: h.manifestPath,
|
|
1838
2107
|
configDir: h.dir,
|
|
2108
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
1839
2109
|
issuer: "https://hub.example",
|
|
1840
2110
|
registry: getDefaultOperationsRegistry(),
|
|
1841
2111
|
};
|
|
@@ -1892,6 +2162,7 @@ describe("done screen auto-minted token (hub#272 Item A)", () => {
|
|
|
1892
2162
|
db,
|
|
1893
2163
|
manifestPath: h.manifestPath,
|
|
1894
2164
|
configDir: h.dir,
|
|
2165
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
1895
2166
|
issuer: "https://hub.example",
|
|
1896
2167
|
registry: getDefaultOperationsRegistry(),
|
|
1897
2168
|
},
|
|
@@ -1957,6 +2228,7 @@ describe("done screen auto-minted token (hub#272 Item A)", () => {
|
|
|
1957
2228
|
db,
|
|
1958
2229
|
manifestPath: h.manifestPath,
|
|
1959
2230
|
configDir: h.dir,
|
|
2231
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
1960
2232
|
issuer: "https://hub.example",
|
|
1961
2233
|
registry: getDefaultOperationsRegistry(),
|
|
1962
2234
|
},
|
|
@@ -2015,6 +2287,7 @@ describe("done screen auto-minted token (hub#272 Item A)", () => {
|
|
|
2015
2287
|
db,
|
|
2016
2288
|
manifestPath: h.manifestPath,
|
|
2017
2289
|
configDir: h.dir,
|
|
2290
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
2018
2291
|
issuer: "https://hub.example",
|
|
2019
2292
|
registry: getDefaultOperationsRegistry(),
|
|
2020
2293
|
},
|
|
@@ -2076,6 +2349,7 @@ describe("done screen auto-minted token (hub#272 Item A)", () => {
|
|
|
2076
2349
|
db,
|
|
2077
2350
|
manifestPath: h.manifestPath,
|
|
2078
2351
|
configDir: h.dir,
|
|
2352
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
2079
2353
|
issuer: "https://hub.example",
|
|
2080
2354
|
registry: getDefaultOperationsRegistry(),
|
|
2081
2355
|
});
|
|
@@ -2139,6 +2413,7 @@ describe("done screen install tiles (hub#272 Item B)", () => {
|
|
|
2139
2413
|
db,
|
|
2140
2414
|
manifestPath: h.manifestPath,
|
|
2141
2415
|
configDir: h.dir,
|
|
2416
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
2142
2417
|
issuer: "https://hub.example",
|
|
2143
2418
|
registry: getDefaultOperationsRegistry(),
|
|
2144
2419
|
},
|
|
@@ -2204,6 +2479,7 @@ describe("done screen install tiles (hub#272 Item B)", () => {
|
|
|
2204
2479
|
db,
|
|
2205
2480
|
manifestPath: h.manifestPath,
|
|
2206
2481
|
configDir: h.dir,
|
|
2482
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
2207
2483
|
issuer: "https://hub.example",
|
|
2208
2484
|
registry: getDefaultOperationsRegistry(),
|
|
2209
2485
|
},
|
|
@@ -2255,6 +2531,7 @@ describe("done screen install tiles (hub#272 Item B)", () => {
|
|
|
2255
2531
|
db,
|
|
2256
2532
|
manifestPath: h.manifestPath,
|
|
2257
2533
|
configDir: h.dir,
|
|
2534
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
2258
2535
|
issuer: "https://hub.example",
|
|
2259
2536
|
registry: reg,
|
|
2260
2537
|
},
|
|
@@ -2294,6 +2571,7 @@ describe("done screen install tiles (hub#272 Item B)", () => {
|
|
|
2294
2571
|
db,
|
|
2295
2572
|
manifestPath: h.manifestPath,
|
|
2296
2573
|
configDir: h.dir,
|
|
2574
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
2297
2575
|
issuer: "https://hub.example",
|
|
2298
2576
|
registry: getDefaultOperationsRegistry(),
|
|
2299
2577
|
});
|
|
@@ -2317,6 +2595,7 @@ describe("done screen install tiles (hub#272 Item B)", () => {
|
|
|
2317
2595
|
db,
|
|
2318
2596
|
manifestPath: h.manifestPath,
|
|
2319
2597
|
configDir: h.dir,
|
|
2598
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
2320
2599
|
issuer: "https://hub.example",
|
|
2321
2600
|
supervisor: makeSupervisor(),
|
|
2322
2601
|
registry: getDefaultOperationsRegistry(),
|
|
@@ -2345,6 +2624,7 @@ describe("done screen install tiles (hub#272 Item B)", () => {
|
|
|
2345
2624
|
db,
|
|
2346
2625
|
manifestPath: h.manifestPath,
|
|
2347
2626
|
configDir: h.dir,
|
|
2627
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
2348
2628
|
issuer: "https://hub.example",
|
|
2349
2629
|
registry: getDefaultOperationsRegistry(),
|
|
2350
2630
|
});
|
|
@@ -2363,6 +2643,7 @@ describe("done screen install tiles (hub#272 Item B)", () => {
|
|
|
2363
2643
|
db,
|
|
2364
2644
|
manifestPath: h.manifestPath,
|
|
2365
2645
|
configDir: h.dir,
|
|
2646
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
2366
2647
|
issuer: "https://hub.example",
|
|
2367
2648
|
supervisor: makeSupervisor(),
|
|
2368
2649
|
registry: getDefaultOperationsRegistry(),
|
|
@@ -2390,6 +2671,7 @@ describe("done screen install tiles (hub#272 Item B)", () => {
|
|
|
2390
2671
|
db,
|
|
2391
2672
|
manifestPath: h.manifestPath,
|
|
2392
2673
|
configDir: h.dir,
|
|
2674
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
2393
2675
|
issuer: "https://hub.example",
|
|
2394
2676
|
supervisor: makeSupervisor(),
|
|
2395
2677
|
registry: getDefaultOperationsRegistry(),
|
|
@@ -2411,6 +2693,7 @@ describe("done screen install tiles (hub#272 Item B)", () => {
|
|
|
2411
2693
|
db,
|
|
2412
2694
|
manifestPath: h.manifestPath,
|
|
2413
2695
|
configDir: h.dir,
|
|
2696
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
2414
2697
|
issuer: "https://hub.example",
|
|
2415
2698
|
registry: getDefaultOperationsRegistry(),
|
|
2416
2699
|
});
|
|
@@ -2429,6 +2712,7 @@ describe("done screen install tiles (hub#272 Item B)", () => {
|
|
|
2429
2712
|
db,
|
|
2430
2713
|
manifestPath: h.manifestPath,
|
|
2431
2714
|
configDir: h.dir,
|
|
2715
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
2432
2716
|
issuer: "https://hub.example",
|
|
2433
2717
|
supervisor: makeSupervisor(),
|
|
2434
2718
|
registry: getDefaultOperationsRegistry(),
|
|
@@ -2457,6 +2741,7 @@ describe("done screen install tiles (hub#272 Item B)", () => {
|
|
|
2457
2741
|
db,
|
|
2458
2742
|
manifestPath: h.manifestPath,
|
|
2459
2743
|
configDir: h.dir,
|
|
2744
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
2460
2745
|
issuer: "https://hub.example",
|
|
2461
2746
|
registry: getDefaultOperationsRegistry(),
|
|
2462
2747
|
},
|
|
@@ -2490,6 +2775,7 @@ describe("typed vault name (hub#267)", () => {
|
|
|
2490
2775
|
db,
|
|
2491
2776
|
manifestPath: h.manifestPath,
|
|
2492
2777
|
configDir: h.dir,
|
|
2778
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
2493
2779
|
issuer: "https://hub.example",
|
|
2494
2780
|
registry: getDefaultOperationsRegistry(),
|
|
2495
2781
|
});
|
|
@@ -2532,6 +2818,7 @@ describe("typed vault name (hub#267)", () => {
|
|
|
2532
2818
|
db,
|
|
2533
2819
|
manifestPath: h.manifestPath,
|
|
2534
2820
|
configDir: h.dir,
|
|
2821
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
2535
2822
|
issuer: "https://hub.example",
|
|
2536
2823
|
supervisor,
|
|
2537
2824
|
registry: getDefaultOperationsRegistry(),
|
|
@@ -2565,6 +2852,7 @@ describe("typed vault name (hub#267)", () => {
|
|
|
2565
2852
|
db,
|
|
2566
2853
|
manifestPath: h.manifestPath,
|
|
2567
2854
|
configDir: h.dir,
|
|
2855
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
2568
2856
|
issuer: "https://hub.example",
|
|
2569
2857
|
registry: getDefaultOperationsRegistry(),
|
|
2570
2858
|
});
|
|
@@ -2585,6 +2873,7 @@ describe("typed vault name (hub#267)", () => {
|
|
|
2585
2873
|
db,
|
|
2586
2874
|
manifestPath: h.manifestPath,
|
|
2587
2875
|
configDir: h.dir,
|
|
2876
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
2588
2877
|
issuer: "https://hub.example",
|
|
2589
2878
|
supervisor: makeSupervisor(),
|
|
2590
2879
|
registry: getDefaultOperationsRegistry(),
|
|
@@ -2610,6 +2899,7 @@ describe("typed vault name (hub#267)", () => {
|
|
|
2610
2899
|
db,
|
|
2611
2900
|
manifestPath: h.manifestPath,
|
|
2612
2901
|
configDir: h.dir,
|
|
2902
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
2613
2903
|
issuer: "https://hub.example",
|
|
2614
2904
|
registry: getDefaultOperationsRegistry(),
|
|
2615
2905
|
});
|
|
@@ -2650,6 +2940,7 @@ describe("typed vault name (hub#267)", () => {
|
|
|
2650
2940
|
db,
|
|
2651
2941
|
manifestPath: h.manifestPath,
|
|
2652
2942
|
configDir: h.dir,
|
|
2943
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
2653
2944
|
issuer: "https://hub.example",
|
|
2654
2945
|
supervisor,
|
|
2655
2946
|
registry: getDefaultOperationsRegistry(),
|
|
@@ -2712,6 +3003,7 @@ describe("typed vault name (hub#267)", () => {
|
|
|
2712
3003
|
db,
|
|
2713
3004
|
manifestPath: h.manifestPath,
|
|
2714
3005
|
configDir: h.dir,
|
|
3006
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
2715
3007
|
issuer: "https://hub.example",
|
|
2716
3008
|
registry: getDefaultOperationsRegistry(),
|
|
2717
3009
|
},
|
|
@@ -2763,6 +3055,7 @@ describe("typed vault name (hub#267)", () => {
|
|
|
2763
3055
|
db,
|
|
2764
3056
|
manifestPath: h.manifestPath,
|
|
2765
3057
|
configDir: h.dir,
|
|
3058
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
2766
3059
|
issuer: "https://hub.example",
|
|
2767
3060
|
registry: getDefaultOperationsRegistry(),
|
|
2768
3061
|
},
|
|
@@ -2814,6 +3107,7 @@ describe("typed vault name (hub#267)", () => {
|
|
|
2814
3107
|
db,
|
|
2815
3108
|
manifestPath: h.manifestPath,
|
|
2816
3109
|
configDir: h.dir,
|
|
3110
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
2817
3111
|
issuer: "https://hub.example",
|
|
2818
3112
|
registry: getDefaultOperationsRegistry(),
|
|
2819
3113
|
},
|
|
@@ -2884,6 +3178,7 @@ describe("bootstrap token gate (handleSetupAccountPost)", () => {
|
|
|
2884
3178
|
db,
|
|
2885
3179
|
manifestPath: h.manifestPath,
|
|
2886
3180
|
configDir: h.dir,
|
|
3181
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
2887
3182
|
issuer: "https://hub.example",
|
|
2888
3183
|
registry: getDefaultOperationsRegistry(),
|
|
2889
3184
|
});
|
|
@@ -2908,6 +3203,7 @@ describe("bootstrap token gate (handleSetupAccountPost)", () => {
|
|
|
2908
3203
|
db,
|
|
2909
3204
|
manifestPath: h.manifestPath,
|
|
2910
3205
|
configDir: h.dir,
|
|
3206
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
2911
3207
|
issuer: "https://hub.example",
|
|
2912
3208
|
registry: getDefaultOperationsRegistry(),
|
|
2913
3209
|
});
|
|
@@ -2933,6 +3229,7 @@ describe("bootstrap token gate (handleSetupAccountPost)", () => {
|
|
|
2933
3229
|
db,
|
|
2934
3230
|
manifestPath: h.manifestPath,
|
|
2935
3231
|
configDir: h.dir,
|
|
3232
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
2936
3233
|
issuer: "https://hub.example",
|
|
2937
3234
|
registry: getDefaultOperationsRegistry(),
|
|
2938
3235
|
});
|
|
@@ -2954,6 +3251,7 @@ describe("bootstrap token gate (handleSetupAccountPost)", () => {
|
|
|
2954
3251
|
db,
|
|
2955
3252
|
manifestPath: h.manifestPath,
|
|
2956
3253
|
configDir: h.dir,
|
|
3254
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
2957
3255
|
issuer: "https://hub.example",
|
|
2958
3256
|
registry: getDefaultOperationsRegistry(),
|
|
2959
3257
|
},
|
|
@@ -2976,6 +3274,7 @@ describe("bootstrap token gate (handleSetupAccountPost)", () => {
|
|
|
2976
3274
|
db,
|
|
2977
3275
|
manifestPath: h.manifestPath,
|
|
2978
3276
|
configDir: h.dir,
|
|
3277
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
2979
3278
|
issuer: "https://hub.example",
|
|
2980
3279
|
registry: getDefaultOperationsRegistry(),
|
|
2981
3280
|
});
|
|
@@ -2997,6 +3296,7 @@ describe("bootstrap token gate (handleSetupAccountPost)", () => {
|
|
|
2997
3296
|
db,
|
|
2998
3297
|
manifestPath: h.manifestPath,
|
|
2999
3298
|
configDir: h.dir,
|
|
3299
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
3000
3300
|
issuer: "https://hub.example",
|
|
3001
3301
|
registry: getDefaultOperationsRegistry(),
|
|
3002
3302
|
},
|
|
@@ -3026,6 +3326,7 @@ describe("bootstrap token gate (handleSetupAccountPost)", () => {
|
|
|
3026
3326
|
db,
|
|
3027
3327
|
manifestPath: h.manifestPath,
|
|
3028
3328
|
configDir: h.dir,
|
|
3329
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
3029
3330
|
issuer: "https://hub.example",
|
|
3030
3331
|
registry: getDefaultOperationsRegistry(),
|
|
3031
3332
|
});
|
|
@@ -3047,6 +3348,7 @@ describe("bootstrap token gate (handleSetupAccountPost)", () => {
|
|
|
3047
3348
|
db,
|
|
3048
3349
|
manifestPath: h.manifestPath,
|
|
3049
3350
|
configDir: h.dir,
|
|
3351
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
3050
3352
|
issuer: "https://hub.example",
|
|
3051
3353
|
registry: getDefaultOperationsRegistry(),
|
|
3052
3354
|
},
|
|
@@ -3074,6 +3376,7 @@ describe("bootstrap token gate (handleSetupAccountPost)", () => {
|
|
|
3074
3376
|
db,
|
|
3075
3377
|
manifestPath: h.manifestPath,
|
|
3076
3378
|
configDir: h.dir,
|
|
3379
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
3077
3380
|
issuer: "https://hub.example",
|
|
3078
3381
|
registry: getDefaultOperationsRegistry(),
|
|
3079
3382
|
});
|
|
@@ -3095,6 +3398,7 @@ describe("bootstrap token gate (handleSetupAccountPost)", () => {
|
|
|
3095
3398
|
db,
|
|
3096
3399
|
manifestPath: h.manifestPath,
|
|
3097
3400
|
configDir: h.dir,
|
|
3401
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
3098
3402
|
issuer: "https://hub.example",
|
|
3099
3403
|
registry: getDefaultOperationsRegistry(),
|
|
3100
3404
|
},
|
|
@@ -3120,6 +3424,7 @@ describe("bootstrap token gate (handleSetupAccountPost)", () => {
|
|
|
3120
3424
|
db,
|
|
3121
3425
|
manifestPath: h.manifestPath,
|
|
3122
3426
|
configDir: h.dir,
|
|
3427
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
3123
3428
|
issuer: "https://hub.example",
|
|
3124
3429
|
registry: getDefaultOperationsRegistry(),
|
|
3125
3430
|
});
|
|
@@ -3140,6 +3445,7 @@ describe("bootstrap token gate (handleSetupAccountPost)", () => {
|
|
|
3140
3445
|
db,
|
|
3141
3446
|
manifestPath: h.manifestPath,
|
|
3142
3447
|
configDir: h.dir,
|
|
3448
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
3143
3449
|
issuer: "https://hub.example",
|
|
3144
3450
|
registry: getDefaultOperationsRegistry(),
|
|
3145
3451
|
},
|
|
@@ -3186,6 +3492,7 @@ describe("bootstrap token gate (handleSetupAccountPost)", () => {
|
|
|
3186
3492
|
db,
|
|
3187
3493
|
manifestPath: h.manifestPath,
|
|
3188
3494
|
configDir: h.dir,
|
|
3495
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
3189
3496
|
issuer: "https://hub.example",
|
|
3190
3497
|
registry: getDefaultOperationsRegistry(),
|
|
3191
3498
|
});
|
|
@@ -3207,6 +3514,7 @@ describe("bootstrap token gate (handleSetupAccountPost)", () => {
|
|
|
3207
3514
|
db,
|
|
3208
3515
|
manifestPath: h.manifestPath,
|
|
3209
3516
|
configDir: h.dir,
|
|
3517
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
3210
3518
|
issuer: "https://hub.example",
|
|
3211
3519
|
registry: getDefaultOperationsRegistry(),
|
|
3212
3520
|
};
|
|
@@ -3290,6 +3598,7 @@ describe("done screen — 'Start using your vault' tile (hub#342)", () => {
|
|
|
3290
3598
|
db,
|
|
3291
3599
|
manifestPath: h.manifestPath,
|
|
3292
3600
|
configDir: h.dir,
|
|
3601
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
3293
3602
|
issuer: "https://hub.example",
|
|
3294
3603
|
registry: getDefaultOperationsRegistry(),
|
|
3295
3604
|
},
|
|
@@ -3353,6 +3662,7 @@ describe("done screen — 'Start using your vault' tile (hub#342)", () => {
|
|
|
3353
3662
|
db,
|
|
3354
3663
|
manifestPath: h.manifestPath,
|
|
3355
3664
|
configDir: h.dir,
|
|
3665
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
3356
3666
|
issuer: "https://hub.example",
|
|
3357
3667
|
registry: getDefaultOperationsRegistry(),
|
|
3358
3668
|
},
|
|
@@ -3411,6 +3721,7 @@ describe("done screen — 'Start using your vault' tile (hub#342)", () => {
|
|
|
3411
3721
|
db,
|
|
3412
3722
|
manifestPath: h.manifestPath,
|
|
3413
3723
|
configDir: h.dir,
|
|
3724
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
3414
3725
|
issuer: "https://hub.example",
|
|
3415
3726
|
registry: reg,
|
|
3416
3727
|
},
|
|
@@ -3470,6 +3781,7 @@ describe("done screen — 'Start using your vault' tile (hub#342)", () => {
|
|
|
3470
3781
|
db,
|
|
3471
3782
|
manifestPath: h.manifestPath,
|
|
3472
3783
|
configDir: h.dir,
|
|
3784
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
3473
3785
|
issuer: "https://hub.example",
|
|
3474
3786
|
registry: getDefaultOperationsRegistry(),
|
|
3475
3787
|
},
|
|
@@ -3497,6 +3809,7 @@ describe("done screen — 'Start using your vault' tile (hub#342)", () => {
|
|
|
3497
3809
|
db,
|
|
3498
3810
|
manifestPath: h.manifestPath,
|
|
3499
3811
|
configDir: h.dir,
|
|
3812
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
3500
3813
|
issuer: "https://hub.example",
|
|
3501
3814
|
registry: getDefaultOperationsRegistry(),
|
|
3502
3815
|
});
|
|
@@ -3593,6 +3906,7 @@ describe("setup-wizard JSON surface (hub#168 Cuts 2/3)", () => {
|
|
|
3593
3906
|
db,
|
|
3594
3907
|
manifestPath: h.manifestPath,
|
|
3595
3908
|
configDir: h.dir,
|
|
3909
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
3596
3910
|
issuer: "http://127.0.0.1:1939",
|
|
3597
3911
|
registry: getDefaultOperationsRegistry(),
|
|
3598
3912
|
};
|
|
@@ -3618,6 +3932,7 @@ describe("setup-wizard JSON surface (hub#168 Cuts 2/3)", () => {
|
|
|
3618
3932
|
db,
|
|
3619
3933
|
manifestPath: h.manifestPath,
|
|
3620
3934
|
configDir: h.dir,
|
|
3935
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
3621
3936
|
issuer: "http://127.0.0.1:1939",
|
|
3622
3937
|
registry: getDefaultOperationsRegistry(),
|
|
3623
3938
|
supervisor,
|
|
@@ -3657,7 +3972,11 @@ describe("setup-wizard JSON surface (hub#168 Cuts 2/3)", () => {
|
|
|
3657
3972
|
// The skip flag is persisted.
|
|
3658
3973
|
expect(getSetting(db, "setup_vault_skipped")).toBe("true");
|
|
3659
3974
|
// deriveWizardState advances past the vault step.
|
|
3660
|
-
const s = deriveWizardState({
|
|
3975
|
+
const s = deriveWizardState({
|
|
3976
|
+
db,
|
|
3977
|
+
manifestPath: h.manifestPath,
|
|
3978
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
3979
|
+
});
|
|
3661
3980
|
expect(s.hasVault).toBe(true);
|
|
3662
3981
|
expect(s.step).toBe("expose");
|
|
3663
3982
|
} finally {
|
|
@@ -3674,6 +3993,7 @@ describe("setup-wizard JSON surface (hub#168 Cuts 2/3)", () => {
|
|
|
3674
3993
|
db,
|
|
3675
3994
|
manifestPath: h.manifestPath,
|
|
3676
3995
|
configDir: h.dir,
|
|
3996
|
+
readExposeStateFn: h.readExposeStateFn,
|
|
3677
3997
|
issuer: "http://127.0.0.1:1939",
|
|
3678
3998
|
registry: getDefaultOperationsRegistry(),
|
|
3679
3999
|
supervisor,
|
|
@@ -3767,10 +4087,10 @@ describe("setup-wizard JSON surface (hub#168 Cuts 2/3)", () => {
|
|
|
3767
4087
|
let capturedBody: unknown;
|
|
3768
4088
|
const stubFetch = (async (_: string | URL | Request, init?: RequestInit) => {
|
|
3769
4089
|
capturedBody = JSON.parse((init?.body as string) ?? "{}");
|
|
3770
|
-
return new Response(
|
|
3771
|
-
|
|
3772
|
-
|
|
3773
|
-
);
|
|
4090
|
+
return new Response(JSON.stringify({ notes_imported: 1 }), {
|
|
4091
|
+
status: 200,
|
|
4092
|
+
headers: { "content-type": "application/json" },
|
|
4093
|
+
});
|
|
3774
4094
|
}) as typeof fetch;
|
|
3775
4095
|
|
|
3776
4096
|
await postVaultImportImpl({
|