DelegusDocsv0.3 rc1

Docs/SDK and CLI

Reference

SDK and CLI reference

@delegus/sdk 0.3.4, the next release (npm has 0.3.3) for Node 22 and later. Every signature on this page is read from the package's TypeScript source at build time, and the build fails if the package does not typecheck, so what you see here is what the code exports.

The person who gives an agent its authority stays in charge of it. They decide what it may do, one revoke takes it back everywhere, and every decision comes with a signed receipt.

Status and license. The SDK is built from the v0.2 and v0.3 (rc1) specifications and published on npm as @delegus/sdk, alongside @delegus/core (the protocol engine) and @delegus/conformance (the vectors and CLI); all are Apache-2.0. This reference is generated from the source on the main branch, which can be ahead of the version on the registry; the version at the top of this page is the source version. The Delegus service is not open source. The integration surface is the one the integrate page shows.

Client#

The one object a relying party or a Principal talks to Delegus through.

Delegusclass#

packages/sdk/src/client.ts

ts
class Delegus {
  new (opts?: DelegusOptions): Delegus
  transport: Transport
  // The RP's own public base URL (for Proof binding and the MCP tool URI); not a secret.
  publicBaseUrl: string | null
  // GET /me: what this client's API key resolves to (subject, role, settings).
  me(): Promise<JsonObject>
  // GET /healthz: true when Delegus reports every backing service reachable.
  health(): Promise<{ ok: boolean; env?: string; did?: string; }>
  apiKeys: { list: (subject?: string) => Promise<JsonObject>; create: (label?: string, subject?: string) => Promise<JsonObject>; revoke: (keyId: string, subject?: string) => Promise<JsonObject>; }
  // Express-style middleware for an ordinary HTTP API (http.ts): every request is checked against the caller's
  // Grant and Proof, bound to the exact method and URL, with the Action built from the body, path and query
  // through a route map. Mount before the routes it protects.
  http(opts?: HttpMiddlewareOptions): ReturnType<typeof createHttpMiddleware>
  mcp(opts?: McpOptions): McpMiddleware
  // POST /verify. Returns the signed Receipt for ALLOW and DENY alike.
  // 
  // The API answers with the receipt of the relying party's own profile, so by
  // default (`protocol: "auto"`) the SDK reads `receipt_version` from inside the
  // signed receipt payload (never from an unsigned member) and checks the
  // response accordingly:
  //   - delegus-receipt-v1: the v0.2 path, after checking the receipt
  //     signature under the service's published keys (the same key source and
  //     rules as v2: EdDSA, the receipt's kid, a `#receipt-<n>` key of the
  //     service DID; did:web:delegus.ai in production) and that the response
  //     body is exactly the signed payload;
  //   - delegus-receipt-v2: the v0.3-rc1 checks in full (parseVerifyResponseV3):
  //     the signature under the service's published keys, the body equal to
  //     the payload, `authority_commitment` opened to `authority` (and, when
  //     pinned, `capability_key_commitment` with `capability_key_opening`),
  //     `relies_on`, `requires` and `opening`;
  //   - anything else, or no readable receipt: ResponseIntegrityError.
  // Either way, after the signature check the receipt must be about this
  // request: its signed grant_hash and proof_hash must be sha256 over the
  // Grant and Proof sent (and, on v2, request_hash over the Action when present).
  // `requires` is sent as given; a v1 receipt in answer to it fails closed.
  // 
  // `protocol: "v0.2"` and `protocol: "v0.3"` pin one profile; a receipt of the
  // other one throws ResponseIntegrityError naming the pin and what came back.
  // Every failure is fail closed: do not act on the request.
  verify(req: VerifyRequestV3): Promise<VerifyResponseV3>
  // POST /verify. Returns the signed Receipt for ALLOW and DENY alike.
  // 
  // The API answers with the receipt of the relying party's own profile, so by
  // default (`protocol: "auto"`) the SDK reads `receipt_version` from inside the
  // signed receipt payload (never from an unsigned member) and checks the
  // response accordingly:
  //   - delegus-receipt-v1: the v0.2 path, after checking the receipt
  //     signature under the service's published keys (the same key source and
  //     rules as v2: EdDSA, the receipt's kid, a `#receipt-<n>` key of the
  //     service DID; did:web:delegus.ai in production) and that the response
  //     body is exactly the signed payload;
  //   - delegus-receipt-v2: the v0.3-rc1 checks in full (parseVerifyResponseV3):
  //     the signature under the service's published keys, the body equal to
  //     the payload, `authority_commitment` opened to `authority` (and, when
  //     pinned, `capability_key_commitment` with `capability_key_opening`),
  //     `relies_on`, `requires` and `opening`;
  //   - anything else, or no readable receipt: ResponseIntegrityError.
  // Either way, after the signature check the receipt must be about this
  // request: its signed grant_hash and proof_hash must be sha256 over the
  // Grant and Proof sent (and, on v2, request_hash over the Action when present).
  // `requires` is sent as given; a v1 receipt in answer to it fails closed.
  // 
  // `protocol: "v0.2"` and `protocol: "v0.3"` pin one profile; a receipt of the
  // other one throws ResponseIntegrityError naming the pin and what came back.
  // Every failure is fail closed: do not act on the request.
  verify(req: VerifyRequestV2): Promise<Receipt>
  // POST /verify. Returns the signed Receipt for ALLOW and DENY alike.
  // 
  // The API answers with the receipt of the relying party's own profile, so by
  // default (`protocol: "auto"`) the SDK reads `receipt_version` from inside the
  // signed receipt payload (never from an unsigned member) and checks the
  // response accordingly:
  //   - delegus-receipt-v1: the v0.2 path, after checking the receipt
  //     signature under the service's published keys (the same key source and
  //     rules as v2: EdDSA, the receipt's kid, a `#receipt-<n>` key of the
  //     service DID; did:web:delegus.ai in production) and that the response
  //     body is exactly the signed payload;
  //   - delegus-receipt-v2: the v0.3-rc1 checks in full (parseVerifyResponseV3):
  //     the signature under the service's published keys, the body equal to
  //     the payload, `authority_commitment` opened to `authority` (and, when
  //     pinned, `capability_key_commitment` with `capability_key_opening`),
  //     `relies_on`, `requires` and `opening`;
  //   - anything else, or no readable receipt: ResponseIntegrityError.
  // Either way, after the signature check the receipt must be about this
  // request: its signed grant_hash and proof_hash must be sha256 over the
  // Grant and Proof sent (and, on v2, request_hash over the Action when present).
  // `requires` is sent as given; a v1 receipt in answer to it fails closed.
  // 
  // `protocol: "v0.2"` and `protocol: "v0.3"` pin one profile; a receipt of the
  // other one throws ResponseIntegrityError naming the pin and what came back.
  // Every failure is fail closed: do not act on the request.
  verify(req: VerifyRequestAuto): Promise<VerifyResult>
  // POST /verify. Returns the signed Receipt for ALLOW and DENY alike.
  // 
  // The API answers with the receipt of the relying party's own profile, so by
  // default (`protocol: "auto"`) the SDK reads `receipt_version` from inside the
  // signed receipt payload (never from an unsigned member) and checks the
  // response accordingly:
  //   - delegus-receipt-v1: the v0.2 path, after checking the receipt
  //     signature under the service's published keys (the same key source and
  //     rules as v2: EdDSA, the receipt's kid, a `#receipt-<n>` key of the
  //     service DID; did:web:delegus.ai in production) and that the response
  //     body is exactly the signed payload;
  //   - delegus-receipt-v2: the v0.3-rc1 checks in full (parseVerifyResponseV3):
  //     the signature under the service's published keys, the body equal to
  //     the payload, `authority_commitment` opened to `authority` (and, when
  //     pinned, `capability_key_commitment` with `capability_key_opening`),
  //     `relies_on`, `requires` and `opening`;
  //   - anything else, or no readable receipt: ResponseIntegrityError.
  // Either way, after the signature check the receipt must be about this
  // request: its signed grant_hash and proof_hash must be sha256 over the
  // Grant and Proof sent (and, on v2, request_hash over the Action when present).
  // `requires` is sent as given; a v1 receipt in answer to it fails closed.
  // 
  // `protocol: "v0.2"` and `protocol: "v0.3"` pin one profile; a receipt of the
  // other one throws ResponseIntegrityError naming the pin and what came back.
  // Every failure is fail closed: do not act on the request.
  verify(req: AnyVerifyRequest): Promise<VerifyResult>
  // OpenID AuthZEN Access Evaluation over /verify (for PEPs such as MCP servers):
  // subject {type:"agent", id, properties:{grant, proof}}, action {name, properties}, resource {type, id}.
  // `decision` is true only for ALLOW; `context.reason` is the Delegus reason, `context.receipt` the signed receipt.
  evaluate(req: { subject: { type: string; id: string; properties?: JsonObject; }; action: { name: string; properties?: JsonObject; }; resource: { type: string; id: string; properties?: JsonObject; }; context?: JsonObject; }): Promise<{ decision: boolean; context: JsonObject; }>
  outcomes: { report: (receiptId: string, event: OutcomeEvent) => Promise<JsonObject>; }
  decisions: { get: (receiptId: string) => Promise<DecisionRecord>; chain: (receiptId: string) => Promise<ChainInput>; list: (opts?: ListOptions & { rp?: string; keyId?: string; decision?: "ALLOW" | "DENY"; reason?: string; principal?: string; grantId?: string; }) => Promise<Page<JsonObject>>; }
  // GET /decisions/export as NDJSON rows (decision summary + full receipt + outcome ledger); one page, cursor in `next_cursor`.
  decisionsExport(opts?: ListOptions & { rp?: string; keyId?: string; decision?: "ALLOW" | "DENY"; reason?: string; principal?: string; grantId?: string; }): Promise<Page<JsonObject>>
  // GET /decisions/{receipt_id}/disclosure (v0.3-rc1 §R.5): the disclosure
  // package for a v2 receipt, for its relying party or principal only (404 for
  // anyone else, and for a receipt with nothing to disclose). It carries the
  // openings of the receipt's commitments, the consumption snapshot when the
  // receipt pins one, and per dependency entry what reproduces it (the prior
  // receipt and its opening only for a caller entitled to that receipt). Pass it
  // as `disclosure` to receipts.verifyV2Entitled; nothing is verified here.
  disclosure(receiptId: string): Promise<DisclosurePackage>
  // GET /decisions/stats: decisions and outcomes rolled up per Principal.
  decisionsStats(opts?: { since?: string; until?: string; rp?: string; principal?: string; }): Promise<JsonObject>
  // The Principal directory (§2.1 trust network): who is registered and verified, since when, with which keys. Any live key.
  principals: { list: (opts?: { kind?: "managed" | "hosted"; state?: "verified" | "unverified"; orgId?: string; limit?: number; cursor?: string; }) => Promise<Page<JsonObject>>; get: (did: string) => Promise<JsonObject>; }
  grants: { list: (opts?: ListOptions & { principal?: string; agent?: string; state?: "active" | "revoked"; }) => Promise<Page<JsonObject>>; }
  // GET /usage: verifies per UTC day (`byKey` adds a per-API-key breakdown).
  usage(opts?: { since?: string; until?: string; rp?: string; principal?: string; keyId?: string; byKey?: boolean; }): Promise<JsonObject>
  // GET /audit: newest first; own actions for a subject key, the org and its members for an org key, everything for admin.
  audit(opts?: ListOptions & { actor?: string; action?: string; target?: string; }): Promise<Page<JsonObject>>
  orgs: { create: (opts: { slug: string; name: string; }) => Promise<Org>; selfServe: (opts: { slug: string; name: string; adminEmail: string; clientIp?: string; }) => Promise<SelfServeBundle>; selfServeStarter: (rpDid: string) => Promise<SelfServeStarter>; selfServeFirstReceipt: (rpDid: string) => Promise<Receipt>; entitlement: (orgId: string) => Promise<Entitlement>; setEntitlement: (orgId: string, e: EntitlementRequest) => Promise<Entitlement>; get: (orgId: string) => Promise<Org & { members: JsonObject[]; }>; addMember: (orgId: string, did: string) => Promise<JsonObject>; apiKeys: { list: (orgId: string) => Promise<JsonObject>; create: (orgId: string, role: "read" | "admin", label?: string) => Promise<JsonObject>; revoke: (orgId: string, keyId: string) => Promise<JsonObject>; }; principal: (did: string) => Principal; }
  // Principal onboarding (admin token, or an org:admin key, which onboards into its own org). `org` here is the managed-Principal DID path `did:web:<domain>:org:<slug>`; the customer account is `orgs`.
  org: { create: (opts: { slug: string; signer?: Signer; keyId?: string; orgId?: string; }) => Promise<CreatedOrg>; register: (opts: { did: string; kid?: string; signer?: Signer; orgId?: string; }) => Promise<{ principal: Principal; apiKey: string; verification: JsonObject; didDocumentResolved: boolean; }>; }
  relyingParties: { create: (opts: { slug?: string; did?: string; name?: string; proofWindowSeconds?: number; orgId?: string; profile?: "delegus-base-v1" | "delegus-base-v3" | "delegus-base-v4-draft"; }) => Promise<{ did: string; apiKey: string; client: Delegus; }>; get: (did: string) => Promise<JsonObject>; update: (did: string, patch: { name?: string; proofWindowSeconds?: number; verifyRateLimitPerMinute?: number; }) => Promise<JsonObject>; }
  checkpoints: { get: (day?: string | "latest") => Promise<JsonObject>; leaves: (day: string) => Promise<string[]>; verify: (day?: string | "latest", keys?: Readonly<Record<string, Uint8Array<ArrayBufferLike>>> | undefined) => Promise<{ ok: boolean; day: string; root: string; treeSize: number; detail?: string; checkpoint?: Checkpoint; }>; contains: (day: string, receiptIds: readonly string[]) => Promise<{ present: string[]; missing: string[]; }>; }
  evidence: { get: (hash: string) => Promise<Uint8Array | null>; }
  // The service DID document's keys by kid (receipt and status-list keys). Only
  // methods of the document's own DID count (`<doc.id>#…`, controller absent or
  // `doc.id`), so a receipt's kid is bound to that DID; which fragment may sign
  // what (`#receipt-<n>`, `#status-<n>`) is checked at verification. Against the
  // production API the document must be `did:web:delegus.ai`.
  serviceKeys(): Promise<TrustedKeys>
  receipts: { verify: (receiptJws: string, keys: Readonly<Record<string, Uint8Array<ArrayBufferLike>>>, did?: string) => ReceiptVerification; verifyV2Public: (receiptJws: string, opts?: { body?: Record<string, unknown>; keys?: Readonly<Record<string, Uint8Array<ArrayBufferLike>>>; did?: string; }) => Promise<PublicVerificationV2>; verifyV2Entitled: (receiptJws: string, opts?: Omit<Parameters<typeof verifyReceiptV2Entitled>[0], "receipt" | "keys"> & { keys?: Readonly<Record<string, Uint8Array<ArrayBufferLike>>>; }) => Promise<EntitledVerificationV2>; inclusion: (receiptId: string, keys?: Readonly<Record<string, Uint8Array<ArrayBufferLike>>> | undefined) => Promise<{ ok: boolean; pending?: boolean; day: string; root?: string; detail?: string; }>; reverify: (input: { receipt: Receipt | string | Record<string, unknown>; grant: string; proof: string; action: unknown; keys?: Readonly<Record<string, Uint8Array<ArrayBufferLike>>>; proofWindowSeconds?: number; requires?: DependencyDeclaration[]; evidence?: ReadonlyMap<string, Uint8Array>; consumptionSnapshot?: ConsumptionSnapshot; }) => Promise<ReverifyResult>; }
}

isVerifyResponseV3function#

packages/sdk/src/client.ts

Is this verify() result a checked v0.3 response (delegus-receipt-v2)?

ts
function isVerifyResponseV3(r: VerifyResult): r is VerifyResponseV3

PRODUCTION_APIconst#

packages/sdk/src/client.ts

ts
const PRODUCTION_API: "https://api.delegus.ai"

PRODUCTION_SERVICE_DIDconst#

packages/sdk/src/client.ts

The production service DID (spec §2.0); its document is served at PRODUCTION_API/.well-known/did.json.

ts
const PRODUCTION_SERVICE_DID: "did:web:delegus.ai"

VERIFY_DEFAULT_PROTOCOLconst#

packages/sdk/src/client.ts

ts
const VERIFY_DEFAULT_PROTOCOL: VerifyProtocol

CreatedOrginterface#

packages/sdk/src/client.ts

ts
interface CreatedOrg {
  principal: Principal
  did: string
  kid: string
  apiKey: string
  signer: Signer
}

DecisionRecordinterface#

packages/sdk/src/client.ts

GET /decisions/{receipt_id}: the receipt, its outcomes and, for a v2 receipt's own parties, its openings.

ts
interface DecisionRecord {
  receipt: Receipt
  outcomes: JsonObject[]
  // The matched Capability in plaintext; opens `authority_commitment` under `authority_opening`.
  authority?: Capability | undefined
  // Opens `authority_commitment` (43-char base64url).
  authority_opening?: string | undefined
  // Opens `evidence.consumption.capability_key_commitment` (43-char base64url).
  capability_key_opening?: string | undefined
}

DelegusOptionsinterface#

packages/sdk/src/client.ts

ts
interface DelegusOptions {
  // RP or Principal API key (`dk_rp_…` / `dk_principal_…`).
  apiKey?: string | undefined
  // Delegus admin token, for onboarding calls.
  adminToken?: string | undefined
  // Self-serve provision key (console only): POST /orgs/self-serve, the starter calls, and org entitlements.
  provisionKey?: string | undefined
  // API origin; default production.
  baseUrl?: string | undefined
  // The origin Agents address this RP at (§4.3). RPs behind proxies MUST set
  // it so htu binding checks see the URL the Agent targeted.
  publicBaseUrl?: string | undefined
  fetch?: FetchLike | undefined
  timeoutMs?: number | undefined
}

DisclosurePackageinterface#

packages/sdk/src/client.ts

GET /decisions/{receipt_id}/disclosure (v0.3-rc1 §R.5).

ts
interface DisclosurePackage {
  receipt_id: string
  // The consumption snapshot the receipt pins by hash (budgeted Capabilities).
  consumption_snapshot?: JsonObject | undefined
  // Per dependency entry: the pinned results plus what reproduces them (receipt and opening only when the caller is entitled to the prior receipt).
  relies_on?: DisclosureEntry[] | undefined
  // The matched Capability in plaintext; opens `authority_commitment` under `authority_opening`.
  authority?: Capability | undefined
  // Opens `authority_commitment` (43-char base64url).
  authority_opening?: string | undefined
  // Opens `evidence.consumption.capability_key_commitment` (43-char base64url).
  capability_key_opening?: string | undefined
}

Entitlementinterface#

packages/sdk/src/client.ts

The engine's view of an org's plan: the stored row (null fields when none is stored) and what the gate would decide now.

