Commit Graph

105 Commits

Author SHA1 Message Date
chrisfu
da0fd2c545 feat(env): auto-detect gke_ kubecontext prefix as prod; status.py context helpers
knoe/knoe_conf.py: normalize_environment() now recognises the gke_ prefix
(e.g. gke_plenary-truck-485623-p7_us-west3_knoe-dev-0) as the 'prod'
environment, matching real GKE kubecontext naming.

status.py: add _current_kubecontext() and _cfg_path_from_kubecontext()
so status.py auto-selects the correct cfg file based on the active
kubectl context without manual KNOE_CONF overrides.

Co-authored-by: Junie <junie@jetbrains.com>
2026-05-23 21:31:07 -07:00
chrisfu
ef20c8a598 fix(cfg): refuse to serialize non-string widget values into knoe.cfg
Add _validate_cfg_values() to knoe/ui/screens/cfg.py — called before
_filter_cfg_values_for_persistence so MagicMock (or any non-str) widget
values raise TypeError instead of being silently str()-coerced into
conf/<mode>.cfg.

Also re-raise TypeError/ValueError from _save_knoe_cfg so the error
escapes the outer broad except-Exception handler.

New test: tests/installer/test_cfg_save_refuses_mock_values.py
  - test_save_knoe_cfg_refuses_non_string_widget_values: MagicMock vars → TypeError
  - test_save_knoe_cfg_real_strings_produce_clean_cfg: real _Var stubs → clean cfg

Fixes TODO-1 / tracked in docs/completed/todo-1-cfg-save-path-bug.md.
conf/k3d.cfg and conf/k3s.cfg still contain stale MagicMock values from
before this fix and must be regenerated before committing.

Co-authored-by: Junie <junie@jetbrains.com>
2026-05-23 21:31:02 -07:00
chrisfu
e014fd5b71 feat(k3s): add pg.prole.org as CNPG postgres endpoint with split-horizon DNS
- knoe-db.yaml: switch to CNPG-managed TLS cert with serverAltDNSNames
  (pg.prole.org + knoe-db-rw cluster service) — removes static serverTLSSecret/serverCASecret
- dns.yml: add pg.prole.org A record to prole_k3s_dns_records (10.0.0.3, 10.0.0.6)
  for Ansible-managed split-horizon DNS via Samba AD DC
- k3s.cfg: align KNOE_HOME paths to ~/dev/prole, add PROLE_KDC_* vars, remove
  hardcoded KUBECTL_CONTEXT (kubeconfig current-context is authoritative)
- prod.cfg: add PROLE_KDC_STORAGE_CLASS = prole-iscsi
- onepassword.py: skip vault check gracefully when no 1Password session active (non-TTY)
- CLAUDE.md: document production postgres connection string and DNS/CA cert ops

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 22:46:46 -07:00
chrisfu
3f34fa8b32 fix(installer): k3s --reset path hardening (kdc deploy, no-TTY 1password, context overrides)
Five fixes Junie surfaced while running the kdc-trust-reset-repeatable
Junie brief end-to-end (companion to commit 6f99f95). All hit during
the unattended `install.sh --mode k3s --reset` pipeline.

  - knoe/core/milestones.py (KerberosMilestone):
    For k3s and k3d modes, deploy the KDC pod via `init_kdc.sh start`
    before running init_kerberos.sh. init_kerberos.sh only chains into
    init_kdc.sh when PROLE_KDC_STANDALONE=1; without this hook the
    cluster came up with no KDC pod and the cross-realm trust principals
    had nowhere to land.

  - knoe/milestone.py (Milestone._get_script_env):
    Clear KUBECTL_CONTEXT in addition to KUBECONTEXT so stale entries
    from a different machine's cfg don't override the kubeconfig's
    own current-context.

  - etc/knoe_cfg.sh (_knoe_read_cfg):
    Skip KUBECTL_CONTEXT / KUBE_CONTEXT_NAME / KUBECONTEXT entries when
    reading cfg in k3s mode. Same theme: kubeconfig current-context is
    authoritative.

  - etc/init_1password.sh + knoe/core/onepassword.py:
    When running non-interactively (no TTY on stdin) and no `op`
    session exists, skip rather than hang on `op signin`. Lets the
    unattended pipeline proceed for k3s/k3d where in-cluster secrets
    are managed separately from 1Password.

