@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.
- package/README.md +11 -1
- package/dist/index.js +3801 -3716
- package/dist/index.js.map +1 -1
- package/dist/worker-artifact/app-runtime/index.js +64 -11
- package/dist/worker-artifact/main/index.js +229 -135
- package/dist/worker-artifact/version.json +6 -6
- package/package.json +3 -3
- package/templates/app/full/qinto.app.jsonc +0 -129
- package/templates/app/full/src/browser.ts +0 -15
- package/templates/app/full/src/server.ts +0 -133
- package/templates/app/full/ui/src/pages/index.astro +0 -53
- package/templates/app/minimal/qinto.app.jsonc +0 -20
- package/templates/app/minimal/src/server.ts +0 -9
- package/templates/project/gitignore +0 -3
- package/templates/project/package.json +0 -13
- package/templates/project/tsconfig.json +0 -12
- package/templates/ui/astro.config.mjs +0 -6
- package/templates/ui/package.json +0 -12
- package/templates/ui/src/pages/index.astro +0 -50
|
@@ -790,6 +790,10 @@ var deriveVisitorSignature = /* @__PURE__ */ __name(async (masterBase64, domainI
|
|
|
790
790
|
return hmacHex(masterBase64, `${domainId}#visitor#${anonId}`);
|
|
791
791
|
}, "deriveVisitorSignature");
|
|
792
792
|
|
|
793
|
+
// ../../libs/app-manifest/src/app-roles.ts
|
|
794
|
+
var DECLARABLE_APP_ROLES = ["owner", "admin", "manager", "editor", "member", "viewer"];
|
|
795
|
+
var APP_ROLES = ["full", ...DECLARABLE_APP_ROLES];
|
|
796
|
+
|
|
793
797
|
// ../../libs/app-manifest/src/cron.ts
|
|
794
798
|
var MAX_CRON_LENGTH = 128;
|
|
795
799
|
var MINUTE_LITERAL = /^([0-9]|[1-5][0-9])$/;
|
|
@@ -20348,6 +20352,10 @@ var VARIABLE_NAME = /^[A-Z][A-Z0-9_]*$/;
|
|
|
20348
20352
|
var APP_SLUG_PATTERN = /^[a-z][a-z0-9-]{2,29}$/;
|
|
20349
20353
|
var FUNCTION_NAME = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
|
|
20350
20354
|
var identifierField = external_exports.string().min(1).max(64).regex(IDENTIFIER);
|
|
20355
|
+
var RENDERABLE_TEXT = /^[^\u0000-\u0009\u000B-\u001F\u007F\u200B-\u200F\u202A-\u202E\u2066-\u2069\uFEFF]*$/;
|
|
20356
|
+
var renderableText = /* @__PURE__ */ __name((min, max) => {
|
|
20357
|
+
return external_exports.string().min(min).max(max).regex(RENDERABLE_TEXT, "must not carry control or bidirectional-override characters");
|
|
20358
|
+
}, "renderableText");
|
|
20351
20359
|
var httpsUrl = /* @__PURE__ */ __name((field) => {
|
|
20352
20360
|
return external_exports.url().max(2048).refine((value) => value.startsWith("https://"), `${field} must be an HTTPS URL`);
|
|
20353
20361
|
}, "httpsUrl");
|
|
@@ -20483,6 +20491,35 @@ var validateOauth = /* @__PURE__ */ __name((input2, ctx) => {
|
|
|
20483
20491
|
}
|
|
20484
20492
|
}, "validateOauth");
|
|
20485
20493
|
|
|
20494
|
+
// ../../libs/app-manifest/src/roles.ts
|
|
20495
|
+
var MAX_APP_ROLE_DESCRIPTION = 200;
|
|
20496
|
+
var roleSchema = external_exports.object({
|
|
20497
|
+
key: external_exports.enum(DECLARABLE_APP_ROLES, {
|
|
20498
|
+
error: /* @__PURE__ */ __name((issue2) => {
|
|
20499
|
+
return issue2.input === "full" ? "full access is always available and is not declared" : void 0;
|
|
20500
|
+
}, "error")
|
|
20501
|
+
}),
|
|
20502
|
+
description: renderableText(1, MAX_APP_ROLE_DESCRIPTION).optional()
|
|
20503
|
+
}).strict();
|
|
20504
|
+
var rolesSchema = external_exports.array(roleSchema).max(DECLARABLE_APP_ROLES.length).superRefine((roles, ctx) => {
|
|
20505
|
+
uniqueOrIssue(
|
|
20506
|
+
ctx,
|
|
20507
|
+
roles.map((role) => role.key),
|
|
20508
|
+
[],
|
|
20509
|
+
"role"
|
|
20510
|
+
);
|
|
20511
|
+
}).transform((roles) => {
|
|
20512
|
+
return [...roles].sort((a, b) => APP_ROLES.indexOf(a.key) - APP_ROLES.indexOf(b.key));
|
|
20513
|
+
});
|
|
20514
|
+
var validateRoles = /* @__PURE__ */ __name((manifest, ctx) => {
|
|
20515
|
+
const declared = /* @__PURE__ */ new Set(["full", ...(manifest.roles ?? []).map((role) => role.key)]);
|
|
20516
|
+
for (const [index, tool] of manifest.tools.entries()) {
|
|
20517
|
+
if (tool.role !== void 0 && !declared.has(tool.role)) {
|
|
20518
|
+
ctx.addIssue({ code: "custom", path: ["tools", index, "role"], message: `Tool role ${tool.role} is not declared in roles` });
|
|
20519
|
+
}
|
|
20520
|
+
}
|
|
20521
|
+
}, "validateRoles");
|
|
20522
|
+
|
|
20486
20523
|
// ../../libs/app-manifest/src/route.ts
|
|
20487
20524
|
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_-]+))*)?$/;
|
|
20488
20525
|
var isParam = /* @__PURE__ */ __name((segment) => {
|
|
@@ -20579,10 +20616,6 @@ var MAX_MANIFEST_TOOLS_BYTES = 150 * 1024;
|
|
|
20579
20616
|
var TOOL_PROPERTY_NAME = /^[a-zA-Z][a-zA-Z0-9_]*$/;
|
|
20580
20617
|
var RESERVED_TOOL_ARGUMENTS = ["teamId", "siteId", "installId"];
|
|
20581
20618
|
var TOOL_STRING_FORMATS = ["uuid", "date", "date-time", "email", "uri"];
|
|
20582
|
-
var RENDERABLE_TEXT = /^[^\u0000-\u0009\u000B-\u001F\u007F\u200B-\u200F\u202A-\u202E\u2066-\u2069\uFEFF]*$/;
|
|
20583
|
-
var renderableText = /* @__PURE__ */ __name((min, max) => {
|
|
20584
|
-
return external_exports.string().min(min).max(max).regex(RENDERABLE_TEXT, "must not carry control or bidirectional-override characters");
|
|
20585
|
-
}, "renderableText");
|
|
20586
20619
|
var propertyName = external_exports.string().min(1).max(48).regex(TOOL_PROPERTY_NAME);
|
|
20587
20620
|
var FORMAT_SCHEMAS = {
|
|
20588
20621
|
uuid: external_exports.uuid(),
|
|
@@ -20678,7 +20711,8 @@ var toolSchema = external_exports.object({
|
|
|
20678
20711
|
title: renderableText(1, MAX_APP_TOOL_TITLE_LENGTH),
|
|
20679
20712
|
description: renderableText(MIN_APP_TOOL_DESCRIPTION, MAX_APP_TOOL_DESCRIPTION),
|
|
20680
20713
|
inputSchema: toolInputSchema,
|
|
20681
|
-
annotations: toolAnnotationsSchema
|
|
20714
|
+
annotations: toolAnnotationsSchema,
|
|
20715
|
+
role: external_exports.enum(APP_ROLES).optional()
|
|
20682
20716
|
}).strict();
|
|
20683
20717
|
var nodeChildren = /* @__PURE__ */ __name((value) => {
|
|
20684
20718
|
const properties2 = value["properties"];
|
|
@@ -21082,6 +21116,9 @@ var baseSchema = external_exports.object({
|
|
|
21082
21116
|
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."
|
|
21083
21117
|
}),
|
|
21084
21118
|
endpoints: external_exports.array(endpointSchema).max(16).default([]).meta({ description: "The HTTP routes served at https://<site>/app/<slug><path>." }),
|
|
21119
|
+
roles: rolesSchema.optional().meta({
|
|
21120
|
+
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."
|
|
21121
|
+
}),
|
|
21085
21122
|
tools: toolsSchema.meta({
|
|
21086
21123
|
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."
|
|
21087
21124
|
}),
|
|
@@ -21438,6 +21475,7 @@ var appManifestSchema = baseSchema.superRefine((manifest, ctx) => {
|
|
|
21438
21475
|
validateOauth(manifest, ctx);
|
|
21439
21476
|
validateServer(manifest, ctx);
|
|
21440
21477
|
validateTools(manifest.tools, ctx);
|
|
21478
|
+
validateRoles(manifest, ctx);
|
|
21441
21479
|
});
|
|
21442
21480
|
|
|
21443
21481
|
// ../../libs/app-manifest/src/oauth-flow.ts
|
|
@@ -21500,9 +21538,10 @@ var effectGroupSchema = external_exports.object({
|
|
|
21500
21538
|
context: external_exports.array(contextWriteSchema).optional()
|
|
21501
21539
|
}).strict();
|
|
21502
21540
|
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();
|
|
21541
|
+
var pageSchema = external_exports.object({ url: external_exports.string().min(1).max(4096), referrer: external_exports.string().min(1).max(4096).optional() }).strict();
|
|
21503
21542
|
var actionContextFields = {
|
|
21504
21543
|
occurredAt: external_exports.number().int().nonnegative().safe(),
|
|
21505
|
-
page:
|
|
21544
|
+
page: pageSchema.optional(),
|
|
21506
21545
|
network: external_exports.object({
|
|
21507
21546
|
ip: external_exports.string().min(1).max(64).optional(),
|
|
21508
21547
|
userAgent: external_exports.string().min(1).max(512).optional(),
|
|
@@ -21530,6 +21569,8 @@ var envelopeRequestSchema = external_exports.object({
|
|
|
21530
21569
|
}).strict().optional(),
|
|
21531
21570
|
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(),
|
|
21532
21571
|
geo: external_exports.record(external_exports.string(), external_exports.unknown()).optional(),
|
|
21572
|
+
// Connect envelopes only: the page the visitor's socket opened from.
|
|
21573
|
+
page: pageSchema.optional(),
|
|
21533
21574
|
// Only what this app captured or wrote for this visitor; `updatedAt` is when the current value
|
|
21534
21575
|
// was first seen, which is the click time a CAPI `fbc` is built from.
|
|
21535
21576
|
captures: external_exports.record(external_exports.string().max(64), captureValueSchema).optional(),
|
|
@@ -21705,7 +21746,12 @@ var toolSchema2 = external_exports.object({
|
|
|
21705
21746
|
name: external_exports.string().min(1).max(MAX_APP_TOOL_NAME_LENGTH).regex(APP_TOOL_NAME_PATTERN),
|
|
21706
21747
|
// Who asked, and what they may do on this site. Derived from the bearer by the portal, never
|
|
21707
21748
|
// from the model's arguments.
|
|
21708
|
-
viewer: external_exports.object({
|
|
21749
|
+
viewer: external_exports.object({
|
|
21750
|
+
userId: external_exports.string().min(1).max(64),
|
|
21751
|
+
access: external_exports.enum(["read", "write"]),
|
|
21752
|
+
// Optional only while a site worker or app runtime that predates it can still receive this envelope; absent means `full`.
|
|
21753
|
+
appRole: external_exports.enum(APP_ROLES).optional()
|
|
21754
|
+
}).strict(),
|
|
21709
21755
|
// Already validated against the tool's declared inputSchema, with the reserved routing names
|
|
21710
21756
|
// stripped. Every declared input schema has an object root, so this is an object too — and a
|
|
21711
21757
|
// call that names no arguments normalizes to `{}` rather than reaching the handler as undefined.
|
|
@@ -21911,7 +21957,12 @@ var MAX_UI_BODY_BYTES = 1024 * 1024;
|
|
|
21911
21957
|
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();
|
|
21912
21958
|
var uiContextSchema = external_exports.object({
|
|
21913
21959
|
version: external_exports.string().min(1).max(32),
|
|
21914
|
-
viewer: external_exports.object({
|
|
21960
|
+
viewer: external_exports.object({
|
|
21961
|
+
userId: external_exports.string().min(1).max(64),
|
|
21962
|
+
access: external_exports.enum(["read", "write"]),
|
|
21963
|
+
// Optional only while a site worker that predates it can still send this header; absent means `full`.
|
|
21964
|
+
appRole: external_exports.enum(APP_ROLES).optional()
|
|
21965
|
+
}).strict(),
|
|
21915
21966
|
install: uiInstallSchema,
|
|
21916
21967
|
installs: external_exports.array(uiInstallSchema).min(1).max(MAX_INSTALLS_PER_APP),
|
|
21917
21968
|
writeTicket: external_exports.string().min(1).max(2048).optional()
|
|
@@ -26305,14 +26356,15 @@ var captureAppsField = external_exports.record(external_exports.string().max(30)
|
|
|
26305
26356
|
description: "Values to record, keyed by app slug and then by capture name. A name the app does not declare is dropped.",
|
|
26306
26357
|
example: { facebook: { fbclid: "IwAR0abc" }, "google-ads": { gclid: "Cj0KCQ" } }
|
|
26307
26358
|
});
|
|
26359
|
+
var pageContextField = external_exports.object({
|
|
26360
|
+
url: external_exports.string().min(1).max(4096),
|
|
26361
|
+
referrer: external_exports.string().min(1).max(4096).optional()
|
|
26362
|
+
}).strict();
|
|
26308
26363
|
var serverActionContextField = external_exports.object({
|
|
26309
26364
|
occurredAt: external_exports.number().int().nonnegative().safe().optional().openapi({
|
|
26310
26365
|
description: "When the visitor action occurred, as Unix milliseconds; defaults to Qinto receipt time."
|
|
26311
26366
|
}),
|
|
26312
|
-
page:
|
|
26313
|
-
url: external_exports.string().min(1).max(4096),
|
|
26314
|
-
referrer: external_exports.string().min(1).max(4096).optional()
|
|
26315
|
-
}).strict().optional(),
|
|
26367
|
+
page: pageContextField.optional(),
|
|
26316
26368
|
network: external_exports.object({
|
|
26317
26369
|
ip: external_exports.string().min(1).max(64).optional(),
|
|
26318
26370
|
userAgent: external_exports.string().min(1).max(512).optional(),
|
|
@@ -27718,6 +27770,7 @@ var buildEnvelope = /* @__PURE__ */ __name((target, trigger, snapshot, context)
|
|
|
27718
27770
|
},
|
|
27719
27771
|
...buckets.includes("consentState") ? { consent: { enabled: context.consentEnforced, categories: snapshot.consent.categories, apps: snapshot.consent.apps } } : {},
|
|
27720
27772
|
...geoAllowed && currentGeo !== void 0 ? { geo: currentGeo } : {},
|
|
27773
|
+
...trigger.kind === "connect" && trigger.page !== void 0 && buckets.includes("eventContext") ? { page: trigger.page } : {},
|
|
27721
27774
|
// Not gated on a capabilities.data bucket: an app only ever sees what it captured or wrote.
|
|
27722
27775
|
...captures === void 0 ? {} : { captures },
|
|
27723
27776
|
...visitorContext === void 0 ? {} : { context: visitorContext },
|
|
@@ -29733,7 +29786,9 @@ var claimsSchema = external_exports.object({
|
|
|
29733
29786
|
appId: external_exports.string().min(1),
|
|
29734
29787
|
appInstallId: external_exports.string().min(1),
|
|
29735
29788
|
appVersionId: external_exports.string().min(1),
|
|
29736
|
-
access: external_exports.enum(["read", "write"])
|
|
29789
|
+
access: external_exports.enum(["read", "write"]),
|
|
29790
|
+
// Absent means `full`; see the mint below.
|
|
29791
|
+
appRole: external_exports.enum(APP_ROLES).optional()
|
|
29737
29792
|
}).strict();
|
|
29738
29793
|
var appUiAudience = /* @__PURE__ */ __name((slug) => {
|
|
29739
29794
|
return `app-ui:${slug}`;
|
|
@@ -29902,7 +29957,8 @@ var forwardToApp2 = /* @__PURE__ */ __name(async (c, input2) => {
|
|
|
29902
29957
|
"app.install_ord": install.ord,
|
|
29903
29958
|
"app.install_label": install.label,
|
|
29904
29959
|
"app.viewer_id": viewer.userId,
|
|
29905
|
-
"app.viewer_access": viewer.access
|
|
29960
|
+
"app.viewer_access": viewer.access,
|
|
29961
|
+
"app.viewer_app_role": viewer.appRole
|
|
29906
29962
|
}
|
|
29907
29963
|
},
|
|
29908
29964
|
() => {
|
|
@@ -29948,7 +30004,13 @@ var authorizeUi = /* @__PURE__ */ __name(async (c, slug, origin) => {
|
|
|
29948
30004
|
appId: verdict.claims.appId,
|
|
29949
30005
|
appVersionId: verdict.claims.appVersionId
|
|
29950
30006
|
}) : void 0;
|
|
29951
|
-
return {
|
|
30007
|
+
return {
|
|
30008
|
+
app: app2,
|
|
30009
|
+
install,
|
|
30010
|
+
// The portal mints `full` as no claim, so a site worker that predates the claim still accepts the token.
|
|
30011
|
+
viewer: { userId: verdict.claims.userId, access: verdict.claims.access, appRole: verdict.claims.appRole ?? "full" },
|
|
30012
|
+
writeTicket
|
|
30013
|
+
};
|
|
29952
30014
|
}, "authorizeUi");
|
|
29953
30015
|
var handleAppUi = /* @__PURE__ */ __name(async (c, slug) => {
|
|
29954
30016
|
const host = c.env.APP_UI_HOST;
|
|
@@ -30087,9 +30149,141 @@ var defaultHook = /* @__PURE__ */ __name((result, c) => {
|
|
|
30087
30149
|
}, "defaultHook");
|
|
30088
30150
|
var createApiRouter = /* @__PURE__ */ __name(() => new OpenAPIHono({ defaultHook }), "createApiRouter");
|
|
30089
30151
|
|
|
30152
|
+
// src/id-graph/anon/connection.ts
|
|
30153
|
+
var CONNECTION_CF_HEADER = "x-connection-cf";
|
|
30154
|
+
var SESSION_HEADER = "x-session";
|
|
30155
|
+
var OPEN_PAGE_PARAMS = ["url", "referrer"];
|
|
30156
|
+
var MAX_HOST_USER_AGENT_LENGTH = 512;
|
|
30157
|
+
var MAX_HOST_LOCALE_LENGTH = 64;
|
|
30158
|
+
var INTERNAL_HEADERS = /* @__PURE__ */ new Set([
|
|
30159
|
+
"x-user-id",
|
|
30160
|
+
"x-new-user",
|
|
30161
|
+
"x-geo",
|
|
30162
|
+
SITE_ID_HEADER,
|
|
30163
|
+
CONNECTION_CF_HEADER,
|
|
30164
|
+
SESSION_HEADER,
|
|
30165
|
+
TRACE_HEADER,
|
|
30166
|
+
CF_DATA_HEADER
|
|
30167
|
+
]);
|
|
30168
|
+
var REDACTED_HEADERS = /* @__PURE__ */ new Set(["authorization"]);
|
|
30169
|
+
var encodeConnectionCf = /* @__PURE__ */ __name((cf) => {
|
|
30170
|
+
if (cf === void 0) {
|
|
30171
|
+
return void 0;
|
|
30172
|
+
}
|
|
30173
|
+
const encoded = headerJson(cf);
|
|
30174
|
+
return encoded.length > MAX_ATTACHMENT_BYTES ? void 0 : encoded;
|
|
30175
|
+
}, "encodeConnectionCf");
|
|
30176
|
+
var forwardedCf = /* @__PURE__ */ __name((request) => {
|
|
30177
|
+
const raw2 = request.headers.get(CONNECTION_CF_HEADER);
|
|
30178
|
+
if (raw2 === null) {
|
|
30179
|
+
return void 0;
|
|
30180
|
+
}
|
|
30181
|
+
return JSON.parse(raw2);
|
|
30182
|
+
}, "forwardedCf");
|
|
30183
|
+
var forwardedSession = /* @__PURE__ */ __name((request) => {
|
|
30184
|
+
const raw2 = request.headers.get(SESSION_HEADER);
|
|
30185
|
+
if (raw2 === null) {
|
|
30186
|
+
return void 0;
|
|
30187
|
+
}
|
|
30188
|
+
return JSON.parse(raw2);
|
|
30189
|
+
}, "forwardedSession");
|
|
30190
|
+
var withoutPageParams = /* @__PURE__ */ __name((url2) => {
|
|
30191
|
+
const parsed = new URL(url2);
|
|
30192
|
+
for (const param of OPEN_PAGE_PARAMS) {
|
|
30193
|
+
parsed.searchParams.delete(param);
|
|
30194
|
+
}
|
|
30195
|
+
return parsed.toString();
|
|
30196
|
+
}, "withoutPageParams");
|
|
30197
|
+
var connectPage = /* @__PURE__ */ __name((request) => {
|
|
30198
|
+
const params = new URL(request.url).searchParams;
|
|
30199
|
+
const url2 = params.get("url");
|
|
30200
|
+
if (url2 === null) {
|
|
30201
|
+
return void 0;
|
|
30202
|
+
}
|
|
30203
|
+
const referrer = params.get("referrer");
|
|
30204
|
+
const parsed = pageContextField.safeParse({ url: url2, ...referrer === null ? {} : { referrer } });
|
|
30205
|
+
return parsed.success ? parsed.data : void 0;
|
|
30206
|
+
}, "connectPage");
|
|
30207
|
+
var connectAttrs = /* @__PURE__ */ __name((request, geo) => {
|
|
30208
|
+
const headers = {};
|
|
30209
|
+
for (const [name, value] of request.headers) {
|
|
30210
|
+
const lower = name.toLowerCase();
|
|
30211
|
+
if (!INTERNAL_HEADERS.has(lower) && !REDACTED_HEADERS.has(lower)) {
|
|
30212
|
+
headers[name] = value;
|
|
30213
|
+
}
|
|
30214
|
+
}
|
|
30215
|
+
const cf = forwardedCf(request);
|
|
30216
|
+
return {
|
|
30217
|
+
"url.full": withoutPageParams(request.url),
|
|
30218
|
+
"http.request.headers": JSON.stringify(headers),
|
|
30219
|
+
...cf === void 0 ? {} : { "qinto.cf": JSON.stringify(cf) },
|
|
30220
|
+
...geo === void 0 ? {} : { "qinto.geo": JSON.stringify(loggableGeo(geo)) }
|
|
30221
|
+
};
|
|
30222
|
+
}, "connectAttrs");
|
|
30223
|
+
var withoutQuery = /* @__PURE__ */ __name((url2) => {
|
|
30224
|
+
const parsed = new URL(url2);
|
|
30225
|
+
parsed.search = "";
|
|
30226
|
+
return parsed.toString();
|
|
30227
|
+
}, "withoutQuery");
|
|
30228
|
+
var browserGeoFrom = /* @__PURE__ */ __name((geo) => {
|
|
30229
|
+
if (geo === void 0) {
|
|
30230
|
+
return void 0;
|
|
30231
|
+
}
|
|
30232
|
+
return {
|
|
30233
|
+
country: geo.country ?? null,
|
|
30234
|
+
// EdgeTag's geoRegion is Cloudflare's subdivision code.
|
|
30235
|
+
region: geo.regionCode ?? null,
|
|
30236
|
+
state: geo.region ?? null,
|
|
30237
|
+
isEU: geo.isEUCountry === "yes"
|
|
30238
|
+
};
|
|
30239
|
+
}, "browserGeoFrom");
|
|
30240
|
+
var attachmentFieldBytes = /* @__PURE__ */ __name((name, value) => {
|
|
30241
|
+
return value === void 0 ? 0 : new TextEncoder().encode(`,"${name}":${JSON.stringify(value)}`).length;
|
|
30242
|
+
}, "attachmentFieldBytes");
|
|
30243
|
+
var boundedHost = /* @__PURE__ */ __name((request) => {
|
|
30244
|
+
const raw2 = hostFromRequest(request);
|
|
30245
|
+
const bounded = {
|
|
30246
|
+
ip: raw2.ip,
|
|
30247
|
+
userAgent: raw2.userAgent !== void 0 && raw2.userAgent.length <= MAX_HOST_USER_AGENT_LENGTH ? raw2.userAgent : void 0,
|
|
30248
|
+
locale: raw2.locale !== void 0 && raw2.locale.length <= MAX_HOST_LOCALE_LENGTH ? raw2.locale : void 0
|
|
30249
|
+
};
|
|
30250
|
+
return bounded.ip === void 0 && bounded.userAgent === void 0 && bounded.locale === void 0 ? void 0 : bounded;
|
|
30251
|
+
}, "boundedHost");
|
|
30252
|
+
var connectionAttachment = /* @__PURE__ */ __name((request, geo, siteId) => {
|
|
30253
|
+
const userAgent = request.headers.get("user-agent");
|
|
30254
|
+
const attrs = {
|
|
30255
|
+
"url.full": withoutQuery(request.url),
|
|
30256
|
+
...geo?.country === void 0 ? {} : { "qinto.country": geo.country },
|
|
30257
|
+
...geo?.city === void 0 ? {} : { "qinto.city": geo.city },
|
|
30258
|
+
...userAgent === null ? {} : { user_agent: userAgent }
|
|
30259
|
+
};
|
|
30260
|
+
const host = boundedHost(request);
|
|
30261
|
+
const hostBytes = attachmentFieldBytes("host", host);
|
|
30262
|
+
const browserGeo = browserGeoFrom(geo);
|
|
30263
|
+
const browserGeoBytes = attachmentFieldBytes("browserGeo", browserGeo);
|
|
30264
|
+
const session2 = forwardedSession(request);
|
|
30265
|
+
const sessionBytes = attachmentFieldBytes("session", session2);
|
|
30266
|
+
const siteBytes = attachmentFieldBytes("siteId", siteId);
|
|
30267
|
+
const cf = forwardedCf(request);
|
|
30268
|
+
const cfSuffix = cf === void 0 ? "" : `,"cf":${JSON.stringify(cf)}`;
|
|
30269
|
+
const cfBytes = new TextEncoder().encode(cfSuffix).length;
|
|
30270
|
+
const emptyAttrsBytes = new TextEncoder().encode(JSON.stringify({ attrs: {} })).length;
|
|
30271
|
+
const fixedBytes = siteBytes + sessionBytes + hostBytes + browserGeoBytes;
|
|
30272
|
+
const includedCf = cfBytes <= MAX_ATTACHMENT_BYTES - emptyAttrsBytes - fixedBytes ? cf : void 0;
|
|
30273
|
+
const budgeted = budgetAttrs(attrs, MAX_ATTACHMENT_BYTES - fixedBytes - (includedCf === void 0 ? 0 : cfBytes));
|
|
30274
|
+
return {
|
|
30275
|
+
...budgeted,
|
|
30276
|
+
siteId,
|
|
30277
|
+
...session2 === void 0 ? {} : { session: session2 },
|
|
30278
|
+
...browserGeo === void 0 ? {} : { browserGeo },
|
|
30279
|
+
...includedCf === void 0 ? {} : { cf: includedCf },
|
|
30280
|
+
...host === void 0 ? {} : { host }
|
|
30281
|
+
};
|
|
30282
|
+
}, "connectionAttachment");
|
|
30283
|
+
|
|
30090
30284
|
// src/helpers/request-span.ts
|
|
30091
30285
|
var OMITTED_HEADERS = /* @__PURE__ */ new Set(["authorization", DISPATCH_HEADER, CF_DATA_HEADER]);
|
|
30092
|
-
var requestAttrs = /* @__PURE__ */ __name((request) => {
|
|
30286
|
+
var requestAttrs = /* @__PURE__ */ __name((request, pathname) => {
|
|
30093
30287
|
const headers = {};
|
|
30094
30288
|
for (const [name, value] of request.headers) {
|
|
30095
30289
|
if (!OMITTED_HEADERS.has(name.toLowerCase())) {
|
|
@@ -30099,7 +30293,7 @@ var requestAttrs = /* @__PURE__ */ __name((request) => {
|
|
|
30099
30293
|
const cf = request.cf;
|
|
30100
30294
|
return {
|
|
30101
30295
|
"http.request.method": request.method,
|
|
30102
|
-
"url.full": request.url,
|
|
30296
|
+
"url.full": pathname === "/open" ? withoutPageParams(request.url) : request.url,
|
|
30103
30297
|
"http.request.headers": JSON.stringify(headers),
|
|
30104
30298
|
...cf === void 0 ? {} : { "qinto.cf": JSON.stringify(cf) }
|
|
30105
30299
|
};
|
|
@@ -30114,7 +30308,7 @@ var requestSpan = /* @__PURE__ */ __name(async (c, next) => {
|
|
|
30114
30308
|
const pathname = new URL(c.req.url).pathname;
|
|
30115
30309
|
const dispatch = parseDispatchTrace(c.req.raw.headers.get(DISPATCH_HEADER));
|
|
30116
30310
|
const trace = dispatch === void 0 ? inboundTrace(c.req.raw, pathname) : { traceId: dispatch.traceId, parent: dispatch.spanId };
|
|
30117
|
-
await runInvocation({ name: `${c.req.method} ${pathname}`, trace, attrs: requestAttrs(c.req.raw) }, async () => {
|
|
30311
|
+
await runInvocation({ name: `${c.req.method} ${pathname}`, trace, attrs: requestAttrs(c.req.raw, pathname) }, async () => {
|
|
30118
30312
|
try {
|
|
30119
30313
|
await next();
|
|
30120
30314
|
setSpanAttributes({ "http.response.status_code": c.res.status });
|
|
@@ -30321,120 +30515,6 @@ idGraphInspect.post("/internal/id-graph/rows", async (c) => {
|
|
|
30321
30515
|
return c.json({ page: await inspectObjectTable(c.env, body) });
|
|
30322
30516
|
});
|
|
30323
30517
|
|
|
30324
|
-
// src/id-graph/anon/connection.ts
|
|
30325
|
-
var CONNECTION_CF_HEADER = "x-connection-cf";
|
|
30326
|
-
var SESSION_HEADER = "x-session";
|
|
30327
|
-
var MAX_HOST_USER_AGENT_LENGTH = 512;
|
|
30328
|
-
var MAX_HOST_LOCALE_LENGTH = 64;
|
|
30329
|
-
var INTERNAL_HEADERS = /* @__PURE__ */ new Set([
|
|
30330
|
-
"x-user-id",
|
|
30331
|
-
"x-new-user",
|
|
30332
|
-
"x-geo",
|
|
30333
|
-
SITE_ID_HEADER,
|
|
30334
|
-
CONNECTION_CF_HEADER,
|
|
30335
|
-
SESSION_HEADER,
|
|
30336
|
-
TRACE_HEADER,
|
|
30337
|
-
CF_DATA_HEADER
|
|
30338
|
-
]);
|
|
30339
|
-
var REDACTED_HEADERS = /* @__PURE__ */ new Set(["authorization"]);
|
|
30340
|
-
var encodeConnectionCf = /* @__PURE__ */ __name((cf) => {
|
|
30341
|
-
if (cf === void 0) {
|
|
30342
|
-
return void 0;
|
|
30343
|
-
}
|
|
30344
|
-
const encoded = headerJson(cf);
|
|
30345
|
-
return encoded.length > MAX_ATTACHMENT_BYTES ? void 0 : encoded;
|
|
30346
|
-
}, "encodeConnectionCf");
|
|
30347
|
-
var forwardedCf = /* @__PURE__ */ __name((request) => {
|
|
30348
|
-
const raw2 = request.headers.get(CONNECTION_CF_HEADER);
|
|
30349
|
-
if (raw2 === null) {
|
|
30350
|
-
return void 0;
|
|
30351
|
-
}
|
|
30352
|
-
return JSON.parse(raw2);
|
|
30353
|
-
}, "forwardedCf");
|
|
30354
|
-
var forwardedSession = /* @__PURE__ */ __name((request) => {
|
|
30355
|
-
const raw2 = request.headers.get(SESSION_HEADER);
|
|
30356
|
-
if (raw2 === null) {
|
|
30357
|
-
return void 0;
|
|
30358
|
-
}
|
|
30359
|
-
return JSON.parse(raw2);
|
|
30360
|
-
}, "forwardedSession");
|
|
30361
|
-
var connectAttrs = /* @__PURE__ */ __name((request, geo) => {
|
|
30362
|
-
const headers = {};
|
|
30363
|
-
for (const [name, value] of request.headers) {
|
|
30364
|
-
const lower = name.toLowerCase();
|
|
30365
|
-
if (!INTERNAL_HEADERS.has(lower) && !REDACTED_HEADERS.has(lower)) {
|
|
30366
|
-
headers[name] = value;
|
|
30367
|
-
}
|
|
30368
|
-
}
|
|
30369
|
-
const cf = forwardedCf(request);
|
|
30370
|
-
return {
|
|
30371
|
-
"url.full": request.url,
|
|
30372
|
-
"http.request.headers": JSON.stringify(headers),
|
|
30373
|
-
...cf === void 0 ? {} : { "qinto.cf": JSON.stringify(cf) },
|
|
30374
|
-
...geo === void 0 ? {} : { "qinto.geo": JSON.stringify(loggableGeo(geo)) }
|
|
30375
|
-
};
|
|
30376
|
-
}, "connectAttrs");
|
|
30377
|
-
var withoutQuery = /* @__PURE__ */ __name((url2) => {
|
|
30378
|
-
const parsed = new URL(url2);
|
|
30379
|
-
parsed.search = "";
|
|
30380
|
-
return parsed.toString();
|
|
30381
|
-
}, "withoutQuery");
|
|
30382
|
-
var browserGeoFrom = /* @__PURE__ */ __name((geo) => {
|
|
30383
|
-
if (geo === void 0) {
|
|
30384
|
-
return void 0;
|
|
30385
|
-
}
|
|
30386
|
-
return {
|
|
30387
|
-
country: geo.country ?? null,
|
|
30388
|
-
// EdgeTag's geoRegion is Cloudflare's subdivision code.
|
|
30389
|
-
region: geo.regionCode ?? null,
|
|
30390
|
-
state: geo.region ?? null,
|
|
30391
|
-
isEU: geo.isEUCountry === "yes"
|
|
30392
|
-
};
|
|
30393
|
-
}, "browserGeoFrom");
|
|
30394
|
-
var attachmentFieldBytes = /* @__PURE__ */ __name((name, value) => {
|
|
30395
|
-
return value === void 0 ? 0 : new TextEncoder().encode(`,"${name}":${JSON.stringify(value)}`).length;
|
|
30396
|
-
}, "attachmentFieldBytes");
|
|
30397
|
-
var boundedHost = /* @__PURE__ */ __name((request) => {
|
|
30398
|
-
const raw2 = hostFromRequest(request);
|
|
30399
|
-
const bounded = {
|
|
30400
|
-
ip: raw2.ip,
|
|
30401
|
-
userAgent: raw2.userAgent !== void 0 && raw2.userAgent.length <= MAX_HOST_USER_AGENT_LENGTH ? raw2.userAgent : void 0,
|
|
30402
|
-
locale: raw2.locale !== void 0 && raw2.locale.length <= MAX_HOST_LOCALE_LENGTH ? raw2.locale : void 0
|
|
30403
|
-
};
|
|
30404
|
-
return bounded.ip === void 0 && bounded.userAgent === void 0 && bounded.locale === void 0 ? void 0 : bounded;
|
|
30405
|
-
}, "boundedHost");
|
|
30406
|
-
var connectionAttachment = /* @__PURE__ */ __name((request, geo, siteId) => {
|
|
30407
|
-
const userAgent = request.headers.get("user-agent");
|
|
30408
|
-
const attrs = {
|
|
30409
|
-
"url.full": withoutQuery(request.url),
|
|
30410
|
-
...geo?.country === void 0 ? {} : { "qinto.country": geo.country },
|
|
30411
|
-
...geo?.city === void 0 ? {} : { "qinto.city": geo.city },
|
|
30412
|
-
...userAgent === null ? {} : { user_agent: userAgent }
|
|
30413
|
-
};
|
|
30414
|
-
const host = boundedHost(request);
|
|
30415
|
-
const hostBytes = attachmentFieldBytes("host", host);
|
|
30416
|
-
const browserGeo = browserGeoFrom(geo);
|
|
30417
|
-
const browserGeoBytes = attachmentFieldBytes("browserGeo", browserGeo);
|
|
30418
|
-
const session2 = forwardedSession(request);
|
|
30419
|
-
const sessionBytes = attachmentFieldBytes("session", session2);
|
|
30420
|
-
const siteBytes = attachmentFieldBytes("siteId", siteId);
|
|
30421
|
-
const cf = forwardedCf(request);
|
|
30422
|
-
const cfSuffix = cf === void 0 ? "" : `,"cf":${JSON.stringify(cf)}`;
|
|
30423
|
-
const cfBytes = new TextEncoder().encode(cfSuffix).length;
|
|
30424
|
-
const emptyAttrsBytes = new TextEncoder().encode(JSON.stringify({ attrs: {} })).length;
|
|
30425
|
-
const fixedBytes = siteBytes + sessionBytes + hostBytes + browserGeoBytes;
|
|
30426
|
-
const includedCf = cfBytes <= MAX_ATTACHMENT_BYTES - emptyAttrsBytes - fixedBytes ? cf : void 0;
|
|
30427
|
-
const budgeted = budgetAttrs(attrs, MAX_ATTACHMENT_BYTES - fixedBytes - (includedCf === void 0 ? 0 : cfBytes));
|
|
30428
|
-
return {
|
|
30429
|
-
...budgeted,
|
|
30430
|
-
siteId,
|
|
30431
|
-
...session2 === void 0 ? {} : { session: session2 },
|
|
30432
|
-
...browserGeo === void 0 ? {} : { browserGeo },
|
|
30433
|
-
...includedCf === void 0 ? {} : { cf: includedCf },
|
|
30434
|
-
...host === void 0 ? {} : { host }
|
|
30435
|
-
};
|
|
30436
|
-
}, "connectionAttachment");
|
|
30437
|
-
|
|
30438
30518
|
// src/paths/open.ts
|
|
30439
30519
|
var withSetCookie = /* @__PURE__ */ __name((res, cookies) => {
|
|
30440
30520
|
if (res.webSocket) {
|
|
@@ -31638,6 +31718,10 @@ var acceptedCaptures = /* @__PURE__ */ __name((registry3, consent2, apps, enforc
|
|
|
31638
31718
|
}
|
|
31639
31719
|
return accepted;
|
|
31640
31720
|
}, "acceptedCaptures");
|
|
31721
|
+
var declaredTtlMs = /* @__PURE__ */ __name((registry3, appId, key) => {
|
|
31722
|
+
const app2 = registry3.apps[appId];
|
|
31723
|
+
return app2 === void 0 ? null : declaration(app2, key)?.ttlMs ?? null;
|
|
31724
|
+
}, "declaredTtlMs");
|
|
31641
31725
|
|
|
31642
31726
|
// src/id-graph/kv-cache.ts
|
|
31643
31727
|
var cachedKv = /* @__PURE__ */ __name((kv) => {
|
|
@@ -32562,7 +32646,7 @@ var MAX_BROWSER_RESULTS_BYTES = 32 * 1024;
|
|
|
32562
32646
|
var MAX_FRAME_BYTES = 64 * 1024;
|
|
32563
32647
|
var browserContextFrame = external_exports.object({
|
|
32564
32648
|
occurredAt: external_exports.number().int().nonnegative().safe(),
|
|
32565
|
-
page:
|
|
32649
|
+
page: pageContextField
|
|
32566
32650
|
}).strict();
|
|
32567
32651
|
var browserResult = external_exports.unknown().refine((value) => {
|
|
32568
32652
|
return new TextEncoder().encode(JSON.stringify(value)).length <= MAX_BROWSER_RESULT_BYTES;
|
|
@@ -32794,8 +32878,14 @@ var AnonDO = class extends DurableObject2 {
|
|
|
32794
32878
|
const attachment = connectionAttachment(request, geo, siteId);
|
|
32795
32879
|
server.serializeAttachment(attachment);
|
|
32796
32880
|
this.sendSharedContext([server], context);
|
|
32881
|
+
const page = connectPage(request);
|
|
32797
32882
|
this.appFanOut(
|
|
32798
|
-
{
|
|
32883
|
+
{
|
|
32884
|
+
kind: "connect",
|
|
32885
|
+
...attachment.cf === void 0 ? {} : { geo: attachment.cf },
|
|
32886
|
+
host: attachment.host,
|
|
32887
|
+
...page === void 0 ? {} : { page }
|
|
32888
|
+
},
|
|
32799
32889
|
userId,
|
|
32800
32890
|
context
|
|
32801
32891
|
);
|
|
@@ -32996,7 +33086,11 @@ var AnonDO = class extends DurableObject2 {
|
|
|
32996
33086
|
if (!appWriteAllowed(context.registry, consentState2(this.kv), input2.slug, context.consentEnforced)) {
|
|
32997
33087
|
return;
|
|
32998
33088
|
}
|
|
32999
|
-
this.storeCaptures(
|
|
33089
|
+
this.storeCaptures(
|
|
33090
|
+
input2.writes.map((write) => {
|
|
33091
|
+
return { ...write, appId: input2.slug, source: "app", ttlMs: declaredTtlMs(context.registry, input2.slug, write.key) };
|
|
33092
|
+
})
|
|
33093
|
+
);
|
|
33000
33094
|
});
|
|
33001
33095
|
});
|
|
33002
33096
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"main": {
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"gitSha": "
|
|
5
|
-
"builtAt": "2026-09-
|
|
3
|
+
"version": "0.1.6",
|
|
4
|
+
"gitSha": "802179565243bb2e4dd99f79f00a3815d4f0568c",
|
|
5
|
+
"builtAt": "2026-09-28T04:28:30.340Z",
|
|
6
6
|
"compatibilityDate": "2026-06-23",
|
|
7
7
|
"compatibilityFlags": [
|
|
8
8
|
"nodejs_compat"
|
|
@@ -39,9 +39,9 @@
|
|
|
39
39
|
]
|
|
40
40
|
},
|
|
41
41
|
"app-runtime": {
|
|
42
|
-
"version": "0.1.
|
|
43
|
-
"gitSha": "
|
|
44
|
-
"builtAt": "2026-09-
|
|
42
|
+
"version": "0.1.4",
|
|
43
|
+
"gitSha": "b53a595d63827d8fda4f898391c6c0986f0fd1fa",
|
|
44
|
+
"builtAt": "2026-09-28T04:28:33.821Z",
|
|
45
45
|
"compatibilityDate": "2026-06-23",
|
|
46
46
|
"compatibilityFlags": [
|
|
47
47
|
"nodejs_compat"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blotout/qinto-cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.22",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Qinto CLI: authenticate against the Qinto platform and operate it from the terminal or from an agent.",
|
|
6
6
|
"repository": {
|
|
@@ -16,8 +16,7 @@
|
|
|
16
16
|
},
|
|
17
17
|
"files": [
|
|
18
18
|
"bin",
|
|
19
|
-
"dist"
|
|
20
|
-
"templates"
|
|
19
|
+
"dist"
|
|
21
20
|
],
|
|
22
21
|
"publishConfig": {
|
|
23
22
|
"access": "public"
|
|
@@ -35,6 +34,7 @@
|
|
|
35
34
|
"@qinto/app-build": "0.0.0",
|
|
36
35
|
"@qinto/app-dev": "0.0.0",
|
|
37
36
|
"@qinto/app-manifest": "0.0.0",
|
|
37
|
+
"@qinto/app-templates": "0.0.0",
|
|
38
38
|
"@qinto/oauth-grammar": "0.0.0",
|
|
39
39
|
"@types/node": "25.9.5",
|
|
40
40
|
"@types/proper-lockfile": "4.1.4",
|