siteplane 0.1.67 → 0.1.68

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/dist/index.js CHANGED
@@ -1,12 +1,35 @@
1
- // ../cli/dist/analytics/manifest.js
1
+ // ../cli/dist/booking/manifest.js
2
2
  import { mkdir, readFile, writeFile } from "fs/promises";
3
3
  import { dirname } from "path";
4
4
 
5
5
  // ../shared/dist/actors.js
6
6
  import { z } from "zod";
7
- var ACTOR_TYPES = ["workspace_member", "site_member", "agent", "setup_guest", "system"];
7
+ var ACTOR_TYPES = ["workspace_member", "site_member", "agent", "system"];
8
8
  var actorTypeSchema = z.enum(ACTOR_TYPES);
9
9
 
10
+ // ../shared/dist/agent-connection.js
11
+ import { z as z2 } from "zod";
12
+ var AGENT_CONNECTION_TOKEN_PREFIX = "sp_agent_";
13
+ var deviceAuthorizationResponseSchema = z2.object({
14
+ device_code: z2.string().min(43),
15
+ user_code: z2.string().min(8),
16
+ verification_uri: z2.string().url(),
17
+ verification_uri_complete: z2.string().url(),
18
+ expires_in: z2.number().int().positive(),
19
+ interval: z2.number().int().positive()
20
+ });
21
+ var deviceTokenResponseSchema = z2.object({
22
+ access_token: z2.string().startsWith(AGENT_CONNECTION_TOKEN_PREFIX).min(40),
23
+ token_type: z2.literal("Bearer"),
24
+ scope: z2.string(),
25
+ expires_in: z2.number().int().positive()
26
+ });
27
+ var deviceTokenErrorSchema = z2.object({
28
+ error: z2.string(),
29
+ error_description: z2.string().optional(),
30
+ interval: z2.number().int().positive().optional()
31
+ });
32
+
10
33
  // ../shared/dist/analytics-defaults.js
