@mcp-index/sdk 0.15.0 → 0.17.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.
Files changed (39) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.md +41 -2
  3. package/dist/src/canonical.d.ts +8 -0
  4. package/dist/src/canonical.d.ts.map +1 -1
  5. package/dist/src/canonical.js +57 -0
  6. package/dist/src/canonical.js.map +1 -1
  7. package/dist/src/contractFields.d.ts +42 -0
  8. package/dist/src/contractFields.d.ts.map +1 -0
  9. package/dist/src/contractFields.js +103 -0
  10. package/dist/src/contractFields.js.map +1 -0
  11. package/dist/src/fileLock.d.ts +20 -0
  12. package/dist/src/fileLock.d.ts.map +1 -0
  13. package/dist/src/fileLock.js +191 -0
  14. package/dist/src/fileLock.js.map +1 -0
  15. package/dist/src/gate.d.ts +28 -3
  16. package/dist/src/gate.d.ts.map +1 -1
  17. package/dist/src/gate.js +85 -3
  18. package/dist/src/gate.js.map +1 -1
  19. package/dist/src/index.d.ts +3 -1
  20. package/dist/src/index.d.ts.map +1 -1
  21. package/dist/src/index.js +2 -1
  22. package/dist/src/index.js.map +1 -1
  23. package/dist/src/listingFilter.d.ts +6 -3
  24. package/dist/src/listingFilter.d.ts.map +1 -1
  25. package/dist/src/listingFilter.js +17 -6
  26. package/dist/src/listingFilter.js.map +1 -1
  27. package/dist/src/pendingStore.d.ts +53 -0
  28. package/dist/src/pendingStore.d.ts.map +1 -0
  29. package/dist/src/pendingStore.js +309 -0
  30. package/dist/src/pendingStore.js.map +1 -0
  31. package/dist/src/preflight.d.ts +37 -7
  32. package/dist/src/preflight.d.ts.map +1 -1
  33. package/dist/src/preflight.js +340 -83
  34. package/dist/src/preflight.js.map +1 -1
  35. package/dist/src/wrap.d.ts +13 -7
  36. package/dist/src/wrap.d.ts.map +1 -1
  37. package/dist/src/wrap.js +199 -14
  38. package/dist/src/wrap.js.map +1 -1
  39. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -5,6 +5,26 @@ additive feature, patch = fix). Backward-compatible additions only in 0.2.0.
5
5
 
6
6
  ## [Unreleased]
7
7
 
8
+ ## 0.17.0 - 2026-10-11
9
+
10
+ ### Changed
11
+
12
+ - The MCP client's own listChanged refresh is filtered. `wrap()` routes the inner client's `listTools` and its notification handlers through the gate, so `onChanged` receives only the tools the list would show, and calls to a tool hold under guard and strict after a `tools/list_changed` notification until a list page read after it carries that tool. This holds whether the client is wrapped before or after `connect()`. `wrap()` throws under guard and strict for a client object that rejects new properties.
13
+ - Tool fields outside the definition hash are pinned and compared: `title`, `icons`, `_meta`, `execution`, any other top-level field, and annotation keys other than the four hints. Under guard and strict a change to one of them on a pinned tool leaves the tool out and holds its call. `approvalDigest` covers the same fields; a digest over the 0.16.0 field set is unchanged.
14
+ - Pins record a field-set marker inside `schema`, which older writers keep. A pin written before 0.17.0 records the new fields once, from the first list whose definition matches, and compares them after that.
15
+ - Still not covered: first-time `outputSchema` text on an otherwise unchanged tool.
16
+
17
+ ## 0.16.0 - 2026-10-11
18
+
19
+ ### Changed
20
+
21
+ - Under guard and strict, a new tool on an already-pinned server is left out of the tool list and cannot be called until it is reviewed. `approvePending(name, digest)` pins the stored definition when the digest over its full public contract matches. `onWithheld` carries that digest.
22
+ - A change that arrives without an upgrade is held for review and is never bulk-approved. `newTools: "tofu"` restores first-sight trust for that wrapper.
23
+ - The file pin store takes a lock and merges from disk before each write, so a Python CLI approval and a TypeScript process on the same pin file cannot lose each other's pins. The lock uses only Node built-ins and works on Windows. The package has no runtime dependencies. Pins may carry an optional `launchKey`.
24
+ - A pin store that goes missing, stops being a regular file, or no longer holds pins for a server it held before is treated as tampered, whether that happens while the process runs or before a restart. Pins already loaded are kept, every call holds, and the store refuses writes. `resetPins(serverId)` is the deliberate recovery: it clears the store and its ever-pinned record so the next list pins from the current contract.
25
+ - A pin reload that fails under a lock timeout classifies held tools as changed-without-upgrade, not floating.
26
+ - The SDK client's own listChanged refresh is still not filtered.
27
+
8
28
  ## 0.15.0 - 2026-10-05
