Commit Graph
7 Commits
Author SHA1 Message Date
popertots fe88f2084d fix: review-loop B — adversarial findings (sweep auto-refund, admin clamp, 2FA real challenge, opaque refresh tokens, gated client IP, GBP pence)
Loop B aggressive adversarial round (3 attack agents) + fix + secondary + verification:
- CRITICAL: sweep replay auto-refunds provably-created-later duplicate charges (gated on parseable CreatedAt); 22h legitimate-retry window == 22h sweep cutoff (no dead zone)
- HIGH: admin Take Payment clamps to remaining obligation (cash/giftcard/saved-card/terminal); no unintended tip from overflow; campaign credit against remaining
- HIGH: /api/services/eligible-for/{id} requires auth + owner-or-admin (DOB/age + patch-test health-data leak closed)
- HIGH: opaque refresh-token rotation (login/refresh return {token, jti, refreshToken}; refresh REQUIRES opaque token; single-use rotation; logout revokes; access token rejected at refresh)
- HIGH: saved-card charges require a REAL 2FA verification code (B6/B10) — backend gate on all 8 charge paths + shared TwoFactorCodeInput frontend component on all 7 surfaces; 2FA gate is no longer setup-flag-only
- MEDIUM: ungated CF-Connecting-IP in reserve/admin_reserve gated via exported mw.ClientIP; 2FA limiter keyed on userID alone (no header-rotation bypass); ChangePassword actually revokes JTI + refresh tokens; 2FA setup mint cooldown + persistent failed-attempt counter; campaign redemption race surfaces campaign_fully_redeemed
- Terminal saved-card VAT applied (was under-collected); age-guard reconcile failures notify; isWeakJWTSecret entropy gate; gift-card redeem per-card counter + per-user limiter; webhook signature key startup validation
- NEW internal/twofa package (single source of truth breaking the payments<->user import cycle); consolidation of duplicate 2FA hash/verify
- Frontend: refresh-token storage + rotation, TwoFactorCodeInput component, amountPaidPence in admin modal, B5/B6/B10 contract wiring; 70 frontend tests
- Tests: loop_b_fixes_test.go, internal/twofa tests, updated auth/services/profile/twofa/mw tests

All 26 backend packages pass (incl. internal/twofa); frontend 70/70 + build clean; env-docs 41/41.
2026-08-22 00:34:50 +01:00
popertots faceb9809c fix: review-loop A — discount credit on admin payments, campaign over-credit cap, sweep replay window, dedup refund revalidation, duplication/modularisation, GBP pence naming
Round-A fresh review (6 agents) + fix + secondary cross-cutting + verification rounds:
- F1: campaign discounts reduce the charged amount (deposit credit + admin PaymentModal discounted total); capDiscountToRemainingObligation prevents over-credit at completion in all four campaign blocks
- F2: sweep replay rescue distinguishes legitimate same-key retries (21h window) from expired-key new charges; ccof blind-fails leave pending + CRITICAL instead of clawing back
- F3: post-start online overflow carved as a tip record (mirrors terminal split builder)
- A1: single-source Square decline-code classification (till delegates to square.IsDefinitivePaymentError)
- A2/A5: refund attempt-cap literals consolidated; refund-failure counter capped + reset on terminal resolutions + admin notifications
- A3/A9: idempotency helpers adopted across derivations; IsExplicitDevOrMockEnv relocated + all gates unified (incl. health-check)
- A7: 2FA user+IP limiter + TRUST_PROXY_HEADERS startup warning; SNAPSHOT_ENC_KEY startup validation; TWO_FACTOR_PEPPER docs corrected
- A8: snapshot encryption on all 6 write sites + marker-aware reuse paths; MPV->SPV effective voucher type (single VAT point)
- A10/A11/A12/A16: gift-card slot scan advances past failed; amount-aware refund reconciliation; completed-booking refund re-check; PaymentWasRefunded on SquareClient interface
- Dedup refund revalidation on tip/terminal/gift-card paths; sweep acknowledged_at IS NULL parity; refund-notification single source (exported payments.InsertRefundFailedNotifications)
- Duplication/modularisation round: shared frontend helpers (sanitizeDecimalInput, campaignDiscountCents, twoFactorBlocksSavedCards getter, generateUUID), single-source MaxIdempotencyKeyLength, notification-helper consolidation, snapshot-guard comments
- Cross-cutting GBP rename: Cents->Pence across backend + frontend + tests (26 identifiers, 16 files)
- Tests: 11 behavior-change tests updated to new invariants; coverage for fixed functions; frontend vitest 55 tests; docs corrected (test counts, 2FA delivery, pre-launch checklist, resolution status)
- gitleaks: allowlist backend/internal/square test fixtures (mock idempotency keys)

All 25 backend packages pass; frontend 55/55 + build clean; env-docs 41/41.
2026-08-22 00:34:50 +01:00
popertotsandSisyphus 510828c924 chore: run go fix for Go 1.26 modernization
CI / Go vulnerabilities (push) Successful in 1m10s
CI / Build & Vet (push) Successful in 1m39s
CI / Frontend build (gate) (push) Successful in 1m42s
CI / Frontend QC (audit) (push) Successful in 56s
CI / Frontend QC (typecheck) (push) Successful in 1m36s
CI / Frontend QC (lint) (push) Successful in 1m51s
CI / Tests (prod) (push) Has been cancelled
CI / Tests (dev) (push) Has been cancelled
CI / Race (prod) (push) Has been cancelled
CI / Race (dev) (push) Has been cancelled
106 files: interface{}→any, strings.Split→SplitSeq, CutPrefix/Cut, strings.Builder, slices.Contains, remove redundant // +build directives, gofmt import ordering and indentation.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-07-09 17:25:23 +01:00
popertotsandSisyphus 7b24f8e484 refactor(payments): integrate VAT into gift card buy flow and wrap in transactions
Refactor BuyGiftCard to insert pending payment before Square call with VAT applied. Add transaction wrapping to gift card handlers. Remove redundant Content-Type header sets. Migrate all time.Now() to clock.Now().

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-06-24 23:43:40 +01:00
popertotsandSisyphus 220a0ef6e8 refactor(backend): update test files for PoolProxy and per-test transactions
Migrate all test files from SetupTestDB/db.DB pattern to per-test transactions:

- Replace SetupTestDB(t) with SetupTestTx(t) for context + transaction
- Replace db.DB.Query/QueryRow/Exec with tx.Query/QueryRow/Exec
- Replace context.Background() with context from SetupTestTx
- Replace defer rows.Close() pattern with explicit rows.Close()
- Add testdb.SeedBaseline(pool) to all TestMain functions
- Wire db.Conn = db.NewPoolProxy(pool) in all TestMain functions

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-06-21 19:29:24 +01:00
popertotsandSisyphus b03c4f6247 refactor(backend): replace resetTestData with SetupTestDB and add new tests
Migrate all test files from resetTestData(t) to testutils.SetupTestDB(t) for isolated per-package test databases.

- Add new feature tests: name history assertions, referral discount preview,
  time blockers, email validation, GDPR export, loyalty manual redemption
- Update existing tests to use batch queries and SetupTestDB
- Remove test_helpers.go resetTestData infrastructure
- Add comprehensive user profile tests (442 new lines)

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-06-20 16:57:36 +01:00
popertotsandSisyphus aeab289be9 feat(backend): add payment discount preview and status tests
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-06-18 16:26:34 +01:00