feat: dashboard Second Brain, essai 7 jours et vérification e-mail
All checks were successful
CI / Lint, Unit Tests & Build (push) Successful in 7m14s
CI / Deploy production (on server) (push) Successful in 1m25s

Rendre le dashboard actionnable (inbox, peek, carte mentale), aligner la facturation sur l’essai 7 jours, et bloquer le login e-mail tant que l’adresse n’est pas confirmée.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Antigravity
2026-08-30 07:19:36 +00:00
parent 69c99e4f4f
commit 80ccc1f6de
95 changed files with 4158 additions and 618 deletions

View File

@@ -7,7 +7,9 @@ import {
INTERACTIVE_PAGE_SCHEMA_VERSION,
PAGE_BLOCK_TYPES,
SIM_CAPS,
STEPS_CAPS,
} from './constants'
import { isValidSimParamId } from './sim-eval'
const intentSchema = z.enum(INTENT_IDS).optional()
@@ -90,6 +92,9 @@ const imageBlock = z.object({
const simParamIdSchema = z
.string()
.regex(/^[A-Za-z_][A-Za-z0-9_]*$/, 'Invalid sim identifier')
.refine(isValidSimParamId, {
message: 'Identifier collides with a reserved constant/function',
})
const genericSimParamSchema = z.object({
id: simParamIdSchema,
@@ -150,6 +155,22 @@ const simBlock = z.object({
caption: z.string().optional(),
})
const stepsBlock = z.object({
type: z.literal('steps'),
title: z.string().optional(),
steps: z
.array(
z.object({
tex: z.string().min(1),
rule: z.string().optional(),
speak: z.string().optional(),
})
)
.min(STEPS_CAPS.minSteps)
.max(STEPS_CAPS.maxSteps),
caption: z.string().optional(),
})
export const pageBlockSchema = z.discriminatedUnion('type', [
proseBlock,
formulaBlock,
@@ -160,6 +181,7 @@ export const pageBlockSchema = z.discriminatedUnion('type', [
tableBlock,
imageBlock,
simBlock,
stepsBlock,
])
const sectionSchema = z.object({
@@ -199,7 +221,7 @@ export const pageSpecV1Schema = z.object({
overview: overviewSchema.optional(),
sections: z
.array(sectionSchema)
.min(1)
.min(2)
.max(INTERACTIVE_PAGE_CAPS.maxSections),
footer: z.string().optional(),
})