# Money Factory · Complete Extension Brief (v2)
> **Self-contained spec for any AI extending or integrating with this system.** Read once, full context. No external docs needed.
> v2 supersedes v1 — covers everything live as of 2026-05-12.

---

## 1. IDENTITY

- **Name:** The Money Factory (Cloudflare project: `nr-money-factory`)
- **Owner:** Trent McRae · Penta Dank · Next Realm Interactive
- **Public URL:** https://nr-money-factory.pages.dev
- **Local repo:** `C:\Users\tmcra\OneDrive\Desktop\NEXT REALM INTERACTIVE\OVERNIGHT_MONEY_APPS\`
- **CF account ID:** `869002bb49acbb6b6e30d499b587c929`
- **Origin session:** `7b436a20-a63e-49b0-a48d-d31853e8e1a4`

**One-paragraph definition:** A federated portfolio of 85 live consumer micro-SaaS AI tools running on Cloudflare Pages, anchored by a master grid that triples as (a) the public landing page, (b) the operator console for the owner, and (c) a self-serve operator portal where vetted external operators apply, get approved, and **claim individual apps to white-label as their own businesses** with their own branding, pricing, and Stripe payouts. The platform takes a 20% revenue split. On top of that the master grid runs **autonomous AI agents** that do marketing (Director, Copywriter, Recruiter, Curator, Analyst), idea discovery (the Scout), B2B outreach (the Prospector), and message delivery (CARRIER). Built to be ingested by Next Realm OS (NRO) via factory-federation/v1 spec, so the entire portfolio appears as one node in a larger operator mesh.

**Strategic intent:**
- Generate revenue at scale: 85 apps × hundreds of operators × niche specialization
- Be the canonical "white-label AI tool factory"
- Establish factory-federation/v1 as a standard so other AI factories interoperate
- Operate fully autonomously: 1 founder + AI agents run a 5-person growth team

**Current state (2026-05-12):**
- ✅ 85 apps live, all bound to shared D1 + Workers AI
- ✅ LLM router (CF Workers AI Llama 3.3 70B free / Anthropic Sonnet pro / Groq fallback)
- ✅ Open Beta launch stack everywhere
- ✅ Operator program (1 approved: `@smoketest`)
- ✅ Toolkit revenue node ($29/$99/$299 tiers · 24 grandfathered listings)
- ✅ Federation v1 (discovery + 3 read endpoints + outbound NRO Hub push)
- ✅ Launch Director (one-click 30-day launch plans)
- ✅ AI Marketing Team (5 agents · cron-ready · approval queue · intent URLs)
- ✅ Scout engine (300/day idea discovery · 4 sources · LLM scoring 0-350 · pitch composer)
- ✅ Prospect Pipeline (B2B founder discovery via public web · Prospector LLM agent · 3-step sequences)
- ✅ CARRIER (channel-agnostic multi-backend send/receive · dryrun mode default · auto-upgrades to Resend/MailChannels)
- ✅ AI hero image generation (flux-1-schnell, edge-cached)
- ✅ Cinematic landing (animated gradient bg · Space Grotesk hero · sticky topnav · 3-role band)
- 🔧 v6 Clarity overhaul (cleanup spec written, awaiting approval)
- ❌ Brand resolver (per-request branding per claim) — designed, not built
- ❌ Stripe Connect (operator payouts) — planned

---

## 2. STACK

| Layer | Choice | Notes |
|---|---|---|
| Runtime | Cloudflare Pages Functions (Workers) | edge runtime, no cold starts, sub-100ms |
| Compat | `compatibility_date = "2025-04-01"`, `compatibility_flags = ["nodejs_compat"]` | per app + master |
| Database | Cloudflare D1 (SQLite at edge) | one shared db: `nextrealm-production` (UUID `7e9df4a7-1c34-4dc4-865c-01315e5bab0d`) |
| LLM | Multi-provider router | CF Workers AI Llama 3.3 70B (free) primary · Anthropic Claude Sonnet 4.6 (pro) · Groq fallback |
| Image gen | CF Workers AI flux-1-schnell | per-app hero images, edge-cached 24h |
| Email | CARRIER abstraction → Resend / MailChannels / dryrun | dryrun by default; auto-upgrades on key drop-in |
| Payments | Stripe Checkout + webhooks | per-app secret; Stripe Connect for operators (planned) |
| Frontend | Vanilla HTML/JS/CSS, no framework | Tailwind via CDN on per-app sites |
| Build | None — direct upload via wrangler | no bundler, no transpilation |
| CLI | wrangler 4.90.0 (installed globally + `npx wrangler@latest` works) | |

**Capacity caps:**
- CF Pages projects: **86 of 100 free** (85 NR-* + 1 master)
- D1 databases: 10 free / 50,000 paid (using 1: `nextrealm-production`)
- Workers AI: **10,000 neurons/day free** (≈ thousands of generations across portfolio)
- Workers Free subrequests: **50 per request** — every wizard/scout/cron paginates to PAGE=30
- D1 storage: 5 GB free
- D1 reads: 5M/day, writes: 100k/day

**15 apps queued but not deployed** (hit 100-project cap): `raidsched, lfgmatch, mmorotation, streamclip, barberbook, tattooportfolio, menubuilder, realestatepost, contractorquote, cleaningcrm, roofingleads, detailquote, etsyopt, gumroadgen, productvault, voicecompliment`

---

## 3. CREDENTIALS & URLS

**All values persisted at:** `.cache/system-secrets.json` (gitignored)

| Name | Value | Where used |
|---|---|---|
| Master grid login | `moneyfactory-00272970` | nr-money-factory.pages.dev → Admin tab |
| Per-app admin password | `nrfactory-90a0a92c2dac` | every nr-<slug>.pages.dev/admin |
| FACTORY_TOKEN | `6ee5cbd439235a62dff7b03599fdfd5f0eb09da5931c95e0` | cross-app machine auth (Bearer) |
| ADMIN_SECRET | `8f9f961e77b8206a1819e011a97647362a086ca3a1cdc035` | per-app cookie HMAC |
| OPERATOR_SECRET | `10bc20724102070c48490f9cd03c9f5ca1314a0c329c2fa1` | operator session HMAC |
| AGENTS_CRON_SECRET | `nro-cron-C9B728C0C098CB06` | header for /api/factory/agents/cron + /scout/cron + /cleanup |
| MASTER_PASSWORD secret | (set on master) | Admin login |
| MASTER_SECRET | (set on master) | master cookie HMAC |
| CF_API_TOKEN | `cfat_eZHEf...` (in chat history; rotate after build) | bulk wizards |
| CF_ACCOUNT_ID | `869002bb49acbb6b6e30d499b587c929` | wizards |
| ANTHROPIC_API_KEY | $50 credit standing by, NOT YET PUSHED per user request | Pro tier LLM router |
| RESEND_API_KEY | not configured (CARRIER falls back to dryrun) | when set: CARRIER auto-routes through Resend |
| MAILCHANNELS_API_KEY | not configured | when set: CARRIER auto-routes through MailChannels |
| HUNTER_API_KEY | not configured (Prospector uses public-web extraction only) | when set: domain email enrichment ($34/mo) |

**Key URLs:**
- Master grid: https://nr-money-factory.pages.dev
- Operator portal: /operator
- Toolkit listing apply page: /toolkit
- Federation discovery: /.well-known/factory.json
- Public unsubscribe: /unsubscribe
- Sample app: https://nr-roastmywebsite.pages.dev
- All 85: `https://nr-<slug>.pages.dev` (slugs in `functions/_lib/live-apps.ts`)

