feat(tenant): remove the single-tenant cargo feature; no normal user lands in the default tenant #187

Merged
David merged 2 commits from feat/pms-262-remove-single-tenant-feature into main 2026-06-13 12:58:10 +02:00
Owner

PMS-262 (step 7/9 of PMS-255 per-user isolation). The single-tenant feature was the original "everyone shares one tenant" design: it pinned every operation to the fixed UUID 00000000-0000-0000-0000-000000000001 via db::tenant::default_tenant_id() and Default for TenantContext, the single biggest cross-tenant data-leak vector. Remove the feature entirely so that shared-data code path can no longer be compiled or reached. There is deliberately no Default for TenantContext any more: a tenant must always be resolved from an authenticated identity, never fall back to a shared constant.

Drop single-tenant = [] from Cargo.toml (default features stay ["multi-tenant", "server"]), delete the two #[cfg(feature = "single-tenant")] arms in main.rs (is_multi_tenant is now unconditionally true and the startup log no longer claims single-tenant mode), and refresh the stale resolve_tenant_for_login doc that referenced the removed symbol.

Default-tenant disposition is now documented as INFRA-ONLY: the only legitimate residents of Uuid::from_u128(1) (the Bunyip default landing tenant, OIDC_DEFAULT_TENANT_ID) are platform super_admins. place_bunyip_user already backfills every non-admin out of it into a personal tenant on next login (is_stuck_in_default, PMS-245); this pins that contract with two end-to-end placement tests in tests/bunyip_login.rs - a non-admin parked in the default tenant is rehomed into their own personal tenant, and a super_admin is left in place. Documented in db/tenant.rs and dev-docs/codebase-state.md.

#PMS-262

PMS-262 (step 7/9 of PMS-255 per-user isolation). The `single-tenant` feature was the original "everyone shares one tenant" design: it pinned every operation to the fixed UUID `00000000-0000-0000-0000-000000000001` via `db::tenant::default_tenant_id()` and `Default for TenantContext`, the single biggest cross-tenant data-leak vector. Remove the feature entirely so that shared-data code path can no longer be compiled or reached. There is deliberately no `Default for TenantContext` any more: a tenant must always be resolved from an authenticated identity, never fall back to a shared constant. Drop `single-tenant = []` from Cargo.toml (default features stay `["multi-tenant", "server"]`), delete the two `#[cfg(feature = "single-tenant")]` arms in main.rs (`is_multi_tenant` is now unconditionally true and the startup log no longer claims single-tenant mode), and refresh the stale `resolve_tenant_for_login` doc that referenced the removed symbol. Default-tenant disposition is now documented as INFRA-ONLY: the only legitimate residents of `Uuid::from_u128(1)` (the Bunyip default landing tenant, `OIDC_DEFAULT_TENANT_ID`) are platform super_admins. `place_bunyip_user` already backfills every non-admin out of it into a personal tenant on next login (`is_stuck_in_default`, PMS-245); this pins that contract with two end-to-end placement tests in tests/bunyip_login.rs - a non-admin parked in the default tenant is rehomed into their own personal tenant, and a super_admin is left in place. Documented in db/tenant.rs and dev-docs/codebase-state.md. #PMS-262
feat(tenant): remove the single-tenant cargo feature; no normal user lands in the default tenant
All checks were successful
E2E (staging) / Playwright against staging (pull_request) Successful in 49s
Check / fmt + clippy + compile + tests (pull_request) Successful in 2m37s
Build OCI container / Build and push mokosh-api image (push) Successful in 3m44s
6969297356
PMS-262 (step 7/9 of PMS-255 per-user isolation). The `single-tenant` feature was the original "everyone shares one tenant" design: it pinned every operation to the fixed UUID `00000000-0000-0000-0000-000000000001` via `db::tenant::default_tenant_id()` and `Default for TenantContext`, the single biggest cross-tenant data-leak vector. Remove the feature entirely so that shared-data code path can no longer be compiled or reached. There is deliberately no `Default for TenantContext` any more: a tenant must always be resolved from an authenticated identity, never fall back to a shared constant.

Drop `single-tenant = []` from Cargo.toml (default features stay `["multi-tenant", "server"]`), delete the two `#[cfg(feature = "single-tenant")]` arms in main.rs (`is_multi_tenant` is now unconditionally true and the startup log no longer claims single-tenant mode), and refresh the stale `resolve_tenant_for_login` doc that referenced the removed symbol.

Default-tenant disposition is now documented as INFRA-ONLY: the only legitimate residents of `Uuid::from_u128(1)` (the Bunyip default landing tenant, `OIDC_DEFAULT_TENANT_ID`) are platform super_admins. `place_bunyip_user` already backfills every non-admin out of it into a personal tenant on next login (`is_stuck_in_default`, PMS-245); this pins that contract with two end-to-end placement tests in tests/bunyip_login.rs - a non-admin parked in the default tenant is rehomed into their own personal tenant, and a super_admin is left in place. Documented in db/tenant.rs and dev-docs/codebase-state.md.

#PMS-262
Merge branch 'main' into feat/pms-262-remove-single-tenant-feature
All checks were successful
Create release / Create release from merged PR (pull_request) Has been skipped
E2E (staging) / Playwright against staging (pull_request) Successful in 35s
Check / fmt + clippy + compile + tests (pull_request) Successful in 6m58s
Build OCI container / Build and push mokosh-api image (push) Successful in 12m33s
28e059f858
David merged commit d8d2696135 into main 2026-06-13 12:58:10 +02:00
David deleted branch feat/pms-262-remove-single-tenant-feature 2026-06-13 12:58:10 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
psa-systems/mokosh-server!187
No description provided.