SDK docs · sdk/03

Service mode & the OpenAPI contract

Run the same SDK as an HTTP service inside your perimeter, so a backend in any language verifies through a frozen, versioned OpenAPI contract.

The contract

Service mode lets a backend in any language use the same nine-condition pipeline: the SDK runs inside a thin first-party HTTP service you deploy next to your backend, and transport-only clients call it, TypeScript today and further languages as demand appears. It is embedded mode plus transport, with the same checks, no extra options and no “lite” path.

verifier-service.v1 — a versioned OpenAPI 3.1 document, frozen by a published decision record (see the verifier service contract record). Four operations:

OperationMethod & pathPurpose
createChallengePOST /v1/challengesIssue one signed presentation challenge bound to the deployment's registered identity
validatePresentationPOST /v1/presentationsRun the nine conditions; returns the decision
getBuildInfoGET /v1/build-infoThe artifact's release pins (versions — never secrets) and, since 1.6.0, the source it was built from (source_revision, release)
checkStatusRootPOST /v1/status-root-checksIs a status root still the issuer's current, unexpired one? (1.5.0 — what a session built on a decision re-checks)

Semver at the contract level: decision semantics or reason-vocabulary changes are major; additive surface is minor (current: 1.6.0 in production, 1.7.0 on the public testnet, where a challenge may ask for profile: "agent_v2"; 1.1.0 added the conformance-suite pin to build-info).

Deliberately absent from the wire — these are invariants, not parameters: any lifetime setting (10 s is a constant), any skip flag for the conditions, and max_height_lag (local deployment policy, configured at service start — a compromised web tier must not be able to widen staleness acceptance).

Decision vs transport error

  • Anything parseable into the challenge-response schema flows through the pipeline and returns HTTP 200 with a decision — accept or reject — plus exactly one decision record server-side.
  • HTTP 400 exists only for bodies that cannot be parsed into the schema at all (no session identity exists, so no decision record is possible).
  • HTTP 422 policy_refused (contract 1.2.0): the challenge was refused before it existed — the body carries the agent-profile code that explains why (scope_value_not_in_vocabulary, policy_axis_uncovered, pseudonym_verifier_mismatch, pseudonym_required or unexpired_required); no challenge and no session exist.
  • HTTP 503 means the service refused to issue a challenge because proven chain state was unavailable — fail closed; retry, never work around.

Deploying

Before you deploy:

  • Identity is deployment configuration — origin, verifier identity and request key — bound to your on-chain registrations and never accepted from HTTP callers.
  • Challenge signing is your key custody. The service signs challenges with a request signer you provide, backed by hardware-protected keys.
  • The bundled runner is a reference server for integration; in production, front it with your own web tier.
  • The service holds no state of its own: durability lives in the replay store and the decision log you configure.

Trust boundaries, restated

Your service instance is part of your verifier. Deploy it inside your perimeter and point your transport clients at it, never at anyone else’s: the acceptance decision is your obligation as a registered verifier, and handing the service to someone else hands them that decision.