Phase 2 of the execution roadmap:
- Add DELETE endpoints for notes (soft-delete), workspaces, tasks, artifacts, relationships
- Add requireWriter() role enforcement on all write routes (POST/PATCH/DELETE)
- Activate trackEvent() telemetry on note.created, note.updated, note.archived, workspace.created
- Gate notes search behind isFeatureEnabled('notes.enabled')
- Update all test mocks to include role and new auth exports
Made-with: Cursor
13 KiB
NoteLett — Agent Task Roadmap
Date: March 29, 2026
Product: NoteLett (notelett) — Structured notes for humans + AI agents
Repo: learning_ai_notes
Stack: Fastify 5 backend (port 4016) · Next.js 16 web (port 3000) · Expo mobile
Platform deps: 23 @bytelyst/* packages (all resolve against learning_ai_common_plat)
Current State
| Surface | Routes / Modules | Tests | Build | Platform Pkgs |
|---|---|---|---|---|
| Backend | 7 modules, ~32 endpoints, 8 MCP tools | 20 files (unit + integration) | ✅ tsc | 13 (5 missing source in common_plat) |
| Web | 6 pages, 13 components, 15 lib files | 7 unit + 7 E2E | ✅ next build | 10 (all used) |
| Mobile | 4 tabs, note detail, auth, 5 stores | 23 tests (4 files) | ✅ typecheck | — |
Package resolution note: 5 backend @bytelyst/* packages (backend-config, backend-flags, backend-telemetry, fastify-auth, field-encrypt) do not have source directories in learning_ai_common_plat/packages/. They resolve via ^0.1.0 from the private Gitea npm registry but their source must be created in common_plat. This is a shared blocker with NomGap — see Phase 0 below.
Phase 0 — Missing Platform Package Source (SHARED BLOCKER)
These 5 backend packages are depended on by both NoteLett and NomGap but have no source directory in learning_ai_common_plat/packages/. They must be created there before either product's backend can be built from a clean checkout of common_plat.
-
0.1 Create
@bytelyst/backend-configinlearning_ai_common_plat/packages/backend-config/- Base Zod config schema extended by all product backends
- Imported by:
backend/src/lib/config.ts
-
0.2 Create
@bytelyst/backend-flagsinlearning_ai_common_plat/packages/backend-flags/- Feature flag registry for backend services
- Imported by:
backend/src/lib/feature-flags.ts
-
0.3 Create
@bytelyst/backend-telemetryinlearning_ai_common_plat/packages/backend-telemetry/- Buffered telemetry event tracking for backends
- Imported by:
backend/src/lib/telemetry.ts
-
0.4 Create
@bytelyst/fastify-authinlearning_ai_common_plat/packages/fastify-auth/- JWT auth middleware (RS256 JWKS + HS256 fallback),
extractAuth,requireRole,createRequestContext - Imported by:
backend/src/lib/auth.ts,backend/src/lib/request-context.ts, all route modules
- JWT auth middleware (RS256 JWKS + HS256 fallback),
-
0.5 Create
@bytelyst/field-encryptinlearning_ai_common_plat/packages/field-encrypt/- Field-level encryption/decryption with AKV/env/memory key providers
- Imported by:
backend/src/lib/field-encrypt.ts,backend/src/modules/notes/repository.ts
Note: These tasks require changes in learning_ai_common_plat, not in this repo. Coordinate with the common platform agent. NomGap also depends on all 5 of these.
Verification:
cd ../learning_ai_common_plat && pnpm run build
cd ../learning_ai_notes/backend && pnpm install && pnpm run typecheck
Phase 0.5 — Fix Broken Imports + Adopt Dashboard Components
- 0.5.1 Replace broken
@bytelyst/uiToastProvider withsonner—7babee7 - 0.5.2 Adopt
@bytelyst/dashboard-components(ErrorPage, NotFoundPage, LoadingSpinner) —7babee7 - 0.5.3 Replace raw
extraction-client.tswith@bytelyst/extraction—7babee7
Phase 1 — Critical Web Gaps
These block the web app from being usable by real users.
-
1.1 Add auth pages — login, register, forgot-password —
839218a- Create
web/src/app/(auth)/login/page.tsx,register/page.tsx,forgot-password/page.tsx - Wire to existing
@bytelyst/react-authconfig inweb/src/lib/auth.ts - Include form validation, error states, loading states
- Files: new pages under
web/src/app/(auth)/
- Create
-
1.2 Add
middleware.tsfor route protection —839218a- Redirect unauthenticated users from
(app)/*routes to/login - Redirect authenticated users from
/loginto/dashboard - Check kill-switch status (call
checkKillSwitch()fromweb/src/lib/kill-switch.ts) - File:
web/src/middleware.ts
- Redirect unauthenticated users from
-
1.3 Replace plain textarea with a rich note editor —
839218a- Current
NoteEditor.tsxis a bare<textarea>— inadequate for a notes product - Add markdown support (headings, bold, italic, lists, code blocks) at minimum
- Consider Tiptap, Lexical, or MDXEditor
- File:
web/src/components/NoteEditor.tsx
- Current
-
1.4 Add workspace CRUD from web —
839218a- Backend already has
POST /workspacesandPATCH /workspaces/:id - Add create-workspace modal/form on the workspaces page
- Add edit/delete actions on workspace cards
- Files:
web/src/app/(app)/workspaces/page.tsx, new modal component
- Backend already has
-
1.5 Wire toast notifications —
839218aToastProviderfrom@bytelyst/uiis mounted but zero toasts are triggered- Replace
window.confirm()calls with a confirmation dialog component - Add success/error toasts after note create, update, archive, link, task create, artifact create
- Files: all page files + components that do mutations
Verification:
cd web && pnpm run typecheck && pnpm test && pnpm run build
Phase 2 — Backend Hardening
-
2.1 Add integration tests for all route modules using
buildTestApp()+ Fastify.inject()- Current route tests only check handler registration counts
- Need real request/response tests: happy path, validation errors, auth enforcement, 404s
- Modules needing inject tests: notes, workspaces, note-relationships, note-tasks, note-artifacts, note-agent-actions, saved-views
- Files:
backend/src/modules/*/routes.integration.test.ts(7 new files)
-
2.2 Add DELETE endpoints for notes, workspaces, tasks, artifacts, relationships
- Currently only saved-views has DELETE
- Notes support archive but not hard delete — add soft-delete with a
deletedAttimestamp - Files:
backend/src/modules/*/routes.ts+repository.ts
-
2.3 Enforce role-based access on REST routes
requireRoleis exported and tested but not used on any REST route- At minimum: write routes (POST/PATCH/DELETE) should require
editororadminrole - File: every
routes.tsfile
-
2.4 Enforce workspace member authorization
workspace.membersarray is stored but never checked- Note CRUD should verify the requesting user is a member of the target workspace
- Files:
backend/src/modules/notes/routes.ts,backend/src/modules/workspaces/repository.ts
-
2.5 Activate telemetry — call
trackEvent()on key business actions- Buffer and flush infrastructure exist but no route handler actually calls
trackEvent() - Track: note.created, note.updated, note.archived, note.searched, workspace.created, agentAction.approved, agentAction.rejected
- Files: all
routes.tsfiles +backend/src/lib/telemetry.ts
- Buffer and flush infrastructure exist but no route handler actually calls
-
2.6 Activate feature flags in route logic
- 6 flags registered with defaults but no route checks
isFeatureEnabled() - At minimum: gate MCP write tools behind
mcp.enabled, gate export behind a flag - Files:
backend/src/lib/feature-flags.ts, relevant route files
- 6 flags registered with defaults but no route checks
Verification:
cd backend && pnpm run typecheck && pnpm test
Phase 3 — Web UX Polish
-
3.1 Add pagination to all list views
- Backend already returns
total,limit,offset— web ignores them and fetches everything - Add pagination controls to: notes list, workspaces list, search results, review queue, saved views
- Files: all page files under
web/src/app/(app)/
- Backend already returns
-
3.2 Fix
getNoteDetail— useGET /notes/:idinstead of fetching all notes- File:
web/src/lib/notes-client.tsline ~291
- File:
-
3.3 Fix
listApprovalQueueN+1 — add backend cross-workspace pending-actions endpoint- Currently fetches all workspaces, then all actions per workspace
- Add
GET /note-agent-actions/pending(already exists) usage in web client - Files:
web/src/lib/review-client.ts
-
3.4 Add skeleton loading states per section (not just global spinner)
- File: new
Skeleton.tsxcomponent + integration in each page
- File: new
-
3.5 Add file upload UI for artifacts
blob-client.tssupportsuploadArtifact()but no component triggers it- Add file picker + upload progress to ArtifactPanel
- File:
web/src/components/ArtifactPanel.tsx
-
3.6 Remove unused dependencies
- Remove
zustandandzodfrom webpackage.json(declared, never imported anywhere inweb/src/)
- Remove
-
3.7 Fix SSR crash risk — lazy-init module-scope API clients
extraction-client.tsandblob-client.tsinstantiate clients at module scope- Apply lazy singleton pattern (init on first call, not on import)
- Add
"use client"tonotes-client.tsor refactor extraction-client - Files:
web/src/lib/extraction-client.ts,web/src/lib/blob-client.ts,web/src/lib/notes-client.ts
-
3.8 Consolidate duplicate type definitions
NoteAgentActionDoc,NoteDoc, etc. duplicated acrossnotes-client.ts,review-client.ts,extraction-client.ts- Move to
web/src/lib/types.tsand import from there - Files:
web/src/lib/types.ts+ all client files
Verification:
cd web && pnpm run typecheck && pnpm test && pnpm run build
Phase 4 — MCP & AI Enrichment
-
4.1 Wire MCP tool registration to shared
mcp-serverMCP_SERVER_URL=http://localhost:4007is configured but no outbound call exists- Backend exposes tools via
register-note-tools.ts— need HTTP client to register them with the shared MCP server at startup - File:
backend/src/server.tsor newbackend/src/lib/mcp-registration.ts
-
4.2 Add note summarization to web UI
- Backend
POST /notes/:id/summarizealready works via extraction-service - Add "Summarize" button to note detail page that calls the endpoint and shows the result
- Files:
web/src/app/(app)/notes/[noteId]/page.tsx,web/src/lib/notes-client.ts
- Backend
-
4.3 Add note export UI
- Backend
GET /notes/exportalready supports JSON and Markdown formats - Add "Export" button to dashboard or workspace pages
- Files:
web/src/app/(app)/dashboard/page.tsxor workspaces page
- Backend
Verification:
cd backend && pnpm run typecheck && pnpm test
cd web && pnpm run typecheck && pnpm test && pnpm run build
Phase 5 — DevOps & CI
-
5.1 Review and enable CI workflows
- Gitea CI (
.gitea/workflows/ci.yml) is already active - GitHub Actions (
.github/workflows/ci.yml.disabled) exists but is disabled — review, update, rename toci.ymlif GitHub is the target - Files:
.github/workflows/ci.yml,.gitea/workflows/ci.yml
- Gitea CI (
-
5.2 Fix Docker Compose platform-service reference
docker-compose.ymlreferenceslocalhost:4003andlocalhost:4005but doesn't define those services- Either add
platform-serviceandextraction-serviceas services, or document that they must be run separately - File:
docker-compose.yml
-
5.3 Fix
web/.env.example- Bug: Product identity is stale — shows
NEXT_PUBLIC_PRODUCT_NAME=ByteLyst Agentic NotesandNEXT_PUBLIC_PRODUCT_ID=agentic-notesinstead ofNoteLett/notelett - Missing vars:
NEXT_PUBLIC_EXTRACTION_SERVICE_URLandNEXT_PUBLIC_PLATFORM_SERVICE_ORIGINare used in code but not listed - File:
web/.env.example
- Bug: Product identity is stale — shows
Verification:
docker compose build
docker compose up -d && curl http://localhost:4016/api/bootstrap
Phase 6 — Docs Alignment
-
6.1 Update
docs/ROADMAP.mdphase checklists- Many Phase 0–3 items remain unchecked despite being implemented (per progress notes in §8)
- File:
docs/ROADMAP.md
-
6.2 Update
AGENTS.mdwith current test counts and any new endpoints added in this roadmap -
6.3 Update
README.mdwith current quick-start that reflects real auth and data flow
Task Summary
| Phase | Tasks | Priority | Est. Effort |
|---|---|---|---|
| 0 — Missing Platform Packages | 5 | CRITICAL | 4–6 hours (in common_plat) |
| 1 — Critical Web Gaps | 5 | HIGH | 6–8 hours |
| 2 — Backend Hardening | 6 | HIGH | 5–7 hours |
| 3 — Web UX Polish | 7 | MEDIUM | 4–5 hours |
| 4 — MCP & AI | 3 | MEDIUM | 2–3 hours |
| 5 — DevOps & CI | 3 | MEDIUM | 1–2 hours |
| 6 — Docs | 3 | LOW | 1 hour |
| Total | 32 | 23–32 hours |
Phase 0 must be done first — it requires changes in learning_ai_common_plat and unblocks both NoteLett and NomGap backends.
Verification Commands (run after each phase)
# Backend
cd backend && pnpm run typecheck && pnpm test && pnpm run build
# Web
cd web && pnpm run typecheck && pnpm test && pnpm run build
# Mobile
cd mobile && pnpm run typecheck && pnpm test
# E2E
cd web && pnpm exec playwright test