# Progress

Every phase must ship at 90%+ coverage (enforced in CI).

    Phase  Name                           Status
    ─────  ─────────────────────────────  ───────
     0     Project skeleton               DONE
     1     K8s abstraction + fake client  DONE
     2     Apps + link + resolution       DONE
     3     Config                         DONE
     4     Deploy + build + PS (merged)   DONE
     5     Multi-cluster                  DONE
     6     Logs + exec                    DONE
     7     Addons                         DONE
     8     Networking                     DONE
     9     Domains + ingress + gateway    DONE
     9.6   Link restructure + open + E2E DONE
     9.7   Status + maintenance + cleanup DONE
    10     Plugins + addon versioning     DONE
    11     RBAC doctor enhancements       DONE
    12     Distribution                   DONE

NOTE: Original 15 phases (0-14) consolidated to 13 phases (0-12).
Phase 4 merged original Phases 4 (deploy), 6 (build-from-git), and 7 (PS).
Phase 13 (integration tests) absorbed into Phase 4 E2E tests.
Phase 9.6/9.7 were incremental releases before Phase 10.

Total tests: 1324 unit + 17 E2E suites (236 E2E tests on real K8s)
mypy --strict: 55 source files, clean
ruff check: clean


## Phase 0 — Project skeleton

    Delivered: pyproject.toml, branding.py, CLI entry point, models, exceptions.
    Demo: `pip install -e .` works, `kuberoku --version` prints version.


## Phase 1 — K8s abstraction + fake client

    Delivered: K8sClientProtocol, FakeK8sClient, label/resource helpers.
    Demo: Tests pass against a fake K8s — development works offline.


## Phase 2 — Apps + link + resolution

Beyond the original scope (apps + link + resolution), Phase 2 pulled forward
work from later phases to establish a solid foundation early:

    Core (original scope):
      - AppsService: create, destroy, info, list, rename
      - CLI: apps:*, link, unlink (ColonCommandGroup)
      - App resolution: --app flag → KUBEROKU_APP env → .kuberoku file
      - KuberokuFactory DI container

    Pulled from Phase 5 (Networking):
      - NetworkPolicy CRUD in K8s layer (protocol, real client, fake client)
      - 4 resource builders: deny, process-allow, addon-allow, external-allow
      - Deny policy on apps:create, cleanup on destroy, label update on rename
      - 8 contract tests for NetworkPolicy CRUD (fake + real K8s)
      - 10 resource builder tests

    Pulled from Phase 11 (Doctor + RBAC):
      - DoctorService with 6 diagnostic checks (API, namespace, CM, Secret,
        Deployment, NetworkPolicy CRUD)
      - CLI: `kuberoku doctor` with numbered pass/fail output
      - 17 tests (SDK + CLI, including partial failure and broken client tests)
      - RBAC enhancements (--fix, SelfSubjectAccessReview) deferred to Phase 11

    Pulled from Phase 12 (Distribution):
      - .github/workflows/tests.yml (lint + fake + k3d integration)
      - .github/workflows/compat.yml (kind weekly)
      - .github/workflows/release.yml (gate on tag v*)

    Pulled from integration tests:
      - RealK8sClient wrapper with error normalization
      - --backend flag (fake/real), tmp_namespace fixture
      - 32 contract tests across 6 resource types (all pass on both backends)

    Test count: 348 tests
    Verification: lint.sh 4/4 PASS, test.sh both backends PASS


## Phase 3 — Config

    Delivered:
      - ConfigService: set, get, unset (ConfigMap + Secret with --secret)
      - CLI: config, config:set, config:get, config:unset
      - Optimistic concurrency with resourceVersion on all CM/Secret updates
      - Rolling restart on config:set/unset was DEFERRED to Phase 4
        (requires Deployment to exist first)

    Files:
      sdk/config.py, cli/config.py
      tests/config/test_set.py, test_get.py, test_unset.py, test_list.py

    Test count: 448 tests (100 new)
    Demo: "I set DATABASE_URL and it's ready for my app to read at deploy time."


## Phase 4 — Deploy + build + PS (merged)

