Hoppa till huvudinnehåll
Petanque Life

Organization Hierarchy Access

F02.04 8 features Plattform+

I korthet

Organization Hierarchy Access enforces the platform's two-layer access model: standalone tenants for hard data isolation between federations, and OrgNodes (districts and clubs) for scoping authority within a tenant. Cross-tenant interaction goes exclusively through signed public APIs, while shared auth identities let the same person hold separate profiles in multiple federations without leaking data.

Så fungerar det

Every database document carries a tenant_id; the data layer rejects any query that does not filter on it. A tenant represents a complete federation — FIPJP, a continental confederation, or a national federation — and tenants never read each other's data directly, even when the underlying entities are conceptually related. Within a tenant, OrgNodes form a configurable tree whose depth is set per federation: Norway runs flat with the national tenant only, Sweden uses district→club, France uses ligue→comité→club.

Each OrgNode has a parent_id and a materialised path so subtree queries (e.g. "all clubs under this district") resolve in a single index lookup. Role assignments (F02.03) bind to a tenant_id and optionally an org_node_id, and the authorisation middleware derives the effective scope by walking the path: a District Admin assigned at SE-Stockholm sees clubs and players whose org_node_path begins with /se/stockholm, while a Club President sees only the leaf they were assigned to. Because the same human may participate in multiple federations (a French player living in Sweden), the auth identity is shared across tenants while the profiles are not — F02.01 stores one PlayerProfile per tenant linked to the same identity, and F02.06 produces the federated login that makes this seamless.

Cross-tenant flows — license verification, International Transfer Certificates, squad submission to FIPJP — never bypass the isolation: they go through public, signed APIs that one tenant exposes and another consumes, with explicit rate limits and audit. Delegation lets a federation admin temporarily assign part of their authority to an assistant, recorded as an explicit role grant rather than implicit impersonation, so audit logs always show the actual user.

Centrala funktioner

  • Hard tenant isolation enforced at the data layer (every query is tenant-scoped)
  • Configurable OrgNode tree depth per federation (flat to three levels)
  • Role assignments scoped to tenant + optional OrgNode subtree
  • Linked player identity across tenants (shared auth, separate profiles)
  • Public APIs as the only cross-tenant integration path
  • Subtree filtering via materialised OrgNode paths for fast scope resolution
  • Explicit delegation grants instead of impersonation for audit clarity

I praktiken

A Swedish player transfers temporarily to a French club for the season. In the Swedish tenant her PlayerProfile remains intact; in the French tenant her federation admin issues a guest license that creates a second PlayerProfile linked to the same auth identity. She logs in once and the app shows two contexts; she chooses 'French Federation' and sees only French clubs and competitions.

Meanwhile, a French district admin tries to view her Swedish history — the request hits the public license-verification API, returns a signed minimal payload (active license, valid through), and never crosses tenant isolation. When she returns to Sweden, the French tenant retains the historical record but no longer drives any of her permissions; her Swedish role at her home club is unchanged.

Features i detta subsystem

8
ID Status Funktioner
F02.04.01 Levererad Tenant-scoped data isolation (every federation is a standalone tenant) ✅ PL-F0204a (TENANT_SCOPED_MODEL_REGISTRY, describe_tenant_isolation, assert_tenant_match + structlog-audit hierarchy_access.cross_tenant_violation, GET /hierarchy-access/tenant-isolation)
F02.04.02 Levererad Public APIs for cross-tenant interactions (license verification, ITC, squad submission) ✅ PL-F0204a (CROSS_TENANT_PUBLIC_APIS-registret med 8 ytor: /public/licenses/verify, /public/itc/{request,release,complete}, /public/squads/{submit,{ref}}, /public/federations/directory; GET /hierarchy-access/public-apis)
F02.04.03 Levererad Linked player identity across tenants (same auth, separate profiles) ✅ PL-F0204a (resolve_linked_identities bypassar tenant-filter via rå Beanie-query, grupperar player/official/coach/administrator per tenant, GET /hierarchy-access/linked-identities/{user_id})
F02.04.04 Levererad District-based scope filtering (district admin sees clubs/players in their OrgNode subtree) ✅ PL-F0204a (scope_district_id-query + X-District-Scope-header på GET /player-profiles, BFS-traversal via resolve_district_subtree, GET /hierarchy-access/district-scope/{district_id} med audit-log)
F02.04.05 Levererad Delegation of authority (federation admin delegates to assistant) ✅ PL-F0204b (DelegationOfAuthority-modell med scope_type tenant/district/club, POST /hierarchy-access/delegations skapa, GET lista/hämta, POST .../revoke med audit-log, duplicate-guard 409, tid-begränsade eller permanenta delegationer)
F02.04.06 Levererad Club OrgNode management within national tenant ✅ PL-F0204b (GET /hierarchy-access/manageable-clubs scopad lista baserat på roll/delegation, GET /manageable-districts, POST /check-club-access med granting_scope-svar, federation-admin→alla, distriktsadmin→subtree, klubbordförande→egen klubb)
F02.04.07 Levererad Role assignment scoped to OrgNode (club president only manages their club) ✅ PL-F0204b (GET /hierarchy-access/scopes/{user_id} aggregerar rolltilldelningar + delegationer, POST /check-org-node-access scope-enforcement, assert_can_manage_club i service-layer)
F02.04.08 Levererad Role assignment scoped to district OrgNode (district admin) ✅ PL-F0204b (POST /hierarchy-access/check-district-access med subtree-traversal, assert_can_manage_district verifierar direkt scope, parent-subtree eller tenant-nivå, distriktsadmin ser alla underliggande distrikt + klubbar)