Skip to content

Requirements

Living requirements for racket-book V2 — a multi-tenant, mobile-first web app for tennis-stringing job tracking. V1 is the existing stringing_orders.xlsx spreadsheet plus the read-only stringing.wagen.io site; V2 replaces both. V1 is not being rebuilt — V2 is built directly, with the full V1 history migrated.

Status

Topic State
1. Vision & motivation Closed (2026-04-27)
2. Users & personas Closed (2026-04-27)
3. Core use cases / JTBDs Closed (2026-04-27)
4. Scope (MoSCoW) Closed (2026-04-27)
5. Non-functional needs Closed (2026-04-27)
6. Recap & sign-off Closed (signed off 2026-04-27)

Working session log: team/sessions/requirements_session_log.md.

Contents

  • V1 baseline — current state captured from stringing_orders.xlsx and stringing.wagen.io.
  • V2 scope — full MoSCoW table and the four locked data-model decisions.
  • V3 vision — features deferred to a future release. Includes the 2026-05-01 sign-off workflow + channel exploration (scoped, answers captured) — still V3-deferred and not part of the 2026-04-27 V2 sign-off.
  • Use cases — flows from Topic 3 (stringing day, order entry, receipts, notifications, multi-stringer admin, edge cases, share-player, catalogue moderation).
  • Client identity & sharing(2026-05-02 re-shape.) Person + ClientProfile identity model and the three sharing rules. Supersedes the original "duplicate Players + single share button" model.
  • Data model — Person, ClientProfile, Rackets, Strings, Orders, Stringers, Catalogue submissions, sharing rules. (Identity is owned by client identity & sharing; this page is the cross-cut reference for the rest of the entities.)
  • Order lifecycle — state machine, edit-permission matrix per state, price-edit policy after Strung, receipt re-emit triggers. (Iris's rules layer; ADR-0007 — Theo — owns the structural model.)
  • Receipt content — quadrant-by-quadrant field list, Stringer business-identity fields backing the receipt, receipt-number format, locale handling. (Field-list contract for Mira + Pax.)
  • Receipt delivery — when the receipt is emitted (initial + re-emit triggers), recipient resolution, channel selection, SMTP failure semantics, "one receipt per racket-order" precise meaning, V2-out-of-scope list. (Delivery-rules contract for Pax — companion to receipt content.)
  • Stringer lifecycle — onboarding profile fields, offboarding flow + 90-day grace + admin-finalize, FADP-aligned cascade rules. (Iris's rules layer for the Stringer entity over its full lifecycle.)
  • FADP posture — Person-side data-subject rights (DSAR, erasure, portability), retention windows, consent records (incl. stringer-created draft Persons), processor / sub-processor disclosure, privacy-notice skeleton. Companion to client identity & sharing and stringer lifecycle; together they cover the full FADP cascade.
  • FADP implementation asks — formal requirements (R-FADP-1 … R-FADP-7) for the seven schema / endpoint asks logged in fadp-posture.md. Schema-impact summary + per-requirement rationale, acceptance criteria, edge cases, test scenarios. Target for Theo's data-model amendment + Pax's Phase 3.x slice.
  • Non-functional requirements — formal NFR list with answers.
  • Glossary — domain terms (BYO, gauge, dynamic tension, etc.).

Sign-off

Signed off by Stefan on 2026-04-27. Confirmed in this round:

  1. The four locked data-model decisions in V2 scope.
  2. New M21: stringer auth = magic-link (first sign-in / registration) then password available thereafter; both methods supported per stringer.
  3. i18n locale rule (NFR-7): user's saved preference (stringer.default_locale in V2, player.default_locale in V3 client portal) wins over the browser Accept-Language header.

Requirements are now the baseline that downstream design proceeds against. Future changes go through change-control rather than re-opening this sign-off.

Change log

  • CC-2026-05-02-1 — client identity + sharing re-shape. "Duplicate Player rows per stringer" is replaced by Person (platform-level identity) + ClientProfile (stringer-scoped). The single M18 "Share player" button is replaced by three explicit sharing rules (1: stringer-initiated per-job; 2: client-initiated per-job; 3: client global preference, future-inclusive). Identity matching is verified-email only. Authoritative requirements page: client identity & sharing. Authoritative architecture: ADR-0004 (Theo). The 2026-04-27 sign-off topics (locked decisions, M21, i18n) are unchanged. Tracked in racket-book#76 (this requirements rewrite) and racket-book#77 (Theo's ADR + architecture).
  • CC-2026-05-02-2 — close OQ-1..OQ-5 on the client identity + sharing page. The five open questions logged in CC-2026-05-02-1 are now closed with the proposed defaults: OQ-1 pricing under client-granted shares (Rules 2 & 3) is visible; OQ-2 per-job comments-share toggle for Rule 1 is deferred to V3 (V2 keeps blanket comments-redact, consistent with ADR-0004); OQ-3 notification channels are in-app mandatory + email opt-in via Person.notification_prefs; OQ-4 Person merge does not auto-share existing ClientProfile rows across stringers (cross-stringer visibility still requires an explicit grant); OQ-5 when a Rule 1 grantee already holds a ClientProfile for the same Person, the share appears as a standalone "Shared with me" entry in V2 (auto-link is V3 polish). The "Open questions" section on the client identity & sharing page is now empty; decisions are inlined into the relevant decision sections. No schema impact on ADR-0004. Tracked in racket-book#76 (MR !18).
  • CC-2026-05-04 — close OQ-L-1 (price-edit), OQ-R-1 (comments on receipt), OQ-R-3 (thank-you text), OQ-R-4 (lifecycle dates on receipt). Stefan reviewed the open questions left in the requirements layer and flipped four decisions away from Iris's drafted defaults. OQ-L-1 (order-lifecycle): price-edit policy is now (a) — prices are always editable for the owning stringer in any post-Draft state; every saved edit re-emits the receipt; old receipt versions are retained as snapshots in Order.receipt_emit_log for audit; no "lock at paid_at" gate. OQ-R-1 (receipt-content): Order.comments IS on the receipt as a comments band (rendered when non-empty); a Rule #1 grantee (receiving stringer per ADR-0004) sees the receipt with comments redacted server-side. OQ-R-3 (receipt-content): the bottom-right thank-you text is per-stringer customizable via a new Stringer.receipt_thankyou_text field; falls back to a platform-default i18n string (receipt.thankyou.default) when NULL. OQ-R-4 (receipt-content): the receipt shows only ordered_at (when set) and strung_at; returned_at and paid_at are never rendered on the receipt — they are admin/stringer-tracking-only, not customer-facing. The matching architecture-side flips (ADR-0007 amendment for price-edit (a), ADR-0008 amendment, docs/architecture/receipts.md date scope, docs/architecture/i18n.md new-Person locale default) are filed in parallel by Theo. Tracked in racket-book#93 (this requirements MR) and Theo's parallel architecture issue (cross-link added in MR descriptions).
  • CC-2026-05-02-4 — FADP posture page added. New page fadp-posture.md lands the Person-side data-subject rights surfaces that the existing client identity & sharing and stringer-lifecycle pages do not pin down: right to access (DSAR), right to erasure (two-stage soft-delete + 30-day grace + admin-triggered hard-erase), right to data portability (JSON, distinct from M20 per-stringer export), retention windows (10y for Order/receipt rows per Swiss CO art. 957–958f; 5y for share_audit and dsar_log; 30d for soft-deleted Persons; 90d for backups), consent records (including the consent-by-proxy legal basis for stringer-created draft Persons + the V3 magic-link claim ratification flow), and processor / sub-processor disclosure (Resend, keystone-managed Postgres, Hetzner Storage Box, gotrue, GitLab Pages). Privacy-notice skeleton is specified (11 sections; actual notice copy is a legal-review deliverable, not Iris's). Schema asks (Person.deleted_at, Person.scrubbed_at, dsar_log table, admin finalize-expired endpoint, share_audit event-kind extension) flagged for Theo (data-model amendment) and Pax (Phase-1.x slice). Five open questions logged with proposed defaults (OQ-F-1 audit retention 5y; OQ-F-2 Person-erasure grace 30d; OQ-F-3 processor-change notify-only; OQ-F-4 Order.comments redacted in DSAR; OQ-F-5 re-onboard after scrub allowed). Tracked in racket-book#98.
  • CC-2026-05-04-2 — close OQ-F-3 + OQ-F-4 on the FADP posture page. Stefan confirmed OQ-F-3 default (sub-processor list change behaviour = notify-only, no re-consent gate) and flipped OQ-F-4 to "visible in DSAR": Order.comments is included verbatim in the DSAR JSON, symmetric with the receipt-comments-visible decision (OQ-R-1, CC-2026-05-04). Stringers should treat comments as customer-facing in all contexts; if a future need surfaces for stringer-private working notes, that becomes a new field, not a hidden surface on Order.comments. OQ-F-1, OQ-F-2, OQ-F-5 confirmed at their drafted defaults (no doc change). Tracked in this MR.
  • CC-2026-05-02-3 — reqs-side stale-doc cleanup pass. Sweep the Player references in data-model.md and rewrite the page around Person + ClientProfile (the "partially superseded" banner is removed; the page is now coherent with client identity & sharing and ADR-0004). Rewrite v2-scope M5 and v2-scope M18 to reference Person/ClientProfile and Rule 1 respectively (M5 numeric ID stable; M18 rewording reflects that Rules 2 & 3 are V3-portal-gated). Add a one-line clarification on Person.email: optional at ClientProfile level (a stringer can create a client without an email) but required for promotion to a verified Person (the magic-link claim flow needs an email). Locked-decision text in v2-scope.md updated in place (decisions unchanged; only the entity name shifts from "Player" → "ClientProfile"). No semantic changes to any requirement; this is naming hygiene. Glossary, V1-baseline, V3-vision, and NFR pages keep their Player references where they refer to legacy/V1 context or V3-portal slots not yet rewritten. Tracked in racket-book#85.
  • CC-2026-05-05-2 — receipt delivery requirements. New page receipt-delivery.md lands the delivery-semantics rules layer that the existing receipt-content.md (field list) and order-lifecycle.md (state machine + re-emit triggers) leave open. Covers: trigger (initial = T2 Ordered → Strung + re-emit per the order-lifecycle trigger list); recipient resolution (default = Person.email; fallback = print-only with delivery_status = "skipped_no_email" audit row; no stringer-CC in V2; no multi-recipient); channel selection (email-or-print in V2; SMS/WhatsApp/Telegram are V3 parking-lot); failure semantics (silent + log per #44 (C2) restated; PDF render failure rolls back, SMTP failure does not; bounce webhook NOT consumed in V2); idempotency / re-emit ("one Order ↔ one number forever" per ADR-0008; each emit appends to receipt_emit_log; clients receive a fresh email per re-emit per the proposed default for OQ-D-1); explicit "what is NOT in V2" list (bounce webhook, multi-recipient, send-on-Returned, in-app preview, version UI, in-process retry loop, bulk re-send). Three open questions with proposed defaults: OQ-D-1 re-emit-on-edit also re-sends the email (default: yes — symmetric with initial emit; flag chatty inbox risk); OQ-D-2 PDF attachment only in V2, V3 portal adds a view-online link (default: PDF-only); OQ-D-3 rely on Resend's transport-level retry, no RBO-side retry loop (default: rely-on-Resend; admin re-trigger is the only retry path). Companion to M14 (#67) and C2 (#44); is Pax-A's delivery-semantics source-of-truth. Tracked in racket-book#116.
  • CC-2026-05-05 — FADP implementation asks formalized + Phase 3 M-issue housekeeping. New page fadp-implementation-asks.md promotes the seven schema / endpoint asks logged in fadp-posture.md § Schema asks to numbered requirements R-FADP-1 … R-FADP-7: Person.deleted_at, Person.scrubbed_at (set-once tombstone), dsar_log table, draft-Person provenance, POST /admin/persons/finalize-expired endpoint, scrub_orders_for_person() helper, share_audit.event_kind extension (person_erasure, dsar_served, consent_change). Each ask carries rationale (FADP article + consequence-if-missing), acceptance criteria, edge cases, and test scenarios; the page leads with a schema-impact summary table assigning ownership (Theo for data-model amendment of R-FADP-1/2/4/7; Pax for R-FADP-3/5/6 endpoint + helper). No schema changes land in this MR — this is a target for Theo's ADR-0004 / data-model.md amendment + Pax's Phase 3.x slice. Same MR also performs an issue-housekeeping sweep: closes the M-issues completed in Phase 1 / Phase 2 (M5 #59 + M18 #71 superseded by ADR-0004; M8 #62 + M10 #64 + M11 #65 closed by MR !47) by cross-link, and posts forward-reference / status comments on the in-flight or partial M-issues (#57, #58, #60, #61, #63, #66, #68, #70, #72, #74). V3-deferred D/E issues left untouched. Tracked in racket-book#111.