P0: Next.js shell — tokens, motion, SlidePanel, LeftRail, auth plumbing
- Tailwind v4 @theme block encoding all spec §2 tokens; full §3 keyframe inventory with prefers-reduced-motion handling; Geist vendored (air-gap) - SlidePanel width-animation primitive (component-tested: exit-transition unmount, fixed-width inner content, a11y region semantics) - session-key.ts mirroring the Rust codec + URL-param encoding; nuqs panel-params with spec ?sessions=1 flag shape and routines->scheduled alias - Zod-typed API client; httpOnly cookie session bridge (/auth/session); login page; (workspace) layout with LeftRail roster/nav/user; Team and Credits pages on real endpoints (+ GET /api/team/members in tc-api) - Vitest + Testing Library harness (26 tests); ESLint max-lines 1250 + no-warning-comments mirroring the CI gates Co-Authored-By: Claude Fable 5 <[email protected]>
This commit is contained in:
co-authored by
Claude Fable 5
parent
c4349bf292
commit
172a3c8fed
@@ -0,0 +1,47 @@
|
||||
// Zod schemas mirroring the Rust API responses (spec §13/§14). The backend
|
||||
// is a separate codebase: every response is parsed so drift fails loudly in
|
||||
// tests, not silently in the UI.
|
||||
|
||||
import { z } from "zod";
|
||||
|
||||
export const RoleSchema = z.enum(["owner", "member"]);
|
||||
export type Role = z.infer<typeof RoleSchema>;
|
||||
|
||||
export const UserSchema = z.object({
|
||||
id: z.string().uuid(),
|
||||
workspace_id: z.string().uuid(),
|
||||
email: z.string(),
|
||||
role: RoleSchema,
|
||||
display_name: z.string(),
|
||||
created_at: z.string(),
|
||||
});
|
||||
export type User = z.infer<typeof UserSchema>;
|
||||
|
||||
export const AgentStatusSchema = z.enum(["provisioning", "online", "offline"]);
|
||||
export type AgentStatus = z.infer<typeof AgentStatusSchema>;
|
||||
|
||||
export const AgentSchema = z.object({
|
||||
id: z.string().uuid(),
|
||||
workspace_id: z.string().uuid(),
|
||||
name: z.string(),
|
||||
job_title: z.string(),
|
||||
system_prompt: z.string(),
|
||||
avatar: z.string(),
|
||||
accent: z.string(),
|
||||
wallpaper: z.string(),
|
||||
managed_by: z.string().uuid(),
|
||||
status: AgentStatusSchema,
|
||||
});
|
||||
export type Agent = z.infer<typeof AgentSchema>;
|
||||
|
||||
export const PermissionsSchema = z.object({
|
||||
role: RoleSchema,
|
||||
can_manage_team: z.boolean(),
|
||||
can_manage_billing: z.boolean(),
|
||||
});
|
||||
export type Permissions = z.infer<typeof PermissionsSchema>;
|
||||
|
||||
export const CreditsSchema = z.object({
|
||||
available: z.number(),
|
||||
});
|
||||
export type Credits = z.infer<typeof CreditsSchema>;
|
||||
Reference in New Issue
Block a user