Add OIDC sign-in, group-derived roles and declarative instance configuration

Workspaces, group mappings and sign-in methods now come from a configuration
file synchronized at startup; workspaces dropped from it are disabled, never
deleted. Instance administrators (a new role) see and help every workspace and
may delete disabled ones; workspace administrators and employees are derived
from the user's groups at every SSO sign-in or administrator edit, and the
employee permission set belongs to the workspace. Self-registration is gone:
users come from SSO (only when their groups map) or from the administrator.
Break-glass bootstrap accounts get an HMAC-derived hourly password that all
replicas agree on. First SSO sign-in links a matching email contact to the
user. The demo runs on the same model with a generated per-start password.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Aleksandr BogomiakovandClaude committed 2026-10-07 13:28:43 +01:00
1 parent e37d583179
commit 4764f3545f
68 files changed
+7220 -964

No files matched your search

+4 -3
View File
@@ -13,6 +13,7 @@ All built-in UI text, labels, placeholders, accessible names and errors belong i
- `domain`: typed state and permissions; no HTTP, database, or provider dependencies.
- `engine`: deterministic schedule calculation with an explicit clock/range; no I/O.
- `store` / `service`: Cot ORM and atomic PostgreSQL statement boundaries, authorization, optimistic versions, approval workflow, audit, durable sync requests.
- `access`: pure instance configuration, group-to-role resolution and bootstrap passwords. `identity`: configuration sync, group-derived access, SSO accounts and contact linking. `oidc`: token protocol and verification only. `admin`: instance administrator operations. Anything that grants access goes through `identity::apply_access`.
- `providers`: provider translation and HTTP only. Scheduling decisions belong in the engine. Never silently omit an unsupported provider feature.
- `worker`: retryable reconciliation, drift checks, publication checkpoints. Multiple replicas must not publish a workspace concurrently.
- `web`: thin authenticated handlers. Every workspace operation checks its workspace scope on the server.
@@ -20,7 +21,7 @@ All built-in UI text, labels, placeholders, accessible names and errors belong i
## Invariants
1. Workspace permissions are checked on every API and background operation. Membership in one workspace never grants access to another. Workspace owners administer only their workspace. There is no workspace hierarchy or implicit team.
1. Workspace permissions are checked on every API and background operation. Membership in one workspace never grants access to another. Workspace administrators administer only their workspace; instance administrators (a flag derived from `instance_admin_groups` or a bootstrap account) act on every enabled workspace without being members and are the only ones who see instance configuration, users and disabled workspaces. Workspaces, their keys and the groups that grant roles come only from the instance configuration; memberships are derived from stored groups by `identity::apply_access` and never granted any other way, and there is no self-registration. Disabled workspaces are inaccessible to everyone and are never deleted automatically. There is no workspace hierarchy or implicit team.
2. A request is not an override until all required participants approve or a user with the force permission applies it. Every action is audited; its comment is optional, including forced application. Revalidate ownership, availability, and overlaps at application time. A subsequent approved replacement supersedes only overlapping effective spans; preserve original requests and history.
3. Intervals are half-open `[start, end)`. Every schedule has its own handover in the workspace's IANA zone, snapshotted in workspace history. User timezone affects display only and defaults to the browser zone. Reject ambiguous/nonexistent local handovers instead of guessing. Never substitute a fixed UTC offset.
4. Base rotations have an explicit ordered participant list and anchor. An override does not advance or reset the base rotation.
@@ -29,13 +30,13 @@ All built-in UI text, labels, placeholders, accessible names and errors belong i
7. External drift blocks publication by default. Overwrite is an explicit workspace policy. Reconcile only owned resources. Persist successful remote writes so partial failures can recover.
8. Provider secrets come from the deployment secret store/environment, never API responses, audit snapshots, examples, or logs.
9. Report approval and publication as separate statuses. Never label an unverified external write as synchronized.
10. Scheduling contacts never gain login or workspace access through an email entry. Country defaults to CY. Imports use the same country codes and are add-only, server-previewed, and revision-checked. Resolve external identities exactly before remote writes; never guess accounts from similar names.
10. Scheduling contacts never gain login or workspace access through an email entry. At SSO sign-in an email may bind an existing contact in a workspace the user already belongs to (the contact ID is replaced by the user ID and kept as an alias); this identifies a person but never grants access, and ambiguous matches are skipped. SSO identities are never linked to existing password accounts automatically. Country defaults to CY. Imports use the same country codes and are add-only, server-previewed, and revision-checked. Resolve external identities exactly before remote writes; never guess accounts from similar names.
## Required workflow
Implement a small coherent change; add meaningful regression tests for scheduling, authorization, workflow, or reconciliation behavior it changes. Run `cargo fmt --check`, `cargo clippy --all-targets -- -D warnings`, `cargo test`, and the PostgreSQL integration suite described in `docs/development.md`. Inspect the actual browser for UI work. Do not add tests that only mirror constants or formatting.
Do not silently skip unavailable checks: record the limitation. Keep `Cargo.lock` committed for this application. New schema changes get a new migration; never edit an applied migration. Do not commit credentials, local database files, build output, or `opsgenie-master/`.
Do not silently skip unavailable checks: record the limitation. Keep `Cargo.lock` committed for this application. New schema changes get a new migration; never edit an applied migration. Instance configuration is declarative and owns workspaces and group mappings; never add a UI or API that creates workspaces or edits those mappings. The OIDC client secret and bootstrap passwords never enter configuration files, API responses, audit or logs other than the single documented bootstrap log line. Do not commit credentials, local database files, build output, or `opsgenie-master/`.
The ignored Terraform directory is reference material only. Store anonymized behavioral examples and tests in the repository so other agents do not depend on it. Preserve its business patterns, not its historical workarounds (manual DST tables, cached remote on-call lookup, multiple Terraform applies).