---

## 4. FILE STRUCTURE

```
OVERNIGHT_MONEY_APPS/
├── index.html                     # master grid SPA (5 view tabs + 18 admin sections)
├── factory.js                     # master grid logic (~1900 lines)
├── apps.js                        # APP[] registry: name, desc, price, tags, status
├── operator.html                  # standalone /operator portal
├── toolkit.html                   # standalone /toolkit application page
├── styles.css                     # shared theme tokens
├── wrangler.toml                  # master config (with [ai] binding for OG gen)
├── .assetsignore                  # excludes NR-*/, node_modules/, .cache/, *.log
│
├── _NR-CORE/                      # shared library (bundled into each NR-* via Python script)
│   ├── ai.ts                      # multi-provider LLM router — claude(env, msgs, opts)
│   ├── analytics.ts               # track() + getKpis() + getFlag()
│   ├── stripe.ts                  # createCheckoutSession() + verifyWebhook()
│   ├── admin.ts                   # per-app admin auth helpers
│   ├── admin-handlers.ts          # per-app admin route handlers
│   ├── nro_export.ts              # pushToNRO() — federation outbound
│   ├── schema.sql                 # universal D1 schema for app tables
│   ├── ui/
│   │   ├── open-beta-snippet.html # injected into every NR-*/public/index.html
│   │   ├── admin-shell.html       # shared admin chrome
│   │   └── theme.css              # shared theme
│   └── README.md
│
├── functions/                     # master grid Pages Functions
│   ├── _lib/
│   │   ├── admin.ts               # master cookie auth (factory_admin)
│   │   ├── operators.ts           # operator cookie auth + D1 helpers (d1Query, d1Rows, d1One)
│   │   ├── live-apps.ts           # source-of-truth array of 85 live slugs
│   │   ├── agents.ts              # 5-agent prompts + LLM calls + output parser + intent URLs
│   │   ├── scout-sources.ts       # Reddit / HN / App Store / Product Hunt connectors
│   │   ├── scout-analyst.ts       # 7-dimension scoring (0-350) + pitch composer
│   │   ├── prospector.ts          # web extraction + email composer + compliance helpers
│   │   └── carrier.ts             # CARRIER channel layer — unified send/receive abstraction
│   ├── .well-known/
│   │   └── factory.json.ts        # federation discovery doc
│   ├── unsubscribe.ts             # public CAN-SPAM unsubscribe page + suppression
│   └── api/
│       ├── factory/               # auth: master cookie (except where noted)
│       │   ├── login.ts logout.ts me.ts
│       │   ├── health.ts          # paginated app health probe
│       │   ├── setup.ts           # paginated bulk secret PATCH via CF API
│       │   ├── d1bind.ts          # paginated bulk D1 binding
│       │   ├── bindai.ts          # paginated bulk Workers AI binding
│       │   ├── og.ts              # CF flux image generator (edge-cached)
│       │   ├── founders.ts        # public POST + auth GET (Beta Founders capture)
│       │   ├── operators.ts       # master-side operator approval/list/suspend
│       │   ├── snapshot/[slug].ts # proxy to per-app KPI snapshot
│       │   ├── events.ts          # aggregated event stream
│       │   ├── toolkit.ts         # toolkit listing CRUD (master mutations)
│       │   ├── launch.ts          # Launch Director endpoint (full 30-day plans)
│       │   ├── agents/            # AI Marketing Team
│       │   │   ├── run.ts         # master · invoke any agent for any app
│       │   │   ├── cron.ts        # X-Cron-Secret · daily auto-run
│       │   │   ├── outputs.ts     # queue list + approve/reject/mark-published
│       │   │   └── cron-config.ts # master · returns cron secret + schedule
│       │   ├── scout/             # The Scout · idea discovery
│       │   │   ├── run.ts         # master · run pipeline (dry or real)
│       │   │   ├── cron.ts        # X-Cron-Secret · daily 30-idea pass
│       │   │   ├── ideas.ts       # list/filter/promote/trash/reject ideas
│       │   │   └── cleanup.ts     # TTL purge stale + permanent delete >30d
│       │   ├── prospects/         # The Prospector · B2B outreach
│       │   │   ├── discover.ts    # web extraction → contacts
│       │   │   ├── list.ts        # list/filter/summary
│       │   │   ├── sequence.ts    # LLM writes 3-email Day 1/4/10 sequence
│       │   │   └── send.ts        # send via CARRIER (with pre-flight checks)
│       │   └── carrier/           # 📡 CARRIER channel layer
│       │       ├── send.ts        # unified send any channel
│       │       ├── inbox.ts       # internal test inbox view
│       │       ├── setup.ts       # config + dryrun↔live toggle
│       │       └── webhook.ts     # Resend/MailChannels delivery events
│       ├── operators/             # auth: operator cookie OR public
│       │   ├── apply.ts login.ts me.ts catalog.ts claim.ts
│       ├── toolkit/
│       │   └── apply.ts           # public POST · toolkit listing application
│       └── federation/            # public, CORS-open, sanitized
│           ├── catalog.ts operators.ts stats.ts
│
├── NR-<slug>/                     # 101 app folders (85 deployed + 16 queued)
│   ├── public/
│   │   ├── index.html             # branded landing (with open-beta snippet injected)
│   │   ├── styles.css app.js
│   ├── functions/
│   │   ├── _lib/core.ts           # bundled _NR-CORE — sync via Python script
│   │   └── api/
│   │       ├── generate.ts        # POST /api/generate — calls claude() from core.ts
│   │       ├── checkout.ts webhook.ts track.ts
│   │       ├── admin/{login,stats,users,payments,events,flags,generations}.ts
│   │       └── factory/{snapshot,events}.ts  # auth: Bearer FACTORY_TOKEN
│   ├── wrangler.toml              # MUST include [[d1_databases]] + [ai] blocks
│   └── schema.sql
│
├── scripts/                       # operational helpers
│   ├── audit-deployments.py       # → deployments-manifest.json
│   ├── push-system-secrets.py     # paginated wrapper of master /setup
│   ├── bind-d1.py bind-ai.py      # paginated wrappers
│   ├── redeploy-fast.sh           # sequential per-app redeploy (~15 min for 85)
│   └── bulk-*.ps1                 # PowerShell equivalents
│
├── .cache/                        # gitignored runtime data
│   └── system-secrets.json
│
├── deployments-manifest.json      # canonical state from CF API
├── docs/                          # full documentation
│   ├── README.md ARCHITECTURE.md API_REFERENCE.md
│   ├── DATA_MODEL.md DEPLOYMENTS.md FEDERATION.md
└── HANDOFF.md OPERATOR_PROGRAM.md TUTORIAL.md
   LAUNCH_AI_PROMPT.md LAUNCH_PLAYBOOK.md CLEANUP_V6_SPEC.md
   EXTENSION_BRIEF.md (this file)
```

