E-Sign Contract Page — Playground Prototype + SvelteKit Repo #72
Labels
No labels
domain:backend
domain:devops
domain:frontend
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
forgejo_admin/westside-landing#72
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Type
Feature
Lineage
plan-wkq→ Phase 14 (Billing Tiers & Contracts) → E-Sign Contract PageRepo
forgejo_admin/westside-app(issue home), new repowestside-contractscreated as part of this work. Prototype inpal-e-playground.User Story
As a parent
I want to receive an email with a link to a digital contract, read the season terms, and sign with a drawn signature
So that I can officially commit to the program without paper forms and the org has a legally traceable record
Context
Westside Kings & Queens needs digital contracts for the spring/summer 2026 season. Two contract types: Travel teams (17U Elite, 17U Select, 16U Elite) with monthly fees + tournament travel costs, and Local teams with monthly fees + group-decided tournaments.
The signing flow: parent receives a tokenized email link → contract page renders terms for their player's team → checkbox unlocks a drawn signature pad (phone finger / desktop mouse) → signature + timestamp + IP stored in DB, image in MinIO. Under-18 players require parent/guardian signature, enforced by token→parent association.
E-SIGN Act compliant: intent (checkbox), consent (clicked link), association (token→email), retention (DB + MinIO).
The new
westside-contractsrepo uses SvelteKit withadapter-nodeso server routes can talk directly to basketball-api's Postgres — no separate backend needed. HTML/CSS prototype in pal-e-playground is the literal source of truth for the SvelteKit components.Travel contract includes: $200/month (or tier), 2 practices/week + optional weight room, jersey, Power 32 Circuit registration ($186/player), travel costs per trip (Seal Beach $395, Vegas TBD, Championship TBD), practice schedule, Vertical Raise fundraising info, Klarna installments.
Local contract includes: $200/month, 2 practices/week, jersey, practice schedule, tournaments decided as a group via GroupMe, separate bill when confirmed.
File Targets
Phase 1 — Playground:
pal-e-playground/westside-contract.html— single-file prototype (HTML/CSS/JS)Phase 2 — SvelteKit repo (new: westside-contracts):
src/routes/contract/[token]/+page.svelte— contract page (from playground HTML)src/routes/contract/[token]/+page.server.ts— token resolution, Postgres querysrc/routes/contract/[token]/sign/+server.ts— POST endpoint for signature submissionsrc/lib/db.ts— Postgres connection (direct to basketball-api DB)src/lib/minio.ts— signature image uploadDockerfile— adapter-node production buildsvelte.config.js— adapter-node configPhase 3 — Email:
basketball-api (migration only):
contract_signature_urlcolumn to players tableFiles NOT to touch:
westside-app/— existing SPA, separate concernbasketball-api/src/— no route changes, migration onlyAcceptance Criteria
Test Expectations
npm run test(SvelteKit) +pytest tests/test_contract.py(migration verification)Constraints
signature_pad.jsvia CDN (no npm package needed for playground, npm install for SvelteKit)brand_wrappercolorsadapter-node(NOT adapter-static) — needs server routesChecklist
Related
project-westside-basketball— project pageplan-wkq→ Phase 14 — Billing Tiers & Contractswestside-practice-schedule— practice schedule data for contract termstourney-power32-seal-beach-may-2026— tournament cost datawestside-vertical-raise-fundraising— fundraising detailswestside-tournament-schedule— parent tournament schedule noteQA Scope Review — Decisions Made
QA agent reviewed this ticket and identified 5 gaps. All resolved:
Token Design
Decision:
secrets.token_urlsafe(32)— same pattern asParent.registration_tokenandCoach.invite_token. NOT JWT. Stored ascontract_tokencolumn on Player model. No expiry (one-time sign).Prerequisite: basketball-api #152 — adds
contract_token+contract_signature_urlto Player model. Must merge first.Contract Variant Routing
Decision: Derive from team name.
"Local" in team.name→ local contract template. Otherwise → travel contract template. No new columns or URL params needed.Shared DB Access
Decision: westside-contracts connects to
postgres.basketball-api.svc.cluster.local:5432via cross-namespace DNS. Database credentials shared via k8s Secret. SQLAlchemy models duplicated (minimal subset: Player, Parent, Team — read-only except contract fields). Schema ownership stays with basketball-api (all migrations there).Migration Ownership
Decision: basketball-api owns all migrations. Separate ticket: basketball-api #152 (2 points). Blocking dependency for Phase 2.
Contract Content Versioning
Decision: Add
contract_versionstring to the signing record (e.g., "2026-spring-travel-v1"). Simple, sufficient for E-SIGN audit trail. Tracked in the same migration (#152).Travel vs Local Contract Content
Deployment Details (still TBD — resolve before agent spawn)
Additional AC — Confirmation Email
After a parent signs the contract, a confirmation email must be sent automatically:
This is part of the end-to-end flow: contract email → sign → confirmation email with GroupMe + next steps.
Additional Contract Sections Added