@mikeargento/bitgraph-player 0.5.1 → 0.6.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 (50) hide show
  1. package/DOMAIN.md +119 -0
  2. package/README.md +25 -5
  3. package/dist/__tests__/domain.test.d.ts +2 -0
  4. package/dist/__tests__/domain.test.d.ts.map +1 -0
  5. package/dist/__tests__/domain.test.js +265 -0
  6. package/dist/__tests__/domain.test.js.map +1 -0
  7. package/dist/check.d.ts +45 -2
  8. package/dist/check.d.ts.map +1 -1
  9. package/dist/check.js +94 -7
  10. package/dist/check.js.map +1 -1
  11. package/dist/cli.js +194 -12
  12. package/dist/cli.js.map +1 -1
  13. package/dist/domain.d.ts +64 -0
  14. package/dist/domain.d.ts.map +1 -0
  15. package/dist/domain.js +212 -0
  16. package/dist/domain.js.map +1 -0
  17. package/dist/index.d.ts +5 -1
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +2 -0
  20. package/dist/index.js.map +1 -1
  21. package/dist/pin.d.ts +55 -0
  22. package/dist/pin.d.ts.map +1 -0
  23. package/dist/pin.js +126 -0
  24. package/dist/pin.js.map +1 -0
  25. package/dist/play.d.ts +6 -1
  26. package/dist/play.d.ts.map +1 -1
  27. package/dist/play.js +6 -1
  28. package/dist/play.js.map +1 -1
  29. package/dist/sig.d.ts +2 -0
  30. package/dist/sig.d.ts.map +1 -1
  31. package/dist/sig.js +1 -1
  32. package/dist/sig.js.map +1 -1
  33. package/dist/types.d.ts +7 -0
  34. package/dist/types.d.ts.map +1 -1
  35. package/dist/types.js +7 -0
  36. package/dist/types.js.map +1 -1
  37. package/dist/verdict.d.ts +1 -1
  38. package/dist/verdict.js +1 -1
  39. package/dist-web/verify.html +3 -3
  40. package/package.json +4 -3
  41. package/src/__tests__/domain.test.ts +321 -0
  42. package/src/check.ts +149 -9
  43. package/src/cli.ts +199 -12
  44. package/src/domain.ts +245 -0
  45. package/src/index.ts +17 -1
  46. package/src/pin.ts +155 -0
  47. package/src/play.ts +6 -1
  48. package/src/sig.ts +1 -1
  49. package/src/types.ts +8 -0
  50. package/src/verdict.ts +1 -1
