You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
vibed/pages/.beans/pages-kns6--pages-and-users...

1.9 KiB

title status type priority created_at updated_at parent blocked_by
Pages and users JSON API completed feature normal 2026-07-13T02:09:09Z 2026-07-13T16:47:43Z pages-77lk
pages-zd46

Implement design doc §4.1 API rows + §4.6 upload pipeline. src/routes/api.rs (wasm-only): GET /api/me; GET /api/pages (public); POST /api/pages?name= — auth (401), can_upload (403), Origin check vs BASE_URL (403), slug validation/reserved (400) via core, quota 50 pages/user (403), Content-Length + buffered size cap 10 MiB (413), core::upload::build_manifest by Content-Type text/html vs application/zip (400 on other types), D1 insert first (409 NameTaken), then R2 puts under slug/ with best-effort rollback on failure (500); DELETE /api/pages/:slug — owner or admin, delete R2 prefix (list+delete loop) then D1 row; GET /api/users + PATCH /api/users/:id {can_upload} — admin only. All errors JSON {"error": "..."} with correct status. Wire into router. Keep handlers thin; any new pure logic goes in core with native tests.

  • /api/me, GET /api/pages
  • POST /api/pages full pipeline in §4.6 order
  • DELETE /api/pages/:slug
  • admin user endpoints
  • Origin-check helper + native tests where pure
  • full validation suite passes

Summary of Changes

Full JSON API by a Sonnet agent; Opus review APPROVE with fixes applied:

  • src/routes/api.rs: /api/me, GET/POST /api/pages (§4.6 pipeline: auth, can_upload, Origin, slug, quota, size caps, manifest, D1-first slug reservation, R2 puts with rollback), DELETE with paginated R2 prefix cleanup, admin /api/users GET/PATCH.
  • src/core/origin.rs: origin_allowed + can_delete pure helpers (12 tests + 2 doctests).
  • Review fixes: DefaultBodyLimit::max(10 MiB) instead of disable() (memory bounded at body-collection time); DELETE Origin check hoisted before DB lookups per §4.6. 122 unit tests + 16 doctests green; both targets clippy-clean.