Skip to main content
Petanque Life

User Registration & Profile

F02.01 16 features Shipped

At a glance

User Registration & Profile establishes the identity foundation across the federation hierarchy, supporting self-registration with email/phone verification, OAuth2 social sign-up, and multiple coexisting personas (player, official, administrator, coach) on a single auth identity. It also produces the digital and printable player ID cards with embedded QR codes that anchor on-site recognition at events and venues.

How it works

Registration begins at any tenant entry point — federation site, club portal, or marketing landing — and routes through the platform's auth identity service. Users either self-register with email/phone verification or initiate OAuth2 with Google, Microsoft, or GitHub; in both flows the system creates a single auth identity that can later carry multiple tenant-scoped profiles. Once verified, the user is prompted to complete a role-aware profile: PlayerProfile captures name, date of birth, nationality, photo and preferred playing position (pointer/shooter/middle); OfficialProfile records umpire grade, certifications and spoken languages; AdministratorProfile records federation, role and mandate period.

Multi-identity support lets the same person hold all three at once — a club secretary who plays in the regional league and umpires on weekends keeps one login and three profile documents, each linked to the appropriate OrgNode and tenant. Photo uploads route through the media pipeline with automatic resizing and content moderation. A profile-completion service computes a percentage and surfaces missing fields in the user's dashboard, prompting players to add a photo before their first competition or coaches to upload certifications before the next training cycle.

ID-card generation produces both a digital wallet-compatible card and a printable PDF, embedding a signed QR payload that resolves to the player's tenant + license number; the same QR is used by tournament check-in scanners and by venue access control. GDPR rights — data export and deletion request — are exposed under /me as standard endpoints; deletion uses the platform-wide 30-day grace window before anonymisation cascades through results, rankings, and audit references.

Key capabilities

  • Self-registration with email/phone verification or OAuth2 social sign-up
  • Multi-identity profiles (player + official + coach + administrator) on one auth identity
  • Role-specific profile schemas with photo upload and content moderation
  • Profile-completion tracking with contextual prompts and gates
  • Digital + printable player ID card with signed QR payload
  • QR-based check-in identification reused across events and venue access
  • GDPR data export and 30-day grace deletion endpoints under /me

In practice

A French player registers on her national federation site using Sign in with Google. The OAuth gateway returns her to the federation tenant with a fresh auth identity and a verified email. She completes the player profile — date of birth, nationality, photo, preferred position 'shooter' — and the completion meter jumps to 100%.

The next month her club president grants her a Club Secretary role; without re-registering, she now holds two profiles under the same login. Before her first regional tournament she opens her wallet, displays the QR on her digital ID card, and is checked in by the scorer's tablet in under two seconds. A year later she emigrates and requests data export under /me; the JSON archive is delivered within minutes, and a deletion request she files afterwards begins the 30-day grace window before anonymisation.

Features in this subsystem