package/DOMAIN.md ADDED
@@ -0,0 +1,119 @@
1
+ # BitGraph Domain
2
+
3
+ A BitGraph Domain is a party's own domain publishing the keys that record
4
+ for it. A reader pins the domain once; `bitgraph-play check --from
5
+ <domain>` then answers offline, from the export in hand and the pin on
6
+ disk, whether a file holds a recorded position under a key the domain
7
+ published.
8
+
9
+ The domain's file is the party speaking for itself, never BitGraph
10
+ speaking about the party. A proof carries a key and nothing else. Which
11
+ domains to pin, and what to make of them, belongs to each reader; a
12
+ domain's file is one source among any number, never an authority.
13
+
14
+ ## The file: `bitgraph-domain/1`
15
+
16
+ Served over HTTPS at `https://<domain>/.well-known/bitgraph`, at most
17
+ 64 KiB:
18
+
19
+ ```json
20
+ {
21
+ "version": "bitgraph-domain/1",
22
+ "domain": "acme.com",
23
+ "party": "Acme Corp",
24
+ "keys": {
25
+ "invoices": { "alg": "es256", "publicKey": "<SPKI DER, base64>" },
26
+ "press": { "alg": "ed25519", "publicKey": "<raw 32 bytes, base64>" }
27
+ }
28
+ }
29
+ ```
30
+
31
+ - `version` is exactly `"bitgraph-domain/1"`. The discriminator field is
32
+ `version`, as in `bitgraph/1` proofs, because `domain` is the file's own
33
+ subject field. Unknown fields are a parse error; additions are a new
34
+ format version.
35
+ - `domain` is a lowercase hostname: no scheme, no port, no path. At pin
36
+ time it must equal the domain the reader asked for, so a redirect cannot
37
+ cause one party's file to be stored under another party's name.
38
+ - `party` is the name the domain gives itself. Display only; the domain is
39
+ the binding.
40
+ - `keys` is a nonempty object. Names follow the trusted-key grammar of
41
+ SPEC.md section 9.1 (`[A-Za-z0-9_.-]+`, at least one non-digit, unique),
42
+ and each entry is exactly a section 9.1 trusted-key body: for `es256`
43
+ the publicKey is SPKI DER in base64, the spelling actor proofs carry;
44
+ for `ed25519` it is the raw 32-byte key in base64. An entry therefore
45
+ pastes into a format 2 rule's `trustedKeys` unchanged.
46
+
47
+ A key's **fingerprint** is the lowercase hex SHA-256 of the decoded
48
+ publicKey bytes. For `es256` keys this is exactly the `keyId` actor proofs
49
+ carry. Fingerprints are always derived and never written in the file, so a
50
+ domain cannot claim a key it does not show.
51
+
52
+ ## Pin
53
+
54
+ `bitgraph-play pin <domain>` fetches the file, prints the party and every
55
+ key's name, algorithm and fingerprint, and stores the file bytes verbatim
56
+ on the reader's machine after confirmation. Pinning is the only step that
57
+ touches the network, once per domain. Pinning again shows what changed,
58
+ added, removed or replaced keys, before asking again. `pin` alone lists
59
+ stored pins; `pin --forget <domain>` removes one.
60
+
61
+ A malformed file is refused at the pin, so a check never reads a bad one.
62
+ `check --from` never fetches; `--from` naming a domain with no stored pin
63
+ is an invocation error (exit 3) whose remedy is the pin command, because a
64
+ reader's missing setup is not evidence and gets no verdict.
65
+
66
+ ## The domain line
67
+
68
+ With `--from <domain>`, one line joins the check report for each
69
+ recording.
70
+
71
+ TRUE when the recording verifies and either
72
+
73
+ - its actor's `keyId` equals the fingerprint of an `es256` key in the
74
+ pinned file, or
75
+ - a `bitgraph-sig/1` file among the bundle's candidate signature files
76
+ (SPEC.md section 9.4) verifies over the recording's digest under any
77
+ pinned key.
78
+
79
+ UNDETERMINED otherwise. **The domain line is never FALSE**, by the same
80
+ open-world rule as `signedBy` (SPEC.md section 9.3): domain evidence can
81
+ exist outside any bundle, so its absence contradicts nothing. Evidence in
82
+ hand that contradicts the recording itself already reads FALSE on the
83
+ existing lines; the domain line does not restate them.
84
+
85
+ An enclave epoch key listed in a domain's file matches nothing: it is not
86
+ an actor key, and the enclave never signs the domain-separated
87
+ bitgraph-sig message. Exit codes are unchanged; the line joins the
88
+ report's conjunction.
89
+
90
+ ## What it establishes, and the cost
91
+
92
+ TRUE establishes that a key published by the domain stands behind a
93
+ recording of exactly these bytes at a fixed causal position. Not
94
+ authorship: anyone can record a file they downloaded, under any key they
95
+ hold. Not content. Not exclusivity: the same bytes may hold other
96
+ positions, under other keys or none. The statement is as strong as the
97
+ domain and the keys behind it: a stolen key keeps the domain's standing
98
+ until it is removed and readers pin again.
99
+
100
+ Publishing a key names it in public, retroactively: every recording the
101
+ key has ever made or will make reads as the party's, positions and volume
102
+ included, and pins outlive the file that provided them. Only digests
103
+ travel, so no content is exposed, and unpublished keys and anonymous
104
+ recordings are untouched. Publish keys dedicated to what you intend to
105
+ stand behind, named for their purpose. A published key is per purpose,
106
+ never per document: the per-document evidence is the signature each
107
+ recording already carries, and a pin only works because the keys it
108
+ stores outlive it. Attribution without public grouping is the other
109
+ posture, and it needs no domain file: record under an unpublished key and
110
+ hand the counterparty the evidence directly; they declare the key in
111
+ their own rule's `trustedKeys`.
112
+
113
+ ## Relation to the specification
114
+
115
+ Evaluation semantics (SPEC.md sections 1 through 9) are untouched. The
116
+ domain file shares section 9.1's key grammar, section 9.3's open-world
117
+ rule and section 9.4's candidate discipline; `check` remains the section
118
+ 8 convenience surface, and its report format adds the domain entry as
119
+ `bitgraph-check/2`.
package/README.md CHANGED
@@ -52,6 +52,25 @@ same code. It is not hosted anywhere: the site's own drop box checks a file
52
52
  against the public ledger, and a second box that could only say
