4.3 KiB
AGENTS.md — AI coding agent guide for knoe-db / Prole
What this repo is
Knoe is an infrastructure stack for deploying a Supabase-style internal developer platform (PostgreSQL, object storage, secrets, auth, observability) across K3d (local), K3s (on-prem), and GKE (cloud) environments. The Python "Prole" installer (prole/cli.py) drives all cluster setup via milestones.
Architecture overview
Dual-cluster GKE layout (prod)
Two GKE clusters in us-west3:
| Cluster | Context | Purpose |
|---|---|---|
knoe-dev-0 |
gke_plenary-truck-485623-p7_us-west3_knoe-dev-0 |
App cluster — Garage, Registry, OpenBao, Kong, GitLab, monitoring |
knoe-cnpg-0 |
gke_plenary-truck-485623-p7_us-west3_knoe-cnpg-0 |
DB cluster — CNPG/PostgreSQL only |
Critical: Garage must NEVER be deployed to knoe-cnpg-0. SSD quota (300 GB) is fully consumed by CNPG — all non-CNPG PVCs must use standard storage class (HDD), not standard-rwo/premium-rwo.
Deployment environments / modes
cluster_env |
PROLE_MODE |
Target |
|---|---|---|
dev |
k3d |
Local K3d cluster |
service |
k3s |
On-prem K3s cluster |
prod |
k8s |
GKE (or other cloud) |
_deployment_mode_from_env() in knoe/core/env.py converts env strings to mode strings.
Config file mapping
knoe/prole_conf.py maps environments to config files under conf/:
dev→k3d.cfgservice→k3s.cfgprod→gke.cfg
Config is layered: env-specific file overrides base. PROLE_CONF env var or conf/service/ subdirs point to the active config.
Key source locations
| Path | Purpose |
|---|---|
knoe/core/env.py |
Core config/env helpers, secret encryption, kubeconfig resolution |
knoe/core/actions.py |
All installer actions and unattended workflow helpers (~8k lines) |
knoe/milestone.py |
Milestone ABC — all install steps implement this; _get_script_env() builds the env for subprocesses |
knoe/prole_conf.py |
Config path resolution and layered loading |
knoe/core/milestones.py |
Concrete milestone definitions |
conf/gke.cfg |
Production GKE config (must have correct app_cluster_kubecontext / db_cluster_kubecontext) |
conf/service/prod.cfg |
Unattended deploy config for ./deploy.sh |
etc/ |
Shell init scripts (init_*.sh) called by milestones |
k8s/ |
Kubernetes manifests by service |
scripts/reset_clusters.sh |
Full cluster teardown + recreate |
Developer workflows
Install dependencies
make requirements # pip install -r prole_requirements.txt
Run tests
make test # runs pyconv (black check) then pytest with coverage
# or directly:
PYTHONPATH=. pytest tests/
Build the prole CLI binary
make prole # PyInstaller one-file binary → dist/prole
Interactive installer (ncurses)
./install.sh # reads conf/gke.cfg (or PROLE_CONF)
# or via the unified launcher:
./knoe.sh install
Unattended deploy
./deploy.sh # reads conf/service/prod.cfg
Code style
black . # formatter (black --check . is enforced in CI)
Secret handling
Secrets in prole.cfg are AES-GCM encrypted at rest using ${PROLE_SECRET:v1:...} tokens. On macOS, the key is in Keychain (prole-installer service); on Linux, at ~/.prole/secrets/knoe.key. OpenBao references use ${OPENBAO:kv/prole/<ns>/<leaf>#<key>}. Never store plaintext passwords in config files.
Milestone pattern
All installer steps subclass Milestone (knoe/milestone.py). They must:
- Be UI-agnostic (no tkinter/ncurses imports)
- Use
_run_cmd()for subprocesses (handles env injection) - Use
_get_script_env(state)to build env dicts for shell scripts — this is whereKUBECONTEXT,DB_CLUSTER_KUBECONTEXT,PROLE_CONF, etc. are set
Missing init_cluster.app_cluster_kubecontext in config causes Garage to deploy to the wrong cluster.
CNPG / backup specifics
- CNPG backups go to GCS (not Garage):
gs://knoe-0-backups/andgs://knoe-0-wal/ - Workload Identity SA:
cnpg-backup@plenary-truck-485623-p7.iam.gserviceaccount.com - ObjectStore manifest:
k8s/prole/knoe-db-barman-objectstore-gcs.yaml - Setup:
etc/init_cnpg_gke.shandetc/init_cnpg_backup.sh