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/next.js CHANGED
@@ -1,19 +1,41 @@
1
1
  // src/next.ts
2
- import { execFile as execFile4 } from "child_process";
3
- import { createHash as createHash5 } from "crypto";
4
- import { access as access8, readFile as readFile13 } from "fs/promises";
5
- import { dirname as dirname10, join as join14, resolve as resolve4 } from "path";
6
- import { promisify as promisify4 } from "util";
2
+ import { execFile } from "child_process";
3
+ import { access as access2, readFile as readFile5 } from "fs/promises";
4
+ import { join as join6, resolve } from "path";
5
+ import { promisify } from "util";
7
6
 
8
- // ../cli/dist/analytics/manifest.js
7
+ // ../cli/dist/booking/manifest.js
9
8
  import { mkdir, readFile, writeFile } from "fs/promises";
10
9
  import { dirname } from "path";
11
10
 
12
11
  // ../shared/dist/actors.js
13
12
  import { z } from "zod";
14
- var ACTOR_TYPES = ["workspace_member", "site_member", "agent", "setup_guest", "system"];
13
+ var ACTOR_TYPES = ["workspace_member", "site_member", "agent", "system"];
15
14
  var actorTypeSchema = z.enum(ACTOR_TYPES);
16
15
 
16
+ // ../shared/dist/agent-connection.js
17
+ import { z as z2 } from "zod";
18
+ var AGENT_CONNECTION_TOKEN_PREFIX = "sp_agent_";
19
+ var deviceAuthorizationResponseSchema = z2.object({
20
+ device_code: z2.string().min(43),
21
+ user_code: z2.string().min(8),
22
+ verification_uri: z2.string().url(),
23
+ verification_uri_complete: z2.string().url(),
24
+ expires_in: z2.number().int().positive(),
25
+ interval: z2.number().int().positive()
26
+ });
27
+ var deviceTokenResponseSchema = z2.object({
28
+ access_token: z2.string().startsWith(AGENT_CONNECTION_TOKEN_PREFIX).min(40),
29
+ token_type: z2.literal("Bearer"),
30
+ scope: z2.string(),
31
+ expires_in: z2.number().int().positive()
32
+ });
33
+ var deviceTokenErrorSchema = z2.object({
34
+ error: z2.string(),
35
+ error_description: z2.string().optional(),
36
+ interval: z2.number().int().positive().optional()
37
+ });
38
+
17
39
  // ../shared/dist/analytics-defaults.js
