{ "$schema": "https://json-schema.org/draft-07/schema#", "title": "urlaubsverwaltung 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, global) - the chart does not interpret their contents, so it cannot judge which keys are meaningful.", "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": { "databaseSecretRef": { "description": "op:// item path carrying \"jdbc-url\", \"username\" and \"password\". Required - the chart deploys no database and all state lives in the external one. Enforced by required() in the template, not here: the null default keeps this type widened, and a schema \"required\" entry could never fire against a key that is present with value null.", "type": ["string", "null"] }, "oidcSecretRef": { "description": "op:// item path carrying \"client-id\", \"client-secret\", \"issuer-name\", \"issuer-uri\", \"jwt-issuer-uri\" and \"redirect-uri\". Required - the chart offers no non-OIDC login and the app resolves the issuer at boot. Enforced by required() in the template, not here: the null default keeps this type widened, and a schema \"required\" entry could never fire against a key that is present with value null.", "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. Checked in both directions for this chart: nothing outside the two routing templates reads ingress.domain (UV_MAIL_APPLICATIONURL is a hardcoded placeholder and deliberately not derived from it), so domain is unnecessary while BOTH routing modes are off; clusterIssuer is read by the Ingress alone.", "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. The OIDC redirect URI lives in the 1Password item and does not follow it - publishing under a new name means updating both.", "type": "array", "items": { "type": "string" } } } }, "urlaubsverwaltung": { "type": "object", "additionalProperties": false, "properties": { "replicas": { "type": "integer", "minimum": 0 }, "securityContext": { "$ref": "#/definitions/securityContext" }, "livenessProbe": { "$ref": "#/definitions/probe" }, "readinessProbe": { "$ref": "#/definitions/probe" }, "startupProbe": { "$ref": "#/definitions/probe" }, "env": { "$ref": "#/definitions/env" }, "resources": { "$ref": "#/definitions/resources" } } } }, "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", "items": { "type": "object", "additionalProperties": false, "required": ["name"], "properties": { "name": { "type": "string" }, "value": { "type": "string" }, "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 container's securityContext; 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"] } } }