@engramx/client 0.16.0-rc.13 → 0.16.0-rc.14

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.
@@ -0,0 +1,352 @@
1
+ // Evidence bundles: what a writer captures right after a write, and the check anyone runs on it.
2
+ //
3
+ // ⟨ADDED 2026-10-15, the owner's ruling 6B of 2026-10-14⟩ The claim a bundle proves is narrow and
4
+ // exact: "this entry — and, when the bundle carries one, this write's bytes — was in the record by
5
+ // the time the subnet signed this certificate." The check is a chain of links, and each must hold:
6
+ //
7
+ // 1. content → memory event the bytes, with the receipt's previous head, time, size and content
8
+ // root, rebuild the memory-file event whose hash is the receipt's head;
9
+ // 2. memory event → entry the record entry names that event (`seq=…` and `head=…`);
10
+ // 3. entry → entry hash the entry's body, hashed first and chained onto the record head
11
+ // before it (the receipt's `recordPrev`);
12
+ // 4. certificate it verifies against the pinned IC mainnet root key for this canister,
13
+ // at any age, and its signed `/time` is read;
14
+ // 5. certified head the certificate's certified data is the bundle's head;
15
+ // 6. walk from the entry, through hash-only rows (from the bundle, or fetched
16
+ // from the canister by anyone), to the certified head;
17
+ // 7. total the number of entries that head covers, proven by the walk, is the
18
+ // number the bundle claims.
19
+ //
20
+ // What it does NOT prove: that nothing was written elsewhere (another path, engram or key), or any
21
+ // time EARLIER than the certificate's — an entry's certified time is the signed time of the earliest
22
+ // certificate one keeps that covers it. A controller can rewrite a record and certify a new,
23
+ // self-consistent head; only someone who kept an OLDER certificate catches that, which is why the
24
+ // bundle keeps the certificate's bytes, not a flag saying one was checked.
25
+ //
26
+ // NODE-ONLY: the memory-file half (ledgerfsHash.ts) hashes with node:crypto. The browser-safe parts
27
+ // (the chain walk, the historical certificate check) are in recordChain.ts and certifiedAudit.ts.
28
+ import { Principal } from '@icp-sdk/core/principal';
29
+ import { contentRoot as ledgerContentRoot, chunkHash, deltaHash, eventHash, } from './ledgerfsHash.js';
30
+ import { recordEntryHash, sameBytes, toHexString, walkToCertifiedHead, } from './recordChain.js';
31
+ import { verifyHistoricalCertificate } from './certifiedAudit.js';
32
+ export const EVIDENCE_FORMAT = 'engramx-evidence/1';
33
+ /** ledgerfs's fixed chunk size (src/ledgerfs/Types.mo · CHUNK_SIZE) — part of every content root. */
34
+ const CHUNK_SIZE = 262144;
35
+ // ── parsing (every field checked, so a malformed bundle is named, never half-checked) ────────────
36
+ const hex = (what, h, len) => {
37
+ if (typeof h !== 'string' || !/^([0-9a-f]{2})*$/.test(h)) {
38
+ throw new Error(`${what} is not lowercase hex`);
39
+ }
40
+ const out = Uint8Array.from(h.match(/../g) ?? [], (b) => parseInt(b, 16));
41
+ if (len !== undefined && out.length !== len)
42
+ throw new Error(`${what} is ${out.length} bytes, not ${len}`);
43
+ return out;
44
+ };
45
+ const nat = (what, n) => {
46
+ if (typeof n !== 'string' || !/^\d+$/.test(n))
47
+ throw new Error(`${what} is not a decimal string`);
48
+ return BigInt(n);
49
+ };
50
+ const int = (what, n) => {
51
+ if (typeof n !== 'string' || !/^-?\d+$/.test(n))
52
+ throw new Error(`${what} is not a decimal string`);
53
+ return BigInt(n);
54
+ };
55
+ const b64 = (what, s) => {
56
+ if (typeof s !== 'string')
57
+ throw new Error(`${what} is not base64 text`);
58
+ return new Uint8Array(Buffer.from(s, 'base64'));
59
+ };
60
+ /** Which ledgerfs op a record entry's operation wrote — the two a writer can rebuild from its bytes. */
61
+ function opKind(operation) {
62
+ if (operation === 'memory.append' ||
63
+ operation === 'mcp.append' ||
64
+ operation === 'memory.append.session') {
65
+ return 'append';
66
+ }
67
+ if (operation === 'memory.write' || operation === 'memory.revise')
68
+ return 'set';
69
+ return null;
70
+ }
71
+ /** The memory-file event a write committed, rebuilt from its bytes and its receipt. */
72
+ function rebuildEvent(kind, w, bytes) {
73
+ const r = w.receipt;
74
+ const seq = nat('write.receipt.seq', r.seq);
75
+ const size = nat('write.receipt.size', r.size);
76
+ const receiptRoot = hex('write.receipt.contentRoot', r.contentRoot, 32);
77
+ let op;
78
+ let contentRootChecked = false;
79
+ if (kind === 'append') {
80
+ op = { kind: 'append', deltaHash: deltaHash(bytes), deltaSize: bytes.length, newSize: size };
81
+ }
82
+ else {
83
+ // A set seals its whole content from an empty tail: full 256 KiB chunks, then the remainder,
84
+ // every ref born at this event's seq (Store.prepareSet · seal).
85
+ const full = [];
86
+ let i = 0;
87
+ for (; i + CHUNK_SIZE <= bytes.length; i += CHUNK_SIZE)
88
+ full.push(bytes.subarray(i, i + CHUNK_SIZE));
89
+ const tail = bytes.subarray(i);
90
+ const fullHashes = full.map((c) => chunkHash(c));
91
+ const tailHash = tail.length > 0 ? chunkHash(tail) : null;
92
+ const root = ledgerContentRoot(fullHashes, tailHash);
93
+ const chunks = fullHashes.map((h) => ({ hash: h, size: CHUNK_SIZE, birthSeq: seq }));
94
+ if (tailHash)
95
+ chunks.push({ hash: tailHash, size: tail.length, birthSeq: seq });
96
+ op = { kind: 'set', manifest: { chunks, totalSize: BigInt(bytes.length), contentRoot: root } };
97
+ contentRootChecked = sameBytes(root, receiptRoot);
98
+ }
99
+ return {
100
+ event: {
101
+ seq,
102
+ path: w.path,
103
+ version: nat('write.receipt.version', r.version),
104
+ op,
105
+ byRaw: Principal.fromText(w.by).toUint8Array(),
106
+ at: int('write.receipt.atNs', r.atNs),
107
+ size,
108
+ contentRoot: receiptRoot,
109
+ prev: hex('write.receipt.prev', r.prev, 32),
110
+ },
111
+ contentRootChecked,
112
+ };
113
+ }
114
+ /** Run every link. Never throws for a broken bundle: a malformed field is a broken link, named. */
115
+ export async function checkEvidence(bundle, opts = {}) {
116
+ const links = [];
117
+ const done = (extra = {}) => {
118
+ const broken = links.find((l) => !l.ok);
119
+ return {
120
+ ok: !broken,
121
+ links,
122
+ why: broken ? `${broken.link}: ${broken.detail}` : 'ok',
123
+ ...extra,
124
+ };
125
+ };
126
+ const fail = (link, detail, extra = {}) => {
127
+ links.push({ link, ok: false, detail });
128
+ return done(extra);
129
+ };
130
+ try {
131
+ if (bundle?.format !== EVIDENCE_FORMAT) {
132
+ return fail('bundle', `format is ${JSON.stringify(bundle?.format)}, not "${EVIDENCE_FORMAT}"`);
133
+ }
134
+ Principal.fromText(bundle.canisterId);
135
+ }
136
+ catch (e) {
137
+ return fail('bundle', e.message);
138
+ }
139
+ let entry;
140
+ let entryId;
141
+ let recordPrev;
142
+ let hashFirstFrom;
143
+ try {
144
+ const e = bundle.entry;
145
+ entryId = nat('entry.id', e.id);
146
+ entry = {
147
+ id: entryId,
148
+ timestampNs: int('entry.timestampNs', e.timestampNs),
149
+ caller: Principal.fromText(e.caller).toText(),
150
+ callerRole: String(e.callerRole),
151
+ operation: String(e.operation),
152
+ details: String(e.details),
153
+ success: e.success === true,
154
+ };
155
+ recordPrev = hex('recordPrev', bundle.recordPrev);
156
+ if (recordPrev.length !== 0 && recordPrev.length !== 32)
157
+ throw new Error('recordPrev is neither empty (genesis) nor 32 bytes');
158
+ hashFirstFrom = nat('hashFirstFrom', bundle.hashFirstFrom);
159
+ }
160
+ catch (e) {
161
+ return fail('bundle', e.message);
162
+ }
163
+ // 1–2. content → memory event → record entry
164
+ if (bundle.write) {
165
+ const kind = opKind(entry.operation);
166
+ if (!kind) {
167
+ return fail('content → memory event', `the entry's operation "${entry.operation}" is not a write this check can rebuild from its bytes (an append or a set)`);
168
+ }
169
+ let built;
170
+ let receiptHead;
171
+ try {
172
+ built = rebuildEvent(kind, bundle.write, b64('write.bytes', bundle.write.bytes));
173
+ receiptHead = hex('write.receipt.head', bundle.write.receipt.head, 32);
174
+ }
175
+ catch (e) {
176
+ return fail('content → memory event', `the write is malformed: ${e.message}`);
177
+ }
178
+ if (kind === 'set' && !built.contentRootChecked) {
179
+ return fail('content → memory event', "the bytes do not hash to the receipt's content root: they are not the content this write set");
180
+ }
181
+ const h = eventHash(built.event);
182
+ if (!sameBytes(h, receiptHead)) {
183
+ return fail('content → memory event', `the event rebuilt from the bytes and the receipt hashes to ${toHexString(h)}, not to the receipt's head ` +
184
+ `${toHexString(receiptHead)}: the bytes are not the ones written, or the receipt's previous head, time, size ` +
185
+ `or content root is wrong`);
186
+ }
187
+ links.push({
188
+ link: 'content → memory event',
189
+ ok: true,
190
+ detail: `${kind === 'append' ? 'the appended bytes' : 'the content'} rebuild event ${bundle.write.receipt.seq}, head ${toHexString(receiptHead)}`,
191
+ });
192
+ // The engram writes a memory entry's details as `v=<version>[ src=…] seq=<seq> head=<head>[ conn=…]
193
+ // path=<path>[ key=…]`, capped at 512 characters with the path LAST so a cap cuts the path, never
194
+ // the proof (main.mo · receiptSuffix). All three tokens must name THIS write.
195
+ const d = entry.details;
196
+ const seqTok = ` seq=${bundle.write.receipt.seq} head=${toHexString(receiptHead)}`;
197
+ const versionTok = `v=${bundle.write.receipt.version} `;
198
+ const pathTok = ` path=${bundle.write.path}`;
199
+ const pathCut = Array.from(d).length === 512 && pathTok.startsWith(d.slice(d.lastIndexOf(' path=')));
200
+ if (!d.startsWith(versionTok) ||
201
+ !d.includes(`${seqTok} `) ||
202
+ !(d.includes(pathTok) || pathCut)) {
203
+ return fail('memory event → record entry', `the entry does not name this write: its details are "${d.slice(0, 200)}", and they must begin ` +
204
+ `"${versionTok.trim()}", carry "${seqTok.trim()}" and name path "${bundle.write.path}"`);
205
+ }
206
+ links.push({
207
+ link: 'memory event → record entry',
208
+ ok: true,
209
+ detail: `entry ${entryId} records seq ${bundle.write.receipt.seq}`,
210
+ });
211
+ }
212
+ // 3. entry → its hash
213
+ const entryHash = await recordEntryHash(entry, recordPrev, hashFirstFrom);
214
+ if (bundle.entry.entryHash !== undefined) {
215
+ let served;
216
+ try {
217
+ served = hex('entry.entryHash', bundle.entry.entryHash, 32);
218
+ }
219
+ catch (e) {
220
+ return fail('record entry → entry hash', e.message);
221
+ }
222
+ if (!sameBytes(served, entryHash)) {
223
+ return fail('record entry → entry hash', `the entry, chained onto the previous record head ${toHexString(recordPrev) || '(genesis)'}, hashes to ` +
224
+ `${toHexString(entryHash)}, not to its entry hash ${toHexString(served)}: the entry's text, or the receipt's previous record head, is wrong`);
225
+ }
226
+ }
227
+ links.push({
228
+ link: 'record entry → entry hash',
229
+ ok: true,
230
+ detail: `entry ${entryId} hashes to ${toHexString(entryHash)} (${entryId >= hashFirstFrom ? 'hashed first, then chained' : 'the older rule'})`,
231
+ });
232
+ // 4–5. certificate and certified head
233
+ let certified;
234
+ let claimedHead;
235
+ try {
236
+ claimedHead = hex('certified.headHash', bundle.certified.headHash, 32);
237
+ const witness = bundle.certified.witness
238
+ ? b64('certified.witness', bundle.certified.witness)
239
+ : null;
240
+ certified = await (opts.verifyCertificate ?? verifyHistoricalCertificate)({
241
+ certificate: b64('certified.certificate', bundle.certified.certificate),
242
+ canisterId: bundle.canisterId,
243
+ rootKey: opts.rootKey,
244
+ witness,
245
+ leafPath: witness ? [new TextEncoder().encode('audit_head')] : undefined,
246
+ });
247
+ }
248
+ catch (e) {
249
+ return fail('certificate', e.message);
250
+ }
251
+ if (!certified.verified || certified.signedTimeNs === null) {
252
+ return fail('certificate', certified.why);
253
+ }
254
+ const signedTimeNs = certified.signedTimeNs;
255
+ links.push({
256
+ link: 'certificate',
257
+ ok: true,
258
+ detail: `signed by the subnet at ${new Date(Number(signedTimeNs / 1000000n)).toISOString()} for ${bundle.canisterId}`,
259
+ });
260
+ const certifiedHead = certified.leaf ?? certified.certifiedData;
261
+ if (!sameBytes(certifiedHead, claimedHead)) {
262
+ return fail('certified head', `the certificate certifies ${toHexString(certifiedHead)}, not the bundle's head ${toHexString(claimedHead)}`, { signedTimeNs });
263
+ }
264
+ links.push({
265
+ link: 'certified head',
266
+ ok: true,
267
+ detail: `the subnet signed head ${toHexString(certifiedHead)}`,
268
+ });
269
+ // The certificate predates the entry when it certifies the head the entry was chained onto.
270
+ if (sameBytes(certifiedHead, recordPrev)) {
271
+ return fail('walk', `the certificate precedes the entry: it certifies the record head from just before entry ${entryId}, so it was captured before the write and proves nothing about it`, { signedTimeNs });
272
+ }
273
+ // 6. walk
274
+ let rows;
275
+ try {
276
+ rows = (bundle.rows ?? []).map((r, i) => ({
277
+ id: nat(`rows[${i}].id`, r.id),
278
+ digest: hex(`rows[${i}].digest`, r.digest, 32),
279
+ entryHash: hex(`rows[${i}].entryHash`, r.entryHash, 32),
280
+ }));
281
+ }
282
+ catch (e) {
283
+ return fail('walk', `the bundle's rows are malformed: ${e.message}`, {
284
+ signedTimeNs,
285
+ });
286
+ }
287
+ let walk = await walkToCertifiedHead({
288
+ fromId: entryId,
289
+ fromHash: entryHash,
290
+ rows,
291
+ certifiedHead,
292
+ hashFirstFrom,
293
+ });
294
+ // Fetch only when the bundle carried no rows, or its rows simply ran out. A row that is missing,
295
+ // swapped or altered INSIDE the bundle is a broken bundle — never repaired by fetching.
296
+ const ranOut = !walk.ok && (rows.length === 0 || /was not reached/.test(walk.why));
297
+ if (!walk.ok && ranOut && opts.fetchRows) {
298
+ const last = rows.length ? rows[rows.length - 1].id : entryId;
299
+ let fetched;
300
+ try {
301
+ fetched = await opts.fetchRows(rows.length ? last + 1n : entryId + 1n);
302
+ }
303
+ catch (e) {
304
+ return fail('walk', `fetching hash-only rows failed: ${e.message}`, {
305
+ signedTimeNs,
306
+ });
307
+ }
308
+ if (fetched.hashFirstFrom !== hashFirstFrom) {
309
+ return fail('walk', `the canister says its record switched rule at ${fetched.hashFirstFrom}, the bundle says ${hashFirstFrom}`, { signedTimeNs });
310
+ }
311
+ walk = await walkToCertifiedHead({
312
+ fromId: entryId,
313
+ fromHash: entryHash,
314
+ rows: [...rows, ...fetched.rows.filter((r) => r.id > last)],
315
+ certifiedHead,
316
+ hashFirstFrom,
317
+ });
318
+ }
319
+ if (!walk.ok)
320
+ return fail('walk', walk.why, { signedTimeNs });
321
+ links.push({
322
+ link: 'walk',
323
+ ok: true,
324
+ detail: `${walk.distance} entr${walk.distance === 1n ? 'y' : 'ies'} from entry ${entryId} to the certified head (entry ${walk.headId})`,
325
+ });
326
+ // 7. total
327
+ const covered = walk.headId + 1n;
328
+ if (bundle.certified.total !== undefined) {
329
+ let claimed;
330
+ try {
331
+ claimed = nat('certified.total', bundle.certified.total);
332
+ }
333
+ catch (e) {
334
+ return fail('total', e.message, { signedTimeNs, distance: walk.distance });
335
+ }
336
+ if (claimed !== covered) {
337
+ return fail('total', `the bundle says the head covers ${claimed} entries; the walk proves it covers ${covered}`, { signedTimeNs, distance: walk.distance });
338
+ }
339
+ links.push({
340
+ link: 'total',
341
+ ok: true,
342
+ detail: `the certified head covers exactly ${covered} entries`,
343
+ });
344
+ }
345
+ return done({ signedTimeNs, distance: walk.distance, entriesCovered: covered });
346
+ }
347
+ /** Encode a bundle field from bytes. */
348
+ export const bundleHex = toHexString;
349
+ export const bundleB64 = (b) => Buffer.from(Uint8Array.from(b)).toString('base64');
350
+ /** For a page's full items: the hash-only row of each, so a page that mixes both can be walked. */
351
+ export { sealedRowOf, recordEntryBody } from './recordChain.js';
352
+ //# sourceMappingURL=evidence.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evidence.js","sourceRoot":"","sources":["../src/evidence.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -8,6 +8,13 @@ export { verifyCertifiedAuditHead } from './certifiedAudit.js';
8
8
  export { verifyCertifiedLeaf, verifyCertifiedRegistryHead, verifyCertifiedAnchor, } from './certifiedAudit.js';
