ADR-0102: Prior art and OSS reference patterns¶
What we adopt, defer, and reject from Flux, external-secrets, kube-state-metrics, and Argo CD.
Theme: 01 · Foundations · Status: Current (living — update as we learn)
Context¶
Kollect occupies a niche: generic attribute-selection CRD + resource-selection CRD + aggregation +
multi-backend export (Git, object storage, Postgres, Kafka). No single OSS project combines all
of these. Doc-sync / Confluence publication is rejected (ADR-0702). Local shallow clones
under references/oss/ (read-only, never shipped) inform CRD ergonomics, informers, sinks, CI, and
metrics. This ADR records what we adopt, defer, and reject after sampling those repos.
Primary OSS references we actually use for design and CI patterns:
- Flux (source-controller, notification-controller) — static Provider, suspend, CEL validations
- external-secrets (ESO) — provider registry, Helm chart hygiene, status without secret bytes
- kube-state-metrics (KSM) — config-driven GVK → Prometheus; generic informers
- Argo CD — AppProject tenancy, Application status conditions
OSS comparison summary¶
external-secrets¶
| Pattern | Finding | Kollect stance |
|---|---|---|
| Provider plugin registry | SecretStoreProvider discriminated union + Go provider packages |
Adopt — KollectSink type + internal registry/factory (ADR-0402) |
| Cluster vs namespaced stores | ClusterSecretStore + namespace conditions |
Adopt (Phase 1) — KollectScope + optional watchNamespaces / tenantMode (ADR-0203) |
| Helm/CI | helm-docs, helm-unittest, values.schema.json, helm template → manifests |
Adopt — Helm chart day 1 (REQUIREMENTS.md) |
| Status content | Sync metadata only, never secret bytes | Adopt — aligns with ADR-0103 |
| Reconciled SecretStore | ESO reconciles stores for validation/status | Reject for Profile/Sink — follow Flux static config (ADR-0202) |
Flux (source-controller + notification-controller)¶
| Pattern | Finding | Kollect stance |
|---|---|---|
| Static Provider/Alert | No status subresource, no Provider reconciler | Adopt — KollectProfile, KollectSink static |
spec.suspend |
On all reconciled sources | Adopt — all reconciled Kollect kinds |
CEL XValidation |
Provider-type constraints, source-controller cross-field rules | Adopt — CRD OpenAPI + validating webhooks early |
| Receiver | Inbound webhook → enqueue work | Defer — reserve KollectReceiver |
| Interval reconciliation | Sources reconcile on spec.interval |
Reject as primary — collection is event-driven (ADR-0301) |
| CEL in runtime | commitStatusExpr on Provider |
Adopt — attribute predicates + future notification hooks |
Argo CD¶
| Pattern | Finding | Kollect stance |
|---|---|---|
| AppProject | Allowed repos, destinations, resource GVKs, RBAC roles | Adopt (Phase 1) — namespaced KollectScope (ADR-0203) |
| ApplicationSet generators | Matrix/git/cluster generators → many Applications | Defer — reserve KollectTargetSet |
| Status conditions | SetConditions with evaluated types, health aggregation |
Adopt — Ready/Synced/Degraded + observedGeneration |
| Application status size | Summaries + revision, not full manifest in status | Adopt — reinforces ADR-0103 |
kube-state-metrics¶
| Pattern | Finding | Kollect stance |
|---|---|---|
| CustomResourceStateMetrics | Config-driven GVK → Prometheus from informer paths | Adopt (early) — metrics testable from Phase 0/1 |
| Generic informers | Dynamic GVK registration, path-based label extraction | Adopt — validates KollectTarget engine |
| No persistence | Metrics served from cache, not etcd | Adopt — no inventory payload in status |
| Metrics-only scope | Observability, not stakeholder docs | Reject as sole solution — Kollect also exports to Git/docs |
Other cited projects (not primary clones)¶
- krateo resources-ingester — dynamic CRD discovery + informers → DB; informs engine, not CRD shape.
- crust-gather / influxdata/sinker — full-state gather / JSONPath mapping; ideas for aggregation.
Rejected¶
| Project | Reason |
|---|---|
| git-change-operator | Single-star OSS, unmaintained; not worth CRD comparison — Git sink ergonomics validated via Gitea/testcontainers and Flux/Git patterns instead |
Decision¶
Lean on OSS patterns rather than reinvent:
- Static config + reconciled workload split (Flux).
- Backend registry (ESO provider model, simplified).
- Tenancy boundary (Argo AppProject →
KollectScope). - Event-driven informers (KSM + controller-runtime).
- Status as summary (all mature refs).
- Helm/CI/docs toolchain (ESO + Flux release hygiene).
- Reject
KollectPublication/ Confluence doc-sync — templating and CMS push belong in external CI consuming Git or Kafka/Postgres export (ADR-0702). - Add Postgres + Kafka sinks as first-class export targets (ADR-0402).
Kollect's unique value is the combination plus stakeholder-facing export (Git, HTTP, Postgres, Kafka) with multi-cluster aggregation (ADR-0501) without per-cluster export noise.
Consequences¶
Positive¶
- Reduces design risk; every major choice has a production precedent.
- Clear "not invented here" boundaries speed implementation reviews.
- Dropping git-change-operator avoids chasing dead prior art.
Negative¶
- Mixing patterns from GitOps (Flux/Argo), secrets (ESO), and metrics (KSM) requires careful documentation so users understand Kollect is an inventory export operator, not GitOps or a CMS.
Open questions¶
- RESOLVED : Multi-tenant — both deployment models: default cluster-scoped manager
with namespaced
KollectScopetenancy, plus optional per-team installs via HelmwatchNamespaces[]andtenantMode(ESO scoped-controller pattern). Phase 1 priority — ADR-0203. - RESOLVED : Helm release sample — Flux
HelmReleasesummary profile default; values profile gated + redacted (ADR-0303).