sec: persist Functions Plane CRON_SECRET across provisions#16
Merged
Conversation
prepareFunctions() minted CRON_SECRET fresh on every call and never stored it, so any reconcile / re-provision / update (docker rm -f + docker run) silently rotated it. Cron callers that cached the old value — systemd timers, edge-function crons — then failed every invocation because the presented X-Cron-Secret no longer matched the container env. Flagged by Svalinn/deepsec (HIGH). Persist it like jwt_secret: add a nullable `functions_cron_secret` column to `projects` (control migration 0013, add-column-if-not-exists, applied on boot via `pnpm bootstrap`); prepareFunctions() reads it back and mints a new value only when the column is NULL (first provision). The secret is now stable across container replacements. Note: an already-provisioned Functions Plane gets a one-time secret rotation on its next re-provision (column starts NULL) — same effect a re-provision has today — and is stable thereafter. Card: Brokk a8b1160c (svalinn:hauldr:deepsec:cron-secret-rotation) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
O que
Persiste o
CRON_SECRETdo Functions Plane na tabelaprojects(control migration0013) em vez de regenerá-lo a cada provision.Por quê (Svalinn/deepsec — HIGH)
prepareFunctions()geravarandomBytes(24)a cada chamada e nunca armazenava. Todo reconcile/re-provision/update fazdocker rm -f+docker run→ container novo com secret novo. Consumidores que cachearam o valor antigo (timers systemd, crons de edge function) passavam a ser rejeitados (X-Cron-Secret não bate) → cron silenciosamente quebrado.Como
control/0013_functions_cron_secret.sql:add column if not exists functions_cron_secret text(nullable, aplicada no boot viapnpm bootstrap; idempotente, não-bloqueante).prepareFunctions(): lê a coluna; se NULL, gera+persiste; usa o valor estável. Só gera novo no 1º provision. Mesmo padrão dojwt_secret.Aceite
provisionFunctions()no mesmo projeto → mesmo CRON_SECRET (estável entre recriações). ✓Deploy
Não deployar agora. Código+migration acumulam na
main; rollout numa janela recriando SÓ o containercontrol-plane(aplica a migration no boot). Apphauldr= compose com o Postgres compartilhado, não redeployar de dia.Card Brokk:
a8b1160c-f356-4892-a8f8-7688f1f89181🤖 Generated with Claude Code