NOTE: This phase merged original Phases 4, 6, and 7 (minus logs/run).
The split between --image deploy, build-from-git, and PS operations
proved unnecessary — they share the same Deployment/Formation data model
and are better tested together. Logs and run remain for Phase 6.

    Delivered:
      - DeployService: deploy --image (create/update Deployments + Services)
        and build-from-git (git archive → docker build → push to registry)
      - ReleasesService: create (optimistic concurrency), list, info,
        rollback (creates NEW release with old images), prune
      - PsService: set_commands, get_commands, scale, stop, restart
        (delete pods), list_dynos, set_type (cpu/memory), get_type
      - BuildService: git archive → docker build → push. All subprocess,
        no shell=True. Supports HEAD, tags, commit SHAs.
      - RegistryService: auto-detect from cluster endpoint
        (EKS→ECR, GKE→AR, AKS→ACR). KUBEROKU_REGISTRY env override.
      - Procfile parser: TYPE: COMMAND format, comments, blank lines
      - Config restart: config:set/unset triggers rolling restart + release
        (deferred from Phase 3). --no-restart flag.
      - Rollout wait: --wait polls pods, detects CrashLoopBackOff,
        ImagePullBackOff, OOMKilled. --no-wait skips.
      - Process-allow NetworkPolicy: same-app ingress on declared ports
        (created during deploy when ports are present)
      - Resource format: `250m` = request only, `250m/500m` = request/limit
      - Port format: `8080/tcp` → containerPort dict

    CLI commands wired:
      deploy, releases, releases:info, releases:rollback, releases:prune,
      ps, ps:scale, ps:restart, ps:stop, ps:type, ps:set, ps:commands

    Bug fixes discovered during E2E testing:
      - cluster_endpoint was a stub returning "" — now reads from K8s client
      - build.py push/load ordering was backwards for colima + local registry
      - ps.restart() 404 race on already-terminated pods during rolling updates
      - Docker 28/29 multi-platform manifest push issue — E2E tests use
        FROM alpine:3.21 with RUN layer to create single-platform images

    Files (SDK):
      sdk/deploy.py, sdk/releases.py, sdk/ps.py, sdk/build.py,
      sdk/registry.py, sdk/procfile.py
    Files (CLI):
      cli/deploy.py, cli/releases.py, cli/ps.py
    Files (Tests — unit):
      tests/deploy/ (test_image, test_release_create, test_releases_list,
        test_rollback, test_releases_prune, test_procfile_deploy,
        test_wait, test_build, test_multi_app)
      tests/ps/ (test_set, test_commands, test_scale, test_restart,
        test_stop, test_list, test_type)
      tests/infrastructure/ (test_procfile, test_port_parsing,
        test_registry, test_cli_phase4)
    Files (Tests — E2E on real K8s):
      tests/e2e/test_hello_world.py   — 21 tests: full lifecycle
        (create app, deploy nginx, scale, restart, rollback, port-forward
        + curl HTTP, resource limits, destroy)
      tests/e2e/test_git_deploy.py    — 11 tests: git-deploy
        (HEAD, tag v1.0, raw commit SHA, registry push, pod verification,
        port-forward + curl, releases list)
      tests/e2e/test_network_isolation.py — 9 tests: cross-app isolation
        (two apps, deny-all + process-allow policies, same-app connectivity
        OK via exec+wget, cross-app blocked both directions)

    Test count: 639 total (598 unit + 41 E2E), all pass
    Verification: mypy --strict 38 files clean, ruff clean


## Phase 5 — Multi-cluster

    Delivered:
      - ClustersService: add, remove, list, switch, current, info
      - User config: ~/.kuberoku/config.yaml CRUD (config/user.py)
      - CLI: clusters, clusters:add, clusters:remove, clusters:switch,
        clusters:current, clusters:info, clusters:doctor, clusters:setup
      - Check registry (sdk/checks.py): 9 diagnostic checks shared by
        doctor + setup. 2 fixable (namespace_access, cni_enforcement).
      - Setup auto-fix: creates namespace, installs Calico if missing.

    Files:
      sdk/clusters.py, sdk/checks.py, config/user.py
      cli/clusters.py
      tests/clusters/ (test_add, test_remove, test_list, test_switch,
        test_info, test_checks, test_cli_clusters)
      tests/infrastructure/test_user_config.py


## Phase 6 — Logs + exec

    Delivered:
      - ServicesService: logs (with --follow), exec (interactive + one-shot)
      - CLI: services:logs, services:exec
      - Duration parsing for --since flag (e.g. "2h", "30m")

    Files:
      sdk/services.py (logs/exec methods)
      cli/services.py
      tests/services/ (test_logs, test_logs_follow, test_exec)
      tests/infrastructure/test_duration.py, test_cli_logs_exec.py
      tests/e2e/test_services_logs_exec.py


