Skip to content

Guided flow · ECZ-ID Service & Workload Passport™

Service & Workload guided flow

Carry an enduring service through the Accountability Chain: its identity, deployment and operator, authority and delegation, a machine-to-machine action, current state and Intent, the result, and the Receipt and re-verify.

  1. Workload identity
  2. Deployment and operator
  3. Authority and delegation
  4. Machine-to-machine action
  5. State and Intent
  6. Result
  7. Receipt and re-verify

Steps at a glance · what is live today

  1. 01Identify the workloadLive · public
  2. 02Connect deployment and operatorLive · public
  3. 03Establish authority and delegationLive · signed in
  4. 04Check the other machine firstLive · public
  5. 05Read state, carry IntentLive · signed in
  6. 06Record the resultYour system
  7. 07Receipt and re-verifyNo public retrieval

Step 01 of 7

Identify the workload#

Identity

Live · public

Live in production and publicly readable, with no account and no key.

GoalGive the service a free ECZ-ID Passport and declare it where its ecosystem already looks.

Why it mattersOne enduring logical service is one Passport. Pods, replicas, processes and regions are never Passports; environments, regions and clusters are bindings.

Prerequisites

  • An enduring service you operate.
  • One identifier: its workload name, its service origin or its repository.

Example

yamlIllustrative deployment annotation. Use the values your TrustOps console shows.
apiVersion: apps/v1
kind: Deployment
metadata:
  name: settlement-service
  annotations:
    ecz_id: ECZ-GB-EXAMPL::SERVICE_WORKLOAD_PASSPORT-AB12CD
    resolver_backlink: https://resolver.ecocitizenz.org/p/ECZ-GB-EXAMPL::SERVICE_WORKLOAD_PASSPORT-AB12CD

Check

bashCheck it from the relying side. No install, no account.
npx -y @ecocitizenz/ecz-id-mcp-verifier check --target docker.io/library/nginx:1.27 --target-type container_image

Expected output

jsonMeasured 2026-10-09 · abridged
{
  "target_type": "container_image",
  "policy_mode": "OPEN",
  "result_state": "NO_PUBLIC_RESOLVER_PROOF_FOUND",
  "reason_codes": ["NO_PUBLIC_RESOLVER_PROOF_FOUND", "RESOLVER_READ_ONLY",
                   "LOCAL_POLICY_DECIDES"],
  "primary_action": "CHOOSE_OPERATOR_PATH",
  "exit_code": 0
}

A public image with no ECZ-ID, reported as absence. Your workload declares its ECZ-ID in its deployment manifest or annotations.

What this proves

  • That the machine has a persistent, publicly resolvable identity under an accountable organisation, once issued and declared.

What this does not prove

  • That the machine is safe, secure, correct or verified. A free Passport never claims that.
  • Control of any native identity. A declaration is a pointer; only a proven binding proves.

Next: Connect deployment and operator →

Step 02 of 7

Connect deployment and operator#

Identity

Live · public

Live in production and publicly readable, with no account and no key.

GoalTie the workload’s deployments to its one identity, and its identity to its operator.

Why it mattersYour cloud and cluster identities stay authoritative inside their providers. ECZ-ID adds one enduring identity around them, so a relying service reaches the operator whichever deployment it meets.

Prerequisites

  • The workload’s Passport.
  • Your deployment manifests.

Example

yamlIllustrative deployment annotation. Use the values your TrustOps console shows.
metadata:
  name: settlement-service
  annotations:
    ecz_id: ECZ-GB-EXAMPL::SERVICE_WORKLOAD_PASSPORT-AB12CD
    resolver_backlink: https://resolver.ecocitizenz.org/p/ECZ-GB-EXAMPL::SERVICE_WORKLOAD_PASSPORT-AB12CD

Workload identity classes (cloud roles, workload identities, SPIFFE IDs, service accounts, OIDC issuers) are binding classes the contract defines, not claims of live provider integrations.