---

## 5. DATA MODEL — every D1 table

Database: `nextrealm-production` (UUID `7e9df4a7-1c34-4dc4-865c-01315e5bab0d`), bound as `env.DB` on every NR-*.

### Core (universal — `_NR-CORE/schema.sql`)
- **`events`** (id, ts, session_id, user_id, event, path, referrer, country, ua, meta) — analytics firehose
- **`users`** (id PK=email-or-stripe-id, email UNIQUE, created_at, plan='free|pro|lifetime', stripe_customer_id, meta)
- **`subscriptions`** (id PK=stripe-sub, user_id, status, plan, current_period_end, created_at)
- **`payments`** (id PK=stripe-pi-or-session, user_id, amount_cents, currency, status, product, created_at, meta)
- **`generations`** (id, ts, session_id, user_id, input, output, model, tokens_in, tokens_out, cost_cents, meta)
- **`feature_flags`** (key PK, value, updated_at) — runtime config

### Beta capture
- **`founders`** (id, email UNIQUE, app_slug, source, ip, ua, country, ts, meta)

### Operator program
- **`operators`** (id PK='op_<16hex>', email UNIQUE, handle UNIQUE, display_name, tier='bronze|silver|gold|diamond', status='pending|approved|suspended', password_hash, password_salt, stripe_account_id, custom_domain, default_brand JSON, applied_at, approved_at, approved_by, meta)
- **`claims`** (id PK='clm_<16hex>', operator_id FK, app_slug, niche, subdomain, custom_domain, brand JSON, pricing JSON, system_prompt_override, active_model, status='active|paused|reclaimable|removed', claimed_at, last_active_at, meta · UNIQUE(operator_id, app_slug, niche))
- **`claim_revenue`** (id, claim_id FK, ts, event_type='charge|refund|platform_fee', amount_cents, stripe_id, meta)

### Toolkit (revenue node)
- **`toolkit_listings`** (id PK='tl_<16hex>', app_slug, external_url, external_name, external_desc, external_icon, external_category, owner_email, owner_handle, tier='listed|featured|spotlight', status='applied|approved|active|paused|rejected', monthly_cents, stripe_subscription_id, expires_at, ordering, pitch, applied_at, approved_at, approved_by, meta)

### Launch Director
- **`launch_packages`** (id, app_slug, variant, brand, niche, audience, package_md, asset_count, generated_at, generated_by, model_used, provider, cost_cents, meta)

### AI Marketing Team
- **`agent_runs`** (id, agent='director|copywriter|recruiter|curator|analyst|team', trigger='manual|cron|event', app_slug, niche, status='running|done|failed', output_count, cost_cents, model_used, provider, duration_ms, error, started_at, finished_at, meta)
- **`agent_outputs`** (id, run_id FK, agent, channel='twitter|reddit|linkedin|tiktok|email|dm|...', app_slug, title, body, meta JSON, status='queued|approved|published|rejected', publish_url, created_at, approved_at, published_at, approved_by)

### Scout · Idea Board
- **`discovered_ideas`** (id PK='idea_<16hex>', source='reddit|hackernews|appstore|producthunt|manual', source_id, source_url, raw_title, raw_payload JSON, signature_name, pitch_md, hero_image_url, category, niche, estimated_build_hours, estimated_arr_cents, defensibility_note, recommended_operator_archetype, score_market/audience/feasibility/signature_fit/differentiation/speed/monetization (each 0-50), score_total (0-350), status='discovered|analyzing|pitched|dev_queue|building|shipped|trashed|rejected', promoted_to_dev_at, promoted_by, built_as_slug, trashed_at, trash_reason, discovered_at, analyzed_at, pitched_at, meta · UNIQUE(source, source_id))
- **`scout_runs`** (id, trigger, source, ideas_discovered, ideas_pitched, ideas_skipped, status, duration_ms, cost_cents, error, started_at, finished_at, meta)

### Prospect Pipeline · The Prospector
- **`prospects`** (id PK='pr_<16hex>', email UNIQUE, name, title, company, company_domain, company_url, social_handle, source='scout_idea|hunter|apollo|manual|warm_founders|warm_operators', source_idea_id FK, source_confidence (0-100), geo_country, pitch_angle='operator|partner|toolkit|customer', status='discovered|enriched|queued|sent|replied|converted|opted_out|bounced|suppressed', added_at, enriched_at, last_outreach_at, reply_at, meta)
- **`prospect_sequences`** (id, prospect_id FK, step (1-3), channel='email|linkedin', subject, body_md, scheduled_for, sent_at, resend_message_id, open_at, click_at, bounce_at, reply_at, status='draft|scheduled|sent|bounced|replied|cancelled', created_at)
- **`suppression_list`** (email PK, reason='opted_out|bounced|manual|gdpr|spam_complaint', added_at, source_seq_id)

### CARRIER · channel layer
- **`carrier_messages`** (id, channel='email|x|linkedin|instagram|facebook|sms', direction='outbound|inbound', backend='dryrun|resend|mailchannels|ses|manual', to_addr, from_addr, subject, body_text, body_html, meta JSON, external_id, status='queued|sent|delivered|opened|clicked|bounced|failed|replied', cost_cents, scheduled_for, sent_at, delivered_at, opened_at, clicked_at, bounced_at, replied_at, error, created_at)

