Skip to main content
Glama

verify_receipt

Read-only

Verify a CodeRifts signed chain-receipt you ALREADY HOLD: cryptographic authenticity (signature + key id), body binding, and — when lifecycle indices are available — whether it is currently valid authorization (not expired, superseded, or revoked) for a stated operation/target.

Use this when:

  • You already obtained a chain_receipt / receipt token from a prior preflight (or CI artifact) and are about to act (merge/deploy) under that receipt.

  • A contract-gate or policy requires offline/online proof that the receipt is authentic for this change before proceeding.

  • You must distinguish "signature ok" from "currently authorized" (stale or superseded receipts must not be treated as live approval).

Do not use when:

  • You do not have a receipt yet — call coderifts.preflight_change_set first.

  • You need a NEW decision for a changed base→head set — preflight again; verify_receipt does not re-diff specs.

  • The receipt you hold binds a different operation or target than the one you are about to perform — call coderifts.preflight_change_set with context.operation set to that operation (a merge receipt does not authorize a deploy); verify_receipt cannot re-scope or re-issue a decision.

  • You only need human-readable history of an old decision_id without a receipt token — use coderifts.get_decision_details.

  • The change set itself is unknown or incomplete — fix the change set and preflight; do not "verify" a placeholder.

Inputs: receipt token (required); optional intended context (operation, environment, fingerprint, target_id, audience, repository/branch/pull_request, base/head) and the body_hash-bound decision_result envelope. 30s clock-skew leeway on expiry. A 0s grace for declared destructive production operations is defined in the policy but is unreachable today: the intended-context schema has no destructive field, so nothing can declare one and the 30s leeway always applies. Returns { valid, status, currently_authorized (bool|null), reason, payload, authz_* }. Branch on currently_authorized; null = not evaluated.

When a decision envelope is also in hand (e.g. from a prior preflight), its control_envelope.next_agent_step (if present) is structured remediation guidance the agent MAY follow after a non-CONTINUE decision — still branch on execution_action; next_agent_step is suggestion, not permission.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
baseNoIntended base commit/ref SHA the receipt must match (signed-wins vs envelope.base)
headNoIntended head commit/ref SHA the receipt must match (signed-wins vs envelope.head)
tokenYesThe chain receipt token (base64url(body).base64url(signature))
branchNoIntended branch the receipt must bind (place binding; optional)
audienceNoIntended audience — must match the receipt
operationNoIntended operation the receipt must authorize (conventional: merge|deploy|tool_call|publish). Triggers authorization evaluation when non-empty; supply decision_result for full scope binding.
target_idNoIntended apply-site target the receipt must bind
repositoryNoIntended repository the receipt must bind (place binding; optional)
environmentNoIntended environment (e.g. production) — must match the receipt
fingerprintNoIntended change fingerprint — must equal the receipt fp
pull_requestNoIntended pull-request id the receipt must bind (place binding; optional)
decision_resultNoThe body_hash-bound decision envelope (carries operation/target/decision). Required for a meaningful AUTHORIZATION evaluation of scope; without it, intended context alone fails closed on authorization (currently_authorized false) while signature status remains independent. Full schema: https://coderifts.com/schemas/decision-result.v1.consumer.json.

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
validYestrue iff status is VERIFIED_CURRENT or RETIRED_KEY_VALID_AT_ISSUE
reasonNo
statusYes
payloadNo
authz_noteNoPresent when no intended context supplied: status reflects signature+expiry only
authz_stateNoLifecycle state from isCurrentlyAuthorized when authorization is evaluated (optional; omitted when currently_authorized is null)
authz_reasonNoWhen currently_authorized=false: the deny reason (operation_mismatch, decision_not_allow, superseded, expired, target_mismatch, environment_mismatch, …)
authz_statusNoAuthorization-level status (VERIFIED_WRONG_ENVIRONMENT / VERIFIED_SUPERSEDED / VERIFIED_SCOPE_MISMATCH / …)
caller_valueNoCaller claim that differed from the signed envelope
signed_valueNoSigned envelope slot when signed-wins fail-closed (source_binding_mismatch)
binding_levelNoplace_and_content | content_only — forensic, not a second verdict
correlation_idNoRoute-owned trace id (ID828); always a non-empty string on 200
currently_authorizedYesWhether the receipt currently authorizes the intended operation/target/fp (§106). null means authorization could not be evaluated (e.g. no intended context) — not unauthorized and not authorized.

