@mikeargento/bitgraph 1.1.0 → 1.1.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 (144) hide show
  1. package/README.md +49 -40
  2. package/dist/__tests__/audit-anchors.test.d.ts +2 -0
  3. package/dist/__tests__/audit-anchors.test.d.ts.map +1 -0
  4. package/dist/__tests__/audit-anchors.test.js +152 -0
  5. package/dist/__tests__/audit-anchors.test.js.map +1 -0
  6. package/dist/__tests__/audit-anomalies.test.d.ts +2 -0
  7. package/dist/__tests__/audit-anomalies.test.d.ts.map +1 -0
  8. package/dist/__tests__/audit-anomalies.test.js +663 -0
  9. package/dist/__tests__/audit-anomalies.test.js.map +1 -0
  10. package/dist/__tests__/audit-attestation.test.d.ts +2 -0
  11. package/dist/__tests__/audit-attestation.test.d.ts.map +1 -0
  12. package/dist/__tests__/audit-attestation.test.js +403 -0
  13. package/dist/__tests__/audit-attestation.test.js.map +1 -0
  14. package/dist/__tests__/audit-bench-smoke.test.d.ts +2 -0
  15. package/dist/__tests__/audit-bench-smoke.test.d.ts.map +1 -0
  16. package/dist/__tests__/audit-bench-smoke.test.js +87 -0
  17. package/dist/__tests__/audit-bench-smoke.test.js.map +1 -0
  18. package/dist/__tests__/audit-boundary.test.d.ts +20 -0
  19. package/dist/__tests__/audit-boundary.test.d.ts.map +1 -0
  20. package/dist/__tests__/audit-boundary.test.js +84 -0
  21. package/dist/__tests__/audit-boundary.test.js.map +1 -0
  22. package/dist/__tests__/audit-cli.test.d.ts +2 -0
  23. package/dist/__tests__/audit-cli.test.d.ts.map +1 -0
  24. package/dist/__tests__/audit-cli.test.js +239 -0
  25. package/dist/__tests__/audit-cli.test.js.map +1 -0
  26. package/dist/__tests__/audit-dependencies.test.d.ts +2 -0
  27. package/dist/__tests__/audit-dependencies.test.d.ts.map +1 -0
  28. package/dist/__tests__/audit-dependencies.test.js +116 -0
  29. package/dist/__tests__/audit-dependencies.test.js.map +1 -0
  30. package/dist/__tests__/audit-fixtures.d.ts +265 -0
  31. package/dist/__tests__/audit-fixtures.d.ts.map +1 -0
  32. package/dist/__tests__/audit-fixtures.js +511 -0
  33. package/dist/__tests__/audit-fixtures.js.map +1 -0
  34. package/dist/__tests__/audit-ingest.test.d.ts +2 -0
  35. package/dist/__tests__/audit-ingest.test.d.ts.map +1 -0
  36. package/dist/__tests__/audit-ingest.test.js +473 -0
  37. package/dist/__tests__/audit-ingest.test.js.map +1 -0
  38. package/dist/__tests__/audit-memory-ingest.test.d.ts +12 -0
  39. package/dist/__tests__/audit-memory-ingest.test.d.ts.map +1 -0
  40. package/dist/__tests__/audit-memory-ingest.test.js +120 -0
  41. package/dist/__tests__/audit-memory-ingest.test.js.map +1 -0
  42. package/dist/__tests__/audit-property.test.d.ts +2 -0
  43. package/dist/__tests__/audit-property.test.d.ts.map +1 -0
  44. package/dist/__tests__/audit-property.test.js +771 -0
  45. package/dist/__tests__/audit-property.test.js.map +1 -0
  46. package/dist/__tests__/audit-real-fixtures.test.d.ts +2 -0
  47. package/dist/__tests__/audit-real-fixtures.test.d.ts.map +1 -0
  48. package/dist/__tests__/audit-real-fixtures.test.js +132 -0
  49. package/dist/__tests__/audit-real-fixtures.test.js.map +1 -0
  50. package/dist/__tests__/audit-real-live.test.d.ts +2 -0
  51. package/dist/__tests__/audit-real-live.test.d.ts.map +1 -0
  52. package/dist/__tests__/audit-real-live.test.js +107 -0
  53. package/dist/__tests__/audit-real-live.test.js.map +1 -0
  54. package/dist/__tests__/audit-reconstruct.test.d.ts +2 -0
  55. package/dist/__tests__/audit-reconstruct.test.d.ts.map +1 -0
  56. package/dist/__tests__/audit-reconstruct.test.js +287 -0
  57. package/dist/__tests__/audit-reconstruct.test.js.map +1 -0
  58. package/dist/__tests__/audit-report.test.d.ts +2 -0
  59. package/dist/__tests__/audit-report.test.d.ts.map +1 -0
  60. package/dist/__tests__/audit-report.test.js +186 -0
  61. package/dist/__tests__/audit-report.test.js.map +1 -0
  62. package/dist/__tests__/audit-roundtrip.test.d.ts +2 -0
  63. package/dist/__tests__/audit-roundtrip.test.d.ts.map +1 -0
  64. package/dist/__tests__/audit-roundtrip.test.js +368 -0
  65. package/dist/__tests__/audit-roundtrip.test.js.map +1 -0
  66. package/dist/__tests__/audit-temporal.test.d.ts +2 -0
  67. package/dist/__tests__/audit-temporal.test.d.ts.map +1 -0
  68. package/dist/__tests__/audit-temporal.test.js +364 -0
  69. package/dist/__tests__/audit-temporal.test.js.map +1 -0
  70. package/dist/__tests__/audit-tiers.test.d.ts +2 -0
  71. package/dist/__tests__/audit-tiers.test.d.ts.map +1 -0
  72. package/dist/__tests__/audit-tiers.test.js +282 -0
  73. package/dist/__tests__/audit-tiers.test.js.map +1 -0
  74. package/dist/__tests__/audit-witness-real.test.d.ts +19 -0
  75. package/dist/__tests__/audit-witness-real.test.d.ts.map +1 -0
  76. package/dist/__tests__/audit-witness-real.test.js +82 -0
  77. package/dist/__tests__/audit-witness-real.test.js.map +1 -0
  78. package/dist/__tests__/audit-witness.test.d.ts +2 -0
  79. package/dist/__tests__/audit-witness.test.d.ts.map +1 -0
  80. package/dist/__tests__/audit-witness.test.js +308 -0
  81. package/dist/__tests__/audit-witness.test.js.map +1 -0
  82. package/dist/__tests__/chain-hash-anchor.test.d.ts +22 -0
  83. package/dist/__tests__/chain-hash-anchor.test.d.ts.map +1 -0
  84. package/dist/__tests__/chain-hash-anchor.test.js +55 -0
  85. package/dist/__tests__/chain-hash-anchor.test.js.map +1 -0
  86. package/dist/__tests__/declared-proof-fixture.d.ts +66 -0
  87. package/dist/__tests__/declared-proof-fixture.d.ts.map +1 -0
  88. package/dist/__tests__/declared-proof-fixture.js +66 -0
  89. package/dist/__tests__/declared-proof-fixture.js.map +1 -0
  90. package/dist/__tests__/mock-proof-fixture.d.ts +15 -0
  91. package/dist/__tests__/mock-proof-fixture.d.ts.map +1 -0
  92. package/dist/__tests__/mock-proof-fixture.js +34 -0
  93. package/dist/__tests__/mock-proof-fixture.js.map +1 -0
  94. package/dist/__tests__/proof-hash-regression.test.js +4 -43
  95. package/dist/__tests__/proof-hash-regression.test.js.map +1 -1
  96. package/dist/__tests__/proof-hash.test.js +3 -21
  97. package/dist/__tests__/proof-hash.test.js.map +1 -1
  98. package/dist/__tests__/proof-integrity.test.d.ts +2 -0
  99. package/dist/__tests__/proof-integrity.test.d.ts.map +1 -0
  100. package/dist/__tests__/proof-integrity.test.js +426 -0
  101. package/dist/__tests__/proof-integrity.test.js.map +1 -0
  102. package/dist/__tests__/realistic-proof-fixture.d.ts +56 -0
  103. package/dist/__tests__/realistic-proof-fixture.d.ts.map +1 -0
  104. package/dist/__tests__/realistic-proof-fixture.js +57 -0
  105. package/dist/__tests__/realistic-proof-fixture.js.map +1 -0
  106. package/dist/__tests__/verifier.test.js +74 -0
  107. package/dist/__tests__/verifier.test.js.map +1 -1
  108. package/package.json +10 -5
  109. package/src/__tests__/audit-anchors.test.ts +188 -0
  110. package/src/__tests__/audit-anomalies.test.ts +815 -0
  111. package/src/__tests__/audit-attestation.test.ts +529 -0
  112. package/src/__tests__/audit-bench-smoke.test.ts +108 -0
  113. package/src/__tests__/audit-boundary.test.ts +96 -0
  114. package/src/__tests__/audit-cli.test.ts +288 -0
  115. package/src/__tests__/audit-dependencies.test.ts +141 -0
  116. package/src/__tests__/audit-fixtures.ts +736 -0
  117. package/src/__tests__/audit-ingest.test.ts +575 -0
  118. package/src/__tests__/audit-memory-ingest.test.ts +140 -0
  119. package/src/__tests__/audit-property.test.ts +892 -0
  120. package/src/__tests__/audit-real-fixtures.test.ts +153 -0
  121. package/src/__tests__/audit-real-live.test.ts +128 -0
  122. package/src/__tests__/audit-reconstruct.test.ts +353 -0
  123. package/src/__tests__/audit-report.test.ts +222 -0
  124. package/src/__tests__/audit-roundtrip.test.ts +464 -0
  125. package/src/__tests__/audit-temporal.test.ts +446 -0
  126. package/src/__tests__/audit-tiers.test.ts +343 -0
  127. package/src/__tests__/audit-witness-real.test.ts +92 -0
  128. package/src/__tests__/audit-witness.test.ts +345 -0
  129. package/src/__tests__/chain-hash-anchor.test.ts +67 -0
  130. package/src/__tests__/declared-proof-fixture.ts +65 -0
  131. package/src/__tests__/mock-proof-fixture.ts +36 -0
  132. package/src/__tests__/proof-hash-regression.test.ts +4 -44
  133. package/src/__tests__/proof-hash.test.ts +3 -22
  134. package/src/__tests__/proof-integrity.test.ts +541 -0
  135. package/src/__tests__/real-fixtures/anchor-after-112762.json +47 -0
  136. package/src/__tests__/real-fixtures/anchor-with-ethereum-112758.json +47 -0
  137. package/src/__tests__/real-fixtures/live-proof-0.json +42 -0
  138. package/src/__tests__/real-fixtures/live-proof-1.json +43 -0
  139. package/src/__tests__/real-fixtures/live-proof-2.json +43 -0
  140. package/src/__tests__/real-fixtures/successor-112760.json +38 -0
  141. package/src/__tests__/real-fixtures/witness-25525146.json +6 -0
  142. package/src/__tests__/real-fixtures/witness-25525147.json +6 -0
  143. package/src/__tests__/realistic-proof-fixture.ts +57 -0
  144. package/src/__tests__/verifier.test.ts +83 -0
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # BitGraph
2
2
 
