@openparachute/hub 0.5.13 → 0.5.14-rc.10

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 (101) hide show
  1. package/README.md +109 -15
  2. package/package.json +2 -2
  3. package/src/__tests__/account-home-ui.test.ts +205 -0
  4. package/src/__tests__/admin-handlers.test.ts +74 -0
  5. package/src/__tests__/admin-host-admin-token.test.ts +62 -0
  6. package/src/__tests__/admin-vault-admin-token.test.ts +44 -0
  7. package/src/__tests__/admin-vaults.test.ts +70 -4
  8. package/src/__tests__/api-account.test.ts +191 -1
  9. package/src/__tests__/api-mint-token.test.ts +682 -3
  10. package/src/__tests__/api-modules-config.test.ts +16 -10
  11. package/src/__tests__/api-modules-ops.test.ts +97 -0
  12. package/src/__tests__/api-modules.test.ts +100 -83
  13. package/src/__tests__/api-ready.test.ts +135 -0
  14. package/src/__tests__/api-revoke-token.test.ts +384 -0
  15. package/src/__tests__/api-users.test.ts +390 -13
  16. package/src/__tests__/chrome-strip.test.ts +15 -15
  17. package/src/__tests__/cli.test.ts +7 -5
  18. package/src/__tests__/cloudflare-detect.test.ts +60 -5
  19. package/src/__tests__/expose-auth-preflight.test.ts +58 -50
  20. package/src/__tests__/expose-cloudflare.test.ts +114 -3
  21. package/src/__tests__/expose-interactive.test.ts +10 -4
  22. package/src/__tests__/expose-public-auto.test.ts +5 -1
  23. package/src/__tests__/expose.test.ts +49 -1
  24. package/src/__tests__/hub-db.test.ts +194 -29
  25. package/src/__tests__/hub-server.test.ts +322 -33
  26. package/src/__tests__/hub.test.ts +11 -0
  27. package/src/__tests__/init.test.ts +827 -0
  28. package/src/__tests__/lifecycle.test.ts +33 -1
  29. package/src/__tests__/migrate.test.ts +433 -51
  30. package/src/__tests__/notes-redirect.test.ts +20 -20
  31. package/src/__tests__/oauth-handlers.test.ts +1060 -29
  32. package/src/__tests__/oauth-ui.test.ts +12 -1
  33. package/src/__tests__/proxy-error-ui.test.ts +212 -0
  34. package/src/__tests__/proxy-state.test.ts +192 -0
  35. package/src/__tests__/resource-binding.test.ts +97 -0
  36. package/src/__tests__/scope-explanations.test.ts +36 -0
  37. package/src/__tests__/serve.test.ts +9 -9
  38. package/src/__tests__/services-manifest.test.ts +40 -40
  39. package/src/__tests__/setup-wizard.test.ts +1114 -66
  40. package/src/__tests__/setup.test.ts +1 -1
  41. package/src/__tests__/status.test.ts +39 -0
  42. package/src/__tests__/users.test.ts +396 -9
  43. package/src/__tests__/vault-auth-status.test.ts +271 -11
  44. package/src/__tests__/vault-hub-origin-env.test.ts +126 -0
  45. package/src/__tests__/well-known.test.ts +9 -9
  46. package/src/__tests__/wizard.test.ts +372 -0
  47. package/src/account-home-ui.ts +547 -0
  48. package/src/admin-handlers.ts +49 -17
  49. package/src/admin-host-admin-token.ts +25 -0
  50. package/src/admin-login-ui.ts +4 -4
  51. package/src/admin-vault-admin-token.ts +17 -0
  52. package/src/admin-vaults.ts +48 -15
  53. package/src/api-account.ts +72 -6
  54. package/src/api-mint-token.ts +132 -24
  55. package/src/api-modules-ops.ts +52 -16
  56. package/src/api-modules.ts +31 -14
  57. package/src/api-ready.ts +102 -0
  58. package/src/api-revoke-token.ts +107 -21
  59. package/src/api-users.ts +497 -58
  60. package/src/bun-link.ts +55 -0
  61. package/src/chrome-strip.ts +6 -6
  62. package/src/cli.ts +93 -24
  63. package/src/cloudflare/config.ts +10 -4
  64. package/src/cloudflare/detect.ts +73 -6
  65. package/src/commands/expose-auth-preflight.ts +55 -63
  66. package/src/commands/expose-cloudflare.ts +114 -10
  67. package/src/commands/expose-interactive.ts +10 -11
  68. package/src/commands/expose-public-auto.ts +6 -4
  69. package/src/commands/expose.ts +8 -0
  70. package/src/commands/init.ts +563 -0
  71. package/src/commands/install.ts +41 -23
  72. package/src/commands/lifecycle.ts +12 -0
  73. package/src/commands/migrate.ts +293 -41
  74. package/src/commands/status.ts +10 -1
  75. package/src/commands/wizard.ts +843 -0
  76. package/src/env-file.ts +10 -0
  77. package/src/help.ts +157 -17
  78. package/src/hub-db.ts +42 -0
  79. package/src/hub-server.ts +136 -23
  80. package/src/hub-settings.ts +13 -2
  81. package/src/hub.ts +16 -9
  82. package/src/notes-redirect.ts +5 -5
  83. package/src/oauth-handlers.ts +342 -173
  84. package/src/oauth-ui.ts +28 -2
  85. package/src/proxy-error-ui.ts +506 -0
  86. package/src/proxy-state.ts +131 -0
  87. package/src/resource-binding.ts +134 -0
  88. package/src/scope-attenuation.ts +85 -0
  89. package/src/scope-explanations.ts +94 -5
  90. package/src/service-spec.ts +39 -18
  91. package/src/setup-wizard.ts +1173 -117
  92. package/src/users.ts +307 -29
  93. package/src/vault/auth-status.ts +152 -25
  94. package/src/vault-hub-origin-env.ts +100 -0
  95. package/web/ui/dist/assets/index-2SSK7JbM.js +61 -0
  96. package/web/ui/dist/assets/index-B28SdMSz.css +1 -0
  97. package/web/ui/dist/index.html +2 -2
  98. package/src/__tests__/vault-tokens-create-interactive.test.ts +0 -183
  99. package/src/commands/vault-tokens-create-interactive.ts +0 -143
  100. package/web/ui/dist/assets/index-7DtAXz7y.css +0 -1
  101. package/web/ui/dist/assets/index-Dzrbe6EP.js +0 -61
