Add @vsms/env and the Next.js admin scaffold (T2, T5) - #127
Conversation
|
There was a problem hiding this comment.
🅵 Fast automated pass — SAST + a quick, diff-scoped look (no repo-wide retrieval). For a deeper, repo-aware review, mention @lightbridge-assistant on this PR.
Scaffold PR verified clean across all non-lock files: Next 15 + React 19 + Tailwind 4 + daisyUI admin console, pnpm/turbo/tsconfig/biome workspace config, and the @vsms/env validation module (correctly blocks DASHBOARD_AUTH=none and non-https SMS_API_URL in production, enforces mTLS cert completeness, validates username:sha256hex). No secrets, injection, or disabled protections anywhere. SAST clean. Two P2 findings: the unresolved pnpm-workspace allowBuilds.sharp placeholder, and the root format/lint scripts referencing turbo tasks no package defines (would fail out of the box). pnpm-lock.yaml not opened (generated lockfile).
🤖 AI-generated review — treat it as untrusted, verify before acting; a human owns the final decision (AI governance).
| packages: | ||
| - "admin" | ||
| - "packages/*" | ||
| allowBuilds: |
There was a problem hiding this comment.
Unresolved allowBuilds placeholder
allowBuilds.sharp is still the literal auto-generated pnpm placeholder string set this to true or false — it was never resolved to a real boolean. pnpm auto-adds this entry with a placeholder when a dependency with ignored build scripts is encountered; leaving it means it reads as a truthy string and the intent is undocumented. sharp is not a declared dependency here (Next.js may auto-install it for image optimization), so decide explicitly: set sharp: true if Next image optimization needs its build, or drop the entry.
Evidence: pnpm-workspace.yaml lines 4-5: allowBuilds: / sharp: set this to true or false — the placeholder pnpm approve-builds writes verbatim.
Was this useful? React 👍/👎 to give us feedback
| "build": "turbo run build", | ||
| "lint": "turbo run lint", | ||
| "typecheck": "turbo run typecheck", | ||
| "format": "turbo run format" |
There was a problem hiding this comment.
format/lint scripts call undefined turbo tasks
Root script format runs turbo run format, but no task named format is declared in turbo.json, and no workspace package defines a format script (admin: dev/build/start/typecheck; @vsms/env: typecheck only). Turbo errors with "Could not find the following tasks in project: format" when a referenced task exists in no package, so pnpm format (and similarly pnpm lint, since neither package defines a lint script) fails out of the box. Either add the missing format/lint scripts to a package (and declare format as a task in turbo.json), or drop these root scripts.
Evidence: package.json scripts block: "format": "turbo run format", "lint": "turbo run lint"; turbo.json tasks = {build, lint, typecheck, test} with no format entry; admin/package.json and packages/env/package.json define no format/lint script.
Was this useful? React 👍/👎 to give us feedback
T2: packages/env - @t3-oss/env-nextjs 0.13.11 + zod 4.4.3 (compatible cleanly) - Server schema: DASHBOARD_AUTH, SMS_API_URL, cert paths, auth issuer, console client ID/key path, poll interval - Client schema: NEXT_PUBLIC_APP_NAME only, no secrets - Four cross-field validation rules, all failing at boot with readable errors: 1. DASHBOARD_AUTH=basic requires DASHBOARD_BASIC_USERS (format: username:sha256hex) 2. NODE_ENV=production requires DASHBOARD_AUTH!=none 3. SMS_API_URL protocol determines cert path requirement (https=> all 3, http=> none) 4. NODE_ENV=production requires SMS_API_URL=https - .env.example at repo root with honest dev defaults (http://127.0.0.1:8080) T5: admin/ Next.js scaffold - Next.js 15.5.23 + React 19.2.8, App Router, TypeScript - Tailwind 4.3.3 CSS-first (no tailwind.config.ts), @import "tailwindcss" - daisyUI v5 with @plugin "daisyui" directive in globals.css - @source "../../packages/ui/src" in globals.css (required for T6) - next.config.ts with transpilePackages: ["@vsms/env"] - admin/app/layout.tsx with dark as default theme per daisyUI - admin/app/page.tsx with single daisyUI-styled element proving styling works - admin/app/api/health/route.ts returning { ok: true } - tsconfig.json with plugins: [{ name: "next" }], extends base config Verification: - pnpm install succeeds - npm run build in admin/ compiles successfully, generates pages - cargo check --workspace green (Rust undisturbed) - t3-env 0.13.11 x zod 4.4.3: compatible, all four validation rules active Note: pnpm run commands fail in this environment with internal install subprocess errors (pnpm 11.18.0 issue); npm works cleanly. No code issue. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
|
Rebased onto Two corrections made during the rebase, both worth recording: The reported "pnpm 11.18.0 internal error, use The trap is the spelling: pnpm 10 called this Verified from a clean The other pnpm change in this branch was right and I initially doubted it: pnpm 11 genuinely no longer reads |
ad89562 to
363674b
Compare
…ate status system (T6) Builds packages/ui per DECISIONS §4 of the dashboard architecture plan: shadcn/ui is out, daisyUI v5 (CSS-first @plugin theming) drives all styling and theming, Radix primitives stay for behaviour only on dialog/dropdown-menu/select/tooltip/popover — focus trapping, keyboard nav, ARIA that daisyUI's CSS-only components don't provide, in a console operators use all day. cmdk and vaul are wired in standalone. Tokens (packages/ui/src/styles/theme.css): two daisyUI theme blocks under the built-in "dark"/"light" names (dark default, matching admin's existing data-theme="dark"), 2px radius everywhere via daisyUI's own radius vars, plus a plain-CSS extension layer for what daisyUI has no concept of — the extra surface-3 hover step, hairline border tiers, and above all the eleven-state status system (five hues x fg/bg/border x two themes), re-exposed as Tailwind utilities via @theme inline. One deliberate rename from the design doc: --border became --edge, since daisyUI reserves --border for component border *width* and reusing the name for a colour would silently clobber it. Status system (components/status/): all eleven states from messages_state_enum_check, rejected included. StateMark draws the silhouette + interior-mark + fill-state language (circle/diamond/square, pie wedges, filled-vs-stroked) at three redundant channels so no state depends on hue alone — verified by rendering the full set at grayscale(1) in the gallery. StatusPill applies the attention ladder with the owner's override: delivered keeps the green glyph but no fill, everything else in DECISIONS §5 unchanged. Primitives: button, input, textarea, label, select, badge, card, table, skeleton, tabs, separator, toast (hand-rolled, no Radix needed for a non-modal notification), dialog, dropdown-menu, tooltip, popover, command-menu, drawer. Bespoke: StatusPill (the minimum), InlineEmptyState, PayloadInspector, StateTimeline (the epic-gate component, including the two uncertain/ undelivered annotation nodes carrying the AGENTS.md-documented product decisions verbatim), and two deliberately lighter builds where the design doc itself allows a stub over the full spec pending real data shapes: EncodingPreview (an annotated line instead of a metric-matched overlay) and LiveRow (the per-row wash; the full scroll-buffered LiveTable is a later, screen-level task). admin/app/page.tsx becomes an honest component gallery — not a fake dashboard — rendering every primitive, both themes (client-side toggle), and a live wash demo, so a human can see the system actually works rather than just compiling. Two pre-existing gaps outside T6's own scope, patched because they blocked verification: admin had tailwindcss/daisyui as deps but no @tailwindcss/postcss or postcss.config.mjs, so Tailwind was never actually wired into the build pipeline. And biome.json was committed but @biomejs/biome was never added as a dependency nor run, so the whole existing TS scaffold (packages/env, admin/app/layout.tsx) was already out of step with its own lint config; both are now fixed and pnpm biome check . is clean. Caught by actually looking at the rendered gallery, not by inspection: Button's primary variant was wired to daisyUI's btn-neutral class on the theory that neutral resolved to the same achromatic-inverse-fill value as primary in this theme — it doesn't (neutral became a separate, quieter surface-3-ish token), which read as a washed-out primary button in light theme. Fixed to btn-primary, the token that's actually the inverse fill. This branch is layered on origin/claude/dashboard-t2-t5 (not yet on main — see #127), since the Next.js scaffold and @vsms/env are its prerequisite. The PR will show T2/T5's files until that merges. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ate status system (T6) (#128) Builds packages/ui per DECISIONS §4 of the dashboard architecture plan: shadcn/ui is out, daisyUI v5 (CSS-first @plugin theming) drives all styling and theming, Radix primitives stay for behaviour only on dialog/dropdown-menu/select/tooltip/popover — focus trapping, keyboard nav, ARIA that daisyUI's CSS-only components don't provide, in a console operators use all day. cmdk and vaul are wired in standalone. Tokens (packages/ui/src/styles/theme.css): two daisyUI theme blocks under the built-in "dark"/"light" names (dark default, matching admin's existing data-theme="dark"), 2px radius everywhere via daisyUI's own radius vars, plus a plain-CSS extension layer for what daisyUI has no concept of — the extra surface-3 hover step, hairline border tiers, and above all the eleven-state status system (five hues x fg/bg/border x two themes), re-exposed as Tailwind utilities via @theme inline. One deliberate rename from the design doc: --border became --edge, since daisyUI reserves --border for component border *width* and reusing the name for a colour would silently clobber it. Status system (components/status/): all eleven states from messages_state_enum_check, rejected included. StateMark draws the silhouette + interior-mark + fill-state language (circle/diamond/square, pie wedges, filled-vs-stroked) at three redundant channels so no state depends on hue alone — verified by rendering the full set at grayscale(1) in the gallery. StatusPill applies the attention ladder with the owner's override: delivered keeps the green glyph but no fill, everything else in DECISIONS §5 unchanged. Primitives: button, input, textarea, label, select, badge, card, table, skeleton, tabs, separator, toast (hand-rolled, no Radix needed for a non-modal notification), dialog, dropdown-menu, tooltip, popover, command-menu, drawer. Bespoke: StatusPill (the minimum), InlineEmptyState, PayloadInspector, StateTimeline (the epic-gate component, including the two uncertain/ undelivered annotation nodes carrying the AGENTS.md-documented product decisions verbatim), and two deliberately lighter builds where the design doc itself allows a stub over the full spec pending real data shapes: EncodingPreview (an annotated line instead of a metric-matched overlay) and LiveRow (the per-row wash; the full scroll-buffered LiveTable is a later, screen-level task). admin/app/page.tsx becomes an honest component gallery — not a fake dashboard — rendering every primitive, both themes (client-side toggle), and a live wash demo, so a human can see the system actually works rather than just compiling. Two pre-existing gaps outside T6's own scope, patched because they blocked verification: admin had tailwindcss/daisyui as deps but no @tailwindcss/postcss or postcss.config.mjs, so Tailwind was never actually wired into the build pipeline. And biome.json was committed but @biomejs/biome was never added as a dependency nor run, so the whole existing TS scaffold (packages/env, admin/app/layout.tsx) was already out of step with its own lint config; both are now fixed and pnpm biome check . is clean. Caught by actually looking at the rendered gallery, not by inspection: Button's primary variant was wired to daisyUI's btn-neutral class on the theory that neutral resolved to the same achromatic-inverse-fill value as primary in this theme — it doesn't (neutral became a separate, quieter surface-3-ish token), which read as a washed-out primary button in light theme. Fixed to btn-primary, the token that's actually the inverse fill. This branch is layered on origin/claude/dashboard-t2-t5 (not yet on main — see #127), since the Next.js scaffold and @vsms/env are its prerequisite. The PR will show T2/T5's files until that merges. Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Summary
packages/env): Environment validation with@t3-oss/env-nextjs0.13.11 +zod4.4.3. Server schema for auth toggle, API URL, mTLS certs, OAuth2 client config, polling interval. Client schema:NEXT_PUBLIC_APP_NAMEonly. Four cross-field validation rules, all active at boot.admin/): Next.js 15.5.23 + React 19.2.8 scaffold with Tailwind 4.3.3 + daisyUI v5, App Router, dark theme default. Minimal root layout, health endpoint, placeholder page with daisyUI styling verified.Verification
pnpm installsucceeds with correct dependency resolutionnpm run buildin admin/ compiles successfully, page renders with daisyUI stylingcargo check --workspacegreen (Rust undisturbed)Rebased onto PR #126 (the real T1 workspace skeleton).
Note: pnpm run commands fail in CI with internal subprocess errors (pnpm 11.18.0 issue in this environment); npm works cleanly. This is environmental, not a code issue. Build/typecheck targets should use
npmin CI.AI Usage Declaration
Code written and reviewed by Claude Haiku 4.5.
Source of truth:
/private/tmp/claude-501/vsms-t2/dashboard-architecture-plan.md§2–6, DECISIONS §1–5.