Schema Changelog

Changes observed during successful MCP inspections. Dates show when Glama detected each change.

  1. Changed1 schema field changed
    • changedOutput schema / properties / status / enum
      Previous value: -[
      -  "VERIFIED_CURRENT",
      -  "VERIFIED_EXPIRED",
      -  "VERIFIED_WRONG_AUDIENCE",
      -  "VERIFIED_WRONG_ENVIRONMENT",
      -  "VERIFIED_SUPERSEDED",
      -  "VERIFIED_SCOPE_MISMATCH",
      -  "UNKNOWN_KEY",
      -  "RETIRED_KEY_VALID_AT_ISSUE",
      -  "INVALID_SIGNATURE",
      -  "MALFORMED",
      -  "UNSUPPORTED_VERSION",
      -  "REGISTRY_UNREACHABLE"
      -]New value: +[
      +  "VERIFIED_CURRENT",
      +  "VERIFIED_EXPIRED",
      +  "VERIFIED_WRONG_AUDIENCE",
      +  "VERIFIED_WRONG_ENVIRONMENT",
      +  "VERIFIED_SUPERSEDED",
      +  "VERIFIED_SCOPE_MISMATCH",
      +  "VERIFIED_UNBOUND_OPERATION",
      +  "VERIFIED_UNBOUND_TARGET",
      +  "VERIFIED_UNBOUND_REPOSITORY",
      +  "VERIFIED_UNBOUND_BRANCH",
      +  "VERIFIED_UNBOUND_PULL_REQUEST",
      +  "UNKNOWN_KEY",
      +  "UNKNOWN_KEY_STATUS",
      +  "RETIRED_KEY_VALID_AT_ISSUE",
      +  "KEY_RETIRED_AFTER_SIGNING",
      +  "REVOKED_KEY",
      +  "REVOKED_KEY_UNDECIDABLE",
      +  "KEY_REVOKED",
      +  "REVOCATION_UNDECIDABLE",
      +  "AUTHORIZATION_UNDECIDABLE",
      +  "INVALID_SIGNATURE",
      +  "MALFORMED",
      +  "UNSUPPORTED_VERSION",
      +  "REGISTRY_UNREACHABLE"
      +]
  2. Changed1 schema field changed
    • changedInput schema / properties / decision_result / properties / derivation / description
      Previous value: -"ID637 6b additive. Present only when derivation:\"server\" produced this envelope. { source: github_compare, base_sha, head_sha }. Covered by body_hash; not fingerprint."New value: +"ID637 6b additive. Present only when derivation:\"server\" produced this envelope. { source, platform?, base_sha, head_sha }. Covered by body_hash; not fingerprint."
  3. Changed1 schema field changed
    • addedInput schema / properties / decision_result / properties / derivation
      Added value: +{
      +  "description": "ID637 6b additive. Present only when derivation:\"server\" produced this envelope. { source: github_compare, base_sha, head_sha }. Covered by body_hash; not fingerprint.",
      +  "type": [
      +    "object",
      +    "null"
      +  ]
      +}
  4. Changed2 schema fields changed
    • addedInput schema / properties / decision_result / properties / audience
      Added value: +{
      +  "type": [
      +    "string",
      +    "null"
      +  ]
      +}
    • addedInput schema / properties / decision_result / properties / authority
      Added value: +{
      +  "description": "ID963 additive. { audience, tenant_scope: bound|unbound, binding_proven_at? }. Informational — not permission, not a verify-receipt gate, not an ACL.",
      +  "type": [
      +    "object",
      +    "null"
      +  ]
      +}
  5. Changed1 schema field changed
    • addedInput schema / properties / decision_result / properties / blast_radius
      Added value: +{
      +  "description": "ID27 additive COUNTS (not a score). Not permission.",
      +  "properties": {
      +    "consumers_declared": {
      +      "minimum": 0,
      +      "type": "integer"
      +    },
      +    "consumers_observed": {
      +      "minimum": 0,
      +      "type": "integer"
      +    },
      +    "endpoints": {
      +      "minimum": 0,
      +      "type": "integer"
      +    },
      +    "fields": {
      +      "minimum": 0,
      +      "type": "integer"
      +    },
      +    "graph_source": {
      +      "type": "string"
      +    },
      +    "params": {
      +      "minimum": 0,
      +      "type": "integer"
      +    }
      +  },
      +  "type": "object"
      +}
  6. Changed4 schema fields changed
    • changedInput schema / description
      Previous value: -"Two evaluation modes (schema-documented; no mode discriminator field). SIGNATURE: supply token only — signature + expiry; currently_authorized is null. AUTHORIZATION: also supply intended context (operation, environment, fingerprint, target_id, audience, and/or base/head) AND the body_hash-bound decision_result envelope so currently_authorized / authz_status / authz_reason can be evaluated. Token alone is always accepted; omitting the envelope when context fields are present yields a signature verdict plus fail-closed authorization (currently_authorized false), not a schema reject."New value: +"Two evaluation modes (schema-documented; no mode discriminator field). SIGNATURE: supply token only — signature + expiry; currently_authorized is null. AUTHORIZATION: also supply intended context (operation, environment, fingerprint, target_id, audience, repository/branch/pull_request, and/or base/head) AND the body_hash-bound decision_result envelope so currently_authorized / authz_status / authz_reason can be evaluated. Token alone is always accepted; omitting the envelope when context fields are present yields a signature verdict plus fail-closed authorization (currently_authorized false), not a schema reject."
    • addedInput schema / properties / branch
      Added value: +{
      +  "description": "Intended branch the receipt must bind (place binding; optional)",
      +  "type": "string"
      +}
    • addedInput schema / properties / pull_request
      Added value: +{
      +  "description": "Intended pull-request id the receipt must bind (place binding; optional)",
      +  "oneOf": [
      +    {
      +      "type": "string"
      +    },
      +    {
      +      "type": "number"
      +    }
      +  ]
      +}
    • addedInput schema / properties / repository
      Added value: +{
      +  "description": "Intended repository the receipt must bind (place binding; optional)",
      +  "type": "string"
      +}
  7. Changed2 schema fields changed
    • changedInput schema / properties / decision_result / description
      Previous value: -"The body_hash-bound decision envelope (carries operation/target/decision). Required for a meaningful AUTHORIZATION evaluation of scope; without it, intended context alone fails closed on authorization (currently_authorized false) while signature status remains independent."New value: +"The body_hash-bound decision envelope (carries operation/target/decision). Required for a meaningful AUTHORIZATION evaluation of scope; without it, intended context alone fails closed on authorization (currently_authorized false) while signature status remains independent. Full schema: https://coderifts.com/schemas/decision-result.v1.consumer.json."
    • addedInput schema / properties / decision_result / properties
      Added value: +{
      +  "base": {
      +    "type": [
      +      "string",
      +      "null"
      +    ]
      +  },
      +  "decision": {
      +    "enum": [
      +      "ALLOW",
      +      "WARN",
      +      "REQUIRE_APPROVAL",
      +      "BLOCK"
      +    ],
      +    "type": "string"
      +  },
      +  "decision_body_hash": {
      +    "type": [
      +      "string",
      +      "null"
      +    ]
      +  },
      +  "decision_id": {
      +    "type": "string"
      +  },
      +  "environment": {
      +    "type": [
      +      "string",
      +      "null"
      +    ]
      +  },
      +  "execution_action": {
      +    "enum": [
      +      "CONTINUE",
      +      "CONTINUE_WITH_MONITORING",
      +      "REQUEST_APPROVAL",
      +      "STOP"
      +    ],
      +    "type": "string"
      +  },
      +  "expires_at": {
      +    "type": "string"
      +  },
      +  "fingerprint": {
      +    "type": "string"
      +  },
      +  "head": {
      +    "type": [
      +      "string",
      +      "null"
      +    ]
      +  },
      +  "input_fingerprint": {
      +    "type": "string"
      +  },
      +  "operation": {
      +    "type": [
      +      "string",
      +      "null"
      +    ]
      +  },
      +  "receipt": {
      +    "type": "object"
      +  },
      +  "repository": {
      +    "type": [
      +      "string",
      +      "null"
      +    ]
      +  },
      +  "safe_for_agent": {
      +    "type": "boolean"
      +  },
      +  "spec_version": {
      +    "pattern": "^decision-result\\.v1(\\.[0-9]+)?$",
      +    "type": "string"
      +  }
      +}
  8. Changed3 schema fields changed
    • changedInput schema / description
      Previous value: -"Two evaluation modes (schema-documented; no mode discriminator field). SIGNATURE: supply token only — signature + expiry; currently_authorized is null. AUTHORIZATION: also supply intended context (operation, environment, fingerprint, target_id, and/or audience) AND the body_hash-bound decision_result envelope so currently_authorized / authz_status / authz_reason can be evaluated. Token alone is always accepted; omitting the envelope when context fields are present yields a signature verdict plus fail-closed authorization (currently_authorized false), not a schema reject."New value: +"Two evaluation modes (schema-documented; no mode discriminator field). SIGNATURE: supply token only — signature + expiry; currently_authorized is null. AUTHORIZATION: also supply intended context (operation, environment, fingerprint, target_id, audience, and/or base/head) AND the body_hash-bound decision_result envelope so currently_authorized / authz_status / authz_reason can be evaluated. Token alone is always accepted; omitting the envelope when context fields are present yields a signature verdict plus fail-closed authorization (currently_authorized false), not a schema reject."
    • addedInput schema / properties / base
      Added value: +{
      +  "description": "Intended base commit/ref SHA the receipt must match (signed-wins vs envelope.base)",
      +  "type": "string"
      +}
    • addedInput schema / properties / head
      Added value: +{
      +  "description": "Intended head commit/ref SHA the receipt must match (signed-wins vs envelope.head)",
      +  "type": "string"
      +}
  9. Changed4 schema fields changed
    • addedOutput schema / properties / binding_level
      Added value: +{
      +  "description": "place_and_content | content_only — forensic, not a second verdict",
      +  "type": "string"
      +}
    • addedOutput schema / properties / caller_value
      Added value: +{
      +  "description": "Caller claim that differed from the signed envelope",
      +  "type": [
      +    "string",
      +    "null"
      +  ]
      +}
    • addedOutput schema / properties / correlation_id
      Added value: +{
      +  "description": "Route-owned trace id (ID828); always a non-empty string on 200",
      +  "type": "string"
      +}
    • addedOutput schema / properties / signed_value
      Added value: +{
      +  "description": "Signed envelope slot when signed-wins fail-closed (source_binding_mismatch)",
      +  "type": [
      +    "string",
      +    "null"
      +  ]
      +}
  10. First observed

