Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
5bc3b09
chore: adr
j-zimnowoda Jul 7, 2026
9d5babb
Merge branch 'main' into gh-3428
svcAPLBot Jul 7, 2026
6a13db3
Merge branch 'main' into gh-3428
svcAPLBot Jul 9, 2026
0bdfdce
Merge branch 'main' into gh-3428
svcAPLBot Jul 10, 2026
735be4c
Merge branch 'main' into gh-3428
svcAPLBot Jul 13, 2026
b234a70
Merge branch 'main' into gh-3428
svcAPLBot Jul 15, 2026
d4d88f1
Merge branch 'main' into gh-3428
svcAPLBot Jul 16, 2026
2519589
Merge branch 'main' into gh-3428
svcAPLBot Jul 20, 2026
550e66f
Merge branch 'main' into gh-3428
svcAPLBot Jul 21, 2026
db1ec06
Merge branch 'main' into gh-3428
svcAPLBot Jul 21, 2026
00ee5dd
Merge branch 'main' into gh-3428
svcAPLBot Jul 22, 2026
2ba3f7f
Merge branch 'main' into gh-3428
svcAPLBot Jul 27, 2026
d33ea1a
Merge branch 'main' into gh-3428
svcAPLBot Jul 28, 2026
93cadf4
Merge branch 'main' into gh-3428
svcAPLBot Jul 28, 2026
3c34246
Merge branch 'main' into gh-3428
svcAPLBot Jul 28, 2026
ca0802e
Merge branch 'main' into gh-3428
svcAPLBot Jul 28, 2026
2ffba57
Merge branch 'main' into gh-3428
svcAPLBot Jul 28, 2026
3c13aab
Merge branch 'main' into gh-3428
svcAPLBot Jul 29, 2026
7c26bd2
Merge branch 'main' into gh-3428
svcAPLBot Jul 29, 2026
02d4638
Merge branch 'main' into gh-3428
svcAPLBot Jul 29, 2026
fa3e7b3
Merge branch 'main' into gh-3428
svcAPLBot Jul 29, 2026
e989c57
Merge branch 'main' into gh-3428
svcAPLBot Aug 4, 2026
5958175
Merge branch 'main' into gh-3428
svcAPLBot Aug 4, 2026
d10ea75
Merge branch 'main' into gh-3428
svcAPLBot Aug 4, 2026
69df2d8
Merge branch 'main' into gh-3428
svcAPLBot Aug 5, 2026
83c2f92
Merge branch 'main' into gh-3428
svcAPLBot Aug 6, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions CONTEXT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# APL Core

The platform layer that installs, configures, and reconciles all APL components on a Kubernetes cluster. It owns the values repo structure, the GitOps reconciliation loop, and the ArgoCD project model.

## Language

### GitOps

**Values repo**: The single git repository (`ENV_DIR`) that is the source of truth for all platform configuration, Helm values, and raw Kubernetes manifests. The apl-operator reads from and writes to it; ArgoCD reconciles it continuously.
_Avoid_: config repo, gitops repo, env repo

**Manifests directory**: The `env/manifests/` subtree of the values repo. The only place in the values repo where raw Kubernetes resource YAMLs live. Reconciled directly by ArgoCD, not by Helmfile.
_Avoid_: raw manifests, k8s manifests folder

**Namespace directory**: A subdirectory of `env/manifests/namespaces/` whose name matches a Kubernetes namespace. The apl-operator creates one ArgoCD Application per namespace directory that syncs its contents into that namespace.

**Global directory**: `env/manifests/global/` — contains cluster-scoped resources (CRDs, ClusterRoles). Synced by a single ArgoCD Application with no destination namespace.

**Operator-owned directory**: A namespace directory whose name starts with `apl-` and whose contents are written exclusively by the apl-operator program (e.g. `apl-secrets/`, `apl-users/`). Platform admins must not write to these.
_Avoid_: system directory, reserved directory

**Platform-admin-owned directory**: A namespace directory whose name starts with `apl-` and whose contents are written by human platform admins, not the apl-operator program. `apl-addons/` is the only current example. The operator bootstraps the directory but does not manage its contents.

### ArgoCD model

**AppProject**: An ArgoCD `AppProject` resource that scopes which source repos, destination namespaces/clusters, and Kubernetes resource types an Application is permitted to use.
_Avoid_: project, argo project

**Team project**: An AppProject named `team-{id}` scoped to a single team namespace. Generated by `charts/team-ns/templates/argocd/argocd-project.yaml`.

**apl-addons project**: The AppProject named `apl-addons` that governs Applications dropped by platform admins. Fully unrestricted: any source repo, any destination namespace, any cluster, any resource type.

