Complete Backend Loop Engineering - #46
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 58bf53129f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if (action === 'commit') { | ||
| assertSamePaths(fresh.repository.worktreePaths, fresh.preflight.taskPaths, 'worktree'); |
There was a problem hiding this comment.
Ignore verification reports during commit handoff
For every medium/high-risk task, the full lane runs duplication:report, which creates untracked _WIP/duplication-report.md and _WIP/small-helper-duplication-report.md. TaskService deliberately excludes these controller artifacts from preflight.taskPaths, but PublicationAdapter.inspect() leaves them in worktreePaths, so this equality rejects the subsequent commit dry-run even though verification passed. Filter the known controller artifacts from this repository-shape comparison while continuing to keep them unstaged.
AGENTS.md reference: AGENTS.md:L79-L79
Useful? React with 👍 / 👎.
| async verify(taskId: string): Promise<TaskVerificationResult> { | ||
| let state = await this.states.read(taskId); | ||
| this.assertVerifiable(state); | ||
| if (Date.parse(this.now()) - Date.parse(state.startedAt) > state.boundaries.timeoutMs) { |
There was a problem hiding this comment.
Enforce the task timeout while verification runs
When a verification command hangs or simply runs past the task deadline after this initial check, nothing interrupts it: the registered profile steps provide no timeoutMs, and the controller awaits profiles.run() without passing the remaining task duration. The state consequently remains verifying indefinitely and cannot be retried through assertVerifiable; apply the remaining task deadline to each profile execution and transition to the timeout state when it expires.
Useful? React with 👍 / 👎.
Introduce ADR-0018 for progressive feature tiers (endpoint slice, capability slice, clean/hexagonal slice) with promotion triggers, accepted defaults, and updated boundary enforcement. Update normative docs, guide docs, code-quality standards, and guardrails. Rework the feature scaffold with a simple default tier and an explicit clean tier, and extend the scaffold smoke test to validate both.
Add AppProblemError and AppProblemErrorFilter as shared platform primitives so simple feature slices can return RFC7807 problem details without generating feature-specific error classes and filters. Update simple and clean scaffold controllers to use the shared filter, and document the pattern in the feature and endpoint guides.
Move email verification service, token helper, jobs, and HTTP handlers into libs/features/auth/email-verification as Phase 1 of the auth capability split. Add EmailVerificationController for the verify and resend routes, drop the AuthService pass-throughs, and update worker and test imports. Endpoint paths, operation IDs, schemas, and error codes are unchanged.
Move password reset service, token helper, jobs, DTOs, and HTTP handlers into libs/features/auth/password-reset as Phase 2 of the auth capability split. Add PasswordResetController for the request and confirm routes, drop the AuthService pass-throughs, and update worker and test imports. Endpoint paths, operation IDs, schemas, and error codes are unchanged.
Move push token service, controller, DTO, and controller spec into libs/features/auth/push-tokens as Phase 3 of the auth capability split. Update AuthModule wiring and remove the old app and infra http files. Endpoint paths, operation IDs, schemas, and error codes are unchanged.
Move session list/revoke, refresh, logout, and JWKS controllers into libs/features/auth/sessions as Phase 4 of the auth capability split. Split into MeSessionsController (Users tag) and AuthSessionsController (Auth tag) to preserve OpenAPI tags, point refresh/logout/JWKS at AuthSessionLifecycleService directly, and drop the AuthService pass-throughs. Endpoint paths, operation IDs, schemas, and error codes are unchanged.
Move password register/login/change handlers and DTOs into libs/features/auth/password as Phase 5 of the auth capability split. Create PasswordAuthController with the AuthEmailVerificationJobs enqueue and UsersService merge, strip the password handlers from AuthController (leaving OIDC only), and remove the moved DTOs and password policy. Endpoint paths, operation IDs, tags, schemas, and error codes are unchanged.
Move OIDC exchange/connect handlers and DTOs into libs/features/auth/oidc as Phase 6 of the auth capability split. Create OidcController, delete the now-empty AuthController, and remove the OIDC DTOs from auth.dto.ts. Endpoint paths, operation IDs, tags, schemas, and error codes are unchanged.
Finish the auth capability split (Phase 7): consolidate shared code under auth/shared, move app services into capability folders, delete the AuthService facade and app/infra/domain trees, and move the module to the feature root. Also remove re-export shims (tx, time, rate-limit utils), dedupe the push-platform type, consolidate the user-state checks, and share the rate-limit error factory. Endpoint paths, tags, schemas, and error codes are unchanged.
Merge small auth primitives into shared/auth.model.ts and small service ports into shared/ports/auth.ports.ts, move the AuthErrorCode re-export into auth.errors.ts, and update all importers. Fix stale rate-limiter paths in the auth abuse documentation. Behavior and OpenAPI contracts are unchanged.
Remove the asNonEmptyString re-export from platform auth utils and import it from libs/shared/string in the access token verifier, auth keyring, and emails worker handler.
Merge the split env schema files into a single env.schema.ts, extract runtime defaults into env.defaults.ts, and consolidate env parsing helpers (boolean/int parsing, asEnvNumber) into env-parsing.ts. Replace inline magic-number fallbacks in rate limiters, auth/users modules, and entrypoints with the shared defaults. Fix the FCM credential invariant to include the base64 strategy and enforce exactly one credential source, with tests.
Remove the misnamed advisory-locks re-export and import NodeEnv from env.enums directly. Initialize the Resend client only when email is fully configured, and reject empty recipients in arrays instead of silently dropping them. Clamp tx-retry maxAttempts to at least 1. Add tests for each fix.
Remove the AppProblemError/AppProblemErrorFilter experiment and extract shared status/code/title resolution into problem-details.mapping.ts, used by both ProblemDetailsFilter and feature-error.mapper. Normalize invalid request ids via getOrCreateRequestId in the filter. Remove list-query and idempotency re-export shims, align ApiListQueryOptions with ListQueryPipeOptions, and drop unused idempotency result fields. Update scaffold and guides to recommend ProblemException with the global filter.
…fecycle Extract the pino-http options builder into pino-http.options.ts and simplify the telemetry SDK lifecycle (drop the redundant started flag, reset sdk on shutdown so re-init works). Export and test OTLP URL and header parsing, and add a telemetry spec covering disabled-env and init/shutdown/re-init. Import NodeEnv from env.enums directly and correct the observability docs to state metrics are not wired yet.
Delete the unused PushJobs job enqueuer and its spec, fold PUSH_QUEUE into push.job.ts and the PUSH_SERVICE symbol into push.service.ts, and use the PushProvider enum instead of raw strings. Update the FCM doc with the base64 credential option.
Fold json.types, job-name, and queue-name into queue.types.ts with their validators, consolidate the validator spec, and update all importers. Make QueueProducer.getQueue private.
Remove the @SkipRbac escape hatch and the implicit /v1/admin/* path hydration, requiring admin controllers to declare @UseDbRoles() explicitly. Simplify @RequirePermissions to SetMetadata (class and handler still merge via getAllAndMerge). Fold permissions provider and tokens into permissions.ts and the use-db-roles decorator into rbac.decorator.ts. Pin FCM credential strategies in the auth e2e harness so the stricter credential invariant does not break boot.
Replace the local redis config readers and magic-number defaults with the shared REDIS_CONFIG_DEFAULTS, and derive object storage enabled state from the client. Validate object keys in headObject and deleteObject.
Move the admin prisma-list-query helpers into shared libs/shared/list-query/where.ts and convert the auth sessions cursor builders to the shared pattern. Dedupe hasOwnField into object.ts, drop the legacy bracketed-key filter parsing, fail fast on invalid limit, and set the ListQueryValidationError name.
Move users.module.ts to the feature root, consolidate shared code under users/shared (model, errors with the UsersErrorCode re-export, error filter, tokens, ports, persistence), and remove the app/time and users.error-codes re-export shims. Update all internal and external importers. Behavior and contracts unchanged.
Extend the feature-app boundary rule to permit imports of the feature-internal shared folder, mirroring the auth shared layer, so interim app services can use shared code during the users split.
Document the users feature reorganization plan: the proposal under _WIP, four execution plans (shared foundation completed, me + account-deletion split, profile-image split, cleanup and docs), and refresh the auth capability roadmap target shape.
Split UsersService into me/me.service.ts (MeService: getMe, updateMeProfile) and account-deletion/account-deletion.service.ts (AccountDeletionService: request/cancel), delete the orphaned facade, and move the controllers, DTOs, jobs, and queue into the capability folders. Rewire the module and auth getMe imports, update worker and test importers, and migrate the service specs per capability. Behavior and contracts unchanged.
Consolidate the profile-image endpoint group into libs/features/users/profile-image: service, policy, controller, DTOs, storage adapter, rate limiter, and cleanup jobs. Rewire the module, worker, and test importers. Behavior and contracts unchanged.
Remove the empty app and infra trees, update the duplication harness example paths to the capability structure, and mark the final users execution plan complete.
Move admin.module.ts to the feature root, consolidate shared code under admin/shared (errors with the AdminErrorCode re-export, error filter, model, ports, persistence), and create admin-users, admin-audit, and whoami capability folders with consolidated DTOs. Delete the app and infra trees and update the duplication allowlist paths. RBAC metadata, endpoints, and contracts unchanged.
Clear service-relevant env vars in a unit-test setup so ConfigService cannot leak shell config into platform specs, fixing the 10 pre-existing failures. Fix the stale auth module path in gate honesty and drop the obsolete duplication allowlist entry for the merged admin audit DTO.
Upgrade @nestjs/platform-fastify to 11.1.28 (fastify 5.10), prisma to 7.9.1, @fastify/swagger-ui to 6.1.1, and the OpenTelemetry stack to latest. Add overrides pinning patched transitive versions (find-my-way, @fastify/static, uuid, js-yaml, hono, lodash) to clear all production advisories.
Extract a shared createNestFastifyApp helper, inject WORKER_CLOCK into the push and email workers, and move the users account-deletion job handlers into libs/features/users/shared/jobs.
Document the admin feature reorganization plan (capability folders, shared layer, DTO consolidation, and the confirmed decisions).
Apply prettier union-type wrapping to the merged admin model and the profile image repository port.
Delete the tools/agent dev-wrapper scripts (nodew, npmw, gitw, dockw, doctor, win wrappers, Heroku helpers) which have no references in docs, scripts, or CI.
Add one-shot backendkit events run --once to deterministically select a queued approved V2 plan, deduplicate delivery with strict receipts, and create ordinary task state. Add backendkit maintenance run --once with a fixed read-only observation registry (knowledge, architecture, duplication, dependency audit). Wire both into the CLI with tests.
Update the agent PR loop, backendkit CLI guide, guardrails, execution plan readme, and development workflow to describe the queued-plan intake and read-only maintenance commands.
Accept ADR-0023 for one-shot queued-plan intake, strict event receipts, and read-only maintenance, and move the completed Phase 5 execution plan into the completed folder.
Summary
Production evidence
Important boundary
Phase 8 machinery is installed but remains fail-closed until five independently reviewed exact-revision tasks satisfy the operating-evidence threshold. No evidence was fabricated for this release.
Reviewer focus