@soulcraft/kit-schema 2.0.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/CLAUDE.md +77 -0
- package/README.md +271 -0
- package/bun.lock +263 -0
- package/package.json +27 -0
- package/src/index.ts +37 -0
- package/src/loader.ts +183 -0
- package/src/schema.ts +705 -0
- package/src/skills.ts +127 -0
- package/src/types.ts +2338 -0
- package/src/variables.ts +143 -0
- package/tsconfig.base.json +21 -0
- package/tsconfig.json +12 -0
package/src/types.ts
ADDED
|
@@ -0,0 +1,2338 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @soulcraft/kit-schema/types
|
|
3
|
+
* @description TypeScript type definitions for the Soulcraft kit manifest format.
|
|
4
|
+
*
|
|
5
|
+
* Kits are the unit of customization across all Soulcraft products. A kit bundles
|
|
6
|
+
* together configuration, content templates, AI skill definitions, and product-specific
|
|
7
|
+
* extensions that configure a generic platform deployment for a specific vertical.
|
|
8
|
+
*
|
|
9
|
+
* The `type` field on every kit manifest is a discriminant that selects the right
|
|
10
|
+
* product-specific config block:
|
|
11
|
+
* - `"venue"` — Soulcraft Venue (experience-based businesses: candle studios, cat cafes, etc.)
|
|
12
|
+
* - `"content"` — Soulcraft Workshop content kit (knowledge management, documents)
|
|
13
|
+
* - `"app"` — Soulcraft Workshop app kit (runnable SvelteKit applications)
|
|
14
|
+
* - `"academy"` — Soulcraft Academy (learning/certification platform, reserved)
|
|
15
|
+
* - `"soulcraft"` — Unified kit spanning all products with optional per-product sections.
|
|
16
|
+
* One kit.json transforms Workshop (CREATE), Venue (OPERATE), and Academy (GROW).
|
|
17
|
+
*
|
|
18
|
+
* Each kit directory follows this structure:
|
|
19
|
+
* ```
|
|
20
|
+
* kits/{kit-id}/
|
|
21
|
+
* ├── kit.json # Kit manifest (validated by this package)
|
|
22
|
+
* ├── files/
|
|
23
|
+
* │ ├── cms/ # Default CMS content (JSON)
|
|
24
|
+
* │ ├── emails/ # Notification templates (HTML/text)
|
|
25
|
+
* │ └── waivers/ # Waiver text templates (Markdown)
|
|
26
|
+
* └── skills/
|
|
27
|
+
* └── {skill-name}/SKILL.md # AI skill definitions
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
import type { ThemeSeed } from '@soulcraft/theme';
|
|
32
|
+
|
|
33
|
+
// ──────────────────────────────────────────────
|
|
34
|
+
// Shared base types
|
|
35
|
+
// ──────────────────────────────────────────────
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Author metadata embedded in a kit manifest.
|
|
39
|
+
*/
|
|
40
|
+
export interface KitAuthor {
|
|
41
|
+
/** Author display name or organization. */
|
|
42
|
+
name: string;
|
|
43
|
+
/** Contact email address. */
|
|
44
|
+
email?: string;
|
|
45
|
+
/** Author's website or GitHub URL. */
|
|
46
|
+
url?: string;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* A suggestion chip for AI assistant interfaces across Soulcraft products.
|
|
51
|
+
*
|
|
52
|
+
* Used in Workshop's AI chat intro screen (`shared.suggestions`) and Venue's
|
|
53
|
+
* customer-facing chatbot. Cross-product unified replacement for the legacy
|
|
54
|
+
* product-specific suggestion type previously nested under `WorkshopConfig`.
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* ```ts
|
|
58
|
+
* const suggestion: KitSuggestion = {
|
|
59
|
+
* label: 'Add a recipe',
|
|
60
|
+
* prompt: 'Add a new recipe to my cookbook'
|
|
61
|
+
* };
|
|
62
|
+
* ```
|
|
63
|
+
*/
|
|
64
|
+
export interface KitSuggestion {
|
|
65
|
+
/** Short button text shown on the chip (1–5 words). */
|
|
66
|
+
label: string;
|
|
67
|
+
/** Complete sentence the AI acts on when the chip is clicked. */
|
|
68
|
+
prompt: string;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* A `{{variable}}` that users must fill in during kit installation or onboarding.
|
|
73
|
+
*
|
|
74
|
+
* Variables are substituted into kit template files before seeding. The onboarding
|
|
75
|
+
* wizard renders a form field for each variable defined here.
|
|
76
|
+
*
|
|
77
|
+
* @example
|
|
78
|
+
* ```ts
|
|
79
|
+
* const variable: KitVariable = {
|
|
80
|
+
* key: 'businessName',
|
|
81
|
+
* label: 'Business Name',
|
|
82
|
+
* description: 'The display name of your business (e.g. "Wicks & Whiskers Charlotte")',
|
|
83
|
+
* type: 'string',
|
|
84
|
+
* required: true,
|
|
85
|
+
* example: 'Wicks & Whiskers Charlotte'
|
|
86
|
+
* };
|
|
87
|
+
* ```
|
|
88
|
+
*/
|
|
89
|
+
export interface KitVariable {
|
|
90
|
+
/** Variable key used in `{{variableKey}}` template substitutions. */
|
|
91
|
+
key: string;
|
|
92
|
+
/** Human-readable label shown in the onboarding wizard form. */
|
|
93
|
+
label: string;
|
|
94
|
+
/** Explanatory text shown below the form field. */
|
|
95
|
+
description?: string;
|
|
96
|
+
/** Input field type, used to render the correct form control. */
|
|
97
|
+
type: 'string' | 'email' | 'url' | 'phone' | 'timezone' | 'address' | 'color' | 'number';
|
|
98
|
+
/** Whether this variable must be filled in before installation can proceed. */
|
|
99
|
+
required?: boolean;
|
|
100
|
+
/** Placeholder or example value shown in the form field. */
|
|
101
|
+
example?: string;
|
|
102
|
+
/** Default value applied when the user leaves the field empty. */
|
|
103
|
+
default?: string;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Parsed frontmatter from a `SKILL.md` file.
|
|
108
|
+
*
|
|
109
|
+
* Skills teach the AI assistant domain-specific knowledge and capabilities.
|
|
110
|
+
* Background skills are included in every AI context; invocable skills can be
|
|
111
|
+
* triggered by name.
|
|
112
|
+
*/
|
|
113
|
+
export interface SkillFrontmatter {
|
|
114
|
+
/** Unique identifier for this skill within the kit. */
|
|
115
|
+
id: string;
|
|
116
|
+
/** Human-readable skill name. */
|
|
117
|
+
name: string;
|
|
118
|
+
/** One-line description of what this skill teaches or enables. */
|
|
119
|
+
description: string;
|
|
120
|
+
/**
|
|
121
|
+
* Whether this skill is always active (`"background"`), user-triggered (`"invocable"`),
|
|
122
|
+
* or injected automatically based on context signals (`"contextual"`).
|
|
123
|
+
*/
|
|
124
|
+
type: 'background' | 'invocable' | 'contextual';
|
|
125
|
+
/** Version string for the skill definition. */
|
|
126
|
+
version?: string;
|
|
127
|
+
/** Whether this skill requires vision/image analysis capabilities. */
|
|
128
|
+
requiresVision?: boolean;
|
|
129
|
+
/** Whether this skill requires access to the business's live Brainy data. */
|
|
130
|
+
requiresData?: boolean;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* A parsed skill with its frontmatter metadata and body Markdown content.
|
|
135
|
+
*/
|
|
136
|
+
export interface ParsedSkill {
|
|
137
|
+
/** Resolved filesystem path to the SKILL.md file. */
|
|
138
|
+
filePath: string;
|
|
139
|
+
/** Parsed YAML frontmatter from the skill definition. */
|
|
140
|
+
frontmatter: SkillFrontmatter;
|
|
141
|
+
/** The body of the SKILL.md file (everything after the frontmatter block). */
|
|
142
|
+
body: string;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// ──────────────────────────────────────────────
|
|
146
|
+
// Base kit manifest (product-agnostic fields)
|
|
147
|
+
// ──────────────────────────────────────────────
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* A documentation callout for a specific platform feature, surfaced in the admin UI.
|
|
151
|
+
*
|
|
152
|
+
* Kit authors use this to explain hardware requirements, external service setup steps,
|
|
153
|
+
* or other feature-specific information that admins need when enabling a feature.
|
|
154
|
+
*
|
|
155
|
+
* @example
|
|
156
|
+
* ```json
|
|
157
|
+
* {
|
|
158
|
+
* "title": "Compatible Card Readers",
|
|
159
|
+
* "body": "This kit uses Stripe Terminal for in-person card payments...",
|
|
160
|
+
* "links": [{ "label": "Order from Stripe", "url": "https://dashboard.stripe.com/terminal/hardware" }]
|
|
161
|
+
* }
|
|
162
|
+
* ```
|
|
163
|
+
*/
|
|
164
|
+
export interface KitFeatureDoc {
|
|
165
|
+
/** Short heading shown above the callout body. */
|
|
166
|
+
title: string;
|
|
167
|
+
/**
|
|
168
|
+
* Markdown-formatted body content explaining setup requirements, compatible
|
|
169
|
+
* hardware, external accounts needed, or any other admin-facing guidance.
|
|
170
|
+
*/
|
|
171
|
+
body: string;
|
|
172
|
+
/** Optional links rendered as a list below the body. */
|
|
173
|
+
links?: Array<{
|
|
174
|
+
/** Link display text. */
|
|
175
|
+
label: string;
|
|
176
|
+
/** Absolute URL. */
|
|
177
|
+
url: string;
|
|
178
|
+
}>;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Base fields shared by all kit manifests regardless of product type.
|
|
183
|
+
*
|
|
184
|
+
* Extended by {@link VenueKitConfig}, {@link WorkshopKitConfig},
|
|
185
|
+
* {@link AcademyKitConfig}, and {@link SoulcraftKitConfig} via the `type` discriminant.
|
|
186
|
+
*/
|
|
187
|
+
export interface BaseKitManifest {
|
|
188
|
+
/**
|
|
189
|
+
* JSON Schema URL for editor autocompletion and validation.
|
|
190
|
+
* @example "https://soulcraft.com/schemas/kit/v2.json"
|
|
191
|
+
*/
|
|
192
|
+
$schema?: string;
|
|
193
|
+
/** Unique kebab-case identifier for this kit. @example "wicks-and-whiskers" */
|
|
194
|
+
id: string;
|
|
195
|
+
/** Human-readable name. @example "Wicks & Whiskers" */
|
|
196
|
+
name: string;
|
|
197
|
+
/** One-line description of the vertical or use case. */
|
|
198
|
+
description: string;
|
|
199
|
+
/** Semantic version of this kit definition. @example "1.0.0" */
|
|
200
|
+
version: string;
|
|
201
|
+
/** Author or publishing organization. */
|
|
202
|
+
author: KitAuthor;
|
|
203
|
+
/**
|
|
204
|
+
* Release status of this kit. Controls visibility in the kit gallery:
|
|
205
|
+
* - `'released'` — Publicly available to all users.
|
|
206
|
+
* - `'beta'` — Restricted to users listed in `allowedUsers`.
|
|
207
|
+
* - `'draft'` — Hidden from the gallery; only loadable by kit authors.
|
|
208
|
+
* @default 'released'
|
|
209
|
+
*/
|
|
210
|
+
status?: 'released' | 'beta' | 'draft';
|
|
211
|
+
/**
|
|
212
|
+
* Emoji icon displayed on the kit gallery card and in product selection UIs.
|
|
213
|
+
* @example "🕯️" | "🍳" | "🎸"
|
|
214
|
+
*/
|
|
215
|
+
icon?: string;
|
|
216
|
+
/**
|
|
217
|
+
* Markdown-formatted extended description for the kit gallery detail view.
|
|
218
|
+
* Supports headings, bullet lists, and inline code. Used by Workshop's kit
|
|
219
|
+
* browser and Venue's onboarding wizard.
|
|
220
|
+
*/
|
|
221
|
+
longDescription?: string;
|
|
222
|
+
/**
|
|
223
|
+
* User IDs or email addresses permitted to install this kit when `status` is `'beta'`.
|
|
224
|
+
* An empty array means the kit is publicly available regardless of status.
|
|
225
|
+
* Only enforced when {@link status} is `"beta"`.
|
|
226
|
+
*/
|
|
227
|
+
allowedUsers?: string[];
|
|
228
|
+
/**
|
|
229
|
+
* Minimum required platform version. Enforced by the kit loader to prevent
|
|
230
|
+
* incompatibility between older platform deployments and newer kit features.
|
|
231
|
+
* @example "1.0.0"
|
|
232
|
+
*/
|
|
233
|
+
minPlatformVersion?: string;
|
|
234
|
+
/** Tags used for kit discovery and filtering in the onboarding gallery. */
|
|
235
|
+
tags?: string[];
|
|
236
|
+
/**
|
|
237
|
+
* URL to a screenshot or preview image shown on the kit selection card
|
|
238
|
+
* during onboarding.
|
|
239
|
+
*/
|
|
240
|
+
previewImageUrl?: string;
|
|
241
|
+
/**
|
|
242
|
+
* Whether this kit is a primary vertical kit or an extension that augments
|
|
243
|
+
* an already-installed primary kit.
|
|
244
|
+
*
|
|
245
|
+
* - `'primary'` — Defines the core identity of the deployment (the vertical).
|
|
246
|
+
* Only one primary kit should be active at a time. Provides the base theme,
|
|
247
|
+
* experience types, and core feature set.
|
|
248
|
+
* - `'extension'` — Adds capabilities on top of the primary kit (e.g. loyalty
|
|
249
|
+
* program, content studio, franchise ops). Multiple extensions can be active.
|
|
250
|
+
* Extensions declare their dependencies via `requires`.
|
|
251
|
+
*
|
|
252
|
+
* @default 'primary'
|
|
253
|
+
*/
|
|
254
|
+
role?: 'primary' | 'extension';
|
|
255
|
+
/**
|
|
256
|
+
* Kit IDs that must be installed (and active) before this kit can be activated.
|
|
257
|
+
* The kit loader validates these at install time; missing dependencies are errors.
|
|
258
|
+
* Only relevant when `role` is `'extension'`.
|
|
259
|
+
* @example ["wicks-and-whiskers"] — this extension only works with W&W
|
|
260
|
+
*/
|
|
261
|
+
requires?: string[];
|
|
262
|
+
/**
|
|
263
|
+
* Kit IDs that cannot be active at the same time as this kit.
|
|
264
|
+
* The kit manager enforces mutual exclusion — activating one automatically
|
|
265
|
+
* prompts the admin to deactivate conflicting kits.
|
|
266
|
+
* @example ["retail-store"] — booking-based kit conflicts with retail-only kit
|
|
267
|
+
*/
|
|
268
|
+
conflicts?: string[];
|
|
269
|
+
/**
|
|
270
|
+
* Workshop apps declared by this kit.
|
|
271
|
+
*
|
|
272
|
+
* When this kit is activated in a Venue instance, these entries tell Venue's
|
|
273
|
+
* dynamic loader which Workshop app component to mount at which URL path for
|
|
274
|
+
* which user roles. Multiple entries can share the same `mountPath` with
|
|
275
|
+
* different `roles` for role-aware mounting (e.g. rider vs. driver both at `/app`,
|
|
276
|
+
* but Venue mounts the correct component based on the authenticated user's role).
|
|
277
|
+
*
|
|
278
|
+
* Apps are deployed via `POST /api/deploy` from Workshop and then matched
|
|
279
|
+
* to these declarations by slug. Venue cross-references this list against
|
|
280
|
+
* live deployments to resolve the correct bundle at mount time.
|
|
281
|
+
*/
|
|
282
|
+
apps?: KitAppEntry[];
|
|
283
|
+
/**
|
|
284
|
+
* Per-feature documentation shown in the admin Kit Management page.
|
|
285
|
+
*
|
|
286
|
+
* Keys are feature flag names as they appear in the platform's feature config
|
|
287
|
+
* (e.g. `"pos"`, `"loyalty"`, `"subscriptions"`). When the corresponding feature
|
|
288
|
+
* is enabled in an installed kit, this callout appears in the Kit Management
|
|
289
|
+
* admin page to guide the operator through any required setup.
|
|
290
|
+
*
|
|
291
|
+
* @example
|
|
292
|
+
* ```json
|
|
293
|
+
* {
|
|
294
|
+
* "pos": {
|
|
295
|
+
* "title": "Compatible Card Readers",
|
|
296
|
+
* "body": "Use Stripe Terminal internet-connected readers: S700, WisePOS E, or WisePad 3.",
|
|
297
|
+
* "links": [{ "label": "Order from Stripe", "url": "https://dashboard.stripe.com/terminal/hardware" }]
|
|
298
|
+
* }
|
|
299
|
+
* }
|
|
300
|
+
* ```
|
|
301
|
+
*/
|
|
302
|
+
docs?: Record<string, KitFeatureDoc>;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// ──────────────────────────────────────────────
|
|
306
|
+
// Venue kit (Soulcraft Venue product)
|
|
307
|
+
// ──────────────────────────────────────────────
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* Theme seed configuration embedded in a Venue kit manifest.
|
|
311
|
+
*
|
|
312
|
+
* Aliased directly to {@link ThemeSeed} from `@soulcraft/theme` so that kit authors
|
|
313
|
+
* work with the canonical type and any future additions to ThemeSeed automatically
|
|
314
|
+
* propagate here. All color values use OKLCH notation; fonts are Google Font names.
|
|
315
|
+
*
|
|
316
|
+
* @example
|
|
317
|
+
* ```ts
|
|
318
|
+
* const theme: VenueKitTheme = {
|
|
319
|
+
* primary: 'oklch(0.72 0.15 25)',
|
|
320
|
+
* bgBase: 'oklch(0.96 0.02 80)',
|
|
321
|
+
* accent: 'oklch(0.80 0.12 75)',
|
|
322
|
+
* textPrimary: 'oklch(0.30 0.02 60)',
|
|
323
|
+
* displayFont: 'Fraunces',
|
|
324
|
+
* bodyFont: 'Inter'
|
|
325
|
+
* };
|
|
326
|
+
* ```
|
|
327
|
+
*
|
|
328
|
+
* @see {@link ThemeSeed} in `@soulcraft/theme` — the canonical source of truth.
|
|
329
|
+
*/
|
|
330
|
+
export type VenueKitTheme = ThemeSeed;
|
|
331
|
+
|
|
332
|
+
/**
|
|
333
|
+
* Feature flags controlling which platform capabilities are available for a kit.
|
|
334
|
+
*
|
|
335
|
+
* When a feature is `false`, the corresponding routes return 404, nav items are
|
|
336
|
+
* hidden, and admin sections are not rendered. All features default to `false`
|
|
337
|
+
* unless explicitly enabled.
|
|
338
|
+
*/
|
|
339
|
+
export interface VenueFeatures {
|
|
340
|
+
/** Enable live animals (kittens, cats) in the lounge. Activates `/kittens` route and session tracking. */
|
|
341
|
+
animals?: boolean;
|
|
342
|
+
/** Enable the adoption application workflow. Requires `animals: true`. */
|
|
343
|
+
adoption?: boolean;
|
|
344
|
+
/** Enable AI-generated Experience Memory storybooks after each visit. */
|
|
345
|
+
memories?: boolean;
|
|
346
|
+
/** Enable customer loyalty program (points, tiers, rewards). */
|
|
347
|
+
loyalty?: boolean;
|
|
348
|
+
/** Enable digital and physical gift card sales and redemption. */
|
|
349
|
+
giftCards?: boolean;
|
|
350
|
+
/** Enable liability waiver collection before check-in. */
|
|
351
|
+
waivers?: boolean;
|
|
352
|
+
/** Enable the public blog and admin blog editor. */
|
|
353
|
+
blog?: boolean;
|
|
354
|
+
/** Enable the in-store Point of Sale terminal. */
|
|
355
|
+
pos?: boolean;
|
|
356
|
+
/** Enable CMS-managed content pages (About, FAQ, Policies). */
|
|
357
|
+
cms?: boolean;
|
|
358
|
+
/** Enable partner/sponsor listings on the About page. */
|
|
359
|
+
partners?: boolean;
|
|
360
|
+
/** Enable franchise multi-location management. */
|
|
361
|
+
franchise?: boolean;
|
|
362
|
+
/** Enable customer loyalty accounts. */
|
|
363
|
+
customerAccounts?: boolean;
|
|
364
|
+
/**
|
|
365
|
+
* Enable hosting of Workshop-published apps (Svelte component bundles).
|
|
366
|
+
* Activates the `/apps/{slug}` route and the "Apps & Content" admin section.
|
|
367
|
+
*/
|
|
368
|
+
apps?: boolean;
|
|
369
|
+
/**
|
|
370
|
+
* Enable hosting of Workshop-published documents (markdown/rich text).
|
|
371
|
+
* Activates the `/docs/{slug}` route and document management in admin.
|
|
372
|
+
*/
|
|
373
|
+
documents?: boolean;
|
|
374
|
+
/**
|
|
375
|
+
* Enable hosting of Workshop-published visualizations (knowledge graphs, mind maps, etc.).
|
|
376
|
+
* Activates the `/viz/{slug}` route and visualization management in admin.
|
|
377
|
+
*/
|
|
378
|
+
visualizations?: boolean;
|
|
379
|
+
/**
|
|
380
|
+
* Enable WebSocket real-time features for Workshop apps hosted on this instance.
|
|
381
|
+
*
|
|
382
|
+
* Required for apps that use `ws.on()` / `ws.emit()` from {@link AppRuntimeContext}.
|
|
383
|
+
* Activates Venue's WebSocket bridge server, which forwards Brainy entity change
|
|
384
|
+
* events and custom app events to connected clients.
|
|
385
|
+
*
|
|
386
|
+
* Needed for: live dispatch boards, location tracking, in-app chat, real-time
|
|
387
|
+
* inventory updates, collaborative features.
|
|
388
|
+
*/
|
|
389
|
+
realtime?: boolean;
|
|
390
|
+
/**
|
|
391
|
+
* Enable push/email/SMS notifications via the `notify` prop of {@link AppRuntimeContext}.
|
|
392
|
+
*
|
|
393
|
+
* Required for Workshop apps that send notifications to customers or staff.
|
|
394
|
+
* Venue handles delivery via Resend (email), Twilio (SMS), and Web Push (PWA).
|
|
395
|
+
* Includes rate limiting, unsubscribe management, and compliance templates.
|
|
396
|
+
*/
|
|
397
|
+
notifications?: boolean;
|
|
398
|
+
/**
|
|
399
|
+
* Enable the public-facing website with CMS-managed pages, blog, and gallery.
|
|
400
|
+
*
|
|
401
|
+
* Activates the homepage, `/[page]` CMS routes, `/blog`, and the website admin section.
|
|
402
|
+
*
|
|
403
|
+
* **Standalone mode** (without Workshop): uses built-in templates from the kit's
|
|
404
|
+
* `theme` config — business picks a design template and edits content in Venue admin.
|
|
405
|
+
*
|
|
406
|
+
* **With Workshop**: a `website-kit` deployed from Workshop provides custom component
|
|
407
|
+
* templates and a full design system. Venue's page editor still manages content;
|
|
408
|
+
* Workshop controls the visual layer. Progressive enhancement — both modes share
|
|
409
|
+
* the same Brainy content entities.
|
|
410
|
+
*/
|
|
411
|
+
website?: boolean;
|
|
412
|
+
/**
|
|
413
|
+
* Enable recurring subscription billing via Stripe Subscriptions.
|
|
414
|
+
*
|
|
415
|
+
* Activates the subscription plan management admin (`/admin/subscriptions`),
|
|
416
|
+
* customer subscription lifecycle (subscribe, cancel, change plan), and usage
|
|
417
|
+
* metering endpoints. Required for SaaS, retainer, and membership business models.
|
|
418
|
+
*
|
|
419
|
+
* MRR, churn, and ARPU analytics are available in the Financials dashboard
|
|
420
|
+
* when this feature is enabled.
|
|
421
|
+
*/
|
|
422
|
+
subscriptions?: boolean;
|
|
423
|
+
/**
|
|
424
|
+
* Enable the customer support ticketing system.
|
|
425
|
+
*
|
|
426
|
+
* Activates the customer-facing ticket submission portal (`/support`), the
|
|
427
|
+
* admin ticket queue (`/admin/support`), and the knowledge base (`/help`).
|
|
428
|
+
* Support tickets are linked to customer accounts for full context.
|
|
429
|
+
*
|
|
430
|
+
* Enables the `SupportTicketMeta` and `KnowledgeBaseMeta` entity types
|
|
431
|
+
* in the data model.
|
|
432
|
+
*/
|
|
433
|
+
support?: boolean;
|
|
434
|
+
/**
|
|
435
|
+
* Enable the built-in analytics pipeline.
|
|
436
|
+
*
|
|
437
|
+
* Activates event ingestion (page views, conversions, funnel steps), the
|
|
438
|
+
* analytics dashboard (`/admin/analytics`), and the `analytics` service
|
|
439
|
+
* slot on {@link AppServicesContext}. Workshop apps can record domain events
|
|
440
|
+
* via `services.analytics.track()` — Venue aggregates them for admin reporting.
|
|
441
|
+
*
|
|
442
|
+
* Also enables A/B test framework hooks and cohort retention analysis when
|
|
443
|
+
* combined with `subscriptions`.
|
|
444
|
+
*/
|
|
445
|
+
analytics?: boolean;
|
|
446
|
+
/**
|
|
447
|
+
* Enable outbound webhook delivery to external services.
|
|
448
|
+
*
|
|
449
|
+
* Activates the webhook management UI (`/admin/webhooks`), endpoint registration,
|
|
450
|
+
* event subscription per endpoint, and delivery retry logic with exponential backoff.
|
|
451
|
+
* Supports Zapier, Slack, custom HTTP endpoints, and any other webhook consumer.
|
|
452
|
+
*
|
|
453
|
+
* Venue signs all webhook payloads with HMAC-SHA256 using a per-endpoint secret
|
|
454
|
+
* for consumer-side verification.
|
|
455
|
+
*/
|
|
456
|
+
webhooks?: boolean;
|
|
457
|
+
/**
|
|
458
|
+
* Enable API key management for third-party integrations.
|
|
459
|
+
*
|
|
460
|
+
* Activates the API key admin UI (`/admin/api-keys`), key issuance with
|
|
461
|
+
* scope-limited permissions, usage tracking, and key revocation. External systems
|
|
462
|
+
* (scripts, integrations, kiosk devices) authenticate with issued keys.
|
|
463
|
+
*
|
|
464
|
+
* Keys are scoped to a subset of Venue's REST API capabilities — no key can
|
|
465
|
+
* grant more than the issuing admin's own permissions.
|
|
466
|
+
*/
|
|
467
|
+
apiKeys?: boolean;
|
|
468
|
+
/**
|
|
469
|
+
* Enable the scheduled jobs system for time-based automation.
|
|
470
|
+
*
|
|
471
|
+
* Activates the job scheduler UI (`/admin/jobs`), cron expression editor, and
|
|
472
|
+
* job history log. Workshop apps can register named job handlers; Venue's
|
|
473
|
+
* scheduler calls them on the configured schedule.
|
|
474
|
+
*
|
|
475
|
+
* Common uses: daily revenue reports, weekly inventory low-stock digests,
|
|
476
|
+
* subscription renewal reminders, and automated booking confirmation follow-ups.
|
|
477
|
+
*/
|
|
478
|
+
scheduledJobs?: boolean;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
/**
|
|
482
|
+
* Defines a session attribute that staff should log after a booking session.
|
|
483
|
+
*
|
|
484
|
+
* Session attribute definitions are declared per experience type in the kit manifest.
|
|
485
|
+
* The staff UI renders these as a tap-grid of options (for `select`/`multiselect` types)
|
|
486
|
+
* or a text input (for `text` type) in the post-session log form.
|
|
487
|
+
*
|
|
488
|
+
* This generalizes the W&W-specific `candleChoices` pattern across all verticals:
|
|
489
|
+
* - Canvas & Corks: painting name, skill level, medium, color palette
|
|
490
|
+
* - Clay & Co: piece type, glaze colors, firing type
|
|
491
|
+
* - Gather & Grill: dish name, cuisine type, dietary notes
|
|
492
|
+
*
|
|
493
|
+
* @example
|
|
494
|
+
* ```json
|
|
495
|
+
* {
|
|
496
|
+
* "key": "paintingName",
|
|
497
|
+
* "label": "Painting Name",
|
|
498
|
+
* "type": "text",
|
|
499
|
+
* "perGuest": true,
|
|
500
|
+
* "required": true
|
|
501
|
+
* }
|
|
502
|
+
* ```
|
|
503
|
+
*/
|
|
504
|
+
export interface SessionAttributeDefinition {
|
|
505
|
+
/**
|
|
506
|
+
* Unique key matching {@link SessionAttribute.key} in the session log.
|
|
507
|
+
* Must follow camelCase convention. @example "paintingName"
|
|
508
|
+
*/
|
|
509
|
+
key: string;
|
|
510
|
+
/** Human-readable label shown in the staff UI form. @example "Painting Name" */
|
|
511
|
+
label: string;
|
|
512
|
+
/**
|
|
513
|
+
* Input type controlling how the staff UI renders this field:
|
|
514
|
+
* - `'text'` — free-text entry (name, description)
|
|
515
|
+
* - `'select'` — single choice from `options` list (skill level, medium)
|
|
516
|
+
* - `'multiselect'` — multiple choices from `options` list (color palette)
|
|
517
|
+
*/
|
|
518
|
+
type: 'text' | 'select' | 'multiselect';
|
|
519
|
+
/**
|
|
520
|
+
* When `true`, staff logs one value per guest (e.g. painting name per person).
|
|
521
|
+
* When `false`, one value is logged for the entire booking session (e.g. class theme).
|
|
522
|
+
*/
|
|
523
|
+
perGuest: boolean;
|
|
524
|
+
/**
|
|
525
|
+
* Available options for `'select'` and `'multiselect'` input types.
|
|
526
|
+
* Not required for `'text'` type.
|
|
527
|
+
*/
|
|
528
|
+
options?: string[];
|
|
529
|
+
/** Whether the attribute must be filled in before the session log can be saved. */
|
|
530
|
+
required?: boolean;
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
/**
|
|
534
|
+
* A bookable experience type defined by the kit.
|
|
535
|
+
*
|
|
536
|
+
* These are the template definitions that seed creates `ExperienceMeta` entities
|
|
537
|
+
* from. The `slug` becomes the entity's `metadata.slug` field.
|
|
538
|
+
*/
|
|
539
|
+
export interface VenueExperienceType {
|
|
540
|
+
/** URL-safe slug. @example "kandle-experience" */
|
|
541
|
+
slug: string;
|
|
542
|
+
/** Display name. @example "Kandle Experience" */
|
|
543
|
+
name: string;
|
|
544
|
+
/** Marketing description. */
|
|
545
|
+
description: string;
|
|
546
|
+
/** Per-guest price in cents. @example 5500 */
|
|
547
|
+
priceInCents: number;
|
|
548
|
+
/** Duration in minutes. @example 90 */
|
|
549
|
+
durationMinutes: number;
|
|
550
|
+
/** Minimum guest count. */
|
|
551
|
+
minGuests: number;
|
|
552
|
+
/** Maximum guest count. */
|
|
553
|
+
maxGuests: number;
|
|
554
|
+
/** Whether guests must sign a waiver. */
|
|
555
|
+
requiresWaiver: boolean;
|
|
556
|
+
/** Whether this is a combo of multiple experiences. */
|
|
557
|
+
isCombo?: boolean;
|
|
558
|
+
/** Slugs of component experiences (for combos). */
|
|
559
|
+
componentSlugs?: string[];
|
|
560
|
+
/** Display sort order. */
|
|
561
|
+
sortOrder: number;
|
|
562
|
+
/**
|
|
563
|
+
* Color for schedule grid color-coding in OKLCH notation.
|
|
564
|
+
* @example "oklch(0.82 0.10 75)"
|
|
565
|
+
*/
|
|
566
|
+
color?: string;
|
|
567
|
+
/** Hero image URL for the storefront card. */
|
|
568
|
+
imageUrl?: string;
|
|
569
|
+
/**
|
|
570
|
+
* Variable per-guest pricing tiers based on party size (e.g. private events).
|
|
571
|
+
* When present, the booking wizard uses these tiers instead of the flat
|
|
572
|
+
* {@link priceInCents} rate. Tiers must be listed in ascending `minGuests` order.
|
|
573
|
+
*
|
|
574
|
+
* @example
|
|
575
|
+
* ```json
|
|
576
|
+
* [
|
|
577
|
+
* { "minGuests": 4, "maxGuests": 6, "pricePerPersonInCents": 5500 },
|
|
578
|
+
* { "minGuests": 7, "maxGuests": 8, "pricePerPersonInCents": 5000 }
|
|
579
|
+
* ]
|
|
580
|
+
* ```
|
|
581
|
+
*/
|
|
582
|
+
pricingTiers?: Array<{
|
|
583
|
+
/** Minimum number of guests for this tier (inclusive). */
|
|
584
|
+
minGuests: number;
|
|
585
|
+
/** Maximum number of guests for this tier (inclusive). */
|
|
586
|
+
maxGuests: number;
|
|
587
|
+
/** Per-person price in cents for this tier. */
|
|
588
|
+
pricePerPersonInCents: number;
|
|
589
|
+
}>;
|
|
590
|
+
/**
|
|
591
|
+
* Generic post-session attributes staff log for this experience type.
|
|
592
|
+
*
|
|
593
|
+
* Used by non-W&W verticals (paint studios, pottery, cooking classes) to capture
|
|
594
|
+
* experience-specific data without the COGS inventory tracking of `candleChoices`.
|
|
595
|
+
* The staff UI renders a tap-grid form from these definitions after check-in.
|
|
596
|
+
*
|
|
597
|
+
* Leave empty for W&W candle experiences, which use the dedicated `candleChoices` path.
|
|
598
|
+
*/
|
|
599
|
+
sessionAttributeDefinitions?: SessionAttributeDefinition[];
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
/**
|
|
603
|
+
* An inventory category with display label and icon.
|
|
604
|
+
*/
|
|
605
|
+
export interface VenueInventoryCategory {
|
|
606
|
+
/** Category identifier used in `InventoryItemMeta.category`. */
|
|
607
|
+
id: string;
|
|
608
|
+
/** Human-readable display label. */
|
|
609
|
+
label: string;
|
|
610
|
+
/** Optional emoji or icon name for the category. */
|
|
611
|
+
icon?: string;
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
/**
|
|
615
|
+
* A staff role extension beyond the platform defaults.
|
|
616
|
+
*/
|
|
617
|
+
export interface VenueStaffRole {
|
|
618
|
+
/** Role identifier. */
|
|
619
|
+
id: string;
|
|
620
|
+
/** Display label. */
|
|
621
|
+
label: string;
|
|
622
|
+
/** Default capabilities granted to this role. */
|
|
623
|
+
defaultCapabilities?: string[];
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
/**
|
|
627
|
+
* A suggestion chip shown in the customer-facing AI chatbot widget.
|
|
628
|
+
*/
|
|
629
|
+
export interface VenueChatSuggestion {
|
|
630
|
+
/** Button label shown to the customer. */
|
|
631
|
+
label: string;
|
|
632
|
+
/** Pre-filled message sent when the customer clicks this chip. */
|
|
633
|
+
message: string;
|
|
634
|
+
/** Optional emoji decoration for the chip. */
|
|
635
|
+
emoji?: string;
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
/**
|
|
639
|
+
* A built-in back-office role in the Venue platform.
|
|
640
|
+
*
|
|
641
|
+
* These are the three platform-level roles available in the Venue back-office.
|
|
642
|
+
* Custom roles defined in {@link VenueConfig.staffRoles} use colon-namespaced
|
|
643
|
+
* strings (e.g. `'staff:driver'`) and are a superset of this type.
|
|
644
|
+
*/
|
|
645
|
+
export type VenueBackOfficeRole = 'staff' | 'manager' | 'owner';
|
|
646
|
+
|
|
647
|
+
/**
|
|
648
|
+
* Who provides a station's back-end route and logic.
|
|
649
|
+
*
|
|
650
|
+
* - `'platform'` — Venue provides this route natively. Available to any org
|
|
651
|
+
* that enables the associated feature flag; no custom kit logic required.
|
|
652
|
+
* - `'kit'` — This kit contributes a custom route for this station. In Phase 1
|
|
653
|
+
* the route is a built-in Venue SvelteKit page activated only when this kit
|
|
654
|
+
* is active. In Phase 4+ the station ships its own `bundle` — a Svelte 5
|
|
655
|
+
* component module loaded lazily by the admin shell.
|
|
656
|
+
*/
|
|
657
|
+
export type VenueStationScope = 'platform' | 'kit';
|
|
658
|
+
|
|
659
|
+
/**
|
|
660
|
+
* The deployment context a station is relevant to.
|
|
661
|
+
*
|
|
662
|
+
* - `'physical'` — Physical venue with staff, bookings, and on-site operations
|
|
663
|
+
* (e.g. candle studio, escape room). Digital-only orgs will not see these.
|
|
664
|
+
* - `'digital'` — Digital product or service published via Workshop (e.g. SaaS
|
|
665
|
+
* app, subscription offering). Physical-only orgs will not see these.
|
|
666
|
+
* - `'both'` — Relevant to any org regardless of type. Used for shared concerns
|
|
667
|
+
* like analytics, notifications, and settings.
|
|
668
|
+
*/
|
|
669
|
+
export type VenueStationContext = 'physical' | 'digital' | 'both';
|
|
670
|
+
|
|
671
|
+
/**
|
|
672
|
+
* A pluggable back-office section contributed by a kit or the Venue platform.
|
|
673
|
+
*
|
|
674
|
+
* Stations appear in the Venue admin sidebar under their assigned group.
|
|
675
|
+
* Each station declares which staff roles can see it, which route it maps to
|
|
676
|
+
* under `/{org}/admin/`, and whether it applies to physical venues, digital
|
|
677
|
+
* products, or both. The Venue shell filters visible stations at render time
|
|
678
|
+
* based on role, context, and active feature flags.
|
|
679
|
+
*
|
|
680
|
+
* @example
|
|
681
|
+
* ```ts
|
|
682
|
+
* // Platform-provided, physical-only station
|
|
683
|
+
* const checkin: VenueStation = {
|
|
684
|
+
* id: 'staff-checkin', label: 'Check-In', route: 'staff/checkin',
|
|
685
|
+
* icon: 'M9 12.75L11.25 15 15 9.75M21 12a9 9 0 11-18 0 9 9 0 0118 0z',
|
|
686
|
+
* roles: ['staff', 'manager', 'owner'], scope: 'platform', context: 'physical'
|
|
687
|
+
* };
|
|
688
|
+
*
|
|
689
|
+
* // Kit-contributed station (W&W specific — ships its own bundle in Phase 4)
|
|
690
|
+
* const kittens: VenueStation = {
|
|
691
|
+
* id: 'kittens', label: 'Kittens', route: 'kittens',
|
|
692
|
+
* icon: 'M21 8.25c0-2.485-2.099-4.5...',
|
|
693
|
+
* roles: ['manager', 'owner'], scope: 'kit', context: 'physical',
|
|
694
|
+
* bundle: 'stations/kittens.js', group: 'Operations'
|
|
695
|
+
* };
|
|
696
|
+
* ```
|
|
697
|
+
*/
|
|
698
|
+
export interface VenueStation {
|
|
699
|
+
/** Unique identifier for this station within the kit. */
|
|
700
|
+
id: string;
|
|
701
|
+
/** Display label shown in the admin sidebar. */
|
|
702
|
+
label: string;
|
|
703
|
+
/**
|
|
704
|
+
* Route path relative to `/{org}/admin/`.
|
|
705
|
+
* @example "staff/pos" resolves to "/{org}/admin/staff/pos"
|
|
706
|
+
* @example "inventory" resolves to "/{org}/admin/inventory"
|
|
707
|
+
*/
|
|
708
|
+
route: string;
|
|
709
|
+
/**
|
|
710
|
+
* SVG `<path>` data for the sidebar icon, sized for a 24×24 viewBox.
|
|
711
|
+
* The Venue shell wraps this in an `<svg>` element automatically.
|
|
712
|
+
* Multiple subpaths may be concatenated into a single `d` string.
|
|
713
|
+
*/
|
|
714
|
+
icon: string;
|
|
715
|
+
/**
|
|
716
|
+
* Back-office roles that can see and access this station.
|
|
717
|
+
* Roles are checked against the authenticated staff member's platform role.
|
|
718
|
+
*/
|
|
719
|
+
roles: VenueBackOfficeRole[];
|
|
720
|
+
/**
|
|
721
|
+
* Who provides this station's route and logic.
|
|
722
|
+
*
|
|
723
|
+
* - `'platform'` — The route is a built-in Venue page, always available.
|
|
724
|
+
* - `'kit'` — Phase 1: the route is a Venue SvelteKit page activated only
|
|
725
|
+
* for this kit's vertical. Phase 4+: the station ships its own `bundle`.
|
|
726
|
+
*
|
|
727
|
+
* @default 'platform'
|
|
728
|
+
*/
|
|
729
|
+
scope?: VenueStationScope;
|
|
730
|
+
/**
|
|
731
|
+
* The venue context this station applies to.
|
|
732
|
+
* The shell hides stations whose context doesn't match the org type.
|
|
733
|
+
* @default 'both'
|
|
734
|
+
*/
|
|
735
|
+
context?: VenueStationContext;
|
|
736
|
+
/**
|
|
737
|
+
* Path to the station's Svelte 5 component module bundle, relative to the
|
|
738
|
+
* kit's deployed assets directory.
|
|
739
|
+
*
|
|
740
|
+
* When present, the Venue admin shell lazy-loads this bundle and mounts the
|
|
741
|
+
* default-exported component with `{ sdk, config }` props — identical to
|
|
742
|
+
* how Workshop apps are mounted. When absent, the shell uses the built-in
|
|
743
|
+
* SvelteKit route at the declared `route` path.
|
|
744
|
+
*
|
|
745
|
+
* @example "stations/kittens.js"
|
|
746
|
+
* @since Phase 4 (kit migration to Svelte 5 modules)
|
|
747
|
+
*/
|
|
748
|
+
bundle?: string;
|
|
749
|
+
/**
|
|
750
|
+
* Optional sidebar group label for grouping related stations.
|
|
751
|
+
* @example "Staff" | "Operations" | "Business" | "Settings"
|
|
752
|
+
*/
|
|
753
|
+
group?: string;
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
/**
|
|
757
|
+
* Venue-specific fields in a kit manifest.
|
|
758
|
+
*
|
|
759
|
+
* Nested under the `venue` key in the kit.json manifest. These fields configure
|
|
760
|
+
* the platform for a specific experience-based business vertical.
|
|
761
|
+
*/
|
|
762
|
+
export interface VenueConfig {
|
|
763
|
+
/** Bookable experience types available at this kind of venue. */
|
|
764
|
+
experienceTypes: VenueExperienceType[];
|
|
765
|
+
/** Feature flags controlling which platform capabilities are enabled. */
|
|
766
|
+
features: VenueFeatures;
|
|
767
|
+
/**
|
|
768
|
+
* Default brand theme applied at onboarding (customizable by the business owner).
|
|
769
|
+
* Optional for extension kits that augment a primary kit without defining a theme.
|
|
770
|
+
*/
|
|
771
|
+
theme?: VenueKitTheme;
|
|
772
|
+
/** Inventory categories relevant to this vertical. */
|
|
773
|
+
inventoryCategories?: VenueInventoryCategory[];
|
|
774
|
+
/** Additional staff roles beyond the platform defaults (staff, manager, owner). */
|
|
775
|
+
staffRoles?: VenueStaffRole[];
|
|
776
|
+
/**
|
|
777
|
+
* Two-letter booking number prefix.
|
|
778
|
+
* @example "WW" → booking numbers like "WW-2026-00145"
|
|
779
|
+
*/
|
|
780
|
+
bookingNumberPrefix?: string;
|
|
781
|
+
/**
|
|
782
|
+
* Prefix for the deployment subdomain on the shared hosting tier.
|
|
783
|
+
* @example "wicks" → "wicks.venue.soulcraft.com"
|
|
784
|
+
*/
|
|
785
|
+
subdomainPrefix?: string;
|
|
786
|
+
/** Suggestion chips for the customer-facing AI chatbot. */
|
|
787
|
+
chatSuggestions?: VenueChatSuggestion[];
|
|
788
|
+
/**
|
|
789
|
+
* Default inventory level detection mode for the `/inventory-scan` vision AI skill.
|
|
790
|
+
*
|
|
791
|
+
* - `'vision'` — Containers are clear or frosted; AI estimates fill levels from photo automatically.
|
|
792
|
+
* Best for: frosted-glass scent bottles (new W&W franchise spec), wine/liquor bottles,
|
|
793
|
+
* clear ingredient jars, mixology studios, paint bottles.
|
|
794
|
+
* - `'manual'` — Containers are opaque (e.g. amber glass); AI reads labels only, then prompts
|
|
795
|
+
* staff to tap Full/Half/Low for each item. Used for legacy W&W with existing amber bottles.
|
|
796
|
+
* - `'hybrid'` — AI auto-detects levels where possible; prompts manual input only for items
|
|
797
|
+
* where the liquid line isn't visible. Default for mixed-container setups.
|
|
798
|
+
*
|
|
799
|
+
* Staff can always override the mode at scan time regardless of kit default.
|
|
800
|
+
*
|
|
801
|
+
* @default 'hybrid'
|
|
802
|
+
*/
|
|
803
|
+
inventoryLevelDetection?: 'vision' | 'manual' | 'hybrid';
|
|
804
|
+
/**
|
|
805
|
+
* Back-office stations contributed by this kit.
|
|
806
|
+
*
|
|
807
|
+
* Stations appear in the Venue admin sidebar and map to routes under `/{org}/admin/`.
|
|
808
|
+
* The Venue shell renders visible stations based on the authenticated staff role.
|
|
809
|
+
* When omitted, no custom stations are added (the platform's built-in navigation is used).
|
|
810
|
+
*/
|
|
811
|
+
stations?: VenueStation[];
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
/**
|
|
815
|
+
* A complete Venue kit manifest — the `kit.json` for a Soulcraft Venue kit.
|
|
816
|
+
*
|
|
817
|
+
* @example
|
|
818
|
+
* ```ts
|
|
819
|
+
* const kit: VenueKitConfig = {
|
|
820
|
+
* id: 'wicks-and-whiskers',
|
|
821
|
+
* type: 'venue',
|
|
822
|
+
* name: 'Wicks & Whiskers',
|
|
823
|
+
* description: 'Candle-making + kitten lounge experience platform',
|
|
824
|
+
* version: '1.0.0',
|
|
825
|
+
* author: { name: 'Soulcraft Labs', email: 'kits@soulcraft.com' },
|
|
826
|
+
* variables: [...],
|
|
827
|
+
* venue: {
|
|
828
|
+
* features: { animals: true, adoption: true, memories: true, ... },
|
|
829
|
+
* theme: { primary: 'oklch(0.72 0.15 25)', ... },
|
|
830
|
+
* experienceTypes: [...],
|
|
831
|
+
* }
|
|
832
|
+
* };
|
|
833
|
+
* ```
|
|
834
|
+
*/
|
|
835
|
+
export interface VenueKitConfig extends BaseKitManifest {
|
|
836
|
+
/** Discriminant identifying this as a Venue kit. */
|
|
837
|
+
type: 'venue';
|
|
838
|
+
/** User-configurable variables substituted into template files at onboarding. */
|
|
839
|
+
variables: KitVariable[];
|
|
840
|
+
/** Venue-specific configuration block. */
|
|
841
|
+
venue: VenueConfig;
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
// ──────────────────────────────────────────────
|
|
845
|
+
// Workshop kit (Soulcraft Workshop product)
|
|
846
|
+
// ──────────────────────────────────────────────
|
|
847
|
+
|
|
848
|
+
/**
|
|
849
|
+
* Explore view types available in Workshop's ExplorePanel visualization.
|
|
850
|
+
*/
|
|
851
|
+
export type WorkshopExploreView =
|
|
852
|
+
| 'graph'
|
|
853
|
+
| 'mindmap'
|
|
854
|
+
| 'timeline'
|
|
855
|
+
| 'board'
|
|
856
|
+
| 'matrix'
|
|
857
|
+
| 'gallery'
|
|
858
|
+
| 'calendar'
|
|
859
|
+
| 'tree'
|
|
860
|
+
| 'stats'
|
|
861
|
+
| 'map'
|
|
862
|
+
| 'dev'
|
|
863
|
+
| 'app';
|
|
864
|
+
|
|
865
|
+
/**
|
|
866
|
+
* Workspace paradigm presets controlling the first-open experience in Workshop.
|
|
867
|
+
*/
|
|
868
|
+
export type WorkshopWorkspaceParadigm =
|
|
869
|
+
| 'writer' // Editor-centric, file tree, word count
|
|
870
|
+
| 'researcher' // Graph + Matrix, citations, synthesis
|
|
871
|
+
| 'planner' // Calendar + Board, timeline focus
|
|
872
|
+
| 'developer' // Code + Graph, dependencies
|
|
873
|
+
| 'creative' // Gallery + Graph, visual references
|
|
874
|
+
| 'analyst' // Stats + Matrix, data focus
|
|
875
|
+
| 'builder' // App-centric, live preview, component tree
|
|
876
|
+
| 'custom'; // Fully custom configuration
|
|
877
|
+
|
|
878
|
+
/**
|
|
879
|
+
* Workspace layout and view configuration for a Workshop kit's first-open experience.
|
|
880
|
+
*/
|
|
881
|
+
export interface WorkshopWorkspaceConfig {
|
|
882
|
+
/** Use a preset paradigm (applies sensible defaults). */
|
|
883
|
+
paradigm?: WorkshopWorkspaceParadigm;
|
|
884
|
+
/** Which tab opens first: 'edit' (Editor), 'explore' (Visualizations), or 'app' (embedded app view). */
|
|
885
|
+
defaultTab?: 'edit' | 'explore' | 'app';
|
|
886
|
+
/** Default view within the Explore tab. */
|
|
887
|
+
defaultView?: WorkshopExploreView;
|
|
888
|
+
/** File to open in Editor tab on first load (supports {{variables}}). */
|
|
889
|
+
defaultFile?: string;
|
|
890
|
+
/** Fallback files if defaultFile doesn't exist. */
|
|
891
|
+
fallbackFiles?: string[];
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
/**
|
|
895
|
+
* AI persona giving the assistant domain expertise for a Workshop kit type.
|
|
896
|
+
*/
|
|
897
|
+
export interface WorkshopAIPersona {
|
|
898
|
+
/** Role description, e.g. "You are an experienced screenwriter..." */
|
|
899
|
+
role: string;
|
|
900
|
+
/** Areas of expertise, e.g. ["three-act structure", "character arcs"]. */
|
|
901
|
+
expertise: string[];
|
|
902
|
+
/** Interaction style. */
|
|
903
|
+
tone: 'mentor' | 'editor' | 'collaborator' | 'assistant';
|
|
904
|
+
/** Things the AI should NOT do, e.g. ["Don't rewrite without asking"]. */
|
|
905
|
+
avoidances?: string[];
|
|
906
|
+
}
|
|
907
|
+
|
|
908
|
+
/**
|
|
909
|
+
* Domain knowledge that embeds expertise the AI can reference in a Workshop kit.
|
|
910
|
+
*/
|
|
911
|
+
export interface WorkshopDomainKnowledge {
|
|
912
|
+
/** Term definitions for the domain glossary. */
|
|
913
|
+
glossary?: Record<string, string>;
|
|
914
|
+
/** Industry best practices. */
|
|
915
|
+
conventions?: string[];
|
|
916
|
+
/** Common mistakes to avoid. */
|
|
917
|
+
antiPatterns?: string[];
|
|
918
|
+
/** Format rules for this domain. */
|
|
919
|
+
formatting?: string[];
|
|
920
|
+
/** References and external resources. */
|
|
921
|
+
references?: Array<{
|
|
922
|
+
title: string;
|
|
923
|
+
description: string;
|
|
924
|
+
url?: string;
|
|
925
|
+
}>;
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
/**
|
|
929
|
+
* A pre-defined workflow the AI can execute within a Workshop kit.
|
|
930
|
+
*/
|
|
931
|
+
export interface WorkshopWorkflow {
|
|
932
|
+
/** Unique identifier for this workflow. */
|
|
933
|
+
id: string;
|
|
934
|
+
/** Display name, e.g. "Develop Character". */
|
|
935
|
+
name: string;
|
|
936
|
+
/** What this workflow accomplishes. */
|
|
937
|
+
description: string;
|
|
938
|
+
/** Step-by-step instructions for the AI. */
|
|
939
|
+
steps: string[];
|
|
940
|
+
/** Required inputs for this workflow. */
|
|
941
|
+
inputs?: Array<{
|
|
942
|
+
name: string;
|
|
943
|
+
description: string;
|
|
944
|
+
required?: boolean;
|
|
945
|
+
}>;
|
|
946
|
+
/** What gets created or modified on completion. */
|
|
947
|
+
outputs?: string[];
|
|
948
|
+
/** Keywords that suggest this workflow. */
|
|
949
|
+
triggers?: string[];
|
|
950
|
+
/** Whether to auto-run (true) or confirm steps with user (false). */
|
|
951
|
+
autoExecute?: boolean;
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
/**
|
|
955
|
+
* Guidance for knowledge graph operations within a Workshop kit.
|
|
956
|
+
*/
|
|
957
|
+
export interface WorkshopGraphGuidance {
|
|
958
|
+
/** When and how to create new concepts. */
|
|
959
|
+
conceptCreation?: {
|
|
960
|
+
/** Conditions that trigger concept creation. Optional — typeMapping alone is sufficient. */
|
|
961
|
+
triggers?: string[];
|
|
962
|
+
/** Maps domain terms to graph entity types. @example { "character": "person" } */
|
|
963
|
+
typeMapping: Record<string, string>;
|
|
964
|
+
};
|
|
965
|
+
/** Relationship patterns to encourage in the graph. */
|
|
966
|
+
relationshipPatterns?: Array<{
|
|
967
|
+
from: string;
|
|
968
|
+
to: string;
|
|
969
|
+
verb: string;
|
|
970
|
+
description: string;
|
|
971
|
+
}>;
|
|
972
|
+
/** Graph integrity rules, e.g. "Every character should link to at least one scene". */
|
|
973
|
+
rules?: string[];
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
/**
|
|
977
|
+
* Quality gates defining what "complete" looks like for a Workshop kit project.
|
|
978
|
+
*/
|
|
979
|
+
export interface WorkshopQualityGates {
|
|
980
|
+
/** Per-file content requirements. */
|
|
981
|
+
fileChecks?: Array<{
|
|
982
|
+
path: string;
|
|
983
|
+
required?: string[];
|
|
984
|
+
optional?: string[];
|
|
985
|
+
}>;
|
|
986
|
+
/** Project-level requirements. */
|
|
987
|
+
projectChecks?: string[];
|
|
988
|
+
/** Requirements that must pass before export/publish. */
|
|
989
|
+
exportReady?: string[];
|
|
990
|
+
}
|
|
991
|
+
|
|
992
|
+
/**
|
|
993
|
+
* Export handler definition within a Workshop kit.
|
|
994
|
+
*
|
|
995
|
+
* The `handler` field references a built-in handler ID (e.g. "manuscript-docx",
|
|
996
|
+
* "markdown-bundle"). Handler implementations live in Workshop's export registry,
|
|
997
|
+
* not in this shared package.
|
|
998
|
+
*/
|
|
999
|
+
export interface WorkshopExporter {
|
|
1000
|
+
/** Unique ID for this exporter. */
|
|
1001
|
+
id: string;
|
|
1002
|
+
/** Display name, e.g. "Manuscript (Word)". */
|
|
1003
|
+
name: string;
|
|
1004
|
+
/** What this export produces. */
|
|
1005
|
+
description: string;
|
|
1006
|
+
/** Emoji icon. */
|
|
1007
|
+
icon: string;
|
|
1008
|
+
/** File extension, e.g. "docx", "pdf", "epub". */
|
|
1009
|
+
format: string;
|
|
1010
|
+
/** Export category for grouping in the export dialog. */
|
|
1011
|
+
category: 'manuscript' | 'ebook' | 'archive' | 'web' | 'document' | 'data' | 'presentation' | 'other';
|
|
1012
|
+
/** Built-in handler ID registered in Workshop's export registry. */
|
|
1013
|
+
handler: string;
|
|
1014
|
+
}
|
|
1015
|
+
|
|
1016
|
+
/**
|
|
1017
|
+
* Export preferences and defaults for a Workshop kit.
|
|
1018
|
+
*/
|
|
1019
|
+
export interface WorkshopExportPreferences {
|
|
1020
|
+
/** Default exporter ID to show first in the export dialog. */
|
|
1021
|
+
defaultExporter?: string;
|
|
1022
|
+
/** Kit for output filename (supports {{variables}}). */
|
|
1023
|
+
fileNameTemplate?: string;
|
|
1024
|
+
/** General export instructions shown to the user. */
|
|
1025
|
+
instructions?: string;
|
|
1026
|
+
/** Quality gates that must pass before any export. */
|
|
1027
|
+
globalPrerequisites?: string[];
|
|
1028
|
+
}
|
|
1029
|
+
|
|
1030
|
+
/**
|
|
1031
|
+
* Configuration for how to order/combine multiple files when exporting.
|
|
1032
|
+
*/
|
|
1033
|
+
export interface WorkshopExportStructure {
|
|
1034
|
+
/** How to determine file order: by graph relationships, path, or manual list. */
|
|
1035
|
+
combineStrategy: 'graph-order' | 'path-order' | 'manual';
|
|
1036
|
+
/** Relationship type to use for ordering (e.g. 'precedes') when using graph-order. */
|
|
1037
|
+
orderRelationship?: string;
|
|
1038
|
+
/** Glob patterns for files to include. */
|
|
1039
|
+
includePatterns?: string[];
|
|
1040
|
+
/** Glob patterns for files to exclude. */
|
|
1041
|
+
excludePatterns?: string[];
|
|
1042
|
+
/** Manual file order (when using manual strategy). */
|
|
1043
|
+
fileOrder?: string[];
|
|
1044
|
+
}
|
|
1045
|
+
|
|
1046
|
+
/**
|
|
1047
|
+
* Suggestion chip shown on Workshop's AI chat intro screen.
|
|
1048
|
+
*
|
|
1049
|
+
* @deprecated Use {@link KitSuggestion} instead. `WorkshopSuggestion` is now an
|
|
1050
|
+
* alias for the cross-product `KitSuggestion` type. The field has moved from
|
|
1051
|
+
* `WorkshopConfig.suggestions` to `SharedKitFoundation.suggestions`.
|
|
1052
|
+
*
|
|
1053
|
+
* @example
|
|
1054
|
+
* ```json
|
|
1055
|
+
* { "label": "Add a recipe", "prompt": "Add a new recipe to my cookbook" }
|
|
1056
|
+
* ```
|
|
1057
|
+
*/
|
|
1058
|
+
export type WorkshopSuggestion = KitSuggestion;
|
|
1059
|
+
|
|
1060
|
+
/**
|
|
1061
|
+
* A single field definition in a `manifest.json` config schema.
|
|
1062
|
+
*
|
|
1063
|
+
* `ManifestConfigField` drives Venue's admin config editor for a deployed app.
|
|
1064
|
+
* Venue renders a typed form control for each field and persists the user's values
|
|
1065
|
+
* as the app's runtime config, merging them over the manifest defaults.
|
|
1066
|
+
*
|
|
1067
|
+
* @example
|
|
1068
|
+
* ```ts
|
|
1069
|
+
* const field: ManifestConfigField = {
|
|
1070
|
+
* type: 'select',
|
|
1071
|
+
* label: 'Primary Language',
|
|
1072
|
+
* default: 'en',
|
|
1073
|
+
* options: ['en', 'es', 'fr'],
|
|
1074
|
+
* description: 'Default language used by the AI assistant'
|
|
1075
|
+
* };
|
|
1076
|
+
* ```
|
|
1077
|
+
*/
|
|
1078
|
+
export interface ManifestConfigField {
|
|
1079
|
+
/** Input type — determines the form control rendered in Venue's admin panel. */
|
|
1080
|
+
type: 'string' | 'number' | 'boolean' | 'select';
|
|
1081
|
+
/** Default value applied when the admin has not overridden this field. */
|
|
1082
|
+
default?: string | number | boolean;
|
|
1083
|
+
/** Allowed values for `type: 'select'` fields. */
|
|
1084
|
+
options?: string[];
|
|
1085
|
+
/** Human-readable label shown in Venue's admin config editor. */
|
|
1086
|
+
label?: string;
|
|
1087
|
+
/** Explanatory text shown below the form control. */
|
|
1088
|
+
description?: string;
|
|
1089
|
+
}
|
|
1090
|
+
|
|
1091
|
+
/**
|
|
1092
|
+
* Configuration for publishing a Workshop kit's output to Venue.
|
|
1093
|
+
*
|
|
1094
|
+
* When a kit is publishable, Workshop's publish flow calls Venue's `POST /api/deploy`
|
|
1095
|
+
* endpoint with a {@link PublishPayload}. The content type here determines which
|
|
1096
|
+
* renderer Venue uses to serve the published content.
|
|
1097
|
+
*
|
|
1098
|
+
* The three new fields — `permissions`, `configSchema`, `adminConfig` — are used by
|
|
1099
|
+
* Workshop's `buildVenueAppBundle()` to generate `manifest.json` alongside `bundle.js`.
|
|
1100
|
+
* Venue validates permissions at deploy time and uses configSchema to drive its admin
|
|
1101
|
+
* config editor.
|
|
1102
|
+
*/
|
|
1103
|
+
export interface WorkshopPublishConfig {
|
|
1104
|
+
/** The type of content this kit produces when published to Venue. */
|
|
1105
|
+
contentType: 'app' | 'document' | 'visualization' | 'slideshow' | 'static';
|
|
1106
|
+
/** Whether content from this kit can be published to Venue. @default false */
|
|
1107
|
+
publishable?: boolean;
|
|
1108
|
+
/** Default URL slug for the published content. */
|
|
1109
|
+
defaultSlug?: string;
|
|
1110
|
+
/**
|
|
1111
|
+
* Entry Svelte component for Venue app deployment.
|
|
1112
|
+
* Workshop's buildVenueAppBundle() compiles this component to a single ES module.
|
|
1113
|
+
* Path is relative to the project root (e.g. 'src/App.svelte').
|
|
1114
|
+
* Only applies when contentType is 'app'.
|
|
1115
|
+
* @default 'src/App.svelte'
|
|
1116
|
+
*/
|
|
1117
|
+
appEntry?: string;
|
|
1118
|
+
/**
|
|
1119
|
+
* Platform permissions the app requires at runtime.
|
|
1120
|
+
*
|
|
1121
|
+
* Venue validates this list at deploy time and rejects any unknown permission
|
|
1122
|
+
* strings with HTTP 422. At runtime, SDK calls that require a permission not
|
|
1123
|
+
* declared here are rejected with HTTP 403.
|
|
1124
|
+
*
|
|
1125
|
+
* Default permissions by content type (applied when this field is omitted):
|
|
1126
|
+
* - `app`: `['data:read', 'data:write']`
|
|
1127
|
+
* - `document`: `['data:read', 'vfs:read']`
|
|
1128
|
+
* - `static`: `[]` (no runtime permissions)
|
|
1129
|
+
*
|
|
1130
|
+
* @example `['data:read', 'data:write', 'media:read']`
|
|
1131
|
+
*/
|
|
1132
|
+
permissions?: string[];
|
|
1133
|
+
/**
|
|
1134
|
+
* Config schema for Venue's admin config editor.
|
|
1135
|
+
*
|
|
1136
|
+
* Each key maps to one admin-editable field. Venue renders a typed form control
|
|
1137
|
+
* for each field and merges admin-set values over the manifest defaults at runtime.
|
|
1138
|
+
* The merged config is passed to the app as the `config` prop via `createSDK()`.
|
|
1139
|
+
*
|
|
1140
|
+
* @example
|
|
1141
|
+
* ```ts
|
|
1142
|
+
* configSchema: {
|
|
1143
|
+
* theme: { type: 'select', label: 'Color Theme', default: 'light', options: ['light', 'dark'] },
|
|
1144
|
+
* maxItems: { type: 'number', label: 'Max Items Per Page', default: 20 }
|
|
1145
|
+
* }
|
|
1146
|
+
* ```
|
|
1147
|
+
*/
|
|
1148
|
+
configSchema?: Record<string, ManifestConfigField>;
|
|
1149
|
+
/**
|
|
1150
|
+
* Admin panel configuration for this app's Venue presence.
|
|
1151
|
+
*
|
|
1152
|
+
* - `dashboard`: Whether to show a summary dashboard card in Venue admin. @default true for 'app'
|
|
1153
|
+
* - `settings`: Whether to render a settings page driven by `configSchema`. @default true when configSchema is non-empty
|
|
1154
|
+
* - `stations`: Kit-scoped station IDs whose bundles are included in this deploy.
|
|
1155
|
+
* Each ID maps to `build/stations/{id}.js` in the deploy payload.
|
|
1156
|
+
*/
|
|
1157
|
+
adminConfig?: {
|
|
1158
|
+
/** Show a summary dashboard card in Venue admin. @default true for app contentType */
|
|
1159
|
+
dashboard?: boolean;
|
|
1160
|
+
/** Render a settings page driven by configSchema. @default true when configSchema is non-empty */
|
|
1161
|
+
settings?: boolean;
|
|
1162
|
+
/** Kit-scoped station IDs bundled alongside this app. Maps to build/stations/{id}.js */
|
|
1163
|
+
stations?: string[];
|
|
1164
|
+
};
|
|
1165
|
+
}
|
|
1166
|
+
|
|
1167
|
+
/**
|
|
1168
|
+
* A pre-built workbench that Workshop creates when connected to a live Venue location.
|
|
1169
|
+
*
|
|
1170
|
+
* Each connected workbench is a named Workshop view scoped to specific entity types
|
|
1171
|
+
* from the live Venue Brainy instance. Defined in `workshop.remoteWorkspace.connectedWorkbenches`
|
|
1172
|
+
* inside `kit.json`.
|
|
1173
|
+
*
|
|
1174
|
+
* @example
|
|
1175
|
+
* ```json
|
|
1176
|
+
* {
|
|
1177
|
+
* "name": "Order Explorer",
|
|
1178
|
+
* "view": "graph",
|
|
1179
|
+
* "entityTypes": ["order", "customer", "product"],
|
|
1180
|
+
* "description": "Visualize order-to-customer relationships"
|
|
1181
|
+
* }
|
|
1182
|
+
* ```
|
|
1183
|
+
*/
|
|
1184
|
+
export interface WorkshopConnectedWorkbench {
|
|
1185
|
+
/** Display name shown in Workshop's workbench switcher. */
|
|
1186
|
+
name: string;
|
|
1187
|
+
/**
|
|
1188
|
+
* Explore view type to open for this workbench.
|
|
1189
|
+
* Matches Workshop's ExploreView discriminant.
|
|
1190
|
+
*/
|
|
1191
|
+
view: 'graph' | 'mindmap' | 'tree' | 'timeline' | 'board' | 'gallery' | 'stats' | 'matrix' | 'calendar';
|
|
1192
|
+
/**
|
|
1193
|
+
* Brainy entity types to load from the live Venue instance.
|
|
1194
|
+
* Maps to `NounType` values in the connected Brainy graph.
|
|
1195
|
+
*/
|
|
1196
|
+
entityTypes: string[];
|
|
1197
|
+
/** Optional description shown below the workbench name. */
|
|
1198
|
+
description?: string;
|
|
1199
|
+
}
|
|
1200
|
+
|
|
1201
|
+
/**
|
|
1202
|
+
* Configuration for Workshop's Remote Session mode.
|
|
1203
|
+
*
|
|
1204
|
+
* When a Workshop project has a `.venue-link.json` file (written at deploy time),
|
|
1205
|
+
* Workshop can connect to the live Venue Brainy instance for full read+write access.
|
|
1206
|
+
* The `remoteWorkspace` block defines which workbenches Workshop pre-builds
|
|
1207
|
+
* from that live data.
|
|
1208
|
+
*
|
|
1209
|
+
* Remote Session phases:
|
|
1210
|
+
* - **Phase 1** (`.venue-link.json`): Link file in VFS project root, written at deploy.
|
|
1211
|
+
* - **Phase 2** (Remote Session): WebSocket Brainy proxy — Workshop reads/writes live Venue data.
|
|
1212
|
+
* - **Phase 3** (Hot-patch): `PATCH /api/apps/{slug}/bundle` — push updated bundle without full re-deploy.
|
|
1213
|
+
*/
|
|
1214
|
+
export interface WorkshopRemoteWorkspace {
|
|
1215
|
+
/**
|
|
1216
|
+
* Workbenches to open automatically when connecting to the live Venue location.
|
|
1217
|
+
* Each workbench queries specific entity types from the Venue Brainy instance.
|
|
1218
|
+
*/
|
|
1219
|
+
connectedWorkbenches?: WorkshopConnectedWorkbench[];
|
|
1220
|
+
}
|
|
1221
|
+
|
|
1222
|
+
/**
|
|
1223
|
+
* Template identity metadata used by Workshop to recognise and configure kit projects.
|
|
1224
|
+
*
|
|
1225
|
+
* @example
|
|
1226
|
+
* ```json
|
|
1227
|
+
* { "identifyByStructure": true, "runnable": true, "runnableCommand": "npm run dev" }
|
|
1228
|
+
* ```
|
|
1229
|
+
*/
|
|
1230
|
+
export interface WorkshopTemplateMetadata {
|
|
1231
|
+
/**
|
|
1232
|
+
* When `true`, Workshop infers the project is an existing instance of this kit
|
|
1233
|
+
* by inspecting its file structure rather than requiring an explicit manifest link.
|
|
1234
|
+
*/
|
|
1235
|
+
identifyByStructure?: boolean;
|
|
1236
|
+
/** Whether this kit produces a runnable application. */
|
|
1237
|
+
runnable?: boolean;
|
|
1238
|
+
/**
|
|
1239
|
+
* Shell command to start the application locally.
|
|
1240
|
+
* Shown in Workshop's run panel when `runnable` is `true`.
|
|
1241
|
+
* @example "npm run dev"
|
|
1242
|
+
*/
|
|
1243
|
+
runnableCommand?: string;
|
|
1244
|
+
}
|
|
1245
|
+
|
|
1246
|
+
/**
|
|
1247
|
+
* Cloud deployment configuration for Workshop kits that produce runnable applications.
|
|
1248
|
+
*
|
|
1249
|
+
* @example
|
|
1250
|
+
* ```json
|
|
1251
|
+
* {
|
|
1252
|
+
* "provider": "cloud-run",
|
|
1253
|
+
* "buildCommand": "npm run build",
|
|
1254
|
+
* "outputDir": "build",
|
|
1255
|
+
* "config": { "port": 3000, "memory": "512Mi" }
|
|
1256
|
+
* }
|
|
1257
|
+
* ```
|
|
1258
|
+
*/
|
|
1259
|
+
export interface WorkshopDeployConfig {
|
|
1260
|
+
/** Cloud provider identifier. @example "cloud-run" | "vercel" | "netlify" */
|
|
1261
|
+
provider?: string;
|
|
1262
|
+
/** Build command that produces deployable artifacts. @example "npm run build" */
|
|
1263
|
+
buildCommand?: string;
|
|
1264
|
+
/** Output directory for build artifacts. @example "build" | "dist" | ".svelte-kit/output" */
|
|
1265
|
+
outputDir?: string;
|
|
1266
|
+
/** Provider-specific configuration (e.g. memory limits, port, environment vars). */
|
|
1267
|
+
config?: Record<string, unknown>;
|
|
1268
|
+
/** One-click deploy command shown in Workshop's deploy panel. @example "gcloud run deploy" */
|
|
1269
|
+
oneClickCommand?: string;
|
|
1270
|
+
}
|
|
1271
|
+
|
|
1272
|
+
/**
|
|
1273
|
+
* A sample entity for pre-populating a Workshop project with demonstration data.
|
|
1274
|
+
*
|
|
1275
|
+
* Entity types correspond to Brainy NounTypes (`document`, `thing`, `person`, `event`, etc.).
|
|
1276
|
+
*/
|
|
1277
|
+
export interface WorkshopSampleEntity {
|
|
1278
|
+
/** Brainy entity type (NounType). @example "document" | "thing" | "person" | "event" */
|
|
1279
|
+
type: string;
|
|
1280
|
+
/** Display name for the entity. */
|
|
1281
|
+
name: string;
|
|
1282
|
+
/** Arbitrary entity properties stored in Brainy `metadata`. */
|
|
1283
|
+
properties?: Record<string, unknown>;
|
|
1284
|
+
}
|
|
1285
|
+
|
|
1286
|
+
/**
|
|
1287
|
+
* A relationship between two sample entities in a Workshop project's seed graph.
|
|
1288
|
+
*/
|
|
1289
|
+
export interface WorkshopSampleRelationship {
|
|
1290
|
+
/** Name of the source entity (must match a name in the `entities` array). */
|
|
1291
|
+
from: string;
|
|
1292
|
+
/** Relationship verb (VerbType). @example "contains" | "uses" | "precedes" */
|
|
1293
|
+
verb: string;
|
|
1294
|
+
/** Name of the target entity (must match a name in the `entities` array). */
|
|
1295
|
+
to: string;
|
|
1296
|
+
}
|
|
1297
|
+
|
|
1298
|
+
/**
|
|
1299
|
+
* Sample data to seed a new Workshop project for demonstration or onboarding.
|
|
1300
|
+
*
|
|
1301
|
+
* When present, Workshop creates these entities and relationships in a new
|
|
1302
|
+
* project's Brainy graph during the "Try with sample data" flow. Sample data
|
|
1303
|
+
* lets new users experience the kit's knowledge graph before adding their own content.
|
|
1304
|
+
*
|
|
1305
|
+
* @example
|
|
1306
|
+
* ```json
|
|
1307
|
+
* {
|
|
1308
|
+
* "description": "Sample recipes demonstrating the app features",
|
|
1309
|
+
* "entities": [{ "type": "document", "name": "Pasta Carbonara", "properties": {} }],
|
|
1310
|
+
* "relationships": [{ "from": "Pasta Carbonara", "verb": "contains", "to": "Spaghetti" }]
|
|
1311
|
+
* }
|
|
1312
|
+
* ```
|
|
1313
|
+
*/
|
|
1314
|
+
export interface WorkshopSampleData {
|
|
1315
|
+
/** Human-readable description of what this sample dataset represents. */
|
|
1316
|
+
description?: string;
|
|
1317
|
+
/** Entities to create in the new project's Brainy graph. */
|
|
1318
|
+
entities: WorkshopSampleEntity[];
|
|
1319
|
+
/** Relationships to create between the sample entities. */
|
|
1320
|
+
relationships?: WorkshopSampleRelationship[];
|
|
1321
|
+
}
|
|
1322
|
+
|
|
1323
|
+
/**
|
|
1324
|
+
* Workshop-specific fields in a kit manifest.
|
|
1325
|
+
*
|
|
1326
|
+
* These fields power Workshop's AI collaboration, workspace configuration,
|
|
1327
|
+
* knowledge graph guidance, export system, and publish-to-Venue flow.
|
|
1328
|
+
* Nested under the `workshop` key in kit.json.
|
|
1329
|
+
*/
|
|
1330
|
+
export interface WorkshopConfig {
|
|
1331
|
+
/** Workspace layout and first-open experience configuration. */
|
|
1332
|
+
workspaceConfig?: WorkshopWorkspaceConfig;
|
|
1333
|
+
/** Guidance for the AI assistant's knowledge graph operations. */
|
|
1334
|
+
graphGuidance?: WorkshopGraphGuidance;
|
|
1335
|
+
/** Quality gates defining project completion criteria. */
|
|
1336
|
+
qualityGates?: WorkshopQualityGates;
|
|
1337
|
+
/** Configuration for publishing this kit's content to Venue. */
|
|
1338
|
+
publishConfig?: WorkshopPublishConfig;
|
|
1339
|
+
/** AI persona giving the assistant domain expertise for this kit type. */
|
|
1340
|
+
aiPersona?: WorkshopAIPersona;
|
|
1341
|
+
/** Domain knowledge the AI can reference (glossary, conventions, anti-patterns). */
|
|
1342
|
+
domainKnowledge?: WorkshopDomainKnowledge;
|
|
1343
|
+
/** Pre-defined workflows the AI can execute. */
|
|
1344
|
+
workflows?: WorkshopWorkflow[];
|
|
1345
|
+
/** Export handlers available for this kit's content. */
|
|
1346
|
+
exporters?: WorkshopExporter[];
|
|
1347
|
+
/** Export preferences and defaults. */
|
|
1348
|
+
exportPreferences?: WorkshopExportPreferences;
|
|
1349
|
+
/**
|
|
1350
|
+
* Configuration for combining multiple files into a single export
|
|
1351
|
+
* (using knowledge graph for ordering).
|
|
1352
|
+
*/
|
|
1353
|
+
exportStructure?: WorkshopExportStructure;
|
|
1354
|
+
/**
|
|
1355
|
+
* Remote Session configuration.
|
|
1356
|
+
* Defines which workbenches Workshop pre-builds when connecting to a live Venue deployment.
|
|
1357
|
+
* Only relevant for `app`-type kits that will be deployed to Venue.
|
|
1358
|
+
*/
|
|
1359
|
+
remoteWorkspace?: WorkshopRemoteWorkspace;
|
|
1360
|
+
/**
|
|
1361
|
+
* Experience difficulty level, used in the kit gallery to filter by skill level.
|
|
1362
|
+
* @example 'beginner' | 'intermediate' | 'advanced'
|
|
1363
|
+
*/
|
|
1364
|
+
difficulty?: 'beginner' | 'intermediate' | 'advanced';
|
|
1365
|
+
/**
|
|
1366
|
+
* Template quality/completeness tier (1–5). Higher tiers indicate more polished
|
|
1367
|
+
* templates with richer sample data, AI guidance, and export support.
|
|
1368
|
+
* Used by the kit gallery to surface highest-quality templates first.
|
|
1369
|
+
*/
|
|
1370
|
+
templateTier?: number;
|
|
1371
|
+
/**
|
|
1372
|
+
* Template identity metadata for structured project recognition and run configuration.
|
|
1373
|
+
* Used by Workshop to detect existing project instances and configure the run panel.
|
|
1374
|
+
*/
|
|
1375
|
+
templateMetadata?: WorkshopTemplateMetadata;
|
|
1376
|
+
/**
|
|
1377
|
+
* Cloud deployment configuration for app kits that produce runnable applications.
|
|
1378
|
+
* Drives Workshop's one-click deploy flow.
|
|
1379
|
+
*/
|
|
1380
|
+
deploy?: WorkshopDeployConfig;
|
|
1381
|
+
/**
|
|
1382
|
+
* Sample data to pre-populate a new project's knowledge graph for demonstration.
|
|
1383
|
+
* Shown in Workshop's onboarding "Try with sample data" flow.
|
|
1384
|
+
*/
|
|
1385
|
+
sampleData?: WorkshopSampleData;
|
|
1386
|
+
}
|
|
1387
|
+
|
|
1388
|
+
/**
|
|
1389
|
+
* A Workshop kit manifest — the `kit.json` for a Soulcraft Workshop kit.
|
|
1390
|
+
*
|
|
1391
|
+
* Workshop kits have two types:
|
|
1392
|
+
* - `"content"` — Document/knowledge graph projects (novels, research, knowledge bases)
|
|
1393
|
+
* - `"app"` — Runnable SvelteKit application projects
|
|
1394
|
+
*
|
|
1395
|
+
* @example
|
|
1396
|
+
* ```ts
|
|
1397
|
+
* const kit: WorkshopKitConfig = {
|
|
1398
|
+
* id: 'novel-writer',
|
|
1399
|
+
* type: 'content',
|
|
1400
|
+
* name: 'Novel Writer',
|
|
1401
|
+
* description: 'Write your novel with AI assistance',
|
|
1402
|
+
* version: '1.0.0',
|
|
1403
|
+
* author: { name: 'Soulcraft Labs' },
|
|
1404
|
+
* variables: [{ key: 'title', label: 'Novel Title', type: 'string', required: true }],
|
|
1405
|
+
* workshop: {
|
|
1406
|
+
* workspaceConfig: { paradigm: 'writer', defaultTab: 'edit' },
|
|
1407
|
+
* suggestions: [
|
|
1408
|
+
* { label: 'Add a chapter', prompt: 'Add a new chapter to my novel' },
|
|
1409
|
+
* ],
|
|
1410
|
+
* }
|
|
1411
|
+
* };
|
|
1412
|
+
* ```
|
|
1413
|
+
*/
|
|
1414
|
+
export interface WorkshopKitConfig extends BaseKitManifest {
|
|
1415
|
+
/** Discriminant identifying this as a Workshop kit. */
|
|
1416
|
+
type: 'content' | 'app';
|
|
1417
|
+
/** User-configurable variables substituted into template files at project creation. */
|
|
1418
|
+
variables?: KitVariable[];
|
|
1419
|
+
/** Workshop-specific configuration block. */
|
|
1420
|
+
workshop?: WorkshopConfig;
|
|
1421
|
+
}
|
|
1422
|
+
|
|
1423
|
+
// ──────────────────────────────────────────────
|
|
1424
|
+
// Academy kit (Soulcraft Academy product)
|
|
1425
|
+
// ──────────────────────────────────────────────
|
|
1426
|
+
|
|
1427
|
+
/**
|
|
1428
|
+
* Academy-specific configuration block.
|
|
1429
|
+
*
|
|
1430
|
+
* This interface is a reserved placeholder. Academy product design is deferred
|
|
1431
|
+
* until the product vision is clear. Fields for course structure, certification
|
|
1432
|
+
* configuration, and skill trees will be added here in a future release.
|
|
1433
|
+
*/
|
|
1434
|
+
export interface AcademyConfig {
|
|
1435
|
+
// Reserved for Academy product features.
|
|
1436
|
+
// Course structure, certification config, and skill trees will be defined here.
|
|
1437
|
+
}
|
|
1438
|
+
|
|
1439
|
+
/**
|
|
1440
|
+
* An Academy kit manifest — the `kit.json` for a Soulcraft Academy kit.
|
|
1441
|
+
*
|
|
1442
|
+
* Academy is the learning and certification product in the Soulcraft platform.
|
|
1443
|
+
* This type is reserved for future use; internal design is deferred.
|
|
1444
|
+
*/
|
|
1445
|
+
export interface AcademyKitConfig extends BaseKitManifest {
|
|
1446
|
+
/** Discriminant identifying this as an Academy kit. */
|
|
1447
|
+
type: 'academy';
|
|
1448
|
+
/** User-configurable variables. */
|
|
1449
|
+
variables?: KitVariable[];
|
|
1450
|
+
/** Academy-specific configuration block (reserved, design deferred). */
|
|
1451
|
+
academy?: AcademyConfig;
|
|
1452
|
+
}
|
|
1453
|
+
|
|
1454
|
+
// ──────────────────────────────────────────────
|
|
1455
|
+
// App Runtime Context (Venue → Workshop app interface)
|
|
1456
|
+
// ──────────────────────────────────────────────
|
|
1457
|
+
|
|
1458
|
+
/**
|
|
1459
|
+
* Role specifier for app access control and conditional mounting in Venue.
|
|
1460
|
+
*
|
|
1461
|
+
* Built-in roles correspond to Venue's RBAC system:
|
|
1462
|
+
* - `'public'` — unauthenticated visitors (no login required)
|
|
1463
|
+
* - `'customer'` — authenticated customers with booking history
|
|
1464
|
+
* - `'staff'` — any authenticated staff member
|
|
1465
|
+
* - `'staff:manager'` — managers with elevated admin access
|
|
1466
|
+
*
|
|
1467
|
+
* Custom roles can be defined per-kit in {@link VenueConfig.staffRoles}.
|
|
1468
|
+
* Use colon-namespaced strings for custom roles: `'staff:driver'`, `'staff:barista'`.
|
|
1469
|
+
* The `(string & {})` type preserves string autocompletion for built-in roles
|
|
1470
|
+
* while allowing arbitrary custom role values.
|
|
1471
|
+
*/
|
|
1472
|
+
export type AppRole =
|
|
1473
|
+
| 'public'
|
|
1474
|
+
| 'customer'
|
|
1475
|
+
| 'staff'
|
|
1476
|
+
| 'staff:manager'
|
|
1477
|
+
| (string & {}); // allow kit-defined custom role strings e.g. 'staff:driver'
|
|
1478
|
+
|
|
1479
|
+
/**
|
|
1480
|
+
* Pricing model declared by a Workshop app for Venue's payment broker.
|
|
1481
|
+
*
|
|
1482
|
+
* Venue acts as a payment broker: it collects from customers via Stripe,
|
|
1483
|
+
* distributes earnings to the business (minus a platform fee), and in future
|
|
1484
|
+
* marketplace mode, to kit authors as well.
|
|
1485
|
+
*
|
|
1486
|
+
* All monetary values are in the smallest currency unit (e.g. cents for USD).
|
|
1487
|
+
*/
|
|
1488
|
+
export interface AppPricingModel {
|
|
1489
|
+
/** ISO 4217 currency code. @default 'usd' */
|
|
1490
|
+
currency?: string;
|
|
1491
|
+
/** Fixed base price in smallest currency unit. @example 100 = $1.00 */
|
|
1492
|
+
base?: number;
|
|
1493
|
+
/**
|
|
1494
|
+
* Per-use/per-event pricing in smallest currency unit.
|
|
1495
|
+
* @example { per_ride: 15 } means $0.15 per 'ride' event processed.
|
|
1496
|
+
*/
|
|
1497
|
+
perUnit?: Record<string, number>;
|
|
1498
|
+
/**
|
|
1499
|
+
* Platform fee percentage retained by Soulcraft. Applied after base + per-unit.
|
|
1500
|
+
* @default 0.05 (5%)
|
|
1501
|
+
*/
|
|
1502
|
+
platformFeePercent?: number;
|
|
1503
|
+
}
|
|
1504
|
+
|
|
1505
|
+
/**
|
|
1506
|
+
* Declares a Workshop-built app component that is part of a kit.
|
|
1507
|
+
*
|
|
1508
|
+
* When a Venue kit is activated, these entries tell Venue's dynamic loader which
|
|
1509
|
+
* Workshop app to mount at which path for which roles. Multiple entries can share
|
|
1510
|
+
* the same `mountPath` for role-aware mounting — Venue mounts the first entry
|
|
1511
|
+
* whose `roles` includes the authenticated user's role.
|
|
1512
|
+
*
|
|
1513
|
+
* @example
|
|
1514
|
+
* A dispatch kit with three role-aware mounts, two at the same path:
|
|
1515
|
+
* ```json
|
|
1516
|
+
* [
|
|
1517
|
+
* { "slug": "rider-app", "roles": ["customer"], "mountPath": "/app" },
|
|
1518
|
+
* { "slug": "driver-app", "roles": ["staff:driver"], "mountPath": "/app" },
|
|
1519
|
+
* { "slug": "dispatch-ops", "roles": ["staff:manager"], "mountPath": "/admin/dispatch" }
|
|
1520
|
+
* ]
|
|
1521
|
+
* ```
|
|
1522
|
+
* A customer visiting `/app` sees the rider experience; a logged-in driver sees
|
|
1523
|
+
* their dispatch UI; a manager visits `/admin/dispatch` for the operations board.
|
|
1524
|
+
*/
|
|
1525
|
+
export interface KitAppEntry {
|
|
1526
|
+
/** Unique slug for this app within the kit. Used to match deployed bundles. */
|
|
1527
|
+
slug: string;
|
|
1528
|
+
/** Human-readable name shown in the admin Apps & Content section. */
|
|
1529
|
+
name: string;
|
|
1530
|
+
/** One-line description. */
|
|
1531
|
+
description?: string;
|
|
1532
|
+
/**
|
|
1533
|
+
* Roles that will see this app mounted at `mountPath`.
|
|
1534
|
+
* Venue resolves the first entry whose roles include the user's current role.
|
|
1535
|
+
*/
|
|
1536
|
+
roles: AppRole[];
|
|
1537
|
+
/**
|
|
1538
|
+
* URL path within the Venue instance where this app is mounted.
|
|
1539
|
+
* Multiple entries can share the same path for role-aware mounting.
|
|
1540
|
+
* @example '/app' — primary customer-facing experience
|
|
1541
|
+
* @example '/admin/dispatch' — staff operations board
|
|
1542
|
+
*/
|
|
1543
|
+
mountPath: string;
|
|
1544
|
+
/**
|
|
1545
|
+
* Path within the Venue VFS to the compiled ES module bundle.
|
|
1546
|
+
* Populated by Venue after the app is deployed via `POST /api/deploy`.
|
|
1547
|
+
* @example 'deployments/app/rider-app/bundle.js'
|
|
1548
|
+
*/
|
|
1549
|
+
bundlePath?: string;
|
|
1550
|
+
/**
|
|
1551
|
+
* Name of the exported Svelte component from the bundle.
|
|
1552
|
+
* @default 'default'
|
|
1553
|
+
*/
|
|
1554
|
+
exportName?: string;
|
|
1555
|
+
/**
|
|
1556
|
+
* WebSocket event types this app subscribes to via `ws.on()`.
|
|
1557
|
+
* Venue's WebSocket bridge filters incoming events to only forward
|
|
1558
|
+
* the declared subscription types to this app.
|
|
1559
|
+
* @example ['ride:accepted', 'ride:completed', 'driver:location']
|
|
1560
|
+
*/
|
|
1561
|
+
realtimeSubscriptions?: string[];
|
|
1562
|
+
/**
|
|
1563
|
+
* WebSocket event types this app is permitted to emit via `ws.emit()`.
|
|
1564
|
+
* Venue rejects any emitted event not on this allowlist.
|
|
1565
|
+
* @example ['ride:dispatch', 'driver:location:update']
|
|
1566
|
+
*/
|
|
1567
|
+
realtimeEmits?: string[];
|
|
1568
|
+
/** Pricing model for Venue's payment broker integration. */
|
|
1569
|
+
pricing?: AppPricingModel;
|
|
1570
|
+
}
|
|
1571
|
+
|
|
1572
|
+
/**
|
|
1573
|
+
* Authenticated user identity available to Workshop apps at runtime.
|
|
1574
|
+
* Derived from Venue's better-auth session at mount time.
|
|
1575
|
+
*/
|
|
1576
|
+
export interface AppAuthContext {
|
|
1577
|
+
/** Currently authenticated user, or null if unauthenticated. */
|
|
1578
|
+
user: {
|
|
1579
|
+
/** Venue user ID (stable, derived from better-auth). */
|
|
1580
|
+
id: string;
|
|
1581
|
+
/** Display name. */
|
|
1582
|
+
name: string;
|
|
1583
|
+
/** Email address. */
|
|
1584
|
+
email: string;
|
|
1585
|
+
} | null;
|
|
1586
|
+
/** The user's role in this Venue instance, or null if unauthenticated. */
|
|
1587
|
+
role: AppRole | null;
|
|
1588
|
+
/**
|
|
1589
|
+
* Returns true if the current user has the given Venue capability string.
|
|
1590
|
+
* Checks against the same capability system as Venue's own admin routes.
|
|
1591
|
+
* @example auth.can('published.manage')
|
|
1592
|
+
*/
|
|
1593
|
+
can(capability: string): boolean;
|
|
1594
|
+
/** Sign out the current user and redirect to Venue's login page. */
|
|
1595
|
+
signOut(): Promise<void>;
|
|
1596
|
+
}
|
|
1597
|
+
|
|
1598
|
+
/**
|
|
1599
|
+
* WebSocket context for real-time bidirectional communication with Venue.
|
|
1600
|
+
*
|
|
1601
|
+
* Provided by Venue's WebSocket bridge, which forwards Brainy entity change
|
|
1602
|
+
* events and custom app-to-app events. Venue validates all emitted events
|
|
1603
|
+
* against the kit's declared {@link KitAppEntry.realtimeEmits} allowlist.
|
|
1604
|
+
*
|
|
1605
|
+
* Available when {@link VenueFeatures.realtime} is enabled.
|
|
1606
|
+
*
|
|
1607
|
+
* @example
|
|
1608
|
+
* ```ts
|
|
1609
|
+
* // In a Svelte 5 Workshop app:
|
|
1610
|
+
* const unsub = ws.on<{ lat: number; lng: number }>('driver:location', (pos) => {
|
|
1611
|
+
* updateMarker(pos);
|
|
1612
|
+
* });
|
|
1613
|
+
* onDestroy(unsub); // always clean up subscriptions
|
|
1614
|
+
*
|
|
1615
|
+
* ws.emit('ride:dispatch', { driverId: 'drv-001', rideId: 'ride-123' });
|
|
1616
|
+
* ```
|
|
1617
|
+
*/
|
|
1618
|
+
export interface AppWebSocketContext {
|
|
1619
|
+
/**
|
|
1620
|
+
* Subscribe to a named event stream.
|
|
1621
|
+
* Returns an unsubscribe function — call it in `onDestroy` to prevent leaks.
|
|
1622
|
+
*/
|
|
1623
|
+
on<T = unknown>(event: string, handler: (data: T) => void): () => void;
|
|
1624
|
+
/**
|
|
1625
|
+
* Emit an event to Venue. Only events declared in `realtimeEmits` are permitted;
|
|
1626
|
+
* Venue silently rejects others in development and throws in production.
|
|
1627
|
+
*/
|
|
1628
|
+
emit(event: string, data: unknown): void;
|
|
1629
|
+
/** Whether the WebSocket connection is currently open and authenticated. */
|
|
1630
|
+
readonly connected: boolean;
|
|
1631
|
+
}
|
|
1632
|
+
|
|
1633
|
+
/**
|
|
1634
|
+
* Venue service layer available to Workshop apps at runtime.
|
|
1635
|
+
*
|
|
1636
|
+
* Provides type-safe access to Venue's operational services. Each service
|
|
1637
|
+
* enforces Venue's business rules, capability checks, and audit trails —
|
|
1638
|
+
* identical to how Venue's own admin UI interacts with the same services.
|
|
1639
|
+
*
|
|
1640
|
+
* Concrete TypeScript types are declared in Venue's service layer
|
|
1641
|
+
* (`apps/web/src/lib/server/services/`). The `unknown` placeholders here
|
|
1642
|
+
* avoid a circular dependency; consuming code in Venue uses the concrete types.
|
|
1643
|
+
*
|
|
1644
|
+
* Services are populated based on which {@link VenueFeatures} are enabled.
|
|
1645
|
+
* Accessing a service slot for a disabled feature throws at runtime with a
|
|
1646
|
+
* descriptive error directing the kit author to enable the feature flag.
|
|
1647
|
+
*/
|
|
1648
|
+
export interface AppServicesContext {
|
|
1649
|
+
/** Create, read, cancel, and query bookings. */
|
|
1650
|
+
bookings: unknown;
|
|
1651
|
+
/** Charge, refund, and list financial transactions via Stripe. */
|
|
1652
|
+
transactions: unknown;
|
|
1653
|
+
/** List, adjust, and track inventory items. */
|
|
1654
|
+
inventory: unknown;
|
|
1655
|
+
/** Look up, create, and update customer profiles. */
|
|
1656
|
+
customers: unknown;
|
|
1657
|
+
/**
|
|
1658
|
+
* Manage recurring subscription plans and customer subscriptions.
|
|
1659
|
+
* Available when {@link VenueFeatures.subscriptions} is enabled.
|
|
1660
|
+
*/
|
|
1661
|
+
subscriptions: unknown;
|
|
1662
|
+
/**
|
|
1663
|
+
* Create, update, and query support tickets and knowledge base articles.
|
|
1664
|
+
* Available when {@link VenueFeatures.support} is enabled.
|
|
1665
|
+
*/
|
|
1666
|
+
support: unknown;
|
|
1667
|
+
/**
|
|
1668
|
+
* Earn, redeem, and query loyalty points for customer accounts.
|
|
1669
|
+
* Available when {@link VenueFeatures.loyalty} is enabled.
|
|
1670
|
+
*/
|
|
1671
|
+
loyalty: unknown;
|
|
1672
|
+
/**
|
|
1673
|
+
* Record analytics events and query aggregated metrics.
|
|
1674
|
+
* Available when {@link VenueFeatures.analytics} is enabled.
|
|
1675
|
+
*
|
|
1676
|
+
* @example
|
|
1677
|
+
* ```ts
|
|
1678
|
+
* // Record a domain event from a Workshop app:
|
|
1679
|
+
* await services.analytics.track('checkout:completed', {
|
|
1680
|
+
* value: 4500,
|
|
1681
|
+
* plan: 'pro',
|
|
1682
|
+
* userId: auth.user?.id
|
|
1683
|
+
* });
|
|
1684
|
+
* ```
|
|
1685
|
+
*/
|
|
1686
|
+
analytics: unknown;
|
|
1687
|
+
}
|
|
1688
|
+
|
|
1689
|
+
/**
|
|
1690
|
+
* Claude AI context available to Workshop apps via Venue's Anthropic API key.
|
|
1691
|
+
*
|
|
1692
|
+
* Apps can use AI features — chat, search, generation — without managing their
|
|
1693
|
+
* own API keys. All requests route through Venue's key with rate limiting
|
|
1694
|
+
* applied per Venue instance.
|
|
1695
|
+
*/
|
|
1696
|
+
export interface AppAIContext {
|
|
1697
|
+
/**
|
|
1698
|
+
* Send a conversation exchange and receive a streaming text response.
|
|
1699
|
+
* @param messages The conversation history.
|
|
1700
|
+
* @param opts Optional system prompt and model ID overrides.
|
|
1701
|
+
* @returns An async iterable of text tokens suitable for streaming display.
|
|
1702
|
+
*/
|
|
1703
|
+
chat(
|
|
1704
|
+
messages: Array<{ role: 'user' | 'assistant'; content: string }>,
|
|
1705
|
+
opts?: { system?: string; model?: string }
|
|
1706
|
+
): AsyncIterable<string>;
|
|
1707
|
+
/**
|
|
1708
|
+
* Generate text embeddings for semantic search or similarity ranking.
|
|
1709
|
+
* @param text Single string or batch of strings.
|
|
1710
|
+
* @returns Array of embedding vectors (one per input string).
|
|
1711
|
+
*/
|
|
1712
|
+
embed(text: string | string[]): Promise<number[][]>;
|
|
1713
|
+
}
|
|
1714
|
+
|
|
1715
|
+
/**
|
|
1716
|
+
* Venue VFS and CDN file access for Workshop apps.
|
|
1717
|
+
*
|
|
1718
|
+
* Files are stored in a per-app namespace within the Venue VFS.
|
|
1719
|
+
* In production, uploads go to GCS and are served via CDN.
|
|
1720
|
+
* In development, files are served from the local `static/` directory.
|
|
1721
|
+
*/
|
|
1722
|
+
export interface AppFilesContext {
|
|
1723
|
+
/**
|
|
1724
|
+
* Upload a file to the Venue VFS.
|
|
1725
|
+
* @param file The File or Blob to upload.
|
|
1726
|
+
* @param path Destination path within this app's VFS namespace.
|
|
1727
|
+
* @returns The stable public CDN URL for the uploaded file.
|
|
1728
|
+
*/
|
|
1729
|
+
upload(file: File | Blob, path: string): Promise<string>;
|
|
1730
|
+
/**
|
|
1731
|
+
* Read a file from the Venue VFS.
|
|
1732
|
+
* @param path File path within this app's VFS namespace.
|
|
1733
|
+
*/
|
|
1734
|
+
read(path: string): Promise<Blob>;
|
|
1735
|
+
/**
|
|
1736
|
+
* Delete a file from the Venue VFS.
|
|
1737
|
+
* @param path File path within this app's VFS namespace.
|
|
1738
|
+
*/
|
|
1739
|
+
delete(path: string): Promise<void>;
|
|
1740
|
+
/**
|
|
1741
|
+
* List files under a VFS directory prefix.
|
|
1742
|
+
* @param prefix Directory path prefix within this app's VFS namespace.
|
|
1743
|
+
* @returns Array of matching file paths.
|
|
1744
|
+
*/
|
|
1745
|
+
list(prefix: string): Promise<string[]>;
|
|
1746
|
+
}
|
|
1747
|
+
|
|
1748
|
+
/**
|
|
1749
|
+
* Notification delivery context for Workshop apps.
|
|
1750
|
+
*
|
|
1751
|
+
* Venue handles delivery infrastructure, queuing, rate limiting, and compliance
|
|
1752
|
+
* (unsubscribe links, CAN-SPAM, TCPA opt-in). Apps declare notification needs
|
|
1753
|
+
* via {@link VenueFeatures.notifications}.
|
|
1754
|
+
*
|
|
1755
|
+
* Email delivery: Resend. SMS: Twilio. Push: Web Push API (requires PWA).
|
|
1756
|
+
*/
|
|
1757
|
+
export interface AppNotifyContext {
|
|
1758
|
+
/**
|
|
1759
|
+
* Send a transactional email.
|
|
1760
|
+
* @param to Recipient email address.
|
|
1761
|
+
* @param subject Email subject line.
|
|
1762
|
+
* @param body Plain-text email body (auto-generates HTML fallback).
|
|
1763
|
+
* @param opts Optional HTML override and reply-to address.
|
|
1764
|
+
*/
|
|
1765
|
+
email(
|
|
1766
|
+
to: string,
|
|
1767
|
+
subject: string,
|
|
1768
|
+
body: string,
|
|
1769
|
+
opts?: { html?: string; replyTo?: string }
|
|
1770
|
+
): Promise<void>;
|
|
1771
|
+
/**
|
|
1772
|
+
* Send an SMS message via Twilio.
|
|
1773
|
+
* Requires the recipient's phone to be verified and opted in per TCPA rules.
|
|
1774
|
+
* @param to E.164 phone number, e.g. '+17045551234'.
|
|
1775
|
+
* @param message SMS body text (160 chars max for single segment).
|
|
1776
|
+
*/
|
|
1777
|
+
sms(to: string, message: string): Promise<void>;
|
|
1778
|
+
/**
|
|
1779
|
+
* Send a Web Push notification to a user's device(s).
|
|
1780
|
+
* Requires the user to have granted push permission via Venue's PWA service worker.
|
|
1781
|
+
* @param userId Venue user ID (may have multiple registered devices).
|
|
1782
|
+
* @param payload Notification title, body text, and optional click-through URL.
|
|
1783
|
+
*/
|
|
1784
|
+
push(
|
|
1785
|
+
userId: string,
|
|
1786
|
+
payload: { title: string; body: string; url?: string }
|
|
1787
|
+
): Promise<void>;
|
|
1788
|
+
}
|
|
1789
|
+
|
|
1790
|
+
/**
|
|
1791
|
+
* Full runtime context injected into every Workshop-built app when it mounts in Venue.
|
|
1792
|
+
*
|
|
1793
|
+
* A Workshop app receiving this context is indistinguishable from native Venue code —
|
|
1794
|
+
* it reads and writes the same Brainy database, authenticates the same users, calls
|
|
1795
|
+
* the same operational services, and streams from the same WebSocket bridge.
|
|
1796
|
+
*
|
|
1797
|
+
* This is the central contract between Venue (runtime host) and Workshop (app author).
|
|
1798
|
+
* Changes to this interface are breaking changes for all deployed apps.
|
|
1799
|
+
*
|
|
1800
|
+
* Venue's dynamic loader (Phase 4) constructs and injects this context at mount time.
|
|
1801
|
+
* Workshop's build tooling validates that app components declare compatible prop types.
|
|
1802
|
+
*
|
|
1803
|
+
* @example
|
|
1804
|
+
* ```svelte
|
|
1805
|
+
* <!-- MyWorkshopApp.svelte -->
|
|
1806
|
+
* <script lang="ts">
|
|
1807
|
+
* import type { AppRuntimeContext } from '@soulcraft/kit-schema';
|
|
1808
|
+
*
|
|
1809
|
+
* let { brain, auth, kit, ws, services, ai, files, notify, config, slot }: AppRuntimeContext = $props();
|
|
1810
|
+
*
|
|
1811
|
+
* // Real-time dispatch example:
|
|
1812
|
+
* const unsub = ws.on<RideAccepted>('ride:accepted', (ride) => mapState.addRide(ride));
|
|
1813
|
+
* onDestroy(unsub);
|
|
1814
|
+
*
|
|
1815
|
+
* // AI-powered feature:
|
|
1816
|
+
* async function suggestRoute() {
|
|
1817
|
+
* for await (const token of ai.chat([{ role: 'user', content: 'Suggest optimal route' }])) {
|
|
1818
|
+
* suggestion += token;
|
|
1819
|
+
* }
|
|
1820
|
+
* }
|
|
1821
|
+
* </script>
|
|
1822
|
+
* ```
|
|
1823
|
+
*/
|
|
1824
|
+
export interface AppRuntimeContext {
|
|
1825
|
+
/**
|
|
1826
|
+
* The Venue Brainy instance — identical to the database backing all of Venue's
|
|
1827
|
+
* own features. Apps can freely query, create, update, and delete entities.
|
|
1828
|
+
*
|
|
1829
|
+
* Typed as `unknown` here to avoid a circular dependency on `@soulcraft/brainy`;
|
|
1830
|
+
* import `Brainy` from `@soulcraft/brainy` and cast in consuming code.
|
|
1831
|
+
*/
|
|
1832
|
+
brain: unknown;
|
|
1833
|
+
/** Authenticated user identity, role, and Venue capability checks. */
|
|
1834
|
+
auth: AppAuthContext;
|
|
1835
|
+
/** The active kit configuration for this Venue instance. */
|
|
1836
|
+
kit: KitManifest;
|
|
1837
|
+
/**
|
|
1838
|
+
* WebSocket connection to Venue's real-time bridge.
|
|
1839
|
+
* Supports live entity-change streams, dispatch events, in-app chat,
|
|
1840
|
+
* location tracking, and any custom bidirectional event types declared
|
|
1841
|
+
* in the kit's {@link KitAppEntry.realtimeSubscriptions} / {@link KitAppEntry.realtimeEmits}.
|
|
1842
|
+
* Available when {@link VenueFeatures.realtime} is enabled.
|
|
1843
|
+
*/
|
|
1844
|
+
ws: AppWebSocketContext;
|
|
1845
|
+
/**
|
|
1846
|
+
* Venue's typed operational service layer — same services as the admin UI.
|
|
1847
|
+
* Bookings, transactions, inventory, customers.
|
|
1848
|
+
*/
|
|
1849
|
+
services: AppServicesContext;
|
|
1850
|
+
/**
|
|
1851
|
+
* Claude AI access via Venue's Anthropic API key.
|
|
1852
|
+
* Chat streaming, embeddings, and content generation — no separate key needed.
|
|
1853
|
+
*/
|
|
1854
|
+
ai: AppAIContext;
|
|
1855
|
+
/**
|
|
1856
|
+
* Venue VFS and CDN file access.
|
|
1857
|
+
* Upload, read, list, and delete files in this app's VFS namespace.
|
|
1858
|
+
*/
|
|
1859
|
+
files: AppFilesContext;
|
|
1860
|
+
/**
|
|
1861
|
+
* Email, SMS, and Web Push notification delivery via Venue's infrastructure.
|
|
1862
|
+
* Available when {@link VenueFeatures.notifications} is enabled.
|
|
1863
|
+
*/
|
|
1864
|
+
notify: AppNotifyContext;
|
|
1865
|
+
/**
|
|
1866
|
+
* Admin-configured runtime values for this deployment.
|
|
1867
|
+
*
|
|
1868
|
+
* Keys correspond to entries in the app's `manifest.json` `config` schema
|
|
1869
|
+
* (see {@link ManifestConfigField}). Values are the Venue admin's overrides
|
|
1870
|
+
* merged over the manifest defaults. Absent when the deployment has no config
|
|
1871
|
+
* schema or the admin has not set any overrides.
|
|
1872
|
+
*
|
|
1873
|
+
* Use this for feature flags, API endpoints, display preferences, or any other
|
|
1874
|
+
* per-deployment customization the app author wants to expose to the venue owner.
|
|
1875
|
+
*
|
|
1876
|
+
* @example
|
|
1877
|
+
* ```svelte
|
|
1878
|
+
* <script lang="ts">
|
|
1879
|
+
* let { config }: AppRuntimeContext = $props();
|
|
1880
|
+
* const theme = config?.theme ?? 'light'; // 'string' field
|
|
1881
|
+
* const maxItems = config?.maxItems ?? 10; // 'number' field
|
|
1882
|
+
* const showBanner = config?.showBanner ?? true; // 'boolean' field
|
|
1883
|
+
* </script>
|
|
1884
|
+
* ```
|
|
1885
|
+
*/
|
|
1886
|
+
config?: Record<string, string | number | boolean>;
|
|
1887
|
+
/**
|
|
1888
|
+
* The URL mount path this app was loaded at within the Venue instance.
|
|
1889
|
+
* @example '/app' or '/admin/dispatch'
|
|
1890
|
+
*/
|
|
1891
|
+
slot?: string;
|
|
1892
|
+
}
|
|
1893
|
+
|
|
1894
|
+
// ──────────────────────────────────────────────
|
|
1895
|
+
// Publish Protocol (Workshop → Venue deploy API)
|
|
1896
|
+
// ──────────────────────────────────────────────
|
|
1897
|
+
|
|
1898
|
+
/**
|
|
1899
|
+
* Content types that Workshop can publish to Venue's deploy API.
|
|
1900
|
+
*/
|
|
1901
|
+
export type PublishContentType = 'app' | 'document' | 'visualization' | 'slideshow' | 'static';
|
|
1902
|
+
|
|
1903
|
+
/**
|
|
1904
|
+
* Content payload for a document-type deployment.
|
|
1905
|
+
* Stores content inline in Venue's Brainy entity metadata.
|
|
1906
|
+
*/
|
|
1907
|
+
export interface DocumentPublishContent {
|
|
1908
|
+
/** The document body in markdown or HTML format. */
|
|
1909
|
+
body: string;
|
|
1910
|
+
/** MIME type of the content body. */
|
|
1911
|
+
mimeType?: 'text/markdown' | 'text/html';
|
|
1912
|
+
}
|
|
1913
|
+
|
|
1914
|
+
/**
|
|
1915
|
+
* Content payload for a visualization-type deployment (knowledge graphs, mind maps, etc.).
|
|
1916
|
+
*/
|
|
1917
|
+
export interface VisualizationPublishContent {
|
|
1918
|
+
/** Graph nodes and edges from Workshop's Brainy knowledge graph. */
|
|
1919
|
+
graph: {
|
|
1920
|
+
nodes: Array<{ id: string; label: string; type: string; metadata?: Record<string, unknown> }>;
|
|
1921
|
+
edges: Array<{ id: string; from: string; to: string; type: string; metadata?: Record<string, unknown> }>;
|
|
1922
|
+
};
|
|
1923
|
+
/** Which visualization type to render (graph, mindmap, tree, etc.). */
|
|
1924
|
+
viewType?: WorkshopExploreView;
|
|
1925
|
+
/** Visualization renderer configuration. */
|
|
1926
|
+
config?: Record<string, unknown>;
|
|
1927
|
+
}
|
|
1928
|
+
|
|
1929
|
+
/**
|
|
1930
|
+
* Content payload for a slideshow-type deployment.
|
|
1931
|
+
*/
|
|
1932
|
+
export interface SlideshowPublishContent {
|
|
1933
|
+
/** Slide content as an array of markdown strings (one per slide). */
|
|
1934
|
+
slides: string[];
|
|
1935
|
+
/** Slideshow configuration (theme, transitions, etc.). */
|
|
1936
|
+
config?: Record<string, unknown>;
|
|
1937
|
+
}
|
|
1938
|
+
|
|
1939
|
+
/**
|
|
1940
|
+
* Content payload for a static site deployment.
|
|
1941
|
+
*/
|
|
1942
|
+
export interface StaticPublishContent {
|
|
1943
|
+
/** File map: relative path → base64-encoded file content. */
|
|
1944
|
+
files: Record<string, string>;
|
|
1945
|
+
/** Entry point file path (e.g. "index.html"). */
|
|
1946
|
+
entryPoint: string;
|
|
1947
|
+
}
|
|
1948
|
+
|
|
1949
|
+
/**
|
|
1950
|
+
* Content payload for an app-type deployment (Svelte 5 component bundle).
|
|
1951
|
+
*
|
|
1952
|
+
* Workshop compiles app kits into ES module bundles that Venue loads dynamically
|
|
1953
|
+
* via `import()`. The bundle must export a default Svelte 5 component that accepts
|
|
1954
|
+
* the full {@link AppRuntimeContext} as props — giving the app access to Venue's
|
|
1955
|
+
* Brainy instance, authenticated user, operational services, WebSocket, AI, files,
|
|
1956
|
+
* and notification delivery.
|
|
1957
|
+
*/
|
|
1958
|
+
export interface AppPublishContent {
|
|
1959
|
+
/** ES module bundle as a UTF-8 string. */
|
|
1960
|
+
bundle: string;
|
|
1961
|
+
/** Source map for debugging (optional). */
|
|
1962
|
+
sourceMap?: string;
|
|
1963
|
+
/** The export name of the root component. @default "default" */
|
|
1964
|
+
exportName?: string;
|
|
1965
|
+
}
|
|
1966
|
+
|
|
1967
|
+
/**
|
|
1968
|
+
* The content portion of a publish payload, discriminated by `contentType`.
|
|
1969
|
+
*
|
|
1970
|
+
* Use type narrowing on `contentType` to access the typed `content` field:
|
|
1971
|
+
* ```ts
|
|
1972
|
+
* if (payload.contentType === 'document') {
|
|
1973
|
+
* const { body } = payload.content; // DocumentPublishContent
|
|
1974
|
+
* }
|
|
1975
|
+
* ```
|
|
1976
|
+
*/
|
|
1977
|
+
export type PublishContentPayload =
|
|
1978
|
+
| { contentType: 'document'; content: DocumentPublishContent }
|
|
1979
|
+
| { contentType: 'visualization'; content: VisualizationPublishContent }
|
|
1980
|
+
| { contentType: 'slideshow'; content: SlideshowPublishContent }
|
|
1981
|
+
| { contentType: 'static'; content: StaticPublishContent }
|
|
1982
|
+
| { contentType: 'app'; content: AppPublishContent };
|
|
1983
|
+
|
|
1984
|
+
/**
|
|
1985
|
+
* The full payload sent from Workshop to Venue's `POST /api/deploy` endpoint.
|
|
1986
|
+
*
|
|
1987
|
+
* Workshop assembles this payload and calls Venue's deploy API with the authenticated
|
|
1988
|
+
* user's SSO token. Venue stores the deployment as a Brainy entity and serves it
|
|
1989
|
+
* at the appropriate route.
|
|
1990
|
+
*
|
|
1991
|
+
* @example
|
|
1992
|
+
* ```ts
|
|
1993
|
+
* const payload: PublishPayload = {
|
|
1994
|
+
* kitId: 'novel-writer',
|
|
1995
|
+
* title: 'My Novel',
|
|
1996
|
+
* slug: 'my-novel',
|
|
1997
|
+
* version: '1.0.0',
|
|
1998
|
+
* sourceWorkshopUserId: 'user-abc123',
|
|
1999
|
+
* sourceWorkspaceId: 'ws-xyz456',
|
|
2000
|
+
* deployedAt: new Date().toISOString(),
|
|
2001
|
+
* contentType: 'document',
|
|
2002
|
+
* content: { body: '# Chapter 1\n\nOnce upon a time...', mimeType: 'text/markdown' },
|
|
2003
|
+
* };
|
|
2004
|
+
* ```
|
|
2005
|
+
*/
|
|
2006
|
+
export type PublishPayload = {
|
|
2007
|
+
/** The kit that produced this content. */
|
|
2008
|
+
kitId: string;
|
|
2009
|
+
/** Human-readable title for the deployed content. */
|
|
2010
|
+
title: string;
|
|
2011
|
+
/** Optional description shown in Venue's admin. */
|
|
2012
|
+
description?: string;
|
|
2013
|
+
/**
|
|
2014
|
+
* URL-safe slug for routing.
|
|
2015
|
+
* @example "my-novel" → `/docs/my-novel`
|
|
2016
|
+
*/
|
|
2017
|
+
slug: string;
|
|
2018
|
+
/** Semantic version of this deployment (for change tracking). */
|
|
2019
|
+
version: string;
|
|
2020
|
+
/** Workshop user ID (for attribution and update authorization). */
|
|
2021
|
+
sourceWorkshopUserId: string;
|
|
2022
|
+
/** Workshop workspace ID this content was created in. */
|
|
2023
|
+
sourceWorkspaceId: string;
|
|
2024
|
+
/** ISO 8601 timestamp of when this deployment was created. */
|
|
2025
|
+
deployedAt: string;
|
|
2026
|
+
/**
|
|
2027
|
+
* Optional theme catalog ID from `@soulcraft/theme` representing the Workshop user's
|
|
2028
|
+
* chosen visual theme for this content. Venue calls `resolveTheme({ userThemeId })` when
|
|
2029
|
+
* rendering the deployment. `null` means inherit the Venue instance's active kit theme.
|
|
2030
|
+
*/
|
|
2031
|
+
themeId?: string | null;
|
|
2032
|
+
} & PublishContentPayload;
|
|
2033
|
+
|
|
2034
|
+
/**
|
|
2035
|
+
* Response from Venue's `POST /api/deploy` endpoint.
|
|
2036
|
+
*/
|
|
2037
|
+
export interface PublishResponse {
|
|
2038
|
+
/** Whether the deployment succeeded. */
|
|
2039
|
+
success: boolean;
|
|
2040
|
+
/** The deployment entity ID in Venue's Brainy. Present on success. */
|
|
2041
|
+
deploymentId?: string;
|
|
2042
|
+
/** The public URL where the deployed content is served. Present on success. */
|
|
2043
|
+
url?: string;
|
|
2044
|
+
/** Error message if deployment failed. */
|
|
2045
|
+
error?: string;
|
|
2046
|
+
}
|
|
2047
|
+
|
|
2048
|
+
// ──────────────────────────────────────────────
|
|
2049
|
+
// Unified Soulcraft kit (spans all products)
|
|
2050
|
+
// ──────────────────────────────────────────────
|
|
2051
|
+
|
|
2052
|
+
/**
|
|
2053
|
+
* Cross-product intelligence shared by all three Soulcraft products.
|
|
2054
|
+
*
|
|
2055
|
+
* When a `SoulcraftKitConfig` declares a `shared` block, Workshop uses it to
|
|
2056
|
+
* prime Briggy's domain expertise, Venue uses it to label entities in the admin
|
|
2057
|
+
* UI, and Academy uses it to scaffold training modules.
|
|
2058
|
+
*
|
|
2059
|
+
* This is the single source of industry truth for "install one kit, AI gains
|
|
2060
|
+
* skills everywhere" — the shared glossary and expertise areas propagate to
|
|
2061
|
+
* every product's AI without duplicate configuration.
|
|
2062
|
+
*
|
|
2063
|
+
* @example
|
|
2064
|
+
* ```ts
|
|
2065
|
+
* const shared: SharedKitFoundation = {
|
|
2066
|
+
* industry: 'saas',
|
|
2067
|
+
* glossary: { MRR: 'Monthly Recurring Revenue', churn: 'Rate of subscription cancellations' },
|
|
2068
|
+
* aiExpertise: ['SaaS metrics', 'subscription economics', 'user onboarding', 'pricing strategy'],
|
|
2069
|
+
* dataModelHints: ['subscription', 'customer', 'transaction', 'usage_event']
|
|
2070
|
+
* };
|
|
2071
|
+
* ```
|
|
2072
|
+
*/
|
|
2073
|
+
/**
|
|
2074
|
+
* Per-product annotation on a domain entity, declaring how the entity maps
|
|
2075
|
+
* to each product's internal concepts and UI behaviours.
|
|
2076
|
+
*/
|
|
2077
|
+
export interface SharedDataModelEntityProducts {
|
|
2078
|
+
/** Workshop-specific entity display configuration. */
|
|
2079
|
+
workshop?: {
|
|
2080
|
+
/** Default explore view to use when browsing this entity type. @example "card" | "graph" */
|
|
2081
|
+
view?: string;
|
|
2082
|
+
/** Emoji icon for the entity type in Workshop's graph. */
|
|
2083
|
+
icon?: string;
|
|
2084
|
+
};
|
|
2085
|
+
/** Venue-specific entity mapping for business operations. */
|
|
2086
|
+
venue?: {
|
|
2087
|
+
/** The Venue entity type this domain entity maps to. @example "inventoryItem" | "booking" */
|
|
2088
|
+
mapsTo?: string;
|
|
2089
|
+
/** Whether this entity appears on the Venue POS screen. */
|
|
2090
|
+
pos?: boolean;
|
|
2091
|
+
/** Whether Venue should track stock levels for this entity. */
|
|
2092
|
+
trackStock?: boolean;
|
|
2093
|
+
};
|
|
2094
|
+
/** Academy-specific entity mapping for learning paths. */
|
|
2095
|
+
academy?: {
|
|
2096
|
+
/** The Academy entity type this maps to. @example "lesson" | "module" */
|
|
2097
|
+
mapsTo?: string;
|
|
2098
|
+
/** Whether this entity can be assessed/scored in Academy. */
|
|
2099
|
+
assessable?: boolean;
|
|
2100
|
+
};
|
|
2101
|
+
}
|
|
2102
|
+
|
|
2103
|
+
/**
|
|
2104
|
+
* A domain entity declared in `shared.dataModel`.
|
|
2105
|
+
*
|
|
2106
|
+
* Maps a business domain concept (e.g. "recipe") to a Brainy NounType
|
|
2107
|
+
* (e.g. "Document") and declares per-product behaviours.
|
|
2108
|
+
*/
|
|
2109
|
+
export interface SharedDataModelEntity {
|
|
2110
|
+
/** Business domain name for this entity. @example "recipe" | "booking" | "ingredient" */
|
|
2111
|
+
domain: string;
|
|
2112
|
+
/** Brainy NounType this entity maps to. @example "Document" | "Thing" | "Person" | "Event" */
|
|
2113
|
+
type: string;
|
|
2114
|
+
/** Human-readable description of what this entity represents. */
|
|
2115
|
+
description: string;
|
|
2116
|
+
/** Per-product annotations controlling how this entity surfaces in each product's UI. */
|
|
2117
|
+
products?: SharedDataModelEntityProducts;
|
|
2118
|
+
}
|
|
2119
|
+
|
|
2120
|
+
/**
|
|
2121
|
+
* Per-product annotation on a domain relationship.
|
|
2122
|
+
*/
|
|
2123
|
+
export interface SharedDataModelRelationshipProducts {
|
|
2124
|
+
/** Venue-specific relationship behaviours. */
|
|
2125
|
+
venue?: {
|
|
2126
|
+
/** Business operation triggered by this relationship. @example "inventoryDeduction" */
|
|
2127
|
+
triggers?: string;
|
|
2128
|
+
};
|
|
2129
|
+
/** Academy-specific relationship behaviours. */
|
|
2130
|
+
academy?: {
|
|
2131
|
+
/** Academy concept this relationship creates. @example "prerequisite" */
|
|
2132
|
+
creates?: string;
|
|
2133
|
+
};
|
|
2134
|
+
}
|
|
2135
|
+
|
|
2136
|
+
/**
|
|
2137
|
+
* A domain relationship declared in `shared.dataModel`.
|
|
2138
|
+
*
|
|
2139
|
+
* Represents a typed connection between two domain entities.
|
|
2140
|
+
*/
|
|
2141
|
+
export interface SharedDataModelRelationship {
|
|
2142
|
+
/** Source entity `domain` value. @example "recipe" */
|
|
2143
|
+
from: string;
|
|
2144
|
+
/** Target entity `domain` value. @example "ingredient" */
|
|
2145
|
+
to: string;
|
|
2146
|
+
/** Relationship verb (Brainy VerbType convention). @example "Contains" | "Precedes" */
|
|
2147
|
+
verb: string;
|
|
2148
|
+
/** Human-readable description of what this relationship means. */
|
|
2149
|
+
description: string;
|
|
2150
|
+
/** Per-product annotations for this relationship. */
|
|
2151
|
+
products?: SharedDataModelRelationshipProducts;
|
|
2152
|
+
}
|
|
2153
|
+
|
|
2154
|
+
/**
|
|
2155
|
+
* Unified domain model declaration for a kit.
|
|
2156
|
+
*
|
|
2157
|
+
* `shared.dataModel` is the single source of truth for "what domain entities exist in
|
|
2158
|
+
* this kit" — replacing the older scattered `dataModelHints` (string array) and
|
|
2159
|
+
* `workshop.graphGuidance.conceptCreation.typeMapping` (Workshop-specific object).
|
|
2160
|
+
*
|
|
2161
|
+
* One declaration drives all products: Workshop reads it for graph guidance and
|
|
2162
|
+
* AI persona priming; Venue uses it for entity labelling and station auto-generation;
|
|
2163
|
+
* Academy uses it to scaffold training modules.
|
|
2164
|
+
*
|
|
2165
|
+
* @example
|
|
2166
|
+
* ```json
|
|
2167
|
+
* {
|
|
2168
|
+
* "entities": [
|
|
2169
|
+
* { "domain": "recipe", "type": "Document", "description": "A cooking recipe",
|
|
2170
|
+
* "products": { "venue": { "mapsTo": "menuItem", "pos": true } } }
|
|
2171
|
+
* ],
|
|
2172
|
+
* "relationships": [
|
|
2173
|
+
* { "from": "recipe", "to": "ingredient", "verb": "Contains",
|
|
2174
|
+
* "description": "Recipe uses this ingredient" }
|
|
2175
|
+
* ]
|
|
2176
|
+
* }
|
|
2177
|
+
* ```
|
|
2178
|
+
*/
|
|
2179
|
+
export interface SharedDataModel {
|
|
2180
|
+
/** Domain entity declarations. */
|
|
2181
|
+
entities?: SharedDataModelEntity[];
|
|
2182
|
+
/** Domain relationship declarations. */
|
|
2183
|
+
relationships?: SharedDataModelRelationship[];
|
|
2184
|
+
}
|
|
2185
|
+
|
|
2186
|
+
export interface SharedKitFoundation {
|
|
2187
|
+
/**
|
|
2188
|
+
* Industry vertical identifier.
|
|
2189
|
+
* Used to categorize kits in the gallery and prime AI domain knowledge.
|
|
2190
|
+
* @example 'creative-experiences' | 'saas' | 'food-beverage' | 'professional-services'
|
|
2191
|
+
*/
|
|
2192
|
+
industry: string;
|
|
2193
|
+
/**
|
|
2194
|
+
* Display category used for gallery filtering and discovery.
|
|
2195
|
+
* Shown as a badge on kit cards and used for the category filter sidebar.
|
|
2196
|
+
* @example 'creative' | 'business' | 'games' | 'knowledge' | 'dev'
|
|
2197
|
+
*/
|
|
2198
|
+
category?: string;
|
|
2199
|
+
/**
|
|
2200
|
+
* Industry-specific term definitions injected into AI system prompts.
|
|
2201
|
+
* Keys are terms; values are plain-English definitions the AI uses to answer questions.
|
|
2202
|
+
* @example { "MRR": "Monthly Recurring Revenue — monthly subscription revenue excluding one-time charges" }
|
|
2203
|
+
*/
|
|
2204
|
+
glossary?: Record<string, string>;
|
|
2205
|
+
/**
|
|
2206
|
+
* Areas of domain expertise the AI should embody across all products.
|
|
2207
|
+
* Injected into Workshop's Briggy persona and Venue's chat context.
|
|
2208
|
+
* @example ["SaaS metrics", "subscription economics", "user onboarding", "pricing strategy"]
|
|
2209
|
+
*/
|
|
2210
|
+
aiExpertise?: string[];
|
|
2211
|
+
/**
|
|
2212
|
+
* Brainy entity type IDs that this kit uses heavily.
|
|
2213
|
+
* Hints to the graph engine which entity types to optimize storage for,
|
|
2214
|
+
* and tells Briggy which types to suggest when building the knowledge graph.
|
|
2215
|
+
* @example ["subscription", "customer", "transaction", "usage_event"]
|
|
2216
|
+
*/
|
|
2217
|
+
dataModelHints?: string[];
|
|
2218
|
+
/**
|
|
2219
|
+
* Cross-product suggestion chips for AI assistant interfaces.
|
|
2220
|
+
*
|
|
2221
|
+
* In Workshop: shown on the AI chat intro screen (replaces `WorkshopConfig.suggestions`).
|
|
2222
|
+
* In Venue: shown as quick-action chips in the customer-facing chatbot widget.
|
|
2223
|
+
*
|
|
2224
|
+
* Order convention — first 1–2: create/add actions; middle 2–3: domain workflows;
|
|
2225
|
+
* last 1–2: explore/visualize actions.
|
|
2226
|
+
*/
|
|
2227
|
+
suggestions?: KitSuggestion[];
|
|
2228
|
+
/**
|
|
2229
|
+
* Unified domain model declaration.
|
|
2230
|
+
*
|
|
2231
|
+
* Single source of truth for all domain entities and relationships in this kit.
|
|
2232
|
+
* Drives Workshop's graph guidance, Venue's entity labelling and station hints,
|
|
2233
|
+
* and Academy's learning path scaffolding.
|
|
2234
|
+
*
|
|
2235
|
+
* Supersedes `dataModelHints` (kept for backward compat) and
|
|
2236
|
+
* `workshop.graphGuidance.conceptCreation.typeMapping` (product-specific override
|
|
2237
|
+
* still works for fine-tuning).
|
|
2238
|
+
*
|
|
2239
|
+
* @see {@link SharedDataModel}
|
|
2240
|
+
*/
|
|
2241
|
+
dataModel?: SharedDataModel;
|
|
2242
|
+
}
|
|
2243
|
+
|
|
2244
|
+
/**
|
|
2245
|
+
* A complete unified Soulcraft kit manifest — the `kit.json` for a kit that
|
|
2246
|
+
* spans multiple Soulcraft products via optional per-product config blocks.
|
|
2247
|
+
*
|
|
2248
|
+
* The `type: 'soulcraft'` discriminant marks a kit as product-agnostic at its
|
|
2249
|
+
* core. Each product reads only its own section (`workshop`, `venue`, `academy`)
|
|
2250
|
+
* and ignores the others. The `shared` block provides cross-product intelligence
|
|
2251
|
+
* (glossary, AI expertise, industry identity) that enriches all products equally.
|
|
2252
|
+
*
|
|
2253
|
+
* This is the recommended type for new kits targeting more than one product.
|
|
2254
|
+
* Existing `type: 'venue'`, `type: 'content'`, and `type: 'app'` kits continue
|
|
2255
|
+
* to work without changes — the discriminated union is additive, not breaking.
|
|
2256
|
+
*
|
|
2257
|
+
* @example
|
|
2258
|
+
* ```ts
|
|
2259
|
+
* const kit: SoulcraftKitConfig = {
|
|
2260
|
+
* id: 'saas-app',
|
|
2261
|
+
* type: 'soulcraft',
|
|
2262
|
+
* name: 'SaaS Application',
|
|
2263
|
+
* description: 'Full-stack SaaS platform with subscriptions, CRM, and AI',
|
|
2264
|
+
* version: '1.0.0',
|
|
2265
|
+
* role: 'primary',
|
|
2266
|
+
* author: { name: 'Soulcraft Labs', email: 'kits@soulcraft.com' },
|
|
2267
|
+
* shared: {
|
|
2268
|
+
* industry: 'saas',
|
|
2269
|
+
* aiExpertise: ['SaaS metrics', 'subscription economics'],
|
|
2270
|
+
* },
|
|
2271
|
+
* venue: {
|
|
2272
|
+
* features: { subscriptions: true, customerAccounts: true, support: true },
|
|
2273
|
+
* theme: { primary: 'oklch(0.55 0.25 250)', bgBase: 'oklch(0.98 0.005 250)' },
|
|
2274
|
+
* experienceTypes: [],
|
|
2275
|
+
* },
|
|
2276
|
+
* workshop: {
|
|
2277
|
+
* workspaceConfig: { paradigm: 'developer', defaultTab: 'explore' },
|
|
2278
|
+
* aiPersona: { role: 'Senior SaaS architect', expertise: ['SaaS metrics'], tone: 'collaborator' },
|
|
2279
|
+
* },
|
|
2280
|
+
* };
|
|
2281
|
+
* ```
|
|
2282
|
+
*/
|
|
2283
|
+
export interface SoulcraftKitConfig extends BaseKitManifest {
|
|
2284
|
+
/** Discriminant identifying this as a unified multi-product Soulcraft kit. */
|
|
2285
|
+
type: 'soulcraft';
|
|
2286
|
+
/** User-configurable variables substituted into template files at onboarding. */
|
|
2287
|
+
variables?: KitVariable[];
|
|
2288
|
+
/**
|
|
2289
|
+
* Cross-product foundation — industry identity, glossary, and AI expertise.
|
|
2290
|
+
* Consumed by Workshop (Briggy), Venue (UI labels, chat context), and Academy.
|
|
2291
|
+
*/
|
|
2292
|
+
shared?: SharedKitFoundation;
|
|
2293
|
+
/**
|
|
2294
|
+
* Venue-specific configuration block.
|
|
2295
|
+
* When present, this kit can be used to configure a Venue deployment.
|
|
2296
|
+
* Absent for Workshop-only or Academy-only kits.
|
|
2297
|
+
*/
|
|
2298
|
+
venue?: VenueConfig;
|
|
2299
|
+
/**
|
|
2300
|
+
* Workshop-specific configuration block.
|
|
2301
|
+
* When present, this kit configures a Workshop workspace with the given persona,
|
|
2302
|
+
* workflows, and AI expertise. Absent for Venue-only kits.
|
|
2303
|
+
*/
|
|
2304
|
+
workshop?: WorkshopConfig;
|
|
2305
|
+
/**
|
|
2306
|
+
* Academy-specific configuration block.
|
|
2307
|
+
* Reserved for future Academy product integration. Absent until Academy ships.
|
|
2308
|
+
*/
|
|
2309
|
+
academy?: AcademyConfig;
|
|
2310
|
+
}
|
|
2311
|
+
|
|
2312
|
+
// ──────────────────────────────────────────────
|
|
2313
|
+
// Discriminated union
|
|
2314
|
+
// ──────────────────────────────────────────────
|
|
2315
|
+
|
|
2316
|
+
/**
|
|
2317
|
+
* Discriminated union of all kit manifest types across the Soulcraft platform.
|
|
2318
|
+
*
|
|
2319
|
+
* Use the `type` field to narrow to the specific manifest variant:
|
|
2320
|
+
*
|
|
2321
|
+
* ```ts
|
|
2322
|
+
* function loadKit(manifest: KitManifest) {
|
|
2323
|
+
* if (manifest.type === 'venue') {
|
|
2324
|
+
* // TypeScript narrows to VenueKitConfig
|
|
2325
|
+
* const { features } = manifest.venue;
|
|
2326
|
+
* } else if (manifest.type === 'content' || manifest.type === 'app') {
|
|
2327
|
+
* // TypeScript narrows to WorkshopKitConfig
|
|
2328
|
+
* const { workshop } = manifest;
|
|
2329
|
+
* } else if (manifest.type === 'academy') {
|
|
2330
|
+
* // TypeScript narrows to AcademyKitConfig
|
|
2331
|
+
* } else if (manifest.type === 'soulcraft') {
|
|
2332
|
+
* // TypeScript narrows to SoulcraftKitConfig
|
|
2333
|
+
* const { shared, venue, workshop, academy } = manifest;
|
|
2334
|
+
* }
|
|
2335
|
+
* }
|
|
2336
|
+
* ```
|
|
2337
|
+
*/
|
|
2338
|
+
export type KitManifest = VenueKitConfig | WorkshopKitConfig | AcademyKitConfig | SoulcraftKitConfig;
|