Storage
What we store—and where
EDMA separates facts we must prove publicly from files we must protect.
On-chain (L2 → L1 blobs): PoV hash (of the canonical JSON bytes), EMT ids, Locked→Unlocked EDSD deltas, fee and EDM burn lines (with burn tx hash), One-Claim updates. This is the public anchor you can replay.
Off-chain (evidence vaults, role-gated): PDFs, photos, CSVs, EDI payloads (COA/PSI, BL + seal photo/number, temp logs, customs, DC QA). The chain stores hashes, never the files.
Why: auditors and partners must verify truth from the chain; operators must keep sensitive dossiers private—without changing the hash that money relies on.
Storage layout
Evidence Vault (primary object store): Encrypted object storage for all submitted evidence and “proof pack” bundles. Every object carries metadata (sha256, size, content-type, created_at, schema_id). Objects are immutable by default (WORM/retention lock supported).
CDN & signed URLs (delivery): Files are never in webhooks. Authorized clients fetch via short-lived signed URLs (time-boxed, IP-scoped). Links are logged and redactable by policy.
Proof Pages & Explorer (public view): Human pages show the PoV hash, EMT id, burn hash, Locked→Unlocked EDSD deltas, One-Claim ref, and links to schemas. They do not expose raw files; they point to role-gated URLs.
Ledgers & receipts (accounting): Per-order and per-listing ledgers record releases/settlements, fee lines, and burn hashes. CSV/PDF exports are kept in the vault (with their own digests).
Proof-of-Reserves store (treasury): Daily snapshots of Locked EDSD reserves (≈75% T-bills / ≈25% cash), bank/custodian attestations, and a reserve ladder. Each snapshot is hashed and the hash is referenced on-chain.
Security controls
Encryption at rest: AES-256 (server-side), envelope-encrypted keys in KMS/HSM; per-object keys; automatic key rotation.
Encryption in transit: TLS 1.2+ everywhere; HSTS on public endpoints.
Access control: role-based (buyer, seller, attestor, regulator/auditor, EDMA ops); least-privilege policies; IP allowlists for regulated roles.
Signed URLs: expiring, single-use; duration and scope governed; every fetch is audit-logged.
Upload hygiene: content-type validation, size limits, AV/malware scan, checksum verification prior to accept.
Keys & salts: attestor keys in the Attestor Registry; redaction salts kept in a dedicated Salt Vault (KMS-backed), rotated per org/lane; never reused across orders.
Integrity & auditability
File digests: every file is referenced by {name, sha256, size} in the dossier; changing a byte changes the hash and fails equality.
PoV hash: sha256(canonical_json_bytes) binds the dossier and its file digests; the same facts always hash to the same bytes.
Merkle roots (big logs): schemas may store a temp_log_root (SHA-256 Merkle); inclusion proofs verify segments without downloading the whole log.
Receipts: show PoV hash, EMT id, fee line, EDM burn hash, and claim id so auditors can replay from L1 blobs.
Append-only: corrections (revocation/replacement) append; we never mutate history. Proof pages show original + corrective lineage.
Lifecycle & retention
Retention policy: schema + lane decide retention (e.g., 7–10 years for trade docs; 10+ for ESG). The vault enforces retention locks (WORM) and legal holds.
Cold storage: old evidence moves to lower-cost classes with retrieval SLAs; hashes stay live.
Deletion & DSAR: we never delete hashes on-chain; off-chain PII can be purged or redacted at path-level. Redaction uses salted commitments so a regulator can verify later without changing the PoV hash.
Backups & replication: multi-AZ, cross-region replication; daily backups; RPO ≤ 15 minutes, RTO ≤ 4 hours.
Privacy & redaction
Schema-declared redactable paths: (/evidence/warehouse_contact, ...).
Redacted fields: are omitted from canonical JSON; redactions[] records {path, reason, sha256(contact||salt)}.
Salts: live in the Salt Vault; disclosure is controlled and auditable.
Selective-disclosure / ZK wrappers: (roadmap) prove claims like “shelf-life ≥ X” or “temp in range” without revealing values.
APIs
POST /v1/evidence/upload: returns { name, sha256, size } after checksum & AV pass.
POST /v1/evidence/bundle: creates a proof pack (ZIP with receipts + dossier JSON); returns a signed URL (expires).
GET /v1/evidence/{sha256}: signed URL for that object (role-gated).
GET /v1/proof/{emt_id|token_id}: summary (PoV hash, claim id, links to schema & receipts).
GET /v1/por/daily: latest PoR snapshot (hash + signed link).
Webhooks: evidence.upload.accepted · proofpack.ready · por.snapshot.posted.
Monitoring & flags
Info: “Top-up due T-24h”, “PoR published”.
Warning: “Large file pending AV review”, “signed URL attempted after expiry”.
Blocker: “File hash mismatch”, “Merkle inclusion invalid”, “Reserve mismatch” (treasury). Blockers pause only the affected slice/listing.
Compliance mapping
GDPR/DSAR: PII redaction and path-level purge; immutable on-chain hashes remain.
SEC 17a-4 / WORM: retention lock on vault buckets; legal hold supported.
SOC2/ISO 27001 posture: audit logs (append-only), key management (KMS/HSM), access reviews, change control.
Sanctions/AML: role-gated evidence access; fetches logged; exports controlled for restricted parties.
Operator checklist
Store files by digest, not inline.
Keep canonical bytes next to the structured object in your DB so you can reproduce hashes byte-for-byte.
Use signed URLs only from trusted networks, and expect them to expire quickly.
When a banner flags a mismatch, re-upload the correct file or schedule re-inspection; the platform pauses only what’s affected.
Plain recap
Last updated