design-proposal(compute-plane): deliver as an operator-owned extra module wrapping apps/kubernetes (supersedes #27)#33
Conversation
…ing apps/kubernetes Revise the ComputePlane proposal: deliver it as an operator-owned Tenant module (extra/computeplane) that wraps the existing apps/kubernetes chart with fixed values, instead of user-facing preset fields on kind: Kubernetes. Keeps the "not a new kind" conclusion from the #17 review and #26; supersedes the preset-field revision (#27). The underlying isolation mechanism (remote Flux apply, per-VM boundary, single-tenant) is unchanged. Assisted-By: Claude Signed-off-by: Andrei Kvapil <kvapss@gmail.com>
|
Warning Review limit reached
Next review available in: 33 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughChangesThe ComputePlane proposal now defines an operator-owned Tenant module wrapping ComputePlane delivery redesign
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Code Review
This pull request updates the design proposal for Cozystack's ComputePlane. Instead of introducing a new top-level kind or user-facing preset fields on kind: Kubernetes, the proposal now delivers ComputePlane as an operator-controlled Tenant module (packages/extra/computeplane) that wraps the ordinary apps/kubernetes chart with operator-fixed values. The reviewer identified an architectural contradiction in the packaging design: the proposal describes ComputePlane as a new Tenant module, but the illustrative HelmRelease points directly to the re-sourced apps/kubernetes chart, which would bypass the packages/extra/computeplane chart entirely. Clarification on whether the module chart acts as a wrapper or if it is redundant is requested.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| Reuse the `kubernetes` app as the substrate, unchanged. A ComputePlane is delivered as a new Tenant module, `packages/extra/computeplane`, of the same shape as `extra/etcd` / `extra/seaweedfs`. When a tenant has the module enabled, the tenant chart renders a `HelmRelease` (in the tenant namespace, on the management cluster) whose `chartRef` points at the **source-only** `apps/kubernetes` `ExternalArtifact`, carrying operator-fixed values: | ||
|
|
||
| ```yaml | ||
| # packages/extra/computeplane — rendered HelmRelease (illustrative) | ||
| apiVersion: helm.toolkit.fluxcd.io/v2 | ||
| kind: HelmRelease | ||
| metadata: | ||
| name: computeplane | ||
| namespace: tenant-<name> # management cluster, tenant namespace | ||
| spec: | ||
| chartRef: | ||
| kind: ExternalArtifact | ||
| name: cozystack-computeplane-application-kubevirt-kubernetes # apps/kubernetes, re-sourced (Design §2) | ||
| namespace: cozy-system | ||
| values: # operator-owned; the tenant cannot edit these | ||
| # hardened posture: restricted PSA + admission, deny egress → management kube-apiserver, | ||
| # scoped per-service egress only, addon set, GPU node groups, autoscaling bounds … | ||
| valuesFrom: | ||
| - kind: Secret # only the curated knobs the module chooses to surface | ||
| name: cozystack-values | ||
| ``` |
There was a problem hiding this comment.
There is an architectural contradiction in how the packages/extra/computeplane module is defined versus how it is deployed:
- The proposal states that "ComputePlane is delivered as a new Tenant module,
packages/extra/computeplane" (line 78). - However, the illustrative
HelmRelease(lines 81-98) has itschartRefpointing directly atcozystack-computeplane-application-kubevirt-kubernetes(which is the re-sourcedapps/kuberneteschart).
If the tenant chart's HelmRelease points directly to the re-sourced apps/kubernetes chart, the packages/extra/computeplane chart itself is bypassed and remains completely unused.
To resolve this, please clarify the packaging structure:
- Option A: The tenant chart renders a
HelmReleasepointing topackages/extra/computeplane, andpackages/extra/computeplaneacts as the wrapper that contains/renders theapps/kubernetesHelmReleaseor templates. - Option B: If the tenant chart directly releases
apps/kuberneteswith overridden values, then thepackages/extra/computeplanechart is redundant and only thecomputeplane-applicationPackageSource andcomputeplane-rdare needed.
…module A Tenant module is registered via an ApplicationDefinition, so ComputePlane does get its own apps.cozystack.io kind and API — the 'not a new top-level kind' claim carried over from #27 is inaccurate for this delivery. Reframe honestly: no new CRD, no new controller/reconcile path, and no fields on kind: Kubernetes; but a thin ComputePlane module-kind is registered like every other managed service. Assisted-By: Claude Signed-off-by: Andrei Kvapil <kvapss@gmail.com>
There was a problem hiding this comment.
Actionable comments posted: 6
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@design-proposals/compute-plane/README.md`:
- Line 151: Expand the “Connectivity to tenant services” section to define the
complete ComputePlane-to-service egress contract: identify the authorization
owner, specify how scoped CiliumNetworkPolicy resources are generated, bind
policies to workloads and tenant services, define revocation behavior, and
prevent bypass through direct service endpoints. Keep the contract explicit
about denying kube-apiserver access and allowing only authorized tenant
services.
- Line 211: Clarify the tenant/module deletion flow by naming the existing
component that owns and removes the module finalizer, and document the
fail-closed disable-then-deprovision sequence. Explicitly state that remote
HelmReleases are deleted before the ComputePlane or target cluster disappears,
and describe the behavior when cleanup cannot be confirmed so deletion cannot
hang or proceed prematurely.
- Line 136: Update the ComputePlane design and related deployment flow so
placement: ComputePlane app releases use Flux remote-cluster ServiceAccount
impersonation via spec.serviceAccountName and a least-privilege identity. Remove
references to computeplane-admin-kubeconfig and super-admin.svc for app routing,
while retaining the Kamaji admin kubeconfig only where administrative access is
explicitly required.
- Around line 207-208: Update the ComputePlane placement dependency
documentation and implementation guidance so the remote HelmRelease waits for
the module-level ComputePlane Ready condition, not merely the
computeplane-admin-kubeconfig Secret. Ensure Flux starts the remote release only
after PSA, admission, and egress hardening reconciliation completes, while
preserving the existing fail-closed behavior for missing or rotated credentials.
- Around line 92-98: Update the cozystack-values valuesFrom configuration to
enforce an explicit allowlist or schema for accepted Secret keys, ensuring
parent- or tenant-editable inputs cannot override hardened settings through
targetPath or Flux merge ordering. Keep only the curated knobs intended by the
module exposed, and preserve the operator-owned inline values as authoritative.
- Line 144: Update the ComputePlane deployment flow for ApplicationDefinition
placement so the target tenant namespace is pre-created with required PSA
labels, quotas, and ownership metadata before the HelmRelease can install
workloads. Do not rely solely on spec.install.createNamespace; either provision
the namespace explicitly or enforce equivalent admission gating before workload
creation.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 9a3c7d2e-1201-4964-b71f-8b232983157f
📒 Files selected for processing (1)
design-proposals/compute-plane/README.md
| - `computeplane-rd` → `path: system/computeplane-rd` with `install:` — the resource-definition chart carrying the module's `cozyrd` (its `ApplicationDefinition` / dashboard presentation and the tenant-values wiring), the same role `seaweedfs-rd` / `kubernetes-rd` play. | ||
|
|
||
| An empty string means disabled; a non-empty value names a ComputePlane **profile/class**. The profile — node groups, GPU types, Kubernetes version, autoscaling bounds — is defined **once** at the tenant/platform level and referenced by name. There is deliberately **no per-module `valuesOverride` blob**: that would re-create the two-sources-of-truth problem (the module spec living both in the profile and inline on the tenant). Keeping the module a bare profile reference makes the profile definition the single source of truth. | ||
| The tenant chart gains a `computePlane` toggle (a bool, or a profile name if the operator ships more than one module variant) alongside the existing module toggles; when set by the parent tenant, `packages/apps/tenant/templates/computeplane.yaml` renders the `HelmRelease` above. Kamaji writes the cluster's admin kubeconfig to `computeplane-admin-kubeconfig` (key `super-admin.svc`), which `placement: ComputePlane` apps consume (Design §4). |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Inspect the relevant section of the proposal
FILE="design-proposals/compute-plane/README.md"
wc -l "$FILE"
sed -n '120,170p' "$FILE"
# Find references to the kubeconfig and placement
rg -n "computeplane-admin-kubeconfig|super-admin\.svc|placement: ComputePlane|HelmRelease|serviceAccountRef|remote cluster" "$FILE"Repository: cozystack/community
Length of output: 16209
🌐 Web query:
Flux HelmRelease remote cluster serviceAccountName kubeConfig secretRef docs
💡 Result:
To deploy a HelmRelease to a remote cluster using Flux, you use the spec.kubeConfig field to reference a Kubernetes Secret containing the remote cluster's kubeconfig [1][2][3]. This configuration directs the Flux helm-controller to perform Helm operations on the target cluster instead of the local cluster where Flux is installed [2][4]. Key components for this setup include: 1. KubeConfig Secret: You must create a Kubernetes Secret in the same namespace as the HelmRelease [2][5][6]. This secret stores the kubeconfig file for the remote cluster, typically under the data key value (default) or as specified by the secretRef [2][4][5]. 2. HelmRelease Configuration: Include the kubeConfig field in your HelmRelease manifest to link to this secret [2][3]: spec: kubeConfig: secretRef: name: 3. Impersonation (Optional): You can optionally use spec.serviceAccountName to specify a ServiceAccount in the target cluster that the controller should impersonate [2][4]. When both spec.kubeConfig and spec.serviceAccountName are provided, the controller will act on behalf of that ServiceAccount within the remote cluster [2][4]. For this to work, the ServiceAccount must exist in the target cluster within a namespace that matches the namespace of the HelmRelease on the management cluster [2]. Important considerations: - The management cluster must have network access to the remote cluster's API server [5]. - If the remote API server uses self-signed certificates, you may need to configure the controller with the --insecure-kubeconfig-tls flag [5]. - The secretRef must reside in the same namespace as the HelmRelease object [2][5]. - If you do not specify a ServiceAccount, the controller will default to using the credentials provided in the kubeconfig [4]. Note that there is a distinction between the ServiceAccount used for impersonation on the remote cluster (spec.serviceAccountName) and the controller's own ServiceAccount [2].
Citations:
- 1: https://fluxcd.io/flux/components/helm/api/v2/
- 2: https://github.com/fluxcd/helm-controller/blob/main/docs/spec/v2/helmreleases.md
- 3: https://oneuptime.com/blog/post/2026-03-13-how-to-set-up-hub-and-spoke-mode-multi-cluster-with-flux-cd/view
- 4: https://github.com/fluxcd/helm-controller/blob/main/docs/spec/v2beta1/helmreleases.md
- 5: https://github.com/fluxcd/flux2-hub-spoke-example/blob/main/README.md
- 6: https://v2-0.docs.fluxcd.io/flux/components/helm/helmreleases/
Don't route app releases with the ComputePlane super-admin kubeconfig
placement: ComputePlane should use Flux remote-cluster ServiceAccount impersonation (spec.serviceAccountName) with a least-privilege identity, not computeplane-admin-kubeconfig/super-admin.svc. An admin kubeconfig gives a compromised chart the ability to create cluster-scoped resources and access other tenant secrets.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@design-proposals/compute-plane/README.md` at line 136, Update the
ComputePlane design and related deployment flow so placement: ComputePlane app
releases use Flux remote-cluster ServiceAccount impersonation via
spec.serviceAccountName and a least-privilege identity. Remove references to
computeplane-admin-kubeconfig and super-admin.svc for app routing, while
retaining the Kamaji admin kubeconfig only where administrative access is
explicitly required.
Source: MCP tools
| ### 4. `placement` routes a catalog app onto the ComputePlane | ||
|
|
||
| This is where the design leans entirely on an existing, proven mechanism. An application that must be isolated declares `placement: ComputePlane` on its `ApplicationDefinition`. When a tenant creates the app: | ||
| `ApplicationDefinition` gains `placement` = `ManagementPlane` (default) | `ComputePlane`. `ManagementPlane` deploys into the tenant namespace on the management cluster, as today. `ComputePlane` routes the generated `HelmRelease` onto the tenant's ComputePlane by injecting `spec.kubeConfig.secretRef` → `computeplane-admin-kubeconfig` (the module's fixed secret) and `spec.install.createNamespace: true`. Because the module is a single per-tenant enabler, `ComputePlane` resolves unambiguously to *that* tenant's cluster — no cluster name to thread through the app. |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift
🧩 Analysis chain
🏁 Script executed:
sed -n '120,170p' design-proposals/compute-plane/README.mdRepository: cozystack/community
Length of output: 7627
🏁 Script executed:
rg -n "createNamespace|targetNamespace|computeplane-admin-kubeconfig|Placement|ManagementPlane|ComputePlane" design-proposals/compute-plane/README.mdRepository: cozystack/community
Length of output: 19897
🌐 Web query:
Flux HelmRelease install.createNamespace targetNamespace namespace labels PSA quotas documentation
💡 Result:
Flux HelmRelease fields/behavior for: 1) install.createNamespace - In Flux HelmRelease v2, namespace creation is controlled by.spec.install.createNamespace (boolean). It “tells the Helm install action to create the HelmReleaseSpec.TargetNamespace if it does not exist yet”. On uninstall, “the namespace will not be garbage collected”. It defaults to false. [1][2] - Nuance: this only affects the Helm install action (not upgrades). [1][2][3] 2) targetNamespace -.spec.targetNamespace is optional and specifies “the namespace to which the Helm release is made”; it defaults to the namespace where the HelmRelease resource lives. [4][2] - Warning: changing.spec.targetNamespace after install will not move the already-installed release; instead it uninstalls and reinstalls in the new target namespace. [2] 3) namespace labels - Flux/helm-controller can apply labels/annotations to the Kubernetes objects it manages via: a) HelmRelease metadata (Kubernetes-native labels), b) HelmReleaseSpec.commonMetadata (“common labels and annotations that are applied to all resources”). [1] - Those labels are applied to the objects created by Flux/Helm (deployments, services, etc.), not automatically to the Namespace object itself via createNamespace. 4) PSA labels and quotas - Flux’s HelmRelease documentation does not state any built-in option that, when createNamespace is enabled, will automatically set Kubernetes Namespace PSA labels (pod-security.kubernetes.io/*) or create ResourceQuota/LimitRange objects for quotas. - PSA is enforced by Namespace-level labels, and quotas are represented by Kubernetes ResourceQuota/LimitRange API objects, which must be created as Kubernetes manifests (either by your GitOps namespace-manifest layer, and/or by templates in your Helm chart). [5][1][2] What this means for your specific query - install.createNamespace: use spec.install.createNamespace to ensure the target Namespace exists. [1][2] - targetNamespace: use spec.targetNamespace to choose where the Helm release is installed. [4][2] - labels / PSA quotas: you must manage Namespace labels for PSA and Namespace ResourceQuota/LimitRange objects separately from Flux’s createNamespace behavior; Flux’s HelmRelease createNamespace does not provide automatic PSA/quotas setup per the official docs. [5][1][2] If you tell me the PSA profile you want (e.g., baseline/restricted/audit/warn/enforce versions) and the quota numbers, I can generate a GitOps-ready set of Namespace + ResourceQuota/LimitRange manifests to pair with your HelmRelease.
Citations:
- 1: https://v2-0.docs.fluxcd.io/flux/components/helm/api/
- 2: https://github.com/fluxcd/helm-controller/blob/main/docs/spec/v2/helmreleases.md
- 3: Not creating new namespace with impersonation ServiceAccount even though it has proper role. fluxcd/helm-controller#338
- 4: https://fluxcd.io/flux/components/helm/helmreleases/
- 5: https://kubernetes.io/docs/concepts/security/pod-security-admission/
Pre-create the ComputePlane namespace. install.createNamespace: true only creates targetNamespace; it won’t apply PSA labels, quotas, or ownership metadata. Pre-create that namespace with the required controls, or gate namespace creation through admission before workloads start.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@design-proposals/compute-plane/README.md` at line 144, Update the
ComputePlane deployment flow for ApplicationDefinition placement so the target
tenant namespace is pre-created with required PSA labels, quotas, and ownership
metadata before the HelmRelease can install workloads. Do not rely solely on
spec.install.createNamespace; either provision the namespace explicitly or
enforce equivalent admission gating before workload creation.
Source: MCP tools
|
|
||
| The routing decision is driven by the `placement` enum on the `ApplicationDefinition` — `ManagementPlane` (default) applies into the tenant namespace on the management cluster as today; `ComputePlane` injects the ComputePlane `kubeConfig.secretRef`. The two values name the two symmetric planes. This keeps the routing policy declarative and out of per-app charts. | ||
| - **Remote apply (into the cluster).** For a `placement: ComputePlane` app, `cozystack-api` converts it to a `HelmRelease` on the management cluster carrying `spec.kubeConfig.secretRef` → `computeplane-admin-kubeconfig`; Flux applies the chart **into the ComputePlane**, never into the tenant namespace on management. This is exactly what the first revision implemented. | ||
| - **Connectivity to tenant services (`sandbox` data-plane contract).** A notebook/LLM/n8n flow needs the tenant's data ("my Jupyter → my managed Postgres"), which runs in the tenant namespace on the management cluster. The guarantee is "no kube-API access / no creds to escalate," **not** "no packets ever." No mesh is required: the ComputePlane's KubeVirt-VM node pods sit on the management Cilium pod network, so reachability is a **scoped per-service `CiliumNetworkPolicy`** — allow → the tenant's Postgres Service, deny → kube-apiserver (same shape as the existing `policy.cozystack.io/allow-to-apiserver` label). Per-service egress is narrower-by-construction than a node mesh — which matters because the consumer is untrusted code. |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Map the target file and nearby sections
wc -l design-proposals/compute-plane/README.md
sed -n '120,260p' design-proposals/compute-plane/README.md
# Find the referenced label / policy shape and any related contract text
rg -n "allow-to-apiserver|CiliumNetworkPolicy|network policy|egress|sandbox|tenant's Postgres|tenant namespace|open questions|untrusted code|direct-endpoint|workload-to-service|revocation|authorization" design-proposals/compute-plane/README.md design-proposals -SRepository: cozystack/community
Length of output: 50377
Define the ComputePlane→service egress contract.
The per-service egress path is still underspecified: who authorizes it, how the CiliumNetworkPolicy is generated, how workload-to-service binding and revocation work, and how direct-endpoint bypass is blocked all need to be nailed down before this sandbox contract is treated as complete.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@design-proposals/compute-plane/README.md` at line 151, Expand the
“Connectivity to tenant services” section to define the complete
ComputePlane-to-service egress contract: identify the authorization owner,
specify how scoped CiliumNetworkPolicy resources are generated, bind policies to
workloads and tenant services, define revocation behavior, and prevent bypass
through direct service endpoints. Keep the contract explicit about denying
kube-apiserver access and allowing only authorized tenant services.
| - **ComputePlane not ready when a `placement: ComputePlane` app is created** → the `HelmRelease` waits on the `computeplane-admin-kubeconfig` Secret; Flux surfaces not-ready, as with any dependency ordering. | ||
| - **kubeconfig Secret missing/rotated** → remote apply fails closed (no fallback to local apply); the security-correct behavior. |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Show nearby context around the cited lines
file="design-proposals/compute-plane/README.md"
wc -l "$file"
sed -n '170,240p' "$file"
# Search for the key terms across the repo
rg -n --hidden --glob '!**/.git/**' -e 'computeplane-admin-kubeconfig|placement: ComputePlane|hardening readiness|PSA|admission|egress policy|remote apply|ComputePlane' .Repository: cozystack/community
Length of output: 35012
🏁 Script executed:
#!/bin/bash
set -euo pipefail
file="design-proposals/compute-plane/README.md"
wc -l "$file"
sed -n '170,240p' "$file"
rg -n --hidden --glob '!**/.git/**' -e 'computeplane-admin-kubeconfig|placement: ComputePlane|hardening readiness|PSA|admission|egress policy|remote apply|ComputePlane' .Repository: cozystack/community
Length of output: 35012
Gate placement on full ComputePlane readiness, not just kubeconfig availability. The computeplane-admin-kubeconfig Secret only gives remote-apply credentials; it does not guarantee the ComputePlane’s PSA/admission/egress hardening has finished reconciling. Make placement: ComputePlane wait on a module-level Ready condition before Flux starts the remote release.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@design-proposals/compute-plane/README.md` around lines 207 - 208, Update the
ComputePlane placement dependency documentation and implementation guidance so
the remote HelmRelease waits for the module-level ComputePlane Ready condition,
not merely the computeplane-admin-kubeconfig Secret. Ensure Flux starts the
remote release only after PSA, admission, and egress hardening reconciliation
completes, while preserving the existing fail-closed behavior for missing or
rotated credentials.
| - **kubeconfig Secret missing/rotated** → remote apply fails closed (no fallback to local apply); the security-correct behavior. | ||
| - **`placement: ComputePlane` app but the module is disabled on the tenant** → reject at admission. Never climb to an ancestor's ComputePlane (Design §7). | ||
| - **GPU exhaustion** → cluster-autoscaler adds GPU nodes up to the configured `maxReplicas`; beyond that the workload pends. | ||
| - **Tenant / module deletion** → remote `HelmRelease`s must be deleted *before* the cluster is deprovisioned (a finalizer on the module blocks teardown until they're cleaned up) — otherwise Flux's HelmRelease finalizers block once the target API is gone. |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
sed -n '180,240p' design-proposals/compute-plane/README.mdRepository: cozystack/community
Length of output: 9979
🏁 Script executed:
rg -n "finalizer|teardown|deprovision|disablement|disable|module.*finalizer|HelmRelease" design-proposals/compute-plane/README.mdRepository: cozystack/community
Length of output: 7702
🏁 Script executed:
sed -n '1,180p' design-proposals/compute-plane/README.mdRepository: cozystack/community
Length of output: 26654
🏁 Script executed:
sed -n '240,360p' design-proposals/compute-plane/README.mdRepository: cozystack/community
Length of output: 2408
Clarify teardown ownership and ordering. The finalizer needs an explicit owner and removal path; otherwise module deletion can hang waiting for cleanup, or the ComputePlane can disappear before Flux deletes the remote HelmReleases. Spell out which existing component clears the finalizer and the fail-closed disable/deprovision sequence.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@design-proposals/compute-plane/README.md` at line 211, Clarify the
tenant/module deletion flow by naming the existing component that owns and
removes the module finalizer, and document the fail-closed
disable-then-deprovision sequence. Explicitly state that remote HelmReleases are
deleted before the ComputePlane or target cluster disappears, and describe the
behavior when cleanup cannot be confirmed so deletion cannot hang or proceed
prematurely.
The illustrative HelmRelease conflated the tenant-rendered module release with the cluster release the module renders, making extra/computeplane look bypassed. Show both levels — tenant chart → extra/computeplane (release computeplane-module) → re-sourced apps/kubernetes (release computeplane → the computeplane-admin-kubeconfig contract) — matching the implementation in cozystack/cozystack#3280, and pin the tenant toggle as the computeplane bool. Assisted-By: Claude Signed-off-by: Andrei Kvapil <kvapss@gmail.com>
What
Revises the ComputePlane design proposal. ComputePlane is delivered as a Cozystack-owned Tenant module (
packages/extra/computeplane) that provisions a hardenedkind: Kubernetesby wrapping the existingapps/kuberneteschart with operator-fixed values — not user-facing preset fields (isolationProfile×componentProfile) onkind: Kubernetes.Because a Tenant module is registered via an
ApplicationDefinition, ComputePlane does get its ownapps.cozystack.iomodule-kind and API (likeSeaweedFS,Kubernetesand every managed service). The accurate framing is therefore: no new CRD, no new controller/reconcile path, and no new fields onkind: Kubernetes— theComputePlanekind is a thin operator-owned wrapper over the unchangedapps/kubernetes.Why this supersedes #27
#27 put the posture on
kind: Kubernetesas user-facing fields. This revision moves it into an operator-ownedextramodule:appsvsextra(docs(development): explain why packages live in apps vs extra website#594): a ComputePlane is a per-tenant enabler switched on under the hood, not a first-class cluster the tenant orders/configures — exactly anextramodule (likeextra/etcd→apps/kubernetes).kind: Kubernetesuntouched: no fields added to the cluster app; the user still gets the same cluster — they just don't administer it and can change only the curated knobs the module exposes.Mechanism
Reuses the existing PackageSource "source-only chart" pattern (how NATS/SeaweedFS already ship): a
computeplane-applicationPackageSource re-sourcesapps/kubernetesas a source-onlyExternalArtifact, plus acomputeplane-rdresource-definition and theextra/computeplanemodule chart. Apps route in via a newplacement: ManagementPlane | ComputePlanefield onApplicationDefinition, injectingkubeConfig.secretRef → computeplane-admin-kubeconfigfor one-way remote Flux apply (unchanged mechanism from the merged first revision).Relationship to prior proposals
Departs from #26's "no new kind at all" (that is the #27 field model, set aside here) but keeps the #26 / #17-review objection to a heavyweight distinct kind: the
ComputePlanemodule-kind does not duplicate the cluster reconcile/RBAC path — it wraps the unchangedapps/kubernetes. Supersedes #27 (preset fields — see "Alternatives considered" for the full trade-off). The underlying isolation mechanism (remote Flux apply, per-VM boundary, single-tenant, scoped egress, cozystack-api visibility control) is unchanged.Closes #26
Summary by CodeRabbit