Files
meguri/docs/development.md
T
2026-10-07 14:22:37 +01:00

13 KiB
Raw Blame History

Development

Requirements: Rust 1.97 (Cot itself requires 1.94), PostgreSQL 17+, and a browser. Node is only needed for browser automation or upgrading vendored browser assets; serving the application has no Node build step.

Use .env.example as the list of supported settings. Environment files are not loaded automatically. Start a dedicated PostgreSQL database and either run the disposable demo (MEGURI_SEED_DEMO=true, loopback only, built-in configuration, see below) or write an instance configuration file (start from deploy/instance-config.example.yaml; auth.password_login: true plus auth.bootstrap_admin gives a local administrator without an identity provider), set DATABASE_URL and MEGURI_CONFIG_FILE, then run cargo run. Startup fails without a configuration file. Database migrations and the configuration sync run before the server accepts requests; the generated bootstrap password is logged. There is no registration: create further password users on the instance page, or sign in through an OIDC provider.

For an isolated Windows development database, use scripts/dev.ps1. It uses installed PostgreSQL binaries, creates data under ignored target/, binds the database and app to loopback, and starts disposable demo mode. The demo password is generated on every start; it appears on the login screen and in target/local/app.log. scripts/stop-dev.ps1 stops only the processes started for this workspace.

Required checks:

cargo fmt --check
cargo clippy --all-targets -- -D warnings
cargo test

PostgreSQL integration tests require MEGURI_TEST_DATABASE_URL pointing at a disposable database with CREATEDB (lifecycle and configuration-sync tests create and drop uniquely named databases, because sync disables every unconfigured workspace). Run cargo test --locked --tests -- --ignored --test-threads=1; this covers tests/integration.rs, tests/access.rs, tests/oidc.rs and tests/demo_lifecycle.rs. Most scheduling tests create uniquely keyed workspaces and users through the real configuration and group path; lifecycle tests test protection, reset, retention, and reseeding. Never use a production database.

CI uses an explicit Debian Node job container and the PostgreSQL service hostname postgres, for both Gitea Actions and GitHub Actions. Loopback inside the job does not reach the database service. No host database port is published. A bounded authenticated psql SELECT 1 check runs before compilation; database networking/authentication failures stop the job rather than producing a pool timeout in every integration test. The application and browser tests still share job-container loopback.

Browser checks: sign in with a demo account; inspect the calendar; create a request as one user and approve it as another; verify the publication status separately; verify that a user outside the workspace cannot read it. Use both desktop and narrow viewports. A test failure is not a reason to relax an authorization or scheduling invariant.

Operational limitations

For automated browser checks, run npm ci, npx playwright install chromium, then npm run test:browser against a freshly started demo (MEGURI_SEED_DEMO=true). The suites read the generated password from /api/session (tests/support/browser.cjs), so they need no configuration; set MEGURI_BROWSER_URL for a non-default address. By default the tests use installed Chrome; set MEGURI_BROWSER_CHANNEL=chromium for downloaded Chromium or MEGURI_BROWSER_EXECUTABLE for a specific binary. Workspaces cannot be created from the UI or API, so suites that need an isolated workspace create a fresh password user through the instance administrator API with groups from the demonstration configuration. tests/browser-access.cjs covers the login guide, absence of registration, the SSO error banner, the instance page and its read-only rules, employee permission editing (including force without approval), employee and outsider views, and workspace isolation. tests/browser-calendars.cjs checks email participants/absences, country defaults, reactive CSV import, workspace working hours, policy flows, and display-timezone isolation. tests/browser-configuration.cjs checks removal dependencies/redirects, native routing drag/drop, saved positions, insertion/removal renumbering, and mobile controls. Screenshots go under ignored test-results/. The suites modify demo data (some empty a demo workspace); restart the demo before repeating a run.

Windows development needs complete PostgreSQL server binaries and their share/ data files, not a client-only installation. Pass -PostgresBin to use a portable distribution. The loopback-only local database uses trust authentication and is not a production configuration. The script serves a copy of the executable so Cargo can rebuild while it runs.

Read testing.md when changing rules and deployment.md before preparing GKE deployment.

Demo lifecycle

MEGURI_SEED_DEMO=true enables disposable demo mode, not just seed insertion. It is limited to loopback and a single all or web process, uses the built-in configuration src/demo-config.yaml (any MEGURI_CONFIG_FILE is ignored) and needs no OIDC. Startup verifies the previous database mode before migrations, resets only positively marked demo application data, migrates, synchronizes the built-in configuration and seeds four examples. Normal startup records normal, including migration/worker roles. A missing or unreadable provenance marker never grants deletion authority. The existing development meguri DB will therefore be preserved on its first transition to this mode.

When the configured DB is protected, Meguri selects a separate meguri_demo_<stable fingerprint>_<slot> DB. The application login needs CREATEDB, or an administrator must supply an empty MEGURI_DEMO_DATABASE_URL with suitable permissions. Credentials are never shown in the browser/log notice. Protected fallback candidates are skipped, never dropped or overwritten. Isolation failure aborts startup. Do not manually mark a production database as demo. Another active client blocks reset; stop the old demo process before restarting.

