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