Co-authored-by: Junie <junie@jetbrains.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-11 13:34:10 -07:00
chrisfu
6f99f95f84 kdc: verify install.sh --reset converges to a working cross-realm trust
Fix _deployment_mode_hint() to correctly map cluster_env=service → k3s
mode. Previously 'service' was not handled in the normalized_env checks,
causing fallthrough to build.deploy_env='Dev' → mode='dev' → k3d
dependency required. On a k3s node (myrddin/merlin/gandalf) k3d is not
installed and the DependenciesMilestone fatally aborted the install.

Also fix get_required_dependency_ids(): k3s mode does not require k3d
(k3s is provisioned on the cluster nodes by Ansible, not by the
installer binary).

Fixes: install.sh --mode k3s --reset failing with
  'Dependencies unresolved after install attempts. Required: k3d'

Co-authored-by: Junie <junie@jetbrains.com>
2026-05-11 02:33:38 -07:00
chrisfu
2df7c91926 fix(kong): SERVICE_NAMESPACE=default in conf/dev overlay caused kong to deploy to default ns
conf/dev/knoe.cfg had a stale SERVICE_NAMESPACE=default written by a prior TUI session.
Also guard _service_namespace() so the value 'default' is never returned — it is never
a valid service namespace and signals a stale generated config.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-04 01:44:51 -07:00
chrisfu
c7871e2780 fix(installer): silent mode — gcp skip for k3d, op timeout, KNOE_SKIP_OP bypass
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-04 01:44:44 -07:00
chrisfu
a9b11f3ee6 fix(cnpg-backup/k3d): skip re-init when already healthy; add breadcrumb 2026-05-04 00:46:43 -07:00
chrisfu
de1a04c0fb fix(ui/cluster): stop combobox overlapping Add/Delete buttons
Combobox width=30 chars extends to ~320-380px depending on font metrics,
colliding with Add at x+290 and Delete at x+350. Narrowed combobox to
width=22 and shifted buttons to x+260 and x+320 to give clear separation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-04 00:34:18 -07:00
chrisfu
2f98a5afd2 fix(cnpg/k3d): skip reinitialize when cluster already healthy
install_barman_plugin() fetches from GitHub on every run (up to 6×120 s
retries), stalling the installer worker thread even when the CNPG cluster
is already at 'Cluster in healthy state' with all pods 2/2 Ready.

Add a fast-path at the top of initialize(): check .status.phase for
'healthy' then verify all pods show 2/N ready — if both pass, return
immediately. Full pipeline (ensure_operator, install_barman_plugin,
_apply_manifest, _wait_cnpg_pods) is only entered when needed.

Also adds test_cnpg_initialize_skips_when_cluster_healthy to
test_deployment_mode_isolation.py to guard against regression.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-03 23:54:22 -07:00
chrisfu
5295e47753 fix(monitoring/k3d): skip helm upgrade when already deployed and healthy
kube-prometheus-stack CRD re-application stalls on every installer run
even when the release is in deployed state with all pods Running. For k3d
this is purely idempotency noise — skip the upgrade and return immediately.
Broken state (failed status, unbound PVCs) still triggers a full purge+reinstall.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-03 22:56:39 -07:00
chrisfu
47ae5d69d6 fix(supabase/k3d): disable node affinity, ingress, and TUI clutter
- render_supabase.py: k3d sets scheduling.enforceGeneralNodeRole=false so
  pods don't require knoe.dev/node-role=general label (k3d nodes unlabelled)
- render_supabase.py: disable kong and studio ingress for k3d (port-forwards
  are used instead; avoids db.knoe.org reference that doesn't exist
- deploy.sh: escape double quotes in SQL comment on lines 2114-2115 to fix
  bash prematurely closing the psql -c ... string
- supabase.py: remove broken node-selector text entry (black rectangle in Tk)
  and redundant Deploy button (enable checkbox already triggers deployment)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
EOF
)
2026-05-03 22:15:07 -07:00
chrisfu
d110f594c6 fix(k3d): patch containerd registry mirror on all cluster nodes
k3d registry containers are addressed as k3d-NAME.localhost:PORT from
inside the cluster, but containerd resolves that as 127.0.0.1 (loopback)
which has nothing listening.  The fix is to write /etc/rancher/k3s/registries.yaml
on every server/agent node to mirror k3d-NAME.localhost:PORT -> http://k3d-NAME:PORT
(Docker network DNS), then restart the node so containerd picks it up.

