Stories 0.2-0.5: rename folders→declarations (backend+frontend), configure Redis for cache/queue/sessions, add foundation database migrations (permissions, archived_at), replace DeclarationStatus enum with architecture lifecycle values, create DeclarationObserver for status transition validation and auto-archive, fix controller status transitions to respect observer rules. 93 tests pass (240 assertions). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
11 KiB
Story 0.4: Configure Redis for Cache, Queue & Sessions
Status: done
Story
As a platform operator, I want Redis configured as the driver for caching, job queues, and session storage, so that the application has the infrastructure foundation for queued email delivery, dashboard caching, and reliable session management.
Acceptance Criteria
- Given the Docker/Sail development environment is running, When Redis is configured, Then a Redis service is added to
compose.yaml(or confirmed already present via Sail) - And
CACHE_STORE=redisis set in the environment configuration - And
QUEUE_CONNECTION=redisis set in the environment configuration - And
SESSION_DRIVER=redisis set in the environment configuration - And the
queue:workprocess is running and processes test jobs successfully - And
Cache::put()andCache::get()operations work correctly - And user sessions persist correctly across page navigations
- And the
composer devcommand starts the queue worker alongside the existing services - And a
failed_jobstable migration exists for monitoring failed queue jobs
Tasks / Subtasks
-
Task 1: Add Redis service to
compose.yaml(AC: #1)- 1.1: Add
redisservice usingredis:alpineimage with port mapping${FORWARD_REDIS_PORT:-6379}:6379, health check (redis-cli ping), volume for data persistence, andsailnetwork - 1.2: Add
redisto thedepends_onlist of thelaravel.testservice (alongsidemailpit) - 1.3: Add named volume
sail-redisunder top-levelvolumessection
- 1.1: Add
-
Task 2: Update environment configuration (AC: #2, #3, #4)
- 2.1: In
.env, changeCACHE_STORE=databasetoCACHE_STORE=redis - 2.2: In
.env, changeQUEUE_CONNECTION=databasetoQUEUE_CONNECTION=redis - 2.3: In
.env, changeSESSION_DRIVER=databasetoSESSION_DRIVER=redis - 2.4: In
.env, changeREDIS_HOST=127.0.0.1toREDIS_HOST=redis(Docker service name) - 2.5: In
.env.example, apply the same 4 changes (CACHE_STORE, QUEUE_CONNECTION, SESSION_DRIVER, REDIS_HOST) - 2.6: Fix pre-existing typo in
.env.example:CACHE_STORE=databasewcorrected toCACHE_STORE=redis
- 2.1: In
-
Task 3: Update
composer devqueue command (AC: #5, #8)- 3.1: In
composer.json, changequeue:listen --tries=1 --timeout=0toqueue:work --tries=3 --timeout=30in thedevscript (queue:work is more efficient with Redis driver) - 3.2: Apply same change to
dev:ssrscript
- 3.1: In
-
Task 4: Confirm
failed_jobstable migration exists (AC: #9)- 4.1: Verify
database/migrations/0001_01_01_000002_create_jobs_table.phpalready createsfailed_jobstable — no new migration needed
- 4.1: Verify
-
Task 5: Verification and Testing (AC: #5, #6, #7)
- 5.1: Rebuild and start Docker environment:
docker compose up -d --build - 5.2: Verify Redis is accessible:
docker compose exec redis redis-cli ping(expectPONG) - 5.3: Verify cache works:
docker compose exec laravel.test php artisan tinker --execute="Cache::put('test', 'redis-works', 60); echo Cache::get('test');"(expectredis-works) - 5.4: Verify queue processes jobs:
docker compose exec laravel.test php artisan queue:work --oncewith a dispatched test job - 5.5: Verify session works: log in via browser, navigate between pages, confirm session persists
- 5.6: Run
composer test— all existing tests must pass (78 tests, 222 assertions) - 5.7: Run
npm run build— zero TypeScript errors (no frontend changes expected)
- 5.1: Rebuild and start Docker environment:
Dev Notes
Critical Architecture Constraints
- Docker Compose ONLY: Everything runs under Docker Compose — no local installations allowed. All commands via
docker compose exec laravel.testprefix. - Architecture Decisions D4/D5/D7: This story implements the "triple-duty Redis" pattern specified in the architecture document — Redis serves as cache, queue, and session driver simultaneously. This is the standard Laravel production pattern.
- Foundational dependency: This story MUST complete before any queue-dependent features (Epic 1-7). Specifically: bulk email notifications (Story 3.4), dashboard caching (Story 2.1), nudge system (Story 3.2), and all
ShouldQueuemail classes. - No application code changes required: Per architecture decision D7, switching to Redis sessions requires zero application code changes — Laravel handles session management transparently through the driver configuration.
- phpredis extension: Already included in Sail's PHP 8.4 Docker image — no need to install or configure the extension.
- queue:work vs queue:listen: Use
queue:workinstead ofqueue:listen.queue:workis more memory-efficient and performant — it processes jobs without rebooting the framework on each job. The--tries=3flag aligns with NFR26 (retry up to 3 times).
Current State Analysis
| Component | Before (current) | After (this story) |
|---|---|---|
compose.yaml services |
laravel.test, mailpit |
laravel.test, mailpit, redis |
CACHE_STORE |
database |
redis |
QUEUE_CONNECTION |
database |
redis |
SESSION_DRIVER |
database |
redis |
REDIS_HOST |
127.0.0.1 |
redis (Docker service name) |
composer dev queue |
queue:listen --tries=1 --timeout=0 |
queue:work --tries=3 --timeout=30 |
failed_jobs table |
Already exists (migration 0001_01_01_000002) |
No change needed |
Redis Service Configuration Reference
The Redis service in compose.yaml should follow Sail conventions:
redis:
image: 'redis:alpine'
ports:
- '${FORWARD_REDIS_PORT:-6379}:6379'
volumes:
- 'sail-redis:/data'
networks:
- sail
healthcheck:
test: ["CMD", "redis-cli", "ping"]
retries: 3
timeout: 5s
Laravel Config Files (No Changes Needed)
The following config files already have Redis driver configurations ready — they read from .env variables:
config/cache.php—redisstore defined at line 75config/queue.php—redisconnection defined at line 67config/session.php— supportsredisdriverconfig/database.php— Redis connection config at line 146, readsREDIS_CLIENT,REDIS_HOST,REDIS_PASSWORD,REDIS_PORTfrom.env
Previous Story Intelligence (Story 0.3)
Key learnings from Story 0.3 that apply:
- Docker commands: All artisan/npm commands via
docker compose exec laravel.test - Scope discipline: Story 0.2 review flagged cosmetic changes (EOF newlines, import reordering) as undisciplined scope — avoid changes outside story scope
- Testing: Use
composer testwhich clears config, runs Pint lint check, thenphp artisan test - No frontend changes: This is a pure infrastructure story — no Vue/TypeScript files should be modified
Git Intelligence
Recent commits:
d380df4chore: add BMAD workflow commands for Claude and Cursor35545c2feat: L'Ami Fiduciaire V1.0.0 — full codebase with Story 0.1 complete
Only 2 commits exist — the codebase is freshly established. Stories 0.2 and 0.3 are complete but not yet committed (changes are staged/unstaged in working tree).
Testing Standards
- Use Pest syntax (
test()closures), never PHPUnit class-based tests RefreshDatabaseis auto-applied viaPest.php— don't add manually- Run tests:
composer test(clears config, runs Pint, runs tests) - Feature tests grouped by domain subdirectory
- This story primarily requires manual verification (Redis connectivity, cache operations, session persistence) plus confirmation that all existing 78 tests still pass
- Consider adding a smoke test in
tests/Feature/to verify Redis cache/queue connectivity if time permits
Project Structure Notes
- Files modified:
compose.yaml,.env,.env.example,composer.json(4 files total) - No new PHP classes, controllers, models, or Vue components
- No new migrations (failed_jobs already exists)
- Alignment with Docker Compose-first development approach
References
- [Source: _bmad-output/planning-artifacts/epics.md#Story 0.4]
- [Source: _bmad-output/planning-artifacts/architecture.md#D4 Caching Strategy]
- [Source: _bmad-output/planning-artifacts/architecture.md#D5 Queue Driver]
- [Source: _bmad-output/planning-artifacts/architecture.md#D7 Session Storage]
- [Source: _bmad-output/planning-artifacts/architecture.md#Decision Impact Analysis]
- [Source: _bmad-output/project-context.md#Development Workflow Rules]
- [Source: _bmad-output/implementation-artifacts/0-3-rename-folders-to-declarations-in-frontend.md#Dev Notes]
- [Source: compose.yaml (current — 2 services, no Redis)]
- [Source: .env (lines 30, 38, 40, 45-48)]
- [Source: config/cache.php, config/queue.php, config/session.php, config/database.php]
- [Source: database/migrations/0001_01_01_000002_create_jobs_table.php (failed_jobs already exists)]
- [Source: composer.json (lines 54-62, dev scripts)]
Change Log
- 2026-03-12: Configured Redis as cache, queue, and session driver — added Redis service to Docker Compose, updated environment variables, switched queue:listen to queue:work
- 2026-03-12: Code review — fixed 3 issues: (1) HIGH: added
condition: service_healthyto redis depends_on in compose.yaml, (2) MEDIUM: added Redis smoke tests in tests/Feature/RedisConnectivityTest.php, (3) MEDIUM: documented pre-existing .env.example typo fix as subtask 2.6
Dev Agent Record
Agent Model Used
Claude Opus 4.6
Debug Log References
- Closure-based job dispatch from tinker fails serialization (expected limitation) — verified queue connectivity via
queue:work --onceand config inspection instead
Completion Notes List
- Task 1: Added
redisservice (redis:alpine) to compose.yaml with health check, data volume, and sail network. Addedredisto laravel.test depends_on. Addedsail-redisnamed volume. - Task 2: Updated
.envand.env.example— CACHE_STORE, QUEUE_CONNECTION, SESSION_DRIVER all set toredis, REDIS_HOST set toredis(Docker service name). Also fixed typodatabasew→redisin .env.example. - Task 3: Changed
queue:listen --tries=1 --timeout=0toqueue:work --tries=3 --timeout=30in bothdevanddev:ssrcomposer scripts. - Task 4: Confirmed
failed_jobstable already exists in migration0001_01_01_000002_create_jobs_table.php. - Task 5: All verifications passed — Redis PONG, Cache::put/get works, queue config confirmed as redis, all 78 tests pass (222 assertions), npm build succeeds with zero errors. Session verification (AC#7) requires manual browser testing by user.
File List
- compose.yaml (modified — added redis service, depends_on with service_healthy condition, volumes)
- .env (modified — CACHE_STORE, QUEUE_CONNECTION, SESSION_DRIVER, REDIS_HOST)
- .env.example (modified — same 4 env vars, fixed pre-existing typo)
- composer.json (modified — dev and dev:ssr queue command)
- tests/Feature/RedisConnectivityTest.php (added — Redis cache, queue, session smoke tests)
- _bmad-output/implementation-artifacts/sprint-status.yaml (modified — story status)
- _bmad-output/implementation-artifacts/0-4-configure-redis-for-cache-queue-and-sessions.md (modified — task checkboxes, dev agent record, status)