@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.
- package/README.md +28 -14
- package/bin/utopia-ds-mcp.mjs +6 -2
- package/bin/utopia-ds.mjs +94 -21
- package/data/docs/arabic-friendly.md +19 -2
- package/data/docs/billing-setup.md +80 -0
- package/data/docs/cer-003-032-033-round-8-repair.md +41 -0
- package/data/docs/cer-007-checkout.md +51 -0
- package/data/docs/cer-008-011-qa-repair.md +64 -0
- package/data/docs/cer-016-023-round-6-repair.md +92 -0
- package/data/docs/cer-024-031-round-7-repair.md +51 -0
- package/data/docs/cer-033-035-036-round-12-repair.md +37 -0
- package/data/docs/cer-035-037-round-10-repair.md +34 -0
- package/data/docs/charts.md +34 -3
- package/data/docs/chat-service-methodology.md +181 -0
- package/data/docs/code-block.md +20 -0
- package/data/docs/creative-production.md +149 -0
- package/data/docs/designer-agent-backend-contract.md +552 -0
- package/data/docs/email-resend.md +29 -0
- package/data/docs/foundations.md +46 -8
- package/data/docs/guide.md +9 -9
- package/data/docs/handover-billing-aiden.md +132 -0
- package/data/docs/logo-maker-methodology.md +109 -0
- package/data/docs/presentation-asset-repository.md +53 -0
- package/data/docs/product-architecture.md +42 -0
- package/data/docs/quick-start-ai.md +4 -4
- package/data/docs/shadcn-conversion.md +1 -1
- package/data/docs/sidebar-placement.md +56 -0
- package/data/docs/theme-authoring.md +6 -3
- package/data/manifests/catalog.json +42 -46
- package/data/manifests/components.json +317 -66
- package/data/manifests/logo-skills.json +174 -0
- package/data/manifests/motion-profiles.json +2 -2
- package/data/manifests/patterns.json +201 -7
- package/data/manifests/presentation-assets.schema.json +44 -0
- package/data/manifests/templates.json +87 -1
- package/data/manifests/theme-dextrum.json +7 -7
- package/data/manifests/theme-prism-mono.json +19 -0
- package/data/manifests/theme-utopia-cloudblur.json +135 -0
- package/data/manifests/theme-utopia-default.json +31 -31
- package/data/manifests/theme-vyapti.json +17 -1
- package/data/manifests/theme-y2k-pop.json +18 -0
- package/data/manifests/themes.json +285 -57
- package/data/templates/analytics-dashboard/main.tsx +14 -1
- package/data/templates/calendar-application/main.tsx +14 -1
- package/data/templates/chat-workspace/README.md +12 -0
- package/data/templates/chat-workspace/index.html +11 -0
- package/data/templates/chat-workspace/main.tsx +97 -0
- package/data/templates/chat-workspace/styles.css +19 -0
- package/data/templates/chat-workspace/template.manifest.json +13 -0
- package/data/templates/composition-registry-lab/main.tsx +12 -1
- package/data/templates/dashboard-composer/main.tsx +14 -1
- package/data/templates/database-workspace/main.tsx +14 -1
- package/data/templates/interaction-lab/main.tsx +12 -1
- package/data/templates/quantum-verification-story/README.md +12 -0
- package/data/templates/quantum-verification-story/components.json +21 -0
- package/data/templates/quantum-verification-story/eslint.config.mjs +13 -0
- package/data/templates/quantum-verification-story/next-env.d.ts +7 -0
- package/data/templates/quantum-verification-story/next.config.mjs +11 -0
- package/data/templates/quantum-verification-story/package-lock.json +7535 -0
- package/data/templates/quantum-verification-story/package.json +46 -0
- package/data/templates/quantum-verification-story/postcss.config.js +6 -0
- package/data/templates/quantum-verification-story/src/app/assessment/page.tsx +138 -0
- package/data/templates/quantum-verification-story/src/app/ceramic-theme.css +48 -0
- package/data/templates/quantum-verification-story/src/app/deployment/page.tsx +178 -0
- package/data/templates/quantum-verification-story/src/app/fonts/IBMPlexSansArabic-Bold.ttf +0 -0
- package/data/templates/quantum-verification-story/src/app/fonts/IBMPlexSansArabic-Medium.ttf +0 -0
- package/data/templates/quantum-verification-story/src/app/fonts/IBMPlexSansArabic-Regular.ttf +0 -0
- package/data/templates/quantum-verification-story/src/app/fonts/ReadexPro-Variable.ttf +0 -0
- package/data/templates/quantum-verification-story/src/app/fonts/TWKLausanne-350.ttf +0 -0
- package/data/templates/quantum-verification-story/src/app/fonts/TWKLausanne-500.ttf +0 -0
- package/data/templates/quantum-verification-story/src/app/fonts/TWKLausanne-700.ttf +0 -0
- package/data/templates/quantum-verification-story/src/app/globals.css +175 -0
- package/data/templates/quantum-verification-story/src/app/layout.tsx +45 -0
- package/data/templates/quantum-verification-story/src/app/not-found.tsx +39 -0
- package/data/templates/quantum-verification-story/src/app/page.tsx +24 -0
- package/data/templates/quantum-verification-story/src/app/products/page.tsx +132 -0
- package/data/templates/quantum-verification-story/src/app/utopia-default.css +312 -0
- package/data/templates/quantum-verification-story/src/components/RotatingText.css +36 -0
- package/data/templates/quantum-verification-story/src/components/RotatingText.tsx +189 -0
- package/data/templates/quantum-verification-story/src/components/brand-mark.tsx +14 -0
- package/data/templates/quantum-verification-story/src/components/console-preview-section.tsx +57 -0
- package/data/templates/quantum-verification-story/src/components/console-preview.tsx +72 -0
- package/data/templates/quantum-verification-story/src/components/fade-up.tsx +54 -0
- package/data/templates/quantum-verification-story/src/components/floating-network.tsx +125 -0
- package/data/templates/quantum-verification-story/src/components/footer.tsx +83 -0
- package/data/templates/quantum-verification-story/src/components/harvest-timeline.tsx +70 -0
- package/data/templates/quantum-verification-story/src/components/lattice-diagram.tsx +73 -0
- package/data/templates/quantum-verification-story/src/components/lattice-field.tsx +129 -0
- package/data/templates/quantum-verification-story/src/components/nav.tsx +104 -0
- package/data/templates/quantum-verification-story/src/components/presentation-layout.tsx +91 -0
- package/data/templates/quantum-verification-story/src/components/readiness-estimator.tsx +135 -0
- package/data/templates/quantum-verification-story/src/components/scramble-text.tsx +60 -0
- package/data/templates/quantum-verification-story/src/components/section-backdrop.tsx +38 -0
- package/data/templates/quantum-verification-story/src/components/sections/clients.tsx +140 -0
- package/data/templates/quantum-verification-story/src/components/sections/contact.tsx +125 -0
- package/data/templates/quantum-verification-story/src/components/sections/hero.tsx +92 -0
- package/data/templates/quantum-verification-story/src/components/sections/moat.tsx +73 -0
- package/data/templates/quantum-verification-story/src/components/sections/offer.tsx +113 -0
- package/data/templates/quantum-verification-story/src/components/sections/pilot.tsx +63 -0
- package/data/templates/quantum-verification-story/src/components/sections/problem.tsx +53 -0
- package/data/templates/quantum-verification-story/src/components/text-particle.tsx +204 -0
- package/data/templates/quantum-verification-story/src/components/ticker.tsx +27 -0
- package/data/templates/quantum-verification-story/src/components/ui/badge.tsx +29 -0
- package/data/templates/quantum-verification-story/src/components/ui/button.tsx +55 -0
- package/data/templates/quantum-verification-story/src/components/ui/card.tsx +46 -0
- package/data/templates/quantum-verification-story/src/components/ui/cursor-driven-particle-typography.tsx +288 -0
- package/data/templates/quantum-verification-story/src/components/ui/input.tsx +20 -0
- package/data/templates/quantum-verification-story/src/components/ui/label.tsx +21 -0
- package/data/templates/quantum-verification-story/src/components/ui/separator.tsx +25 -0
- package/data/templates/quantum-verification-story/src/components/ui/textarea.tsx +19 -0
- package/data/templates/quantum-verification-story/src/lib/utils.ts +6 -0
- package/data/templates/quantum-verification-story/tailwind.config.js +95 -0
- package/data/templates/quantum-verification-story/template.manifest.json +23 -0
- package/data/templates/quantum-verification-story/tsconfig.json +42 -0
- package/data/templates/saas-solution-homepage/main.tsx +91 -14
- package/data/templates/saas-solution-homepage/privacy/index.html +1 -0
- package/data/templates/saas-solution-homepage/styles.css +47 -2
- package/data/templates/saas-solution-homepage/team/index.html +1 -0
- package/data/templates/saas-solution-homepage/template.manifest.json +41 -0
- package/data/templates/saas-solution-homepage/terms/index.html +1 -0
- package/lib/api.mjs +52 -3
- package/lib/template-runtime.mjs +1 -0
- 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.
|