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>
Crussell
Nail salon booking platform — Go 1.25 backend + SvelteKit 5 SPA + PostgreSQL 17 + Docker. Built for a UK sole-trader nail artist. Europe/London timezone only, UK phone format only, single-employee business.
Features
Booking: Self-service (customer), walk-in (admin), call-in (admin). Slot reservations prevent double-booking (4 TTL types). Guest accounts with GDPR-compliant anonymization. Service eligibility based on age + patch test validity.
Payments: Square Terminal (in-person) + Web Payments SDK (online). Cash with change calculation. Gift cards (12-digit code or account balance). Saved cards for faster checkout. Tips on completed bookings. Refunds. All payment types: deposit, full, partial, balance, tip.
Gift Cards: Multi-method purchase (cash, card machine, online card, giveaway). Inventory cards for stock management. 24-month rolling expiry. Idle account cleanup (2yr/5yr thresholds). Expired balance recovery with admin audit trail. Transaction audit log. Idempotency keys for purchases.
Scheduling: Default weekly hours, holiday/exceptional groups, time blockers (one-off + recurring with cron). Lunch protection. Late-night lock (22:00–11:00). Admin schedule page (Google Calendar-style week view).
Admin: Today page with interactive calendar grid. Booking management (create, edit, reschedule, approve, cancel). User management with customer relationship data (spend, visits, top services). Discount campaigns (time-based and milestone). Time blocker CRUD. Portfolio image upload with tag management. Gift card management. Business settings (VAT, gift card config). Notification queue with priority ordering.
Loyalty & Discounts: 1 stamp per paid appointment (max 1/day). 10 stamps → 10% off next visit. Campaigns: time-based, per-user milestone, global milestone, anniversary. All discounts stack additively against original total.
Compliance: GDPR Article 15 data export (async, 12h cache, 16-section JSON + PDF). Account deletion with external system scrubbing (S3, Square). Guest PII anonymized 6 months post-appointment. UK financial data retention (7 years). Gift card SPV/MPV VAT treatment configurable.
Frontend: Portfolio gallery with tag/category filtering, multi-format images (AVIF/WebP/JPEG/JXL with WASM client-side encoding). MapLibre GL map on contact page. PhoneInput component with UK validation. CharCounter for long notes.
Infrastructure: Docker Compose (postgres, backend, sabredav, nginx). Dev mock for Square payments (//go:build dev). RustFS dev storage, Cloudflare R2 for prod. SabreDAV CardDAV sync for profile photos.
Limitations
- Single employee — no multi-staff scheduling, no team management
- No email/SMS — SMTP integration not wired; booking reminders, password resets, and notifications are UI-only
- No production S3/R2 — prod storage stubs return "not implemented"
- No social auth — OAuth providers (Google, Microsoft, Facebook) not registered
- No dark mode, no PWA, no recurring bookings, no CSV export
- Password reset flow exists backend-only — no frontend link
- No error tracking/monitoring — Sentry not configured
Prerequisites
| Tool | Version |
|---|---|
| Docker & Docker Compose | >= 20.10 |
| Go | >= 1.22 |
| Node | >= 18 (npm) |
| tmux | >= 3.0 |
Getting Started
cp .env.example .env
# Edit .env — set POSTGRES_*, JWT_SECRET_KEY
docker compose up --build -d
| Service | URL |
|---|---|
| Frontend | http://localhost |
| API | http://localhost/api |
| SabreDAV | http://localhost/dav |
Local dev (tmux)
./local-dev-2.sh
Launches 4-pane tmux session: psql console, Go dev server, Svelte dev server, Rustfs logs. Seeds 20 users, 12 services, 43 bookings, guest accounts, time blockers, exceptional hours.
Default logins (password: password):
- Admin:
admin@example.com - User:
user@example.com
Building & Testing
cd backend && go build -o bin/backend ./main.go
cd frontend && npm ci && npm run build
cd backend && go test -tags "test,dev" -p 1 ./... # 633/636 passing, 3 skipped
Full Documentation
Detailed architecture, schema, admin workflows, user journeys, and backlog in obsidian/Crussell/.