# Ferry

See [OPERATIONS.md](OPERATIONS.md) for command effects and prerequisites; run
`node scripts/operations.mjs describe` from this edition checkout to inspect them.

Read [first-release acceptance](ACCEPTANCE.md) for purpose, unmet release obligations, preserved requirements and the evidence decision rule.

Ferry is an intervention-first sales pipeline for one business. Its Focus,
Pipeline and Deal Story connect real people, deals, activities, customer promises
and explainable health. The Sales family supplies contact identity and link
validation; optional Base SendGrid source supplies native sign-in mail transport.
This edition owns its complete source and selected components.

The preserved interface now runs on TanStack Start in one Cloudflare Worker,
with Hono APIs and native auth backed by D1. New installations can create a
contact and deal in Pipeline, then plan an activity and record a qualified
customer commitment in Deal Story. Confirmed outbound follow-up email remains
unimplemented and the Send control stays disabled.

## Local use

For guided setup, run `node scripts/install.mjs`. Review the inferred details,
fill only the missing business choices, then approve the real local install.
See [onboarding](docs/INSTALLER.md) for agent prefill, privacy and source custody.

Use Node 26.8.1 and pnpm 8.15.6:

```sh
pnpm install --frozen-lockfile
FERRY_OWNER_EMAIL=you@your-business.example FERRY_OWNER_NAME="Your name" pnpm dev
```

Replace the owner values with your own, then open the printed local URL and choose
**Sign in to local workspace**. This initializes an empty local database with your
operator and stages; it creates no sample contacts or deals. `pnpm dev:test` is the
explicit fixture-backed test runtime and refuses to seed populated non-test data.
`pnpm verify` runs types, lint, shared component tests, Workers tests, and build.
`pnpm exec playwright install chromium && pnpm test:browser` runs a real browser
creation journey. See HANDOVER for emitted-Worker verification and remaining
acceptance gaps.

## Owner deployment

Set these values in the deployment environment:

| Variable | Purpose |
| --- | --- |
| `FERRY_WORKER_NAME` | Unique lowercase Cloudflare Worker name |
| `APP_URL` | Its canonical HTTPS origin |
| `FERRY_OWNER_EMAIL`, `FERRY_OWNER_NAME` | Explicit initial operator |
| `FERRY_BUSINESS_NAME` | Business record name |
| `FERRY_TIME_ZONE`, `FERRY_CURRENCY` | IANA zone and currency; defaults UTC/USD |
| `EMAIL_FROM` | Verified SendGrid sender |
| `SENDGRID_API_KEY` | SendGrid secret |
| `AUTH_SESSION_SECRET` | Random secret of at least 32 characters |
| `CLOUDFLARE_ACCOUNT_ID` | Required when the credential has multiple accounts |

Authenticate Wrangler or supply `CLOUDFLARE_API_TOKEN`. Edit `src/ext/config.ts`
for the public identity plate. Then:

```sh
pnpm run setup -- --dry-run
pnpm run deploy -- --dry-run
pnpm run setup
pnpm run deploy
```

Setup finds or creates the named D1 database and writes ignored local deployment
configuration. Generated `wrangler.toml` is disposable; keep custom deployment
configuration in the generator or a separately maintained owner file. Deploy builds the generated Worker, applies migrations, bootstraps
the explicit owner/business/stages on the first installation, sends secrets through
a private temporary file, and checks `/health`. It refuses a local-demo deployment
and refuses to reactivate an absent configured owner in populated data. An owner
signs in through `/signin`; mail contains an expiring link followed by explicit
confirmation. Product records remain in the owner's Cloudflare account.

Read `CONTRACT.md` for the target guarantees and `HANDOVER.md` for current evidence.
Full release acceptance, remote deployment verification and confirmed deal mail
are separate from the passing local migration checks.

## Owner updates

Integrate changes from the edition's upstream with ordinary Git, using
an approach suited to the owner's fork. Preserve `.seed/intent.md` and all owner
requirements, review migrations, and verify the affected workflow as well as
`pnpm verify` and owner tests. A clean merge alone is not acceptance. There is no
implemented marketplace update CLI or automatic conflict-to-contract reporting.
Use `pnpm run setup` and `pnpm run deploy` for an authorized deployment after the
candidate is verified; see `AGENTS.md` in this edition for update guidance.

## Source authoring

Edit this repository directly. `edition.json` selects editable local foundation,
Sales, SendGrid and Ferry components with exact comparison origins; the edition
owns integration. Run `pnpm source:inspect`, `pnpm source:lock` after intentional
source changes, and `pnpm source:check` before release. Stage new files before
locking. `pnpm source:release -- /absolute/new/repository` creates a portable
local Git release from a clean committed checkout; source release does not deploy.

The 14 September 2026 cutover preserves the runtime, tests, migration history and
dependency lockfile from Ferry `260ab4993b3b8cf69a137ca287b549cbd71b0680`.
Its comparison sources remain Base `bc27ecf55693a68bfa7e8a6aba9fe3ce8883bcfe`
and Sales `b3b195939af1cdfdef3008d878c6cb945e3e0cd6`. The retained
`composition.lock.json` records that historical assembly and supports existing
checks; it is no longer a writer configuration. Product acceptance and live
pilot evidence retain their existing limits.