ts
interface Entitlement {
  org_id: string
  // Whether a row exists. With enforcement on, no row means no plan.
  stored: boolean
  production: "allowed" | "blocked" | null
  production_until: string | null
  check_cap: number | null
  cap_since: string | null
  reason: "trial" | "paid" | "past_due_grace" | "canceled" | "comp" | "none" | null
  as_of: string | null
  updated_at: string | null
  // Production checks counted since cap_since (at most check_cap); null without a cap.
  production_checks_since_cap: number | null
  // A staff, self-test or canary tenant that never needs a plan.
  comp: boolean
  // What the gate would decide for the next production check now.
  effective: "allowed" | "blocked"
  // Why it would be refused; null when allowed.
  effective_detail: string | null
  // Whether this deployment refuses (true) or only logs (false) a blocked production check.
  enforced: boolean
  // PUT only: whether this push was stored.
  applied?: boolean | undefined
}

EntitlementRequestinterface#

packages/sdk/src/client.ts

An org's production entitlement, as the console pushes it (PUT /orgs/{org_id}/entitlement).

ts
interface EntitlementRequest {
  production: "allowed" | "blocked"
  // Production checks stop at this instant; null for no end.
  production_until: string | null
  // At most this many production checks since cap_since; null for no cap.
  check_cap: number | null
  cap_since: string | null
  reason: "trial" | "paid" | "past_due_grace" | "canceled" | "comp" | "none"
  // The console's change time: an older push never overwrites a newer one.
  as_of: string
}

ListOptionsinterface#

packages/sdk/src/client.ts

ts
interface ListOptions {
  limit?: number | undefined
  cursor?: string | undefined
  since?: string | undefined
  until?: string | undefined
}

Orginterface#

packages/sdk/src/client.ts

An organization: a customer account owning Principals and relying parties.

ts
interface Org {
  org_id: string
  slug: string
  name: string
  created_at: string
}

OutcomeEventinterface#

packages/sdk/src/client.ts

ts
interface OutcomeEvent {
  type: "fulfilled" | "cancelled" | "dispute_opened" | "dispute_resolved" | "chargeback_received" | "chargeback_reversed" | "loss_reported"
  occurred_at: string
  evidence_ref?: string | undefined
  note?: string | undefined
  correction_of?: string | undefined
  resolution?: "agent_at_fault" | "agent_not_at_fault" | "indeterminate" | undefined
  loss_amount?: number | undefined
  currency?: string | undefined
  reporter_signature?: string | undefined
}

Pageinterface#

packages/sdk/src/client.ts

ts
interface Page {
  items: T[]
  // Pass back as `cursor` for the next page; null on the last page.
  next_cursor: string | null
}

ReceiptOpeningsinterface#

packages/sdk/src/client.ts

What opens a v2 receipt's commitments, as GET /decisions/{id} and its disclosure package return them (review H2).

ts
interface ReceiptOpenings {
  // The matched Capability in plaintext; opens `authority_commitment` under `authority_opening`.
  authority?: Capability | undefined
  // Opens `authority_commitment` (43-char base64url).
  authority_opening?: string | undefined
  // Opens `evidence.consumption.capability_key_commitment` (43-char base64url).
  capability_key_opening?: string | undefined
}

SelfServeBundleinterface#

packages/sdk/src/client.ts

POST /orgs/self-serve: a whole new tenant plus its first-ALLOW material.

ts
interface SelfServeBundle {
  org: Org
  // org:admin key — keep server-side; never show the customer.
  org_admin_key: string
  relying_party: { did: string; name: string; profile: string; proof_window_seconds: number; }
  // The customer's first verify key (dk_rp_…), shown once.
  rp_verify_key: string
  starter: SelfServeStarter
}

SelfServeStarterinterface#

packages/sdk/src/client.ts

A ready-to-verify sample from the shared sandbox Principal, bound to one relying party. POST grant/proof/action to /verify with the RP's key.

ts
interface SelfServeStarter {
  grant: string
  proof: string
  action: JsonObject
  grant_id: string
  // When the Proof leaves the RP's proof window; ask for a fresh starter after this.
  expires_at: string
  verify_url: string
  verify_curl: string
}

VerifyRequestinterface#

packages/sdk/src/client.ts

ts
interface VerifyRequest {
  grant: string
  proof: string
  action: unknown
  // The request the RP received. When given, the SDK checks the Proof's
  // htm/htu against it before calling Delegus (§4.3) and throws
  // ProofBindingError on mismatch. `path` is joined to `publicBaseUrl`.
  request?: { method: string; url?: string; path?: string; chain?: string[]; } | undefined
}

VerifyRequestAutointerface#

packages/sdk/src/client.ts

A /verify request that accepts either profile (the default). requires goes to a v0.3 relying party; a v1 receipt in answer to it fails closed.

ts
interface VerifyRequestAuto {
  protocol?: "auto" | undefined
  requires?: DependencyDeclaration[] | undefined
  grant: string
  proof: string
  action: unknown
  // The request the RP received. When given, the SDK checks the Proof's
  // htm/htu against it before calling Delegus (§4.3) and throws
  // ProofBindingError on mismatch. `path` is joined to `publicBaseUrl`.
  request?: { method: string; url?: string; path?: string; chain?: string[]; } | undefined
}

VerifyRequestV2interface#

packages/sdk/src/client.ts

A /verify request pinned to v0.2 (delegus-receipt-v1 only).

ts
interface VerifyRequestV2 {
  protocol: "v0.2"
  grant: string
  proof: string
  action: unknown
  // The request the RP received. When given, the SDK checks the Proof's
  // htm/htu against it before calling Delegus (§4.3) and throws
  // ProofBindingError on mismatch. `path` is joined to `publicBaseUrl`.
  request?: { method: string; url?: string; path?: string; chain?: string[]; } | undefined
}

VerifyRequestV3interface#

packages/sdk/src/client.ts

A v0.3-rc1 /verify request pinned to v0.3 (delegus-receipt-v2 only).

ts
interface VerifyRequestV3 {
  protocol: "v0.3"
  // The prior decisions this action must rest on (§5.1): 1–8 distinct { fingerprint, mode }; the actor's `relies_on` must cover each (D1).
  requires?: DependencyDeclaration[] | undefined
  grant: string
  proof: string
  action: unknown
  // The request the RP received. When given, the SDK checks the Proof's
  // htm/htu against it before calling Delegus (§4.3) and throws
  // ProofBindingError on mismatch. `path` is joined to `publicBaseUrl`.
  request?: { method: string; url?: string; path?: string; chain?: string[]; } | undefined
}

AnyVerifyRequesttype#

packages/sdk/src/client.ts

Any /verify request.

ts
type AnyVerifyRequest = VerifyRequestV3 | VerifyRequestV2 | VerifyRequestAuto

VerifyProtocoltype#

packages/sdk/src/client.ts

Which receipt profile verify() accepts. - "auto" (the default): whatever the relying party's profile answers with, read from the signed receipt payload. delegus-receipt-v1 takes the v0.2 path; delegus-receipt-v2 takes the full v0.3 checks; anything else fails closed. - "v0.2": a pin; only delegus-receipt-v1 is accepted. - "v0.3": a pin; only delegus-receipt-v2 is accepted.

ts
type VerifyProtocol = "v0.3" | "v0.2" | "auto"

VerifyResulttype#

packages/sdk/src/client.ts

What verify() returns under "auto": a v1 receipt or a checked v0.3 response. Tell them apart with isVerifyResponseV3.

ts
type VerifyResult = Receipt | VerifyResponseV3

Principal#

A company that issues Grants to its agents.

Principalclass#

packages/sdk/src/principal.ts

ts
class Principal {
  new (opts: PrincipalOptions): Principal
  did: string
  kid: string | null
  signer: Signer | null
  grant: { create: (req: GrantRequest) => Promise<IssuedGrant>; revoke: (grantId: string) => Promise<{ grant_id: string; revoked_at: string; }>; }
  keys: { retire: (kid: string) => Promise<{ kid: string; state: "retired" | "compromised"; }>; compromise: (kid: string) => Promise<void>; }
  // Run domain verification now and return the state and instructions.
  verifyDomain(): Promise<JsonObject>
  status(): Promise<JsonObject>
}

V3_CAPABILITY_ACTIONSconst#

packages/sdk/src/principal.ts

v0.2 action types, plus the v0.3-rc1 seller-side commitments (usable only with relying parties on delegus-base-v3).

ts
const V3_CAPABILITY_ACTIONS = {
  // Returns a string representation of an array.
  toString(): string
  // Returns a string representation of an array. The elements are converted to string using their toLocaleString methods.
  toLocaleString(): string
  // Combines two or more arrays.
  concat(...items: ConcatArray<"commerce:quote" | "commerce:accept" | "commerce:fulfil">[]): ("commerce:quote" | "commerce:accept" | "commerce:fulfil")[]
  // Adds all the elements of an array separated by the specified separator string.
  join(separator?: string): string
  // Returns a section of an array.
  slice(start?: number, end?: number): ("commerce:quote" | "commerce:accept" | "commerce:fulfil")[]
  // Returns the index of the first occurrence of a value in an array.
  indexOf(searchElement: "commerce:quote" | "commerce:accept" | "commerce:fulfil", fromIndex?: number): number
  // Returns the index of the last occurrence of a specified value in an array.
  lastIndexOf(searchElement: "commerce:quote" | "commerce:accept" | "commerce:fulfil", fromIndex?: number): number
  // Determines whether all the members of an array satisfy the specified test.
  every<S extends "commerce:quote" | "commerce:accept" | "commerce:fulfil">(predicate: (value: "commerce:quote" | "commerce:accept" | "commerce:fulfil", index: number, array: readonly ("commerce:quote" | "commerce:accept" | "commerce:fulfil")[]) => value is S, thisArg?: any): this is readonly S[]
  // Determines whether the specified callback function returns true for any element of an array.
  some(predicate: (value: "commerce:quote" | "commerce:accept" | "commerce:fulfil", index: number, array: readonly ("commerce:quote" | "commerce:accept" | "commerce:fulfil")[]) => unknown, thisArg?: any): boolean
  // Performs the specified action for each element in an array.
  forEach(callbackfn: (value: "commerce:quote" | "commerce:accept" | "commerce:fulfil", index: number, array: readonly ("commerce:quote" | "commerce:accept" | "commerce:fulfil")[]) => void, thisArg?: any): void
  // Calls a defined callback function on each element of an array, and returns an array that contains the results.
  map<U>(callbackfn: (value: "commerce:quote" | "commerce:accept" | "commerce:fulfil", index: number, array: readonly ("commerce:quote" | "commerce:accept" | "commerce:fulfil")[]) => U, thisArg?: any): U[]
  // Returns the elements of an array that meet the condition specified in a callback function.
  filter<S extends "commerce:quote" | "commerce:accept" | "commerce:fulfil">(predicate: (value: "commerce:quote" | "commerce:accept" | "commerce:fulfil", index: number, array: readonly ("commerce:quote" | "commerce:accept" | "commerce:fulfil")[]) => value is S, thisArg?: any): S[]
  // Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
  reduce(callbackfn: (previousValue: "commerce:quote" | "commerce:accept" | "commerce:fulfil", currentValue: "commerce:quote" | "commerce:accept" | "commerce:fulfil", currentIndex: number, array: readonly ("commerce:quote" | "commerce:accept" | "commerce:fulfil")[]) => "commerce:quote" | "commerce:accept" | "commerce:fulfil"): "commerce:quote" | "commerce:accept" | "commerce:fulfil"
  // Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
  reduceRight(callbackfn: (previousValue: "commerce:quote" | "commerce:accept" | "commerce:fulfil", currentValue: "commerce:quote" | "commerce:accept" | "commerce:fulfil", currentIndex: number, array: readonly ("commerce:quote" | "commerce:accept" | "commerce:fulfil")[]) => "commerce:quote" | "commerce:accept" | "commerce:fulfil"): "commerce:quote" | "commerce:accept" | "commerce:fulfil"
  // Returns the value of the first element in the array where predicate is true, and undefined
  // otherwise.
  find<S extends "commerce:quote" | "commerce:accept" | "commerce:fulfil">(predicate: (value: "commerce:quote" | "commerce:accept" | "commerce:fulfil", index: number, obj: readonly ("commerce:quote" | "commerce:accept" | "commerce:fulfil")[]) => value is S, thisArg?: any): S | undefined
  // Returns the index of the first element in the array where predicate is true, and -1
  // otherwise.
  findIndex(predicate: (value: "commerce:quote" | "commerce:accept" | "commerce:fulfil", index: number, obj: readonly ("commerce:quote" | "commerce:accept" | "commerce:fulfil")[]) => unknown, thisArg?: any): number
  // Returns an iterable of key, value pairs for every entry in the array
  entries(): ArrayIterator<[number, "commerce:quote" | "commerce:accept" | "commerce:fulfil"]>
  // Returns an iterable of keys in the array
  keys(): ArrayIterator<number>
  // Returns an iterable of values in the array
  values(): ArrayIterator<"commerce:quote" | "commerce:accept" | "commerce:fulfil">
  // Determines whether an array includes a certain element, returning true or false as appropriate.
  includes(searchElement: "commerce:quote" | "commerce:accept" | "commerce:fulfil", fromIndex?: number): boolean
  // Calls a defined callback function on each element of an array. Then, flattens the result into
  // a new array.
  // This is identical to a map followed by flat with depth 1.
  flatMap<U, This = undefined>(callback: (this: This, value: "commerce:quote" | "commerce:accept" | "commerce:fulfil", index: number, array: ("commerce:quote" | "commerce:accept" | "commerce:fulfil")[]) => U | readonly U[], thisArg?: This | undefined): U[]
  // Returns a new array with all sub-array elements concatenated into it recursively up to the
  // specified depth.
  flat<A, D extends number = 1>(this: A, depth?: D | undefined): FlatArray<A, D>[]
  // Returns the item located at the specified index.
  at(index: number): "commerce:quote" | "commerce:accept" | "commerce:fulfil" | undefined
  // Iterator of values in the array.
  __@iterator@208(): ArrayIterator<"commerce:quote" | "commerce:accept" | "commerce:fulfil">
  // Is an object whose properties have the value 'true'
  // when they will be absent when used in a 'with' statement.
  __@unscopables@592: { readonly [x: number]: boolean | undefined; readonly length?: boolean | undefined; toString?: boolean | undefined; toLocaleString?: boolean | undefined; concat?: boolean | undefined; join?: boolean | undefined; slice?: boolean | undefined; indexOf?: boolean | undefined; lastIndexOf?: boolean | undefined; every?: boolean | undefined; some?: boolean | undefined; forEach?: boolean | undefined; map?: boolean | undefined; filter?: boolean | undefined; reduce?: boolean | undefined; reduceRight?: boolean | undefined; find?: boolean | undefined; findIndex?: boolean | undefined; entries?: boolean | undefined; keys?: boolean | undefined; values?: boolean | undefined; includes?: boolean | undefined; flatMap?: boolean | undefined; flat?: boolean | undefined; at?: boolean | undefined; [Symbol.iterator]?: boolean | undefined; readonly [Symbol.unscopables]?: boolean | undefined; }
}

AgentInventoryEntryinterface#

From the next SDK release. AgentInventoryEntry isn't in the published @delegus/sdk 0.3.3 on npm yet.

packages/sdk/src/principal.ts

ts
interface AgentInventoryEntry {
  did: string
  principal: string
  created_at: string
  disabled_at: string | null
}

Capabilityinterface#

packages/sdk/src/principal.ts

ts
interface Capability {
  action: "commerce:quote" | "commerce:accept" | "commerce:fulfil" | "commerce:purchase" | "api:call"
  constraints: JsonObject
  resources?: string[] | undefined
}

GrantRequestinterface#

packages/sdk/src/principal.ts

ts
interface GrantRequest {
  // Agent DID (did:key).
  agent: string
  // 1–16 Capabilities (§3.3).
  authority: Capability[]
  // RFC 3339 UTC; default now (whole seconds).
  validFrom?: string | undefined
  // RFC 3339 UTC; default validFrom + 30 days; at most 90 days after validFrom.
  validUntil?: string | undefined
  // RP DIDs; absent = any registered RP.
  audience?: string[] | undefined
  // Refuse (PersonalDataError, before any request) when lintAuthority() finds
  // an email address, a phone number or a card number in the authority's
  // strings. Default false: the Grant is issued and the findings come back in
  // `warnings`. Resources should be opaque ids; receipts may keep them for years.
  refusePersonalData?: boolean | undefined
  // Default true: declare the authority, audience and validity at allocation and record the Grant's hash after signing (never the bytes). false: allocate only.
  declare?: boolean | undefined
}

IssuedGrantinterface#

packages/sdk/src/principal.ts

ts
interface IssuedGrant {
  id: string
  // The Grant compact JWS to hand to the Agent.
  jws: string
  credentialStatus: JsonObject
  validFrom: string
  validUntil: string
  // Present only when lintAuthority() found something that looks like personal data in the authority.
  warnings?: LintFinding[] | undefined
}

PrincipalOptionsinterface#

packages/sdk/src/principal.ts

ts
interface PrincipalOptions {
  did: string
  // `did:web:…#key-n` of `signer`; required to create Grants.
  kid?: string | undefined
  signer?: Signer | undefined
  apiKey: string
  transport: Transport
  now?: (() => number) | undefined
  // `apiKey` is an org:admin key of the Principal's org: name the Principal on every call (`?principal=<did>`). Grants cannot be created this way.
  viaOrgKey?: boolean | undefined
}

Agent#

The key that signs a Proof for each request.

Agentclass#

packages/sdk/src/agent.ts

ts
class Agent {
  new (signer: Signer): Agent
  did: string
  kid: string
  signer: Signer
  sign(req: ProofRequest): Promise<string>
  // The two request headers the RP forwards to /verify (§4.4).
  headers(req: ProofRequest): Promise<{ "Delegus-Grant": string; "Delegus-Proof": string; "Delegus-Grant-Chain"?: string; }>
  // Add this agent to a company's agent list with an enrolment token the company gave its builder (named-agents.md).
  // The request is also signed with this agent's key, so a token can only ever list the key that signs. The agent
  // arrives pending: it can be named in sentences, and given authority, only after an admin approves it.
  register(req: { delegus: DelegusEndpoint; token: string; name: string; description?: string; }): Promise<JsonObject>
  // A vendor's agent joins a customer's agent list with the one-time connect code the customer created and shared. It
  // arrives pending, labelled with the vendor, until the customer approves it; the vendor gets no power to issue grants.
  connect(req: { delegus: DelegusEndpoint; code: string; name: string; vendor: string; description?: string; }): Promise<JsonObject>
  createChild(req: { parent: string; parentChain?: string[]; agent: string; authority: unknown[]; audience: string[]; validFrom?: string; validUntil?: string; depth?: number; delegus: DelegusEndpoint; }): Promise<{ jws: string; id: string; chain: string[]; }>
  // The Delegus-Grant / Delegus-Proof headers for one HTTP request to a Delegus-guarded API (http.ts): the Proof
  // binds the method and the canonical URL; the Action is built exactly as the server builds it, through the
  // server's route map when given (`routes` = the compiled map from compileRouteMap, or the JSON it serves at
  // /delegus-routes.json), else `api:call` on the URL.
  httpHeaders(req: { grant: string; method: string; url: string; rpDid: string; body?: unknown; routes?: CompiledRoutes | unknown; iat?: number; jti?: string; chain?: string[]; op?: string; }): Promise<{ "Delegus-Grant": string; "Delegus-Proof": string; "Delegus-Grant-Chain"?: string; }>
  mcpHeaders(req: { grant: string; endpoint: string; tool: string; rpDid: string; iat?: number; jti?: string; chain?: string[]; op?: string; args?: unknown; map?: ToolMap; }): Promise<{ "Delegus-Grant": string; "Delegus-Proof": string; }>
  // New Agent with an in-memory Ed25519 key (dev default).
  static create(): Agent
}