### Feature flags currently seeded (50+)
```
# Core
paywall_enabled=true, free_daily_limit=5, pro_price_cents=900, lifetime_price_cents=4900
active_model='cloudflare', beta_banner_enabled=true, beta_lifetime_price_cents=500

# Operator program
operator_tier_{bronze,silver,gold,diamond}_max_claims = 1, 3, 10, 999
operator_revenue_split_pct=20, operator_program_open=true

# Toolkit revenue
toolkit_tier_{listed,featured,spotlight}_cents = 2900, 9900, 29900
toolkit_max_{listed,featured,spotlight} = 40, 12, 4
toolkit_program_open=true

# AI Marketing Team
agents_enabled=true, agents_cron_secret=<auto-gen>, agents_daily_app_count=5

# Scout
scout_enabled=true, scout_daily_cap=300, scout_dev_queue_nightly_cap=100
scout_pitch_min_score=200, scout_idea_ttl_days=7, scout_dev_ttl_days=30
scout_sources_enabled='reddit,hackernews,appstore,producthunt'

# Prospect Pipeline
prospects_enabled=true, prospects_daily_send_cap=50, prospects_per_domain_cap=3
prospects_skip_gdpr_geos=true
prospects_geos_to_skip='DE,FR,IT,ES,NL,BE,SE,DK,FI,NO,AT,IE,PL,CZ,PT,GR,UK,GB,CA'

# CARRIER
carrier_default_backend='dryrun'
carrier_email_backend_priority='resend,mailchannels,dryrun'
carrier_dryrun_mode='true'  ← flip to 'false' for live sending
carrier_sender_name='Trent McRae · Next Realm'
carrier_sender_email='outreach@nr-money-factory.pages.dev'
carrier_unsubscribe_url='https://nr-money-factory.pages.dev/unsubscribe'
carrier_physical_address='Set this in Admin → Carrier before live sending (CAN-SPAM)'
```

---

## 6. EVERY API ENDPOINT (75+)

### Master grid `/api/factory/*` (auth: master cookie unless noted)
```
POST   /api/factory/login              {password}                                  public
POST   /api/factory/logout                                                         public
GET    /api/factory/me                                                             cookie
GET    /api/factory/health?offset&limit&deep=1                                     public
POST   /api/factory/setup              {secrets, apps, offset, limit, dry_run?}    cookie
GET    /api/factory/setup                                                          cookie
GET    /api/factory/d1bind                                                         cookie
POST   /api/factory/d1bind             {uuid, name, binding, apps, offset, limit}  cookie
POST   /api/factory/bindai             {binding, apps, offset, limit}              cookie
GET    /api/factory/og?slug&name&tags                                              public · 24h cache
POST   /api/factory/founders           {email, app_slug?, source?}                 public CORS
GET    /api/factory/founders                                                       cookie
GET    /api/factory/operators                                                      cookie · pending+claims
POST   /api/factory/operators          {operator_id, tier?, password?}             cookie · approve
DELETE /api/factory/operators?id=                                                  cookie · suspend
GET    /api/factory/snapshot/[slug]                                                cookie
GET    /api/factory/events                                                         cookie
GET    /api/factory/toolkit                                                        public · live listings
GET    /api/factory/toolkit?status=applied|all                                     cookie
POST   /api/factory/toolkit            {id, status?, tier?, ordering?, ...}        cookie
POST   /api/factory/toolkit?action=approve|reject  {id, tier?, reason?}            cookie
DELETE /api/factory/toolkit?id=                                                    cookie
POST   /api/factory/launch?slug=&variant=LAUNCH|WEEKLY|RELAUNCH|KILL               cookie
GET    /api/factory/launch                                                         cookie · history
GET    /api/factory/launch?id=                                                     cookie
```

### AI Marketing Team `/api/factory/agents/*`
```
POST   /api/factory/agents/run         {agent, app_slug?, niche?, input?}          cookie
GET    /api/factory/agents/cron                                                    X-Cron-Secret
POST   /api/factory/agents/cron?agent=copywriter                                   X-Cron-Secret · daily run
GET    /api/factory/agents/cron-config                                             cookie · returns secret
GET    /api/factory/agents/outputs?status=queued|approved|published|rejected       cookie
POST   /api/factory/agents/outputs     {id, action: 'approve|reject|mark_published'} cookie
```

### Scout `/api/factory/scout/*`
```
POST   /api/factory/scout/run          {dry_run?: bool, limit?: 1-60}              cookie
GET    /api/factory/scout/cron                                                     X-Cron-Secret
POST   /api/factory/scout/cron                                                     X-Cron-Secret · daily 30-pass
GET    /api/factory/scout/ideas?status=&limit=                                     cookie
GET    /api/factory/scout/ideas?summary=1                                          cookie
GET    /api/factory/scout/ideas?id=                                                cookie · single + full pitch_md
POST   /api/factory/scout/ideas        {id, action: 'promote|trash|reject|reset|shipped', reason?, slug?} cookie
GET    /api/factory/scout/cleanup                                                  cookie OR X-Cron-Secret · preview
POST   /api/factory/scout/cleanup                                                  cookie OR X-Cron-Secret · execute
```

### Prospect Pipeline `/api/factory/prospects/*`
```
POST   /api/factory/prospects/discover {idea_id?, url?, pitch_angle?}              cookie
GET    /api/factory/prospects/list?status=                                         cookie
GET    /api/factory/prospects/list?summary=1                                       cookie
GET    /api/factory/prospects/list?id=                                             cookie · single + sequence
POST   /api/factory/prospects/sequence {prospect_id, pitch_angle?, context?}       cookie
POST   /api/factory/prospects/send     {sequence_id, dry_run?}                     cookie · routes through CARRIER
```

### 📡 CARRIER `/api/factory/carrier/*`
```
POST   /api/factory/carrier/send       {channel, to, subject?, body, html?, ref?, tags?}  cookie · UNIFIED SEND
GET    /api/factory/carrier/inbox?status=&backend=&channel=&limit=                 cookie
GET    /api/factory/carrier/inbox?summary=1                                        cookie
GET    /api/factory/carrier/inbox?id=                                              cookie · full HTML preview
GET    /api/factory/carrier/setup                                                  cookie · config + readiness
POST   /api/factory/carrier/setup      {key, value} OR {action: 'go_live|go_dryrun'}  cookie
POST   /api/factory/carrier/webhook    (Resend/MailChannels delivery events)       public
GET    /api/factory/carrier/webhook                                                public · info doc
```

### Operator endpoints `/api/operators/*`
```
POST   /api/operators/apply            {email, handle, display_name?, pitch?}      public CORS
POST   /api/operators/login            {handle_or_email, password}                 public · Set-Cookie
GET    /api/operators/catalog                                                      public CORS
GET    /api/operators/me                                                           operator cookie
POST   /api/operators/me               {display_name?, custom_domain?, default_brand?, stripe_account_id?}  operator cookie
POST   /api/operators/claim            {app_slug, niche?, brand?, pricing?}        operator cookie · tier-gated
PATCH  /api/operators/claim?id=        {brand?, pricing?, system_prompt_override?, active_model?, custom_domain?, status?, niche?}  operator cookie
DELETE /api/operators/claim?id=                                                    operator cookie
```

