siteplane 0.1.36 → 0.1.38

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.
@@ -11,7 +11,7 @@ import { dirname } from "path";
11
11
 
12
12
  // ../shared/dist/actors.js
13
13
  import { z } from "zod";
14
- var ACTOR_TYPES = ["developer", "client", "agent", "system"];
14
+ var ACTOR_TYPES = ["workspace_member", "site_member", "agent", "system"];
15
15
  var actorTypeSchema = z.enum(ACTOR_TYPES);
16
16
 
17
17
  // ../shared/dist/analytics-defaults.js
@@ -648,7 +648,7 @@ var bookingAvailabilityIntervalsSchema = z8.array(z8.object({
648
648
  });
649
649
  var bookingPublicConfigSchema = z8.object({
650
650
  site: z8.object({
651
- name: z8.string().trim().min(1),
651
+ displayName: z8.string().trim().min(1),
652
652
  timezone: z8.string().trim().min(1),
653
653
  locale: z8.string().trim().min(2),
654
654
  bookingPageSlug: z8.string().regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/).min(2).max(64),
@@ -1283,6 +1283,9 @@ var CONTINUE_SITE_SETUP_MAX_ITEMS = 50;
1283
1283
  var CONTINUE_SITE_SETUP_RENDERED_PATH_MAX_BYTES = 512;
1284
1284
  var CONTINUE_SITE_SETUP_VISIBLE_VALUE_MAX_BYTES = 256;
1285
1285
  var CONTINUE_SITE_SETUP_LOCATOR_HINT_MAX_BYTES = 512;
1286
+ var CONTINUE_SITE_SETUP_REQUESTED_LABEL_MAX_BYTES = 120;
1287
+ var CONTINUE_SITE_SETUP_REQUESTED_SECTION_MAX_BYTES = 120;
1288
+ var CONTINUE_SITE_SETUP_REQUESTED_SUBSECTION_MAX_BYTES = 120;
1286
1289
  var CONTINUE_SITE_SETUP_ITEMS_MAX_BYTES = 32 * 1024;
1287
1290
  var CONTINUE_SITE_SETUP_HTTP_BODY_MAX_BYTES = 64 * 1024;
1288
1291
  var siteSetupRunStatusSchema = z14.enum(SITE_SETUP_RUN_STATUSES);
@@ -1291,6 +1294,7 @@ var siteSetupErrorCodeSchema = z14.enum(SITE_SETUP_ERROR_CODES);
1291
1294
  var editorFieldSchema = z14.object({
1292
1295
  fieldId: fieldIdSchema,
1293
1296
  label: z14.string().trim().min(1),
1297
+ subsection: z14.string().trim().min(1).optional(),
1294
1298
  description: z14.string().trim().min(1).optional(),
1295
1299
  required: z14.boolean().optional(),
1296
1300
  maxLength: z14.number().int().positive().optional()
@@ -1298,7 +1302,24 @@ var editorFieldSchema = z14.object({
1298
1302
  var editorSectionSchema = z14.object({
1299
1303
  label: z14.string().trim().min(1),
1300
1304
  fields: z14.array(editorFieldSchema).min(1)
1301
- }).strict();
1305
+ }).strict().superRefine((section, context) => {
1306
+ const closedSubsections = /* @__PURE__ */ new Set();
1307
+ let currentSubsection;
1308
+ for (const [index, field] of section.fields.entries()) {
1309
+ if (field.subsection === currentSubsection)
1310
+ continue;
1311
+ if (currentSubsection)
1312
+ closedSubsections.add(currentSubsection);
1313
+ currentSubsection = field.subsection;
1314
+ if (currentSubsection && closedSubsections.has(currentSubsection)) {
1315
+ context.addIssue({
1316
+ code: "custom",
1317
+ message: `Subgroup fields must stay contiguous: ${currentSubsection}`,
1318
+ path: ["fields", index, "subsection"]
1319
+ });
1320
+ }
1321
+ }
1322
+ });
1302
1323
  var editorRouteSchema = z14.object({
1303
1324
  routeKey: siteFieldRouteKeySchema,
1304
1325
  label: z14.string().trim().min(1),
@@ -1378,13 +1399,34 @@ function normalizedSafeTextSchema(maxBytes, label) {
1378
1399
  var correctionItemBase = {
1379
1400
  renderedPath: renderedPathSchema,
1380
1401
  visibleValue: normalizedSafeTextSchema(CONTINUE_SITE_SETUP_VISIBLE_VALUE_MAX_BYTES, "visibleValue"),
1381
- locatorHint: normalizedSafeTextSchema(CONTINUE_SITE_SETUP_LOCATOR_HINT_MAX_BYTES, "locatorHint")
1402
+ locatorHint: normalizedSafeTextSchema(CONTINUE_SITE_SETUP_LOCATOR_HINT_MAX_BYTES, "locatorHint"),
1403
+ requestedLabel: normalizedSafeTextSchema(CONTINUE_SITE_SETUP_REQUESTED_LABEL_MAX_BYTES, "requestedLabel").optional(),
1404
+ requestedSection: normalizedSafeTextSchema(CONTINUE_SITE_SETUP_REQUESTED_SECTION_MAX_BYTES, "requestedSection").optional(),
1405
+ requestedSubsection: normalizedSafeTextSchema(CONTINUE_SITE_SETUP_REQUESTED_SUBSECTION_MAX_BYTES, "requestedSubsection").optional(),
1406
+ requestedSortOrder: z14.number().int().nonnegative().optional()
1382
1407
  };
1383
1408
  var setupCorrectionItemSchema = z14.discriminatedUnion("kind", [
1384
1409
  z14.object({ kind: z14.literal("text"), ...correctionItemBase }).strict(),
1385
1410
  z14.object({ kind: z14.literal("link"), ...correctionItemBase }).strict(),
1386
1411
  z14.object({ kind: z14.literal("image"), ...correctionItemBase }).strict()
1387
- ]);
1412
+ ]).superRefine((item, context) => {
1413
+ if (item.requestedSubsection && !item.requestedSection) {
1414
+ context.addIssue({
1415
+ code: "custom",
1416
+ message: "requestedSubsection requires requestedSection.",
1417
+ path: ["requestedSubsection"]
1418
+ });
1419
+ }
1420
+ });
1421
+ var setupCorrectionItemsSchema = z14.array(setupCorrectionItemSchema).max(CONTINUE_SITE_SETUP_MAX_ITEMS).superRefine((items, context) => {
1422
+ const bytes = utf8Bytes(stableJsonStringify(items));
1423
+ if (bytes > CONTINUE_SITE_SETUP_ITEMS_MAX_BYTES) {
1424
+ context.addIssue({
1425
+ code: "custom",
1426
+ message: "Correction items exceed the 32 KiB canonical payload limit."
1427
+ });
1428
+ }
1429
+ });
1388
1430
  var canonicalHashSchema = z14.string().regex(/^sha256:[0-9a-f]{64}$/iu);
1389
1431
  var deploymentRevisionSchema = normalizedSafeTextSchema(256, "deploymentRevision");
1390
1432
  var continueSiteSetupInputSchema = z14.object({
@@ -1392,17 +1434,8 @@ var continueSiteSetupInputSchema = z14.object({
1392
1434
  runId: z14.string().uuid(),
1393
1435
  expectedFieldContractHash: canonicalHashSchema,
1394
1436
  expectedDeploymentRevision: deploymentRevisionSchema,
1395
- correctionItems: z14.array(setupCorrectionItemSchema).max(CONTINUE_SITE_SETUP_MAX_ITEMS)
1396
- }).strict().superRefine((input, context) => {
1397
- const bytes = utf8Bytes(stableJsonStringify(input.correctionItems));
1398
- if (bytes > CONTINUE_SITE_SETUP_ITEMS_MAX_BYTES) {
1399
- context.addIssue({
1400
- code: "custom",
1401
- message: "Correction items exceed the 32 KiB canonical payload limit.",
1402
- path: ["correctionItems"]
1403
- });
1404
- }
1405
- });
1437
+ correctionItems: setupCorrectionItemsSchema
1438
+ }).strict();
1406
1439
  var siteSetupContextInputSchema = z14.object({}).strict();
1407
1440
  var siteSetupApplyInputSchema = z14.object({
1408
1441
  fieldContract: siteFieldContractV1Schema,
@@ -1496,25 +1529,8 @@ var completeSiteSetupInputSchema = z14.object({
1496
1529
  runId: z14.string().uuid(),
1497
1530
  expectedFieldContractHash: canonicalHashSchema,
1498
1531
  expectedDeploymentRevision: deploymentRevisionSchema,
1499
- accessMode: z14.enum(["fallback", "custom_domain"]),
1500
- siteDomainId: z14.string().uuid().optional(),
1501
- defaultCanPublish: z14.boolean()
1502
- }).strict().superRefine((input, context) => {
1503
- if (input.accessMode === "fallback" && input.siteDomainId) {
1504
- context.addIssue({
1505
- code: "custom",
1506
- message: "Fallback access cannot use a custom domain.",
1507
- path: ["siteDomainId"]
1508
- });
1509
- }
1510
- if (input.accessMode === "custom_domain" && !input.siteDomainId) {
1511
- context.addIssue({
1512
- code: "custom",
1513
- message: "Custom-domain access requires a site domain.",
1514
- path: ["siteDomainId"]
1515
- });
1516
- }
1517
- });
1532
+ expectedReadyFingerprint: canonicalHashSchema
1533
+ }).strict();
1518
1534
  var refreshSiteSetupDeploymentInputSchema = z14.object({
1519
1535
  siteId: z14.string().uuid(),
1520
1536
  deploymentUrl: z14.string().url().refine((value) => value.startsWith("https://")),
@@ -1539,7 +1555,7 @@ function utf8Bytes(value) {
1539
1555
  }
1540
1556
 
1541
1557
  // ../shared/dist/bridge-protocol.js
1542
- var BRIDGE_PROTOCOL_VERSION = 1;
1558
+ var BRIDGE_PROTOCOL_VERSION = 2;
1543
1559
  var bridgeRectSchema = z15.object({
1544
1560
  x: z15.number(),
1545
1561
  y: z15.number(),
@@ -1566,6 +1582,12 @@ var bridgePreviewValueSchema = z15.discriminatedUnion("fieldType", [
1566
1582
  previewLinkValueSchema,
1567
1583
  previewImageValueSchema
1568
1584
  ]);
1585
+ var fieldSelectionModeSchema = z15.enum(["replace", "range", "toggle"]);
1586
+ var fieldBridgeMissingContentActionSchema = z15.enum([
1587
+ "add",
1588
+ "select",
1589
+ "remove"
1590
+ ]);
1569
1591
  var FIELD_BRIDGE_MESSAGE_TYPES = [
1570
1592
  "siteplane:field-bridge:init",
1571
1593
  "siteplane:field-bridge:ready",
@@ -1575,11 +1597,12 @@ var FIELD_BRIDGE_MESSAGE_TYPES = [
1575
1597
  "siteplane:field-bridge:apply-preview-values",
1576
1598
  "siteplane:field-bridge:test-preview-values",
1577
1599
  "siteplane:field-bridge:preview-ack",
1578
- "siteplane:field-bridge:set-editability-review",
1600
+ "siteplane:field-bridge:set-visual-control-state",
1579
1601
  "siteplane:field-bridge:missing-content",
1580
1602
  "siteplane:field-bridge:error"
1581
1603
  ];
1582
1604
  var canonicalFieldContractHashSchema = z15.string().regex(/^sha256:[0-9a-f]{64}$/u);
1605
+ var bridgeSectionSchema = z15.string().trim().min(1).max(256);
1583
1606
  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.");
1584
1607
  var fieldBridgeIdentitySchema = z15.object({
1585
1608
  publicRuntimeKeyId: z15.string().uuid(),
@@ -1625,7 +1648,7 @@ var fieldBridgeReadyMessageSchema = fieldBridgeBaseSchema.extend({
1625
1648
  z15.literal("field_selection"),
1626
1649
  z15.literal("preview_values"),
1627
1650
  z15.literal("field_evidence"),
1628
- z15.literal("editability_review")
1651
+ z15.literal("visual_field_control")
1629
1652
  ])
1630
1653
  }).strict()
1631
1654
  });
@@ -1638,14 +1661,33 @@ var fieldBridgeFieldsMessageSchema = fieldBridgeBaseSchema.extend({
1638
1661
  });
1639
1662
  var fieldBridgeSelectFieldMessageSchema = fieldBridgeBaseSchema.extend({
1640
1663
  type: z15.literal("siteplane:field-bridge:select-field"),
1641
- payload: z15.object({ fieldId: fieldIdSchema }).strict()
1664
+ payload: z15.object({
1665
+ fieldId: fieldIdSchema,
1666
+ selectionMode: fieldSelectionModeSchema
1667
+ }).strict()
1642
1668
  });
1643
1669
  var fieldBridgeSetSelectedFieldMessageSchema = fieldBridgeBaseSchema.extend({
1644
1670
  type: z15.literal("siteplane:field-bridge:set-selected-field"),
1645
1671
  payload: z15.object({
1646
- fieldId: fieldIdSchema.nullable(),
1672
+ fieldIds: z15.array(fieldIdSchema).max(200),
1673
+ primaryFieldId: fieldIdSchema.nullable(),
1647
1674
  scrollIntoView: z15.boolean().optional()
1648
- }).strict()
1675
+ }).strict().superRefine((value, context) => {
1676
+ if (value.fieldIds.length > 0 && value.primaryFieldId === null) {
1677
+ context.addIssue({
1678
+ code: "custom",
1679
+ message: "A non-empty selection needs a primary field.",
1680
+ path: ["primaryFieldId"]
1681
+ });
1682
+ }
1683
+ if (value.primaryFieldId !== null && !value.fieldIds.includes(value.primaryFieldId)) {
1684
+ context.addIssue({
1685
+ code: "custom",
1686
+ message: "The primary field must be part of the selection.",
1687
+ path: ["primaryFieldId"]
1688
+ });
1689
+ }
1690
+ })
1649
1691
  });
1650
1692
  var fieldBridgeApplyPreviewValuesMessageSchema = fieldBridgeBaseSchema.extend({
1651
1693
  type: z15.literal("siteplane:field-bridge:apply-preview-values"),
@@ -1664,13 +1706,28 @@ var fieldBridgePreviewAckMessageSchema = fieldBridgeBaseSchema.extend({
1664
1706
  fieldIds: z15.array(fieldIdSchema).max(200)
1665
1707
  }).strict()
1666
1708
  });
1667
- var fieldBridgeSetEditabilityReviewMessageSchema = fieldBridgeBaseSchema.extend({
1668
- type: z15.literal("siteplane:field-bridge:set-editability-review"),
1669
- payload: z15.object({ enabled: z15.boolean() }).strict()
1709
+ var fieldBridgeSetVisualControlStateMessageSchema = fieldBridgeBaseSchema.extend({
1710
+ type: z15.literal("siteplane:field-bridge:set-visual-control-state"),
1711
+ payload: z15.object({
1712
+ enabled: z15.boolean(),
1713
+ fieldProximityEnabled: z15.boolean(),
1714
+ pendingKeys: z15.array(z15.string().trim().min(1).max(2048)).max(50),
1715
+ activeFieldIds: z15.array(fieldIdSchema),
1716
+ fieldSections: z15.record(fieldIdSchema, bridgeSectionSchema),
1717
+ selectedPending: z15.array(z15.object({
1718
+ key: z15.string().trim().min(1).max(2048),
1719
+ locatorHint: z15.string().trim().min(1).max(2048)
1720
+ }).strict()).max(50),
1721
+ scrollPendingIntoView: z15.boolean().optional()
1722
+ }).strict()
1670
1723
  });
1671
1724
  var fieldBridgeMissingContentMessageSchema = fieldBridgeBaseSchema.extend({
1672
1725
  type: z15.literal("siteplane:field-bridge:missing-content"),
1673
- payload: z15.object({ item: setupCorrectionItemSchema }).strict()
1726
+ payload: z15.object({
1727
+ action: fieldBridgeMissingContentActionSchema,
1728
+ item: setupCorrectionItemSchema,
1729
+ suggestedSection: bridgeSectionSchema.optional()
1730
+ }).strict()
1674
1731
  });
1675
1732
  var fieldBridgeErrorMessageSchema = fieldBridgeBaseSchema.extend({
1676
1733
  type: z15.literal("siteplane:field-bridge:error"),
@@ -1689,7 +1746,7 @@ var fieldBridgeMessageSchema = z15.discriminatedUnion("type", [
1689
1746
  fieldBridgeApplyPreviewValuesMessageSchema,
1690
1747
  fieldBridgeTestPreviewValuesMessageSchema,
1691
1748
  fieldBridgePreviewAckMessageSchema,
1692
- fieldBridgeSetEditabilityReviewMessageSchema,
1749
+ fieldBridgeSetVisualControlStateMessageSchema,
1693
1750
  fieldBridgeMissingContentMessageSchema,
1694
1751
  fieldBridgeErrorMessageSchema
1695
1752
  ]);
@@ -1700,8 +1757,8 @@ import { z as z17 } from "zod";
1700
1757
  // ../shared/dist/errors.js
1701
1758
  import { z as z16 } from "zod";
1702
1759
  var UI_ERROR_CATEGORIES = [
1703
- "client",
1704
- "developer",
1760
+ "site_member",
1761
+ "workspace_member",
1705
1762
  "internal"
1706
1763
  ];
1707
1764
  var uiErrorCategorySchema = z16.enum(UI_ERROR_CATEGORIES);
@@ -1726,52 +1783,79 @@ var commandResultSchema = z17.discriminatedUnion("ok", [
1726
1783
  commandErrorSchema
1727
1784
  ]);
1728
1785
 
1729
- // ../shared/dist/fallback-portal.js
1786
+ // ../shared/dist/editor-settings.js
1730
1787
  import { z as z18 } from "zod";
1731
- var FALLBACK_PORTAL_SLUG_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
1732
- var fallbackPortalSlugSchema = z18.string().regex(FALLBACK_PORTAL_SLUG_PATTERN, "Invalid fallback portal slug");
1788
+ var editorColorSchemeSchema = z18.enum([
1789
+ "paper",
1790
+ "slate",
1791
+ "siteplane",
1792
+ "bloom"
1793
+ ]);
1794
+ var editorColorSchemes = editorColorSchemeSchema.options;
1795
+ var editorColorModeSchema = z18.enum(["light", "dark"]);
1796
+ var editorColorModes = editorColorModeSchema.options;
1733
1797
 
1734
- // ../shared/dist/entitlements.js
1798
+ // ../shared/dist/site-slug.js
1735
1799
  import { z as z19 } from "zod";
1736
- var entitlementSnapshotSchema = z19.object({
1737
- planKey: z19.string().trim().min(1),
1738
- sitesLimit: z19.number().int().positive(),
1739
- clientAccountsPerSiteLimit: z19.number().int().positive(),
1740
- customAdminDomainsEnabled: z19.boolean(),
1741
- agentMcpEnabled: z19.boolean(),
1742
- emailNotificationsEnabled: z19.boolean(),
1743
- analyticsEnabled: z19.boolean(),
1744
- analyticsSitesLimit: z19.number().int().min(0),
1745
- analyticsClientPerformanceEnabled: z19.boolean(),
1746
- analyticsMonthlyReportsEnabled: z19.boolean(),
1747
- analyticsAiSummaryEnabled: z19.boolean(),
1748
- analyticsRawEventRetentionDays: z19.number().int().min(1).max(ANALYTICS_RETENTION_DEFAULTS.maxRawEventRetentionDaysWithoutAdr),
1749
- analyticsMonthlyEventLimit: z19.number().int().min(0),
1750
- bookingEnabled: z19.boolean().default(false),
1751
- bookingSitesLimit: z19.number().int().min(0).default(0),
1752
- bookingClientManagementEnabled: z19.boolean().default(false),
1753
- bookingResourcesPerSiteLimit: z19.number().int().min(0).default(0),
1754
- bookingServicesPerSiteLimit: z19.number().int().min(0).default(0),
1755
- bookingMonthlyBookingsLimit: z19.number().int().min(0).default(0),
1756
- bookingRemindersEnabled: z19.boolean().default(false)
1800
+ var SITE_SLUG_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
1801
+ var RESERVED_SITE_SLUGS = /* @__PURE__ */ new Set([
1802
+ "account",
1803
+ "admin",
1804
+ "api",
1805
+ "app",
1806
+ "auth",
1807
+ "book",
1808
+ "claim",
1809
+ "dev",
1810
+ "login",
1811
+ "new",
1812
+ "portal",
1813
+ "support",
1814
+ "workspace"
1815
+ ]);
1816
+ var siteSlugSchema = z19.string().regex(SITE_SLUG_PATTERN, "Invalid site slug").refine((value) => !RESERVED_SITE_SLUGS.has(value), "Reserved site slug");
1817
+
1818
+ // ../shared/dist/entitlements.js
1819
+ import { z as z20 } from "zod";
1820
+ var entitlementSnapshotSchema = z20.object({
1821
+ planKey: z20.string().trim().min(1),
1822
+ sitesLimit: z20.number().int().positive(),
1823
+ siteMembersPerSiteLimit: z20.number().int().positive(),
1824
+ customAdminDomainsEnabled: z20.boolean(),
1825
+ agentMcpEnabled: z20.boolean(),
1826
+ emailNotificationsEnabled: z20.boolean(),
1827
+ analyticsEnabled: z20.boolean(),
1828
+ analyticsSitesLimit: z20.number().int().min(0),
1829
+ analyticsPortalPerformanceEnabled: z20.boolean(),
1830
+ analyticsMonthlyReportsEnabled: z20.boolean(),
1831
+ analyticsAiSummaryEnabled: z20.boolean(),
1832
+ analyticsRawEventRetentionDays: z20.number().int().min(1).max(ANALYTICS_RETENTION_DEFAULTS.maxRawEventRetentionDaysWithoutAdr),
1833
+ analyticsMonthlyEventLimit: z20.number().int().min(0),
1834
+ bookingEnabled: z20.boolean().default(false),
1835
+ bookingSitesLimit: z20.number().int().min(0).default(0),
1836
+ bookingPortalManagementEnabled: z20.boolean().default(false),
1837
+ bookingResourcesPerSiteLimit: z20.number().int().min(0).default(0),
1838
+ bookingServicesPerSiteLimit: z20.number().int().min(0).default(0),
1839
+ bookingMonthlyBookingsLimit: z20.number().int().min(0).default(0),
1840
+ bookingRemindersEnabled: z20.boolean().default(false)
1757
1841
  });
1758
1842
  var EARLY_ACCESS_PLAN = {
1759
1843
  planKey: "early_access_2026",
1760
1844
  sitesLimit: 3,
1761
- clientAccountsPerSiteLimit: 5,
1845
+ siteMembersPerSiteLimit: 5,
1762
1846
  customAdminDomainsEnabled: true,
1763
1847
  agentMcpEnabled: true,
1764
1848
  emailNotificationsEnabled: true,
1765
1849
  analyticsEnabled: false,
1766
1850
  analyticsSitesLimit: 0,
1767
- analyticsClientPerformanceEnabled: false,
1851
+ analyticsPortalPerformanceEnabled: false,
1768
1852
  analyticsMonthlyReportsEnabled: false,
1769
1853
  analyticsAiSummaryEnabled: false,
1770
1854
  analyticsRawEventRetentionDays: ANALYTICS_RETENTION_DEFAULTS.enabledRawEventRetentionDays,
1771
1855
  analyticsMonthlyEventLimit: 0,
1772
1856
  bookingEnabled: true,
1773
1857
  bookingSitesLimit: 3,
1774
- bookingClientManagementEnabled: true,
1858
+ bookingPortalManagementEnabled: true,
1775
1859
  bookingResourcesPerSiteLimit: 10,
1776
1860
  bookingServicesPerSiteLimit: 50,
1777
1861
  bookingMonthlyBookingsLimit: 0,
@@ -1779,7 +1863,7 @@ var EARLY_ACCESS_PLAN = {
1779
1863
  };
1780
1864
 
1781
1865
  // ../shared/dist/readiness.js
1782
- import { z as z20 } from "zod";
1866
+ import { z as z21 } from "zod";
1783
1867
  var READINESS_CHECK_KEYS = [
1784
1868
  "agent_instructions_installed",
1785
1869
  "runtime_package_connected",
@@ -1794,19 +1878,19 @@ var READINESS_STATUSES = [
1794
1878
  "failing",
1795
1879
  "warning"
1796
1880
  ];
1797
- var readinessCheckKeySchema = z20.enum(READINESS_CHECK_KEYS);
1798
- var readinessStatusSchema = z20.enum(READINESS_STATUSES);
1881
+ var readinessCheckKeySchema = z21.enum(READINESS_CHECK_KEYS);
1882
+ var readinessStatusSchema = z21.enum(READINESS_STATUSES);
1799
1883
 
1800
1884
  // ../shared/dist/site.js
1801
- import { z as z21 } from "zod";
1885
+ import { z as z22 } from "zod";
1802
1886
  var SITE_STATUSES = [
1803
1887
  "setup",
1804
- "client_ready",
1888
+ "active",
1805
1889
  "disabled",
1806
1890
  "archived"
1807
1891
  ];
1808
- var siteStatusSchema = z21.enum(SITE_STATUSES);
1809
- var websiteUrlSchema = z21.string().trim().url().refine((value) => value.startsWith("https://") || value.startsWith("http://"), "Website URL must use http or https");
1892
+ var siteStatusSchema = z22.enum(SITE_STATUSES);
1893
+ var websiteUrlSchema = z22.string().trim().url().refine((value) => value.startsWith("https://") || value.startsWith("http://"), "Website URL must use http or https");
1810
1894
 
1811
1895
  // ../cli/dist/analytics/manifest.js
1812
1896
  async function readAnalyticsManifestFile(manifestPath) {
@@ -2611,16 +2695,16 @@ async function analyticsReadinessCommand(input) {
2611
2695
  }
2612
2696
 
2613
2697
  // ../cli/dist/commands/analytics/public-key.js
2614
- import { z as z22 } from "zod";
2615
- var responseSchema = z22.object({
2616
- ok: z22.literal(true),
2617
- data: z22.object({
2618
- rawPublicKey: z22.string().regex(/^pk_siteplane_[A-Za-z0-9_-]{16}_[A-Za-z0-9_-]{43}$/)
2698
+ import { z as z23 } from "zod";
2699
+ var responseSchema = z23.object({
2700
+ ok: z23.literal(true),
2701
+ data: z23.object({
2702
+ rawPublicKey: z23.string().regex(/^pk_siteplane_[A-Za-z0-9_-]{16}_[A-Za-z0-9_-]{43}$/)
2619
2703
  })
2620
2704
  });
2621
- var errorResponseSchema = z22.object({
2622
- error: z22.object({
2623
- code: z22.string().regex(/^[a-z][a-z0-9_.-]+$/u)
2705
+ var errorResponseSchema = z23.object({
2706
+ error: z23.object({
2707
+ code: z23.string().regex(/^[a-z][a-z0-9_.-]+$/u)
2624
2708
  })
2625
2709
  });
2626
2710
  async function analyticsPublicKeyCommand(input) {
@@ -2836,54 +2920,48 @@ async function bookingTestCommand(input) {
2836
2920
  });
2837
2921
  }
2838
2922
 
2839
- // ../cli/dist/config/project-config.js
2840
- import { access, chmod, open, readFile as readFile5, rename, rm } from "fs/promises";
2923
+ // ../cli/dist/commands/connect.js
2924
+ import { randomBytes } from "crypto";
2925
+ import { z as z27 } from "zod";
2926
+
2927
+ // ../cli/dist/config/credentials.js
2928
+ import { execFile } from "child_process";
2841
2929
  import { randomUUID as randomUUID2 } from "crypto";
2842
- import { join as join3 } from "path";
2843
- import { z as z23 } from "zod";
2844
- var siteplaneProjectConfigSchema = z23.object({
2845
- version: z23.literal(1),
2846
- apiBaseUrl: z23.string().url(),
2847
- siteId: z23.string().uuid(),
2848
- publicSiteKeyId: z23.string().uuid(),
2849
- publicSiteKey: z23.string().trim().min(1),
2850
- fieldContractHash: z23.string().regex(/^sha256:[0-9a-f]{64}$/iu).optional()
2930
+ import { chmod, mkdir as mkdir5, open, readFile as readFile5, rename, rm } from "fs/promises";
2931
+ import { dirname as dirname5, join as join3, relative } from "path";
2932
+ import { promisify } from "util";
2933
+ import { z as z24 } from "zod";
2934
+ var siteplaneCredentialsSchema = z24.object({
2935
+ accessToken: z24.string().trim().min(1),
2936
+ siteRevalidationSecret: z24.string().trim().min(1)
2851
2937
  }).strict();
2852
- async function readProjectPackageJson(projectDir) {
2853
- return JSON.parse(await readFile5(join3(projectDir, "package.json"), "utf8"));
2854
- }
2855
- async function detectNextProject(projectDir) {
2856
- const packageJson = await readProjectPackageJson(projectDir).catch(() => null);
2857
- if (packageJson?.dependencies?.next || packageJson?.devDependencies?.next) {
2858
- return true;
2938
+ async function assertLocalCredentialsPathSafe(projectDir, options = {}) {
2939
+ const path = join3(projectDir, ".siteplane/credentials.json");
2940
+ const isTrackedFile = options.isTrackedFile ?? ((targetPath) => gitPathMatches(projectDir, targetPath, "ls-files"));
2941
+ const isIgnoredFile = options.isIgnoredFile ?? ((targetPath) => gitPathMatches(projectDir, targetPath, "check-ignore"));
2942
+ if (await isTrackedFile(path)) {
2943
+ throw new Error("Refusing to write Siteplane credentials into a tracked file.");
2859
2944
  }
2860
- for (const fileName of [
2861
- "next.config.js",
2862
- "next.config.mjs",
2863
- "next.config.ts"
2864
- ]) {
2865
- try {
2866
- await access(join3(projectDir, fileName));
2867
- return true;
2868
- } catch {
2869
- }
2945
+ if (!await isIgnoredFile(path)) {
2946
+ throw new Error("Add .siteplane/credentials.json to .gitignore before running Siteplane connect.");
2870
2947
  }
2871
- return false;
2948
+ return path;
2872
2949
  }
2873
- async function writeProjectConfig(projectDir, config) {
2874
- const path = join3(projectDir, "siteplane.config.json");
2875
- const parsed = siteplaneProjectConfigSchema.parse(config);
2876
- await writeJsonAtomically(path, parsed, 420);
2950
+ async function writeLocalCredentials(projectDir, credentials, options = {}) {
2951
+ const path = await assertLocalCredentialsPathSafe(projectDir, options);
2952
+ const parsed = siteplaneCredentialsSchema.parse(credentials);
2953
+ await mkdir5(dirname5(path), { recursive: true, mode: 448 });
2954
+ await writeCredentialsAtomically(path, parsed);
2877
2955
  return path;
2878
2956
  }
2879
- async function readProjectConfig(projectDir) {
2880
- return siteplaneProjectConfigSchema.parse(JSON.parse(await readFile5(join3(projectDir, "siteplane.config.json"), "utf8")));
2957
+ async function readLocalCredentials(projectDir) {
2958
+ return siteplaneCredentialsSchema.parse(JSON.parse(await readFile5(join3(projectDir, ".siteplane/credentials.json"), "utf8")));
2881
2959
  }
2882
- async function writeJsonAtomically(path, value, mode) {
2960
+ async function writeCredentialsAtomically(path, credentials) {
2883
2961
  const temporaryPath = `${path}.${randomUUID2()}.tmp`;
2884
- const file = await open(temporaryPath, "wx", mode);
2962
+ const file = await open(temporaryPath, "wx", 384);
2885
2963
  try {
2886
- await file.writeFile(`${JSON.stringify(value, null, 2)}
2964
+ await file.writeFile(`${JSON.stringify(credentials, null, 2)}
2887
2965
  `, "utf8");
2888
2966
  await file.sync();
2889
2967
  } catch (error) {
@@ -2894,47 +2972,71 @@ async function writeJsonAtomically(path, value, mode) {
2894
2972
  await file.close();
2895
2973
  try {
2896
2974
  await rename(temporaryPath, path);
2897
- await chmod(path, mode);
2975
+ await chmod(path, 384);
2898
2976
  } catch (error) {
2899
2977
  await rm(temporaryPath, { force: true });
2900
2978
  throw error;
2901
2979
  }
2902
2980
  }
2981
+ var execFileAsync = promisify(execFile);
2982
+ async function gitPathMatches(projectDir, path, command) {
2983
+ const args = command === "check-ignore" ? ["check-ignore", "--quiet", relative(projectDir, path)] : ["ls-files", "--error-unmatch", relative(projectDir, path)];
2984
+ try {
2985
+ await execFileAsync("git", args, { cwd: projectDir });
2986
+ return true;
2987
+ } catch {
2988
+ return false;
2989
+ }
2990
+ }
2903
2991
 
2904
- // ../cli/dist/config/credentials.js
2905
- import { execFile } from "child_process";
2992
+ // ../cli/dist/config/project-config.js
2993
+ import { access, chmod as chmod2, open as open2, readFile as readFile6, rename as rename2, rm as rm2 } from "fs/promises";
2906
2994
  import { randomUUID as randomUUID3 } from "crypto";
2907
- import { chmod as chmod2, mkdir as mkdir5, open as open2, readFile as readFile6, rename as rename2, rm as rm2 } from "fs/promises";
2908
- import { dirname as dirname5, join as join4, relative } from "path";
2909
- import { promisify } from "util";
2910
- import { z as z24 } from "zod";
2911
- var siteplaneCredentialsSchema = z24.object({
2912
- accessToken: z24.string().trim().min(1),
2913
- siteRevalidationSecret: z24.string().trim().min(1)
2995
+ import { join as join4 } from "path";
2996
+ import { z as z25 } from "zod";
2997
+ var siteplaneProjectConfigSchema = z25.object({
2998
+ version: z25.literal(1),
2999
+ apiBaseUrl: z25.string().url(),
3000
+ siteId: z25.string().uuid(),
3001
+ publicSiteKeyId: z25.string().uuid(),
3002
+ publicSiteKey: z25.string().trim().min(1),
3003
+ fieldContractHash: z25.string().regex(/^sha256:[0-9a-f]{64}$/iu).optional()
2914
3004
  }).strict();
2915
- async function writeLocalCredentials(projectDir, credentials, options = {}) {
2916
- const path = join4(projectDir, ".siteplane/credentials.json");
2917
- const isTrackedFile = options.isTrackedFile ?? ((targetPath) => gitPathMatches(projectDir, targetPath, "ls-files"));
2918
- const isIgnoredFile = options.isIgnoredFile ?? ((targetPath) => gitPathMatches(projectDir, targetPath, "check-ignore"));
2919
- if (await isTrackedFile(path)) {
2920
- throw new Error("Refusing to write Siteplane credentials into a tracked file.");
3005
+ async function readProjectPackageJson(projectDir) {
3006
+ return JSON.parse(await readFile6(join4(projectDir, "package.json"), "utf8"));
3007
+ }
3008
+ async function detectNextProject(projectDir) {
3009
+ const packageJson = await readProjectPackageJson(projectDir).catch(() => null);
3010
+ if (packageJson?.dependencies?.next || packageJson?.devDependencies?.next) {
3011
+ return true;
2921
3012
  }
2922
- if (!await isIgnoredFile(path)) {
2923
- throw new Error("Add .siteplane/credentials.json to .gitignore before running siteplane init.");
3013
+ for (const fileName of [
3014
+ "next.config.js",
3015
+ "next.config.mjs",
3016
+ "next.config.ts"
3017
+ ]) {
3018
+ try {
3019
+ await access(join4(projectDir, fileName));
3020
+ return true;
3021
+ } catch {
3022
+ }
2924
3023
  }
2925
- const parsed = siteplaneCredentialsSchema.parse(credentials);
2926
- await mkdir5(dirname5(path), { recursive: true, mode: 448 });
2927
- await writeCredentialsAtomically(path, parsed);
3024
+ return false;
3025
+ }
3026
+ async function writeProjectConfig(projectDir, config) {
3027
+ const path = join4(projectDir, "siteplane.config.json");
3028
+ const parsed = siteplaneProjectConfigSchema.parse(config);
3029
+ await writeJsonAtomically(path, parsed, 420);
2928
3030
  return path;
2929
3031
  }
2930
- async function readLocalCredentials(projectDir) {
2931
- return siteplaneCredentialsSchema.parse(JSON.parse(await readFile6(join4(projectDir, ".siteplane/credentials.json"), "utf8")));
3032
+ async function readProjectConfig(projectDir) {
3033
+ return siteplaneProjectConfigSchema.parse(JSON.parse(await readFile6(join4(projectDir, "siteplane.config.json"), "utf8")));
2932
3034
  }
2933
- async function writeCredentialsAtomically(path, credentials) {
3035
+ async function writeJsonAtomically(path, value, mode) {
2934
3036
  const temporaryPath = `${path}.${randomUUID3()}.tmp`;
2935
- const file = await open2(temporaryPath, "wx", 384);
3037
+ const file = await open2(temporaryPath, "wx", mode);
2936
3038
  try {
2937
- await file.writeFile(`${JSON.stringify(credentials, null, 2)}
3039
+ await file.writeFile(`${JSON.stringify(value, null, 2)}
2938
3040
  `, "utf8");
2939
3041
  await file.sync();
2940
3042
  } catch (error) {
@@ -2945,26 +3047,16 @@ async function writeCredentialsAtomically(path, credentials) {
2945
3047
  await file.close();
2946
3048
  try {
2947
3049
  await rename2(temporaryPath, path);
2948
- await chmod2(path, 384);
3050
+ await chmod2(path, mode);
2949
3051
  } catch (error) {
2950
3052
  await rm2(temporaryPath, { force: true });
2951
3053
  throw error;
2952
3054
  }
2953
3055
  }
2954
- var execFileAsync = promisify(execFile);
2955
- async function gitPathMatches(projectDir, path, command) {
2956
- const args = command === "check-ignore" ? ["check-ignore", "--quiet", relative(projectDir, path)] : ["ls-files", "--error-unmatch", relative(projectDir, path)];
2957
- try {
2958
- await execFileAsync("git", args, { cwd: projectDir });
2959
- return true;
2960
- } catch {
2961
- return false;
2962
- }
2963
- }
2964
3056
 
2965
3057
  // ../cli/dist/commands/init.js
2966
3058
  import { join as join5 } from "path";
2967
- import { z as z25 } from "zod";
3059
+ import { z as z26 } from "zod";
2968
3060
  async function initCommand(input) {
2969
3061
  if (!input.setupToken.trim()) {
2970
3062
  throw new Error("A Siteplane setup token is required.");
@@ -2984,24 +3076,24 @@ async function initCommand(input) {
2984
3076
  ]
2985
3077
  };
2986
3078
  }
2987
- var siteSetupBootstrapDataSchema = z25.object({
2988
- credentialPurpose: z25.literal("site_setup"),
2989
- apiBaseUrl: z25.string().url(),
2990
- siteId: z25.string().uuid(),
2991
- publicSiteKeyId: z25.string().uuid(),
2992
- publicSiteKey: z25.string().trim().min(1),
2993
- accessToken: z25.string().trim().min(1),
2994
- siteRevalidationSecret: z25.string().regex(/^[A-Za-z0-9_-]{43}$/u)
3079
+ var siteSetupBootstrapDataSchema = z26.object({
3080
+ credentialPurpose: z26.literal("site_setup"),
3081
+ apiBaseUrl: z26.string().url(),
3082
+ siteId: z26.string().uuid(),
3083
+ publicSiteKeyId: z26.string().uuid(),
3084
+ publicSiteKey: z26.string().trim().min(1),
3085
+ accessToken: z26.string().trim().min(1),
3086
+ siteRevalidationSecret: z26.string().regex(/^[A-Za-z0-9_-]{43}$/u)
2995
3087
  }).strict();
2996
- var featureBootstrapDataSchema = z25.object({
2997
- credentialPurpose: z25.enum(["analytics", "booking"]),
2998
- apiBaseUrl: z25.string().url(),
2999
- siteId: z25.string().uuid(),
3000
- accessToken: z25.string().trim().min(1)
3088
+ var featureBootstrapDataSchema = z26.object({
3089
+ credentialPurpose: z26.enum(["analytics", "booking"]),
3090
+ apiBaseUrl: z26.string().url(),
3091
+ siteId: z26.string().uuid(),
3092
+ accessToken: z26.string().trim().min(1)
3001
3093
  }).strict();
3002
- var bootstrapResponseSchema = z25.object({
3003
- ok: z25.literal(true),
3004
- data: z25.discriminatedUnion("credentialPurpose", [
3094
+ var bootstrapResponseSchema = z26.object({
3095
+ ok: z26.literal(true),
3096
+ data: z26.discriminatedUnion("credentialPurpose", [
3005
3097
  siteSetupBootstrapDataSchema,
3006
3098
  featureBootstrapDataSchema
3007
3099
  ])
@@ -3099,6 +3191,126 @@ function readErrorMessage(payload) {
3099
3191
  return null;
3100
3192
  }
3101
3193
 
3194
+ // ../cli/dist/commands/connect.js
3195
+ var claimResponseSchema = z27.object({
3196
+ ok: z27.literal(true),
3197
+ data: z27.object({
3198
+ pairingId: z27.string().uuid(),
3199
+ status: z27.literal("approval_required")
3200
+ }).passthrough()
3201
+ }).strict();
3202
+ var waitingResponseSchema = z27.object({
3203
+ ok: z27.literal(true),
3204
+ data: z27.object({ status: z27.literal("approval_required") }).strict()
3205
+ }).strict();
3206
+ var bootstrapResponseSchema2 = z27.object({
3207
+ ok: z27.literal(true),
3208
+ data: siteSetupBootstrapDataSchema
3209
+ }).strict();
3210
+ async function connectCommand(input) {
3211
+ if (!await detectNextProject(input.projectDir)) {
3212
+ throw new Error("Siteplane connect currently supports Next.js projects.");
3213
+ }
3214
+ await assertLocalCredentialsPathSafe(input.projectDir, {
3215
+ ...input.isIgnoredFile ? { isIgnoredFile: input.isIgnoredFile } : {},
3216
+ ...input.isTrackedFile ? { isTrackedFile: input.isTrackedFile } : {}
3217
+ });
3218
+ const fetcher = input.fetcher ?? fetch;
3219
+ const pollSecret = randomBytes(32).toString("base64url");
3220
+ const envelopeKey = randomBytes(32).toString("base64url");
3221
+ const endpoint = `${input.apiBaseUrl.replace(/\/$/, "")}/api/cli/connect`;
3222
+ const headers = createHeaders(input);
3223
+ const claimResponse = await fetcher(endpoint, {
3224
+ method: "POST",
3225
+ headers,
3226
+ body: JSON.stringify({
3227
+ action: "claim",
3228
+ pairingCode: input.pairingCode.trim().toUpperCase(),
3229
+ pollSecret,
3230
+ envelopeKey,
3231
+ agentLabel: input.agentLabel?.trim() || null
3232
+ })
3233
+ });
3234
+ const claimPayload = await readJson(claimResponse);
3235
+ const claim = claimResponseSchema.safeParse(claimPayload);
3236
+ if (!claimResponse.ok || !claim.success) {
3237
+ throw new Error(readErrorMessage2(claimPayload) ?? "Siteplane pairing failed.");
3238
+ }
3239
+ const wait = input.wait ?? ((milliseconds) => new Promise((resolve2) => setTimeout(resolve2, milliseconds)));
3240
+ let bootstrap = null;
3241
+ for (; ; ) {
3242
+ const pollResponse = await fetcher(endpoint, {
3243
+ method: "POST",
3244
+ headers,
3245
+ body: JSON.stringify({
3246
+ action: "poll",
3247
+ pairingId: claim.data.data.pairingId,
3248
+ pollSecret,
3249
+ envelopeKey
3250
+ })
3251
+ });
3252
+ const pollPayload = await readJson(pollResponse);
3253
+ const ready = bootstrapResponseSchema2.safeParse(pollPayload);
3254
+ if (pollResponse.ok && ready.success) {
3255
+ bootstrap = ready.data.data;
3256
+ break;
3257
+ }
3258
+ if (pollResponse.status !== 202 || !waitingResponseSchema.safeParse(pollPayload).success) {
3259
+ throw new Error(readErrorMessage2(pollPayload) ?? "Siteplane pairing was not approved.");
3260
+ }
3261
+ await wait(1500);
3262
+ }
3263
+ const paths = await persistSiteSetupBootstrap({
3264
+ projectDir: input.projectDir,
3265
+ setupToken: "pairing",
3266
+ apiBaseUrl: input.apiBaseUrl,
3267
+ ...input.isIgnoredFile ? { isIgnoredFile: input.isIgnoredFile } : {},
3268
+ ...input.isTrackedFile ? { isTrackedFile: input.isTrackedFile } : {}
3269
+ }, bootstrap);
3270
+ const acknowledgement = await fetcher(endpoint, {
3271
+ method: "POST",
3272
+ headers,
3273
+ body: JSON.stringify({
3274
+ action: "acknowledge",
3275
+ pairingId: claim.data.data.pairingId,
3276
+ pollSecret,
3277
+ envelopeKey
3278
+ })
3279
+ });
3280
+ if (!acknowledgement.ok) {
3281
+ throw new Error("Siteplane setup acknowledgement failed.");
3282
+ }
3283
+ return {
3284
+ ...paths,
3285
+ nextSteps: [
3286
+ "npx siteplane setup context",
3287
+ "Instrument the site and create EditorDefinitionV1.",
3288
+ "npx siteplane setup apply --definition /tmp/siteplane-editor.json"
3289
+ ]
3290
+ };
3291
+ }
3292
+ function createHeaders(input) {
3293
+ return new Headers({
3294
+ "content-type": "application/json",
3295
+ ...input.vercelAutomationBypassSecret?.trim() ? { "x-vercel-protection-bypass": input.vercelAutomationBypassSecret.trim() } : {}
3296
+ });
3297
+ }
3298
+ async function readJson(response) {
3299
+ try {
3300
+ return await response.json();
3301
+ } catch {
3302
+ return null;
3303
+ }
3304
+ }
3305
+ function readErrorMessage2(payload) {
3306
+ if (!payload || typeof payload !== "object" || !("error" in payload))
3307
+ return null;
3308
+ const error = payload.error;
3309
+ if (!error || typeof error !== "object" || !("message" in error))
3310
+ return null;
3311
+ return typeof error.message === "string" ? error.message : null;
3312
+ }
3313
+
3102
3314
  // ../cli/dist/commands/scan.js
3103
3315
  import { readdir } from "fs/promises";
3104
3316
  import { extname, join as join6 } from "path";
@@ -3144,7 +3356,7 @@ async function collectSourceFiles(directory) {
3144
3356
  import { execFile as execFile2 } from "child_process";
3145
3357
  import { readFile as readFile7 } from "fs/promises";
3146
3358
  import { promisify as promisify2 } from "util";
3147
- import { z as z26 } from "zod";
3359
+ import { z as z28 } from "zod";
3148
3360
 
3149
3361
  // ../cli/dist/scan/next-source-scan.js
3150
3362
  import ts2 from "typescript";
@@ -3811,49 +4023,52 @@ function isPositionalFieldReference(value) {
3811
4023
 
3812
4024
  // ../cli/dist/commands/site-setup.js
3813
4025
  var execFileAsync2 = promisify2(execFile2);
3814
- var safeErrorSchema = z26.object({
3815
- code: z26.string().trim().min(1),
3816
- message: z26.string().trim().min(1)
4026
+ var safeErrorSchema = z28.object({
4027
+ code: z28.string().trim().min(1),
4028
+ message: z28.string().trim().min(1)
3817
4029
  }).passthrough();
3818
- var errorResponseSchema2 = z26.object({ ok: z26.literal(false), error: safeErrorSchema }).passthrough();
3819
- var contextDataSchema = z26.object({
3820
- site: z26.object({ siteId: z26.string().uuid(), websiteUrl: z26.string().url() }),
3821
- run: z26.object({
3822
- runId: z26.string().uuid(),
3823
- mode: z26.enum(["initial", "update"]),
3824
- status: z26.enum([
4030
+ var errorResponseSchema2 = z28.object({ ok: z28.literal(false), error: safeErrorSchema }).passthrough();
4031
+ var contextDataSchema = z28.object({
4032
+ site: z28.object({ siteId: z28.string().uuid(), portalPath: z28.string() }),
4033
+ run: z28.object({
4034
+ runId: z28.string().uuid(),
4035
+ mode: z28.enum(["initial", "update"]),
4036
+ status: z28.enum([
3825
4037
  "waiting_for_agent",
3826
4038
  "working",
3827
4039
  "action_required",
3828
4040
  "ready_for_review"
3829
4041
  ]),
3830
- fieldContractHash: z26.string().nullable(),
3831
- deploymentOrigin: z26.string().nullable(),
3832
- deploymentRevision: z26.string().nullable(),
3833
- errorCode: z26.string().nullable(),
3834
- errorMessage: z26.string().nullable()
4042
+ fieldContractHash: z28.string().nullable(),
4043
+ deploymentOrigin: z28.string().nullable(),
4044
+ deploymentRevision: z28.string().nullable(),
4045
+ errorCode: z28.string().nullable(),
4046
+ errorMessage: z28.string().nullable()
3835
4047
  }),
3836
- allowedTasks: z26.array(z26.string()),
3837
- requiredEnvironmentNames: z26.array(z26.string())
4048
+ structureHandoff: z28.object({
4049
+ pendingFields: z28.array(setupCorrectionItemSchema).min(1).max(50)
4050
+ }).strict().nullable(),
4051
+ allowedTasks: z28.array(z28.string()),
4052
+ requiredEnvironmentNames: z28.array(z28.string())
3838
4053
  }).strict();
3839
- var contextResponseSchema = z26.object({ ok: z26.literal(true), data: contextDataSchema }).strict();
3840
- var applyDataSchema = z26.object({
3841
- status: z26.enum(["applied", "ready_for_review"]),
3842
- runId: z26.string().uuid().optional(),
3843
- contractVersionId: z26.string().uuid().optional(),
3844
- fieldContractHash: z26.string().regex(/^sha256:[0-9a-f]{64}$/u),
3845
- editorDefinitionHash: z26.string().regex(/^sha256:[0-9a-f]{64}$/u).optional(),
3846
- fieldCount: z26.number().int().nonnegative().optional(),
3847
- routeCount: z26.number().int().nonnegative().optional()
4054
+ var contextResponseSchema = z28.object({ ok: z28.literal(true), data: contextDataSchema }).strict();
4055
+ var applyDataSchema = z28.object({
4056
+ status: z28.enum(["applied", "ready_for_review"]),
4057
+ runId: z28.string().uuid().optional(),
4058
+ contractVersionId: z28.string().uuid().optional(),
4059
+ fieldContractHash: z28.string().regex(/^sha256:[0-9a-f]{64}$/u),
4060
+ editorDefinitionHash: z28.string().regex(/^sha256:[0-9a-f]{64}$/u).optional(),
4061
+ fieldCount: z28.number().int().nonnegative().optional(),
4062
+ routeCount: z28.number().int().nonnegative().optional()
3848
4063
  }).strict();
3849
- var applyResponseSchema = z26.object({ ok: z26.literal(true), data: applyDataSchema }).strict();
3850
- var verifyDataSchema = z26.object({
3851
- status: z26.literal("ready_for_review"),
3852
- runId: z26.string().uuid().optional(),
3853
- deploymentOrigin: z26.string().url().optional(),
3854
- deploymentRevision: z26.string().optional()
4064
+ var applyResponseSchema = z28.object({ ok: z28.literal(true), data: applyDataSchema }).strict();
4065
+ var verifyDataSchema = z28.object({
4066
+ status: z28.literal("ready_for_review"),
4067
+ runId: z28.string().uuid().optional(),
4068
+ deploymentOrigin: z28.string().url().optional(),
4069
+ deploymentRevision: z28.string().optional()
3855
4070
  }).strict();
3856
- var verifyResponseSchema = z26.object({ ok: z26.literal(true), data: verifyDataSchema }).strict();
4071
+ var verifyResponseSchema = z28.object({ ok: z28.literal(true), data: verifyDataSchema }).strict();
3857
4072
  async function siteSetupContextCommand(input) {
3858
4073
  const response = await postSiteSetup(input, "context", {});
3859
4074
  const parsed = contextResponseSchema.safeParse(response.payload);
@@ -3963,24 +4178,26 @@ async function readGitRevision(projectDir) {
3963
4178
  // src/bin/run-siteplane.ts
3964
4179
  async function runSiteplaneCli(args, dependencies = createDefaultDependencies()) {
3965
4180
  const [command, ...commandArgs] = args;
3966
- if (command === "init") {
3967
- const setupToken = readOption(commandArgs, "--setup-token");
3968
- const apiBaseUrl = readOption(commandArgs, "--api-base-url") ?? dependencies.env.SITEPLANE_API_BASE_URL ?? "https://app.siteplane.io";
3969
- if (!setupToken) {
3970
- throw new Error("Missing --setup-token.");
4181
+ if (command === "connect") {
4182
+ const pairingCode = commandArgs[0];
4183
+ if (pairingCode === "--help" || pairingCode === "-h") {
4184
+ dependencies.stdout("Usage: siteplane connect <pairing-code>");
4185
+ return { exitCode: 0 };
4186
+ }
4187
+ const apiBaseUrl = readOption(commandArgs, "--api-base-url") ?? dependencies.env.SITEPLANE_API_BASE_URL ?? "https://siteplane.io";
4188
+ if (!pairingCode || pairingCode.startsWith("--")) {
4189
+ throw new Error("Usage: siteplane connect <pairing-code>");
3971
4190
  }
3972
- const result = await dependencies.commands.initCommand({
4191
+ const result = await dependencies.commands.connectCommand({
3973
4192
  projectDir: dependencies.cwd(),
3974
- setupToken,
4193
+ pairingCode,
3975
4194
  apiBaseUrl,
3976
4195
  ...readOptionalVercelAutomationBypassSecret(dependencies.env)
3977
4196
  });
3978
4197
  dependencies.stdout(`Wrote ${result.configPath}`);
3979
4198
  dependencies.stdout(`Wrote ${result.credentialsPath}`);
3980
- dependencies.stdout("Next steps:");
3981
- for (const nextStep of result.nextSteps) {
3982
- dependencies.stdout(`- ${nextStep}`);
3983
- }
4199
+ dependencies.stdout("Siteplane connected. Next steps:");
4200
+ for (const nextStep of result.nextSteps) dependencies.stdout(`- ${nextStep}`);
3984
4201
  return { exitCode: 0 };
3985
4202
  }
3986
4203
  if (command === "booking") {
@@ -3997,10 +4214,10 @@ async function runSiteplaneCli(args, dependencies = createDefaultDependencies())
3997
4214
  return { exitCode: 0 };
3998
4215
  }
3999
4216
  if (command === "--help" || command === "-h") {
4000
- dependencies.stdout("Usage: siteplane <init|setup|analytics|booking>");
4217
+ dependencies.stdout("Usage: siteplane <connect|setup|analytics|booking>");
4001
4218
  return { exitCode: 0 };
4002
4219
  }
4003
- dependencies.stdout("Usage: siteplane <init|setup|analytics|booking>");
4220
+ dependencies.stdout("Usage: siteplane <connect|setup|analytics|booking>");
4004
4221
  return { exitCode: 1 };
4005
4222
  }
4006
4223
  async function runAnalyticsCommand(args, dependencies) {
@@ -4012,6 +4229,17 @@ async function runAnalyticsCommand(args, dependencies) {
4012
4229
  );
4013
4230
  return { exitCode: subcommand ? 0 : 1 };
4014
4231
  }
4232
+ if (subcommand === "init") {
4233
+ const setupToken = readOption(subcommandArgs, "--setup-token");
4234
+ if (setupToken) {
4235
+ await dependencies.commands.initCommand({
4236
+ projectDir,
4237
+ setupToken,
4238
+ apiBaseUrl: readOption(subcommandArgs, "--api-base-url") ?? dependencies.env.SITEPLANE_API_BASE_URL ?? "https://siteplane.io",
4239
+ ...readOptionalVercelAutomationBypassSecret(dependencies.env)
4240
+ });
4241
+ }
4242
+ }
4015
4243
  const [projectConfig, credentials] = await Promise.all([
4016
4244
  dependencies.commands.readProjectConfig(projectDir),
4017
4245
  dependencies.commands.readLocalCredentials(projectDir)
@@ -4286,6 +4514,7 @@ function createDefaultDependencies() {
4286
4514
  siteSetupApplyCommand,
4287
4515
  siteSetupContextCommand,
4288
4516
  siteSetupVerifyCommand,
4517
+ connectCommand,
4289
4518
  initCommand,
4290
4519
  bookingInitCommand,
4291
4520
  bookingCheckCommand,