docs release evidence p14 t04 votes - AlexandreZanata/Abastevo GitHub Wiki
P14-T04 — Validity votes and percentages
Status: LOCAL_DONE on codex/phase-14-station-feedback (phase PR
#33, draft). Issue: #31 (slice 4 of 5; issue stays open until the
phase PR merges). No live-provider contact.
Slice acceptance (frozen before coding)
- T04 (this commit) — changeable one-account-one-revision votes:
000025(live-unique per account/comment/revision, exact per-revision tallies), self-vote refusal, converge/rewrite/ idempotent-remove, revision move on comment edit, vote/remove/ tally transport reusingFeedbackAgreementmath, exact display counts. Zero votes is null; denominators match the shared fixtures (2/1 → 6666).
What changed
db/migrations/000025_feedback_votes.sql(append-only) + 7 owner queries + committed regeneration.feedback/domain: vote choices,StoredVote,VoteTally(+Agreementfold through the single math path),ErrSelfVote/ErrVoteChoiceInvalid+ verdicts.feedback/application:VoteStore,Service.Vote/RemoveVote/Tally/RebuildTally(gate + target + self checks; removal converges no-op by task text, unlike rating delete), MemStore parity with signed deltas.feedback/adapters: transactionalPGStorelanes;httpvote/remove/tally routes (200 tallies, 400/401/403/ 404 mapping) with null-percentage JSON.- Tallies AND rating stats moved from recompute-in-transaction to atomic signed deltas (see bug below); full recomputation stays in the Rebuild paths for reconciliation.
contracts/openapi/v1.yaml:FeedbackTallyschema + 3 paths;vacuum0/0; 2 tally vectors keepapicontractgreen.
Concurrency bug found and fixed in-task
The T04 8-voter race tallied 2/0 instead of 8/0: recompute-in-
transaction loses updates under concurrency (overlapping
snapshots, last-writer-wins stale counts). The same latent race
existed in T02 rating stats (its tests never raced multiple
accounts). Both lanes now apply signed deltas in a single
INSERT … ON CONFLICT DO UPDATE statement, which serializes on
the row; recompute remains only for rebuilds. New multi-account
ratings race test covers the T02 lane. This fix is recorded
here, not hidden in a rewrite.
RED → GREEN
- RED proven by neutering the self-vote guard: author votes proceed instead of refusing; GREEN on restore.
Validation (exact commands, this host)
cd backend && GOTOOLCHAIN=go1.27.1 go build ./... && sqlc vet && sqlc generate
gofmt -l internal/modules/feedback cmd/api; GOTOOLCHAIN=go1.27.1 go vet ./internal/modules/feedback/... ./cmd/api/...
GOTOOLCHAIN=go1.27.1 go test -count=1 ./internal/modules/feedback/...
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/feedback/...
vacuum lint -r contracts/openapi/vacuum-rules.yaml contracts/openapi/v1.yaml --no-update-check
(cd backend && GOTOOLCHAIN=go1.27.1 go test -count=1 ./internal/platform/apicontract/...)
make quick-verify
git diff --check
Outcome: unit green (vote/change/remove/revision/gate matrix);
integration with -race green (golden 2/1 denominator,
change/remove/revision, 8-voter exact tally, suspended
refusal); vacuum 0/0/26 info; apicontract ok;
quick-verify selection=full ok; diff --check clean;
secrets scan clean.
Limits (not claimed)
- No moderation/privacy (T05); no jobs — tallies stay synchronous by design (single-statement deltas need no broker; rebuilds are the replay story, documented above).
- Reads are no-store; shared-cache policy deferred.
Rollback
Append-only migrations stay; code rollback = delete vote slices (domain records, application, adapters, transport, OpenAPI additions). Ratings/comments keep working.
Next
P14-T05 moderation/privacy/exit (#32, same branch). Issue #31 stays open until the phase PR merges.