18
40
  var ANALYTICS_BATCH_LIMITS = {
19
41
  maxEventsPerRequest: 50,
@@ -30,7 +52,7 @@ var ANALYTICS_RETENTION_DEFAULTS = {
30
52
  };
31
53
 
32
54
  // ../shared/dist/analytics-booking.js
33
- import { z as z2 } from "zod";
55
+ import { z as z3 } from "zod";
34
56
  var bookingProviders = ["treatwell", "beautinda", "other"];
35
57
  var bookingAttributionModes = [
36
58
  "outbound_click_and_utm",
@@ -52,16 +74,16 @@ var bookingAttributionConfidences = [
52
74
  "manual_import",
53
75
  "verified_webhook"
54
76
  ];
55
- var bookingProviderSchema = z2.enum(bookingProviders);
56
- var bookingAttributionModeSchema = z2.enum(bookingAttributionModes);
57
- var bookingSignalSourceSchema = z2.enum(bookingSignalSources);
58
- var bookingAttributionConfidenceSchema = z2.enum(bookingAttributionConfidences);
59
- var bookingProviderHintSchema = z2.object({
77
+ var bookingProviderSchema = z3.enum(bookingProviders);
78
+ var bookingAttributionModeSchema = z3.enum(bookingAttributionModes);
79
+ var bookingSignalSourceSchema = z3.enum(bookingSignalSources);
80
+ var bookingAttributionConfidenceSchema = z3.enum(bookingAttributionConfidences);
81
+ var bookingProviderHintSchema = z3.object({
60
82
  bookingProvider: bookingProviderSchema,
61
- bookingUrlHost: z2.string().min(1).max(253),
83
+ bookingUrlHost: z3.string().min(1).max(253),
62
84
  bookingAttributionMode: bookingAttributionModeSchema,
63
- utmContent: z2.string().min(1).max(200).optional(),
64
- successCondition: z2.literal("redirect_status=succeeded").optional()
85
+ utmContent: z3.string().min(1).max(200).optional(),
86
+ successCondition: z3.literal("redirect_status=succeeded").optional()
65
87
  }).superRefine((hint, context) => {
66
88
  if (hint.successCondition !== void 0 && hint.bookingAttributionMode !== "provider_redirect") {
67
89
  context.addIssue({
@@ -73,17 +95,15 @@ var bookingProviderHintSchema = z2.object({
73
95
  });
74
96
 
75
97
  // ../shared/dist/analytics-contract.js
76
- import { z as z3 } from "zod";
77
- var ANALYTICS_CONTRACT_VERSION = "analytics-contract.v1";
78
- var ANALYTICS_CONTRACT_HASH = "sha256:a91bddcc3c5e4196933b0335d03eaf41ff929cb736bdd694fe54d07ab52dada1";
98
+ import { z as z4 } from "zod";
79
99
  var ANALYTICS_IMPORT_SCHEMA_VERSION = "analytics-provider-import.v1";
80
- var analyticsImportTargetIdSchema = z3.string().min(1).max(120).regex(/^[a-zA-Z][a-zA-Z0-9]*(?:[._-][a-zA-Z0-9]+)*$/u);
81
- var analyticsProviderImportRowSchema = z3.object({
100
+ var analyticsImportTargetIdSchema = z4.string().min(1).max(120).regex(/^[a-zA-Z][a-zA-Z0-9]*(?:[._-][a-zA-Z0-9]+)*$/u);
101
+ var analyticsProviderImportRowSchema = z4.object({
82
102
  targetId: analyticsImportTargetIdSchema,
83
- occurredAt: z3.string().datetime({ offset: true }),
84
- attributionConfidence: z3.enum(["provider_reported", "manual_import"]),
85
- providerEventId: z3.string().trim().min(1).max(160).optional(),
86
- idempotencyKey: z3.string().trim().min(1).max(160).optional()
103
+ occurredAt: z4.string().datetime({ offset: true }),
104
+ attributionConfidence: z4.enum(["provider_reported", "manual_import"]),
105
+ providerEventId: z4.string().trim().min(1).max(160).optional(),
106
+ idempotencyKey: z4.string().trim().min(1).max(160).optional()
87
107
  }).strict().superRefine((row, context) => {
88
108
  if (!row.providerEventId && !row.idempotencyKey) {
89
109
  context.addIssue({
@@ -93,24 +113,24 @@ var analyticsProviderImportRowSchema = z3.object({
93
113
  });
94
114
  }
95
115
  });
96
- var analyticsProviderImportSchema = z3.object({
97
- schemaVersion: z3.literal(ANALYTICS_IMPORT_SCHEMA_VERSION),
98
- provider: z3.enum(["treatwell", "beautinda", "other"]),
99
- sourceName: z3.string().trim().min(1).max(160).optional(),
100
- rows: z3.array(analyticsProviderImportRowSchema).min(1).max(1e3)
116
+ var analyticsProviderImportSchema = z4.object({
117
+ schemaVersion: z4.literal(ANALYTICS_IMPORT_SCHEMA_VERSION),
118
+ provider: z4.enum(["treatwell", "beautinda", "other"]),
119
+ sourceName: z4.string().trim().min(1).max(160).optional(),
120
+ rows: z4.array(analyticsProviderImportRowSchema).min(1).max(1e3)
101
121
  }).strict();
102
122
 
103
123
  // ../shared/dist/analytics-config.js
104
- import { z as z4 } from "zod";
124
+ import { z as z5 } from "zod";
105
125
  var ANALYTICS_CONFIG_LEASE_MS = 6e4;
106
- var analyticsMeasurementConfigSchema = z4.object({
107
- version: z4.literal(1),
108
- installationGeneration: z4.number().int().positive(),
109
- configRevision: z4.number().int().positive(),
110
- effectiveSiteMode: z4.enum(["disabled", "session_only", "full_analytics"]),
111
- measurementEnabled: z4.boolean(),
112
- issuedAt: z4.string().datetime({ offset: true }),
113
- expiresAt: z4.string().datetime({ offset: true })
126
+ var analyticsMeasurementConfigSchema = z5.object({
127
+ version: z5.literal(1),
128
+ installationGeneration: z5.number().int().positive(),
129
+ configRevision: z5.number().int().positive(),
130
+ effectiveSiteMode: z5.enum(["disabled", "session_only", "full_analytics"]),
131
+ measurementEnabled: z5.boolean(),
132
+ issuedAt: z5.string().datetime({ offset: true }),
133
+ expiresAt: z5.string().datetime({ offset: true })
114
134
  }).strict().superRefine((config, context) => {
115
135
  const lifetime = Date.parse(config.expiresAt) - Date.parse(config.issuedAt);
116
136
  if (lifetime <= 0 || lifetime > ANALYTICS_CONFIG_LEASE_MS) {
@@ -130,11 +150,11 @@ var analyticsMeasurementConfigSchema = z4.object({
130
150
  });
131
151
 
132
152
  // ../shared/dist/analytics-events.js
133
- import { z as z5 } from "zod";
153
+ import { z as z6 } from "zod";
134
154
  var ANALYTICS_SCHEMA_VERSION = "analytics.v1";
135
- var analyticsSessionIdSchema = z5.string().regex(/^cpa_s_[a-f0-9]{32}$/u);
136
- var analyticsVisitorIdSchema = z5.string().regex(/^cpa_v_[a-f0-9]{32}$/u);
137
- var analyticsPersistedIdentityHashSchema = z5.string().regex(/^[a-f0-9]{64}$/u);
155
+ var analyticsSessionIdSchema = z6.string().regex(/^cpa_s_[a-f0-9]{32}$/u);
156
+ var analyticsVisitorIdSchema = z6.string().regex(/^cpa_v_[a-f0-9]{32}$/u);
157
+ var analyticsPersistedIdentityHashSchema = z6.string().regex(/^[a-f0-9]{64}$/u);
138
158
  var analyticsEventNames = [
139
159
  "page_view",
140
160
  "section_view",
@@ -214,43 +234,43 @@ var analyticsValidityStatuses = [
214
234
  "rejected",
215
235
  "ignored"
216
236
  ];
217
- var analyticsEventNameSchema = z5.enum(analyticsEventNames);
218
- var serverOnlyAnalyticsEventSchema = z5.enum(serverOnlyAnalyticsEvents);
219
- var analyticsEventSourceSchema = z5.enum(analyticsEventSources);
220
- var analyticsIngestionChannelSchema = z5.enum(analyticsIngestionChannels);
221
- var analyticsTargetTypeSchema = z5.enum(analyticsTargetTypes);
222
- var analyticsDataAttributeEventSchema = z5.enum(analyticsDataAttributeEvents);
223
- var analyticsDeviceTypeSchema = z5.enum(analyticsDeviceTypes);
224
- var analyticsBotClassificationSchema = z5.enum(analyticsBotClassifications);
225
- var analyticsValidityStatusSchema = z5.enum(analyticsValidityStatuses);
226
- var analyticsPropertiesSchema = z5.record(z5.string(), z5.unknown());
227
- var analyticsTimestampSchema = z5.string().datetime({ offset: true });
228
- var analyticsBrowserEventSchema = z5.object({
229
- eventId: z5.string().min(1).max(160),
230
- installationGeneration: z5.number().int().positive().optional(),
231
- measurementMode: z5.enum(["session_only", "full_analytics"]).optional(),
237
+ var analyticsEventNameSchema = z6.enum(analyticsEventNames);
238
+ var serverOnlyAnalyticsEventSchema = z6.enum(serverOnlyAnalyticsEvents);
239
+ var analyticsEventSourceSchema = z6.enum(analyticsEventSources);
240
+ var analyticsIngestionChannelSchema = z6.enum(analyticsIngestionChannels);
241
+ var analyticsTargetTypeSchema = z6.enum(analyticsTargetTypes);
242
+ var analyticsDataAttributeEventSchema = z6.enum(analyticsDataAttributeEvents);
243
+ var analyticsDeviceTypeSchema = z6.enum(analyticsDeviceTypes);
244
+ var analyticsBotClassificationSchema = z6.enum(analyticsBotClassifications);
245
+ var analyticsValidityStatusSchema = z6.enum(analyticsValidityStatuses);
246
+ var analyticsPropertiesSchema = z6.record(z6.string(), z6.unknown());
247
+ var analyticsTimestampSchema = z6.string().datetime({ offset: true });
248
+ var analyticsBrowserEventSchema = z6.object({
249
+ eventId: z6.string().min(1).max(160),
250
+ installationGeneration: z6.number().int().positive().optional(),
251
+ measurementMode: z6.enum(["session_only", "full_analytics"]).optional(),
232
252
  eventName: analyticsEventNameSchema,
233
253
  eventSource: analyticsEventSourceSchema.optional().default("browser"),
234
- targetId: z5.string().min(1).max(160).optional(),
254
+ targetId: z6.string().min(1).max(160).optional(),
235
255
  targetType: analyticsTargetTypeSchema.optional(),
236
256
  visitorId: analyticsVisitorIdSchema.optional(),
237
257
  sessionId: analyticsSessionIdSchema,
238
- idempotencyKey: z5.string().min(1).max(240).optional(),
258
+ idempotencyKey: z6.string().min(1).max(240).optional(),
239
259
  occurredAt: analyticsTimestampSchema,
240
- pageUrl: z5.string().url().max(2048).optional(),
241
- pagePath: z5.string().min(1).max(1024).optional(),
242
- routeTemplate: z5.string().min(1).max(1024).optional(),
243
- referrer: z5.string().url().max(2048).optional(),
244
- utmSource: z5.string().min(1).max(200).optional(),
245
- utmMedium: z5.string().min(1).max(200).optional(),
246
- utmCampaign: z5.string().min(1).max(200).optional(),
247
- utmContent: z5.string().min(1).max(200).optional(),
248
- utmTerm: z5.string().min(1).max(200).optional(),
260
+ pageUrl: z6.string().url().max(2048).optional(),
261
+ pagePath: z6.string().min(1).max(1024).optional(),
262
+ routeTemplate: z6.string().min(1).max(1024).optional(),
263
+ referrer: z6.string().url().max(2048).optional(),
264
+ utmSource: z6.string().min(1).max(200).optional(),
265
+ utmMedium: z6.string().min(1).max(200).optional(),
266
+ utmCampaign: z6.string().min(1).max(200).optional(),
267
+ utmContent: z6.string().min(1).max(200).optional(),
268
+ utmTerm: z6.string().min(1).max(200).optional(),
249
269
  deviceType: analyticsDeviceTypeSchema.optional(),
250
- browserName: z5.string().min(1).max(120).optional(),
251
- osName: z5.string().min(1).max(120).optional(),
252
- country: z5.string().min(1).max(80).optional(),
253
- region: z5.string().min(1).max(120).optional(),
270
+ browserName: z6.string().min(1).max(120).optional(),
271
+ osName: z6.string().min(1).max(120).optional(),
272
+ country: z6.string().min(1).max(80).optional(),
273
+ region: z6.string().min(1).max(120).optional(),
254
274
  properties: analyticsPropertiesSchema.optional().default({})
255
275
  }).superRefine((event, context) => {
256
276
  if (isServerOnlyAnalyticsEvent(event.eventName)) {
@@ -275,44 +295,44 @@ var analyticsBrowserEventSchema = z5.object({
275
295
  });
276
296
  }
277
297
  });
278
- var analyticsBrowserEventPayloadSchema = z5.object({
279
- siteKey: z5.string().min(1),
280
- schemaVersion: z5.literal(ANALYTICS_SCHEMA_VERSION),
281
- mode: z5.enum(["live", "test"]).optional().default("live"),
282
- events: z5.array(analyticsBrowserEventSchema).min(1).max(50)
298
+ var analyticsBrowserEventPayloadSchema = z6.object({
299
+ siteKey: z6.string().min(1),
300
+ schemaVersion: z6.literal(ANALYTICS_SCHEMA_VERSION),
301
+ mode: z6.enum(["live", "test"]).optional().default("live"),
302
+ events: z6.array(analyticsBrowserEventSchema).min(1).max(50)
283
303
  });
284
- var analyticsNormalizedEventBaseSchema = z5.object({
285
- site_id: z5.string().uuid(),
286
- event_id: z5.string().min(1).max(160),
287
- schema_version: z5.literal(ANALYTICS_SCHEMA_VERSION),
304
+ var analyticsNormalizedEventBaseSchema = z6.object({
305
+ site_id: z6.string().uuid(),
306
+ event_id: z6.string().min(1).max(160),
307
+ schema_version: z6.literal(ANALYTICS_SCHEMA_VERSION),
288
308
  event_name: analyticsEventNameSchema,
289
309
  event_source: analyticsEventSourceSchema,
290
310
  ingestion_channel: analyticsIngestionChannelSchema,
291
- target_id: z5.string().min(1).max(160).nullable().optional(),
311
+ target_id: z6.string().min(1).max(160).nullable().optional(),
292
312
  target_type: analyticsTargetTypeSchema.nullable().optional(),
293
- dedupe_key: z5.string().regex(/^analytics_dedupe_v1_[a-f0-9]{64}$/u).nullable().optional(),
294
- idempotency_key: z5.string().min(1).max(240).nullable().optional(),
313
+ dedupe_key: z6.string().regex(/^analytics_dedupe_v1_[a-f0-9]{64}$/u).nullable().optional(),
314
+ idempotency_key: z6.string().min(1).max(240).nullable().optional(),
295
315
  bot_classification: analyticsBotClassificationSchema,
296
316
  validity_status: analyticsValidityStatusSchema,
297
- rejection_reason: z5.string().min(1).max(240).nullable().optional(),
317
+ rejection_reason: z6.string().min(1).max(240).nullable().optional(),
298
318
  occurred_at: analyticsTimestampSchema,
299
319
  received_at: analyticsTimestampSchema,
300
- page_url: z5.string().url().max(2048).nullable().optional(),
301
- page_path: z5.string().min(1).max(1024).nullable().optional(),
302
- route_template: z5.string().min(1).max(1024).nullable().optional(),
303
- referrer: z5.string().url().max(2048).nullable().optional(),
304
- utm_source: z5.string().min(1).max(200).nullable().optional(),
305
- utm_medium: z5.string().min(1).max(200).nullable().optional(),
306
- utm_campaign: z5.string().min(1).max(200).nullable().optional(),
307
- utm_content: z5.string().min(1).max(200).nullable().optional(),
308
- utm_term: z5.string().min(1).max(200).nullable().optional(),
309
- country: z5.string().min(1).max(80).nullable().optional(),
310
- region: z5.string().min(1).max(120).nullable().optional(),
320
+ page_url: z6.string().url().max(2048).nullable().optional(),
321
+ page_path: z6.string().min(1).max(1024).nullable().optional(),
322
+ route_template: z6.string().min(1).max(1024).nullable().optional(),
323
+ referrer: z6.string().url().max(2048).nullable().optional(),
324
+ utm_source: z6.string().min(1).max(200).nullable().optional(),
325
+ utm_medium: z6.string().min(1).max(200).nullable().optional(),
326
+ utm_campaign: z6.string().min(1).max(200).nullable().optional(),
327
+ utm_content: z6.string().min(1).max(200).nullable().optional(),
328
+ utm_term: z6.string().min(1).max(200).nullable().optional(),
329
+ country: z6.string().min(1).max(80).nullable().optional(),
330
+ region: z6.string().min(1).max(120).nullable().optional(),
311
331
  device_type: analyticsDeviceTypeSchema,
312
- browser_name: z5.string().min(1).max(120).nullable().optional(),
313
- os_name: z5.string().min(1).max(120).nullable().optional(),
314
- provider: z5.string().min(1).max(120).nullable().optional(),
315
- provider_event_id: z5.string().min(1).max(240).nullable().optional(),
332
+ browser_name: z6.string().min(1).max(120).nullable().optional(),
333
+ os_name: z6.string().min(1).max(120).nullable().optional(),
334
+ provider: z6.string().min(1).max(120).nullable().optional(),
335
+ provider_event_id: z6.string().min(1).max(240).nullable().optional(),
316
336
  properties: analyticsPropertiesSchema
317
337
  });
318
338
  var analyticsRawNormalizedEventSchema = analyticsNormalizedEventBaseSchema.extend({
@@ -328,11 +348,11 @@ function isServerOnlyAnalyticsEvent(eventName) {
328
348
  }
329
349
 
330
350
  // ../shared/dist/analytics-manifest.js
331
- import { z as z6 } from "zod";
332
- var analyticsTargetIdSchema = z6.string().min(1).max(120).regex(/^[a-zA-Z][a-zA-Z0-9]*(?:[._-][a-zA-Z0-9]+)*$/u, {
351
+ import { z as z7 } from "zod";
352
+ var analyticsTargetIdSchema = z7.string().min(1).max(120).regex(/^[a-zA-Z][a-zA-Z0-9]*(?:[._-][a-zA-Z0-9]+)*$/u, {
333
353
  message: "Analytics target IDs must be stable identifiers without whitespace or visible copy."
334
354
  });
335
- var analyticsManifestRecordSchema = z6.record(z6.string(), z6.unknown());
355
+ var analyticsManifestRecordSchema = z7.record(z7.string(), z7.unknown());
336
356
  var analyticsFormPurposes = [
337
357
  "contact",
338
358
  "lead",
@@ -341,21 +361,21 @@ var analyticsFormPurposes = [
341
361
  "login",
342
362
  "other"
343
363
  ];
344
- var analyticsFormPurposeSchema = z6.enum(analyticsFormPurposes);
345
- var analyticsManifestRouteSchema = z6.object({
346
- path: z6.string().min(1).max(1024),
347
- pageType: z6.string().min(1).max(120).optional(),
348
- label: z6.string().min(1).max(200).optional()
364
+ var analyticsFormPurposeSchema = z7.enum(analyticsFormPurposes);
365
+ var analyticsManifestRouteSchema = z7.object({
366
+ path: z7.string().min(1).max(1024),
367
+ pageType: z7.string().min(1).max(120).optional(),
368
+ label: z7.string().min(1).max(200).optional()
349
369
  }).passthrough();
350
- var analyticsManifestTargetSchema = z6.object({
370
+ var analyticsManifestTargetSchema = z7.object({
351
371
  id: analyticsTargetIdSchema,
352
372
  type: analyticsTargetTypeSchema,
353
373
  event: analyticsEventNameSchema.optional(),
354
- events: z6.array(analyticsEventNameSchema).min(1).max(20).optional(),
355
- route: z6.string().min(1).max(1024).optional(),
356
- label: z6.string().min(1).max(200).optional(),
357
- description: z6.string().min(1).max(1e3).optional(),
358
- autoActive: z6.boolean().optional(),
374
+ events: z7.array(analyticsEventNameSchema).min(1).max(20).optional(),
375
+ route: z7.string().min(1).max(1024).optional(),
376
+ label: z7.string().min(1).max(200).optional(),
377
+ description: z7.string().min(1).max(1e3).optional(),
378
+ autoActive: z7.boolean().optional(),
359
379
  sourceHints: analyticsManifestRecordSchema.optional()
360
380
  }).passthrough().superRefine((target, context) => {
361
381
  if (target.event === void 0 && target.events === void 0) {
@@ -380,21 +400,21 @@ var analyticsManifestTargetSchema = z6.object({
380
400
  });
381
401
  }
382
402
  });
383
- var analyticsManifestSchema = z6.object({
384
- schemaVersion: z6.literal(ANALYTICS_SCHEMA_VERSION),
385
- siteId: z6.string().min(1),
386
- siteKeyRef: z6.string().regex(/^env:[A-Z][A-Z0-9_]*$/u, {
403
+ var analyticsManifestSchema = z7.object({
404
+ schemaVersion: z7.literal(ANALYTICS_SCHEMA_VERSION),
405
+ siteId: z7.string().min(1),
406
+ siteKeyRef: z7.string().regex(/^env:[A-Z][A-Z0-9_]*$/u, {
387
407
  message: "siteKeyRef must be an environment-variable reference."
388
408
  }),
389
- siteKeyLookup: z6.string().regex(/^pk_siteplane_[A-Za-z0-9_-]{16}$/),
390
- routes: z6.array(analyticsManifestRouteSchema),
391
- targets: z6.array(analyticsManifestTargetSchema),
409
+ siteKeyLookup: z7.string().regex(/^pk_siteplane_[A-Za-z0-9_-]{16}$/),
410
+ routes: z7.array(analyticsManifestRouteSchema),
411
+ targets: z7.array(analyticsManifestTargetSchema),
392
412
  metadata: analyticsManifestRecordSchema.optional(),
393
- siteKey: z6.string().optional(),
394
- secretKey: z6.string().optional(),
395
- rawKey: z6.string().optional(),
396
- token: z6.string().optional(),
397
- accessToken: z6.string().optional()
413
+ siteKey: z7.string().optional(),
414
+ secretKey: z7.string().optional(),
415
+ rawKey: z7.string().optional(),
416
+ token: z7.string().optional(),
417
+ accessToken: z7.string().optional()
398
418
  }).passthrough().superRefine((manifest, context) => {
399
419
  const targetIds = /* @__PURE__ */ new Set();
400
420
  for (const [index, target] of manifest.targets.entries()) {
@@ -438,9 +458,9 @@ function isPlainRecord(value) {
438
458
  }
439
459
 
440
460
  // ../shared/dist/analytics-metrics.js
441
- import { z as z7 } from "zod";
461
+ import { z as z8 } from "zod";
442
462
  var analyticsVisitorQualities = ["exact", "estimated"];
443
- var analyticsVisitorQualitySchema = z7.enum(analyticsVisitorQualities);
463
+ var analyticsVisitorQualitySchema = z8.enum(analyticsVisitorQualities);
444
464
  var analyticsKpiKeys = [
445
465
  "pageViews",
446
466
  "sessions",
@@ -452,7 +472,7 @@ var analyticsKpiKeys = [
452
472
  "conversionRate",
453
473
  "inquiryRate"
454
474
  ];
455
- var analyticsKpiKeySchema = z7.enum(analyticsKpiKeys);
475
+ var analyticsKpiKeySchema = z8.enum(analyticsKpiKeys);
456
476
 
457
477
  // ../shared/dist/analytics-privacy.js
458
478
  var serverPropertySchemas = {
@@ -490,7 +510,7 @@ function revenuePropertySchema() {
490
510
  }
491
511
 
492
512
  // ../shared/dist/assets.js
493
- import { z as z8 } from "zod";
513
+ import { z as z9 } from "zod";
494
514
  var ASSET_STAGES = ["staging", "final", "deleted"];
495
515
  var ASSET_VISIBILITIES = ["private", "public", "deleted"];
496
516
  var ASSET_USAGE_ENTITY_TYPES = [
@@ -499,13 +519,13 @@ var ASSET_USAGE_ENTITY_TYPES = [
499
519
  "change_set",
500
520
  "published_value"
501
521
  ];
502
- var assetStageSchema = z8.enum(ASSET_STAGES);
503
- var assetVisibilitySchema = z8.enum(ASSET_VISIBILITIES);
504
- var assetUsageEntityTypeSchema = z8.enum(ASSET_USAGE_ENTITY_TYPES);
505
- var brandingAccentColorSchema = z8.string().regex(/^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/);
522
+ var assetStageSchema = z9.enum(ASSET_STAGES);
523
+ var assetVisibilitySchema = z9.enum(ASSET_VISIBILITIES);
524
+ var assetUsageEntityTypeSchema = z9.enum(ASSET_USAGE_ENTITY_TYPES);
525
+ var brandingAccentColorSchema = z9.string().regex(/^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/);
506
526
 
507
527
  // ../shared/dist/booking-contracts.js
508
- import { z as z9 } from "zod";
528
+ import { z as z10 } from "zod";
509
529
  var bookingStatuses = [
510
530
  "pending_payment",
511
531
  "confirmed",
@@ -560,30 +580,30 @@ var bookingResourceKinds = [
560
580
  "equipment",
561
581
  "other"
562
582
  ];
563
- var bookingStatusSchema = z9.enum(bookingStatuses);
564
- var bookingPaymentStatusSchema = z9.enum(bookingPaymentStatuses);
565
- var bookingAccountReadinessStatusSchema = z9.enum(bookingAccountReadinessStatuses);
566
- var bookingRefundStatusSchema = z9.enum(bookingRefundStatuses);
567
- var bookingDisputeStatusSchema = z9.enum(bookingDisputeStatuses);
568
- var bookingPaymentModeSchema = z9.enum(bookingPaymentModes);
569
- var bookingPaymentCollectionTypeSchema = z9.enum(bookingPaymentCollectionTypes);
570
- var bookingPaymentCollectionSchema = z9.discriminatedUnion("type", [
571
- z9.object({ type: z9.literal("full_amount") }).strict(),
572
- z9.object({
573
- type: z9.literal("deposit_percent"),
574
- depositPercent: z9.number().int().min(10).max(90)
583
+ var bookingStatusSchema = z10.enum(bookingStatuses);
584
+ var bookingPaymentStatusSchema = z10.enum(bookingPaymentStatuses);
585
+ var bookingAccountReadinessStatusSchema = z10.enum(bookingAccountReadinessStatuses);
586
+ var bookingRefundStatusSchema = z10.enum(bookingRefundStatuses);
587
+ var bookingDisputeStatusSchema = z10.enum(bookingDisputeStatuses);
588
+ var bookingPaymentModeSchema = z10.enum(bookingPaymentModes);
589
+ var bookingPaymentCollectionTypeSchema = z10.enum(bookingPaymentCollectionTypes);
590
+ var bookingPaymentCollectionSchema = z10.discriminatedUnion("type", [
591
+ z10.object({ type: z10.literal("full_amount") }).strict(),
592
+ z10.object({
593
+ type: z10.literal("deposit_percent"),
594
+ depositPercent: z10.number().int().min(10).max(90)
575
595
  }).strict()
576
596
  ]);
577
597
  var bookingPaymentChoices = ["onsite", "online"];
578
- var bookingPaymentChoiceSchema = z9.enum(bookingPaymentChoices);
579
- var bookingPaymentSnapshotSchema = z9.object({
580
- snapshotId: z9.string().uuid(),
581
- snapshotVersion: z9.number().int().positive(),
582
- currency: z9.literal("EUR"),
583
- totalAmountCents: z9.number().int().min(0),
584
- onlineAmountCents: z9.number().int().min(0),
585
- onsiteRemainderCents: z9.number().int().min(0),
586
- maxStripeRefundAmountCents: z9.number().int().min(0)
598
+ var bookingPaymentChoiceSchema = z10.enum(bookingPaymentChoices);
599
+ var bookingPaymentSnapshotSchema = z10.object({
600
+ snapshotId: z10.string().uuid(),
601
+ snapshotVersion: z10.number().int().positive(),
602
+ currency: z10.literal("EUR"),
603
+ totalAmountCents: z10.number().int().min(0),
604
+ onlineAmountCents: z10.number().int().min(0),
605
+ onsiteRemainderCents: z10.number().int().min(0),
606
+ maxStripeRefundAmountCents: z10.number().int().min(0)
587
607
  }).strict().superRefine((snapshot, context) => {
588
608
  if (snapshot.onlineAmountCents + snapshot.onsiteRemainderCents !== snapshot.totalAmountCents) {
589
609
  context.addIssue({
@@ -598,17 +618,17 @@ var bookingPaymentSnapshotSchema = z9.object({
598
618
  });
599
619
  }
600
620
  });
601
- var bookingServiceVariantSchema = z9.object({
602
- id: z9.string().uuid(),
603
- name: z9.string().trim().min(1).max(120),
604
- durationMinutes: z9.number().int().min(1).max(1440),
605
- priceCents: z9.number().int().min(0).nullable()
621
+ var bookingServiceVariantSchema = z10.object({
622
+ id: z10.string().uuid(),
623
+ name: z10.string().trim().min(1).max(120),
624
+ durationMinutes: z10.number().int().min(1).max(1440),
625
+ priceCents: z10.number().int().min(0).nullable()
606
626
  }).strict();
607
- var bookingServiceVariantsSchema = z9.array(bookingServiceVariantSchema).min(1).max(20);
608
- var isoDateSchema = z9.string().regex(/^\d{4}-\d{2}-\d{2}$/);
609
- var utcDateTimeSchema = z9.string().datetime();
610
- var bookingLocalTimeSchema = z9.string().regex(/^(?:[01]\d|2[0-3]):[0-5]\d$/);
611
- var bookingAvailabilityIntervalsSchema = z9.array(z9.object({
627
+ var bookingServiceVariantsSchema = z10.array(bookingServiceVariantSchema).min(1).max(20);
628
+ var isoDateSchema = z10.string().regex(/^\d{4}-\d{2}-\d{2}$/);
629
+ var utcDateTimeSchema = z10.string().datetime();
630
+ var bookingLocalTimeSchema = z10.string().regex(/^(?:[01]\d|2[0-3]):[0-5]\d$/);
631
+ var bookingAvailabilityIntervalsSchema = z10.array(z10.object({
612
632
  start: bookingLocalTimeSchema,
613
633
  end: bookingLocalTimeSchema
614
634
  }).strict().refine((interval) => interval.end > interval.start)).superRefine((intervals, context) => {
@@ -623,76 +643,78 @@ var bookingAvailabilityIntervalsSchema = z9.array(z9.object({
623
643
  }
624
644
  }
625
645
  });
626
- var bookingPublicConfigSchema = z9.object({
627
- site: z9.object({
628
- displayName: z9.string().trim().min(1),
629
- timezone: z9.string().trim().min(1),
630
- locale: z9.string().trim().min(2),
631
- bookingPageSlug: z9.string().regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/).min(2).max(64),
632
- privacyUrl: z9.string().url().nullable()
646
+ var bookingPublicConfigSchema = z10.object({
647
+ site: z10.object({
648
+ displayName: z10.string().trim().min(1),
649
+ timezone: z10.string().trim().min(1),
650
+ locale: z10.string().trim().min(2),
651
+ bookingPageSlug: z10.string().regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/).min(2).max(64),
652
+ privacyUrl: z10.string().url().nullable()
633
653
  }),
634
- branding: z9.object({
635
- logoUrl: z9.string().url().nullable(),
636
- accentColor: z9.string().trim().min(1).nullable()
654
+ branding: z10.object({
655
+ logoUrl: z10.string().url().nullable(),
656
+ accentColor: z10.string().trim().min(1).nullable()
637
657
  }),
638
- settings: z9.object({
639
- slotIntervalMinutes: z9.number().int().positive(),
640
- minLeadMinutes: z9.number().int().min(0),
641
- minCancelLeadMinutes: z9.number().int().min(0),
642
- maxAdvanceDays: z9.number().int().min(1),
643
- requirePhone: z9.boolean(),
644
- collectNote: z9.boolean(),
645
- confirmationMessage: z9.string().nullable()
658
+ settings: z10.object({
659
+ slotIntervalMinutes: z10.number().int().positive(),
660
+ minLeadMinutes: z10.number().int().min(0),
661
+ minCancelLeadMinutes: z10.number().int().min(0),
662
+ maxAdvanceDays: z10.number().int().min(1),
663
+ requirePhone: z10.boolean(),
664
+ collectNote: z10.boolean(),
665
+ confirmationMessage: z10.string().nullable()
646
666
  }),
647
667
  /** Freitexte des Salons, im Kassen-Schritt vor der Bestaetigung sichtbar. */
648
- policies: z9.object({
649
- cancellation: z9.string().nullable(),
650
- lateArrival: z9.string().nullable()
668
+ policies: z10.object({
669
+ cancellation: z10.string().nullable(),
670
+ lateArrival: z10.string().nullable()
651
671
  }),
652
- payment: z9.object({
672
+ payment: z10.object({
653
673
  mode: bookingPaymentModeSchema,
654
674
  collection: bookingPaymentCollectionSchema,
655
- onlinePaymentsReady: z9.boolean()
675
+ onlinePaymentsReady: z10.boolean()
656
676
  }).strict(),
657
- serviceCategories: z9.array(z9.object({
658
- id: z9.string().uuid(),
659
- name: z9.string().trim().min(1),
660
- sortOrder: z9.number().int()
677
+ serviceCategories: z10.array(z10.object({
678
+ id: z10.string().uuid(),
679
+ name: z10.string().trim().min(1),
680
+ sortOrder: z10.number().int()
661
681
  })),
662
- serviceSubcategories: z9.array(z9.object({
663
- id: z9.string().uuid(),
664
- categoryId: z9.string().uuid(),
665
- name: z9.string().trim().min(1),
666
- sortOrder: z9.number().int()
682
+ serviceSubcategories: z10.array(z10.object({
683
+ id: z10.string().uuid(),
684
+ categoryId: z10.string().uuid(),
685
+ name: z10.string().trim().min(1),
686
+ sortOrder: z10.number().int()
667
687
  })),
668
- services: z9.array(z9.object({
669
- id: z9.string().trim().min(1),
670
- name: z9.string().trim().min(1),
671
- durationMinutes: z9.number().int().positive(),
672
- priceCents: z9.number().int().min(0).nullable(),
673
- currency: z9.string().regex(/^[A-Z]{3}$/),
674
- description: z9.string().nullable(),
675
- categoryId: z9.string().uuid(),
676
- subcategoryId: z9.string().uuid().nullable(),
688
+ services: z10.array(z10.object({
689
+ id: z10.string().trim().min(1),
690
+ name: z10.string().trim().min(1),
691
+ durationMinutes: z10.number().int().positive(),
692
+ priceCents: z10.number().int().min(0).nullable(),
693
+ currency: z10.string().regex(/^[A-Z]{3}$/),
694
+ description: z10.string().nullable(),
695
+ categoryId: z10.string().uuid(),
696
+ subcategoryId: z10.string().uuid().nullable(),
677
697
  variants: bookingServiceVariantsSchema,
678
- allowsAnyResource: z9.boolean(),
679
- sortOrder: z9.number().int()
698
+ allowsAnyResource: z10.boolean(),
699
+ sortOrder: z10.number().int()
680
700
  })),
681
- resources: z9.array(z9.object({
682
- id: z9.string().trim().min(1),
683
- name: z9.string().trim().min(1),
684
- kind: z9.enum(bookingResourceKinds)
701
+ resources: z10.array(z10.object({
702
+ id: z10.string().trim().min(1),
703
+ name: z10.string().trim().min(1),
704
+ kind: z10.enum(bookingResourceKinds),
705
+ /** Profilfoto für „Bei wem?“; `null` ohne Foto. */
706
+ photoUrl: z10.string().url().nullable()
685
707
  })),
686
- serviceResources: z9.array(z9.object({
687
- serviceId: z9.string().trim().min(1),
688
- resourceId: z9.string().trim().min(1)
708
+ serviceResources: z10.array(z10.object({
709
+ serviceId: z10.string().trim().min(1),
710
+ resourceId: z10.string().trim().min(1)
689
711
  }))
690
712
  });
691
- var bookingItemSchema = z9.object({
692
- serviceId: z9.string().trim().min(1),
693
- variantId: z9.string().trim().min(1)
713
+ var bookingItemSchema = z10.object({
714
+ serviceId: z10.string().trim().min(1),
715
+ variantId: z10.string().trim().min(1)
694
716
  }).strict();
695
- var bookingItemsSchema = z9.array(bookingItemSchema).min(1).max(10);
717
+ var bookingItemsSchema = z10.array(bookingItemSchema).min(1).max(10);
696
718
  function parseBookingItemsParam(value) {
697
719
  const items = value.split(",").map((entry) => entry.trim()).filter((entry) => entry !== "").map((entry) => {
698
720
  const [serviceId, variantId, ...rest] = entry.split(":");
@@ -700,36 +722,36 @@ function parseBookingItemsParam(value) {
700
722
  });
701
723
  return items.every((item) => item !== null) ? items : null;
702
724
  }
703
- var bookingSlotsQuerySchema = z9.object({
704
- items: z9.preprocess((value) => typeof value === "string" ? parseBookingItemsParam(value) : value, bookingItemsSchema),
705
- resourceId: z9.string().trim().min(1).optional(),
725
+ var bookingSlotsQuerySchema = z10.object({
726
+ items: z10.preprocess((value) => typeof value === "string" ? parseBookingItemsParam(value) : value, bookingItemsSchema),
727
+ resourceId: z10.string().trim().min(1).optional(),
706
728
  fromDate: isoDateSchema,
707
729
  toDate: isoDateSchema
708
730
  });
709
- var bookingSlotsResponseSchema = z9.object({
710
- timezone: z9.string().trim().min(1),
731
+ var bookingSlotsResponseSchema = z10.object({
732
+ timezone: z10.string().trim().min(1),
711
733
  items: bookingItemsSchema,
712
734
  // Reine Behandlungsdauer ohne Puffer: das UI zeigt damit die Terminspanne,
713
735
  // ohne selbst rechnen zu muessen.
714
- totalDurationMinutes: z9.number().int().min(1),
715
- mode: z9.enum(["any", "resource"]),
716
- slots: z9.array(z9.object({
736
+ totalDurationMinutes: z10.number().int().min(1),
737
+ mode: z10.enum(["any", "resource"]),
738
+ slots: z10.array(z10.object({
717
739
  startUtc: utcDateTimeSchema,
718
- resourceId: z9.string().trim().min(1).optional()
740
+ resourceId: z10.string().trim().min(1).optional()
719
741
  }))
720
742
  });
721
- var bookingAvailabilityQuerySchema = z9.object({
722
- items: z9.preprocess((value) => typeof value === "string" ? parseBookingItemsParam(value) : value, bookingItemsSchema),
723
- resourceId: z9.string().trim().min(1).optional(),
743
+ var bookingAvailabilityQuerySchema = z10.object({
744
+ items: z10.preprocess((value) => typeof value === "string" ? parseBookingItemsParam(value) : value, bookingItemsSchema),
745
+ resourceId: z10.string().trim().min(1).optional(),
724
746
  fromDate: isoDateSchema,
725
747
  toDate: isoDateSchema
726
748
  });
727
- var bookingAvailabilityResponseSchema = z9.object({
728
- timezone: z9.string().trim().min(1),
729
- totalDurationMinutes: z9.number().int().min(1),
730
- days: z9.array(z9.object({
749
+ var bookingAvailabilityResponseSchema = z10.object({
750
+ timezone: z10.string().trim().min(1),
751
+ totalDurationMinutes: z10.number().int().min(1),
752
+ days: z10.array(z10.object({
731
753
  date: isoDateSchema,
732
- hasSlots: z9.boolean()
754
+ hasSlots: z10.boolean()
733
755
  })),
734
756
  /** Erster Tag mit Slot ab `fromDate`, auch ausserhalb des Fensters. */
735
757
  nextAvailableDate: isoDateSchema.nullable()
@@ -747,72 +769,72 @@ var bookingPublicErrorCodes = [
747
769
  "too_late",
748
770
  "not_found"
749
771
  ];
750
- var bookingPublicErrorSchema = z9.object({
751
- error: z9.enum(bookingPublicErrorCodes),
752
- message: z9.string().optional(),
753
- requestId: z9.string().optional()
772
+ var bookingPublicErrorSchema = z10.object({
773
+ error: z10.enum(bookingPublicErrorCodes),
774
+ message: z10.string().optional(),
775
+ requestId: z10.string().optional()
754
776
  }).strict();
755
- var bookingCreateRequestSchema = z9.object({
777
+ var bookingCreateRequestSchema = z10.object({
756
778
  items: bookingItemsSchema,
757
- resourceId: z9.string().min(1).nullable(),
779
+ resourceId: z10.string().min(1).nullable(),
758
780
  startUtc: utcDateTimeSchema,
759
- customer: z9.object({
760
- name: z9.string().min(1).max(120),
761
- email: z9.string().email().max(254),
762
- phone: z9.string().max(32).optional(),
763
- note: z9.string().max(1e3).optional()
781
+ customer: z10.object({
782
+ name: z10.string().min(1).max(120),
783
+ email: z10.string().email().max(254),
784
+ phone: z10.string().max(32).optional(),
785
+ note: z10.string().max(1e3).optional()
764
786
  }).strict(),
765
- hp: z9.string().optional(),
766
- clientToken: z9.string().uuid(),
787
+ hp: z10.string().optional(),
788
+ clientToken: z10.string().uuid(),
767
789
  paymentChoice: bookingPaymentChoiceSchema,
768
790
  // Werbe-Einwilligung. Bestaetigung, Erinnerung und Storno-Link sind davon
769
791
  // unabhaengig und werden immer versendet.
770
- consent: z9.object({
771
- marketingEmail: z9.boolean(),
772
- marketingSms: z9.boolean()
792
+ consent: z10.object({
793
+ marketingEmail: z10.boolean(),
794
+ marketingSms: z10.boolean()
773
795
  }).strict().optional()
774
796
  }).strict();
775
- var bookingPublicPaymentResponseSchema = z9.object({
776
- clientSecret: z9.string().min(1),
777
- stripeAccountId: z9.string().startsWith("acct_")
797
+ var bookingPublicPaymentResponseSchema = z10.object({
798
+ clientSecret: z10.string().min(1),
799
+ stripeAccountId: z10.string().startsWith("acct_")
778
800
  }).strict();
779
- var bookingCreateResponseSchema = z9.union([
780
- z9.object({
781
- status: z9.literal("confirmed"),
782
- booking: z9.object({
783
- id: z9.string().min(1),
801
+ var bookingCreateResponseSchema = z10.union([
802
+ z10.object({
803
+ status: z10.literal("confirmed"),
804
+ booking: z10.object({
805
+ id: z10.string().min(1),
784
806
  startUtc: utcDateTimeSchema,
785
807
  endUtc: utcDateTimeSchema,
786
- timezone: z9.string().trim().min(1),
787
- serviceName: z9.string().trim().min(1),
788
- resourceName: z9.string().trim().min(1)
808
+ timezone: z10.string().trim().min(1),
809
+ serviceName: z10.string().trim().min(1),
810
+ resourceName: z10.string().trim().min(1)
789
811
  }).strict(),
790
- manageUrl: z9.string().url(),
791
- confirmationMessage: z9.string().nullable()
812
+ manageUrl: z10.string().url(),
813
+ confirmationMessage: z10.string().nullable()
792
814
  }).strict(),
793
- z9.object({
794
- status: z9.literal("pending_payment"),
795
- bookingId: z9.string().min(1),
815
+ z10.object({
816
+ status: z10.literal("pending_payment"),
817
+ bookingId: z10.string().min(1),
796
818
  holdExpiresAt: utcDateTimeSchema,
797
819
  payment: bookingPublicPaymentResponseSchema,
798
- statusToken: z9.string().min(20),
799
- manageUrl: z9.string().url().optional()
820
+ statusToken: z10.string().min(20),
821
+ manageUrl: z10.string().url().optional()
800
822
  }).strict(),
801
823
  bookingPublicErrorSchema
802
824
  ]);
803
- var bookingStatusResponseSchema = z9.object({
825
+ var bookingStatusResponseSchema = z10.object({
804
826
  bookingStatus: bookingStatusSchema,
805
827
  paymentStatus: bookingPaymentStatusSchema,
806
828
  refundStatus: bookingRefundStatusSchema,
807
829
  disputeStatus: bookingDisputeStatusSchema,
808
830
  holdExpiresAt: utcDateTimeSchema.nullable()
809
831
  }).strict();
810
- var bookingCancelRequestSchema = z9.object({
811
- token: z9.string().min(20)
832
+ var bookingCancelRequestSchema = z10.object({
833
+ token: z10.string().min(20)
812
834
  });
813
- var bookingCancelResponseSchema = z9.union([
814
- z9.object({
815
- status: z9.enum(["cancelled", "already_cancelled", "too_late", "not_found"])
835
+ var bookingCancelResponseSchema = z10.union([
836
+ z10.object({
837
+ status: z10.enum(["cancelled", "already_cancelled", "too_late", "not_found"])
816
838
  }),
817
839
  bookingPublicErrorSchema
818
840
  ]);
@@ -821,33 +843,33 @@ var bookingMoveErrorCodes = [
821
843
  "booking_not_movable",
822
844
  "not_found"
823
845
  ];
824
- var bookingMoveRequestSchema = z9.object({
825
- bookingId: z9.string().uuid(),
846
+ var bookingMoveRequestSchema = z10.object({
847
+ bookingId: z10.string().uuid(),
826
848
  newStartUtc: utcDateTimeSchema,
827
- newResourceId: z9.string().uuid().optional(),
828
- notifyCustomer: z9.boolean().default(false),
829
- reason: z9.string().max(500).optional()
830
- });
831
- var bookingMoveResponseSchema = z9.union([
832
- z9.object({
833
- status: z9.literal("moved"),
834
- bookingId: z9.string().uuid(),
849
+ newResourceId: z10.string().uuid().optional(),
850
+ notifyCustomer: z10.boolean().default(false),
851
+ reason: z10.string().max(500).optional()
852
+ });
853
+ var bookingMoveResponseSchema = z10.union([
854
+ z10.object({
855
+ status: z10.literal("moved"),
856
+ bookingId: z10.string().uuid(),
835
857
  startUtc: utcDateTimeSchema,
836
858
  endUtc: utcDateTimeSchema,
837
- resourceId: z9.string().uuid()
859
+ resourceId: z10.string().uuid()
838
860
  }),
839
- z9.object({
840
- error: z9.enum(bookingMoveErrorCodes),
841
- message: z9.string().optional(),
842
- requestId: z9.string().optional()
861
+ z10.object({
862
+ error: z10.enum(bookingMoveErrorCodes),
863
+ message: z10.string().optional(),
864
+ requestId: z10.string().optional()
843
865
  })
844
866
  ]);
845
- var bookingManifestSchema = z9.object({
846
- schemaVersion: z9.number().int().positive(),
847
- siteId: z9.string().trim().min(1),
848
- bookingPageSlug: z9.string().regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/).min(2).max(64),
849
- integration: z9.literal("rewrite").optional(),
850
- productionOrigin: z9.string().url().optional()
867
+ var bookingManifestSchema = z10.object({
868
+ schemaVersion: z10.number().int().positive(),
869
+ siteId: z10.string().trim().min(1),
870
+ bookingPageSlug: z10.string().regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/).min(2).max(64),
871
+ integration: z10.literal("rewrite").optional(),
872
+ productionOrigin: z10.string().url().optional()
851
873
  }).passthrough();
852
874
 
853
875
  // ../shared/dist/booking-defaults.js
@@ -857,20 +879,20 @@ var BOOKING_CREATE_PAYLOAD_LIMIT_BYTES = 16 * 1024;
857
879
  import { z as z17 } from "zod";
858
880
 
859
881
  // ../shared/dist/field-id.js
860
- import { z as z10 } from "zod";
882
+ import { z as z11 } from "zod";
861
883
  var FIELD_ID_PATTERN = /^[a-z][a-z0-9_-]*(\.[a-z][a-z0-9_-]*)+$/;
862
- var fieldIdSchema = z10.string().regex(FIELD_ID_PATTERN, "Invalid field id");
884
+ var fieldIdSchema = z11.string().regex(FIELD_ID_PATTERN, "Invalid field id");
863
885
  function isFieldId(value) {
864
886
  return typeof value === "string" && fieldIdSchema.safeParse(value).success;
865
887
  }
866
888
 
867
889
  // ../shared/dist/field-types.js
868
- import { z as z11 } from "zod";
890
+ import { z as z12 } from "zod";
869
891
  var FIELD_TYPES = ["text", "longText", "image", "link"];
870
- var fieldTypeSchema = z11.enum(FIELD_TYPES);
892
+ var fieldTypeSchema = z12.enum(FIELD_TYPES);
871
893
 
872
894
  // ../shared/dist/image-value.js
873
- import { z as z12 } from "zod";
895
+ import { z as z13 } from "zod";
874
896
  var SUPPORTED_IMAGE_CONTENT_TYPES = [
875
897
  "image/jpeg",
876
898
  "image/png",
@@ -879,21 +901,21 @@ var SUPPORTED_IMAGE_CONTENT_TYPES = [
879
901
  ];
880
902
  var maxImageUploadBytes = 10 * 1024 * 1024;
881
903
  var largeImageWarningBytes = 2 * 1024 * 1024;
882
- var imageContentTypeSchema = z12.enum(SUPPORTED_IMAGE_CONTENT_TYPES);
883
- var imageCropSchema = z12.object({
884
- x: z12.number().min(0).max(100),
885
- y: z12.number().min(0).max(100),
886
- zoom: z12.number().min(1).max(4),
887
- aspectRatio: z12.number().positive().max(10)
888
- });
889
- var imageValueSchema = z12.object({
890
- src: z12.string().trim().min(1),
891
- alt: z12.string().trim().min(1).max(300),
892
- width: z12.number().int().positive().optional(),
893
- height: z12.number().int().positive().optional(),
904
+ var imageContentTypeSchema = z13.enum(SUPPORTED_IMAGE_CONTENT_TYPES);
905
+ var imageCropSchema = z13.object({
906
+ x: z13.number().min(0).max(100),
907
+ y: z13.number().min(0).max(100),
908
+ zoom: z13.number().min(1).max(4),
909
+ aspectRatio: z13.number().positive().max(10)
910
+ });
911
+ var imageValueSchema = z13.object({
912
+ src: z13.string().trim().min(1),
913
+ alt: z13.string().trim().min(1).max(300),
914
+ width: z13.number().int().positive().optional(),
915
+ height: z13.number().int().positive().optional(),
894
916
  crop: imageCropSchema.optional(),
895
- assetId: z12.string().uuid().optional(),
896
- finalStorageProvider: z12.enum([
917
+ assetId: z13.string().uuid().optional(),
918
+ finalStorageProvider: z13.enum([
897
919
  "repo_static_assets",
898
920
  "repo_handoff",
899
921
  "site_owned_storage",
@@ -901,75 +923,83 @@ var imageValueSchema = z12.object({
901
923
  ]).optional()
902
924
  });
903
925
 
904
- // ../shared/dist/setup-deployment.js
905
- import { z as z13 } from "zod";
906
- var version = z13.string().regex(/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/u);
907
- var siteSetupPackagesSchema = z13.object({
908
- siteplane: version,
909
- runtimeNext: version,
910
- analytics: version.optional()
911
- }).strict();
912
- var hash = z13.string().regex(/^sha256:[0-9a-f]{64}$/u);
913
- var setupDeploymentRecordSchema = z13.object({
914
- version: z13.literal(1),
915
- operationId: z13.string().uuid(),
916
- provider: z13.literal("vercel"),
917
- projectId: z13.string().regex(/^prj_[A-Za-z0-9]+$/u),
918
- teamId: z13.string().regex(/^(?:team|user)_[A-Za-z0-9]+$/u),
919
- origin: z13.string().url().refine((value) => {
920
- const url = new URL(value);
921
- return url.protocol === "https:" && url.origin === value && !url.username && !url.password;
922
- }),
923
- deploymentId: z13.string().regex(/^dpl_[A-Za-z0-9]+$/u).nullable(),
924
- revision: z13.string().regex(/^[0-9a-f]{40}$/u),
925
- fieldContractHash: hash,
926
- packages: siteSetupPackagesSchema,
927
- configurationFingerprint: hash,
928
- adminSecretGeneration: z13.string().uuid(),
929
- revalidationGeneration: z13.number().int().positive(),
930
- startedAt: z13.string().datetime(),
931
- environmentWrittenAt: z13.string().datetime().nullable(),
932
- deployRequestedAt: z13.string().datetime().nullable(),
933
- deadline: z13.string().datetime(),
934
- phase: z13.enum([
935
- "planned",
936
- "environment_written",
937
- "deploy_requested",
938
- "deployed",
939
- "verified",
940
- "failed"
941
- ]),
942
- build: z13.object({
943
- node: version,
944
- packageManager: z13.enum(["npm", "pnpm"]),
945
- packageManagerVersion: version,
946
- lockfileHash: hash
947
- }).strict().nullable()
948
- }).strict();
949
- var setupDeploymentInputSchema = z13.discriminatedUnion("action", [
950
- z13.object({ action: z13.literal("read") }).strict(),
951
- z13.object({
952
- action: z13.literal("record"),
953
- expectedOperationId: z13.string().uuid().nullable(),
954
- record: setupDeploymentRecordSchema
955
- }).strict()
956
- ]);
957
-
958
- // ../shared/dist/site-setup.js
959
- import { z as z16 } from "zod";
926
+ // ../shared/dist/missing-content.js
927
+ import { z as z14 } from "zod";
928
+ var MISSING_CONTENT_RENDERED_PATH_MAX_BYTES = 512;
929
+ var MISSING_CONTENT_VISIBLE_VALUE_MAX_BYTES = 256;
930
+ var MISSING_CONTENT_LOCATOR_HINT_MAX_BYTES = 512;
931
+ var MISSING_CONTENT_LABEL_MAX_BYTES = 120;
932
+ var forbiddenControlOrBidi = /[\u0000-\u001f\u007f-\u009f‪-‮⁦-⁩]/u;
933
+ var unsafeLocator = /<\/?[a-z][^>]*>|\b(?:javascript|data:text\/html)\s*:|\bon[a-z]+\s*=/iu;
934
+ var renderedPathSchema = z14.string().trim().transform((value) => value !== "/" ? value.replace(/\/+$/u, "") : value).superRefine((value, context) => {
935
+ if (!value.startsWith("/") || value === "$global" || value.includes("?") || value.includes("#")) {
936
+ context.addIssue({
937
+ code: "custom",
938
+ message: "renderedPath must be a canonical real path."
939
+ });
940
+ }
941
+ addSafeByteIssues(value, MISSING_CONTENT_RENDERED_PATH_MAX_BYTES, "renderedPath", context);
942
+ });
943
+ function normalizedSafeTextSchema(maxBytes, label) {
944
+ return z14.string().transform((value) => value.trim().replace(new RegExp("\\p{White_Space}+", "gu"), " ")).pipe(z14.string().min(1)).superRefine((value, context) => {
945
+ addSafeByteIssues(value, maxBytes, label, context);
946
+ if (label === "locatorHint" && unsafeLocator.test(value)) {
947
+ context.addIssue({
948
+ code: "custom",
949
+ message: "locatorHint contains unsafe markup or executable content."
950
+ });
951
+ }
952
+ });
953
+ }
954
+ var missingContentItemBase = {
955
+ renderedPath: renderedPathSchema,
956
+ visibleValue: normalizedSafeTextSchema(MISSING_CONTENT_VISIBLE_VALUE_MAX_BYTES, "visibleValue"),
957
+ locatorHint: normalizedSafeTextSchema(MISSING_CONTENT_LOCATOR_HINT_MAX_BYTES, "locatorHint"),
958
+ requestedLabel: normalizedSafeTextSchema(MISSING_CONTENT_LABEL_MAX_BYTES, "requestedLabel").optional(),
959
+ requestedSection: normalizedSafeTextSchema(MISSING_CONTENT_LABEL_MAX_BYTES, "requestedSection").optional(),
960
+ requestedSubsection: normalizedSafeTextSchema(MISSING_CONTENT_LABEL_MAX_BYTES, "requestedSubsection").optional(),
961
+ requestedSortOrder: z14.number().int().nonnegative().optional()
962
+ };
963
+ var missingContentItemSchema = z14.discriminatedUnion("kind", [
964
+ z14.object({ kind: z14.literal("text"), ...missingContentItemBase }).strict(),
965
+ z14.object({ kind: z14.literal("link"), ...missingContentItemBase }).strict(),
966
+ z14.object({ kind: z14.literal("image"), ...missingContentItemBase }).strict()
967
+ ]).superRefine((item, context) => {
968
+ if (item.requestedSubsection && !item.requestedSection) {
969
+ context.addIssue({
970
+ code: "custom",
971
+ message: "requestedSubsection requires requestedSection.",
972
+ path: ["requestedSubsection"]
973
+ });
974
+ }
975
+ });
976
+ function addSafeByteIssues(value, maxBytes, label, context) {
977
+ if (new TextEncoder().encode(value).byteLength > maxBytes) {
978
+ context.addIssue({
979
+ code: "custom",
980
+ message: `${label} exceeds ${maxBytes} UTF-8 bytes.`
981
+ });
982
+ }
983
+ if (forbiddenControlOrBidi.test(value)) {
984
+ context.addIssue({
985
+ code: "custom",
986
+ message: `${label} contains a forbidden control or bidi character.`
987
+ });
988
+ }
989
+ }
960
990
 
961
991
  // ../shared/dist/site-field-contract.js
962
- import { z as z15 } from "zod";
992
+ import { z as z16 } from "zod";
963
993
 
964
994
  // ../shared/dist/fallback-hash.js
965
- import { z as z14 } from "zod";
995
+ import { z as z15 } from "zod";
966
996
  var SAFE_REPRESENTATION_REASONS = [
967
997
  "asset_import_rewritten",
968
998
  "relative_url_normalized",
969
999
  "line_endings_normalized",
970
1000
  "image_value_serialized"
971
1001
  ];
972
- var safeRepresentationReasonSchema = z14.enum(SAFE_REPRESENTATION_REASONS);
1002
+ var safeRepresentationReasonSchema = z15.enum(SAFE_REPRESENTATION_REASONS);
973
1003
  function canonicalizeFallbackValue(input) {
974
1004
  const fieldType = fieldTypeSchema.parse(input.fieldType);
975
1005
  if (input.safeRepresentationReason !== void 0) {
@@ -1005,10 +1035,10 @@ function createCanonicalFallbackHash(input) {
1005
1035
  const payload = stableJsonStringify(canonical);
1006
1036
  return `sha256:${sha256Hex(payload)}`;
1007
1037
  }
1008
- var linkFallbackSchema = z14.object({
1009
- href: z14.string().trim().min(1),
1010
- label: z14.string().trim().min(1).optional(),
1011
- target: z14.enum(["_self", "_blank"]).optional()
1038
+ var linkFallbackSchema = z15.object({
1039
+ href: z15.string().trim().min(1),
1040
+ label: z15.string().trim().min(1).optional(),
1041
+ target: z15.enum(["_self", "_blank"]).optional()
1012
1042
  }).passthrough();
1013
1043
  function normalizeLineEndings(value) {
1014
1044
  return value.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
@@ -1186,67 +1216,67 @@ var SHA256_CONSTANTS = [
1186
1216
  // ../shared/dist/site-field-contract.js
1187
1217
  var fieldContractVersion = "1.0.0";
1188
1218
  var scannerContractVersion = "1.0.0";
1189
- var siteFieldStatusSchema = z15.enum(["hidden", "active"]);
1190
- var semanticVersionSchema = z15.string().regex(/^\d+\.\d+\.\d+$/u);
1191
- 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.");
1192
- 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.");
1193
- var sourceMappingSchema = z15.object({
1194
- kind: z15.literal("function"),
1219
+ var siteFieldStatusSchema = z16.enum(["hidden", "active"]);
1220
+ var semanticVersionSchema = z16.string().regex(/^\d+\.\d+\.\d+$/u);
1221
+ 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.");
1222
+ 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.");
1223
+ var sourceMappingSchema = z16.object({
1224
+ kind: z16.literal("function"),
1195
1225
  filePath: repositoryRelativePosixPathSchema,
1196
- exportName: z15.string().trim().min(1).optional(),
1197
- sourcePath: z15.string().trim().min(1).optional(),
1226
+ exportName: z16.string().trim().min(1).optional(),
1227
+ sourcePath: z16.string().trim().min(1).optional(),
1198
1228
  editTarget: fieldIdSchema.optional()
1199
1229
  }).strict();
1200
- var domMappingSchema = z15.object({
1201
- attribute: z15.literal("data-siteplane-field-id"),
1202
- previewStrategy: z15.enum(["dom", "event"])
1230
+ var domMappingSchema = z16.object({
1231
+ attribute: z16.literal("data-siteplane-field-id"),
1232
+ previewStrategy: z16.enum(["dom", "event"])
1203
1233
  }).strict();
1204
- var fieldBaseSchema = z15.object({
1234
+ var fieldBaseSchema = z16.object({
1205
1235
  fieldId: fieldIdSchema,
1206
1236
  routeKey: siteFieldRouteKeySchema,
1207
1237
  source: sourceMappingSchema,
1208
1238
  dom: domMappingSchema.optional()
1209
1239
  }).strict();
1210
- var linkFallbackSchema2 = z15.object({
1211
- href: z15.string().trim().min(1),
1212
- label: z15.string().trim().min(1).optional(),
1213
- target: z15.enum(["_self", "_blank"]).optional()
1240
+ var linkFallbackSchema2 = z16.object({
1241
+ href: z16.string().trim().min(1),
1242
+ label: z16.string().trim().min(1).optional(),
1243
+ target: z16.enum(["_self", "_blank"]).optional()
1214
1244
  }).strict();
1215
- var imageFallbackSchema = z15.object({
1216
- src: z15.string().trim().min(1),
1217
- alt: z15.string().trim().max(300),
1218
- width: z15.number().int().positive().optional(),
1219
- height: z15.number().int().positive().optional(),
1220
- crop: z15.object({
1221
- x: z15.number().min(0).max(100),
1222
- y: z15.number().min(0).max(100),
1223
- zoom: z15.number().min(1).max(4),
1224
- aspectRatio: z15.number().positive().max(10)
1245
+ var imageFallbackSchema = z16.object({
1246
+ src: z16.string().trim().min(1),
1247
+ alt: z16.string().trim().max(300),
1248
+ width: z16.number().int().positive().optional(),
1249
+ height: z16.number().int().positive().optional(),
1250
+ crop: z16.object({
1251
+ x: z16.number().min(0).max(100),
1252
+ y: z16.number().min(0).max(100),
1253
+ zoom: z16.number().min(1).max(4),
1254
+ aspectRatio: z16.number().positive().max(10)
1225
1255
  }).strict().optional()
1226
1256
  }).strict();
1227
- var siteFieldContractFieldSchema = z15.discriminatedUnion("fieldType", [
1257
+ var siteFieldContractFieldSchema = z16.discriminatedUnion("fieldType", [
1228
1258
  fieldBaseSchema.extend({
1229
- fieldType: z15.literal("text"),
1230
- fallback: z15.string()
1259
+ fieldType: z16.literal("text"),
1260
+ fallback: z16.string()
1231
1261
  }),
1232
1262
  fieldBaseSchema.extend({
1233
- fieldType: z15.literal("longText"),
1234
- fallback: z15.string()
1263
+ fieldType: z16.literal("longText"),
1264
+ fallback: z16.string()
1235
1265
  }),
1236
1266
  fieldBaseSchema.extend({
1237
- fieldType: z15.literal("link"),
1267
+ fieldType: z16.literal("link"),
1238
1268
  fallback: linkFallbackSchema2
1239
1269
  }),
1240
1270
  fieldBaseSchema.extend({
1241
- fieldType: z15.literal("image"),
1271
+ fieldType: z16.literal("image"),
1242
1272
  fallback: imageFallbackSchema
1243
1273
  })
1244
1274
  ]);
1245
- var siteFieldContractV1Schema = z15.object({
1246
- version: z15.literal(1),
1275
+ var siteFieldContractV1Schema = z16.object({
1276
+ version: z16.literal(1),
1247
1277
  fieldContractVersion: semanticVersionSchema,
1248
1278
  scannerContractVersion: semanticVersionSchema,
1249
- fields: z15.array(siteFieldContractFieldSchema)
1279
+ fields: z16.array(siteFieldContractFieldSchema)
1250
1280
  }).strict().superRefine((contract, context) => {
1251
1281
  const seen = /* @__PURE__ */ new Set();
1252
1282
  for (const [index, field] of contract.fields.entries()) {
@@ -1272,550 +1302,6 @@ function createSiteFieldContractHash(input) {
1272
1302
  return `sha256:${sha256Hex(payload)}`;
1273
1303
  }
1274
1304
 
1275
- // ../shared/dist/site-setup.js
1276
- var SITE_SETUP_RUN_STATUSES = [
1277
- "waiting_for_agent",
1278
- "working",
1279
- "action_required",
1280
- "ready_for_review",
1281
- "completed"
1282
- ];
1283
- var SITE_SETUP_RUN_MODES = ["initial", "update"];
1284
- var SITE_SETUP_ERROR_CODES = [
1285
- "action_required",
1286
- "deployment_evidence_required",
1287
- "field_contract_scan_failed",
1288
- "invalid_editor_definition",
1289
- "invalid_field_contract",
1290
- "missing_build_revision",
1291
- "missing_field_contract",
1292
- "review_locked",
1293
- "stale_deployment_contract",
1294
- "stale_field_contract",
1295
- "stale_setup_review",
1296
- "update_required"
1297
- ];
1298
- var CONTINUE_SITE_SETUP_MAX_ITEMS = 50;
1299
- var CONTINUE_SITE_SETUP_RENDERED_PATH_MAX_BYTES = 512;
1300
- var CONTINUE_SITE_SETUP_VISIBLE_VALUE_MAX_BYTES = 256;
1301
- var CONTINUE_SITE_SETUP_LOCATOR_HINT_MAX_BYTES = 512;
1302
- var CONTINUE_SITE_SETUP_REQUESTED_LABEL_MAX_BYTES = 120;
1303
- var CONTINUE_SITE_SETUP_REQUESTED_SECTION_MAX_BYTES = 120;
1304
- var CONTINUE_SITE_SETUP_REQUESTED_SUBSECTION_MAX_BYTES = 120;
1305
- var SITE_SETUP_OWNER_EDITABILITY_NOTE_MAX_LENGTH = 2e3;
1306
- var SITE_SETUP_OWNER_EDITABILITY_NOTE_MAX_BYTES = 8e3;
1307
- var CONTINUE_SITE_SETUP_ITEMS_MAX_BYTES = 32 * 1024;
1308
- var CONTINUE_SITE_SETUP_HTTP_BODY_MAX_BYTES = 64 * 1024;
1309
- var siteSetupRunStatusSchema = z16.enum(SITE_SETUP_RUN_STATUSES);
1310
- var siteSetupRunModeSchema = z16.enum(SITE_SETUP_RUN_MODES);
1311
- var siteSetupErrorCodeSchema = z16.enum(SITE_SETUP_ERROR_CODES);
1312
- var editorFieldSchema = z16.object({
1313
- fieldId: fieldIdSchema,
1314
- label: z16.string().trim().min(1),
1315
- subsection: z16.string().trim().min(1).optional(),
1316
- description: z16.string().trim().min(1).optional(),
1317
- required: z16.boolean().optional(),
1318
- maxLength: z16.number().int().positive().optional()
1319
- }).strict();
1320
- var editorSectionSchema = z16.object({
1321
- label: z16.string().trim().min(1),
1322
- fields: z16.array(editorFieldSchema).min(1)
1323
- }).strict().superRefine((section, context) => {
1324
- const closedSubsections = /* @__PURE__ */ new Set();
1325
- let currentSubsection;
1326
- for (const [index, field] of section.fields.entries()) {
1327
- if (field.subsection === currentSubsection)
1328
- continue;
1329
- if (currentSubsection)
1330
- closedSubsections.add(currentSubsection);
1331
- currentSubsection = field.subsection;
1332
- if (currentSubsection && closedSubsections.has(currentSubsection)) {
1333
- context.addIssue({
1334
- code: "custom",
1335
- message: `Subgroup fields must stay contiguous: ${currentSubsection}`,
1336
- path: ["fields", index, "subsection"]
1337
- });
1338
- }
1339
- }
1340
- });
1341
- var editorRouteSchema = z16.object({
1342
- routeKey: siteFieldRouteKeySchema,
1343
- 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(),
1344
- label: z16.string().trim().min(1),
1345
- sections: z16.array(editorSectionSchema).min(1)
1346
- }).strict().superRefine((route, context) => {
1347
- if (route.routeKey.includes("[") && !route.previewPath) {
1348
- context.addIssue({
1349
- code: "custom",
1350
- path: ["previewPath"],
1351
- message: "Dynamic editor routes need a previewPath for an existing page; keep the canonical routeKey unchanged."
1352
- });
1353
- }
1354
- const sections = /* @__PURE__ */ new Set();
1355
- for (const [index, section] of route.sections.entries()) {
1356
- if (sections.has(section.label)) {
1357
- context.addIssue({
1358
- code: "custom",
1359
- message: `Duplicate section label: ${section.label}`,
1360
- path: ["sections", index, "label"]
1361
- });
1362
- }
1363
- sections.add(section.label);
1364
- }
1365
- });
1366
- var editorDefinitionV1Schema = z16.object({
1367
- version: z16.literal(1),
1368
- routes: z16.array(editorRouteSchema).min(1)
1369
- }).strict().superRefine((definition, context) => {
1370
- const routes = /* @__PURE__ */ new Set();
1371
- const fields = /* @__PURE__ */ new Set();
1372
- for (const [routeIndex, route] of definition.routes.entries()) {
1373
- if (routes.has(route.routeKey)) {
1374
- context.addIssue({
1375
- code: "custom",
1376
- message: `Duplicate route key: ${route.routeKey}`,
1377
- path: ["routes", routeIndex, "routeKey"]
1378
- });
1379
- }
1380
- routes.add(route.routeKey);
1381
- for (const [sectionIndex, section] of route.sections.entries()) {
1382
- for (const [fieldIndex, field] of section.fields.entries()) {
1383
- if (fields.has(field.fieldId)) {
1384
- context.addIssue({
1385
- code: "custom",
1386
- message: `Duplicate editor field id: ${field.fieldId}`,
1387
- path: [
1388
- "routes",
1389
- routeIndex,
1390
- "sections",
1391
- sectionIndex,
1392
- "fields",
1393
- fieldIndex,
1394
- "fieldId"
1395
- ]
1396
- });
1397
- }
1398
- fields.add(field.fieldId);
1399
- }
1400
- }
1401
- }
1402
- });
1403
- var forbiddenControlOrBidi = /[\u0000-\u001f\u007f-\u009f\u202a-\u202e\u2066-\u2069]/u;
1404
- var forbiddenOwnerNoteControlOrBidi = /[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f-\u009f\u202a-\u202e\u2066-\u2069]/u;
1405
- var unsafeLocator = /<\/?[a-z][^>]*>|\b(?:javascript|data:text\/html)\s*:|\bon[a-z]+\s*=/iu;
1406
- var renderedPathSchema = z16.string().trim().transform((value) => value !== "/" ? value.replace(/\/+$/u, "") : value).superRefine((value, context) => {
1407
- if (!value.startsWith("/") || value === "$global" || value.includes("?") || value.includes("#")) {
1408
- context.addIssue({
1409
- code: "custom",
1410
- message: "renderedPath must be a canonical real path."
1411
- });
1412
- }
1413
- addSafeByteIssues(value, CONTINUE_SITE_SETUP_RENDERED_PATH_MAX_BYTES, "renderedPath", context);
1414
- });
1415
- function normalizedSafeTextSchema(maxBytes, label) {
1416
- return z16.string().transform((value) => value.trim().replace(new RegExp("\\p{White_Space}+", "gu"), " ")).pipe(z16.string().min(1)).superRefine((value, context) => {
1417
- addSafeByteIssues(value, maxBytes, label, context);
1418
- if (label === "locatorHint" && unsafeLocator.test(value)) {
1419
- context.addIssue({
1420
- code: "custom",
1421
- message: "locatorHint contains unsafe markup or executable content."
1422
- });
1423
- }
1424
- });
1425
- }
1426
- var correctionItemBase = {
1427
- renderedPath: renderedPathSchema,
1428
- visibleValue: normalizedSafeTextSchema(CONTINUE_SITE_SETUP_VISIBLE_VALUE_MAX_BYTES, "visibleValue"),
1429
- locatorHint: normalizedSafeTextSchema(CONTINUE_SITE_SETUP_LOCATOR_HINT_MAX_BYTES, "locatorHint"),
1430
- requestedLabel: normalizedSafeTextSchema(CONTINUE_SITE_SETUP_REQUESTED_LABEL_MAX_BYTES, "requestedLabel").optional(),
1431
- requestedSection: normalizedSafeTextSchema(CONTINUE_SITE_SETUP_REQUESTED_SECTION_MAX_BYTES, "requestedSection").optional(),
1432
- requestedSubsection: normalizedSafeTextSchema(CONTINUE_SITE_SETUP_REQUESTED_SUBSECTION_MAX_BYTES, "requestedSubsection").optional(),
1433
- requestedSortOrder: z16.number().int().nonnegative().optional()
1434
- };
1435
- var setupCorrectionItemSchema = z16.discriminatedUnion("kind", [
1436
- z16.object({ kind: z16.literal("text"), ...correctionItemBase }).strict(),
1437
- z16.object({ kind: z16.literal("link"), ...correctionItemBase }).strict(),
1438
- z16.object({ kind: z16.literal("image"), ...correctionItemBase }).strict()
1439
- ]).superRefine((item, context) => {
1440
- if (item.requestedSubsection && !item.requestedSection) {
1441
- context.addIssue({
1442
- code: "custom",
1443
- message: "requestedSubsection requires requestedSection.",
1444
- path: ["requestedSubsection"]
1445
- });
1446
- }
1447
- });
1448
- var setupCorrectionItemsSchema = z16.array(setupCorrectionItemSchema).max(CONTINUE_SITE_SETUP_MAX_ITEMS).superRefine((items, context) => {
1449
- const bytes = utf8Bytes(stableJsonStringify(items));
1450
- if (bytes > CONTINUE_SITE_SETUP_ITEMS_MAX_BYTES) {
1451
- context.addIssue({
1452
- code: "custom",
1453
- message: "Correction items exceed the 32 KiB canonical payload limit."
1454
- });
1455
- }
1456
- });
1457
- var siteSetupOwnerEditabilityNoteSchema = z16.string().max(SITE_SETUP_OWNER_EDITABILITY_NOTE_MAX_LENGTH).superRefine((value, context) => {
1458
- if (utf8Bytes(value) > SITE_SETUP_OWNER_EDITABILITY_NOTE_MAX_BYTES) {
1459
- context.addIssue({
1460
- code: "custom",
1461
- message: `ownerEditabilityNote exceeds ${SITE_SETUP_OWNER_EDITABILITY_NOTE_MAX_BYTES} UTF-8 bytes.`
1462
- });
1463
- }
1464
- if (forbiddenOwnerNoteControlOrBidi.test(value)) {
1465
- context.addIssue({
1466
- code: "custom",
1467
- message: "ownerEditabilityNote contains a forbidden control or bidi character."
1468
- });
1469
- }
1470
- });
1471
- var SITE_SETUP_MODULE_SCOPES = {
1472
- editing: ["setup:read", "setup:write"],
1473
- analytics: [
1474
- "analytics:setup",
1475
- "analytics:sync",
1476
- "analytics:test",
1477
- "analytics:readiness",
1478
- "analytics:agent_instructions",
1479
- "analytics:public_key_read"
1480
- ]
1481
- };
1482
- 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.");
1483
- function siteSetupScopes(modules) {
1484
- return modules.flatMap((module) => [...SITE_SETUP_MODULE_SCOPES[module]]);
1485
- }
1486
- function hasExactSiteSetupScopes(scopes, modules) {
1487
- const matches = (expected) => scopes.length === expected.length && expected.every((scope) => scopes.includes(scope));
1488
- return modules ? matches(siteSetupScopes(modules)) : matches(siteSetupScopes(["editing"])) || matches(siteSetupScopes(["editing", "analytics"]));
1489
- }
1490
- var siteSetupActivityInputSchema = z16.object({
1491
- phase: z16.enum([
1492
- "inspecting",
1493
- "integrating",
1494
- "deploying",
1495
- "verifying",
1496
- "repairing"
1497
- ]),
1498
- textId: z16.enum([
1499
- "inspecting",
1500
- "integrating",
1501
- "deploying",
1502
- "verifying",
1503
- "repairing"
1504
- ])
1505
- }).strict().refine((value) => value.phase === value.textId, "Activity text must describe its phase.");
1506
- var nextActionFields = {
1507
- actor: z16.enum(["agent", "user", "siteplane"]),
1508
- boundary: z16.enum([
1509
- "source",
1510
- "environment",
1511
- "deployment",
1512
- "verification",
1513
- "authorization",
1514
- "review"
1515
- ]),
1516
- precondition: z16.string().min(1).max(1e3),
1517
- instruction: z16.string().min(1).max(2e3),
1518
- expectedEvidence: z16.string().min(1).max(1e3)
1519
- };
1520
- var siteSetupNextActionSchema = z16.discriminatedUnion("kind", [
1521
- z16.object({
1522
- ...nextActionFields,
1523
- kind: z16.literal("run_command"),
1524
- command: z16.string().min(1).max(500)
1525
- }).strict(),
1526
- z16.object({ ...nextActionFields, kind: z16.literal("agent_edit") }).strict(),
1527
- z16.object({ ...nextActionFields, kind: z16.literal("needs_user_action") }).strict(),
1528
- z16.object({ ...nextActionFields, kind: z16.literal("wait") }).strict(),
1529
- z16.object({ ...nextActionFields, kind: z16.literal("done") }).strict()
1530
- ]);
1531
- var siteSetupTaskRunSchema = z16.object({
1532
- runId: z16.string().uuid(),
1533
- mode: siteSetupRunModeSchema,
1534
- status: siteSetupRunStatusSchema,
1535
- fieldContractHash: z16.string().nullable(),
1536
- deploymentOrigin: z16.string().url().nullable(),
1537
- deploymentRevision: z16.string().nullable(),
1538
- publicRuntimeKeyId: z16.string().uuid().nullable(),
1539
- reviewVersion: z16.number().int().positive()
1540
- }).strict();
1541
- var siteSetupTaskProgressSchema = z16.object({
1542
- progressStage: z16.enum([
1543
- "waiting_for_connection",
1544
- "agent_connected",
1545
- "project_context_loaded",
1546
- "fields_prepared",
1547
- "deployment_verification",
1548
- "ready_for_review",
1549
- "action_required",
1550
- "completed"
1551
- ]),
1552
- lastVerifiedAt: z16.string().datetime().nullable(),
1553
- lastActivityAt: z16.string().datetime(),
1554
- activitySource: z16.enum(["user", "server", "agent"]),
1555
- activityPhase: siteSetupActivityInputSchema.shape.phase.nullable(),
1556
- activityTextId: siteSetupActivityInputSchema.shape.textId.nullable()
1557
- }).strict();
1558
- var siteSetupTaskSchema = z16.object({
1559
- contractVersion: z16.literal("siteplane.setup-task.v2"),
1560
- workflow: z16.enum(["initial_setup", "structure_update"]),
1561
- goal: z16.string().min(1),
1562
- modules: siteSetupModulesSchema,
1563
- authorizationVersion: z16.number().int().positive(),
1564
- authorizedScopes: z16.array(z16.string()).min(2),
1565
- site: z16.object({
1566
- siteId: z16.string().uuid(),
1567
- portalPath: z16.string(),
1568
- adminOrigin: z16.string().url()
1569
- }).strict().nullable(),
1570
- run: siteSetupTaskRunSchema.nullable(),
1571
- progress: siteSetupTaskProgressSchema.nullable(),
1572
- deployment: setupDeploymentRecordSchema.nullable(),
1573
- revalidationGeneration: z16.number().int().positive(),
1574
- assignment: z16.enum(["owned", "provisional", "claimed"]),
1575
- deadline: z16.string().datetime().nullable(),
1576
- userInstructions: z16.object({
1577
- text: siteSetupOwnerEditabilityNoteSchema,
1578
- source: z16.literal("user"),
1579
- trust: z16.literal("untrusted")
1580
- }).strict(),
1581
- corrections: setupCorrectionItemsSchema,
1582
- contentSelectionSummary: z16.object({
1583
- text: siteSetupOwnerEditabilityNoteSchema,
1584
- source: z16.literal("agent"),
1585
- trust: z16.literal("untrusted")
1586
- }).strict().nullable(),
1587
- environmentBindings: z16.array(z16.object({
1588
- name: z16.string().regex(/^[A-Z][A-Z0-9_]+$/u),
1589
- source: z16.string().min(1),
1590
- sensitivity: z16.enum(["public", "secret"]),
1591
- usage: z16.enum(["build", "server", "build_and_server"]),
1592
- evidence: z16.string().min(1)
1593
- }).strict()),
1594
- nextAction: siteSetupNextActionSchema,
1595
- error: z16.object({
1596
- code: z16.string().regex(/^[a-z0-9_.]+$/u).max(160),
1597
- boundary: nextActionFields.boundary,
1598
- responsibleActor: nextActionFields.actor,
1599
- retryable: z16.boolean(),
1600
- retryAfter: z16.number().int().nonnegative().nullable(),
1601
- requestId: z16.string().regex(/^[A-Za-z0-9_-]+$/u).max(128)
1602
- }).strict().nullable(),
1603
- packages: siteSetupPackagesSchema,
1604
- communication: z16.object({
1605
- beforeSourceChanges: z16.string().min(1),
1606
- updates: z16.array(z16.string().min(1)).min(1),
1607
- blocker: z16.string().min(1)
1608
- }).strict(),
1609
- discovery: z16.object({
1610
- inspectPublicRoutes: z16.boolean(),
1611
- contentKinds: z16.array(z16.enum(["text", "longText", "link", "image"])).min(1),
1612
- rules: z16.array(z16.string().min(1)).min(1)
1613
- }).strict(),
1614
- steps: z16.array(z16.object({
1615
- id: z16.enum([
1616
- "inspect_repository",
1617
- "install_packages",
1618
- "instrument_fields",
1619
- "apply_contract",
1620
- "deploy_production",
1621
- "verify_deployment"
1622
- ]),
1623
- instruction: z16.string().min(1)
1624
- }).strict()).length(6),
1625
- completion: z16.object({
1626
- verifiedStatus: z16.literal("ready_for_review"),
1627
- instruction: z16.string().min(1)
1628
- }).strict()
1629
- }).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.");
1630
- var canonicalHashSchema = z16.string().regex(/^sha256:[0-9a-f]{64}$/iu);
1631
- var deploymentRevisionSchema = normalizedSafeTextSchema(256, "deploymentRevision");
1632
- var continueSiteSetupInputSchema = z16.object({
1633
- siteId: z16.string().uuid(),
1634
- runId: z16.string().uuid(),
1635
- expectedReviewVersion: z16.number().int().positive(),
1636
- mutationId: z16.string().uuid(),
1637
- intent: z16.enum(["continue_review", "correct_completed_review"]),
1638
- expectedFieldContractHash: canonicalHashSchema,
1639
- expectedDeploymentRevision: deploymentRevisionSchema,
1640
- correctionItems: setupCorrectionItemsSchema,
1641
- ownerEditabilityNote: siteSetupOwnerEditabilityNoteSchema.optional()
1642
- }).strict();
1643
- var saveSiteSetupOwnerNoteInputSchema = z16.object({
1644
- siteId: z16.string().uuid(),
1645
- runId: z16.string().uuid(),
1646
- expectedReviewVersion: z16.number().int().positive(),
1647
- expectedFieldContractHash: canonicalHashSchema,
1648
- expectedDeploymentRevision: deploymentRevisionSchema,
1649
- ownerEditabilityNote: siteSetupOwnerEditabilityNoteSchema
1650
- }).strict();
1651
- var setupReviewPreferenceSelectionSchema = z16.object({
1652
- analyticsMode: z16.enum(["disabled", "session_only"]).nullable(),
1653
- assetTargetType: z16.enum(["repo_static_assets", "siteplane_managed_fallback"]).nullable(),
1654
- assetTargetId: z16.string().uuid().nullable()
1655
- }).strict().refine((value) => value.assetTargetType !== null || value.assetTargetId === null, {
1656
- message: "An asset target requires its delivery type."
1657
- });
1658
- var setupReviewPreferencesSchema = setupReviewPreferenceSelectionSchema.safeExtend({
1659
- managedHostingApproved: z16.boolean()
1660
- });
1661
- var saveSetupReviewPreferencesInputSchema = z16.object({
1662
- siteId: z16.string().uuid(),
1663
- runId: z16.string().uuid(),
1664
- expectedReviewVersion: z16.number().int().positive(),
1665
- preferences: setupReviewPreferenceSelectionSchema
1666
- }).strict();
1667
- var siteSetupContextInputSchema = z16.object({}).strict();
1668
- var siteSetupApplyInputSchema = z16.object({
1669
- fieldContract: siteFieldContractV1Schema,
1670
- editorDefinition: editorDefinitionV1Schema,
1671
- contentSelectionSummary: siteSetupOwnerEditabilityNoteSchema.refine((text) => text.trim().length > 0, "Describe the selected content, important exclusions and any open gaps.")
1672
- }).strict().superRefine((input, context) => {
1673
- const contractRoutesByFieldId = new Map(input.fieldContract.fields.map((field) => [
1674
- field.fieldId,
1675
- field.routeKey
1676
- ]));
1677
- const definitionFieldIds = /* @__PURE__ */ new Set();
1678
- for (const [routeIndex, route] of input.editorDefinition.routes.entries()) {
1679
- for (const [sectionIndex, section] of route.sections.entries()) {
1680
- for (const [fieldIndex, field] of section.fields.entries()) {
1681
- const fieldPath = [
1682
- "editorDefinition",
1683
- "routes",
1684
- routeIndex,
1685
- "sections",
1686
- sectionIndex,
1687
- "fields",
1688
- fieldIndex,
1689
- "fieldId"
1690
- ];
1691
- const contractRouteKey = contractRoutesByFieldId.get(field.fieldId);
1692
- const contractField = input.fieldContract.fields.find((candidate) => candidate.fieldId === field.fieldId);
1693
- definitionFieldIds.add(field.fieldId);
1694
- if (!contractRouteKey) {
1695
- context.addIssue({
1696
- code: "custom",
1697
- message: `Unknown editor field id: ${field.fieldId}`,
1698
- path: fieldPath
1699
- });
1700
- } else if (contractRouteKey !== route.routeKey) {
1701
- context.addIssue({
1702
- code: "custom",
1703
- message: `Editor field ${field.fieldId} must use route ${contractRouteKey}.`,
1704
- path: fieldPath
1705
- });
1706
- } else if (field.maxLength !== void 0 && contractField?.fieldType !== "text" && contractField?.fieldType !== "longText") {
1707
- context.addIssue({
1708
- code: "custom",
1709
- message: `maxLength is not supported for ${contractField?.fieldType ?? "unknown"} fields.`,
1710
- path: [
1711
- "editorDefinition",
1712
- "routes",
1713
- routeIndex,
1714
- "sections",
1715
- sectionIndex,
1716
- "fields",
1717
- fieldIndex,
1718
- "maxLength"
1719
- ]
1720
- });
1721
- }
1722
- }
1723
- }
1724
- }
1725
- for (const field of input.fieldContract.fields) {
1726
- if (!definitionFieldIds.has(field.fieldId)) {
1727
- context.addIssue({
1728
- code: "custom",
1729
- message: `Missing editor field id: ${field.fieldId}`,
1730
- path: ["editorDefinition", "routes"]
1731
- });
1732
- }
1733
- }
1734
- });
1735
- var siteSetupVerifyInputSchema = z16.object({
1736
- deploymentUrl: z16.string().url().refine((value) => value.startsWith("https://")),
1737
- deploymentRevision: deploymentRevisionSchema,
1738
- wait: z16.boolean().optional()
1739
- }).strict();
1740
- var siteSetupEvidenceInputSchema = z16.object({
1741
- siteId: z16.string().uuid(),
1742
- runId: z16.string().uuid(),
1743
- expectedFieldContractHash: canonicalHashSchema,
1744
- expectedDeploymentOrigin: z16.string().url().refine((value) => value.startsWith("https://")),
1745
- expectedDeploymentRevision: deploymentRevisionSchema,
1746
- publicRuntimeKeyId: z16.string().uuid(),
1747
- bridgeSessionId: normalizedSafeTextSchema(256, "bridgeSessionId"),
1748
- observations: z16.array(z16.object({
1749
- fieldId: fieldIdSchema,
1750
- fieldType: fieldTypeSchema,
1751
- routeKey: siteFieldRouteKeySchema,
1752
- renderedPath: renderedPathSchema,
1753
- targetResolved: z16.boolean(),
1754
- previewAck: z16.boolean()
1755
- }).strict().refine((value) => !value.previewAck || value.targetResolved, "Preview ACK requires a resolved target.")).min(1).max(200)
1756
- }).strict();
1757
- var completeSetupReviewInputSchema = z16.object({
1758
- siteId: z16.string().uuid(),
1759
- runId: z16.string().uuid(),
1760
- expectedReviewVersion: z16.number().int().positive(),
1761
- expectedFieldContractHash: canonicalHashSchema,
1762
- expectedDeploymentRevision: deploymentRevisionSchema,
1763
- expectedReadyFingerprint: canonicalHashSchema
1764
- }).strict();
1765
- var activateSiteSetupInputSchema = z16.object({
1766
- siteId: z16.string().uuid(),
1767
- runId: z16.string().uuid(),
1768
- expectedReviewVersion: z16.number().int().positive(),
1769
- expectedSnapshotHash: canonicalHashSchema
1770
- }).strict();
1771
- var refreshSiteSetupDeploymentInputSchema = z16.object({
1772
- siteId: z16.string().uuid(),
1773
- deploymentUrl: z16.string().url().refine((value) => value.startsWith("https://")),
1774
- deploymentRevision: deploymentRevisionSchema
1775
- }).strict();
1776
- function addSafeByteIssues(value, maxBytes, label, context) {
1777
- if (utf8Bytes(value) > maxBytes) {
1778
- context.addIssue({
1779
- code: "custom",
1780
- message: `${label} exceeds ${maxBytes} UTF-8 bytes.`
1781
- });
1782
- }
1783
- if (forbiddenControlOrBidi.test(value)) {
1784
- context.addIssue({
1785
- code: "custom",
1786
- message: `${label} contains a forbidden control or bidi character.`
1787
- });
1788
- }
1789
- }
1790
- function utf8Bytes(value) {
1791
- return new TextEncoder().encode(value).byteLength;
1792
- }
1793
- var setupActivationApprovalSchema = z16.object({
1794
- reviewVersion: z16.number().int().positive(),
1795
- snapshotHash: canonicalHashSchema,
1796
- analytics: z16.object({
1797
- status: z16.enum(["active", "skipped"]),
1798
- reviewVersion: z16.number().int().positive(),
1799
- generation: z16.number().int().nonnegative()
1800
- }).optional()
1801
- });
1802
- var activateSetupModulesInputSchema = activateSiteSetupInputSchema.extend({
1803
- analytics: z16.discriminatedUnion("decision", [
1804
- z16.object({ decision: z16.literal("pending") }).strict(),
1805
- z16.object({
1806
- decision: z16.literal("enable"),
1807
- readinessTestRunId: z16.string().regex(/^analytics_owner_[0-9a-f-]{36}$/u),
1808
- expectedInstallationGeneration: z16.number().int().positive(),
1809
- measurementApproved: z16.literal(true)
1810
- }).strict(),
1811
- z16.object({
1812
- decision: z16.literal("skip"),
1813
- expectedInstallationGeneration: z16.number().int().nonnegative(),
1814
- continueWithoutAnalytics: z16.literal(true)
1815
- }).strict()
1816
- ])
1817
- }).strict();
1818
-
1819
1305
  // ../shared/dist/bridge-protocol.js
1820
1306
  var BRIDGE_PROTOCOL_VERSION = 2;
1821
1307
  var bridgeRectSchema = z17.object({
@@ -1874,18 +1360,6 @@ var fieldBridgeIdentitySchema = z17.object({
1874
1360
  fieldContractHash: canonicalFieldContractHashSchema,
1875
1361
  deploymentRevision: z17.string().trim().min(1).max(256)
1876
1362
  }).strict();
1877
- var setupPreviewAccessSchema = z17.object({
1878
- capability: z17.string().regex(/^v1\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]{43}$/u).max(4096),
1879
- expiresAt: z17.string().datetime()
1880
- }).strict();
1881
- var setupPreviewReadSchema = fieldBridgeIdentitySchema.extend({
1882
- scope: z17.literal("setup_preview"),
1883
- siteId: z17.string().uuid(),
1884
- runId: z17.string().uuid(),
1885
- bridgeSessionId: z17.string().min(1),
1886
- expiresAt: z17.string().datetime(),
1887
- contract: siteFieldContractV1Schema
1888
- }).strict();
1889
1363
  var fieldBridgeBaseSchema = z17.object({
1890
1364
  version: z17.literal(BRIDGE_PROTOCOL_VERSION),
1891
1365
  type: z17.enum(FIELD_BRIDGE_MESSAGE_TYPES),
@@ -1913,8 +1387,7 @@ var fieldBridgeInitMessageSchema = fieldBridgeBaseSchema.extend({
1913
1387
  payload: z17.object({
1914
1388
  adminOrigin: z17.string().url(),
1915
1389
  customerOrigin: z17.string().url(),
1916
- renderedPath: realRenderedPathSchema,
1917
- setupPreview: setupPreviewAccessSchema.optional()
1390
+ renderedPath: realRenderedPathSchema
1918
1391
  }).strict()
1919
1392
  });
1920
1393
  var fieldBridgeReadyMessageSchema = fieldBridgeBaseSchema.extend({
@@ -1927,7 +1400,7 @@ var fieldBridgeReadyMessageSchema = fieldBridgeBaseSchema.extend({
1927
1400
  z17.literal("preview_values"),
1928
1401
  z17.literal("field_evidence"),
1929
1402
  z17.literal("visual_field_control")
1930
- ]).rest(z17.enum(["analytics_preview_readiness", "setup_preview"])).refine((capabilities) => capabilities.length <= 6)
1403
+ ]).rest(z17.enum(["analytics_preview_readiness"])).refine((capabilities) => capabilities.length <= 5)
1931
1404
  }).strict()
1932
1405
  });
1933
1406
  var fieldBridgeFieldsMessageSchema = fieldBridgeBaseSchema.extend({
@@ -2003,7 +1476,7 @@ var fieldBridgeMissingContentMessageSchema = fieldBridgeBaseSchema.extend({
2003
1476
  type: z17.literal("siteplane:field-bridge:missing-content"),
2004
1477
  payload: z17.object({
2005
1478
  action: fieldBridgeMissingContentActionSchema,
2006
- item: setupCorrectionItemSchema,
1479
+ item: missingContentItemSchema,
2007
1480
  suggestedSection: bridgeSectionSchema.optional()
2008
1481
  }).strict()
2009
1482
  });
@@ -2164,12 +1637,7 @@ var updateEditorOrganizationInputSchema = z21.discriminatedUnion("operation", [
2164
1637
  routeKey: siteFieldRouteKeySchema.refine((value) => value !== "$global", "Global content has no page label."),
2165
1638
  label: labelSchema
2166
1639
  })
2167
- ]).and(z21.object({
2168
- review: z21.object({
2169
- runId: z21.string().uuid(),
2170
- expectedReviewVersion: z21.number().int().positive()
2171
- }).strict().optional()
2172
- })).superRefine((input, context) => {
1640
+ ]).superRefine((input, context) => {
2173
1641
  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) {
2174
1642
  context.addIssue({
2175
1643
  code: "custom",
@@ -2252,9 +1720,6 @@ var EARLY_ACCESS_PLAN = {
2252
1720
  bookingRemindersEnabled: true
2253
1721
  };
2254
1722
 
2255
- // ../shared/dist/first-party-image-upload.js
2256
- var maxFirstPartyImageUploadBytes = 4 * 1024 * 1024;
2257
-
2258
1723
  // ../shared/dist/readiness.js
2259
1724
  import { z as z24 } from "zod";
2260
1725
  var READINESS_CHECK_KEYS = [
@@ -2276,244 +1741,82 @@ var readinessStatusSchema = z24.enum(READINESS_STATUSES);
2276
1741
 
2277
1742
  // ../shared/dist/site.js
2278
1743
  import { z as z25 } from "zod";
2279
- var SITE_STATUSES = [
2280
- "setup",
2281
- "active",
2282
- "disabled",
2283
- "archived"
2284
- ];
1744
+ var SITE_STATUSES = ["active", "disabled", "archived"];
2285
1745
  var siteStatusSchema = z25.enum(SITE_STATUSES);
2286
1746
  var websiteUrlSchema = z25.string().trim().url().refine((value) => value.startsWith("https://") || value.startsWith("http://"), "Website URL must use http or https");
2287
1747
 
2288
- // ../shared/dist/setup-assets.js
1748
+ // ../shared/dist/field-sync.js
2289
1749
  import { z as z26 } from "zod";
2290
- var configureSetupAssetTargetInputSchema = z26.object({
2291
- siteId: z26.string().uuid(),
2292
- runId: z26.string().uuid(),
2293
- expectedReviewVersion: z26.number().int().positive(),
2294
- expectedSnapshotHash: z26.string().regex(/^sha256:[0-9a-f]{64}$/u),
2295
- mutationId: z26.string().uuid(),
2296
- expectedApprovalId: z26.string().uuid().nullable(),
2297
- targetId: z26.string().uuid().nullable(),
2298
- targetType: z26.enum(["repo_static_assets", "siteplane_managed_fallback"]),
2299
- approveManagedHosting: z26.boolean()
2300
- }).strict().refine((value) => value.targetType === "siteplane_managed_fallback" || !value.approveManagedHosting);
2301
- var setupAssetTargetApprovalSchema = z26.object({
2302
- id: z26.string().uuid(),
2303
- runId: z26.string().uuid(),
2304
- reviewVersion: z26.number().int().positive(),
2305
- snapshotHash: z26.string().regex(/^sha256:[0-9a-f]{64}$/u),
2306
- targetId: z26.string().uuid(),
2307
- targetType: z26.enum(["repo_static_assets", "siteplane_managed_fallback"]),
2308
- targetRevision: z26.number().int().positive(),
2309
- deploymentOrigin: z26.string().url(),
2310
- gitConnectionId: z26.string().uuid().nullable(),
2311
- gitRevision: z26.number().int().positive().nullable(),
2312
- managedHostingApproved: z26.boolean(),
2313
- actorUserId: z26.string().uuid(),
2314
- approvedAt: z26.string().datetime({ offset: true })
2315
- }).strict();
2316
- var setupAssetReadinessSchema = z26.union([
2317
- z26.object({
2318
- status: z26.enum([
2319
- "not_required",
2320
- "needs_choice",
2321
- "stale_setup_review",
2322
- "permission_denied"
2323
- ])
2324
- }).strict(),
2325
- z26.object({
2326
- status: z26.literal("stale_approval"),
2327
- approval: setupAssetTargetApprovalSchema.optional()
2328
- }).strict(),
1750
+ var FIELD_SYNC_MAX_FIELDS = 2e3;
1751
+ 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.");
1752
+ var fieldBase = {
1753
+ id: fieldIdSchema.max(160),
1754
+ file: filePathSchema,
1755
+ label: z26.string().trim().min(1).max(120).optional()
1756
+ };
1757
+ var fieldSyncFieldSchema = z26.discriminatedUnion("type", [
1758
+ z26.object({ ...fieldBase, type: z26.literal("text"), fallback: z26.string().max(256) }).strict(),
1759
+ z26.object({ ...fieldBase, type: z26.literal("longText"), fallback: z26.string().max(5e4) }).strict(),
2329
1760
  z26.object({
2330
- status: z26.literal("not_verified"),
2331
- approval: setupAssetTargetApprovalSchema,
2332
- jobId: z26.string().uuid().optional(),
2333
- checkedAt: z26.string().datetime({ offset: true }).nullable().optional()
1761
+ ...fieldBase,
1762
+ type: z26.literal("link"),
1763
+ fallback: z26.object({ href: z26.string().min(1).max(2048), label: z26.string().max(256) }).strict()
2334
1764
  }).strict(),
2335
1765
  z26.object({
2336
- status: z26.enum(["ready", "checking", "retrying"]),
2337
- approval: setupAssetTargetApprovalSchema,
2338
- jobId: z26.string().uuid(),
2339
- checkedAt: z26.string().datetime({ offset: true }).nullable()
2340
- }).strict().refine((value) => value.status !== "ready" || value.checkedAt !== null)
2341
- ]);
2342
- var checkSetupAssetTargetInputSchema = z26.object({
2343
- siteId: z26.string().uuid(),
2344
- runId: z26.string().uuid(),
2345
- approvalId: z26.string().uuid(),
2346
- intent: z26.enum(["start", "poll"])
2347
- }).strict();
2348
-
2349
- // ../shared/dist/setup-installation.js
2350
- import { z as z27 } from "zod";
2351
- var setupInstallationRequestSchema = z27.object({
2352
- modules: siteSetupModulesSchema,
2353
- ownerEditabilityNote: siteSetupOwnerEditabilityNoteSchema,
2354
- provider: z27.object({
2355
- projectId: z27.string().min(1).max(200),
2356
- teamId: z27.string().min(1).max(200)
1766
+ ...fieldBase,
1767
+ type: z26.literal("image"),
1768
+ fallback: z26.object({ src: z26.string().min(1).max(2048), alt: z26.string().max(300) }).strict()
2357
1769
  }).strict()
2358
- }).strict();
2359
-
2360
- // ../shared/dist/setup-claim.js
2361
- import { z as z28 } from "zod";
2362
- var setupClaimCodeSchema = z28.string().regex(/^[0-9A-HJKMNP-TV-Z]{8}$/u);
2363
- var setupClaimBindingSchema = z28.object({
2364
- siteId: z28.string().uuid(),
2365
- runId: z28.string().uuid()
2366
- });
2367
- var setupClaimReceiptSchema = setupClaimBindingSchema.extend({
2368
- status: z28.literal("claimed"),
2369
- requestId: z28.string().uuid(),
2370
- workspaceId: z28.string().uuid(),
2371
- userId: z28.string().uuid(),
2372
- claimedAt: z28.string().datetime({ offset: true })
2373
- }).strict();
2374
- var setupClaimInspectionSchema = setupClaimBindingSchema.extend({
2375
- status: z28.literal("pending"),
2376
- requestId: z28.string().uuid(),
2377
- siteName: z28.string(),
2378
- userId: z28.string().uuid(),
2379
- accountEmail: z28.string().email(),
2380
- workspaceId: z28.string().uuid(),
2381
- workspaceName: z28.string(),
2382
- expiresAt: z28.string().datetime({ offset: true })
2383
- }).strict();
2384
- var setupClaimDenialSchema = z28.object({
2385
- status: z28.enum([
2386
- "invalid_claim_request",
2387
- "invalid_installation",
2388
- "already_claimed",
2389
- "project_expired",
2390
- "invalid_guest_session",
2391
- "stale_setup_review",
2392
- "verified_account_required",
2393
- "workspace_access_denied",
2394
- "workspace_entitlement_required",
2395
- "site_limit_reached",
2396
- "provisional_relationship_conflict",
2397
- "rate_limited"
2398
- ])
2399
- }).strict();
2400
-
2401
- // ../cli/dist/analytics/static-scan.js
2402
- import ts from "typescript";
2403
-
2404
- // ../cli/dist/booking/manifest.js
2405
- import { mkdir as mkdir2, readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
2406
- import { dirname as dirname2 } from "path";
2407
-
2408
- // ../cli/dist/booking/static-scan.js
2409
- import ts2 from "typescript";
2410
-
2411
- // ../cli/dist/commands/analytics/check.js
2412
- import { readFile as readFile3 } from "fs/promises";
2413
-
2414
- // ../cli/dist/commands/analytics/init.js
2415
- import { mkdir as mkdir3, writeFile as writeFile3 } from "fs/promises";
2416
- import { dirname as dirname3, join } from "path";
2417
- var analyticsRulesTemplate = `# Siteplane Analytics Rules
2418
-
2419
- Analytics contract version: ${ANALYTICS_CONTRACT_VERSION}
2420
- Analytics contract hash: ${ANALYTICS_CONTRACT_HASH}
2421
-
2422
- - Do not change visible layout, copy, styling, animation or business logic while adding analytics.
2423
- - Use stable data-siteplane-target-id values that do not depend on visible copy.
2424
- - Use public site keys only through environment references.
2425
- - Do not write secret analytics keys, setup tokens or project CLI tokens into source files.
2426
- - 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.
2427
- - 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.
2428
- - 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.
2429
- - Suppress editor-preview traffic from live analytics.
2430
- - Run npx siteplane analytics check, npx siteplane analytics sync and npx siteplane analytics test after setup.
2431
- `;
2432
- var analyticsCursorRulesTemplate = `---
2433
- description: Siteplane Analytics rules
2434
- alwaysApply: true
2435
- ---
2436
-
2437
- ${analyticsRulesTemplate}`;
2438
-
2439
- // ../cli/dist/commands/analytics/import.js
2440
- import { createHash } from "crypto";
1770
+ ]);
1771
+ var fieldSyncRequestSchema = z26.object({ fields: z26.array(fieldSyncFieldSchema).max(FIELD_SYNC_MAX_FIELDS) }).strict();
1772
+
1773
+ // ../shared/dist/signing-keys.js
1774
+ var pkcs8Ed25519Prefix = Uint8Array.from([
1775
+ 48,
1776
+ 46,
1777
+ 2,
1778
+ 1,
1779
+ 0,
1780
+ 48,
1781
+ 5,
1782
+ 6,
1783
+ 3,
1784
+ 43,
1785
+ 101,
1786
+ 112,
1787
+ 4,
1788
+ 34,
1789
+ 4,
1790
+ 32
1791
+ ]);
2441
1792
 
2442
- // ../cli/dist/commands/analytics/sync.js
2443
- function createAnalyticsCliRequestHeaders(config) {
2444
- const headers = {
2445
- authorization: `Bearer ${config.accessToken}`,
2446
- "content-type": "application/json"
2447
- };
2448
- const bypassSecret = config.vercelAutomationBypassSecret?.trim();
2449
- if (bypassSecret) {
2450
- headers["x-vercel-protection-bypass"] = bypassSecret;
2451
- }
2452
- return headers;
1793
+ // ../shared/dist/preview-token.js
1794
+ var PREVIEW_TOKEN_MAX_SECONDS = 60 * 60;
1795
+ var header = encodeJson({ alg: "EdDSA", typ: "JWT" });
1796
+ function encodeJson(value) {
1797
+ return toBase64Url(new TextEncoder().encode(JSON.stringify(value)));
2453
1798
  }
2454
-
2455
- // ../cli/dist/commands/analytics/public-key.js
2456
- import { z as z29 } from "zod";
2457
- var responseSchema = z29.object({
2458
- ok: z29.literal(true),
2459
- data: z29.object({
2460
- rawPublicKey: z29.string().regex(/^pk_siteplane_[A-Za-z0-9_-]{16}_[A-Za-z0-9_-]{43}$/)
2461
- })
2462
- });
2463
- var errorResponseSchema = z29.object({
2464
- error: z29.object({
2465
- code: z29.string().regex(/^[a-z][a-z0-9_.-]+$/u)
2466
- })
2467
- });
2468
- async function analyticsPublicKeyCommand(input) {
2469
- const fetcher = input.fetchImpl ?? fetch;
2470
- const response = await fetcher(`${input.config.apiBaseUrl.replace(/\/$/u, "")}/api/cli/analytics/public-key`, {
2471
- method: "POST",
2472
- redirect: "error",
2473
- signal: AbortSignal.timeout(2e4),
2474
- headers: createAnalyticsCliRequestHeaders(input.config),
2475
- body: JSON.stringify({ siteId: input.config.siteId })
2476
- });
2477
- const payload = await response.json().catch(() => null);
2478
- const parsed = responseSchema.safeParse(payload);
2479
- if (!response.ok || !parsed.success) {
2480
- const error = errorResponseSchema.safeParse(payload);
2481
- throw new Error(`${error.success ? error.data.error.code : "analytics_public_key.invalid_response"}: Unable to read the active Analytics public key.`);
2482
- }
2483
- return parsed.data.data.rawPublicKey;
1799
+ function toBase64Url(bytes) {
1800
+ let binary = "";
1801
+ for (const byte of bytes)
1802
+ binary += String.fromCharCode(byte);
1803
+ return btoa(binary).replace(/\+/gu, "-").replace(/\//gu, "_").replace(/=+$/u, "");
2484
1804
  }
2485
1805
 
2486
- // ../cli/dist/commands/analytics/prepare.js
2487
- import { z as z30 } from "zod";
2488
- var resultSchema = z30.object({
2489
- ok: z30.literal(true),
2490
- data: z30.object({
2491
- rawPublicKey: z30.string().regex(/^pk_siteplane_[A-Za-z0-9_-]{16}_[A-Za-z0-9_-]{43}$/u),
2492
- generation: z30.number().int().positive(),
2493
- status: z30.enum([
2494
- "setup_started",
2495
- "test_mode",
2496
- "active",
2497
- "paused",
2498
- "error",
2499
- "deleting"
2500
- ])
2501
- }).strict()
2502
- }).strict();
2503
- var errorSchema = z30.object({
2504
- error: z30.object({ code: z30.string().regex(/^[a-z][a-z0-9_.-]+$/u) })
2505
- });
1806
+ // ../shared/dist/webhook-signature.js
1807
+ var WEBHOOK_TOLERANCE_SECONDS = 5 * 60;
1808
+ var encoder = new TextEncoder();
2506
1809
 
2507
- // ../cli/dist/commands/analytics/test.js
2508
- import { randomUUID } from "crypto";
1810
+ // ../cli/dist/booking/static-scan.js
1811
+ import ts from "typescript";
2509
1812
 
2510
1813
  // ../cli/dist/commands/booking/check.js
2511
- import { dirname as dirname4, join as join2 } from "path";
2512
- import { access, readFile as readFile4 } from "fs/promises";
1814
+ import { dirname as dirname2, join } from "path";
1815
+ import { access, readFile as readFile2 } from "fs/promises";
2513
1816
 
2514
1817
  // ../cli/dist/commands/booking/init.js
2515
- import { mkdir as mkdir4, writeFile as writeFile4 } from "fs/promises";
2516
- import { dirname as dirname5, join as join3 } from "path";
1818
+ import { mkdir as mkdir2, writeFile as writeFile2 } from "fs/promises";
1819
+ import { dirname as dirname3, join as join2 } from "path";
2517
1820
  var bookingRulesTemplate = `# Siteplane Booking Rules
2518
1821
 
2519
1822
  - Do not change layout, copy, styling, animation or business logic while adding Booking.
@@ -2524,6 +1827,7 @@ var bookingRulesTemplate = `# Siteplane Booking Rules
2524
1827
  - Preserve customer CSP and middleware; explain required Siteplane/Stripe permissions and exclude /booking from customer middleware.
2525
1828
  - Do not write setup tokens, project CLI tokens or private keys into source files.
2526
1829
  - Run npx siteplane booking check, npx siteplane booking sync and npx siteplane booking test after setup.
1830
+ - 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.
2527
1831
  - booking test stays in test_mode; live booking only starts after explicit dashboard activation.
2528
1832
  `;
2529
1833
  var bookingCursorRulesTemplate = `---
@@ -2533,602 +1837,9 @@ alwaysApply: true
2533
1837
 
2534
1838
  ${bookingRulesTemplate}`;
2535
1839
 
2536
- // ../cli/dist/config/project-config.js
2537
- import { access as access2, chmod, open, readFile as readFile5, rename, rm } from "fs/promises";
2538
- import { randomUUID as randomUUID2 } from "crypto";
2539
- import { join as join4 } from "path";
2540
- import { z as z31 } from "zod";
2541
- var siteplaneProjectConfigSchema = z31.object({
2542
- version: z31.literal(2),
2543
- apiBaseUrl: z31.string().url(),
2544
- siteId: z31.string().uuid(),
2545
- publicSiteKeyId: z31.string().uuid(),
2546
- publicSiteKey: z31.string().trim().min(1),
2547
- runId: z31.string().uuid(),
2548
- appDirectory: z31.string().min(1),
2549
- taskContractVersion: z31.literal("siteplane.setup-task.v2"),
2550
- adminProtocolVersion: z31.literal(2),
2551
- packages: siteSetupPackagesSchema,
2552
- fieldContractHash: z31.string().regex(/^sha256:[0-9a-f]{64}$/iu).optional()
2553
- }).strict();
2554
- async function readProjectConfig(projectDir) {
2555
- return siteplaneProjectConfigSchema.parse(JSON.parse(await readFile5(join4(projectDir, "siteplane.config.json"), "utf8")));
2556
- }
2557
-
2558
- // ../cli/dist/config/credentials.js
2559
- import { execFile } from "child_process";
2560
- import { randomUUID as randomUUID3 } from "crypto";
2561
- import { chmod as chmod2, lstat, mkdir as mkdir5, open as open2, readFile as readFile6, rename as rename2, rm as rm2 } from "fs/promises";
2562
- import { dirname as dirname6, join as join5, relative } from "path";
2563
- import { promisify } from "util";
2564
- import { z as z32 } from "zod";
2565
- var localSetupInstallationSchema = z32.object({
2566
- key: z32.string().regex(/^[A-Za-z0-9_-]{43}$/u),
2567
- idempotencyKey: z32.string().uuid(),
2568
- apiBaseUrl: z32.string().url(),
2569
- request: setupInstallationRequestSchema,
2570
- bootstrapAcknowledged: z32.boolean()
2571
- }).strict();
2572
- var siteplaneCredentialsSchema = z32.object({
2573
- accessToken: z32.string().trim().min(1),
2574
- siteRevalidationSecret: z32.string().trim().min(1),
2575
- installation: localSetupInstallationSchema.optional(),
2576
- claimReceipt: setupClaimReceiptSchema.optional(),
2577
- adminSession: z32.object({
2578
- secret: z32.string().regex(/^[A-Za-z0-9_-]{43}$/u),
2579
- generation: z32.string().uuid()
2580
- }).strict().optional()
2581
- }).strict();
2582
- var localSetupCredentialsSchema = z32.union([
2583
- siteplaneCredentialsSchema,
2584
- z32.object({ installation: localSetupInstallationSchema }).strict()
2585
- ]);
2586
- async function assertLocalCredentialsPathSafe(projectDir, options = {}) {
2587
- const path = join5(projectDir, ".siteplane/credentials.json");
2588
- await assertCredentialFilesystemSafe(projectDir);
2589
- const isTrackedFile = options.isTrackedFile ?? ((targetPath) => gitPathMatches(projectDir, targetPath, "ls-files"));
2590
- const isIgnoredFile = options.isIgnoredFile ?? ((targetPath) => gitPathMatches(projectDir, targetPath, "check-ignore"));
2591
- if (await isTrackedFile(path)) {
2592
- throw new Error("Refusing to write Siteplane credentials into a tracked file.");
2593
- }
2594
- if (!await isIgnoredFile(path)) {
2595
- throw new Error("Add .siteplane/credentials.json to .gitignore before running Siteplane init.");
2596
- }
2597
- return path;
2598
- }
2599
- async function assertCredentialFilesystemSafe(projectDir) {
2600
- for (const [path, directory, mode] of [
2601
- [projectDir, true, null],
2602
- [join5(projectDir, ".siteplane"), true, 448],
2603
- [join5(projectDir, ".siteplane/credentials.json"), false, 384]
2604
- ]) {
2605
- const stat = await lstat(path).catch((error) => {
2606
- if (error.code === "ENOENT")
2607
- return null;
2608
- throw error;
2609
- });
2610
- if (!stat)
2611
- continue;
2612
- if (stat.isSymbolicLink() || (directory ? !stat.isDirectory() : !stat.isFile())) {
2613
- throw new Error("Siteplane credential paths must not contain symlinks or unexpected file types.");
2614
- }
2615
- if (mode !== null && (stat.mode & 511) !== mode) {
2616
- throw new Error(`Siteplane credential ${directory ? "directory" : "file"} permissions must be ${mode.toString(8)} before setup.`);
2617
- }
2618
- }
2619
- }
2620
- async function readLocalCredentials(projectDir) {
2621
- const credentials = await readLocalSetupCredentials(projectDir);
2622
- if (!("accessToken" in credentials)) {
2623
- throw new Error("setup_exchange_pending: Run siteplane setup start to finish the stored installation exchange.");
2624
- }
2625
- return credentials;
2626
- }
2627
- async function readLocalSetupCredentials(projectDir) {
2628
- await assertCredentialFilesystemSafe(projectDir);
2629
- return localSetupCredentialsSchema.parse(JSON.parse(await readFile6(join5(projectDir, ".siteplane/credentials.json"), "utf8")));
2630
- }
2631
- var execFileAsync = promisify(execFile);
2632
- async function gitPathMatches(projectDir, path, command) {
2633
- const args = command === "check-ignore" ? ["check-ignore", "--quiet", relative(projectDir, path)] : ["ls-files", "--error-unmatch", relative(projectDir, path)];
2634
- try {
2635
- await execFileAsync("git", args, { cwd: projectDir });
2636
- return true;
2637
- } catch {
2638
- return false;
2639
- }
2640
- }
2641
-
2642
- // ../cli/dist/commands/init.js
2643
- import { access as access4 } from "fs/promises";
2644
- import { join as join8, relative as relative3 } from "path";
2645
- import { z as z35 } from "zod";
2646
-
2647
- // ../cli/dist/commands/setup-preflight.js
2648
- import { createHash as createHash2 } from "crypto";
2649
- import semver from "semver";
2650
- import { minimatch } from "minimatch";
2651
- import { parse as parseYaml } from "yaml";
2652
-
2653
- // ../cli/dist/config/installed-package.js
2654
- import { createRequire } from "module";
2655
- import { readFile as readFile7 } from "fs/promises";
2656
- import { join as join6 } from "path";
2657
- import { z as z33 } from "zod";
2658
- var packageSchema = z33.object({
2659
- name: z33.string().optional(),
2660
- version: z33.string(),
2661
- peerDependencies: z33.record(z33.string(), z33.string()).optional()
2662
- });
2663
- async function readInstalledPackage(projectDir, name2) {
2664
- const require2 = createRequire(join6(projectDir, "package.json"));
2665
- for (const directory of require2.resolve.paths(name2) ?? []) {
2666
- try {
2667
- return packageSchema.parse(JSON.parse(await readFile7(join6(directory, name2, "package.json"), "utf8")));
2668
- } catch (error) {
2669
- if (error.code !== "ENOENT")
2670
- throw error;
2671
- }
2672
- }
2673
- throw new Error(`Install ${name2} with the canonical package manager before setup.`);
2674
- }
2675
-
2676
- // ../cli/dist/commands/setup-preflight.js
2677
- import { access as access3, readFile as readFile8, realpath, readdir, readlink } from "fs/promises";
2678
- import { dirname as dirname7, join as join7, relative as relative2, resolve, sep } from "path";
2679
- import { z as z34 } from "zod";
2680
-
2681
- // ../cli/dist/commands/setup-process.js
2682
- import { spawn } from "child_process";
2683
- var SetupFailure = class extends Error {
2684
- code;
2685
- constructor(code, message) {
2686
- super(message);
2687
- this.code = code;
2688
- }
2689
- };
2690
- async function setupProcess(binary, args, options) {
2691
- return new Promise((resolve5, reject) => {
2692
- const child = spawn(binary, args, {
2693
- cwd: options.cwd,
2694
- env: process.env,
2695
- stdio: ["pipe", "pipe", "pipe"]
2696
- });
2697
- const chunks = [];
2698
- const errors = [];
2699
- let errorBytes = 0;
2700
- let bytes = 0;
2701
- let exceeded = false;
2702
- const timer = setTimeout(() => {
2703
- exceeded = true;
2704
- child.kill("SIGKILL");
2705
- }, options.timeoutMs ?? 12e4);
2706
- const capture = (chunk) => {
2707
- bytes += chunk.length;
2708
- if (bytes > 4 * 1024 * 1024) {
2709
- exceeded = true;
2710
- child.kill("SIGKILL");
2711
- } else
2712
- chunks.push(chunk);
2713
- };
2714
- child.stdout.on("data", capture);
2715
- child.stderr.on("data", (chunk) => {
2716
- errorBytes += chunk.length;
2717
- if (errorBytes <= 4 * 1024 * 1024)
2718
- errors.push(chunk);
2719
- else {
2720
- exceeded = true;
2721
- child.kill("SIGKILL");
2722
- }
2723
- });
2724
- child.on("error", () => {
2725
- clearTimeout(timer);
2726
- reject(new SetupFailure("local_tool_unavailable", `${binary} could not be started. Check the local installation and access.`));
2727
- });
2728
- child.on("close", (code) => {
2729
- clearTimeout(timer);
2730
- if (exceeded)
2731
- reject(new SetupFailure("provider_timeout", "The operation exceeded its time or response limit; inspect the existing operation before retrying."));
2732
- else if (code !== 0) {
2733
- const diagnostic = Buffer.concat([...chunks, ...errors]).toString("utf8");
2734
- if (/\b(?:401|403|unauthorized|forbidden|not authenticated|not authorized|login required|E401|E403)\b/iu.test(diagnostic))
2735
- reject(new SetupFailure("provider_access_denied", `${binary} denied access. Restore the existing local login and project/package permissions before retrying.`));
2736
- else if (/\b(?:ECONNRESET|ETIMEDOUT|ENOTFOUND|EAI_AGAIN|ECONNREFUSED|429|502|503|504)\b/iu.test(diagnostic))
2737
- reject(new SetupFailure("provider_transport_failed", `${binary} could not reach its provider. Inspect the existing operation before retrying.`));
2738
- else
2739
- reject(new SetupFailure("local_command_failed", `${binary} failed. Check its local login, permissions and project configuration.`));
2740
- } else
2741
- resolve5(Buffer.concat(options.includeStderr ? [...chunks, ...errors] : chunks).toString("utf8"));
2742
- });
2743
- child.stdin.on("error", () => {
2744
- });
2745
- child.stdin.end(options.input);
2746
- });
2747
- }
2748
- async function setupVercelApi(cwd, endpoint, body, method, options) {
2749
- const args = ["api", endpoint, "--raw"];
2750
- if (body !== void 0)
2751
- args.push("--method", method ?? "POST", "--input", "-");
2752
- else if (method)
2753
- args.push("--method", method);
2754
- let output = "";
2755
- for (let attempt = 0; attempt < 3; attempt++) {
2756
- const remaining = (options?.deadline ?? Date.now() + 3e4) - Date.now();
2757
- if (remaining <= 0)
2758
- throw new SetupFailure("provider_deadline_exceeded", "The provider deadline expired; inspect the recorded operation before continuing.");
2759
- try {
2760
- output = await setupProcess("vercel", args, {
2761
- cwd,
2762
- timeoutMs: Math.min(3e4, remaining),
2763
- ...body === void 0 ? {} : { input: JSON.stringify(body) }
2764
- });
2765
- break;
2766
- } catch (error) {
2767
- if (!(error instanceof SetupFailure) || error.code !== "provider_transport_failed" || attempt === 2)
2768
- throw error;
2769
- await new Promise((resolve5) => setTimeout(resolve5, Math.min(1e3 * 2 ** attempt, Math.max(0, (options?.deadline ?? Date.now() + 2e3) - Date.now()))));
2770
- }
2771
- }
2772
- try {
2773
- return JSON.parse(output);
2774
- } catch {
2775
- throw new SetupFailure("invalid_provider_response", "Vercel did not return valid JSON for the bound project.");
2776
- }
2777
- }
2778
-
2779
- // ../cli/dist/commands/setup-preflight.js
2780
- var manifestSchema = z34.object({
2781
- packageManager: z34.string().optional(),
2782
- engines: z34.object({ node: z34.string().optional() }).optional(),
2783
- dependencies: z34.record(z34.string(), z34.string()).optional(),
2784
- devDependencies: z34.record(z34.string(), z34.string()).optional(),
2785
- scripts: z34.record(z34.string(), z34.string()).optional(),
2786
- workspaces: z34.unknown().optional()
2787
- });
2788
- var vercelProjectSchema = z34.object({
2789
- id: z34.string(),
2790
- accountId: z34.string(),
2791
- name: z34.string(),
2792
- nodeVersion: z34.string().nullable().optional(),
2793
- rootDirectory: z34.string().nullable().optional(),
2794
- framework: z34.string().nullable().optional(),
2795
- installCommand: z34.string().nullable().optional(),
2796
- buildCommand: z34.string().nullable().optional(),
2797
- link: z34.object({
2798
- type: z34.string(),
2799
- repo: z34.string().optional(),
2800
- repoId: z34.union([z34.string(), z34.number()]).optional(),
2801
- org: z34.string().optional(),
2802
- productionBranch: z34.string().optional()
2803
- }).nullable().optional()
2804
- });
2805
- var exists = async (path) => access3(path).then(() => true, () => false);
2806
- var fail = (code, message) => {
2807
- throw new SetupFailure(code, message);
2808
- };
2809
- var stable = (version2, major) => new RegExp(`^${major}\\.\\d+\\.\\d+$`, "u").test(version2);
2810
- async function inspectSetupLocalProject(projectDir) {
2811
- const projectDirectory = await realpath(resolve(projectDir));
2812
- const manifest = manifestSchema.parse(JSON.parse(await readFile8(join7(projectDirectory, "package.json"), "utf8")));
2813
- const apps = (await Promise.all(["app", "src/app"].map(async (path) => await exists(join7(projectDirectory, path)) ? path : null))).filter((path) => path !== null);
2814
- if (apps.length !== 1)
2815
- fail("ambiguous_app_directory", "Select one Next.js App Router application with exactly one app/ or src/app/ directory.");
2816
- const repositoryRoot = (await setupProcess("git", ["rev-parse", "--show-toplevel"], {
2817
- cwd: projectDirectory
2818
- })).trim();
2819
- const tracked = await setupProcess("git", ["ls-files", "--stage", "-z"], {
2820
- cwd: repositoryRoot
2821
- });
2822
- for (const entry of tracked.split("\0").filter(Boolean)) {
2823
- if (entry.startsWith("160000 "))
2824
- fail("git_submodule_conflict", "The repository contains Git submodules. Resolve the explicit deployment source boundary before setup; the CLI will not copy external repositories.");
2825
- if (!entry.startsWith("120000 "))
2826
- continue;
2827
- const path = join7(repositoryRoot, entry.slice(entry.indexOf(" ") + 1));
2828
- const target = resolve(dirname7(path), await readlink(path));
2829
- const bound = relative2(repositoryRoot, target);
2830
- if (bound.startsWith("..") || bound.startsWith(sep))
2831
- 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.");
2832
- }
2833
- let lockfileRoot = projectDirectory;
2834
- const lockNames = [
2835
- "package-lock.json",
2836
- "npm-shrinkwrap.json",
2837
- "pnpm-lock.yaml",
2838
- "yarn.lock",
2839
- "bun.lock",
2840
- "bun.lockb"
2841
- ];
2842
- let locks = [];
2843
- for (; ; ) {
2844
- locks = (await Promise.all(lockNames.map(async (name3) => await exists(join7(lockfileRoot, name3)) ? name3 : null))).filter((name3) => name3 !== null);
2845
- if (locks.length || lockfileRoot === repositoryRoot || dirname7(lockfileRoot) === lockfileRoot)
2846
- break;
2847
- lockfileRoot = dirname7(lockfileRoot);
2848
- }
2849
- if (locks.length > 1)
2850
- fail("conflicting_lockfiles", "Resolve conflicting package-manager lockfiles before setup; Siteplane does not replace them.");
2851
- if (!locks.length)
2852
- fail("lockfile_missing", "Install the existing application with its chosen package manager to create one canonical lockfile.");
2853
- const lockName = locks[0];
2854
- if (!["package-lock.json", "pnpm-lock.yaml"].includes(lockName))
2855
- fail("unsupported_package_manager", "This setup supports npm 10 or pnpm 9/10 with their canonical lockfile.");
2856
- const rootManifest = manifestSchema.parse(JSON.parse(await readFile8(join7(lockfileRoot, "package.json"), "utf8")));
2857
- if (lockfileRoot !== projectDirectory) {
2858
- const workspaceFile = join7(lockfileRoot, "pnpm-workspace.yaml");
2859
- 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([
2860
- z34.array(z34.string()),
2861
- z34.object({ packages: z34.array(z34.string()) }).transform((value) => value.packages)
2862
- ]).parse(rootManifest.workspaces);
2863
- const selected = relative2(lockfileRoot, projectDirectory).split(sep).join("/");
2864
- if (!workspace.some((pattern) => !pattern.startsWith("!") && minimatch(selected, pattern)) || workspace.some((pattern) => pattern.startsWith("!") && minimatch(selected, pattern.slice(1))))
2865
- fail("unbound_workspace_app", "The selected application is excluded from the canonical lockfile's workspace packages. Select its actual application root.");
2866
- }
2867
- for (let ancestor = dirname7(lockfileRoot); ancestor.startsWith(repositoryRoot + sep) || ancestor === repositoryRoot; ancestor = dirname7(ancestor)) {
2868
- const ancestorLocks = await Promise.all(lockNames.map((name3) => exists(join7(ancestor, name3))));
2869
- if (ancestorLocks.some(Boolean))
2870
- fail("ambiguous_lockfile_root", "Both the selected package and its repository ancestors contain lockfiles. Select one canonical workspace resolution before setup.");
2871
- if (ancestor === repositoryRoot)
2872
- break;
2873
- }
2874
- const lockText = await readFile8(join7(lockfileRoot, lockName), "utf8");
2875
- const npmLock = lockName === "package-lock.json" ? z34.object({
2876
- lockfileVersion: z34.number(),
2877
- packages: z34.record(z34.string(), z34.object({
2878
- version: z34.string().optional(),
2879
- peerDependencies: z34.record(z34.string(), z34.string()).optional()
2880
- })).optional()
2881
- }).parse(JSON.parse(lockText)) : null;
2882
- async function version2(name3) {
2883
- try {
2884
- return (await readInstalledPackage(projectDirectory, name3)).version;
2885
- } catch {
2886
- const resolved = npmLock?.packages?.[`node_modules/${name3}`]?.version;
2887
- if (resolved)
2888
- return resolved;
2889
- return fail("dependencies_not_installed", `Install the existing ${name3} dependency using the canonical lockfile before setup.`);
2890
- }
2891
- }
2892
- const [nextVersion, reactVersion, reactDomVersion] = await Promise.all([
2893
- version2("next"),
2894
- version2("react"),
2895
- version2("react-dom")
2896
- ]);
2897
- if (!stable(nextVersion, 16))
2898
- fail("unsupported_next_version", "Setup supports stable Next.js 16 App Router projects. Framework migration requires a separate owner decision.");
2899
- if (!stable(reactVersion, 19) || reactDomVersion !== reactVersion)
2900
- fail("react_version_conflict", "Use the same stable React 19/react-dom version compatible with the installed Next.js peers.");
2901
- if (!stable(process.versions.node, 22))
2902
- fail("unsupported_node_version", "Run setup under Node.js 22; this does not change your framework or package-manager versions.");
2903
- const nextMetadata = await readInstalledPackage(projectDirectory, "next").catch(() => npmLock?.packages?.["node_modules/next"] ?? null);
2904
- const peers = nextMetadata?.peerDependencies;
2905
- if (!peers?.react || !peers["react-dom"])
2906
- fail("next_peer_metadata_missing", "Install the locked Next.js dependency before setup so its actual React peer requirements can be checked.");
2907
- if (!semver.satisfies(reactVersion, peers.react) || !semver.satisfies(reactDomVersion, peers["react-dom"]))
2908
- fail("react_peer_conflict", "The installed React pair does not satisfy the installed Next.js peer requirements. Choose a compatible pair explicitly.");
2909
- if (manifest.engines?.node && !semver.satisfies(process.versions.node, manifest.engines.node))
2910
- fail("node_engine_conflict", "The selected application's Node engine declaration excludes the active supported Node.js 22 runtime.");
2911
- const name2 = lockName === "package-lock.json" ? "npm" : "pnpm";
2912
- const declared = rootManifest.packageManager ?? manifest.packageManager ?? null;
2913
- if (rootManifest.packageManager && manifest.packageManager && rootManifest.packageManager !== manifest.packageManager)
2914
- fail("package_manager_conflict", "Application and workspace packageManager declarations disagree.");
2915
- if (declared && !new RegExp(`^${name2}@\\d+\\.\\d+\\.\\d+$`, "u").test(declared))
2916
- fail("package_manager_conflict", "Declare an exact supported npm/pnpm packageManager version matching the canonical lockfile.");
2917
- const localVersion = (await setupProcess(declared ? "npx" : name2, declared ? ["--yes", "--package", declared, name2, "--version"] : ["--version"], { cwd: lockfileRoot })).trim();
2918
- if (!(name2 === "npm" ? stable(localVersion, 10) : stable(localVersion, 9) || stable(localVersion, 10)))
2919
- fail("unsupported_package_manager_version", "Use npm 10 or pnpm 9/10; other versions are outside the initial setup support range.");
2920
- if (declared && declared !== `${name2}@${localVersion}`)
2921
- 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.");
2922
- const format = npmLock ? String(npmLock.lockfileVersion) : /^lockfileVersion:\s*['"]?([\d.]+)/mu.exec(lockText)?.[1];
2923
- if (name2 === "npm" && format !== "3" || name2 === "pnpm" && format !== "9.0" && format !== "9")
2924
- fail("lockfile_format_conflict", "The canonical lockfile format does not match npm 10 or pnpm 9/10.");
2925
- const sourceConflicts = [];
2926
- for (const file of ["next.config.js", "next.config.mjs", "next.config.ts"]) {
2927
- if (!await exists(join7(projectDirectory, file)))
2928
- continue;
2929
- const source = await readFile8(join7(projectDirectory, file), "utf8");
2930
- if (/output\s*:\s*['"]export['"]/u.test(source))
2931
- sourceConflicts.push("static_export");
2932
- if (/\bbasePath\s*:/u.test(source))
2933
- sourceConflicts.push("base_path");
2934
- if (/\bloaderFile\s*:|\bloader\s*:\s*['"](?:custom|imgix|cloudinary|akamai)['"]/u.test(source))
2935
- sourceConflicts.push(`inspect_image_loader:${file}`);
2936
- }
2937
- if (sourceConflicts.some((conflict) => conflict === "static_export" || conflict === "base_path"))
2938
- fail("unsupported_server_configuration", "Resolve static export/basePath configuration explicitly; Siteplane requires its server-side admin and revalidation handlers.");
2939
- for (const name3 of [
2940
- "middleware.ts",
2941
- "middleware.js",
2942
- "proxy.ts",
2943
- "proxy.js",
2944
- "src/middleware.ts",
2945
- "src/middleware.js",
2946
- "src/proxy.ts",
2947
- "src/proxy.js"
2948
- ]) {
2949
- if (await exists(join7(projectDirectory, name3))) {
2950
- sourceConflicts.push(`inspect_routing:${name3}`);
2951
- if (await readlink(join7(projectDirectory, name3)).catch(() => null))
2952
- continue;
2953
- const policySource = await readFile8(join7(projectDirectory, name3), "utf8");
2954
- if (/Content-Security-Policy|img-src|default-src/iu.test(policySource))
2955
- sourceConflicts.push(`inspect_image_csp:${name3}`);
2956
- }
2957
- }
2958
- async function inspectSource(directory) {
2959
- for (const entry of await readdir(directory, { withFileTypes: true })) {
2960
- if (entry.isSymbolicLink() || ["node_modules", ".git", ".next", ".siteplane", ".vercel"].includes(entry.name))
2961
- continue;
2962
- const path = join7(directory, entry.name);
2963
- if (entry.isDirectory()) {
2964
- await inspectSource(path);
2965
- continue;
2966
- }
2967
- if (!/\.[cm]?[jt]sx?$/u.test(entry.name))
2968
- continue;
2969
- const source = await readFile8(path, "utf8");
2970
- if (/Content-Security-Policy|img-src|default-src/iu.test(source))
2971
- sourceConflicts.push(`inspect_image_csp:${relative2(projectDirectory, path)}`);
2972
- if (/from\s*["']next\/image["']/u.test(source))
2973
- sourceConflicts.push(`inspect_image_policy:${relative2(projectDirectory, path)}`);
2974
- if (/\b(?:Cookiebot|OneTrust|cookieyes|consentManager|cookieConsent)\b/iu.test(source))
2975
- sourceConflicts.push(`inspect_existing_consent:${relative2(projectDirectory, path)}`);
2976
- if (/from\s*["']next\/image["']/u.test(source) && semver.lt(nextVersion, "16.3.3"))
2977
- 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.`);
2978
- if (/["']use server["']/u.test(source) && semver.lt(nextVersion, "16.2.11"))
2979
- 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.`);
2980
- }
2981
- }
2982
- await inspectSource(join7(projectDirectory, apps[0]));
2983
- const gitRead = async (args) => setupProcess("git", args, { cwd: projectDirectory }).then((value) => value.trim(), () => null);
2984
- return {
2985
- projectDirectory,
2986
- repositoryRoot,
2987
- lockfileRoot,
2988
- appDirectory: apps[0],
2989
- nextVersion,
2990
- reactVersion,
2991
- nodeVersion: process.versions.node,
2992
- packageManager: { name: name2, version: localVersion, declared },
2993
- lockfile: {
2994
- path: relative2(repositoryRoot, join7(lockfileRoot, lockName)),
2995
- format,
2996
- sha256: createHash2("sha256").update(lockText).digest("hex")
2997
- },
2998
- git: {
2999
- branch: await gitRead(["branch", "--show-current"]),
3000
- revision: await gitRead(["rev-parse", "HEAD"]),
3001
- remote: safeGitRemote(await gitRead(["remote", "get-url", "origin"])),
3002
- changes: (await gitRead(["status", "--porcelain=v1", "--untracked-files=all"]))?.split("\n").filter(Boolean) ?? []
3003
- },
3004
- sourceConflicts
3005
- };
3006
- }
3007
- async function setupPreflightCommand(input) {
3008
- let local;
3009
- try {
3010
- local = await inspectSetupLocalProject(input.projectDir);
3011
- await assertLocalCredentialsPathSafe(input.projectDir);
3012
- let linkDirectory = local.projectDirectory;
3013
- while (!await exists(join7(linkDirectory, ".vercel/project.json")) && linkDirectory !== local.repositoryRoot && dirname7(linkDirectory) !== linkDirectory)
3014
- linkDirectory = dirname7(linkDirectory);
3015
- if (!await exists(join7(linkDirectory, ".vercel/project.json")))
3016
- fail("vercel_project_not_linked", "Link this application to its intended Vercel project before setup; Siteplane will not guess a target.");
3017
- const linked = z34.object({
3018
- projectId: z34.string().regex(/^prj_[A-Za-z0-9]+$/u),
3019
- orgId: z34.string().regex(/^(?:team|user)_[A-Za-z0-9]+$/u)
3020
- }).parse(JSON.parse(await readFile8(join7(linkDirectory, ".vercel/project.json"), "utf8")));
3021
- const project = vercelProjectSchema.parse(await setupVercelApi(linkDirectory, `/v9/projects/${linked.projectId}?teamId=${linked.orgId}`));
3022
- if (project.id !== linked.projectId || project.accountId !== linked.orgId)
3023
- fail("vercel_identity_conflict", "The provider project does not match the locally linked project and team.");
3024
- const expectedRoot = relative2(local.repositoryRoot, local.projectDirectory).split(sep).join("/");
3025
- if ((project.rootDirectory ?? "") !== expectedRoot)
3026
- fail("vercel_root_conflict", "Vercel Root Directory and the selected local app must identify the same application.");
3027
- if (project.nodeVersion !== "22.x" || project.framework !== "nextjs")
3028
- fail("vercel_framework_conflict", "The bound Vercel project must use Next.js with Node.js 22 before setup.");
3029
- if (project.link && project.link.productionBranch !== local.git.branch)
3030
- fail("vercel_production_branch_conflict", "The local branch differs from the bound Vercel Production branch.");
3031
- if (project.link?.repo && project.link.org && !local.git.remote?.replace(/\.git$/u, "").endsWith(`${project.link.org}/${project.link.repo}`))
3032
- fail("vercel_git_conflict", "The local origin repository differs from the Vercel Git connection.");
3033
- const env = z34.object({
3034
- envs: z34.array(z34.object({
3035
- key: z34.string(),
3036
- value: z34.string().optional(),
3037
- target: z34.array(z34.string()).optional()
3038
- }))
3039
- }).parse(await setupVercelApi(linkDirectory, `/v10/projects/${linked.projectId}/env?teamId=${linked.orgId}`));
3040
- const corepack = env.envs.some((item) => item.key === "ENABLE_EXPERIMENTAL_COREPACK" && item.value === "1" && item.target?.includes("production"));
3041
- const install = project.installCommand ?? null;
3042
- const selected = corepack ? "corepack" : install ? "install_override" : "automatic";
3043
- if (local.packageManager.declared && selected === "automatic")
3044
- 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.");
3045
- if (install && /\b(?:yarn|bun)\b/u.test(install))
3046
- fail("vercel_package_manager_conflict", "The Vercel install override selects an unsupported package manager.");
3047
- const overridePin = install ? /\b(npm|pnpm)@(\d+\.\d+\.\d+)\b/u.exec(install) : null;
3048
- if (overridePin && overridePin[1] !== local.packageManager.name)
3049
- fail("vercel_package_manager_conflict", "The provider override selects a different package manager than the canonical lockfile.");
3050
- const overrideFamily = install ? /(?:^|[;&|]\s*)(npm|pnpm)\s+(?:ci|install)\b/u.exec(install)?.[1] : null;
3051
- if (overrideFamily && overrideFamily !== local.packageManager.name)
3052
- fail("vercel_package_manager_conflict", "The provider install command conflicts with the canonical lockfile.");
3053
- if (overridePin && local.packageManager.declared && `${overridePin[1]}@${overridePin[2]}` !== local.packageManager.declared)
3054
- fail("vercel_package_manager_conflict", "The Vercel install override conflicts with the exact packageManager declaration.");
3055
- 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);
3056
- for (const [, family, version2] of buildRunners) {
3057
- if (family !== local.packageManager.name || version2 && local.packageManager.declared && `${family}@${version2}` !== local.packageManager.declared)
3058
- 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.");
3059
- }
3060
- return {
3061
- status: "ready",
3062
- local,
3063
- provider: {
3064
- projectId: project.id,
3065
- teamId: project.accountId,
3066
- name: project.name,
3067
- rootDirectory: expectedRoot,
3068
- nodeVersion: project.nodeVersion,
3069
- git: project.link,
3070
- installCommand: install,
3071
- buildCommand: project.buildCommand ?? null,
3072
- packageManagerSelection: selected,
3073
- declaredPackageManager: local.packageManager.declared,
3074
- observedPackageManager: null
3075
- }
3076
- };
3077
- } catch (error) {
3078
- return {
3079
- status: "action_required",
3080
- code: error instanceof SetupFailure ? error.code : "invalid_local_project",
3081
- message: error instanceof SetupFailure ? error.message : "The selected project or provider response could not be validated. Check the application manifest and local project access.",
3082
- ...local ? { local } : {}
3083
- };
3084
- }
3085
- }
3086
- function safeGitRemote(value) {
3087
- if (!value)
3088
- return null;
3089
- if (!value.includes("://"))
3090
- return value;
3091
- try {
3092
- const url = new URL(value);
3093
- url.username = "";
3094
- url.password = "";
3095
- url.search = "";
3096
- url.hash = "";
3097
- return url.toString().replace(/\/$/u, "");
3098
- } catch {
3099
- return null;
3100
- }
3101
- }
3102
-
3103
- // ../cli/dist/commands/init.js
3104
- var siteSetupBootstrapDataSchema = z35.object({
3105
- credentialPurpose: z35.literal("site_setup"),
3106
- apiBaseUrl: z35.string().url(),
3107
- siteId: z35.string().uuid(),
3108
- publicSiteKeyId: z35.string().uuid(),
3109
- publicSiteKey: z35.string().trim().min(1),
3110
- accessToken: z35.string().trim().min(1),
3111
- siteRevalidationSecret: z35.string().regex(/^[A-Za-z0-9_-]{43}$/u),
3112
- runId: z35.string().uuid(),
3113
- packages: siteSetupPackagesSchema
3114
- }).strict();
3115
- var featureBootstrapDataSchema = z35.object({
3116
- credentialPurpose: z35.enum(["analytics", "booking"]),
3117
- apiBaseUrl: z35.string().url(),
3118
- siteId: z35.string().uuid(),
3119
- accessToken: z35.string().trim().min(1)
3120
- }).strict();
3121
- var bootstrapResponseSchema = z35.object({
3122
- ok: z35.literal(true),
3123
- data: z35.discriminatedUnion("credentialPurpose", [
3124
- siteSetupBootstrapDataSchema,
3125
- featureBootstrapDataSchema
3126
- ])
3127
- }).strict();
3128
-
3129
1840
  // ../cli/dist/commands/scan.js
3130
- import { readdir as readdir2 } from "fs/promises";
3131
- import { extname, join as join9 } from "path";
1841
+ import { readdir } from "fs/promises";
1842
+ import { extname, join as join3 } from "path";
3132
1843
  var defaultScanRoots = ["app", "src", "pages", "components", "lib"];
3133
1844
  var excludedDirectories = /* @__PURE__ */ new Set([
3134
1845
  ".git",
@@ -3146,14 +1857,14 @@ async function resolveScanFilePaths(filePaths, options = {}) {
3146
1857
  return filePaths;
3147
1858
  }
3148
1859
  const projectDir = options.projectDir ?? process.cwd();
3149
- const discovered = await Promise.all(defaultScanRoots.map((root) => collectSourceFiles(join9(projectDir, root))));
1860
+ const discovered = await Promise.all(defaultScanRoots.map((root) => collectSourceFiles(join3(projectDir, root))));
3150
1861
  return [...new Set(discovered.flat())].sort();
3151
1862
  }
3152
1863
  async function collectSourceFiles(directory) {
3153
- const entries = await readdir2(directory, { withFileTypes: true }).catch(() => []);
1864
+ const entries = await readdir(directory, { withFileTypes: true }).catch(() => []);
3154
1865
  const files = [];
3155
1866
  for (const entry of entries) {
3156
- const entryPath = join9(directory, entry.name);
1867
+ const entryPath = join3(directory, entry.name);
3157
1868
  if (entry.isDirectory()) {
3158
1869
  if (!excludedDirectories.has(entry.name)) {
3159
1870
  files.push(...await collectSourceFiles(entryPath));
@@ -3167,19 +1878,59 @@ async function collectSourceFiles(directory) {
3167
1878
  return files;
3168
1879
  }
3169
1880
 
3170
- // ../cli/dist/commands/site-setup.js
3171
- import { execFile as execFile2 } from "child_process";
3172
- import { readFile as readFile9 } from "fs/promises";
3173
- import { promisify as promisify2 } from "util";
3174
- import { z as z36 } from "zod";
1881
+ // ../cli/dist/auth/device-login.js
1882
+ import { spawn } from "child_process";
1883
+ import { hostname } from "os";
1884
+
1885
+ // ../cli/dist/config/agent-connections.js
1886
+ import { randomUUID } from "crypto";
1887
+ import { chmod, mkdir as mkdir3, open, readFile as readFile3, rename, rm } from "fs/promises";
1888
+ import { join as join4 } from "path";
1889
+ import { z as z27 } from "zod";
1890
+ var storeSchema = z27.object({
1891
+ connections: z27.array(z27.object({
1892
+ apiOrigin: z27.string().url(),
1893
+ siteId: z27.string().min(1),
1894
+ accessToken: z27.string().min(1),
1895
+ scopes: z27.array(z27.string()),
1896
+ expiresAt: z27.string()
1897
+ }))
1898
+ });
1899
+
1900
+ // ../cli/dist/config/project-config.js
1901
+ import { readFile as readFile4 } from "fs/promises";
1902
+ import { join as join5 } from "path";
1903
+ import { z as z28 } from "zod";
1904
+ var packageVersionSchema = z28.string().regex(/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/u);
1905
+ var projectPackagesSchema = z28.object({
1906
+ siteplane: packageVersionSchema,
1907
+ runtimeNext: packageVersionSchema,
1908
+ analytics: packageVersionSchema.optional()
1909
+ }).strict();
1910
+ var siteplaneProjectConfigSchema = z28.object({
1911
+ version: z28.literal(2),
1912
+ apiBaseUrl: z28.string().url(),
1913
+ siteId: z28.string().uuid(),
1914
+ publicSiteKeyId: z28.string().uuid(),
1915
+ publicSiteKey: z28.string().trim().min(1),
1916
+ runId: z28.string().uuid(),
1917
+ appDirectory: z28.string().min(1),
1918
+ taskContractVersion: z28.literal("siteplane.setup-task.v2"),
1919
+ adminProtocolVersion: z28.literal(2),
1920
+ packages: projectPackagesSchema,
1921
+ fieldContractHash: z28.string().regex(/^sha256:[0-9a-f]{64}$/iu).optional()
1922
+ }).strict();
1923
+ async function readProjectConfig(projectDir) {
1924
+ return siteplaneProjectConfigSchema.parse(JSON.parse(await readFile4(join5(projectDir, "siteplane.config.json"), "utf8")));
1925
+ }
3175
1926
 
3176
1927
  // ../cli/dist/scan/next-source-scan.js
3177
- import ts3 from "typescript";
3178
- import { isAbsolute, relative as relative4 } from "path";
1928
+ import ts2 from "typescript";
1929
+ import { isAbsolute, relative } from "path";
3179
1930
  var eventPreviewHandlerMissingMessage = "Event preview fields must consume preview values with useSiteplanePreviewText from @siteplane/runtime-next/client or a siteplane:preview-value-applied listener.";
3180
1931
  var valueCallUnusedMessage = "Siteplane value calls must feed rendered content. Assign or await the returned value and render that value instead of ignoring the call.";
3181
1932
  var legacyEditableComponentPrefix = "Editable";
3182
- var editableComponentNames = new Set(["Image", "Text", "LongText", "Link"].map((name2) => `${legacyEditableComponentPrefix}${name2}`));
1933
+ var editableComponentNames = new Set(["Image", "Text", "LongText", "Link"].map((name) => `${legacyEditableComponentPrefix}${name}`));
3183
1934
  var functionTypeByName = {
3184
1935
  text: "text",
3185
1936
  longText: "longText",
@@ -3330,10 +2081,10 @@ function scanSourceFile(file, fields, hardErrors) {
3330
2081
  const eventPreviewComponentPropUsages = [];
3331
2082
  const eventPreviewConsumerFieldIds = /* @__PURE__ */ new Set();
3332
2083
  let hasGenericEventPreviewConsumer = false;
3333
- const sourceFile = ts3.createSourceFile(file.filePath, file.sourceText, ts3.ScriptTarget.Latest, true, ts3.ScriptKind.TSX);
2084
+ const sourceFile = ts2.createSourceFile(file.filePath, file.sourceText, ts2.ScriptTarget.Latest, true, ts2.ScriptKind.TSX);
3334
2085
  function visit(node, currentComponentName) {
3335
2086
  const nextComponentName = getFunctionComponentName(node) ?? currentComponentName;
3336
- if (ts3.isJsxSelfClosingElement(node) || ts3.isJsxOpeningElement(node)) {
2087
+ if (ts2.isJsxSelfClosingElement(node) || ts2.isJsxOpeningElement(node)) {
3337
2088
  const componentName = getJsxTagName(node.tagName);
3338
2089
  if (editableComponentNames.has(componentName)) {
3339
2090
  hardErrors.push({
@@ -3344,7 +2095,7 @@ function scanSourceFile(file, fields, hardErrors) {
3344
2095
  }
3345
2096
  collectEventPreviewComponentPropUsages(node, eventPreviewAttrVariables, eventPreviewComponentPropUsages, file);
3346
2097
  }
3347
- if (ts3.isCallExpression(node)) {
2098
+ if (ts2.isCallExpression(node)) {
3348
2099
  collectAttrsCall(node, attrFieldIds, attrRouteRefs, eventPreviewAttrs, eventPreviewAttrVariables, directAttrs, file);
3349
2100
  collectUnusedValueCallError(node, hardErrors, file);
3350
2101
  const extractedFields = extractFunctionFields(node, file);
@@ -3368,7 +2119,7 @@ function scanSourceFile(file, fields, hardErrors) {
3368
2119
  if (isGenericEventPreviewConsumerReference(node)) {
3369
2120
  hasGenericEventPreviewConsumer = true;
3370
2121
  }
3371
- ts3.forEachChild(node, (child) => visit(child, nextComponentName));
2122
+ ts2.forEachChild(node, (child) => visit(child, nextComponentName));
3372
2123
  }
3373
2124
  visit(sourceFile);
3374
2125
  markMissingAttrsWarnings(fieldsInFile, attrFieldIds, attrRouteRefs);
@@ -3395,7 +2146,7 @@ function collectUnusedValueCallError(node, hardErrors, file) {
3395
2146
  });
3396
2147
  }
3397
2148
  function getSiteplaneValueFunctionName(node) {
3398
- if (!ts3.isPropertyAccessExpression(node.expression)) {
2149
+ if (!ts2.isPropertyAccessExpression(node.expression)) {
3399
2150
  return void 0;
3400
2151
  }
3401
2152
  if (node.expression.expression.getText() !== "siteplane") {
@@ -3408,16 +2159,16 @@ function getSiteplaneValueFunctionName(node) {
3408
2159
  return void 0;
3409
2160
  }
3410
2161
  function isIgnoredValueCall(node) {
3411
- if (ts3.isVoidExpression(node.parent)) {
2162
+ if (ts2.isVoidExpression(node.parent)) {
3412
2163
  return true;
3413
2164
  }
3414
- if (ts3.isExpressionStatement(node.parent)) {
2165
+ if (ts2.isExpressionStatement(node.parent)) {
3415
2166
  return true;
3416
2167
  }
3417
- return ts3.isAwaitExpression(node.parent) && ts3.isExpressionStatement(node.parent.parent);
2168
+ return ts2.isAwaitExpression(node.parent) && ts2.isExpressionStatement(node.parent.parent);
3418
2169
  }
3419
2170
  function extractFunctionFields(node, file) {
3420
- if (!ts3.isPropertyAccessExpression(node.expression)) {
2171
+ if (!ts2.isPropertyAccessExpression(node.expression)) {
3421
2172
  return [];
3422
2173
  }
3423
2174
  if (node.expression.expression.getText() !== "siteplane") {
@@ -3555,7 +2306,7 @@ function createFallbackHash(fieldType, fallback) {
3555
2306
  }
3556
2307
  }
3557
2308
  function collectAttrsCall(node, attrFieldIds, attrRouteRefs, eventPreviewAttrs, eventPreviewAttrVariables, directAttrs, file) {
3558
- if (!ts3.isPropertyAccessExpression(node.expression)) {
2309
+ if (!ts2.isPropertyAccessExpression(node.expression)) {
3559
2310
  return;
3560
2311
  }
3561
2312
  if (node.expression.expression.getText() !== "siteplane" || node.expression.name.text !== "attrs") {
@@ -3584,7 +2335,7 @@ function collectAttrsCall(node, attrFieldIds, attrRouteRefs, eventPreviewAttrs,
3584
2335
  }
3585
2336
  return;
3586
2337
  }
3587
- if (firstArg && ts3.isIdentifier(firstArg) && typeof secondArg === "string") {
2338
+ if (firstArg && ts2.isIdentifier(firstArg) && typeof secondArg === "string") {
3588
2339
  attrRouteRefs.add(`${firstArg.text}:${secondArg}`);
3589
2340
  }
3590
2341
  }
@@ -3621,7 +2372,7 @@ function hasEventPreviewStrategy(options) {
3621
2372
  return !!options && typeof options === "object" && !Array.isArray(options) && options.previewStrategy === "event";
3622
2373
  }
3623
2374
  function isGenericEventPreviewConsumerReference(node) {
3624
- return (ts3.isStringLiteral(node) || ts3.isNoSubstitutionTemplateLiteral(node)) && node.text === "siteplane:preview-value-applied";
2375
+ return (ts2.isStringLiteral(node) || ts2.isNoSubstitutionTemplateLiteral(node)) && node.text === "siteplane:preview-value-applied";
3625
2376
  }
3626
2377
  function getPreviewHookFieldId(node, eventPreviewAttrVariables) {
3627
2378
  const firstArg = getUseSiteplanePreviewTextFirstArg(node);
@@ -3632,7 +2383,7 @@ function getPreviewHookFieldId(node, eventPreviewAttrVariables) {
3632
2383
  if (typeof directFieldId === "string") {
3633
2384
  return directFieldId;
3634
2385
  }
3635
- if (ts3.isIdentifier(firstArg)) {
2386
+ if (ts2.isIdentifier(firstArg)) {
3636
2387
  return eventPreviewAttrVariables.get(firstArg.text);
3637
2388
  }
3638
2389
  return void 0;
@@ -3642,16 +2393,16 @@ function getPreviewHookPropName(node, eventPreviewAttrVariables) {
3642
2393
  if (!firstArg) {
3643
2394
  return void 0;
3644
2395
  }
3645
- if (ts3.isIdentifier(firstArg) && !eventPreviewAttrVariables.has(firstArg.text)) {
2396
+ if (ts2.isIdentifier(firstArg) && !eventPreviewAttrVariables.has(firstArg.text)) {
3646
2397
  return firstArg.text;
3647
2398
  }
3648
- if (ts3.isPropertyAccessExpression(firstArg) && ts3.isIdentifier(firstArg.expression)) {
2399
+ if (ts2.isPropertyAccessExpression(firstArg) && ts2.isIdentifier(firstArg.expression)) {
3649
2400
  return firstArg.name.text;
3650
2401
  }
3651
2402
  return void 0;
3652
2403
  }
3653
2404
  function getUseSiteplanePreviewTextFirstArg(node) {
3654
- if (ts3.isIdentifier(node.expression) && node.expression.text === "useSiteplanePreviewText") {
2405
+ if (ts2.isIdentifier(node.expression) && node.expression.text === "useSiteplanePreviewText") {
3655
2406
  return node.arguments[0];
3656
2407
  }
3657
2408
  return void 0;
@@ -3732,19 +2483,19 @@ function staticExpressionValue(expression) {
3732
2483
  if (!expression) {
3733
2484
  return void 0;
3734
2485
  }
3735
- if (ts3.isStringLiteral(expression) || ts3.isNoSubstitutionTemplateLiteral(expression)) {
2486
+ if (ts2.isStringLiteral(expression) || ts2.isNoSubstitutionTemplateLiteral(expression)) {
3736
2487
  return expression.text;
3737
2488
  }
3738
- if (ts3.isNumericLiteral(expression)) {
2489
+ if (ts2.isNumericLiteral(expression)) {
3739
2490
  return Number(expression.text);
3740
2491
  }
3741
- if (expression.kind === ts3.SyntaxKind.TrueKeyword) {
2492
+ if (expression.kind === ts2.SyntaxKind.TrueKeyword) {
3742
2493
  return true;
3743
2494
  }
3744
- if (expression.kind === ts3.SyntaxKind.FalseKeyword) {
2495
+ if (expression.kind === ts2.SyntaxKind.FalseKeyword) {
3745
2496
  return false;
3746
2497
  }
3747
- if (ts3.isObjectLiteralExpression(expression)) {
2498
+ if (ts2.isObjectLiteralExpression(expression)) {
3748
2499
  return readObjectLiteral(expression);
3749
2500
  }
3750
2501
  return void 0;
@@ -3752,20 +2503,20 @@ function staticExpressionValue(expression) {
3752
2503
  function readObjectLiteral(expression) {
3753
2504
  const value = {};
3754
2505
  for (const property of expression.properties) {
3755
- if (!ts3.isPropertyAssignment(property)) {
2506
+ if (!ts2.isPropertyAssignment(property)) {
3756
2507
  continue;
3757
2508
  }
3758
- const name2 = getPropertyName(property.name);
3759
- if (!name2) {
2509
+ const name = getPropertyName(property.name);
2510
+ if (!name) {
3760
2511
  continue;
3761
2512
  }
3762
- value[name2] = staticExpressionValue(property.initializer);
2513
+ value[name] = staticExpressionValue(property.initializer);
3763
2514
  }
3764
2515
  return value;
3765
2516
  }
3766
- function getPropertyName(name2) {
3767
- if (ts3.isIdentifier(name2) || ts3.isStringLiteral(name2)) {
3768
- return name2.text;
2517
+ function getPropertyName(name) {
2518
+ if (ts2.isIdentifier(name) || ts2.isStringLiteral(name)) {
2519
+ return name.text;
3769
2520
  }
3770
2521
  return null;
3771
2522
  }
@@ -3775,7 +2526,7 @@ function collectEventPreviewComponentPropUsages(node, eventPreviewAttrVariables,
3775
2526
  return;
3776
2527
  }
3777
2528
  for (const property of node.attributes.properties) {
3778
- if (!ts3.isJsxAttribute(property)) {
2529
+ if (!ts2.isJsxAttribute(property)) {
3779
2530
  continue;
3780
2531
  }
3781
2532
  const propName = getJsxAttributeName(property.name);
@@ -3791,9 +2542,9 @@ function collectEventPreviewComponentPropUsages(node, eventPreviewAttrVariables,
3791
2542
  });
3792
2543
  }
3793
2544
  }
3794
- function getJsxAttributeName(name2) {
3795
- if (ts3.isIdentifier(name2)) {
3796
- return name2.text;
2545
+ function getJsxAttributeName(name) {
2546
+ if (ts2.isIdentifier(name)) {
2547
+ return name.text;
3797
2548
  }
3798
2549
  return void 0;
3799
2550
  }
@@ -3801,32 +2552,32 @@ function getJsxFieldIdValue(initializer, eventPreviewAttrVariables) {
3801
2552
  if (!initializer) {
3802
2553
  return void 0;
3803
2554
  }
3804
- if (ts3.isStringLiteral(initializer)) {
2555
+ if (ts2.isStringLiteral(initializer)) {
3805
2556
  return initializer.text;
3806
2557
  }
3807
- if (ts3.isJsxExpression(initializer) && initializer.expression && ts3.isIdentifier(initializer.expression)) {
2558
+ if (ts2.isJsxExpression(initializer) && initializer.expression && ts2.isIdentifier(initializer.expression)) {
3808
2559
  return eventPreviewAttrVariables.get(initializer.expression.text);
3809
2560
  }
3810
2561
  return void 0;
3811
2562
  }
3812
2563
  function getFunctionComponentName(node) {
3813
- if (ts3.isFunctionDeclaration(node) && node.name && isComponentName(node.name.text)) {
2564
+ if (ts2.isFunctionDeclaration(node) && node.name && isComponentName(node.name.text)) {
3814
2565
  return node.name.text;
3815
2566
  }
3816
- if (ts3.isVariableDeclaration(node) && ts3.isIdentifier(node.name) && isComponentName(node.name.text) && node.initializer && (ts3.isArrowFunction(node.initializer) || ts3.isFunctionExpression(node.initializer))) {
2567
+ if (ts2.isVariableDeclaration(node) && ts2.isIdentifier(node.name) && isComponentName(node.name.text) && node.initializer && (ts2.isArrowFunction(node.initializer) || ts2.isFunctionExpression(node.initializer))) {
3817
2568
  return node.name.text;
3818
2569
  }
3819
2570
  return void 0;
3820
2571
  }
3821
- function isComponentName(name2) {
3822
- return /^[A-Z]/.test(name2);
2572
+ function isComponentName(name) {
2573
+ return /^[A-Z]/.test(name);
3823
2574
  }
3824
2575
  function getAssignedVariableName(node) {
3825
2576
  let current = node;
3826
- while (ts3.isAwaitExpression(current.parent)) {
2577
+ while (ts2.isAwaitExpression(current.parent)) {
3827
2578
  current = current.parent;
3828
2579
  }
3829
- if (ts3.isVariableDeclaration(current.parent) && ts3.isIdentifier(current.parent.name)) {
2580
+ if (ts2.isVariableDeclaration(current.parent) && ts2.isIdentifier(current.parent.name)) {
3830
2581
  return current.parent.name.text;
3831
2582
  }
3832
2583
  return void 0;
@@ -3867,391 +2618,13 @@ function inferRouteHint(filePath) {
3867
2618
  return route ? `/${route}` : "/";
3868
2619
  }
3869
2620
  function toRepositoryRelativePosixPath(filePath, projectRoot) {
3870
- const path = isAbsolute(filePath) ? relative4(projectRoot, filePath) : filePath;
2621
+ const path = isAbsolute(filePath) ? relative(projectRoot, filePath) : filePath;
3871
2622
  return path.replaceAll("\\", "/");
3872
2623
  }
3873
2624
  function isPositionalFieldReference(value) {
3874
2625
  return value ? /\[\d+\]|\.\d+(?:\.|$)/.test(value) : false;
3875
2626
  }
3876
2627
 
3877
- // ../cli/dist/commands/site-setup.js
3878
- var execFileAsync2 = promisify2(execFile2);
3879
- var safeErrorSchema = z36.object({
3880
- code: z36.string().trim().min(1),
3881
- message: z36.string().trim().min(1)
3882
- }).passthrough();
3883
- var errorResponseSchema2 = z36.object({ ok: z36.literal(false), error: safeErrorSchema }).passthrough();
3884
- var contextDataSchema = z36.object({
3885
- task: siteSetupTaskSchema.refine((task) => task.run !== null)
3886
- }).strict();
3887
- var contextResponseSchema = z36.object({ ok: z36.literal(true), data: contextDataSchema }).strict();
3888
- var applyDataSchema = z36.object({
3889
- status: z36.enum(["applied", "ready_for_review"]),
3890
- runId: z36.string().uuid().optional(),
3891
- contractVersionId: z36.string().uuid().optional(),
3892
- fieldContractHash: z36.string().regex(/^sha256:[0-9a-f]{64}$/u),
3893
- editorDefinitionHash: z36.string().regex(/^sha256:[0-9a-f]{64}$/u).optional(),
3894
- fieldCount: z36.number().int().nonnegative().optional(),
3895
- routeCount: z36.number().int().nonnegative().optional()
3896
- }).strict();
3897
- var applyResponseSchema = z36.object({ ok: z36.literal(true), data: applyDataSchema }).strict();
3898
- var verifyDataSchema = z36.object({
3899
- status: z36.literal("ready_for_review"),
3900
- runId: z36.string().uuid().optional(),
3901
- deploymentOrigin: z36.string().url().optional(),
3902
- deploymentRevision: z36.string().optional()
3903
- }).strict();
3904
- var verifyResponseSchema = z36.object({ ok: z36.literal(true), data: verifyDataSchema }).strict();
3905
- async function siteSetupContextCommand(input) {
3906
- const response = await postSiteSetup(input, "context", {});
3907
- const parsed = contextResponseSchema.safeParse(response.payload);
3908
- if (response.ok && parsed.success) {
3909
- return { status: "ok", ...parsed.data.data };
3910
- }
3911
- return actionRequired(response.payload, "Siteplane setup context is unavailable.");
3912
- }
3913
- async function siteSetupVerifyCommand(input) {
3914
- const resolveSourceFiles = input.resolveSourceFiles ?? resolveScanFilePaths;
3915
- const readSourceFile = input.readSourceFile ?? ((path) => readFile9(path, "utf8"));
3916
- const paths = await resolveSourceFiles([], { projectDir: input.projectDir });
3917
- const sources = await Promise.all(paths.map(readSourceFile));
3918
- if (!sources.some(hasMountedFieldRuntimeBridge)) {
3919
- return {
3920
- status: "action_required",
3921
- code: "missing_field_runtime_bridge",
3922
- message: "Mount FieldRuntimeBridge from @siteplane/runtime-next/client before deployment verification."
3923
- };
3924
- }
3925
- const deploymentRevision = await (input.readRevision ?? readGitRevision)(input.projectDir);
3926
- const response = await postSiteSetup(input, "verify", {
3927
- deploymentUrl: input.deploymentUrl,
3928
- deploymentRevision,
3929
- ...input.wait ? { wait: true } : {}
3930
- });
3931
- const parsed = verifyResponseSchema.safeParse(response.payload);
3932
- if (response.ok && parsed.success) {
3933
- return parsed.data.data;
3934
- }
3935
- return actionRequired(response.payload, "Siteplane deployment verification failed.");
3936
- }
3937
- function hasMountedFieldRuntimeBridge(source) {
3938
- return /from\s+["']@siteplane\/runtime-next(?:\/client)?["']/u.test(source) && /<FieldRuntimeBridge(?:\s|\/|>)/u.test(source);
3939
- }
3940
- async function postSiteSetup(input, operation, body) {
3941
- const [config, credentials] = await Promise.all([
3942
- readProjectConfig(input.projectDir),
3943
- readLocalCredentials(input.projectDir)
3944
- ]);
3945
- try {
3946
- const response = await (input.fetcher ?? fetch)(`${config.apiBaseUrl.replace(/\/$/u, "")}/api/cli/setup/${operation}`, {
3947
- method: "POST",
3948
- signal: AbortSignal.timeout(Math.max(1, Math.min(2e4, (input.deadline ?? Date.now() + 2e4) - Date.now()))),
3949
- headers: {
3950
- authorization: `Bearer ${credentials.accessToken}`,
3951
- "content-type": "application/json",
3952
- ...input.vercelAutomationBypassSecret?.trim() ? {
3953
- "x-vercel-protection-bypass": input.vercelAutomationBypassSecret.trim()
3954
- } : {}
3955
- },
3956
- body: JSON.stringify(body)
3957
- });
3958
- const payload = await response.json().catch(() => null);
3959
- return { ok: response.ok, payload };
3960
- } catch {
3961
- return {
3962
- ok: false,
3963
- payload: {
3964
- ok: false,
3965
- error: {
3966
- code: "site_setup.transport_failed",
3967
- message: "The setup request was not acknowledged. Reload the existing task before retrying; no credential values are included."
3968
- }
3969
- }
3970
- };
3971
- }
3972
- }
3973
- function actionRequired(payload, fallbackMessage) {
3974
- const parsed = errorResponseSchema2.safeParse(payload);
3975
- return parsed.success ? {
3976
- status: "action_required",
3977
- code: parsed.data.error.code,
3978
- message: parsed.data.error.message
3979
- } : {
3980
- status: "action_required",
3981
- code: "invalid_server_response",
3982
- message: fallbackMessage
3983
- };
3984
- }
3985
- async function readGitRevision(projectDir) {
3986
- const { stdout } = await execFileAsync2("git", ["rev-parse", "HEAD"], {
3987
- cwd: projectDir,
3988
- encoding: "utf8"
3989
- });
3990
- const revision = stdout.trim();
3991
- if (!revision) {
3992
- throw new Error("A committed Git revision is required before setup verify.");
3993
- }
3994
- return revision;
3995
- }
3996
-
3997
- // ../cli/dist/commands/setup-start.js
3998
- import { randomBytes, randomUUID as randomUUID4 } from "crypto";
3999
- import { access as access5 } from "fs/promises";
4000
- import { join as join10, relative as relative5 } from "path";
4001
- import { z as z37 } from "zod";
4002
- var bootstrapResponseSchema2 = z37.object({
4003
- ok: z37.literal(true),
4004
- data: siteSetupBootstrapDataSchema
4005
- }).strict();
4006
-
4007
- // ../cli/dist/commands/setup-review.js
4008
- import { z as z38 } from "zod";
4009
- var responseSchema2 = z38.object({
4010
- ok: z38.literal(true),
4011
- data: z38.object({
4012
- reviewUrl: z38.string().url(),
4013
- expiresAt: z38.string().datetime({ offset: true })
4014
- }).strict()
4015
- }).strict();
4016
-
4017
- // ../cli/dist/commands/setup-prepare.js
4018
- 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";
4019
- import { randomUUID as randomUUID5 } from "crypto";
4020
- import { dirname as dirname8, join as join11, relative as relative6, sep as sep2 } from "path";
4021
- import ts4 from "typescript";
4022
-
4023
- // ../cli/dist/commands/setup-lock.js
4024
- import { randomUUID as randomUUID6 } from "crypto";
4025
- import { lstat as lstat3, mkdir as mkdir7, open as open4, readFile as readFile11, rm as rm4, rmdir } from "fs/promises";
4026
- import { resolve as resolve2 } from "path";
4027
- import { z as z39 } from "zod";
4028
- var ownerSchema = z39.object({ pid: z39.number().int().positive(), nonce: z39.string().uuid() }).strict();
4029
-
4030
- // ../cli/dist/config/build-provenance.js
4031
- import { createHash as createHash3 } from "crypto";
4032
- import { execFile as execFile3 } from "child_process";
4033
- import { lstat as lstat4, readFile as readFile12, writeFile as writeFile5, mkdir as mkdir8 } from "fs/promises";
4034
- import { dirname as dirname9, isAbsolute as isAbsolute2, join as join12, relative as relative7, resolve as resolve3, sep as sep3 } from "path";
4035
- import { isDeepStrictEqual, promisify as promisify3 } from "util";
4036
- import { z as z40 } from "zod";
4037
- var execute = promisify3(execFile3);
4038
- var name = ".siteplane/build-source.json";
4039
- var oid = z40.string().regex(/^[0-9a-f]{40}$/u);
4040
- var entrySchema = z40.object({
4041
- path: z40.string().min(1).max(4096),
4042
- mode: z40.enum(["100644", "100755", "120000"]),
4043
- oid
4044
- }).strict();
4045
- var schema = z40.object({
4046
- version: z40.literal(2),
4047
- revision: oid,
4048
- commit: z40.string().min(1).max(1048576),
4049
- entries: z40.array(entrySchema).min(1).max(1e5),
4050
- providerConfigurations: z40.array(z40.object({
4051
- path: z40.string().max(4096).regex(/(?:^|\/)vercel\.json$/u),
4052
- source: z40.string().max(1048576)
4053
- }).strict()).max(1e3)
4054
- }).strict();
4055
- var gitHash = (type, content) => createHash3("sha1").update(`${type} ${content.length}\0`).update(content).digest("hex");
4056
- async function writeBuildProvenance(checkout, revision) {
4057
- const commit = (await execute("git", ["cat-file", "commit", revision], {
4058
- cwd: checkout,
4059
- maxBuffer: 1048576
4060
- })).stdout;
4061
- const tree = (await execute("git", ["ls-tree", "-rz", "--full-tree", revision], {
4062
- cwd: checkout,
4063
- maxBuffer: 16777216
4064
- })).stdout;
4065
- const entries = tree.split("\0").filter(Boolean).map((line) => {
4066
- const match = /^(100644|100755|120000) blob ([0-9a-f]{40})\t([\s\S]+)$/u.exec(line);
4067
- if (!match)
4068
- throw new Error("Git submodules or unsupported tracked objects need an explicit deployment configuration.");
4069
- return { path: match[3], mode: match[1], oid: match[2] };
4070
- });
4071
- for (const entry of entries) {
4072
- if (entry.mode !== "120000")
4073
- continue;
4074
- const { readlink: readlink2 } = await import("fs/promises");
4075
- const path = join12(checkout, entry.path);
4076
- const target2 = resolve3(dirname9(path), await readlink2(path));
4077
- const bound = relative7(checkout, target2);
4078
- if (bound.startsWith("..") || isAbsolute2(bound))
4079
- throw new Error("A tracked symbolic link escapes the committed upload; resolve that source boundary before deployment.");
4080
- }
4081
- const providerConfigurations = await Promise.all(entries.filter((entry) => /(?:^|\/)vercel\.json$/u.test(entry.path)).map(async (entry) => ({
4082
- path: entry.path,
4083
- source: await readFile12(join12(checkout, entry.path), "utf8")
4084
- })));
4085
- const record = schema.parse({
4086
- version: 2,
4087
- revision,
4088
- commit,
4089
- entries,
4090
- providerConfigurations
4091
- });
4092
- const target = join12(checkout, name);
4093
- await mkdir8(dirname9(target), { recursive: true, mode: 448 });
4094
- await writeFile5(target, JSON.stringify(record), { flag: "wx", mode: 384 });
4095
- }
4096
- async function readBuildProvenance(projectDirectory) {
4097
- let root = resolve3(projectDirectory);
4098
- let raw = null;
4099
- for (; ; ) {
4100
- raw = await readFile12(join12(root, name), "utf8").catch((error) => {
4101
- if (error.code === "ENOENT")
4102
- return null;
4103
- throw error;
4104
- });
4105
- if (raw !== null || dirname9(root) === root)
4106
- break;
4107
- root = dirname9(root);
4108
- }
4109
- if (raw === null)
4110
- return null;
4111
- if (Buffer.byteLength(raw) > 16777216)
4112
- throw new Error("Build provenance is oversized.");
4113
- const record = schema.parse(JSON.parse(raw));
4114
- if (gitHash("commit", Buffer.from(record.commit)) !== record.revision)
4115
- throw new Error("The build revision is not the supplied Git commit.");
4116
- const expectedTree = /^tree ([0-9a-f]{40})\n/u.exec(record.commit)?.[1];
4117
- if (treeHash(record.entries) !== expectedTree)
4118
- throw new Error("The build file inventory does not belong to this Git commit.");
4119
- const bound = new Map(record.entries.map((entry) => [entry.path, entry]));
4120
- const configurations = /* @__PURE__ */ new Map();
4121
- for (const config of record.providerConfigurations) {
4122
- const entry = bound.get(config.path);
4123
- if (!entry || entry.mode === "120000" || configurations.has(config.path) || gitHash("blob", Buffer.from(config.source)) !== entry.oid)
4124
- throw new Error("The original provider configuration is not bound to the Git commit.");
4125
- configurations.set(config.path, config.source);
4126
- }
4127
- if (record.entries.some((entry) => /(?:^|\/)vercel\.json$/u.test(entry.path) && !configurations.has(entry.path)))
4128
- throw new Error("The committed provider configuration is missing from the build provenance.");
4129
- const appRelative = relative7(root, projectDirectory).split(sep3).join("/");
4130
- if (!bound.has(appRelative ? `${appRelative}/package.json` : "package.json"))
4131
- throw new Error("The selected app is not part of the committed upload.");
4132
- for (const entry of record.entries) {
4133
- const path = join12(root, entry.path);
4134
- const stat = await lstat4(path).catch((error) => {
4135
- if (error.code === "ENOENT")
4136
- return null;
4137
- throw error;
4138
- });
4139
- if (!stat)
4140
- continue;
4141
- if (stat.isSymbolicLink()) {
4142
- const { readlink: readlink2 } = await import("fs/promises");
4143
- if (entry.mode !== "120000" || gitHash("blob", Buffer.from(await readlink2(path))) !== entry.oid)
4144
- throw new Error("A deployed symbolic link differs from the commit.");
4145
- } else {
4146
- const contents = stat.isFile() ? await readFile12(path) : null;
4147
- if (contents && entry.mode !== "120000" && gitHash("blob", contents) === entry.oid)
4148
- continue;
4149
- const original = configurations.get(entry.path);
4150
- if (contents && original && entry.mode !== "120000") {
4151
- try {
4152
- const object = z40.record(z40.string(), z40.unknown());
4153
- const actual = object.parse(JSON.parse(contents.toString("utf8")));
4154
- const expected = object.parse(JSON.parse(original));
4155
- if (!Object.hasOwn(expected, "version") && actual.version === 2)
4156
- delete actual.version;
4157
- if (!Object.hasOwn(expected, "name") && typeof actual.name === "string" && /^[a-z0-9][a-z0-9._-]{0,99}$/iu.test(actual.name))
4158
- delete actual.name;
4159
- if (isDeepStrictEqual(actual, expected))
4160
- continue;
4161
- } catch {
4162
- }
4163
- }
4164
- throw new Error(`A deployed file ${JSON.stringify(entry.path).slice(0, 260)} differs from the committed upload.`);
4165
- }
4166
- }
4167
- return record.revision;
4168
- }
4169
- function treeHash(entries) {
4170
- const root = /* @__PURE__ */ new Map();
4171
- for (const entry of entries) {
4172
- const parts = entry.path.split("/");
4173
- if (parts.some((part) => !part || part === "." || part === ".." || part.includes("\0") || part.includes("\\")))
4174
- throw new Error("Unsafe Git inventory path.");
4175
- let tree = root;
4176
- for (const part of parts.slice(0, -1)) {
4177
- let child = tree.get(part);
4178
- if (!child) {
4179
- child = /* @__PURE__ */ new Map();
4180
- tree.set(part, child);
4181
- }
4182
- if (!(child instanceof Map))
4183
- throw new Error("Conflicting Git inventory path.");
4184
- tree = child;
4185
- }
4186
- const leaf = parts.at(-1);
4187
- if (tree.has(leaf))
4188
- throw new Error("Duplicate Git inventory path.");
4189
- tree.set(leaf, { mode: entry.mode, oid: entry.oid });
4190
- }
4191
- const hash2 = (tree) => {
4192
- const sorted = [...tree].sort(([a, av], [b, bv]) => Buffer.compare(Buffer.from(a + (av instanceof Map ? "/" : "")), Buffer.from(b + (bv instanceof Map ? "/" : ""))));
4193
- return gitHash("tree", Buffer.concat(sorted.map(([path, value]) => Buffer.concat([
4194
- Buffer.from(`${value instanceof Map ? "40000" : value.mode} ${path}\0`),
4195
- Buffer.from(value instanceof Map ? hash2(value) : value.oid, "hex")
4196
- ]))));
4197
- };
4198
- return hash2(root);
4199
- }
4200
-
4201
- // ../cli/dist/commands/setup-deploy.js
4202
- import { createHash as createHash4, randomBytes as randomBytes2, randomUUID as randomUUID7 } from "crypto";
4203
- import { access as access7, mkdir as mkdir9, mkdtemp, rm as rm5, writeFile as writeFile6 } from "fs/promises";
4204
- import { tmpdir } from "os";
4205
- import { join as join13 } from "path";
4206
- import { z as z41 } from "zod";
4207
- var envSchema = z41.object({
4208
- id: z41.string(),
4209
- key: z41.string(),
4210
- target: z41.array(z41.string()),
4211
- type: z41.string(),
4212
- comment: z41.string().optional(),
4213
- updatedAt: z41.number().optional()
4214
- });
4215
- var deploymentSchema = z41.object({
4216
- id: z41.string(),
4217
- projectId: z41.string(),
4218
- ownerId: z41.string().optional(),
4219
- target: z41.string().nullable(),
4220
- readyState: z41.string(),
4221
- createdAt: z41.number(),
4222
- url: z41.string(),
4223
- meta: z41.record(z41.string(), z41.unknown()).optional(),
4224
- gitSource: z41.object({ sha: z41.string().optional() }).nullable().optional()
4225
- });
4226
- var buildProofSchema = z41.object({
4227
- node: z41.string(),
4228
- packageManager: z41.enum(["npm", "pnpm"]),
4229
- packageManagerVersion: z41.string(),
4230
- lockfileHash: z41.string(),
4231
- revision: z41.string(),
4232
- fieldContractHash: z41.string(),
4233
- siteplane: z41.string(),
4234
- runtimeNext: z41.string(),
4235
- analytics: z41.string().optional(),
4236
- next: z41.string(),
4237
- react: z41.string()
4238
- }).strict();
4239
- var defaults = {
4240
- preflight: setupPreflightCommand,
4241
- context: siteSetupContextCommand,
4242
- api: setupVercelApi,
4243
- process: setupProcess,
4244
- verify: siteSetupVerifyCommand,
4245
- post: postSiteSetup,
4246
- writeBuildProvenance,
4247
- analyticsPublicKey: analyticsPublicKeyCommand,
4248
- now: Date.now,
4249
- pause: (milliseconds) => new Promise((resolve5) => setTimeout(resolve5, milliseconds))
4250
- };
4251
-
4252
- // ../cli/dist/commands/setup-claim.js
4253
- import { z as z42 } from "zod";
4254
-
4255
2628
  // src/next.ts
4256
2629
  var SiteplaneNextContractError = class extends Error {
4257
2630
  constructor(code, message) {
@@ -4262,14 +2635,14 @@ var SiteplaneNextContractError = class extends Error {
4262
2635
  code;
4263
2636
  };
4264
2637
  async function scanNextProjectFieldContract(projectDir) {
4265
- const resolvedProjectDir = resolve4(projectDir);
2638
+ const resolvedProjectDir = resolve(projectDir);
4266
2639
  const filePaths = await resolveScanFilePaths([], {
4267
2640
  projectDir: resolvedProjectDir
4268
2641
  });
4269
2642
  const files = await Promise.all(
4270
2643
  filePaths.map(async (filePath) => ({
4271
2644
  filePath,
4272
- sourceText: await readFile13(filePath, "utf8")
2645
+ sourceText: await readFile5(filePath, "utf8")
4273
2646
  }))
4274
2647
  );
4275
2648
  const result = scanNextSourceFilesToSiteFieldContract(files, {
@@ -4298,7 +2671,7 @@ async function withSiteplane(nextConfig, options = {}) {
4298
2671
  "Siteplane booking.site must be the Site ID from Booking settings."
4299
2672
  );
4300
2673
  for (const folder of ["app/booking", "src/app/booking"]) {
4301
- if (await access8(join14(projectDir, folder)).then(
2674
+ if (await access2(join6(projectDir, folder)).then(
4302
2675
  () => true,
4303
2676
  () => false
4304
2677
  ))
@@ -4328,34 +2701,13 @@ async function withSiteplane(nextConfig, options = {}) {
4328
2701
  };
4329
2702
  }
4330
2703
  };
4331
- const hasEditor = await access8(
4332
- join14(projectDir, "siteplane.config.json")
4333
- ).then(
4334
- () => true,
4335
- () => false
4336
- );
4337
- if (!hasEditor) return { ...integrated, env: { ...nextConfig.env } };
2704
+ return { ...integrated, env: { ...nextConfig.env } };
4338
2705
  }
4339
2706
  const config = await readProjectConfig(projectDir);
4340
2707
  const scan = await scanNextProjectFieldContract(projectDir);
4341
2708
  const requestedRevision = options.buildRevision?.trim() || process.env.SITEPLANE_BUILD_REVISION?.trim();
4342
2709
  const providerRevision = process.env.VERCEL === "1" ? process.env.VERCEL_GIT_COMMIT_SHA?.trim() : void 0;
4343
- const buildRevision = providerRevision || await readGitRevision2(projectDir) || await readBuildProvenance(projectDir) || requestedRevision || "local";
4344
- if (process.env.VERCEL === "1" && /^[0-9a-f]{40}$/u.test(buildRevision)) {
4345
- try {
4346
- await emitBuildProof(
4347
- projectDir,
4348
- config.packages,
4349
- buildRevision,
4350
- scan.fieldContractHash
4351
- );
4352
- } catch (error) {
4353
- const detail = error instanceof SiteplaneNextContractError ? error.code : "unavailable";
4354
- console.warn(
4355
- `[Siteplane] Build proof ${detail}; the website build continues. Run the scoped Siteplane setup verification when editor evidence must be refreshed.`
4356
- );
4357
- }
4358
- }
2710
+ const buildRevision = providerRevision || await readGitRevision(projectDir) || requestedRevision || "local";
4359
2711
  const hasImages = scan.contract.fields.some(
4360
2712
  (field) => field.fieldType === "image"
4361
2713
  );
@@ -4376,10 +2728,10 @@ async function withSiteplane(nextConfig, options = {}) {
4376
2728
  }
4377
2729
  };
4378
2730
  }
4379
- var execFileAsync3 = promisify4(execFile4);
4380
- async function readGitRevision2(projectDir) {
2731
+ var execFileAsync = promisify(execFile);
2732
+ async function readGitRevision(projectDir) {
4381
2733
  try {
4382
- const result = await execFileAsync3("git", ["rev-parse", "HEAD"], {
2734
+ const result = await execFileAsync("git", ["rev-parse", "HEAD"], {
4383
2735
  cwd: projectDir
4384
2736
  });
4385
2737
  return result.stdout.trim();
@@ -4391,19 +2743,19 @@ function frameHeaders(rules, adminOrigin, imageOrigin) {
4391
2743
  const policy = `frame-ancestors 'self' ${adminOrigin}`;
4392
2744
  const hasFrameOptions = rules.some(
4393
2745
  (rule) => rule.headers.some(
4394
- (header) => header.key.toLowerCase() === "x-frame-options"
2746
+ (header2) => header2.key.toLowerCase() === "x-frame-options"
4395
2747
  )
4396
2748
  );
4397
2749
  const prepared = rules.map((rule) => ({
4398
2750
  ...rule,
4399
- headers: rule.headers.map((header) => {
4400
- if (header.key.toLowerCase() !== "content-security-policy") return header;
2751
+ headers: rule.headers.map((header2) => {
2752
+ if (header2.key.toLowerCase() !== "content-security-policy") return header2;
4401
2753
  const ancestors = /(?:^|;)\s*frame-ancestors\s+([^;]+)/iu.test(
4402
- header.value
2754
+ header2.value
4403
2755
  );
4404
- const value = ancestors || hasFrameOptions ? header.value : `${header.value.replace(/;\s*$/u, "")}; ${policy}`;
2756
+ const value = ancestors || hasFrameOptions ? header2.value : `${header2.value.replace(/;\s*$/u, "")}; ${policy}`;
4405
2757
  return {
4406
- ...header,
2758
+ ...header2,
4407
2759
  value: imageOrigin ? prepareImageCsp(value, imageOrigin) : value
4408
2760
  };
4409
2761
  })
@@ -4428,7 +2780,7 @@ function readImageWebsiteOrigin() {
4428
2780
  } catch {
4429
2781
  throw new SiteplaneNextContractError(
4430
2782
  "image_origin_missing",
4431
- "If configured, SITEPLANE_SITE_ORIGIN must be the exact public HTTPS website origin. setup deploy sets it from the verified provider domain; local fallback-image builds can omit it. Never substitute a wildcard or private host."
2783
+ "If configured, SITEPLANE_SITE_ORIGIN must be the exact public HTTPS website origin; local fallback-image builds can omit it. Never substitute a wildcard or private host."
4432
2784
  );
4433
2785
  }
4434
2786
  }
@@ -4469,14 +2821,14 @@ function prepareImageCsp(policy, websiteOrigin) {
4469
2821
  "Split combined CSP policies into separate header rules before image preparation; preserve every existing directive."
4470
2822
  );
4471
2823
  const directives = policy.split(";").map((part) => part.trim()).filter(Boolean);
4472
- const find = (name2) => directives.map((part, index) => ({ index, tokens: part.split(/\s+/u) })).filter((part) => part.tokens[0]?.toLowerCase() === name2);
4473
- const image = find("img-src"), defaults2 = find("default-src");
4474
- if (image.length > 1 || defaults2.length > 1)
2824
+ const find = (name) => directives.map((part, index) => ({ index, tokens: part.split(/\s+/u) })).filter((part) => part.tokens[0]?.toLowerCase() === name);
2825
+ const image = find("img-src"), defaults = find("default-src");
2826
+ if (image.length > 1 || defaults.length > 1)
4475
2827
  throw new SiteplaneNextContractError(
4476
2828
  "image_policy_conflict",
4477
2829
  "Remove ambiguous duplicate img-src/default-src directives before image preparation without changing unrelated policies."
4478
2830
  );
4479
- const existing = image[0] ?? defaults2[0];
2831
+ const existing = image[0] ?? defaults[0];
4480
2832
  if (!existing) return policy;
4481
2833
  const sources = existing.tokens.slice(1).filter((source) => source !== "'none'");
4482
2834
  for (const source of [
@@ -4491,53 +2843,6 @@ function prepareImageCsp(policy, websiteOrigin) {
4491
2843
  else directives.push(value);
4492
2844
  return directives.join("; ");
4493
2845
  }
4494
- async function emitBuildProof(projectDir, packages, revision, fieldContractHash) {
4495
- const [cli, runtime, next, react] = await Promise.all(
4496
- ["siteplane", "@siteplane/runtime-next", "next", "react"].map(
4497
- (name2) => readInstalledPackage(projectDir, name2)
4498
- )
4499
- );
4500
- const analytics = packages.analytics ? await readInstalledPackage(projectDir, "@siteplane/analytics") : void 0;
4501
- if (analytics?.version !== packages.analytics || cli.version !== packages.siteplane || runtime.version !== packages.runtimeNext)
4502
- throw new SiteplaneNextContractError(
4503
- "build_identity_missing",
4504
- "The provider installed different Siteplane package versions than the task requires."
4505
- );
4506
- const executable = process.env.npm_execpath;
4507
- if (!executable)
4508
- throw new SiteplaneNextContractError(
4509
- "build_identity_missing",
4510
- "Run the provider build through the selected npm/pnpm executable so its actual version can be verified."
4511
- );
4512
- const packageManager = /pnpm/iu.test(executable) ? "pnpm" : "npm";
4513
- const packageManagerVersion = (await execFileAsync3(process.execPath, [executable, "--version"], {
4514
- cwd: projectDir
4515
- })).stdout.trim();
4516
- let directory = resolve4(projectDir);
4517
- let lock = null;
4518
- while (true) {
4519
- lock = await readFile13(
4520
- join14(
4521
- directory,
4522
- packageManager === "npm" ? "package-lock.json" : "pnpm-lock.yaml"
4523
- ),
4524
- "utf8"
4525
- ).catch((error) => {
4526
- if (error.code === "ENOENT") return null;
4527
- throw error;
4528
- });
4529
- if (lock !== null || dirname10(directory) === directory) break;
4530
- directory = dirname10(directory);
4531
- }
4532
- if (!lock)
4533
- throw new SiteplaneNextContractError(
4534
- "build_identity_missing",
4535
- "The provider build is missing the selected canonical lockfile."
4536
- );
4537
- console.info(
4538
- `SITEPLANE_BUILD_PROOF=${JSON.stringify({ node: process.versions.node, packageManager, packageManagerVersion, lockfileHash: `sha256:${createHash5("sha256").update(lock).digest("hex")}`, revision, fieldContractHash, siteplane: cli.version, runtimeNext: runtime.version, ...analytics ? { analytics: analytics.version } : {}, next: next.version, react: react.version })}`
4539
- );
4540
- }
4541
2846
  export {
4542
2847
  SiteplaneNextContractError,
4543
2848
  scanNextProjectFieldContract,