9
9
  export type { CertifiedLeaf } from './certifiedAudit.js';
10
10
  export type { CertifiedAuditHead, VerifiedAuditHead } from './certifiedAudit.js';
11
+ export { verifyHistoricalCertificate, IC_MAINNET_ROOT_KEY_HEX } from './certifiedAudit.js';
12
+ export type { HistoricalCertificate } from './certifiedAudit.js';
13
+ export { recordEntryBody, recordDigest, recordLink, legacyRecordLink, recordEntryHash, sealedRowOf, walkToCertifiedHead, } from './recordChain.js';
14
+ export type { RecordEntryFields, SealedRow, WalkResult } from './recordChain.js';
15
+ export { checkEvidence, EVIDENCE_FORMAT } from './evidence.js';
16
+ export type { EvidenceBundle, EvidenceCheck, EvidenceLink, CheckOptions } from './evidence.js';
17
+ export { fetchSealedRows } from './publicRecord.js';
11
18
  export { verifyActionReceipt, actionMessage, actionFields, enrolmentMessage, signEnrolment, } from './actionReceipt.js';
12
19
  export type { ActionAuth, Enrolment } from './actionReceipt.js';
13
20
  export * as Schema from './schema.js';
package/dist/index.js CHANGED
@@ -9,6 +9,14 @@ export { verifyCertifiedAuditHead } from './certifiedAudit.js';
9
9
  // Tree-format verification (registry ≥ 0.7.17): the registry's certified_data is a merkle root and
