feat(notes): notes-tools create/update/delete/get/search_notes + list_note_keywords (IDEA-226, PBI-30) #171

Merged
janpeter merged 9 commits from feat/notes-tools-pbi30 into main 2026-09-28 14:07:52 +02:00
Owner

Notes-tools (IDEA-226, PBI-30 — spiegel van Scrum4Me PBI-167)

Zes MCP-tools voor privé-notes van de tokengebruiker, met hetzelfde gedrag als de web-adapter lib/notes-server.ts in Scrum4Me (#270, gemerged en gedeployed).

Wat

  • T-149 — vendor/scrum4me-shared → 5f9afaa (merge scrum4me-shared#65: Note/NoteKeyword/NoteKeywordLink + lib/note-schema.ts), prisma/schema.prisma geregenereerd, import-rooktest; ppe-bundle1-parity-pin mee naar 5f9afaa.
  • T-150 — src/lib/notes-data.ts: de enige module die prisma.note*/noteKeyword*/noteKeywordLink* raakt. Alle queries user-scoped (keyword-reads: defaults + eigen); productkoppeling én productfilter via userCanAccessProduct (respecteert scoped_products); update in één transactie met rollback bij count-mismatch; lijst zonder body.
  • T-151 — get_note (enige read/search-tool mét body), search_notes (limit 1–100 zonder clamp, offset, {items,total,limit,offset,has_more} zonder body), list_note_keywords.
  • T-152 — create_note, update_note (partiële semantiek spec § 2.5.1), delete_note; requireWriteAccess() als eerste statement van elke handler, beschrijving eindigt op "Forbidden for demo accounts.". Protocoltest via InMemoryTransport legt vast: demo + geldige input → PERMISSION_DENIED; input die het gepubliceerde schema niet haalt → SDK-validatiefout vóór de handler (geen adaptercall).
  • T-153 — README-tooltabel + db pull-verbod op note_keywords (Schema sync) en sectie Notes-tools in CLAUDE.md.

Verificatie

npx tsc --noEmit groen; npm test 2008 passed / 69 skipped, 0 failed. Per-taak reviews (opus) en whole-branch review: 0 Critical, 0 Important.

Uitrol (na merge)

DB is al klaar: migratie 20260928060000_add_notes staat op de server-DB en scrum4me_web_runtime (de MCP-rol) heeft CRUD op de drie tabellen. Bij elke host de submodule meenemen, anders faalt de import van @shared/note-schema.js en valt de héle MCP om:

git pull --ff-only && git submodule update --init vendor/scrum4me-shared && npm ci

Geen nieuwe env-vars, geen migratie, geen db pull.

Beslissingen en uitgesteld

  • Een demo-token met input die het gepubliceerde schema niet haalt krijgt de SDK-validatiefout i.p.v. PERMISSION_DENIED; schrijft in beide gevallen niets. Schema's bewust niet versoepeld.
  • Productfilter buiten toegang/scope → "Product niet gevonden" (web filtert alleen op eigen notes).
  • Uitgesteld: link-delete zonder user-scope als defense-in-depth (ook in web, pariteit); offset zonder bovengrens (shared-contract); get_note keyword-vorm genest vs list_note_keywords plat; geen test tegen een echte DB.
  • Ter beslissing: een product-gescoped token (bv. copilot) kan alle notes van zijn gebruiker lezen/wijzigen — binnen de spec, die scoped_products alleen op koppelen/filteren toepast.

🤖 Generated with Claude Code

## Notes-tools (IDEA-226, PBI-30 — spiegel van Scrum4Me PBI-167) Zes MCP-tools voor privé-notes van de tokengebruiker, met hetzelfde gedrag als de web-adapter `lib/notes-server.ts` in Scrum4Me (#270, gemerged en gedeployed). ### Wat - **T-149** — `vendor/scrum4me-shared` → `5f9afaa` (merge scrum4me-shared#65: Note/NoteKeyword/NoteKeywordLink + `lib/note-schema.ts`), `prisma/schema.prisma` geregenereerd, import-rooktest; `ppe-bundle1-parity`-pin mee naar `5f9afaa`. - **T-150** — `src/lib/notes-data.ts`: de enige module die `prisma.note*`/`noteKeyword*`/`noteKeywordLink*` raakt. Alle queries user-scoped (keyword-reads: defaults + eigen); productkoppeling én productfilter via `userCanAccessProduct` (respecteert `scoped_products`); update in één transactie met rollback bij count-mismatch; lijst zonder body. - **T-151** — `get_note` (enige read/search-tool mét body), `search_notes` (limit 1–100 zonder clamp, offset, `{items,total,limit,offset,has_more}` zonder body), `list_note_keywords`. - **T-152** — `create_note`, `update_note` (partiële semantiek spec § 2.5.1), `delete_note`; `requireWriteAccess()` als eerste statement van elke handler, beschrijving eindigt op "Forbidden for demo accounts.". Protocoltest via `InMemoryTransport` legt vast: demo + geldige input → `PERMISSION_DENIED`; input die het gepubliceerde schema niet haalt → SDK-validatiefout vóór de handler (geen adaptercall). - **T-153** — README-tooltabel + `db pull`-verbod op `note_keywords` (Schema sync) en sectie Notes-tools in CLAUDE.md. ### Verificatie `npx tsc --noEmit` groen; `npm test` 2008 passed / 69 skipped, 0 failed. Per-taak reviews (opus) en whole-branch review: 0 Critical, 0 Important. ### Uitrol (na merge) DB is al klaar: migratie `20260928060000_add_notes` staat op de server-DB en `scrum4me_web_runtime` (de MCP-rol) heeft CRUD op de drie tabellen. **Bij elke host de submodule meenemen**, anders faalt de import van `@shared/note-schema.js` en valt de héle MCP om: ```bash git pull --ff-only && git submodule update --init vendor/scrum4me-shared && npm ci ``` Geen nieuwe env-vars, geen migratie, geen `db pull`. ### Beslissingen en uitgesteld - Een demo-token met input die het gepubliceerde schema niet haalt krijgt de SDK-validatiefout i.p.v. `PERMISSION_DENIED`; schrijft in beide gevallen niets. Schema's bewust niet versoepeld. - Productfilter buiten toegang/scope → "Product niet gevonden" (web filtert alleen op eigen notes). - Uitgesteld: link-delete zonder user-scope als defense-in-depth (ook in web, pariteit); `offset` zonder bovengrens (shared-contract); `get_note` keyword-vorm genest vs `list_note_keywords` plat; geen test tegen een echte DB. - Ter beslissing: een product-gescoped token (bv. copilot) kan alle notes van zijn gebruiker lezen/wijzigen — binnen de spec, die `scoped_products` alleen op koppelen/filteren toepast. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
docs(notes): body- en demo-volgorde exact benoemd (review T-151/152)
All checks were successful
CI / Final merge attestation and immutable publication (pull_request) Has been skipped
CI / PR candidate (never published) (pull_request) Successful in 6m21s
99acbca880
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
s4m-codex-reviewer left a comment

APPROVED

  • Geen blokkerende findings aangetroffen. De nieuwe notes-tools houden gebruikersscoping en demo-schrijfbeperking consequent afgedwongen, gebruiken het gedeelde schema-contract en registreren alle zes tools in de gedeelde toolset.
  • Tests: het bijgewerkte Prisma-schema genereert succesvol en beide TypeScript-configuraties slagen. De gerichte Vitest-run kon lokaal niet starten omdat de tijdelijke mount noexec is; dit is geen codefinding.
  • geen gekoppeld plan gevonden — beoordeeld op codekwaliteit + product-standaarden.
## APPROVED - Geen blokkerende findings aangetroffen. De nieuwe notes-tools houden gebruikersscoping en demo-schrijfbeperking consequent afgedwongen, gebruiken het gedeelde schema-contract en registreren alle zes tools in de gedeelde toolset. - Tests: het bijgewerkte Prisma-schema genereert succesvol en beide TypeScript-configuraties slagen. De gerichte Vitest-run kon lokaal niet starten omdat de tijdelijke mount `noexec` is; dit is geen codefinding. - geen gekoppeld plan gevonden — beoordeeld op codekwaliteit + product-standaarden.
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
janpeter/scrum4me-mcp!171
No description provided.