@mikeargento/bitgraph-audit 0.9.0 → 0.10.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 (49) hide show
  1. package/README.md +5 -3
  2. package/dist/audit.d.ts +4 -3
  3. package/dist/audit.d.ts.map +1 -1
  4. package/dist/audit.js +9 -3
  5. package/dist/audit.js.map +1 -1
  6. package/dist/ceilings.d.ts.map +1 -1
  7. package/dist/ceilings.js +1 -0
  8. package/dist/ceilings.js.map +1 -1
  9. package/dist/cli.js +72 -19
  10. package/dist/cli.js.map +1 -1
  11. package/dist/exports.d.ts.map +1 -1
  12. package/dist/exports.js +6 -3
  13. package/dist/exports.js.map +1 -1
  14. package/dist/floors.d.ts +23 -0
  15. package/dist/floors.d.ts.map +1 -0
  16. package/dist/floors.js +203 -0
  17. package/dist/floors.js.map +1 -0
  18. package/dist/index.d.ts +4 -1
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +3 -0
  21. package/dist/index.js.map +1 -1
  22. package/dist/ingest.d.ts +2 -0
  23. package/dist/ingest.d.ts.map +1 -1
  24. package/dist/ingest.js +14 -0
  25. package/dist/ingest.js.map +1 -1
  26. package/dist/report-json.d.ts.map +1 -1
  27. package/dist/report-json.js +15 -0
  28. package/dist/report-json.js.map +1 -1
  29. package/dist/report-md.js +95 -27
  30. package/dist/report-md.js.map +1 -1
  31. package/dist/temporal.d.ts +12 -0
  32. package/dist/temporal.d.ts.map +1 -1
  33. package/dist/temporal.js +245 -41
  34. package/dist/temporal.js.map +1 -1
  35. package/dist/types.d.ts +136 -5
  36. package/dist/types.d.ts.map +1 -1
  37. package/package.json +3 -2
  38. package/src/__tests__/base-floor.test.ts +405 -0
  39. package/src/audit.ts +9 -3
  40. package/src/ceilings.ts +1 -0
  41. package/src/cli.ts +80 -20
  42. package/src/exports.ts +7 -3
  43. package/src/floors.ts +242 -0
  44. package/src/index.ts +8 -0
  45. package/src/ingest.ts +15 -0
  46. package/src/report-json.ts +15 -0
  47. package/src/report-md.ts +109 -31
  48. package/src/temporal.ts +279 -48
  49. package/src/types.ts +140 -6
package/src/types.ts CHANGED
@@ -342,6 +342,19 @@ export interface AnchorWitnessFile {
342
342
  witness: Record<string, unknown>;
343
343
  }
344
344
 
345
+ /**
346
+ * A floor header file (bitgraph-floor-header/1):
347
+ * { version, chain: "base", evmChainId: 8453, blockNumber, blockHash, blockTimestamp, header }
348
+ * where header is the block's RLP as 0x hex. Only the header bytes are
349
+ * evidence: they are checked by keccak-256 against the floor a proof signs,
350
+ * and the other fields are a convenience for readers.
351
+ */
352
+ export interface FloorHeaderFile {
353
+ path: string;
354
+ fileSha256Hex: string;
355
+ json: Record<string, unknown>;
356
+ }
357
+
345
358
  // ---------------------------------------------------------------------------
346
359
  // Manifest
347
360
  // ---------------------------------------------------------------------------
