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>
5.9 KiB
5.9 KiB
tracker-web — Backend Enablers
Follow-ups that cannot ship from
dashboards/tracker-webalone because they require a change to the sharedservices/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-serviceis shared by 9 products (LysnrAI, MindLyst, ChronoMind, JarvisJr, NomGap, PeakPulse, FlowMonk, NoteLett, ActionTrail, EffoRise, LocalMemGPT — seeAGENTS.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 itsproductId.
| 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-textRichTextEditor/RichTextViewerin 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.descriptionandComment.bodyare plainstrings rendered withwhitespace-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.descriptionandcomments.body(create and update). - Allowlist of formatting tags only — e.g.
p,br,strong,em,u,s,a,ul/ol/li,blockquote,code,pre,h1–h3. Everything else is stripped/escaped. - Attribute allowlist: only safe attributes survive;
a[href]is restricted tohttp:/https:/mailto:schemes (and getsrel="noopener noreferrer"). - Stripped unconditionally:
<script>/<style>/<iframe>/<object>, all inline event-handler attributes (on*), andjavascript:/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>forRichTextEditor(compose) and render saved content withRichTextViewer— no client-sidedangerouslySetInnerHTMLof 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 +InboxItemrows) in tracker-web. - Target module:
services/platform-service— its existing notifications module (event emission) + the/api/trackerproxy (read surface). - Why it's blocked: tracker exposes no notifications feed — the
/api/tracker/*proxy surfaces only items / comments / votes / roadmap.NotificationCenter/InboxItemhave nothing to bind to, so only the client-sideBannerStack/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
productIdso the feed is product-scoped. - A read API (list with pagination, unread count, mark-as-read / mark-all-read) is exposed through
the
/api/trackerproxy so the dashboard reads it with the existing auth token. - Payload shape is compatible with
@bytelyst/notifications-uiInboxItem(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
NotificationCenterto the feed (bell +InboxItemrows) in the AppShell sidebar/header, reading via the/api/trackerproxy.