Files

44 lines
5.7 KiB
Markdown
Raw Permalink Normal View History

2026-09-24 14:35:05 +03:00
# Working on Meguri
Read `docs/product.md`, `docs/architecture.md`, `docs/development.md`, and `docs/testing.md` before changing behavior. They are the maintained specification. Update them with a behavior change, not after it. Keep this entry point short; put detailed decisions in `docs/`.
## Product boundaries
Meguri is the source of truth for on-call schedules, approved replacements, escalation policies, and their provider configuration. External providers receive the desired configuration and execute alerting. Meguri must never become an alert receiver or implement escalation timers/incident notifications.
All built-in UI text, labels, placeholders, accessible names and errors belong in the in-memory catalog `static/locales/messages.json`, with complete English, Russian and French entries. Templates and presentation code must use catalog keys, never inline human phrases. User-entered names/data remain unchanged. Store user language separately from scheduling state; unset follows a supported browser language, otherwise English. Source comments and repository documentation are English. Speak to collaborators in their language. Use ordinary forms, not a user-facing DSL.
## Module boundaries
- `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.
- `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.
- `static`: localized HTML, CSS, Alpine.js. Never inject user text with `innerHTML` or `x-html`.
## 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.
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.
5. Dependent coverage uses the effective fallback schedule at its own handover, including approved replacements. Country holidays skip only people in that country; general rotations remain continuous. Legacy global holidays retain direct-fallback behavior. Detect dependency cycles. Preserve approved history when rules change.
6. Save state, audit, and the sync request in one transaction. Use revision checks to reject stale edits. Never hold a workspace write lock while calling a provider.
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.
## 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/`.
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).
## Adding a provider
Document capability differences, credential requirements, identity mappings, ownership conventions, pagination, retries, idempotency, and drift semantics. Implement the shared provider contract, a fake-server contract test, and a dry-run path before enabling real writes. Do not hide capabilities behind vendor-specific scheduling logic in the engine. Live integration tests require a dedicated external test account; ordinary tests must never call a real provider.