Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 17 additions & 5 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,29 @@ FROM python:3.12-slim AS paper-engine

ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1 \
ZERO_MODE=paper
ZERO_MODE=paper \
ZERO_FOUNDATION_STATE_DIR=/data/.zero \
ZERO_FOUNDATION_HEARTBEAT_ENABLED=true

WORKDIR /app

COPY engine/pyproject.toml engine/README.md /app/engine/
COPY engine/src /app/engine/src
RUN useradd --create-home --shell /usr/sbin/nologin zero \
&& mkdir -p /data/.zero \
&& chown -R zero:zero /data /app
Comment thread
coderabbitai[bot] marked this conversation as resolved.

COPY examples /app/examples
COPY scripts/railway_start.sh /app/scripts/railway_start.sh

RUN python -m pip install --no-cache-dir --upgrade pip \
&& python -m pip install --no-cache-dir /app/engine \
&& chmod +x /app/scripts/railway_start.sh
&& python -m pip install --no-cache-dir zero-engine==0.1.6 \
&& chmod +x /app/scripts/railway_start.sh \
&& chown -R zero:zero /app

USER zero

EXPOSE 8765

HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \
CMD python -c "import json, os, urllib.request; port=os.environ.get('PORT', '8765'); payload=json.load(urllib.request.urlopen(f'http://127.0.0.1:{port}/health', timeout=3)); raise SystemExit(0 if payload.get('status') == 'ok' else 1)"

