siteplane 0.1.41 → 0.1.43

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,8 +1,9 @@
1
1
  // src/next.ts
2
- import { execFile as execFile3 } from "child_process";
3
- import { readFile as readFile8 } from "fs/promises";
4
- import { resolve } from "path";
5
- import { promisify as promisify3 } from "util";
2
+ import { execFile as execFile4 } from "child_process";
3
+ import { createHash as createHash5 } from "crypto";
4
+ import { readFile as readFile13 } from "fs/promises";
5
+ import { dirname as dirname9, join as join12, resolve as resolve4 } from "path";
6
+ import { promisify as promisify4 } from "util";
6
7
 
7
8
  // ../cli/dist/analytics/manifest.js
8
9
  import { mkdir, readFile, writeFile } from "fs/promises";
@@ -822,7 +823,7 @@ var bookingManifestSchema = z8.object({
822
823
  var BOOKING_CREATE_PAYLOAD_LIMIT_BYTES = 16 * 1024;
823
824
 
824
825
  // ../shared/dist/bridge-protocol.js
825
- import { z as z15 } from "zod";
826
+ import { z as z16 } from "zod";
826
827
 
827
828
  // ../shared/dist/field-id.js
828
829
  import { z as z9 } from "zod";
@@ -869,21 +870,70 @@ var imageValueSchema = z11.object({
869
870
  ]).optional()
870
871
  });
871
872
 
873
+ // ../shared/dist/setup-deployment.js
874
+ import { z as z12 } from "zod";
875
+ var version = z12.string().regex(/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/u);
876
+ var hash = z12.string().regex(/^sha256:[0-9a-f]{64}$/u);
877
+ var setupDeploymentRecordSchema = z12.object({
878
+ version: z12.literal(1),
879
+ operationId: z12.string().uuid(),
880
+ provider: z12.literal("vercel"),
881
+ projectId: z12.string().regex(/^prj_[A-Za-z0-9]+$/u),
882
+ teamId: z12.string().regex(/^(?:team|user)_[A-Za-z0-9]+$/u),
883
+ origin: z12.string().url().refine((value) => {
884
+ const url = new URL(value);
885
+ return url.protocol === "https:" && url.origin === value && !url.username && !url.password;
886
+ }),
887
+ deploymentId: z12.string().regex(/^dpl_[A-Za-z0-9]+$/u).nullable(),
888
+ revision: z12.string().regex(/^[0-9a-f]{40}$/u),
889
+ fieldContractHash: hash,
890
+ packages: z12.object({ siteplane: version, runtimeNext: version }).strict(),
891
+ configurationFingerprint: hash,
892
+ adminSecretGeneration: z12.string().uuid(),
893
+ revalidationGeneration: z12.number().int().positive(),
894
+ startedAt: z12.string().datetime(),
895
+ environmentWrittenAt: z12.string().datetime().nullable(),
896
+ deployRequestedAt: z12.string().datetime().nullable(),
897
+ deadline: z12.string().datetime(),
898
+ phase: z12.enum([
899
+ "planned",
900
+ "environment_written",
901
+ "deploy_requested",
902
+ "deployed",
903
+ "verified",
904
+ "failed"
905
+ ]),
906
+ build: z12.object({
907
+ node: version,
908
+ packageManager: z12.enum(["npm", "pnpm"]),
909
+ packageManagerVersion: version,
910
+ lockfileHash: hash
911
+ }).strict().nullable()
912
+ }).strict();
913
+ var setupDeploymentInputSchema = z12.discriminatedUnion("action", [
914
+ z12.object({ action: z12.literal("read") }).strict(),
915
+ z12.object({
916
+ action: z12.literal("record"),
917
+ expectedOperationId: z12.string().uuid().nullable(),
918
+ record: setupDeploymentRecordSchema
919
+ }).strict()
920
+ ]);
921
+
872
922
  // ../shared/dist/site-setup.js
873
- import { z as z14 } from "zod";
923
+ import { z as z15 } from "zod";
874
924
 
875
925
  // ../shared/dist/site-field-contract.js
876
- import { z as z13 } from "zod";
926
+ import { z as z14 } from "zod";
877
927
 
878
928
  // ../shared/dist/fallback-hash.js
879
- import { z as z12 } from "zod";
929
+ import { z as z13 } from "zod";
880
930
  var SAFE_REPRESENTATION_REASONS = [
881
931
  "asset_import_rewritten",
882
932
  "relative_url_normalized",
883
933
  "line_endings_normalized",
884
934
  "image_value_serialized"
885
935
  ];
