# `subscription_handoff`

## Use when / do not use when

Use for a non-terminal app, store, or deep-link handoff. Do not use for the canonical post-purchase registration-completion terminal.

## Exact metadata contract

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

- Step contract version: `3`
- Contract hash: `d761e91d5ac6ff9e72c6d49c5bcd014270912473a66f99c49d726c65998085cf`
- Type: `subscription_handoff`
- Family: `commerce`
- Description: A non-terminal app, store, or deep-link handoff.
- Action owner: `step`
- Analytics role: _none_
- Terminal: `false`
- Required kind: `subscription-handoff`
- Allowed kinds: `subscription-handoff`
- Allowed semantic events: _None_
- Forbidden capabilities: `choice-write`, `email-capture`, `checkout`, `subscription-management`, `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

- `subscription-handoff` must be owned by `runtime-handoff-helper`.

#### Reserved identities

_No reserved identity for this type._

#### Golden fixture source

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

const manifestStep = {
  id: 'open-app',
  name: 'open-app',
  path: '/open-app',
  filePath: 'src/steps/step-open-app.tsx',
  componentKey: 'stepOpenApp',
  type: 'subscription_handoff',
  kind: 'subscription-handoff',
  title: 'Continue in the app',
} as const satisfies FunnelManifestStep;

const componentMeta = {
  id: 'open-app',
  name: 'open-app',
  type: 'subscription_handoff',
  kind: 'subscription-handoff',
  figmaNodeId: 'golden:subscription-handoff',
  title: 'Continue in the app',
  description: 'Continue through a non-terminal app handoff.',
} as const satisfies FunnelStepMeta;

export const goldenFixture = {
  stepType: 'subscription_handoff',
  manifestStep,
  componentMeta,
  helper: 'runtime handoff helper',
  isRegistrationCompletion: false,
} as const;
```
<!-- funnelsgrove:generated:end contract-v3/step/subscription_handoff -->

## Interaction and persisted answer shape

Build the outbound destination through the runtime handoff helper. This screen persists no choice answer.

## Automatic lifecycle events

Leaving through the handoff is not funnel registration completion. The controller owns the step outcome.

## Required semantic conversions

None. This non-terminal handoff must not emit funnel or registration completion.

## Approved shared helpers

Use the runtime subscription-handoff helper with the safe default `SubscriptionHandoffScreen` completion mode of `step`; never opt a non-terminal handoff into `completionMode="funnel"`.

## MUST rules

- Treat the destination as configuration/runtime data.
- Keep non-terminal semantics explicit.

## NEVER rules

- Never emit trusted `purchase_completed`, `registration_completed`, or terminal `funnel_completed`.
- Never build an unvalidated deep link by string concatenation.

## Golden template or fixture

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

## Validation command

Run `fgrove validate`.

## Manual QA and completion criteria

Test installed/uninstalled destinations, query propagation, return behavior, and absence of completion conversions.
