Organization
Data Entity
Description
A tenant organization on the Meander platform. Represents a national disability organization (e.g., NHF, Blindeforbundet, HLF) or any sub-unit within its hierarchy. Organizations are the primary multi-tenancy boundary — all operational data (users, activities, expenses, contacts, reports) is scoped to an organization. Supports hierarchical structures (national → regional → local) via a closure table pattern.
Data Structure
| Name | Type | Description | Constraints |
|---|---|---|---|
id |
uuid |
Globally unique identifier for the organization. Used as the tenant key across all multi-tenant queries. | PKrequiredunique |
name |
string |
Full legal or display name of the organization (e.g., 'Norges Handikapforbund'). | required |
slug |
string |
URL-safe lowercase identifier used in API paths and routing. Derived from name on creation, immutable after first use in active data. | requiredunique |
parent_organization_id |
uuid |
Foreign key to the parent organization in the hierarchy. NULL for top-level organizations. Enables multi-level structures (national → regional → local). | - |
organization_level |
enum |
Position in the organizational hierarchy. Drives scoping logic and admin portal visibility rules. | required |
short_name |
string |
Abbreviated name used in UI labels, report headers, and notifications (e.g., 'NHF', 'HLF'). | - |
description |
text |
Optional description of the organization's mission or scope. Displayed on the Admin Web Portal organization settings page. | - |
logo_url |
string |
CDN URL for the organization's uploaded logo. Used in mobile app branding, reports, and admin portal headers. | - |
website_url |
string |
Public website URL for the organization, shown in admin portal and help sections. | - |
contact_email |
string |
Primary administrative contact email. Used for system notifications and support routing. | - |
contact_phone |
string |
Primary contact phone number in E.164 format. Used for SMS notification routing and admin contact display. | - |
country_code |
string |
ISO 3166-1 alpha-2 country code. Defaults to 'NO' for Norwegian organizations. Drives locale defaults and legal document selection. | required |
bufdir_org_id |
string |
External organization identifier assigned by Bufdir. Required for automated Bufdir report generation and export. NULL for organizations not receiving Bufdir funding. | unique |
active |
boolean |
Soft-delete flag. Inactive organizations are hidden from all operational views but preserved for audit history and historical reporting. Never physically deleted. | required |
onboarded_at |
datetime |
Timestamp when the organization was fully onboarded and activated on the platform. NULL means onboarding is in progress. | - |
created_at |
datetime |
Record creation timestamp. Set by the database on INSERT. | required |
updated_at |
datetime |
Last modification timestamp. Updated automatically on any field change. | required |
Database Indexes
idx_organizations_slug
Columns: slug
idx_organizations_parent_id
Columns: parent_organization_id
idx_organizations_active
Columns: active
idx_organizations_bufdir_org_id
Columns: bufdir_org_id
idx_organizations_level_active
Columns: organization_level, active
Validation Rules
name_required_non_empty
error
Validation failed
slug_format_valid
error
Validation failed
logo_url_valid_format
error
Validation failed
contact_email_valid_format
error
Validation failed
contact_phone_e164_format
error
Validation failed
parent_organization_must_exist_and_be_active
error
Validation failed
country_code_iso3166
error
Validation failed
Business Rules
tenant_isolation_enforced
Every query touching operational data (activities, users, contacts, expenses, reports) MUST include an organization_id WHERE clause. Cross-organization data access is architecturally forbidden except for Global Admins performing system-level operations. Global Admins may not access org operational content by default.
soft_delete_only
Organizations are never physically deleted. Setting active=false deactivates the organization and hides all associated users and data from operational views. Historical audit records are preserved indefinitely. Hard DELETE is not permitted.
circular_hierarchy_prevention
An organization cannot be set as its own ancestor. Before persisting a parent_organization_id change, the hierarchy service must verify no cycle would be introduced using the closure table ancestry check.
bufdir_id_unique_across_platform
bufdir_org_id must be globally unique. Two organizations cannot share the same Bufdir identifier, as this would corrupt government grant reporting and audit trails.
slug_immutable_after_use
Once an organization slug is referenced in active user accounts, JWT tokens, or external integrations, it cannot be changed. The organization-service must check for existing references before allowing a slug update.
hierarchy_level_consistency
An organization's level (national/regional/local) must be consistent with its position in the closure table. A 'local' organization cannot have children; a 'national' organization can have 'regional' or 'local' children.
deactivation_cascade_warning
Deactivating an organization must emit a warning if it has active users, pending expense approvals, or unsubmitted Bufdir reports. Deactivation proceeds but all associated active sessions are revoked.