886
- var safeRepresentationReasonSchema = z12.enum(SAFE_REPRESENTATION_REASONS);
936
+ var safeRepresentationReasonSchema = z13.enum(SAFE_REPRESENTATION_REASONS);
887
937
  function canonicalizeFallbackValue(input) {
888
938
  const fieldType = fieldTypeSchema.parse(input.fieldType);
889
939
  if (input.safeRepresentationReason !== void 0) {
@@ -919,10 +969,10 @@ function createCanonicalFallbackHash(input) {
919
969
  const payload = stableJsonStringify(canonical);
920
970
  return `sha256:${sha256Hex(payload)}`;
921
971
  }
922
- var linkFallbackSchema = z12.object({
923
- href: z12.string().trim().min(1),
924
- label: z12.string().trim().min(1).optional(),
925
- target: z12.enum(["_self", "_blank"]).optional()
972
+ var linkFallbackSchema = z13.object({
973
+ href: z13.string().trim().min(1),
974
+ label: z13.string().trim().min(1).optional(),
975
+ target: z13.enum(["_self", "_blank"]).optional()
926
976
  }).passthrough();
927
977
  function normalizeLineEndings(value) {
928
978
  return value.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
@@ -1100,67 +1150,67 @@ var SHA256_CONSTANTS = [
1100
1150
  // ../shared/dist/site-field-contract.js
1101
1151
  var fieldContractVersion = "1.0.0";
1102
1152
  var scannerContractVersion = "1.0.0";
1103
- var siteFieldStatusSchema = z13.enum(["hidden", "active"]);
1104
- var semanticVersionSchema = z13.string().regex(/^\d+\.\d+\.\d+$/u);
1105
- var siteFieldRouteKeySchema = z13.string().trim().refine((value) => value === "$global" || value.startsWith("/") && !value.includes("?") && !value.includes("#") && (value === "/" || !value.endsWith("/")), "Route keys must be canonical paths or $global.");
1106
- var repositoryRelativePosixPathSchema = z13.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.");
1107
- var sourceMappingSchema = z13.object({
1108
- kind: z13.literal("function"),
1153
+ var siteFieldStatusSchema = z14.enum(["hidden", "active"]);
1154
+ var semanticVersionSchema = z14.string().regex(/^\d+\.\d+\.\d+$/u);
1155
+ var siteFieldRouteKeySchema = z14.string().trim().refine((value) => value === "$global" || value.startsWith("/") && !value.includes("?") && !value.includes("#") && (value === "/" || !value.endsWith("/")), "Route keys must be canonical paths or $global.");
1156
+ var repositoryRelativePosixPathSchema = z14.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.");
1157
+ var sourceMappingSchema = z14.object({
1158
+ kind: z14.literal("function"),
1109
1159
  filePath: repositoryRelativePosixPathSchema,
1110
- exportName: z13.string().trim().min(1).optional(),
1111
- sourcePath: z13.string().trim().min(1).optional(),
1160
+ exportName: z14.string().trim().min(1).optional(),
1161
+ sourcePath: z14.string().trim().min(1).optional(),
1112
1162
  editTarget: fieldIdSchema.optional()
1113
1163
  }).strict();
1114
- var domMappingSchema = z13.object({
1115
- attribute: z13.literal("data-siteplane-field-id"),
1116
- previewStrategy: z13.enum(["dom", "event"])
1164
+ var domMappingSchema = z14.object({
1165
+ attribute: z14.literal("data-siteplane-field-id"),
1166
+ previewStrategy: z14.enum(["dom", "event"])
1117
1167
  }).strict();
1118
- var fieldBaseSchema = z13.object({
1168
+ var fieldBaseSchema = z14.object({
1119
1169
  fieldId: fieldIdSchema,
1120
1170
  routeKey: siteFieldRouteKeySchema,
1121
1171
  source: sourceMappingSchema,
1122
1172
  dom: domMappingSchema.optional()
1123
1173
  }).strict();
1124
- var linkFallbackSchema2 = z13.object({
1125
- href: z13.string().trim().min(1),
1126
- label: z13.string().trim().min(1).optional(),
1127
- target: z13.enum(["_self", "_blank"]).optional()
1174
+ var linkFallbackSchema2 = z14.object({
1175
+ href: z14.string().trim().min(1),
1176
+ label: z14.string().trim().min(1).optional(),
1177
+ target: z14.enum(["_self", "_blank"]).optional()
1128
1178
  }).strict();
1129
- var imageFallbackSchema = z13.object({
1130
- src: z13.string().trim().min(1),
1131
- alt: z13.string().trim().max(300),
1132
- width: z13.number().int().positive().optional(),
1133
- height: z13.number().int().positive().optional(),
1134
- crop: z13.object({
1135
- x: z13.number().min(0).max(100),
1136
- y: z13.number().min(0).max(100),
1137
- zoom: z13.number().min(1).max(4),
1138
- aspectRatio: z13.number().positive().max(10)
1179
+ var imageFallbackSchema = z14.object({
1180
+ src: z14.string().trim().min(1),
1181
+ alt: z14.string().trim().max(300),
1182
+ width: z14.number().int().positive().optional(),
1183
+ height: z14.number().int().positive().optional(),
1184
+ crop: z14.object({
1185
+ x: z14.number().min(0).max(100),
1186
+ y: z14.number().min(0).max(100),
1187
+ zoom: z14.number().min(1).max(4),
1188
+ aspectRatio: z14.number().positive().max(10)
1139
1189
  }).strict().optional()
1140
1190
  }).strict();
1141
- var siteFieldContractFieldSchema = z13.discriminatedUnion("fieldType", [
1191
+ var siteFieldContractFieldSchema = z14.discriminatedUnion("fieldType", [
1142
1192
  fieldBaseSchema.extend({
1143
- fieldType: z13.literal("text"),
1144
- fallback: z13.string()
1193
+ fieldType: z14.literal("text"),
1194
+ fallback: z14.string()
1145
1195
  }),
1146
1196
  fieldBaseSchema.extend({
1147
- fieldType: z13.literal("longText"),
1148
- fallback: z13.string()
1197
+ fieldType: z14.literal("longText"),
1198
+ fallback: z14.string()
1149
1199
  }),
1150
1200
  fieldBaseSchema.extend({
1151
- fieldType: z13.literal("link"),
1201
+ fieldType: z14.literal("link"),
1152
1202
  fallback: linkFallbackSchema2
1153
1203
  }),
1154
1204
  fieldBaseSchema.extend({
1155
- fieldType: z13.literal("image"),
1205
+ fieldType: z14.literal("image"),
1156
1206
  fallback: imageFallbackSchema
1157
1207
  })
1158
1208
  ]);
1159
- var siteFieldContractV1Schema = z13.object({
1160
- version: z13.literal(1),
1209
+ var siteFieldContractV1Schema = z14.object({
1210
+ version: z14.literal(1),
1161
1211
  fieldContractVersion: semanticVersionSchema,
1162
1212
  scannerContractVersion: semanticVersionSchema,
1163
- fields: z13.array(siteFieldContractFieldSchema)
1213
+ fields: z14.array(siteFieldContractFieldSchema)
1164
1214
  }).strict().superRefine((contract, context) => {
1165
1215
  const seen = /* @__PURE__ */ new Set();
1166
1216
  for (const [index, field] of contract.fields.entries()) {
@@ -1220,55 +1270,20 @@ var SITE_SETUP_OWNER_EDITABILITY_NOTE_MAX_LENGTH = 2e3;
1220
1270
  var SITE_SETUP_OWNER_EDITABILITY_NOTE_MAX_BYTES = 8e3;
1221
1271
  var CONTINUE_SITE_SETUP_ITEMS_MAX_BYTES = 32 * 1024;
1222
1272
  var CONTINUE_SITE_SETUP_HTTP_BODY_MAX_BYTES = 64 * 1024;
1223
- var siteSetupRunStatusSchema = z14.enum(SITE_SETUP_RUN_STATUSES);
1224
- var siteSetupRunModeSchema = z14.enum(SITE_SETUP_RUN_MODES);
1225
- var siteSetupErrorCodeSchema = z14.enum(SITE_SETUP_ERROR_CODES);
1226
- var siteSetupTaskSchema = z14.object({
1227
- contractVersion: z14.literal("siteplane.setup-task.v1"),
1228
- workflow: z14.enum(["initial_setup", "structure_update"]),
1229
- goal: z14.string().min(1),
1230
- modules: z14.tuple([z14.literal("visual_editor")]),
1231
- packages: z14.object({
1232
- siteplane: z14.string().regex(/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/u),
1233
- runtimeNext: z14.string().regex(/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/u)
1234
- }).strict(),
1235
- communication: z14.object({
1236
- beforeSourceChanges: z14.string().min(1),
1237
- updates: z14.array(z14.string().min(1)).min(1),
1238
- blocker: z14.string().min(1)
1239
- }).strict(),
1240
- discovery: z14.object({
1241
- inspectPublicRoutes: z14.boolean(),
1242
- contentKinds: z14.array(z14.enum(["text", "longText", "link", "image"])).min(1),
1243
- rules: z14.array(z14.string().min(1)).min(1)
1244
- }).strict(),
1245
- steps: z14.array(z14.object({
1246
- id: z14.enum([
1247
- "inspect_repository",
1248
- "install_packages",
1249
- "instrument_fields",
1250
- "apply_contract",
1251
- "deploy_production",
1252
- "verify_deployment"
1253
- ]),
1254
- instruction: z14.string().min(1)
1255
- }).strict()).length(6),
1256
- completion: z14.object({
1257
- verifiedStatus: z14.literal("ready_for_review"),
1258
- instruction: z14.string().min(1)
1259
- }).strict()
1260
- }).strict();
1261
- var editorFieldSchema = z14.object({
1273
+ var siteSetupRunStatusSchema = z15.enum(SITE_SETUP_RUN_STATUSES);
1274
+ var siteSetupRunModeSchema = z15.enum(SITE_SETUP_RUN_MODES);
1275
+ var siteSetupErrorCodeSchema = z15.enum(SITE_SETUP_ERROR_CODES);
1276
+ var editorFieldSchema = z15.object({
1262
1277
  fieldId: fieldIdSchema,
1263
- label: z14.string().trim().min(1),
1264
- subsection: z14.string().trim().min(1).optional(),
1265
- description: z14.string().trim().min(1).optional(),
1266
- required: z14.boolean().optional(),
1267
- maxLength: z14.number().int().positive().optional()
1278
+ label: z15.string().trim().min(1),
1279
+ subsection: z15.string().trim().min(1).optional(),
1280
+ description: z15.string().trim().min(1).optional(),
1281
+ required: z15.boolean().optional(),
1282
+ maxLength: z15.number().int().positive().optional()
1268
1283
  }).strict();
1269
- var editorSectionSchema = z14.object({
1270
- label: z14.string().trim().min(1),
1271
- fields: z14.array(editorFieldSchema).min(1)
1284
+ var editorSectionSchema = z15.object({
1285
+ label: z15.string().trim().min(1),
1286
+ fields: z15.array(editorFieldSchema).min(1)
1272
1287
  }).strict().superRefine((section, context) => {
1273
1288
  const closedSubsections = /* @__PURE__ */ new Set();
1274
1289
  let currentSubsection;
@@ -1287,10 +1302,10 @@ var editorSectionSchema = z14.object({
1287
1302
  }
1288
1303
  }
1289
1304
  });
1290
- var editorRouteSchema = z14.object({
1305
+ var editorRouteSchema = z15.object({
1291
1306
  routeKey: siteFieldRouteKeySchema,
1292
- label: z14.string().trim().min(1),
1293
- sections: z14.array(editorSectionSchema).min(1)
1307
+ label: z15.string().trim().min(1),
1308
+ sections: z15.array(editorSectionSchema).min(1)
1294
1309
  }).strict().superRefine((route, context) => {
1295
1310
  const sections = /* @__PURE__ */ new Set();
1296
1311
  for (const [index, section] of route.sections.entries()) {
@@ -1304,9 +1319,9 @@ var editorRouteSchema = z14.object({
1304
1319
  sections.add(section.label);
1305
1320
  }
1306
1321
  });
1307
- var editorDefinitionV1Schema = z14.object({
1308
- version: z14.literal(1),
1309
- routes: z14.array(editorRouteSchema).min(1)
1322
+ var editorDefinitionV1Schema = z15.object({
1323
+ version: z15.literal(1),
1324
+ routes: z15.array(editorRouteSchema).min(1)
1310
1325
  }).strict().superRefine((definition, context) => {
1311
1326
  const routes = /* @__PURE__ */ new Set();
1312
1327
  const fields = /* @__PURE__ */ new Set();
@@ -1344,7 +1359,7 @@ var editorDefinitionV1Schema = z14.object({
1344
1359
  var forbiddenControlOrBidi = /[\u0000-\u001f\u007f-\u009f\u202a-\u202e\u2066-\u2069]/u;
1345
1360
  var forbiddenOwnerNoteControlOrBidi = /[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f-\u009f\u202a-\u202e\u2066-\u2069]/u;
1346
1361
  var unsafeLocator = /<\/?[a-z][^>]*>|\b(?:javascript|data:text\/html)\s*:|\bon[a-z]+\s*=/iu;
1347
- var renderedPathSchema = z14.string().trim().transform((value) => value !== "/" ? value.replace(/\/+$/u, "") : value).superRefine((value, context) => {
1362
+ var renderedPathSchema = z15.string().trim().transform((value) => value !== "/" ? value.replace(/\/+$/u, "") : value).superRefine((value, context) => {
1348
1363
  if (!value.startsWith("/") || value === "$global" || value.includes("?") || value.includes("#")) {
1349
1364
  context.addIssue({
1350
1365
  code: "custom",
@@ -1354,7 +1369,7 @@ var renderedPathSchema = z14.string().trim().transform((value) => value !== "/"
1354
1369
  addSafeByteIssues(value, CONTINUE_SITE_SETUP_RENDERED_PATH_MAX_BYTES, "renderedPath", context);
1355
1370
  });
1356
1371
  function normalizedSafeTextSchema(maxBytes, label) {
1357
- return z14.string().transform((value) => value.trim().replace(new RegExp("\\p{White_Space}+", "gu"), " ")).pipe(z14.string().min(1)).superRefine((value, context) => {
1372
+ return z15.string().transform((value) => value.trim().replace(new RegExp("\\p{White_Space}+", "gu"), " ")).pipe(z15.string().min(1)).superRefine((value, context) => {
1358
1373
  addSafeByteIssues(value, maxBytes, label, context);
1359
1374
  if (label === "locatorHint" && unsafeLocator.test(value)) {
1360
1375
  context.addIssue({
@@ -1371,12 +1386,12 @@ var correctionItemBase = {
1371
1386
  requestedLabel: normalizedSafeTextSchema(CONTINUE_SITE_SETUP_REQUESTED_LABEL_MAX_BYTES, "requestedLabel").optional(),
1372
1387
  requestedSection: normalizedSafeTextSchema(CONTINUE_SITE_SETUP_REQUESTED_SECTION_MAX_BYTES, "requestedSection").optional(),
1373
1388
  requestedSubsection: normalizedSafeTextSchema(CONTINUE_SITE_SETUP_REQUESTED_SUBSECTION_MAX_BYTES, "requestedSubsection").optional(),
1374
- requestedSortOrder: z14.number().int().nonnegative().optional()
1389
+ requestedSortOrder: z15.number().int().nonnegative().optional()
1375
1390
  };
1376
- var setupCorrectionItemSchema = z14.discriminatedUnion("kind", [
1377
- z14.object({ kind: z14.literal("text"), ...correctionItemBase }).strict(),
1378
- z14.object({ kind: z14.literal("link"), ...correctionItemBase }).strict(),
1379
- z14.object({ kind: z14.literal("image"), ...correctionItemBase }).strict()
1391
+ var setupCorrectionItemSchema = z15.discriminatedUnion("kind", [
1392
+ z15.object({ kind: z15.literal("text"), ...correctionItemBase }).strict(),
1393
+ z15.object({ kind: z15.literal("link"), ...correctionItemBase }).strict(),
1394
+ z15.object({ kind: z15.literal("image"), ...correctionItemBase }).strict()
1380
1395
  ]).superRefine((item, context) => {
1381
1396
  if (item.requestedSubsection && !item.requestedSection) {
1382
1397
  context.addIssue({
@@ -1386,7 +1401,7 @@ var setupCorrectionItemSchema = z14.discriminatedUnion("kind", [
1386
1401
  });
1387
1402
  }
1388
1403
  });
1389
- var setupCorrectionItemsSchema = z14.array(setupCorrectionItemSchema).max(CONTINUE_SITE_SETUP_MAX_ITEMS).superRefine((items, context) => {
1404
+ var setupCorrectionItemsSchema = z15.array(setupCorrectionItemSchema).max(CONTINUE_SITE_SETUP_MAX_ITEMS).superRefine((items, context) => {
1390
1405
  const bytes = utf8Bytes(stableJsonStringify(items));
1391
1406
  if (bytes > CONTINUE_SITE_SETUP_ITEMS_MAX_BYTES) {
1392
1407
  context.addIssue({
@@ -1395,7 +1410,7 @@ var setupCorrectionItemsSchema = z14.array(setupCorrectionItemSchema).max(CONTIN
1395
1410
  });
1396
1411
  }
1397
1412
  });
1398
- var siteSetupOwnerEditabilityNoteSchema = z14.string().trim().max(SITE_SETUP_OWNER_EDITABILITY_NOTE_MAX_LENGTH).superRefine((value, context) => {
1413
+ var siteSetupOwnerEditabilityNoteSchema = z15.string().max(SITE_SETUP_OWNER_EDITABILITY_NOTE_MAX_LENGTH).superRefine((value, context) => {
1399
1414
  if (utf8Bytes(value) > SITE_SETUP_OWNER_EDITABILITY_NOTE_MAX_BYTES) {
1400
1415
  context.addIssue({
1401
1416
  code: "custom",
@@ -1409,27 +1424,190 @@ var siteSetupOwnerEditabilityNoteSchema = z14.string().trim().max(SITE_SETUP_OWN
1409
1424
  });
1410
1425
  }
1411
1426
  });
1412
- var canonicalHashSchema = z14.string().regex(/^sha256:[0-9a-f]{64}$/iu);
1427
+ var SITE_SETUP_MODULE_SCOPES = {
1428
+ editing: ["setup:read", "setup:write"],
1429
+ analytics: [
1430
+ "analytics:setup",
1431
+ "analytics:sync",
1432
+ "analytics:test",
1433
+ "analytics:readiness",
1434
+ "analytics:agent_instructions",
1435
+ "analytics:public_key_read"
1436
+ ]
1437
+ };
1438
+ var siteSetupModulesSchema = z15.array(z15.enum(["editing", "analytics"])).min(1).max(2).refine((modules) => modules[0] === "editing" && (modules.length === 1 || modules[1] === "analytics"), "Choose Editing with optional Analytics.");
1439
+ function siteSetupScopes(modules) {
1440
+ return modules.flatMap((module) => [...SITE_SETUP_MODULE_SCOPES[module]]);
1441
+ }
1442
+ function hasExactSiteSetupScopes(scopes, modules) {
1443
+ const matches = (expected) => scopes.length === expected.length && expected.every((scope) => scopes.includes(scope));
1444
+ return modules ? matches(siteSetupScopes(modules)) : matches(siteSetupScopes(["editing"])) || matches(siteSetupScopes(["editing", "analytics"]));
1445
+ }
1446
+ var siteSetupActivityInputSchema = z15.object({
1447
+ phase: z15.enum([
1448
+ "inspecting",
1449
+ "integrating",
1450
+ "deploying",
1451
+ "verifying",
1452
+ "repairing"
1453
+ ]),
1454
+ textId: z15.enum([
1455
+ "inspecting",
1456
+ "integrating",
1457
+ "deploying",
1458
+ "verifying",
1459
+ "repairing"
1460
+ ])
1461
+ }).strict().refine((value) => value.phase === value.textId, "Activity text must describe its phase.");
1462
+ var nextActionFields = {
1463
+ actor: z15.enum(["agent", "user", "siteplane"]),
1464
+ boundary: z15.enum([
1465
+ "source",
1466
+ "environment",
1467
+ "deployment",
1468
+ "verification",
1469
+ "authorization",
1470
+ "review"
1471
+ ]),
1472
+ precondition: z15.string().min(1).max(1e3),
1473
+ instruction: z15.string().min(1).max(2e3),
1474
+ expectedEvidence: z15.string().min(1).max(1e3)
1475
+ };
1476
+ var siteSetupNextActionSchema = z15.discriminatedUnion("kind", [
1477
+ z15.object({
1478
+ ...nextActionFields,
1479
+ kind: z15.literal("run_command"),
1480
+ command: z15.string().min(1).max(500)
1481
+ }).strict(),
1482
+ z15.object({ ...nextActionFields, kind: z15.literal("agent_edit") }).strict(),
1483
+ z15.object({ ...nextActionFields, kind: z15.literal("needs_user_action") }).strict(),
1484
+ z15.object({ ...nextActionFields, kind: z15.literal("wait") }).strict(),
1485
+ z15.object({ ...nextActionFields, kind: z15.literal("done") }).strict()
1486
+ ]);
1487
+ var siteSetupTaskRunSchema = z15.object({
1488
+ runId: z15.string().uuid(),
1489
+ mode: siteSetupRunModeSchema,
1490
+ status: siteSetupRunStatusSchema,
1491
+ fieldContractHash: z15.string().nullable(),
1492
+ deploymentOrigin: z15.string().url().nullable(),
1493
+ deploymentRevision: z15.string().nullable(),
1494
+ publicRuntimeKeyId: z15.string().uuid().nullable(),
1495
+ reviewVersion: z15.string().nullable()
1496
+ }).strict();
1497
+ var siteSetupTaskProgressSchema = z15.object({
1498
+ progressStage: z15.enum([
1499
+ "waiting_for_connection",
1500
+ "agent_connected",
1501
+ "project_context_loaded",
1502
+ "fields_prepared",
1503
+ "deployment_verification",
1504
+ "ready_for_review",
1505
+ "action_required",
1506
+ "completed"
1507
+ ]),
1508
+ lastVerifiedAt: z15.string().datetime().nullable(),
1509
+ lastActivityAt: z15.string().datetime(),
1510
+ activitySource: z15.enum(["user", "server", "agent"]),
1511
+ activityPhase: siteSetupActivityInputSchema.shape.phase.nullable(),
1512
+ activityTextId: siteSetupActivityInputSchema.shape.textId.nullable()
1513
+ }).strict();
1514
+ var siteSetupTaskSchema = z15.object({
1515
+ contractVersion: z15.literal("siteplane.setup-task.v2"),
1516
+ workflow: z15.enum(["initial_setup", "structure_update"]),
1517
+ goal: z15.string().min(1),
1518
+ modules: siteSetupModulesSchema,
1519
+ authorizationVersion: z15.number().int().positive(),
1520
+ authorizedScopes: z15.array(z15.string()).min(2),
1521
+ site: z15.object({
1522
+ siteId: z15.string().uuid(),
1523
+ portalPath: z15.string(),
1524
+ adminOrigin: z15.string().url()
1525
+ }).strict().nullable(),
1526
+ run: siteSetupTaskRunSchema.nullable(),
1527
+ progress: siteSetupTaskProgressSchema.nullable(),
1528
+ deployment: setupDeploymentRecordSchema.nullable(),
1529
+ revalidationGeneration: z15.number().int().positive(),
1530
+ assignment: z15.literal("owned"),
1531
+ deadline: z15.string().datetime().nullable(),
1532
+ userInstructions: z15.object({
1533
+ text: siteSetupOwnerEditabilityNoteSchema,
1534
+ source: z15.literal("user"),
1535
+ trust: z15.literal("untrusted")
1536
+ }).strict(),
1537
+ corrections: setupCorrectionItemsSchema,
1538
+ contentSelectionSummary: z15.object({
1539
+ text: siteSetupOwnerEditabilityNoteSchema,
1540
+ source: z15.literal("agent"),
1541
+ trust: z15.literal("untrusted")
1542
+ }).strict().nullable(),
1543
+ environmentBindings: z15.array(z15.object({
1544
+ name: z15.string().regex(/^[A-Z][A-Z0-9_]+$/u),
1545
+ source: z15.string().min(1),
1546
+ sensitivity: z15.enum(["public", "secret"]),
1547
+ usage: z15.enum(["build", "server", "build_and_server"]),
1548
+ evidence: z15.string().min(1)
1549
+ }).strict()),
1550
+ nextAction: siteSetupNextActionSchema,
1551
+ error: z15.object({
1552
+ code: z15.string().regex(/^[a-z0-9_.]+$/u).max(160),
1553
+ boundary: nextActionFields.boundary,
1554
+ responsibleActor: nextActionFields.actor,
1555
+ retryable: z15.boolean(),
1556
+ retryAfter: z15.number().int().nonnegative().nullable(),
1557
+ requestId: z15.string().regex(/^[A-Za-z0-9_-]+$/u).max(128)
1558
+ }).strict().nullable(),
1559
+ packages: z15.object({
1560
+ siteplane: z15.string().regex(/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/u),
1561
+ runtimeNext: z15.string().regex(/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/u)
1562
+ }).strict(),
1563
+ communication: z15.object({
1564
+ beforeSourceChanges: z15.string().min(1),
1565
+ updates: z15.array(z15.string().min(1)).min(1),
1566
+ blocker: z15.string().min(1)
1567
+ }).strict(),
1568
+ discovery: z15.object({
1569
+ inspectPublicRoutes: z15.boolean(),
1570
+ contentKinds: z15.array(z15.enum(["text", "longText", "link", "image"])).min(1),
1571
+ rules: z15.array(z15.string().min(1)).min(1)
1572
+ }).strict(),
1573
+ steps: z15.array(z15.object({
1574
+ id: z15.enum([
1575
+ "inspect_repository",
1576
+ "install_packages",
1577
+ "instrument_fields",
1578
+ "apply_contract",
1579
+ "deploy_production",
1580
+ "verify_deployment"
1581
+ ]),
1582
+ instruction: z15.string().min(1)
1583
+ }).strict()).length(6),
1584
+ completion: z15.object({
1585
+ verifiedStatus: z15.literal("ready_for_review"),
1586
+ instruction: z15.string().min(1)
1587
+ }).strict()
1588
+ }).strict().refine((task) => hasExactSiteSetupScopes(task.authorizedScopes, task.modules), "Task scopes must exactly match its modules.");
1589
+ var canonicalHashSchema = z15.string().regex(/^sha256:[0-9a-f]{64}$/iu);
1413
1590
  var deploymentRevisionSchema = normalizedSafeTextSchema(256, "deploymentRevision");
1414
- var continueSiteSetupInputSchema = z14.object({
1415
- siteId: z14.string().uuid(),
1416
- runId: z14.string().uuid(),
1591
+ var continueSiteSetupInputSchema = z15.object({
1592
+ siteId: z15.string().uuid(),
1593
+ runId: z15.string().uuid(),
1417
1594
  expectedFieldContractHash: canonicalHashSchema,
1418
1595
  expectedDeploymentRevision: deploymentRevisionSchema,
1419
1596
  correctionItems: setupCorrectionItemsSchema,
1420
1597
  ownerEditabilityNote: siteSetupOwnerEditabilityNoteSchema.optional()
1421
1598
  }).strict();
1422
- var saveSiteSetupOwnerNoteInputSchema = z14.object({
1423
- siteId: z14.string().uuid(),
1424
- runId: z14.string().uuid(),
1599
+ var saveSiteSetupOwnerNoteInputSchema = z15.object({
1600
+ siteId: z15.string().uuid(),
1601
+ runId: z15.string().uuid(),
1425
1602
  expectedFieldContractHash: canonicalHashSchema,
1426
1603
  expectedDeploymentRevision: deploymentRevisionSchema,
1427
1604
  ownerEditabilityNote: siteSetupOwnerEditabilityNoteSchema
1428
1605
  }).strict();
1429
- var siteSetupContextInputSchema = z14.object({}).strict();
1430
- var siteSetupApplyInputSchema = z14.object({
1606
+ var siteSetupContextInputSchema = z15.object({}).strict();
1607
+ var siteSetupApplyInputSchema = z15.object({
1431
1608
  fieldContract: siteFieldContractV1Schema,
1432
- editorDefinition: editorDefinitionV1Schema
1609
+ editorDefinition: editorDefinitionV1Schema,
1610
+ contentSelectionSummary: siteSetupOwnerEditabilityNoteSchema.refine((text) => text.trim().length > 0, "Describe the selected content, important exclusions and any open gaps.")
1433
1611
  }).strict().superRefine((input, context) => {
1434
1612
  const contractRoutesByFieldId = new Map(input.fieldContract.fields.map((field) => [
1435
1613
  field.fieldId,
@@ -1493,37 +1671,37 @@ var siteSetupApplyInputSchema = z14.object({
1493
1671
  }
1494
1672
  }
1495
1673
  });
1496
- var siteSetupVerifyInputSchema = z14.object({
1497
- deploymentUrl: z14.string().url().refine((value) => value.startsWith("https://")),
1674
+ var siteSetupVerifyInputSchema = z15.object({
1675
+ deploymentUrl: z15.string().url().refine((value) => value.startsWith("https://")),
1498
1676
  deploymentRevision: deploymentRevisionSchema,
1499
- wait: z14.boolean().optional()
1677
+ wait: z15.boolean().optional()
1500
1678
  }).strict();
1501
- var siteSetupEvidenceInputSchema = z14.object({
1502
- siteId: z14.string().uuid(),
1503
- runId: z14.string().uuid(),
1679
+ var siteSetupEvidenceInputSchema = z15.object({
1680
+ siteId: z15.string().uuid(),
1681
+ runId: z15.string().uuid(),
1504
1682
  expectedFieldContractHash: canonicalHashSchema,
1505
- expectedDeploymentOrigin: z14.string().url().refine((value) => value.startsWith("https://")),
1683
+ expectedDeploymentOrigin: z15.string().url().refine((value) => value.startsWith("https://")),
1506
1684
  expectedDeploymentRevision: deploymentRevisionSchema,
1507
- publicRuntimeKeyId: z14.string().uuid(),
1685
+ publicRuntimeKeyId: z15.string().uuid(),
1508
1686
  bridgeSessionId: normalizedSafeTextSchema(256, "bridgeSessionId"),
1509
- observations: z14.array(z14.object({
1687
+ observations: z15.array(z15.object({
1510
1688
  fieldId: fieldIdSchema,
1511
1689
  routeKey: siteFieldRouteKeySchema,
1512
1690
  renderedPath: renderedPathSchema,
1513
- targetResolved: z14.boolean(),
1514
- previewAck: z14.boolean()
1691
+ targetResolved: z15.boolean(),
1692
+ previewAck: z15.boolean()
1515
1693
  }).strict().refine((value) => !value.previewAck || value.targetResolved, "Preview ACK requires a resolved target.")).min(1).max(200)
1516
1694
  }).strict();
1517
- var completeSiteSetupInputSchema = z14.object({
1518
- siteId: z14.string().uuid(),
1519
- runId: z14.string().uuid(),
1695
+ var completeSiteSetupInputSchema = z15.object({
1696
+ siteId: z15.string().uuid(),
1697
+ runId: z15.string().uuid(),
1520
1698
  expectedFieldContractHash: canonicalHashSchema,
1521
1699
  expectedDeploymentRevision: deploymentRevisionSchema,
1522
1700
  expectedReadyFingerprint: canonicalHashSchema
1523
1701
  }).strict();
1524
- var refreshSiteSetupDeploymentInputSchema = z14.object({
1525
- siteId: z14.string().uuid(),
1526
- deploymentUrl: z14.string().url().refine((value) => value.startsWith("https://")),
1702
+ var refreshSiteSetupDeploymentInputSchema = z15.object({
1703
+ siteId: z15.string().uuid(),
1704
+ deploymentUrl: z15.string().url().refine((value) => value.startsWith("https://")),
1527
1705
  deploymentRevision: deploymentRevisionSchema
1528
1706
  }).strict();
1529
1707
  function addSafeByteIssues(value, maxBytes, label, context) {
@@ -1546,34 +1724,34 @@ function utf8Bytes(value) {
1546
1724
 
1547
1725
  // ../shared/dist/bridge-protocol.js
1548
1726
  var BRIDGE_PROTOCOL_VERSION = 2;
1549
- var bridgeRectSchema = z15.object({
1550
- x: z15.number(),
1551
- y: z15.number(),
1552
- width: z15.number().nonnegative(),
1553
- height: z15.number().nonnegative()
1727
+ var bridgeRectSchema = z16.object({
1728
+ x: z16.number(),
1729
+ y: z16.number(),
1730
+ width: z16.number().nonnegative(),
1731
+ height: z16.number().nonnegative()
1554
1732
  });
1555
- var previewTextValueSchema = z15.object({
1556
- fieldType: z15.enum(["text", "longText"]),
1557
- value: z15.string()
1733
+ var previewTextValueSchema = z16.object({
1734
+ fieldType: z16.enum(["text", "longText"]),
1735
+ value: z16.string()
1558
1736
  });
1559
- var previewLinkValueSchema = z15.object({
1560
- fieldType: z15.literal("link"),
1561
- value: z15.object({
1562
- href: z15.string().trim().min(1),
1563
- label: z15.string().trim().min(1).optional()
1737
+ var previewLinkValueSchema = z16.object({
1738
+ fieldType: z16.literal("link"),
1739
+ value: z16.object({
1740
+ href: z16.string().trim().min(1),
1741
+ label: z16.string().trim().min(1).optional()
1564
1742
  })
1565
1743
  });
1566
- var previewImageValueSchema = z15.object({
1567
- fieldType: z15.literal("image"),
1744
+ var previewImageValueSchema = z16.object({
1745
+ fieldType: z16.literal("image"),
1568
1746
  value: imageValueSchema
1569
1747
  });
1570
- var bridgePreviewValueSchema = z15.discriminatedUnion("fieldType", [
1748
+ var bridgePreviewValueSchema = z16.discriminatedUnion("fieldType", [
1571
1749
  previewTextValueSchema,
1572
1750
  previewLinkValueSchema,
1573
1751
  previewImageValueSchema
1574
1752
  ]);
1575
- var fieldSelectionModeSchema = z15.enum(["replace", "range", "toggle"]);
1576
- var fieldBridgeMissingContentActionSchema = z15.enum([
1753
+ var fieldSelectionModeSchema = z16.enum(["replace", "range", "toggle"]);
1754
+ var fieldBridgeMissingContentActionSchema = z16.enum([
1577
1755
  "add",
1578
1756
  "select",
1579
1757
  "remove"
@@ -1592,77 +1770,77 @@ var FIELD_BRIDGE_MESSAGE_TYPES = [
1592
1770
  "siteplane:field-bridge:preview-scrolled",
1593
1771
  "siteplane:field-bridge:error"
1594
1772
  ];
1595
- var canonicalFieldContractHashSchema = z15.string().regex(/^sha256:[0-9a-f]{64}$/u);
1596
- var bridgeSectionSchema = z15.string().trim().min(1).max(256);
1597
- var realRenderedPathSchema = z15.string().trim().refine((value) => value.startsWith("/") && value !== "$global" && !value.includes("?") && !value.includes("#"), "A field bridge rendered path must be a real canonical path.");
1598
- var fieldBridgeIdentitySchema = z15.object({
1599
- publicRuntimeKeyId: z15.string().uuid(),
1773
+ var canonicalFieldContractHashSchema = z16.string().regex(/^sha256:[0-9a-f]{64}$/u);
1774
+ var bridgeSectionSchema = z16.string().trim().min(1).max(256);
1775
+ var realRenderedPathSchema = z16.string().trim().refine((value) => value.startsWith("/") && value !== "$global" && !value.includes("?") && !value.includes("#"), "A field bridge rendered path must be a real canonical path.");
1776
+ var fieldBridgeIdentitySchema = z16.object({
1777
+ publicRuntimeKeyId: z16.string().uuid(),
1600
1778
  fieldContractHash: canonicalFieldContractHashSchema,
1601
- deploymentRevision: z15.string().trim().min(1).max(256)
1779
+ deploymentRevision: z16.string().trim().min(1).max(256)
1602
1780
  }).strict();
1603
- var fieldBridgeBaseSchema = z15.object({
1604
- version: z15.literal(BRIDGE_PROTOCOL_VERSION),
1605
- type: z15.enum(FIELD_BRIDGE_MESSAGE_TYPES),
1606
- siteId: z15.string().uuid(),
1607
- sessionId: z15.string().trim().min(1),
1608
- publicRuntimeKeyId: z15.string().uuid(),
1781
+ var fieldBridgeBaseSchema = z16.object({
1782
+ version: z16.literal(BRIDGE_PROTOCOL_VERSION),
1783
+ type: z16.enum(FIELD_BRIDGE_MESSAGE_TYPES),
1784
+ siteId: z16.string().uuid(),
1785
+ sessionId: z16.string().trim().min(1),
1786
+ publicRuntimeKeyId: z16.string().uuid(),
1609
1787
  fieldContractHash: canonicalFieldContractHashSchema,
1610
- deploymentRevision: z15.string().trim().min(1).max(256),
1611
- requestId: z15.string().trim().min(1),
1612
- sentAt: z15.string().datetime()
1788
+ deploymentRevision: z16.string().trim().min(1).max(256),
1789
+ requestId: z16.string().trim().min(1),
1790
+ sentAt: z16.string().datetime()
1613
1791
  }).strict();
1614
- var fieldBridgeFieldSchema = z15.object({
1792
+ var fieldBridgeFieldSchema = z16.object({
1615
1793
  fieldId: fieldIdSchema,
1616
1794
  fieldType: fieldTypeSchema,
1617
1795
  routeKey: siteFieldRouteKeySchema,
1618
1796
  renderedPath: realRenderedPathSchema,
1619
- sourcePath: z15.string().trim().min(1).optional(),
1797
+ sourcePath: z16.string().trim().min(1).optional(),
1620
1798
  editTarget: fieldIdSchema,
1621
1799
  rect: bridgeRectSchema,
1622
- targetResolved: z15.literal(true),
1800
+ targetResolved: z16.literal(true),
1623
1801
  currentValue: bridgePreviewValueSchema.optional()
1624
1802
  }).strict();
1625
1803
  var fieldBridgeInitMessageSchema = fieldBridgeBaseSchema.extend({
1626
- type: z15.literal("siteplane:field-bridge:init"),
1627
- payload: z15.object({
1628
- adminOrigin: z15.string().url(),
1629
- customerOrigin: z15.string().url(),
1804
+ type: z16.literal("siteplane:field-bridge:init"),
1805
+ payload: z16.object({
1806
+ adminOrigin: z16.string().url(),
1807
+ customerOrigin: z16.string().url(),
1630
1808
  renderedPath: realRenderedPathSchema
1631
1809
  }).strict()
1632
1810
  });
1633
1811
  var fieldBridgeReadyMessageSchema = fieldBridgeBaseSchema.extend({
1634
- type: z15.literal("siteplane:field-bridge:ready"),
1635
- payload: z15.object({
1812
+ type: z16.literal("siteplane:field-bridge:ready"),
1813
+ payload: z16.object({
1636
1814
  renderedPath: realRenderedPathSchema,
1637
- fieldCount: z15.number().int().nonnegative(),
1638
- capabilities: z15.tuple([
1639
- z15.literal("field_selection"),
1640
- z15.literal("preview_values"),
1641
- z15.literal("field_evidence"),
1642
- z15.literal("visual_field_control")
1815
+ fieldCount: z16.number().int().nonnegative(),
1816
+ capabilities: z16.tuple([
1817
+ z16.literal("field_selection"),
1818
+ z16.literal("preview_values"),
1819
+ z16.literal("field_evidence"),
1820
+ z16.literal("visual_field_control")
1643
1821
  ])
1644
1822
  }).strict()
1645
1823
  });
1646
1824
  var fieldBridgeFieldsMessageSchema = fieldBridgeBaseSchema.extend({
1647
- type: z15.literal("siteplane:field-bridge:fields"),
1648
- payload: z15.object({
1825
+ type: z16.literal("siteplane:field-bridge:fields"),
1826
+ payload: z16.object({
1649
1827
  renderedPath: realRenderedPathSchema,
1650
- fields: z15.array(fieldBridgeFieldSchema)
1828
+ fields: z16.array(fieldBridgeFieldSchema)
1651
1829
  }).strict()
1652
1830
  });
1653
1831
  var fieldBridgeSelectFieldMessageSchema = fieldBridgeBaseSchema.extend({
1654
- type: z15.literal("siteplane:field-bridge:select-field"),
1655
- payload: z15.object({
1832
+ type: z16.literal("siteplane:field-bridge:select-field"),
1833
+ payload: z16.object({
1656
1834
  fieldId: fieldIdSchema,
1657
1835
  selectionMode: fieldSelectionModeSchema
1658
1836
  }).strict()
1659
1837
  });
1660
1838
  var fieldBridgeSetSelectedFieldMessageSchema = fieldBridgeBaseSchema.extend({
1661
- type: z15.literal("siteplane:field-bridge:set-selected-field"),
1662
- payload: z15.object({
1663
- fieldIds: z15.array(fieldIdSchema).max(200),
1839
+ type: z16.literal("siteplane:field-bridge:set-selected-field"),
1840
+ payload: z16.object({
1841
+ fieldIds: z16.array(fieldIdSchema).max(200),
1664
1842
  primaryFieldId: fieldIdSchema.nullable(),
1665
- scrollIntoView: z15.boolean().optional()
1843
+ scrollIntoView: z16.boolean().optional()
1666
1844
  }).strict().superRefine((value, context) => {
1667
1845
  if (value.fieldIds.length > 0 && value.primaryFieldId === null) {
1668
1846
  context.addIssue({
@@ -1681,58 +1859,58 @@ var fieldBridgeSetSelectedFieldMessageSchema = fieldBridgeBaseSchema.extend({
1681
1859
  })
1682
1860
  });
1683
1861
  var fieldBridgeApplyPreviewValuesMessageSchema = fieldBridgeBaseSchema.extend({
1684
- type: z15.literal("siteplane:field-bridge:apply-preview-values"),
1685
- payload: z15.object({ values: z15.record(fieldIdSchema, bridgePreviewValueSchema) }).strict()
1862
+ type: z16.literal("siteplane:field-bridge:apply-preview-values"),
1863
+ payload: z16.object({ values: z16.record(fieldIdSchema, bridgePreviewValueSchema) }).strict()
1686
1864
  });
1687
1865
  var fieldBridgeTestPreviewValuesMessageSchema = fieldBridgeBaseSchema.extend({
1688
- type: z15.literal("siteplane:field-bridge:test-preview-values"),
1689
- payload: z15.object({ fieldIds: z15.array(fieldIdSchema).min(1).max(200) }).strict()
1866
+ type: z16.literal("siteplane:field-bridge:test-preview-values"),
1867
+ payload: z16.object({ fieldIds: z16.array(fieldIdSchema).min(1).max(200) }).strict()
1690
1868
  });
1691
1869
  var fieldBridgePreviewAckMessageSchema = fieldBridgeBaseSchema.extend({
1692
- type: z15.literal("siteplane:field-bridge:preview-ack"),
1693
- payload: z15.object({
1694
- ackRequestId: z15.string().trim().min(1),
1695
- kind: z15.enum(["apply", "test"]),
1870
+ type: z16.literal("siteplane:field-bridge:preview-ack"),
1871
+ payload: z16.object({
1872
+ ackRequestId: z16.string().trim().min(1),
1873
+ kind: z16.enum(["apply", "test"]),
1696
1874
  renderedPath: realRenderedPathSchema,
1697
- fieldIds: z15.array(fieldIdSchema).max(200)
1875
+ fieldIds: z16.array(fieldIdSchema).max(200)
1698
1876
  }).strict()
1699
1877
  });
1700
1878
  var fieldBridgeSetVisualControlStateMessageSchema = fieldBridgeBaseSchema.extend({
1701
- type: z15.literal("siteplane:field-bridge:set-visual-control-state"),
1702
- payload: z15.object({
1703
- enabled: z15.boolean(),
1704
- fieldProximityEnabled: z15.boolean(),
1705
- pendingKeys: z15.array(z15.string().trim().min(1).max(2048)).max(50),
1706
- activeFieldIds: z15.array(fieldIdSchema),
1707
- fieldSections: z15.record(fieldIdSchema, bridgeSectionSchema),
1708
- selectedPending: z15.array(z15.object({
1709
- key: z15.string().trim().min(1).max(2048),
1710
- locatorHint: z15.string().trim().min(1).max(2048)
1879
+ type: z16.literal("siteplane:field-bridge:set-visual-control-state"),
1880
+ payload: z16.object({
1881
+ enabled: z16.boolean(),
1882
+ fieldProximityEnabled: z16.boolean(),
1883
+ pendingKeys: z16.array(z16.string().trim().min(1).max(2048)).max(50),
1884
+ activeFieldIds: z16.array(fieldIdSchema),
1885
+ fieldSections: z16.record(fieldIdSchema, bridgeSectionSchema),
1886
+ selectedPending: z16.array(z16.object({
1887
+ key: z16.string().trim().min(1).max(2048),
1888
+ locatorHint: z16.string().trim().min(1).max(2048)
1711
1889
  }).strict()).max(50),
1712
- scrollPendingIntoView: z15.boolean().optional()
1890
+ scrollPendingIntoView: z16.boolean().optional()
1713
1891
  }).strict()
1714
1892
  });
1715
1893
  var fieldBridgeMissingContentMessageSchema = fieldBridgeBaseSchema.extend({
1716
- type: z15.literal("siteplane:field-bridge:missing-content"),
1717
- payload: z15.object({
1894
+ type: z16.literal("siteplane:field-bridge:missing-content"),
1895
+ payload: z16.object({
1718
1896
  action: fieldBridgeMissingContentActionSchema,
1719
1897
  item: setupCorrectionItemSchema,
1720
1898
  suggestedSection: bridgeSectionSchema.optional()
1721
1899
  }).strict()
1722
1900
  });
1723
1901
  var fieldBridgePreviewScrolledMessageSchema = fieldBridgeBaseSchema.extend({
1724
- type: z15.literal("siteplane:field-bridge:preview-scrolled"),
1725
- payload: z15.object({ renderedPath: realRenderedPathSchema }).strict()
1902
+ type: z16.literal("siteplane:field-bridge:preview-scrolled"),
1903
+ payload: z16.object({ renderedPath: realRenderedPathSchema }).strict()
1726
1904
  });
1727
1905
  var fieldBridgeErrorMessageSchema = fieldBridgeBaseSchema.extend({
1728
- type: z15.literal("siteplane:field-bridge:error"),
1729
- payload: z15.object({
1730
- code: z15.string().trim().min(1),
1731
- message: z15.string().trim().min(1),
1732
- recoverable: z15.boolean().default(false)
1906
+ type: z16.literal("siteplane:field-bridge:error"),
1907
+ payload: z16.object({
1908
+ code: z16.string().trim().min(1),
1909
+ message: z16.string().trim().min(1),
1910
+ recoverable: z16.boolean().default(false)
1733
1911
  }).strict()
1734
1912
  });
1735
- var fieldBridgeMessageSchema = z15.discriminatedUnion("type", [
1913
+ var fieldBridgeMessageSchema = z16.discriminatedUnion("type", [
1736
1914
  fieldBridgeInitMessageSchema,
1737
1915
  fieldBridgeReadyMessageSchema,
1738
1916
  fieldBridgeFieldsMessageSchema,
@@ -1748,51 +1926,51 @@ var fieldBridgeMessageSchema = z15.discriminatedUnion("type", [
1748
1926
  ]);
1749
1927
 
1750
1928
  // ../shared/dist/commands.js
1751
- import { z as z17 } from "zod";
1929
+ import { z as z18 } from "zod";
1752
1930
 
1753
1931
  // ../shared/dist/errors.js
1754
- import { z as z16 } from "zod";
1932
+ import { z as z17 } from "zod";
1755
1933
  var UI_ERROR_CATEGORIES = [
1756
1934
  "site_member",
1757
1935
  "workspace_member",
1758
1936
  "internal"
1759
1937
  ];
1760
- var uiErrorCategorySchema = z16.enum(UI_ERROR_CATEGORIES);
1761
- var commandErrorPayloadSchema = z16.object({
1762
- code: z16.string().min(1),
1763
- message: z16.string().min(1),
1938
+ var uiErrorCategorySchema = z17.enum(UI_ERROR_CATEGORIES);
1939
+ var commandErrorPayloadSchema = z17.object({
1940
+ code: z17.string().min(1),
1941
+ message: z17.string().min(1),
1764
1942
  category: uiErrorCategorySchema,
1765
- details: z16.record(z16.string(), z16.unknown()).optional()
1943
+ details: z17.record(z17.string(), z17.unknown()).optional()
1766
1944
  });
1767
1945
 
1768
1946
  // ../shared/dist/commands.js
1769
- var commandSuccessSchema = z17.object({
1770
- ok: z17.literal(true),
1771
- data: z17.unknown()
1947
+ var commandSuccessSchema = z18.object({
1948
+ ok: z18.literal(true),
1949
+ data: z18.unknown()
1772
1950
  });
1773
- var commandErrorSchema = z17.object({
1774
- ok: z17.literal(false),
1951
+ var commandErrorSchema = z18.object({
1952
+ ok: z18.literal(false),
1775
1953
  error: commandErrorPayloadSchema
1776
1954
  });
1777
- var commandResultSchema = z17.discriminatedUnion("ok", [
1955
+ var commandResultSchema = z18.discriminatedUnion("ok", [
1778
1956
  commandSuccessSchema,
1779
1957
  commandErrorSchema
1780
1958
  ]);
1781
1959
 
1782
1960
  // ../shared/dist/editor-settings.js
1783
- import { z as z18 } from "zod";
1784
- var editorColorSchemeSchema = z18.enum([
1961
+ import { z as z19 } from "zod";
1962
+ var editorColorSchemeSchema = z19.enum([
1785
1963
  "paper",
1786
1964
  "slate",
1787
1965
  "siteplane",
1788
1966
  "bloom"
1789
1967
  ]);
1790
1968
  var editorColorSchemes = editorColorSchemeSchema.options;
1791
- var editorColorModeSchema = z18.enum(["light", "dark"]);
1969
+ var editorColorModeSchema = z19.enum(["light", "dark"]);
1792
1970
  var editorColorModes = editorColorModeSchema.options;
1793
1971
 
1794
1972
  // ../shared/dist/site-slug.js
1795
- import { z as z19 } from "zod";
1973
+ import { z as z20 } from "zod";
1796
1974
  var SITE_SLUG_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
1797
1975
  var RESERVED_SITE_SLUGS = /* @__PURE__ */ new Set([
1798
1976
  "account",
@@ -1809,31 +1987,31 @@ var RESERVED_SITE_SLUGS = /* @__PURE__ */ new Set([
1809
1987
  "support",
1810
1988
  "workspace"
1811
1989
  ]);
1812
- var siteSlugSchema = z19.string().regex(SITE_SLUG_PATTERN, "Invalid site slug").refine((value) => !RESERVED_SITE_SLUGS.has(value), "Reserved site slug");
1990
+ var siteSlugSchema = z20.string().regex(SITE_SLUG_PATTERN, "Invalid site slug").refine((value) => !RESERVED_SITE_SLUGS.has(value), "Reserved site slug");
1813
1991
 
1814
1992
  // ../shared/dist/entitlements.js
1815
- import { z as z20 } from "zod";
1816
- var entitlementSnapshotSchema = z20.object({
1817
- planKey: z20.string().trim().min(1),
1818
- sitesLimit: z20.number().int().positive(),
1819
- siteMembersPerSiteLimit: z20.number().int().positive(),
1820
- customAdminDomainsEnabled: z20.boolean(),
1821
- agentMcpEnabled: z20.boolean(),
1822
- emailNotificationsEnabled: z20.boolean(),
1823
- analyticsEnabled: z20.boolean(),
1824
- analyticsSitesLimit: z20.number().int().min(0),
1825
- analyticsPortalPerformanceEnabled: z20.boolean(),
1826
- analyticsMonthlyReportsEnabled: z20.boolean(),
1827
- analyticsAiSummaryEnabled: z20.boolean(),
1828
- analyticsRawEventRetentionDays: z20.number().int().min(1).max(ANALYTICS_RETENTION_DEFAULTS.maxRawEventRetentionDaysWithoutAdr),
1829
- analyticsMonthlyEventLimit: z20.number().int().min(0),
1830
- bookingEnabled: z20.boolean().default(false),
1831
- bookingSitesLimit: z20.number().int().min(0).default(0),
1832
- bookingPortalManagementEnabled: z20.boolean().default(false),
1833
- bookingResourcesPerSiteLimit: z20.number().int().min(0).default(0),
1834
- bookingServicesPerSiteLimit: z20.number().int().min(0).default(0),
1835
- bookingMonthlyBookingsLimit: z20.number().int().min(0).default(0),
1836
- bookingRemindersEnabled: z20.boolean().default(false)
1993
+ import { z as z21 } from "zod";
1994
+ var entitlementSnapshotSchema = z21.object({
1995
+ planKey: z21.string().trim().min(1),
1996
+ sitesLimit: z21.number().int().positive(),
1997
+ siteMembersPerSiteLimit: z21.number().int().positive(),
1998
+ customAdminDomainsEnabled: z21.boolean(),
1999
+ agentMcpEnabled: z21.boolean(),
2000
+ emailNotificationsEnabled: z21.boolean(),
2001
+ analyticsEnabled: z21.boolean(),
2002
+ analyticsSitesLimit: z21.number().int().min(0),
2003
+ analyticsPortalPerformanceEnabled: z21.boolean(),
2004
+ analyticsMonthlyReportsEnabled: z21.boolean(),
2005
+ analyticsAiSummaryEnabled: z21.boolean(),
2006
+ analyticsRawEventRetentionDays: z21.number().int().min(1).max(ANALYTICS_RETENTION_DEFAULTS.maxRawEventRetentionDaysWithoutAdr),
2007
+ analyticsMonthlyEventLimit: z21.number().int().min(0),
2008
+ bookingEnabled: z21.boolean().default(false),
2009
+ bookingSitesLimit: z21.number().int().min(0).default(0),
2010
+ bookingPortalManagementEnabled: z21.boolean().default(false),
2011
+ bookingResourcesPerSiteLimit: z21.number().int().min(0).default(0),
2012
+ bookingServicesPerSiteLimit: z21.number().int().min(0).default(0),
2013
+ bookingMonthlyBookingsLimit: z21.number().int().min(0).default(0),
2014
+ bookingRemindersEnabled: z21.boolean().default(false)
1837
2015
  });
1838
2016
  var EARLY_ACCESS_PLAN = {
1839
2017
  planKey: "early_access_2026",
@@ -1859,7 +2037,7 @@ var EARLY_ACCESS_PLAN = {
1859
2037
  };
1860
2038
 
1861
2039
  // ../shared/dist/readiness.js
1862
- import { z as z21 } from "zod";
2040
+ import { z as z22 } from "zod";
1863
2041
  var READINESS_CHECK_KEYS = [
1864
2042
  "agent_instructions_installed",
1865
2043
  "runtime_package_connected",
@@ -1874,19 +2052,19 @@ var READINESS_STATUSES = [
1874
2052
  "failing",
1875
2053
  "warning"
1876
2054
  ];
1877
- var readinessCheckKeySchema = z21.enum(READINESS_CHECK_KEYS);
1878
- var readinessStatusSchema = z21.enum(READINESS_STATUSES);
2055
+ var readinessCheckKeySchema = z22.enum(READINESS_CHECK_KEYS);
2056
+ var readinessStatusSchema = z22.enum(READINESS_STATUSES);
1879
2057
 
1880
2058
  // ../shared/dist/site.js
1881
- import { z as z22 } from "zod";
2059
+ import { z as z23 } from "zod";
1882
2060
  var SITE_STATUSES = [
1883
2061
  "setup",
1884
2062
  "active",
1885
2063
  "disabled",
1886
2064
  "archived"
1887
2065
  ];
1888
- var siteStatusSchema = z22.enum(SITE_STATUSES);
1889
- var websiteUrlSchema = z22.string().trim().url().refine((value) => value.startsWith("https://") || value.startsWith("http://"), "Website URL must use http or https");
2066
+ var siteStatusSchema = z23.enum(SITE_STATUSES);
2067
+ var websiteUrlSchema = z23.string().trim().url().refine((value) => value.startsWith("https://") || value.startsWith("http://"), "Website URL must use http or https");
1890
2068
 
1891
2069
  // ../cli/dist/analytics/static-scan.js
1892
2070
  import ts from "typescript";
@@ -1924,16 +2102,16 @@ ${analyticsRulesTemplate}`;
1924
2102
  import { createHash } from "crypto";
1925
2103
 
1926
2104
  // ../cli/dist/commands/analytics/public-key.js
1927
- import { z as z23 } from "zod";
1928
- var responseSchema = z23.object({
1929
- ok: z23.literal(true),
1930
- data: z23.object({
1931
- rawPublicKey: z23.string().regex(/^pk_siteplane_[A-Za-z0-9_-]{16}_[A-Za-z0-9_-]{43}$/)
2105
+ import { z as z24 } from "zod";
2106
+ var responseSchema = z24.object({
2107
+ ok: z24.literal(true),
2108
+ data: z24.object({
2109
+ rawPublicKey: z24.string().regex(/^pk_siteplane_[A-Za-z0-9_-]{16}_[A-Za-z0-9_-]{43}$/)
1932
2110
  })
1933
2111
  });
1934
- var errorResponseSchema = z23.object({
1935
- error: z23.object({
1936
- code: z23.string().regex(/^[a-z][a-z0-9_.-]+$/u)
2112
+ var errorResponseSchema = z24.object({
2113
+ error: z24.object({
2114
+ code: z24.string().regex(/^[a-z][a-z0-9_.-]+$/u)
1937
2115
  })
1938
2116
  });
1939
2117
 
@@ -1967,14 +2145,22 @@ ${bookingRulesTemplate}`;
1967
2145
  import { access, chmod, open, readFile as readFile5, rename, rm } from "fs/promises";
1968
2146
  import { randomUUID as randomUUID2 } from "crypto";
1969
2147
  import { join as join3 } from "path";
1970
- import { z as z24 } from "zod";
1971
- var siteplaneProjectConfigSchema = z24.object({
1972
- version: z24.literal(1),
1973
- apiBaseUrl: z24.string().url(),
1974
- siteId: z24.string().uuid(),
1975
- publicSiteKeyId: z24.string().uuid(),
1976
- publicSiteKey: z24.string().trim().min(1),
1977
- fieldContractHash: z24.string().regex(/^sha256:[0-9a-f]{64}$/iu).optional()
2148
+ import { z as z25 } from "zod";
2149
+ var siteplaneProjectConfigSchema = z25.object({
2150
+ version: z25.literal(2),
2151
+ apiBaseUrl: z25.string().url(),
2152
+ siteId: z25.string().uuid(),
2153
+ publicSiteKeyId: z25.string().uuid(),
2154
+ publicSiteKey: z25.string().trim().min(1),
2155
+ runId: z25.string().uuid(),
2156
+ appDirectory: z25.string().min(1),
2157
+ taskContractVersion: z25.literal("siteplane.setup-task.v2"),
2158
+ adminProtocolVersion: z25.literal(2),
2159
+ packages: z25.object({
2160
+ siteplane: z25.string().regex(/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/u),
2161
+ runtimeNext: z25.string().regex(/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/u)
2162
+ }).strict(),
2163
+ fieldContractHash: z25.string().regex(/^sha256:[0-9a-f]{64}$/iu).optional()
1978
2164
  }).strict();
1979
2165
  async function readProjectConfig(projectDir) {
1980
2166
  return siteplaneProjectConfigSchema.parse(JSON.parse(await readFile5(join3(projectDir, "siteplane.config.json"), "utf8")));
@@ -1983,45 +2169,545 @@ async function readProjectConfig(projectDir) {
1983
2169
  // ../cli/dist/config/credentials.js
1984
2170
  import { execFile } from "child_process";
1985
2171
  import { randomUUID as randomUUID3 } from "crypto";
1986
- import { chmod as chmod2, mkdir as mkdir5, open as open2, readFile as readFile6, rename as rename2, rm as rm2 } from "fs/promises";
2172
+ import { chmod as chmod2, lstat, mkdir as mkdir5, open as open2, readFile as readFile6, rename as rename2, rm as rm2 } from "fs/promises";
1987
2173
  import { dirname as dirname5, join as join4, relative } from "path";
1988
2174
  import { promisify } from "util";
1989
- import { z as z25 } from "zod";
1990
- var siteplaneCredentialsSchema = z25.object({
1991
- accessToken: z25.string().trim().min(1),
1992
- siteRevalidationSecret: z25.string().trim().min(1)
2175
+ import { z as z26 } from "zod";
2176
+ var siteplaneCredentialsSchema = z26.object({
2177
+ accessToken: z26.string().trim().min(1),
2178
+ siteRevalidationSecret: z26.string().trim().min(1),
2179
+ adminSession: z26.object({
2180
+ secret: z26.string().regex(/^[A-Za-z0-9_-]{43}$/u),
2181
+ generation: z26.string().uuid()
2182
+ }).strict().optional()
1993
2183
  }).strict();
2184
+ async function assertLocalCredentialsPathSafe(projectDir, options = {}) {
2185
+ const path = join4(projectDir, ".siteplane/credentials.json");
2186
+ await assertCredentialFilesystemSafe(projectDir);
2187
+ const isTrackedFile = options.isTrackedFile ?? ((targetPath) => gitPathMatches(projectDir, targetPath, "ls-files"));
2188
+ const isIgnoredFile = options.isIgnoredFile ?? ((targetPath) => gitPathMatches(projectDir, targetPath, "check-ignore"));
2189
+ if (await isTrackedFile(path)) {
2190
+ throw new Error("Refusing to write Siteplane credentials into a tracked file.");
2191
+ }
2192
+ if (!await isIgnoredFile(path)) {
2193
+ throw new Error("Add .siteplane/credentials.json to .gitignore before running Siteplane init.");
2194
+ }
2195
+ return path;
2196
+ }
2197
+ async function assertCredentialFilesystemSafe(projectDir) {
2198
+ for (const [path, directory, mode] of [
2199
+ [projectDir, true, null],
2200
+ [join4(projectDir, ".siteplane"), true, 448],
2201
+ [join4(projectDir, ".siteplane/credentials.json"), false, 384]
2202
+ ]) {
2203
+ const stat = await lstat(path).catch((error) => {
2204
+ if (error.code === "ENOENT")
2205
+ return null;
2206
+ throw error;
2207
+ });
2208
+ if (!stat)
2209
+ continue;
2210
+ if (stat.isSymbolicLink() || (directory ? !stat.isDirectory() : !stat.isFile())) {
2211
+ throw new Error("Siteplane credential paths must not contain symlinks or unexpected file types.");
2212
+ }
2213
+ if (mode !== null && (stat.mode & 511) !== mode) {
2214
+ throw new Error(`Siteplane credential ${directory ? "directory" : "file"} permissions must be ${mode.toString(8)} before setup.`);
2215
+ }
2216
+ }
2217
+ }
2218
+ async function readLocalCredentials(projectDir) {
2219
+ await assertCredentialFilesystemSafe(projectDir);
2220
+ return siteplaneCredentialsSchema.parse(JSON.parse(await readFile6(join4(projectDir, ".siteplane/credentials.json"), "utf8")));
2221
+ }
1994
2222
  var execFileAsync = promisify(execFile);
2223
+ async function gitPathMatches(projectDir, path, command) {
2224
+ const args = command === "check-ignore" ? ["check-ignore", "--quiet", relative(projectDir, path)] : ["ls-files", "--error-unmatch", relative(projectDir, path)];
2225
+ try {
2226
+ await execFileAsync("git", args, { cwd: projectDir });
2227
+ return true;
2228
+ } catch {
2229
+ return false;
2230
+ }
2231
+ }
1995
2232
 
1996
2233
  // ../cli/dist/commands/init.js
2234
+ import { access as access3 } from "fs/promises";
2235
+ import { join as join7, relative as relative3 } from "path";
2236
+ import { z as z29 } from "zod";
2237
+
2238
+ // ../cli/dist/commands/setup-preflight.js
2239
+ import { createHash as createHash2 } from "crypto";
2240
+ import semver from "semver";
2241
+ import { minimatch } from "minimatch";
2242
+ import { parse as parseYaml } from "yaml";
2243
+
2244
+ // ../cli/dist/config/installed-package.js
2245
+ import { createRequire } from "module";
2246
+ import { readFile as readFile7 } from "fs/promises";
1997
2247
  import { join as join5 } from "path";
1998
- import { z as z26 } from "zod";
1999
- var siteSetupBootstrapDataSchema = z26.object({
2000
- credentialPurpose: z26.literal("site_setup"),
2001
- apiBaseUrl: z26.string().url(),
2002
- siteId: z26.string().uuid(),
2003
- publicSiteKeyId: z26.string().uuid(),
2004
- publicSiteKey: z26.string().trim().min(1),
2005
- accessToken: z26.string().trim().min(1),
2006
- siteRevalidationSecret: z26.string().regex(/^[A-Za-z0-9_-]{43}$/u)
2248
+ import { z as z27 } from "zod";
2249
+ var packageSchema = z27.object({
2250
+ name: z27.string().optional(),
2251
+ version: z27.string(),
2252
+ peerDependencies: z27.record(z27.string(), z27.string()).optional()
2253
+ });
2254
+ async function readInstalledPackage(projectDir, name2) {
2255
+ const require2 = createRequire(join5(projectDir, "package.json"));
2256
+ for (const directory of require2.resolve.paths(name2) ?? []) {
2257
+ try {
2258
+ return packageSchema.parse(JSON.parse(await readFile7(join5(directory, name2, "package.json"), "utf8")));
2259
+ } catch (error) {
2260
+ if (error.code !== "ENOENT")
2261
+ throw error;
2262
+ }
2263
+ }
2264
+ throw new Error(`Install ${name2} with the canonical package manager before setup.`);
2265
+ }
2266
+
2267
+ // ../cli/dist/commands/setup-preflight.js
2268
+ import { access as access2, readFile as readFile8, realpath, readdir, readlink } from "fs/promises";
2269
+ import { dirname as dirname6, join as join6, relative as relative2, resolve, sep } from "path";
2270
+ import { z as z28 } from "zod";
2271
+
2272
+ // ../cli/dist/commands/setup-process.js
2273
+ import { spawn } from "child_process";
2274
+ var SetupFailure = class extends Error {
2275
+ code;
2276
+ constructor(code, message) {
2277
+ super(message);
2278
+ this.code = code;
2279
+ }
2280
+ };
2281
+ async function setupProcess(binary, args, options) {
2282
+ return new Promise((resolve5, reject) => {
2283
+ const child = spawn(binary, args, {
2284
+ cwd: options.cwd,
2285
+ env: process.env,
2286
+ stdio: ["pipe", "pipe", "pipe"]
2287
+ });
2288
+ const chunks = [];
2289
+ const errors = [];
2290
+ let errorBytes = 0;
2291
+ let bytes = 0;
2292
+ let exceeded = false;
2293
+ const timer = setTimeout(() => {
2294
+ exceeded = true;
2295
+ child.kill("SIGKILL");
2296
+ }, options.timeoutMs ?? 12e4);
2297
+ const capture = (chunk) => {
2298
+ bytes += chunk.length;
2299
+ if (bytes > 4 * 1024 * 1024) {
2300
+ exceeded = true;
2301
+ child.kill("SIGKILL");
2302
+ } else
2303
+ chunks.push(chunk);
2304
+ };
2305
+ child.stdout.on("data", capture);
2306
+ child.stderr.on("data", (chunk) => {
2307
+ errorBytes += chunk.length;
2308
+ if (errorBytes <= 4 * 1024 * 1024)
2309
+ errors.push(chunk);
2310
+ else {
2311
+ exceeded = true;
2312
+ child.kill("SIGKILL");
2313
+ }
2314
+ });
2315
+ child.on("error", () => {
2316
+ clearTimeout(timer);
2317
+ reject(new SetupFailure("local_tool_unavailable", `${binary} could not be started. Check the local installation and access.`));
2318
+ });
2319
+ child.on("close", (code) => {
2320
+ clearTimeout(timer);
2321
+ if (exceeded)
2322
+ reject(new SetupFailure("provider_timeout", "The operation exceeded its time or response limit; inspect the existing operation before retrying."));
2323
+ else if (code !== 0) {
2324
+ const diagnostic = Buffer.concat([...chunks, ...errors]).toString("utf8");
2325
+ if (/\b(?:401|403|unauthorized|forbidden|not authenticated|not authorized|login required|E401|E403)\b/iu.test(diagnostic))
2326
+ reject(new SetupFailure("provider_access_denied", `${binary} denied access. Restore the existing local login and project/package permissions before retrying.`));
2327
+ else if (/\b(?:ECONNRESET|ETIMEDOUT|ENOTFOUND|EAI_AGAIN|ECONNREFUSED|429|502|503|504)\b/iu.test(diagnostic))
2328
+ reject(new SetupFailure("provider_transport_failed", `${binary} could not reach its provider. Inspect the existing operation before retrying.`));
2329
+ else
2330
+ reject(new SetupFailure("local_command_failed", `${binary} failed. Check its local login, permissions and project configuration.`));
2331
+ } else
2332
+ resolve5(Buffer.concat(options.includeStderr ? [...chunks, ...errors] : chunks).toString("utf8"));
2333
+ });
2334
+ child.stdin.on("error", () => {
2335
+ });
2336
+ child.stdin.end(options.input);
2337
+ });
2338
+ }
2339
+ async function setupVercelApi(cwd, endpoint, body, method, options) {
2340
+ const args = ["api", endpoint, "--raw"];
2341
+ if (body !== void 0)
2342
+ args.push("--method", method ?? "POST", "--input", "-");
2343
+ else if (method)
2344
+ args.push("--method", method);
2345
+ let output = "";
2346
+ for (let attempt = 0; attempt < 3; attempt++) {
2347
+ const remaining = (options?.deadline ?? Date.now() + 3e4) - Date.now();
2348
+ if (remaining <= 0)
2349
+ throw new SetupFailure("provider_deadline_exceeded", "The provider deadline expired; inspect the recorded operation before continuing.");
2350
+ try {
2351
+ output = await setupProcess("vercel", args, {
2352
+ cwd,
2353
+ timeoutMs: Math.min(3e4, remaining),
2354
+ ...body === void 0 ? {} : { input: JSON.stringify(body) }
2355
+ });
2356
+ break;
2357
+ } catch (error) {
2358
+ if (!(error instanceof SetupFailure) || error.code !== "provider_transport_failed" || attempt === 2)
2359
+ throw error;
2360
+ await new Promise((resolve5) => setTimeout(resolve5, Math.min(1e3 * 2 ** attempt, Math.max(0, (options?.deadline ?? Date.now() + 2e3) - Date.now()))));
2361
+ }
2362
+ }
2363
+ try {
2364
+ return JSON.parse(output);
2365
+ } catch {
2366
+ throw new SetupFailure("invalid_provider_response", "Vercel did not return valid JSON for the bound project.");
2367
+ }
2368
+ }
2369
+
2370
+ // ../cli/dist/commands/setup-preflight.js
2371
+ var manifestSchema = z28.object({
2372
+ packageManager: z28.string().optional(),
2373
+ engines: z28.object({ node: z28.string().optional() }).optional(),
2374
+ dependencies: z28.record(z28.string(), z28.string()).optional(),
2375
+ devDependencies: z28.record(z28.string(), z28.string()).optional(),
2376
+ scripts: z28.record(z28.string(), z28.string()).optional(),
2377
+ workspaces: z28.unknown().optional()
2378
+ });
2379
+ var vercelProjectSchema = z28.object({
2380
+ id: z28.string(),
2381
+ accountId: z28.string(),
2382
+ name: z28.string(),
2383
+ nodeVersion: z28.string().nullable().optional(),
2384
+ rootDirectory: z28.string().nullable().optional(),
2385
+ framework: z28.string().nullable().optional(),
2386
+ installCommand: z28.string().nullable().optional(),
2387
+ buildCommand: z28.string().nullable().optional(),
2388
+ link: z28.object({
2389
+ type: z28.string(),
2390
+ repo: z28.string().optional(),
2391
+ repoId: z28.union([z28.string(), z28.number()]).optional(),
2392
+ org: z28.string().optional(),
2393
+ productionBranch: z28.string().optional()
2394
+ }).nullable().optional()
2395
+ });
2396
+ var exists = async (path) => access2(path).then(() => true, () => false);
2397
+ var fail = (code, message) => {
2398
+ throw new SetupFailure(code, message);
2399
+ };
2400
+ var stable = (version2, major) => new RegExp(`^${major}\\.\\d+\\.\\d+$`, "u").test(version2);
2401
+ async function inspectSetupLocalProject(projectDir) {
2402
+ const projectDirectory = await realpath(resolve(projectDir));
2403
+ const manifest = manifestSchema.parse(JSON.parse(await readFile8(join6(projectDirectory, "package.json"), "utf8")));
2404
+ const apps = (await Promise.all(["app", "src/app"].map(async (path) => await exists(join6(projectDirectory, path)) ? path : null))).filter((path) => path !== null);
2405
+ if (apps.length !== 1)
2406
+ fail("ambiguous_app_directory", "Select one Next.js App Router application with exactly one app/ or src/app/ directory.");
2407
+ const repositoryRoot = (await setupProcess("git", ["rev-parse", "--show-toplevel"], {
2408
+ cwd: projectDirectory
2409
+ })).trim();
2410
+ const tracked = await setupProcess("git", ["ls-files", "--stage", "-z"], {
2411
+ cwd: repositoryRoot
2412
+ });
2413
+ for (const entry of tracked.split("\0").filter(Boolean)) {
2414
+ if (entry.startsWith("160000 "))
2415
+ fail("git_submodule_conflict", "The repository contains Git submodules. Resolve the explicit deployment source boundary before setup; the CLI will not copy external repositories.");
2416
+ if (!entry.startsWith("120000 "))
2417
+ continue;
2418
+ const path = join6(repositoryRoot, entry.slice(entry.indexOf(" ") + 1));
2419
+ const target = resolve(dirname6(path), await readlink(path));
2420
+ const bound = relative2(repositoryRoot, target);
2421
+ if (bound.startsWith("..") || bound.startsWith(sep))
2422
+ 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.");
2423
+ }
2424
+ let lockfileRoot = projectDirectory;
2425
+ const lockNames = [
2426
+ "package-lock.json",
2427
+ "npm-shrinkwrap.json",
2428
+ "pnpm-lock.yaml",
2429
+ "yarn.lock",
2430
+ "bun.lock",
2431
+ "bun.lockb"
2432
+ ];
2433
+ let locks = [];
2434
+ for (; ; ) {
2435
+ locks = (await Promise.all(lockNames.map(async (name3) => await exists(join6(lockfileRoot, name3)) ? name3 : null))).filter((name3) => name3 !== null);
2436
+ if (locks.length || lockfileRoot === repositoryRoot || dirname6(lockfileRoot) === lockfileRoot)
2437
+ break;
2438
+ lockfileRoot = dirname6(lockfileRoot);
2439
+ }
2440
+ if (locks.length > 1)
2441
+ fail("conflicting_lockfiles", "Resolve conflicting package-manager lockfiles before setup; Siteplane does not replace them.");
2442
+ if (!locks.length)
2443
+ fail("lockfile_missing", "Install the existing application with its chosen package manager to create one canonical lockfile.");
2444
+ const lockName = locks[0];
2445
+ if (!["package-lock.json", "pnpm-lock.yaml"].includes(lockName))
2446
+ fail("unsupported_package_manager", "This setup supports npm 10 or pnpm 9/10 with their canonical lockfile.");
2447
+ const rootManifest = manifestSchema.parse(JSON.parse(await readFile8(join6(lockfileRoot, "package.json"), "utf8")));
2448
+ if (lockfileRoot !== projectDirectory) {
2449
+ const workspaceFile = join6(lockfileRoot, "pnpm-workspace.yaml");
2450
+ const workspace = lockName === "pnpm-lock.yaml" && await exists(workspaceFile) ? z28.object({ packages: z28.array(z28.string()) }).parse(parseYaml(await readFile8(workspaceFile, "utf8"))).packages : z28.union([
2451
+ z28.array(z28.string()),
2452
+ z28.object({ packages: z28.array(z28.string()) }).transform((value) => value.packages)
2453
+ ]).parse(rootManifest.workspaces);
2454
+ const selected = relative2(lockfileRoot, projectDirectory).split(sep).join("/");
2455
+ if (!workspace.some((pattern) => !pattern.startsWith("!") && minimatch(selected, pattern)) || workspace.some((pattern) => pattern.startsWith("!") && minimatch(selected, pattern.slice(1))))
2456
+ fail("unbound_workspace_app", "The selected application is excluded from the canonical lockfile's workspace packages. Select its actual application root.");
2457
+ }
2458
+ for (let ancestor = dirname6(lockfileRoot); ancestor.startsWith(repositoryRoot + sep) || ancestor === repositoryRoot; ancestor = dirname6(ancestor)) {
2459
+ const ancestorLocks = await Promise.all(lockNames.map((name3) => exists(join6(ancestor, name3))));
2460
+ if (ancestorLocks.some(Boolean))
2461
+ fail("ambiguous_lockfile_root", "Both the selected package and its repository ancestors contain lockfiles. Select one canonical workspace resolution before setup.");
2462
+ if (ancestor === repositoryRoot)
2463
+ break;
2464
+ }
2465
+ const lockText = await readFile8(join6(lockfileRoot, lockName), "utf8");
2466
+ const npmLock = lockName === "package-lock.json" ? z28.object({
2467
+ lockfileVersion: z28.number(),
2468
+ packages: z28.record(z28.string(), z28.object({
2469
+ version: z28.string().optional(),
2470
+ peerDependencies: z28.record(z28.string(), z28.string()).optional()
2471
+ })).optional()
2472
+ }).parse(JSON.parse(lockText)) : null;
2473
+ async function version2(name3) {
2474
+ try {
2475
+ return (await readInstalledPackage(projectDirectory, name3)).version;
2476
+ } catch {
2477
+ const resolved = npmLock?.packages?.[`node_modules/${name3}`]?.version;
2478
+ if (resolved)
2479
+ return resolved;
2480
+ return fail("dependencies_not_installed", `Install the existing ${name3} dependency using the canonical lockfile before setup.`);
2481
+ }
2482
+ }
2483
+ const [nextVersion, reactVersion, reactDomVersion] = await Promise.all([
2484
+ version2("next"),
2485
+ version2("react"),
2486
+ version2("react-dom")
2487
+ ]);
2488
+ if (!stable(nextVersion, 16))
2489
+ fail("unsupported_next_version", "Setup supports stable Next.js 16 App Router projects. Framework migration requires a separate owner decision.");
2490
+ if (!stable(reactVersion, 19) || reactDomVersion !== reactVersion)
2491
+ fail("react_version_conflict", "Use the same stable React 19/react-dom version compatible with the installed Next.js peers.");
2492
+ if (!stable(process.versions.node, 22))
2493
+ fail("unsupported_node_version", "Run setup under Node.js 22; this does not change your framework or package-manager versions.");
2494
+ const nextMetadata = await readInstalledPackage(projectDirectory, "next").catch(() => npmLock?.packages?.["node_modules/next"] ?? null);
2495
+ const peers = nextMetadata?.peerDependencies;
2496
+ if (!peers?.react || !peers["react-dom"])
2497
+ fail("next_peer_metadata_missing", "Install the locked Next.js dependency before setup so its actual React peer requirements can be checked.");
2498
+ if (!semver.satisfies(reactVersion, peers.react) || !semver.satisfies(reactDomVersion, peers["react-dom"]))
2499
+ fail("react_peer_conflict", "The installed React pair does not satisfy the installed Next.js peer requirements. Choose a compatible pair explicitly.");
2500
+ if (manifest.engines?.node && !semver.satisfies(process.versions.node, manifest.engines.node))
2501
+ fail("node_engine_conflict", "The selected application's Node engine declaration excludes the active supported Node.js 22 runtime.");
2502
+ const name2 = lockName === "package-lock.json" ? "npm" : "pnpm";
2503
+ const declared = rootManifest.packageManager ?? manifest.packageManager ?? null;
2504
+ if (rootManifest.packageManager && manifest.packageManager && rootManifest.packageManager !== manifest.packageManager)
2505
+ fail("package_manager_conflict", "Application and workspace packageManager declarations disagree.");
2506
+ if (declared && !new RegExp(`^${name2}@\\d+\\.\\d+\\.\\d+$`, "u").test(declared))
2507
+ fail("package_manager_conflict", "Declare an exact supported npm/pnpm packageManager version matching the canonical lockfile.");
2508
+ const localVersion = (await setupProcess(declared ? "npx" : name2, declared ? ["--yes", declared, "--version"] : ["--version"], { cwd: lockfileRoot })).trim();
2509
+ if (!(name2 === "npm" ? stable(localVersion, 10) : stable(localVersion, 9) || stable(localVersion, 10)))
2510
+ fail("unsupported_package_manager_version", "Use npm 10 or pnpm 9/10; other versions are outside the initial setup support range.");
2511
+ if (declared && declared !== `${name2}@${localVersion}`)
2512
+ 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.");
2513
+ const format = npmLock ? String(npmLock.lockfileVersion) : /^lockfileVersion:\s*['"]?([\d.]+)/mu.exec(lockText)?.[1];
2514
+ if (name2 === "npm" && format !== "3" || name2 === "pnpm" && format !== "9.0" && format !== "9")
2515
+ fail("lockfile_format_conflict", "The canonical lockfile format does not match npm 10 or pnpm 9/10.");
2516
+ const sourceConflicts = [];
2517
+ for (const file of ["next.config.js", "next.config.mjs", "next.config.ts"]) {
2518
+ if (!await exists(join6(projectDirectory, file)))
2519
+ continue;
2520
+ const source = await readFile8(join6(projectDirectory, file), "utf8");
2521
+ if (/output\s*:\s*['"]export['"]/u.test(source))
2522
+ sourceConflicts.push("static_export");
2523
+ if (/\bbasePath\s*:/u.test(source))
2524
+ sourceConflicts.push("base_path");
2525
+ }
2526
+ if (sourceConflicts.length)
2527
+ fail("unsupported_server_configuration", "Resolve static export/basePath configuration explicitly; Siteplane requires its server-side admin and revalidation handlers.");
2528
+ for (const name3 of [
2529
+ "middleware.ts",
2530
+ "middleware.js",
2531
+ "proxy.ts",
2532
+ "proxy.js",
2533
+ "src/middleware.ts",
2534
+ "src/middleware.js",
2535
+ "src/proxy.ts",
2536
+ "src/proxy.js"
2537
+ ]) {
2538
+ if (await exists(join6(projectDirectory, name3)))
2539
+ sourceConflicts.push(`inspect_routing:${name3}`);
2540
+ }
2541
+ async function inspectSource(directory) {
2542
+ for (const entry of await readdir(directory, { withFileTypes: true })) {
2543
+ if (entry.isSymbolicLink() || ["node_modules", ".git", ".next", ".siteplane", ".vercel"].includes(entry.name))
2544
+ continue;
2545
+ const path = join6(directory, entry.name);
2546
+ if (entry.isDirectory()) {
2547
+ await inspectSource(path);
2548
+ continue;
2549
+ }
2550
+ if (!/\.[cm]?[jt]sx?$/u.test(entry.name))
2551
+ continue;
2552
+ const source = await readFile8(path, "utf8");
2553
+ if (/from\s*["']next\/image["']/u.test(source))
2554
+ sourceConflicts.push(`inspect_image_policy:${relative2(projectDirectory, path)}`);
2555
+ if (/\b(?:Cookiebot|OneTrust|cookieyes|consentManager|cookieConsent)\b/iu.test(source))
2556
+ sourceConflicts.push(`inspect_existing_consent:${relative2(projectDirectory, path)}`);
2557
+ if (/from\s*["']next\/image["']/u.test(source) && semver.lt(nextVersion, "16.3.3"))
2558
+ 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.`);
2559
+ if (/["']use server["']/u.test(source) && semver.lt(nextVersion, "16.2.11"))
2560
+ 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.`);
2561
+ }
2562
+ }
2563
+ await inspectSource(join6(projectDirectory, apps[0]));
2564
+ const gitRead = async (args) => setupProcess("git", args, { cwd: projectDirectory }).then((value) => value.trim(), () => null);
2565
+ return {
2566
+ projectDirectory,
2567
+ repositoryRoot,
2568
+ lockfileRoot,
2569
+ appDirectory: apps[0],
2570
+ nextVersion,
2571
+ reactVersion,
2572
+ nodeVersion: process.versions.node,
2573
+ packageManager: { name: name2, version: localVersion, declared },
2574
+ lockfile: {
2575
+ path: relative2(repositoryRoot, join6(lockfileRoot, lockName)),
2576
+ format,
2577
+ sha256: createHash2("sha256").update(lockText).digest("hex")
2578
+ },
2579
+ git: {
2580
+ branch: await gitRead(["branch", "--show-current"]),
2581
+ revision: await gitRead(["rev-parse", "HEAD"]),
2582
+ remote: safeGitRemote(await gitRead(["remote", "get-url", "origin"])),
2583
+ changes: (await gitRead(["status", "--porcelain=v1", "--untracked-files=all"]))?.split("\n").filter(Boolean) ?? []
2584
+ },
2585
+ sourceConflicts
2586
+ };
2587
+ }
2588
+ async function setupPreflightCommand(input) {
2589
+ let local;
2590
+ try {
2591
+ local = await inspectSetupLocalProject(input.projectDir);
2592
+ await assertLocalCredentialsPathSafe(input.projectDir);
2593
+ let linkDirectory = local.projectDirectory;
2594
+ while (!await exists(join6(linkDirectory, ".vercel/project.json")) && linkDirectory !== local.repositoryRoot && dirname6(linkDirectory) !== linkDirectory)
2595
+ linkDirectory = dirname6(linkDirectory);
2596
+ if (!await exists(join6(linkDirectory, ".vercel/project.json")))
2597
+ fail("vercel_project_not_linked", "Link this application to its intended Vercel project before setup; Siteplane will not guess a target.");
2598
+ const linked = z28.object({
2599
+ projectId: z28.string().regex(/^prj_[A-Za-z0-9]+$/u),
2600
+ orgId: z28.string().regex(/^(?:team|user)_[A-Za-z0-9]+$/u)
2601
+ }).parse(JSON.parse(await readFile8(join6(linkDirectory, ".vercel/project.json"), "utf8")));
2602
+ const project = vercelProjectSchema.parse(await setupVercelApi(linkDirectory, `/v9/projects/${linked.projectId}?teamId=${linked.orgId}`));
2603
+ if (project.id !== linked.projectId || project.accountId !== linked.orgId)
2604
+ fail("vercel_identity_conflict", "The provider project does not match the locally linked project and team.");
2605
+ const expectedRoot = relative2(local.repositoryRoot, local.projectDirectory).split(sep).join("/");
2606
+ if ((project.rootDirectory ?? "") !== expectedRoot)
2607
+ fail("vercel_root_conflict", "Vercel Root Directory and the selected local app must identify the same application.");
2608
+ if (project.nodeVersion !== "22.x" || project.framework !== "nextjs")
2609
+ fail("vercel_framework_conflict", "The bound Vercel project must use Next.js with Node.js 22 before setup.");
2610
+ if (project.link && project.link.productionBranch !== local.git.branch)
2611
+ fail("vercel_production_branch_conflict", "The local branch differs from the bound Vercel Production branch.");
2612
+ if (project.link?.repo && project.link.org && !local.git.remote?.replace(/\.git$/u, "").endsWith(`${project.link.org}/${project.link.repo}`))
2613
+ fail("vercel_git_conflict", "The local origin repository differs from the Vercel Git connection.");
2614
+ const env = z28.object({
2615
+ envs: z28.array(z28.object({
2616
+ key: z28.string(),
2617
+ value: z28.string().optional(),
2618
+ target: z28.array(z28.string()).optional()
2619
+ }))
2620
+ }).parse(await setupVercelApi(linkDirectory, `/v10/projects/${linked.projectId}/env?teamId=${linked.orgId}`));
2621
+ const corepack = env.envs.some((item) => item.key === "ENABLE_EXPERIMENTAL_COREPACK" && item.value === "1" && item.target?.includes("production"));
2622
+ const install = project.installCommand ?? null;
2623
+ const selected = corepack ? "corepack" : install ? "install_override" : "automatic";
2624
+ if (local.packageManager.declared && selected === "automatic")
2625
+ 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.");
2626
+ if (install && /\b(?:yarn|bun)\b/u.test(install))
2627
+ fail("vercel_package_manager_conflict", "The Vercel install override selects an unsupported package manager.");
2628
+ const overridePin = install ? /\b(npm|pnpm)@(\d+\.\d+\.\d+)\b/u.exec(install) : null;
2629
+ if (overridePin && overridePin[1] !== local.packageManager.name)
2630
+ fail("vercel_package_manager_conflict", "The provider override selects a different package manager than the canonical lockfile.");
2631
+ const overrideFamily = install ? /(?:^|[;&|]\s*)(npm|pnpm)\s+(?:ci|install)\b/u.exec(install)?.[1] : null;
2632
+ if (overrideFamily && overrideFamily !== local.packageManager.name)
2633
+ fail("vercel_package_manager_conflict", "The provider install command conflicts with the canonical lockfile.");
2634
+ if (overridePin && local.packageManager.declared && `${overridePin[1]}@${overridePin[2]}` !== local.packageManager.declared)
2635
+ fail("vercel_package_manager_conflict", "The Vercel install override conflicts with the exact packageManager declaration.");
2636
+ return {
2637
+ status: "ready",
2638
+ local,
2639
+ provider: {
2640
+ projectId: project.id,
2641
+ teamId: project.accountId,
2642
+ name: project.name,
2643
+ rootDirectory: expectedRoot,
2644
+ nodeVersion: project.nodeVersion,
2645
+ git: project.link,
2646
+ installCommand: install,
2647
+ buildCommand: project.buildCommand ?? null,
2648
+ packageManagerSelection: selected,
2649
+ declaredPackageManager: local.packageManager.declared,
2650
+ observedPackageManager: null
2651
+ }
2652
+ };
2653
+ } catch (error) {
2654
+ return {
2655
+ status: "action_required",
2656
+ code: error instanceof SetupFailure ? error.code : "invalid_local_project",
2657
+ message: error instanceof SetupFailure ? error.message : "The selected project or provider response could not be validated. Check the application manifest and local project access.",
2658
+ ...local ? { local } : {}
2659
+ };
2660
+ }
2661
+ }
2662
+ function safeGitRemote(value) {
2663
+ if (!value)
2664
+ return null;
2665
+ if (!value.includes("://"))
2666
+ return value;
2667
+ try {
2668
+ const url = new URL(value);
2669
+ url.username = "";
2670
+ url.password = "";
2671
+ url.search = "";
2672
+ url.hash = "";
2673
+ return url.toString().replace(/\/$/u, "");
2674
+ } catch {
2675
+ return null;
2676
+ }
2677
+ }
2678
+
2679
+ // ../cli/dist/commands/init.js
2680
+ var siteSetupBootstrapDataSchema = z29.object({
2681
+ credentialPurpose: z29.literal("site_setup"),
2682
+ apiBaseUrl: z29.string().url(),
2683
+ siteId: z29.string().uuid(),
2684
+ publicSiteKeyId: z29.string().uuid(),
2685
+ publicSiteKey: z29.string().trim().min(1),
2686
+ accessToken: z29.string().trim().min(1),
2687
+ siteRevalidationSecret: z29.string().regex(/^[A-Za-z0-9_-]{43}$/u),
2688
+ runId: z29.string().uuid(),
2689
+ packages: z29.object({
2690
+ siteplane: z29.string().regex(/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/u),
2691
+ runtimeNext: z29.string().regex(/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/u)
2692
+ }).strict()
2007
2693
  }).strict();
2008
- var featureBootstrapDataSchema = z26.object({
2009
- credentialPurpose: z26.enum(["analytics", "booking"]),
2010
- apiBaseUrl: z26.string().url(),
2011
- siteId: z26.string().uuid(),
2012
- accessToken: z26.string().trim().min(1)
2694
+ var featureBootstrapDataSchema = z29.object({
2695
+ credentialPurpose: z29.enum(["analytics", "booking"]),
2696
+ apiBaseUrl: z29.string().url(),
2697
+ siteId: z29.string().uuid(),
2698
+ accessToken: z29.string().trim().min(1)
2013
2699
  }).strict();
2014
- var bootstrapResponseSchema = z26.object({
2015
- ok: z26.literal(true),
2016
- data: z26.discriminatedUnion("credentialPurpose", [
2700
+ var bootstrapResponseSchema = z29.object({
2701
+ ok: z29.literal(true),
2702
+ data: z29.discriminatedUnion("credentialPurpose", [
2017
2703
  siteSetupBootstrapDataSchema,
2018
2704
  featureBootstrapDataSchema
2019
2705
  ])
2020
2706
  }).strict();
2021
2707
 
2022
2708
  // ../cli/dist/commands/scan.js
2023
- import { readdir } from "fs/promises";
2024
- import { extname, join as join6 } from "path";
2709
+ import { readdir as readdir2 } from "fs/promises";
2710
+ import { extname, join as join8 } from "path";
2025
2711
  var defaultScanRoots = ["app", "src", "pages", "components", "lib"];
2026
2712
  var excludedDirectories = /* @__PURE__ */ new Set([
2027
2713
  ".git",
@@ -2039,14 +2725,14 @@ async function resolveScanFilePaths(filePaths, options = {}) {
2039
2725
  return filePaths;
2040
2726
  }
2041
2727
  const projectDir = options.projectDir ?? process.cwd();
2042
- const discovered = await Promise.all(defaultScanRoots.map((root) => collectSourceFiles(join6(projectDir, root))));
2728
+ const discovered = await Promise.all(defaultScanRoots.map((root) => collectSourceFiles(join8(projectDir, root))));
2043
2729
  return [...new Set(discovered.flat())].sort();
2044
2730
  }
2045
2731
  async function collectSourceFiles(directory) {
2046
- const entries = await readdir(directory, { withFileTypes: true }).catch(() => []);
2732
+ const entries = await readdir2(directory, { withFileTypes: true }).catch(() => []);
2047
2733
  const files = [];
2048
2734
  for (const entry of entries) {
2049
- const entryPath = join6(directory, entry.name);
2735
+ const entryPath = join8(directory, entry.name);
2050
2736
  if (entry.isDirectory()) {
2051
2737
  if (!excludedDirectories.has(entry.name)) {
2052
2738
  files.push(...await collectSourceFiles(entryPath));
@@ -2062,17 +2748,17 @@ async function collectSourceFiles(directory) {
2062
2748
 
2063
2749
  // ../cli/dist/commands/site-setup.js
2064
2750
  import { execFile as execFile2 } from "child_process";
2065
- import { readFile as readFile7 } from "fs/promises";
2751
+ import { readFile as readFile9 } from "fs/promises";
2066
2752
  import { promisify as promisify2 } from "util";
2067
- import { z as z27 } from "zod";
2753
+ import { z as z30 } from "zod";
2068
2754
 
2069
2755
  // ../cli/dist/scan/next-source-scan.js
2070
2756
  import ts2 from "typescript";
2071
- import { isAbsolute, relative as relative2 } from "path";
2757
+ import { isAbsolute, relative as relative4 } from "path";
2072
2758
  var eventPreviewHandlerMissingMessage = "Event preview fields must consume preview values with useSiteplanePreviewText from @siteplane/runtime-next/client or a siteplane:preview-value-applied listener.";
2073
2759
  var valueCallUnusedMessage = "Siteplane value calls must feed rendered content. Assign or await the returned value and render that value instead of ignoring the call.";
2074
2760
  var legacyEditableComponentPrefix = "Editable";
2075
- var editableComponentNames = new Set(["Image", "Text", "LongText", "Link"].map((name) => `${legacyEditableComponentPrefix}${name}`));
2761
+ var editableComponentNames = new Set(["Image", "Text", "LongText", "Link"].map((name2) => `${legacyEditableComponentPrefix}${name2}`));
2076
2762
  var functionTypeByName = {
2077
2763
  text: "text",
2078
2764
  longText: "longText",
@@ -2610,17 +3296,17 @@ function readObjectLiteral(expression) {
2610
3296
  if (!ts2.isPropertyAssignment(property)) {
2611
3297
  continue;
2612
3298
  }
2613
- const name = getPropertyName(property.name);
2614
- if (!name) {
3299
+ const name2 = getPropertyName(property.name);
3300
+ if (!name2) {
2615
3301
  continue;
2616
3302
  }
2617
- value[name] = staticExpressionValue(property.initializer);
3303
+ value[name2] = staticExpressionValue(property.initializer);
2618
3304
  }
2619
3305
  return value;
2620
3306
  }
2621
- function getPropertyName(name) {
2622
- if (ts2.isIdentifier(name) || ts2.isStringLiteral(name)) {
2623
- return name.text;
3307
+ function getPropertyName(name2) {
3308
+ if (ts2.isIdentifier(name2) || ts2.isStringLiteral(name2)) {
3309
+ return name2.text;
2624
3310
  }
2625
3311
  return null;
2626
3312
  }
@@ -2646,9 +3332,9 @@ function collectEventPreviewComponentPropUsages(node, eventPreviewAttrVariables,
2646
3332
  });
2647
3333
  }
2648
3334
  }
2649
- function getJsxAttributeName(name) {
2650
- if (ts2.isIdentifier(name)) {
2651
- return name.text;
3335
+ function getJsxAttributeName(name2) {
3336
+ if (ts2.isIdentifier(name2)) {
3337
+ return name2.text;
2652
3338
  }
2653
3339
  return void 0;
2654
3340
  }
@@ -2673,8 +3359,8 @@ function getFunctionComponentName(node) {
2673
3359
  }
2674
3360
  return void 0;
2675
3361
  }
2676
- function isComponentName(name) {
2677
- return /^[A-Z]/.test(name);
3362
+ function isComponentName(name2) {
3363
+ return /^[A-Z]/.test(name2);
2678
3364
  }
2679
3365
  function getAssignedVariableName(node) {
2680
3366
  let current = node;
@@ -2722,7 +3408,7 @@ function inferRouteHint(filePath) {
2722
3408
  return route ? `/${route}` : "/";
2723
3409
  }
2724
3410
  function toRepositoryRelativePosixPath(filePath, projectRoot) {
2725
- const path = isAbsolute(filePath) ? relative2(projectRoot, filePath) : filePath;
3411
+ const path = isAbsolute(filePath) ? relative4(projectRoot, filePath) : filePath;
2726
3412
  return path.replaceAll("\\", "/");
2727
3413
  }
2728
3414
  function isPositionalFieldReference(value) {
@@ -2731,54 +3417,354 @@ function isPositionalFieldReference(value) {
2731
3417
 
2732
3418
  // ../cli/dist/commands/site-setup.js
2733
3419
  var execFileAsync2 = promisify2(execFile2);
2734
- var safeErrorSchema = z27.object({
2735
- code: z27.string().trim().min(1),
2736
- message: z27.string().trim().min(1)
3420
+ var safeErrorSchema = z30.object({
3421
+ code: z30.string().trim().min(1),
3422
+ message: z30.string().trim().min(1)
2737
3423
  }).passthrough();
2738
- var errorResponseSchema2 = z27.object({ ok: z27.literal(false), error: safeErrorSchema }).passthrough();
2739
- var contextDataSchema = z27.object({
2740
- task: siteSetupTaskSchema,
2741
- site: z27.object({ siteId: z27.string().uuid(), portalPath: z27.string() }),
2742
- run: z27.object({
2743
- runId: z27.string().uuid(),
2744
- mode: z27.enum(["initial", "update"]),
2745
- status: z27.enum([
2746
- "waiting_for_agent",
2747
- "working",
2748
- "action_required",
2749
- "ready_for_review"
2750
- ]),
2751
- fieldContractHash: z27.string().nullable(),
2752
- deploymentOrigin: z27.string().nullable(),
2753
- deploymentRevision: z27.string().nullable(),
2754
- errorCode: z27.string().nullable(),
2755
- errorMessage: z27.string().nullable()
2756
- }),
2757
- structureHandoff: z27.object({
2758
- pendingFields: z27.array(setupCorrectionItemSchema).max(50),
2759
- ownerEditabilityNote: siteSetupOwnerEditabilityNoteSchema
2760
- }).strict().nullable(),
2761
- allowedTasks: z27.array(z27.string()),
2762
- requiredEnvironmentNames: z27.array(z27.string())
3424
+ var errorResponseSchema2 = z30.object({ ok: z30.literal(false), error: safeErrorSchema }).passthrough();
3425
+ var contextDataSchema = z30.object({ task: siteSetupTaskSchema }).strict();
3426
+ var contextResponseSchema = z30.object({ ok: z30.literal(true), data: contextDataSchema }).strict();
3427
+ var applyDataSchema = z30.object({
3428
+ status: z30.enum(["applied", "ready_for_review"]),
3429
+ runId: z30.string().uuid().optional(),
3430
+ contractVersionId: z30.string().uuid().optional(),
3431
+ fieldContractHash: z30.string().regex(/^sha256:[0-9a-f]{64}$/u),
3432
+ editorDefinitionHash: z30.string().regex(/^sha256:[0-9a-f]{64}$/u).optional(),
3433
+ fieldCount: z30.number().int().nonnegative().optional(),
3434
+ routeCount: z30.number().int().nonnegative().optional()
2763
3435
  }).strict();
2764
- var contextResponseSchema = z27.object({ ok: z27.literal(true), data: contextDataSchema }).strict();
2765
- var applyDataSchema = z27.object({
2766
- status: z27.enum(["applied", "ready_for_review"]),
2767
- runId: z27.string().uuid().optional(),
2768
- contractVersionId: z27.string().uuid().optional(),
2769
- fieldContractHash: z27.string().regex(/^sha256:[0-9a-f]{64}$/u),
2770
- editorDefinitionHash: z27.string().regex(/^sha256:[0-9a-f]{64}$/u).optional(),
2771
- fieldCount: z27.number().int().nonnegative().optional(),
2772
- routeCount: z27.number().int().nonnegative().optional()
3436
+ var applyResponseSchema = z30.object({ ok: z30.literal(true), data: applyDataSchema }).strict();
3437
+ var verifyDataSchema = z30.object({
3438
+ status: z30.literal("ready_for_review"),
3439
+ runId: z30.string().uuid().optional(),
3440
+ deploymentOrigin: z30.string().url().optional(),
3441
+ deploymentRevision: z30.string().optional()
2773
3442
  }).strict();
2774
- var applyResponseSchema = z27.object({ ok: z27.literal(true), data: applyDataSchema }).strict();
2775
- var verifyDataSchema = z27.object({
2776
- status: z27.literal("ready_for_review"),
2777
- runId: z27.string().uuid().optional(),
2778
- deploymentOrigin: z27.string().url().optional(),
2779
- deploymentRevision: z27.string().optional()
3443
+ var verifyResponseSchema = z30.object({ ok: z30.literal(true), data: verifyDataSchema }).strict();
3444
+ async function siteSetupContextCommand(input) {
3445
+ const response = await postSiteSetup(input, "context", {});
3446
+ const parsed = contextResponseSchema.safeParse(response.payload);
3447
+ if (response.ok && parsed.success) {
3448
+ return { status: "ok", ...parsed.data.data };
3449
+ }
3450
+ return actionRequired(response.payload, "Siteplane setup context is unavailable.");
3451
+ }
3452
+ async function siteSetupVerifyCommand(input) {
3453
+ const resolveSourceFiles = input.resolveSourceFiles ?? resolveScanFilePaths;
3454
+ const readSourceFile = input.readSourceFile ?? ((path) => readFile9(path, "utf8"));
3455
+ const paths = await resolveSourceFiles([], { projectDir: input.projectDir });
3456
+ const sources = await Promise.all(paths.map(readSourceFile));
3457
+ if (!sources.some(hasMountedFieldRuntimeBridge)) {
3458
+ return {
3459
+ status: "action_required",
3460
+ code: "missing_field_runtime_bridge",
3461
+ message: "Mount FieldRuntimeBridge from @siteplane/runtime-next/client before deployment verification."
3462
+ };
3463
+ }
3464
+ const deploymentRevision = await (input.readRevision ?? readGitRevision)(input.projectDir);
3465
+ const response = await postSiteSetup(input, "verify", {
3466
+ deploymentUrl: input.deploymentUrl,
3467
+ deploymentRevision,
3468
+ ...input.wait ? { wait: true } : {}
3469
+ });
3470
+ const parsed = verifyResponseSchema.safeParse(response.payload);
3471
+ if (response.ok && parsed.success) {
3472
+ return parsed.data.data;
3473
+ }
3474
+ return actionRequired(response.payload, "Siteplane deployment verification failed.");
3475
+ }
3476
+ function hasMountedFieldRuntimeBridge(source) {
3477
+ return /from\s+["']@siteplane\/runtime-next(?:\/client)?["']/u.test(source) && /<FieldRuntimeBridge(?:\s|\/|>)/u.test(source);
3478
+ }
3479
+ async function postSiteSetup(input, operation, body) {
3480
+ const [config, credentials] = await Promise.all([
3481
+ readProjectConfig(input.projectDir),
3482
+ readLocalCredentials(input.projectDir)
3483
+ ]);
3484
+ try {
3485
+ const response = await (input.fetcher ?? fetch)(`${config.apiBaseUrl.replace(/\/$/u, "")}/api/cli/setup/${operation}`, {
3486
+ method: "POST",
3487
+ signal: AbortSignal.timeout(Math.max(1, Math.min(2e4, (input.deadline ?? Date.now() + 2e4) - Date.now()))),
3488
+ headers: {
3489
+ authorization: `Bearer ${credentials.accessToken}`,
3490
+ "content-type": "application/json",
3491
+ ...input.vercelAutomationBypassSecret?.trim() ? {
3492
+ "x-vercel-protection-bypass": input.vercelAutomationBypassSecret.trim()
3493
+ } : {}
3494
+ },
3495
+ body: JSON.stringify(body)
3496
+ });
3497
+ const payload = await response.json().catch(() => null);
3498
+ return { ok: response.ok, payload };
3499
+ } catch {
3500
+ return {
3501
+ ok: false,
3502
+ payload: {
3503
+ ok: false,
3504
+ error: {
3505
+ code: "site_setup.transport_failed",
3506
+ message: "The setup request was not acknowledged. Reload the existing task before retrying; no credential values are included."
3507
+ }
3508
+ }
3509
+ };
3510
+ }
3511
+ }
3512
+ function actionRequired(payload, fallbackMessage) {
3513
+ const parsed = errorResponseSchema2.safeParse(payload);
3514
+ return parsed.success ? {
3515
+ status: "action_required",
3516
+ code: parsed.data.error.code,
3517
+ message: parsed.data.error.message
3518
+ } : {
3519
+ status: "action_required",
3520
+ code: "invalid_server_response",
3521
+ message: fallbackMessage
3522
+ };
3523
+ }
3524
+ async function readGitRevision(projectDir) {
3525
+ const { stdout } = await execFileAsync2("git", ["rev-parse", "HEAD"], {
3526
+ cwd: projectDir,
3527
+ encoding: "utf8"
3528
+ });
3529
+ const revision = stdout.trim();
3530
+ if (!revision) {
3531
+ throw new Error("A committed Git revision is required before setup verify.");
3532
+ }
3533
+ return revision;
3534
+ }
3535
+
3536
+ // ../cli/dist/commands/setup-prepare.js
3537
+ import { access as access4, lstat as lstat2, mkdir as mkdir6, open as open3, readFile as readFile10, rename as rename3, rm as rm3 } from "fs/promises";
3538
+ import { randomUUID as randomUUID4 } from "crypto";
3539
+ import { dirname as dirname7, join as join9, relative as relative5, sep as sep2 } from "path";
3540
+ import ts3 from "typescript";
3541
+
3542
+ // ../cli/dist/commands/setup-lock.js
3543
+ import { randomUUID as randomUUID5 } from "crypto";
3544
+ import { lstat as lstat3, mkdir as mkdir7, open as open4, readFile as readFile11, rm as rm4, rmdir } from "fs/promises";
3545
+ import { resolve as resolve2 } from "path";
3546
+ import { z as z31 } from "zod";
3547
+ var ownerSchema = z31.object({ pid: z31.number().int().positive(), nonce: z31.string().uuid() }).strict();
3548
+
3549
+ // ../cli/dist/config/build-provenance.js
3550
+ import { createHash as createHash3 } from "crypto";
3551
+ import { execFile as execFile3 } from "child_process";
3552
+ import { lstat as lstat4, readFile as readFile12, writeFile as writeFile5, mkdir as mkdir8 } from "fs/promises";
3553
+ import { dirname as dirname8, isAbsolute as isAbsolute2, join as join10, relative as relative6, resolve as resolve3, sep as sep3 } from "path";
3554
+ import { isDeepStrictEqual, promisify as promisify3 } from "util";
3555
+ import { z as z32 } from "zod";
3556
+ var execute = promisify3(execFile3);
3557
+ var name = ".siteplane/build-source.json";
3558
+ var oid = z32.string().regex(/^[0-9a-f]{40}$/u);
3559
+ var entrySchema = z32.object({
3560
+ path: z32.string().min(1).max(4096),
3561
+ mode: z32.enum(["100644", "100755", "120000"]),
3562
+ oid
3563
+ }).strict();
3564
+ var schema = z32.object({
3565
+ version: z32.literal(2),
3566
+ revision: oid,
3567
+ commit: z32.string().min(1).max(1048576),
3568
+ entries: z32.array(entrySchema).min(1).max(1e5),
3569
+ providerConfigurations: z32.array(z32.object({
3570
+ path: z32.string().max(4096).regex(/(?:^|\/)vercel\.json$/u),
3571
+ source: z32.string().max(1048576)
3572
+ }).strict()).max(1e3)
2780
3573
  }).strict();
2781
- var verifyResponseSchema = z27.object({ ok: z27.literal(true), data: verifyDataSchema }).strict();
3574
+ var gitHash = (type, content) => createHash3("sha1").update(`${type} ${content.length}\0`).update(content).digest("hex");
3575
+ async function writeBuildProvenance(checkout, revision) {
3576
+ const commit = (await execute("git", ["cat-file", "commit", revision], {
3577
+ cwd: checkout,
3578
+ maxBuffer: 1048576
3579
+ })).stdout;
3580
+ const tree = (await execute("git", ["ls-tree", "-rz", "--full-tree", revision], {
3581
+ cwd: checkout,
3582
+ maxBuffer: 16777216
3583
+ })).stdout;
3584
+ const entries = tree.split("\0").filter(Boolean).map((line) => {
3585
+ const match = /^(100644|100755|120000) blob ([0-9a-f]{40})\t([\s\S]+)$/u.exec(line);
3586
+ if (!match)
3587
+ throw new Error("Git submodules or unsupported tracked objects need an explicit deployment configuration.");
3588
+ return { path: match[3], mode: match[1], oid: match[2] };
3589
+ });
3590
+ for (const entry of entries) {
3591
+ if (entry.mode !== "120000")
3592
+ continue;
3593
+ const { readlink: readlink2 } = await import("fs/promises");
3594
+ const path = join10(checkout, entry.path);
3595
+ const target2 = resolve3(dirname8(path), await readlink2(path));
3596
+ const bound = relative6(checkout, target2);
3597
+ if (bound.startsWith("..") || isAbsolute2(bound))
3598
+ throw new Error("A tracked symbolic link escapes the committed upload; resolve that source boundary before deployment.");
3599
+ }
3600
+ const providerConfigurations = await Promise.all(entries.filter((entry) => /(?:^|\/)vercel\.json$/u.test(entry.path)).map(async (entry) => ({
3601
+ path: entry.path,
3602
+ source: await readFile12(join10(checkout, entry.path), "utf8")
3603
+ })));
3604
+ const record = schema.parse({
3605
+ version: 2,
3606
+ revision,
3607
+ commit,
3608
+ entries,
3609
+ providerConfigurations
3610
+ });
3611
+ const target = join10(checkout, name);
3612
+ await mkdir8(dirname8(target), { recursive: true, mode: 448 });
3613
+ await writeFile5(target, JSON.stringify(record), { flag: "wx", mode: 384 });
3614
+ }
3615
+ async function readBuildProvenance(projectDirectory) {
3616
+ let root = resolve3(projectDirectory);
3617
+ let raw = null;
3618
+ for (; ; ) {
3619
+ raw = await readFile12(join10(root, name), "utf8").catch((error) => {
3620
+ if (error.code === "ENOENT")
3621
+ return null;
3622
+ throw error;
3623
+ });
3624
+ if (raw !== null || dirname8(root) === root)
3625
+ break;
3626
+ root = dirname8(root);
3627
+ }
3628
+ if (raw === null)
3629
+ return null;
3630
+ if (Buffer.byteLength(raw) > 16777216)
3631
+ throw new Error("Build provenance is oversized.");
3632
+ const record = schema.parse(JSON.parse(raw));
3633
+ if (gitHash("commit", Buffer.from(record.commit)) !== record.revision)
3634
+ throw new Error("The build revision is not the supplied Git commit.");
3635
+ const expectedTree = /^tree ([0-9a-f]{40})\n/u.exec(record.commit)?.[1];
3636
+ if (treeHash(record.entries) !== expectedTree)
3637
+ throw new Error("The build file inventory does not belong to this Git commit.");
3638
+ const bound = new Map(record.entries.map((entry) => [entry.path, entry]));
3639
+ const configurations = /* @__PURE__ */ new Map();
3640
+ for (const config of record.providerConfigurations) {
3641
+ const entry = bound.get(config.path);
3642
+ if (!entry || entry.mode === "120000" || configurations.has(config.path) || gitHash("blob", Buffer.from(config.source)) !== entry.oid)
3643
+ throw new Error("The original provider configuration is not bound to the Git commit.");
3644
+ configurations.set(config.path, config.source);
3645
+ }
3646
+ if (record.entries.some((entry) => /(?:^|\/)vercel\.json$/u.test(entry.path) && !configurations.has(entry.path)))
3647
+ throw new Error("The committed provider configuration is missing from the build provenance.");
3648
+ const appRelative = relative6(root, projectDirectory).split(sep3).join("/");
3649
+ if (!bound.has(appRelative ? `${appRelative}/package.json` : "package.json"))
3650
+ throw new Error("The selected app is not part of the committed upload.");
3651
+ for (const entry of record.entries) {
3652
+ const path = join10(root, entry.path);
3653
+ const stat = await lstat4(path).catch((error) => {
3654
+ if (error.code === "ENOENT")
3655
+ return null;
3656
+ throw error;
3657
+ });
3658
+ if (!stat)
3659
+ continue;
3660
+ if (stat.isSymbolicLink()) {
3661
+ const { readlink: readlink2 } = await import("fs/promises");
3662
+ if (entry.mode !== "120000" || gitHash("blob", Buffer.from(await readlink2(path))) !== entry.oid)
3663
+ throw new Error("A deployed symbolic link differs from the commit.");
3664
+ } else {
3665
+ const contents = stat.isFile() ? await readFile12(path) : null;
3666
+ if (contents && entry.mode !== "120000" && gitHash("blob", contents) === entry.oid)
3667
+ continue;
3668
+ const original = configurations.get(entry.path);
3669
+ if (contents && original && entry.mode !== "120000") {
3670
+ try {
3671
+ const object = z32.record(z32.string(), z32.unknown());
3672
+ const actual = object.parse(JSON.parse(contents.toString("utf8")));
3673
+ const expected = object.parse(JSON.parse(original));
3674
+ if (!Object.hasOwn(expected, "version") && actual.version === 2)
3675
+ delete actual.version;
3676
+ if (!Object.hasOwn(expected, "name") && typeof actual.name === "string" && /^[a-z0-9][a-z0-9._-]{0,99}$/iu.test(actual.name))
3677
+ delete actual.name;
3678
+ if (isDeepStrictEqual(actual, expected))
3679
+ continue;
3680
+ } catch {
3681
+ }
3682
+ }
3683
+ throw new Error(`A deployed file ${JSON.stringify(entry.path).slice(0, 260)} differs from the committed upload.`);
3684
+ }
3685
+ }
3686
+ return record.revision;
3687
+ }
3688
+ function treeHash(entries) {
3689
+ const root = /* @__PURE__ */ new Map();
3690
+ for (const entry of entries) {
3691
+ const parts = entry.path.split("/");
3692
+ if (parts.some((part) => !part || part === "." || part === ".." || part.includes("\0") || part.includes("\\")))
3693
+ throw new Error("Unsafe Git inventory path.");
3694
+ let tree = root;
3695
+ for (const part of parts.slice(0, -1)) {
3696
+ let child = tree.get(part);
3697
+ if (!child) {
3698
+ child = /* @__PURE__ */ new Map();
3699
+ tree.set(part, child);
3700
+ }
3701
+ if (!(child instanceof Map))
3702
+ throw new Error("Conflicting Git inventory path.");
3703
+ tree = child;
3704
+ }
3705
+ const leaf = parts.at(-1);
3706
+ if (tree.has(leaf))
3707
+ throw new Error("Duplicate Git inventory path.");
3708
+ tree.set(leaf, { mode: entry.mode, oid: entry.oid });
3709
+ }
3710
+ const hash2 = (tree) => {
3711
+ const sorted = [...tree].sort(([a, av], [b, bv]) => Buffer.compare(Buffer.from(a + (av instanceof Map ? "/" : "")), Buffer.from(b + (bv instanceof Map ? "/" : ""))));
3712
+ return gitHash("tree", Buffer.concat(sorted.map(([path, value]) => Buffer.concat([
3713
+ Buffer.from(`${value instanceof Map ? "40000" : value.mode} ${path}\0`),
3714
+ Buffer.from(value instanceof Map ? hash2(value) : value.oid, "hex")
3715
+ ]))));
3716
+ };
3717
+ return hash2(root);
3718
+ }
3719
+
3720
+ // ../cli/dist/commands/setup-deploy.js
3721
+ import { createHash as createHash4, randomBytes, randomUUID as randomUUID6 } from "crypto";
3722
+ import { access as access5, mkdir as mkdir9, mkdtemp, rm as rm5, writeFile as writeFile6 } from "fs/promises";
3723
+ import { tmpdir } from "os";
3724
+ import { join as join11 } from "path";
3725
+ import { z as z33 } from "zod";
3726
+ var envSchema = z33.object({
3727
+ id: z33.string(),
3728
+ key: z33.string(),
3729
+ target: z33.array(z33.string()),
3730
+ type: z33.string(),
3731
+ comment: z33.string().optional(),
3732
+ updatedAt: z33.number().optional()
3733
+ });
3734
+ var deploymentSchema = z33.object({
3735
+ id: z33.string(),
3736
+ projectId: z33.string(),
3737
+ ownerId: z33.string().optional(),
3738
+ target: z33.string().nullable(),
3739
+ readyState: z33.string(),
3740
+ createdAt: z33.number(),
3741
+ url: z33.string(),
3742
+ meta: z33.record(z33.string(), z33.unknown()).optional(),
3743
+ gitSource: z33.object({ sha: z33.string().optional() }).nullable().optional()
3744
+ });
3745
+ var buildProofSchema = z33.object({
3746
+ node: z33.string(),
3747
+ packageManager: z33.enum(["npm", "pnpm"]),
3748
+ packageManagerVersion: z33.string(),
3749
+ lockfileHash: z33.string(),
3750
+ revision: z33.string(),
3751
+ fieldContractHash: z33.string(),
3752
+ siteplane: z33.string(),
3753
+ runtimeNext: z33.string(),
3754
+ next: z33.string(),
3755
+ react: z33.string()
3756
+ }).strict();
3757
+ var defaults = {
3758
+ preflight: setupPreflightCommand,
3759
+ context: siteSetupContextCommand,
3760
+ api: setupVercelApi,
3761
+ process: setupProcess,
3762
+ verify: siteSetupVerifyCommand,
3763
+ post: postSiteSetup,
3764
+ writeBuildProvenance,
3765
+ now: Date.now,
3766
+ pause: (milliseconds) => new Promise((resolve5) => setTimeout(resolve5, milliseconds))
3767
+ };
2782
3768
 
2783
3769
  // src/next.ts
2784
3770
  var SiteplaneNextContractError = class extends Error {
@@ -2790,14 +3776,14 @@ var SiteplaneNextContractError = class extends Error {
2790
3776
  code;
2791
3777
  };
2792
3778
  async function scanNextProjectFieldContract(projectDir) {
2793
- const resolvedProjectDir = resolve(projectDir);
3779
+ const resolvedProjectDir = resolve4(projectDir);
2794
3780
  const filePaths = await resolveScanFilePaths([], {
2795
3781
  projectDir: resolvedProjectDir
2796
3782
  });
2797
3783
  const files = await Promise.all(
2798
3784
  filePaths.map(async (filePath) => ({
2799
3785
  filePath,
2800
- sourceText: await readFile8(filePath, "utf8")
3786
+ sourceText: await readFile13(filePath, "utf8")
2801
3787
  }))
2802
3788
  );
2803
3789
  const result = scanNextSourceFilesToSiteFieldContract(files, {
@@ -2830,15 +3816,32 @@ async function withSiteplane(nextConfig, options = {}) {
2830
3816
  "The instrumented source no longer matches siteplane.config.json. Run siteplane setup apply again."
2831
3817
  );
2832
3818
  }
2833
- const buildRevision = options.buildRevision?.trim() || process.env.SITEPLANE_BUILD_REVISION?.trim() || await readGitRevision(projectDir);
2834
- if (!buildRevision) {
3819
+ const checkoutRevision = await readGitRevision2(projectDir) || await readBuildProvenance(projectDir) || (process.env.VERCEL === "1" ? process.env.VERCEL_GIT_COMMIT_SHA?.trim() : "");
3820
+ const requestedRevision = options.buildRevision?.trim() || process.env.SITEPLANE_BUILD_REVISION?.trim();
3821
+ if (!checkoutRevision || !/^[0-9a-f]{40}$/u.test(checkoutRevision))
2835
3822
  throw new SiteplaneNextContractError(
2836
3823
  "missing_build_revision",
2837
- "Set SITEPLANE_BUILD_REVISION or build from a Git checkout with a commit."
3824
+ "Build from the committed Git checkout with provider Git metadata; an arbitrary revision override is insufficient."
3825
+ );
3826
+ if (requestedRevision && requestedRevision !== checkoutRevision)
3827
+ throw new SiteplaneNextContractError(
3828
+ "build_revision_conflict",
3829
+ "SITEPLANE_BUILD_REVISION does not match the actual build checkout. Deploy the applied commit with its current configuration."
3830
+ );
3831
+ const buildRevision = checkoutRevision;
3832
+ if (process.env.VERCEL === "1")
3833
+ await emitBuildProof(
3834
+ projectDir,
3835
+ config.packages,
3836
+ buildRevision,
3837
+ scan.fieldContractHash
2838
3838
  );
2839
- }
2840
3839
  return {
2841
3840
  ...nextConfig,
3841
+ headers: async () => frameHeaders(
3842
+ await nextConfig.headers?.() ?? [],
3843
+ new URL(config.apiBaseUrl).origin
3844
+ ),
2842
3845
  env: {
2843
3846
  ...nextConfig.env ?? {},
2844
3847
  SITEPLANE_BUILD_FIELD_CONTRACT_HASH: scan.fieldContractHash,
@@ -2847,8 +3850,8 @@ async function withSiteplane(nextConfig, options = {}) {
2847
3850
  }
2848
3851
  };
2849
3852
  }
2850
- var execFileAsync3 = promisify3(execFile3);
2851
- async function readGitRevision(projectDir) {
3853
+ var execFileAsync3 = promisify4(execFile4);
3854
+ async function readGitRevision2(projectDir) {
2852
3855
  try {
2853
3856
  const result = await execFileAsync3("git", ["rev-parse", "HEAD"], {
2854
3857
  cwd: projectDir
@@ -2858,6 +3861,85 @@ async function readGitRevision(projectDir) {
2858
3861
  return "";
2859
3862
  }
2860
3863
  }
3864
+ function frameHeaders(rules, adminOrigin) {
3865
+ const policy = `frame-ancestors 'self' ${adminOrigin}`;
3866
+ const prepared = rules.map((rule) => ({
3867
+ ...rule,
3868
+ headers: rule.headers.map((header) => {
3869
+ if (header.key.toLowerCase() === "x-frame-options" && /^(DENY|SAMEORIGIN)$/iu.test(header.value.trim()))
3870
+ throw new SiteplaneNextContractError(
3871
+ "frame_policy_conflict",
3872
+ "The existing X-Frame-Options blocks the Siteplane preview. Reconcile that explicit website policy with the canonical admin origin."
3873
+ );
3874
+ if (header.key.toLowerCase() !== "content-security-policy") return header;
3875
+ const ancestors = /(?:^|;)\s*frame-ancestors\s+([^;]+)/iu.exec(
3876
+ header.value
3877
+ )?.[1];
3878
+ if (ancestors && (!ancestors.split(/\s+/u).includes(adminOrigin) || ancestors.includes("*")))
3879
+ throw new SiteplaneNextContractError(
3880
+ "frame_policy_conflict",
3881
+ "Keep the existing CSP directives and explicitly allow only the canonical Siteplane admin origin in frame-ancestors."
3882
+ );
3883
+ return {
3884
+ ...header,
3885
+ value: ancestors ? header.value : `${header.value.replace(/;\s*$/u, "")}; ${policy}`
3886
+ };
3887
+ })
3888
+ }));
3889
+ return [
3890
+ {
3891
+ source: "/:path*",
3892
+ headers: [{ key: "Content-Security-Policy", value: policy }]
3893
+ },
3894
+ ...prepared
3895
+ ];
3896
+ }
3897
+ async function emitBuildProof(projectDir, packages, revision, fieldContractHash) {
3898
+ const [cli, runtime, next, react] = await Promise.all(
3899
+ ["siteplane", "@siteplane/runtime-next", "next", "react"].map(
3900
+ (name2) => readInstalledPackage(projectDir, name2)
3901
+ )
3902
+ );
3903
+ if (cli.version !== packages.siteplane || runtime.version !== packages.runtimeNext)
3904
+ throw new SiteplaneNextContractError(
3905
+ "build_identity_missing",
3906
+ "The provider installed different Siteplane package versions than the task requires."
3907
+ );
3908
+ const executable = process.env.npm_execpath;
3909
+ if (!executable)
3910
+ throw new SiteplaneNextContractError(
3911
+ "build_identity_missing",
3912
+ "Run the provider build through the selected npm/pnpm executable so its actual version can be verified."
3913
+ );
3914
+ const packageManager = /pnpm/iu.test(executable) ? "pnpm" : "npm";
3915
+ const packageManagerVersion = (await execFileAsync3(process.execPath, [executable, "--version"], {
3916
+ cwd: projectDir
3917
+ })).stdout.trim();
3918
+ let directory = resolve4(projectDir);
3919
+ let lock = null;
3920
+ while (true) {
3921
+ lock = await readFile13(
3922
+ join12(
3923
+ directory,
3924
+ packageManager === "npm" ? "package-lock.json" : "pnpm-lock.yaml"
3925
+ ),
3926
+ "utf8"
3927
+ ).catch((error) => {
3928
+ if (error.code === "ENOENT") return null;
3929
+ throw error;
3930
+ });
3931
+ if (lock !== null || dirname9(directory) === directory) break;
3932
+ directory = dirname9(directory);
3933
+ }
3934
+ if (!lock)
3935
+ throw new SiteplaneNextContractError(
3936
+ "build_identity_missing",
3937
+ "The provider build is missing the selected canonical lockfile."
3938
+ );
3939
+ console.info(
3940
+ `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, next: next.version, react: react.version })}`
3941
+ );
3942
+ }
2861
3943
  export {
2862
3944
  SiteplaneNextContractError,
2863
3945
  scanNextProjectFieldContract,