Updated for new version

This commit is contained in:
2026-10-29 11:44:17 -04:00
parent d038fe3bab
commit 885f4160a7
11 changed files with 199 additions and 56 deletions
+60 -42
View File
@@ -5,13 +5,16 @@ Deploy the Wikideck production container to an existing Kubernetes cluster using
volume claim, a dedicated ServiceAccount, a ClusterIP Service, and a NetworkPolicy.
An HTTPS Ingress is optional and disabled by default.
**Wikideck is an experimental RandomX testnet, not a production-ready public
mainnet.** The updated application has independent validating nodes, fork choice,
native NFTs, and encrypted wallet backup/recovery. It supplies no public bootnodes
or deployed public network. Use test wallets and no valuable assets. This role
**Wikideck is mainnet-first in code but remains an experimental, launch-gated
candidate; the current production decision is NO-GO.** No public network,
bootnodes, independent audit, or production readiness is established. The
application includes validating nodes, fork choice, native NFTs, and encrypted
local-wallet backup/recovery. Use test wallets and no valuable assets. This role
deploys a **validator**, never a miner: mining is an explicitly started native CLI
process outside the browser. Private keys, backups and passwords must stay off
validator pods and out of Ansible variables.
validator pods and out of Ansible variables. See the upstream
[mainnet launch gates](https://github.com/ericomeehan/wikideck/blob/main/docs/mainnet-launch.md)
and [operations/recovery guidance](https://github.com/ericomeehan/wikideck/blob/main/docs/operations-recovery.md).
## Requirements
@@ -24,13 +27,16 @@ validator pods and out of Ansible variables.
- Kubeconfig access to create/update/read the resources in the target namespace,
delete the role's Ingress/NetworkPolicy when disabled, and optionally create a
Namespace. No cluster-admin access or in-cluster workload RBAC is needed.
- **A published image built from Wikideck's production Dockerfile.** There is no
- **A published, immutable image built from Wikideck's production Dockerfile.** There is no
assumed official registry image. Set `wikideck_image` to your actual tagged or
digest-pinned image. The role does not build/push images or install a cluster.
preferably digest-pinned image. The role does not build/push images or install a cluster.
Rebuild from the current source: the image must include Node 24, libstdc++, and
the native RandomX executable, with `RANDOMX_BINARY` set by the image. An old
browser-mining image is incompatible. Build and verify for your worker node
architecture; do not assume a locally built image is multi-architecture.
architecture; do not assume a locally built image is multi-architecture. The
production Dockerfile defaults to mainnet and pins its profile/genesis into the
image manifest; runtime settings cannot change that identity. Testnet is an
explicit development fixture, not a public deployment profile.
- For ingress: an ingress controller, DNS, and a trusted TLS Secret in the app
namespace. Alternatively, configure cert-manager annotations and an existing
issuer. The role does not install cert-manager or create an issuer.
@@ -43,30 +49,23 @@ environment. Windows controllers must run Ansible through WSL or Linux container
Install this checkout into your playbook's role search path as `roles/wikideck`,
or install it using an Ansible Galaxy Git role requirement named `wikideck`.
[examples/playbook.yml](examples/playbook.yml) shows an HTTPS deployment with
ingress-nginx and cert-manager. Replace the image, hostname, peer URLs, class,
issuer, and controller namespace with real values before running it.
```yaml
- name: Deploy a cluster-internal Wikideck instance
hosts: localhost
connection: local
gather_facts: false
roles:
- role: wikideck
vars:
wikideck_image: registry.example.com/games/wikideck:1.0.0
```
[examples/playbook.yml](examples/playbook.yml) is the gated HTTPS deployment
example with ingress-nginx and cert-manager. It requires an approved image
digest, the image's verified manifest/genesis, launch gates, and real peers before
it will change the cluster. There is intentionally no ungated, copy-and-run
mainnet snippet: use a pre-task gate like the example. Empty gates cause the
application to exit before listening, but do not by themselves prevent Kubernetes
resources from being created.
Run the playbook on the controller, using its normal kubeconfig discovery or
`wikideck_kubeconfig` / `wikideck_kube_context` overrides. Do not target every
Kubernetes node: the role operates on the Kubernetes API, not over node SSH.
For a private local preview, forward the Service with
For an explicitly built testnet development image, forward the Service with
`kubectl -n wikideck port-forward service/wikideck 3001:80` and open
<http://127.0.0.1:3001>. Keep the forwarding bind address at its loopback default.
Wikideck already allows this local origin. Different hosts, ports, schemes, and
browser profiles use different browser wallets.
The app allows this local origin. Different hosts, ports, schemes, and browser
profiles use different browser wallets. This does not bypass mainnet startup gates.
For remote browsers, enable ingress and set `wikideck_public_origin` to exactly
`https://` followed by `wikideck_ingress_host` (no slash or path). HTTPS is needed
@@ -81,6 +80,11 @@ Set `wikideck_peers` to a list of up to 16 compatible peer HTTPS origins, such a
An empty list deliberately starts an **isolated validator**. There is no automatic
discovery, bootnode list, or automatic reciprocal configuration: configure the
other operators' nodes too. All nodes must run the same network/genesis/consensus.
For mainnet, application startup additionally requires at least two distinct
public HTTPS peer origins, an arrived image-pinned genesis time, the exact chain-ID
approval, and explicit unaudited-risk acceptance. These switches are not launch
approval from this role; the project currently records a NO-GO decision. The role
does not discover or verify peer independence.
Peer RPC uses `/p2p/*` on the **same port 3001** as the UI/API; no separate TCP/UDP
P2P Service or host networking is required. The existing `/` ingress path forwards
@@ -149,6 +153,8 @@ All defaults are in [defaults/main.yml](defaults/main.yml).
| `wikideck_image_pull_secrets` | `[]` | Names of existing registry Secrets in this namespace. |
| `wikideck_peers` | `[]` | Up to 16 static peer origins; empty means isolated. |
| `wikideck_allow_private_peers` | `false` | Explicit test-only private/HTTP peer permission. |
| `wikideck_mainnet_launch` | empty | Exact 64-character chain-ID startup approval; leave empty unless a launch is formally approved. |
| `wikideck_mainnet_risk_ack` | empty | Must equal `operator-accepts-unaudited-risk` to acknowledge residual risk; not a certification. |
| `wikideck_public_origin` | empty | Additional allowed HTTPS browser origin; required with ingress. |
| `wikideck_ingress_enabled` | `false` | Create TLS ingress; disabling removes the role's named ingress. |
| `wikideck_ingress_host` | empty | DNS hostname, without scheme, port, or path. |
@@ -161,6 +167,8 @@ All defaults are in [defaults/main.yml](defaults/main.yml).
| `wikideck_storage_access_modes` | `[ReadWriteOnce]` | `ReadWriteOnce` or `ReadWriteOncePod`; never `ReadWriteMany`. |
| `wikideck_resources` | see defaults | CPU/memory requests `250m`/`512Mi`, limits `1`/`1Gi`; small-validator starting point, not a capacity guarantee. |
| `wikideck_node_selector` / `wikideck_tolerations` / `wikideck_affinity` | `{}` / `[]` / `{}` | Pod placement settings. |
| `wikideck_trusted_proxies` | `[]` | Up to 16 literal proxy IPs/CIDRs; only trust actual edge source addresses after the edge overwrites forwarded headers. |
| `wikideck_ops_port` | empty | Optional port for a diagnostics listener bound only to container loopback; never add it to the Service, Ingress, or NetworkPolicy. |
| `wikideck_network_policy_enabled` | `true` | Manage network isolation; disabling deletes this role's policy. |
| `wikideck_network_policy_ingress_from` | same-namespace pods | List of NetworkPolicy peers allowed to reach TCP 3001; empty list denies all ingress. |
| `wikideck_network_policy_dns_to` | `kube-system` namespace | DNS peers allowed on UDP/TCP 53; adapt for custom/NodeLocal DNS. |
@@ -182,10 +190,14 @@ entrypoint are deliberately preserved; no production fake-PoW fallback is added.
`ReadWriteOncePod` if supported by your CSI driver. Do not force-delete an old
pod on a partitioned node until it has been fenced; Recreate is not a
distributed storage lock.
- `/app/data/testnet/ledger.json` stores the block DAG and pending transfers;
`/app/data/testnet-node.lock` exclusively locks the entire data directory.
The old demo chain is separate, not imported, and has **no migration** to the
new testnet. Back it up first; preferably use a fresh claim for the new network.
- The active ledger is SQLite at `/app/data/<profile>/ledger.sqlite` (with WAL
sidecars); `/app/data/<profile>-node.lock` exclusively locks that profile's data.
A matching legacy `ledger.json` may be imported once and is retained as a
recovery copy. The import path accepts at most 128 MiB and 10,000 blocks; these
are legacy-import limits, not live SQLite disk bounds. Different profiles and
chain identities must not share a writable claim. Preserve and back up existing
data before changing image profile or genesis; incompatible chain data fails
closed rather than resetting automatically.
The process runs
as UID/GID 1000 with `fsGroup: 1000`. Your storage driver must honor ownership
settings, or the existing volume must already be writable by this identity.
@@ -199,15 +211,18 @@ entrypoint are deliberately preserved; no production fake-PoW fallback is added.
backup or use your CSI provider's documented snapshot procedure. Encrypt disks
and backups, define retention, and test restores. Deleting a namespace or PVC
can still destroy data depending on the underlying reclaim policy.
- The current `node:backup` utility creates/verifies/restores ledger-only packages
while the node is stopped. It does not contain browser wallets, secrets, or
configuration, and it does not encrypt the package; store it in restricted,
encrypted off-host storage and verify a restore before relying on it.
- Full native RandomX revalidation runs before the server listens. Increase
`wikideck_startup_probe_failure_threshold` and `wikideck_wait_timeout` together
for your measured replay time, leaving scheduling/image-pull margin. A healthy
empty node does not exercise the native cache or prove peer synchronization.
- The app bounds the ledger to 128 MiB and 10,000 total DAG blocks, with 256
pending transfers. Complete NFT states are retained per DAG node, so RAM may
grow quadratically despite disk bounds. Whole-ledger rewrites and full replay
are **not suitable for a long-lived public chain**; a larger PVC does not fix
those application limits.
- SQLite avoids whole-ledger JSON rewrites, but the node retains DAG records in
memory, rebuilds state roots over the full NFT set, and revalidates proofs at
startup. Long-chain capacity and archival-scale operation remain unresolved;
a larger PVC does not fix memory, replay, or consensus-capacity limits.
### Crash recovery and resource sizing
@@ -268,12 +283,15 @@ your worker architecture and runtime security profile; HTTP health alone cannot
detect every native engine failure. Do not grant privileged mode or disable
seccomp as an untested performance workaround.
Wikideck does not currently configure Express `trust proxy`. Clients behind one
proxy can therefore share an IP-based application rate limit. Review the
application before public exposure; do not try to fix this by blindly trusting
forwarded headers. The current app limits `/api` and `/p2p` together; default
forwarded-header behavior can also produce express-rate-limit validation errors
in logs. The role adds no authentication, WAF, or abuse protection. Eclipse,
`WIKIDECK_TRUSTED_PROXIES` is empty/untrusted by default. Populate
`wikideck_trusted_proxies` only with the literal source addresses/CIDRs actually
used by the trusted edge; the app validates them at startup. The edge must
overwrite forwarded headers, and network controls must prevent direct backend
access. Do not copy a generic proxy range without verifying the cluster path.
The optional `WIKIDECK_OPS_PORT` listener is loopback-only inside the pod and is
not exposed by role resources. It is intended for local/container-exec checks,
not an ingress endpoint. The role adds no authentication, WAF, or abuse
protection. Eclipse,
majority-hashpower, spam/DoS and reorganization risks remain application/protocol
issues; deployment hardening does not make a public mainnet safe.
@@ -282,8 +300,8 @@ issues; deployment hardening does not make a public mainnet safe.
[tests/render.yml](tests/render.yml) runs entirely offline: it validates inputs,
renders/parses every template across default, ingress, existing-claim, storage
class, isolated/public/private peers, custom HTTPS ports, deny-all, longer startup,
and digest-image variants, and checks wiring/security
invariants. It also checks that unsafe/invalid settings are rejected. Run it with
digest-image, launch-gate, proxy-trust and diagnostics variants, and checks
wiring/security invariants. It also checks that unsafe/invalid settings are rejected. Run it with
`ansible-playbook -i tests/inventory tests/render.yml`.
[tests/test.yml](tests/test.yml) is a real-cluster smoke test using the local
+7
View File
@@ -21,6 +21,9 @@ wikideck_image_pull_secrets: []
wikideck_peers: []
# Test/private networks only; permits private addresses AND HTTP in the app.
wikideck_allow_private_peers: false
# Explicit mainnet candidate startup gates. Never set these before launch approval.
wikideck_mainnet_launch: ""
wikideck_mainnet_risk_ack: ""
# Exact browser origin, without a trailing slash. Required when using ingress.
wikideck_public_origin: ""
wikideck_ingress_enabled: false
@@ -48,6 +51,10 @@ wikideck_resources:
wikideck_node_selector: {}
wikideck_tolerations: []
wikideck_affinity: {}
# Trust only literal proxy source IPs/CIDRs whose edge overwrites forwarded headers.
wikideck_trusted_proxies: []
# Optional private operations listener; application binds it to container loopback.
wikideck_ops_port: ""
# Requires a NetworkPolicy-capable CNI. Same-namespace clients only by default.
wikideck_network_policy_enabled: true
+23 -7
View File
@@ -2,16 +2,32 @@
- name: Deploy Wikideck
hosts: localhost
connection: local
gather_facts: false
gather_facts: true
pre_tasks:
- name: Require an approved and ready mainnet candidate release
ansible.builtin.assert:
that:
- wikideck_mainnet_deployment_approved | default(false) | bool
- wikideck_release_image is defined and wikideck_release_image is string and wikideck_release_image is match('^.+@sha256:[a-f0-9]{64}$')
- wikideck_release_peers is defined and wikideck_release_peers is sequence and wikideck_release_peers is not string and wikideck_release_peers | length >= 2
- wikideck_release_peers | unique | list | length == wikideck_release_peers | length
- wikideck_candidate_chain_id is defined and wikideck_candidate_chain_id is match('^[a-f0-9]{64}$')
- wikideck_candidate_risk_ack | default('') == 'operator-accepts-unaudited-risk'
- wikideck_release_genesis_time is defined and (wikideck_release_genesis_time | string) is match('^[1-9][0-9]{8,10}$')
- wikideck_release_genesis_time | int >= 1700000000 and wikideck_release_genesis_time | int <= 4102444800
- wikideck_release_genesis_time | int <= ansible_date_time.epoch | int
fail_msg: >-
Mainnet is currently NO-GO. Supply only an approved digest-pinned image,
verified frozen manifest and arrived genesis, independent public HTTPS
peers, and explicit unaudited-risk acceptance.
roles:
- role: wikideck
vars:
# Replace with your published, scanned image; preferably use @sha256:...
wikideck_image: registry.example.com/games/wikideck:1.0.0
# Replace with real compatible testnet peers. No bootnodes are supplied.
wikideck_peers:
- https://peer-a.example.org
- https://peer-b.example.org
wikideck_image: "{{ wikideck_release_image }}"
wikideck_image_pull_policy: IfNotPresent
wikideck_peers: "{{ wikideck_release_peers }}"
wikideck_mainnet_launch: "{{ wikideck_candidate_chain_id }}"
wikideck_mainnet_risk_ack: "{{ wikideck_candidate_risk_ack }}"
wikideck_ingress_enabled: true
wikideck_ingress_host: wikideck.example.com
wikideck_public_origin: https://wikideck.example.com
+1 -1
View File
@@ -3,7 +3,7 @@
galaxy_info:
role_name: wikideck
author: Eric Meehan
description: Deploy Wikideck to Kubernetes with persistent storage and optional TLS ingress.
description: Deploy the gated Wikideck mainnet candidate or an explicit development node to Kubernetes.
license: MIT-0
min_ansible_version: "2.16"
galaxy_tags:
+45
View File
@@ -0,0 +1,45 @@
- name: Deploy Wikideck
hosts: alpha-control-plane
become: true
vars_files:
- ~/Desktop/secrets.yaml
pre_tasks:
- name: Require an explicitly approved, immutable mainnet release
ansible.builtin.assert:
that:
- wikideck_mainnet_deployment_approved | default(false) | bool
- wikideck_release_image is defined and wikideck_release_image is string and wikideck_release_image is match('^.+@sha256:[a-f0-9]{64}$')
- wikideck_mainnet_peers is defined and wikideck_mainnet_peers is sequence and wikideck_mainnet_peers is not string and wikideck_mainnet_peers | length >= 2
- wikideck_mainnet_peers | unique | list | length == wikideck_mainnet_peers | length
- wikideck_candidate_chain_id is defined and wikideck_candidate_chain_id is match('^[a-f0-9]{64}$')
- wikideck_candidate_risk_ack | default('') == 'operator-accepts-unaudited-risk'
- wikideck_release_genesis_time is defined and (wikideck_release_genesis_time | string) is match('^[1-9][0-9]{8,10}$')
- wikideck_release_genesis_time | int >= 1700000000 and wikideck_release_genesis_time | int <= 4102444800
- wikideck_release_genesis_time | int <= ansible_date_time.epoch | int
fail_msg: >-
Mainnet is currently NO-GO. Do not deploy until the operator has approved
a digest-pinned image with a verified frozen manifest, arrived genesis,
at least two independent public HTTPS peers, and explicit risk acceptance.
roles:
- role: ericomeehan.wikideck
vars:
wikideck_image: "{{ wikideck_release_image }}"
wikideck_image_pull_policy: IfNotPresent
wikideck_peers: "{{ wikideck_mainnet_peers }}"
wikideck_mainnet_launch: "{{ wikideck_candidate_chain_id }}"
wikideck_mainnet_risk_ack: "{{ wikideck_candidate_risk_ack }}"
wikideck_public_origin: https://wikideck.eom.dev
wikideck_ingress_enabled: true
wikideck_ingress_host: wikideck.eom.dev
wikideck_ingress_class_name: nginx
wikideck_ingress_annotations:
cert-manager.io/cluster-issuer: ca-issuer
# Match the actual ingress controller namespace; add its podSelector if known.
wikideck_network_policy_ingress_from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: ingress-nginx
wikideck_storage_size: 2Ti
wikideck_storage_class: nfs-client
# Populate only after confirming the real proxy source IPs/CIDRs.
wikideck_trusted_proxies: "{{ wikideck_ingress_proxy_sources | default([]) }}"
+11
View File
@@ -28,6 +28,16 @@
- wikideck_existing_claim | length == 0 or wikideck_existing_claim is match('^[a-z0-9]([a-z0-9.-]*[a-z0-9])?$')
- wikideck_public_origin is string
- wikideck_public_origin | length == 0 or wikideck_public_origin is match('^https://[a-z0-9.-]+(:[0-9]+)?$')
- wikideck_mainnet_launch is string
- wikideck_mainnet_launch | length == 0 or wikideck_mainnet_launch is match('^[a-f0-9]{64}$')
- wikideck_mainnet_risk_ack is string
- wikideck_mainnet_risk_ack in ['', 'operator-accepts-unaudited-risk']
- wikideck_trusted_proxies is sequence and wikideck_trusted_proxies is not string and wikideck_trusted_proxies is not mapping
- wikideck_trusted_proxies | length <= 16
- wikideck_trusted_proxies | select('string') | list | length == wikideck_trusted_proxies | length
- wikideck_trusted_proxies | select('match', '^[0-9a-fA-F:.]+(/[0-9]{1,3})?$') | list | length == wikideck_trusted_proxies | length
- wikideck_ops_port is string or wikideck_ops_port is integer
- wikideck_ops_port | string | length == 0 or ((wikideck_ops_port | string) is match('^[1-9][0-9]{0,4}$') and wikideck_ops_port | int <= 65535)
- wikideck_ingress_enabled is boolean
- wikideck_network_policy_enabled is boolean
- wikideck_allow_private_peers is boolean
@@ -68,6 +78,7 @@
- wikideck_network_policy_https_ports
- wikideck_network_policy_peer_egress
- wikideck_peers
- wikideck_trusted_proxies
- name: Validate the static peer allowlist
ansible.builtin.assert:
+12
View File
@@ -71,6 +71,18 @@ spec:
value: {{ (wikideck_peers | join(',')) | to_json }}
- name: WIKIDECK_ALLOW_PRIVATE_PEERS
value: {{ ('1' if wikideck_allow_private_peers else '0') | to_json }}
- name: WIKIDECK_MAINNET_LAUNCH
value: {{ wikideck_mainnet_launch | to_json }}
- name: WIKIDECK_MAINNET_RISK_ACK
value: {{ wikideck_mainnet_risk_ack | to_json }}
{% if wikideck_trusted_proxies | length > 0 %}
- name: WIKIDECK_TRUSTED_PROXIES
value: {{ (wikideck_trusted_proxies | join(',')) | to_json }}
{% endif %}
{% if wikideck_ops_port | string | length > 0 %}
- name: WIKIDECK_OPS_PORT
value: {{ (wikideck_ops_port | string) | to_json }}
{% endif %}
{% if wikideck_public_origin | length > 0 %}
- name: PUBLIC_ORIGIN
value: {{ wikideck_public_origin | to_json }}
+4
View File
@@ -19,6 +19,10 @@
wikideck_network_policy_peer_egress: "{{ invalid_case.peer_egress | default([]) }}"
wikideck_image_pull_secrets: "{{ invalid_case.pull_secrets | default([]) }}"
wikideck_network_policy_ingress_from: "{{ invalid_case.ingress_from | default([{'podSelector': {}}]) }}"
wikideck_trusted_proxies: "{{ invalid_case.trusted_proxies | default([]) }}"
wikideck_ops_port: "{{ invalid_case.ops_port | default('') }}"
wikideck_mainnet_launch: "{{ invalid_case.mainnet_launch | default('') }}"
wikideck_mainnet_risk_ack: "{{ invalid_case.risk_ack | default('') }}"
block:
- name: Run role input validation
ansible.builtin.include_tasks: ../tasks/validate.yml
+19
View File
@@ -15,6 +15,10 @@
wikideck_namespace: "{{ render_case.namespace | default('wikideck') }}"
wikideck_peers: "{{ render_case.peers | default([]) }}"
wikideck_allow_private_peers: "{{ render_case.allow_private | default(false) }}"
wikideck_mainnet_launch: "{{ render_case.mainnet_launch | default('') }}"
wikideck_mainnet_risk_ack: "{{ render_case.risk_ack | default('') }}"
wikideck_trusted_proxies: "{{ render_case.trusted_proxies | default([]) }}"
wikideck_ops_port: "{{ render_case.ops_port | default('') }}"
wikideck_startup_probe_failure_threshold: "{{ render_case.startup_threshold | default(180) }}"
wikideck_ingress_enabled: "{{ render_case.ingress | default(false) }}"
wikideck_ingress_host: wikideck.example.com
@@ -73,6 +77,13 @@
https_to: []
- label: digest-pinned image
image: registry.example.com/wikideck@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
- label: proxy trust and private diagnostics
peers: [https://peer-a.example.org, https://peer-b.example.org]
trusted_proxies: [10.20.30.40, 2001:db8::/64]
ops_port: "9090"
- label: exact mainnet launch configuration
mainnet_launch: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
risk_ack: operator-accepts-unaudited-risk
loop_control:
loop_var: render_case
label: "{{ render_case.label }}"
@@ -146,6 +157,14 @@
peer_egress:
- to: [{podSelector: {}}]
ports: [{protocol: UDP, port: 3001}]
- label: malformed mainnet chain approval
mainnet_launch: not-a-chain-id
- label: unsupported mainnet risk acknowledgement
risk_ack: operator-accepts-risk
- label: proxy entry is not an IP or CIDR
trusted_proxies: [proxy.example.org]
- label: operations port out of range
ops_port: "70000"
loop_control:
loop_var: invalid_case
label: "{{ invalid_case.label }}"
+4
View File
@@ -48,6 +48,10 @@
- env.WIKIDECK_DATA_DIR == '/app/data' and env.NODE_ENV == 'production'
- env.WIKIDECK_PEERS == wikideck_peers | join(',')
- env.WIKIDECK_ALLOW_PRIVATE_PEERS == ('1' if wikideck_allow_private_peers else '0')
- env.WIKIDECK_MAINNET_LAUNCH == wikideck_mainnet_launch
- env.WIKIDECK_MAINNET_RISK_ACK == wikideck_mainnet_risk_ack
- (env.WIKIDECK_TRUSTED_PROXIES | default('')) == wikideck_trusted_proxies | join(',')
- (env.WIKIDECK_OPS_PORT | default('')) == (wikideck_ops_port | string)
- env.WIKIDECK_OFFLINE is not defined
- env.RANDOMX_BINARY is not defined
- container.command is not defined and container.args is not defined
+13 -6
View File
@@ -2,7 +2,8 @@
import assert from 'node:assert/strict';
import { spawn, execFileSync } from 'node:child_process';
import { once } from 'node:events';
import { readFile, access } from 'node:fs/promises';
import { access } from 'node:fs/promises';
import { DatabaseSync } from 'node:sqlite';
assert.equal(process.env.WIKIDECK_DATA_DIR, '/app/data');
assert.equal(process.env.WIKIDECK_PEERS, '');
@@ -39,17 +40,23 @@ async function runNode() {
const body = await response.json();
if (path === '/healthz') {
assert.equal(body.status, 'ok');
assert.equal(body.network, 'wikideck-randomx-testnet-2');
assert.equal(body.network, 'wikideck-randomx-testnet-6');
} else if (path === '/p2p/status') {
assert.equal(body.network, 'wikideck-randomx-testnet-2');
assert.equal(body.network, 'wikideck-randomx-testnet-6');
assert.equal(body.size, 0);
assert.match(body.chainId, /^[a-f0-9]{64}$/);
} else assert.deepEqual(body.peers, []);
}
await access('/app/data/testnet-node.lock');
const ledger = JSON.parse(await readFile('/app/data/testnet/ledger.json', 'utf8'));
assert.equal(ledger.network, 'wikideck-randomx-testnet-2');
assert.deepEqual(ledger.blocks, []);
const ledger = new DatabaseSync('/app/data/testnet/ledger.sqlite');
try {
const metadata = ledger.prepare('SELECT value FROM metadata WHERE key = ?').get('network');
assert.equal(metadata.value, 'wikideck-randomx-testnet-6');
assert.equal(ledger.prepare('SELECT COUNT(*) AS count FROM blocks').get().count, 0);
assert.equal(ledger.prepare('SELECT COUNT(*) AS count FROM pending_transfers').get().count, 0);
} finally {
ledger.close();
}
child.kill('SIGTERM');
assert.deepEqual(await exited, [0, null], output);
await assert.rejects(access('/app/data/testnet-node.lock'), { code: 'ENOENT' });