`GITEA_WEBHOOK_SECRET` is now mandatory at startup. The framework
refuses to load_config() when the env var is empty unless the
operator opts into the dev-bypass with `RFC_APP_INSECURE_WEBHOOKS=1`.
This is the v0.18.0 startup-loud-failure shape — the pre-v0.18.0
"silently accept unsigned POSTs when the secret is empty" path is
the bug the proposal targets.
`webhooks.receive`:
* Defense in depth: refuses 500 if the secret is empty at request
time and the dev-bypass is not set (catches the case where
something mutates env after startup).
* Logs a loud warning every time a webhook lands under the
bypass — so a misconfigured production deployment shows up in
the logs even if the operator missed the warning at boot.
* Adds an INFO log at the unknown-repo branch (previously
silently 200-OK'd a hook on a fork or a stale Gitea binding).
`tmp_env` fixture binds a fake secret so the existing 277 tests
boot cleanly; the new test_webhooks_vertical.py exercises both
the production-secret path (valid signature, invalid signature,
missing signature) and the dev-bypass path (config loads with
empty secret when bypass set, refuses without it).
7 new tests; full suite: 284 passed.