137 Commits

Author SHA1 Message Date
fc62834019 fix(web-auth): soften forgot-password hint to 'contact IT' 2026-05-03 09:48:05 +08:00
f4d5f97c42 fix(web-auth): import WebAuthn JSON types from @simplewebauthn/types
In @simplewebauthn/server v11 the JSON response and transport types are
no longer re-exported from the server package — they live in the sibling
@simplewebauthn/types package. Adds the dep and switches the imports.
2026-05-03 09:45:36 +08:00
312cc4dc21 fix(web-auth): gate Secure cookie on CM_DEBUG, pass CM_AGENT creds to web-next
Previously the session cookie used Secure=NODE_ENV==='production', and the
dev override still runs the standalone build with NODE_ENV=production, so
the cookie was unreachable from phone-on-LAN testing over HTTP. Switching
to CM_DEBUG lets dev (CM_DEBUG=true) drop the Secure flag while keeping
prod (CM_DEBUG=false) safe.

Also wires CM_AGENT_ID/CM_AGENT_PASSWORD/CM_DEBUG into the web-next
service env block so the login Server Action can compare against them.
2026-05-03 09:01:35 +08:00
a8ee6f068d docs(agents): document the auth model and passkey storage 2026-05-03 08:31:23 +08:00
b4c526bf9f feat(web): nav account menu with sign out + passkey settings link 2026-05-03 08:31:00 +08:00
6ee95bca08 feat(web): /cm-passkeys settings page for passkey enroll/remove 2026-05-03 08:30:25 +08:00
9e74d75c94 feat(web): /cm-auth login page with passkey + password options 2026-05-03 08:29:25 +08:00
0d0dfd593c feat(web): middleware redirects unauthenticated requests to /cm-auth 2026-05-03 08:28:16 +08:00
7dd8bfcefa feat(web): Server Actions for password login + WebAuthn passkey flows 2026-05-03 08:28:04 +08:00
380e86b885 feat(web): WebAuthn relying-party helper (host-derived rpID/origin) 2026-05-03 08:27:32 +08:00
7a6569800e feat(web): JSON-file passkey store with atomic writes + write lock 2026-05-03 08:27:21 +08:00
a8751b6731 feat(web): add iron-session wrapper (web/lib/auth.ts) 2026-05-03 08:27:05 +08:00
f2facb200f feat(compose): mount web-next-auth-data volume + pass CM_AUTH_SECRET 2026-05-03 08:26:49 +08:00
54c47cf7d2 feat(envs): add CM_AUTH_SECRET to all .env.example templates 2026-05-03 08:26:11 +08:00
e5a2a36fb2 build(web): add iron-session and simplewebauthn deps 2026-05-03 08:25:32 +08:00
9af4d17aab Add implementation plan for B-auth (login + WebAuthn passkeys) 2026-05-03 08:21:47 +08:00
9771bb72c5 fix(web): move mobile status back into card header next to username
Earlier change made the badge the editable trigger and demoted it
into the body's Status row. That separated status from the row
identifier on mobile, which read as 'where is this status from?'.

Move the EditableCell-with-StatusBadge back into the card header,
right after the username, and drop the body Status row entirely.
Mobile now matches desktop's information density: identifier +
status badge inline, edit via badge click.
2026-05-03 08:17:23 +08:00
43533c3485 fix(spec): rename auth routes to /cm-auth and /cm-passkeys
Avoids the well-known /login path that scanners hit by default.
The cm- prefix matches the rest of the project's namespacing
(cm-web-next, cm-api, etc.) and isn't on standard scanner wordlists.

Settings page moves to flat /cm-passkeys (was /settings/passkeys)
to drop the simple 'settings' word — same scanner-noise reasoning.

