@utopia-studio-design/design-system-cli 0.6.2 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (123) hide show
  1. package/README.md +28 -14
  2. package/bin/utopia-ds-mcp.mjs +6 -2
  3. package/bin/utopia-ds.mjs +94 -21
  4. package/data/docs/arabic-friendly.md +19 -2
  5. package/data/docs/billing-setup.md +80 -0
  6. package/data/docs/cer-003-032-033-round-8-repair.md +41 -0
  7. package/data/docs/cer-007-checkout.md +51 -0
  8. package/data/docs/cer-008-011-qa-repair.md +64 -0
  9. package/data/docs/cer-016-023-round-6-repair.md +92 -0
  10. package/data/docs/cer-024-031-round-7-repair.md +51 -0
  11. package/data/docs/cer-033-035-036-round-12-repair.md +37 -0
  12. package/data/docs/cer-035-037-round-10-repair.md +34 -0
  13. package/data/docs/charts.md +34 -3
  14. package/data/docs/chat-service-methodology.md +181 -0
  15. package/data/docs/code-block.md +20 -0
  16. package/data/docs/creative-production.md +149 -0
  17. package/data/docs/designer-agent-backend-contract.md +552 -0
  18. package/data/docs/email-resend.md +29 -0
  19. package/data/docs/foundations.md +46 -8
  20. package/data/docs/guide.md +9 -9
  21. package/data/docs/handover-billing-aiden.md +132 -0
  22. package/data/docs/logo-maker-methodology.md +109 -0
  23. package/data/docs/presentation-asset-repository.md +53 -0
  24. package/data/docs/product-architecture.md +42 -0
  25. package/data/docs/quick-start-ai.md +4 -4
  26. package/data/docs/shadcn-conversion.md +1 -1
  27. package/data/docs/sidebar-placement.md +56 -0
  28. package/data/docs/theme-authoring.md +6 -3
  29. package/data/manifests/catalog.json +42 -46
  30. package/data/manifests/components.json +317 -66
  31. package/data/manifests/logo-skills.json +174 -0
  32. package/data/manifests/motion-profiles.json +2 -2
  33. package/data/manifests/patterns.json +201 -7
  34. package/data/manifests/presentation-assets.schema.json +44 -0
  35. package/data/manifests/templates.json +87 -1
  36. package/data/manifests/theme-dextrum.json +7 -7
  37. package/data/manifests/theme-prism-mono.json +19 -0
  38. package/data/manifests/theme-utopia-cloudblur.json +135 -0
  39. package/data/manifests/theme-utopia-default.json +31 -31
  40. package/data/manifests/theme-vyapti.json +17 -1
  41. package/data/manifests/theme-y2k-pop.json +18 -0
  42. package/data/manifests/themes.json +285 -57
  43. package/data/templates/analytics-dashboard/main.tsx +14 -1
  44. package/data/templates/calendar-application/main.tsx +14 -1
  45. package/data/templates/chat-workspace/README.md +12 -0
  46. package/data/templates/chat-workspace/index.html +11 -0
  47. package/data/templates/chat-workspace/main.tsx +97 -0
  48. package/data/templates/chat-workspace/styles.css +19 -0
  49. package/data/templates/chat-workspace/template.manifest.json +13 -0
  50. package/data/templates/composition-registry-lab/main.tsx +12 -1
  51. package/data/templates/dashboard-composer/main.tsx +14 -1
  52. package/data/templates/database-workspace/main.tsx +14 -1
  53. package/data/templates/interaction-lab/main.tsx +12 -1
  54. package/data/templates/quantum-verification-story/README.md +12 -0
  55. package/data/templates/quantum-verification-story/components.json +21 -0
  56. package/data/templates/quantum-verification-story/eslint.config.mjs +13 -0
  57. package/data/templates/quantum-verification-story/next-env.d.ts +7 -0
  58. package/data/templates/quantum-verification-story/next.config.mjs +11 -0
  59. package/data/templates/quantum-verification-story/package-lock.json +7535 -0
  60. package/data/templates/quantum-verification-story/package.json +46 -0
  61. package/data/templates/quantum-verification-story/postcss.config.js +6 -0
  62. package/data/templates/quantum-verification-story/src/app/assessment/page.tsx +138 -0
  63. package/data/templates/quantum-verification-story/src/app/ceramic-theme.css +48 -0
  64. package/data/templates/quantum-verification-story/src/app/deployment/page.tsx +178 -0
  65. package/data/templates/quantum-verification-story/src/app/fonts/IBMPlexSansArabic-Bold.ttf +0 -0
  66. package/data/templates/quantum-verification-story/src/app/fonts/IBMPlexSansArabic-Medium.ttf +0 -0
  67. package/data/templates/quantum-verification-story/src/app/fonts/IBMPlexSansArabic-Regular.ttf +0 -0
  68. package/data/templates/quantum-verification-story/src/app/fonts/ReadexPro-Variable.ttf +0 -0
  69. package/data/templates/quantum-verification-story/src/app/fonts/TWKLausanne-350.ttf +0 -0
  70. package/data/templates/quantum-verification-story/src/app/fonts/TWKLausanne-500.ttf +0 -0
  71. package/data/templates/quantum-verification-story/src/app/fonts/TWKLausanne-700.ttf +0 -0
  72. package/data/templates/quantum-verification-story/src/app/globals.css +175 -0
  73. package/data/templates/quantum-verification-story/src/app/layout.tsx +45 -0
  74. package/data/templates/quantum-verification-story/src/app/not-found.tsx +39 -0
  75. package/data/templates/quantum-verification-story/src/app/page.tsx +24 -0
  76. package/data/templates/quantum-verification-story/src/app/products/page.tsx +132 -0
  77. package/data/templates/quantum-verification-story/src/app/utopia-default.css +312 -0
  78. package/data/templates/quantum-verification-story/src/components/RotatingText.css +36 -0
  79. package/data/templates/quantum-verification-story/src/components/RotatingText.tsx +189 -0
  80. package/data/templates/quantum-verification-story/src/components/brand-mark.tsx +14 -0
  81. package/data/templates/quantum-verification-story/src/components/console-preview-section.tsx +57 -0
  82. package/data/templates/quantum-verification-story/src/components/console-preview.tsx +72 -0
  83. package/data/templates/quantum-verification-story/src/components/fade-up.tsx +54 -0
  84. package/data/templates/quantum-verification-story/src/components/floating-network.tsx +125 -0
  85. package/data/templates/quantum-verification-story/src/components/footer.tsx +83 -0
  86. package/data/templates/quantum-verification-story/src/components/harvest-timeline.tsx +70 -0
  87. package/data/templates/quantum-verification-story/src/components/lattice-diagram.tsx +73 -0
  88. package/data/templates/quantum-verification-story/src/components/lattice-field.tsx +129 -0
  89. package/data/templates/quantum-verification-story/src/components/nav.tsx +104 -0
  90. package/data/templates/quantum-verification-story/src/components/presentation-layout.tsx +91 -0
  91. package/data/templates/quantum-verification-story/src/components/readiness-estimator.tsx +135 -0
  92. package/data/templates/quantum-verification-story/src/components/scramble-text.tsx +60 -0
  93. package/data/templates/quantum-verification-story/src/components/section-backdrop.tsx +38 -0
  94. package/data/templates/quantum-verification-story/src/components/sections/clients.tsx +140 -0
  95. package/data/templates/quantum-verification-story/src/components/sections/contact.tsx +125 -0
  96. package/data/templates/quantum-verification-story/src/components/sections/hero.tsx +92 -0
  97. package/data/templates/quantum-verification-story/src/components/sections/moat.tsx +73 -0
  98. package/data/templates/quantum-verification-story/src/components/sections/offer.tsx +113 -0
  99. package/data/templates/quantum-verification-story/src/components/sections/pilot.tsx +63 -0
  100. package/data/templates/quantum-verification-story/src/components/sections/problem.tsx +53 -0
  101. package/data/templates/quantum-verification-story/src/components/text-particle.tsx +204 -0
  102. package/data/templates/quantum-verification-story/src/components/ticker.tsx +27 -0
  103. package/data/templates/quantum-verification-story/src/components/ui/badge.tsx +29 -0
  104. package/data/templates/quantum-verification-story/src/components/ui/button.tsx +55 -0
  105. package/data/templates/quantum-verification-story/src/components/ui/card.tsx +46 -0
  106. package/data/templates/quantum-verification-story/src/components/ui/cursor-driven-particle-typography.tsx +288 -0
  107. package/data/templates/quantum-verification-story/src/components/ui/input.tsx +20 -0
  108. package/data/templates/quantum-verification-story/src/components/ui/label.tsx +21 -0
  109. package/data/templates/quantum-verification-story/src/components/ui/separator.tsx +25 -0
  110. package/data/templates/quantum-verification-story/src/components/ui/textarea.tsx +19 -0
  111. package/data/templates/quantum-verification-story/src/lib/utils.ts +6 -0
  112. package/data/templates/quantum-verification-story/tailwind.config.js +95 -0
  113. package/data/templates/quantum-verification-story/template.manifest.json +23 -0
  114. package/data/templates/quantum-verification-story/tsconfig.json +42 -0
  115. package/data/templates/saas-solution-homepage/main.tsx +91 -14
  116. package/data/templates/saas-solution-homepage/privacy/index.html +1 -0
  117. package/data/templates/saas-solution-homepage/styles.css +47 -2
  118. package/data/templates/saas-solution-homepage/team/index.html +1 -0
  119. package/data/templates/saas-solution-homepage/template.manifest.json +41 -0
  120. package/data/templates/saas-solution-homepage/terms/index.html +1 -0
  121. package/lib/api.mjs +52 -3
  122. package/lib/template-runtime.mjs +1 -0
  123. package/package.json +2 -2