_patch_k3d_registry_mirrors() is called from _ensure_k3d_registry() after
the registry is confirmed running (idempotent — skips nodes already configured).
This makes knoe-authority and any other image pushed to localhost:5000
immediately pullable inside the cluster as k3d-knoe-registry.localhost:5000/...

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-03 15:18:11 -07:00
chrisfu
63185d8104 fix(port-forwards): make argocd/dashboard conditional; fix grafana release name; non-fatal start
Port-forward setup was failing the installation because:
1. argocd and dashboard entries were always added to port-mapping even when
   those services haven't been selected or installed yet
2. Grafana/Prometheus service names were hardcoded as kps-* but monitoring
   deploys with release name "prometheus" → services are prometheus-grafana etc.
3. The grafana status poll after init_port_forwards.sh start would mark the
   entire installation failed if grafana wasn't reachable

Changes:
- _build_required_port_forwards (env.py): add argocd_enabled, dashboard_enabled,
  monitoring_release params; argocd/dashboard only included when enabled; grafana
  and prometheus targets use f"svc/{monitoring_release}-grafana" etc.
- _sync_port_forward_mappings (actions.py): read argocd_enabled from installer
  config; read MONITORING_RELEASE from Monitoring section; clean up argocd and
  dashboard entries from [Port Forwards] when disabled
- run_init_scripts (services.py): port-forward step is non-fatal — failure logs
  a warning and continues; blocking grafana poll removed
- 2 new regression tests (7e) covering the above invariants

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-03 14:39:10 -07:00
chrisfu
c75c63eb9c fix(services): pass service namespace to init_kong.sh, not DB namespace
services.py run_init_scripts() called init_kong.sh with -n env[NAMESPACE]
where NAMESPACE is the database namespace (e.g. knoe-db). The -n flag
sets COMMON_CORE_NAMESPACE which wins over SERVICE_NAMESPACE in
common_core_resolve_namespace, so Kong deployed into knoe-db.

Fix: resolve kong_ns from SERVICE_NAMESPACE, falling back to
_get_service_namespace() and finally knoe-system. Exclude default
as it is the Tk StringVar initial value, not a real service namespace.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-03 13:56:34 -07:00
chrisfu
4bcd8f846e fix(milestone): SERVICE_NAMESPACE must not fall back to DB namespace
When SERVICE_NAMESPACE was absent from the config file and OS env,
_get_script_env() fell back to env["NAMESPACE"] — the database namespace
(e.g. knoe-db). InitializationScriptsMilestone then called init_kong.sh
with SERVICE_NAMESPACE=knoe-db, causing Kong to deploy into the DB
namespace and collide with the existing knoe-system/svc-knoe-ingress.

Fix: default to "knoe-system", matching _service_namespace() in actions.py.
Configs that set SERVICE_NAMESPACE explicitly are unaffected.

Add tests/test_deployment_mode_isolation.py to guard against k3d/k3s/gke
mode-specific config bleeding into each other: SERVICE_NAMESPACE fallback,
monitoring storage class separation, Kong gitea host gating, and
_service_namespace() across all three deployment modes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-03 13:22:12 -07:00
chrisfu
8dcec846cd fix(monitoring): stop purge cycle on k3d retry
Three issues caused the purge-and-reinstall loop:

1. _purge_broken_monitoring deleted ALL PVCs including Bound ones; grafana's
   working PVC was wiped on every retry. Now only delete PVCs in Pending state.

2. Broken-state detection keyed on Pending pods + unbound PVCs, which is true
   during any still-converging install (including ones that timed out but
   whose pods eventually came up). Gate on helm status=='failed' + unbound PVCs.

3. k3d install used --wait, which blocks on all kube-prometheus-stack components
   (prometheus, alertmanager, node-exporter). They converge async after the
   Prometheus operator starts; --wait always timed out. Drop --wait for k3d;
   the status_common_services.sh check verifies readiness independently.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-03 12:55:11 -07:00