TDQS

A5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond readOnlyHint=true, the description discloses the 30s clock-skew leeway, the unreachable 0s destructive-production grace, fail-closed authorization when the envelope is omitted, return semantics with currently_authorized null, and next_agent_step being advisory. No annotation contradiction; this goes well beyond what annotations and schema already state.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description front-loads the core purpose, then uses scannable bullets for when/do-not-use, then compactly adds operational details and return guidance. It is dense, but every sentence carries a distinct fact relevant to invoking or interpreting the tool; there is no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a complex 12-parameter verification tool with nested objects and an output schema, it covers prerequisites, mode selection, edge cases, return branching, and sibling routing. The existing output schema makes detailed return documentation unnecessary, and the description still gives the essential branching pointer.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Although schema coverage is 100%, the description adds meaning that the schema alone does not: two evaluation modes, token-only acceptance, fail-closed behavior when intended context is present but the decision envelope is omitted, and the need for decision_result for full scope binding. This materially helps an agent construct correct calls.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific action and resource: verify a chain-receipt you ALREADY HOLD, covering signature authenticity, body binding, and authorization status. It also differentiates itself from preflight_change_set and get_decision_details in the Do-not-use section, so an agent can distinguish it from siblings without inspecting schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit 'Use this when' and 'Do not use when' blocks specify the exact conditions: holding an existing receipt, about to act, needing proof, and needing to distinguish signature-ok from authorized. It names sibling tools and states when to call them instead, such as preflight for new decisions and get_decision_details for history without a receipt token.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

TDQS

A4.7/5.0
Disambiguation5/5

preflight_change_set is the sole creation/analysis entry point, get_decision_details is explicitly for retrieving past decisions, and verify_receipt is for validating an already-held receipt. Their descriptions include cross-references and negative usage guidance that make the boundaries unambiguous.

Naming Consistency5/5

All three tool names follow a consistent snake_case verb_noun pattern: preflight_change_set, get_decision_details, verify_receipt. There are no mixed conventions or vague verbs.

Tool Count5/5

Three tools map cleanly to the core governance workflow: create/analyze a change set, inspect a past decision, and verify a receipt before acting. The count is well-scoped and each tool earns its place.

Completeness5/5

The set covers the full decision lifecycle for its stated domain: preflight produces decisions/receipts, get_decision_details retrieves historical decision records, and verify_receipt validates current authorization. Decisions are immutable and revocation is checked via receipt validity, so no obvious lifecycle step is missing.