## Phase 7 — Addons

    Delivered:
      - AddonsService: create, destroy, list, info, backup
      - Addon definitions: postgres (StatefulSet + PVC), redis (StatefulSet + PVC)
      - AddonDef registry with per-type resource builders
      - Addon networking: addon-allow NetworkPolicy per addon
      - CLI: addons, addons:create, addons:destroy, addons:info,
        addons:backup, addons:expose, addons:connect, addons:exec

    Files:
      sdk/addons.py, addons/ (_types.py, postgres.py, redis.py)
      cli/addons.py
      tests/addons/ (test_cli_addons, test_expose, test_connect,
        test_expose_gateway)
      tests/e2e/ (test_addon_lifecycle)


## Phase 8 — Networking

    Delivered:
      - ServicesService: expose_on/off, connect, ports list/add/remove
      - Three-tier exposure: HTTP→Ingress, Non-HTTP→Gateway, Fixed→LB
      - GatewayService: port allocation 10000-10999 via ConfigMap
      - NetworkPolicy co-ownership (expose + domains as comma-separated owners)
      - CLI: services:expose:on/off, services:connect,
        services:ports, services:ports:add, services:ports:remove

    Files:
      sdk/services.py, sdk/gateway.py
      cli/services.py
      tests/services/ (test_expose, test_unexpose, test_connect,
        test_ports_list, test_ports_add, test_ports_remove,
        test_name_resolution, test_expose_gateway)
      tests/infrastructure/ (test_cli_networking, test_networking_resources,
        test_gateway)
      tests/e2e/ (test_expose_connect, test_multi_port)


## Phase 9 — Domains + ingress + gateway

    Delivered:
      - DomainsService: add, remove, list, clear, auto_domain
      - One Ingress resource per app (multi-rule, TLS, ingressClassName)
      - Ingress detection: detect_ingress_controller, detect_cert_manager,
        detect_lb_support. Environment-aware (k3s, Docker Desktop, kind, minikube).
      - 4 new doctor checks: ingress_controller, ingress_crud,
        cert_manager, lb_support (13 total)
      - Auto-domain on first web deploy (best-effort, never fails deploy)
      - CLI: domains, domains:add, domains:remove, domains:clear

    Files:
      sdk/domains.py, sdk/ingress.py, sdk/gateway.py
      cli/domains.py
      tests/domains/ (test_add, test_remove, test_list, test_clear,
        test_auto_domain, test_cli_domains)
      tests/clusters/test_checks_phase9.py
      tests/infrastructure/test_ingress_detection.py
      tests/contract/test_ingress_crud.py
      tests/e2e/test_domains_lifecycle.py


## Phase 9.6 — Link restructure + services:open + E2E

    Delivered:
      - Restructured link/unlink → apps:link:add, apps:link:remove
      - services:open: opens HTTP process URL in browser (4-tier resolution:
        custom domain → ingress → gateway → port-forward)
      - Shared E2E helpers (tests/e2e/helpers.py): make_real_factory,
        cleanup_namespace_fixture, skip_if_no_cluster, wait_for_pods_ready
      - 6 new E2E suites (config_lifecycle, link_lifecycle, doctor_setup,
        services_logs_exec, multi_port, expose_connect)

    Files:
      sdk/services.py (open method), cli/services.py
      sdk/apps.py (link_add/link_remove), cli/apps.py
      tests/apps/test_link.py, tests/services/test_open.py
      tests/e2e/helpers.py + 6 new E2E suites


## Phase 9.7 — Status + maintenance + NORTHSTAR cleanup

    Delivered:
      - apps:status: dashboard aggregator (AppStatus model) showing release,
        processes, config counts, addons, domains, maintenance state
      - apps:maintenance:on/off: all-process maintenance (scale to 0,
        save replicas in annotations, restore on off)
      - services:maintenance:on/off TYPE: per-process maintenance
      - MaintenanceInfo model with saved_replicas, services list, since timestamp
      - Storage: ConfigMap annotations ({domain}/maintenance, maintenance-since,
        maintenance-saved, maintenance-services)
      - 4 new E2E suites: test_apps_rename, test_releases_prune,
        test_clusters_config (no K8s needed), test_maintenance_lifecycle
      - Strengthened test_domains_lifecycle (auto-domain) and
        test_doctor_setup (all-checks verification)
      - NORTHSTAR cleanup: removed memcached (~13 refs), addons:restore,
        addons:logs. Rewrote sections 4.11 (maintenance) and 4.12 (status).

    New commands: apps:status, apps:maintenance, apps:maintenance:on,
      apps:maintenance:off, services:maintenance:on, services:maintenance:off

    Files:
      models.py (AppStatus, MaintenanceInfo)
      sdk/apps.py (status, maintenance_on/off/status)
      sdk/services.py (maintenance_on/off)
      cli/apps.py (status cmd, maintenance group)
      cli/services.py (maintenance group)
      tests/apps/ (test_status, test_maintenance)
      tests/services/test_maintenance.py
      tests/e2e/ (test_apps_rename, test_releases_prune, test_clusters_config,
        test_maintenance_lifecycle)

    Test count: 1217 unit + 16 E2E suites
    Verification: mypy --strict 51 files clean, ruff clean


