Invariants and boundaries

The safety properties, package layers, controller split, and status ownership model of OpenBao Operator.

Updated 9 August 2026 · 4 min read

On this page

The operator is a lifecycle supervisor for operator-owned OpenBaoCluster resources. It is not an import layer for arbitrary unmanaged OpenBao clusters.

Preserve these invariants

AreaInvariant
IdentityProvisioner and controller identities remain separate. Tenant access is explicitly provisioned, and Secret read or write access is derived from named resources rather than wildcard enumeration.
OwnershipThe operator owns generated configuration, identity, networking, and workload resources. Users change the custom resource or use a documented maintenance path instead of editing generated objects.
Production postureThe Hardened profile requires self-initialization, trusted TLS, and a non-static unseal path. OperatorManaged TLS is not a Hardened production trust model.
GuardrailsRequest-time authorization belongs to admission. Reconciliation rechecks the subset that must remain visible at runtime. Sensitive reconciliation pauses when required admission dependencies are unavailable.
IntegrationsGateway, ACME, audit storage, Kubernetes API, backup, and restore dependencies surface through explicit status and readiness contracts. The surrounding platform still owns the external systems.
LifecycleA new cluster starts with one pod. Restore remains an explicit destructive request. Backup, restore, and upgrade do not overlap on the same cluster.
Data consistencyOpenBao remains the source of truth for Raft snapshots, membership, and data consistency. The operator coordinates those operations instead of reimplementing the data plane.
Optional modulesCore APIs remain in openbao.org. Optional modules use separate API groups, may depend on stable core contracts, and must not become prerequisites of the core build or runtime.

internal/platform/hardenedcontract assigns stable rule IDs and enforcement ownership to Hardened guardrails. Moving a rule between admission and runtime enforcement is a contract change and requires the catalog, policy, runtime, and agreement tests to change together.

Follow the layer direction

LayerPackagesResponsibility
L0api/v1alpha1Declarative API data and validation markers
L1cmd/*, internal/platform/entrypointProcess startup and dependency construction
L2internal/controller/*Fetch, observe, delegate, patch, and requeue
L3internal/app/*Coordinate domain workflows and phase ordering
L4internal/service/*Own domain behavior such as workload, backup, restore, and upgrade
L5internal/port/*Stable interfaces and neutral contract types
L6internal/adapter/*Implement integrations and ports
L7internal/platform/*Cross-cutting reconciliation, status, security, logging, and ownership utilities

Dependencies point inward through the declared seams:

  • controllers normally call app facades and platform utilities;
  • app packages call services, ports, and platform utilities, but not adapters;
  • services may call ports, adapters, and platform utilities, but never controllers;
  • adapters may call ports and platform utilities, but never services or controllers;
  • ports never import adapters.

The generated architecture policy enforces package allowlists. A new import across these boundaries requires an explicit architecture decision, not only a compiling build.

Keep controller work separated

Controller pathOwnsReason for the split
OpenBaoCluster workloadCertificates, infrastructure, storage, initialization, Autopilot follow-up, and workload-side statusHigh-churn repair must continue while administrative work is waiting.
OpenBaoCluster AdminOpsBackup and upgrade orchestrationLong-running workflows need their own retry and status model.
OpenBaoCluster statusObservation, conditions, finalizer, and cluster deletionStatus aggregation and deletion must not be coupled to workload mutation.
OpenBaoRestoreValidation and destructive restore workflowRestore has its own request, status, finalizer, and operation-lock lifecycle.
OpenBaoTenant provisionerTenant onboarding and namespace-scoped guardrailsPrivileged namespace setup is a Day 0 responsibility, not a workload side effect.

Each controller delegates to its matching internal/app package. Application code sequences domain services; services own their write surfaces. Controllers must not accumulate broad business orchestration.

Treat status as owned planes

The OpenBaoCluster status is divided among server-side apply field managers.

PlaneOwns
Observed statusPhase, leader, replicas, current version, observed generation, and conditions
Workload statusInitialization, self-initialization, and workload progress
AdminOps statusBackup, upgrade, blue-green, requests, break-glass, and AdminOps state
Operation lockstatus.operationLock only

A writer applies only its plane. Within the shared AdminOps plane, a writer must read the latest object, mutate its concern, and apply the complete plane; omitting a sibling field with the same field manager can clear it. Read directly from the API after a write when the next decision depends on the committed value because the controller cache can lag.

Account for tenancy watch boundaries

Single-tenant mode can watch owned child resources in the operator namespace. Multi-tenant mode avoids cluster-wide child watches because those watches would require list and watch access across tenant namespaces. It relies on parent events, explicit progress requeues, retries, and periodic status refresh instead.

Adding multi-tenant child watches changes the RBAC and trust model. Review the permissions, controller registration, repair latency, and tests together.

Search the handbook

Try “install”, “threat model”, or “compatibility”.