Commit Graph

226 Commits

Author SHA1 Message Date
saravanakumardb1
0c982de7e6 feat(web/ui8): remove legacy global classes + tighten audit regex + lock CI gate
UI8 closes the migration cycle started by UI0. The four legacy global
classes (.surface-card, .surface-muted, .badge, .input-shell) are
removed from web/src/app/globals.css and the CI ratchet now enforces
zero new occurrences across three of the four drift categories.

Changes:

1. Audit regex precision (scripts/ui-drift-audit.sh, scripts/ui-drift-ratchet.sh)

   The previous pattern 'className="[^"]*(badge|surface-card|surface-muted|input-shell)'
   matched the literal token anywhere inside className, which caused 21
   false positives against Tailwind arbitrary values like
   'bg-[color:var(--nl-surface-muted)]' where the legacy name appears
   inside a 'var(--nl-...)' reference.

   New pattern requires the legacy class to be a whole class token —
   either at the start of className, or preceded by a space, and
   followed by a space or closing quote. Result: 21 false positives
   eliminated; the ratchet now reports an honest 0 for the legacy
   category.

2. globals.css cleanup (web/src/app/globals.css)

   Removed .surface-card, .surface-muted, .badge, .input-shell rules.
   Only truly global utilities remain (typography, focus-visible,
   sr-only, skip-link, motion preferences, layout grids). A header
   comment documents that re-introductions should be solved at the
   call-site with a primitive, not by restoring the global rule.

3. Ratchet baseline (scripts/ui-drift-baseline.json)

   Final counts after UI5–UI8 across the session:
     raw interactive controls       14   (was 38 at start)
     legacy global surface classes  0    (was 92 at start)
     hardcoded color literals       0    (no change, was already 0)
     direct @bytelyst/ui imports    0    (no change, was already 0)

   The 14 remaining raw controls are intentional and tracked:
     NoteEditor toolbar buttons (10)
     ArtifactPanel hidden file input (1)
     search/page radio inputs (2)
     NoteVersionsPanel disclosure button (1)

4. CI gate (.github/workflows/ci.yml release-guards job)

   Documented that the ratchet is the canonical gate post-UI8: because
   legacy/colors/imports baselines are 0, any new occurrence in those
   three categories now fails CI. The strict-audit script is kept as
   a local diagnostic tool but not wired as a gate (would fail on the
   14 intentional raw controls).

5. Roadmap (docs/UI_UX_PLATFORM_CORE_ROADMAP.md)

   Marked UI5, UI6, UI7, UI8 all complete with per-phase commit hashes
   and explicit deliverables.

Cumulative migration impact (from initial baseline):
   raw interactive controls       38 → 14   (-24, -63%)
   legacy global surface classes  92 → 0    (-92, -100%)

Verified:
- pnpm run verify: backend 380/380, web 96/96, mobile 97/97
- bash scripts/ui-drift-ratchet.sh: all four categories at baseline
- bash scripts/ui-drift-audit.sh: only "Raw interactive controls"
  category has matches (intentional, tracked above)
- Live Docker stack at http://localhost:3050 still serves 200,
  backend health 200
2026-05-23 01:55:36 -07:00
saravanakumardb1
d5e857dbf7 test(e2e): docker compose E2E test + seed scripts + 9-step verification
Implements the full E2E flow against the deployed docker stack and
documents it as a repeatable test playbook.

Surfaced and fixed three real issues while building the E2E:

1. JWT secret mismatch — docker-compose.override.yml backend was using
   a NoteLett-only JWT_SECRET that platform-service did not share, so
   every Authorization: Bearer call returned 'Invalid or expired token'.
   Aligned the override to use platform-service's actual secret
   (dev-ecosystem-secret-do-not-use-in-production).

2. CORS preflight missing PATCH/DELETE — @bytelyst/fastify-core registers
   @fastify/cors with only { origin }, which leaves Access-Control-Allow-
   Methods at the @fastify/cors default of 'GET,HEAD,POST'. Real browser
   PATCH/DELETE preflights would fail. Added an onSend hook in
   backend/src/server.ts that rewrites the header to
   'GET,HEAD,POST,PATCH,PUT,DELETE,OPTIONS' on CORS preflight responses.

3. Product 'notelett' wasn't registered with platform-service — auth
   register/login both error with 'Unknown or disabled product: notelett'.
   The seed script now POSTs to /api/products idempotently.

Deliverables:

- scripts/e2e-docker-seed.sh — idempotent: registers the notelett product
  and creates two test users (admin@notelett.app with role=admin who can
  write, user@notelett.app with role=user who is read-only). Re-runs are
  no-ops once seeded.

- scripts/e2e-docker-test.sh — 9-step E2E that drives the deployed stack
  via HTTP only (no browser): login → CORS preflight for PATCH →
  workspace create → note create → note read → note PATCH (status:
  draft→active) → note list → note delete → workspace delete.

- docs/testing/E2E_DOCKER_TESTING.md — full playbook covering prereqs,
  seed, automated E2E, manual UI smoke, stack architecture diagram,
  troubleshooting (JWT mismatch, unknown product, role rejection,
  CORS, port conflict, data loss), tear-down, CI wiring guidance.

- package.json — pnpm e2e:docker:seed and pnpm e2e:docker:test
  shortcuts.

Verified live on this host's deployed stack:

  $ bash scripts/e2e-docker-seed.sh
  ↷ product 'notelett' already exists
  ↷ admin user already registered + login works
  ✓ user created
  🟢 Seed complete.

  $ bash scripts/e2e-docker-test.sh
  ✓ user=usr_e094e0c2-... role=admin
  ✓ CORS allows PATCH
  ✓ workspace created
  ✓ note created
  ✓ note read matches
  ✓ note patched (status: draft → active)
  ✓ note list returned (1 item)
  ✓ note deleted (HTTP 204)
  ✓ workspace deleted (HTTP 204)
  🟢 All 9 E2E steps passed.