16
ID Status Features
F02.01.01 Shipped Self-registration with email/phone verification ✅ PL-F0201a (OTP via craft_easy.core.auth.otp, best-effort delivery sink)
F02.01.02 Shipped OAuth2 social login (Google, Microsoft, GitHub) ✅ PL-1801 (gateway), ✅ PL-1802/03/04 (providers), ✅ PL-1805 (app + admin SSO-knappar), ✅ PL-1806 (flera identiteter per user, Connected Accounts-vy, fresh-auth-fönster, last_auth_method-policy, upstream-revokation)
F02.01.03 Shipped Player profile (name, DOB, nationality, photo, playing position) ✅ PL-F0201a (base model PL-105, per-tenant matrix SE/FR/DE), ✅ PL-T311 (premium app-shell — cover-gradient + −48 px overlap-avatar + sticky <SegmentedControl> Översikt/Stats/Lic/Settings, mobil 1-kol / desktop 2-kol, gateadepad bakom pl_premium_profile_v1)
F02.01.04 Shipped Official profile (umpire grade, certifications, languages) ✅ PL-F0201a (umpire grade L1–L5, certification expiry validation, language list)
F02.01.05 Shipped Administrator profile (federation, role, mandate period) ✅ PL-F0201a (role enum, mandate range validator, currently-serving filter)
F02.01.06 Shipped Multi-identity support (same person = player + umpire + coach) ✅ PL-F0201a (GET /users/{user_id}/profiles aggregates player/official/coach/administrator)
F02.01.07 Shipped Profile photo upload and management ✅ PL-F0201b (multipart upload, PNG/JPEG/WebP, max 5 MB, magic-byte + Pillow-validering, SHA-256 ETag, en bild per profil över alla fyra profil-typer)
F02.01.08 Shipped Profile completion tracking and prompts ✅ PL-F0201a (completion_pct + currently_serving on administrator), ✅ PL-F0201b (GET /{profile}/prompts med aktionsbara meddelanden och severity high/medium/low)
F02.01.09 Shipped GDPR-compliant data export and deletion ✅ PL-F0201b (profile_photos + check_in_records inkluderade i /me/data-export; foton raderas och administrator-profiler anonymiseras i raderingsflödet)
F02.01.10 Shipped Player ID card generation (digital + printable) ✅ PL-F0201b (GET /player-profiles/{id}/card?format=json|pdf|png, ISO/IEC 7810 ID-1 PDF, 1050×660 PNG, stabil JSON + base64-url QR-payload), ✅ PL-T311 (app <LicensePassCard> — bottle-green gradient + embossed QR + holografisk sheen + multi-tenant pager, mountad på (tabs)/license-routen och i profilens License-tab), ♻️ Rebuild 525ece23.m-3.t-1 (rena /v1-kontraktet GET /v1/player-profiles/{id}/card?format=json|png|pdf|pkpass i Go: json/png MUST, pdf/pkpass SHOULD, 415 på okänt format; pkpass-pass (Wallet) med live giltighet/spärr; se specs/api/endpoints/card-and-checkin.md)
F02.01.11 Shipped QR code identification for check-in at events ✅ PL-F0201b (HMAC-SHA256 v1-token, SVG/JSON QR, POST /major-events/{id}/check-in med replay-, expiry- och tampering-försvar, audit-log via CheckInRecord), ♻️ Rebuild 525ece23.m-3.t-1 (Go: GET /v1/me/check-in-token HMAC-signerad self-contained token + POST /v1/events/{id}/check-in append-only check_in_record med token_jti UNIQUE-replay-grind; felkontrakt check_in_token_replayed/_expired/_invalid; offline-verifierbar för Wallet/dålig täckning)
F02.01.12 Shipped Player stats dashboard (ELO trend, win-rate, partners, opponents, history) ✅ PL-T311 (GET /me/stats?period=30d|90d|365d|all aggregator + app <StatsTab> med <EloTrendChart>, <WinRateRing>, top-3 partners/opponents, last-20-matches; Cache-Control: private, no-store)
F02.01.13 Planned ICE/nödkontakt + skyddad medicinsk basinfo (art.9) med break-glass ♻️ Rebuild 525ece23.m-5.t-1 (Go: additiv ALTER player_profile (emergency_contact/medical_flags jsonb); GET/PUT /v1/me/emergency-medical — samtyckesgrindad (ConsentResolver-port, fail-closed) + minderårig-parental_consent + optimistisk låsning + audit; maskerad i alla icke-ägar-läsvägar (FR-3); break-glass GET /v1/events/{id}/participants/{aid}/emergency-medical capability-gatead (incident:emergency-read) + incheckad + pågående event + obligatoriskt audit-skäl; felkontrakt consent_required/parental_consent_required. Samtyckes-/retention-modellen ägs av D-GDPR; se specs/api/endpoints/dusers-emergency-medical.md + docs/domain/emergency-medical.md)
F02.01.14 Planned Egen ICS-kalender (SHOULD) — personlig prenumerationsfeed över alla tenants ♻️ Rebuild 525ece23.m-6 (Go t-1: GET /v1/me/calendar.ics?token= publik, token-autentiserad RFC 5545-feed som aggregerar personens egna poster över alla tenants (BR06.08) via en CalendarSource-port — D-VENUE-banbokningar wirade, D-COMP/D-EVENTS som seams (noll poster, aldrig fel, §5d/NFR-9); revokerbar, endast hashad feed-token; GET /v1/me/calendar-subscription + POST /v1/me/calendar.ics:rotate-token; stabil UID per post. app-UI t-2: Inställningar → "Min kalender & favoriter" visar/kopierar feed-URL:en + roterar/spärrar (app/app/kalender-favoriter.tsx); se specs/api/endpoints/me-calendar-favorites.md + specs/app/views/kalender-favoriter.md)
F02.01.15 Planned Spara favoriter (NICE) — favoritklubb/-venue/-spelare/-tävling ♻️ Rebuild 525ece23.m-6 (Go t-1: favorite-tabell (polymorf, tenant_id nullable, CHECK-enum favorite_type, UNIQUE (auth_identity_id, favorite_type, target_ref), ingen version) + GET/POST/DELETE /v1/me/favorites — self-skopad (IDOR-skydd), 409 favorite_exists, 422 på okänd typ/icke-UUID, 404-icke-läckage; server-side tenant-skopning (player → tenant_id=NULL); bokmärkes-semantik, ingen cross-domän-validering. app-UI t-2: favorit-snabblista (lägg till/ta bort) i app/app/kalender-favoriter.tsx; se specs/api/endpoints/me-calendar-favorites.md + specs/app/views/kalender-favoriter.md)
F02.01.16 Planned Tenant-medlemsregister — admin listar den aktiva tenantens medlemmar och öppnar en LIVE profil-detalj ♻️ Rebuild be2f9ef1.m-1.t-1 (Go: GET /v1/tenant/members — den tenant-skopade läsytan admin-registret (admin/lib/members.tsx, useMemberRegister) konsumerar, tidigare 404. Capability-gatead member:read (ingen ny capability), aktiv tenant ur kontexten (requireTenant/reqctx, aldrig path/query/body/header), {members:[MemberRow]}-kuvert där varje rad bär ett konkret profile_id (= <type>_profile.id, inte auth_identity_id) som löser GET /v1/{profile_type}-profiles/{id}. Riktig data: UNION ALL över player/official/coach/administrator_profile JOIN auth_identity, tenant-filter på <type>_profile.tenant_id (NFR-1 hård cross-tenant-isolation), stabil ordning, NULL display_name → "". Read-only, ingen migration/audit. Stängde den sista hårda frontend↔backend-kontraktsluckan på webbplattformen. Se specs/api/endpoints/tenant-members.md + specs/admin/views/member-register.md)