@trops/dash-core 0.1.432 → 0.1.434

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.
@@ -64600,6 +64600,99 @@ function remapLayoutPackageScopes$1(
64600
64600
  return next;
64601
64601
  }
64602
64602
 
64603
+ /**
64604
+ * Defense-in-depth guard: throw if any layout item in `workspace`
64605
+ * still references a local-only scope (e.g. `@ai-built/...`).
64606
+ *
64607
+ * `remapLayoutPackageScopes` rewrites local scopes to the publisher's
64608
+ * scope BUT silently no-ops when no `callerScope` is available
64609
+ * (failed auth, no profile, no `authorId` fallback). When that
64610
+ * happens the publish would otherwise ship a manifest that no
64611
+ * installer can resolve — `@ai-built/...` only exists on the
64612
+ * publisher's machine.
64613
+ *
64614
+ * This function is meant to be called immediately after
64615
+ * `remapLayoutPackageScopes` on the publish path. It walks layout,
64616
+ * sidebarLayout, and every `pages[].layout`, and checks each item's
64617
+ * `packageId`, `_sourcePackage`, and scoped `component` field.
64618
+ *
64619
+ * Throws a single descriptive Error listing every violation (capped
64620
+ * at the first 10 to keep messages readable). Pure / side-effect-free
64621
+ * on the success path.
64622
+ *
64623
+ * @param {Object} workspace
64624
+ * @param {string[]} [localOnlyScopes=["ai-built"]]
64625
+ * @throws {Error} if any local-only scope reference remains
64626
+ */
64627
+ function assertNoLocalScopes$1(workspace, localOnlyScopes = ["ai-built"]) {
64628
+ if (!workspace || typeof workspace !== "object") return;
64629
+ const localSet = new Set(
64630
+ localOnlyScopes.map((s) => String(s).replace(/^@/, "")),
64631
+ );
64632
+ const violations = [];
64633
+
64634
+ const checkPackageId = (pkgId, where) => {
64635
+ if (typeof pkgId !== "string" || pkgId.length === 0) return;
64636
+ const m = pkgId.match(/^@?([^/]+)\//);
64637
+ if (m && localSet.has(m[1])) {
64638
+ violations.push(`${where}: ${pkgId}`);
64639
+ }
64640
+ };
64641
+ const checkComponent = (component, where) => {
64642
+ if (typeof component !== "string" || component.length === 0) return;
64643
+ const parts = component.split(".");
64644
+ if (parts.length === 3 && localSet.has(parts[0])) {
64645
+ violations.push(`${where}: ${component}`);
64646
+ }
64647
+ };
64648
+
64649
+ const walkItem = (item, path) => {
64650
+ if (!item || typeof item !== "object") return;
64651
+ const at = `${path}#${item.id ?? item.uuid ?? "?"}`;
64652
+ if (item.packageId) checkPackageId(item.packageId, `${at}.packageId`);
64653
+ if (item._sourcePackage) {
64654
+ checkPackageId(item._sourcePackage, `${at}._sourcePackage`);
64655
+ }
64656
+ if (item.component) checkComponent(item.component, `${at}.component`);
64657
+ if (Array.isArray(item.items)) {
64658
+ item.items.forEach((c, i) => walkItem(c, `${at}.items[${i}]`));
64659
+ }
64660
+ if (Array.isArray(item.layout)) {
64661
+ item.layout.forEach((c, i) => walkItem(c, `${at}.layout[${i}]`));
64662
+ }
64663
+ };
64664
+
64665
+ if (Array.isArray(workspace.layout)) {
64666
+ workspace.layout.forEach((item, i) => walkItem(item, `layout[${i}]`));
64667
+ }
64668
+ if (Array.isArray(workspace.sidebarLayout)) {
64669
+ workspace.sidebarLayout.forEach((item, i) =>
64670
+ walkItem(item, `sidebarLayout[${i}]`),
64671
+ );
64672
+ }
64673
+ if (Array.isArray(workspace.pages)) {
64674
+ workspace.pages.forEach((page, pi) => {
64675
+ if (page && Array.isArray(page.layout)) {
64676
+ page.layout.forEach((item, i) =>
64677
+ walkItem(item, `pages[${pi}].layout[${i}]`),
64678
+ );
64679
+ }
64680
+ });
64681
+ }
64682
+
64683
+ if (violations.length === 0) return;
64684
+ const scopesList = [...localSet].join(", ");
64685
+ const head = violations.slice(0, 10).join("\n - ");
64686
+ const tail =
64687
+ violations.length > 10 ? `\n - ...and ${violations.length - 10} more` : "";
64688
+ throw new Error(
64689
+ `Refusing to publish: ${violations.length} layout item(s) still reference ` +
64690
+ `local-only scope(s) [${scopesList}] after rescoping. This usually ` +
64691
+ `means the publisher has no resolved caller scope (registry auth ` +
64692
+ `missing, no githubUser, no authorId). Violations:\n - ${head}${tail}`,
64693
+ );
64694
+ }
64695
+
64603
64696
  var dashboardConfigUtils$1 = {
64604
64697
  collectComponentNames: collectComponentNames$1,
64605
64698
  collectComponentNamesFromWorkspace: collectComponentNamesFromWorkspace$1,
@@ -64617,6 +64710,7 @@ var dashboardConfigUtils$1 = {
64617
64710
  checkApiCompatibility,
64618
64711
  stripPersonalizationFromWorkspace: stripPersonalizationFromWorkspace$1,
64619
64712
  remapLayoutPackageScopes: remapLayoutPackageScopes$1,
64713
+ assertNoLocalScopes: assertNoLocalScopes$1,
64620
64714
  };
64621
64715
 
64622
64716
  /**
@@ -65659,6 +65753,7 @@ const {
65659
65753
  applyEventWiringToLayout,
65660
65754
  stripPersonalizationFromWorkspace,
65661
65755
  remapLayoutPackageScopes,
65756
+ assertNoLocalScopes,
65662
65757
  } = dashboardConfigUtils$1;
65663
65758
  const { searchRegistry, getPackage } = registryController$3;
65664
65759
  const { getStoredToken, clearToken } = registryAuthController$2;
@@ -67105,6 +67200,14 @@ async function prepareDashboardForPublish$1(
67105
67200
  resolvedCallerScope,
67106
67201
  );
67107
67202
  }
67203
+ // Defense in depth: if remap was a no-op (no resolved caller scope)
67204
+ // OR if a code path slipped a local-scope reference in after the
67205
+ // remap, fail loudly instead of shipping a manifest no installer
67206
+ // can resolve. `@ai-built/...` only exists on the publisher's
67207
+ // machine — letting it through silently produces "package not
67208
+ // found" errors at install time, which is the harder failure mode
67209
+ // to debug.
67210
+ assertNoLocalScopes(sharedWorkspace);
67108
67211
  const layout = sharedWorkspace.layout || [];
67109
67212
 
67110
67213
  // 3. Build the dashboard config — walk main + pages + sidebar