DelegusEndpointinterface#

packages/sdk/src/agent.ts

What createChild() needs to reach Delegus: its base URL and the service DID agent-signed requests are addressed to.

ts
interface DelegusEndpoint {
  baseUrl: string
  serviceDid: string
  fetch?: { (input: RequestInfo | URL, init?: RequestInit): Promise<Response>; (input: string | URL | Request, init?: RequestInit): Promise<Response>; } | undefined
}

ProofRequestinterface#

packages/sdk/src/agent.ts

ts
interface ProofRequest {
  // The Grant compact JWS (its `id` is taken from it) or a bare Grant id.
  grant: string
  // The RP DID the Proof is for (`aud`).
  audience: string
  // The HTTP request the Agent is about to make.
  method: string
  url: string
  // The Action, built with `actions.*` from the same wire fields the RP will use.
  action: unknown
  // Override the clock (seconds since epoch); default now.
  iat?: number | undefined
  // Override the nonce (22–64 base64url chars); default 16 random bytes.
  jti?: string | undefined
}

Actions#

Helpers that build the action object the relying party describes.

actionsconst#

packages/sdk/src/actions.ts

ts
const actions = {
  // `commerce:purchase`: amount in minor units (integer), ISO 4217 currency.
  purchase(fields: { resource: string; amount: number; currency: string; }): Action
  // `api:call`: uppercase HTTP method, absolute http(s) resource URI.
  apiCall(fields: { method: string; resource: string; }): Action
}

actionsV3const#

packages/sdk/src/actions.ts

ts
const actionsV3 = {
  // `commerce:purchase`: the actor commits its Principal to buy.
  purchase(fields: Amounted): ActionV3
  // `commerce:quote`: the actor offers, for its Principal, to sell at this price.
  quote(fields: Amounted): ActionV3
  // `commerce:accept`: the actor accepts an order for its Principal at this price.
  accept(fields: Amounted): ActionV3
  // `commerce:fulfil`: the actor commits its Principal to deliver the named resource.
  fulfil(fields: { resource: string; } & DependencyFields): ActionV3
  // `api:call`: uppercase HTTP method, absolute http(s) resource URI.
  apiCall(fields: { method: string; resource: string; } & DependencyFields): ActionV3
  // Add `relies_on` to an Action built elsewhere (it must not already declare one, and must carry no transaction handle).
  withDependencies(action: Action | ActionV3, deps: DependencyFields): ActionV3
}

DependencyFieldsinterface#

packages/sdk/src/actions.ts

The optional v0.3 declaration every v3 Action may carry.

ts
interface DependencyFields {
  // 1–8 distinct { fingerprint, mode } entries; there is no default mode.
  relies_on?: DependencyDeclaration[] | undefined
}

Keys and signers#

Where private keys live. The signer interface is pluggable: memory for development, KMS or an HSM in production.

MemorySignerclass#

packages/sdk/src/keys.ts

ts
class MemorySigner {
  new (seed: Uint8Array): MemorySigner
  // Raw 32-byte Ed25519 public key.
  publicKey: Uint8Array<ArrayBufferLike>
  // PureEdDSA over exactly `data`; 64 bytes.
  sign(data: Uint8Array): Uint8Array
  toJwk(): Ed25519Jwk
  static generate(): MemorySigner
  static fromSeed(seed: Uint8Array): MemorySigner
  static fromJwk(jwk: unknown): MemorySigner
}

didKeyOffunction#

packages/sdk/src/keys.ts

ts
function didKeyOf(s: Signer): string

publicKeyMultibasefunction#

packages/sdk/src/keys.ts

ts
function publicKeyMultibase(s: Signer): string

Ed25519Jwkinterface#

packages/sdk/src/keys.ts

Ed25519 private key as a JWK (RFC 8037): the portable at-rest form.

ts
interface Ed25519Jwk {
  kty: "OKP"
  crv: "Ed25519"
  x: string
  d: string
}

Signerinterface#

packages/sdk/src/keys.ts

ts
interface Signer {
  // Raw 32-byte Ed25519 public key.
  publicKey: Uint8Array<ArrayBufferLike>
  // PureEdDSA over exactly `data`; 64 bytes.
  sign(data: Uint8Array): Uint8Array | Promise<Uint8Array>
}

Errors#

Everything the SDK throws.

DelegusApiErrorclass#

packages/sdk/src/errors.ts

A non-2xx answer from the Delegus API: { error, message } plus the HTTP status.

ts
class DelegusApiError {
  new (status: number, code: string, message: string): DelegusApiError
  name: string
  status: number
  code: string
  message: string
  stack?: string | undefined
  cause?: unknown
}

DelegusErrorclass#

packages/sdk/src/errors.ts

ts
class DelegusError {
  new (message?: string): DelegusError
  new (message?: string, options?: ErrorOptions): DelegusError
  name: string
  message: string
  stack?: string | undefined
  cause?: unknown
}

PersonalDataErrorclass#

packages/sdk/src/errors.ts

grant.create refused: the authority's strings look like they contain personal data (lintAuthority) and refusePersonalData was set. Use opaque ids.

ts
class PersonalDataError {
  new (findings: ReadonlyArray<{ path: string; kind: string; }>): PersonalDataError
  name: "PersonalDataError"
  findings: readonly { path: string; kind: string; }[]
  message: string
  stack?: string | undefined
  cause?: unknown
}

PlanRequiredErrorclass#

packages/sdk/src/errors.ts

HTTP 402 PLAN_REQUIRED: production checks need a plan for this account. Not a DENY: the check was refused before evaluation, no receipt was issued, and the Proof was not spent. Sandbox checks keep working.

ts
class PlanRequiredError {
  new (status: number, code: string, message: string): PlanRequiredError
  name: string
  status: number
  code: string
  message: string
  stack?: string | undefined
  cause?: unknown
}

ProofBindingErrorclass#

packages/sdk/src/errors.ts

ts
class ProofBindingError {
  new (expected: { method: string; url: string; }, proof: { htm: string; htu: string; }): ProofBindingError
  name: "ProofBindingError"
  expected: { method: string; url: string; }
  proof: { htm: string; htu: string; }
  message: string
  stack?: string | undefined
  cause?: unknown
}

Transport#

HTTP plumbing, replaceable for tests.

Transportclass#

packages/sdk/src/transport.ts

ts
class Transport {
  new (opts: TransportOptions): Transport
  baseUrl: string
  json(method: string, path: string, opts?: { token?: string | null; body?: unknown; headers?: Record<string, string>; }): Promise<JsonValue>
  // A request whose body is text (NDJSON, CSV, plain); errors are the API's JSON errors.
  raw(method: string, path: string, opts?: { token?: string | null; }): Promise<{ status: number; text: string; headers: Headers; }>
  bytes(path: string): Promise<Uint8Array | null>
}

FetchLiketype#

packages/sdk/src/transport.ts

ts
type FetchLike = (input: string, init: RequestInit) => Promise<Response>

v0.3#

Verifying under the v0.3 rules: opening checks, dependency helpers and receipt v2 verification.

ResponseIntegrityErrorclass#

packages/sdk/src/v3.ts

A v0.3 /verify response failed an integrity check. Fail closed: do not act on it.

ts
class ResponseIntegrityError {
  new (message?: string): ResponseIntegrityError
  new (message?: string, options?: ErrorOptions): ResponseIntegrityError
  name: string
  message: string
  stack?: string | undefined
  cause?: unknown
}

checkAuthorityOpeningfunction#

packages/sdk/src/v3.ts