chrisfu
489593dca2 fix(monitoring): extend helm --wait timeout to 20m for k3d
kube-prometheus-stack pulls multiple large images on a fresh k3d install;
600s / 10m is not enough. Set --timeout 20m and process timeout 1320s
(20m + 2m buffer) for k3d, keep 10m for k8s/k3s where images are warm.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-03 01:23:06 -07:00
chrisfu
ac7b5928ca fix(monitoring): k3d values + purge broken release with stuck PVCs
Two bugs kept prometheus-grafana-0 Pending for 21 days in k3d:

1. update() routed k3d through _values_yaml_k3s() which hardcodes
   merlin-local-iscsi-* storage classes and merlin.prole.org node affinity
   — neither exists in k3d, so grafana's PVC could never bind.
   Add _values_yaml_k3d() that uses local-path (or MONITORING_STORAGE_CLASS
   override) with no node affinity; dispatch k3d separately in update().

2. No broken-state recovery for non-k8s mode. Add _purge_broken_monitoring()
   (helm uninstall + delete stuck PVCs) and call it from update() when
   Pending pods and unbound PVCs are both detected in the monitoring namespace.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-03 01:03:59 -07:00
chrisfu
055069c1f8 fix(k3d): clean up prole-registry and fix registry running check
k3d-prole-registry was squatting on port 5000, leaving k3d-knoe-registry
in created state. Two bugs made this invisible:

- k3d_registry.py: substring match (name in stdout) matched k3d-knoe-registry
  as already-exists without checking STATUS=running; add _k3d_registry_running()
  requiring last column == running, detect and delete prole-registry before
  creating knoe-registry, recreate if found in non-running state
- status_common_services.sh: grep -qx 'knoe-registry' (exact) never matched
  k3d prefix 'k3d-knoe-registry'; fix with awk suffix match + STATUS==running

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-03 00:31:43 -07:00
chrisfu
82c1ff555f fix(k3d): rename prole-svc-kong → knoe-svc-kong, clean up stale resources
k3s manifests still used prole-svc-kong after the rebrand; init_kong.sh
was waiting on `rollout status deployment/knoe-svc-kong` which never
existed, hanging the Common Services milestone.

- Rename kong-deployment.yaml and kong-service.yaml: prole-svc-kong →
  knoe-svc-kong (labels, selector, configmap volume ref)
- Remove prole-svc-kong-configmap.yaml (static file replaced by
  init_kong.sh dynamic ConfigMap generation; hardcoded namespace and
  prole-branded routes were dead weight)
- init_kong.sh: add cleanup_legacy_prole_kong() called from action_update()
  to remove stale prole-era resources before deploying knoe-svc-kong
- init_kong.sh: add _is_host_claimed_by_other_ingress() helper; set
  include_gitea_host=0 for k3d mode (git is port-forward only, no public
  hostname) — keeps the safety-net pre-check for k3s
