The bank scopes. Knox produces. The examiner verifies.
When an examiner requests records, a bank’s BSA officer scopes an audit pack — period, event types, the examination authority on whose behalf the records are being produced. Knox resolves the in-scope Knox-anchored events, encodes a deterministic bundle (canonical-JSON manifest + per-event signed-record entries + Federal Rules of Evidence 902(13) and 902(14) certificate template + verification instructions), and anchors the bundle’s hashes to the chain. The bank’s portal delivers; the examiner verifies every hash and every chain link locally and confirms the bundle’s Knox anchor at the public verify endpoint.
Same source events plus same scope plus same generation timestamp always produce byte-identical bundle bytes.
- The gap. A bank’s case-management tool holds the BSA work product. When an examiner asks for records, the bank exports from that tool — CSV / PDF / report bundle. The export is what the examiner sees; the chain of custody from production through delivery is internal to the bank.
- What Knox produces. A deterministic ZIP archive with four artifact classes: manifest.json (canonical-JSON, RFC-8785-shaped), signed-records/<iso>_<type>_<short-block>.json (one per event), certificate-of-authenticity.txt (Federal Rules of Evidence 902(13) and 902(14) template), verification-instructions.md (Markdown, examiner-grade vocabulary).
- What Knox anchors. bonis_audit_pack_generated records the scope and the computed bundle_manifest_sha256 + bundle_zip_sha256 + events_included_count + generation_completion_timestamp. bonis_examiner_audit_pack_exported records each pull’s examiner reference + examination authority + delivery channel + bank’s chain-of-custody attestation. Both anchors propagate into the canonical hourly Merkle aggregation submitted to the OpenTimestamps protocol calendars for Bitcoin block confirmation.
- Tamper-evidence on export. Every pull re-resolves source events (frozen to created_at ≤ generation_completion_timestamp), re-runs the pure-function generator + deterministic ZIP encoder, and verifies the rebuilt hashes against the anchored hashes. Mismatch returns HTTP 409 with both hashes echoed — a structural tamper signal that halts export until investigated.
- Posture. Bank scopes. Bank delivers. Bank’s custodian signs the printed FRE 902 certificate. Knox produces deterministic bytes and records receipts.
Four artifact classes. Every file’s hash recorded in the manifest.
The manifest is the index; the signed-records are the records; the certificate is the self-authenticating instrument under the Federal Rules of Evidence; the verification instructions tell the examiner exactly how to confirm every claim independently. The full generator ships at src/lib/audit-pack-generator.ts; the ZIP encoder at src/lib/audit-pack-zip.ts.
Canonical-JSON RFC-8785-shaped manifest of every event in the bundle.
Per-event entries: knox_event_id, event_type, payload_sha256, block_hash, previous_event_hash, ots_proof_verify_url, anchored_at, signed_record_filename, signed_record_sha256. Top-level: manifest_version, scope echo (the original AuditPackScope), events array, summary (events_included_count, distinct_event_types_count, earliest/latest anchored_at), certificate metadata (filename + sha256 + rules), verification_instructions metadata. Sorted, integer-only numbers, no whitespace — byte-stable across machines.
One canonical-JSON file per anchored event in the scope.
Each file contains: knox_event_id, event_type, anchored_at, block_hash, previous_event_hash, payload_sha256, ots_proof_verify_url, payload (the structurally-redacted BSA attestation payload). Filename ordering is deterministic and lexicographically sortable; identical inputs always produce identical filenames. SHA-256 of each file is recorded in manifest.json.
Plain-text Federal Rules of Evidence 902(13) and 902(14) certificate template.
Cites both rules together. Explains that records are generated by an automated process (902(13)) and that the bundle is a hash-identified copy of records held on the Knox chain (902(14)). Includes the bundle scope summary, the substrate description (SHA-256 → chain → Merkle → OpenTimestamps → Bitcoin), a reference to verification-instructions.md, and a custodian signature block. The bank's custodian signs the printed copy; Knox provides the technical evidence supporting the certification.
Markdown procedure for an examiner to independently verify the bundle.
Four steps: (1) verify every signed-record SHA-256 against the manifest entry; (2) walk every chain block via /api/knox/verify and confirm chain.previousAnchor.hash matches each manifest entry's previous_event_hash; (3) describes the canonical hourly OpenTimestamps Bitcoin-anchor process plus the v1.1 roadmap for end-to-end examiner-side .ots proof retrieval; (4) fetch the generation anchor descriptor at /api/knox/verify by the bundle's anchor payload hash (supplied by the bank's portal alongside delivery) and confirm the recorded bundle_manifest_sha256 + bundle_zip_sha256 match what the examiner computes locally. Notes the Federal Rules of Evidence 902 architectural posture.
Same source events. Same scope. Same generation timestamp. Byte-identical bytes.
Determinism is what makes the bundle hash a load-bearing evidentiary primitive. If the bundle were generated by a non-deterministic encoder, the hash anchored at generation time could not be re-derived later — the examiner would have to trust that Bonis or the bank kept the original bundle bits intact. Pure-function generator + STORE-method ZIP with pinned timestamps removes the trust requirement. Every byte is reproducible from the source events; every hash is verifiable by recomputation.
No I/O, no clock reads, no random sources, no module-level mutable state. Same inputs always produce identical AuditPackBundle output (manifest, manifest_canonical_json, manifest_sha256, signed_records[], certificate_text, certificate_sha256, verification_instructions_text, verification_instructions_sha256).
canonicalize() sorts object keys, rejects NaN/Infinity/floats (Knox payloads are integer-only by schema), no whitespace, JSON.stringify-escaped strings. Both manifest serialization and per-event signed-record serialization run through the same canonicalizer.
encodeDeterministicZip() sorts entries by filename in ASCII order, uses STORE method (no compression — no per-implementation DEFLATE-encoder variance), pins every Local File Header and Central Directory Header timestamp to the ZIP format epoch (1980-01-01 00:00:00), sets the UTF-8 GP flag bit, omits all extra fields/comments. CRC-32 uses reflected polynomial 0xEDB88320 (the standard variant used by ZIP, PNG, and Ethernet), table-based; round-trip tested against the in-tree parseStoreZip reader and against system unzip(1).
The export route at /api/knox/bsa/audit-pack/[bundleId] re-resolves the same Knox-anchored source events frozen to created_at <= generation_completion_timestamp, re-runs the deterministic generator + zip encoder, and confirms the rebuilt bundle_manifest_sha256 + bundle_zip_sha256 match the values anchored in bonis_audit_pack_generated. Mismatch returns HTTP 409 with both anchored and rebuilt hashes echoed — a structural tamper indicator that halts export until investigated.
On every export pull the source-event re-query filters by created_at <= the timestamp recorded at original generation, so events anchored after the bundle was first produced do not contaminate the rebuild. The events_included_count, the manifest, and the zip hashes therefore remain stable across every subsequent export of the same bundle_id.
One POST to generate. One GET to export. Per-tenant isolation enforced on both.
Generation produces the deterministic bundle and anchors the generation receipt. Export rebuilds, verifies, anchors the export receipt, and streams the bytes. The bank’s portal authenticates to both endpoints with the same Knox API key.
Bearer Knox API key. Body is the AuditPackScope minus computed fields (bundle_request_internal_ref, scope_period_start/end, scope_event_types, scope_customer_filter_count, scope_case_filter_count, requesting_examination_authority, requestor_internal_ref, requestor_role). Server fills events_included_count, bundle_manifest_sha256, bundle_zip_sha256, fre_902_certificate_rules, generation_completion_timestamp; anchors bonis_audit_pack_generated; returns the bundle_id (Knox event ID) plus hashes plus the download URL plus the required-headers description for the export call.
Bearer Knox API key (must match the originating bank — per-tenant isolation enforced; cross-tenant lookups return 404 to avoid existence leak). Required headers: X-Examiner-Opaque-Ref, X-Examination-Authority, X-Delivery-Channel, X-Chain-Of-Custody-Ref. Server re-resolves the bundle deterministically, verifies rebuilt hashes against anchored hashes (409 on mismatch), defense-in-depth PII scans the bundle (422 on hit), anchors bonis_examiner_audit_pack_exported BEFORE returning bytes, and streams application/zip with Content-Disposition: attachment plus echoed bundle hashes in response headers.
A bank can only audit-pack and export its own Knox-anchored events. The findMany filters at generate and at export-rebuild are both partitioned by apiKeyId == validated-caller. A probe attempting to export another bank's bundle_id receives HTTP 404 (not 403) so the response does not leak the existence of a different tenant's bundle.
Audit-pack schemas: bonisAuditPackGeneratedSchema (.strict, .superRefine for scope-period invariant + hash-distinct invariant) and bonisExaminerAuditPackExportedSchema (.strict, hash-distinct invariant). BSA_EVENT_SCHEMAS map widens to include both. Examination authority and delivery channel are enum-restricted; FRE 902 certificate rules are locked to fre_902_13_and_14 at v1.
Pure-function library: canonicalize, sha256Hex, buildSignedRecords, buildAuditPackManifest (two-pass: draft manifest → certificate + instructions → real-hashes manifest), buildFre902Certificate, buildVerificationInstructions, buildAuditPackBundle, scanBundleForPii (defense-in-depth). No I/O. No zip emission — that lives in the encoder.
Pure-function deterministic ZIP writer: crc32, encodeDeterministicZip, parseStoreZip (used by tests to round-trip-verify). STORE method only, sorted entries, pinned ZIP-epoch timestamps, UTF-8 GP flag, no extra fields, full Local File Header + Central Directory Header + EOCDR by hand per PKWARE APPNOTE 6.3.10. Round-trip tested vs system unzip(1).
Bank decides. Bank delivers. Bank’s custodian signs. Knox records.
The scope (period, event types, customer/case filter counts, requesting examination authority, requestor reference + role) is selected by the bank's officer. Bonis has no view onto, no role in, and no authority over scope selection.
The /api/knox/bsa/audit-pack/[bundleId] GET route is authenticated as the bank, not the examiner. The bank's portal is the delivery shim — it pulls the bundle, populates the examiner identity + delivery channel + chain-of-custody headers from the bank's own records, and delivers the zip to the examiner over the bank's chosen secure channel.
The certificate-of-authenticity.txt template carries the bank custodian's signature block. Knox does not sign the certificate. The custodian's signature attests the cryptographic evidence presented in the bundle on behalf of the bank's BSA program.
bonis_audit_pack_generated anchors the scope + computed bundle hashes + events_included_count. bonis_examiner_audit_pack_exported anchors the examiner identity + delivery channel + chain-of-custody reference. Both events are SHA-256 chained on the Knox chain and propagate into the canonical hourly Merkle aggregation that submits to the OpenTimestamps protocol calendars for Bitcoin block confirmation. The receipt pair is the structural evidence that an audit pack was produced and delivered.
Knox never decides scope, never decides delivery, never signs the FRE 902 certificate, never communicates with the examiner. Knox produces deterministic bytes and records receipts. The audit, the examination, and the adjudication belong to whoever has jurisdiction over the matter.
Cryptographic bundle hashes anchored to the Knox chain. The export rebuilds the bundle from source events and verifies the hash.
An examiner-bound export from a case-management tool delivers a report whose authenticity rests on the institution’s assurance that the tool produced it. An audit pack from Knox delivers a bundle whose authenticity is proved by recomputation against the public Knox chain — an attestation surface independent of the bank, independent of Bonis, and independent of any cooperation either party might or might not provide years after the fact. The Knox chain itself Merkle-aggregates hourly and submits to the OpenTimestamps protocol calendars for Bitcoin block confirmation; per-event raw .ots proof retrieval via public API is on the v1.1 roadmap.
What changes for the examiner
- Independent verifiability (v1). Every hash in the bundle is checkable with any SHA-256 implementation against the bundle bytes plus the public Knox chain descriptors at /api/knox/verify. End-to-end examiner-side raw .ots proof retrieval against any Bitcoin full node is on the v1.1 roadmap; the v1 evidentiary primitive is the SHA-256 hash chain plus the Knox-anchored bundle hash.
- Tamper-evidence end-to-end. The bundle hash is anchored at generation; the export route rebuilds and verifies on every pull. Any divergence between anchored and rebuilt hashes is structural evidence of tampering and returns HTTP 409.
- FRE 902(13)+(14) architecture. The certificate template cites both rules together — the strongest self-authenticating stance available for cryptographic evidence. The bank’s custodian signs; the technical evidence supporting the certification is in the verification instructions.
- Structural redaction. The BSA attestation schemas have no PII field. The audit-pack bundle inherits that structural property — no PII can reach the examiner because no PII was ever in the source records. Defense-in-depth scans at both ingress and export catch integration mistakes.
- Determinism as evidentiary primitive. Pure-function generator + STORE-method ZIP + pinned timestamps means the bundle bytes are reproducible from the source events. The examiner does not have to trust that Bonis or the bank kept the original bundle bits intact — they can reproduce them.
Every claim on this page resolves to live code or an external authoritative source.
Pure-function library: canonicalize, sha256Hex, buildSignedRecords, two-pass manifest, FRE 902 certificate, verification instructions, scanBundleForPii.
Deterministic STORE-method writer: crc32, encodeDeterministicZip, parseStoreZip (for round-trip verification in tests). Round-trip tested via the in-tree parseStoreZip parser plus system unzip(1).
bonisAuditPackGeneratedSchema + bonisExaminerAuditPackExportedSchema with cross-field invariants. BSA_EVENT_SCHEMAS map widens to 8 entries.
POST. Per-tenant chain query. Pure-function bundle assembly. Anchors bonis_audit_pack_generated.
GET. Rebuild-and-verify with frozen source set. Anchors bonis_examiner_audit_pack_exported. Streams application/zip.
The canonical BSA/AML Examination Manual. Every enum value in the BSA attestation and audit-pack schemas is named for what an examiner reads in this manual.
Cornell LII publication of the Federal Rules of Evidence. Rules 902(13) (electronically generated records) and 902(14) (data copied with hash identification) cited together in the certificate template.
The Knox chain submits hourly Merkle roots to the OpenTimestamps protocol calendars (alice / bob / finney). Bitcoin block confirmation status is recorded on the chain anchor descriptor as merkle.status. Per-event raw .ots proof retrieval via public API is on the v1.1 roadmap.
A Knox-anchored examiner audit-pack with a Federal Rules of Evidence 902(13)+(14) certificate template, every claim verifiable from chain descriptors and local recomputation.
Generate produces deterministic bytes and anchors the bundle hash. Export rebuilds, verifies against the anchor, and records the delivery. The bank’s custodian signs the printed certificate. The examiner verifies every signed-record hash, every chain link, and the bundle’s Knox anchor locally, independent of Bonis. Bitcoin-anchor confirmation propagates via the canonical hourly OpenTimestamps Merkle aggregation; per-event raw .ots proof retrieval via public API is on the v1.1 roadmap. Knox stays substrate; the audit-permanence layer is above the bank’s existing workflow, not in it.