@wix/himalaya-cli 0.1456.0 → 0.1458.0

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.
@@ -9037,7 +9037,9 @@ var screenDescriptorSchema = {
9037
9037
  maxArgDepth: { type: "integer", minimum: 1 },
9038
9038
  maxMessageBytes: { type: "integer", minimum: 1 },
9039
9039
  rateLimitMaxCalls: { type: "integer", minimum: 1 },
9040
- rateLimitWindowMs: { type: "integer", minimum: 1 }
9040
+ rateLimitWindowMs: { type: "integer", minimum: 1 },
9041
+ // RFC 0073 §4.4 — "" is today's T4 floor; "app_content" raises the caps.
9042
+ profile: { type: "string", enum: ["", "app_content"] }
9041
9043
  }
9042
9044
  },
9043
9045
  contentFilterRules: { type: "string" },
@@ -9069,7 +9071,17 @@ var screenDescriptorSchema = {
9069
9071
  // RFC 0062 §5.8 — the native session bridge (fields 47/48).
9070
9072
  sessionBridge: { type: "boolean" },
9071
9073
  hostedSiteAdapter: { type: "string", enum: ["", "wix", "base44"] },
9072
- hideHostedSiteMenu: { type: "boolean" }
9074
+ hideHostedSiteMenu: { type: "boolean" },
9075
+ // RFC 0073 §4 — embedded worker-bridged WebViews (fields 52–54).
9076
+ originIsolation: { type: "string", enum: ["", "shared", "per_instance"] },
9077
+ framePolicy: { type: "string", enum: ["", "content"] },
9078
+ storageSeed: {
9079
+ type: "object",
9080
+ additionalProperties: false,
9081
+ properties: {
9082
+ snapshotPath: { type: "string" }
9083
+ }
9084
+ }
9073
9085
  }
9074
9086
  }
9075
9087
  }