- actions.py: extend legacy namespace dedupe to sweep prole-svc-kong from
  both default and service_ns

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-03 00:24:02 -07:00
chrisfu
dba8a2d1dc feat(installer): TDD stabilization for k3d install path; dual-cluster GKE TUI
Junie's session targeted the prompt "stabilize ./install.py -c conf/k3d.cfg
using strict TDD" — broad installer-side work, not the k3d-mirror Phase 3
brief I had filed (which she didn't pick up; phase-3 brief stays open). All
750 installer tests pass post-change.

What Junie produced:

  install.py                          (NEW) Top-level CLI entry point. Was
                                            imagined by the prompt but didn't
                                            exist; this commit makes it real.
  knoe/deployment.py                  (NEW) `KnoeDeployment` orchestrator for
                                            the k3s service-mode deploy pipeline.
                                            Wraps Ansible kubeconfig fetch,
                                            opentofu apply, init_*.sh post-apply
                                            scripts, and (optionally) supabase/
                                            deploy.sh.
  knoe/ui/screens/cluster.py          Dual-cluster GKE kubecontext UI: prod env
  knoe/ui/screens/cfg.py              now shows separate "App Cluster:" and
                                       "DB Cluster:" dropdowns instead of a
                                       single "Kubernetes Context:" combo.
                                       New _app_kubectx_combo + _db_kubectx_combo
                                       widgets; new app/db_cluster_kubecontext
                                       tk.StringVars.
  knoe/core/{actions,env,milestones}.py
  knoe/core/ops/storage.py
  knoe/config.py, knoe/knoe_conf.py   Plumbing changes for the dual-cluster
                                       kubecontext flow + storage-class topology
                                       detection cleanup.
  knoe/tools/cleanup_cnpg_storage.py  (NEW) Stand-alone cleanup utility.
  tools/dashboard.sh                  (NEW) Dashboard helper.
  conf/knoe.cfg                       (NEW) Master cfg generated by knoe_conf.
  conf/dev/                           (NEW) Dev-mode cfg directory.
  conf/port-mapping.cfg               Port mapping tweaks for k3d.
  tests/installer/* (8 files)         New + extended tests for the dual-cluster
  tests/test_database_options.py      TUI, kubecontext save flow, storage ops,
                                       topology detection, deploy helpers,
                                       database-options screen.

Issues found in Junie's working state and fixed here:

  1. install.py was a 11-line import shim with no shebang, no `chmod +x`,
     no `if __name__ == '__main__'` block. `./install.py -c conf/k3d.cfg`
     returned `Permission denied` and `python install.py` did nothing.
     Added `#!/usr/bin/env python3`, `chmod +x`, and a __main__ block
     that delegates to `knoe.ui.screens.main()`. `./install.py --help`
     now prints the canonical argparse help.

  2. knoe/deployment.py had FIVE `subprocess.run()` call sites with no
     `timeout=` argument (`_run_script`, `_run_cmd`, the Ansible playbook
     fetch, `tofu init`, `tofu apply`). A hung child process — typical
     failure mode is a script waiting on stdin or a stalled network
     call — would lock up the installer indefinitely. Added timeouts:
       - Ansible kubeconfig fetch: 120s
       - tofu init: 300s
       - tofu apply, _run_script, _run_cmd: bounded by new module
         constant `_MILESTONE_TIMEOUT` (default 1800s = 30 min, override
         via `KNOE_MILESTONE_TIMEOUT_SECONDS` env var).
     `subprocess.TimeoutExpired` is caught explicitly; on timeout the
     run helpers return exit code 124 (conventional timeout code).

  3. `conf/k3d.cfg` was corrupted with MagicMock string-reprs on disk:
        KNOE_CONF = <MagicMock name='Canvas().tk.call().strip()' id='4743999712'>
        argocd.node_selector = <MagicMock name='mock.StringVar().get().strip()' id='...'>
     Likely path: Junie ran `./install.py -c conf/k3d.cfg` interactively
     in a non-Tk environment (or with a partially-mocked widget set) and
     the installer's "save current state" path wrote the mock-objects'
     `__repr__` strings into the cfg file. This commit reverts the cfg
     to its pre-Junie state. **Followup: harden the cfg save path
     against non-string widget values** — track separately.

  4. The corrupted cfg caused the installer to call `os.makedirs()` on
     the mock-string values, producing 10 directories on disk literally
     named `<MagicMock name='Canvas().tk.call().strip()' id='4733210304'>/`
     etc., with 5–86 files of install artifacts inside each. Removed.

The "final step is timing out" the user reported was almost certainly
issue #2 above: install.py walked the milestone pipeline, hit one of
the unbounded subprocess.run calls, and the wrapped command (probably
supabase/deploy.sh, which Junie was reading for context when her
session timed out) hung. With the timeouts in place that path now
exits cleanly with rc=124 instead of locking up.

Verification:
  - pytest tests/installer/ -q                                   750 passed in ~25s
  - python3 -c "import knoe.deployment"                          imports clean
  - ./install.py --help                                          prints argparse help
  - find . -maxdepth 1 -type d -name '<MagicMock*' | wc -l       0
  - head -7 conf/k3d.cfg                                          clean (no MagicMock)

Out of scope for this commit (followups):
  - The cfg save-path that wrote mock-objects-as-strings (issue #3 root cause).
    Reproducer: launch the installer in an env where Tk widget vars are
    `unittest.mock.MagicMock` instances. The cfg save code should refuse to
    serialize non-str values rather than calling `str()` on a MagicMock.
  - The k3d-mirror Phase 3 brief (`docs/plans/junie/k3d-knoe-auth-pod-deploy.md`)
    is still open — Junie picked a different prompt this round.

Co-authored-by: Junie <junie@jetbrains.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 23:51:14 -07:00
chrisfu
00f0ebec07 Merge claude/crazy-bose-fec256 into main
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 (commit 9daa94b, 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 commit 9daa94b was 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>
2026-05-01 16:39:10 -07:00
chrisfu
f5b5542f87 fix(test): extract field.replace to variable before f-string in cloudnative_pg.py
Co-authored-by: Junie <junie@jetbrains.com>
2026-04-30 16:03:38 -07:00
chrisfu
c570160fb5 chore(installer): core Python updates — env, milestones, monitoring
Minor updates aligned with min-mode and auth Round 1 integration.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 14:47:27 -07:00
chrisfu
03d89eaa53 Phase 0: test pipeline foundation — pyproject.toml, IntelliJ run configs, coverage fix, welcome mode selector
Co-authored-by: Junie <junie@jetbrains.com>
2026-04-27 14:44:46 -07:00
chrisfu
b421f49af1 Migrate Ansible-based scripts and documentation to 1Password integration. Removed deprecated and redundant Ansible vault workflows, added 1Password CLI handling for secrets management, and updated tests to reflect the change. 2026-04-22 20:54:13 -07:00
chrisfu
55b6a6aff3 Complete rebranding from prole to knoe and fix macOS application identity. Bulk renamed 'prole' to 'knoe' across code, scripts, and manifests. Updated Makefile with 'knoe', 'build', and 'start' targets. Implemented macOS Application Bundle (.app) support for correct identity. Fixed macOS 'Python' process name to 'Knoe.DB Installer' via Objective-C bridge. Standardized application name to 'Knoe.DB Installer' across all interfaces.
Co-authored-by: Junie <junie@jetbrains.com>
2026-04-22 15:08:35 -07:00
chrisfu
af89ef547f Implement minimal installation mode (--min) with containerd support
Co-authored-by: Junie <junie@jetbrains.com>
2026-04-22 09:48:04 -07:00
chrisfu
f44ce32a27 Rebrand and consolidate authentication and scanning systems. Consolidate Kerberos authentication system into authority/src and rename ProleAuthApplication to KnoeAuthApplication. Remove deprecated prole/, prole-app/, prole-mssql-db/, and prole-tools-app/ directories. Migrate and rename prole-net/prole-agent to scan/network-agent. Update install.sh, Makefile, and documentation to use Knoe branding and new scan paths. Rebrand configuration properties and URLs to knoe.dev and svc.knoe.dev.
Co-authored-by: Junie <junie@jetbrains.com>
2026-04-22 09:28:14 -07:00
chrisfu
62a7a3f0da chore: add stale Helm lock detection and recovery for Prometheus
- Introduced `_recover_stale_prometheus_helm_lock` to detect and recover from stale Helm release locks during Prometheus deployment.
- Enhanced Prometheus deployment flow with stability verification and rollback to the last deployed state.
2026-04-19 11:05:56 -07:00
chrisfu
666ed5c1c3 chore: add secretref resolution for auth OIDC inputs
- Added `_resolve_secretref_value` to handle `secretref://` values for `auth.clientId` and `auth.clientSecret`.
- Extended environment and file-based lookups for secretref resolution.
- Updated tests to validate new secretref resolution logic in config and GitOps workflows.
2026-04-18 18:08:16 -07:00
chrisfu
f2677b3eaf chore: add auth OIDC secret refs handling in config loader
- Implemented `auth.clientId` and `auth.clientSecret` backfilling from Global section and environment variables.
- Added tests to verify correct hydration of OIDC inputs in configuration defaults.
2026-04-18 17:28:34 -07:00
chrisfu
0a799ca191 chore: refine post-remediation checks in init_gitlab.sh for GitLab workload convergence
- Introduced `gitlab_post_remediation_success` flag to streamline corrective action logging.
- Adjusted logic to skip unnecessary workload convergence gates when remediation is successful.
2026-04-18 15:48:36 -07:00
chrisfu
b8a55888be checkpoint: update GKE deployment docs and infra changes
Summarize CLAUDE.md updates:

- Document both live GKE clusters as e2-standard-2 x3 in us-west3 and note stale app default in code.

- Call out DB cluster naming mismatch between conf (knoe-dev-cnpg-0) and code default (knoe-cnpg-0).

- Add SSD quota guidance: 300GB fully consumed by CNPG, so non-CNPG PVCs must use standard/pd-standard.

- Refresh reset script reference and quota section details to match current runtime state.

Co-authored-by: Junie <junie@jetbrains.com>
2026-04-18 07:18:10 -07:00
chrisfu
e73f320740 chore: rename Prole to Knoe.dev across deployment scripts and update ingress logic
- Standardized naming from "Prole" to "Knoe" in README, scripts, and deployment files for consistency.
- Refined ingress configuration to adjust class and annotations based on mode.
- Enhanced deploy.sh to handle public APP endpoint status for specific hosts.
2026-04-15 10:55:00 -07:00
chrisfu
4b8da412a4 chore: refine ingress logic and add post-deploy endpoint summary
- Updated `init_kong.sh` to handle `include_gitea_host` flag for improved flexibility in Gitea ingress setup.
- Added comprehensive post-deploy endpoint summary in `deploy.sh` to display public services and external IPs.
- Enhanced kubectl command handling with role-specific context logic for better split-cluster support.
- Improved DB context logging across CNPG operations and milestones.
- Updated GKE configuration with new contexts and Grafana hostname.
2026-04-15 01:28:58 -07:00
chrisfu
a37015c887 chore: enhance Garage ILB endpoint resolution and persist config updates
- Added fallback logic to resolve Garage ILB hostname if IP is unavailable.
- Improved handling of `self.inputs` with prioritized merging for better automation.
- Updated config persistence to use `write_config` for milestones and repairs.
- Extended Garage ILB IP retry logic to 5 minutes for GKE provisioning delays.
2026-04-14 14:45:23 -07:00
chrisfu
5fabb94a19 chore: update Garage ILB logic for split-cluster GKE and GitLab object storage
- Changed ILB deployment context to DB cluster (`knoe-cnpg-0`) for GitLab object storage setup.
- Renamed service to `garage-s3-ilb` and updated related references.
- Enhanced logging for Garage ILB IP resolution with retry and error handling.
- Persisted resolved ILB endpoint to config files for improved reliability.
- Refined split-cluster Garage deployment workflows with clearer context management and debugging.
2026-04-14 14:17:41 -07:00
chrisfu
3db704bc52 chore: add support for resolving Garage ILB endpoint in split-cluster GKE setups
- Introduced `get_endpoint_ip` utility to fetch Garage ILB IPs across k3s, k3d, and k8s modes.
- Updated initialization to deploy Garage on the DB cluster when using split GKE clusters.
- Enhanced logic to persist resolved Garage ILB endpoints for GitLab object storage configurations.
- Added Redis master resolution and removed placeholder Garage endpoints during deployment.
- Updated post-init scripts to include Redis initialization alongside Kong and backup scripts.
2026-04-14 14:02:11 -07:00
chrisfu
fddaf80823 checkpoint: make node placement config-driven and add GitLab rerun fast-path
- remove hardcoded physical host assumptions in UI/init flows and rely on config-driven selectors\n- optimize GitLab reruns to skip unnecessary operator upgrades/long reconcile waits when unchanged\n- add and update regression/shell tests for fast-path and k8s context/ingress/garage behaviors

Co-authored-by: Junie <junie@jetbrains.com>
2026-04-14 06:43:37 -07:00
chrisfu
bfa712273e Implement split-cluster host ownership and context-safe deploy wiring
- move Supabase k8s ingress defaults to env-indexed api/db hostnames and remove legacy host bleed-through

- enforce explicit APP/DB kubecontext role validation across cluster ops and init scripts

- align env/default derivation and extend tests for hostname rendering and context checks

Co-authored-by: Junie <junie@jetbrains.com>
2026-04-12 21:00:20 -07:00
chrisfu
6741a684dd chore: add GKE auth plugin and kubeconfig handling for improved GKE bootstrap
- Added `gke-gcloud-auth-plugin` as a required dependency for `linux/apt` environments.
- Enhanced GKE context acquisition with writable kubeconfig target resolution.
- Improved failure reporting with detailed messages for GKE dependency and context issues.
- Expanded test coverage for scenarios involving missing auth plugins, kubeconfig errors, and GKE configurations.
2026-04-12 18:51:35 -07:00
chrisfu
797b566663 chore: refactor dependency resolution and auto-install logic
- Replaced static dependency configuration with dynamic resolution using `get_required_dependencies` and `get_required_dependency_ids`.
- Streamlined runtime checks, fallback behaviors, and handling of missing/optional dependencies.
- Hardened GKE context acquisition and validation for Kubernetes clusters.
- Enhanced test coverage for dependency resolution under various deployment modes (`dev`, `prod`, `gke`).
2026-04-12 18:36:39 -07:00
chrisfu
10bfc42bad chore: refactor dependency resolution and auto-install logic
- Replaced static dependency configuration with dynamic resolution using `get_required_dependencies` and `get_required_dependency_ids`.
- Streamlined runtime checks, fallback behaviors, and handling of missing/optional dependencies.
- Hardened GKE context acquisition and validation for Kubernetes clusters.
- Enhanced test coverage for dependency resolution under various deployment modes (`dev`, `prod`, `gke`).
2026-04-12 18:17:35 -07:00
chrisfu
cedcaae2c5 chore: update prole.cfg defaults for dev cluster, refine config overrides
- Updated default paths, namespaces, and cluster names for k3d/dev configuration.
- Added `skip_names` set to exclude `prod.cfg` and `gcp.cfg` from override processing.
- Refined init parameters for Supabase, Kubernetes, and database deployments to align with dev-specific settings.
- Enhanced test coverage for excluded config files (`prod.cfg`, `gcp.cfg`) within `test_prole_conf.py`.
2026-04-12 14:58:55 -07:00
chrisfu
090b0e882a chore: update prole.cfg defaults for dev cluster, refine config overrides
- Updated default paths, namespaces, and cluster names for k3d/dev configuration.
- Added `skip_names` set to exclude `prod.cfg` and `gcp.cfg` from override processing.
- Refined init parameters for Supabase, Kubernetes, and database deployments to align with dev-specific settings.
- Enhanced test coverage for excluded config files (`prod.cfg`, `gcp.cfg`) within `test_prole_conf.py`.
2026-04-12 13:26:59 -07:00
chrisfu
138a01c181 chore: update prole.cfg defaults for dev cluster, refine config overrides
- Updated default paths, namespaces, and cluster names for k3d/dev configuration.
- Added `skip_names` set to exclude `prod.cfg` and `gcp.cfg` from override processing.
- Refined init parameters for Supabase, Kubernetes, and database deployments to align with dev-specific settings.
- Enhanced test coverage for excluded config files (`prod.cfg`, `gcp.cfg`) within `test_prole_conf.py`.
2026-04-12 12:52:43 -07:00
chrisfu
65369811f7 Harden ingress targeting and normalize HOME paths
- enforce app-cluster-only rendering for public ingress hosts with DB-cluster guardrails\n- fix Supabase/GitLab/authority ingress host ownership and ingress-class safety checks\n- normalize persisted home-directory paths to /Users/chrisfu and update gke config defaults\n- add/adjust regression tests for ingress placement/hostname and cfg path normalization

Co-authored-by: Junie <junie@jetbrains.com>
2026-04-12 12:32:09 -07:00
chrisfu
e3c2e625f1 refactor(config): separate k3d k3s and gke config entrypoints
Rename env config files from conf/*/prole.cfg to conf/k3d.cfg, conf/k3s.cfg, and conf/gke.cfg. Update shell/Python loaders and etc/deploy scripts to resolve named configs cleanly while keeping legacy fallback behavior. Align k3s Ansible tasks, docs, and regression coverage with the new configuration layout.

Co-authored-by: Junie <junie@jetbrains.com>
2026-04-11 22:20:45 -07:00