ADR-0100 — Token Economy Security Model + Admin Observability¶
- Status: Accepted
- Date: 2026-05-26
- Deciders: André Luiz Gallon (project owner) + security review session 2026-05-26
- Driver: Project owner request — "token economy 100% protected, inviolable, perfect, no failures, no errors; admin dashboard for technical + executive teams"
- Related: ADR-0033 (UTXO model — preserved, patent claim #25 boundary), ADR-0099 (v5 token economy — extends with security layers + observability)
- Patent claim family: Extension of #25 — multi-layer fraud-defense + tamper-evident audit chain may qualify for a follow-on claim (TBD with patent counsel)
Context¶
The project owner's directive: "ensure the token economy is 100% protected against fraud and counterfeiting, perfect operation, no failures, inviolable, anti-hacking; admin dashboard at tlsstress.art for tech + exec teams".
Engineering reality check¶
There is no software system that is 100% inviolable. Pursuing that as an engineering goal leads to two failure modes:
- Marketing-engineering gap — claiming 100% creates legal liability when (not if) a real incident occurs. FTX, Mt.Gox, and NewBank all promised inviolability.
- False sense of security — chasing impossible perfection causes teams to under-invest in detection + rollback (which matter more than prevention because no prevention is perfect).
The engineering-honest framing is: "defense in depth at industry-leading parity with the top crypto-exchanges, banks, and SaaS platforms (Stripe / Coinbase / Cloudflare / AWS / Snowflake), with cryptographic provenance making attacks expensive, audit-evident, and reversible".
This ADR commits to that model + the corresponding admin surface so the operator can observe, audit, and respond.
Decision¶
Adopt 7-layer defense-in-depth model for the Token Economy. Every operation that mints, spends, or refunds TSU passes through (most or all of) these layers. Each layer is independently sufficient to catch most attacks; an attacker must defeat ALL applicable layers concurrently.
Security Layer Model (Phase G)¶
| Layer | Defends against | Implementation file |
|---|---|---|
| 1 — UTXO note model | Restore-from-backup attack | pkg/license-art/internal/ledger/ (ADR-0033) |
| 2 — Cryptographic operation signing | DB tampering, insider modification | pkg/license-art/internal/security/signing.go |
| 3 — Tamper-evident audit chain | Forensic gap, evidence destruction | pkg/license-art/internal/security/audit_chain.go |
| 4 — Idempotency + nonce store | Replay attacks, double-spend via retry | pkg/license-art/internal/security/idempotency.go |
| 5 — Rate limiting (per-account + per-IP) | Brute-force, velocity attacks | pkg/license-art/internal/security/ratelimit.go |
| 6 — Fraud risk scoring engine | Behavioral anomalies, abuse patterns | pkg/license-art/internal/security/fraud_score.go |
| 7 — Manual review queue + revocation broadcast | Confirmed fraud, account takeover | pkg/oobi/licenseart/ (existing) + new admin UI |
Admin Observability (Phase H)¶
Three operator-facing dashboard panels at https://tlsstress.art/admin:
| Panel | Audience | Surfaces |
|---|---|---|
Executive (/admin/exec) |
C-level, board | ARR, MRR, MoM growth, churn, tier mix, conversion funnel |
Financial (/admin/finance) |
CFO, RevOps, Finance | Stripe reconciliation, MSSP settlement, refund rate, anomalies, revenue by tier/region |
Technical (/admin/tech) |
Eng team, SRE | Ledger latency p50/p95/p99, mint/spend velocity, error rate, fraud alerts inbox, audit chain integrity status |
All three dashboards consume the SAME underlying APIs — only the rendering differs. APIs return real data when LEDGER_BACKEND=sql is set; Fake demo data otherwise (per ADR-0099 adapter pattern).
Layer-by-layer specification¶
L1 — UTXO note model (preserved per ADR-0033 + claim #25)¶
Already shipped via pkg/license-art/internal/ledger/. The note-not-balance accounting structurally defeats restore-from-backup attacks: restoring an old DB state restores spent notes, but their successor notes don't validate because the chain has moved on.
Threat defeated: Insider operator backs up the DB, runs tests to deplete TSU, restores backup, runs again. Defeated because successor notes from the original run reference the now-restored old state, but the validator's chain head has moved on.
L2 — Cryptographic operation signing (Ed25519)¶
Every mint, spend, and refund operation produces a signed envelope at write time. The envelope contains: - Operation type (mint/spend/refund) - Operation timestamp - Account ID - Amount - Source/reference - SHA-256 of the prior operation's signature (chain link) - Ed25519 signature using the operator's HSM-backed private key
The Postgres rows store the signature alongside the operation. Anyone with read access to the DB can verify the chain externally without trusting our binaries.
Threat defeated: Rogue DBA modifies a UTXO row to increase balance. The Ed25519 signature now mismatches the modified row's content, breaking the chain at the next verification pass. Operator-facing alert fires.
L3 — Tamper-evident audit chain (SHA-256 hash chain)¶
Independent from L2 — provides a SECOND verification path:
- Every operation appended to an immutable audit_chain table
- Each row's entry_hash = SHA-256(prev_hash || canonical_json(operation))
- A daily cron walks the chain end-to-end and recomputes hashes
- Mismatch → operator alert + chain frozen until resolution
This is the same model NetSec OPEN uses (already wired in pkg/octopus/syslog-art/ for SYSLOG audit). We extend it to ledger operations.
Threat defeated: Rogue DBA modifies a UTXO row AND its signature (defeating L2). The audit chain row still references the original SHA-256, so the chain still breaks. Attacker must modify the audit chain TOO — which then breaks the daily integrity scan.
L4 — Idempotency + nonce store¶
Every operation that can be retried (Stripe webhook, payment confirmation, mint/spend/refund) carries an idempotency key:
- Webhooks: event.id from Stripe / Coinbase / etc.
- API calls: Idempotency-Key HTTP header
- Internal ops: ULID minted at request creation
The idempotency_keys table dedupes — second submission with same key returns the original result without re-running side effects.
Threat defeated: Replay attack (capture a successful POST, re-submit). The second submission hits the idempotency check and returns cached result without minting twice. Stripe-webhook double-delivery (already wired for KYC per ADR-0076) extended to all payment surfaces.
L5 — Rate limiting (token bucket)¶
Two layers: - Per-account: max N operations per minute (per type — mint allowed faster than refund) - Per-IP: max M operations per minute (no auth bypass)
Token bucket algorithm with operator-tunable rates. Defaults aligned with Stripe's published rate limits (100 req/s default; burst 500).
Threat defeated: Brute-force enumeration of accounts; mass-scrape of operations; auth-bypass via flooding. Bucket exhaustion → HTTP 429 with retry-after.
L6 — Fraud risk scoring engine¶
Rule-chain that scores every operation 0–100 (low → high risk): - Velocity rules (spending >3× 30-day avg = +30 points) - Amount rules (single op > $10k = +20 points) - Geo rules (IP country ≠ KYC country = +25 points) - Promo abuse rules (5+ codes redeemed in 30 days = +20 points) - KYC tier mismatch (Defense operation on KYC-Tier-1 account = +50 points) - Device fingerprint (new device on $1k+ op = +15 points)
Score → decision: - 0–40: auto-allow - 41–69: allow + flag for admin review - 70–100: block + queue for manual review (operator decides)
Rules are pluggable; operator tunes thresholds via admin UI.
Threat defeated: Compromised credentials draining account; promo-farming networks; geographic anomalies suggesting account takeover.
L7 — Manual review queue + revocation broadcast¶
Confirmed fraud triggers: 1. Account flagged in admin UI 2. UTXO clawback (anti-UTXO mint cancelling fraudulent UTXOs) 3. Stripe customer suspended (no further charges) 4. Revocation broadcast via OOBI Hello mesh (per ADR-0048) — every deployment receives the revocation list within ~30s globally 5. License tokens expire on next rolling check → MÓDULO refuses service
Threat defeated: Confirmed fraud after the fact. The revocation broadcast is the kill-switch that makes recovery global + automatic without per-deployment operator action.
Admin observability surface (Phase H)¶
Authentication¶
/admin/* requires:
- Separate session cookie from customer-app (different domain or subdomain)
- WebAuthn (FIDO2) required — TOTP fallback rejected for admin tier
- Per-admin RBAC: viewer | analyst | finance | admin | superadmin
- All admin actions logged to the same audit chain (Layer 3)
Page structure¶
/admin
├── /admin/exec — Executive
│ ├── ARR / MRR cards with MoM trend
│ ├── Tier-mix pie chart (Free / Pro / Ent / Def / Unlim)
│ ├── Conversion funnel (Free→Pro, Pro→Ent)
│ ├── Churn rate (rolling 90d)
│ └── Geo revenue map
├── /admin/finance — Financial
│ ├── Stripe reconciliation (charges vs mint events)
│ ├── MSSP monthly settlement (per partner)
│ ├── Refund rate + anomaly flags
│ ├── Revenue by tier + region
│ ├── Failed-payment retry queue
│ └── Tax compliance status (Stripe Tax + NF-e.io)
├── /admin/tech — Technical
│ ├── Ledger latency p50/p95/p99
│ ├── Mint / spend / refund velocity (real-time)
│ ├── Error rate per endpoint
│ ├── Audit chain integrity (last 24h walk result)
│ ├── Fraud alerts inbox (risk score ≥70)
│ └── Rate-limit hits by /endpoint, /account
└── /admin/audit-chain — Audit chain viewer
├── Search by account / time / operation type
├── Chain verification on-demand
└── Forensic export (CSV/JSON, signed)
Consequences¶
Pros¶
- Defense in depth at top-tier industry parity — matches what Stripe, Coinbase, Cloudflare deploy.
- Patent claim #25 boundary preserved — security layers wrap the UTXO model; they don't modify it.
- Audit-evidence by design — every operation cryptographically verifiable independently of our binaries.
- Operator visibility — exec/finance/tech can each consume the same data through their lens.
- Compliance-ready — audit chain + RBAC + per-event provenance map directly to SOC 2 controls + EU NIS2 + DORA.
- Reversibility — confirmed fraud reverses via OOBI broadcast + anti-UTXO; not "tough luck".
Cons¶
- Operational complexity — 7 layers = 7 things that can mis-configure. Mitigated by adapter-pattern Disabled defaults + comprehensive tests.
- Latency cost — each operation crosses Layers 2+3+4+5+6 → ~3-5ms overhead in the hot path. Mitigated by async writes to L3 audit chain + sub-ms verification of L4 idempotency.
- No "100% guarantee" — engineering reality. We commit to defense in depth + rapid detection + reversibility, not perfection. Documented in this ADR for legal/marketing clarity.
Reversibility¶
- L1-L4: high (configurable, can disable per env-var per adapter pattern)
- L5: high (rate limits tunable per-endpoint)
- L6: high (rule weights operator-tunable via admin UI)
- L7: medium (OOBI broadcast is a one-way operation per ADR-0048; we have rescind capability)
Implementation roadmap (extension of ADR-0099 Wave-A..F)¶
| Phase | Duration | Scope |
|---|---|---|
| G — Security primitives | 2 weeks | L2 signing + L3 audit chain + L4 idempotency + L5 rate limit + L6 fraud scoring |
| H — Admin dashboard | 3 weeks | RBAC + 3 panels (exec/finance/tech) + audit chain viewer |
| G+H mostly stdlib-only | — | No new deps; admin uses existing customer-app stack |
This ADR commits to PARITY-with-top-tier-platforms. Specific incremental enhancements (e.g. Sigstore transparency log integration, ML behavioral analysis, HSM upgrade beyond software-Ed25519) ship as follow-up ADRs as demand signals materialize.
Related¶
- ADR-0033 — UTXO model (foundation, claim #25)
- ADR-0048 — ZTP-Prem compliance (revocation broadcast)
- ADR-0076 — Stripe Identity webhook idempotency (foundation for L4)
- ADR-0099 — Token Economy v5 (this ADR extends)
Last verified against strategy: 2026-05-26 (Phase G + H decision locked in security review session).