# Decision Log — Keystone Migration + AI Layer + GTM (2026-05-28/29)

See [SPEC.md](SPEC.md). Decisions below were made with Cris in-session.

## GTM
- **DL1 — One free + one paid.** Storefront sells **Community (free) + Pro (paid)** only. **Defer Enterprise + MSSP**: flag off, strip from storefront/pricing, retain code in-tree.
  *Rationale:* the constraint is the first paying customer; MSSP is a different business (reseller motion, multi-tenant isolation risk); narrows audit/attack surface. *Alt rejected:* keep all four tiers (dilutes message, widens surface).

## AI — both products
- **DL2 — AI is a Pro feature.** Community = built-in **template-based analysis** (no LLM). Pro+ unlock AI. *Rationale:* clean upsell; deletes the per-day quota mechanism (and a bug class).
- **DL3 — Meter only AI that hits DonjonSec's wallet.** DonjonSec-provided AI = metered/tier-gated; customer **BYO key / local model = ungated**. *Rationale:* we don't pay for their inference; metering their own resource is pointless and (client-side) unenforceable. One rule unifies both products.
- **DL4 — Universal local compatibility (scanner).** Support native Ollama + any OpenAI-compatible endpoint (`custom`) + a configurable **`generic`** HTTP adapter (request_template + response_path) as the escape hatch. *Rationale:* "any local model" must be a real promise; OpenAI-compat covers most, generic covers the long tail.
- **DL5 — Air-gap guard on the AI path.** `DONJON_OFFLINE` hard-blocks cloud backends and requires local/loopback endpoints (DNS-free check). *Rationale:* the audit found the AI path unguarded; zero-egress must be provable, and a DNS lookup to "verify" a host is itself egress.
- **DL6 — PolicyPro default = Anthropic Claude API (zero-retention) + per-tenant BYO.** *Rationale:* a sellable SaaS shouldn't have its AI die when the home GPU box blinks; BYO keeps regulated tenants' data with their approved vendor (DonjonSec out of the data path). Ollama default was broken (model not installed → 500s).

## Keystone / BCDR (detail in SPEC §5)
- **DL7 — Invert the topology.** OCI A1 (Always Free) becomes the always-on public keystone (Forgejo on Postgres behind Cloudflare Access, def-cadence, release packaging, Object Storage distribution); R630 becomes a flaky backup + GPU/factory brain that may be offline. A1 depends on nothing at home.
- **DL8 — No PAYG.** The definition-update cadence's activity doubles as the Always-Free keep-alive (no idle reclamation), so PAYG stays deferred until a live demo is actually requested.
- **DL9 — Signing key never on the internet-facing A1; CT106 stays hot as DR mirror.**
- **DL10 — Phase 0 truth reconciliation precedes the migration.** Commit each deployed tree to Forgejo (secret-scanned) before treating Forgejo as truth. DONE: PolicyPro `34c1c90`, scanner `db6416a`.

## Execution (this session)
- **DL11 — Swarm via parallel agents.** Separate-repo agents run free; same-repo (scanner) agents use **git worktree isolation**; no agent pushes — orchestrator integrates. The cost-monitor hook was overridden in each agent prompt (carrying Cris's standing "disregard cost" directive) after it caused agents to abort mid-task.
- **DL12 — PolicyPro AI shipped as feature branch `policypro-ai`, NOT main.** Main-merge + deploy awaits a live Claude integration test (real key + deployed stack). *Rationale:* unit-verified ≠ functionally verified against a real target.
- **DL13 — Marketing changes committed locally, NOT pushed.** A push auto-deploys the live site; held for Cris's explicit go + resolution of the 18-vs-19 scanner-count question.
- **DL14 — Trial-integrity P0 kept out of the swarm.** Key-sensitive (signs trial licenses with the existing private key); done deliberately by the orchestrator, never regenerating keys.

## Open items (need Cris)
- Marketing deploy (auto-deploys on push) + scanner count 18 vs 19 (resolve against the scanner registry).
- PolicyPro main-merge gating: live Claude integration test setup.
- PolicyPro `TenantAIConfig.api_key` stored plaintext → recommend Fernet/pgcrypto column encryption (security follow-up).
- PolicyPro SaaS runtime still on R630 (uptime ≠ survivable); near-term container-portable + tested failover (decision pending).
