@mikeargento/bitgraph-player 0.1.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 (69) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +98 -0
  3. package/SPEC.md +234 -0
  4. package/dist/__tests__/cast-order.test.d.ts +2 -0
  5. package/dist/__tests__/cast-order.test.d.ts.map +1 -0
  6. package/dist/__tests__/cast-order.test.js +434 -0
  7. package/dist/__tests__/cast-order.test.js.map +1 -0
  8. package/dist/__tests__/evaluate-verdict.test.d.ts +2 -0
  9. package/dist/__tests__/evaluate-verdict.test.d.ts.map +1 -0
  10. package/dist/__tests__/evaluate-verdict.test.js +228 -0
  11. package/dist/__tests__/evaluate-verdict.test.js.map +1 -0
  12. package/dist/__tests__/fixtures.d.ts +63 -0
  13. package/dist/__tests__/fixtures.d.ts.map +1 -0
  14. package/dist/__tests__/fixtures.js +150 -0
  15. package/dist/__tests__/fixtures.js.map +1 -0
  16. package/dist/__tests__/logic-rule.test.d.ts +2 -0
  17. package/dist/__tests__/logic-rule.test.d.ts.map +1 -0
  18. package/dist/__tests__/logic-rule.test.js +190 -0
  19. package/dist/__tests__/logic-rule.test.js.map +1 -0
  20. package/dist/cast.d.ts +29 -0
  21. package/dist/cast.d.ts.map +1 -0
  22. package/dist/cast.js +85 -0
  23. package/dist/cast.js.map +1 -0
  24. package/dist/cli.d.ts +3 -0
  25. package/dist/cli.d.ts.map +1 -0
  26. package/dist/cli.js +130 -0
  27. package/dist/cli.js.map +1 -0
  28. package/dist/evaluate.d.ts +30 -0
  29. package/dist/evaluate.d.ts.map +1 -0
  30. package/dist/evaluate.js +177 -0
  31. package/dist/evaluate.js.map +1 -0
  32. package/dist/index.d.ts +22 -0
  33. package/dist/index.d.ts.map +1 -0
  34. package/dist/index.js +9 -0
  35. package/dist/index.js.map +1 -0
  36. package/dist/logic.d.ts +16 -0
  37. package/dist/logic.d.ts.map +1 -0
  38. package/dist/logic.js +29 -0
  39. package/dist/logic.js.map +1 -0
  40. package/dist/order.d.ts +50 -0
  41. package/dist/order.d.ts.map +1 -0
  42. package/dist/order.js +290 -0
  43. package/dist/order.js.map +1 -0
  44. package/dist/rule.d.ts +40 -0
  45. package/dist/rule.d.ts.map +1 -0
  46. package/dist/rule.js +324 -0
  47. package/dist/rule.js.map +1 -0
  48. package/dist/types.d.ts +205 -0
  49. package/dist/types.d.ts.map +1 -0
  50. package/dist/types.js +16 -0
  51. package/dist/types.js.map +1 -0
  52. package/dist/verdict.d.ts +14 -0
  53. package/dist/verdict.d.ts.map +1 -0
  54. package/dist/verdict.js +146 -0
  55. package/dist/verdict.js.map +1 -0
  56. package/package.json +42 -0
  57. package/src/__tests__/cast-order.test.ts +473 -0
  58. package/src/__tests__/evaluate-verdict.test.ts +266 -0
  59. package/src/__tests__/fixtures.ts +206 -0
  60. package/src/__tests__/logic-rule.test.ts +221 -0
  61. package/src/cast.ts +120 -0
  62. package/src/cli.ts +143 -0
  63. package/src/evaluate.ts +238 -0
  64. package/src/index.ts +38 -0
  65. package/src/logic.ts +39 -0
  66. package/src/order.ts +380 -0
  67. package/src/rule.ts +340 -0
  68. package/src/types.ts +224 -0
  69. package/src/verdict.ts +159 -0
