Implement posts API routes #64

Merged
erik merged 1 commit from feat/task-782a7074-posts-api-routes into main 2026-05-22 20:49:59 -05:00
Owner

Summary

Implement the Slugkit posts management API routes for draft article/link/note posts, lifecycle operations, author expansion, and tag assignment.

Task

Task: #task-782a7074

Changes

  • Add SQLite tables for posts, tags, post/tag joins, contacts, and post authors.
  • Add post service logic for create/list/get/update/delete/publish/unpublish.
  • Add authenticated posts API routes under /api/v1/posts.
  • Add validation, not-found, and conflict error handling for posts.
  • Document posts routes and schemas in OpenAPI.
  • Add API tests for draft creation, listing/get, update, lifecycle, authors, tags, validation, conflict, and OpenAPI coverage.
  • Fold in the architecture note for API-backed UI/CLI parity.

Testing

  • Unit tests added/updated
  • Manual testing performed: migrated dev DB, used bearer API key to create a draft note through POST /api/v1/posts, and listed it by draft status/tag.
  • make check passes
  • ./scripts/pre-pr.sh passes

Checklist

  • ./scripts/pre-pr.sh passes
  • Documentation updated (if needed)
  • No unrelated changes included
## Summary Implement the Slugkit posts management API routes for draft article/link/note posts, lifecycle operations, author expansion, and tag assignment. ## Task Task: #task-782a7074 ## Changes - Add SQLite tables for posts, tags, post/tag joins, contacts, and post authors. - Add post service logic for create/list/get/update/delete/publish/unpublish. - Add authenticated posts API routes under `/api/v1/posts`. - Add validation, not-found, and conflict error handling for posts. - Document posts routes and schemas in OpenAPI. - Add API tests for draft creation, listing/get, update, lifecycle, authors, tags, validation, conflict, and OpenAPI coverage. - Fold in the architecture note for API-backed UI/CLI parity. ## Testing - [x] Unit tests added/updated - [x] Manual testing performed: migrated dev DB, used bearer API key to create a draft note through `POST /api/v1/posts`, and listed it by draft status/tag. - [x] `make check` passes - [x] `./scripts/pre-pr.sh` passes ## Checklist - [x] `./scripts/pre-pr.sh` passes - [x] Documentation updated (if needed) - [x] No unrelated changes included
feat: implement posts API routes
All checks were successful
CI / build-lint-test (pull_request) Successful in 31s
934df7848a
Task: #task-782a7074
erik force-pushed feat/task-782a7074-posts-api-routes from 934df7848a
All checks were successful
CI / build-lint-test (pull_request) Successful in 31s
to 498f308915
All checks were successful
CI / build-lint-test (pull_request) Successful in 32s
2026-05-22 19:51:47 -05:00
Compare
erik force-pushed feat/task-782a7074-posts-api-routes from 498f308915
All checks were successful
CI / build-lint-test (pull_request) Successful in 32s
to 127d0d594f
All checks were successful
CI / build-lint-test (pull_request) Successful in 24s
2026-05-22 19:54:08 -05:00
Compare
Author
Owner

PR Review: Approved

Summary

Reviewed PR #64 at commit 127d0d5. The PR implements the posts API vertical slice with SQLite persistence, protected post routes, draft/publish lifecycle behavior, author expansion, tag find-or-create assignment, shared error handling, OpenAPI coverage, tests, documentation updates, and the architecture parity note requested before this task.

Acceptance Criteria

  • Can create draft article, link, and note posts: met — POST /api/v1/posts supports all three types and tests assert created posts have publishedAt: null.
  • Can list posts and get a post by slug: met — GET /api/v1/posts supports filters/pagination metadata and omits content in list items; GET /api/v1/posts/:slug returns full post content.
  • Can update post metadata/content without accidentally publishing: met — PUT /api/v1/posts/:slug updates slug/title/content and preserves publishedAt: null for drafts.
  • Can explicitly publish and unpublish posts: met — POST /posts/:slug/publish and /unpublish are implemented and tested.
  • authorIds requests produce expanded authors responses: met — migration adds minimal contacts/post_authors tables and tests verify authorIds expands to contact objects.
  • tagSlugs requests produce expanded tag responses and obey omitted-vs-empty update semantics: met — service creates tags from normalized slugs; tests verify omitted tagSlugs preserves tags and tagSlugs: [] clears them.
  • Validation failures use the shared error shape: met — route validation returns VALIDATION_ERROR; duplicate slugs return shared CONFLICT; missing posts return shared NOT_FOUND.
  • Every posts route appears in OpenAPI with the documented operation ID: met — OpenAPI includes list/create/get/update/delete/publish/unpublish operation IDs plus post request/response and error schemas; route tests assert coverage.
  • Relevant lint/test checks pass: met — make check, ./scripts/pre-pr.sh, manual smoke, and Forgejo CI passed.

Blocking Issues

None.

Warnings

None.

Verdict

Approved for merge after explicit human approval.

## PR Review: Approved ### Summary Reviewed PR #64 at commit `127d0d5`. The PR implements the posts API vertical slice with SQLite persistence, protected post routes, draft/publish lifecycle behavior, author expansion, tag find-or-create assignment, shared error handling, OpenAPI coverage, tests, documentation updates, and the architecture parity note requested before this task. ### Acceptance Criteria - [x] Can create draft article, link, and note posts: met — `POST /api/v1/posts` supports all three types and tests assert created posts have `publishedAt: null`. - [x] Can list posts and get a post by slug: met — `GET /api/v1/posts` supports filters/pagination metadata and omits content in list items; `GET /api/v1/posts/:slug` returns full post content. - [x] Can update post metadata/content without accidentally publishing: met — `PUT /api/v1/posts/:slug` updates slug/title/content and preserves `publishedAt: null` for drafts. - [x] Can explicitly publish and unpublish posts: met — `POST /posts/:slug/publish` and `/unpublish` are implemented and tested. - [x] `authorIds` requests produce expanded `authors` responses: met — migration adds minimal contacts/post_authors tables and tests verify `authorIds` expands to contact objects. - [x] `tagSlugs` requests produce expanded tag responses and obey omitted-vs-empty update semantics: met — service creates tags from normalized slugs; tests verify omitted `tagSlugs` preserves tags and `tagSlugs: []` clears them. - [x] Validation failures use the shared error shape: met — route validation returns `VALIDATION_ERROR`; duplicate slugs return shared `CONFLICT`; missing posts return shared `NOT_FOUND`. - [x] Every posts route appears in OpenAPI with the documented operation ID: met — OpenAPI includes list/create/get/update/delete/publish/unpublish operation IDs plus post request/response and error schemas; route tests assert coverage. - [x] Relevant lint/test checks pass: met — `make check`, `./scripts/pre-pr.sh`, manual smoke, and Forgejo CI passed. ### Blocking Issues None. ### Warnings None. ### Verdict Approved for merge after explicit human approval.
erik merged commit 3760b417b5 into main 2026-05-22 20:49:59 -05:00
erik deleted branch feat/task-782a7074-posts-api-routes 2026-05-22 20:49:59 -05:00
Sign in to join this conversation.
No description provided.