Files
Crussell/obsidian/Crussell/Future Work - Gap Backlog.md
T
popertots 457f7a452e Update docs: test counts, Square wire contract, planned upcoming integrations
Refresh README and obsidian docs to the post-review state: 1,902 tests passed (4 skipped), 23 jobs / three sweeps, nonce-direct one-off charges, save-only card-on-file, GDPR square-reference scrubbing, /terms and /privacy-policy routes, webhook fail-closed wording. Mark Email, S3/R2, Mettle/FreeAgent accounting, and user notification delivery as planned upcoming bodies of work (including new backlog item P15) so references no longer read as dead features.
2026-08-22 00:34:49 +01:00

18 KiB
Raw Blame History

Future Work — Gap Backlog

Last Updated: August 2026 Status: Living backlog — add to this as gaps are discovered Previous version: OUT OF DATE — this replaces the prior document. Completed items removed, new items added from exhaustive codebase audit.

This document has three lists: Pre-Launch (integration tasks), MVP (missing features for daily ops), Stretch (nice-to-have). Items are numbered sequentially. All done items are removed without tracking (see "Previously Completed" sections).

Development Context

Much of the application was built rapidly in development mode. External integrations (Square payments, S3/R2 storage, SMTP email, OAuth, error monitoring) were stubbed out as the business logic evolved — mocks and placeholders that let us move fast without configuring real services. Square payments has since been fully implemented; the remaining integrations (S3/R2 storage, SMTP email, OAuth, error monitoring) are the upcoming bodies of work.

Those dev placeholders have not kept pace with the application's feature growth. As we approach production, each needs:

  1. A production-side implementation wired alongside the dev mock
  2. The dev stub itself may need updating to better reflect real-world behaviour
  3. End-to-end alignment between what the application expects and what the integration delivers

Some items in this backlog are genuine missing features — these sit in MVP/Stretch. But many are simply "the app finished its dev journey and needs its production integrations wired up."


Pre-Launch — Production Integration Tasks

These are things that work fine in dev (with mocks) but need real implementations hooked in before production goes live. Each is an expected step in the dev→prod journey — the app was built this way deliberately to stay fast.