Does opening open commitment (a receipt's authority_commitment) to this Capability? Core's verifyAuthorityOpening, after the SDK's integers-only rule. Throws TypeError when authority is not a JSON object with integers only; otherwise true or false, never a fallback.

ts
function checkAuthorityOpening(commitment: string, opening: string, authority: unknown): boolean

checkCapabilityKeyOpeningfunction#

packages/sdk/src/v3.ts

Does opening open commitment (a receipt's evidence.consumption.capability_key_commitment) to the key of this Capability? The key is core's capabilityKey: sha256(JCS(authority)). Throws TypeError when authority is not a JSON object with integers only.

ts
function checkCapabilityKeyOpening(commitment: string, opening: string, authority: unknown): boolean

decisionDisagreementfunction#

packages/sdk/src/v3.ts

Do the decision, the reason and the check results agree (spec §5.4)? ALLOW: reason null, every protocol and trust check true. DENY: some check is false, and the reason is one the first false check in the v3 order can report. Either way each layer's result is PASS exactly when all its checks are true. Returns null when they agree, else what disagrees.

ts
function decisionDisagreement(body: Pick<ReceiptV2Body, "decision" | "reason" | "protocol" | "trust">): string | null

dependencyOnfunction#

packages/sdk/src/v3.ts

The relies_on entry a downstream action declares for a prior response: its fingerprint (never the nonce) and a mode.

ts
function dependencyOn(response: Pick<VerifyResponseV3, typeof F_OPENING>, mode: DependencyMode): DependencyDeclaration

isReliesOnEntriesfunction#

packages/sdk/src/v3.ts

Well-formed recorded dependency entries (the engine's rule) with distinct fingerprints.

ts
function isReliesOnEntries(v: unknown): v is ReliesOnEntry[]

parseReceiptV2Bodyfunction#

packages/sdk/src/v3.ts

Parse a signed payload as a delegus-receipt-v2 body (profile delegus-base-v3); null unless well formed.

ts
function parseReceiptV2Body(payload: unknown): ReceiptV2Body | null

parseVerifyResponseV3function#

packages/sdk/src/v3.ts

Validate a /verify response as v0.3-rc1 and return it typed. Throws ResponseIntegrityError (fail closed) unless: - it carries a receipt JWS whose signature verifies under trust (the service's published keys; a #receipt-<n> key of its DID), whose payload is a delegus-receipt-v2 body (profile delegus-base-v3) and equals the response body after JCS, with authority, authority_opening, capability_key_opening, relies_on and opening set aside; - when sent.grant / sent.proof are given, the signed grant_hash and proof_hash are their sha256 (the receipt is about this request); - the decision, reason and check results agree (decisionDisagreement): an ALLOW has every protocol and trust check true, D1–D7 included; a DENY's reason is one its first false check in the v3 order can report; - on ALLOW: authority_commitment, authority, authority_opening, transaction and opening are all present; - authority and authority_opening are present exactly when authority_commitment is (ALLOW or DENY), and the opening opens the commitment to authority (core verifyAuthorityOpening; integers only); - capability_key_opening is present exactly when evidence.consumption.capability_key_commitment is, and opens it to sha256(JCS(authority)) (core verifyCapabilityKeyOpening); a v2 receipt carrying a plaintext capability_key is refused; - relies_on is present exactly when relies_on_hash is, well formed, and hashes to it; its entries are the action's declaration, in order; an ALLOW for an action that declared relies_on must pin them; - requires_hash is present exactly when requires was sent, and is its hash; - opening is exactly { fingerprint, nonce } and opens the fingerprint for this receipt's JWS; - transaction is a canonical 22-character handle; - request_hash, when present and the action is given, is sha256(JCS(action)).

ts
function parseVerifyResponseV3(response: unknown, sent: SentV3, trust: ReceiptTrust): VerifyResponseV3

receiptBindingMismatchfunction#

packages/sdk/src/v3.ts

Is this signed receipt payload about the request that was sent? grant_hash and proof_hash are sha256 over the UTF-8 of the Grant and Proof exactly as sent (core computes them the same way). Null when they match (or were not given), else what differs. Call it on the verified payload, after the signature.

ts
function receiptBindingMismatch(payload: Record<string, unknown>, sent: { grant?: string; proof?: string; }): string | null

reliesOnHashfunction#

packages/sdk/src/v3.ts

relies_on_hash: sha256 over the UTF-8 of JCS(the full entries array). Throws unless the entries are well formed.

ts
function reliesOnHash(entries: unknown): Sha256Ref

requiresHashfunction#

packages/sdk/src/v3.ts

requires_hash: sha256 over the UTF-8 of JCS(requires). Throws unless requires is well formed.

ts
function requiresHash(requires: unknown): Sha256Ref

splitV2Responsefunction#

packages/sdk/src/v3.ts

Split a v3 /verify response into the receipt body and the members returned beside it (authority, authority_opening, capability_key_opening, relies_on, opening).

ts
function splitV2Response(response: unknown): SplitResponseV2 | string

validateRequiresfunction#

packages/sdk/src/v3.ts

Parse and validate requires (§5.1): the same shape and rules as relies_on (1–8 entries, distinct, a mode each).

ts
function validateRequires(requires: unknown): DependencyDeclaration[]

verifyReceiptV2Entitledfunction#

packages/sdk/src/v3.ts

Entitled reproduction (§6.4) as far as material allows: public verification, then open authority_commitment (and capability_key_commitment) with their openings, reproduce relies_on_hash and requires_hash from their plaintext, and each dependency entry from a disclosure package entry and/or a prior receipt with its opening. ok is true only when everything was reproduced: any part that was not reproducible (or not supplied) makes it false, and D5 is reported as Delegus's attestation.

ts
function verifyReceiptV2Entitled(input: { receipt: string; body?: Record<string, unknown>; keys: TrustedKeys; did?: string; authority?: unknown; reliesOn?: unknown; requires?: unknown; authorityOpening?: unknown; capabilityKeyOpening?: unknown; disclosure?: unknown; priors?: readonly PriorReceipt[]; }): EntitledVerificationV2

verifyReceiptV2Publicfunction#

packages/sdk/src/v3.ts

Public verification of a v2 receipt (§6.4): anyone holding it can check it is authentic and unmodified. Signature, body equals payload (when a JSON body is given), and the v2 fields are well formed and consistent. It does not say why the decision was made.

ts
function verifyReceiptV2Public(input: { receipt: string; body?: Record<string, unknown>; keys: TrustedKeys; did?: string; }): PublicVerificationV2

verifyReceiptV2Signaturefunction#

packages/sdk/src/v3.ts

The engine's receipt signature check, narrowed to delegus-receipt-v2.

ts
function verifyReceiptV2Signature(receiptJws: unknown, keys: TrustedKeys, did?: string): ReceiptV2Signature

DependencyOpeninginterface#

packages/sdk/src/v3.ts

The commitment to a receipt a later action may declare (fingerprint) and its opening (nonce, 43-char base64url).

ts
interface DependencyOpening {
  fingerprint: `sha256:${string}`
  nonce: string
}

DependencyVerificationinterface#

packages/sdk/src/v3.ts

ts
interface DependencyVerification {
  index: number
  fingerprint: string
  mode: string
  // reproduced: every applicable part reproduced (D5 attested);
  // partial: nothing failed but something was not reproducible;
  // failed: something failed; not_supplied: no material at all for this entry.
  result: "not_supplied" | "reproduced" | "partial" | "failed"
  checks: Record<DependencyPart, { status: PartStatus; detail: string; }>
  // The prior receipt's id, when its receipt was supplied and verifies.
  receipt_id?: string | undefined
}

DisclosureEntryinterface#

packages/sdk/src/v3.ts

One entry of a dependency disclosure package (GET /decisions/{id}/disclosure, relies_on). Always: fingerprint, mode, checks (D2–D7), transaction_equal and receipt_hash. For CURRENT_AUTHORITY: status_credential, status_list_index and evidence_nonce. The prior receipt and its opening only for a caller entitled to that receipt itself.

ts
interface DisclosureEntry {
  fingerprint: string
  mode: string
  checks: Record<string, unknown>
  transaction_equal: boolean | null
  receipt_hash?: string | undefined
  status_credential?: string | undefined
  status_list_index?: string | undefined
  evidence_nonce?: string | undefined
  receipt?: string | undefined
  opening?: string | undefined
}

EntitledVerificationV2interface#

packages/sdk/src/v3.ts

ts
interface EntitledVerificationV2 {
  level: "entitled"
  // `authority_commitment` opened with `authority_opening` to the plaintext Capability.
  authority: PlaintextComparison
  // `evidence.consumption.capability_key_commitment` opened with `capability_key_opening` to sha256(JCS(authority)).
  capability_key: PlaintextComparison
  relies_on: PlaintextComparison
  requires: PlaintextComparison
  dependencies: DependencyVerification[]
  // Supplied priors or disclosure entries that name no relies_on entry of this receipt, or contradict themselves.
  unmatched: { source: "priors" | "disclosure"; index: number; detail: string; }[]
  receipt_id: string | null
  decision: string | null
  reason: string | null
  ok: boolean
  checks: V2Check[]
}

PlaintextComparisoninterface#

packages/sdk/src/v3.ts

ts
interface PlaintextComparison {
  result: PlaintextResult
  pinned: string | null
  computed: string | null
  detail?: string | undefined
}

PriorReceiptinterface#

packages/sdk/src/v3.ts

A prior receipt and its opening, as an entitled party holds them (e.g. the prior /verify response it stored).

ts
interface PriorReceipt {
  // The prior receipt's compact JWS, exactly as issued.
  receipt: string
  // Its opening nonce (43-char base64url).
  nonce: string
  // The fingerprint the opening came with, if known; checked too.
  fingerprint?: string | undefined
}

PublicVerificationV2interface#

packages/sdk/src/v3.ts

ts
interface PublicVerificationV2 {
  ok: boolean
  level: "public"
  receipt_id: string | null
  decision: string | null
  reason: string | null
  checks: V2Check[]
}

ReceiptTrustinterface#

packages/sdk/src/v3.ts

The keys a v2 receipt must verify under: the service's published keys (its DID document), and that DID.

ts
interface ReceiptTrust {
  keys: Readonly<Record<string, Uint8Array<ArrayBufferLike>>>
  // The service DID; the receipt's kid must be a `#receipt-<n>` key of it.
  did?: string | undefined
}

SentV3interface#

packages/sdk/src/v3.ts

What the relying party sent, for the response checks.

ts
interface SentV3 {
  action?: unknown
  requires?: readonly DependencyDeclaration[] | undefined
  // The Grant compact JWS sent; when given, the receipt's grant_hash must be sha256 over its UTF-8.
  grant?: string | undefined
  // The Proof compact JWS sent; when given, the receipt's proof_hash must be sha256 over its UTF-8.
  proof?: string | undefined
}

SplitResponseV2interface#

packages/sdk/src/v3.ts

A response (or stored response JSON) split into the signed body and what came beside it.

ts
interface SplitResponseV2 {
  jws: string
  parsed: ParsedJws
  // The members that must equal the signed payload.
  body: Record<string, unknown>
  authority?: unknown
  authorityOpening?: unknown
  capabilityKeyOpening?: unknown
  reliesOn?: unknown
  opening?: unknown
}

V2Checkinterface#

packages/sdk/src/v3.ts

ts
interface V2Check {
  check: string
  ok: boolean
  detail: string
}

DependencyParttype#

packages/sdk/src/v3.ts

ts
type DependencyPart = "D2" | "D3" | "D4" | "D5" | "D6" | "D7" | "receipt_hash" | "evidence_commitment"

PartStatustype#

packages/sdk/src/v3.ts

How one part of a dependency was established: reproduced recomputed from supplied material; equals what the receipt pins failed recomputed; differs from what the receipt pins (or the material contradicts itself) attested Delegus's statement, which no one outside Delegus can recompute by design (D5) not_reproducible the material to recompute it was not supplied skipped does not apply to this entry (D6, D7 and evidence_commitment for PRIOR_DECISION)

ts
type PartStatus = "reproduced" | "failed" | "attested" | "not_reproducible" | "skipped"

PlaintextResulttype#

packages/sdk/src/v3.ts

ts
type PlaintextResult = "match" | "mismatch" | "not_supplied" | "not_in_receipt" | "invalid"

ReceiptV2type#

packages/sdk/src/v3.ts

A delegus-receipt-v2 receipt: the body plus its receipt JWS.

ts
type ReceiptV2 = Omit<Receipt, V2Omit> & V2Fields

ReceiptV2Bodytype#

packages/sdk/src/v3.ts

A delegus-receipt-v2 body (no plaintext authority, no plaintext dependencies).

ts
type ReceiptV2Body = Omit<ReceiptBody, V2Omit> & V2Fields

ReceiptV2Signaturetype#

packages/sdk/src/v3.ts

ts
type ReceiptV2Signature = { ok: true; body: ReceiptV2Body; kid: string; } | { ok: false; detail: string; }

ReliesOnEntrytype#

packages/sdk/src/v3.ts

One relies_on entry as Delegus records it: the declaration plus per-entry results D2–D7 and, for CURRENT_AUTHORITY, an evidence commitment.

ts
type ReliesOnEntry = DependencyEntryResult

VerifyResponseV3type#

packages/sdk/src/v3.ts

A /verify response under v0.3-rc1: the v2 receipt plus, beside it, the plaintext authority with authority_opening (and capability_key_opening when the receipt pins that commitment), the plaintext relies_on entries and, on ALLOW, the opening. Every one of them has been checked against the receipt.

ts
type VerifyResponseV3 = Omit<Receipt, V2Omit> & V2Fields & { authority?: Capability; authority_opening?: string; capability_key_opening?: string; relies_on?: ReliesOnEntry[]; opening?: DependencyOpening; }

v0.3 fields#

The v0.3 Action and response fields.

PROFILE_V3const#

packages/sdk/src/v3-fields.ts

ts
const PROFILE_V3: "delegus-base-v3"

RECEIPT_VERSION_V2const#

packages/sdk/src/v3-fields.ts

ts
const RECEIPT_VERSION_V2: "delegus-receipt-v2"

MCP servers#

The middleware that checks every MCP tools/call before the tool runs, and the agent-side helpers. See /docs/mcp.

createMcpMiddlewarefunction#

packages/sdk/src/mcp.ts

ts
function createMcpMiddleware(client: Delegus, opts?: McpOptions): McpMiddleware

encodeToolNamefunction#

packages/sdk/src/mcp.ts

Percent-encode any character outside the SHOULD-limited [A-Za-z0-9_.-] tool-name set (both sides use this).

ts
function encodeToolName(name: string): string

fetchToolMapfunction#

packages/sdk/src/mcp.ts

Agent side: fetch and validate the tool map an MCP endpoint publishes at <endpoint>/delegus-tools.json. Cached per URL by hash; expectHash (from a Delegus-Tools header, sha256=<hex> or sha256:<hex>) makes a stale cache entry refetch and a mismatching file an error, so the agent learns of a changed map before signing rather than at P14. null = the endpoint publishes no map (404): build the bare tool-URI Action.

ts
function fetchToolMap(endpoint: string, opts?: { fetch?: typeof fetch; expectHash?: string; }): Promise<FetchedToolMap | null>

toolUrifunction#

packages/sdk/src/mcp.ts

The tool URI an api:call Action addresses: <normalizeHtu(publicBaseUrl + path)>/tools/<name>.

ts
function toolUri(publicBaseUrl: string, path: string, toolName: string): string | null

ARGUMENTS_UNMAPPABLEconst#

packages/sdk/src/mcp.ts

The middleware's own refusal when a mapped tool's arguments cannot be turned into an Action: an integration error, before /verify, never a receipt reason.

ts
const ARGUMENTS_UNMAPPABLE: "ARGUMENTS_UNMAPPABLE"

MCP_DEFAULT_PROTOCOLconst#

packages/sdk/src/mcp.ts

ts
const MCP_DEFAULT_PROTOCOL: VerifyProtocol

MCP_DELEGUS_ERROR_CODEconst#

packages/sdk/src/mcp.ts

JSON-RPC server-error range (-32000..-32099); avoids MCP's own -32020.

ts
const MCP_DELEGUS_ERROR_CODE: -32040

TOOL_MAP_FILEconst#

packages/sdk/src/mcp.ts

The file name, beside the MCP endpoint, at which the middleware serves its tool map.

ts
const TOOL_MAP_FILE: "delegus-tools.json"

FetchedToolMapinterface#

packages/sdk/src/mcp.ts

What fetchToolMap returns: the validated map, its hash and where it came from.

ts
interface FetchedToolMap {
  map: ToolMap
  hash: string
  url: string
}

McpCallSeeninterface#

From the next SDK release. McpCallSeen isn't in the published @delegus/sdk 0.3.3 on npm yet.

packages/sdk/src/mcp.ts

What the middleware saw of one tools/call, set on the request for the code around it (the gateway's record).

ts
interface McpCallSeen {
  tool: string
  // The JSON-RPC id of the call (null for a notification).
  id: string | number | null
  // The Action sent to Delegus, once built.
  action?: unknown
  decision?: "ALLOW" | "DENY" | undefined
  reason?: string | null | undefined
  receipt?: McpReceipt | undefined
  // Whether the tool is enforced (false: unlisted under `tools`, passed unchecked).
  enforced: boolean
}

McpDecisioninterface#

packages/sdk/src/mcp.ts

ts
interface McpDecision {
  decision: "ALLOW" | "DENY"
  reason: string | null
  tool: string
  receipt?: McpReceipt | undefined
  receiptId?: string | undefined
  // On a DENY decided in the middleware because /verify failed or its response did not check: what went wrong (for operators, never sent to the caller).
  error?: string | undefined
}

McpOptionsinterface#

packages/sdk/src/mcp.ts

ts
interface McpOptions {
  // Which tools to enforce: an allow-list or a predicate. Absent = enforce every tool. Unlisted tools pass through UNVERIFIED.
  tools?: string[] | ((name: string) => boolean) | undefined
  // Called with the outcome of every enforced tools/call (for logging / metrics).
  onDecision?: ((d: McpDecision) => void) | undefined
  // The relying-party DID to advertise in the discovery header on missing credentials. Absent = resolved once via GET /me.
  relyingParty?: string | undefined
  // "auto" (default, MCP_DEFAULT_PROTOCOL), or a pin: "v0.2" or "v0.3". Passed through to verify().
  protocol?: VerifyProtocol | undefined
  // With "auto" or "v0.3": the prior decisions every enforced tools/call must rest on (§5.1); checked when the middleware is created. A v0.2 relying party refuses them (fail closed).
  requires?: DependencyDeclaration[] | undefined
  // The MCP tool map (tool-map.ts): how a tool's arguments become the Action's resource and amount. The
  // parsed JSON object; validated when the middleware is created (a ToolMapError names the tool and field).
  // Tools without an entry keep the bare tool-URI Action. The map is served at `<path>/delegus-tools.json`
  // and named in the `Delegus-Tools` header, so agents build the same Action.
  map?: unknown
}

McpRequestinterface#

packages/sdk/src/mcp.ts

Minimal Express-style shapes so the middleware needs no web-framework dependency.

ts
interface McpRequest {
  method?: string | undefined
  url?: string | undefined
  path?: string | undefined
  headers: Record<string, string | string[] | undefined>
  body?: unknown
  // Set on ALLOW: the Delegus receipt (v0.3: the checked response) and the Action that authorized this tools/call.
  delegus?: { receipt: McpReceipt; action: unknown; } | undefined
  // Set for every single tools/call with a string tool name: what the middleware saw and decided.
  delegusCall?: McpCallSeen | undefined
}

McpResponseinterface#

packages/sdk/src/mcp.ts

ts
interface McpResponse {
  statusCode?: number | undefined
  setHeader(name: string, value: string): void
  end(body?: string): void
}

McpMiddlewaretype#

packages/sdk/src/mcp.ts

ts
type McpMiddleware = (req: McpRequest, res: McpResponse, next: McpNext) => Promise<void>

McpNexttype#

packages/sdk/src/mcp.ts

ts
type McpNext = () => void

McpProtocoltype#

packages/sdk/src/mcp.ts

The protocol the middleware speaks to Delegus: "auto" (the default) accepts the relying party's own profile; "v0.2" and "v0.3" pin one.

ts
type McpProtocol = "v0.3" | "v0.2" | "auto"

McpReceipttype#

packages/sdk/src/mcp.ts

The receipt the middleware attaches: a v0.2 receipt, or the checked v0.3 response (receipt v2 plus authority and its opening).

ts
type McpReceipt = Receipt | VerifyResponseV3

Tool maps#

How a tool call’s arguments become the action Delegus Check verifies, on the server and the agent alike.

ToolMapErrorclass#

packages/sdk/src/tool-map.ts

A map that cannot be loaded; tool and field name the entry at fault when there is one.

ts
class ToolMapError {
  new (message: string, tool?: string | null, field?: string | null): ToolMapError
  tool: string | null
  field: string | null
  name: string
  message: string
  stack?: string | undefined
  cause?: unknown
}

encodeSegmentfunction#

packages/sdk/src/tool-map.ts

Percent-encode one path segment: RFC 3986 unreserved characters kept, everything else (incl. * ? % # /) encoded as UTF-8.

ts
function encodeSegment(s: string): string

isDotSegmentfunction#

packages/sdk/src/tool-map.ts

"." or ".." in disguise. Percent-decode repeatedly (stop when unchanged or malformed), NFKC-normalize each round; true when any round is a dot segment, when the text still carries "%2e" (any case) once decoding stops, or when it is still changing after DECODE_ROUNDS rounds. A malformed sequence is literal.

ts
function isDotSegment(segment: string): boolean

mcpActionfunction#

packages/sdk/src/tool-map.ts

Build the Action for one tools/call. null = the tool has no entry (keep the bare tool-URI Action). toolUri is the URI the caller derives for the tool (<base>/tools/<name>); an api:call resource is <toolUri>/<path>. A refusal names the field so the caller can deny with the reason spelled out.

ts
function mcpAction(map: ToolMap, tool: string, toolUri: string, args: unknown): ToolMapResult | null

resolvePointerfunction#

packages/sdk/src/tool-map.ts

RFC 6901 resolution over the call's arguments. undefined = no such path. "" = the whole document.

ts
function resolvePointer(doc: unknown, pointer: string): unknown

toMinorUnitsfunction#

packages/sdk/src/tool-map.ts

Exact conversion to integer minor units; a string explains a refusal. Never floating-point arithmetic.

ts
function toMinorUnits(value: unknown, unit: "minor" | "major", decimals?: number): number | string

toolMapHashfunction#

packages/sdk/src/tool-map.ts

sha256 over the JCS form of the map: the identifier both sides compare.

ts
function toolMapHash(map: ToolMap): Sha256Ref

toolMapWarningsfunction#

packages/sdk/src/tool-map.ts

Non-fatal findings for an operator: two tools mapping to the same commerce type with the same template shape share one authority (a Grant for one authorizes the other).

ts
function toolMapWarnings(map: ToolMap): string[]

TOOL_MAP_ACTIONSconst#

packages/sdk/src/tool-map.ts

ts
const TOOL_MAP_ACTIONS = {
  // Returns a string representation of an array.
  toString(): string
  // Returns a string representation of an array. The elements are converted to string using their toLocaleString methods.
  toLocaleString(): string
  // Combines two or more arrays.
  concat(...items: ConcatArray<"commerce:quote" | "commerce:accept" | "commerce:fulfil" | "commerce:purchase" | "api:call">[]): ("commerce:quote" | "commerce:accept" | "commerce:fulfil" | "commerce:purchase" | "api:call")[]
  // Adds all the elements of an array separated by the specified separator string.
  join(separator?: string): string
  // Returns a section of an array.
  slice(start?: number, end?: number): ("commerce:quote" | "commerce:accept" | "commerce:fulfil" | "commerce:purchase" | "api:call")[]
  // Returns the index of the first occurrence of a value in an array.
  indexOf(searchElement: "commerce:quote" | "commerce:accept" | "commerce:fulfil" | "commerce:purchase" | "api:call", fromIndex?: number): number
  // Returns the index of the last occurrence of a specified value in an array.
  lastIndexOf(searchElement: "commerce:quote" | "commerce:accept" | "commerce:fulfil" | "commerce:purchase" | "api:call", fromIndex?: number): number
  // Determines whether all the members of an array satisfy the specified test.
  every<S extends "commerce:quote" | "commerce:accept" | "commerce:fulfil" | "commerce:purchase" | "api:call">(predicate: (value: "commerce:quote" | "commerce:accept" | "commerce:fulfil" | "commerce:purchase" | "api:call", index: number, array: readonly ("commerce:quote" | "commerce:accept" | "commerce:fulfil" | "commerce:purchase" | "api:call")[]) => value is S, thisArg?: any): this is readonly S[]
  // Determines whether the specified callback function returns true for any element of an array.
  some(predicate: (value: "commerce:quote" | "commerce:accept" | "commerce:fulfil" | "commerce:purchase" | "api:call", index: number, array: readonly ("commerce:quote" | "commerce:accept" | "commerce:fulfil" | "commerce:purchase" | "api:call")[]) => unknown, thisArg?: any): boolean
  // Performs the specified action for each element in an array.
  forEach(callbackfn: (value: "commerce:quote" | "commerce:accept" | "commerce:fulfil" | "commerce:purchase" | "api:call", index: number, array: readonly ("commerce:quote" | "commerce:accept" | "commerce:fulfil" | "commerce:purchase" | "api:call")[]) => void, thisArg?: any): void
  // Calls a defined callback function on each element of an array, and returns an array that contains the results.
  map<U>(callbackfn: (value: "commerce:quote" | "commerce:accept" | "commerce:fulfil" | "commerce:purchase" | "api:call", index: number, array: readonly ("commerce:quote" | "commerce:accept" | "commerce:fulfil" | "commerce:purchase" | "api:call")[]) => U, thisArg?: any): U[]
  // Returns the elements of an array that meet the condition specified in a callback function.
  filter<S extends "commerce:quote" | "commerce:accept" | "commerce:fulfil" | "commerce:purchase" | "api:call">(predicate: (value: "commerce:quote" | "commerce:accept" | "commerce:fulfil" | "commerce:purchase" | "api:call", index: number, array: readonly ("commerce:quote" | "commerce:accept" | "commerce:fulfil" | "commerce:purchase" | "api:call")[]) => value is S, thisArg?: any): S[]
  // Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
  reduce(callbackfn: (previousValue: "commerce:quote" | "commerce:accept" | "commerce:fulfil" | "commerce:purchase" | "api:call", currentValue: "commerce:quote" | "commerce:accept" | "commerce:fulfil" | "commerce:purchase" | "api:call", currentIndex: number, array: readonly ("commerce:quote" | "commerce:accept" | "commerce:fulfil" | "commerce:purchase" | "api:call")[]) => "commerce:quote" | "commerce:accept" | "commerce:fulfil" | "commerce:purchase" | "api:call"): "commerce:quote" | "commerce:accept" | "commerce:fulfil" | "commerce:purchase" | "api:call"
  // Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
  reduceRight(callbackfn: (previousValue: "commerce:quote" | "commerce:accept" | "commerce:fulfil" | "commerce:purchase" | "api:call", currentValue: "commerce:quote" | "commerce:accept" | "commerce:fulfil" | "commerce:purchase" | "api:call", currentIndex: number, array: readonly ("commerce:quote" | "commerce:accept" | "commerce:fulfil" | "commerce:purchase" | "api:call")[]) => "commerce:quote" | "commerce:accept" | "commerce:fulfil" | "commerce:purchase" | "api:call"): "commerce:quote" | "commerce:accept" | "commerce:fulfil" | "commerce:purchase" | "api:call"
  // Returns the value of the first element in the array where predicate is true, and undefined
  // otherwise.
  find<S extends "commerce:quote" | "commerce:accept" | "commerce:fulfil" | "commerce:purchase" | "api:call">(predicate: (value: "commerce:quote" | "commerce:accept" | "commerce:fulfil" | "commerce:purchase" | "api:call", index: number, obj: readonly ("commerce:quote" | "commerce:accept" | "commerce:fulfil" | "commerce:purchase" | "api:call")[]) => value is S, thisArg?: any): S | undefined
  // Returns the index of the first element in the array where predicate is true, and -1
  // otherwise.
  findIndex(predicate: (value: "commerce:quote" | "commerce:accept" | "commerce:fulfil" | "commerce:purchase" | "api:call", index: number, obj: readonly ("commerce:quote" | "commerce:accept" | "commerce:fulfil" | "commerce:purchase" | "api:call")[]) => unknown, thisArg?: any): number
  // Returns an iterable of key, value pairs for every entry in the array
  entries(): ArrayIterator<[number, "commerce:quote" | "commerce:accept" | "commerce:fulfil" | "commerce:purchase" | "api:call"]>
  // Returns an iterable of keys in the array
  keys(): ArrayIterator<number>
  // Returns an iterable of values in the array
  values(): ArrayIterator<"commerce:quote" | "commerce:accept" | "commerce:fulfil" | "commerce:purchase" | "api:call">
  // Determines whether an array includes a certain element, returning true or false as appropriate.
  includes(searchElement: "commerce:quote" | "commerce:accept" | "commerce:fulfil" | "commerce:purchase" | "api:call", fromIndex?: number): boolean
  // Calls a defined callback function on each element of an array. Then, flattens the result into
  // a new array.
  // This is identical to a map followed by flat with depth 1.
  flatMap<U, This = undefined>(callback: (this: This, value: "commerce:quote" | "commerce:accept" | "commerce:fulfil" | "commerce:purchase" | "api:call", index: number, array: ("commerce:quote" | "commerce:accept" | "commerce:fulfil" | "commerce:purchase" | "api:call")[]) => U | readonly U[], thisArg?: This | undefined): U[]
  // Returns a new array with all sub-array elements concatenated into it recursively up to the
  // specified depth.
  flat<A, D extends number = 1>(this: A, depth?: D | undefined): FlatArray<A, D>[]
  // Returns the item located at the specified index.
  at(index: number): "commerce:quote" | "commerce:accept" | "commerce:fulfil" | "commerce:purchase" | "api:call" | undefined
  // Iterator of values in the array.
  __@iterator@208(): ArrayIterator<"commerce:quote" | "commerce:accept" | "commerce:fulfil" | "commerce:purchase" | "api:call">
  // Is an object whose properties have the value 'true'
  // when they will be absent when used in a 'with' statement.
  __@unscopables@592: { readonly [x: number]: boolean | undefined; readonly length?: boolean | undefined; toString?: boolean | undefined; toLocaleString?: boolean | undefined; concat?: boolean | undefined; join?: boolean | undefined; slice?: boolean | undefined; indexOf?: boolean | undefined; lastIndexOf?: boolean | undefined; every?: boolean | undefined; some?: boolean | undefined; forEach?: boolean | undefined; map?: boolean | undefined; filter?: boolean | undefined; reduce?: boolean | undefined; reduceRight?: boolean | undefined; find?: boolean | undefined; findIndex?: boolean | undefined; entries?: boolean | undefined; keys?: boolean | undefined; values?: boolean | undefined; includes?: boolean | undefined; flatMap?: boolean | undefined; flat?: boolean | undefined; at?: boolean | undefined; [Symbol.iterator]?: boolean | undefined; readonly [Symbol.unscopables]?: boolean | undefined; }
}

TOOL_MAP_VERSIONconst#

packages/sdk/src/tool-map.ts

ts
const TOOL_MAP_VERSION: 1

ToolMapinterface#

packages/sdk/src/tool-map.ts

ts
interface ToolMap {
  version: 1
  tools: Record<string, ToolMapEntry>
}

ToolMapAmountinterface#

packages/sdk/src/tool-map.ts

ts
interface ToolMapAmount {
  // JSON pointer to the amount.
  value: string
  // JSON pointer to the currency, or a literal ISO 4217 code (three upper-case letters).
  currency: string
  // "minor": the value is a non-negative safe integer in minor units. "major": a number or decimal string with at most `decimals` fractional digits, converted by string arithmetic.
  unit: "minor" | "major"
  // Required with "major": the currency's fractional digits (0–6).
  decimals?: number | undefined
}

ToolMapEntryinterface#

packages/sdk/src/tool-map.ts

ts
interface ToolMapEntry {
  action: "commerce:quote" | "commerce:accept" | "commerce:fulfil" | "commerce:purchase" | "api:call"
  // Literal text plus `{<json-pointer>}` placeholders. For api:call the result is appended to the tool URI; for the commerce types it is the resource itself.
  resource: string
  amount?: ToolMapAmount | undefined
}

ToolMapActiontype#

packages/sdk/src/tool-map.ts

ts
type ToolMapAction = "commerce:quote" | "commerce:accept" | "commerce:fulfil" | "commerce:purchase" | "api:call"

ToolMapResulttype#

packages/sdk/src/tool-map.ts

ts
type ToolMapResult = { ok: true; action: Record<string, JsonValue>; resource: string; method: string; } | { ok: false; error: string; field: string; }

Ordinary HTTP APIs#

The same check in front of a REST API: Express and Fastify middleware and the route map. See /docs/http.

RouteMapErrorclass#

packages/sdk/src/http.ts

ts
class RouteMapError {
  new (message: string, route?: string | null): RouteMapError
  route: string | null
  name: string
  message: string
  stack?: string | undefined
  cause?: unknown
}

checkHttpRequestfunction#

packages/sdk/src/http.ts

The check itself. url is the canonical public URL of the request (the server knows its publicBaseUrl; the path and query come from the request). Pure apart from the one call to Delegus.

ts
function checkHttpRequest(client: Delegus, opts: HttpCheckOptions, req: HttpRequestLike & { url: string; }): Promise<HttpCheckOutcome>

createHttpMiddlewarefunction#

packages/sdk/src/http.ts

Express-style middleware: app.use(delegus.http({ routeMap })) before the routes it protects (mount express.json() first so req.body is the parsed JSON). Serves the route map at /delegus-routes.json. OPTIONS passes; everything else is checked. On ALLOW req.delegus holds the receipt and the Action, and Delegus-Receipt-Id is on the response; on DENY, 403 (401 without credentials) with the reason.

ts
function createHttpMiddleware(client: Delegus, opts?: HttpMiddlewareOptions): (req: MinimalReq, res: MinimalRes, next: (err?: unknown) => void) => Promise<void>

fastifyDelegusHttpfunction#

packages/sdk/src/http.ts

Fastify: app.addHook("preHandler", fastifyDelegusHttp(client, { routeMap })). Uses request.body as Fastify parsed it, request.raw.url and request.headers; on ALLOW request.delegus is set and the receipt header added to the reply; on DENY the reply is sent and the handler never runs.

ts
function fastifyDelegusHttp(client: Delegus, opts?: HttpMiddlewareOptions): (request: { method: string; url: string; headers: Record<string, string | string[] | undefined>; body?: unknown; delegus?: unknown; }, reply: { code(c: number): unknown; header(n: string, v: string): unknown; send(b: unknown): unknown; }) => Promise<void>

httpActionfunction#

packages/sdk/src/http.ts

The Action a request is checked as. url must be the canonical public URL (publicBaseUrl + path, query kept as received).

ts
function httpAction(compiled: CompiledRoutes | null, req: { method: string; url: string; body?: unknown; }): HttpActionResult

matchRoutefunction#

packages/sdk/src/http.ts

The first route whose method and path pattern match, with the path parameters it bound.

ts
function matchRoute(compiled: CompiledRoutes, method: string, path: string): { route: CompiledRoutes["routes"][number]; params: Record<string, string>; } | null

ROUTE_MAP_FILEconst#

packages/sdk/src/http.ts

ts
const ROUTE_MAP_FILE: "delegus-routes.json"

ROUTE_MAP_VERSIONconst#

packages/sdk/src/http.ts

ts
const ROUTE_MAP_VERSION: 1

CompiledRoutesinterface#

packages/sdk/src/http.ts

A compiled route map: the path matcher per route and the tool-map-shaped templates the Action is built from.

ts
interface CompiledRoutes {
  map: RouteMap
  hash: string
  json: string
  routes: (RouteDef & { segments: Array<{ literal: string; } | { param: string; }>; })[]
  // The templates, as a tool map keyed by route id (so mcpAction renders them).
  templates: ToolMap
  // The same templates under the tool map's own member name, so mcpAction can read a CompiledRoutes directly.
  tools: Record<string, ToolMapEntry>
}

HttpCheckOptionsinterface#

packages/sdk/src/http.ts

ts
interface HttpCheckOptions {
  // The route map, already compiled with compileRouteMap; null = every request is `api:call` on its URL.
  routes?: CompiledRoutes | null | undefined
  protocol?: VerifyProtocol | undefined
  // The relying-party DID to advertise on missing credentials. Absent = resolved once via GET /me.
  relyingParty?: string | undefined
  onDecision?: ((d: { decision: "ALLOW" | "DENY"; reason: string | null; route: string | null; method: string; url: string; receiptId?: string; error?: string; }) => void) | undefined
}

HttpCheckOutcomeinterface#

packages/sdk/src/http.ts

ts
interface HttpCheckOutcome {
  status: 200 | 401 | 403
  headers: Record<string, string>
  // Present when the request may proceed.
  receipt?: VerifyResult | undefined
  // Present on a refusal: the JSON body to send.
  body?: JsonObject | undefined
  decision: "ALLOW" | "DENY"
  reason: string | null
  action: JsonObject | null
  route: string | null
}

HttpMiddlewareOptionsinterface#

packages/sdk/src/http.ts

ts
interface HttpMiddlewareOptions {
  // The route map JSON (validated here) or an already compiled one.
  routeMap?: unknown
  // The route map, already compiled with compileRouteMap; null = every request is `api:call` on its URL.
  routes?: CompiledRoutes | null | undefined
  protocol?: VerifyProtocol | undefined
  // The relying-party DID to advertise on missing credentials. Absent = resolved once via GET /me.
  relyingParty?: string | undefined
  onDecision?: ((d: { decision: "ALLOW" | "DENY"; reason: string | null; route: string | null; method: string; url: string; receiptId?: string; error?: string; }) => void) | undefined
}

RouteMapinterface#

packages/sdk/src/http.ts

ts
interface RouteMap {
  version: 1
  routes: RouteDef[]
}

HttpActionResulttype#

packages/sdk/src/http.ts

ts
type HttpActionResult = { ok: true; action: JsonObject; route: string | null; } | { ok: false; reason: string; detail: string; route: string | null; }

Receipt chains#

From the next SDK release. This section isn't in the published @delegus/sdk 0.3.3 on npm yet.

Verify a chain of linked receipts offline.

comparePolicyfunction#

packages/sdk/src/chain.ts

Compare a verified chain to the confirmed policy. report comes from verifyChain with the company's Grants supplied.

ts
function comparePolicy(report: ChainReport, policy: PolicyMapping): PolicyReport

verifyChainfunction#

packages/sdk/src/chain.ts

Verify a chain offline. grants: the Grants the company holds, any order; matched to links by sha256 of the JWS.

ts
function verifyChain(chain: ChainInput, keys: Record<string, Uint8Array>, grants?: readonly string[], serviceDid?: string): ChainReport

ChainInputinterface#

packages/sdk/src/chain.ts

ts
interface ChainInput {
  root: string
  links: { receipt_id: string; depth: number; receipt: string; decision: "ALLOW" | "DENY"; reason: string | null; evaluated_at: string; relying_party: string; principal: string | null; agent: string | null; grant_id: string | null; grant_hash: string | null; action: JsonValue | null; relies_on: Array<{ fingerprint: string; mode: string; checks: JsonValue; transaction_equal: boolean | null; receipt_hash?: string; receipt_id?: string; opening?: string; withheld?: boolean; }>; }[]
  withheld?: number | undefined
  truncated?: boolean | undefined
}

ChainReportinterface#

packages/sdk/src/chain.ts

ts
interface ChainReport {
  root: string
  ok: boolean
  links: LinkReport[]
  link_count: number
  withheld: number
  truncated: boolean
  not_confirmed_here: string[]
  // Each link's action as the chain carried it, by receipt id (for the policy comparison).
  actions?: Record<string, JsonValue> | undefined
}

LinkReportinterface#

packages/sdk/src/chain.ts

ts
interface LinkReport {
  receipt_id: string
  depth: number
  agent: string | null
  decision: "ALLOW" | "DENY"
  reason: string | null
  signature: "invalid" | "valid"
  body_matches_payload: boolean
  relies_on: { fingerprint: string; mode: string; prior_receipt_id: string | null; prior_agent: string | null; opening_reproduces: boolean | "withheld"; prior_is_allow: boolean | "withheld"; prior_signature: "valid" | "invalid" | "withheld"; }[]
  grant: { grant_id: string | null; grant_hash: string | null; supplied: boolean; hash_matches: boolean | null; parses: boolean | null; subject_is_agent: boolean | null; authority: Capability[] | null; audience: string[] | null; valid_from: string | null; valid_until: string | null; }
  ok: boolean
  failures: string[]
}

packages/sdk/src/chain.ts

ts
interface PolicyLink {
  receipt_id: string
  agent: string | null
  holder: { id: string; kind: string; } | null
  // matches: same authority; narrower: inside the policy's; wider: something the policy does not give; not_supplied: no Grant to compare; no_holder: the agent is not a holder at as_of.
  grant: "not_supplied" | "matches" | "narrower" | "wider" | "no_holder"
  detail: string | null
  // Per Grant Capability: the policy rule ids it traces to (empty when it fits no policy Capability).
  provenance: { capability: number; rules: string[]; }[]
  // The step this link performed, read from the action's resource; null when it cannot be told, with the candidates.
  step: string | null
  candidates: string[]
}

PolicyMappinginterface#

packages/sdk/src/chain.ts

ts
interface PolicyMapping {
  format: "delegus-pack-authority-map-v1"
  matrix_hash: string
  as_of: string
  relying_party: string
  grants: { did: string; id: string; kind: string; authority: Capability[]; audience: string[]; provenance: Array<{ capability: number; rules: Array<{ rule: string; role: string; unit: string; }>; }>; }[]
  steps: { action: string; operation: string; doc: string; creates: boolean; approval: boolean; distinct_from: string[]; requires_prior: string[]; quorum: { actions: string[]; min: number; } | null; }[]
}

PolicyReportinterface#

packages/sdk/src/chain.ts

ts
interface PolicyReport {
  matrix_hash: string
  as_of: string
  ok: boolean
  links: PolicyLink[]
  segregation: SegregationCheck[]
  quorum: QuorumCheck[]
  not_confirmed_here: string[]
}

QuorumCheckinterface#

packages/sdk/src/chain.ts

ts
interface QuorumCheck {
  receipt_id: string
  step: string
  required: number
  distinct_voters: number
  verdict: "not_determinable" | "met" | "not_met"
  why: string
}

SegregationCheckinterface#

packages/sdk/src/chain.ts

ts
interface SegregationCheck {
  receipt_id: string
  prior_receipt_id: string | null
  agent: string | null
  prior_agent: string | null
  step: string | null
  prior_step: string | null
  // distinct: different agents; same_agent_violation: the policy requires different people here; same_agent_allowed: the same person, and the policy does not forbid it; not_determinable: a step or an agent is unknown (withheld, or ambiguous).
  verdict: "distinct" | "same_agent_violation" | "same_agent_allowed" | "not_determinable"
  why: string
}

Issuance lint#

Warnings for personal data in a grant before it is issued.

lintAuthorityfunction#

packages/sdk/src/lint.ts

Lint a Grant's authority (an array of Capabilities, or one Capability) for personal data in its strings. Returns one finding per kind per string; empty when nothing looks personal.

ts
function lintAuthority(authority: unknown): LintFinding[]

luhnValidfunction#

packages/sdk/src/lint.ts

Luhn (mod 10) over a digit string.

ts
function luhnValid(d: string): boolean

personalDataInfunction#

packages/sdk/src/lint.ts

The kinds of personal data a single string looks like it contains.

ts
function personalDataIn(s: string): PersonalDataKind[]

LintFindinginterface#

packages/sdk/src/lint.ts

ts
interface LintFinding {
  // Where, e.g. `authority[0].resources[1]`. The matched value is not echoed.
  path: string
  kind: PersonalDataKind
}

PersonalDataKindtype#

packages/sdk/src/lint.ts

ts
type PersonalDataKind = "email" | "phone" | "card"

Types from @delegus/core#

Re-exported so an integrator never needs to import core directly.

EVALUATION_ORDER_V3const#

packages/core/src/types.ts

delegus-base-v3 order (v0.3-rc1 §5.4): … P20 → P21 → D1 … D7 → [consume] → T7. The atomic spend is the very last step: it runs only when every other check passed, so no request consumes budget and is then refused.

ts
const EVALUATION_ORDER_V3 = {
  // Gets the length of the array. This is a number one higher than the highest element defined in an array.
  length: number
  // Returns a string representation of an array.
  toString(): string
  // Returns a string representation of an array. The elements are converted to string using their toLocaleString methods.
  toLocaleString(): string
  // Combines two or more arrays.
  concat(...items: ConcatArray<CheckId>[]): CheckId[]
  // Adds all the elements of an array separated by the specified separator string.
  join(separator?: string): string
  // Returns a section of an array.
  slice(start?: number, end?: number): CheckId[]
  // Returns the index of the first occurrence of a value in an array.
  indexOf(searchElement: CheckId, fromIndex?: number): number
  // Returns the index of the last occurrence of a specified value in an array.
  lastIndexOf(searchElement: CheckId, fromIndex?: number): number
  // Determines whether all the members of an array satisfy the specified test.
  every<S extends CheckId>(predicate: (value: CheckId, index: number, array: readonly CheckId[]) => value is S, thisArg?: any): this is readonly S[]
  // Determines whether the specified callback function returns true for any element of an array.
  some(predicate: (value: CheckId, index: number, array: readonly CheckId[]) => unknown, thisArg?: any): boolean
  // Performs the specified action for each element in an array.
  forEach(callbackfn: (value: CheckId, index: number, array: readonly CheckId[]) => void, thisArg?: any): void
  // Calls a defined callback function on each element of an array, and returns an array that contains the results.
  map<U>(callbackfn: (value: CheckId, index: number, array: readonly CheckId[]) => U, thisArg?: any): U[]
  // Returns the elements of an array that meet the condition specified in a callback function.
  filter<S extends CheckId>(predicate: (value: CheckId, index: number, array: readonly CheckId[]) => value is S, thisArg?: any): S[]
  // Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
  reduce(callbackfn: (previousValue: CheckId, currentValue: CheckId, currentIndex: number, array: readonly CheckId[]) => CheckId): CheckId
  // Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
  reduceRight(callbackfn: (previousValue: CheckId, currentValue: CheckId, currentIndex: number, array: readonly CheckId[]) => CheckId): CheckId
  // Returns the value of the first element in the array where predicate is true, and undefined
  // otherwise.
  find<S extends CheckId>(predicate: (value: CheckId, index: number, obj: readonly CheckId[]) => value is S, thisArg?: any): S | undefined
  // Returns the index of the first element in the array where predicate is true, and -1
  // otherwise.
  findIndex(predicate: (value: CheckId, index: number, obj: readonly CheckId[]) => unknown, thisArg?: any): number
  // Returns an iterable of key, value pairs for every entry in the array
  entries(): ArrayIterator<[number, CheckId]>
  // Returns an iterable of keys in the array
  keys(): ArrayIterator<number>
  // Returns an iterable of values in the array
  values(): ArrayIterator<CheckId>
  // Determines whether an array includes a certain element, returning true or false as appropriate.
  includes(searchElement: CheckId, fromIndex?: number): boolean
  // Calls a defined callback function on each element of an array. Then, flattens the result into
  // a new array.
  // This is identical to a map followed by flat with depth 1.
  flatMap<U, This = undefined>(callback: (this: This, value: CheckId, index: number, array: CheckId[]) => U | readonly U[], thisArg?: This | undefined): U[]
  // Returns a new array with all sub-array elements concatenated into it recursively up to the
  // specified depth.
  flat<A, D extends number = 1>(this: A, depth?: D | undefined): FlatArray<A, D>[]
  // Returns the item located at the specified index.
  at(index: number): CheckId | undefined
  // Iterator of values in the array.
  __@iterator@208(): ArrayIterator<CheckId>
  // Is an object whose properties have the value 'true'
  // when they will be absent when used in a 'with' statement.
  __@unscopables@592: { readonly [x: number]: boolean | undefined; readonly length?: boolean | undefined; toString?: boolean | undefined; toLocaleString?: boolean | undefined; concat?: boolean | undefined; join?: boolean | undefined; slice?: boolean | undefined; indexOf?: boolean | undefined; lastIndexOf?: boolean | undefined; every?: boolean | undefined; some?: boolean | undefined; forEach?: boolean | undefined; map?: boolean | undefined; filter?: boolean | undefined; reduce?: boolean | undefined; reduceRight?: boolean | undefined; find?: boolean | undefined; findIndex?: boolean | undefined; entries?: boolean | undefined; keys?: boolean | undefined; values?: boolean | undefined; includes?: boolean | undefined; flatMap?: boolean | undefined; flat?: boolean | undefined; at?: boolean | undefined; [Symbol.iterator]?: boolean | undefined; readonly [Symbol.unscopables]?: boolean | undefined; }
}

DependencyDeclarationinterface#

packages/core/src/action-v3.ts

ts
interface DependencyDeclaration {
  fingerprint: `sha256:${string}`
  mode: "PRIOR_DECISION" | "CURRENT_AUTHORITY"
}

Receiptinterface#

packages/core/src/receipt.ts

A signed receipt: the body as signed (§6.4: equal to the JWS payload) and the JWS.

ts
interface Receipt {
  // Non-detached compact JWS over JCS(body as signed).
  receipt: string
  receipt_version: "delegus-receipt-v2" | "delegus-receipt-v1" | "delegus-receipt-v3"
  // delegus-receipt-v1 only: the matched Capability, or null on DENY.
  authority?: Capability | null | undefined
  // delegus-receipt-v2: the matched Capability under a commitment (§R.6); the plaintext and its opening go to the RP beside the receipt.
  authority_commitment?: `sha256:${string}` | undefined
  // delegus-receipt-v2: sha256 over JCS(the declared dependencies with their per-entry results).
  // Constant size whatever the number of dependencies (KMS signs ≤ 4,096 bytes); the entries
  // themselves go to the relying party beside the receipt, like `authority`.
  relies_on_hash?: `sha256:${string}` | undefined
  // delegus-receipt-v2: sha256 over JCS(the relying party's `requires`), when it sent one, so D1 is reproducible.
  requires_hash?: `sha256:${string}` | undefined
  // delegus-receipt-v2: this receipt's pairwise transaction handle (22 chars base64url).
  transaction?: string | undefined
  receipt_id: string
  decision: Decision
  reason: ReasonCode | null
  evaluated_at: string
  relying_party: string
  principal?: { id: string; verification: "domain" | "unverified" | "managed"; } | undefined
  agent?: string | undefined
  grant_id?: string | undefined
  grant_hash: `sha256:${string}`
  proof_hash: `sha256:${string}`
  request_hash?: `sha256:${string}` | undefined
  expires_at?: string | undefined
  evidence: ReceiptEvidence
  trust: { result: LayerResult; policy_version: ProfileSpec["policy"]; checks: Record<string, CheckOutcome>; }
  protocol: Omit<{ result: LayerResult; profile: ProfileId; profile_hash: Sha256Ref; checks: Record<string, CheckOutcome>; }, "checks"> & { checks: ReceiptBody["protocol"]["checks"] | string; }
}

ReverifyResultinterface#

packages/core/src/receipt.ts

ts
interface ReverifyResult {
  // Signature valid, every supplied artifact matches its pinned hash, and everything that could be reproduced was.
  ok: boolean
  signature: "invalid" | "valid"
  detail?: string | undefined
  hashes?: Record<"profile" | "grant" | "proof" | "request" | "did_document" | "status_credential" | "trust_config", HashComparison> | undefined
  // Whether `protocol`, `decision` and `reason` were reproduced, and what differed.
  reproduced?: { protocol: boolean; decision: boolean; differences: string[]; } | undefined
  // What this run could not reproduce and why: the trust attestations (always), and for a v0.3 receipt
  // the commitments without their openings, P21 without the consumption snapshot, D1–D7 without the
  // dependency material, and the decision when it rests on one of those. Not a failure; a boundary.
  notReproduced?: { what: string; why: string; }[] | undefined
  receipt?: ReceiptBody | undefined
  recomputed?: ReceiptBody | undefined
}

DependencyModetype#

packages/core/src/action-v3.ts

ts
type DependencyMode = "PRIOR_DECISION" | "CURRENT_AUTHORITY"

TrustedKeystype#

packages/core/src/status.ts

Raw Ed25519 public keys by kid.

ts
type TrustedKeys = { readonly [x: string]: Uint8Array<ArrayBufferLike>; }

The delegus CLI#

The same operations from a shell, for onboarding and for scripts. The text below is the binary's own help output, captured at build time.

delegus --help
Usage: delegus <command> [options]

  Delegus verifies an AI agent's delegated authority to act (spec v0.3-rc1; v0.2 receipts supported).
  Every command prints one JSON object on stdout. Exit 0 on success
  (ALLOW), 1 on error, 2 when a decision is DENY or a receipt does not
  reverify.

Commands:
  conformance          Run the Delegus conformance vectors (v0.2; --v3 for v0.3) (needs @delegus/conformance installed)
  doctor               Check the API, your key and its subject; the first thing to run on day one
  key list             List the API keys of your subject (ids and labels only)
  key create           Issue an additional API key for your subject (rotation step 1); the key is printed once
  key revoke           Revoke one of your subject's API keys by its id (rotation step 2, or a leaked key)
  keygen               Generate an Ed25519 key and write it as a private JWK (mode 0600)
  org init             Create an organization account (owns Principals and relying parties; holds dashboard keys) (admin token)
  org show             Show an organization and its members (org key or admin token)
  org add-member       Attach an existing Principal or relying party to an organization (admin token)
  org key-create       Issue an org key with role read or admin, printed once (org:admin key or admin token)
  org key-list         List an organization's keys (ids and labels only)
  org key-revoke       Revoke an organization key by its id (org:admin key or admin token)
  org create           Create a managed Principal at Delegus whose signing key is --key (admin token, or an org:admin key)
  org register         Register a customer-hosted Principal (did:web) and get its domain-verification instructions (admin token, or an org:admin key)
  org verify           Run domain verification for a Principal now and print its state (Principal key)
  rp create            Create a Relying Party, managed (--slug) or hosted (--did), and print its API key once (admin token, or an org:admin key)
  agent create         Generate an Agent key (did:key) and write it as a private JWK (mode 0600)
  agent register       Add an Agent to the Principal's inventory (Principal key)
  agent disable        Kill switch: revoke every Grant naming the Agent (Principal key)
  grant create         Issue a Grant: allocate its status entry at Delegus, sign it locally with --key (Principal key)
  grant compile        Compile authority written in plain words into the exact capabilities a Grant will carry, with its read-back (offline)
  grant explain        Read a Grant back in words from its JSON, and name anything it carries that the read-back does not explain (offline)
  approval verify      Re-check a passkey approval record with nothing from Delegus: the person's assertion over the Grant's exact bytes (offline)
  grant revoke         Revoke a Grant; returns once every later /verify anywhere will deny it (Principal key)
  key retire           Retire a Principal signing key (rotation): existing Grants stay valid, new Grants must use an active key (Principal key)
  key compromise       Mark a Principal key compromised: every Grant it signed denies immediately (Principal key)
  proof sign           Sign a proof of grant with an Agent key, binding one Grant, one RP and one request
  verify               POST /verify as a Relying Party; prints the signed Receipt, exit 0 for ALLOW and 2 for DENY (RP key)
  outcome report       Append an Outcome Attestation to a decision (RP key, the RP in the receipt)
  decision get         Fetch a decision: its receipt and outcome ledger (RP key, the RP in the receipt)
  principal list       Principal directory: who is registered and verified, since when, with which keys (any key)
  principal show       One Principal from the directory (full record for its own key, its org or admin)
  decision list        List decisions newest first (RP key: own; org key: the org's relying parties; admin: any)
  decision export      Export decisions with full receipts and outcome ledgers (NDJSON to stdout, or --csv); follows cursors until done or --limit rows
  decision stats       Decisions and outcomes rolled up per Principal over a range (default last 30 days)
  receipt verify       Verify a receipt (no API key needed). Alone: signature under the published DID document and the public check. With --grant --proof --action: re-run the open checks with the artifacts fetched by hash and say exactly what was and was not reproduced (v0.2 and v0.3). --entitled (v0.3): open the commitments without a re-run
  chain verify         The auditor's chain: fetch (or read) a receipt's chain and re-verify every link offline: each receipt's signature, each relies_on opening against the prior receipt (D2), each prior decision ALLOW (D4), and each Grant you hold against its link's grant_hash and agent; with --policy, each Grant against the confirmed policy and the people across links. Exit 0 only when every link (and the policy) passes
  receipt inclusion    Prove a receipt is in its day's signed Merkle checkpoint (audit path to the root, root signature from the DID document; no key needed)
  checkpoint verify    Third-party check of a day's checkpoint: recompute the Merkle root from the published leaves and verify the signature (no key needed)
  checkpoint contains  Check that receipt ids (from `delegus decision list` or your logs) are leaves of a day's checkpoint
  action purchase      Print the canonical commerce:purchase Action for these wire fields
  action api-call      Print the canonical api:call Action for these wire fields

Global options:
  --api-url <url>        API origin (env DELEGUS_API_URL; default https://api.delegus.ai)
  --api-key <key>        RP or Principal API key (env DELEGUS_API_KEY)
  --admin-token <token>  Delegus admin token for onboarding (env DELEGUS_ADMIN_TOKEN)
  --json-compact         Print the result on one line
  --help, -h             Show help

Environment: DELEGUS_API_URL, DELEGUS_API_KEY, DELEGUS_ADMIN_TOKEN; the flags above override them.
Key files are Ed25519 private JWKs (kty OKP, crv Ed25519, x, d) written with mode 0600.
Arguments shown as <jws|file> or <json|file> take the value itself or the path of a file holding it.

Run 'delegus <command> --help' for the options of one command.

delegus conformance#

delegus conformance --help
Usage: delegus conformance [--impl <module>] [--only <id,id>] [--dir <path>]

  Run the Delegus conformance vectors (v0.2; --v3 for v0.3) (needs @delegus/conformance installed).

Options:
  --impl <module>  Module exporting an Implementation to test instead of @delegus/core
  --only <id,id>   Run only these vector ids
  --dir <path>     A cases/ + sets/ directory other than the shipped vectors

Global options:
  --api-url <url>        API origin (env DELEGUS_API_URL; default https://api.delegus.ai)
  --api-key <key>        RP or Principal API key (env DELEGUS_API_KEY)
  --admin-token <token>  Delegus admin token for onboarding (env DELEGUS_ADMIN_TOKEN)
  --json-compact         Print the result on one line
  --help, -h             Show help

delegus doctor#

delegus doctor --help
Usage: delegus doctor

  Check the API, your key and its subject; the first thing to run on day one.

Options:

Global options:
  --api-url <url>        API origin (env DELEGUS_API_URL; default https://api.delegus.ai)
  --api-key <key>        RP or Principal API key (env DELEGUS_API_KEY)
  --admin-token <token>  Delegus admin token for onboarding (env DELEGUS_ADMIN_TOKEN)
  --json-compact         Print the result on one line
  --help, -h             Show help

delegus key list#

delegus key list --help
Usage: delegus key list

  List the API keys of your subject (ids and labels only).

Options:

Global options:
  --api-url <url>        API origin (env DELEGUS_API_URL; default https://api.delegus.ai)
  --api-key <key>        RP or Principal API key (env DELEGUS_API_KEY)
  --admin-token <token>  Delegus admin token for onboarding (env DELEGUS_ADMIN_TOKEN)
  --json-compact         Print the result on one line
  --help, -h             Show help

delegus key create#

delegus key create --help
Usage: delegus key create [--label <label>]

  Issue an additional API key for your subject (rotation step 1); the key is printed once.

Options:
  --label <label>  A label for the new key

Global options:
  --api-url <url>        API origin (env DELEGUS_API_URL; default https://api.delegus.ai)
  --api-key <key>        RP or Principal API key (env DELEGUS_API_KEY)
  --admin-token <token>  Delegus admin token for onboarding (env DELEGUS_ADMIN_TOKEN)
  --json-compact         Print the result on one line
  --help, -h             Show help

delegus key revoke#

delegus key revoke --help
Usage: delegus key revoke --id <key_id>

  Revoke one of your subject's API keys by its id (rotation step 2, or a leaked key).

Options:
  --id <key_id>  The key id from `delegus key list`

Global options:
  --api-url <url>        API origin (env DELEGUS_API_URL; default https://api.delegus.ai)
  --api-key <key>        RP or Principal API key (env DELEGUS_API_KEY)
  --admin-token <token>  Delegus admin token for onboarding (env DELEGUS_ADMIN_TOKEN)
  --json-compact         Print the result on one line
  --help, -h             Show help

delegus keygen#

delegus keygen --help
Usage: delegus keygen --out <file> [--force]

  Generate an Ed25519 key and write it as a private JWK (mode 0600).

Options:
  --out <file>  File to write the JWK to
  --force       Overwrite an existing file

Global options:
  --api-url <url>        API origin (env DELEGUS_API_URL; default https://api.delegus.ai)
  --api-key <key>        RP or Principal API key (env DELEGUS_API_KEY)
  --admin-token <token>  Delegus admin token for onboarding (env DELEGUS_ADMIN_TOKEN)
  --json-compact         Print the result on one line
  --help, -h             Show help

delegus org init#

delegus org init --help
Usage: delegus org init --slug <slug> --name <name>

  Create an organization account (owns Principals and relying parties; holds dashboard keys) (admin token).

Options:
  --slug <slug>  Account slug (lowercase DNS label)
  --name <name>  Display name

Global options:
  --api-url <url>        API origin (env DELEGUS_API_URL; default https://api.delegus.ai)
  --api-key <key>        RP or Principal API key (env DELEGUS_API_KEY)
  --admin-token <token>  Delegus admin token for onboarding (env DELEGUS_ADMIN_TOKEN)
  --json-compact         Print the result on one line
  --help, -h             Show help

delegus org show#

delegus org show --help
Usage: delegus org show --id <org_id>

  Show an organization and its members (org key or admin token).

Options:
  --id <org_id>  The org id from `delegus org init`

Global options:
  --api-url <url>        API origin (env DELEGUS_API_URL; default https://api.delegus.ai)
  --api-key <key>        RP or Principal API key (env DELEGUS_API_KEY)
  --admin-token <token>  Delegus admin token for onboarding (env DELEGUS_ADMIN_TOKEN)
  --json-compact         Print the result on one line
  --help, -h             Show help

delegus org add-member#

delegus org add-member --help
Usage: delegus org add-member --id <org_id> --did <did:web>

  Attach an existing Principal or relying party to an organization (admin token).

Options:
  --id <org_id>    The org id
  --did <did:web>  The Principal's or relying party's DID

Global options:
  --api-url <url>        API origin (env DELEGUS_API_URL; default https://api.delegus.ai)
  --api-key <key>        RP or Principal API key (env DELEGUS_API_KEY)
  --admin-token <token>  Delegus admin token for onboarding (env DELEGUS_ADMIN_TOKEN)
  --json-compact         Print the result on one line
  --help, -h             Show help

delegus org key-create#

delegus org key-create --help
Usage: delegus org key-create --id <org_id> --role <read|admin> [--label <label>]

  Issue an org key with role read or admin, printed once (org:admin key or admin token).

Options:
  --id <org_id>        The org id
  --role <read|admin>  read: every GET about the org; admin: also onboarding, keys, revocation
  --label <label>      A label for the key

Global options:
  --api-url <url>        API origin (env DELEGUS_API_URL; default https://api.delegus.ai)
  --api-key <key>        RP or Principal API key (env DELEGUS_API_KEY)
  --admin-token <token>  Delegus admin token for onboarding (env DELEGUS_ADMIN_TOKEN)
  --json-compact         Print the result on one line
  --help, -h             Show help

delegus org key-list#

delegus org key-list --help
Usage: delegus org key-list --id <org_id>

  List an organization's keys (ids and labels only).

Options:
  --id <org_id>  The org id

Global options:
  --api-url <url>        API origin (env DELEGUS_API_URL; default https://api.delegus.ai)
  --api-key <key>        RP or Principal API key (env DELEGUS_API_KEY)
  --admin-token <token>  Delegus admin token for onboarding (env DELEGUS_ADMIN_TOKEN)
  --json-compact         Print the result on one line
  --help, -h             Show help

delegus org key-revoke#

delegus org key-revoke --help
Usage: delegus org key-revoke --id <org_id> --key-id <key_id>

  Revoke an organization key by its id (org:admin key or admin token).

Options:
  --id <org_id>      The org id
  --key-id <key_id>  The key id from `delegus org key-list`

Global options:
  --api-url <url>        API origin (env DELEGUS_API_URL; default https://api.delegus.ai)
  --api-key <key>        RP or Principal API key (env DELEGUS_API_KEY)
  --admin-token <token>  Delegus admin token for onboarding (env DELEGUS_ADMIN_TOKEN)
  --json-compact         Print the result on one line
  --help, -h             Show help

delegus org create#

delegus org create --help
Usage: delegus org create --slug <slug> --key <file> [--key-id <id>] [--org <org_id>]

  Create a managed Principal at Delegus whose signing key is --key (admin token, or an org:admin key).

Options:
  --slug <slug>   Principal slug (DID did:web:<domain>:org:<slug>)
  --key <file>    Principal key file from `delegus keygen`
  --key-id <id>   Key id fragment (default key-1)
  --org <org_id>  Attach to this organization (admin token; an org:admin key always uses its own)

Global options:
  --api-url <url>        API origin (env DELEGUS_API_URL; default https://api.delegus.ai)
  --api-key <key>        RP or Principal API key (env DELEGUS_API_KEY)
  --admin-token <token>  Delegus admin token for onboarding (env DELEGUS_ADMIN_TOKEN)
  --json-compact         Print the result on one line
  --help, -h             Show help

delegus org register#

delegus org register --help
Usage: delegus org register --did <did:web> [--org <org_id>]

  Register a customer-hosted Principal (did:web) and get its domain-verification instructions (admin token, or an org:admin key).

Options:
  --did <did:web>  The Principal's DID
  --org <org_id>   Attach to this organization (admin token)

Global options:
  --api-url <url>        API origin (env DELEGUS_API_URL; default https://api.delegus.ai)
  --api-key <key>        RP or Principal API key (env DELEGUS_API_KEY)
  --admin-token <token>  Delegus admin token for onboarding (env DELEGUS_ADMIN_TOKEN)
  --json-compact         Print the result on one line
  --help, -h             Show help

delegus org verify#

delegus org verify --help
Usage: delegus org verify --did <did:web>

  Run domain verification for a Principal now and print its state (Principal key).

Options:
  --did <did:web>  The Principal's DID

Global options:
  --api-url <url>        API origin (env DELEGUS_API_URL; default https://api.delegus.ai)
  --api-key <key>        RP or Principal API key (env DELEGUS_API_KEY)
  --admin-token <token>  Delegus admin token for onboarding (env DELEGUS_ADMIN_TOKEN)
  --json-compact         Print the result on one line
  --help, -h             Show help

delegus rp create#

delegus rp create --help
Usage: delegus rp create [--slug <slug>] [--did <did:web>] [--name <name>] [--proof-window <seconds>] [--org <org_id>]

  Create a Relying Party, managed (--slug) or hosted (--did), and print its API key once (admin token, or an org:admin key).

Options:
  --slug <slug>             Managed RP slug (exactly one of --slug, --did)
  --did <did:web>           Hosted RP DID (exactly one of --slug, --did)
  --name <name>             Display name
  --proof-window <seconds>  How long a proof of grant stays fresh
  --org <org_id>            Attach to this organization (admin token; an org:admin key always uses its own)

Global options:
  --api-url <url>        API origin (env DELEGUS_API_URL; default https://api.delegus.ai)
  --api-key <key>        RP or Principal API key (env DELEGUS_API_KEY)
  --admin-token <token>  Delegus admin token for onboarding (env DELEGUS_ADMIN_TOKEN)
  --json-compact         Print the result on one line
  --help, -h             Show help

delegus agent create#

delegus agent create --help
Usage: delegus agent create --out <file> [--force]

  Generate an Agent key (did:key) and write it as a private JWK (mode 0600).

Options:
  --out <file>  File to write the JWK to
  --force       Overwrite an existing file

Global options:
  --api-url <url>        API origin (env DELEGUS_API_URL; default https://api.delegus.ai)
  --api-key <key>        RP or Principal API key (env DELEGUS_API_KEY)
  --admin-token <token>  Delegus admin token for onboarding (env DELEGUS_ADMIN_TOKEN)
  --json-compact         Print the result on one line
  --help, -h             Show help

delegus agent register#

delegus agent register --help
Usage: delegus agent register --principal <did:web> --did <did:key>

  Add an Agent to the Principal's inventory (Principal key).

Options:
  --principal <did:web>  The Principal's DID (did:web)
  --did <did:key>        The Agent's DID

Global options:
  --api-url <url>        API origin (env DELEGUS_API_URL; default https://api.delegus.ai)
  --api-key <key>        RP or Principal API key (env DELEGUS_API_KEY)
  --admin-token <token>  Delegus admin token for onboarding (env DELEGUS_ADMIN_TOKEN)
  --json-compact         Print the result on one line
  --help, -h             Show help

delegus agent disable#

delegus agent disable --help
Usage: delegus agent disable --principal <did:web> --did <did:key>

  Kill switch: revoke every Grant naming the Agent (Principal key).

Options:
  --principal <did:web>  The Principal's DID (did:web)
  --did <did:key>        The Agent's DID

Global options:
  --api-url <url>        API origin (env DELEGUS_API_URL; default https://api.delegus.ai)
  --api-key <key>        RP or Principal API key (env DELEGUS_API_KEY)
  --admin-token <token>  Delegus admin token for onboarding (env DELEGUS_ADMIN_TOKEN)
  --json-compact         Print the result on one line
  --help, -h             Show help

delegus grant create#

delegus grant create --help
Usage: delegus grant create --principal <did:web> --key <file> --kid <kid> --agent <did:key> --authority <json|file> [--valid-from <iso>] [--valid-until <iso>] [--audience <did,did>] [--refuse-personal-data]

  Issue a Grant: allocate its status entry at Delegus, sign it locally with --key (Principal key).

Options:
  --principal <did:web>    The Principal's DID (did:web)
  --key <file>             Principal key file
  --kid <kid>              Verification method of --key in the Principal's DID document (did:web:…#key-n)
  --agent <did:key>        The Agent the Grant is for
  --authority <json|file>  JSON array of capabilities: [{action, constraints, resources?}]
  --valid-from <iso>       RFC 3339 UTC, whole seconds (default now)
  --valid-until <iso>      RFC 3339 UTC, whole seconds (default validFrom + 30 days; at most 90)
  --audience <did,did>     Comma-separated RP DIDs (default any registered RP)
  --refuse-personal-data   Refuse (exit 1) when the authority looks like it holds an email, phone or card number; by default the Grant is issued with `warnings`

Global options:
  --api-url <url>        API origin (env DELEGUS_API_URL; default https://api.delegus.ai)
  --api-key <key>        RP or Principal API key (env DELEGUS_API_KEY)
  --admin-token <token>  Delegus admin token for onboarding (env DELEGUS_ADMIN_TOKEN)
  --json-compact         Print the result on one line
  --help, -h             Show help

delegus grant compile#

delegus grant compile --help
Usage: delegus grant compile --sentence <text> [--agents <json|file>] [--relying-parties <json|file>] [--now <iso>]

  Compile authority written in plain words into the exact capabilities a Grant will carry, with its read-back (offline).

Options:
  --sentence <text>              e.g. "Let ordering-agent pay acme-* up to $250 per day until 2026-12-31, at Northfield only"
  --agents <json|file>           Agent names to did:key, e.g. {"ordering-agent": "did:key:z6Mk…"} (a did:key in the sentence needs none)
  --relying-parties <json|file>  Relying party names to DIDs, for "at <name> only"
  --now <iso>                    The clock (default now); the Grant starts at this second

Global options:
  --api-url <url>        API origin (env DELEGUS_API_URL; default https://api.delegus.ai)
  --api-key <key>        RP or Principal API key (env DELEGUS_API_KEY)
  --admin-token <token>  Delegus admin token for onboarding (env DELEGUS_ADMIN_TOKEN)
  --json-compact         Print the result on one line
  --help, -h             Show help

delegus grant explain#

delegus grant explain --help
Usage: delegus grant explain --grant <jws|json|file>

  Read a Grant back in words from its JSON, and name anything it carries that the read-back does not explain (offline).

Options:
  --grant <jws|json|file>  A Grant JWS, its decoded payload, or a compiled draft

Global options:
  --api-url <url>        API origin (env DELEGUS_API_URL; default https://api.delegus.ai)
  --api-key <key>        RP or Principal API key (env DELEGUS_API_KEY)
  --admin-token <token>  Delegus admin token for onboarding (env DELEGUS_ADMIN_TOKEN)
  --json-compact         Print the result on one line
  --help, -h             Show help

delegus approval verify#

delegus approval verify --help
Usage: delegus approval verify --record <json|file> [--grant <jws|file>] [--rp-id <id>] [--origin <url>]

  Re-check a passkey approval record with nothing from Delegus: the person's assertion over the Grant's exact bytes (offline).

Options:
  --record <json|file>  The delegus-approval-v1 record (as retrieved by its approval_record_hash)
  --grant <jws|file>    The Grant JWS: also check the record is about exactly these bytes
  --rp-id <id>          Require this WebAuthn relying party id (e.g. app.delegus.ai)
  --origin <url>        Require this ceremony origin (e.g. https://app.delegus.ai)

Global options:
  --api-url <url>        API origin (env DELEGUS_API_URL; default https://api.delegus.ai)
  --api-key <key>        RP or Principal API key (env DELEGUS_API_KEY)
  --admin-token <token>  Delegus admin token for onboarding (env DELEGUS_ADMIN_TOKEN)
  --json-compact         Print the result on one line
  --help, -h             Show help

delegus grant revoke#

delegus grant revoke --help
Usage: delegus grant revoke --principal <did:web> --id <urn:delegus:grant:…>

  Revoke a Grant; returns once every later /verify anywhere will deny it (Principal key).

Options:
  --principal <did:web>       The Principal's DID (did:web)
  --id <urn:delegus:grant:…>  The Grant id

Global options:
  --api-url <url>        API origin (env DELEGUS_API_URL; default https://api.delegus.ai)
  --api-key <key>        RP or Principal API key (env DELEGUS_API_KEY)
  --admin-token <token>  Delegus admin token for onboarding (env DELEGUS_ADMIN_TOKEN)
  --json-compact         Print the result on one line
  --help, -h             Show help

delegus key retire#

delegus key retire --help
Usage: delegus key retire --principal <did:web> --kid <kid>

  Retire a Principal signing key (rotation): existing Grants stay valid, new Grants must use an active key (Principal key).

Options:
  --principal <did:web>  Your Principal DID
  --kid <kid>            The key's DID URL

Global options:
  --api-url <url>        API origin (env DELEGUS_API_URL; default https://api.delegus.ai)
  --api-key <key>        RP or Principal API key (env DELEGUS_API_KEY)
  --admin-token <token>  Delegus admin token for onboarding (env DELEGUS_ADMIN_TOKEN)
  --json-compact         Print the result on one line
  --help, -h             Show help

delegus key compromise#

delegus key compromise --help
Usage: delegus key compromise --principal <did:web> --kid <kid>

  Mark a Principal key compromised: every Grant it signed denies immediately (Principal key).

Options:
  --principal <did:web>  The Principal's DID (did:web)
  --kid <kid>            The compromised key (did:web:…#key-n)

Global options:
  --api-url <url>        API origin (env DELEGUS_API_URL; default https://api.delegus.ai)
  --api-key <key>        RP or Principal API key (env DELEGUS_API_KEY)
  --admin-token <token>  Delegus admin token for onboarding (env DELEGUS_ADMIN_TOKEN)
  --json-compact         Print the result on one line
  --help, -h             Show help

delegus proof sign#

delegus proof sign --help
Usage: delegus proof sign --key <file> --grant <jws|file|id> --rp <did:web> --method <M> --url <url> --action <json|file> [--iat <seconds>] [--jti <nonce>]

  Sign a proof of grant with an Agent key, binding one Grant, one RP and one request.

Options:
  --key <file>           Agent key file
  --grant <jws|file|id>  The Grant JWS, a file holding it, or a bare Grant id
  --rp <did:web>         The Relying Party the proof of grant is for (aud)
  --method <M>           HTTP method of the request
  --url <url>            Absolute http(s) URL of the request
  --action <json|file>   The Action (see `delegus action …`)
  --iat <seconds>        Issued-at override, seconds since the epoch (default now)
  --jti <nonce>          Nonce override, 22–64 base64url chars (default 16 random bytes)

Global options:
  --api-url <url>        API origin (env DELEGUS_API_URL; default https://api.delegus.ai)
  --api-key <key>        RP or Principal API key (env DELEGUS_API_KEY)
  --admin-token <token>  Delegus admin token for onboarding (env DELEGUS_ADMIN_TOKEN)
  --json-compact         Print the result on one line
  --help, -h             Show help

delegus verify#

delegus verify --help
Usage: delegus verify --grant <jws|file> --proof <jws|file> --action <json|file> [--method <M>] [--url <url>] [--v3] [--requires <json|file>]

  POST /verify as a Relying Party; prints the signed Receipt, exit 0 for ALLOW and 2 for DENY (RP key).

Options:
  --grant <jws|file>      The Grant the Agent presented
  --proof <jws|file>      The proof of grant the Agent presented
  --action <json|file>    The Action built from the request
  --method <M>            With --url: check the proof of grant binds to this request before calling Delegus
  --url <url>             With --method: the URL the request arrived at
  --v3                    v0.3-rc1: expect a delegus-receipt-v2 and check authority (opened against authority_commitment), relies_on, requires and opening against it (fails closed)
  --requires <json|file>  With --v3: the prior decisions this action must rest on, [{ fingerprint, mode }]

Global options:
  --api-url <url>        API origin (env DELEGUS_API_URL; default https://api.delegus.ai)
  --api-key <key>        RP or Principal API key (env DELEGUS_API_KEY)
  --admin-token <token>  Delegus admin token for onboarding (env DELEGUS_ADMIN_TOKEN)
  --json-compact         Print the result on one line
  --help, -h             Show help

delegus outcome report#

delegus outcome report --help
Usage: delegus outcome report --receipt <drc_…> --type <type> [--occurred-at <iso>] [--note <text>] [--evidence-ref <ref>] [--resolution <r>] [--loss-amount <int>] [--currency <CCY>] [--correction-of <id>]

  Append an Outcome Attestation to a decision (RP key, the RP in the receipt).

Options:
  --receipt <drc_…>     The receipt id
  --type <type>         One of fulfilled, cancelled, dispute_opened, dispute_resolved, chargeback_received, chargeback_reversed, loss_reported
  --occurred-at <iso>   RFC 3339 UTC (default now)
  --note <text>         Free-text note
  --evidence-ref <ref>  Reference to the reporter's evidence
  --resolution <r>      One of agent_at_fault, agent_not_at_fault, indeterminate
  --loss-amount <int>   Loss in minor units
  --currency <CCY>      ISO 4217 currency of --loss-amount
  --correction-of <id>  The attestation this one corrects

Global options:
  --api-url <url>        API origin (env DELEGUS_API_URL; default https://api.delegus.ai)
  --api-key <key>        RP or Principal API key (env DELEGUS_API_KEY)
  --admin-token <token>  Delegus admin token for onboarding (env DELEGUS_ADMIN_TOKEN)
  --json-compact         Print the result on one line
  --help, -h             Show help

delegus decision get#

delegus decision get --help
Usage: delegus decision get --receipt <drc_…>

  Fetch a decision: its receipt and outcome ledger (RP key, the RP in the receipt).

Options:
  --receipt <drc_…>  The receipt id

Global options:
  --api-url <url>        API origin (env DELEGUS_API_URL; default https://api.delegus.ai)
  --api-key <key>        RP or Principal API key (env DELEGUS_API_KEY)
  --admin-token <token>  Delegus admin token for onboarding (env DELEGUS_ADMIN_TOKEN)
  --json-compact         Print the result on one line
  --help, -h             Show help

delegus principal list#

delegus principal list --help
Usage: delegus principal list [--kind <managed|hosted>] [--state <verified|unverified>] [--limit <n>] [--cursor <did>]

  Principal directory: who is registered and verified, since when, with which keys (any key).

Options:
  --kind <managed|hosted>        Filter
  --state <verified|unverified>  Filter
  --limit <n>                    Page size (≤ 200)
  --cursor <did>                 next_cursor from the previous page

Global options:
  --api-url <url>        API origin (env DELEGUS_API_URL; default https://api.delegus.ai)
  --api-key <key>        RP or Principal API key (env DELEGUS_API_KEY)
  --admin-token <token>  Delegus admin token for onboarding (env DELEGUS_ADMIN_TOKEN)
  --json-compact         Print the result on one line
  --help, -h             Show help

delegus principal show#

delegus principal show --help
Usage: delegus principal show --did <did:web>

  One Principal from the directory (full record for its own key, its org or admin).

Options:
  --did <did:web>  The Principal's DID (did:web)

Global options:
  --api-url <url>        API origin (env DELEGUS_API_URL; default https://api.delegus.ai)
  --api-key <key>        RP or Principal API key (env DELEGUS_API_KEY)
  --admin-token <token>  Delegus admin token for onboarding (env DELEGUS_ADMIN_TOKEN)
  --json-compact         Print the result on one line
  --help, -h             Show help

delegus decision list#

delegus decision list --help
Usage: delegus decision list [--rp <did:web>] [--decision <ALLOW|DENY>] [--reason <code>] [--since <iso>] [--until <iso>] [--limit <n>] [--cursor <receipt_id>]

  List decisions newest first (RP key: own; org key: the org's relying parties; admin: any).

Options:
  --rp <did:web>           One relying party
  --decision <ALLOW|DENY>  Filter
  --reason <code>          DENY reason filter
  --since <iso>            evaluated_at ≥
  --until <iso>            evaluated_at <
  --limit <n>              Page size (≤ 200)
  --cursor <receipt_id>    next_cursor from the previous page

Global options:
  --api-url <url>        API origin (env DELEGUS_API_URL; default https://api.delegus.ai)
  --api-key <key>        RP or Principal API key (env DELEGUS_API_KEY)
  --admin-token <token>  Delegus admin token for onboarding (env DELEGUS_ADMIN_TOKEN)
  --json-compact         Print the result on one line
  --help, -h             Show help

delegus decision export#

delegus decision export --help
Usage: delegus decision export [--rp <did:web>] [--since <iso>] [--until <iso>] [--decision <ALLOW|DENY>] [--csv] [--limit <n>]

  Export decisions with full receipts and outcome ledgers (NDJSON to stdout, or --csv); follows cursors until done or --limit rows.

Options:
  --rp <did:web>           One relying party
  --since <iso>            evaluated_at ≥
  --until <iso>            evaluated_at <
  --decision <ALLOW|DENY>  Filter
  --csv                    CSV instead of NDJSON (one API page of up to 5000 rows)
  --limit <n>              Stop after this many rows (NDJSON)

Global options:
  --api-url <url>        API origin (env DELEGUS_API_URL; default https://api.delegus.ai)
  --api-key <key>        RP or Principal API key (env DELEGUS_API_KEY)
  --admin-token <token>  Delegus admin token for onboarding (env DELEGUS_ADMIN_TOKEN)
  --json-compact         Print the result on one line
  --help, -h             Show help

delegus decision stats#

delegus decision stats --help
Usage: delegus decision stats [--rp <did:web>] [--principal <did:web>] [--since <iso>] [--until <iso>]

  Decisions and outcomes rolled up per Principal over a range (default last 30 days).

Options:
  --rp <did:web>         One relying party
  --principal <did:web>  One Principal
  --since <iso>          inclusive
  --until <iso>          exclusive

Global options:
  --api-url <url>        API origin (env DELEGUS_API_URL; default https://api.delegus.ai)
  --api-key <key>        RP or Principal API key (env DELEGUS_API_KEY)
  --admin-token <token>  Delegus admin token for onboarding (env DELEGUS_ADMIN_TOKEN)
  --json-compact         Print the result on one line
  --help, -h             Show help

delegus receipt verify#

delegus receipt verify --help
Usage: delegus receipt verify --receipt <json|jws|file> [--grant <jws|file>] [--proof <jws|file>] [--action <json|file>] [--proof-window <seconds>] [--evidence <dir>] [--consumption-snapshot <json|file>] [--entitled] [--authority <json|file>] [--authority-opening <base64url>] [--capability-key-opening <base64url>] [--relies-on <json|file>] [--requires <json|file>] [--priors <json|file>] [--disclosure <json|file>] [--did-document <json|file>]

  Verify a receipt (no API key needed). Alone: signature under the published DID document and the public check. With --grant --proof --action: re-run the open checks with the artifacts fetched by hash and say exactly what was and was not reproduced (v0.2 and v0.3). --entitled (v0.3): open the commitments without a re-run.

Options:
  --receipt <json|jws|file>             The receipt JSON as printed by `delegus verify`, or its JWS
  --grant <jws|file>                    Re-run: the Grant the RP presented (v1 receipts: required)
  --proof <jws|file>                    Re-run: the proof of grant the RP presented (v1 receipts: required)
  --action <json|file>                  Re-run: the Action the RP presented (v1 receipts: required)
  --proof-window <seconds>              Re-run: the RP's proof-of-grant window at the time (default 60)
  --evidence <dir>                      Re-run: a directory of artifacts already held, one file per sha256 (named <hex> or sha256-<hex>); anything missing is fetched by hash. With --did-document this is fully offline
  --consumption-snapshot <json|file>    Re-run, v0.3 with a budget: the consumption snapshot the receipt pins (entitled material); without it P21 and the decision are reported as not reproduced
  --entitled                            v2 receipts: also open authority_commitment (and capability_key_commitment), reproduce relies_on_hash and requires_hash, and each dependency (from --disclosure and/or --priors); exit 0 only when everything was reproduced
  --authority <json|file>               With --entitled: the plaintext Capability, or a stored response carrying it and its openings (default: `authority` in the --receipt JSON)
  --authority-opening <base64url>       With --entitled: the opening of authority_commitment (default: `authority_opening` in the --receipt JSON, --authority response or --disclosure package)
  --capability-key-opening <base64url>  With --entitled: the opening of evidence.consumption.capability_key_commitment (default: `capability_key_opening`, as for --authority-opening)
  --relies-on <json|file>               With --entitled: the plaintext relies_on entries (default: `relies_on` in the --receipt JSON)
  --requires <json|file>                With --entitled: the requires the relying party sent
  --priors <json|file>                  With --entitled: a JSON array of prior /verify responses (receipt + opening) or { receipt, nonce }
  --disclosure <json|file>              With --entitled: the dependency disclosure package (GET /decisions/{id}/disclosure) or its relies_on entries
  --did-document <json|file>            The service DID document to take the receipt keys from (default: fetched from the API)

Global options:
  --api-url <url>        API origin (env DELEGUS_API_URL; default https://api.delegus.ai)
  --api-key <key>        RP or Principal API key (env DELEGUS_API_KEY)
  --admin-token <token>  Delegus admin token for onboarding (env DELEGUS_ADMIN_TOKEN)
  --json-compact         Print the result on one line
  --help, -h             Show help

delegus chain verify#

From the next SDK release. It isn't in the published @delegus/sdk on npm yet.

delegus chain verify --help
Usage: delegus chain verify [--id <drc_…>] [--chain <json|file>] [--grants <dir|file,...>] [--did-document <json|file>] [--policy <json|file>]

  The auditor's chain: fetch (or read) a receipt's chain and re-verify every link offline: each receipt's signature, each relies_on opening against the prior receipt (D2), each prior decision ALLOW (D4), and each Grant you hold against its link's grant_hash and agent; with --policy, each Grant against the confirmed policy and the people across links. Exit 0 only when every link (and the policy) passes.

Options:
  --id <drc_…>                The root receipt id (fetched with the API key; its relying party, principal or org)
  --chain <json|file>         A chain as returned by GET /decisions/{id}/chain, for a fully offline run (then --did-document is needed too)
  --grants <dir|file,...>     The company's Grant JWS files (one JWS per file, or a directory of them); matched to links by sha256
  --did-document <json|file>  The service DID document to take the receipt keys from (default: fetched from the API)
  --policy <json|file>        The confirmed policy as @delegus/authority-map maps it (delegus-pack-authority-map-v1): each link's Grant is compared to the holder's authority (matches, narrower, wider) with the rule ids it traces to, and the agents across links are checked where the policy wants different people (dual control, no self-approval, a quorum)

Global options:
  --api-url <url>        API origin (env DELEGUS_API_URL; default https://api.delegus.ai)
  --api-key <key>        RP or Principal API key (env DELEGUS_API_KEY)
  --admin-token <token>  Delegus admin token for onboarding (env DELEGUS_ADMIN_TOKEN)
  --json-compact         Print the result on one line
  --help, -h             Show help

delegus receipt inclusion#

delegus receipt inclusion --help
Usage: delegus receipt inclusion --id <drc_…>

  Prove a receipt is in its day's signed Merkle checkpoint (audit path to the root, root signature from the DID document; no key needed).

Options:
  --id <drc_…>  The receipt id

Global options:
  --api-url <url>        API origin (env DELEGUS_API_URL; default https://api.delegus.ai)
  --api-key <key>        RP or Principal API key (env DELEGUS_API_KEY)
  --admin-token <token>  Delegus admin token for onboarding (env DELEGUS_ADMIN_TOKEN)
  --json-compact         Print the result on one line
  --help, -h             Show help

delegus checkpoint verify#

delegus checkpoint verify --help
Usage: delegus checkpoint verify [--day <YYYY-MM-DD>]

  Third-party check of a day's checkpoint: recompute the Merkle root from the published leaves and verify the signature (no key needed).

Options:
  --day <YYYY-MM-DD>  UTC day (default: the latest closed day)

Global options:
  --api-url <url>        API origin (env DELEGUS_API_URL; default https://api.delegus.ai)
  --api-key <key>        RP or Principal API key (env DELEGUS_API_KEY)
  --admin-token <token>  Delegus admin token for onboarding (env DELEGUS_ADMIN_TOKEN)
  --json-compact         Print the result on one line
  --help, -h             Show help

delegus checkpoint contains#

delegus checkpoint contains --help
Usage: delegus checkpoint contains --day <YYYY-MM-DD> --ids <id,id|file>

  Check that receipt ids (from `delegus decision list` or your logs) are leaves of a day's checkpoint.

Options:
  --day <YYYY-MM-DD>  UTC day
  --ids <id,id|file>  Comma-separated receipt ids, or a file with one per line

Global options:
  --api-url <url>        API origin (env DELEGUS_API_URL; default https://api.delegus.ai)
  --api-key <key>        RP or Principal API key (env DELEGUS_API_KEY)
  --admin-token <token>  Delegus admin token for onboarding (env DELEGUS_ADMIN_TOKEN)
  --json-compact         Print the result on one line
  --help, -h             Show help

delegus action purchase#

delegus action purchase --help
Usage: delegus action purchase --resource <r> --amount <int> --currency <CCY>

  Print the canonical commerce:purchase Action for these wire fields.

Options:
  --resource <r>    What is bought
  --amount <int>    Amount in minor units
  --currency <CCY>  ISO 4217 currency

Global options:
  --api-url <url>        API origin (env DELEGUS_API_URL; default https://api.delegus.ai)
  --api-key <key>        RP or Principal API key (env DELEGUS_API_KEY)
  --admin-token <token>  Delegus admin token for onboarding (env DELEGUS_ADMIN_TOKEN)
  --json-compact         Print the result on one line
  --help, -h             Show help

delegus action api-call#

delegus action api-call --help
Usage: delegus action api-call --method <M> --resource <url>

  Print the canonical api:call Action for these wire fields.

Options:
  --method <M>      HTTP method (uppercased)
  --resource <url>  Absolute http(s) resource URI

Global options:
  --api-url <url>        API origin (env DELEGUS_API_URL; default https://api.delegus.ai)
  --api-key <key>        RP or Principal API key (env DELEGUS_API_KEY)
  --admin-token <token>  Delegus admin token for onboarding (env DELEGUS_ADMIN_TOKEN)
  --json-compact         Print the result on one line
  --help, -h             Show help

SDK and CLI: v0.3 additions#

Additions to SDK and CLI for the v0.3 release candidate, as published in @delegus/sdk 0.2.0 (packages/sdk/src/v3.ts, v3-fields.ts, client.ts, actions.ts, cli.ts). Names, inputs and results below are copied from that code.

Release candidate. These additions follow v0.3-rc1 and ship in @delegus/sdk 0.2.0, the first release that carries v0.3; 0.1.4 has none of it. Nothing here changes a v0.2 call: a relying party on delegus-base-v1 keeps getting v1 receipts.

Most of the /docs/sdk page is generated at build time from the TypeScript source and the CLI's own help output. The text below is the explanation that goes above them: what each v0.3 piece is for and how the pieces fit.

SDK 0.2.0 also adds: decisions.get() returning the fields that come back beside the receipt (the authority and its openings); a disclosure(receiptId) method for GET /decisions/{receipt_id}/disclosure; signature checking of v1 receipts; and request binding, where proof_hash and grant_hash must match what was sent.

Choosing the protocol#

delegus-base-v3 is the default profile for relying parties (PATCH /relying-parties/{did} with { "profile": ... } sets it; only an org:admin key of the organization that owns the relying party, or Delegus staff, may change it, and moving a relying party back to an older profile is staff-only). verify takes a protocol option:

ts
import { Delegus } from "@delegus/sdk";

const delegus = new Delegus({ apiKey: process.env.DELEGUS_API_KEY });
const d = await delegus.verify({ grant, proof, action, protocol: "v0.3" });

Verifying under v0.3#

delegus.verify(req: VerifyRequestV3): Promise<VerifyResponseV3>#

VerifyRequestV3 is the v0.2 VerifyRequest (grant, proof, action, optional request) plus:

MemberTypeMeaning
protocol"v0.3"Required to opt in
requiresDependencyDeclaration[], optionalThe earlier decisions this action must rest on: 1–8 distinct { fingerprint, mode }. Validated before sending (TypeError if malformed).

VerifyResponseV3 is the v2 receipt (ReceiptV2) plus the members returned beside it:

MemberTypePresent
authorityCapabilityExactly when the receipt pins authority_commitment
authority_openingstring (43 characters)Same
capability_key_openingstringExactly when the receipt pins evidence.consumption.capability_key_commitment
relies_onReliesOnEntry[]Exactly when the receipt pins relies_on_hash
openingDependencyOpening ({ fingerprint, nonce })ALLOW only

Before returning, the SDK checks the response against the receipt and throws ResponseIntegrityError (fail closed) unless all of these hold:

A pinned commitment is never trusted without its opening.

Building v0.3 Actions: actionsV3#

FunctionBuilds
actionsV3.purchase({ resource, amount, currency, relies_on? })commerce:purchase
actionsV3.quote({ resource, amount, currency, relies_on? })commerce:quote
actionsV3.accept({ resource, amount, currency, relies_on? })commerce:accept
actionsV3.fulfil({ resource, relies_on? })commerce:fulfil
actionsV3.apiCall({ method, resource, relies_on? })api:call
actionsV3.withDependencies(action, { relies_on })Adds relies_on to an Action built elsewhere

Each validates the result with the engine's v0.3 Action rules (check P15) and throws if it is malformed. withDependencies throws if the Action already declares relies_on or carries a transaction handle. None of them can add a transaction handle: under v0.3 an Action never carries one.

dependencyOn(response, mode): DependencyDeclaration#

Returns the relies_on entry a later action declares for an earlier decision: { fingerprint, mode }, taken from the earlier response's opening. It never includes the nonce. Throws TypeError when mode is not PRIOR_DECISION or CURRENT_AUTHORITY, or when the response has no opening (every DENY).

ts
import { dependencyOn, actionsV3 } from "@delegus/sdk";

const entry = dependencyOn(r1, "CURRENT_AUTHORITY");
const action = actionsV3.accept({ resource: "compute/gpu-hours/order-7731", amount: 1840000, currency: "USD", relies_on: [entry] });

Opening checks#

v0.3 receipts pin the matched capability, and for a budgeted capability its internal key, by commitment: a hash over the value together with a 32-byte random opening. These two functions answer one question each: does this opening open this commitment to this value?

checkAuthorityOpening(commitment: string, opening: string, authority: unknown): boolean#

InputWhat to pass
commitmentThe receipt's authority_commitment
openingauthority_opening: 43 characters of unpadded base64url (32 bytes)
authorityThe plaintext capability: authority from the response, GET /decisions/{receipt_id} or the disclosure package

Result: true when the opening opens the commitment to exactly that capability (canonicalized with JCS), otherwise false. A malformed opening or commitment gives false, never a fallback. Throws TypeError when authority is not a JSON object or contains a number that is not a safe integer (the protocol has no floats).

checkCapabilityKeyOpening(commitment: string, opening: string, authority: unknown): boolean#

InputWhat to pass
commitmentThe receipt's evidence.consumption.capability_key_commitment
openingcapability_key_opening
authorityThe plaintext capability. The function derives the key itself as sha256(JCS(authority)); you never handle the key.

Result and errors: as for checkAuthorityOpening.

Both call the engine's own checks (verifyAuthorityOpening, verifyCapabilityKeyOpening in @delegus/core) after the SDK's integers-only rule. They replace the pre-H2 authorityHash, which no longer exists.

ts
import { checkAuthorityOpening } from "@delegus/sdk";

const ok = checkAuthorityOpening(stored.authority_commitment, stored.authority_opening, stored.authority);
if (!ok) throw new Error("stored authority does not match the receipt");

Verifying a v2 receipt later#

verifyReceiptV2Public({ receipt, body?, keys, did? }): PublicVerificationV2#

What anyone holding the receipt can check: signature, body equals payload (when body is given), v2 shape and profile, decision/reason/results agreement, and each v2 field well formed. Returns { ok, level: "public", receipt_id, decision, reason, checks: V2Check[] }, where each V2Check is { check, ok, detail }. It says nothing about why the decision was made.

Also on the client, with the published keys fetched for you: delegus.receipts.verifyV2Public(receiptJws, { body?, keys?, did? }).

verifyReceiptV2Entitled(input): EntitledVerificationV2#

For the receipt's relying party or principal. Runs the public checks, then reproduces what the receipt pins from the material you supply.

InputMeaning
receipt, body?, keys, did?As for the public check
authority?The plaintext capability. Default: authority in disclosure
authorityOpening?Opens authority_commitment. Default: authority_opening in disclosure
capabilityKeyOpening?Opens capability_key_commitment. Default: capability_key_opening in disclosure
reliesOn?The relies_on entries returned beside the receipt
requires?The requires you sent
disclosure?The disclosure package from GET /decisions/{receipt_id}/disclosure, or its relies_on array
priors?PriorReceipt[]: earlier receipts you hold, each { receipt, nonce, fingerprint? }

Result (EntitledVerificationV2):

MemberMeaning
oktrue only when every applicable part was reproduced (D5 counts as Delegus's attestation). Anything not supplied or only partly reproducible makes it false.
authority, capability_key, relies_on, requiresEach a PlaintextComparison: { result, pinned, computed, detail? }, where result is match, mismatch, not_supplied, not_in_receipt or invalid
dependencies[]One DependencyVerification per entry: { index, fingerprint, mode, result, checks, receipt_id? }. result is reproduced, partial, failed or not_supplied. checks covers D2–D7, receipt_hash and evidence_commitment, each with a status of reproduced, failed, attested (D5), not_reproducible (material missing) or skipped (D6, D7 and evidence_commitment for PRIOR_DECISION)
unmatched[]Supplied priors or disclosure entries that name no entry of this receipt, or contradict themselves

Also on the client: delegus.receipts.verifyV2Entitled(receiptJws, { …same members…, keys? }).

Neither function re-runs the checks P1 to P21 from the Grant, Proof and Action: they check the commitments, the hashes and the per-dependency results. Re-evaluating a v2 receipt offline is not available yet.

Other v0.3 exports#

ExportWhat it does
parseVerifyResponseV3(response, sent, trust)The response check verify runs, for a response you obtained another way. Throws ResponseIntegrityError.
splitV2Response(response)Separates the signed body from the members beside it. Returns an error string if it is not a receipt.
parseReceiptV2Body(payload)A ReceiptV2Body, or null unless well formed on delegus-base-v3
verifyReceiptV2Signature(receiptJws, keys, did?)The engine's signature check, narrowed to v2
reliesOnHash(entries), requiresHash(requires)Recompute relies_on_hash and requires_hash. Throw TypeError on malformed input.
validateRequires(requires), isReliesOnEntries(v)Shape checks for requires and recorded entries
decisionDisagreement(body)null when decision, reason and results agree; otherwise what disagrees
EVALUATION_ORDER_V3The v0.3 check order, P1 through T7
PROFILE_V3, RECEIPT_VERSION_V2, v3FieldsThe v0.3 wire names in one place

CLI#

delegus verify --v3 [--requires <json|file>]#

--v3 expects a delegus-receipt-v2 and runs the same response checks as verify({ protocol: "v0.3" }), failing closed. --requires takes the [{ fingerprint, mode }] list and needs --v3. Exit 0 for ALLOW, 2 for DENY.

delegus receipt verify with a v2 receipt#

--receipt accepts the JSON printed by delegus verify --v3, a stored /verify response, a GET /decisions/{receipt_id} response body, or the bare JWS. A v2 receipt is checked publicly by default; --entitled adds reproduction. No API key is needed.

FlagMeaning
--entitledAlso open authority_commitment (and capability_key_commitment), reproduce relies_on_hash and requires_hash, and each dependency (from --disclosure and/or --priors); exit 0 only when everything was reproduced
--authority <json\|file>With --entitled: the plaintext capability, or a stored response carrying it and its openings (default: authority in the --receipt JSON)
--authority-opening <base64url>With --entitled: the opening of authority_commitment (default: authority_opening in the --receipt JSON, --authority response or --disclosure package)
--capability-key-opening <base64url>With --entitled: the opening of evidence.consumption.capability_key_commitment (default: capability_key_opening, found the same way)
--relies-on <json\|file>With --entitled: the plaintext relies_on entries (default: relies_on in the --receipt JSON)
--requires <json\|file>With --entitled: the requires the relying party sent
--priors <json\|file>With --entitled: a JSON array of earlier /verify responses (receipt and opening) or { receipt, nonce } objects
--disclosure <json\|file>With --entitled: the disclosure package (GET /decisions/{receipt_id}/disclosure) or its relies_on entries
--did-document <json\|file>The service DID document to take receipt keys from (default: fetched from the API)

Rules the CLI enforces: every plaintext flag needs --entitled; --grant, --proof, --action and --proof-window are refused for a v2 receipt; every v2 flag is refused for a v1 receipt. Exit codes: 0 when ok, 2 when not, 1 for a usage error.

Opening flags are needed only when the receipt JSON you pass does not already carry the openings, for example when you kept the receipt and its openings in separate places:

bash
# The receipt alone (bare JWS), with the plaintext capability and both openings kept separately
delegus receipt verify \
  --receipt receipt.jws \
  --entitled \
  --authority capability.json \
  --authority-opening "$AUTHORITY_OPENING" \
  --capability-key-opening "$CAPABILITY_KEY_OPENING" \
  --did-document did.json

The output is the EntitledVerificationV2 object as JSON. With the right capability and openings, authority.result and capability_key.result are match. A wrong opening gives mismatch and exit 2. A receipt that pins a commitment you supplied no opening for gives not_supplied and exit 2. A capability-key opening for a receipt that pins no such commitment is reported, not ignored.

If you stored the full /verify response, the openings come with it and the flags can be left out:

bash
delegus receipt verify --receipt response.json --entitled --requires requires.json --disclosure disclosure.json

decisions.get() (and so the CLI's delegus decision get) returns the authority and openings the API returns beside the receipt, so its output can go straight to receipt verify. delegus.disclosure(receiptId) fetches GET /decisions/{receipt_id}/disclosure with an entitled key.

No CLI command builds a v0.3 Action with relies_on (there is action purchase and action api-call only); write the Action JSON by hand and sign it with delegus proof sign --action.