CodeQL is GitHub-only — its analyze step uploads SARIF to GitHub's code-scanning API and assumes a GitHub Security tab; this CI runs on Gitea only, so the job could never go green (it had been red since it was added). Replace it with Semgrep OSS, a plain CLI SAST with no account/platform API, which runs fine on Gitea. - Remove the codeql job (+ its security-events permission) and the schedule trigger (it existed only for codeql; semgrep runs on push + PR). - Add a semgrep job: setup-python + `pip install semgrep` + `semgrep scan --config p/default --config p/csharp --metrics=off`. pip-on-runner (not container:) mirrors the other jobs' model; anonymous registry, telemetry off. - Report-only for now (no --error → job stays green): a local dry-run found 27 findings, mostly CI/config policy (unpinned actions, .npmrc), not app-code vulns. WP-30 tracks triaging them + flipping to --error (a blocking gate). Verified locally: `semgrep scan` runs clean (exit 0 without --error, 306 rules / 450 files). CI behaviour confirmable only on the Gitea runner — watch the run. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>