{ "$schema": "https://json-schema.org/draft-07/schema#", "title": "voucher-vault values", "description": "Strict values schema (issue #68). additionalProperties is false on every chart-owned object level, so a key that the chart does not read is rejected at render time instead of being silently ignored. The only objects that stay open are the ones passed verbatim into the Kubernetes pod spec (probes, security contexts, ports, volumes, global) - the chart does not interpret their contents, so it cannot judge which keys are meaningful. The hardening, probe and resources blocks additionally accept null, because an erased block falls back to the chart defaults (issue #99).", "type": "object", "additionalProperties": false, "properties": { "global": { "description": "Helm's conventional cross-chart values. Unused by this chart, kept open so an umbrella install cannot break on it.", "type": "object" }, "scaleDown": { "type": "boolean" }, "secrets": { "type": "object", "additionalProperties": false, "properties": { "voucherVaultSecretRef": { "type": ["string", "null"] }, "oidcSecretRef": { "type": ["string", "null"] }, "databaseSecretRef": { "type": ["string", "null"] } } }, "voucherVault": { "type": "object", "additionalProperties": false, "properties": { "replicas": { "type": "integer", "minimum": 0 }, "resources": { "$ref": "#/definitions/resources" }, "livenessProbe": { "$ref": "#/definitions/probe" }, "readinessProbe": { "$ref": "#/definitions/probe" }, "startupProbe": { "$ref": "#/definitions/probe" }, "securityContext": { "$ref": "#/definitions/securityContext" }, "ports": { "description": "Rendered verbatim as the container's ports list; kept open because the chart does not interpret the entries.", "type": ["array", "null"] }, "env": { "description": "The container's full env list (not merely additive here). Entries are rendered through tpl, so values may contain Helm templating.", "$ref": "#/definitions/env" }, "storage": { "description": "Volumes and volumeMounts of the workload, rendered verbatim into the pod spec; kept open because the chart does not interpret the entries.", "type": "object", "additionalProperties": false, "properties": { "volumes": { "type": ["array", "null"] }, "volumeMounts": { "type": ["array", "null"] } } } } }, "storage": { "description": "The data PVC. Not null-safe on purpose: an erased block yields an invalid PVC rather than a silently degraded workload.", "type": "object", "additionalProperties": false, "properties": { "amount": { "type": ["string", "null"] }, "storageClass": { "type": ["string", "null"] } } }, "ingress": { "type": "object", "additionalProperties": false, "properties": { "enabled": { "description": "Gates the whole Ingress template. Mutually exclusive with httpRoute.enabled - the render aborts when both are true. false omits the Ingress and makes clusterIssuer unnecessary - but NOT domain, which is also Django's ALLOWED_HOSTS entry.", "type": "boolean" }, "clusterIssuer": { "type": ["string", "null"] }, "domain": { "type": ["string", "null"] }, "className": { "type": ["string", "null"] }, "annotations": { "description": "Extra Ingress annotations, merged with the cert-manager annotation the chart always sets. Free-form keys by nature. No counterpart in Gateway mode: the Gateway API has no annotation channel, so these are gone when httpRoute.enabled is used instead.", "type": "object" } } }, "httpRoute": { "description": "Gateway-API alternative to the Ingress (Gitea #114). Mutually exclusive with ingress.enabled - the render aborts when both are true. The chart renders only an HTTPRoute with parentRefs; class and certificate sit on the Gateway and belong to the platform. The Gateway-API CRDs must be present in the cluster, because the chart cannot detect them.", "type": "object", "additionalProperties": false, "properties": { "enabled": { "type": "boolean" }, "parentRefs": { "description": "The Gateway(s) the route attaches to. Required while httpRoute.enabled is true, enforced by required()-equivalent in the template (an empty list aborts the render) - a JSON Schema \"required\" cannot do it, because the key ships as an empty list and is therefore present. Entries are the Gateway API's ParentReference and are passed through unchanged.", "type": "array", "items": { "$ref": "#/definitions/parentRef" } }, "hostnames": { "description": "Empty means [ingress.domain], so the hostname has a single source of truth. A hostname set here does not move Django's DOMAIN, so ALLOWED_HOSTS answers it with 400 while all three probes stay green - they carry a Host header of 127.0.0.1 on purpose.", "type": "array", "items": { "type": "string" } } } } }, "definitions": { "parentRef": { "description": "A Gateway API ParentReference, passed verbatim into HTTPRoute.spec.parentRefs. Deliberately left OPEN (no additionalProperties: false), for the same reason probes and security contexts are: Kubernetes owns this schema, the Gateway API adds fields to it across releases, and a closed list here would reject a field only upstream knows about. What the chart can assert is that \"name\" is there - it is required by the API and a reference without it attaches to nothing, which is the silent failure this chart aborts the render over.", "type": "object", "required": ["name"] }, "resources": { "description": "May be null / empty: the chart then falls back to its default requests and computed limits (issue #99) instead of rendering a container without resource accounting.", "type": ["object", "null"], "additionalProperties": false, "properties": { "limitFactor": { "type": "number", "exclusiveMinimum": 0 }, "requests": { "$ref": "#/definitions/resourceList" }, "limits": { "$ref": "#/definitions/resourceList" } } }, "resourceList": { "type": ["object", "null"], "additionalProperties": false, "properties": { "cpu": { "type": ["string", "number", "null"] }, "memory": { "type": ["string", "number", "null"] }, "ephemeral-storage": { "type": ["string", "number", "null"] }, "ephemeralStorage": { "type": ["string", "number", "null"] } } }, "env": { "type": ["array", "null"], "items": { "type": "object", "additionalProperties": false, "required": ["name"], "properties": { "name": { "type": "string" }, "value": { "type": ["string", "number", "boolean"] }, "valueFrom": { "type": "object", "additionalProperties": false, "properties": { "secretKeyRef": { "$ref": "#/definitions/keyRef" }, "configMapKeyRef": { "$ref": "#/definitions/keyRef" } } } } } }, "keyRef": { "type": "object", "additionalProperties": false, "required": ["name", "key"], "properties": { "name": { "type": "string" }, "key": { "type": "string" } } }, "securityContext": { "description": "May be null / empty at any level: the chart then falls back to its hardening defaults (issue #99) instead of rendering an unhardened workload.", "type": ["object", "null"], "additionalProperties": false, "properties": { "pod": { "description": "Merged onto the chart's pod hardening defaults and rendered as the pod's securityContext; kept open because the chart does not interpret the individual fields.", "type": ["object", "null"] }, "container": { "description": "Merged onto the chart's container hardening defaults and rendered as the securityContext of both the init container and the app container; kept open because the chart does not interpret the individual fields.", "type": ["object", "null"] } } }, "probe": { "description": "Merged onto the chart's probe defaults and rendered as a container probe; kept open because the chart does not interpret the individual fields. May be null / empty, which means the defaults apply (issue #99) rather than the probe disappearing.", "type": ["object", "null"] } } }