File paths follow: web/app/cm-auth/, web/app/cm-passkeys/.
2026-05-03 08:16:36 +08:00
fe26878b38 fix(web): drop duplicate status — badge IS the editable trigger
The status column was rendering both a StatusBadge and a separate
EditableCell next to it, so 'done' showed twice in the same cell.
Adds a renderView prop to EditableCell so callers can override the
view-mode display; status now uses the badge as its visual, click-
to-edit behavior intact. Mobile card header drops its standalone
badge for the same reason — the body's Status row now shows the
badge inline.
2026-05-03 08:13:51 +08:00
6c984b6200 fix(web): lock body scroll while modal is open
Native <dialog> in iOS Safari (and a few other browsers) doesn't
prevent the page underneath from scrolling when the user scrolls
inside the dialog or near its edges. Save and restore body overflow
on open/close so the background stays put. Stays correct for stacked
dialogs because we save the previous value rather than blanket-reset
to ''.
2026-05-03 08:12:35 +08:00
48dacdb445 Add design spec for B-auth (login + WebAuthn passkeys) 2026-05-02 21:31:45 +08:00
43db97aeaa fix(api): drop flask_cors from cm_api (CORS-A defense-in-depth)
api-server is internal-only after C5 (no host port in prod compose),
so the permissive 'CORS(app)' default never fires in normal operation.
Removing it eliminates a stale '*' Access-Control-Allow-Origin that
would become attack surface if a host port were ever accidentally
re-exposed.

Server-side fetches from web-view (legacy Flask) and web-next
(Next.js RSC) don't trigger CORS — that's a browser-only mechanism.

flask_cors stays in requirements.txt because cm_web_view.py still
imports it; both get removed in B4 when the legacy web-view retires.
2026-05-02 21:27:06 +08:00
3bfd35ef8d fix(web): PWA notch safe-area + skip autoFocus on touch devices
Adds viewportFit: 'cover' so the PWA can draw under the notch /
Dynamic Island when installed. Nav and Toast read env(safe-area-inset-*)
to keep their content out of the hardware cutouts (no-op on browsers
without a notch — env() resolves to 0).

Replaces autoFocus on the first field of CreateAccountDialog and
CreateUserDialog with a useEffect that only focuses on pointer devices
(matchMedia '(hover: hover) and (pointer: fine)'). Phones no longer
get the soft keyboard popping the instant a dialog opens.
2026-05-02 21:26:42 +08:00
eebbcb3db2 feat(web): success toast on confirmed create/delete
Adds a small top-centered <Toast> that fires only when the Server
Action returns { ok: true } (i.e., the DB write actually succeeded).
Auto-dismisses after 3s.

Wires both create dialogs (CreateAccountDialog, CreateUserDialog) with
an onSuccess callback that the table parent uses to push the toast,
and the delete confirm-flow does the same. Inline-edit success stays
quiet (no toast) — only add/delete trigger it, per the requested
scope.
2026-05-02 21:20:25 +08:00
e3ac94cada feat(web): manual create flow with input dialog for acc and user
api-server gets /create-acc-data and /create-user-data POST routes
that INSERT into the respective tables with required-field validation.
Frontend adds an 'Add' button next to Refresh in each table head;
opens a native <dialog> form with all fields. Inputs use 16px font on
phone (sm:text-[13px] desktop) so iOS doesn't auto-zoom.

A small form-dialog-shell helper centralizes the modal chrome,
field label, and input class so create-account-dialog and
create-user-dialog stay focused on their fields and validation.
2026-05-02 21:19:24 +08:00
e507714dc5 feat(web): delete with confirm dialog + fix iOS auto-zoom on edit
Adds × delete button per row in both tables (desktop column +
mobile card header). Click → native <dialog> confirm modal with
Esc/backdrop-cancel, destructive red button, error inline.
Wires deleteAccount/deleteUser Server Actions calling the new
api-server routes; revalidatePath refreshes the list on success.