package/src/hub.ts CHANGED
@@ -91,8 +91,15 @@ function renderSignedIn(displayName: string, csrfToken: string): string {
91
91
  // Inline POST form so sign-out works without JS. Submit button is
92
92
  // styled as a text link via `.auth-signout` so the visual weight
93
93
  // matches the surrounding "Signed in as <name>" text.
94
+ //
95
+ // The "Account" link is the single breadcrumb to `/account/` — the
96
+ // self-service home where any signed-in user (admin or invited
97
+ // member) can change their password, see their vault, and sign out.
98
+ // Without it, a friend who's been handed credentials has no way to
99
+ // discover the change-password surface after the first-login prompt.
94
100
  return `<div class="auth-indicator">
95
101
  <span class="muted">Signed in as <strong>${escapeHtml(displayName)}</strong></span>
102
+ <a href="/account/" class="auth-account">Account</a>
96
103
  <form method="POST" action="/logout" class="auth-signout-form">
97
104
  <input type="hidden" name="${CSRF_FIELD_NAME}" value="${escapeAttr(csrfToken)}" />
98
105
  <button type="submit" class="auth-signout">Sign out</button>
@@ -203,7 +210,7 @@ const HTML_TEMPLATE = `<!doctype html>
203
210
  margin: 0;
204
211
  display: inline;
205
212
  }