package/dist/rule.d.ts ADDED
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Rule parsing and validation for bitgraph-player/1.
3
+ *
4
+ * Strict by design: unknown fields are rejected at every level, because a
5
+ * silently ignored field in a rule is a claim the author believes is being
6
+ * enforced and is not. `requires.ordering` is mandatory — a rule that does
7
+ * not declare its trust floor does not parse.
8
+ *
9
+ * One deliberate looseness: a claim may reference a role the cast does not
10
+ * declare. That is NOT a parse error; it evaluates to UNDETERMINED. The
11
+ * rule file stays parseable so the verdict can say exactly which reference
12
+ * was undeclared.
13
+ */
14
+ import type { Rule } from "./types.js";
15
+ export declare class RuleError extends Error {
16
+ readonly issues: readonly string[];
17
+ constructor(issues: readonly string[]);
18
+ }
19
+ /**
20
+ * Normalize any accepted digest spelling to the standard-base64 form used
21
+ * by bitgraph/1 proofs (artifact.digestB64). Returns undefined when the
22
+ * input is not a CANONICAL spelling of a 32-byte SHA-256: base64 forms
23
+ * must round-trip byte-exactly, so spellings with nonzero trailing
24
+ * padding bits (which Node's lenient decoder silently reinterprets) are
25
+ * rejected rather than collapsed into different bytes than written.
26
+ */
27
+ export declare function normalizeDigest(input: string): string | undefined;
28
+ /**
29
+ * Tolerant decode of a digest string observed in a bundle proof, for
30
+ * byte-level matching only (a hostile file may spell its digest any way
31
+ * it likes; matching by bytes keeps "only broken recordings exist" from
32
+ * masquerading as "no recordings exist").
33
+ */
34
+ export declare function decodeDigestBytes(input: string): Buffer | undefined;
35
+ /**
36
+ * Parse and validate a rule from raw JSON text. Throws RuleError with every
37
+ * issue found, not just the first.
38
+ */
39
+ export declare function parseRule(jsonText: string): Rule;
40
+ //# sourceMappingURL=rule.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rule.d.ts","sourceRoot":"","sources":["../src/rule.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAA2C,IAAI,EAAE,MAAM,YAAY,CAAC;AAEhF,qBAAa,SAAU,SAAQ,KAAK;IAClC,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;gBACvB,MAAM,EAAE,SAAS,MAAM,EAAE;CAKtC;AAMD;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAmBjE;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAYnE;AAkKD;;;GAGG;AACH,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CA+FhD"}
package/dist/rule.js ADDED
@@ -0,0 +1,324 @@
1
+ // Copyright (c) 2024-2026 Mike Argento. Licensed under the MIT License. See LICENSE.
2
+ export class RuleError extends Error {
3
+ issues;
4
+ constructor(issues) {
5
+ super(`invalid rule: ${issues.join("; ")}`);
6
+ this.name = "RuleError";
7
+ this.issues = issues;
8
+ }
9
+ }
10
+ const HEX64 = /^[0-9a-fA-F]{64}$/;
11
+ const B64_STD = /^[A-Za-z0-9+/]{43}=$/;
12
+ const B64_URL = /^[A-Za-z0-9_-]{43}=?$/;
13
+ /**
14
+ * Normalize any accepted digest spelling to the standard-base64 form used
15
+ * by bitgraph/1 proofs (artifact.digestB64). Returns undefined when the
16
+ * input is not a CANONICAL spelling of a 32-byte SHA-256: base64 forms
17
+ * must round-trip byte-exactly, so spellings with nonzero trailing
18
+ * padding bits (which Node's lenient decoder silently reinterprets) are
19
+ * rejected rather than collapsed into different bytes than written.
20
+ */
21
+ export function normalizeDigest(input) {
22
+ let s = input.trim();
23
+ if (s.toLowerCase().startsWith("sha256:"))
24
+ s = s.slice("sha256:".length);
25
+ if (HEX64.test(s)) {
26
+ return Buffer.from(s, "hex").toString("base64");
27
+ }
28
+ if (B64_STD.test(s)) {
29
+ const bytes = Buffer.from(s, "base64");
30
+ if (bytes.length === 32 && bytes.toString("base64") === s)
31
+ return s;
32
+ return undefined;
33
+ }
34
+ if (B64_URL.test(s)) {
35
+ const bytes = Buffer.from(s, "base64url");
36
+ if (bytes.length === 32 && bytes.toString("base64url") === s.replace(/=+$/, "")) {
37
+ return bytes.toString("base64");
38
+ }
39
+ return undefined;
40
+ }
41
+ return undefined;
42
+ }
43
+ /**
44
+ * Tolerant decode of a digest string observed in a bundle proof, for
45
+ * byte-level matching only (a hostile file may spell its digest any way
46
+ * it likes; matching by bytes keeps "only broken recordings exist" from
47
+ * masquerading as "no recordings exist").
48
+ */
49
+ export function decodeDigestBytes(input) {
50
+ const s = input.trim();
51
+ if (HEX64.test(s))
52
+ return Buffer.from(s, "hex");
53
+ if (/^[A-Za-z0-9+/]+=*$/.test(s)) {
54
+ const bytes = Buffer.from(s, "base64");
55
+ return bytes.length === 32 ? bytes : undefined;
56
+ }
57
+ if (/^[A-Za-z0-9_-]+=*$/.test(s)) {
58
+ const bytes = Buffer.from(s, "base64url");
59
+ return bytes.length === 32 ? bytes : undefined;
60
+ }
61
+ return undefined;
62
+ }
63
+ function isPlainObject(v) {
64
+ return typeof v === "object" && v !== null && !Array.isArray(v);
65
+ }
66
+ function rejectUnknownKeys(obj, allowed, where, issues) {
67
+ for (const key of Object.keys(obj)) {
68
+ if (!allowed.includes(key))
69
+ issues.push(`${where}: unknown field "${key}"`);
70
+ }
71
+ }
72
+ function parsePin(v, where, issues) {
73
+ if (!isPlainObject(v)) {
74
+ issues.push(`${where}: "at" must be an object`);
75
+ return undefined;
76
+ }
77
+ const hasProofHash = "proofHash" in v;
78
+ const hasPosition = "epochId" in v || "counter" in v;
79
+ if (hasProofHash && hasPosition) {
80
+ issues.push(`${where}: "at" must be {proofHash} or {epochId, counter}, not both`);
81
+ return undefined;
82
+ }
83
+ if (hasProofHash) {
84
+ rejectUnknownKeys(v, ["proofHash"], where, issues);
85
+ if (typeof v["proofHash"] !== "string" || v["proofHash"].length === 0) {
86
+ issues.push(`${where}: "at.proofHash" must be a non-empty string`);
87
+ return undefined;
88
+ }
89
+ return { proofHash: v["proofHash"] };
90
+ }
91
+ if (hasPosition) {
92
+ rejectUnknownKeys(v, ["epochId", "counter"], where, issues);
93
+ const epochId = v["epochId"];
94
+ const counter = v["counter"];
95
+ if (typeof epochId !== "string" || epochId.length === 0) {
96
+ issues.push(`${where}: "at.epochId" must be a non-empty string`);
97
+ return undefined;
98
+ }
99
+ if (typeof counter !== "string" || !/^\d+$/.test(counter)) {
100
+ issues.push(`${where}: "at.counter" must be a decimal string`);
101
+ return undefined;
102
+ }
103
+ return { epochId, counter };
104
+ }
105
+ issues.push(`${where}: "at" must be {proofHash} or {epochId, counter}`);
106
+ return undefined;
107
+ }
108
+ function parseCastEntry(role, v, issues) {
109
+ const where = `cast.${role}`;
110
+ if (!isPlainObject(v)) {
111
+ issues.push(`${where}: must be an object`);
112
+ return undefined;
113
+ }
114
+ rejectUnknownKeys(v, ["digest", "means", "at", "signedBy", "optional"], where, issues);
115
+ const digest = v["digest"];
116
+ if (typeof digest !== "string") {
117
+ issues.push(`${where}: "digest" is required and must be a string`);
118
+ return undefined;
119
+ }
120
+ if (normalizeDigest(digest) === undefined) {
121
+ issues.push(`${where}: "digest" is not a well-formed 32-byte SHA-256 in any accepted spelling`);
122
+ return undefined;
123
+ }
124
+ const entry = { digest };
125
+ if ("means" in v) {
126
+ if (typeof v["means"] !== "string") {
127
+ issues.push(`${where}: "means" must be a string`);
128
+ }
129
+ else {
130
+ entry.means = v["means"];
131
+ }
132
+ }
133
+ if ("at" in v) {
134
+ const pin = parsePin(v["at"], where, issues);
135
+ if (pin !== undefined)
136
+ entry.at = pin;
137
+ }
138
+ if ("signedBy" in v) {
139
+ entry.signedBy = v["signedBy"];
140
+ }
141
+ if ("optional" in v) {
142
+ if (typeof v["optional"] !== "boolean") {
143
+ issues.push(`${where}: "optional" must be a boolean`);
144
+ }
145
+ else {
146
+ entry.optional = v["optional"];
147
+ }
148
+ }
149
+ return entry;
150
+ }
151
+ function parseClaim(v, where, issues, depth) {
152
+ if (depth > 32) {
153
+ issues.push(`${where}: claim nesting exceeds the maximum depth of 32`);
154
+ return undefined;
155
+ }
156
+ if (!isPlainObject(v)) {
157
+ issues.push(`${where}: must be an object`);
158
+ return undefined;
159
+ }
160
+ const keys = Object.keys(v);
161
+ if (keys.length !== 1) {
162
+ issues.push(`${where}: a claim must have exactly one operator, got [${keys.join(", ")}]`);
163
+ return undefined;
164
+ }
165
+ const op = keys[0];
166
+ const body = v[op];
167
+ switch (op) {
168
+ case "exists": {
169
+ if (typeof body !== "string" || body.length === 0) {
170
+ issues.push(`${where}.exists: must be a role name`);
171
+ return undefined;
172
+ }
173
+ return { exists: body };
174
+ }
175
+ case "before":
176
+ case "after": {
177
+ if (!Array.isArray(body) || body.length !== 2 || body.some((r) => typeof r !== "string")) {
178
+ issues.push(`${where}.${op}: must be a two-element array of role names`);
179
+ return undefined;
180
+ }
181
+ const pair = body;
182
+ return op === "before" ? { before: pair } : { after: pair };
183
+ }
184
+ case "between": {
185
+ if (!Array.isArray(body) || body.length !== 3 || body.some((r) => typeof r !== "string")) {
186
+ issues.push(`${where}.between: must be [subject, lowerRole, upperRole]`);
187
+ return undefined;
188
+ }
189
+ return { between: body };
190
+ }
191
+ case "all":
192
+ case "any": {
193
+ if (!Array.isArray(body) || body.length === 0) {
194
+ issues.push(`${where}.${op}: must be a non-empty array of claims`);
195
+ return undefined;
196
+ }
197
+ const parsed = [];
198
+ let ok = true;
199
+ body.forEach((child, i) => {
200
+ const c = parseClaim(child, `${where}.${op}[${i}]`, issues, depth + 1);
201
+ if (c === undefined)
202
+ ok = false;
203
+ else
204
+ parsed.push(c);
205
+ });
206
+ if (!ok)
207
+ return undefined;
208
+ return op === "all" ? { all: parsed } : { any: parsed };
209
+ }
210
+ case "not": {
211
+ const inner = parseClaim(body, `${where}.not`, issues, depth + 1);
212
+ if (inner === undefined)
213
+ return undefined;
214
+ return { not: inner };
215
+ }
216
+ default:
217
+ issues.push(`${where}: unknown operator "${op}"`);
218
+ return undefined;
219
+ }
220
+ }
221
+ /**
222
+ * Parse and validate a rule from raw JSON text. Throws RuleError with every
223
+ * issue found, not just the first.
224
+ */
225
+ export function parseRule(jsonText) {
226
+ let raw;
227
+ try {
228
+ raw = JSON.parse(jsonText);
229
+ }
230
+ catch (err) {
231
+ throw new RuleError([`not valid JSON: ${err.message}`]);
232
+ }
233
+ const issues = [];
234
+ if (!isPlainObject(raw))
235
+ throw new RuleError(["rule file must be a JSON object"]);
236
+ rejectUnknownKeys(raw, ["rule", "id", "cast", "world", "requires", "claim", "then"], "rule", issues);
237
+ if (raw["rule"] !== "bitgraph-player/1") {
238
+ issues.push(`"rule" must be exactly "bitgraph-player/1"`);
239
+ }
240
+ if (typeof raw["id"] !== "string" || raw["id"].length === 0) {
241
+ issues.push(`"id" is required and must be a non-empty string`);
242
+ }
243
+ if (raw["world"] !== "closed") {
244
+ issues.push(`"world" is required and must be exactly "closed" (the only defined value)`);
245
+ }
246
+ // The trust floor is mandatory. No default: a rule that does not state
247
+ // what evidence it accepts does not parse.
248
+ let ordering;
249
+ if (!isPlainObject(raw["requires"])) {
250
+ issues.push(`"requires" is required: a rule must declare its trust floor via requires.ordering`);
251
+ }
252
+ else {
253
+ rejectUnknownKeys(raw["requires"], ["ordering"], "requires", issues);
254
+ const o = raw["requires"]["ordering"];
255
+ if (o === "hash-linked" || o === "assumption-dependent") {
256
+ ordering = o;
257
+ }
258
+ else {
259
+ issues.push(`requires.ordering must be "hash-linked" or "assumption-dependent"`);
260
+ }
261
+ }
262
+ // Null prototype: a role named "__proto__" must become an ordinary own
263
+ // key, not a prototype assignment that silently drops the role.
264
+ const cast = Object.create(null);
265
+ if (!isPlainObject(raw["cast"]) || Object.keys(raw["cast"]).length === 0) {
266
+ issues.push(`"cast" is required and must declare at least one role`);
267
+ }
268
+ else {
269
+ for (const [role, entry] of Object.entries(raw["cast"])) {
270
+ if (!/^[A-Za-z0-9_.-]+$/.test(role)) {
271
+ issues.push(`cast: role name "${role}" must match [A-Za-z0-9_.-]+`);
272
+ continue;
273
+ }
274
+ // Pure-integer names are re-ordered ahead of string keys by JSON
275
+ // object semantics in some languages, breaking the declaration-order
276
+ // guarantee a verdict depends on. Forbidden by the grammar.
277
+ if (/^[0-9]+$/.test(role)) {
278
+ issues.push(`cast: role name "${role}" must contain at least one non-digit character`);
279
+ continue;
280
+ }
281
+ const parsed = parseCastEntry(role, entry, issues);
282
+ if (parsed !== undefined)
283
+ cast[role] = parsed;
284
+ }
285
+ }
286
+ let claim;
287
+ if (!("claim" in raw)) {
288
+ issues.push(`"claim" is required`);
289
+ }
290
+ else {
291
+ claim = parseClaim(raw["claim"], "claim", issues, 0);
292
+ }
293
+ let then;
294
+ if ("then" in raw) {
295
+ if (!isPlainObject(raw["then"])) {
296
+ issues.push(`"then" must be an object`);
297
+ }
298
+ else {
299
+ // A label and nothing else. The first request for a field here that
300
+ // can cause an action is a request to make Player an enforcer.
301
+ rejectUnknownKeys(raw["then"], ["label"], "then", issues);
302
+ if (typeof raw["then"]["label"] !== "string" || raw["then"]["label"].length === 0) {
303
+ issues.push(`then.label must be a non-empty string`);
304
+ }
305
+ else {
306
+ then = { label: raw["then"]["label"] };
307
+ }
308
+ }
309
+ }
310
+ if (issues.length > 0)
311
+ throw new RuleError(issues);
312
+ const rule = {
313
+ rule: "bitgraph-player/1",
314
+ id: raw["id"],
315
+ cast,
316
+ world: "closed",
317
+ requires: { ordering: ordering },
318
+ claim: claim,
319
+ };
320
+ if (then !== undefined)
321
+ rule.then = then;
322
+ return rule;
323
+ }
324
+ //# sourceMappingURL=rule.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rule.js","sourceRoot":"","sources":["../src/rule.ts"],"names":[],"mappings":"AAAA,qFAAqF;AAkBrF,MAAM,OAAO,SAAU,SAAQ,KAAK;IACzB,MAAM,CAAoB;IACnC,YAAY,MAAyB;QACnC,KAAK,CAAC,iBAAiB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC5C,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC;QACxB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;CACF;AAED,MAAM,KAAK,GAAG,mBAAmB,CAAC;AAClC,MAAM,OAAO,GAAG,sBAAsB,CAAC;AACvC,MAAM,OAAO,GAAG,uBAAuB,CAAC;AAExC;;;;;;;GAOG;AACH,MAAM,UAAU,eAAe,CAAC,KAAa;IAC3C,IAAI,CAAC,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IACrB,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC;QAAE,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IACzE,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QAClB,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAClD,CAAC;IACD,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QACpB,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;QACvC,IAAI,KAAK,CAAC,MAAM,KAAK,EAAE,IAAI,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC;YAAE,OAAO,CAAC,CAAC;QACpE,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QACpB,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC;QAC1C,IAAI,KAAK,CAAC,MAAM,KAAK,EAAE,IAAI,KAAK,CAAC,QAAQ,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,EAAE,CAAC;YAChF,OAAO,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAClC,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAa;IAC7C,MAAM,CAAC,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IACvB,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IAChD,IAAI,oBAAoB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QACjC,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;QACvC,OAAO,KAAK,CAAC,MAAM,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;IACjD,CAAC;IACD,IAAI,oBAAoB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QACjC,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC;QAC1C,OAAO,KAAK,CAAC,MAAM,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;IACjD,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,aAAa,CAAC,CAAU;IAC/B,OAAO,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AAClE,CAAC;AAED,SAAS,iBAAiB,CACxB,GAA4B,EAC5B,OAA0B,EAC1B,KAAa,EACb,MAAgB;IAEhB,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QACnC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC;YAAE,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,oBAAoB,GAAG,GAAG,CAAC,CAAC;IAC9E,CAAC;AACH,CAAC;AAED,SAAS,QAAQ,CAAC,CAAU,EAAE,KAAa,EAAE,MAAgB;IAC3D,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC;QACtB,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,0BAA0B,CAAC,CAAC;QAChD,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,YAAY,GAAG,WAAW,IAAI,CAAC,CAAC;IACtC,MAAM,WAAW,GAAG,SAAS,IAAI,CAAC,IAAI,SAAS,IAAI,CAAC,CAAC;IACrD,IAAI,YAAY,IAAI,WAAW,EAAE,CAAC;QAChC,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,4DAA4D,CAAC,CAAC;QAClF,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,IAAI,YAAY,EAAE,CAAC;QACjB,iBAAiB,CAAC,CAAC,EAAE,CAAC,WAAW,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;QACnD,IAAI,OAAO,CAAC,CAAC,WAAW,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,WAAW,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACtE,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,6CAA6C,CAAC,CAAC;YACnE,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC,WAAW,CAAC,EAAE,CAAC;IACvC,CAAC;IACD,IAAI,WAAW,EAAE,CAAC;QAChB,iBAAiB,CAAC,CAAC,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;QAC5D,MAAM,OAAO,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC;QAC7B,MAAM,OAAO,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC;QAC7B,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxD,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,2CAA2C,CAAC,CAAC;YACjE,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YAC1D,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,yCAAyC,CAAC,CAAC;YAC/D,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;IAC9B,CAAC;IACD,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,kDAAkD,CAAC,CAAC;IACxE,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,cAAc,CAAC,IAAY,EAAE,CAAU,EAAE,MAAgB;IAChE,MAAM,KAAK,GAAG,QAAQ,IAAI,EAAE,CAAC;IAC7B,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC;QACtB,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,qBAAqB,CAAC,CAAC;QAC3C,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,iBAAiB,CAAC,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,UAAU,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;IACvF,MAAM,MAAM,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC;IAC3B,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;QAC/B,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,6CAA6C,CAAC,CAAC;QACnE,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,IAAI,eAAe,CAAC,MAAM,CAAC,KAAK,SAAS,EAAE,CAAC;QAC1C,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,0EAA0E,CAAC,CAAC;QAChG,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,KAAK,GAAc,EAAE,MAAM,EAAE,CAAC;IACpC,IAAI,OAAO,IAAI,CAAC,EAAE,CAAC;QACjB,IAAI,OAAO,CAAC,CAAC,OAAO,CAAC,KAAK,QAAQ,EAAE,CAAC;YACnC,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,4BAA4B,CAAC,CAAC;QACpD,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC;IACD,IAAI,IAAI,IAAI,CAAC,EAAE,CAAC;QACd,MAAM,GAAG,GAAG,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;QAC7C,IAAI,GAAG,KAAK,SAAS;YAAE,KAAK,CAAC,EAAE,GAAG,GAAG,CAAC;IACxC,CAAC;IACD,IAAI,UAAU,IAAI,CAAC,EAAE,CAAC;QACpB,KAAK,CAAC,QAAQ,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC;IACjC,CAAC;IACD,IAAI,UAAU,IAAI,CAAC,EAAE,CAAC;QACpB,IAAI,OAAO,CAAC,CAAC,UAAU,CAAC,KAAK,SAAS,EAAE,CAAC;YACvC,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,gCAAgC,CAAC,CAAC;QACxD,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,QAAQ,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC;QACjC,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,UAAU,CAAC,CAAU,EAAE,KAAa,EAAE,MAAgB,EAAE,KAAa;IAC5E,IAAI,KAAK,GAAG,EAAE,EAAE,CAAC;QACf,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,iDAAiD,CAAC,CAAC;QACvE,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC;QACtB,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,qBAAqB,CAAC,CAAC;QAC3C,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC5B,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,kDAAkD,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC1F,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACnB,MAAM,IAAI,GAAG,CAAC,CAAC,EAAoB,CAAC,CAAC;IACrC,QAAQ,EAAE,EAAE,CAAC;QACX,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAClD,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,8BAA8B,CAAC,CAAC;gBACpD,OAAO,SAAS,CAAC;YACnB,CAAC;YACD,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;QAC1B,CAAC;QACD,KAAK,QAAQ,CAAC;QACd,KAAK,OAAO,CAAC,CAAC,CAAC;YACb,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,EAAE,CAAC;gBACzF,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,IAAI,EAAE,6CAA6C,CAAC,CAAC;gBACzE,OAAO,SAAS,CAAC;YACnB,CAAC;YACD,MAAM,IAAI,GAAG,IAAwB,CAAC;YACtC,OAAO,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;QAC9D,CAAC;QACD,KAAK,SAAS,CAAC,CAAC,CAAC;YACf,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,EAAE,CAAC;gBACzF,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,mDAAmD,CAAC,CAAC;gBACzE,OAAO,SAAS,CAAC;YACnB,CAAC;YACD,OAAO,EAAE,OAAO,EAAE,IAAgC,EAAE,CAAC;QACvD,CAAC;QACD,KAAK,KAAK,CAAC;QACX,KAAK,KAAK,CAAC,CAAC,CAAC;YACX,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC9C,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,IAAI,EAAE,uCAAuC,CAAC,CAAC;gBACnE,OAAO,SAAS,CAAC;YACnB,CAAC;YACD,MAAM,MAAM,GAAY,EAAE,CAAC;YAC3B,IAAI,EAAE,GAAG,IAAI,CAAC;YACd,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE;gBACxB,MAAM,CAAC,GAAG,UAAU,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,EAAE,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC;gBACvE,IAAI,CAAC,KAAK,SAAS;oBAAE,EAAE,GAAG,KAAK,CAAC;;oBAC3B,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACtB,CAAC,CAAC,CAAC;YACH,IAAI,CAAC,EAAE;gBAAE,OAAO,SAAS,CAAC;YAC1B,OAAO,EAAE,KAAK,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC;QAC1D,CAAC;QACD,KAAK,KAAK,CAAC,CAAC,CAAC;YACX,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,EAAE,GAAG,KAAK,MAAM,EAAE,MAAM,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC;YAClE,IAAI,KAAK,KAAK,SAAS;gBAAE,OAAO,SAAS,CAAC;YAC1C,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC;QACxB,CAAC;QACD;YACE,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,uBAAuB,EAAE,GAAG,CAAC,CAAC;YAClD,OAAO,SAAS,CAAC;IACrB,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAC,QAAgB;IACxC,IAAI,GAAY,CAAC;IACjB,IAAI,CAAC;QACH,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAC7B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,SAAS,CAAC,CAAC,mBAAoB,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IACrE,CAAC;IACD,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC;QAAE,MAAM,IAAI,SAAS,CAAC,CAAC,iCAAiC,CAAC,CAAC,CAAC;IAElF,iBAAiB,CAAC,GAAG,EAAE,CAAC,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAErG,IAAI,GAAG,CAAC,MAAM,CAAC,KAAK,mBAAmB,EAAE,CAAC;QACxC,MAAM,CAAC,IAAI,CAAC,4CAA4C,CAAC,CAAC;IAC5D,CAAC;IACD,IAAI,OAAO,GAAG,CAAC,IAAI,CAAC,KAAK,QAAQ,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5D,MAAM,CAAC,IAAI,CAAC,iDAAiD,CAAC,CAAC;IACjE,CAAC;IACD,IAAI,GAAG,CAAC,OAAO,CAAC,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,CAAC,IAAI,CAAC,2EAA2E,CAAC,CAAC;IAC3F,CAAC;IAED,uEAAuE;IACvE,2CAA2C;IAC3C,IAAI,QAAkC,CAAC;IACvC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC;QACpC,MAAM,CAAC,IAAI,CAAC,mFAAmF,CAAC,CAAC;IACnG,CAAC;SAAM,CAAC;QACN,iBAAiB,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC,UAAU,CAAC,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC;QACrE,MAAM,CAAC,GAAG,GAAG,CAAC,UAAU,CAAC,CAAC,UAAU,CAAC,CAAC;QACtC,IAAI,CAAC,KAAK,aAAa,IAAI,CAAC,KAAK,sBAAsB,EAAE,CAAC;YACxD,QAAQ,GAAG,CAAC,CAAC;QACf,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,IAAI,CAAC,mEAAmE,CAAC,CAAC;QACnF,CAAC;IACH,CAAC;IAED,uEAAuE;IACvE,gEAAgE;IAChE,MAAM,IAAI,GAA8B,MAAM,CAAC,MAAM,CAAC,IAAI,CAA8B,CAAC;IACzF,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzE,MAAM,CAAC,IAAI,CAAC,uDAAuD,CAAC,CAAC;IACvE,CAAC;SAAM,CAAC;QACN,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;YACxD,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBACpC,MAAM,CAAC,IAAI,CAAC,oBAAoB,IAAI,8BAA8B,CAAC,CAAC;gBACpE,SAAS;YACX,CAAC;YACD,iEAAiE;YACjE,qEAAqE;YACrE,4DAA4D;YAC5D,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC1B,MAAM,CAAC,IAAI,CAAC,oBAAoB,IAAI,iDAAiD,CAAC,CAAC;gBACvF,SAAS;YACX,CAAC;YACD,MAAM,MAAM,GAAG,cAAc,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;YACnD,IAAI,MAAM,KAAK,SAAS;gBAAE,IAAI,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC;QAChD,CAAC;IACH,CAAC;IAED,IAAI,KAAwB,CAAC;IAC7B,IAAI,CAAC,CAAC,OAAO,IAAI,GAAG,CAAC,EAAE,CAAC;QACtB,MAAM,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;IACrC,CAAC;SAAM,CAAC;QACN,KAAK,GAAG,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;IACvD,CAAC;IAED,IAAI,IAAmC,CAAC;IACxC,IAAI,MAAM,IAAI,GAAG,EAAE,CAAC;QAClB,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;YAChC,MAAM,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;QAC1C,CAAC;aAAM,CAAC;YACN,oEAAoE;YACpE,+DAA+D;YAC/D,iBAAiB,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;YAC1D,IAAI,OAAO,GAAG,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAClF,MAAM,CAAC,IAAI,CAAC,uCAAuC,CAAC,CAAC;YACvD,CAAC;iBAAM,CAAC;gBACN,IAAI,GAAG,EAAE,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;YACzC,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC;QAAE,MAAM,IAAI,SAAS,CAAC,MAAM,CAAC,CAAC;IAEnD,MAAM,IAAI,GAAS;QACjB,IAAI,EAAE,mBAAmB;QACzB,EAAE,EAAE,GAAG,CAAC,IAAI,CAAW;QACvB,IAAI;QACJ,KAAK,EAAE,QAAQ;QACf,QAAQ,EAAE,EAAE,QAAQ,EAAE,QAAwB,EAAE;QAChD,KAAK,EAAE,KAAc;KACtB,CAAC;IACF,IAAI,IAAI,KAAK,SAAS;QAAE,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACzC,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,205 @@
1
+ /**
2
+ * @mikeargento/bitgraph-player
3
+ *
4
+ * Shared vocabulary. The normative semantics live in SPEC.md; the comments
5
+ * here restate them only where a reader of the types needs the contract.
6
+ *
7
+ * Player is a pure function over an AuditResult:
8
+ *
9
+ * evaluate(rule, runAudit(bundle)) -> verdict
10
+ *
11
+ * Three-valued by design. TRUE and FALSE are claims BitGraph evidence
12
+ * supports; UNDETERMINED is the honest answer everywhere the evidence does
13
+ * not decide. A boolean evaluator would launder undecidable into FALSE.
14
+ */
15
+ import type { ObservedProof } from "@mikeargento/bitgraph-audit";
16
+ export type ThreeValued = "TRUE" | "FALSE" | "UNDETERMINED";
17
+ /**
18
+ * Every ordering answer names what it rests on:
19
+ *
20
+ * "chain-link" same partition, both proofs in one verified prevB64
21
+ * component; commit-counter order within a hash-linked
22
+ * structure.
23
+ * "counter-order" same partition, different components; commit-counter
24
+ * values only, which relies on the authority's counter
25
+ * discipline.
26
+ * "epoch-lineage" different epochs related by hard epochLink succession
27
+ * (cryptographic hand-off; transitive pairs from audit).
28
+ * "anchor-bounds" different epochs related through Ethereum anchor
29
+ * bounds. The not-after side always rests on the
30
+ * anchor-freshness assumption.
31
+ */
32
+ export type OrderBasis = "chain-link" | "counter-order" | "epoch-lineage" | "anchor-bounds";
33
+ /**
34
+ * The two honest tiers. "hash-linked" rests on hash links alone;
35
+ * "assumption-dependent" additionally rests on counter discipline or
36
+ * anchor freshness. A rule declares the floor it will accept.
37
+ */
38
+ export type EvidenceTier = "hash-linked" | "assumption-dependent";
39
+ export declare function basisTier(basis: OrderBasis): EvidenceTier;
40
+ /** True when `tier` satisfies a declared floor. */
41
+ export declare function meetsFloor(tier: EvidenceTier, floor: EvidenceTier): boolean;
42
+ /** Result of comparing two resolved recordings. */
43
+ export interface OrderResult {
44
+ /** "same" when both roles resolved to the identical recording. */
45
+ relation: "before" | "after" | "same" | "unordered";
46
+ /** Present exactly when relation is "before" or "after". */
47
+ basis?: OrderBasis;
48
+ /**
49
+ * Present exactly when relation is "before" or "after": the tier this
50
+ * specific answer rests on. Usually basisTier(basis), but epoch-lineage
51
+ * answers whose predecessor-side coverage rests on counter discipline
52
+ * carry "assumption-dependent" despite the hash-linked basis family.
53
+ * The evidence floor gates THIS field.
54
+ */
55
+ tier?: EvidenceTier;
56
+ /** True when the answer rests on an assumption (counter discipline or anchor freshness). */
57
+ assumptionDependent: boolean;
58
+ /** True when the evidence additionally rests on counter-order rather than a chain-link path. */
59
+ weaker: boolean;
60
+ /** Plain-language statement of exactly what was compared and why it answered this way. */
61
+ detail: string;
62
+ }
63
+ /**
64
+ * Pin selecting one occurrence when the same bits hold several causal
65
+ * positions. Exactly one of the two forms.
66
+ */
67
+ export type CastPin = {
68
+ proofHash: string;
69
+ } | {
70
+ epochId: string;
71
+ counter: string;
72
+ };
73
+ /**
74
+ * One cast role. Everything here is DECLARED: taken on the rule author's
75
+ * word, surfaced in the verdict's `declared` block, never derived.
76
+ */
77
+ export interface CastEntry {
78
+ /**
79
+ * Artifact digest identifying the bits. Accepted forms: "sha256:<64 hex>",
80
+ * bare 64-char hex, standard base64, or base64url of the 32-byte digest.
81
+ * Normalized internally to the proof's base64 form.
82
+ */
83
+ digest: string;
84
+ /** What the digest means as a business object. Declared, echoed, never interpreted. */
85
+ means?: string;
86
+ /** Selects one recording when the digest holds several causal positions. */
87
+ at?: CastPin;
88
+ /**
89
+ * External identity evidence (e.g. a C2PA manifest reference). Player
90
+ * echoes it into `declared` verbatim with verifiedHere: false. SIGNED_BY
91
+ * is not a BitGraph primitive and is never derived here.
92
+ */
93
+ signedBy?: unknown;
94
+ /** When true, absence from the bundle is a definite fact under the closed world, not an error. */
95
+ optional?: boolean;
96
+ }
97
+ export type Claim = {
98
+ exists: string;
99
+ } | {
100
+ before: [string, string];
101
+ } | {
102
+ after: [string, string];
103
+ } | {
104
+ between: [string, string, string];
105
+ } | {
106
+ all: Claim[];
107
+ } | {
108
+ any: Claim[];
109
+ } | {
110
+ not: Claim;
111
+ };
112
+ export interface Rule {
113
+ rule: "bitgraph-player/1";
114
+ id: string;
115
+ cast: Record<string, CastEntry>;
116
+ /** The only defined value. Absence is only ever asserted within the declared cast. */
117
+ world: "closed";
118
+ /**
119
+ * Mandatory. A rule that does not state its trust floor does not parse:
120
+ * the rule carries its own security policy.
121
+ */
122
+ requires: {
123
+ ordering: EvidenceTier;
124
+ };
125
+ claim: Claim;
126
+ /**
127
+ * A label and nothing else. No field in this format is capable of
128
+ * causing an action; Player decides, it does not enforce.
129
+ */
130
+ then?: {
131
+ label: string;
132
+ };
133
+ }
134
+ /**
135
+ * A digest identifies bits; a recording identifies an occurrence of those
136
+ * bits at a causal position. A cast role resolves to a RECORDING. Two or
137
+ * more matches with no pin is UNDETERMINED, never a silent pick.
138
+ */
139
+ export type Resolution = {
140
+ kind: "resolved";
141
+ role: string;
142
+ proof: ObservedProof;
143
+ /** Verification tier the resolution rests on ("full" | "integrity"). */
144
+ verificationTier: string;
145
+ /** How many verified recordings of this digest the bundle holds. */
146
+ matchCount: number;
147
+ } | {
148
+ kind: "absent";
149
+ role: string;
150
+ optional: boolean;
151
+ } | {
152
+ kind: "ambiguous";
153
+ role: string;
154
+ matchCount: number;
155
+ candidates: string[];
156
+ } | {
157
+ kind: "invalid";
158
+ role: string;
159
+ reason: string;
160
+ };
161
+ /** One evaluated sub-claim, in evaluation order. Everything BitGraph established. */
162
+ export interface DerivedStep {
163
+ claim: string;
164
+ result: ThreeValued;
165
+ basis?: OrderBasis;
166
+ evidenceTier?: EvidenceTier;
167
+ because: Record<string, unknown>;
168
+ }
169
+ /** One assertion Player took on somebody's word. */
170
+ export interface DeclaredEntry {
171
+ assertion: "signedBy" | "means" | "closed-world" | "pinned-occurrence";
172
+ role?: string;
173
+ verifiedHere: false;
174
+ [k: string]: unknown;
175
+ }
176
+ export interface Verdict {
177
+ verdict: "bitgraph-player-verdict/1";
178
+ result: ThreeValued;
179
+ rule: {
180
+ id: string;
181
+ sha256: string;
182
+ };
183
+ then?: {
184
+ label: string;
185
+ };
186
+ /** Weakest evidence tier any contributing ordering answer rested on. Absent when no ordering was used. */
187
+ weakestEvidence?: EvidenceTier;
188
+ cast: Record<string, {
189
+ digestB64: string;
190
+ resolution: string;
191
+ proofHash?: string;
192
+ epochId?: string;
193
+ chainId?: string;
194
+ counter?: string;
195
+ slotCounter?: string;
196
+ }>;
197
+ derived: DerivedStep[];
198
+ declared: DeclaredEntry[];
199
+ evaluator: {
200
+ name: string;
201
+ version: string;
202
+ };
203
+ network: "none";
204
+ }
205
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,16 @@
1
+ // Copyright (c) 2024-2026 Mike Argento. Licensed under the MIT License. See LICENSE.
2
+ export function basisTier(basis) {
3
+ switch (basis) {
4
+ case "chain-link":
5
+ case "epoch-lineage":
6
+ return "hash-linked";
7
+ case "counter-order":
8
+ case "anchor-bounds":
9
+ return "assumption-dependent";
10
+ }
11
+ }
12
+ /** True when `tier` satisfies a declared floor. */
13
+ export function meetsFloor(tier, floor) {
14
+ return floor === "assumption-dependent" || tier === "hash-linked";
15
+ }
16
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,qFAAqF;AAqDrF,MAAM,UAAU,SAAS,CAAC,KAAiB;IACzC,QAAQ,KAAK,EAAE,CAAC;QACd,KAAK,YAAY,CAAC;QAClB,KAAK,eAAe;YAClB,OAAO,aAAa,CAAC;QACvB,KAAK,eAAe,CAAC;QACrB,KAAK,eAAe;YAClB,OAAO,sBAAsB,CAAC;IAClC,CAAC;AACH,CAAC;AAED,mDAAmD;AACnD,MAAM,UAAU,UAAU,CAAC,IAAkB,EAAE,KAAmB;IAChE,OAAO,KAAK,KAAK,sBAAsB,IAAI,IAAI,KAAK,aAAa,CAAC;AACpE,CAAC"}
@@ -0,0 +1,14 @@
1
+ import type { AuditResult } from "@mikeargento/bitgraph-audit";
2
+ import type { Evaluation } from "./evaluate.js";
3
+ import type { Resolution, Rule, Verdict } from "./types.js";
4
+ /** The player package's own version, read once from its package.json. */
5
+ export declare function playerVersion(): string;
6
+ export declare function buildVerdict(rule: Rule, ruleSha256Hex: string, resolutions: Map<string, Resolution>, evaluation: Evaluation, audit: AuditResult): Verdict;
7
+ /**
8
+ * Deterministic bytes. Fixed key order (construction order), two-space
9
+ * indent, trailing newline. No timestamp: a `generatedAt` field would
10
+ * break byte-identical reproduction, which is the entire product claim.
11
+ * If a run timestamp is wanted it belongs in a sidecar, never here.
12
+ */
13
+ export declare function serializeVerdict(verdict: Verdict): string;
14
+ //# sourceMappingURL=verdict.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verdict.d.ts","sourceRoot":"","sources":["../src/verdict.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEhD,OAAO,KAAK,EAAiB,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAI3E,yEAAyE;AACzE,wBAAgB,aAAa,IAAI,MAAM,CAMtC;AAeD,wBAAgB,YAAY,CAC1B,IAAI,EAAE,IAAI,EACV,aAAa,EAAE,MAAM,EACrB,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,EACpC,UAAU,EAAE,UAAU,EACtB,KAAK,EAAE,WAAW,GACjB,OAAO,CA6ET;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAkBzD"}