ADR-0414: Sink family CRDs¶
Separate destination roles into typed, namespaced CRDs with a shared internal adapter.
Theme: 04 · Sink architecture · Status: Current
Context¶
Snapshot stores, databases, and event streams have different configuration and delivery semantics. A single public sink union made invalid field combinations easy and obscured those roles.
Decision¶
Kollect exposes three namespaced sink CRDs:
| CRD | Role | Admitted spec.type values |
|---|---|---|
KollectSnapshotSink |
Whole-state snapshots | git, gitlab, s3, gcs |
KollectDatabaseSink |
Queryable state | postgres, mongodb, bigquery |
KollectEventSink |
Change events | kafka, nats |
There are nine shipped backends. azureblob and http are reserved constants but admission rejects
them until a real backend and its tests ship. Parquet is an S3/GCS serialization format, not another
sink type.
All public sink resources are namespaced. A KollectClusterInventory references platform-owned
profiles and sinks by name plus namespace, as specified by ADR-0208.
Family specs normalize to the Go-only KollectSinkSpec adapter used by the registry, connection
probes, and export code. That internal name is not a Kubernetes kind.
Validation and reconciliation¶
- Admission allowlists types per family and rejects incompatible type-specific blocks and formats.
- Each family resource has a lightweight reconciler for optional connection tests and preview status; export remains inventory-driven.
KollectScopehas separate allowlists for snapshot, database, and event references.
Consequences¶
- Manifests communicate destination semantics and receive family-specific validation.
- Adding a backend requires implementation, registry wiring, admission, schema, probes, and tests; declaring a constant alone never makes a backend usable.
- Cluster inventories retain a single namespaced source of truth for shared configuration instead of duplicating cluster-scoped sink APIs.