The specific case of deploying an application: taking a trained domain
off-platform as a read-only container that answers claims with the same verdicts, a policy disposition and a
signed evidence package. Use it when a system must verify claims without reaching the platform, or when an
auditor wants an artifact whose identity they can pin. It is a standalone verifier (earl-verify), not
the persistent runtime: it has no memory, no planning, no observation, and it never learns.
VERIFIED / CONTESTED / UNCERTAIN / HALLUCINATED on claims, deterministically,
with evidence, at a network boundary you control.POST /tuning-runs/{id}/freeze-domain
{"codename": "journal-entry-review-v1", "description": "…", "runtime_port": 8410}
Requires training_succeeded. The package (~98 MB) holds the grounded KB, the trained checkpoint, the
earl-verify binary for the container platform, a small FastAPI server, the policy active at that moment
and its evaluator, and identity.json: the substrate identity, a sha256 over the engine release and
commit, the exact binary, the KB fingerprint, every checkpoint file and the policy hash. Editing the policy
afterwards never changes a frozen package. Frozen packages are listed by GET /frozen-domains.
POST /deployments {"name": "journal-entry-review-live", "frozen_domain_package_id": 1, "runtime_port": 8410}
The platform extracts the package and runs docker compose up --build -d for it. Poll
GET /deployments/{id} until status is running (about 20 s) or failed (operation_log carries the
build output). GET /deployments/{id}/health and the container's own GET /identity both answer with the
substrate identity. Stop, start and tail logs with the /deployments/{id}/… routes in the
API walkthrough §11.
To run the container elsewhere, download the package (GET /deployments/{id}/download) and
docker compose up it on the target host; no platform is needed there.
Directly against the container:
curl -X POST http://host:8410/verify -H 'Content-Type: application/json' \
-d '{"candidate_text": "A manual entry requires a controller approval"}'
The field is candidate_text; one claim per line. Each row carries verdict, endpoints,
endpoints_asserted, predicate, passive, negated, asserted_by, asserted_source, grounding,
contradictions, demotion_reason and the policy disposition with its matched rules — the same fields the
SDK path reports, so a verdict is checkable, not just a label.
Through the platform (POST /deployments/{id}/verify, same body, your bearer token) you get the
container's reply unchanged, substrate_identity_mismatch, and a signed evidence package for the
exchange; add expectations and the platform reports expected-versus-actual per claim.
curl -s https://platform/api/evidence/public-key # key_id to pin
curl -s https://platform/api/evidence/verifier > verify_evidence_package.py
python verify_evidence_package.py evidence-<id>.json --pin-key <key_id>
Ten checks (format, signature, key, issuer pin, payload hash, candidate-text hash, identity record); exit 0 only when all pass. A package with one altered character fails. See evidence packages and policy for what a signature does and does not establish: integrity and attribution, never the truth of the evidence.
substrate_identity_mismatch: true.No memory, no planning, no observation, no learning, no authority beyond the policy baked into it. The
verdict is a directed, typed assertion check against the frozen corpus, not truth; the register states
per capability what is qualified and what is not (evidence.evaluate is not qualified for unattended
approval decisions).