11
34
  var ANALYTICS_BATCH_LIMITS = {
12
35
  maxEventsPerRequest: 50,
@@ -23,7 +46,7 @@ var ANALYTICS_RETENTION_DEFAULTS = {
23
46
  };
24
47
 
25
48
  // ../shared/dist/analytics-booking.js
26
- import { z as z2 } from "zod";
49
+ import { z as z3 } from "zod";
27
50
  var bookingProviders = ["treatwell", "beautinda", "other"];
28
51
  var bookingAttributionModes = [
29
52
  "outbound_click_and_utm",
@@ -45,16 +68,16 @@ var bookingAttributionConfidences = [
45
68
  "manual_import",
46
69
  "verified_webhook"
47
70
  ];
48
- var bookingProviderSchema = z2.enum(bookingProviders);
49
- var bookingAttributionModeSchema = z2.enum(bookingAttributionModes);
50
- var bookingSignalSourceSchema = z2.enum(bookingSignalSources);
51
- var bookingAttributionConfidenceSchema = z2.enum(bookingAttributionConfidences);
52
- var bookingProviderHintSchema = z2.object({
71
+ var bookingProviderSchema = z3.enum(bookingProviders);
72
+ var bookingAttributionModeSchema = z3.enum(bookingAttributionModes);
73
+ var bookingSignalSourceSchema = z3.enum(bookingSignalSources);
74
+ var bookingAttributionConfidenceSchema = z3.enum(bookingAttributionConfidences);
75
+ var bookingProviderHintSchema = z3.object({
53
76
  bookingProvider: bookingProviderSchema,
54
- bookingUrlHost: z2.string().min(1).max(253),
77
+ bookingUrlHost: z3.string().min(1).max(253),
55
78
  bookingAttributionMode: bookingAttributionModeSchema,
56
- utmContent: z2.string().min(1).max(200).optional(),
57
- successCondition: z2.literal("redirect_status=succeeded").optional()
79
+ utmContent: z3.string().min(1).max(200).optional(),
80
+ successCondition: z3.literal("redirect_status=succeeded").optional()
58
81
  }).superRefine((hint, context) => {
59
82
  if (hint.successCondition !== void 0 && hint.bookingAttributionMode !== "provider_redirect") {
60
83
  context.addIssue({
@@ -66,17 +89,15 @@ var bookingProviderHintSchema = z2.object({
66
89
  });
67
90
 
68
91
  // ../shared/dist/analytics-contract.js
69
- import { z as z3 } from "zod";
70
- var ANALYTICS_CONTRACT_VERSION = "analytics-contract.v1";
71
- var ANALYTICS_CONTRACT_HASH = "sha256:a91bddcc3c5e4196933b0335d03eaf41ff929cb736bdd694fe54d07ab52dada1";
92
+ import { z as z4 } from "zod";
72
93
  var ANALYTICS_IMPORT_SCHEMA_VERSION = "analytics-provider-import.v1";
73
- var analyticsImportTargetIdSchema = z3.string().min(1).max(120).regex(/^[a-zA-Z][a-zA-Z0-9]*(?:[._-][a-zA-Z0-9]+)*$/u);
74
- var analyticsProviderImportRowSchema = z3.object({
94
+ var analyticsImportTargetIdSchema = z4.string().min(1).max(120).regex(/^[a-zA-Z][a-zA-Z0-9]*(?:[._-][a-zA-Z0-9]+)*$/u);
95
+ var analyticsProviderImportRowSchema = z4.object({
75
96
  targetId: analyticsImportTargetIdSchema,
76
- occurredAt: z3.string().datetime({ offset: true }),
77
- attributionConfidence: z3.enum(["provider_reported", "manual_import"]),
78
- providerEventId: z3.string().trim().min(1).max(160).optional(),
79
- idempotencyKey: z3.string().trim().min(1).max(160).optional()
97
+ occurredAt: z4.string().datetime({ offset: true }),
98
+ attributionConfidence: z4.enum(["provider_reported", "manual_import"]),
99
+ providerEventId: z4.string().trim().min(1).max(160).optional(),
100
+ idempotencyKey: z4.string().trim().min(1).max(160).optional()
80
101
  }).strict().superRefine((row, context) => {
81
102
  if (!row.providerEventId && !row.idempotencyKey) {
82
103
  context.addIssue({
@@ -86,24 +107,24 @@ var analyticsProviderImportRowSchema = z3.object({
86
107
  });
87
108
  }
88
109
  });
89
- var analyticsProviderImportSchema = z3.object({
90
- schemaVersion: z3.literal(ANALYTICS_IMPORT_SCHEMA_VERSION),
91
- provider: z3.enum(["treatwell", "beautinda", "other"]),
92
- sourceName: z3.string().trim().min(1).max(160).optional(),
93
- rows: z3.array(analyticsProviderImportRowSchema).min(1).max(1e3)
110
+ var analyticsProviderImportSchema = z4.object({
111
+ schemaVersion: z4.literal(ANALYTICS_IMPORT_SCHEMA_VERSION),
112
+ provider: z4.enum(["treatwell", "beautinda", "other"]),
113
+ sourceName: z4.string().trim().min(1).max(160).optional(),
114
+ rows: z4.array(analyticsProviderImportRowSchema).min(1).max(1e3)
94
115
  }).strict();
95
116
 
96
117
  // ../shared/dist/analytics-config.js
97
- import { z as z4 } from "zod";
118
+ import { z as z5 } from "zod";
98
119
  var ANALYTICS_CONFIG_LEASE_MS = 6e4;
99
- var analyticsMeasurementConfigSchema = z4.object({
100
- version: z4.literal(1),
101
- installationGeneration: z4.number().int().positive(),
102
- configRevision: z4.number().int().positive(),
103
- effectiveSiteMode: z4.enum(["disabled", "session_only", "full_analytics"]),
104
- measurementEnabled: z4.boolean(),
105
- issuedAt: z4.string().datetime({ offset: true }),
106
- expiresAt: z4.string().datetime({ offset: true })
120
+ var analyticsMeasurementConfigSchema = z5.object({
121
+ version: z5.literal(1),
122
+ installationGeneration: z5.number().int().positive(),
123
+ configRevision: z5.number().int().positive(),
124
+ effectiveSiteMode: z5.enum(["disabled", "session_only", "full_analytics"]),
125
+ measurementEnabled: z5.boolean(),
126
+ issuedAt: z5.string().datetime({ offset: true }),
127
+ expiresAt: z5.string().datetime({ offset: true })
107
128
  }).strict().superRefine((config, context) => {
108
129
  const lifetime = Date.parse(config.expiresAt) - Date.parse(config.issuedAt);
109
130
  if (lifetime <= 0 || lifetime > ANALYTICS_CONFIG_LEASE_MS) {
@@ -123,11 +144,11 @@ var analyticsMeasurementConfigSchema = z4.object({
123
144
  });
124
145
 
125
146
  // ../shared/dist/analytics-events.js
126
- import { z as z5 } from "zod";
147
+ import { z as z6 } from "zod";
127
148
  var ANALYTICS_SCHEMA_VERSION = "analytics.v1";
128
- var analyticsSessionIdSchema = z5.string().regex(/^cpa_s_[a-f0-9]{32}$/u);
129
- var analyticsVisitorIdSchema = z5.string().regex(/^cpa_v_[a-f0-9]{32}$/u);
130
- var analyticsPersistedIdentityHashSchema = z5.string().regex(/^[a-f0-9]{64}$/u);
149
+ var analyticsSessionIdSchema = z6.string().regex(/^cpa_s_[a-f0-9]{32}$/u);
150
+ var analyticsVisitorIdSchema = z6.string().regex(/^cpa_v_[a-f0-9]{32}$/u);
151
+ var analyticsPersistedIdentityHashSchema = z6.string().regex(/^[a-f0-9]{64}$/u);
131
152
  var analyticsEventNames = [
132
153
  "page_view",
133
154
  "section_view",
@@ -207,43 +228,43 @@ var analyticsValidityStatuses = [
207
228
  "rejected",
208
229
  "ignored"
209
230
  ];
210
- var analyticsEventNameSchema = z5.enum(analyticsEventNames);
211
- var serverOnlyAnalyticsEventSchema = z5.enum(serverOnlyAnalyticsEvents);
212
- var analyticsEventSourceSchema = z5.enum(analyticsEventSources);
213
- var analyticsIngestionChannelSchema = z5.enum(analyticsIngestionChannels);
214
- var analyticsTargetTypeSchema = z5.enum(analyticsTargetTypes);
215
- var analyticsDataAttributeEventSchema = z5.enum(analyticsDataAttributeEvents);
216
- var analyticsDeviceTypeSchema = z5.enum(analyticsDeviceTypes);
217
- var analyticsBotClassificationSchema = z5.enum(analyticsBotClassifications);
218
- var analyticsValidityStatusSchema = z5.enum(analyticsValidityStatuses);
219
- var analyticsPropertiesSchema = z5.record(z5.string(), z5.unknown());
220
- var analyticsTimestampSchema = z5.string().datetime({ offset: true });
221
- var analyticsBrowserEventSchema = z5.object({
222
- eventId: z5.string().min(1).max(160),
223
- installationGeneration: z5.number().int().positive().optional(),
224
- measurementMode: z5.enum(["session_only", "full_analytics"]).optional(),
231
+ var analyticsEventNameSchema = z6.enum(analyticsEventNames);
232
+ var serverOnlyAnalyticsEventSchema = z6.enum(serverOnlyAnalyticsEvents);
233
+ var analyticsEventSourceSchema = z6.enum(analyticsEventSources);
234
+ var analyticsIngestionChannelSchema = z6.enum(analyticsIngestionChannels);
235
+ var analyticsTargetTypeSchema = z6.enum(analyticsTargetTypes);
236
+ var analyticsDataAttributeEventSchema = z6.enum(analyticsDataAttributeEvents);
237
+ var analyticsDeviceTypeSchema = z6.enum(analyticsDeviceTypes);
238
+ var analyticsBotClassificationSchema = z6.enum(analyticsBotClassifications);
239
+ var analyticsValidityStatusSchema = z6.enum(analyticsValidityStatuses);
240
+ var analyticsPropertiesSchema = z6.record(z6.string(), z6.unknown());
241
+ var analyticsTimestampSchema = z6.string().datetime({ offset: true });
242
+ var analyticsBrowserEventSchema = z6.object({
243
+ eventId: z6.string().min(1).max(160),
244
+ installationGeneration: z6.number().int().positive().optional(),
245
+ measurementMode: z6.enum(["session_only", "full_analytics"]).optional(),
225
246
  eventName: analyticsEventNameSchema,
226
247
  eventSource: analyticsEventSourceSchema.optional().default("browser"),
227
- targetId: z5.string().min(1).max(160).optional(),
248
+ targetId: z6.string().min(1).max(160).optional(),
228
249
  targetType: analyticsTargetTypeSchema.optional(),
229
250
  visitorId: analyticsVisitorIdSchema.optional(),
230
251
  sessionId: analyticsSessionIdSchema,
231
- idempotencyKey: z5.string().min(1).max(240).optional(),
252
+ idempotencyKey: z6.string().min(1).max(240).optional(),
232
253
  occurredAt: analyticsTimestampSchema,
233
- pageUrl: z5.string().url().max(2048).optional(),
234
- pagePath: z5.string().min(1).max(1024).optional(),
235
- routeTemplate: z5.string().min(1).max(1024).optional(),
236
- referrer: z5.string().url().max(2048).optional(),
237
- utmSource: z5.string().min(1).max(200).optional(),
238
- utmMedium: z5.string().min(1).max(200).optional(),
239
- utmCampaign: z5.string().min(1).max(200).optional(),
240
- utmContent: z5.string().min(1).max(200).optional(),
241
- utmTerm: z5.string().min(1).max(200).optional(),
254
+ pageUrl: z6.string().url().max(2048).optional(),
255
+ pagePath: z6.string().min(1).max(1024).optional(),
256
+ routeTemplate: z6.string().min(1).max(1024).optional(),
257
+ referrer: z6.string().url().max(2048).optional(),
258
+ utmSource: z6.string().min(1).max(200).optional(),
259
+ utmMedium: z6.string().min(1).max(200).optional(),
260
+ utmCampaign: z6.string().min(1).max(200).optional(),
261
+ utmContent: z6.string().min(1).max(200).optional(),
262
+ utmTerm: z6.string().min(1).max(200).optional(),
242
263
  deviceType: analyticsDeviceTypeSchema.optional(),
243
- browserName: z5.string().min(1).max(120).optional(),
244
- osName: z5.string().min(1).max(120).optional(),
245
- country: z5.string().min(1).max(80).optional(),
246
- region: z5.string().min(1).max(120).optional(),
264
+ browserName: z6.string().min(1).max(120).optional(),
265
+ osName: z6.string().min(1).max(120).optional(),
266
+ country: z6.string().min(1).max(80).optional(),
267
+ region: z6.string().min(1).max(120).optional(),
247
268
  properties: analyticsPropertiesSchema.optional().default({})
248
269
  }).superRefine((event, context) => {
249
270
  if (isServerOnlyAnalyticsEvent(event.eventName)) {
@@ -268,44 +289,44 @@ var analyticsBrowserEventSchema = z5.object({
268
289
  });
269
290
  }
270
291
  });
271
- var analyticsBrowserEventPayloadSchema = z5.object({
272
- siteKey: z5.string().min(1),
273
- schemaVersion: z5.literal(ANALYTICS_SCHEMA_VERSION),
274
- mode: z5.enum(["live", "test"]).optional().default("live"),
275
- events: z5.array(analyticsBrowserEventSchema).min(1).max(50)
292
+ var analyticsBrowserEventPayloadSchema = z6.object({
293
+ siteKey: z6.string().min(1),
294
+ schemaVersion: z6.literal(ANALYTICS_SCHEMA_VERSION),
295
+ mode: z6.enum(["live", "test"]).optional().default("live"),
296
+ events: z6.array(analyticsBrowserEventSchema).min(1).max(50)
276
297
  });
277
- var analyticsNormalizedEventBaseSchema = z5.object({
278
- site_id: z5.string().uuid(),
279
- event_id: z5.string().min(1).max(160),
280
- schema_version: z5.literal(ANALYTICS_SCHEMA_VERSION),
298
+ var analyticsNormalizedEventBaseSchema = z6.object({
299
+ site_id: z6.string().uuid(),
300
+ event_id: z6.string().min(1).max(160),
301
+ schema_version: z6.literal(ANALYTICS_SCHEMA_VERSION),
281
302
  event_name: analyticsEventNameSchema,
282
303
  event_source: analyticsEventSourceSchema,
283
304
  ingestion_channel: analyticsIngestionChannelSchema,
284
- target_id: z5.string().min(1).max(160).nullable().optional(),
305
+ target_id: z6.string().min(1).max(160).nullable().optional(),
285
306
  target_type: analyticsTargetTypeSchema.nullable().optional(),
286
- dedupe_key: z5.string().regex(/^analytics_dedupe_v1_[a-f0-9]{64}$/u).nullable().optional(),
287
- idempotency_key: z5.string().min(1).max(240).nullable().optional(),
307
+ dedupe_key: z6.string().regex(/^analytics_dedupe_v1_[a-f0-9]{64}$/u).nullable().optional(),
308
+ idempotency_key: z6.string().min(1).max(240).nullable().optional(),
288
309
  bot_classification: analyticsBotClassificationSchema,
289
310
  validity_status: analyticsValidityStatusSchema,
290
- rejection_reason: z5.string().min(1).max(240).nullable().optional(),
311
+ rejection_reason: z6.string().min(1).max(240).nullable().optional(),
291
312
  occurred_at: analyticsTimestampSchema,
292
313
  received_at: analyticsTimestampSchema,
293
- page_url: z5.string().url().max(2048).nullable().optional(),
294
- page_path: z5.string().min(1).max(1024).nullable().optional(),
295
- route_template: z5.string().min(1).max(1024).nullable().optional(),
296
- referrer: z5.string().url().max(2048).nullable().optional(),
297
- utm_source: z5.string().min(1).max(200).nullable().optional(),
298
- utm_medium: z5.string().min(1).max(200).nullable().optional(),
299
- utm_campaign: z5.string().min(1).max(200).nullable().optional(),
300
- utm_content: z5.string().min(1).max(200).nullable().optional(),
301
- utm_term: z5.string().min(1).max(200).nullable().optional(),
302
- country: z5.string().min(1).max(80).nullable().optional(),
303
- region: z5.string().min(1).max(120).nullable().optional(),
314
+ page_url: z6.string().url().max(2048).nullable().optional(),
315
+ page_path: z6.string().min(1).max(1024).nullable().optional(),
316
+ route_template: z6.string().min(1).max(1024).nullable().optional(),
317
+ referrer: z6.string().url().max(2048).nullable().optional(),
318
+ utm_source: z6.string().min(1).max(200).nullable().optional(),
319
+ utm_medium: z6.string().min(1).max(200).nullable().optional(),
320
+ utm_campaign: z6.string().min(1).max(200).nullable().optional(),
321
+ utm_content: z6.string().min(1).max(200).nullable().optional(),
322
+ utm_term: z6.string().min(1).max(200).nullable().optional(),
323
+ country: z6.string().min(1).max(80).nullable().optional(),
324
+ region: z6.string().min(1).max(120).nullable().optional(),
304
325
  device_type: analyticsDeviceTypeSchema,
305
- browser_name: z5.string().min(1).max(120).nullable().optional(),
306
- os_name: z5.string().min(1).max(120).nullable().optional(),
307
- provider: z5.string().min(1).max(120).nullable().optional(),
308
- provider_event_id: z5.string().min(1).max(240).nullable().optional(),
326
+ browser_name: z6.string().min(1).max(120).nullable().optional(),
327
+ os_name: z6.string().min(1).max(120).nullable().optional(),
328
+ provider: z6.string().min(1).max(120).nullable().optional(),
329
+ provider_event_id: z6.string().min(1).max(240).nullable().optional(),
309
330
  properties: analyticsPropertiesSchema
310
331
  });
311
332
  var analyticsRawNormalizedEventSchema = analyticsNormalizedEventBaseSchema.extend({
@@ -321,11 +342,11 @@ function isServerOnlyAnalyticsEvent(eventName) {
321
342
  }
322
343
 
323
344
  // ../shared/dist/analytics-manifest.js
324
- import { z as z6 } from "zod";
325
- var analyticsTargetIdSchema = z6.string().min(1).max(120).regex(/^[a-zA-Z][a-zA-Z0-9]*(?:[._-][a-zA-Z0-9]+)*$/u, {
345
+ import { z as z7 } from "zod";
346
+ var analyticsTargetIdSchema = z7.string().min(1).max(120).regex(/^[a-zA-Z][a-zA-Z0-9]*(?:[._-][a-zA-Z0-9]+)*$/u, {
326
347
  message: "Analytics target IDs must be stable identifiers without whitespace or visible copy."
327
348
  });
328
- var analyticsManifestRecordSchema = z6.record(z6.string(), z6.unknown());
349
+ var analyticsManifestRecordSchema = z7.record(z7.string(), z7.unknown());
329
350
  var analyticsFormPurposes = [
330
351
  "contact",
331
352
  "lead",
@@ -334,21 +355,21 @@ var analyticsFormPurposes = [
334
355
  "login",
335
356
  "other"
336
357
  ];
337
- var analyticsFormPurposeSchema = z6.enum(analyticsFormPurposes);
338
- var analyticsManifestRouteSchema = z6.object({
339
- path: z6.string().min(1).max(1024),
340
- pageType: z6.string().min(1).max(120).optional(),
341
- label: z6.string().min(1).max(200).optional()
358
+ var analyticsFormPurposeSchema = z7.enum(analyticsFormPurposes);
359
+ var analyticsManifestRouteSchema = z7.object({
360
+ path: z7.string().min(1).max(1024),
361
+ pageType: z7.string().min(1).max(120).optional(),
362
+ label: z7.string().min(1).max(200).optional()
342
363
  }).passthrough();
343
- var analyticsManifestTargetSchema = z6.object({
364
+ var analyticsManifestTargetSchema = z7.object({
344
365
  id: analyticsTargetIdSchema,
345
366
  type: analyticsTargetTypeSchema,
346
367
  event: analyticsEventNameSchema.optional(),
347
- events: z6.array(analyticsEventNameSchema).min(1).max(20).optional(),
348
- route: z6.string().min(1).max(1024).optional(),
349
- label: z6.string().min(1).max(200).optional(),
350
- description: z6.string().min(1).max(1e3).optional(),
351
- autoActive: z6.boolean().optional(),
368
+ events: z7.array(analyticsEventNameSchema).min(1).max(20).optional(),
369
+ route: z7.string().min(1).max(1024).optional(),
370
+ label: z7.string().min(1).max(200).optional(),
371
+ description: z7.string().min(1).max(1e3).optional(),
372
+ autoActive: z7.boolean().optional(),
352
373
  sourceHints: analyticsManifestRecordSchema.optional()
353
374
  }).passthrough().superRefine((target, context) => {
354
375
  if (target.event === void 0 && target.events === void 0) {
@@ -373,21 +394,21 @@ var analyticsManifestTargetSchema = z6.object({
373
394
  });
374
395
  }
375
396
  });
376
- var analyticsManifestSchema = z6.object({
377
- schemaVersion: z6.literal(ANALYTICS_SCHEMA_VERSION),
378
- siteId: z6.string().min(1),
379
- siteKeyRef: z6.string().regex(/^env:[A-Z][A-Z0-9_]*$/u, {
397
+ var analyticsManifestSchema = z7.object({
398
+ schemaVersion: z7.literal(ANALYTICS_SCHEMA_VERSION),
399
+ siteId: z7.string().min(1),
400
+ siteKeyRef: z7.string().regex(/^env:[A-Z][A-Z0-9_]*$/u, {
380
401
  message: "siteKeyRef must be an environment-variable reference."
381
402
  }),
382
- siteKeyLookup: z6.string().regex(/^pk_siteplane_[A-Za-z0-9_-]{16}$/),
383
- routes: z6.array(analyticsManifestRouteSchema),
384
- targets: z6.array(analyticsManifestTargetSchema),
403
+ siteKeyLookup: z7.string().regex(/^pk_siteplane_[A-Za-z0-9_-]{16}$/),
404
+ routes: z7.array(analyticsManifestRouteSchema),
405
+ targets: z7.array(analyticsManifestTargetSchema),
385
406
  metadata: analyticsManifestRecordSchema.optional(),
386
- siteKey: z6.string().optional(),
387
- secretKey: z6.string().optional(),
388
- rawKey: z6.string().optional(),
389
- token: z6.string().optional(),
390
- accessToken: z6.string().optional()
407
+ siteKey: z7.string().optional(),
408
+ secretKey: z7.string().optional(),
409
+ rawKey: z7.string().optional(),
410
+ token: z7.string().optional(),
411
+ accessToken: z7.string().optional()
391
412
  }).passthrough().superRefine((manifest, context) => {
392
413
  const targetIds = /* @__PURE__ */ new Set();
393
414
  for (const [index, target] of manifest.targets.entries()) {
@@ -431,9 +452,9 @@ function isPlainRecord(value) {
431
452
  }
432
453
 
433
454
  // ../shared/dist/analytics-metrics.js
434
- import { z as z7 } from "zod";
455
+ import { z as z8 } from "zod";
435
456
  var analyticsVisitorQualities = ["exact", "estimated"];
436
- var analyticsVisitorQualitySchema = z7.enum(analyticsVisitorQualities);
457
+ var analyticsVisitorQualitySchema = z8.enum(analyticsVisitorQualities);
437
458
  var analyticsKpiKeys = [
438
459
  "pageViews",
439
460
  "sessions",
@@ -445,7 +466,7 @@ var analyticsKpiKeys = [
445
466
  "conversionRate",
446
467
  "inquiryRate"
447
468
  ];
448
- var analyticsKpiKeySchema = z7.enum(analyticsKpiKeys);
469
+ var analyticsKpiKeySchema = z8.enum(analyticsKpiKeys);
449
470
 
450
471
  // ../shared/dist/analytics-privacy.js
451
472
  var serverPropertySchemas = {
@@ -483,7 +504,7 @@ function revenuePropertySchema() {
483
504
  }
484
505
 
485
506
  // ../shared/dist/assets.js
486
- import { z as z8 } from "zod";
507
+ import { z as z9 } from "zod";
487
508
  var ASSET_STAGES = ["staging", "final", "deleted"];
488
509
  var ASSET_VISIBILITIES = ["private", "public", "deleted"];
489
510
  var ASSET_USAGE_ENTITY_TYPES = [
@@ -492,13 +513,13 @@ var ASSET_USAGE_ENTITY_TYPES = [
492
513
  "change_set",
493
514
  "published_value"
494
515
  ];
495
- var assetStageSchema = z8.enum(ASSET_STAGES);
496
- var assetVisibilitySchema = z8.enum(ASSET_VISIBILITIES);
497
- var assetUsageEntityTypeSchema = z8.enum(ASSET_USAGE_ENTITY_TYPES);
498
- var brandingAccentColorSchema = z8.string().regex(/^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/);
516
+ var assetStageSchema = z9.enum(ASSET_STAGES);
517
+ var assetVisibilitySchema = z9.enum(ASSET_VISIBILITIES);
518
+ var assetUsageEntityTypeSchema = z9.enum(ASSET_USAGE_ENTITY_TYPES);
519
+ var brandingAccentColorSchema = z9.string().regex(/^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/);
499
520
 
500
521
  // ../shared/dist/booking-contracts.js
501
- import { z as z9 } from "zod";
522
+ import { z as z10 } from "zod";
502
523
  var bookingStatuses = [
503
524
  "pending_payment",
504
525
  "confirmed",
@@ -553,30 +574,30 @@ var bookingResourceKinds = [
553
574
  "equipment",
554
575
  "other"
555
576
  ];
556
- var bookingStatusSchema = z9.enum(bookingStatuses);
557
- var bookingPaymentStatusSchema = z9.enum(bookingPaymentStatuses);
558
- var bookingAccountReadinessStatusSchema = z9.enum(bookingAccountReadinessStatuses);
559
- var bookingRefundStatusSchema = z9.enum(bookingRefundStatuses);
560
- var bookingDisputeStatusSchema = z9.enum(bookingDisputeStatuses);
561
- var bookingPaymentModeSchema = z9.enum(bookingPaymentModes);
562
- var bookingPaymentCollectionTypeSchema = z9.enum(bookingPaymentCollectionTypes);
563
- var bookingPaymentCollectionSchema = z9.discriminatedUnion("type", [
564
- z9.object({ type: z9.literal("full_amount") }).strict(),
565
- z9.object({
566
- type: z9.literal("deposit_percent"),
567
- depositPercent: z9.number().int().min(10).max(90)
577
+ var bookingStatusSchema = z10.enum(bookingStatuses);
578
+ var bookingPaymentStatusSchema = z10.enum(bookingPaymentStatuses);
579
+ var bookingAccountReadinessStatusSchema = z10.enum(bookingAccountReadinessStatuses);
580
+ var bookingRefundStatusSchema = z10.enum(bookingRefundStatuses);
581
+ var bookingDisputeStatusSchema = z10.enum(bookingDisputeStatuses);
582
+ var bookingPaymentModeSchema = z10.enum(bookingPaymentModes);
583
+ var bookingPaymentCollectionTypeSchema = z10.enum(bookingPaymentCollectionTypes);
584
+ var bookingPaymentCollectionSchema = z10.discriminatedUnion("type", [
585
+ z10.object({ type: z10.literal("full_amount") }).strict(),
586
+ z10.object({
587
+ type: z10.literal("deposit_percent"),
588
+ depositPercent: z10.number().int().min(10).max(90)
568
589
  }).strict()
569
590
  ]);
570
591
  var bookingPaymentChoices = ["onsite", "online"];
571
- var bookingPaymentChoiceSchema = z9.enum(bookingPaymentChoices);
572
- var bookingPaymentSnapshotSchema = z9.object({
573
- snapshotId: z9.string().uuid(),
574
- snapshotVersion: z9.number().int().positive(),
575
- currency: z9.literal("EUR"),
576
- totalAmountCents: z9.number().int().min(0),
577
- onlineAmountCents: z9.number().int().min(0),
578
- onsiteRemainderCents: z9.number().int().min(0),
579
- maxStripeRefundAmountCents: z9.number().int().min(0)
592
+ var bookingPaymentChoiceSchema = z10.enum(bookingPaymentChoices);
593
+ var bookingPaymentSnapshotSchema = z10.object({
594
+ snapshotId: z10.string().uuid(),
595
+ snapshotVersion: z10.number().int().positive(),
596
+ currency: z10.literal("EUR"),
597
+ totalAmountCents: z10.number().int().min(0),
598
+ onlineAmountCents: z10.number().int().min(0),
599
+ onsiteRemainderCents: z10.number().int().min(0),
600
+ maxStripeRefundAmountCents: z10.number().int().min(0)
580
601
  }).strict().superRefine((snapshot, context) => {
581
602
  if (snapshot.onlineAmountCents + snapshot.onsiteRemainderCents !== snapshot.totalAmountCents) {
582
603
  context.addIssue({
@@ -591,17 +612,17 @@ var bookingPaymentSnapshotSchema = z9.object({
591
612
  });
592
613
  }
593
614
  });
594
- var bookingServiceVariantSchema = z9.object({
595
- id: z9.string().uuid(),
596
- name: z9.string().trim().min(1).max(120),
597
- durationMinutes: z9.number().int().min(1).max(1440),
598
- priceCents: z9.number().int().min(0).nullable()
615
+ var bookingServiceVariantSchema = z10.object({
616
+ id: z10.string().uuid(),
617
+ name: z10.string().trim().min(1).max(120),
618
+ durationMinutes: z10.number().int().min(1).max(1440),
619
+ priceCents: z10.number().int().min(0).nullable()
599
620
  }).strict();
600
- var bookingServiceVariantsSchema = z9.array(bookingServiceVariantSchema).min(1).max(20);
601
- var isoDateSchema = z9.string().regex(/^\d{4}-\d{2}-\d{2}$/);
602
- var utcDateTimeSchema = z9.string().datetime();
603
- var bookingLocalTimeSchema = z9.string().regex(/^(?:[01]\d|2[0-3]):[0-5]\d$/);
604
- var bookingAvailabilityIntervalsSchema = z9.array(z9.object({
621
+ var bookingServiceVariantsSchema = z10.array(bookingServiceVariantSchema).min(1).max(20);
622
+ var isoDateSchema = z10.string().regex(/^\d{4}-\d{2}-\d{2}$/);
623
+ var utcDateTimeSchema = z10.string().datetime();
624
+ var bookingLocalTimeSchema = z10.string().regex(/^(?:[01]\d|2[0-3]):[0-5]\d$/);
625
+ var bookingAvailabilityIntervalsSchema = z10.array(z10.object({
605
626
  start: bookingLocalTimeSchema,
606
627
  end: bookingLocalTimeSchema
607
628
  }).strict().refine((interval) => interval.end > interval.start)).superRefine((intervals, context) => {
@@ -616,76 +637,78 @@ var bookingAvailabilityIntervalsSchema = z9.array(z9.object({
616
637
  }
617
638
  }
618
639
  });
619
- var bookingPublicConfigSchema = z9.object({
620
- site: z9.object({
621
- displayName: z9.string().trim().min(1),
622
- timezone: z9.string().trim().min(1),
623
- locale: z9.string().trim().min(2),
624
- bookingPageSlug: z9.string().regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/).min(2).max(64),
625
- privacyUrl: z9.string().url().nullable()
640
+ var bookingPublicConfigSchema = z10.object({
641
+ site: z10.object({
642
+ displayName: z10.string().trim().min(1),
643
+ timezone: z10.string().trim().min(1),
644
+ locale: z10.string().trim().min(2),
645
+ bookingPageSlug: z10.string().regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/).min(2).max(64),
646
+ privacyUrl: z10.string().url().nullable()
626
647
  }),
627
- branding: z9.object({
628
- logoUrl: z9.string().url().nullable(),
629
- accentColor: z9.string().trim().min(1).nullable()
648
+ branding: z10.object({
649
+ logoUrl: z10.string().url().nullable(),
650
+ accentColor: z10.string().trim().min(1).nullable()
630
651
  }),
631
- settings: z9.object({
632
- slotIntervalMinutes: z9.number().int().positive(),
633
- minLeadMinutes: z9.number().int().min(0),
634
- minCancelLeadMinutes: z9.number().int().min(0),
635
- maxAdvanceDays: z9.number().int().min(1),
636
- requirePhone: z9.boolean(),
637
- collectNote: z9.boolean(),
638
- confirmationMessage: z9.string().nullable()
652
+ settings: z10.object({
653
+ slotIntervalMinutes: z10.number().int().positive(),
654
+ minLeadMinutes: z10.number().int().min(0),
655
+ minCancelLeadMinutes: z10.number().int().min(0),
656
+ maxAdvanceDays: z10.number().int().min(1),
657
+ requirePhone: z10.boolean(),
658
+ collectNote: z10.boolean(),
659
+ confirmationMessage: z10.string().nullable()
639
660
  }),
640
661
  /** Freitexte des Salons, im Kassen-Schritt vor der Bestaetigung sichtbar. */
641
- policies: z9.object({
642
- cancellation: z9.string().nullable(),
643
- lateArrival: z9.string().nullable()
662
+ policies: z10.object({
663
+ cancellation: z10.string().nullable(),
664
+ lateArrival: z10.string().nullable()
644
665
  }),
645
- payment: z9.object({
666
+ payment: z10.object({
646
667
  mode: bookingPaymentModeSchema,
647
668
  collection: bookingPaymentCollectionSchema,
648
- onlinePaymentsReady: z9.boolean()
669
+ onlinePaymentsReady: z10.boolean()
649
670
  }).strict(),
650
- serviceCategories: z9.array(z9.object({
651
- id: z9.string().uuid(),
652
- name: z9.string().trim().min(1),
653
- sortOrder: z9.number().int()
671
+ serviceCategories: z10.array(z10.object({
672
+ id: z10.string().uuid(),
673
+ name: z10.string().trim().min(1),
674
+ sortOrder: z10.number().int()
654
675
  })),
655
- serviceSubcategories: z9.array(z9.object({
656
- id: z9.string().uuid(),
657
- categoryId: z9.string().uuid(),
658
- name: z9.string().trim().min(1),
659
- sortOrder: z9.number().int()
676
+ serviceSubcategories: z10.array(z10.object({
677
+ id: z10.string().uuid(),
678
+ categoryId: z10.string().uuid(),
679
+ name: z10.string().trim().min(1),
680
+ sortOrder: z10.number().int()
660
681
  })),
661
- services: z9.array(z9.object({
662
- id: z9.string().trim().min(1),
663
- name: z9.string().trim().min(1),
664
- durationMinutes: z9.number().int().positive(),
665
- priceCents: z9.number().int().min(0).nullable(),
666
- currency: z9.string().regex(/^[A-Z]{3}$/),
667
- description: z9.string().nullable(),
668
- categoryId: z9.string().uuid(),
669
- subcategoryId: z9.string().uuid().nullable(),
682
+ services: z10.array(z10.object({
683
+ id: z10.string().trim().min(1),
684
+ name: z10.string().trim().min(1),
685
+ durationMinutes: z10.number().int().positive(),
686
+ priceCents: z10.number().int().min(0).nullable(),
687
+ currency: z10.string().regex(/^[A-Z]{3}$/),
688
+ description: z10.string().nullable(),
689
+ categoryId: z10.string().uuid(),
690
+ subcategoryId: z10.string().uuid().nullable(),
670
691
  variants: bookingServiceVariantsSchema,
671
- allowsAnyResource: z9.boolean(),
672
- sortOrder: z9.number().int()
692
+ allowsAnyResource: z10.boolean(),
693
+ sortOrder: z10.number().int()
673
694
  })),
674
- resources: z9.array(z9.object({
675
- id: z9.string().trim().min(1),
676
- name: z9.string().trim().min(1),
677
- kind: z9.enum(bookingResourceKinds)
695
+ resources: z10.array(z10.object({
696
+ id: z10.string().trim().min(1),
697
+ name: z10.string().trim().min(1),
698
+ kind: z10.enum(bookingResourceKinds),
699
+ /** Profilfoto für „Bei wem?“; `null` ohne Foto. */
700
+ photoUrl: z10.string().url().nullable()
678
701
  })),
679
- serviceResources: z9.array(z9.object({
680
- serviceId: z9.string().trim().min(1),
681
- resourceId: z9.string().trim().min(1)
702
+ serviceResources: z10.array(z10.object({
703
+ serviceId: z10.string().trim().min(1),
704
+ resourceId: z10.string().trim().min(1)
682
705
  }))
683
706
  });
684
- var bookingItemSchema = z9.object({
685
- serviceId: z9.string().trim().min(1),
686
- variantId: z9.string().trim().min(1)
707
+ var bookingItemSchema = z10.object({
708
+ serviceId: z10.string().trim().min(1),
709
+ variantId: z10.string().trim().min(1)
687
710
  }).strict();
688
- var bookingItemsSchema = z9.array(bookingItemSchema).min(1).max(10);
711
+ var bookingItemsSchema = z10.array(bookingItemSchema).min(1).max(10);
689
712
  function parseBookingItemsParam(value) {
690
713
  const items = value.split(",").map((entry) => entry.trim()).filter((entry) => entry !== "").map((entry) => {
691
714
  const [serviceId, variantId, ...rest] = entry.split(":");
@@ -693,36 +716,36 @@ function parseBookingItemsParam(value) {
693
716
  });
694
717
  return items.every((item) => item !== null) ? items : null;
695
718
  }
696
- var bookingSlotsQuerySchema = z9.object({
697
- items: z9.preprocess((value) => typeof value === "string" ? parseBookingItemsParam(value) : value, bookingItemsSchema),
698
- resourceId: z9.string().trim().min(1).optional(),
719
+ var bookingSlotsQuerySchema = z10.object({
720
+ items: z10.preprocess((value) => typeof value === "string" ? parseBookingItemsParam(value) : value, bookingItemsSchema),
721
+ resourceId: z10.string().trim().min(1).optional(),
699
722
  fromDate: isoDateSchema,
700
723
  toDate: isoDateSchema
701
724
  });
702
- var bookingSlotsResponseSchema = z9.object({
703
- timezone: z9.string().trim().min(1),
725
+ var bookingSlotsResponseSchema = z10.object({
726
+ timezone: z10.string().trim().min(1),
704
727
  items: bookingItemsSchema,
705
728
  // Reine Behandlungsdauer ohne Puffer: das UI zeigt damit die Terminspanne,
706
729
  // ohne selbst rechnen zu muessen.
707
- totalDurationMinutes: z9.number().int().min(1),
708
- mode: z9.enum(["any", "resource"]),
709
- slots: z9.array(z9.object({
730
+ totalDurationMinutes: z10.number().int().min(1),
731
+ mode: z10.enum(["any", "resource"]),
732
+ slots: z10.array(z10.object({
710
733
  startUtc: utcDateTimeSchema,
711
- resourceId: z9.string().trim().min(1).optional()
734
+ resourceId: z10.string().trim().min(1).optional()
712
735
  }))
713
736
  });
714
- var bookingAvailabilityQuerySchema = z9.object({
715
- items: z9.preprocess((value) => typeof value === "string" ? parseBookingItemsParam(value) : value, bookingItemsSchema),
716
- resourceId: z9.string().trim().min(1).optional(),
737
+ var bookingAvailabilityQuerySchema = z10.object({
738
+ items: z10.preprocess((value) => typeof value === "string" ? parseBookingItemsParam(value) : value, bookingItemsSchema),
739
+ resourceId: z10.string().trim().min(1).optional(),
717
740
  fromDate: isoDateSchema,
718
741
  toDate: isoDateSchema
719
742
  });
720
- var bookingAvailabilityResponseSchema = z9.object({
721
- timezone: z9.string().trim().min(1),
722
- totalDurationMinutes: z9.number().int().min(1),
723
- days: z9.array(z9.object({
743
+ var bookingAvailabilityResponseSchema = z10.object({
744
+ timezone: z10.string().trim().min(1),
745
+ totalDurationMinutes: z10.number().int().min(1),
746
+ days: z10.array(z10.object({
724
747
  date: isoDateSchema,
725
- hasSlots: z9.boolean()
748
+ hasSlots: z10.boolean()
726
749
  })),
727
750
  /** Erster Tag mit Slot ab `fromDate`, auch ausserhalb des Fensters. */
728
751
  nextAvailableDate: isoDateSchema.nullable()
@@ -740,72 +763,72 @@ var bookingPublicErrorCodes = [
740
763
  "too_late",
741
764
  "not_found"
742
765
  ];
743
- var bookingPublicErrorSchema = z9.object({
744
- error: z9.enum(bookingPublicErrorCodes),
745
- message: z9.string().optional(),
746
- requestId: z9.string().optional()
766
+ var bookingPublicErrorSchema = z10.object({
767
+ error: z10.enum(bookingPublicErrorCodes),
768
+ message: z10.string().optional(),
769
+ requestId: z10.string().optional()
747
770
  }).strict();
748
- var bookingCreateRequestSchema = z9.object({
771
+ var bookingCreateRequestSchema = z10.object({
749
772
  items: bookingItemsSchema,
750
- resourceId: z9.string().min(1).nullable(),
773
+ resourceId: z10.string().min(1).nullable(),
751
774
  startUtc: utcDateTimeSchema,
752
- customer: z9.object({
753
- name: z9.string().min(1).max(120),
754
- email: z9.string().email().max(254),
755
- phone: z9.string().max(32).optional(),
756
- note: z9.string().max(1e3).optional()
775
+ customer: z10.object({
776
+ name: z10.string().min(1).max(120),
777
+ email: z10.string().email().max(254),
778
+ phone: z10.string().max(32).optional(),
779
+ note: z10.string().max(1e3).optional()
757
780
  }).strict(),
758
- hp: z9.string().optional(),
759
- clientToken: z9.string().uuid(),
781
+ hp: z10.string().optional(),
782
+ clientToken: z10.string().uuid(),
760
783
  paymentChoice: bookingPaymentChoiceSchema,
761
784
  // Werbe-Einwilligung. Bestaetigung, Erinnerung und Storno-Link sind davon
762
785
  // unabhaengig und werden immer versendet.
763
- consent: z9.object({
764
- marketingEmail: z9.boolean(),
765
- marketingSms: z9.boolean()
786
+ consent: z10.object({
787
+ marketingEmail: z10.boolean(),
788
+ marketingSms: z10.boolean()
766
789
  }).strict().optional()
767
790
  }).strict();
768
- var bookingPublicPaymentResponseSchema = z9.object({
769
- clientSecret: z9.string().min(1),
770
- stripeAccountId: z9.string().startsWith("acct_")
791
+ var bookingPublicPaymentResponseSchema = z10.object({
792
+ clientSecret: z10.string().min(1),
793
+ stripeAccountId: z10.string().startsWith("acct_")
771
794
  }).strict();
772
- var bookingCreateResponseSchema = z9.union([
773
- z9.object({
774
- status: z9.literal("confirmed"),
775
- booking: z9.object({
776
- id: z9.string().min(1),
795
+ var bookingCreateResponseSchema = z10.union([
796
+ z10.object({
797
+ status: z10.literal("confirmed"),
798
+ booking: z10.object({
799
+ id: z10.string().min(1),
777
800
  startUtc: utcDateTimeSchema,
778
801
  endUtc: utcDateTimeSchema,
779
- timezone: z9.string().trim().min(1),
780
- serviceName: z9.string().trim().min(1),
781
- resourceName: z9.string().trim().min(1)
802
+ timezone: z10.string().trim().min(1),
803
+ serviceName: z10.string().trim().min(1),
804
+ resourceName: z10.string().trim().min(1)
782
805
  }).strict(),
783
- manageUrl: z9.string().url(),
784
- confirmationMessage: z9.string().nullable()
806
+ manageUrl: z10.string().url(),
807
+ confirmationMessage: z10.string().nullable()
785
808
  }).strict(),
786
- z9.object({
787
- status: z9.literal("pending_payment"),
788
- bookingId: z9.string().min(1),
809
+ z10.object({
810
+ status: z10.literal("pending_payment"),
811
+ bookingId: z10.string().min(1),
789
812
  holdExpiresAt: utcDateTimeSchema,
790
813
  payment: bookingPublicPaymentResponseSchema,
791
- statusToken: z9.string().min(20),
792
- manageUrl: z9.string().url().optional()
814
+ statusToken: z10.string().min(20),
815
+ manageUrl: z10.string().url().optional()
793
816
  }).strict(),
794
817
  bookingPublicErrorSchema
795
818
  ]);
796
- var bookingStatusResponseSchema = z9.object({
819
+ var bookingStatusResponseSchema = z10.object({
797
820
  bookingStatus: bookingStatusSchema,
798
821
  paymentStatus: bookingPaymentStatusSchema,
799
822
  refundStatus: bookingRefundStatusSchema,
800
823
  disputeStatus: bookingDisputeStatusSchema,
801
824
  holdExpiresAt: utcDateTimeSchema.nullable()
802
825
  }).strict();
803
- var bookingCancelRequestSchema = z9.object({
804
- token: z9.string().min(20)
826
+ var bookingCancelRequestSchema = z10.object({
827
+ token: z10.string().min(20)
805
828
  });
806
- var bookingCancelResponseSchema = z9.union([
807
- z9.object({
808
- status: z9.enum(["cancelled", "already_cancelled", "too_late", "not_found"])
829
+ var bookingCancelResponseSchema = z10.union([
830
+ z10.object({
831
+ status: z10.enum(["cancelled", "already_cancelled", "too_late", "not_found"])
809
832
  }),
810
833
  bookingPublicErrorSchema
811
834
  ]);
@@ -814,33 +837,33 @@ var bookingMoveErrorCodes = [
814
837
  "booking_not_movable",
815
838
  "not_found"
816
839
  ];
817
- var bookingMoveRequestSchema = z9.object({
818
- bookingId: z9.string().uuid(),
840
+ var bookingMoveRequestSchema = z10.object({
841
+ bookingId: z10.string().uuid(),
819
842
  newStartUtc: utcDateTimeSchema,
820
- newResourceId: z9.string().uuid().optional(),
821
- notifyCustomer: z9.boolean().default(false),
822
- reason: z9.string().max(500).optional()
823
- });
824
- var bookingMoveResponseSchema = z9.union([
825
- z9.object({
826
- status: z9.literal("moved"),
827
- bookingId: z9.string().uuid(),
843
+ newResourceId: z10.string().uuid().optional(),
844
+ notifyCustomer: z10.boolean().default(false),
845
+ reason: z10.string().max(500).optional()
846
+ });
847
+ var bookingMoveResponseSchema = z10.union([
848
+ z10.object({
849
+ status: z10.literal("moved"),
850
+ bookingId: z10.string().uuid(),
828
851
  startUtc: utcDateTimeSchema,
829
852
  endUtc: utcDateTimeSchema,
830
- resourceId: z9.string().uuid()
853
+ resourceId: z10.string().uuid()
831
854
  }),
832
- z9.object({
833
- error: z9.enum(bookingMoveErrorCodes),
834
- message: z9.string().optional(),
835
- requestId: z9.string().optional()
855
+ z10.object({
856
+ error: z10.enum(bookingMoveErrorCodes),
857
+ message: z10.string().optional(),
858
+ requestId: z10.string().optional()
836
859
  })
837
860
  ]);
838
- var bookingManifestSchema = z9.object({
839
- schemaVersion: z9.number().int().positive(),
840
- siteId: z9.string().trim().min(1),
841
- bookingPageSlug: z9.string().regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/).min(2).max(64),
842
- integration: z9.literal("rewrite").optional(),
843
- productionOrigin: z9.string().url().optional()
861
+ var bookingManifestSchema = z10.object({
862
+ schemaVersion: z10.number().int().positive(),
863
+ siteId: z10.string().trim().min(1),
864
+ bookingPageSlug: z10.string().regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/).min(2).max(64),
865
+ integration: z10.literal("rewrite").optional(),
866
+ productionOrigin: z10.string().url().optional()
844
867
  }).passthrough();
845
868
  var secretManifestKeys = /* @__PURE__ */ new Set([
846
869
  "siteKey",
@@ -865,17 +888,17 @@ var BOOKING_CREATE_PAYLOAD_LIMIT_BYTES = 16 * 1024;
865
888
  import { z as z17 } from "zod";
866
889
 
867
890
  // ../shared/dist/field-id.js
868
- import { z as z10 } from "zod";
891
+ import { z as z11 } from "zod";
869
892
  var FIELD_ID_PATTERN = /^[a-z][a-z0-9_-]*(\.[a-z][a-z0-9_-]*)+$/;
870
- var fieldIdSchema = z10.string().regex(FIELD_ID_PATTERN, "Invalid field id");
893
+ var fieldIdSchema = z11.string().regex(FIELD_ID_PATTERN, "Invalid field id");
871
894
 
872
895
  // ../shared/dist/field-types.js
873
- import { z as z11 } from "zod";
896
+ import { z as z12 } from "zod";
874
897
  var FIELD_TYPES = ["text", "longText", "image", "link"];
875
- var fieldTypeSchema = z11.enum(FIELD_TYPES);
898
+ var fieldTypeSchema = z12.enum(FIELD_TYPES);
876
899
 
877
900
  // ../shared/dist/image-value.js
878
- import { z as z12 } from "zod";
901
+ import { z as z13 } from "zod";
879
902
  var SUPPORTED_IMAGE_CONTENT_TYPES = [
880
903
  "image/jpeg",
881
904
  "image/png",
@@ -884,21 +907,21 @@ var SUPPORTED_IMAGE_CONTENT_TYPES = [
884
907
  ];
885
908
  var maxImageUploadBytes = 10 * 1024 * 1024;
886
909
  var largeImageWarningBytes = 2 * 1024 * 1024;
887
- var imageContentTypeSchema = z12.enum(SUPPORTED_IMAGE_CONTENT_TYPES);
888
- var imageCropSchema = z12.object({
889
- x: z12.number().min(0).max(100),
890
- y: z12.number().min(0).max(100),
891
- zoom: z12.number().min(1).max(4),
892
- aspectRatio: z12.number().positive().max(10)
893
- });
894
- var imageValueSchema = z12.object({
895
- src: z12.string().trim().min(1),
896
- alt: z12.string().trim().min(1).max(300),
897
- width: z12.number().int().positive().optional(),
898
- height: z12.number().int().positive().optional(),
910
+ var imageContentTypeSchema = z13.enum(SUPPORTED_IMAGE_CONTENT_TYPES);
911
+ var imageCropSchema = z13.object({
912
+ x: z13.number().min(0).max(100),
913
+ y: z13.number().min(0).max(100),
914
+ zoom: z13.number().min(1).max(4),
915
+ aspectRatio: z13.number().positive().max(10)
916
+ });
917
+ var imageValueSchema = z13.object({
918
+ src: z13.string().trim().min(1),
919
+ alt: z13.string().trim().min(1).max(300),
920
+ width: z13.number().int().positive().optional(),
921
+ height: z13.number().int().positive().optional(),
899
922
  crop: imageCropSchema.optional(),
900
- assetId: z12.string().uuid().optional(),
901
- finalStorageProvider: z12.enum([
923
+ assetId: z13.string().uuid().optional(),
924
+ finalStorageProvider: z13.enum([
902
925
  "repo_static_assets",
903
926
  "repo_handoff",
904
927
  "site_owned_storage",
@@ -906,155 +929,151 @@ var imageValueSchema = z12.object({
906
929
  ]).optional()
907
930
  });
908
931
 
909
- // ../shared/dist/setup-deployment.js
910
- import { z as z13 } from "zod";
911
- var version = z13.string().regex(/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/u);
912
- var siteSetupPackagesSchema = z13.object({
913
- siteplane: version,
914
- runtimeNext: version,
915
- analytics: version.optional()
916
- }).strict();
917
- var hash = z13.string().regex(/^sha256:[0-9a-f]{64}$/u);
918
- var setupDeploymentRecordSchema = z13.object({
919
- version: z13.literal(1),
920
- operationId: z13.string().uuid(),
921
- provider: z13.literal("vercel"),
922
- projectId: z13.string().regex(/^prj_[A-Za-z0-9]+$/u),
923
- teamId: z13.string().regex(/^(?:team|user)_[A-Za-z0-9]+$/u),
924
- origin: z13.string().url().refine((value) => {
925
- const url = new URL(value);
926
- return url.protocol === "https:" && url.origin === value && !url.username && !url.password;
927
- }),
928
- deploymentId: z13.string().regex(/^dpl_[A-Za-z0-9]+$/u).nullable(),
929
- revision: z13.string().regex(/^[0-9a-f]{40}$/u),
930
- fieldContractHash: hash,
931
- packages: siteSetupPackagesSchema,
932
- configurationFingerprint: hash,
933
- adminSecretGeneration: z13.string().uuid(),
934
- revalidationGeneration: z13.number().int().positive(),
935
- startedAt: z13.string().datetime(),
936
- environmentWrittenAt: z13.string().datetime().nullable(),
937
- deployRequestedAt: z13.string().datetime().nullable(),
938
- deadline: z13.string().datetime(),
939
- phase: z13.enum([
940
- "planned",
941
- "environment_written",
942
- "deploy_requested",
943
- "deployed",
944
- "verified",
945
- "failed"
946
- ]),
947
- build: z13.object({
948
- node: version,
949
- packageManager: z13.enum(["npm", "pnpm"]),
950
- packageManagerVersion: version,
951
- lockfileHash: hash
952
- }).strict().nullable()
953
- }).strict();
954
- var setupDeploymentInputSchema = z13.discriminatedUnion("action", [
955
- z13.object({ action: z13.literal("read") }).strict(),
956
- z13.object({
957
- action: z13.literal("record"),
958
- expectedOperationId: z13.string().uuid().nullable(),
959
- record: setupDeploymentRecordSchema
960
- }).strict()
961
- ]);
962
-
963
- // ../shared/dist/site-setup.js
964
- import { z as z16 } from "zod";
932
+ // ../shared/dist/missing-content.js
933
+ import { z as z14 } from "zod";
934
+ var MISSING_CONTENT_RENDERED_PATH_MAX_BYTES = 512;
935
+ var MISSING_CONTENT_VISIBLE_VALUE_MAX_BYTES = 256;
936
+ var MISSING_CONTENT_LOCATOR_HINT_MAX_BYTES = 512;
937
+ var MISSING_CONTENT_LABEL_MAX_BYTES = 120;
938
+ var forbiddenControlOrBidi = /[\u0000-\u001f\u007f-\u009f‪-‮⁦-⁩]/u;
939
+ var unsafeLocator = /<\/?[a-z][^>]*>|\b(?:javascript|data:text\/html)\s*:|\bon[a-z]+\s*=/iu;
940
+ var renderedPathSchema = z14.string().trim().transform((value) => value !== "/" ? value.replace(/\/+$/u, "") : value).superRefine((value, context) => {
941
+ if (!value.startsWith("/") || value === "$global" || value.includes("?") || value.includes("#")) {
942
+ context.addIssue({
943
+ code: "custom",
944
+ message: "renderedPath must be a canonical real path."
945
+ });
946
+ }
947
+ addSafeByteIssues(value, MISSING_CONTENT_RENDERED_PATH_MAX_BYTES, "renderedPath", context);
948
+ });
949
+ function normalizedSafeTextSchema(maxBytes, label) {
950
+ return z14.string().transform((value) => value.trim().replace(new RegExp("\\p{White_Space}+", "gu"), " ")).pipe(z14.string().min(1)).superRefine((value, context) => {
951
+ addSafeByteIssues(value, maxBytes, label, context);
952
+ if (label === "locatorHint" && unsafeLocator.test(value)) {
953
+ context.addIssue({
954
+ code: "custom",
955
+ message: "locatorHint contains unsafe markup or executable content."
956
+ });
957
+ }
958
+ });
959
+ }
960
+ var missingContentItemBase = {
961
+ renderedPath: renderedPathSchema,
962
+ visibleValue: normalizedSafeTextSchema(MISSING_CONTENT_VISIBLE_VALUE_MAX_BYTES, "visibleValue"),
963
+ locatorHint: normalizedSafeTextSchema(MISSING_CONTENT_LOCATOR_HINT_MAX_BYTES, "locatorHint"),
964
+ requestedLabel: normalizedSafeTextSchema(MISSING_CONTENT_LABEL_MAX_BYTES, "requestedLabel").optional(),
965
+ requestedSection: normalizedSafeTextSchema(MISSING_CONTENT_LABEL_MAX_BYTES, "requestedSection").optional(),
966
+ requestedSubsection: normalizedSafeTextSchema(MISSING_CONTENT_LABEL_MAX_BYTES, "requestedSubsection").optional(),
967
+ requestedSortOrder: z14.number().int().nonnegative().optional()
968
+ };
969
+ var missingContentItemSchema = z14.discriminatedUnion("kind", [
970
+ z14.object({ kind: z14.literal("text"), ...missingContentItemBase }).strict(),
971
+ z14.object({ kind: z14.literal("link"), ...missingContentItemBase }).strict(),
972
+ z14.object({ kind: z14.literal("image"), ...missingContentItemBase }).strict()
973
+ ]).superRefine((item, context) => {
974
+ if (item.requestedSubsection && !item.requestedSection) {
975
+ context.addIssue({
976
+ code: "custom",
977
+ message: "requestedSubsection requires requestedSection.",
978
+ path: ["requestedSubsection"]
979
+ });
980
+ }
981
+ });
982
+ function addSafeByteIssues(value, maxBytes, label, context) {
983
+ if (new TextEncoder().encode(value).byteLength > maxBytes) {
984
+ context.addIssue({
985
+ code: "custom",
986
+ message: `${label} exceeds ${maxBytes} UTF-8 bytes.`
987
+ });
988
+ }
989
+ if (forbiddenControlOrBidi.test(value)) {
990
+ context.addIssue({
991
+ code: "custom",
992
+ message: `${label} contains a forbidden control or bidi character.`
993
+ });
994
+ }
995
+ }
965
996
 
966
997
  // ../shared/dist/site-field-contract.js
967
- import { z as z15 } from "zod";
998
+ import { z as z16 } from "zod";
968
999
 
969
1000
  // ../shared/dist/fallback-hash.js
970
- import { z as z14 } from "zod";
1001
+ import { z as z15 } from "zod";
971
1002
  var SAFE_REPRESENTATION_REASONS = [
972
1003
  "asset_import_rewritten",
973
1004
  "relative_url_normalized",
974
1005
  "line_endings_normalized",
975
1006
  "image_value_serialized"
976
1007
  ];
977
- var safeRepresentationReasonSchema = z14.enum(SAFE_REPRESENTATION_REASONS);
978
- var linkFallbackSchema = z14.object({
979
- href: z14.string().trim().min(1),
980
- label: z14.string().trim().min(1).optional(),
981
- target: z14.enum(["_self", "_blank"]).optional()
1008
+ var safeRepresentationReasonSchema = z15.enum(SAFE_REPRESENTATION_REASONS);
1009
+ var linkFallbackSchema = z15.object({
1010
+ href: z15.string().trim().min(1),
1011
+ label: z15.string().trim().min(1).optional(),
1012
+ target: z15.enum(["_self", "_blank"]).optional()
982
1013
  }).passthrough();
983
- function stableJsonStringify(value) {
984
- return JSON.stringify(sortObjectKeys(value));
985
- }
986
- function sortObjectKeys(value) {
987
- if (Array.isArray(value)) {
988
- return value.map(sortObjectKeys);
989
- }
990
- if (!value || typeof value !== "object") {
991
- return value;
992
- }
993
- return Object.fromEntries(Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key, entryValue]) => [key, sortObjectKeys(entryValue)]));
994
- }
995
1014
 
996
1015
  // ../shared/dist/site-field-contract.js
997
- var siteFieldStatusSchema = z15.enum(["hidden", "active"]);
998
- var semanticVersionSchema = z15.string().regex(/^\d+\.\d+\.\d+$/u);
999
- var siteFieldRouteKeySchema = z15.string().trim().refine((value) => value === "$global" || value.startsWith("/") && !value.includes("?") && !value.includes("#") && (value === "/" || !value.endsWith("/")), "Route keys must be canonical paths or $global.");
1000
- var repositoryRelativePosixPathSchema = z15.string().trim().min(1).refine((value) => !value.startsWith("/") && !value.includes("\\") && !/^[a-z]:/iu.test(value) && !value.split("/").includes(".."), "Source paths must be repository-relative POSIX paths.");
1001
- var sourceMappingSchema = z15.object({
1002
- kind: z15.literal("function"),
1016
+ var siteFieldStatusSchema = z16.enum(["hidden", "active"]);
1017
+ var semanticVersionSchema = z16.string().regex(/^\d+\.\d+\.\d+$/u);
1018
+ var siteFieldRouteKeySchema = z16.string().trim().refine((value) => value === "$global" || value.startsWith("/") && !value.includes("?") && !value.includes("#") && (value === "/" || !value.endsWith("/")), "Route keys must be canonical paths or $global.");
1019
+ var repositoryRelativePosixPathSchema = z16.string().trim().min(1).refine((value) => !value.startsWith("/") && !value.includes("\\") && !/^[a-z]:/iu.test(value) && !value.split("/").includes(".."), "Source paths must be repository-relative POSIX paths.");
1020
+ var sourceMappingSchema = z16.object({
1021
+ kind: z16.literal("function"),
1003
1022
  filePath: repositoryRelativePosixPathSchema,
1004
- exportName: z15.string().trim().min(1).optional(),
1005
- sourcePath: z15.string().trim().min(1).optional(),
1023
+ exportName: z16.string().trim().min(1).optional(),
1024
+ sourcePath: z16.string().trim().min(1).optional(),
1006
1025
  editTarget: fieldIdSchema.optional()
1007
1026
  }).strict();
1008
- var domMappingSchema = z15.object({
1009
- attribute: z15.literal("data-siteplane-field-id"),
1010
- previewStrategy: z15.enum(["dom", "event"])
1027
+ var domMappingSchema = z16.object({
1028
+ attribute: z16.literal("data-siteplane-field-id"),
1029
+ previewStrategy: z16.enum(["dom", "event"])
1011
1030
  }).strict();
1012
- var fieldBaseSchema = z15.object({
1031
+ var fieldBaseSchema = z16.object({
1013
1032
  fieldId: fieldIdSchema,
1014
1033
  routeKey: siteFieldRouteKeySchema,
1015
1034
  source: sourceMappingSchema,
1016
1035
  dom: domMappingSchema.optional()
1017
1036
  }).strict();
1018
- var linkFallbackSchema2 = z15.object({
1019
- href: z15.string().trim().min(1),
1020
- label: z15.string().trim().min(1).optional(),
1021
- target: z15.enum(["_self", "_blank"]).optional()
1037
+ var linkFallbackSchema2 = z16.object({
1038
+ href: z16.string().trim().min(1),
1039
+ label: z16.string().trim().min(1).optional(),
1040
+ target: z16.enum(["_self", "_blank"]).optional()
1022
1041
  }).strict();
1023
- var imageFallbackSchema = z15.object({
1024
- src: z15.string().trim().min(1),
1025
- alt: z15.string().trim().max(300),
1026
- width: z15.number().int().positive().optional(),
1027
- height: z15.number().int().positive().optional(),
1028
- crop: z15.object({
1029
- x: z15.number().min(0).max(100),
1030
- y: z15.number().min(0).max(100),
1031
- zoom: z15.number().min(1).max(4),
1032
- aspectRatio: z15.number().positive().max(10)
1042
+ var imageFallbackSchema = z16.object({
1043
+ src: z16.string().trim().min(1),
1044
+ alt: z16.string().trim().max(300),
1045
+ width: z16.number().int().positive().optional(),
1046
+ height: z16.number().int().positive().optional(),
1047
+ crop: z16.object({
1048
+ x: z16.number().min(0).max(100),
1049
+ y: z16.number().min(0).max(100),
1050
+ zoom: z16.number().min(1).max(4),
1051
+ aspectRatio: z16.number().positive().max(10)
1033
1052
  }).strict().optional()
1034
1053
  }).strict();
1035
- var siteFieldContractFieldSchema = z15.discriminatedUnion("fieldType", [
1054
+ var siteFieldContractFieldSchema = z16.discriminatedUnion("fieldType", [
1036
1055
  fieldBaseSchema.extend({
1037
- fieldType: z15.literal("text"),
1038
- fallback: z15.string()
1056
+ fieldType: z16.literal("text"),
1057
+ fallback: z16.string()
1039
1058
  }),
1040
1059
  fieldBaseSchema.extend({
1041
- fieldType: z15.literal("longText"),
1042
- fallback: z15.string()
1060
+ fieldType: z16.literal("longText"),
1061
+ fallback: z16.string()
1043
1062
  }),
1044
1063
  fieldBaseSchema.extend({
1045
- fieldType: z15.literal("link"),
1064
+ fieldType: z16.literal("link"),
1046
1065
  fallback: linkFallbackSchema2
1047
1066
  }),
1048
1067
  fieldBaseSchema.extend({
1049
- fieldType: z15.literal("image"),
1068
+ fieldType: z16.literal("image"),
1050
1069
  fallback: imageFallbackSchema
1051
1070
  })
1052
1071
  ]);
1053
- var siteFieldContractV1Schema = z15.object({
1054
- version: z15.literal(1),
1072
+ var siteFieldContractV1Schema = z16.object({
1073
+ version: z16.literal(1),
1055
1074
  fieldContractVersion: semanticVersionSchema,
1056
1075
  scannerContractVersion: semanticVersionSchema,
1057
- fields: z15.array(siteFieldContractFieldSchema)
1076
+ fields: z16.array(siteFieldContractFieldSchema)
1058
1077
  }).strict().superRefine((contract, context) => {
1059
1078
  const seen = /* @__PURE__ */ new Set();
1060
1079
  for (const [index, field] of contract.fields.entries()) {
@@ -1069,550 +1088,6 @@ var siteFieldContractV1Schema = z15.object({
1069
1088
  }
1070
1089
  });
1071
1090
 
1072
- // ../shared/dist/site-setup.js
1073
- var SITE_SETUP_RUN_STATUSES = [
1074
- "waiting_for_agent",
1075
- "working",
1076
- "action_required",
1077
- "ready_for_review",
1078
- "completed"
1079
- ];
1080
- var SITE_SETUP_RUN_MODES = ["initial", "update"];
1081
- var SITE_SETUP_ERROR_CODES = [
1082
- "action_required",
1083
- "deployment_evidence_required",
1084
- "field_contract_scan_failed",
1085
- "invalid_editor_definition",
1086
- "invalid_field_contract",
1087
- "missing_build_revision",
1088
- "missing_field_contract",
1089
- "review_locked",
1090
- "stale_deployment_contract",
1091
- "stale_field_contract",
1092
- "stale_setup_review",
1093
- "update_required"
1094
- ];
1095
- var CONTINUE_SITE_SETUP_MAX_ITEMS = 50;
1096
- var CONTINUE_SITE_SETUP_RENDERED_PATH_MAX_BYTES = 512;
1097
- var CONTINUE_SITE_SETUP_VISIBLE_VALUE_MAX_BYTES = 256;
1098
- var CONTINUE_SITE_SETUP_LOCATOR_HINT_MAX_BYTES = 512;
1099
- var CONTINUE_SITE_SETUP_REQUESTED_LABEL_MAX_BYTES = 120;
1100
- var CONTINUE_SITE_SETUP_REQUESTED_SECTION_MAX_BYTES = 120;
1101
- var CONTINUE_SITE_SETUP_REQUESTED_SUBSECTION_MAX_BYTES = 120;
1102
- var SITE_SETUP_OWNER_EDITABILITY_NOTE_MAX_LENGTH = 2e3;
1103
- var SITE_SETUP_OWNER_EDITABILITY_NOTE_MAX_BYTES = 8e3;
1104
- var CONTINUE_SITE_SETUP_ITEMS_MAX_BYTES = 32 * 1024;
1105
- var CONTINUE_SITE_SETUP_HTTP_BODY_MAX_BYTES = 64 * 1024;
1106
- var siteSetupRunStatusSchema = z16.enum(SITE_SETUP_RUN_STATUSES);
1107
- var siteSetupRunModeSchema = z16.enum(SITE_SETUP_RUN_MODES);
1108
- var siteSetupErrorCodeSchema = z16.enum(SITE_SETUP_ERROR_CODES);
1109
- var editorFieldSchema = z16.object({
1110
- fieldId: fieldIdSchema,
1111
- label: z16.string().trim().min(1),
1112
- subsection: z16.string().trim().min(1).optional(),
1113
- description: z16.string().trim().min(1).optional(),
1114
- required: z16.boolean().optional(),
1115
- maxLength: z16.number().int().positive().optional()
1116
- }).strict();
1117
- var editorSectionSchema = z16.object({
1118
- label: z16.string().trim().min(1),
1119
- fields: z16.array(editorFieldSchema).min(1)
1120
- }).strict().superRefine((section, context) => {
1121
- const closedSubsections = /* @__PURE__ */ new Set();
1122
- let currentSubsection;
1123
- for (const [index, field] of section.fields.entries()) {
1124
- if (field.subsection === currentSubsection)
1125
- continue;
1126
- if (currentSubsection)
1127
- closedSubsections.add(currentSubsection);
1128
- currentSubsection = field.subsection;
1129
- if (currentSubsection && closedSubsections.has(currentSubsection)) {
1130
- context.addIssue({
1131
- code: "custom",
1132
- message: `Subgroup fields must stay contiguous: ${currentSubsection}`,
1133
- path: ["fields", index, "subsection"]
1134
- });
1135
- }
1136
- }
1137
- });
1138
- var editorRouteSchema = z16.object({
1139
- routeKey: siteFieldRouteKeySchema,
1140
- previewPath: z16.string().trim().refine((path) => path.startsWith("/") && !path.startsWith("//") && !/[\\\[\]?#\s]/u.test(path) && (path === "/" || !path.endsWith("/")), "previewPath must be a concrete same-site path, for example /services/consultation.").optional(),
1141
- label: z16.string().trim().min(1),
1142
- sections: z16.array(editorSectionSchema).min(1)
1143
- }).strict().superRefine((route, context) => {
1144
- if (route.routeKey.includes("[") && !route.previewPath) {
1145
- context.addIssue({
1146
- code: "custom",
1147
- path: ["previewPath"],
1148
- message: "Dynamic editor routes need a previewPath for an existing page; keep the canonical routeKey unchanged."
1149
- });
1150
- }
1151
- const sections = /* @__PURE__ */ new Set();
1152
- for (const [index, section] of route.sections.entries()) {
1153
- if (sections.has(section.label)) {
1154
- context.addIssue({
1155
- code: "custom",
1156
- message: `Duplicate section label: ${section.label}`,
1157
- path: ["sections", index, "label"]
1158
- });
1159
- }
1160
- sections.add(section.label);
1161
- }
1162
- });
1163
- var editorDefinitionV1Schema = z16.object({
1164
- version: z16.literal(1),
1165
- routes: z16.array(editorRouteSchema).min(1)
1166
- }).strict().superRefine((definition, context) => {
1167
- const routes = /* @__PURE__ */ new Set();
1168
- const fields = /* @__PURE__ */ new Set();
1169
- for (const [routeIndex, route] of definition.routes.entries()) {
1170
- if (routes.has(route.routeKey)) {
1171
- context.addIssue({
1172
- code: "custom",
1173
- message: `Duplicate route key: ${route.routeKey}`,
1174
- path: ["routes", routeIndex, "routeKey"]
1175
- });
1176
- }
1177
- routes.add(route.routeKey);
1178
- for (const [sectionIndex, section] of route.sections.entries()) {
1179
- for (const [fieldIndex, field] of section.fields.entries()) {
1180
- if (fields.has(field.fieldId)) {
1181
- context.addIssue({
1182
- code: "custom",
1183
- message: `Duplicate editor field id: ${field.fieldId}`,
1184
- path: [
1185
- "routes",
1186
- routeIndex,
1187
- "sections",
1188
- sectionIndex,
1189
- "fields",
1190
- fieldIndex,
1191
- "fieldId"
1192
- ]
1193
- });
1194
- }
1195
- fields.add(field.fieldId);
1196
- }
1197
- }
1198
- }
1199
- });
1200
- var forbiddenControlOrBidi = /[\u0000-\u001f\u007f-\u009f\u202a-\u202e\u2066-\u2069]/u;
1201
- var forbiddenOwnerNoteControlOrBidi = /[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f-\u009f\u202a-\u202e\u2066-\u2069]/u;
1202
- var unsafeLocator = /<\/?[a-z][^>]*>|\b(?:javascript|data:text\/html)\s*:|\bon[a-z]+\s*=/iu;
1203
- var renderedPathSchema = z16.string().trim().transform((value) => value !== "/" ? value.replace(/\/+$/u, "") : value).superRefine((value, context) => {
1204
- if (!value.startsWith("/") || value === "$global" || value.includes("?") || value.includes("#")) {
1205
- context.addIssue({
1206
- code: "custom",
1207
- message: "renderedPath must be a canonical real path."
1208
- });
1209
- }
1210
- addSafeByteIssues(value, CONTINUE_SITE_SETUP_RENDERED_PATH_MAX_BYTES, "renderedPath", context);
1211
- });
1212
- function normalizedSafeTextSchema(maxBytes, label) {
1213
- return z16.string().transform((value) => value.trim().replace(new RegExp("\\p{White_Space}+", "gu"), " ")).pipe(z16.string().min(1)).superRefine((value, context) => {
1214
- addSafeByteIssues(value, maxBytes, label, context);
1215
- if (label === "locatorHint" && unsafeLocator.test(value)) {
1216
- context.addIssue({
1217
- code: "custom",
1218
- message: "locatorHint contains unsafe markup or executable content."
1219
- });
1220
- }
1221
- });
1222
- }
1223
- var correctionItemBase = {
1224
- renderedPath: renderedPathSchema,
1225
- visibleValue: normalizedSafeTextSchema(CONTINUE_SITE_SETUP_VISIBLE_VALUE_MAX_BYTES, "visibleValue"),
1226
- locatorHint: normalizedSafeTextSchema(CONTINUE_SITE_SETUP_LOCATOR_HINT_MAX_BYTES, "locatorHint"),
1227
- requestedLabel: normalizedSafeTextSchema(CONTINUE_SITE_SETUP_REQUESTED_LABEL_MAX_BYTES, "requestedLabel").optional(),
1228
- requestedSection: normalizedSafeTextSchema(CONTINUE_SITE_SETUP_REQUESTED_SECTION_MAX_BYTES, "requestedSection").optional(),
1229
- requestedSubsection: normalizedSafeTextSchema(CONTINUE_SITE_SETUP_REQUESTED_SUBSECTION_MAX_BYTES, "requestedSubsection").optional(),
1230
- requestedSortOrder: z16.number().int().nonnegative().optional()
1231
- };
1232
- var setupCorrectionItemSchema = z16.discriminatedUnion("kind", [
1233
- z16.object({ kind: z16.literal("text"), ...correctionItemBase }).strict(),
1234
- z16.object({ kind: z16.literal("link"), ...correctionItemBase }).strict(),
1235
- z16.object({ kind: z16.literal("image"), ...correctionItemBase }).strict()
1236
- ]).superRefine((item, context) => {
1237
- if (item.requestedSubsection && !item.requestedSection) {
1238
- context.addIssue({
1239
- code: "custom",
1240
- message: "requestedSubsection requires requestedSection.",
1241
- path: ["requestedSubsection"]
1242
- });
1243
- }
1244
- });
1245
- var setupCorrectionItemsSchema = z16.array(setupCorrectionItemSchema).max(CONTINUE_SITE_SETUP_MAX_ITEMS).superRefine((items, context) => {
1246
- const bytes = utf8Bytes(stableJsonStringify(items));
1247
- if (bytes > CONTINUE_SITE_SETUP_ITEMS_MAX_BYTES) {
1248
- context.addIssue({
1249
- code: "custom",
1250
- message: "Correction items exceed the 32 KiB canonical payload limit."
1251
- });
1252
- }
1253
- });
1254
- var siteSetupOwnerEditabilityNoteSchema = z16.string().max(SITE_SETUP_OWNER_EDITABILITY_NOTE_MAX_LENGTH).superRefine((value, context) => {
1255
- if (utf8Bytes(value) > SITE_SETUP_OWNER_EDITABILITY_NOTE_MAX_BYTES) {
1256
- context.addIssue({
1257
- code: "custom",
1258
- message: `ownerEditabilityNote exceeds ${SITE_SETUP_OWNER_EDITABILITY_NOTE_MAX_BYTES} UTF-8 bytes.`
1259
- });
1260
- }
1261
- if (forbiddenOwnerNoteControlOrBidi.test(value)) {
1262
- context.addIssue({
1263
- code: "custom",
1264
- message: "ownerEditabilityNote contains a forbidden control or bidi character."
1265
- });
1266
- }
1267
- });
1268
- var SITE_SETUP_MODULE_SCOPES = {
1269
- editing: ["setup:read", "setup:write"],
1270
- analytics: [
1271
- "analytics:setup",
1272
- "analytics:sync",
1273
- "analytics:test",
1274
- "analytics:readiness",
1275
- "analytics:agent_instructions",
1276
- "analytics:public_key_read"
1277
- ]
1278
- };
1279
- var siteSetupModulesSchema = z16.array(z16.enum(["editing", "analytics"])).min(1).max(2).refine((modules) => modules[0] === "editing" && (modules.length === 1 || modules[1] === "analytics"), "Choose Editing with optional Analytics.");
1280
- function siteSetupScopes(modules) {
1281
- return modules.flatMap((module) => [...SITE_SETUP_MODULE_SCOPES[module]]);
1282
- }
1283
- function hasExactSiteSetupScopes(scopes, modules) {
1284
- const matches = (expected) => scopes.length === expected.length && expected.every((scope) => scopes.includes(scope));
1285
- return modules ? matches(siteSetupScopes(modules)) : matches(siteSetupScopes(["editing"])) || matches(siteSetupScopes(["editing", "analytics"]));
1286
- }
1287
- var siteSetupActivityInputSchema = z16.object({
1288
- phase: z16.enum([
1289
- "inspecting",
1290
- "integrating",
1291
- "deploying",
1292
- "verifying",
1293
- "repairing"
1294
- ]),
1295
- textId: z16.enum([
1296
- "inspecting",
1297
- "integrating",
1298
- "deploying",
1299
- "verifying",
1300
- "repairing"
1301
- ])
1302
- }).strict().refine((value) => value.phase === value.textId, "Activity text must describe its phase.");
1303
- var nextActionFields = {
1304
- actor: z16.enum(["agent", "user", "siteplane"]),
1305
- boundary: z16.enum([
1306
- "source",
1307
- "environment",
1308
- "deployment",
1309
- "verification",
1310
- "authorization",
1311
- "review"
1312
- ]),
1313
- precondition: z16.string().min(1).max(1e3),
1314
- instruction: z16.string().min(1).max(2e3),
1315
- expectedEvidence: z16.string().min(1).max(1e3)
1316
- };
1317
- var siteSetupNextActionSchema = z16.discriminatedUnion("kind", [
1318
- z16.object({
1319
- ...nextActionFields,
1320
- kind: z16.literal("run_command"),
1321
- command: z16.string().min(1).max(500)
1322
- }).strict(),
1323
- z16.object({ ...nextActionFields, kind: z16.literal("agent_edit") }).strict(),
1324
- z16.object({ ...nextActionFields, kind: z16.literal("needs_user_action") }).strict(),
1325
- z16.object({ ...nextActionFields, kind: z16.literal("wait") }).strict(),
1326
- z16.object({ ...nextActionFields, kind: z16.literal("done") }).strict()
1327
- ]);
1328
- var siteSetupTaskRunSchema = z16.object({
1329
- runId: z16.string().uuid(),
1330
- mode: siteSetupRunModeSchema,
1331
- status: siteSetupRunStatusSchema,
1332
- fieldContractHash: z16.string().nullable(),
1333
- deploymentOrigin: z16.string().url().nullable(),
1334
- deploymentRevision: z16.string().nullable(),
1335
- publicRuntimeKeyId: z16.string().uuid().nullable(),
1336
- reviewVersion: z16.number().int().positive()
1337
- }).strict();
1338
- var siteSetupTaskProgressSchema = z16.object({
1339
- progressStage: z16.enum([
1340
- "waiting_for_connection",
1341
- "agent_connected",
1342
- "project_context_loaded",
1343
- "fields_prepared",
1344
- "deployment_verification",
1345
- "ready_for_review",
1346
- "action_required",
1347
- "completed"
1348
- ]),
1349
- lastVerifiedAt: z16.string().datetime().nullable(),
1350
- lastActivityAt: z16.string().datetime(),
1351
- activitySource: z16.enum(["user", "server", "agent"]),
1352
- activityPhase: siteSetupActivityInputSchema.shape.phase.nullable(),
1353
- activityTextId: siteSetupActivityInputSchema.shape.textId.nullable()
1354
- }).strict();
1355
- var siteSetupTaskSchema = z16.object({
1356
- contractVersion: z16.literal("siteplane.setup-task.v2"),
1357
- workflow: z16.enum(["initial_setup", "structure_update"]),
1358
- goal: z16.string().min(1),
1359
- modules: siteSetupModulesSchema,
1360
- authorizationVersion: z16.number().int().positive(),
1361
- authorizedScopes: z16.array(z16.string()).min(2),
1362
- site: z16.object({
1363
- siteId: z16.string().uuid(),
1364
- portalPath: z16.string(),
1365
- adminOrigin: z16.string().url()
1366
- }).strict().nullable(),
1367
- run: siteSetupTaskRunSchema.nullable(),
1368
- progress: siteSetupTaskProgressSchema.nullable(),
1369
- deployment: setupDeploymentRecordSchema.nullable(),
1370
- revalidationGeneration: z16.number().int().positive(),
1371
- assignment: z16.enum(["owned", "provisional", "claimed"]),
1372
- deadline: z16.string().datetime().nullable(),
1373
- userInstructions: z16.object({
1374
- text: siteSetupOwnerEditabilityNoteSchema,
1375
- source: z16.literal("user"),
1376
- trust: z16.literal("untrusted")
1377
- }).strict(),
1378
- corrections: setupCorrectionItemsSchema,
1379
- contentSelectionSummary: z16.object({
1380
- text: siteSetupOwnerEditabilityNoteSchema,
1381
- source: z16.literal("agent"),
1382
- trust: z16.literal("untrusted")
1383
- }).strict().nullable(),
1384
- environmentBindings: z16.array(z16.object({
1385
- name: z16.string().regex(/^[A-Z][A-Z0-9_]+$/u),
1386
- source: z16.string().min(1),
1387
- sensitivity: z16.enum(["public", "secret"]),
1388
- usage: z16.enum(["build", "server", "build_and_server"]),
1389
- evidence: z16.string().min(1)
1390
- }).strict()),
1391
- nextAction: siteSetupNextActionSchema,
1392
- error: z16.object({
1393
- code: z16.string().regex(/^[a-z0-9_.]+$/u).max(160),
1394
- boundary: nextActionFields.boundary,
1395
- responsibleActor: nextActionFields.actor,
1396
- retryable: z16.boolean(),
1397
- retryAfter: z16.number().int().nonnegative().nullable(),
1398
- requestId: z16.string().regex(/^[A-Za-z0-9_-]+$/u).max(128)
1399
- }).strict().nullable(),
1400
- packages: siteSetupPackagesSchema,
1401
- communication: z16.object({
1402
- beforeSourceChanges: z16.string().min(1),
1403
- updates: z16.array(z16.string().min(1)).min(1),
1404
- blocker: z16.string().min(1)
1405
- }).strict(),
1406
- discovery: z16.object({
1407
- inspectPublicRoutes: z16.boolean(),
1408
- contentKinds: z16.array(z16.enum(["text", "longText", "link", "image"])).min(1),
1409
- rules: z16.array(z16.string().min(1)).min(1)
1410
- }).strict(),
1411
- steps: z16.array(z16.object({
1412
- id: z16.enum([
1413
- "inspect_repository",
1414
- "install_packages",
1415
- "instrument_fields",
1416
- "apply_contract",
1417
- "deploy_production",
1418
- "verify_deployment"
1419
- ]),
1420
- instruction: z16.string().min(1)
1421
- }).strict()).length(6),
1422
- completion: z16.object({
1423
- verifiedStatus: z16.literal("ready_for_review"),
1424
- instruction: z16.string().min(1)
1425
- }).strict()
1426
- }).strict().refine((task) => hasExactSiteSetupScopes(task.authorizedScopes, task.modules), "Task scopes must exactly match its modules.").refine((task) => task.modules.includes("analytics") === (task.packages.analytics !== void 0), "The Analytics package pin must be present exactly when Analytics is selected.");
1427
- var canonicalHashSchema = z16.string().regex(/^sha256:[0-9a-f]{64}$/iu);
1428
- var deploymentRevisionSchema = normalizedSafeTextSchema(256, "deploymentRevision");
1429
- var continueSiteSetupInputSchema = z16.object({
1430
- siteId: z16.string().uuid(),
1431
- runId: z16.string().uuid(),
1432
- expectedReviewVersion: z16.number().int().positive(),
1433
- mutationId: z16.string().uuid(),
1434
- intent: z16.enum(["continue_review", "correct_completed_review"]),
1435
- expectedFieldContractHash: canonicalHashSchema,
1436
- expectedDeploymentRevision: deploymentRevisionSchema,
1437
- correctionItems: setupCorrectionItemsSchema,
1438
- ownerEditabilityNote: siteSetupOwnerEditabilityNoteSchema.optional()
1439
- }).strict();
1440
- var saveSiteSetupOwnerNoteInputSchema = z16.object({
1441
- siteId: z16.string().uuid(),
1442
- runId: z16.string().uuid(),
1443
- expectedReviewVersion: z16.number().int().positive(),
1444
- expectedFieldContractHash: canonicalHashSchema,
1445
- expectedDeploymentRevision: deploymentRevisionSchema,
1446
- ownerEditabilityNote: siteSetupOwnerEditabilityNoteSchema
1447
- }).strict();
1448
- var setupReviewPreferenceSelectionSchema = z16.object({
1449
- analyticsMode: z16.enum(["disabled", "session_only"]).nullable(),
1450
- assetTargetType: z16.enum(["repo_static_assets", "siteplane_managed_fallback"]).nullable(),
1451
- assetTargetId: z16.string().uuid().nullable()
1452
- }).strict().refine((value) => value.assetTargetType !== null || value.assetTargetId === null, {
1453
- message: "An asset target requires its delivery type."
1454
- });
1455
- var setupReviewPreferencesSchema = setupReviewPreferenceSelectionSchema.safeExtend({
1456
- managedHostingApproved: z16.boolean()
1457
- });
1458
- var saveSetupReviewPreferencesInputSchema = z16.object({
1459
- siteId: z16.string().uuid(),
1460
- runId: z16.string().uuid(),
1461
- expectedReviewVersion: z16.number().int().positive(),
1462
- preferences: setupReviewPreferenceSelectionSchema
1463
- }).strict();
1464
- var siteSetupContextInputSchema = z16.object({}).strict();
1465
- var siteSetupApplyInputSchema = z16.object({
1466
- fieldContract: siteFieldContractV1Schema,
1467
- editorDefinition: editorDefinitionV1Schema,
1468
- contentSelectionSummary: siteSetupOwnerEditabilityNoteSchema.refine((text) => text.trim().length > 0, "Describe the selected content, important exclusions and any open gaps.")
1469
- }).strict().superRefine((input, context) => {
1470
- const contractRoutesByFieldId = new Map(input.fieldContract.fields.map((field) => [
1471
- field.fieldId,
1472
- field.routeKey
1473
- ]));
1474
- const definitionFieldIds = /* @__PURE__ */ new Set();
1475
- for (const [routeIndex, route] of input.editorDefinition.routes.entries()) {
1476
- for (const [sectionIndex, section] of route.sections.entries()) {
1477
- for (const [fieldIndex, field] of section.fields.entries()) {
1478
- const fieldPath = [
1479
- "editorDefinition",
1480
- "routes",
1481
- routeIndex,
1482
- "sections",
1483
- sectionIndex,
1484
- "fields",
1485
- fieldIndex,
1486
- "fieldId"
1487
- ];
1488
- const contractRouteKey = contractRoutesByFieldId.get(field.fieldId);
1489
- const contractField = input.fieldContract.fields.find((candidate) => candidate.fieldId === field.fieldId);
1490
- definitionFieldIds.add(field.fieldId);
1491
- if (!contractRouteKey) {
1492
- context.addIssue({
1493
- code: "custom",
1494
- message: `Unknown editor field id: ${field.fieldId}`,
1495
- path: fieldPath
1496
- });
1497
- } else if (contractRouteKey !== route.routeKey) {
1498
- context.addIssue({
1499
- code: "custom",
1500
- message: `Editor field ${field.fieldId} must use route ${contractRouteKey}.`,
1501
- path: fieldPath
1502
- });
1503
- } else if (field.maxLength !== void 0 && contractField?.fieldType !== "text" && contractField?.fieldType !== "longText") {
1504
- context.addIssue({
1505
- code: "custom",
1506
- message: `maxLength is not supported for ${contractField?.fieldType ?? "unknown"} fields.`,
1507
- path: [
1508
- "editorDefinition",
1509
- "routes",
1510
- routeIndex,
1511
- "sections",
1512
- sectionIndex,
1513
- "fields",
1514
- fieldIndex,
1515
- "maxLength"
1516
- ]
1517
- });
1518
- }
1519
- }
1520
- }
1521
- }
1522
- for (const field of input.fieldContract.fields) {
1523
- if (!definitionFieldIds.has(field.fieldId)) {
1524
- context.addIssue({
1525
- code: "custom",
1526
- message: `Missing editor field id: ${field.fieldId}`,
1527
- path: ["editorDefinition", "routes"]
1528
- });
1529
- }
1530
- }
1531
- });
1532
- var siteSetupVerifyInputSchema = z16.object({
1533
- deploymentUrl: z16.string().url().refine((value) => value.startsWith("https://")),
1534
- deploymentRevision: deploymentRevisionSchema,
1535
- wait: z16.boolean().optional()
1536
- }).strict();
1537
- var siteSetupEvidenceInputSchema = z16.object({
1538
- siteId: z16.string().uuid(),
1539
- runId: z16.string().uuid(),
1540
- expectedFieldContractHash: canonicalHashSchema,
1541
- expectedDeploymentOrigin: z16.string().url().refine((value) => value.startsWith("https://")),
1542
- expectedDeploymentRevision: deploymentRevisionSchema,
1543
- publicRuntimeKeyId: z16.string().uuid(),
1544
- bridgeSessionId: normalizedSafeTextSchema(256, "bridgeSessionId"),
1545
- observations: z16.array(z16.object({
1546
- fieldId: fieldIdSchema,
1547
- fieldType: fieldTypeSchema,
1548
- routeKey: siteFieldRouteKeySchema,
1549
- renderedPath: renderedPathSchema,
1550
- targetResolved: z16.boolean(),
1551
- previewAck: z16.boolean()
1552
- }).strict().refine((value) => !value.previewAck || value.targetResolved, "Preview ACK requires a resolved target.")).min(1).max(200)
1553
- }).strict();
1554
- var completeSetupReviewInputSchema = z16.object({
1555
- siteId: z16.string().uuid(),
1556
- runId: z16.string().uuid(),
1557
- expectedReviewVersion: z16.number().int().positive(),
1558
- expectedFieldContractHash: canonicalHashSchema,
1559
- expectedDeploymentRevision: deploymentRevisionSchema,
1560
- expectedReadyFingerprint: canonicalHashSchema
1561
- }).strict();
1562
- var activateSiteSetupInputSchema = z16.object({
1563
- siteId: z16.string().uuid(),
1564
- runId: z16.string().uuid(),
1565
- expectedReviewVersion: z16.number().int().positive(),
1566
- expectedSnapshotHash: canonicalHashSchema
1567
- }).strict();
1568
- var refreshSiteSetupDeploymentInputSchema = z16.object({
1569
- siteId: z16.string().uuid(),
1570
- deploymentUrl: z16.string().url().refine((value) => value.startsWith("https://")),
1571
- deploymentRevision: deploymentRevisionSchema
1572
- }).strict();
1573
- function addSafeByteIssues(value, maxBytes, label, context) {
1574
- if (utf8Bytes(value) > maxBytes) {
1575
- context.addIssue({
1576
- code: "custom",
1577
- message: `${label} exceeds ${maxBytes} UTF-8 bytes.`
1578
- });
1579
- }
1580
- if (forbiddenControlOrBidi.test(value)) {
1581
- context.addIssue({
1582
- code: "custom",
1583
- message: `${label} contains a forbidden control or bidi character.`
1584
- });
1585
- }
1586
- }
1587
- function utf8Bytes(value) {
1588
- return new TextEncoder().encode(value).byteLength;
1589
- }
1590
- var setupActivationApprovalSchema = z16.object({
1591
- reviewVersion: z16.number().int().positive(),
1592
- snapshotHash: canonicalHashSchema,
1593
- analytics: z16.object({
1594
- status: z16.enum(["active", "skipped"]),
1595
- reviewVersion: z16.number().int().positive(),
1596
- generation: z16.number().int().nonnegative()
1597
- }).optional()
1598
- });
1599
- var activateSetupModulesInputSchema = activateSiteSetupInputSchema.extend({
1600
- analytics: z16.discriminatedUnion("decision", [
1601
- z16.object({ decision: z16.literal("pending") }).strict(),
1602
- z16.object({
1603
- decision: z16.literal("enable"),
1604
- readinessTestRunId: z16.string().regex(/^analytics_owner_[0-9a-f-]{36}$/u),
1605
- expectedInstallationGeneration: z16.number().int().positive(),
1606
- measurementApproved: z16.literal(true)
1607
- }).strict(),
1608
- z16.object({
1609
- decision: z16.literal("skip"),
1610
- expectedInstallationGeneration: z16.number().int().nonnegative(),
1611
- continueWithoutAnalytics: z16.literal(true)
1612
- }).strict()
1613
- ])
1614
- }).strict();
1615
-
1616
1091
  // ../shared/dist/bridge-protocol.js
1617
1092
  var BRIDGE_PROTOCOL_VERSION = 2;
1618
1093
  var bridgeRectSchema = z17.object({
@@ -1671,18 +1146,6 @@ var fieldBridgeIdentitySchema = z17.object({
1671
1146
  fieldContractHash: canonicalFieldContractHashSchema,
1672
1147
  deploymentRevision: z17.string().trim().min(1).max(256)
1673
1148
  }).strict();
1674
- var setupPreviewAccessSchema = z17.object({
1675
- capability: z17.string().regex(/^v1\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]{43}$/u).max(4096),
1676
- expiresAt: z17.string().datetime()
1677
- }).strict();
1678
- var setupPreviewReadSchema = fieldBridgeIdentitySchema.extend({
1679
- scope: z17.literal("setup_preview"),
1680
- siteId: z17.string().uuid(),
1681
- runId: z17.string().uuid(),
1682
- bridgeSessionId: z17.string().min(1),
1683
- expiresAt: z17.string().datetime(),
1684
- contract: siteFieldContractV1Schema
1685
- }).strict();
1686
1149
  var fieldBridgeBaseSchema = z17.object({
1687
1150
  version: z17.literal(BRIDGE_PROTOCOL_VERSION),
1688
1151
  type: z17.enum(FIELD_BRIDGE_MESSAGE_TYPES),
@@ -1710,8 +1173,7 @@ var fieldBridgeInitMessageSchema = fieldBridgeBaseSchema.extend({
1710
1173
  payload: z17.object({
1711
1174
  adminOrigin: z17.string().url(),
1712
1175
  customerOrigin: z17.string().url(),
1713
- renderedPath: realRenderedPathSchema,
1714
- setupPreview: setupPreviewAccessSchema.optional()
1176
+ renderedPath: realRenderedPathSchema
1715
1177
  }).strict()
1716
1178
  });
1717
1179
  var fieldBridgeReadyMessageSchema = fieldBridgeBaseSchema.extend({
@@ -1724,7 +1186,7 @@ var fieldBridgeReadyMessageSchema = fieldBridgeBaseSchema.extend({
1724
1186
  z17.literal("preview_values"),
1725
1187
  z17.literal("field_evidence"),
1726
1188
  z17.literal("visual_field_control")
1727
- ]).rest(z17.enum(["analytics_preview_readiness", "setup_preview"])).refine((capabilities) => capabilities.length <= 6)
1189
+ ]).rest(z17.enum(["analytics_preview_readiness"])).refine((capabilities) => capabilities.length <= 5)
1728
1190
  }).strict()
1729
1191
  });
1730
1192
  var fieldBridgeFieldsMessageSchema = fieldBridgeBaseSchema.extend({
@@ -1800,7 +1262,7 @@ var fieldBridgeMissingContentMessageSchema = fieldBridgeBaseSchema.extend({
1800
1262
  type: z17.literal("siteplane:field-bridge:missing-content"),
1801
1263
  payload: z17.object({
1802
1264
  action: fieldBridgeMissingContentActionSchema,
1803
- item: setupCorrectionItemSchema,
1265
+ item: missingContentItemSchema,
1804
1266
  suggestedSection: bridgeSectionSchema.optional()
1805
1267
  }).strict()
1806
1268
  });
@@ -1961,12 +1423,7 @@ var updateEditorOrganizationInputSchema = z21.discriminatedUnion("operation", [
1961
1423
  routeKey: siteFieldRouteKeySchema.refine((value) => value !== "$global", "Global content has no page label."),
1962
1424
  label: labelSchema
1963
1425
  })
1964
- ]).and(z21.object({
1965
- review: z21.object({
1966
- runId: z21.string().uuid(),
1967
- expectedReviewVersion: z21.number().int().positive()
1968
- }).strict().optional()
1969
- })).superRefine((input, context) => {
1426
+ ]).superRefine((input, context) => {
1970
1427
  if (input.operation === "update_field" && input.label === void 0 && input.description === void 0 && input.section === void 0 && input.subsection === void 0 && input.sortOrder === void 0 && input.status === void 0) {
1971
1428
  context.addIssue({
1972
1429
  code: "custom",
@@ -2049,9 +1506,6 @@ var EARLY_ACCESS_PLAN = {
2049
1506
  bookingRemindersEnabled: true
2050
1507
  };
2051
1508
 
2052
- // ../shared/dist/first-party-image-upload.js
2053
- var maxFirstPartyImageUploadBytes = 4 * 1024 * 1024;
2054
-
2055
1509
  // ../shared/dist/readiness.js
2056
1510
  import { z as z24 } from "zod";
2057
1511
  var READINESS_CHECK_KEYS = [
@@ -2073,142 +1527,81 @@ var readinessStatusSchema = z24.enum(READINESS_STATUSES);
2073
1527
 
2074
1528
  // ../shared/dist/site.js
2075
1529
  import { z as z25 } from "zod";
2076
- var SITE_STATUSES = [
2077
- "setup",
2078
- "active",
2079
- "disabled",
2080
- "archived"
2081
- ];
1530
+ var SITE_STATUSES = ["active", "disabled", "archived"];
2082
1531
  var siteStatusSchema = z25.enum(SITE_STATUSES);
2083
1532
  var websiteUrlSchema = z25.string().trim().url().refine((value) => value.startsWith("https://") || value.startsWith("http://"), "Website URL must use http or https");
2084
1533
 
2085
- // ../shared/dist/setup-assets.js
1534
+ // ../shared/dist/field-sync.js
2086
1535
  import { z as z26 } from "zod";
2087
- var configureSetupAssetTargetInputSchema = z26.object({
2088
- siteId: z26.string().uuid(),
2089
- runId: z26.string().uuid(),
2090
- expectedReviewVersion: z26.number().int().positive(),
2091
- expectedSnapshotHash: z26.string().regex(/^sha256:[0-9a-f]{64}$/u),
2092
- mutationId: z26.string().uuid(),
2093
- expectedApprovalId: z26.string().uuid().nullable(),
2094
- targetId: z26.string().uuid().nullable(),
2095
- targetType: z26.enum(["repo_static_assets", "siteplane_managed_fallback"]),
2096
- approveManagedHosting: z26.boolean()
2097
- }).strict().refine((value) => value.targetType === "siteplane_managed_fallback" || !value.approveManagedHosting);
2098
- var setupAssetTargetApprovalSchema = z26.object({
2099
- id: z26.string().uuid(),
2100
- runId: z26.string().uuid(),
2101
- reviewVersion: z26.number().int().positive(),
2102
- snapshotHash: z26.string().regex(/^sha256:[0-9a-f]{64}$/u),
2103
- targetId: z26.string().uuid(),
2104
- targetType: z26.enum(["repo_static_assets", "siteplane_managed_fallback"]),
2105
- targetRevision: z26.number().int().positive(),
2106
- deploymentOrigin: z26.string().url(),
2107
- gitConnectionId: z26.string().uuid().nullable(),
2108
- gitRevision: z26.number().int().positive().nullable(),
2109
- managedHostingApproved: z26.boolean(),
2110
- actorUserId: z26.string().uuid(),
2111
- approvedAt: z26.string().datetime({ offset: true })
2112
- }).strict();
2113
- var setupAssetReadinessSchema = z26.union([
2114
- z26.object({
2115
- status: z26.enum([
2116
- "not_required",
2117
- "needs_choice",
2118
- "stale_setup_review",
2119
- "permission_denied"
2120
- ])
2121
- }).strict(),
2122
- z26.object({
2123
- status: z26.literal("stale_approval"),
2124
- approval: setupAssetTargetApprovalSchema.optional()
2125
- }).strict(),
1536
+ var FIELD_SYNC_MAX_FIELDS = 2e3;
1537
+ var filePathSchema = z26.string().trim().min(1).max(500).refine((value) => !value.startsWith("/") && !value.includes("\\") && !/^[a-z]:/iu.test(value) && !value.split("/").includes(".."), "Use the file path relative to the project root.");
1538
+ var fieldBase = {
1539
+ id: fieldIdSchema.max(160),
1540
+ file: filePathSchema,
1541
+ label: z26.string().trim().min(1).max(120).optional()
1542
+ };
1543
+ var fieldSyncFieldSchema = z26.discriminatedUnion("type", [
1544
+ z26.object({ ...fieldBase, type: z26.literal("text"), fallback: z26.string().max(256) }).strict(),
1545
+ z26.object({ ...fieldBase, type: z26.literal("longText"), fallback: z26.string().max(5e4) }).strict(),
2126
1546
  z26.object({
2127
- status: z26.literal("not_verified"),
2128
- approval: setupAssetTargetApprovalSchema,
2129
- jobId: z26.string().uuid().optional(),
2130
- checkedAt: z26.string().datetime({ offset: true }).nullable().optional()
1547
+ ...fieldBase,
1548
+ type: z26.literal("link"),
1549
+ fallback: z26.object({ href: z26.string().min(1).max(2048), label: z26.string().max(256) }).strict()
2131
1550
  }).strict(),
2132
1551
  z26.object({
2133
- status: z26.enum(["ready", "checking", "retrying"]),
2134
- approval: setupAssetTargetApprovalSchema,
2135
- jobId: z26.string().uuid(),
2136
- checkedAt: z26.string().datetime({ offset: true }).nullable()
2137
- }).strict().refine((value) => value.status !== "ready" || value.checkedAt !== null)
2138
- ]);
2139
- var checkSetupAssetTargetInputSchema = z26.object({
2140
- siteId: z26.string().uuid(),
2141
- runId: z26.string().uuid(),
2142
- approvalId: z26.string().uuid(),
2143
- intent: z26.enum(["start", "poll"])
2144
- }).strict();
2145
-
2146
- // ../shared/dist/setup-installation.js
2147
- import { z as z27 } from "zod";
2148
- var setupInstallationRequestSchema = z27.object({
2149
- modules: siteSetupModulesSchema,
2150
- ownerEditabilityNote: siteSetupOwnerEditabilityNoteSchema,
2151
- provider: z27.object({
2152
- projectId: z27.string().min(1).max(200),
2153
- teamId: z27.string().min(1).max(200)
1552
+ ...fieldBase,
1553
+ type: z26.literal("image"),
1554
+ fallback: z26.object({ src: z26.string().min(1).max(2048), alt: z26.string().max(300) }).strict()
2154
1555
  }).strict()
2155
- }).strict();
1556
+ ]);
1557
+ var fieldSyncRequestSchema = z26.object({ fields: z26.array(fieldSyncFieldSchema).max(FIELD_SYNC_MAX_FIELDS) }).strict();
1558
+
1559
+ // ../shared/dist/signing-keys.js
1560
+ var pkcs8Ed25519Prefix = Uint8Array.from([
1561
+ 48,
1562
+ 46,
1563
+ 2,
1564
+ 1,
1565
+ 0,
1566
+ 48,
1567
+ 5,
1568
+ 6,
1569
+ 3,
1570
+ 43,
1571
+ 101,
1572
+ 112,
1573
+ 4,
1574
+ 34,
1575
+ 4,
1576
+ 32
1577
+ ]);
2156
1578
 
2157
- // ../shared/dist/setup-claim.js
2158
- import { z as z28 } from "zod";
2159
- var setupClaimCodeSchema = z28.string().regex(/^[0-9A-HJKMNP-TV-Z]{8}$/u);
2160
- var setupClaimBindingSchema = z28.object({
2161
- siteId: z28.string().uuid(),
2162
- runId: z28.string().uuid()
2163
- });
2164
- var setupClaimReceiptSchema = setupClaimBindingSchema.extend({
2165
- status: z28.literal("claimed"),
2166
- requestId: z28.string().uuid(),
2167
- workspaceId: z28.string().uuid(),
2168
- userId: z28.string().uuid(),
2169
- claimedAt: z28.string().datetime({ offset: true })
2170
- }).strict();
2171
- var setupClaimInspectionSchema = setupClaimBindingSchema.extend({
2172
- status: z28.literal("pending"),
2173
- requestId: z28.string().uuid(),
2174
- siteName: z28.string(),
2175
- userId: z28.string().uuid(),
2176
- accountEmail: z28.string().email(),
2177
- workspaceId: z28.string().uuid(),
2178
- workspaceName: z28.string(),
2179
- expiresAt: z28.string().datetime({ offset: true })
2180
- }).strict();
2181
- var setupClaimDenialSchema = z28.object({
2182
- status: z28.enum([
2183
- "invalid_claim_request",
2184
- "invalid_installation",
2185
- "already_claimed",
2186
- "project_expired",
2187
- "invalid_guest_session",
2188
- "stale_setup_review",
2189
- "verified_account_required",
2190
- "workspace_access_denied",
2191
- "workspace_entitlement_required",
2192
- "site_limit_reached",
2193
- "provisional_relationship_conflict",
2194
- "rate_limited"
2195
- ])
2196
- }).strict();
1579
+ // ../shared/dist/preview-token.js
1580
+ var PREVIEW_TOKEN_MAX_SECONDS = 60 * 60;
1581
+ var header = encodeJson({ alg: "EdDSA", typ: "JWT" });
1582
+ function encodeJson(value) {
1583
+ return toBase64Url(new TextEncoder().encode(JSON.stringify(value)));
1584
+ }
1585
+ function toBase64Url(bytes) {
1586
+ let binary = "";
1587
+ for (const byte of bytes)
1588
+ binary += String.fromCharCode(byte);
1589
+ return btoa(binary).replace(/\+/gu, "-").replace(/\//gu, "_").replace(/=+$/u, "");
1590
+ }
2197
1591
 
2198
- // ../cli/dist/analytics/static-scan.js
2199
- import ts from "typescript";
1592
+ // ../shared/dist/webhook-signature.js
1593
+ var WEBHOOK_TOLERANCE_SECONDS = 5 * 60;
1594
+ var encoder = new TextEncoder();
2200
1595
 
2201
1596
  // ../cli/dist/booking/manifest.js
2202
- import { mkdir as mkdir2, readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
2203
- import { dirname as dirname2 } from "path";
2204
1597
  async function readBookingManifestFile(manifestPath) {
2205
- return validateBookingManifestInput(JSON.parse(await readFile2(manifestPath, "utf8")));
1598
+ return validateBookingManifestInput(JSON.parse(await readFile(manifestPath, "utf8")));
2206
1599
  }
2207
1600
  async function writeBookingManifestFile(manifestPath, manifest) {
2208
- await mkdir2(dirname2(manifestPath), {
1601
+ await mkdir(dirname(manifestPath), {
2209
1602
  recursive: true
2210
1603
  });
2211
- await writeFile2(manifestPath, `${JSON.stringify(bookingManifestSchema.parse(manifest), null, 2)}
1604
+ await writeFile(manifestPath, `${JSON.stringify(bookingManifestSchema.parse(manifest), null, 2)}
2212
1605
  `, "utf8");
2213
1606
  }
2214
1607
  function validateBookingManifestInput(input) {
@@ -2242,18 +1635,18 @@ function collectRedactedBookingKeys(input, prefix = "") {
2242
1635
  }
2243
1636
 
2244
1637
  // ../cli/dist/booking/static-scan.js
2245
- import ts2 from "typescript";
1638
+ import ts from "typescript";
2246
1639
  function scanBookingSourceFiles(files, input) {
2247
1640
  const findings = [];
2248
1641
  const hardErrors = [];
2249
1642
  const warnings = [];
2250
1643
  for (const file of files) {
2251
1644
  let visit2 = function(node) {
2252
- if (ts2.isCallExpression(node) && ts2.isIdentifier(node.expression) && node.expression.text === "withSiteplane") {
1645
+ if (ts.isCallExpression(node) && ts.isIdentifier(node.expression) && node.expression.text === "withSiteplane") {
2253
1646
  const options = node.arguments[1];
2254
1647
  const booking = options && property(options, "booking");
2255
1648
  const site = booking && property(booking, "site");
2256
- if (site && ts2.isStringLiteralLike(site)) {
1649
+ if (site && ts.isStringLiteralLike(site)) {
2257
1650
  const issue = {
2258
1651
  code: site.text === input.siteId ? "booking_scan.integration_found" : "booking_scan.site_mismatch",
2259
1652
  message: site.text === input.siteId ? "Booking /booking rewrite configured for this Site ID." : "The Booking wrapper uses a different Site ID; use the Site ID supplied by Siteplane.",
@@ -2262,10 +1655,10 @@ function scanBookingSourceFiles(files, input) {
2262
1655
  (site.text === input.siteId ? findings : hardErrors).push(issue);
2263
1656
  }
2264
1657
  }
2265
- ts2.forEachChild(node, visit2);
1658
+ ts.forEachChild(node, visit2);
2266
1659
  };
2267
1660
  var visit = visit2;
2268
- const source = ts2.createSourceFile(file.filePath, file.sourceText, ts2.ScriptTarget.Latest, true, ts2.ScriptKind.TSX);
1661
+ const source = ts.createSourceFile(file.filePath, file.sourceText, ts.ScriptTarget.Latest, true, ts.ScriptKind.TSX);
2269
1662
  visit2(source);
2270
1663
  }
2271
1664
  if (!findings.length && !hardErrors.length)
@@ -2292,121 +1685,22 @@ function scanBookingSourceFiles(files, input) {
2292
1685
  suggestions: []
2293
1686
  };
2294
1687
  }
2295
- function property(node, name2) {
2296
- if (!ts2.isObjectLiteralExpression(node))
1688
+ function property(node, name) {
1689
+ if (!ts.isObjectLiteralExpression(node))
2297
1690
  return;
2298
1691
  for (const item of node.properties) {
2299
- if (ts2.isPropertyAssignment(item) && (ts2.isIdentifier(item.name) || ts2.isStringLiteral(item.name)) && item.name.text === name2)
1692
+ if (ts.isPropertyAssignment(item) && (ts.isIdentifier(item.name) || ts.isStringLiteral(item.name)) && item.name.text === name)
2300
1693
  return item.initializer;
2301
1694
  }
2302
1695
  }
2303
1696
 
2304
- // ../cli/dist/commands/analytics/check.js
2305
- import { readFile as readFile3 } from "fs/promises";
2306
-
2307
- // ../cli/dist/commands/analytics/init.js
2308
- import { mkdir as mkdir3, writeFile as writeFile3 } from "fs/promises";
2309
- import { dirname as dirname3, join } from "path";
2310
- var analyticsRulesTemplate = `# Siteplane Analytics Rules
2311
-
2312
- Analytics contract version: ${ANALYTICS_CONTRACT_VERSION}
2313
- Analytics contract hash: ${ANALYTICS_CONTRACT_HASH}
2314
-
2315
- - Do not change visible layout, copy, styling, animation or business logic while adding analytics.
2316
- - Use stable data-siteplane-target-id values that do not depend on visible copy.
2317
- - Use public site keys only through environment references.
2318
- - Do not write secret analytics keys, setup tokens or project CLI tokens into source files.
2319
- - Mount the SDK once in the existing client lifecycle. Wire installDataAttributeTracking and createNextAppRouterNavigationAdapter to analytics.track/getRouteViewId/setPageContext, feed initial and subsequent Next.js pathname changes, and refresh attribute targets after navigation. Dispose attribute tracking and the SDK on unmount.
2320
- - Inspect existing consent management. Pass consentAdapter with getConsent and subscribe to initSiteplaneAnalytics for an existing CMP; return unknown while unresolved, disabled for denial and a permitted mode only for its actual visitor grant. Subscribe returns cleanup. Do not mirror CMP snapshots with setConsent or replace stored opt-outs.
2321
- - Omit consentAdapter only after confirming no existing CMP. An unrecognized CMP blocks Analytics with a concrete repair diagnostic; do not invent a grant or a no-op adapter to pass a check.
2322
- - Suppress editor-preview traffic from live analytics.
2323
- - Run npx siteplane analytics check, npx siteplane analytics sync and npx siteplane analytics test after setup.
2324
- `;
2325
- var analyticsCursorRulesTemplate = `---
2326
- description: Siteplane Analytics rules
2327
- alwaysApply: true
2328
- ---
2329
-
2330
- ${analyticsRulesTemplate}`;
2331
-
2332
- // ../cli/dist/commands/analytics/import.js
2333
- import { createHash } from "crypto";
2334
-
2335
- // ../cli/dist/commands/analytics/sync.js
2336
- function createAnalyticsCliRequestHeaders(config) {
2337
- const headers = {
2338
- authorization: `Bearer ${config.accessToken}`,
2339
- "content-type": "application/json"
2340
- };
2341
- const bypassSecret = config.vercelAutomationBypassSecret?.trim();
2342
- if (bypassSecret) {
2343
- headers["x-vercel-protection-bypass"] = bypassSecret;
2344
- }
2345
- return headers;
2346
- }
2347
-
2348
- // ../cli/dist/commands/analytics/public-key.js
2349
- import { z as z29 } from "zod";
2350
- var responseSchema = z29.object({
2351
- ok: z29.literal(true),
2352
- data: z29.object({
2353
- rawPublicKey: z29.string().regex(/^pk_siteplane_[A-Za-z0-9_-]{16}_[A-Za-z0-9_-]{43}$/)
2354
- })
2355
- });
2356
- var errorResponseSchema = z29.object({
2357
- error: z29.object({
2358
- code: z29.string().regex(/^[a-z][a-z0-9_.-]+$/u)
2359
- })
2360
- });
2361
- async function analyticsPublicKeyCommand(input) {
2362
- const fetcher = input.fetchImpl ?? fetch;
2363
- const response = await fetcher(`${input.config.apiBaseUrl.replace(/\/$/u, "")}/api/cli/analytics/public-key`, {
2364
- method: "POST",
2365
- redirect: "error",
2366
- signal: AbortSignal.timeout(2e4),
2367
- headers: createAnalyticsCliRequestHeaders(input.config),
2368
- body: JSON.stringify({ siteId: input.config.siteId })
2369
- });
2370
- const payload = await response.json().catch(() => null);
2371
- const parsed = responseSchema.safeParse(payload);
2372
- if (!response.ok || !parsed.success) {
2373
- const error = errorResponseSchema.safeParse(payload);
2374
- throw new Error(`${error.success ? error.data.error.code : "analytics_public_key.invalid_response"}: Unable to read the active Analytics public key.`);
2375
- }
2376
- return parsed.data.data.rawPublicKey;
2377
- }
2378
-
2379
- // ../cli/dist/commands/analytics/prepare.js
2380
- import { z as z30 } from "zod";
2381
- var resultSchema = z30.object({
2382
- ok: z30.literal(true),
2383
- data: z30.object({
2384
- rawPublicKey: z30.string().regex(/^pk_siteplane_[A-Za-z0-9_-]{16}_[A-Za-z0-9_-]{43}$/u),
2385
- generation: z30.number().int().positive(),
2386
- status: z30.enum([
2387
- "setup_started",
2388
- "test_mode",
2389
- "active",
2390
- "paused",
2391
- "error",
2392
- "deleting"
2393
- ])
2394
- }).strict()
2395
- }).strict();
2396
- var errorSchema = z30.object({
2397
- error: z30.object({ code: z30.string().regex(/^[a-z][a-z0-9_.-]+$/u) })
2398
- });
2399
-
2400
- // ../cli/dist/commands/analytics/test.js
2401
- import { randomUUID } from "crypto";
2402
-
2403
1697
  // ../cli/dist/commands/booking/check.js
2404
- import { dirname as dirname4, join as join2 } from "path";
2405
- import { access, readFile as readFile4 } from "fs/promises";
1698
+ import { dirname as dirname2, join } from "path";
1699
+ import { access, readFile as readFile2 } from "fs/promises";
2406
1700
  async function bookingCheckCommand(input) {
2407
1701
  const validatedManifest = await readBookingManifestFile(input.manifestPath);
2408
- const configs = (await Promise.all(["next.config.ts", "next.config.js", "next.config.mjs"].map(async (name2) => {
2409
- const path = join2(dirname4(input.manifestPath), name2);
1702
+ const configs = (await Promise.all(["next.config.ts", "next.config.js", "next.config.mjs"].map(async (name) => {
1703
+ const path = join(dirname2(input.manifestPath), name);
2410
1704
  return await access(path).then(() => path, () => null);
2411
1705
  }))).filter((path) => path !== null);
2412
1706
  const sourceFiles = await readSourceFiles([
@@ -2438,7 +1732,7 @@ async function bookingCheckCommand(input) {
2438
1732
  async function readSourceFiles(filePaths) {
2439
1733
  return Promise.all(filePaths.map(async (filePath) => ({
2440
1734
  filePath,
2441
- sourceText: await readFile4(filePath, "utf8")
1735
+ sourceText: await readFile2(filePath, "utf8")
2442
1736
  })));
2443
1737
  }
2444
1738
  function createBoundaryErrors(validation) {
@@ -2450,8 +1744,8 @@ function createBoundaryErrors(validation) {
2450
1744
  }
2451
1745
 
2452
1746
  // ../cli/dist/commands/booking/init.js
2453
- import { mkdir as mkdir4, writeFile as writeFile4 } from "fs/promises";
2454
- import { dirname as dirname5, join as join3 } from "path";
1747
+ import { mkdir as mkdir2, writeFile as writeFile2 } from "fs/promises";
1748
+ import { dirname as dirname3, join as join2 } from "path";
2455
1749
  async function bookingInitCommand(input) {
2456
1750
  const manifest = {
2457
1751
  schemaVersion: 1,
@@ -2459,7 +1753,7 @@ async function bookingInitCommand(input) {
2459
1753
  bookingPageSlug: input.bookingPageSlug,
2460
1754
  ...input.productionOrigin ? { productionOrigin: input.productionOrigin } : {}
2461
1755
  };
2462
- const manifestPath = join3(input.projectDir, "siteplane.booking.json");
1756
+ const manifestPath = join2(input.projectDir, "siteplane.booking.json");
2463
1757
  const artifacts = createBookingArtifacts(input.agentClient);
2464
1758
  await writeBookingManifestFile(manifestPath, manifest);
2465
1759
  for (const artifact of artifacts) {
@@ -2499,9 +1793,9 @@ function createBookingArtifacts(agentClient) {
2499
1793
  return artifacts;
2500
1794
  }
2501
1795
  async function writeProjectFile(projectDir, relativePath, contents) {
2502
- const path = join3(projectDir, relativePath);
2503
- await mkdir4(dirname5(path), { recursive: true });
2504
- await writeFile4(path, contents, "utf8");
1796
+ const path = join2(projectDir, relativePath);
1797
+ await mkdir2(dirname3(path), { recursive: true });
1798
+ await writeFile2(path, contents, "utf8");
2505
1799
  }
2506
1800
  var bookingRulesTemplate = `# Siteplane Booking Rules
2507
1801
 
@@ -2513,6 +1807,7 @@ var bookingRulesTemplate = `# Siteplane Booking Rules
2513
1807
  - Preserve customer CSP and middleware; explain required Siteplane/Stripe permissions and exclude /booking from customer middleware.
2514
1808
  - Do not write setup tokens, project CLI tokens or private keys into source files.
2515
1809
  - Run npx siteplane booking check, npx siteplane booking sync and npx siteplane booking test after setup.
1810
+ - The first booking sync prints a link and code for the Siteplane approval; give both to the user and wait until they click Connect. The connection stays outside the project.
2516
1811
  - booking test stays in test_mode; live booking only starts after explicit dashboard activation.
2517
1812
  `;
2518
1813
  function bookingSkillTemplate(agentName) {
@@ -2571,1172 +1866,61 @@ async function bookingTestCommand(input) {
2571
1866
  });
2572
1867
  }
2573
1868
 
2574
- // ../cli/dist/commands/export.js
2575
- async function exportCommand(input) {
2576
- requireContentExportScope(input.tokenScopes);
2577
- const values = await input.readPublishedValues();
2578
- if (input.format === "prompt") {
2579
- return {
2580
- kind: "prompt",
2581
- output: Object.entries(values).map(([fieldId, value]) => `${fieldId}: ${JSON.stringify(value)}`).join("\n")
2582
- };
2583
- }
2584
- return {
2585
- kind: "json",
2586
- values
2587
- };
2588
- }
2589
- function requireContentExportScope(scopes) {
2590
- if (!scopes?.includes("content:export")) {
2591
- throw new Error("A Project Connection with content:export is required.");
2592
- }
2593
- }
2594
-
2595
- // ../cli/dist/config/project-config.js
2596
- import { access as access2, chmod, open, readFile as readFile5, rename, rm } from "fs/promises";
2597
- import { randomUUID as randomUUID2 } from "crypto";
2598
- import { join as join4 } from "path";
2599
- import { z as z31 } from "zod";
2600
- var siteplaneProjectConfigSchema = z31.object({
2601
- version: z31.literal(2),
2602
- apiBaseUrl: z31.string().url(),
2603
- siteId: z31.string().uuid(),
2604
- publicSiteKeyId: z31.string().uuid(),
2605
- publicSiteKey: z31.string().trim().min(1),
2606
- runId: z31.string().uuid(),
2607
- appDirectory: z31.string().min(1),
2608
- taskContractVersion: z31.literal("siteplane.setup-task.v2"),
2609
- adminProtocolVersion: z31.literal(2),
2610
- packages: siteSetupPackagesSchema,
2611
- fieldContractHash: z31.string().regex(/^sha256:[0-9a-f]{64}$/iu).optional()
2612
- }).strict();
2613
- async function readProjectPackageJson(projectDir) {
2614
- return JSON.parse(await readFile5(join4(projectDir, "package.json"), "utf8"));
2615
- }
2616
- async function detectNextProject(projectDir) {
2617
- const packageJson = await readProjectPackageJson(projectDir).catch(() => null);
2618
- if (packageJson?.dependencies?.next || packageJson?.devDependencies?.next) {
2619
- return true;
2620
- }
2621
- for (const fileName of [
2622
- "next.config.js",
2623
- "next.config.mjs",
2624
- "next.config.ts"
2625
- ]) {
2626
- try {
2627
- await access2(join4(projectDir, fileName));
2628
- return true;
2629
- } catch {
2630
- }
2631
- }
2632
- return false;
2633
- }
2634
- async function writeProjectConfig(projectDir, config) {
2635
- const path = join4(projectDir, "siteplane.config.json");
2636
- const parsed = siteplaneProjectConfigSchema.parse(config);
2637
- await writeJsonAtomically(path, parsed, 420);
2638
- return path;
2639
- }
2640
- async function readProjectConfig(projectDir) {
2641
- return siteplaneProjectConfigSchema.parse(JSON.parse(await readFile5(join4(projectDir, "siteplane.config.json"), "utf8")));
2642
- }
2643
- async function writeJsonAtomically(path, value, mode) {
2644
- const temporaryPath = `${path}.${randomUUID2()}.tmp`;
2645
- const file = await open(temporaryPath, "wx", mode);
2646
- try {
2647
- await file.writeFile(`${JSON.stringify(value, null, 2)}
2648
- `, "utf8");
2649
- await file.sync();
2650
- } catch (error) {
2651
- await file.close();
2652
- await rm(temporaryPath, { force: true });
2653
- throw error;
2654
- }
2655
- await file.close();
2656
- try {
2657
- await rename(temporaryPath, path);
2658
- await chmod(path, mode);
2659
- } catch (error) {
2660
- await rm(temporaryPath, { force: true });
2661
- throw error;
2662
- }
2663
- }
2664
-
2665
- // ../cli/dist/config/credentials.js
2666
- import { execFile } from "child_process";
2667
- import { randomUUID as randomUUID3 } from "crypto";
2668
- import { chmod as chmod2, lstat, mkdir as mkdir5, open as open2, readFile as readFile6, rename as rename2, rm as rm2 } from "fs/promises";
2669
- import { dirname as dirname6, join as join5, relative } from "path";
2670
- import { promisify } from "util";
2671
- import { z as z32 } from "zod";
2672
- var localSetupInstallationSchema = z32.object({
2673
- key: z32.string().regex(/^[A-Za-z0-9_-]{43}$/u),
2674
- idempotencyKey: z32.string().uuid(),
2675
- apiBaseUrl: z32.string().url(),
2676
- request: setupInstallationRequestSchema,
2677
- bootstrapAcknowledged: z32.boolean()
2678
- }).strict();
2679
- var siteplaneCredentialsSchema = z32.object({
2680
- accessToken: z32.string().trim().min(1),
2681
- siteRevalidationSecret: z32.string().trim().min(1),
2682
- installation: localSetupInstallationSchema.optional(),
2683
- claimReceipt: setupClaimReceiptSchema.optional(),
2684
- adminSession: z32.object({
2685
- secret: z32.string().regex(/^[A-Za-z0-9_-]{43}$/u),
2686
- generation: z32.string().uuid()
2687
- }).strict().optional()
2688
- }).strict();
2689
- var localSetupCredentialsSchema = z32.union([
2690
- siteplaneCredentialsSchema,
2691
- z32.object({ installation: localSetupInstallationSchema }).strict()
2692
- ]);
2693
- async function assertLocalCredentialsPathSafe(projectDir, options = {}) {
2694
- const path = join5(projectDir, ".siteplane/credentials.json");
2695
- await assertCredentialFilesystemSafe(projectDir);
2696
- const isTrackedFile = options.isTrackedFile ?? ((targetPath) => gitPathMatches(projectDir, targetPath, "ls-files"));
2697
- const isIgnoredFile = options.isIgnoredFile ?? ((targetPath) => gitPathMatches(projectDir, targetPath, "check-ignore"));
2698
- if (await isTrackedFile(path)) {
2699
- throw new Error("Refusing to write Siteplane credentials into a tracked file.");
2700
- }
2701
- if (!await isIgnoredFile(path)) {
2702
- throw new Error("Add .siteplane/credentials.json to .gitignore before running Siteplane init.");
2703
- }
2704
- return path;
2705
- }
2706
- async function assertCredentialFilesystemSafe(projectDir) {
2707
- for (const [path, directory, mode] of [
2708
- [projectDir, true, null],
2709
- [join5(projectDir, ".siteplane"), true, 448],
2710
- [join5(projectDir, ".siteplane/credentials.json"), false, 384]
2711
- ]) {
2712
- const stat = await lstat(path).catch((error) => {
2713
- if (error.code === "ENOENT")
2714
- return null;
2715
- throw error;
2716
- });
2717
- if (!stat)
2718
- continue;
2719
- if (stat.isSymbolicLink() || (directory ? !stat.isDirectory() : !stat.isFile())) {
2720
- throw new Error("Siteplane credential paths must not contain symlinks or unexpected file types.");
2721
- }
2722
- if (mode !== null && (stat.mode & 511) !== mode) {
2723
- throw new Error(`Siteplane credential ${directory ? "directory" : "file"} permissions must be ${mode.toString(8)} before setup.`);
2724
- }
2725
- }
2726
- }
2727
- async function writeLocalCredentials(projectDir, credentials, options = {}) {
2728
- return writeLocalSetupCredentials(projectDir, siteplaneCredentialsSchema.parse(credentials), options);
2729
- }
2730
- async function writeLocalSetupCredentials(projectDir, credentials, options = {}) {
2731
- const path = await assertLocalCredentialsPathSafe(projectDir, options);
2732
- const parsed = localSetupCredentialsSchema.parse(credentials);
2733
- await mkdir5(dirname6(path), { recursive: true, mode: 448 });
2734
- await writeCredentialsAtomically(path, parsed);
2735
- return path;
2736
- }
2737
- async function readLocalCredentials(projectDir) {
2738
- const credentials = await readLocalSetupCredentials(projectDir);
2739
- if (!("accessToken" in credentials)) {
2740
- throw new Error("setup_exchange_pending: Run siteplane setup start to finish the stored installation exchange.");
2741
- }
2742
- return credentials;
2743
- }
2744
- async function readLocalSetupCredentials(projectDir) {
2745
- await assertCredentialFilesystemSafe(projectDir);
2746
- return localSetupCredentialsSchema.parse(JSON.parse(await readFile6(join5(projectDir, ".siteplane/credentials.json"), "utf8")));
2747
- }
2748
- async function writeCredentialsAtomically(path, credentials) {
2749
- const temporaryPath = `${path}.${randomUUID3()}.tmp`;
2750
- const file = await open2(temporaryPath, "wx", 384);
2751
- try {
2752
- await file.writeFile(`${JSON.stringify(credentials, null, 2)}
2753
- `, "utf8");
2754
- await file.sync();
2755
- } catch (error) {
2756
- await file.close();
2757
- await rm2(temporaryPath, { force: true });
2758
- throw error;
2759
- }
2760
- await file.close();
2761
- try {
2762
- await rename2(temporaryPath, path);
2763
- await chmod2(path, 384);
2764
- const directory = await open2(dirname6(path), "r");
2765
- try {
2766
- await directory.sync();
2767
- } finally {
2768
- await directory.close();
2769
- }
2770
- } catch (error) {
2771
- await rm2(temporaryPath, { force: true });
2772
- throw error;
2773
- }
2774
- }
2775
- var execFileAsync = promisify(execFile);
2776
- async function gitPathMatches(projectDir, path, command) {
2777
- const args = command === "check-ignore" ? ["check-ignore", "--quiet", relative(projectDir, path)] : ["ls-files", "--error-unmatch", relative(projectDir, path)];
2778
- try {
2779
- await execFileAsync("git", args, { cwd: projectDir });
2780
- return true;
2781
- } catch {
2782
- return false;
2783
- }
2784
- }
2785
-
2786
- // ../cli/dist/commands/init.js
2787
- import { access as access4 } from "fs/promises";
2788
- import { join as join8, relative as relative3 } from "path";
2789
- import { z as z35 } from "zod";
2790
-
2791
- // ../cli/dist/commands/setup-preflight.js
2792
- import { createHash as createHash2 } from "crypto";
2793
- import semver from "semver";
2794
- import { minimatch } from "minimatch";
2795
- import { parse as parseYaml } from "yaml";
2796
-
2797
- // ../cli/dist/config/installed-package.js
2798
- import { createRequire } from "module";
2799
- import { readFile as readFile7 } from "fs/promises";
2800
- import { join as join6 } from "path";
2801
- import { z as z33 } from "zod";
2802
- var packageSchema = z33.object({
2803
- name: z33.string().optional(),
2804
- version: z33.string(),
2805
- peerDependencies: z33.record(z33.string(), z33.string()).optional()
2806
- });
2807
- async function readInstalledPackage(projectDir, name2) {
2808
- const require2 = createRequire(join6(projectDir, "package.json"));
2809
- for (const directory of require2.resolve.paths(name2) ?? []) {
2810
- try {
2811
- return packageSchema.parse(JSON.parse(await readFile7(join6(directory, name2, "package.json"), "utf8")));
2812
- } catch (error) {
2813
- if (error.code !== "ENOENT")
2814
- throw error;
2815
- }
2816
- }
2817
- throw new Error(`Install ${name2} with the canonical package manager before setup.`);
2818
- }
2819
-
2820
- // ../cli/dist/commands/setup-preflight.js
2821
- import { access as access3, readFile as readFile8, realpath, readdir, readlink } from "fs/promises";
2822
- import { dirname as dirname7, join as join7, relative as relative2, resolve, sep } from "path";
2823
- import { z as z34 } from "zod";
1869
+ // ../cli/dist/commands/scan.js
1870
+ import { readdir } from "fs/promises";
1871
+ import { extname, join as join3 } from "path";
2824
1872
 
2825
- // ../cli/dist/commands/setup-process.js
1873
+ // ../cli/dist/auth/device-login.js
2826
1874
  import { spawn } from "child_process";
2827
- var SetupFailure = class extends Error {
2828
- code;
2829
- constructor(code, message) {
2830
- super(message);
2831
- this.code = code;
2832
- }
2833
- };
2834
- async function setupProcess(binary, args, options) {
2835
- return new Promise((resolve4, reject) => {
2836
- const child = spawn(binary, args, {
2837
- cwd: options.cwd,
2838
- env: process.env,
2839
- stdio: ["pipe", "pipe", "pipe"]
2840
- });
2841
- const chunks = [];
2842
- const errors = [];
2843
- let errorBytes = 0;
2844
- let bytes = 0;
2845
- let exceeded = false;
2846
- const timer = setTimeout(() => {
2847
- exceeded = true;
2848
- child.kill("SIGKILL");
2849
- }, options.timeoutMs ?? 12e4);
2850
- const capture = (chunk) => {
2851
- bytes += chunk.length;
2852
- if (bytes > 4 * 1024 * 1024) {
2853
- exceeded = true;
2854
- child.kill("SIGKILL");
2855
- } else
2856
- chunks.push(chunk);
2857
- };
2858
- child.stdout.on("data", capture);
2859
- child.stderr.on("data", (chunk) => {
2860
- errorBytes += chunk.length;
2861
- if (errorBytes <= 4 * 1024 * 1024)
2862
- errors.push(chunk);
2863
- else {
2864
- exceeded = true;
2865
- child.kill("SIGKILL");
2866
- }
2867
- });
2868
- child.on("error", () => {
2869
- clearTimeout(timer);
2870
- reject(new SetupFailure("local_tool_unavailable", `${binary} could not be started. Check the local installation and access.`));
2871
- });
2872
- child.on("close", (code) => {
2873
- clearTimeout(timer);
2874
- if (exceeded)
2875
- reject(new SetupFailure("provider_timeout", "The operation exceeded its time or response limit; inspect the existing operation before retrying."));
2876
- else if (code !== 0) {
2877
- const diagnostic = Buffer.concat([...chunks, ...errors]).toString("utf8");
2878
- if (/\b(?:401|403|unauthorized|forbidden|not authenticated|not authorized|login required|E401|E403)\b/iu.test(diagnostic))
2879
- reject(new SetupFailure("provider_access_denied", `${binary} denied access. Restore the existing local login and project/package permissions before retrying.`));
2880
- else if (/\b(?:ECONNRESET|ETIMEDOUT|ENOTFOUND|EAI_AGAIN|ECONNREFUSED|429|502|503|504)\b/iu.test(diagnostic))
2881
- reject(new SetupFailure("provider_transport_failed", `${binary} could not reach its provider. Inspect the existing operation before retrying.`));
2882
- else
2883
- reject(new SetupFailure("local_command_failed", `${binary} failed. Check its local login, permissions and project configuration.`));
2884
- } else
2885
- resolve4(Buffer.concat(options.includeStderr ? [...chunks, ...errors] : chunks).toString("utf8"));
2886
- });
2887
- child.stdin.on("error", () => {
2888
- });
2889
- child.stdin.end(options.input);
2890
- });
2891
- }
2892
- async function setupVercelApi(cwd, endpoint, body, method, options) {
2893
- const args = ["api", endpoint, "--raw"];
2894
- if (body !== void 0)
2895
- args.push("--method", method ?? "POST", "--input", "-");
2896
- else if (method)
2897
- args.push("--method", method);
2898
- let output = "";
2899
- for (let attempt = 0; attempt < 3; attempt++) {
2900
- const remaining = (options?.deadline ?? Date.now() + 3e4) - Date.now();
2901
- if (remaining <= 0)
2902
- throw new SetupFailure("provider_deadline_exceeded", "The provider deadline expired; inspect the recorded operation before continuing.");
2903
- try {
2904
- output = await setupProcess("vercel", args, {
2905
- cwd,
2906
- timeoutMs: Math.min(3e4, remaining),
2907
- ...body === void 0 ? {} : { input: JSON.stringify(body) }
2908
- });
2909
- break;
2910
- } catch (error) {
2911
- if (!(error instanceof SetupFailure) || error.code !== "provider_transport_failed" || attempt === 2)
2912
- throw error;
2913
- await new Promise((resolve4) => setTimeout(resolve4, Math.min(1e3 * 2 ** attempt, Math.max(0, (options?.deadline ?? Date.now() + 2e3) - Date.now()))));
2914
- }
2915
- }
2916
- try {
2917
- return JSON.parse(output);
2918
- } catch {
2919
- throw new SetupFailure("invalid_provider_response", "Vercel did not return valid JSON for the bound project.");
2920
- }
2921
- }
1875
+ import { hostname } from "os";
2922
1876
 
2923
- // ../cli/dist/commands/setup-preflight.js
2924
- var manifestSchema = z34.object({
2925
- packageManager: z34.string().optional(),
2926
- engines: z34.object({ node: z34.string().optional() }).optional(),
2927
- dependencies: z34.record(z34.string(), z34.string()).optional(),
2928
- devDependencies: z34.record(z34.string(), z34.string()).optional(),
2929
- scripts: z34.record(z34.string(), z34.string()).optional(),
2930
- workspaces: z34.unknown().optional()
2931
- });
2932
- var vercelProjectSchema = z34.object({
2933
- id: z34.string(),
2934
- accountId: z34.string(),
2935
- name: z34.string(),
2936
- nodeVersion: z34.string().nullable().optional(),
2937
- rootDirectory: z34.string().nullable().optional(),
2938
- framework: z34.string().nullable().optional(),
2939
- installCommand: z34.string().nullable().optional(),
2940
- buildCommand: z34.string().nullable().optional(),
2941
- link: z34.object({
2942
- type: z34.string(),
2943
- repo: z34.string().optional(),
2944
- repoId: z34.union([z34.string(), z34.number()]).optional(),
2945
- org: z34.string().optional(),
2946
- productionBranch: z34.string().optional()
2947
- }).nullable().optional()
1877
+ // ../cli/dist/config/agent-connections.js
1878
+ import { randomUUID } from "crypto";
1879
+ import { chmod, mkdir as mkdir3, open, readFile as readFile3, rename, rm } from "fs/promises";
1880
+ import { join as join4 } from "path";
1881
+ import { z as z27 } from "zod";
1882
+ var storeSchema = z27.object({
1883
+ connections: z27.array(z27.object({
1884
+ apiOrigin: z27.string().url(),
1885
+ siteId: z27.string().min(1),
1886
+ accessToken: z27.string().min(1),
1887
+ scopes: z27.array(z27.string()),
1888
+ expiresAt: z27.string()
1889
+ }))
2948
1890
  });
2949
- var exists = async (path) => access3(path).then(() => true, () => false);
2950
- var fail = (code, message) => {
2951
- throw new SetupFailure(code, message);
2952
- };
2953
- var stable = (version2, major) => new RegExp(`^${major}\\.\\d+\\.\\d+$`, "u").test(version2);
2954
- async function inspectSetupLocalProject(projectDir) {
2955
- const projectDirectory = await realpath(resolve(projectDir));
2956
- const manifest = manifestSchema.parse(JSON.parse(await readFile8(join7(projectDirectory, "package.json"), "utf8")));
2957
- const apps = (await Promise.all(["app", "src/app"].map(async (path) => await exists(join7(projectDirectory, path)) ? path : null))).filter((path) => path !== null);
2958
- if (apps.length !== 1)
2959
- fail("ambiguous_app_directory", "Select one Next.js App Router application with exactly one app/ or src/app/ directory.");
2960
- const repositoryRoot = (await setupProcess("git", ["rev-parse", "--show-toplevel"], {
2961
- cwd: projectDirectory
2962
- })).trim();
2963
- const tracked = await setupProcess("git", ["ls-files", "--stage", "-z"], {
2964
- cwd: repositoryRoot
2965
- });
2966
- for (const entry of tracked.split("\0").filter(Boolean)) {
2967
- if (entry.startsWith("160000 "))
2968
- fail("git_submodule_conflict", "The repository contains Git submodules. Resolve the explicit deployment source boundary before setup; the CLI will not copy external repositories.");
2969
- if (!entry.startsWith("120000 "))
2970
- continue;
2971
- const path = join7(repositoryRoot, entry.slice(entry.indexOf(" ") + 1));
2972
- const target = resolve(dirname7(path), await readlink(path));
2973
- const bound = relative2(repositoryRoot, target);
2974
- if (bound.startsWith("..") || bound.startsWith(sep))
2975
- fail("external_symlink_conflict", "A tracked symbolic link points outside this repository. Resolve that source boundary before setup; local external files cannot enter a deployment.");
2976
- }
2977
- let lockfileRoot = projectDirectory;
2978
- const lockNames = [
2979
- "package-lock.json",
2980
- "npm-shrinkwrap.json",
2981
- "pnpm-lock.yaml",
2982
- "yarn.lock",
2983
- "bun.lock",
2984
- "bun.lockb"
2985
- ];
2986
- let locks = [];
2987
- for (; ; ) {
2988
- locks = (await Promise.all(lockNames.map(async (name3) => await exists(join7(lockfileRoot, name3)) ? name3 : null))).filter((name3) => name3 !== null);
2989
- if (locks.length || lockfileRoot === repositoryRoot || dirname7(lockfileRoot) === lockfileRoot)
2990
- break;
2991
- lockfileRoot = dirname7(lockfileRoot);
2992
- }
2993
- if (locks.length > 1)
2994
- fail("conflicting_lockfiles", "Resolve conflicting package-manager lockfiles before setup; Siteplane does not replace them.");
2995
- if (!locks.length)
2996
- fail("lockfile_missing", "Install the existing application with its chosen package manager to create one canonical lockfile.");
2997
- const lockName = locks[0];
2998
- if (!["package-lock.json", "pnpm-lock.yaml"].includes(lockName))
2999
- fail("unsupported_package_manager", "This setup supports npm 10 or pnpm 9/10 with their canonical lockfile.");
3000
- const rootManifest = manifestSchema.parse(JSON.parse(await readFile8(join7(lockfileRoot, "package.json"), "utf8")));
3001
- if (lockfileRoot !== projectDirectory) {
3002
- const workspaceFile = join7(lockfileRoot, "pnpm-workspace.yaml");
3003
- const workspace = lockName === "pnpm-lock.yaml" && await exists(workspaceFile) ? z34.object({ packages: z34.array(z34.string()) }).parse(parseYaml(await readFile8(workspaceFile, "utf8"))).packages : z34.union([
3004
- z34.array(z34.string()),
3005
- z34.object({ packages: z34.array(z34.string()) }).transform((value) => value.packages)
3006
- ]).parse(rootManifest.workspaces);
3007
- const selected = relative2(lockfileRoot, projectDirectory).split(sep).join("/");
3008
- if (!workspace.some((pattern) => !pattern.startsWith("!") && minimatch(selected, pattern)) || workspace.some((pattern) => pattern.startsWith("!") && minimatch(selected, pattern.slice(1))))
3009
- fail("unbound_workspace_app", "The selected application is excluded from the canonical lockfile's workspace packages. Select its actual application root.");
3010
- }
3011
- for (let ancestor = dirname7(lockfileRoot); ancestor.startsWith(repositoryRoot + sep) || ancestor === repositoryRoot; ancestor = dirname7(ancestor)) {
3012
- const ancestorLocks = await Promise.all(lockNames.map((name3) => exists(join7(ancestor, name3))));
3013
- if (ancestorLocks.some(Boolean))
3014
- fail("ambiguous_lockfile_root", "Both the selected package and its repository ancestors contain lockfiles. Select one canonical workspace resolution before setup.");
3015
- if (ancestor === repositoryRoot)
3016
- break;
3017
- }
3018
- const lockText = await readFile8(join7(lockfileRoot, lockName), "utf8");
3019
- const npmLock = lockName === "package-lock.json" ? z34.object({
3020
- lockfileVersion: z34.number(),
3021
- packages: z34.record(z34.string(), z34.object({
3022
- version: z34.string().optional(),
3023
- peerDependencies: z34.record(z34.string(), z34.string()).optional()
3024
- })).optional()
3025
- }).parse(JSON.parse(lockText)) : null;
3026
- async function version2(name3) {
3027
- try {
3028
- return (await readInstalledPackage(projectDirectory, name3)).version;
3029
- } catch {
3030
- const resolved = npmLock?.packages?.[`node_modules/${name3}`]?.version;
3031
- if (resolved)
3032
- return resolved;
3033
- return fail("dependencies_not_installed", `Install the existing ${name3} dependency using the canonical lockfile before setup.`);
3034
- }
3035
- }
3036
- const [nextVersion, reactVersion, reactDomVersion] = await Promise.all([
3037
- version2("next"),
3038
- version2("react"),
3039
- version2("react-dom")
3040
- ]);
3041
- if (!stable(nextVersion, 16))
3042
- fail("unsupported_next_version", "Setup supports stable Next.js 16 App Router projects. Framework migration requires a separate owner decision.");
3043
- if (!stable(reactVersion, 19) || reactDomVersion !== reactVersion)
3044
- fail("react_version_conflict", "Use the same stable React 19/react-dom version compatible with the installed Next.js peers.");
3045
- if (!stable(process.versions.node, 22))
3046
- fail("unsupported_node_version", "Run setup under Node.js 22; this does not change your framework or package-manager versions.");
3047
- const nextMetadata = await readInstalledPackage(projectDirectory, "next").catch(() => npmLock?.packages?.["node_modules/next"] ?? null);
3048
- const peers = nextMetadata?.peerDependencies;
3049
- if (!peers?.react || !peers["react-dom"])
3050
- fail("next_peer_metadata_missing", "Install the locked Next.js dependency before setup so its actual React peer requirements can be checked.");
3051
- if (!semver.satisfies(reactVersion, peers.react) || !semver.satisfies(reactDomVersion, peers["react-dom"]))
3052
- fail("react_peer_conflict", "The installed React pair does not satisfy the installed Next.js peer requirements. Choose a compatible pair explicitly.");
3053
- if (manifest.engines?.node && !semver.satisfies(process.versions.node, manifest.engines.node))
3054
- fail("node_engine_conflict", "The selected application's Node engine declaration excludes the active supported Node.js 22 runtime.");
3055
- const name2 = lockName === "package-lock.json" ? "npm" : "pnpm";
3056
- const declared = rootManifest.packageManager ?? manifest.packageManager ?? null;
3057
- if (rootManifest.packageManager && manifest.packageManager && rootManifest.packageManager !== manifest.packageManager)
3058
- fail("package_manager_conflict", "Application and workspace packageManager declarations disagree.");
3059
- if (declared && !new RegExp(`^${name2}@\\d+\\.\\d+\\.\\d+$`, "u").test(declared))
3060
- fail("package_manager_conflict", "Declare an exact supported npm/pnpm packageManager version matching the canonical lockfile.");
3061
- const localVersion = (await setupProcess(declared ? "npx" : name2, declared ? ["--yes", "--package", declared, name2, "--version"] : ["--version"], { cwd: lockfileRoot })).trim();
3062
- if (!(name2 === "npm" ? stable(localVersion, 10) : stable(localVersion, 9) || stable(localVersion, 10)))
3063
- fail("unsupported_package_manager_version", "Use npm 10 or pnpm 9/10; other versions are outside the initial setup support range.");
3064
- if (declared && declared !== `${name2}@${localVersion}`)
3065
- fail("package_manager_conflict", "The actual local package-manager version differs from the project's exact packageManager declaration. Select the declared tool without rewriting the lockfile.");
3066
- const format = npmLock ? String(npmLock.lockfileVersion) : /^lockfileVersion:\s*['"]?([\d.]+)/mu.exec(lockText)?.[1];
3067
- if (name2 === "npm" && format !== "3" || name2 === "pnpm" && format !== "9.0" && format !== "9")
3068
- fail("lockfile_format_conflict", "The canonical lockfile format does not match npm 10 or pnpm 9/10.");
3069
- const sourceConflicts = [];
3070
- for (const file of ["next.config.js", "next.config.mjs", "next.config.ts"]) {
3071
- if (!await exists(join7(projectDirectory, file)))
3072
- continue;
3073
- const source = await readFile8(join7(projectDirectory, file), "utf8");
3074
- if (/output\s*:\s*['"]export['"]/u.test(source))
3075
- sourceConflicts.push("static_export");
3076
- if (/\bbasePath\s*:/u.test(source))
3077
- sourceConflicts.push("base_path");
3078
- if (/\bloaderFile\s*:|\bloader\s*:\s*['"](?:custom|imgix|cloudinary|akamai)['"]/u.test(source))
3079
- sourceConflicts.push(`inspect_image_loader:${file}`);
3080
- }
3081
- if (sourceConflicts.some((conflict) => conflict === "static_export" || conflict === "base_path"))
3082
- fail("unsupported_server_configuration", "Resolve static export/basePath configuration explicitly; Siteplane requires its server-side admin and revalidation handlers.");
3083
- for (const name3 of [
3084
- "middleware.ts",
3085
- "middleware.js",
3086
- "proxy.ts",
3087
- "proxy.js",
3088
- "src/middleware.ts",
3089
- "src/middleware.js",
3090
- "src/proxy.ts",
3091
- "src/proxy.js"
3092
- ]) {
3093
- if (await exists(join7(projectDirectory, name3))) {
3094
- sourceConflicts.push(`inspect_routing:${name3}`);
3095
- if (await readlink(join7(projectDirectory, name3)).catch(() => null))
3096
- continue;
3097
- const policySource = await readFile8(join7(projectDirectory, name3), "utf8");
3098
- if (/Content-Security-Policy|img-src|default-src/iu.test(policySource))
3099
- sourceConflicts.push(`inspect_image_csp:${name3}`);
3100
- }
3101
- }
3102
- async function inspectSource(directory) {
3103
- for (const entry of await readdir(directory, { withFileTypes: true })) {
3104
- if (entry.isSymbolicLink() || ["node_modules", ".git", ".next", ".siteplane", ".vercel"].includes(entry.name))
3105
- continue;
3106
- const path = join7(directory, entry.name);
3107
- if (entry.isDirectory()) {
3108
- await inspectSource(path);
3109
- continue;
3110
- }
3111
- if (!/\.[cm]?[jt]sx?$/u.test(entry.name))
3112
- continue;
3113
- const source = await readFile8(path, "utf8");
3114
- if (/Content-Security-Policy|img-src|default-src/iu.test(source))
3115
- sourceConflicts.push(`inspect_image_csp:${relative2(projectDirectory, path)}`);
3116
- if (/from\s*["']next\/image["']/u.test(source))
3117
- sourceConflicts.push(`inspect_image_policy:${relative2(projectDirectory, path)}`);
3118
- if (/\b(?:Cookiebot|OneTrust|cookieyes|consentManager|cookieConsent)\b/iu.test(source))
3119
- sourceConflicts.push(`inspect_existing_consent:${relative2(projectDirectory, path)}`);
3120
- if (/from\s*["']next\/image["']/u.test(source) && semver.lt(nextVersion, "16.3.3"))
3121
- fail("next_security_advisory", `Next.js ${nextVersion} uses image optimization affected by the August 2026 AVIF advisory. Review https://nextjs.org/blog/august-2026-security-release and explicitly update the affected dependency before setup; no framework upgrade was performed.`);
3122
- if (/["']use server["']/u.test(source) && semver.lt(nextVersion, "16.2.11"))
3123
- fail("next_security_advisory", `Next.js ${nextVersion} contains Server Actions affected by the July 2026 advisory. Review https://nextjs.org/blog/july-2026-security-release and explicitly update the affected dependency before setup.`);
3124
- }
3125
- }
3126
- await inspectSource(join7(projectDirectory, apps[0]));
3127
- const gitRead = async (args) => setupProcess("git", args, { cwd: projectDirectory }).then((value) => value.trim(), () => null);
3128
- return {
3129
- projectDirectory,
3130
- repositoryRoot,
3131
- lockfileRoot,
3132
- appDirectory: apps[0],
3133
- nextVersion,
3134
- reactVersion,
3135
- nodeVersion: process.versions.node,
3136
- packageManager: { name: name2, version: localVersion, declared },
3137
- lockfile: {
3138
- path: relative2(repositoryRoot, join7(lockfileRoot, lockName)),
3139
- format,
3140
- sha256: createHash2("sha256").update(lockText).digest("hex")
3141
- },
3142
- git: {
3143
- branch: await gitRead(["branch", "--show-current"]),
3144
- revision: await gitRead(["rev-parse", "HEAD"]),
3145
- remote: safeGitRemote(await gitRead(["remote", "get-url", "origin"])),
3146
- changes: (await gitRead(["status", "--porcelain=v1", "--untracked-files=all"]))?.split("\n").filter(Boolean) ?? []
3147
- },
3148
- sourceConflicts
3149
- };
3150
- }
3151
- async function setupPreflightCommand(input) {
3152
- let local;
3153
- try {
3154
- local = await inspectSetupLocalProject(input.projectDir);
3155
- await assertLocalCredentialsPathSafe(input.projectDir);
3156
- let linkDirectory = local.projectDirectory;
3157
- while (!await exists(join7(linkDirectory, ".vercel/project.json")) && linkDirectory !== local.repositoryRoot && dirname7(linkDirectory) !== linkDirectory)
3158
- linkDirectory = dirname7(linkDirectory);
3159
- if (!await exists(join7(linkDirectory, ".vercel/project.json")))
3160
- fail("vercel_project_not_linked", "Link this application to its intended Vercel project before setup; Siteplane will not guess a target.");
3161
- const linked = z34.object({
3162
- projectId: z34.string().regex(/^prj_[A-Za-z0-9]+$/u),
3163
- orgId: z34.string().regex(/^(?:team|user)_[A-Za-z0-9]+$/u)
3164
- }).parse(JSON.parse(await readFile8(join7(linkDirectory, ".vercel/project.json"), "utf8")));
3165
- const project = vercelProjectSchema.parse(await setupVercelApi(linkDirectory, `/v9/projects/${linked.projectId}?teamId=${linked.orgId}`));
3166
- if (project.id !== linked.projectId || project.accountId !== linked.orgId)
3167
- fail("vercel_identity_conflict", "The provider project does not match the locally linked project and team.");
3168
- const expectedRoot = relative2(local.repositoryRoot, local.projectDirectory).split(sep).join("/");
3169
- if ((project.rootDirectory ?? "") !== expectedRoot)
3170
- fail("vercel_root_conflict", "Vercel Root Directory and the selected local app must identify the same application.");
3171
- if (project.nodeVersion !== "22.x" || project.framework !== "nextjs")
3172
- fail("vercel_framework_conflict", "The bound Vercel project must use Next.js with Node.js 22 before setup.");
3173
- if (project.link && project.link.productionBranch !== local.git.branch)
3174
- fail("vercel_production_branch_conflict", "The local branch differs from the bound Vercel Production branch.");
3175
- if (project.link?.repo && project.link.org && !local.git.remote?.replace(/\.git$/u, "").endsWith(`${project.link.org}/${project.link.repo}`))
3176
- fail("vercel_git_conflict", "The local origin repository differs from the Vercel Git connection.");
3177
- const env = z34.object({
3178
- envs: z34.array(z34.object({
3179
- key: z34.string(),
3180
- value: z34.string().optional(),
3181
- target: z34.array(z34.string()).optional()
3182
- }))
3183
- }).parse(await setupVercelApi(linkDirectory, `/v10/projects/${linked.projectId}/env?teamId=${linked.orgId}`));
3184
- const corepack = env.envs.some((item) => item.key === "ENABLE_EXPERIMENTAL_COREPACK" && item.value === "1" && item.target?.includes("production"));
3185
- const install = project.installCommand ?? null;
3186
- const selected = corepack ? "corepack" : install ? "install_override" : "automatic";
3187
- if (local.packageManager.declared && selected === "automatic")
3188
- fail("vercel_package_manager_pin_unconfirmed", "This project declares an exact packageManager but Vercel automatic selection does not bind that version. Enable its supported Corepack selection or set an exact install AND build override in the existing project, then rerun preflight. No package, lockfile or provider setting was changed.");
3189
- if (install && /\b(?:yarn|bun)\b/u.test(install))
3190
- fail("vercel_package_manager_conflict", "The Vercel install override selects an unsupported package manager.");
3191
- const overridePin = install ? /\b(npm|pnpm)@(\d+\.\d+\.\d+)\b/u.exec(install) : null;
3192
- if (overridePin && overridePin[1] !== local.packageManager.name)
3193
- fail("vercel_package_manager_conflict", "The provider override selects a different package manager than the canonical lockfile.");
3194
- const overrideFamily = install ? /(?:^|[;&|]\s*)(npm|pnpm)\s+(?:ci|install)\b/u.exec(install)?.[1] : null;
3195
- if (overrideFamily && overrideFamily !== local.packageManager.name)
3196
- fail("vercel_package_manager_conflict", "The provider install command conflicts with the canonical lockfile.");
3197
- if (overridePin && local.packageManager.declared && `${overridePin[1]}@${overridePin[2]}` !== local.packageManager.declared)
3198
- fail("vercel_package_manager_conflict", "The Vercel install override conflicts with the exact packageManager declaration.");
3199
- const buildRunners = (project.buildCommand ?? "").matchAll(/(?:^|[;&|\n])\s*(?:(?:corepack|npx(?:\s+(?:--yes|-y))?)\s+)?(npm|pnpm|yarn|bun)(?:@(\d+\.\d+\.\d+))?\s+(?:run\s+)?build\b/gu);
3200
- for (const [, family, version2] of buildRunners) {
3201
- if (family !== local.packageManager.name || version2 && local.packageManager.declared && `${family}@${version2}` !== local.packageManager.declared)
3202
- fail("vercel_package_manager_conflict", "The explicit Vercel build command conflicts with the selected package manager or its declared version. Align the existing build override and rerun preflight; no setup writes were performed.");
3203
- }
3204
- return {
3205
- status: "ready",
3206
- local,
3207
- provider: {
3208
- projectId: project.id,
3209
- teamId: project.accountId,
3210
- name: project.name,
3211
- rootDirectory: expectedRoot,
3212
- nodeVersion: project.nodeVersion,
3213
- git: project.link,
3214
- installCommand: install,
3215
- buildCommand: project.buildCommand ?? null,
3216
- packageManagerSelection: selected,
3217
- declaredPackageManager: local.packageManager.declared,
3218
- observedPackageManager: null
3219
- }
3220
- };
3221
- } catch (error) {
3222
- return {
3223
- status: "action_required",
3224
- code: error instanceof SetupFailure ? error.code : "invalid_local_project",
3225
- message: error instanceof SetupFailure ? error.message : "The selected project or provider response could not be validated. Check the application manifest and local project access.",
3226
- ...local ? { local } : {}
3227
- };
3228
- }
3229
- }
3230
- function safeGitRemote(value) {
3231
- if (!value)
3232
- return null;
3233
- if (!value.includes("://"))
3234
- return value;
3235
- try {
3236
- const url = new URL(value);
3237
- url.username = "";
3238
- url.password = "";
3239
- url.search = "";
3240
- url.hash = "";
3241
- return url.toString().replace(/\/$/u, "");
3242
- } catch {
3243
- return null;
3244
- }
3245
- }
3246
1891
 
3247
- // ../cli/dist/commands/init.js
3248
- async function initCommand(input) {
3249
- if (!input.setupToken.trim()) {
3250
- throw new Error("A Siteplane setup token is required.");
3251
- }
3252
- if (!await detectNextProject(input.projectDir)) {
3253
- throw new Error("Siteplane init currently supports Next.js projects.");
3254
- }
3255
- await assertLocalCredentialsPathSafe(input.projectDir, {
3256
- ...input.isIgnoredFile ? { isIgnoredFile: input.isIgnoredFile } : {},
3257
- ...input.isTrackedFile ? { isTrackedFile: input.isTrackedFile } : {}
3258
- });
3259
- const preflight = await (input.preflight ?? setupPreflightCommand)({
3260
- projectDir: input.projectDir
3261
- });
3262
- if (preflight.status !== "ready")
3263
- throw new Error(`${preflight.code}: ${preflight.message}`);
3264
- const bootstrap = await bootstrapProjectConnection(input);
3265
- const paths = bootstrap.credentialPurpose === "site_setup" ? await persistSiteSetupBootstrap(input, bootstrap, relative3(preflight.local.lockfileRoot, preflight.local.projectDirectory) || ".") : await persistFeatureBootstrap(input, bootstrap);
3266
- await acknowledgeBootstrapResponse(input);
3267
- return {
3268
- ...paths,
3269
- nextSteps: [
3270
- "Run npx siteplane setup context and read the returned task.",
3271
- "Before source changes, briefly tell the user what Siteplane requested and what you will do.",
3272
- "Follow the returned steps through setup prepare and setup deploy --wait, which performs setup verify; stop only at ready_for_review or action_required."
3273
- ]
3274
- };
3275
- }
3276
- var siteSetupBootstrapDataSchema = z35.object({
3277
- credentialPurpose: z35.literal("site_setup"),
3278
- apiBaseUrl: z35.string().url(),
3279
- siteId: z35.string().uuid(),
3280
- publicSiteKeyId: z35.string().uuid(),
3281
- publicSiteKey: z35.string().trim().min(1),
3282
- accessToken: z35.string().trim().min(1),
3283
- siteRevalidationSecret: z35.string().regex(/^[A-Za-z0-9_-]{43}$/u),
3284
- runId: z35.string().uuid(),
3285
- packages: siteSetupPackagesSchema
3286
- }).strict();
3287
- var featureBootstrapDataSchema = z35.object({
3288
- credentialPurpose: z35.enum(["analytics", "booking"]),
3289
- apiBaseUrl: z35.string().url(),
3290
- siteId: z35.string().uuid(),
3291
- accessToken: z35.string().trim().min(1)
1892
+ // ../cli/dist/config/project-config.js
1893
+ import { readFile as readFile4 } from "fs/promises";
1894
+ import { join as join5 } from "path";
1895
+ import { z as z28 } from "zod";
1896
+ var packageVersionSchema = z28.string().regex(/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/u);
1897
+ var projectPackagesSchema = z28.object({
1898
+ siteplane: packageVersionSchema,
1899
+ runtimeNext: packageVersionSchema,
1900
+ analytics: packageVersionSchema.optional()
3292
1901
  }).strict();
3293
- var bootstrapResponseSchema = z35.object({
3294
- ok: z35.literal(true),
3295
- data: z35.discriminatedUnion("credentialPurpose", [
3296
- siteSetupBootstrapDataSchema,
3297
- featureBootstrapDataSchema
3298
- ])
1902
+ var siteplaneProjectConfigSchema = z28.object({
1903
+ version: z28.literal(2),
1904
+ apiBaseUrl: z28.string().url(),
1905
+ siteId: z28.string().uuid(),
1906
+ publicSiteKeyId: z28.string().uuid(),
1907
+ publicSiteKey: z28.string().trim().min(1),
1908
+ runId: z28.string().uuid(),
1909
+ appDirectory: z28.string().min(1),
1910
+ taskContractVersion: z28.literal("siteplane.setup-task.v2"),
1911
+ adminProtocolVersion: z28.literal(2),
1912
+ packages: projectPackagesSchema,
1913
+ fieldContractHash: z28.string().regex(/^sha256:[0-9a-f]{64}$/iu).optional()
3299
1914
  }).strict();
3300
- async function bootstrapProjectConnection(input) {
3301
- const fetcher = input.fetcher ?? fetch;
3302
- const existing = await access4(join8(input.projectDir, "siteplane.config.json")).then(() => readProjectConfig(input.projectDir), () => null);
3303
- const response = await fetcher(`${input.apiBaseUrl.replace(/\/$/, "")}/api/cli/setup/bootstrap`, {
3304
- method: "POST",
3305
- signal: AbortSignal.timeout(2e4),
3306
- headers: createBootstrapHeaders(input),
3307
- body: JSON.stringify({
3308
- action: "bootstrap",
3309
- ...existing ? { expectedSiteId: existing.siteId, expectedRunId: existing.runId } : {},
3310
- agentClient: input.agentClient ?? "codex"
3311
- })
3312
- });
3313
- const payload = await response.json();
3314
- const parsed = bootstrapResponseSchema.safeParse(payload);
3315
- if (!response.ok || !parsed.success) {
3316
- throw new Error(readErrorMessage(payload) ?? "Siteplane init failed.");
3317
- }
3318
- return parsed.data.data;
3319
- }
3320
- async function acknowledgeBootstrapResponse(input) {
3321
- const fetcher = input.fetcher ?? fetch;
3322
- const response = await fetcher(`${input.apiBaseUrl.replace(/\/$/, "")}/api/cli/setup/bootstrap`, {
3323
- method: "POST",
3324
- signal: AbortSignal.timeout(2e4),
3325
- headers: createBootstrapHeaders(input),
3326
- body: JSON.stringify({ action: "acknowledge" })
3327
- });
3328
- if (!response.ok) {
3329
- throw new Error("Siteplane setup acknowledgement failed.");
3330
- }
3331
- }
3332
- async function persistSiteSetupBootstrap(input, bootstrap, appDirectory, installation) {
3333
- const previous = await access4(join8(input.projectDir, "siteplane.config.json")).then(() => readProjectConfig(input.projectDir), () => null);
3334
- if (previous && (previous.siteId !== bootstrap.siteId || previous.runId !== bootstrap.runId || previous.publicSiteKeyId !== bootstrap.publicSiteKeyId || previous.publicSiteKey !== bootstrap.publicSiteKey))
3335
- throw new Error("The grant does not match this local Siteplane run. Preserve this directory and choose the correct owner connection.");
3336
- const previousCredentials = previous ? await access4(join8(input.projectDir, ".siteplane/credentials.json")).then(() => readLocalSetupCredentials(input.projectDir), () => null) : null;
3337
- const credentialsPath = await writeLocalCredentials(input.projectDir, {
3338
- ...previousCredentials && "adminSession" in previousCredentials && previousCredentials.adminSession ? { adminSession: previousCredentials.adminSession } : {},
3339
- ...previousCredentials && "claimReceipt" in previousCredentials && previousCredentials.claimReceipt ? { claimReceipt: previousCredentials.claimReceipt } : {},
3340
- accessToken: bootstrap.accessToken,
3341
- siteRevalidationSecret: bootstrap.siteRevalidationSecret,
3342
- ...installation ?? previousCredentials?.installation ? { installation: installation ?? previousCredentials?.installation } : {}
3343
- }, {
3344
- ...input.isIgnoredFile ? { isIgnoredFile: input.isIgnoredFile } : {},
3345
- ...input.isTrackedFile ? { isTrackedFile: input.isTrackedFile } : {}
3346
- });
3347
- const configPath = await writeProjectConfig(input.projectDir, {
3348
- ...previous ?? {},
3349
- version: 2,
3350
- appDirectory,
3351
- runId: bootstrap.runId,
3352
- packages: bootstrap.packages,
3353
- taskContractVersion: "siteplane.setup-task.v2",
3354
- adminProtocolVersion: 2,
3355
- apiBaseUrl: bootstrap.apiBaseUrl,
3356
- siteId: bootstrap.siteId,
3357
- publicSiteKeyId: bootstrap.publicSiteKeyId,
3358
- publicSiteKey: bootstrap.publicSiteKey
3359
- });
3360
- const [credentials, config] = await Promise.all([
3361
- readLocalCredentials(input.projectDir),
3362
- readProjectConfig(input.projectDir)
3363
- ]);
3364
- if (credentials.accessToken !== bootstrap.accessToken || credentials.siteRevalidationSecret !== bootstrap.siteRevalidationSecret || config.runId !== bootstrap.runId || config.packages.siteplane !== bootstrap.packages.siteplane || config.packages.runtimeNext !== bootstrap.packages.runtimeNext || config.packages.analytics !== bootstrap.packages.analytics || config.apiBaseUrl !== bootstrap.apiBaseUrl || config.siteId !== bootstrap.siteId || config.publicSiteKeyId !== bootstrap.publicSiteKeyId || config.publicSiteKey !== bootstrap.publicSiteKey) {
3365
- throw new Error("Siteplane setup files could not be verified.");
3366
- }
3367
- return { configPath, credentialsPath };
3368
- }
3369
- async function persistFeatureBootstrap(input, bootstrap) {
3370
- const [config, existingCredentials] = await Promise.all([
3371
- readProjectConfig(input.projectDir),
3372
- readLocalCredentials(input.projectDir)
3373
- ]);
3374
- if (config.siteId !== bootstrap.siteId) {
3375
- throw new Error("The setup token belongs to a different Siteplane site.");
3376
- }
3377
- const credentialsPath = await writeLocalCredentials(input.projectDir, {
3378
- ...existingCredentials,
3379
- accessToken: bootstrap.accessToken
3380
- }, {
3381
- ...input.isIgnoredFile ? { isIgnoredFile: input.isIgnoredFile } : {},
3382
- ...input.isTrackedFile ? { isTrackedFile: input.isTrackedFile } : {}
3383
- });
3384
- const persistedCredentials = await readLocalCredentials(input.projectDir);
3385
- if (persistedCredentials.accessToken !== bootstrap.accessToken || persistedCredentials.siteRevalidationSecret !== existingCredentials.siteRevalidationSecret) {
3386
- throw new Error("Siteplane credentials could not be verified.");
3387
- }
3388
- return {
3389
- configPath: join8(input.projectDir, "siteplane.config.json"),
3390
- credentialsPath
3391
- };
3392
- }
3393
- function createBootstrapHeaders(input) {
3394
- return new Headers({
3395
- authorization: `Bearer ${input.setupToken}`,
3396
- "content-type": "application/json",
3397
- ...input.vercelAutomationBypassSecret?.trim() ? {
3398
- "x-vercel-protection-bypass": input.vercelAutomationBypassSecret.trim()
3399
- } : {}
3400
- });
3401
- }
3402
- function readErrorMessage(payload) {
3403
- if (payload && typeof payload === "object" && "error" in payload && payload.error && typeof payload.error === "object" && "message" in payload.error && typeof payload.error.message === "string") {
3404
- const code = "code" in payload.error && typeof payload.error.code === "string" ? payload.error.code : null;
3405
- return code ? `${code}: ${payload.error.message}` : payload.error.message;
3406
- }
3407
- return null;
3408
- }
3409
-
3410
- // ../cli/dist/commands/scan.js
3411
- import { readdir as readdir2 } from "fs/promises";
3412
- import { extname, join as join9 } from "path";
3413
- var defaultScanRoots = ["app", "src", "pages", "components", "lib"];
3414
- var excludedDirectories = /* @__PURE__ */ new Set([
3415
- ".git",
3416
- ".next",
3417
- ".turbo",
3418
- ".vercel",
3419
- "build",
3420
- "coverage",
3421
- "dist",
3422
- "node_modules"
3423
- ]);
3424
- var sourceExtensions = /* @__PURE__ */ new Set([".js", ".jsx", ".ts", ".tsx"]);
3425
- async function resolveScanFilePaths(filePaths, options = {}) {
3426
- if (filePaths.length > 0) {
3427
- return filePaths;
3428
- }
3429
- const projectDir = options.projectDir ?? process.cwd();
3430
- const discovered = await Promise.all(defaultScanRoots.map((root) => collectSourceFiles(join9(projectDir, root))));
3431
- return [...new Set(discovered.flat())].sort();
3432
- }
3433
- async function collectSourceFiles(directory) {
3434
- const entries = await readdir2(directory, { withFileTypes: true }).catch(() => []);
3435
- const files = [];
3436
- for (const entry of entries) {
3437
- const entryPath = join9(directory, entry.name);
3438
- if (entry.isDirectory()) {
3439
- if (!excludedDirectories.has(entry.name)) {
3440
- files.push(...await collectSourceFiles(entryPath));
3441
- }
3442
- continue;
3443
- }
3444
- if (entry.isFile() && sourceExtensions.has(extname(entry.name))) {
3445
- files.push(entryPath);
3446
- }
3447
- }
3448
- return files;
3449
- }
3450
-
3451
- // ../cli/dist/commands/site-setup.js
3452
- import { execFile as execFile2 } from "child_process";
3453
- import { readFile as readFile9 } from "fs/promises";
3454
- import { promisify as promisify2 } from "util";
3455
- import { z as z36 } from "zod";
3456
1915
 
3457
1916
  // ../cli/dist/scan/next-source-scan.js
3458
- import ts3 from "typescript";
3459
- import { isAbsolute, relative as relative4 } from "path";
1917
+ import ts2 from "typescript";
1918
+ import { isAbsolute, relative } from "path";
3460
1919
  var legacyEditableComponentPrefix = "Editable";
3461
- var editableComponentNames = new Set(["Image", "Text", "LongText", "Link"].map((name2) => `${legacyEditableComponentPrefix}${name2}`));
3462
-
3463
- // ../cli/dist/commands/site-setup.js
3464
- var execFileAsync2 = promisify2(execFile2);
3465
- var safeErrorSchema = z36.object({
3466
- code: z36.string().trim().min(1),
3467
- message: z36.string().trim().min(1)
3468
- }).passthrough();
3469
- var errorResponseSchema2 = z36.object({ ok: z36.literal(false), error: safeErrorSchema }).passthrough();
3470
- var contextDataSchema = z36.object({
3471
- task: siteSetupTaskSchema.refine((task) => task.run !== null)
3472
- }).strict();
3473
- var contextResponseSchema = z36.object({ ok: z36.literal(true), data: contextDataSchema }).strict();
3474
- var applyDataSchema = z36.object({
3475
- status: z36.enum(["applied", "ready_for_review"]),
3476
- runId: z36.string().uuid().optional(),
3477
- contractVersionId: z36.string().uuid().optional(),
3478
- fieldContractHash: z36.string().regex(/^sha256:[0-9a-f]{64}$/u),
3479
- editorDefinitionHash: z36.string().regex(/^sha256:[0-9a-f]{64}$/u).optional(),
3480
- fieldCount: z36.number().int().nonnegative().optional(),
3481
- routeCount: z36.number().int().nonnegative().optional()
3482
- }).strict();
3483
- var applyResponseSchema = z36.object({ ok: z36.literal(true), data: applyDataSchema }).strict();
3484
- var verifyDataSchema = z36.object({
3485
- status: z36.literal("ready_for_review"),
3486
- runId: z36.string().uuid().optional(),
3487
- deploymentOrigin: z36.string().url().optional(),
3488
- deploymentRevision: z36.string().optional()
3489
- }).strict();
3490
- var verifyResponseSchema = z36.object({ ok: z36.literal(true), data: verifyDataSchema }).strict();
3491
- async function siteSetupContextCommand(input) {
3492
- const response = await postSiteSetup(input, "context", {});
3493
- const parsed = contextResponseSchema.safeParse(response.payload);
3494
- if (response.ok && parsed.success) {
3495
- return { status: "ok", ...parsed.data.data };
3496
- }
3497
- return actionRequired(response.payload, "Siteplane setup context is unavailable.");
3498
- }
3499
- async function siteSetupVerifyCommand(input) {
3500
- const resolveSourceFiles = input.resolveSourceFiles ?? resolveScanFilePaths;
3501
- const readSourceFile = input.readSourceFile ?? ((path) => readFile9(path, "utf8"));
3502
- const paths = await resolveSourceFiles([], { projectDir: input.projectDir });
3503
- const sources = await Promise.all(paths.map(readSourceFile));
3504
- if (!sources.some(hasMountedFieldRuntimeBridge)) {
3505
- return {
3506
- status: "action_required",
3507
- code: "missing_field_runtime_bridge",
3508
- message: "Mount FieldRuntimeBridge from @siteplane/runtime-next/client before deployment verification."
3509
- };
3510
- }
3511
- const deploymentRevision = await (input.readRevision ?? readGitRevision)(input.projectDir);
3512
- const response = await postSiteSetup(input, "verify", {
3513
- deploymentUrl: input.deploymentUrl,
3514
- deploymentRevision,
3515
- ...input.wait ? { wait: true } : {}
3516
- });
3517
- const parsed = verifyResponseSchema.safeParse(response.payload);
3518
- if (response.ok && parsed.success) {
3519
- return parsed.data.data;
3520
- }
3521
- return actionRequired(response.payload, "Siteplane deployment verification failed.");
3522
- }
3523
- function hasMountedFieldRuntimeBridge(source) {
3524
- return /from\s+["']@siteplane\/runtime-next(?:\/client)?["']/u.test(source) && /<FieldRuntimeBridge(?:\s|\/|>)/u.test(source);
3525
- }
3526
- async function postSiteSetup(input, operation, body) {
3527
- const [config, credentials] = await Promise.all([
3528
- readProjectConfig(input.projectDir),
3529
- readLocalCredentials(input.projectDir)
3530
- ]);
3531
- try {
3532
- const response = await (input.fetcher ?? fetch)(`${config.apiBaseUrl.replace(/\/$/u, "")}/api/cli/setup/${operation}`, {
3533
- method: "POST",
3534
- signal: AbortSignal.timeout(Math.max(1, Math.min(2e4, (input.deadline ?? Date.now() + 2e4) - Date.now()))),
3535
- headers: {
3536
- authorization: `Bearer ${credentials.accessToken}`,
3537
- "content-type": "application/json",
3538
- ...input.vercelAutomationBypassSecret?.trim() ? {
3539
- "x-vercel-protection-bypass": input.vercelAutomationBypassSecret.trim()
3540
- } : {}
3541
- },
3542
- body: JSON.stringify(body)
3543
- });
3544
- const payload = await response.json().catch(() => null);
3545
- return { ok: response.ok, payload };
3546
- } catch {
3547
- return {
3548
- ok: false,
3549
- payload: {
3550
- ok: false,
3551
- error: {
3552
- code: "site_setup.transport_failed",
3553
- message: "The setup request was not acknowledged. Reload the existing task before retrying; no credential values are included."
3554
- }
3555
- }
3556
- };
3557
- }
3558
- }
3559
- function actionRequired(payload, fallbackMessage) {
3560
- const parsed = errorResponseSchema2.safeParse(payload);
3561
- return parsed.success ? {
3562
- status: "action_required",
3563
- code: parsed.data.error.code,
3564
- message: parsed.data.error.message
3565
- } : {
3566
- status: "action_required",
3567
- code: "invalid_server_response",
3568
- message: fallbackMessage
3569
- };
3570
- }
3571
- async function readGitRevision(projectDir) {
3572
- const { stdout } = await execFileAsync2("git", ["rev-parse", "HEAD"], {
3573
- cwd: projectDir,
3574
- encoding: "utf8"
3575
- });
3576
- const revision = stdout.trim();
3577
- if (!revision) {
3578
- throw new Error("A committed Git revision is required before setup verify.");
3579
- }
3580
- return revision;
3581
- }
3582
-
3583
- // ../cli/dist/commands/setup-start.js
3584
- import { randomBytes, randomUUID as randomUUID4 } from "crypto";
3585
- import { access as access5 } from "fs/promises";
3586
- import { join as join10, relative as relative5 } from "path";
3587
- import { z as z37 } from "zod";
3588
- var bootstrapResponseSchema2 = z37.object({
3589
- ok: z37.literal(true),
3590
- data: siteSetupBootstrapDataSchema
3591
- }).strict();
3592
-
3593
- // ../cli/dist/commands/setup-review.js
3594
- import { z as z38 } from "zod";
3595
- var responseSchema2 = z38.object({
3596
- ok: z38.literal(true),
3597
- data: z38.object({
3598
- reviewUrl: z38.string().url(),
3599
- expiresAt: z38.string().datetime({ offset: true })
3600
- }).strict()
3601
- }).strict();
3602
-
3603
- // ../cli/dist/commands/setup-prepare.js
3604
- import { access as access6, lstat as lstat2, mkdir as mkdir6, open as open3, readFile as readFile10, rename as rename3, rm as rm3 } from "fs/promises";
3605
- import { randomUUID as randomUUID5 } from "crypto";
3606
- import { dirname as dirname8, join as join11, relative as relative6, sep as sep2 } from "path";
3607
- import ts4 from "typescript";
3608
-
3609
- // ../cli/dist/commands/setup-lock.js
3610
- import { randomUUID as randomUUID6 } from "crypto";
3611
- import { lstat as lstat3, mkdir as mkdir7, open as open4, readFile as readFile11, rm as rm4, rmdir } from "fs/promises";
3612
- import { resolve as resolve2 } from "path";
3613
- import { z as z39 } from "zod";
3614
- var ownerSchema = z39.object({ pid: z39.number().int().positive(), nonce: z39.string().uuid() }).strict();
3615
-
3616
- // ../cli/dist/config/build-provenance.js
3617
- import { createHash as createHash3 } from "crypto";
3618
- import { execFile as execFile3 } from "child_process";
3619
- import { lstat as lstat4, readFile as readFile12, writeFile as writeFile5, mkdir as mkdir8 } from "fs/promises";
3620
- import { dirname as dirname9, isAbsolute as isAbsolute2, join as join12, relative as relative7, resolve as resolve3, sep as sep3 } from "path";
3621
- import { isDeepStrictEqual, promisify as promisify3 } from "util";
3622
- import { z as z40 } from "zod";
3623
- var execute = promisify3(execFile3);
3624
- var name = ".siteplane/build-source.json";
3625
- var oid = z40.string().regex(/^[0-9a-f]{40}$/u);
3626
- var entrySchema = z40.object({
3627
- path: z40.string().min(1).max(4096),
3628
- mode: z40.enum(["100644", "100755", "120000"]),
3629
- oid
3630
- }).strict();
3631
- var schema = z40.object({
3632
- version: z40.literal(2),
3633
- revision: oid,
3634
- commit: z40.string().min(1).max(1048576),
3635
- entries: z40.array(entrySchema).min(1).max(1e5),
3636
- providerConfigurations: z40.array(z40.object({
3637
- path: z40.string().max(4096).regex(/(?:^|\/)vercel\.json$/u),
3638
- source: z40.string().max(1048576)
3639
- }).strict()).max(1e3)
3640
- }).strict();
3641
- async function writeBuildProvenance(checkout, revision) {
3642
- const commit = (await execute("git", ["cat-file", "commit", revision], {
3643
- cwd: checkout,
3644
- maxBuffer: 1048576
3645
- })).stdout;
3646
- const tree = (await execute("git", ["ls-tree", "-rz", "--full-tree", revision], {
3647
- cwd: checkout,
3648
- maxBuffer: 16777216
3649
- })).stdout;
3650
- const entries = tree.split("\0").filter(Boolean).map((line) => {
3651
- const match = /^(100644|100755|120000) blob ([0-9a-f]{40})\t([\s\S]+)$/u.exec(line);
3652
- if (!match)
3653
- throw new Error("Git submodules or unsupported tracked objects need an explicit deployment configuration.");
3654
- return { path: match[3], mode: match[1], oid: match[2] };
3655
- });
3656
- for (const entry of entries) {
3657
- if (entry.mode !== "120000")
3658
- continue;
3659
- const { readlink: readlink2 } = await import("fs/promises");
3660
- const path = join12(checkout, entry.path);
3661
- const target2 = resolve3(dirname9(path), await readlink2(path));
3662
- const bound = relative7(checkout, target2);
3663
- if (bound.startsWith("..") || isAbsolute2(bound))
3664
- throw new Error("A tracked symbolic link escapes the committed upload; resolve that source boundary before deployment.");
3665
- }
3666
- const providerConfigurations = await Promise.all(entries.filter((entry) => /(?:^|\/)vercel\.json$/u.test(entry.path)).map(async (entry) => ({
3667
- path: entry.path,
3668
- source: await readFile12(join12(checkout, entry.path), "utf8")
3669
- })));
3670
- const record = schema.parse({
3671
- version: 2,
3672
- revision,
3673
- commit,
3674
- entries,
3675
- providerConfigurations
3676
- });
3677
- const target = join12(checkout, name);
3678
- await mkdir8(dirname9(target), { recursive: true, mode: 448 });
3679
- await writeFile5(target, JSON.stringify(record), { flag: "wx", mode: 384 });
3680
- }
3681
-
3682
- // ../cli/dist/commands/setup-deploy.js
3683
- import { createHash as createHash4, randomBytes as randomBytes2, randomUUID as randomUUID7 } from "crypto";
3684
- import { access as access7, mkdir as mkdir9, mkdtemp, rm as rm5, writeFile as writeFile6 } from "fs/promises";
3685
- import { tmpdir } from "os";
3686
- import { join as join13 } from "path";
3687
- import { z as z41 } from "zod";
3688
- var envSchema = z41.object({
3689
- id: z41.string(),
3690
- key: z41.string(),
3691
- target: z41.array(z41.string()),
3692
- type: z41.string(),
3693
- comment: z41.string().optional(),
3694
- updatedAt: z41.number().optional()
3695
- });
3696
- var deploymentSchema = z41.object({
3697
- id: z41.string(),
3698
- projectId: z41.string(),
3699
- ownerId: z41.string().optional(),
3700
- target: z41.string().nullable(),
3701
- readyState: z41.string(),
3702
- createdAt: z41.number(),
3703
- url: z41.string(),
3704
- meta: z41.record(z41.string(), z41.unknown()).optional(),
3705
- gitSource: z41.object({ sha: z41.string().optional() }).nullable().optional()
3706
- });
3707
- var buildProofSchema = z41.object({
3708
- node: z41.string(),
3709
- packageManager: z41.enum(["npm", "pnpm"]),
3710
- packageManagerVersion: z41.string(),
3711
- lockfileHash: z41.string(),
3712
- revision: z41.string(),
3713
- fieldContractHash: z41.string(),
3714
- siteplane: z41.string(),
3715
- runtimeNext: z41.string(),
3716
- analytics: z41.string().optional(),
3717
- next: z41.string(),
3718
- react: z41.string()
3719
- }).strict();
3720
- var defaults = {
3721
- preflight: setupPreflightCommand,
3722
- context: siteSetupContextCommand,
3723
- api: setupVercelApi,
3724
- process: setupProcess,
3725
- verify: siteSetupVerifyCommand,
3726
- post: postSiteSetup,
3727
- writeBuildProvenance,
3728
- analyticsPublicKey: analyticsPublicKeyCommand,
3729
- now: Date.now,
3730
- pause: (milliseconds) => new Promise((resolve4) => setTimeout(resolve4, milliseconds))
3731
- };
3732
-
3733
- // ../cli/dist/commands/setup-claim.js
3734
- import { z as z42 } from "zod";
1920
+ var editableComponentNames = new Set(["Image", "Text", "LongText", "Link"].map((name) => `${legacyEditableComponentPrefix}${name}`));
3735
1921
  export {
3736
1922
  bookingCheckCommand,
3737
1923
  bookingInitCommand,
3738
1924
  bookingSyncCommand,
3739
- bookingTestCommand,
3740
- exportCommand,
3741
- initCommand
1925
+ bookingTestCommand
3742
1926
  };