mirror of
https://github.com/dredx/prole.git
synced 2026-09-24 19:54:32 +00:00
Bringing the long-running session-feature branch back into main in one deliberate sweep. The branch carried the cluster work that's been live for weeks (cross-cluster CNPG metrics, Grafana w/ Google OAuth, supabase oauth2-proxy, cluster recovery, pg.0.knoe.dev + per-engineer onboarding, GCS-backed CNPG backups via Workload Identity, the env-contamination guard, the Junie brief queue, the cnpg-grafana CSRF + memory-request fixes from today), while main accumulated Junie's parallel knoe-auth Phase 2 OIDC work (full provider surface: discovery, authorize, token, userinfo, JWKS, RS256 signing, code exchange, session services). Key decision: the two branches did COMPETING rebrands off the same starting point (5ba9b63, 2026-04-27): - claude branch (commit b355855, earlier): org.prole.authority.* → dev.knoe.auth.* (artifact renamed to knoe-auth.jar) - main (commit9daa94b, recent): org.prole.authority.* → dev.knoe.authority.* (kept "authority" artifact name) dev.knoe.auth wins: cluster runs from this name, the Maven artifact is already knoe-auth.jar, and the broader rename is the documented namespace direction (per ~/.claude/projects/-Users-chrisfu-dev-knoe-db/ memory/MEMORY.md). All of main's recent Phase 2 OIDC content was ported from authority/src/.../dev/knoe/authority/ into authority/src/.../dev/knoe/auth/ with package declarations rewritten. == File-level resolution summary == Textual conflicts (4): authority/pom.xml - Took our artifactId="auth" - Took our branch's removal of spring-security-kerberos-client (verified: Junie's Phase 2 OIDC code does not import it; the dep was already-dead config) docs/pipeline-phases.md - Took our branch's "Phase 1 not started" status. Main had a misplaced "✅ Complete" with a knoe-auth-Phase-1 commit ref in the autobuild Phase 1 section — different domain. docs/plans/knoe-auth-round-1.md - Took our branch's dev.knoe.auth file table (vs main's dev.knoe.authority listing). Pure rename mismatch. supabase/helm/knoe-supabase/templates/kong/config.yaml - Took our branch's onboard route + plain dashboard wiring. Main had an oauth2proxy.enabled toggle that put oauth2-proxy as a Kong upstream — but the deployed architecture (commit 25f1b2e) has oauth2-proxy in FRONT of Kong, not behind. Main's wrapper reflected an architecture that was never deployed. - Took our branch's removal of basic-auth from dashboard route (queue #15 brief still tracks the matching values.yaml / kong/deployment.yaml cleanup). Java tree reconciliation (44 file-pairs): 20 dual-path source files + 2 dual-path tests Body-identical between main's authority/ and our branch's auth/ after stripping package decls — main's commit9daa94bwas a pure rebrand. Took our branch's auth/ version for all 22. 8 main-only source files (Phase 2 OIDC), ported into auth/: web/JwksController.java web/OidcAuthorizeController.java web/OidcDiscoveryController.java web/OidcTokenController.java web/OidcUserInfoController.java session/OidcCodeService.java session/OidcTokenService.java session/SessionService.java 12 main-only test files, ported into auth/: HealthControllerTest.java enroll/EnrollValueTypesTest.java enroll/EnrollmentControllerTest.java enroll/TotpServiceTest.java kerberos/KadminClientTest.java kerberos/KerberosSpnegoResultTest.java web/LoginControllerTest.java admin/AdminControllerTest.java user/PrincipalNormalizerTest.java regression/IdentityRegressionTest.java session/OidcCodeServiceTest.java session/SessionServiceTest.java Port mechanics: read main:authority/...<file> via git show, then sed rewrite `package dev.knoe.authority` → `package dev.knoe.auth` and `import dev.knoe.authority` → `import dev.knoe.auth`. Body content unchanged. authority/src/main/java/dev/knoe/authority/ — DELETED (duplicate) authority/src/test/java/dev/knoe/authority/ — DELETED (duplicate) == Verification == - grep -rln '<<<<<<<' across .java/.md/.yaml/.yml/.sh/.xml/.tpl: clean - find authority/src -path '*/dev/knoe/authority*': empty (subtree gone) - grep 'package dev.knoe.authority' across repo: clean - bash -n install.sh deploy.sh etc/preflight_kubecontext.sh: clean - git ls-files -u | wc -l: 0 unmerged paths - helm lint supabase/helm/knoe-supabase: pre-existing failure on studioIngress.enabled undefined in values.yaml (introduced by Junie on main; unrelated to this merge — flagging as follow-up). == Followups (carried into TODO ranked queue or noted here) == - helm lint failure: studioIngress block in values.yaml is missing enable flag; templates/studio/{ingress,oauth2proxy-deployment, oauth2proxy-service}.yaml all reference studioIngress.enabled with no default. Pre-existing on main; not introduced by this merge. - The five Junie briefs filed on this branch are now reachable from main at docs/plans/junie/{02,06,07,13,15}-*.md. Junie can pick them up in any order. - knoe-auth Phase 2 OIDC source (now at dev.knoe.auth.*) is not yet deployed to the cluster. Deployment is its own task. - The branch claude/crazy-bose-fec256 stays in place (worktree at .claude/worktrees/crazy-bose-fec256 may have ongoing context for Claude Code sessions). Safe to delete once next session starts cleanly from main. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
189 lines
13 KiB
Markdown
189 lines
13 KiB
Markdown
# Deployment Modes — Welcome Screen + Wizard Fast-Path
|
|
|
|
**Status:** Implemented and operational. Architectural reference. Welcome-screen mode selector and `min`-mode fast-path shipped in Phase 0.
|
|
**Owner:** chrisfu
|
|
**Audience:** Jr/mid engineer onboarding to knoe.dev. Familiarity with Tk/tkinter helps but is not required.
|
|
|
|
---
|
|
|
|
## 1. Context
|
|
|
|
The knoe-db installer (`./install.sh` / `./knoe.sh install`, driven by the Tk UI in `knoe/ui/screens/`) supports four ways to deploy the platform. Different audiences, different hardware, but **the same architecture underneath**.
|
|
|
|
Earlier installer revisions assumed the engineer already knew which mode they wanted, presented a welcome screen that was a wall of text, and shipped a sidebar tab strip (`k3d` / `k3s` / `k8s`) that didn't reliably refresh state across screens. Phase 0 replaced all of that with a first-screen mode selector that teaches the engineer what each mode *is* before asking them to choose, and added a `min`-mode fast-path that skips wizard screens irrelevant to a single-container deployment.
|
|
|
|
### The four modes
|
|
|
|
| Mode | What it is | Who it's for | Required tools |
|
|
| --- | --- | --- | --- |
|
|
| **min** | A single `knoe-db` container under `containerd` — no Kubernetes, no Docker. The Spring Boot app runs locally on the host. | Engineers running a Spring app on a laptop and wanting a CNPG-compatible Postgres without a full cluster. | Homebrew, 1Password |
|
|
| **k3d** | A Docker-based local k3s cluster. Full CNPG + optional Supabase / ArgoCD / Gitea / GitLab. | Local development with the full platform. | Docker, Homebrew, 1Password |
|
|
| **k3s** | A multi-node k3s cluster on real hardware. Full Kerberos auth stack, Garage S3, monitoring. Mirrors the GKE shape. | Homelab contributors with their own hardware (e.g. a 3-node Pi cluster). | k3sup, Homebrew, 1Password |
|
|
| **gke** | The production dual-cluster on Google Cloud (`knoe-dev-0` + `knoe-dev-cnpg-0` in `us-west3`). | Production. | gcloud, kubectl, 1Password |
|
|
|
|
The architectural commitment matters: **all four modes are scaled-down mirrors of the GKE shape.** Not parallel implementations of the same idea, not divergent forks — the same components composed at different scales. CNPG runs in all four. The Spring Boot `authority` service runs in all four. `knoe.user` lives in the same schema in all four. The only thing that changes is what platform the components run on and which optional services are enabled.
|
|
|
|
### Mode → cluster_env mapping
|
|
|
|
| `cluster_env` | `KNOE_MODE` | Target |
|
|
| --- | --- | --- |
|
|
| `dev` | `k3d` | Local K3d cluster |
|
|
| `service` | `k3s` | On-prem K3s cluster |
|
|
| `prod` | `k8s` (alias `gke`) | GKE (or other cloud) |
|
|
| `min` | `min` | Local containerd (no Kubernetes) |
|
|
|
|
The conversion lives in `knoe/core/env.py` (`_deployment_mode_from_env()`).
|
|
|
|
### Config file mapping
|
|
|
|
`knoe/knoe_conf.py` maps environments to config files under `conf/`:
|
|
|
|
| Mode | Config file |
|
|
| --- | --- |
|
|
| `min` | `conf/min.cfg` |
|
|
| `k3d` (`dev`) | `conf/k3d.cfg` |
|
|
| `k3s` (`service`) | `conf/k3s.cfg` |
|
|
| `gke` (`prod`) | `conf/gke.cfg` |
|
|
|
|
Config is layered: env-specific file overrides base. `KNOE_CONF` env var or `conf/service/` subdirs point to the active config.
|
|
|
|
---
|
|
|
|
## 2. How it's wired — file map
|
|
|
|
| Component | Location | What's there |
|
|
| --- | --- | --- |
|
|
| Welcome screen with mode selector | `knoe/ui/screens/welcome.py` | `WelcomeScreenMixin._render_welcome_page()` renders the four mode cards. Click handler updates `deployment_mode` and `cluster_env`, redraws card borders, re-evaluates the Next gate. |
|
|
| Sidebar nav | `knoe/ui/screens/navigation.py` | `_create_sidebar_nav()` no longer renders the old `k3d/k3s/k8s` tab strip — the welcome card selector replaces it. `_set_deployment_mode` is still called from the welcome handler. |
|
|
| Mode/state initialization | `knoe/ui/screens/__init__.py` | `nav_items` list, `deployment_mode = tk.StringVar(...)`, `cluster_env = tk.StringVar(...)`. |
|
|
| Wizard transitions | `knoe/ui/screens/navigation.py` `on_next` / `on_prev` | Min-mode fast-path skips screens that don't apply (network scan, cluster init, Kerberos, ArgoCD, Supabase, common services). |
|
|
| Update-footer Next-button gate | `knoe/ui/screens/navigation.py` `update_footer` | Welcome screen disables Next until a mode is selected. |
|
|
| Min-mode bootstrap | `etc/init_min.sh` | Idempotent: ensures Homebrew + containerd, pulls and runs the `knoe-db` container locally, runs schema bootstrap, prints connection info. Invoked from `init_scripts` step in min mode. |
|
|
| Min-mode config | `conf/min.cfg` | Modeled on `conf/k3d.cfg`. Just what `init_min.sh` needs. |
|
|
| Min-mode lifecycle | `knoe.sh` (`start` / `stop` / `restart` subcommands) | Manages the local containerd `knoe-db` instance for users who don't want to run the wizard every time. |
|
|
|
|
---
|
|
|
|
## 3. UI layout — welcome screen
|
|
|
|
```
|
|
┌──────────────────────────────────────────────────────────────────┐
|
|
│ │
|
|
│ knoe.dev │
|
|
│ infrastructure.auto() │
|
|
│ │
|
|
│ Welcome │
|
|
│ ─────── │
|
|
│ Knoe.DB sets up a production-grade PostgreSQL cluster with │
|
|
│ Kerberos authentication. Pick the mode that matches your │
|
|
│ hardware — we'll walk you through every step. │
|
|
│ │
|
|
│ ┌────────────┬────────────┬────────────┬────────────┐ │
|
|
│ │ min │ k3d │ k3s │ gke │ │
|
|
│ │ Just a │ Local │ Homelab │ Production│ │
|
|
│ │ Database │ Cluster │ │ │ │
|
|
│ │ One knoe-db│ k3s-in- │ Multi-node │ Dual GKE │ │
|
|
│ │ container │ Docker │ k3s on real│ clusters on│ │
|
|
│ │ via │ cluster on │ hardware. │ Google │ │
|
|
│ │ containerd.│ your Mac. │ Full │ Cloud. │ │
|
|
│ │ No K8s. │ Full CNPG │ Kerberos │ CNPG + │ │
|
|
│ │ Perfect for│ database — │ auth stack,│ GCS backups│ │
|
|
│ │ a Spring │ add │ Garage S3, │ + Workload │ │
|
|
│ │ app on your│ Supabase, │ monitoring.│ Identity. │ │
|
|
│ │ laptop. │ ArgoCD, │ │ │ │
|
|
│ │ │ Gitea, or │ │ │ │
|
|
│ │ │ GitLab. │ │ │ │
|
|
│ │ Homebrew + │ Docker + │ k3sup + │ gcloud + │ │
|
|
│ │ 1Password │ Homebrew + │ Homebrew + │ 1Password │ │
|
|
│ │ │ 1Password │ 1Password │ │ │
|
|
│ └────────────┴────────────┴────────────┴────────────┘ │
|
|
│ │
|
|
│ You'll need: Docker · Homebrew · 1Password │
|
|
│ │
|
|
│ [ Next → ] │
|
|
└──────────────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
Behavior:
|
|
|
|
- The four cards are clickable.
|
|
- The selected card gets a colored border in the mode's accent color (`_MODE_COLORS`: `min` purple, `k3d` blue, `k3s` green, `gke` orange).
|
|
- The "You'll need:" line below the cards updates to reflect the selected mode's tools.
|
|
- The Next button is **disabled** until a mode is selected.
|
|
- Selecting a card also sets `cluster_env` via the mode-to-cluster_env map.
|
|
- On Next, mode is persisted to `knoe_cfg_data["Global"]["DEPLOYMENT_MODE"]`.
|
|
|
|
---
|
|
|
|
## 4. Wizard transitions — `min`-mode fast-path
|
|
|
|
### Default flow (k3d / k3s / gke)
|
|
|
|
```
|
|
welcome → network_scan → env_setup → init_cluster → cluster_nodes →
|
|
init_password → init_scripts → kerberos_config → knoe_users →
|
|
argocd_config → gitops_config → supabase_config → common_services →
|
|
… → security
|
|
```
|
|
|
|
### Min-mode flow
|
|
|
|
```
|
|
welcome → dependencies → environment → init_password → init_scripts → security
|
|
```
|
|
|
|
Skipped in min: `network_scan`, `init_cluster`, `cluster_nodes`, `kerberos_config`, `knoe_users`, `argocd_config`, `gitops_config`, `supabase_config`, `common_services`. None of them apply when there's no Kubernetes cluster and no Kerberos KDC. `init_scripts` invokes `etc/init_min.sh` instead of the cluster-mode init scripts.
|
|
|
|
The fast-path is implemented as a `_min_mode_next` dictionary in `knoe/ui/screens/navigation.py` consulted from `on_next` / `on_prev`. The override is only active when `_is_min_mode()` returns true.
|
|
|
|
---
|
|
|
|
## 5. Verification
|
|
|
|
Run after any change touching the wizard or mode logic.
|
|
|
|
1. `./install.sh` opens. The welcome screen shows four mode cards. The sidebar has **no** k3d/k3s/k8s tab strip.
|
|
2. With no mode selected, the Next button is disabled.
|
|
3. Click the **min** card. Next becomes enabled. Click Next.
|
|
- The wizard skips the network-scan screen.
|
|
- It skips `init_cluster` and `cluster_nodes`.
|
|
- It skips `kerberos_config`, `knoe_users`, `argocd_config`, `gitops_config`, `supabase_config`, `common_services`.
|
|
- It runs `init_min.sh` at the `init_scripts` step.
|
|
- It lands on the `security` screen.
|
|
- Going back through `on_prev` walks the same trimmed sequence in reverse without hitting any skipped screens.
|
|
4. Click the **k3d** card on a fresh run. The wizard follows the existing k3d flow exactly as before.
|
|
5. `python3 -c "from knoe.ui.screens import KnoeInstaller"` — no import errors.
|
|
6. After completing min mode, `nerdctl ps` shows the `knoe-db` container running locally and `psql "${printed_conn_string}" -c '\dt knoe.*'` lists the `knoe.user` table.
|
|
7. `./knoe.sh stop` and `./knoe.sh start` cleanly stop/restart the local containerd instance.
|
|
|
|
---
|
|
|
|
## 6. Out of scope
|
|
|
|
- A `min`-mode equivalent of the full Kerberos auth stack. Min is "just a database". Auth in min is a follow-up.
|
|
- Migrating an existing `k3d` deployment to `min` (or any other mode-to-mode migration). Each mode is an independent target.
|
|
- A unified package format that produces all four mode-specific installers from one `pyinstaller` build. The current per-mode build is fine.
|
|
- Letting one wizard run install *multiple* modes (e.g. set up `k3d` and `gke` from the same session). One mode per run.
|
|
|
|
---
|
|
|
|
## 7. Glossary
|
|
|
|
**k3s** — A lightweight Kubernetes distribution by Rancher Labs. Single binary, runs comfortably on a Raspberry Pi. The same project, two delivery shapes: `k3d` is k3s wrapped in Docker; bare k3s is k3s on actual hardware.
|
|
|
|
**k3d** — A wrapper that runs k3s clusters inside Docker containers. Useful for local dev because it gives you a "real" Kubernetes cluster without having to provision VMs.
|
|
|
|
**GKE (Google Kubernetes Engine)** — Google Cloud's managed Kubernetes. We use Standard for `knoe-dev-0` and `knoe-dev-cnpg-0`. See `CLAUDE.md` for cluster topology.
|
|
|
|
**containerd** — A container runtime. Speaks the OCI image and runtime specs. Both Docker and Kubernetes use containerd under the hood. In `min` mode we talk to it directly via `nerdctl`, skipping Docker entirely.
|
|
|
|
**nerdctl** — A Docker-CLI-compatible client for `containerd`. If you know `docker run`, you know `nerdctl run`.
|
|
|
|
**CNPG (CloudNativePG)** — The Postgres operator we use for `knoe-db`. See `CLAUDE.md` for which cluster runs it in production.
|
|
|
|
**`cluster_env`** — A label the installer carries internally that picks which `conf/*.cfg` file to read and which downstream config branches to take. Maps from `deployment_mode` per the table in §1. Don't reuse this name for new variables — it's already overloaded enough.
|
|
|
|
**Tk / tkinter** — Python's standard GUI toolkit. The installer is built on it. Canvas-based rendering means we draw text and shapes directly rather than using Tk's widget hierarchy for the welcome screen.
|
|
|
|
**Wizard / pid** — The installer is a multi-screen wizard. Each screen has a "page id" (`pid`) — `welcome`, `network_scan`, `init_cluster`, etc. `nav_items` is the ordered list; `on_next` / `on_prev` decide transitions based on the current `pid` and the user's state.
|