Spec 0003a: Fix ESO CRD Ordering — Split ClusterSecretStore into Dependent Kustomization
- Save this spec to
.sdd/specification/spec-0003a-fix-eso-crd-ordering.mdin the repo. - Implement all changes described below.
- After completing all work, create a provenance record at
.sdd/provenance/spec-0003a-fix-eso-crd-ordering.provenance.md. See the Provenance Record section for the required format.
Problem
Section titled “Problem”Spec 0003 placed the ClusterSecretStore in the same Flux Kustomization as the ESO HelmRelease (k8s/external-secrets/). Flux’s kustomize-controller performs a server-side dry-run of ALL resources before applying ANY of them. The ClusterSecretStore CRD does not exist until ESO installs it via the HelmRelease, so the dry-run fails:
ClusterSecretStore/azure-keyvault dry-run failed: no matches for kind "ClusterSecretStore" in version "external-secrets.io/v1"This blocks the entire Kustomization — including the HelmRelease that would install the CRDs. It is a chicken-and-egg deadlock.
Solution
Section titled “Solution”Split the ClusterSecretStore into its own directory and Flux Kustomization with dependsOn, so it only applies after ESO is fully installed and CRDs are registered.
Current state (read these files before making changes)
Section titled “Current state (read these files before making changes)”| File | Current content |
|---|---|
k8s/external-secrets/clustersecretstore.yaml | ClusterSecretStore manifest — must be moved |
k8s/external-secrets/namespace.yaml | Namespace — stays |
k8s/external-secrets/helmrepository.yaml | HelmRepository — stays |
k8s/external-secrets/helmrelease.yaml | HelmRelease — stays |
k8s/flux-system/external-secrets-sync.yaml | Flux Kustomization for k8s/external-secrets/ — stays unchanged |
k8s/flux-system/kustomization.yaml | Resource list — needs new entry |
1. Move ClusterSecretStore to new directory
Section titled “1. Move ClusterSecretStore to new directory”Delete k8s/external-secrets/clustersecretstore.yaml.
Create k8s/external-secrets-store/clustersecretstore.yaml with the exact same content:
apiVersion: external-secrets.io/v1kind: ClusterSecretStoremetadata: name: azure-keyvaultspec: provider: azurekv: authType: ManagedIdentity vaultUrl: "https://kv-kevinryan-io.vault.azure.net/"2. Create Flux sync with dependsOn
Section titled “2. Create Flux sync with dependsOn”Create k8s/flux-system/external-secrets-store-sync.yaml:
apiVersion: kustomize.toolkit.fluxcd.io/v1kind: Kustomizationmetadata: name: external-secrets-store namespace: flux-systemspec: dependsOn: - name: external-secrets interval: 10m0s path: ./k8s/external-secrets-store prune: true sourceRef: kind: GitRepository name: flux-systemKey detail: dependsOn: [{name: external-secrets}] means Flux will not reconcile this Kustomization until the external-secrets Kustomization reports Ready=True. The external-secrets Kustomization becomes Ready only after the HelmRelease succeeds (ESO installed, CRDs registered). At that point, the ClusterSecretStore dry-run passes.
3. Update k8s/flux-system/kustomization.yaml
Section titled “3. Update k8s/flux-system/kustomization.yaml”Add external-secrets-store-sync.yaml to the resources list:
apiVersion: kustomize.config.k8s.io/v1beta1kind: Kustomizationresources: - gotk-components.yaml - gotk-sync.yaml - kevinryan-io-sync.yaml - brand-kevinryan-io-sync.yaml - aiimmigrants-com-sync.yaml - specmcp-ai-sync.yaml - sddbook-com-sync.yaml - distributedequity-org-sync.yaml - docs-kevinryan-io-sync.yaml - external-secrets-sync.yaml - external-secrets-store-sync.yaml4. No other changes
Section titled “4. No other changes”k8s/external-secrets/namespace.yaml— unchangedk8s/external-secrets/helmrepository.yaml— unchangedk8s/external-secrets/helmrelease.yaml— unchangedk8s/flux-system/external-secrets-sync.yaml— unchanged- No Terraform changes
Expected reconciliation flow after merge
Section titled “Expected reconciliation flow after merge”- Flux syncs
k8s/flux-system/— sees two Kustomizations:external-secretsandexternal-secrets-store external-secretsKustomization applies: namespace, HelmRepository, HelmRelease — all standard resources, dry-run passes- Helm controller installs ESO chart — pods start, CRDs are registered
external-secretsKustomization becomesReady=Trueexternal-secrets-storeKustomization is now eligible (dependency satisfied)- ClusterSecretStore dry-run passes (CRD exists), resource is applied
- ClusterSecretStore connects to Key Vault via managed identity
Provenance Record
Section titled “Provenance Record”After completing the work, create .sdd/provenance/spec-0003a-fix-eso-crd-ordering.provenance.md with the following structure:
# Provenance: Spec 0003a — Fix ESO CRD Ordering
**Spec:** `.sdd/specification/spec-0003a-fix-eso-crd-ordering.md`**Executed:** <timestamp>**Agent:** <agent identifier if available>
## Actions Taken
Chronological list of every action performed (files created, files modified, files deleted, commands run).
## Decisions Made
Any decisions the agent made during execution that were not explicitly specified in the spec. For each:
| Decision | Options Considered | Chosen | Rationale ||----------|-------------------|--------|-----------|| ... | ... | ... | ... |
If no autonomous decisions were required, state: "No autonomous decisions were required — all actions were explicitly specified in the spec."
## Deviations from Spec
Any points where the agent deviated from the spec, and why. If none, state: "No deviations from spec."
## Artifacts Produced
| File | Status ||------|--------|| ... | Created / Modified / Deleted |
## Validation Results
Results of each validation step from the spec (pass/fail with details).Validation steps
Section titled “Validation steps”After completing all work, confirm:
- This spec has been saved to
.sdd/specification/spec-0003a-fix-eso-crd-ordering.md k8s/external-secrets/clustersecretstore.yamldoes NOT exist (deleted)k8s/external-secrets/contains exactly 3 files:namespace.yaml,helmrepository.yaml,helmrelease.yamlk8s/external-secrets-store/clustersecretstore.yamlexists with correct content (authType: ManagedIdentity,vaultUrl: "https://kv-kevinryan-io.vault.azure.net/")k8s/flux-system/external-secrets-store-sync.yamlexists withdependsOn: [{name: external-secrets}]andpath: ./k8s/external-secrets-storek8s/flux-system/kustomization.yamlincludes bothexternal-secrets-sync.yamlandexternal-secrets-store-sync.yamlk8s/flux-system/external-secrets-sync.yamlis unchanged from its current content- No Terraform files were modified
- The provenance record exists at
.sdd/provenance/spec-0003a-fix-eso-crd-ordering.provenance.mdand contains all required sections - All files (spec, K8s manifests, provenance) are committed together