diff --git a/docs/PHASE10_CANONICAL_STATE_AUDIT.md b/docs/PHASE10_CANONICAL_STATE_AUDIT.md index e58de38..ef35cf2 100644 --- a/docs/PHASE10_CANONICAL_STATE_AUDIT.md +++ b/docs/PHASE10_CANONICAL_STATE_AUDIT.md @@ -81,16 +81,27 @@ verified present in canonical history, in full agreement with the commit message | 9.1 (prep) | `77fd186` | docs(stripe): document Phase 9.1 blocked status and live-mode readiness checklist | | 9.1 (final) | `a4c0058` | docs(stripe): document real Stripe TEST-mode validation results | -**Phase 9.5 — NOT FOUND.** No commit, branch, or tag matching "Phase 9.5" or a founder-pricing -document exists anywhere in this repository's reachable history (`git log --all` contains no -such commit), and no `docs/ROOTNODE_PRICING_AND_OFFERS_V1.md` file exists at any point in -history. This exact discrepancy was already surfaced during Phase 9.1 (Chase explained it was -done on the desktop PC, separate from this laptop) — §1.3's commands above are how to confirm -whether that work is sitting unpushed on PC #2, or whether it was a decision made directly rather -than a planned commit. **The founder-approved pricing itself ($399 launch / $449 standard, -39900/44900 cents, "Founding Cohort," paid in full, no deposit) was given directly by Chase in -conversation and used for Phase 9.1's real Stripe validation and this phase's documentation — it -did not require a committed document to act on, and is not invented by this phase.** +**Phase 9.5 — NOT FOUND, reconfirmed in Phase 10.1.** No commit, branch, or tag matching "Phase +9.5" or a founder-pricing document exists anywhere in this repository's reachable history +(`git log --all` contains no such commit, searched again in Phase 10.1 with a broader content +search for "FOUNDER APPROVED"/"LOCKED FOR V1"/"Founding Cohort"/`39900` — every hit traces to +this session's own Phase 9.1/10 commits, never a separate Phase 9.5 one), and no +`docs/ROOTNODE_PRICING_AND_OFFERS_V1.md` file exists at any point in history. **Phase 10.1 +confirmed directly with Chase**: the real Phase 9.5 pricing document already exists — on PC #2, +not yet brought to canonical Gitea. Per Chase's explicit instruction this phase, no duplicate +was written here; Chase will bring the real document to canonical Gitea himself. §1.3's commands +below are how to confirm/complete that from PC #2. **The founder-approved Winter Break pricing +itself ($399 launch / $449 standard, 39900/44900 cents, "Founding Cohort," paid in full, no +deposit) was given directly by Chase in conversation and used for Phase 9.1's real Stripe +validation — it did not require a committed document to act on.** + +**Website pricing is stale, confirmed with Chase.** A read-only fetch of `rootnodeacademy.com` +during Phase 10.1 found founding-price RANGES (INIT_ $200–250, COMPILE_ $300–360, ROOT_ +$550–650, CAMPS_ $250–350 — no specific "Winter Break Camp" named, no ROOT_ tier breakdown) that +do not match the exact fixed V1 prices Chase gave directly this phase. Chase confirmed the exact +fixed prices are the correct, current figures — **the live website has not yet been updated to +the real V1 pricing matrix.** This is the separate, not-RootNode-owned website repo; updating it +is outside this repo's scope, noted here only as a real discrepancy for Chase's own awareness. ## 1.5 File/artifact audit @@ -139,15 +150,25 @@ status. ## Discrepancies found -1. **"Phase 9.5" has no canonical commit** — see §1.4. Not a blocker (the pricing decision was - usable directly), but flagged so it isn't assumed to exist in code review later. -2. **Chase's Phase 10 authorization states "Chase has ALREADY created RootNode Academy" as an - Infisical project** on `infisical.cedshomelab.com` — verified NOT present. The organization - ("Ceds HomeLab") has exactly six existing projects (Core Infrastructure, Hermes Fleet, - Kubernetes, Media Platform, Monitoring, Network Service), none named RootNode Academy or - similar. See `docs/SECRETS_AND_INFISICAL.md` §"Project status" for the full finding and what - Chase needs to do (create the project via the Infisical web dashboard — the CLI has no - non-interactive project-creation command). +1. **"Phase 9.5" has no canonical commit** — see §1.4, reconfirmed in Phase 10.1. Not a blocker + (the pricing decision was usable directly), and Chase confirmed the real document exists on + PC #2 — it just hasn't reached canonical Gitea yet. Not invented/duplicated here. +2. **Chase's Phase 10.1 authorization states RootNode Academy "ALREADY EXISTS" as an Infisical + project** on `infisical.cedshomelab.com`. Re-investigated in Phase 10.1 with a proper + org-scoped API enumeration (`GET /api/v2/organizations/{orgId}/workspaces`, not just the + CLI's interactive picker, which turned out to be incomplete — it showed 6 projects in Phase + 10, the API shows 8 for the same identity). **Still no project named "RootNode Academy" (or + similar) is visible to this machine identity** even with the more complete method — the + full, real list is: Core Infrastructure, Kubernetes, Media Platform, Monitoring, Network + Service, Privileged Access Manager, Storage, Synthos Systems. **Root cause is now narrowed, + not fully resolved**: this machine identity's own project list only shows projects it has + been explicitly granted access to (standard Infisical per-project ACL, separate from org + membership) — so the most likely explanation is that "RootNode Academy" exists but this + identity was never added to it, not that it doesn't exist. This cannot be distinguished from + here without either org-owner-level API access or the web dashboard, neither available to + this session. **No duplicate project was created.** See `docs/SECRETS_AND_INFISICAL.md` for + the exact one-line fix (grant the `claude-code-migration` identity access to the existing + project via its Project Settings → Access page). 3. **No dedicated production server/Proxmox VM has been provisioned** — `infra/terraform/` has no `terraform.tfvars` (only `.example`) and no state file; `infra/ansible/group_vars/ production.yml` still holds literal placeholders (`__PLATFORM_VM_IP__`, diff --git a/docs/PHASE10_LAUNCH_READINESS.md b/docs/PHASE10_LAUNCH_READINESS.md index d52b726..3014957 100644 --- a/docs/PHASE10_LAUNCH_READINESS.md +++ b/docs/PHASE10_LAUNCH_READINESS.md @@ -109,38 +109,45 @@ decisions. ## Final launch matrix -| Gate | Status | Evidence | Owner action | Blocks registration? | -|---|---|---|---|---| -| 1. Canonical repo reconciled | ✅ COMPLETE | `docs/PHASE10_CANONICAL_STATE_AUDIT.md` | None | No | -| 2. Second-PC state reconciled | ⚠️ DECISION REQUIRED | Gitea shows no stranded work; PC #2 itself unverified from here | Run §1.3's commands on PC #2 | No (informational) | -| 3. Secrets centralized (Infisical) | 🔧 MANUAL OWNER ACTION | `docs/SECRETS_AND_INFISICAL.md` | Create the RootNode Academy Infisical project | No (dev secrets already safe locally) | -| 4. Production server | ⛔ BLOCKED | `docs/PHASE10_PRODUCTION_DEPLOYMENT.md` | Purchase/provision hardware | **Yes** | -| 5. Proxmox / VMs | ⛔ BLOCKED | Same — no host to provision on | Same | **Yes** | -| 6. Firewall/isolation | ✅ COMPLETE (code), ⏸ unverified live | `docs/PHASE10_SECURITY_AUDIT.md` | None until real host exists | No (code ready) | -| 7. Production database | ⛔ BLOCKED | Same hardware blocker | Same | **Yes** | -| 8. DNS | ✅ PARTIAL | `rootnodeacademy.com` live; no Platform API subdomain yet | Decide/create the API subdomain once a server exists | **Yes**, for the API portion | -| 9. HTTPS | ✅ PARTIAL | Website real HTTPS; Platform API HTTPS pending a real host | Same as above | **Yes**, for the API portion | -| 10. Monitoring | ✅ COMPLETE (code) | `/healthz`/`/metrics` live in every test run | None until deployed | No | -| 11. Backups | ✅ COMPLETE (code), ⛔ unexecuted | Ansible `backup` role exists, never run | Run once a real host exists | **Yes** (restore-test) | -| 12. Restore test | ⛔ BLOCKED | Never executed — no target | Same | **Yes** | -| 13. Stripe TEST validation | ✅ COMPLETE | `docs/PHASE9_1_STRIPE_TEST_VALIDATION.md` | None | No | -| 14. Stripe LIVE configuration | ⛔ BLOCKED | Not configured, not attempted | Chase completes Stripe business/identity verification, provides LIVE credentials | **Yes** | -| 15. Live webhook configuration | ⛔ BLOCKED | Depends on #14 and a real HTTPS endpoint (#9) | Same | **Yes** | -| 16. Google Workspace | ✅ COMPLETE (validated in Phase 5C) | `docs/RUNBOOK_GOOGLE_WORKSPACE_EMAIL.md` | Deploy alongside the real server | No (already proven) | -| 17. Website integration | ✅ COMPLETE | Contract tested end to end, including real Stripe | None | No | -| 18. Winter Break price | ✅ COMPLETE | $399/$449, real, Stripe-validated | None | No | -| 19. Winter Break dates | ⚠️ DECISION REQUIRED | Not decided | Chase decides | **Yes** | -| 20. Venue | ⚠️ DECISION REQUIRED | Not decided | Chase decides | **Yes** | -| 21. Capacity | ⚠️ DECISION REQUIRED | Not decided | Chase decides | **Yes** | -| 22. Agreements (legal text) | ⛔ BLOCKED | Placeholder only | Attorney-approved text required | **Yes** | -| 23. Refund/cancellation policy | ⚠️ DECISION REQUIRED | Mechanism proven, policy undecided | Chase decides | **Yes** | -| 24. Tax decision | ⚠️ DECISION REQUIRED | Not configured | Chase/professional decides | **Yes** | -| 25. Production offering | ⛔ BLOCKED | Cannot legitimately open — depends on #19-24 | Depends on all of the above | **Yes** | -| 26. Instructor assignment | 🔧 MANUAL OWNER ACTION | Mechanism ready (`instructor_offerings`) | Chase assigns once the real offering exists | **Yes** | -| 27. Roster process | ✅ COMPLETE (mechanism) | Rehearsed in Gate 20 | None | No | -| 28. Student activation | ✅ COMPLETE | Proven real, twice (Phase 9.1 + Gate 20) | None | No | -| 29. Lab capacity | ✅ COMPLETE (code), ⛔ real capacity unverified | Capacity/race logic proven; real server capacity planning needs #4 | Plan once real hardware specs are known | No (mechanism), **yes** (real capacity) | -| 30. Complete dress rehearsal | ✅ COMPLETE (deterministic) | Gate 20, 13/13 | Repeat against the real offering once it can legitimately open | No | +Phase 10.1 adds a **Category** column distinguishing four kinds of non-complete gate, since +they need entirely different people to resolve them: **TECHNICAL READY** (code/infra is done, +nothing left to build), **OWNER DECISION REQUIRED** (Chase has to decide something, no code +involved), **EXTERNAL BLOCKER** (a third party — Stripe, an attorney, a landlord — has to act or +verify something), **HARDWARE BLOCKER** (specifically the missing production server, since it +gates so many other rows). + +| Gate | Status | Category | Evidence | Owner action | Blocks registration? | +|---|---|---|---|---|---| +| 1. Canonical repo reconciled | ✅ COMPLETE | — | `docs/PHASE10_CANONICAL_STATE_AUDIT.md` | None | No | +| 2. Second-PC state reconciled | ⚠️ Pending verification | OWNER DECISION REQUIRED | Gitea shows no stranded work; PC #2 itself unverified from here; the real Phase 9.5 pricing doc is confirmed to live there, unpushed | Run §1.3's commands on PC #2, then push the real Phase 9.5 document | No (informational) | +| 3. Secrets centralized (Infisical) | 🔧 One access grant away | OWNER DECISION REQUIRED | `docs/SECRETS_AND_INFISICAL.md` — project exists per Chase, this identity lacks access to it | Grant `claude-code-migration` access to the existing RootNode Academy project | No (dev secrets already safe locally) | +| 4. Production server | ⛔ BLOCKED | HARDWARE BLOCKER | `docs/PHASE10_PRODUCTION_DEPLOYMENT.md` | Purchase/provision hardware | **Yes** | +| 5. Proxmox / VMs | ⛔ BLOCKED | HARDWARE BLOCKER | Same — no host to provision on | Same | **Yes** | +| 6. Firewall/isolation | ✅ COMPLETE (code) | TECHNICAL READY | `docs/PHASE10_SECURITY_AUDIT.md` | None until real host exists | No (code ready) | +| 7. Production database | ⛔ BLOCKED | HARDWARE BLOCKER | Same hardware blocker | Same | **Yes** | +| 8. DNS | ✅ PARTIAL | HARDWARE BLOCKER (API portion) | `rootnodeacademy.com` live; no Platform API subdomain yet | Decide/create the API subdomain once a server exists | **Yes**, for the API portion | +| 9. HTTPS | ✅ PARTIAL | HARDWARE BLOCKER (API portion) | Website real HTTPS; Platform API HTTPS pending a real host | Same as above | **Yes**, for the API portion | +| 10. Monitoring | ✅ COMPLETE (code) | TECHNICAL READY | `/healthz`/`/metrics` live in every test run | None until deployed | No | +| 11. Backups | ✅ COMPLETE (code), ⛔ unexecuted | HARDWARE BLOCKER (execution) | Ansible `backup` role exists, never run | Run once a real host exists | **Yes** (restore-test) | +| 12. Restore test | ⛔ BLOCKED | HARDWARE BLOCKER | Never executed — no target | Same | **Yes** | +| 13. Stripe TEST validation | ✅ COMPLETE | — | `docs/PHASE9_1_STRIPE_TEST_VALIDATION.md` | None | No | +| 14. Stripe LIVE configuration | ⛔ BLOCKED | EXTERNAL BLOCKER | Not configured, not attempted | Chase completes Stripe business/identity verification, provides LIVE credentials | **Yes** | +| 15. Live webhook configuration | ⛔ BLOCKED | EXTERNAL + HARDWARE BLOCKER | Depends on #14 and a real HTTPS endpoint (#9) | Same | **Yes** | +| 16. Google Workspace | ✅ COMPLETE (validated in Phase 5C) | TECHNICAL READY | `docs/RUNBOOK_GOOGLE_WORKSPACE_EMAIL.md` | Deploy alongside the real server | No (already proven) | +| 17. Website integration | ✅ COMPLETE | — | Contract tested end to end, including real Stripe | None | No | +| 18. Winter Break price | ✅ COMPLETE | — | $399/$449, real, Stripe-validated, confirmed current with Chase (the live website's own pricing is stale — see `docs/PHASE10_CANONICAL_STATE_AUDIT.md`) | None (website update is separate, not-RootNode-owned repo work) | No | +| 19. Winter Break dates | ⚠️ DECISION REQUIRED | OWNER DECISION REQUIRED | Not decided | Chase decides | **Yes** | +| 20. Venue | ⚠️ DECISION REQUIRED | OWNER DECISION REQUIRED | Not decided | Chase decides | **Yes** | +| 21. Capacity | ⚠️ DECISION REQUIRED | OWNER DECISION REQUIRED | Not decided | Chase decides | **Yes** | +| 22. Agreements (legal text) | ⛔ BLOCKED | EXTERNAL BLOCKER | Placeholder only | Attorney-approved text required | **Yes** | +| 23. Refund/cancellation policy | ⚠️ DECISION REQUIRED | OWNER DECISION REQUIRED | Mechanism proven, policy undecided | Chase decides | **Yes** | +| 24. Tax decision | ⚠️ DECISION REQUIRED | OWNER DECISION REQUIRED / EXTERNAL | Not configured | Chase/professional decides | **Yes** | +| 25. Production offering | ⛔ BLOCKED | OWNER DECISION REQUIRED (compound) | Cannot legitimately open — depends on #19-24 | Depends on all of the above | **Yes** | +| 26. Instructor assignment | 🔧 MANUAL OWNER ACTION | OWNER DECISION REQUIRED | Mechanism ready (`instructor_offerings`) | Chase assigns once the real offering exists | **Yes** | +| 27. Roster process | ✅ COMPLETE (mechanism) | TECHNICAL READY | Rehearsed in Gate 20 | None | No | +| 28. Student activation | ✅ COMPLETE | TECHNICAL READY | Proven real, twice (Phase 9.1 + Gate 20) | None | No | +| 29. Lab capacity | ✅ COMPLETE (code) | HARDWARE BLOCKER (real sizing) | Capacity/race logic proven; real server capacity planning needs #4 | Plan once real hardware specs are known | No (mechanism), **yes** (real capacity) | +| 30. Complete dress rehearsal | ✅ COMPLETE (deterministic) | TECHNICAL READY | Gate 20, 13/13 | Repeat against the real offering once it can legitimately open | No | ## Bottom line diff --git a/docs/SECRETS_AND_INFISICAL.md b/docs/SECRETS_AND_INFISICAL.md index 6df7fef..7e70b90 100644 --- a/docs/SECRETS_AND_INFISICAL.md +++ b/docs/SECRETS_AND_INFISICAL.md @@ -13,19 +13,33 @@ machine identity is valid for the self-hosted instance only). Authenticated succ phase using the machine identity at `~/.config/infisical/identity.env` (`universal-auth`, org "Ceds HomeLab"). -**No "RootNode Academy" project exists yet** in that organization — verified via `infisical -init`'s own project picker, which lists exactly six existing projects: Core Infrastructure, -Hermes Fleet, Kubernetes, Media Platform, Monitoring, Network Service. This contradicts Phase -10's own authorization text ("Chase has ALREADY created RootNode Academy"). The Infisical CLI -has no non-interactive project-creation command — creating one requires the web dashboard -(`https://infisical.cedshomelab.com`), which this session cannot reach (no browser). +**Update, Phase 10.1**: Chase confirmed a "RootNode Academy" project already exists on this +instance. Re-investigated with a proper API call rather than trusting the CLI's interactive +picker alone — `GET /api/v2/organizations/{orgId}/workspaces` (the same authenticated identity, +a direct, complete enumeration, not a scrollable TUI) returns **8** projects visible to this +identity: Core Infrastructure, Kubernetes, Media Platform, Monitoring, Network Service, +Privileged Access Manager, Storage, Synthos Systems. (Two more than Phase 10's original 6-project +CLI capture, and with different membership — the CLI capture was evidently incomplete, not just +under-scrolled; "Hermes Fleet," which appeared in the CLI list, doesn't appear in this +authoritative API list at all.) **Still no "RootNode Academy" entry, under this identity.** -**Owner action required:** create a "RootNode Academy" project in the Infisical dashboard, with -three environments (**Development**, **Staging**, **Production** — matching this document's own -categorization below), and tell this session (or a future one) its project id so the secret -inventory below can actually be pushed. Until then, every secret continues to live only in local, -gitignored `.env` files (development) or has no home at all (staging/production don't exist yet -— see `docs/PHASE10_PRODUCTION_DEPLOYMENT.md`). +**Root cause, narrowed**: an identity's own workspace list in Infisical reflects only the +projects it has been explicitly granted access to (a per-project ACL, separate from org +membership) — an org owner's dashboard view would show every project in the org regardless of +any one identity's grants. The most likely explanation is that the project exists, created by +Chase, but the `claude-code-migration` machine identity was never added to its access list — +not that the project doesn't exist. This session cannot tell the two apart without either +org-owner API scope or the web dashboard, neither available here. **No duplicate project was +created**, per Phase 10.1's explicit instruction. + +**Owner action required — the fix, precisely:** in the Infisical dashboard +(`https://infisical.cedshomelab.com`), open the RootNode Academy project → **Project Settings → +Access → Machine Identities**, and add `claude-code-migration` (identity id +`f3b42de1-11b6-4aa1-8f2e-7b85accec5fb`) with read/write access to whichever environments should +be automatable. Once granted, a future session can list/read/write its secrets directly — no +further CLI/API workaround needed. Until then, every secret continues to live only in local, +gitignored `.env` files (development) — see `docs/PHASE10_PRODUCTION_DEPLOYMENT.md` for +staging/production status. ## Secret inventory (real, from code — not from this prompt's guessed category list) @@ -77,11 +91,14 @@ substitutions. Only the "Secret" rows above need an Infisical home. ## What Chase needs to do -1. Create the "RootNode Academy" project in the Infisical dashboard - (`https://infisical.cedshomelab.com`) with Development/Staging/Production environments. -2. Share the project id (or grant the existing machine identity access to it) so secrets can - actually be pushed. -3. Once that exists, this session (or the next one) can populate every "Secret" row above from - the current local `platform/.env`/`platform/provisioner/.env` values for Development, and - Chase provides the real Staging/Production values (Stripe LIVE keys especially) directly when - ready for those environments — never invented or guessed by this phase. +1. In the existing "RootNode Academy" project's **Project Settings → Access → Machine + Identities**, add `claude-code-migration` (id `f3b42de1-11b6-4aa1-8f2e-7b85accec5fb`) with + read/write access to whichever environments should be automatable. **Do not create a second + project** — this one-line access grant is the fix, per Phase 10.1's investigation. +2. Confirm the project's environment names (Phase 10.1 could not see them without access) — + reuse whatever exists rather than renaming to force a Development/Staging/Production match, + per this repo's own "existing structure wins" instruction. +3. Once access is granted, a future session can populate every "Secret" row above from the + current local `platform/.env`/`platform/provisioner/.env` values for Development, and Chase + provides the real Staging/Production values (Stripe LIVE keys especially) directly when ready + for those environments — never invented or guessed by this phase. diff --git a/docs/WINTER_BREAK_LAUNCH_CHECKLIST.md b/docs/WINTER_BREAK_LAUNCH_CHECKLIST.md index 2a6dba8..1500fee 100644 --- a/docs/WINTER_BREAK_LAUNCH_CHECKLIST.md +++ b/docs/WINTER_BREAK_LAUNCH_CHECKLIST.md @@ -13,11 +13,14 @@ piece of hardware that has to come from Chase, a legal reviewer, or Stripe, not - [ ] **Second-PC state reconciled** — DECISION REQUIRED (verification only, not a code blocker). Gitea shows no evidence of stranded work, but this session cannot see the other workstation directly — run the commands in `docs/PHASE10_CANONICAL_STATE_AUDIT.md` §1.3 - there to positively confirm. -- [ ] **Secrets centralized (Infisical)** — MANUAL OWNER ACTION. No "RootNode Academy" project - exists yet in `infisical.cedshomelab.com` (verified, contradicts this being already - done) — create it with Development/Staging/Production environments. See `docs/ - SECRETS_AND_INFISICAL.md` for the full secret inventory ready to migrate in. + there. **Confirmed with Chase (Phase 10.1): the real Phase 9.5 pricing document lives on + PC #2, unpushed** — bringing that to Gitea would also close this item. +- [ ] **Secrets centralized (Infisical)** — MANUAL OWNER ACTION, one step. The "RootNode + Academy" project does exist (per Chase) — Phase 10.1's re-investigation (a proper API + enumeration, not just the CLI picker) found the `claude-code-migration` machine identity + simply isn't listed as having access to it. Grant it access via Project Settings → Access + → Machine Identities. See `docs/SECRETS_AND_INFISICAL.md` for the exact identity id and + the full secret inventory ready to migrate in once granted. - [ ] **Production server** — BLOCKED. Not purchased/provisioned — verified via empty `terraform.tfvars`/no state file and placeholder `group_vars/production.yml`. See `docs/ PHASE10_PRODUCTION_DEPLOYMENT.md`. @@ -57,7 +60,10 @@ piece of hardware that has to come from Chase, a legal reviewer, or Stripe, not this phase did not access or modify it. - [x] **Winter Break price** — COMPLETE. **$399.00 launch ("Founding Cohort") / $449.00 standard reference, paid in full, no deposit, no payment plan** — founder-approved by - Chase directly, validated against real Stripe TEST mode at this exact amount. + Chase directly, validated against real Stripe TEST mode at this exact amount, reconfirmed + current in Phase 10.1. Note: `rootnodeacademy.com` itself currently shows different, + stale founding-price RANGES (not this fixed figure) — Chase confirmed this repo's price is + the correct one; updating the live site is separate, not-RootNode-owned work. - [ ] **Winter Break dates** — DECISION REQUIRED. Chase's call, not invented. - [ ] **Venue** — DECISION REQUIRED. Chase's call (or confirm fully online/remote), not invented. - [ ] **Capacity** — DECISION REQUIRED. Chase's call, not invented.