feat: implement notes CRUD for SQLite and API backends #3
No Reviewers
Labels
Clear labels
Agentic
Compat/Breaking
Kind/Bug
Kind/Documentation
Kind/Enhancement
Kind/Feature
Kind/Security
Kind/Testing
Agent
Fable
Work made by a Claude Fable agent
Agent
gpt-5.6-luna
Work made by a gpt-5.6-luna agent
Agent
gpt-5.6-sol
Work made by a gpt-5.6-sol agent
Agent
gpt-5.6-terra
Work made by a gpt-5.6-terra agent
Work made by an agent
Agent
Opus
Work made by a Claude Opus agent
Agent
Sonnet
Work made by a Claude Sonnet agent
Breaking change that won't be backward compatible
Something is not working
Documentation changes
Improve existing functionality
New functionality
This is security issue
Issue or pull request related to testing
Priority
Critical
1
The priority is critical
Priority
High
2
The priority is high
Priority
Low
4
The priority is low
Priority
Medium
3
The priority is medium
Reviewed
Confirmed
1
Issue has been confirmed
Reviewed
Duplicate
2
This issue or pull request already exists
Reviewed
Invalid
3
Invalid issue
Reviewed
Won't Fix
3
This issue won't be fixed
Status
Abandoned
3
Somebody has started to work on this but abandoned work
Status
Blocked
1
Something is blocking this issue or pull request
Status
Need More Info
2
Feedback is required to reproduce issue or to continue work
Milestone
No items
No Milestone
Projects
Clear projects
No projects
Notifications
Due Date
No due date set.
Reference: codinget/abode#3
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary
Implements the previously-stubbed Notes feature across all layers of the stack.
What was missing
All 7 note methods in both database backends threw
new Error("Unimplemented"):listNotes(),getNoteById(),deleteNoteById()createNote(),updateNote()listNotesByAbodeId(),listNotesByUserId()The API router also had three issues blocking the feature:
PATCH /notes/:nidwas missing theupdatenotevalidator/user/:uid/auth/clear-sessionsand/user/:uid/noteshad a typo (/user/instead of/users/), which also caused them to bypass theauthenticatemiddlewareChanges
src/db/sqlite/cast.ts— AddedsqliteToNote,sqliteToPartialNote, and property cast helpers.PartialNotealways hastype(defaults to"note").src/db/sqlite/query.ts— AddedselectNote,selectNotes,selectPartialNoteshelpers following the existing pattern.src/db/sqlite/SqliteInterface.ts— Implemented all 7 note methods.listNotesByUserIdfilters bycreated_by.src/db/api/ApiInterface.ts— Implemented all 7 note methods asfetchcalls to the appropriate routes. Added the missingctxparameter tocreateNote/updateNoteto matchDbInterface.src/webapi/apirouter.ts— Addedupdatenoteimport + validator toPATCH /notes/:nid; fixed both/user/:uid/→/users/:uid/typos.Test plan
POST /abodes/:aid/notes— creates a note and returns fullNoteGET /notes— lists all notes asPartialNote[](nocontentfield)GET /notes/:nid— returns fullNotewithcontentPATCH /notes/:nid— updatesname/content/properties; invalid body returns 400DELETE /notes/:nid— deletes note, returns 204GET /abodes/:aid/notes— lists notes for a specific abodeGET /users/:uid/notes— lists notes created by a userPATCH /notes/:nidwithout a valid body returns{ ok: false, error: "invalid" }/users/:uid/notesrequires authentication (was previously unauthenticated)🤖 Generated with Claude Code
Review: request changes — two confirmed bugs, please rebase on #2 or cherry-pick its fixes
Great catch on the
/user/:uid/→/users/:uid/typo fix in apirouter.ts — that's actually security-relevant, not cosmetic: theauthenticatemiddleware is mounted on/users, soPOST /user/:uid/auth/clear-sessionsandGET /user/:uid/noteswere running without authentication before this fix. Also confirmed theupdatenotevalidator is correctly wired intoPATCH /notes/:nid, and the SqliteInterface note methods mirror the established resident/abode patterns correctly (readonly checks,calcUpdates/InvalidAbodeError,NotFoundAbodeErroron 0 rows affected, FK violations correctly mapped).However, two bugs in
src/db/api/ApiInterface.ts— both pre-existing in#url()/#call()and independently fixed by PR #2 on the same lines, but not present here since this branch forked before that fix:#url()(~L58):remaining.delete(part)should beremaining.delete(part.slice(1)).remainingis keyed by bare param names ("nid"), butpartstill has the leading colon (":nid"), so the delete is a no-op. Verified directly — every new note route with a path param (GET/PATCH/DELETE /notes/:nid,POST/GET /abodes/:aid/notes,GET /users/:uid/notes) leaks that param into the query string on every request.#call()(~L116): no handling for HTTP 204 beforereturn res.json(). Verifiedapirouter.ts'sDELETE /notes/:nidreturnsctx.status = 204with no body — soApiInterface.deleteNoteById()will throwSyntaxError: Unexpected end of JSON inputon every single call. This method is completely broken as written. (This isn't notes-specific — the same bug affectsdeleteUserById/deleteAbodeById/etc. via the API backend — but this PR'sdeleteNoteByIdis what actually surfaces it here since it's new code routing through the same broken#call.)Recommendation: merge #2 first (it fixes both of these at the source), then rebase this branch on top so it inherits the fixes — cleaner than patching the same lines twice. Everything else in this PR looks ready to go once that's resolved.