@blotout/qinto-cli 0.1.20 → 0.1.22

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.
@@ -4,6 +4,10 @@ var __export = (target, all) => {
4
4
  __defProp(target, name, { get: all[name], enumerable: true });
5
5
  };
6
6
 
7
+ // ../../../libs/app-manifest/src/app-roles.ts
8
+ var DECLARABLE_APP_ROLES = ["owner", "admin", "manager", "editor", "member", "viewer"];
9
+ var APP_ROLES = ["full", ...DECLARABLE_APP_ROLES];
10
+
7
11
  // ../../../libs/app-manifest/src/cron.ts
8
12
  var MAX_CRON_LENGTH = 128;
9
13
  var MINUTE_LITERAL = /^([0-9]|[1-5][0-9])$/;
@@ -18947,6 +18951,10 @@ var VARIABLE_NAME = /^[A-Z][A-Z0-9_]*$/;
18947
18951
  var APP_SLUG_PATTERN = /^[a-z][a-z0-9-]{2,29}$/;
18948
18952
  var FUNCTION_NAME = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
18949
18953
  var identifierField = external_exports.string().min(1).max(64).regex(IDENTIFIER);
18954
+ var RENDERABLE_TEXT = /^[^\u0000-\u0009\u000B-\u001F\u007F\u200B-\u200F\u202A-\u202E\u2066-\u2069\uFEFF]*$/;
18955
+ var renderableText = (min, max) => {
18956
+ return external_exports.string().min(min).max(max).regex(RENDERABLE_TEXT, "must not carry control or bidirectional-override characters");
18957
+ };
18950
18958
  var httpsUrl = (field2) => {
18951
18959
  return external_exports.url().max(2048).refine((value) => value.startsWith("https://"), `${field2} must be an HTTPS URL`);
18952
18960
  };
@@ -19082,6 +19090,35 @@ var validateOauth = (input2, ctx) => {
19082
19090
  }
19083
19091
  };
19084
19092
 
19093
+ // ../../../libs/app-manifest/src/roles.ts
19094
+ var MAX_APP_ROLE_DESCRIPTION = 200;
19095
+ var roleSchema = external_exports.object({
19096
+ key: external_exports.enum(DECLARABLE_APP_ROLES, {
19097
+ error: (issue2) => {
19098
+ return issue2.input === "full" ? "full access is always available and is not declared" : void 0;
19099
+ }
19100
+ }),
19101
+ description: renderableText(1, MAX_APP_ROLE_DESCRIPTION).optional()
19102
+ }).strict();
19103
+ var rolesSchema = external_exports.array(roleSchema).max(DECLARABLE_APP_ROLES.length).superRefine((roles, ctx) => {
19104
+ uniqueOrIssue(
19105
+ ctx,
19106
+ roles.map((role) => role.key),
19107
+ [],
19108
+ "role"
19109
+ );
19110
+ }).transform((roles) => {
19111
+ return [...roles].sort((a, b) => APP_ROLES.indexOf(a.key) - APP_ROLES.indexOf(b.key));
19112
+ });
19113
+ var validateRoles = (manifest, ctx) => {
19114
+ const declared = /* @__PURE__ */ new Set(["full", ...(manifest.roles ?? []).map((role) => role.key)]);
19115
+ for (const [index, tool] of manifest.tools.entries()) {
19116
+ if (tool.role !== void 0 && !declared.has(tool.role)) {
19117
+ ctx.addIssue({ code: "custom", path: ["tools", index, "role"], message: `Tool role ${tool.role} is not declared in roles` });
19118
+ }
19119
+ }
19120
+ };
19121
+
19085
19122
  // ../../../libs/app-manifest/src/route.ts
19086
19123
  var ENDPOINT_PATH_PATTERN = /^\/(?:(?::[a-zA-Z][a-zA-Z0-9_]*|[a-zA-Z0-9_-]+)(?:\/(?::[a-zA-Z][a-zA-Z0-9_]*|[a-zA-Z0-9_-]+))*)?$/;
