Organization
Data Entity
Description
A top-level member organization within the platform (NHF, Blindeforbundet, HLF, Barnekreftforeningen). Organizations own their own labels, settings, feature toggles, and reporting data. Serves as the multi-tenancy root — all data is scoped to an organization and its hierarchy.
Data Structure
| Name | Type | Description | Constraints |
|---|---|---|---|
id |
uuid |
Immutable primary key generated on creation. Used as the tenant identifier in JWT claims (organization_id) and as the foreign key anchor for all scoped data across the platform. | PKrequiredunique |
name |
string |
Official display name of the organization (e.g., 'Norges Handikapforbund', 'Hørselsforbundet'). Used in UI headings, invitation emails, Bufdir reports, and analytics dashboards. | requiredunique |
slug |
string |
URL-safe, lowercase, hyphenated short identifier for the organization (e.g., 'nhf', 'blindeforbundet', 'hlf', 'barnekreftforeningen'). Used in API paths, iCal feed tokens, deep links, and referral link namespacing. Immutable after creation. | requiredunique |
logo_url |
string |
Absolute URL pointing to the organization's logo asset stored in cloud object storage. Rendered in the organization selection screen, onboarding flow, admin panel header, and generated Bufdir report headers. | - |
feature_flags |
json |
JSONB map of feature toggle flags enabling or disabling optional platform capabilities per organization. Examples: { 'encrypted_assignments': true, 'bulk_registration': false, 'gamification': false, 'course_management': true, 'reimbursements': true }. Validated against the settings schema on every write. | - |
settings |
json |
JSONB map of organization-specific operational configuration. Includes: reimbursement thresholds (auto_approve_km_threshold, auto_approve_amount_threshold_nok), receipt_required_above_nok, default_activity_duration_minutes, honorarium_tier_thresholds, max_association_memberships_per_user. Validated against the settings schema on every write. | - |
contact_email |
string |
Primary administrative contact email for the organization. Used by the platform operator for billing, support escalation, and release communications. Not exposed to end users. | - |
contact_phone |
string |
Primary administrative contact phone number in E.164 format (e.g., +4712345678). Used for billing and support escalation by the platform operator. | - |
website_url |
string |
Public website URL for the organization. Displayed in the onboarding flow and organization settings screen for context. | - |
bufdir_organization_code |
string |
The organization's official Bufdir grant recipient identifier code. Required when generating Bufdir compliance reports. Each of the four partner organizations has a unique code assigned by Bufdir. | unique |
default_language |
string |
BCP-47 language tag representing the primary language for this organization's user interface and generated reports (e.g., 'nb-NO' for Norwegian Bokmål). Drives i18n defaults for label resolution. | required |
is_active |
boolean |
Soft-delete flag. When false, the organization and all its members are locked out of the platform. No data is physically deleted. Used for contract suspension or offboarding. Defaults to true on creation. | required |
created_at |
datetime |
UTC timestamp when the organization record was first created. Set once on insert and never modified. Used for audit trails and platform analytics. | required |
updated_at |
datetime |
UTC timestamp of the most recent modification to any organization field. Auto-updated on every write via database trigger or ORM hook. Used for cache invalidation and optimistic concurrency checks. | required |
Database Indexes
idx_organization_slug
Columns: slug
idx_organization_name
Columns: name
idx_organization_is_active
Columns: is_active
idx_organization_bufdir_code
Columns: bufdir_organization_code
idx_organization_created_at
Columns: created_at
Validation Rules
name_non_empty_and_bounded
error
Validation failed
name_non_empty_and_bounded_on_update
error
Validation failed
slug_format_validation
error
Validation failed
slug_uniqueness
error
Validation failed
name_uniqueness
error
Validation failed
name_uniqueness_on_update
error
Validation failed
logo_url_format_validation
error
Validation failed
logo_url_format_validation_on_update
error
Validation failed
contact_email_format_validation
error
Validation failed
contact_email_format_validation_on_update
error
Validation failed
contact_phone_e164_format
error
Validation failed
contact_phone_e164_format_on_update
error
Validation failed
default_language_valid_bcp47
error
Validation failed
default_language_valid_bcp47_on_update
error
Validation failed
bufdir_code_uniqueness
error
Validation failed
bufdir_code_uniqueness_on_update
error
Validation failed
feature_flags_no_unknown_keys
error
Validation failed
feature_flags_no_unknown_keys_on_update
error
Validation failed
settings_threshold_values_positive
error
Validation failed
settings_threshold_values_positive_on_update
error
Validation failed
bufdir_code_required_for_report_generation
warning
Validation failed
Business Rules
slug_immutable_after_creation
The slug field cannot be modified after the organization record is first created. It is used as a stable external identifier in deep links, API paths, iCal tokens, and referral namespaces. Any attempt to update the slug must be rejected with a validation error.
tenant_data_isolation
All queries against any entity that has a foreign key relationship to organizations must include an organization_id scope filter. No cross-organization data access is permitted at any layer. The multi-tenancy infrastructure middleware enforces this by attaching a TenantContext to every request derived from the authenticated user's JWT claims.
organization_requires_active_admin
An organization must retain at least one active user with the Organization Administrator or Global Administrator role. Attempts to deactivate or demote the last admin must be rejected. This prevents organizations from becoming permanently inaccessible.
deactivation_is_soft_delete_only
Organizations are never physically deleted from the database. Setting is_active = false is the only permitted deactivation mechanism. All historical data — activities, reports, reimbursements, assignments — must remain queryable for audit and Bufdir compliance purposes.
feature_flags_validated_against_schema
The feature_flags JSONB field must conform to the known feature flags schema on every write. Unknown keys are rejected. This prevents silent misconfiguration that could expose features to organizations not licensed or configured for them.
feature_flags_validated_against_schema_on_update
The feature_flags JSONB field must conform to the known feature flags schema on every update. Unknown keys are rejected.
logo_stored_via_object_storage
The logo_url field must reference a URL in the platform's configured cloud object storage domain. Base64-encoded inline images or external CDN URLs not under the platform's control are not permitted. This enforces consistent access control, retention, and CDN delivery for all organization branding assets.
logo_stored_via_object_storage_on_update
The logo_url field update must reference a URL in the platform's configured cloud object storage domain.
settings_validated_against_schema
The settings JSONB field must conform to the known settings schema on every write. Numeric threshold values (km, NOK) must be positive integers within defined min/max bounds. Invalid settings are rejected before persistence.
settings_validated_against_schema_on_update
The settings JSONB field must conform to the known settings schema on every update.
organization_id_embedded_in_jwt
On every successful authentication, the user's current organization_id must be embedded as a claim in the issued JWT token. The multi-tenancy middleware uses this claim to construct the TenantContext for the request lifecycle. Sessions without a valid organization_id claim are rejected by all protected routes.
labels_cache_invalidated_on_settings_change
When an organization's settings or feature_flags are updated, the labels cache for that organization must be invalidated. This ensures that mobile clients receive updated terminology and feature availability on next app foreground or explicit refresh.
CRUD Operations
Storage Configuration
Entity Relationships
An organization defines and owns the set of activity types available to its members
An organization defines its own badge catalog and recognition program for peer mentors
An organization generates multiple Bufdir compliance reports across reporting periods
An organization manages its own catalog of training courses and certification programs
An organization configures the available expense types and their validation rules for its peer mentors
An organization curates its own list of external resource links for peer mentors
An organization can have multiple external system integrations (accounting, portals) configured independently
An organization owns all its local associations directly, supporting direct org-to-association queries bypassing region
An organization owns a set of terminology overrides customizing app labels throughout the platform
An organization has multiple regional groupings that aggregate local associations
An organization has many team and coordinator-level operational reports generated within it
An organization maintains its own library of talking cards and toolbox content for peer mentors
An organization has many user role assignments scoped to it