@@ -0,0 +1,552 @@
1
+ # Ceramic Designer Agent Backend and API Contract
2
+
3
+ Status: implemented in the Convex development deployment
4
+ Owner: Ceramic Design System
5
+ Backend: Convex + Clerk + `@convex-dev/agent` + Convex file storage
6
+
7
+ ### Provider configuration
8
+
9
+ Designer Agent generation uses OpenAI through `@convex-dev/agent` and the
10
+ server-only `@ai-sdk/openai` provider. The only enabled production model is
11
+ `gpt-5.6-luna`; a client-supplied model identifier outside the server allowlist
12
+ is replaced by that model. Store the credential only in each Convex deployment:
13
+
14
+ ```bash
15
+ npx convex env set OPENAI_API_KEY "$OPENAI_API_KEY"
16
+ ```
17
+
18
+ Never use a `VITE_` prefix, commit the value, place it in Brand Room data, or
19
+ send it to the browser. If the variable is absent, `sendMessage` records a
20
+ failed run and returns `errorCode: "PROVIDER_UNAVAILABLE"`; it does not create a
21
+ fixture response that could be mistaken for model output.
22
+
23
+ ## 1. Purpose
24
+
25
+ This contract makes every Designer Agent session durable, resumable, reactive,
26
+ auditable, and safe to approve. The Brand Room remains the control plane. The
27
+ conversation is not the source of truth for approved work: artifacts, versions,
28
+ decisions, approvals, connections, and execution records are stored as governed
29
+ Brand Room data.
30
+
31
+ The browser must be able to close, reload, switch device, or switch model without
32
+ losing accepted state. Preview mode may remain browser-local, but it must be
33
+ visibly labeled and must never impersonate a server-backed save.
34
+
35
+ ## 2. System boundaries
36
+
37
+ ```text
38
+ Clerk identity
39
+ ↓ authenticated JWT
40
+ Convex public API
41
+ ├── Brand Room ownership and membership
42
+ ├── Designer Agent session state
43
+ ├── artifacts, versions, decisions, approvals
44
+ ├── connections, operations, audit events
45
+ └── file storage metadata
46
+ ↓ internal functions only
47
+ @convex-dev/agent
48
+ ├── durable thread and messages
49
+ ├── streaming model execution
50
+ └── governed tool calls
51
+ ↓ explicit approval gates
52
+ Ceramic MCP / GitHub / Figma / media providers / publishing
53
+ ```
54
+
55
+ The web client calls typed Convex functions. It does not write directly to
56
+ tables, store provider secrets, or treat local reducer state as saved state.
57
+ Ceramic MCP and external provider adapters call the same authorization and
58
+ domain rules rather than maintaining a parallel source of truth.
59
+
60
+ ## 3. Required platform components
61
+
62
+ - `@convex-dev/agent`: one durable thread per Designer Agent session. Do not
63
+ create a hand-written messages table.
64
+ - Convex file storage: source uploads, generated previews, editable masters,
65
+ exports, and review attachments.
66
+ - `@convex-dev/workpool`: bounded asynchronous execution for provider calls,
67
+ generation, validation, packaging, and retries.
68
+ - `@convex-dev/rate-limiter`: limits by owner, Room, provider, and operation.
69
+ - Optional `@convex-dev/presence`: only when collaborative viewing, typing, or
70
+ multi-user editing is introduced. Presence is never stored on session rows.
71
+
72
+ ## 4. Identity and authorization
73
+
74
+ All public functions derive the actor from `ctx.auth.getUserIdentity()` and use
75
+ `identity.tokenIdentifier`. No public API accepts an owner or user ID for
76
+ authorization.
77
+
78
+ Initial release keeps the existing owner-only Brand Room policy. The data model
79
+ must support these future Room roles without changing artifact ownership:
80
+
81
+ | Role | Read | Draft | Run tools | Review | Publish/manage |
82
+ | --- | --- | --- | --- | --- | --- |
83
+ | owner | yes | yes | yes | yes | yes |
84
+ | editor | yes | yes | yes | no | no |
85
+ | reviewer | yes | no | no | yes | no |
86
+ | viewer | yes | no | no | no | no |
87
+
88
+ Every write requires active membership, Room access, and a server-side action
89
+ policy check. Approval and publishing permissions are checked independently.
90
+ Unauthorized and missing Room responses are intentionally indistinguishable.
91
+
92
+ ## 5. Data model
93
+
94
+ ### 5.1 Existing tables retained
95
+
96
+ - `brandRooms`: owner, slug, names, source mode, agent target, lifecycle.
97
+ - `brandRoomSources`: managed, repository, uploaded, or blank sources.
98
+ - `brandRoomApprovals`: onboarding-level source, agent, and publishing gates.
99
+
100
+ These tables do not store live Designer Agent work.
101
+
102
+ ### 5.2 `designerAgentSessions`
103
+
104
+ One row per resumable work session.
105
+
106
+ | Field | Type | Contract |
107
+ | --- | --- | --- |
108
+ | `roomId` | `Id<'brandRooms'>` | owning Room |
109
+ | `ownerTokenIdentifier` | string | denormalized authorization index |
110
+ | `agentThreadId` | string | `@convex-dev/agent` thread ID |
111
+ | `title` | string | user-readable session title |
112
+ | `status` | `active \| paused \| completed \| archived` | lifecycle |
113
+ | `currentStage` | journey stage enum | derived checkpoint, not display copy |
114
+ | `locale` | `en \| ko \| ar` | session language |
115
+ | `modelProvider` | approved provider enum | no credentials |
116
+ | `modelId` | string | exact execution model |
117
+ | `revision` | number | optimistic concurrency counter |
118
+ | `lastActivityAt` | number | material activity time |
119
+ | `createdAt`, `updatedAt` | number | mutation timestamps |
120
+
121
+ Indexes:
122
+
123
+ - `by_room_id_and_updated_at: [roomId, updatedAt]`
124
+ - `by_owner_token_identifier_and_updated_at: [ownerTokenIdentifier, updatedAt]`
125
+ - `by_room_id_and_status: [roomId, status]`
126
+ - unique lookup by `agentThreadId`
127
+
128
+ ### 5.3 `designerAgentDrafts`
129
+
130
+ Small, replaceable editor state. Never store an unbounded transcript here.
131
+
132
+ | Field | Type | Contract |
133
+ | --- | --- | --- |
134
+ | `sessionId` | session ID | parent |
135
+ | `roomId` | Room ID | authorization/index |
136
+ | `draftKey` | enum/string | `discovery`, `logo-brief`, `workspace-url`, etc. |
137
+ | `value` | validated object/string | bounded draft payload |
138
+ | `clientRevision` | number | conflict detection |
139
+ | `updatedByTokenIdentifier` | string | actor |
140
+ | `updatedAt` | number | last save |
141
+
142
+ Index `by_session_id_and_draft_key` must be unique. Draft payloads are limited to
143
+ 64 KB. Large binaries and generated output use file storage.
144
+
145
+ ### 5.4 `designerAgentArtifacts`
146
+
147
+ Stable artifact identity independent of versions.
148
+
149
+ | Field | Type | Contract |
150
+ | --- | --- | --- |
151
+ | `roomId`, `sessionId` | IDs | ownership and origin |
152
+ | `kind` | governed enum | brief, identity, theme, PRD, workspace, package, template, app, site, presentation, marketing, report |
153
+ | `name` | string | human-readable identity |
154
+ | `status` | `draft \| review \| approved \| rejected \| archived` | lifecycle |
155
+ | `currentVersionId` | artifact-version ID or null | current pointer |
156
+ | `createdBy` | `user \| agent \| imported` | provenance |
157
+ | `createdByTokenIdentifier` | optional string | actor when applicable |
158
+ | `createdAt`, `updatedAt` | number | timestamps |
159
+
160
+ Indexes:
161
+
162
+ - `by_room_id_and_status`
163
+ - `by_session_id_and_updated_at`
164
+ - `by_room_id_and_kind`
165
+
166
+ ### 5.5 `designerAgentArtifactVersions`
167
+
168
+ Immutable versions. Approval points to a version, never only to an artifact.
169
+
170
+ | Field | Type | Contract |
171
+ | --- | --- | --- |
172
+ | `artifactId`, `roomId`, `sessionId` | IDs | ownership |
173
+ | `version` | number | monotonic per artifact |
174
+ | `format` | governed enum | json, markdown, svg, png, webp, pdf, pptx, zip, git-ref, figma-ref |
175
+ | `content` | optional bounded object/string | small structured output |
176
+ | `storageId` | optional storage ID | large/binary output |
177
+ | `previewStorageId` | optional storage ID | optimized preview |
178
+ | `sourceRunId` | optional run ID | generation provenance |
179
+ | `themeId`, `themeVersion` | optional strings | visual contract |
180
+ | `assetManifestCommit` | optional string | governed input revision |
181
+ | `checksum` | string | integrity/idempotency |
182
+ | `provenance` | validated object | model, provider, prompt ref, sources, license, cost |
183
+ | `createdAt` | number | immutable timestamp |
184
+
185
+ Unique index: `by_artifact_id_and_version`. Lists must be paginated.
186
+
187
+ ### 5.6 `designerAgentRuns`
188
+
189
+ One record per tool, model, validation, import, or export execution.
190
+
191
+ Fields: `roomId`, `sessionId`, `operationId`, `kind`, `toolId`, `status`,
192
+ `provider`, `modelId`, `inputSummary`, `outputSummary`, `progress`, `attempt`,
193
+ `startedAt`, `completedAt`, `errorCode`, `sanitizedError`, `costAmount`,
194
+ `costCurrency`, `requiresApproval`, `approvalId`.
195
+
196
+ Statuses: `queued`, `running`, `waiting-for-approval`, `succeeded`, `failed`,
197
+ `cancelled`. Raw prompts, raw tool output, stack traces, and secrets are not
198
+ stored in this table.
199
+
200
+ Indexes:
201
+
202
+ - `by_session_id_and_started_at`
203
+ - `by_room_id_and_status`
204
+ - `by_operation_id`
205
+
206
+ ### 5.7 `designerAgentApprovals`
207
+
208
+ Fine-grained approvals for artifact versions and actions. This is separate from
209
+ the existing onboarding gates.
210
+
211
+ Fields: `roomId`, `sessionId`, `subjectKind`, `subjectId`, `action`, `status`,
212
+ `requestedBy`, `requestedAt`, `resolvedByTokenIdentifier`, `resolvedAt`,
213
+ `reason`, `expectedRevision`, `expiresAt`.
214
+
215
+ Statuses: `pending`, `approved`, `rejected`, `expired`, `cancelled`.
216
+ Publishing, deployment, repository writes, paid generation, and external human
217
+ service requests always require an approval unless a later explicit policy
218
+ allows otherwise.
219
+
220
+ ### 5.8 `designerAgentConnections`
221
+
222
+ Versioned connection metadata, never secrets.
223
+
224
+ Fields: `roomId`, `kind`, `status`, `label`, `repositoryUrl`, `defaultBranch`,
225
+ `figmaFileKey`, `assetWorkspaceRef`, `providerAccountRef`, `capabilities`,
226
+ `verifiedAt`, `createdAt`, `updatedAt`.
227
+
228
+ Kinds: `git`, `figma`, `assets`, `mcp`, `media-provider`. Provider credentials
229
+ remain in a server-side secret system. The database may store only a revocable
230
+ opaque provider account reference.
231
+
232
+ ### 5.9 `designerAgentOperations`
233
+
234
+ Idempotency and retry boundary for client commands and external callbacks.
235
+
236
+ Fields: `roomId`, `sessionId`, `clientOperationId`, `kind`, `status`, `resultRef`,
237
+ `createdByTokenIdentifier`, `createdAt`, `completedAt`.
238
+
239
+ Unique index `by_session_id_and_client_operation_id` prevents double-send,
240
+ double-generation, double-approval, and double-publish after retries.
241
+
242
+ ### 5.10 `designerAgentDecisions` and `designerAgentAuditEvents`
243
+
244
+ `designerAgentDecisions` stores durable product/brand decisions with scope,
245
+ statement, rationale, evidence references, status, superseded decision, and
246
+ actor. It is the compact Room memory injected into future sessions.
247
+
248
+ Before discovery decisions are split into that compact register, the latest
249
+ approved discovery brief is stored as an immutable `markdown` artifact version
250
+ and injected into later model turns as bounded Brand Room memory. Draft composer
251
+ state and unapproved artifact versions never enter this durable context.
252
+
253
+ `designerAgentAuditEvents` is append-only and stores sanitized event type,
254
+ actor, subject, operation ID, timestamp, and bounded metadata. It never stores
255
+ message bodies, secrets, raw prompts, raw provider responses, or stack traces.
256
+ Audit queries are paginated and owner/reviewer restricted.
257
+
258
+ ## 6. Public Convex API
259
+
260
+ ### Queries
261
+
262
+ | Function | Arguments | Result |
263
+ | --- | --- | --- |
264
+ | `designerAgent.getWorkspace` | `roomId` | active session summary, current stage, drafts, connections, current artifacts, pending approvals, active runs |
265
+ | `designerAgent.getSession` | `sessionId` | authorized session metadata |
266
+ | `designerAgent.listSessions` | `roomId`, pagination | newest Room sessions |
267
+ | `designerAgent.listMessages` | agent thread + pagination | delegated to `@convex-dev/agent` |
268
+ | `designerAgent.listArtifacts` | `roomId`, status/kind, pagination | artifact summaries |
269
+ | `designerAgent.getArtifact` | `artifactId` | artifact plus current version and approval state |
270
+ | `designerAgent.listArtifactVersions` | `artifactId`, pagination | immutable version history |
271
+ | `designerAgent.listRuns` | `sessionId`, pagination | bounded execution history |
272
+ | `designerAgent.listAuditEvents` | `roomId`, pagination | authorized sanitized audit log |
273
+
274
+ `getWorkspace` is the initial reactive read and must avoid a client request
275
+ waterfall. Long histories remain separate paginated queries.
276
+
277
+ ### Mutations
278
+
279
+ | Function | Purpose |
280
+ | --- | --- |
281
+ | `designerAgent.startSession` | create a session and agent thread, or return an idempotent existing session |
282
+ | `designerAgent.resumeSession` | reactivate a paused session and return the current revision |
283
+ | `designerAgent.pauseSession` | explicit close/pause checkpoint |
284
+ | `designerAgent.saveDraft` | upsert one bounded draft with expected client revision |
285
+ | `designerAgent.clearDraft` | clear a saved composer/tool draft |
286
+ | `designerAgent.updateStage` | internal/domain-validated stage transition only |
287
+ | `designerAgent.requestApproval` | create a pending approval for a version/action |
288
+ | `designerAgent.resolveApproval` | approve/reject with expected revision and role check |
289
+ | `designerAgent.registerUpload` | attach uploaded source or artifact storage to the Room |
290
+ | `designerAgent.connectWorkspace` | create/update a verified connection after server validation |
291
+ | `designerAgent.disconnectWorkspace` | revoke metadata and dependent capabilities |
292
+ | `designerAgent.cancelRun` | request cancellation for a cancellable run |
293
+ | `designerAgent.archiveSession` | recoverable archive, never destructive deletion |
294
+
295
+ ### Actions
296
+
297
+ | Function | Purpose |
298
+ | --- | --- |
299
+ | `designerAgent.sendMessage` | idempotently append user input, invoke the agent, stream response/tool activity, checkpoint results |
300
+ | `designerAgent.runTool` | execute one registered governed tool through the work pool |
301
+ | `designerAgent.retryRun` | retry an idempotent failed operation |
302
+ | `designerAgent.verifyConnection` | server-side Git/Figma/provider capability check |
303
+ | `designerAgent.exportArtifact` | create a governed binary export in storage |
304
+ | `designerAgent.createHandoff` | create an MCP/Codex/Claude handoff containing approved context only |
305
+
306
+ Provider-specific calls are internal actions. Public clients select a registered
307
+ capability, not an arbitrary function name, URL, command, model endpoint, or
308
+ prompt template.
309
+
310
+ ### Logo Maker through MCP
311
+
312
+ The browser and MCP read `manifests/logo-skills.json` as the same Logo Maker
313
+ source of truth. An MCP conversation calls `get_room_context`,
314
+ `list_logo_skills` or `get_logo_skill`, and then `prepare_logo_maker_run` with
315
+ the selected skill id, brief, and up to three optional reference ids. The
316
+ prepared response includes the governed prompt and review sequence; it is a
317
+ proposal handoff, not proof that generation, approval, checkpointing, or
318
+ publishing occurred. An authenticated remote MCP adapter may submit that exact
319
+ input to `designerAgent.runTool`, but it must preserve Room authorization,
320
+ idempotency, audit events, artifact provenance, and the explicit human approval
321
+ gate rather than writing around Convex.
322
+
323
+ The prepared response also exposes the manifest's `qualityFramework`, including
324
+ the shared Logo Quality Check gates and the canonical
325
+ `docs/design-system/logo-maker-methodology.md` reference. Browser and MCP
326
+ clients must render artifact-backed evidence for those gates; receiving the
327
+ framework or a model-authored assessment does not by itself constitute a pass.
328
+
329
+ The initial production provider is OpenAI through the server-side
330
+ `OPENAI_API_KEY`, with `gpt-5.6-luna` as the cost-sensitive default model.
331
+ Provider credentials never cross the Convex action boundary and are never
332
+ written to Room state, messages, operations, or audit metadata.
333
+
334
+ ### File-storage mutations
335
+
336
+ - `designerAgent.generateUploadUrl({ roomId, purpose })`
337
+ - `designerAgent.attachUpload({ roomId, sessionId, storageId, purpose,
338
+ fileName, contentType, size, checksum })`
339
+ - `designerAgent.getDownloadUrl({ artifactVersionId })`
340
+
341
+ The attach mutation validates Room access, declared purpose, metadata, maximum
342
+ size, actual `_storage` metadata, checksum policy, and allowed MIME type.
343
+
344
+ ## 7. Internal API and execution transaction
345
+
346
+ Each tool execution follows this sequence:
347
+
348
+ 1. Public action validates identity, membership, Room access, capability, and
349
+ `clientOperationId`.
350
+ 2. Internal mutation creates or reuses the operation and queued run.
351
+ 3. Work pool performs the provider/tool call.
352
+ 4. Internal mutation atomically records sanitized run output, new artifact
353
+ version(s), current artifact pointers, decisions, audit event, and stage
354
+ transition.
355
+ 5. If approval is required, the run becomes `waiting-for-approval`; no external
356
+ write or publication occurs.
357
+ 6. Approval mutation validates the exact subject version and expected revision.
358
+ 7. An internal scheduled action performs the approved external side effect and
359
+ records its final reference.
360
+
361
+ Failure before step 4 creates no partial approved artifact. Retried operations
362
+ reuse the same operation ID and never duplicate side effects.
363
+
364
+ ## 8. Autosave and recovery contract
365
+
366
+ ### Save points
367
+
368
+ - Message send: durable before model execution begins.
369
+ - Composer/tool draft: debounce after 750 ms of inactivity and save on blur.
370
+ - Selection/reference changes: save immediately as a draft.
371
+ - Artifact/run transition: server checkpoint in the same mutation as the
372
+ transition.
373
+ - Approval: transactional save before any dependent action is scheduled.
374
+ - Navigation or explicit exit: call `pauseSession`; unsent text remains a draft.
375
+
376
+ `pagehide` is best-effort only and is not the primary save mechanism.
377
+
378
+ ### Client state
379
+
380
+ - Convex reactive queries are the server truth.
381
+ - Optimistic UI is allowed for drafts and message submission.
382
+ - Every mutation carries `clientOperationId` and, where applicable,
383
+ `expectedRevision`.
384
+ - Revision conflict returns a typed conflict with the current server revision;
385
+ the client preserves both draft values and asks the user to reconcile when an
386
+ automatic merge is unsafe.
387
+ - Preview mode may use local storage under a preview-only namespace. Production
388
+ state must never silently fall back to local storage.
389
+
390
+ ### Reload recovery
391
+
392
+ On load, the client obtains `getWorkspace` and the agent thread messages,
393
+ restores saved drafts, subscribes to active runs, and scrolls to the latest
394
+ meaningful message. A `running` operation without a live worker is reconciled by
395
+ a scheduled recovery job to `queued`, `failed`, or `waiting-for-approval` based
396
+ on its durable checkpoint.
397
+
398
+ ## 9. Agent tool contract
399
+
400
+ Every registered tool declares:
401
+
402
+ - stable ID and version;
403
+ - input and output validators;
404
+ - required Room capabilities;
405
+ - reversible or irreversible classification;
406
+ - approval policy;
407
+ - cost policy and currency;
408
+ - artifact kinds it may read/write;
409
+ - timeout, retry, and idempotency behavior;
410
+ - sanitized progress and error vocabulary;
411
+ - audit event types.
412
+
413
+ Tools may read only approved Room context plus explicitly selected drafts and
414
+ sources. They do not receive the entire raw conversation by default. Outputs
415
+ cannot directly mutate approved artifacts, publish, deploy, or write to Git.
416
+
417
+ ## 10. Streaming and real-time behavior
418
+
419
+ - Agent messages and tool steps stream through `@convex-dev/agent`.
420
+ - Substantive designer replies persist as a bounded Markdown contract: short
421
+ summary, proposed directions with form/typography/palette cues, decisions
422
+ needed, and one next step. Browser clients may render those sections as
423
+ visual comparison cards and lists; API and MCP clients
424
+ retain the same readable source instead of receiving presentation-only JSON.
425
+ - Artifact, approval, run, and connection panels update through reactive Convex
426
+ queries.
427
+ - Streaming text is not considered an approved artifact.
428
+ - A completed tool result is committed as a version before the UI labels it
429
+ saved.
430
+ - The right output rail renders only durable or explicitly marked transient
431
+ results. Transient previews identify their unsaved state.
432
+
433
+ ## 11. Errors
434
+
435
+ Public APIs return stable error codes with localized client copy:
436
+
437
+ - `AUTH_REQUIRED`
438
+ - `MEMBERSHIP_REQUIRED`
439
+ - `ROOM_NOT_FOUND`
440
+ - `FORBIDDEN`
441
+ - `REVISION_CONFLICT`
442
+ - `VALIDATION_FAILED`
443
+ - `APPROVAL_REQUIRED`
444
+ - `CAPABILITY_MISSING`
445
+ - `RATE_LIMITED`
446
+ - `PROVIDER_UNAVAILABLE`
447
+ - `OPERATION_NOT_RETRYABLE`
448
+ - `FILE_REJECTED`
449
+
450
+ Server logs may contain an internal correlation ID. Client-visible and stored
451
+ errors are sanitized and contain no credential, raw provider response, stack,
452
+ or unrelated Room data.
453
+
454
+ ## 12. Privacy, retention, and deletion
455
+
456
+ - No API keys, OAuth tokens, cookies, raw authorization headers, or local paths
457
+ enter messages, artifacts, audit metadata, analytics, or client storage.
458
+ - Provider prompts and responses are retained only according to the visible
459
+ Room policy. Approved decisions and artifact provenance remain durable.
460
+ - Archived sessions remain recoverable. Permanent Room deletion requires an
461
+ explicit destructive flow that batches child deletion and storage cleanup.
462
+ - Export includes messages, decisions, approvals, artifacts, versions,
463
+ provenance, and audit events that the actor is authorized to read.
464
+ - Analytics remains separate from operational persistence and follows consent.
465
+
466
+ ## 13. Limits and abuse controls
467
+
468
+ - Paginate all messages, sessions, runs, versions, and audit events.
469
+ - No unbounded arrays or `.collect()` on growing tables.
470
+ - Draft payload: 64 KB maximum.
471
+ - Individual structured artifact content: 256 KB maximum; larger output uses
472
+ storage.
473
+ - Upload limits depend on purpose and MIME policy; current Brand source maximum
474
+ remains 25 MB until explicitly changed.
475
+ - Rate limits apply to messages, provider execution, uploads, approvals, and
476
+ exports separately.
477
+ - Paid operations disclose estimated cost and require an approval record before
478
+ execution.
479
+
480
+ ## 14. Client service contract
481
+
482
+ The React page must consume a service/orchestration interface rather than Convex
483
+ references directly:
484
+
485
+ ```ts
486
+ type DesignerAgentService = {
487
+ startSession(input: StartSessionInput): Promise<SessionRef>
488
+ saveDraft(input: SaveDraftInput): Promise<SavedDraft>
489
+ sendMessage(input: SendMessageInput): Promise<OperationRef>
490
+ resolveApproval(input: ResolveApprovalInput): Promise<ApprovalResult>
491
+ connectWorkspace(input: ConnectWorkspaceInput): Promise<ConnectionResult>
492
+ cancelRun(input: CancelRunInput): Promise<void>
493
+ }
494
+ ```
495
+
496
+ Domain transition and approval rules remain pure in `src/domain/`. Convex
497
+ function references live in `src/services/`. `src/utopia-os.tsx` orchestrates
498
+ authentication and reactive data. Pages bind content, routing, and composition
499
+ only.
500
+
501
+ ## 15. Test contract
502
+
503
+ ### Convex tests
504
+
505
+ - owner and non-owner access for every public function;
506
+ - active membership enforcement;
507
+ - session start idempotency;
508
+ - message operation idempotency;
509
+ - draft save and revision conflict;
510
+ - immutable artifact versions and monotonic version number;
511
+ - approval of the exact expected version;
512
+ - no publish/deploy/write before approval;
513
+ - run retry/cancel rules;
514
+ - connection verification and revocation;
515
+ - storage metadata and file limits;
516
+ - bounded and indexed pagination;
517
+ - sanitized errors and audit events;
518
+ - interrupted-run recovery.
519
+
520
+ ### Browser tests
521
+
522
+ - refresh restores conversation, stage, drafts, output, and artifacts;
523
+ - another authenticated browser receives reactive updates;
524
+ - duplicate submission does not duplicate a message, artifact, or operation;
525
+ - offline/failed save remains visibly unsaved and recovers;
526
+ - revision conflict preserves both drafts;
527
+ - approval changes the exact version shown in the output rail;
528
+ - preview mode remains visibly local;
529
+ - desktop/mobile and English/Arabic RTL preserve the same saved state.
530
+
531
+ ## 16. Delivery sequence
532
+
533
+ 1. Mount `@convex-dev/agent`, work pool, and rate limiter.
534
+ 2. Add session, draft, operation, run, artifact/version, approval, connection,
535
+ decision, and audit schemas with indexes.
536
+ 3. Implement owner-only authorization helpers and snapshot/session APIs.
537
+ 4. Implement durable agent thread, send, autosave, idempotency, and reload.
538
+ 5. Move discovery brief and Logo Maker output from React reducer state into
539
+ artifact versions and approvals.
540
+ 6. Move workspace connection into verified durable connections.
541
+ 7. Add recovery jobs, export/archive, and storage cleanup.
542
+ 8. Add Room collaboration roles only after owner flow passes security and
543
+ recovery tests.
544
+
545
+ ## 17. Definition of done
546
+
547
+ The backend is complete only when a signed-in user can create a session, send a
548
+ message, close the browser during execution, return from another browser, and
549
+ recover the same conversation, stage, draft, run status, output, artifact
550
+ version, decision, connection, and pending approval. No UI may display “saved,”
551
+ “approved,” “connected,” or “completed” until the corresponding durable server
552
+ record exists.
@@ -0,0 +1,29 @@
1
+ # Resend newsletter integration
2
+
3
+ Ceramic's homepage newsletter posts to `/api/subscribe`. The Vercel function
4
+ registers the subscriber directly with Resend Contacts; the browser never sees
5
+ the Resend API key.
6
+
7
+ ## Required configuration
8
+
9
+ Set these server-side environment variables in the Vercel project:
10
+
11
+ - `RESEND_API_KEY`: restricted Resend API key with Contacts access.
12
+ - `RESEND_NEWSLETTER_SEGMENT_ID`: optional Segment ID for Ceramic subscribers.
13
+
14
+ Do not prefix either variable with `VITE_`. After changing a production
15
+ environment variable, redeploy the site so the serverless function receives it.
16
+
17
+ ## Runtime behavior
18
+
19
+ 1. Reject malformed addresses and submissions without explicit consent.
20
+ 2. Quietly accept honeypot submissions without contacting Resend.
21
+ 3. Create an opted-in Resend contact and add it to the configured Segment.
22
+ 4. If the contact already exists, restore its opted-in state and ensure Segment
23
+ membership instead of treating the duplicate as an error.
24
+ 5. Return only generic errors to the browser. Provider payloads and API keys are
25
+ never logged or returned.
26
+
27
+ The endpoint currently registers contacts only. Broadcasts, templates, and
28
+ transactional welcome emails remain controlled from Resend and require a
29
+ verified sending domain before activation.