@mikeargento/bitgraph-mcp 0.6.0 → 0.7.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.
Files changed (71) hide show
  1. package/dist/__tests__/carrier.test.js +2 -2
  2. package/dist/__tests__/carrier.test.js.map +1 -1
  3. package/dist/__tests__/format.test.js +1 -1
  4. package/dist/__tests__/format.test.js.map +1 -1
  5. package/dist/__tests__/proof-beside.test.js +1 -1
  6. package/dist/__tests__/proof-beside.test.js.map +1 -1
  7. package/dist/__tests__/tools.test.js +1 -1
  8. package/dist/__tests__/tools.test.js.map +1 -1
  9. package/dist/format.d.ts +11 -2
  10. package/dist/format.d.ts.map +1 -1
  11. package/dist/format.js +3 -4
  12. package/dist/format.js.map +1 -1
  13. package/dist/index.js +1 -1
  14. package/dist/index.js.map +1 -1
  15. package/dist/instructions.d.ts +2 -0
  16. package/dist/instructions.d.ts.map +1 -0
  17. package/dist/instructions.js +9 -0
  18. package/dist/instructions.js.map +1 -0
  19. package/dist/server.d.ts +3 -38
  20. package/dist/server.d.ts.map +1 -1
  21. package/dist/server.js +15 -106
  22. package/dist/server.js.map +1 -1
  23. package/package.json +4 -3
  24. package/src/__tests__/carrier.test.ts +2 -2
  25. package/src/__tests__/format.test.ts +2 -2
  26. package/src/__tests__/proof-beside.test.ts +1 -1
  27. package/src/__tests__/tools.test.ts +1 -1
  28. package/src/format.ts +3 -5
  29. package/src/index.ts +1 -1
  30. package/src/instructions.ts +11 -0
  31. package/src/server.ts +25 -186
  32. package/dist/__tests__/encoding.test.d.ts +0 -2
  33. package/dist/__tests__/encoding.test.d.ts.map +0 -1
  34. package/dist/__tests__/encoding.test.js +0 -51
  35. package/dist/__tests__/encoding.test.js.map +0 -1
  36. package/dist/__tests__/scan.test.d.ts +0 -2
  37. package/dist/__tests__/scan.test.d.ts.map +0 -1
  38. package/dist/__tests__/scan.test.js +0 -73
  39. package/dist/__tests__/scan.test.js.map +0 -1
  40. package/dist/api.d.ts +0 -42
  41. package/dist/api.d.ts.map +0 -1
  42. package/dist/api.js +0 -121
  43. package/dist/api.js.map +0 -1
  44. package/dist/carrier-io.d.ts +0 -52
  45. package/dist/carrier-io.d.ts.map +0 -1
  46. package/dist/carrier-io.js +0 -91
  47. package/dist/carrier-io.js.map +0 -1
  48. package/dist/encoding.d.ts +0 -19
  49. package/dist/encoding.d.ts.map +0 -1
  50. package/dist/encoding.js +0 -64
  51. package/dist/encoding.js.map +0 -1
  52. package/dist/scan.d.ts +0 -60
  53. package/dist/scan.d.ts.map +0 -1
  54. package/dist/scan.js +0 -201
  55. package/dist/scan.js.map +0 -1
  56. package/dist/task.d.ts +0 -55
  57. package/dist/task.d.ts.map +0 -1
  58. package/dist/task.js +0 -182
  59. package/dist/task.js.map +0 -1
  60. package/dist/types.d.ts +0 -108
  61. package/dist/types.d.ts.map +0 -1
  62. package/dist/types.js +0 -3
  63. package/dist/types.js.map +0 -1
  64. package/src/__tests__/encoding.test.ts +0 -64
  65. package/src/__tests__/scan.test.ts +0 -80
  66. package/src/api.ts +0 -170
  67. package/src/carrier-io.ts +0 -120
  68. package/src/encoding.ts +0 -72
  69. package/src/scan.ts +0 -220
  70. package/src/task.ts +0 -187
  71. package/src/types.ts +0 -96