**gitops-ns Application**: An ArgoCD Application named `gitops-ns-{namespace}` created by the apl-operator for each namespace directory. Syncs all manifests in that directory into the corresponding namespace with `prune: true` and `CreateNamespace: true`.
_Avoid_: parent app, bootstrap app

**App-of-Apps**: The pattern where one ArgoCD Application manages a directory of other Application CRs. The `gitops-ns-apl-addons` Application is an App-of-Apps: it syncs Application CRs into the `apl-addons` namespace, where ArgoCD picks them up via the "app in any namespace" feature.

**App in any namespace**: The ArgoCD feature (controlled by `application.namespaces` in `argocd-cm`) that allows ArgoCD to watch and reconcile Application CRs living in namespaces other than `argocd`.
41 changes: 41 additions & 0 deletions adr/2026-07-07-apl-addons-argocd-project.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# apl-addons ArgoCD project for platform-admin addon deployments

- Status: accepted

## Context and Problem Statement

Platform admins need a way to deploy arbitrary Kubernetes addons to any namespace without going through the team-scoped AppProject model. Every existing AppProject is locked to a single team namespace and forbids cluster-scoped resources. There is no supported escape hatch for platform admins who need to deploy, say, a CRD, a cross-namespace operator, or a Helm chart that spans multiple namespaces.

## Decision Outcome

A new `apl-addons` AppProject and namespace are introduced. Platform admins drop ArgoCD `Application` CRs into `env/manifests/namespaces/apl-addons/` in the values repo. The existing `addGitOpsApps` mechanism (which scans `env/manifests/namespaces/*` and creates one `gitops-ns-{namespace}` ArgoCD Application per directory) picks this up automatically and syncs those Application CRs into the `apl-addons` namespace. ArgoCD's "app in any namespace" feature then reconciles them under the `apl-addons` project.

### AppProject spec

The `apl-addons` AppProject is fully unrestricted:

- `sourceRepos: ['*']` — platform admins must be free to pull from any registry or git host
- `sourceNamespaces: ['apl-addons']` — only Application CRs living in the `apl-addons` namespace may reference this project
- `destinations: [{namespace: '*', server: '*'}]` — any namespace on any registered cluster
- `clusterResourceWhitelist: [{group: '*', kind: '*'}]` — cluster-scoped resources allowed
- `namespaceResourceBlacklist: []` — no restrictions

### ArgoCD "app in any namespace" wiring

`application.namespaces: apl-addons` is set in both `configs.cm` (argocd-cm) and `configs.params` (argocd-cmd-params-cm). The latter triggers the conditional extra verbs on the server ClusterRole in `charts/argocd/templates/argocd-server/clusterrole.yaml`.

### Protection via ValidatingAdmissionPolicy

The `apl-addons` AppProject carries no ArgoCD finalizer. Instead, a `ValidatingAdmissionPolicy` at the API-server level blocks DELETE operations on the AppProject. A finalizer can be stripped by anyone with sufficient kubectl access and then the project deleted; a VAP cannot be bypassed without first modifying the VAP itself, which requires a separate privilege escalation step.

### Naming convention deviation

[ADR-2026-06-25](2026-06-25-manifests-directory.md) establishes that directories with an `apl-` prefix under `namespaces/` are operator-owned (written by the apl-operator program, not by humans). `apl-addons/` deviates from this: the operator bootstraps the directory with a `.gitkeep` but its contents are written by human platform admins. The `apl-` prefix is retained to signal that this directory is privileged and not a regular user-owned namespace directory.

### Constraints not enforced by the AppProject

ArgoCD AppProject `destinations` is a whitelist only — there is no native destination blacklist. Platform admins must not target the `argocd` namespace as a destination; this is documented but not enforced. Application CRs must set `project: apl-addons`; if they do not, ArgoCD will reject them with an RBAC error (no operator-level pre-validation is added).

### ORCS registry policy

Pods deployed into the `apl-addons` namespace remain subject to the Kyverno ORCS registry enforcement policy. The unrestricted AppProject scope does not imply unrestricted image provenance.
1 change: 1 addition & 0 deletions adr/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ This log lists the architectural decisions for apl-core.
- [ADR-2026-06-25](2026-06-25-manifests-directory.md) - Manifests directory in the values repo
- [ADR-2026-06-25](2026-06-25-git-server-as-default-values-repo.md) - Lightweight git-server as the default values repository backend
- [ADR-2026-06-25](2026-06-25-git-credential-management.md) - Git credential management via Kubernetes Secret
- [ADR-2026-07-07](2026-07-07-apl-addons-argocd-project.md) - apl-addons ArgoCD project for platform-admin addon deployments

<!-- adrlogstop -->

Expand Down