SDK v2.2.0 — ERF record builder for developers
Build review-ready records from your own code.
The Vraimony SDK gives you everything you need to assemble an ERF-compatible evidence record, assess its readiness, and generate the portable JSON that travels with it — and now also includes local-first helpers for browser-first upload routing, lightweight cache, compact receiver-pack sync, and template recommendation without any third-party runtimes or hidden telemetry. Final signing, premium compilation, and verify issuance stay on the server.
Zero dependencies
No telemetry
Node.js + Browser
ERF/1.0 compatible
SHA-256: c766c295ed878511c4c9fe5bd75ac37e82c3016ede16f396c679c241da7ed935 — verify against SHA256SUMS.txt before deploying.
What the SDK does
Seven functions. One consistent record model.
| FUNCTION | PURPOSE | RETURNS |
| createRecord(opts) |
Build an ERF-compatible record from structured input — parties, timeline, evidence, ask |
ERF record object with light footprint baked in |
| assessReadiness(record) |
Assess whether a record is weak / partial / review-ready. Returns gaps list. |
{ state, gaps[], score } |
| validateERF(json) |
Validate ERF record format (structure only — not truth) |
{ ok, errors[], status_hint } |
| buildExportJSON(record) |
Generate portable ERF JSON with packaged_by, protocol, verify_url baked in |
Export-ready JSON object |
| statusLabel(item) |
Get PASS / Declared / Unverified for a single evidence item |
'PASS' | 'Declared' | 'Unverified' |
| formatReviewerSummary(record) |
Plain-text reviewer summary — suitable for email or handoff |
Formatted string with verify URL |
| canonicalize(value) |
Deterministic JSON serialization (Vraimony canonical profile — keys sorted lexicographically) |
Canonical JSON string |
What the SDK does NOT do: Cryptographic signing (ed25519), receiver-aware premium playbook compilation, entitlement checks, or final verify issuance — those require server-side control. The SDK stays a local runtime and helper layer.
Quick start
Build a record in under a minute.
const { createRecord, assessReadiness, buildExportJSON } = require('./vraimony-sdk');
const record = createRecord({
type: 'dispute',
title: 'Invoice #2891 — Scope Change Dispute',
sender: { name: 'Acme Agency', ref: 'AGCY-001' },
receiver: { name: 'Client Co', ref: 'CLT-042' },
ask: 'Confirm the scope change in the March change order is payable.',
timeline: [
{ date: '2026-01-15', event: 'Original contract signed' },
{ date: '2026-02-28', event: 'Scope change requested by client' },
{ date: '2026-03-10', event: 'Change order sent for approval' },
{ date: '2026-03-20', event: 'Invoice #2891 issued' }
],
evidence: [
{ label: 'Original contract', value: 'contract_2026-01.pdf', verified: true, mechanism: 'sha256' },
{ label: 'Change order email', value: 'email_2026-02-28.eml', verified: false },
{ label: 'Signed change order', value: null }
],
template: 'disputes/standard',
record_id: '3fa85f64-5717-4562-b3fc-2c963f66afa6'
});
const readiness = assessReadiness(record);
console.log(readiness.state); // 'partial'
console.log(readiness.gaps); // ['evidence_no_values'] — signed change order missing
console.log(readiness.score); // 70
const exportJSON = buildExportJSON(record);
PASS / Declared / Unverified
Every evidence item gets an honest status — not fake certainty.
const { statusLabel } = require('./vraimony-sdk');
statusLabel({ value: 'file.pdf', verified: true, mechanism: 'sha256' });
// → 'PASS'
statusLabel({ value: 'approval_email.eml', verified: false });
// → 'Declared'
statusLabel({ value: null });
// → 'Unverified'
PASS
Confirmed via verifiable mechanism. SHA-256 hash, server signature, or explicit verification flag.
Declared
Stated by sender — value exists in the record but not independently confirmed. Reviewer sees this explicitly.
Unverified
Missing or null. Gap is visible — the record does not pretend completeness it does not have.
Light footprint — baked into every export
Every JSON export carries three fields that make Vraimony visible to the receiver.
{
"packaged_by": "Vraimony",
"protocol": "https://www.vraimony.com/protocol.html",
"verify_url": "https://verify.vraimony.com/r/RECORD_ID",
"sdk_version": "2.0.0"
}
Every developer who opens this JSON sees the protocol link. Every reviewer who receives it can follow the verify URL. This is how the SDK distributes awareness — not through tracking, but through the record itself.
Readiness assessment
Know whether the record is ready before packaging anything.
const { assessReadiness } = require('./vraimony-sdk');
const result = assessReadiness(record);
result.state
result.gaps
result.score
weak
Multiple critical gaps. Record stays as local draft. Cannot be sealed. Use gap list to guide remediation.
partial
Most elements present, 1–2 gaps remain. Can be sealed as Provisional. Reviewer sees which elements are declared vs confirmed.
review-ready
All required elements present. Ready to seal as Final. Full PASS/Declared/Unverified labels. Tamper-evident.
Seal levels
Set in the SDK, enforced on the platform.
L1_PROVISIONAL
Draft — local only. The record is being assembled. Not yet sealed or tamper-evident.
L2_STANDARD
Sealed — server-signed, ed25519, tamper-evident. Review page active. Verify URL live.
L3_FINAL
Finalized — no further amendments. Used when the record is complete and the review has concluded.
Sealing happens on the Vraimony platform — not in the SDK. The SDK sets the intended seal level; the platform enforces it.
Evidence Degree (1–10) — optional precision layer
Declare how independently verifiable each evidence item is.
statusLabel({
value: 'bill-of-lading.pdf', verified: true, mechanism: 'sha256',
evidence_degree: 9, confidence: 95, externally_anchored: true
});
// → 'PASS' · Degree 9/10 · Externally anchored
statusLabel({ value: 'email.eml', verified: false, evidence_degree: 5, confidence: 75 });
// → 'Declared' · Degree 5/10 · 75% sender confidence
Degree 8–10 → PASS. Degree 4–7 → Declared. Degree 1–3 → Unverified.
Full reference →
Timestamp anchor — independent time proof
SHA-256 commitment verifiable offline — no Vraimony servers needed.
const anchor = buildTimestampAnchor({
contentHash: 'a3f4...', createdAt: '2026-03-25T10:00:00Z',
receiptId: '3fa85f64-...'
});
const result = verifyTimestampAnchor(anchor);
// → { ok: true, commitment_hex: '...', anchored_at: '2026-03-25...' }
Actor model — nested under Case
Every Case knows who its parties are.
The Actor model is stored internally under each Case (GA session, dispute, claim). It handles permissions, task routing, submission tokens, and audit trail. It is not exposed directly in the public API — it powers the logic behind it.
const actors = [
{
actor_id: 'actor-adjuster-001',
role: 'reviewer',
party_name: 'Richards Hogg Lindley',
permissions: ['read_all', 'download_all', 'close_session']
},
{
actor_id: 'actor-submitter-001',
role: 'submitter',
party_name: 'Acme Freight Forwarding',
interest_id: 'GA-2025-0441-001',
permissions: ['submit:GA-2025-0441-001']
}
];
Why internal? Exposing actors publicly would leak party relationships to unauthorised requests. The Actor model is the enforcement layer — it powers submission tokens, status visibility, and future multi-user access without appearing in public responses.
Workspace-specific examples
Same SDK core. Different workspace context.
🚢 Shipping / GA
fetch('/v1/ga/request', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
ga_reference: 'GA-2025-0441',
adjuster_name: 'Average Adjusters Ltd',
interests: [
{ role: 'forwarder', bl_ref: 'BL-001' },
{ role: 'insurer' }
]
})
})
🛒 Commerce / Dispute
fetch('/v1/seal', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
hash: sha256(file),
evidence: [
{ label: 'Invoice', status: 'PASS',
evidence_degree: 9 },
{ label: 'Delivery email', status: 'Declared',
evidence_degree: 5 }
]
})
})
Event authenticity — HMAC signing
Verify signed GA submissions before processing them.
Every GA submission generates a signed event envelope. The adjuster verifies the HMAC-SHA256 signature before updating their system. Constant-time comparison prevents timing attacks.
{
event_type: 'ga.interest.submitted',
ga_reference: 'GA-2025-0441',
timestamp_ms: 1748000000000,
signature: 'sha256=a3f4...',
algorithm: 'hmac-sha256',
signed: true
}
const canonical = `${event_type}:${ga_reference}:${timestamp_ms}:${sha256(data)}`;
const expected = 'sha256=' + hmacSHA256(canonical, GA_WEBHOOK_SECRET);
const { verifyGAEvent, signGAEvent, GA_EVENT_TYPES } = require('./lib/webhookSignatures');
const result = verifyGAEvent(envelope, GA_WEBHOOK_SECRET);
// → { ok: true } or { ok: false, reason: 'invalid_signature' | 'expired' }
GA_WEBHOOK_SECRET: Set in server env. If absent, events are signed: false (graceful — not a fatal error). Absent secret = unsigned events, not broken events.
Security Architecture v1 →
Verdict Stack — reading the multi-layer verdict
Every /v1/seal response now includes a verdict object.
{
receipt: { ... },
verdict: {
label: 'SEALED',
score: 87,
stack: {
structural: { ok: true, score: 100, issues: [] },
integrity: { ok: true, score: 100, anchor_verified: true },
policy: { ok: true, score: 90, quarantine_triggers: [] },
readiness: { ok: true, score: 80, readiness_label: 'review_ready' },
risk_flags: []
}
}
}
verdict: {
label: 'QUARANTINED',
score: 62,
quarantine: {
flagged_items: [{ type: 'overclaim', item: 'delivery_proof',
reason: 'confidence=90 but degree=3' }],
safe_to_share: true,
restore_path: 'Correct flagged items and re-seal'
},
appeal: {
endpoint: '/v1/seal/explain',
why_flagged: ['evidence_pass_below_min_degree:delivery_proof'],
what_would_clear_it: ['Set evidence_degree >= 6 or downgrade to Declared']
}
}
const explain = await fetch(`/v1/seal/explain?id=${receiptId}`).then(r => r.json());
Reviewer state API — four endpoints
Track what the reviewer did with the record.
await fetch('/v1/review/open', {
method: 'POST', headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ receipt_id: '3fa85f64-...' })
});
// → { ok: true, first_open: true, open_count: 1 }
await fetch('/v1/review/ack', {
method: 'POST', headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ receipt_id: '3fa85f64-...', note: 'Confirmed. Cargo release authorised.' })
});
await fetch('/v1/review/mer', {
method: 'POST', headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ receipt_id: '3fa85f64-...', content: 'Commercial invoice CIF value missing' })
});
const state = await fetch(`/v1/review/state?id=3fa85f64-...`, { headers: { Authorization: `Bearer ${certToken}` } }).then(r => r.json());
// → { reviewer_state: { state: 'acknowledged', link_opened: true, open_count: 2,
// ack_received: true, ack_at: '2026-03-26T...', mer_requested: false } }
Privacy: No reviewer identity stored. Actions only. State stored in reviewer_states/, never in the sealed ERF record.
Recovery paths — Authenticator-inspired fallback design
Every critical path has a recovery. The delete_token is your backup code.
fetch('/v1/seal/reissue-access', {
method: 'POST', headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ receipt_id: '3fa85f64-...', delete_token: 'your_backup_code' })
})
// → { ok: true, certificate_token: 'new_token', reviewer_state_url: '...' }
fetch('/v1/seal/supersede', {
method: 'POST',
body: JSON.stringify({ receipt_id: '3fa85f64-...', delete_token: 'backup',
reason: 'Invoice value updated' })
})
// → { superseded_id: '...', next_step: 'POST /v1/seal with supersedes_id in payload' }
fetch('/v1/ga/reopen?ref=GA-2025-0441&name=Average+Adjusters+Ltd')
// → { adjuster_token: 'new_token', status_url: '...' }
Design rule: delete_token = backup code. Never lose it. Store separately from certificate_token.
Like Google Authenticator: backup codes are the recovery path when the primary fails.
Install in 3 steps
No package manager required. Works anywhere JS runs.
1. Download
Download the official ZIP from www.vraimony.com. Verify SHA-256 before deploying.
2. Include
const SDK = require('./vraimony-sdk');
<script src="vraimony-sdk.js"></script>
3. Start narrow
Build one record. Run assessReadiness(). Check the gaps. Expand only when the basic flow proves itself.
Security and privacy
What we promise about the SDK.
✓ No telemetry. No tracking. No analytics. No phone-home.
✓ No remote dependencies. Works fully offline.
✓ Full ed25519 signature verification requires verify.vraimony.com — the SDK provides the validation stub and structure only.
✓ This SDK does not claim legal admissibility, compliance certification, or official validation. Integrity packaging only.
New in v2.2.0
Local-first workflow helpers.
Use capabilityProbe() to decide between local and hybrid mode, summarizeUploads(), assessBundleVerdict(), and recommendTemplate() to route bundles in the browser, createIndexedCaseCache() for IndexedDB state, and fetchTemplatePacks() for same-owner server packs only. No third-party runtimes. Same-server workflows only.
Core decision assets
Everything here should map back to four assets only.
PFRPPre-Flight Rejection Predictor
Predict likely pushback before the case is packaged, then fix the structural blockers first.
Receiver PacksReceiver Packs
Signed, receiver-specific guidance packs: required evidence, preferred order, rejection patterns, delivery lane, wording bans, and official-source deltas.
ZRDRZero-Read Decision Receipt
Give the receiving side a summary they can act on fast, without reading the whole file first.
Final Approval / DeliveryFinal Approval + Delivery
Apply receiver-aware approval rules, then send the file through the lane that fits that workflow best.
Receiver Profiles
Receiver Profiles are the guidance layer across scan, packaging, verify, and rails.
- Required evidenceWhat the receiver expects before the file feels complete enough to review.
- Preferred orderHow the file should be read first: summary, timeline, proof, policy, then the ask.
- Rejection patternsThe structural reasons this type of receiver most often pushes a case back.
- Delivery laneThe lane that fits best: portal, verify-first, summary PDF, or supporting attachments after review.
- Wording bansWeak or noisy phrasing that makes the file harder to trust or easier to dismiss.
- Official-source deltasCompact updates distilled from the receiver's own public guidance, rules, or dispute documentation.
Vraimony uses the same Receiver Profiles layer across Free Scan, One Case, Viewer, Verify, Downloads, SDK, and plugin rails — so the file is guided by the receiver, not by a generic template.
Decision layer fit
Not another tool. A receiver-aware decision layer.
Use the same four assets everywhere: PFRP, Receiver Packs, ZRDR, and Final Approval / Delivery. The plugin, SDK, verify surface, and templates are rails around that layer — not the layer itself.
PFRPReceiver PacksZRDRFinal Approval / Delivery