Code-review fixes and refactors #69
Loading…
Reference in a new issue
No description provided.
Delete branch "fix/code-review"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Code-review pass: fixes, refactors, schema migration and an OpenAPI contract. Release 1.0.0 (breaking for API clients:
GET /admin/changelog/:idremoved, every DELETE answers 204, migration 0029 adds NOT NULL columns and a 0..10 CHECK on filter exposure compensation).Includes the unreleased work already on develop (password reset, email change, per-owner names) and the brand update.
Fixes
Refactors
Contract
openapi.jsoncommitted, generated bypnpm openapi:generate, CI drift check, contract int test validating every operationSchema (0029): NOT NULL audit columns, isColor/flash, filter range 0..10, redundant indexes dropped.
CI: nest build, changelog/front version check, gitleaks, docker build, OpenAPI drift.
Tests: 265 unit, 279 integration.
- once an email change is confirmed, send a notice to the OLD address ("your email was changed to x; if this wasn't you, reset your password"), from a user.update database hook that only fires for the verify-email request that actually switched the address - OTP_TTL_MINUTES / RESET_PASSWORD_TTL_SECONDS are passed to Better-Auth and used in the email copy (the 2FA email said 5 minutes while the default period is 3) - auth emails go out through advanced.backgroundTasks, so responses no longer wait on SMTP only for existing accounts (enumeration by timing); pending sends are drained on shutdown - BETTER_AUTH_URL is required in production (email links were otherwise built from the Host header) - AdminGuard re-reads isAdmin from the database instead of trusting the 5-minute cookie cacheOne write contract for every resource: - POST answers the created entity and PATCH the updated one, shaped exactly like GET reads it back: the list item for the catalog entities (camera with its filmFormat object, film with iso {id, value}) and folder, GET /shoot/:id for shoot (also PATCH /pin and /done), and GET /frame/:id for frame (also POST /:id/duplicate). Shoot and frame POST used to answer only {id}; the new body is a superset. An empty PATCH answers the current entity. - DELETE answers 204 with no body everywhere, DELETE /shoot/:id/frames included. - GET /frame/:id selects explicit weather/lens/filter columns, so it no longer exposes who created or edited those rows. response-shapes.int-spec checks POST/PATCH bodies against GET for each entity.- OwnedCrudConfig.hasUpdatedBy: every CRUD table has updatedBy. - setIsGlobalOnCreate: isGlobal defaults to false and the DTO whitelist already rejects a client-sent isGlobal (iso never had it). - The changelog relations(): nothing uses the relational query API. - GET /admin/changelog/:id and ChangelogService.findOne: neither the front nor the app calls it (the admin page edits from the list). - Idempotency-Key in the CORS allow-list: no front or app build still sends it; the preflight now allows Content-Type and Authorization only. - Orphan or stale comments in data-wipe.ts, frame-location.service.ts (no second query, no 403) and import.constants.ts ("tunable via env").Enable the @nestjs/swagger CLI plugin (nest build only) so request and response classes carry their schemas, and give every handler its success status and response type: - one response DTO per shape, next to the module's request DTOs: catalog items (camera with filmFormat, film with iso {id, value}), folder, shoot list item vs detail, frame row vs detail with its joins, frame location, changelog page/since/entry, import preview/result, health (and its 503); - list endpoints document both answers (ApiListResponse): the page envelope, or with all=true a bare array plus X-Total-Count; - 201 for POSTs, 204 for DELETEs and changelog/seen, the zip of GET /export and the multipart body of the import routes. Nullable columns and unset references are marked nullable. Update DTOs use @nestjs/swagger's PartialType (same validation, but it carries the schema), so @nestjs/mapped-types is no longer a direct dependency. The pagination query marks its defaulted fields optional, and controllers declare their return types so a service drifting from its DTO fails to compile. The document is titled "RollNote API" and versioned from package.json; Swagger stays off in production.