Competition Management
403 features · 27 subsystems
End-to-end management of all petanque competitions: from calendar planning to results and rankings. Covers all formats (singles, doubles, triples), all levels (club to world championships), and all disciplines (petanque, jeu provencal, sport-boules).
Competition Calendar
F04.01- F04.01.01 Shipped
Multi-level calendar (world, continental, national, regional, club) — PL-F0401a
✅ PL-F0401a - F04.01.02 Shipped
Calendar event types (championship, open, league, friendly, training) — PL-F0401a
✅ PL-F0401a - F04.01.03 Shipped
Date conflict detection across levels — PL-F0401a
✅ PL-F0401a - F04.01.04 Shipped
Calendar approval workflow (regional > national > continental) — PL-F0401a
✅ PL-F0401a - F04.01.05 Shipped
Public calendar view with filters (level, region, discipline, format) — PL-F0401b
✅ PL-F0401b - F04.01.06 Shipped
Calendar subscription (iCal export, webcal://, ETag/If-Modified-Since, cursor pagination) — PL-F0401b, PL-T074
✅ PL-F0401b, PL-T074 - F04.01.07 Shipped
Season definition and management — PL-F0401b
✅ PL-F0401b - F04.01.08 Shipped
Calendar notifications and reminders — PL-F0401b
✅ PL-F0401b
Tournament Setup
F04.02> **Greenfield-ombyggnad (D-COMP m-1, `04caab5e.m-1`):** den rena Go/Postgres-backenden
How it works- F04.02.01 Shipped
Tournament creation wizard (type, format, rules, venue, dates) — PL-F0402a
✅ PL-F0402a - F04.02.02 Shipped
Competition formats (see F04.10 for full format catalog) — PL-F0402a
✅ PL-F0402a - F04.02.03 Shipped
Disciplines: pétanque, jeu provençal, sport-boules — configurable per tenant — PL-F0402a
✅ PL-F0402a - F04.02.04 Shipped
Configurable game formats per tenant — tête-à-tête, doublette, triplette, mixed doublette, mixed triplette + tenant-specific variants. Includes players per team, boules per player. — PL-F0402a
✅ PL-F0402a - F04.02.05 Shipped
Configurable competition classes (spelklasser) per tenant — each federation defines its own age/gender classes with codes, age limits, and ranking eligibility. Examples: Sweden (M/YJ/J/Ö/D/V55/V65), France (Poussin→Vétéran), Germany (Minimes→Senioren), Spain (Benjamín→Veterano+Sub-23). Class is always age OR gender, never both combined. — PL-F0402a
✅ PL-F0402a - F04.02.06 Shipped
Competition class = competition class + game format — the atomic unit is the combination, e.g., "Ös" (Open singles), "V65d" (Veteran 65 doubles). A competition event can have multiple competition classes. — PL-F0402a
✅ PL-F0402a - F04.02.07 Shipped
Disability categories and adaptive rules — PL-F0402b
✅ PL-F0402b - F04.02.08 Shipped
Points system configuration (per competition type) — PL-F0402b
✅ PL-F0402b - F04.02.09 Shipped
Entry fee configuration — PL-F0402b
✅ PL-F0402b - F04.02.10 Shipped
Maximum participants / team limits — PL-F0402b
✅ PL-F0402b - F04.02.11 Shipped
Qualification criteria (ranking threshold, regional qualification) — PL-F0402b
✅ PL-F0402b - F04.02.12 Shipped
Multi-day tournament scheduling — PL-F0402b
✅ PL-F0402b - F04.02.13 Shipped
Competition regulation document attachment — PL-F0402c
✅ PL-F0402c - F04.02.14 Shipped
Configurable competition levels per tenant — each federation defines its own levels (e.g., Sweden: internationell/nationell/regional/lokal/propaganda; France: international/national/régional/départemental/local/animation; Germany: A/B/C/D). Each level has: who can sanction it, ranking eligibility, ranking coefficient, required referee grade, venue requirements. — PL-F0402c. Rebuild — LIVE (D-FEDCONFIG d0601eb6.m-2): nivåer & sanktionsmatris administreras som data i federationskonfigurations-hubbens nivå-flik (#nivaer): tävlingsnivåstegen = rader i tenant_configs.sanction_matrix (kod, etikett, sanktionerande organ härlett ur nivådeklarationens can_sanction, ranking_eligible, opak licensindikation; "Other"-raden bär aldrig licenskrav) + org-nivådeklarationens autonomi-/kapabilitetsflaggor via GET/PUT /v1/tenant/levels (delad tenant_configs.version-linje, If-Match/412-flöde). Wizardens nivådropdown läser samma matris (parseLevels) — ändringar slår igenom utan omdeploy. Vy-spec: specs/admin/views/federationskonfiguration.md.
✅ d0601eb6.m-2.t-2 - F04.02.15 Shipped
Competition type classification — configurable per tenant: championship (SM/DM/VM), cup, open/concours, league, friendly, mêlée, propaganda/recruitment (license-free), inbjudningstävling, extern tävling — PL-F0402c
✅ PL-F0402c - F04.02.16 Shipped
Multi-discipline event (same event hosts multiple competition classes as separate draws) — PL-F0402c
✅ PL-F0402c - F04.02.17 Shipped
Multi-day scheduling with sessions (morning/afternoon) — PL-F0402c
✅ PL-F0402c - F04.02.18 Shipped
Competition templates (save and reuse common setups) — PL-F0402c
✅ PL-F0402c - F04.02.19 Shipped
Competition cloning (copy last year's tournament with new dates) — PL-F0402d
✅ PL-F0402d - F04.02.20 Shipped
Sanction application workflow — club/district applies for sanction → relevant authority reviews (federation for national+, district for local) → district provides statement on regional applications → authority approves/rejects → sanction fee charged → competition listed in calendar. Configurable per level per tenant. — PL-F0402d
✅ PL-F0402d - F04.02.21 Shipped
Sanction deadlines per level — configurable per tenant (e.g., Sweden: Aug 1 for int/nat, Sep 30 for regional, district decides for local) — PL-F0402d
✅ PL-F0402d - F04.02.22 Shipped
Sanction quotas — configurable max per level per year (e.g., Sweden: ~7 int/nat, ~48 regional, max 4 parallel regionals). Blackout periods (e.g., no other events during SM). — PL-F0402d
✅ PL-F0402d - F04.02.23 Shipped
Sanction fee per competition class — configurable per tenant (e.g., Sweden: 300 SEK/class, no fee for youth classes). Payable to district or federation. — PL-F0402d
✅ PL-F0402d - F04.02.24 Shipped
Promotion/recruitment competition (propaganda) — license-free events for recruitment. Configurable: who can sanction (federation and/or district with quota), no ranking points, open to unlicensed players. — PL-F0402d
✅ PL-F0402d - F04.02.25 Shipped
Ranking-capped competitions (concours promotionnel) — France: events restricted to players below a certain ranking level. Configurable ranking threshold per competition. Per-tenant RankingCapConfig med default/min/max cap och level-koppling. — PL-F0402e
✅ PL-F0402e - F04.02.26 Shipped
Club-bound flag — if enabled, all players in a team must hold license in the same club. Violation = configurable penalty (disqualification, forfeit score, fine). club_bound_violation_penalty och club_bound_fine_amount på Competition. — PL-F0402e
✅ PL-F0402e - F04.02.27 Shipped
Match time limit — configurable per tenant/level (e.g., Spain: 60 min, CEP: 75 min). Optional. CompetitionLevel.default_match_time_limit_minutes och default_throw_time_limit_seconds auto-populeras vid skapande. — PL-F0402e
✅ PL-F0402e - F04.02.28 Shipped
Sanction revocation — authority can revoke sanction with mandatory reason, category, revoked_by. Auto-suspenderar tävling. Giltiga kategorier: rule_violation, safety_concern, venue_issue, federation_interest, organizer_misconduct, other. — PL-F0402e
✅ PL-F0402e
Tournament Discovery & Registration
F04.03> **Greenfield-ombyggnad (D-COMP m-2, `04caab5e.m-2`):** den rena Go/Postgres-backenden
How it works- F04.03.01 Shipped
Global tournament search (find competitions in any country) — PL-F0403a
✅ PL-F0403a - F04.03.02 Shipped
Map-based tournament finder (search by location, radius, dates) — PL-F0403a
✅ PL-F0403a - F04.03.03 Shipped
Filter by: country, region, format, discipline, team format, level, open/invitational — PL-F0403a
✅ PL-F0403a - F04.03.04 Shipped
"Traveling player" mode (show tournaments near a destination + date range) — PL-F0403a
✅ PL-F0403a - F04.03.05 Shipped
Tournament recommendations based on ELO level and preferences — PL-F0403a
✅ PL-F0403a - F04.03.06 Shipped
Follow tournaments in other countries (get notifications) — PL-F0403b
✅ PL-F0403b - F04.03.07 Shipped
Tournament detail page: rules, venue, entry fee, accommodation tips, language — PL-F0403b
✅ PL-F0403b - F04.03.08 Shipped
"Open to foreign players" flag on tournaments (organizer marks this) — PL-F0403b
✅ PL-F0403b - F04.03.09 Shipped
Cross-border entry requirements info (license validity, temporary license) — PL-F0403b
✅ PL-F0403b - F04.03.10 Shipped
Temporary license / day pass for foreign players (federation configurable) — PL-F0403b
✅ PL-F0403b - F04.03.11 Shipped
Tournament saved/wishlist (plan your tournament calendar) — PL-F0403c
✅ PL-F0403c - F04.03.12 Shipped
Travel group finder (other players going to same tournament) — PL-F0403c
✅ PL-F0403c - F04.03.13 Shipped
Online registration (individual and team) — PL-F0403c
✅ PL-F0403c - F04.03.14 Shipped
Registration validation (license check, age category, ranking eligibility) — PL-F0403c
✅ PL-F0403c - F04.03.15 Shipped
Registration payment integration (multi-currency for international) — PL-F0403c
✅ PL-F0403c - F04.03.16 Shipped
Registration deadline management — PL-F0403d
✅ PL-F0403d - F04.03.17 Shipped
Waiting list management — PL-F0403d
✅ PL-F0403d - F04.03.18 Shipped
Late registration handling — PL-F0403d
✅ PL-F0403d - F04.03.19 Shipped
Team composition validation (correct number of players, mixed rules) — PL-F0403d
✅ PL-F0403d - F04.03.20 Shipped
Substitution rules and management — PL-F0403d
✅ PL-F0403d - F04.03.21 Shipped
Registration confirmation and receipt — PL-F0403e
✅ PL-F0403e - F04.03.22 Shipped
Bulk registration (club enters multiple teams) — PL-F0403e
✅ PL-F0403e - F04.03.23 Shipped
Seeding based on rankings — PL-F0403e
✅ PL-F0403e - F04.03.24 Shipped
Cross-border registration (register for tournament in another nation with valid license) — PL-F0403e
✅ PL-F0403e - F04.03.25 Shipped
Registration language (show tournament info in player's language) — PL-F0403e
✅ PL-F0403e - F04.03.26 Shipped
PublicationScope enum (PRIVATE/ORGNODE/TENANT/GLOBAL) on Competition — PL-T007
✅ PL-T007 - F04.03.27 Shipped
PUT /competitions/{id}/publication endpoint with audit log — PL-T007
✅ PL-T007 - F04.03.28 Shipped
GET /public/competitions/global cross-tenant public API (paginerad, cachad 15 min) — PL-T007
✅ PL-T007 - F04.03.29 Shipped
GET /public/tenants/{code}/competitions per-federation public listing — PL-T007
✅ PL-T007 - F04.03.30 Shipped
Scope filter on GET /competitions (query param scope=private
tenant|orgnode|global) — PL-T007 | ✅ PL-T007 - F04.03.31 Shipped
GLOBAL scope requires federation-admin (club-admin 403 policy) — PL-T007
✅ PL-T007 - F04.03.32 Shipped
Competition visibility service with ORGNODE ancestor/descendant expansion — PL-T007
✅ PL-T007 - F04.03.33 Shipped
Backfill migration (existing competitions → TENANT scope) — PL-T007
✅ PL-T007 - F04.03.34 Shipped
Compound index (publication_scope, status, start_date) for queries — PL-T007
✅ PL-T007
Draw & Scheduling (Tirage au Sort)
F04.04> **Greenfield-rebuild (D-COMP `04caab5e.m-3`, backend t-1):** F04.04 (lottning/tirage) +
How it works- F04.04.01 Shipped
Automatic draw generation (randomized with seeding rules)
✅ PL-F0404a - F04.04.02 Shipped
Separation rules (same club, same region in different groups)
✅ PL-F0404a - F04.04.03 Shipped
Poule composition (balanced by ranking)
✅ PL-F0404a - F04.04.04 Shipped
Bracket generation (single/double elimination)
✅ PL-F0404a - F04.04.05 Shipped
Swiss-system pairing algorithm
✅ PL-F0404a - F04.04.12 Shipped
Monrad pairing algorithm (Swiss variant, common in Scandinavia)
✅ PL-F0404b - F04.04.13 Shipped
Mêlée random team draw (new random teams each round)
✅ PL-F0404b - F04.04.14 Shipped
Super-mêlée draw (mixed player levels, partner rotation every round)
✅ PL-F0404b - F04.04.06 Shipped
Court assignment optimization
✅ PL-F0404b - F04.04.07 Shipped
Schedule generation (time slots per round)
✅ PL-F0404b - F04.04.08 Shipped
Draw publication and notification
✅ PL-F0404c - F04.04.09 Shipped
Manual draw adjustments (with audit trail)
✅ PL-F0404c - F04.04.10 Shipped
Bye management (odd number of participants)
✅ PL-F0404c - F04.04.11 Shipped
Re-draw capabilities (when teams withdraw)
✅ PL-F0404c
Match Management
F04.05> **Greenfield-rebuild (D-COMP `04caab5e.m-4`, backend):** match-status-FSM (F04.05.03),
How it works- F04.05.01 Shipped
Match score entry (by official, scorer, or team delegate) — PL-F0405a
✅ PL-F0405a - F04.05.02 Shipped
Real-time score tracking — PL-F0405a
✅ PL-F0405a - F04.05.03 Shipped
Match status tracking (scheduled, in progress, completed, suspended, forfeit) — PL-F0405a
✅ PL-F0405a - F04.05.04 Shipped
Match timer — configurable: total match time limit (Spain: 60 min, CEP: 75 min) AND per-throw time limit (Spain: 30 seconds). Both optional and configurable per tenant/competition level. Distinct enforcement UI for each. — PL-F0405a
✅ PL-F0405a - F04.05.05 Shipped
Match result confirmation (both teams or umpire) — PL-F0405a
✅ PL-F0405a - F04.05.06 Shipped
Score dispute resolution workflow — PL-F0405a
✅ PL-F0405a - F04.05.07 Shipped
Forfeit and withdrawal handling — PL-F0405b
✅ PL-F0405b - F04.05.08 Shipped
Court change management — PL-F0405b
✅ PL-F0405b - F04.05.09 Shipped
Match comments and incident reporting — PL-F0405b
✅ PL-F0405b - F04.05.10 Shipped
Photo/video attachment to match records — PL-F0405b
✅ PL-F0405b - F04.05.11 Shipped
Mène (end/round) tracking — score progression per mène within a match — PL-F0405b
✅ PL-F0405b - F04.05.12 Shipped
Mène-level detail: which team scored, how many points, cochonnet position — PL-F0405b
✅ PL-F0405b - F04.05.13 Shipped
Individual throw tracking (optional, for detailed analytics) — PL-F0405c
✅ PL-F0405c - F04.05.14 Shipped
Throw type classification: point (portée/raspaille/donnée), tir (carreau/palet/raté) — PL-F0405c
✅ PL-F0405c - F04.05.15 Shipped
Throw outcome recording: successful/missed, distance from cochonnet — PL-F0405c
✅ PL-F0405c - F04.05.16 Shipped
Photo proof upload per mène (disputed measurements) — PL-F0405c
✅ PL-F0405c - F04.05.17 Shipped
Match timeline view (mène-by-mène score progression) — PL-F0405c
✅ PL-F0405c - F04.05.18 Shipped
Court Ops Console — live-board för marshal/jury president med color-coded threshold-flaggor och SSE-stream per event — PL-T223
✅ PL-T223 - F04.05.19 Shipped
Threshold alerts — warn/overrun/escalate (75/100/125 % default), tenant/event-config, audit-trail i CourtOpsAlert med ack-flow — PL-T223
✅ PL-T223 - F04.05.20 Shipped
Marshal broadcast — audience ∈ {all_marshals, all_teams, court_neighbors, next_up}, multi-lang body, F09.02-fan-out — PL-T223
✅ PL-T223 - F04.05.21 Shipped
Live rond-timer — server-auktoritativ nedräknings-FSM (not_started→running→paused⇄running→expired) styrd av arrangör/court-ops (start/paus/förläng/avsluta), timer-event på live-kanalen + nedräkning i app & publik scoreboard, expiry-tick med "spela klart sista rundan"-banner (v1 = in-app/SSE, ingen native push) — D-COMP-TIMER 1e481c39.m-1
✅ D-COMP-TIMER (backend t-1) - F04.05.22 Shipped
Arrangörens "Tidtagning"-flik (admin/app/tavlingar/detalj?id=[id]&tab=tidtagning) — stor server-driven klocka + status ("Kör · startades … · Rond N · alla banor") + knapparna ▶ Starta / ⏸ Paus / +5 min / Avsluta rond, som anropar t-1:s capability-gejtade endpoints via den genererade klienten (If-Match/version). Expired-signal med ikon + text (NF-7). — D-COMP-TIMER 1e481c39.m-1 t-2
✅ D-COMP-TIMER (frontend t-2) - F04.05.23 Shipped
Spelar-app-nedräkning (app/app/live/[comp]) — "Tid kvar MM:SS · Rond N" driven av den pollade live-snapshotten, klientlokal tick med server_time-skew-korrektion (NF-1); expiry-banner "Tiden är ute — spela klart sista rundan." reses klientlokalt när nedräkningen når 0 för en running-timer med last_end_on_expiry (eller vid server-flippad expired) — den pollande appen inväntar inte serverns expiry-tick (in-app/SSE, ingen native push); vid poll-tapp behålls senast kända nedräkning ("återansluter…", NF-8). — D-COMP-TIMER 1e481c39.m-1 t-2
✅ D-COMP-TIMER (frontend t-2) - F04.05.24 Shipped
Publik scoreboard-nedräkning (web/app/d/[displayId], D-SCORE) — "Tid kvar · Rond N" ur den pollade /public/scoreboard/{id}-snapshotten, samma server-instant-nedräkning; utomhusläsbar display-variant. — D-COMP-TIMER 1e481c39.m-1 t-2
✅ D-COMP-TIMER (frontend t-2) - F04.05.25 Shipped
Court Marshal-tavla — bana-centrerad tävlingsdags-trafikledning (GET/POST /v1/operator/court-marshal/{id}/{board\
queue|call-up|clear|delays|delays/{did}/report|stream}). Ban-status-tavla som projicerar varje allokerad bana (härledd ur venue-courts/num_courts, aldrig hårdkodad) med tillstånd free|in_progress|done|delayed, KPI-rad, prioriterad klass-filtrerbar match-kö, upprop (tilldela ledig bana via schemaläggnings-substratet + registrera announcement m. kanaler/språk, race-säker + idempotent), clear-court, flagga-försening + rapportera-TD, SSE-ström. Skild från D-VENUE banstatus (FR-13). Backend i t-1; admin-tavla wire:ad i t-2 (admin ▸ tavlingsdags ▸ #marshal: KPI-rad, ban-status-kort, klass-filtrerbar kö, upprops- + delay-paneler, live-poll, a11y AA). — D-COMP-OPS 8a5db0fb.m-2 | ✅ D-COMP-OPS (backend t-1 · frontend t-2) - F04.05.26 Shipped
Table Official-desk — tävlingsdags incheckningsdisk (GET/POST /v1/operator/table-official/{id}/{desk\
check-in|bulk-check-in|day-of|no-show|escalate|stream}). Ett operativt lager ovanpå anmälnings- (registration), licens- (license) och betalnings- (payments) substraten som binder ihop tävlingsdagens flöde "välkomna → verifiera → checka in → ta betalt": disk-projektion (KPI-rad + incheckningslista med sök/filter/CSV, härledd ur riktiga anmälningar joinade mot licens-status valid|expired|blocked|unknown + betalnings-status paid|pending|none), licens-verifiering (läst ur D-MEMBER, aldrig fabricerat), incheckning + on-site-betalning (pay_on_site skapar en RIKTIG payments-rad markerad betald och länkar via registration.payment_ref, idempotent + race-säker), bulk-incheckning (hoppar över blocked/expired/redan), eskalera-spärr → head umpire, day-of walk-in-registrering (full klass → dokumenterat utfall, aldrig tyst överbokning), no-show/scratch (+ typad event/SSE-signal mot lottningen + TD), SSE-ström. Check-in-/no-show-tillstånd strikt additivt på registration (migration 00108). Skild från D-VENUE court-booking-checkin (FR-14). Backend i t-1; admin-disk wire:ad i t-2 (admin ▸ tavlingsdags ▸ #desk). — D-COMP-OPS 8a5db0fb.m-3 | ✅ D-COMP-OPS (backend t-1 · frontend t-2) - F04.05.27 Shipped
Rules Reference — courtside sökbar regel-uppslagning (GET /v1/rules/{search\
categories|articles/{id}|bundle|bundle/version|recent-changes|bookmarks}, POST/DELETE /v1/rules/bookmarks[/{id}]). Ett läs-lager över ett läs-optimerat regel-innehålls-substrat (migration 00109, seedat av seed-rules): nyckelordssök (artikelnummer/titel/brödtext/situation, trigram-index, p95 < 300 ms), chip-kategorier, artikeldetalj med tolkningar (FAQ|precedent|guidance) + genuina kors-referenser, flerspråkig uppslag med markerad språk-fallback (en/sv/fr/es/it), versionerad+checksummad offline-bundle (deterministisk version, olika tillämpligt innehåll → olika version), senaste-ändringar och actor-privata bokmärken (idempotent star/unstar). Bas-FIPJP delat (tenant_id IS NULL), nationell/regional variant tenant-scopad (aldrig läckt, 404 x-tenant), endast Approved exponeras. Pull-baserad (ingen SSE). Ny bred läs-capability rules:read (domarkår L1–L5/jury/spelare + tävlingsroller). Kanonisk regelkälla/authoring ägs av D-GOV (admin/regelverk, ostartad); denna task läser + seedar minimalt substrat. Skild från D-OFF/D-EDU utbildning (innehåll, ej kurs). — D-COMP-OPS 8a5db0fb.m-4 t-1 | ✅ D-COMP-OPS (backend t-1) - F04.05.28 Shipped
Rules Reference — admin courtside-yta (tavlingsdags ▸ #regler). Wire:ar F04.05.27:s riktiga endpoints till admin-vyn admin/app/tavlingar/detalj/tavlingsdags/page.tsx (RulesReference.tsx + lib/rules-reference.tsx hooks + lib/rules-reference-presenter.ts ren logik): sökpanel (fritextsök med debounce → /search, språkväljare en/sv/fr/es/it → ?lang, Offline-badge som speglar verklig manifest-version ur /bundle/version — aldrig hårdkodat datum), kategori-chips (/categories + "Alla"-reset → ?category), träfflista med härledd träffräknare + artikelnr/kategori/titel/utdrag, artikeldetalj (full regel + tolkningar/kors-refs ur /articles/{id}, markerad språk-fallback), samt sido-korten Snabb uppslagning · Flerspråkig · Bokmärken (GET/POST/DELETE /bookmarks) & senaste ändringar (/recent-changes). Ingen hårdkodad/placeholder-data (AC-14); tom/laddande/fel/403-lägen verkliga; pull-baserad (ingen SSE, FR-12). ALL åtkomst via delat transport-lager (rulesReferenceOps.*) — ingen rå fetch( (fetch-ratchet). A11y WCAG 2.2 AA (färg aldrig enda bäraren av kategori-/tolknings-/status-info, träffytor ≥44px, aria-live träffräknare). Terminologi "runda"/"Boulodrome"/å/ä/ö. #marshal (m-2), #desk (m-3) och referee-call-spegeln (m-1) orörda (NFR-7). E2e: tools/gate/rules-reference-e2e.mjs (verify.sh L4, RUN_UI). — D-COMP-OPS 8a5db0fb.m-4 t-2
✅ D-COMP-OPS (frontend t-2)
Results & Standings
F04.06> **Rena Go/Postgres-ytan (D-COMP m-6, `04caab5e.m-6`) levererad.** Standings-beräkningen
How it works- F04.06.01 Shipped
Real-time standings/leaderboard calculation
✅ PL-F0406a - F04.06.02 Shipped
Tiebreaker rules (head-to-head, point difference, quotient)
✅ PL-F0406a - F04.06.03 Shipped
Poule standings with all stats (W, L, PF, PA, PD, quotient)
✅ PL-F0406a - F04.06.04 Shipped
Bracket progression (automatic advancement)
✅ PL-F0406a - F04.06.05 Shipped
Final results publication
✅ PL-F0406a - F04.06.06 Shipped
Result export (PDF, CSV, federation format)
✅ PL-F0406b - F04.06.07 Shipped
Historical results archive
✅ PL-F0406b - F04.06.08 Shipped
Public results page (embeddable)
✅ PL-F0406b - F04.06.09 Shipped
Audit trail on all result entries and modifications
✅ PL-F0406b
Rankings
F04.07> **Rebuild-status (D-RANK `4aaa301a.m-1`).** Ranking-fundamentet är byggt i Go/Postgres: de rena
How it works- F04.07.01 Shipped
National ranking system per federation
✅ PL-F0407a - F04.07.02 Shipped
World ranking (FIPJP)
✅ PL-F0407a - F04.07.03 Shipped
Continental rankings
✅ PL-F0407a - F04.07.04 Shipped
Configurable ranking algorithm per tenant — each federation defines: point scale per competition level × placement × number of participants, ranking coefficient/multiplier per level, max competitions counted per year, and whether ranking is per competition class (Sweden: separate list for Ös, Ds, V55s etc.)
✅ PL-F0407a - F04.07.05 Shipped
Ranking per configurable dimension — separate rankings per: competition class (age/gender), game format, or combined. Configurable per tenant. A player can appear on multiple ranking lists.
✅ PL-F0407a - F04.07.06 Shipped
Ranking history and progression charts
✅ PL-F0407a - F04.07.07 Shipped
Configurable ranking validity — points expire after configurable period: Sweden 1 year from competition date, France 2 years, Germany 3 years with weighted decay (3×current + 2×previous + 1×two years ago)
✅ PL-F0407b - F04.07.08 Shipped
Tournament category multipliers — configurable categories (e.g., Germany: A/B/C/D with multipliers 4/3/2/1; Sweden: point scale varies by level + participant count; France: coefficients per level)
✅ PL-F0407b - F04.07.09 Shipped
Ranking publication and notification
✅ PL-F0407b - F04.07.10 Shipped
Ranking-based qualification thresholds
✅ PL-F0407b - F04.07.11 Shipped
Club/team rankings
✅ PL-F0407b - F04.07.12 Shipped
Public ranking search and filtering
✅ PL-F0407b - F04.07.13 Shipped
Global ELO rating system (skill-based, worldwide, format-independent) — PL-F0407c
✅ PL-F0407c - F04.07.14 Shipped
ELO calculation per match result (win/loss margin affects change) — PL-F0407c
✅ PL-F0407c - F04.07.15 Shipped
ELO K-factor configuration (higher for new players, lower for established) — PL-F0407c
✅ PL-F0407c - F04.07.16 Shipped
ELO separate ratings per format (singles, doubles, triples) — PL-F0407c
✅ PL-F0407c - F04.07.17 Shipped
ELO history and progression chart per player — PL-F0407c
✅ PL-F0407c - F04.07.18 Shipped
ELO-based matchmaking suggestions (balanced pairing) — PL-F0407c
✅ PL-F0407c - F04.07.19 Shipped
ELO leaderboards (global, continental, national, club) — PL-F0407d
✅ PL-F0407d - F04.07.20 Shipped
Dual ranking display: Federation Points + Global ELO side by side — PL-F0407d
✅ PL-F0407d - F04.07.21 Shipped
ELO updated from both official competitions and casual games — PL-F0407d
✅ PL-F0407d - F04.07.22 Shipped
Partnership/team ELO (combined rating for regular partnerships) — PL-F0407d
✅ PL-F0407d
League / Series Management
F04.08Season-long competitions where clubs/teams play regular fixtures.
How it works- F04.08.01 Shipped
League creation (divisions, tiers, pools) — configurable per tenant — PL-F0408a
✅ PL-F0408a - F04.08.02 Shipped
Promotion/relegation rules (automatic + playoff, configurable spots per tenant) — PL-F0408a
✅ PL-F0408a - F04.08.03 Shipped
Home/away fixture generation (round-robin, single or double) — PL-F0408a
✅ PL-F0408a - F04.08.04 Shipped
Configurable tiebreaker rules per tenant — Sweden: points → wins → klotskillnad → head-to-head → lottery. Other nations may differ. — PL-F0408a
✅ PL-F0408a - F04.08.05 Shipped
Match postponement and rescheduling with audit trail + tenant deadline enforcement — PL-F0408a
✅ PL-F0408a - F04.08.06 Shipped
Season results archive with public endpoints and cross-league search — PL-F0408a
✅ PL-F0408a - F04.08.07 Shipped
Team roster with max players per season — configurable per tenant (e.g., Germany Bundesliga: max 10 players per team per season). max_players_per_team på League, valideras vid register_team + update_roster. — PL-F0408b
✅ PL-F0408b - F04.08.08 Shipped
League registration deadline and team enrollment. registration_deadline på League (date, optional). POST /leagues/{id}/open-registration (setup→registration, kräver minst en division), POST /leagues/{id}/close-registration (registration→active). Deadline kontrolleras inklusivt vid teamregistrering och roster-uppdatering. — PL-F0408b
✅ PL-F0408b - F04.08.09 Shipped
Composite match day — a league match day consists of multiple sub-matches. Configurable format per league: Germany Bundesliga (1 triplette + 1 doublette + 1 mixed doublette), France D1N (3 triplettes + 3 doublettes + 3 tête-à-tête = 9 parties), Denmark (similar). Match day result = sum of sub-match results. CompositeMatchDayConfig stöder name/description; spelarantal per sub-match valideras mot GameFormat.players_per_team; GET /leagues/{id}/match-day-summary med round_number-filter. — PL-F0408b
✅ PL-F0408b - F04.08.10 Shipped
Player eligibility per match (registered in roster, not suspended, not transferred). Service check_player_eligibility() med 4 kontroller: roster, license_active, not_transferred, club_match. Bulk-endpoint POST /leagues/{id}/divisions/{level}/teams/{club_id}/check-eligibility. Eligibilitetsfel blockerar sub-match-recordning. — PL-F0408b
✅ PL-F0408b - F04.08.11 Shipped
League statistics (top scorers, most wins, etc.). GET /leagues/{id}/player-statistics med sort_by (total_points_scored/matches_won/sub_matches_won/matches_played) och division_level-filter. Publik spegling GET /public/leagues/{id}/player-statistics. — PL-F0408b
✅ PL-F0408b - F04.08.12 Shipped
Inter-club league (clubs send teams). league_type (inter_club/individual/mixed) på League. Inter_club: klubbar valideras mot Club-samlingen, en klubb kan ej registreras i flera divisioner i samma liga (409), holdfællesskab via club_ids (2+ klubbar som ett lag). GET /leagues/?league_type= filter. — PL-F0408b
✅ PL-F0408b - F04.08.13 Shipped
Inter-region/district league (regional all-star teams or district series). scope (club/district/region) och district_id på League; district_id på LeagueTeam; validering att district_id krävs vid teamregistrering i district/region-liga; duplikat-district i samma division blockeras (409). — PL-F0408c
✅ PL-F0408c - F04.08.14 Shipped
Playoff generation from league standings. championship-bracket-typ; seeded_from_standings; rounds_total (2 = hem+borta); seed_from_phase; duplikat-bracket skyddas (409). — PL-F0408c
✅ PL-F0408c - F04.08.15 Shipped
League calendar with venue rotation. GET /leagues/{id}/calendar (rounds grupperade med fixture-detaljer, from_date/to_date-filter); GET /public/leagues/{id}/calendar (utan auth); home_venue_map vid fixture-generering. — PL-F0408c
✅ PL-F0408c - F04.08.16 Shipped
League hierarchy — national league feeds into regional/district leagues. parent_league_id/league_level på League; LeagueHierarchyLevel i TenantConfig.LeagueConfig; GET /leagues/hierarchy-tree (rekursivt träd per tenant); GET /leagues/{id}/hierarchy (per-liga vy). Konfigurerbart per tenant (France: D1N→D2N→D3N→DR→DD, Germany: Bundesliga→Landesliga→Bezirksliga). — PL-F0408c
✅ PL-F0408c - F04.08.17 Shipped
Transfer quarantine during active league — configurable: transfer_quarantine_scope (tenant/player_league/none) i TenantConfig.LeagueConfig. GET /leagues/{id}/transfer-quarantine-status per spelare. Karantänlogik integrerad i transfer-flödet. — PL-F0408c
✅ PL-F0408c - F04.08.18 Shipped
Multi-phase league season — format_type (round_robin/knockout/swiss/monrad), points_for_win/draw/loss-override, carry_over_points, transition_criteria (top_n/threshold/all) per fas. POST /leagues/{id}/phases/{n}/transition med kvalificerade/eliminerade lag i svar. — PL-F0408c
✅ PL-F0408c - F04.08.19 Shipped
Promotion via standalone tournament — configurable: promotion determined by a separate tournament (Germany: Aufstiegsrunde where 10 Landesmeister play round-robin, top 4 promote to Bundesliga). Distinct from in-league promotion. — PL-F0408d
✅ PL-F0408d - F04.08.20 Shipped
Substitution constraints per league — configurable: reserve players locked to specific sub-match after insertion (Spain: Liga Nacional), maximum reserves per match day, substitution registration deadline. — PL-F0408d
✅ PL-F0408d - F04.08.21 Shipped
Court specification enforcement per league — configurable: minimum court dimensions, closed court rules (Spain: pista cerrada 50cm from sideline, 1m from backline). Validated at venue assignment. — PL-F0408d
✅ PL-F0408d
National Team Selection
F04.09> **Greenfield-ombyggnad (D-NATIONAL m-1 t-1, `7cd8cecf.m-1`) — uttagningsprocessens grund:**
How it works- F04.09.01 Shipped
Selection committee management — PL-F0409
✅ PL-F0409 - F04.09.02 Shipped
Selection criteria definition — PL-F0409
✅ PL-F0409 - F04.09.03 Shipped
Candidate pool tracking (ranking, performance, availability) — PL-F0409
✅ PL-F0409 - F04.09.04 Shipped
Team composition builder — PL-F0409
✅ PL-F0409 - F04.09.05 Shipped
Selection announcement workflow — PL-F0409
✅ PL-F0409 - F04.09.06 Shipped
National team history and records — PL-F0409
✅ PL-F0409
Competition Format Catalog
F04.10All supported competition formats and their unique rules.
How it works- F04.10.01 Shipped
Knockout / Elimination — single elimination, loser goes home — PL-F0410a
✅ PL-F0410a - F04.10.02 Shipped
Double elimination — losers bracket, second chance — PL-F0410a
✅ PL-F0410a - F04.10.03 Shipped
Consolation bracket (consolante) — separate bracket for first-round losers — PL-F0410a
✅ PL-F0410a - F04.10.04 Shipped
Round-robin — everyone plays everyone — PL-F0410a
✅ PL-F0410a - F04.10.05 Shipped
Poules + Knockout — group stage then elimination (most common) — PL-F0410a
✅ PL-F0410a - F04.10.06 Shipped
Swiss system — paired by similar results, no elimination — PL-F0410a
✅ PL-F0410a - F04.10.07 Shipped
Monrad system — Swiss variant (Scandinavian, strength-based pairing) — PL-F0410b
✅ PL-F0410b - F04.10.08 Shipped
Mêlée — individual entry, random team draw each round, individual ranking — PL-F0410b
✅ PL-F0410b - F04.10.09 Shipped
Super-mêlée — like mêlée but mixed levels, partner rotation every round — PL-F0410b
✅ PL-F0410b - F04.10.10 Shipped
Marathon — continuous play all day, most wins/points wins — PL-F0410b
✅ PL-F0410b - F04.10.11 Shipped
Américaine — doublette with partner change after each match (round-robin style) — PL-F0410b
✅ PL-F0410b - F04.10.12 Shipped
Tête-à-tête integral — every player plays every other player — PL-F0410b
✅ PL-F0410b - F04.10.13 Shipped
Championnat Tête-à-tête — singles championship (3 boules each)
✅ PL-F0410c ✅ PL-F0410c - F04.10.14 Shipped
Championnat Doublette — doubles championship (3 boules each)
✅ PL-F0410c ✅ PL-F0410c - F04.10.15 Shipped
Championnat Triplette — triples championship (2 boules each)
✅ PL-F0410c ✅ PL-F0410c - F04.10.16 Shipped
Championnat Mixte — mixed doubles/triples (mandatory male+female)
✅ PL-F0410c ✅ PL-F0410c - F04.10.17 Shipped
Championnat Combiné — combined competition (match play + shooting skills)
✅ PL-F0410c ✅ PL-F0410c - F04.10.18 Shipped
Championnat des Clubs — inter-club championship (club sends multiple teams)
✅ PL-F0410c ✅ PL-F0410c - F04.10.19 Shipped
Championnat des Nations — nation vs nation (national delegations)
✅ PL-F0410d ✅ PL-F0410d - F04.10.20 Shipped
Tir de Précision — precision shooting at marked targets on court
✅ PL-F0410d ✅ PL-F0410d - F04.10.21 Shipped
Tir de Précision scoring system (points per target zone hit)
✅ PL-F0410d ✅ PL-F0410d - F04.10.22 Shipped
Tir de Précision court layout management (target positions per FIPJP rules)
✅ PL-F0410d ✅ PL-F0410d - F04.10.23 Shipped
Tir Rapide — rapid shooting against the clock
✅ PL-F0410d ✅ PL-F0410d - F04.10.24 Shipped
Tir Rapide timer integration (countdown per attempt)
✅ PL-F0410d ✅ PL-F0410d - F04.10.25 Shipped
Tir Progressif — increasingly difficult targets (distance, angle, obstacles)
✅ PL-F0410e ✅ PL-F0410e - F04.10.26 Shipped
Tir Progressif level progression and scoring
✅ PL-F0410e ✅ PL-F0410e - F04.10.27 Shipped
Relais de Tir — team shooting relay (each player shoots in sequence)
✅ PL-F0410e ✅ PL-F0410e - F04.10.28 Shipped
Shooting competition leaderboard (separate from match rankings)
✅ PL-F0410e ✅ PL-F0410e - F04.10.29 Shipped
Shooting accuracy statistics per player (career, season, competition)
✅ PL-F0410e ✅ PL-F0410e - F04.10.30 Shipped
Shooting competition as standalone event or embedded within combined championship
✅ PL-F0410e ✅ PL-F0410e - F04.10.31 Shipped
Video replay integration for shooting competitions (analyze technique)
✅ PL-F0410f ✅ PL-F0410f - F04.10.32 Shipped
National Championship (qualification pathway: club > regional > national)
✅ PL-F0410f ✅ PL-F0410f - F04.10.33 Shipped
Continental Championship (e.g., European Championship) — national delegations
✅ PL-F0410f ✅ PL-F0410f - F04.10.34 Shipped
World Championship — FIPJP sanctioned, all disciplines
✅ PL-F0410f ✅ PL-F0410f - F04.10.35 Shipped
Cup / Coupe — knockout with seeding, often multi-round across weeks
✅ PL-F0410f ✅ PL-F0410f - F04.10.36 Shipped
Grand Prix / Ranking tournament — open entry, high ranking points coefficient
✅ PL-F0410f ✅ PL-F0410f - F04.10.37 Shipped
Challenge / Trophée — invitational tournament (organizer selects participants)
✅ PL-F0410g ✅ PL-F0410g - F04.10.38 Shipped
Masters / Finale — end-of-season event for top-ranked players
✅ PL-F0410g ✅ PL-F0410g - F04.10.39 Shipped
World Games — multi-sport event with petanque included
✅ PL-F0410g ✅ PL-F0410g - F04.10.40 Shipped
Youth Championship — dedicated age-group championships (U13, U15, U18, U23)
✅ PL-F0410g ✅ PL-F0410g - F04.10.41 Shipped
Veterans Championship — 55+, 65+ categories
✅ PL-F0410g ✅ PL-F0410g - F04.10.42 Shipped
Para-Petanque Championship — disability classifications
✅ PL-F0410g ✅ PL-F0410g - F04.10.43 Shipped
Women's Championship — dedicated women's events at all levels
✅ PL-F0410h ✅ PL-F0410h - F04.10.44 Shipped
Championship series — multiple events, cumulative points determine overall winner
✅ PL-F0410h ✅ PL-F0410h - F04.10.45 Shipped
Series calendar management (which events count)
✅ PL-F0410h ✅ PL-F0410h - F04.10.46 Shipped
Series standings (running total across events)
✅ PL-F0410h ✅ PL-F0410h - F04.10.47 Shipped
Best-of-N scoring (only top X results count)
✅ PL-F0410h ✅ PL-F0410h - F04.10.48 Shipped
Series finale qualification (top N qualify for finale)
✅ PL-F0410h ✅ PL-F0410h - F04.10.49 Shipped
Series sponsorship and branding per circuit
✅ PL-F0410i ✅ PL-F0410i - F04.10.50 Shipped
Custom format builder (combine stages: poules → repechage → knockout)
✅ PL-F0410i ✅ PL-F0410i - F04.10.51 Shipped
Stage transition rules (how many advance from each stage)
✅ PL-F0410i ✅ PL-F0410i - F04.10.52 Shipped
Points-to-win configuration (11, 13, or custom per round/stage)
✅ PL-F0410i ✅ PL-F0410i - F04.10.53 Shipped
Time limit per match/mène (configurable per competition)
✅ PL-F0410i ✅ PL-F0410i - F04.10.54 Shipped
Tiebreaker configuration per format
✅ PL-F0410i ✅ PL-F0410i - F04.10.55 Shipped
Format validation (ensure rules are internally consistent)
✅ PL-F0410j ✅ PL-F0410j - F04.10.56 Shipped
Format preview (simulate a tournament with N teams to check flow)
✅ PL-F0410j ✅ PL-F0410j - F04.10.57 Shipped
Composable Steg▸Fas system per competition class (D-COMP-SYS delta #1, ee51ed1f.m-1) — a class bears an ordered chain of stages, each an ordered pipeline of phases (poule/group/swiss_monrad/round_robin/snake/finals + team-formation select/melee/panache/vauclusienne; tiers A–E, consolante, barrage, semi_pool, multi-stage kval→final). t-1 [DONE]: pure per-fas engine (GenerateComposedDraw). t-2 [DONE]: data model (competition_stage/competition_phase, migration 00062), persistence, and the komponerings-API PUT/GET /v1/competitions/{id}/classes/{cid}/system. t-3 [DONE]: per-fas draw persisted end-to-end (POST …/draws stamps stage_id/phase_id; flat classes stay NULL — FR-9), fas-aware format/preview (unsaved system), and the traceability matrix vs spelsystem.astro. Scoring resolution = delta #2; wizard UI = delta #3. Docs: docs/domain/competition/steg-fas-model.md, docs/domain/competition/steg-fas-sparbarhetsmatris.md, specs/api/competition-compose-system.md, specs/api/competition-draw-per-phase.md.
✅ ee51ed1f.m-1 - F04.10.58 Shipped
Per-fas/steg/match/klass-poäng + avslutsvillkor (D-COMP-SYS delta #2, ee51ed1f.m-2) — poäng- och avslutsregler löses upp per fas/steg/match i stället för en global points_to_win. En tävling bär default_scoring (end_condition ∈ points \
time_plus_end | fixed_ends, points_to_win, time_limit_min, ends_cap) som ärvs och kan åsidosättas på klass- (scoring_default), steg-, fas- och match-nivå (scoring_override), upplöst fält-för-fält längs kedjan match→fas→steg→klass→tävling. t-1 [DONE]: ren upplösnings-/validerings-/tir-kärna. t-2 [DONE]: additiv migration (00063), upplösning inläst ur bärarna, scoring_override-validering i PUT …/system (13|11|annat relaxat; time_plus_end utan tid → 422), avslutsvillkors-medveten confirm + mjuk-validerings-tröskel (score_above_<N>) mot riktig Postgres, och upplöst scoring_config på GET /v1/matches/{id}. t-3 [DONE]: Tir de précision-poängväg (5 stationer × 5 skott, 0–5/skott, total 0–25) + registrerings-API (POST /v1/matches/{id}/tir-shots, GET …/tir-result, GET /v1/competitions/{id}/classes/{cid}/tir-standings), append-only-korrigering, rangordning + tiebreak (fler 5:or → fler 4:or → …), och strikt separation tir↔klot (fel spelform mot fel väg → 422) bevisat mot riktig Postgres. Wizard-UI = delta #3. Docs: docs/domain/competition/scoring-resolution-model.md, docs/domain/competition/tir-de-precision-scoring.md, specs/api/competition-scoring-resolution.md, specs/api/competition-tir-precision.md. | ✅ ee51ed1f.m-2 - F04.10.60 Shipped
Format och regler är DATA — disciplin-scopad katalog + namngivna presets i tenant_configs (D-COMP-SYS delta #7, ee51ed1f.m-4) — den katalog av spelformat, systemtyper, fas-enum-domäner och poäng-/klot-regler (FIPJP Art.1) som tidigare låg hårdkodad i Go-maps (recognisedFormats, defaultBoules, validPhaseType, valid*, EndCondition-domänen, maxPointsToWin) är nu disciplin-scopad data i tenant_configs, seedad med en plattforms-baslinje och per-tenant överskrivningsbar — en flerdisciplin-federation (FRA: petanque + jeu_provencal, §N gap #7) bär en egen katalog per disciplin utan att de blandas. Ovanpå katalogen bär tenanten de namngivna presets (§D / spelsystem.astro rad 30–40) som data. t-1 [DONE]: ren datamodell (competition.Catalog/Preset) injicerad i validerarna. t-2 [DONE]: migration 00065 (system_catalog/presets-kolumnerna), disciplin-scopad seed, kant-resolver som injicerar den per-tenant-resolverade katalogen (samma anrop → olika utfall enbart pga data: {"format":"raffa"} → 200 för tenant med override, 422 för baslinje), och preset-läs-API GET /v1/competitions/presets?discipline= (auth-skyddat, tenant-scopat) som wizardens preset-väljare (delta #3) konsumerar — bevisat mot riktig Postgres, ingen Go-map är längre runtime-auktoritet (FR-5). Wizard-UI = delta #3; league-preset-komposition = D-LEAGUE (A-3). Docs: docs/domain/competition/format-katalog-presets-data.md, specs/api/competition-presets-catalog.md. D-FEDCONFIG d0601eb6.m-2 (t-1+t-3) — spelsystem-presets LIVE i federationskonfigurations-hubben: system_catalog/presets skrivbara via PUT /v1/tenant/config (strukturvalidering ValidatePresets/ValidateSystemCatalog, 422 fältpekat) och preset-fliken (#presets) i admin/federationskonfiguration hanterar hela livscykeln som DATA — aktivera/avaktivera (disabled på raden; server-side-filtrerad ur läs-API:t, "avaktivera samtliga" ⇒ tom wizard-lista, aldrig tyst baslinje-fallback), anpassa (kopia med ny key), skapa egen (minimal giltig komposition), ärlig "baslinje"-märkning + materialisering av HELA den upplösta disciplin-listan vid första redigeringen. Genomslag utan omdeploy i wizardens spelsystem-steg och /tavlingar/spelsystem. Vy-spec: specs/admin/views/federationskonfiguration.md.
✅ ee51ed1f.m-4 · d0601eb6.m-2.t-3 - F04.10.61 Shipped
7-stegs "Skapa tävling"-wizard + systemkatalog — backend-luckor (delta #3, ee51ed1f.m-5.t-1) — de sista mockup-fälten som saknade en backend-bärare stängs additivt (migration 00066, strikt additiv). competition bär nu de redaktionella Grunder-fälten num_courts/competition_director/contact_email/visibility (public\
members_only|invited, skild från publication_scope) samt write-vägen för default_scoring (§K tävlings-standard, m-2). competition_class får require_license + write-vägen för m-3-constraints (min_age/max_age/gender_rule/squad_size/reserves_allowed) och scoring_default via POST/PATCH …/classes (tidigare bara läsprojektion). Nytt tenant-scopat läs-API GET /v1/competitions/system-catalog?discipline= projicerar katalogens byggstenar (Lagbildning · Kvalfaser · Slutspelsfaser + fas-enum-domäner) som DATA (SystemCatalogView/CatalogBlock), så systemkatalog-vyn (spelsystem.astro) renderar från riktig data i stället för en hårdkodad frontend-lista (AS-2). openapi + genererad TS-klient i synk (make api-ts-client-check). Wizard-UI + katalogvy = t-2/t-3. Bevis mot riktig Postgres: competition_wizard_backend_contract_integration_test.go. Docs: specs/api/competition-system-catalog.md. | ✅ ee51ed1f.m-5 - F04.10.62 Shipped
Full 7-stegs "Skapa tävling"-wizard, wire:ad mot riktiga endpoints (delta #3, ee51ed1f.m-5.t-2) — admin/components/competition/CompetitionWizard.tsx utökad från 4 → 7 steg i mockup-ordning (tavling-ny.astro): Grunder · Klass & format · Spelsystem · Sanktionering · Anmälan · Domare & jury · Granska & publicera. Varje steg/fält är wire:at till ett endpoint som finns: POST /v1/competitions (utkast + Grunder-fält), POST …/classes (constraints m-3 + scoring_default m-2), GET /v1/competitions/presets (preset-väljaren fyller steg/fas-editorn — inga hårdkodade mall-namn), PUT …/classes/{cid}/system + POST …/format/preview (komponering + fas-medveten förhandsvisning, m-1/m-2), POST …/request-sanction (§I-statuskedja), PATCH /v1/competitions/{id} (anmälnings-konfig), GET /v1/officials + POST /v1/officials/assignments (D-OFF), GET /v1/org-nodes (arrangör), och steg 7 bygger sammanfattningen från läst API-data (GET /v1/competitions/{id} + GET …/system) — aldrig formulärminne. Additiv backend-lucka stängd (FR-24): PATCH /v1/competitions/{id} accepterar nu entry_fee_minor/entry_fee_currency/allow_waitlist (Money *_minor+ISO-4217, NFR-4) för anmälnings-konfig-persistens (bakåtkompat; sqlc-regenererad). Bevis: admin/__acceptance__/competition-wizard.acceptance.mjs grön (7 steg + fält + wiring + kontrakt), npm run build grön, api-ts-client-check i synk, competition_registration_config_integration_test.go mot riktig Postgres. Katalogvy + spårbarhetsmatris = t-3. Docs: specs/admin/views/competition-wizard.md.
✅ ee51ed1f.m-5 - F04.10.63 Shipped
Fristående systemkatalog-vy (riktig data) + konformitets-/spårbarhetsmatris (delta #3, ee51ed1f.m-5.t-3) — den fristående systemkatalog-vyn (admin/app/tavlingar/spelsystem/page.tsx, route /tavlingar/spelsystem, nåbar från steg 3 via system-catalog-link, mockup spelsystem.astro) renderar hierarki-illustrationen (Tävling ▸ Steg ▸ Fas), de tre byggstens-sektionerna Lagbildning · Kvalfaser · Slutspelsfaser och de namngivna mallarna (presets) — allt från riktiga endpoints (GET /v1/competitions/system-catalog för byggstenarna, GET /v1/competitions/presets för mallarna), inte en hårdkodad frontend-lista (FR-22/AC-13). Serie/liga-preseten visas markerad "via D-LEAGUE" och expanderar inte (A-1). Parsers (parseSystemCatalog/parsePresets/presetViaExternal) är rena + enhetstestade (admin/lib/__tests__/competition-catalog.test.ts). Levererar även konformitets-/spårbarhetsmatrisen (milestones/ee51ed1f.m-5/conformance-matrix.md) som mappar varje steg+fält i tavling-ny.astro och varje byggsten+preset i spelsystem.astro post-för-post → wizard-/katalog-element + endpoint/datakälla. Bevis: node admin/__acceptance__/system-catalog-view.acceptance.mjs grön (vy + byggstens-/preset-testID + riktig-data-wiring + matris), npm run build grön. Docs: specs/admin/views/system-catalog.md, specs/admin/views/competition-wizard.md.
✅ ee51ed1f.m-5 - F04.10.59 Shipped
Strukturerade kategori-constraints + trupp > lag & reserver (D-COMP-SYS delta #4 + #6, ee51ed1f.m-3) — competition_class bär strukturerade behörighets-constraints min_age/max_age/gender_rule (open\
men_only|women_only|mixed_required, §F/§K, mockup tavling-ny.astro steg 2) + trupp/reserv-modellen squad_size/reserves_allowed (§A/§G: EM-triplette = 4-mannatrupp ställer upp 3 + 1 reserv), och registration_player bär player_role (fielded|reserve). t-1 [DONE]: additiv migration (00064) + rena DB-fria behörighetsfunktioner (CheckCategoryEligibility ålder+kön per spelare, CheckMixedRequirement mixed-kvot per lag), deterministiska/ackumulerande, fail-open på saknad fakta. t-2 [DONE]: enforcering i anmälningsgrinden mot D-MEMBER (player_profile.date_of_birth/gender — enda källan), deny-by-default 422 category_ineligible (reasons[] ∈ {age_below_min, age_above_max, gender_not_allowed, mixed_requirement_unmet}) skild från 409-licensfamiljen; trupp/reserv-validering + player_role-persistens (422 team_composition_invalid); constraints + trupproller exponerade på läs-API + OpenAPI (RegistrationCreateInput/CompetitionClassConstraints) + TS-klient i synk — bevisat mot riktig Postgres. Kategori-preset-select + wizard-yta = delta #3. Docs: docs/domain/competition/category-constraints-squad.md, specs/api/endpoints/registrations-v1.md. | ✅ ee51ed1f.m-3 - F04.10.64 Shipped
Anpassade tävlingar — para-klasser och adaptiva regler som KONFIG-DATA (D-PARA cc3657f5.m-4.t-1) — en arrangör deklarerar tävlingen som anpassad i ett regelkort (para_competition_ruleset, migration 00213, 1:1 per tävling som DB-invariant): öppna para-kategorier ur FIPJP-katalogen, entry_model (para_only\
mixed_para_open), throwing_circle (standard|extended_60cm|ramp_allowed), assistant_allowed och accessibility_requirement (wheelchair_full|partial|none) — allt ur DEKLARERADE vokabulärer i kod, aldrig fri text, aldrig en tenant-redigerbar tabell. adapted behåller EN definition — klassernas is_adapted (regelkortet omdefinierar den aldrig; ett kort kan inte skapas utan levande anpassad klass ⇒ 422 para_no_adapted_class). D-COMP:s allowed_para_categories får sin saknade katalogvalidering i BÅDA klass-skrivvägarna (422 para_category_unknown / para_category_not_open med fältpekare — delmängdsinvarianten, så två listor aldrig blir två sanningar), och anmälningsgrinden får EN snäv blockerare i den befintliga sömmen (409 para_classification_required, aktiv endast vid para_only ∧ icke-tom klasslista ∧ utan OPEN_NEC; utan regelkort är den INERT). Publikt: två additiva facetter (para_category, accessibility) + tre kortfält (adapted, para_categories, accessibility_requirement) + detaljens adapted_rules på husets BEFINTLIGA oautentiserade discovery — serverfiltrering, ingen ny rutt, oförändrad adapted/level/discipline-semantik. Arenans egen tillgänglighetsprofil förblir D-VENUE:s: kravet är arrangörens, ingen automatisk uppfyllnadsdom fälls. Lokal fixtur: go run . seed-para (två GLOBAL-publicerade demo-tävlingar i SWE genom D-COMP:s EGNA sömmar). Adminfliken *Anpassade tävlingar* + kalenderfiltret = t-2. Docs: specs/api/endpoints/para-competition-rulesets.md, specs/api/endpoints/public-competitions-adapted.md, docs/domain/para-petanque.md. | ✅ cc3657f5.m-4
Qualification Pathways
F04.11Multi-stage qualification from local to international level.
How it works- F04.11.01 Shipped
Qualification pathway definition (e.g., club > district > regional > national > world) — PL-F0411a
✅ greenfield-byggd i 7cd8cecf.m-4 (nivåerna kommer ur tenantens egna org_node_levels) - F04.11.02 Shipped
Qualification spots allocation (how many advance from each stage) — PL-F0411a
✅ greenfield-byggd i 7cd8cecf.m-4 (places_forward per bunden tävlingsklass) - F04.11.03 Shipped
Automatic qualification tracking (player qualifies at district → registered for regional) — PL-F0411a
✅ greenfield-byggd i 7cd8cecf.m-4 — med BOKFÖRD avgränsning: auto_entry_on_advancement flyttar spelaren fram i STEGEN och skriver INGEN tävlingsanmälan (anmälan ägs av D-COMP med avgift, godkännandegrind och klubbbundenhet) - F04.11.04 Shipped
Wild card / invitation slots — PL-F0411a
✅ greenfield-byggd i 7cd8cecf.m-4 (den enda LAGRADE kvalificeringen; taket prövas under radlås) - F04.11.05 Shipped
Qualification via ranking (top N nationally qualify for continental) — PL-F0411b
✅ greenfield-byggd i 7cd8cecf.m-4 (topp N ur en LÅST kval-snapshot, låset prövat vid varje härledning) - F04.11.06 Shipped
Qualification history per player (which championships qualified for) — PL-F0411b
✅ greenfield-byggd i 7cd8cecf.m-5 — spelarhistoriken (GET /v1/tenant/selection/history/players/{userId}): hennes uttagningar + hennes kvalificeringar med EVIDENS, härledd vid läsning (ingen ny tabell, kval-halvan är m-4:s EGEN spårningssöm skopad till en människa). I 7cd8cecf.m-4 var raden ännu inte greenfield-byggd — m-4 spårade EN kvalstege i taget (m-4:s non-goal 8) och historiken över säsonger/stegar var uttryckligen senare arbete; det arbetet är m-5. ORDET är UTTAGNINGAR, aldrig landskamper: huset har inget landskampsregister, så selection_count räknar uttagningar registrerade i Petanque Life - F04.11.07 Planned
Cross-reference: national qualification linked to continental/world entry — PL-F0411b
⛔ F04.11.07 är fortfarande inte greenfield-byggd — varken i 7cd8cecf.m-4 eller i 7cd8cecf.m-5, och det är ett UTTRYCKLIGT beslut: m-5 PRODUCERAR squad-artefakten (petanque-life-v1) men skickar den aldrig — inlämningen, kvittensen och M2M-mottagningen är D-PUBAPI (m-5:s bindande non-goal 1). Utan ett kvitto från CEP/FIPJP finns ingen byggd källa att korsreferera mot; mockupens fotnot renderas INTE och fabriceras inte. Uppdaterat (D-PUBAPI a95566cc.m-6, 2026-09): KVITTOT FINNS NU. Truppinlämningen till CEP/FIPJP är byggd (/v1/squad-submissions, kvittensen med sina MÄTTA kontroller, accepten på F1-6:s generiska ärendeyta — squad-submissions.md), så det finns en mottagen och beslutad inlämning att korsreferera MOT. Själva korsreferensen — att koppla den nationella kvalificeringen till den kontinentala/globala anmälan — är fortsatt D-NATIONAL/D-COMP:s och är INTE byggd här; m-6 äger transporten, inte kvalvägens koppling
International Competitions
F04.12Features specific to international events (continental, world championships, World Games).
How it works- F04.12.01 Shipped
National delegation management (federation submits team roster)
✅ PL-F0412a ✅ PL-F0412a - F04.12.02 Shipped
Delegation size limits per event type
✅ PL-F0412a ✅ PL-F0412a - F04.12.03 Shipped
Nation vs nation format (e.g., triplette championship = 3 triplettes per nation)
✅ PL-F0412a ✅ PL-F0412a - F04.12.04 Shipped
Flag/anthem management per nation (for ceremonies)
✅ PL-F0412a ✅ PL-F0412a - F04.12.05 Shipped
Accreditation system (player, official, media, VIP badges)
✅ PL-F0412a ✅ PL-F0412a - F04.12.06 Shipped
Multi-language announcements at event
✅ PL-F0412a ✅ PL-F0412a - F04.12.07 Shipped
Time zone management (schedule in local time, display in viewer's time)
✅ PL-F0412b ✅ PL-F0412b - F04.12.08 Shipped
International ranking points (FIPJP points from world/continental events)
✅ PL-F0412b ✅ PL-F0412b - F04.12.09 Shipped
Travel and accommodation coordination per delegation
✅ PL-F0412b ✅ PL-F0412b - F04.12.10 Shipped
International competition results fed back to national rankings
✅ PL-F0412b ✅ PL-F0412b - F04.12.11 Shipped
Historical records per international competition (all-time medal table)
✅ PL-F0412b ✅ PL-F0412b - F04.12.12 Shipped
International competition bidding (federation applies to host)
✅ PL-F0412b ✅ PL-F0412b
Casual Games
F04.13Non-tournament games between players — social play, practice matches, club evenings.
How it works- F04.13.01 Shipped
Quick game creation (pick players, format, start playing) — PL-F0413a
✅ PL-F0413a - F04.13.02 Shipped
Casual game score tracking (same scoring as official matches) — PL-F0413a
✅ PL-F0413a - F04.13.03 Shipped
Mène tracking for casual games (optional) — PL-F0413a
✅ PL-F0413a - F04.13.04 Shipped
Casual game history per player — PL-F0413a
✅ PL-F0413a - F04.13.05 Shipped
Casual game ELO impact (configurable — can be weighted lower than official) — PL-F0413a
✅ PL-F0413a - F04.13.06 Shipped
Location tagging (where was the game played — venue or GPS)
✅ PL-F0413b ✅ PL-F0413b - F04.13.07 Shipped
Invite players to casual game (in-app)
✅ PL-F0413b ✅ PL-F0413b - F04.13.08 Shipped
"Looking for game" status (player signals availability at a venue)
✅ PL-F0413b ✅ PL-F0413b - F04.13.09 Shipped
Club evening management (organized casual play sessions)
✅ PL-F0413b ✅ PL-F0413b - F04.13.10 Shipped
Random team generator (shuffle players into balanced teams by ELO)
✅ PL-F0413b ✅ PL-F0413b - F04.13.11 Shipped
Casual game statistics (separate from official stats)
✅ PL-F0413c ✅ PL-F0413c - F04.13.12 Shipped
Social sharing of casual game results
✅ PL-F0413c ✅ PL-F0413c - F04.13.13 Shipped
Photo/video from casual games
✅ PL-F0413c ✅ PL-F0413c
Player of the Match & Awards
F04.14Inspired by football, tennis, and other sports — in-match and post-match recognition.
How it works- F04.14.01 Shipped
Player of the Match voting (spectators, officials, or automatic from stats)
✅ greenfield f01df0d0.m-2 — matchinstansen skapas EXPLICIT (POST /v1/award-instances, matchslutet skapar den aldrig), röstningen öppnas med sin FRYSTA regel, valsedeln materialiseras ur matchens egna anmälningar och rösten läggs antingen inloggad (POST /v1/me/award-ballots/{round_id}:vote, väljarklassen avgörs av SERVERN ur rullorna) eller anonymt genom den publika vägen med en HttpOnly förstapartskaka. Den statistik-baserade grenen är f01df0d0.m-1:s - F04.14.02 Shipped
Player of the Tournament award
✅ greenfield f01df0d0.m-1 — katalograd med decision_method=panel; instansen föds open av publiceringen och avgörs med ett MANUELLT POST /v1/award-instances/{id}:decide med obligatorisk motivering — och sedan f01df0d0.m-2 kan samma pris i stället avgöras genom en RIKTIG panelomröstning med kvorum, jävsdeklaration och en attribuerbar juryröst - F04.14.03 Shipped
Best Shooter award (highest tir accuracy in competition)
✅ greenfield f01df0d0.m-1 — metriken tir_hit_pct, RÄKNAD ur throw-rader i klassen i publiceringens EGEN transaktion (hit_bps i HELTALS-baspunkter med deklarerad half-up). Utan kastdata blir instansen not_measurable med skälet no_throw_data — aldrig en vinnare på tunn luft - F04.14.04 Shipped
Best Pointer award (highest pointing accuracy)
✅ greenfield f01df0d0.m-1 — metriken point_hit_pct, samma källnivå och samma ärliga nej - F04.14.05 Shipped
Most Carreaux award (most perfect hits)
✅ greenfield f01df0d0.m-1 — metriken carreau_count. Noll kröns aldrig: en klass där ingen slog en carreau ger no_qualifying_result, inte en vinnare med värdet 0 - F04.14.06 Shipped
Comeback of the tournament (biggest deficit overcome)
✅ greenfield f01df0d0.m-1 — metriken biggest_turnaround ur mene-nivån (tiebreak: FÄRRE spelade mèner vinner). Mène-för-mène är VALFRI i huset ⇒ utan den no_mene_data - F04.14.07 Shipped
Fair play award (sportsmanship, nominated by umpires)
✅ greenfield f01df0d0.m-1 — katalograd med decision_method=umpire_nomination; instansen föds open och avgörs manuellt med motivering. Vinnaren kan vara en PERSON, en ANMÄLAN eller en ORGANISATION (composite-FK mot org_nodes (tenant_id, id)) - F04.14.08 Shipped
Season awards: Player of the Year, Young Player, Newcomer, Coach, Club, Umpire
✅ greenfield f01df0d0.m-1 — som KATALOGDATA (level=season, season_year = kalenderår). Sedan f01df0d0.m-2 får säsongspriset en instans EXPLICIT (utan aktivering, utan tävling, med en deterministisk scope_ref av (förbund, pris, år)) och avgörs genom nominering + röstning. Ingen publicering utlöser den — det är fortfarande en människas handling - F04.14.09 Shipped
Award voting system (federation configurable: public vote, expert panel, stats-based)
✅ greenfield f01df0d0.m-1 + f01df0d0.m-2 — alla tre grenarna finns: den STATISTIK-baserade (m-1), den PUBLIKA/rulle-baserade och den VIKTADE rösten samt EXPERTPANELEN med kvorum (m-2). Konfigurationen är förbundets DATA i criteria med en SLUTEN nyckelmängd per metod (väljarkår · viktning i heltals-bps som måste summera till 10000 · fönster · tröskel · kvorum · mellanställningens synlighet · publiceringspolicy), och den ärver katalogens DUBBLA frysning. Räkningen är heltal hela vägen med deklarerad half-up, och ett delat högsta värde blir tie_unresolved — huset gör ingen automatisk tiebreak i en röstning - F04.14.10 Shipped
Awards history and hall of fame integration
✅ greenfield f01df0d0.m-1 + f01df0d0.m-5 — historiken är rader sedan m-1 (award_instance + award_winner med decided_at/published_at och ett FRYST kriterium per instans, så ett avgjort pris för alltid bär den regel det dömdes efter), och hall of fame plus publiceringen till D-CMS-rekordväggen levererades i m-5. Ett inval är ett BESLUT: förvaltaren föreslår ur ett publicerat pris, ett publicerat rekord eller ett styrelseprotokoll, och en ANNAN människa avgör i F1-6 (hall_of_fame_induction; självbeslut ⇒ 403). Statusorden har EXAKT en skrivare var (hookparet respektive :withdraw), och EN levande invald per källa är ett partiellt unikt index — aldrig ett if. Namnet lagras inte för en person: det löses upp vid läsning bakom husets ENDA avtäckningsregel (awards.DiscloseHallOfFameHolder), ett lag med en dold medlem är odisclosed som helhet, och en SEVRAD person är odisclosed — en anonymiserad människa står aldrig som *»Raderad spelare«* på en hederssida. Väggen är en vanlig cms_page med blocket record_wall, skriven genom D-CMS:s EGNA sömmar (ingen rå DML mot cms_*), så redaktören äger sidan efteråt och record_scope_level=club ger en klubbvägg utan en ny rutt - F04.14.11 Shipped
Record database with automatic record detection
✅ greenfield f01df0d0.m-3 — rekordkategorin är förbundets DATA (metrik · skop · riktning · trösklar) och posten en MÄTNING ur D-RANK:s performance_result/elo_rating och D-COMP:s publicerade resultat. Det finns medvetet ingen POST /v1/records: detekteringssömmen är enda producenten, med två anropare (nattsvepet award_record_detect_tick och människans :detect), och en människa granskar/publicerar/avslår. Idempotensen är faktum-nyckelns DB-invariant — som därmed också är »nagga aldrig igen«-garantin: en avslagen post kan aldrig resas på nytt. Lika värde superseder ingenting (delat rekord); faller källan bort auto-avslås en candidate medan en granskad/publicerad post STÄMPLAS och larmar (ett svep kör aldrig över en människa). Rekordboken är en LÄSNING ur template_of-kedjan — ingen tabell, ingen namnmatchning — och publiksiffran redovisas i coverage[] MED ägare, aldrig som ett tal - F04.14.12 Shipped
Milestones and badges from career statistics
✅ greenfield f01df0d0.m-4 — milstolpeprogrammet är förbundets DATA (trösklar per mätetal ur en SLUTEN, kod-deklarerad katalog bunden till D-RANK:s rollup; mockupens 100 · 250 · 500 · 1000 står ingenstans i koden) och badgen ett FAKTUM om en karriär. Det finns medvetet ingen POST /v1/player-badges, ingen DELETE och inget :revoke — mätsömmen är enda producenten, med två anropare (nattsvepet award_milestone_detect_tick och människans :detect), och värdet LÄSES ur ranking.PerformanceRollup: D-AWARDS räknar aldrig en karriär själv. »En badge EN gång« är DB-invarianten unique (tenant_id, user_id, milestone_definition_id, threshold); en sänkt tröskel delar inte ut om (below_awarded_threshold) och en höjd tar aldrig tillbaka (threshold_retired, HÄRLETT vid läsning). Beskedet är en hälsning per spelare och körning (högsta tröskeln bär den, resten bundled) med MÄTT utfall på raden, och självläkningen är en EGEN notisplikt vars urval står i frågan. Spelaren ser alltid sina egna badges (GET /v1/me/badges, självguardad och cross-tenant); publiken bara genom TRE grindar i frågan (förbundets share_in_app, spelarens profile_public och husets inneslutning), där varje nej är BYTE-IDENTISKT tomt — ytan är varken ett existens- eller ett samtyckesorakel. ⊘ federations-skopad karriär (talen är cross-tenant; en tenant-skopad rollup-variant är ett tillägg i D-RANK, inte här)
Head-to-Head & Comparison Tools
F04.15Inspired by tennis, chess, and combat sports.
How it works- F04.15.01 Shipped
Head-to-head comparison (any two players — record, stats, ELO delta)
✅ PL-F0415a ✅ PL-F0415a - F04.15.02 Shipped
Team vs team comparison (two clubs, two nations — all-time record)
✅ PL-F0415a ✅ PL-F0415a - F04.15.03 Shipped
Player comparison tool (side-by-side: stats, ELO, ranking, strengths)
✅ PL-F0415a ✅ PL-F0415a - F04.15.04 Shipped
Pre-match prediction (ELO-based win probability)
✅ PL-F0415a ✅ PL-F0415a - F04.15.05 Shipped
Form guide (last 5/10/20 results, W/L streak)
✅ PL-F0415b ✅ PL-F0415b - F04.15.06 Shipped
Surface/terrain performance comparison (indoor vs outdoor, gravel vs sand)
✅ PL-F0415b ✅ PL-F0415b - F04.15.07 Shipped
Rivalry tracking (frequent opponents, notable matchups)
✅ PL-F0415b ✅ PL-F0415b
Records & Milestones
F04.16Inspired by cricket, athletics, and tennis — tracking all-time records.
How it works- F04.16.01 Shipped
All-time records database (per federation, per competition, per club)
✅ PL-F0416a - F04.16.02 Shipped
Record categories: most titles, longest win streak, highest ELO, most 13-0 wins
✅ PL-F0416a - F04.16.03 Shipped
Automatic record detection (system alerts when a record is broken)
✅ PL-F0416a - F04.16.04 Shipped
Milestone alerts (100th match, 500th win, 10th season, etc.)
✅ PL-F0416a - F04.16.05 Shipped
Career milestone badges
✅ PL-F0416a - F04.16.06 Shipped
First-ever tracking (first player from a nation to reach X, first 13-0 in a final, etc.)
✅ PL-F0416b - F04.16.07 Shipped
Youngest/oldest records (youngest champion, oldest active player, etc.)
✅ PL-F0416b - F04.16.08 Shipped
Record book per competition (every edition's winners, stats, attendance)
✅ PL-F0416b - F04.16.09 Shipped
Nation/club record walls (displayed on CMS site)
✅ PL-F0416b
Team Partnerships
F04.17Track stable partnerships over time — who plays well together.
How it works- F04.17.01 Shipped
Partnership registry (regular doublette/triplette combinations)
✅ PL-F0417a ✅ PL-F0417a - F04.17.02 Shipped
Partnership win/loss record
✅ PL-F0417a ✅ PL-F0417a - F04.17.03 Shipped
Partnership ELO (combined team rating)
✅ PL-F0417a ✅ PL-F0417a - F04.17.04 Shipped
Partnership history (all matches played together)
✅ PL-F0417a ✅ PL-F0417a - F04.17.05 Shipped
"Find a partner" matching (by ELO range, location, availability, playing style)
✅ PL-F0417b ✅ PL-F0417b - F04.17.06 Shipped
Partnership chemistry score (win rate together vs. individually)
✅ PL-F0417b ✅ PL-F0417b - F04.17.07 Shipped
Partnership profile page (public)
✅ PL-F0417b ✅ PL-F0417b
Per-National Competition Structures
F04.18Per-nation championship pathways, league hierarchies, discipline variants, age-class configurations, and official calendars.
How it works- F04.18.01 Shipped
France - Championnat de France national → ligue → comité → club
✅ PL-F0418a ✅ PL-F0418a - F04.18.02 Shipped
France - 4 championship categories (Tête-à-tête, Doublette, Triplette, Mixte)
✅ PL-F0418a ✅ PL-F0418a - F04.18.03 Shipped
France - Jeu provençal as separate discipline
✅ PL-F0418a ✅ PL-F0418a - F04.18.04 Shipped
Sweden - SM (Svenska Mästerskapen)
✅ PL-F0418a ✅ PL-F0418a - F04.18.05 Shipped
Sweden - Elitserien / Division 1 / Division 2
✅ PL-F0418a ✅ PL-F0418a - F04.18.06 Shipped
Germany - DPV Bundesliga + Landesligan
✅ PL-F0418a ✅ PL-F0418a - F04.18.07 Shipped
Norway - NM med kvalspel (flat hierarchy, federation-sanctioned)
✅ PL-F0418b ✅ PL-F0418b - F04.18.08 Shipped
Spain - Campeonato de España (autonomous federation → national, Swiss system)
✅ PL-F0418b ✅ PL-F0418b - F04.18.09 Shipped
FIPJP - VM-kvalifikationer per nation (national → continental → world)
✅ PL-F0418b ✅ PL-F0418b - F04.18.10 Shipped
CEP - EM-kvalifikationer per nation (national → European Championship)
✅ PL-F0418b ✅ PL-F0418b - F04.18.11 Shipped
Per-tenant tävlingskategorier (åldersklass) — Norway + Spain age classes
✅ PL-F0418b ✅ PL-F0418b - F04.18.12 Shipped
Per-tenant officiell tävlingskalender — Norway + Spain calendars
✅ PL-F0418b ✅ PL-F0418b
Mêlée och avancerade tävlingsformat
F04.19Multi-round mêlée tournaments, score-based pairing, 1v1 mêlée, cup formats, round robin, Swiss ELO, single/double elimination, poules→knockout, and Concours A/B/C.
How it works- F04.19.01 Shipped
Mêlée draw algorithm (slumpad lagdragning)
✅ PL-F0419a ✅ PL-F0419a - F04.19.02 Shipped
Supermêlée med score-based pairing
✅ PL-F0419a ✅ PL-F0419a - F04.19.03 Shipped
Tête-à-tête mêlée variation
✅ PL-F0419a ✅ PL-F0419a - F04.19.04 Shipped
Coupe de France-format
✅ PL-F0419a ✅ PL-F0419a - F04.19.05 Shipped
National Cup-format per nation
✅ PL-F0419a ✅ PL-F0419a - F04.19.06 Shipped
Round robin (alla mot alla)
✅ PL-F0419a ✅ PL-F0419a - F04.19.07 Shipped
Schweizer system med ELO-baserad pairing
✅ PL-F0419b ✅ PL-F0419b - F04.19.08 Shipped
Single elimination bracket
✅ PL-F0419b ✅ PL-F0419b - F04.19.09 Shipped
Double elimination bracket
✅ PL-F0419b ✅ PL-F0419b - F04.19.10 Shipped
Pool play → knockout-format
✅ PL-F0419b ✅ PL-F0419b - F04.19.11 Shipped
Concours A/B/C med trösteklass
✅ PL-F0419b ✅ PL-F0419b
Official Rankings per Nation
F04.20Official ranking preset definitions and provisioning for 5 nations/bodies. Static preset configurations with one-click provisioning to RankingConfig documents. Per-tenant formula config, cross-tenant ELO, ranking trends, qualification snapshots, and dispute workflow.
How it works- F04.20.01 Shipped
France — Classement national + ligues + comités (24 mo, linear decay)
✅ PL-F0420a ✅ PL-F0420a - F04.20.02 Shipped
Sverige — SM-ranking (12 mo, no decay) + nationell ELO
✅ PL-F0420a ✅ PL-F0420a - F04.20.03 Shipped
Deutschland — DPV-Rangliste (36 mo, weighted_years 3/2/1, A-D multipliers)
✅ PL-F0420a ✅ PL-F0420a - F04.20.04 Shipped
FIPJP — World ranking (cross-tenant, world scope)
✅ PL-F0420a ✅ PL-F0420a - F04.20.05 Shipped
CEP — Continental ranking (cross-tenant, continental scope)
✅ PL-F0420a ✅ PL-F0420a - F04.20.06 Shipped
Per-tenant ranking formula (point model with bonus rules, caps, thresholds)
✅ PL-F0420b ✅ PL-F0420b - F04.20.07 Shipped
Cross-tenant ELO for casual matches (global singleton config, margin modifier)
✅ PL-F0420b ✅ PL-F0420b - F04.20.08 Shipped
Ranking history and trends (direction, moving average, velocity)
✅ PL-F0420b ✅ PL-F0420b - F04.20.09 Shipped
Ranking snapshot at qualification deadline (locked freeze for team selection)
✅ PL-F0420b ✅ PL-F0420b - F04.20.10 Shipped
Dispute ranking points (formal process with review/resolve workflow)
✅ PL-F0420b ✅ PL-F0420b
Live Scoring & Official Result Entry
F04.21Real-time scoring infrastructure: mobile-first live entry with offline support, official scorekeeper role with digital signing, real-time leaderboard, push notifications, score corrections with audit, score protests, walkover handling, and round timing.
How it works- F04.21.01 Shipped
Live score entry on mobile with offline support
✅ PL-F0421a ✅ PL-F0421a - F04.21.02 Shipped
Official scorekeeper role with digital signing
✅ PL-F0421a ✅ PL-F0421a - F04.21.03 Shipped
Real-time leaderboard updates (SSE)
✅ PL-F0421a ✅ PL-F0421a - F04.21.04 Shipped
Push notifications for match events (subscriptions)
✅ PL-F0421a ✅ PL-F0421a - F04.21.05 Shipped
Score correction flow with audit
✅ PL-F0421b ✅ PL-F0421b - F04.21.06 Shipped
Score protest from team captain
✅ PL-F0421b ✅ PL-F0421b - F04.21.07 Shipped
Walkover and WO handling
✅ PL-F0421b ✅ PL-F0421b - F04.21.08 Shipped
Round timing per round (45 min default)
✅ PL-F0421b ✅ PL-F0421b - F04.21.20 Shipped
VolunteerScoreEntry — parallel light-weight scoring surface optimised for volunteers, big-button UI, idempotent on (device_id, client_ts, end_number), soft-validation with stable warning codes (zero_score_end / both_teams_scored / score_above_13 / missing_end_<n>) — PL-T222
✅ PL-T222 ✅ PL-T222 - F04.21.21 Shipped
Volunteer offline cache — exponential-backoff retry-loop, server-idempotency on tuple guarantees no duplicates, sync-status badge (synced/pending/error) — PL-T222
✅ PL-T222 ✅ PL-T222 - F04.21.22 Shipped
Dispute flagging — measure / dead_end / timeout / rule_question / other, sets is_dispute=true + needs_review, dispatchar scoring.dispute_raised till court-marshal via F09.02 — PL-T222
✅ PL-T222 ✅ PL-T222 - F04.21.23 Shipped
BulkScoreUpload — fixed-column CSV (competition_match_ref,end_number,team_a_points,team_b_points,scorer_note), parse-job med per-row error/warning, atomic-per-match apply, status uploaded/parsing/validated/applied/partially_applied/failed — PL-T222
✅ PL-T222 ✅ PL-T222 - F04.21.30 Shipped
Enhetsregistret scoreboard_device (migration 00161): den fysiska tavlan ägd av PL:s tenant-noll, bunden till hyresgästens match med mjuka referenser, med serial_no/kit_instance_id mot D-EQUIP:s brädregister — 1ee83e2c.m-1
✅ 1ee83e2c.m-1 (t-1) - F04.21.31 Shipped
Signaturverifierad uplink-ingest POST /v1/scoreboards/ingest (LNS-webhook, X-PL-Webhook-Signature, ±5 min färskhetsfönster, fail-closed utan en enda DB-skrivning) — 1ee83e2c.m-1
✅ 1ee83e2c.m-1 (t-1) - F04.21.32 Shipped
Uplink → score_entry med source='board' och device_id: delta mot competition.DeriveScore, ökning ⇒ ny mène, minskning med 1 ⇒ husets undo-rad (is_undo/replaces_entry_id), aldrig negativ poäng eller DELETE — 1ee83e2c.m-1
✅ 1ee83e2c.m-1 (t-1) - F04.21.33 Shipped
Validering mot den resolvade poänggränsen (ResolveScoring, aldrig hårdkodad 13:a) + stabila avvisningskoder (score_above_max, score_decrement_too_large, invalid_score_delta, scoreboard_match_closed, scoreboard_match_mismatch) — 1ee83e2c.m-1
✅ 1ee83e2c.m-1 (t-1) - F04.21.34 Shipped
Replay-skydd på frame counter inom sessions-epok + partiellt unikt index på (device_id, session_epoch, f_cnt) where outcome='applied' ⇒ exakt-en-gång även vid at-least-once-leverans; varje utfall spåras append-only i scoreboard_uplink_event — 1ee83e2c.m-1
✅ 1ee83e2c.m-1 (t-1) - F04.21.35 Shipped
match_final → D-COMP:s egen FSM (Transition + CompleteMatch) med vinnare ur DeriveOutcome; tavlan sätter aldrig confirmed_by_* — det fysiska långtrycket är en inmatning, inte resultatsignering — 1ee83e2c.m-1
✅ 1ee83e2c.m-1 (t-1) - F04.21.36 Shipped
Flott-/bindnings-API GET /v1/scoreboards, GET\
PATCH /v1/scoreboards/{id}, POST /v1/scoreboards, POST /v1/scoreboards/{id}/assign-match — ETag/If-Match, cursor-paginering, server-injicerat skop (hyresgästen ser bara enheter med aktiv uthyrning), nyckelfälten projiceras aldrig — 1ee83e2c.m-1 | ✅ 1ee83e2c.m-1 (t-2) - F04.21.37 Shipped
Två mandat, inte ett (scoreboard:fleet_admin i den smala systemmallen platform_scoreboard_admin; scoreboard:operate på klubb-/distrikts-/förbundsadmin) + fixturen seed-scoreboard-hw som konsumerar D-EQUIP:s custody-brädor — 1ee83e2c.m-1
✅ 1ee83e2c.m-1 (t-2) - F04.21.38 Shipped
Enhetstelemetri som riktiga rader (migration 00162): scoreboard_device_health (1:1 per enhet — batteri, tavlans egen RSSI, gateway-RSSI/SNR ur rxInfo, senast sedd, härledd presence) + tidsserien scoreboard_health_sample, upsertad i ingestens enda transaktion. Ingen temperaturserie: v1-payloaden mäter ingen temperatur, over_temp är en flagga — 1ee83e2c.m-2
✅ 1ee83e2c.m-2 (t-1) - F04.21.39 Shipped
Larm-inboxen scoreboard_alert + GET /v1/scoreboards/alerts(/{id}, /acknowledge, /resolve): fem typer, warning/critical, en öppen rad per (enhet, typ) via partiellt unikt index, kvittens ≠ lösning (kvittensen är idempotent och fryser eskaleringen), auto-lösning per typ — tamper löses endast manuellt — 1ee83e2c.m-2
✅ 1ee83e2c.m-2 (t-1) - F04.21.40 Shipped
Trösklarna är konfig-data, aldrig konstanter — scoreboard_telemetry_config med treskikts-upplösning enhet → kit → plattform (null = ärv) och GET/PUT /v1/scoreboards/telemetry-config*; en ändring får effekt på nästa uplink utan omstart — 1ee83e2c.m-2
✅ 1ee83e2c.m-2 (t-1) - F04.21.41 Shipped
Downlink-porten och kön (LNSDownlink + register + deterministisk fake + ChirpStack-adapter bakom env): scoreboard_command med den ärliga statusmaskinen queued → sent → acked \
expired | failed, där sent betyder LNS:en accepterade enqueuen, aldrig levererad — 1ee83e2c.m-2 | ✅ 1ee83e2c.m-2 (t-2) - F04.21.42 Shipped
Tamper-armering POST /v1/scoreboards/{id}/tamper-arm\
tamper-disarm (202 med kommandoraden, If-Match, konvergent på partiellt unikt index) + kvittensvägen POST /v1/scoreboards/ingest?event=ack på samma signatur-fail-closed: enhetens tamper_armed speglas först vid tavlans egen kvittens — 1ee83e2c.m-2 | ✅ 1ee83e2c.m-2 (t-2) - F04.21.43 Shipped
assign-match köar set_match (0x01) och auto-arm/disarm ur D-EQUIP:s egna emitterade scoreboard_inventory_event-rader (received ⇒ arm, returning ⇒ disarm) — läsning, aldrig skrivning i D-EQUIP:s revir; dedup-cursorn lever på m-2:s egen kommandorad — 1ee83e2c.m-2
✅ 1ee83e2c.m-2 (t-2) - F04.21.44 Shipped
Hälsosvepet api run-job scoreboard_health_sweep med fyra plikter (närvaro-larm stale/lost, auto-arm/disarm-avstämning, kommando-TTL + omförsök, retention på tidsserien), now injicerat, batch-takat och idempotent — 1ee83e2c.m-2
✅ 1ee83e2c.m-2 (t-1/t-2)
External Event Proxying
F04.22Cross-tenant event display: subscribe to GLOBAL-published competitions from other tenants, cache metadata locally, sync every 15 min, render in CMS upcoming-events widget with source badge and override support.
How it works- F04.22.01 Shipped
ExternalEventProxy model with sync lifecycle (OK/STALE/FAILED/SOURCE_DELETED)
✅ PL-T008 ✅ PL-T008 - F04.22.02 Shipped
Admin subscribe/unsubscribe to global competitions
✅ PL-T008 ✅ PL-T008 - F04.22.03 Shipped
Local overrides (title, translation, note) per proxy
✅ PL-T008 ✅ PL-T008 - F04.22.04 Shipped
Background sync job (15 min, batch 50, exponential backoff)
✅ PL-T008 ✅ PL-T008 - F04.22.05 Shipped
Public upcoming-events endpoint (union of own + proxied)
✅ PL-T008 ✅ PL-T008 - F04.22.06 Shipped
CMS widget renders proxy events with source badge and link
✅ PL-T008 ✅ PL-T008 - F04.22.07 Shipped
Admin UI with status colors, search, subscribe, resync
✅ PL-T008 ✅ PL-T008 - F04.22.08 Shipped
Manual resync with rate limiting (1/min per proxy)
✅ PL-T008 ✅ PL-T008
Para-pétanque Classification & Adapted Competition
F04.23FIPJP-aligned para-pétanque classification system: per-player
- F04.23.01 Shipped
ParaClassification model with FIPJP categories (W1/W2/W3/standing/visual/intellectual/open), status, validity window
✅ PL-T220 ✅ PL-T220 - F04.23.02 Shipped
ClassificationPanel with 3–5 members and required role coverage (medical+coach+admin)
✅ PL-T220 ✅ PL-T220 - F04.23.03 Shipped
ClassificationDecision with quorum, panel votes, reasoning, audit
✅ PL-T220 ✅ PL-T220 - F04.23.04 Shipped
Cross-tenant verify endpoint mirroring license-verify (FIPJP-recognised panels only)
✅ PL-T220 ✅ PL-T220 - F04.23.05 Shipped
Public adapted-competition discovery (/public/competitions?adapted=true) with category + accessibility filters
✅ PL-T220 ✅ PL-T220 - F04.23.06 Shipped
Daily expiry cron + 30/14/7-day renewal-reminder notifications
✅ PL-T220 ✅ PL-T220
Seriespel / Leagues — Struktur & Admin-API (D-LEAGUE m-1)
F04.24Liga-strukturfundament (greenfield ovanpå den platta tävlingskärnan): säsong →
- F04.24.01 Shipped
Datalager: league_season/division/division_group/promotion_rule (migration 00078 + sqlc + store), tenant-scopat, optimistiskt låst, soft delete
✅ - F04.24.02 Shipped
Admin-CRUD-API /v1/league/* för säsong/division/grupp/upp-ned-regel (ETag/If-Match, audit, capability competitions:write)
✅ - F04.24.03 Shipped
Pyramid-läsyta GET /v1/league/seasons/{id}/pyramid per (säsong, player_class_code) — nivåer topp→botten + parallella grupper + admin per tier + upp/ned-länkar
✅ - F04.24.04 Shipped
Preset-applicering POST …/apply-preset — materialiserar seedad landstopologi som riktiga rader, idempotent per (säsong, preset_key)
✅ - F04.24.05 Shipped
seed-leagues-subkommando + SE/FR-presets som tenant_configs-DATA (migration 00079); config-är-data-guard
✅ - F04.24.06 Shipped
Genererad TS-klient operations/league.ts (drift-gate make api-ts-client-check) för admin-frontend (t-3)
✅ - F04.24.07 Shipped
Admin seriespel-yta (admin/app/tavlingar/seriespel) — strukturhalvan av mockupen: säsongsväljare (+ skapa säsong), klass-stege-väljare, divisionspyramid (namn/gruppantal/admin-badge/↕-text) och landspreset-lista med applicerings-flöde, allt mot riktiga /v1/league-endpoints (ingen hårdkodad topologi). Tabell/upp-ned-legend = m-3 (utelämnad)
✅
Seriespel / Leagues — Encounter & sammansatt matchdag (D-LEAGUE m-2)
F04.25Komposit-matchdagen (§M axel 5 / §N gap #1): ett klubbmöte (`encounter`) aggregerar flera
- F04.25.01 Shipped
Datalager: encounter/encounter_scoring/encounter_format (migration 00080/00081 + sqlc + store) + nullbar competition_match.encounter_id/sub_match_ordinal (delmatch = kärn-match, draw_id nullbar per A-1); ren deterministisk utfalls-härledning (sub_match_wins/total_points, forfeit-semantik)
✅ - F04.25.02 Shipped
Encounter-API:t kontraktfryst additivt (10 operationer under /v1/league/*): möte-format läs/sätt (konfig-DATA, 422-validering mot kärnans formatfamiljer) · start-play (fyller m-1 A-1-sömmen, idempotent) · RR-spelschema (enkel/dubbel, bye, regenererings-lås schedule_locked) · mötes-läsyta med delmatcher + aggregat i ett anrop · möte-start (delmatch-materialisering per slot) · ombokning (app-validerad reason + deadline-spärr, mockupens "Postponed match") · möte-w.o. · minimal delmatch-uppställning (antal-mot-format via RequiredTeamSize + lagtillhörighet — m-4-kroken, 00082)
✅ - F04.25.03 Shipped
Automatiskt mötesutfall i samma transaktion: sista delmatchens confirm/forfeit fullbordar mötet (encounter.complete); jury-korrigering (protest) omhärleder aggregatet (encounter.rederive) — settle-sömmen är strikt no-op för icke-liga-matcher (kärnan oförändrad)
✅ - F04.25.04 Shipped
SE/FR-preset-utökning (data-only): encounter_format per klass-stege i presets/{se,fr}.json; apply-preset (fryst path) materialiserar formatet idempotent; topologi-guarden utökad med kompositions-fingeravtryck
✅ - F04.25.05 Shipped
Admin matchdags-sektion + ombokningskort (admin/app/tavlingar/seriespel) mot riktiga endpoints (aktuell mockup design/src/pages/admin/seriespel.astro): grupp/rond/möte-väljare ur pyramid + mötesschema, delmatch-tabell (nr · format · poänginput hemma/borta · status) med rapportering via kärnans /v1/matches/{id}/menes+/confirm, mötesutfall-läget läst ur serverns scoring-aggregat (aldrig lokalt summerat), starta-möte (If-Match), verkliga tomt-/laddnings-/fel-tillstånd, ombokningskort med frusna orsaks-values + svenska etiketter (412/422 som riktiga fel). m-3/m-4-sektionerna utelämnade (ej stubbar)
✅
Seriespel / Leagues — Ligatabell & poäng + publik tabellvy (D-LEAGUE m-3)
F04.26Facit-lagret (§N gap #8 / §K / §E): varje spelande grupps ligatabell räknas fram
- F04.26.01 Shipped
Datalager: standing.league_points/drawn/sub_wins (heltal, additiv migration 00083) + division_group.public_visible (default dold) + league_table_config (poängschema + forfeit-jsonb + ordnad tiebreaks-jsonb + slutfall, en levande konfig per division, arv division→grupp) + sqlc/store
✅ - F04.26.02 Shipped
Ren deterministisk tabell-/tiebreak-motor (internal/league/table.go): schema + ORDNINGSKÄNSLIG kedja (head_to_head/sub_match_wins/point_diff/points_for) + slutfall (shared_position/playoff), forfeit som konfig-data; omräknings-söm i samma transaktion som fullbordan/forfeit/omhärledning — korrigeringskaskaden når tabellen automatiskt, auditerbart (league.table.recompute)
✅ - F04.26.03 Shipped
Tabell-API:t kontraktfryst additivt: table-config läs/sätt (404 tills satt · 422 vid ogiltiga värden · If-Match = divisionens ETag · PUT triggar omräkning av divisionens grupper) · tabell-läsmodellen GET /v1/league/groups/{id}/table (rader i positionsordning med lagnamn server-side — m-2:s "starta spel som namn-läsväg"-workaround pensionerad, after_round, poänglegend-data, tiebreak_playoff; ETag = gruppens; 422 table_config_missing)
✅ - F04.26.04 Shipped
Zoner ur promotion_rule vid LÄSNING (FR-5): promotion (topp-up_n), playoff (barrage-platsen), relegation (botten-down_n, kantfall utan fel), kryss-nivå via zone_to_division_id — ren härledning, flytten exekveras aldrig (non-goal)
✅ - F04.26.05 Shipped
Playoff-instansiering ur tabellen POST /v1/league/groups/{id}/playoffs (3 typer: mästerskapsslutspel topp-N seedat 1vN/2vN-1 · upp/ned-kval enligt barrage-regel · fristående uppflyttningsturnering; legs 1\
2): intern container-grupp med egen kärnklass (RR-tabellen förblir ren), mötena spelas via m-2:s flöden; idempotent per (grupp, typ); 409 table_not_ready utan underlag | ✅ - F04.26.06 Shipped
Publik yta: synlighetsgrind PUT /v1/league/groups/{id}/visibility (default DOLD, auditloggad) + oinloggade GET /v1/public/league/{tenant_slug}/seasons (navigeringsträd med ENDAST synliggjorda grupper) och GET /v1/public/league/{tenant_slug}/groups/{id}/table (läsmodellen minus admin-fält; dold/okänd/fel tenant ⇒ samma 404 utan läcka; tenant ur slug, aldrig bearer)
✅ - F04.26.07 Shipped
SE/FR-preset-utökning (data-only): table_config (schema + kedja + slutfall, FR med källnot) per klass-stege i presets/{se,fr}.json; apply-preset (fryst path) materialiserar tabell-konfigen idempotent; topologi-guarden utökad med poängschema-/kedje-fingeravtryck
✅ - F04.26.08 Shipped
Admin-tabellyta (admin/app/tavlingar/seriespel/TableSection.tsx: tabell # · Lag · S · V · F · Diff · P, poänglegend renderad ur gruppens VERKLIGA points_scheme-data — aldrig mockupens exempeltext, zonmarkering radfärg + ↑/↓, synliggör-kontroll med If-Match, kval/playoff-kort med de 3 frusna typerna + legs; m-2:s lagnamns-workaround UTFASAD — resolveGroupTeamNames läser tabell-läsmodellen) + publik oinloggad web-sida web/app/seriespel/[tenant] (säsong/division/grupp-val + tabell ur /v1/public/league/*, no-store ⇒ aldrig stale efter korrigering). Vy-specar: specs/admin/seriespel-tabell.md + specs/web/seriespel-publik-tabell.md
✅
Seriespel / Leagues — Parallella klass-stegar (spelklarhet) + reservlag & könskvot (D-LEAGUE m-4)
F04.27Regel-lagret (§M axel 4+11 / §N gap #4/#5 / §L): seriespelets lag-regler är **verkliga och
- F04.27.01 Shipped
Datalager 00084 (additiv): registration.is_reserve_team (default false) + league_team_eligibility_rules (ETT jsonb-regeldokument per division, arv division→grupp, soft delete) + division.class_rule (nullbar jsonb — preset-transport tills start-play materialiserar på kärnans 00064-kolumner) + courts.enclosed (NULLBAR — NULL = okänt = fail-open) + sqlc/store med batchade faktaqueries (ingen N+1)
✅ - F04.27.02 Shipped
Ren spelklarhetsmotor (internal/league/eligibility.go): per-spelare-evaluering (roster · licens · övergång · klubb · klassregel via kärnans frusna CheckCategoryEligibility · reservlagsspärr) + uppställningsnivåns könskvot/ersättarregler/bankrav; fryst skälkodskatalog (§3b) + statusmappning eligible/warning/ineligible; kontraktspaket fryst FÖRE handlers (FR-13)
✅ - F04.27.03 Shipped
Regel-CRUD GET/PUT /v1/league/divisions/{id}/team-eligibility-rules (404 tills satt; If-Match = divisionens ETag; 422 validation_failed, okända fält avvisas; auditloggad) — reglerna är DATA, aldrig kod (TestNoHardcodedCountryTopology utökad)
✅ - F04.27.04 Shipped
Spelklarhets-läsytan GET /v1/league/registrations/{id}/eligibility: {squad {size,max?}, items[{status, checks{roster,license,transfer,club}, reasons[], quarantine_until?}]} — ALLA skäl ackumulerade, batchläst (max 12 queries per koll oavsett truppstorlek, NFR-9), valfri ?player_profile_id= för icke-rostrade (late entry-vyn)
✅ - F04.27.05 Shipped
Verkställighet: uppställnings-PUT avvisar KÄNT ej spelklara spelare (422 lineup_ineligible + samtliga skäl — klassregel/licens/karantän/klubb/reservlagsspärr/könskvot/ersättarregler); rapporteringen (kärnans mène/confirm) OMEVALUERAR persisterade uppställningar; delmatch utan uppställning rapporteras som i m-2 (fail-open); anmälningsytan bär is_reserve_team + squad_full/reserve_team_tier/one_team_per_club; PATCH-actions add_player/late_entry (roster-lås; late entry = enda auditloggade vägen förbi)
✅ - F04.27.06 Shipped
Arena-valet PUT /v1/league/encounters/{id}/venue med bankravsvalidering (court_too_small/court_not_enclosed under 422 court_requirements_unmet; saknad bandata/enclosed NULL = fail-open; venues-API:t orört — ren läsning)
✅ - F04.27.07 Shipped
SE/FR-preset-utökning (data-only): class_rule per stege (SE V55 min_age 55, FR CNC-F women_only — med källnoter) + team_eligibility_rules per division; apply-preset (fryst path) materialiserar idempotent; NL/PL/CZ-kvotmotorn bevisad via config-data i test (deras presetdata = m-5)
✅ - F04.27.08 Shipped
Admin trupp & spelklarhets-yta (admin/app/tavlingar/seriespel/EligibilitySection.tsx): konfigkortet (truppstorlek-tak · "X av Y" ur spelklarhets-svarets squad {size,max} · lag-anmälnings-deadline · karantänväljare med tre frusna lägen) + spelklarhetskollen inför vald rond (grön/gul/röd chip MED text + mockupens fyra kontroller + ALLA klartext-skäl + quarantine_until-datum + blockeringsnotisen) + reservregler-kortet (max ersättare/matchdag · locked-to-sub-match ES · registrering-senast med frusna values) + bankravs-kortet (min-mått · pista cerrada ES) — allt mot riktiga endpoints, PUT mergar in i senast lästa kanoniska doc, verkliga tomt-/laddnings-/fel-tillstånd. Vy-spec: specs/admin/seriespel-trupp-spelklarhet.md
✅
No features match your filters.