### Toolkit application `/api/toolkit/*`
```
POST   /api/toolkit/apply              {external_name, external_desc, external_url, external_icon, external_category, owner_email, tier, pitch}  public CORS
```

### Federation `/api/federation/*` (public, CORS-open, sanitized, cached)
```
GET    /.well-known/factory.json                  spec discovery + capabilities + terms (5min cache)
GET    /api/federation/catalog                    every live app stable shape (2min cache)
GET    /api/federation/operators                  approved operators sanitized (5min cache)
GET    /api/federation/stats                      aggregate KPIs (2min cache)
```

### Per-app endpoints `/api/*` on every nr-<slug>.pages.dev
```
POST   /api/generate                   {input/url/topic/prompt, session_id}        core LLM endpoint via claude()
POST   /api/checkout                   {plan: 'pro'|'lifetime'}                    Stripe checkout
POST   /api/webhook                    Stripe-signed body                          Stripe events
POST   /api/track                      {event, session_id, meta?}                  analytics
POST   /api/admin/login                {password}                                  Set-Cookie nr_admin
GET    /api/admin/{stats,users,payments,events,flags,generations}                  per-app cookie
POST   /api/admin/flags                {key, value}
GET    /api/factory/snapshot           Bearer FACTORY_TOKEN                        KPI export
GET    /api/factory/events             Bearer FACTORY_TOKEN                        event tail
```

### Public unsubscribe
```
GET    /unsubscribe?email=             public · auto-suppresses + renders confirmation
POST   /unsubscribe                    {email}                                      public · suppress
```

### Standard pagination contract (setup/d1bind/bindai/health/scout/agents)
```json
{ "summary": { "total": 30, "total_apps": 85, "offset": 0, "limit": 30, "has_more": true,
               "ok": 30, "failed": 0, ... },
  "results": [{"slug":"...", "ok":true, ...}, ...] }
```
Client loops: `for (off=0; off<200; off+=PAGE) { fetch(...&offset=off&limit=PAGE); if (!has_more) break; }`

---

## 7. AUTH MODEL

| Cookie | Lifetime | Issuer | Verifies |
|---|---|---|---|
| `factory_admin` | 7d | POST /api/factory/login | password === MASTER_PASSWORD, signed by MASTER_SECRET |
| `nro_operator` | 30d | POST /api/operators/login | HMAC(OPERATOR_SECRET+salt, password), signed by OPERATOR_SECRET |
| `nr_admin` (per-app) | 7d | POST /api/admin/login | password === ADMIN_PASSWORD, signed by app's ADMIN_SECRET |

Plus machine: `Authorization: Bearer <FACTORY_TOKEN>` for cross-app calls.
Plus cron: `X-Cron-Secret: <agents_cron_secret>` for /agents/cron + /scout/cron + /scout/cleanup.

Cookie format: `<role>.<exp_ms>.<hex_hmac>`. Verify by recomputing HMAC.

---

## 8. LLM PROVIDER ROUTER (`_NR-CORE/ai.ts`)

Single function `claude(env, messages, opts)` routes by tier:

```typescript
async function claude(env, messages, opts) {
  const tier = opts.tier ?? (opts.is_pro ? 'pro' : 'free');
  // pro tier with key → Anthropic Claude Sonnet 4.6
  if (tier === 'pro' && env.ANTHROPIC_API_KEY) {
    try { return await callAnthropic(env, msgs, opts, 'claude-sonnet-4-6'); }
    catch { /* fall through */ }
  }
  // free tier → CF Workers AI Llama 3.3 70B (free, edge, ~100ms)
  if (env.AI) {
    try { return await callCloudflare(env, msgs, opts, '@cf/meta/llama-3.3-70b-instruct-fp8-fast'); }
    catch {
      if (env.GROQ_API_KEY) try { return await callGroq(...); } catch {}
      if (env.ANTHROPIC_API_KEY) try { return await callAnthropic(...); } catch {}
      try { return await callCloudflare(env, msgs, opts, '@cf/meta/llama-3.1-8b-instruct'); } catch {}
    }
  }
  // No providers → echo placeholder
  return { text: '{"error":"no_llm_provider"}', usage:{...}, provider:'echo', model:'echo' };
}
// Returns: { text, usage, provider, model }
```

**Same call site every app uses:**
```typescript
import { claude } from "../_lib/core";
const out = await claude(env, [{role:'user', content:userMsg}], { system, max_tokens: 1500, cache_system: true });
```

---

## 9. THE 5-AGENT MARKETING TEAM (`_lib/agents.ts`)

Each agent has its own role/prompt. All callable via `/api/factory/agents/run` or daily cron.

| Agent | Role | Input | Output | Speed/Cost |
|---|---|---|---|---|
| 🎬 **The Director** | CGO · 30-day launch packages | `LAUNCH: <slug>` | 4-section package: positioning, content arsenal, metrics, next-7-days | 30s · $0.0001 Llama / $0.05 Sonnet |
| ✍️ **The Copywriter** | Daily content factory | `DAILY: <slug>` | 5-7 publish-ready items: 2 X / 1 Reddit / 1 LinkedIn / 1 TikTok / 1 email | 13s · $0.0001 Llama |
| 📡 **The Recruiter** | Operator outreach DMs | `RECRUIT: <niche>` | 5 archetype-specific DMs ≤80 words | 15s · $0.0001 Llama |
| ⚖️ **The Curator** | Toolkit application reviewer | `CURATE: <json>` | Approve/reject + 80-word verdict | 5s · $0.00005 Llama |
| 📊 **The Analyst** | Metrics → action | `ANALYZE: <slug>` + stats JSON | HEALTHY / FLAT / DEAD verdict + concrete next move | 10s · $0.0001 Llama |

**Output queue + intent URLs:** Every parsed output gets a one-click publish URL (Twitter intent, Reddit submit, LinkedIn share, mailto:). Status: `queued → approved → published OR rejected`.

**Cron (daily auto-run):** `POST /api/factory/agents/cron` with `X-Cron-Secret` header → runs The Copywriter for the top 5 most-active apps. Set up via Cloudflare Cron Trigger or external pinger.

---

## 10. THE SCOUT (`_lib/scout-sources.ts` + `_lib/scout-analyst.ts`)

Autonomous discovery engine. Pulls signals from public sources, scores 0-350 confidence, generates full pitch decks for ideas worth building.

**Sources (4 connectors live):**
- **Reddit** — top posts from 13 SaaS/indie/gaming subs, prioritizing revenue-mentioning posts
- **HackerNews** — Show HN with ≥30 points (Algolia API, public)
- **Apple App Store** — top 100 free + top 50 paid (RSS, public)
- **Product Hunt** — daily top (RSS)

