@openparachute/vault 0.6.4-rc.8 → 0.6.4-rc.9

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openparachute/vault",
3
- "version": "0.6.4-rc.8",
3
+ "version": "0.6.4-rc.9",
4
4
  "description": "Agent-native knowledge graph. Notes, tags, links over MCP.",
5
5
  "module": "src/cli.ts",
6
6
  "type": "module",
package/src/cli.ts CHANGED
@@ -1674,11 +1674,11 @@ function cmdRemove(args: string[]) {
1674
1674
  // out of the parachute-vault row immediately — the same selfRegister
1675
1675
  // refresh cmdCreate does (#208). Without this, the hub's well-known
1676
1676
  // fan-out kept advertising the deleted vault until the next server boot.
1677
- // Note: with zero vaults remaining, selfRegister falls back to the
1678
- // manifest's canonical paths (`/vault/default`) the same row a
1679
- // subsequent boot would write so CLI-remove and boot agree on the
1680
- // zero-vault registration shape. Warnings go to stderr; status lines stay
1681
- // ours.
1677
+ // Note: with zero vaults remaining, selfRegister emits paths: [] (#478) —
1678
+ // the row stays present (so the hub still sees the module as installed)
1679
+ // but advertises no /vault/<name> path. The hub must tolerate empty-paths
1680
+ // rows and skip them rather than resolving a phantom "default". Warnings
1681
+ // go to stderr; status lines stay ours.
1682
1682
  selfRegister({
1683
1683
  version: pkg.version,
1684
1684
  warn: (msg) => console.error(`Warning: ${msg}`),
@@ -61,10 +61,8 @@ function captureLogs(): {
61
61
  }
62
62
 
63
63
  describe("self-register", () => {
64
- test("buildVaultServicePaths — no vaults yet → manifest fallback", () => {
65
- expect(buildVaultServicePaths(undefined, [], ["/vault/default"])).toEqual([
66
- "/vault/default",
67
- ]);
64
+ test("buildVaultServicePaths — no vaults yet → empty paths (no phantom /vault/default, #478)", () => {
65
+ expect(buildVaultServicePaths(undefined, [], ["/vault/default"])).toEqual([]);
68
66
  });
69
67
 
70
68
  test("buildVaultServicePaths — default vault sorts first", () => {
@@ -108,7 +106,9 @@ describe("self-register", () => {
108
106
  const row = parsed.services[0] as Record<string, unknown>;
109
107
  expect(row.name).toBe("parachute-vault");
110
108
  expect(row.port).toBe(1940);
111
- expect(row.paths).toEqual(["/vault/default"]);
109
+ // Zero vaults → paths: [] (no phantom /vault/default, #478).
110
+ // Health still well-formed: paths[0] ?? "/vault/default" fallback.
111
+ expect(row.paths).toEqual([]);
112
112
  expect(row.health).toBe("/vault/default/health");
113
113
  expect(row.version).toBe("0.4.8-rc.3");
114
114
  expect(row.installDir).toBe("/fake/install/dir");
@@ -56,8 +56,13 @@ import { listVaults, readGlobalConfig, DEFAULT_PORT } from "./config.ts";
56
56
  *
57
57
  * Mirrors `buildVaultServicePaths` in `cli.ts` so the self-register pass
58
58
  * produces the same multi-vault path advertisement as `parachute-vault
59
- * init` / `vault create`. With no vaults yet, falls back to the manifest's
60
- * canonical `paths[0]` so early-boot registration is still well-formed.
59
+ * init` / `vault create`.
60
+ *
61
+ * At zero vaults, returns an empty array (`paths: []`). The row remains
62
+ * present in services.json (name, port, health, version, installDir intact
63
+ * — so the module is still detected as installed), but it advertises no
64
+ * `/vault/<name>` path and the hub must not resolve it to a phantom
65
+ * `/vault/default`. Closes #478.
61
66
  *
62
67
  * Exported for tests; not part of the public module surface.
63
68
  */
@@ -66,7 +71,7 @@ export function buildVaultServicePaths(
66
71
  vaults: readonly string[],
67
72
  fallbackFromManifest: readonly string[],
68
73
  ): string[] {
69
- if (vaults.length === 0) return [...fallbackFromManifest];
74
+ if (vaults.length === 0) return [];
70
75
  if (defaultVault && vaults.includes(defaultVault)) {
71
76
  return [
72
77
  `/vault/${defaultVault}`,
@@ -141,13 +141,12 @@ describe("vault remove — last-vault auto_create marker", () => {
141
141
  // resurrection of a freshly-credentialed "default".
142
142
  expect(bootAutoCreateAllowed(config)).toBe(false);
143
143
 
144
- // services.json was still refreshed: with zero vaults the row falls back
145
- // to the manifest's canonical paths the SAME row a subsequent boot's
146
- // selfRegister writes, so CLI-remove and boot agree on the zero-vault
147
- // registration shape (and the hub still sees the module as installed).
144
+ // services.json was still refreshed: with zero vaults the row carries
145
+ // paths: [] (#478) — the row stays present so the hub sees the module as
146
+ // installed, but advertises no /vault/<name> path (no phantom default).
148
147
  const vault = readServices(home).find((s) => s.name === "parachute-vault");
149
148
  expect(vault).toBeDefined();
150
- expect(vault!.paths).toEqual(["/vault/default"]);
149
+ expect(vault!.paths).toEqual([]);
151
150
  });
152
151
 
153
152
  test("removing a NON-last vault does not write the marker", () => {