learning_ai_common_plat/dashboards/tracker-web/docs/roadmaps/BACKEND_ENABLERS.md
saravanakumardb1 060daa4883 docs(tracker-web): record backend enablers for UX-12.3/13.1
Mark UX-12.3 (rich-text) and UX-13.1 (NotificationCenter) as
🔒 blocked-on-backend rather than open — they are excluded from the 
count and each now carries a one-paragraph spec of the exact
platform-service change required:
- UX-12.3: server-side HTML sanitization (allowlist tags/attrs; strip
  scripts/event-handlers/js: + data: URLs) on items.description +
  comments.body write paths, so RichTextEditor/RichTextViewer can be
  safely adopted.
- UX-13.1: emit notifications into platform-service's existing
  notifications module on tracker events (new comment, status change,
  vote milestone) targeted to the item author/subscribers with productId,
  exposed via the /api/tracker proxy, so NotificationCenter binds a real
  feed.

Add BACKEND_ENABLERS.md tracking both follow-ups (title, blocking item,
target module, acceptance criteria, backward-compat constraint —
platform-service is shared by 9 products). Update the Expand tracker line
and notes to show all client-only waves complete and these two
backend-blocked. Docs only — no source/dep/lockfile changes.

Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-05-29 07:31:55 -07:00

5.9 KiB
Raw Blame History

tracker-web — Backend Enablers

Follow-ups that cannot ship from dashboards/tracker-web alone because they require a change to the shared services/platform-service. They are the only remaining items on the UX integration roadmap and are excluded from its count until the backend enabler lands.

Hard constraint for every item below: platform-service is shared by 9 products (LysnrAI, MindLyst, ChronoMind, JarvisJr, NomGap, PeakPulse, FlowMonk, NoteLett, ActionTrail, EffoRise, LocalMemGPT — see AGENTS.md). Every change here must be additive and backward-compatible: no behavioural change for products that do not opt in, existing rows/reads keep working, and every persisted document keeps its productId.

ID Title Blocks Target module Status
BE-1 Server-side HTML sanitization for item/comment bodies UX-12.3 (rich-text) services/platform-service — items + comments write paths 🔒 Not started
BE-2 Tracker-event notifications feed UX-13.1 (NotificationCenter) services/platform-service — notifications module + /api/tracker proxy 🔒 Not started

BE-1 — Server-side HTML sanitization for items.description + comments.body

  • Title: Sanitize rich HTML on the item-description and comment-body write paths.
  • Blocking roadmap item: UX-12.3 — adopt @bytelyst/rich-text RichTextEditor / RichTextViewer in tracker-web.
  • Target module: services/platform-service — the items module (items.description) and the comments module (comments.body), applied server-side before persist (create + update).
  • Why it's blocked: Today TrackerItem.description and Comment.body are plain strings rendered with whitespace-pre-wrap; the /api/tracker/* proxy neither stores nor sanitizes rich HTML. Adopting a rich-text editor client-side would persist attacker-controlled HTML with no server-side sanitization (stored-XSS), so it must not be done until the backend guarantees safety.

Acceptance criteria

  • HTML is sanitized on the server (never trust the client) on every write to items.description and comments.body (create and update).
  • Allowlist of formatting tags only — e.g. p, br, strong, em, u, s, a, ul/ol/li, blockquote, code, pre, h1h3. Everything else is stripped/escaped.
  • Attribute allowlist: only safe attributes survive; a[href] is restricted to http: / https: / mailto: schemes (and gets rel="noopener noreferrer").
  • Stripped unconditionally: <script> / <style> / <iframe> / <object>, all inline event-handler attributes (on*), and javascript: / data: URLs.
  • Output is idempotent (sanitizing already-sanitized content is a no-op) and length-bounded as today.
  • Backward-compatible: existing plain-text rows still read correctly; products that send plain text are unaffected; the response shape is unchanged. No behavioural change for the other 8 products sharing platform-service.
  • Unit tests cover the XSS vectors above (script injection, onerror=, javascript: href, data: URI, mismatched/oversized tags).

Unblocks (tracker-web side, once shipped)

  • Swap the description/comment <textarea> for RichTextEditor (compose) and render saved content with RichTextViewer — no client-side dangerouslySetInnerHTML of unsanitized content.

BE-2 — Tracker-event notifications feed

  • Title: Emit + expose a per-user notifications feed for tracker events.
  • Blocking roadmap item: UX-13.1 — mount NotificationCenter (bell + InboxItem rows) in tracker-web.
  • Target module: services/platform-service — its existing notifications module (event emission) + the /api/tracker proxy (read surface).
  • Why it's blocked: tracker exposes no notifications feed — the /api/tracker/* proxy surfaces only items / comments / votes / roadmap. NotificationCenter/InboxItem have nothing to bind to, so only the client-side BannerStack/Announcement (UX-13.2) shipped.

Acceptance criteria

  • Tracker events emit notifications into the existing notifications module — at minimum: new comment, status change, and vote milestone (e.g. crossing 10/25/50 votes).
  • Each notification is fanned out to the item author and any subscribers/watchers of the item, and is stamped with productId so the feed is product-scoped.
  • A read API (list with pagination, unread count, mark-as-read / mark-all-read) is exposed through the /api/tracker proxy so the dashboard reads it with the existing auth token.
  • Payload shape is compatible with @bytelyst/notifications-ui InboxItem (id, title/body, type, timestamp, read flag, deep-link to the item).
  • Additive / backward-compatible: emitting these notifications causes no behavioural change for the 9 products that do not subscribe; the notifications module contract is extended, not broken; every notification document carries productId.
  • Tests cover emission on each event type, author/subscriber targeting, product scoping, and the unread-count / mark-as-read transitions.

Unblocks (tracker-web side, once shipped)

  • Bind NotificationCenter to the feed (bell + InboxItem rows) in the AppShell sidebar/header, reading via the /api/tracker proxy.