Commit Graph
543 Commits
Author SHA1 Message Date
popertotsandSisyphus 3c447a5c33 fix(backend): address gift card review findings
Fix #1: remove expiry_date from gift card INSERTs (rolling 24-month via last_used_at only)

Fix #2: add FOR UPDATE to RedeemGiftCard SELECT (race condition)

Fix #6: add ?type=customer|inventory filter to GetGiftCards

Fix #7: add admin_audit_log INSERT to GetUserGiftCardBalanceAdmin

Fix #10: refactor normalizeCode to validators.NormalizeGiftCardCode

Schema: add admin_audit_log table (GDPR Article 30), update testdb.go

Tests: expiry-date-null, inventory-filter, audit-log, db table references

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

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-06-12 10:50:49 +01:00
popertotsandSisyphus e7fd9c89eb style(backend): lowercase error messages across handlers
Normalize error message casing to lowercase for consistency across auth, bookings, services, customer relationship, and profile handlers.

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

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-06-12 10:50:43 +01:00
popertotsandSisyphus b36d8aded8 test(backend): add phone injection-security tests
Verify ValidateUKPhoneNumber rejects SQLi, XSS, command injection, and control character payloads. Also verifies mixed injection-wrapped numbers are rejected (libphonenumber doesn't extract digits from noise).

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

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-06-12 10:50:39 +01:00
popertotsandSisyphus 5f0248540f feat(backend): add email validator package
Add ValidateEmail and NormalizeGiftCardCode functions with comprehensive tests. Migrate guest.go from inline mail.ParseAddress to validators.ValidateEmail.

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

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-06-12 10:50:34 +01:00
popertotsandSisyphus 834c0f1da0 chore: remove Go test binary artifacts
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-06-11 22:08:34 +01:00
popertotsandSisyphus ceb33f7b3a chore(obsidian): update workspace state
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-06-11 22:08:33 +01:00
popertotsandSisyphus 181c58147d docs: add Gift Card Terms, Privacy Policy, Terms, and Testing Architecture
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-06-11 22:08:32 +01:00
popertotsandSisyphus c1fc1a2314 docs: rewrite README and all Obsidian documentation to match current state
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-06-11 22:08:31 +01:00
popertotsandSisyphus e7634ba187 feat(frontend): add email check and gift card support to booking flow
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-06-11 22:08:28 +01:00
popertotsandSisyphus 7a459a3986 feat(frontend): add gift card management UI and payment modal updates
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-06-11 22:08:27 +01:00
popertotsandSisyphus 1be82986a5 feat(frontend): add PhoneInput component with UK validation
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-06-11 22:08:26 +01:00
popertotsandSisyphus 8fd42867a4 feat(db): add gift card tables, audit log, expired balances, and VAT functions
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-06-11 22:08:25 +01:00
popertotsandSisyphus 56d91ba4ef chore(tests): add advisory locks and statement parser for test infrastructure
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-06-11 22:08:23 +01:00
popertotsandSisyphus 6de0371e1d feat(user): add email check endpoint for registered user detection
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-06-11 22:08:22 +01:00
popertotsandSisyphus b750b3c203 feat(scheduling): add gift card expiry and idle account cleanup
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-06-11 22:08:21 +01:00
popertotsandSisyphus 44895a3697 feat(admin): add business settings API and routing for gift card config
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-06-11 22:08:21 +01:00
popertotsandSisyphus 30ded0bb95 feat(payments): add gift card system v2 with management, expiry, inventory, audit log
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-06-11 22:08:18 +01:00
popertots 6756723c60 saved cards store 2026-06-07 12:38:22 +01:00
popertots 75cca8b158 fixes 2026-06-06 15:25:58 +01:00
popertots 59e7dd9fdc fixes 2026-06-06 15:23:10 +01:00
popertots 9c6eeeb426 Fixes 2026-06-06 15:18:37 +01:00
popertots b274d2c47b fixes for giftcards and phone input 2026-06-06 15:11:01 +01:00
popertots 4e174a6123 Fixes for giftcards and phone input 2026-06-06 15:10:48 +01:00
popertots 5258f90b06 Add giftcard management 2026-06-06 14:26:42 +01:00
popertots 310e6aaa80 Add giftcard management 2026-06-06 14:26:33 +01:00
popertots 44c9d423ec fix: restore cardNum definition in addCard
- Re-added 'const cardNum = newCardNumber.replace(/\s/g, '');' inside addCard
- Log actual error to console in catch block of addCard
2026-06-05 21:15:05 +01:00
popertots d2dea38b01 fix: replace crypto.randomUUID with generateIdempotencyKey
- Changed purchase flow to use generateIdempotencyKey() which uses secure
  window.crypto.getRandomValues with a math fallback, avoiding secure-context blocks on HTTP
- Log actual error to console in both Buy and Redeem catch blocks
2026-06-05 21:11:47 +01:00
popertots 883fd3076a fix: disable pay button unless full valid card is entered
- Added isBuyExpiryValid and isBuyCardValid reactive derivations
- Disabled Buy Gift Card button unless card is fully valid (Luhn checked number, future expiry, complete CVC)
- Verified clean compilation with zero warnings
2026-06-05 21:07:13 +01:00
popertots 0d4a74bd4a feat: caret preservation and Luhn validation in card inputs
- Added generic formatAndPreserveCursor() helper on frontend to track
  and restore selection caret position during dynamic input sanitization
- Applied to all card inputs, gift card code inputs, and expiry inputs
- Added Luhn validation (isValidLuhn) for saved cards and gift cards
- Rebuilt payments test DB and got 100% green tests
2026-06-05 21:05:36 +01:00
popertots fd41ca2920 chore: add catch-all for Go test binaries in .gitignore 2026-06-05 16:37:37 +01:00
popertots f4a6033715 feat: financial data retention & aggregation system
Add CleanupExpiredFinancialRecords to enforce HMRC + Limitation Act
compliance (7-year retention, 1-year post-anonymization buffer).

- financial_aggregates table: monthly totals by payment method/type (no PII)
- CleanupExpiredFinancialRecords(): aggregates expired payments/refunds,
  deletes granular records, idempotent via ON CONFLICT DO UPDATE
- Wired into GET /api/availability alongside existing cleanup functions
- 8 tests: 7yr expiry, 1yr buffer, 9yr override, aggregation totals,
  idempotency, active user protection, both-thresholds elapsed, refunds
- testdb.go: financial_aggregates in drop-order and truncate lists
- README + Technical Manual updated
2026-06-05 16:37:04 +01:00
popertotsandSisyphus 06efdfdac0 chore(obsidian): update workspace state
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-06-05 15:40:51 +01:00
popertotsandSisyphus 69420298bd feat(frontend): add booking stats summary section to GDPR page
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-06-05 15:40:46 +01:00
popertotsandSisyphus 5cc3e25a2c fix(db): update FK constraints to SET NULL and expand delete_user anonymization
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-06-05 15:40:43 +01:00
popertotsandSisyphus f88854e5c2 feat(scheduling): add expired loyalty cleanup and extend guest anonymization
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-06-05 15:40:38 +01:00
popertotsandSisyphus 6cc65341a0 docs: update README and Obsidian docs with GDPR compliance system
Update README feature list with GDPR compliance system details. Update Overview.md Data & Compliance section with full Article 15 SAR details. Update Technical Manual: add /gdpr route, gdpr_export.go handler, GET /api/user/gdpr-export endpoint, update Key Functions table, update Guest User System section. Update Future Work backlog: mark #7 GDPR export as complete, update dependency map and Phase 3 execution order. Update test count: 446/449 -> 576/579.

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

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-06-05 12:13:34 +01:00
popertotsandSisyphus 36ad38f670 feat(frontend): add /gdpr page with PDF export and JSON download
New /gdpr route: skeleton loading state, 2s polling for async export, styled report cards/tables matching /schedule and /account styling. 16 data sections with conditional rendering (empty sections hidden). VAT breakdowns hidden until any payment has non-zero VAT. Deposits Required hidden when 0. PDF export via window.print() with print CSS hiding navbar and verification banner. Raw JSON download button. Export My Data button added to Account page under Change Password. Vite worker format set to 'es' for WASM encoder compatibility.

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

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-06-05 12:13:07 +01:00
popertotsandSisyphus b460c2ec20 fix(scheduling): extend AnonymizeStaleGuestAccounts with additional field scrubbing
AnonymizeStaleGuestAccounts now additionally scrubs profile_pic_url (NULL), referral_code (NULL), notes (NULL), and data_retention_consent (FALSE) for stale guest accounts. Previously only scrubbed name, email, phone, and date_of_birth. Ensures comprehensive PII removal for guests with no active/pending bookings and last booking over 6 months old.

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

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-06-05 12:12:38 +01:00
popertotsandSisyphus 40840c0458 feat(user): extend DeleteAccountHandler with external system scrubbing
DeleteAccountHandler now scrubs external systems BEFORE SQL-level anonymization. S3: deletes profile picture from S3/R2 (profiles/{userID}.jpg) when s3.Client is configured. Square: iterates user's saved cards and calls DeleteCardOnFile for each non-deleted card when payments.SquareClient is configured. Both run in background goroutines (non-blocking, best-effort with warning logs). CardDAV contact deletion remains as existing best-effort goroutine.

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

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-06-05 12:12:12 +01:00
popertotsandSisyphus f58a4bd2a9 feat(user): add async GDPR export endpoint with 12h cache and 25 tests
Add GET /api/user/gdpr-export handler (GetGDPRExportHandler) with async background generation — navigation away doesn't cancel. 12h in-memory cache with 5-minute cleanup ticker. Three cache states: MISS (triggers generation), HIT (returns cached data), GENERATING (concurrent request while building). Route registered without RequireVerified middleware so unverified users can export. 25 tests covering: auth rejection, cache miss/hit/generating/expired states, anonymize_user child table scrubbing (social logins, saved cards, verification codes, time blockers, edit notes, notification prefs), export_all_user_data 16-section export, AnonymizeStaleGuestAccounts field scrubbing.

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

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-06-05 12:11:45 +01:00
popertotsandSisyphus bf0571fe84 fix(db): anonymize_user NOT NULL constraint fix + export_all_user_data extensions
Fix anonymize_user() setting exp_month/exp_year to NULL on NOT NULL columns — use placeholder values (1/2000) matching pattern for other NOT NULL columns. Extend export_all_user_data() with 9 new sections: saved_cards, refunds, social_logins, loyalty_redemptions, booking_discounts, edit_requests, affiliate_payouts, verification_codes, forgiven_no_shows. Add total_price to booking objects (sums COALESCE override prices). LEFT JOIN loyalty_redemptions to bookings for booking_date/booking_services. LEFT JOIN booking_discounts to discount_campaigns for campaign_name. Simplify referrals to referrer_name/referred_name using u.fn.

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

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-06-05 12:11:17 +01:00
popertots 6d4bc4d637 feat(loyalty-discount): implement loyalty and discount system
- Add discount campaign management and validation logic
- Update booking handlers with discount application flow
- Add customer relationship endpoints for loyalty tracking
- Update frontend modals (booking, approval, payment, reschedule)
- Add DiscountsManagement and loyalty reference documentation
- Update dev scripts and database init for discount tables
- Clean up completed plan files
2026-06-04 23:13:02 +01:00
popertots 79b23a3cf7 New Plan 2026-06-04 21:12:21 +01:00
popertotsandSisyphus 5e02b90fdc docs: update route references for /admin/notifications move
Updated Technical Manual and Future Work backlog to reflect /notifications → /admin/notifications move and /manage removal.

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

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-06-04 20:09:30 +01:00
popertotsandSisyphus f379e5c09a refactor(routes): move notifications to /admin/notifications, remove /manage
Moved /notifications to /admin/notifications to match admin-only access pattern. Updated NavBar bell icon and mobile menu links. Removed /manage route (leftover prototyping). Pre-hydration redirect already in place for admin-only guard.

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

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-06-04 20:08:34 +01:00
popertotsandSisyphus 24b1823a5d fix(routes): add pre-hydration auth redirects to all protected pages
Replaced slow $effect-based auth checks with synchronous IIFE scripts in <svelte:head> that run during HTML parsing, before Svelte hydration. Covers: /today, /admin, /admin/schedule, /manage, /notifications (admin-only), and /account (auth-required). All redirect via window.location.replace() with no page flash.

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

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-06-04 20:04:54 +01:00
popertotsandSisyphus 413b28b759 fix(login): redirect authenticated users before hydration
Uses a raw IIFE script in <svelte:head> that runs synchronously during HTML parsing, before Svelte hydration. Checks localStorage JWT and calls window.location.replace() for an instant redirect with no page flash.

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

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-06-04 19:50:53 +01:00
popertotsandSisyphus ae1bc0f91a fix(login): redirect authenticated users before page render
Replaced -based redirect with +page.ts load function. Checks localStorage token directly and throws redirect(302) before the component mounts, preventing any flash of the login page.

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

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-06-04 19:48:08 +01:00
popertotsandSisyphus f083da6345 fix(login): redirect authenticated users away from login page
Authenticated users visiting /login are immediately redirected: admins to /today, all others to /.

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

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-06-04 19:46:36 +01:00
popertotsandSisyphus 8a1da43131 test(auth): add referral code case-insensitivity tests
Tests lowercase, uppercase, mixed case, and all caps referral codes against a lowercase stored code. All 4 sub-tests pass, confirming the strings.ToLower fix in RegisterHandler.

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

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-06-04 12:05:20 +01:00