Platform Operations & Cross-Cutting Concerns
218 features · 21 subsystems
Cross-cutting capabilities that affect the entire platform: offline support, print integration, localization beyond language, and operational resilience. These are critical for real-world adoption by federations operating in varied conditions.
Offline & Resilience
F16.01**Status:** F16.01.01–04 implemented (PL-F1601a), F16.01.05–08 implemented (PL-F1601b)
How it works- F16.01.01 Shipped
Offline tournament management (draw, score entry, standings — sync when online)
✅ PL-F1601a - F16.01.02 Shipped
Offline license verification (cached license data on device)
✅ PL-F1601a - F16.01.03 Shipped
Conflict-free data sync (CRDT or last-write-wins with conflict UI)
✅ PL-F1601a - F16.01.04 Shipped
Offline check-in at events (QR code scan against cached participant list)
✅ PL-F1601a - F16.01.05 Shipped
Background sync with retry and queue management
✅ PL-F1601b - F16.01.06 Shipped
Sync status indicator (what's pending, what's synced)
✅ PL-F1601b - F16.01.07 Shipped
Graceful degradation (features that work offline vs. require connectivity)
✅ PL-F1601b - F16.01.08 Shipped
Manual fallback procedures (paper score sheets that can be digitized later)
✅ PL-F1601b
Print & Paper Integration
F16.02**Status:** F16.02.01–05 implemented (PL-F1602a), F16.02.06–09 implemented (PL-F1602b)
How it works- F16.02.01 Shipped
Printable draw sheets (formatted for posting at venue)
✅ PL-F1602a - F16.02.02 Shipped
Printable bracket posters (knockout/elimination tournaments)
✅ PL-F1602a - F16.02.03 Shipped
Printable score sheets (per match, for manual scoring)
✅ PL-F1602a - F16.02.04 Shipped
Printable court maps (venue layout with court numbers)
✅ PL-F1602a - F16.02.05 Shipped
QR codes on printed documents linking to digital records
✅ PL-F1602a - F16.02.06 Shipped
OCR/photo scan of paper score sheets for digital entry
✅ PL-F1602b - F16.02.07 Shipped
Printable license cards and certificates
✅ PL-F1602b - F16.02.08 Shipped
Printable competition regulations and rules summary
✅ PL-F1602b - F16.02.09 Shipped
PDF report generation (results, rankings, financial reports)
✅ PL-F1602b
Localization & Federation Customization
F16.03**Status:** F16.03.01–F16.03.05 implemented (PL-F1603a), F16.03.11+F16.03.13–F16.03.14 implemented (PL-F1603c), F16.03.16–F16.03.20 implemented (PL-F1603d). i18n-utvidgningar: gettext (.po), react-intl, RTL-config, locale-detektering, datumformatering, tyska översättningar (PL-F1607a). Franska/spanska/italienska översättningar, översättnings-CMS, lazy-loading, pluralisering (PL-F1607b).
How it works- F16.03.01 Shipped
Configurable competition class registry — each tenant defines its own age/gender classes with: code, name, type (age/gender/open), min/max age, gender filter, ranking eligibility. Examples: Sweden (M/YJ/J/Ö/D/V55/V65), France (Poussin/Benjamin/Minime/Cadet/Junior/Sénior/Vétéran), Spain (Benjamín→Veterano+Sub-23). Implemented (PL-F1603a): PlayerClass model med class_type-fält (age/gender/open), CompetitionClass = PlayerClass + GameFormat. CRUD-endpoints med unik kodvalidering per tenant.
✅ PL-F1603a - F16.03.02 Shipped
Configurable game format registry — each tenant defines: code, name, players per team, boules per player, mixed gender required. Standard formats (s/d/t/Mxd/Mxt) pre-seeded, tenants can add variants. Implemented (PL-F1603a): GameFormat model med mixed_gender_required. CRUD-endpoints med unik kodvalidering per tenant.
✅ PL-F1603a - F16.03.03 Shipped
Configurable competition level registry — each tenant defines its levels with: code, name, who can sanction, ranking eligibility, ranking coefficient, required referee grade, venue requirements, sanction deadline, quota. Not hardcoded. Implemented (PL-F1603a): CompetitionLevel med sanction_deadline_days och quota. CRUD-endpoints med unik kodvalidering per tenant.
✅ PL-F1603a - F16.03.04 Shipped
Configurable fee structure with OrgNode-level components — license fee can be split across multiple OrgNode levels (federation + region + district + insurance). Each level sets its own component. Supports regional price variation. Implemented (PL-F1603a): LicenseFeeConfig med FeeComponent[], LicenseFeeOverride per OrgNode, beräkningsendpoint som resolver OrgNode-hierarkin.
✅ PL-F1603a - F16.03.05 Shipped
Configurable license type registry — each tenant defines its license types with: code, name, competition eligibility, insurance inclusion, age limits, duration (annual/time-limited), medical certificate requirement, renewability. Implemented (PL-F1603a): LicenseType med alla fält inkl. renewable, includes_insurance, base_fee, fee_currency, requires_parental_consent, reduced_fee_pct. Fullständig validering.
✅ PL-F1603a - F16.03.06 Shipped
Configurable transfer rules — per tenant: transfer window dates, max transfers per season, required approvals (player/old club/new club/federation/district), cross-region extra approval, outstanding debt blocking, quarantine during league. Implemented (PL-F1603b): Dedikerade GET/PUT-endpoints under /tenant-config/transfer-config/. Full TransferConfig med alla fält inkl. ITC-inställningar.
✅ PL-F1603b - F16.03.07 Shipped
Configurable ranking algorithm — per tenant: point scale per level × placement × participant count, validity period (1/2/3 years), weighting across years (Germany: 3×/2×/1×), max competitions counted, separate per class/format/gender. Implemented (PL-F1603b): RankingAlgorithmConfig i TenantConfig med ParticipantThreshold-stöd. Dedikerade GET/PUT-endpoints under /tenant-config/ranking-algorithm/.
✅ PL-F1603b - F16.03.08 Shipped
Configurable OrgNode hierarchy — per tenant: number of levels (0-3+), type names per level, capabilities per level (can_sanction, can_set_license_price, has_discipline_body, can_issue_licenses). Implemented (PL-F1603b): Dedikerade GET/PUT-endpoints under /tenant-config/org-hierarchy/ med validering av djup och sekventiella nivåer.
✅ PL-F1603b - F16.03.09 Shipped
Configurable umpire grade registry — per tenant: grade names, count, progression path, playing-umpire allowed per level. Implemented (PL-F0501a, verifierat PL-F1603b): Befintliga endpoints under /tenant-config/umpire-grades/ med full progression, multi-part exam och recertification.
✅ PL-F1603b - F16.03.10 Shipped
Configurable discipline rules — per tenant: penalty amounts, suspension rules, who can decide (only federation vs also district). Implemented (PL-F1603b): Utökad DisciplinaryConfigSchema med sanction_catalog (straffkatalog med belopp, typ, varaktighet) och adr_config (alternativ tvistlösning). Beslutsmyndighet konfigureras via levels[].org_node_level.
✅ PL-F1603b - F16.03.11 Shipped
Configurable medical requirements — per tenant: medical certificate required (yes/no), at first license only, renewal cycle, attestation sur l'honneur, health certificate for international play. Implemented (PL-F1603c): MedicalCertificateConfig med required_at_first_license_only och health_certificate_for_international. Dedikerad config-endpoint GET /medical-certificates/config.
✅ PL-F1603c - F16.03.12 Shipped
Multi-language UI — architected for 43+ FIPJP-member-nation languages, with 5 launch languages delivered (en, sv, fr, es, it) and additional languages activated per nation via tools/translate/translate.py. Implemented (PL-1701, refined under PL-T328): i18n framework, language picker, per-tenant default language, translation management API, completeness reporting (CI gate i18n-coverage enforces ≥ 80% Tier-1 coverage). See specs/shared/i18n.md and docs/engineering/i18n-strategy.md.
✅ PL-F1603c - F16.03.13 Shipped
Multi-language content management (rules, news, documents). Implemented (PL-F1603c): LocalizedContent modell med per-språk title/body/summary, CRUD-endpoints under /content, slug-lookup, per-language translation management (PUT/DELETE /content/{id}/translations/{lang}).
✅ PL-F1603c - F16.03.14 Shipped
Locale-aware formatting (dates, numbers, currency). Implemented (PL-F1603c): LocaleFormattingConfig i TenantConfig med date/time/number/currency-format. Endpoints GET /i18n/locale-formats/{locale} och GET /i18n/locale-formats. Inbyggda defaults för en/sv/fr/de/es/ar.
✅ PL-F1603c - F16.03.15 Shipped
Right-to-left language support. Implemented (PL-1701): RTL detection and layout mirroring for Arabic, Hebrew, Persian, Urdu via I18nManager (React Native) and dir="rtl" (web).
✅ PL-F1603c - F16.03.16 Shipped
Tenant-level branding — logo, colors, terminology per federation. Implemented (PL-F1603d): BrandingConfig embedded i TenantConfig med logo_url, logo_dark_url, favicon_url, primary/secondary/accent/background/text colors (hex-validerade), font_heading, font_body, custom_css. Dedikerade endpoints GET/PUT /tenant-config/branding/.
✅ PL-F1603d - F16.03.17 Shipped
Federation-specific terminology mapping — each tenant maps generic terms to local equivalents. Implemented (PL-F1603d): STANDARD_TERMINOLOGY_KEYS (26 standardtermer), dedikerade endpoints GET/PUT /tenant-config/terminology/ som returnerar terminology dict + standard_keys lista.
✅ PL-F1603d - F16.03.18 Shipped
Game variant support — Jeu Provençal, Pétanque, Sport-Boules. Implemented (PL-F1603d): GameVariantConfig med variant, enabled, name i18n, court_dimensions (CourtDimensions), boules_per_player, max_points, team size, competition_class_codes, rules_document_url. Dedikerade endpoints GET/PUT /tenant-config/game-variants/ med unik variant-validering.
✅ PL-F1603d - F16.03.19 Shipped
Variable OrgNode depth per branch within tenant — non-uniform hierarchy depth. Implemented (PL-F1603d): BranchHierarchyOverride med region_code, region_name i18n, extra_levels (list[OrgNodeTypeConfig]), description. Dedikerade endpoints GET/PUT /tenant-config/branch-hierarchy/ med unik region_code-validering.
✅ PL-F1603d - F16.03.20 Shipped
Delegated admin and CMS per OrgNode level — autonomous sub-federations. Implemented (PL-F1603d): has_own_admin och has_own_cms boolean-fält i OrgNodeTypeConfig. Dedikerad read-endpoint GET /tenant-config/delegated-admin/ som returnerar delegated_levels + parent_branding.
✅ PL-F1603d
Data Visibility & Public Access
F16.04**Status:** F16.04.01–04 implemented (PL-F1604a), F16.04.05–08 implemented (PL-F1604b)
How it works- F16.04.01 Shipped
Public user role (unauthenticated access to public data) — spectator roll, @public decorator, metadata-endpoint
✅ PL-F1604a - F16.04.02 Shipped
Per-resource public field configuration — PublicFieldConfig modell, admin CRUD, defaults, effektiv vy
✅ PL-F1604a - F16.04.03 Shipped
Global public data: world rankings (scope_type=world), federation directory, rules (GET /public/rules)
✅ PL-F1604a - F16.04.04 Shipped
National public data: national rankings (scope_type=national), results, club/district directory (federation_code-filter)
✅ PL-F1604a - F16.04.05 Shipped
Player privacy settings (what's visible on public profile) — PrivacySettings embedded i PlayerProfile, GET/PUT /player-profiles/{id}/privacy-settings, GET /public/players/ respekterar profile_visible+visibility, GET /public/players/{id} respekterar show_club/show_date_of_birth/show_ranking/show_results, hidden profiles returnerar 404
✅ PL-F1604b - F16.04.06 Shipped
Capability-based field visibility (sensitive fields hidden by role) — GET /player-profiles/{id}/visible-fields med tre-tier-filter (public/member/sensitive via apply_role_filter), SensitiveFieldRule med required_capability (profile:read_dob, profile:read_license_number, profile:read_contact), tenant-specifika PublicFieldConfig-overrides
✅ PL-F1604b - F16.04.07 Shipped
Public API for rankings, results, calendar (open data) — GET /public/open-data API-katalog med 14 endpoints, GET /public/calendar med federation_code-filter, GET /public/competitions med federation_code-filter, GET /public/calendar/ical RFC 5545 iCalendar-feed, cursor-paginering på alla listendpoints
✅ PL-F1604b - F16.04.08 Shipped
SEO-friendly public pages (for discoverability) — GET /public/seo/sitemap.xml XML-sitemap med federation/club/competition/venue/ranking-sidor, JSON-LD structured data för federation (SportsOrganization), competition (SportsEvent), calendar-event (Event), venue (SportsActivityLocation), Open Graph metadata GET /public/seo/meta/{resource_type}/{id} för federation/club/competition/venue/calendar_event
✅ PL-F1604b
Event Day Contingency
F16.05**Status:** F16.05.01–04 implemented (PL-F1605a), F16.05.05–07 implemented (PL-F1605b)
How it works- F16.05.01 Shipped
Weather-triggered tournament pause/cancellation workflow
✅ PL-F1605a - F16.05.02 Shipped
Participant no-show management with automatic draw adjustment
✅ PL-F1605a - F16.05.03 Shipped
Court unavailability handling (reassignment, schedule recalculation)
✅ PL-F1605a - F16.05.04 Shipped
Partial results handling (some rounds completed, tournament cancelled)
✅ PL-F1605a - F16.05.05 Shipped
Refund/credit processing for cancelled events
✅ PL-F1605b - F16.05.06 Shipped
Tournament continuation from saved state (resume next day)
✅ PL-F1605b - F16.05.07 Shipped
Emergency communication to all participants
✅ PL-F1605b
Federation Reporting & Compliance
F16.06**Status:** Implemented (PL-1706), buggfixar och integrationstester (PL-F1606a), sponsorrapportering, revisionsklar data, compliance-checklista automation och GDPR-dataläckenotifiering (PL-F1606b)
How it works- F16.06.01 Shipped
Mandatory report templates per federation level — ReportTemplate with configurable sections, deadlines, frequency
✅ PL-F1606a - F16.06.02 Shipped
Automated report generation from system data — GeneratedReport with typed KPI sections (membership, competitions, financial, umpires, sponsors)
✅ PL-F1606a - F16.06.03 Shipped
Report submission deadline tracking and reminders — ReportDeadline with reminder/escalation workflow
✅ PL-F1606a - F16.06.04 Shipped
Upward reporting (club > nation > continent > FIPJP) — Aggregation endpoint combines child reports into parent
✅ PL-F1606a - F16.06.05 Shipped
Government/sports council report generation — GovernmentReportSection with Riksidrottsförbundet-compatible fields
✅ PL-F1606a - F16.06.06 Shipped
Sponsor reporting (participation data, exposure metrics) — SponsorSection with impressions, clicks, value
✅ PL-F1606b - F16.06.07 Shipped
Audit-ready data with full trail — is_audit_ready flag on reports, revision tracking on all documents
✅ PL-F1606b - F16.06.08 Shipped
Compliance checklist automation (tournament had jury, insurance, etc.) — ComplianceChecklist with auto-scoring and action items
✅ PL-F1606b - F16.06.09 Shipped
Data breach notification workflow (GDPR Article 33/34) — DataBreachNotification with 72h tracking and full timeline
✅ PL-F1606b
Stakeholder Feedback & Feature Requests
F16.07**Status:** Implemented (PL-2110)
How it works- F16.07.01 Shipped
Structured feature request form with 6 sections (contact, stakeholder category, request details, acceptance criteria, attachments, priority)
✅ PL-F1607a - F16.07.02 Shipped
Live Markdown preview — real-time rendering of generated task-spec alongside the form
✅ PL-F1607a - F16.07.03 Shipped
Stakeholder category/subcategory selection — 11 categories with dynamic subcategory filtering
✅ PL-F1607a - F16.07.04 Shipped
Feature inventory integration — searchable dropdown over 1 250+ features for "related feature" linking
✅ PL-F1607a - F16.07.05 Shipped
Markdown task-spec generation — structured .md file following backlog runner format
✅ PL-F1607a - F16.07.06 Shipped
Email delivery via Azure Communication Services — support notification + stakeholder confirmation
✅ PL-F1607a - F16.07.07 Shipped
MongoDB storage with audit trail — feature_requests collection with revision tracking and soft-delete
✅ PL-F1607b - F16.07.08 Shipped
Admin triage endpoints — list, detail, status update, soft-delete via REST API
✅ PL-F1607b - F16.07.09 Shipped
Anti-spam protection — honeypot field, Cloudflare Turnstile CAPTCHA, rate limiting (5/h per IP)
✅ PL-F1607b - F16.07.10 Shipped
i18n — form available in EN, FR, ES, SV; generated Markdown always in English
✅ PL-F1607b - F16.07.11 Shipped
WCAG 2.1 AA accessibility — labelled fields, aria attributes, keyboard navigation, contrast compliance
✅ PL-F1607b - F16.07.12 Shipped
SEO — per-language meta tags, JSON-LD ContactPage schema, sitemap inclusion
✅ PL-F1607b - F16.08.01 Shipped
Score entry offline med WatermelonDB — WatermelonDB-compatible pull/push sync protocol with delta timestamps, per-table change tracking (match_scores, mene_scores), idempotent push with version-based conflict detection
✅ PL-F1608a - F16.08.02 Shipped
License-verifiering med cachad data — HMAC-SHA256 integrity hash on license bundles, incremental delta download via previous_hash, server-side license verification endpoint
✅ PL-F1608a - F16.08.03 Shipped
Sync-status indikator — sync session creation/completion, per-type progress tracking with percentage, pending/completed/failed/conflict counts, enhanced UI progress bar and per-type breakdown
✅ PL-F1608a - F16.08.04 Shipped
Konflikthantering vid sync (last-write-wins) — configurable per-resource-type policies with auto/manual field classification, LWW/server-wins/client-wins/manual strategies, full audit trail via ConflictAuditEntry
✅ PL-F1608a - F16.08.05 Shipped
Bakgrundssync vid wifi-anslutning — per-user wifi-only preference (BackgroundSyncPreference), auto-sync on reconnect, periodic sync interval, quiet hours, sync trigger evaluation based on connection type and preferences
✅ PL-F1608b - F16.08.06 Shipped
Offline-fönster max 7 dagar — configurable max offline window (default 7 days), 12h grace period, 5-day warning threshold, per-data-type validation, automatic invalidation of expired offline data
✅ PL-F1608b - F16.08.07 Shipped
Selective sync (bara aktuell tävling) — per-user competition scope (SelectiveSyncScope), sync only selected competitions, estimated data size calculation, automatic inclusion of requested competition in scope
✅ PL-F1608b - F16.08.08 Shipped
Bandwidth-medveten sync (3G vs wifi) — per-connection-type profiles (wifi/5G/4G/3G/2G/ethernet), adaptive batch sizing based on effective bandwidth and signal strength, image sync control, compression, throttling
✅ PL-F1608b
Audit Log & Compliance Retention
F16.09**Status:** F16.09.01–04 implemented (PL-F1609a), F16.09.05–08 implemented (PL-F1609b)
How it works- F16.09.01 Shipped
Strukturerad audit log via Craft Easy — unified cross-domain AuditLog collection with 13 domain categories, central write service (write_audit_log), read endpoints (GET /audit-log/, entity trail, actor trail), append-only immutable contract. Implemented (PL-F1609a): AuditLog model med domain/action/entity_type/entity_id/actor_id/details/search_text, 7 composite indexes, tenant-scoped.
✅ PL-F1609a - F16.09.02 Shipped
Utökad loggning för disciplin-ärenden — extended DisciplinaryAuditEntry med ip_address, user_agent, entity_type, DisciplinaryAuditAction enum (30 actions: case lifecycle, hearing, sanction, appeal, ADR, CAS), dual-write till central audit log via write_discipline_audit. Implemented (PL-F1609a).
✅ PL-F1609a - F16.09.03 Shipped
Utökad loggning för ekonomi-mutationer — write_finance_audit service som skriver till både FinancialAuditLog och central AuditLog, enriched details med amount/currency, coverage för alla 80+ FinancialAuditAction typer. Implemented (PL-F1609a).
✅ PL-F1609a - F16.09.04 Shipped
Audit log search med fritext — search_text fält med auto-genererad sökbar text, regex-baserad case-insensitive sökning (Cosmos DB-kompatibel), GET /audit-log/search?q= endpoint med domain/datum-filter, paginering. Implemented (PL-F1609a).
✅ PL-F1609a - F16.09.05 Shipped
Obegränsad audit-retention — AUDIT_LOG_RETENTION_DAYS=0 (indefinite), validate_retention_policy service flaggar non-compliant tenant-policies, GET /audit-log/retention endpoint. Inga TTL-indexes, inga expireAfterSeconds. Rättslig grund: GDPR Art. 6(1)(f). Implemented (PL-F1609b).
✅ PL-F1609b - F16.09.06 Shipped
GDPR-dataexport inkluderar audit logs — export_audit_logs_for_user service samlar alla entries där användaren är actor, integrerat i GET /me/data-export (Art. 20). Implemented (PL-F1609b).
✅ PL-F1609b - F16.09.07 Shipped
GDPR right-to-erasure (anonymisering) — anonymise_audit_logs_for_user ersätter PII (actor_id→null, ip→0.0.0.0, UA→ANONYMISED, PII-nycklar i details→ANONYMISED) utan radering. is_anonymised-flagga. Integrerat i POST /data-deletion-requests/{id}/process. Implemented (PL-F1609b).
✅ PL-F1609b - F16.09.08 Shipped
Per-fält PII-klassificering — PIICategory enum (identity/network/behavioural/contextual), json_schema_extra PII-taggar, AuditLog.pii_fields() classmethod, ANONYMISATION_RULES, GET /audit-log/pii-schema endpoint. Implemented (PL-F1609b).
✅ PL-F1609b
Rate Limiting & DoS Protection
F16.10**Status:** F16.10.01–04 implemented (PL-F1610a), F16.10.05–07 implemented (PL-F1610b)
How it works- F16.10.01 Shipped
Rate limiting per IP — sliding-window per-IP enforcement via RateLimitMiddleware, configurable limit/window (default 200/60s), 429 response with Retry-After and X-RateLimit-* headers, health-check paths exempt. Implemented (PL-F1610a).
✅ PL-F1610a - F16.10.02 Shipped
Rate limiting per user — per-authenticated-user sliding window (default 300/60s), keyed on principal_id from auth context, public pseudo-users excluded, independent from per-IP limits. Implemented (PL-F1610a).
✅ PL-F1610a - F16.10.03 Shipped
Rate limiting per tenant — aggregate sliding window across all users within a tenant (default 5000/60s), keyed on tenant_id from auth context, prevents single-tenant resource monopolisation. Implemented (PL-F1610a).
✅ PL-F1610a - F16.10.04 Shipped
Cloudflare DDoS-skydd — CloudflareMiddleware extracts real client IP from CF-Connecting-IP, passes through CF-Ray/CF-IPCountry as response headers, optional origin protection (CLOUDFLARE_REQUIRE_HEADER) blocks direct access (403), X-Cloudflare-Protected response header. Implemented (PL-F1610a).
✅ PL-F1610a - F16.10.05 Shipped
Brute-force-skydd på login — LoginProtectionMiddleware monitors auth endpoints (POST /auth/token, /auth/login, etc.) for failed login attempts (HTTP 401/403), applies per-IP exponential backoff (1s→2s→4s→...→30s capped), lockout with Retry-After header. Implemented (PL-F1610b).
✅ PL-F1610b - F16.10.06 Shipped
CAPTCHA fallback vid attack — after configurable failure threshold (default 3), requires Cloudflare Turnstile CAPTCHA token via X-Captcha-Token header before allowing further login attempts. Returns 429 with captcha_required: true. Shared verify_turnstile_token service. Implemented (PL-F1610b).
✅ PL-F1610b - F16.10.07 Shipped
Adaptive rate limits baserat på trafik — AdaptiveRateLimitController monitors total API traffic volume in sliding window, dynamically adjusts rate limits across three levels: normal (1.0×), elevated (0.5× at 2× baseline), critical (0.25× at 5× baseline). Integrated with RateLimitMiddleware. Implemented (PL-F1610b).
✅ PL-F1610b - F16.10.08 Shipped
Turnstile bot-protection på alla publika POST-endpoints — TurnstileMiddleware för auth-endpoints + Depends(verify_turnstile) för marketing/signup/contract/feature-requests. Defense-in-depth med honeypot + rate-limit. Shared widget i packages/shared/src/turnstile/. CSP uppdaterad för challenges.cloudflare.com. Fail-open vid CF-timeout (5s). Implemented (PL-T072).
✅ PL-T072
Security Headers & CORS
F16.11**Status:** F16.11.01–04 implemented (PL-F1611a), F16.11.05–07 implemented (PL-F1611b), F16.11.08 implemented (PL-T287)
How it works- F16.11.01 Shipped
CORS-policy per miljö och app — per-environment CORS origin allowlist med production-origins för admin/app/www/petanque.life + localhost i dev, wildcard-reject i production via model_validator, credentials/methods/headers/expose/max-age konfigurerat. Implemented (PL-F1611a).
✅ PL-F1611a - F16.11.02 Shipped
Content-Security-Policy med nonces — per-request secrets.token_urlsafe(16) nonce injicerat i CSP script-src och style-src via {nonce}-placeholder, frame-ancestors 'none', base-uri 'self', form-action 'self', upgrade-insecure-requests. Nonce tillgängligt via request.state.csp_nonce. Implemented (PL-F1611a).
✅ PL-F1611a - F16.11.03 Shipped
HSTS preload-list inclusion — Strict-Transport-Security: max-age=31536000; includeSubDomains; preload på alla HTTPS-svar, HSTS-header utelämnad på plain HTTP, proxy-stöd via X-Forwarded-Proto. Implemented (PL-F1611a).
✅ PL-F1611a - F16.11.04 Shipped
X-Frame-Options DENY för admin — X-Frame-Options: DENY som default (konfigurerbar via SECURITY_HEADERS_X_FRAME_OPTIONS), förhindrar clickjacking på admin- och API-endpoints. Implemented (PL-F1611a).
✅ PL-F1611a - F16.11.05 Shipped
Referrer-Policy strict-origin — konfigurerbar via SECURITY_HEADERS_REFERRER_POLICY, Petanque Life default strict-origin (striktare än craft-easy default strict-origin-when-cross-origin). Skickar bara origin, aldrig path/query. Implemented (PL-F1611b).
✅ PL-F1611b - F16.11.06 Shipped
Permissions-Policy per app-typ — konfigurerbar via SECURITY_HEADERS_PERMISSIONS_POLICY, inaktiverar camera, microphone, geolocation, payment, usb, magnetometer, gyroscope, accelerometer, ambient-light-sensor, autoplay. Tillåter fullscreen, encrypted-media, picture-in-picture för same-origin. Implemented (PL-F1611b).
✅ PL-F1611b - F16.11.07 Shipped
Subresource Integrity (SRI) för CDN-assets — SriAsset-modell, hash-beräkning (sha256/384/512), publikt manifest (GET /sri/manifest), admin CRUD, re-verifiering. Implemented (PL-F1611b).
✅ PL-F1611b - F16.11.08 Shipped
Security.txt (RFC 9116) — /.well-known/security.txt på alla publika domäner (petanque.life, *.web.petanque.life, api/admin/app/sys/design.petanque.life). Shared TS-generator i packages/shared/src/security/security-txt.ts, FastAPI-route i api/src/petanque_api/routes/well_known.py, build-time-genererad fil för Expo SWA via tools/security/generate-security-txt.mjs. PGP-nyckel + disclosure-policy (en/sv/fr/es) + hall-of-fame på petanque.life. Veckovis CI-kontroll av Expires (tools/security/verify_security_txt.py). Implemented (PL-T287).
✅ PL-T287
Capability-baserad åtkomstkontroll
F16.12**Status:** F16.12.01–06 implemented (PL-F1612)
How it works- F16.12.01 Shipped
Capability-check på varje endpoint — POST /capability-check och POST /capability-check-batch verifierar att anroparen har erforderlig capability. Nekad åtkomst loggas i audit log. Implemented (PL-F1612).
✅ PL-F1612 - F16.12.02 Shipped
Capability-tilldelning per OrgNode-roll — GET /users/{user_id}/orgnode-capabilities/{org_node_id} beräknar effektiva capabilities för en användare vid en specifik OrgNode, filtrerar på scope (system/tenant/org_node). Implemented (PL-F1612).
✅ PL-F1612 - F16.12.03 Shipped
Konfigurerbara capabilities per tenant — GET/PUT /tenant-capability-config/{tenant_id} låter varje federation inaktivera capabilities och begränsa till specifika domäner. TenantCapabilityConfig-modell med disabled_capabilities och enabled_domains. Implemented (PL-F1612).
✅ PL-F1612 - F16.12.04 Shipped
Capability audit log — GET /capability-audit querying av capability-domänens audit-logg. Alla grant/revoke/deny/config-ändringar loggas under AuditLogDomain.CAPABILITY. Implemented (PL-F1612).
✅ PL-F1612 - F16.12.05 Shipped
Tidsbegränsade capabilities (sommarvikariat) — GET /capability-grants/expiring listar utgående grants, GET /capability-grants/summary ger dashboard-översikt. Stöd för valid_from/valid_until på rolltilldelningar. Implemented (PL-F1612).
✅ PL-F1612 - F16.12.06 Shipped
Capability-templates per roll-arketyp — POST/GET/PUT/DELETE /capability-templates, POST /capability-templates/{id}/apply. CapabilityTemplate-modell för användardefinierade capability-buntar med wildcard-expansion vid applicering. Implemented (PL-F1612).
✅ PL-F1612
Observability och driftövervakning
F16.13**Status:** F16.13.01–09 implemented (PL-F1613a, PL-F1613b)
How it works- F16.13.01 Shipped
Strukturerad loggning med structlog — sensitive-field masking (SENSITIVE_FIELDS frozen set), request context binding (request_id/tenant_id/user_id/trace_id), JSON/console renderers, startup info event, ObservabilityMiddleware logs every request with method/path/status/duration/client_ip. Implemented (PL-F1613a).
✅ PL-F1613a - F16.13.02 Shipped
Prometheus metrics — craft-easy MetricsMiddleware (HTTP requests, duration, in-flight, request/response size), petanque-specific business metrics: petanque_license_operations_total, petanque_auth_operations_total, petanque_tenant_api_requests_total, petanque_match_scores_submitted_total, petanque_audit_log_entries_total, petanque_sync_operations_total, petanque_db_query_duration_seconds, petanque_health_check_*. /metrics scrape endpoint. Implemented (PL-F1613a).
✅ PL-F1613a - F16.13.03 Shipped
OpenTelemetry distributed tracing — setup_telemetry() initializes OTLP gRPC exporter, auto-instruments FastAPI/httpx/pymongo, injects trace_id/span_id into structlog events, X-Trace-Id response header, graceful no-op when OTel packages absent. Configurable via OTEL_ENABLED, OTEL_EXPORTER_OTLP_ENDPOINT, OTEL_SERVICE_NAME. Implemented (PL-F1613a).
✅ PL-F1613a - F16.13.04 Shipped
Health check endpoints — craft-easy /health (liveness) and /ready (readiness with MongoDB ping), petanque /startup (startup probe for Kubernetes/Azure Container Apps), /health/detailed (per-dependency status with latency: MongoDB, Redis), /observability/config (non-sensitive config inspection). Implemented (PL-F1613a).
✅ PL-F1613a - F16.13.05 Shipped
Grafana dashboards — JSON provisioning under infrastructure/grafana/: dashboard provider config (provisioning/dashboards.yml), API overview dashboard (dashboards/api-overview.json) with 12 panels: request rate, latency p50/p95/p99, in-flight, error rate, health status, health latency, license ops, auth ops, tenant traffic, DB query latency, audit log rate, sync ops/conflicts. Implemented (PL-F1613a).
✅ PL-F1613a - F16.13.06 Shipped
Alert routing till PagerDuty/Opsgenie — per-tenant alert routing config (AlertRoutingConfig), stöd för PagerDuty Events API v2, Opsgenie Alerts API v2, generiska webhooks, cooldown-baserad deduplicering, AlertHistory audit trail. Endpoints: GET/PUT /observability/alerts/config/{tenant_id}, POST /observability/alerts/fire/{tenant_id}, GET /observability/alerts/history/{tenant_id}. Prometheus-metrics: petanque_alerts_fired_total, petanque_alerts_suppressed_total. Implemented (PL-F1613b).
✅ PL-F1613b - F16.13.07 Shipped
Per-tenant SLO-mätning — konfigurerbara SLO-mål per tenant (TenantSLOConfig) med systemdefaulter (99.9% tillgänglighet, p95 ≤ 300 ms, p99 ≤ 800 ms). SLOMeasurement dokument för historik. Endpoints: GET/PUT /observability/slo/config/{tenant_id}, POST /observability/slo/measure/{tenant_id}, GET /observability/slo/status/{tenant_id}, GET /observability/slo/history/{tenant_id}/{slo_type}. Prometheus-gauge: petanque_slo_compliance_ratio. Implemented (PL-F1613b).
✅ PL-F1613b - F16.13.08 Shipped
Error budget burndown — beräknar felbudget från SLO-mål och faktisk compliance, burnrate per timme, estimerad tid till budgetuttömning. Status: ok/warning/critical/exhausted. Endpoint: GET /observability/slo/burndown/{tenant_id}. Prometheus-gauge: petanque_error_budget_remaining_ratio. Implemented (PL-F1613b).
✅ PL-F1613b - F16.13.09 Shipped
Sentry för frontend-felfångst — Sentry DSN-konfiguration för frontend-appar (GET /observability/sentry/config), envelope tunnel för CSP-compliance (POST /observability/sentry/envelope), lättviktig felrapportering (POST /observability/sentry/report). Prometheus-counter: petanque_frontend_errors_total. Implemented (PL-F1613b).
✅ PL-F1613b - F16.13.10 Shipped
Live status page — publik statussida som hämtar realtidsstatus via GET /public/status och GET /public/status/incidents. ServiceHealthSample-modell med TTL (90 dagar), StatusIncident-modell med automatisk incident-skapning vid statusändring. Bakgrundsjobb (CollectStatusSamplesJob) kör var 60:e sekund. Admin-endpoints POST /incidents + PATCH /incidents/{id} för manuell incidenthantering. Uptime beräknas som 30-dagars rullande fönster. www-statussidan hämtar data via client-side fetch med 30s auto-refresh och 5s timeout-fallback. Implemented (PL-T045).
✅ PL-T045 - F16.13.11 Shipped
Performance profiling (continuous)
✅ PL-T288
Disaster Recovery & Restore Drill
F16.14**Status:** Implemented (PL-T052)
How it works- F16.14.01 Shipped
DR-runbook med scenariomatris (data-corruption, region-down, credential-leak, ransomware, delete-by-mistake). Per scenario: detection → containment → recovery → post-mortem. Exakta az cosmosdb mongodb database restore-kommandon. RPO 4h / RTO 8h.
✅ PL-T052 - F16.14.02 Shipped
Automatiserad månatlig restore-drill (GitHub Actions cron 0 4 1-7 * 1). Skapar petanque-drill-<timestamp> via PITR, kör smoke-queries, jämför counts mot prod (±1 %), raderar temp-DB, skickar Slack-rapport.
✅ PL-T052 - F16.14.03 Shipped
Smoke-test-script (tools/dr-drill-smoke.py) — queries tenants, users, licenses, invoices, tenant_subscriptions. Delta-gräns ±1 %. Exit code 0 = PASS, 1 = FAIL, 2 = prereq-fel.
✅ PL-T052 - F16.14.04 Shipped
Service principal sp-petanque-dr-drill med custom role Petanque DR Drill Operator (minimala Cosmos DB-rättigheter). Skapas via infrastructure/scripts/create-dr-drill-sp.sh.
✅ PL-T052 - F16.14.05 Shipped
Key Vault-backup-rutin dokumenterad (soft-delete + purge-protection, az keyvault secret backup/restore).
✅ PL-T052 - F16.14.06 Shipped
Stripe-nyckelrotationsprocedur dokumenterad (az containerapp secret set + az containerapp update vid credential-läcka).
✅ PL-T052 - F16.14.07 Shipped
ACS connection-string-rotationsprocedur dokumenterad (az communication regenerate-key + Container App-uppdatering).
✅ PL-T052 - F16.14.08 Shipped
RPO/RTO baseline i infrastructure/drill-history.md — uppdateras automatiskt efter varje drill-körning.
✅ PL-T052
Incident-Response & Alert-Routing
F16.15**Status:** Implemented (PL-T053)
How it works- F16.15.01 Shipped
Severity-matris Sev1/Sev2/Sev3 med eskaleringsvägar, responstider och SLA-formulering (docs/engineering/operations/incident-response.md).
✅ PL-T053 - F16.15.02 Shipped
On-call-rotation dokumenterad (docs/engineering/operations/on-call-rotation.md) med schema, kontaktuppgifter och semesterhantering.
✅ PL-T053 - F16.15.03 Shipped
Blameless postmortem-mall (docs/engineering/operations/postmortem-template.md) med timeline, root cause, kontribuerande faktorer och åtgärdslista.
✅ PL-T053 - F16.15.04 Shipped
Azure Monitor action group ag-petanque-primary (e-post + Slack-webhook) provisionerad via infrastructure/monitoring.bicep.
✅ PL-T053 - F16.15.05 Shipped
Sev1-alerts: 5xx-rate > 1 % / 5 min, Cosmos RU-throttling > 10 % / 5 min, ACS e-post bounce > 5 % / 15 min.
✅ PL-T053 - F16.15.06 Shipped
Sev2-alerts: Container App restarts > 3/h, API-latens p95 > 2 s / 10 min, Stripe webhook-fel > 5 %.
✅ PL-T053 - F16.15.07 Shipped
Deploy-script infrastructure/deploy-monitoring.sh för att applicera Bicep mot Azure.
✅ PL-T053 - F16.15.08 Shipped
IncidentLog Beanie-modell med severity (sev1/sev2/sev3), workflow-status (investigating/identified/monitoring/resolved), public_message och updates-lista.
✅ PL-T053 - F16.15.09 Shipped
GET /public/incidents?since=<iso> — returnerar senaste 30 dagars incidents, publika fält, sortering nyaste-först.
✅ PL-T053 - F16.15.10 Shipped
POST /admin/incidents + PATCH /admin/incidents/{id} — platform-admin-only, skapar och uppdaterar incidents med severity-klassning.
✅ PL-T053 - F16.15.11 Shipped
Status-sida (www/src/pages/status.astro + fr/es/sv-varianter) uppdaterad att hämta incident-historik från IncidentLog-collection via /public/incidents. Severity- och workflow-badges i UI.
✅ PL-T053
Security Pipeline
F16.16**Status:** Implemented (PL-T054)
How it works- F16.16.01 Shipped
Dependabot — veckovisa PR:ar för npm (admin/app/www/packages/shared), pip (api) och månatliga för github-actions. Minor/patch grupperas per ekosystem.
✅ PL-T054 - F16.16.02 Shipped
Gitleaks secret-scan — kör på varje PR (diff) och push (incremental). Anpassade regler för Stripe-nycklar, Azure connection strings, JWT private keys, Google OAuth-secrets och generiska high-entropy strings (entropi ≥ 4.5).
✅ PL-T054 - F16.16.03 Shipped
CodeQL statisk analys — Python (api) + JavaScript/TypeScript (admin/app/www/shared). Kör på varje PR och veckovis (söndagar 03:00 UTC). security-extended query-suite.
✅ PL-T054 - F16.16.04 Shipped
Trivy container-image-scan — integrerat i deploy-api.yml pre-push. Blockar deploy vid CRITICAL/HIGH CVE med fix-version. SECURITY_OVERRIDE-undantag med automatisk Slack-notifiering till #ops-alerts.
✅ PL-T054 - F16.16.05 Shipped
CVE-policy (docs/engineering/operations/cve-policy.md) — sev-matris, responsible disclosure via security@petanque.life, SECURITY_OVERRIDE-process, retrospektivkrav för CRITICAL.
✅ PL-T054 - F16.16.06 Shipped
SECURITY.md i repo-rot — publik responsible disclosure-policy med scope, SLA och kontakt.
✅ PL-T054
Coverage Gate + Critical-path Tests
F16.17**Status:** Implemented (PL-T051)
How it works- F16.17.01 Shipped
pytest-cov coverage-gate — fail_under=80, branch=true, coverage.xml-artefakt uppladdad per PR. Exkluderar migrations, seeds, __init__.py, TYPE_CHECKING-block.
✅ PL-T051 - F16.17.02 Shipped
PR coverage-kommentar via py-cov-action/python-coverage-comment-action@v3 — informell, continue-on-error=true, blockar inte på kommentarfel.
✅ PL-T051 - F16.17.03 Shipped
ci-api / coverage som required check — blockar merge vid < 80 % line-täckning.
✅ PL-T051 - F16.17.04 Shipped
Critical-path testsvit api/tests/critical_path/ — 7 filer, 55+ tester, in-memory MongoDB (mongomock_motor), Stripe mockad.
✅ PL-T051 - F16.17.05 Shipped
ci-api / critical-path som required check — blockar merge vid trasigt billing- eller GDPR-flöde.
✅ PL-T051 - F16.17.06 Shipped
Frontend coverage soft gate — admin npm test --coverage i CI, continue-on-error=true, artefakt uppladdad 14 dagar.
✅ PL-T051
Self-service Data Import
F16.18**Status:** Implemented (PL-T056)
How it works- F16.18.01 Shipped
CSV- och Excel-parsing med auto-detektering av delimiter, BOM-stöd och Excel-datumkonvertering.
✅ PL-T056 - F16.18.02 Shipped
6-stegs import-wizard i admin (/import): välj typ → ladda upp → mappning → dry-run → commit → status.
✅ PL-T056 - F16.18.03 Shipped
Auto-mappning av kolumnrubriker (case-insensitiv + vanliga aliaser: email, e-post, förnamn, etc.).
✅ PL-T056 - F16.18.04 Shipped
Dry-run validering: schema-validering + domänvalidering utan att skriva data. Upp till 100 fel inline.
✅ PL-T056 - F16.18.05 Shipped
Commit i bakgrundsjobb med batch-storlek 500 rader. Progress-uppdatering per batch.
✅ PL-T056 - F16.18.06 Shipped
Rollback inom 1 timme: tar bort alla created_doc_ids från jobbet. 410 Gone efter fönstret.
✅ PL-T056 - F16.18.07 Shipped
Konfigurerbar dedup-strategi per jobb: skip, update, fail vid kollisioner.
✅ PL-T056 - F16.18.08 Shipped
Per-resurs importerare (players, licenses, clubs, memberships) med egna fältscheman och dedup-nycklar.
✅ PL-T056 - F16.18.09 Shipped
Template-generator: GET /import/templates/{resource} returnerar CSV med rätt kolumner och exempelrad.
✅ PL-T056 - F16.18.10 Shipped
ImportJob-modell med fullständig audit trail: status, mappning, valideringsfel, skapade doc-ID:n, tidsstämplar.
✅ PL-T056
Legal Document Versioning & Signing
F16.19**Status:** Kärninfrastruktur (modeller, service, routes, clickwrap) implementerad i PL-T094. DocuSign/BankID-integrationerna returnerar 501 tills provider-credentials landat.
How it works- F16.19.01 Shipped
LegalDocument-modell (platform-scoped) — versionerad per (type, language), SHA-256 content-hash, superseded_by-länk till efterföljande version.
✅ PL-T094 - F16.19.02 Shipped
LegalDocumentAcceptance-modell (tenant-scoped, append-only) — immutable audit-rad per (tenant, type, version) med IP, UA, content-hash-kopia och signerings-metadata.
✅ PL-T094 - F16.19.03 Shipped
Automatisk supersede: publish_version sätter superseded_by på tidigare aktiv version för samma (type, language).
✅ PL-T094 - F16.19.04 Shipped
GET /legal/documents?type=&lang= — publik läsning av aktiv version.
✅ PL-T094 - F16.19.05 Shipped
POST /legal/documents (platform_admin) — publicera ny version.
✅ PL-T094 - F16.19.06 Shipped
GET /legal/documents/history (platform_admin) — versionshistorik sorterad på effective_date desc.
✅ PL-T094 - F16.19.07 Shipped
POST /tenants/{id}/legal/{doc_type}/sign-clickwrap — checkbox-flöde med IP + UA-logg.
✅ PL-T094 - F16.19.08 Shipped
GET /tenants/{id}/legal/pending?lang= — dokument där tenant saknar acceptance eller aktiv version kräver re-acceptance.
✅ PL-T094 - F16.19.09 Shipped
GET /tenants/{id}/legal/acceptances — full tenant-acceptanshistorik.
✅ PL-T094 - F16.19.10 Shipped
is_fully_accepted() — service-helper för onboarding-guard (True när pending-listan är tom).
✅ PL-T094 - F16.19.11 Shipped
DocuSign eSignature REST v2.1-integration via JWT Grant + RSA-nyckel i Key Vault, create_envelope/get_envelope_status/download_signed_pdf, HMAC-SHA256 webhook-validering.
✅ PL-T289 - F16.19.12 Shipped
BankID v6 RP-flöde (/sign, /collect, /cancel) via mTLS-cert i Key Vault, default-provider för SE-tenants, PNR-redaktering i loggar och i tjänstelagret.
✅ PL-T289 - F16.19.13 Shipped
PDF-rendering för kontrakt + legal-dokument med signatur-attest-sida (signer, signed-at, SHA-256, provider-referens). PDF/A-1b-konformans verifieras av verapdf-cli i CI-jobbet ci-api / pdf-a-conformance.
✅ PL-T289 - F16.19.14 Shipped
Contract.legal_document_acceptances länkar kontrakt till accepterade dokument-versioner. GET /admin/contracts/{id}/legal-coverage exponerar audit-trailen.
✅ PL-T289 - F16.19.15 Shipped
Onboarding-guard i POST /sys/tenants returnerar 422 onboarding_acceptance_incomplete med missing_documents-lista. Sys-konsolens tenant-create-vy visar checklistan och blockerar submit.
✅ PL-T289
Admin Console Premium UX
F16.20**Status:** IA-restrukturering, designsystem, nya admin-vyer, ⌘K-palett, brödsmulor, keyboard shortcuts, rollbaserad menyfiltrering och UX-telemetri implementerade i PL-T099.
How it works- F16.20.01 Shipped
Informationsarkitektur — 14 sektioner konsoliderade till 6 grupper (Översikt, Organisation, Aktivitet, Ekonomi, Kommersiellt, Plattform) i admin/src/navigation/sections.ts. "Coming soon" borttaget.
✅ PL-T099 - F16.20.02 Shipped
Designsystem — tokens i packages/shared/src/design/native (bottle-green/ivory), admin-bridge admin/src/theme/tokens.ts, ThemeContext med light/dark.
✅ PL-T099 - F16.20.03 Shipped
Komponentbibliotek — DataTable, FormField + FormSection, Breadcrumbs, CommandPalette, KeyboardShortcutsOverlay, OnboardingBanner som delade primitiver.
✅ PL-T099 - F16.20.04 Shipped
Dashboard-startsida — hälsning, onboarding-banner, 3 snabbåtgärder, 4 KPI-kort, aktivitetsflöde-placeholder. admin/app/(dashboard)/index.tsx.
✅ PL-T099 - F16.20.05 Shipped
Fyra top-level admin-vyer — Federations, Licenses, Governance, Discipline. Audit-logg bruten ut till egen route. Se specs/admin/views/.
✅ PL-T099 - F16.20.06 Shipped
Kommandopalett (⌘K / Ctrl+K) — global sök över nav-items och tenant-switch. Samma synlighetsregler som sidomenyn.
✅ PL-T099 - F16.20.07 Shipped
Brödsmulor — Breadcrumbs-primitiv mountad i governance, federations, audit, discipline. Sista item inert, tidigare router-länkade.
✅ PL-T099 - F16.20.08 Shipped
Keyboard shortcuts — ? öppnar cheat-sheet (KeyboardShortcutsOverlay), Esc stänger, Meta+K / Ctrl+K öppnar paletten. Input-typing-suppress.
✅ PL-T099 - F16.20.09 Shipped
Rollbaserad menyfiltrering — NavItem.requiredTenantRoles: TenantRole[], visibleSectionsFor(tt, isPlatformAdmin, activeRole). RBAC-lins på nav, applicerad på sidomeny + palett.
✅ PL-T099 - F16.20.10 Shipped
UX-telemetri — lättviktig buffer i admin/src/lib/telemetry.ts med trackRouteView / trackRouteAction, 200-event ringbuffer, opt-out via localStorage.
✅ PL-T099 - F16.20.11 Shipped
UserDashboardPreferences-endpoint-spec — /me/dashboard-preferences GET/PUT/reset, tenant-scoped, upsert-on-read. Backend-implementation deferrad.
✅ PL-T099 (spec) - F16.20.12 Shipped
Widget drag-and-drop med persistens mot /me/dashboard-preferences. Backend-endpoint + frontend-binding via DraggableDashboardGrid (keyboard-first WCAG 2.1.1 AA, HTML5 drag-events på web). 500 ms debounced PUT, optimistisk UI med rollback vid 5xx, "Lägg till widget"-meny + "Nollställ layout"-knapp. Tillämpad på både admin- och sys-konsolens dashboards.
✅ PL-T290 - F16.20.13 Shipped
Aktivitetsflöde kopplat till audit-stream — senaste 20 entries från GET /audit-log?limit=20 med relativ tid, domän-ikon och EmptyState/Banner-fallbacks. admin/app/(dashboard)/index.tsx.
✅ PL-T156 - F16.20.14 Shipped
UX-validerings-pipeline för admin-konsolen — testprotokoll i docs/product/admin/usability-test-protocol.md (5 deltagare × 5 kärnuppgifter, SUS-mätning, severity-klassad friktion), avpersonifierad rapport-mall i usability-test-2026-h1.md; Lighthouse-runner tools/lighthouse/run-admin-routes.sh (12 routes × mobile+desktop) + compare-baselines.mjs med absolut floor 90 och regression-tröskel 5 poäng (routes.json); CI-workflow admin-lighthouse.yml (PR + nightly mot prod, PR-kommentar med summary-tabell); admin-baseline visual regression (tools/visual-regression/tests/admin-baseline.spec.ts, 12 routes × {375,1440} × {light,dark} = 48 PNG i Chromium) med dedikerat workflow admin-visual-regression.yml + [accept admin baseline]-marker; budget-doc i docs/engineering/testing/lighthouse-budget.md. Modererat användartest mot 5 icke-tekniska klubbadmins är OWNER-todo (kräver rekrytering + Zoom-sessioner).
✅ PL-T291 - F16.20.15 Shipped
Dual-mode admin-shell — useDeviceClass() växlar mellan desktop-sidebar och mobile bottom-tab + drawer utan route-byte eller data-remount. 5 bottom-tab-slottar (Översikt / Min org / Aktivitet / Ekonomi / Mer). admin/app/(dashboard)/_layout.tsx, admin/src/components/ui/BottomTabNav.tsx.
✅ PL-T156 - F16.20.16 Shipped
Design-system-primitives i admin — Text (Fraunces display + Inter UI via Google Fonts på web), SkeletonBlock, Banner, EmptyState i admin/src/components/ui/. Dashboard-vyn är referensimplementation; breddare sweep över 200+ vyer pågår i owner-todo.
✅ PL-T156 - F16.20.17 Shipped
Tenant-branding injicerad i ThemeProvider — useTenantBranding() hämtar /tenants/{id}/branding vid tenant-byte, ThemeProvider.applyTenantBranding blandar primary-färg med WCAG-aware hover/text/focus-varianter. CSS-var --pl-tenant-primary broadcastas för externa widgets. Dark mode respekterar tenant-primary. admin/src/context/ThemeContext.tsx, admin/src/hooks/useTenantBranding.ts.
✅ PL-T156 - F16.20.18 Shipped
Guided 5-stegs onboarding-tour för tenant-admins — tenant-config → första licens → första medlem → första tävling → första faktura. Dismiss/later + per-tenant-progress i cross-platform storage. Migrerar till UserDashboardPreferences.onboarding_progress när endpointen landar. admin/src/components/OnboardingTour.tsx.
✅ PL-T156 - F16.20.19 Shipped
Onboarding-checklist-widget på dashboard-startsidan — renderar wizard-progressionen (6 steg från /onboarding/status), försvinner när wizard + tour är klara, primary-branded CTA som deep-länkar till wizarden.
✅ PL-T156 - F16.20.20 Shipped
Command palette tillgänglig på mobil — search-ikon i topbaren öppnar samma <CommandPalette> som desktop (⌘K). Modal-layouten skalar till viewport utan separat mobil-komponent.
✅ PL-T156
Visual Regression Pipeline
F16.21**Status:** Pipeline-infrastruktur, deterministisk seed, CI-workflow och dokumentation implementerade i PL-T113.
How it works- F16.21.01 Shipped
tools/visual-regression/ med Playwright-config, projects-matris (Chromium + Firefox + WebKit × mobile/tablet/desktop = 9), shared helpers för deterministisk runtime-freeze.
✅ PL-T113 - F16.21.02 Shipped
Spec-filer per app — www.spec.ts, web.spec.ts, admin.spec.ts, app.spec.ts, sys.spec.ts täcker ~25 nyckelvyer. Routes som tillkommer i framtida tasks markeras med test.skip bakom env-flagga.
✅ PL-T113 - F16.21.03 Shipped
tools/visual-regression/seed.py — drop+återskapa MongoDB-databas med pinnade ObjectIds, slugs och tidsstämplar. RNG seedad till 42, frozen now 2026-01-15T12:00:00Z.
✅ PL-T113 - F16.21.04 Shipped
docker-compose.yml i monorepo-roten — MongoDB + Redis + petanque-api med healthchecks; återanvänds av integration-tester.
✅ PL-T113 - F16.21.05 Shipped
Tids-/RNG-/animation-freeze i webbläsaren via freezeRuntime(page) (init-script innan app-kod kör).
✅ PL-T113 - F16.21.06 Shipped
.github/workflows/visual-regression.yml — PR-triggered, parallell, cachar Playwright-browsers + node_modules. Bryter bygget vid > 0.1 % pixel-diff.
✅ PL-T113 - F16.21.07 Shipped
[accept visual baseline]-marker i commit-meddelande tillåter workflow att köra --update-snapshots och pusha nya baselines tillbaka till PR-branchen.
✅ PL-T113 - F16.21.08 Shipped
HTML-rapport (Playwright reporter) laddas upp som GitHub Actions artifact visual-regression-report (14 dagar retention). PR-kommentar med länk vid fail.
✅ PL-T113 - F16.21.09 Shipped
Tolerance-tröskel maxDiffPixelRatio: 0.001 (0,1 %) global, override per-test för canvas/chart-tunga vyer med dokumenterad motivering.
✅ PL-T113 - F16.21.10 Shipped
Maintenance-rutiner i docs/product/design-system/visual-regression.md (lägg till vy, uppdatera baseline, tolerance, beslutstabellen "uppdatera vs inte").
✅ PL-T113 - F16.21.11 Shipped
Kom-igång lokalt i tools/visual-regression/README.md — quick-start, layout-översikt, troubleshooting-tabell.
✅ PL-T113 - F16.21.12 Planned
Native mobile-screenshot-suite (iOS/Android-simulator) — separat task om web-target visar sig otillräckligt.
Icebox
DPO Compliance Console & Consent Lifecycle
F16.22**Status:** Implemented (PL-T221)
- F16.22.01 Shipped
ConsentScopeDefinition model — granular per-purpose consent definitions versioned per (tenant, scope_key) with monotonic version-bump and auto-superseding. Categories: marketing/analytics/operational/subprocessor/photo/research. Existing user consents stay attributable to the exact text the subject saw.
✅ PL-T221 - F16.22.02 Shipped
DpoAccessRequest model — DSAR-on-behalf with status FSM (draft → submitted → in_review → fulfilled / rejected / cancelled), inline append-only audit_trail mirrored to global AuditLog. Request types: data_export / rectification / erasure / restriction / portability. Mandatory legal_ground.
✅ PL-T221 - F16.22.03 Shipped
DPO console endpoints /dpo/* — 12 endpoints covering consent-scope CRUD + version-history + retire, access-request lifecycle, DSAR-job proxy, cross-tenant overview. Capability-gated on gdpr:dpo:read / gdpr:dpo:write.
✅ PL-T221 - F16.22.04 Shipped
New capabilities gdpr:dpo:read, gdpr:dpo:write — registered in role-template catalog, capability-deny logged to AuditLog with action=capability.deny.
✅ PL-T221 - F16.22.05 Shipped
Admin DPO console — 4 routes (/(dashboard)/dpo overview, /dpo/consent-scopes, /dpo/access-requests kanban, /dpo/cross-tenant) with shared visual primitives. Hidden for affiliate/venue/individual tenant types.
✅ PL-T221 - F16.22.06 Shipped
Cross-tenant DPO overview — in-memory parallel fan-out per tenant the operator holds gdpr:dpo:read in. Returns per-tenant {open_requests, active_scopes} — no automatic cross-tenant DB join. Operator's own tenant always allowed; system-scope tokens get full body.tenants.
✅ PL-T221 - F16.22.07 Shipped
Reusable AuditTrail admin component — shared timeline rendering used by DPO request detail and earmarked for future governance/anti-doping/finance consoles.
✅ PL-T221 - F16.22.08 Shipped
Audit-log integration — DPO-action category=gdpr_dpo, scope-version-action category=gdpr_consent_versioning. Hash-chain (F16.09) garanterar tamper-evidence on the global trail.
✅ PL-T221
No features match your filters.