chore: the pre-push hook refuses unsigned commits for main, as the deploy does
All checks were successful
CI / check (push) Successful in 11m56s
CI / deploy (push) Successful in 19s

deploy/redeploy.sh deploys main only if every new commit is signed by a key
in deploy/allowed-signers, and finds out after CI. On 2026-10-09 that held
learn.halkyon.eu at v0.2.2 for two days: 37 commits had reached main
unsigned, and every deploy since refused them. tool/check_signatures.sh
applies the same rule to a push, to the commits it brings to main that the
remote doesn't have yet (the list as the pushed commit has it), and
tool/check.sh runs it first when it runs as the pre-push hook: a second,
where the rest takes minutes. CI runs check.sh under its own name and
skips it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MMm7usAo6q9ZZRoPkWjoxi
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
Tizian 「ティツィアーン」 2026-10-09 18:56:18 +02:00
commit 3bbdb9d747
Signed by: raisondetredev
GPG key ID: 07F6FCF405488B64

View file

@ -70,7 +70,7 @@ A spaced-repetition learning app: studysets of flashcards, reviewed on an FSRS s
- **Before keeping a framework default, name the alternatives** and recommend one, especially where a choice becomes expensive once users or data exist.
- Every decision carries its reason (in `NEXT.md` or an ADR under `docs/adr/`).
- **Commits** are GPG-signed and carry a DCO `Signed-off-by` trailer (`git commit -s`; a local `prepare-commit-msg` hook adds it automatically).
- **Pushes** pass `tool/check.sh` first, through a local `pre-push` hook (in a fresh clone: `ln -s ../../tool/check.sh .git/hooks/pre-push`). CI runs it again, and a green `main` deploys itself (see *CI and deploys*), so an unsigned commit on `main` blocks every deploy after it.
- **Pushes** pass `tool/check.sh` first, through a local `pre-push` hook (in a fresh clone: `ln -s ../../tool/check.sh .git/hooks/pre-push`). CI runs it again, and a green `main` deploys itself (see *CI and deploys*), so an unsigned commit on `main` blocks every deploy after it. As the hook, the script first refuses a push to `main` that brings a commit not signed by a key in `deploy/allowed-signers` (`tool/check_signatures.sh`, the deploy's own rule), so it fails on the laptop rather than after CI.
- **Lints**: LeanCode's strict set (`leancode_lint`), configured once in the root `analysis_options.yaml`, which also enables its analyzer plugin. Plugins can only be enabled at the root of a pub workspace and only reach packages whose options include that file, so the server and the app include it; the generated client doesn't. Every `// ignore:` gets a comment saying why (`document_ignores`). The server switches off the four rules for Dart v3.13's constructor syntax (`use_primary_constructors`, `use_declaring_parameters`, `empty_container_bodies`, `unnecessary_type_name_in_constructor`): Serverpod's code generator (checked with v4.0.3) can't parse that syntax in endpoint files yet.
## App architecture