# R5.2 — REST Conventions Audit Generated: 2026-05-08 Branch: acadenice/main ## A. Endpoints audited | Endpoint | Method | Status Code | Method OK | Code OK | Naming OK | Notes | Action | |----------|--------|-------------|-----------|---------|-----------|-------|--------| | GET /v1/api-keys | GET | 200 | OK | OK | OK | - | None | | POST /v1/api-keys | POST | 201 | OK | OK | OK | explicit HttpCode(201) present | None | | DELETE /v1/api-keys/:id | DELETE | 204 | OK | OK | OK | - | None | | GET /v1/audit-log | GET | 200 | OK | OK | KO | singular noun — route predates R5.2 scope | Deferred (no rename) | | GET /v1/pages/:pageId/backlinks | GET | 200 | OK | OK | OK | sub-resource path correct | None | | POST /v1/clipper/import | POST | 201 | OK | OK | OK | creates a page resource | None | | POST /v1/clipper/tokens | POST | 201 | OK | OK | OK | - | None | | GET /v1/clipper/tokens | GET | 200 | OK | OK | OK | - | None | | DELETE /v1/clipper/tokens/:id | DELETE | 204 | OK | OK | OK | - | None | | POST /v1/page-comments/resolve | POST | 200 | OK | OK | OK | action verb, no resource created | None | | GET /v1/graph | GET | 200 | OK | OK | OK | - | None | | GET /v1/notifications | GET | 200 | OK | OK | OK | - | None | | GET /v1/notifications/unread-count | GET | 200 | OK | OK | OK | - | None | | POST /v1/notifications/read-all | POST | 204 | OK | OK | OK | action, no resource | None | | POST /v1/notifications/mark-read | POST | 204 | OK | OK | OK | action, no resource | None | | POST /v1/notifications/:id/read | POST | 204 | OK | OK | OK | action, no resource | None | | GET /v1/notification-preferences | GET | 200 | OK | OK | OK | - | None | | PUT /v1/notification-preferences | PUT | 200 | OK | OK | OK | full replace semantics correct | None | | GET /v1/roles | GET | 200 | OK | OK | OK | - | None | | POST /v1/roles | POST | 201 | OK | OK | OK | explicit HttpCode(201) | None | | GET /v1/roles/:id | GET | 200 | OK | OK | OK | - | None | | PATCH /v1/roles/:id | PATCH | 200 | OK | OK | OK | - | None | | DELETE /v1/roles/:id | DELETE | 204 | OK | OK | OK | - | None | | GET /v1/roles/:id/permissions | GET | 200 | OK | OK | OK | sub-resource | None | | PUT /v1/roles/:id/permissions | PUT | 200 | OK | OK | OK | full replace semantics | None | | GET /v1/users/:userId/roles | GET | 200 | OK | OK | OK | sub-resource | None | | POST /v1/users/:userId/roles | POST | 200 | KO | KO | OK | assigns roles (action), 201 would also be valid | Deferred | | DELETE /v1/users/:userId/roles/:roleId | DELETE | 204 | OK | OK | OK | - | None | | GET /v1/permissions | GET | 200 | OK | OK | OK | - | None | | GET /v1/permissions/me | GET | 200 | OK | OK | OK | sub-resource | None | | GET /v1/security/oidc-status | GET | 200 | OK | OK | OK | - | None | | GET /v1/slash-commands | GET | 200 | OK | OK | OK | - | None | | GET /v1/slash-commands/:id | GET | 200 | OK | OK | OK | - | None | | POST /v1/slash-commands | POST | 201 | OK | OK | OK | added explicit HttpCode(201) — R5.2 | PATCHED | | PATCH /v1/slash-commands/:id | PATCH | 200 | OK | OK | OK | - | None | | DELETE /v1/slash-commands/:id | DELETE | 204 | OK | OK | OK | - | None | | POST /v1/sync-blocks | POST | 201 | OK | OK | OK | added explicit HttpCode(201) — R5.2 | PATCHED | | GET /v1/sync-blocks/:id | GET | 200 | OK | OK | OK | - | None | | PATCH /v1/sync-blocks/:id | PATCH | 200 | OK | OK | OK | - | None | | DELETE /v1/sync-blocks/:id | DELETE | 204 | OK | OK | OK | - | None | | GET /v1/sync-blocks/:id/usages | GET | 200 | OK | OK | OK | sub-resource | None | | GET /v1/templates | GET | 200 | OK | OK | OK | - | None | | GET /v1/templates/:id | GET | 200 | OK | OK | OK | - | None | | POST /v1/templates | POST | 201 | OK | OK | OK | added explicit HttpCode(201) — R5.2 | PATCHED | | PATCH /v1/templates/:id | PATCH | 200 | OK | OK | OK | - | None | | DELETE /v1/templates/:id | DELETE | 204 | OK | OK | OK | - | None | | POST /v1/templates/:id/instantiate | POST | 201 | OK | OK | OK | creates a page — 201 correct, added explicit | PATCHED | | PATCH /v1/templates/:id/default | PATCH | 200 | OK | OK | OK | - | None | | POST /v1/row-comments/list | POST | 200 | KO | OK | KO | RPC verb in path | PATCHED → GET /v1/row-comments | | POST /v1/row-comments/create | POST | 200 | KO | KO | KO | RPC verb, wrong code | PATCHED → POST /v1/row-comments 201 | | POST /v1/row-comments/update | POST | 200 | KO | OK | KO | RPC verb in path | PATCHED → PATCH /v1/row-comments/:id | | POST /v1/row-comments/resolve | POST | 200 | KO | OK | KO | RPC verb in path | PATCHED → PATCH /v1/row-comments/:id/resolve | | POST /v1/row-comments/delete | POST | 200 | KO | KO | KO | RPC verb, wrong method | PATCHED → DELETE /v1/row-comments/:id 204 | | POST /v1/row-comments/count | POST | 200 | KO | OK | KO | RPC verb in path | PATCHED → GET /v1/row-comments/count | **Total audited: 54 endpoints** **Violations found: 9** **Patches applied: 9 (6 row-comments routes + 3 missing 201 codes)** ## B. Breaking changes | Change | Before | After | Impact | |--------|--------|-------|--------| | row-comments list | POST /v1/row-comments/list | GET /v1/row-comments?tableId=&rowId= | Breaking — client updated | | row-comments create | POST /v1/row-comments/create | POST /v1/row-comments (201) | Breaking — client + status updated | | row-comments update | POST /v1/row-comments/update (body commentId) | PATCH /v1/row-comments/:id | Breaking — client + server updated | | row-comments resolve | POST /v1/row-comments/resolve (body commentId) | PATCH /v1/row-comments/:id/resolve | Breaking — client + server updated | | row-comments delete | POST /v1/row-comments/delete (body commentId) | DELETE /v1/row-comments/:id (204) | Breaking — client + server updated | | row-comments count | POST /v1/row-comments/count | GET /v1/row-comments/count?tableId=&rowId= | Breaking — client updated | All breaking changes updated consistently across: server controller, server spec, client service, client test. ## C. Patches applied ### P1 — row-comments: Full REST refactor (breaking) - `row-comments.controller.ts`: 6 routes converted from RPC POST to proper HTTP methods - `comment.dto.ts`: Removed `commentId` from `UpdateRowCommentDto` and `ResolveRowCommentDto` (now path param) - `row-comments.controller.spec.ts`: Rewrote to match new REST interface - `row-comment.service.spec.ts`: Fixed 3 DTO literals (removed `commentId`) - `row-comments-client.ts` (client): Converted from POST-only to GET/POST/PATCH/DELETE - `row-comments-client.test.ts` (client): Rewrote to match new REST methods ### P2 — sync-blocks: explicit 201 on POST create - `sync-blocks.controller.ts`: Added `@HttpCode(HttpStatus.CREATED)` ### P3 — slash-commands: explicit 201 on POST create - `slash-commands.controller.ts`: Added `@HttpCode(HttpStatus.CREATED)` ### P4 — templates: explicit 201 on POST create + instantiate - `templates.controller.ts`: Added `@HttpCode(HttpStatus.CREATED)` to `create` and `instantiate` ### P5 — Fix pre-existing test failures (D section) #### D1 — clipper-client.test.ts: jest → vitest - Converted `jest.mock`, `jest.fn()`, `jest.Mocked`, `afterEach(jest.resetAllMocks)` to vitest equivalents #### D2 — templates-client.test.ts: `.data.data` → `.data` - `templates-client.ts`: Removed double-unwrap `.data.data` → `.data` (x6 methods) - `clipper-client.ts`: Same fix (x2 methods) - `slash-commands-client.ts`: Same fix (x4 methods) - `sync-blocks-client.ts`: Same fix (x4 methods) ## D. Test counts | Suite | Before | After | |-------|--------|-------| | Server Jest (acadenice) | 321 pass | 322 pass | | Server Jest (total) | 440 pass / 5 fail | 448 pass / 5 fail (pre-existing) | | Client Vitest | 356 pass / 7 fail | 366 pass / 0 fail |