Add Quantum Arcade design spec
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
181
docs/superpowers/specs/2026-08-05-quantum-arcade-design.md
Normal file
181
docs/superpowers/specs/2026-08-05-quantum-arcade-design.md
Normal file
@@ -0,0 +1,181 @@
|
||||
# Quantum Arcade — Design Spec
|
||||
|
||||
**Date:** 2026-08-05
|
||||
**Status:** Approved for planning
|
||||
**Repo:** https://gitea.thetempleofdoom.com/drjones/casino.git
|
||||
|
||||
## 1. Context and Scope
|
||||
|
||||
Quantum Arcade is a private, LAN-hosted physics gaming platform for the host and
|
||||
their friends, including at parties of up to ~100 people on phones. It runs
|
||||
entirely on a single Linux box owned by the host.
|
||||
|
||||
**In scope:** deterministic physics games (group and single-player), a
|
||||
provably-fair RNG, a double-entry ledger, Lightning deposits/withdrawals and
|
||||
peer-to-peer transfers, ephemeral chat, and a single-box Docker deployment.
|
||||
|
||||
**Out of scope for this phase:** public internet deployment, KYC/identity
|
||||
verification, geo-gating, and licensed real-money operation. The architecture
|
||||
keeps these as additive modules rather than rewrites, but they are not built
|
||||
here and this system is not to be exposed publicly as-is.
|
||||
|
||||
**Success criteria:**
|
||||
- A guest joins from a phone in under 5 seconds with no account creation.
|
||||
- 100 concurrent phones sustain a group round with no visible desync.
|
||||
- Any player can independently verify any round outcome on their own device.
|
||||
- End-of-night balances reconcile exactly, with a per-transaction explanation.
|
||||
|
||||
## 2. Identity
|
||||
|
||||
Identity is a keypair, not an account.
|
||||
|
||||
On first visit the browser generates an ed25519 keypair stored in IndexedDB and
|
||||
prompts for a nickname. The public key is the player ID: it is what the ledger
|
||||
posts against and what signs bet intents. There is no email, password, reset
|
||||
flow, or KYC.
|
||||
|
||||
Multi-device: a QR code exports the key from one device to another.
|
||||
Key loss means balance loss. This is accepted and stated plainly in the UI.
|
||||
|
||||
Nicknames are display-only and non-unique; the pubkey prefix disambiguates.
|
||||
|
||||
## 3. Architecture
|
||||
|
||||
One Go binary with enforced internal module boundaries, plus PostgreSQL, Redis,
|
||||
LND, and Caddy. Nine separate services on one machine would add latency and
|
||||
operational burden with no benefit at this scale.
|
||||
|
||||
```
|
||||
Caddy (TLS termination, static assets, WebSocket upgrade)
|
||||
└── quantum-arcade (single Go binary)
|
||||
├── ledger/ double-entry postings, append-only
|
||||
├── rng/ commit-reveal seed lifecycle
|
||||
├── sim/ deterministic physics core
|
||||
├── room/ round lifecycle, tick broadcast
|
||||
├── wallet/ Lightning in/out, P2P transfers
|
||||
└── chat/ ephemeral, in-memory only
|
||||
PostgreSQL ledger, rounds, seeds, results
|
||||
Redis live room state, presence, rate limits
|
||||
LND Lightning node, isolated wallet
|
||||
```
|
||||
|
||||
Modules communicate only through Go interfaces defined by the *consumer*. No
|
||||
module imports another's internal types. Extracting a module into its own
|
||||
process later is a transport change at the call site, not a rewrite.
|
||||
|
||||
**Scaling posture:** 100 concurrent WebSocket clients is a small fraction of a
|
||||
single Go process's capacity. The genuine constraint is PostgreSQL write
|
||||
throughput at settlement, addressed by settling each round in exactly one
|
||||
transaction with batched postings.
|
||||
|
||||
## 4. Deterministic Simulation Core
|
||||
|
||||
The physics core is fixed-timestep and integer-seeded, using fixed-point
|
||||
arithmetic rather than floating point to guarantee bit-identical results across
|
||||
platforms. It is compiled twice from one source: natively for the authoritative
|
||||
server, and to WASM for the browser.
|
||||
|
||||
Consequences:
|
||||
- The server broadcasts a seed, not a position stream. Bandwidth per additional
|
||||
phone is negligible.
|
||||
- Any client can replay any historical round locally.
|
||||
- The public verifier is simply the sim run against published inputs.
|
||||
|
||||
Determinism is a hard invariant, enforced by test (§9), not a convention.
|
||||
|
||||
## 5. Provable Fairness
|
||||
|
||||
Per round:
|
||||
|
||||
1. **Commit.** Server generates `serverSeed`, publishes `SHA256(serverSeed)`
|
||||
before the betting window opens.
|
||||
2. **Client seed.** Derived from the concatenated public keys of all
|
||||
participants in the round, in join order. The host cannot know the outcome in
|
||||
advance because the host does not control the inputs.
|
||||
3. **Outcome.** `HMAC-SHA256(serverSeed, clientSeed || nonce)` seeds the sim.
|
||||
The crash point / result is a pure function of that seed.
|
||||
4. **Reveal.** After settlement the server publishes `serverSeed`. Clients
|
||||
recompute the commitment hash, re-derive the seed, and re-run the WASM sim.
|
||||
|
||||
Verification runs on-device in roughly 400ms and requires trusting no server
|
||||
response. Seeds, commitments, and participant sets are retained permanently.
|
||||
|
||||
## 6. Games
|
||||
|
||||
All games share the sim core and the fairness pipeline.
|
||||
|
||||
**Group rounds** — a fixed ~5-minute cadence; all players watch the same
|
||||
simulation. Three crash variants rotate:
|
||||
- *Rocket vs. gravity* — multiplier is altitude; the craft visibly strains as
|
||||
fuel depletes toward the seeded crash point.
|
||||
- *Orbital decay* — multiplier is orbits completed, each pass dipping lower.
|
||||
- *Stacking tower* — multiplier is height; wobble grows until collapse.
|
||||
|
||||
Round lifecycle: `betting_open` → `locked` → `running` → `settled`. Cash-out
|
||||
intents are signed by the player key and accepted only while `running`.
|
||||
|
||||
**Single-player** — always available between group rounds, ~10 seconds per play,
|
||||
one tap to start: gravity-slingshot targeting, physics drop, and a
|
||||
momentum/timing challenge. Same fairness proof, per-play nonce.
|
||||
|
||||
## 7. Ledger and Money
|
||||
|
||||
Double-entry, append-only. No row is ever updated or deleted; corrections are
|
||||
compensating entries.
|
||||
|
||||
Every posting records: transaction ID, timestamp, player pubkey, account,
|
||||
amount, round ID, balance before, balance after. Each transaction's postings sum
|
||||
to zero. Player balances may never go negative.
|
||||
|
||||
Accounts: per-player balances, house pot, and Lightning bridge accounts. The
|
||||
house pot balance is displayed in the UI to all players — the pool is never
|
||||
opaque.
|
||||
|
||||
**Lightning:** deposit and withdraw via invoice/QR against the on-box LND node.
|
||||
The LND wallet is isolated from application state, with its own credentials and
|
||||
backup path.
|
||||
|
||||
**Peer-to-peer transfers:** instant, purely internal ledger entries between two
|
||||
player accounts, signed by the sender's key. This is the primary way value moves
|
||||
between friends at a party.
|
||||
|
||||
## 8. Interface and Feel
|
||||
|
||||
Phone-first portrait layout; cash-out is thumb-reachable.
|
||||
|
||||
Deep obsidian and indigo ground, with dense ornate filigree etched into the
|
||||
background. Vibrant cyan and magenta are reserved exclusively for the live
|
||||
multiplier, the player's balance, and the cash-out control — everything that
|
||||
matters is luminous, nothing else is.
|
||||
|
||||
Ambient music is synthesized in WebAudio: endless, non-looping, and shipping
|
||||
with zero audio assets.
|
||||
|
||||
Chat is a compact sidebar, in-memory only, discarded when the round ends.
|
||||
Nothing is written to disk.
|
||||
|
||||
## 9. Testing
|
||||
|
||||
- **Ledger:** property-based tests for the invariants in §7 — postings sum to
|
||||
zero, balances never negative, no value created or destroyed across arbitrary
|
||||
transaction sequences.
|
||||
- **Sim determinism:** identical seed produces identical output across 10,000
|
||||
runs, and native output matches WASM output byte-for-byte.
|
||||
- **Fairness:** commitment always matches revealed seed; independent
|
||||
reimplementation of the verifier agrees with the server on recorded rounds.
|
||||
- **Load:** harness simulating 150 concurrent phone clients through a complete
|
||||
group round, asserting no desync and correct settlement.
|
||||
|
||||
## 10. Deployment
|
||||
|
||||
`docker compose up` on the single Linux box. Postgres and LND data on persistent
|
||||
volumes with scheduled backups. Caddy terminates TLS on the LAN. Prometheus and
|
||||
Grafana included for host and application metrics.
|
||||
|
||||
## 11. Explicit Non-Goals
|
||||
|
||||
- Not exposed to the public internet in this phase.
|
||||
- No engagement mechanics designed to extend play beyond a player's intent: no
|
||||
loss-chasing prompts, no artificial near-miss tuning, no dark patterns on
|
||||
cash-out. Game feel comes from the physics being genuinely good.
|
||||
- No mixing or obfuscation of fund provenance. The ledger is the product.
|
||||
Reference in New Issue
Block a user