feat(seed): production per-account PSA demo, gated to production (PMS-710) #485

Merged
longjacksonle merged 3 commits from feat/PMS-710-per-account-psa-seed into main 2026-08-02 23:01:48 +02:00

PMS-710: Redefine seed data per environment

Production seeds a small, coherent set of Mokosh PSA examples for each new account; staging (and every non-production environment) seeds nothing automatically.

Trace (acceptance criterion 1)

Three seed systems exist. Only mokosh-server's per-account SeedService is the "new account" seed; the others are out of scope.

  • bunyip seed.rs - the admin "Demo MSP"/"minimal" templates seed PLATFORM entities (users/apps/groups/feedback) under the reserved email domain demo.psa-systems.test. That reserved domain is a bunyip reset-scope key (PSA-56), not a mokosh concept, and is unrelated to per-account PSA seeding. (The Demo MSP button defect is PMS-709, already fixed and separate.)
  • mokosh-server SeedService (PMS-157) - the first-visit per-account auto-seed. Before this change: one company, two contacts, three tickets, tagged demo, data-driven from demo_seed.json. Also backs the Settings -> Data "Load demo data" button (PMS-679).
  • mokosh-server showcase/qa - operator/CLI-only rich datasets that explicitly refuse production tenants. Out of scope.

Environment / tenant facts that shaped the design:

  • Both prod and staging currently set MOKOSH_DEMO_SEED: "false", so the per-account seed was OFF in both. Production seeded nothing either.
  • The PMS-239 shared-tenant funnel is already retired in code: PMS-244/245 give each self-signup their own personal tenant (ensure_personal_tenant, which runs copy_default_config), and users stuck in the shared default get backfilled off it. So per-account scoping is already the model - the auto-seed scopes to the visiting personal tenant. No shared demo domain is involved on the mokosh side.

Change (mokosh-server code + tests)

  • Content (demo_seed.json + data.rs): widened to two companies, four contacts, one service SLA (attached to a client via company.sla_id), two projects (one active with a phase and a task), and five tickets - enough that company -> contact -> ticket -> project -> SLA relationships are visible, and no more. Human content stays in the JSON; FK wiring and structural fields live in the builders. SeedService drives the projects and SLA services too, in FK order; the project phase/task and each ticket are best-effort so a tenant missing default config still gets the core rows. Ticket sla_id is intentionally left to the SLA subsystem; the durable "client is on an SLA" relationship is company.sla_id.
  • Gate (service.rs): the automatic first-visit seed runs in ENVIRONMENT=production only; every other environment seeds nothing unless a developer sets MOKOSH_DEMO_SEED=true. The decision is a pure, unit-tested seed_enabled_for(environment, override) captured once into a per-instance enabled flag (with_seed_enabled for tests). The explicit "Load demo data" admin action is unchanged and not gated.
  • Tests: data.rs bundle-shape unit test; service.rs gate unit tests (production seeds, staging/dev do not, dev honours the opt-in); tests/seed_demo.rs updated to the new profile with a company -> SLA relationship assertion, plus a new auto_seed_is_a_no_op_when_the_gate_is_off proving staging seeds nothing.

Verification

cargo fmt --check, clippy --all-targets -D warnings, lib + doc tests, and the seed_demo Postgres suite (8 tests) all pass. Full integration suite is green except three pre-existing upload/attachment tests that fail only in my sandbox with Permission denied (os error 13) writing files to disk - a filesystem-permission artifact unrelated to this change (it touches no storage code). Not yet run against live staging.

Acceptance status

  • Current seed behavior traced and documented (above; reserved demo domain is a bunyip concept, not used per-account).
  • Production seed creates only Mokosh PSA examples (tickets, SLA, projects, contacts, companies).
  • Seeded content scoped to the new account (the visiting personal tenant), not a shared demo domain.
  • No demo seed load runs in staging (env gate + auto_seed_is_a_no_op_when_the_gate_is_off).
  • Tests cover the production profile and assert staging seeds nothing.