9
29
 
10
30
  ### Changed
package/README.md CHANGED
@@ -22,7 +22,7 @@ Peer dependency: `@modelcontextprotocol/sdk` >=1.0.0 <2 (the wrapper gates by se
22
22
  import { wrap } from '@mcp-index/sdk';
23
23
 
24
24
  // wrap an already-connected MCP client session
25
- const guarded = wrap(session); // pins each tool's contract on first use (TOFU)
25
+ const guarded = wrap(session); // in-memory pins for this process only
26
26
 
27
27
  // use `guarded` exactly like `session`; a drifted contract is HELD before the call
28
28
  // fires. A PreflightHold surfaces (Guard/Strict) so you can route the agent to
@@ -44,6 +44,40 @@ const guarded = wrap(session, { serverId: 'my-mcp-server' }); // pins on disk
44
44
  `pinStore: 'file'` forces the file store without one. You can also pass your own
45
45
  `PreflightPin` as `pin`.
46
46
 
47
+ ### New tools on an already-pinned server
48
+
49
+ Under `guard` and `strict`, when a server you already pinned adds a tool, that
50
+ tool is left out of the list and a call to it holds. It is not trusted mid-session on
51
+ first sight. A process running as you that rewrites the pin store with its own
52
+ well-formed pins is still trusted. `onWithheld` receives the definition digest. Pin
53
+ the stored definition with `approvePending(name, digest)` when you have reviewed it:
54
+
55
+ ```ts
56
+ const guarded = wrap(session, {
57
+ serverId: 'my-mcp-server',
58
+ onWithheld: (_server, name, _reason, digest) => {
59
+ // review the held tool, then:
60
+ // guarded.approvePending(name, digest);
61
+ },
62
+ });
63
+ ```
64
+
65
+ Pass `newTools: 'tofu'` to restore first-sight trust for new tools on that
66
+ wrapper.
67
+
68
+ The MCP client's own `listChanged` refresh is filtered too: `wrap()` routes the
69
+ inner client's `listTools` through the gate, so `onChanged` receives only the
70
+ tools the list would show. After a `tools/list_changed` notification, calls hold
71
+ under guard and strict until the list is read again. `wrap()` throws under guard
72
+ and strict for a client object that rejects new properties (a frozen object).
73
+
74
+ The pin records every top-level field a server lists for a tool (`title`,
75
+ `icons`, `_meta`, `execution`, and any later field) and annotation keys other
76
+ than the four hints. A change to one of them on a pinned tool leaves the tool
77
+ out under guard and strict. A pin written before 0.17.0 records those fields
78
+ once, from the first matching list. First-time `outputSchema` text on an
79
+ otherwise unchanged tool is still shown.
80
+
47
81
  ## Sign in (optional) - `mcpindex login`
48
82
 
49
83
  Signs you in with GitHub and stores a free API key at `~/.mcpindex/credentials.json`
@@ -66,7 +100,12 @@ different host to override the default (`https://mcpindex.ai`).
66
100
 
67
101
  ## What it does
68
102
 
69
- - Pins each MCP tool's contract trust-on-first-use (TOFU), persisted across restarts.
103
+ - Pins each MCP tool's contract on first sight in an empty store. With a `serverId`
104
+ (or `pinStore: 'file'`), those pins are kept on disk and survive restarts. Without
105
+ one they stay in memory for the process only.
106
+ - Under `guard` and `strict`, a new tool on an already-pinned server is left out of
107
+ the list until you review it (`approvePending`). `newTools: 'tofu'` restores
108
+ first-sight trust for that wrapper.
70
109
  - Runs a **deterministic** contract-diff (the ChangeKind taxonomy: added-required-param,
71
110
  constraint-narrowed, annotation-flip-to-destructive, output-schema-changed,
72
111
  type/enum/removed, ...) plus an injection/exfil marker scan over input and output schema.
@@ -43,4 +43,12 @@ export declare function toolHash(name: string, description: string, inputSchema:
43
43
  * to `hashTool({description: null})` that bypasses the wrapper's normalization —
44
44
  * we keep the `""` coercion (it is the wrapper-faithful value) and note the gap. */
45
45
  export declare function hashTool(defn: Record<string, unknown>): string;
46
+ /**
47
+ * Digest over the whole public contract a person reviews (port of Python
48
+ * ``approval_digest``). Covers name, description, inputSchema, outputSchema,
49
+ * annotations, and every other top-level field the server listed (title,
50
+ * icons, _meta, ...). Pending approve tokens use this; pin drift still uses
51
+ * ``hashTool``.
52
+ */
53
+ export declare function approvalDigest(defn: Record<string, unknown>): string;
46
54
  //# sourceMappingURL=canonical.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"canonical.d.ts","sourceRoot":"","sources":["../../src/canonical.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAOH,kDAAkD;AAClD,MAAM,MAAM,IAAI,GACZ,IAAI,GACJ,OAAO,GACP,MAAM,GACN,MAAM,GACN,IAAI,EAAE,GACN;IAAE,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC;AAiM1B;kCACkC;AAClC,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAEnD;AAED;;yEAEyE;AACzE,wBAAgB,aAAa,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAElD;AAED;8EAC8E;AAC9E,wBAAgB,QAAQ,CACtB,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACnC,MAAM,CAOR;AAED;;;;;;;;;oFASoF;AACpF,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAY9D"}
1
+ {"version":3,"file":"canonical.d.ts","sourceRoot":"","sources":["../../src/canonical.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAQH,kDAAkD;AAClD,MAAM,MAAM,IAAI,GACZ,IAAI,GACJ,OAAO,GACP,MAAM,GACN,MAAM,GACN,IAAI,EAAE,GACN;IAAE,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC;AAiM1B;kCACkC;AAClC,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAEnD;AAED;;yEAEyE;AACzE,wBAAgB,aAAa,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAElD;AAED;8EAC8E;AAC9E,wBAAgB,QAAQ,CACtB,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACnC,MAAM,CAOR;AAED;;;;;;;;;oFASoF;AACpF,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAY9D;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CA4BpE"}
@@ -18,6 +18,7 @@
18
18
  * `_hash_tool` maps the public `inputSchema` field onto `input_schema` before
19
19
  * hashing. We replicate that exactly.
20
20
  */
21
+ import { assignOwn, extraFields } from "./contractFields.js";
21
22
  import { createHash } from "node:crypto";
22
23
  const FLOAT_DIGITS = 17;
23
24
  const MAX_CANON_DEPTH = 64;
@@ -265,4 +266,60 @@ export function hashTool(defn) {
265
266
  : {};
266
267
  return toolHash(name, desc, inSch);
267
268
  }
269
+ /**
270
+ * Digest over the whole public contract a person reviews (port of Python
271
+ * ``approval_digest``). Covers name, description, inputSchema, outputSchema,
272
+ * annotations, and every other top-level field the server listed (title,
273
+ * icons, _meta, ...). Pending approve tokens use this; pin drift still uses
274
+ * ``hashTool``.
275
+ */
276
+ export function approvalDigest(defn) {
277
+ const payload = {
278
+ name: defn.name === undefined || defn.name === null ? "" : String(defn.name),
279
+ description: defn.description === undefined || defn.description === null
280
+ ? ""
281
+ : String(defn.description),
282
+ inputSchema: defn.inputSchema !== null &&
283
+ typeof defn.inputSchema === "object" &&
284
+ !Array.isArray(defn.inputSchema)
285
+ ? defn.inputSchema
286
+ : {},
287
+ };
288
+ const outp = defn.outputSchema;
289
+ if (outp !== null && typeof outp === "object" && !Array.isArray(outp)) {
290
+ payload.outputSchema = outp;
291
+ }
292
+ const ann = defn.annotations;
293
+ if (ann !== null && typeof ann === "object" && !Array.isArray(ann)) {
294
+ payload.annotations = ann;
295
+ }
296
+ // title, icons, _meta, execution and any later top-level field. The title
297
+ // rule is unchanged, so a digest over the 0.16 field set comes out the same.
298
+ assignOwn(payload, extraFields(defn));
299
+ // Python: json.dumps(..., sort_keys=True, separators=(",", ":"), ensure_ascii=False)
300
+ const stable = dumpsSorted(payload);
301
+ return createHash("sha256").update(Buffer.from(stable, "utf8")).digest("hex");
302
+ }
303
+ function dumpsSorted(value) {
304
+ if (value === null)
305
+ return "null";
306
+ if (typeof value === "boolean")
307
+ return value ? "true" : "false";
308
+ if (typeof value === "number") {
309
+ if (!Number.isFinite(value))
310
+ throw new Error("non-finite number");
311
+ return Number.isInteger(value) ? String(value) : JSON.stringify(value);
312
+ }
313
+ if (typeof value === "string")
314
+ return JSON.stringify(value);
315
+ if (Array.isArray(value)) {
316
+ return "[" + value.map(dumpsSorted).join(",") + "]";
317
+ }
318
+ if (typeof value === "object") {
319
+ const keys = Object.keys(value).sort();
320
+ const parts = keys.map((key) => JSON.stringify(key) + ":" + dumpsSorted(value[key]));
321
+ return "{" + parts.join(",") + "}";
322
+ }
323
+ throw new Error("unsupported JSON value");
324
+ }
268
325
  //# sourceMappingURL=canonical.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"canonical.js","sourceRoot":"","sources":["../../src/canonical.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"canonical.js","sourceRoot":"","sources":["../../src/canonical.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Top-level tool fields that the definition hash does not cover (port of Python
3
+ * `contract_fields`).
4
+ *
5
+ * The hash covers name, description and inputSchema. annotations and
6
+ * outputSchema have their own rules in the gate. Every other top-level key a
7
+ * server lists (title, icons, _meta, execution, and whatever a later spec adds)
8
+ * reaches the host too, so a pin records it and the gate compares it on a hash
9
+ * match.
10
+ *
11
+ * A pin written before this module has no `contractFields` marker. On such a
12
+ * pin a key it lacks was never recorded, so it is filled in from the first
13
+ * matching list instead of read as a change.
14
+ */
15
+ export declare const CONTRACT_FIELDS_VERSION = 2;
16
+ /** Where a pin file keeps the marker: inside `schema`, which gate 0.18 and SDK
17
+ * 0.16 keep whole when they rewrite a record. The store moves it out on load and
18
+ * back on write; `extraFields` skips it so a server cannot supply it. */
19
+ export declare const SCHEMA_MARKER_KEY = "_mcpindex_contract_fields";
20
+ /** Set an own enumerable property. Plain assignment of a JSON `__proto__` key
21
+ * would set the prototype instead and drop the key. */
22
+ export declare function setOwn(obj: Record<string, unknown>, key: string, value: unknown): void;
23
+ export declare function assignOwn(target: Record<string, unknown>, source: Record<string, unknown>): void;
24
+ /** The top-level fields outside the hash and the classified pair, as listed.
25
+ * `undefined` and `null` are absent. An empty or non-string title is absent,
26
+ * matching what pins written by 0.16 stored. */
27
+ export declare function extraFields(entry: unknown): Record<string, unknown>;
28
+ export declare const ANNOTATION_TEXT_KEY = "annotations";
29
+ /** What the gate compares on a hash match: the extra fields, plus the
30
+ * annotation keys other than the four hints under one synthetic key that never
31
+ * reaches a pin or a digest. Mirrors Python `compared_fields`. */
32
+ export declare function comparedFields(entry: unknown): Record<string, unknown>;
33
+ /** Which keys to compare. A marked pin compares the union. An old pin compares
34
+ * the keys it recorded, plus the annotation text: pins have always stored
35
+ * annotations whole. */
36
+ export declare function comparedKeys(pinnedSchema: Record<string, unknown>, observed: Record<string, unknown>, complete: boolean): string[];
37
+ /** Extra fields the live entry has and an old pin never recorded. */
38
+ export declare function missingExtraFields(pinnedSchema: Record<string, unknown>, observed: Record<string, unknown>): Record<string, unknown>;
39
+ /** A server-chosen key, quoted and escaped for a reason string (Python
40
+ * `json.dumps(key, ensure_ascii=True)`). */
41
+ export declare function fieldLabel(key: string): string;
42
+ //# sourceMappingURL=contractFields.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contractFields.d.ts","sourceRoot":"","sources":["../../src/contractFields.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,eAAO,MAAM,uBAAuB,IAAI,CAAC;AAEzC;;yEAEyE;AACzE,eAAO,MAAM,iBAAiB,8BAA8B,CAAC;AAE7D;uDACuD;AACvD,wBAAgB,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAEtF;AAED,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAEhG;AAKD;;gDAEgD;AAChD,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAUnE;AAOD,eAAO,MAAM,mBAAmB,gBAAgB,CAAC;AAEjD;;kEAEkE;AAClE,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAatE;AAED;;wBAEwB;AACxB,wBAAgB,YAAY,CAC1B,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACrC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,QAAQ,EAAE,OAAO,GAChB,MAAM,EAAE,CAOV;AAED,qEAAqE;AACrE,wBAAgB,kBAAkB,CAChC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACrC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAChC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAOzB;AAED;4CAC4C;AAC5C,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAM9C"}
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Top-level tool fields that the definition hash does not cover (port of Python
3
+ * `contract_fields`).
4
+ *
5
+ * The hash covers name, description and inputSchema. annotations and
6
+ * outputSchema have their own rules in the gate. Every other top-level key a
7
+ * server lists (title, icons, _meta, execution, and whatever a later spec adds)
8
+ * reaches the host too, so a pin records it and the gate compares it on a hash
9
+ * match.
10
+ *
11
+ * A pin written before this module has no `contractFields` marker. On such a
12
+ * pin a key it lacks was never recorded, so it is filled in from the first
13
+ * matching list instead of read as a change.
14
+ */
15
+ export const CONTRACT_FIELDS_VERSION = 2;
16
+ /** Where a pin file keeps the marker: inside `schema`, which gate 0.18 and SDK
17
+ * 0.16 keep whole when they rewrite a record. The store moves it out on load and
18
+ * back on write; `extraFields` skips it so a server cannot supply it. */
19
+ export const SCHEMA_MARKER_KEY = "_mcpindex_contract_fields";
20
+ /** Set an own enumerable property. Plain assignment of a JSON `__proto__` key
21
+ * would set the prototype instead and drop the key. */
22
+ export function setOwn(obj, key, value) {
23
+ Object.defineProperty(obj, key, { value, enumerable: true, writable: true, configurable: true });
24
+ }
25
+ export function assignOwn(target, source) {
26
+ for (const key of Object.keys(source))
27
+ setOwn(target, key, source[key]);
28
+ }
29
+ const HASHED_FIELDS = new Set(["name", "description", "inputSchema"]);
30
+ const CLASSIFIED_FIELDS = new Set(["annotations", "outputSchema"]);
31
+ /** The top-level fields outside the hash and the classified pair, as listed.
32
+ * `undefined` and `null` are absent. An empty or non-string title is absent,
33
+ * matching what pins written by 0.16 stored. */
34
+ export function extraFields(entry) {
35
+ const out = {};
36
+ if (entry === null || typeof entry !== "object" || Array.isArray(entry))
37
+ return out;
38
+ for (const [key, value] of Object.entries(entry)) {
39
+ if (HASHED_FIELDS.has(key) || CLASSIFIED_FIELDS.has(key) || key === SCHEMA_MARKER_KEY)
40
+ continue;
41
+ if (value === undefined || value === null)
42
+ continue;
43
+ if (key === "title" && !(typeof value === "string" && value.length > 0))
44
+ continue;
45
+ setOwn(out, key, value);
46
+ }
47
+ return out;
48
+ }
49
+ // The boolean hints the gate classifies. Every other annotation key,
50
+ // annotations.title among them, is compared like a top-level field.
51
+ const ANNOTATION_HINTS = new Set(["readOnlyHint", "destructiveHint", "idempotentHint", "openWorldHint"]);
52
+ // "annotations" itself: `extraFields` never carries a top-level "annotations",
53
+ // so no server key can collide with it.
54
+ export const ANNOTATION_TEXT_KEY = "annotations";
55
+ /** What the gate compares on a hash match: the extra fields, plus the
56
+ * annotation keys other than the four hints under one synthetic key that never
57
+ * reaches a pin or a digest. Mirrors Python `compared_fields`. */
58
+ export function comparedFields(entry) {
59
+ const out = extraFields(entry);
60
+ if (entry === null || typeof entry !== "object" || Array.isArray(entry))
61
+ return out;
62
+ const ann = entry["annotations"];
63
+ if (ann !== null && typeof ann === "object" && !Array.isArray(ann)) {
64
+ const text = {};
65
+ for (const [key, value] of Object.entries(ann)) {
66
+ if (ANNOTATION_HINTS.has(key) || value === undefined || value === null)
67
+ continue;
68
+ setOwn(text, key, value);
69
+ }
70
+ if (Object.keys(text).length > 0)
71
+ setOwn(out, ANNOTATION_TEXT_KEY, text);
72
+ }
73
+ return out;
74
+ }
75
+ /** Which keys to compare. A marked pin compares the union. An old pin compares
76
+ * the keys it recorded, plus the annotation text: pins have always stored
77
+ * annotations whole. */
78
+ export function comparedKeys(pinnedSchema, observed, complete) {
79
+ const keys = new Set(Object.keys(comparedFields(pinnedSchema)));
80
+ const live = Object.keys(comparedFields(observed));
81
+ for (const key of live) {
82
+ if (complete || key === ANNOTATION_TEXT_KEY)
83
+ keys.add(key);
84
+ }
85
+ return [...keys].sort();
86
+ }
87
+ /** Extra fields the live entry has and an old pin never recorded. */
88
+ export function missingExtraFields(pinnedSchema, observed) {
89
+ const have = new Set(Object.keys(extraFields(pinnedSchema)));
90
+ const out = {};
91
+ for (const [key, value] of Object.entries(extraFields(observed))) {
92
+ if (!have.has(key))
93
+ setOwn(out, key, value);
94
+ }
95
+ return out;
96
+ }
97
+ /** A server-chosen key, quoted and escaped for a reason string (Python
98
+ * `json.dumps(key, ensure_ascii=True)`). */
99
+ export function fieldLabel(key) {
100
+ const text = JSON.stringify(key).replace(/[\u007f-\uffff]/g, (ch) => "\\u" + ch.charCodeAt(0).toString(16).padStart(4, "0"));
101
+ return text.length <= 64 ? text : text.slice(0, 60) + '..."';
102
+ }
103
+ //# sourceMappingURL=contractFields.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contractFields.js","sourceRoot":"","sources":["../../src/contractFields.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Exclusive lock for a pin or pending file.
3
+ *
4
+ * Sibling path ``<path>.lck``, created with ``O_CREAT | O_EXCL`` (and
5
+ * ``O_NOFOLLOW`` where it exists). The holder writes its pid and an ISO
6
+ * timestamp, then closes the file. Another process that sees the file waits
7
+ * and retries. A lock older than the stale threshold is broken by renaming it
8
+ * aside and unlinking the aside name; only the rename winner proceeds. Release
9
+ * unlinks the file when it still carries our pid and timestamp.
10
+ *
11
+ * Built from the Node standard library only. No native addons. An empty
12
+ * leftover ``<path>.lock`` from an older flock-based build is ignored.
13
+ */
14
+ export declare class LockTimeoutError extends Error {
15
+ constructor(message: string);
16
+ }
17
+ export declare function lockPathFor(path: string): string;
18
+ /** Hold an exclusive create-excl lock on ``path + '.lck'`` for ``fn``. */
19
+ export declare function withExclusiveLock<T>(path: string, fn: () => T): T;
20
+ //# sourceMappingURL=fileLock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fileLock.d.ts","sourceRoot":"","sources":["../../src/fileLock.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAsBH,qBAAa,gBAAiB,SAAQ,KAAK;gBAC7B,OAAO,EAAE,MAAM;CAI5B;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEhD;AA8HD,0EAA0E;AAC1E,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CA6BjE"}
@@ -0,0 +1,191 @@
1
+ /**
2
+ * Exclusive lock for a pin or pending file.
3
+ *
4
+ * Sibling path ``<path>.lck``, created with ``O_CREAT | O_EXCL`` (and
5
+ * ``O_NOFOLLOW`` where it exists). The holder writes its pid and an ISO
6
+ * timestamp, then closes the file. Another process that sees the file waits
7
+ * and retries. A lock older than the stale threshold is broken by renaming it
8
+ * aside and unlinking the aside name; only the rename winner proceeds. Release
9
+ * unlinks the file when it still carries our pid and timestamp.
10
+ *
11
+ * Built from the Node standard library only. No native addons. An empty
12
+ * leftover ``<path>.lock`` from an older flock-based build is ignored.
13
+ */
14
+ import { closeSync, constants, linkSync, lstatSync, mkdirSync, openSync, readFileSync, renameSync, rmdirSync, unlinkSync, writeSync, } from "node:fs";
15
+ import { dirname } from "node:path";
16
+ const SUFFIX = ".lck";
17
+ const STALE_MS = 30_000;
18
+ const DEADLINE_MS = 5_000;
19
+ const SLEEP_MS = 50;
20
+ export class LockTimeoutError extends Error {
21
+ constructor(message) {
22
+ super(message);
23
+ this.name = "LockTimeoutError";
24
+ }
25
+ }
26
+ export function lockPathFor(path) {
27
+ return `${path}${SUFFIX}`;
28
+ }
29
+ function nowIso() {
30
+ return new Date().toISOString();
31
+ }
32
+ function sleepSync(ms) {
33
+ const buf = new Int32Array(new SharedArrayBuffer(4));
34
+ Atomics.wait(buf, 0, 0, ms);
35
+ }
36
+ function createLock(lockPath, pid, stamp) {
37
+ let flags = constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL;
38
+ if (typeof constants.O_NOFOLLOW === "number") {
39
+ flags |= constants.O_NOFOLLOW;
40
+ }
41
+ const fd = openSync(lockPath, flags, 0o600);
42
+ try {
43
+ writeSync(fd, Buffer.from(`${pid}\n${stamp}\n`, "ascii"));
44
+ }
45
+ finally {
46
+ closeSync(fd);
47
+ }
48
+ }
49
+ function readLockIdentity(lockPath) {
50
+ try {
51
+ const text = readFileSync(lockPath, "ascii");
52
+ const lines = text.split(/\r?\n/);
53
+ if (lines.length < 2)
54
+ return null;
55
+ const pid = Number(lines[0]);
56
+ if (!Number.isFinite(pid))
57
+ return null;
58
+ return { pid, stamp: lines[1] ?? "" };
59
+ }
60
+ catch {
61
+ return null;
62
+ }
63
+ }
64
+ function tryBreakStale(lockPath) {
65
+ let st;
66
+ try {
67
+ st = lstatSync(lockPath);
68
+ }
69
+ catch {
70
+ return;
71
+ }
72
+ if (Date.now() - st.mtimeMs < STALE_MS)
73
+ return;
74
+ if (!st.isFile()) {
75
+ // A symlink or directory at the lock path blocks every write forever.
76
+ if (st.isDirectory()) {
77
+ try {
78
+ rmdirSync(lockPath);
79
+ }
80
+ catch {
81
+ throw new LockTimeoutError(`lock path ${lockPath} is a non-empty directory`);
82
+ }
83
+ return;
84
+ }
85
+ try {
86
+ unlinkSync(lockPath);
87
+ }
88
+ catch {
89
+ // best effort
90
+ }
91
+ return;
92
+ }
93
+ // Capture the holder we judged stale. If a new holder rewrote the file
94
+ // before we rename, leave it alone and retry.
95
+ const identity = readLockIdentity(lockPath);
96
+ if (identity === null)
97
+ return;
98
+ const again = readLockIdentity(lockPath);
99
+ if (again === null ||
100
+ again.pid !== identity.pid ||
101
+ again.stamp !== identity.stamp) {
102
+ return;
103
+ }
104
+ // Remaining window: a third process can still create a lock between this
105
+ // re-read and the rename below. The post-rename inode check restores when
106
+ // the aside inode differs from the stale lstat; that does not close a
107
+ // create that lands after rename. Documented, not closed.
108
+ const aside = `${lockPath}.stale.${process.pid}.${process.hrtime.bigint()}`;
109
+ try {
110
+ renameSync(lockPath, aside);
111
+ }
112
+ catch {
113
+ return;
114
+ }
115
+ let asideSt;
116
+ try {
117
+ asideSt = lstatSync(aside);
118
+ }
119
+ catch {
120
+ return;
121
+ }
122
+ if (asideSt.ino !== st.ino) {
123
+ try {
124
+ linkSync(aside, lockPath);
125
+ }
126
+ catch {
127
+ // A new lock already exists at lockPath.
128
+ }
129
+ try {
130
+ unlinkSync(aside);
131
+ }
132
+ catch {
133
+ // best effort
134
+ }
135
+ return;
136
+ }
137
+ try {
138
+ unlinkSync(aside);
139
+ }
140
+ catch {
141
+ // best effort
142
+ }
143
+ }
144
+ function stillOurs(lockPath, pid, stamp) {
145
+ const identity = readLockIdentity(lockPath);
146
+ return identity !== null && identity.pid === pid && identity.stamp === stamp;
147
+ }
148
+ function release(lockPath, pid, stamp) {
149
+ if (!stillOurs(lockPath, pid, stamp))
150
+ return;
151
+ try {
152
+ unlinkSync(lockPath);
153
+ }
154
+ catch {
155
+ // best effort
156
+ }
157
+ }
158
+ /** Hold an exclusive create-excl lock on ``path + '.lck'`` for ``fn``. */
159
+ export function withExclusiveLock(path, fn) {
160
+ const lockPath = lockPathFor(path);
161
+ const directory = dirname(lockPath) || ".";
162
+ mkdirSync(directory, { recursive: true });
163
+ const pid = process.pid;
164
+ const stamp = nowIso();
165
+ const deadline = Date.now() + DEADLINE_MS;
166
+ for (;;) {
167
+ try {
168
+ createLock(lockPath, pid, stamp);
169
+ break;
170
+ }
171
+ catch (err) {
172
+ const code = err !== null && typeof err === "object" && "code" in err
173
+ ? String(err.code)
174
+ : "";
175
+ if (code !== "EEXIST")
176
+ throw err;
177
+ tryBreakStale(lockPath);
178
+ if (Date.now() >= deadline) {
179
+ throw new LockTimeoutError(`timed out waiting for pin store lock ${lockPath}`);
180
+ }
181
+ sleepSync(SLEEP_MS);
182
+ }
183
+ }
184
+ try {
185
+ return fn();
186
+ }
187
+ finally {
188
+ release(lockPath, pid, stamp);
189
+ }
190
+ }
191
+ //# sourceMappingURL=fileLock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fileLock.js","sourceRoot":"","sources":["../../src/fileLock.ts"],"names":[],"mappings":"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"}