> ## Documentation Index
> Fetch the complete documentation index at: https://docs.agentvault.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Attested detokenization

> Revealing a card number only inside a hardware-attested enclave: current status, design, limitations and error codes.

Attested detokenization moves the moment a card number is revealed into a
confidential computing enclave whose identity is cryptographically verified.

## Status

<Warning>
  **Off by default, and unavailable unless a deployment has provisioned an
  attested enclave.**

  The in-proxy gate is a deployment setting, off by default. With it off, card
  reveals follow the standard path on [Card storage](/security/card-storage). With
  it on and no enclave present, every reveal is refused with `attestation_required`.
  That refusal is the intended fail-closed behaviour.

  It is not enabled on the hosted Agent Vault service. On a self-hosted
  deployment, confirm its configuration before planning an integration around
  this page.
</Warning>

## The guarantee

**When enabled, a card number is revealed only after the code requesting it has
proven, with a hardware-signed attestation, that it is an approved image running
in a confidential enclave with debugging disabled. If that proof cannot be made,
no card is revealed.**

## The problem it addresses

On the standard path, the card number is revealed inside the proxy and typed into
the merchant page. The proxy is Agent Vault infrastructure, so at that instant an
operator with sufficient access to the running proxy could in principle observe
the number.

Attested detokenization narrows where that reveal can happen: only inside an
enclave whose identity is cryptographically proven, running an image whose digest
is on an allow-list, with debugging disabled and no command or environment
overrides.

## How it works

### Attestation check

| Component | State |
| - | - |
| An attestation-token verifier with full signature verification against the attestation service's published keys | Shipped |
| Enforcement of every pinned claim: software identity, image digest allow-list, debug status, support level, hardware model, and empty command and environment overrides | Shipped |
| A fail-closed gate in the reveal path that requires a successful attestation **before** any card number is read | Shipped |
| The deployment setting that turns the gate on | Shipped, off by default |
| Releasing the vault credential only to an attested, approved image | Provisioned per deployment, outside the application |

The in-proxy verifier is a **defence-in-depth re-check**. The authoritative
control sits outside the application: the vault credential is released only to
an attested, approved image.

The application never fabricates a passing attestation. A valid attestation token
is issued only by the enclave's launcher to a workload running inside a
provisioned enclave. Outside an enclave, no such token exists.

### Attested checkout

Separately from the gate above, the SDK exposes `attestedCheckout(plan)`. It hands
a whole card checkout, described as a declarative plan, to the enclave. The
enclave reveals the card and types it in its own browser, so the card number is
never in the proxy process. You get back `last4` and, where one was recorded, the
`transactionId`.

```mermaid theme={null}
sequenceDiagram
    autonumber
    participant A as Agent
    participant P as Proxy
    participant B as Agent Vault backend
    participant E as Attested enclave
    participant M as Merchant

    A->>P: attestedCheckout(cardToken, plan)
    P->>P: Validate the plan
    P->>B: Authorize and record the transaction
    B-->>P: Allowed, with the vault token id only
    P->>E: Delegate the plan, after verifying the enclave's attestation
    E->>E: Reveal the card inside the enclave
    E->>M: Runs the plan and types the card
    E-->>P: Result and last four
    P->>B: Confirm, or reverse the transaction on failure
```

#### The plan

Step types: `goto`, `click`, `fill`, `fillSecret`, `waitFor` and `wait`.

`screenshot` steps are refused: they would write a caller-named file inside the
enclave. Use `page.screenshot()` on your own session instead.

#### The shape rule

`fillSecret` must be followed by **exactly one** state-changing action, and it
must be a `click` on the merchant's pay button. Only `wait` and `waitFor` may
follow that click.

| With no click | With more than one |
| - | - |
| The enclave types the card and returns success on a form that was never submitted. Its browser closes with the plan, so nothing can finish the checkout | One approval would authorize two submissions |

A malformed plan is refused with `invalid_plan` **before** any transaction is
recorded.

## What this does not protect against

