Service Layer high complexity Shared Component backend
1
Dependencies
4
Dependents
2
Entities
0
Integrations

Description

Resolves and traverses the organisation tree structure, supporting both NHF's deeply nested model (national → region → chapter) and flat two-level models. Provides scoped subtree queries so that any admin action is automatically limited to the correct org nodes. Used across multiple features that need org-contextual data filtering.

Feature: Organisation Admin Portal

org-hierarchy-service

Summaries

The Organisation Hierarchy Service is a foundational capability that enables the platform to serve organisations of any structural complexity — from NHF's deeply nested national-region-chapter model to simpler two-level federations. By automatically constraining every admin action to the correct organisational scope, it eliminates the risk of data leakage between chapters or regions, protecting member privacy and maintaining compliance with governance requirements. This reusability across all admin features means the business avoids building bespoke scoping logic repeatedly, reducing long-term maintenance costs and accelerating delivery of new admin capabilities.

This is a high-complexity shared service that underpins multiple features, meaning its delivery is on the critical path for any admin portal functionality. Teams should plan for at least one sprint of design and implementation, plus dedicated time for caching strategy and cache invalidation edge cases. Its dependency on the admin-repository layer means that component must be stable before full integration testing begins. Risk: any change to the organisation data model (e.g.

adding a new tier) will require this service to be updated and re-tested across every feature that consumes it. Plan regression test coverage proportional to that blast radius.

Implements a tree traversal and caching service over the organisation entity model. Key interfaces include `getDescendantIds()` for RLS scope expansion (returns all org IDs beneath a given node, used to build Supabase IN-clause filters), `getAncestorPath()` for breadcrumb/context display, and `isOrgInScope()` for guard checks. The service must handle both adjacency-list and flat two-level org structures through a unified query interface, likely via a strategy or adapter pattern. Caching should be keyed by root org ID with invalidation triggered on org structure mutations.

Integrates with admin-repository for raw node data; consumed by admin-rls-guard, admin-export-service, and dashboard services.

Responsibilities

  • Build and cache the org tree for a given admin's root node
  • Resolve all descendant org IDs for a given node (for RLS scope expansion)
  • Support both nested and flat org structures with a unified query interface
  • Invalidate cached tree on org structure changes

Interfaces

getOrgTree(rootOrgId) -> OrgTree
getDescendantIds(orgId) -> List<String>
getAncestorPath(orgId) -> List<OrgNode>
searchOrgs(query, rootOrgId) -> List<OrgNode>
getOrgDepth(orgId) -> int
isOrgInScope(orgId, adminOrgId) -> bool

Relationships

Dependencies (1)

Components this component depends on

Dependents (4)

Components that depend on this component

Related Data Entities (2)

Data entities managed by this component

API Contract

View full contract →
REST /api/v1/orgs 9 endpoints
GET /api/v1/orgs List orgs (paginated)
GET /api/v1/orgs/:id Get a single org node
POST /api/v1/orgs Create a new org node
PUT /api/v1/orgs/:id Update an org node
DELETE /api/v1/orgs/:id Remove an org node (only if no children)
GET /api/v1/orgs/tree Get full org tree from a root
+3 more