Files
amare/openspec/changes/complete-foundation-parity/tasks.md

5.7 KiB

1. Auth and strict types parity

  • 1.1 Add MustVerifyEmail to User and require verified + active in canAccessPanel; update seed so admin/assistant are verified; feature tests for unverified denial and verified access
  • 1.2 Confirm Filament/Laravel password reset is enabled; add feature tests for registered vs unknown email without account enumeration — required a custom App\Filament\Pages\Auth\RequestPasswordReset overriding Filament's stock page, which discloses account existence via a distinguishable danger notification on Password::INVALID_USER
  • 1.3 Add declare(strict_types=1); to project-owned PHP files missing it (e.g. AdminPanelProvider); architecture/unit regression as needed — 15 files total: AdminPanelProvider, Controller, and 13 Filament Resource Pages classes
  • 1.4 Run composer pint, composer phpstan, and composer test:feature for auth changes — all green

2. Local runtime and PHP 8.4 alignment

  • 2.1 Extend docker-compose.yml with FrankenPHP app service (build Dockerfile, depend on healthy postgres, publish 8000); document in README
  • 2.2 Align README/docs to PHP 8.4 canonical (keep Composer ^8.3); verify Dockerfile/CI already on 8.4
  • 2.3 Smoke local compose: docker compose up -dGET /up returns 200 — run as an isolated -p fase0smoke project (separate container names/ports via a !override compose overlay, kept outside the repo) so it didn't collide with the amare-postgres container already running for a concurrent sibling worktree session. depends_on: condition: service_healthy correctly gated app on Postgres's healthcheck, curl localhost:18000/up returned 200, and docker exec ... php artisan migrate --force succeeded — proving DB_HOST: postgres resolves the app container to the postgres service by Compose's service-name DNS, not just that the image boots. Torn down afterwards (down -v + image removal); the shared sibling amare-postgres container was untouched throughout.
  • 2.4 Run composer quality after compose/docs changes — pint/phpstan/test:feature all green locally (browser suite is CI-only, per AGENTS.md)

3. Quality gates: npm audit and coverage

  • 3.1 Add npm audit step to composer quality and CI static (policy: production deps; document any allowlist) — npm audit --omit=dev --audit-level=high, rationale documented inline in ci.yml; currently a vacuous forward guard since package.json has no runtime dependencies
  • 3.2 Enable Domain/Application coverage in CI unit with 80% fail threshold; exclude views/migrations/framework — scoped via a dedicated phpunit.coverage.xml (not the project-wide phpunit.xml), run as Unit,Architecture,Feature because the Application/Queries/Marketing classes are only exercised via Feature/HTTP tests; measured locally with pcov at 98.1%, well above the 80% gate
  • 3.3 Add/adjust unit tests if current Domain/Application coverage is below threshold — no-op: measured coverage (98.1%) already clears 80% with existing Feature-suite coverage of the Marketing queries plus existing PageMeta/HomeContent unit tests
  • 3.4 Verify CI static and unit fail appropriately on intentional audit/coverage breakage in a branch experiment or equivalent proof — blocked: no push/PR in this task's scope, so no real CI run exists to break intentionally; defer to a follow-up once a PR is open

4. Staging/production Compose and Dokploy prep

  • 4.1 Add versioned Compose template (docker-compose.deploy.yml: web, queue, scheduler, migrate one-shot) parameterized by APP_IMAGE/IMAGE_TAG for staging and production stacks
  • 4.2 Document Dokploy project setup: GHCR registry credentials, Postgres per environment, Compose import, required env vars (APP_KEY, DB, Resend, R2), trusted proxies/session cookies
  • 4.3 Document rollback procedure: move environment alias to previous SHA and redeploy without rebuild
  • 4.4 Document PostgreSQL daily backup (≥14d retention), restore procedure, and test restore on staging before first production promotion

5. Deploy workflow and smoke

  • 5.1 Create .github/workflows/deploy-staging.yml gated on successful CI on main: build image, push ghcr.io/...:<sha> + :staging, trigger Dokploy compose.deploy
  • 5.2 Create .github/workflows/promote-production.yml (workflow_dispatch + confirmation): retag same digest as :production, deploy production stack, smoke
  • 5.3 Wire migrate-before-serve (Compose migrate service) and healthcheck on /up
  • 5.4 Add post-deploy smoke script/job for /up, /, /admin/login returning 200
  • 5.5 Store orchestration secrets only in GitHub; Laravel/DB/R2/Resend only in Dokploy; ensure no secrets in image layers

6. Phase 0 exit evidence

  • 6.1 Perform first successful staging deploy of a main SHA and capture evidence (workflow URL, smoke output) — run 31395107465 deployed 7e68c0e successfully; smoke recorded /up, / and /admin/login returning HTTP 200.
  • 6.2 Verify rollback to previous SHA works once on staging
  • 6.3 Update SPEC.md §18 Fase 0 checkboxes only for items with evidence; note remaining deferred items if any — local runtime/auth/audit/coverage evidence was recorded by PR #39, and the staging exit criterion was subsequently marked complete from successful run 31395107465.
  • 6.4 Run full composer quality and confirm all five CI jobs + staging deploy path green — local quality evidence is recorded in task 2.4; PR #39 passed static, unit, feature, browser and container, then run 31395107465 deployed that exact merge SHA and passed all three smoke endpoints.
  • 6.5 Report in SPEC §24 format; archive this change only after remaining parity tasks are complete — blocked by tasks 3.4 and 6.2, tracked separately in MAN-125.