# IAM Department Hierarchy Implementation Plan v1

Status: draft execution plan
Owner: Platform Architecture / IAM
Last updated: 2026-06-02

## Purpose

Define the execution order for making department/cost-center attribution a
mandatory platform data-model invariant without making department capabilities
mandatory in user onboarding or simple tenant UX.

This plan converts the shared decision in
`Unified_IAM_Billing_Across_Products_v1.md`,
`Tenant_Project_Ownership_Baseline.md`, and
`token-factory/IAM_Department_Layer_Readiness_v1.md` into Fairway-trackable
implementation slices.

## Decision

Department is mandatory at the data/model boundary and optional at the
capability/UX boundary.

Invariants:

- every organization receives a default department at creation;
- every project has a non-null `department_id`;
- every project department belongs to the same organization as the project;
- usage, audit, billing, policy, and reporting use a consistent
  `organization -> department -> project` shape;
- simple tenants do not see or manage departments until department-level
  reporting, budgets, delegation, or filtering is enabled.

Department capabilities remain optional and gated:

- department admins;
- department hard budgets;
- department policy inheritance;
- approval workflows;
- always-visible department context picker;
- resource-group hierarchy below project.

## Target Hierarchy

```text
organization / tenant
  -> department / cost center
    -> project
      -> resources
```

Project remains the operational workspace/resource scope. A project may
represent an application, environment, workload, experiment, training run, or
team workspace. Resource groups below project remain deferred until a concrete
within-project lifecycle, delete/export, policy, or cost-analysis workflow
requires them.

## Contract Boundary

The external contract exposes department attribution where callers need stable
project context, not as a mandatory onboarding input.

Project read models must include:

- `department_id`;
- `department_name`;
- `department_slug`.

Project creation may accept `department_id` for enterprise callers that already
manage departments. When omitted, the API assigns the organization's default
department. This keeps simple tenant UX project-first while preserving the
non-null data invariant.

Department read models use:

- `id`;
- `org_id`;
- `slug`;
- `display_name`;
- `is_default`;
- `lifecycle_state`;
- `created_at`;
- `updated_at`.

The contract does not enable department admins, hard budgets, policy
inheritance, approval workflows, or an always-visible department picker. Those
remain separate capability-gated surfaces.

## Additive Migration Boundary

The schema migration should be additive-first even though the repo is still
pre-production:

1. Create `platform_iam_departments`.
2. Add nullable `platform_iam_projects.department_id`.
3. Backfill one default department per organization.
4. Backfill every project to the owning organization's default department.
5. Add same-organization enforcement between project and department.
6. Enforce `platform_iam_projects.department_id not null`.
7. Update signup, seed, and project-create paths to assign the default
   department before the non-null steady state is relied on.

After the migration, nullable department attribution is not an accepted steady
state for new projects.

## Platform Billing Attribution Contract

Department attribution is part of the platform billing attribution contract,
not a per-product billing feature.

Stable billing hierarchy:

```text
organization -> department -> project
```

Products may meter at more specific leaves:

```text
organization -> department -> project -> service_account/api_key -> product resource -> usage
```

All accepted usage should preserve these dimensions:

1. Billing owner
   - `organization_id`
   - `department_id`
   - `project_id`
   - `billing_account_id`
2. Metering principal
   - `actor_type`
   - `actor_id`
   - `service_account_id`
   - `credential_id` or `api_key_id`
3. Product resource
   - `product_id`
   - `resource_type`
   - `resource_id`
   - product dimensions such as `model_id`, `endpoint_id`, `sku_id`, or
     `app_id`
4. Usage measurement
   - `usage_unit`
   - `quantity`
   - `usage_unit_version`
   - `metered_at`
   - `source_event_id`
5. Rating context
   - `pricing_plan_id`
   - `pricing_plan_version`
   - `rate_card_id`
   - `currency`
   - `pricing_snapshot`
6. Governance and traceability
   - `correlation_id`
   - `request_id`
   - `idempotency_key`
   - product metering source fields such as `tokenizer_version`, `gateway_id`,
     or `metering_source`
   - `reconciliation_status`