<AccordionGroup>
  <Accordion title="The interactive fill path">
    Enabling attested checkout does not change the standard interactive path. A card
    token filled on your own session's page is still revealed in the proxy.
  </Accordion>

  <Accordion title="Cards with a spending cap">
    The page renders in the enclave, so the proxy cannot read the authoritative order
    total, and an enforced cap refuses an unknown amount. Use the standard fill for
    capped cards. Any `amount` you pass is recorded for audit only and is not trusted.
  </Accordion>

  <Accordion title="Hosted card fields">
    The plan has no frame-targeting step, and the enclave fills the top-level page. A
    card field inside a hosted payment iframe cannot be filled this way.
  </Accordion>

  <Accordion title="Anything after submission">
    A 3-D Secure step, one-time code or CAPTCHA raised after the pay click belongs to
    the enclave's browser. Neither the agent nor a
    [challenge handoff](/guides/challenges) can reach it.
  </Accordion>

  <Accordion title="Merchants that require a CVV">
    The plan carries one secret, the card number. A live CVV is typed into your own
    session's page, not the enclave's, so these checkouts must use the standard fill.
  </Accordion>

  <Accordion title="Tunnelled sessions">
    Where the deployment relays the enclave's traffic, an attested checkout in a
    tunnel-required session (`tunnel: true`) leaves through your tunnel like any other
    session. Where it cannot relay the enclave, that session is refused with
    `attested_checkout_unavailable` and nothing is recorded: open a session that does not
    require the tunnel, or fill the card token on your own page. See
    [Tunnelling and attested checkout](/sdk/tunnel#tunnelling-and-attested-checkout).
  </Accordion>

  <Accordion title="A dropped connection">
    If your connection closes after the plan is submitted, the call fails on your side
    while the enclave continues. There is no idempotency key for a retry to join the
    run. Do not resend the plan until you have checked the merchant's order state or
    the session on the dashboard.
  </Accordion>

  <Accordion title="Agent Vault's own infrastructure outside the enclave">
    The enclave narrows where the card number is revealed. The authorization
    decision, the vault token id and the merchant page are unchanged, and the merchant
    still receives a real card number.
  </Accordion>
</AccordionGroup>

## How to verify

<Steps>
  <Step title="Call attestedCheckout on your deployment">
    Pass a test card token and a valid plan from an untunnelled session.
  </Step>

  <Step title="Read the result">
    Where no enclave is configured, the call fails up front with
    `attested_checkout_unavailable` and nothing is recorded. Where the gate is on
    and attestation cannot be proven, reveals fail with `attestation_required`.
    Both confirm the path fails closed.
  </Step>

  <Step title="Check the record">
    On a deployment where the path is live, a successful run returns the card's
    `last4`, and the session normally appears in [Activity](/dashboard/activity)
    like any other checkout. Activity recording is best effort, so the returned
    `last4` is the proof, not the entry.
  </Step>
</Steps>

## Error codes

Retry guidance differs sharply between these codes. The full table is in the
[error reference](/sdk/error-codes#attested-checkout).

| Code | Meaning | Retry |
| - | - | - |
| `attestation_required` | The process could not prove it is running in the enclave. Covers both a persistent policy misconfiguration and a transient launcher or key-fetch failure | Mostly no. One retry after a backoff covers the transient case |
| `attested_checkout_unavailable` | Seven causes. Six refuse up front with nothing recorded: no enclave endpoint configured, a plaintext non-loopback endpoint, egress filtering not declared, enclave identity verification not declared, the endpoint failing to prove it is an approved enclave, and a session that required tunnel egress on a deployment that cannot relay the enclave. The seventh arrives late: the enclave did not use the egress relay it was granted, the card was not entered, and the transaction is reversed | Read the message. Configuration causes do not clear by themselves. The tunnel case is fixed by opening a session that does not require the tunnel. The relay case is retryable once a rolling deploy settles |
| `attested_checkout_busy` | A concurrency ceiling for the session, the key, the account or the server | Yes, after a wait. Back off rather than opening more sessions; the per-key and per-account ceilings mean extra keys do not raise the limit |
| `attested_fill_failed` | Failed **before** the card was entered, and the transaction was reversed | **Yes.** This is the retry-safe attested failure |
| `attested_fill_unreversed` | Failed before the card was entered, but the transaction could **not** be reversed | **No.** Reconcile first |
| `attested_fill_incomplete` | Failed **after** the card was entered, or the outcome is unknown. The transaction is kept | **No.** Check the order at the merchant and tell the account holder about the possible card use |
| `invalid_plan` | A malformed plan, **or** a session that required a tunnel and lost it while the account holder considered an approval | No for a malformed plan. Yes for the lost tunnel: relaunch with `tunnel: true` and run the same plan |
| `malformed_response` | On this path, the enclave reported filling a card whose last four do not match the authorized card | A critical anomaly. Reconcile; do not retry |

<Warning>
  On `attested_fill_incomplete`, Agent Vault attempts to notify the cardholder, but
  that notification is best effort and its failure is not reported. Do not assume
  the account holder was told. Tell them yourself.
</Warning>

## What it requires

Attested checkout works only on a deployment that runs an attested enclave and
has turned the feature on. That is set up per deployment. There is nothing to
enable from the SDK, the MCP server or the dashboard.

To tell whether it is on for you, make the call described in
[How to verify](#how-to-verify). A refusal with `attested_checkout_unavailable`
before anything is recorded means it is not available on your deployment. This
page does not yet document any other indicator.

## Related

<CardGroup cols={2}>
  <Card title="Card storage" icon="vault" href="/security/card-storage">
    The standard reveal path, which is on today.
  </Card>

  <Card title="Security model" icon="shield" href="/security/model">
    What this narrows, and what it does not.
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.