Organization
Data Entity
Description
Represents one of the partner organizations using the platform (NHF, Blindeforbundet, HLF, etc.). Each organization has its own branding, terminology overrides, feature flags, activity type catalogue, and organizational hierarchy. All data in the system is isolated by organization_id for multi-tenant security.
Data Structure
| Name | Type | Description | Constraints |
|---|---|---|---|
id |
uuid |
Globally unique identifier for the organization, used as the multi-tenant partition key across all RLS policies | PKrequiredunique |
name |
string |
Official full name of the organization (e.g., 'Norges Handikapforbund') | requiredunique |
slug |
string |
URL-safe lowercase identifier used in routing, deep links, and feature flag keys (e.g., 'nhf', 'blindeforbundet', 'hlf') | requiredunique |
display_name |
string |
Short display name shown in the organization selection screen and branding headers (e.g., 'NHF', 'Blindeforbundet') | - |
logo_url |
string |
Public URL to the organization's logo image, served from Supabase Storage or CDN | - |
logo_storage_path |
string |
Internal Supabase Storage bucket path for the logo asset, used to generate signed URLs and manage asset lifecycle | - |
primary_color |
string |
Primary brand color as a CSS hex code (e.g., '#005B9A') used in design token overrides for org-specific theming | - |
secondary_color |
string |
Secondary brand color as a CSS hex code, used for accent elements in org-specific theming | - |
website_url |
string |
Public website URL for the organization, displayed in the no-access screen for global admins and in onboarding copy | - |
admin_portal_url |
string |
URL to the web-based admin portal for this organization, shown to global_admin users on the no-access screen to redirect them to the correct interface | - |
contact_email |
string |
Administrative contact email for the organization, used for system notifications and support escalation | - |
is_active |
boolean |
Whether the organization is active and visible in the organization selection screen. Inactive organizations are hidden from all user-facing flows but their historical data is preserved. | required |
created_at |
datetime |
UTC timestamp when the organization record was created | required |
updated_at |
datetime |
UTC timestamp of the most recent update to any organization field, maintained via database trigger | required |
Database Indexes
idx_organization_slug
Columns: slug
idx_organization_name
Columns: name
idx_organization_is_active
Columns: is_active
Validation Rules
slug_format_valid
error
Validation failed
name_not_empty
error
Validation failed
logo_url_format
error
Validation failed
color_hex_format
error
Validation failed
contact_email_format
error
Validation failed
admin_portal_url_format
error
Validation failed
display_name_length
error
Validation failed
wcag_color_contrast
warning
Validation failed
Business Rules
soft_delete_only
Organizations must never be hard-deleted. Deactivation via is_active=false preserves all historical activity, reporting, and audit data required for Bufdir grant accountability. Physical deletion is prohibited.
single_active_configuration
Each organization must have exactly one active Organisation Configuration record. The one-to-one relationship is enforced at the database level via unique constraint on organization_id in the organisation_configurations table.
rls_tenant_isolation
All data tables containing an organization_id foreign key must have Row Level Security policies enforcing that authenticated users can only read and write data belonging to their active organization context. This is the core multi-tenancy security guarantee.
slug_immutable_after_creation
The slug field must not be changed after the organization record is created, as it is used in deep links, routing, and external system references. Changes would break existing links and integrations.
active_org_required_for_login
Users may only authenticate and establish a tenant session for organizations where is_active=true. Attempting to select an inactive organization must be blocked before any authentication flow is initiated.
branding_cache_invalidation_on_update
When organization branding fields (logo_url, primary_color, secondary_color) are updated, the org-branding-cache must be invalidated for all active sessions to ensure consistent visual presentation.
unique_slug_per_platform
The slug must be globally unique across all organizations on the platform, not just within a tenant. It serves as the canonical identifier in routing and cannot collide.
CRUD Operations
Storage Configuration
Entity Relationships
Each organization maintains its own catalogue of activity types with organization-specific names and Bufdir mappings
Each organization configures its own badge definitions matching its volunteer recognition programme
Each organization has one active Bufdir column schema that maps internal fields to official Bufdir export columns
Bufdir export audit records are scoped to an organization for regulatory accountability
All contacts are scoped to a single organization for multi-tenant data isolation via Supabase RLS
Accounting system export runs are scoped to an organization and used to track double-export prevention per organization
All Bufdir export files are scoped to the requesting organization for audit trail and re-download purposes
Each organization has exactly one configuration record containing feature flags, terminology labels, and reimbursement rate settings
An organization may have multiple external system integrations (Xledger, Dynamics, member management) each with its own config
An organization owns its entire hierarchy of units (chapters, regions, national associations) as root-level entries
Organizations configure their own tier structure (Bronze/Silver/Gold) with organization-specific thresholds
An organization defines its own Bufdir reporting periods aligned to its grant cycle calendar
An organization defines its own set of sensitive fields that require screen reader disclosure warnings before vocalization
Each field schema is owned by exactly one organization and defines that organization's post-session report form structure
Each role assignment is scoped to a specific organization, enabling users to hold different roles in different organizations