Tenancy & Access Model

Ported from the full pack's tenancy/access doc, extended with gist's LayerShare and DisclosureProfile (which the starter pack did not have).

Objective

Demonstrate that shared spatial awareness does not imply unrestricted information sharing.

Access chain

User → Role → Permission → Tenant → Layer → Feature
flowchart LR
    U[User]
    R[Role]
    P[Permission - scope tenant/layer/feature]
    T[Tenant]
    L[Layer]
    F[Feature]
    SH[LayerShare - cross-tenant]
    DP[DisclosureProfile]
    U --> R --> P
    P --> T
    P --> L
    L --> F
    T --> F
    L -->|granted access level| SH
    SH -->|to another tenant| T
    SH --> DP
    DP -->|geometry policy + field allow/deny| F

Default rule

Deny cross-tenant visibility unless an explicit permission or a controlled LayerShare exists.

Seeded roles (per tenant)

Role Scope Rights (demo seed)
Tenant Administrator (transport.admin) tenant full: view/create/edit/delete/export/share
Transport Planner (transport.planner) layer road_projects view/create/edit/export/share
Lease Manager (mining.lease_manager) layer mining_leases view/create/edit/export
Regulatory Reviewer (regulator.reviewer) tenant view/export only (read + acknowledge)

Permission.scope is one of tenant / layer / feature; scope_ref names the layer/feature when scoped below tenant.

Sharing modes (LayerShare.access_level)

The LayerShare model is the only sanctioned way a layer crosses a tenant boundary. Its access level escalates what the target tenant may do:

none → metadata → geometry → read → export

  • Shared layer — a whole layer is visible to an authorised tenant at the granted level.
  • Shared affected feature — only features relevant to an event are exposed (via the disclosure profile on the event). This better represents need-to-know access.

Seeded shares (all under profile coordination_basic):

Source → Target Layer Access
mining → transport mining_leases read
utility → transport pipelines geometry
regulator → transport environmental_areas read
transport → mining road_projects read

Disclosure profiles

A DisclosureProfile bounds what a cross-tenant disclosure actually contains:

  • coordination_basic — geometry policy full; shares external_ref/name/feature_type/status/ geometry/properties; denies internal_target_model, commercial_notes, resource_estimate (so mining's confidential target model never reaches transport).
  • metadata_only — geometry policy none; identifying fields only.
  • centroid_only — geometry policy centroid; location without exact boundary.

Important distinction

Permission:      "May this user see the feature?"
Responsibility:  "What is this organisation's relationship to the feature?" (FeatureResponsibility)

Responsibility (owner / custodian / operator / regulator / approver / affected_party …) is a business relationship, not an access-control role.

Test requirements

  • Tenant A cannot query Tenant B's private features.
  • Shared layers are role-controlled and honour the LayerShare access level.
  • A disclosure never exceeds its DisclosureProfile (full → centroid down-resolution, field allow/deny lists enforced).
  • Export honours the same permissions as UI access.
  • API and UI produce equivalent authorisation decisions.

The pack's tests/access_matrix.yaml is the ready-made who-can-see-what fixture (page 12).