Skip to content

feat: add document CRUD API and document list UI#30

Merged
rjwalters merged 1 commit into
mainfrom
feature/issue-13
Apr 14, 2026
Merged

feat: add document CRUD API and document list UI#30
rjwalters merged 1 commit into
mainfrom
feature/issue-13

Conversation

@rjwalters

Copy link
Copy Markdown
Owner

Summary

Implement document management backend API endpoints and integrate document listing into the ProjectDetailPage UI, enabling users to create, read, update, and delete documents within projects.

Changes

  • Add Document interface and 5 CRUD handler functions in functions/api/[[route]].ts: list, get, create, update (with revision tracking), and delete (with R2 cleanup)
  • Add route matching for /api/projects/:projectId/documents and /api/projects/:projectId/documents/:docId
  • Add verifyProjectOwnership helper to authorize document operations
  • Update src/pages/ProjectDetailPage.tsx with a Documents section showing document list, "New Document" button, delete per document, and links to the edit page
  • Add functions/api/__tests__/documents.test.ts with 10 tests covering all document endpoints (auth, validation, CRUD, R2 interactions)

Acceptance Criteria Verification

Criterion Status Verification
GET /api/projects/:projectId/documents lists documents Done Implemented and tested
POST /api/projects/:projectId/documents creates document + R2 + revision Done Implemented and tested
GET /api/projects/:projectId/documents/:docId returns metadata + R2 content Done Implemented and tested
PUT /api/projects/:projectId/documents/:docId creates new revision in R2 Done Implemented and tested
DELETE /api/projects/:projectId/documents/:docId removes D1 + R2 Done Implemented and tested
All endpoints verify project ownership Done verifyProjectOwnership called in every handler
ProjectDetailPage shows document list Done Documents section with EmptyState fallback
New Document button creates and navigates to edit Done POST then navigate
Delete button per document Done With ConfirmDialog
Tests for document endpoints Done 10 tests in documents.test.ts

Test Plan

  • pnpm run build passes (tsc + vite)
  • pnpm run lint:fix passes (biome)
  • pnpm run test -- all 85 tests pass; 3 pre-existing empty suite failures in packages/ are unrelated

Closes #13

Add backend endpoints for document management (list, create, get, update, delete)
under /api/projects/:projectId/documents with R2 content storage and revision
tracking. Update ProjectDetailPage to display documents with create/delete actions.
Add comprehensive tests for all document endpoints.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@rjwalters rjwalters added the loom:review-requested PR ready for Judge to review label Apr 14, 2026
@rjwalters

Copy link
Copy Markdown
Owner Author

Loom Judge Review -- APPROVED

Reviewed all three changed files: functions/api/[[route]].ts, functions/api/__tests__/documents.test.ts, and src/pages/ProjectDetailPage.tsx.

What looks good

  • Security: All five document endpoints correctly call verifyProjectOwnership before any data access. SQL queries use parameterized binding throughout -- no injection risk.
  • Authorization: Authentication is enforced at the route-matching level before dispatching to handlers, consistent with the existing project endpoints.
  • R2 integration: Content storage follows a clean key convention (users/{uid}/projects/{pid}/documents/{did}/rev_{n}.md). Revision tracking increments correctly, and delete cleans up all R2 objects before removing the DB record.
  • Tests: 10 tests covering auth (401), ownership (404), validation (400), and successful CRUD for all endpoints. Mock setup is thorough and consistent with existing test patterns.
  • Frontend: Documents section uses existing UI components (EmptyState, ConfirmDialog, Card, Button). Loading skeleton, empty state, and document list rendering are well-structured. Optimistic local state update on delete is a nice touch.
  • Schema alignment: The Document interface matches the migration schema in 0001_initial.sql. CASCADE deletes on the revisions table are correctly relied upon for DB cleanup.
  • All 85 tests pass. Lint/format errors are pre-existing in src/pipeline/ (not files touched by this PR).

Minor observations (non-blocking)

  1. Sequential R2 deletes on document deletion: The for...of loop in handleDeleteDocument deletes R2 objects one at a time. For documents with many revisions, Promise.all would be faster. Low priority since revision counts are typically small.

  2. Silent error handling on document creation: handleCreateDocument in the frontend catches errors silently. The user sees "Creating..." revert to "New Document" with no feedback on failure. This matches the existing pattern in ProjectsPage for delete/status-toggle, so it is consistent, but worth noting for a future UX pass.

  3. No atomicity between R2 and D1: If CONTENT_BUCKET.put() succeeds but the subsequent DB.prepare().run() fails (or vice versa), state becomes inconsistent. This is an inherent limitation of the current architecture (no distributed transactions) and not specific to this PR.

Verdict

Clean implementation that follows established patterns. Approving.


Reviewed by Loom Judge

@rjwalters rjwalters added loom:pr PR approved by Judge, ready for human to merge and removed loom:review-requested PR ready for Judge to review labels Apr 14, 2026
@rjwalters
rjwalters merged commit cc689ae into main Apr 14, 2026
@rjwalters
rjwalters deleted the feature/issue-13 branch April 14, 2026 05:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

loom:pr PR approved by Judge, ready for human to merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Build document management UI and API

1 participant