Practical rules:

- `project_id` determines the billing owner within the organization.
- `department_id` determines reporting, showback, budget grouping, and future
  delegation boundaries.
- `api_key_id` or `credential_id` determines metering, rate limits, abuse
  controls, and detailed usage analytics.
- Product-specific dimensions determine rating.
- The platform ledger remains the authority; products never write ledger
  entries directly.

Product onboarding must require:

- product ID registration;
- usage-unit registration;
- resource-type registration;
- pricing/rating rule registration;
- optional quota-dimension registration;
- accepted usage emitted through the shared platform usage contract;
- usage attribution resolved from IAM/project context;
- department grouping/filtering exposed through platform billing read models,
  not product-owned department state.

## Execution Order

1. Contract and migration plan
   - Update OpenAPI/read-model contracts only for fields and endpoints exposed
     to callers.
   - Define department object shape, default department naming, lifecycle, and
     non-null project attribution.
   - Define additive migration posture from current org/project state.

2. Schema and bootstrap
   - Add `platform_iam_departments`.
   - Add `platform_iam_projects.department_id`.
   - Backfill every organization with one default department.
   - Backfill every project to its organization default department.
   - Enforce non-null and same-organization constraints after backfill.
   - Update signup and project-creation paths to assign the default department.

3. IAM resolver and read models
   - Extend project-scope resolution to return organization, department,
     project, actor, and membership context.
   - Keep current tenant/project memberships valid.
   - Do not introduce department delegation in this slice.

4. Policy and quota scope
   - Add department as a recognized policy/quota scope.
   - Resolve effective policy through
     `global -> plan -> organization -> department -> project`.
   - Keep department quota enforcement capability-gated until quota assignment
     APIs and UX are ready.

5. Billing, usage, audit, and evidence attribution
   - Define accepted usage as a platform billing attribution contract, not a
     product-specific billing feature.
   - Ensure usage records and accepted usage events carry billing owner,
     metering principal, product resource, usage measurement, rating context,
     and governance/traceability dimensions.
   - Ensure department attribution is always present or can be resolved from
     immutable project snapshots.
   - Ensure audit/read-model filters can represent department scope where
     exposed.
   - Preserve immutable ledger behavior; do not rewrite historical ledger rows.

6. Service accounts and API keys
   - Ensure service-account/API-key records can snapshot project and department
     attribution, scope registry version, expiry policy, and actor/correlation
     evidence.
   - Do not create product-specific API-key models.

7. Portal and UX
   - Hide department controls when only the default department exists or
     department capabilities are disabled.
   - Add department filtering/context only when multiple departments or
     enterprise controls are enabled.

## Acceptance Criteria

- No nullable `department_id` path remains for new projects.
- Small-tenant onboarding still creates a usable default project without asking
  for department input.
- Product code does not directly query IAM-owned department tables.
- Policy, billing, audit, and usage contracts have a department-aware decision
  or attribution shape.
- Department admins, hard budgets, and approval workflows are not enabled by
  schema alone.
- Fairway tasks make contract/schema/resolver/policy/billing/key/UX ordering
  explicit.

## Related Fairway Tasks

- `IAM-DEPARTMENT-HIERARCHY-EPIC`
- `IAM-DEPARTMENT-CONTRACT-001`
- `IAM-DEPARTMENT-SCHEMA-BOOTSTRAP-001`
- `IAM-DEPARTMENT-RESOLUTION-001`
- `IAM-DEPARTMENT-POLICY-QUOTA-001`
- `IAM-DEPARTMENT-USAGE-AUDIT-ATTRIBUTION-001`
- `IAM-DEPARTMENT-SERVICE-ACCOUNT-SNAPSHOT-001`
- `IAM-DEPARTMENT-PORTAL-GATE-001`

## Related Docs

- `Unified_IAM_Billing_Across_Products_v1.md`
- `Tenant_Project_Ownership_Baseline.md`
- `Tenant_Admin_Quota_Delegation_v1.md`
- `token-factory/IAM_Department_Layer_Readiness_v1.md`
- `platform-foundation/Platform_Shared_Services_Model_v2.md`
