# Consent ceremony

Consent that names exactly what flows where (Candor's CeremonySurface): each flow as what → where → how long it's kept, an acknowledgement the person ticks themselves, and how to take it back. The grant button stays locked, with its reason, until they've ticked it.

- Registry name: `consent-ceremony` (`@candor/consent-ceremony`)
- Tier: Pro. Installing it needs a Pro, Premium or Team licence key: the person runs `npx candor-ui key <key>` themselves; never ask for the key in chat or write it to a file.
- Docs: https://candor.themethodic.com/docs/consent-ceremony

## Install

```bash
npx candor-ui add consent-ceremony
```

Run `npx candor-ui@latest init` once first (https://candor.themethodic.com/get-started.md). Without the CLI: `npx shadcn@latest add @candor/consent-ceremony`.
It brings in: button, locale, locked, team, terms, utils.
npm packages: lucide-react@^1.67.0.

## Example

```tsx
"use client"

import { ConsentCeremony } from "@/components/consent-ceremony"
import type { DataFlow } from "@/lib/team"

const flows: DataFlow[] = [
  { what: "Code and config: repositories, schema, migrations and CI settings", to: "Keel’s servers in us-east", kept: "while connected" },
  { what: "Row counts and column fill rates", to: "Keel’s servers in us-east", kept: "90 days" },
  { what: "What an agent needs to answer a question", to: "The model provider, with zero data retention", kept: "not kept after the answer" },
]

export default function Example() {
  return (
    <ConsentCeremony
      className="w-full max-w-xl"
      title="Allow Keel to read Acme API Staging"
      flows={flows}
      notFlowing={["Row contents, unless an agent needs one to answer you", "Secrets, environment variables and encrypted columns"]}
      revoke="Disconnect in Settings › Environments. Access stops at once."
      acknowledgement="I can connect this code for Acme, and I understand what Keel reads and where it goes."
      grantLabel="Allow and continue"
      onGrant={() => {}}
      onCancel={() => {}}
    />
  )
}
```

## <ConsentCeremony>

Props:

- `title: string`: The heading, e.g. "Let agents read your workspace".
- `flows: DataFlow[]`: Each thing read: what it is, where it goes and how long it's kept.
- `notFlowing?: string[] | undefined`: What does not leave, said plainly.
- `revoke: string`: How to revoke later.
- `acknowledgement: string`: The sentence the person ticks themselves before granting.
- `grantLabel?: string | undefined`: The grant button's label. Defaults to "Allow".
- `onGrant: () => void`: Called when the person grants, after ticking the acknowledgement.
- `onCancel?: (() => void) | undefined`: Shows Not now; called when it's clicked.
- `busy?: boolean | undefined` (default `false`): Disables the grant button while consent is being recorded.
- `className?: string | undefined`

## Strings (`consentCeremony`)

The fixed words, English by default. Override any of them under `consentCeremony` in `<LocaleProvider strings={{ consentCeremony: { … } }}>`; the table is exported as `consentCeremonyStrings`.

- `allow`: Allow
- `whatIsRead`: What {product} will read, and where it goes
- `goesTo`: goes to
- `kept`: Kept: {kept}
- `whatStays`: What stays in your {environment}
- `takeBack`: To take this back:
- `notNow`: Not now
- `tickFirst`: Tick the acknowledgement first.

## Rules for using Candor UI

- Components take plain typed data. Never pass model output as HTML or render it as a link; messages are typed blocks.
- A control that can't be used says why: wrap it in `<Locked reason="…">`, don't just disable it.
- Don't show a value you don't have: leave it out (it renders as —) rather than guess. An estimate is labelled as one.
- Nothing is pre-selected in a decision a person makes, and the agent is named from your app's data, never from model output.
- Your app's words go in `LocaleProvider` (fixed strings) and `TermsProvider` (nouns); entity kinds and agent roles in `EntityKindsProvider` and `AgentRolesProvider`.