19087
19124
  var isParam = (segment) => {
@@ -19115,10 +19152,6 @@ var MAX_MANIFEST_TOOLS_BYTES = 150 * 1024;
19115
19152
  var TOOL_PROPERTY_NAME = /^[a-zA-Z][a-zA-Z0-9_]*$/;
19116
19153
  var RESERVED_TOOL_ARGUMENTS = ["teamId", "siteId", "installId"];
19117
19154
  var TOOL_STRING_FORMATS = ["uuid", "date", "date-time", "email", "uri"];
19118
- var RENDERABLE_TEXT = /^[^\u0000-\u0009\u000B-\u001F\u007F\u200B-\u200F\u202A-\u202E\u2066-\u2069\uFEFF]*$/;
19119
- var renderableText = (min, max) => {
19120
- return external_exports.string().min(min).max(max).regex(RENDERABLE_TEXT, "must not carry control or bidirectional-override characters");
19121
- };
19122
19155
  var propertyName = external_exports.string().min(1).max(48).regex(TOOL_PROPERTY_NAME);
19123
19156
  var FORMAT_SCHEMAS = {
19124
19157
  uuid: external_exports.uuid(),
@@ -19214,7 +19247,8 @@ var toolSchema = external_exports.object({
19214
19247
  title: renderableText(1, MAX_APP_TOOL_TITLE_LENGTH),
19215
19248
  description: renderableText(MIN_APP_TOOL_DESCRIPTION, MAX_APP_TOOL_DESCRIPTION),
19216
19249
  inputSchema: toolInputSchema,
19217
- annotations: toolAnnotationsSchema
19250
+ annotations: toolAnnotationsSchema,
19251
+ role: external_exports.enum(APP_ROLES).optional()
19218
19252
  }).strict();
19219
19253
  var nodeChildren = (value) => {
19220
19254
  const properties = value["properties"];
@@ -19618,6 +19652,9 @@ var baseSchema = external_exports.object({
19618
19652
  description: "The push topics this app broadcasts to every app on the site. Requires the `sharedContext` data capability; a topic left out reaches only this app\u2019s own browser code."
19619
19653
  }),
19620
19654
  endpoints: external_exports.array(endpointSchema).max(16).default([]).meta({ description: "The HTTP routes served at https://<site>/app/<slug><path>." }),
19655
+ roles: rolesSchema.optional().meta({
19656
+ description: "The app roles this app uses, from the fixed list owner, admin, manager, editor, member, viewer. Full access is always available and is not declared. A team member is given one app role per app."
19657
+ }),
19621
19658
  tools: toolsSchema.meta({
19622
19659
  description: "The MCP tools this app serves to AI assistants, published as `<slug>_<name>`. Each one a site manager accepts becomes callable on their behalf by an assistant."
19623
19660
  }),
@@ -19974,6 +20011,7 @@ var appManifestSchema = baseSchema.superRefine((manifest, ctx) => {
19974
20011
  validateOauth(manifest, ctx);
19975
20012
  validateServer(manifest, ctx);
19976
20013
  validateTools(manifest.tools, ctx);
20014
+ validateRoles(manifest, ctx);
19977
20015
  });
19978
20016
 
19979
20017
  // ../../../libs/app-manifest/src/oauth-flow.ts
@@ -20026,9 +20064,10 @@ var effectGroupSchema = external_exports.object({
20026
20064
  context: external_exports.array(contextWriteSchema).optional()
20027
20065
  }).strict();
20028
20066
  var captureValueSchema = external_exports.object({ value: external_exports.string().max(512), createdAt: external_exports.number().int(), updatedAt: external_exports.number().int(), type: external_exports.enum(CAPTURE_TYPES) }).strict();
20067
+ var pageSchema = external_exports.object({ url: external_exports.string().min(1).max(4096), referrer: external_exports.string().min(1).max(4096).optional() }).strict();
20029
20068
  var actionContextFields = {
20030
20069
  occurredAt: external_exports.number().int().nonnegative().safe(),
20031
- page: external_exports.object({ url: external_exports.string().min(1).max(4096), referrer: external_exports.string().min(1).max(4096).optional() }).strict().optional(),
20070
+ page: pageSchema.optional(),
20032
20071
  network: external_exports.object({
20033
20072
  ip: external_exports.string().min(1).max(64).optional(),
20034
20073
  userAgent: external_exports.string().min(1).max(512).optional(),
@@ -20056,6 +20095,8 @@ var envelopeRequestSchema = external_exports.object({
20056
20095
  }).strict().optional(),
20057
20096
  consent: external_exports.object({ enabled: external_exports.boolean(), categories: external_exports.record(external_exports.string(), external_exports.boolean()), apps: external_exports.record(external_exports.string(), external_exports.boolean()) }).strict().optional(),
20058
20097
  geo: external_exports.record(external_exports.string(), external_exports.unknown()).optional(),
20098
+ // Connect envelopes only: the page the visitor's socket opened from.
20099
+ page: pageSchema.optional(),
20059
20100
  // Only what this app captured or wrote for this visitor; `updatedAt` is when the current value
20060
20101
  // was first seen, which is the click time a CAPI `fbc` is built from.
20061
20102
  captures: external_exports.record(external_exports.string().max(64), captureValueSchema).optional(),
@@ -20185,7 +20226,12 @@ var toolSchema2 = external_exports.object({
20185
20226
  name: external_exports.string().min(1).max(MAX_APP_TOOL_NAME_LENGTH).regex(APP_TOOL_NAME_PATTERN),
20186
20227
  // Who asked, and what they may do on this site. Derived from the bearer by the portal, never
20187
20228
  // from the model's arguments.
20188
- viewer: external_exports.object({ userId: external_exports.string().min(1).max(64), access: external_exports.enum(["read", "write"]) }).strict(),
20229
+ viewer: external_exports.object({
20230
+ userId: external_exports.string().min(1).max(64),
20231
+ access: external_exports.enum(["read", "write"]),
20232
+ // Optional only while a site worker or app runtime that predates it can still receive this envelope; absent means `full`.
20233
+ appRole: external_exports.enum(APP_ROLES).optional()
20234
+ }).strict(),
20189
20235
  // Already validated against the tool's declared inputSchema, with the reserved routing names
20190
20236
  // stripped. Every declared input schema has an object root, so this is an object too — and a
20191
20237
  // call that names no arguments normalizes to `{}` rather than reaching the handler as undefined.
@@ -20413,7 +20459,12 @@ var appUiAnalyticsQueryPath = (domainId, appSlug2, resourceIdentifier) => {
20413
20459
  var uiInstallSchema = external_exports.object({ id: external_exports.string().min(1).max(64), ord: external_exports.number().int().min(1), label: external_exports.string().max(100), enabled: external_exports.boolean() }).strict();
20414
20460
  var uiContextSchema = external_exports.object({
20415
20461
  version: external_exports.string().min(1).max(32),
20416
- viewer: external_exports.object({ userId: external_exports.string().min(1).max(64), access: external_exports.enum(["read", "write"]) }).strict(),
20462
+ viewer: external_exports.object({
20463
+ userId: external_exports.string().min(1).max(64),
20464
+ access: external_exports.enum(["read", "write"]),
20465
+ // Optional only while a site worker that predates it can still send this header; absent means `full`.
20466
+ appRole: external_exports.enum(APP_ROLES).optional()
20467
+ }).strict(),
20417
20468
  install: uiInstallSchema,
20418
20469
  installs: external_exports.array(uiInstallSchema).min(1).max(MAX_INSTALLS_PER_APP),
20419
20470
  writeTicket: external_exports.string().min(1).max(2048).optional()
@@ -21938,7 +21989,8 @@ var buildContext2 = (envelope, env) => {
21938
21989
  env,
21939
21990
  site,
21940
21991
  install: { id: install.id, label: install.label },
21941
- viewer: envelope.tool.viewer,
21992
+ // An envelope from a portal that predates the role, or one carrying `full`, has no `appRole`.
21993
+ viewer: { ...envelope.tool.viewer, appRole: envelope.tool.viewer.appRole ?? "full" },
21942
21994
  callId: envelope.tool.callId,
21943
21995
  startWorkflow: buildStartWorkflow({ ord: install.ord, installId: install.id, installLabel: install.label, anonId: null }),
21944
21996
  oauth: buildOauth(env, install.ord),
@@ -22621,7 +22673,8 @@ var dispatchUi = async ({ request, env, versions }) => {
22621
22673
  secrets,
22622
22674
  appVariables,
22623
22675
  appSecrets,
22624
- viewer: context.viewer,
22676
+ // A site worker that predates app roles sends none, and every member had full access then.
22677
+ viewer: { ...context.viewer, appRole: context.viewer.appRole ?? "full" },
22625
22678
  observability: buildObservability(context.install.ord),
22626
22679
  identity: buildIdentity(env),
22627
22680
  apps: buildAppsClient(env, { depth: 0 })
@@ -22889,7 +22942,7 @@ var dispatch = async (envelope, versions, env) => {
22889
22942
  if (handler === void 0) {
22890
22943
  return jsonError(200, "missing handler: onConnect");
22891
22944
  }
22892
- return runInstalls(envelope, env, (ctx) => handler(ctx));
22945
+ return runInstalls(envelope, env, (ctx) => handler({ ...ctx, ...envelope.page === void 0 ? {} : { page: envelope.page } }));
22893
22946
  }
22894
22947
  case "transform": {
22895
22948
  return dispatchTransform(envelope, bundle, env);