<!-- @generated by packages/sdk/scripts/copy-reference-docs.mjs -- DO NOT EDIT -->
<!-- Regenerate: pnpm scaffold:sync -->

﻿---
title: Customize organization-model.ts
description: Annotated walkthrough for customizing the System-backed Organization Model in template-derived projects.
---

# Customize organization-model.ts

`core/config/organization-model.ts` is the semantic contract between the UI shell and platform operations. The shell reads the id-keyed `systems` map for semantic ownership and access, reads `navigation.sidebar` for shell navigation, and binds resources through the id-keyed `resources` map.

## Imports

```ts
import {
  createFoundationOrganizationModel,
  defineOrganizationModel,
  type OrganizationModel
} from '@elevasis/core/organization-model'
```

- `defineOrganizationModel` gives a typed override shape.
- `createFoundationOrganizationModel` resolves defaults and returns the canonical model plus UI-facing helpers.
- `OrganizationModel` is the fully resolved model type.

## Systems

The `systems` map is the source of truth for semantic hierarchy, lifecycle, admin visibility, and governed ownership.

```ts
const override = defineOrganizationModel({
  systems: {
    dashboard: {
      id: 'dashboard',
      order: 10,
      label: 'Dashboard',
      lifecycle: 'active',
      description: 'Command Center home'
    },
    sales: {
      id: 'sales',
      order: 20,
      label: 'Sales',
      lifecycle: 'active'
    },
    'sales.crm': {
      id: 'sales.crm',
      order: 30,
      label: 'CRM',
      parentSystemId: 'sales',
      lifecycle: 'active',
      description: 'CRM pipeline and deal operations'
    }
  },
  navigation: {
    sidebar: {
      primary: {
        dashboard: {
          type: 'surface',
          order: 10,
          label: 'Dashboard',
          path: '/',
          surfaceType: 'dashboard',
          icon: 'feature.dashboard',
          targets: { systems: ['dashboard'] }
        },
        business: {
          type: 'group',
          order: 20,
          label: 'Business',
          children: {
            crm: {
              type: 'surface',
              order: 10,
              label: 'CRM',
              path: '/crm',
              surfaceType: 'page',
              targets: { systems: ['sales.crm'] }
            }
          }
        }
      },
      bottom: {}
    }
  }
})
```

System field reference:

- `id` -- lowercase dotted path. Parent Systems are inferred from prefix segments or declared through `parentSystemId`.
- `order` -- deterministic map iteration order. Use multiples of 10 for easy insertion.
- `label` -- sidebar and breadcrumb label.
- `description` -- optional settings/help text.
- `kind` -- product, operational, platform, or diagnostic.
- `parentSystemId` -- explicit parent System link.
- `lifecycle` -- draft, beta, active, deprecated, or archived.
- `ui` -- optional route metadata used by shell matching during migration.
- `requiresAdmin` -- hides the node for non-admin members; descendants inherit it.
- `actions` / `policies` -- references to cross-cutting domains.
- `ontology` -- System-owned object, link, action, catalog, event, surface, interface, value-type, property, or group records.
- `config` -- JSON-serializable settings local to this System.
- `systems` -- nested child Systems. Use this for new recursive authoring; `subsystems` is a compatibility alias only.

## Ontology

Use top-level `ontology` for global/shared primitives and `System.ontology` for owned contracts. The resolved ontology index is compiled from root and System scopes and validated for ID shape, kind mismatch, and duplicate IDs.

```ts
const override = defineOrganizationModel({
  ontology: {
    valueTypes: {
      'global:value-type/text': {
        id: 'global:value-type/text',
        label: 'Text'
      }
    }
  },
  systems: {
    sales: {
      id: 'sales',
      order: 20,
      label: 'Sales',
      lifecycle: 'active',
      systems: {
        crm: {
          id: 'sales.crm',
          order: 30,
          label: 'CRM',
          parentSystemId: 'sales',
          lifecycle: 'active',
          ontology: {
            objectTypes: {
              'sales.crm:object/deal': {
                id: 'sales.crm:object/deal',
                label: 'Deal',
                ownerSystemId: 'sales.crm'
              }
            },
            actionTypes: {
              'sales.crm:action/deal.update-stage': {
                id: 'sales.crm:action/deal.update-stage',
                label: 'Update Deal Stage',
                ownerSystemId: 'sales.crm',
                actsOn: ['sales.crm:object/deal']
              }
            }
          }
        }
      }
    }
  }
})
```

Top-level `entities`, top-level `actions`, and `System.content kind: "schema"` remain accepted for existing consumers and are projected into compiled ontology indexes. Prefer `System.ontology` for new object/action/catalog contracts.

## System Config

Use `systems[*].config` for local settings and defaults that are not semantic contracts:

```ts
const override = defineOrganizationModel({
  systems: {
    sales: {
      id: 'sales',
      order: 20,
      label: 'Sales',
      lifecycle: 'active',
      systems: {
        crm: {
          id: 'sales.crm',
          order: 30,
          label: 'CRM',
          parentSystemId: 'sales',
          lifecycle: 'active',
          config: {
            defaultPipelineId: 'sales.crm:catalog/pipeline',
            kanban: {
              groupBy: 'stage',
              showProbability: true
            }
          }
        }
      }
    }
  }
})
```