Backend regression suite still green: 380/380.
2026-05-23 01:16:19 -07:00
saravanakumardb1
34cb219962 docs(p10.5): live shared-service smoke verified end-to-end May 23, 2026
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.
2026-05-23 00:30:44 -07:00
saravanakumardb1
78433b0e45 feat(ci): one-way UI drift ratchet to prevent regressions
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)
2026-05-23 00:13:50 -07:00
saravanakumardb1
4667f85e20 docs(cleanup): move historical roadmaps to docs/archive/ and update AGENTS.md
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.
2026-05-22 23:23:50 -07:00
saravanakumardb1
bcad7d330a docs(runbooks): add MEK rotation and secret-management runbooks
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.
2026-05-22 23:23:38 -07:00
saravanakumardb1
1258d49488 feat(backend): emit task.created + workspace.created events; add share revocation regression test
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
2026-05-22 23:23:08 -07:00
saravanakumardb1
c75ed3dc25 docs(sprint-a): record build restoration and refreshed sprint plan
- 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
2026-05-22 15:08:42 -07:00
root
3fe4f0786c feat(ux): add UX testing setup guide and common platform integration 2026-05-09 22:09:43 +00:00
a983e044b1 docs(ui): record shell css cleanup 2026-05-06 13:40:45 -07:00
2ba846698f docs(ui): record navigation boundary 2026-05-06 13:38:10 -07:00
2a2c773ca1 docs(ui): record app shell migration 2026-05-06 13:36:25 -07:00
4cfe5aee5e docs(ui): record review verification 2026-05-06 13:29:33 -07:00
ca0f64e416 docs(ui): record review empty states 2026-05-06 13:19:23 -07:00
192a2aafde docs(ui): record review keyboard shortcuts 2026-05-06 13:16:01 -07:00
116c0c982b docs(ui): record review component split 2026-05-06 13:14:18 -07:00
936d2899fe docs(ui): record review primitive migration 2026-05-06 11:49:06 -07:00
1784f72d70 docs(ui): record adapter defaults 2026-05-06 11:36:42 -07:00
02c691bd8e docs(ui): record token alias migration 2026-05-06 11:34:46 -07:00
e95db18f50 docs(ui): record common ui verification 2026-05-06 11:31:52 -07:00
fd90d07339 docs(ui): record primitive story coverage 2026-05-06 11:31:14 -07:00
d7516a3566 docs(ui): record data display primitive migration 2026-05-06 11:28:16 -07:00
c1c23b194e docs(ui): record control primitive migration 2026-05-06 11:26:05 -07:00
bb1e400dfc docs(ui): record surface primitive migration 2026-05-06 11:22:11 -07:00
6540f5c494 docs(ui): record primitive variant migration 2026-05-06 11:20:55 -07:00
109810572f docs(ui): record status token migration 2026-05-06 11:16:56 -07:00
4e01733f31 docs(ui): record platform core migration verification 2026-05-06 11:13:34 -07:00
5009a22675 docs(ui): add platform core migration roadmap 2026-05-06 11:06:30 -07:00
f18abbe5fc docs(roadmap): record P10.8 remote status 2026-05-05 14:21:39 -07:00
07d3257753 docs(roadmap): record P10.7 release docs 2026-05-05 14:20:42 -07:00
64d2f6f2b6 docs(release): record final handoff status 2026-05-05 14:20:15 -07:00
0563bcdc26 docs(roadmap): record P10.6 audits 2026-05-05 14:19:09 -07:00
6d8780b440 docs(roadmap): record P10.5 platform smoke 2026-05-05 14:17:08 -07:00
1797ca7e25 docs(roadmap): record P10.4 compose gate 2026-05-05 14:09:04 -07:00
21a2619c74 docs(roadmap): record P10.3 web e2e 2026-05-05 14:08:03 -07:00
81adcd7d2b docs(roadmap): record P10.2 lint gate 2026-05-05 14:05:22 -07:00
00d022071d docs(roadmap): record P10.1 verification 2026-05-05 13:56:26 -07:00
e9f045571b docs(roadmap): record P9.5 operator runbook 2026-05-05 13:54:27 -07:00
57a7e10bc9 docs(ops): add operator runbook 2026-05-05 13:53:59 -07:00
95f252a520 docs(roadmap): record P9.4 telemetry taxonomy 2026-05-05 13:51:57 -07:00
40b62bf3a6 docs(ops): define telemetry taxonomy 2026-05-05 13:51:28 -07:00
067e32a2aa docs(roadmap): record P9.3 migration plan 2026-05-05 13:49:24 -07:00
3b8fa29c2a docs(data): add migration backfill plan 2026-05-05 13:48:52 -07:00
5ce97f8615 docs(roadmap): record P9.2 seed bootstrap 2026-05-05 13:46:16 -07:00
efcc5fa044 feat(data): add seed bootstrap strategy 2026-05-05 13:45:43 -07:00
1059b138d7 docs(roadmap): record cosmos operations 2026-05-05 13:39:19 -07:00
d897702d9e docs(data): add cosmos operations runbook 2026-05-05 13:38:58 -07:00
33ea533d8b docs(roadmap): record release checklist 2026-05-05 13:37:46 -07:00
606828401e docs(release): add deploy checklist template 2026-05-05 13:37:26 -07:00
2c01ffb0eb docs(roadmap): record dependency health 2026-05-05 13:36:28 -07:00