@blotout/qinto-cli 0.1.17 → 0.1.18

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.
@@ -18959,6 +18959,10 @@ var uniqueOrIssue = (ctx, values, path, label) => {
18959
18959
  seen.add(value);
18960
18960
  }
18961
18961
  };
18962
+ var PLATFORM_ZONES = ["blotout.io", "qinto.tech"];
18963
+ var isPlatformHost = (host) => {
18964
+ return PLATFORM_ZONES.some((zone) => host === zone || host.endsWith(`.${zone}`));
18965
+ };
18962
18966
 
18963
18967
  // ../../../libs/app-manifest/src/oauth.ts
18964
18968
  var OAUTH_TOKEN_METHODS = ["POST", "GET"];
@@ -18988,8 +18992,7 @@ var RESERVED_AUTHORIZE_PARAMS = /* @__PURE__ */ new Set([
18988
18992
  var PRIVATE_HOST = /^(localhost|\[?::1\]?|.+\.local|.+\.internal|10\..+|127\..+|169\.254\..+|192\.168\..+|172\.(1[6-9]|2\d|3[01])\..+|\d+\.\d+\.\d+\.\d+)$/;
18989
18993
  var vendorUrl = (field2) => {
18990
18994
  return httpsUrl(field2).refine((value) => {
18991
- const host = new URL(value).hostname;
18992
- return host !== "qinto.io" && !host.endsWith(".qinto.io") && host !== "qinto.tech" && !host.endsWith(".qinto.tech");
18995
+ return !isPlatformHost(new URL(value).hostname);
18993
18996
  }, `${field2} must be the vendor's own endpoint, not a Qinto platform URL`).refine((value) => {
18994
18997
  return !PRIVATE_HOST.test(new URL(value).hostname);
18995
18998
  }, `${field2} must be a public host`).refine((value) => {
@@ -19386,8 +19389,7 @@ var PLATFORM_APP_SCOPE_VARIABLE_IDENTIFIER_PREFIX = "appvar-";
19386
19389
  var STORAGE_LINK_BINDING_PREFIX = "QINTO_LINK_";
19387
19390
  var legalUrl = (field2) => {
19388
19391
  return httpsUrl(field2).refine((value) => {
19389
- const host = new URL(value).hostname;
19390
- return host !== "qinto.io" && !host.endsWith(".qinto.io");
19392
+ return !isPlatformHost(new URL(value).hostname);
19391
19393
  }, `${field2} must be the developer's own document, not a Qinto platform URL`);
19392
19394
  };
19393
19395
  var bindingField = external_exports.string().min(1).max(255).regex(BINDING_NAME);
@@ -19560,7 +19562,7 @@ var captureSchema = external_exports.object({
19560
19562
  var endpointSchema = external_exports.object({
19561
19563
  path: external_exports.string().min(1).max(255).regex(ENDPOINT_PATH_PATTERN, "Endpoint paths are absolute; each segment is a literal or a :name parameter"),
19562
19564
  methods: external_exports.array(external_exports.enum(["GET", "POST", "PUT", "PATCH", "DELETE"])).min(1).max(5),
19563
- auth: external_exports.enum(["public", "token"]),
19565
+ auth: external_exports.enum(["public", "token", "visitor"]),
19564
19566
  mode: external_exports.enum(["webhook", "api"])
19565
19567
  }).strict();
19566
19568
  var eventsSchema = external_exports.object({
@@ -19786,6 +19788,22 @@ var validatePipelines = (manifest, ctx) => {
19786
19788
  }
19787
19789
  }
19788
19790
  };
19791
+ var validateVisitorEndpoint = (manifest, ctx, endpoint, index) => {
19792
+ if (endpoint.mode !== "api") {
19793
+ ctx.addIssue({
19794
+ code: "custom",
19795
+ path: ["endpoints", index, "mode"],
19796
+ message: "A visitor endpoint answers one visitor, so its mode must be api"
19797
+ });
19798
+ }
19799
+ if (manifest.browser?.entry === void 0) {
19800
+ ctx.addIssue({
19801
+ code: "custom",
19802
+ path: ["endpoints", index, "auth"],
19803
+ message: "A visitor endpoint is called by the app's own browser code, so it needs a browser entry"
19804
+ });
19805
+ }
19806
+ };
19789
19807
  var validateEndpoints = (manifest, ctx) => {
19790
19808
  const shapes = /* @__PURE__ */ new Map();
19791
19809
  for (const [index, endpoint] of manifest.endpoints.entries()) {
@@ -19811,7 +19829,9 @@ var validateEndpoints = (manifest, ctx) => {
19811
19829
  message: `Endpoint path ${endpoint.path} names the parameter ${repeated} twice`
19812
19830
  });
19813
19831
  }
19814
- if (endpoint.mode === "api" && manifest.install.multiple) {
19832
+ if (endpoint.auth === "visitor") {
19833
+ validateVisitorEndpoint(manifest, ctx, endpoint, index);
19834
+ } else if (endpoint.mode === "api" && manifest.install.multiple) {
19815
19835
  ctx.addIssue({
19816
19836
  code: "custom",
19817
19837
  path: ["endpoints", index, "mode"],
@@ -19966,7 +19986,7 @@ var appRpcContractSchema = external_exports.record(external_exports.string().reg
19966
19986
  }, "The RPC contract exceeds the size cap");
19967
19987
 
19968
19988
  // ../../../libs/app-envelope/src/envelope.ts
19969
- var ENVELOPE_VERSION = 2;
19989
+ var ENVELOPE_VERSION = 3;
19970
19990
  var ENVELOPE_ERROR_CODES = ["invalid_arguments"];
19971
19991
  var MAX_INSTALLS_PER_APP = 15;
19972
19992
  var MAX_EMITS_PER_INSTALL = 10;
@@ -20021,12 +20041,12 @@ var actionContextSchema = external_exports.discriminatedUnion("source", [
20021
20041
  var envelopeRequestSchema = external_exports.object({
20022
20042
  v: external_exports.literal(ENVELOPE_VERSION),
20023
20043
  kind: external_exports.enum(["event", "connect", "transform", "rpc"]),
20024
- site: external_exports.object({ origin: external_exports.string().min(1).max(255) }).strict(),
20025
20044
  app: external_exports.object({ slug: external_exports.string().min(1).max(30), version: external_exports.string().min(1).max(32) }).strict(),
20026
20045
  installs: external_exports.array(installSchema).min(1).max(MAX_INSTALLS_PER_APP),
20027
20046
  user: external_exports.object({
20028
20047
  anonId: external_exports.string().min(1).max(64),
20029
20048
  globalId: external_exports.string().min(1).max(64).nullable(),
20049
+ createdAt: external_exports.number().int().optional(),
20030
20050
  properties: external_exports.record(external_exports.string(), external_exports.unknown()),
20031
20051
  geo: external_exports.record(external_exports.string(), external_exports.string()).optional()
20032
20052
  }).strict().optional(),
@@ -20070,7 +20090,7 @@ var envelopeResponseSchema = external_exports.object({
20070
20090
  }).strict();
20071
20091
 
20072
20092
  // ../../../libs/app-envelope/src/control.ts
20073
- var CONTROL_ENVELOPE_VERSION = 1;
20093
+ var CONTROL_ENVELOPE_VERSION = 2;
20074
20094
  var MAX_CONTROL_BYTES = 256 * 1024;
20075
20095
  var MAX_MIGRATION_CHECKPOINT_BYTES = 16 * 1024;
20076
20096
  var MIGRATION_DATABASE_LINK_CHANGED = "migration_database_link_changed";
@@ -20174,7 +20194,6 @@ var toolSchema2 = external_exports.object({
20174
20194
  var controlEnvelopeSchema = external_exports.object({
20175
20195
  v: external_exports.literal(CONTROL_ENVELOPE_VERSION),
20176
20196
  kind: external_exports.enum(["noop", "lifecycle", "migration", "schedule", "tool"]),
20177
- site: external_exports.object({ origin: external_exports.string().min(1).max(255) }).strict(),
20178
20197
  app: external_exports.object({ slug: external_exports.string().min(1).max(30), version: external_exports.string().min(1).max(32) }).strict(),
20179
20198
  install: external_exports.object({ id: external_exports.string().min(1).max(64), ord: external_exports.number().int().min(1), label: external_exports.string().max(100) }).strict().optional(),
20180
20199
  lifecycle: lifecycleEventSchema.optional(),
@@ -20248,6 +20267,7 @@ var controlResponseSchema = external_exports.object({
20248
20267
  var ENDPOINT_CONTEXT_HEADER = "x-qinto-endpoint-context";
20249
20268
  var ENDPOINT_OUTCOMES_HEADER = "x-qinto-endpoint-outcomes";
20250
20269
  var MAX_ENDPOINT_BODY_BYTES = 1024 * 1024;
20270
+ var MAX_VISITOR_ENDPOINT_BODY_BYTES = 2 * 1024 * 1024;
20251
20271
  var MAX_ENDPOINT_OUTCOMES_BYTES = 64 * 1024;
20252
20272
  var MAX_ENDPOINT_PATH_LENGTH = 16 * 1024;
20253
20273
  var installSchema3 = external_exports.object({ id: external_exports.string().min(1).max(64), ord: external_exports.number().int().min(1), label: external_exports.string().max(100) }).strict();
@@ -20263,12 +20283,14 @@ var endpointContextSchema = external_exports.object({
20263
20283
  method: external_exports.enum(["GET", "POST", "PUT", "PATCH", "DELETE"]),
20264
20284
  mode: external_exports.enum(["webhook", "api"]),
20265
20285
  version: external_exports.string().min(1).max(32),
20266
- site: external_exports.object({ origin: external_exports.string().min(1).max(255) }).strict(),
20267
20286
  geo: external_exports.record(external_exports.string(), external_exports.unknown()).optional(),
20268
- installs: external_exports.array(installSchema3).min(1).max(15)
20287
+ installs: external_exports.array(installSchema3).min(1).max(15),
20288
+ user: external_exports.object({ anonId: external_exports.string().min(1).max(64) }).strict().optional()
20269
20289
  }).strict().refine((context) => {
20270
20290
  return context.mode === "webhook" || context.installs.length === 1;
20271
- }, "An api endpoint carries exactly one install");
20291
+ }, "An api endpoint carries exactly one install").refine((context) => {
20292
+ return context.user === void 0 || context.mode === "api";
20293
+ }, "Only an api endpoint carries a visitor");
20272
20294
  var endpointOutcomesSchema = external_exports.object({
20273
20295
  outcomes: external_exports.array(
20274
20296
  external_exports.object({
@@ -21284,9 +21306,9 @@ var parseVariableMaps = (env) => {
21284
21306
  }
21285
21307
  return maps;
21286
21308
  };
21287
- var contextKindsOf = (env) => {
21309
+ var appContextOf = (env) => {
21288
21310
  const context = JSON.parse(env.APP_CONTEXT);
21289
- return { variableKinds: context.variableKinds ?? {}, appVariableKinds: context.appVariableKinds ?? {} };
21311
+ return { variableKinds: context.variableKinds ?? {}, appVariableKinds: context.appVariableKinds ?? {}, site: context.site };
21290
21312
  };
21291
21313
  var linkedDatabasesOf = (env) => {
21292
21314
  const context = JSON.parse(env.APP_CONTEXT);
@@ -21309,7 +21331,7 @@ var projectAppValues = (env, kinds) => {
21309
21331
  return { appVariables, appSecrets };
21310
21332
  };
21311
21333
  var secretValues = (env) => {
21312
- const { variableKinds, appVariableKinds } = contextKindsOf(env);
21334
+ const { variableKinds, appVariableKinds } = appContextOf(env);
21313
21335
  const values = /* @__PURE__ */ new Set();
21314
21336
  for (const [name, byOrd] of parseVariableMaps(env)) {
21315
21337
  if (variableKinds[name] !== "secret") {
@@ -21496,7 +21518,7 @@ var readStamp = (payload) => {
21496
21518
  return { q: stamp, payload: params?.payload };
21497
21519
  };
21498
21520
  var buildWorkflowContext = (env, stamp) => {
21499
- const { variableKinds, appVariableKinds } = contextKindsOf(env);
21521
+ const { variableKinds, appVariableKinds } = appContextOf(env);
21500
21522
  const { variables, secrets } = projectInstallValues(parseVariableMaps(env), variableKinds, stamp.ord);
21501
21523
  const { appVariables, appSecrets } = projectAppValues(env, appVariableKinds);
21502
21524
  const install = { id: stamp.installId, label: stamp.installLabel };
@@ -21567,6 +21589,7 @@ var createWorkflow = (className, bundle) => {
21567
21589
  var buildContext = ({
21568
21590
  env,
21569
21591
  envelope,
21592
+ site,
21570
21593
  install,
21571
21594
  maps,
21572
21595
  kinds,
@@ -21580,7 +21603,7 @@ var buildContext = ({
21580
21603
  const subject = envelope.user?.anonId ?? null;
21581
21604
  return {
21582
21605
  env,
21583
- site: envelope.site,
21606
+ site,
21584
21607
  install: { id: install.id, label: install.label },
21585
21608
  startWorkflow: buildStartWorkflow({
21586
21609
  ord: install.ord,
@@ -21744,7 +21767,7 @@ var dispatchSchedule = async (envelope, bundle, env) => {
21744
21767
  error: { message: `missing handler: schedules.${schedule.id}` }
21745
21768
  });
21746
21769
  }
21747
- const { variableKinds, appVariableKinds } = contextKindsOf(env);
21770
+ const { variableKinds, appVariableKinds, site } = appContextOf(env);
21748
21771
  const maps = parseVariableMaps(env);
21749
21772
  const appScope = projectAppValues(env, appVariableKinds);
21750
21773
  const event = { id: schedule.id, cron: schedule.cron, scheduledTime: new Date(schedule.scheduledTime) };
@@ -21753,7 +21776,7 @@ var dispatchSchedule = async (envelope, bundle, env) => {
21753
21776
  const { variables, secrets } = projectInstallValues(maps, variableKinds, install.ord);
21754
21777
  const context = {
21755
21778
  env,
21756
- site: envelope.site,
21779
+ site,
21757
21780
  install: { id: install.id, label: install.label },
21758
21781
  startWorkflow: buildStartWorkflow({
21759
21782
  ord: install.ord,
@@ -21876,13 +21899,13 @@ var checkResult = (result) => {
21876
21899
  };
21877
21900
  var buildContext2 = (envelope, env) => {
21878
21901
  const install = envelope.install;
21879
- const { variableKinds, appVariableKinds } = contextKindsOf(env);
21902
+ const { variableKinds, appVariableKinds, site } = appContextOf(env);
21880
21903
  const maps = parseVariableMaps(env);
21881
21904
  const appScope = projectAppValues(env, appVariableKinds);
21882
21905
  const { variables, secrets } = projectInstallValues(maps, variableKinds, install.ord);
21883
21906
  return {
21884
21907
  env,
21885
- site: envelope.site,
21908
+ site,
21886
21909
  install: { id: install.id, label: install.label },
21887
21910
  viewer: envelope.tool.viewer,
21888
21911
  callId: envelope.tool.callId,
@@ -21946,20 +21969,21 @@ var controlError = (status, message) => {
21946
21969
  return json2(status, { v: CONTROL_ENVELOPE_VERSION, ok: false, error: { message } });
21947
21970
  };
21948
21971
  var controlContextValues = (env) => {
21949
- const { variableKinds, appVariableKinds } = contextKindsOf(env);
21972
+ const { variableKinds, appVariableKinds, site } = appContextOf(env);
21950
21973
  return {
21951
21974
  maps: parseVariableMaps(env),
21952
21975
  variableKinds,
21976
+ site,
21953
21977
  appScope: projectAppValues(env, appVariableKinds)
21954
21978
  };
21955
21979
  };
21956
21980
  var lifecycleContext = (env, envelope) => {
21957
21981
  const install = envelope.install;
21958
- const { maps, variableKinds, appScope } = controlContextValues(env);
21982
+ const { maps, variableKinds, site, appScope } = controlContextValues(env);
21959
21983
  const { variables, secrets } = projectInstallValues(maps, variableKinds, install.ord);
21960
21984
  return {
21961
21985
  env,
21962
- site: envelope.site,
21986
+ site,
21963
21987
  install: { id: install.id, label: install.label },
21964
21988
  variables,
21965
21989
  secrets,
@@ -21974,11 +21998,11 @@ var lifecycleContext = (env, envelope) => {
21974
21998
  observability: buildObservability(install.ord)
21975
21999
  };
21976
22000
  };
21977
- var migrationContext = (env, envelope) => {
21978
- const { appScope } = controlContextValues(env);
22001
+ var migrationContext = (env) => {
22002
+ const { site, appScope } = controlContextValues(env);
21979
22003
  return {
21980
22004
  env,
21981
- site: envelope.site,
22005
+ site,
21982
22006
  appVariables: appScope.appVariables,
21983
22007
  appSecrets: appScope.appSecrets,
21984
22008
  // A migration runs once for the site, not once per install, so it has no install to attribute
@@ -22034,10 +22058,7 @@ var dispatchMigration = async (envelope, bundle, env) => {
22034
22058
  if (typeof handler !== "function") {
22035
22059
  throw new Error(`missing migration handler: ${migration.handler}`);
22036
22060
  }
22037
- const result = await handler(
22038
- { id: migration.id, checkpoint: migration.checkpoint },
22039
- migrationContext(env, envelope)
22040
- );
22061
+ const result = await handler({ id: migration.id, checkpoint: migration.checkpoint }, migrationContext(env));
22041
22062
  if (result.done !== true && result.done !== false) {
22042
22063
  throw new Error("migration handler returned no completion result");
22043
22064
  }
@@ -22126,7 +22147,8 @@ var buildContext3 = ({
22126
22147
  install,
22127
22148
  site,
22128
22149
  geo,
22129
- params
22150
+ params,
22151
+ user
22130
22152
  }) => {
22131
22153
  const { variables, secrets } = projectInstallValues(maps, kinds, install.ord);
22132
22154
  return {
@@ -22135,9 +22157,13 @@ var buildContext3 = ({
22135
22157
  geo,
22136
22158
  params,
22137
22159
  install: { id: install.id, label: install.label },
22138
- // An endpoint has no visitor, so a workflow it starts cannot push or touch context. `push` and
22139
- // `context` below are the exceptions: they name their subject rather than inheriting one.
22140
- startWorkflow: buildStartWorkflow({ ord: install.ord, installId: install.id, installLabel: install.label, anonId: null }),
22160
+ ...user === void 0 ? {} : { user: { anonId: user.anonId, globalId: null, properties: {} } },
22161
+ startWorkflow: buildStartWorkflow({
22162
+ ord: install.ord,
22163
+ installId: install.id,
22164
+ installLabel: install.label,
22165
+ anonId: user?.anonId ?? null
22166
+ }),
22141
22167
  oauth: buildOauth(env, install.ord),
22142
22168
  variables,
22143
22169
  secrets,
@@ -22203,6 +22229,21 @@ var runWebhook = async (invoke, installs) => {
22203
22229
  }
22204
22230
  return Response.json({ outcomes }, { headers: { [ENDPOINT_OUTCOMES_HEADER]: "1" } });
22205
22231
  };
22232
+ var endpointHandler = (bundle, context) => {
22233
+ const endpoints = bundle?.endpoints;
22234
+ const candidate = endpoints !== void 0 && Object.hasOwn(endpoints, context.route) ? endpoints[context.route] : void 0;
22235
+ if (typeof candidate === "function") {
22236
+ return candidate;
22237
+ }
22238
+ const visitor = typeof candidate === "object" && candidate !== null ? candidate.__qintoVisitorEndpoint : void 0;
22239
+ if (typeof visitor !== "function") {
22240
+ return Response.json({ error: "not_found" }, { status: 404 });
22241
+ }
22242
+ if (context.user === void 0) {
22243
+ return Response.json({ error: "invalid_context" }, { status: 400 });
22244
+ }
22245
+ return visitor;
22246
+ };
22206
22247
  var dispatchEndpoint = async ({ request, env, versions }) => {
22207
22248
  const context = parseContext(request.headers.get(ENDPOINT_CONTEXT_HEADER));
22208
22249
  if (context === null) {
@@ -22211,22 +22252,29 @@ var dispatchEndpoint = async ({ request, env, versions }) => {
22211
22252
  if (!(context.version in versions)) {
22212
22253
  return Response.json({ error: "unknown version" }, { status: 404 });
22213
22254
  }
22214
- const bundle = versions[context.version];
22215
- const endpoints = bundle?.endpoints;
22216
- const candidate = endpoints !== void 0 && Object.hasOwn(endpoints, context.route) ? endpoints[context.route] : void 0;
22217
- if (typeof candidate !== "function") {
22218
- return Response.json({ error: "not_found" }, { status: 404 });
22255
+ const handler = endpointHandler(versions[context.version], context);
22256
+ if (handler instanceof Response) {
22257
+ return handler;
22219
22258
  }
22220
- const handler = candidate;
22221
22259
  const body = await request.arrayBuffer();
22222
22260
  const maps = parseVariableMaps(env);
22223
- const { variableKinds, appVariableKinds } = contextKindsOf(env);
22261
+ const { variableKinds, appVariableKinds, site } = appContextOf(env);
22224
22262
  const appScope = projectAppValues(env, appVariableKinds);
22225
22263
  const invoke = async (install) => {
22226
22264
  return installSpan(install, () => {
22227
22265
  return handler(
22228
22266
  handlerRequest(request, context, body),
22229
- buildContext3({ env, maps, kinds: variableKinds, appScope, install, site: context.site, geo: context.geo, params: context.params })
22267
+ buildContext3({
22268
+ env,
22269
+ maps,
22270
+ kinds: variableKinds,
22271
+ appScope,
22272
+ install,
22273
+ site,
22274
+ geo: context.geo,
22275
+ params: context.params,
22276
+ user: context.user
22277
+ })
22230
22278
  );
22231
22279
  });
22232
22280
  };
@@ -22514,12 +22562,13 @@ var dispatchUi = async ({ request, env, versions }) => {
22514
22562
  if (handler === void 0) {
22515
22563
  return Response.json({ error: "not_found" }, { status: 404 });
22516
22564
  }
22517
- const { variableKinds, appVariableKinds } = contextKindsOf(env);
22565
+ const { variableKinds, appVariableKinds, site } = appContextOf(env);
22518
22566
  const maps = parseVariableMaps(env);
22519
22567
  const { variables, secrets } = projectInstallValues(maps, variableKinds, context.install.ord);
22520
22568
  const { appVariables, appSecrets } = projectAppValues(env, appVariableKinds);
22521
22569
  const ctx = {
22522
22570
  env,
22571
+ site,
22523
22572
  install: { id: context.install.id, label: context.install.label },
22524
22573
  installs: projectAllInstallValues(maps, variableKinds, context.installs),
22525
22574
  // The install is named rather than inherited: one panel serves every install, and reading the
@@ -22599,7 +22648,7 @@ var projectAction = (action, installId) => {
22599
22648
  };
22600
22649
  var runInstalls = async (envelope, env, invoke) => {
22601
22650
  const maps = parseVariableMaps(env);
22602
- const { variableKinds: kinds, appVariableKinds } = contextKindsOf(env);
22651
+ const { variableKinds: kinds, appVariableKinds, site } = appContextOf(env);
22603
22652
  const appScope = projectAppValues(env, appVariableKinds);
22604
22653
  const groups = [];
22605
22654
  let failure2;
@@ -22608,7 +22657,7 @@ var runInstalls = async (envelope, env, invoke) => {
22608
22657
  const pushes = [];
22609
22658
  const captures = [];
22610
22659
  const context = contextCollector();
22611
- const ctx = buildContext({ env, envelope, install, maps, kinds, appScope, emits, pushes, captures, context });
22660
+ const ctx = buildContext({ env, envelope, site, install, maps, kinds, appScope, emits, pushes, captures, context });
22612
22661
  try {
22613
22662
  await installSpan(install, () => {
22614
22663
  return invoke(ctx, install);
@@ -22656,11 +22705,12 @@ var runTransform = async (envelope, env, action, handler) => {
22656
22705
  const captures = [];
22657
22706
  const context = contextCollector();
22658
22707
  const maps = parseVariableMaps(env);
22659
- const { variableKinds: kinds, appVariableKinds } = contextKindsOf(env);
22708
+ const { variableKinds: kinds, appVariableKinds, site } = appContextOf(env);
22660
22709
  const appScope = projectAppValues(env, appVariableKinds);
22661
22710
  const { apps: _apps, ...withoutApps } = buildContext({
22662
22711
  env,
22663
22712
  envelope,
22713
+ site,
22664
22714
  install,
22665
22715
  maps,
22666
22716
  kinds,
@@ -22742,11 +22792,11 @@ var dispatchRpc = async (envelope, bundle, env) => {
22742
22792
  const captures = [];
22743
22793
  const context = contextCollector();
22744
22794
  const maps = parseVariableMaps(env);
22745
- const { variableKinds: kinds, appVariableKinds } = contextKindsOf(env);
22795
+ const { variableKinds: kinds, appVariableKinds, site } = appContextOf(env);
22746
22796
  const appScope = projectAppValues(env, appVariableKinds);
22747
22797
  const subject = envelope.user?.anonId ?? null;
22748
22798
  const ctx = {
22749
- ...buildContext({ env, envelope, install, maps, kinds, appScope, emits, pushes, captures, context }),
22799
+ ...buildContext({ env, envelope, site, install, maps, kinds, appScope, emits, pushes, captures, context }),
22750
22800
  context: fetchedContext(
22751
22801
  env,
22752
22802
  (what) => {