Guides
Verify before reliance
Read a counterparty’s public ECZ-ID record live, apply your own policy to it, and hold the line in CI. Everything on this page runs today with no account.
Live in production and publicly readable, with no account and no key. Measured read-only on 2026-10-10.
Accountability Chain:IdentityCurrent stateRe-verify
1. Read the record
One HTTP GET, no key. The machine record lives on the API host; the human page lives on the Resolver host.
curl -s https://api.ecocitizenz.com/api/p/ECZ-GB-RBS1NW.jsonRead resolver_v2.state, resolver_v2.binding, resolver_v2.reliance and resolver_v2.machine_policy. The record lists the fields machines should use in machine_policy.machines_should_use; prefer those over anything else in the payload.
2. Put your policy on it
// Read live. Never cache a record; never treat absence as a verdict.
async function relianceCheck(eczId) {
const res = await fetch(`https://api.ecocitizenz.com/api/p/${eczId}.json`);
if (res.status === 404) {
// No public record. Not unsafe, not untrusted, not a failed check.
return { record: null, allow: false, reason: 'NO_PUBLIC_ECZ_ID_FOUND', retryable: false };
}
if (!res.ok) {
// 429, 503 and friends: unreadable is not absent. Retry; do not downgrade.
return { record: null, allow: false, reason: 'RESOLVER_UNREADABLE', retryable: true };
}
const v2 = (await res.json()).resolver_v2;
const failClosed = v2.machine_policy.fail_closed_states;
// Your policy. ECZ-ID reports state; it does not decide for you.
const allow =
v2.state.lifecycle_state === 'ACTIVE' &&
!failClosed.includes(v2.state.lifecycle_state) &&
!failClosed.includes(v2.binding.state);
return { record: v2, allow, reason: v2.state.reliance_level, retryable: false };
}- Read live, because state moves and records are served
no-store. - Treat unreadable as unreadable: a 429 or 503 is a retry, never a downgrade of the counterparty.
- Treat absence as absence: no record is not unsafe, not untrusted and not a failed check.
- Fail closed on every state in
machine_policy.fail_closed_statesfor high-risk actions.
3. Or use the published verifier
The ECZ-ID MCP Verifier is free, read-only and local-first. It classifies a target (an ECZ-ID, an MCP endpoint, an agent manifest, an API URL, a repository, a package or a container image), reads public Resolver posture where one applies, and returns a deterministic result. It never uploads source, secrets or telemetry, and never writes truth.
npx -y @ecocitizenz/ecz-id-mcp-verifier check --target ECZ-GB-RBS1NW{
"verifier_version": "0.9.0",
"target": "ECZ-GB-RBS1NW",
"target_type": "ecz_id",
"policy_mode": "OPEN",
"result_state": "RESOLVER_VERIFIABLE",
"reason_codes": [],
"resolver_url": "https://resolver.ecocitizenz.org/p/ECZ-GB-RBS1NW",
"machine_json_url": "https://api.ecocitizenz.com/api/p/ECZ-GB-RBS1NW.json",
"primary_action": "VIEW_RESOLVER_PROOF",
"verifier_writes_truth": false,
"local_policy_decides": true,
"recheck_before_reliance": true,
"exit_code": 0
}| Policy | Behaviour | Measured |
|---|---|---|
OPEN | Reports. Missing proof exits 0. | ECZ-ZZ-NOPE00 → NO_PUBLIC_RESOLVER_PROOF_FOUND, exit 0 |
PREFER | Reports and recommends. Your policy chooses. | — |
REQUIRE | Missing or unresolved proof exits 1. | ECZ-ZZ-NOPE00 → NO_PUBLIC_RESOLVER_PROOF_FOUND, exit 1 |
4. Hold the line in CI
- uses: Ecocitizenz/ecz-id-mcp-verifier@v0.9.0
with:
target: ${{ env.COUNTERPARTY_ECZ_ID }}
policy: REQUIREThe Action reads only. It does not mutate your repository, upload your source or secrets, or emit telemetry. Full exit-code semantics are on the result states reference.
Related
This page is explanation, not authority. Current state is only ever the live Resolver record. Live facts on this page were measured read-only on 2026-10-10.
