Skip to content

feat(account-security): design-system-first hub UI slice (#313)#317

Merged
izzywdev merged 14 commits into
masterfrom
claude/account-security-ui
Jul 22, 2026
Merged

feat(account-security): design-system-first hub UI slice (#313)#317
izzywdev merged 14 commits into
masterfrom
claude/account-security-ui

Conversation

@izzywdev

Copy link
Copy Markdown
Owner

account-security UI slice (issue #313 — first approved design flow)

Implements the UI slice only of the account-security hub, design-system-first against the frozen packages/security/openapi.yaml contract + the approved frames in design/frames/account-security/.

SCOPE DONE (verified)

1. Design-system foundation (I am the sole owner of design-system/)

  • Added StatusCallout — soft-tinted inline banner (icon chip + title + text + actions), the DS addition named in the frame manifest. Tokens-only, RTL-safe (logical props), role defaults by tone (alert/status). design-system/components/feedback/StatusCallout.{jsx,d.ts}, regenerated index.js/index.d.ts/_ds_manifest.json.
  • Added base tokens --success-soft / --warning-soft / --error-soft (dark + light) to design-system/tokens/colors.css. No base primitive/token was forked or shadowed.

2. @fuzefront/account-security-ui package (private publishConfig → GitHub Packages @fuzefront, repository field, dual es/cjs+dts build config, wired into workspaces)

  • Orchestrator AccountSecurityHub @ /account/security + components: SecurityHub, SecurityPostureSummary, SecurityCard, SignInMethodsList, SetPasswordBanner, ConnectedAccountRow, SecurityCardGridSkeleton, LoadErrorRetry.
  • All contract states from 02-states.html: loading skeleton; load-error + retry; social-only hasPassword:false → set-password-first guard (data-guard="set-password-first"); last-sign-in-method unlink 409 guard (data-guard="last-sign-in-method"). All frame data-* test hooks present.
  • Consumes ONLY design-system tokens/components (zero raw hex/rgb/px) + the generated @fuzefront/security-client types. a11y (roles, keyboard, aria-busy), RTL via CSS logical properties + own i18n (en + he).
  • No identity-vendor names on any consumer surface (only the social provider "Google", which the approved frames show).

3. Shell wiring — route /account/security (frontend/src/pages/AccountSecurityPage.tsx), vite source-alias + tsconfig path, workspace entry. Feature flag fuzefront.account-security.hub (default OFF) gating both states. Module-Federation shared untouched (react/react-dom only, per the UI-package rule).

Verification results (run locally):

  • vitest run12/12 passing across 4 files (client contract paths + 409, StatusCallout a11y, 409 last-method guard, orchestrator loading→ready/error+retry/no-password-guard/RTL flip).
  • tsc --noEmit (with @fuzefront/* path mappings) → clean (exit 0).
  • gate_ds_conformance.py --changed-onlyno raw design values in changed lines. OK (0 hard violations).

⚠️ Backend / contract-client gap (for contract-designer / backend-engineer)

The published @fuzefront/security-client v0.2.0 is stale: openapi.yaml defines IdentityConnections + SocialConnection (GET /v1/security/identity/connections), but neither the generated generated.ts nor hand-authored types.ts exposes them. Action: regenerate + republish the client from the frozen spec. Until then those two schemas are mirrored contract-faithfully in packages/account-security-ui/src/types.ts (clearly flagged; remove on regen). I did not hand-edit the generated client.

Honest empty/unknown states rendered where no endpoint backs a field: active API-token count (activeTokens: null, "Unavailable") — the Security contract has no token-count endpoint yet; and active-device count is best-effort from GET /v1/security/sessions.

NOT verified — environment blocker

  • MANDATORY Chrome-DevTools runtime console-clean gate: NOT executed. This Windows worktree's root/frontend node_modules is unbuildable (ENOTEMPTY on npm rmdir + the intentional os=linux .npmrc), so the dev server + real-Chromium render could not be run here. Unit/DS tests were run via an isolated clean harness. The runtime gate MUST be run in CI / a Linux env (or by frontend-test-engineer) before merge.

OUT OF SCOPE — NOT DONE (sibling layers)

  • Backend: /v1/security/identity/connections + /methods implementation and the security-client regen/republish — backend-engineer / contract-designer.
  • Independent UI e2e (Playwright/browser vs the approved frames, pre/post-prod, the RED spec) — frontend-test-engineer.
  • API/contract acceptance teststest-engineer.
  • Deploy (Helm/Argo/CI) — devops-engineer.
  • Consumer docsdocs-maintainer.

This feature is NOT complete — only the UI slice is built. Feature completeness is the orchestrator's call once every sibling PR is green + merged.

🤖 Generated with Claude Code

fuzeone-bot Bot and others added 6 commits July 20, 2026 16:46
…-tint tokens

Foundation for the account-security hub: a soft-tinted inline banner
(icon chip + title + text + actions) for warn/error/info/success states,
named in design/frames/account-security/manifest.json as the required DS
addition. Tokens-only, RTL-safe (logical props), role defaults by tone.

Adds --success-soft/--warning-soft/--error-soft base tokens (dark+light).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session-Id: f636c22e-1cd7-401e-8843-97e3e3a4ba01
…pes, i18n) [skip ci]

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session-Id: f636c22e-1cd7-401e-8843-97e3e3a4ba01
…t states) [skip ci]

SecurityHub/AccountSecurityHub, posture summary, cards, sign-in methods list
with the 409 last-method guard, set-password banner, skeleton, error+retry.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session-Id: f636c22e-1cd7-401e-8843-97e3e3a4ba01
… alias, flag) [skip ci]

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session-Id: f636c22e-1cd7-401e-8843-97e3e3a4ba01
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session-Id: f636c22e-1cd7-401e-8843-97e3e3a4ba01
…SocialConnection

The published @fuzefront/security-client (v0.2.0) predates the
IdentityConnections + SocialConnection schemas in the frozen openapi.yaml, so
neither generated.ts nor types.ts exposes them. Mirror those two schemas
locally (contract-faithful) until the client is regenerated + republished;
source AuthMethods/SocialProvider/ErrorBody from the client. Fixes type-check.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session-Id: f636c22e-1cd7-401e-8843-97e3e3a4ba01
@izzywdev izzywdev added the auto-merge Enable squash auto-merge once CI passes label Jul 20, 2026
@github-actions
github-actions Bot enabled auto-merge (squash) July 20, 2026 18:40
@github-actions

Copy link
Copy Markdown
Contributor

Automated code review (gate-code-review)

Credit balance is too low

Report-only — this check never blocks merge.

Rebuilds design-system/index.{js,d.ts} and _ds_manifest.json via
build.mjs to reconcile the barrel conflicts from the concurrent
signup-UI work (FieldStatus, PasswordChecklist, StatusCallout, AppTile)
with the account-security additions, rather than manually splicing
conflict markers.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session-Id: f636c22e-1cd7-401e-8843-97e3e3a4ba01
@github-actions

Copy link
Copy Markdown
Contributor

Automated code review (gate-code-review)

Credit balance is too low

Report-only — this check never blocks merge.

@github-actions

Copy link
Copy Markdown
Contributor

Automated code review (gate-code-review)

Credit balance is too low

Report-only — this check never blocks merge.

Wires the previously-orphaned SignInMethodsList (with its fail-closed
last-sign-in-method 409 guard) into SecurityHub, adds
AccountSecurityClient.unlinkProvider (DELETE /v1/security/social/{provider}/link
per packages/security/openapi.yaml), and threads onUnlink/onLinkProvider through
AccountSecurityHub. This satisfies the frames' manifest (build.components
declares SignInMethodsList + ConnectedAccountRow on the /account/security route,
frame 02-states shows the last-method 409 guard on this same route) and the
independent RED e2e (feature/account-security-red-e2e) which exercises unlink
directly from the hub.

Also flips VITE_FF_ACCOUNT_SECURITY_HUB=true as a Dockerfile/e2e-compose build
arg (default false in prod) so the release-gated route actually renders in the
docker-compose e2e stack the RED specs run against.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session-Id: f636c22e-1cd7-401e-8843-97e3e3a4ba01
@github-actions

Copy link
Copy Markdown
Contributor

Automated code review (gate-code-review)

Credit balance is too low

Report-only — this check never blocks merge.

@github-actions

Copy link
Copy Markdown
Contributor

Automated code review (gate-code-review)

Credit balance is too low

Report-only — this check never blocks merge.

#317)

npm ci was hard-failing (EUSAGE) — the lock was missing @fuzefront/account-security-ui
(new workspace), vitest, and jsdom, reddening gate-frontend-build, Backend tests,
NPM Security Audit and OIDC plumbing (one root cause, not four). Regenerated via
npm install --package-lock-only; npm ci --dry-run now resolves cleanly.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session-Id: f636c22e-1cd7-401e-8843-97e3e3a4ba01
@github-actions

Copy link
Copy Markdown
Contributor

Automated code review (gate-code-review)

Credit balance is too low

Report-only — this check never blocks merge.

The prior regen used npm 11 (local), which drifted transitive versions vs CI's
node20/npm10 — npm ci failed with 'Missing @types/express@4.17.21'. Regenerated with
npm@10 so the lockfile matches the resolver CI uses.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session-Id: f636c22e-1cd7-401e-8843-97e3e3a4ba01
@github-actions

Copy link
Copy Markdown
Contributor

Automated code review (gate-code-review)

Credit balance is too low

Report-only — this check never blocks merge.

The rebased account-security UI carried explicit `import React` lines that are
unnecessary under the react-jsx transform and failed `tsc --noEmit` (TS6133) in
Lint & Test. Removed the standalone React imports (6 files) and dropped `React,`
from the two named-import lines; no React.* usage remains in any of them.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session-Id: f636c22e-1cd7-401e-8843-97e3e3a4ba01
@github-actions

Copy link
Copy Markdown
Contributor

Automated code review (gate-code-review)

Credit balance is too low

Report-only — this check never blocks merge.

@izzywdev
izzywdev merged commit d1703f0 into master Jul 22, 2026
50 checks passed
@izzywdev
izzywdev deleted the claude/account-security-ui branch July 22, 2026 18:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

auto-merge Enable squash auto-merge once CI passes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant