Phase 1 — Demarcation Provisioning Runbook
Date: 2026-05-15
Status: Draft v0.1 (ready to execute)
Related: docs/architecture/FIN_CENTRAL_TENANT_DEMARCATION_PLAN_2026-05-15.md
Time budget: 2-4 hours for one focused execution session
Outcome: FIN Central infrastructure exists and is empty, ready to
receive Phase 2 (code demarcation) and Phase 3 (data demarcation)
0. Pre-Flight
Before starting, confirm you have:
- Neon account login + admin access to current project
- Cloudflare account login + admin access to current Workers deployment
- GitHub account login + ability to create new private repos under the FIN GitHub org (or your personal account if FIN org not yet created)
- AWS Secrets Manager access (for adding new secret subtrees)
- Approx 2-4 uninterrupted hours
- No active production cutover or deploy in progress (this is provisioning only; should not affect running Nathel deployment, but avoid concurrent risky changes)
1. Neon Project Provisioning (30-45 minutes)
1.1 Rename current project
The current Neon project is unnamed (or named ambiguously). Rename it first so the new project doesn’t collide.
- Log in to Neon console:
https://console.neon.tech - Open current project (the one serving fin-agentic/staging)
- Settings → General → Rename to:
nathel-prod - Confirm rename. Update any local
.envreferences in mental note (we won’t touch them yet — Phase 2 work).
1.2 Create new project: fin-central-prod
- Neon console → Create new project
- Name:
fin-central-prod - Region: same region as
nathel-prod(likelyus-east-2or wherever your current project lives — match for lower cross-region latency) - Postgres version: match current (
15.xor16.x— checknathel-prodsetting) - Default branch:
main - Plan: same tier as current (start on lowest paid tier; can scale)
1.3 Capture the connection string
- Open
fin-central-prod→ Connection details - Copy the connection string. Format:
postgresql://user:pass@host/db?sslmode=require - Note the host (will be different from nathel-prod’s host)
1.4 Apply current schema
The four-table schema is the canonical starting point. We’ll apply it to the new project so it’s structurally identical to nathel-prod.
# In a terminal, from fin-agentic repo root
cd /Users/robert/Projects/FIN/_03_Dev/fin-agentic
# Set the env to the new project
export FIN_CENTRAL_DATABASE_URL='postgresql://<paste from 1.3>'
# Apply schema via dbmate (the canonical migration tool per AGENTS.md)
DATABASE_URL=$FIN_CENTRAL_DATABASE_URL npx dbmate upIf dbmate up fails, check that:
- Connection string is correct (paste error common)
- Migrations directory is at
db/migrations/ - pgvector extension is installable in your Neon tier (it is on all paid tiers; free tier limitations may apply)
1.5 Verify
- Neon console → fin-central-prod → SQL Editor
- Run:
SELECT table_name FROM information_schema.tables WHERE table_schema='public' ORDER BY 1; - Confirm:
actors,events,knowledge,operational_memorypresent + projection tables from migrations 041-044
1.6 Pin the connection in a secure location
Do NOT commit to repo. Save the connection string to your password manager AND to AWS Secrets Manager (next step).
2. AWS Secrets Manager Provisioning (15-30 minutes)
2.1 Create new subtree
- AWS console → Secrets Manager
- Create new secret group / subtree namespace:
/fin/central/ - Migrate existing secrets that are FIN-Central concerns. Examples:
- GOOGLE_API_KEY (used by external scrapers — Central concern)
- ANTHROPIC_API_KEY (used by both, but Central has its own copy)
- Anthropic federal endpoint config (Wave 4) — placeholder for now
2.2 Add the new Neon connection
- Create secret:
/fin/central/database-url - Value: the connection string from §1.3
- Tags:
role=central,env=prod,provisioned=2026-05-15
2.3 Tag existing tenant-secret subtree
- Either:
- Move existing tenant secrets to
/fin/tenant/nathel/namespace, OR - Tag the existing secrets with
role=tenant,tenant=nathel
- Move existing tenant secrets to
- Whichever is faster; full migration can happen Phase 2
3. Cloudflare Worker Provisioning (45-60 minutes)
3.1 Identify current deployment
- Cloudflare console → Workers & Pages
- Find your current
fin-agenticWorker - Note its current routes:
- Likely something like
staging.fin.app/*or similar - Document the route(s) in your password manager / notes
- Likely something like
3.2 Tag current deployment as tenant-Nathel
- Cloudflare console → your existing Worker → Settings → Variables
- Add env var:
DEPLOYMENT_ROLE = tenant - Add env var:
TENANT_ID = nathel - Optionally: rename the Worker to
nathel-tenant-fin-agenticin Cloudflare for clarity. (Worker name changes don’t affect routes.) - Save / deploy this config change (no code change yet; it just sets env vars Phase 2 code will read)
3.3 Create new Worker for FIN Central
- Cloudflare console → Workers & Pages → Create
- Name:
fin-central-fin-agentic - Initial template: “Hello World” Worker (we’ll deploy real code in Phase 2)
- After creation, configure:
- Environment Variables:
DEPLOYMENT_ROLE = centralNEON_DATABASE_URL = (secret binding to AWS SM /fin/central/database-url)ANTHROPIC_API_KEY = (secret binding)GOOGLE_API_KEY = (secret binding)
- Compatibility flags: match
nathel-tenant-fin-agenticworker - Service bindings: none yet (Phase 2)
- KV namespaces: provision new ones with
fin-centralprefix - Durable Objects: defer; provision when first used
- Environment Variables:
- Routes: don’t add yet. Phase 5 wires the route to
central.fin.app.
3.4 Provision Hyperdrive for Central
- Cloudflare console → Hyperdrive
- Create new config:
fin-central-hyperdrive - Target: the fin-central-prod Neon connection string from §1.3
- Note the Hyperdrive binding ID; you’ll bind it to the
fin-central-fin-agenticWorker in Phase 2
3.5 Provision R2 bucket for FIN Central
- Cloudflare console → R2
- Create new bucket:
fin-central-artifacts - CORS rules: same as nathel-prod bucket (copy from existing)
- Set up lifecycle rules: 7-year retention default (federal-grade)
3.6 Reserve DNS for central.fin.app
- Cloudflare DNS for fin.app zone
- Add CNAME or A record for
central.fin.app - Don’t activate the route on the new Worker yet (Phase 5)
4. GitHub Vault Repositories (30 minutes)
4.1 Create FIN GitHub Organization (if not exists)
If you don’t have a FIN GitHub org yet:
- GitHub → Create new organization
- Name:
food-intelligence-incorfin-platform(pick one;food-intelligence-incis more descriptive for federal/legal purposes) - Plan: Team plan recommended (allows private repos with more features)
- Add Rob as owner. Add Josh + Jake as members (not owners) with appropriate team permissions.
4.2 Create fin-central-intranet repo
- GitHub → org → New repository
- Name:
fin-central-intranet - Visibility: Private
- Initialize with:
- README.md (boilerplate; we’ll replace in Phase 5)
.gitignore(markdown / common patterns)- LICENSE: leave blank; this is an internal vault, not public
- Branch protection on
main: require PR review before merge - Initial folder structure (commit empty
.gitkeepper folder):decisions/ design/ planning/ proof/ runbooks/ sops/ reference/ canon/ - Commit
obsidian-vault-config.mdat root (see Phase 5 runbook for contents)
4.3 Create nathel-intranet repo
- GitHub → org → New repository
- Name:
nathel-intranet - Visibility: Private
- Same folder structure as 4.2
- Branch protection same as 4.2
- Note: this repo lives in FIN’s org initially. Plan to transfer admin to Nathel’s GitHub org (if they have one) after Phase 5 stabilizes. Rob retains co-admin.
4.4 Set up Webhook URLs (placeholders)
For each repo, set up the placeholder webhook config. We won’t activate until Phase 4 has the receiver code ready.
- Repo → Settings → Webhooks → Add webhook
- For
fin-central-intranet:- Payload URL:
https://central.fin.app/api/v1/webhooks/github(placeholder) - Content type:
application/json - Secret: generate a fresh HMAC secret; store in AWS SM at
/fin/central/github-webhook-secret - Events: push, pull_request
- Active: No for now; we’ll activate in Phase 4
- Payload URL:
- For
nathel-intranet:- Payload URL:
https://nathel.fin.app/api/v1/webhooks/github(placeholder; might already exist if you’ve wired the current deployment) - Same setup, separate secret stored at
/fin/tenant/nathel/github-webhook-secret
- Payload URL:
5. Verification + Documentation (15-30 minutes)
5.1 Sanity check
Confirm you can see (don’t touch yet):
-
nathel-prodNeon project (renamed) -
fin-central-prodNeon project with 4 tables + projection tables -
nathel-tenant-fin-agenticWorker (current, retagged) -
fin-central-fin-agenticWorker (new, “hello world”) -
fin-central-hyperdriveconfig -
fin-central-artifactsR2 bucket - DNS record for
central.fin.app -
fin-central-intranetGitHub repo with folders -
nathel-intranetGitHub repo with folders - AWS SM
/fin/central/*subtree with database-url + API keys - AWS SM
/fin/tenant/nathel/*subtree (existing or migrated)
5.2 Record what you did
Append to this runbook or to a new note:
- Exact Neon connection strings (in password manager, NOT in repo)
- Cloudflare Worker IDs
- Hyperdrive binding IDs
- KV namespace IDs (when created in 3.3)
- Webhook secrets (in AWS SM)
- Anything you renamed or moved
This becomes the recovery doc if something needs to be reverted.
5.3 Don’t deploy anything yet
Phase 1 is provisioning only. The new Worker is a “hello world” placeholder. The new Neon DB is empty (only schema). The new GitHub repos have only folder skeletons.
Phase 2 (next) is the code work that activates the new infrastructure.
6. Rollback Plan
If anything goes wrong in Phase 1, rollback is mostly trivial because nothing is wired up yet:
- Neon: delete the new
fin-central-prodproject. Rename existing back if needed. No data loss because we haven’t migrated yet. - Cloudflare: delete the new Worker. Revert env vars on
nathel-tenant-fin-agenticif you don’t want them yet. Routes haven’t changed. - GitHub: archive or delete the new repos.
- AWS SM: delete the new secrets.
- DNS: delete the new record.
Nothing in Phase 1 affects production Nathel operations. If something breaks, it’s in the new provisioning, not the running tenant.
7. Common Pitfalls
- Pasting the wrong connection string. Neon connection strings are long and error-prone. Use the “copy” button in Neon UI, don’t retype.
- Missing pgvector extension. New Neon project needs
CREATE EXTENSION pgvector;before HNSW indexes can build. Check the migration log to confirm extensions installed. - Setting routes on the new Worker too early. Don’t bind
central.fin.appto the new Worker until Phase 5 — it would route live traffic to a hello-world response. - GitHub webhook activation too early. Leave webhooks inactive until Phase 4 receiver code ships, or they’ll attempt to deliver to endpoints that don’t exist and emit retry storms.
- Mixing tenant and central secrets. AWS SM subtree discipline matters. If a secret is accessed by both deployments, duplicate it to both subtrees rather than sharing — it makes the demarcation enforceable.
8. What’s Next After Phase 1
Phase 2 (Code Demarcation, 4-8 hours):
- Add
DEPLOYMENT_ROLEenv wiring in fin-agentic - Gate scrapers, Taproot canonical writers, anonymization policy,
Tier 0 routes behind
role === central - Gate email ingest, PP extractors, operator agents, portals behind
role === tenant - Deploy fin-agentic to both Workers with their respective roles
- Verify role-correct features activate per deployment
See docs/architecture/FIN_CENTRAL_TENANT_DEMARCATION_PLAN_2026-05-15.md
§5 for full Phase 2 spec.
9. Success Criteria
Phase 1 is complete when:
- Two Neon projects exist with the same schema, named clearly
- Two Cloudflare Workers exist with role env vars set
- Two GitHub vault repos exist with folder structures and webhooks pre-configured but inactive
- AWS SM has separate subtrees per role
- DNS records reserved for both routes
- You can articulate: “central.fin.app will serve FIN Central; nathel.fin.app continues serving Nathel; they share the fin-agentic codebase but deploy with different role configs.”
Total elapsed: 2-4 focused hours. Most of this is Cloudflare UI clicking; the code work begins in Phase 2.