PRIMARY LAST-MILE PROFILE

Bind supported AP2 approval facts to the exact Stripe request.

AP2 can carry signed checkout authority and Stripe can execute a PaymentIntent. MandateShield addresses the narrow seam between them: the exact approved facts must remain bound to the final provider account, payee, amount, currency and request body attempted by the customer-controlled executor.

THE CURRENT NEED

Two valid artifacts do not automatically prove a valid transformation

A signed payment mandate can be valid while a later provider request contains a changed amount, payee, connected account, PaymentMethod or body. A valid Stripe result proves what Stripe processed; by itself it does not prove that this was the checkout approved in a separate authority protocol.

MandateShield preserves one canonical envelope across strict authority verification, durable budget reservation, the provider-bound permit and the Stripe form-body digest. A single-winner MandateShield claim authorizes the exclusive executor to attempt the idempotent operation. It does not guarantee exactly-once provider delivery.

SUPPORTED SCOPE

Deliberately narrower than complete AP2 or complete Stripe commerce

MandateShield checks

  • One disclosed mandate.payment.1 projection
  • RFC 9901 holder KB-JWT and account-pinned issuer
  • Exact amount, currency, payee and checkout reference
  • Registered per-attempt and cumulative authority limits
  • Stripe connected account and merchant-account binding
  • Exact PaymentIntent form-body SHA-256 digest
  • Fresh online permit claim before the executor attempts
  • Configured PaymentIntent outcome without trusting the caller report

The integration still owns

  • Full AP2 checkout and delegate chain validation
  • AP2 issuer registry and external trust-chain decisions
  • Stripe credentials, PaymentMethod and customer handling
  • Stripe SPT or other credential-token lifecycle
  • Fraud, sanctions, SCA, disputes, refunds and settlement
  • Globally linearizable customer Gate storage
  • Blocked alternate provider egress from the agent runtime

ONE SERVER-SIDE PATH

Project, verify, bind, claim, execute idempotently, reconcile

npm install \
  https://mandateshield.com/packages/npm/1.13.0/mandateshield-sdk-1.13.0.tgz \
  pg
import { Pool } from "pg"
import { MandateShield } from "@mandateshield/sdk"
import {
  createMandateShieldGateway
} from "@mandateshield/sdk/gateway"
import {
  createPostgresGatewayJournal
} from "@mandateshield/sdk/gateway/postgres"
import {
  createStripePaymentIntentsAdapter,
  STRIPE_PAYMENT_INTENTS_AUDIENCE
} from "@mandateshield/sdk/gateway/stripe-payment-intents"

const verifier = new MandateShield({
  apiKey: process.env.MANDATESHIELD_VERIFY_KEY
})
const processor = new MandateShield({
  apiKey: process.env.MANDATESHIELD_PROCESSOR_KEY
})
const database = new Pool({
  connectionString: process.env.GATEWAY_DATABASE_URL,
  ssl: { rejectUnauthorized: true }
})
const journal = createPostgresGatewayJournal({
  database,
  namespace: "ap2-stripe.production"
})
await journal.checkReadiness()

const stripeAccountId = process.env.STRIPE_CONNECTED_ACCOUNT
const merchantId = process.env.MANDATESHIELD_MERCHANT_ID
const stripe = createStripePaymentIntentsAdapter({
  secretKey: process.env.STRIPE_SECRET_KEY,
  stripeAccountId,
  merchantId,
  processorAudience: STRIPE_PAYMENT_INTENTS_AUDIENCE,
  apiVersion: process.env.STRIPE_API_VERSION
})
const stripeGateway = createMandateShieldGateway({
  journal,
  mandateShield: processor,
  provider: stripe
})