Deferred by agreement (scoped to mokosh-server code this pass):

  • Docker config: none required for production to start seeding (the gate keys on ENVIRONMENT=production, so the stale MOKOSH_DEMO_SEED: "false" in nc-01 is now a no-op). Cleaning that stale line from nc-01/c-01 is optional hygiene.
  • MAPPS-352 reconciliation (selectable setup templates) - to be noted on that issue: with production seeding now per-account and minimal, selectable templates are no longer needed there.
  • "A new production account shows the example content" - to confirm on live staging/production after deploy.
## PMS-710: Redefine seed data per environment Production seeds a small, coherent set of Mokosh PSA examples for each new account; staging (and every non-production environment) seeds nothing automatically. ### Trace (acceptance criterion 1) Three seed systems exist. Only mokosh-server's per-account `SeedService` is the "new account" seed; the others are out of scope. - **bunyip `seed.rs`** - the admin "Demo MSP"/"minimal" templates seed PLATFORM entities (users/apps/groups/feedback) under the reserved email domain `demo.psa-systems.test`. That reserved domain is a bunyip reset-scope key (PSA-56), not a mokosh concept, and is unrelated to per-account PSA seeding. (The Demo MSP button defect is PMS-709, already fixed and separate.) - **mokosh-server `SeedService`** (PMS-157) - the first-visit per-account auto-seed. Before this change: one company, two contacts, three tickets, tagged `demo`, data-driven from `demo_seed.json`. Also backs the Settings -> Data "Load demo data" button (PMS-679). - **mokosh-server `showcase`/`qa`** - operator/CLI-only rich datasets that explicitly refuse production tenants. Out of scope. Environment / tenant facts that shaped the design: - Both prod and staging currently set `MOKOSH_DEMO_SEED: "false"`, so the per-account seed was OFF in both. Production seeded nothing either. - The PMS-239 shared-tenant funnel is already retired in code: PMS-244/245 give each self-signup their own personal tenant (`ensure_personal_tenant`, which runs `copy_default_config`), and users stuck in the shared default get backfilled off it. So per-account scoping is already the model - the auto-seed scopes to the visiting personal tenant. No shared demo domain is involved on the mokosh side. ### Change (mokosh-server code + tests) - **Content** (`demo_seed.json` + `data.rs`): widened to two companies, four contacts, one service SLA (attached to a client via `company.sla_id`), two projects (one active with a phase and a task), and five tickets - enough that company -> contact -> ticket -> project -> SLA relationships are visible, and no more. Human content stays in the JSON; FK wiring and structural fields live in the builders. `SeedService` drives the projects and SLA services too, in FK order; the project phase/task and each ticket are best-effort so a tenant missing default config still gets the core rows. Ticket `sla_id` is intentionally left to the SLA subsystem; the durable "client is on an SLA" relationship is `company.sla_id`. - **Gate** (`service.rs`): the automatic first-visit seed runs in `ENVIRONMENT=production` only; every other environment seeds nothing unless a developer sets `MOKOSH_DEMO_SEED=true`. The decision is a pure, unit-tested `seed_enabled_for(environment, override)` captured once into a per-instance `enabled` flag (`with_seed_enabled` for tests). The explicit "Load demo data" admin action is unchanged and not gated. - **Tests**: `data.rs` bundle-shape unit test; `service.rs` gate unit tests (production seeds, staging/dev do not, dev honours the opt-in); `tests/seed_demo.rs` updated to the new profile with a company -> SLA relationship assertion, plus a new `auto_seed_is_a_no_op_when_the_gate_is_off` proving staging seeds nothing. ### Verification `cargo fmt --check`, `clippy --all-targets -D warnings`, lib + doc tests, and the `seed_demo` Postgres suite (8 tests) all pass. Full integration suite is green except three pre-existing upload/attachment tests that fail only in my sandbox with `Permission denied (os error 13)` writing files to disk - a filesystem-permission artifact unrelated to this change (it touches no storage code). Not yet run against live staging. ### Acceptance status - [x] Current seed behavior traced and documented (above; reserved demo domain is a bunyip concept, not used per-account). - [x] Production seed creates only Mokosh PSA examples (tickets, SLA, projects, contacts, companies). - [x] Seeded content scoped to the new account (the visiting personal tenant), not a shared demo domain. - [x] No demo seed load runs in staging (env gate + `auto_seed_is_a_no_op_when_the_gate_is_off`). - [x] Tests cover the production profile and assert staging seeds nothing. Deferred by agreement (scoped to mokosh-server code this pass): - **Docker config**: none required for production to start seeding (the gate keys on `ENVIRONMENT=production`, so the stale `MOKOSH_DEMO_SEED: "false"` in nc-01 is now a no-op). Cleaning that stale line from nc-01/c-01 is optional hygiene. - **MAPPS-352** reconciliation (selectable setup templates) - to be noted on that issue: with production seeding now per-account and minimal, selectable templates are no longer needed there. - **"A new production account shows the example content"** - to confirm on live staging/production after deploy.
Redefine the first-visit demo seed so a brand-new production account (each self-signup gets its own personal tenant, PMS-244) sees a small, connected set of Mokosh PSA examples instead of an empty shell, and so no environment other than production seeds automatically.

