mirror of
https://github.com/Sea-Haven-Industries/shoc-pr-review-runner.git
synced 2026-09-30 07:23:11 +00:00
148 lines
8.7 KiB
Markdown
148 lines
8.7 KiB
Markdown
|
|
# Phase 2 TODO — Runtime Environment (disposable DB, startup, API checks)
|
||
|
|
|
||
|
|
Scope (spec Phase 2): disposable database, migration validation, backend
|
||
|
|
startup + health gate, frontend startup, shared environment variables, API
|
||
|
|
runtime checks, process/log management. Everything below turns an existing
|
||
|
|
`NOT_RUN` line in `review-evidence.md` into a real gate recorded through
|
||
|
|
`scripts/lib.sh` (`record_gate`/`run_gate`). Facts about the product repos were
|
||
|
|
verified 2026-07-29; trust them over the original spec draft (which wrongly
|
||
|
|
said PostgreSQL — the backend is EF Core 8.0.8 + SQL Server).
|
||
|
|
|
||
|
|
## Ordered work plan
|
||
|
|
|
||
|
|
### 1. Workflow: SQL Server service container
|
||
|
|
- Add a `services: mssql` block to the `review` job in
|
||
|
|
`.github/workflows/review-pr.yml`: `mcr.microsoft.com/mssql/server:2022-latest`,
|
||
|
|
port `1433:1433`, `ACCEPT_EULA=Y`, `MSSQL_SA_PASSWORD` (see open questions),
|
||
|
|
container health-cmd so the job waits for readiness. No compose file exists in
|
||
|
|
shoc-backend; the service container is the whole database story.
|
||
|
|
- Install `sqlcmd` on the runner (`mssql-tools18` apt package) in a step gated
|
||
|
|
on backend/paired, before provisioning.
|
||
|
|
- Generate per-run runtime secrets in an early step: `JWT_SECRET`
|
||
|
|
(`openssl rand -hex 32` — must be ≥32 chars or login 500s) and the DB
|
||
|
|
password if per-run. Add both to `redact-check.sh`'s scan set.
|
||
|
|
|
||
|
|
### 2. New scripts (all source `lib.sh`, all gated on backend/paired unless noted)
|
||
|
|
- `scripts/proc.sh` — shared process-management helpers sourced next to
|
||
|
|
`lib.sh`: `start_bg <name> <logfile> <cmd...>` (nohup, PID to
|
||
|
|
`$ARTIFACTS_DIR/pids/<name>.pid`, log to `$LOG_DIR`), `stop_bg`,
|
||
|
|
`stop_all_bg` (kill + wait, idempotent, never fails the caller).
|
||
|
|
- `scripts/provision-database.sh` — wait for SQL Server, `CREATE DATABASE
|
||
|
|
ShocReview` via sqlcmd; gate `backend.db_provision`.
|
||
|
|
- `scripts/run-migration-gates.sh` — migration validation (see §3); gates
|
||
|
|
`backend.migration_list`, `backend.migration_script`, `backend.migration_apply`.
|
||
|
|
- `scripts/seed-admin-user.sh` — direct-SQL identity seed (see §4); gate
|
||
|
|
`backend.seed_admin`.
|
||
|
|
- `scripts/start-backend.sh` — start the API via `proc.sh`, poll health, run
|
||
|
|
the DB-touching assertion (see §5); gates `backend.startup`, `backend.health`.
|
||
|
|
- `scripts/run-api-checks.sh` — authenticated runtime scenarios (see §6);
|
||
|
|
gate `backend.api_runtime` (plus per-scenario detail in the gate table).
|
||
|
|
- `scripts/start-frontend.sh` — frontend runtime startup (see §7); gates
|
||
|
|
`frontend.dev_startup`, `frontend.preview_build`, `frontend.preview_startup`.
|
||
|
|
Gated on frontend/paired; runtime API checks require paired (else NOT_RUN
|
||
|
|
with reason "no live backend in frontend-only review").
|
||
|
|
- `scripts/stop-runtime.sh` — calls `stop_all_bg`; wired as an `if: always()`
|
||
|
|
workflow step so backend/frontend processes are stopped even after failed
|
||
|
|
stages (spec requirement), before evidence generation and artifact upload.
|
||
|
|
|
||
|
|
### 3. Migration validation detail
|
||
|
|
- 43 migrations live in `Data.SeaHavenIndustries/Migrations/`; there is NO
|
||
|
|
migrate-on-startup and NO `IDesignTimeDbContextFactory`.
|
||
|
|
- `dotnet tool restore` must run from `Api.SeaHavenIndustries/` (the tool
|
||
|
|
manifest — dotnet-ef 8.0.8, rollForward false — is at
|
||
|
|
`Api.SeaHavenIndustries/.config/dotnet-tools.json`).
|
||
|
|
- Every `dotnet ef` call needs `--project Data.SeaHavenIndustries/... --startup-project
|
||
|
|
Api.SeaHavenIndustries/...`.
|
||
|
|
- Gates: `migrations list` (enumerates cleanly), `migrations script
|
||
|
|
--idempotent -o $ARTIFACTS_DIR/migrations.sql` (SQL generation as artifact),
|
||
|
|
then apply. Prefer `database update`; the repo's own deploy uses
|
||
|
|
`ef migrations bundle --self-contained -r linux-x64` (see its
|
||
|
|
`scripts/package-elastic-beanstalk.sh`) — bundle is the fidelity option if
|
||
|
|
`database update` misbehaves.
|
||
|
|
|
||
|
|
### 4. Seeding strategy (first-admin bootstrap gap)
|
||
|
|
- No register endpoint; `UserController.AddUser` is `[Authorize]`; API user
|
||
|
|
creation emails passwords via SendGrid; the Program.cs role-seeding block is
|
||
|
|
fully commented out (Program.cs:199-253). So: seed by direct SQL.
|
||
|
|
- `seed-admin-user.sh` runs a `templates/seed-admin.sql` via sqlcmd inserting
|
||
|
|
`AspNetRoles` ("Admin" — the only role enforced in `[Authorize]` attributes),
|
||
|
|
`AspNetUsers` (fixed reviewer account, precomputed ASP.NET Identity v3
|
||
|
|
PBKDF2 password hash), `AspNetUserRoles`.
|
||
|
|
- The known password + hash pair is committed (disposable localhost-only DB;
|
||
|
|
document as non-sensitive). Run after migration apply, before startup.
|
||
|
|
|
||
|
|
### 5. Backend startup + health
|
||
|
|
- Start `dotnet run --project Api.SeaHavenIndustries/... --no-build -c Release`
|
||
|
|
(or run the built DLL) via `proc.sh` with the shared env (§8).
|
||
|
|
- NO anonymous /health endpoint exists (the only health-ish route is
|
||
|
|
Admin-authorized). Health probe = `GET /swagger/v1/swagger.json` with retry
|
||
|
|
budget; requires `ASPNETCORE_ENVIRONMENT=Development` (anything else disables
|
||
|
|
Swagger AND enables HTTPS redirect).
|
||
|
|
- Swagger 200 ≠ DB configured: the committed appsettings placeholder
|
||
|
|
`"${CONNECTION_STRING}"` lets the app start and fail per-request. So the
|
||
|
|
health gate also asserts DB wiring: `POST /api/Authentication/login` with bad
|
||
|
|
creds must return 401 — a 500 means the connection string didn't take.
|
||
|
|
- Expect log noise: 4 hosted services start at boot; the vendor-document scan
|
||
|
|
worker polls the DB every 30s. Capture full stdout/stderr to
|
||
|
|
`logs/backend-runtime.log`; evidence links it.
|
||
|
|
|
||
|
|
### 6. API runtime checks
|
||
|
|
- With the seeded admin: login → 200 + JWT; call one Admin-authorized
|
||
|
|
endpoint with the token → 200; call it unauthenticated → 401.
|
||
|
|
- Record known limitation: ClamAV__Host is empty, so vendor uploads return
|
||
|
|
423 — assert-and-record as limitation, not failure.
|
||
|
|
|
||
|
|
### 7. Frontend runtime
|
||
|
|
- Dev startup gate: `npm run dev` with `VITE_API_TARGET=http://127.0.0.1:5141`
|
||
|
|
(the dev proxy target env var), probe `http://127.0.0.1:3000/` for 200.
|
||
|
|
- Production preview: `vite preview` (4173) has NO /api proxy, so a preview
|
||
|
|
against the local backend needs a second build with absolute
|
||
|
|
`VITE_API_URL=http://127.0.0.1:5141/api` baked at BUILD time (must end in
|
||
|
|
`/api` or the build-time contract guard throws; the Phase-1 gate build uses
|
||
|
|
relative `/api` and cannot be reused). Then probe 4173.
|
||
|
|
- Playwright's own dev server on 4173 is untouched (mocked suite unchanged).
|
||
|
|
|
||
|
|
### 8. Shared environment variables (one place: workflow env + runner-config)
|
||
|
|
- `ConnectionStrings__DefaultConnection` = `Server=127.0.0.1,1433;Database=ShocReview;User Id=sa;Password=...;TrustServerCertificate=True`
|
||
|
|
- `JWT__Secret` = per-run ≥32 chars (the committed `"${JWT_SECRET}"`
|
||
|
|
placeholder passes the null check but breaks login — never rely on it)
|
||
|
|
- `ASPNETCORE_ENVIRONMENT=Development`, `ASPNETCORE_URLS=http://127.0.0.1:5141`
|
||
|
|
- `WorkOrderIngest__Enabled=false`, `Sync__Enabled=false`,
|
||
|
|
`WorkOrderReconciliation__Enabled=false`, `ClamAV__Host=` (empty)
|
||
|
|
|
||
|
|
### 9. `review/runner-config.yml` additions
|
||
|
|
- `database:` extend with db name, sa-password sourcing, sqlcmd tooling.
|
||
|
|
- `backend:` add `runtime_env` block (§8 values), health retry budget,
|
||
|
|
seed account name, migration project paths.
|
||
|
|
- `frontend:` add `preview_port: 4173`, `dev_api_target`, preview build env.
|
||
|
|
- Keep the workflow-env mirror rule (CI cross-checks the pair).
|
||
|
|
|
||
|
|
### 10. Evidence report (`generate-evidence.sh`)
|
||
|
|
- Backend Gates: Migration list/script/apply, Startup, Health endpoint, API
|
||
|
|
runtime scenarios switch from hardcoded NOT_RUN to `$(be_gate ...)`; add DB
|
||
|
|
provision + admin seed lines.
|
||
|
|
- Frontend Gates: Development startup and Production preview switch to
|
||
|
|
`$(fe_gate ...)`.
|
||
|
|
- Runtime Limitations rewritten: enumerate disabled integrations (ingest,
|
||
|
|
sync, reconciliation, ClamAV → uploads 423), note JWT secret and DB are
|
||
|
|
runner-provided, keep "mocked Playwright ≠ live coverage".
|
||
|
|
- Tests: new fixtures in `tests/fixtures/artifacts/` covering runtime-gate
|
||
|
|
PASS/FAIL rows; extend CI bash tests for `proc.sh` start/stop semantics.
|
||
|
|
|
||
|
|
## Out of scope (Phase 3+)
|
||
|
|
- Live Playwright against the running stack, affected-route walking, console/
|
||
|
|
failed-request capture (Phase 3). Stacked/paired PR intelligence (Phase 4).
|
||
|
|
- Fixing shoc-backend itself (health endpoint, seeding block) — record gaps.
|
||
|
|
|
||
|
|
## Open questions
|
||
|
|
1. `MSSQL_SA_PASSWORD`: fixed throwaway (service env can't consume step
|
||
|
|
outputs) vs repo secret? Leaning fixed + documented non-sensitive.
|
||
|
|
2. sqlcmd via apt `mssql-tools18` vs `docker exec` into the service container?
|
||
|
|
3. Migration apply: `dotnet ef database update` vs the repo's own bundle path?
|
||
|
|
4. Is the dev-server startup gate worth its runtime once preview startup
|
||
|
|
exists, or is preview + dev-proxy config check enough?
|
||
|
|
5. Which Admin endpoint is the canonical authenticated smoke check (stable,
|
||
|
|
read-only, no side effects/emails)?
|
||
|
|
6. Should `backend.health` failing hard-block the frontend preview gates in
|
||
|
|
paired runs (BLOCKED) or let them probe independently?
|