Draft, not final
v1beta1 does not exist yet. These pages describe the changes proposed for it in docuconf-go pull requests #27, #28, #29 and #30, which are not merged. Anything here can still change. Keep contracts on v1alpha1 until the format freeze lands. See the versioning policy and the draft SPEC.md.
Outputs
A contract is written once, by the app's SDK, and everything else is generated from it. That is what keeps every tool in agreement: the Helm schema, the CUE validation, the rendered pod and the SDK's boot check all read the same document, so none of them can drift from the code.
Generation targets
| Output | Artifact | Produced by | Consumed by | Status |
|---|---|---|---|---|
| Contract (CUE) | contract.cue | Every language SDK’s export | The platform: docuconf CLI, CUE, Crossplane, Helm | Implemented |
| Contract (JSON) | contract.json | cue export, docuconf helm | Tools without CUE; the Helm library chart (files/docuconf/contract.json) | Implemented |
| Validation report | one line per problem; exit code 1 | docuconf vet, #Validate | CI before merge; the Crossplane function at composition | Implemented |
| Pod configuration | env, volumes, volumeMounts, configMaps, restartTriggers, podAnnotations, podLabels | docuconf render, #Render | Deployments and other pod templates | Implemented |
| Helm values schema | values.schema.json + files/docuconf/contract.json | docuconf helm, #HelmValuesSchema | Helm 3 and 4 on lint, template, install and upgrade | Implemented |
| Helm library chart | docuconf.env, .volumes, .volumeMounts, .configMaps, .reloaderAnnotations, .podAnnotations, .podLabels | helm/docuconf chart | App charts | Implemented |
| Boot-time violation report | all violations with stable error codes; /dev/termination-log | Each language SDK at startup | Operators, kubectl describe pod | Implemented |
| Config-file overlay | a host-format file (appsettings.Production.json, application.yml, Config.toml) in a ConfigMap | docuconf render and the Helm library chart, for variables the platform routes to an overlay | Hosts that layer config files: .NET, Spring, Rails, figment, Hoplite | Implemented |
| OCI contract artifact | application/vnd.docuconf.contract.v1beta1+cue, referring to the image digest | docuconf push (CI); read back by docuconf pull | The platform, which validates the contract of the exact image it deploys | Specified, not built |
| Compatibility report | each change classified compatible, notable, breaking for the platform, or breaking; text or JSON | docuconf diff old.cue new.cue | CI merge gates | Specified, not built |
| Crossplane composition function | ContractValid condition and patched env/volumes | function-docuconf | Crossplane v2 composition pipelines | Specified, not built |
| Configuration docs | CONFIG.md for developers, CONFIG.agents.md for coding and ops agents | docuconf docs | Developers, AI agents, an AGENTS.md or llms.txt | Implemented |
| Docs model | docs.json (kind ConfigDocs, apiVersion docs.docuconf.dev/v1alpha1) | docuconf docs --format model | Renderers: the CLI, a website, an MCP server, a Backstage plugin | Implemented |
| Standalone values JSON Schema | values.schema.json for any values file | docuconf schema | Argo CD, Kustomize users, IDEs | Planned |
| Knative Service template | ksvc spec.template env and volumes | docuconf render --target knative | Knative Serving, Cloud Run | Planned |
| Kubernetes OpenAPI v3 schema | XRD / CRD openAPIV3Schema | docuconf xrd | The Kubernetes API server | Planned |
| Admission policy | CEL ValidatingAdmissionPolicy, or a cosign attestation for Kyverno | docuconf policy | The Kubernetes admission chain | Planned |
| KCL schema | KCL schema module | docuconf kcl | function-kcl, KCL-based platforms | Planned |
| .env.example | .env.example with descriptions | docuconf dotenv | Local development | Planned |
- Contract (CUE) Implemented
- Plain data that unifies with #Contract: kind ConfigContract, apiVersion docuconf.dev/v1beta1. Deterministic, sorted by name.
- Contract (JSON) Implemented
- A lossless JSON form of the same contract.
- Validation report Implemented
- Checks values, file sources and platform policy together. Secret values are never printed.
- Pod configuration Implemented
- Values in each app’s wire encoding, $ escaped, files projected with items (never subPath), inline content as content-hashed ConfigMaps, and the pod-template annotations and labels injectors need.
- Helm values schema Implemented
- JSON Schema draft-07: types, ranges, enums, required inputs, unknown names, secrets only as references, config-file content.
- Helm library chart Implemented
- Renders the same env, volumes and mounts as #Render; tested for parity on Helm 3 and 4.
- Boot-time violation report Implemented
- Covers what the platform cannot see: secret contents, certificate expiry and key match, file contents.
- Config-file overlay Implemented
- Values are placed at each variable’s configKey in native types, mounted at the overlay’s path; reload: watch maps to the host’s reload-on-change.
- OCI contract artifact Specified, not built
- Prevents validating image B against contract A. An OCI 1.1 artifact whose subject is the image, kept under the referrers tag schema on registries without the referrers API. Signable with cosign. docuconf push and pull are built in docuconf-go PR #28, not merged yet.
- Compatibility report Specified, not built
- Exits 1 on a breaking change unless an --ack file accepts it. Constraints compare as bounds and JSON Schemas structurally; anything diff cannot classify is breaking. Built in docuconf-go PR #28, not merged yet.
- Crossplane composition function Specified, not built
- Validates at composition time and injects the rendered configuration into the composed workload.
- Configuration docs Implemented
- Rendered from the docs model, which is built from the contract, so docs cannot drift from code. Each input’s description and details come from its doc comment in the app.
- Docs model Implemented
- Every fact a renderer shows, already phrased, checked against #DocsModel, including field tables for JSON Schemas and the rotation steps of every key set. Secrets never have a value in it.
- Standalone values JSON Schema Planned
- The Helm schema without the chart wrapper.
- Knative Service template Planned
- Respects Knative’s reserved variables (PORT, K_SERVICE…) and reserved mount paths.
- Kubernetes OpenAPI v3 schema Planned
- Rejects a bad claim at kubectl apply.
- Admission policy Planned
- Catches edits that bypass CI, such as kubectl set env.
- KCL schema Planned
- For platforms that chose KCL over CUE.
- .env.example Planned
- Secrets appear as placeholders, never values.
The contract
contract.cue is the one output an SDK must produce. It is plain data — no CUE expressions — that unifies with the meta-schema's #Contract:
kind: ConfigContract,apiVersion: docuconf.dev/v1beta1,metadata.name(a DNS label),metadata.generator(language, SDK, version).- Header
// Code generated by docuconf. DO NOT EDIT., a package clause andimport "docuconf.dev/contract". - Deterministic: variables and files sorted by name, so the same code always exports the same bytes and diffs stay readable.
- Canonical durations: units in the order
h m s ms us ns, each at most once, zero units omitted (1h30m, never90mor1h30m0s). contract.jsonis the same document as JSON (cue export), for tools without CUE.
Validation reports
docuconf vet (and the meta-schema's #Validate) checks a platform's values, file sources and policy against the contract and prints one line per problem:
$ docuconf vet -contract contract.cue -values values.yaml -files files.yaml -policy prod.cue
DATABASE_URL: is secret, so it must come from a secretKeyRef, never a literal or another reference
LOG_LEVL: is not declared in the contract (check the spelling)
PAYMENTS_TIMEOUT: "2 seconds" is not a duration such as 1m30s
TRACE_SAMPLE_RATIO: 1.5 is not allowed by policy
serving-tls: certificate does not cover orders.internal
tax-rates: inline content does not match its schema: default: invalid value 20 (out of bound <=1)It exits 1 when there is any problem, and never prints a secret value — including one wrongly written as a literal. A deprecated input the platform still sets is a warning: docuconf vet prints it with its message and exits 0 when there are only warnings. See Deprecating an input.
Pod configuration
docuconf render (and #Render) turns valid values into the pod's configuration:
env— each value in the app's wire encoding,$escaped, secrets asvalueFrom.secretKeyRef, plus every file'spathEnv.volumesandvolumeMounts— one per file input, projected withitems(neversubPath), read-only, mode0400for secrets and0444otherwise.configMaps— immutable ConfigMaps for inline content, named with a hash of their content so any change rolls the pods.restartTriggers— Secrets and ConfigMaps whose change must roll the pods (inputs withreload: restart).podAnnotationsandpodLabels— what injectors need on the pod template, frominjectedsources and the values document's shared maps, with placeholders expanded. Empty without injectors. See Enabling the injector.
Helm
docuconf helm -contract contract.cue -chart . writes the chart's files/docuconf/contract.json and values.schema.json. Helm then enforces the contract on every lint, template, install and upgrade, and the docuconf library chart renders the same env, volumes and mounts as #Render, and the same pod annotations and labels through its docuconf.podAnnotations and docuconf.podLabels helpers. JSON Schema cannot compare durations, see the cluster or apply policy, so docuconf vet still runs in CI for those.
Generated docs
docuconf docs builds a docs model from the contract and renders CONFIG.md for developers and CONFIG.agents.md for coding and ops agents, from each input's description and details. See Generated docs.
Boot-time reports
Every SDK checks the real environment and files when the process starts and reports all violations together, each with a stable error code, to stderr and to /dev/termination-log so kubectl describe pod shows why it stopped. This is the only check that sees secret contents, injected values and certificate details. For a program in a language without an SDK, docuconf check runs the same checks against a contract, and docuconf exec runs them and then starts the program with the environment it checked.
Compatibility report: docuconf diff
docuconf diff <old.cue | old.json | -> <new.cue | new.json | -> [--format text|json] [--allow-breaking] [--ack file]docuconf diff compares two contracts after unifying both with the meta-schema, so a default written out is not a change. Every change gets a change id and one of four classes:
| Class | Printed as | Meaning |
|---|---|---|
compatible | ok | Nothing the platform supplies stops working. |
notable | NOTABLE | Behaviour changes, or the platform must re-render: a new default, a changed encoding, a deprecated input. |
breaking-platform | BREAKING (platform only) | Values or sources that still set something the contract dropped fail: a removed input or overlay. |
breaking | BREAKING | Existing values or sources may no longer validate. |
Constraints compare as bounds: raising a lower bound or lowering an upper one tightens. JSON Schemas are compared keyword by keyword, following local $refs. A change diff cannot classify, such as a new pattern, is breaking.
$ docuconf diff old.cue contract.cue
BREAKING WORKER_COUNT: max lowered from 64 to 32 [max-tightened]
BREAKING LEGACY_MODE: variable removed; it was deprecated (...) [var-removed, platform only]
NOTABLE PORT: default changed from 8080 to 9090 [default-changed]
ok LOG_LEVEL: description changed (docs only) [description-changed]
orders-api: 2 breaking, 1 notable, 1 compatibleIt exits 0 when no change is breaking, 1 when one is, and 2 on a usage or parse error. CI blocks unacknowledged breaking changes; --ack file lists accepted ones as <input> <change-id>, and an acknowledgment that matches nothing is reported so stale lines get cleaned up. --format json prints the same as a list of objects.
The contract as an OCI artifact: docuconf push and pull
A contract describes one build of an app, so it travels with the image:
docuconf push --image registry/repo@sha256:<digest> [--plain-http] contract.cue
docuconf pull --image registry/repo@sha256:<digest> | registry/repo:<tag> [-o contract.cue] [--plain-http]pushvalidates the contract and pushes it as an OCI 1.1 artifact (artifactType: application/vnd.docuconf.contract.v1beta1+cue) whosesubjectis the image. The image must be given by digest; a tag is refused. On a registry without the referrers API, the artifact is indexed under the referrers tag schema. Pushing the same contract again pushes nothing.pushprints only the artifact's reference, so CI can sign it:cosign sign $(docuconf push --image ... contract.cue).pullresolves a tag to a digest, lists the image's contract referrers (the newest wins when there are several), falls back to thedev.docuconf.contractimage label, and checks the contract against the meta-schema before writing it. It exits 1 when the image has no contract.- A platform that validates by digest runs
docuconf pull --image <image@digest> -o contract.cue, thendocuconf vet, so it can never validate image B against contract A.
docuconf diff, push and pull are built in docuconf-go pull request #28, which is not merged yet. See SPEC.md §8 and §9.
What is next
function-docuconf brings validation and rendering into Crossplane v2 composition pipelines. See the roadmap.