feat: publication IA (magazine/brief/essay) + fixes critique
Some checks failed
CI / Lint, Unit Tests & Build (push) Failing after 1m22s
CI / Deploy production (on server) (push) Has been skipped

Publication IA:
- 4 templates (magazine, brief, essay, simple) avec CSS riche
- Rewrite IA (article/exercises/tutorial/reference/mixed)
- Modération avec timeout 12s + fallback safe
- Quotas publish_enhance par tier (basic=2, pro=15, business=100)
- Détection contenu stale (hash)
- Migration DB publishedContent/publishedTemplate/publishedSourceHash

Fixes:
- cheerio v1.2: Element -> AnyNode (domhandler), decodeEntities cast
- _isShared ajouté au type Note (champ virtuel serveur)
- callout colors PDF export: extraction fonction pure testable
- admin/published: guard note.userId null
- Cmd+S fonctionne en mode dialog (pas seulement fullPage)

i18n:
- 23 clés publish* traduites dans les 15 locales
- Extension Web Clipper: 13 locales mise à jour

Tests:
- callout-colors.test.ts (6 tests)
- note-visible-in-view.test.ts (5 tests)
- entitlements.test.ts + byok-entitlements.test.ts: mock usageLog + unstubAllEnvs
- 199/199 tests passent

Tracker: user-stories.md sync avec sprint-status.yaml
This commit is contained in:
Antigravity
2026-06-28 07:32:57 +00:00
parent 902fe95a69
commit 96e7902f01
169 changed files with 5382 additions and 1527 deletions

View File

@@ -0,0 +1,4 @@
-- AlterTable
ALTER TABLE "Note" ADD COLUMN "publishedContent" TEXT;
ALTER TABLE "Note" ADD COLUMN "publishedTemplate" TEXT;
ALTER TABLE "Note" ADD COLUMN "publishedSourceHash" TEXT;

View File

@@ -117,6 +117,7 @@ model Notebook {
workflows Workflow[]
flashcardDecks FlashcardDeck[]
schema NotebookSchema?
site NotebookSite?
@@index([userId, order])
@@index([userId])
@@ -124,6 +125,19 @@ model Notebook {
@@index([trashedAt])
}
model NotebookSite {
id String @id @default(cuid())
notebookId String @unique
slug String @unique
isPublic Boolean @default(true)
publishedAt DateTime @default(now())
updatedAt DateTime @updatedAt
template String @default("magazine")
selectedNoteIds String // JSON array de note IDs ordonnés
description String? // Résumé IA du carnet
notebook Notebook @relation(fields: [notebookId], references: [id], onDelete: Cascade)
}
model Label {
id String @id @default(cuid())
name String
@@ -179,6 +193,12 @@ model Note {
isPublic Boolean @default(false)
publicSlug String? @unique
publishedAt DateTime?
/// HTML rendu pour la page publique (publication IA)
publishedContent String?
/// magazine | brief | essay
publishedTemplate String?
/// Hash du contenu source au moment de la publication
publishedSourceHash String?
/// URL d'origine pour les clips web (Web Clipper)
sourceUrl String?
/// Note de démonstration insérée lors de l'onboarding