EditableCell input switches to text-base (16px) on phone (sm:text-[13px]
above 640px), preventing iOS Safari auto-zoom-on-focus that was
shifting the layout when the soft keyboard appeared.
2026-05-02 21:17:19 +08:00
dac1e10b5d feat(api): add /delete-acc-data and /delete-user-data routes 2026-05-02 21:15:21 +08:00
f13e3993e9 feat(web): reskin to refined SaaS aesthetic (per Dribbble reference)
Drop the brutalist hazard-tape vocabulary in favor of refined modern
SaaS: white cards on zinc-50, soft ring-1 zinc-200 borders (no hard
2px black), rounded-full pills, sans for chrome + mono for tabular
data, emerald replacing yellow as the saturated accent. Theme color
shifts to zinc-900 with an emerald dot on the icon.
2026-05-02 21:15:02 +08:00
3fe33772ce fix(web): editable cell wraps long values instead of overflowing
Long URLs in the link column would overflow on mobile because
truncate + inline-flex without min-w-0 expanded the cell beyond the
card width. Switch to flex+items-start, min-w-0 on the value span,
break-all so unbreakable strings wrap. Edit hint stays pinned right
with shrink-0.
2026-05-02 21:08:19 +08:00
b497e133bd feat(web): add PWA icons via Next.js ImageResponse (frontend-design) 2026-05-02 21:02:58 +08:00
afc94e613e feat(web): add PWA manifest config (theme_color matches layout viewport) 2026-05-02 21:01:18 +08:00
7a5c00d08a feat(web): add layout, nav, and error boundary (frontend-design) 2026-05-02 21:01:15 +08:00
c0749d1af0 feat(web): add Server Component entry pages for / and /users 2026-05-02 20:56:56 +08:00
7b97e593e5 feat(web): add data tables and editable-cell primitive (frontend-design) 2026-05-02 20:56:49 +08:00
0ebd35f964 feat(web): add 30s auto-refresh client component 2026-05-02 20:50:55 +08:00
b398faba0a feat(web): add updateAccount and updateUser Server Actions 2026-05-02 20:50:50 +08:00
3297c500a4 feat(web): add server-side api-server fetch helper 2026-05-02 20:50:45 +08:00
aa76131b23 feat(web): add TypeScript types for Acc and User 2026-05-02 20:50:38 +08:00
a9642a7121 Add implementation plan for B2+B3 (UI port + PWA) 2026-05-02 20:49:13 +08:00
2de545e854 Add design spec for B2+B3 (UI port + PWA) 2026-05-02 20:45:52 +08:00
21bb1f0dde fix(web): bump tailwind to ^4.1 (4.0.0 had a postcss/oxide serde mismatch) 2026-05-02 20:39:04 +08:00
ccb6c27c3d fix(web): pin typescript to 5.7.2 (5.7.0 was never published) 2026-05-02 20:37:33 +08:00
5cac356007 docs(spec): hide /api entirely — drop Route Handler section, document RSC+Server-Actions choice 2026-05-02 20:36:11 +08:00
ff99b1248a feat(web): hide /api entirely — RSC + Server Actions instead
The Route Handler proxy and hash mapping are gone. Browser never
hits a JSON endpoint: data reads happen in React Server Components
fetching api-server:3000 server-side; mutations (B2) will use
Next.js Server Actions. Zero public API surface to scrape or
enumerate.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 20:34:31 +08:00
a04d7ecc50 docs(agents): document web/ Next.js project and cm-web-next dev URL 2026-05-02 20:33:00 +08:00
203ab5daef feat(scripts): include web-next in dev.sh and publish.sh 2026-05-02 20:32:47 +08:00
e78d8c8fa8 feat(envs): add CM_WEB_NEXT_HOST_PORT to all .env.example templates 2026-05-02 20:32:24 +08:00
17b38a7c35 feat(compose): add web-next service (side-by-side with web-view) 2026-05-02 20:32:20 +08:00
96fa650caf feat(docker): add multi-stage Dockerfile for cm-web-next 2026-05-02 20:31:53 +08:00
addc40e851 feat(web): hash-encoded API paths + catch-all Route Handler proxy 2026-05-02 20:31:38 +08:00