**Analyst scoring rubric (each 0-50, total /350):**
- `market` — signal strength (rank, reviews, age, buzz)
- `audience` — operator-network fit
- `feasibility` — can we ship in <12hr on our stack
- `signature_fit` — matches our cinematic AI-wrapper voice
- `differentiation` — wedge over original
- `speed` — launch in <72h
- `monetization` — clear $9/mo or $5 lifetime path

Pitch composer fires when score ≥ 200, generates full markdown pitch + binds AI hero image URL.

**Caps:**
- 300 ideas/day max (`scout_daily_cap`)
- 100 dev queue promotions/night (`scout_dev_queue_nightly_cap`)
- TTL: pitched > 7 days → auto-trash; trashed/rejected > 30 days → permanent delete

**Smoke-test verified:** 150 raw ideas pulled in 4.4s across all 4 sources.

---

## 11. THE PROSPECTOR (`_lib/prospector.ts`)

B2B founder outreach. Discovery → enrichment → 3-step email sequence → send via CARRIER.

**Discovery:** `extractFromCompanyUrl(url)` scrapes only public web pages (`/about`, `/contact`, `/team`). Domain-matched emails only. Common noise (no-reply, postmaster, off-domain) auto-filtered. Optional Hunter.io fallback when `HUNTER_API_KEY` set.

**Sequence composer:** LLM writes 3 emails (Day 1 / Day 4 / Day 10) tuned to pitch_angle:
- `operator` — "claim Money Factory apps as your white-label business"
- `partner` — cross-promo
- `toolkit` — "list your tool in The Toolkit, $29-299/mo"
- `customer` — "use this app for your work"

**Compliance:**
- Suppression list (per-email, persistent)
- GDPR geo-skip (19 EU/UK/Canada countries, configurable)
- Daily send cap (default 50)
- Per-domain cap (default 3, anti-spam-flag)
- CAN-SPAM footer + List-Unsubscribe header (auto-injected by CARRIER)
- Public `/unsubscribe` page (one-click, instant)

**Smoke-test verified:** Scraped resend.com/about → found 4 real founder emails @ 80% confidence.

---

## 12. 📡 CARRIER (`_lib/carrier.ts`) — NEW

Next Realm's **own multi-backend channel layer**. One unified `carrierSend(env, {channel, to, subject, body})` and CARRIER handles routing.

**Backend routing logic:**
1. If `carrier_dryrun_mode='true'` (default) → **dryrun backend**: writes fully-rendered envelope to `carrier_messages` table with `status='sent'`, viewable in internal inbox. Nothing leaves.
2. Else if `RESEND_API_KEY` env present → **Resend** (3K/mo free tier)
3. Else if `MAILCHANNELS_API_KEY` env present → **MailChannels** (paid)
4. Else fall back to dryrun (never fails)

**Auto-injected on every email:**
- CAN-SPAM compliance footer with sender name + physical address + unsubscribe link
- `List-Unsubscribe` header (Gmail/Outlook one-click)

**Channels supported:**
- `email` — full pipeline live (dryrun + Resend + MailChannels)
- `x` / `linkedin` / `instagram` / `facebook` / `sms` — schema ready, status='manual_queue' until OAuth wired

**Inbound webhook ingestion:** `POST /api/factory/carrier/webhook` — accepts Resend/MailChannels delivery events, updates `carrier_messages.status` (delivered/opened/clicked/bounced) by `external_id` match.

**To upgrade dryrun → live:**
```bash
# OPTION A — Resend (free 3K/mo)
echo "re_xxx" | wrangler pages secret put RESEND_API_KEY --project-name nr-money-factory
# OPTION B — MailChannels (paid)
echo "..." | wrangler pages secret put MAILCHANNELS_API_KEY --project-name nr-money-factory
# Then in Admin → 📡 CARRIER: set physical address + click 🚀 Go Live
```

**The Prospector now sends through CARRIER** (no more Resend gating errors). Future systems (founders launch email, operator approval emails, daily digests) all use CARRIER.

---

## 13. OPERATOR PROGRAM

5-tier white-label marketplace. Operators apply at `/operator`, master approves, operators claim apps + niches, run them as branded businesses.

**Tier capabilities:**
| Tier | Max active claims |
|---|---|
| Bronze | 1 |
| Silver | 3 |
| Gold | 10 |
| Diamond | 999 |

**Lifecycle:**
1. Apply at `/operator` → status `pending`
2. Master approves via Admin → 🛠 Operators → temp password generated, copies to clipboard
3. Operator logs in → claims `app_slug + niche` → row in `claims` table with `subdomain='op-<handle>-<slug>'`
4. Preview at `https://nr-<slug>.pages.dev?op=<handle>&niche=<niche>` (Brand Resolver Phase V — designed, not built — will read these and apply branding)

**Public:** approved operators visible at `/api/federation/operators` with sanitized profile (no email/password/IP).

---

## 14. TOOLKIT REVENUE NODE

The "85 free tools" cross-app discovery modal on every NR-* app is now a **revenue surface**. Apps (internal NR-* OR external) pay monthly to be listed.

**Tiers (capped to maintain quality):**
| Tier | Price | Cap |
|---|---|---|
| ★ Spotlight | $299/mo | 4 max — hero gold cards |
| ◆ Featured | $99/mo | 12 max — purple-bordered, 2-col |
| · Listed | $29/mo | 40 max — standard listing |

**Flow:**
1. Apply at `/toolkit` → row in `toolkit_listings` with status='applied'
2. Master reviews via Admin → 🧰 Toolkit Manager → approve at chosen tier (Stripe charge on approval — TODO: wire Stripe Connect)
3. Listing appears across every NR-* app's modal automatically (modal fetches from `/api/factory/toolkit`)
4. 24 internal NR-* apps grandfathered free as the baseline curated set

**Projected MRR at full caps:** 4×$299 + 12×$99 + 40×$29 = $3,544/mo = $42K ARR from toolkit alone

---

## 15. FEDERATION v1

`factory-federation/v1` spec. Discovery doc at `/.well-known/factory.json`.

**Inbound (others read from us, public CORS):**
- `/api/federation/catalog` — every live app stable shape
- `/api/federation/operators` — sanitized public operator profiles + claims
- `/api/federation/stats` — aggregate portfolio KPIs

**Sanitization rules (non-negotiable):**
- ❌ Never expose: email, password_hash, stripe_account_id, IP, internal session IDs, factory tokens
- ✅ Safe: handle, display_name, tier, app_slug, niche, public custom_domain, claim_count, timestamps

**Stable response shape:**
```json
{ "spec": "factory-federation/v1/<endpoint>",
  "instance_url": "https://nr-money-factory.pages.dev",
  "generated_at": <ms_epoch>,
  "<resource>": [...] }
```