206
- .auth-signout, .auth-signin {
213
+ .auth-signout, .auth-signin, .auth-account {
207
214
  background: none;
208
215
  border: none;
209
216
  padding: 0;
@@ -214,10 +221,10 @@ const HTML_TEMPLATE = `<!doctype html>
214
221
  text-decoration-thickness: 1px;
215
222
  text-underline-offset: 2px;
216
223
  }
217
- .auth-signout:hover, .auth-signin:hover {
224
+ .auth-signout:hover, .auth-signin:hover, .auth-account:hover {
218
225
  color: var(--accent-hover);
219
226
  }
220
- a.auth-signin {
227
+ a.auth-signin, a.auth-account {
221
228
  /* Anchor needs explicit reset since the a element has its own
222
229
  color/decoration. */
223
230
  border-bottom: none;
@@ -471,9 +478,9 @@ const HTML_TEMPLATE = `<!doctype html>
471
478
  * Render the "Get started" section (hub#342) above the Services grid.
472
479
  *
473
480
  * One hardcoded target, conditional on its prerequisite being installed:
474
- * - "Open Notes" → /app/notes/ (requires parachute-app installed;
475
- * App auto-bootstraps Notes-as-UI per parachute-app §17, so the
476
- * mere presence of App means /app/notes/ is live)
481
+ * - "Open Notes" → /surface/notes/ (requires parachute-surface installed;
482
+ * Surface auto-bootstraps Notes-as-UI per parachute-surface §17, so the
483
+ * mere presence of Surface means /surface/notes/ is live)
477
484
  *
478
485
  * The earlier "Browse Vault" tile retired in workstream C (2026-05-25)
479
486
  * once vault declared uiUrl in its module.json (per patterns#96). With
@@ -500,12 +507,12 @@ const HTML_TEMPLATE = `<!doctype html>
500
507
  function renderGetStarted(services) {
501
508
  if (!getStartedGrid || !getStartedSection) return;
502
509
  const tiles = [];
503
- const hasApp = services.some((s) => s && s.name === 'parachute-app');
504
- if (hasApp) {
510
+ const hasSurface = services.some((s) => s && s.name === 'parachute-surface');
511
+ if (hasSurface) {
505
512
  tiles.push({
506
513
  title: 'Open Notes',
507
514
  desc: 'Browse + capture in the Notes app — reads from your vault.',
508
- href: '/app/notes/',
515
+ href: '/surface/notes/',
509
516
  });
510
517
  }
511
518
  if (tiles.length === 0) {
@@ -2,9 +2,9 @@
2
2
  * Notes-as-app migration Phase 2 (parachute-app design doc §16).
3
3
  *
4
4
  * When parachute-app ships and Notes installs as `parachute-app add
5
- * @openparachute/notes-ui --name notes --path /app/notes`, operators with
5
+ * @openparachute/notes-ui --name notes --path /surface/notes`, operators with
6
6
  * existing `/notes/*` bookmarks need a transparent bridge. The hub serves a
7
- * 301 redirect from `/notes/*` → `/app/notes/*` so:
7
+ * 301 redirect from `/notes/*` → `/surface/notes/*` so:
8
8
  *
9
9
  * - cached operator URLs (notes PWA install banners, browser history,
10
10
  * in-vault links) keep working
@@ -44,14 +44,14 @@ export function isLegacyNotesPath(pathname: string): boolean {
44
44
  * string. The query is preserved verbatim; the fragment isn't visible
45
45
  * server-side (clients reassemble it after following the redirect).
46
46
  *
47
- * The transform is purely path-rewrite — `/notes` → `/app/notes`, `/notes/`
48
- * → `/app/notes/`, `/notes/foo/bar` → `/app/notes/foo/bar`.
47
+ * The transform is purely path-rewrite — `/notes` → `/surface/notes`, `/notes/`
48
+ * → `/surface/notes/`, `/notes/foo/bar` → `/surface/notes/foo/bar`.
49
49
  */
50
50
  export function buildNotesRedirectTarget(pathname: string, search: string): string {
51
51
  // Slice off the leading "/notes" — what remains is either "" (bare /notes),
52
52
  // "/" (trailing slash), or "/<rest>" (sub-path).
53
53
  const tail = pathname.slice("/notes".length);
54
- return `/app/notes${tail}${search}`;
54
+ return `/surface/notes${tail}${search}`;
55
55
  }
56
56
 
57
57
  /**