Commit Graph
383 Commits
Author SHA1 Message Date
jklein 2cb1a05d6f homeassistant: strict values.schema.json and null-safe hardening
No ingress gate change: this chart already honours ingress.enabled, and
its ingress block keeps the upstream-style host/tls lists that the README
documents as an exception. The schema models that shape as it is instead
of pushing the repo's domain/clusterIssuer pair onto it, and the list
entries stay open because they go verbatim into the Ingress spec.

The domain checkpoint ran over values.yaml and templates and came back
empty: ingress.domain does not exist in this chart at all.

1. values.schema.json (#68): additionalProperties: false on every
   chart-owned object level. Pod-spec passthrough (volumes, volumeMounts,
   nodeSelector, tolerations, affinity, ingress hosts/tls) stays open.

2. Null-safety for hardening, probes and resources (#99).

   This chart's hardening is a documented deviation and the fallbacks
   reproduce it exactly: the pod context is deliberately EMPTY, because
   the official image must start as root (s6-overlay does its setup as
   uid 0 and the image has no non-root user), and capabilities.add keeps
   NET_RAW, without which device discovery (DHCP watcher, ping/arp
   integrations) logs "Operation not permitted".

core.storage stays deliberately not null-safe: an erased block yields an
invalid PVC, which is the loud class #99 excludes.

The #82 limitation around the 1Password-backed config Secret is
untouched: Helm never sees the content, so it cannot be hashed, and the
values.yaml note about the manual rollout restart stays as it is.

Rendering with normal values is byte-identical to 5.0.0.
2026-08-23 21:44:49 +02:00
jklein f0faf8c222 Merge pull request #116 from jk-cluster/feat/values-schema-samba
samba: strict values.schema.json + Null-Absicherung (Welle 2, #68/#99)
2026-08-23 19:42:30 +00:00
jklein 24d3366e8b samba: strict values.schema.json and null-safe hardening
No ingress gate: this chart has no Ingress at all (SMB and NetBIOS are
exposed via NodePort), and ingress.domain appears neither in its
templates nor in its values.

1. values.schema.json (#68): additionalProperties: false on every
   chart-owned object level, including the entries of the samba.shares
   list.

2. Null-safety for hardening, probes and resources (#99).

   This chart's hardening is a documented deviation forced by the
   ghcr.io/dockur/samba image, and the fallbacks reproduce it exactly
   instead of restoring the repo standard: no runAs* values (the
   entrypoint creates Unix users and smbd impersonates the share user per
   session, both requiring a root start), readOnlyRootFilesystem stays
   false (the entrypoint writes /etc/passwd, /etc/group, the healthcheck
   symlink and the Samba TDBs), and capabilities.add keeps the six
   entries a multi-user root file server needs. Restoring the standard
   here would stop the file server from working.

   The probes target the SMB TCP port directly, because SMB is not HTTP.

The users.conf / checksum-config limitation from #82 is untouched: Helm
never sees the Secret content, so it cannot be hashed, and the comment in
values.yaml documenting the manual rollout restart stays as it is.

Rendering with normal values is byte-identical to 5.0.0.
2026-08-23 21:39:49 +02:00
jklein 1b8087d77c Merge pull request #115 from jk-cluster/feat/values-schema-calibre
calibre-web-automated: strict values.schema.json + Ingress-Gate + Null-Absicherung (Welle 2, #68/#93/#99)
2026-08-23 19:37:24 +00:00
jklein 6c04a68763 calibre-web-automated: strict schema, ingress gate and null-safe hardening
Three changes, all about values that do not do what they promise:

1. values.schema.json (#68): additionalProperties: false on every
   chart-owned object level.

2. Ingress gate (#93): the Ingress template is wrapped in
   {{- if .Values.ingress.enabled }} and the key is added to values.yaml
   with default true, so behaviour is unchanged.

   The domain checkpoint from rallly ran over values.yaml and templates
   and came back empty here: ingress.domain is read nowhere but in the
   Ingress template. Unlike rallly, zipline, voucher-vault and outline,
   this gate therefore frees both domain and clusterIssuer, and no extra
   required() is needed.

3. Null-safety for hardening, probes and resources (#99).

   This chart's hardening is a documented deviation from the repo
   standard, and the fallbacks reproduce it exactly instead of restoring
   the standard: no runAs* values (s6-overlay boots as root and drops to
   PUID/PGID 1000), readOnlyRootFilesystem stays false (read-only mode
   disables the PUID/PGID remapping, silently moving the runtime uid from
   1000 to 911 and breaking existing volume data), and capabilities.add
   keeps its six entries that the s6 init and supervision need. A
   "cleaned up" standard default here would not be tidier, it would be an
   outage.

cwa.storage stays deliberately not null-safe: an erased value yields an
invalid PVC, which is the loud class #99 excludes.

Rendering with normal values is byte-identical to 4.0.0.
2026-08-23 21:34:32 +02:00
jklein 4e63e8c164 Merge pull request #114 from jk-cluster/feat/values-schema-satisfactory
satisfactory: strict values.schema.json + Null-Absicherung (Welle 2, #68/#99)
2026-08-23 19:31:07 +00:00
jklein 290c69cc7d satisfactory: strict values.schema.json and null-safe hardening
No ingress gate: this chart has no Ingress at all (game and messaging
ports are exposed via NodePort), and ingress.domain appears neither in
its templates nor in its values.

1. values.schema.json (#68): additionalProperties: false on every
   chart-owned object level. Like teamspeak-server, this chart keeps env,
   probes and securityContext at the TOP level, and the schema mirrors
   that shape.

2. Null-safety for hardening, probes and resources (#99). What a rebuilt
   default must not lose here:
   - liveness and startup run the image's own healthcheck script via
     exec. It queries the server's HTTPS API on SERVERGAMEPORT, so it
     survives a port override, which a tcpSocket default could not.
   - readiness keeps the named "api" port.
   - the resources default keeps limitFactor 2 rather than the repo-wide
     3, which is what holds the memory limit at the published 8Gi.
   - the pod context keeps fsGroupChangePolicy OnRootMismatch, which is
     what avoids a recursive chown of multi-GB game files on every start.

server.storage stays deliberately not null-safe: an erased value yields
an invalid PVC, which is the loud class #99 excludes.

This chart is excluded from the CI install-test, so the local proof is
the only one. Rendering is byte-identical to 4.0.0 with default values
and with the production bundle values, and the rendered manifests were
additionally validated by the cluster's API server via a server-side
dry-run.
2026-08-23 21:28:52 +02:00
jklein 5b3524a354 Merge pull request #113 from jk-cluster/feat/values-schema-teamspeak
teamspeak-server: strict values.schema.json + Null-Absicherung (Welle 2, #68/#99)
2026-08-23 19:26:03 +00:00
jklein e54776e6c1 teamspeak-server: strict values.schema.json and null-safe hardening
No ingress gate: this chart has no Ingress at all (voice/file-transfer
are exposed via NodePort), and ingress.domain appears neither in its
templates nor in its values.

1. values.schema.json (#68): additionalProperties: false on every
   chart-owned object level. Note that this chart keeps replicas,
   resources, probes and securityContext at the TOP level rather than
   under a chart-named key, so the schema mirrors that shape.

2. Null-safety for hardening, probes and resources (#99). The rebuilt
   probes keep the "file-transfer" port name: the voice service is UDP
   and cannot be probed, so that TCP port is the only thing a probe can
   target - a default probe without it would leave the workload with no
   working probe at all.

   The container defaults keep capabilities.add as an empty list, exactly
   as values.yaml has it, so an erased block restores today's rendering
   byte for byte rather than a cleaned-up variant.

storage stays deliberately not null-safe: an erased block yields an
invalid PVC, which is the loud class #99 excludes.

Rendering with normal values is byte-identical to 4.0.0.
2026-08-23 21:23:30 +02:00
jklein 24fb0d2d2b Merge pull request #112 from jk-cluster/feat/values-schema-outline
outline: strict values.schema.json + Null-Absicherung (Welle 2, #68/#99)
2026-08-23 19:21:58 +00:00
jklein 24ca3513fc outline: strict values.schema.json and null-safe hardening
No ingress gate: this chart already gates its Ingress correctly. Two
changes plus one guard the existing gate turned out to need.

1. values.schema.json (#68): additionalProperties: false on every
   chart-owned object level.

2. Null-safety for hardening, probes and resources (#99). All three
   probes keep /_health when rebuilt: it is Outline's only health
   endpoint, and "/" returns 500 as well when the database is down, so
   there is no dependency-free path to fall back to.

3. ingress.domain is required() where the StatefulSet reads it. It feeds
   the URL env var - Outline's public URL for generated links and the
   OIDC redirect URI - and did so without a guard. With the existing gate
   and no domain it rendered "https://", breaking logins silently. That
   hole predates this change; it now fails loudly.

outline.storage stays deliberately not null-safe: an erased block yields
an invalid PVC, which is the loud class #99 excludes.

Apart from an added comment, the rendered manifest is unchanged.
2026-08-23 21:18:58 +02:00
jklein 81549d6aab Merge pull request #111 from jk-cluster/feat/values-schema-voucher-vault
voucher-vault: strict values.schema.json + Null-Absicherung (Welle 2, #68/#99)
2026-08-23 19:17:14 +00:00
jklein f2fc18c6ae voucher-vault: strict values.schema.json and null-safe hardening
No ingress gate: this chart already gates its Ingress correctly. Two
changes plus one guard that the existing gate turned out to need.

1. values.schema.json (#68): additionalProperties: false on every
   chart-owned object level. Lists that go verbatim into the pod spec
   (ports, storage.volumes, storage.volumeMounts) stay open.

2. Null-safety for hardening, probes and resources (#99). Two specifics
   of this chart:

   - The probes were wrapped in "if" guards, so an erased probe block did
     not render "livenessProbe: null" - it removed the probe entirely and
     silently. The guards are gone; an empty block now means chart
     defaults, so the workload keeps its probes.
   - The rebuilt probes keep the Host: 127.0.0.1 header. Django's
     ALLOWED_HOSTS only accepts 127.0.0.1 and the configured DOMAIN, so a
     probe without it would get 400 and the pod would never be ready.

3. ingress.domain is required() where it is read. The dependency lives in
   values.yaml, not in a template: the DOMAIN env entry is a tpl string
   feeding Django's ALLOWED_HOSTS. With the existing gate and no domain
   the app rendered DOMAIN: "" and answered 400 to every real request -
   silently, and already before this change. It now fails loudly.

Apart from an added comment, the rendered manifest is unchanged.
2026-08-23 21:14:01 +02:00
jklein e22e1235e6 Merge pull request #110 from jk-cluster/feat/values-schema-zipline
zipline: strict values.schema.json + Ingress-Gate + Null-Absicherung (Welle 2, #68/#93/#99)
2026-08-23 19:10:12 +00:00
jklein 40289a2e67 zipline: strict values.schema.json, ingress gate and null-safe hardening
Three changes, all about values that do not do what they promise:

1. values.schema.json (#68): additionalProperties: false on every
   chart-owned object level, so a key the chart does not read is rejected
   at render time instead of being silently ignored.

2. Ingress gate (#93): the Ingress template is wrapped in
   {{- if .Values.ingress.enabled }} and the key is added to values.yaml
   with default true, so behaviour is unchanged.

   As in rallly, ingress.domain is not a pure Ingress value: the
   StatefulSet also feeds it to CORE_DEFAULT_DOMAIN, the app's default
   domain for generated share links, and did so without required(). The
   guarantee only came from the ungated Ingress template, so the gate
   would have handed out unusable links silently. That read is now
   required() as well; only clusterIssuer becomes unnecessary.

3. Null-safety for hardening, probes and resources (#99): an erased block
   fell back to "securityContext: null" (unhardened), a vanished probe or
   a container without resource accounting. The rebuilt liveness probe
   keeps "/" rather than /api/healthcheck, so a database outage still does
   not restart the pod.

config stays deliberately not null-safe: storage and storageClass are
required(), which puts an erased block in the loud class #99 excludes.

Apart from an added comment, the rendered manifest is unchanged.
2026-08-23 21:07:11 +02:00
jklein 4f5870db20 Merge pull request #108 from jk-cluster/feat/values-schema-rallly
rallly: strict values.schema.json + Ingress-Gate + Null-Absicherung (Welle 2, #68/#93/#99)
2026-08-23 19:02:37 +00:00
jklein 37eda69fdd rallly: strict values.schema.json, ingress gate and null-safe hardening
Three changes, all about values that do not do what they promise:

1. values.schema.json (#68): additionalProperties: false on every
   chart-owned object level, so a key the chart does not read is rejected
   at render time instead of being silently ignored.

2. Ingress gate (#93): the Ingress template is wrapped in
   {{- if .Values.ingress.enabled }} and the key is added to values.yaml
   with default true, so behaviour is unchanged.

   ingress.domain is NOT a pure Ingress value here - it is also the app's
   public base URL (NEXT_PUBLIC_BASE_URL). Gating alone would therefore
   have introduced a new silent failure: with the Ingress switched off and
   no domain, the deployment rendered value: "https://" and every
   generated link would be broken. The deployment's read of the value is
   now required(), so that case fails loudly. Only clusterIssuer actually
   becomes unnecessary when the Ingress is off.

3. Null-safety for hardening, probes and resources (#99): an erased block
   fell back to "securityContext: null" (unhardened), a vanished probe or
   a container without resource accounting. Restoring the pod context
   matters especially here, because its fsGroup is what makes the Next.js
   cache emptyDir group-writable for the container.

rallly.cache is deliberately NOT null-safe: cache.path is required(), so
an erased block fails loudly and belongs to the loud class #99 excludes.

Apart from an added comment, the rendered manifest is unchanged.
2026-08-23 20:58:52 +02:00
jklein a9992d356d Merge pull request #107 from jk-cluster/feat/apache-tika-notes-txt
Add NOTES.txt to the apache-tika chart
2026-08-23 18:52:48 +00:00
jklein f74870b246 apache-tika: note why the notes use effectiveResources
Records the reasoning inline, matching the comment the gotenberg chart
carries, so the next edit does not quietly switch back to the raw helper and
drop the paragraph whenever a resources: block has been erased.
2026-08-23 20:46:50 +02:00
jklein 6295f4b9c1 Add NOTES.txt to the apache-tika chart
Tika has no Ingress, so the notes lead with the cluster-internal URL, the
Service-port-80 to container-port-9998 mismatch a consumer has to get right,
and /parsers as the direct answer to "why did this file come back empty".

Two warnings come from measuring the running container rather than from
reading the values file:

- The image tag has to keep its "-full" suffix. That variant is where
  Tesseract 5.5.0 and the extra parsers live; the plain image carries no
  tesseract binary at all, so dropping the suffix does not fail loudly, it
  just stops OCR and returns empty text for scans.
- The JVM never sees the container limit. It starts without -Xmx and derives
  its heap from the limit at MaxRAMPercentage=25, so the number worth sizing
  against is a quarter of it.

The heap figure is computed from the effective limit through the chart's own
null-safe effectiveResources helper, so an erased resources: block still
prints the defaults the container actually receives instead of dropping the
paragraph. Refs #43.
2026-08-23 20:44:02 +02:00
jklein 4b10870d59 Merge pull request #103 from jk-cluster/feat/gotenberg-null-safety
gotenberg: Null-Absicherung + Schema-Typen (Nachrüstung Welle 1, #99/#68)
2026-08-23 18:40:08 +00:00
jklein 392fc6c36a Merge pull request #105 from jk-cluster/feat/apache-tika-null-safety
apache-tika: Null-Absicherung + Schema-Typen (Nachrüstung Welle 1, #99/#68)
2026-08-23 18:38:48 +00:00
jklein 8bc673d80d gotenberg: null-safe hardening, probes and resources
Retrofit of #99 for a chart that already carries a values.schema.json,
plus the schema type change that goes with it.

An override written without children is YAML null. Where the chart
defines a default, Helm's coalescing deletes the default before schema
validation runs, so the schema never sees the null and cannot reject it:
the container rendered "securityContext: null" - unhardened, healthy,
silent. Where the chart defines no default (resources.limits), the null
survives into validation and a strict "object" type aborted the render.

The defaultedDict helper from #96 handles the first case; widening the
types of exactly these blocks to ["object", "null"] handles the second.
All other keys stay strict, additionalProperties: false is untouched.

The probes address the container port by name, so a rebuilt default probe
needs no further context.

Rendering with normal values is byte-identical to 5.0.0.
2026-08-23 20:37:12 +02:00
jklein 1698b6dab8 Merge pull request #104 from jk-cluster/feat/gotenberg-notes-txt
Add NOTES.txt to the gotenberg chart
2026-08-23 18:34:40 +00:00
jklein 07ce0bb816 apache-tika: null-safe hardening, probes and resources
Retrofit of #99 for a chart that already carries a values.schema.json,
plus the schema type change that goes with it.

An override written without children is YAML null. Where the chart
defines a default, Helm's coalescing deletes the default before schema
validation runs, so the schema never sees the null and cannot reject it:
the container rendered "securityContext: null" - unhardened, healthy,
silent. Where the chart defines no default (resources.limits), the null
survives into validation and a strict "object" type aborted the render.

The defaultedDict helper from #96 handles the first case; widening the
types of exactly these blocks to ["object", "null"] handles the second.
All other keys stay strict, additionalProperties: false is untouched.

The probes address the container port by name, so a rebuilt default probe
needs no further context.

Rendering with normal values is byte-identical to 8.0.0.
2026-08-23 20:33:00 +02:00
jklein 09d8a94bfc Add NOTES.txt to the gotenberg chart
Gotenberg has no Ingress, so the notes lead with the cluster-internal URL and
point out that the Service listens on 80 while the container listens on 3000
— the mismatch a consumer such as paperless-ngx has to get right — plus the
port-forward command for reaching it by hand.

Three findings from measuring the running chart went in as warnings:

- The chart passes no command-line flags, so Gotenberg's basic auth, OIDC,
  SSRF guards and request timeout cannot be enabled through values at all.
- Memory, not disk, is the first limit to hit: at the default limit a large
  document gets the container OOM-killed, the caller sees the connection
  dropped rather than an HTTP error, and the notes give the exact kubectl
  command that prints OOMKilled.
- Temp space is an emptyDir counted against ephemeral-storage, where running
  out looks different — the pod is evicted and replaced, not restarted.

Both limits are read back through the chart's own resources helper, so the
printed figures follow limitFactor and any override instead of being
hardcoded. Refs #43.
2026-08-23 20:30:22 +02:00
jklein 5e5fb631c3 Merge pull request #102 from jk-cluster/feat/cyberchef-ingress-gate
cyberchef: Ingress-Gate + Null-Absicherung + Schema-Typen (Welle 1, #93/#99/#68)
2026-08-23 18:29:28 +00:00
jklein 4e97097a64 cyberchef: honour ingress.enabled, add null-safe hardening
Three changes, all about values that do not do what they promise:

1. Ingress gate (#93): the Ingress template is wrapped in
   {{- if .Values.ingress.enabled }}. The key already existed in
   values.yaml with default true but was never read, so switching it off
   did nothing. Both required() calls for domain and clusterIssuer live
   inside the Ingress file, so gating also removes the contradiction that
   one had to supply a domain and issuer in order to turn off an Ingress
   one does not want.

2. Null-safety for hardening, probes and resources (#99): an override
   written without children is YAML null and erased the whole default
   sub-tree, rendering "securityContext: null" - an unhardened container
   that starts and reports healthy.

3. values.schema.json types (#68 + #99): the blocks covered by the
   null-safety accept null. This is load-bearing only for keys that have
   no chart default (e.g. resources.limits): there Helm has nothing to
   delete, so the null survives into schema validation and a strict
   "object" type rejected it outright.

Rendering with normal values is byte-identical to 7.0.0.
2026-08-23 20:27:00 +02:00
jklein 60136840f6 Merge pull request #101 from jk-cluster/feat/cyberchef-notes-txt
Add NOTES.txt to the cyberchef chart
2026-08-23 18:23:17 +00:00
jklein 907cb16d6a Merge pull request #98 from jk-cluster/feat/values-schema-patchmon
patchmon: strict values.schema.json + Ingress-Gate + Null-Absicherung (Welle 1, #68/#93/#99)
2026-08-23 18:21:46 +00:00
jklein db319b916d Merge pull request #100 from jk-cluster/feat/values-schema-urlaubsverwaltung
urlaubsverwaltung: strict values.schema.json + Null-Absicherung (Welle 1, #68/#99)
2026-08-23 18:21:38 +00:00
jklein e6e3ad961e Add NOTES.txt to the cyberchef chart
Prints what an operator would otherwise have to look up after installing:
the rendered Ingress URL, the cert-manager Certificate to watch while the
browser still warns, and the fact that the chart needs no secrets and no
volumes.

Adds three warnings that the values alone do not tell: CyberChef ships no
authentication, so everything that reaches the URL can use it; the app is
static and holds no server-side state, so upgrades and rollbacks need no
migration; and cyberchef.env reaches nginx but never the served bundle.

Scaled-down installations are called out conditionally, naming whichever of
scaleDown / cyberchef.replicas caused it, via the chart's own replicas
helper so the notice cannot drift from the rendered Deployment.

The URL is only ever rendered from .Values.ingress.domain, so no domain is
stored in the chart. Refs #43.
2026-08-23 20:19:41 +02:00
jklein 03c9fd6467 Add null-safe hardening, probes and resources to patchmon
Third change of the same class (#99): an override written without
children is YAML null and replaced the whole default sub-tree, rendering
"securityContext: null" (unhardened container), a vanished probe or a
container without resource accounting - silently, while the workload
reports healthy.

The defaultedDict helper from #96 is adopted for both workloads, so an
empty block means "chart defaults apply" while an explicitly set value
still wins, including false and 0.

The server probes rebuild their Host header from ingress.domain via the
passed-in root context, because the 2.x server rejects requests whose
Host is neither loopback nor a CORS_ORIGIN host.

The schema types allow null for exactly these blocks, so schema and
helper agree instead of the schema rejecting what the helper absorbs.

Rendering with normal values is byte-identical to the previous version,
with and without the guacd sidecar.
2026-08-23 20:19:08 +02:00
jklein 4976c67ce3 Add strict values.schema.json and null-safe hardening to urlaubsverwaltung
Two changes, both about values that do not do what they promise:

1. values.schema.json (#68): additionalProperties: false on every
   chart-owned object level, so a key the chart does not read is rejected
   at render time instead of being silently ignored.

2. Null-safety for hardening, probes and resources (#99): an override
   written without children is YAML null and replaced the whole default
   sub-tree, rendering "securityContext: null" (unhardened container), a
   vanished probe or a container without resource accounting - silently.
   The defaultedDict helper from #96 is adopted so an empty block means
   "chart defaults apply", while an explicitly set value still wins,
   including false and 0.

The schema types allow null for exactly these blocks, so the two changes
agree instead of the schema rejecting what the helper is meant to absorb.

No ingress gate here: this chart already gates its Ingress correctly.

Rendering with normal values is byte-identical to the previous version.

Major bump: a schema can break existing deployments that carry dead keys.
2026-08-23 20:14:27 +02:00
jklein 144e9e4155 Merge pull request #96 from jk-cluster/fix/paperless-barcodes-null-safe
paperless-ngx: leerer barcodes-Block faellt auf die Chart-Defaults zurueck
2026-08-23 17:37:19 +00:00
jklein 399a68fd31 Merge pull request #97 from jk-cluster/fix/rallly-nextjs-cache-emptydir
rallly: emptyDir für den Next.js-Cache (5.0.0+up4.12.3)
2026-08-23 17:36:08 +00:00
jklein a7a6d6da7c Add strict values.schema.json and the ingress gate to patchmon
Two changes of the same class - values that do not do what they promise:

1. values.schema.json (#68): additionalProperties: false on every
   chart-owned object level, so a key the chart does not read is rejected
   at render time instead of being silently ignored. Objects passed
   verbatim into the pod spec (probes, securityContext, global) stay open.

2. Ingress gate (#93): the Ingress template is wrapped in
   {{- if .Values.ingress.enabled }} and the key is added to values.yaml
   with default true, so behaviour is unchanged. Without the gate the
   value did not exist at all and could not switch the Ingress off.

Major bump: a schema can break existing deployments that carry dead keys.
2026-08-23 19:34:41 +02:00
jklein 82d68d4f22 Merge pull request #91 from jk-cluster/feat/minecraft-server-config-checksum-java21
Update minecraft-server to the java21 line (3.0.0+up2026.8.2.java21)
2026-08-23 17:33:52 +00:00
jklein 2de85ea30e Mount an emptyDir for the Next.js cache in rallly (5.0.0+up4.12.3)
The chart mounted no volumes at all while running with
readOnlyRootFilesystem: true, so every Next.js write to
/app/apps/web/.next/cache failed. The image optimizer's failure even
surfaced as an unhandledRejection, so this was more than log noise.

The cache path is now a writable emptyDir; path and an optional
sizeLimit are configurable under rallly.cache. The hardening is
untouched — the pod's existing fsGroup (1000) is what makes the mounted
volume writable for uid 20000.

Verified in a throwaway k3d cluster which paths the app actually writes:
with a fully writable root filesystem and the cache mounted, the only
path the container touches is the cache directory itself. /tmp, $HOME
(=/app) and the rest of the root filesystem stay untouched, so no second
mount is needed.

Also drops the vestigial "capabilities.add: []": Trivy's AVD-KSV-0022 for
rallly (#84) comes from the older chart version deployed in the cluster,
which rendered a null list entry under add:. Reproduced with trivy config
against both renderings; the app needs no capabilities.

Major bump: runtime behavior changes, a volume is added.

Fixes #60
2026-08-23 19:33:06 +02:00
jklein 58e84793bf Merge pull request #95 from jk-cluster/feat/values-schema-apache-tika
apache-tika: strict values.schema.json (Welle 1, #68)
2026-08-23 17:32:29 +00:00
jklein 4f489b0854 paperless-ngx: an empty barcodes block falls back to the chart defaults
A "barcodes:" key left without children (e.g. after deleting the last
remaining sub-key, PAPERLESS_CONSUMER_BARCODE_SCANNER, which paperless-ngx
3.0 removed) is YAML null and replaced the whole default sub-tree on merge.
Rendering then failed on the nil pointer, so the release simply stopped
updating.

An empty or null block now means "the chart defaults apply". The merge runs
through a new paperless-ngx.defaultedDict helper: nulls never delete, nested
maps merge recursively, and explicitly set values win - including false and 0,
which "default" and "mergeOverwrite" would swallow. A scalar where the
defaults define a map is rejected with the values path in the message.

Major bump: the meaning of a values override changes.

Fixes #61
2026-08-23 19:31:20 +02:00
jklein a6c20162f9 Add strict values.schema.json to apache-tika
additionalProperties: false on every chart-owned object level, so a key
the chart does not read is rejected at render time instead of being
silently ignored. Objects passed verbatim into the pod spec (probes,
securityContext, global) stay open - Kubernetes owns their schema there.

Major bump: a schema can break existing deployments that carry dead keys.

Refs #68
2026-08-23 19:29:14 +02:00
jklein f5bbffca3c Merge pull request #94 from jk-cluster/feat/values-schema-gotenberg
gotenberg: strict values.schema.json (Welle 1, #68)
2026-08-23 17:28:18 +00:00
jklein c39c1b080d Merge pull request #92 from jk-cluster/feat/checksum-config-homeassistant
homeassistant: Secret-Verweis abdecken, Inhalts-Lücke dokumentieren (#82)
2026-08-23 17:24:55 +00:00
jklein a4d7a93912 Add strict values.schema.json to gotenberg
additionalProperties: false on every chart-owned object level, so a key
the chart does not read is rejected at render time instead of being
silently ignored. Objects passed verbatim into the pod spec (probes,
securityContext, global) stay open - Kubernetes owns their schema there.

Major bump: a schema can break existing deployments that carry dead keys.

Refs #68
2026-08-23 19:24:42 +02:00
jklein 9eaa2ea6c0 Merge pull request #90 from jk-cluster/feat/values-schema-cyberchef
cyberchef: strict values.schema.json (Welle 1, #68)
2026-08-23 17:23:19 +00:00
jklein 55f5aefdbe homeassistant: cover the secret reference, document the content gap
Home Assistant reads configuration.yaml, http-config.yaml and
recorder-config.yaml from a 1Password-backed Secret, mounted with subPath.
Two different gaps hide behind that, and only one of them can be closed.

Repointing secrets.configSecretRef at a different vault item used to leave the
running pod on the old configuration. That is now covered: the pod template
carries checksum/secret-ref over the rendered OnePasswordItem. The annotation
is named apart from checksum/config on purpose - it only promises that the
config source changed, not the config itself - matching the pattern
minecraft-server introduced.

Changing the CONTENT of the item in the vault still does not restart anything,
and cannot: Helm never sees the content, so there is nothing to hash. The
operator's own auto-restart annotation is no way out either - onepassword-
operator 1.12.0 enumerates exactly one workload type in its secret-update
handler (appsv1.DeploymentList) and this workload is a StatefulSet, so the
annotation would be a silent no-op advertising a guarantee it cannot keep. It
is deliberately not set. values.yaml states the limitation and the manual
rollout restart it requires; the README guideline records the operator finding,
the annotation precedence trap, and the checksum/secret-ref pattern so neither
is rediscovered the hard way.

Major bump: runtime behavior changes - changing the secret reference now costs
a restart. For this release the effect is preventive, since it currently runs
at zero replicas via scaleDown.
2026-08-23 19:20:16 +02:00
jklein 6543c6f02c Update minecraft-server to the java21 line (3.0.0+up2026.8.2.java21)
Last of the three publishes that carry the checksum annotations from
3.0.0+up2026.8.2.java8, leaving main on the line of the only running server.
Same chart content as the java8 and java17 publishes, only the published Java
line changes: appVersion moves to the dated tag 2026.8.2-java21 and the
minecraft.version default moves to 1.21.1, the version ftb-skies-2 actually
runs (Java 8 runs up to 1.16.5, 1.18-1.20.4 need Java 17, 1.20.5+ need
Java 21).

Against the state before this series (2.0.0+up2026.8.2.java21) the only
replaced line in Chart.yaml and values.yaml is the chart version; appVersion
and the minecraft.version default are byte-identical, everything else is
additive.

Refs #82.
2026-08-23 19:19:57 +02:00
jklein 2cfc2bfbba Add strict values.schema.json to cyberchef
additionalProperties: false on every chart-owned object level, so a key
the chart does not read is rejected at render time instead of being
silently ignored. Objects passed verbatim into the pod spec (probes,
securityContext, global) stay open - Kubernetes owns their schema there.

Major bump: a schema can break existing deployments that carry dead keys.

Refs #68
2026-08-23 19:19:44 +02:00
jklein 1dd62ba610 Merge pull request #89 from jk-cluster/feat/minecraft-server-config-checksum-java17
Update minecraft-server to the java17 line (3.0.0+up2026.8.2.java17)
2026-08-23 17:18:57 +00:00