Integration & API
152 features · 18 subsystems
External system integrations, API strategy, data exchange, and machine-to-machine communication. Provides M2M OAuth2, webhooks, and file import capabilities.
API-klientaxeln, den publika verifieringen: det som FAKTISKT är byggt
F14.00Raderna .01–.09 levererades av **D-PUBAPI `a95566cc.m-1`** (t-1 axeln i API:t, t-2 ytorna),
- F14.00.01 Shipped
M2M-/klientidentiteten — m2m_client utvidgad med kind (developer · federation_integration · service_account), tier, rate_limit_per_minute, is_sandbox, owner_identity_id; status HÄRLEDS ur stämplarna (aldrig en lagrad kolumn)
✅ a95566cc.m-1 t-1 - F14.00.02 Shipped
Nycklarna (api_token) — flera per klient, token_prefix synlig, hemligheten bara som sha-256-hash och visad EXAKT en gång; överlappande rotation
✅ a95566cc.m-1 t-1 - F14.00.03 Shipped
Client-credentials-granten POST /v1/oauth/token (RFC 6749 §4.4, client_secret_basic + client_secret_post), alias POST /auth/m2m/token; varje misslyckande svarar BYTE-IDENTISKT 401 invalid_client (enumerationsskydd)
✅ a95566cc.m-1 t-1 - F14.00.04 Shipped
Fyra grindar per anrop — revocation vid decode (401 invalid_token, OMEDELBAR), IP-allowlist (403 ip_not_allowlisted), scope→capability i authz-UNIONEN (403 insufficient_scope, deny-by-default) och klient-limitern per tier/override/sandbox ×10 (429 rate_limited)
✅ a95566cc.m-1 t-1 - F14.00.05 Shipped
Self-service-nycklar POST/GET/DELETE /v1/developer/keys + /v1/developer/client (människosession, aldrig en M2M-token); PL_DEVELOPER_SIGNUP_ENABLED=false ⇒ 403 registration_disabled
✅ a95566cc.m-1 t-1 - F14.00.06 Shipped
Förbundets klienter /v1/api-clients[...] med scope-katalogen, If-Match-låsning, livscykeln :suspend
:reactivate|:revoke och eskaleringsspärren 422 scope_exceeds_grantor | ✅ a95566cc.m-1 t-1 - F14.00.07 Shipped
Sys-läsytan /v1/sys/developer-platform/clients[...] (cross-tenant, aldrig en hash) + F1-3:s befintliga fresh-auth-gatade servicekonto-CRUD
✅ a95566cc.m-1 t-1 - F14.00.08 Shipped
Ytorna — admin /webhooks-api (sektionen *API-klienter*: tabellen, scope-katalogens kryssrutor, nyckeln vars hemlighet visas en gång, If-Match-redigeringen och livscykeln) och sys /utvecklarplattform (flikarna *Utvecklare* och *Servicekonton*)
✅ a95566cc.m-1 t-2 - F14.00.09 Shipped
Fixturen seed-api-clients — fem klienter genom API:ts egna sömmar, kända hemligheter bara i PL_ENV ∈ {local,test}
✅ a95566cc.m-1 t-1 - F14.00.10 Shipped
Publik, privacy-säker licensverifiering över tenant-gränsen — GET /v1/public/licenses/verify?federation=&license_number=&birth_year=&discipline= (sluten utfalls-enum valid|blocked|expired|not_found, byte-identisk not_found = inget existens-orakel, blocked säger aldrig varför, identitetsavtäckning bara vid valid och publik profil, födelseåret BEKRÄFTAR och ekas aldrig) + GET /v1/public/players/{user_id}/licenses (PII-fri cross-tenant-översikt på husets EGEN auth_identity). Anonyma, taggade cross-tenant-public-read och med i den filtrerade partnerprojektionen; per-avsändartak PL_LICENSE_VERIFY_RATE_MAX (default 300/h, DELAT mellan rutterna), Cache-Control: public, max-age=60 utan ETag. Noll migrationer, noll skrivningar, ingen uppslagshistorik. Fixtur: seed-license-verify. Kontrakt: specs/api/endpoints/public-license-verification.md
✅ a95566cc.m-4 t-1 - F14.00.11 Planned
Batch-/bulk-verifiering (en hel startlista i ett anrop) och en M2M-scope-skopad högvolymyta ovanpå F14.00.10
⊘ a95566cc.m-7/m-8 — öppnas när ett scope motiverar den; m-4:s yta frågar EXAKT ett förbund per anrop med flit - F14.00.12 Shipped
Bulk-exportjobbet — löv-paketet internal/bulkexport (dataset-registryn med kolumner, pii-flaggor, maskeringsregler och ett DEKLARERAT filterschema; strömmande, deterministiska csv/json/xlsx-skrivare där två identiska exporter ger IDENTISKA bytes och samma sha256), migration 00256, capabilityn export:manage som ger YTAN medan datasetets EGEN capability prövas utöver den — BÅDE vid beställningen och en gång till i vågen — POST/GET /v1/exports, GET /v1/exports/{id} med MÄTTA tal, :cancel, och F1-7-vågen bulk_export_run (claim med for update skip locked, batchad läsning, failed:worker_lost bortom PL_BULK_EXPORT_STALE_MINUTES)
✅ a95566cc.m-10 t-1 - F14.00.13 Shipped
Exportmallarna — /v1/export-templates (skapa · lista · läs · If-Match-skriv · :archive · :preview), kolumnmappning husets kolumn → mottagarens rubrik → transform ur en SLUTEN, parametriserad mängd, delad/personlig (403 template_not_owned), och förhandsvisningen på ≤ 20 RIKTIGA rader maskerade som default, utan en enda sidoeffekt
✅ a95566cc.m-10 t-1 - F14.00.14 Shipped
Schemalagda leveranser — /v1/export-schedules (skapa · If-Match-skriv · DELETE · :pause/:resume · :run-now · /deliveries · :retry), sex frekvenser räknade i TENANTENS zon och lagrade i UTC (inget hourly), F1-7-svepet bulk_export_schedule_tick med single-fire som DB-invariant unique (schedule_id, scheduled_for), och tre kanaler med MÄTTA utfall per mottagare (email med LÄNKEN genom husets ENDA utgång + delade spärrlista · webhook genom förbundets EGEN prenumeration · in_app). Beställarens mandat prövas i VÅGEN: har hon förlorat det blir jobbet failed:capability_denied med noll bytes
✅ a95566cc.m-10 t-2 - F14.00.15 Shipped
Retention-begränsade nedladdnings-URL:er — GET /v1/exports/{id}/download?token=… (token-verifierad i handlaren, fungerar ur ett mejl utan session), klartexten lagras ALDRIG (bara sha256), länken mintas i KLICKÖGONBLICKET och den föregående dör samtidigt, :revoke-links dödar varje levande länk, varje fel svarar byte-identiskt 404 (inget uppräkningsorakel), och F1-7-svepet bulk_export_retention_tick river bytesen bortom fristen medan talen och sha256 står kvar för alltid
✅ a95566cc.m-10 t-1/t-2 - F14.00.16 Shipped
Tävlingsexporten — POST/GET /v1/competitions/{id}/exports som SAMMA jobb (source='competition', samma kö, samma frist, samma signerade länk): fipjp_json = husets EGET petanque-life-v1-kuvert (typen competition_results, kanonisk serialisering, exchange.ScanForbidden FÖRE första byten ⇒ inget fullt födelsedatum, ingen adress) och generic_csv = datasetet results genom förbundets egen mall. Läst ur den PUBLICERADE ögonblicksbilden — ett opublicerat resultat följer aldrig med. Plus webhook-typen export.ready (cross_tenant_public: false)
✅ a95566cc.m-10 t-2 - F14.00.17 Shipped
Ytan — admin /dataexport med mockupens fyra export-flikar LEVANDE (*Exportjobb* · *Schemalagda rapporter* · *Exportmallar* · *Tävlingsexport*), nav-postens »någon av«-villkor utvidgat med export:manage, grinden PER FLIK med mandatet i klartext, *Maskera personuppgifter* förvald PÅ med sin bokföringstext, inga förhandsutgråade knappar (serverns 403/422/429 VID åtgärden) och INGEN katalog, frist eller formatetikett i ytan. Vy-spec specs/admin/views/dataexport.md, runbook docs/engineering/runbooks/bulk-export.md, bevis node tools/gate/dpubapi-m10-e2e.mjs
✅ a95566cc.m-10 t-3 - F14.00.18 Shipped
Det signerade, återkallbara widget-tokenet — wgt_<16 hex kortid>.<epok>.<sig> där kortidet är widget-uuid:ts första 64 bitar (genererad kolumn med unikt index ⇒ O(1)-uppslag) och signaturen 16 byte HMAC-SHA256(nyckel, "<kortid>
<epok>"). Epoken ÄR återkallelsen (:regenerate-token höjer den; inget token lagras, så det finns ingenting att radera), formen prövas statlöst FÖRE varje databasfråga (en förfalskningsflod kostar noll store-anrop) och utan PL_WIDGET_TOKEN_SIGNING_KEY är allt fail-closed (503 på skapandet, 404 publikt) — ett osignerat token får aldrig existera | ✅ a95566cc.m-11 t-1 - F14.00.19 Shipped
Den publika familjen på rotnivå, ANONYM: GET /public/widgets/{token} (HTML-dokumentet), …/data (JSON, embed_version på toppnivå, rows alltid en array, CORS * utan credentials) och /public/widgets.js (loadern: beroendefri, < 8 KiB, aldrig innerHTML — grep-vaktat — och en loader per sida oavsett antal widgets). Handlarens ordning är tak → form → uppslag → grind → innehåll → räkning, och varje misslyckande svarar BYTE-IDENTISKT 404 med no-store (ingen skillnad mellan »finns inte«, »pausad« och »fel signatur« — annars vore ytan ett orakel)
✅ a95566cc.m-11 t-1 - F14.00.20 Shipped
Ursprungslistan och taket — allowed_origins blir frame-ancestors i dokumentets CSP (webbläsaren fäller inbäddningen) och prövas mot Origin på JSON-ytan ⇒ 403 origin_not_allowed; en begäran utan Origin släpps igenom med flit (listan skyddar mot obehörig INBÄDDNING, den är inget autentiseringsmedel). Per-IP-taket 3 600/timme (PL_WIDGET_PUBLIC_RATE_MAX) gäller hela familjen utom loadern och körs FÖRST i varje handler
✅ a95566cc.m-11 t-1 - F14.00.21 Shipped
Katalogen, anpassningen och embed-kod-generatorn — GET /v1/widgets/catalog serverar de fyra typerna med sina fält och husets mängder (färger · teman · typsnitt · språk · empty_reasons), kontrasten döms server-side mot WCAG 2.2 AA med den uppmätta kvoten i detail (422 contrast_insufficient), custom_css går genom husets ENDA sanerare (som avvisar, aldrig strippar tyst) och GET /v1/widgets/{id}/embed-code bygger de tre snippetarna (iframe sandboxad utan allow-same-origin · script + mount-div · direktadress) — ytan bygger aldrig en egen. Plus …/stats (värdar, aldrig vägar), …/preview (samma renderare, utan räkning, fungerar även pausad) och F1-7-svepet embed_widget_view_retention_tick
✅ a95566cc.m-11 t-1 - F14.00.22 Shipped
Ytan — admin /inbaddning med mockupens fyra flikar, TVÅ LEVANDE (*Widgets* · *Anpassning & inbäddningskod*) och TVÅ ⊘ MED ÄGARE (*Streaming & video* = F14.14 · *Kartor & geokodning* = F14.11, synliga och aria-disabled — en dold flik är lika osann som en attrapp). Nav-posten 🖇️ gatad på widget:manage, MÄTTA *Visningar 30 d* (»—« utan svar, aldrig 0), den SERVERBYGGDA customization_summary, serverns 422 VID färgfältet och snippetarna tecken för tecken ur servern. Vy-spec specs/admin/views/inbaddning.md, partnerguide docs/engineering/integration-api/widgets.md, bevis node tools/gate/dpubapi-m11-e2e.mjs
✅ a95566cc.m-11 t-2
Public API
F14.01- F14.01.01 Planned
RESTful API with OpenAPI/Swagger documentation — GET /api/info discovery endpoint, enriched OpenAPI metadata (contact, license, terms, tags), Swagger UI at /docs, ReDoc at /redoc
⊘ byggt i den nuvarande stacken av F1-1/F1-8 (/openapi.json, /reference); legacy-raden beskriver FastAPI-Swagger som inte finns - F14.01.02 Planned
API versioning — X-API-Version response header on all responses, /v1/ URL prefix transparency, X-API-Version-Deprecated header for mismatched versions
⊘ X-API-Version finns (F1-1); X-API-Version-Deprecated/Sunset ägs av a95566cc.m-2 - F14.01.03 Shipped
Rate limiting per client — X-RateLimit-Limit/X-RateLimit-Remaining/X-RateLimit-Reset response headers, per-IP sliding window, per-M2M-client configurable limits (1–10 000 req/min), abuse monitor with lockout
✅ a95566cc.m-1 för rate-limit per klient/tier + headers; *abuse monitor with lockout* har ingen ägare (ingen missbruksvakt finns i huset) - F14.01.04 Shipped
M2M OAuth2 client credentials authentication — RFC 6749 §4.4 compliant POST /auth/m2m/token, ES512 JWT, SHA-256 secret hashing, IP CIDR allowlist, secret rotation, admin CRUD
✅ a95566cc.m-1 — granten, hashningen, allowlisten och rotationen; se F14.00.03/.04 - F14.01.05 Planned
Public endpoints (rankings, results, calendar, venue directory) — GET /public/rankings, /public/rankings/{id}, /public/results, /public/results/{competition_id}, /public/venues, /public/venues/{id} with cursor pagination, filters, and search
⊘ D-RANK/D-COMP/D-VENUE äger datan; den publika läsytan har ingen egen D-PUBAPI-leverans ännu - F14.01.06 Planned
API developer portal — POST /api-tokens, scopade M2M-tokens, rate limiting
⊘ delvis: nyckel-self-service finns (F14.00.05) och portalens API-halva är byggd i a95566cc.m-7 t-1 (sandbox-familjen + de tre katalogprojektionerna GET /v1/developer/scope-catalog, …/webhooks/{event-types,policy}, …/deliveries/summary — samma kataloger som förbundsytans, byte-för-byte); PORTALENS SIDOR i web är BYGGDA i a95566cc.m-7 t-3 — de fem rutterna /developers, /developers/nycklar, /developers/sandlada, /developers/webhooks, /developers/referens under PLATTFORMS-chromen (§9b D-9, markören x-pl-devportal), som läser katalogerna ur SERVERN och aldrig bär en egen lista eller ett eget tal. Kvarstående luckor renderas MED ägare i ytan: arkivets kort *Tillgänglighet 99,96 %* som »—« med ägaren F1-8, fakturering BILL, data-produktkatalogen m-8, cursor-pagineringen F14.03.06. Vy-kontraktet specs/web/views/developers-portal.md; bevis node tools/gate/dpubapi-m7-e2e.mjs - F14.01.07 Shipped
API key management — token-livscykel (create, revoke, validate), SHA-256-hash
✅ a95566cc.m-1 — se F14.00.02 - F14.01.08 Planned
API usage analytics and monitoring — ApiUsageRecord hourly buckets, GET /api-usage/summary, /api-usage/by-token, /api-usage/timeseries with per-endpoint breakdowns, latency tracking, and rate-limit hit counting
⊘ a95566cc.m-2 (usage-buckets, rollup-jobb, p50) - F14.01.09 Planned
ERD drill-down explorer — three-tier /erd viewer (super-domain → sub-domain → entity) with breadcrumb, URL-state, fuzzy search, heatmap, BFS radius 1–2, cross-domain-bridge toggle; new JSON endpoints /erd/domains, /erd/domains/{id}, /erd/entities/{name}; project-configurable F01–F20 mapping via SuperDomainConfig
⊘ ingen ägare — ERD-utforskaren fanns bara i det rivna systemet - F14.01.10 Planned
Service-account M2M-tokens with admin scopes — ServiceAccount-modell, ApiScope admin-scopes (tenants:write, federations:write, cms:write, admin_invitations:create, users:write, seed:run), /sys/service-accounts CRUD + token mint/revoke, 90-day default TTL, agent-driven prod-bootstrap utan WebAuthn-step-up
⊘ delvis: servicekontot som identitet + dess nycklar finns (F14.00.07); admin-scope-katalogen tenants:write/seed:run finns INTE — scope-katalogen är kod-deklarerad och läsande i m-1
Federation System Integration
F14.02> **Greenfield-not (D-PUBAPI `a95566cc.m-6`, 2026-09) — TRUPPINLÄMNINGEN är byggd.**
How it works- F14.02.01 Shipped
Data exchange with existing national federation systems — FederationIntegrationConfig CRUD, lifecycle (draft→active→paused→decommissioned), field mapping, sync state
✅ PL-F1402a - F14.02.02 Shipped
File import service (CSV, XML, fixed-width) for legacy data — greenfield: /v1/federation/import-formats (receptet, validerat VID sparandet), POST /v1/federation/imports (RÅA bytes, mätt sha256/mime/size_bytes), :validate (torrkörningen som ett VERB) och :run (skrivpasset bakom fyra villkor). Legacy-radens POST /parse finns INTE: en parsning utan jobbrad lämnar inget spår efter sig
byggt av D-PUBAPI m-9 (a95566cc-serien, federations-/legacy-importen) - F14.02.03 Shipped
FIPJP data submission format support — FipjpSubmission CRUD, canonical envelope, payload validation per type, lifecycle (draft→submitted→accepted/rejected)
✅ PL-F1402a - F14.02.04 Shipped
Continental confederation data exchange — ContinentalExchangeSession CRUD, lifecycle (initiated→in_progress→completed/failed/cancelled), participant tracking
✅ PL-F1402a - F14.02.05 Shipped
Bi-directional sync for federations with existing systems — BidirectionalSyncSession CRUD, lifecycle (pending→pulling→pushing→completed/resolving_conflicts), conflict detection/resolution, per-direction statistics
✅ PL-F1402b - F14.02.06 Shipped
Migration tools for legacy system data import — MigrationJob CRUD, lifecycle (draft→validating→validated→running→completed), batch processing, dry-run, rollback
✅ PL-F1402b - F14.02.07 Shipped
Import validation and error reporting — greenfield: regelmotorn med de fem regeltyperna (required → type → format → range → uniqueness, stannar vid första felet per fält), rapporten som AGGREGAT + sample på jobbets detalj, felmängden …/errors (serverfiltrerad, cursor över hela sorteringen) och …/errors.csv (UTF-8 med BOM, åtta kolumner)
byggt av D-PUBAPI m-9 (a95566cc-serien, federations-/legacy-importen)
Webhooks & Events
F14.03- F14.03.01 Shipped
Webhook configuration (outbound) — prenumerations-CRUD på POST /v1/webhooks (förbundet) och POST /v1/developer/webhooks (utvecklaren), :pause/:resume/:enable
byggt av a95566cc.m-3 - F14.03.02 Shipped
Event types — competition.created/completed, result.published, license.issued/transferred, ranking.updated, sanction.created som SLUTEN kod-katalog (api/internal/webhook/catalog.go), serverad av GET /v1/webhooks/event-types
byggt av a95566cc.m-3 - F14.03.03 Planned
~~Retry med exponential backoff (max 5 försök, 10s×n²)~~ — LEGACY-formeln gäller inte. Den byggda trappan är F14.03.09:s: max 8 försök, bas 30 s, kapad vid 1 h. Bokfört val (webhook.MaxAttempts/BaseDelay med källan vid raden)
LEGACY — ersatt av F14.03.09 - F14.03.04 Shipped
HMAC-SHA256-signering + :rotate-secret med 24 h överlappande dubbelsignering; hemligheten FÖRSEGLAD i databasen och läsbar exakt en gång
byggt av a95566cc.m-3 - F14.03.05 Shipped
Petanque-specifik händelsekatalog (7 prenumererbara typer + den syntetiska test.ping)
byggt av a95566cc.m-3 - F14.03.06 Shipped
Delivery log per prenumeration + :test-endpoint (5/min) + manuell :replay/:replay-dlq; KPI-summan på GET /v1/webhooks/deliveries/summary
byggt av a95566cc.m-3
Third-Party Integrations
F14.04- F14.04.01 Shipped
Payment gateway integration (Stripe, PayPal, Swish, iDEAL, etc.) — PaymentGatewayIntegration CRUD, lifecycle (draft→active→paused→decommissioned), key-vault credential refs, multi-currency, sandbox mode, usage tracking, validation
✅ PL-F1404a - F14.04.02 Shipped
Calendar integration (Google Calendar, Outlook, iCal) — CalendarIntegration CRUD, lifecycle, OAuth/API-key refs, sync direction (push/pull/bidirectional), sync state tracking, event type filtering
✅ PL-F1404a - F14.04.03 Shipped
Social media API integration (Facebook, Instagram, X) — SocialMediaIntegration CRUD, lifecycle, OAuth refs, page/account management, publish/analytics/moderation capabilities, auto-publish events
✅ PL-F1404a - F14.04.04 Shipped
Video streaming platform integration (YouTube, Twitch) — StreamingIntegration CRUD, lifecycle, API/stream-key refs, channel management, RTMP URL, DVR/chat/auto-record config
✅ PL-F1404a - F14.04.05 Shipped
Mapping/geolocation services (Google Maps, Mapbox) — MappingIntegration CRUD, lifecycle, API-key refs, geocoding/directions/static-maps/places-search toggles, domain allowlist, usage budget
✅ PL-F1404a - F14.04.06 Shipped
WADA/ADAMS integration for anti-doping — WadaAdamsIntegration CRUD, lifecycle (draft→active→paused→decommissioned), ADAMS API/signing-key refs, organization/sport codes, athlete pool management, whereabouts sync, TUE management, test result tracking, notification relay
✅ PL-F1404b - F14.04.07 Shipped
Insurance provider API integration — InsuranceIntegration CRUD, lifecycle, API/OAuth credential refs, broker/policy group IDs, coverage types, auto-enrollment, claims submission, premium calculation, certificate generation, sandbox mode
✅ PL-F1404b - F14.04.08 Shipped
Government sports registry integration (per country) — GovSportsRegistryIntegration CRUD, lifecycle, API/signing-certificate refs, federation code, country code (auto-uppercased), membership reporting, grant applications, facility registration, event reporting, compliance tracking, reporting schedule
✅ PL-F1404b - F14.04.09 Shipped
Accounting software integration (Fortnox, Xero, QuickBooks) — AccountingIntegration CRUD, lifecycle, OAuth/API-key refs, company ID, fiscal year config, sync direction (push/pull/bidirectional), chart of accounts mapping, invoice/payment/expense sync, VAT reporting, sandbox mode
✅ PL-F1404b
Data Export & Reporting
F14.05> **Raderna nedan beskriver det RIVNA PL-F1405-systemet.** Bulk-exporten är ombyggd rent i
How it works- F14.05.01 Shipped
Bulk data export (CSV, JSON, Excel) — ExportJob CRUD, CSV/JSON/Excel format, configurable filters & columns, download lifecycle
✅ a95566cc.m-10 — byggd rent i Go/Postgres; se F14.00.12 (raden beskriver det RIVNA PL-F1405-systemet) - F14.05.02 Shipped
Scheduled report generation and delivery — ScheduledExportJob CRUD, 6 frekvenser, pause/resume/trigger, webhook + e-post-leverans
✅ a95566cc.m-10 — se F14.00.14; bokförd avvikelse: kanalen är en PRENUMERATION, aldrig en URL i schemat, och brevet bär LÄNKEN, aldrig en bilaga - F14.05.03 Shipped
Custom export templates — ExportTemplate CRUD, kolumnmappning med transform, delad/personlig, delimiter/encoding-konfiguration
✅ a95566cc.m-10 — se F14.00.13 - F14.05.04 Planned
Competition result export (federation-specific formats) — CompetitionExportJob, SBP CSV, FFPJP XML, DPV CSV, FIPJP JSON, generic CSV
⊘ delvis a95566cc.m-10 — fipjp_json (husets EGET petanque-life-v1-kuvert) och generic_csv (mallstyrd) är byggda (F14.00.16); sbp_csv · ffpjp_xml · dpv_csv byggs INTE: mottagarnas filscheman är okända i huset, och ett påhittat schema importeras TYST hos mottagaren. De står SYNLIGT i katalogen med sitt skäl och en väg som finns (422 competition_format_unavailable + use_instead: generic_csv) - F14.05.05 Shipped
GDPR data portability export — GdprPortabilityExport, Art. 20, JSON/CSV, 48h-utgång, dubblettskydd, nedladdningsspårning
✅ PL-F1405 - F14.05.06 Planned
Open data feeds (public statistics, rankings) — OpenDataFeed CRUD, JSON/CSV/RSS/Atom, slug-baserad åtkomst, caching, accessräknare
⊘ ägarbeslut — de publika, oautentiserade läsytorna (rankings, kalender, resultat) och D-COMM:s syndikeringsflöden ÄR husets öppna data (visionens scope-tillägg 2026-07-09: *»open-data har redan ägare«*). En förvaltningsyta för förbundets EGNA flöden är ett beslut, inte en glömd flik; fliken *Öppna data* på /dataexport står ⊘ med den ägaren
Embedding & Widgets
F14.06> **Raderna nedan beskriver det RIVNA PL-F1406-systemet.** De inbäddningsbara widgetarna är
How it works- F14.06.01 Shipped
Embeddable results widget for federation/club websites — WidgetConfig (type: results), GET /public/widgets/{token} returns published CompetitionResult data with embed-friendly headers, tenant-scoped, configurable columns (balls, club)
✅ a95566cc.m-11 — byggd rent i Go/Postgres; se F14.00.19 (raden beskriver det RIVNA PL-F1406-systemet) - F14.06.02 Shipped
Embeddable calendar widget — WidgetConfig (type: calendar), queries CalendarEvent with date range, event type filter, federation/club filter, configurable months ahead
✅ a95566cc.m-11 — se F14.00.19/.21; källan är kalenderdomänens EGEN publika söm - F14.06.03 Shipped
Embeddable ranking widget — WidgetConfig (type: ranking), queries RankingEntry by config/dimension/category, show/hide club and rank change columns
✅ a95566cc.m-11 — se F14.00.21; bokförd avvikelse: källan är en PUBLIK, aktiv D-RANK-preset (preset_slug), och en icke-publik preset ger ett ärligt tomläge preset_not_public — aldrig en rad - F14.06.04 Shipped
Embeddable live score widget — WidgetConfig (type: live_score), queries Match for in_progress/scheduled matches, mène detail, court assignment, auto-refresh config
✅ a95566cc.m-11 — se F14.00.19; auto_refresh_seconds 5—60, pollen armeras EN gång per montering - F14.06.05 Shipped
Widget customization (colors, branding) — WidgetCustomization with full color palette (8 colors), branding (logo, powered-by, custom footer), theme (light/dark/custom), size, locale, border radius, font family, max items, custom CSS
✅ a95566cc.m-11 — se F14.00.21; bokförd skärpning: kontrasten DÖMS av servern (WCAG 2.2 AA, 4,5:1) med den uppmätta kvoten i svaret, och custom_css avvisas — aldrig strippas tyst - F14.06.06 Shipped
Widget embed code generator — POST /widgets/{id}/embed-code and GET /public/widgets/{token}/embed-code, generates iframe snippet (sandbox, lazy-load, referrerpolicy), JavaScript snippet, and direct URL with configurable dimensions
✅ a95566cc.m-11 — se F14.00.21; bokförd avvikelse: generatorn är GET /v1/widgets/{id}/embed-code (en LÄSNING, inte en POST) och den publika …/embed-code finns INTE — en anonym yta ska inte generera inbäddningskod åt någon annans widget
Stripe Deep Integration
F14.07- F14.07.01 Shipped
Stripe Payment Intents — StripePaymentIntent-samling tenant-scopad med stripe_payment_intent_id/stripe_client_secret/invoice_id/payment_id/amount/currency/status (requires_payment_method/requires_confirmation/requires_action/processing/succeeded/canceled/requires_capture)/payment_method_types/capture_method (automatic/manual)/metadata (StripePaymentIntentMetadata invoice_id/debtor_id/debtor_type/fee_category/season_id/custom)/connected_account_id/application_fee_amount/requires_action/description/stripe_customer_id; CRUD /stripe/payment-intents/ med filtrering status/invoice_id, confirm/capture/cancel/sync-endpoints
✅ PL-F1407 - F14.07.02 Shipped
Stripe Connect — StripeTenantConnectAccount-samling tenant-scopad med stripe_account_id/account_type (standard/express/custom)/status (pending/onboarding/active/restricted/disabled)/entity_type (federation/club/org_node)/entity_id/country/default_currency/display_name/onboarding (StripeConnectOnboarding requirements_due/payouts_enabled/charges_enabled/details_submitted)/platform_fee_percent; CRUD /stripe/connect/ med filtrering status/entity_type, account-link/refresh/disable-endpoints
✅ PL-F1407 - F14.07.03 Shipped
Stripe Webhooks — StripeWebhookEvent-samling tenant-scopad med stripe_event_id/event_type/status (received/verified/failed_verification/processed/processing_failed)/signature_valid/idempotency_key/payload/processing_error; POST /stripe/webhooks/ med signaturverifiering mot STRIPE_WEBHOOK_SECRET, idempotens-kontroll, dispatch till handlers (payment_intent.succeeded/failed/canceled/requires_action, charge.refunded, refund.updated, account.updated); GET /stripe/webhooks/events för audit-loggning
✅ PL-F1407 - F14.07.04 Shipped
Stripe SCA / 3D Secure — StripeScaChallenge-samling tenant-scopad med stripe_payment_intent_id/status (not_required/required/initiated/succeeded/failed)/three_ds_version/authentication_flow (challenge/frictionless)/failure_reason/initiated_at/completed_at; CRUD /stripe/sca/, POST /stripe/sca/{stripe_pi_id}/complete med success/failure_reason
✅ PL-F1407 - F14.07.05 Shipped
Stripe Refunds — StripeRefund-samling tenant-scopad med stripe_refund_id/stripe_payment_intent_id/invoice_id/refund_type (full/partial)/amount/currency/status (pending/succeeded/failed/canceled/requires_action)/reason (duplicate/fraudulent/requested_by_customer)/description; CRUD /stripe/refunds/ med filtrering status/invoice_id/payment_intent_id, sync-endpoint
✅ PL-F1407 - F14.07.06 Shipped
Stripe Tax — StripeTaxConfig-samling tenant-scopad med country/tax_behavior (inclusive/exclusive)/tax_code/tax_id/tax_id_type/automatic_tax_enabled/tax_rates[StripeTaxRate display_name/percentage/inclusive/country/tax_type/stripe_tax_rate_id]/tax_registrations[]/head_office_address/status (active/inactive/deleted); CRUD /stripe/tax/configs, registrations/sync-rates/calculate-endpoints med per-tenant momsberäkning (SE 25% exclusive, FR 20% inclusive, DE 19% exclusive)
✅ PL-F1407
PayPal Deep Integration
F14.08- F14.08.01 Shipped
PayPal Checkout — PayPalOrder-samling tenant-scopad med paypal_order_id/intent (capture/authorize)/status (created/saved/approved/voided/completed/payer_action_required)/invoice_id/payment_id/amount/currency/purchase_units[PayPalPurchaseUnit]/payer_email/payer_id/capture_id/authorization_id/approval_url/metadata (PayPalOrderMetadata invoice_id/debtor_id/debtor_type/fee_category/season_id/custom)/brand_name/sandbox/express_profile_id; CRUD /paypal/orders/ med filtrering status/invoice_id/payer_id, capture/void/sync-endpoints
✅ PL-F1408 - F14.08.02 Shipped
PayPal IPN/Webhooks — PayPalWebhookEvent-samling tenant-scopad med paypal_event_id/event_type/resource_type/status (received/verified/failed_verification/processed/processing_failed)/signature_valid/idempotency_key/related_resource_id/related_order_id/webhook_id/processing_error; POST /paypal/webhooks/ med signaturverifiering via PayPal Notifications API, idempotens-kontroll, dispatch till handlers (CHECKOUT.ORDER.APPROVED/COMPLETED/DECLINED, PAYMENT.CAPTURE.COMPLETED/DENIED/REFUNDED/REVERSED/PENDING); GET /paypal/webhooks/events för audit-loggning
✅ PL-F1408 - F14.08.03 Shipped
PayPal Refunds — PayPalRefund-samling tenant-scopad med paypal_refund_id/paypal_capture_id/paypal_order_id/order_doc_id/invoice_id/refund_type (full/partial)/amount/currency/status (pending/completed/failed/cancelled)/reason/note_to_payer/seller_payable_breakdown; CRUD /paypal/refunds/ med filtrering status/capture_id/order_id/invoice_id, sync-endpoint
✅ PL-F1408 - F14.08.04 Shipped
PayPal Express för one-click — PayPalExpressProfile-samling tenant-scopad med user_id/paypal_payer_id/payer_email/payment_token (vault token)/consent_status (pending/active/revoked/expired)/display_name/preferred/last_used_at; CRUD /paypal/express/profiles med activate/revoke/set-preferred-endpoints, integration med PayPal Vault API för sparade betalningskällor
✅ PL-F1408
Local Payment Methods
F14.09- F14.09.01 Shipped
Swish QR-betalningar (Sverige) — SwishPaymentRequest-samling tenant-scopad med swish_instruction_uuid indexed/payee_alias/payer_alias/amount Decimal/currency SEK/message (max 50)/status (created/paid/declined/error/cancelled)/qr_code_data base64/qr_format/callback_url/invoice_id/payment_id/payment_reference/payer_payment_reference/error_code/error_message/paid_at/metadata (SwishPaymentMetadata invoice_id/debtor_id/debtor_type/fee_category/season_id/custom); CRUD /swish/payments/ med filtrering status/invoice_id, cancel/sync-endpoints; valutavalidering (enbart SEK); QR-kodgenerering vid skapande
✅ PL-F1409a - F14.09.02 Shipped
Swish webhook callbacks — SwishCallbackEvent-samling tenant-scopad med swish_instruction_uuid indexed/event_status (PAID/DECLINED/ERROR/CANCELLED)/callback_identifier indexed för idempotens/status (received/verified/processed/processing_failed)/payload_summary saniterad/processing_error/payer_alias/payment_reference/amount/date_paid; POST /swish/callbacks/ tar emot Swish-callbacks med idempotens-kontroll, dispatch till handlers som uppdaterar SwishPaymentRequest och skapar Payment+Receipt vid PAID; GET /swish/callbacks/events för audit-loggning
✅ PL-F1409a - F14.09.03 Shipped
iDEAL (Nederländerna) — IDealPayment-samling tenant-scopad med ideal_transaction_id indexed/provider (stripe/mollie)/provider_payment_id/bank_bic/bank_name/amount Decimal/currency EUR/status (created/pending/succeeded/failed/expired/canceled)/invoice_id/payment_id/redirect_url/return_url/webhook_url/description/metadata (IDealPaymentMetadata)/succeeded_at/failed_at/error_code/error_message; CRUD /ideal/payments/ med filtrering status/invoice_id, sync-endpoint, webhook-endpoint; valutavalidering (enbart EUR); skapar Payment+Receipt vid succeeded
✅ PL-F1409a - F14.09.04 Shipped
Bancontact (Belgien) — BancontactPayment-samling tenant-scopad med bancontact_transaction_id indexed/provider (stripe/mollie)/provider_payment_id/cardholder_name/preferred_language (nl/fr/de/en)/amount Decimal/currency EUR/status (created/pending/authorized/succeeded/failed/expired/canceled)/invoice_id/payment_id/redirect_url/return_url/description/metadata (BancontactPaymentMetadata)/succeeded_at/failed_at/error_code/error_message; CRUD /bancontact/payments/ med filtrering status/invoice_id, sync-endpoint, webhook-endpoint; valutavalidering (enbart EUR); skapar Payment+Receipt vid succeeded
✅ PL-F1409a - F14.09.05 Shipped
Bizum (Spanien) — BizumPayment-samling tenant-scopad med bizum_transaction_id indexed/provider (stripe/redsys)/provider_payment_id/payer_phone/amount Decimal/currency EUR/status (created/pending/paid/failed/cancelled/timeout)/qr_code_data base64/qr_format/invoice_id/payment_id/redirect_url/return_url/description/metadata (BizumPaymentMetadata)/paid_at/failed_at/error_code/error_message; CRUD /bizum/payments/ med filtrering status/invoice_id, sync-endpoint, webhook-endpoint; valutavalidering (enbart EUR); QR-kodgenerering; skapar Payment+Receipt vid paid
✅ PL-F1409b - F14.09.06 Shipped
SEPA Direct Debit (EUR-länder) — SepaDirectDebitPayment-samling tenant-scopad med sepa_transaction_id indexed/provider (stripe/mollie)/provider_payment_id/mandate_id indexed/mandate_status (pending/active/revoked/expired)/debtor_iban/debtor_name/creditor_id/amount Decimal/currency EUR/status (pending/authorized/processing/succeeded/failed/reversed/cancelled)/sequence_type (OOFF/RCUR/FRST/FNAL)/invoice_id/payment_id/description (max 140)/return_url/redirect_url/return_code (R01-R99)/metadata (SepaDirectDebitMetadata)/succeeded_at/failed_at/error_code/error_message; CRUD /sepa-direct-debit/payments/ med filtrering status/invoice_id/mandate_id, sync-endpoint, webhook-endpoint; mandathantering; SEPA-returkoder; valutavalidering (enbart EUR); skapar Payment+Receipt vid succeeded
✅ PL-F1409b - F14.09.07 Shipped
Klarna BNPL (EU) — KlarnaPayment-samling tenant-scopad med klarna_order_id indexed/provider (klarna/stripe)/provider_payment_id/klarna_session_id/purchase_country (18 länder)/purchase_language/amount Decimal/currency (EUR/SEK/NOK/DKK/GBP/USD/CHF/PLN/CZK)/status (created/authorized/captured/failed/cancelled/expired)/payment_type (pay_later/pay_over_time/direct_debit/direct_bank_transfer)/installment_count (2–36)/invoice_id/payment_id/redirect_url/return_url/description/customer_email/metadata (KlarnaPaymentMetadata)/authorized_at/captured_at/failed_at/error_code/error_message; CRUD /klarna/payments/ med filtrering status/invoice_id/payment_type, capture-endpoint, sync-endpoint, webhook-endpoint; lands- och valutavalidering; tvåstegsflöde (authorize→capture); skapar Payment+Receipt vid captured
✅ PL-F1409b
Bokföringsintegrationer
F14.10- F14.10.01 Shipped
Fortnox API (Sverige) — AccountingProviderConfig (provider=fortnox) med FortnoxConfig (client_id_ref/client_secret_ref/access_token_ref/refresh_token_ref/company_id/default_account_plan BAS2024/auto_create_customers/auto_bookkeep_invoices); AccountingSyncJob för batch-push av fakturor/betalningar/kunder till Fortnox API med idempotent AccountingSyncMapping, hashbaserad ändringsdetektering, dry-run-stöd; AccountingWebhookEvent med HMAC-SHA256-signaturverifiering för Fortnox webhooks
✅ PL-F1410 - F14.10.02 Shipped
Xero API (internationell) — AccountingProviderConfig (provider=xero) med XeroConfig (client_id_ref/client_secret_ref/access_token_ref/refresh_token_ref/xero_tenant_id/tracking_category_id/auto_create_contacts/branding_theme_id); faktura/betalning/kontakt-sync till Xero REST API, OAuth2-tokenhantering, webhook-mottagning med idempotens
✅ PL-F1410 - F14.10.03 Shipped
Visma eEkonomi (Sverige) — AccountingProviderConfig (provider=visma) med VismaConfig (client_id_ref/client_secret_ref/access_token_ref/refresh_token_ref/company_id/fiscal_year_id/auto_create_customers); faktura/betalning/kund-sync till Visma eAccountingAPI
✅ PL-F1410 - F14.10.04 Shipped
QuickBooks (US/UK) — AccountingProviderConfig (provider=quickbooks) med QuickBooksConfig (client_id_ref/client_secret_ref/access_token_ref/refresh_token_ref/realm_id/minor_version/sandbox_mode/auto_create_customers); faktura/betalning/kund-sync till QuickBooks Online API
✅ PL-F1410 - F14.10.05 Shipped
SIE4-fil-export (svensk standard) — SIE4Export med livscykel (pending→generating→completed/failed), #FLAGGA 0/#PROGRAM/#FORMAT PC8/#GEN/#SIETYP 4/#FNR/#FNAMN/#RAR/#KONTO/#IB/#UB/#VER/#TRANS; konfigurerbar räkenskapsår, datumfilter, öppnings-/stängningssaldon, periodbalans; POST /accounting/sie4-exports/ genererar och returnerar metadata, GET .../download returnerar filinnehåll
✅ PL-F1410 - F14.10.06 Shipped
Per-tenant kontoplansmappning — ProviderAccountMapping med livscykel (draft→active→archived), AccountMappingRule (internal_category/internal_account_number/provider_account_code/provider_account_name/vat_code/cost_centre), validering (dubbletter, numerisk kontroll för Fortnox), BAS2024-standardmappningar för 8 kategorier (licensavgifter/tävlingsavgifter/klubbavgifter/medlemsavgifter/sponsorintäkter/bidrag/resekostnader/förbrukningsinventarier), sync-to-provider
✅ PL-F1410
Kart- och geokod-integrationer
F14.11- F14.11.01 Shipped
Google Maps embed för venue-sidor — MapEmbedConfig-samling tenant-scopad med venue_id/embed_type (google_maps_embed/google_maps_static/mapbox_gl/mapbox_static/openstreetmap)/style (MapEmbedStyle zoom/map_type/width/height/show_marker/marker_label/custom_style_url)/mapping_integration_id/show_nearby_clubs/nearby_radius_km/show_directions_link/show_street_view/custom_marker_icon_url; GET /geo/venues/{venue_id}/embed genererar embed-URL med adress, koordinater och directions-länk; GET /geo/venues/{venue_id}/embed-config + PATCH för konfigurationshantering
✅ PL-F1411 - F14.11.02 Shipped
Mapbox alternativ med vector tiles — Mapbox GL JS-konfiguration med style_url (mapbox://styles/mapbox/streets-v12), center, zoom, markers; generate_mapbox_embed_config() returnerar fullständig klientkonfiguration; generate_mapbox_static_url() för statiska kartbilder via Mapbox Static Images API; stöd för OpenStreetMap som gratis fallback utan API-nyckel
✅ PL-F1411 - F14.11.03 Shipped
Geocoding för venue-adresser — GeocodingResult-samling tenant-scopad med direction (forward/reverse)/provider (google_maps/mapbox/openstreetmap/here)/input_address/coordinates (GeoCoordinates lat/lng)/address (GeocodedAddress formatted_address/street/city/postal_code/country/country_code/region)/confidence 0.0–1.0/cached_at/expires_at/mapping_integration_id; POST /geo/geocode med cachning, provider-val och integration mot MappingIntegration
✅ PL-F1411 - F14.11.04 Shipped
Reverse geocoding för spelarposition — POST /geo/reverse-geocode med lat/lng input, cachning med ~100m bounding-box matchning, returnerar GeocodedAddress med strukturerad adress; stöd för Google Maps och Mapbox providers; tenant-scopad cachning med TTL
✅ PL-F1411 - F14.11.05 Shipped
Route-beräkning till tävlingsvenues — RouteCalculation-samling tenant-scopad med provider/travel_mode (driving/walking/cycling/transit)/origin (GeoCoordinates)/destination (GeoCoordinates)/venue_id/status (ok/not_found/zero_results/error)/summary (RouteSummary total_distance_m/total_duration_s/total_distance_km/total_duration_min)/steps[RouteStep]/polyline/cached_at/expires_at; POST /geo/route med haversine-baserad uppskattning, cachning med ~500m tolerans
✅ PL-F1411 - F14.11.06 Shipped
Klubb-finder med radius-sökning — GET /public/clubs/nearby publik endpoint utan autentisering med lat/lng/radius_km (0.5–500)/level/facilities (kommaseparerad)/skip/limit (1–100); bounding-box pre-filter på venue-koordinater sedan exakt haversine-avstånd; resultat sorterade efter avstånd (närmast först); ClubFinderResult med club_id/club_name/club_code/distance_km/location/address/city/facilities/level/venue_id/venue_name; cross-tenant som standard, tenant-scopad med valfri tenant_id-parameter
✅ PL-F1411
Anti-doping system-integration
F14.12- F14.12.01 Shipped
WADA ADAMS export — AdamsIntegrationConfig-samling tenant-scopad med display_name/credentials (AdamsCredentialRefs api_key_ref/api_secret_ref/signing_key_ref/endpoint_url)/organisation_code/sport_code/enable_athlete_export/enable_whereabouts_sync/enable_test_result_import/enable_tue_sync/registered_testing_pool_ids/testing_pool_ids/sandbox_mode; CRUD /anti-doping/adams-configs/ med enable/disable-endpoints; AdamsExportJob-samling tenant-scopad med config_id/entity_type (athlete_profile/whereabouts/test_result/tue_application/sanction)/status (pending/exporting/completed/completed_with_errors/failed/cancelled)/dry_run/statistics (AdamsExportStatistics total/succeeded/failed/skipped)/results[AdamsExportResult]; CRUD /anti-doping/export-jobs/ med run/cancel-endpoints; hashbaserad ändringsdetektering för idempotent export
✅ PL-F1412 - F14.12.02 Shipped
Whereabouts upload — WhereaboutsRecord-samling tenant-scopad med player_id/adams_athlete_id/quarter_year/quarter_number/entries[WhereaboutsEntry slot_date/slot_type (overnight/training/competition/other/sixty_minute)/start_time/end_time/address/city/country_code]/status (draft/submitted/confirmed/rejected/expired/cancelled)/submitted_at/confirmed_at/rejected_reason/adams_submission_id/sync_hash; CRUD /anti-doping/whereabouts/ med submit/confirm/reject-livscykel; tidsvalidering HH:MM, auto-uppercase country_code
✅ PL-F1412 - F14.12.03 Shipped
Test result import — TestResultImport-samling tenant-scopad med player_id/adams_test_id/source_provider (NadoProvider)/source_reference/detail (TestResultDetail sample_code/sample_type/collection_date/lab_name/lab_code/substances_detected/result_code/b_sample_requested/b_sample_result)/test_type/competition_id/status (received/validated/processed/failed/rejected)/linked_doping_test_id/idempotency_key; CRUD /anti-doping/test-results/ med validate/process-livscykel; process skapar DopingTest-record med korrekt resultatmappning (negative/adverse→positive/atypical/pending); idempotens via idempotency_key
✅ PL-F1412 - F14.12.04 Shipped
TUE application sync — TueSyncRecord-samling tenant-scopad med tue_application_id/player_id/direction (push/pull)/status (pending/syncing/synced/failed/conflict)/adams_tue_id/adams_status/sync_hash/conflict_field/local_value/remote_value; CRUD /anti-doping/tue-syncs/ med execute-endpoint; push exporterar lokal TUE till ADAMS, pull hämtar ADAMS-beslut och uppdaterar lokalt; konfliktdetektering
✅ PL-F1412 - F14.12.05 Shipped
Per-nation anti-doping-byrå-koppling — NadoConfig-samling tenant-scopad med provider (rf_antidoping/afld/nada_de/ukad/usada/nadof/nada_at/wada/other)/country_code (auto-uppercase)/contact (NadoContactInfo organisation_name/website/email/phone/address/dco_contact_email/reporting_portal_url)/has_api/api_key_ref/api_endpoint_url/code_version/whereabouts_required/tue_committee_email/notify_on_adverse_finding/notify_on_whereabouts_failure; CRUD /anti-doping/nado-configs/ med enable/disable-endpoints; GET /defaults returnerar standardkonfigurationer för SE/FR/DE; AntiDopingWebhookEvent-samling med HMAC-SHA256-signaturverifiering per provider, idempotens-kontroll, dispatch till handlers (test_result.*/tue.*/whereabouts.*); POST /anti-doping/webhooks/{provider} + GET /anti-doping/webhooks/events audit-logg
✅ PL-F1412
Kommunikationsintegrationer
F14.13- F14.13.01 Shipped
SendGrid transactional email — SendGridConfig-samling tenant-scopad med display_name/credentials (SendGridCredentialRefs api_key_ref/webhook_signing_key_ref)/from_email/from_name/reply_to_email/enable_open_tracking/enable_click_tracking/enable_unsubscribe_tracking/ip_pool_name/sandbox_mode/usage (UsageMetrics); CRUD /communication/sendgrid/configs/ med livscykel (draft→active→paused→error→decommissioned); EmailMessage-samling med config_id/provider/to[EmailRecipient]/subject/template_id/template_data/body_text/body_html/status/engagement (EmailEngagementMetrics)/bounce_type/idempotency_key; POST /communication/sendgrid/emails/ skickar via SendGrid v3 API
✅ PL-F1413 - F14.13.02 Shipped
ELKS SMS för svenska nummer — ElksConfig-samling tenant-scopad med display_name/credentials (ElksCredentialRefs api_username_ref/api_password_ref)/sender_id (max 11 tecken GSM)/default_country_code (+46)/dlr_callback_url/usage; SmsMessage-samling med direction (outbound/inbound)/from_number/to (SmsRecipient)/body (max 1600)/segments/cost_amount/cost_currency SEK/idempotency_key; POST /communication/elks/sms/ skickar via 46elks API
✅ PL-F1413 - F14.13.03 Shipped
Firebase Cloud Messaging för push — FcmConfig-samling tenant-scopad med credentials (FcmCredentialRefs service_account_json_ref/project_id)/default_ttl_seconds/default_priority/usage; PushNotification-samling med target (PushTarget device_token/platform/player_id)/topic/title/body/image_url/data/priority/ttl_seconds/collapse_key/badge_count/sound/click_action/idempotency_key; POST /communication/fcm/push/ skickar via FCM v1 API
✅ PL-F1413 - F14.13.04 Shipped
Twilio SMS som international fallback — TwilioConfig-samling tenant-scopad med credentials (TwilioCredentialRefs account_sid_ref/auth_token_ref/messaging_service_sid)/from_number E.164/status_callback_url/supported_countries[]/usage; SmsMessage (delad med ELKS) med provider=twilio; POST /communication/twilio/sms/ skickar via Twilio Messages API
✅ PL-F1413 - F14.13.05 Shipped
Mailgun som backup till SendGrid — MailgunConfig-samling tenant-scopad med credentials (MailgunCredentialRefs api_key_ref/webhook_signing_key_ref/domain/region eu
us)/from_email/from_name/enable_tracking/enable_click_tracking/test_mode/usage; EmailMessage (delad med SendGrid) med provider=mailgun; POST /communication/mailgun/emails/ skickar via Mailgun v3 API | ✅ PL-F1413 - F14.13.06 Shipped
WhatsApp Business API för notiser — WhatsAppConfig-samling tenant-scopad med credentials (WhatsAppCredentialRefs access_token_ref/phone_number_id/business_account_id/webhook_verify_token_ref)/display_phone_number/business_name/default_language_code BCP 47/usage; WhatsAppMessage-samling med to (WhatsAppRecipient)/message_type (template/text)/template_name/template_language/template_parameters[]/body_text/media_url/read_at/idempotency_key; POST /communication/whatsapp/messages/template och /text skickar via WhatsApp Cloud API v18.0; CommunicationWebhookEvent med signaturverifiering (HMAC-SHA256/SHA1), idempotens-kontroll, dispatch till email/sms/whatsapp-handlers
✅ PL-F1413
Streaming & Video Integrations
F14.14- F14.14.01 Shipped
YouTube Live embed — YouTubeLiveEmbed-samling tenant-scopad med name/channel_id/video_id/api_key_ref/privacy (public/unlisted/private)/player_params (YouTubePlayerParams autoplay/mute/controls/loop/modest_branding/rel/fs/cc_load_policy)/embed_width/embed_height/responsive/allowed_domains/competition_id/live_chat_embed/enabled; CRUD /youtube-embeds/ med filtrering enabled/competition_id; GET /{id}/embed genererar embed-URL och iframe-HTML med responsiv 16:9 container; GET /{id}/validate validerar konfiguration (video_id/channel_id-format); live chat iframe-URL vid live_chat_embed=true
✅ PL-F1414 - F14.14.02 Shipped
Twitch embed — TwitchEmbed-samling tenant-scopad med name/channel_name/video_id/collection_id/layout (video/video_with_chat)/player_params (TwitchPlayerParams autoplay/muted/allow_fullscreen/time)/parent_domains (obligatorisk)/embed_width/embed_height/responsive/competition_id/theme (dark/light)/enabled; CRUD /twitch-embeds/ med filtrering enabled/competition_id; GET /{id}/embed genererar embed-URL med parent-domain-säkerhet; GET /{id}/validate validerar channel_name-format och parent_domains; chat-embed-URL vid layout=video_with_chat
✅ PL-F1414 - F14.14.03 Shipped
RTMP relay-konfiguration — RtmpRelayConfig-samling tenant-scopad med name/status (draft/active/paused/error/decommissioned)/ingest_protocol (rtmp/rtmps/srt)/ingest_url/ingest_key_ref/destinations[RtmpRelayDestination name/platform/rtmp_url/stream_key_ref/enabled/bitrate_kbps/resolution] (max 5)/max_bitrate_kbps/transcoding_enabled/recording_enabled/competition_id; CRUD /rtmp-relays/ med filtrering status/competition_id; livscykel activate/pause/decommission med statusvakter (409); URL-validering (rtmp://rtmps://srt://)
✅ PL-F1414 - F14.14.04 Shipped
Stream metadata API — StreamMetadata-samling tenant-scopad med title/stream_type (live/vod/clip)/status (scheduled/live/ended/processing/available/error/archived)/platform/platform_stream_id/platform_url/thumbnail_url/embed_url/competition_id/match_id/language/tags[]/scheduled_start_at/actual_start_at/ended_at/duration_seconds/viewer_stats (StreamViewerStats peak_concurrent/total_views/average_watch_time_s/unique_viewers)/is_featured/is_public; CRUD /stream-metadata/ med filtrering stream_type/status/platform/competition_id/is_featured/is_public; livscykel start/end/available/archive med statusvakter; viewer-stats endpoint med peak_concurrent max-beräkning
✅ PL-F1414 - F14.14.05 Shipped
Vimeo för on-demand replay — VimeoReplay-samling tenant-scopad med name/status (draft/uploading/transcoding/available/error/archived)/vimeo_video_id/vimeo_uri/api_token_ref/privacy (anybody/nobody/password/unlisted/disable)/password_ref/embed_responsive/embed_width/embed_height/embed_autoplay/embed_loop/embed_title/embed_byline/embed_portrait/embed_color/allowed_domains/competition_id/match_id/duration_seconds/file_size_bytes/download_enabled; CRUD /vimeo-replays/ med filtrering status/competition_id; livscykel available/archive; GET /{id}/embed genererar Vimeo embed-URL med parametrar; GET /{id}/validate kontrollerar video_id/api_token/password
✅ PL-F1414 - F14.14.06 Shipped
Cloudflare Stream för egen leverans — CloudflareStreamConfig-samling tenant-scopad med name/status (draft/ready/live_input_created/connected/disconnected/error/decommissioned)/mode (live/on_demand)/account_id_ref/api_token_ref/cf_stream_id/cf_live_input_id/rtmp_url/rtmp_key_ref/srt_url/webrtc_url/playback_hls_url/playback_dash_url/signed_url_config (SignedUrlConfig signing_key_ref/token_ttl_seconds/require_signed_urls)/allowed_origins[CloudflareStreamAllowedOrigin]/recording_enabled/require_signed_urls/max_duration_seconds/competition_id; CRUD /cloudflare-streams/ med filtrering status/mode/competition_id; livscykel activate/create-live-input/decommission; HMAC-SHA256 signed playback URL-generering med konfigurerbar TTL
✅ PL-F1414
DNS, SSL & CDN Integrations
F14.15**Plattform-CMS-trafik (`*.web.petanque.life` + custom domains) routas via Caddy reverse proxy** på Azure VM `vm-petanque-proxy` (`20.238.51.13`) — hanterar TLS-termination för obegränsat antal CMS-sajter framför `swa-petanque-web`. On-demand TLS via Let's Encrypt HTTP-01, cert-persistens i Docker-volym `caddy_data`. Cert-utfärdande gateas av `GET /public/domains/cert-allowed?domain=<host>` (plattforms-API:t) som returnerar 200 om hostname matchar aktiv `CmsSite.subdomain`/`CmsSite.domain` eller verifierad `CmsCustomDomain`. Federationer pekar sin egen domän mot CNAME-target `proxy.web.petanque.life`. Se `docs/engineering/architecture/05a-dns-and-tls.md` och `specs/infrastructure/caddy-proxy.md`.
How it works- F14.15.01 Shipped
ACME/Let's Encrypt certificate management — AcmeCertificate-samling tenant-scopad med automatisk certifikatutfärdande och förnyelse; för CMS-trafik: Caddy-baserad on-demand TLS via HTTP-01 challenge på vm-petanque-proxy med cert-persistens i Docker-volym (PL-T232)
✅ PL-F1415 + PL-T232 - F14.15.02 Shipped
Cloudflare DNS zone management — CloudflareDnsZone-samling tenant-scopad med zone CRUD och DNS-posthantering
✅ PL-F1415 - F14.15.03 Shipped
Cloudflare DNS record management — CloudflareDnsRecord-samling tenant-scopad med A/AAAA/CNAME/MX/TXT-poster
✅ PL-F1415 - F14.15.04 Shipped
Domain verification — DomainVerification-samling tenant-scopad med TXT/CNAME-verifieringsmetoder, WildcardCertificate för wildcard-certifikat
✅ PL-F1415 - F14.15.05 Shipped
Cloudflare Workers för edge computing — CloudflareWorkerDeployment-samling tenant-scopad med worker-konfiguration och deployment-hantering
✅ PL-F1415 - F14.15.06 Shipped
Caddy reverse proxy för CMS-trafik — vm-petanque-proxy Azure VM (B1s, statisk IP 20.238.51.13) kör Caddy 2.x i Docker; on-demand TLS via Let's Encrypt HTTP-01; cert-cache i volym caddy_data; reverse-proxy med header_up Host {host} till swa-petanque-web; gateas av /public/domains/cert-allowed-endpoint mot abuse; stabilt CNAME-target proxy.web.petanque.life för federationers egna domäner; ersätter Cloudflare for SaaS (PL-T046) som vilande alternativ (PL-T232)
✅ PL-T232 - F14.15.07 Shipped
Loopia DNS API-integration för auto-provisionering av plattform-subdomäner — services/sys/loopia_dns (XML-RPC mot https://api.loopia.se/RPCSERV) hookas in i POST/PATCH/DELETE /cms/sites/ så A-record <slug>.web.petanque.life → 20.238.51.13 skapas, byts eller tas bort automatiskt vid CmsSite-livscykelhändelser; dns_provisioning_status (pending/active/failed/disabled) + dns_provisioning_error + dns_provisioned_at på CmsSite för observability; POST /cms/sites/{id}/repair-dns för idempotent retry; reserverade slugs (proxy, _acme-challenge, test) blockerade; transient API-fel rullar inte tillbaka CmsSite-creation (PL-T235)
✅ PL-T235
Analytics & Tracking Integrations
F14.16## F14.01 (additions) — PL-T215
How it works- F14.16.01 Shipped
Plausible analytics (privacy-respecting) — PlausibleConfig-samling tenant-scopad med display_name/credentials (PlausibleCredentialRefs api_key_ref)/site_id/instance_url (cloud eller self-hosted)/enable_custom_events/enable_revenue_tracking/allowed_domains/usage (AnalyticsUsageMetrics); CRUD /analytics/plausible/configs/ med livscykel (draft→active→paused→error→decommissioned); AnalyticsEvent-samling med config_id/provider/event_name/event_properties/user_id/anonymous_id/page_url/referrer/user_agent/idempotency_key; POST /analytics/plausible/events/ skickar via Plausible Events API; GDPR-kompatibel utan cookies
✅ PL-F1416 - F14.16.02 Shipped
Umami analytics som självhostat alternativ — UmamiConfig-samling tenant-scopad med display_name/credentials (UmamiCredentialRefs api_key_ref/username_ref/password_ref)/instance_url/website_id/share_url/enable_custom_events/track_outbound_links/usage; CRUD /analytics/umami/configs/ med livscykel; POST /analytics/umami/events/ skickar via Umami Collect API; privacy-fokuserad, cookiefri
✅ PL-F1416 - F14.16.03 Shipped
Google Analytics 4 (opt-in per tenant) — GA4Config-samling tenant-scopad med display_name/credentials (GA4CredentialRefs measurement_id/api_secret_ref/service_account_json_ref)/property_id/data_stream_id/require_cookie_consent (default true)/anonymize_ip/enable_enhanced_measurement/enable_ecommerce/debug_mode/usage; CRUD /analytics/ga4/configs/ med livscykel; POST /analytics/ga4/events/ skickar via GA4 Measurement Protocol med client_id; kräver cookie-samtycke (analytics-kategori) innan spårning aktiveras
✅ PL-F1416 - F14.16.04 Shipped
Per-tenant cookie consent — CookieConsentConfig-samling tenant-scopad med display_name/status/banner (ConsentBannerConfig position/style/primary_color/background_color/text_color/show_reject_all/show_preferences)/categories (necessary/functional/analytics/marketing med ConsentCategoryConfig enabled/required/default_accepted/display_name/description/cookie_names)/privacy_policy_url/cookie_policy_url/consent_expiry_days (1–730)/geo_targeting_enabled/respect_do_not_track; CRUD /analytics/cookie-consent/configs/ med PATCH-uppdatering; integrerar med befintlig CookieConsentRecord (privacy.py) för individuella samtyckesbeslut
✅ PL-F1416 - F14.16.05 Shipped
PostHog event tracking integration for product analytics, feature flags, and funnel analysis with per-tenant configuration
✅ PL-F1416 - F14.16.06 Shipped
API usage analytics aggregation per developer/tier — RateLimitWindow flushes till ApiUsageRecord-buckets; admin /admin/api/usage-vy med stacked area chart per tier, drilldown per utvecklare
✅ PL-T215 - F14.16.07 Shipped
Per-record provenance metadata — _meta.dataset_version + _meta.provenance_uri + field_provenance på alla data-product-svar för spårning av källdataset och version
✅ PL-T215 - F14.01.10 Shipped
Developer portal self-service — POST /developer/keys, GET/DELETE /developer/keys/{id}, GET /developer/keys/{id}/usage med 256-bit-key + SHA-256-hash; X-Developer-Id-bootstrap-header för första key-issuance
✅ delvis a95566cc.m-1 (nyckel-CRUD, se F14.00.05 — klienten ensureas ur SESSIONEN, X-Developer-Id-bootstrapen finns INTE och kommer inte); …/usage ⊘ a95566cc.m-2, portalens UI ✅ a95566cc.m-7 t-3 (web /developers/nycklar) - F14.01.11 Shipped
Sandbox-tenant provisioning — POST /developer/sandbox med 4 seed-templates (minimal, national_federation, club, competition_in_progress), separat PostgreSQL-databas, 30-dagars auto-expiry, 10× rate-limit
✅ a95566cc.m-7 (POST|GET /v1/developer/sandbox, …/templates, …/{id}:extend, …:reset, DELETE …): en RIKTIG tenant (tenant_type='sandbox', server-myntad kod sbx-<16 hex>, land XS) född genom husets ENDA defaults-väg, med de fyra mallarna byggda av de ägande domänernas EGNA sömmar och ett serverat manifest med ärliga omits[]; 30 dagars frist (block om 30, tak 120, varning 7) genom svepet developer_sandbox_expiry_tick; m-1:s ×10-budget genom is_sandbox + X-Petanque-Environment: sandbox. TRE legacy-löften ERSATTA (spec §9b): »separat PostgreSQL-databas« ⇒ tenant-isolation (arkitekturen har EN Postgres) · »raderas 1 dygn efter expiry« ⇒ stängning (klient återkallad + tenant arkiverad; huset har ingen tenant-hard-delete) · 429 vid kvot ⇒ 409 sandbox_quota_exceeded med {tier, limit, used}. Kontraktet: specs/api/endpoints/developer-sandbox.md §Greenfield. Portalens YTA (web /developers/sandlada) är BYGGD i a95566cc.m-7 t-3: mallarna med sina SERVERADE manifest och luckornas ägare cell för cell, beståndet med frist/dagräknare, :extend/:reset/DELETE och serverns 409 sandbox_quota_exceeded renderat VID åtgärden (aldrig en förhandsutgråad knapp). Operatörens motsvarighet är sys-panelen *Sandbox-tenanter* (/utvecklarplattform?flik=utvecklare) — en ren LÄSNING utan en enda mutationsknapp, där mockupens databaskolumn är ersatt av Tenant (§9b D-3) och *Provision sandbox (operator override)* står som ⊘ med skäl och pekar på den väg som FAKTISKT finns (impersonation med samtycke, D-SYS m-5) — §9b D-6 - F14.01.12 Shipped
OAuth 2.0 client-credentials grant — POST /v1/oauth/token med scope-baserad authorization (api:read, webhooks:write, data:integrity etc.); 3600s opaque token-livslängd; key-id-blacklist vid revoke
✅ a95566cc.m-1 — granten och key-id-blacklisten; tokenen är kortlivad och signerad (bokförd avvikelse mot legacys 3600 s opaka token) - F14.01.13 Planned
Public OpenAPI surface — GET /v1/openapi.json filtrerat till canonical tags (CANONICAL_DOMAINS frozenset i domains.py)
⊘ a95566cc.m-2 (GET /public/openapi.json, den filtrerade projektionen) - F14.01.14 Planned
API-versionering policy + middleware — /v{N} URL-prefix, X-API-Version/X-API-Version-Deprecated/Sunset headers, route-aware aliasing (explicit /v1/X-routes passerar genom oförändrade)
⊘ a95566cc.m-2 (versionslivscykeln) - F14.01.15 Shipped
Sliding-window rate-limit per client + tier — Redis sorted-set per (client_id, bucket); per-endpoint-buckets (default, webhook_management, data_product_query, oauth_token); fail-open vid Redis-utfall
✅ a95566cc.m-1 — per klient/tier, in-memory sliding window per instans (Redis är avvecklad, arkitektur §3) - F14.01.16 Planned
Legacy federation field-mapping — nationsprofilkatalogen GET /v1/federation/import-nation-profiles (SBF · NBoF · FFPJP ifyllda ur legacy-federation-mapping.md; FBP · FIB · FEP available: false med skäl och TOM mappning) + förbundets EGNA recept (/v1/federation/import-formats, mappning per kolumn med sluten transformmängd) och fältmappnings-editorn i admin /dataexport. Legacy-radens tenant.field_mapping_overrides ERSATT: mappningen är en TENANT-ÄGD rad, inte en override i tenant-konfigurationen — profilen KOPIERAS vid sparandet och läses aldrig igen. FIPJP-/CEP-formatet ligger kvar hos truppinlämningen (F14.02.03/.04)
byggt av D-PUBAPI m-9 (a95566cc-serien, federations-/legacy-importen) - F14.03.07 Shipped
Signed payload v2 — kanonisk "{timestamp}.{råa body-bytes}" HMAC-SHA256 (Stripe-formen), 5 min replay-fönster, headerfamiljen X-Petanque-Signature/-Timestamp/-Event-Id/-Delivery/-Attempt (+ -Replay-Of, -Environment) genom husets ENDA header-writer
byggt av a95566cc.m-3 - F14.03.08 Shipped
Self-service CRUD + debugging — /v1/developer/webhooks*, leveransloggen med per-försök-status, :test, :replay med X-Petanque-Replay-Of
byggt av a95566cc.m-3 - F14.03.09 Shipped
DLQ + auto-disable — 8 försök (backoff bas 30 s, kapad 1 h) ⇒ dlq; prenumerationen auto-avstängs efter 24 h med 100 % fel (disabled_reason='too_many_failures') av webhook_health_sweep, med audit (systemaktör) + in_app-notis. Ingen självläkning — :enable är en människas handling
byggt av a95566cc.m-3 - F14.03.10 Shipped
Sandbox-säker routning — en sandbox-klient når bara PL_WEBHOOK_SANDBOX_TARGET_ALLOWLIST (default webhook.site + loopback i local/test); prövat vid BÅDE registrering (403 webhook_target_not_allowed med allowlisten i detail) och sändning; leveransen bär X-Petanque-Environment: sandbox
byggt av a95566cc.m-3 - F14.03.11 Planned
ed25519-overlay — ed25519:<kid>=<hex> som tillägg till HMAC på integritetstyper (sanction.created); publik nyckel via GET /v1/integrity/public-key (ETag/304, 404 fail-closed) och roterade föregångare i previous[]. ⊘ Kvartalsvis AUTOMATISK rotation är INTE byggd — rotationen är en manuell driftåtgärd, runbooken §2. Ägare: D-PUBAPI (senare milstolpe)
byggt av a95566cc.m-3 (rotationsautomatiken ⊘) - F14.04.10 Shipped
Insurance risk-feed (aggregerad) — GET /v1/insurance/snapshots/{period} med månads-/kvartalssnapshots; competitions/venues/incidents-aggregat per region (NUTS-2), surface, capacity-band; väderdata per outdoor-event-hours; inga PII
✅ PL-T215 - F14.05.07 Shipped
GraphQL analytics-endpoint — POST /v1/analytics/graphql query-only med complexity-limit (count("{")*10 + count("(")*2, default 1000); per-tier-tak; field-level scope-gating
✅ PL-T215 - F14.05.08 Shipped
Research cohort query — POST /v1/research/cohorts/{id}/query med pseudonymized k=5-anonymity, consent-version per record, ethics-committee-approval-flow
✅ PL-T215 - F14.05.09 Shipped
Integrity event stream (SSE) — GET /v1/integrity/events/{event_id}/stream med Last-Event-ID-reconnect, p50<250ms latency-SLA, 15s heartbeat
✅ PL-T215 - F14.05.10 Shipped
Sanctions-list för betting-operatörer — GET /v1/integrity/sanctions med since/jurisdiction-filter, player_pseudo_id, ed25519-signerat _meta
✅ PL-T215
Data Product Subscriptions [DONE] — PL-T215
F14.17> **Greenfield-not (D-PUBAPI `a95566cc.m-8`, 2026-09) — DATATORGET är byggt.** Legacy-taggen
- F14.17.01 Shipped
Self-service-applicering — POST /developer/data-products/subscriptions med per-product required fields (regulator-jurisdiction för integrity, ethics-committee-approval för research); pending_review-default
✅ a95566cc.m-8 (POST /v1/developer/data-products/subscriptions): ansökan skapar F1-6-ärendet på plattforms-sentinel-tenanten, aldrig en åtkomst. Fältmängden är PRODUKTENS — integrity kräver regulator_jurisdiction ur en SLUTEN lista om sex myndigheter, research institution + ansvarig forskare + etikprövningsreferens; use_case ≥ 40 tecken. Läget HÄRLEDS vid läsning (raden har ingen status-kolumn) och dubblettskyddet är DB-invarianten dps_live_uq, inte ett if - F14.17.02 Shipped
Admin review-queue — GET /admin/applications med tabbar för status, side-drawer-detaljvy, FIFO-sortering, internal-notes (admin-only); POST .../approve
reject|revoke med audit-trail | ✅ a95566cc.m-8 (GET /v1/sys/data-products/subscriptions[/{id}], POST …/{id}:revoke): granskningen fattas på F1-6:s GENERISKA steg-rutt — m-8 bygger ingen egen beslutsväg — bakom sys.data_product.review (sys_security ensam; sys_support LÄSER, deny-by-default bevisas mot en riktig inloggning). internal_note lämnar aldrig utvecklarens projektion. Legacys admin-yta är superseded (admin-data-product-applications.md) - F14.17.03 Shipped
Tier-scopade subscriptions — 4 data products × 4 tiers (free/standard/partner/enterprise) med scope-injection vid approve (scopes_granted adderas till DeveloperApiKey.allowed_scopes)
✅ a95566cc.m-8: godkännandet injicerar produktens scopes på klienten OCH på varje levande nyckel (audit api_client.scopes_injected), och ensurear klientens pseudonym-salt en gång. Grinden är requireDataProduct i den pinnade ordningen M2M-only (401) → tokenens scope (403 insufficient_scope med required_scopes + apply_url — nekandet PEKAR PÅ DÖRREN) → det LEVANDE avtalet, med is_sandbox = false och valid_through som villkor i själva FRÅGAN. Scopen heter data:* (m-1:s slutna katalog, SelfService: false) - F14.17.04 Shipped
Subscription-lifecycle — pending_review → approved → revoked
expired; auto-expiry vid valid_through; revoke med future effective_at för compliance grace period | ✅ a95566cc.m-8: hela livscykeln pending_review → approved → rejected|withdrawn|revoked|expired HÄRLEDD, med svepet data_product_subscription_tick (dygnskadens) som verkställer den framtida fristen, skriver expired och varnar 30/7 dygn — högst EN notis per rad och körning, single-fire som DB-invariant på data_product_notice, och utfallet MÄTT (dispatched_at XOR skipped_reason). Svepet är BOKFÖRINGEN: åtkomsten dör vid ANROPET, inte vid vågen - F14.17.05 Shipped
API version lifecycle management — admin /api/versions-vy med experimental → stable → deprecated → sunset transitions; minst 12 mån deprecation-fönster; force-sunset kräver typed confirmation
✅ a95566cc.m-2 (versionslivscykeln, GET /v1/api-versions + sys-ytan) — se F14.01 - F14.17.06 Shipped
De fyra läsrutterna — GET /v1/data/rankings|results|integrity/sanctions|research/cohorts + POST …/cohorts/{key}:query. Varje svar är {data, page, _meta} med keyset-paginering (page_size ≤ 500, opak next_cursor bunden till sina filter; ett offset mot en levande källa hade tyst hoppat över rader) och Cache-Control: private, no-store + stark ETag ⇒ 304. ?since är inkrementell synk på den precision databasen LAGRAR (RFC 3339 med bråkdel — en sekundtrunkerad stämpel gör »vad är nytt sedan sist« evigt trasig). Ingenting lämnar huset som förbundet inte redan publicerat: bara publika presets, bara publicerade TENANT/GLOBAL-resultat, bara FIPJP-registrets cross-tenant-publicerade rader (BR07.04 — aldrig active_sanction), aldrig en sandbox-tenant. En NAMNGIVEN preset= RESOLVAS (publik ∧ aktiv ∧ icke-raderad ∧ icke-sandbox) och ger annars 404 med en byte-identisk kropp för privat, raderad, inaktiv, sandbox och okänd — en tom 200 hade läst som »förbundet har inga publika presets«, och en skillnad mellan fallen hade varit ett existensorakel
✅ a95566cc.m-8 - F14.17.07 Shipped
PII-friheten är MÄTT, inte lovad — varje subjekt bärs av pl-ps_<40 hex> = HMAC-SHA256(klientens salt, uuid): stabil per klient över produkterna, olik mellan klienter, aldrig inverterbar (saltet lämnar aldrig processen). Acceptanssviten går REKURSIVT genom varje svar och faller på en förbjuden nyckel ELLER ett husets uuid utanför de tillåtna handtagen. Ett saknat salt UTELÄMNAR fältet — aldrig en tom pseudonym, som hade varit samma värde för varje människa
✅ a95566cc.m-8 - F14.17.08 Shipped
Provenance är MÄTT, aldrig skriven — _meta bär dataset_version (vattenmärke ur datans EGNA tidsstämplar; en tom sida ⇒ #empty, aldrig ett räknat löpnummer), provenance_uri, source_state ∈ {measured, register_unavailable, empty} (utan FIPJP-registret svarar feeden 200 med register_unavailable — aldrig en tystnad som läses som »inga avstängningar finns«), en KOD-deklarerad field_provenance där VARJE fält i data[] har en rad — per fält, inte per fråga: kohortens sources är unionen av allt frågan läser, men ursprungsraden för ett mått namnger de tabeller precis det måttet mättes ur (matches_played mäts ur D-COMP:s färdigspelade matcher i publicerade tävlingar, aldrig ur rankingens counted_results) — subscription, terms och — bara på integrity — en ed25519-signatur vars recept står körbart i Go/Node/Python. Utan nyckel: signature: null + signature_state: "unavailable"; en fejkad signatur är värre än ingen. Två läsningar utan skrivning emellan ⇒ byte-identiskt _meta
✅ a95566cc.m-8 - F14.17.09 Shipped
K-anonyma kohorter — en kohort är en DEKLARERAD aggregatfråga (dimensioner, mått, k_floor, max_cells, källor i den serverade katalogen), aldrig fri SQL: deny-by-default i två led gör att gender, postal_code och varje annat fritt fält per konstruktion inte kan nå SQL:en (422 med fältpekare). Varje grupp med n < 5 är suppressed: true med varje mått null, aldrig 0 (en nolla läses som ett mätvärde) och n nollas med dem. Inga poster på individnivå — legacys pseudo_id-rader kräver ett consent-scope ingen söm i huset frågar, och ett dataset som PÅSTOD samtycke vore fabricerad data
✅ a95566cc.m-8
No features match your filters.