Keep semantic nouns, verbs, relationships, events, catalogs, interfaces, and value types in ontology. Keep secrets, credentials, per-run execution state, logs, and external service state outside the Organization Model.

## Sidebar Navigation

Author shell navigation under `navigation.sidebar`. Groups can contain nested nodes; routeable surface leaves provide `path`, `surfaceType`, and `targets`. Dashboard should appear before Business, Business is a navigation group only, and `/clients` is the canonical clients route.

## Resource Binding

Resource identity and governance metadata live in `OrganizationModel` under `resources`. Workflows, agents, integrations, and scripts import those descriptors and derive runtime `resourceId` / `type` from them. The graph derives System membership from `ResourceEntry.systemPath`.

```ts
// core/config/organization-model.ts
import { defineResources } from '@elevasis/core/organization-model'

export const resourceDescriptors = defineResources({
  leadImport: {
    id: 'lead-import',
    title: 'Lead Import',
    description: 'Updates CRM deal stage data from imported lead records.',
    order: 10,
    kind: 'workflow',
    systemPath: 'sales.crm',
    ownerRoleId: 'role-ops-lead',
    status: 'active',
    ontology: {
      actions: ['sales.crm:action/deal.update-stage'],
      primaryAction: 'sales.crm:action/deal.update-stage',
      reads: ['sales.crm:object/deal'],
      writes: ['sales.crm:object/deal'],
      usesCatalogs: ['sales.crm:catalog/pipeline'],
      emits: ['sales.crm:event/deal-stage-updated']
    }
  }
})

// operations/src/lead-import/index.ts
config: {
  resource: resourceDescriptors.leadImport,
  resourceId: resourceDescriptors.leadImport.id,
  name: 'Lead Import',
  type: resourceDescriptors.leadImport.kind,
  version: '1.0.0',
  status: 'prod',
  category: 'production'
}
```

Use kind-prefixed graph IDs for cross-collection links:

- `system:sales.crm`
- `integration:instantly`
- `resource:lead-import`
- `action:operations.queue.review`

`category` is one of `production`, `diagnostic`, `internal`, or `testing`.

Descriptor `title` and `description` own executable display metadata. Use nested `resource.ontology` bindings to declare which ontology actions, objects, catalogs, and events the resource performs, reads, writes, uses, or emits. `resource.ontology.primaryAction` names the default/selectable action and must be included in `resource.ontology.actions`. Resource event emissions can still be declared through top-level `emits` for older descriptors, but new descriptors should use `resource.ontology.emits`.

## Compatibility Domain Mirrors

The old `sales`, `prospecting`, and `projects` top-level keys are not part of the current primary Organization Model schema. If an older local project still has bridge-era examples for those concepts, migrate the data toward owning Systems:

- durable objects -> `System.ontology.objectTypes`
- stable verbs -> `System.ontology.actionTypes`
- pipelines, stages, templates, and status vocabularies -> `System.ontology.catalogTypes`
- local settings and defaults -> `System.config`
- existing `System.content kind: "schema"` nodes -> compatibility catalog projections

```ts
systems: {
  sales: {
    id: 'sales',
    order: 20,
    label: 'Sales',
    lifecycle: 'active',
    systems: {
      crm: {
        id: 'sales.crm',
        order: 30,
        label: 'CRM',
        lifecycle: 'active',
        parentSystemId: 'sales',
        ontology: {
          catalogTypes: {
            'sales.crm:catalog/pipeline': {
              id: 'sales.crm:catalog/pipeline',
              label: 'Default Pipeline',
              kind: 'pipeline',
              ownerSystemId: 'sales.crm',
              entries: {
                interested: { label: 'Interested', color: 'blue', order: 10, semanticClass: 'open' },
                closed_won: { label: 'Closed Won', color: 'green', order: 20, semanticClass: 'closed_won' }
              }
            }
          }
        }
      }
    }
  }
}
```

Keep `semanticClass` values stable; platform analytics and triggers depend on them.

Policy and role integration remains outside ontology in this pass. Use `roles`, `policies`, `responsibleRoleId`, and `ownerRoleId` for accountability and access semantics until a dedicated policy/role ontology design is published.

## Export Pattern

```ts
const foundation = createFoundationOrganizationModel(override)

export const canonicalOrganizationModel: OrganizationModel = foundation.canonical
export const organizationModel = foundation.model
export const { getOrganizationSurface } = foundation
```

Pass `canonicalOrganizationModel` to `ElevasisSystemsProvider` in `ui/src/routes/__root.tsx`.

## Resolve Behavior

`createFoundationOrganizationModel(override)` resolves defaults, validates System hierarchy, and exposes helper functions used by the shell. Id-keyed domain maps merge additively by key, so tenant overrides can add one System or resource without re-authoring every default entry.

Validation catches duplicate System IDs, missing parent Systems, invalid graph IDs, invalid UI paths, invalid ontology IDs, ontology kind mismatches, and duplicate ontology IDs.

## Refresh Generated Scaffold Copies

This file is source guidance for generated SDK reference copies. After changing Organization Model scaffold docs, refresh and verify generated outputs from the monorepo root:

```bash
pnpm scaffold:sync
pnpm scaffold:verify
pnpm verify:scaffold-reference
```
