docs release evidence p13 t04d write gate - AlexandreZanata/Abastevo GitHub Wiki
P13-T04D — Social-write gate + suspend-revoke races
Status: LOCAL_DONE on codex/phase-13-free-accounts (phase PR #27,
draft). Issue: #25 (slice 4 of P13-T04 — P13-T04 COMPLETE, pending
phase merge). No live-provider contact.
Slice acceptance (frozen before coding)
- T04D (this commit) — enforcement of suspension/erasure on social
writes:
ErrAccountBlocked+ nil-safeCheckAccounton communityPorts/VotePorts, enforced in Submit/Confirm/Dispute before quota burn; HTTP 403community.account-blocked; account-sideBindingBlockedhelper (unbound keeps the anonymous baseline; bound follows owner status; deleted reads as unbound since bindings drop at deletion);main.gowiring for both port sets; suspend-storm race proof (concurrent session use vs suspend stays closed, post-commit everything refuses, every family revoked). Key purge of ex-contributors stays with the privacy erasure flow (P07), which retires keys; the audit ledger retains contributor IDs for that operator path.
What changed
community/application:ErrAccountBlocked;CheckAccountports onPorts+VotePorts(nil = pre-account baseline); gate before quota in all three write use cases.community/adapters/http: 403community.account-blockedmapping (+ table row).account/application/binding.go:BindingBlockedhelper over theStoreport (no new queries).cmd/api/main.go: sharedaccountStorehandle feeds the account service plus thecheckAccountGateclosure (blocked →ErrAccountBlocked, store errors propagate to 500) wired into both community port sets.- Tests: community
gate_test.go(block before quota, error passthrough, nil baseline, votes block); accountBindingBlockedunit matrix + PG matrix;pggatesuspend storm (4 independent logins × validate/refresh racers + suspender, stable across 3 runs).
RED → GREEN
- RED proven by dropping the
Submitgate call: a blocked submit proceeds into execution instead of refusing withErrAccountBlocked(test fails); GREEN on restore. - Storm-test bug found and fixed in-task: shared-session racers
confused post-rotation stale-token denial (
code-unknown, correct behavior) with gate failure. Independent logins per racer pair plus kind-aware classification fixed it; the investigation is recorded here, not hidden.
Validation (exact commands, this host)
cd backend && GOTOOLCHAIN=go1.27.1 go build ./... && sqlc vet && sqlc generate
gofmt -l internal/modules/account internal/modules/community cmd/api
GOTOOLCHAIN=go1.27.1 go vet ./internal/modules/account/... ./internal/modules/community/... ./cmd/api/...
GOTOOLCHAIN=go1.27.1 go test -count=1 ./internal/modules/account/... ./internal/modules/community/...
export ANPFUEL_TEST_DATABASE_URL=postgres://anpfuel:[email protected]:5434/anpfuel?sslmode=disable
GOTOOLCHAIN=go1.27.1 go test -count=1 -race -tags=integration ./internal/modules/account/... ./internal/modules/community/...
GOTOOLCHAIN=go1.27.1 go test -count=3 -run TestPGSuspendStormClosesSessions -tags=integration ./internal/modules/account/adapters/
make quick-verify
git diff --check
Outcome: unit green (community gate 2/2 + votes mapping row,
account gate matrix); integration with -race green (account +
community incl. storm 3/3); vacuum 0/0/14 info (no spec change);
quick-verify selection=full ok 14s; diff --check clean;
secrets scan clean.
Limits (not claimed)
- Data purge of ex-contributor social rows stays with the privacy erasure flow (existing per-contributor scopes + ledger replay); this slice blocks writes, which is the T04 acceptance.
- Validation-time recheck needs token→contributor reverse lookup; submit-time TOCTOU vs suspend matches the quota pattern and the storm proves the session layer closes it.
- Live providers stay P13-T05/G13.
Rollback
No migration change in this slice. Code rollback = revert gate ports, helper, wiring and tests; account/community behavior returns to T04C.
Next
P13-T05 shared and native login integration (#26, same branch; needs G12 device evidence per roadmap). Issue #25 stays open until the phase PR merges.