@@ -1,52 +0,0 @@
1
- import { type CarrierVerifyResult } from "@mikeargento/bitgraph-verify";
2
- /** The window as the tools state it. not_after null = NOT FETCHED, in those words. */
3
- export interface CarrierWindowView {
4
- verdict: "TRUE" | "FALSE" | "UNDETERMINED";
5
- not_before: {
6
- block: number;
7
- hash: string;
8
- time: string | null;
9
- } | null;
10
- /** null when the ceiling has not been fetched into the file yet. */
11
- not_after: {
12
- block: number;
13
- hash: string;
14
- time: string | null;
15
- } | null;
16
- ceiling: "present" | "unfetched" | null;
17
- reasons: string[];
18
- }
19
- export declare function carrierWindowView(r: CarrierVerifyResult): CarrierWindowView;
20
- /**
21
- * One line for a markdown row: the verdict and the window, in the stated
22
- * words. The floor is temporal (after the block's own time, cryptographically);
23
- * the ceiling is POSITIONAL: committed before the ANCHORING of the later
24
- * block, never before that block's mine time, because an anchor is built
25
- * after the block it carries. Canon §3.5/§3.6: floor in time, ceiling in
26
- * position; converting the positional ceiling into a clock reading is the
27
- * one error.
28
- */
29
- export declare function carrierLine(view: CarrierWindowView): string;
30
- /**
31
- * True when the file's last 8 bytes are the carrier magic. One positioned
32
- * read; no file that is not a carrier pays more than that.
33
- */
34
- export declare function sniffCarrierTail(path: string, size: number): Promise<boolean>;
35
- export interface CarrierFileResult {
36
- /** "ok": readable block, judged. "corrupt": block found but unreadable. */
37
- status: "ok" | "corrupt";
38
- /** Standard base64 SHA-256 of the COMMITTED bytes inside; the digest every lookup uses. */
39
- innerDigestB64: string | null;
40
- /** The committed bytes, for callers that go on to sniff or serve them. */
41
- inner: Uint8Array | null;
42
- result: CarrierVerifyResult | null;
43
- view: CarrierWindowView | null;
44
- corruptReason: string | null;
45
- }
46
- /**
47
- * Read a tail-confirmed carrier whole and judge it offline: the carried
48
- * proof, the floor by identity, the witnesses, the ceiling when present.
49
- * Proof-level judgment (attestation depth stays the audit CLI's job).
50
- */
51
- export declare function readCarrierFile(path: string): Promise<CarrierFileResult>;
52
- //# sourceMappingURL=carrier-io.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"carrier-io.d.ts","sourceRoot":"","sources":["../src/carrier-io.ts"],"names":[],"mappings":"AAkBA,OAAO,EAEL,KAAK,mBAAmB,EACzB,MAAM,8BAA8B,CAAC;AAKtC,sFAAsF;AACtF,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,GAAG,OAAO,GAAG,cAAc,CAAC;IAC3C,UAAU,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAAG,IAAI,CAAC;IACxE,oEAAoE;IACpE,SAAS,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAAG,IAAI,CAAC;IACvE,OAAO,EAAE,SAAS,GAAG,WAAW,GAAG,IAAI,CAAC;IACxC,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,mBAAmB,GAAG,iBAAiB,CAQ3E;AAED;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,iBAAiB,GAAG,MAAM,CAS3D;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAUnF;AAED,MAAM,WAAW,iBAAiB;IAChC,2EAA2E;IAC3E,MAAM,EAAE,IAAI,GAAG,SAAS,CAAC;IACzB,2FAA2F;IAC3F,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,0EAA0E;IAC1E,KAAK,EAAE,UAAU,GAAG,IAAI,CAAC;IACzB,MAAM,EAAE,mBAAmB,GAAG,IAAI,CAAC;IACnC,IAAI,EAAE,iBAAiB,GAAG,IAAI,CAAC;IAC/B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAED;;;;GAIG;AACH,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAoB9E"}
@@ -1,91 +0,0 @@
1
- // Copyright (c) 2024-2026 Argento Computing Inc. Licensed under the MIT License. See LICENSE.
2
- /**
3
- * @mikeargento/bitgraph-mcp: BitGraphed files (bitgraph-carrier/1).
4
- *
5
- * A BitGraphed file is committed bytes followed by one structural block that
6
- * carries the proof and the anchor evidence. The block is found from the END
7
- * of the file, by structure, never by scanning. Everything here is local:
8
- * an 8-byte tail read decides whether a file is a carrier at all, and the
9
- * full judgment runs offline through @mikeargento/bitgraph-verify.
10
- *
11
- * The one rule that cannot bend: the envelope is never the recorded thing,
12
- * the bytes inside it are. So the tools look up the INNER digest, and
13
- * bitgraph_record never mints carrier bytes, the same structural guarantee
14
- * the site's drop box gives.
15
- */
16
- import { open } from "node:fs/promises";
17
- import { CARRIER_MAGIC, CARRIER_OVERHEAD, parseCarrier, verifyCarrier, } from "@mikeargento/bitgraph-verify";
18
- /** ISO string for a witness timestamp (seconds), or null when the header was unreadable. */
19
- const iso = (ts) => (ts === null ? null : new Date(ts * 1000).toISOString());
20
- export function carrierWindowView(r) {
21
- return {
22
- verdict: r.verdict,
23
- not_before: r.bounds ? { block: r.bounds.notBefore.blockNumber, hash: r.bounds.notBefore.blockHash, time: iso(r.bounds.notBefore.timestamp) } : null,
24
- not_after: r.bounds?.notAfter ? { block: r.bounds.notAfter.blockNumber, hash: r.bounds.notAfter.blockHash, time: iso(r.bounds.notAfter.timestamp) } : null,
25
- ceiling: r.ceiling,
26
- reasons: r.reasons,
27
- };
28
- }
29
- /**
30
- * One line for a markdown row: the verdict and the window, in the stated
31
- * words. The floor is temporal (after the block's own time, cryptographically);
32
- * the ceiling is POSITIONAL: committed before the ANCHORING of the later
33
- * block, never before that block's mine time, because an anchor is built
34
- * after the block it carries. Canon §3.5/§3.6: floor in time, ceiling in
35
- * position; converting the positional ceiling into a clock reading is the
36
- * one error.
37
- */
38
- export function carrierLine(view) {
39
- const parts = [`carried proof ${view.verdict}`];
40
- if (view.not_before)
41
- parts.push(`after block ${view.not_before.block}${view.not_before.time ? ` (mined ${view.not_before.time})` : ""}`);
42
- parts.push(view.not_after
43
- ? `before the anchoring of block ${view.not_after.block}${view.not_after.time ? ` (block mined ${view.not_after.time})` : ""}`
44
- : "closing anchor NOT FETCHED (drop the file on bitgraph.ing to complete it)");
45
- return parts.join(" · ");
46
- }
47
- /**
48
- * True when the file's last 8 bytes are the carrier magic. One positioned
49
- * read; no file that is not a carrier pays more than that.
50
- */
51
- export async function sniffCarrierTail(path, size) {
52
- if (size < CARRIER_OVERHEAD)
53
- return false;
54
- const fd = await open(path, "r");
55
- try {
56
- const tail = Buffer.alloc(CARRIER_MAGIC.length);
57
- await fd.read(tail, 0, tail.length, size - tail.length);
58
- return tail.equals(Buffer.from(CARRIER_MAGIC));
59
- }
60
- finally {
61
- await fd.close();
62
- }
63
- }
64
- /**
65
- * Read a tail-confirmed carrier whole and judge it offline: the carried
66
- * proof, the floor by identity, the witnesses, the ceiling when present.
67
- * Proof-level judgment (attestation depth stays the audit CLI's job).
68
- */
69
- export async function readCarrierFile(path) {
70
- const fd = await open(path, "r");
71
- let bytes;
72
- try {
73
- const info = await fd.stat();
74
- const buf = Buffer.alloc(info.size);
75
- await fd.read(buf, 0, info.size, 0);
76
- bytes = new Uint8Array(buf);
77
- }
78
- finally {
79
- await fd.close();
80
- }
81
- const parsed = parseCarrier(bytes);
82
- if (parsed.kind !== "carrier") {
83
- const reason = parsed.kind === "corrupt" ? parsed.reason : "the tail magic matched but no block parsed";
84
- return { status: "corrupt", innerDigestB64: null, inner: null, result: null, view: null, corruptReason: reason };
85
- }
86
- const result = await verifyCarrier(bytes);
87
- const { createHash } = await import("node:crypto");
88
- const innerDigestB64 = createHash("sha256").update(parsed.inner).digest("base64");
89
- return { status: "ok", innerDigestB64, inner: parsed.inner, result, view: carrierWindowView(result), corruptReason: null };
90
- }
91
- //# sourceMappingURL=carrier-io.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"carrier-io.js","sourceRoot":"","sources":["../src/carrier-io.ts"],"names":[],"mappings":"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"}
@@ -1,19 +0,0 @@
1
- /** Standard base64 → URL-safe unpadded base64. */
2
- export declare function toUrlSafeB64(b64: string): string;
3
- /**
4
- * URL-safe base64 → standard base64 with padding.
5
- * A no-op (apart from re-padding) when the input is already standard base64,
6
- * so it is safe to call on either form.
7
- */
8
- export declare function fromUrlSafeB64(urlSafe: string): string;
9
- /** True if the string plausibly encodes 32 bytes of SHA-256 in either base64 form. */
10
- export declare function looksLikeDigest(s: string): boolean;
11
- /**
12
- * SHA-256 of a file's bytes as standard base64.
13
- * Streams from disk, so file size is not a memory concern. Only this digest
14
- * ever leaves the machine; file contents are never uploaded.
15
- */
16
- export declare function sha256FileB64(path: string): Promise<string>;
17
- /** Run an async mapper over items with bounded concurrency, preserving order. */
18
- export declare function mapConcurrent<T, R>(items: readonly T[], concurrency: number, fn: (item: T, index: number) => Promise<R>): Promise<R[]>;
19
- //# sourceMappingURL=encoding.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"encoding.d.ts","sourceRoot":"","sources":["../src/encoding.ts"],"names":[],"mappings":"AAcA,kDAAkD;AAClD,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAItD;AAED,sFAAsF;AACtF,wBAAgB,eAAe,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAIlD;AAED;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAUjE;AAED,iFAAiF;AACjF,wBAAsB,aAAa,CAAC,CAAC,EAAE,CAAC,EACtC,KAAK,EAAE,SAAS,CAAC,EAAE,EACnB,WAAW,EAAE,MAAM,EACnB,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,GACzC,OAAO,CAAC,CAAC,EAAE,CAAC,CAYd"}
package/dist/encoding.js DELETED
@@ -1,64 +0,0 @@
1
- // Copyright (c) 2024-2026 Argento Computing Inc. Licensed under the MIT License. See LICENSE.
2
- /**
3
- * @mikeargento/bitgraph-mcp: digest encoding and file hashing.
4
- *
5
- * BitGraph uses two base64 forms for the same SHA-256 digest:
6
- * standard base64 with padding inside proof objects and commit requests,
7
- * URL-safe unpadded base64 in API lookups, S3 keys, and proof page URLs.
8
- */
9
- import { createHash } from "node:crypto";
10
- import { createReadStream } from "node:fs";
11
- import { stat } from "node:fs/promises";
12
- /** Standard base64 → URL-safe unpadded base64. */
13
- export function toUrlSafeB64(b64) {
14
- return b64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
15
- }
16
- /**
17
- * URL-safe base64 → standard base64 with padding.
18
- * A no-op (apart from re-padding) when the input is already standard base64,
19
- * so it is safe to call on either form.
20
- */
21
- export function fromUrlSafeB64(urlSafe) {
22
- let b64 = urlSafe.replace(/-/g, "+").replace(/_/g, "/");
23
- while (b64.length % 4 !== 0)
24
- b64 += "=";
25
- return b64;
26
- }
27
- /** True if the string plausibly encodes 32 bytes of SHA-256 in either base64 form. */
28
- export function looksLikeDigest(s) {
29
- const normalized = fromUrlSafeB64(s.trim());
30
- if (!/^[A-Za-z0-9+/]{43}=$/.test(normalized))
31
- return false;
32
- return Buffer.from(normalized, "base64").length === 32;
33
- }
34
- /**
35
- * SHA-256 of a file's bytes as standard base64.
36
- * Streams from disk, so file size is not a memory concern. Only this digest
37
- * ever leaves the machine; file contents are never uploaded.
38
- */
39
- export async function sha256FileB64(path) {
40
- const info = await stat(path);
41
- if (!info.isFile()) {
42
- throw new Error(`Not a regular file: ${path}`);
43
- }
44
- const hash = createHash("sha256");
45
- for await (const chunk of createReadStream(path)) {
46
- hash.update(chunk);
47
- }
48
- return hash.digest("base64");
49
- }
50
- /** Run an async mapper over items with bounded concurrency, preserving order. */
51
- export async function mapConcurrent(items, concurrency, fn) {
52
- const results = new Array(items.length);
53
- let next = 0;
54
- async function worker() {
55
- while (next < items.length) {
56
- const index = next++;
57
- results[index] = await fn(items[index], index);
58
- }
59
- }
60
- const workers = Array.from({ length: Math.min(concurrency, items.length) }, () => worker());
61
- await Promise.all(workers);
62
- return results;
63
- }
64
- //# sourceMappingURL=encoding.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"encoding.js","sourceRoot":"","sources":["../src/encoding.ts"],"names":[],"mappings":"AAAA,8FAA8F;AAE9F;;;;;;GAMG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAC3C,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAExC,kDAAkD;AAClD,MAAM,UAAU,YAAY,CAAC,GAAW;IACtC,OAAO,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AACxE,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,OAAe;IAC5C,IAAI,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IACxD,OAAO,GAAG,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC;QAAE,GAAG,IAAI,GAAG,CAAC;IACxC,OAAO,GAAG,CAAC;AACb,CAAC;AAED,sFAAsF;AACtF,MAAM,UAAU,eAAe,CAAC,CAAS;IACvC,MAAM,UAAU,GAAG,cAAc,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IAC5C,IAAI,CAAC,sBAAsB,CAAC,IAAI,CAAC,UAAU,CAAC;QAAE,OAAO,KAAK,CAAC;IAC3D,OAAO,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC,MAAM,KAAK,EAAE,CAAC;AACzD,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAAY;IAC9C,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC;IAC9B,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;QACnB,MAAM,IAAI,KAAK,CAAC,uBAAuB,IAAI,EAAE,CAAC,CAAC;IACjD,CAAC;IACD,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;IAClC,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,gBAAgB,CAAC,IAAI,CAAC,EAAE,CAAC;QACjD,IAAI,CAAC,MAAM,CAAC,KAAe,CAAC,CAAC;IAC/B,CAAC;IACD,OAAO,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;AAC/B,CAAC;AAED,iFAAiF;AACjF,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,KAAmB,EACnB,WAAmB,EACnB,EAA0C;IAE1C,MAAM,OAAO,GAAQ,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC7C,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,KAAK,UAAU,MAAM;QACnB,OAAO,IAAI,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;YAC3B,MAAM,KAAK,GAAG,IAAI,EAAE,CAAC;YACrB,OAAO,CAAC,KAAK,CAAC,GAAG,MAAM,EAAE,CAAC,KAAK,CAAC,KAAK,CAAM,EAAE,KAAK,CAAC,CAAC;QACtD,CAAC;IACH,CAAC;IACD,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,KAAK,CAAC,MAAM,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC;IAC5F,MAAM,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAC3B,OAAO,OAAO,CAAC;AACjB,CAAC"}
package/dist/scan.d.ts DELETED
@@ -1,60 +0,0 @@
1
- /**
2
- * @mikeargento/bitgraph-mcp: the scan.
3
- *
4
- * One pass over each file yields its SHA-256 (the member's origin) and a
5
- * hasher left open after the placement's prefix and the file's last byte, so
6
- * the member's fused digest can be finished later, for whatever slot the set
7
- * is made under, without reading the file again. A placement is prefix,
8
- * original, suffix (its frame): trailer/1 has no prefix and container/2's is
9
- * the original's tar header, which depends on the size alone; the suffix
10
- * carries the commitment and is hashed at BitGraph time. Node's SHA-256 is
11
- * the platform's own, and a Hash can be copied mid-stream, which is the whole
12
- * trick: the copy takes the suffix, so no file is read twice or held in
13
- * memory, and the original is never touched.
14
- */
15
- import { type Hash } from "node:crypto";
16
- /** The placements the scan makes: chosen from the bytes by the core, never from the name. */
17
- export type ScanPlacement = "trailer/1" | "container/2";
18
- export interface ScannedFile {
19
- path: string;
20
- name: string;
21
- size: number;
22
- /** SHA-256 of the file, standard base64: the member's origin. */
23
- digestB64: string;
24
- originDigest: Uint8Array;
25
- placement: ScanPlacement;
26
- /**
27
- * The hasher after the placement's prefix and the file's bytes, still open.
28
- * Null when the file's length changed while it was read: its fused digest
29
- * then needs the bytes again.
30
- */
31
- state: Hash | null;
32
- /** True when the bytes carry what looks like a C2PA manifest (Content Credentials). */
33
- c2pa: boolean;
34
- }
35
- /** One-shot form for bytes already in memory (a carrier's committed bytes). */
36
- export declare function sniffC2paBytes(bytes: Uint8Array): boolean;
37
- /** Hash one file in a single pass. Throws, before any network call, when the path is not a regular file. */
38
- export declare function scanFile(path: string): Promise<ScannedFile>;
39
- /**
40
- * A member's fused digest for a slot: the open hasher, copied, finished with
41
- * the placement's suffix for that slot's commitment. The hash of prefix,
42
- * original, suffix is exactly the hash of the placement's own build, which
43
- * a test pins.
44
- */
45
- export declare function fusedDigestFor(file: ScannedFile, commitment: Uint8Array): Uint8Array;
46
- export interface Expansion {
47
- /** Regular files in the order given; a directory contributes its files sorted by name, depth first. */
48
- files: string[];
49
- /** How many of the inputs were directories. */
50
- directories: number;
51
- }
52
- /**
53
- * Paths to files: a regular file is itself; a directory is every regular
54
- * file under it, recursively, with hidden entries (names starting with a
55
- * dot) and symbolic links left out. The same file twice is one file. A path
56
- * that is missing or neither kind, or more than `limit` files in all, throws
57
- * before any network call; the message names every path that failed.
58
- */
59
- export declare function expandPaths(paths: readonly string[], limit: number): Promise<Expansion>;
60
- //# sourceMappingURL=scan.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"scan.d.ts","sourceRoot":"","sources":["../src/scan.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAc,KAAK,IAAI,EAAE,MAAM,aAAa,CAAC;AAOpD,6FAA6F;AAC7F,MAAM,MAAM,aAAa,GAAG,WAAW,GAAG,aAAa,CAAC;AAExD,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,iEAAiE;IACjE,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,UAAU,CAAC;IACzB,SAAS,EAAE,aAAa,CAAC;IACzB;;;;OAIG;IACH,KAAK,EAAE,IAAI,GAAG,IAAI,CAAC;IACnB,uFAAuF;IACvF,IAAI,EAAE,OAAO,CAAC;CACf;AAuCD,+EAA+E;AAC/E,wBAAgB,cAAc,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAEzD;AAKD,4GAA4G;AAC5G,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAuDjE;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU,GAAG,UAAU,CAMpF;AAED,MAAM,WAAW,SAAS;IACxB,uGAAuG;IACvG,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,+CAA+C;IAC/C,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;GAMG;AACH,wBAAsB,WAAW,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CA2C7F"}
package/dist/scan.js DELETED
@@ -1,201 +0,0 @@
1
- // Copyright (c) 2024-2026 Argento Computing Inc. Licensed under the MIT License. See LICENSE.
2
- /**
3
- * @mikeargento/bitgraph-mcp: the scan.
4
- *
5
- * One pass over each file yields its SHA-256 (the member's origin) and a
6
- * hasher left open after the placement's prefix and the file's last byte, so
7
- * the member's fused digest can be finished later, for whatever slot the set
8
- * is made under, without reading the file again. A placement is prefix,
9
- * original, suffix (its frame): trailer/1 has no prefix and container/2's is
10
- * the original's tar header, which depends on the size alone; the suffix
11
- * carries the commitment and is hashed at BitGraph time. Node's SHA-256 is
12
- * the platform's own, and a Hash can be copied mid-stream, which is the whole
13
- * trick: the copy takes the suffix, so no file is read twice or held in
14
- * memory, and the original is never touched.
15
- */
16
- import { createHash } from "node:crypto";
17
- import { createReadStream } from "node:fs";
18
- import { readdir, stat } from "node:fs/promises";
19
- import { basename, join } from "node:path";
20
- import { placementForBytes } from "@mikeargento/bitgraph";
21
- import { getPlacement } from "@mikeargento/bitgraph-verify";
22
- /**
23
- * Content Credentials detection, structural and cheap: a C2PA manifest lives
24
- * in a JUMBF box whose description ("jumd") is followed within a few bytes by
25
- * the store label "c2pa", in every container (JPEG APP11, PNG caBX, ISO BMFF).
26
- * Requiring the pair in order and near each other keeps a stray "c2pa" in
27
- * prose from counting. Detection, not judgment: the proof page parses and
28
- * displays the manifest itself.
29
- */
30
- const JUMD = Buffer.from("jumd", "ascii");
31
- const C2PA_LABEL = Buffer.from("c2pa", "ascii");
32
- const C2PA_NEAR = 96;
33
- function windowHasC2pa(buf) {
34
- for (let i = buf.indexOf(JUMD); i !== -1; i = buf.indexOf(JUMD, i + 1)) {
35
- const from = i + JUMD.length;
36
- const to = Math.min(buf.length, i + C2PA_NEAR);
37
- if (buf.subarray(from, to).indexOf(C2PA_LABEL) !== -1)
38
- return true;
39
- }
40
- return false;
41
- }
42
- class C2paSniffer {
43
- found = false;
44
- /** The last C2PA_NEAR + 4 bytes of the previous chunk, so a pair split across chunks is seen whole. */
45
- carry = Buffer.alloc(0);
46
- update(chunk) {
47
- if (this.found)
48
- return;
49
- const buf = this.carry.length > 0 ? Buffer.concat([this.carry, chunk]) : chunk;
50
- if (windowHasC2pa(buf)) {
51
- this.found = true;
52
- return;
53
- }
54
- const keep = Math.min(buf.length, C2PA_NEAR + JUMD.length);
55
- this.carry = Buffer.from(buf.subarray(buf.length - keep));
56
- }
57
- }
58
- /** One-shot form for bytes already in memory (a carrier's committed bytes). */
59
- export function sniffC2paBytes(bytes) {
60
- return windowHasC2pa(Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength));
61
- }
62
- /** Bytes the placement decision reads: every magic number sits in the first 16. */
63
- const SNIFF = 64;
64
- /** Hash one file in a single pass. Throws, before any network call, when the path is not a regular file. */
65
- export async function scanFile(path) {
66
- const info = await stat(path);
67
- if (!info.isFile())
68
- throw new Error(`Not a regular file: ${path}`);
69
- const size = info.size;
70
- const origin = createHash("sha256");
71
- // Held in one object: the closures below assign to it.
72
- const run = { fused: null, placement: null };
73
- let head = null;
74
- let bytes = 0;
75
- const start = (p) => {
76
- run.placement = p;
77
- // A second hasher runs over prefix and bytes when the prefix is not
78
- // empty; with an empty prefix the origin hasher's own state is the fused state.
79
- const prefix = getPlacement(p)?.scanPrefix?.(size) ?? null;
80
- if (prefix !== null && prefix.length > 0)
81
- run.fused = createHash("sha256").update(prefix);
82
- };
83
- const sniffer = new C2paSniffer();
84
- const feed = (chunk) => {
85
- origin.update(chunk);
86
- if (run.fused !== null)
87
- run.fused.update(chunk);
88
- sniffer.update(chunk);
89
- };
90
- for await (const raw of createReadStream(path)) {
91
- const chunk = raw;
92
- if (run.placement === null) {
93
- head = head === null ? chunk : Buffer.concat([head, chunk]);
94
- if (head.length >= SNIFF) {
95
- start(placementForBytes(new Uint8Array(head.subarray(0, SNIFF))));
96
- feed(head);
97
- head = null;
98
- }
99
- }
100
- else {
101
- feed(chunk);
102
- }
103
- bytes += chunk.length;
104
- }
105
- if (run.placement === null) {
106
- // A short file: decide from what there is, then hash it.
107
- start(placementForBytes(new Uint8Array(head ?? Buffer.alloc(0))));
108
- if (head !== null)
109
- feed(head);
110
- }
111
- const placement = run.placement;
112
- const state = bytes !== size ? null : (run.fused ?? origin);
113
- // When the origin hasher is the state its digest is taken from a copy, so it stays open.
114
- const digest = state === origin ? origin.copy().digest() : origin.digest();
115
- return {
116
- path,
117
- name: basename(path),
118
- size,
119
- digestB64: digest.toString("base64"),
120
- originDigest: Uint8Array.from(digest),
121
- placement,
122
- state,
123
- c2pa: sniffer.found,
124
- };
125
- }
126
- /**
127
- * A member's fused digest for a slot: the open hasher, copied, finished with
128
- * the placement's suffix for that slot's commitment. The hash of prefix,
129
- * original, suffix is exactly the hash of the placement's own build, which
130
- * a test pins.
131
- */
132
- export function fusedDigestFor(file, commitment) {
133
- if (file.state === null)
134
- throw new Error(`${file.path}: the file changed while it was read`);
135
- const placement = getPlacement(file.placement);
136
- if (placement?.frame === undefined)
137
- throw new Error(`placement ${file.placement} has no frame`);
138
- const { suffix } = placement.frame({ originalSize: file.size, originDigest: file.originDigest, commitment });
139
- return Uint8Array.from(file.state.copy().update(suffix).digest());
140
- }
141
- /**
142
- * Paths to files: a regular file is itself; a directory is every regular
143
- * file under it, recursively, with hidden entries (names starting with a
144
- * dot) and symbolic links left out. The same file twice is one file. A path
145
- * that is missing or neither kind, or more than `limit` files in all, throws
146
- * before any network call; the message names every path that failed.
147
- */
148
- export async function expandPaths(paths, limit) {
149
- const files = [];
150
- const seen = new Set();
151
- const failures = [];
152
- let directories = 0;
153
- const push = (p) => {
154
- if (seen.has(p))
155
- return;
156
- seen.add(p);
157
- files.push(p);
158
- if (files.length > limit)
159
- throw new Error(`more than ${limit} files; BitGraph fewer at a time`);
160
- };
161
- const walk = async (dir) => {
162
- const entries = (await readdir(dir, { withFileTypes: true }))
163
- .filter((e) => !e.name.startsWith("."))
164
- .sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));
165
- for (const e of entries) {
166
- const full = join(dir, e.name);
167
- if (e.isSymbolicLink())
168
- continue;
169
- if (e.isDirectory())
170
- await walk(full);
171
- else if (e.isFile())
172
- push(full);
173
- }
174
- };
175
- for (const p of paths) {
176
- try {
177
- const info = await stat(p);
178
- if (info.isDirectory()) {
179
- directories += 1;
180
- await walk(p);
181
- }
182
- else if (info.isFile()) {
183
- push(p);
184
- }
185
- else {
186
- throw new Error("not a regular file or a directory");
187
- }
188
- }
189
- catch (err) {
190
- const message = err instanceof Error ? err.message : String(err);
191
- if (message.startsWith("more than "))
192
- throw err;
193
- failures.push(`${p}: ${message}`);
194
- }
195
- }
196
- if (failures.length > 0) {
197
- throw new Error(`Could not read ${failures.length} path(s); nothing was BitGraphed.\n${failures.join("\n")}\nUse absolute paths to existing regular files or directories.`);
198
- }
199
- return { files, directories };
200
- }
201
- //# sourceMappingURL=scan.js.map
package/dist/scan.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"scan.js","sourceRoot":"","sources":["../src/scan.ts"],"names":[],"mappings":"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"}
package/dist/task.d.ts DELETED
@@ -1,55 +0,0 @@
1
- import type { BitGraphProof, SlotAllocation } from "@mikeargento/bitgraph-verify";
2
- import { type ApiConfig } from "./api.js";
3
- export declare const SLOT_TTL_SECONDS = 120;
4
- export interface TaskState {
5
- v: 1;
6
- task: true;
7
- slot: SlotAllocation;
8
- }
9
- export declare function encodeTaskToken(state: TaskState): string;
10
- export declare function decodeTaskToken(token: string): TaskState | null;
11
- export interface Begun {
12
- token: string;
13
- /** Unpadded base64url: the string to put into the task. */
14
- commitment: string;
15
- commitmentB64: string;
16
- slotCounter: string;
17
- epoch: string;
18
- floor: {
19
- block: number;
20
- } | null;
21
- }
22
- /** Step one of the task form: a held slot and its commitment, before any work exists. */
23
- export declare function beginTask(config: ApiConfig): Promise<Begun>;
24
- export interface SealedTask {
25
- proof: BitGraphProof;
26
- artifactDigestB64: string;
27
- /** Byte offsets of the commitment string inside the task bytes, when the bytes were given. */
28
- offsets: number[] | null;
29
- }
30
- /**
31
- * Step two: the task bytes (a path, or the bytes themselves) sealed under
32
- * the held slot with the inline marker. When the bytes are in hand the
33
- * commitment is looked for BEFORE the commit, so a task that does not carry
34
- * it is refused without spending the slot.
35
- */
36
- export declare function sealTask(config: ApiConfig, state: TaskState, task: {
37
- path: string;
38
- } | {
39
- bytes: Uint8Array;
40
- } | {
41
- digestB64: string;
42
- }): Promise<SealedTask>;
43
- export declare const TASK_INSTRUCTIONS: string;
44
- /**
45
- * Write a sealed task's proof beside the file it is about, whole, and say
46
- * where. `make_task.txt` gets `make_task.proof.json`; a name already taken
47
- * gets the position's counter in it rather than being overwritten.
48
- *
49
- * ⚠️ THE SERVER WRITES IT, NOT THE AGENT. Handed the JSON to save, an agent
50
- * tidied it and dropped slotAllocation and environment, and the signature
51
- * had no body left to be checked against (Grok, 2026-09-13). A file this
52
- * process writes is the proof exactly as the boundary returned it.
53
- */
54
- export declare function writeProofBeside(sealedPath: string, proof: BitGraphProof): Promise<string>;
55
- //# sourceMappingURL=task.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"task.d.ts","sourceRoot":"","sources":["../src/task.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAClF,OAAO,EAAY,KAAK,SAAS,EAAE,MAAM,UAAU,CAAC;AAGpD,eAAO,MAAM,gBAAgB,MAAM,CAAC;AAKpC,MAAM,WAAW,SAAS;IACxB,CAAC,EAAE,CAAC,CAAC;IACL,IAAI,EAAE,IAAI,CAAC;IACX,IAAI,EAAE,cAAc,CAAC;CACtB;AASD,wBAAgB,eAAe,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAExD;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAO/D;AAkBD,MAAM,WAAW,KAAK;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,2DAA2D;IAC3D,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;CACjC;AAED,yFAAyF;AACzF,wBAAsB,SAAS,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,KAAK,CAAC,CAcjE;AAED,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,aAAa,CAAC;IACrB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,8FAA8F;IAC9F,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;CAC1B;AAED;;;;;GAKG;AACH,wBAAsB,QAAQ,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,KAAK,EAAE,UAAU,CAAA;CAAE,GAAG;IAAE,SAAS,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,UAAU,CAAC,CA4B/J;AAkBD,eAAO,MAAM,iBAAiB,QAK0J,CAAC;AAEzL;;;;;;;;;GASG;AACH,wBAAsB,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CAWhG"}