@@ -413,6 +426,8 @@ export interface IngestCounts {
413
426
  artifacts: number;
414
427
  /** Anchor witness files. */
415
428
  witnesses: number;
429
+ /** Floor header files (bitgraph-floor-header/1). Absent when there are none. */
430
+ floorHeaders?: number;
416
431
  /** Ceiling files (bitgraph-ceiling/1) and ceiling status notes (bitgraph-ceiling-status/1). */
417
432
  ceilings?: number;
418
433
  /** Export-shaped files (format "bitgraph-export/..."), checked or rejected. */
@@ -486,6 +501,12 @@ export interface IngestResult {
486
501
  artifacts: ArtifactRecord[];
487
502
  /** Anchor witness files in observation order. */
488
503
  witnesses: AnchorWitnessFile[];
504
+ /**
505
+ * Floor header files (bitgraph-floor-header/1): the header of a Base block
506
+ * a proof signs as its floor, the way the carrier/3 unpacker writes it.
507
+ * Evidence, never artifacts. Optional so older embedders' IngestResults still type.
508
+ */
509
+ floorHeaders?: FloorHeaderFile[];
489
510
  /** Ceiling files (bitgraph-ceiling/1) in observation order. Optional so older embedders' IngestResults still type. */
490
511
  ceilings?: CeilingFile[];
491
512
  /** Ceiling status notes (bitgraph-ceiling-status/1): a package saying why a ceiling is absent. */
@@ -668,9 +689,13 @@ export interface EpochAnchorBound {
668
689
  * anchor evidence. "not-before": they came after it. Always one-sided.
669
690
  */
670
691
  kind: "not-after" | "not-before";
671
- /** Canonical hash of the anchor proof providing the bound. */
692
+ /** Canonical hash of the anchor proof providing the bound (for a Base floor, the proof that signs it). */
672
693
  anchorProofHash: string;
673
- /** Ethereum block number parsed from the signed anchor title URL (decimal string). */
694
+ /** Absent for an anchor bound; "signed-floor" when the representative bound is a Base floor a proof signs. */
695
+ source?: "signed-floor";
696
+ /** Absent for Ethereum; "base" when the representative bound is a Base block. */
697
+ chain?: "base";
698
+ /** Block number (decimal string): the anchored Ethereum block, or the Base floor block. */
674
699
  blockNumber?: string;
675
700
  /** Ethereum block hash from the signed attribution message. */
676
701
  blockHash?: string;
@@ -1072,8 +1097,17 @@ export interface AnchorWitnessAnalysis {
1072
1097
  * "counter-order" only the commit counters order them. This relies on
1073
1098
  * the authority's per-chain counter discipline rather
1074
1099
  * than verifiable hash links, and is marked weaker.
1100
+ * "signed-floor" the bounded proof itself signs the floor block
1101
+ * (commit.slotFloor, a Base block, enclave v10). Nothing
1102
+ * stands between the proof and the block: it is the
1103
+ * proof's own signed field. Not weaker.
1104
+ *
1105
+ * A Base floor bound reaches other proofs only the way an anchor bound
1106
+ * does: through a verified hash-link path ("chain-link") or by counter
1107
+ * order ("counter-order"), and only as a NOT-BEFORE. A floor never yields a
1108
+ * not-after: a later proof's floor block can predate this proof.
1075
1109
  */
1076
- export type BoundEvidence = "chain-link" | "counter-order";
1110
+ export type BoundEvidence = "chain-link" | "counter-order" | "signed-floor";
1077
1111
 
1078
1112
  /**
1079
1113
  * One one-sided temporal bound on a segment, derived from a verified
@@ -1103,7 +1137,27 @@ export type BoundEvidence = "chain-link" | "counter-order";
1103
1137
  */
1104
1138
  export interface SegmentBound {
1105
1139
  kind: "not-before" | "not-after";
1140
+ /**
1141
+ * The proof that supplies the bound: the anchor proof, or for a Base floor
1142
+ * (source "signed-floor") the proof that signs the floor block.
1143
+ */
1106
1144
  anchorProofHash: string;
1145
+ /**
1146
+ * Absent for an anchor bound (an Ethereum anchor proof with a verified
1147
+ * witness, every bound before enclave v10). "signed-floor": the Base block a
1148
+ * proof signs as commit.slotFloor (enclave v10). Always a not-before.
1149
+ */
1150
+ source?: "signed-floor";
1151
+ /** Absent for Ethereum (every anchor bound); "base" for a Base floor. */
1152
+ chain?: "base";
1153
+ /**
1154
+ * Base floors only: where the block time comes from. "header": a header in
1155
+ * the bundle hashes to the signed block and carries the signed number and
1156
+ * time. "signed": no header for the block is in the bundle; the time is the
1157
+ * one the proof signs (on Base mainnet's schedule for its number), and
1158
+ * confirming the block needs a Base lookup.
1159
+ */
1160
+ timeSource?: "header" | "signed";
1107
1161
  /** Block number confirmed by the verified witness header (decimal string). */
1108
1162
  blockNumber?: string;
1109
1163
  /** Locally recomputed block hash (0x + 64 lowercase hex). */
@@ -1197,6 +1251,52 @@ export interface AnchorOrderedPair {
1197
1251
  note: string;
1198
1252
  }
1199
1253
 
1254
+ /**
1255
+ * A Base floor one proof signs (commit.slotFloor, enclave v10), as the
1256
+ * temporal pass read it. Listed only for Base floors: an Ethereum floor
1257
+ * (commit.slotAnchor) is read through the anchor proofs, as before.
1258
+ */
1259
+ export interface SignedFloorRecord {
1260
+ proofHash: string;
1261
+ chain: "base";
1262
+ blockNumber: number;
1263
+ /** 0x-prefixed lowercase hex, as signed. */
1264
+ blockHash: string;
1265
+ /** Unix seconds, as signed. */
1266
+ blockTimestamp: number;
1267
+ /** "checked": a header in the bundle hashes to the signed block (headerPath names it). "not-carried": none is here. */
1268
+ header: "checked" | "not-carried";
1269
+ /** Bundle path of the header that was checked (a floor header file, a ceiling file or an export). */
1270
+ headerPath?: string;
1271
+ /** "not-before": the floor bounds the proof. "withheld": it does not, for withheldReason. */
1272
+ bound: "not-before" | "withheld";
1273
+ withheldReason?: string;
1274
+ }
1275
+
1276
+ /** Problem codes of the floor stage. Every one sets exit bit 2. */
1277
+ export type FloorProblemCode =
1278
+ /** The proof signs two floors (commit.slotAnchor and commit.slotFloor): ambiguous, bounds nothing. */
1279
+ | "floor-ambiguous"
1280
+ /** commit.slotFloor does not name Base mainnet, or lacks a 32-byte hash, a number or a time. */
1281
+ | "floor-malformed"
1282
+ /** The signed Base floor time is not Base mainnet's schedule for the signed block number. */
1283
+ | "floor-off-schedule"
1284
+ /** A floor header file names a block a proof signs, and does not match it (hash, number, time or chain). */
1285
+ | "floor-header-mismatch"
1286
+ /** A floor header file is unreadable or not a Base header. */
1287
+ | "floor-header-malformed"
1288
+ /** A floor header file hashes to a block no proof in the bundle signs as its floor. */
1289
+ | "floor-header-unmatched";
1290
+
1291
+ export interface FloorProblem {
1292
+ code: FloorProblemCode;
1293
+ /** The proof concerned, when there is one. */
1294
+ proofHash?: string;
1295
+ /** The bundle path concerned (a proof file or a floor header file). */
1296
+ path?: string;
1297
+ message: string;
1298
+ }
1299
+
1200
1300
  /** Output of the temporal bounds pass. */
1201
1301
  export interface TemporalAnalysis {
1202
1302
  /** Per-partition segments with their bounds, deterministically ordered. */
@@ -1207,6 +1307,10 @@ export interface TemporalAnalysis {
1207
1307
  verifiedAnchorProofHashes: string[];
1208
1308
  /** Identified anchors with no verified witness: they still establish causal order, but confer no wall-clock evidence. Sorted. */
1209
1309
  unverifiedAnchorProofHashes: string[];
1310
+ /** Base floors the proofs sign (enclave v10), in observation order. Absent when no proof signs one. */
1311
+ signedFloors?: SignedFloorRecord[];
1312
+ /** Floor problems (exit bit 2). Absent when there are none. */
1313
+ floorProblems?: FloorProblem[];
1210
1314
  }
1211
1315
 
1212
1316
  // ---------------------------------------------------------------------------
@@ -1378,6 +1482,8 @@ export interface CeilingCheck {
1378
1482
  /** One line for people, e.g. "Ceiling: included in Base block N at hh:mm:ss UTC. ..."; it never claims settlement the file does not prove. */
1379
1483
  label?: string;
1380
1484
  window?: {
1485
+ /** "base" when the floor block (the one the proof signs) is a Base block; absent for Ethereum or no floor. */
1486
+ floorChain?: "base";
1381
1487
  floorBlock: number | null;
1382
1488
  floorTime: number | null;
1383
1489
  ceilingChainId: number;
@@ -1471,8 +1577,14 @@ export interface ExportClaimRecord {
1471
1577
 
1472
1578
  /** The three time claims as verifyExport establishes them. Never merged; a null field was not established. */
1473
1579
  export interface ExportTimes {
1474
- /** The committed bytes were finished after this Ethereum block (the proof's signed floor block, its header checked by hash). */
1475
- floor: { blockNumber: number; blockHash: string; blockTimestamp: number } | null;
1580
+ /**
1581
+ * The committed bytes were finished after this block (the proof's signed
1582
+ * floor block, its header checked by hash), on its chain: chain absent is
1583
+ * Ethereum (an anchor floor, commit.slotAnchor), "base" a Base floor
1584
+ * (commit.slotFloor, enclave v10). Absent rather than "ethereum" so reports
1585
+ * on older exports stay byte-identical.
1586
+ */
1587
+ floor: { chain?: "base"; blockNumber: number; blockHash: string; blockTimestamp: number } | null;
1476
1588
  /** The record existed by this Base block, at its time. Provisional until the block is checked against Base (offline, always provisional). */
1477
1589
  ceilingBase: { blockNumber: number; blockHash: string; blockTimestamp: number; provisional: boolean } | null;
1478
1590
  /** The record existed by this Ethereum block (through Base's output root; needs no trust in Base). */
@@ -1626,7 +1738,9 @@ export interface AuditResult {
1626
1738
  * witness failed its offline verification (a witness-* code: RLP or
1627
1739
  * header malformation, block-hash mismatch, digest-binding mismatch,
1628
1740
  * block-number mismatch, an invalid candidate anchor, or an unmatched
1629
- * witness). Benign findings are reported but never set exit bits: ingest
1741
+ * witness), or any floor problem (a floor-* code: a proof signing two
1742
+ * floors, a malformed or off-schedule Base floor, a floor header that
1743
+ * contradicts the signed floor or matches none). Benign findings are reported but never set exit bits: ingest
1630
1744
  * advisories (duplicate copies, manifest advisories, unsafe paths,
1631
1745
  * embedded proofHash mismatches) and informational anchor findings
1632
1746
  * (anchor-metadata-disagreement, anchor-metadata-only-claim,
@@ -1801,6 +1915,22 @@ export interface ReportSummary {
1801
1915
  segmentsLowerBounded: number;
1802
1916
  segmentsUpperBounded: number;
1803
1917
  segmentsUnanchored: number;
1918
+ /**
1919
+ * Base floors (enclave v10), as counts. Present only when a proof signs a
1920
+ * Base floor or a floor problem was found, so older reports are unchanged.
1921
+ */
1922
+ baseFloors?: {
1923
+ /** Proofs that sign a Base floor (commit.slotFloor). */
1924
+ signed: number;
1925
+ /** Of those, floors that bound their proof not-before. */
1926
+ bounding: number;
1927
+ /** Of those, floors whose header the bundle carries, checked against the signed block. */
1928
+ headersChecked: number;
1929
+ /** Floors not used as a bound (see SignedFloorRecord.withheldReason). */
1930
+ withheld: number;
1931
+ /** Floor problems (exit bit 2). */
1932
+ problems: number;
1933
+ };
1804
1934
  };
1805
1935
  /** Exports (bitgraph-export/1), as counts. Present only when the bundle carries export-shaped files. */
1806
1936
  exports?: {
@@ -1878,6 +2008,10 @@ export interface AuditJsonReport {
1878
2008
  segments: TemporalSegment[];
1879
2009
  verifiedAnchorProofHashes: string[];
1880
2010
  unverifiedAnchorProofHashes: string[];
2011
+ /** Base floors the proofs sign (enclave v10). Absent when there are none. */
2012
+ signedFloors?: SignedFloorRecord[];
2013
+ /** Floor problems (exit bit 2). Absent when there are none. */
2014
+ floorProblems?: FloorProblem[];
1881
2015
  };
1882
2016
  summary: ReportSummary;
1883
2017
  }