Previously P10.5 was marked complete with a deferral note because the
sibling services (platform-service 4003, extraction-service 4005,
mcp-server 4007) were not running on the audit host. Today they are
all running, so I executed the smoke and confirmed it passes.
Command:
JWT_SECRET="dev-secret-change-me-at-least-32-characters-long" \
bash scripts/local-smoke.sh
Output (exit 0, 11 ok lines):
info: starting NoteLett backend in memory mode
ok: NoteLett backend started at http://localhost:4016
ok: NoteLett health
ok: NoteLett bootstrap
ok: platform-service health
ok: extraction-service health
ok: mcp-server health
ok: authenticated workspace create
ok: authenticated note create
ok: authenticated note read
ok: smoke cleanup attempted
ok: local production-readiness smoke passed
Updates:
- §Post-Sprint-A Re-verification: replaces the blanket deferral note
with the actual verification details for live shared-service smoke
and a separate, narrower deferral note for Docker compose smoke
(which still fails on corp-network hosts due to TLS interception in
the backend/Dockerfile npm install step but succeeds on CI).
- §P10.5: replaces the historical deferral text with today's
end-to-end verification result.
UI8 deferred deleting the legacy global classes (.surface-card,
.surface-muted, .input-shell, .badge) because 69+ call sites in UI6/UI7
territory (dashboard, search, workspaces, notes detail, chat, palace)
still depend on them. Removing the globals before those screens migrate
would visually break the app.
Instead, ship a one-way ratchet that solves the actually-important
problem: prevent NEW legacy usage from creeping in while existing
sites get migrated.
- scripts/ui-drift-ratchet.sh — reads scripts/ui-drift-baseline.json
and FAILS if any of the four UI drift categories regress above the
tracked baseline. Pure bash, no jq required, works with grep or
ripgrep. Uses the same patterns as scripts/ui-drift-audit.sh.
- scripts/ui-drift-baseline.json — checked-in baseline captured today:
raw controls 38, legacy classes 92, hardcoded colors 0, direct imports 0.
- package.json — adds pnpm run audit:ui:ratchet and
audit:ui:ratchet:update scripts.
- .github/workflows/ci.yml release-guards job — runs the ratchet as a
required step plus the existing audit in report mode.
- docs/UI_UX_PLATFORM_CORE_ROADMAP.md — marks the CI-guard checklist
item complete, documents the path to fully strict mode (drive
baseline to zero, then delete globals.css legacy classes, then flip
audit:ui:strict from advisory to required).
Verified:
- Ratchet at baseline: exits 0
- Synthetic regression (added a file with surface-card + raw <input>):
ratchet correctly exits 1, reporting +1 in each affected category
- pnpm run verify: backend 380/380, web 96/96, mobile 97/97 (no
behavior change)
Sprint B — closes audit item B7 (doc consolidation).
- docs/AGENT_TASK_ROADMAP.md, docs/ARCHITECTURE_REVIEW_AND_REUSE_ROADMAP.md,
docs/GAP_ANALYSIS.md were each self-marked as historical snapshots
but kept polluting the top of docs/. Moved them under docs/archive/
in the previous commit; this commit:
- Adds docs/archive/README.md explaining what's archived vs active
- Repoints cross-doc links in docs/IMPLEMENTATION_TRACKER.md,
docs/WEB_AI_FAST_ROADMAP.md, and docs/roadmaps/*.md to the new
archive paths
- Fixes relative links inside the archived files themselves so
historical readers can still navigate back to active docs
- AGENTS.md §1.1 refreshed: reflects the May 22 re-verified state
(382/96/97 tests), links the two new runbooks, and points readers
away from docs/archive/ as a work source.
Sprint B — closes audit items B4 and B5.
- docs/runbooks/MEK_ROTATION.md: step-by-step procedure for rotating
the field-encrypt master key in Azure Key Vault, including pre-flight
checks, rewrapAllDeks usage, verification queries, rollback, and lost-MEK
recovery. Replaces the previous gap where MEK rotation had no
documented operator path.
- docs/runbooks/SECRET_MANAGEMENT.md: inventory of every secret consumed
by NoteLett with its production source (AKV), two production-grade
patterns (workload identity vs K8s CSI), the compose-host pattern,
rotation flow per secret type, verification commands, and red-flag
triage.
Both docs cross-link each other and call out concrete open items
(automation, dual-JWT support, audit-log emission) for later sprints
rather than overstating current capabilities.
Sprint B — closes audit items B6 (event-bus completeness) and B3
(public-share revocation regression).
Event bus:
- note-tasks/repository.ts createNoteTask now emits task.created with
taskId, noteId, workspaceId, userId, title
- workspaces/repository.ts createWorkspace now emits workspace.created
with workspaceId, userId, name
The event-bus already declared these event types (event-bus.ts) and
webhook subscribers can target them, but they were never emitted —
making the contract dead. Emissions follow the same .catch(() => {})
pattern used by note.created/updated/deleted in notes/repository.ts so
a subscriber failure cannot break the create flow.
Regression tests:
- note-tasks/repository.test.ts and workspaces/repository.test.ts
exercise the emission paths end-to-end through the in-memory
datastore.
- note-shares/repository.integration.test.ts adds a 5-test integration
suite for the public-share revocation path: token resolves before
revocation; token returns null after deleteShare (hard delete);
expired token returns null; cross-product token rejected;
listSharesForNote does not include revoked shares.
Verified:
- pnpm --filter @notelett/backend run test: 380/380 (was 373, +7 new)
- pnpm run verify end-to-end green
- Commit previously untracked docs/NEXT_SPRINT_ROADMAP.md with refreshed
May 22 status; mark Sprint 1 (backend build) and Sprint 2 (lint) as
resolved by Sprint A workspace-path fix
- Add post-Sprint-A re-verification section to
docs/PRODUCTION_READINESS_HANDOFF_ROADMAP.md documenting the
workspace-path regression and the re-verified gates
- Update README quick-start to reference the canonical common-platform
checkout path with BYTELYST_COMMON_PLAT_ROOT override note