Implement JobStepsModule for granular step tracking within runner jobs. Features: - Create and track job steps (SETUP, EXECUTION, VALIDATION, CLEANUP) - Track step status transitions (PENDING → RUNNING → COMPLETED/FAILED) - Record token usage for AI_ACTION steps - Calculate step duration automatically - GET endpoints for listing and retrieving steps Implementation: - JobStepsService: CRUD operations, status tracking, duration calculation - JobStepsController: GET /runner-jobs/:jobId/steps endpoints - DTOs: CreateStepDto, UpdateStepDto with validation - Full unit test coverage (16 tests) Quality gates: - Build: ✅ Passed - Lint: ✅ Passed - Tests: ✅ 16/16 passed - Coverage: ✅ 100% statements, 100% functions, 100% lines, 83.33% branches Also fixed pre-existing TypeScript strict mode issue in job-events DTO. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
3.5 KiB
3.5 KiB
Issue #169: Job events and audit logging
Objective
Implement job-events module for immutable audit logging using event sourcing pattern.
Approach
- Create module structure (module, service, controller, DTOs)
- Define event type constants
- Implement event emission and persistence (PostgreSQL)
- Add API endpoints for querying events
- Follow TDD: Write tests first, then implementation
Event Types
- Job lifecycle: job.created, job.queued, job.started, job.completed, job.failed
- Step lifecycle: step.started, step.progress, step.output, step.completed
- AI events: ai.tool_called, ai.tokens_used, ai.artifact_created
- Gate events: gate.started, gate.passed, gate.failed
Storage Strategy
- PostgreSQL: Immutable audit log (permanent)
- Valkey Streams: Deferred to future issue
- Valkey Pub/Sub: Deferred to future issue
API Endpoints
- GET /runner-jobs/:jobId/events - List events for a job
- GET /runner-jobs/:jobId/events/stream - SSE stream (Phase 4, deferred)
Progress
- Create scratchpad
- Review existing schema (JobEvent model)
- Define event type constants
- Write tests for JobEventsService
- Implement JobEventsService
- Write tests for JobEventsController
- Implement JobEventsController
- Create JobEventsModule
- Register modules in app.module.ts
- Run quality gates (typecheck, lint, build, test)
- Commit changes
Testing
- Unit tests for service (event emission, persistence, querying)
- Unit tests for controller (endpoint behavior)
- Target: >85% coverage
Results:
- JobEventsService: 13 tests passed
- JobEventsController: 4 tests passed
- Total: 17 tests passed
- All quality gates passed (typecheck, lint, build, test)
Notes
- Events are immutable once created
- JobEvent model already exists in Prisma schema (from #164)
- RunnerJobsModule available (from #167)
- SSE streaming deferred to Phase 4
Implementation Details
Files Created:
- /apps/api/src/job-events/event-types.ts - Event type constants
- /apps/api/src/job-events/dto/create-event.dto.ts - DTO for creating events
- /apps/api/src/job-events/dto/query-events.dto.ts - DTO for querying events
- /apps/api/src/job-events/dto/index.ts - DTO exports
- /apps/api/src/job-events/job-events.service.ts - Event service implementation
- /apps/api/src/job-events/job-events.service.spec.ts - Service tests (13 tests)
- /apps/api/src/job-events/job-events.controller.ts - Event controller
- /apps/api/src/job-events/job-events.controller.spec.ts - Controller tests (4 tests)
- /apps/api/src/job-events/job-events.module.ts - Module definition
- /apps/api/src/job-events/index.ts - Module exports
Files Modified:
- /apps/api/src/app.module.ts - Registered JobEventsModule
Event Types Implemented:
- Job lifecycle: job.created, job.queued, job.started, job.completed, job.failed, job.cancelled
- Step lifecycle: step.started, step.progress, step.output, step.completed, step.failed
- AI events: ai.tool_called, ai.tokens_used, ai.artifact_created
- Gate events: gate.started, gate.passed, gate.failed
API Endpoints:
- GET /api/runner-jobs/:jobId/events - List events for a job (with pagination and filtering)
Service Methods:
- emitEvent() - Generic event emission
- getEventsByJobId() - Query events with filters
- Convenience methods: emitJobCreated(), emitJobStarted(), emitStepStarted(), emitAiTokensUsed(), etc.
Quality Gates:
- Typecheck: PASSED
- Lint: PASSED
- Build: PASSED
- Tests: PASSED (17/17 tests)
- Full test suite: PASSED (1327 tests)