Review: API endpoints -- Rails serves the REST surface for MCP

review-1561-2026-06-22-r2 Review

review needs-refinement

Verdict: NEEDS_REFINEMENT

Template Completeness

  • [x] Type -- Feature
  • [x] Lineage -- depends on paldocs#49, part of consolidation
  • [x] Repo -- ldraney/paldocs
  • [x] User Story -- MCP layer needs Rails API parity
  • [x] Context -- 36 MCP tools across 7 controller groups detailed
  • [x] File Targets -- 10 files listed with do/don't-touch guidance
  • [x] Feature Flag -- none (correct, new namespace)
  • [x] Acceptance Criteria -- 8 criteria
  • [x] Test Expectations -- 4 expectations with run command
  • [x] Constraints -- JSON shape parity, tsvector search, stub semantic, namespace
  • [x] Checklist -- 8 items
  • [x] Related -- project, story, arch, upstream/downstream/parallel all documented
All template sections present and complete.

Traceability

  • [x] story:consolidation label -- story-paldocs-consolidation note exists in pal-e-docs (user-story type, project paldocs)
  • [x] story note verified -- found in project-paldocs user-stories section ("story-paldocs-consolidation -- absorb pal-e-docs into Rails monolith")
  • [x] arch:rails-api label -- arch-rails-api note exists in pal-e-docs (architecture type, project paldocs)
  • [x] arch note verified -- arch-rails-api note exists with diagram, components table, and key decisions
  • [x] Forgejo issue -- ldraney/paldocs#51, state: open
Full traceability triangle verified.

File Targets

  • [x] app/controllers/api/notes_controller.rb -- NEW file. Parent dir app/controllers/ exists. api/ subdir must be created. Note model exists at app/models/note.rb.
  • [x] app/controllers/api/blocks_controller.rb -- NEW file. Block model exists at app/models/block.rb.
  • [x] app/controllers/api/boards_controller.rb -- NEW file. Board is modeled as Note with note_type: "board", not a separate model. Existing UI BoardsController uses Note.find_by!(slug: params[:slug], note_type: "board").
  • [x] app/controllers/api/board_items_controller.rb -- NEW file. BoardItem model exists at app/models/board_item.rb.
  • [x] app/controllers/api/projects_controller.rb -- NEW file. Project model exists at app/models/project.rb.
  • [x] app/controllers/api/repos_controller.rb -- NEW file. Repo model exists at app/models/repo.rb.
  • [x] app/controllers/api/tags_controller.rb -- NEW file. Tag model exists at app/models/tag.rb.
  • [x] app/controllers/api/search_controller.rb -- NEW file. Keyword search uses tsvector (in DB). Semantic search is stub.
  • [x] config/routes.rb -- EXISTS. Currently has only UI routes. API namespace block must be added.
  • [ ] app/views/api/ -- ISSUE: Issue says "jbuilder templates for JSON responses" but jbuilder gem is NOT in the Gemfile or Gemfile.lock. Either add jbuilder or use render json: directly. [BODY] Clarify JSON rendering strategy: add jbuilder gem or use render json: with as_json overrides.

Repo Placement

OK. Issue is filed on ldraney/paldocs, all file targets are in the paldocs repo. Single-repo change.

Dependencies

  • Upstream: paldocs#49 (schema ownership transfer) -- state: open, currently in_progress on board. This ticket depends on #49 completing first (models must exist with correct schema). Models already exist in app/models/ but schema ownership is still transferring.
  • Parallel: paldocs#50 (sprint schema), paldocs#52 (embedding pipeline), paldocs#56 (sprint UI) -- no blocking dependency, can run in parallel.
  • Downstream: paldocs#54 (new MCP server) -- depends on this ticket's API being available.
Dependencies are well documented in the issue.

Acceptance Criteria

8 acceptance criteria -- all are testable via HTTP request specs. Test expectations include request specs per controller, CRUD integration tests, and response shape comparison against pal-e-docs. Run command (bundle exec rspec) is valid.
However, the "response shape comparison" AC ("When I compare Rails API responses to pal-e-docs responses, then the JSON shapes match") is vague. No reference JSON fixtures or pal-e-docs response examples are provided. The agent will need to call pal-e-docs API or reference the FastAPI source to know the exact shapes.

Blast Radius

Low risk. New /api/ namespace is isolated from existing UI routes. No existing controllers are modified. The constraint "Must not break existing paldocs UI routes" is well addressed by the namespace separation. No other repos are affected.

Decomposition Assessment

NEEDS DECOMPOSITION
  • File targets: 10 files (8 new controllers + routes + views/serialization), all in 1 repo -- exceeds 3 file target guideline
  • Acceptance criteria: 8 AC -- exceeds 5 AC guideline
  • Scope: 36 MCP tool endpoints across 8 controller groups with JSON shape parity requirements
  • Estimated agent time: Well over 5 minutes -- each controller needs endpoint implementation, JSON serialization, and request specs
  • Recommendation: Decompose into per-controller-group sub-tickets (e.g., notes controller, boards+board_items controller, projects+repos+tags controller, search controller). Each sub-ticket would be 2-3 points with 2-3 file targets.
Route to skill-decompose-ticket for automated sub-ticket creation.

Recommendation

  • [BODY] Clarify JSON rendering strategy: issue references "jbuilder templates" but jbuilder is not in the Gemfile. Either add gem "jbuilder" to Gemfile or change to render json: approach.
  • [DECOMPOSE] 8 AC across 10 files with 36 endpoint implementations. Route to skill-decompose-ticket. Suggested split: (1) Notes controller (12 tools, 3pts), (2) Boards + Board Items controllers (11 tools, 3pts), (3) Projects + Repos + Tags controllers (7 tools, 2pts), (4) Search controller (2 tools + routes namespace, 2pts).