**Outbound:** every per-app revenue event fires `pushToNRO(env, {...})` if `NRO_HUB_URL` set. Fire-and-forget. Idempotency key: `(app, ts, session_id, type)`.

---

## 16. CONVENTIONS & IDIOMS

**Naming:**
- Apps live as `NR-<slug>/` (folder), `nr-<slug>.pages.dev` (URL), CF project `nr-<slug>`
- Slug: lowercase, alphanumeric + hyphens, ≤30 chars
- Per-claim subdomain: `op-<handle>-<slug>`
- IDs: operator `op_<16hex>`, claim `clm_<16hex>`, idea `idea_<16hex>`, prospect `pr_<16hex>`, toolkit listing `tl_<16hex>`

**Code patterns:**
- All Pages Functions export `onRequest{Get,Post,Put,Patch,Delete,Options}` — never default export
- Always include `type PagesFunction<E>` declaration at bottom of each function file
- Auth gate: `const guard = await requireMaster(env, request); if (guard) return guard;`
- D1 calls via helpers: `d1Rows(env, sql, params)` returns array · `d1One` returns first row · `d1Query` returns full result
- Errors: `Response.json({ ok:false, error:"message" }, { status:4xx })` — never throw to user
- CORS for public endpoints: spread `...CORS` in headers; include separate `onRequestOptions`

**File-bundling pattern:**
- `_NR-CORE/<file>.ts` is source of truth
- Each `NR-<slug>/functions/_lib/core.ts` is concatenation of every `_NR-CORE/*.ts` with `// ===== <filename> =====` markers
- Update all 85 apps: edit `_NR-CORE/<file>.ts`, run Python regex script that finds the marker block + replaces it across all 101 core.ts files
- **Never edit `NR-<slug>/functions/_lib/core.ts` directly** — it gets overwritten

**Wrangler.toml CRITICAL convention:**
- Every `NR-<slug>/wrangler.toml` MUST include `[[d1_databases]]` (with shared UUID) + `[ai]` blocks
- Reason: `wrangler pages deploy` reads the toml and OVERWRITES the project's bindings. If toml omits these, env.DB and env.AI become undefined in production.
- Master grid wrangler.toml has `[ai]` (for /api/factory/og image gen)

**Pagination convention:**
- Every bulk-mutation endpoint accepts `?offset&limit` (max limit=40)
- Returns `summary.has_more` boolean
- Client loops `for (off=0; off<200; off+=PAGE) { ... if (!has_more) break; }`
- Reason: CF Workers Free tier 50-subrequest cap

**Frontend conventions:**
- Vanilla JS, no framework
- All shared CSS classes prefix `nr-`
- Toast feedback: `toast(msg, kind?)` where kind = 'good' | 'bad'
- Listen for `nr:generate` custom event for cross-app communication
- Onboarding tour fires once per `localStorage.nr_tour_seen`

---

## 17. CONSTRAINTS & GOTCHAS

| Gotcha | Fix |
|---|---|
| Wrangler `pages deploy` from OneDrive sometimes fails "Please check the file path" | Retry — transient |
| `npx wrangler@latest` downloads wrangler each call (~30s overhead) | Use globally-installed wrangler |
| Multiple `redeploy-sequential.sh` in parallel = file path errors | Run ONE at a time |
| CF Workers Free tier subrequest cap = 50 | Every bulk endpoint paginates to PAGE=30 |
| OneDrive scans home dirs and trips on Permission denied | Cosmetic, ignore |
| `git rev-parse HEAD` fails because no .git | Cosmetic |
| Wrangler `--remote` on `d1 execute` may hang on prompt | Use direct CF API: `POST /accounts/{id}/d1/database/{uuid}/query` |
| `wrangler pages deploy` STRIPS bindings not in wrangler.toml | Always include [[d1_databases]] + [ai] |
| API-set bindings only take effect on NEXT deployment | Always redeploy after binding changes |
| Cookies must be `Secure; SameSite=Lax` for cross-subdomain on .pages.dev | Already set |
| CF Pages API `per_page` doesn't accept all values | Stick to per_page=25 or 50 |
| flux-1-schnell returns slightly different image each call (no seed pinning) | Cache aggressively at edge |
| Wrangler OAuth token expires; deploys fail with "Invalid access token [code: 9109]" | Use `CLOUDFLARE_API_TOKEN=cfat_xxx wrangler pages deploy ...` to bypass OAuth |
| Pages Functions 30s CPU limit; long LLM generations time out | Cap CF AI to 2000 max_tokens; longer outputs need streaming or Anthropic |
| Channel detection in agent output parser falsely matched "x" inside "expert" | Word-boundary regex + sort keys by length desc |

---

## 18. HOW TO EXTEND — concrete recipes

### Add a new app to the portfolio
1. Create `NR-<slug>/` with `public/index.html`, `public/styles.css`, `wrangler.toml` (copy from existing — swap name+slug, KEEP [[d1_databases]] + [ai])
2. Add `functions/api/{generate,checkout,webhook,track}.ts` (copy patterns)
3. Run sync script to bundle `_NR-CORE/` into `functions/_lib/core.ts`
4. Inject `_NR-CORE/ui/open-beta-snippet.html` before `</body>`
5. Add slug to `functions/_lib/live-apps.ts`
6. Add entry to `apps.js` (`{slug, name, desc, price, tags, status:'live'}`)
7. Deploy: `cd NR-<slug> && wrangler pages deploy public --project-name=nr-<slug> --branch=main --commit-dirty=true`
8. Push secrets: `python scripts/push-system-secrets.py`
9. Re-deploy master grid

### Add a new master-grid endpoint
```typescript
import { requireMaster, MasterEnv } from "../../_lib/admin";
export const onRequestGet: PagesFunction<MasterEnv> = async ({ request, env }) => {
  const guard = await requireMaster(env, request); if (guard) return guard;
  return Response.json({ ok: true, ... });
};
type PagesFunction<E = any> = (ctx: { request: Request; env: E; params: Record<string,string>; waitUntil:(p:Promise<any>)=>void }) => Response | Promise<Response>;
```

### Add a new agent to the marketing team
1. In `functions/_lib/agents.ts`, add to `AGENTS` map: `{ name, role, system, max_tokens }`
2. In `functions/api/factory/agents/run.ts`, add the agent's input format to the trigger logic
3. In `factory.js → AGENT_DEFS`, add the agent metadata for the UI
4. Deploy

### Add a new D1 column or table
```python
import json, urllib.request
url = f'https://api.cloudflare.com/client/v4/accounts/{ACCT}/d1/database/{UUID}/query'
urllib.request.urlopen(urllib.request.Request(url,
    data=json.dumps({'sql':'<your SQL>'}).encode(),
    headers={'Authorization':f'Bearer {TOKEN}','Content-Type':'application/json'}, method='POST'))
```
Then update `_NR-CORE/schema.sql` for new-app initialization + this brief's data model section.