10
10
  // its bare-head method was REMOVED (loud break). Engram/cashier slots keep verifyCertifiedAuditHead.
11
11
  export { verifyCertifiedLeaf, verifyCertifiedRegistryHead, verifyCertifiedAnchor, } from './certifiedAudit.js';
12
+ // ⟨2026-10-15, the owner's ruling 6B of 2026-10-14⟩ Checking one record entry without the owner: the
13
+ // historical-certificate check (any age, signed time read, pinned mainnet key), the record's hash
14
+ // contract and the walk to a certified head, and the evidence bundle a writer captures and anyone
15
+ // checks (`engramx verify`). recordChain and the certificate check are also on `./verify`.
16
+ export { verifyHistoricalCertificate, IC_MAINNET_ROOT_KEY_HEX } from './certifiedAudit.js';
17
+ export { recordEntryBody, recordDigest, recordLink, legacyRecordLink, recordEntryHash, sealedRowOf, walkToCertifiedHead, } from './recordChain.js';
18
+ export { checkEvidence, EVIDENCE_FORMAT } from './evidence.js';
19
+ export { fetchSealedRows } from './publicRecord.js';
12
20
  // Owner-action receipts (D1), VERIFY half only. An owner authorizes a money-path action by signing
13
21
  // a canonical, domain-separated message with their IC identity key; the engram persists it into the
