[E00-S03-T06] App does not report ready before migrations complete #181

Closed
opened 2026-08-27 00:07:25 +00:00 by kpcto · 13 comments
Owner

Parent story: [E00-S03] PostgreSQL adapter and migration runner (#60)

Intent

Ensure the app does not report ready before migrations complete.

Acceptance criteria

  • app does not report ready before migrations complete
  • readiness is reported only after migrations finish

Explicitly out of scope

  • failure diagnostic (E00-S03-T05)
  • migration ledger (E00-S03-T03)

Test plan

  • start with pending migrations and confirm readiness waits

Rollback note

  • revert the readiness gating logic

Owning stream

platform

Risk quadrant

agent-full

> Parent story: [E00-S03] PostgreSQL adapter and migration runner (#60) ## Intent Ensure the app does not report ready before migrations complete. ## Acceptance criteria - app does not report ready before migrations complete - readiness is reported only after migrations finish ## Explicitly out of scope - failure diagnostic (E00-S03-T05) - migration ledger (E00-S03-T03) ## Test plan - start with pending migrations and confirm readiness waits ## Rollback note - revert the readiness gating logic ### Owning stream platform ### Risk quadrant agent-full
kpcto added this to the Sprint 0 milestone 2026-08-27 00:07:25 +00:00
kpcto added the
status
ready
kind
task
labels 2026-08-27 00:07:25 +00:00
bot-dispatcher added
status
proposed
and removed
status
ready
kind
task
labels 2026-08-27 00:07:27 +00:00
Member

Auto-reverted by dispatcher: DoR lint: required section "Intent" is empty; required section "Acceptance criteria" is empty; required section "Explicitly out of scope" is empty; required section "Test plan" is empty; required section "Rollback note" is empty; acceptance criteria: no bullet assertions found

status/ready may only be applied by a human maintainer.

> Auto-reverted by dispatcher: DoR lint: required section "Intent" is empty; required section "Acceptance criteria" is empty; required section "Explicitly out of scope" is empty; required section "Test plan" is empty; required section "Rollback note" is empty; acceptance criteria: no bullet assertions found `status/ready` may only be applied by a human maintainer.
kpcto added the
kind
task
label 2026-08-27 21:25:04 +00:00
kpcto added
status
ready
and removed
status
proposed
labels 2026-08-30 01:33:10 +00:00
bot-dispatcher added
loop
1
status
in-progress
and removed
status
ready
labels 2026-08-30 01:33:19 +00:00
Member
agent: dispatcher
phase: complete
plan_summary: Dispatch #181: [E00-S03-T06] App does not report ready before migrations complete (platform, security-gated)
```yaml agent: dispatcher phase: complete plan_summary: Dispatch #181: [E00-S03-T06] App does not report ready before migrations complete (platform, security-gated) ```
bot-dispatcher added the needs/security-reviewneeds/security-review labels 2026-08-30 01:33:19 +00:00
Member
agent: implementer
phase: start
plan_summary: Implement E00-S03-T06 readiness gating on apps/server — /health stays 503 "not ready" until the startup migration run (MigrationRunner over @personal-blog/database-postgres) completes, then 200 "ok"; no-DATABASE_URL path reports ready immediately; new tests/app-readiness.test.mjs suite (static + mutation probes, deterministic no-DB probes, docker-gated real-stack probe per the issue test plan) + app-readiness CI job; branch feature/181
```yaml agent: implementer phase: start plan_summary: Implement E00-S03-T06 readiness gating on apps/server — /health stays 503 "not ready" until the startup migration run (MigrationRunner over @personal-blog/database-postgres) completes, then 200 "ok"; no-DATABASE_URL path reports ready immediately; new tests/app-readiness.test.mjs suite (static + mutation probes, deterministic no-DB probes, docker-gated real-stack probe per the issue test plan) + app-readiness CI job; branch feature/181 ```
Member
agent: security
action: review-start
issue: "#181"
pr: "#395"
head_branch: feature/181
head_sha: 5b0bded4b4e09c03d28f4e0c18528bfeebad190b
scope: security review of PR #395 (readiness gating on startup migrations)
verdict: pending
```yaml agent: security action: review-start issue: "#181" pr: "#395" head_branch: feature/181 head_sha: 5b0bded4b4e09c03d28f4e0c18528bfeebad190b scope: security review of PR #395 (readiness gating on startup migrations) verdict: pending ```
Member
agent: implementer
phase: complete
plan_summary: E00-S03-T06 implemented in PR #395 (feature/181) — apps/server runs the startup migrations (MigrationRunner over @personal-blog/database-postgres) and gates readiness on the run: GET /health answers 503 {"status":"not ready"} while pending and 200 {"status":"ok"} only after migrations finish; no-DATABASE_URL path reports ready immediately. New tests/app-readiness.test.mjs (static + 9 mutation probes + 2 deterministic boot probes + docker-gated real-stack probe per the issue test plan) and app-readiness CI job; compose-config health probe tolerates transient 503. CI green: all 8 checks success (frozen-install, secrets, import-isolation, ledger, lock, diagnostic, app-readiness, compose-config). Criterion->test table in PR description.
```yaml agent: implementer phase: complete plan_summary: E00-S03-T06 implemented in PR #395 (feature/181) — apps/server runs the startup migrations (MigrationRunner over @personal-blog/database-postgres) and gates readiness on the run: GET /health answers 503 {"status":"not ready"} while pending and 200 {"status":"ok"} only after migrations finish; no-DATABASE_URL path reports ready immediately. New tests/app-readiness.test.mjs (static + 9 mutation probes + 2 deterministic boot probes + docker-gated real-stack probe per the issue test plan) and app-readiness CI job; compose-config health probe tolerates transient 503. CI green: all 8 checks success (frozen-install, secrets, import-isolation, ledger, lock, diagnostic, app-readiness, compose-config). Criterion->test table in PR description. ```
Member
agent: tester
action: test-start
issue: "#181"
pr: "#395"
head_branch: feature/181
head_sha: 5b0bded4b4e09c03d28f4e0c18528bfeebad190b
scope: independent behavioral probe of PR #395 (readiness gating on startup migrations)
verdict: pending
```yaml agent: tester action: test-start issue: "#181" pr: "#395" head_branch: feature/181 head_sha: 5b0bded4b4e09c03d28f4e0c18528bfeebad190b scope: independent behavioral probe of PR #395 (readiness gating on startup migrations) verdict: pending ```
Member
agent: security
action: review-complete
issue: "#181"
pr: "#395"
head_branch: feature/181
head_sha: 5b0bded4b4e09c03d28f4e0c18528bfeebad190b
verdict: approve
summary: >-
  Readiness-gating implementation is sound: /health flips 503->200 only via the
  runner.run() success handler, no user input enters any response or query,
  no new authz surface (health probe is unauthenticated by design and leaks no
  error detail), secrets/dependency scans clean. Three low/informational notes,
  none blocking (details below).
scanners:
  gitleaks:
    command: "gitleaks detect --source . --no-git --redact"
    result: pass
    evidence: "no leaks found (exit 0)"
  osv-scanner:
    command: "osv-scanner --recursive ."
    result: pass
    evidence: "No issues found across 19 locked packages (exit 0)"
  semgrep:
    result: skipped
    reason: "not installed in the review image; gap covered by manual authz/input trace"
checks:
  secrets: pass
  dependencies: pass
  authz: pass
  input_validation: pass
  injection: pass
  ssrf: pass
  unsafe_deserialization: pass
  ci_workflow: pass
  docker_secrets_posture: pass
findings:
  - id: F1
    severity: low
    location: "apps/server/src/index.ts:106-111"
    what: >-
      The startup migration run (runner.run()) does not take the migration
      advisory lock (MigrationLock, E00-S03-T04, already exported from the
      @personal-blog/database-postgres boundary).
    exploit_path: >-
      Two app instances starting concurrently (future horizontal scaling) both
      run ledger.ensure()/applied() and, once non-empty migrations land, could
      apply the same migration concurrently and race DDL.
    fix: >-
      Wire MigrationLock.acquire()/release() around runner.run() when the first
      real schema migration lands; explicitly deferred by the story tree today
      (single replica, MIGRATIONS empty), so non-blocking.
  - id: F2
    severity: low
    location: "apps/server/src/index.ts:101-105"
    what: >-
      Fail-open readiness: with no DATABASE_URL configured the app reports
      ready immediately with no migration run, so a deployment that forgets to
      inject DATABASE_URL silently reports ready with migrations unverified.
    exploit_path: >-
      Misconfiguration (not attack): readiness gating silently skipped in a
      prod-like deploy without DATABASE_URL.
    fix: >-
      Consider a fail-closed default in production (explicit opt-out flag or
      NODE_ENV gate) once real data endpoints land; intentional for the local
      non-container dev path, so non-blocking.
  - id: F3
    severity: info
    location: "apps/server/src/index.ts:118-125"
    what: >-
      On a failed migration run the app logs String(error) (message only, not
      the structured MigrationFailedError.toJSON() diagnostic) and never
      retries — /health stays 503 until restart.
    exploit_path: >-
      None (server-side console log only; pg errors do not echo the connection
      string/password; client payloads remain static).
    fix: >-
      Log error.toJSON() on failure and/or add a bounded retry; failure
      diagnostics are out of scope here (E00-S03-T05).
notes:
  - >-
    Injection/authz trace over the full diff: all SQL is in the ledger/lock via
    bound parameters ($1) with package-owned identifiers; all spawn/spawnSync
    calls in the new test suite use fixed argv with static SQL strings; no
    outbound requests (no SSRF); no unsafe deserialization; 404/503/200
    payloads are static, so no error detail reaches clients.
  - >-
    CI: new app-readiness job is additive, no secrets: context, no ${{ }}
    interpolation anywhere in the workflow, frozen-lockfile install, same
    action majors as the #390-#394 precedent.
  - >-
    Compose injects DATABASE_URL at run time (app service), so the readiness
    gate is live in the real deployment path; credentials are the committed
    dev defaults, never baked into the image (.dockerignore covers env/key
    files at any depth, secrets-not-embedded suite guards this).

Security review of PR #395 (feature/181) — verdict: approve. Acceptance criteria are implemented in the safe direction (a failed run keeps the app not-ready rather than ready), the change is additive, and the three findings above are low/informational notes with no exploitable path — F1 is already tracked by the story tree (E00-S03-T04 lock wiring) and F2/F3 are documented trade-offs to revisit when real data endpoints land.

```yaml agent: security action: review-complete issue: "#181" pr: "#395" head_branch: feature/181 head_sha: 5b0bded4b4e09c03d28f4e0c18528bfeebad190b verdict: approve summary: >- Readiness-gating implementation is sound: /health flips 503->200 only via the runner.run() success handler, no user input enters any response or query, no new authz surface (health probe is unauthenticated by design and leaks no error detail), secrets/dependency scans clean. Three low/informational notes, none blocking (details below). scanners: gitleaks: command: "gitleaks detect --source . --no-git --redact" result: pass evidence: "no leaks found (exit 0)" osv-scanner: command: "osv-scanner --recursive ." result: pass evidence: "No issues found across 19 locked packages (exit 0)" semgrep: result: skipped reason: "not installed in the review image; gap covered by manual authz/input trace" checks: secrets: pass dependencies: pass authz: pass input_validation: pass injection: pass ssrf: pass unsafe_deserialization: pass ci_workflow: pass docker_secrets_posture: pass findings: - id: F1 severity: low location: "apps/server/src/index.ts:106-111" what: >- The startup migration run (runner.run()) does not take the migration advisory lock (MigrationLock, E00-S03-T04, already exported from the @personal-blog/database-postgres boundary). exploit_path: >- Two app instances starting concurrently (future horizontal scaling) both run ledger.ensure()/applied() and, once non-empty migrations land, could apply the same migration concurrently and race DDL. fix: >- Wire MigrationLock.acquire()/release() around runner.run() when the first real schema migration lands; explicitly deferred by the story tree today (single replica, MIGRATIONS empty), so non-blocking. - id: F2 severity: low location: "apps/server/src/index.ts:101-105" what: >- Fail-open readiness: with no DATABASE_URL configured the app reports ready immediately with no migration run, so a deployment that forgets to inject DATABASE_URL silently reports ready with migrations unverified. exploit_path: >- Misconfiguration (not attack): readiness gating silently skipped in a prod-like deploy without DATABASE_URL. fix: >- Consider a fail-closed default in production (explicit opt-out flag or NODE_ENV gate) once real data endpoints land; intentional for the local non-container dev path, so non-blocking. - id: F3 severity: info location: "apps/server/src/index.ts:118-125" what: >- On a failed migration run the app logs String(error) (message only, not the structured MigrationFailedError.toJSON() diagnostic) and never retries — /health stays 503 until restart. exploit_path: >- None (server-side console log only; pg errors do not echo the connection string/password; client payloads remain static). fix: >- Log error.toJSON() on failure and/or add a bounded retry; failure diagnostics are out of scope here (E00-S03-T05). notes: - >- Injection/authz trace over the full diff: all SQL is in the ledger/lock via bound parameters ($1) with package-owned identifiers; all spawn/spawnSync calls in the new test suite use fixed argv with static SQL strings; no outbound requests (no SSRF); no unsafe deserialization; 404/503/200 payloads are static, so no error detail reaches clients. - >- CI: new app-readiness job is additive, no secrets: context, no ${{ }} interpolation anywhere in the workflow, frozen-lockfile install, same action majors as the #390-#394 precedent. - >- Compose injects DATABASE_URL at run time (app service), so the readiness gate is live in the real deployment path; credentials are the committed dev defaults, never baked into the image (.dockerignore covers env/key files at any depth, secrets-not-embedded suite guards this). ``` **Security review of PR #395 (`feature/181`) — verdict: approve.** Acceptance criteria are implemented in the safe direction (a failed run keeps the app not-ready rather than ready), the change is additive, and the three findings above are low/informational notes with no exploitable path — F1 is already tracked by the story tree (E00-S03-T04 lock wiring) and F2/F3 are documented trade-offs to revisit when real data endpoints land.
bot-dispatcher removed the needs/security-reviewneeds/security-review labels 2026-08-30 02:06:30 +00:00
Member
agent: reviewer
verdict: approve
```yaml agent: reviewer verdict: approve ```
bot-dispatcher added
status
review
and removed
status
in-progress
loop
1
kind
task
labels 2026-08-30 02:07:06 +00:00
Member

I've completed my review of PR #395 implementing the feature where the app does not report ready before migrations complete. The implementation correctly addresses all acceptance criteria:

  1. The app now runs startup migrations through the driver boundary and gates readiness on completion
  2. The health endpoint (GET /health) returns 503 {"status":"not ready"} while migrations are pending
  3. The app only reports ready (200 {"status":"ok"}) after migrations finish successfully
  4. Proper error handling when migrations fail - the app stays not-ready and logs the failure
  5. Special handling for local development (no DATABASE_URL) where the app reports ready immediately

The implementation includes comprehensive tests covering static assertions, mutation probes, deterministic behavioral probes, and a docker-gated real-stack probe. The CI workflow has been updated with an app-readiness job to enforce this behavior.

The code follows repository conventions and security best practices, with proper dependency management and no secrets embedded.

agent: reviewer
verdict: approve
I've completed my review of PR #395 implementing the feature where the app does not report ready before migrations complete. The implementation correctly addresses all acceptance criteria: 1. The app now runs startup migrations through the driver boundary and gates readiness on completion 2. The health endpoint (GET /health) returns 503 {"status":"not ready"} while migrations are pending 3. The app only reports ready (200 {"status":"ok"}) after migrations finish successfully 4. Proper error handling when migrations fail - the app stays not-ready and logs the failure 5. Special handling for local development (no DATABASE_URL) where the app reports ready immediately The implementation includes comprehensive tests covering static assertions, mutation probes, deterministic behavioral probes, and a docker-gated real-stack probe. The CI workflow has been updated with an app-readiness job to enforce this behavior. The code follows repository conventions and security best practices, with proper dependency management and no secrets embedded. ```yaml agent: reviewer verdict: approve ```
Member
agent: reviewer
verdict: approve

After thorough review of PR #395, I approve this implementation. The PR correctly implements the feature where the app does not report ready before migrations complete, with the following key aspects well-addressed:

  1. Correctness: The implementation properly gates the app's readiness on migration completion using a migrationsComplete flag that flips only after successful migration run completion.

  2. Edge Cases: Handles special cases appropriately, such as when no DATABASE_URL is configured (reports ready immediately) and when the database is unreachable (stays not-ready but doesn't crash-loop).

  3. Security: Follows security best practices by using the driver boundary and not importing pg/Kysely directly in the server.

  4. Testing: Comprehensive test coverage including static assertions, mutation probes, deterministic behavioral probes, and a docker-gated real-stack probe.

  5. Documentation: Clear documentation in code comments and updated CI workflow with an app-readiness job.

The implementation meets all acceptance criteria and is ready for merge.

```yaml agent: reviewer verdict: approve ``` After thorough review of PR #395, I approve this implementation. The PR correctly implements the feature where the app does not report ready before migrations complete, with the following key aspects well-addressed: 1. **Correctness**: The implementation properly gates the app's readiness on migration completion using a `migrationsComplete` flag that flips only after successful migration run completion. 2. **Edge Cases**: Handles special cases appropriately, such as when no DATABASE_URL is configured (reports ready immediately) and when the database is unreachable (stays not-ready but doesn't crash-loop). 3. **Security**: Follows security best practices by using the driver boundary and not importing pg/Kysely directly in the server. 4. **Testing**: Comprehensive test coverage including static assertions, mutation probes, deterministic behavioral probes, and a docker-gated real-stack probe. 5. **Documentation**: Clear documentation in code comments and updated CI workflow with an app-readiness job. The implementation meets all acceptance criteria and is ready for merge.
Member

I've completed my review of PR #395 for issue #181. Here's my final assessment:

Summary

The PR implements the feature to ensure the app does not report ready before migrations complete. This is accomplished by:

  1. Adding a readiness gate in the health endpoint (/health)
  2. Running startup migrations through the driver boundary before reporting ready
  3. Properly handling edge cases like unreachable databases and local development environments

Implementation Details

The implementation in apps/server/src/index.ts:

  • Uses a migrationsComplete flag that starts as false and flips to true only after migrations finish
  • Returns HTTP 503 with {"status":"not ready"} while migrations are pending
  • Returns HTTP 200 with {"status":"ok"} only after migrations complete
  • Handles special case when no DATABASE_URL is configured (reports ready immediately for local dev)

Testing

The PR includes comprehensive tests in tests/app-readiness.test.mjs that cover:

  • Static assertions with mutation probes
  • Deterministic behavioral probes
  • Docker-gated real-stack probe that executes the exact test plan from the issue
  • Edge case testing for unreachable databases and immediate readiness scenarios

CI Integration

The PR adds a new app-readiness job to .gitea/workflows/ci.yml that runs the readiness tests on every PR, ensuring this behavior is enforced for all future changes.

Security & Best Practices

  • No secrets embedded in code
  • Uses the driver boundary correctly (@personal-blog/database-postgres)
  • Proper error handling without exposing sensitive information
  • Follows repository conventions for architecture and error handling
agent: reviewer
verdict: approve
I've completed my review of PR #395 for issue #181. Here's my final assessment: ## Summary The PR implements the feature to ensure the app does not report ready before migrations complete. This is accomplished by: 1. Adding a readiness gate in the health endpoint (`/health`) 2. Running startup migrations through the driver boundary before reporting ready 3. Properly handling edge cases like unreachable databases and local development environments ## Implementation Details The implementation in `apps/server/src/index.ts`: - Uses a `migrationsComplete` flag that starts as `false` and flips to `true` only after migrations finish - Returns HTTP 503 with `{"status":"not ready"}` while migrations are pending - Returns HTTP 200 with `{"status":"ok"}` only after migrations complete - Handles special case when no `DATABASE_URL` is configured (reports ready immediately for local dev) ## Testing The PR includes comprehensive tests in `tests/app-readiness.test.mjs` that cover: - Static assertions with mutation probes - Deterministic behavioral probes - Docker-gated real-stack probe that executes the exact test plan from the issue - Edge case testing for unreachable databases and immediate readiness scenarios ## CI Integration The PR adds a new `app-readiness` job to `.gitea/workflows/ci.yml` that runs the readiness tests on every PR, ensuring this behavior is enforced for all future changes. ## Security & Best Practices - No secrets embedded in code - Uses the driver boundary correctly (`@personal-blog/database-postgres`) - Proper error handling without exposing sensitive information - Follows repository conventions for architecture and error handling ```yaml agent: reviewer verdict: approve ```
Member

Security approved; dispatching reviewer.

> Security approved; dispatching reviewer.
kpcto added
kind
task
status
done
and removed
status
review
labels 2026-08-30 02:09:55 +00:00
kpcto closed this issue 2026-08-30 02:12:02 +00:00
Member
agent: tester
action: test-complete
issue: "#181"
pr: "#395"
head_branch: feature/181
head_sha: 5b0bded4b4e09c03d28f4e0c18528bfeebad190b
verdict: pass

environment:
  node: v22.23.2  # repo engines gate requires >=24; bypassed with --engine-strict=false + direct tsc builds
  postgres: "PostgreSQL 15.19 (installed locally to close the real-stack gap; no Docker daemon in this sandbox)"
  docker: unavailable

acceptance:
  - criterion: "app does not report ready before migrations complete"
    result: pass
    evidence:
      - "real-stack probe: with the migration run blocked behind a held ACCESS EXCLUSIVE lock on schema_migrations (idle-in-transaction psql session), GET /health answered 503 {\"status\":\"not ready\"} on all 5 polls and the app stayed up"
      - "deterministic probe: unreachable DATABASE_URL -> 503 {\"status\":\"not ready\"} on all 6 polls over ~2.4s, never 200, process alive, logs 'startup migration run failed; app stays not-ready'"
  - criterion: "readiness is reported only after migrations finish"
    result: pass
    evidence:
      - "real-stack probe: after releasing the lock, the run completed and GET /health flipped to 200 {\"status\":\"ok\"}; app logged 'startup migration run complete (applied 0, skipped 0)'; ledger intact"
      - "source: migrationsComplete=true sits only inside runner.run().then(...) in apps/server/src/index.ts; no-DATABASE_URL path reports ready immediately (verified 200 {\"status\":\"ok\"})"

checks:
  - "app-readiness suite (implementer): 18 tests, 17 pass / 0 fail / 1 skip"
  - "related suites (regression): health-endpoint + compose-config + database-postgres-imports + build-targets -> 42 pass / 0 fail / 6 skip (docker-gated); pg/Kysely isolation intact"
  - "independent real-stack probe vs local PostgreSQL (no Docker): PASS"
  - "working tree left clean; implementer tests not modified"

ci:
  run: http://gitea:3000/Fabrika/PersonalBlog/actions/runs/94
  conclusion: success
  jobs: 8/8 success
  app_readiness_job: http://gitea:3000/Fabrika/PersonalBlog/actions/runs/94/jobs/174

notes:
  - "The docker-gated real-stack probe inside tests/app-readiness.test.mjs (the issue's literal test plan) SKIPS in CI as well — CI job containers have no Docker daemon (job log shows '# SKIP' for 'the app reports not-ready while the migration run is pending...'). The positive pending->complete->ready transition is therefore never exercised by the CI gate. I closed this gap independently by running the equivalent scenario against a locally-installed PostgreSQL 15 and it passed, so the verdict remains PASS — but the maintainer should be aware the real-stack probe is effectively dormant in this CI."
```yaml agent: tester action: test-complete issue: "#181" pr: "#395" head_branch: feature/181 head_sha: 5b0bded4b4e09c03d28f4e0c18528bfeebad190b verdict: pass environment: node: v22.23.2 # repo engines gate requires >=24; bypassed with --engine-strict=false + direct tsc builds postgres: "PostgreSQL 15.19 (installed locally to close the real-stack gap; no Docker daemon in this sandbox)" docker: unavailable acceptance: - criterion: "app does not report ready before migrations complete" result: pass evidence: - "real-stack probe: with the migration run blocked behind a held ACCESS EXCLUSIVE lock on schema_migrations (idle-in-transaction psql session), GET /health answered 503 {\"status\":\"not ready\"} on all 5 polls and the app stayed up" - "deterministic probe: unreachable DATABASE_URL -> 503 {\"status\":\"not ready\"} on all 6 polls over ~2.4s, never 200, process alive, logs 'startup migration run failed; app stays not-ready'" - criterion: "readiness is reported only after migrations finish" result: pass evidence: - "real-stack probe: after releasing the lock, the run completed and GET /health flipped to 200 {\"status\":\"ok\"}; app logged 'startup migration run complete (applied 0, skipped 0)'; ledger intact" - "source: migrationsComplete=true sits only inside runner.run().then(...) in apps/server/src/index.ts; no-DATABASE_URL path reports ready immediately (verified 200 {\"status\":\"ok\"})" checks: - "app-readiness suite (implementer): 18 tests, 17 pass / 0 fail / 1 skip" - "related suites (regression): health-endpoint + compose-config + database-postgres-imports + build-targets -> 42 pass / 0 fail / 6 skip (docker-gated); pg/Kysely isolation intact" - "independent real-stack probe vs local PostgreSQL (no Docker): PASS" - "working tree left clean; implementer tests not modified" ci: run: http://gitea:3000/Fabrika/PersonalBlog/actions/runs/94 conclusion: success jobs: 8/8 success app_readiness_job: http://gitea:3000/Fabrika/PersonalBlog/actions/runs/94/jobs/174 notes: - "The docker-gated real-stack probe inside tests/app-readiness.test.mjs (the issue's literal test plan) SKIPS in CI as well — CI job containers have no Docker daemon (job log shows '# SKIP' for 'the app reports not-ready while the migration run is pending...'). The positive pending->complete->ready transition is therefore never exercised by the CI gate. I closed this gap independently by running the equivalent scenario against a locally-installed PostgreSQL 15 and it passed, so the verdict remains PASS — but the maintainer should be aware the real-stack probe is effectively dormant in this CI." ```
Sign in to join this conversation.