What this proves

  • Where the operator says each deployment belongs.

What this does not prove

  • Control of a cloud identity until a binding is proven.

Next: Establish authority and delegation →

Step 03 of 7

Establish authority and delegation#

AuthorityDelegation

Live · signed-in operation in TrustOps

Live in production and operated by the account holder, signed in, through the TrustOps Dashboard.

GoalHave an owner or admin authorise an ECZ-ID Intent for the service in the TrustOps Dashboard.

Why it mattersAuthority is who authorised the work, recorded where a stranger can later ask. A Passport, a payment or a binding never grants it.

Prerequisites

  • The service's child Passport.
  • An ECZ-ID Intent plan, purchased in TrustOps.
  • An owner or administrator to authorise. Nobody authorises their own request.

Example

jsonIllustrative. The authorisation block Core records on an Intent; placeholder values.
"authorisation": {
  "kind": "DELEGATION_CHAIN",
  "principal_ref": "user:finance-admin-01",
  "principal_role": "ADMIN",
  "authorised_at": "2026-10-11T09:14:02Z",
  "evidence_digest": "sha256:<64 hex>",
  "chain": [{ "intent_id": "INT-0000000000PARENT00", "version": 2 }]
}

What this proves

  • Who authorised the service's work, in what role, and when, as ECZ-ID Core recorded it.
  • That a delegated Intent is bounded by its parent: Core refuses a delegation that widens scope.

What this does not prove

  • Any permission in your own access systems. OAuth scopes and API keys stay yours.
  • That runtime actions stay inside the bounds. That needs a decision before the action.
  • Anything public: the public Intent disclosure is not enabled.

Next: Check the other machine first →

Step 04 of 7

Check the other machine first#

IdentityCurrent state

Live · public

Live in production and publicly readable, with no account and no key.

GoalBefore a machine-to-machine call with consequence, resolve the service you are calling.

Why it mattersService meshes authenticate connections. They do not say who answers for the service on the other end, or whether its public state still supports reliance.

Prerequisites

  • The other service’s ECZ-ID.

Example

jsRuns today. Node 18+.
// Runs today: your own policy over live Resolver state.
async function mayProceed(eczId) {
  const res = await fetch('https://api.ecocitizenz.com/api/p/' + eczId + '.json');
  if (res.status === 404) return { ok: false, why: 'NO_PUBLIC_ECZ_ID_FOUND' };
  if (!res.ok) return { ok: false, why: 'RESOLVER_UNREADABLE', retry: true };
  const v2 = (await res.json()).resolver_v2;
  const failClosed = v2.machine_policy.fail_closed_states;
  const ok = v2.state.lifecycle_state === 'ACTIVE'
    && !failClosed.includes(v2.state.lifecycle_state)
    && !failClosed.includes(v2.binding.state);
  return { ok, why: v2.state.reliance_level };
}

What this proves

  • The counterparty service’s operator and current published state.

What this does not prove

  • That your call is authorised. That is your Intent.
  • An Intent-bounded decision on the call. That is IntentControl: its interface is release-gated and not callable, and commercially it is coming soon in TrustOps and not yet on sale.

Next: Read state, carry Intent →

Step 05 of 7

Read state, carry Intent#

Current stateIntent

Live · signed-in operation in TrustOps

Live in production and operated by the account holder, signed in, through the TrustOps Dashboard.

GoalState what the service is authorised to do, within what bounds and for how long, and make every consequential action name that Intent.

Why it mattersPermission says what a credential can reach. Intent says what this actor may do. The gap between them is where a permitted action can still be one nobody authorised.

Prerequisites

  • An authorised ECZ-ID Intent in force (state ACTIVE).
  • A single choke point in your code where consequential actions pass.

Example