export async function executeApprovedAp2Checkout({
  compactClosedPaymentProjection,
  registeredMandateId,
  agentId,
  checkoutAttemptId,
  pinnedKeyThumbprint,
  trustedServerSidePaymentMethodId,
  signExactClosedPaymentAuthority
}) {
  // Projection only: this never authorizes payment.
  const projected = await verifier.normalizePaymentProtocol({
    adapter: "AP2_CLOSED_PAYMENT_SD_JWT",
    source: compactClosedPaymentProjection,
    context: {
      mandate_id: registeredMandateId,
      agent_id: agentId,
      idempotency_key: checkoutAttemptId
    }
  })
  if (
    projected.assurance.enforcement_authorized !== false ||
    projected.protocol !== "AP2"
  ) throw new Error("Unsafe protocol projection")
  if (projected.envelope.merchant_id !== merchantId) {
    throw new Error("Projected AP2 payee is not the configured merchant")
  }

  // Add the exact Stripe destination before signing. Never mutate it later.
  const finalEnvelope = structuredClone({
    ...projected.envelope,
    payee_identity: {
      profile: "MANDATESHIELD_PAYEE_IDENTITY_V1",
      provider: "STRIPE",
      merchant_id: merchantId,
      binding: {
        connected_account_id: stripeAccountId,
        merchant_account_id: stripeAccountId
      },
      verification: {
        method: "STRIPE_ACCOUNT_CONFIGURATION",
        verifier: "customer-stripe-gateway",
        evidence_ref:
          `urn:stripe:connected-account:${stripeAccountId}`
      }
    }
  })

  const challenge = await verifier.createChallenge({
    mandate_id: registeredMandateId,
    protocol: "AP2",
    key_thumbprint: pinnedKeyThumbprint
  })
  if (challenge.audience !== STRIPE_PAYMENT_INTENTS_AUDIENCE) {
    throw new Error("Pinned authority audience is not the Stripe profile")
  }

  // Customer-owned signer: issue the AP2 SD-JWT + holder KB-JWT over this
  // exact finalEnvelope, challenge nonce, issuer and audience.
  const signedEvidence = await signExactClosedPaymentAuthority({
    envelope: finalEnvelope,
    challenge
  })
  const reservation = await verifier.verifyAuthority({
    envelope: finalEnvelope,
    evidence: {
      ...signedEvidence,
      expected_nonce: challenge.nonce,
      expected_audience: challenge.audience
    }
  })
  if (
    reservation.decision !== "ALLOW" ||
    reservation.mode !== "live" ||
    reservation.persisted !== true ||
    reservation.enforcement_authorized !== true ||
    reservation.assurance?.authority_valid !== true ||
    reservation.assurance?.key_trust !== "ACCOUNT_PINNED" ||
    reservation.execution_authorization?.state !== "RESERVED" ||
    reservation.execution_authorization?.consumable !== true ||
    !reservation.signed_receipt?.receipt_id ||
    !reservation.signed_receipt?.compact
  ) throw new Error("No consumable strict live reservation")

  // CONSUME → fresh permit claim → exact Stripe POST → reconciliation.
  return stripeGateway.execute({
    receipt_id: reservation.signed_receipt.receipt_id,
    compact: reservation.signed_receipt.compact,
    expected_envelope: finalEnvelope,
    expected_audience: STRIPE_PAYMENT_INTENTS_AUDIENCE,
    provider_input: {
      payment_method_id: trustedServerSidePaymentMethodId
    }
  })
}

The normalization call is intentionally non-executable and always reports enforcement_authorized=false. Production authority begins only after strict verification succeeds with the registered mandate, fresh challenge, account-pinned key and the supported signed evidence. The Stripe credential remains inside the customer's exclusive executor.

FAIL-CLOSED RESULT

A timeout never recreates spendable authority

The executor uses the idempotency key bound into the fresh permit. MandateShield then retrieves the exact configured PaymentIntent through a separately restricted lookup connection and checks its account, amount, received amount, currency, PaymentMethod, capture and confirmation modes, card method, request ID, payee metadata and permit-bound request-body digest. Pending, unavailable, not-found and conflicting results remain reserved. They do not authorize a blind retry.

The legacy independent_verification response field means independent of the caller's asserted result. It is not an independent organization, Stripe attestation, certification or audit.

HONEST BOUNDARY

No AP2, Stripe or payment-network adoption is implied

This is a first-party MandateShield integration profile, not an AP2 certification, Google partnership, Stripe partnership or claim that either ecosystem requires MandateShield. It is useful only when a customer deliberately makes its credential-isolated executor require the MandateShield handoff.