3
- **Portable cryptographic proof of construction for digital artifacts.**
3
+ **A BitGraph gives bits a place.**
4
4
 
5
5
  [![npm @mikeargento/bitgraph](https://img.shields.io/npm/v/@mikeargento/bitgraph?label=%40mikeargento%2Fbitgraph&color=cb3837)](https://www.npmjs.com/package/@mikeargento/bitgraph)
6
6
  [![Website](https://img.shields.io/badge/bitgraph.ing-live-0065A4)](https://bitgraph.ing)
@@ -8,11 +8,11 @@
8
8
 
9
9
  ---
10
10
 
11
- Just as a photograph captures photons through the constraint of a single frame of film, a BitGraph captures bits through the constraint of a single mathematical slot.
11
+ BitGraphs are not labels or metadata added after the fact. They are new computations created when your file's hash *fills* a pre-existing cryptographic slot, constraining the commitment so it cannot be retroactively constructed. This occurs entirely off-chain and produces a proof permanently bound to that exact digital state.
12
12
 
13
- Origin can be enforced or it can be claimed. Most digital provenance systems claim it. They produce an artifact and then attach a signature, a timestamp, or a metadata block describing where the artifact came from. The claim arrives after the artifact already exists, which is the wrong end of the timeline.
13
+ Provenance can be enforced or it can be claimed. Most systems claim it: they bind a statement about the content to the content itself. That binding can be cryptographically strong, and it can be made at the moment of capture rather than afterward, so the weakness is not timing. The weakness is that a claim is something a trusted signer can attach to any artifact at all. The artifact does not have to satisfy any prior condition to receive one.
14
14
 
15
- BitGraph enforces origin. A measured trusted execution environment creates an unpredictable cryptographic slot before the artifact's hash is known. The artifact's hash arrives later and is bound into the slot. The slot is consumed and cannot be reused. What emerges is not a description of provenance but a proof of construction.
15
+ BitGraph enforces it instead. A measured trusted execution environment creates an unpredictable cryptographic slot before the artifact's hash reaches it. The artifact's hash arrives later and is bound into the slot. The slot is consumed and cannot be reused. What emerges is not a description of provenance but a proof of placement.
16
16
 
17
17
  > This exact digital state was committed through this measured process, in this order, under these constraints.
18
18
 
@@ -20,32 +20,32 @@ BitGraph enforces origin. A measured trusted execution environment creates an un
20
20
 
21
21
  Nonce first. Hash second. Atomic binding third.
22
22
 
23
- The TEE generates hardware entropy inside the enclave. That entropy becomes a slot, signed with the enclave's key, with an identity no attacker could have precomputed. The slot exists as a cryptographic object before any artifact hash has been seen.
23
+ The TEE generates hardware entropy inside the enclave. That entropy becomes a slot, signed with the enclave's key, with an identity that could not feasibly have been predicted. The slot exists as a cryptographic object before it has seen any artifact hash.
24
24
 
25
25
  The artifact hash arrives. The TEE binds the hash into the slot, signs the binding, and advances its internal order. The slot becomes consumed.
26
26
 
27
27
  > UNUSED slot exists first. Artifact hash enters later. TEE binds the hash to the slot. Slot becomes CONSUMED. Proof travels with the artifact.
28
28
 
29
- The atomicity is the whole guarantee. The slot is allocated and signed before the hash is known. The slot can be consumed exactly once by a single binding operation. The artifact itself can be produced anywhere, by any process, using any tools. What matters is that when the hash arrives, the slot is already there waiting.
29
+ The atomicity is the whole guarantee, and it constrains the record rather than the artifact. The artifact itself can be produced anywhere, by any process, using any tools. What matters is that when the hash arrives, the slot is already there waiting.
30
30
 
31
- Most systems say: "Here is a file hash. Now let's sign it." BitGraph says: "Here is a pre-existing origin slot. Now this file hash has occupied it."
31
+ Most systems begin with the bits. BitGraph begins with the place. They say: "Here is a file hash. Now let's sign it." BitGraph says: "Here is a pre-existing position. Now this file hash has occupied it."
32
32
 
33
33
  ## Why nonce-first matters
34
34
 
35
- If a nonce, timestamp, or credential is added after the hash is already witnessed, it is just a label. It can prove someone signed something. It can prove a record existed by some moment. It cannot constrain the artifact's origin, because the artifact already existed before the nonce entered the picture.
35
+ If a nonce, timestamp, or credential is added after the hash is already witnessed, it is just a label. It can prove someone signed something. It can prove a record existed by some moment. It cannot impose a prior condition merely by being attached afterward. The credential may describe where the artifact came from, but the artifact never had to consume a pre-existing, single-use position in order to receive one.
36
36
 
37
- That leaves a forgery window. A malicious actor can prepare old hashes, replay prior material, backfill records, or attach fresh randomness to something never produced through the claimed path. The label looks valid. The construction was never constrained.
37
+ That leaves a forgery window. A malicious actor can prepare old hashes, replay prior material, backfill records, or attach fresh randomness to something never produced through the claimed path. The label looks valid. Nothing had to be true before it was attached.
38
38
 
39
- BitGraph closes the window by requiring the slot to exist first. The slot is not evidence added afterward. It is the condition the artifact must satisfy.
39
+ BitGraph narrows that window by requiring the slot to exist first. It does not stop an old file being committed today: the hash occupies a slot allocated today, and the position claims nothing about when the bytes were made. What it stops is a position being invented after the fact, or occupied twice. The slot is not evidence added afterward. It is the condition the artifact must satisfy.
40
40
 
41
41
  ## What a BitGraph proof contains
42
42
 
43
- A BitGraph proof is a portable proof object, typically JSON, that travels with the artifact. It can include:
43
+ A BitGraph proof is a portable proof object, a JSON document, that travels with the artifact. It can include:
44
44
 
45
45
  | Component | Purpose |
46
46
  |---|---|
47
47
  | Artifact hash | Identifies the exact file or digital state |
48
- | Nonce | The pre-existing causal slot |
48
+ | Nonce | Hardware entropy giving the slot an identity that cannot feasibly be predicted |
49
49
  | Slot counter | Shows the slot was allocated before the commit |
50
50
  | Commit counter | Shows the artifact consumed the slot later |
51
51
  | Epoch ID | Groups an ordered run of commitments |
@@ -56,39 +56,39 @@ A BitGraph proof is a portable proof object, typically JSON, that travels with t
56
56
  | Attestation | Shows the proof came from measured hardware |
57
57
  | Public anchor | Tethers BitGraph logical time to a public reference |
58
58
 
59
- The result is not "a file was signed." It is: this hash was committed into this causal slot, by this measured environment, at this position in logical order, under this signing identity.
59
+ Taken together: this hash was committed into this causal slot, by this measured environment, at this position in logical order, under this signing identity.
60
60
 
61
61
  ## Logical time
62
62
 
63
63
  Every proof has order. Every slot and commit has a position. The system can prove that this happened after that, that this slot existed before this hash was bound, that this proof came before the next, that this epoch has an internal cryptographic history.
64
64
 
65
- BitGraph proves causal order first. Clock time is optional.
65
+ BitGraph proves causal order. It does not assert a clock time.
66
66
 
67
- ## Ethereum: the backward seal
67
+ ## Establishing wall clock time
68
68
 
69
- BitGraph's internal ordering does not require Ethereum. The chain creates internal order through slot allocation, consumption, counters, signatures, and chained proof history. Ethereum anchors add a different property on top: a public backward seal that any third party can independently verify.
69
+ BitGraph's internal ordering does not require Ethereum. The chain creates internal order through slot allocation, consumption, counters, signatures, and chained proof history. What that order lacks, on its own, is a clock. The enclave keeps no trusted one; any clock reading inside a proof is advisory.
70
70
 
71
- An Ethereum block hash that becomes available after the artifact has been committed could not have been known at the moment of commitment. This produces an entropy sandwich:
71
+ Ethereum is where the order meets the wall clock. An anchor is an ordinary proof on the same chain whose artifact is the hash of a recent Ethereum block. A block hash does not exist before its block is produced, so the anchor, and every proof chained after it, came after that block and its public date. Anchors recur throughout every epoch. This is the wall-clock statement every proof page shows, and it runs in one direction: provably no earlier than. The other side of the window narrows through the chain's cadence, measured enclave behavior rather than public data, which is why it is narrowed, not closed.
72
72
 
73
- 1. Private TEE entropy before the artifact.
74
- 2. Artifact commitment in the middle.
75
- 3. Public blockchain entropy after it.
73
+ The anchors also fix history backward, through content. Each anchor is hash-linked to everything before it, so once an anchor exists, the history behind it is fixed: alter any earlier proof and the chain no longer reaches the anchor. When the epoch ends, its signing key is destroyed, and the set closes.
76
74
 
77
- The artifact was committed after the TEE-created slot existed and before the later Ethereum block was knowable. That bounds the commitment in adversary-resistant entropy, witnessed in a public timeline anyone can check years later.
75
+ Ethereum is not asked to be a good source of randomness, and it is not asked to establish the artifact's position. BitGraph establishes the position. Ethereum ties the positions to the public timeline, so anyone, years later, can check the order and the earliest date each position could have existed.
78
76
 
79
- Ethereum is not asked to prove the artifact's origin. BitGraph does that. Ethereum provides the backward seal that makes the commitment publicly verifiable.
77
+ ## Compromise and containment
80
78
 
81
- ## Multi-TEE breach detection
79
+ BitGraph assumes the boundary can be compromised and bounds the damage instead of claiming it cannot happen.
82
80
 
83
- BitGraph's architecture supports running three independent TEEs in parallel as a tripwire, not a consensus system. Three TEEs witness the same input and produce three individual proofs with different nonces, signatures, and attestations. They agree on the meaningful result: same artifact hash, same policy decision, valid measurements, valid signatures, expected ordering behavior.
81
+ The signing key exists only in enclave memory. Every restart destroys it and begins a new epoch with a fresh key and a fresh counter. Proofs from prior epochs were signed by keys that no longer exist, so a compromise cannot reach backward.
84
82
 
85
- If one diverges, the system does not need to know which one is compromised. It only needs to know something is wrong. The batch is quarantined, the affected range is marked suspect, the epoch is rotated, and downstream verification accounts for the gap.
83
+ Forgery requires more than key theft. Every proof carries a hardware attestation whose user_data must equal the hash of that exact proof body, and only the enclave's secure module can produce one. A useful breach must execute inside the running enclave, and it dies at the next restart.
86
84
 
87
- This is not "trust this TEE forever." It is: compromise is assumed, silence is what gets eliminated.
85
+ Damage control is precise. Every proof names its epoch permanently, so a suspect window is identified exactly: rotate the epoch, publish the affected epochId as quarantined, and every other epoch is untouched. Verifiers that pin measurements and track epochs account for the gap.
86
+
87
+ The production deployment makes rotation routine rather than exceptional: the boundary restarts every day at 23:59 UTC, destroying the epoch key and starting a fresh one, so a normally operating epoch runs about a day. An unexpected restart ends one early and a failed rotation extends one; either way the boundary is recorded in the proofs themselves. A breach that depends on staying resident inside the enclave cannot outlive its epoch without freshly re-compromising a new one. The schedule is deliberately public: rotation times are visible on the ledger regardless, and the protection comes from the key dying, not from anyone guessing when.
88
88
 
89
89
  ## The trust model
90
90
 
91
- BitGraph does not depend on blind trust in any single component. Not the operator, the TEE, Ethereum, the clock, a certificate authority, or a live server. Each layer adds an independently verifiable property.
91
+ BitGraph does not ask for blind trust in any single component. It has real dependencies, and the point is that each one is inspectable rather than assumed: the enclave's attestation chains to the AWS Nitro Attestation PKI root, and the measurement it carries is published, so both are things you check rather than things you take on faith. Each layer adds an independently verifiable property.
92
92
 
93
93
  | Layer | What it contributes |
94
94
  |---|---|
@@ -97,8 +97,7 @@ BitGraph does not depend on blind trust in any single component. Not the operato
97
97
  | Atomic binding | Prevents post-hoc attachment |
98
98
  | Counters | Internal logical order |
99
99
  | Proof chain | Historical continuity |
100
- | Ethereum anchor | Public backward seal |
101
- | Multi-TEE redundancy | Breach visibility |
100
+ | Ethereum anchor | Public wall-clock bound |
102
101
  | Epoch rotation | Damage containment |
103
102
  | Portable verification | Independence from the original server |
104
103
 
@@ -106,11 +105,11 @@ BitGraph does not depend on blind trust in any single component. Not the operato
106
105
 
107
106
  BitGraph works on any digital state that can be hashed. The same primitive applies whether the artifact is a photograph, a contract, a model output, a dataset, or a software release.
108
107
 
109
- **Media.** Photos, videos, audio, edited files, generative outputs. The question shifts from "is this real?" to "what origin path does this artifact satisfy?"
108
+ **Media.** Photos, videos, audio, edited files, generative outputs. The question shifts from "is this real?" to "what position does this exact digital state occupy?"
110
109
 
111
- **AI outputs.** Model results bound to authenticated identity and causal position without requiring the model to run inside an enclave.
110
+ **AI outputs.** Model results bound to a causal position, and optionally to a key that authorized the recording, without requiring the model to run inside an enclave.
112
111
 
113
- **Software supply chain.** Build artifacts, releases, model weights, and deployment packages bound to a measured construction path.
112
+ **Software supply chain.** Build artifacts, releases, model weights, and deployment packages bound to a position in a measured sequence.
114
113
 
115
114
  **Legal and clinical records.** Contracts, filings, telehealth session manifests, lab results, and consent forms with independently verifiable causal ordering.
116
115
 
@@ -124,22 +123,24 @@ BitGraph is often confused with adjacent systems. The differences are structural
124
123
  |---|---|---|
125
124
  | Signatures | This key signed this data | This key was controlled by a measured environment that consumed an unused slot |
126
125
  | Timestamps | This hash existed by time T | This hash consumed a pre-existing slot at this position in causal order |
127
- | C2PA | Here are signed claims about this content | Here is the construction path this content satisfied |
128
- | Blockchains | Public ordering of shared transactions | Private origin coordinates with optional public anchoring |
126
+ | C2PA | Here are signed claims about this content | This exact digital state occupied this pre-existing position |
127
+ | Blockchains | Public ordering of shared transactions | Ordering established inside a measured enclave, then anchored publicly |
129
128
 
130
- Signatures, timestamps, content credentials, and blockchains all answer "who claimed what, when?" BitGraph answers "what construction path did this exact artifact satisfy?" They are complementary, not competing. A signature can be inside a BitGraph proof. A timestamp can decorate one. Content credentials can ride alongside one. None of them, alone, do what BitGraph does.
129
+ Signatures, timestamps, content credentials, and blockchains all answer "who claimed what, when?" BitGraph answers "what position does this exact digital state occupy?" They are complementary, not competing. A signature can be inside a BitGraph proof. A timestamp can decorate one. Content credentials can ride alongside one. None of them, alone, do what BitGraph does.
131
130
 
132
- ## Multiple copies of the same original
131
+ ## Every copy carries the same position
133
132
 
134
- Physical originality depends on singularity. There is one canvas, one negative, one signed paper. Digital files broke that because perfect copies are indistinguishable from the source.
133
+ Physical originality depended on singularity. There was one canvas, one negative, one signed paper, and the object's uniqueness was how you knew it came from the author's hand. Digital files broke that. Perfect copies are indistinguishable from the source, so the physical anchor for originality stopped working.
135
134
 
136
- BitGraph introduces a different category. A digital artifact can be copied without losing its original provenance. The proof travels with the bytes or alongside them. Instead of every copy being a degraded copy, BitGraph allows multiple copies of the same original. Originality moves from physical container to causal proof. Singularity is no longer required for originality.
135
+ BitGraph does not restore originality. It makes it unnecessary. The artifact's hash is the proof's anchor, so any exact copy of the bytes carries the same position, and no copy has to be the special one. The proof object itself can travel with the file, stay on the server that issued it, or be stored anywhere, and each of those can have copies too. Verification does not depend on where anything lives. What used to need a unique object now needs only the exact bytes.
137
136
 
138
137
  ## The simplest version
139
138
 
140
- A measured TEE creates a random unused slot before the artifact hash arrives. The hash arrives. The TEE binds it to the slot, consumes the slot, signs the result, and links it into an ordered chain. Three TEEs can run in parallel so silent compromise becomes visible. The same mechanism periodically commits an Ethereum block hash, sealing everything before it in a public timeline.
139
+ A measured TEE creates a random unused slot before the artifact hash arrives. The hash arrives. The TEE binds it to the slot, consumes the slot, signs the result, and links it into an ordered chain. Every restart begins a new epoch with a new key, so a compromised boundary is bounded, never retroactive. The same mechanism periodically commits an Ethereum block hash, fixing the history behind it and giving everything after it a public date it provably followed.
140
+
141
+ The result is a protocol that does not say "someone signed this."
141
142
 
142
- The result is a provenance system that does not say "someone signed this." It says: this exact artifact occupied this origin coordinate.
143
+ **It proves: these exact bits occupy this position.**
143
144
 
144
145
  ---
145
146
 
@@ -164,6 +165,14 @@ if (result.ok) {
164
165
 
165
166
  See [bitgraph.ing/docs](https://bitgraph.ing/docs) for the full proof format, verification checklist, attestation handling, and self-host instructions.
166
167
 
168
+ ## Verification and audit packages
169
+
170
+ Two MIT-licensed packages in this repository make BitGraph evidence checkable without permission:
171
+
172
+ **[`@mikeargento/bitgraph-verify`](https://www.npmjs.com/package/@mikeargento/bitgraph-verify)** verifies one proof. `verify()` checks a proof against the original artifact bytes: structure, canonical Ed25519 signature, slot binding, epoch link, and the digest match. `verifyProofIntegrity()` runs every check except the artifact binding for cases where the bytes are not available, and its result states explicitly that the binding was not checked.
173
+
174
+ **`@mikeargento/bitgraph-audit`** audits a whole bundle of proofs, fully offline. It ingests a directory, `.tar`, or `.tar.gz`, verifies every proof through the canonical verifier, reconstructs causal order from the hash links and counters, classifies anomalies with stable machine-readable codes, and preserves divergence between valid proofs for the reader to adjudicate instead of choosing a winner. It ships a CLI (`bitgraph-audit <bundle>`) that writes machine-readable and human-readable reports. The bundle format is specified in [docs/BUNDLE-FORMAT.md](docs/BUNDLE-FORMAT.md); the recipient walkthrough is [docs/HOW-TO-AUDIT.md](docs/HOW-TO-AUDIT.md).
175
+
167
176
  ## License
168
177
 
169
178
  Copyright 2024-2026 Mike Argento. All rights reserved. Patent Pending.
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=audit-anchors.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit-anchors.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/audit-anchors.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,152 @@
1
+ // Copyright (c) Mike Argento. All rights reserved. See LICENSE.
2
+ /**
3
+ * Anchor identification tests (G5): the SIGNED attribution.name is the
4
+ * discriminator; unsigned metadata.type is corroboration only, recorded
5
+ * but never trusted; the block number comes only from the signed
6
+ * Etherscan URL; no wall-clock time is ever derived from anything here.
7
+ */
8
+ import { describe, it } from "node:test";
9
+ import * as assert from "node:assert/strict";
10
+ import { identifyAnchors, ingestBundle, verifyObservedProofs, } from "@mikeargento/bitgraph-audit";
11
+ import { makeAnchorProof, makeChainIdProof, makeTempDir, proofJson, writeBundleDir, } from "./audit-fixtures.js";
12
+ const BLOCK_HASH = "0x28ed3639cd705fb8cb2b915c1991e9f808b40e775bc8eb540702942729fec2c0";
13
+ async function ingestAndVerify(files) {
14
+ const dir = await makeTempDir("bg-audit-anchors-");
15
+ await writeBundleDir(dir, files);
16
+ const ingest = await ingestBundle(dir);
17
+ await verifyObservedProofs(ingest);
18
+ return ingest;
19
+ }
20
+ describe("audit anchors: identification by signed attribution", () => {
21
+ it("identifies an anchor by attribution.name and extracts the signed facts", async () => {
22
+ const anchor = await makeAnchorProof({
23
+ blockHash: BLOCK_HASH,
24
+ blockNumber: "24800448",
25
+ epochId: "EPOCH-A",
26
+ counter: "4",
27
+ slotCounter: "3",
28
+ chainId: "bitgraph:main",
29
+ metadata: {
30
+ type: "ethereum-anchor",
31
+ anchor: { blockNumber: 24800448, blockHash: BLOCK_HASH, blockTime: 1750000000 },
32
+ },
33
+ });
34
+ const user = await makeChainIdProof({ chainId: "bitgraph:main", counter: "6", epochId: "EPOCH-A" });
35
+ const ingest = await ingestAndVerify({
36
+ "proofs/anchor.json": proofJson(anchor.proof),
37
+ "proofs/user.json": proofJson(user.proof),
38
+ });
39
+ const result = identifyAnchors(ingest);
40
+ assert.equal(result.anchors.length, 1);
41
+ const record = result.anchors[0];
42
+ assert.equal(record.proofHash, anchor.proofHash);
43
+ assert.equal(record.epochId, "EPOCH-A");
44
+ assert.equal(record.chainId, "bitgraph:main");
45
+ assert.equal(record.counter, "4");
46
+ assert.equal(record.slotCounter, "3");
47
+ assert.equal(record.blockHash, BLOCK_HASH);
48
+ assert.equal(record.blockNumber, "24800448");
49
+ assert.equal(record.metadataCorroboration, "agrees");
50
+ // The unsigned metadata carries a blockTime; no time field of any kind
51
+ // may appear on the record.
52
+ assert.ok(!("timestamp" in record));
53
+ assert.ok(!("blockTime" in record));
54
+ assert.equal(result.findings.length, 0);
55
+ });
56
+ it("copies the run verification status onto the record", async () => {
57
+ const good = await makeAnchorProof({ blockHash: BLOCK_HASH, blockNumber: "1", epochId: "E", counter: "2" });
58
+ const bad = await makeAnchorProof({ blockHash: BLOCK_HASH.replace("28", "29"), blockNumber: "2", epochId: "E", counter: "4" });
59
+ // Tamper the signature after signing: identification still works (it
60
+ // reads the signed body fields), and the failed status is copied.
61
+ bad.proof.signer.signatureB64 = `AA${bad.proof.signer.signatureB64.slice(2)}`;
62
+ const ingest = await ingestAndVerify({
63
+ "proofs/good.json": proofJson(good.proof),
64
+ "proofs/bad.json": proofJson(bad.proof),
65
+ });
66
+ const result = identifyAnchors(ingest);
67
+ assert.equal(result.anchors.length, 2);
68
+ const goodRecord = result.anchors.find((a) => a.proofHash === good.proofHash);
69
+ assert.equal(goodRecord.verificationTier, "integrity");
70
+ assert.equal(goodRecord.verificationStatus, "artifact-unavailable");
71
+ const badRecord = result.anchors.find((a) => a.proofHash !== good.proofHash);
72
+ assert.equal(badRecord.verificationStatus, "failed");
73
+ assert.ok(badRecord.verificationReason !== undefined);
74
+ });
75
+ it("never identifies an anchor from unsigned metadata alone", async () => {
76
+ const user = await makeChainIdProof({ counter: "2", epochId: "E-META" });
77
+ user.proof["metadata"] = { type: "ethereum-anchor" };
78
+ const ingest = await ingestAndVerify({ "proofs/claimant.json": proofJson(user.proof) });
79
+ const result = identifyAnchors(ingest);
80
+ assert.equal(result.anchors.length, 0);
81
+ assert.equal(result.metadataOnlyProofHashes.length, 1);
82
+ const finding = result.findings.find((f) => f.code === "anchor-metadata-only-claim");
83
+ assert.ok(finding !== undefined);
84
+ assert.match(finding.message, /not treated as an anchor/);
85
+ });
86
+ it("records disagreement between the signed attribution and unsigned metadata", async () => {
87
+ const anchor = await makeAnchorProof({
88
+ blockHash: BLOCK_HASH,
89
+ blockNumber: "7",
90
+ epochId: "E-DIS",
91
+ counter: "2",
92
+ metadata: { type: "something-else" },
93
+ });
94
+ const ingest = await ingestAndVerify({ "proofs/anchor.json": proofJson(anchor.proof) });
95
+ const result = identifyAnchors(ingest);
96
+ assert.equal(result.anchors.length, 1, "the signed field governs: still an anchor");
97
+ assert.equal(result.anchors[0].metadataCorroboration, "disagrees");
98
+ assert.ok(result.findings.some((f) => f.code === "anchor-metadata-disagreement"));
99
+ });
100
+ it("treats absent metadata as absent corroboration, not disagreement", async () => {
101
+ const anchor = await makeAnchorProof({ blockHash: BLOCK_HASH, blockNumber: "9", epochId: "E-ABS", counter: "2" });
102
+ const ingest = await ingestAndVerify({ "proofs/anchor.json": proofJson(anchor.proof) });
103
+ const result = identifyAnchors(ingest);
104
+ assert.equal(result.anchors[0].metadataCorroboration, "absent");
105
+ assert.equal(result.findings.filter((f) => f.code === "anchor-metadata-disagreement").length, 0);
106
+ });
107
+ });
108
+ describe("audit anchors: block number from the signed title URL", () => {
109
+ it("parses the number only from a strict Etherscan block URL", async () => {
110
+ const good = await makeAnchorProof({ blockHash: BLOCK_HASH, blockNumber: "24800448", epochId: "E-URL", counter: "2" });
111
+ const foreign = await makeAnchorProof({
112
+ blockHash: BLOCK_HASH.replace("28", "30"),
113
+ title: "https://example.com/block/99",
114
+ epochId: "E-URL",
115
+ counter: "4",
116
+ });
117
+ const missing = await makeAnchorProof({
118
+ blockHash: BLOCK_HASH.replace("28", "31"),
119
+ noTitle: true,
120
+ epochId: "E-URL",
121
+ counter: "6",
122
+ });
123
+ const ingest = await ingestAndVerify({
124
+ "proofs/good.json": proofJson(good.proof),
125
+ "proofs/foreign.json": proofJson(foreign.proof),
126
+ "proofs/missing.json": proofJson(missing.proof),
127
+ });
128
+ const result = identifyAnchors(ingest);
129
+ const byHash = new Map(result.anchors.map((a) => [a.proofHash, a]));
130
+ assert.equal(byHash.get(good.proofHash).blockNumber, "24800448");
131
+ assert.equal(byHash.get(foreign.proofHash).blockNumber, undefined);
132
+ assert.equal(byHash.get(missing.proofHash).blockNumber, undefined);
133
+ assert.equal(result.findings.filter((f) => f.code === "anchor-title-unparseable").length, 2);
134
+ });
135
+ });
136
+ describe("audit anchors: non-anchor proofs are untouched", () => {
137
+ it("produces no records or findings for ordinary proofs and mutates nothing", async () => {
138
+ const a = await makeChainIdProof({ counter: "2", epochId: "E-PLAIN" });
139
+ const b = await makeChainIdProof({ counter: "4", epochId: "E-PLAIN" });
140
+ const ingest = await ingestAndVerify({
141
+ "proofs/a.json": proofJson(a.proof),
142
+ "proofs/b.json": proofJson(b.proof),
143
+ });
144
+ const statusesBefore = ingest.proofs.map((p) => p.verification?.status);
145
+ const result = identifyAnchors(ingest);
146
+ assert.equal(result.anchors.length, 0);
147
+ assert.equal(result.metadataOnlyProofHashes.length, 0);
148
+ assert.equal(result.findings.length, 0);
149
+ assert.deepEqual(ingest.proofs.map((p) => p.verification?.status), statusesBefore, "identification is read-only");
150
+ });
151
+ });
152
+ //# sourceMappingURL=audit-anchors.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit-anchors.test.js","sourceRoot":"","sources":["../../src/__tests__/audit-anchors.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=audit-anomalies.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit-anomalies.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/audit-anomalies.test.ts"],"names":[],"mappings":""}