mirror of
https://github.com/turnstonelabs/turnstone.git
synced 2026-08-12 23:12:23 -06:00
9334cf0cef
* fix(helm): render the chart Secret for every inline credential Setting llm.existingSecret suppressed the chart's whole Secret, not just the LLM API key it replaces. POSTGRES_PASSWORD and TURNSTONE_JWT_SECRET went unrendered with it while server, console and the migrate Job went on referencing them, so every pod stalled in CreateContainerConfigError. Supplying an LLM Secret is a supported, documented configuration, and it took the install down on both the bundled and external database paths. turnstone.db.secretName compounded it by falling back to turnstone.llm.secretName, pointing the password lookup at the operator's LLM Secret — which has no reason to carry a database password. Both now derive from one predicate. turnstone.db.inlinePassword returns the password when the chart stores it itself and empty when an operator supplies it, so secret.yaml renders on exactly the condition under which turnstone.db.secretName resolves to <fullname>-secrets. The two cannot disagree about where the password lives, which is what the earlier llm.secretName fallback was working around. Each key keeps its own condition, so an existingSecret still suppresses the value it replaces and nothing else. Verified by rendering nine values permutations against both this and the previous templates and diffing every secretKeyRef against the Secrets each tree creates: three permutations fixed, six byte-identical, none regressed. helm lint passes on all nine. The bundled-PostgreSQL default is unaffected and still broken: the subchart generates its password into <fullname>-postgresql, which the chart never reads. It is separately blocked by the migrate hook running before the database exists, so it needs the design decision called for in #932 rather than a secret-name change. * fix(helm): default the inline password so an unset key cannot become one turnstone.db.inlinePassword is reached through include, which captures rendered text rather than a value. A key that is unset rather than empty — "password:" with nothing after it, or --set database.external.password=null — renders as the literal "<no value>", and a ten-character string is truthy, so it satisfied the gate in templates/secret.yaml and landed base64-encoded in POSTGRES_PASSWORD. Workloads then authenticated with the string "<no value>". Reaching the values through default "" keeps unset and empty equivalent, which is what the previous templates got for free by testing the value directly instead of the rendered text. Introduced by the commit before this one; caught in review. The two null spellings are now permanent cases in the render matrix. Across eleven permutations, three are fixed relative to main, eight are byte-identical, none regress, and the inline password still round-trips byte-exact. helm lint passes on all eleven. * docs(helm): narrow the inlinePassword guarantee to what it holds The comment claimed secret.yaml and turnstone.db.secretName cannot disagree about where the password lives. That holds wherever the chart or the operator supplies the password, but not where the bundled subchart generates its own — that lands in the subchart's Secret, which neither helper reads. State the two guarantees that do hold instead. * fix(helm): make the bundled-PostgreSQL default installable The default values have never produced a working install. Two faults, and the first is why the second could not be fixed on its own. The migrate Job ran as a pre-install hook, and Helm creates ordinary resources only once hooks have finished. On a first install that means none of what the migration needs exists yet: not the ConfigMap, not the Secret, and — because the subchart is an ordinary resource — not the database either. #932 worked around the first two by dropping the Job's ServiceAccount reference and inlining its environment, but nothing can work around the third: no reference to the subchart's Secret, however derived, is readable by a hook that runs before the subchart exists. So the Job moves to post-install, and to pre-upgrade rather than post-upgrade: on an upgrade everything is already running, and migrations belong before the new code rolls out rather than after. Helm does not wait for readiness before post-install hooks, so the Job's own retry is what waits for a cold database, and backoffLimit rises to cover an image pull and cluster initialisation. That in turn unwinds the workarounds. The Job takes the chart's ServiceAccount back, and templates/secret.yaml drops the hook annotations it was given so the pre-install Job could read it — those made it a hook resource, untracked by the release, so the credentials survived helm uninstall and were skipped by helm rollback. With ordering fixed the password resolves properly. When the subchart generates its own, turnstone.db.secretName now points at the subchart's Secret instead of at <fullname>-secrets, which never carried the key. The naming is mirrored rather than delegated, since the subchart's helpers expect a context this chart cannot hand them, and it is derived from the release name: a fullnameOverride here renames this chart's resources and leaves the subchart's alone, so "<fullname>-postgresql" would name a Secret that does not exist. Verified across fifteen values permutations against origin/main: nine fixed, six byte-identical, none regressed, helm lint clean on all fifteen. The permutations cover both fullnameOverride spellings, a subchart existingSecret with a renamed key, and the superuser key rule. An external database with no password and no existingSecret is unchanged and still fails at pod start. Passwordless authentication is not something the chart models — the URL always references a password — so that stays as it was rather than becoming a template-time error.