Skip to content

Local stack bring-up

Relocated from the root CLAUDE.md. See also Quartz local development and local MongoDB development.

Local stack bring-up invariant (scripts/setup-local.sh + process-compose.yaml)

The local stack deliberately runs API and Project Management with two different ActiveEnvironment readings, and both are load-bearing. Do not "simplify" either side.

  • Overlay selection is command-line. setup-local.sh appends -- ... --ActiveEnvironment=local to CMD_API/CMD_PM (and already did for CMD_QUARTZ). HostExtensions.GetEnvironmentName() builds its probe with AddCommandLine last, and its result selects appsettings.{env}.json. Remove the flag and the services look for a non-existent appsettings.staging.json, so the generated per-worktree appsettings.local.json — Mongo/RabbitMQ ports, mock OIDC — is never loaded and startup fails.
  • Effective identity is the SYRF__ environment. process-compose.yaml exports SYRF__RuntimeEnvironment=staging, SYRF__ActiveEnvironment=staging and SYRF__BulkPdfStorage__EnvironmentRoot=staging. CreateSyrfWebApplicationBuilder appends AddEnvironmentVariables("SYRF__") after the WebApplicationBuilder's own command-line source, so the effective ActiveEnvironment value stays staging and BulkPdfDeploymentIdentity still matches exactly. Reordering those two sources breaks one side or the other.
  • Application arguments go after --. dotnet run parses --urls as its own option otherwise.
  • Only BulkPdfStorage:PublicBaseUrl points at pdf-static. pdf-static serves the agent's bulk output directory alone. PdfSettings:BaseUrl is the legacy link base used by BulkPdfLinkService for studies without a BulkPdfDeliveredPath; it keeps the local template's own value and must not be overridden to the bulk server.
  • Compose project name. Every docker compose invocation passes -p "${COMPOSE_PROJECT_NAME:-syrf-local}". setup-local.sh exports a per-worktree name; direct process-compose invocations share syrf-local unless you export your own.

.github/scripts/test-local-bulk-pdf-authority.sh pins this contract; changing either side fails CI until the test is updated deliberately.