The permanent header explains creation-based expiry and any protected-DB fallback. Defaults: workspaces 24 hours; accounts created by an administrator during the run 48 hours; requests 2 hours; audit/history 6 hours; physical purge 10 minutes after soft deletion. Configure seconds with the MEGURI_DEMO_* settings in .env.example (60 seconds–30 days). Sweeps run every minute and also re-run the configuration sync and seeding. Nested configuration expires with its owning aggregate to preserve dependencies. The seeded accounts remain; baseline workspaces are recreated and reseeded after expiry. No cleanup runs in normal mode. Demo rejects real provider integrations/publication.

Accounts (one password per start, shown on the login screen and in the log; there is no registration): admin is the instance administrator (a bootstrap account), alice administers all four workspaces, and bob, carol, dave, erin are employees. Groups are assigned as an instance administrator would assign them, and the built-in configuration is in the production format. Bob belongs to Engineering and Regional Platform; Carol to Engineering, Support and Commerce; Dave and Erin to Engineering. Engineering uses projects, responsible, and on_call; Support has independent queues, agents, and lead variables. All generated state is activated through the regular preview/commit code path with the mock provider.

Additional browser suites: browser-absence.cjs checks collapsed holidays, DD-MM-YYYY input, live bulk absence impact, range replacements and force; browser-generation.cjs checks demos, their permanent notice and isolated memberships, visual data/binding editing, early errors, preview without writes, stable generated IDs, and mobile forms. Restart after browser tests to return to the four clean examples.

Authentication is OpenID Connect plus optional password accounts; see deployment for configuration and Keycloak setup. No external JSM account is needed to run the mock provider. JSM writes require explicit integration configuration and workspace-scoped environment credentials. Contract tests use a fake HTTP server, never a production account.

Workspace configuration edits take effect when saved. Historical queries use saved configuration revisions. There is no user-configurable delayed activation of a whole configuration revision in the first release.

tests/browser-cover.cjs exercises daily volunteering/approval and optional comments in a separate disposable workspace, with desktop and mobile screenshots. Configuration navigation is grouped under Setup.

Navigation and language coverage: tests/browser-navigation.cjs checks direct menu/workspace links, reload and browser history, saved language versus browser preference, Russian/French display, safe interpolation, catalog completeness and the prohibition on literal template copy. It runs in npm run test:browser.

Demo workspaces import src/demo-holidays-2026.csv through the regular holiday service: 15 Cyprus dates supplied by the project owner, the 8 England and Wales bank holidays of 2026 from https://www.gov.uk/bank-holidays.json (verified 2026-10-07), and the 13 statutory Armenian public holidays/days off of 2026 (listed from the Labour Code, not re-verified against an official calendar). This is a fixed 2026 example, not a recurring calendar or an annual-date extrapolation. Demo accounts also differ in scheduling country so that country holidays are visible: alice and dave Cyprus, bob and erin United Kingdom (GB), carol Armenia (AM).

Demo workspaces: Acme Engineering (project priorities + weekly cover), Customer Support (daily queues), Regional Platform (dictionary regions → nested enabled services, region-specific handovers/rotation lengths, shared commander), Commerce Operations (product → tier dictionary lookup, variable escalation delays/repeats/working windows, shared weekly fallback). Alice administers all four; Bob is an employee in Acme/Regional, Carol in Acme/Support/Commerce. Regional times use the workspace scheduling zone, not a per-region zone. Disabled Sandbox and Legacy export illustrate filtering; enabling the latter requires adding its missing retired tier or choosing an existing tier. All examples use normal generation preview/apply and demo cleanup; provider remains local preview.

The main Acme Engineering demo contains six services (Payments, Search, Billing, Identity, Data platform, Developer portal), each with two or three ordered owners drawn from five login members: alice, bob, carol, dave, erin. All five share the weekly Monday 11:00 Time off rotation. Dave and Erin only access Acme; Carol also has Support/Commerce access through her groups. Other demo workspaces remain separate. The login password is the one generated for the run.

Single workspace schema

Migration 8 replaces the former tenant/team tables with workspaces and workspace memberships. It requires an empty legacy schema; it refuses to erase a populated non-demo database. Demo startup resets only provenance-verified demo data before migrations and recreates four independent workspaces. No history conversion or runtime compatibility layer is provided. All settings and generation state share the workspace revision. API paths are /api/workspaces/{workspace}; navigation uses ?workspace=.... PostgreSQL integration tests use the dedicated meguri_workspace_test database.

The default Engineering example stores projects as one list of dictionaries: each entry has name and an ordered responsible person list. The Project iteration reads both fields directly from its current entry; no parallel responsible lookup variable is needed. The independent on_call list still defines the shared weekly rotation.

Generation map uses locally vendored Cytoscape.js 3.33.1 (static/vendor/cytoscape.js, adjacent MIT license), with no CDN requests or Node build requirement. Its preset lane layout and inspector live in static/generation-map.js / .html; engine trace data is returned by the authorized generation-preview endpoint. Run node tests/browser-generation-map.cjs against the disposable demo for nested iterations, filtering, diagnostics, read-only behavior, canvas interactions and mobile layout.

Browser-check sandboxes

Browser suites that change data cannot reuse the example workspaces: approved replacements are permanent history, so a schedule that has one can never be removed. Start the demo with MEGURI_DEMO_SANDBOXES=12 to add empty Sandbox 1..12 workspaces, each with its own administrator group sandbox-N-leads and employee group sandbox-N-staff. Every mutating suite creates a throwaway password user in its own sandbox through the instance-administrator API. Restart the demo before each full run; sandboxes are not reset.