mirror of
https://github.com/siop-spelev/siop2.git
synced 2026-08-08 12:41:54 +00:00
feat(r0.10): apps/api — auth fermée par défaut, matrice en base, démo-login ADR-002, seed
- packages/shared : rôles/catégories, schémas Zod, contrat d'API ; pnpm contract → docs/openapi.json committée (règle d'or ADR-001) - apps/api : NestJS 11 + Prisma 6, migration r0_identity (Role/Permission/User) ; guard JWT global + @Public() ; PermissionsGuard (@RequirePermission, matrice relue en base, cache 60 s) ; FileStorage (seul import MinIO) ; /health - démo-login ADR-002 : module conditionnel DEMO_MODE (404 sinon, testé e2e), double verrou production, refus des comptes isDemo=false - seed idempotent : 7 rôles, matrice complète (70 lignes), 7 comptes démo - 19 tests Jest (unit + e2e) ; smoke test sur build de prod Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
42
packages/shared/src/schemas/auth.ts
Normal file
42
packages/shared/src/schemas/auth.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
import { z } from 'zod';
|
||||
import { ROLE_NAMES } from '../permissions';
|
||||
|
||||
export const AuthUserSchema = z.object({
|
||||
id: z.uuid(),
|
||||
email: z.email(),
|
||||
displayName: z.string(),
|
||||
role: z.object({ id: z.uuid(), name: z.enum(ROLE_NAMES) }),
|
||||
isDemo: z.boolean(),
|
||||
});
|
||||
export type AuthUser = z.infer<typeof AuthUserSchema>;
|
||||
|
||||
export const LoginRequestSchema = z.object({
|
||||
email: z.email(),
|
||||
password: z.string().min(1),
|
||||
});
|
||||
export type LoginRequest = z.infer<typeof LoginRequestSchema>;
|
||||
|
||||
export const AuthResponseSchema = z.object({
|
||||
accessToken: z.string(),
|
||||
user: AuthUserSchema,
|
||||
});
|
||||
export type AuthResponse = z.infer<typeof AuthResponseSchema>;
|
||||
|
||||
/** ADR-002 — jamais de secret dans cette liste. */
|
||||
export const DemoAccountSchema = z.object({
|
||||
id: z.uuid(),
|
||||
displayName: z.string(),
|
||||
roleName: z.enum(ROLE_NAMES),
|
||||
initials: z.string().min(1).max(3),
|
||||
});
|
||||
export type DemoAccount = z.infer<typeof DemoAccountSchema>;
|
||||
|
||||
export const DemoAccountsResponseSchema = z.object({
|
||||
accounts: z.array(DemoAccountSchema),
|
||||
});
|
||||
export type DemoAccountsResponse = z.infer<typeof DemoAccountsResponseSchema>;
|
||||
|
||||
export const DemoLoginRequestSchema = z.object({
|
||||
userId: z.uuid(),
|
||||
});
|
||||
export type DemoLoginRequest = z.infer<typeof DemoLoginRequestSchema>;
|
||||
13
packages/shared/src/schemas/health.ts
Normal file
13
packages/shared/src/schemas/health.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
const ServiceStateSchema = z.enum(['up', 'down']);
|
||||
|
||||
export const HealthResponseSchema = z.object({
|
||||
status: z.enum(['ok', 'degraded']),
|
||||
services: z.object({
|
||||
database: ServiceStateSchema,
|
||||
redis: ServiceStateSchema,
|
||||
storage: ServiceStateSchema,
|
||||
}),
|
||||
});
|
||||
export type HealthResponse = z.infer<typeof HealthResponseSchema>;
|
||||
11
packages/shared/src/schemas/users.ts
Normal file
11
packages/shared/src/schemas/users.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { z } from 'zod';
|
||||
import { AuthUserSchema } from './auth';
|
||||
import { PermissionEntrySchema } from '../permissions';
|
||||
|
||||
/** Profil courant : identité + matrice du rôle (le JWT, lui, ne porte jamais
|
||||
* de droits — le web lit cette réponse pour adapter l'UI, l'API re-vérifie
|
||||
* chaque requête via PermissionsGuard). */
|
||||
export const MeResponseSchema = AuthUserSchema.extend({
|
||||
permissions: z.array(PermissionEntrySchema),
|
||||
});
|
||||
export type MeResponse = z.infer<typeof MeResponseSchema>;
|
||||
Reference in New Issue
Block a user