A product can wait for an externally owned SQL, Document or Graph engine and its published application credentials. The controller observes readiness; the database operator creates, upgrades, backs up and deletes the source. Product workloads consume the connection Secret directly.
Enable both provisionedSources.enabled=true and engineProviders.enabled=true in the Helm chart.
The manager settings are PROVISIONED_SOURCES_ENABLED=true and ENGINE_PROVIDERS_ENABLED=true.
The OpenFeature flags provisioned-sources and engine-providers default off. A declared engine
stays unready while either gate is off, and disabled gates perform no source or Secret reads.
Apply the release's CRD before upgrading an existing chart installation, as described in the README.
spec.source.engine uses the engine-provider/v1 contract. Admission binds each supported selection
to one adapter and resource API. The runtime resolver repeats that check before any reads.
| Selection | Adapter | Referenced resource | Connection publication |
|---|---|---|---|
| Engine omitted | crossplane/v1 |
Namespaced custom resource | Matching writeConnectionSecretToRef, owned by that resource |
sql / native |
cnpg/v1 |
postgresql.cnpg.io/v1 Cluster |
Operator-generated <cluster>-app Secret, owned by the current Cluster UID |
document / native |
percona-mongodb/v1 |
psmdb.percona.com/v1 PerconaServerMongoDB |
Explicit custom-user password Secret, published with the current source UID |
graph / native |
arangodb/v1 |
database.arangodb.com/v1 ArangoDeployment |
Independently published read-only application password, with v1 metadata and current source UID |
document / cnpg-hybrid |
cnpg-hybrid/v1 |
postgresql.cnpg.io/v1 Cluster |
Dedicated JSONB reader publication, current source UID and generation |
graph / cnpg-hybrid |
cnpg-hybrid/v1 |
postgresql.cnpg.io/v1 Cluster |
Dedicated AGE reader publication, current source UID and generation |
SQL uses the native adapter; a SQL hybrid selection is unsupported. Unknown versions, contradictory adapters and other resource APIs are rejected at admission. SQL requires its generated application Secret name; Document and Graph publication receive additional runtime checks against the externally owned source. Existing untyped Crossplane products retain their contract.
The SQL example refers to a Cluster named warehouse in
products. Install and configure CloudNativePG independently, including storage, database ownership,
network access, backups and retention. Deploy the product's query workload and public contract
independently; declaring output URLs does not create them.
The cnpg/v1 adapter requires:
- exactly one
Ready=Truecondition; - positive
spec.instances, with matchingstatus.instancesandstatus.readyInstances; - matching, nonempty
status.currentPrimaryandstatus.targetPrimary; - current explicit observed generations; an omitted generation follows CNPG's condition contract;
- a non-deleting generated application Secret whose owner reference matches the current Cluster's UID, name, API group and kind.
The adapter accepts the operator-generated application Secret only. A supplied
spec.bootstrap.initdb.secret, spec.bootstrap.recovery.secret or
spec.bootstrap.pg_basebackup.secret is outside this publication contract and reports
ConnectionPublicationUnsupported. Application workloads use the generated credentials directly;
the controller never requests their values. See CloudNativePG's application connection guide
and Cluster API reference.
SourceReady refreshes independently of other dependencies. Missing sources, publication ownership
mismatches, lost permissions, unready replicas and deletion produce stable reasons without copying
provider messages into product status. Aggregate readiness also requires the product's other
declared dependencies. Typed observation uses a fixed resource mapping, fresh exact-name reads, a five-second deadline and
30-second polling; unchanged observations do not rewrite status.
After a selected provider completes, cancellation or deadline expiry makes the
observation unavailable, even if the final API read returned a healthy object.
This completion check also applies to the legacy Crossplane adapter.
Engine and legacy source readers negotiate only single-object partial metadata for application Secrets.
Servers that cannot provide that representation fail observation with SourceUnavailable;
the client never negotiates a full-Secret fallback. Kubernetes still authorizes the complete
Secret GET, so exact-name RBAC remains required. Normal source-object reads retain their full
operator status representation.
CloudNativePG may omit observed generations. In that case the observer cannot establish that status reflects the latest spec. Control-plane readiness and Secret ownership do not prove Secret contents, database authentication, query availability, backups or extension support. The registry publishes neither source references nor credentials.
The hybrid products refer to an independently operated
CloudNativePG Cluster. Document uses JSONB; Graph uses the owned PostgreSQL / AGE image.
Both require the native Cluster readiness checks, an exact supported immutable image in
spec.imageName, and the same currently running image reported in status.image. Catalog
indirection cannot establish this profile. Document also supports the upstream minimal PostgreSQL
17.11 Trixie index. Graph requires the owned AGE 1.7.0 profile and age in the operator's
spec.postgresql.shared_preload_libraries array. A free-form parameter or invented status
field does not satisfy the declared preload profile.
The controller neither initializes the extension nor verifies its installation by connecting.
The supported immutable profiles are:
- Core JSONB:
ghcr.io/cloudnative-pg/postgresql:17.11-minimal-trixie@sha256:d78e771decf39071aa8bfb96684e8b7e6e5f3c6e00a945404249756db2c6c712. - JSONB or AGE:
ghcr.io/devantler-tech/data-product-controller-postgresql-age:17.11-age1.7.0-dpc1.16.0@sha256:0b6e2d75d5551586570979d767a28b255953c2ee86820409ad9fe37d91ce3fa8.
Both the version tag and digest are required: CloudNativePG uses the tag to detect upgrades,
while the digest fixes the image bytes. Digest-only references, other tags, digests and repositories
are unsupported, including newer owned images until their profile is validated.
Real PostgreSQL acceptance uses CloudNativePG 1.30.1; source observation does not verify the
installed operator binary. The owned image's v1.16.0 source is
04d6ec7b517b59e6d2cffcab484f8a42a711c1ce, signed by the immutable publisher
86f0f95e5ac93ec914f5717f561af878b7d09bf1 under the verification procedure in the image guide.
Choose the hybrid provider for PostgreSQL storage and operating conventions, with these explicit capability differences:
| Model | Hybrid query capability | Native provider difference |
|---|---|---|
| Document | JSONB values in PostgreSQL tables, with a publisher-selected schema, table and column | It does not provide MongoDB wire-protocol compatibility, MongoDB operators or native document command semantics |
| Graph | AGE Cypher over graph tables in the selected PostgreSQL database | It does not expose ArangoDB AQL or its native graph/document APIs |
| Lifecycle | Both models share the independently operated CNPG source, storage and failure domain | Dedicated native engines have their own operators, configuration and source lifecycle |
Query contracts describe each independent application interface; selecting a model does not make native and hybrid query languages interchangeable. AGE requires supported preload configuration, extension initialization in the selected database and a planned restart for existing sources. The owned image guide describes those steps. Real acceptance verifies both query languages and reader roles; metadata-only observation cannot establish them.
Use dedicated reader Secrets. Bootstrap-owner, superuser, replication, server, CA and client credential names are rejected before any reads. Configured superuser, bootstrap application and certificate references are also excluded after reading the Cluster and before reading publication metadata. An independent publisher verifies application queries and effective read-only grants, then adds metadata and the current Cluster owner reference:
metadata:
annotations:
data.devantler.tech/cnpg-hybrid-publication: v1
data.devantler.tech/cnpg-hybrid-access: read-only
data.devantler.tech/cnpg-hybrid-source-generation: "3"
data.devantler.tech/cnpg-hybrid-database: catalog
data.devantler.tech/cnpg-hybrid-user: document_reader
data.devantler.tech/cnpg-hybrid-capability: jsonb/v1
data.devantler.tech/cnpg-hybrid-schema: public
data.devantler.tech/cnpg-hybrid-table: documents
data.devantler.tech/cnpg-hybrid-column: payloadFor Graph, use capability age/1.7.0 and data.devantler.tech/cnpg-hybrid-graph: lineage.
Identifiers contain 1–63 lowercase ASCII letters, digits or underscores and start with a letter.
Privileged PostgreSQL and CNPG users are unsupported. A changed Cluster generation requires a fresh
publication after query verification; recreation also requires the new source UID. Rotation at the
same publication name uses the application workload's projected password without a controller restart.
The hybrid observer Role grants only the named Cluster and dedicated publication GETs. Metadata declares publisher intent; it does not prove Secret contents, effective privileges, query health, graph existence, backups or PostgreSQL extension compatibility.
Apply the observer Role example in the product namespace.
Adjust its controller ServiceAccount and namespace for your installation. It grants get only on
warehouse and warehouse-app; the chart does not grant database or Secret access.
The manager requests PartialObjectMetadata for the Secret and bypasses caches. Kubernetes RBAC
authorizes a whole Secret get, even when the request negotiates metadata only, so keep resource
names and namespaces explicit. No list, watch or mutation grant is needed for external sources.
The Document product selects the percona-mongodb/v1
adapter. Install Percona Operator for MongoDB 1.23.0 independently and use spec.crVersion: 1.23.0.
That declaration does not verify the installed operator image. The initial supported profile is
one managed, unpaused, unsharded replica set, with positive size and no arbiter, non-voting, hidden
or external members.
status.state must be ready, and status.size and status.ready must equal the requested size.
An explicit status.observedGeneration must be current. Percona's published status contract may
omit it; in that case the observer cannot establish that status reflects the latest spec.
The referenced password Secret must match exactly one explicit spec.users[].passwordSecretRef.name.
The selected custom user must declare only built-in read roles on non-system databases. Its
authentication database may be admin; $external authentication is unsupported. For example:
spec:
crVersion: 1.23.0
replsets:
- name: rs0
size: 3
users:
- name: catalog-reader
db: admin
passwordSecretRef:
name: documents-reader
key: password
roles:
- name: read
db: catalogThis fragment shows the observation fields, not a complete database installation. An independent
publisher must bind documents-reader to the current PerconaServerMongoDB through an owner
reference with API psmdb.percona.com/v1, kind, name and UID. This is a controller publication
requirement; Percona documentation does not promise that ownership automatically. Do not modify
operator-managed system or connection-string Secrets to satisfy it. Admission rejects the default
system Secret. Initial runtime validation also rejects it as SourceInvalid, before any reads.
Configured operator credential roles under spec.secrets and spec.vault, internal system Secrets, operator-generated passwords,
connection-string Secrets, system accounts, duplicate usernames, multiple users sharing the password
Secret, custom roles and privileged roles report ConnectionPublicationUnsupported. Reserved publication names follow
Percona's connection-Secret naming contract;
a manual password binding cannot reuse another declared user's generated connection-Secret name.
The supported operator's Secrets and Vault API sections
define these credential roles; their references are checked before any application Secret metadata read.
Apply the Document observer Role, adjusting its ServiceAccount for your installation. It grants only the named source and password Secret GETs. The application workload consumes its credentials independently; the controller requests only Secret metadata. Declared read roles and publication ownership do not prove effective privileges, password validity, database access or query availability. See Percona's custom-user guide, status contract and system-user guidance.
The Graph product selects arangodb/v1. Its query URL
and OpenAPI document describe a separately operated workload; DPC does not create that workload
or send AQL queries. Install the ArangoDB operator independently, using the
1.4.5 API.
The real-provider acceptance profile requires spec.mode: Single, explicit spec.single.count: 1,
enabled authentication and the verified release index
sha256:4bc086d5050ca7ea11c6d00a36d8b910c838bb54ad553f8c1b715769d3499bcf.
The index is accepted with the 3.12.12 tag or without a tag, using arangodb or
docker.io/library/arangodb. The original tag-only declaration arangodb:3.12.12 retains its
previous non-enterprise binary-metadata requirement; it does not identify the immutable profile
tested here. Other digests, registries, image repositories and contradictory tags are unsupported.
Single mode provides no high availability.
The live typed specification checksum must match both status.acceptedSpecVersion and
status.appliedVersion. DPC does not apply defaults before hashing: the operator hashes the raw
spec and separately stores defaulted status.accepted-spec. Hashing preserves the pinned
operator's Kubernetes 0.33 PVC metadata encoding, including a null empty creation timestamp;
the controller's newer Kubernetes library otherwise omits that field. The accepted specification must also
retain exactly the declared image, Single/count-one profile and a resolved authentication Secret;
contradictory status does not establish readiness. Ready, SpecAccepted, UpToDate,
BootstrapCompleted and upstream's misspelled BootstrapSucceded conditions must be True.
Deployment phase must be Running, with exactly one Created and Ready Single member, a modern
Pod name/UID, matching image declarations and reported desired/running image IDs, and ArangoDB
3.12.12 versions. The verified official immutable index reports an Enterprise binary marker;
both current and member observations must match that actual binary profile. The marker does not
establish license entitlement. Update,
upgrade, Secret-change, pending update, member-restart and member-termination states withdraw readiness,
even when the departing member still reports Ready. Missing,
unknown, malformed or duplicate conditions cannot establish readiness. Condition hashes,
transition timestamps, historical SpecPropagated and Pod-spec checksums are not freshness markers.
An independent publisher owns application setup and the password Secret. The pinned bootstrap
validator accepts only root accounts. The publisher must create a dedicated non-administrator
user, deny _system and database wildcard access, grant ro on the application database, deny
collection wildcard access and grant ro on every named vertex/edge collection. Assign explicit
none grants to all other application collections. ArangoDB's database ro grant otherwise
supplies read access when no specific collection grant exists; a collection wildcard none
does not override it. The publisher must install a specific denial before adding an unpublished
collection, and keep system collections outside the published query contract. It publishes the
password for consumption directly by the query workload. DPC sees only this public metadata:
metadata:
name: lineage-reader
namespace: products
annotations:
data.devantler.tech/arango-publication: v1
data.devantler.tech/arango-user: catalog-reader
data.devantler.tech/arango-database: catalog
data.devantler.tech/arango-graph: lineage
data.devantler.tech/arango-access: read-only
data.devantler.tech/arango-collections: products,relations
ownerReferences:
- apiVersion: database.arangodb.com/v1
kind: ArangoDeployment
name: lineage
uid: <current-source-uid>Under v1, read-only declares this grant profile, including no other positive collection grants
and explicit denials for unpublished application collections. This is publisher intent, not
proof that future collections are automatically isolated. See the upstream
permission resolution rules.
Identifiers start with an ASCII letter followed by at most 63 ASCII letters, digits,
underscores or hyphens. Collections form a comma-separated list of 1–64 unique identifiers
without whitespace or wildcards. Root, operator, internal and backup users are rejected in any
letter case. System names, unsupported versions and writable declarations are rejected.
The selected Secret must match the current source owner. Default/configured JWT, root-password
and operator credential publications are unsupported. Do not relabel operator Secrets as application publications.
Apply the Graph observer Role, adjusting its
ServiceAccount binding. It permits only exact-name GETs on lineage and lineage-reader in
products. Kubernetes authorizes a whole-Secret GET despite metadata negotiation.
These checks establish operator-reported current-spec readiness and publisher intent. They do not verify the installed operator binary, immutable running image, credential values, effective permissions, graph existence, queries, backups or distribution support. ArangoDB's Community binary terms restrict deployment uses; this adapter neither deploys nor licenses the database. Independently verify the applicable edition and terms. The required real Graph acceptance separately exercises the pinned operator and authenticated traversal; its current-head run must pass.
Creation and deletion stay with the operator. A missing source reports SourceNotFound; deleting
one reports SourceDeleting. Recreating it changes its UID, so an old Secret cannot satisfy
publication ownership. Credential rotation at the same Secret name does not require a DataProduct
change or copy values into status. Removing the source declaration or deleting the DataProduct
leaves the source and Secret independently owned; the controller adds no finalizers or owner references.
The hosted source-observation suite exercises admission, scoped permissions, both gates, readiness loss/recovery, publication ownership and retention using synthetic SQL, Document and Graph status fixtures. It does not install database operators or prove database availability. The separate required real Document acceptance installs Percona and exercises authenticated queries, effective privileges, rotation, outage recovery and retained data. Its current-head run must pass; synthetic observer results cannot replace that evidence. The required real Graph acceptance applies the same boundary to ArangoDB traversal, effective grants and retained source recovery. The remaining real provider matrix is tracked in #38, and released deployment acceptance is required before retiring the gate in #128.