14
22
  // tamper-evident audit log. Whoever later reads that log is a relying party, and this is what they
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import { type SealedRow } from './recordChain.js';
2
+ export declare function fetchSealedRows(host: string, canisterId: string, fromId: bigint, rootKey?: Uint8Array): Promise<{
3
+ rows: SealedRow[];
4
+ hashFirstFrom: bigint;
5
+ }>;
@@ -0,0 +1,52 @@
1
+ // Reading a record's hash-only rows as a stranger — the fetch half of `engramx verify`.
2
+ //
3
+ // ⟨ADDED 2026-10-15, the owner's ruling 6B of 2026-10-14⟩ An engram's record read
4
+ // (`listAuditEntries`) is public: a caller with no role, the anonymous one included, gets every entry
5
+ // as a hash-only row (id, digest, entry hash) and never a body. That is all a walk to a certified
6
+ // head needs. This reads those rows with NO identity, from `fromId` onward, a page at a time.
7
+ //
8
+ // It refuses rather than returning a short list: below the ring floor the rows are gone from the
9
+ // canister (the bundle captured at the time is the only copy), and the page says where the floor is.
10
+ import { Actor, HttpAgent } from '@icp-sdk/core/agent';
11
+ import { idlFactory } from './idl.js';
12
+ import { sealedRowOf } from './recordChain.js';
13
+ import { errorMessage } from './wire.js';
14
+ const PAGE = 500n;
15
+ const MAX_PAGES = 20;
16
+ export async function fetchSealedRows(host, canisterId, fromId, rootKey) {
17
+ // Anonymous: no identity is passed. The root key matters only for update calls and read_state;
18
+ // a query's reply is not what is being trusted here — every row is checked against the certified
19
+ // head by the walk, so a lying replica can only make the check FAIL, never pass.
20
+ const agent = await HttpAgent.create({ host, ...(rootKey ? { rootKey } : {}) });
21
+ const actor = Actor.createActor(idlFactory, { agent, canisterId });
22
+ const rows = [];
23
+ let hashFirstFrom = null;
24
+ let next = fromId;
25
+ for (let pages = 0; pages < MAX_PAGES; pages++) {
26
+ const r = await actor.listAuditEntries(next, PAGE);
27
+ if ('Err' in r)
28
+ throw new Error(`the record read refused: ${errorMessage(r.Err)}`);
29
+ const page = r.Ok;
30
+ hashFirstFrom ?? (hashFirstFrom = page.hashFirstFrom);
31
+ if (page.ringFloor > next) {
32
+ throw new Error(`the record no longer holds entry ${next} (its ring now starts at ${page.ringFloor}); ` +
33
+ 'those rows exist only in a bundle captured while they were retained');
34
+ }
35
+ const got = page.sealed.map((s) => ({
36
+ id: s.id,
37
+ digest: Uint8Array.from(s.digest),
38
+ entryHash: Uint8Array.from(s.entryHash),
39
+ }));
40
+ for (const e of page.items)
41
+ got.push(await sealedRowOf(e));
42
+ got.sort((a, b) => (a.id < b.id ? -1 : a.id > b.id ? 1 : 0));
43
+ rows.push(...got);
44
+ if (got.length === 0)
45
+ break;
46
+ next = got[got.length - 1].id + 1n;
47
+ if (next >= page.total)
48
+ break;
49
+ }
50
+ return { rows, hashFirstFrom: hashFirstFrom ?? 0n };
51
+ }
52
+ //# sourceMappingURL=publicRecord.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"publicRecord.js","sourceRoot":"","sources":["../src/publicRecord.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,69 @@
1
+ /** A record entry's hashed fields, as the record read decodes them or as a bundle carries them. */
2
+ export interface RecordEntryFields {
3
+ id: bigint | number | string;
4
+ timestampNs: bigint | number | string;
5
+ /** A Principal (anything with `toText()`) or its text. */
6
+ caller: string | {
7
+ toText(): string;
8
+ };
9
+ /** The role as Candid decodes it (`{ Agent: null }`) or its text (`"Agent"`). */
10
+ callerRole: string | Record<string, null>;
11
+ operation: string;
12
+ details: string;
13
+ success: boolean;
14
+ }
15
+ /** One hash-only row of the record: what a reader who may not see an entry in full is served. */
16
+ export interface SealedRow {
17
+ id: bigint;
18
+ digest: Uint8Array;
19
+ entryHash: Uint8Array;
20
+ }
21
+ /** The bytes an entry's hash covers — byte-for-byte `AuditLog.bodyOf`. */
22
+ export declare function recordEntryBody(e: RecordEntryFields): Uint8Array;
23
+ export declare function sha256(bytes: Uint8Array): Promise<Uint8Array>;
24
+ /** SHA-256 of an entry's body — the digest a hash-only row carries. */
25
+ export declare const recordDigest: (body: Uint8Array) => Promise<Uint8Array>;
26
+ /** The hash-first rule: SHA-256(prev ‖ digest). */
27
+ export declare const recordLink: (prev: Uint8Array, digest: Uint8Array) => Promise<Uint8Array>;
28
+ /** The rule before a chain's switch point: SHA-256(prev ‖ body). */
29
+ export declare const legacyRecordLink: (prev: Uint8Array, body: Uint8Array) => Promise<Uint8Array>;
30
+ /**
31
+ * One entry's hash from its fields and the head before it, under the rule its id falls on.
32
+ * `hashFirstFrom` is the chain's switch point as its record read serves it.
33
+ */
34
+ export declare function recordEntryHash(e: RecordEntryFields, prev: Uint8Array, hashFirstFrom: bigint): Promise<Uint8Array>;
35
+ /** A full entry turned into the row a stranger would be served — for walking a page that mixes the two. */
36
+ export declare function sealedRowOf(e: RecordEntryFields & {
37
+ entryHash: Uint8Array | number[];
38
+ }): Promise<SealedRow>;
39
+ export declare const sameBytes: (a: Uint8Array, b: Uint8Array) => boolean;
40
+ export declare const toHexString: (b: Uint8Array) => string;
41
+ export type WalkResult = {
42
+ ok: true;
43
+ /** Entries walked past the starting entry to reach the certified head (0: it IS the head). */
44
+ distance: bigint;
45
+ /** The id of the entry whose hash is the certified head. Entries ever written = this + 1. */
46
+ headId: bigint;
47
+ } | {
48
+ ok: false;
49
+ /** Which link broke, in words a person can act on. */
50
+ why: string;
51
+ /** The row id the walk stopped at, when there is one. */
52
+ at?: bigint;
53
+ };
54
+ /**
55
+ * Walk from one entry's hash, through hash-only rows, to a certified head.
56
+ *
57
+ * `rows` are taken in the order given and must continue the chain from `fromId + 1` with no gap and
58
+ * no reordering — the walk does NOT sort them, so a removed or a swapped row is named rather than
59
+ * silently repaired. Leading rows at or below `fromId` are skipped (a fetched page may start earlier).
60
+ * Each row's digest is chained onto the running head; when the row carries an entry hash it must
61
+ * agree. The walk succeeds the moment the running head equals `certifiedHead`.
62
+ */
63
+ export declare function walkToCertifiedHead(args: {
64
+ fromId: bigint;
65
+ fromHash: Uint8Array;
66
+ rows: SealedRow[];
67
+ certifiedHead: Uint8Array;
68
+ hashFirstFrom: bigint;
69
+ }): Promise<WalkResult>;