## Phase 10 — Plugins + addon versioning

    Delivered:
      - PluginService: list, install, uninstall, search (PyPI)
      - Plugin loader: CLI plugin discovery via `kuberoku.plugins` entry_points
      - Addon plugin discovery via `kuberoku.addons` entry_points
      - Core command protection (plugins cannot shadow built-in commands)
      - Addon versioning: versions dict, default_version, migration_paths on AddonDef
      - addons:scale (resource scaling — cpu, memory)
      - addons:migrate (version migration with backup → PVC wipe → restore)
      - addons:migrate-rollback (rollback to previous version)
      - Migration paths: postgres sequential (15→16→17), redis any-to-any
      - CLI: plugins, plugins:install, plugins:uninstall, plugins:search
      - CLI: addons:scale, addons:migrate, addons:migrate-rollback, --version on create

    Files:
      plugins/loader.py, sdk/plugins.py, cli/plugins.py
      addons/_types.py (versions, default_version, migration_paths)
      addons/__init__.py (_discover_addon_plugins)
      addons/postgres.py, addons/redis.py (version definitions)
      sdk/addons.py (scale, migrate, migrate_rollback)
      cli/addons.py (scale, migrate, migrate-rollback commands)
      models.py (PluginInfo dataclass)
      tests/plugins/ (test_loader, test_cli_plugins, test_plugins_service)
      tests/addons/ (test_versioning, test_upgrade)
      tests/e2e/ (test_plugins, test_addon_versioning)


## Phase 11 — RBAC doctor enhancements

    Delivered:
      - RbacService: 8 required + 5 elevated RBAC rules
      - check_rbac() via SelfSubjectAccessReview (can_i with api_group + subresource)
      - generate_rbac_yaml() for Role + RoleBinding YAML output
      - 14th cluster check: rbac_permissions (added to doctor)
      - doctor --fix: generates YAML for missing permissions
      - FakeK8sClient: inject_denied_permission() for testing
      - RbacPermission, RbacReport, RbacFixYaml dataclasses

    Files:
      sdk/rbac.py, sdk/doctor.py, sdk/checks.py
      cli/clusters.py (--fix flag)
      k8s/protocols.py (can_i extended with api_group, subresource)
      k8s/client.py (can_i, exec_in_pod with stdin_data)
      tests/infrastructure/test_rbac.py, test_doctor.py
      tests/clusters/test_checks.py, test_checks_phase9.py
      tests/e2e/test_doctor_setup.py


## Phase 12 — Distribution

    Delivered:
      - PyInstaller spec (kuberoku.spec): one-file binary with certifi CA bundle
      - scripts/install.sh: POSIX shell installer (curl/wget, OS/arch detect, atomic)
      - scripts/install.ps1: PowerShell installer for Windows
      - scripts/test-install.sh: Multi-distro Docker test harness
      - release.yml: gate → publish (PyPI OIDC) + binaries (5 targets) + GitHub Release
      - tests.yml: smoke test (pip install + entry point) + installer test (shellcheck)
      - README.md: full rewrite with install guides, local cluster setup, command reference
      - CONTRIBUTING.md, CHANGELOG.md, issue templates

    Files:
      kuberoku.spec, scripts/install.sh, scripts/install.ps1, scripts/test-install.sh
      .github/workflows/release.yml, .github/workflows/tests.yml
      README.md, CONTRIBUTING.md, CHANGELOG.md
      .github/ISSUE_TEMPLATE/


## All phases complete

    All 13 phases (0-12) are done. The project is feature-complete per
    the NORTHSTAR spec and ready for first alpha release (0.1.0).
