@openparachute/vault 0.4.8-rc.4 → 0.4.8-rc.6

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.
@@ -3,7 +3,6 @@
3
3
  "manifestName": "parachute-vault",
4
4
  "displayName": "Vault",
5
5
  "tagline": "Your owner-authenticated MCP knowledge store.",
6
- "kind": "api",
7
6
  "port": 1940,
8
7
  "paths": ["/vault/default"],
9
8
  "health": "/vault/default/health",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openparachute/vault",
3
- "version": "0.4.8-rc.4",
3
+ "version": "0.4.8-rc.6",
4
4
  "description": "Agent-native knowledge graph. Notes, tags, links over MCP.",
5
5
  "module": "src/cli.ts",
6
6
  "type": "module",
@@ -40,14 +40,13 @@ describe("module-manifest", () => {
40
40
  });
41
41
  });
42
42
 
43
- test("readSelfManifest parses a valid manifest", () => {
43
+ test("readSelfManifest parses a valid manifest (no kind — hub#301 Phase B)", () => {
44
44
  withTempPackageRoot(
45
45
  {
46
46
  name: "vault",
47
47
  manifestName: "parachute-vault",
48
48
  displayName: "Vault",
49
49
  tagline: "Test tagline",
50
- kind: "api",
51
50
  port: 1940,
52
51
  paths: ["/vault/default"],
53
52
  health: "/vault/default/health",
@@ -58,13 +57,34 @@ describe("module-manifest", () => {
58
57
  expect(m?.name).toBe("vault");
59
58
  expect(m?.manifestName).toBe("parachute-vault");
60
59
  expect(m?.displayName).toBe("Vault");
61
- expect(m?.kind).toBe("api");
60
+ expect(m?.kind).toBeUndefined();
62
61
  expect(m?.port).toBe(1940);
63
62
  expect(m?.paths).toEqual(["/vault/default"]);
64
63
  },
65
64
  );
66
65
  });
67
66
 
67
+ test("readSelfManifest tolerates a legacy manifest that still includes kind", () => {
68
+ // hub#301 Phase B retired the `kind` field, but legacy manifests on
69
+ // pinned installs may still include it. The reader accepts it without
70
+ // erroring; the field is never branched on.
71
+ withTempPackageRoot(
72
+ {
73
+ name: "vault",
74
+ manifestName: "parachute-vault",
75
+ kind: "api",
76
+ port: 1940,
77
+ paths: ["/vault/default"],
78
+ health: "/vault/default/health",
79
+ },
80
+ (root) => {
81
+ const m = readSelfManifest(root);
82
+ expect(m).not.toBeNull();
83
+ expect(m?.kind).toBe("api");
84
+ },
85
+ );
86
+ });
87
+
68
88
  test("readSelfManifest throws on malformed JSON", () => {
69
89
  withTempPackageRoot("{ not valid json", (root) => {
70
90
  expect(() => readSelfManifest(root)).toThrow();
@@ -73,7 +93,7 @@ describe("module-manifest", () => {
73
93
 
74
94
  test("readSelfManifest throws when required field missing", () => {
75
95
  withTempPackageRoot(
76
- { name: "vault" /* missing manifestName / port / paths / health / kind */ },
96
+ { name: "vault" /* missing manifestName / port / paths / health */ },
77
97
  (root) => {
78
98
  expect(() => readSelfManifest(root)).toThrow(/missing required/);
79
99
  },
@@ -83,11 +103,12 @@ describe("module-manifest", () => {
83
103
  test("readSelfManifest reads the actual shipped manifest in the repo", () => {
84
104
  // Smoke test the real shipped file — guards against ever shipping a
85
105
  // malformed manifest. Uses the real resolvePackageRoot (which finds
86
- // the repo root in tests).
106
+ // the repo root in tests). Post hub#301 Phase B, the shipped manifest
107
+ // no longer includes `kind`.
87
108
  const m = readSelfManifest();
88
109
  expect(m).not.toBeNull();
89
110
  expect(m?.manifestName).toBe("parachute-vault");
90
- expect(m?.kind).toBe("api");
111
+ expect(m?.kind).toBeUndefined();
91
112
  expect(m?.port).toBe(1940);
92
113
  });
93
114
  });
@@ -36,7 +36,14 @@ export interface VaultModuleManifest {
36
36
  readonly manifestName: string;
37
37
  readonly displayName?: string;
38
38
  readonly tagline?: string;
39
- readonly kind: ModuleKind;
39
+ /**
40
+ * Deprecated as of hub#301 Phase B (kind retirement, 2026-05-23). Hub's
41
+ * validator dropped `kind` from required-fields in hub#327; vault no
42
+ * longer ships the field in `.parachute/module.json`. Kept here as
43
+ * optional only so an older shipped manifest (pinned legacy install)
44
+ * still parses without throwing — the field is never branched on.
45
+ */
46
+ readonly kind?: ModuleKind;
40
47
  readonly port: number;
41
48
  readonly paths: readonly string[];
42
49
  readonly health: string;
@@ -87,8 +94,11 @@ export function readSelfManifest(
87
94
  if (typeof parsed.port !== "number" || !Array.isArray(parsed.paths)) {
88
95
  throw new Error(`${path}: manifest missing required "port" / "paths"`);
89
96
  }
90
- if (typeof parsed.health !== "string" || typeof parsed.kind !== "string") {
91
- throw new Error(`${path}: manifest missing required "health" / "kind"`);
97
+ if (typeof parsed.health !== "string") {
98
+ throw new Error(`${path}: manifest missing required "health"`);
92
99
  }
100
+ // `kind` is retired as of hub#301 Phase B — hub#327 made it optional in
101
+ // the hub-side validator, and vault no longer ships it. If a legacy
102
+ // manifest still includes the field, accept it; just don't require it.
93
103
  return parsed as unknown as VaultModuleManifest;
94
104
  }
package/src/routes.ts CHANGED
@@ -1308,7 +1308,7 @@ async function handleNotesInner(
1308
1308
  }
1309
1309
  }
1310
1310
 
1311
- // DELETE /notes/:idOrPath — admin only (enforced at server level)
1311
+ // DELETE /notes/:idOrPath — vault:write (no admin gate; consistent with verbForMethod)
1312
1312
  if (method === "DELETE") {
1313
1313
  const note = await resolveNote(store, idOrPath);
1314
1314
  if (!note) return json({ error: "Not found" }, 404);
@@ -911,7 +911,6 @@ describe("/.parachute/info + /.parachute/icon.svg", () => {
911
911
  tagline: string;
912
912
  version: string;
913
913
  iconUrl: string;
914
- kind: string;
915
914
  };
916
915
  expect(body).toEqual({
917
916
  name: "parachute-vault",
@@ -919,8 +918,11 @@ describe("/.parachute/info + /.parachute/icon.svg", () => {
919
918
  tagline: expect.stringContaining("knowledge graph"),
920
919
  version: pkg.version,
921
920
  iconUrl: "/vault/journal/.parachute/icon.svg",
922
- kind: "api",
923
921
  });
922
+ // `kind` retired from the info-endpoint response per hub#330 (companion
923
+ // to vault#359's module.json drop). Pin its absence so regressions are
924
+ // surfaced — the shape is a locked contract with the hub.
925
+ expect(body).not.toHaveProperty("kind");
924
926
  });
925
927
 
926
928
  test("info iconUrl is vault-scoped and points at a live icon handler", async () => {
package/src/routing.ts CHANGED
@@ -132,11 +132,11 @@ function handleParachuteInfo(vaultName: string): Response {
132
132
  tagline: "Agent-native knowledge graph — notes, tags, links, attachments over REST + MCP",
133
133
  version: pkg.version,
134
134
  iconUrl: `/vault/${vaultName}/.parachute/icon.svg`,
135
- // Hub renders `kind: "api"` cards as an expandable detail panel (MCP URL,
136
- // OAuth link, version) rather than navigating to the API's root. Vault
137
- // has no browser UI, so navigating to it shows raw JSON — not useful.
138
- kind: "api",
139
135
  };
136
+ // `kind` was previously emitted here (and matched module.json) to let the
137
+ // hub branch its card rendering on api vs ui. Retired per hub#330 — the hub
138
+ // now infers presentation from the response shape itself. Companion to
139
+ // vault#359 (manifest drop); closes part of hub#340.
140
140
  return Response.json(body, {
141
141
  headers: { "Access-Control-Allow-Origin": "*" },
142
142
  });
@@ -39,7 +39,6 @@ const TEST_MANIFEST: VaultModuleManifest = {
39
39
  manifestName: "parachute-vault",
40
40
  displayName: "Vault",
41
41
  tagline: "Test tagline",
42
- kind: "api",
43
42
  port: 1940,
44
43
  paths: ["/vault/default"],
45
44
  health: "/vault/default/health",