docs: correct Gitea Actions guarantees
CI / verify (pull_request) Successful in 29s
CI / infrastructure-smoke (pull_request) Successful in 20s
CI / migration-smoke (pull_request) Failing after 39s

The security document claimed the CI workflow "is least privilege" because it
declares `permissions: contents: read`. That is not true on the server this
repository actually uses.

The inventoried server is Gitea 1.24.2, and its official comparison page lists
`permissions` / `jobs.<job_id>.permissions`, `concurrency`, and
`jobs.<job_id>.timeout-minutes` under unsupported workflow syntax — verified
against https://docs.gitea.com/1.24/usage/actions/comparison rather than assumed.
On this server those keys are inert, so the branch cannot claim the in-job
GITEA_TOKEN is read-only, and cannot claim YAML-enforced timeout or concurrency
behavior. Job-token permission controls, repository/owner defaults, and
server-side maximum-permission clamping arrive in the 1.26 feature line
(https://docs.gitea.com/1.26/usage/actions/token-permissions).

The document now separates what is actually true of this repository — full-SHA
action pins, frozen-lockfile install, no pull_request_target, no referenced
secret, `persist-credentials: false` on every checkout, and the declared
`permissions` block — from what the server enforces. It also states precisely
what `persist-credentials: false` proves: checkout leaves no credential in
`.git/config` for a later step, which is not the same as removing or reducing
the job token. The CI blockers are recorded: upgrade to a reviewed supported
release, configure repository/owner defaults and a maximum permission, prove
against the real server what the token cannot do, move timeout/cancellation/
teardown into the trusted provisioner and reaper, and finish the disposable-guest
proof before opening the real pull request.

The workflow keeps every declaration — they are already correct for a supported
Gitea release and for GitHub Actions — and gains a comment saying plainly that
this server ignores them, so no future reader mistakes them for enforcement.

Nothing about runners, proxies, firewalls, or deployment is asserted here.

Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
ekklesia
2026-07-28 20:10:20 -05:00
co-authored by Claude Opus 5
parent cda841f8c7
commit a2db774b8c
2 changed files with 81 additions and 11 deletions
+17
View File
@@ -1,5 +1,22 @@
name: CI
# IMPORTANT — the currently inventoried server is Gitea 1.24.2, which *ignores* several keys used
# below. Per https://docs.gitea.com/1.24/usage/actions/comparison, its unsupported workflow syntax
# includes `permissions` / `jobs.<job_id>.permissions`, `concurrency`, and
# `jobs.<job_id>.timeout-minutes`. They are declared here deliberately, so the workflow is already
# correct on a supported release and on GitHub Actions, but on this server they are inert:
#
# * `permissions:` does NOT restrict the in-job `GITEA_TOKEN`. Job-token permission controls,
# repository/owner defaults, and server-side maximum-permission clamping arrive in the 1.26
# feature line (https://docs.gitea.com/1.26/usage/actions/token-permissions). Until the server
# is upgraded and configured, the token's authority is whatever the server grants — not what
# this file requests.
# * `concurrency:` and `timeout-minutes:` are NOT bounded-execution guarantees here. Cancellation,
# timeout, and teardown must be enforced by the trusted runner provisioner/reaper.
#
# `persist-credentials: false` below is unaffected by any of this and is enforced by the action
# itself. See docs/development/security.md.
on:
pull_request:
push: