Release 0.6.0: anonymous-write gates audit + hardening
Sweep-the-edges hardening release (roadmap item #4). Audits every write-shaped backend endpoint to confirm each one enforces an explicit auth.require_contributor (or stricter) gate before doing state-changing work; adds a regression test net (test_anon_offlimits_vertical.py, 12 tests, 66 assertions) so future endpoints can't quietly ship without a gate. The only behaviour change: GET /api/rfcs/<slug>/graduate/progress now requires auth.require_user since the step detail (repo name, PR number, rollback steps) isn't part of the v0.3.0 anonymous-read contract. No schema, no env, no dependency changes; operator action is rebuild + restart per CHANGELOG §0.6.0 upgrade steps. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -23,6 +23,105 @@ skip versions are the composition of each intervening adjacent
|
||||
release's steps in order — no A-to-B path is pre-computed beyond
|
||||
that.
|
||||
|
||||
## 0.6.0 — 2026-05-28
|
||||
|
||||
**Minor — no operator action required.** A sweep-the-edges hardening
|
||||
release (roadmap item #4, "anon discuss + contribute off-limits") that
|
||||
audits every write-shaped backend endpoint and asserts each one
|
||||
enforces an explicit `auth.require_contributor` (or stricter) gate
|
||||
before doing any state-changing work. v0.3.0 hid write affordances
|
||||
behind a sign-in CTA on the frontend; v0.5.0 added the PR-less
|
||||
discussion surface with its own write gate; v0.6.0 sweeps the rest
|
||||
and adds a regression test net so future endpoints can't quietly
|
||||
ship without a gate. No schema migration, no env-var changes, no
|
||||
new dependencies. The only behavioural change is one tightening: the
|
||||
`GET /api/rfcs/<slug>/graduate/progress` SSE now requires
|
||||
`auth.require_user` since it surfaces operator-visible step detail
|
||||
(repo name, PR number, rollback steps) not part of the v0.3.0
|
||||
anonymous-read contract for catalog/RFC bodies.
|
||||
|
||||
### Changed
|
||||
|
||||
- **`backend/app/api_graduation.py`** — `GET /graduate/progress`
|
||||
now calls `auth.require_user(request)` as its first line.
|
||||
Anonymous callers receive 401 instead of being able to subscribe
|
||||
to a graduation's SSE. The floor is `require_user` (not
|
||||
`require_contributor`) so a write-muted operator can still observe
|
||||
the progress of a graduation they kicked off before being muted.
|
||||
- **SPEC `§6.1`** (`SPEC.md`) — the Anonymous role's bullet now
|
||||
documents the v0.6.0 audit: every write-shaped endpoint in §17
|
||||
enforces an explicit gate; anonymous writes refuse 401. The list
|
||||
of audited write families is recorded in-line.
|
||||
- **SPEC `§10.10`** — the discussion-vs-contribution section now
|
||||
records that the v0.5.0 write gates have a regression test net
|
||||
(`test_anon_offlimits_vertical.py`) added in v0.6.0.
|
||||
- **SPEC `§17`** — the `GET /api/rfcs/<slug>/graduate/progress`
|
||||
bullet now documents the `require_user` gate added in v0.6.0,
|
||||
with the rationale.
|
||||
|
||||
### Added (tests)
|
||||
|
||||
- **`backend/tests/test_anon_offlimits_vertical.py`** — twelve new
|
||||
tests asserting that every write-shaped endpoint surveyed in the
|
||||
v0.6.0 audit refuses anonymous callers with 401, and that the five
|
||||
anonymous-read surfaces (health, philosophy, auth/me, catalog,
|
||||
RFC view, discussion threads, proposals) stay reachable. Sixty-six
|
||||
assertions in total, covering: propose; proposal merge / decline /
|
||||
withdraw; branch promote-to-branch / start-edit-branch / metadata /
|
||||
manual-flush / visibility / grants (POST + DELETE) / threads (POST)
|
||||
/ messages (POST) / resolve / chat-seen / changes (accept / decline
|
||||
/ reask) / chat-stream; super-draft start-edit-branch + metadata;
|
||||
PR pr-draft / open / seen / review / merge / withdraw /
|
||||
description / resolution-branch; discussion thread create + message
|
||||
post + resolve; admin role / mute / allowlist (POST + DELETE) plus
|
||||
the admin reads; notification preferences / quiet-hours / watch /
|
||||
mark-read / user-mute (POST + DELETE); funder credentials (POST +
|
||||
DELETE) + consent (POST + DELETE); graduation kickoff + claim +
|
||||
progress SSE; PR review page anonymous-readable.
|
||||
|
||||
### Anonymous-writeable allowlist
|
||||
|
||||
Two endpoints are intentionally anonymous-by-design. They are not
|
||||
audit findings; they are documented here so the contract is
|
||||
explicit:
|
||||
|
||||
- `GET /auth/login` and `GET /auth/callback` — the OAuth
|
||||
round-trip. Anonymous-by-design because they ARE the sign-in
|
||||
entrypoint.
|
||||
- `POST /api/webhooks/gitea` and `POST /api/webhooks/email-bounce`
|
||||
— anonymous in the session sense but authenticated by HMAC shared
|
||||
secret (`GITEA_WEBHOOK_SECRET` and `WEBHOOK_EMAIL_BOUNCE_SECRET`
|
||||
respectively). The webhook receiver is the wrong place for an
|
||||
authenticated session; the shared-secret shape is correct.
|
||||
|
||||
### §19.2 candidates surfaced
|
||||
|
||||
- None unique to this release. The two pre-existing candidates the
|
||||
audit touched — anonymous-read polish for the discussion surface
|
||||
(carried from v0.5.0) and the operator-visibility floor on
|
||||
graduation progress — were settled here as `require_user` on
|
||||
`/graduate/progress` rather than deferred.
|
||||
|
||||
### Upgrade steps (from 0.5.0)
|
||||
|
||||
1. The deployment **MUST** rebuild the frontend (`npm install &&
|
||||
npm run build`) so the frontend bundle's reported version matches
|
||||
the backend's. No new env vars; existing `frontend/.env` is
|
||||
sufficient.
|
||||
2. The deployment **MUST** restart the backend so the new
|
||||
`require_user` gate on `/graduate/progress` is enforced. No
|
||||
schema migration runs.
|
||||
3. The deployment **MAY** announce the audit completion to
|
||||
operators: every write-shaped backend endpoint now enforces an
|
||||
explicit gate, and the `test_anon_offlimits_vertical.py` test
|
||||
net asserts the contract on every CI run. The audited surfaces
|
||||
are listed in the `Added (tests)` section above and in `SPEC.md`
|
||||
§6.1.
|
||||
4. The deployment **MUST NOT** assume any new envelope behaviour:
|
||||
v0.6.0 is purely a hardening release. No schema, no env, no
|
||||
dependency changes; the operator's role is reduced to rebuild +
|
||||
restart.
|
||||
|
||||
## 0.5.0 — 2026-05-27
|
||||
|
||||
**Minor — no operator action required.** This release wires the
|
||||
|
||||
Reference in New Issue
Block a user