53
53
  "self-consistent" would be two boxes with different meanings.
54
54
 
55
+ ## Pin a domain
56
+
57
+ bitgraph-play pin acme.com
58
+ bitgraph-play check "BitGraph (invoice-4471.pdf)/" --from acme.com
59
+
60
+ A domain can publish the keys that record for it: one `bitgraph-domain/1`
61
+ file at `https://<domain>/.well-known/bitgraph` (the format is in
62
+ [DOMAIN.md](./DOMAIN.md)). `pin` fetches it once, shows the party and
63
+ every key's fingerprint, and stores the bytes verbatim on your machine
64
+ after you confirm; it is the only command in this package that touches
65
+ the network, and only when invoked. `check --from` then adds one line per
66
+ recording, offline, from the pin on disk: TRUE when the recording
67
+ verifies and a pinned key stands behind it, as the actor inside the proof
68
+ or as a detached `bitgraph-sig/1` in the bundle; UNDETERMINED otherwise;
69
+ and never FALSE, because domain evidence can exist outside any bundle,
70
+ so its absence contradicts nothing. Pinning again shows what changed
71
+ before you accept it. `pin` alone lists your pins; `pin --forget
72
+ <domain>` removes one.
73
+
55
74
  ## Start a rule
56
75
 
57
76
  bitgraph-play init po.pdf delivery.jpg approval.pdf --out rule.json
@@ -64,11 +83,12 @@ rule's own security policy and has no default, from the scaffolder or
64
83
  anywhere else. Choose the floor, say what each digest means, refine the
65
84
  claim, then run it.
66
85
 
67
- `init` is a reserved first word as of 0.2.0. A rule file literally
68
- named `init` is still reachable: write it as `./init`, or after `--`,
69
- which ends option parsing (`bitgraph-play -- init bundle/`). When a
70
- file named `init` exists in the working directory, the bare spelling is
71
- refused as ambiguous rather than silently picking a mode.
86
+ `init` is a reserved first word as of 0.2.0, `check` as of 0.4.0, and
87
+ `pin` as of 0.6.0. A rule file literally named like one of them is still
88
+ reachable: write it as `./init`, or after `--`, which ends option
89
+ parsing (`bitgraph-play -- init bundle/`). When a file with one of those
90
+ names exists in the working directory, the bare spelling is refused as
91
+ ambiguous rather than silently picking a mode.
72
92
 
73
93
  ## A rule
74
94
 
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=domain.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"domain.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/domain.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,265 @@
1
+ // Copyright (c) 2024-2026 Mike Argento. Licensed under the MIT License. See LICENSE.
2
+ /**
3
+ * BitGraph Domain: parseDomainFile, fingerprints, the pin store, the
4
+ * fetch, and check --from's "domain" line.
5
+ *
6
+ * The invariants under test:
7
+ * - The domain line is TRUE or UNDETERMINED, never FALSE: absence of
8
+ * domain evidence contradicts nothing (SPEC §9.3's open-world rule).
9
+ * - Fingerprints are always derived from key material, never read from
10
+ * the file; for es256 the fingerprint IS the actor keyId, proved
11
+ * against the real declared recording (fixtures/declared-12010).
12
+ * - A malformed file is refused at the pin, and a redirect cannot store
13
+ * one party's file under another party's name (the `domain` field
14
+ * must equal the domain the reader asked for).
15
+ * - A report without --from stays bitgraph-check/1 with no `from` key.
16
+ *
17
+ * Everything runs in memory or under a temp dir. The fetch is injected;
18
+ * no network, no ledger writes, ever.
19
+ */
20
+ import { strict as assert } from "node:assert";
21
+ import { createHash, generateKeyPairSync, sign as cryptoSign } from "node:crypto";
22
+ import { mkdtempSync, readFileSync, rmSync } from "node:fs";
23
+ import { tmpdir } from "node:os";
24
+ import { join } from "node:path";
25
+ import { test } from "node:test";
26
+ import { ingestEntries } from "@mikeargento/bitgraph-audit";
27
+ import { checkIngest } from "../check.js";
28
+ import { checkDomain, diffDomainFiles, DomainFileError, domainKeyRefs, isDomainName, keyFingerprint, parseDomainFile, } from "../domain.js";
29
+ import { fetchDomainFile, forgetPin, listPins, readPin, writePin } from "../pin.js";
30
+ import { sigMessage } from "../sig.js";
31
+ // ---------------------------------------------------------------------------
32
+ // The real declared recording: actor key ee0c6517…, provider passkey
33
+ // ---------------------------------------------------------------------------
34
+ const proofBytes = readFileSync(new URL("../../src/__tests__/fixtures/declared-12010/proof.json", import.meta.url));
35
+ const proofJson = JSON.parse(proofBytes.toString("utf8"));
36
+ const ACTOR_KEY_B64 = proofJson.agency.actor.publicKeyB64;
37
+ const ACTOR_KEY_ID = proofJson.agency.actor.keyId;
38
+ const DIGEST_HEX = Buffer.from(proofJson.artifact.digestB64, "base64").toString("hex");
39
+ function domainText(overrides) {
40
+ return JSON.stringify({
41
+ version: "bitgraph-domain/1",
42
+ domain: "acme.com",
43
+ party: "Acme Corp",
44
+ keys: { studio: { alg: "es256", publicKey: ACTOR_KEY_B64 } },
45
+ ...overrides,
46
+ });
47
+ }
48
+ async function ingestProof(bytes = proofBytes) {
49
+ return ingestEntries([{ path: "proof.json", open: () => Promise.resolve(new Uint8Array(bytes)) }]);
50
+ }
51
+ function onlyRecording(report) {
52
+ assert.equal(report.recordings.length, 1);
53
+ return report.recordings[0];
54
+ }
55
+ function domainLineOf(recording) {
56
+ const line = recording.lines.find((l) => l.name === "domain");
57
+ assert.notEqual(line, undefined, "expected a domain line");
58
+ return line;
59
+ }
60
+ // ---------------------------------------------------------------------------
61
+ // Parsing and fingerprints
62
+ // ---------------------------------------------------------------------------
63
+ test("parseDomainFile accepts a valid file and derives the party/keys", () => {
64
+ const file = parseDomainFile(domainText(), "acme.com");
65
+ assert.equal(file.domain, "acme.com");
66
+ assert.equal(file.party, "Acme Corp");
67
+ assert.deepEqual(Object.keys(file.keys), ["studio"]);
68
+ });
69
+ test("isDomainName: lowercase dotted hostnames only", () => {
70
+ assert.equal(isDomainName("acme.com"), true);
71
+ assert.equal(isDomainName("sub.acme-corp.co.uk"), true);
72
+ assert.equal(isDomainName("ACME.com"), false);
73
+ assert.equal(isDomainName("acme"), false);
74
+ assert.equal(isDomainName("acme.com/path"), false);
75
+ assert.equal(isDomainName("https://acme.com"), false);
76
+ assert.equal(isDomainName("acme.com:443"), false);
77
+ assert.equal(isDomainName(""), false);
78
+ });
79
+ test("parseDomainFile refuses malformed files with every issue named", () => {
80
+ const bad = (text, expected) => {
81
+ try {
82
+ parseDomainFile(text, expected);
83
+ }
84
+ catch (err) {
85
+ assert.ok(err instanceof DomainFileError);
86
+ return [...err.issues];
87
+ }
88
+ assert.fail("expected DomainFileError");
89
+ };
90
+ assert.match(bad(domainText({ version: "bitgraph-domain/2" })).join(" "), /"version" must be exactly/);
91
+ assert.match(bad(domainText({ extra: 1 })).join(" "), /unknown field "extra"/);
92
+ assert.match(bad(domainText(), "other.example").join(" "), /refusing to store one party's file/);
93
+ assert.match(bad(domainText({ party: " " })).join(" "), /"party" is required/);
94
+ assert.match(bad(domainText({ keys: {} })).join(" "), /at least one key/);
95
+ assert.match(bad(domainText({ keys: { "1234": { alg: "es256", publicKey: ACTOR_KEY_B64 } } })).join(" "), /non-digit/);
96
+ assert.match(bad(domainText({ keys: { studio: { alg: "es256", publicKey: ACTOR_KEY_B64, note: "x" } } })).join(" "), /unknown field "note"/);
97
+ assert.match(bad(domainText({ keys: { studio: { alg: "rsa", publicKey: ACTOR_KEY_B64 } } })).join(" "), /"alg" must be/);
98
+ assert.match(bad(domainText({ keys: { studio: { alg: "es256", publicKey: "!!!" } } })).join(" "), /does not decode/);
99
+ assert.match(bad(domainText({ keys: { press: { alg: "ed25519", publicKey: Buffer.alloc(16).toString("base64") } } })).join(" "), /does not decode/);
100
+ assert.match(bad(domainText({ domain: "https://acme.com" })).join(" "), /lowercase hostname/);
101
+ // Oversize input is refused before parsing.
102
+ const big = new Uint8Array(70_000);
103
+ assert.throws(() => parseDomainFile(big), DomainFileError);
104
+ });
105
+ test("an es256 fingerprint IS the actor keyId (derived, never assigned)", () => {
106
+ assert.equal(keyFingerprint({ alg: "es256", publicKey: ACTOR_KEY_B64 }), ACTOR_KEY_ID);
107
+ const refs = domainKeyRefs(parseDomainFile(domainText()));
108
+ assert.deepEqual(refs.map((r) => [r.name, r.fingerprint]), [["studio", ACTOR_KEY_ID]]);
109
+ });
110
+ test("checkDomain resolves actor keyIds case-insensitively, es256 only", () => {
111
+ const from = checkDomain(parseDomainFile(domainText()));
112
+ assert.equal(from.actorKeyName(ACTOR_KEY_ID), "studio");
113
+ assert.equal(from.actorKeyName(ACTOR_KEY_ID.toUpperCase()), "studio");
114
+ assert.equal(from.actorKeyName("00".repeat(32)), undefined);
115
+ // An ed25519 key never actor-matches: actors are P-256.
116
+ const edPub = generateKeyPairSync("ed25519").publicKey.export({ type: "spki", format: "der" });
117
+ const edOnly = parseDomainFile(domainText({ keys: { press: { alg: "ed25519", publicKey: edPub.subarray(edPub.length - 32).toString("base64") } } }));
118
+ const edFingerprint = keyFingerprint(edOnly.keys["press"]);
119
+ assert.equal(checkDomain(edOnly).actorKeyName(edFingerprint), undefined);
120
+ });
121
+ // ---------------------------------------------------------------------------
122
+ // check --from: the domain line
123
+ // ---------------------------------------------------------------------------
124
+ test("check --from: the real declared recording reads TRUE under its published key", async () => {
125
+ const report = await checkIngest(await ingestProof(), { from: checkDomain(parseDomainFile(domainText())) });
126
+ assert.equal(report.check, "bitgraph-check/2");
127
+ assert.deepEqual(report.from, { domain: "acme.com", party: "Acme Corp" });
128
+ const line = domainLineOf(onlyRecording(report));
129
+ assert.equal(line.result, "TRUE");
130
+ assert.match(line.detail, /actor key "studio" · published by acme\.com \(Acme Corp\)/);
131
+ assert.ok(report.notChecked.some((n) => n.includes("pinned")));
132
+ });
133
+ test("check --from: a domain that never published the key reads UNDETERMINED, never FALSE", async () => {
134
+ const otherKey = generateKeyPairSync("ec", { namedCurve: "P-256" })
135
+ .publicKey.export({ type: "spki", format: "der" });
136
+ const from = checkDomain(parseDomainFile(domainText({ keys: { invoices: { alg: "es256", publicKey: otherKey.toString("base64") } } })));
137
+ const report = await checkIngest(await ingestProof(), { from });
138
+ const line = domainLineOf(onlyRecording(report));
139
+ assert.equal(line.result, "UNDETERMINED");
140
+ assert.match(line.detail, /is not among the 1 key\(s\) acme\.com publishes/);
141
+ });
142
+ test("check --from: a recording that does not verify gets an UNDETERMINED domain line", async () => {
143
+ const stripped = JSON.parse(proofBytes.toString("utf8"));
144
+ delete stripped["agency"];
145
+ const report = await checkIngest(await ingestProof(Buffer.from(JSON.stringify(stripped))), {
146
+ from: checkDomain(parseDomainFile(domainText())),
147
+ });
148
+ const recording = onlyRecording(report);
149
+ assert.equal(recording.lines.find((l) => l.name === "signature")?.result, "FALSE");
150
+ const line = domainLineOf(recording);
151
+ assert.equal(line.result, "UNDETERMINED");
152
+ assert.match(line.detail, /is not verified here/);
153
+ });
154
+ test("check --from: a detached bitgraph-sig/1 under a published ed25519 key reads TRUE", async () => {
155
+ const { publicKey, privateKey } = generateKeyPairSync("ed25519");
156
+ const spki = publicKey.export({ type: "spki", format: "der" });
157
+ const rawB64 = spki.subarray(spki.length - 32).toString("base64");
158
+ const signature = cryptoSign(null, sigMessage(DIGEST_HEX), privateKey).toString("base64");
159
+ const sigBytes = Buffer.from(JSON.stringify({
160
+ sig: "bitgraph-sig/1",
161
+ over: `sha256:${DIGEST_HEX}`,
162
+ alg: "ed25519",
163
+ publicKey: rawB64,
164
+ signature,
165
+ }));
166
+ const from = checkDomain(parseDomainFile(domainText({ keys: { press: { alg: "ed25519", publicKey: rawB64 } } })));
167
+ const sigEvidence = new Map([[createHash("sha256").update(sigBytes).digest("hex"), new Uint8Array(sigBytes)]]);
168
+ const report = await checkIngest(await ingestProof(), { from, sigEvidence });
169
+ const line = domainLineOf(onlyRecording(report));
170
+ assert.equal(line.result, "TRUE");
171
+ assert.match(line.detail, /signature by "press" · published by acme\.com/);
172
+ });
173
+ test("without --from the report stays bitgraph-check/1 with no from key and no domain line", async () => {
174
+ const report = await checkIngest(await ingestProof());
175
+ assert.equal(report.check, "bitgraph-check/1");
176
+ assert.equal("from" in report, false);
177
+ assert.equal(onlyRecording(report).lines.some((l) => l.name === "domain"), false);
178
+ });
179
+ // ---------------------------------------------------------------------------
180
+ // The pin store
181
+ // ---------------------------------------------------------------------------
182
+ test("pin store: write, read, list, forget; malformed pins are refused at read", () => {
183
+ const dir = mkdtempSync(join(tmpdir(), "bitgraph-pins-"));
184
+ try {
185
+ const path = writePin("acme.com", Buffer.from(domainText()), dir);
186
+ assert.ok(path.endsWith("acme.com"));
187
+ const pin = readPin("acme.com", dir);
188
+ assert.equal(pin?.file.party, "Acme Corp");
189
+ assert.equal(pin?.bytes.toString("utf8"), domainText());
190
+ // A stored file naming a different domain is refused: the store binds
191
+ // name to statement, so a bad write cannot impersonate.
192
+ writePin("evil.example", Buffer.from(domainText()), dir);
193
+ assert.throws(() => readPin("evil.example", dir), DomainFileError);
194
+ writePin("broken.example", Buffer.from("{"), dir);
195
+ assert.throws(() => readPin("broken.example", dir), DomainFileError);
196
+ const listed = listPins(dir);
197
+ assert.deepEqual(listed.map((p) => [p.domain, p.malformed]), [
198
+ ["acme.com", false],
199
+ ["broken.example", true],
200
+ ["evil.example", true],
201
+ ]);
202
+ assert.equal(listed[0]?.party, "Acme Corp");
203
+ assert.equal(listed[0]?.keyCount, 1);
204
+ assert.equal(forgetPin("acme.com", dir), true);
205
+ assert.equal(readPin("acme.com", dir), undefined);
206
+ assert.equal(forgetPin("acme.com", dir), false);
207
+ }
208
+ finally {
209
+ rmSync(dir, { recursive: true, force: true });
210
+ }
211
+ });
212
+ // ---------------------------------------------------------------------------
213
+ // The fetch (injected; the only networked verb)
214
+ // ---------------------------------------------------------------------------
215
+ function fakeFetch(body, status = 200) {
216
+ const urls = [];
217
+ const impl = (url) => {
218
+ urls.push(url);
219
+ return Promise.resolve({
220
+ ok: status >= 200 && status < 300,
221
+ status,
222
+ headers: { get: () => null },
223
+ arrayBuffer: () => {
224
+ const buf = Buffer.from(body);
225
+ return Promise.resolve(buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength));
226
+ },
227
+ });
228
+ };
229
+ return { impl, urls };
230
+ }
231
+ test("fetchDomainFile: fixed well-known path, verbatim bytes, strict domain binding", async () => {
232
+ const { impl, urls } = fakeFetch(domainText());
233
+ const fetched = await fetchDomainFile("acme.com", impl);
234
+ assert.deepEqual(urls, ["https://acme.com/.well-known/bitgraph"]);
235
+ assert.equal(fetched.file.party, "Acme Corp");
236
+ assert.equal(fetched.bytes.toString("utf8"), domainText());
237
+ // The served file names acme.com; pinning it as another.example must
238
+ // refuse: a redirect cannot repoint the name.
239
+ await assert.rejects(fetchDomainFile("another.example", fakeFetch(domainText()).impl), DomainFileError);
240
+ await assert.rejects(fetchDomainFile("acme.com", fakeFetch("nope", 404).impl), /HTTP 404/);
241
+ await assert.rejects(fetchDomainFile("acme.com", fakeFetch(Buffer.alloc(70_000)).impl), /the cap is/);
242
+ await assert.rejects(fetchDomainFile("https://acme.com", fakeFetch(domainText()).impl), /bare hostname/);
243
+ });
244
+ // ---------------------------------------------------------------------------
245
+ // Re-pin diffs
246
+ // ---------------------------------------------------------------------------
247
+ test("diffDomainFiles reports added, removed, changed, and a renamed party", () => {
248
+ const edPub = generateKeyPairSync("ed25519").publicKey.export({ type: "spki", format: "der" });
249
+ const edB64 = edPub.subarray(edPub.length - 32).toString("base64");
250
+ const before = parseDomainFile(domainText());
251
+ const after = parseDomainFile(domainText({
252
+ party: "Acme Corporation",
253
+ keys: {
254
+ studio: { alg: "ed25519", publicKey: edB64 },
255
+ press: { alg: "ed25519", publicKey: edB64 },
256
+ },
257
+ }));
258
+ const diff = diffDomainFiles(before, after);
259
+ assert.deepEqual(diff.partyChanged, { before: "Acme Corp", after: "Acme Corporation" });
260
+ assert.deepEqual(diff.added.map((r) => r.name), ["press"]);
261
+ assert.deepEqual(diff.removed.map((r) => r.name), []);
262
+ assert.deepEqual(diff.changed.map((c) => c.name), ["studio"]);
263
+ assert.equal(diff.unchanged, 0);
264
+ });
265
+ //# sourceMappingURL=domain.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"domain.test.js","sourceRoot":"","sources":["../../src/__tests__/domain.test.ts"],"names":[],"mappings":"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"}
package/dist/check.d.ts CHANGED
@@ -65,7 +65,7 @@ export declare const KNOWN_ENCLAVE_MEASUREMENTS: ReadonlyArray<{
65
65
  }>;
