- Documentation
- /
- Gist
- /
- Tenancy & Access Model
Tenancy & Access Model
Ported from the full pack's tenancy/access doc, extended with gist's
LayerShareandDisclosureProfile(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
LayerShareexists.
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 policyfull; sharesexternal_ref/name/feature_type/status/ geometry/properties; deniesinternal_target_model,commercial_notes,resource_estimate(so mining's confidential target model never reaches transport).metadata_only— geometry policynone; identifying fields only.centroid_only— geometry policycentroid; 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
LayerShareaccess 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).