CMD ["zero-paper-demo"]
30 changes: 19 additions & 11 deletions contracts/distribution/railway-template.json
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
{
"checks": {
"deploy_docs_name_doctor": true,
"dockerfile_installs_engine": true,
"dockerfile_installs_claim_capable_package": true,
"dockerfile_present": true,
"partner_docs_name_application_url": true,
"partner_docs_name_support_commitment": true,
"partner_docs_name_template_queue": true,
"partner_docs_name_template_url": true,
"partner_docs_present": true,
"railway_healthcheck_configured": true,
"railway_start_names_runtime_version": true,
"railway_start_uses_durable_journal": true,
"railway_start_uses_foundation_state_dir": true,
"railway_start_uses_port": true,
"railway_toml_present": true,
"railway_uses_dockerfile": true,
Expand All @@ -20,15 +22,18 @@
"schema_version": "zero.railway_template_packet.v1",
"start_script_present": true,
"template_docs_include_marketplace_overview": true,
"template_docs_name_bootstrap_readback": true,
"template_docs_name_claim_success_log": true,
"template_docs_name_dashboard_generation": true,
"template_docs_name_icon": true,
"template_docs_name_marketplace_icon": true,
"template_docs_name_partner_publish_step": true,
"template_docs_name_public_demo": true,
"template_docs_name_runtime_package": true,
"template_docs_name_template_url": true,
"template_icon_present": true
},
"generated_at": "2026-05-05T07:51:46Z",
"generated_at": "2026-07-01T08:05:00Z",
"marketplace": {
"create_flow": "Project Settings -> Generate Template from Project",
"deploy_button_markdown": "[![Deploy on Railway](https://railway.com/button.svg)](https://railway.com/deploy/zero-paper-runtime)",
Expand Down Expand Up @@ -66,33 +71,36 @@
"builder": "DOCKERFILE",
"dockerfile_path": "Dockerfile",
"healthcheck_path": "/health",
"runtime_package": "zero-engine==0.1.6",
Comment thread
squaeragent marked this conversation as resolved.
"start_command": "/app/scripts/railway_start.sh"
},
"doctor_summary": {
"fail": 0,
"ok": 17,
"warn": 1
"reason": "0.1.6 claim-capable template source changed after the last live demo evidence bundle",
"status": "pending_after_marketplace_republish"
},
"environment": "production",
"evidence_bundle_at_generation": "artifacts/deployment-evidence/20260504T192122Z",
"evidence_bundle_at_generation": null,
"evidence_verify": {
"checks": 60,
"fail": 0,
"ok": true
"ok": null,
"status": "pending_after_marketplace_republish"
},
"partner_application": "template_published_partner_pending",
"partner_application_packet": "docs/railway-partner.md",
"project": "fabulous-enchantment",
"public_demo_url": "https://zero-production-5214.up.railway.app",
"service": "zero",
"status": "published_on_marketplace",
"status": "pending_marketplace_republish_after_runtime_package_update",
"template_name": "ZERO Paper Runtime",
"template_url": "https://railway.com/deploy/zero-paper-runtime",
"verified_deployment_at_generation": "ea8424de-f5e3-4227-84a3-67970f5b0cfd",
"verified_deployment_at_generation": null,
"workspace": "zero"
},
"template_variables": {
"ZERO_CLAIM_TOKEN": "",
"ZERO_CONTROL_URL": "",
"ZERO_DEPLOYMENT_ID": "zero-railway-public-paper",
"ZERO_DEPLOYMENT_VERSION": "engine-v0.1.6",
"ZERO_FOUNDATION_STATE_DIR": "/data/.zero",
"ZERO_HYPERLIQUID_LIVE_PRICES": "true",
"ZERO_INTELLIGENCE_API_ACCOUNT_ID": "acct_railway",
"ZERO_INTELLIGENCE_API_PLAN": "free",
Expand Down
28 changes: 26 additions & 2 deletions docs/llms-full.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2297,6 +2297,10 @@ The latest Railway Template Publish Packet is committed at
It records the live demo URL, point-in-time verified deployment id, evidence
bundle path, doctor result, required variables, autodeploy config, and
marketplace publish state.
After template-impacting runtime package changes, the packet must mark live
evidence as pending until the Railway project is rebuilt from `main`, the
marketplace template is regenerated, and a fresh doctor/evidence bundle is
captured.

## Common Use Cases

Expand All @@ -2309,7 +2313,10 @@ marketplace publish state.
## Dependencies for ZERO Hosting

- Railway service sourced from `https://github.com/zero-intel/zero`.
- Dockerfile build from the repository root.
- Dockerfile build from the repository root. The root Dockerfile installs the
claim-capable public PyPI package `zero-engine==0.1.6` so the marketplace
template can consume Foundation claim bootstrap without copying commercial app
code into the public repo.
- Public HTTP networking enabled for the runtime service.
- Persistent Railway volume mounted at `/data`.
- Railway-provided `PORT`; do not hardcode a port.
Expand All @@ -2335,6 +2342,7 @@ marketplace publish state.
| Branch | `main` |
| Builder | Dockerfile |
| Dockerfile path | `Dockerfile` |
| Runtime package | `zero-engine==0.1.6` |
| Start command | from `railway.toml`: `/app/scripts/railway_start.sh` |
| Healthcheck path | `/health` |
| Healthcheck timeout | `60` |
Expand Down Expand Up @@ -2377,7 +2385,7 @@ before any live authority ceremony.
## Dependencies for ZERO Hosting

- Railway service sourced from `https://github.com/zero-intel/zero`.
- Dockerfile build from the repository root.
- Dockerfile build from the repository root, installing `zero-engine==0.1.6`.
- Public HTTP networking enabled for the runtime service.
- Persistent Railway volume mounted at `/data`.
- Railway-provided `PORT`.
Expand All @@ -2397,12 +2405,28 @@ inspectable, interruptible, and paper-first by default.
| `ZERO_MODE` | yes | `paper` | Keeps the template in paper mode. |
| `ZERO_JOURNAL_PATH` | yes | `/data/decisions.jsonl` | Durable append-only paper journal on the Railway volume. |
| `ZERO_HYPERLIQUID_LIVE_PRICES` | yes | `true` | Uses Hyperliquid public mids as read-only market data. |
| `ZERO_DEPLOYMENT_VERSION` | yes | `engine-v0.1.6` | Identifies the claim-capable runtime package in `/deployment/claim` readbacks. |
| `ZERO_FOUNDATION_STATE_DIR` | yes | `/data/.zero` | Persists the scoped Foundation API key and runtime keys on the Railway volume after a successful claim. |
| `ZERO_CONTROL_URL` | app-connected only | empty | ZERO app/control-plane URL from Studio Vibe Deploy, usually `https://getzero.dev`. |
| `ZERO_DEPLOYMENT_ID` | app-connected only | `zero-railway-public-paper` | Replace with the deployment id minted by Studio before app binding. |
| `ZERO_CLAIM_TOKEN` | app-connected only | empty | One-time claim ticket copied from Studio. Keep hidden in Railway; do not publish it in logs or docs. |
| `ZERO_INTELLIGENCE_STORE_PATH` | yes | `/data/zero/intelligence.jsonl` | Durable aggregate store for hosted-compatible Intelligence reference endpoints. |
| `ZERO_INTELLIGENCE_API_TOKEN` | optional | empty | Disposable demo bearer token for hosted-compatible protected Intelligence routes. |
| `ZERO_INTELLIGENCE_API_PLAN` | optional | `free` | Reference account plan shown by local hosted-compatible packets. |
| `ZERO_INTELLIGENCE_API_ACCOUNT_ID` | optional | `acct_railway` | Public-safe local account label for reference packets. |
| `ZERO_INTELLIGENCE_WEBHOOK_SIGNING_KEY` | optional | `${{secret(64, "abcdef0123456789")}}` | Demo HMAC key for webhook fixture signatures. Never reuse production keys. |

Successful app-connected boots must print:

```text
zero foundation deployment claimed: <deployment_id> claim_token_consumed=true runtime_base_url=https://<railway-domain>
```

`/deployment/claim` and `/deployment/heartbeat` must also expose public-safe
`runtime.foundation_bootstrap_*` fields. If the runtime reports version `0.1.5`
or omits those fields, rebuild the Railway service from the current template
before recovering another claim ticket.

## Railway Template Publish Packet

The packet schema is `zero.railway_template_packet.v1`. Regenerate it after any
Expand Down
28 changes: 26 additions & 2 deletions docs/railway-template.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ The latest Railway Template Publish Packet is committed at
It records the live demo URL, point-in-time verified deployment id, evidence
bundle path, doctor result, required variables, autodeploy config, and
marketplace publish state.
After template-impacting runtime package changes, the packet must mark live
evidence as pending until the Railway project is rebuilt from `main`, the
marketplace template is regenerated, and a fresh doctor/evidence bundle is
captured.

## Common Use Cases

Expand All @@ -42,7 +46,10 @@ marketplace publish state.
## Dependencies for ZERO Hosting

- Railway service sourced from `https://github.com/zero-intel/zero`.
- Dockerfile build from the repository root.
- Dockerfile build from the repository root. The root Dockerfile installs the
claim-capable public PyPI package `zero-engine==0.1.6` so the marketplace
template can consume Foundation claim bootstrap without copying commercial app
code into the public repo.
- Public HTTP networking enabled for the runtime service.
- Persistent Railway volume mounted at `/data`.
- Railway-provided `PORT`; do not hardcode a port.
Expand All @@ -68,6 +75,7 @@ marketplace publish state.
| Branch | `main` |
| Builder | Dockerfile |
| Dockerfile path | `Dockerfile` |
| Runtime package | `zero-engine==0.1.6` |
| Start command | from `railway.toml`: `/app/scripts/railway_start.sh` |
| Healthcheck path | `/health` |
| Healthcheck timeout | `60` |
Expand Down Expand Up @@ -110,7 +118,7 @@ before any live authority ceremony.
## Dependencies for ZERO Hosting

- Railway service sourced from `https://github.com/zero-intel/zero`.
- Dockerfile build from the repository root.
- Dockerfile build from the repository root, installing `zero-engine==0.1.6`.
- Public HTTP networking enabled for the runtime service.
- Persistent Railway volume mounted at `/data`.
- Railway-provided `PORT`.
Expand All @@ -130,12 +138,28 @@ inspectable, interruptible, and paper-first by default.
| `ZERO_MODE` | yes | `paper` | Keeps the template in paper mode. |
| `ZERO_JOURNAL_PATH` | yes | `/data/decisions.jsonl` | Durable append-only paper journal on the Railway volume. |
| `ZERO_HYPERLIQUID_LIVE_PRICES` | yes | `true` | Uses Hyperliquid public mids as read-only market data. |
| `ZERO_DEPLOYMENT_VERSION` | yes | `engine-v0.1.6` | Identifies the claim-capable runtime package in `/deployment/claim` readbacks. |
| `ZERO_FOUNDATION_STATE_DIR` | yes | `/data/.zero` | Persists the scoped Foundation API key and runtime keys on the Railway volume after a successful claim. |
| `ZERO_CONTROL_URL` | app-connected only | empty | ZERO app/control-plane URL from Studio Vibe Deploy, usually `https://getzero.dev`. |
| `ZERO_DEPLOYMENT_ID` | app-connected only | `zero-railway-public-paper` | Replace with the deployment id minted by Studio before app binding. |
| `ZERO_CLAIM_TOKEN` | app-connected only | empty | One-time claim ticket copied from Studio. Keep hidden in Railway; do not publish it in logs or docs. |
| `ZERO_INTELLIGENCE_STORE_PATH` | yes | `/data/zero/intelligence.jsonl` | Durable aggregate store for hosted-compatible Intelligence reference endpoints. |
| `ZERO_INTELLIGENCE_API_TOKEN` | optional | empty | Disposable demo bearer token for hosted-compatible protected Intelligence routes. |
| `ZERO_INTELLIGENCE_API_PLAN` | optional | `free` | Reference account plan shown by local hosted-compatible packets. |
| `ZERO_INTELLIGENCE_API_ACCOUNT_ID` | optional | `acct_railway` | Public-safe local account label for reference packets. |
| `ZERO_INTELLIGENCE_WEBHOOK_SIGNING_KEY` | optional | `${{secret(64, "abcdef0123456789")}}` | Demo HMAC key for webhook fixture signatures. Never reuse production keys. |

Successful app-connected boots must print:

```text
zero foundation deployment claimed: <deployment_id> claim_token_consumed=true runtime_base_url=https://<railway-domain>
```

`/deployment/claim` and `/deployment/heartbeat` must also expose public-safe
`runtime.foundation_bootstrap_*` fields. If the runtime reports version `0.1.5`
or omits those fields, rebuild the Railway service from the current template
before recovering another claim ticket.

## Railway Template Publish Packet

The packet schema is `zero.railway_template_packet.v1`. Regenerate it after any
Expand Down
4 changes: 3 additions & 1 deletion scripts/hardening_gate.sh
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,9 @@ contains "https://station.railway.com/my-template-queue" docs/railway-partner.md
contains "scripts/homebrew_formula.py" docs/distribution.md
contains "zero.registry_launch_packet.v1" docs/registry-launch.md
contains "zero.railway_template_packet.v1" contracts/distribution/railway-template.json
contains "published_on_marketplace" contracts/distribution/railway-template.json
contains "pending_marketplace_republish_after_runtime_package_update" contracts/distribution/railway-template.json
contains "zero-engine==0.1.6" contracts/distribution/railway-template.json
contains "pending_after_marketplace_republish" contracts/distribution/railway-template.json
contains "template_published_partner_pending" contracts/distribution/railway-template.json
contains "docs/assets/zero-template-icon.svg" contracts/distribution/railway-template.json
contains "https://railway.com/deploy/zero-paper-runtime" contracts/distribution/railway-template.json
Expand Down
4 changes: 3 additions & 1 deletion scripts/public_readiness_gate.sh
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,9 @@ file_contains "brew tap zero-intel/zero" README.md
file_contains "https://zero-production-5214.up.railway.app" README.md
file_contains "https://railway.com/deploy/zero-paper-runtime" README.md
file_contains "zero.railway_template_packet.v1" contracts/distribution/railway-template.json
file_contains "published_on_marketplace" contracts/distribution/railway-template.json
file_contains "pending_marketplace_republish_after_runtime_package_update" contracts/distribution/railway-template.json
file_contains "zero-engine==0.1.6" contracts/distribution/railway-template.json
file_contains "pending_after_marketplace_republish" contracts/distribution/railway-template.json
file_contains "template_published_partner_pending" contracts/distribution/railway-template.json
file_contains "ZERO Paper Runtime" contracts/distribution/railway-template.json
file_contains "https://railway.com/deploy/zero-paper-runtime" contracts/distribution/railway-template.json
Expand Down
6 changes: 4 additions & 2 deletions scripts/railway_smoke.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ HOST_PORT="${ZERO_RAILWAY_SMOKE_PORT:-18765}"
CONTAINER_NAME="zero-railway-smoke-${HOST_PORT}"
API="http://127.0.0.1:${HOST_PORT}"
STATE_DIR="$(mktemp -d)"
chmod 0777 "${STATE_DIR}"

cleanup() {
status=$?
Expand Down Expand Up @@ -42,9 +43,10 @@ start_container() {
docker run -d \
--name "${CONTAINER_NAME}" \
-p "${HOST_PORT}:${HOST_PORT}" \
-v "${STATE_DIR}:/tmp/zero" \
-v "${STATE_DIR}:/data" \
-e PORT="${HOST_PORT}" \
-e ZERO_JOURNAL_PATH=/tmp/zero/decisions.jsonl \
-e ZERO_JOURNAL_PATH=/data/decisions.jsonl \
-e ZERO_FOUNDATION_STATE_DIR=/data/.zero \
-e ZERO_HYPERLIQUID_LIVE_PRICES=false \
-e ZERO_INTELLIGENCE_API_TOKEN=railway-intelligence-token \
-e ZERO_INTELLIGENCE_API_PLAN=team_fund \
Expand Down
5 changes: 4 additions & 1 deletion scripts/railway_start.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@ set -euo pipefail
PORT="${PORT:-8765}"
ZERO_JOURNAL_PATH="${ZERO_JOURNAL_PATH:-/data/decisions.jsonl}"
ZERO_HYPERLIQUID_LIVE_PRICES="${ZERO_HYPERLIQUID_LIVE_PRICES:-true}"
ZERO_DEPLOYMENT_VERSION="${ZERO_DEPLOYMENT_VERSION:-engine-v0.1.6}"
ZERO_FOUNDATION_STATE_DIR="${ZERO_FOUNDATION_STATE_DIR:-/data/.zero}"
ZERO_REPO_ROOT="${ZERO_REPO_ROOT:-/app}"

mkdir -p "$(dirname "${ZERO_JOURNAL_PATH}")"
export ZERO_REPO_ROOT
mkdir -p "${ZERO_FOUNDATION_STATE_DIR}"
export ZERO_DEPLOYMENT_VERSION ZERO_FOUNDATION_STATE_DIR ZERO_REPO_ROOT

args=(
zero-paper-api
Expand Down
Loading