# Task Effort Area Dev Status Notes
P2 S3/R2 storage: implement prod side of the abstraction M (2-3d) Backend Dev works (internal/s3/s3_dev.go — RustFS + in-memory fallback). Prod side (internal/s3/s3.go:52-62) returns "not implemented" for Upload/Download/Delete. The prod S3Client struct lacks the *s3.Client field entirely — it was never populated. The storage abstraction was defined early and the dev side got a full implementation. The prod side needs the AWS SDK v2 dependency and real S3/R2 calls. Portfolio images and profile pictures will start working in prod once this is done.
P3 Square webhook event handling: from log-only to action S (1d) Backend Still open. Webhook signature verification works (HMAC-SHA256) and is fail-closed (503 without the signing key, 403 on bad/missing signature), event parsing works, and event_id dedup is implemented (duplicate events are skipped). But handlePaymentUpdated (square.go:152) and handleRefundUpdated (square.go:163) still only log the event data — they never update booking/payment state. In the interim, payment/refund state is tracked via the synchronous request paths plus the three background sweeps (sweep-pending-square-refunds, sweep-stale-pending-payments, sweep-stale-terminal-checkouts), which reconcile stuck states without webhook events. The handlers that act on events were deferred: update payment status on payment.updated, update refund status on refund.updated.
P4 Payment reconciliation: add recovery for split-brain scenarios L (3-5d) Backend Partial progress (Aug 2026). 20 log.Printf("CRITICAL: ... manual reconciliation required") calls exist across payment, refund, and till handlers. When Square succeeds but the DB transaction fails afterwards, state diverges with no automated recovery. The three background sweeps now provide interim recovery for pending states (refund sweep retries up to 3 attempts; stale-pending and terminal-checkout sweeps fail/clean stale rows), but a DB-commit failure after a successful Square charge still leaves no automated path to reconcile the orphaned Square-side payment. This happens when the application correctly processes a Square payment but then hits a DB error on commit. In dev, this was handled by just logging it. For prod, we need a reconciliation job or retry mechanism. (Count grew from 18 to 20 with the stale-pending sweep's manual-reconciliation warnings in the Aug 2026 review round.)
P5 Till Purchases: wire the backend payment flow M (1d) Frontend + Backend DONE (Aug 2026)backend/handlers/payments/till.go implements the till-sale endpoint (cash, card_machine Terminal checkout + polling, saved_card, online_square Web Payments SDK nonce, on_the_house); TillPurchases.svelte wires all payment methods and the Charge button is enabled (gated only for retail-item carts, which cannot be charged yet). The till UI and backend sale path are fully connected. Only retail-item charging remains deferred (see TillPurchases.svelte canCharge).
P6 Email/SMS notification delivery XL (5-7d) Backend user_notification_preferences table stores delivery preferences. 8 TODO markers reference this blocker. Notification creation works (admin_notifications table), but no delivery channel exists. No SMTP configuration, no SMS provider. 2 tests skipped as "WIP handler." The notification queue works (reasons, priorities, acknowledging). What's missing is the delivery backend. Affects: slot eviction alerts, edit request approvals/denials, gift card codes, unpaid booking reminders, idle account warnings.
P7 Production security headers S (1h) Backend HSTS and Referrer-Policy headers are commented out in main.go:231-233 with TODO markers. They were left disabled for dev HTTP convenience. Uncomment and configure for production.
P8 Social auth stubs (Google/Microsoft/Facebook) L (2-3d) Backend + Frontend handlers/auth/social.go is 1 line (package auth). Frontend login page has 3 social buttons that show toast.info("${provider} login coming soon"). The user_social_logins table and account_type enum values exist from early schema design. The schema was designed for social auth from the start (table + enum values). The OAuth flow itself was never implemented. Buttons exist as UI placeholders.
P10 No automated database backups M (1d) Infrastructure PostgreSQL volume is persistent in Docker but no pg_dump cron, no point-in-time recovery. Standard production DB setup task.
P12 Square sandbox smoke test (pre-go-live gate) S-M (1d, once credentials available) E2E BLOCKED — no real Square credentials available. Must exercise the real API path end-to-end: new-card tokenization → payment → saved card → refund → reconcile, against Square's sandbox. Also verifies the M-8 open question (is card.customer_id enforced as Required?). The dev mock cannot exercise Square's real wire contract (key-length limits, device_options, refund statuses, error codes). This is the sole remaining item before the production flip. See plans/p11-square-web-payments-sdk.md Remaining Items.
P13 Reconcile deterministically-keyed saved-card charges S (2-3h) Backend Deferred — deliberate trade-off (N-OBS-1). The admin "Charge Saved Card" idempotency key bookingID-sc-type-amount-cardID dedups two identical repeat charges on one booking. Not UI-reachable today (PaymentModal always sends the current totalDue, which changes after each charge). Revisit if the admin flow ever gains a "charge exact amount twice" path — the key would then need a client nonce or attempt counter. Tracked from the final payment review.
P14 Square customer provisioning & consent S-M (1-2d) Backend + Frontend + Docs IMPLEMENTED (Aug 2026) — lazy customer provisioning on card-save, square_customer_id persisted + forwarded to Square as card.customer_id/CreatePayment CustomerID, one-off/guest no-customer, /privacy-policy route + consent pop-over, SCA verificationDetails wired across all charge flows. Remaining: P12 sandbox verification that Square enforces customer_id, and final privacy-policy copy review (route ships DRAFT-bannered). See plans/p14-square-customer-provisioning-consent.md. Closed out of the deep post-implementation review (Aug 2026).
P15 Accounting integration (Mettle bank feed + FreeAgent bookkeeping export) M (2-3d) Backend Planned upcoming body of work. No code yet. The square_deposits schema (backlog T1) was the placeholder for Square batch deposit reconciliation against Mettle. Mettle bank feed: match Square batch deposits against bank statements. FreeAgent: bookkeeping export (VAT return / P&L data) feeding the existing HMRC MTD SQL functions (see M1/M9).

MVP — Must Do Before Launch

These are missing functionality that prevents daily operations, legal compliance, or basic UX. Unlike the Pre-Launch tasks above, these aren't about wiring production counterparts — they're features that were genuinely deferred or overlooked.

# Gap Effort Area Notes
M1 VAT/Tax export endpoints M (1-2d) Backend 6 SQL functions exist (get_vat_return_data, export_sales_transactions, get_monthly_business_summary, get_sales_totals, calculate_vat, get_receipt_data) but no Go handler calls them. Needed for HMRC MTD compliance.
M2 Password reset — no frontend route S (2-3h) Frontend Backend has verification codes with verification_purpose = 'password_reset' and /verify/generate + /verify/check endpoints. No "forgot password" link or reset form exists.
M3 Email verification calls wrong API endpoint S (2h) Frontend +layout.svelte:33 calls /api/verify-email which 404s. Correct endpoints: POST /api/verify/generate and POST /api/verify/check. Every login triggers a silent failure.
M4 CSRF protection S (2-3h) Backend SvelteKit handles CSRF for its own forms, but direct API calls to /api/* bypass it.
M5 XSS input sanitization S (2-3h) Backend Backend validates format (regex, length) but doesn't sanitize HTML entities in stored fields. CSP mitigates but doesn't eliminate risk.
M7 Booking cancellation UI from user account S (2-3h) Frontend UserBookingModal shows details but has no cancel button. Backend DELETE /api/bookings/{id} exists.
M8 Business settings management UI M (1-2d) Frontend GET/PUT /api/admin/settings endpoints exist. No admin page — staff use curl or SQL.
M9 CSV/Excel export for bookings/payments M (1d) Backend No endpoint for accounting software export. SQL functions exist but not wired.
M10 CurrentAppointment action stubs M (1d) Frontend Extend and Cancel buttons on Today page are dead. Edit/TakePayment/Reschedule are already wired.
M11 /terms and /privacy routes are draft only stubs S (1h) Frontend Login and account pages link to these — needs work.
M12 Admin notifications list/acknowledge untested S (2-3h) Backend 2 tests skipped as WIP (today_test.go:940,946). Notification endpoints have zero coverage.

Stretch — Post-Launch

These improve the experience or add features, but the business can operate without them.

# Gap Effort Area Notes
S1 One-off custom services M (1-2d) Full-stack Single-use services must be added to permanent catalog then deleted.
S2 One-off exceptional hours M (1d) Full-stack Single-day open hours require a full exceptional group. Time blockers handle closures but not openings.
S3 Referral system UI M (1-2d) Full-stack Backend complete. Users can't see their code or track uses. No admin campaign management. affiliate role and affiliate_payouts table exist but unused.
S4 Analytics endpoints M (1-2d) Backend analytics.go is 1 line. 4 SQL summary functions exist but no Go handler.
S5 API documentation M (1-2d) Backend No OpenAPI/Swagger spec.
S6 Per-user rate limiting M (1d) Backend Currently IP-based only.
S7 Begin button (Today page) S (2-3h) Full-stack Manual appointment start for early arrivals.
S8 Booking conflict detection for users S (2-3h) Backend Users can double-book themselves in two tabs.
S9 Service category/tag management M (1-2d) Full-stack Flat service list, no grouping.
S10 No-show tracking dashboard S (2-3h) Frontend forgiven_no_shows table exists but no UI.
S11 Dark mode M (1-2d) Frontend Tailwind supports it. No toggle.
S12 PWA support L (3-5d) Frontend No service worker, manifest, or offline support.
S13 Recurring bookings L (3-5d) Full-stack No weekly/monthly booking support.
S14 Gift card self-service portal M (1d) Frontend Users see balance but can't redeem without admin.
S15 Admin audit trail for account anonymization S (1h) Backend No user_anonymized notification when admin deletes a user.
S16 User notification of slot eviction S (2h) Backend When a booking is evicted (deposit not paid, slot reclaimed), the user is never notified. 3 TODO sites reference this.
S17 Password reset should clear lockout state S (1h) Backend TODO in auth/local.go:427 — currently failed_attempts/locked_until aren't cleared on password reset.

Technical Debt — Cleanup

These don't add features but reduce maintenance cost and risk.

# Task Effort Area Notes
T1 Drop orphaned square_deposits table + function S (1h) DB Schema Full table + generate_square_deposit_id() function. Zero Go code references it. Square bank reconciliation was planned but never built.
T2 Remove 6 unused DB enum values S (2h) DB Schema account_role: 'affiliate', account_type: 'google'/'microsoft'/'facebook', payment_status: 'failed'/'refunded', discount_campaign_scope: 'first_booking_only'/'new_customers_only', till_item_type: 'retail_product' — defined but never referenced in Go code.
T3 Remove 4 unused admin_notification_reason values S (1h) DB Schema 'rescheduled_booking', 'gift_card_purchased_for_friend', 'edit_request' (code uses 'edit_requested'), 'deposit_paid' (in priority ordering but never inserted).
T4 Create or remove documented update_data_consent() function S (1h) DB Schema Listed in FUNCTION USAGE SUMMARY comment (~line 2401) but no CREATE FUNCTION exists.
T5 Resolve 2 route-conflicted lint-ignored handlers S (1h) Backend manage.go:27,314 — handlers exist only for tests but routes conflict.
T6 Resolve portfolio lint-ignored handler S (1h) Backend images.go:53 — handler referenced from tests only, never routed.
T7 Fix README job count: 22 not 21 S (5min) Docs COMPLETED Aug 2026 — README now documents 23 maintenance jobs (the three payment sweeps: sweep-pending-square-refunds, sweep-stale-pending-payments, sweep-stale-terminal-checkouts).
T8 Audit 18 silent catch blocks M (1d) Frontend 1 catch (e) {}, 17 catch (_err) — errors swallowed silently. Many should show user-facing toasts.
T9 33 svelte/no-navigation-without-resolve suppressions M (1d) Frontend Create a project-wide goto wrapper instead of suppressing per-file.
T10 Replace as any in HolidayHours S (30min) Frontend HolidayHours.svelte:234(group.hours as any[])?.map(…). Hours array has known shape.
T11 Replace e: any in button onclick S (30min) Frontend button.svelte:101 — click handler typed as e: any.
T12 Former name display (4 TODO sites) S (1d) Frontend + Backend 4 TODOs across GiftCards + notifications needing previousFirstName/previousLastName from backend.
T13 Fix devProdClient rune-arithmetic in test S (30min) Backend COMPLETED July 2026 — rune('0'+idx) replaced with fmt.Sprintf("concurrent-key-%d", idx) for proper numeric formatting beyond index 9.
T14 Error tracking / monitoring (Sentry) M (1-2d) Backend log.Printf() only. No alerting on 5xx. 39 ALERT + 20 CRITICAL logs will never be seen.

Previously Completed Items (August 2026 backlog)

  • Square payments: wire prod client alongside dev mock (P1)internal/square/square_http_client.go implements the real REST client (payments, terminal checkouts, refunds, cards, list-refunds). Prod client (internal/square/square.go) and dev devProdClient (square_dev.go) both call real Square when SQUARE_ENVIRONMENT=sandbox|production; mock uses the in-memory client. The health endpoint reports "mock"/"ok" accordingly (was "not_implemented").
  • Square Web Payments SDK: re-enable new-card entry with nonce-based flow (P11)SquareCardInput.svelte tokenizes cards to cnon: nonces via the Web Payments SDK (env-gated on VITE_SQUARE_APPLICATION_ID/VITE_SQUARE_LOCATION_ID); all 8 flows re-enabled (tips ×3, booking payment, deposit, Buy a Gift Card, account Add Card, till online_square); CardEntryUnavailable kept only as the no-credentials fallback. See plans/p11-square-web-payments-sdk.md.
  • Square webhook signature verification — enforce always (M6) — the webhook handler is now fail-closed: rejects with 503 when SQUARE_WEBHOOK_SIGNATURE_KEY is unset and 403 when the signature header is missing/invalid (handlers/webhooks/square.go).
  • Fix README job count (T7) — README updated to 23 maintenance jobs.
  • Fix devProdClient rune-arithmetic in test (T13)rune('0'+idx) replaced with fmt.Sprintf("concurrent-key-%d", idx).

Previously Completed Items (July 2026 backlog)

  • Tip payments: replace placeholder card tokens (P9)card_token: 'placeholder' replaced with real saved card selection + CardInput with Luhn/expiry/CVC validation across all 3 tip pages. CardBrandIcon SVGs added for all Square-supported brands.

Previously Completed Items (June 2026 backlog)

  • Reservation/cleanup background cron — All 20 jobs migrated to centralized scheduler
  • XSS input sanitization (partial) — CSP added, error messages sanitized, ICS injection fixed
  • Per-user rate limiting (partial) — L3 ProgressiveRateLimit added for login/register

This catalog was compiled from a full codebase audit (July 2026): 4 parallel deep-dive agents covering backend TODOs, frontend gaps, implied stubs, and DB schema analysis. Every item traces to specific file paths and line numbers.