@@ -14124,6 +14136,373 @@ function mergeSiteMenu(nav, site, menu) {
14124
14136
  function siteMenuDrifted(drift) {
14125
14137
  return drift.added.length > 0 || drift.removed.length > 0 || drift.renamed.length > 0;
14126
14138
  }
14139
+
14140
+ // ../../core/ts/src/webview-origin.ts
14141
+ function hasDotSegment(absolute) {
14142
+ const schemeEnd = absolute.indexOf("://");
14143
+ if (schemeEnd < 0) return false;
14144
+ const hierarchical = absolute.slice(schemeEnd + 3).split(/[?#]/)[0];
14145
+ const pathStart = hierarchical.indexOf("/");
14146
+ if (pathStart < 0) return false;
14147
+ return hierarchical.slice(pathStart).replace(/%2e/g, ".").split("/").some((seg) => seg === "." || seg === "..");
14148
+ }
14149
+ function rawUrlParts(url) {
14150
+ const trimmed = url.replace(/^[\u0000- ]+|[\u0000- ]+$/g, "");
14151
+ if (/[\\\u0000-\u0020\u007f]/.test(trimmed)) return null;
14152
+ const raw = trimmed;
14153
+ const m = /^([a-z][a-z0-9+.-]*):\/\/([^/?#]*)/i.exec(raw);
14154
+ if (!m) return null;
14155
+ const authority = m[2].slice(m[2].lastIndexOf("@") + 1);
14156
+ let host;
14157
+ let port = "";
14158
+ if (authority.startsWith("[")) {
14159
+ const close = authority.indexOf("]");
14160
+ if (close < 0) return null;
14161
+ host = authority.slice(1, close);
14162
+ const rest = authority.slice(close + 1);
14163
+ if (rest.startsWith(":")) port = rest.slice(1);
14164
+ } else {
14165
+ const colon = authority.lastIndexOf(":");
14166
+ host = colon >= 0 ? authority.slice(0, colon) : authority;
14167
+ port = colon >= 0 ? authority.slice(colon + 1) : "";
14168
+ }
14169
+ host = host.toLowerCase();
14170
+ if (!host) return null;
14171
+ if (port !== "" && !/^\d+$/.test(port)) return null;
14172
+ let parsed;
14173
+ try {
14174
+ parsed = new URL(raw);
14175
+ } catch {
14176
+ return null;
14177
+ }
14178
+ const scheme = m[1].toLowerCase();
14179
+ const bracketless = parsed.hostname.replace(/^\[|\]$/g, "").toLowerCase();
14180
+ if (parsed.protocol !== `${scheme}:` || bracketless !== host) return null;
14181
+ if (parsed.port !== "" && parsed.port !== String(Number(port))) return null;
14182
+ return { absolute: raw.toLowerCase(), host, hostPort: port !== "" ? `${host}:${Number(port)}` : host };
14183
+ }
14184
+ function webViewOriginAllowed(url, origins) {
14185
+ const u = rawUrlParts(url);
14186
+ if (!u) return false;
14187
+ const { absolute, host, hostPort } = u;
14188
+ for (const o of origins) {
14189
+ const origin = o.toLowerCase();
14190
+ if (origin.endsWith("/") && origin.includes("://")) {
14191
+ if (hasDotSegment(absolute)) continue;
14192
+ const base = origin.slice(0, -1);
14193
+ if (absolute.startsWith(origin) || absolute === base || absolute.startsWith(base + "?") || absolute.startsWith(base + "#")) return true;
14194
+ continue;
14195
+ }
14196
+ if (origin === host || origin === hostPort) return true;
14197
+ if (absolute.startsWith(origin)) {
14198
+ const next = absolute.charAt(origin.length);
14199
+ if (origin.endsWith("/") || next === "" || next === "/" || next === "?" || next === "#") return true;
14200
+ }
14201
+ if (origin.startsWith("*.") || origin.startsWith(".")) {
14202
+ const suffix = origin.startsWith("*.") ? origin.slice(2) : origin.slice(1);
14203
+ if (host === suffix || host.endsWith(`.${suffix}`)) return true;
14204
+ }
14205
+ }
14206
+ return false;
14207
+ }
14208
+
14209
+ // ../../core/ts/src/webview-embedded.ts
14210
+ var MAX_SIMULTANEOUS_BRIDGED_WEBVIEWS = 4;
14211
+ var WEBVIEW_EMBEDDED_ENUMS = {
14212
+ bridge: ["", "worker"],
14213
+ originIsolation: ["", "shared", "per_instance"],
14214
+ framePolicy: ["", "content"],
14215
+ profile: ["", "app_content"]
14216
+ };
14217
+ var isRec = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
14218
+ var byCodeUnit = (a, b) => a < b ? -1 : a > b ? 1 : 0;
14219
+ function canonicalJson(value) {
14220
+ return canonicalJsonAt(value, /* @__PURE__ */ new Set());
14221
+ }
14222
+ function canonicalJsonAt(value, path) {
14223
+ if (value === null || typeof value === "boolean" || typeof value === "string") return JSON.stringify(value);
14224
+ if (typeof value === "number") {
14225
+ if (!Number.isFinite(value)) throw new TypeError(`canonicalJson: ${value} is not representable in JSON`);
14226
+ return String(value);
14227
+ }
14228
+ if (typeof value !== "object") throw new TypeError(`canonicalJson: a ${typeof value} is not JSON data`);
14229
+ if (path.has(value)) throw new TypeError("canonicalJson: a cyclic value is not JSON data");
14230
+ path.add(value);
14231
+ try {
14232
+ if (Array.isArray(value)) {
14233
+ const parts = [];
14234
+ for (let i = 0; i < value.length; i++) {
14235
+ if (!(i in value)) throw new TypeError(`canonicalJson: array element ${i} is a hole, which is not JSON data`);
14236
+ const v = value[i];
14237
+ if (v === void 0) throw new TypeError(`canonicalJson: array element ${i} is undefined, which is not JSON data`);
14238
+ parts.push(canonicalJsonAt(v, path));
14239
+ }
14240
+ return `[${parts.join(",")}]`;
14241
+ }
14242
+ const proto = Object.getPrototypeOf(value);
14243
+ if (proto !== Object.prototype && proto !== null) {
14244
+ throw new TypeError(`canonicalJson: a ${value.constructor?.name ?? "non-plain object"} is not JSON data \u2014 pass a plain object, an array, or a primitive`);
14245
+ }
14246
+ const rec = value;
14247
+ const keys = Object.keys(rec).filter((k) => rec[k] !== void 0).sort(byCodeUnit);
14248
+ return `{${keys.map((k) => `${JSON.stringify(k)}:${canonicalJsonAt(rec[k], path)}`).join(",")}}`;
14249
+ } finally {
14250
+ path.delete(value);
14251
+ }
14252
+ }
14253
+ function canonicalScreenArgs(args) {
14254
+ if (!args) return "";
14255
+ return Object.keys(args).filter((k) => args[k] !== void 0).sort(byCodeUnit).map((k) => `${encodeURIComponent(k)}=${encodeURIComponent(canonicalJson(args[k]))}`).join("&");
14256
+ }
14257
+ function effectiveWebViewInstanceId(screenId, args, componentId, explicitInstanceId) {
14258
+ if (typeof explicitInstanceId === "string" && explicitInstanceId !== "") return explicitInstanceId;
14259
+ return `${screenId}?${canonicalScreenArgs(args)}/${componentId}`;
14260
+ }
14261
+ var isComponent = (v) => isRec(v) && isRec(v.body) && typeof v.body.package === "string" && typeof v.body.type === "string";
14262
+ var typeOf = (c) => {
14263
+ const body = c.body;
14264
+ return body.package === "himalaya" ? body.type : null;
14265
+ };
14266
+ var propsOf = (c) => {
14267
+ const p = c.body.props;
14268
+ return isRec(p) ? p : {};
14269
+ };
14270
+ var hasItemsPath = (props) => typeof props.itemsPath === "string" && props.itemsPath !== "";
14271
+ function childComponents(value, path, inTemplate, out) {
14272
+ if (Array.isArray(value)) {
14273
+ value.forEach((v, i) => childComponents(v, `${path}[${i}]`, inTemplate, out));
14274
+ return;
14275
+ }
14276
+ if (!isRec(value)) return;
14277
+ if (isComponent(value)) {
14278
+ out.push({ c: value, path, inTemplate });
14279
+ return;
14280
+ }
14281
+ for (const [k, v] of Object.entries(value)) childComponents(v, `${path}.${k}`, inTemplate || /Template$/.test(k), out);
14282
+ }
14283
+ function childrenOf(c, path, inTemplate) {
14284
+ const props = propsOf(c);
14285
+ const type = typeOf(c);
14286
+ const boundList = (type === "LazyList" || type === "Grid" || type === "Carousel") && hasItemsPath(props);
14287
+ const out = [];
14288
+ for (const [k, v] of Object.entries(props)) {
14289
+ const templ = inTemplate || /Template$/.test(k) || boundList && k === "items";
14290
+ childComponents(v, `${path}.body.props.${k}`, templ, out);
14291
+ }
14292
+ return out;
14293
+ }
14294
+ function roots(descriptor) {
14295
+ const out = [];
14296
+ for (const key of ["payload", "stickyHeader", "stickyFooter"]) {
14297
+ const v = descriptor[key];
14298
+ if (isComponent(v)) out.push({ c: v, path: key });
14299
+ }
14300
+ return out;
14301
+ }
14302
+ function collectWebViews(descriptor) {
14303
+ const sites = [];
14304
+ const visit = (c, path, inTemplate) => {
14305
+ if (typeOf(c) === "WebView") {
14306
+ sites.push({ path, id: typeof c.id === "string" ? c.id : "", props: propsOf(c), inTemplate });
14307
+ }
14308
+ for (const child of childrenOf(c, path, inTemplate)) visit(child.c, child.path, child.inTemplate);
14309
+ };
14310
+ for (const r of roots(descriptor)) visit(r.c, r.path, false);
14311
+ return sites;
14312
+ }
14313
+ var isBridged = (props) => props.bridge === "worker";
14314
+ var configOf = (props) => isRec(props.config) ? props.config : {};
14315
+ var isPerInstance = (props) => configOf(props).originIsolation === "per_instance";
14316
+ var isLiteral = (v) => typeof v === "string" && v !== "" && !v.startsWith("$");
14317
+ var isItemDerived = (v) => typeof v === "string" && /\$item\.[A-Za-z0-9_]/.test(v);
14318
+ function mountable(c, inTemplate = false) {
14319
+ const type = typeOf(c);
14320
+ const props = propsOf(c);
14321
+ const repeated = (n) => inTemplate && n > 0 ? Infinity : n;
14322
+ if (type === "WebView") return repeated(isBridged(props) ? 1 : 0);
14323
+ if (type === "LazyList") {
14324
+ let slots = 0;
14325
+ for (const [k, v] of Object.entries(props)) {
14326
+ if (k === "items") continue;
14327
+ const found = [];
14328
+ childComponents(v, "", inTemplate || /Template$/.test(k), found);
14329
+ for (const child of found) slots += mountable(child.c, child.inTemplate);
14330
+ }
14331
+ return slots;
14332
+ }
14333
+ if (type === "Carousel" || type === "Pager") {
14334
+ const pages = type === "Carousel" ? props.items : props.pages;
14335
+ const perPage = Array.isArray(pages) ? pages.map((p) => isComponent(p) ? mountable(p) : 0) : [];
14336
+ const window = typeof props.liveWindow === "number" && props.liveWindow > 0 ? Math.floor(props.liveWindow) : 0;
14337
+ const bound = type === "Carousel" && hasItemsPath(props);
14338
+ if (bound) {
14339
+ const template = perPage[0] ?? 0;
14340
+ if (template === 0) return 0;
14341
+ return repeated(window > 0 ? template * (2 * window + 1) : Infinity);
14342
+ }
14343
+ if (window > 0) return repeated(perPage.sort((a, b) => b - a).slice(0, 2 * window + 1).reduce((a, b) => a + b, 0));
14344
+ return repeated(perPage.reduce((a, b) => a + b, 0));
14345
+ }
14346
+ if (type === "Grid" && hasItemsPath(props)) {
14347
+ const items = props.items;
14348
+ const template = Array.isArray(items) && isComponent(items[0]) ? mountable(items[0]) : 0;
14349
+ return template === 0 ? 0 : Infinity;
14350
+ }
14351
+ let total = 0;
14352
+ for (const child of childrenOf(c, "", inTemplate)) total += mountable(child.c, child.inTemplate);
14353
+ return total;
14354
+ }
14355
+ function webViewEmbeddedFindings(descriptor) {
14356
+ if (!isRec(descriptor)) return [];
14357
+ const out = [];
14358
+ const screenConfig = isRec(descriptor.webViewConfig) ? descriptor.webViewConfig : {};
14359
+ if (screenConfig.storageSeed !== void 0 && screenConfig.originIsolation !== "per_instance") {
14360
+ out.push({
14361
+ severity: "error",
14362
+ rule: "storage_seed_requires_per_instance",
14363
+ path: "webViewConfig.storageSeed",
14364
+ message: `the screen's webViewConfig sets storageSeed without originIsolation: "per_instance" \u2014 a seed migrates into a per-instance origin only (RFC 0073 \xA74.2)`
14365
+ });
14366
+ }
14367
+ const sites = collectWebViews(descriptor);
14368
+ if (sites.length === 0) return out;
14369
+ const screenId = typeof descriptor.screenId === "string" ? descriptor.screenId : "";
14370
+ const lb = isRec(descriptor.logicBundle) ? descriptor.logicBundle : null;
14371
+ const caps = lb && Array.isArray(lb.declaredCapabilities) ? lb.declaredCapabilities : [];
14372
+ const seen = /* @__PURE__ */ new Map();
14373
+ for (const s of sites) {
14374
+ const { props, path } = s;
14375
+ const config = configOf(props);
14376
+ const bridged = isBridged(props);
14377
+ const security = isRec(config.bridgeSecurity) ? config.bridgeSecurity : {};
14378
+ for (const [field, value, prop] of [
14379
+ ["bridge", props.bridge, "bridge"],
14380
+ ["originIsolation", config.originIsolation, "config.originIsolation"],
14381
+ ["framePolicy", config.framePolicy, "config.framePolicy"],
14382
+ ["profile", security.profile, "config.bridgeSecurity.profile"]
14383
+ ]) {
14384
+ const allowed = WEBVIEW_EMBEDDED_ENUMS[field];
14385
+ if (value === void 0 || typeof value === "string" && allowed.includes(value)) continue;
14386
+ out.push({
14387
+ severity: "error",
14388
+ rule: "unknown_enum_value",
14389
+ path: `${path}.body.props.${prop}`,
14390
+ message: `WebView "${s.id}" sets ${prop}: ${JSON.stringify(value)} \u2014 not one of ${allowed.map((v) => JSON.stringify(v)).join(" | ")}; the hosts read an unknown value as ${JSON.stringify(allowed[0])} (RFC 0073 \xA74)`
14391
+ });
14392
+ }
14393
+ if (bridged && (!lb || !caps.includes("webview"))) {
14394
+ out.push({
14395
+ severity: "error",
14396
+ rule: "bridge_requires_worker",
14397
+ path: `${path}.body.props.bridge`,
14398
+ message: !lb ? `WebView "${s.id}" sets bridge: "worker" but the screen has no logicBundle \u2014 the channel connects the page to the screen's worker (RFC 0073 \xA74.6)` : `WebView "${s.id}" sets bridge: "worker" but logicBundle.declaredCapabilities lacks "webview" (RFC 0073 \xA73, \xA74.6)`
14399
+ });
14400
+ }
14401
+ if ((bridged || isPerInstance(props)) && s.inTemplate && !isItemDerived(props.instanceId)) {
14402
+ out.push({
14403
+ severity: "error",
14404
+ rule: "template_instance_id",
14405
+ path: `${path}.body.props.instanceId`,
14406
+ message: `WebView "${s.id}" is ${bridged ? "bridged" : `per_instance`} inside an item template but its instanceId is not derived from the item (e.g. "$item.id") \u2014 every row would share one ${bridged ? "channel and one origin" : "origin and its storage"} (RFC 0073 \xA74.1)`
14407
+ });
14408
+ }
14409
+ if ((bridged || isPerInstance(props)) && !s.inTemplate) {
14410
+ const explicit = props.instanceId;
14411
+ const effective = isLiteral(explicit) ? explicit : explicit === void 0 || explicit === "" ? effectiveWebViewInstanceId(screenId, void 0, s.id) : null;
14412
+ if (effective !== null) {
14413
+ const first = seen.get(effective);
14414
+ if (first !== void 0) {
14415
+ out.push({
14416
+ severity: "error",
14417
+ rule: "duplicate_instance_id",
14418
+ path: `${path}.body.props.instanceId`,
14419
+ message: `WebView "${s.id}" has the same effective instance_id "${effective}" as ${first} \u2014 two pages on one screen would share a channel and storage (RFC 0073 \xA74.1)`
14420
+ });
14421
+ } else {
14422
+ seen.set(effective, path);
14423
+ }
14424
+ }
14425
+ }
14426
+ if (config.storageSeed !== void 0 && config.originIsolation !== "per_instance") {
14427
+ out.push({
14428
+ severity: "error",
14429
+ rule: "storage_seed_requires_per_instance",
14430
+ path: `${path}.body.props.config.storageSeed`,
14431
+ message: `WebView "${s.id}" sets config.storageSeed without originIsolation: "per_instance" \u2014 a seed migrates into a per-instance origin only (RFC 0073 \xA74.2)`
14432
+ });
14433
+ }
14434
+ if (config.originIsolation === "per_instance" && typeof props.url === "string" && props.url !== "") {
14435
+ out.push({
14436
+ severity: "warning",
14437
+ rule: "per_instance_with_url",
14438
+ path: `${path}.body.props.config.originIsolation`,
14439
+ message: `WebView "${s.id}" sets originIsolation: "per_instance" with a url \u2014 per-instance origins apply to inlineHtml only; a url keeps its own origin (RFC 0073 \xA74.2)`
14440
+ });
14441
+ }
14442
+ if (props.fill === true && (props.height !== void 0 || props.aspectRatio !== void 0 || props.heightPath !== void 0)) {
14443
+ out.push({
14444
+ severity: "warning",
14445
+ rule: "fill_with_height",
14446
+ path: `${path}.body.props.fill`,
14447
+ message: `WebView "${s.id}" sets fill together with height / aspectRatio / heightPath \u2014 fill wins and the others are ignored (RFC 0073 \xA74)`
14448
+ });
14449
+ }
14450
+ if (bridged && isLiteral(props.url)) {
14451
+ const allowed = Array.isArray(config.allowedOrigins) ? config.allowedOrigins.filter((o) => typeof o === "string") : [];
14452
+ if (allowed.length > 0 && !webViewOriginAllowed(props.url, allowed)) {
14453
+ out.push({
14454
+ severity: "warning",
14455
+ rule: "bridged_url_not_allowed",
14456
+ path: `${path}.body.props.url`,
14457
+ message: `WebView "${s.id}" is bridged to a url whose origin is not listed in config.allowedOrigins \u2014 list it to assert the page is app-controlled; web refuses the bridge otherwise (RFC 0073 \xA74.6, \xA78)`
14458
+ });
14459
+ }
14460
+ }
14461
+ }
14462
+ let total = 0;
14463
+ let crossedAt = "";
14464
+ for (const r of roots(descriptor)) {
14465
+ total += mountable(r.c);
14466
+ if (crossedAt === "" && total > MAX_SIMULTANEOUS_BRIDGED_WEBVIEWS) crossedAt = r.path;
14467
+ }
14468
+ if (crossedAt !== "") {
14469
+ out.push({
14470
+ severity: "warning",
14471
+ rule: "too_many_bridged",
14472
+ path: crossedAt,
14473
+ message: `this screen can mount ${Number.isFinite(total) ? total : "an unbounded number of"} worker-bridged WebViews at once (more than ${MAX_SIMULTANEOUS_BRIDGED_WEBVIEWS}) \u2014 put them in a LazyList or a Carousel/Pager with liveWindow (RFC 0073 \xA74.5)`
14474
+ });
14475
+ }
14476
+ return out;
14477
+ }
14478
+ function webViewEmbeddedAppFindings(screens) {
14479
+ const byId = /* @__PURE__ */ new Map();
14480
+ for (const { screenId, descriptor } of screens) {
14481
+ if (!isRec(descriptor)) continue;
14482
+ for (const s of collectWebViews(descriptor)) {
14483
+ if (!isPerInstance(s.props) || !isLiteral(s.props.instanceId)) continue;
14484
+ const content = [s.props.inlineHtml, s.props.url].find(isLiteral);
14485
+ if (content === void 0) continue;
14486
+ const list = byId.get(s.props.instanceId) ?? [];
14487
+ list.push({ screenId, path: s.path, content });
14488
+ byId.set(s.props.instanceId, list);
14489
+ }
14490
+ }
14491
+ const out = [];
14492
+ for (const [id, uses] of byId) {
14493
+ const screensSeen = new Set(uses.map((u) => u.screenId));
14494
+ const contents = new Set(uses.map((u) => u.content));
14495
+ if (screensSeen.size < 2 || contents.size < 2) continue;
14496
+ out.push({
14497
+ severity: "warning",
14498
+ rule: "instance_id_reused_across_screens",
14499
+ screenId: uses[0].screenId,
14500
+ path: `${uses[0].path}.body.props.instanceId`,
14501
+ message: `per_instance instanceId "${id}" is bound to different content on screens ${[...screensSeen].join(", ")} \u2014 they would share one origin and its storage (RFC 0073 \xA74.1)`
14502
+ });
14503
+ }
14504
+ return out;
14505
+ }
14127
14506
  export {
14128
14507
  ALL_ORIENTATIONS,
14129
14508
  APP_ID_PATTERN,
@@ -14156,6 +14535,7 @@ export {
14156
14535
  LAUNCH_MANIFEST_SCHEMA,
14157
14536
  LAUNCH_NAMESPACE,
14158
14537
  LINK_MOUNT_PATHS,
14538
+ MAX_SIMULTANEOUS_BRIDGED_WEBVIEWS,
14159
14539
  OAUTH_IDP_ORIGINS,
14160
14540
  ORIGIN_PARAM_KEYS,
14161
14541
  PACKAGE_SHARE_ID_PATTERN,
@@ -14195,6 +14575,7 @@ export {
14195
14575
  SYSTEM_FONT_FAMILY,
14196
14576
  TONAL_ELEVATION_ALPHA,
14197
14577
  UNIVERSAL_LAUNCH_NAMESPACES,
14578
+ WEBVIEW_EMBEDDED_ENUMS,
14198
14579
  WIDGET_COMPONENTS,
14199
14580
  WIDGET_FAMILIES,
14200
14581
  WIDGET_VOCABULARY,
@@ -14212,6 +14593,8 @@ export {
14212
14593
  buildTokenRegistry,
14213
14594
  buttonHitSlop,
14214
14595
  buttonVariant,
14596
+ canonicalJson,
14597
+ canonicalScreenArgs,
14215
14598
  chassisOuterSize,
14216
14599
  checkTierCaps,
14217
14600
  chooseCandidate,
@@ -14226,6 +14609,7 @@ export {
14226
14609
  defineSitePageScreen,
14227
14610
  defineSiteTab,
14228
14611
  effectiveFieldRule,
14612
+ effectiveWebViewInstanceId,
14229
14613
  errorMessageFor,
14230
14614
  evaluate,
14231
14615
  evaluateAll,
@@ -14313,6 +14697,9 @@ export {
14313
14697
  validateWorkerSubtree,
14314
14698
  validators,
14315
14699
  viewTargetRenderMode,
14700
+ webViewEmbeddedAppFindings,
14701
+ webViewEmbeddedFindings,
14702
+ webViewOriginAllowed,
14316
14703
  widgetSnapshotSchema,
14317
14704
  workerSubtreePolicyErrors,
14318
14705
  workerSubtreeSha256
@@ -7729,7 +7729,9 @@ var screenDescriptorSchema = {
7729
7729
  maxArgDepth: { type: "integer", minimum: 1 },
7730
7730
  maxMessageBytes: { type: "integer", minimum: 1 },
7731
7731
  rateLimitMaxCalls: { type: "integer", minimum: 1 },
7732
- rateLimitWindowMs: { type: "integer", minimum: 1 }
7732
+ rateLimitWindowMs: { type: "integer", minimum: 1 },
7733
+ // RFC 0073 §4.4 — "" is today's T4 floor; "app_content" raises the caps.
7734
+ profile: { type: "string", enum: ["", "app_content"] }
7733
7735
  }
7734
7736
  },
7735
7737
  contentFilterRules: { type: "string" },
@@ -7761,7 +7763,17 @@ var screenDescriptorSchema = {
7761
7763
  // RFC 0062 §5.8 — the native session bridge (fields 47/48).
7762
7764
  sessionBridge: { type: "boolean" },
7763
7765
  hostedSiteAdapter: { type: "string", enum: ["", "wix", "base44"] },
7764
- hideHostedSiteMenu: { type: "boolean" }
7766
+ hideHostedSiteMenu: { type: "boolean" },
7767
+ // RFC 0073 §4 — embedded worker-bridged WebViews (fields 52–54).
7768
+ originIsolation: { type: "string", enum: ["", "shared", "per_instance"] },
7769
+ framePolicy: { type: "string", enum: ["", "content"] },
7770
+ storageSeed: {
7771
+ type: "object",
7772
+ additionalProperties: false,
7773
+ properties: {
7774
+ snapshotPath: { type: "string" }
7775
+ }
7776
+ }
7765
7777
  }
7766
7778
  }
7767
7779
  }