### Send anything via CARRIER (from any future system)
```typescript
import { carrierSend } from "../../_lib/carrier";
const result = await carrierSend(env, {
  channel: "email",          // or 'x' | 'linkedin' | 'instagram' | 'facebook' | 'sms'
  to: "you@example.com",
  subject: "Hello",
  body: "Plain text or markdown",
  ref: { kind: "my_module", id: 123 },
  tags: ["my_module"],
});
// result = { ok, message_id, backend, status, external_id?, error?, preview? }
```
- Dryrun mode: returns ok=true, logs to internal inbox
- Live mode: routes through Resend/MailChannels automatically

### Wire a real cron for AI Marketing Team or Scout
**Easiest:** cron-job.org → POST `https://nr-money-factory.pages.dev/api/factory/agents/cron` (or `/scout/cron`) with header `X-Cron-Secret: <agents_cron_secret from feature_flags>`. Runs daily.

**Native CF:** add to wrangler.toml `[triggers] crons = ["0 17 * * *"]` + create a scheduled handler that POSTs to the same endpoint.

---

## 19. STATE MACHINE (current build)

**85 apps existence:** all on CF (verified via `python scripts/audit-deployments.py`)
**85 apps secrets:**
- 85/85 have FACTORY_TOKEN, ADMIN_PASSWORD, ADMIN_SECRET (system secrets)
- 50/85 have ANTHROPIC_API_KEY + STRIPE_SECRET_KEY (user previously pushed)
- 35/85 still need user-provided ANTHROPIC + STRIPE (works without — router falls back to free CF AI)

**85 apps bindings:** 85/85 have D1 + AI bindings (verified via manifest)
**Operators:** 1 approved (`@smoketest`, bronze, 0 claims)
**Founders:** 1 captured (smoketest@nextrealm.io)
**Toolkit listings:** 24 grandfathered active + 1 smoketest application
**Launch packages generated:** 2 (hookforge, tradejournal)
**Agent runs:** several (Copywriter for hookforge/tradejournal/roastmywebsite)
**Scout ideas discovered:** 0 in DB (smoke-test verified pipeline; user hasn't run a real pass yet)
**Prospects discovered:** 4 (real Resend.com founders from smoke test)
**CARRIER messages:** 1 (smoke-test send, dryrun-logged)

---

## 20. BRAND VOICE (Next Realm aesthetic)

**Visual:**
- Dark UI (#06080d background, #0a0c12 cards)
- Neon green accent #00FF94 (`var(--nr-accent)`)
- Purple secondary #7C4DFF (`var(--nr-accent-2)`)
- Gold accent #FBBF24 (toolkit spotlight, founder rank)
- Warning amber #FFB020, danger #FF3366
- Fonts: Inter (UI), JetBrains Mono (code/labels), Space Grotesk (cinematic hero)
- Scanline overlay + animated gradient background + grid overlay
- Per-card category tinting (creator=coral, finance=mint, social=purple, etc — see `categoryClass()` in factory.js)
- AI-generated hero images per app (flux-1-schnell, prompts auto-tuned per category)

**Tone (in all LLM-generated content):**
- "SSS+ grade" — top-tier, no compromises
- Cinematic, mission-control feel
- Founder-to-founder peer voice in outreach
- No clichés ("synergy," "leverage" as a verb, "in today's fast-paced world")
- Numbers in every claim
- Single ask per email/message

---

## 21. QUICK REFERENCE

**Test the master grid:** https://nr-money-factory.pages.dev (login `moneyfactory-00272970`)
**Test an app:** https://nr-roastmywebsite.pages.dev → paste any URL → click Roast
**Test the federation:**
```bash
curl https://nr-money-factory.pages.dev/.well-known/factory.json
curl https://nr-money-factory.pages.dev/api/federation/catalog
curl https://nr-money-factory.pages.dev/api/federation/stats
```
**Test the AI marketing team:** Admin → 🤖 AI Marketing Team → pick agent → run
**Test the Scout:** Admin → 💡 Idea Board · Scout → 🔍 Dry-run preview → ▶ Run scout
**Test the Prospector:** Admin → 📧 Prospect Pipeline → discover URL → write sequence
**Test CARRIER:** Admin → 📡 CARRIER → smoke-test → see in internal inbox

**Regenerate canonical state:** `python scripts/audit-deployments.py` → `deployments-manifest.json`
**Bulk redeploy:** `bash scripts/redeploy-fast.sh` (~15 min for 85 apps)
**Bulk push secrets:** `python scripts/push-system-secrets.py`
**Bulk bind D1:** `python scripts/bind-d1.py`
**Bulk bind AI:** `python scripts/bind-ai.py`

---

## 22. EXTENSION SAFETY RULES (mandatory for any AI building on this)

1. **Never modify `wrangler.toml` files to remove `[[d1_databases]]` or `[ai]` blocks** — production bindings will be wiped
2. **Never expose secrets in federation endpoints** — every public response must be sanitized per Section 15
3. **Always paginate bulk endpoints** to PAGE=30 — CF Workers Free 50-subreq cap
4. **Never edit `NR-<slug>/functions/_lib/core.ts` directly** — edit `_NR-CORE/<file>.ts` and propagate via script
5. **Never break the federation v1 stable shape** — additions OK, removals/renames need a new major version
6. **Never default-export Pages Functions** — always named exports `onRequest{Get,Post,etc}`
7. **Always include the PagesFunction type alias at the bottom of every function file**
8. **Brand Resolver (Phase V)** must be append-only on system prompts, never replace — protects parent brand voice
9. **Operator suspension** must auto-pause all their active claims (already implemented in `/api/factory/operators` DELETE)
10. **AI router** is single-source-of-truth for LLM choice — never call Anthropic/CF AI directly from app code; always go through `claude(env, ...)`
11. **CARRIER is single-source-of-truth for sending** — never call Resend/MailChannels directly from app code; always go through `carrierSend(env, ...)`
12. **Scout/Prospector outbound** must respect suppression list + GDPR geo-skip + per-domain cap — checked in CARRIER pipeline
13. **CAN-SPAM compliance** is non-negotiable — physical address + unsubscribe link in every email (auto-injected by CARRIER)
14. **Cron secrets** are NOT in env vars — they're in `feature_flags` so they can be rotated without redeploy
15. **Tier caps** (operator claims, toolkit listings, scout daily, dev queue nightly, send daily) are in `feature_flags` — modifiable via D1 directly

---

**END OF EXTENSION BRIEF v2.** Hand this entire document to any AI and they have full context to extend, integrate with, or build on top of the Money Factory.
