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.xlsxandstringing.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:
- The four locked data-model decisions in V2 scope.
- New M21: stringer auth = magic-link (first sign-in / registration) then password available thereafter; both methods supported per stringer.
- i18n locale rule (NFR-7): user's saved preference (
stringer.default_localein V2,player.default_localein V3 client portal) wins over the browserAccept-Languageheader.
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-4Personmerge does not auto-share existingClientProfilerows across stringers (cross-stringer visibility still requires an explicit grant); OQ-5 when a Rule 1 grantee already holds aClientProfilefor the samePerson, 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_logfor audit; no "lock atpaid_at" gate. OQ-R-1 (receipt-content):Order.commentsIS 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 newStringer.receipt_thankyou_textfield; falls back to a platform-default i18n string (receipt.thankyou.default) when NULL. OQ-R-4 (receipt-content): the receipt shows onlyordered_at(when set) andstrung_at;returned_atandpaid_atare 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.mddate scope,docs/architecture/i18n.mdnew-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_auditanddsar_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_logtable, admin finalize-expired endpoint,share_auditevent-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-4Order.commentsredacted 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.commentsis included verbatim in the DSAR JSON, symmetric with the receipt-comments-visible decision (OQ-R-1, CC-2026-05-04). Stringers should treatcommentsas customer-facing in all contexts; if a future need surfaces for stringer-private working notes, that becomes a new field, not a hidden surface onOrder.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
Playerreferences indata-model.mdand rewrite the page aroundPerson+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 onPerson.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 theirPlayerreferences 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 withdelivery_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 toreceipt_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_logtable, draft-Person provenance,POST /admin/persons/finalize-expiredendpoint,scrub_orders_for_person()helper,share_audit.event_kindextension (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.mdamendment + 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.