Content: widen the `demo_seed.json` bundle + `data.rs` builders from one company / two contacts / three tickets to two companies, four contacts, one service SLA (attached to a client via `company.sla_id`), two projects (one active with a phase and a task), and five tickets - enough that the company -> contact -> ticket -> project -> SLA relationships are visible, and no more. Human content stays in the JSON; FK wiring and structural fields (dates, budgets, billing) live in the builders. `SeedService` now drives the projects and SLA services too, in FK-dependency order; the project phase/task and each ticket stay best-effort so a tenant missing default config still gets the core rows.

Gate: the automatic first-visit seed runs in `ENVIRONMENT=production` only. Staging is the shared demo environment where people log in to see the real, current app, so it is kept clean; dev/test seed nothing unless a developer sets `MOKOSH_DEMO_SEED=true`. The decision is a pure, unit-tested function (`seed_enabled_for`) captured once into a per-instance `enabled` flag that tests can pin via `with_seed_enabled`. The explicit admin "Load demo data" action is unchanged and not gated. This retires `MOKOSH_DEMO_SEED` as the production on/off, so no docker config change is needed for production to start seeding.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V9DhtRyWubFuzzKohE3JBt
test(seed): cover the PMS-710 production profile and the gate (PMS-710)
Some checks failed
Check / fmt + clippy + build + tests (pull_request) Successful in 3m50s
Integration / integration tests (pull_request) Successful in 8m6s
E2E / Playwright against staging (pull_request) Failing after 1m39s
2d44993bc5
Update the first-visit integration suite to the widened dataset (two companies, four contacts, one demo SLA, two projects, five tickets) and assert the durable company -> SLA relationship. Pin the environment gate with `with_seed_enabled(true)` so the auto-seed tests do not depend on the process ENVIRONMENT, and add `auto_seed_is_a_no_op_when_the_gate_is_off` to prove staging seeds nothing at the service level. The demo SLA is counted by name because a fresh tenant already ships a default SLA policy.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V9DhtRyWubFuzzKohE3JBt
longjacksonle scheduled this pull request to auto merge when all checks succeed 2026-08-02 22:39:21 +02:00
Merge branch 'main' into feat/PMS-710-per-account-psa-seed
All checks were successful
Check / fmt + clippy + build + tests (pull_request) Successful in 1m39s
E2E / Playwright against staging (pull_request) Successful in 1m35s
Create release / Gate (release-branch merges only) (pull_request) Successful in 7s
Create release / Create release from merged PR (pull_request) Has been skipped
Integration / integration tests (pull_request) Successful in 5m10s
383332d345
longjacksonle deleted branch feat/PMS-710-per-account-psa-seed 2026-08-02 23:01:49 +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!485
No description provided.