Departments

Organizational units structuring the Renewa One team. Departments define team hierarchy, skill-level ownership, and are used for responsibility filtering in Document Obtaining and access scoping in RBAC Authorization.

Entra-owned (2026-06): departments and internal employees are sourced from Microsoft Entra ID via an hourly BullMQ sync job (entra-sync, cron 30 * * * * in backend/src/lib/jobs/schedulers.ts; service backend/src/services/entra/entra-sync-service.ts). Neither mocks nor migrations may re-seed them. Spec: docs/superpowers/specs/2026-06-09-mock-people-defer-to-entra-design.md.

Source Files

LayerPath
Schemabackend/src/db/schema.ts (departments)
Routesbackend/src/routes/admin/departments/ (department-crud.ts, members.ts)
Entra Syncbackend/src/services/entra/entra-sync-service.ts, backend/src/lib/jobs/processors/entra-sync.ts
Admin Pagefrontend/src/pages/admin/DepartmentsAdmin.tsx
Team Pagefrontend/src/pages/internal/TeamPage.tsx
Filter Contextfrontend/src/contexts/ResponsibilityFilterContext.tsx

Database Tables

TablePurpose
departmentsMain entity — localized name, code, skill level, ownership flag, Entra sync key

The user_departments M2M junction was removed (RNW-336): department placement is now a single FK contacts.departmentId on Contacts — one contact, one department — populated by the Entra profile sync.

Key Fields

FieldTypeNotes
namejsonb (LocalizedText)Bilingual name {de, en}; German name unique (admin invariant)
codevarchar(30)Unique internal code (e.g., RENOVATION_MANAGEMENT, OPM, SALES)
shortNamevarchar(20)Badge/UI label (e.g., SAM, FP, FD, EBO)
skillenumpro or basic — skill level this department handles
isOwnerbooleanWhether this is the “owner” department for its skill level
descriptionjsonb (LocalizedText)Bilingual description
entraKeyvarchar(255)Entra department string used for sync matching (unique, case-insensitive); null for departments outside Entra sync
originenumcurated (admin-created) or entra_auto (auto-created by sync)
sortOrderintegerUI display order
isActivebooleanActive flag

Skill-Level Ownership

Departments are categorized by the project skill level they handle:

SkillOwner DeptMeaning
proSAM ProOwns PRO-level projects (complex renovations)
basicSAL BasicOwns BASIC-level projects (simpler renovations)

The isOwner flag determines which department is the primary owner for projects at that skill level.

Relationships

Department 1──* Contacts (contacts.departmentId, Entra-synced)
Department -- used by --> Document Obtaining (responsibility filter)
Department -- used by --> RBAC Authorization (team lead scoping)

Membership

Department membership lives on Contacts (contacts.departmentId, single FK — RNW-336):

  • One contact belongs to at most one department
  • Populated by the Entra profile sync (Entra user.department string matched against departments.entraKey; unknown departments are auto-created with origin: entra_auto)
  • Used by team leads to scope their admin access (see RBAC Authorization); user lists filter via contacts.departmentId joins (backend/src/routes/admin/users/user-crud.ts)

Frontend

  • Admin page (DepartmentsAdmin.tsx) — department curation (display names, ordering); membership itself is Entra-owned
  • Team page (TeamPage.tsx) — internal team directory grouped by department
  • Responsibility filter (ResponsibilityFilterContext.tsx) — context provider that lets users filter views by department responsibility

Access Scoping

Team leads see only users in departments they manage. This is enforced in:

  • backend/src/routes/admin/users/user-crud.ts — filters user lists by managed departments
  • backend/src/middleware/rbac.tsrequireTeamLeadOrAdmin middleware

Users | Contacts | Document Obtaining | RBAC Authorization | Admin Dashboard | Database Architecture | Service Layer Pattern