@openparachute/hub 0.7.5 → 0.7.6-rc.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.
- package/package.json +1 -1
- package/src/__tests__/admin-module-token.test.ts +40 -3
- package/src/__tests__/api-modules-ops.test.ts +8 -3
- package/src/__tests__/api-modules.test.ts +26 -18
- package/src/__tests__/connections-store.test.ts +84 -0
- package/src/__tests__/git-notify.test.ts +29 -1
- package/src/__tests__/grants-store.test.ts +33 -1
- package/src/__tests__/install.test.ts +28 -0
- package/src/__tests__/serve-boot.test.ts +60 -0
- package/src/__tests__/service-spec-discovery.test.ts +32 -9
- package/src/__tests__/setup.test.ts +64 -16
- package/src/__tests__/stale-module-units.test.ts +1 -1
- package/src/admin-connections.ts +5 -1
- package/src/admin-module-token.ts +2 -2
- package/src/api-modules-ops.ts +3 -3
- package/src/api-modules.ts +13 -13
- package/src/commands/install.ts +29 -3
- package/src/commands/migrate.ts +5 -0
- package/src/commands/setup.ts +10 -9
- package/src/connections-store.ts +15 -2
- package/src/git-notify.ts +34 -5
- package/src/grants-store.ts +15 -2
- package/src/help.ts +3 -3
- package/src/install-source.ts +1 -1
- package/src/service-spec.ts +36 -44
- package/src/services-manifest.ts +1 -1
- package/src/stale-module-units.ts +2 -2
- package/src/well-known.ts +3 -3
package/src/service-spec.ts
CHANGED
|
@@ -322,7 +322,7 @@ const NOTES_FALLBACK: FirstPartyFallback = {
|
|
|
322
322
|
* Indexed by short name (the `parachute install <X>` token).
|
|
323
323
|
*
|
|
324
324
|
* Only notes remains — see the block comment above for the rationale
|
|
325
|
-
* (vault/scribe/
|
|
325
|
+
* (vault/scribe/agent now self-register and ship their own
|
|
326
326
|
* module.json). Other code paths consult both this table AND `KNOWN_MODULES`
|
|
327
327
|
* (which carries the post-self-register-retirement entries) via the helpers
|
|
328
328
|
* in this file (`shortNameForManifest`, `knownServices`, …).
|
|
@@ -437,27 +437,17 @@ export const KNOWN_MODULES: Record<string, KnownModule> = {
|
|
|
437
437
|
],
|
|
438
438
|
},
|
|
439
439
|
},
|
|
440
|
-
runner:
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
extras: {
|
|
452
|
-
// Backward-compat startCmd — same rationale as scribe / vault above.
|
|
453
|
-
startCmd: () => ["parachute-runner", "serve"],
|
|
454
|
-
// Runner's HTTP routes (everything past `/healthz`) gate on a
|
|
455
|
-
// hub-issued JWT carrying `runner:admin` scope (see runner's
|
|
456
|
-
// `src/auth.ts`). Surfaces in `parachute status` as auth-required by
|
|
457
|
-
// default, same posture as vault.
|
|
458
|
-
hasAuth: true,
|
|
459
|
-
},
|
|
460
|
-
},
|
|
440
|
+
// NOTE (2026-07-01): `runner` was REMOVED from this registry (decision:
|
|
441
|
+
// Aaron 2026-07-01 — the module set of record is vault / hub / agent /
|
|
442
|
+
// scribe / surface). Runner is no longer offered, installable, or
|
|
443
|
+
// lifecycle-addressable by short name from the hub's bootstrap registries.
|
|
444
|
+
// Existing installs stay GRACEFUL: a legacy `parachute-runner` services.json
|
|
445
|
+
// row is handled exactly like any unknown/third-party row — `parachute
|
|
446
|
+
// status` renders it (short falls back to the row name), `parachute serve`
|
|
447
|
+
// boots it via `<installDir>/.parachute/module.json` when installDir is
|
|
448
|
+
// stamped and logs-and-skips otherwise. Deliberately NOT added to
|
|
449
|
+
// RETIRED_MODULES: that registry GC-drops rows on load, which would break
|
|
450
|
+
// routing for operators still running the runner daemon.
|
|
461
451
|
agent: {
|
|
462
452
|
short: "agent",
|
|
463
453
|
package: "@openparachute/agent",
|
|
@@ -474,7 +464,7 @@ export const KNOWN_MODULES: Record<string, KnownModule> = {
|
|
|
474
464
|
canonicalStripPrefix: true,
|
|
475
465
|
extras: {
|
|
476
466
|
// Backward-compat startCmd for rows without installDir — same rationale
|
|
477
|
-
// as scribe / vault
|
|
467
|
+
// as scribe / vault. The bare binary IS the daemon (agent's
|
|
478
468
|
// package.json bin maps `parachute-agent` → src/daemon.ts).
|
|
479
469
|
startCmd: () => ["parachute-agent"],
|
|
480
470
|
// Agent gates its endpoints behind hub-issued JWTs (agent:* scopes).
|
|
@@ -498,14 +488,14 @@ export const KNOWN_MODULES: Record<string, KnownModule> = {
|
|
|
498
488
|
canonicalHealth: "/surface/healthz",
|
|
499
489
|
canonicalStripPrefix: false,
|
|
500
490
|
extras: {
|
|
501
|
-
// Backward-compat startCmd — same rationale as scribe / vault
|
|
491
|
+
// Backward-compat startCmd — same rationale as scribe / vault
|
|
502
492
|
// above. Post-self-register, lifecycle reads module.json's startCmd via
|
|
503
493
|
// `composeKnownModuleSpec` and that path wins.
|
|
504
494
|
startCmd: () => ["parachute-surface", "serve"],
|
|
505
495
|
// Surface's admin + per-UI surfaces gate behind hub-issued JWTs (design
|
|
506
496
|
// doc §6 same-hub auto-trust + scope `surface:admin`). Surfaces in
|
|
507
|
-
// `parachute status` as auth-required by default, same posture as
|
|
508
|
-
//
|
|
497
|
+
// `parachute status` as auth-required by default, same posture as
|
|
498
|
+
// vault.
|
|
509
499
|
hasAuth: true,
|
|
510
500
|
},
|
|
511
501
|
},
|
|
@@ -646,10 +636,11 @@ export function knownServices(): string[] {
|
|
|
646
636
|
* - `experimental` — agent (legit preview; still OFFERED on a fresh install)
|
|
647
637
|
* + any unlisted third-party short.
|
|
648
638
|
* - `deprecated` — notes (notes-daemon deprecated 2026-05-22; notes-ui moved
|
|
649
|
-
* into parachute-surface)
|
|
650
|
-
*
|
|
651
|
-
*
|
|
652
|
-
*
|
|
639
|
+
* into parachute-surface). Still RESOLVABLE (discoverableShorts unchanged)
|
|
640
|
+
* and SHOWN-IF-INSTALLED so an existing operator can manage/uninstall, but
|
|
641
|
+
* NOT OFFERED on a fresh setup. `runner` used to sit here too (deprecated
|
|
642
|
+
* 2026-06-25) until its full registry removal on 2026-07-01 — see the note
|
|
643
|
+
* in KNOWN_MODULES.
|
|
653
644
|
*
|
|
654
645
|
* **Show all installed; never hide** — `focus` groups + labels; the one
|
|
655
646
|
* behavioral lever is the fresh-install OFFER, which drops `deprecated` shorts.
|
|
@@ -660,7 +651,6 @@ const FOCUS_DEFAULTS: Record<string, ModuleFocus> = {
|
|
|
660
651
|
hub: "core",
|
|
661
652
|
surface: "core",
|
|
662
653
|
agent: "experimental",
|
|
663
|
-
runner: "deprecated",
|
|
664
654
|
notes: "deprecated",
|
|
665
655
|
};
|
|
666
656
|
|
|
@@ -671,7 +661,7 @@ const FOCUS_DEFAULTS: Record<string, ModuleFocus> = {
|
|
|
671
661
|
* returns undefined — the Modules screen always has a tier to group by.
|
|
672
662
|
*
|
|
673
663
|
* Tier semantics: `core`/`experimental` are both OFFERED on a fresh install;
|
|
674
|
-
* `deprecated` (notes
|
|
664
|
+
* `deprecated` (notes) is NOT offered on a fresh setup but stays
|
|
675
665
|
* resolvable + shown-if-installed (the `isKnownModuleShort` /
|
|
676
666
|
* `discoverableShorts` resolution surface is unchanged). The fresh-install
|
|
677
667
|
* filters in `setup.ts` + `api-modules.ts` consult this tier to drop
|
|
@@ -689,14 +679,16 @@ export function focusForShort(short: string, declared?: ModuleFocus): ModuleFocu
|
|
|
689
679
|
* `CURATED_MODULES` whitelist (2026-06-09 modular-UI architecture, P2): every
|
|
690
680
|
* module the hub can resolve a package/manifest for is discoverable + installable,
|
|
691
681
|
* regardless of `focus` tier. Deduped, with FIRST_PARTY_FALLBACKS shorts first
|
|
692
|
-
* (notes) then KNOWN_MODULES (vault / scribe /
|
|
693
|
-
*
|
|
694
|
-
* `notes`
|
|
695
|
-
*
|
|
696
|
-
*
|
|
697
|
-
*
|
|
698
|
-
*
|
|
699
|
-
*
|
|
682
|
+
* (notes) then KNOWN_MODULES (vault / scribe / agent / surface).
|
|
683
|
+
*
|
|
684
|
+
* `notes` is intentionally included — still resolvable (vendored fallback)
|
|
685
|
+
* for legacy installs; it surfaces as `deprecated` (2026-06-25) and isn't
|
|
686
|
+
* OFFERED on a fresh install. The fresh-install OFFER (setup wizard + admin
|
|
687
|
+
* SPA) filters by tier (`focus !== "deprecated"`); `discoverableShorts`
|
|
688
|
+
* itself stays the full resolution surface so existing installs keep working.
|
|
689
|
+
* `runner` is NOT here anymore (registry removal 2026-07-01 — see the
|
|
690
|
+
* KNOWN_MODULES note); a legacy runner install is handled as an
|
|
691
|
+
* unknown/third-party row.
|
|
700
692
|
*/
|
|
701
693
|
export function discoverableShorts(): string[] {
|
|
702
694
|
const seen = new Set<string>();
|
|
@@ -750,7 +742,7 @@ export function canonicalPortForManifest(manifestName: string): number | undefin
|
|
|
750
742
|
* spec with embedded manifest + extras — the vendored manifest is the
|
|
751
743
|
* source of truth pre-install and the install path preserves it through.
|
|
752
744
|
*
|
|
753
|
-
* KNOWN_MODULES shorts (vault / scribe /
|
|
745
|
+
* KNOWN_MODULES shorts (vault / scribe / agent / surface — post
|
|
754
746
|
* FALLBACK retirement) return a **minimal** spec carrying `package`, `manifestName`,
|
|
755
747
|
* and the imperative `extras` fields
|
|
756
748
|
* (`init`, `hasAuth`, `urlForEntry`, `postInstallFooter`). They do NOT carry
|
|
@@ -860,7 +852,7 @@ const LEGACY_MANIFEST_ALIASES: Record<string, string> = {
|
|
|
860
852
|
|
|
861
853
|
/** Short name for a given manifest name, e.g. `parachute-vault` → `vault`.
|
|
862
854
|
* Consults both FIRST_PARTY_FALLBACKS (notes) and KNOWN_MODULES
|
|
863
|
-
* (vault / scribe /
|
|
855
|
+
* (vault / scribe / agent / surface — post-FALLBACK-retirement).
|
|
864
856
|
* Returns undefined for unknown manifests. */
|
|
865
857
|
export function shortNameForManifest(manifestName: string): string | undefined {
|
|
866
858
|
for (const [short, fb] of Object.entries(FIRST_PARTY_FALLBACKS)) {
|
|
@@ -887,7 +879,7 @@ export function shortNameForManifest(manifestName: string): string | undefined {
|
|
|
887
879
|
* here — `shortNameForManifest` only knows the canonical `parachute-vault`, so
|
|
888
880
|
* `findServiceByShort(services, "vault")` returns undefined even when a vault is
|
|
889
881
|
* installed. Vault rows are resolved by mount path via `findVaultUpstream`; this
|
|
890
|
-
* helper is for single-instance modules (agent / scribe /
|
|
882
|
+
* helper is for single-instance modules (agent / scribe / surface).
|
|
891
883
|
*/
|
|
892
884
|
export function findServiceByShort<T extends { name: string }>(
|
|
893
885
|
services: readonly T[],
|
|
@@ -901,7 +893,7 @@ export function findServiceByShort<T extends { name: string }>(
|
|
|
901
893
|
* manifest data the caller has on hand (typically read from
|
|
902
894
|
* `<installDir>/.parachute/module.json`).
|
|
903
895
|
*
|
|
904
|
-
* Used at install-time and lifecycle-time for vault / scribe /
|
|
896
|
+
* Used at install-time and lifecycle-time for vault / scribe / surface —
|
|
905
897
|
* where hub no longer vendors the manifest (services.json + module.json
|
|
906
898
|
* are authoritative) but still needs the imperative `extras` bits
|
|
907
899
|
* (`init`, `postInstallFooter`, `urlForEntry`, `hasAuth`) the CLI install
|
package/src/services-manifest.ts
CHANGED
|
@@ -124,7 +124,7 @@ const UI_AUDIENCE_VALUES: readonly UiAudience[] = ["public", "hub-users", "opera
|
|
|
124
124
|
* one shot without touching its siblings.
|
|
125
125
|
*
|
|
126
126
|
* Backwards-compat: this is purely additive. Modules that don't use `uis`
|
|
127
|
-
* (vault, scribe, notes
|
|
127
|
+
* (vault, scribe, notes today) continue to render as flat rows;
|
|
128
128
|
* the field is optional throughout the read + write paths.
|
|
129
129
|
*/
|
|
130
130
|
export interface UiSubUnit {
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
* SCOPE + OWNERSHIP SAFETY (the hard constraint): we ONLY ever disable a unit
|
|
23
23
|
* whose name EXACTLY matches `parachute-<short>.service` (systemd) or
|
|
24
24
|
* `computer.parachute.<short>` (launchd) for a KNOWN module short
|
|
25
|
-
* (`knownServices()` — vault / scribe /
|
|
25
|
+
* (`knownServices()` — vault / scribe / surface / notes / agent). We
|
|
26
26
|
* NEVER disable an arbitrary or unrecognized unit — an unknown unit is invisible
|
|
27
27
|
* to this sweep by construction (we look up exact names, never enumerate-and-
|
|
28
28
|
* match-loosely). On top of that we EXPLICITLY exclude the units the supervised
|
|
@@ -98,7 +98,7 @@ function isProtectedLaunchdLabel(label: string): boolean {
|
|
|
98
98
|
/**
|
|
99
99
|
* The module shorts whose stale standalone autostart units the sweep targets.
|
|
100
100
|
* Derived from `knownServices()` (the canonical FIRST_PARTY_FALLBACKS +
|
|
101
|
-
* KNOWN_MODULES list — vault / scribe /
|
|
101
|
+
* KNOWN_MODULES list — vault / scribe / surface / notes / agent), so
|
|
102
102
|
* a future module is covered automatically. `hub` is deliberately NOT in that
|
|
103
103
|
* list — the hub unit is the supervised model itself; we never disable it. As a
|
|
104
104
|
* defensive double-check we also drop any short whose derived unit name lands in
|
package/src/well-known.ts
CHANGED
|
@@ -88,7 +88,7 @@ export interface WellKnownServicesEntry {
|
|
|
88
88
|
* Sub-units hosted under this module, surfaced as an array (the on-disk
|
|
89
89
|
* shape is a map; the well-known shape is an array so consumers iterate
|
|
90
90
|
* cleanly). Each entry promotes the map key into `name`. Absent on
|
|
91
|
-
* modules that don't declare `uis` (vault, scribe, notes
|
|
91
|
+
* modules that don't declare `uis` (vault, scribe, notes today).
|
|
92
92
|
* See `UiSubUnit` in services-manifest.ts + parachute-app design doc §12.
|
|
93
93
|
*/
|
|
94
94
|
uis?: WellKnownUiSubUnit[];
|
|
@@ -318,8 +318,8 @@ export function buildWellKnown(opts: BuildWellKnownOpts): WellKnownDocument {
|
|
|
318
318
|
// an array of records so JS consumers iterate cleanly without a second
|
|
319
319
|
// Object.entries round-trip. `name` promotes the map key into a field
|
|
320
320
|
// — same convention as `WellKnownVaultEntry`. Absent on the parent
|
|
321
|
-
// when the entry doesn't declare `uis`, so vault / notes / scribe
|
|
322
|
-
//
|
|
321
|
+
// when the entry doesn't declare `uis`, so vault / notes / scribe
|
|
322
|
+
// rows stay byte-identical to their pre-#313 shape.
|
|
323
323
|
//
|
|
324
324
|
// Emitted on every path of a multi-path entry — today only vault has
|
|
325
325
|
// multi-path entries, and vault doesn't declare `uis` yet, so the
|