66
66
  /** One checked property, three-valued, with a plain-language reason. */
67
67
  export interface CheckLine {
68
- name: "file" | "signature" | "attestation" | "enclave" | "witness" | "contradiction";
68
+ name: "file" | "signature" | "attestation" | "enclave" | "witness" | "contradiction" | "domain";
69
69
  result: ThreeValued;
70
70
  detail: string;
71
71
  }
@@ -115,7 +115,13 @@ export interface CheckAnchor {
115
115
  result: ThreeValued;
116
116
  }
117
117
  export interface CheckReport {
118
- check: "bitgraph-check/1";
118
+ /** /2 exactly when the report was built against a pinned domain (`from`). */
119
+ check: "bitgraph-check/1" | "bitgraph-check/2";
120
+ /** The pinned domain this report was checked against, when one was. */
121
+ from?: {
122
+ domain: string;
123
+ party: string;
124
+ };
119
125
  result: ThreeValued;
120
126
  /** One-sentence plain-language conclusion, deterministic. */
121
127
  summary: string;
@@ -134,6 +140,30 @@ export interface CheckReport {
134
140
  };
135
141
  network: "none";
136
142
  }
143
+ /**
144
+ * A pinned BitGraph Domain, as the report builder consults it: one line
145
+ * per recording, TRUE or UNDETERMINED, never FALSE (absence of domain
146
+ * evidence contradicts nothing; the open-world rule of SPEC §9.3).
147
+ *
148
+ * An interface here rather than an import from domain.ts, deliberately:
149
+ * this module is also built into the browser verifier, and the crypto the
150
+ * adapter needs (key decoding, signature verification) stays behind it.
151
+ * domain.ts's `checkDomain(file)` is the implementation; embedders may
152
+ * supply their own.
153
+ */
154
+ export interface CheckDomain {
155
+ domain: string;
156
+ party: string;
157
+ keyCount: number;
158
+ /** Key name for an actor keyId (es256 fingerprint match), if published. */
159
+ actorKeyName(keyId: string): string | undefined;
160
+ /**
161
+ * Key name of the first pinned key a candidate bitgraph-sig/1 file
162
+ * verifies under, over this digest (lowercase hex). Deterministic:
163
+ * candidates ascending by content hash, keys in name order.
164
+ */
165
+ signatureKeyName(targetSha256Hex: string, evidence: ReadonlyMap<string, Uint8Array>): string | undefined;
166
+ }
137
167
  export interface CheckOptions {
138
168
  /**
139
169
  * False when the environment cannot run the attestation's ECDSA P-384
@@ -141,6 +171,19 @@ export interface CheckOptions {
141
171
  * with that reason instead of a false FALSE. Defaults to true.
142
172
  */
143
173
  webCryptoAvailable?: boolean;
174
+ /**
175
+ * Check against a pinned domain: adds one "domain" line per recording
176
+ * and stamps the report bitgraph-check/2. The check itself stays
177
+ * offline; the pin was the one fetch, and it already happened.
178
+ */
179
+ from?: CheckDomain;
180
+ /**
181
+ * Candidate signature bytes by content sha256 hex, for the domain
182
+ * line's detached-signature path (SPEC §9.4 discipline). checkIngest
183
+ * collects this from the bundle's matched artifacts when absent;
184
+ * embedders may supply additional candidates.
185
+ */
186
+ sigEvidence?: ReadonlyMap<string, Uint8Array>;
144
187
  }
145
188
  /**
146
189
  * Check an already-ingested bundle: runs the audit's pure tail (no
@@ -1 +1 @@
1
- {"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../src/check.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../src/check.ts"],"names":[],"mappings":"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"}