jsonIllustrative, abridged. Field names from the Core contract ecz.intent.v1; placeholder identifiers.
{
  "schema": "ecz.intent.v1",
  "actor": { "kind": "ECZ_PASSPORT", "ecz_id": "ECZ-GB-EXAMPL::SERVICE_WORKLOAD_PASSPORT-AB12CD", "family": "SERVICE_WORKLOAD" },
  "objective_summary": "Post settlement entries to the ledger service",
  "constraints": {
    "actions": { "permitted": ["ledger:post_entry"], "excluded": ["ledger:reverse_*"] },
    "destinations": { "permitted": ["ledger.internal.example"], "excluded": [] },
    "data_classes_denied": ["personal_data"],
    "rate": { "max_actions": 5000, "window_seconds": 3600 }
  },
  "window": { "not_before": "2026-10-12T00:00:00Z", "expires_at": "2026-10-19T00:00:00Z" },
  "state": "ACTIVE"
}

In your system

jsIllustrative. Your audit log, written before each consequential action.
// Your audit log: one entry per consequential action, written before it runs.
// ECZ-ID defines the Intent reference; the rest belongs to your system.
log.info('consequential_action', {
  actor_ecz_id: 'ECZ-GB-EXAMPL::SERVICE_WORKLOAD_PASSPORT-AB12CD',
  intent_ref: { intent_id: 'INT-0000000000EXAMPLE0', version: 3 },
  request_id: crypto.randomUUID(),
  action: 'ledger:post_entry',
  destination: 'ledger.internal.example',
});

Request identifiers, nonces and correlation IDs belong to the request, not the Intent. ECZ-ID defines no header for carrying an Intent reference over arbitrary protocols, and this site does not invent one.

What this proves

  • What was authorised, as a versioned record with its bounds and window.

What this does not prove

  • That any action stayed inside those bounds. Holding an Intent identifier authorises nothing by itself.
  • That a sandbox Intent covers production. It never does.

Next: Record the result →

Step 06 of 7

Record the result#

Action

Runs in your system

This happens in the integrator’s own system.

GoalRecord what the call did, in your own system.

Why it mattersThe result belongs to the services involved. ECZ-ID never executes or proxies the call.

Prerequisites

  • Your audit log entry from the Intent step.

What this proves

  • What your service did, as it recorded it.

What this does not prove

  • That the other service processed the call correctly.

Next: Receipt and re-verify →

Step 07 of 7

Receipt and re-verify#

ReceiptEvidenceRe-verify

Recorded · no public retrieval

ECZ-ID Core records it, but public, unauthenticated retrieval and verification are not enabled.

GoalKeep a record of what the service did, and know what ECZ-ID publishes about it.

Why it mattersReceipts record what Core recorded about the service’s decisions and events. A Receipt proves what the recording system recorded; it does not prove every real-world assertion behind it.

Prerequisites

  • Your own audit log entry from the Intent step.

Example

bashRead the evidence block of a public record.
curl -s https://api.ecocitizenz.com/api/p/ECZ-GB-RBS1NW.json

Expected output

jsonMeasured 2026-10-09 · resolver_v2.evidence, abridged
"evidence": {
  "public_receipts_count": 0,
  "public_receipt_state": "NO_PUBLIC_RECEIPT",
  "public_receipt_retrievable": false,
  "receipt_retrieval_state": "NONE_PUBLISHED",
  "recorded_receipts_count": 1,
  "reason_codes": ["RECEIPTS_RECORDED_NOT_PUBLICLY_RETRIEVABLE"]
}

Recorded is not published. Decide on evidence.public_receipt_state and evidence.public_receipt_retrievable, the fields the record lists for machines.

What this proves

  • Whether Core has recorded receipts for the subject, and whether any are publicly retrievable.

What this does not prove

  • What any receipt says. Public retrieval and public verification are not enabled.
  • That an action happened or succeeded. An allow is not a result, and a decision receipt is not an action receipt.

Where next

This page is explanation, not authority. Current state is only ever the live Resolver record. Commands were run read-only on 2026-10-10; illustrative examples are labelled.