# Deployment handoff for the coordinator

This lab is ready for a dedicated Worker named `bwc-memory`, with compatibility date `2026-10-15`. No remote resources, deployment, DNS, or git state are changed by the lab builder. Keep the existing `lab.cfsalestools.com` untouched. The coordinator chooses the new hostname and integrates the portal/account handoff.

## Resources and secrets

Run from `labs/memory` in the intended sponsored account. Do not bind an existing unrelated index. Names must be unique in that account.

```sh
npm ci
npx wrangler whoami
npx wrangler vectorize create bwc-memory-v1 --dimensions=768 --metric=cosine
npx wrangler secret put LAB_ACCESS_CODE
npx wrangler secret put SESSION_SECRET
```

Use a private event access code and a random SESSION_SECRET of at least 32 characters. Keep the session secret stable across deployments to preserve sessions. Rotate the event code as needed. Returning attendees can use their private resume code without the current event code. SESSION_SECRET also purpose-signs resume codes; rotating it invalidates those codes as well as sessions. Do not place actual values in source, example files, client code, downloads, logs, or command-line arguments.

The checked-in `wrangler.jsonc` declares the AI binding, Vectorize index, Worker-first assets, and SQLite Durable Object migration. There are no implicit cross-account service bindings. Configure `LIVE_ENABLED` to `true` in the deploy configuration only after resources, limits, and the event budget have been reviewed. Keep `false` for a safe storage-only launch.

```sh
npm run check
npm test
npm run dry-run
npm run deploy
```

`npm run deploy` builds the source archive before publishing. It is an operator command, not something the lab builder has run. Bind a dedicated route/custom domain through the coordinator's infrastructure; this lab deliberately declares none.

## Readiness gates

1. Check `/api/health`. `configured` reports presence of bindings and secrets; this does not prove they are operational.
2. Join with a canary event code, save a memory, refresh, and verify SQLite persistence across a deployment/restart.
3. Index a known short fact. Poll Search manually for up to 30 seconds. Confirm query returns that exact current text and a score; capture indexing visibility latency.
4. Ask a question and verify the actual Workers AI response contains an accurate citation. Repeat with conflicting evidence under both conflict policies.
5. Join from a second browser profile and verify zero data leakage. Delete the first record and immediately query again; no old citation may appear.
6. Schedule a one-minute check-in, close the browser, and verify one delivery after reopening. Check canceled prompts do not arrive.
7. Export participant data, preview/confirm an import into a second workspace, and verify new IDs, rules, saved history, paused check-ins, explicit indexing, and no cross-workspace vector reuse. Create a resume code, reopen the original workspace without its cookie, replace the code and verify the old one fails, then revoke it.
8. Download `/api/export`, unpack it, and confirm it rebuilds. Verify `/api/data` requires the participant cookie and that the source archive contains no secrets.
9. Run the 50-user live validation below on an isolated pre-event deployment/index. Record results in STATUS.md. Do not advertise capacity until measured.

## Capacity validation

The script creates 50 signed sessions and independent records, edits, exports, and deletes them. With `LOAD_LIVE=true`, it also indexes, polls retrieval with a bounded retry budget, asks a cited question, checks isolation, and tests immediate post-delete retrieval. It does not cover 150 minutes of sustained workshop usage or all model-quality cases.

Provide `LAB_BASE_URL`, `LAB_ACCESS_CODE`, optional `LOAD_LIVE=true`, and optional `LOAD_REPORT=/path/report.json` in the process environment, then run `npm run test:load`. Use a secret-capable terminal/environment rather than pasting secrets into shared command transcripts. It is intentionally capped at 50 users and cannot target an arbitrary host without an explicit environment variable. Test accounts consume event admissions and live budgets. Use a dedicated staging Worker/index with its own Durable Object namespace; never reuse the production participant data store for load runs.

Success criteria: 50/50 isolated workflows complete; zero cross-participant citations or exports; zero deleted citations; error fraction 0 in this bounded preflight; report p50/p95 latency by operation and total wall time. Investigate and document any failure rather than rerunning until it disappears. Set event-specific latency objectives before the test. Follow with a facilitator-led 50-browser, 150-minute rehearsal if the full event capacity claim requires it.

## Participant deployment and keepability

The app's source archive is portable and contains complete configuration plus a lockfile. Participant rules and data are separate downloads. The coordinator integrates browser-hosted deployment and temporary-account claim as a separate flow. This app does not claim deployment or account ownership has occurred. A destination account needs its own Workers AI/Vectorize access and a new index, alongside the Worker and Durable Object migration. The browser import flow restores the existing participant JSON export. Join the destination, choose the file, select add or explicit replacement, inspect the preview, and type the confirmation. Full replacement restores records/rules/saved conversation/check-ins. Merge preserves existing content and rules unless the attendee explicitly chooses the imported rules, and rejects capacity overflow. All imported IDs are fresh, all records require explicit indexing, and imported pending check-ins are paused. Identity credentials, operational counters, quota counters, and Vectorize state are not imported. There is no automatic resource transfer.

## Operation and retention

Set `LIVE_ENABLED=false` and redeploy to stop new expensive work. Existing cleanup alarms can still delete retired vectors. To revoke all signed sessions and resume codes, rotate SESSION_SECRET; this abandons access, not storage deletion. Keep the secret stable for continuity. Participants can create, replace, download, and revoke their own non-expiring resume code; it opens the same sponsored workspace after cookie expiry, while the deployment and data remain available. Codes stay out of URLs, exports, and logs, and the Durable Object stores only SHA-256 hashes. Reset revokes the code. Replacement import preserves the destination code. Plan an event retention sweep with the coordinator before launch. The application exposes participant reset, but does not implement an operator-wide purge/index deletion endpoint. Do not delete the shared Vectorize index while active participants need it.

Provider backup/recovery retention remains subject to Cloudflare policies. No content is sent to third-party hosts by the frontend; no model credentials reach browsers. Do not enable request-body logging for this deployment.

## Storage schema update (v1.1)

No Wrangler migration/configuration change is required. The existing SQLite class adds bounded import-preview/payload tables, a `paused` reminder column, and an `imported` history column on startup. Existing records, reminders, and history remain unchanged. Confirm the 29-test local suite and a deployment canary after rollout. Source archive/version is 1.1.0.
