mcp-scraper 0.84.0 → 0.85.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.
- package/CHANGELOG.md +15 -0
- package/README.md +2 -2
- package/dist/bin/api-server.js +2 -2
- package/dist/bin/mcp-scraper-cli.js +3 -3
- package/dist/bin/mcp-scraper-core.js +6 -6
- package/dist/bin/mcp-scraper-install.js +2 -2
- package/dist/bin/mcp-stdio-server.js +6 -6
- package/dist/{chunk-WDWWCNMW.js → chunk-2ZDYUTOZ.js} +3 -3
- package/dist/{chunk-LHIWX7RM.js → chunk-6IOGTFNS.js} +1 -1
- package/dist/{chunk-ZB55UMMF.js → chunk-C7OKENCR.js} +1 -1
- package/dist/{chunk-4S6HPHPB.js → chunk-P7FWOMU7.js} +6 -9
- package/dist/{chunk-OUTE3755.js → chunk-RHAOKXQK.js} +1 -1
- package/dist/{chunk-4KFD2WXG.js → chunk-W3SGF7GX.js} +33 -7
- package/dist/{chunk-U77X4NIR.js → chunk-W4IY6CB4.js} +49 -290
- package/dist/{chunk-NLWBM55O.js → chunk-WN7N4ESQ.js} +2 -2
- package/dist/{chunk-UM7DCY6W.js → chunk-X5HRAAQM.js} +2 -2
- package/dist/{extract-bundle-SI35H4HR.js → extract-bundle-NSMGHEG6.js} +2 -2
- package/dist/{gmail-service-MOZ6S56I.js → gmail-service-BTRAHGJS.js} +2 -2
- package/dist/{server-3F3JMHBF.js → server-EOPETL7Q.js} +463 -869
- package/dist/{site-extract-repository-3WC3VB5Y.js → site-extract-repository-DWU52BRQ.js} +2 -2
- package/dist/{worker-VTFGHWZL.js → worker-5A375BGN.js} +1 -1
- package/package.json +1 -1
- package/public/.well-known/xray-install.json +5 -8
- package/public/agent-install.md +4 -8
|
@@ -43,7 +43,7 @@ import {
|
|
|
43
43
|
setExtractJobTotal,
|
|
44
44
|
settleExtractJob,
|
|
45
45
|
terminalExtractJobStatus
|
|
46
|
-
} from "./chunk-
|
|
46
|
+
} from "./chunk-C7OKENCR.js";
|
|
47
47
|
import {
|
|
48
48
|
REQUIRED_LOCATION_STATE_CODES,
|
|
49
49
|
importHostedCensusPlacesCsv,
|
|
@@ -88,6 +88,7 @@ import {
|
|
|
88
88
|
GmailServiceError,
|
|
89
89
|
MainNangoTransportError,
|
|
90
90
|
assertGmailSelectionReceipt,
|
|
91
|
+
assertNangoProviderAvailable,
|
|
91
92
|
callNangoToolDirect,
|
|
92
93
|
createNangoReconnectSessionDirect,
|
|
93
94
|
createNangoSessionDirect,
|
|
@@ -96,6 +97,7 @@ import {
|
|
|
96
97
|
discoverOwnedNangoConnections,
|
|
97
98
|
getOwnedGmailSelection,
|
|
98
99
|
gmailFingerprint,
|
|
100
|
+
isWithdrawnNangoProvider,
|
|
99
101
|
listConnectedUsageHistory,
|
|
100
102
|
listNangoCatalogDirect,
|
|
101
103
|
listNangoToolsDirect,
|
|
@@ -103,7 +105,7 @@ import {
|
|
|
103
105
|
probeNangoConnectionDirect,
|
|
104
106
|
recordNangoConnectionCost,
|
|
105
107
|
settleConnectedUsage
|
|
106
|
-
} from "./chunk-
|
|
108
|
+
} from "./chunk-W3SGF7GX.js";
|
|
107
109
|
import {
|
|
108
110
|
ANALYTICS_ATTRIBUTION_MODELS,
|
|
109
111
|
ANALYTICS_CONTENT_SORTS,
|
|
@@ -154,7 +156,6 @@ import {
|
|
|
154
156
|
getPublicAnalyticsForm,
|
|
155
157
|
identityHmac,
|
|
156
158
|
ingestAnalyticsEvents,
|
|
157
|
-
insertAnalyticsRevenueSetupRevision,
|
|
158
159
|
isAnalyticsFormPlacementApproved,
|
|
159
160
|
linkAnalyticsFormIdentity,
|
|
160
161
|
listAnalyticsActivationDestinations,
|
|
@@ -251,13 +252,15 @@ import {
|
|
|
251
252
|
AnalyticsCrmOutboundJobSchema,
|
|
252
253
|
AnalyticsCrmOutboundPolicySchema,
|
|
253
254
|
AnalyticsCrmOutboundReceiptSchema,
|
|
254
|
-
AnalyticsCrmProviderIdSchema,
|
|
255
255
|
AnalyticsCrmProvisioningPlanSchema,
|
|
256
256
|
AnalyticsCrmProvisioningReceiptSchema,
|
|
257
257
|
AnalyticsCrmSyncStatusSchema,
|
|
258
258
|
AnalyticsExperimentPlanSchema,
|
|
259
259
|
AnalyticsPipelineEventMappingSchema,
|
|
260
260
|
AnalyticsPipelineEventSchema,
|
|
261
|
+
AnalyticsPublicCrmProviderIdSchema,
|
|
262
|
+
AnalyticsPublicCrmProvisioningPlanSchema,
|
|
263
|
+
AnalyticsPublicCrmProvisioningReceiptSchema,
|
|
261
264
|
AnalyticsResolvedCrmCapabilitySchema,
|
|
262
265
|
ApiErrorResponseSchema,
|
|
263
266
|
ApprovalDecisionSchema,
|
|
@@ -384,7 +387,7 @@ import {
|
|
|
384
387
|
transcribeMediaUrl,
|
|
385
388
|
transitionAnalyticsExperiment,
|
|
386
389
|
validateAnalyticsRestResponseForRequest
|
|
387
|
-
} from "./chunk-
|
|
390
|
+
} from "./chunk-W4IY6CB4.js";
|
|
388
391
|
import {
|
|
389
392
|
auditImageUrls,
|
|
390
393
|
auditImages,
|
|
@@ -455,7 +458,7 @@ import {
|
|
|
455
458
|
tierChangeLeavesPrivateOffer,
|
|
456
459
|
tierCreditsPerInterval,
|
|
457
460
|
vendorCostUsdToMc
|
|
458
|
-
} from "./chunk-
|
|
461
|
+
} from "./chunk-X5HRAAQM.js";
|
|
459
462
|
import {
|
|
460
463
|
browserServiceApiKey,
|
|
461
464
|
browserServiceProfileName,
|
|
@@ -479,7 +482,7 @@ import {
|
|
|
479
482
|
workflowOutputBaseDir,
|
|
480
483
|
workflowStepCount,
|
|
481
484
|
workflowSupportsSteps
|
|
482
|
-
} from "./chunk-
|
|
485
|
+
} from "./chunk-6IOGTFNS.js";
|
|
483
486
|
import {
|
|
484
487
|
csvRecords,
|
|
485
488
|
parseCsv,
|
|
@@ -497,7 +500,7 @@ import {
|
|
|
497
500
|
} from "./chunk-OWF2JJKN.js";
|
|
498
501
|
import {
|
|
499
502
|
extractContactEvidence
|
|
500
|
-
} from "./chunk-
|
|
503
|
+
} from "./chunk-P7FWOMU7.js";
|
|
501
504
|
import {
|
|
502
505
|
isPrivateIpAddress,
|
|
503
506
|
loadHtmlDocument,
|
|
@@ -505,7 +508,7 @@ import {
|
|
|
505
508
|
} from "./chunk-GGZEC22A.js";
|
|
506
509
|
import {
|
|
507
510
|
PACKAGE_VERSION
|
|
508
|
-
} from "./chunk-
|
|
511
|
+
} from "./chunk-RHAOKXQK.js";
|
|
509
512
|
import {
|
|
510
513
|
CaptchaError,
|
|
511
514
|
MapsSearchIncompletePageError,
|
|
@@ -3968,7 +3971,7 @@ async function generateOgImage(post) {
|
|
|
3968
3971
|
|
|
3969
3972
|
// src/api/server.ts
|
|
3970
3973
|
import { Resend as Resend3 } from "resend";
|
|
3971
|
-
import { createHash as
|
|
3974
|
+
import { createHash as createHash103, randomUUID as randomUUID68 } from "crypto";
|
|
3972
3975
|
|
|
3973
3976
|
// src/api/kpo-extractor.ts
|
|
3974
3977
|
import TurndownService from "turndown";
|
|
@@ -9760,7 +9763,7 @@ var siteExtractFn = inngest.createFunction(
|
|
|
9760
9763
|
});
|
|
9761
9764
|
}) : null;
|
|
9762
9765
|
const finalized = await step.run("finalize", async () => {
|
|
9763
|
-
const { assembleExtractArtifacts } = await import("./extract-bundle-
|
|
9766
|
+
const { assembleExtractArtifacts } = await import("./extract-bundle-NSMGHEG6.js");
|
|
9764
9767
|
const current = await getExtractJob(jobId2);
|
|
9765
9768
|
if (!current) throw new Error("extract job disappeared before finalization");
|
|
9766
9769
|
const stored = await assembleExtractArtifacts(current, { branding, imageAudit });
|
|
@@ -22274,11 +22277,11 @@ async function beginOrResumeGmailImport(args) {
|
|
|
22274
22277
|
await ensureGmailImportSchema();
|
|
22275
22278
|
const key3 = args.idempotencyKey.trim();
|
|
22276
22279
|
if (key3.length < 8 || key3.length > 200) throw new GmailImportRepositoryError("idempotency_key_invalid", "Idempotency-Key must be 8-200 characters.");
|
|
22277
|
-
const
|
|
22280
|
+
const fingerprint5 = gmailFingerprint({ importPlanId: args.plan.importPlanId, planFingerprint: args.plan.planFingerprint });
|
|
22278
22281
|
const existing = await getDb().execute({ sql: `SELECT * FROM gmail_import_jobs WHERE owner_identity = ? AND idempotency_key = ? LIMIT 1`, args: [args.ownerId, key3] });
|
|
22279
22282
|
if (existing.rows[0]) {
|
|
22280
22283
|
const job2 = jobFromRow(existing.rows[0]);
|
|
22281
|
-
if (job2.fingerprint !==
|
|
22284
|
+
if (job2.fingerprint !== fingerprint5) throw new GmailImportRepositoryError("idempotency_conflict", "This Idempotency-Key is already bound to a different Gmail import.", 409);
|
|
22282
22285
|
if (job2.status !== "running") return { job: job2, acquired: false };
|
|
22283
22286
|
const now2 = args.now ?? /* @__PURE__ */ new Date();
|
|
22284
22287
|
if (job2.leaseExpiresAt && new Date(job2.leaseExpiresAt).getTime() > now2.getTime()) return { job: job2, acquired: false };
|
|
@@ -22290,7 +22293,7 @@ async function beginOrResumeGmailImport(args) {
|
|
|
22290
22293
|
}
|
|
22291
22294
|
const now = args.now ?? /* @__PURE__ */ new Date();
|
|
22292
22295
|
const leaseExpiresAt = new Date(now.getTime() + (args.leaseMs ?? 45e3)).toISOString();
|
|
22293
|
-
const job = { ingestId: `ging_${randomUUID6().replace(/-/g, "")}`, ownerId: args.ownerId, importPlanId: args.plan.importPlanId, idempotencyKey: key3, fingerprint:
|
|
22296
|
+
const job = { ingestId: `ging_${randomUUID6().replace(/-/g, "")}`, ownerId: args.ownerId, importPlanId: args.plan.importPlanId, idempotencyKey: key3, fingerprint: fingerprint5, status: "running", attempts: 0, leaseExpiresAt, progress: { messagesStored: 0, attachmentsStored: 0, attachmentsIndexed: 0, skipped: 0, errors: [], checkpoints: {} }, createdAt: now.toISOString(), updatedAt: now.toISOString() };
|
|
22294
22297
|
await getDb().execute({ sql: `INSERT INTO gmail_import_jobs (ingest_id, owner_identity, import_plan_id, idempotency_key, fingerprint, status, attempts, lease_expires_at, progress_json, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, args: [job.ingestId, job.ownerId, job.importPlanId, job.idempotencyKey, job.fingerprint, job.status, job.attempts, job.leaseExpiresAt, JSON.stringify(job.progress), job.createdAt, job.updatedAt] });
|
|
22295
22298
|
return { job, acquired: true };
|
|
22296
22299
|
}
|
|
@@ -24204,12 +24207,12 @@ directoryApp.post("/run", createApiKeyAuth(), async (c) => {
|
|
|
24204
24207
|
const keyResult = idempotencyKey(c.req.header("idempotency-key") ?? c.req.header("x-idempotency-key"));
|
|
24205
24208
|
if (!keyResult.ok) return c.json({ error: keyResult.message, error_code: "invalid_request", retryable: false }, 400);
|
|
24206
24209
|
c.header("Idempotency-Key", keyResult.key);
|
|
24207
|
-
const
|
|
24210
|
+
const fingerprint5 = requestFingerprint(parsed.data);
|
|
24208
24211
|
let existingJob = null;
|
|
24209
24212
|
if (parsed.data.background) {
|
|
24210
24213
|
existingJob = await getDirectoryWorkflowJobByIdempotencyKey(Number(user.id), keyResult.key);
|
|
24211
24214
|
if (existingJob) {
|
|
24212
|
-
if (existingJob.requestFingerprint !==
|
|
24215
|
+
if (existingJob.requestFingerprint !== fingerprint5) {
|
|
24213
24216
|
return c.json({ error: "Idempotency-Key was already used for different directory workflow inputs.", error_code: "idempotency_conflict", retryable: false }, 409);
|
|
24214
24217
|
}
|
|
24215
24218
|
if (existingJob.status !== "initializing") return c.json(await publicJobEnvelope(existingJob));
|
|
@@ -24264,7 +24267,7 @@ directoryApp.post("/run", createApiKeyAuth(), async (c) => {
|
|
|
24264
24267
|
id: requestedJobId,
|
|
24265
24268
|
userId: Number(user.id),
|
|
24266
24269
|
idempotencyKey: keyResult.key,
|
|
24267
|
-
requestFingerprint:
|
|
24270
|
+
requestFingerprint: fingerprint5,
|
|
24268
24271
|
options: parsed.data,
|
|
24269
24272
|
plan,
|
|
24270
24273
|
holdMc,
|
|
@@ -24474,7 +24477,7 @@ async function createOrGetLeadListUpload(args) {
|
|
|
24474
24477
|
const id2 = cleanId(args.id ?? newLeadListUploadId(), "upl");
|
|
24475
24478
|
const ownerId3 = bounded(args.ownerId, "ownerId", 1, 160);
|
|
24476
24479
|
const key3 = bounded(args.idempotencyKey, "idempotencyKey", 8, 200);
|
|
24477
|
-
const
|
|
24480
|
+
const fingerprint5 = bounded(args.requestFingerprint, "requestFingerprint", 16, 128);
|
|
24478
24481
|
const createdAt = args.createdAt ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
24479
24482
|
const result3 = await getDb().execute({
|
|
24480
24483
|
sql: `INSERT OR IGNORE INTO lead_list_uploads (
|
|
@@ -24485,7 +24488,7 @@ async function createOrGetLeadListUpload(args) {
|
|
|
24485
24488
|
id2,
|
|
24486
24489
|
ownerId3,
|
|
24487
24490
|
key3,
|
|
24488
|
-
|
|
24491
|
+
fingerprint5,
|
|
24489
24492
|
args.blobPathname,
|
|
24490
24493
|
args.filenameHint ?? null,
|
|
24491
24494
|
JSON.stringify(args.allowedMimeTypes),
|
|
@@ -24498,7 +24501,7 @@ async function createOrGetLeadListUpload(args) {
|
|
|
24498
24501
|
const upload = await getLeadListUploadByIdempotencyKey(ownerId3, key3);
|
|
24499
24502
|
if (!upload) throw new Error("lead-list upload insert did not persist");
|
|
24500
24503
|
const created = Number(result3.rowsAffected ?? 0) > 0;
|
|
24501
|
-
return { upload, created, conflict: !created && upload.requestFingerprint !==
|
|
24504
|
+
return { upload, created, conflict: !created && upload.requestFingerprint !== fingerprint5 };
|
|
24502
24505
|
}
|
|
24503
24506
|
async function getLeadListUpload(id2, ownerId3) {
|
|
24504
24507
|
await ensureLeadListImportRepositorySchema();
|
|
@@ -24548,7 +24551,7 @@ async function createOrGetImportedLeadList(args) {
|
|
|
24548
24551
|
const id2 = cleanId(args.id ?? newImportedLeadListId(), "lst");
|
|
24549
24552
|
const ownerId3 = bounded(args.ownerId, "ownerId", 1, 160);
|
|
24550
24553
|
const key3 = bounded(args.idempotencyKey, "idempotencyKey", 8, 200);
|
|
24551
|
-
const
|
|
24554
|
+
const fingerprint5 = bounded(args.requestFingerprint, "requestFingerprint", 16, 128);
|
|
24552
24555
|
const createdAt = args.createdAt ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
24553
24556
|
const result3 = await getDb().execute({
|
|
24554
24557
|
sql: `INSERT OR IGNORE INTO imported_lead_lists (
|
|
@@ -24560,7 +24563,7 @@ async function createOrGetImportedLeadList(args) {
|
|
|
24560
24563
|
id2,
|
|
24561
24564
|
ownerId3,
|
|
24562
24565
|
key3,
|
|
24563
|
-
|
|
24566
|
+
fingerprint5,
|
|
24564
24567
|
args.normalizedArtifactId,
|
|
24565
24568
|
args.normalizedDigest,
|
|
24566
24569
|
args.sourceFormat,
|
|
@@ -24580,7 +24583,7 @@ async function createOrGetImportedLeadList(args) {
|
|
|
24580
24583
|
const leadList = await getImportedLeadListByIdempotencyKey(ownerId3, key3);
|
|
24581
24584
|
if (!leadList) throw new Error("imported lead-list insert did not persist");
|
|
24582
24585
|
const created = Number(result3.rowsAffected ?? 0) > 0;
|
|
24583
|
-
return { leadList, created, conflict: !created && leadList.requestFingerprint !==
|
|
24586
|
+
return { leadList, created, conflict: !created && leadList.requestFingerprint !== fingerprint5 };
|
|
24584
24587
|
}
|
|
24585
24588
|
async function getImportedLeadList(id2, ownerId3) {
|
|
24586
24589
|
await ensureLeadListImportRepositorySchema();
|
|
@@ -25832,10 +25835,10 @@ leadListEnrichmentApp.post("/jobs", createApiKeyAuth(), async (c) => {
|
|
|
25832
25835
|
const failure2 = inputError(error);
|
|
25833
25836
|
return c.json({ error: failure2.message, error_code: failure2.code, retryable: false, details: failure2.details }, 400);
|
|
25834
25837
|
}
|
|
25835
|
-
const
|
|
25838
|
+
const fingerprint5 = leadListEnrichmentFingerprint(input);
|
|
25836
25839
|
const existingJob = await getLeadListEnrichmentJobByIdempotencyKey(userId, key3.value);
|
|
25837
25840
|
if (existingJob) {
|
|
25838
|
-
if (existingJob.requestFingerprint !==
|
|
25841
|
+
if (existingJob.requestFingerprint !== fingerprint5) {
|
|
25839
25842
|
return c.json({
|
|
25840
25843
|
error: "Idempotency-Key was already used for different lead-list enrichment inputs.",
|
|
25841
25844
|
error_code: "idempotency_conflict",
|
|
@@ -25859,7 +25862,7 @@ leadListEnrichmentApp.post("/jobs", createApiKeyAuth(), async (c) => {
|
|
|
25859
25862
|
id: existingJob?.id ?? newJobId(),
|
|
25860
25863
|
userId,
|
|
25861
25864
|
idempotencyKey: key3.value,
|
|
25862
|
-
requestFingerprint:
|
|
25865
|
+
requestFingerprint: fingerprint5,
|
|
25863
25866
|
input,
|
|
25864
25867
|
holdMc,
|
|
25865
25868
|
debitKey: debitKeyFor2(userId, key3.value),
|
|
@@ -33507,17 +33510,6 @@ function evaluateAnalyticsEventValueRule(input, context) {
|
|
|
33507
33510
|
}
|
|
33508
33511
|
|
|
33509
33512
|
// src/api/analytics-contracts.ts
|
|
33510
|
-
var AnalyticsRevenueProviderSchema = z32.literal("stripe_revenue");
|
|
33511
|
-
var AnalyticsRevenueConnectionReferenceSchema = z32.object({
|
|
33512
|
-
provider: AnalyticsRevenueProviderSchema,
|
|
33513
|
-
serviceConnectionRef: z32.string().trim().min(1).max(240),
|
|
33514
|
-
role: z32.enum(["primary", "observation"]),
|
|
33515
|
-
outcomeFamily: z32.literal("subscription_revenue")
|
|
33516
|
-
}).strict().superRefine((value, context) => {
|
|
33517
|
-
if (/(?:secret|token|password|api[_-]?key|authorization)/i.test(value.serviceConnectionRef)) {
|
|
33518
|
-
context.addIssue({ code: "custom", path: ["serviceConnectionRef"], message: "Use an authorized connection reference, never a credential." });
|
|
33519
|
-
}
|
|
33520
|
-
});
|
|
33521
33513
|
var AnalyticsClickIdSchema = z32.object({
|
|
33522
33514
|
gclid: z32.string().trim().max(500).optional(),
|
|
33523
33515
|
gbraid: z32.string().trim().max(500).optional(),
|
|
@@ -34536,7 +34528,8 @@ async function claimAnalyticsCrmOutboundJobs(input) {
|
|
|
34536
34528
|
`WITH due AS (
|
|
34537
34529
|
SELECT j.job_id FROM analytics_crm_outbound_jobs j
|
|
34538
34530
|
JOIN analytics_crm_outbound_policies p ON p.policy_id=j.policy_id
|
|
34539
|
-
WHERE p.enabled=true AND
|
|
34531
|
+
WHERE p.enabled=true AND p.provider NOT IN ('salesforce','pipedrive')
|
|
34532
|
+
AND ((j.state IN ('pending','retrying') AND j.next_attempt_at <= now()) OR
|
|
34540
34533
|
(j.state='running' AND j.lease_expires_at < now()))
|
|
34541
34534
|
ORDER BY coalesce(j.next_attempt_at,j.lease_expires_at),j.created_at FOR UPDATE OF j SKIP LOCKED LIMIT $1
|
|
34542
34535
|
)
|
|
@@ -34674,8 +34667,11 @@ async function settleAnalyticsCrmOutboundJob(input) {
|
|
|
34674
34667
|
}
|
|
34675
34668
|
async function listAnalyticsCrmOutboundReceipts(input) {
|
|
34676
34669
|
const result3 = await dbOrDefault(input.db).query(
|
|
34677
|
-
`SELECT r.* FROM analytics_crm_outbound_receipts r
|
|
34678
|
-
|
|
34670
|
+
`SELECT r.* FROM analytics_crm_outbound_receipts r
|
|
34671
|
+
JOIN analytics_crm_outbound_jobs j ON j.job_id=r.job_id
|
|
34672
|
+
JOIN analytics_crm_outbound_policies p ON p.policy_id=j.policy_id
|
|
34673
|
+
WHERE j.site_id=$1 AND p.provider NOT IN ('salesforce','pipedrive')
|
|
34674
|
+
ORDER BY r.occurred_at DESC LIMIT $2`,
|
|
34679
34675
|
[input.siteId, Math.max(1, Math.min(100, input.limit ?? 25))]
|
|
34680
34676
|
);
|
|
34681
34677
|
return result3.rows.map((row) => AnalyticsCrmOutboundReceiptSchema.parse({
|
|
@@ -34700,6 +34696,12 @@ var ANALYTICS_CRM_PROVIDER_IDS = [
|
|
|
34700
34696
|
"pipedrive",
|
|
34701
34697
|
"keap"
|
|
34702
34698
|
];
|
|
34699
|
+
var ANALYTICS_PUBLIC_CRM_PROVIDER_IDS = [
|
|
34700
|
+
"hubspot",
|
|
34701
|
+
"highlevel",
|
|
34702
|
+
"zoho",
|
|
34703
|
+
"keap"
|
|
34704
|
+
];
|
|
34703
34705
|
var operations = (enabled) => {
|
|
34704
34706
|
const result3 = {
|
|
34705
34707
|
describe: false,
|
|
@@ -36994,7 +36996,11 @@ function safeAnalyticsConnectionErrorCode(error) {
|
|
|
36994
36996
|
function analyticsConnectionSetupProfile(input) {
|
|
36995
36997
|
const provider = input.provider;
|
|
36996
36998
|
const profile = CONNECTION_SETUP[provider];
|
|
36997
|
-
if (!profile) throw new AnalyticsRepositoryError(
|
|
36999
|
+
if (!profile) throw new AnalyticsRepositoryError(
|
|
37000
|
+
"analytics_connection_provider_unavailable",
|
|
37001
|
+
"This analytics connection is not available in the current public release.",
|
|
37002
|
+
404
|
|
37003
|
+
);
|
|
36998
37004
|
return {
|
|
36999
37005
|
callbackPath: `/analytics/v1/webhooks/${provider}/${input.connectionId}`,
|
|
37000
37006
|
expectedEventTypes: [...profile.expectedEventTypes],
|
|
@@ -46532,7 +46538,7 @@ function xmlEscape(value) {
|
|
|
46532
46538
|
import { Hono as Hono36 } from "hono";
|
|
46533
46539
|
import { createMiddleware as createMiddleware4 } from "hono/factory";
|
|
46534
46540
|
import { z as z43 } from "zod";
|
|
46535
|
-
import { createHash as
|
|
46541
|
+
import { createHash as createHash43, randomUUID as randomUUID38 } from "crypto";
|
|
46536
46542
|
import Papa5 from "papaparse";
|
|
46537
46543
|
|
|
46538
46544
|
// src/api/analytics-manual-imports.ts
|
|
@@ -46652,10 +46658,10 @@ function previewAnalyticsManualImport(input) {
|
|
|
46652
46658
|
});
|
|
46653
46659
|
}
|
|
46654
46660
|
const headers = parsed.meta.fields ?? [];
|
|
46655
|
-
const
|
|
46661
|
+
const fingerprint5 = createHash31("sha256").update(canonical({ sourceSystem: parsedInput.sourceSystem, filename: parsedInput.filename, mapping: parsedInput.mapping, rows })).digest("hex");
|
|
46656
46662
|
return {
|
|
46657
46663
|
schemaVersion: 1,
|
|
46658
|
-
fingerprint:
|
|
46664
|
+
fingerprint: fingerprint5,
|
|
46659
46665
|
headers,
|
|
46660
46666
|
totalRows: parsed.data.length,
|
|
46661
46667
|
acceptedRows: rows.length,
|
|
@@ -48561,7 +48567,7 @@ async function callMainOwnedExportPage(identity, input) {
|
|
|
48561
48567
|
});
|
|
48562
48568
|
}
|
|
48563
48569
|
if (connection.providerConfigKey === "google-mail" && input.dataset === "emails") {
|
|
48564
|
-
const { GmailService: GmailService2 } = await import("./gmail-service-
|
|
48570
|
+
const { GmailService: GmailService2 } = await import("./gmail-service-BTRAHGJS.js");
|
|
48565
48571
|
const service = new GmailService2();
|
|
48566
48572
|
const ownerId3 = createHash32("sha256").update(identity.toLowerCase()).digest("hex").slice(0, 24);
|
|
48567
48573
|
const after = Math.floor(Date.parse(input.from) / 1e3);
|
|
@@ -49327,13 +49333,11 @@ async function readSaasChecklist(siteId, db) {
|
|
|
49327
49333
|
if (site.rows[0]?.business_model !== "saas") return [];
|
|
49328
49334
|
const definitions = [
|
|
49329
49335
|
{ key: "tag", label: "Global tag", nextAction: "Install and verify the X-Ray tag across every production surface.", sql: `SELECT p.id::text AS evidence_id,CASE WHEN EXISTS(SELECT 1 FROM analytics_ingestion_receipts r WHERE r.site_id=p.site_id AND r.accepted_count>0) THEN 'complete' ELSE 'in_progress' END AS status FROM analytics_pixels p WHERE p.site_id=$1 AND p.status='active' AND EXISTS(SELECT 1 FROM analytics_pixel_domains d WHERE d.pixel_id=p.id AND d.state='approved') LIMIT 1` },
|
|
49330
|
-
{ key: "ads", label: "Ad
|
|
49336
|
+
{ key: "ads", label: "Ad-source capture", nextAction: "Preserve consent-eligible campaign and click identifiers on landing events.", sql: `SELECT id::text AS evidence_id,'complete' AS status FROM analytics_attribution_touches WHERE site_id=$1 AND click_ids<>'{}'::jsonb LIMIT 1` },
|
|
49331
49337
|
{ key: "lifecycle", label: "Lifecycle channels", nextAction: "Configure signup, account, checkout, email, and product lifecycle events.", sql: `SELECT id::text AS evidence_id,'complete' AS status FROM analytics_event_definitions WHERE site_id=$1 AND status='active' AND event_name ~ '(signup|account|checkout|trial|demo)' LIMIT 1` },
|
|
49332
|
-
{ key: "
|
|
49333
|
-
{ key: "calls_demos", label: "Calls and demos", nextAction: "Connect a call or CRM source when demos participate in the sales journey.", sql: `SELECT id::text AS evidence_id,CASE WHEN readiness IN ('verified','live') THEN 'complete' WHEN readiness='configured_unverified' THEN 'in_progress' WHEN readiness='degraded' THEN 'blocked' ELSE 'unavailable' END AS status FROM analytics_connections WHERE site_id=$1 AND provider IN ('callrail','calltrackingmetrics','twilio','hubspot','highlevel','generic_crm') ORDER BY updated_at DESC LIMIT 1` },
|
|
49334
|
-
{ key: "currency_timezone", label: "Currency and timezone", nextAction: "Confirm the reporting timezone and collect one authoritative currency receipt.", sql: `SELECT s.id::text AS evidence_id,CASE WHEN s.timezone<>'' AND EXISTS(SELECT 1 FROM analytics_conversions c WHERE c.site_id=s.id AND c.currency ~ '^[A-Z]{3}$') THEN 'complete' ELSE 'in_progress' END AS status FROM analytics_sites s WHERE s.id=$1` },
|
|
49338
|
+
{ key: "currency_timezone", label: "Currency and timezone", nextAction: "Confirm the reporting timezone and the ISO currency attached to measured value events.", sql: `SELECT s.id::text AS evidence_id,CASE WHEN s.timezone<>'' AND EXISTS(SELECT 1 FROM analytics_conversions c WHERE c.site_id=s.id AND c.currency ~ '^[A-Z]{3}$') THEN 'complete' ELSE 'in_progress' END AS status FROM analytics_sites s WHERE s.id=$1` },
|
|
49335
49339
|
{ key: "consent", label: "Consent", nextAction: "Publish the analytics and customer-reported measurement disclosures.", sql: `SELECT min(id::text) AS evidence_id,CASE WHEN count(*) FILTER(WHERE purpose='site_analytics' AND enabled AND retired_at IS NULL)>0 THEN 'complete' ELSE 'in_progress' END AS status FROM analytics_purpose_policies WHERE site_id=$1 HAVING count(*)>0` },
|
|
49336
|
-
{ key: "
|
|
49340
|
+
{ key: "observed_event_verification", label: "Observed outcome event", nextAction: "Verify at least one configured outcome event is observed; browser evidence does not prove paid revenue.", sql: `SELECT c.id::text AS evidence_id,'complete' AS status FROM analytics_conversions c WHERE c.site_id=$1 LIMIT 1` }
|
|
49337
49341
|
];
|
|
49338
49342
|
const rows = await Promise.all(definitions.map((definition) => db.query(definition.sql, [siteId])));
|
|
49339
49343
|
return definitions.map((definition, index) => {
|
|
@@ -50147,8 +50151,8 @@ function buildAnalyticsSiteInventory(input) {
|
|
|
50147
50151
|
evidenceIds: [...new Set(input.routes.flatMap((route) => route.evidenceIds))]
|
|
50148
50152
|
});
|
|
50149
50153
|
}
|
|
50150
|
-
const
|
|
50151
|
-
return { schemaVersion: 1, ...input, diagnoses, fingerprint: stableFingerprint2(
|
|
50154
|
+
const stable2 = { startUrl: input.startUrl, routes: input.routes, surfaces: input.surfaces, diagnoses };
|
|
50155
|
+
return { schemaVersion: 1, ...input, diagnoses, fingerprint: stableFingerprint2(stable2) };
|
|
50152
50156
|
}
|
|
50153
50157
|
|
|
50154
50158
|
// src/api/analytics-site-setup.ts
|
|
@@ -50416,13 +50420,11 @@ var AnalyticsSiteSetupService = class {
|
|
|
50416
50420
|
measurementPlan: { eventRuleCount: candidates.length, recommendedRuleCount: candidates.filter((candidate) => candidate.disposition === "recommended").length, approvalRequired: true },
|
|
50417
50421
|
...outcomePlan.businessModel === "saas" ? { saasChecklist: [
|
|
50418
50422
|
{ key: "tag", state: tagReady ? "complete" : routesWithPixel > 0 ? "in_progress" : "not_configured", evidenceIds: input.inventory.routes.flatMap((route) => route.evidenceIds), nextAction: tagReady ? null : "Install and verify the X-Ray tag across every rendering surface." },
|
|
50419
|
-
{ key: "ads", state: input.inventory.routes.some((route) => route.semanticTags > 0) ? "in_progress" : "not_configured", evidenceIds: [], nextAction: "
|
|
50423
|
+
{ key: "ads", state: input.inventory.routes.some((route) => route.semanticTags > 0) ? "in_progress" : "not_configured", evidenceIds: [], nextAction: "Preserve consent-eligible campaign and click identifiers through the installed tag." },
|
|
50420
50424
|
{ key: "lifecycle", state: candidates.some((candidate) => /signup|account|checkout/i.test(candidate.eventName)) ? "in_progress" : "not_configured", evidenceIds: candidates.map((candidate) => candidate.candidateId), nextAction: "Tag signup, account, and checkout lifecycle actions." },
|
|
50421
|
-
{ key: "revenue", state: "not_configured", evidenceIds: [], nextAction: "Connect and verify one primary subscription revenue authority." },
|
|
50422
|
-
{ key: "calls_demos", state: "not_configured", evidenceIds: [], nextAction: "Connect call or CRM evidence when demos are part of the sales journey." },
|
|
50423
50425
|
{ key: "currency_timezone", state: "not_configured", evidenceIds: [], nextAction: "Confirm reporting currency and IANA timezone." },
|
|
50424
50426
|
{ key: "consent", state: "in_progress", evidenceIds: input.inventory.routes.flatMap((route) => route.evidenceIds), nextAction: "Publish consent purposes before collecting analytics or reported influence." },
|
|
50425
|
-
{ key: "
|
|
50427
|
+
{ key: "observed_event_verification", state: candidates.some((candidate) => candidate.disposition === "recommended") ? "in_progress" : "not_configured", evidenceIds: candidates.filter((candidate) => candidate.disposition === "recommended").map((candidate) => candidate.candidateId), nextAction: "Verify at least one configured outcome event; browser evidence does not prove paid revenue." }
|
|
50426
50428
|
] } : {},
|
|
50427
50429
|
readiness: readiness2,
|
|
50428
50430
|
backlog: (input.backlog ?? []).map((item) => ({ ...item, revision })),
|
|
@@ -50544,390 +50546,8 @@ var AnalyticsSiteSetupService = class {
|
|
|
50544
50546
|
}
|
|
50545
50547
|
};
|
|
50546
50548
|
|
|
50547
|
-
// src/api/analytics-revenue-setup.ts
|
|
50548
|
-
import { createHash as createHash40, randomUUID as randomUUID33 } from "crypto";
|
|
50549
|
-
|
|
50550
|
-
// src/api/analytics-revenue-authority.ts
|
|
50551
|
-
import { createHash as createHash39, createHmac as createHmac12, randomUUID as randomUUID32 } from "crypto";
|
|
50552
|
-
function requiredText2(value, name, maximum) {
|
|
50553
|
-
if (typeof value !== "string" || !value.trim() || value.trim().length > maximum)
|
|
50554
|
-
throw new AnalyticsRepositoryError("analytics_revenue_outcome_invalid", `${name} is invalid.`);
|
|
50555
|
-
return value.trim();
|
|
50556
|
-
}
|
|
50557
|
-
function opaqueProviderRef(value, name) {
|
|
50558
|
-
const normalized = requiredText2(value, name, 300);
|
|
50559
|
-
if (normalized.includes("@")) {
|
|
50560
|
-
throw new AnalyticsRepositoryError(
|
|
50561
|
-
"analytics_revenue_customer_binding_required",
|
|
50562
|
-
`${name} must be an opaque provider reference; email is not identity evidence.`
|
|
50563
|
-
);
|
|
50564
|
-
}
|
|
50565
|
-
return normalized;
|
|
50566
|
-
}
|
|
50567
|
-
async function setPrimaryRevenueAuthority(input) {
|
|
50568
|
-
const db = input.db ?? getAnalyticsPool();
|
|
50569
|
-
const client2 = await db.connect();
|
|
50570
|
-
const provider = requiredText2(input.provider, "provider", 80).toLowerCase();
|
|
50571
|
-
const sourceAccountRef = opaqueProviderRef(input.sourceAccountRef, "sourceAccountRef");
|
|
50572
|
-
const outcomeFamily = input.outcomeFamily ?? "subscription_revenue";
|
|
50573
|
-
const role = input.role ?? "primary";
|
|
50574
|
-
const state2 = input.state ?? "configured_unverified";
|
|
50575
|
-
try {
|
|
50576
|
-
await client2.query("BEGIN");
|
|
50577
|
-
await requireAnalyticsEditor(client2, input.siteId, input.userId);
|
|
50578
|
-
if (role === "primary") {
|
|
50579
|
-
await client2.query(
|
|
50580
|
-
`UPDATE analytics_revenue_authorities
|
|
50581
|
-
SET authority_role='observation',current_revision=current_revision+1,
|
|
50582
|
-
updated_at=now()
|
|
50583
|
-
WHERE site_id=$1 AND outcome_family=$2 AND authority_role='primary'
|
|
50584
|
-
AND state<>'disabled'
|
|
50585
|
-
AND NOT (provider=$3 AND source_account_ref=$4)`,
|
|
50586
|
-
[input.siteId, outcomeFamily, provider, sourceAccountRef]
|
|
50587
|
-
);
|
|
50588
|
-
}
|
|
50589
|
-
const authorityId = input.authorityId ?? randomUUID32();
|
|
50590
|
-
const result3 = await client2.query(
|
|
50591
|
-
`INSERT INTO analytics_revenue_authorities(
|
|
50592
|
-
authority_id,site_id,provider,source_account_ref,connection_id,
|
|
50593
|
-
outcome_family,authority_role,state,current_revision,created_by_user_id
|
|
50594
|
-
) VALUES($1,$2,$3,$4,$5,$6,$7,$8,1,$9)
|
|
50595
|
-
ON CONFLICT(site_id,provider,source_account_ref,outcome_family)
|
|
50596
|
-
DO UPDATE SET connection_id=EXCLUDED.connection_id,
|
|
50597
|
-
authority_role=EXCLUDED.authority_role,state=EXCLUDED.state,
|
|
50598
|
-
current_revision=analytics_revenue_authorities.current_revision+1,
|
|
50599
|
-
updated_at=now(),disabled_at=CASE WHEN EXCLUDED.state='disabled' THEN now() ELSE NULL END
|
|
50600
|
-
RETURNING authority_id,authority_role,state,current_revision`,
|
|
50601
|
-
[
|
|
50602
|
-
authorityId,
|
|
50603
|
-
input.siteId,
|
|
50604
|
-
provider,
|
|
50605
|
-
sourceAccountRef,
|
|
50606
|
-
input.connectionId ?? null,
|
|
50607
|
-
outcomeFamily,
|
|
50608
|
-
role,
|
|
50609
|
-
state2,
|
|
50610
|
-
input.userId
|
|
50611
|
-
]
|
|
50612
|
-
);
|
|
50613
|
-
await client2.query("COMMIT");
|
|
50614
|
-
return {
|
|
50615
|
-
authorityId: result3.rows[0].authority_id,
|
|
50616
|
-
role: result3.rows[0].authority_role,
|
|
50617
|
-
state: result3.rows[0].state,
|
|
50618
|
-
revision: result3.rows[0].current_revision
|
|
50619
|
-
};
|
|
50620
|
-
} catch (error) {
|
|
50621
|
-
await client2.query("ROLLBACK").catch(() => void 0);
|
|
50622
|
-
throw error;
|
|
50623
|
-
} finally {
|
|
50624
|
-
client2.release();
|
|
50625
|
-
}
|
|
50626
|
-
}
|
|
50627
|
-
|
|
50628
|
-
// src/api/analytics-revenue-setup.ts
|
|
50629
|
-
function stable(value) {
|
|
50630
|
-
if (Array.isArray(value)) return value.map(stable);
|
|
50631
|
-
if (!value || typeof value !== "object") return value;
|
|
50632
|
-
return Object.fromEntries(Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key3, item]) => [key3, stable(item)]));
|
|
50633
|
-
}
|
|
50634
|
-
function fingerprint4(value) {
|
|
50635
|
-
return createHash40("sha256").update(JSON.stringify(stable(value))).digest("hex");
|
|
50636
|
-
}
|
|
50637
|
-
function requiredText3(value, field, max = 240) {
|
|
50638
|
-
if (typeof value !== "string" || !value.trim()) {
|
|
50639
|
-
throw new AnalyticsRepositoryError("analytics_revenue_setup_invalid", `${field} is required.`, 400);
|
|
50640
|
-
}
|
|
50641
|
-
const normalized = value.trim();
|
|
50642
|
-
if (normalized.length > max) {
|
|
50643
|
-
throw new AnalyticsRepositoryError("analytics_revenue_setup_invalid", `${field} exceeds its size limit.`, 400);
|
|
50644
|
-
}
|
|
50645
|
-
return normalized;
|
|
50646
|
-
}
|
|
50647
|
-
function safeConnection(connection) {
|
|
50648
|
-
if (!connection || connection.lifecycleStatus !== "connected") {
|
|
50649
|
-
throw new AnalyticsRepositoryError(
|
|
50650
|
-
"analytics_revenue_connection_unavailable",
|
|
50651
|
-
"Choose a connected Stripe revenue account before continuing.",
|
|
50652
|
-
409
|
|
50653
|
-
);
|
|
50654
|
-
}
|
|
50655
|
-
if (connection.providerConfigKey !== "stripe_revenue") {
|
|
50656
|
-
throw new AnalyticsRepositoryError(
|
|
50657
|
-
"analytics_revenue_connection_provider_invalid",
|
|
50658
|
-
"The selected connection is not an approved Stripe revenue connection.",
|
|
50659
|
-
409
|
|
50660
|
-
);
|
|
50661
|
-
}
|
|
50662
|
-
if (!connection.providerAccountId || !/^acct_[A-Za-z0-9]+$/.test(connection.providerAccountId) || !connection.providerIdentityCheckedAt) {
|
|
50663
|
-
throw new AnalyticsRepositoryError(
|
|
50664
|
-
"analytics_revenue_provider_identity_unverified",
|
|
50665
|
-
"Stripe account identity must be verified before revenue setup.",
|
|
50666
|
-
409
|
|
50667
|
-
);
|
|
50668
|
-
}
|
|
50669
|
-
return connection;
|
|
50670
|
-
}
|
|
50671
|
-
function publicPlan2(row) {
|
|
50672
|
-
return {
|
|
50673
|
-
...row.plan,
|
|
50674
|
-
setupId: row.setup_id,
|
|
50675
|
-
siteId: row.site_id,
|
|
50676
|
-
revision: row.revision,
|
|
50677
|
-
state: row.state,
|
|
50678
|
-
authorityId: row.authority_id,
|
|
50679
|
-
createdAt: new Date(row.created_at).toISOString()
|
|
50680
|
-
};
|
|
50681
|
-
}
|
|
50682
|
-
async function currentRow(db, siteId, setupId, lock = false) {
|
|
50683
|
-
const result3 = await db.query(
|
|
50684
|
-
`SELECT setup_id,site_id,revision,authority_id,state,plan,created_at
|
|
50685
|
-
FROM analytics_revenue_setup_revisions
|
|
50686
|
-
WHERE site_id=$1 AND setup_id=$2
|
|
50687
|
-
ORDER BY revision DESC LIMIT 1${lock ? " FOR UPDATE" : ""}`,
|
|
50688
|
-
[siteId, setupId]
|
|
50689
|
-
);
|
|
50690
|
-
if (!result3.rows[0]) {
|
|
50691
|
-
throw new AnalyticsRepositoryError("analytics_revenue_setup_not_found", "Revenue setup not found.", 404);
|
|
50692
|
-
}
|
|
50693
|
-
return result3.rows[0];
|
|
50694
|
-
}
|
|
50695
|
-
async function idempotentReceipt(input) {
|
|
50696
|
-
const result3 = await input.db.query(
|
|
50697
|
-
`SELECT request_fingerprint,receipt FROM analytics_revenue_setup_receipts
|
|
50698
|
-
WHERE site_id=$1 AND idempotency_key=$2`,
|
|
50699
|
-
[input.siteId, input.idempotencyKey]
|
|
50700
|
-
);
|
|
50701
|
-
const receipt4 = result3.rows[0];
|
|
50702
|
-
if (!receipt4) return null;
|
|
50703
|
-
if (receipt4.request_fingerprint !== input.requestFingerprint) {
|
|
50704
|
-
throw new AnalyticsRepositoryError(
|
|
50705
|
-
"analytics_revenue_setup_idempotency_conflict",
|
|
50706
|
-
"The idempotency key was reused with a different request.",
|
|
50707
|
-
409
|
|
50708
|
-
);
|
|
50709
|
-
}
|
|
50710
|
-
return receipt4.receipt.setup;
|
|
50711
|
-
}
|
|
50712
|
-
async function appendReceipt(input) {
|
|
50713
|
-
await input.db.query(
|
|
50714
|
-
`INSERT INTO analytics_revenue_setup_receipts(
|
|
50715
|
-
receipt_id,setup_id,site_id,revision,operation,status,idempotency_key,request_fingerprint,receipt
|
|
50716
|
-
) VALUES($1,$2,$3,$4,$5,$6,$7,$8,$9::jsonb)`,
|
|
50717
|
-
[
|
|
50718
|
-
randomUUID33(),
|
|
50719
|
-
input.setup.setupId,
|
|
50720
|
-
input.setup.siteId,
|
|
50721
|
-
input.setup.revision,
|
|
50722
|
-
input.operation,
|
|
50723
|
-
input.setup.state,
|
|
50724
|
-
input.idempotencyKey,
|
|
50725
|
-
input.requestFingerprint,
|
|
50726
|
-
JSON.stringify({ setup: input.setup })
|
|
50727
|
-
]
|
|
50728
|
-
);
|
|
50729
|
-
}
|
|
50730
|
-
async function prepareAnalyticsRevenueSetup(input) {
|
|
50731
|
-
const db = input.db ?? getAnalyticsPool();
|
|
50732
|
-
const serviceConnectionRef = requiredText3(input.serviceConnectionRef, "serviceConnectionRef");
|
|
50733
|
-
const role = input.role ?? "primary";
|
|
50734
|
-
const idempotencyKey4 = requiredText3(input.idempotencyKey, "idempotencyKey");
|
|
50735
|
-
const requestFingerprint3 = fingerprint4({ siteId: input.siteId, serviceConnectionRef, role });
|
|
50736
|
-
await requireAnalyticsEditor(db, input.siteId, input.userId);
|
|
50737
|
-
const replay = await idempotentReceipt({ db, siteId: input.siteId, idempotencyKey: idempotencyKey4, requestFingerprint: requestFingerprint3 });
|
|
50738
|
-
if (replay) return replay;
|
|
50739
|
-
const connection = safeConnection(await getOwnedServiceConnection(input.ownerIdentity, serviceConnectionRef));
|
|
50740
|
-
const setupId = randomUUID33();
|
|
50741
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
50742
|
-
const plan = {
|
|
50743
|
-
schemaVersion: 1,
|
|
50744
|
-
setupId,
|
|
50745
|
-
siteId: input.siteId,
|
|
50746
|
-
revision: 1,
|
|
50747
|
-
state: "prepared",
|
|
50748
|
-
authorityId: null,
|
|
50749
|
-
provider: "stripe_revenue",
|
|
50750
|
-
serviceConnectionRef,
|
|
50751
|
-
providerAccountRef: connection.providerAccountId,
|
|
50752
|
-
providerIdentityVerifiedAt: connection.providerIdentityCheckedAt,
|
|
50753
|
-
outcomeFamily: "subscription_revenue",
|
|
50754
|
-
role,
|
|
50755
|
-
eventFamilies: ["subscription", "invoice", "refund", "credit_note"],
|
|
50756
|
-
verification: { status: "not_started", receiptRef: null, evidenceKind: null, testClass: null },
|
|
50757
|
-
nextAction: "Review the Stripe account, authority role, and event families, then apply this exact revision.",
|
|
50758
|
-
createdAt: now
|
|
50759
|
-
};
|
|
50760
|
-
const client2 = await db.connect();
|
|
50761
|
-
try {
|
|
50762
|
-
await client2.query("BEGIN");
|
|
50763
|
-
await requireAnalyticsEditor(client2, input.siteId, input.userId);
|
|
50764
|
-
const concurrentReplay = await idempotentReceipt({ db: client2, siteId: input.siteId, idempotencyKey: idempotencyKey4, requestFingerprint: requestFingerprint3 });
|
|
50765
|
-
if (concurrentReplay) {
|
|
50766
|
-
await client2.query("COMMIT");
|
|
50767
|
-
return concurrentReplay;
|
|
50768
|
-
}
|
|
50769
|
-
await insertAnalyticsRevenueSetupRevision({
|
|
50770
|
-
db: client2,
|
|
50771
|
-
setupId,
|
|
50772
|
-
siteId: input.siteId,
|
|
50773
|
-
expectedRevision: 0,
|
|
50774
|
-
state: plan.state,
|
|
50775
|
-
plan,
|
|
50776
|
-
requestFingerprint: requestFingerprint3,
|
|
50777
|
-
createdByUserId: input.userId
|
|
50778
|
-
});
|
|
50779
|
-
await appendReceipt({ db: client2, setup: plan, operation: "prepare", idempotencyKey: idempotencyKey4, requestFingerprint: requestFingerprint3 });
|
|
50780
|
-
await client2.query("COMMIT");
|
|
50781
|
-
return plan;
|
|
50782
|
-
} catch (error) {
|
|
50783
|
-
await client2.query("ROLLBACK").catch(() => void 0);
|
|
50784
|
-
throw error;
|
|
50785
|
-
} finally {
|
|
50786
|
-
client2.release();
|
|
50787
|
-
}
|
|
50788
|
-
}
|
|
50789
|
-
async function currentAnalyticsRevenueSetup(input) {
|
|
50790
|
-
const db = input.db ?? getAnalyticsPool();
|
|
50791
|
-
await requireAnalyticsAccess(db, input.siteId, input.userId);
|
|
50792
|
-
return publicPlan2(await currentRow(db, input.siteId, input.setupId));
|
|
50793
|
-
}
|
|
50794
|
-
async function currentAnalyticsRevenueSetupForOwner(input) {
|
|
50795
|
-
const db = input.db ?? getAnalyticsPool();
|
|
50796
|
-
const result3 = await db.query(
|
|
50797
|
-
`SELECT revision_row.setup_id,revision_row.site_id,revision_row.revision,
|
|
50798
|
-
revision_row.authority_id,revision_row.state,revision_row.plan,revision_row.created_at
|
|
50799
|
-
FROM analytics_revenue_setup_revisions revision_row
|
|
50800
|
-
JOIN analytics_site_grants grant_row
|
|
50801
|
-
ON grant_row.site_id=revision_row.site_id
|
|
50802
|
-
AND grant_row.user_id=$2 AND grant_row.role='owner'
|
|
50803
|
-
WHERE revision_row.setup_id=$1
|
|
50804
|
-
ORDER BY revision_row.revision DESC LIMIT 1`,
|
|
50805
|
-
[input.setupId, input.userId]
|
|
50806
|
-
);
|
|
50807
|
-
if (!result3.rows[0]) {
|
|
50808
|
-
throw new AnalyticsRepositoryError(
|
|
50809
|
-
"analytics_revenue_setup_not_found",
|
|
50810
|
-
"No owner-authorized revenue setup was found.",
|
|
50811
|
-
404
|
|
50812
|
-
);
|
|
50813
|
-
}
|
|
50814
|
-
return publicPlan2(result3.rows[0]);
|
|
50815
|
-
}
|
|
50816
|
-
async function applyAnalyticsRevenueSetup(input) {
|
|
50817
|
-
const db = input.db ?? getAnalyticsPool();
|
|
50818
|
-
await requireAnalyticsEditor(db, input.siteId, input.userId);
|
|
50819
|
-
const idempotencyKey4 = requiredText3(input.idempotencyKey, "idempotencyKey");
|
|
50820
|
-
const requestFingerprint3 = fingerprint4({ setupId: input.setupId, revision: input.revision, confirmed: input.confirmed });
|
|
50821
|
-
const replay = await idempotentReceipt({ db, siteId: input.siteId, idempotencyKey: idempotencyKey4, requestFingerprint: requestFingerprint3 });
|
|
50822
|
-
if (replay) return replay;
|
|
50823
|
-
const current = publicPlan2(await currentRow(db, input.siteId, input.setupId));
|
|
50824
|
-
if (current.revision !== input.revision) {
|
|
50825
|
-
throw new AnalyticsRepositoryError("analytics_revenue_setup_stale_revision", `Revenue setup revision ${input.revision} is stale; current revision is ${current.revision}.`, 409);
|
|
50826
|
-
}
|
|
50827
|
-
const connection = safeConnection(await getOwnedServiceConnection(input.ownerIdentity, current.serviceConnectionRef));
|
|
50828
|
-
if (connection.providerAccountId !== current.providerAccountRef) {
|
|
50829
|
-
throw new AnalyticsRepositoryError("analytics_revenue_provider_identity_changed", "The connected Stripe account changed after setup preparation.", 409);
|
|
50830
|
-
}
|
|
50831
|
-
const authority = await setPrimaryRevenueAuthority({
|
|
50832
|
-
siteId: input.siteId,
|
|
50833
|
-
userId: input.userId,
|
|
50834
|
-
provider: current.provider,
|
|
50835
|
-
sourceAccountRef: current.providerAccountRef,
|
|
50836
|
-
outcomeFamily: current.outcomeFamily,
|
|
50837
|
-
role: current.role,
|
|
50838
|
-
state: "configured_unverified",
|
|
50839
|
-
db
|
|
50840
|
-
});
|
|
50841
|
-
const next = {
|
|
50842
|
-
...current,
|
|
50843
|
-
revision: current.revision + 1,
|
|
50844
|
-
state: "configured_unverified",
|
|
50845
|
-
authorityId: authority.authorityId,
|
|
50846
|
-
verification: { status: "missing_provider_receipt", receiptRef: null, evidenceKind: null, testClass: null },
|
|
50847
|
-
nextAction: "Run provider verification. X-Ray requires a signed webhook or reconciliation receipt from a non-customer test account."
|
|
50848
|
-
};
|
|
50849
|
-
await insertAnalyticsRevenueSetupRevision({
|
|
50850
|
-
db,
|
|
50851
|
-
setupId: next.setupId,
|
|
50852
|
-
siteId: next.siteId,
|
|
50853
|
-
expectedRevision: current.revision,
|
|
50854
|
-
authorityId: next.authorityId,
|
|
50855
|
-
state: next.state,
|
|
50856
|
-
plan: next,
|
|
50857
|
-
requestFingerprint: requestFingerprint3,
|
|
50858
|
-
createdByUserId: input.userId
|
|
50859
|
-
});
|
|
50860
|
-
await appendReceipt({ db, setup: next, operation: "apply", idempotencyKey: idempotencyKey4, requestFingerprint: requestFingerprint3 });
|
|
50861
|
-
return next;
|
|
50862
|
-
}
|
|
50863
|
-
async function verifyAnalyticsRevenueSetup(input) {
|
|
50864
|
-
const db = input.db ?? getAnalyticsPool();
|
|
50865
|
-
await requireAnalyticsEditor(db, input.siteId, input.userId);
|
|
50866
|
-
const idempotencyKey4 = requiredText3(input.idempotencyKey, "idempotencyKey");
|
|
50867
|
-
const requestFingerprint3 = fingerprint4({ setupId: input.setupId, revision: input.revision });
|
|
50868
|
-
const replay = await idempotentReceipt({ db, siteId: input.siteId, idempotencyKey: idempotencyKey4, requestFingerprint: requestFingerprint3 });
|
|
50869
|
-
if (replay) return replay;
|
|
50870
|
-
const current = publicPlan2(await currentRow(db, input.siteId, input.setupId));
|
|
50871
|
-
if (current.revision !== input.revision) {
|
|
50872
|
-
throw new AnalyticsRepositoryError("analytics_revenue_setup_stale_revision", `Revenue setup revision ${input.revision} is stale; current revision is ${current.revision}.`, 409);
|
|
50873
|
-
}
|
|
50874
|
-
if (!current.authorityId) {
|
|
50875
|
-
throw new AnalyticsRepositoryError("analytics_revenue_setup_not_applied", "Apply the revenue setup before verification.", 409);
|
|
50876
|
-
}
|
|
50877
|
-
const connection = safeConnection(await getOwnedServiceConnection(input.ownerIdentity, current.serviceConnectionRef));
|
|
50878
|
-
if (connection.providerAccountId !== current.providerAccountRef) {
|
|
50879
|
-
throw new AnalyticsRepositoryError("analytics_revenue_provider_identity_changed", "The connected Stripe account changed before verification.", 409);
|
|
50880
|
-
}
|
|
50881
|
-
const evidence = await db.query(
|
|
50882
|
-
`SELECT version.receipt_ref,
|
|
50883
|
-
CASE WHEN version.provenance->>'transport'='signed_webhook' THEN 'signed_webhook' ELSE 'reconciliation' END AS evidence_kind
|
|
50884
|
-
FROM analytics_authoritative_outcome_versions version
|
|
50885
|
-
JOIN analytics_authoritative_outcomes outcome
|
|
50886
|
-
ON outcome.site_id=version.site_id AND outcome.outcome_id=version.outcome_id
|
|
50887
|
-
WHERE version.site_id=$1 AND outcome.authority_id=$2
|
|
50888
|
-
AND version.provenance->>'transport' IN ('signed_webhook','reconciliation')
|
|
50889
|
-
AND version.provenance->>'test_class'='non_customer'
|
|
50890
|
-
ORDER BY version.observed_at DESC LIMIT 1`,
|
|
50891
|
-
[input.siteId, current.authorityId]
|
|
50892
|
-
);
|
|
50893
|
-
const receipt4 = evidence.rows[0];
|
|
50894
|
-
if (!receipt4) {
|
|
50895
|
-
throw new AnalyticsRepositoryError(
|
|
50896
|
-
"analytics_revenue_verification_receipt_required",
|
|
50897
|
-
"Verification requires a signed webhook or reconciliation receipt from an authorized non-customer account.",
|
|
50898
|
-
409
|
|
50899
|
-
);
|
|
50900
|
-
}
|
|
50901
|
-
await db.query(
|
|
50902
|
-
`UPDATE analytics_revenue_authorities
|
|
50903
|
-
SET state='live',current_revision=current_revision+1,updated_at=now()
|
|
50904
|
-
WHERE site_id=$1 AND authority_id=$2`,
|
|
50905
|
-
[input.siteId, current.authorityId]
|
|
50906
|
-
);
|
|
50907
|
-
const next = {
|
|
50908
|
-
...current,
|
|
50909
|
-
revision: current.revision + 1,
|
|
50910
|
-
state: "live",
|
|
50911
|
-
verification: { status: "live", receiptRef: receipt4.receipt_ref, evidenceKind: receipt4.evidence_kind, testClass: "non_customer" },
|
|
50912
|
-
nextAction: "Revenue authority is live. Monitor webhook and reconciliation health before relying on reporting."
|
|
50913
|
-
};
|
|
50914
|
-
await insertAnalyticsRevenueSetupRevision({
|
|
50915
|
-
db,
|
|
50916
|
-
setupId: next.setupId,
|
|
50917
|
-
siteId: next.siteId,
|
|
50918
|
-
expectedRevision: current.revision,
|
|
50919
|
-
authorityId: next.authorityId,
|
|
50920
|
-
state: next.state,
|
|
50921
|
-
plan: next,
|
|
50922
|
-
requestFingerprint: requestFingerprint3,
|
|
50923
|
-
createdByUserId: input.userId
|
|
50924
|
-
});
|
|
50925
|
-
await appendReceipt({ db, setup: next, operation: "verify", idempotencyKey: idempotencyKey4, requestFingerprint: requestFingerprint3 });
|
|
50926
|
-
return next;
|
|
50927
|
-
}
|
|
50928
|
-
|
|
50929
50549
|
// src/api/analytics-survey-attribution.ts
|
|
50930
|
-
import { createHash as
|
|
50550
|
+
import { createHash as createHash39, randomBytes as randomBytes5, randomUUID as randomUUID32 } from "crypto";
|
|
50931
50551
|
var CREDIT_SCALE = 1e6;
|
|
50932
50552
|
var REPORTED_IMPACT_METHODOLOGY_VERSION = "xray_observed_plus_reported_equal_selected_v1";
|
|
50933
50553
|
var TOKEN_BYTES = 32;
|
|
@@ -50945,14 +50565,14 @@ var AnalyticsSurveyAttributionError = class extends Error {
|
|
|
50945
50565
|
function fail3(code, message, status = 400) {
|
|
50946
50566
|
throw new AnalyticsSurveyAttributionError(code, message, status);
|
|
50947
50567
|
}
|
|
50948
|
-
function
|
|
50568
|
+
function requiredText2(value, field, max) {
|
|
50949
50569
|
if (typeof value !== "string" || !value.trim()) fail3("analytics_survey_invalid_input", `${field} is required.`);
|
|
50950
50570
|
const normalized = value.trim();
|
|
50951
50571
|
if (normalized.length > max) fail3("analytics_survey_invalid_input", `${field} must not exceed ${max} characters.`);
|
|
50952
50572
|
return normalized;
|
|
50953
50573
|
}
|
|
50954
50574
|
function optionId(value) {
|
|
50955
|
-
const normalized =
|
|
50575
|
+
const normalized = requiredText2(value, "optionId", 80).toLowerCase();
|
|
50956
50576
|
if (!/^[a-z][a-z0-9_-]{0,79}$/u.test(normalized)) {
|
|
50957
50577
|
fail3("analytics_survey_invalid_option", "Survey option IDs must be stable lowercase identifiers.");
|
|
50958
50578
|
}
|
|
@@ -50973,7 +50593,7 @@ function normalizeOptions(input) {
|
|
|
50973
50593
|
const id2 = optionId(raw.optionId);
|
|
50974
50594
|
if (seen.has(id2)) fail3("analytics_survey_duplicate_option", `Survey option ${id2} is duplicated.`);
|
|
50975
50595
|
seen.add(id2);
|
|
50976
|
-
return { optionId: id2, label:
|
|
50596
|
+
return { optionId: id2, label: requiredText2(raw.label, "option label", 160), position };
|
|
50977
50597
|
});
|
|
50978
50598
|
}
|
|
50979
50599
|
function normalizeOutcomeFamilies(values) {
|
|
@@ -50981,23 +50601,23 @@ function normalizeOutcomeFamilies(values) {
|
|
|
50981
50601
|
fail3("analytics_survey_invalid_outcomes", "At least one eligible outcome family is required.");
|
|
50982
50602
|
}
|
|
50983
50603
|
return [...new Set(values.map((value) => {
|
|
50984
|
-
const normalized =
|
|
50604
|
+
const normalized = requiredText2(value, "eligible outcome family", 80).toLowerCase();
|
|
50985
50605
|
if (!/^[a-z][a-z0-9_.-]{0,79}$/u.test(normalized)) {
|
|
50986
50606
|
fail3("analytics_survey_invalid_outcomes", `Invalid eligible outcome family ${normalized}.`);
|
|
50987
50607
|
}
|
|
50988
50608
|
return normalized;
|
|
50989
50609
|
}))].sort();
|
|
50990
50610
|
}
|
|
50991
|
-
function
|
|
50992
|
-
if (Array.isArray(value)) return value.map(
|
|
50611
|
+
function stable(value) {
|
|
50612
|
+
if (Array.isArray(value)) return value.map(stable);
|
|
50993
50613
|
if (!value || typeof value !== "object") return value;
|
|
50994
|
-
return Object.fromEntries(Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key3, item]) => [key3,
|
|
50614
|
+
return Object.fromEntries(Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key3, item]) => [key3, stable(item)]));
|
|
50995
50615
|
}
|
|
50996
|
-
function
|
|
50997
|
-
return
|
|
50616
|
+
function fingerprint4(value) {
|
|
50617
|
+
return createHash39("sha256").update(JSON.stringify(stable(value))).digest("hex");
|
|
50998
50618
|
}
|
|
50999
50619
|
function tokenDigest(value) {
|
|
51000
|
-
return
|
|
50620
|
+
return createHash39("sha256").update(value).digest("hex");
|
|
51001
50621
|
}
|
|
51002
50622
|
function opaqueToken(prefix) {
|
|
51003
50623
|
return `${prefix}_${randomBytes5(TOKEN_BYTES).toString("base64url")}`;
|
|
@@ -51052,23 +50672,23 @@ async function readSurvey(db, siteId, surveyId, lock = false, requestedRevision)
|
|
|
51052
50672
|
};
|
|
51053
50673
|
}
|
|
51054
50674
|
async function createPostPurchaseSurveyDraft(input) {
|
|
51055
|
-
const siteId =
|
|
51056
|
-
const idempotencyKey4 =
|
|
50675
|
+
const siteId = requiredText2(input.siteId, "siteId", 100);
|
|
50676
|
+
const idempotencyKey4 = requiredText2(input.idempotencyKey, "idempotencyKey", 200);
|
|
51057
50677
|
const options = normalizeOptions(input.options);
|
|
51058
50678
|
const record7 = {
|
|
51059
|
-
name:
|
|
51060
|
-
question:
|
|
50679
|
+
name: requiredText2(input.name, "name", 160),
|
|
50680
|
+
question: requiredText2(input.question, "question", 500),
|
|
51061
50681
|
selectionMode: input.selectionMode,
|
|
51062
50682
|
eligibleOutcomeFamilies: normalizeOutcomeFamilies(input.eligibleOutcomeFamilies),
|
|
51063
50683
|
exchangeTtlSeconds: ttl(input.exchangeTtlSeconds, "exchangeTtlSeconds"),
|
|
51064
50684
|
sessionTtlSeconds: ttl(input.sessionTtlSeconds, "sessionTtlSeconds"),
|
|
51065
|
-
approvedCopyId: input.approvedCopyId ?
|
|
50685
|
+
approvedCopyId: input.approvedCopyId ? requiredText2(input.approvedCopyId, "approvedCopyId", 200) : null,
|
|
51066
50686
|
options
|
|
51067
50687
|
};
|
|
51068
50688
|
if (record7.selectionMode !== "single" && record7.selectionMode !== "multiple") {
|
|
51069
50689
|
fail3("analytics_survey_invalid_selection_mode", "selectionMode must be single or multiple.");
|
|
51070
50690
|
}
|
|
51071
|
-
const requestFingerprint3 =
|
|
50691
|
+
const requestFingerprint3 = fingerprint4(record7);
|
|
51072
50692
|
return transaction(input.db, async (db) => {
|
|
51073
50693
|
const replay = await db.query(
|
|
51074
50694
|
`SELECT survey_id,create_request_fingerprint FROM analytics_post_purchase_surveys
|
|
@@ -51081,7 +50701,7 @@ async function createPostPurchaseSurveyDraft(input) {
|
|
|
51081
50701
|
}
|
|
51082
50702
|
return { ...await readSurvey(db, siteId, replay.rows[0].survey_id), created: false };
|
|
51083
50703
|
}
|
|
51084
|
-
const surveyId =
|
|
50704
|
+
const surveyId = randomUUID32();
|
|
51085
50705
|
await db.query(
|
|
51086
50706
|
`INSERT INTO analytics_post_purchase_surveys(
|
|
51087
50707
|
survey_id,site_id,current_revision,state,name,question,selection_mode,eligible_outcome_families,
|
|
@@ -51124,8 +50744,8 @@ async function transitionPostPurchaseSurvey(input) {
|
|
|
51124
50744
|
if (!Number.isInteger(input.expectedRevision) || input.expectedRevision < 1) {
|
|
51125
50745
|
fail3("analytics_survey_invalid_revision", "expectedRevision must be a positive integer.");
|
|
51126
50746
|
}
|
|
51127
|
-
const idempotencyKey4 =
|
|
51128
|
-
const requestFingerprint3 =
|
|
50747
|
+
const idempotencyKey4 = requiredText2(input.idempotencyKey, "idempotencyKey", 240);
|
|
50748
|
+
const requestFingerprint3 = fingerprint4({
|
|
51129
50749
|
surveyId: input.surveyId,
|
|
51130
50750
|
expectedRevision: input.expectedRevision,
|
|
51131
50751
|
nextState: input.nextState,
|
|
@@ -51157,7 +50777,7 @@ async function transitionPostPurchaseSurvey(input) {
|
|
|
51157
50777
|
if (!ALLOWED_TRANSITIONS[survey.state].includes(input.nextState)) {
|
|
51158
50778
|
fail3("analytics_survey_invalid_transition", `Survey state ${survey.state} cannot transition to ${input.nextState}.`, 409);
|
|
51159
50779
|
}
|
|
51160
|
-
const approvedCopyId = input.approvedCopyId ?
|
|
50780
|
+
const approvedCopyId = input.approvedCopyId ? requiredText2(input.approvedCopyId, "approvedCopyId", 200) : survey.approvedCopyId;
|
|
51161
50781
|
if (input.nextState === "published") {
|
|
51162
50782
|
if (!approvedCopyId) fail3("analytics_survey_copy_approval_required", "Published surveys require an approved disclosure copy ID.", 409);
|
|
51163
50783
|
if (survey.options.length < 2) fail3("analytics_survey_options_required", "Published surveys require at least two active options.", 409);
|
|
@@ -51198,7 +50818,7 @@ async function transitionPostPurchaseSurvey(input) {
|
|
|
51198
50818
|
});
|
|
51199
50819
|
}
|
|
51200
50820
|
async function exchangePostPurchaseSurveyCode(input) {
|
|
51201
|
-
const code =
|
|
50821
|
+
const code = requiredText2(input.exchangeCode, "exchangeCode", 200);
|
|
51202
50822
|
if (!code.startsWith("xse_")) fail3("analytics_survey_exchange_invalid", "The survey exchange code is invalid.", 404);
|
|
51203
50823
|
return transaction(input.db, async (db) => {
|
|
51204
50824
|
const now = new Date(input.now ?? (/* @__PURE__ */ new Date()).toISOString());
|
|
@@ -51227,14 +50847,14 @@ async function exchangePostPurchaseSurveyCode(input) {
|
|
|
51227
50847
|
});
|
|
51228
50848
|
}
|
|
51229
50849
|
async function redeemPostPurchaseSurveyInvite(input) {
|
|
51230
|
-
const sessionToken =
|
|
50850
|
+
const sessionToken = requiredText2(input.sessionToken, "sessionToken", 200);
|
|
51231
50851
|
if (!sessionToken.startsWith("xss_")) fail3("analytics_survey_session_invalid", "The survey session is invalid.", 404);
|
|
51232
50852
|
if (!Array.isArray(input.selectedOptionIds)) fail3("analytics_survey_invalid_response", "selectedOptionIds must be an array.");
|
|
51233
50853
|
const selectedOptionIds = [...new Set(input.selectedOptionIds.map(optionId))].sort();
|
|
51234
50854
|
if (selectedOptionIds.length === 0 || selectedOptionIds.length > 20) {
|
|
51235
50855
|
fail3("analytics_survey_invalid_response", "Select between one and twenty survey options.");
|
|
51236
50856
|
}
|
|
51237
|
-
const bodyFingerprint =
|
|
50857
|
+
const bodyFingerprint = fingerprint4({ selectedOptionIds });
|
|
51238
50858
|
return transaction(input.db, async (db) => {
|
|
51239
50859
|
const now = new Date(input.now ?? (/* @__PURE__ */ new Date()).toISOString());
|
|
51240
50860
|
if (!Number.isFinite(now.getTime())) fail3("analytics_survey_invalid_time", "now must be a valid timestamp.");
|
|
@@ -51276,7 +50896,7 @@ async function redeemPostPurchaseSurveyInvite(input) {
|
|
|
51276
50896
|
if (options.rows.length !== selectedOptionIds.length) {
|
|
51277
50897
|
fail3("analytics_survey_option_unavailable", "One or more selected survey options are unavailable.", 409);
|
|
51278
50898
|
}
|
|
51279
|
-
const responseId =
|
|
50899
|
+
const responseId = randomUUID32();
|
|
51280
50900
|
await db.query(
|
|
51281
50901
|
`INSERT INTO analytics_post_purchase_survey_responses(
|
|
51282
50902
|
response_id,site_id,survey_id,survey_revision,conversion_id,invite_id,body_fingerprint,submitted_at
|
|
@@ -51294,7 +50914,7 @@ async function redeemPostPurchaseSurveyInvite(input) {
|
|
|
51294
50914
|
);
|
|
51295
50915
|
const evidence = [];
|
|
51296
50916
|
for (const option of options.rows) {
|
|
51297
|
-
const evidenceId =
|
|
50917
|
+
const evidenceId = randomUUID32();
|
|
51298
50918
|
await db.query(
|
|
51299
50919
|
`INSERT INTO analytics_reported_influences(
|
|
51300
50920
|
evidence_id,site_id,response_id,conversion_id,survey_id,survey_revision,option_id,option_label
|
|
@@ -51526,7 +51146,7 @@ function buildObservedPlusReportedImpact(input) {
|
|
|
51526
51146
|
}
|
|
51527
51147
|
|
|
51528
51148
|
// src/api/analytics-provider-view-evidence.ts
|
|
51529
|
-
import { createHash as
|
|
51149
|
+
import { createHash as createHash40, randomUUID as randomUUID33 } from "crypto";
|
|
51530
51150
|
var ANALYTICS_VIEW_EVIDENCE_RESEARCH_DATE = "2026-09-01";
|
|
51531
51151
|
var ANALYTICS_VIEW_EVIDENCE_PROVIDERS = [
|
|
51532
51152
|
"meta",
|
|
@@ -51700,7 +51320,7 @@ var PostgresAnalyticsSiteSetupStore = class {
|
|
|
51700
51320
|
};
|
|
51701
51321
|
|
|
51702
51322
|
// src/api/analytics-product-health.ts
|
|
51703
|
-
import { createHash as
|
|
51323
|
+
import { createHash as createHash41, randomUUID as randomUUID34 } from "crypto";
|
|
51704
51324
|
var ANALYTICS_PRODUCT_MILESTONES = [
|
|
51705
51325
|
"xray_opened",
|
|
51706
51326
|
"setup_started",
|
|
@@ -51727,7 +51347,7 @@ function asIso2(value) {
|
|
|
51727
51347
|
}
|
|
51728
51348
|
function safeReference(kind, value) {
|
|
51729
51349
|
if (!value) return null;
|
|
51730
|
-
return `${kind}:${
|
|
51350
|
+
return `${kind}:${createHash41("sha256").update(value).digest("hex").slice(0, 16)}`;
|
|
51731
51351
|
}
|
|
51732
51352
|
function numberValue(value) {
|
|
51733
51353
|
const number = Number(value ?? 0);
|
|
@@ -51861,7 +51481,7 @@ async function getAnalyticsProductHealth(input, db = getAnalyticsPool()) {
|
|
|
51861
51481
|
}
|
|
51862
51482
|
|
|
51863
51483
|
// src/api/analytics-consent.ts
|
|
51864
|
-
import { randomUUID as
|
|
51484
|
+
import { randomUUID as randomUUID35 } from "crypto";
|
|
51865
51485
|
import { z as z41 } from "zod";
|
|
51866
51486
|
var ChoiceSchema = z41.enum(["granted", "denied", "unknown"]);
|
|
51867
51487
|
var CurrentReceiptSchema = z41.object({
|
|
@@ -52016,7 +51636,7 @@ async function recordAnalyticsConsentReceipt(raw, options = {}) {
|
|
|
52016
51636
|
WHERE site_id=$1 AND subject_ref=$2 FOR UPDATE`,
|
|
52017
51637
|
[receipt4.siteId, receipt4.subjectRef]
|
|
52018
51638
|
);
|
|
52019
|
-
const id2 =
|
|
51639
|
+
const id2 = randomUUID35();
|
|
52020
51640
|
const allowed = (purpose) => evaluateAnalyticsPurpose({ receipt: receipt4, purpose }).allowed;
|
|
52021
51641
|
const inserted = await tx.query(
|
|
52022
51642
|
`INSERT INTO analytics_consent_receipts(
|
|
@@ -52241,7 +51861,7 @@ function analyticsVisualPickerUxSdk() {
|
|
|
52241
51861
|
}
|
|
52242
51862
|
|
|
52243
51863
|
// src/api/analytics-privacy-lifecycle.ts
|
|
52244
|
-
import { randomUUID as
|
|
51864
|
+
import { randomUUID as randomUUID36 } from "crypto";
|
|
52245
51865
|
var ANALYTICS_PRIVACY_FIELD_REGISTRY = Object.freeze([
|
|
52246
51866
|
{
|
|
52247
51867
|
dataClass: "necessary",
|
|
@@ -52603,7 +52223,7 @@ async function deleteAnalyticsPrivacySubject(input) {
|
|
|
52603
52223
|
`INSERT INTO analytics_privacy_audits(id, site_id, namespace_ref, subject_ref, action, idempotency_key, actor_user_id, result_code, affected_counts, created_at)
|
|
52604
52224
|
VALUES($1,$2,$3,$4,'deletion_requested',$5,$6,'running','{}'::jsonb,$7)
|
|
52605
52225
|
ON CONFLICT(site_id, idempotency_key) DO UPDATE SET result_code='running'`,
|
|
52606
|
-
[
|
|
52226
|
+
[randomUUID36(), siteId, namespaceId, subject.ref, input.idempotencyKey, input.actorUserId, now]
|
|
52607
52227
|
);
|
|
52608
52228
|
const target = await resolveSubject(client2, { siteId, namespaceId, subject });
|
|
52609
52229
|
const tombstones = await client2.query(
|
|
@@ -52792,7 +52412,7 @@ async function applyAnalyticsPrivacyWithdrawal(input) {
|
|
|
52792
52412
|
`INSERT INTO analytics_privacy_audits(id, site_id, namespace_ref, subject_ref, action, idempotency_key, result_code, affected_counts, created_at, completed_at)
|
|
52793
52413
|
VALUES($1,$2,$3,$4,'withdrawal_applied',$5,'completed',$6::jsonb,$7,$7)
|
|
52794
52414
|
ON CONFLICT(site_id, idempotency_key) DO NOTHING`,
|
|
52795
|
-
[
|
|
52415
|
+
[randomUUID36(), siteId, namespaceId, subject.ref, input.idempotencyKey, JSON.stringify(affectedCounts), now]
|
|
52796
52416
|
);
|
|
52797
52417
|
if (ownsTransaction) await client2.query("COMMIT");
|
|
52798
52418
|
return { affectedCounts };
|
|
@@ -52969,7 +52589,7 @@ async function drainAnalyticsPrivacyLifecycle(input = {}) {
|
|
|
52969
52589
|
}
|
|
52970
52590
|
|
|
52971
52591
|
// src/api/analytics-crm-sync.ts
|
|
52972
|
-
import { createHash as
|
|
52592
|
+
import { createHash as createHash42 } from "crypto";
|
|
52973
52593
|
var VERIFIED_READ_SCOPES = Object.freeze({
|
|
52974
52594
|
hubspot: ["crm.objects.deals.read"],
|
|
52975
52595
|
salesforce: ["api"],
|
|
@@ -53035,7 +52655,7 @@ async function previewAnalyticsCrmSync(input) {
|
|
|
53035
52655
|
};
|
|
53036
52656
|
}
|
|
53037
52657
|
function stableId2(prefix, input) {
|
|
53038
|
-
return `${prefix}_${
|
|
52658
|
+
return `${prefix}_${createHash42("sha256").update(JSON.stringify(input)).digest("hex").slice(0, 24)}`;
|
|
53039
52659
|
}
|
|
53040
52660
|
function isRecord5(value) {
|
|
53041
52661
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
@@ -53208,7 +52828,7 @@ async function cancelAnalyticsCrmSync(input) {
|
|
|
53208
52828
|
}
|
|
53209
52829
|
|
|
53210
52830
|
// src/api/analytics-prediction.ts
|
|
53211
|
-
import { randomUUID as
|
|
52831
|
+
import { randomUUID as randomUUID37 } from "crypto";
|
|
53212
52832
|
import { z as z42 } from "zod";
|
|
53213
52833
|
function createAnalyticsPredictionTables() {
|
|
53214
52834
|
return { targets: /* @__PURE__ */ new Map(), manifests: /* @__PURE__ */ new Map(), results: [] };
|
|
@@ -53255,7 +52875,7 @@ function targetKey(namespaceId, targetId) {
|
|
|
53255
52875
|
}
|
|
53256
52876
|
function registerAnalyticsPredictionTarget(input) {
|
|
53257
52877
|
const parsed = TargetInputSchema.parse(input.target);
|
|
53258
|
-
const id2 = input.id ??
|
|
52878
|
+
const id2 = input.id ?? randomUUID37();
|
|
53259
52879
|
const key3 = targetKey(parsed.namespaceId, id2);
|
|
53260
52880
|
const existing = input.tables.targets.get(key3);
|
|
53261
52881
|
if (existing && input.expectedVersion !== existing.version) throw new AnalyticsPredictionError("analytics_prediction_version_conflict", "The prediction target changed; reload before updating.");
|
|
@@ -53312,7 +52932,7 @@ function analyticsContractRequestId(c) {
|
|
|
53312
52932
|
const existing = analyticsRequestIds.get(c.req.raw);
|
|
53313
52933
|
if (existing) return existing;
|
|
53314
52934
|
const supplied = c.req.header("x-request-id");
|
|
53315
|
-
const requestId = supplied && supplied.length <= 160 && /^[a-zA-Z0-9._:-]+$/.test(supplied) ? supplied :
|
|
52935
|
+
const requestId = supplied && supplied.length <= 160 && /^[a-zA-Z0-9._:-]+$/.test(supplied) ? supplied : randomUUID38();
|
|
53316
52936
|
analyticsRequestIds.set(c.req.raw, requestId);
|
|
53317
52937
|
return requestId;
|
|
53318
52938
|
}
|
|
@@ -53400,7 +53020,7 @@ function analyticsSiteSetupService() {
|
|
|
53400
53020
|
publishManifest: async ({ record: record7, idempotencyKey: idempotencyKey4 }) => {
|
|
53401
53021
|
const hostname = new URL(record7.startUrl).hostname.toLowerCase().replace(/\.$/, "");
|
|
53402
53022
|
const uuidFor = (value) => {
|
|
53403
|
-
const hex =
|
|
53023
|
+
const hex = createHash43("sha256").update(`${record7.siteId}:${value}`).digest("hex").slice(0, 32).split("");
|
|
53404
53024
|
hex[12] = "4";
|
|
53405
53025
|
hex[16] = ["8", "9", "a", "b"][Number.parseInt(hex[16], 16) % 4];
|
|
53406
53026
|
return `${hex.slice(0, 8).join("")}-${hex.slice(8, 12).join("")}-${hex.slice(12, 16).join("")}-${hex.slice(16, 20).join("")}-${hex.slice(20).join("")}`;
|
|
@@ -53539,7 +53159,7 @@ function isRecord6(value) {
|
|
|
53539
53159
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
53540
53160
|
}
|
|
53541
53161
|
function analyticsPrivacyRequestFingerprint(siteId, operation, body3) {
|
|
53542
|
-
return
|
|
53162
|
+
return createHash43("sha256").update(canonicalRequest({ siteId, operation, body: { ...body3, idempotencyKey: void 0 } })).digest("hex");
|
|
53543
53163
|
}
|
|
53544
53164
|
function privacyIdempotency(c, body3, siteId, operation) {
|
|
53545
53165
|
const header = c.req.header("Idempotency-Key")?.trim();
|
|
@@ -53547,8 +53167,8 @@ function privacyIdempotency(c, body3, siteId, operation) {
|
|
|
53547
53167
|
if (header && legacy && header !== legacy) throw new AnalyticsRepositoryError("analytics_invalid_request", "Idempotency-Key header and body key must match.", 400);
|
|
53548
53168
|
const key3 = header || legacy;
|
|
53549
53169
|
if (key3.length < 8 || key3.length > 240) throw new AnalyticsRepositoryError("analytics_invalid_request", "Idempotency-Key is required (8-240 characters).", 400);
|
|
53550
|
-
const
|
|
53551
|
-
return { key: key3, fingerprint:
|
|
53170
|
+
const fingerprint5 = analyticsPrivacyRequestFingerprint(siteId, operation, body3);
|
|
53171
|
+
return { key: key3, fingerprint: fingerprint5 };
|
|
53552
53172
|
}
|
|
53553
53173
|
function manualImportPreviewOrThrow(input) {
|
|
53554
53174
|
try {
|
|
@@ -53558,8 +53178,8 @@ function manualImportPreviewOrThrow(input) {
|
|
|
53558
53178
|
throw new AnalyticsRepositoryError(code, code === "analytics_manual_import_row_limit" ? "Import files are limited to 2,500 rows per batch." : "The CSV or TSV could not be parsed.", 400);
|
|
53559
53179
|
}
|
|
53560
53180
|
}
|
|
53561
|
-
function assertAnalyticsPrivacyIdempotencyFingerprint(row,
|
|
53562
|
-
if (row.request_fingerprint !==
|
|
53181
|
+
function assertAnalyticsPrivacyIdempotencyFingerprint(row, fingerprint5) {
|
|
53182
|
+
if (row.request_fingerprint !== fingerprint5) throw new AnalyticsRepositoryError("idempotency_conflict", "This Idempotency-Key was already used for a different X-Ray privacy request.", 409);
|
|
53563
53183
|
}
|
|
53564
53184
|
function analyticsConsentWithdrawalPublicResponse(receipt4, replayed = false) {
|
|
53565
53185
|
if (!receipt4 || typeof receipt4 !== "object" || Array.isArray(receipt4)) {
|
|
@@ -54346,7 +53966,7 @@ analyticsApp.get("/v1/pixels/:publicPixelId/event-definitions", async (c) => {
|
|
|
54346
53966
|
});
|
|
54347
53967
|
});
|
|
54348
53968
|
function deterministicRuntimeManifestId(siteId) {
|
|
54349
|
-
const hex =
|
|
53969
|
+
const hex = createHash43("sha256").update(`xray-runtime-manifest:${siteId}`).digest("hex").slice(0, 32).split("");
|
|
54350
53970
|
hex[12] = "4";
|
|
54351
53971
|
hex[16] = ["8", "9", "a", "b"][Number.parseInt(hex[16], 16) % 4];
|
|
54352
53972
|
return `${hex.slice(0, 8).join("")}-${hex.slice(8, 12).join("")}-${hex.slice(12, 16).join("")}-${hex.slice(16, 20).join("")}-${hex.slice(20).join("")}`;
|
|
@@ -54601,8 +54221,8 @@ analyticsApp.post("/forms/:publicId/submissions", async (c) => {
|
|
|
54601
54221
|
const firstName = typeof data.first_name === "string" ? data.first_name.trim() : "";
|
|
54602
54222
|
const lastName = typeof data.last_name === "string" ? data.last_name.trim() : "";
|
|
54603
54223
|
const fullName = [firstName, lastName].filter(Boolean).join(" ") || (typeof data.name === "string" ? data.name.trim() : "") || email || "Website lead";
|
|
54604
|
-
const identitySeed = email || phone.replace(/\D/g, "") ||
|
|
54605
|
-
const suffix2 =
|
|
54224
|
+
const identitySeed = email || phone.replace(/\D/g, "") || randomUUID38();
|
|
54225
|
+
const suffix2 = createHash43("sha256").update(identitySeed).digest("hex").slice(0, 12);
|
|
54606
54226
|
const path5 = `Leads/person-${suffix2}`;
|
|
54607
54227
|
const crmPersonRef = `People::${path5}`;
|
|
54608
54228
|
const { key: memoryKey, error: memoryKeyError } = await getOrCreateUserMemoryKey(user);
|
|
@@ -54694,9 +54314,9 @@ Submitted the published form.
|
|
|
54694
54314
|
});
|
|
54695
54315
|
}
|
|
54696
54316
|
const match = {
|
|
54697
|
-
...email ? { emailSha256:
|
|
54317
|
+
...email ? { emailSha256: createHash43("sha256").update(email).digest("hex") } : {},
|
|
54698
54318
|
...phone ? {
|
|
54699
|
-
phoneSha256:
|
|
54319
|
+
phoneSha256: createHash43("sha256").update(phone.replace(/\D/g, "")).digest("hex")
|
|
54700
54320
|
} : {}
|
|
54701
54321
|
};
|
|
54702
54322
|
const conversionOccurredAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -54823,7 +54443,7 @@ analyticsApp.post("/v1/events", async (c) => {
|
|
|
54823
54443
|
if (rule.condition.eventName && rule.condition.eventName !== event2.eventName) continue;
|
|
54824
54444
|
const tags = Array.isArray(event2.properties?.tags) ? event2.properties.tags.map(String) : [];
|
|
54825
54445
|
if ((rule.condition.excludedTags ?? []).some((tag) => tags.includes(tag))) continue;
|
|
54826
|
-
const sourceEventId = `browser-rule:${rule.id}:${
|
|
54446
|
+
const sourceEventId = `browser-rule:${rule.id}:${createHash43("sha256").update(event2.eventId).digest("hex").slice(0, 32)}`;
|
|
54827
54447
|
const valueMinor = Number(rule.default_value_minor ?? 0);
|
|
54828
54448
|
await createAnalyticsConversion({
|
|
54829
54449
|
userId: ownerUserId2,
|
|
@@ -54982,7 +54602,7 @@ analyticsApp.post("/v1/webhooks/:provider/:connectionId", async (c) => {
|
|
|
54982
54602
|
connectionId: connection.id,
|
|
54983
54603
|
provider,
|
|
54984
54604
|
sourceAccountRef: connection.sourceAccountRef,
|
|
54985
|
-
sourceEventId: `invalid:${
|
|
54605
|
+
sourceEventId: `invalid:${createHash43("sha256").update(rawBody).digest("hex")}`,
|
|
54986
54606
|
signatureStatus: "invalid"
|
|
54987
54607
|
});
|
|
54988
54608
|
await setAnalyticsConnectionReadiness({
|
|
@@ -55221,73 +54841,6 @@ analyticsApp.get("/sites/:siteId/site-setups/:setupId/first-answers", auth4, asy
|
|
|
55221
54841
|
const answers = await analyticsSiteSetupService().firstAnswers({ ownerId: String(userId), setupId });
|
|
55222
54842
|
return c.json({ ok: true, answers }, 200, noStore);
|
|
55223
54843
|
});
|
|
55224
|
-
var RevenueSetupPrepareSchema = z43.object({
|
|
55225
|
-
serviceConnectionRef: z43.string().trim().min(1).max(240),
|
|
55226
|
-
role: z43.enum(["primary", "observation"]).default("primary"),
|
|
55227
|
-
idempotencyKey: z43.string().trim().min(8).max(240)
|
|
55228
|
-
}).strict();
|
|
55229
|
-
var RevenueSetupMutationSchema = z43.object({
|
|
55230
|
-
revision: z43.number().int().positive(),
|
|
55231
|
-
confirmed: z43.literal(true).optional(),
|
|
55232
|
-
idempotencyKey: z43.string().trim().min(8).max(240).optional()
|
|
55233
|
-
}).strict();
|
|
55234
|
-
analyticsApp.post("/sites/:siteId/revenue-source-setup/prepare", auth4, async (c) => {
|
|
55235
|
-
const { siteId, userId, user } = await requireOwnedSite(c);
|
|
55236
|
-
const body3 = await strictJson(c, RevenueSetupPrepareSchema);
|
|
55237
|
-
const setup = await prepareAnalyticsRevenueSetup({
|
|
55238
|
-
siteId,
|
|
55239
|
-
userId,
|
|
55240
|
-
ownerIdentity: user.email,
|
|
55241
|
-
serviceConnectionRef: body3.serviceConnectionRef,
|
|
55242
|
-
role: body3.role,
|
|
55243
|
-
idempotencyKey: c.req.header("idempotency-key") ?? body3.idempotencyKey
|
|
55244
|
-
});
|
|
55245
|
-
return c.json({ ok: true, setup }, 201, noStore);
|
|
55246
|
-
});
|
|
55247
|
-
analyticsApp.get("/sites/:siteId/revenue-source-setups/:setupId", auth4, async (c) => {
|
|
55248
|
-
const { siteId, userId } = await requireOwnedSite(c);
|
|
55249
|
-
const setup = await currentAnalyticsRevenueSetup({ siteId, userId, setupId: pathParam(c, "setupId") });
|
|
55250
|
-
return c.json({ ok: true, setup }, 200, noStore);
|
|
55251
|
-
});
|
|
55252
|
-
analyticsApp.get("/revenue-source-setups/:setupId", auth4, entitlementGuard, async (c) => {
|
|
55253
|
-
const setup = await currentAnalyticsRevenueSetupForOwner({
|
|
55254
|
-
setupId: pathParam(c, "setupId"),
|
|
55255
|
-
userId: Number(c.get("user").id)
|
|
55256
|
-
});
|
|
55257
|
-
return c.json({ ok: true, setup }, 200, noStore);
|
|
55258
|
-
});
|
|
55259
|
-
analyticsApp.post("/sites/:siteId/revenue-source-setups/:setupId/apply", auth4, async (c) => {
|
|
55260
|
-
const { siteId, userId, user } = await requireOwnedSite(c);
|
|
55261
|
-
const body3 = await strictJson(c, RevenueSetupMutationSchema);
|
|
55262
|
-
if (body3.confirmed !== true) throw new AnalyticsRepositoryError("analytics_revenue_setup_confirmation_required", "Confirm the reviewed revenue setup before applying it.", 400);
|
|
55263
|
-
const idempotencyKey4 = c.req.header("idempotency-key") ?? body3.idempotencyKey;
|
|
55264
|
-
if (!idempotencyKey4) throw new AnalyticsRepositoryError("idempotency_key_required", "Apply requires an Idempotency-Key header or body field.", 400);
|
|
55265
|
-
const setup = await applyAnalyticsRevenueSetup({
|
|
55266
|
-
siteId,
|
|
55267
|
-
userId,
|
|
55268
|
-
ownerIdentity: user.email,
|
|
55269
|
-
setupId: pathParam(c, "setupId"),
|
|
55270
|
-
revision: body3.revision,
|
|
55271
|
-
confirmed: true,
|
|
55272
|
-
idempotencyKey: idempotencyKey4
|
|
55273
|
-
});
|
|
55274
|
-
return c.json({ ok: true, setup }, 200, noStore);
|
|
55275
|
-
});
|
|
55276
|
-
analyticsApp.post("/sites/:siteId/revenue-source-setups/:setupId/verify", auth4, async (c) => {
|
|
55277
|
-
const { siteId, userId, user } = await requireOwnedSite(c);
|
|
55278
|
-
const body3 = await strictJson(c, RevenueSetupMutationSchema);
|
|
55279
|
-
const idempotencyKey4 = c.req.header("idempotency-key") ?? body3.idempotencyKey;
|
|
55280
|
-
if (!idempotencyKey4) throw new AnalyticsRepositoryError("idempotency_key_required", "Verify requires an Idempotency-Key header or body field.", 400);
|
|
55281
|
-
const setup = await verifyAnalyticsRevenueSetup({
|
|
55282
|
-
siteId,
|
|
55283
|
-
userId,
|
|
55284
|
-
ownerIdentity: user.email,
|
|
55285
|
-
setupId: pathParam(c, "setupId"),
|
|
55286
|
-
revision: body3.revision,
|
|
55287
|
-
idempotencyKey: idempotencyKey4
|
|
55288
|
-
});
|
|
55289
|
-
return c.json({ ok: true, setup }, 200, noStore);
|
|
55290
|
-
});
|
|
55291
54844
|
var PostPurchaseSurveyCreateSchema = z43.object({
|
|
55292
54845
|
name: z43.string().trim().min(1).max(160),
|
|
55293
54846
|
question: z43.string().trim().min(1).max(500),
|
|
@@ -55412,7 +54965,7 @@ function surveyPublicHeaders(c) {
|
|
|
55412
54965
|
}
|
|
55413
54966
|
function surveyRateLimit(c) {
|
|
55414
54967
|
const networkRef = c.req.header("cf-connecting-ip") ?? c.req.header("x-forwarded-for")?.split(",")[0]?.trim() ?? "unknown";
|
|
55415
|
-
const key3 =
|
|
54968
|
+
const key3 = createHash43("sha256").update(`survey-exchange:${networkRef}`).digest("hex");
|
|
55416
54969
|
const now = Date.now();
|
|
55417
54970
|
const window2 = surveyExchangeRateWindows.get(key3);
|
|
55418
54971
|
if (!window2 || now - window2.startedAt >= 6e4) {
|
|
@@ -55435,7 +54988,7 @@ function surveyCookie(c) {
|
|
|
55435
54988
|
return { siteId, sessionToken };
|
|
55436
54989
|
}
|
|
55437
54990
|
async function approvedSurveyExchangeSite(exchangeCode, origin) {
|
|
55438
|
-
const digest23 =
|
|
54991
|
+
const digest23 = createHash43("sha256").update(exchangeCode).digest("hex");
|
|
55439
54992
|
const hostname = normalizeAnalyticsHostname(new URL(origin).hostname);
|
|
55440
54993
|
const result3 = await getAnalyticsPool().query(
|
|
55441
54994
|
`SELECT invite.site_id
|
|
@@ -55474,7 +55027,7 @@ analyticsApp.post("/survey/exchange", async (c) => {
|
|
|
55474
55027
|
return c.redirect("/analytics/survey/session", 303);
|
|
55475
55028
|
});
|
|
55476
55029
|
async function readPublicSurveySession(siteId, sessionToken) {
|
|
55477
|
-
const digest23 =
|
|
55030
|
+
const digest23 = createHash43("sha256").update(sessionToken).digest("hex");
|
|
55478
55031
|
const session = await getAnalyticsPool().query(
|
|
55479
55032
|
`SELECT invite.survey_id,invite.survey_revision,invite.conversion_id,invite.session_expires_at,
|
|
55480
55033
|
survey.state,survey.name,survey.question,survey.selection_mode,survey.eligible_outcome_families,
|
|
@@ -55641,10 +55194,10 @@ analyticsApp.post("/v1/conversions", auth4, async (c) => {
|
|
|
55641
55194
|
clickIds: clickIds ?? {},
|
|
55642
55195
|
match: {
|
|
55643
55196
|
...normalizedEmail ? {
|
|
55644
|
-
emailSha256:
|
|
55197
|
+
emailSha256: createHash43("sha256").update(normalizedEmail).digest("hex")
|
|
55645
55198
|
} : {},
|
|
55646
55199
|
...normalizedPhone ? {
|
|
55647
|
-
phoneSha256:
|
|
55200
|
+
phoneSha256: createHash43("sha256").update(normalizedPhone).digest("hex")
|
|
55648
55201
|
} : {}
|
|
55649
55202
|
}
|
|
55650
55203
|
}),
|
|
@@ -55683,7 +55236,7 @@ analyticsApp.get("/sites/:siteId/connections", auth4, async (c) => {
|
|
|
55683
55236
|
const origin = new URL(analyticsExternalRequestUrl(c)).origin;
|
|
55684
55237
|
return c.json({
|
|
55685
55238
|
ok: true,
|
|
55686
|
-
connections: connections.map((connection) => buildAnalyticsConnectionSetupView(connection, origin))
|
|
55239
|
+
connections: connections.filter((connection) => connection.provider !== "salesforce" && connection.provider !== "pipedrive").map((connection) => buildAnalyticsConnectionSetupView(connection, origin))
|
|
55687
55240
|
});
|
|
55688
55241
|
});
|
|
55689
55242
|
analyticsApp.post("/sites/:siteId/connections", auth4, async (c) => {
|
|
@@ -56173,7 +55726,7 @@ analyticsApp.post("/sites/:siteId/crm-imports", auth4, async (c) => {
|
|
|
56173
55726
|
rejectedCount += 1;
|
|
56174
55727
|
continue;
|
|
56175
55728
|
}
|
|
56176
|
-
const digest23 =
|
|
55729
|
+
const digest23 = createHash43("sha256").update(
|
|
56177
55730
|
`${parsed.data.sourceSystem}:${externalId || email || phone || `${fullName}:${index}`}`
|
|
56178
55731
|
).digest("hex").slice(0, 16);
|
|
56179
55732
|
const path5 = `Leads/person-${digest23}`;
|
|
@@ -56897,7 +56450,7 @@ analyticsApp.post("/sites/:siteId/consent/policies", auth4, async (c) => {
|
|
|
56897
56450
|
ON CONFLICT(site_id,purpose,policy_version,jurisdiction_profile) DO UPDATE SET
|
|
56898
56451
|
retention_days=excluded.retention_days, enabled=excluded.enabled, policy=excluded.policy, retired_at=NULL
|
|
56899
56452
|
RETURNING id,purpose,policy_version AS "policyVersion",jurisdiction_profile AS "jurisdictionProfile",retention_days AS "retentionDays",enabled,policy`,
|
|
56900
|
-
[
|
|
56453
|
+
[randomUUID38(), siteId, body3.purpose, body3.policyVersion, body3.jurisdictionProfile, body3.retentionDays ?? null, body3.enabled, JSON.stringify(body3.policy), userId]
|
|
56901
56454
|
);
|
|
56902
56455
|
return c.json({ ok: true, policy: result3.rows[0] }, 201, noStore);
|
|
56903
56456
|
});
|
|
@@ -56921,7 +56474,7 @@ analyticsApp.post("/sites/:siteId/consent/withdrawals", auth4, async (c) => {
|
|
|
56921
56474
|
try {
|
|
56922
56475
|
await client2.query("BEGIN");
|
|
56923
56476
|
await client2.query(`INSERT INTO analytics_privacy_audits(id,site_id,subject_ref,action,idempotency_key,request_fingerprint,actor_user_id,result_code)
|
|
56924
|
-
VALUES($1,$2,$3,'withdrawal_applied',$4,$5,$6,'running') ON CONFLICT(site_id,idempotency_key) DO NOTHING`, [
|
|
56477
|
+
VALUES($1,$2,$3,'withdrawal_applied',$4,$5,$6,'running') ON CONFLICT(site_id,idempotency_key) DO NOTHING`, [randomUUID38(), siteId, `subject:${createHash43("sha256").update(body3.subjectRef).digest("hex").slice(0, 16)}`, idem.key, idem.fingerprint, userId]);
|
|
56925
56478
|
const claimed = await client2.query("SELECT request_fingerprint,result_code,affected_counts FROM analytics_privacy_audits WHERE site_id=$1 AND idempotency_key=$2 FOR UPDATE", [siteId, idem.key]);
|
|
56926
56479
|
assertAnalyticsPrivacyIdempotencyFingerprint(claimed.rows[0], idem.fingerprint);
|
|
56927
56480
|
if (claimed.rows[0].result_code === "completed") {
|
|
@@ -57028,7 +56581,7 @@ analyticsApp.post("/sites/:siteId/identity-namespaces/:namespaceId/candidates/:a
|
|
|
57028
56581
|
});
|
|
57029
56582
|
analyticsApp.get("/sites/:siteId/crm/capabilities", auth4, async (c) => {
|
|
57030
56583
|
await requireSite(c);
|
|
57031
|
-
const providers =
|
|
56584
|
+
const providers = ANALYTICS_PUBLIC_CRM_PROVIDER_IDS.map((provider) => ({
|
|
57032
56585
|
profile: getAnalyticsCrmProviderProfile(provider),
|
|
57033
56586
|
sync: getAnalyticsCrmSyncCapability(provider)
|
|
57034
56587
|
}));
|
|
@@ -57037,7 +56590,7 @@ analyticsApp.get("/sites/:siteId/crm/capabilities", auth4, async (c) => {
|
|
|
57037
56590
|
analyticsApp.post("/sites/:siteId/crm/schema/discover", auth4, async (c) => {
|
|
57038
56591
|
const { user, userId, siteId } = await requireSite(c, true);
|
|
57039
56592
|
const body3 = await strictJson(c, z43.object({
|
|
57040
|
-
provider:
|
|
56593
|
+
provider: AnalyticsPublicCrmProviderIdSchema,
|
|
57041
56594
|
connectionId: z43.string().trim().min(1).max(240),
|
|
57042
56595
|
discoveryContext: z43.object({
|
|
57043
56596
|
locationId: z43.string().trim().min(1).max(128).regex(/^[A-Za-z0-9_-]+$/).optional(),
|
|
@@ -57084,7 +56637,7 @@ analyticsApp.post("/sites/:siteId/crm/schema/discover", auth4, async (c) => {
|
|
|
57084
56637
|
analyticsApp.post("/sites/:siteId/crm/provisioning/plan", auth4, async (c) => {
|
|
57085
56638
|
const { siteId, userId } = await requireSite(c, true);
|
|
57086
56639
|
const body3 = await strictJson(c, z43.object({
|
|
57087
|
-
provider:
|
|
56640
|
+
provider: AnalyticsPublicCrmProviderIdSchema,
|
|
57088
56641
|
connectionId: z43.string().trim().min(1).max(240),
|
|
57089
56642
|
fields: z43.array(AnalyticsCrmFieldSchema).max(5e3),
|
|
57090
56643
|
allowedOperations: z43.array(z43.string()).max(100).optional()
|
|
@@ -57095,7 +56648,7 @@ analyticsApp.post("/sites/:siteId/crm/provisioning/plan", auth4, async (c) => {
|
|
|
57095
56648
|
});
|
|
57096
56649
|
analyticsApp.post("/sites/:siteId/crm/provisioning/approve", auth4, async (c) => {
|
|
57097
56650
|
const { user, userId, siteId } = await requireSite(c, true);
|
|
57098
|
-
const body3 = await strictJson(c, z43.object({ plan:
|
|
56651
|
+
const body3 = await strictJson(c, z43.object({ plan: AnalyticsPublicCrmProvisioningPlanSchema, approvedFieldInternalNames: z43.array(z43.string().trim().min(1).max(160)).max(50) }).strict());
|
|
57099
56652
|
const persistedPlan = await readAnalyticsCrmProvisioningPlan({ siteId, planId: body3.plan.planId });
|
|
57100
56653
|
if (persistedPlan.requestFingerprint !== body3.plan.requestFingerprint)
|
|
57101
56654
|
throw new AnalyticsRepositoryError("idempotency_conflict", "The submitted plan does not match the persisted plan.", 409);
|
|
@@ -57117,7 +56670,7 @@ analyticsApp.post("/sites/:siteId/crm/provisioning/approve", auth4, async (c) =>
|
|
|
57117
56670
|
});
|
|
57118
56671
|
analyticsApp.post("/sites/:siteId/crm/provisioning/test", auth4, async (c) => {
|
|
57119
56672
|
const { user, userId, siteId } = await requireSite(c, true);
|
|
57120
|
-
const body3 = await strictJson(c, z43.object({ receipt:
|
|
56673
|
+
const body3 = await strictJson(c, z43.object({ receipt: AnalyticsPublicCrmProvisioningReceiptSchema }).strict());
|
|
57121
56674
|
const persistedReceipt = await readAnalyticsCrmProvisioningReceipt({ siteId, receiptId: body3.receipt.receiptId });
|
|
57122
56675
|
if (persistedReceipt.planFingerprint !== body3.receipt.planFingerprint)
|
|
57123
56676
|
throw new AnalyticsRepositoryError("idempotency_conflict", "The submitted receipt does not match the persisted receipt.", 409);
|
|
@@ -57128,7 +56681,7 @@ analyticsApp.post("/sites/:siteId/crm/provisioning/test", auth4, async (c) => {
|
|
|
57128
56681
|
analyticsApp.post("/sites/:siteId/crm/person-sync", auth4, async (c) => {
|
|
57129
56682
|
const { user } = await requireSite(c, true);
|
|
57130
56683
|
const body3 = await strictJson(c, z43.object({
|
|
57131
|
-
provider:
|
|
56684
|
+
provider: AnalyticsPublicCrmProviderIdSchema,
|
|
57132
56685
|
connectionId: z43.string().trim().min(1).max(240),
|
|
57133
56686
|
person: AnalyticsConfirmedPersonProjectionSchema,
|
|
57134
56687
|
mapping: z43.record(z43.string(), z43.string()).optional()
|
|
@@ -57139,7 +56692,7 @@ analyticsApp.post("/sites/:siteId/crm/person-sync", auth4, async (c) => {
|
|
|
57139
56692
|
analyticsApp.post("/sites/:siteId/crm/pipeline-mapping/apply", auth4, async (c) => {
|
|
57140
56693
|
const { user } = await requireSite(c, true);
|
|
57141
56694
|
const body3 = await strictJson(c, z43.object({
|
|
57142
|
-
provider:
|
|
56695
|
+
provider: AnalyticsPublicCrmProviderIdSchema,
|
|
57143
56696
|
connectionId: z43.string().trim().min(1).max(240),
|
|
57144
56697
|
person: AnalyticsConfirmedPersonProjectionSchema.pick({ identityTier: true, personId: true, deterministicIdentity: true, consentReceiptRef: true }),
|
|
57145
56698
|
event: AnalyticsPipelineEventSchema,
|
|
@@ -57150,12 +56703,16 @@ analyticsApp.post("/sites/:siteId/crm/pipeline-mapping/apply", auth4, async (c)
|
|
|
57150
56703
|
});
|
|
57151
56704
|
analyticsApp.get("/sites/:siteId/crm/outbound-policies", auth4, async (c) => {
|
|
57152
56705
|
const { siteId } = await requireSite(c);
|
|
57153
|
-
|
|
56706
|
+
const policies = await listAnalyticsCrmOutboundPolicies({ siteId });
|
|
56707
|
+
return c.json({
|
|
56708
|
+
ok: true,
|
|
56709
|
+
policies: policies.filter((policy7) => policy7.provider !== "salesforce" && policy7.provider !== "pipedrive")
|
|
56710
|
+
}, 200, noStore);
|
|
57154
56711
|
});
|
|
57155
56712
|
analyticsApp.post("/sites/:siteId/crm/outbound-policies", auth4, async (c) => {
|
|
57156
56713
|
const { siteId, userId } = await requireSite(c, true);
|
|
57157
56714
|
const body3 = await strictJson(c, z43.object({
|
|
57158
|
-
provider:
|
|
56715
|
+
provider: AnalyticsPublicCrmProviderIdSchema,
|
|
57159
56716
|
connectionId: z43.string().trim().min(1).max(240),
|
|
57160
56717
|
kind: z43.enum(["person_summary", "pipeline_event"]),
|
|
57161
56718
|
enabled: z43.boolean(),
|
|
@@ -57168,7 +56725,7 @@ analyticsApp.post("/sites/:siteId/crm/outbound-policies", auth4, async (c) => {
|
|
|
57168
56725
|
selectedEvents: z43.array(z43.string().regex(/^[a-z][a-z0-9_]{1,79}$/)).max(100),
|
|
57169
56726
|
purpose: z43.enum(["necessary_form_fulfillment", "site_analytics", "advertising_measurement"])
|
|
57170
56727
|
}).strict());
|
|
57171
|
-
const policyId = `crmpolicy_${
|
|
56728
|
+
const policyId = `crmpolicy_${createHash43("sha256").update(JSON.stringify({
|
|
57172
56729
|
siteId,
|
|
57173
56730
|
connectionId: body3.connectionId,
|
|
57174
56731
|
kind: body3.kind,
|
|
@@ -57199,11 +56756,12 @@ analyticsApp.post("/sites/:siteId/crm/outbound-policies", auth4, async (c) => {
|
|
|
57199
56756
|
analyticsApp.get("/sites/:siteId/crm/outbound-receipts", auth4, async (c) => {
|
|
57200
56757
|
const { siteId } = await requireSite(c);
|
|
57201
56758
|
const limit = z43.coerce.number().int().min(1).max(100).catch(25).parse(c.req.query("limit"));
|
|
57202
|
-
|
|
56759
|
+
const receipts = await listAnalyticsCrmOutboundReceipts({ siteId, limit });
|
|
56760
|
+
return c.json({ ok: true, receipts }, 200, noStore);
|
|
57203
56761
|
});
|
|
57204
56762
|
analyticsApp.post("/sites/:siteId/crm/sync/discover", auth4, async (c) => {
|
|
57205
56763
|
const { user, siteId } = await requireSite(c);
|
|
57206
|
-
const body3 = await strictJson(c, z43.object({ provider:
|
|
56764
|
+
const body3 = await strictJson(c, z43.object({ provider: AnalyticsPublicCrmProviderIdSchema, connectionId: z43.string().trim().max(240).optional() }).strict());
|
|
57207
56765
|
const serviceConnectionRef = body3.connectionId ? await analyticsCrmServiceConnectionRef(siteId, body3.connectionId) : void 0;
|
|
57208
56766
|
let baseDiscovery = await discoverAnalyticsCrmObjects({ provider: body3.provider });
|
|
57209
56767
|
let discoveryContext;
|
|
@@ -57258,7 +56816,7 @@ analyticsApp.post("/sites/:siteId/crm/sync/discover", auth4, async (c) => {
|
|
|
57258
56816
|
analyticsApp.post("/sites/:siteId/crm/sync/test", auth4, async (c) => {
|
|
57259
56817
|
await requireSite(c);
|
|
57260
56818
|
const body3 = await strictJson(c, z43.object({
|
|
57261
|
-
provider:
|
|
56819
|
+
provider: AnalyticsPublicCrmProviderIdSchema,
|
|
57262
56820
|
mapping: AnalyticsCrmMappingSchema,
|
|
57263
56821
|
availableObjects: z43.array(z43.object({ name: z43.string().trim().min(1).max(100), fields: z43.array(z43.string().trim().min(1).max(160)).max(1e3) }).strict()).max(100).optional()
|
|
57264
56822
|
}).strict());
|
|
@@ -57267,7 +56825,7 @@ analyticsApp.post("/sites/:siteId/crm/sync/test", auth4, async (c) => {
|
|
|
57267
56825
|
analyticsApp.post("/sites/:siteId/crm/sync/preview", auth4, async (c) => {
|
|
57268
56826
|
const { user, siteId } = await requireSite(c, true);
|
|
57269
56827
|
const body3 = await strictJson(c, z43.object({
|
|
57270
|
-
provider:
|
|
56828
|
+
provider: AnalyticsPublicCrmProviderIdSchema,
|
|
57271
56829
|
connectionId: z43.string().uuid(),
|
|
57272
56830
|
mapping: AnalyticsCrmMappingSchema
|
|
57273
56831
|
}).strict());
|
|
@@ -57316,7 +56874,7 @@ analyticsApp.post("/sites/:siteId/crm/sync/preview", auth4, async (c) => {
|
|
|
57316
56874
|
analyticsApp.post("/sites/:siteId/crm/sync/start", auth4, async (c) => {
|
|
57317
56875
|
const { siteId } = await requireSite(c, true);
|
|
57318
56876
|
const body3 = await strictJson(c, z43.object({
|
|
57319
|
-
provider:
|
|
56877
|
+
provider: AnalyticsPublicCrmProviderIdSchema,
|
|
57320
56878
|
connectionId: z43.string().trim().min(1).max(240),
|
|
57321
56879
|
mode: z43.enum(["initial", "incremental"]),
|
|
57322
56880
|
mapping: AnalyticsCrmMappingSchema,
|
|
@@ -57356,16 +56914,25 @@ analyticsApp.post("/sites/:siteId/crm/sync/start", auth4, async (c) => {
|
|
|
57356
56914
|
});
|
|
57357
56915
|
analyticsApp.get("/sites/:siteId/crm/sync/:syncId", auth4, async (c) => {
|
|
57358
56916
|
const { siteId } = await requireSite(c);
|
|
56917
|
+
const syncId = pathParam(c, "syncId");
|
|
56918
|
+
const current = await readAnalyticsCrmSyncRun({ siteId, syncId });
|
|
56919
|
+
if (current && (current.provider === "salesforce" || current.provider === "pipedrive")) {
|
|
56920
|
+
throw new AnalyticsRepositoryError(
|
|
56921
|
+
"analytics_crm_provider_unavailable",
|
|
56922
|
+
"This CRM provider integration is not currently available.",
|
|
56923
|
+
409
|
|
56924
|
+
);
|
|
56925
|
+
}
|
|
57359
56926
|
const status = await getAnalyticsCrmSyncStatus({
|
|
57360
|
-
syncId
|
|
57361
|
-
dependencies: { readStatus: async (
|
|
56927
|
+
syncId,
|
|
56928
|
+
dependencies: { readStatus: async () => current }
|
|
57362
56929
|
});
|
|
57363
56930
|
return c.json({ ok: true, sync: status }, 200, noStore);
|
|
57364
56931
|
});
|
|
57365
56932
|
analyticsApp.patch("/sites/:siteId/crm/sync/:syncId/schedule", auth4, async (c) => {
|
|
57366
56933
|
const { siteId } = await requireSite(c, true);
|
|
57367
56934
|
const syncId = pathParam(c, "syncId");
|
|
57368
|
-
const body3 = await strictJson(c, z43.object({ provider:
|
|
56935
|
+
const body3 = await strictJson(c, z43.object({ provider: AnalyticsPublicCrmProviderIdSchema, connectionId: z43.string().trim().min(1).max(240), intervalSeconds: z43.number().int().nullable() }).strict());
|
|
57369
56936
|
const schedule = await updateAnalyticsCrmSyncSchedule({
|
|
57370
56937
|
provider: body3.provider,
|
|
57371
56938
|
connectionId: body3.connectionId,
|
|
@@ -57381,8 +56948,17 @@ analyticsApp.patch("/sites/:siteId/crm/sync/:syncId/schedule", auth4, async (c)
|
|
|
57381
56948
|
});
|
|
57382
56949
|
analyticsApp.delete("/sites/:siteId/crm/sync/:syncId", auth4, async (c) => {
|
|
57383
56950
|
const { siteId } = await requireSite(c, true);
|
|
57384
|
-
const
|
|
57385
|
-
|
|
56951
|
+
const syncId = pathParam(c, "syncId");
|
|
56952
|
+
const current = await readAnalyticsCrmSyncRun({ siteId, syncId });
|
|
56953
|
+
if (current && (current.provider === "salesforce" || current.provider === "pipedrive")) {
|
|
56954
|
+
throw new AnalyticsRepositoryError(
|
|
56955
|
+
"analytics_crm_provider_unavailable",
|
|
56956
|
+
"This CRM provider integration is not currently available.",
|
|
56957
|
+
409
|
|
56958
|
+
);
|
|
56959
|
+
}
|
|
56960
|
+
const result3 = await cancelAnalyticsCrmSync({ syncId, dependencies: {
|
|
56961
|
+
cancel: async (syncId2) => cancelAnalyticsCrmSyncRun({ siteId, syncId: syncId2 })
|
|
57386
56962
|
} });
|
|
57387
56963
|
return c.json({ ok: true, ...result3 }, 200, noStore);
|
|
57388
56964
|
});
|
|
@@ -57504,7 +57080,7 @@ analyticsApp.post("/sites/:siteId/saved-views", auth4, async (c) => {
|
|
|
57504
57080
|
const { siteId, userId } = await requireSite(c, true);
|
|
57505
57081
|
const body3 = await strictJson(c, z43.object({ name: z43.string().trim().min(1).max(120), settings: z43.any(), isDefault: z43.boolean().default(false) }).strict());
|
|
57506
57082
|
const settings = parseAnalyticsReportView(body3.settings);
|
|
57507
|
-
const id2 =
|
|
57083
|
+
const id2 = randomUUID38();
|
|
57508
57084
|
const client2 = await getAnalyticsPool().connect();
|
|
57509
57085
|
try {
|
|
57510
57086
|
await client2.query("BEGIN");
|
|
@@ -57576,7 +57152,7 @@ analyticsApp.post("/sites/:siteId/privacy/subject/export", auth4, async (c) => {
|
|
|
57576
57152
|
await getAnalyticsPool().query(
|
|
57577
57153
|
`INSERT INTO analytics_privacy_audits(id,site_id,subject_ref,action,idempotency_key,request_fingerprint,actor_user_id,result_code,affected_counts,completed_at)
|
|
57578
57154
|
VALUES($1,$2,$3,'export_completed',$4,$5,$6,'completed',$7::jsonb,now()) ON CONFLICT(site_id,idempotency_key) DO NOTHING`,
|
|
57579
|
-
[
|
|
57155
|
+
[randomUUID38(), siteId, `person:${createHash43("sha256").update(body3.subjectRef).digest("hex").slice(0, 16)}`, idem.key, idem.fingerprint, userId, JSON.stringify({ export: { schemaVersion: 1, subject: person.rows[0], restrictedIdentityExcluded: true } })]
|
|
57580
57156
|
);
|
|
57581
57157
|
const persisted = await getAnalyticsPool().query("SELECT request_fingerprint,affected_counts FROM analytics_privacy_audits WHERE site_id=$1 AND idempotency_key=$2", [siteId, idem.key]);
|
|
57582
57158
|
assertAnalyticsPrivacyIdempotencyFingerprint(persisted.rows[0], idem.fingerprint);
|
|
@@ -57590,7 +57166,7 @@ analyticsApp.post("/sites/:siteId/privacy/subject/delete", auth4, async (c) => {
|
|
|
57590
57166
|
try {
|
|
57591
57167
|
await client2.query("BEGIN");
|
|
57592
57168
|
await client2.query(`INSERT INTO analytics_privacy_audits(id,site_id,subject_ref,action,idempotency_key,request_fingerprint,actor_user_id,result_code)
|
|
57593
|
-
VALUES($1,$2,$3,'deletion_requested',$4,$5,$6,'running') ON CONFLICT(site_id,idempotency_key) DO NOTHING`, [
|
|
57169
|
+
VALUES($1,$2,$3,'deletion_requested',$4,$5,$6,'running') ON CONFLICT(site_id,idempotency_key) DO NOTHING`, [randomUUID38(), siteId, `subject:${createHash43("sha256").update(body3.subjectRef).digest("hex").slice(0, 16)}`, idem.key, idem.fingerprint, userId]);
|
|
57594
57170
|
const claim = await client2.query("SELECT request_fingerprint,result_code,affected_counts FROM analytics_privacy_audits WHERE site_id=$1 AND idempotency_key=$2 FOR UPDATE", [siteId, idem.key]);
|
|
57595
57171
|
assertAnalyticsPrivacyIdempotencyFingerprint(claim.rows[0], idem.fingerprint);
|
|
57596
57172
|
if (claim.rows[0].result_code === "deleted") {
|
|
@@ -57608,7 +57184,7 @@ analyticsApp.post("/sites/:siteId/privacy/subject/delete", auth4, async (c) => {
|
|
|
57608
57184
|
db: client2
|
|
57609
57185
|
});
|
|
57610
57186
|
const counts = { ...deletion.affectedCounts };
|
|
57611
|
-
await client2.query(`UPDATE analytics_privacy_audits SET namespace_ref=$3,subject_ref=$4,action='deletion_completed',result_code='deleted',affected_counts=$5::jsonb,completed_at=now() WHERE site_id=$1 AND idempotency_key=$2`, [siteId, idem.key, `namespace:${locked.rows[0].namespace_id}`, `deleted:${
|
|
57187
|
+
await client2.query(`UPDATE analytics_privacy_audits SET namespace_ref=$3,subject_ref=$4,action='deletion_completed',result_code='deleted',affected_counts=$5::jsonb,completed_at=now() WHERE site_id=$1 AND idempotency_key=$2`, [siteId, idem.key, `namespace:${locked.rows[0].namespace_id}`, `deleted:${createHash43("sha256").update(body3.subjectRef).digest("hex").slice(0, 16)}`, JSON.stringify(counts)]);
|
|
57612
57188
|
await client2.query("COMMIT");
|
|
57613
57189
|
return c.json({ ok: true, deleted: true, counts }, 200, noStore);
|
|
57614
57190
|
} catch (error) {
|
|
@@ -57652,7 +57228,7 @@ analyticsApp.post("/sites/:siteId/privacy/namespace/delete", auth4, async (c) =>
|
|
|
57652
57228
|
await client2.query(
|
|
57653
57229
|
`INSERT INTO analytics_privacy_audits(id,site_id,namespace_ref,action,idempotency_key,actor_user_id,result_code,affected_counts,completed_at)
|
|
57654
57230
|
VALUES($1,$2,$3,'deletion_completed',$4,$5,'deleted',$6::jsonb,now()) ON CONFLICT(site_id,idempotency_key) DO NOTHING`,
|
|
57655
|
-
[
|
|
57231
|
+
[randomUUID38(), siteId, `deleted:${createHash43("sha256").update(body3.namespaceId).digest("hex").slice(0, 16)}`, body3.idempotencyKey, userId, JSON.stringify(counts)]
|
|
57656
57232
|
);
|
|
57657
57233
|
await client2.query("COMMIT");
|
|
57658
57234
|
return c.json({ ok: true, deleted: true, counts }, 200, noStore);
|
|
@@ -57984,7 +57560,7 @@ async function deliverPendingAnalyticsCrmImports(limit = 10) {
|
|
|
57984
57560
|
}
|
|
57985
57561
|
|
|
57986
57562
|
// src/api/analytics-activation-dispatcher.ts
|
|
57987
|
-
import { randomUUID as
|
|
57563
|
+
import { randomUUID as randomUUID39 } from "crypto";
|
|
57988
57564
|
function parseAnalyticsActivationDestinationProviderConfig(platform, value) {
|
|
57989
57565
|
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
57990
57566
|
const config = value;
|
|
@@ -58063,7 +57639,7 @@ async function claimAnalyticsActivationJobs(limit = 10) {
|
|
|
58063
57639
|
}));
|
|
58064
57640
|
}
|
|
58065
57641
|
async function beginAttempt(job, stableEventId) {
|
|
58066
|
-
const id2 =
|
|
57642
|
+
const id2 = randomUUID39();
|
|
58067
57643
|
const result3 = await getAnalyticsPool().query(
|
|
58068
57644
|
`INSERT INTO analytics_activation_delivery_attempts(
|
|
58069
57645
|
id, job_id, destination_id, mapping_version, attempt_number, provider_event_id, actor
|
|
@@ -58448,7 +58024,7 @@ async function pollPendingGoogleActivationDiagnostics(limit = 10, deadlineMs = D
|
|
|
58448
58024
|
}
|
|
58449
58025
|
|
|
58450
58026
|
// src/api/analytics-reconciliation.ts
|
|
58451
|
-
import { createHash as
|
|
58027
|
+
import { createHash as createHash44, randomUUID as randomUUID40 } from "crypto";
|
|
58452
58028
|
var RECONCILIATION_INTERVAL_SECONDS = 15 * 60;
|
|
58453
58029
|
var WEBHOOK_ONLY_RECHECK_SECONDS = 24 * 60 * 60;
|
|
58454
58030
|
var LEASE_SECONDS = 90;
|
|
@@ -58472,7 +58048,7 @@ var defaultDependencies2 = {
|
|
|
58472
58048
|
input: input.payload,
|
|
58473
58049
|
classification: "read",
|
|
58474
58050
|
operationKind: "sync",
|
|
58475
|
-
requestId:
|
|
58051
|
+
requestId: randomUUID40()
|
|
58476
58052
|
});
|
|
58477
58053
|
},
|
|
58478
58054
|
async resolveMappedCrmPerson(input) {
|
|
@@ -58575,14 +58151,14 @@ function crmReadInput(provider, sourceAccountRef, cursorValue, now) {
|
|
|
58575
58151
|
}
|
|
58576
58152
|
}
|
|
58577
58153
|
function crmOutcomeSourceEventId(outcome) {
|
|
58578
|
-
const digest23 =
|
|
58154
|
+
const digest23 = createHash44("sha256").update(`${outcome.provider}:${outcome.sourceRecordId}:${outcome.updatedAt}:${outcome.tombstone}`).digest("hex").slice(0, 40);
|
|
58579
58155
|
return `crm:${outcome.provider}:${digest23}`;
|
|
58580
58156
|
}
|
|
58581
58157
|
function analyticsCrmOutcomeToExternalEvent(outcome, sourceAccountRef) {
|
|
58582
58158
|
const sourceEventId = crmOutcomeSourceEventId(outcome);
|
|
58583
58159
|
return {
|
|
58584
58160
|
schemaVersion: 1,
|
|
58585
|
-
eventId: `crm_${
|
|
58161
|
+
eventId: `crm_${createHash44("sha256").update(sourceEventId).digest("hex").slice(0, 24)}`,
|
|
58586
58162
|
sourceEventId,
|
|
58587
58163
|
source: outcome.provider,
|
|
58588
58164
|
sourceAccountRef,
|
|
@@ -58717,6 +58293,7 @@ async function ensureDueJobs() {
|
|
|
58717
58293
|
FROM analytics_connections c
|
|
58718
58294
|
LEFT JOIN analytics_reconciliation_jobs j ON j.connection_id=c.id
|
|
58719
58295
|
WHERE c.readiness <> 'disabled' AND j.connection_id IS NULL
|
|
58296
|
+
AND c.provider NOT IN ('salesforce','pipedrive')
|
|
58720
58297
|
AND (
|
|
58721
58298
|
c.provider IN ('callrail','twilio')
|
|
58722
58299
|
OR EXISTS (
|
|
@@ -58738,7 +58315,7 @@ async function ensureDueJobs() {
|
|
|
58738
58315
|
await db.query(
|
|
58739
58316
|
`INSERT INTO analytics_reconciliation_jobs(id, connection_id)
|
|
58740
58317
|
VALUES ($1,$2) ON CONFLICT(connection_id) DO NOTHING`,
|
|
58741
|
-
[
|
|
58318
|
+
[randomUUID40(), connection.id]
|
|
58742
58319
|
);
|
|
58743
58320
|
}
|
|
58744
58321
|
}
|
|
@@ -58747,10 +58324,12 @@ async function claimAnalyticsReconciliationJobs(limit = 10, leaseSeconds = LEASE
|
|
|
58747
58324
|
await ensureDueJobs();
|
|
58748
58325
|
const result3 = await getAnalyticsPool().query(
|
|
58749
58326
|
`WITH due AS (
|
|
58750
|
-
SELECT id FROM analytics_reconciliation_jobs
|
|
58751
|
-
|
|
58752
|
-
|
|
58753
|
-
|
|
58327
|
+
SELECT j.id FROM analytics_reconciliation_jobs j
|
|
58328
|
+
JOIN analytics_connections c ON c.id=j.connection_id
|
|
58329
|
+
WHERE j.next_attempt_at <= now()
|
|
58330
|
+
AND c.provider NOT IN ('salesforce','pipedrive')
|
|
58331
|
+
AND (j.status='pending' OR (j.status='leased' AND j.lease_until < now()))
|
|
58332
|
+
ORDER BY j.next_attempt_at, j.created_at
|
|
58754
58333
|
FOR UPDATE SKIP LOCKED
|
|
58755
58334
|
LIMIT $1
|
|
58756
58335
|
)
|
|
@@ -58784,7 +58363,8 @@ async function loadScope(jobId2) {
|
|
|
58784
58363
|
WHERE sr.site_id=c.site_id AND sr.connection_id=c.id AND sr.state <> 'cancelled'
|
|
58785
58364
|
ORDER BY sr.created_at DESC LIMIT 1
|
|
58786
58365
|
) latest_sync ON true
|
|
58787
|
-
WHERE j.id=$1 AND j.status='leased' AND j.lease_until > now()
|
|
58366
|
+
WHERE j.id=$1 AND j.status='leased' AND j.lease_until > now()
|
|
58367
|
+
AND c.provider NOT IN ('salesforce','pipedrive')`,
|
|
58788
58368
|
[jobId2]
|
|
58789
58369
|
);
|
|
58790
58370
|
return result3.rows[0] ?? null;
|
|
@@ -58878,7 +58458,7 @@ async function deferAnalyticsReconciliationJob(input) {
|
|
|
58878
58458
|
connectionId: input.connectionId,
|
|
58879
58459
|
safeErrorCode: errorCode2,
|
|
58880
58460
|
nextRunAt: new Date(Date.now() + delaySeconds * 1e3).toISOString(),
|
|
58881
|
-
receiptFingerprint:
|
|
58461
|
+
receiptFingerprint: createHash44("sha256").update(`${input.jobId}:${input.attempts}:${errorCode2}`).digest("hex")
|
|
58882
58462
|
});
|
|
58883
58463
|
}
|
|
58884
58464
|
}
|
|
@@ -58989,7 +58569,7 @@ async function reconcileAnalyticsConnection(job, dependencies = defaultDependenc
|
|
|
58989
58569
|
deduplicated: duplicates,
|
|
58990
58570
|
rejected: page3.rejected,
|
|
58991
58571
|
hasMore: page3.hasMore,
|
|
58992
|
-
receiptFingerprint:
|
|
58572
|
+
receiptFingerprint: createHash44("sha256").update(`${job.id}:${JSON.stringify(page3.nextCursor)}:${replayed}:${duplicates}`).digest("hex"),
|
|
58993
58573
|
scheduleConfigured: Boolean(scope.sync_id),
|
|
58994
58574
|
scheduleIntervalSeconds: scope.sync_interval_seconds ?? null
|
|
58995
58575
|
}
|
|
@@ -59026,7 +58606,7 @@ async function drainAnalyticsReconciliation(limit = 5, deadlineMs = Date.now() +
|
|
|
59026
58606
|
}
|
|
59027
58607
|
|
|
59028
58608
|
// src/api/analytics-scheduled-lanes.ts
|
|
59029
|
-
import { randomUUID as
|
|
58609
|
+
import { randomUUID as randomUUID41 } from "crypto";
|
|
59030
58610
|
var ANALYTICS_SCHEDULED_LANES = [
|
|
59031
58611
|
{ key: "rollup", intervalMinutes: 15, catchUpIntervals: 2, maxAttempts: 4 },
|
|
59032
58612
|
{ key: "form_delivery", intervalMinutes: 1, catchUpIntervals: 3, maxAttempts: 5 },
|
|
@@ -59073,7 +58653,7 @@ var PostgresAnalyticsScheduledOccurrenceStore = class {
|
|
|
59073
58653
|
(id,lane_key,scheduled_for,status,attempt_count,max_attempts,next_attempt_at,created_at,updated_at)
|
|
59074
58654
|
VALUES ($1,$2,$3,'pending',0,$4,$3,now(),now())
|
|
59075
58655
|
ON CONFLICT (lane_key,scheduled_for) DO NOTHING`,
|
|
59076
|
-
[
|
|
58656
|
+
[randomUUID41(), definition.key, scheduledFor, definition.maxAttempts]
|
|
59077
58657
|
);
|
|
59078
58658
|
inserted += Number(result3.rowCount ?? 0);
|
|
59079
58659
|
}
|
|
@@ -59156,7 +58736,7 @@ var PostgresAnalyticsScheduledOccurrenceStore = class {
|
|
|
59156
58736
|
async function runAnalyticsScheduledLanes(executors, options = {}) {
|
|
59157
58737
|
const store = options.store ?? new PostgresAnalyticsScheduledOccurrenceStore();
|
|
59158
58738
|
const now = options.now ?? (() => /* @__PURE__ */ new Date());
|
|
59159
|
-
const owner5 = options.owner ?? `cron:${
|
|
58739
|
+
const owner5 = options.owner ?? `cron:${randomUUID41()}`;
|
|
59160
58740
|
const leaseMs = options.leaseMs ?? 6e4;
|
|
59161
58741
|
const maxClaims = options.maxClaims ?? 12;
|
|
59162
58742
|
const firstNow = now();
|
|
@@ -59206,13 +58786,13 @@ import { Hono as Hono37 } from "hono";
|
|
|
59206
58786
|
import { z as z44 } from "zod";
|
|
59207
58787
|
|
|
59208
58788
|
// src/api/scheduled-artifact-owner.ts
|
|
59209
|
-
import { createHash as
|
|
58789
|
+
import { createHash as createHash45 } from "crypto";
|
|
59210
58790
|
function scheduledArtifactOwnerIdForApiKey(apiKey) {
|
|
59211
|
-
return
|
|
58791
|
+
return createHash45("sha256").update(apiKey).digest("hex").slice(0, 24);
|
|
59212
58792
|
}
|
|
59213
58793
|
|
|
59214
58794
|
// src/api/scheduled-run-view-links.ts
|
|
59215
|
-
import { createHash as
|
|
58795
|
+
import { createHash as createHash46, randomBytes as randomBytes6, randomUUID as randomUUID42 } from "crypto";
|
|
59216
58796
|
var schemaReady3 = false;
|
|
59217
58797
|
async function ensureScheduledRunViewLinksSchema() {
|
|
59218
58798
|
if (schemaReady3) return;
|
|
@@ -59266,7 +58846,7 @@ async function ensureScheduledRunViewLinksSchema() {
|
|
|
59266
58846
|
schemaReady3 = true;
|
|
59267
58847
|
}
|
|
59268
58848
|
function tokenHash2(token7) {
|
|
59269
|
-
return
|
|
58849
|
+
return createHash46("sha256").update(token7).digest("hex");
|
|
59270
58850
|
}
|
|
59271
58851
|
function mapRow(row) {
|
|
59272
58852
|
return {
|
|
@@ -59288,7 +58868,7 @@ async function createScheduledRunViewLink(input) {
|
|
|
59288
58868
|
const now = input.now ?? /* @__PURE__ */ new Date();
|
|
59289
58869
|
const token7 = randomBytes6(32).toString("base64url");
|
|
59290
58870
|
const record7 = {
|
|
59291
|
-
shareId:
|
|
58871
|
+
shareId: randomUUID42(),
|
|
59292
58872
|
ownerId: input.ownerId,
|
|
59293
58873
|
runId: input.runId,
|
|
59294
58874
|
artifactId: input.artifactId,
|
|
@@ -59353,7 +58933,7 @@ async function revokeScheduledRunViewLink(ownerId3, runId, shareId, now = /* @__
|
|
|
59353
58933
|
}
|
|
59354
58934
|
|
|
59355
58935
|
// src/personal-authority/render.ts
|
|
59356
|
-
import { createHash as
|
|
58936
|
+
import { createHash as createHash47 } from "crypto";
|
|
59357
58937
|
function escapeHtml8(value) {
|
|
59358
58938
|
return value.replace(/[&<>"']/g, (character) => ({
|
|
59359
58939
|
"&": "&",
|
|
@@ -59413,13 +58993,13 @@ ${section(flags.finalCta && Boolean(finalCta), `<section class="section cta" id=
|
|
|
59413
58993
|
html,
|
|
59414
58994
|
filename: `${input.name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "") || "personal-authority"}.html`,
|
|
59415
58995
|
bytes: bytes2,
|
|
59416
|
-
sha256:
|
|
58996
|
+
sha256: createHash47("sha256").update(html).digest("hex"),
|
|
59417
58997
|
generatedAt: generatedAtIso
|
|
59418
58998
|
};
|
|
59419
58999
|
}
|
|
59420
59000
|
|
|
59421
59001
|
// src/personal-authority/render-v2.ts
|
|
59422
|
-
import { createHash as
|
|
59002
|
+
import { createHash as createHash48 } from "crypto";
|
|
59423
59003
|
var FONT_STACKS = Object.freeze({
|
|
59424
59004
|
"editorial-serif": "Iowan Old Style, Baskerville, Times New Roman, serif",
|
|
59425
59005
|
"modern-sans": "Avenir Next, Avenir, Helvetica Neue, Arial, sans-serif",
|
|
@@ -59523,13 +59103,13 @@ ${section2(flags.finalCta && Boolean(finalCta), `<section class="section cta" id
|
|
|
59523
59103
|
html,
|
|
59524
59104
|
filename: `${input.name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "") || "personal-authority"}.html`,
|
|
59525
59105
|
bytes: bytes2,
|
|
59526
|
-
sha256:
|
|
59106
|
+
sha256: createHash48("sha256").update(html).digest("hex"),
|
|
59527
59107
|
generatedAt: generatedAtIso
|
|
59528
59108
|
};
|
|
59529
59109
|
}
|
|
59530
59110
|
|
|
59531
59111
|
// src/newsroom-publisher/render.ts
|
|
59532
|
-
import { createHash as
|
|
59112
|
+
import { createHash as createHash49 } from "crypto";
|
|
59533
59113
|
function escapeHtml10(value) {
|
|
59534
59114
|
return value.replace(/[&<>"']/g, (character) => ({
|
|
59535
59115
|
"&": "&",
|
|
@@ -59635,13 +59215,13 @@ body{overflow-x:hidden}.lead-story__body,.lead-support__item,.story-card__body{m
|
|
|
59635
59215
|
@media(max-width:620px){.desk-section__grid--panorama,.desk-section__grid--mosaic,.desk-section__grid--tiles{grid-template-columns:1fr}.story-card--panorama{display:block}.story-card--panorama h3,.story-card--mosaic-lead h3{font-size:34px}.story-card--mosaic-lead{grid-column:auto;grid-row:auto}.desk-section__grid--tiles>.story-card:nth-child(3n+2){margin-top:0}}
|
|
59636
59216
|
</style></head><body data-theme="${escapeHtml10(config.theme)}" id="top" data-scheduled-renderer="newsroom_publisher_v1">${ticker}${masthead}${navigation}<main>${leadGrid}${latest}${sections}${newsletter}${pressRoom}${trustCenter}</main>${trustFooter}</body></html>`;
|
|
59637
59217
|
const bytes2 = Buffer.byteLength(html);
|
|
59638
|
-
const sha2564 =
|
|
59218
|
+
const sha2564 = createHash49("sha256").update(html).digest("hex");
|
|
59639
59219
|
const filename2 = `${brand.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "") || "newsroom"}-news-site.html`;
|
|
59640
59220
|
return { html, filename: filename2, bytes: bytes2, sha256: sha2564, generatedAt: generatedAtIso };
|
|
59641
59221
|
}
|
|
59642
59222
|
|
|
59643
59223
|
// src/blog-article/render.ts
|
|
59644
|
-
import { createHash as
|
|
59224
|
+
import { createHash as createHash50 } from "crypto";
|
|
59645
59225
|
function escapeHtml11(value) {
|
|
59646
59226
|
return value.replace(
|
|
59647
59227
|
/[&<>"']/g,
|
|
@@ -59729,7 +59309,7 @@ function renderBlogArticleV1(input, config, generatedAt) {
|
|
|
59729
59309
|
:root{--ink:#10213d;--ink2:#1c355a;--blue:#2563eb;--blue2:#1749b6;--mint:#45d5aa;--paper:#f7f5f0;--line:#dce4ef;--card:#fff;--body:#475569;--serif:Iowan Old Style,Palatino Linotype,Palatino,Georgia,serif;--sans:Inter,Avenir Next,ui-sans-serif,system-ui,sans-serif}body[data-theme="slate"]{--ink:#1e293b;--ink2:#334155;--blue:#475569;--blue2:#1e293b;--mint:#94a3b8;--paper:#f8fafc}body[data-theme="forest"]{--ink:#12352e;--ink2:#23584c;--blue:#147d64;--blue2:#0c5b48;--mint:#79d8bd;--paper:#f4f8f3}*{box-sizing:border-box}html{scroll-behavior:smooth;background:var(--paper)}body{margin:0;color:#252a33;background:var(--paper);font-family:var(--sans);line-height:1.6}a{color:inherit}button{font:inherit}button:focus-visible,a:focus-visible{outline:3px solid var(--mint);outline-offset:3px}.progress{position:fixed;z-index:50;top:0;left:0;height:4px;width:0;background:var(--mint)}.hero{position:relative;overflow:hidden;color:#fff;background:var(--ink)}.hero:after{position:absolute;right:-110px;top:-150px;width:420px;height:420px;border:1px solid #ffffff1a;border-radius:50%;content:""}.hero-inner{position:relative;z-index:1;max-width:1240px;margin:auto;padding:58px 42px 126px}.breadcrumb{display:flex;gap:8px;margin-bottom:34px;color:#dbeafecc;font-size:14px}.eyebrow{display:block;color:var(--blue);font-size:12px;font-weight:800;letter-spacing:.16em;text-transform:uppercase}.hero .eyebrow{color:var(--mint)}h1,h2,h3,p{margin-top:0}.hero h1{max-width:1000px;margin:14px 0 24px;font:700 clamp(44px,6vw,78px)/.98 var(--serif);letter-spacing:-.035em}.hero .dek{max-width:780px;color:#dbeafe;font-size:20px}.contributors{margin-top:30px;color:#eff6ff;font-size:14px}.contributors a{font-weight:800}.meta{display:flex;flex-wrap:wrap;gap:12px;margin-top:6px;color:#dbeafecc}.layout{position:relative;z-index:2;display:grid;grid-template-columns:minmax(0,760px) 290px;gap:64px;max-width:1240px;margin:-78px auto 0;padding:0 42px 80px}.main{min-width:0}.takeaways{padding:38px 44px;border-radius:24px;background:#fff;box-shadow:0 24px 70px #10213d24}.takeaways h2{margin:5px 0 20px;font:700 32px/1.1 var(--serif);color:var(--ink)}.takeaways ul{display:grid;gap:16px;margin:0;padding:0;list-style:none}.takeaways li{position:relative;padding-left:26px;color:var(--body);font-size:17px}.takeaways li:before{position:absolute;left:2px;top:.7em;width:8px;height:8px;border-radius:50%;background:var(--blue);content:""}.intro{padding:40px 0 4px}.intro p,.article-section>p{margin-bottom:22px;color:var(--body);font:400 18px/1.75 var(--sans)}.article-section{scroll-margin-top:28px;padding-top:45px}.article-section h2,.faq h2{margin:6px 0 20px;color:var(--ink);font:700 38px/1.08 var(--serif);letter-spacing:-.02em}.article-section ul{display:grid;gap:10px;margin:22px 0;padding-left:24px;color:var(--body);font-size:17px}.article-section li::marker{color:var(--blue)}.callout{margin:34px 0;padding:24px 28px;border-left:4px solid var(--blue);border-radius:0 16px 16px 0;background:#fff}.callout span{color:var(--blue);font-size:11px;font-weight:800;letter-spacing:.13em;text-transform:uppercase}.callout h3{margin:5px 0 8px;color:var(--ink);font:700 24px/1.15 var(--serif)}.callout p{margin:0;color:var(--body)}.rail{padding-top:0}.sidebar-media{overflow:hidden;margin:0 0 18px;border:1px solid #dbeafe;border-radius:16px;background:#fff}.sidebar-media img,.sidebar-media svg{display:block;width:100%;aspect-ratio:16/9;object-fit:cover}.sidebar-media figcaption{padding:10px 13px;color:#64748b;font-size:11px}.disclosure{margin-bottom:28px;border-top:1px solid #dbeafe;border-bottom:1px solid #dbeafe}.disclosure button{display:flex;width:100%;align-items:center;justify-content:space-between;gap:14px;padding:15px 0;border:0;color:#64748b;background:transparent;text-align:left;font-size:12px;cursor:pointer}.disclosure button b{color:var(--blue);font-size:18px;transition:transform .2s}.disclosure button[aria-expanded="true"] b{transform:rotate(180deg)}.disclosure p{padding:0 0 16px;margin:0;color:#64748b;font-size:12px}.toc{position:sticky;top:30px;padding:22px;border:1px solid var(--line);border-radius:16px;background:#fff;box-shadow:0 2px 5px #10213d12}.toc header{display:flex;align-items:center;justify-content:space-between}.toc header strong{color:var(--ink);font:700 21px/1 var(--serif)}.toc header button{width:34px;height:34px;border:0;border-radius:50%;color:var(--blue);background:transparent;cursor:pointer}.toc nav{display:grid;margin-top:14px}.toc nav a{display:flex;align-items:flex-start;gap:11px;padding:8px 0;color:#64748b;text-decoration:none;font-size:13px;line-height:1.35}.toc nav i{width:8px;height:8px;margin-top:5px;border:2px solid #bfdbfe;border-radius:50%}.toc nav a[aria-current="location"]{color:var(--ink);font-weight:800}.toc nav a[aria-current="location"] i{border-color:var(--blue);background:var(--blue)}.back-top{width:100%;margin-top:18px;padding:16px 0 0;border:0;border-top:1px solid var(--line);color:var(--blue);background:transparent;text-align:right;font-size:13px;font-weight:800;cursor:pointer}.faq{scroll-margin-top:28px;padding-top:64px}.faq>div{border-top:1px solid var(--line);border-bottom:1px solid var(--line)}.faq article+article{border-top:1px solid var(--line)}.faq h3{margin:0}.faq h3 button{display:flex;width:100%;align-items:center;justify-content:space-between;gap:18px;padding:19px 0;border:0;color:var(--ink);background:transparent;text-align:left;font-weight:800;cursor:pointer}.faq h3 b{color:var(--blue);font-size:22px}.faq article>p{padding:0 0 20px;margin:0;color:var(--body);font-size:16px}.author-card{margin-top:64px;padding:32px 36px;border-radius:18px;background:#fff}.article-actions{display:flex;flex-wrap:wrap;justify-content:space-between;gap:14px}.article-actions button{display:inline-flex;min-height:46px;align-items:center;justify-content:center;gap:8px;padding:8px 18px;border:2px solid var(--blue);border-radius:999px;color:var(--ink);background:#fff;font-weight:800;cursor:pointer}.article-actions button:hover{color:#fff;background:var(--blue)}.action-status{min-height:20px;margin:8px 0 0;color:var(--blue);text-align:right;font-size:13px;font-weight:700}.author-grid{display:grid;grid-template-columns:auto 1fr auto;gap:22px;align-items:center;margin-top:24px}.author-portrait{width:88px;height:88px;border-radius:50%;object-fit:cover}.author-initials{display:grid;place-items:center;color:var(--ink);background:#fecdd3;font-size:22px;font-weight:900}.author-grid span{color:#64748b;font-size:13px}.author-grid h2{margin:2px 0;color:var(--ink);font:700 27px/1 var(--serif)}.author-grid h2 a{text-decoration:none}.author-grid p{margin:8px 0;color:#64748b;font-size:14px}.author-grid nav{display:flex;flex-wrap:wrap;gap:14px}.author-grid nav a{color:#64748b;font-size:12px}.author-more{display:inline-flex;min-height:48px;align-items:center;justify-content:center;padding:10px 24px;border:2px solid var(--blue);color:var(--blue);text-align:center;text-decoration:none;font-size:13px;font-weight:800}.author-bio{margin:24px 0 0!important;padding-top:20px;border-top:1px solid var(--line);color:var(--body);font-size:16px}dialog{width:min(720px,calc(100% - 30px));max-height:calc(100dvh - 30px);padding:0;border:0;border-radius:18px;color:var(--ink);background:#fff;box-shadow:0 24px 70px #10213d38}dialog::backdrop{background:#0f172a7a;backdrop-filter:blur(2px)}dialog>div{position:relative;padding:30px}dialog h2{margin:0 50px 2px 0;font:700 30px/1.1 var(--serif)}dialog>div>p{color:#64748b}.dialog-close{position:absolute;top:13px;right:13px;width:44px;height:44px;border:0;border-radius:50%;color:var(--blue);background:transparent;font-size:29px;cursor:pointer}dialog section{border-top:1px solid var(--line)}dialog section button{display:block;width:100%;padding:17px 5px;border:0;border-bottom:1px solid var(--line);color:var(--body);background:#fff;text-align:left;line-height:1.65;cursor:pointer}.citation-status{min-height:22px;margin:14px 0 0!important;color:var(--blue)!important;font-size:13px;font-weight:800}.generated{max-width:1156px;margin:-52px auto 50px;padding:0 42px;color:#94a3b8;font-size:11px}@media(max-width:900px){.layout{display:block}.rail{display:none}.hero-inner{padding-bottom:116px}}@media(max-width:620px){.hero-inner{padding:36px 20px 104px}.hero h1{font-size:46px}.hero .dek{font-size:17px}.layout{margin-top:-70px;padding:0 16px 54px}.takeaways{padding:28px 24px}.article-section h2,.faq h2{font-size:32px}.author-card{padding:24px}.article-actions{display:grid;justify-content:start}.author-grid{grid-template-columns:1fr;gap:12px}.author-more{width:100%}dialog>div{padding:24px}.generated{padding:0 20px}}
|
|
59730
59310
|
</style></head><body data-theme="${escapeHtml11(config.theme)}" data-scheduled-renderer="blog_article_v1"><div class="progress" aria-hidden="true"></div><header class="hero"><div class="hero-inner"><nav class="breadcrumb" aria-label="Breadcrumb"><a href="${safeHref4(input.canonicalUrl)}">${escapeHtml11(input.category)}</a><span>/</span><span>Article</span></nav><span class="eyebrow">${escapeHtml11(input.eyebrow)}</span><h1>${escapeHtml11(input.title)}</h1>${input.dek ? `<p class="dek">${escapeHtml11(input.dek)}</p>` : ""}<div class="contributors">${contributorText}<div class="meta"><time datetime="${escapeHtml11(articleDate)}">Updated ${formatDate2(articleDate)}</time><span>\u2022</span><span>${input.readTimeMinutes} min read</span>${input.reviewer ? "<span>\u2022</span><strong>Expert reviewed</strong>" : ""}</div></div></div></header><main class="layout"><article class="main"><section class="takeaways"><span class="eyebrow">The short answer</span><h2>Key takeaways</h2><ul>${input.keyTakeaways.map((item) => `<li>${escapeHtml11(item)}</li>`).join("")}</ul></section><section class="intro">${input.introduction.map((paragraph) => `<p>${escapeHtml11(paragraph)}</p>`).join("")}</section>${sections}${faq}${author}</article><div class="rail">${media}${disclosure}${toc}</div></main>${config.showGeneratedAt ? `<p class="generated">Rendered ${formatDate2(generatedAtIso)} by MCP Scraper.</p>` : ""}${citationDialog}<script>(()=>{const citations=${jsonForScript(citationValues)};const canonical=${jsonForScript(input.canonicalUrl)};const title=${jsonForScript(input.title)};const progress=document.querySelector('.progress');const tocLinks=[...document.querySelectorAll('.toc nav a')];const targets=tocLinks.map(link=>document.querySelector(link.hash)).filter(Boolean);const update=()=>{const max=document.documentElement.scrollHeight-innerHeight;if(progress)progress.style.width=(max>0?scrollY/max*100:0)+'%';let active=targets[0]?.id;for(const target of targets){if(target.getBoundingClientRect().top<=innerHeight*.55)active=target.id}tocLinks.forEach(link=>link.toggleAttribute('aria-current',link.hash==='#'+active));tocLinks.forEach(link=>{if(link.hash==='#'+active)link.setAttribute('aria-current','location');else link.removeAttribute('aria-current')})};addEventListener('scroll',update,{passive:true});addEventListener('resize',update);update();document.querySelectorAll('.faq h3 button').forEach(button=>button.addEventListener('click',()=>{const panel=document.getElementById(button.getAttribute('aria-controls'));const open=button.getAttribute('aria-expanded')==='true';button.setAttribute('aria-expanded',String(!open));panel.hidden=open;button.querySelector('b').textContent=open?'+':'\u2212'}));const disclosure=document.querySelector('.disclosure button');disclosure?.addEventListener('click',()=>{const panel=document.getElementById(disclosure.getAttribute('aria-controls'));const open=disclosure.getAttribute('aria-expanded')==='true';disclosure.setAttribute('aria-expanded',String(!open));panel.hidden=open});const tocToggle=document.querySelector('.toc header button');tocToggle?.addEventListener('click',()=>{const nav=document.getElementById('toc-links');const open=tocToggle.getAttribute('aria-expanded')==='true';tocToggle.setAttribute('aria-expanded',String(!open));nav.hidden=open;tocToggle.textContent=open?'\u2304':'\u2303'});document.querySelector('.back-top')?.addEventListener('click',()=>scrollTo({top:0,behavior:'smooth'}));const copy=async text=>{try{await navigator.clipboard.writeText(text)}catch{const area=document.createElement('textarea');area.value=text;area.style.position='fixed';area.style.opacity='0';document.body.append(area);area.select();document.execCommand('copy');area.remove()}};const dialog=document.getElementById('citation-dialog');document.querySelector('[data-cite]')?.addEventListener('click',()=>dialog.showModal());document.querySelector('.dialog-close')?.addEventListener('click',()=>dialog.close());dialog?.addEventListener('click',event=>{if(event.target===dialog)dialog.close()});document.querySelectorAll('[data-citation]').forEach(button=>button.addEventListener('click',async()=>{const style=button.dataset.citation;await copy(citations[style]);document.querySelector('.citation-status').textContent=style+' citation copied to clipboard.'}));document.querySelector('[data-share]')?.addEventListener('click',async()=>{const status=document.querySelector('.action-status');if(navigator.share){try{await navigator.share({title,url:canonical});status.textContent='Sharing options opened.';return}catch(error){if(error.name==='AbortError')return}}await copy(canonical);status.textContent='Article link copied to clipboard.'})})()</script></body></html>`;
|
|
59731
59311
|
const bytes2 = Buffer.byteLength(html);
|
|
59732
|
-
const sha2564 =
|
|
59312
|
+
const sha2564 = createHash50("sha256").update(html).digest("hex");
|
|
59733
59313
|
return {
|
|
59734
59314
|
html,
|
|
59735
59315
|
filename: "blog-article.html",
|
|
@@ -60032,7 +59612,7 @@ scheduledResultApp.delete("/schedule-runs/:runId/view-links/:shareId", async (c)
|
|
|
60032
59612
|
import { Hono as Hono38 } from "hono";
|
|
60033
59613
|
|
|
60034
59614
|
// src/scheduled-artifacts/scheduled-run-artifact-store.ts
|
|
60035
|
-
import { createHash as
|
|
59615
|
+
import { createHash as createHash51 } from "crypto";
|
|
60036
59616
|
var SCHEDULED_RUN_ARTIFACT_PREFIX = "scheduled-run-artifacts/";
|
|
60037
59617
|
var SCHEDULED_RUN_ARTIFACT_DOWNLOAD_TTL_MS = 15 * 60 * 1e3;
|
|
60038
59618
|
var SCHEDULED_RUN_ARTIFACT_MAX_BYTES = 2e6;
|
|
@@ -60048,7 +59628,7 @@ function policy5() {
|
|
|
60048
59628
|
};
|
|
60049
59629
|
}
|
|
60050
59630
|
function runStorageSegment(runId) {
|
|
60051
|
-
return /^[a-zA-Z0-9_-]{1,160}$/.test(runId) ? runId : `run-${
|
|
59631
|
+
return /^[a-zA-Z0-9_-]{1,160}$/.test(runId) ? runId : `run-${createHash51("sha256").update(runId).digest("hex").slice(0, 32)}`;
|
|
60052
59632
|
}
|
|
60053
59633
|
async function createScheduledRunArtifact(args) {
|
|
60054
59634
|
if (args.rendered.bytes > SCHEDULED_RUN_ARTIFACT_MAX_BYTES) {
|
|
@@ -60240,11 +59820,11 @@ scheduledArtifactInternalApp.post("/render", async (c) => {
|
|
|
60240
59820
|
});
|
|
60241
59821
|
|
|
60242
59822
|
// src/api/personal-assistant-routes.ts
|
|
60243
|
-
import { createHash as
|
|
59823
|
+
import { createHash as createHash59, randomUUID as randomUUID44 } from "crypto";
|
|
60244
59824
|
import { Hono as Hono41 } from "hono";
|
|
60245
59825
|
|
|
60246
59826
|
// src/api/personal-assistant-schedule-readiness.ts
|
|
60247
|
-
import { createHash as
|
|
59827
|
+
import { createHash as createHash52 } from "crypto";
|
|
60248
59828
|
import { z as z45 } from "zod";
|
|
60249
59829
|
var opaqueRef = z45.string().trim().regex(/^[a-z][a-z0-9_]*_[A-Za-z0-9_-]{3,128}$/);
|
|
60250
59830
|
var isoTimestamp2 = z45.iso.datetime({ offset: true });
|
|
@@ -60317,7 +59897,7 @@ function canonicalJson2(value) {
|
|
|
60317
59897
|
return JSON.stringify(value);
|
|
60318
59898
|
}
|
|
60319
59899
|
function digest2(value) {
|
|
60320
|
-
return
|
|
59900
|
+
return createHash52("sha256").update(canonicalJson2(value)).digest("hex");
|
|
60321
59901
|
}
|
|
60322
59902
|
function validTimezone2(timezone) {
|
|
60323
59903
|
try {
|
|
@@ -60578,7 +60158,7 @@ async function evaluateScheduleReadiness(rawInput, dependencies) {
|
|
|
60578
60158
|
}
|
|
60579
60159
|
|
|
60580
60160
|
// src/api/personal-assistant-command-builder.ts
|
|
60581
|
-
import { createHash as
|
|
60161
|
+
import { createHash as createHash53 } from "crypto";
|
|
60582
60162
|
function canonicalJson3(value) {
|
|
60583
60163
|
return JSON.stringify(value, (_key, entry) => {
|
|
60584
60164
|
if (!entry || typeof entry !== "object" || Array.isArray(entry)) return entry;
|
|
@@ -60586,7 +60166,7 @@ function canonicalJson3(value) {
|
|
|
60586
60166
|
});
|
|
60587
60167
|
}
|
|
60588
60168
|
function digest3(value) {
|
|
60589
|
-
return
|
|
60169
|
+
return createHash53("sha256").update(canonicalJson3(value)).digest("hex");
|
|
60590
60170
|
}
|
|
60591
60171
|
function explicitControlIntent(text3) {
|
|
60592
60172
|
const normalized = text3.trim().toLowerCase();
|
|
@@ -60635,7 +60215,7 @@ async function buildPersonalAssistantCommand(context, input) {
|
|
|
60635
60215
|
}
|
|
60636
60216
|
|
|
60637
60217
|
// src/api/personal-assistant-consent-content.ts
|
|
60638
|
-
import { createHash as
|
|
60218
|
+
import { createHash as createHash54 } from "crypto";
|
|
60639
60219
|
var SUBMITTED_EVIDENCE = Object.freeze({
|
|
60640
60220
|
evidenceVersion: "twilio-toll-free-submission.2026-08-28.v1",
|
|
60641
60221
|
policyVersion: "2026-08-28.v1",
|
|
@@ -60698,7 +60278,7 @@ var ASSISTANT_ENROLLMENT_DISCLOSURE_TEXT = Object.freeze([
|
|
|
60698
60278
|
ASSISTANT_CONSENT_CONTENT_V1.retentionDisclosure,
|
|
60699
60279
|
ASSISTANT_CONSENT_CONTENT_V1.termsDisclosure
|
|
60700
60280
|
].join("\n\n"));
|
|
60701
|
-
var ASSISTANT_ENROLLMENT_DISCLOSURE_DIGEST =
|
|
60281
|
+
var ASSISTANT_ENROLLMENT_DISCLOSURE_DIGEST = createHash54("sha256").update(`${ASSISTANT_CONSENT_CONTENT_V1.policyVersion}\0${ASSISTANT_ENROLLMENT_DISCLOSURE_TEXT}`).digest("hex");
|
|
60702
60282
|
var ASSISTANT_ENROLLMENT_DISCLOSURE_PROJECTION = Object.freeze({
|
|
60703
60283
|
policyVersion: ASSISTANT_CONSENT_CONTENT_V1.policyVersion,
|
|
60704
60284
|
disclosureDigest: ASSISTANT_ENROLLMENT_DISCLOSURE_DIGEST,
|
|
@@ -60709,11 +60289,11 @@ var ASSISTANT_ENROLLMENT_DISCLOSURE_PROJECTION = Object.freeze({
|
|
|
60709
60289
|
});
|
|
60710
60290
|
|
|
60711
60291
|
// src/api/personal-assistant-lifecycle.ts
|
|
60712
|
-
import { createHash as
|
|
60292
|
+
import { createHash as createHash56, randomUUID as randomUUID43 } from "crypto";
|
|
60713
60293
|
import { z as z46 } from "zod";
|
|
60714
60294
|
|
|
60715
60295
|
// src/api/personal-assistant-db.ts
|
|
60716
|
-
import { createHash as
|
|
60296
|
+
import { createHash as createHash55 } from "crypto";
|
|
60717
60297
|
import { Pool } from "pg";
|
|
60718
60298
|
|
|
60719
60299
|
// src/api/personal-assistant-schema.ts
|
|
@@ -60835,7 +60415,7 @@ function assistantDatabaseBindingFingerprint(value) {
|
|
|
60835
60415
|
if (!database) {
|
|
60836
60416
|
throw new AssistantDatabaseError("assistant_database_binding_invalid", "Personal Assistant database name is missing.");
|
|
60837
60417
|
}
|
|
60838
|
-
return
|
|
60418
|
+
return createHash55("sha256").update(`${normalizedNeonHost(parsed.hostname)}\0${database}`).digest("hex");
|
|
60839
60419
|
}
|
|
60840
60420
|
function assistantDatabaseRole(value) {
|
|
60841
60421
|
const role = decodeURIComponent(parseDatabaseUrl(value).username);
|
|
@@ -61123,7 +60703,7 @@ var AssistantLifecycleError = class extends Error {
|
|
|
61123
60703
|
};
|
|
61124
60704
|
|
|
61125
60705
|
// src/api/personal-assistant-service.ts
|
|
61126
|
-
import { createHash as
|
|
60706
|
+
import { createHash as createHash57 } from "crypto";
|
|
61127
60707
|
var PERSONAL_ASSISTANT_INTENT_ENVELOPE_VERSION = "assistant-intent-envelope.v1";
|
|
61128
60708
|
var CONTROL_INTENTS = /* @__PURE__ */ new Set(["help", "status", "approve", "reject", "cancel"]);
|
|
61129
60709
|
var EXPLICIT_TASK_INTENTS = /* @__PURE__ */ new Set([
|
|
@@ -61289,7 +60869,7 @@ function canonicalServiceJson(value) {
|
|
|
61289
60869
|
});
|
|
61290
60870
|
}
|
|
61291
60871
|
function serviceDigest(value) {
|
|
61292
|
-
return
|
|
60872
|
+
return createHash57("sha256").update(canonicalServiceJson(value)).digest("hex");
|
|
61293
60873
|
}
|
|
61294
60874
|
function serviceReceipt(idempotencyKey4, requestDigest2, occurredAt, state2, result3, error = null) {
|
|
61295
60875
|
const receiptRef = `receipt_${serviceDigest({ idempotencyKey: idempotencyKey4, requestDigest: requestDigest2 }).slice(0, 32)}`;
|
|
@@ -62716,7 +62296,7 @@ import twilio3 from "twilio";
|
|
|
62716
62296
|
import { Hono as Hono40 } from "hono";
|
|
62717
62297
|
|
|
62718
62298
|
// src/api/personal-assistant-observability.ts
|
|
62719
|
-
import { createHash as
|
|
62299
|
+
import { createHash as createHash58 } from "crypto";
|
|
62720
62300
|
var OPAQUE_TRACE_REF = /^trace_[A-Za-z0-9_-]{8,128}$/u;
|
|
62721
62301
|
var KINDS = /* @__PURE__ */ new Set([
|
|
62722
62302
|
"purchase_unknown",
|
|
@@ -63413,7 +62993,7 @@ function payloadWithout(input, ...keys) {
|
|
|
63413
62993
|
return Object.fromEntries(Object.entries(input).filter(([key3, value]) => !omitted.has(key3) && value !== void 0));
|
|
63414
62994
|
}
|
|
63415
62995
|
function personalAssistantMessagingServiceReviewDigest(review) {
|
|
63416
|
-
return
|
|
62996
|
+
return createHash59("sha256").update(JSON.stringify({
|
|
63417
62997
|
schemaVersion: "assistant-messaging-service-review.v1",
|
|
63418
62998
|
numberRef: review.numberRef,
|
|
63419
62999
|
connectionRef: review.connectionRef,
|
|
@@ -63547,7 +63127,7 @@ function ownerCaller(c) {
|
|
|
63547
63127
|
throw new OwnerRouteError("not_authenticated", "Authentication is required.", 401);
|
|
63548
63128
|
}
|
|
63549
63129
|
if (ownerUserId2 <= 0n) throw new OwnerRouteError("not_authenticated", "Authentication is required.", 401);
|
|
63550
|
-
const subjectRef = `owner_${
|
|
63130
|
+
const subjectRef = `owner_${createHash59("sha256").update(ownerUserId2.toString()).digest("hex").slice(0, 24)}`;
|
|
63551
63131
|
return { kind: "owner", surface: "rest", ownerUserId: ownerUserId2, subjectRef };
|
|
63552
63132
|
}
|
|
63553
63133
|
function enrollmentRequesterBinding(c, caller2) {
|
|
@@ -63601,7 +63181,7 @@ function publicError2(error, requestRef) {
|
|
|
63601
63181
|
function buildPersonalAssistantOwnerRoutes(options) {
|
|
63602
63182
|
const app2 = new Hono41();
|
|
63603
63183
|
const now = options.now ?? (() => /* @__PURE__ */ new Date());
|
|
63604
|
-
const nextRequestRef = options.requestRef ?? (() => `request_${
|
|
63184
|
+
const nextRequestRef = options.requestRef ?? (() => `request_${randomUUID44().replaceAll("-", "")}`);
|
|
63605
63185
|
const route = (method, path5, mutating, call) => {
|
|
63606
63186
|
app2[method](path5, async (c) => {
|
|
63607
63187
|
const requestRef = nextRequestRef();
|
|
@@ -63876,7 +63456,7 @@ function buildPersonalAssistantOwnerRoutes(options) {
|
|
|
63876
63456
|
var personalAssistantOwnerApp = buildPersonalAssistantOwnerRoutes({ service: getPersonalAssistantService });
|
|
63877
63457
|
|
|
63878
63458
|
// src/api/personal-assistant-browser-handoff-routes.ts
|
|
63879
|
-
import { randomUUID as
|
|
63459
|
+
import { randomUUID as randomUUID45 } from "crypto";
|
|
63880
63460
|
import { Hono as Hono42 } from "hono";
|
|
63881
63461
|
var PERSONAL_ASSISTANT_BROWSER_HANDOFF_PROJECTION_VERSION = "assistant-browser-handoff.v1";
|
|
63882
63462
|
var OPAQUE_REF2 = /^[a-z][a-z0-9]{1,31}_[A-Za-z0-9_-]{3,160}$/;
|
|
@@ -63989,7 +63569,7 @@ function controlUrl(raw) {
|
|
|
63989
63569
|
function buildPersonalAssistantBrowserHandoffRoutes(options) {
|
|
63990
63570
|
const app2 = new Hono42();
|
|
63991
63571
|
const now = options.now ?? (() => /* @__PURE__ */ new Date());
|
|
63992
|
-
const nextRequestRef = options.requestRef ?? (() => `request_${
|
|
63572
|
+
const nextRequestRef = options.requestRef ?? (() => `request_${randomUUID45().replaceAll("-", "")}`);
|
|
63993
63573
|
const json = async (c, operation, created = false) => {
|
|
63994
63574
|
const requestRef = nextRequestRef();
|
|
63995
63575
|
try {
|
|
@@ -64077,7 +63657,7 @@ function buildPersonalAssistantBrowserHandoffRoutes(options) {
|
|
|
64077
63657
|
}
|
|
64078
63658
|
|
|
64079
63659
|
// src/api/personal-assistant-browser-profile-routes.ts
|
|
64080
|
-
import { randomUUID as
|
|
63660
|
+
import { randomUUID as randomUUID46 } from "crypto";
|
|
64081
63661
|
import { Hono as Hono43 } from "hono";
|
|
64082
63662
|
var PERSONAL_ASSISTANT_BROWSER_PROFILE_PROJECTION_VERSION = "assistant-browser-profile.v1";
|
|
64083
63663
|
var IDEMPOTENCY_KEY3 = /^[A-Za-z0-9._~:/+-]{8,240}$/;
|
|
@@ -64240,7 +63820,7 @@ function buildPersonalAssistantBrowserProfileRoutes(options) {
|
|
|
64240
63820
|
const app2 = new Hono43();
|
|
64241
63821
|
const now = options.now ?? (() => /* @__PURE__ */ new Date());
|
|
64242
63822
|
const healthStaleAfterMs = options.healthStaleAfterMs ?? 15 * 6e4;
|
|
64243
|
-
const requestRef = options.requestRef ?? (() => `request_${
|
|
63823
|
+
const requestRef = options.requestRef ?? (() => `request_${randomUUID46().replaceAll("-", "")}`);
|
|
64244
63824
|
const respond = async (c, operation, created = false) => {
|
|
64245
63825
|
const ref6 = requestRef();
|
|
64246
63826
|
try {
|
|
@@ -64323,10 +63903,10 @@ function buildPersonalAssistantBrowserProfileRoutes(options) {
|
|
|
64323
63903
|
}
|
|
64324
63904
|
|
|
64325
63905
|
// src/api/personal-assistant-browser-production.ts
|
|
64326
|
-
import { createHash as
|
|
63906
|
+
import { createHash as createHash63, randomUUID as randomUUID51 } from "crypto";
|
|
64327
63907
|
|
|
64328
63908
|
// src/api/personal-assistant-browser-handoff-store.ts
|
|
64329
|
-
import { createHmac as
|
|
63909
|
+
import { createHmac as createHmac12, randomUUID as randomUUID47 } from "crypto";
|
|
64330
63910
|
var BrowserHandoffStoreError = class extends Error {
|
|
64331
63911
|
constructor(code, status) {
|
|
64332
63912
|
super(code);
|
|
@@ -64374,7 +63954,7 @@ function nextAction(phase) {
|
|
|
64374
63954
|
return "none";
|
|
64375
63955
|
}
|
|
64376
63956
|
function personalAssistantBrowserOwnerRef(ownerUserId2) {
|
|
64377
|
-
return `owner_${
|
|
63957
|
+
return `owner_${createHmac12("sha256", "assistant-browser-owner-ref").update(String(ownerUserId2)).digest("hex").slice(0, 24)}`;
|
|
64378
63958
|
}
|
|
64379
63959
|
function createPostgresPersonalAssistantBrowserHandoffStore(options) {
|
|
64380
63960
|
if (options.queryable && !options.transaction) throw new TypeError("an injected queryable requires an atomic transaction port");
|
|
@@ -64385,7 +63965,7 @@ function createPostgresPersonalAssistantBrowserHandoffStore(options) {
|
|
|
64385
63965
|
const absoluteLifetimeMs = Math.max(6e4, Math.min(options.absoluteLifetimeMs ?? 20 * 6e4, 20 * 6e4));
|
|
64386
63966
|
const claimLifetimeMs = Math.max(3e4, Math.min(options.claimLifetimeMs ?? 2 * 6e4, 5 * 6e4));
|
|
64387
63967
|
const controlLifetimeMs = Math.max(3e4, Math.min(options.controlLifetimeMs ?? 5 * 6e4, 5 * 6e4));
|
|
64388
|
-
const claimDigest = (claimRef) =>
|
|
63968
|
+
const claimDigest = (claimRef) => createHmac12("sha256", digestKey).update(`assistant.browser-handoff-claim\0${claimRef}`).digest("hex");
|
|
64389
63969
|
async function select(client2, ownerUserId2, takeoverRef, lock = false) {
|
|
64390
63970
|
const result3 = await client2.query(
|
|
64391
63971
|
`${HANDOFF_SELECT}
|
|
@@ -64414,14 +63994,14 @@ function createPostgresPersonalAssistantBrowserHandoffStore(options) {
|
|
|
64414
63994
|
[row.owner_user_id, row.handoff_id, mode, now().toISOString()]
|
|
64415
63995
|
);
|
|
64416
63996
|
if (existing.rows[0]) return existing.rows[0].claim_ref;
|
|
64417
|
-
const claimRef = `claim_${
|
|
63997
|
+
const claimRef = `claim_${randomUUID47().replaceAll("-", "")}`;
|
|
64418
63998
|
const ceiling = Math.min(new Date(row.expires_at).getTime(), now().getTime() + (mode === "control" ? controlLifetimeMs : claimLifetimeMs));
|
|
64419
63999
|
if (ceiling <= now().getTime()) throw new BrowserHandoffStoreError("handoff_expired", 409);
|
|
64420
64000
|
await client2.query(
|
|
64421
64001
|
`INSERT INTO assistant.browser_handoff_claims
|
|
64422
64002
|
(owner_user_id,id,public_id,handoff_id,mode,state,claim_digest,expires_at,created_at)
|
|
64423
64003
|
VALUES ($1,$2,$3,$4,$5,'available',$6,$7::timestamptz,$8::timestamptz)`,
|
|
64424
|
-
[row.owner_user_id,
|
|
64004
|
+
[row.owner_user_id, randomUUID47(), claimRef, row.handoff_id, mode, claimDigest(claimRef), new Date(ceiling).toISOString(), now().toISOString()]
|
|
64425
64005
|
);
|
|
64426
64006
|
return claimRef;
|
|
64427
64007
|
}
|
|
@@ -64443,7 +64023,7 @@ function createPostgresPersonalAssistantBrowserHandoffStore(options) {
|
|
|
64443
64023
|
async function create(input) {
|
|
64444
64024
|
return transaction2(async (client2) => {
|
|
64445
64025
|
const owner5 = positiveOwner(input.ownerUserId);
|
|
64446
|
-
const takeoverRef = `takeover_${
|
|
64026
|
+
const takeoverRef = `takeover_${randomUUID47().replaceAll("-", "")}`;
|
|
64447
64027
|
const createdAt = now();
|
|
64448
64028
|
const expiresAt = new Date(createdAt.getTime() + absoluteLifetimeMs);
|
|
64449
64029
|
const inserted = await client2.query(
|
|
@@ -64458,7 +64038,7 @@ function createPostgresPersonalAssistantBrowserHandoffStore(options) {
|
|
|
64458
64038
|
) ${HANDOFF_SELECT} JOIN inserted ON inserted.id=handoff.id WHERE handoff.owner_user_id=$1`,
|
|
64459
64039
|
[
|
|
64460
64040
|
owner5,
|
|
64461
|
-
|
|
64041
|
+
randomUUID47(),
|
|
64462
64042
|
takeoverRef,
|
|
64463
64043
|
ref(input.profileRef, PROFILE_REF),
|
|
64464
64044
|
ref(input.loginBindingRef, LOGIN_REF),
|
|
@@ -64617,7 +64197,7 @@ function createPostgresPersonalAssistantBrowserHandoffStore(options) {
|
|
|
64617
64197
|
}
|
|
64618
64198
|
|
|
64619
64199
|
// src/api/personal-assistant-browser-profile-store.ts
|
|
64620
|
-
import { createHash as
|
|
64200
|
+
import { createHash as createHash60, createHmac as createHmac13, randomUUID as randomUUID48 } from "crypto";
|
|
64621
64201
|
import { domainToASCII } from "url";
|
|
64622
64202
|
var PersonalAssistantBrowserProfileStoreError = class extends Error {
|
|
64623
64203
|
constructor(code, message = code, status = code.endsWith("revision_conflict") ? 409 : code.endsWith("input_rejected") ? 400 : 404) {
|
|
@@ -64659,10 +64239,10 @@ function iso2(value) {
|
|
|
64659
64239
|
return value instanceof Date ? value.toISOString() : new Date(value).toISOString();
|
|
64660
64240
|
}
|
|
64661
64241
|
function newRef(prefix) {
|
|
64662
|
-
return `${prefix}_${
|
|
64242
|
+
return `${prefix}_${randomUUID48().replaceAll("-", "")}`;
|
|
64663
64243
|
}
|
|
64664
64244
|
function deterministicRef(prefix, key3, identity) {
|
|
64665
|
-
return `${prefix}_${
|
|
64245
|
+
return `${prefix}_${createHmac13("sha256", key3).update(`assistant.${prefix}\0${identity}`).digest("hex").slice(0, 32)}`;
|
|
64666
64246
|
}
|
|
64667
64247
|
function namespaceKey(value) {
|
|
64668
64248
|
const key3 = Buffer.isBuffer(value) ? Buffer.from(value) : Buffer.from(value, "utf8");
|
|
@@ -64743,11 +64323,11 @@ function assertMaskedIdentity(value) {
|
|
|
64743
64323
|
function deriveBrowserProviderNamespaceDigest(keyInput, ownerUserId2, profileRef) {
|
|
64744
64324
|
const owner5 = assertOwner(ownerUserId2);
|
|
64745
64325
|
assertRef(profileRef, PROFILE_REF2, "profileRef");
|
|
64746
|
-
return
|
|
64326
|
+
return createHmac13("sha256", namespaceKey(keyInput)).update(`assistant.browser-profile\0${owner5}\0${profileRef}`).digest("hex");
|
|
64747
64327
|
}
|
|
64748
64328
|
function digestEvidence(value) {
|
|
64749
64329
|
const canonical3 = JSON.stringify(value, (_key, entry) => entry && typeof entry === "object" && !Array.isArray(entry) ? Object.fromEntries(Object.entries(entry).sort(([a], [b]) => a.localeCompare(b))) : entry);
|
|
64750
|
-
return
|
|
64330
|
+
return createHash60("sha256").update(canonical3).digest("hex");
|
|
64751
64331
|
}
|
|
64752
64332
|
function exactCapabilityList(value, allowed) {
|
|
64753
64333
|
if (!Array.isArray(value)) return [];
|
|
@@ -64862,7 +64442,7 @@ function createPostgresPersonalAssistantBrowserProfileStore(options) {
|
|
|
64862
64442
|
inserted.status,inserted.capability_summary,inserted.revision,inserted.last_verified_at,inserted.verification_digest,
|
|
64863
64443
|
inserted.created_at,inserted.updated_at FROM inserted`, [
|
|
64864
64444
|
owner5,
|
|
64865
|
-
|
|
64445
|
+
randomUUID48(),
|
|
64866
64446
|
profileRef,
|
|
64867
64447
|
input.assistantRef,
|
|
64868
64448
|
label2,
|
|
@@ -64941,7 +64521,7 @@ function createPostgresPersonalAssistantBrowserProfileStore(options) {
|
|
|
64941
64521
|
inserted.identity_label_masked,inserted.status,inserted.capability_summary,inserted.revision,inserted.last_verified_at,
|
|
64942
64522
|
inserted.verification_digest,inserted.created_at,inserted.updated_at FROM inserted`, [
|
|
64943
64523
|
owner5,
|
|
64944
|
-
|
|
64524
|
+
randomUUID48(),
|
|
64945
64525
|
ref6,
|
|
64946
64526
|
assertRef(input.profileRef, PROFILE_REF2, "profileRef"),
|
|
64947
64527
|
canonicalizeBrowserDomain(input.canonicalDomain),
|
|
@@ -65040,7 +64620,7 @@ function createPostgresPersonalAssistantBrowserProfileStore(options) {
|
|
|
65040
64620
|
verification.observed_status,verification.evidence_digest,verification.evidence_summary,verification.verified_at,
|
|
65041
64621
|
verification.created_at FROM verification`, [
|
|
65042
64622
|
owner5,
|
|
65043
|
-
|
|
64623
|
+
randomUUID48(),
|
|
65044
64624
|
newRef("bpver"),
|
|
65045
64625
|
profile.rows[0].id,
|
|
65046
64626
|
bindingId,
|
|
@@ -65098,7 +64678,7 @@ function createPostgresPersonalAssistantBrowserProfileStore(options) {
|
|
|
65098
64678
|
FROM assistant.assistants assistant WHERE assistant.owner_user_id=$1 AND assistant.public_id=$4 AND assistant.deleted_at IS NULL
|
|
65099
64679
|
ON CONFLICT (owner_user_id,public_id) DO NOTHING`, [
|
|
65100
64680
|
owner5,
|
|
65101
|
-
|
|
64681
|
+
randomUUID48(),
|
|
65102
64682
|
profileRef,
|
|
65103
64683
|
input.assistantRef,
|
|
65104
64684
|
assertSafeText(input.displayLabel ?? "Imported browser profile", "displayLabel", 120),
|
|
@@ -65119,7 +64699,7 @@ function createPostgresPersonalAssistantBrowserProfileStore(options) {
|
|
|
65119
64699
|
VALUES ($1,$2,$3,$4,$5,$6,$7,$8::jsonb,$9::timestamptz,$9::timestamptz)
|
|
65120
64700
|
ON CONFLICT (owner_user_id,public_id) DO NOTHING`, [
|
|
65121
64701
|
owner5,
|
|
65122
|
-
|
|
64702
|
+
randomUUID48(),
|
|
65123
64703
|
bindingRef,
|
|
65124
64704
|
existing.rows[0].id,
|
|
65125
64705
|
domain,
|
|
@@ -65153,7 +64733,7 @@ function createPostgresPersonalAssistantBrowserProfileStore(options) {
|
|
|
65153
64733
|
}
|
|
65154
64734
|
|
|
65155
64735
|
// src/api/personal-assistant-idempotency-store.ts
|
|
65156
|
-
import { createHash as
|
|
64736
|
+
import { createHash as createHash61, randomUUID as randomUUID49 } from "crypto";
|
|
65157
64737
|
var PersonalAssistantIdempotencyConflictError = class extends Error {
|
|
65158
64738
|
code = "idempotency_conflict";
|
|
65159
64739
|
status = 409;
|
|
@@ -65182,7 +64762,7 @@ function jsonValue(value) {
|
|
|
65182
64762
|
return JSON.parse(serialized);
|
|
65183
64763
|
}
|
|
65184
64764
|
function resultDigest(value) {
|
|
65185
|
-
return
|
|
64765
|
+
return createHash61("sha256").update(canonicalJson4(value)).digest("hex");
|
|
65186
64766
|
}
|
|
65187
64767
|
function timestamp3(value) {
|
|
65188
64768
|
return value instanceof Date ? value.toISOString() : new Date(value).toISOString();
|
|
@@ -65194,7 +64774,7 @@ function createPostgresPersonalAssistantIdempotencyStore(options = {}) {
|
|
|
65194
64774
|
return Object.freeze({
|
|
65195
64775
|
async run(input, work) {
|
|
65196
64776
|
const ownerUserId2 = input.ownerUserId.toString();
|
|
65197
|
-
const id2 =
|
|
64777
|
+
const id2 = randomUUID49();
|
|
65198
64778
|
const claim = await transaction2(async (client2) => {
|
|
65199
64779
|
const inserted = await client2.query(`
|
|
65200
64780
|
INSERT INTO assistant.owner_request_idempotency (
|
|
@@ -65236,8 +64816,8 @@ function createPostgresPersonalAssistantIdempotencyStore(options = {}) {
|
|
|
65236
64816
|
) VALUES ($1, $2, $3, 'system', 'assistant.idempotency.completed', $4, $5, $6, $7::jsonb, $8::timestamptz)
|
|
65237
64817
|
`, [
|
|
65238
64818
|
ownerUserId2,
|
|
65239
|
-
|
|
65240
|
-
`audit_${
|
|
64819
|
+
randomUUID49(),
|
|
64820
|
+
`audit_${randomUUID49()}`,
|
|
65241
64821
|
input.action,
|
|
65242
64822
|
input.idempotencyKey,
|
|
65243
64823
|
input.requestDigest,
|
|
@@ -65265,7 +64845,7 @@ function createPostgresPersonalAssistantIdempotencyStore(options = {}) {
|
|
|
65265
64845
|
}
|
|
65266
64846
|
|
|
65267
64847
|
// src/api/personal-assistant-browser-account-cleanup.ts
|
|
65268
|
-
import { createHash as
|
|
64848
|
+
import { createHash as createHash62, randomUUID as randomUUID50 } from "crypto";
|
|
65269
64849
|
function positiveOwner2(value) {
|
|
65270
64850
|
if (typeof value !== "bigint" || value <= 0n) throw new TypeError("positive ownerUserId is required");
|
|
65271
64851
|
return value.toString();
|
|
@@ -65324,10 +64904,10 @@ function createPersonalAssistantBrowserAccountCleanup(options) {
|
|
|
65324
64904
|
};
|
|
65325
64905
|
return Object.freeze({
|
|
65326
64906
|
schemaVersion: "assistant-browser-account-cleanup.v1",
|
|
65327
|
-
cleanupRef: `cleanup_${
|
|
64907
|
+
cleanupRef: `cleanup_${randomUUID50().replaceAll("-", "")}`,
|
|
65328
64908
|
state: "confirmed",
|
|
65329
64909
|
...evidence,
|
|
65330
|
-
evidenceDigest:
|
|
64910
|
+
evidenceDigest: createHash62("sha256").update(JSON.stringify(evidence)).digest("hex")
|
|
65331
64911
|
});
|
|
65332
64912
|
};
|
|
65333
64913
|
}
|
|
@@ -65354,7 +64934,7 @@ var VERIFIED_BROWSER_CAPABILITIES = Object.freeze([
|
|
|
65354
64934
|
"download"
|
|
65355
64935
|
]);
|
|
65356
64936
|
function digest5(value) {
|
|
65357
|
-
return
|
|
64937
|
+
return createHash63("sha256").update(JSON.stringify(value, (_key, entry) => {
|
|
65358
64938
|
if (typeof entry === "bigint") return entry.toString();
|
|
65359
64939
|
if (!entry || typeof entry !== "object" || Array.isArray(entry)) return entry;
|
|
65360
64940
|
return Object.fromEntries(Object.entries(entry).sort(([a], [b]) => a.localeCompare(b)));
|
|
@@ -65386,13 +64966,13 @@ function handoffError(error) {
|
|
|
65386
64966
|
}
|
|
65387
64967
|
function receipt2(data, replayed, revision = 1) {
|
|
65388
64968
|
return { data, receipt: {
|
|
65389
|
-
receiptRef: `receipt_${
|
|
64969
|
+
receiptRef: `receipt_${randomUUID51().replaceAll("-", "")}`,
|
|
65390
64970
|
state: replayed ? "reused" : "confirmed",
|
|
65391
64971
|
revision
|
|
65392
64972
|
} };
|
|
65393
64973
|
}
|
|
65394
64974
|
function handoffReceipt(data, replayed) {
|
|
65395
|
-
return { data, receipt: { receiptRef: `receipt_${
|
|
64975
|
+
return { data, receipt: { receiptRef: `receipt_${randomUUID51().replaceAll("-", "")}`, state: replayed ? "reused" : "confirmed" } };
|
|
65396
64976
|
}
|
|
65397
64977
|
function loginHealth(status) {
|
|
65398
64978
|
return status === "deleted" ? "revoked" : status;
|
|
@@ -65504,7 +65084,7 @@ function createPersonalAssistantBrowserProductionDependencies(options) {
|
|
|
65504
65084
|
async createProfile(ownerUserId2, input) {
|
|
65505
65085
|
try {
|
|
65506
65086
|
const result3 = await run(ownerUserId2, "assistant.browser-profile.create", input.idempotencyKey, input, async () => {
|
|
65507
|
-
const profileRef = `bprof_${
|
|
65087
|
+
const profileRef = `bprof_${randomUUID51().replaceAll("-", "")}`;
|
|
65508
65088
|
const scope = { ownerRef: personalAssistantBrowserOwnerRef(ownerUserId2), profileRef };
|
|
65509
65089
|
await runtime.ensureProfile(scope);
|
|
65510
65090
|
try {
|
|
@@ -65567,7 +65147,7 @@ function createPersonalAssistantBrowserProductionDependencies(options) {
|
|
|
65567
65147
|
const result3 = await run(ownerUserId2, "assistant.browser-login.begin", input.idempotencyKey, input, async () => {
|
|
65568
65148
|
const profile = await profiles2.getProfile(ownerUserId2, input.profileRef);
|
|
65569
65149
|
if (!profile) throw new PersonalAssistantBrowserProfileStoreError("browser_profile_not_found");
|
|
65570
|
-
const loginBindingRef = `blogin_${
|
|
65150
|
+
const loginBindingRef = `blogin_${randomUUID51().replaceAll("-", "")}`;
|
|
65571
65151
|
const session = await openLoginSetup(ownerUserId2, profile.profileRef, loginBindingRef, input.canonicalDomain);
|
|
65572
65152
|
try {
|
|
65573
65153
|
const binding = await profiles2.createLoginBinding({
|
|
@@ -65925,7 +65505,7 @@ var personalAssistantBrowserHandoffApp = buildPersonalAssistantBrowserHandoffRou
|
|
|
65925
65505
|
import { Hono as Hono45 } from "hono";
|
|
65926
65506
|
|
|
65927
65507
|
// src/api/personal-assistant-worker-routes.ts
|
|
65928
|
-
import { createHash as
|
|
65508
|
+
import { createHash as createHash64, createPublicKey, verify as verify2 } from "crypto";
|
|
65929
65509
|
import { Hono as Hono44 } from "hono";
|
|
65930
65510
|
import { z as z47 } from "zod";
|
|
65931
65511
|
var PERSONAL_ASSISTANT_WORKER_API_PREFIX = "/api/private/v1/assistant-worker";
|
|
@@ -65955,11 +65535,11 @@ function canonicalJson5(value) {
|
|
|
65955
65535
|
return JSON.stringify(value);
|
|
65956
65536
|
}
|
|
65957
65537
|
function personalAssistantWorkerBodyDigest(rawBody) {
|
|
65958
|
-
return
|
|
65538
|
+
return createHash64("sha256").update(rawBody, "utf8").digest("hex");
|
|
65959
65539
|
}
|
|
65960
65540
|
function personalAssistantPlanDigest(plan) {
|
|
65961
65541
|
const { planRef: _planRef, planDigest: _planDigest, immutable: _immutable, createdAt: _createdAt, ...proposal } = plan;
|
|
65962
|
-
return
|
|
65542
|
+
return createHash64("sha256").update(canonicalJson5(proposal)).digest("hex");
|
|
65963
65543
|
}
|
|
65964
65544
|
function personalAssistantWorkerSigningPayload(input) {
|
|
65965
65545
|
return [
|
|
@@ -66113,7 +65693,7 @@ function verifyPolicyEnvelope(identity, envelope, at) {
|
|
|
66113
65693
|
if (Date.parse(envelope.expiresAt) <= at.getTime() || Math.abs(at.getTime() - Date.parse(envelope.createdAt)) > 6e4) {
|
|
66114
65694
|
throw new AssistantWorkerRouteError("worker_policy_request_expired", "The policy request has expired.", 401);
|
|
66115
65695
|
}
|
|
66116
|
-
const expectedDigest =
|
|
65696
|
+
const expectedDigest = createHash64("sha256").update(canonicalJson5(envelope.body)).digest("hex");
|
|
66117
65697
|
if (expectedDigest !== envelope.bodyDigest) throw new AssistantWorkerRouteError("worker_policy_digest_mismatch", "The policy request digest does not match.", 401);
|
|
66118
65698
|
const { signature, ...unsigned } = envelope;
|
|
66119
65699
|
let valid = false;
|
|
@@ -66131,7 +65711,7 @@ function verifyClaimEnvelope(identity, envelope, at) {
|
|
|
66131
65711
|
if (Math.abs(at.getTime() - Date.parse(envelope.createdAt)) > PERSONAL_ASSISTANT_WORKER_SIGNATURE_TTL_MS) {
|
|
66132
65712
|
throw new AssistantWorkerRouteError("worker_claim_expired", "The worker claim has expired.", 401);
|
|
66133
65713
|
}
|
|
66134
|
-
const expectedDigest =
|
|
65714
|
+
const expectedDigest = createHash64("sha256").update(canonicalJson5(envelope.body)).digest("hex");
|
|
66135
65715
|
if (expectedDigest !== envelope.bodyDigest) throw new AssistantWorkerRouteError("worker_claim_digest_mismatch", "The claim digest does not match.", 401);
|
|
66136
65716
|
const { signature, ...unsigned } = envelope;
|
|
66137
65717
|
let valid = false;
|
|
@@ -66434,12 +66014,12 @@ var personalAssistantWorkerProductionApp = (() => {
|
|
|
66434
66014
|
})();
|
|
66435
66015
|
|
|
66436
66016
|
// src/api/personal-assistant-admin-routes.ts
|
|
66437
|
-
import { createHash as
|
|
66017
|
+
import { createHash as createHash66, createPublicKey as createPublicKey2 } from "crypto";
|
|
66438
66018
|
import { Hono as Hono46 } from "hono";
|
|
66439
66019
|
import { z as z48 } from "zod";
|
|
66440
66020
|
|
|
66441
66021
|
// src/api/personal-assistant-kill-controls.ts
|
|
66442
|
-
import { createHash as
|
|
66022
|
+
import { createHash as createHash65, randomUUID as randomUUID52 } from "crypto";
|
|
66443
66023
|
var PERSONAL_ASSISTANT_KILL_SCOPES = [
|
|
66444
66024
|
"global",
|
|
66445
66025
|
"outbound",
|
|
@@ -66467,7 +66047,7 @@ function canonicalJson6(value) {
|
|
|
66467
66047
|
return JSON.stringify(value);
|
|
66468
66048
|
}
|
|
66469
66049
|
function digest6(value) {
|
|
66470
|
-
return
|
|
66050
|
+
return createHash65("sha256").update(canonicalJson6(value)).digest("hex");
|
|
66471
66051
|
}
|
|
66472
66052
|
function validateTarget(target) {
|
|
66473
66053
|
if (!PERSONAL_ASSISTANT_KILL_SCOPES.includes(target.scope)) throw new PersonalAssistantKillControlError("invalid_kill_control", "Invalid kill-control scope.", 400);
|
|
@@ -66587,7 +66167,7 @@ var PostgresPersonalAssistantKillControlStore = class {
|
|
|
66587
66167
|
const active = input.action === "activate";
|
|
66588
66168
|
if (state2.active === active) throw new PersonalAssistantKillControlError("kill_state_conflict", "Kill control is already in the requested state.", 409);
|
|
66589
66169
|
const revision = Number(state2.revision) + 1;
|
|
66590
|
-
const receiptRef = `kill_receipt_${
|
|
66170
|
+
const receiptRef = `kill_receipt_${randomUUID52().replaceAll("-", "")}`;
|
|
66591
66171
|
await client2.query(`UPDATE assistant.kill_switch_controls SET revision = $3, active = $4, reason_code = $5, actor_ref = $6, updated_at = $7
|
|
66592
66172
|
WHERE scope = $1 AND target_key = $2`, [input.target.scope, input.target.targetKey, revision, active, input.reasonCode, input.actorRef, input.occurredAt]);
|
|
66593
66173
|
const inserted = await client2.query(
|
|
@@ -66735,7 +66315,7 @@ async function strictJson2(c, maxBodyBytes) {
|
|
|
66735
66315
|
}
|
|
66736
66316
|
}
|
|
66737
66317
|
function derivedRef(prefix, ...identity) {
|
|
66738
|
-
return `${prefix}_${
|
|
66318
|
+
return `${prefix}_${createHash66("sha256").update(identity.join("\0")).digest("base64url").slice(0, 32)}`;
|
|
66739
66319
|
}
|
|
66740
66320
|
function ownerUserId(target) {
|
|
66741
66321
|
if (!/^[1-9][0-9]{0,18}$/.test(target.targetKey)) {
|
|
@@ -66821,7 +66401,7 @@ function buildPersonalAssistantAdminRoutes(options) {
|
|
|
66821
66401
|
const identity = c.get("assistantAdmin");
|
|
66822
66402
|
requireCapability(identity, "assistant.worker_registration.register");
|
|
66823
66403
|
const parsed = WorkerRegistrationSchema.safeParse(await strictJson2(c, maxBodyBytes));
|
|
66824
|
-
if (!parsed.success || Date.parse(parsed.data.expiresAt) <= now().getTime() || !/^-----BEGIN PUBLIC KEY-----\n[\s\S]+\n-----END PUBLIC KEY-----\n?$/.test(parsed.data.publicKeyPem) || /PRIVATE KEY|ENCRYPTED/.test(parsed.data.publicKeyPem) ||
|
|
66404
|
+
if (!parsed.success || Date.parse(parsed.data.expiresAt) <= now().getTime() || !/^-----BEGIN PUBLIC KEY-----\n[\s\S]+\n-----END PUBLIC KEY-----\n?$/.test(parsed.data.publicKeyPem) || /PRIVATE KEY|ENCRYPTED/.test(parsed.data.publicKeyPem) || createHash66("sha256").update(parsed.success ? parsed.data.publicKeyPem : "").digest("hex") !== (parsed.success ? parsed.data.publicKeySha256 : "")) {
|
|
66825
66405
|
throw new PersonalAssistantAdminRouteError("invalid_worker_registration", "Invalid worker registration request.", 400);
|
|
66826
66406
|
}
|
|
66827
66407
|
try {
|
|
@@ -66947,24 +66527,24 @@ var personalAssistantCronProductionApp = (() => {
|
|
|
66947
66527
|
})();
|
|
66948
66528
|
|
|
66949
66529
|
// src/api/personal-assistant-production.ts
|
|
66950
|
-
import { createHash as
|
|
66530
|
+
import { createHash as createHash96 } from "crypto";
|
|
66951
66531
|
|
|
66952
66532
|
// src/api/personal-assistant-admin-production.ts
|
|
66953
|
-
import { createHash as
|
|
66533
|
+
import { createHash as createHash70 } from "crypto";
|
|
66954
66534
|
|
|
66955
66535
|
// src/api/personal-assistant-worker-store.ts
|
|
66956
|
-
import { createHash as
|
|
66536
|
+
import { createHash as createHash69, randomUUID as randomUUID54 } from "crypto";
|
|
66957
66537
|
|
|
66958
66538
|
// src/api/personal-assistant-repository.ts
|
|
66959
|
-
import { createHash as
|
|
66539
|
+
import { createHash as createHash68, randomBytes as randomBytes7, randomUUID as randomUUID53 } from "crypto";
|
|
66960
66540
|
|
|
66961
66541
|
// src/api/personal-assistant-wake-packet.ts
|
|
66962
|
-
import { createHash as
|
|
66542
|
+
import { createHash as createHash67 } from "crypto";
|
|
66963
66543
|
function stableJson(value) {
|
|
66964
66544
|
return JSON.stringify(value, (_key, entry) => !entry || typeof entry !== "object" || Array.isArray(entry) ? entry : Object.fromEntries(Object.entries(entry).sort(([a], [b]) => a.localeCompare(b))));
|
|
66965
66545
|
}
|
|
66966
66546
|
function stableDigest(value) {
|
|
66967
|
-
return
|
|
66547
|
+
return createHash67("sha256").update(stableJson(value)).digest("hex");
|
|
66968
66548
|
}
|
|
66969
66549
|
function deterministicWakePacketRef(snapshot) {
|
|
66970
66550
|
return `wake_${stableDigest({ assistantRef: snapshot.assistantRef, commandRef: snapshot.commandRef, cycleRef: snapshot.cycleRef, executionRef: snapshot.executionRef, contextVersionRef: snapshot.contextVersion.contextVersionRef }).slice(0, 32)}`;
|
|
@@ -67017,10 +66597,10 @@ function canonicalJson7(value) {
|
|
|
67017
66597
|
});
|
|
67018
66598
|
}
|
|
67019
66599
|
function digest7(value) {
|
|
67020
|
-
return
|
|
66600
|
+
return createHash68("sha256").update(canonicalJson7(value)).digest("hex");
|
|
67021
66601
|
}
|
|
67022
66602
|
function deterministicRef2(prefix, identity) {
|
|
67023
|
-
return `${prefix}_${
|
|
66603
|
+
return `${prefix}_${createHash68("sha256").update(identity).digest("hex").slice(0, 32)}`;
|
|
67024
66604
|
}
|
|
67025
66605
|
function messageCursor(message) {
|
|
67026
66606
|
return Buffer.from(JSON.stringify([message.occurredAt, message.messageRef])).toString("base64url");
|
|
@@ -67405,7 +66985,7 @@ function createPostgresPersonalAssistantRepositoryStore(options = {}) {
|
|
|
67405
66985
|
const stored = AssistantCommandSchema.parse(existing.rows[0].payload);
|
|
67406
66986
|
return { command: stored, receipt: receipt4, entity: stored };
|
|
67407
66987
|
}
|
|
67408
|
-
const commandId =
|
|
66988
|
+
const commandId = randomUUID53();
|
|
67409
66989
|
const inserted = await client2.query(`
|
|
67410
66990
|
INSERT INTO assistant.commands (
|
|
67411
66991
|
owner_user_id, id, public_id, assistant_id, conversation_id, command_type,
|
|
@@ -67447,7 +67027,7 @@ function createPostgresPersonalAssistantRepositoryStore(options = {}) {
|
|
|
67447
67027
|
)
|
|
67448
67028
|
`, [
|
|
67449
67029
|
ownerUserId2.toString(),
|
|
67450
|
-
|
|
67030
|
+
randomUUID53(),
|
|
67451
67031
|
receipt4.receiptRef,
|
|
67452
67032
|
commandId,
|
|
67453
67033
|
command.operation,
|
|
@@ -67516,7 +67096,7 @@ function createPostgresPersonalAssistantRepositoryStore(options = {}) {
|
|
|
67516
67096
|
`, [ownerUserId2.toString(), row.id]);
|
|
67517
67097
|
}
|
|
67518
67098
|
const token7 = randomBytes7(32).toString("base64url");
|
|
67519
|
-
const tokenHash5 =
|
|
67099
|
+
const tokenHash5 = createHash68("sha256").update(token7).digest("hex");
|
|
67520
67100
|
const leaseRef = deterministicRef2("lease", `${input.executionRef}\0${input.workerRef}\0${input.now}`);
|
|
67521
67101
|
const expiresAt = new Date(Date.parse(input.now) + input.leaseSeconds * 1e3).toISOString();
|
|
67522
67102
|
await client2.query(`
|
|
@@ -67524,7 +67104,7 @@ function createPostgresPersonalAssistantRepositoryStore(options = {}) {
|
|
|
67524
67104
|
owner_user_id, id, public_id, worker_id, execution_id, lease_token_hash,
|
|
67525
67105
|
state, claimed_at, heartbeat_at, expires_at
|
|
67526
67106
|
) VALUES ($1, $2, $3, $4, $5, $6, 'active', $7, $7, $8)
|
|
67527
|
-
`, [ownerUserId2.toString(),
|
|
67107
|
+
`, [ownerUserId2.toString(), randomUUID53(), leaseRef, worker.rows[0].id, row.id, tokenHash5, input.now, expiresAt]);
|
|
67528
67108
|
await client2.query(`
|
|
67529
67109
|
UPDATE assistant.executions
|
|
67530
67110
|
SET state = 'claimed', claimed_by_worker_id = $3, claim_token_hash = $4,
|
|
@@ -67601,7 +67181,7 @@ function createPostgresPersonalAssistantRepositoryStore(options = {}) {
|
|
|
67601
67181
|
RETURNING public_id
|
|
67602
67182
|
`, [
|
|
67603
67183
|
ownerUserId2.toString(),
|
|
67604
|
-
|
|
67184
|
+
randomUUID53(),
|
|
67605
67185
|
grant.grantRef,
|
|
67606
67186
|
grant.revision,
|
|
67607
67187
|
grant.authorityClass,
|
|
@@ -67658,7 +67238,7 @@ function createPostgresPersonalAssistantRepositoryStore(options = {}) {
|
|
|
67658
67238
|
RETURNING public_id
|
|
67659
67239
|
`, [
|
|
67660
67240
|
ownerUserId2.toString(),
|
|
67661
|
-
|
|
67241
|
+
randomUUID53(),
|
|
67662
67242
|
approval.approvalRef,
|
|
67663
67243
|
approval.requestedActionDigest,
|
|
67664
67244
|
approval.approvedArgumentDigest,
|
|
@@ -67791,7 +67371,7 @@ function createPostgresPersonalAssistantRepositoryStore(options = {}) {
|
|
|
67791
67371
|
RETURNING public_id
|
|
67792
67372
|
`, [
|
|
67793
67373
|
ownerUserId2.toString(),
|
|
67794
|
-
|
|
67374
|
+
randomUUID53(),
|
|
67795
67375
|
input.conversationRef,
|
|
67796
67376
|
input.participantDigest,
|
|
67797
67377
|
input.occurredAt,
|
|
@@ -67839,7 +67419,7 @@ function createPostgresPersonalAssistantRepositoryStore(options = {}) {
|
|
|
67839
67419
|
RETURNING public_id
|
|
67840
67420
|
`, [
|
|
67841
67421
|
ownerUserId2.toString(),
|
|
67842
|
-
|
|
67422
|
+
randomUUID53(),
|
|
67843
67423
|
message.messageRef,
|
|
67844
67424
|
message.direction,
|
|
67845
67425
|
message.providerAccountRef,
|
|
@@ -67882,7 +67462,7 @@ function createPostgresPersonalAssistantRepositoryStore(options = {}) {
|
|
|
67882
67462
|
provider_message_sid,provider_event_key,error_class,occurred_at
|
|
67883
67463
|
`, [
|
|
67884
67464
|
ownerUserId2.toString(),
|
|
67885
|
-
|
|
67465
|
+
randomUUID53(),
|
|
67886
67466
|
event2.deliveryEventRef,
|
|
67887
67467
|
event2.providerAccountRef,
|
|
67888
67468
|
event2.providerMessageSid,
|
|
@@ -67931,7 +67511,7 @@ function createPostgresPersonalAssistantRepositoryStore(options = {}) {
|
|
|
67931
67511
|
RETURNING public_id, byte_digest
|
|
67932
67512
|
`, [
|
|
67933
67513
|
ownerUserId2.toString(),
|
|
67934
|
-
|
|
67514
|
+
randomUUID53(),
|
|
67935
67515
|
media.mediaRef,
|
|
67936
67516
|
media.providerAccountRef,
|
|
67937
67517
|
media.providerMediaSid,
|
|
@@ -67990,7 +67570,7 @@ function createPostgresPersonalAssistantRepositoryStore(options = {}) {
|
|
|
67990
67570
|
RETURNING public_id,version,manifest_digest,created_at
|
|
67991
67571
|
`, [
|
|
67992
67572
|
ownerUserId2.toString(),
|
|
67993
|
-
|
|
67573
|
+
randomUUID53(),
|
|
67994
67574
|
input.contextVersionRef,
|
|
67995
67575
|
input.version,
|
|
67996
67576
|
input.manifestDigest,
|
|
@@ -68019,7 +67599,7 @@ function createPostgresPersonalAssistantRepositoryStore(options = {}) {
|
|
|
68019
67599
|
RETURNING public_id,state,opened_at,updated_at,closed_at
|
|
68020
67600
|
`, [
|
|
68021
67601
|
ownerUserId2.toString(),
|
|
68022
|
-
|
|
67602
|
+
randomUUID53(),
|
|
68023
67603
|
cycle.cycleRef,
|
|
68024
67604
|
cycle.state,
|
|
68025
67605
|
cycle.openedAt,
|
|
@@ -68052,7 +67632,7 @@ function createPostgresPersonalAssistantRepositoryStore(options = {}) {
|
|
|
68052
67632
|
FROM assistant.wake_cycles cycle WHERE cycle.owner_user_id = $1 AND cycle.public_id = $9
|
|
68053
67633
|
`, [
|
|
68054
67634
|
ownerUserId2.toString(),
|
|
68055
|
-
|
|
67635
|
+
randomUUID53(),
|
|
68056
67636
|
transition.taskRef,
|
|
68057
67637
|
title,
|
|
68058
67638
|
transition.toState,
|
|
@@ -68086,7 +67666,7 @@ function createPostgresPersonalAssistantRepositoryStore(options = {}) {
|
|
|
68086
67666
|
RETURNING public_id,state,attempt,retry_class,terminal_at
|
|
68087
67667
|
`, [
|
|
68088
67668
|
ownerUserId2.toString(),
|
|
68089
|
-
|
|
67669
|
+
randomUUID53(),
|
|
68090
67670
|
execution.executionRef,
|
|
68091
67671
|
execution.planDigest,
|
|
68092
67672
|
execution.state,
|
|
@@ -68121,7 +67701,7 @@ function createPostgresPersonalAssistantRepositoryStore(options = {}) {
|
|
|
68121
67701
|
RETURNING runtime_version,health,occurred_at
|
|
68122
67702
|
`, [
|
|
68123
67703
|
ownerUserId2.toString(),
|
|
68124
|
-
|
|
67704
|
+
randomUUID53(),
|
|
68125
67705
|
relation.rows[0].worker_id,
|
|
68126
67706
|
relation.rows[0].lease_id,
|
|
68127
67707
|
heartbeat.sequence,
|
|
@@ -68206,7 +67786,7 @@ function createPostgresPersonalAssistantRepositoryStore(options = {}) {
|
|
|
68206
67786
|
RETURNING id
|
|
68207
67787
|
`, [
|
|
68208
67788
|
ownerUserId2.toString(),
|
|
68209
|
-
|
|
67789
|
+
randomUUID53(),
|
|
68210
67790
|
plan.planRef,
|
|
68211
67791
|
plan.planDigest,
|
|
68212
67792
|
JSON.stringify(plan),
|
|
@@ -68225,7 +67805,7 @@ function createPostgresPersonalAssistantRepositoryStore(options = {}) {
|
|
|
68225
67805
|
) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9::jsonb,$10,$11,$12,$13,$14)
|
|
68226
67806
|
`, [
|
|
68227
67807
|
ownerUserId2.toString(),
|
|
68228
|
-
|
|
67808
|
+
randomUUID53(),
|
|
68229
67809
|
step.stepRef,
|
|
68230
67810
|
inserted.rows[0].id,
|
|
68231
67811
|
step.position,
|
|
@@ -68265,7 +67845,7 @@ function createPostgresPersonalAssistantRepositoryStore(options = {}) {
|
|
|
68265
67845
|
RETURNING required_digest,decision,reason_code
|
|
68266
67846
|
`, [
|
|
68267
67847
|
ownerUserId2.toString(),
|
|
68268
|
-
|
|
67848
|
+
randomUUID53(),
|
|
68269
67849
|
barrier.barrierRef,
|
|
68270
67850
|
barrier.barrierKind,
|
|
68271
67851
|
barrier.decision,
|
|
@@ -68296,7 +67876,7 @@ function createPostgresPersonalAssistantRepositoryStore(options = {}) {
|
|
|
68296
67876
|
RETURNING public_id,authorized_minor,state
|
|
68297
67877
|
`, [
|
|
68298
67878
|
ownerUserId2.toString(),
|
|
68299
|
-
|
|
67879
|
+
randomUUID53(),
|
|
68300
67880
|
allocation.allocationRef,
|
|
68301
67881
|
allocation.kind,
|
|
68302
67882
|
allocation.idempotencyKey,
|
|
@@ -68410,7 +67990,7 @@ function createPostgresPersonalAssistantRepositoryStore(options = {}) {
|
|
|
68410
67990
|
ON CONFLICT (owner_user_id, public_id) DO NOTHING
|
|
68411
67991
|
`, [
|
|
68412
67992
|
ownerUserId2.toString(),
|
|
68413
|
-
|
|
67993
|
+
randomUUID53(),
|
|
68414
67994
|
contact.contactRef,
|
|
68415
67995
|
contact.displayName,
|
|
68416
67996
|
contact.phoneCiphertext,
|
|
@@ -68438,7 +68018,7 @@ function createPostgresPersonalAssistantRepositoryStore(options = {}) {
|
|
|
68438
68018
|
ON CONFLICT (owner_user_id, public_id) DO NOTHING
|
|
68439
68019
|
`, [
|
|
68440
68020
|
ownerUserId2.toString(),
|
|
68441
|
-
|
|
68021
|
+
randomUUID53(),
|
|
68442
68022
|
number.numberRef,
|
|
68443
68023
|
number.providerAccountRef,
|
|
68444
68024
|
number.providerNumberSid,
|
|
@@ -68470,7 +68050,7 @@ function createPostgresPersonalAssistantRepositoryStore(options = {}) {
|
|
|
68470
68050
|
ON CONFLICT (owner_user_id, public_id) DO NOTHING
|
|
68471
68051
|
`, [
|
|
68472
68052
|
ownerUserId2.toString(),
|
|
68473
|
-
|
|
68053
|
+
randomUUID53(),
|
|
68474
68054
|
conversation.conversationRef,
|
|
68475
68055
|
conversation.participantDigest,
|
|
68476
68056
|
conversation.occurredAt,
|
|
@@ -68492,7 +68072,7 @@ function createPostgresPersonalAssistantRepositoryStore(options = {}) {
|
|
|
68492
68072
|
ON CONFLICT (owner_user_id, public_id) DO NOTHING
|
|
68493
68073
|
`, [
|
|
68494
68074
|
ownerUserId2.toString(),
|
|
68495
|
-
|
|
68075
|
+
randomUUID53(),
|
|
68496
68076
|
message.messageRef,
|
|
68497
68077
|
message.direction,
|
|
68498
68078
|
message.providerAccountRef,
|
|
@@ -68521,7 +68101,7 @@ function createPostgresPersonalAssistantRepositoryStore(options = {}) {
|
|
|
68521
68101
|
RETURNING id
|
|
68522
68102
|
`, [
|
|
68523
68103
|
ownerUserId2.toString(),
|
|
68524
|
-
|
|
68104
|
+
randomUUID53(),
|
|
68525
68105
|
schedule.scheduleRef,
|
|
68526
68106
|
schedule.sourceSystem,
|
|
68527
68107
|
schedule.sourceRef,
|
|
@@ -68549,7 +68129,7 @@ function createPostgresPersonalAssistantRepositoryStore(options = {}) {
|
|
|
68549
68129
|
ON CONFLICT (owner_user_id, public_id) DO NOTHING
|
|
68550
68130
|
`, [
|
|
68551
68131
|
ownerUserId2.toString(),
|
|
68552
|
-
|
|
68132
|
+
randomUUID53(),
|
|
68553
68133
|
grant.grantRef,
|
|
68554
68134
|
insertedSchedule.rows[0].id,
|
|
68555
68135
|
grant.revision,
|
|
@@ -68575,7 +68155,7 @@ function createPostgresPersonalAssistantRepositoryStore(options = {}) {
|
|
|
68575
68155
|
ON CONFLICT (owner_user_id, public_id) DO NOTHING
|
|
68576
68156
|
`, [
|
|
68577
68157
|
ownerUserId2.toString(),
|
|
68578
|
-
|
|
68158
|
+
randomUUID53(),
|
|
68579
68159
|
run.occurrenceRef,
|
|
68580
68160
|
run.sourceRef,
|
|
68581
68161
|
run.occurrenceKey,
|
|
@@ -68634,7 +68214,7 @@ function createPostgresPersonalAssistantRepositoryStore(options = {}) {
|
|
|
68634
68214
|
INSERT INTO assistant.audit_events (
|
|
68635
68215
|
owner_user_id,id,public_id,actor_kind,event_type,correlation_id,evidence_digest,details,occurred_at
|
|
68636
68216
|
) VALUES ($1,$2,$3,'operator','legacy_import_applied',$3,$4,$5::jsonb,$6)
|
|
68637
|
-
`, [ownerUserId2.toString(),
|
|
68217
|
+
`, [ownerUserId2.toString(), randomUUID53(), input.importRef, applied.classificationDigest, JSON.stringify({ receipt: applied }), appliedAt]);
|
|
68638
68218
|
return applied;
|
|
68639
68219
|
});
|
|
68640
68220
|
}
|
|
@@ -68702,7 +68282,7 @@ async function appendPostgresReceipt(transaction2, ownerUserId2, receipt4, recei
|
|
|
68702
68282
|
) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12::jsonb,$13,$14,$15)
|
|
68703
68283
|
`, [
|
|
68704
68284
|
ownerUserId2.toString(),
|
|
68705
|
-
|
|
68285
|
+
randomUUID53(),
|
|
68706
68286
|
receipt4.receiptRef,
|
|
68707
68287
|
relation.rows[0].command_id,
|
|
68708
68288
|
relation.rows[0].execution_id,
|
|
@@ -68735,7 +68315,7 @@ async function insertPostgresConsentEvidence(queryable, ownerUserId2, evidence)
|
|
|
68735
68315
|
RETURNING public_id
|
|
68736
68316
|
`, [
|
|
68737
68317
|
ownerUserId2.toString(),
|
|
68738
|
-
|
|
68318
|
+
randomUUID53(),
|
|
68739
68319
|
evidence.consentRef,
|
|
68740
68320
|
evidence.recipientHash,
|
|
68741
68321
|
evidence.subjectKey,
|
|
@@ -68776,7 +68356,7 @@ async function insertPostgresSuppressionEvent(queryable, ownerUserId2, event2) {
|
|
|
68776
68356
|
ON CONFLICT (owner_user_id, public_id) DO NOTHING RETURNING public_id
|
|
68777
68357
|
`, [
|
|
68778
68358
|
ownerUserId2.toString(),
|
|
68779
|
-
|
|
68359
|
+
randomUUID53(),
|
|
68780
68360
|
event2.suppressionRef,
|
|
68781
68361
|
event2.subjectKey,
|
|
68782
68362
|
event2.transition,
|
|
@@ -69054,10 +68634,10 @@ var AssistantWorkerStoreError = class extends Error {
|
|
|
69054
68634
|
};
|
|
69055
68635
|
function hash(value) {
|
|
69056
68636
|
const canonical3 = JSON.stringify(value, (_key, entry) => entry && typeof entry === "object" && !Array.isArray(entry) ? Object.fromEntries(Object.entries(entry).sort(([a], [b]) => a.localeCompare(b))) : entry);
|
|
69057
|
-
return
|
|
68637
|
+
return createHash69("sha256").update(canonical3).digest("hex");
|
|
69058
68638
|
}
|
|
69059
68639
|
function ref2(prefix, identity) {
|
|
69060
|
-
return `${prefix}_${
|
|
68640
|
+
return `${prefix}_${createHash69("sha256").update(identity).digest("hex").slice(0, 32)}`;
|
|
69061
68641
|
}
|
|
69062
68642
|
function requiredString(input, key3) {
|
|
69063
68643
|
const value = input[key3];
|
|
@@ -69108,7 +68688,7 @@ var PostgresAssistantWorkerIdentityRegistry = class {
|
|
|
69108
68688
|
RETURNING owner_user_id::text,owner_ref,subject_ref,public_id AS worker_ref,device_key_id,key_ref,
|
|
69109
68689
|
device_public_key,state,expires_at`, [
|
|
69110
68690
|
input.ownerUserId.toString(),
|
|
69111
|
-
|
|
68691
|
+
randomUUID54(),
|
|
69112
68692
|
input.workerRef,
|
|
69113
68693
|
input.ownerRef,
|
|
69114
68694
|
input.subjectRef,
|
|
@@ -69161,7 +68741,7 @@ var PostgresAssistantWorkerNonceLedger = class {
|
|
|
69161
68741
|
INSERT INTO assistant.worker_nonces(owner_user_id,id,namespace,nonce_key,expires_at,consumed_at)
|
|
69162
68742
|
SELECT owner_user_id,$1,$2,$3,$4,$5 FROM unique_candidate
|
|
69163
68743
|
ON CONFLICT (owner_user_id,namespace,nonce_key) DO NOTHING RETURNING id`,
|
|
69164
|
-
[
|
|
68744
|
+
[randomUUID54(), input.namespace, input.key, input.expiresAt, now.toISOString(), workerRef]
|
|
69165
68745
|
);
|
|
69166
68746
|
return (result3.rowCount ?? result3.rows.length) === 1;
|
|
69167
68747
|
}
|
|
@@ -69456,7 +69036,7 @@ var INTERNAL_CAPABILITIES = /* @__PURE__ */ new Set([
|
|
|
69456
69036
|
"assistant.worker_registration.revoke"
|
|
69457
69037
|
]);
|
|
69458
69038
|
function actorRef(issuer, subject) {
|
|
69459
|
-
return `admin_actor_${
|
|
69039
|
+
return `admin_actor_${createHash70("sha256").update(`${issuer}\0${subject}`).digest("base64url").slice(0, 32)}`;
|
|
69460
69040
|
}
|
|
69461
69041
|
var VerifiedPersonalAssistantAdminIdentityPort = class {
|
|
69462
69042
|
constructor(verifier, configuration) {
|
|
@@ -69570,7 +69150,7 @@ function createPersonalAssistantAdminProductionDependencies(input) {
|
|
|
69570
69150
|
}
|
|
69571
69151
|
|
|
69572
69152
|
// src/api/personal-assistant-dispatcher.ts
|
|
69573
|
-
import { createHash as
|
|
69153
|
+
import { createHash as createHash71, randomBytes as randomBytes8, randomUUID as randomUUID55 } from "crypto";
|
|
69574
69154
|
var AssistantLeaseFenceError = class extends Error {
|
|
69575
69155
|
code = "assistant_lease_fence_rejected";
|
|
69576
69156
|
constructor() {
|
|
@@ -69584,7 +69164,7 @@ function canonical2(value) {
|
|
|
69584
69164
|
return Object.fromEntries(Object.entries(value).sort(([a], [b]) => a.localeCompare(b)).map(([key3, entry]) => [key3, canonical2(entry)]));
|
|
69585
69165
|
}
|
|
69586
69166
|
function digest8(value) {
|
|
69587
|
-
return
|
|
69167
|
+
return createHash71("sha256").update(JSON.stringify(canonical2(value))).digest("hex");
|
|
69588
69168
|
}
|
|
69589
69169
|
function ref3(prefix, identity) {
|
|
69590
69170
|
return `${prefix}_${digest8(identity).slice(0, 32)}`;
|
|
@@ -69802,7 +69382,7 @@ function createPostgresPersonalAssistantDispatchStore(options = {}) {
|
|
|
69802
69382
|
const cycleRef = deterministic ? null : ref3("cycle", commandRef);
|
|
69803
69383
|
const executionRef = deterministic ? null : ref3("execution", commandRef);
|
|
69804
69384
|
const occurrenceRef = input.occurrenceKey ? ref3("occurrence", `${ownerId3}\0${input.scheduleRef}\0${input.occurrenceKey}`) : null;
|
|
69805
|
-
const commandId =
|
|
69385
|
+
const commandId = randomUUID55();
|
|
69806
69386
|
const commandPayload = {
|
|
69807
69387
|
schemaVersion: "assistant-command.v1",
|
|
69808
69388
|
commandRef,
|
|
@@ -69847,8 +69427,8 @@ function createPostgresPersonalAssistantDispatchStore(options = {}) {
|
|
|
69847
69427
|
let cycleId = null;
|
|
69848
69428
|
let executionId = null;
|
|
69849
69429
|
if (!deterministic && cycleRef && executionRef) {
|
|
69850
|
-
cycleId =
|
|
69851
|
-
executionId =
|
|
69430
|
+
cycleId = randomUUID55();
|
|
69431
|
+
executionId = randomUUID55();
|
|
69852
69432
|
await client2.query(
|
|
69853
69433
|
`INSERT INTO assistant.wake_cycles
|
|
69854
69434
|
(owner_user_id,id,public_id,assistant_id,command_id,context_version_id,state,opened_at,updated_at)
|
|
@@ -69870,7 +69450,7 @@ function createPostgresPersonalAssistantDispatchStore(options = {}) {
|
|
|
69870
69450
|
ON CONFLICT (owner_user_id,schedule_ref,occurrence_key) DO UPDATE SET public_id=assistant.reminder_occurrences.public_id
|
|
69871
69451
|
RETURNING public_id`, [
|
|
69872
69452
|
ownerId3,
|
|
69873
|
-
|
|
69453
|
+
randomUUID55(),
|
|
69874
69454
|
occurrenceRef,
|
|
69875
69455
|
input.occurrenceKey,
|
|
69876
69456
|
input.scheduledFor,
|
|
@@ -69899,7 +69479,7 @@ function createPostgresPersonalAssistantDispatchStore(options = {}) {
|
|
|
69899
69479
|
VALUES ($1,$2,$3,$4,$5,'assistant.execution.status','response',$6,$7,$8,$9,$10::jsonb,$11,$12)`,
|
|
69900
69480
|
[
|
|
69901
69481
|
ownerId3,
|
|
69902
|
-
|
|
69482
|
+
randomUUID55(),
|
|
69903
69483
|
receiptRef,
|
|
69904
69484
|
commandId,
|
|
69905
69485
|
executionId,
|
|
@@ -69960,7 +69540,7 @@ function createPostgresPersonalAssistantDispatchStore(options = {}) {
|
|
|
69960
69540
|
(owner_user_id,id,public_id,worker_id,execution_id,lease_token_hash,state,claimed_at,heartbeat_at,expires_at)
|
|
69961
69541
|
SELECT $1,$2,$3,$4,execution.id,$5,'active',$6,$6,$7 FROM assistant.executions execution
|
|
69962
69542
|
WHERE execution.owner_user_id=$1 AND execution.public_id=$8`,
|
|
69963
|
-
[ownerId3,
|
|
69543
|
+
[ownerId3, randomUUID55(), leaseRef, worker.rows[0].id, tokenHash3(token7), at, expiresAt, row.execution_ref]
|
|
69964
69544
|
);
|
|
69965
69545
|
await client2.query(
|
|
69966
69546
|
`UPDATE assistant.executions SET state='claimed',claimed_by_worker_id=$3,claim_token_hash=$4,
|
|
@@ -70000,7 +69580,7 @@ function createPostgresPersonalAssistantDispatchStore(options = {}) {
|
|
|
70000
69580
|
SELECT $1,$2,worker.id,lease.id,$3,$4,$5::jsonb,$6 FROM assistant.worker_registrations worker
|
|
70001
69581
|
JOIN assistant.worker_leases lease ON lease.owner_user_id=worker.owner_user_id AND lease.worker_id=worker.id
|
|
70002
69582
|
WHERE worker.owner_user_id=$1 AND worker.public_id=$7 AND lease.public_id=$8 AND lease.state='active'`,
|
|
70003
|
-
[ownerId3,
|
|
69583
|
+
[ownerId3, randomUUID55(), input.sequence, input.runtimeVersion, JSON.stringify(input.health), occurredAt, input.workerRef, input.leaseRef]
|
|
70004
69584
|
);
|
|
70005
69585
|
await client2.query(`UPDATE assistant.worker_leases SET heartbeat_at=$3,expires_at=$4
|
|
70006
69586
|
WHERE owner_user_id=$1 AND public_id=$2 AND state='active'`, [ownerId3, input.leaseRef, occurredAt, expiresAt]);
|
|
@@ -70242,7 +69822,7 @@ function createPostgresAssistantReminderRuntimeStore(options = {}) {
|
|
|
70242
69822
|
payload_digest,payload,parsed_intent,parsed_intent_digest,source,state,accepted_at,updated_at,terminal_at)
|
|
70243
69823
|
SELECT $1,$2,$3,assistant.id,NULL,$4,'assistant-reminder-command.v1',$5,$6,$7::jsonb,NULL,NULL,'system','succeeded',$8,$8,$8
|
|
70244
69824
|
FROM assistant.assistants assistant WHERE assistant.owner_user_id=$1 AND assistant.public_id=$9
|
|
70245
|
-
RETURNING id`, [ownerId3,
|
|
69825
|
+
RETURNING id`, [ownerId3, randomUUID55(), commandRef, command.kind, command.idempotencyKey, digest8(command), JSON.stringify(payload), at, assistantRef2]);
|
|
70246
69826
|
if (!inserted.rows[0]) throw new Error("assistant_reminder_assistant_not_found");
|
|
70247
69827
|
return inserted.rows[0].id;
|
|
70248
69828
|
};
|
|
@@ -70292,7 +69872,7 @@ function createPostgresAssistantReminderRuntimeStore(options = {}) {
|
|
|
70292
69872
|
FROM assistant.assistants assistant WHERE assistant.owner_user_id=$1 AND assistant.public_id=$12`,
|
|
70293
69873
|
[
|
|
70294
69874
|
ownerId3,
|
|
70295
|
-
|
|
69875
|
+
randomUUID55(),
|
|
70296
69876
|
publicRef,
|
|
70297
69877
|
commandRef,
|
|
70298
69878
|
definition2.instruction,
|
|
@@ -70368,7 +69948,7 @@ function createPostgresAssistantReminderRuntimeStore(options = {}) {
|
|
|
70368
69948
|
ON CONFLICT (owner_user_id,schedule_ref,occurrence_key) DO NOTHING RETURNING public_id`,
|
|
70369
69949
|
[
|
|
70370
69950
|
definition.ownerId,
|
|
70371
|
-
|
|
69951
|
+
randomUUID55(),
|
|
70372
69952
|
occurrence.occurrenceRef,
|
|
70373
69953
|
definition.assistantRef,
|
|
70374
69954
|
definition.reminderRef,
|
|
@@ -70448,10 +70028,10 @@ function createPersonalAssistantReminderRuntime(options) {
|
|
|
70448
70028
|
}
|
|
70449
70029
|
|
|
70450
70030
|
// src/api/personal-assistant-reconcile-cron.ts
|
|
70451
|
-
import { createHash as
|
|
70031
|
+
import { createHash as createHash73, timingSafeEqual as timingSafeEqual8 } from "crypto";
|
|
70452
70032
|
|
|
70453
70033
|
// src/api/personal-assistant-reconcile.ts
|
|
70454
|
-
import { createHash as
|
|
70034
|
+
import { createHash as createHash72 } from "crypto";
|
|
70455
70035
|
var PERSONAL_ASSISTANT_RECONCILIATION_LIMITS = Object.freeze({
|
|
70456
70036
|
defaultBatchSize: 20,
|
|
70457
70037
|
maxBatchSize: 50,
|
|
@@ -70473,7 +70053,7 @@ var PUBLIC_REF = /^[a-z][a-z0-9_]*_[A-Za-z0-9_-]{3,128}$/u;
|
|
|
70473
70053
|
var DIGEST2 = /^[a-f0-9]{64}$/u;
|
|
70474
70054
|
var PROVIDER_REF = /^[A-Za-z0-9:_-]{3,200}$/u;
|
|
70475
70055
|
function hash2(value) {
|
|
70476
|
-
return
|
|
70056
|
+
return createHash72("sha256").update(value).digest("hex");
|
|
70477
70057
|
}
|
|
70478
70058
|
function validateCandidate(candidate) {
|
|
70479
70059
|
if (!/^[1-9]\d*$/u.test(candidate.ownerUserId) || !PUBLIC_REF.test(candidate.candidateRef) || !/^trace_[A-Za-z0-9_-]{8,128}$/u.test(candidate.traceRef) || !PUBLIC_REF.test(candidate.claimToken) || !PROVIDER_REF.test(candidate.providerAccountRef) || !PROVIDER_REF.test(candidate.providerLocatorRef) || !DIGEST2.test(candidate.expectedDigest) || !Number.isFinite(Date.parse(candidate.stuckSince))) {
|
|
@@ -70595,8 +70175,8 @@ async function reconcilePersonalAssistantTransports(dependencies, options = {})
|
|
|
70595
70175
|
// src/api/personal-assistant-reconcile-cron.ts
|
|
70596
70176
|
function authorized(actual, expectedSecret) {
|
|
70597
70177
|
if (!actual?.startsWith("Bearer ")) return false;
|
|
70598
|
-
const actualDigest =
|
|
70599
|
-
const expectedDigest =
|
|
70178
|
+
const actualDigest = createHash73("sha256").update(actual).digest();
|
|
70179
|
+
const expectedDigest = createHash73("sha256").update(`Bearer ${expectedSecret}`).digest();
|
|
70600
70180
|
return timingSafeEqual8(actualDigest, expectedDigest);
|
|
70601
70181
|
}
|
|
70602
70182
|
function createPersonalAssistantReconcileCronHandler(options) {
|
|
@@ -70658,7 +70238,7 @@ function createPersonalAssistantReminderCronHandler(options) {
|
|
|
70658
70238
|
}
|
|
70659
70239
|
|
|
70660
70240
|
// src/api/twilio-inbound-admission.ts
|
|
70661
|
-
import { createHash as
|
|
70241
|
+
import { createHash as createHash74, randomBytes as randomBytes9 } from "crypto";
|
|
70662
70242
|
var ACCOUNT_SID = /^AC[0-9a-f]{32}$/iu;
|
|
70663
70243
|
var MESSAGE_SID = /^(?:SM|MM)[0-9a-f]{32}$/iu;
|
|
70664
70244
|
var MESSAGING_SERVICE_SID = /^MG[0-9a-f]{32}$/iu;
|
|
@@ -70680,10 +70260,10 @@ function canonicalJson8(value) {
|
|
|
70680
70260
|
});
|
|
70681
70261
|
}
|
|
70682
70262
|
function digest9(value) {
|
|
70683
|
-
return
|
|
70263
|
+
return createHash74("sha256").update(canonicalJson8(value)).digest("hex");
|
|
70684
70264
|
}
|
|
70685
70265
|
function stableRef(prefix, value) {
|
|
70686
|
-
return `${prefix}_${
|
|
70266
|
+
return `${prefix}_${createHash74("sha256").update(value).digest("hex").slice(0, 32)}`;
|
|
70687
70267
|
}
|
|
70688
70268
|
function normalizeOptionalSid(value) {
|
|
70689
70269
|
const normalized = value?.trim() || null;
|
|
@@ -70829,8 +70409,8 @@ function createTwilioInboundIngressCronHandler(options) {
|
|
|
70829
70409
|
return async (request) => {
|
|
70830
70410
|
if (request.method !== "GET") return Response.json({ error: "method_not_allowed" }, { status: 405, headers: { Allow: "GET" } });
|
|
70831
70411
|
const actual = request.headers.get("authorization") ?? "";
|
|
70832
|
-
const actualDigest =
|
|
70833
|
-
const expectedDigest =
|
|
70412
|
+
const actualDigest = createHash74("sha256").update(actual).digest();
|
|
70413
|
+
const expectedDigest = createHash74("sha256").update(expectedAuthorization).digest();
|
|
70834
70414
|
if (actualDigest.length !== expectedDigest.length || !actualDigest.equals(expectedDigest)) {
|
|
70835
70415
|
return Response.json({ error: "unauthorized" }, { status: 401 });
|
|
70836
70416
|
}
|
|
@@ -70872,7 +70452,7 @@ function createPersonalAssistantWorkerAndCronProduction(options) {
|
|
|
70872
70452
|
}
|
|
70873
70453
|
|
|
70874
70454
|
// src/api/personal-assistant-control-plane-store.ts
|
|
70875
|
-
import { createHash as
|
|
70455
|
+
import { createHash as createHash75, randomUUID as randomUUID56 } from "crypto";
|
|
70876
70456
|
var REF = /^[a-z][A-Za-z0-9_-]{2,159}$/;
|
|
70877
70457
|
var DIGEST4 = /^[a-f0-9]{64}$/;
|
|
70878
70458
|
function record3(input) {
|
|
@@ -70895,7 +70475,7 @@ function ref4(value) {
|
|
|
70895
70475
|
return value;
|
|
70896
70476
|
}
|
|
70897
70477
|
function newRef2(prefix) {
|
|
70898
|
-
return `${prefix}_${
|
|
70478
|
+
return `${prefix}_${randomUUID56().replaceAll("-", "")}`;
|
|
70899
70479
|
}
|
|
70900
70480
|
function canonicalJson9(value) {
|
|
70901
70481
|
return JSON.stringify(value, (_key, entry) => {
|
|
@@ -70904,7 +70484,7 @@ function canonicalJson9(value) {
|
|
|
70904
70484
|
});
|
|
70905
70485
|
}
|
|
70906
70486
|
function digest10(value) {
|
|
70907
|
-
return
|
|
70487
|
+
return createHash75("sha256").update(canonicalJson9(value)).digest("hex");
|
|
70908
70488
|
}
|
|
70909
70489
|
function normalizeE164(value) {
|
|
70910
70490
|
const trimmed = value.trim();
|
|
@@ -70951,7 +70531,7 @@ async function audit(client2, owner5, operation, resourceRef, occurredAt) {
|
|
|
70951
70531
|
`INSERT INTO assistant.audit_events (
|
|
70952
70532
|
owner_user_id,id,public_id,actor_kind,event_type,operation,correlation_id,details,occurred_at
|
|
70953
70533
|
) VALUES ($1,$2,$3,'user','assistant.control_plane.mutation',$4,$5,$6::jsonb,$7::timestamptz)`,
|
|
70954
|
-
[owner5,
|
|
70534
|
+
[owner5, randomUUID56(), newRef2("audit"), operation, resourceRef, JSON.stringify({ resourceRef }), occurredAt]
|
|
70955
70535
|
);
|
|
70956
70536
|
}
|
|
70957
70537
|
var ASSISTANT_PROJECTION = `jsonb_build_object('assistantRef', assistant.public_id, 'state', assistant.status,
|
|
@@ -71032,7 +70612,7 @@ function createPostgresPersonalAssistantControlPlaneStore(options) {
|
|
|
71032
70612
|
'assistantRef',public_id,'state',status,'displayName',name,'revision',revision,'createdAt',created_at,'updatedAt',updated_at) AS projection`,
|
|
71033
70613
|
[
|
|
71034
70614
|
ownerUserId2.toString(),
|
|
71035
|
-
|
|
70615
|
+
randomUUID56(),
|
|
71036
70616
|
assistantRef2,
|
|
71037
70617
|
text2(body3, "displayName", text2(body3, "name", "Personal Assistant")),
|
|
71038
70618
|
optionalText3(body3, "timezone") ?? "UTC",
|
|
@@ -71086,7 +70666,7 @@ function createPostgresPersonalAssistantControlPlaneStore(options) {
|
|
|
71086
70666
|
(owner_user_id,id,public_id,assistant_id,channel,address_ciphertext,address_hash,state,revision,created_at,updated_at)
|
|
71087
70667
|
SELECT $1,$2,$3,assistant.id,$4,$5,$6,'active',1,$7,$7 FROM assistant.assistants assistant WHERE assistant.owner_user_id=$1 AND assistant.public_id=$8 AND assistant.deleted_at IS NULL
|
|
71088
70668
|
RETURNING jsonb_build_object('bindingRef',public_id,'assistantRef',$8::text,'channelEndpointRef',public_id,'channel',channel,'state',state,'revision',revision) AS projection`,
|
|
71089
|
-
[ownerUserId2.toString(),
|
|
70669
|
+
[ownerUserId2.toString(), randomUUID56(), bindingRef, channel, protectedAddress?.ciphertext ?? null, protectedAddress?.digest ?? null, at, ref4(assistantRef2)]
|
|
71090
70670
|
);
|
|
71091
70671
|
if (!result3.rows[0]) throw new Error("assistant_not_found");
|
|
71092
70672
|
await audit(client2, ownerUserId2.toString(), "assistant.channel.bind", bindingRef, at);
|
|
@@ -71143,11 +70723,11 @@ function createPostgresPersonalAssistantControlPlaneStore(options) {
|
|
|
71143
70723
|
const inserted = await client2.query(`INSERT INTO assistant.contacts(owner_user_id,id,public_id,display_name,relationship,phone_ciphertext,phone_hash,timezone,attributes,created_at,updated_at)
|
|
71144
70724
|
VALUES($1,$2,$3,$4,$5,$6,$7,$8,'{}'::jsonb,$9,$9)
|
|
71145
70725
|
ON CONFLICT(owner_user_id,phone_hash) WHERE phone_hash IS NOT NULL DO UPDATE SET updated_at=assistant.contacts.updated_at
|
|
71146
|
-
RETURNING id,public_id`, [ownerUserId2.toString(),
|
|
70726
|
+
RETURNING id,public_id`, [ownerUserId2.toString(), randomUUID56(), contactRef, optionalText3(body3, "displayName"), relationship, protectedAddress.ciphertext, protectedAddress.digest, optionalText3(body3, "timezone"), at]);
|
|
71147
70727
|
const row = inserted.rows[0];
|
|
71148
70728
|
if (!row) throw new Error("contact_create_failed");
|
|
71149
70729
|
await client2.query(`INSERT INTO assistant.contact_delivery_endpoints(owner_user_id,id,public_id,endpoint_key,revision,contact_id,channel,address_ciphertext,address_hash,masked_display,state,created_at)
|
|
71150
|
-
SELECT $1,$2,$3,$4,1,$5,'sms',$6,$7,$8,'unverified',$9 WHERE NOT EXISTS(SELECT 1 FROM (SELECT DISTINCT ON(endpoint_key) endpoint_key,contact_id,address_hash,state FROM assistant.contact_delivery_endpoints WHERE owner_user_id=$1 ORDER BY endpoint_key,revision DESC) effective WHERE effective.contact_id=$5 AND effective.address_hash=$7 AND effective.state<>'removed')`, [ownerUserId2.toString(),
|
|
70730
|
+
SELECT $1,$2,$3,$4,1,$5,'sms',$6,$7,$8,'unverified',$9 WHERE NOT EXISTS(SELECT 1 FROM (SELECT DISTINCT ON(endpoint_key) endpoint_key,contact_id,address_hash,state FROM assistant.contact_delivery_endpoints WHERE owner_user_id=$1 ORDER BY endpoint_key,revision DESC) effective WHERE effective.contact_id=$5 AND effective.address_hash=$7 AND effective.state<>'removed')`, [ownerUserId2.toString(), randomUUID56(), endpointRef, randomUUID56(), row.id, protectedAddress.ciphertext, protectedAddress.digest, maskedPhone(phone), at]);
|
|
71151
70731
|
await audit(client2, ownerUserId2.toString(), "assistant.contact.create", row.public_id, at);
|
|
71152
70732
|
const projected = await client2.query(`SELECT ${CONTACT_PROJECTION} AS projection FROM assistant.contacts contact WHERE contact.owner_user_id=$1 AND contact.public_id=$2`, [ownerUserId2.toString(), row.public_id]);
|
|
71153
70733
|
return projected.rows[0].projection;
|
|
@@ -71172,7 +70752,7 @@ function createPostgresPersonalAssistantControlPlaneStore(options) {
|
|
|
71172
70752
|
if (!DIGEST4.test(protectedAddress.digest)) throw new TypeError("protected address digest is invalid");
|
|
71173
70753
|
return tx(async (client2) => {
|
|
71174
70754
|
const result3 = await client2.query(`INSERT INTO assistant.contact_delivery_endpoints(owner_user_id,id,public_id,endpoint_key,revision,contact_id,channel,address_ciphertext,address_hash,masked_display,state,created_at)
|
|
71175
|
-
SELECT $1,$2,$3,$4,1,contact.id,$5,$6,$7,$8,'unverified',$9 FROM assistant.contacts contact WHERE contact.owner_user_id=$1 AND contact.public_id=$10 AND contact.deleted_at IS NULL AND NOT EXISTS(SELECT 1 FROM (SELECT DISTINCT ON(endpoint_key) endpoint_key,address_hash,state FROM assistant.contact_delivery_endpoints WHERE owner_user_id=$1 ORDER BY endpoint_key,revision DESC) effective WHERE effective.address_hash=$7 AND effective.state<>'removed')`, [ownerUserId2.toString(),
|
|
70755
|
+
SELECT $1,$2,$3,$4,1,contact.id,$5,$6,$7,$8,'unverified',$9 FROM assistant.contacts contact WHERE contact.owner_user_id=$1 AND contact.public_id=$10 AND contact.deleted_at IS NULL AND NOT EXISTS(SELECT 1 FROM (SELECT DISTINCT ON(endpoint_key) endpoint_key,address_hash,state FROM assistant.contact_delivery_endpoints WHERE owner_user_id=$1 ORDER BY endpoint_key,revision DESC) effective WHERE effective.address_hash=$7 AND effective.state<>'removed')`, [ownerUserId2.toString(), randomUUID56(), endpointRef, randomUUID56(), channel, protectedAddress.ciphertext, protectedAddress.digest, maskedPhone(phone), at, ref4(contactRef)]);
|
|
71176
70756
|
if (!result3.rowCount) return null;
|
|
71177
70757
|
await client2.query(`UPDATE assistant.contacts SET phone_ciphertext=COALESCE(phone_ciphertext,$3),phone_hash=COALESCE(phone_hash,$4),updated_at=$5 WHERE owner_user_id=$1 AND public_id=$2`, [ownerUserId2.toString(), contactRef, protectedAddress.ciphertext, protectedAddress.digest, at]);
|
|
71178
70758
|
await audit(client2, ownerUserId2.toString(), "assistant.contact.delivery_endpoint.add", endpointRef, at);
|
|
@@ -71185,7 +70765,7 @@ function createPostgresPersonalAssistantControlPlaneStore(options) {
|
|
|
71185
70765
|
if (!DIGEST4.test(protectedAddress.digest)) throw new TypeError("protected address digest is invalid");
|
|
71186
70766
|
return tx(async (client2) => {
|
|
71187
70767
|
const result3 = await client2.query(`INSERT INTO assistant.contact_delivery_endpoints(owner_user_id,id,public_id,endpoint_key,revision,contact_id,channel,address_ciphertext,address_hash,masked_display,state,created_at)
|
|
71188
|
-
SELECT prior.owner_user_id,$4,$5,prior.endpoint_key,prior.revision+1,prior.contact_id,prior.channel,$6,$7,$8,'unverified',$9 FROM assistant.contact_delivery_endpoints prior JOIN assistant.contacts contact ON contact.owner_user_id=prior.owner_user_id AND contact.id=prior.contact_id WHERE prior.owner_user_id=$1 AND contact.public_id=$2 AND prior.public_id=$3 AND prior.state<>'removed' AND NOT EXISTS(SELECT 1 FROM (SELECT DISTINCT ON(endpoint_key) endpoint_key,address_hash,state FROM assistant.contact_delivery_endpoints WHERE owner_user_id=$1 ORDER BY endpoint_key,revision DESC) effective WHERE effective.address_hash=$7 AND effective.state<>'removed' AND effective.endpoint_key<>prior.endpoint_key)`, [ownerUserId2.toString(), ref4(contactRef), ref4(deliveryEndpointRef),
|
|
70768
|
+
SELECT prior.owner_user_id,$4,$5,prior.endpoint_key,prior.revision+1,prior.contact_id,prior.channel,$6,$7,$8,'unverified',$9 FROM assistant.contact_delivery_endpoints prior JOIN assistant.contacts contact ON contact.owner_user_id=prior.owner_user_id AND contact.id=prior.contact_id WHERE prior.owner_user_id=$1 AND contact.public_id=$2 AND prior.public_id=$3 AND prior.state<>'removed' AND NOT EXISTS(SELECT 1 FROM (SELECT DISTINCT ON(endpoint_key) endpoint_key,address_hash,state FROM assistant.contact_delivery_endpoints WHERE owner_user_id=$1 ORDER BY endpoint_key,revision DESC) effective WHERE effective.address_hash=$7 AND effective.state<>'removed' AND effective.endpoint_key<>prior.endpoint_key)`, [ownerUserId2.toString(), ref4(contactRef), ref4(deliveryEndpointRef), randomUUID56(), nextRef, protectedAddress.ciphertext, protectedAddress.digest, maskedPhone(phone), at]);
|
|
71189
70769
|
if (!result3.rowCount) return null;
|
|
71190
70770
|
await client2.query(`UPDATE assistant.contacts SET phone_ciphertext=$3,phone_hash=$4,updated_at=$5 WHERE owner_user_id=$1 AND public_id=$2`, [ownerUserId2.toString(), contactRef, protectedAddress.ciphertext, protectedAddress.digest, at]);
|
|
71191
70771
|
await audit(client2, ownerUserId2.toString(), "assistant.contact.delivery_endpoint.update", nextRef, at);
|
|
@@ -71197,7 +70777,7 @@ function createPostgresPersonalAssistantControlPlaneStore(options) {
|
|
|
71197
70777
|
const body3 = record3(input), at = now().toISOString(), nextRef = newRef2("delivery");
|
|
71198
70778
|
return tx(async (client2) => {
|
|
71199
70779
|
const result3 = await client2.query(`INSERT INTO assistant.contact_delivery_endpoints(owner_user_id,id,public_id,endpoint_key,revision,contact_id,channel,address_ciphertext,address_hash,masked_display,state,reason_code,created_at)
|
|
71200
|
-
SELECT prior.owner_user_id,$4,$5,prior.endpoint_key,prior.revision+1,prior.contact_id,prior.channel,prior.address_ciphertext,prior.address_hash,prior.masked_display,'removed',$6,$7 FROM assistant.contact_delivery_endpoints prior JOIN assistant.contacts contact ON contact.owner_user_id=prior.owner_user_id AND contact.id=prior.contact_id WHERE prior.owner_user_id=$1 AND contact.public_id=$2 AND prior.public_id=$3 AND prior.state<>'removed'`, [ownerUserId2.toString(), ref4(contactRef), ref4(deliveryEndpointRef),
|
|
70780
|
+
SELECT prior.owner_user_id,$4,$5,prior.endpoint_key,prior.revision+1,prior.contact_id,prior.channel,prior.address_ciphertext,prior.address_hash,prior.masked_display,'removed',$6,$7 FROM assistant.contact_delivery_endpoints prior JOIN assistant.contacts contact ON contact.owner_user_id=prior.owner_user_id AND contact.id=prior.contact_id WHERE prior.owner_user_id=$1 AND contact.public_id=$2 AND prior.public_id=$3 AND prior.state<>'removed'`, [ownerUserId2.toString(), ref4(contactRef), ref4(deliveryEndpointRef), randomUUID56(), nextRef, optionalText3(body3, "reasonCode") ?? "owner_removed", at]);
|
|
71201
70781
|
if (!result3.rowCount) return null;
|
|
71202
70782
|
await client2.query(`WITH effective AS(SELECT DISTINCT ON(endpoint_key) endpoint_key,contact_id,address_ciphertext,address_hash,state,revision FROM assistant.contact_delivery_endpoints WHERE owner_user_id=$1 ORDER BY endpoint_key,revision DESC),replacement AS(SELECT DISTINCT ON(contact_id) contact_id,address_ciphertext,address_hash FROM effective WHERE state<>'removed' ORDER BY contact_id,revision DESC) UPDATE assistant.contacts contact SET phone_ciphertext=replacement.address_ciphertext,phone_hash=replacement.address_hash,updated_at=$3 FROM replacement WHERE contact.owner_user_id=$1 AND contact.public_id=$2 AND replacement.contact_id=contact.id`, [ownerUserId2.toString(), contactRef, at]);
|
|
71203
70783
|
await client2.query(`UPDATE assistant.contacts SET phone_ciphertext=NULL,phone_hash=NULL,updated_at=$3 WHERE owner_user_id=$1 AND public_id=$2 AND NOT EXISTS(SELECT 1 FROM (SELECT DISTINCT ON(endpoint_key) endpoint_key,contact_id,state FROM assistant.contact_delivery_endpoints WHERE owner_user_id=$1 ORDER BY endpoint_key,revision DESC) effective WHERE effective.contact_id=assistant.contacts.id AND effective.state<>'removed')`, [ownerUserId2.toString(), contactRef, at]);
|
|
@@ -71221,7 +70801,7 @@ function createPostgresPersonalAssistantControlPlaneStore(options) {
|
|
|
71221
70801
|
const body3 = record3(input), contactRef = ref4(text2(body3, "contactRef")), consentRef = ref4(text2(body3, "consentRef")), at = now().toISOString();
|
|
71222
70802
|
return tx(async (client2) => {
|
|
71223
70803
|
const result3 = await client2.query(`INSERT INTO assistant.consent_evidence(owner_user_id,id,public_id,contact_id,sender_endpoint_id,recipient_hash,subject_key,message_class,transition,source,proof_digest,captured_at,withdrawn_at)
|
|
71224
|
-
SELECT prior.owner_user_id,$3,$4,prior.contact_id,prior.sender_endpoint_id,prior.recipient_hash,prior.subject_key,prior.message_class,'withdrawn','internal_dnc',$5,$6,$6 FROM assistant.consent_evidence prior JOIN assistant.contacts contact ON contact.owner_user_id=prior.owner_user_id AND contact.id=prior.contact_id JOIN assistant.channel_endpoints endpoint ON endpoint.owner_user_id=prior.owner_user_id AND endpoint.id=prior.sender_endpoint_id WHERE prior.owner_user_id=$1 AND prior.public_id=$2 AND contact.public_id=$7 RETURNING public_id,(SELECT public_id FROM assistant.channel_endpoints WHERE owner_user_id=$1 AND id=sender_endpoint_id) sender_ref,subject_key,message_class,proof_digest`, [ownerUserId2.toString(), consentRef,
|
|
70804
|
+
SELECT prior.owner_user_id,$3,$4,prior.contact_id,prior.sender_endpoint_id,prior.recipient_hash,prior.subject_key,prior.message_class,'withdrawn','internal_dnc',$5,$6,$6 FROM assistant.consent_evidence prior JOIN assistant.contacts contact ON contact.owner_user_id=prior.owner_user_id AND contact.id=prior.contact_id JOIN assistant.channel_endpoints endpoint ON endpoint.owner_user_id=prior.owner_user_id AND endpoint.id=prior.sender_endpoint_id WHERE prior.owner_user_id=$1 AND prior.public_id=$2 AND contact.public_id=$7 RETURNING public_id,(SELECT public_id FROM assistant.channel_endpoints WHERE owner_user_id=$1 AND id=sender_endpoint_id) sender_ref,subject_key,message_class,proof_digest`, [ownerUserId2.toString(), consentRef, randomUUID56(), newRef2("consent"), digest10({ consentRef, at }), at, contactRef]);
|
|
71225
70805
|
if (!result3.rows[0]) throw new Error("consent_not_found");
|
|
71226
70806
|
await audit(client2, ownerUserId2.toString(), "assistant.consent.withdraw", consentRef, at);
|
|
71227
70807
|
const row = result3.rows[0];
|
|
@@ -71231,7 +70811,7 @@ function createPostgresPersonalAssistantControlPlaneStore(options) {
|
|
|
71231
70811
|
async createSchedule(ownerUserId2, assistantRef2, input) {
|
|
71232
70812
|
const body3 = record3(input), scheduleRef = newRef2("schedule"), at = now().toISOString();
|
|
71233
70813
|
return tx(async (client2) => {
|
|
71234
|
-
const result3 = await client2.query(`INSERT INTO assistant.schedules(owner_user_id,id,public_id,assistant_id,source_system,source_ref,source_owner_ref,description,cadence,time_of_day,timezone,logical_vault,status,next_due_at,execution_mode,artifact_selection,source_payload_digest,revision,created_at,updated_at) SELECT $1,$2,$3,assistant.id,$4,$5,$6,$7,$8,$9,$10,$11,'active',$12,$13,$14::jsonb,$15,1,$16,$16 FROM assistant.assistants assistant WHERE assistant.owner_user_id=$1 AND assistant.public_id=$17 RETURNING jsonb_build_object('scheduleRef',public_id,'assistantRef',$17::text,'state',status,'timezone',timezone,'nextDueAt',next_due_at,'revision',revision) AS projection`, [ownerUserId2.toString(),
|
|
70814
|
+
const result3 = await client2.query(`INSERT INTO assistant.schedules(owner_user_id,id,public_id,assistant_id,source_system,source_ref,source_owner_ref,description,cadence,time_of_day,timezone,logical_vault,status,next_due_at,execution_mode,artifact_selection,source_payload_digest,revision,created_at,updated_at) SELECT $1,$2,$3,assistant.id,$4,$5,$6,$7,$8,$9,$10,$11,'active',$12,$13,$14::jsonb,$15,1,$16,$16 FROM assistant.assistants assistant WHERE assistant.owner_user_id=$1 AND assistant.public_id=$17 RETURNING jsonb_build_object('scheduleRef',public_id,'assistantRef',$17::text,'state',status,'timezone',timezone,'nextDueAt',next_due_at,'revision',revision) AS projection`, [ownerUserId2.toString(), randomUUID56(), scheduleRef, optionalText3(body3, "sourceSystem") ?? "assistant", optionalText3(body3, "sourceRef") ?? scheduleRef, optionalText3(body3, "sourceOwnerRef") ?? ownerUserId2.toString(), text2(body3, "description"), text2(body3, "cadence"), optionalText3(body3, "timeOfDay"), optionalText3(body3, "timezone") ?? "UTC", optionalText3(body3, "logicalVault") ?? "Personal Assistant", text2(body3, "nextDueAt"), optionalText3(body3, "executionMode") ?? "agent", JSON.stringify(body3.artifactSelection ?? { mode: "none" }), digest10(body3), at, ref4(assistantRef2)]);
|
|
71235
70815
|
if (!result3.rows[0]) throw new Error("assistant_not_found");
|
|
71236
70816
|
await audit(client2, ownerUserId2.toString(), "assistant.schedule.create", scheduleRef, at);
|
|
71237
70817
|
return result3.rows[0].projection;
|
|
@@ -71254,7 +70834,7 @@ function createPostgresPersonalAssistantControlPlaneStore(options) {
|
|
|
71254
70834
|
async createReminder(ownerUserId2, assistantRef2, input) {
|
|
71255
70835
|
const body3 = record3(input), reminderRef2 = newRef2("reminder"), at = now().toISOString(), scheduledFor = text2(body3, "scheduledFor");
|
|
71256
70836
|
return tx(async (client2) => {
|
|
71257
|
-
const result3 = await client2.query(`INSERT INTO assistant.reminder_occurrences(owner_user_id,id,public_id,assistant_id,schedule_id,schedule_ref,occurrence_key,instruction,scheduled_for,timezone,state,revision,created_at,updated_at) SELECT $1,$2,$3,assistant.id,schedule.id,COALESCE(schedule.public_id,$3),$4,$5,$6,$7,'materialized',1,$8,$8 FROM assistant.assistants assistant LEFT JOIN assistant.schedules schedule ON schedule.owner_user_id=assistant.owner_user_id AND schedule.public_id=$9 WHERE assistant.owner_user_id=$1 AND assistant.public_id=$10 RETURNING jsonb_build_object('reminderRef',public_id,'assistantRef',$10::text,'scheduleRef',CASE WHEN schedule_id IS NULL THEN NULL ELSE schedule_ref END,'state','scheduled','instruction',instruction,'scheduledFor',scheduled_for,'timezone',timezone,'revision',revision,'updatedAt',updated_at) AS projection`, [ownerUserId2.toString(),
|
|
70837
|
+
const result3 = await client2.query(`INSERT INTO assistant.reminder_occurrences(owner_user_id,id,public_id,assistant_id,schedule_id,schedule_ref,occurrence_key,instruction,scheduled_for,timezone,state,revision,created_at,updated_at) SELECT $1,$2,$3,assistant.id,schedule.id,COALESCE(schedule.public_id,$3),$4,$5,$6,$7,'materialized',1,$8,$8 FROM assistant.assistants assistant LEFT JOIN assistant.schedules schedule ON schedule.owner_user_id=assistant.owner_user_id AND schedule.public_id=$9 WHERE assistant.owner_user_id=$1 AND assistant.public_id=$10 RETURNING jsonb_build_object('reminderRef',public_id,'assistantRef',$10::text,'scheduleRef',CASE WHEN schedule_id IS NULL THEN NULL ELSE schedule_ref END,'state','scheduled','instruction',instruction,'scheduledFor',scheduled_for,'timezone',timezone,'revision',revision,'updatedAt',updated_at) AS projection`, [ownerUserId2.toString(), randomUUID56(), reminderRef2, optionalText3(body3, "occurrenceKey") ?? reminderRef2, text2(body3, "instruction"), scheduledFor, optionalText3(body3, "timezone") ?? "UTC", at, optionalText3(body3, "scheduleRef"), ref4(assistantRef2)]);
|
|
71258
70838
|
if (!result3.rows[0]) throw new Error("assistant_not_found");
|
|
71259
70839
|
await audit(client2, ownerUserId2.toString(), "assistant.reminder.create", reminderRef2, at);
|
|
71260
70840
|
return result3.rows[0].projection;
|
|
@@ -71278,7 +70858,7 @@ function createPostgresPersonalAssistantControlPlaneStore(options) {
|
|
|
71278
70858
|
const body3 = record3(input), packetRef = newRef2("packet"), at = now().toISOString(), manifestDigest = text2(body3, "manifestDigest");
|
|
71279
70859
|
if (!DIGEST4.test(manifestDigest)) throw new TypeError("manifestDigest is invalid");
|
|
71280
70860
|
return tx(async (client2) => {
|
|
71281
|
-
const result3 = await client2.query(`INSERT INTO assistant.context_packet_pointers(owner_user_id,id,public_id,assistant_id,context_version_id,memory_vault_ref,packet_ref,packet_revision,revision,manifest_digest,label,sensitivity,state,created_at,updated_at) SELECT $1,$2,$3,assistant.id,context.id,$4,$5,$6,1,$7,$8,$9,'active',$10,$10 FROM assistant.assistants assistant JOIN LATERAL(SELECT id FROM assistant.context_versions WHERE owner_user_id=assistant.owner_user_id AND assistant_id=assistant.id ORDER BY version DESC LIMIT 1) context ON true WHERE assistant.owner_user_id=$1 AND assistant.public_id=$11 RETURNING jsonb_build_object('packetRef',public_id,'assistantRef',$11::text,'revision',revision,'state',state,'manifestDigest',manifest_digest,'label',label,'updatedAt',updated_at) AS projection`, [ownerUserId2.toString(),
|
|
70861
|
+
const result3 = await client2.query(`INSERT INTO assistant.context_packet_pointers(owner_user_id,id,public_id,assistant_id,context_version_id,memory_vault_ref,packet_ref,packet_revision,revision,manifest_digest,label,sensitivity,state,created_at,updated_at) SELECT $1,$2,$3,assistant.id,context.id,$4,$5,$6,1,$7,$8,$9,'active',$10,$10 FROM assistant.assistants assistant JOIN LATERAL(SELECT id FROM assistant.context_versions WHERE owner_user_id=assistant.owner_user_id AND assistant_id=assistant.id ORDER BY version DESC LIMIT 1) context ON true WHERE assistant.owner_user_id=$1 AND assistant.public_id=$11 RETURNING jsonb_build_object('packetRef',public_id,'assistantRef',$11::text,'revision',revision,'state',state,'manifestDigest',manifest_digest,'label',label,'updatedAt',updated_at) AS projection`, [ownerUserId2.toString(), randomUUID56(), packetRef, text2(body3, "memoryVaultRef"), text2(body3, "memoryPacketRef", packetRef), optionalText3(body3, "packetRevision") ?? "1", manifestDigest, text2(body3, "label"), optionalText3(body3, "sensitivity") ?? "standard", at, ref4(assistantRef2)]);
|
|
71282
70862
|
if (!result3.rows[0]) throw new Error("context_version_not_found");
|
|
71283
70863
|
await audit(client2, ownerUserId2.toString(), "assistant.context.create", packetRef, at);
|
|
71284
70864
|
return result3.rows[0].projection;
|
|
@@ -71333,7 +70913,7 @@ function createPostgresPersonalAssistantNumberPort(options) {
|
|
|
71333
70913
|
}
|
|
71334
70914
|
|
|
71335
70915
|
// src/api/personal-assistant-scheduling-store.ts
|
|
71336
|
-
import { createHash as
|
|
70916
|
+
import { createHash as createHash76, randomUUID as randomUUID57 } from "crypto";
|
|
71337
70917
|
var PersonalAssistantSchedulingStoreError = class extends Error {
|
|
71338
70918
|
constructor(code, message = code, status = code === "schedule_not_found" ? 404 : code === "schedule_activation_unavailable" ? 503 : 409) {
|
|
71339
70919
|
super(message);
|
|
@@ -71349,7 +70929,7 @@ function owner3(ownerUserId2) {
|
|
|
71349
70929
|
return ownerUserId2.toString();
|
|
71350
70930
|
}
|
|
71351
70931
|
function ref5(prefix) {
|
|
71352
|
-
return `${prefix}_${
|
|
70932
|
+
return `${prefix}_${randomUUID57().replaceAll("-", "")}`;
|
|
71353
70933
|
}
|
|
71354
70934
|
function iso4(value) {
|
|
71355
70935
|
return value instanceof Date ? value.toISOString() : new Date(value).toISOString();
|
|
@@ -71360,7 +70940,7 @@ function canonicalJson10(value) {
|
|
|
71360
70940
|
return JSON.stringify(value);
|
|
71361
70941
|
}
|
|
71362
70942
|
function digest11(value) {
|
|
71363
|
-
return
|
|
70943
|
+
return createHash76("sha256").update(canonicalJson10(value)).digest("hex");
|
|
71364
70944
|
}
|
|
71365
70945
|
function authorityClass(value) {
|
|
71366
70946
|
if (value === "observe") return "observe";
|
|
@@ -71473,7 +71053,7 @@ function createPostgresPersonalAssistantSchedulingStore(options) {
|
|
|
71473
71053
|
RETURNING id AS schedule_id,revision AS schedule_revision`,
|
|
71474
71054
|
[
|
|
71475
71055
|
ownerRef,
|
|
71476
|
-
|
|
71056
|
+
randomUUID57(),
|
|
71477
71057
|
input.draft.scheduleRef,
|
|
71478
71058
|
input.draft.instruction,
|
|
71479
71059
|
scheduleCadence(input.draft),
|
|
@@ -71507,7 +71087,7 @@ function createPostgresPersonalAssistantSchedulingStore(options) {
|
|
|
71507
71087
|
) VALUES ($1,$2,$3,$4,$5,$6,$7::jsonb,$8,$9,$10::timestamptz,$11::timestamptz)`,
|
|
71508
71088
|
[
|
|
71509
71089
|
ownerRef,
|
|
71510
|
-
|
|
71090
|
+
randomUUID57(),
|
|
71511
71091
|
ref5("schedrev"),
|
|
71512
71092
|
schedule.rows[0].schedule_id,
|
|
71513
71093
|
input.draft.revision,
|
|
@@ -71532,7 +71112,7 @@ function createPostgresPersonalAssistantSchedulingStore(options) {
|
|
|
71532
71112
|
AND profile.deleted_at IS NULL AND login.deleted_at IS NULL`,
|
|
71533
71113
|
[
|
|
71534
71114
|
ownerRef,
|
|
71535
|
-
|
|
71115
|
+
randomUUID57(),
|
|
71536
71116
|
ref5("sbgrant"),
|
|
71537
71117
|
schedule.rows[0].schedule_id,
|
|
71538
71118
|
input.draft.revision,
|
|
@@ -71602,7 +71182,7 @@ function createPostgresPersonalAssistantSchedulingStore(options) {
|
|
|
71602
71182
|
RETURNING id`,
|
|
71603
71183
|
[
|
|
71604
71184
|
ownerRef,
|
|
71605
|
-
|
|
71185
|
+
randomUUID57(),
|
|
71606
71186
|
ref5("sready"),
|
|
71607
71187
|
row.schedule_id,
|
|
71608
71188
|
row.revision,
|
|
@@ -71651,7 +71231,7 @@ function createPostgresPersonalAssistantSchedulingStore(options) {
|
|
|
71651
71231
|
) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12::jsonb,$13::timestamptz)`,
|
|
71652
71232
|
[
|
|
71653
71233
|
ownerRef,
|
|
71654
|
-
|
|
71234
|
+
randomUUID57(),
|
|
71655
71235
|
ref5("sactivate"),
|
|
71656
71236
|
row.schedule_id,
|
|
71657
71237
|
row.revision,
|
|
@@ -71804,7 +71384,7 @@ function assertNoRawTwilioSecretEnvironment(environment2 = process.env) {
|
|
|
71804
71384
|
}
|
|
71805
71385
|
|
|
71806
71386
|
// src/api/twilio-messaging-service.ts
|
|
71807
|
-
import { createHash as
|
|
71387
|
+
import { createHash as createHash77 } from "crypto";
|
|
71808
71388
|
|
|
71809
71389
|
// src/api/personal-assistant-policy.ts
|
|
71810
71390
|
var AUTHORITY_RANK = {
|
|
@@ -72104,10 +71684,10 @@ function canonicalJson11(value) {
|
|
|
72104
71684
|
});
|
|
72105
71685
|
}
|
|
72106
71686
|
function digest12(value) {
|
|
72107
|
-
return
|
|
71687
|
+
return createHash77("sha256").update(canonicalJson11(value)).digest("hex");
|
|
72108
71688
|
}
|
|
72109
71689
|
function deterministicRef3(prefix, identity) {
|
|
72110
|
-
return `${prefix}_${
|
|
71690
|
+
return `${prefix}_${createHash77("sha256").update(identity).digest("hex").slice(0, 32)}`;
|
|
72111
71691
|
}
|
|
72112
71692
|
function isBoundedAuthorityRef(value) {
|
|
72113
71693
|
return typeof value === "string" && value.length >= 3 && value.length <= 240 && !value.includes("\0");
|
|
@@ -72279,7 +71859,7 @@ function inboundIdentity(input, route) {
|
|
|
72279
71859
|
};
|
|
72280
71860
|
}
|
|
72281
71861
|
function sha256Bytes(bytes2) {
|
|
72282
|
-
return
|
|
71862
|
+
return createHash77("sha256").update(bytes2).digest("hex");
|
|
72283
71863
|
}
|
|
72284
71864
|
function startsWith(bytes2, signature) {
|
|
72285
71865
|
return signature.every((value, index) => bytes2[index] === value);
|
|
@@ -73458,11 +73038,11 @@ function createTwilioMessagingService(dependencies = {}) {
|
|
|
73458
73038
|
}
|
|
73459
73039
|
|
|
73460
73040
|
// src/api/twilio-memory-media.ts
|
|
73461
|
-
import { createHash as
|
|
73041
|
+
import { createHash as createHash78, randomUUID as randomUUID58 } from "crypto";
|
|
73462
73042
|
var IMAGE_TYPES = /* @__PURE__ */ new Set(["image/jpeg", "image/png", "image/gif", "image/webp"]);
|
|
73463
73043
|
var FILE_TYPES = /* @__PURE__ */ new Set(["application/pdf", "text/plain"]);
|
|
73464
73044
|
function digestBytes(bytes2) {
|
|
73465
|
-
return
|
|
73045
|
+
return createHash78("sha256").update(bytes2).digest("hex");
|
|
73466
73046
|
}
|
|
73467
73047
|
function publicPointer(pointer) {
|
|
73468
73048
|
return Object.freeze({
|
|
@@ -73546,7 +73126,7 @@ function createTwilioMemoryMedia(options) {
|
|
|
73546
73126
|
return publicPointer(await options.pointers.put({
|
|
73547
73127
|
ownerBindingRef: input.ownerBindingRef,
|
|
73548
73128
|
mediaRef: input.mediaRef,
|
|
73549
|
-
renewablePointerRef: `memory_asset_${
|
|
73129
|
+
renewablePointerRef: `memory_asset_${createHash78("sha256").update(`${input.ownerBindingRef}\0${asset.assetId}`).digest("hex").slice(0, 32)}`,
|
|
73550
73130
|
byteDigest: input.byteDigest,
|
|
73551
73131
|
contentType: input.contentType,
|
|
73552
73132
|
byteSize: input.bytes.byteLength,
|
|
@@ -73579,7 +73159,7 @@ function createTwilioMemoryMedia(options) {
|
|
|
73579
73159
|
}
|
|
73580
73160
|
|
|
73581
73161
|
// src/api/twilio-provider-facade.ts
|
|
73582
|
-
import { createHash as
|
|
73162
|
+
import { createHash as createHash79 } from "crypto";
|
|
73583
73163
|
|
|
73584
73164
|
// src/api/twilio-messaging-client.ts
|
|
73585
73165
|
import twilio4 from "twilio";
|
|
@@ -73914,7 +73494,7 @@ function validAuthority(input) {
|
|
|
73914
73494
|
return /^[1-9]\d*$/u.test(input.ownerUserId) && PUBLIC_REF2.test(input.executionRef) && ACCOUNT_SID3.test(input.providerAccountRef) && PUBLIC_REF2.test(input.connectionRef) && /^[A-Za-z][A-Za-z0-9_.:-]{2,159}$/u.test(input.environmentRef);
|
|
73915
73495
|
}
|
|
73916
73496
|
function digest13(value) {
|
|
73917
|
-
return
|
|
73497
|
+
return createHash79("sha256").update(JSON.stringify(value, (_key, entry) => {
|
|
73918
73498
|
if (!entry || typeof entry !== "object" || Array.isArray(entry)) return entry;
|
|
73919
73499
|
return Object.fromEntries(Object.entries(entry).sort(([a], [b]) => a.localeCompare(b)));
|
|
73920
73500
|
})).digest("hex");
|
|
@@ -74103,7 +73683,7 @@ function createTwilioProduction(options) {
|
|
|
74103
73683
|
}
|
|
74104
73684
|
|
|
74105
73685
|
// src/runtime/personal-assistant-deployment-config.ts
|
|
74106
|
-
import { createHash as
|
|
73686
|
+
import { createHash as createHash80 } from "crypto";
|
|
74107
73687
|
import { readFileSync as readFileSync4 } from "fs";
|
|
74108
73688
|
import { resolve as resolve2 } from "path";
|
|
74109
73689
|
var REF_PATTERN = /^(?:[a-z][a-z0-9+.-]*:\/\/)?[A-Za-z0-9][A-Za-z0-9._:/-]{2,240}$/;
|
|
@@ -74139,7 +73719,7 @@ function databaseBinding(value) {
|
|
|
74139
73719
|
const database = decodeURIComponent(parsed.pathname.replace(/^\//, ""));
|
|
74140
73720
|
const role = decodeURIComponent(parsed.username);
|
|
74141
73721
|
if (!database || !/^[a-z_][a-z0-9_]*$/.test(role)) return null;
|
|
74142
|
-
return { fingerprint:
|
|
73722
|
+
return { fingerprint: createHash80("sha256").update(`${labels.join(".")}\0${database}`).digest("hex"), role };
|
|
74143
73723
|
} catch {
|
|
74144
73724
|
return null;
|
|
74145
73725
|
}
|
|
@@ -74601,7 +74181,7 @@ function createPersonalAssistantHostedConfigurationAdapter(input) {
|
|
|
74601
74181
|
}
|
|
74602
74182
|
|
|
74603
74183
|
// src/api/personal-assistant-authorization.ts
|
|
74604
|
-
import { createHash as
|
|
74184
|
+
import { createHash as createHash81 } from "crypto";
|
|
74605
74185
|
import { z as z49 } from "zod";
|
|
74606
74186
|
var ABUSE_GATED_OPERATIONS = /* @__PURE__ */ new Set(["assistant.message.send", "assistant.bulk.send"]);
|
|
74607
74187
|
var NORMALIZED_RECIPIENT_OPERATIONS = /* @__PURE__ */ new Set([
|
|
@@ -74779,7 +74359,7 @@ function canonicalJson12(value) {
|
|
|
74779
74359
|
return JSON.stringify(value, (_key, entry) => entry && typeof entry === "object" && !Array.isArray(entry) ? Object.fromEntries(Object.entries(entry).sort(([a], [b]) => a.localeCompare(b))) : entry);
|
|
74780
74360
|
}
|
|
74781
74361
|
function factDigest(value) {
|
|
74782
|
-
return
|
|
74362
|
+
return createHash81("sha256").update(canonicalJson12(value)).digest("hex");
|
|
74783
74363
|
}
|
|
74784
74364
|
var PostgresPersonalAssistantPolicyFactsRepository = class {
|
|
74785
74365
|
constructor(db, contexts, now = () => /* @__PURE__ */ new Date()) {
|
|
@@ -74969,7 +74549,7 @@ var PostgresPersonalAssistantPolicyFactsRepository = class {
|
|
|
74969
74549
|
};
|
|
74970
74550
|
|
|
74971
74551
|
// src/api/personal-assistant-abuse-controls.ts
|
|
74972
|
-
import { createHash as
|
|
74552
|
+
import { createHash as createHash82 } from "crypto";
|
|
74973
74553
|
var EMPTY_STATE = () => ({
|
|
74974
74554
|
version: 1,
|
|
74975
74555
|
events: [],
|
|
@@ -74980,7 +74560,7 @@ var EMPTY_STATE = () => ({
|
|
|
74980
74560
|
bulkIdentities: {}
|
|
74981
74561
|
});
|
|
74982
74562
|
function digest14(value) {
|
|
74983
|
-
return
|
|
74563
|
+
return createHash82("sha256").update(JSON.stringify(value)).digest("hex");
|
|
74984
74564
|
}
|
|
74985
74565
|
function isDigest(value) {
|
|
74986
74566
|
return typeof value === "string" && /^[a-f0-9]{64}$/.test(value);
|
|
@@ -75069,10 +74649,10 @@ function applyRequest(state2, request, policy7) {
|
|
|
75069
74649
|
const at = validateRequest(request, policy7);
|
|
75070
74650
|
if (at === null) return decision("deny", "invalid_abuse_request", request);
|
|
75071
74651
|
trimState(state2, at, policy7);
|
|
75072
|
-
const
|
|
74652
|
+
const fingerprint5 = digest14({ ...request, occurredAt: void 0 });
|
|
75073
74653
|
const logicalFingerprint = digest14({ ...request, idempotencyKey: void 0, occurredAt: void 0 });
|
|
75074
74654
|
const idempotent = state2.decisions[request.idempotencyKey];
|
|
75075
|
-
if (idempotent && idempotent.fingerprint !==
|
|
74655
|
+
if (idempotent && idempotent.fingerprint !== fingerprint5) return decision("deny", "invalid_abuse_request", request);
|
|
75076
74656
|
const logical = state2.logicalReservations[request.logicalMessageRef];
|
|
75077
74657
|
if (logical && logical.fingerprint !== logicalFingerprint) return decision("deny", "invalid_abuse_request", request);
|
|
75078
74658
|
let bulkIdentity = request.bulk ? state2.bulkIdentities[request.bulk.operationRef] : void 0;
|
|
@@ -75086,7 +74666,7 @@ function applyRequest(state2, request, policy7) {
|
|
|
75086
74666
|
}
|
|
75087
74667
|
if (logical && !isAdministratorKillReason(logical.decision.reason)) {
|
|
75088
74668
|
const replay = Object.freeze({ ...logical.decision, replayed: true });
|
|
75089
|
-
state2.decisions[request.idempotencyKey] = { fingerprint:
|
|
74669
|
+
state2.decisions[request.idempotencyKey] = { fingerprint: fingerprint5, decision: replay };
|
|
75090
74670
|
return replay;
|
|
75091
74671
|
}
|
|
75092
74672
|
if (idempotent) delete state2.decisions[request.idempotencyKey];
|
|
@@ -75178,7 +74758,7 @@ function applyRequest(state2, request, policy7) {
|
|
|
75178
74758
|
suspicious: Boolean(request.suspiciousInbound)
|
|
75179
74759
|
});
|
|
75180
74760
|
}
|
|
75181
|
-
const stored = { fingerprint:
|
|
74761
|
+
const stored = { fingerprint: fingerprint5, decision: result3 };
|
|
75182
74762
|
state2.decisions[request.idempotencyKey] = stored;
|
|
75183
74763
|
state2.logicalReservations[request.logicalMessageRef] = {
|
|
75184
74764
|
fingerprint: digest14({ ...request, idempotencyKey: void 0, occurredAt: void 0 }),
|
|
@@ -75189,11 +74769,11 @@ function applyRequest(state2, request, policy7) {
|
|
|
75189
74769
|
function applyOutcome(state2, outcome, policy7) {
|
|
75190
74770
|
const at = Date.parse(outcome.occurredAt);
|
|
75191
74771
|
if (!Number.isFinite(at) || !outcome.ownerUserId || !outcome.numberRef || !isDigest(outcome.recipientHash) || !outcome.logicalMessageRef || !outcome.idempotencyKey || !validPolicy(policy7)) return;
|
|
75192
|
-
const
|
|
74772
|
+
const fingerprint5 = digest14(outcome);
|
|
75193
74773
|
const prior = state2.outcomeReceipts[outcome.idempotencyKey];
|
|
75194
74774
|
if (prior) return;
|
|
75195
74775
|
trimState(state2, at, policy7);
|
|
75196
|
-
state2.outcomeReceipts[outcome.idempotencyKey] = { fingerprint:
|
|
74776
|
+
state2.outcomeReceipts[outcome.idempotencyKey] = { fingerprint: fingerprint5, at };
|
|
75197
74777
|
if (outcome.outcome === "succeeded") {
|
|
75198
74778
|
state2.failures = state2.failures.filter((event2) => event2.numberRef !== outcome.numberRef && event2.recipientHash !== outcome.recipientHash);
|
|
75199
74779
|
}
|
|
@@ -75240,10 +74820,10 @@ var PostgresPersonalAssistantAbuseStore = class {
|
|
|
75240
74820
|
};
|
|
75241
74821
|
|
|
75242
74822
|
// src/api/twilio-authority-billing-postgres.ts
|
|
75243
|
-
import { createHash as
|
|
74823
|
+
import { createHash as createHash84, randomUUID as randomUUID59 } from "crypto";
|
|
75244
74824
|
|
|
75245
74825
|
// src/api/personal-assistant-billing.ts
|
|
75246
|
-
import { createHash as
|
|
74826
|
+
import { createHash as createHash83 } from "crypto";
|
|
75247
74827
|
var AssistantBillingError = class extends Error {
|
|
75248
74828
|
constructor(code, message) {
|
|
75249
74829
|
super(message);
|
|
@@ -75260,7 +74840,7 @@ function canonicalJson13(value) {
|
|
|
75260
74840
|
});
|
|
75261
74841
|
}
|
|
75262
74842
|
function digest15(value) {
|
|
75263
|
-
return
|
|
74843
|
+
return createHash83("sha256").update(canonicalJson13(value)).digest("hex");
|
|
75264
74844
|
}
|
|
75265
74845
|
function assertMoney(value, field) {
|
|
75266
74846
|
if (!Number.isSafeInteger(value) || value < 0) throw new AssistantBillingError("billing_invalid_input", `${field} must be a non-negative safe integer.`);
|
|
@@ -75305,7 +74885,7 @@ function canonicalJson14(value) {
|
|
|
75305
74885
|
});
|
|
75306
74886
|
}
|
|
75307
74887
|
function digest16(value) {
|
|
75308
|
-
return
|
|
74888
|
+
return createHash84("sha256").update(canonicalJson14(value)).digest("hex");
|
|
75309
74889
|
}
|
|
75310
74890
|
function amountFor2(usage) {
|
|
75311
74891
|
return usage.reduce((sum2, item) => sum2 + item.units * item.rateMinorPerUnit, 0);
|
|
@@ -75377,7 +74957,7 @@ function createPostgresAssistantBillingStore(options = {}) {
|
|
|
75377
74957
|
FROM assistant.commands command WHERE command.owner_user_id=$1 AND command.public_id=$14
|
|
75378
74958
|
RETURNING *, $14::text AS command_ref`, [
|
|
75379
74959
|
input.ownerUserId.toString(),
|
|
75380
|
-
|
|
74960
|
+
randomUUID59(),
|
|
75381
74961
|
input.billingRef,
|
|
75382
74962
|
input.idempotencyKey,
|
|
75383
74963
|
input.requestDigest,
|
|
@@ -75397,7 +74977,7 @@ function createPostgresAssistantBillingStore(options = {}) {
|
|
|
75397
74977
|
SELECT $1,$2,billing.id,$3,$4,'authorize',$5,$6,$7 FROM assistant.billing_holds billing
|
|
75398
74978
|
WHERE billing.owner_user_id=$1 AND billing.public_id=$8`, [
|
|
75399
74979
|
input.ownerUserId.toString(),
|
|
75400
|
-
|
|
74980
|
+
randomUUID59(),
|
|
75401
74981
|
`authorize:${input.idempotencyKey}`,
|
|
75402
74982
|
inputDigest,
|
|
75403
74983
|
input.requestDigest,
|
|
@@ -75463,7 +75043,7 @@ function createPostgresAssistantBillingStore(options = {}) {
|
|
|
75463
75043
|
FROM assistant.billing_holds billing WHERE billing.owner_user_id=$1 AND billing.public_id=$9`,
|
|
75464
75044
|
[
|
|
75465
75045
|
input.ownerUserId.toString(),
|
|
75466
|
-
|
|
75046
|
+
randomUUID59(),
|
|
75467
75047
|
input.eventKey,
|
|
75468
75048
|
eventDigest,
|
|
75469
75049
|
input.outcome,
|
|
@@ -75511,7 +75091,7 @@ function createPostgresAssistantBillingStore(options = {}) {
|
|
|
75511
75091
|
FROM assistant.billing_holds billing WHERE billing.owner_user_id=$1 AND billing.public_id=$8`,
|
|
75512
75092
|
[
|
|
75513
75093
|
input.ownerUserId.toString(),
|
|
75514
|
-
|
|
75094
|
+
randomUUID59(),
|
|
75515
75095
|
input.eventKey,
|
|
75516
75096
|
eventDigest,
|
|
75517
75097
|
input.evidenceDigest,
|
|
@@ -75540,8 +75120,8 @@ function createPostgresAssistantBillingStore(options = {}) {
|
|
|
75540
75120
|
import {
|
|
75541
75121
|
createCipheriv as createCipheriv3,
|
|
75542
75122
|
createDecipheriv as createDecipheriv3,
|
|
75543
|
-
createHash as
|
|
75544
|
-
createHmac as
|
|
75123
|
+
createHash as createHash85,
|
|
75124
|
+
createHmac as createHmac14,
|
|
75545
75125
|
randomBytes as randomBytes10
|
|
75546
75126
|
} from "crypto";
|
|
75547
75127
|
var ENVELOPE_VERSION = "pa1";
|
|
@@ -75598,7 +75178,7 @@ function canonicalContext(input) {
|
|
|
75598
75178
|
});
|
|
75599
75179
|
}
|
|
75600
75180
|
function contextDigest(context) {
|
|
75601
|
-
return
|
|
75181
|
+
return createHash85("sha256").update(context, "utf8").digest("hex");
|
|
75602
75182
|
}
|
|
75603
75183
|
function decodeBase64Url(value, expectedBytes) {
|
|
75604
75184
|
if (!value || !BASE64URL.test(value)) throw new PersonalAssistantProtectedDataCryptoError("protected_data_envelope_invalid");
|
|
@@ -75708,7 +75288,7 @@ function createFromKeyring(options) {
|
|
|
75708
75288
|
}
|
|
75709
75289
|
function hmacForPurpose(value, purpose) {
|
|
75710
75290
|
const context = canonicalContext({ purpose, ownerBindingRef, environmentRef });
|
|
75711
|
-
return
|
|
75291
|
+
return createHmac14("sha256", materialFor().hmacKey).update(context, "utf8").update("\0").update(value, "utf8").digest("hex");
|
|
75712
75292
|
}
|
|
75713
75293
|
function twilioAad(messageRef) {
|
|
75714
75294
|
if (!BINDING_REF.test(messageRef)) throw new PersonalAssistantProtectedDataCryptoError("protected_data_context_invalid");
|
|
@@ -75787,8 +75367,8 @@ async function resolvePersonalAssistantProtectedDataCryptoFactory(options) {
|
|
|
75787
75367
|
}
|
|
75788
75368
|
|
|
75789
75369
|
// src/api/twilio-first-text-context-postgres.ts
|
|
75790
|
-
import { createHash as
|
|
75791
|
-
var digest17 = (value) =>
|
|
75370
|
+
import { createHash as createHash86 } from "crypto";
|
|
75371
|
+
var digest17 = (value) => createHash86("sha256").update(value).digest("hex");
|
|
75792
75372
|
function createPostgresTwilioFirstTextDiagnosticContextResolver(options = {}) {
|
|
75793
75373
|
const queryable = options.queryable ?? getAssistantPool();
|
|
75794
75374
|
return async (input) => {
|
|
@@ -75833,10 +75413,10 @@ function createPostgresTwilioFirstTextDiagnosticContextResolver(options = {}) {
|
|
|
75833
75413
|
}
|
|
75834
75414
|
|
|
75835
75415
|
// src/api/twilio-first-text-diagnostic-postgres.ts
|
|
75836
|
-
import { createHash as
|
|
75416
|
+
import { createHash as createHash88, randomBytes as randomBytes12, randomUUID as randomUUID60 } from "crypto";
|
|
75837
75417
|
|
|
75838
75418
|
// src/api/twilio-first-text-diagnostic.ts
|
|
75839
|
-
import { createHash as
|
|
75419
|
+
import { createHash as createHash87, randomBytes as randomBytes11 } from "crypto";
|
|
75840
75420
|
var TWILIO_FIRST_TEXT_BODY = ASSISTANT_CONSENT_CONTENT_V1.diagnosticMessage;
|
|
75841
75421
|
var TwilioFirstTextDiagnosticError = class extends Error {
|
|
75842
75422
|
constructor(code) {
|
|
@@ -75847,10 +75427,10 @@ var TwilioFirstTextDiagnosticError = class extends Error {
|
|
|
75847
75427
|
code;
|
|
75848
75428
|
};
|
|
75849
75429
|
function digest18(value) {
|
|
75850
|
-
return
|
|
75430
|
+
return createHash87("sha256").update(JSON.stringify(value)).digest("hex");
|
|
75851
75431
|
}
|
|
75852
75432
|
function stableRef2(prefix, identity) {
|
|
75853
|
-
return `${prefix}_${
|
|
75433
|
+
return `${prefix}_${createHash87("sha256").update(identity).digest("hex").slice(0, 32)}`;
|
|
75854
75434
|
}
|
|
75855
75435
|
function providerSid(result3) {
|
|
75856
75436
|
const value = result3.receipt.providerMessageSid;
|
|
@@ -75962,14 +75542,14 @@ function createTwilioFirstTextDiagnosticService(dependencies) {
|
|
|
75962
75542
|
var COLUMNS = `owner_user_id::text,public_id,idempotency_key,request_digest,policy_version,recipient_ref,sender_ref,
|
|
75963
75543
|
state,mode,stages,provider_message_sid,inbound_event_ref,routing_receipt_ref,acknowledgement_receipt_ref,
|
|
75964
75544
|
retry_eligible,failure_code,execution_token_digest,created_at,updated_at`;
|
|
75965
|
-
var digest19 = (value) =>
|
|
75545
|
+
var digest19 = (value) => createHash88("sha256").update(value).digest("hex");
|
|
75966
75546
|
var iso5 = (value) => new Date(value).toISOString();
|
|
75967
75547
|
function receipt3(row) {
|
|
75968
75548
|
return Object.freeze({
|
|
75969
75549
|
diagnosticRef: row.public_id,
|
|
75970
75550
|
ownerUserId: row.owner_user_id,
|
|
75971
75551
|
idempotencyKey: row.idempotency_key,
|
|
75972
|
-
executionRef: `execution_${
|
|
75552
|
+
executionRef: `execution_${createHash88("sha256").update(row.public_id).digest("hex").slice(0, 32)}`,
|
|
75973
75553
|
requestDigest: row.request_digest,
|
|
75974
75554
|
policyVersion: row.policy_version,
|
|
75975
75555
|
recipientRef: row.recipient_ref,
|
|
@@ -76010,7 +75590,7 @@ function createPostgresTwilioFirstTextDiagnosticStore(options = {}) {
|
|
|
76010
75590
|
ON CONFLICT (owner_user_id,idempotency_key) DO NOTHING RETURNING ${COLUMNS}`,
|
|
76011
75591
|
[
|
|
76012
75592
|
input.ownerUserId,
|
|
76013
|
-
|
|
75593
|
+
randomUUID60(),
|
|
76014
75594
|
input.diagnosticRef,
|
|
76015
75595
|
input.idempotencyKey,
|
|
76016
75596
|
input.requestDigest,
|
|
@@ -76137,10 +75717,10 @@ function createTwilioInboundQuarantineClaimAuthorizer(options) {
|
|
|
76137
75717
|
}
|
|
76138
75718
|
|
|
76139
75719
|
// src/api/twilio-inbound-claim-control-plane-postgres.ts
|
|
76140
|
-
import { createHash as
|
|
76141
|
-
var stableRef3 = (prefix, value) => `${prefix}_${
|
|
75720
|
+
import { createHash as createHash89, randomUUID as randomUUID61 } from "crypto";
|
|
75721
|
+
var stableRef3 = (prefix, value) => `${prefix}_${createHash89("sha256").update(value).digest("hex").slice(0, 32)}`;
|
|
76142
75722
|
var stableUuid = (value) => {
|
|
76143
|
-
const hex =
|
|
75723
|
+
const hex = createHash89("sha256").update(value).digest("hex").slice(0, 32).split("");
|
|
76144
75724
|
hex[12] = "5";
|
|
76145
75725
|
hex[16] = (Number.parseInt(hex[16], 16) & 3 | 8).toString(16);
|
|
76146
75726
|
return `${hex.slice(0, 8).join("")}-${hex.slice(8, 12).join("")}-${hex.slice(12, 16).join("")}-${hex.slice(16, 20).join("")}-${hex.slice(20).join("")}`;
|
|
@@ -76191,7 +75771,7 @@ function createPostgresTwilioInboundClaimControlPlane(options) {
|
|
|
76191
75771
|
(owner_user_id,id,public_id,endpoint_key,revision,contact_id,channel,address_ciphertext,address_hash,masked_display,state,reason_code,created_at)
|
|
76192
75772
|
VALUES ($1::bigint,$2,$3,$4,1,$5,'sms',$6,$7,$8,'unverified','claimed_inbound_requires_enrollment',$9::timestamptz)
|
|
76193
75773
|
ON CONFLICT (owner_user_id,public_id) DO NOTHING`,
|
|
76194
|
-
[input.ownerUserId,
|
|
75774
|
+
[input.ownerUserId, randomUUID61(), endpointRef, endpointKey, contact.rows[0].id, sender.ciphertext, sender.digest, mask(input.sender), input.occurredAt]
|
|
76195
75775
|
);
|
|
76196
75776
|
const route = number.rows[0];
|
|
76197
75777
|
const conversationRef = stableRef3(
|
|
@@ -76222,12 +75802,12 @@ function createPostgresTwilioInboundClaimControlPlane(options) {
|
|
|
76222
75802
|
}
|
|
76223
75803
|
|
|
76224
75804
|
// src/api/twilio-inbound-envelope-postgres.ts
|
|
76225
|
-
import { createHash as
|
|
75805
|
+
import { createHash as createHash91 } from "crypto";
|
|
76226
75806
|
|
|
76227
75807
|
// src/api/twilio-inbound-admission-postgres.ts
|
|
76228
|
-
import { createHash as
|
|
75808
|
+
import { createHash as createHash90, randomBytes as randomBytes13, randomUUID as randomUUID62 } from "crypto";
|
|
76229
75809
|
function tokenHash4(value) {
|
|
76230
|
-
return
|
|
75810
|
+
return createHash90("sha256").update(value).digest("hex");
|
|
76231
75811
|
}
|
|
76232
75812
|
function rowToRecord(row) {
|
|
76233
75813
|
return Object.freeze({
|
|
@@ -76272,7 +75852,7 @@ function createPostgresTwilioInboundAdmissionControl(options = {}) {
|
|
|
76272
75852
|
DO UPDATE SET request_count=assistant.twilio_webhook_rate_buckets.request_count+1,updated_at=EXCLUDED.updated_at
|
|
76273
75853
|
RETURNING request_count`, [
|
|
76274
75854
|
input.ownerUserId,
|
|
76275
|
-
|
|
75855
|
+
randomUUID62(),
|
|
76276
75856
|
input.providerAccountRef,
|
|
76277
75857
|
input.scope,
|
|
76278
75858
|
input.subjectKey,
|
|
@@ -76306,7 +75886,7 @@ function createPostgresTwilioInboundAdmissionStore(options = {}) {
|
|
|
76306
75886
|
provider_message_sid,provider_messaging_service_sid,lane_key,routing_state,payload_digest,protected_envelope,state,attempt,admitted_at`,
|
|
76307
75887
|
[
|
|
76308
75888
|
input.ownerUserId,
|
|
76309
|
-
|
|
75889
|
+
randomUUID62(),
|
|
76310
75890
|
input.ingressRef,
|
|
76311
75891
|
input.ownerBindingRef,
|
|
76312
75892
|
input.providerAccountRef,
|
|
@@ -76396,7 +75976,7 @@ function createPostgresTwilioInboundAdmissionStore(options = {}) {
|
|
|
76396
75976
|
|
|
76397
75977
|
// src/api/twilio-inbound-envelope-postgres.ts
|
|
76398
75978
|
function stableRef4(prefix, identity) {
|
|
76399
|
-
return `${prefix}_${
|
|
75979
|
+
return `${prefix}_${createHash91("sha256").update(identity).digest("hex").slice(0, 32)}`;
|
|
76400
75980
|
}
|
|
76401
75981
|
function parseStoredEnvelope(value) {
|
|
76402
75982
|
let parsed;
|
|
@@ -76610,7 +76190,7 @@ function createPostgresTwilioInboundAdmissionRuntime(options) {
|
|
|
76610
76190
|
}
|
|
76611
76191
|
|
|
76612
76192
|
// src/api/twilio-inbound-quarantine-postgres.ts
|
|
76613
|
-
import { randomUUID as
|
|
76193
|
+
import { randomUUID as randomUUID63 } from "crypto";
|
|
76614
76194
|
function createPostgresTwilioInboundQuarantineAdmissionControl(options = {}) {
|
|
76615
76195
|
const transaction2 = options.transaction ?? ((work) => withAssistantTransaction((client2) => work(client2)));
|
|
76616
76196
|
const windowSeconds = options.windowSeconds ?? 60;
|
|
@@ -76690,7 +76270,7 @@ function createPostgresTwilioInboundQuarantineStore(options = {}) {
|
|
|
76690
76270
|
) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,'pending',$11,$12::timestamptz,$13::timestamptz,$14::timestamptz,$14::timestamptz)
|
|
76691
76271
|
ON CONFLICT DO NOTHING RETURNING ${COLUMNS2}`,
|
|
76692
76272
|
[
|
|
76693
|
-
|
|
76273
|
+
randomUUID63(),
|
|
76694
76274
|
input.quarantineRef,
|
|
76695
76275
|
input.providerAccountDigest,
|
|
76696
76276
|
input.providerMessageDigest,
|
|
@@ -76758,11 +76338,11 @@ function createPostgresTwilioInboundQuarantineStore(options = {}) {
|
|
|
76758
76338
|
}
|
|
76759
76339
|
|
|
76760
76340
|
// src/api/twilio-inbound-quarantine.ts
|
|
76761
|
-
import { createHash as
|
|
76341
|
+
import { createHash as createHash92, createHmac as createHmac15, timingSafeEqual as timingSafeEqual10 } from "crypto";
|
|
76762
76342
|
var DIGEST7 = /^[a-f0-9]{64}$/u;
|
|
76763
76343
|
var OPAQUE2 = /^[A-Za-z][A-Za-z0-9_.:-]{2,199}$/u;
|
|
76764
76344
|
function digest20(value) {
|
|
76765
|
-
return
|
|
76345
|
+
return createHash92("sha256").update(value).digest("hex");
|
|
76766
76346
|
}
|
|
76767
76347
|
function stableRef5(prefix, identity) {
|
|
76768
76348
|
return `${prefix}_${digest20(identity).slice(0, 32)}`;
|
|
@@ -76777,14 +76357,14 @@ function tokenPayload(payload) {
|
|
|
76777
76357
|
}
|
|
76778
76358
|
function signToken(secret, payload) {
|
|
76779
76359
|
const encoded = tokenPayload(payload);
|
|
76780
|
-
return `${encoded}.${
|
|
76360
|
+
return `${encoded}.${createHmac15("sha256", secret).update(encoded).digest("base64url")}`;
|
|
76781
76361
|
}
|
|
76782
76362
|
function verifyToken2(secret, token7, now) {
|
|
76783
76363
|
const [encoded, suppliedSignature, extra] = token7.split(".");
|
|
76784
76364
|
if (!encoded || !suppliedSignature || extra !== void 0 || token7.length > 2048) {
|
|
76785
76365
|
throw new TwilioInboundAdmissionError("inbound_claim_rejected");
|
|
76786
76366
|
}
|
|
76787
|
-
const expected =
|
|
76367
|
+
const expected = createHmac15("sha256", secret).update(encoded).digest();
|
|
76788
76368
|
let supplied;
|
|
76789
76369
|
try {
|
|
76790
76370
|
supplied = Buffer.from(suppliedSignature, "base64url");
|
|
@@ -77077,10 +76657,10 @@ async function createPersonalAssistantTwilioTransportProduction(options) {
|
|
|
77077
76657
|
}
|
|
77078
76658
|
|
|
77079
76659
|
// src/api/twilio-number-production.ts
|
|
77080
|
-
import { createHash as
|
|
76660
|
+
import { createHash as createHash94, randomUUID as randomUUID65 } from "crypto";
|
|
77081
76661
|
|
|
77082
76662
|
// src/api/twilio-number-repository.ts
|
|
77083
|
-
import { createHash as
|
|
76663
|
+
import { createHash as createHash93, randomUUID as randomUUID64 } from "crypto";
|
|
77084
76664
|
var PUBLIC_REF3 = /^[a-z][a-z0-9_]*_[A-Za-z0-9_-]{3,128}$/;
|
|
77085
76665
|
var DIGEST8 = /^[a-f0-9]{64}$/;
|
|
77086
76666
|
var ACCOUNT_SID4 = /^AC[0-9a-f]{32}$/i;
|
|
@@ -77169,7 +76749,7 @@ function priceValue(value) {
|
|
|
77169
76749
|
}), blocker: null });
|
|
77170
76750
|
}
|
|
77171
76751
|
function digest21(value) {
|
|
77172
|
-
return
|
|
76752
|
+
return createHash93("sha256").update(JSON.stringify(value, (_key, entry) => {
|
|
77173
76753
|
if (!entry || typeof entry !== "object" || Array.isArray(entry)) return entry;
|
|
77174
76754
|
return Object.fromEntries(Object.entries(entry).sort(([a], [b]) => a.localeCompare(b)));
|
|
77175
76755
|
})).digest("hex");
|
|
@@ -77296,7 +76876,7 @@ function createPostgresTwilioNumberOwnerRepository(options) {
|
|
|
77296
76876
|
const ownerUserId2 = requireOwner(options.ownerUserId);
|
|
77297
76877
|
const queryable = options.queryable ?? getAssistantPool();
|
|
77298
76878
|
const transaction2 = options.transaction ?? ((work) => withAssistantTransaction((client2) => work(client2)));
|
|
77299
|
-
const newId = options.newId ??
|
|
76879
|
+
const newId = options.newId ?? randomUUID64;
|
|
77300
76880
|
const now = options.now ?? (() => /* @__PURE__ */ new Date());
|
|
77301
76881
|
const snapshot = validateSnapshot(options.resourceSnapshot, ownerUserId2, now());
|
|
77302
76882
|
async function numberRow(numberRef) {
|
|
@@ -77956,13 +77536,13 @@ function createPostgresTwilioNumberProductionAdapters(options) {
|
|
|
77956
77536
|
}
|
|
77957
77537
|
function twilioProviderAccountDigest(providerAccountRef) {
|
|
77958
77538
|
if (!ACCOUNT_SID4.test(providerAccountRef)) throw new TwilioNumberRepositoryError("invalid_provider_account", "Twilio account assignment is invalid.", 400);
|
|
77959
|
-
return
|
|
77539
|
+
return createHash93("sha256").update(providerAccountRef).digest("hex");
|
|
77960
77540
|
}
|
|
77961
77541
|
|
|
77962
77542
|
// src/api/twilio-number-production.ts
|
|
77963
77543
|
var DIGEST9 = /^[a-f0-9]{64}$/u;
|
|
77964
77544
|
function hash3(value) {
|
|
77965
|
-
return
|
|
77545
|
+
return createHash94("sha256").update(typeof value === "string" ? value : JSON.stringify(value, (_key, entry) => {
|
|
77966
77546
|
if (!entry || typeof entry !== "object" || Array.isArray(entry)) return entry;
|
|
77967
77547
|
return Object.fromEntries(Object.entries(entry).sort(([a], [b]) => a.localeCompare(b)));
|
|
77968
77548
|
})).digest("hex");
|
|
@@ -78215,12 +77795,12 @@ function createPostgresTwilioNumberAuthorityAdapters(options) {
|
|
|
78215
77795
|
WHERE approval.owner_user_id=$1 AND approval.state IN ('pending','approved') AND command.owner_user_id=approval.owner_user_id
|
|
78216
77796
|
AND command.id=approval.command_id AND command.assistant_id=$2`, [ownerUserId2.toString(), row.assistant_id]);
|
|
78217
77797
|
const authorityEpoch = hash3({ ownerUserId: ownerUserId2.toString(), numberRef: input.numberRef, releaseRef: input.releaseRef, occurredAt: input.occurredAt });
|
|
78218
|
-
const auditRef = `audit_${
|
|
77798
|
+
const auditRef = `audit_${randomUUID65().replace(/-/g, "")}`;
|
|
78219
77799
|
await client2.query(
|
|
78220
77800
|
`INSERT INTO assistant.audit_events(owner_user_id,id,public_id,assistant_id,actor_kind,event_type,
|
|
78221
77801
|
operation,decision,reason_code,correlation_id,evidence_digest,details,occurred_at)
|
|
78222
77802
|
VALUES($1,$2,$3,$4,'system','twilio.number.release.freeze','twilio.number.release','allow','authority_invalidated',$5,$6,$7::jsonb,$8)`,
|
|
78223
|
-
[ownerUserId2.toString(),
|
|
77803
|
+
[ownerUserId2.toString(), randomUUID65(), auditRef, row.assistant_id, authorityEpoch, hash3(input.releaseRef), JSON.stringify({ numberRef: input.numberRef, releaseRef: input.releaseRef }), input.occurredAt]
|
|
78224
77804
|
);
|
|
78225
77805
|
return {
|
|
78226
77806
|
authorityEpoch,
|
|
@@ -78375,7 +77955,7 @@ function createTwilioNumberProductionInterfaces(options) {
|
|
|
78375
77955
|
}
|
|
78376
77956
|
|
|
78377
77957
|
// src/api/twilio-number-service.ts
|
|
78378
|
-
import { createHash as
|
|
77958
|
+
import { createHash as createHash95, randomUUID as randomUUID66 } from "crypto";
|
|
78379
77959
|
var DEFAULT_RESERVATION_TTL_MS = 5 * 60 * 1e3;
|
|
78380
77960
|
var MIN_RESERVATION_TTL_MS = 60 * 1e3;
|
|
78381
77961
|
var MAX_RESERVATION_TTL_MS = 10 * 60 * 1e3;
|
|
@@ -78511,7 +78091,7 @@ function canonicalJson15(value) {
|
|
|
78511
78091
|
});
|
|
78512
78092
|
}
|
|
78513
78093
|
function digest22(value) {
|
|
78514
|
-
return
|
|
78094
|
+
return createHash95("sha256").update(canonicalJson15(value)).digest("hex");
|
|
78515
78095
|
}
|
|
78516
78096
|
function requireIdempotencyKey(value) {
|
|
78517
78097
|
if (typeof value !== "string" || !/^[A-Za-z0-9][A-Za-z0-9:._/-]{7,239}$/.test(value)) {
|
|
@@ -78632,7 +78212,7 @@ function publicReleaseReceipt(receipt4, replayed = receipt4.replayed) {
|
|
|
78632
78212
|
}
|
|
78633
78213
|
function createTwilioNumberService(dependencies = {}) {
|
|
78634
78214
|
const now = dependencies.now ?? (() => /* @__PURE__ */ new Date());
|
|
78635
|
-
const newId = dependencies.newId ??
|
|
78215
|
+
const newId = dependencies.newId ?? randomUUID66;
|
|
78636
78216
|
const ttlMs = dependencies.reservationTtlMs ?? DEFAULT_RESERVATION_TTL_MS;
|
|
78637
78217
|
if (!Number.isInteger(ttlMs) || ttlMs < MIN_RESERVATION_TTL_MS || ttlMs > MAX_RESERVATION_TTL_MS) {
|
|
78638
78218
|
throw new TwilioNumberServiceError("invalid_configuration", "Number reservation lifetime must be from one through ten minutes.", 500);
|
|
@@ -79940,7 +79520,7 @@ function presence(env) {
|
|
|
79940
79520
|
}
|
|
79941
79521
|
function fingerprintDigest(env) {
|
|
79942
79522
|
const value = env.PA_NEON_BINDING_FINGERPRINT?.trim();
|
|
79943
|
-
return value ?
|
|
79523
|
+
return value ? createHash96("sha256").update("personal-assistant-binding-v1\0").update(value).digest("hex") : null;
|
|
79944
79524
|
}
|
|
79945
79525
|
function missingHostedBindings(env) {
|
|
79946
79526
|
return Object.entries(REQUIRED_HOSTED_BINDINGS).filter(([, variable]) => !env[variable]?.trim()).map(([name]) => `binding_${name}_missing`);
|
|
@@ -80173,7 +79753,7 @@ function shouldRunSiteExtractInBackground(input) {
|
|
|
80173
79753
|
}
|
|
80174
79754
|
|
|
80175
79755
|
// src/api/page-media-artifacts.ts
|
|
80176
|
-
import { createHash as
|
|
79756
|
+
import { createHash as createHash97, randomBytes as randomBytes14 } from "crypto";
|
|
80177
79757
|
import { homedir as homedir4 } from "os";
|
|
80178
79758
|
import { basename, extname, join as join9 } from "path";
|
|
80179
79759
|
import pLimit6 from "p-limit";
|
|
@@ -80320,7 +79900,7 @@ async function fetchMedia(rawUrl, expectedType) {
|
|
|
80320
79900
|
finalUrl: checked.parsed.href,
|
|
80321
79901
|
width: dimensions?.width ?? null,
|
|
80322
79902
|
height: dimensions?.height ?? null,
|
|
80323
|
-
sha256:
|
|
79903
|
+
sha256: createHash97("sha256").update(bytes2).digest("hex")
|
|
80324
79904
|
};
|
|
80325
79905
|
}
|
|
80326
79906
|
throw new Error("media_redirect_rejected");
|
|
@@ -80526,13 +80106,13 @@ async function reconcileSiteExtractSettlements(limit = 25) {
|
|
|
80526
80106
|
}
|
|
80527
80107
|
|
|
80528
80108
|
// src/api/page-diff.ts
|
|
80529
|
-
import { createHash as
|
|
80109
|
+
import { createHash as createHash98 } from "crypto";
|
|
80530
80110
|
import { diffLines } from "diff";
|
|
80531
80111
|
var MAX_SNAPSHOT_CONTENT_CHARS = 25e4;
|
|
80532
80112
|
var MAX_DIFF_HUNKS = 200;
|
|
80533
80113
|
var MAX_DIFF_LINES_PER_RESPONSE = 2e3;
|
|
80534
80114
|
function sha256Hex(value) {
|
|
80535
|
-
return
|
|
80115
|
+
return createHash98("sha256").update(value).digest("hex");
|
|
80536
80116
|
}
|
|
80537
80117
|
function truncateForStorage(value, maxChars = MAX_SNAPSHOT_CONTENT_CHARS) {
|
|
80538
80118
|
if (value.length <= maxChars) return { value, truncated: false };
|
|
@@ -80646,10 +80226,10 @@ async function persistScrapeBody(user, opts) {
|
|
|
80646
80226
|
}
|
|
80647
80227
|
|
|
80648
80228
|
// src/api/scrape-image-sink.ts
|
|
80649
|
-
import { createHash as
|
|
80229
|
+
import { createHash as createHash99 } from "crypto";
|
|
80650
80230
|
var MAX_IMAGES_PER_SCRAPE = 25;
|
|
80651
80231
|
function idempotencyKey3(userId, vault, input) {
|
|
80652
|
-
return `scrape-image-${
|
|
80232
|
+
return `scrape-image-${createHash99("sha256").update(`${userId}\0${vault}\0${input.sourceKind}\0${input.sourceUrl}\0${input.imageUrl ?? ""}\0${input.imageBase64 ?? ""}`).digest("hex")}`;
|
|
80653
80233
|
}
|
|
80654
80234
|
async function persistScrapeImagesToMemory(user, inputs, vault) {
|
|
80655
80235
|
const selected = inputs.slice(0, MAX_IMAGES_PER_SCRAPE);
|
|
@@ -81121,7 +80701,7 @@ function inferredWaybackCapturedAt(content) {
|
|
|
81121
80701
|
}
|
|
81122
80702
|
|
|
81123
80703
|
// src/api/connection-memory-import.ts
|
|
81124
|
-
import { createHash as
|
|
80704
|
+
import { createHash as createHash100 } from "crypto";
|
|
81125
80705
|
var CONNECTION_MEMORY_IMPORT_MAX_ARGS_BYTES = 64 * 1024;
|
|
81126
80706
|
var CONNECTION_MEMORY_IMPORT_MAX_RESULT_BYTES = 1e6;
|
|
81127
80707
|
var CONNECTION_MEMORY_IMPORT_MAX_STRING_CHARS = 256e3;
|
|
@@ -81151,7 +80731,7 @@ function canonicalJson16(value) {
|
|
|
81151
80731
|
return JSON.stringify(value);
|
|
81152
80732
|
}
|
|
81153
80733
|
function sha2562(value) {
|
|
81154
|
-
return
|
|
80734
|
+
return createHash100("sha256").update(value).digest("hex");
|
|
81155
80735
|
}
|
|
81156
80736
|
function sensitiveKey(key3) {
|
|
81157
80737
|
const normalized = key3.toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
@@ -81420,7 +81000,7 @@ async function cleanupExpiredScrapeBlobs(maxAgeMs = SCRAPE_BLOB_TTL_MS) {
|
|
|
81420
81000
|
}
|
|
81421
81001
|
|
|
81422
81002
|
// src/api/site-export-reader.ts
|
|
81423
|
-
import { createHash as
|
|
81003
|
+
import { createHash as createHash101 } from "crypto";
|
|
81424
81004
|
var SiteExportFormatUnavailableError = class extends Error {
|
|
81425
81005
|
constructor(format) {
|
|
81426
81006
|
super(`The ${format} representation was not retained for this export page.`);
|
|
@@ -81430,7 +81010,7 @@ var SiteExportFormatUnavailableError = class extends Error {
|
|
|
81430
81010
|
format;
|
|
81431
81011
|
};
|
|
81432
81012
|
function sha2563(value) {
|
|
81433
|
-
return
|
|
81013
|
+
return createHash101("sha256").update(value).digest("hex");
|
|
81434
81014
|
}
|
|
81435
81015
|
function publicPageRecord(page3) {
|
|
81436
81016
|
const { bodyMarkdown: _body, contentRef: _contentRef, discoveryLinks: _discovery, ...metadata } = page3;
|
|
@@ -81540,7 +81120,7 @@ async function readOwnedSiteExportImage(input) {
|
|
|
81540
81120
|
}
|
|
81541
81121
|
|
|
81542
81122
|
// src/api/search-console-table-export.ts
|
|
81543
|
-
import { randomUUID as
|
|
81123
|
+
import { randomUUID as randomUUID67 } from "crypto";
|
|
81544
81124
|
var SEARCH_CONSOLE_TABLE_EXPORT_MAX_ROWS = 5e4;
|
|
81545
81125
|
var SEARCH_CONSOLE_TABLE_EXPORT_PAGE_SIZE = 2e3;
|
|
81546
81126
|
var SEARCH_CONSOLE_TABLE_EXPORT_MAX_BYTES = 50 * 1024 * 1024;
|
|
@@ -81640,7 +81220,7 @@ async function exportSearchConsoleTableData(args) {
|
|
|
81640
81220
|
offset += rows.length;
|
|
81641
81221
|
if (stoppedForBytes || rows.length < limit || offset >= matchedRows) break;
|
|
81642
81222
|
}
|
|
81643
|
-
const exportId =
|
|
81223
|
+
const exportId = randomUUID67();
|
|
81644
81224
|
const artifact = await args.writeArtifact({
|
|
81645
81225
|
ownerId: args.ownerId,
|
|
81646
81226
|
exportId,
|
|
@@ -81995,7 +81575,7 @@ async function dbUsage(identity, plan) {
|
|
|
81995
81575
|
}
|
|
81996
81576
|
|
|
81997
81577
|
// src/api/resend-control.ts
|
|
81998
|
-
import { createHash as
|
|
81578
|
+
import { createHash as createHash102 } from "crypto";
|
|
81999
81579
|
var DEFAULT_CONNECTION_CONTROL_URL = "https://mcp-scraper-scheduler.vercel.app";
|
|
82000
81580
|
var RESEND_PROVIDER_CONFIG_KEY = "resend";
|
|
82001
81581
|
var RESEND_LOGO_URL = "https://cdn.resend.com/brand/resend-icon-black.svg";
|
|
@@ -82254,7 +81834,7 @@ async function callResendRead(identity, connectionId, tool, args) {
|
|
|
82254
81834
|
return isRecord9(data) ? data.result ?? data : data;
|
|
82255
81835
|
}
|
|
82256
81836
|
async function callResendAction(identity, connectionId, tool, input, idempotencyKey4) {
|
|
82257
|
-
const requestId = `main-resend-action:${
|
|
81837
|
+
const requestId = `main-resend-action:${createHash102("sha256").update(identity).update("\0").update(idempotencyKey4.trim()).digest("hex")}`;
|
|
82258
81838
|
const body3 = await controlRequest2("/api/internal/resend/actions/call", {
|
|
82259
81839
|
method: "POST",
|
|
82260
81840
|
headers: { "x-request-id": requestId },
|
|
@@ -82604,6 +82184,10 @@ app.post("/account/delete", requireAllowedOrigin, sessionAuth, async (c) => {
|
|
|
82604
82184
|
}
|
|
82605
82185
|
}
|
|
82606
82186
|
}
|
|
82187
|
+
await setSubscriptionTier(user.id, null, 0, null);
|
|
82188
|
+
await setConcurrencyPackQuantity(user.id, 0);
|
|
82189
|
+
await setConcurrencySubId(user.id, null);
|
|
82190
|
+
await setMemoryPlan(user.id, "free", null);
|
|
82607
82191
|
await deactivateUser(user.id);
|
|
82608
82192
|
deleteCookie(c, "session", { path: "/", secure: secureCookies2, sameSite: "Strict" });
|
|
82609
82193
|
return c.json({ ok: true });
|
|
@@ -83063,6 +82647,15 @@ function scheduleConnectionError(c, err, fallback) {
|
|
|
83063
82647
|
retryable: err.retryable
|
|
83064
82648
|
}, err.status);
|
|
83065
82649
|
}
|
|
82650
|
+
if (err instanceof MainNangoTransportError) {
|
|
82651
|
+
return c.json({
|
|
82652
|
+
ok: false,
|
|
82653
|
+
error: err.message,
|
|
82654
|
+
code: err.code,
|
|
82655
|
+
errorCode: err.code,
|
|
82656
|
+
retryable: err.retryable
|
|
82657
|
+
}, err.status);
|
|
82658
|
+
}
|
|
83066
82659
|
if (err instanceof ResendControlError) return c.json({ ok: false, error: err.message }, err.status);
|
|
83067
82660
|
console.error("[schedule-connections]", err instanceof Error ? err.message : String(err));
|
|
83068
82661
|
return c.json({ ok: false, error: fallback }, 502);
|
|
@@ -83120,7 +82713,7 @@ async function combinedConnectionCatalog() {
|
|
|
83120
82713
|
}
|
|
83121
82714
|
if (nango.status === "rejected" && resend.status === "rejected") throw nango.reason;
|
|
83122
82715
|
return [
|
|
83123
|
-
...nango.status === "fulfilled" ? nango.value : [],
|
|
82716
|
+
...nango.status === "fulfilled" ? nango.value.filter((entry) => !isWithdrawnNangoProvider(entry.providerConfigKey)) : [],
|
|
83124
82717
|
...resend.status === "fulfilled" ? resend.value : []
|
|
83125
82718
|
];
|
|
83126
82719
|
}
|
|
@@ -83137,7 +82730,7 @@ async function combinedConnections(identity) {
|
|
|
83137
82730
|
}
|
|
83138
82731
|
if (nango.status === "rejected" && resend.status === "rejected") throw nango.reason;
|
|
83139
82732
|
return [
|
|
83140
|
-
...nango.status === "fulfilled" ? nango.value.map((connection) => ({ ...connection, transport: "nango", adminBlockedTools: [] })) : [],
|
|
82733
|
+
...nango.status === "fulfilled" ? nango.value.filter((connection) => !isWithdrawnNangoProvider(connection.providerConfigKey)).map((connection) => ({ ...connection, transport: "nango", adminBlockedTools: [] })) : [],
|
|
83141
82734
|
...resend.status === "fulfilled" ? resend.value.map((connection) => ({
|
|
83142
82735
|
...connection,
|
|
83143
82736
|
toolCapabilities: [
|
|
@@ -83278,6 +82871,7 @@ app.post("/schedule-connections/session", auth5, requireIntegrationsTier, async
|
|
|
83278
82871
|
const providerConfigKey = providerConfigKeyFrom(body3.providerConfigKey);
|
|
83279
82872
|
if (!providerConfigKey) return c.json({ ok: false, error: "providerConfigKey is required." }, 400);
|
|
83280
82873
|
try {
|
|
82874
|
+
assertNangoProviderAvailable(providerConfigKey);
|
|
83281
82875
|
if (providerConfigKey !== "resend") {
|
|
83282
82876
|
await reconcileConnectedAccountBilling(user, await getNangoConnections(user.email, { summaryOnly: true }));
|
|
83283
82877
|
}
|
|
@@ -83456,7 +83050,7 @@ app.post("/schedule-connections/actions/gmail/send-message", auth5, requireInteg
|
|
|
83456
83050
|
}
|
|
83457
83051
|
try {
|
|
83458
83052
|
const result3 = await directGmailService.sendMessage({
|
|
83459
|
-
ownerId:
|
|
83053
|
+
ownerId: createHash103("sha256").update(user.api_key).digest("hex").slice(0, 24),
|
|
83460
83054
|
providerIdentity: user.email,
|
|
83461
83055
|
connectionId,
|
|
83462
83056
|
to: body3.to,
|
|
@@ -84218,7 +83812,7 @@ app.post("/harvest", auth5, async (c) => {
|
|
|
84218
83812
|
if (!harvestOk) return c.json(insufficientBalanceResponse(harvestBal, harvestCost), 402);
|
|
84219
83813
|
jobId2 = await createJob(user.id, options.query, { ...options, billingHoldMc: harvestCost }, body3.callback_url);
|
|
84220
83814
|
} else {
|
|
84221
|
-
jobId2 = derivedJobId ??
|
|
83815
|
+
jobId2 = derivedJobId ?? randomUUID68();
|
|
84222
83816
|
const billingDebitKey = `paa-harvest:${jobId2}:hold`;
|
|
84223
83817
|
const description = `PAA harvest: ${options.query}`.slice(0, 500);
|
|
84224
83818
|
const hold2 = await debitMcIdempotent(
|
|
@@ -84304,11 +83898,11 @@ app.post("/harvest/sync", auth5, async (c) => {
|
|
|
84304
83898
|
return c.json({ error: "Idempotency-Key must contain 1-200 characters.", errorCode: "invalid_idempotency_key", retryable: false }, 400);
|
|
84305
83899
|
}
|
|
84306
83900
|
derivedJobId = `sync_${sha256Hex(`${user.id}\0${trimmedKey}`).slice(0, 24)}`;
|
|
84307
|
-
const
|
|
83901
|
+
const fingerprint5 = JSON.stringify(options);
|
|
84308
83902
|
const existing = await getJob(derivedJobId, user.id);
|
|
84309
83903
|
if (existing) {
|
|
84310
83904
|
const existingFingerprint = JSON.stringify(existing.options);
|
|
84311
|
-
if (existingFingerprint !==
|
|
83905
|
+
if (existingFingerprint !== fingerprint5) {
|
|
84312
83906
|
return c.json({ error: "Idempotency-Key was already used for a different harvest_paa/search_serp call.", errorCode: "idempotency_conflict", retryable: false }, 409);
|
|
84313
83907
|
}
|
|
84314
83908
|
if (existing.status === "done") {
|
|
@@ -84527,11 +84121,11 @@ app.post("/extract-url", auth5, async (c) => {
|
|
|
84527
84121
|
return c.json({ error: "Idempotency-Key must contain 1-200 characters.", errorCode: "invalid_idempotency_key", retryable: false }, 400);
|
|
84528
84122
|
}
|
|
84529
84123
|
derivedJobId = `exurl_${sha256Hex(`${user.id}\0${trimmedKey}`).slice(0, 24)}`;
|
|
84530
|
-
const
|
|
84124
|
+
const fingerprint5 = JSON.stringify(bodyResult.data);
|
|
84531
84125
|
const existing = await getJob(derivedJobId, user.id);
|
|
84532
84126
|
if (existing) {
|
|
84533
84127
|
const existingFingerprint = JSON.stringify(existing.options);
|
|
84534
|
-
if (existingFingerprint !==
|
|
84128
|
+
if (existingFingerprint !== fingerprint5) {
|
|
84535
84129
|
return c.json({ error: "Idempotency-Key was already used for a different extract_url call.", errorCode: "idempotency_conflict", retryable: false }, 409);
|
|
84536
84130
|
}
|
|
84537
84131
|
if (existing.status === "done") {
|
|
@@ -85773,7 +85367,7 @@ app.get("/cron/tick", async (c) => {
|
|
|
85773
85367
|
return c.json({ error: "Unauthorized" }, 401);
|
|
85774
85368
|
}
|
|
85775
85369
|
const startedAt = Date.now();
|
|
85776
|
-
const { drainQueue } = await import("./worker-
|
|
85370
|
+
const { drainQueue } = await import("./worker-5A375BGN.js");
|
|
85777
85371
|
const budget = { maxJobs: 10, deadlineMs: startedAt + CRON_TICK_DRAIN_BUDGET_MS };
|
|
85778
85372
|
const origin = `${new URL(c.req.url).protocol}//${new URL(c.req.url).host}`;
|
|
85779
85373
|
const unfinished = [];
|
|
@@ -85897,8 +85491,8 @@ app.post("/api/internal/extract-refinalize/:id", async (c) => {
|
|
|
85897
85491
|
finishExtractJob: finishExtractJob2,
|
|
85898
85492
|
terminalExtractJobStatus: terminalExtractJobStatus2,
|
|
85899
85493
|
extractJobLimitInfo: extractJobLimitInfo2
|
|
85900
|
-
} = await import("./site-extract-repository-
|
|
85901
|
-
const { assembleExtractArtifacts } = await import("./extract-bundle-
|
|
85494
|
+
} = await import("./site-extract-repository-DWU52BRQ.js");
|
|
85495
|
+
const { assembleExtractArtifacts } = await import("./extract-bundle-NSMGHEG6.js");
|
|
85902
85496
|
const existing = await getExtractJob2(jobId2);
|
|
85903
85497
|
if (!existing) return c.json({ error: "job not found" }, 404);
|
|
85904
85498
|
if (existing.status !== "failed") {
|
|
@@ -85925,7 +85519,7 @@ app.post("/api/internal/extract-refinalize/:id", async (c) => {
|
|
|
85925
85519
|
if (!updated) return c.json({ error: "job state changed during re-finalization" }, 409);
|
|
85926
85520
|
let settlement = "already_settled_or_refunded";
|
|
85927
85521
|
if (job.billedMc == null && job.userId != null) {
|
|
85928
|
-
const { settleExtractJob: settleExtractJob3, countSuccessfulPages: countSuccessfulPages2 } = await import("./site-extract-repository-
|
|
85522
|
+
const { settleExtractJob: settleExtractJob3, countSuccessfulPages: countSuccessfulPages2 } = await import("./site-extract-repository-DWU52BRQ.js");
|
|
85929
85523
|
const heldMc = Number(job.options.heldMc ?? 0);
|
|
85930
85524
|
const successful = await countSuccessfulPages2(jobId2);
|
|
85931
85525
|
const usedMc = Math.min(successful * MC_COSTS.page_scrape, heldMc);
|