# `checkout`

## Use when / do not use when

Use for a dedicated payment-entry screen. Do not use for plan merchandising without payment entry or for subscription management.

## Exact metadata contract

<!-- funnelsgrove:generated:start contract-v3/step/checkout -->
### Generated contract facts — do not edit

- Step contract version: `3`
- Contract hash: `d761e91d5ac6ff9e72c6d49c5bcd014270912473a66f99c49d726c65998085cf`
- Type: `checkout`
- Family: `commerce`
- Description: A dedicated payment-entry screen.
- Action owner: `step`
- Analytics role: _none_
- Terminal: `false`
- Required kind: _none_
- Allowed kinds: _None_
- Allowed semantic events: `checkout_started`, `add_payment_info`, `checkout_completed`
- Forbidden capabilities: `choice-write`, `email-capture`, `subscription-management`, `subscription-handoff`, `hardcoded-navigation`, `provider-direct-analytics`, `browser-registration-completed`

#### Choice contract

_Not a choice type._

#### Automatic lifecycle events

`first_step_clicked`, `first_step_viewed`, `funnel_started`, `step_completed`, `step_exited`, `step_started`

#### Approved capability owners

- `checkout` must be owned by `named-payment-helpers`.

#### Reserved identities

_No reserved identity for this type._

#### Golden fixture source

```ts
import type { FunnelManifestStep, FunnelStepMeta } from '@funnelsgrove/runtime';

const manifestStep = {
  id: 'checkout',
  name: 'checkout',
  path: '/checkout',
  filePath: 'src/steps/step-checkout.tsx',
  componentKey: 'stepCheckout',
  type: 'checkout',
  title: 'Secure checkout',
} as const satisfies FunnelManifestStep;

const componentMeta = {
  id: 'checkout',
  name: 'checkout',
  type: 'checkout',
  figmaNodeId: 'golden:checkout',
  title: 'Secure checkout',
  description: 'Collect payment through shared checkout UI.',
} as const satisfies FunnelStepMeta;

export const goldenFixture = {
  stepType: 'checkout',
  manifestStep,
  componentMeta,
  requiredEventMetadata: [
    'funnelId',
    'funnelVersionId',
    'environment',
    'stepContractVersion',
    'stepId',
    'stepName',
    'stepType',
    'eventId',
  ],
  semanticHelpers: ['trackCheckoutStarted', 'trackPaymentInfoSubmitted', 'trackCheckoutCompleted'],
} as const;
```
<!-- funnelsgrove:generated:end contract-v3/step/checkout -->

## Interaction and persisted answer shape

The payment package owns payment state. Do not persist card, wallet, price, or provider data as funnel answers.

## Automatic lifecycle events

The controller owns step lifecycle. Payment helpers own semantic conversion boundaries and event IDs.

## Required semantic conversions

Use the named checkout-started, payment-info, and checkout-completed helpers with the complete required metadata returned by runtime context.

## Approved shared helpers

Use `trackCheckoutStarted`, `trackPaymentInfoSubmitted`, `trackCheckoutCompleted`, and shared checkout UI/runtime helpers.

## MUST rules

- Keep secrets server-side and provider IDs in configuration.
- Reuse one event ID per logical conversion and allow safe retries.

## NEVER rules

- Never capture raw payment details yourself.
- Never send incomplete, fabricated, or direct-provider analytics.

## Golden template or fixture

See the [embedded canonical fixture](#golden-fixture-source) generated from `checkout.fixture.ts`.

## Validation command

Run `fgrove validate`.

## Manual QA and completion criteria

Test all payment methods, validation, decline, retry, success, deduplication, required metadata, and post-success routing.
