The shape
componentRef: the related resource knows its Component, never the other way round.How it works
-
Component is an identity record
A name, an owning team, a repository and the template it was scaffolded from. It has no fields for deployments, databases or anything else a service might use.
kind: Component metadata: {name: payments} spec: owner: payments-team repository: {name: payments, visibility: public} scaffold: {template: golang-service, version: "0.13.0"} -
Everything else points back
A
Release, aDatabaseor aDatabaseSchemanames itsComponentinspec.componentRef. That reference is the source of truth; theplatform.taskapp.io/componentlabel used for querying is derived from it.kind: Release metadata: {name: payments-dev} spec: componentRef: {name: payments} environment: dev autoDeploy: {branch: main} -
Controllers look things up when they need them
Each controller reconciles only its own type. When it needs shared information it reads the
Component: release-operator, for example, looks up the repository to deploy from, and waits until theComponentis ready. schema-operator reads theComponentfor the repository and theDatabasefor where its credentials live. -
Readers discover, nobody registers
Backstage, Argo CD lookups and dashboards find everything about a service by
componentRefor the derived labels. Adding a new kind of capability doesn't change theComponentor any list of what it has.
The operators
component-operator
Gives a Component its GitHub repository (a Crossplane GitHubRepository) and a ScaffoldRequest, and owns both.
scaffold-operator
Renders a versioned template into the new repository as one commit, once. See Golden-path scaffolding.
release-operator
Turns a Release into the deployment files Argo CD reads, resolves its bindings, and follows main for auto-deploy. It writes to Git, never to a workload cluster.
schema-operator
Turns a DatabaseSchema into a pointer to the service's versioned migration package, which Atlas applies in the workload cluster. Also writes only to Git. See Database schemas.
Crossplane
Not one of the four, but the same pattern: GitHubRepository and Database are Crossplane APIs, shipped as versioned packages, that reconcile into GitHub and AWS.
Design choices
A small API, not a mega-CRD
One resource with fields for every capability would turn into an orchestration engine. Separate resources let a deployment, a database, its schema or a future queue evolve, version and fail independently.
Reference, don't register
A Component keeps no list of what belongs to it, so adding a capability never touches it, and nothing can drift out of sync.
Trade-off: no single object shows everything about a service; readers such as Backstage assemble the view.
Exceptions are written down
The repository and the scaffold request are owned by the Component, because a service without its repository isn't onboarded. Ownership means cascade deletion, so each exception is documented with its consequences before it's built.
Trade-off: deleting a Component doesn't remove its releases, databases or schemas; those are separate, deliberate changes.
The reference is the truth, labels are derived
Labels are only ever derived: component-operator stamps them on what it creates, and the Argo CD Application for every Release, Database and DatabaseSchema takes its label from componentRef. A hand-set label can't attach a resource to the wrong service.
Not built yet
- More capabilities. Queues, caches and buckets fit the same model as
Database; none exist yet.