Canvas (archive de conception)Modèle de données Prisma

Modèle de données Prisma

Archive de conception. Cette page raconte ce qui etait vise le jour ou elle a ete ecrite, pas l'etat du code aujourd'hui. Ce qui a ete livre depuis est recense dans le README.

Archive de conception. Cette page raconte ce qui etait vise le jour ou elle a ete ecrite, pas l'etat du code aujourd'hui. Ce qui a ete livre depuis est recense dans le README.

← retour au README


5. Modèle de données Prisma

Schémas à créer

model Task {
  id              String      @id @default(cuid())
  storeId         String
  conversationId  String?
  title           String
  description     String?
  status          TaskStatus
  priority        Int         @default(0)
  assigneeAgent   String?
  parentTaskId    String?
  dependsOnTaskIds String[]
  plan            Json?
  output          Json?
  agentRunId      String?
  createdBy       String
  createdAt       DateTime    @default(now())
  updatedAt       DateTime    @updatedAt
  completedAt     DateTime?
  store           Store       @relation(fields: [storeId], references: [id])
  activities      TaskActivity[]

  @@index([storeId, status])
  @@index([conversationId])
}

enum TaskStatus {
  PENDING IN_PROGRESS WAITING_REVIEW DONE FAILED CANCELLED
}

model TaskActivity {
  id        String   @id @default(cuid())
  taskId    String
  type      String
  payload   Json
  ts        DateTime @default(now())
  task      Task     @relation(fields: [taskId], references: [id])

  @@index([taskId, ts])
}

model ThemeBranch {
  id              String   @id @default(cuid())
  storeId         String
  shopifyThemeId  String   // draft theme ID on Shopify
  name            String
  conversationId  String?  // chat-as-branch link
  parentBranchId  String?
  status          String   // "active" | "archived" | "published"
  createdBy       String
  createdAt       DateTime @default(now())
  store           Store    @relation(fields: [storeId], references: [id])
  versions        ThemeVersion[]

  @@index([storeId, status])
}

model ThemeVersion {
  id              String   @id @default(cuid())
  branchId        String
  parentVersionId String?
  message         String   // "iRen edit: hero copy"
  authorAgent     String?
  authorUserId    String?
  filesDiff       Json?    // jsonpatch (V2)
  filesSnapshot   Json?    // full snapshot (V1, then compacted)
  publishedAt     DateTime?
  createdAt       DateTime @default(now())
  branch          ThemeBranch @relation(fields: [branchId], references: [id])

  @@index([branchId, createdAt])
}

model StoreReport {
  id          String   @id @default(cuid())
  storeId     String
  type        String   // "SEO" | "CRO" | "PERF" | "TRACKING" | "COMPETITOR" | "SECURITY"
  status      String   // "pending" | "running" | "done" | "failed"
  result      Json?
  triggeredBy String   // userId or "scheduled"
  createdAt   DateTime @default(now())
  completedAt DateTime?
  store       Store    @relation(fields: [storeId], references: [id])

  @@index([storeId, type, createdAt])
}

model StoreNote {
  id           String   @id @default(cuid())
  storeId      String
  content      String   @db.Text
  pinnedToTask String?  // optional Task ID
  createdBy    String
  createdAt    DateTime @default(now())
  updatedAt    DateTime @updatedAt
  store        Store    @relation(fields: [storeId], references: [id])

  @@index([storeId])
}

Migrations à prévoir

  1. Ajouter Task, TaskActivity, ThemeBranch, ThemeVersion, StoreReport, StoreNote
  2. Relations : Store ← Task[], ThemeBranch[], StoreReport[], StoreNote[]
  3. Index (storeId, status), (branchId, createdAt), (storeId, type, createdAt)

16. Vérification croisée du schéma Prisma actuel

Audit du schéma existant avant d'ajouter les nouveaux modèles V2. Évite les collisions de noms et repère où une migration incrémentale vaut mieux qu'un doublon.

Modèles existants pertinents (35 au total)

ExistantRôleImpact V2
StoreConteneur principal d'une boutique Shopify (orgId, slug, framework)✅ Réutilisé : cible des relations de tous les nouveaux modèles
StoreContext (un-à-un avec Store)knowledge, todos, pipeline, agentState (Json)🔄 Cible de migration : todos Json → Task[] relationnel ; knowledge Json → StoreNote[]
Workflow + WorkflowRunWorkflow legacy (canvas)🔍 À auditer : peut être réutilisé comme exécuteur des tâches, ou archivé, selon son état
Conversation + MessageChat @Atlas (multi-canal)✅ Réutilisé : ThemeBranch.conversationId référence Conversation.id
RoadmapItem + ChangelogEntry + FeedbackPlateforme publique (distinct du Kernel au niveau boutique)⚠️ Pas de collision : StoreReport et le Kernel par boutique sont distincts
AuditLogJournal de sécurité de la plateforme✅ Réutilisé pour tracer la création d'une Task, la publication d'une ThemeBranch, etc.
Connector + IntegrationConnection + McpConnectorIntégrations OAuth + MCP✅ Réutilisés : pas de duplication
SkillCatalogue de skills🔍 Mémoire de skills partagée entre boutiques, à imaginer

Conflits / collisions à éviter

  • Workflow : ne pas créer un nouveau modèle du même nom. Soit on le réutilise (le canvas legacy, reconverti en exécuteur des tâches), soit on l'archive et on crée AgentRun pour la nouvelle infra.
  • Workflow.WorkflowRun : déjà la persistance de runs. À voir s'il est compatible avec les flux durables de Workflow DevKit, ou à supprimer.
  • Aucun modèle « Theme »* existant → les noms ThemeBranch et ThemeVersion n'entrent pas en collision.
  • Aucun modèle « Task » existant → nom disponible. ⚠️ Il existe toutefois un MonthlyReset.task: String? (champ texte) : sémantique différente, pas de collision Prisma.

Migration incrémentale recommandée

V1.0 — Tasks queue
  StoreContext.todos (Json[]) → Task[] relationnel via migration
  Migration script : pour chaque StoreContext, parse todos JSON →
  insert Task rows avec storeId
  Garder StoreContext.todos backward-compat 90 jours puis drop

V1.1 — Theme branches
  Nouveau ThemeBranch + ThemeVersion (zero collision)

V1.2 — Notes
  StoreContext.knowledge (Json) → StoreNote[] relationnel
  Pareil que todos : migration script + 90 jours backward-compat

V1.3 — Reports
  Nouveau StoreReport (zero collision)

V1.4 — Workflow legacy
  Audit Workflow + WorkflowRun
  Décision : repurpose (renommer en AgentRun) ou archive

Champs Json → tables relationnelles : pourquoi

  • Json = facile à faire évoluer, mais ni indexable, ni filtrable, ni typé
  • Volumes attendus : ~50 tâches par boutique × 1000 boutiques = 50K lignes, OK
  • Notes, idem : ~10 notes par boutique × 1000 = 10K lignes
  • Rapports : ~5 par boutique et par mois × 1000 = 60K par an
  • Tous OK pour Postgres avec les bons index (storeId, createdAt)

Action V2 — script de migration

Créer prisma/migrations/_workspace-v2-todos-to-tasks.sql qui :

  1. Lit chaque StoreContext.todos JSON
  2. En analyse la forme (à retrouver par rétro-ingénierie du code legacy)
  3. Insère les lignes Task correspondantes
  4. Marque StoreContext.todosMigratedAt (timestamp)
  5. Le code legacy lit Task[] si todosMigratedAt est renseigné, sinon se replie sur todos (Json)

Suivant : tools-shopify.md