Discover the next card.
Run the native RandomX miner to compete for blocks. Each accepted block rewards its miner with a distinct illustrated Wikipedia card.
diff --git a/Dockerfile b/Dockerfile index a46411a..0b38fb7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,12 +12,19 @@ WORKDIR /app COPY package.json package-lock.json ./ RUN npm ci COPY . . -ARG WIKIDECK_NETWORK=testnet +ARG WIKIDECK_NETWORK=mainnet +ARG WIKIDECK_GENESIS_TIME=1798761600 ENV VITE_WIKIDECK_NETWORK=$WIKIDECK_NETWORK +ENV VITE_WIKIDECK_GENESIS_TIME=$WIKIDECK_GENESIS_TIME RUN npm run build FROM build AS test RUN apk add --no-cache libstdc++ +ENV WIKIDECK_NETWORK=testnet \ + WIKIDECK_GENESIS_TIME=1792411200 \ + VITE_WIKIDECK_NETWORK=testnet \ + VITE_WIKIDECK_GENESIS_TIME=1792411200 +RUN npm run build COPY --from=randomx-build /native/build/wikideck-randomx /app/native/wikideck-randomx ENV RANDOMX_BINARY=/app/native/wikideck-randomx CMD ["npm", "test"] @@ -29,11 +36,17 @@ RUN npm ci --omit=dev --ignore-scripts && npm cache clean --force FROM node:24-alpine AS runtime RUN apk add --no-cache libstdc++ +ARG WIKIDECK_NETWORK=mainnet +ARG WIKIDECK_GENESIS_TIME=1798761600 ENV NODE_ENV=production \ HOST=0.0.0.0 \ PORT=3001 \ WIKIDECK_DATA_DIR=/app/data \ - RANDOMX_BINARY=/app/native/wikideck-randomx + RANDOMX_BINARY=/app/native/wikideck-randomx \ + WIKIDECK_NETWORK=$WIKIDECK_NETWORK \ + WIKIDECK_GENESIS_TIME=$WIKIDECK_GENESIS_TIME \ + WIKIDECK_IMAGE_NETWORK=$WIKIDECK_NETWORK \ + WIKIDECK_IMAGE_GENESIS_TIME=$WIKIDECK_GENESIS_TIME WORKDIR /app COPY --from=production-deps /app/node_modules ./node_modules COPY package.json ./ diff --git a/README.md b/README.md index 5fbc931..da570b0 100644 --- a/README.md +++ b/README.md @@ -2,11 +2,11 @@ Wikideck is an experimental blockchain game about **mining, collecting, and trading illustrated Wikipedia cards**. Mine a block with the native RandomX CPU miner to earn a card, build a collection in a local wallet, and trade cards directly with another player. -**Production readiness:** see the [card-only production plan](docs/card-only-production-plan.md). A public beta and a valuable mainnet launch have separate release gates; neither is approved by a successful local build. +**Mainnet-first, still NO-GO:** the default image, runtime profile, and Compose service are mainnet, but the network is experimental, unaudited, and not launched. A local build is not production approval. See the [card-only production plan](docs/card-only-production-plan.md) and [mainnet launch gates](docs/mainnet-launch.md). Mining uses **RandomX, the proof-of-work algorithm also used by Monero**, designed to keep general-purpose consumer CPUs competitive. Wikideck is an independent blockchain, not part of Monero or its mining/security network. Hardware, total network hashpower and difficulty determine results; no particular mining reward rate or profitability is guaranteed. -**This is a local test network, not a public mainnet or an investment product.** No public bootnodes or hosted network are provided. Test NFTs have no promised value. Do not use funds or valuable assets. This project is not affiliated with Wikipedia or the Wikimedia Foundation. +**Mainnet is a gated candidate, not an operating public network or an investment product.** There are no hosted nodes, public bootnodes, or automatic peer discovery. No external audit is planned; the operator accepts that residual risk. Cards have no promised monetary value. Do not use funds or valuable assets. This project is not affiliated with Wikipedia or the Wikimedia Foundation. ## Mine, collect, and trade cards @@ -19,13 +19,13 @@ Mining uses **RandomX, the proof-of-work algorithm also used by Monero**, design ## What's available now -| Available in the testnet | Not included | +| Available in the mainnet-first codebase | Not included | | --- | --- | | RandomX mining and illustrated Wikipedia card rewards | Playable card games | | Encrypted local wallets, collections, transfers, and atomic card trades | Production network launch | -| Local single-node or optional three-node testnet | — | +| Mainnet candidate by default; testnet only as an explicit local development fixture | Public bootstrap network or production readiness | -## Quick start: one local node (Docker) +## Default: mainnet candidate (Docker) Install Docker Desktop with Linux containers and Docker Compose v2. From the repository root: @@ -34,9 +34,11 @@ docker compose up --build -d docker compose ps ``` -Open **http://127.0.0.1:3001**. The first run builds the node and native RandomX engine. The node does not mine automatically. Open the wallet panel to create a local wallet and encrypted backup, then follow [Mine Wikipedia cards with RandomX](#mine-wikipedia-cards-with-randomx) to run the miner. Stop the node with `docker compose down`; the ledger volume remains. **Do not add `-v` unless you intend to delete that data.** +The default Compose service is mainnet-first and binds only to **http://127.0.0.1:3201** behind a separately configured HTTPS edge. It intentionally exits until the exact chain approval, explicit unaudited-risk acceptance, genesis time, HTTPS origin, and at least two valid public HTTPS peers are configured. Do not set these to placeholders just to make the process start. See [mainnet launch gates](docs/mainnet-launch.md). The node does not mine automatically. Stop it with `docker compose down`; the ledger volume remains. **Do not add `-v` unless you intend to delete that data.** -## Optional: three-node testnet (Docker) +For isolated development, use the explicitly testnet-only [three-node fixture](#explicit-testnet-development-fixture-docker). `npm run dev` also pins both the API and Vite browser build to that testnet fixture; it does not silently change a production build. + +## Explicit testnet development fixture (Docker) Install Docker Desktop with Linux containers and Docker Compose v2. From the repository root, start three connected nodes: @@ -56,7 +58,7 @@ docker compose -f compose.testnet.yaml down The target block interval is **15 minutes**. The volumes persist across stops and rebuilds. **Do not add `-v` unless you intend to delete all three ledgers.** Back up wallets separately. Protocol v6 adds atomic multi-card trades and a new chain identity; earlier v2–v5 ledgers and encrypted backups are not compatible. To keep old Docker data intact while trying v6, use a separate Compose project name, for example `docker compose -p wikideck-v6 -f compose.testnet.yaml up --build -d`, and use the same `-p wikideck-v6` for subsequent Compose commands. The default `docker compose up --build -d` uses [compose.yaml](compose.yaml): it starts one isolated node on port 3001 with a different volume. -For an existing host install, keep the old data directory intact and set `WIKIDECK_DATA_DIR` to a new empty directory before starting protocol v6. The node intentionally fails closed on an old-protocol ledger; it does not reset or migrate it. A v6 JSON ledger is imported into SQLite on first startup and left in place as a recovery copy. +For an existing host install, keep the old data directory intact and set `WIKIDECK_DATA_DIR` to a new empty directory before starting protocol v6. The node intentionally fails closed on an old-protocol ledger; it does not reset or migrate it. A v6 JSON ledger is imported into SQLite on first startup and left in place as a recovery copy. `npm start` defaults to the gated mainnet identity; use `npm run dev` only for local testnet development. ## Run on your host @@ -81,19 +83,19 @@ The node listens at **http://127.0.0.1:3001** by default. For development, `npm Open the wallet panel to explicitly create an encrypted local P-256 wallet, unlock an existing vault, or encrypt a legacy plaintext wallet without changing its identity. Nothing is silently generated or unlocked at startup. Choose a strong local password of at least 12 characters. **Wallet backup & recovery** downloads a separately password-encrypted portable backup; keep the file outside the repository and its password separately, and test recovery in another browser profile. -New/migrated local vaults encrypt the key in IndexedDB; the unlocked key remains exportable in tab memory for signing and backup. Manual locking, five-minute inactivity, a four-hour absolute lifetime, reload, or hiding/leaving the tab ends the session. Same-origin compromise can still capture passwords or abuse an unlocked signer. Forgotten local passwords cannot be reset: recover from a usable backup. Legacy disk copies may retain old plaintext keys even after migration. Wallets are scoped to an origin (scheme, hostname, and port), so a backup must be restored at another origin to use the same identity there. Recovery does not move assets between chains. See [encrypted wallet lifecycle and remaining risks](docs/wallet-security.md). +New/migrated local vaults encrypt the key in an IndexedDB database scoped to the exact chain ID; v2 encrypted backups authenticate that same chain ID. Original fixed-testnet v1 backups remain recoverable only on that original testnet. The unlocked key remains exportable in tab memory for signing and backup. Manual locking, five-minute inactivity, a four-hour absolute lifetime, reload, or hiding/leaving the tab ends the session. Same-origin compromise can still capture passwords or abuse an unlocked signer. Forgotten local passwords cannot be reset: recover from a usable backup. Legacy disk copies may retain old plaintext keys even after migration. Wallets are scoped to an origin (scheme, hostname, and port), so a backup must be restored at another origin to use the same identity there. Recovery does not move assets between chains. See [encrypted wallet lifecycle and remaining risks](docs/wallet-security.md). -The current testnet wallet is separate from any wallet used by an older demo. There is no automatic migration. See [consensus, wallets, and operational limits](docs/testnet-consensus.md) and the in-app backup warnings for more detail. +Each genesis has a separate browser wallet store, and backups cannot cross chain identities. Testnet remains only as an explicit development fixture; there is no automatic migration from older demos. See [consensus, wallets, and operational limits](docs/testnet-consensus.md) and the in-app backup warnings for more detail. ## Mine Wikipedia cards with RandomX Mining uses the native CPU RandomX engine. First build the engine, download an encrypted wallet backup, then run the CLI from an interactive terminal and enter the password at its hidden prompt: ```sh -npm run miner -- --wallet "path/to/encrypted-backup.json" --consent --node http://127.0.0.1:3101 --blocks 3 +npm run miner:testnet -- --wallet "path/to/encrypted-backup.json" --consent --node http://127.0.0.1:3101 --blocks 3 ``` -Use port 3001 for the default single host/Docker node, or 3101–3103 for the three-node Docker testnet. The command above uses node-a. The miner defaults to one worker, light mode, and one block; `--blocks 3` requests up to three accepted blocks. Press **Ctrl+C** to stop it. Do not put the backup password in a command, environment variable, or repository file. The backup and password are decrypted locally and are not sent to the node. +The example is intentionally testnet-only and uses node-a; the dedicated command pins that profile and its fixed genesis. For mainnet, use `npm run miner` with a chain-bound mainnet backup and the configured HTTPS node origin after satisfying the mainnet launch gates. The miner defaults to one worker, light mode, and one block; `--blocks 3` requests up to three accepted blocks. Press **Ctrl+C** to stop it. Do not put the backup password in a command, environment variable, or repository file. The backup and password are decrypted locally and are not sent to the node. Each template request asks English Wikipedia for up to ten random pages and retries at most three times to find one with an image and readable extract. The same page may be selected again. The node also captures page size, language-link count, revision, pageviews, and derived scores for the mint-time snapshot. If Wikipedia cannot supply the article or its metadata, template creation returns an error; there is no fixed-article fallback. Validators check and commit the included snapshot without contacting Wikipedia during consensus validation. @@ -112,9 +114,9 @@ The browser interface trusts the connected node's reported state. It does not in ## Mainnet candidate · launch gated -**Production status: NO-GO pending remediation and independent review.** See the [security review](docs/security-review.md) and [operator launch checklist](docs/operator-launch.md). A read-only `launch:preflight` script reports blockers and local gate status without launching or granting approval. +**Production status: NO-GO pending network, capacity, deployment, and recovery evidence.** External audits are not planned; the operator accepts the residual risk, and the candidate must not be described as audited or certified. See the [security review](docs/security-review.md) and [operator launch checklist](docs/operator-launch.md). A read-only `launch:preflight` script reports blockers and local gate status without launching or granting approval. -A separate mainnet profile has its own network/genesis identity, ledger directory, browser wallet, backup checks, and opt-in [Compose definition](compose.mainnet.yaml). It preserves the existing testnet chain and does not migrate testnet cards. **No production network has been launched or certified by this work.** Startup requires explicit chain-specific approval, an operator review attestation, the candidate genesis time, HTTPS origins and multiple configured peers. See [the candidate launch gates and production checklist](docs/mainnet-launch.md). +The mainnet profile is the default and has a deployment-pinned network/genesis identity, separate ledger directory, chain-ID-scoped browser wallet, and chain-bound backups. The alternate [Compose definition](compose.mainnet.yaml) is also explicitly mainnet. Testnet is available only through the dedicated development/test harness. **No production network has been launched or certified by this work.** Startup requires explicit chain-specific approval, explicit unaudited-risk acceptance, the chosen genesis time in the built image, HTTPS origin, and multiple configured public peers. See [the mainnet launch gates and production checklist](docs/mainnet-launch.md). ## Tests and development checks @@ -146,7 +148,7 @@ This mines three real blocks using disposable identities. It changes the testnet Nodes use only explicitly configured peers; there is no discovery service or public bootstrap network. The peer, storage, and HTTP configuration is documented in [docs/testnet-consensus.md](docs/testnet-consensus.md). The implementation is experimental: it has no established economic security and remains vulnerable to resource exhaustion, isolation/eclipsing, censorship, majority-hashpower attacks, and reorganizations. The ledger now uses transactional SQLite/WAL storage and sparse per-block NFT-state deltas, but nodes still retain DAG block records in memory, rebuild state roots over the full NFT set, and revalidate all proofs at startup. It is not yet an archival-scale production design. HTTPS, container hardening, and passing tests do not constitute a security audit. -Before considering any broader deployment, the protocol and cryptography would need independent audits, adversarial network testing, hardened abuse controls, and tested recovery procedures. Do not expose a public node or use valuable assets on this experimental network. +Before considering any broader deployment, complete adversarial network testing, hardened abuse controls, and recovery procedures. External protocol/cryptography audits are not planned; this leaves accepted residual risk. Do not expose a public node or use valuable assets on this experimental network. ## Attribution diff --git a/compose.mainnet.yaml b/compose.mainnet.yaml index f916c90..1321094 100755 --- a/compose.mainnet.yaml +++ b/compose.mainnet.yaml @@ -2,20 +2,21 @@ # Review docs/mainnet-launch.md before attempting activation. services: mainnet: - profiles: [mainnet] build: context: . target: runtime args: WIKIDECK_NETWORK: mainnet + WIKIDECK_GENESIS_TIME: "${WIKIDECK_GENESIS_TIME:-1798761600}" ports: - "127.0.0.1:${WIKIDECK_MAINNET_PORT:-3201}:3001" environment: WIKIDECK_NETWORK: mainnet + WIKIDECK_GENESIS_TIME: "${WIKIDECK_GENESIS_TIME:-1798761600}" PUBLIC_ORIGIN: "${WIKIDECK_MAINNET_ORIGIN:-}" WIKIDECK_PEERS: "${WIKIDECK_MAINNET_PEERS:-}" WIKIDECK_MAINNET_LAUNCH: "${WIKIDECK_MAINNET_LAUNCH:-}" - WIKIDECK_MAINNET_REVIEW_ACK: "${WIKIDECK_MAINNET_REVIEW_ACK:-}" + WIKIDECK_MAINNET_RISK_ACK: "${WIKIDECK_MAINNET_RISK_ACK:-}" WIKIDECK_ALLOW_PRIVATE_PEERS: "0" # Empty by default; set only the actual edge-to-container source IP/CIDR after topology review. WIKIDECK_TRUSTED_PROXIES: "${WIKIDECK_TRUSTED_PROXIES:-}" diff --git a/compose.testnet.yaml b/compose.testnet.yaml index 8e91551..468dd7c 100644 --- a/compose.testnet.yaml +++ b/compose.testnet.yaml @@ -4,7 +4,10 @@ x-node-environment: &node-environment services: node-a: image: wikideck:testnet - build: { context: ., target: runtime } + build: + context: . + target: runtime + args: { WIKIDECK_NETWORK: testnet, WIKIDECK_GENESIS_TIME: "1792411200" } ports: ["127.0.0.1:3101:3001"] environment: <<: *node-environment @@ -23,7 +26,10 @@ services: stop_grace_period: 30s node-b: image: wikideck:testnet - build: { context: ., target: runtime } + build: + context: . + target: runtime + args: { WIKIDECK_NETWORK: testnet, WIKIDECK_GENESIS_TIME: "1792411200" } ports: ["127.0.0.1:3102:3001"] environment: <<: *node-environment @@ -42,7 +48,10 @@ services: stop_grace_period: 30s node-c: image: wikideck:testnet - build: { context: ., target: runtime } + build: + context: . + target: runtime + args: { WIKIDECK_NETWORK: testnet, WIKIDECK_GENESIS_TIME: "1792411200" } ports: ["127.0.0.1:3103:3001"] environment: <<: *node-environment diff --git a/compose.yaml b/compose.yaml index 5902d27..dc320f4 100644 --- a/compose.yaml +++ b/compose.yaml @@ -3,18 +3,25 @@ services: build: context: . target: runtime + args: + WIKIDECK_NETWORK: mainnet + WIKIDECK_GENESIS_TIME: "${WIKIDECK_GENESIS_TIME:-1798761600}" ports: - # Keep the prototype private; listen on all interfaces only inside the container. - - "127.0.0.1:${WIKIDECK_PORT:-3001}:3001" + # Loopback only; terminate reviewed HTTPS at the operator's edge. + - "127.0.0.1:${WIKIDECK_MAINNET_PORT:-3201}:3001" environment: - WIKIDECK_NETWORK: testnet - PUBLIC_ORIGIN: "${PUBLIC_ORIGIN:-http://127.0.0.1:${WIKIDECK_PORT:-3001}}" - WIKIDECK_PEERS: "${WIKIDECK_PEERS:-}" - WIKIDECK_ALLOW_PRIVATE_PEERS: "${WIKIDECK_ALLOW_PRIVATE_PEERS:-0}" + WIKIDECK_NETWORK: mainnet + WIKIDECK_GENESIS_TIME: "${WIKIDECK_GENESIS_TIME:-1798761600}" + PUBLIC_ORIGIN: "${WIKIDECK_MAINNET_ORIGIN:-}" + WIKIDECK_PEERS: "${WIKIDECK_MAINNET_PEERS:-}" + WIKIDECK_MAINNET_LAUNCH: "${WIKIDECK_MAINNET_LAUNCH:-}" + WIKIDECK_MAINNET_RISK_ACK: "${WIKIDECK_MAINNET_RISK_ACK:-}" + WIKIDECK_ALLOW_PRIVATE_PEERS: "0" + WIKIDECK_TRUSTED_PROXIES: "${WIKIDECK_TRUSTED_PROXIES:-}" volumes: - - wikideck-data:/app/data + - wikideck-mainnet-data:/app/data init: true - restart: unless-stopped + restart: "no" read_only: true tmpfs: - /tmp:size=32m,mode=1777,noexec,nosuid @@ -28,4 +35,4 @@ services: stop_grace_period: 30s volumes: - wikideck-data: + wikideck-mainnet-data: diff --git a/deploy/kubernetes/README.md b/deploy/kubernetes/README.md new file mode 100755 index 0000000..59bbfe4 --- /dev/null +++ b/deploy/kubernetes/README.md @@ -0,0 +1,22 @@ +# Kubernetes mainnet preparation + +This directory intentionally contains no apply-ready manifests yet. The code is mainnet-first and supports a genesis frozen into the browser bundle and runtime image, but the current launch gate requires deployment facts that were not supplied. Placeholder origins, approval IDs, TLS secrets, or storage settings would not produce a working or safe deployment. + +## Required topology for this implementation + +- Build and publish one immutable image with `WIKIDECK_NETWORK=mainnet` and one chosen `WIKIDECK_GENESIS_TIME`. Give every peer and browser bundle that same chain identity. A runtime-only genesis override is rejected by the image manifest check. +- Give each node a stable, unique public HTTPS origin. TLS must terminate at an operator-managed ingress/reverse proxy; the application listener itself is HTTP on port 3001. +- Configure at least two other distinct public HTTPS peer origins per node. The current mainnet peer client rejects private IPs and private DNS answers. Kubernetes-only ClusterIP/headless DNS peers are not accepted; never enable `WIKIDECK_ALLOW_PRIVATE_PEERS=1` to bypass the mainnet launch gate. +- Route each public peer hostname deterministically to exactly one node. A shared load-balanced hostname is not a stable peer identity. Separate per-peer Deployments/Services/Ingress routes are the simplest current shape; each node must exclude its own origin from its peer list. +- Give every node an exclusive persistent volume mounted at `/app/data`. Never share a ledger volume between pods. Agree the storage class, capacity, backup/restore procedure, resource limits, failure domains, and upgrade/reorg policy before enabling the launch approval. +- Configure the exact manifest `CHAIN_ID` as `WIKIDECK_MAINNET_LAUNCH`, and explicitly set `WIKIDECK_MAINNET_RISK_ACK=operator-accepts-unaudited-risk`. The latter accepts unaudited residual risk; it is not an audit or readiness check. + +## Pod hardening baseline + +Use a dedicated namespace and least-privilege service account (or disable token automount if no Kubernetes API access is needed), non-root execution matching the image's `node` user, read-only root filesystem, dropped Linux capabilities, `allowPrivilegeEscalation: false`, `seccompProfile: RuntimeDefault`, and a bounded writable `/tmp` volume. Use resource requests and limits based on measured RandomX/replay/sync behavior, not guesses. Readiness/liveness should use `/healthz`; allow a startup grace period for ledger replay and native engine initialization. Restrict ingress to the reviewed edge and egress to DNS, the configured public peers, and required Wikimedia endpoints. Add NetworkPolicy, TLS, image provenance/signature enforcement, monitoring, and tested encrypted backups through the cluster's established platform controls. + +Do not make the public origin or configured peers imply that peers are independent or that the network is secure. This software has no external audit, public bootstrap service, peer discovery, or demonstrated production capacity. + +## Values needed before manifests can be finalized + +Choose the genesis timestamp and image registry/digest; provide the namespace, ingress class and TLS/certificate mechanism, public DNS name per node, peer topology, storage class/size, resource budget, network-policy egress model, backup destination/retention, and desired availability/recovery behavior. Then calculate and publish the exact manifest and chain approval. Until those values and the peer topology are available, this checklist is the safe preparation artifact rather than a misleading runnable YAML template. diff --git a/docs/card-only-production-plan.md b/docs/card-only-production-plan.md index 2779be1..571f193 100755 --- a/docs/card-only-production-plan.md +++ b/docs/card-only-production-plan.md @@ -8,7 +8,7 @@ Wikideck's current product scope is **RandomX mining, collecting cards, and dire The nearest reasonable release target is a **publicly hosted, non-monetary testnet beta**. It must be labeled experimental and valueless. It is not a mainnet launch, a promise of ownership permanence, an investment product, or an independently secured network. Mining consumes compute, electricity, and time; no reward rate or profitability is promised. -Mainnet or valuable-card use is a separate, higher bar. It remains **NO-GO** until consensus, wallet, network, capacity, deployment, and independent-review gates below have evidence and named sign-off. The mainnet candidate's launch date and approval flags do not substitute for that evidence. +Mainnet or valuable-card use is a separate, higher bar. It remains **NO-GO** until consensus, wallet, network, capacity, deployment, and operator risk-acceptance gates below have evidence and named sign-off. The operator has chosen not to commission external audits; this is a conscious acceptance of additional residual risk, not evidence that the protocol or implementation is secure. ## Current starting point @@ -17,7 +17,7 @@ Mainnet or valuable-card use is a separate, higher bar. It remains **NO-GO** unt - Existing runtime volumes and historical backup packages may contain local financial journals or external database bindings. Removing source code does not delete or resolve those records; preserve them separately and do not claim new ledger-only backups include them. - The current network has no public bootnodes or automatic peer discovery. Peers must be configured by operators; containers on one host do not provide independent network security. - The inherited initial proof-of-work target accepts one in sixteen hashes, and the ten-block retarget is not production-calibrated. Nodes retain the DAG in memory, rebuild state roots across the NFT set, and revalidate stored proofs at startup. -- Browser-wallet encryption is implemented, but same-origin code can abuse an unlocked wallet; old plaintext copies, cross-browser recovery, and independent wallet review remain concerns. +- Browser-wallet encryption is implemented, but same-origin code can abuse an unlocked wallet; old plaintext copies and cross-browser recovery remain concerns. See the [mainnet launch limitations](mainnet-launch.md), [consensus reference](testnet-consensus.md), [wallet limitations](wallet-security.md), and [security review](security-review.md). Existing passing tests and local rehearsals are useful evidence, not production certification. @@ -33,22 +33,38 @@ See the [mainnet launch limitations](mainnet-launch.md), [consensus reference](t **Exit evidence:** scope owner approval is still required. Source/deployment removals are complete; API regression checks cover removed routes while preserving card trades; backup v2 and legacy-data refusal are covered; old paired backups remain portable. No active product docs promise sales or payments. -### Gate 1 — independent protocol and application review +### Gate 1 — internal protocol and application review · complete by operator decision -- Commission independent review of consensus serialization, signatures, state roots, fork choice, timestamp/retarget logic, peer message validation, RandomX integration/native boundary, and wallet signing/recovery. -- Test competing branches, deep reorgs, clock skew, eclipse/partition behavior, malformed traffic, mempool/resource exhaustion, and crash/restart recovery on disposable networks. -- Fix critical/high findings and add regression evidence. Publish the exact reviewed protocol manifest and residual risks; do not set review acknowledgements merely to pass startup gates. +**Operator decision (2026-10-28):** no external audit or independent review will be commissioned for this release. The product will proceed using internal code review, regression tests, local adversarial exercises, and explicit operator risk acceptance. This does not certify the software or establish that undiscovered critical defects are absent. -**Exit evidence:** review against the exact release candidate, issue dispositions, regression tests, and named reviewer sign-off. An internal code review or test count is not independent assurance. +Internal source-assisted review covered consensus serialization/validation, signatures, state commitments, fork choice, timestamps/retarget, peer URL/DNS/pagination/response handling, RandomX native boundary, wallet signing/recovery documentation and tests. -### Gate 2 — establish a credible network +Internal findings and dispositions: -- Measure expected and adversarial hashpower on intended hardware; quantify rewrite costs and concentration risk. Choose and review initial difficulty, retarget, timestamp, and stall-recovery behavior before freezing a mainnet identity. -- Design the bootstrap and peer-operations model: independently administered nodes, supported peer discovery or a documented trusted bootstrap list, upgrade coordination, and abuse/isolation response. -- Demonstrate actual connectivity and independent mining across failure domains. Peer URL count alone is not evidence that peers are online, independent, or secure. +- **Clock rollback could strand accepted SQLite history.** Startup replay applied the live future-skew admission bound to every persisted block. A block accepted at the allowed future edge could fail replay if the clock later moved backward. Startup now replays previously accepted SQLite history without reapplying that live-time bound. New blocks imported from legacy JSON retain a pinned import-time clock and imported-block cutoff; their future timestamps are checked on import and on later replays, so an untrusted legacy file cannot seed arbitrarily future-dated history. Regression tests cover both rollback recovery and repeated rejection of future-dated legacy data. +- **Invalid work reached full NFT-state materialization.** Block validation computed the state transition/root before checking the claimed and actual RandomX proof. Cheap commitment/signature/claimed-target checks now precede native proof verification, and the complete state transition/root is computed only after the native proof matches. A regression uses an instrumented state to assert that a wrong claimed proof is rejected before NFT-state enumeration. +- Added a deterministic 30-block versus 16-block competing-fork regression: equal cumulative work keeps the current tip, and a strictly higher-work branch then causes a 30-block reorganization while preserving both DAG branches. This is a local FakePow consensus-state test, not a multi-host security rehearsal. + +Current validation evidence: the Docker test image and TypeScript/Vite build succeeded; the complete offline suite passed **95/95** with the native RandomX HTTP integration; the packaged native engine's upstream known-vector self-test passed. Tests cover signatures/transaction replay, atomic trades, commitments, retarget/key boundaries, equal-work fork choice, reorg/requeue, malformed schemas, peer DNS/manifest/pagination/response rejection, mempool and RPC bounds, wallet backup crypto, and restart/revalidation. These checks are the selected assurance approach; they are not a security certification. + +**Residual risks carried forward:** no external auditor or independent reviewer will sign off. The candidate is not frozen. Multi-host eclipse/partition and clock-skew rehearsals, hostile populated-state load/reorg tests, and broad browser-wallet/XSS/recovery exercises remain open engineering work for Gates 2–5. The operator accepts proceeding without external audit; do not describe the result as audited or independently certified. + +**Exit evidence:** internal findings fixed with regression coverage; current build, offline suite and native known-vector results recorded; operator accepts the unaudited-risk boundary. Gate 1 is **complete under this explicitly reduced scope**. This completion is not external assurance, and its remaining multi-host/load/wallet exercises continue under the following gates. + +### Gate 2 — establish a credible network · in progress + +- **Mainnet candidate inspection (2026-10-28, read-only):** `wikideck-randomx-mainnet-1`, candidate chain ID `3ef36901f49d57127ebb0bf43625c7334e9b8ef817fd31953761723b5474ef6c`, genesis `72be7cdac8e625562bc8a49a82a406f41b96a6fde285c9961dceafdbaca8cd1d`, candidate genesis time 2027-01-01 00:00 UTC. The genesis time has not arrived; this is a candidate manifest, not an announced launch. No production node was started and no approval or data volume was created. +- **Repeat benchmark (2026-10-28):** same executable and container limits, 32 hashes measured 25.11 H/s warm (p50 39.13 ms, p95 48.18 ms), 883 ms cold initialization, and 642 ms for a key/cache switch. These two short samples are not a confidence interval and do not establish normal host variability. Both are verification-path hashes, not miner throughput, dedicated-host measurements, aggregate network hashpower, or a security budget. Do not extrapolate them to choose consensus parameters. +- The first bounded sample in the same container was 23.35 H/s warm (p50 41.09 ms, p95 55.81 ms), 796 ms cold initialization, and 594 ms for a key/cache switch. Together these two observations show run-to-run variation only; they are not intended-host miner measurements. +- **Bootstrap policy for the first beta:** use a fixed, operator-curated HTTPS peer allowlist supplied as `WIKIDECK_PEERS`; do not add DHT, automatic discovery, or peers learned from untrusted network messages. Treat configured peers as trust/bootstrap contacts only; each node independently validates every block and transaction. The current protocol provides no peer identity or independent-operation proof beyond the configured URL and TLS connection. +- **Local rehearsal status:** the complete offline suite's native RandomX HTTP integration syncs two separately started node processes over loopback, gossips a mined transfer, and verifies restart/replay. This is local functional evidence only. A disposable three-node Compose attempt on 2026-10-28 could not allocate a Docker bridge subnet because the configured address pools were exhausted; Compose failed before creating services or volumes. No multi-host/failure-domain rehearsal has been performed. +- **Mainnet peer configuration remains empty/unverified:** the repository has no operator-supplied public HTTPS origins, ownership/failure-domain evidence, or exercised TLS endpoints for the two required mainnet peers. The compose profile only forwards operator-provided peers and origin; placeholders are not launch infrastructure. +- For a multi-node rehearsal, use at least three separately administered nodes across distinct failure domains and network providers; record operator, host/region/provider, address/origin, chain ID, software digest, availability window, and which node supplies each bootstrap connection. Three containers or aliases on one host do not count as independent. +- Measure expected and adversarial hashpower on intended hardware; quantify rewrite costs and concentration risk. Decide whether this experimental beta retains the current easy target or whether a future mainnet identity needs different initial difficulty, retarget, timestamp, and stall-recovery rules. Do not alter a launched chain's consensus. +- Rehearse bootstrap with an empty node, peer loss/recovery, partition/rejoin, conflicting branches, stale/malicious configured peer, and independent mining. Record the observed tips, cumulative work, sync lag, and recovery time. Peer URL count alone is not evidence that peers are online or independent. - State the finality/reorganization limits honestly. There is no formal finality today; a confirmation count is not an absolute guarantee. -**Exit evidence:** reviewed launch manifest/genesis for mainnet (or explicit testnet-only beta decision), multi-host partition/reorg/stall rehearsal, measured hashpower assumptions, and an operator-owned peer/upgrade plan. +**Exit evidence:** explicit testnet-only beta decision (or separately approved mainnet candidate), documented bootstrap peer allowlist and ownership/failure domains, repeated intended-hardware hashrate data with variance, multi-host partition/reorg/stall rehearsal, a written risk/attack-cost estimate, and an operator-owned peer/upgrade/incident plan. Internal sign-off only; no external audit is planned. ### Gate 3 — demonstrate capacity and recovery limits @@ -62,11 +78,11 @@ See the [mainnet launch limitations](mainnet-launch.md), [consensus reference](t ### Gate 4 — wallet, trades, and user protection - Test create, lock, unlock, backup, restore in a fresh browser/profile, and recovery after app/browser upgrade across the supported browser matrix. Test signed transfer/trade review, stale offers, pending state, and reorg outcomes. -- Review same-origin script compromise, extensions, password entry, old plaintext-wallet migration, downloaded backup handling, and key-loss support. Decide whether production needs hardware/isolated signing; document residual risks if it does not. +- Perform an internal threat review of same-origin script compromise, extensions, password entry, old plaintext-wallet migration, downloaded backup handling, and key-loss support. Decide whether the beta accepts browser-only signing; document residual risks rather than implying external wallet assurance. - Publish experimental/no-value disclosures, mining resource risks, irreversible-transfer warnings, privacy/data-retention terms, Wikipedia text/image attribution and license handling, support contact, abuse-report path, and stop conditions. - Select and publish an appropriate project software license before public distribution. A Wikideck license does not replace Wikipedia or dependency licenses. -**Exit evidence:** independent wallet review, verified recovery drill, tested trade flows, reviewed participant disclosures, public support/abuse contacts, and license decision. +**Exit evidence:** internal wallet threat review, verified recovery drill, tested trade flows, reviewed participant disclosures, public support/abuse contacts, and license decision. ### Gate 5 — operate and release safely @@ -86,7 +102,7 @@ May be considered only after all applicable gates pass, the node remains on the ### Mainnet or valuable cards -Requires all gates plus independent consensus/economic-security review, calibrated and frozen consensus parameters, a credible independent peer/miner topology, reviewed wallet protections, sustained capacity and adversarial evidence, and explicit governance/upgrade and incident procedures. Mainnet activation is a separate authorization. Until then, retain **NO-GO**. +Requires all gates plus measured and operator-accepted consensus/economic risks, calibrated and frozen consensus parameters, a credible peer/miner topology, reviewed wallet protections, sustained capacity and adversarial evidence, and explicit governance/upgrade and incident procedures. External audit is intentionally not a requirement under the operator's decision, so residual risk remains higher and must be explicitly accepted before any mainnet activation. Until then, retain **NO-GO**. ### Markets and real money diff --git a/docs/consensus-calibration.md b/docs/consensus-calibration.md index 039f294..ca1e403 100755 --- a/docs/consensus-calibration.md +++ b/docs/consensus-calibration.md @@ -1,6 +1,6 @@ # Consensus calibration and adversarial analysis — stage 3 -**Decision remains NO-GO.** This stage supplies reproducible offline tools and bounded measurements, not new launch parameters, an independent audit or an operational network. Consensus, initial target, genesis, and chain identity are unchanged. +**Decision remains NO-GO.** This stage supplies reproducible offline tools and bounded measurements, not new launch parameters or an operational network. Consensus, initial target, genesis, and chain identity are unchanged. ## Tools and safety boundaries @@ -56,7 +56,7 @@ Before production calibration can be approved: - Benchmark the exact final native/image build on multiple intended independent miner/validator hosts; record CPU model, operating mode, effective quotas, competing load, cold/warm/cache-switch distributions and batch-miner throughput. Use repeated runs and documented confidence/variance, not this single sample. - Establish credible aggregate honest hashrate, launch ramp/surge/drop ranges and attack/rewrite cost assumptions; independently review target choice and the inherited ten-block/clamped endpoint retarget, including gaps across windows and timestamp attacks. - Add stochastic mining/partition/clock/adaptive-hashpower models and sustained multi-host rehearsals with valid reference proofs, full state commitments, mempool/reorg persistence, networking and realistic resource pressure. -- Freeze reviewed rules and actual genesis date with a new identity where required. Publish the manifest/artifact hashes and obtain independent review and explicit operator sign-off. Do not patch an active chain's rules in place. +- Freeze the selected rules and actual genesis date with a new identity where required. Publish the manifest/artifact hashes and record internal findings plus explicit operator risk acceptance. Do not patch an active chain's rules in place. - Document reorganization and confirmation limitations honestly; no finite confirmation count is absolute finality on this unbootstrapped PoW chain. See [security review](security-review.md), [launch evidence register](operator-launch.md) and the read-only preflight. The calibration blocker remains open. diff --git a/docs/mainnet-launch.md b/docs/mainnet-launch.md index d6b6286..83aea4b 100755 --- a/docs/mainnet-launch.md +++ b/docs/mainnet-launch.md @@ -1,50 +1,55 @@ -# Gated mainnet candidate +# Mainnet-first, gated candidate -This repository has a **separate mainnet candidate profile**, not an audited or launched production network. Shipping code does not establish independent miners, economic security, or an operational public network. Market and payment features have been removed from the card-only product. +The repository defaults to a **mainnet candidate**, not an audited or launched production network. Shipping code does not establish independent miners, economic security, or an operational public network. Market and payment features have been removed from the card-only product. **Current production decision: NO-GO.** See the [2026-10-20 security review](security-review.md) and [operator evidence register and launch procedure](operator-launch.md). The read-only `launch:preflight` package script (or node entry-point `--launch-preflight`) reports local gates and unresolved blockers without starting a node or setting approvals. It deliberately exits nonzero while production readiness is blocked. ## What is implemented -| Property | Testnet default | Mainnet candidate | +| Property | Mainnet-first default | Explicit development fixture | | --- | --- | --- | -| Selection | `WIKIDECK_NETWORK=testnet` (or unset) | `WIKIDECK_NETWORK=mainnet` | -| Network ID | `wikideck-randomx-testnet-6` | `wikideck-randomx-mainnet-1` | -| Protocol | Existing version 6 | Version 6 under a distinct chain identity | -| Genesis timestamp | Unchanged | 2027-01-01 00:00 UTC, **candidate only, not a promised launch** | -| Ledger subdirectory | testnet | mainnet | -| Browser wallet | Existing testnet store, unchanged | Separate mainnet store | +| Selection | `WIKIDECK_NETWORK=mainnet` (or unset) | `WIKIDECK_NETWORK=testnet` | +| Network ID | `wikideck-randomx-mainnet-1` | `wikideck-randomx-testnet-6` | +| Protocol | Version 6 | Existing fixed local testnet version 6 | +| Genesis timestamp | 2027-01-01 00:00 UTC by default; deployment may choose another timestamp before building/freezing | Fixed at 2026-10-19 00:00 UTC | +| Ledger directory | mainnet | testnet | +| Browser wallet | IndexedDB name derived from exact chain ID | Separate chain identity | +| New backup | v2 header authenticates exact chain ID | Same v2 format; legacy v1 is accepted only on the original testnet | Both profiles use real RandomX validation, cumulative-work branch selection, the 15-minute target, mint maturity, signed NFT transfers, atomic card trades, and SQLite persistence. The mainnet candidate has no premine, token migration, hidden checkpoint, or fake-PoW option. Changing the network identifier and candidate genesis derives distinct chain/genesis IDs, RandomX initial keys, signature domains, and consensus manifest checks. Existing testnet values and data remain unchanged. -**Testnet cards and backups do not migrate.** Browser storage is separate, backup network headers are authenticated and checked, peers reject mismatched manifests, and transactions are checked against the active chain. The selected profile is pinned at startup/browser build, never silently adopted from an RPC response. +**Cards and backups do not migrate across chain identities.** Browser storage and backup headers are bound to the exact chain ID; peers reject mismatched manifests, and transactions are checked against the active chain. The selected profile and genesis are pinned at startup/browser build, never silently adopted from an RPC response. The original fixed-testnet v1 backups remain supported only on that testnet. ## Inspect without launching The node entry point accepts `--network-manifest`. With `WIKIDECK_NETWORK=mainnet` set in the process environment, this prints the candidate network/chain/genesis/timestamp and exits **before** opening databases, starting a RandomX engine, listening, or contacting peers. It does not require activation credentials or approval and does not launch anything. -Browser builds select `VITE_WIKIDECK_NETWORK=mainnet`; server/miner processes select `WIKIDECK_NETWORK=mainnet`. These must match. Docker's `WIKIDECK_NETWORK` **build argument** sets the browser profile; a runtime variable cannot alter an already compiled UI. A mismatched UI rejects the node network instead of signing for it. The mainnet Compose definition supplies both the build and runtime selections. +Browser builds select `VITE_WIKIDECK_NETWORK=mainnet`; server/miner processes select `WIKIDECK_NETWORK=mainnet`. These must match. `WIKIDECK_GENESIS_TIME` is also part of the chain identity. Docker's network/genesis **build arguments** pin the browser and immutable image manifest; a runtime variable cannot alter an already compiled UI. To choose another genesis, set it for the image build and runtime together, publish the resulting manifest, then use that immutable image and exact timestamp for every node and browser. A runtime-only genesis override fails closed. A mismatched UI rejects the node rather than signing for it. ## Explicit launch gates -[compose.mainnet.yaml](../compose.mainnet.yaml) is an opt-in Compose profile, uses a separate named volume, binds only loopback for an external HTTPS reverse proxy, and does **not** auto-restart a failed candidate. It has no default peers, approval, or public origin. It is not started by the default Compose definitions. **No mainnet nodes have been started by this change.** +[compose.yaml](../compose.yaml) and [compose.mainnet.yaml](../compose.mainnet.yaml) are mainnet-first definitions, use separate named volumes, bind only loopback for an external HTTPS reverse proxy, and do **not** auto-restart a failed candidate. They have no default peers, approval, or public origin. The default service therefore exits until the operator supplies real deployment values. The testnet Docker fixture is separate and explicit. **This code change does not establish or certify a public mainnet.** Starting the candidate node or native miner requires all of: 1. `WIKIDECK_MAINNET_LAUNCH` equals the exact candidate chain ID printed by the manifest command. -2. `WIKIDECK_MAINNET_REVIEW_ACK=independent-review-complete` records the operator's review attestation. This is **not cryptographic proof of an audit**, and the manifest still honestly reports `audited: false`. -3. The candidate genesis timestamp has arrived. If review changes the timestamp or consensus manifest before launch, the chain ID also changes and the old approval is invalidated. Freeze and publish the final manifest only after review. +2. `WIKIDECK_MAINNET_RISK_ACK=operator-accepts-unaudited-risk` records the operator's explicit acceptance that no external audit is planned and residual risks remain. This is not a safety certification; the manifest honestly reports `audited: false`. +3. The candidate genesis timestamp has arrived. If the operator changes the timestamp or consensus manifest before launch, the chain ID also changes and the old approval is invalidated. Freeze and publish the final manifest before launch. 4. An HTTPS `PUBLIC_ORIGIN`, at least two distinct configured HTTPS peer origins, and no private-peer bypass. Configuration count cannot prove the peers are online, independent, or sufficiently distributed; verify that operationally. Existing peer DNS/origin controls still apply. -Unknown profile names fail closed. A direct import of the HTTP entry point is also guarded. Library-level manifest/consensus/storage inspection remains possible for tests and review; activation gates are accident prevention, not a security boundary against someone who edits the source. + +For Kubernetes, the current peer implementation requires HTTPS origins that resolve to public addresses; it rejects private cluster DNS/IPs for mainnet. The node serves HTTP internally and needs a separately configured TLS ingress/reverse proxy. Every node needs a stable, unique public HTTPS origin and at least two distinct peer origins. A default ClusterIP/headless Service alone cannot satisfy these rules, and a load-balanced ingress shared by several pods is not a stable per-node peer identity. Do not set the private-peer bypass to work around this; use public per-node HTTPS endpoints or first review a separate authenticated private-peering design that preserves the public independence gate. No cluster-specific manifests are included because ingress class, TLS/certificate management, storage class/size, resource capacity, and stable peer DNS were not provided. + +See the [Kubernetes mainnet preparation checklist](../deploy/kubernetes/README.md) for the deployment contract and the values needed before manifests can be finalized. +Unknown profile names fail closed. A direct import of the HTTP entry point is also guarded. Library-level manifest/consensus/storage inspection remains possible for tests and review; activation gates are accident prevention and operator risk acceptance, not a security boundary against someone who edits the source. ## Required before an actual production launch -- **Independent review:** protocol/cryptography, signatures and wallet lifecycle, RandomX integration, difficulty/time/retarget attacks, state commitments, fork choice, network message validation and denial-of-service limits. Publish findings, fixes and a versioned final manifest. +- **Internal readiness review:** track code findings and regression evidence in-repository. No external audit is planned; the operator accepts the additional risk and must not describe the candidate as audited or certified. - **Security model:** quantify hashpower, chain-rewrite cost and majority attacks. The inherited easy initial target and ten-block retarget are **not production-calibrated**. Choose reviewed launch difficulty/retarget behavior and test start-up/stall/recovery scenarios. Independent mining participation and sufficient hashpower are not provided by running multiple containers on one host. - **Adversarial rehearsal:** sustained multi-host simulations, partitions/eclipses, competing branches, deep reorganizations, clock skew, bad peers, load/mempool saturation, corrupted state and restart recovery. Test the candidate rules with no valuable assets. - **Operations:** independently administered public HTTPS nodes and miners across failure domains, pinned release artifacts and dependencies, firewall/reverse proxy/rate-limit policies, bounded storage and sync strategy, metrics, alerts, rotation and emergency-response procedures. - **Recovery:** verified offline wallet recovery, consistent ledger snapshots, full replay/revalidation, documented incident and fork handling. No silent ledger reset or reuse of testnet data. -- **Launch governance:** select the actual genesis date, freeze the reviewed identity/configuration, publish binaries and configuration hashes, agree peer/miner readiness and upgrade policy, and explicitly authorize launch. No operator should attest review merely to bypass the gates. +- **Launch governance:** select the actual genesis date, freeze the identity/configuration, publish binaries and configuration hashes, agree peer/miner readiness and upgrade policy, and explicitly record the operator's risk acceptance. Do not treat the flag as proof of safety or peer readiness. - **User and legal review:** no monetary value or security is promised. NFT rights do not imply article/image copyright ownership. Publish experimental-use, privacy, support, and abuse-report terms appropriate to the release. ## Still not production-ready diff --git a/docs/operator-launch.md b/docs/operator-launch.md index 9936e1f..5357388 100755 --- a/docs/operator-launch.md +++ b/docs/operator-launch.md @@ -2,13 +2,13 @@ The [card-only production readiness plan](card-only-production-plan.md) defines the product scope and release gates. The supported product is mining, collecting, and direct card-for-card trades. Market, custody, and payment source has been removed. **Current decision: HOLD / NO-GO for mainnet, valuable assets, or public exposure until the relevant evidence below is reviewed.** -A successful build, local container startup, peer URL count, genesis timestamp, or configured approval flag is not production evidence. The read-only launch preflight reports local blockers; it is not an independent audit or approval. +A successful build, local container startup, peer URL count, genesis timestamp, or configured approval flag is not proof of network security. The read-only launch preflight reports local blockers; it does not certify the release. The operator has chosen not to commission external audits and accepts the corresponding residual risk. ## Safe inspection Use Node.js 24 and a clean, reviewed checkout. For mainnet assessment, select `WIKIDECK_NETWORK=mainnet` and run `launch:preflight`. Use `--network-manifest` for chain identity inspection. These commands do not start a node, create a ledger, start RandomX, or contact peers. -Mainnet startup is gated by a chain-specific approval, a review acknowledgement, the candidate genesis time, HTTPS origin, and multiple configured HTTPS peers. These are accident-prevention checks only; they do not prove that review occurred, peers are online/independent, or a network is secure. Keep deployment and release permissions restricted. +Mainnet startup is gated by a chain-specific approval, explicit unaudited-risk acceptance, the candidate genesis time, HTTPS origin, and multiple configured HTTPS peers. These are accident-prevention checks only; they do not prove peers are online/independent or that a network is secure. Keep deployment and release permissions restricted. ## Evidence required before a public non-monetary testnet beta @@ -26,7 +26,7 @@ If these conditions cannot be verified on a self-hosted site, do not expose it p ## Mainnet and valuable-card blockers -Mainnet or valuable-card use requires the beta evidence plus independent protocol/application review, measured and reviewed consensus parameters, adversarial multi-host partition/reorg/hashpower testing, a credible bootstrap and independent-peer/miner plan, production capacity evidence, and explicit governance/upgrade and incident procedures. The current initial target is deliberately easy and the retarget is not production-calibrated. Nodes retain the DAG in memory and replay proofs at startup. There is no formal finality or automatic peer discovery. Keep mainnet **NO-GO** until these gaps are independently reviewed and signed off. +Mainnet or valuable-card use requires the beta evidence plus internally reviewed and measured consensus parameters, adversarial multi-host partition/reorg/hashpower testing, a credible bootstrap and independent-peer/miner plan, production capacity evidence, and explicit governance/upgrade and incident procedures. External audit is not planned; the operator must record acceptance of this extra risk. The current initial target is deliberately easy and the retarget is not production-calibrated. Nodes retain the DAG in memory and replay proofs at startup. There is no formal finality or automatic peer discovery. Keep mainnet **NO-GO** until the remaining network and operational evidence is recorded and the operator explicitly accepts the residual risks. ## Hold-point register @@ -34,7 +34,7 @@ Record owner, exact release/manifest, evidence location and hash, test/rehearsal | Hold point | Required evidence | Current status | | --- | --- | --- | -| Independent protocol/application review | Review against the exact release; critical/high findings fixed and retested | Missing | +| Internal protocol/application review | Findings documented against the release; fixes have regression coverage; operator records unaudited-risk acceptance | Internal review and regression tests recorded; no external audit planned | | Consensus launch design | Final manifest; measured starting target/hashpower; timestamp, retarget, partition, and reorg analysis | Missing | | Node availability | Realistic long-chain and hostile-traffic capacity report with explicit limits | Missing | | Production wallet | Same-origin threat model, user confirmation, supported-browser lifecycle and offline recovery drill | Unverified | @@ -47,13 +47,13 @@ Record owner, exact release/manifest, evidence location and hash, test/rehearsal ## Freeze and authorize -1. Fix critical findings in a separately reviewed release; do not change consensus rules under a launched chain ID. +1. Fix known critical code findings in a new release and add regression coverage; do not change consensus rules under a launched chain ID. This is internal engineering, not external audit. 2. Freeze the reviewed genesis/manifest, exact build/runtime profile, image digest, peer origins, and artifact hashes. 3. Rehearse initial sync, independent mining, partitions/reconnects, invalid traffic, disk pressure, restart, and isolated full restore. Do not delete production data or weaken rules to pass a drill. 4. Verify DNS/TLS, proxy forwarded-IP handling, no direct backend access, permissions, resource capacity, and monitoring on intended hosts. `/healthz` is liveness only. -5. Record a go/no-go with operator/reviewer names, evidence, known residual risks, change window, recovery objectives, and stop conditions in the controlled operations system. +5. Record a go/no-go with operator name, evidence, known residual risks, change window, recovery objectives, and stop conditions in the controlled operations system. -Do not set review acknowledgements merely to bypass gates. This internal code work is not the independent review required for launch. +Do not set the risk acknowledgement merely to bypass gates. It records acceptance of known risks; it does not attest that an audit occurred or make the system secure. ## Stop conditions diff --git a/docs/security-review.md b/docs/security-review.md index db8bb79..a4ef6ca 100755 --- a/docs/security-review.md +++ b/docs/security-review.md @@ -2,7 +2,7 @@ ## Decision: NO-GO for public production or valuable assets -This is an internal source-assisted readiness review, not an independent security audit, penetration test, formal consensus proof, or production certification. The card-only product consists of RandomX mining, wallets, collections, transfers, and direct atomic card trades. Market, custody, and payment components have been removed from the supported source tree; no real-money feature is part of this release. +This is an internal source-assisted readiness review, not a penetration test, formal consensus proof, or production certification. The operator has chosen not to commission external audits and accepts that residual risk. The card-only product consists of RandomX mining, wallets, collections, transfers, and direct atomic card trades. Market, custody, and payment components have been removed from the supported source tree; no real-money feature is part of this release. A limited, non-monetary testnet beta may be considered only after the release-specific operational, wallet, capacity, recovery, and review gates in the [card-only production plan](card-only-production-plan.md) are met. Mainnet or valuable-card use remains **NO-GO**. @@ -10,14 +10,14 @@ A limited, non-monetary testnet beta may be considered only after the release-sp | Finding | Risk | Required disposition | | --- | --- | --- | -| Consensus/economic security | Current initial proof-of-work target is deliberately easy and the ten-block retarget is not production-calibrated. Hashpower concentration, timestamp/retarget manipulation, eclipse, censorship, and reorganization costs have not received independent review. RandomX use does not inherit Monero's security. | Independent consensus/economic review; representative hashpower measurements; adversarial multi-host clock, partition, stall, fork, and reorg simulations; freeze reviewed launch parameters and chain identity. | +| Consensus/economic security | Current initial proof-of-work target is deliberately easy and the ten-block retarget is not production-calibrated. Hashpower concentration, timestamp/retarget manipulation, eclipse, censorship, and reorganization costs have not been independently measured. RandomX use does not inherit Monero's security. | Measure representative hashpower; run multi-host clock, partition, stall, fork, and reorg simulations; document operator-accepted risk and freeze parameters/identity before launch. | | Node availability and scale | The DAG remains in memory, state-root work visits the NFT set, and startup revalidates stored proofs. Work, RAM, disk, and recovery time grow with history. | Repeated long-chain and hostile-traffic tests on intended hardware; define and validate latency, resource, storage, and recovery limits; establish an archival/capacity strategy. | | Wallet/key protection | Encrypted local storage helps while locked, but a compromised same-origin page, extension, browser, or OS can abuse an unlocked signer. Old plaintext copies and cross-browser recovery require careful handling. | Independent wallet review; supported-browser migration/lock/sign/backup/restore drills; document residual compromise and key-loss risks. Decide whether isolated/hardware signing is required. | | Deployment and operations | The real TLS/proxy/firewall topology, peer/miner independence, off-host recovery, alert delivery, and on-call response have not been verified. A liveness response is not readiness. | Verify intended hosts and external edge; test alert routes and incident procedures; encrypt off-host backups and complete an isolated restore/replay with measured recovery objectives. | | Release supply chain | A successful build or dependency advisory check does not establish artifact integrity or native/container safety. | Freeze base/dependency/native versions and image digest; produce an SBOM, scans, build provenance/signature, and restricted release process for the exact artifact. | | Governance and user terms | No production operator/reviewer sign-off, public support/abuse path, or published project software license is established. | Name accountable decision makers; publish license, support, privacy, experimental/no-value disclosures, abuse reporting, upgrade policy, and stop conditions. | -These are readiness gaps, not claims that each item is an exploited vulnerability. Local tests and rehearsals are useful but do not close independent-review or intended-host evidence requirements. +These are readiness gaps, not claims that each item is an exploited vulnerability. Local tests and rehearsals are useful, but they do not establish security or verify the intended production host. ## Implemented groundwork (not certification) @@ -28,4 +28,4 @@ These are readiness gaps, not claims that each item is an exploited vulnerabilit ## Review evidence and limits -The exact release candidate must be rebuilt and fully retested after scope cleanup. No claims are made here about the user's production host, public peer topology, Internet-facing penetration tests, independent native-code review, alert delivery, off-host recovery, or mainnet security. Do not expose a public node or use valuable assets based solely on a successful test suite or container startup. +The exact release candidate must be rebuilt and fully retested after scope cleanup. No claims are made here about the user's production host, public peer topology, Internet-facing testing, native-code assurance, alert delivery, off-host recovery, or mainnet security. External audits are not planned; retain the NO-GO for mainnet/valuable assets until the remaining network, deployment, and recovery evidence is complete and the operator records informed risk acceptance. A successful test suite or container startup alone is insufficient. diff --git a/docs/testnet-consensus.md b/docs/testnet-consensus.md index f69e964..736d63c 100644 --- a/docs/testnet-consensus.md +++ b/docs/testnet-consensus.md @@ -91,6 +91,6 @@ Sync polls every **5 seconds**, checks network/chain ID, imports at most **32** | `GET /p2p/status`, `/p2p/blocks?offset=0`, `/p2p/mempool` | Manifest/size/tip, 32-block inventory pages, pending transactions. | | `POST /p2p/block`, `/p2p/transaction` | Same validation as local block/transaction submission; transaction endpoint accepts a transfer or atomic trade. | -POSTs require JSON, enforce supplied browser origins and signatures where applicable; peers without an Origin header are not authenticated by this check. HTTP parsing is capped at 68 KiB; API/P2P rate limits are 300/minute and block/transaction/trade submissions additionally 30/minute. There are no consensus fees, peer authentication, or economic spam deterrents. Same-origin browser RPC trusts the node; it does not independently verify these commitments. Deploy no funds: majority-hashpower, eclipse, censorship, reorg and resource-exhaustion risks require independent audits and adversarial testing before any broader launch. +POSTs require JSON, enforce supplied browser origins and signatures where applicable; peers without an Origin header are not authenticated by this check. HTTP parsing is capped at 68 KiB; API/P2P rate limits are 300/minute and block/transaction/trade submissions additionally 30/minute. There are no consensus fees, peer authentication, or economic spam deterrents. Same-origin browser RPC trusts the node; it does not independently verify these commitments. Deploy no valuable assets: majority-hashpower, eclipse, censorship, reorg and resource-exhaustion risks remain and are not externally audited under the operator's current policy. Testnet storage and chain identities above remain unchanged. The [gated mainnet candidate](mainnet-launch.md) selects separate chain/signature domains, storage, lock and wallet identities; it is not a running or certified production network. diff --git a/docs/wallet-security.md b/docs/wallet-security.md index 2dfb01d..baf24a9 100755 --- a/docs/wallet-security.md +++ b/docs/wallet-security.md @@ -42,4 +42,4 @@ Node/WebCrypto storage-boundary tests cover encrypted record-only persistence, e Real browser smoke checks on a disposable loopback origin passed create → lock → unlock and reload → locked. IndexedDB inspection confirmed the vault wrapper/ciphertext and absence of a top-level private key/password without retrieving private material. Tests use ephemeral test credentials only. Final Node 24 TypeScript/Vite build passed; the complete suite passed **86 tests, 0 failed, 0 skipped**, including real RandomX HTTP integration and expanded wallet storage/lifecycle assertions. -**Production wallet review remains open.** At-rest encryption reduces profile-theft exposure when locked but cannot protect an unlocked page or password entry from XSS, a malicious release, privileged extensions or a compromised browser/OS. The in-memory key intentionally remains extractable to support existing backup export. This is not hardware-isolated signing, a browser-extension wallet, or an independent audit. Multi-browser/background/cross-tab races and destructive crash/restore drills need broader coverage; no independent assurance or formal crypto verification is claimed. Do not use valuable assets merely because local encryption exists. +**Wallet risks remain accepted but unresolved.** At-rest encryption reduces profile-theft exposure when locked but cannot protect an unlocked page or password entry from XSS, a malicious release, privileged extensions or a compromised browser/OS. The in-memory key intentionally remains extractable to support existing backup export. This is not hardware-isolated signing or a browser-extension wallet. External wallet audits are not planned; multi-browser/background/cross-tab races and destructive crash/restore drills remain internal engineering work. Do not use valuable assets merely because local encryption exists. diff --git a/index.html b/index.html index fb7bb16..71289fd 100644 --- a/index.html +++ b/index.html @@ -4,8 +4,8 @@ - -
Wikideck and Monero use RandomX, an algorithm designed to resist specialized ASICs and keep general-purpose CPUs competitive. That can make mining more accessible—not make every machine equally powerful or promise rewards. Each accepted Wikideck block earns its miner a distinct illustrated Wikipedia card. Wikideck is its own independent network.
The miner selects a random illustrated English Wikipedia article. The same article can appear again; each card keeps its own mint-time statistics.
wikideck-randomx using the repository’s native build instructions.<backup.json> with your local file path (quote paths with spaces), then run:{nativeCommand}Node: {window.location.origin}. The command connects to this node; use HTTPS for remote nodes. Password entry stays local—never put it in the command. It defaults to one worker and at most one block. Ctrl+C stops the native miner; closing this page does not.
The miner selects a random illustrated English Wikipedia article. The same article can appear again; each card keeps its own mint-time statistics.
wikideck-randomx using the repository’s native build instructions.<backup.json> with your local file path (quote paths with spaces), then run:{nativeCommand}Node: {window.location.origin}. The command connects to this node; use HTTPS for remote nodes. Password entry stays local—never put it in the command. It defaults to one worker and at most one block. Ctrl+C stops the native miner; closing this page does not.
Run the native RandomX miner to compete for blocks. Each accepted block rewards its miner with a distinct illustrated Wikipedia card.
{view === 'My collection' ? 'Confirmed native NFT ownership. Pending transfers stay here until mined.' : snapshot?.blocks.length ? 'Recent native NFTs on this node’s canonical testnet chain.' : 'Sample previews only; mined NFTs use random Wikipedia pages with pictures. The same page may be minted more than once.'}
{view === 'My collection' ? 'Confirmed native NFT ownership. Pending transfers stay here until mined.' : snapshot?.blocks.length ? 'Recent native NFTs on this node’s canonical chain.' : 'Sample previews only; mined NFTs use random Wikipedia pages with pictures. The same page may be minted more than once.'}
{query || category !== 'All cards' ? 'Try another search or explore a different category.' : 'Use the native miner or receive a mined transfer on this chain. Restore a backup to access an existing wallet.'}
Native NFT mints, RandomX proofs, and mined ownership transfers.
Sovereign testnet with independently validating peers and cumulative-work chain selection. This network is unbootstrapped, not a public mainnet. Zero peers means an isolated node, not a connected network. Canonical ownership can change during a reorganization.
Sovereign network with independently validating peers and cumulative-work chain selection. This network is experimental and may be unbootstrapped. Zero peers means an isolated node, not a connected network. Canonical ownership can change during a reorganization.
| Block / confirmations | Discovery | Block ID / NFT token ID | Confirmed owner | RandomX proof / rarity |
|---|---|---|---|---|
| {snapshot.blocks.length - b.height + 1} confirmations | {b.article.title}Wikipedia #{b.article.pageId} | Block {short(b.hash)}NFT {short(b.tokenId)} | {short(testnetOwnerOf(snapshot, b.tokenId) ?? '')} | {short(b.powHash)}{rarity(b.powHash)} |
No NFT blocks loaded yet. Mine a block to earn the next Wikipedia card.
Your encrypted local wallet controls your cards. Restore a backup to use the same identity in another browser profile. Confirmed ownership follows the canonical chain.
Transfers remain pending until confirmed, and a chain reorganization can change confirmed ownership. Looking up a public wallet address reveals its confirmed holdings. Keep your encrypted backup and password separately.
Both players sign the same card list; the complete swap is applied together when mined or rejected. Offers are shared between players, not sold or submitted as listings.
The app rechecks ownership, maturity, sequences, and pending activity before submitting. A trade stays pending until mined; re-check the recipient and cards before signing.
Cards do not grant rights to Wikipedia text or images. Check each card’s attribution and licenses. This is an experimental testnet; cards have no promised monetary value.
Cards do not grant rights to Wikipedia text or images. Check each card’s attribution and licenses. This is an experimental {NETWORK_LABEL.toLowerCase()} network; cards have no promised monetary value.
No server login. This recoverable wallet controls native NFTs through local signatures. It is separate from the original demo wallet.
Use the recipient’s 64-character testnet wallet address on this same chain. Signing submits a pending transaction; it does not immediately transfer ownership.
Transfers take effect only when mined into the canonical chain. Once confirmed, there is no undo button or recovery for a wrong address. Mints require two subsequent blocks at inclusion height; only one pending transfer per NFT is allowed.
{!rpcAvailable ? 'RPC unavailable. Reconnect before signing.' : transferDisabledReason}
}{transferError &&{transferError}
}> + : dialog === 'wallet' ? <>No server login. This recoverable wallet controls native NFTs through local signatures. It is separate from the original demo wallet.
Use the recipient’s 64-character wallet receive address on this same network. Signing submits a pending transaction; it does not immediately transfer ownership.
Transfers take effect only when mined into the canonical chain. Once confirmed, there is no undo button or recovery for a wrong address. Mints require two subsequent blocks at inclusion height; only one pending transfer per NFT is allowed.
{!rpcAvailable ? 'RPC unavailable. Reconnect before signing.' : transferDisabledReason}
}{transferError &&{transferError}
}> : selected && <>{selected.article.extract}
{confirmations} canonical confirmations{!rpcAvailable ? ' · last known state' : ''}. {selectedBlock ? `Confirmed owner: ${selectedOwner}` : 'This mint is not on the loaded canonical chain.'}
{pending &&Transfer pending mining · confirmed owner unchanged.
}>}{selected.article.source === 'live' ? 'Pinned text by Wikipedia contributors, CC BY-SA 4.0. Excerpt shortened for card display.' : 'Original fixed starter summary, linked to the real Wikipedia article; no live revision captured.'} Stats are game values, not encyclopedia facts. NFT ownership grants no rights to article text or images.
{selected.block && selectedOwner === wallet?.address && <>{transferDisabledReason &&{transferDisabledReason}
}>}Backup encryption and recovery happen locally. No private key, backup file, or password is transmitted to a server +
Backups are bound to this exact chain ID; a backup for a different genesis cannot be restored here. Encryption and recovery happen locally. No private key, backup file, or password is transmitted to a server by this panel. Public addresses, public keys and signatures may be shared during normal wallet use.
Forgotten backup passwords cannot be reset or recovered. Keep the encrypted file and a strong, unique password safe and separate. Anyone with both can control this wallet. Downloading does not guarantee the file was saved.
diff --git a/src/wallet.ts b/src/wallet.ts index a41c8b9..e0e3a5f 100644 --- a/src/wallet.ts +++ b/src/wallet.ts @@ -1,5 +1,5 @@ import { decryptWallet, encryptWallet, type WalletBackup } from '../shared/wallet-backup.ts'; -import { IS_MAINNET } from '../shared/network.ts'; +import { expectedChainIdentity } from '../shared/chain-identity.ts'; export type Wallet = { publicKey: string; address: string }; type Keys = Awaited