Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
eba7f06
feat(worker): define ExecutionProof Phala TDX tier + attestation schema
echobt Jul 8, 2026
bc069f6
test(worker): pin cross-repo report_data golden vector (drift guard)
echobt Jul 8, 2026
c43fed2
test(worker): pin cross-repo emitted-envelope conformance (Phala tier)
echobt Jul 8, 2026
e2dd46f
test(worker): fix mypy type-ignore code on Phala envelope conformance…
echobt Jul 8, 2026
6c041c4
feat(worker): Phala-tier ExecutionProof quote verifier (accept valid,…
echobt Jul 8, 2026
2bd279b
test(master): pin R=1 + no reconciliation for attested agent-challeng…
echobt Jul 8, 2026
f73e8f6
test(verify): base-side flag-OFF invariant (R=1 legacy path, Phala ve…
echobt Jul 8, 2026
9b7b9cb
feat(verify): allowlist fail-closed loading + multi-entry image rotat…
echobt Jul 8, 2026
84facd6
fix(worker): park dcap-qvl exit-0-unparseable output; pin cross-repo …
echobt Jul 8, 2026
cc92d7d
test(cross-integration): base-leg R=1 + attestation carry-chain integ…
echobt Jul 9, 2026
a7d3d52
test(supervisor): make weights compute-raise log test order-independent
echobt Jul 9, 2026
15c7f69
test(cross-integration): base leg flag-OFF legacy handling (VAL-CROSS…
echobt Jul 9, 2026
2403f54
feat(worker): add canonical eval proof v2 wire
echobt Jul 11, 2026
3cf1708
feat(master): bridge immutable replay audits
echobt Jul 12, 2026
b2c629c
fix(master): harden replay plan digest validation
echobt Jul 12, 2026
e0775a4
feat(master): harden attested challenge proxy
echobt Jul 12, 2026
63202c6
fix(worker): harden Eval execution proof schema
echobt Jul 12, 2026
cc09ca8
fix(master): deny private proxy fallthrough with allowlist
echobt Jul 12, 2026
01b1e93
fix(worker): set Eval vm_config bound to 256 KiB
echobt Jul 12, 2026
20e2dff
fix(phala): verify dcap-qvl quotes via temp file path
echobt Jul 13, 2026
6f83a0f
fix(test): VAL-CROSS-003 zero agent-challenge assignments (full attes…
echobt Jul 13, 2026
bf9c9f8
docs(readme): note agent-challenge Phala ExecutionProof and R=1 proxy
echobt Jul 13, 2026
2f9d469
docs: complete Phala/agent-challenge attestation integration notes
echobt Jul 13, 2026
4397e92
fix(worker): import ExecutionProof signing helpers from challenge_sdk
echobt Jul 13, 2026
c4ec5c0
fix(test): adapt Phala fixtures to Swarm AssignmentView
echobt Jul 13, 2026
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
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,7 @@ build/
plan/

.omo/
*.env
secrets/
*.pem
*.key
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,14 @@ replay audits, and weight submission.
- **Signed enrollment** — the miner signs a hotkey↔worker binding; provider keys (`LIUM_API_KEY` / `TARGON_API_KEY`) stay in the miner's environment and never reach the master.
- **Anti-collusion** — a worker never evaluates its owner's submission; each unit replicates across **R=2 distinct-owner** workers and is reconciled by `ExecutionProof.manifest_sha256`.
- **Proof tiers** — tier 0 (manifest hash + sr25519 signature), tier 1 (pinned image digest), tier 2 (in-guest attestation, gated off on Targon). Audit sampling is tier-modulated.
- **Agent Challenge Phala Intel TDX path (separate from the PRISM worker plane):** BASE carries
the Phala-tier `ExecutionProof` / `EvalExecutionProof` schema (including `vm_config` ≤ 256 KiB),
quote verification helpers, R=1 assignment for attested units, and public-proxy deny rules so
agent-challenge capability, internal, and direct result-ingestion routes stay challenge-direct
(default off). Flag-off: legacy byte-identical signed submission/env/launch proxy path and R=1
own_runner behavior. Full attested mode uses **one miner-funded external eval (R=1)** with
**zero** BASE validator re-exec multi-replica assignment; score acceptance remains challenge-
owned. Details: [Architecture](docs/architecture.md#agent-challenge-phala-intel-tdx-path).
- **Admission rule** — when enforced, a miner needs ≥1 active bound worker to submit to Prism, else `403 NO_ACTIVE_WORKER`.

See the <a href="docs/miner/worker-plane.md">miner worker deployment guide</a>.
Expand Down
70 changes: 70 additions & 0 deletions docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,3 +120,73 @@ Operator install and deeper cardinality rules: [Compose-only deployment](compose
- Helm / Kubernetes
- Per-challenge Postgres servers managed by BASE
- Automated destructive challenge purge without explicit operator action

## Agent Challenge Phala Intel TDX path

Agent Challenge attestation is **separate from the PRISM miner-funded GPU worker plane**. BASE owns the shared proof, proxy, and assignment surfaces below; end-to-end self-deploy review→eval, RA-TLS key release, and score acceptance live in the agent-challenge service when its own attestation flags are on (cross-repo challenge docs are available after PR merge).

### Flag-off vs flag-on

| Surface | Flag off (default) | Flag on |
|---------|--------------------|---------|
| Master setting | `master.agent_challenge_attested_routes_enabled=false` | `master.agent_challenge_attested_routes_enabled=true` |
| Public proxy | Legacy signed submission / env / launch passthrough | Fail-closed **allowlist** of review/eval + status/SSE + benchmark metadata only |
| Evaluation ownership | Legacy R=1 `own_runner` on validators (reassign on failure, never multi-replica) | Full attested mode: **one miner-funded external eval (R=1)**; BASE creates **zero** agent-challenge validator assignment, retry, replica, reconciliation, audit, or fold rows for those units |
| Phala verifier | Not required on agent-challenge results | Challenge/operators use BASE Phala-tier schema + quote helpers; BASE does not invent challenge-side score policy |

Legacy path is byte-identical when the master attested-routes flag stays off. PRISM worker-plane replication (default R=2, `compute.replication_factor`) is unchanged either way.

```mermaid
flowchart TB
M[Miner] --> P[Public BASE proxy]
P -->|allowlisted review/eval only when flag on| AC[agent-challenge service]
AC -->|miner-funded external Eval R=1| TEE[Phala Intel TDX CVM]
TEE -->|EvalExecutionProof tier phala-tdx| AC
AC -->|internal weights / control plane only| MSTR[Master]
V[Validators] -.->|sampled replay audit only when scheduled| AC
```

### Public vs private challenge proxy boundary

Public clients reach challenges only at `/challenges/{slug}/...`. The proxy always blocks:

- `/internal/*`, `/health`, `/version`
- Generic benchmark-execution-shaped paths (for example `/benchmark-executions` and benchmark `run` / `execute` / `launch` leaves)

With **attested routes enabled**, agent-challenge is additionally **allowlist fail-closed** (`src/base/master/app_proxy.py`): only the exact signed review/eval rows, signed `POST /submissions`, `GET .../status` and `GET .../events`, and `GET /benchmarks/tasks` are forwardable. Capability, assignment, evidence, key-release, direct result ingestion, results aliases, env/launch (legacy), wrong methods, neighboring paths, and non-canonical raw path bytes are denied **locally** (404 before any upstream call). Private routes must never fall through the public proxy.

On allowlisted agent-challenge routes the proxy:

- Preserves miner signature headers `X-Hotkey`, `X-Signature`, `X-Nonce`, `X-Timestamp` where the miner signs the challenge-local path
- Strips hop-by-hop, internal, and attested trust-shaped headers/prefixes (for example `x-base-*`, `x-attestation-*`, `x-ra-tls-*`, client-IP spoofs) so edge clients cannot inject trust

### ExecutionProof Phala tier (BASE schema)

Every worker/eval proof envelope is the shared `ExecutionProof` model in `src/base/schemas/worker.py`:

- Integer tiers **0 / 1 / 2** remain the PRISM worker-plane tiers (manifest + sr25519; image digest; optional in-guest attestation).
- Phala Intel TDX uses string tier **`phala-tdx`** (`PHALA_TDX_TIER`), with an `attestation` block (`PhalaAttestation` / strict `EvalPhalaAttestation`).
- Canonical **Eval** wire equals schema-closed `EvalExecutionProof` (version 1, tier `phala-tdx`, digest-pinned `image_digest`, empty worker-signature placeholders for validator rebind, no extra fields).
- Bound examples (fail closed at parse): TDX quote ≤ 64 KiB, event log ≤ 4096 entries / 2 MiB, **`vm_config` ≤ 256 KiB** (`EVAL_MAX_VM_CONFIG_BYTES`), closed `vm_config` fields `{vcpu, memory_mb, os_image_hash}`.
- Measurement registers use fixed hex widths; `report_data` is 64-byte (128 hex) left-aligned binding with domain tag `base-agent-challenge-v1` (`src/base/worker/proof.py`).

### Quote verify and park vs reject

BASE quote helpers (`src/base/worker/phala_quote.py`, `phala_verify.py`, `proof.py`) verify Phala-tier proofs:

1. **Tier-0** worker (or rebound) signature over `sha256("{manifest_sha256}:{unit_id}")` always required.
2. Quote structure + RTMR3 event-log replay from the hardware-signed TD report (compose bound by content, not trusted by value).
3. Cryptographic DCAP verification via the **`dcap-qvl`** CLI: quote bytes are written to a **temp file** and passed by path (not as an inline argv hex body).
4. Measurement must match a non-empty validator **allowlist** (fail-closed when empty or unloaded).
5. Nonce freshness via validator-issued state; acceptable TCB default includes `UpToDate`.

Outcomes:

- Cryptographic / structure failure → **reject**
- Transient `dcap-qvl` missing, timeout, exit-0 non-JSON, or missing TCB status → **park** (`VerifierUnavailableError`): never accept, never permanent fraud-reject

BASE does not claim perfect hardware trust. Treat Phala as **cryptographically-anchored trust-but-audit**; residual TEE and collateral risks remain (see [Security](security.md)).

### Replay audit seam

Sampled validator replay audits for agent-challenge use the labelled transport in `src/base/master/replay_audit.py` (`agent-challenge.replay-audit.v1`). Requests carry the complete immutable Eval plan; plan digests and trial scores are validated on the BASE wire before forward or accept. This is not ordinary multi-replica worker reconciliation.
10 changes: 10 additions & 0 deletions docs/challenge-integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,16 @@ connection pooling, storage resize workflows, challenge Alembic migration
automation, or automated destructive purge beyond the explicit operator scripts
documented for the master Compose project ([compose.md](compose.md)).

## Agent Challenge attestation surfaces (BASE-owned)

Integrator notes for challenges that participate in the Phala / attested topology (today: agent-challenge). Implement these contracts only when your challenge ships the matching attested mode; generated demo challenges still use the weight + SQLite contract above.

- **Public proxy.** BASE never publicly proxies `/internal/*`, result-ingestion, capability, assignment, evidence, or key-release neighbors. Opt-in review/eval allowlisting is `master.agent_challenge_attested_routes_enabled` (default off keeps legacy submission/env/launch).
- **ExecutionProof.** Prefer the schema-closed Eval wire (`EvalExecutionProof`, tier `phala-tdx`) documented in [Architecture](architecture.md#executionproof-phala-tier-base-schema). Bound `vm_config` JSON encoding to **256 KiB**; quotes, event logs, and string fields have fixed ceilings in `src/base/schemas/worker.py`.
- **R=1 full attested mode.** When the challenge exposes no assignable work units for a fully attested submission, BASE creates **zero** validator multi-replica work rows for that submission. Do not rely on BASE worker-plane R=2 reconciliation for that path; use challenge-owned miner-funded external eval and BASE shared proof helpers only where you integrate them.
- **Flag off.** Leave BASE and challenge attestation flags off for the legacy R=1 `own_runner` / env-launch path. Mixed topologies are unsupported.
- Challenge-owned review→eval and RA-TLS containers, images, and operator docs: **available after PR merge** in the agent-challenge repository.

## Build and publish

The generated CI workflow tests the challenge and pushes its Docker image to GHCR
Expand Down
5 changes: 5 additions & 0 deletions docs/challenges.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,3 +101,8 @@ execution routes.
Challenges export raw **hotkey** weights. The master aggregates and serves the
final vector; validators fetch and call `set_weights`. Challenges never submit
final UID vectors and never receive master database credentials.

## Agent Challenge Phala attestation notes

Private control-plane work (work units, fold, weights, bridge launch) stays on challenge-direct or master-internal channels, never on the public edge. Full attested mode evaluation is one miner-funded external eval (R=1) with **no** BASE validator multi-replica re-exec assignment for those units; cross-repo review→eval behavior is available after PR merge. See [Architecture: Agent Challenge Phala path](architecture.md#agent-challenge-phala-intel-tdx-path).
5. If attested routes are enabled, confirm the client hit an allowlisted review/eval/status path (not a private result or capability route).
14 changes: 14 additions & 0 deletions docs/master/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,3 +96,17 @@ Backup / restore / teardown scripts (Compose-only):
unsupported** for new installs. They must not be documented as the required master path
and must not be run against live production Swarm fabric from this guide. See
[deploy/swarm/README.md](../../deploy/swarm/README.md) for the explicit non-target banner.

## Agent Challenge attested proxy flag

The master proxy setting `master.agent_challenge_attested_routes_enabled` (default
**false**) selects the public agent-challenge topology:

- **Off:** legacy signed submission / env / launch passthrough (byte-identical).
- **On:** fail-closed allowlist for review/eval miner flows; private and result
routes never fall through the public edge.

Full attested evaluation ownership and score policy stay in the agent-challenge
service. See [Architecture](../architecture.md#agent-challenge-phala-intel-tdx-path)
and [Challenges](../challenges.md). Foundation install diffs for challenge-side
CVM credentials are out of scope here and must not appear in this guide.
7 changes: 6 additions & 1 deletion docs/miner/worker-plane.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,14 @@ This guide covers, for both **Lium** and **Targon**:
- [Monitoring your fleet](#monitoring-your-fleet)
- [Troubleshooting](#troubleshooting)

> The whole worker plane is gated behind a feature flag
> The whole (PRISM) worker plane is gated behind a feature flag
> (`compute.worker_plane_enabled` on the master, `worker_plane` in the prism config). With
> the flag off, nothing here applies and the subnet behaves exactly as before.
>
> **This guide is PRISM-only.** Agent Challenge Phala Intel TDX attestation (other
> challenge, separate flags, R=1 external eval, public-proxy allowlist) is **not** the
> miner GPU worker plane. See [Architecture: Agent Challenge Phala path](../architecture.md#agent-challenge-phala-intel-tdx-path)
> and the agent-challenge operator docs (available after PR merge).

---

Expand Down
13 changes: 13 additions & 0 deletions docs/security.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,3 +97,16 @@ and must not display raw text such as `BASE request failed with status 502`.
* LLM gateway services, routes, tokens, and provider clients
* Swarm install path for greenfield hosts (`install-swarm.sh`, Swarm secrets, overlays)
* Application-launched evaluator containers

## Phala attestation residual risk

BASE ships fail-closed Phala-tier verification helpers (schema bounds, measurement allowlist, `dcap-qvl` temp-file quote verify, park-vs-reject on verifier outage). Product posture is **cryptographically-anchored trust-but-audit**, not a claim of absolute TEE safety.

Residual risks operators should plan for:

* Hardware / microarchitectural TEE residual risk (including published TDX class attacks such as TEE.fail-style research) is not eliminated by software allowlists.
* Intel PCS / collateral freshness and `dcap-qvl` availability affect park vs reject; a parked result is intentionally not accepted.
* Challenge-owned score acceptance, RA-TLS key release, and CVM image pinning remain agent-challenge responsibilities (available after PR merge for cross-repo docs). BASE proxy must never expose those private challenge routes on the public edge.
* Flag-off (`agent_challenge_attested_routes_enabled=false`) preserves the legacy non-Phala public surfaces; operators enabling the flag must deploy the matching agent-challenge attested mode rather than mixing topologies.

* Public proxy strips sensitive headers (and, for agent-challenge attested mode, strips attested trust-shaped headers and prefixes).
2 changes: 2 additions & 0 deletions docs/validator/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -174,3 +174,5 @@ uv run pytest tests/unit/test_validator_compose_artifact.py tests/unit/test_vali

Start a live submit path only when wallet material on the host is intentionally
authorized for chain use. CI publishes Docker images to GHCR only from trusted events.

Agent Challenge Phala full-attested mode is also **not** a multi-replica validator re-exec path: evaluation is one miner-funded external eval (R=1) and BASE creates zero agent-challenge multi-replica work rows for that submission. Validators may still run sampled labelled replay audits and the legacy R=1 `own_runner` path when attestation flags are off. See [Architecture: Agent Challenge Phala path](../architecture.md#agent-challenge-phala-intel-tdx-path).
15 changes: 15 additions & 0 deletions src/base/cli_app/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@
from base.master.challenge_client import ChallengeClient
from base.master.challenge_work_source import (
HttpChallengeFoldTrigger,
HttpChallengeReplayClient,
HttpChallengeReplaySource,
HttpChallengeResultForwarder,
HttpChallengeWorkSource,
)
Expand Down Expand Up @@ -586,6 +588,16 @@ def _master_orchestration_driver(
timeout_seconds=settings.master.challenge_timeout_seconds,
retries=settings.master.challenge_retries,
),
replay_source=HttpChallengeReplaySource(
registry,
timeout_seconds=settings.master.challenge_timeout_seconds,
retries=settings.master.challenge_retries,
),
replay_result_forwarder=HttpChallengeReplayClient(
registry,
timeout_seconds=settings.master.challenge_timeout_seconds,
retries=settings.master.challenge_retries,
),
fold_trigger=HttpChallengeFoldTrigger(
registry,
timeout_seconds=settings.master.challenge_timeout_seconds,
Expand Down Expand Up @@ -1157,6 +1169,9 @@ def master_proxy(config: Path = typer.Option(Path("config/master.example.yaml"))
),
identity_resolver=ValidatorIdentityResolver(cache=runtime.identity_cache),
readiness_probes=(database_probe,),
agent_challenge_attested_routes_enabled=(
settings.master.agent_challenge_attested_routes_enabled
),
)
endpoint = f"{settings.master.proxy_host}:{settings.master.proxy_port}"
typer.echo(f"Starting proxy API on {endpoint}")
Expand Down
3 changes: 3 additions & 0 deletions src/base/config/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ class MasterSettings(BaseModel):
upload_require_registered_hotkey: bool = True
# ss58 hotkeys accepted without on-chain registration (QA/allowlist; empty in prod)
upload_extra_registered_hotkeys: list[str] = Field(default_factory=list)
# Opt-in canonical Agent Challenge review/eval proxy topology. OFF preserves
# the legacy signed submission/env/launch proxy behavior byte-for-byte.
agent_challenge_attested_routes_enabled: bool = False
# Validator coordination plane (architecture.md sec 4). The proxy serves the
# hotkey-signed register/heartbeat/pull/progress/result routes, returns
# ``validator_heartbeat_interval_seconds`` to validators, marks a validator
Expand Down
Loading
Loading