mcp-scraper 0.48.0 → 0.49.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/README.md +2 -2
- package/dist/bin/api-server.cjs +647 -195
- package/dist/bin/api-server.cjs.map +1 -1
- package/dist/bin/api-server.js +1 -1
- package/dist/bin/mcp-scraper-cli.cjs +1 -1
- package/dist/bin/mcp-scraper-cli.cjs.map +1 -1
- package/dist/bin/mcp-scraper-cli.js +1 -1
- package/dist/bin/mcp-scraper-install.cjs +3 -3
- package/dist/bin/mcp-scraper-install.cjs.map +1 -1
- package/dist/bin/mcp-scraper-install.js +2 -2
- package/dist/bin/mcp-stdio-server.cjs +46 -3
- package/dist/bin/mcp-stdio-server.cjs.map +1 -1
- package/dist/bin/mcp-stdio-server.js +3 -3
- package/dist/{chunk-PTABZABJ.js → chunk-64WBUDPC.js} +46 -2
- package/dist/chunk-64WBUDPC.js.map +1 -0
- package/dist/{chunk-QAH7WMYC.js → chunk-QH63IZTX.js} +3 -3
- package/dist/chunk-QH63IZTX.js.map +1 -0
- package/dist/chunk-XLEDHV3J.js +7 -0
- package/dist/chunk-XLEDHV3J.js.map +1 -0
- package/dist/{server-EVTCL3KB.js → server-JE7SLZLJ.js} +521 -117
- package/dist/server-JE7SLZLJ.js.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-IAXQIHNS.js +0 -7
- package/dist/chunk-IAXQIHNS.js.map +0 -1
- package/dist/chunk-PTABZABJ.js.map +0 -1
- package/dist/chunk-QAH7WMYC.js.map +0 -1
- package/dist/server-EVTCL3KB.js.map +0 -1
|
@@ -102,6 +102,7 @@ import {
|
|
|
102
102
|
import {
|
|
103
103
|
ApiErrorResponseSchema,
|
|
104
104
|
ArtifactTemplatePresetKeySchema,
|
|
105
|
+
CommonsClaimInputSchema,
|
|
105
106
|
CommonsClaimPublicationInputSchema,
|
|
106
107
|
CommonsPreparePublicationInputSchema,
|
|
107
108
|
CommonsPublishEditorialInputSchema,
|
|
@@ -155,7 +156,7 @@ import {
|
|
|
155
156
|
resolveDeploymentProfile,
|
|
156
157
|
resolveLocalSourcebookSchemaType,
|
|
157
158
|
transcribeMediaUrl
|
|
158
|
-
} from "./chunk-
|
|
159
|
+
} from "./chunk-64WBUDPC.js";
|
|
159
160
|
import {
|
|
160
161
|
auditImageUrls,
|
|
161
162
|
auditImages,
|
|
@@ -211,7 +212,7 @@ import {
|
|
|
211
212
|
} from "./chunk-3ZUBQQPQ.js";
|
|
212
213
|
import {
|
|
213
214
|
PACKAGE_VERSION
|
|
214
|
-
} from "./chunk-
|
|
215
|
+
} from "./chunk-XLEDHV3J.js";
|
|
215
216
|
import {
|
|
216
217
|
abandonExtractSettlement,
|
|
217
218
|
countSuccessfulPages,
|
|
@@ -30873,8 +30874,187 @@ import { Hono as Hono31 } from "hono";
|
|
|
30873
30874
|
import { z as z32 } from "zod";
|
|
30874
30875
|
|
|
30875
30876
|
// src/api/commons-repository.ts
|
|
30876
|
-
import { createHash as
|
|
30877
|
-
|
|
30877
|
+
import { createHash as createHash13, randomUUID as randomUUID15 } from "crypto";
|
|
30878
|
+
|
|
30879
|
+
// src/api/commons-linksets.ts
|
|
30880
|
+
import { createHash as createHash12 } from "crypto";
|
|
30881
|
+
var COMMONS_LINKSET_MEDIA_TYPE = "application/linkset+json";
|
|
30882
|
+
var COMMONS_RELATIONSHIP_PROFILE = "https://mcpscraper.dev/commons/profiles/relationships/v1";
|
|
30883
|
+
var REGISTERED_RELATIONS = /* @__PURE__ */ new Set([
|
|
30884
|
+
"about",
|
|
30885
|
+
"alternate",
|
|
30886
|
+
"author",
|
|
30887
|
+
"canonical",
|
|
30888
|
+
"cite-as",
|
|
30889
|
+
"collection",
|
|
30890
|
+
"contents",
|
|
30891
|
+
"copyright",
|
|
30892
|
+
"describedby",
|
|
30893
|
+
"describes",
|
|
30894
|
+
"first",
|
|
30895
|
+
"glossary",
|
|
30896
|
+
"help",
|
|
30897
|
+
"icon",
|
|
30898
|
+
"index",
|
|
30899
|
+
"item",
|
|
30900
|
+
"last",
|
|
30901
|
+
"latest-version",
|
|
30902
|
+
"license",
|
|
30903
|
+
"memento",
|
|
30904
|
+
"next",
|
|
30905
|
+
"original",
|
|
30906
|
+
"predecessor-version",
|
|
30907
|
+
"prev",
|
|
30908
|
+
"related",
|
|
30909
|
+
"replies",
|
|
30910
|
+
"service-desc",
|
|
30911
|
+
"service-doc",
|
|
30912
|
+
"successor-version",
|
|
30913
|
+
"terms-of-service",
|
|
30914
|
+
"type",
|
|
30915
|
+
"via",
|
|
30916
|
+
"version-history"
|
|
30917
|
+
]);
|
|
30918
|
+
function normalizeCommonsClaims(input) {
|
|
30919
|
+
if (input === void 0) return void 0;
|
|
30920
|
+
if (!Array.isArray(input)) throw new Error("claims must be an array.");
|
|
30921
|
+
if (input.length > 300) throw new Error("claims must contain no more than 300 assertions.");
|
|
30922
|
+
const seen = /* @__PURE__ */ new Set();
|
|
30923
|
+
return input.map((claim, index) => {
|
|
30924
|
+
const predicate = String(claim.predicate ?? "").trim();
|
|
30925
|
+
if (!isSupportedPredicate(predicate)) {
|
|
30926
|
+
throw new Error(`claims[${index}].predicate must be a supported registered relation or an absolute HTTPS relation URI.`);
|
|
30927
|
+
}
|
|
30928
|
+
const objectEntityId = optionalText(claim.objectEntityId, 80);
|
|
30929
|
+
const objectUrl = optionalHttpsUrl(claim.objectUrl, `claims[${index}].objectUrl`);
|
|
30930
|
+
if ((objectEntityId ? 1 : 0) + (objectUrl ? 1 : 0) !== 1) {
|
|
30931
|
+
throw new Error(`claims[${index}] must provide exactly one of objectEntityId or objectUrl.`);
|
|
30932
|
+
}
|
|
30933
|
+
if (objectEntityId && !/^TPW-Q[A-Za-z0-9._-]+$/.test(objectEntityId)) {
|
|
30934
|
+
throw new Error(`claims[${index}].objectEntityId must be a Transparent Commons TPW-Q identifier.`);
|
|
30935
|
+
}
|
|
30936
|
+
const confidence = claim.confidence ?? 1;
|
|
30937
|
+
if (!Number.isFinite(confidence) || confidence < 0 || confidence > 1) {
|
|
30938
|
+
throw new Error(`claims[${index}].confidence must be between 0 and 1.`);
|
|
30939
|
+
}
|
|
30940
|
+
const key = `${predicate}\0${objectEntityId ?? objectUrl}`;
|
|
30941
|
+
if (seen.has(key)) throw new Error(`claims[${index}] duplicates another predicate and object pair.`);
|
|
30942
|
+
seen.add(key);
|
|
30943
|
+
return {
|
|
30944
|
+
predicate,
|
|
30945
|
+
predicateLabel: optionalText(claim.predicateLabel, 160),
|
|
30946
|
+
objectEntityId,
|
|
30947
|
+
objectUrl,
|
|
30948
|
+
title: optionalText(claim.title, 500),
|
|
30949
|
+
mediaType: optionalText(claim.mediaType, 160),
|
|
30950
|
+
hreflang: normalizeHreflang(claim.hreflang),
|
|
30951
|
+
qualifiers: normalizeScalarRecord(claim.qualifiers),
|
|
30952
|
+
references: normalizeReferences(claim.references),
|
|
30953
|
+
rank: claim.rank ?? "normal",
|
|
30954
|
+
confidence,
|
|
30955
|
+
confidenceReason: optionalText(claim.confidenceReason, 1e3),
|
|
30956
|
+
disputeState: claim.disputeState ?? "undisputed",
|
|
30957
|
+
validFrom: optionalDate(claim.validFrom, `claims[${index}].validFrom`),
|
|
30958
|
+
validTo: optionalDate(claim.validTo, `claims[${index}].validTo`),
|
|
30959
|
+
asOf: optionalDate(claim.asOf, `claims[${index}].asOf`),
|
|
30960
|
+
sourceFamily: claim.sourceFamily ?? "unknown"
|
|
30961
|
+
};
|
|
30962
|
+
});
|
|
30963
|
+
}
|
|
30964
|
+
function claimIsPublic(claim, now = /* @__PURE__ */ new Date()) {
|
|
30965
|
+
if (claim.reviewState !== "approved" || claim.rank === "deprecated") return false;
|
|
30966
|
+
if (!["undisputed", "attributed"].includes(claim.disputeState ?? "undisputed")) return false;
|
|
30967
|
+
const timestamp = now.getTime();
|
|
30968
|
+
if (claim.validFrom && Date.parse(claim.validFrom) > timestamp) return false;
|
|
30969
|
+
if (claim.validTo && Date.parse(claim.validTo) < timestamp) return false;
|
|
30970
|
+
return true;
|
|
30971
|
+
}
|
|
30972
|
+
function buildCommonsLinkset(entity, claims) {
|
|
30973
|
+
const publicUrl = `${commonsPublicWikiBaseUrl()}/wiki/${encodeURIComponent(entity.slug)}`;
|
|
30974
|
+
const linksetUrl = commonsLinksetUrl(entity.id);
|
|
30975
|
+
const context = { anchor: publicUrl };
|
|
30976
|
+
const publicClaims = claims.filter((claim) => claimIsPublic(claim)).sort((a, b) => a.predicate.localeCompare(b.predicate) || a.href.localeCompare(b.href) || a.id.localeCompare(b.id));
|
|
30977
|
+
for (const claim of publicClaims) {
|
|
30978
|
+
const targets = context[claim.predicate] ?? [];
|
|
30979
|
+
const target = { href: claim.href };
|
|
30980
|
+
if (claim.mediaType) target.type = claim.mediaType;
|
|
30981
|
+
if (claim.hreflang) target.hreflang = claim.hreflang;
|
|
30982
|
+
if (claim.title) target.title = claim.title;
|
|
30983
|
+
targets.push(target);
|
|
30984
|
+
context[claim.predicate] = targets;
|
|
30985
|
+
}
|
|
30986
|
+
const document2 = { linkset: [context] };
|
|
30987
|
+
const etag = `"${createHash12("sha256").update(JSON.stringify(document2)).digest("hex")}"`;
|
|
30988
|
+
return { document: document2, etag, publicUrl, linksetUrl, profile: COMMONS_RELATIONSHIP_PROFILE };
|
|
30989
|
+
}
|
|
30990
|
+
function commonsLinksetDiscoveryHeader(idOrSlug) {
|
|
30991
|
+
const url = commonsLinksetUrl(idOrSlug);
|
|
30992
|
+
return `<${url}>; rel="linkset"; type="${COMMONS_LINKSET_MEDIA_TYPE}"; profile="${COMMONS_RELATIONSHIP_PROFILE}"`;
|
|
30993
|
+
}
|
|
30994
|
+
function commonsLinksetUrl(idOrSlug) {
|
|
30995
|
+
const base = (process.env.APP_URL?.trim() || "https://mcpscraper.dev").replace(/\/+$/, "");
|
|
30996
|
+
return `${base}/commons/entities/${encodeURIComponent(idOrSlug)}/linkset`;
|
|
30997
|
+
}
|
|
30998
|
+
function commonsClaimIdentityKey(claim) {
|
|
30999
|
+
return `${claim.predicate}\0${claim.objectEntityId ?? claim.objectUrl ?? ""}`;
|
|
31000
|
+
}
|
|
31001
|
+
function commonsPublicWikiBaseUrl() {
|
|
31002
|
+
return (process.env.TRANSPARENT_COMMONS_PUBLIC_BASE_URL?.trim() || "https://transparent-commons.cc").replace(/\/+$/, "");
|
|
31003
|
+
}
|
|
31004
|
+
function isSupportedPredicate(value) {
|
|
31005
|
+
if (REGISTERED_RELATIONS.has(value)) return true;
|
|
31006
|
+
try {
|
|
31007
|
+
const url = new URL(value);
|
|
31008
|
+
return url.protocol === "https:" && Boolean(url.hostname);
|
|
31009
|
+
} catch {
|
|
31010
|
+
return false;
|
|
31011
|
+
}
|
|
31012
|
+
}
|
|
31013
|
+
function optionalText(value, max) {
|
|
31014
|
+
const text2 = String(value ?? "").trim();
|
|
31015
|
+
return text2 ? text2.slice(0, max) : void 0;
|
|
31016
|
+
}
|
|
31017
|
+
function optionalHttpsUrl(value, field) {
|
|
31018
|
+
const text2 = optionalText(value, 2e3);
|
|
31019
|
+
if (!text2) return void 0;
|
|
31020
|
+
try {
|
|
31021
|
+
const url = new URL(text2);
|
|
31022
|
+
if (url.protocol !== "https:") throw new Error();
|
|
31023
|
+
url.hash = "";
|
|
31024
|
+
return url.href;
|
|
31025
|
+
} catch {
|
|
31026
|
+
throw new Error(`${field} must be an absolute HTTPS URL.`);
|
|
31027
|
+
}
|
|
31028
|
+
}
|
|
31029
|
+
function optionalDate(value, field) {
|
|
31030
|
+
const text2 = optionalText(value, 80);
|
|
31031
|
+
if (!text2) return void 0;
|
|
31032
|
+
const timestamp = Date.parse(text2);
|
|
31033
|
+
if (!Number.isFinite(timestamp)) throw new Error(`${field} must be an ISO-compatible date.`);
|
|
31034
|
+
return new Date(timestamp).toISOString();
|
|
31035
|
+
}
|
|
31036
|
+
function normalizeScalarRecord(value) {
|
|
31037
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
31038
|
+
return Object.fromEntries(Object.entries(value).slice(0, 50).map(([key, item]) => [key.slice(0, 120), item]));
|
|
31039
|
+
}
|
|
31040
|
+
function normalizeReferences(value) {
|
|
31041
|
+
if (!Array.isArray(value)) return void 0;
|
|
31042
|
+
return value.slice(0, 50).map((reference) => ({
|
|
31043
|
+
title: String(reference.title ?? "").trim().slice(0, 240),
|
|
31044
|
+
url: optionalHttpsUrl(reference.url, "claim reference URL"),
|
|
31045
|
+
source: optionalText(reference.source, 240),
|
|
31046
|
+
note: optionalText(reference.note, 1e3),
|
|
31047
|
+
accessedAt: optionalDate(reference.accessedAt, "claim reference accessedAt")
|
|
31048
|
+
})).filter((reference) => reference.title);
|
|
31049
|
+
}
|
|
31050
|
+
function normalizeHreflang(value) {
|
|
31051
|
+
if (!Array.isArray(value)) return void 0;
|
|
31052
|
+
const languages = [...new Set(value.map((item) => optionalText(item, 80)).filter((item) => Boolean(item)))];
|
|
31053
|
+
return languages.length ? languages : void 0;
|
|
31054
|
+
}
|
|
31055
|
+
|
|
31056
|
+
// src/api/commons-repository.ts
|
|
31057
|
+
var COMMONS_SCHEMA_VERSION = "2026-08-05.1";
|
|
30878
31058
|
var DEFAULT_COMMONS_BASE_URL = "https://transparent-commons.cc";
|
|
30879
31059
|
var DEFAULT_ENTITY_TYPE = "PublicArticle";
|
|
30880
31060
|
var COMMONS_ENTITY_PROFILES = {
|
|
@@ -31071,6 +31251,42 @@ async function ensureCommonsSchema() {
|
|
|
31071
31251
|
{ sql: `CREATE INDEX IF NOT EXISTS commons_entities_status_updated ON commons_entities(status, updated_at DESC)`, args: [] },
|
|
31072
31252
|
{ sql: `CREATE INDEX IF NOT EXISTS commons_entities_type_updated ON commons_entities(entity_type, updated_at DESC)`, args: [] },
|
|
31073
31253
|
{ sql: `CREATE INDEX IF NOT EXISTS commons_entities_source_domain ON commons_entities(source_json)`, args: [] },
|
|
31254
|
+
{
|
|
31255
|
+
sql: `
|
|
31256
|
+
CREATE TABLE IF NOT EXISTS commons_claims (
|
|
31257
|
+
id TEXT PRIMARY KEY,
|
|
31258
|
+
subject_entity_id TEXT NOT NULL REFERENCES commons_entities(id),
|
|
31259
|
+
predicate TEXT NOT NULL,
|
|
31260
|
+
predicate_label TEXT,
|
|
31261
|
+
object_entity_id TEXT,
|
|
31262
|
+
object_url TEXT,
|
|
31263
|
+
title TEXT,
|
|
31264
|
+
media_type TEXT,
|
|
31265
|
+
hreflang TEXT,
|
|
31266
|
+
qualifiers_json TEXT NOT NULL DEFAULT '{}',
|
|
31267
|
+
references_json TEXT NOT NULL DEFAULT '[]',
|
|
31268
|
+
rank TEXT NOT NULL DEFAULT 'normal',
|
|
31269
|
+
confidence REAL NOT NULL DEFAULT 1,
|
|
31270
|
+
confidence_reason TEXT,
|
|
31271
|
+
dispute_state TEXT NOT NULL DEFAULT 'undisputed',
|
|
31272
|
+
valid_from TEXT,
|
|
31273
|
+
valid_to TEXT,
|
|
31274
|
+
as_of TEXT,
|
|
31275
|
+
source_family TEXT NOT NULL DEFAULT 'unknown',
|
|
31276
|
+
review_state TEXT NOT NULL DEFAULT 'approved',
|
|
31277
|
+
proposal_id TEXT NOT NULL REFERENCES commons_proposals(id),
|
|
31278
|
+
created_by_user_id INTEGER,
|
|
31279
|
+
updated_by_user_id INTEGER,
|
|
31280
|
+
created_at TEXT NOT NULL,
|
|
31281
|
+
updated_at TEXT NOT NULL,
|
|
31282
|
+
CHECK ((object_entity_id IS NOT NULL) != (object_url IS NOT NULL)),
|
|
31283
|
+
UNIQUE(subject_entity_id, predicate, object_entity_id, object_url)
|
|
31284
|
+
)
|
|
31285
|
+
`,
|
|
31286
|
+
args: []
|
|
31287
|
+
},
|
|
31288
|
+
{ sql: `CREATE INDEX IF NOT EXISTS commons_claims_subject_predicate ON commons_claims(subject_entity_id, predicate)`, args: [] },
|
|
31289
|
+
{ sql: `CREATE INDEX IF NOT EXISTS commons_claims_object_entity ON commons_claims(object_entity_id)`, args: [] },
|
|
31074
31290
|
{
|
|
31075
31291
|
sql: `
|
|
31076
31292
|
CREATE TABLE IF NOT EXISTS commons_proposals (
|
|
@@ -31231,8 +31447,15 @@ async function searchCommonsEntities(filters = {}, userId) {
|
|
|
31231
31447
|
args.push(jsonLikeValue(keyword));
|
|
31232
31448
|
}
|
|
31233
31449
|
if (mergedFilters.relatedEntityId) {
|
|
31234
|
-
clauses.push(
|
|
31235
|
-
|
|
31450
|
+
clauses.push(`(
|
|
31451
|
+
related_entities_json LIKE ?
|
|
31452
|
+
OR EXISTS (
|
|
31453
|
+
SELECT 1 FROM commons_claims
|
|
31454
|
+
WHERE commons_claims.subject_entity_id = commons_entities.id
|
|
31455
|
+
AND commons_claims.object_entity_id = ?
|
|
31456
|
+
)
|
|
31457
|
+
)`);
|
|
31458
|
+
args.push(jsonLikeValue(mergedFilters.relatedEntityId), mergedFilters.relatedEntityId);
|
|
31236
31459
|
}
|
|
31237
31460
|
if (mergedFilters.trailId) {
|
|
31238
31461
|
clauses.push("related_entities_json LIKE ?");
|
|
@@ -31254,8 +31477,16 @@ async function searchCommonsEntities(filters = {}, userId) {
|
|
|
31254
31477
|
}
|
|
31255
31478
|
const terms = tokenize(mergedFilters.query);
|
|
31256
31479
|
for (const term of terms) {
|
|
31257
|
-
clauses.push(
|
|
31258
|
-
|
|
31480
|
+
clauses.push(`(
|
|
31481
|
+
search_text LIKE ?
|
|
31482
|
+
OR EXISTS (
|
|
31483
|
+
SELECT 1 FROM commons_claims
|
|
31484
|
+
WHERE commons_claims.subject_entity_id = commons_entities.id
|
|
31485
|
+
AND (commons_claims.predicate LIKE ? OR commons_claims.predicate_label LIKE ? OR commons_claims.title LIKE ? OR commons_claims.object_url LIKE ?)
|
|
31486
|
+
)
|
|
31487
|
+
)`);
|
|
31488
|
+
const pattern = `%${escapeLike(term)}%`;
|
|
31489
|
+
args.push(pattern, pattern, pattern, pattern, pattern);
|
|
31259
31490
|
}
|
|
31260
31491
|
args.push(limit, offset);
|
|
31261
31492
|
const result = await getDb().execute({
|
|
@@ -31277,9 +31508,9 @@ async function searchCommonsEntities(filters = {}, userId) {
|
|
|
31277
31508
|
}
|
|
31278
31509
|
async function prepareCommonsEntity(input, user) {
|
|
31279
31510
|
await ensureCommonsSchema();
|
|
31280
|
-
const title =
|
|
31511
|
+
const title = optionalText2(input.title, 180) ?? "";
|
|
31281
31512
|
const slug2 = normalizeSlug(input.slug || title);
|
|
31282
|
-
const schemaOrgType =
|
|
31513
|
+
const schemaOrgType = optionalText2(input.schemaOrgType, 80);
|
|
31283
31514
|
const contract = commonsEntityProfileFor(input.entityType, schemaOrgType);
|
|
31284
31515
|
const entityType = contract.entityType;
|
|
31285
31516
|
const bodyMarkdown = safeCandidateBody(input.bodyMarkdown, input.contentSections);
|
|
@@ -31337,8 +31568,8 @@ async function validateCommonsEntity(input, user) {
|
|
|
31337
31568
|
await ensureCommonsSchema();
|
|
31338
31569
|
const errors = [];
|
|
31339
31570
|
const warnings = [];
|
|
31340
|
-
const title =
|
|
31341
|
-
const description =
|
|
31571
|
+
const title = optionalText2(input.title, 180);
|
|
31572
|
+
const description = optionalText2(input.description, 600);
|
|
31342
31573
|
const slug2 = normalizeSlug(input.slug || title || "");
|
|
31343
31574
|
const contract = commonsEntityProfileFor(input.entityType, input.seo?.schemaOrgType);
|
|
31344
31575
|
const source = normalizeSource(input.source);
|
|
@@ -31353,6 +31584,11 @@ async function validateCommonsEntity(input, user) {
|
|
|
31353
31584
|
maxCandidates: 8
|
|
31354
31585
|
});
|
|
31355
31586
|
const existing = slug2 || input.entityId ? await findEntityBySlugOrIdAnyStatus(slug2, input.entityId) : null;
|
|
31587
|
+
try {
|
|
31588
|
+
normalizeCommonsClaims(input.claims);
|
|
31589
|
+
} catch (error) {
|
|
31590
|
+
errors.push(error instanceof Error ? error.message : "Claims are invalid.");
|
|
31591
|
+
}
|
|
31356
31592
|
if (!title || title.length < 3) errors.push("title must be at least 3 characters.");
|
|
31357
31593
|
if (!description || description.length < 8) errors.push("description must be at least 8 characters.");
|
|
31358
31594
|
if (!slug2) errors.push("A Commons entity needs a URL slug.");
|
|
@@ -31442,6 +31678,7 @@ async function submitCommonsEntity(input, user) {
|
|
|
31442
31678
|
};
|
|
31443
31679
|
}
|
|
31444
31680
|
const existing = await findEntityBySlugOrIdAnyStatus(normalized.slug, normalized.entityId);
|
|
31681
|
+
const existingClaims = existing && normalized.claims !== void 0 ? await getCommonsClaimsByEntityId(existing.id) : [];
|
|
31445
31682
|
const safety = evaluatePublishSafety(normalized, existing);
|
|
31446
31683
|
const shouldApply = safety.safe && normalized.reviewPolicy !== "always_review";
|
|
31447
31684
|
const proposalId = `commons-proposal-${randomUUID15()}`;
|
|
@@ -31486,6 +31723,10 @@ async function submitCommonsEntity(input, user) {
|
|
|
31486
31723
|
];
|
|
31487
31724
|
if (nextEntity) {
|
|
31488
31725
|
batch.push(entityUpsertStatement(nextEntity, existing));
|
|
31726
|
+
if (normalized.claims !== void 0) {
|
|
31727
|
+
batch.push({ sql: "DELETE FROM commons_claims WHERE subject_entity_id = ?", args: [nextEntity.id] });
|
|
31728
|
+
batch.push(...claimInsertStatements(normalized.claims, existingClaims, nextEntity.id, proposalId, Number(user.id), now));
|
|
31729
|
+
}
|
|
31489
31730
|
batch.push(...commonsIndexStatements(nextEntity, now));
|
|
31490
31731
|
batch.push({
|
|
31491
31732
|
sql: `
|
|
@@ -31502,10 +31743,19 @@ async function submitCommonsEntity(input, user) {
|
|
|
31502
31743
|
actorLabel(input, user),
|
|
31503
31744
|
normalized.actorChannel,
|
|
31504
31745
|
existing ? "entity_updated" : "entity_created",
|
|
31505
|
-
JSON.stringify(
|
|
31746
|
+
JSON.stringify([
|
|
31747
|
+
...changedFieldPaths(existing, nextEntity),
|
|
31748
|
+
...normalized.claims !== void 0 ? ["claims"] : []
|
|
31749
|
+
]),
|
|
31506
31750
|
normalized.changeSummary || (existing ? "Updated Commons entity." : "Created Commons entity."),
|
|
31507
|
-
existing ? JSON.stringify(
|
|
31508
|
-
|
|
31751
|
+
existing ? JSON.stringify({
|
|
31752
|
+
...entityLedgerSnapshot(existing),
|
|
31753
|
+
...normalized.claims !== void 0 ? { claims: existingClaims } : {}
|
|
31754
|
+
}) : null,
|
|
31755
|
+
JSON.stringify({
|
|
31756
|
+
...entityLedgerSnapshot(nextEntity),
|
|
31757
|
+
...normalized.claims !== void 0 ? { claims: normalized.claims } : {}
|
|
31758
|
+
}),
|
|
31509
31759
|
now
|
|
31510
31760
|
]
|
|
31511
31761
|
});
|
|
@@ -31556,11 +31806,35 @@ async function getCommonsEntityLedger(idOrSlug) {
|
|
|
31556
31806
|
ledger: result.rows.map((row) => rowToLedgerEntry(row))
|
|
31557
31807
|
};
|
|
31558
31808
|
}
|
|
31809
|
+
async function listCommonsClaims(idOrSlug) {
|
|
31810
|
+
await ensureCommonsSchema();
|
|
31811
|
+
const entity = await getCommonsEntity(idOrSlug);
|
|
31812
|
+
if (!entity) return null;
|
|
31813
|
+
return { entity, claims: await getCommonsClaimsByEntityId(entity.id) };
|
|
31814
|
+
}
|
|
31815
|
+
async function getCommonsEntityLinkset(idOrSlug) {
|
|
31816
|
+
const result = await listCommonsClaims(idOrSlug);
|
|
31817
|
+
if (!result) return null;
|
|
31818
|
+
const targetIds = [...new Set(result.claims.map((claim) => claim.objectEntityId).filter((id) => Boolean(id)))];
|
|
31819
|
+
const targetSlugs = /* @__PURE__ */ new Map();
|
|
31820
|
+
if (targetIds.length) {
|
|
31821
|
+
const targets = await getDb().execute({
|
|
31822
|
+
sql: `SELECT id, slug FROM commons_entities WHERE status = 'published' AND id IN (${targetIds.map(() => "?").join(", ")})`,
|
|
31823
|
+
args: targetIds
|
|
31824
|
+
});
|
|
31825
|
+
for (const row of targets.rows) targetSlugs.set(String(row.id), String(row.slug));
|
|
31826
|
+
}
|
|
31827
|
+
const resolved = result.claims.map((claim) => {
|
|
31828
|
+
const href = claim.objectUrl ?? (claim.objectEntityId && targetSlugs.has(claim.objectEntityId) ? publicUrlForSlug(targetSlugs.get(claim.objectEntityId)) : null);
|
|
31829
|
+
return href ? { ...claim, href } : null;
|
|
31830
|
+
}).filter((claim) => claim !== null);
|
|
31831
|
+
return { entity: result.entity, claims: result.claims, ...buildCommonsLinkset(result.entity, resolved) };
|
|
31832
|
+
}
|
|
31559
31833
|
async function saveCommonsFilter(input, user) {
|
|
31560
31834
|
await ensureCommonsSchema();
|
|
31561
31835
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
31562
31836
|
const name = requiredText(input.name, "name", 2, 80);
|
|
31563
|
-
const description =
|
|
31837
|
+
const description = optionalText2(input.description, 500);
|
|
31564
31838
|
const filter = sanitizeSearchFilters(input.filter);
|
|
31565
31839
|
const existing = await getDb().execute({
|
|
31566
31840
|
sql: "SELECT id FROM commons_saved_filters WHERE user_id = ? AND name = ? LIMIT 1",
|
|
@@ -31693,9 +31967,9 @@ function commonsDatabaseReport() {
|
|
|
31693
31967
|
conflictBehavior: "Existing entity edits require baseRevision. Otherwise the proposal is pending_review.",
|
|
31694
31968
|
billing: { validationCredits: 0, createCredits: LISTING_WRITE_RATE_POLICY.create.credits, editCredits: LISTING_WRITE_RATE_POLICY.edit.credits }
|
|
31695
31969
|
},
|
|
31696
|
-
searchCorpus: ["title", "disambiguationName", "description", "tags", "keywords", "relatedEntities", "bodyMarkdown", "sections", "media", "source metadata", "jsonLd"],
|
|
31970
|
+
searchCorpus: ["title", "disambiguationName", "description", "tags", "keywords", "relatedEntities", "relationship claims", "bodyMarkdown", "sections", "media", "source metadata", "jsonLd"],
|
|
31697
31971
|
indexing: commonsIndexingPolicy(),
|
|
31698
|
-
tables: ["commons_entities", "commons_proposals", "commons_ledger", "commons_saved_filters", "commons_index_documents"]
|
|
31972
|
+
tables: ["commons_entities", "commons_claims", "commons_proposals", "commons_ledger", "commons_saved_filters", "commons_index_documents"]
|
|
31699
31973
|
};
|
|
31700
31974
|
}
|
|
31701
31975
|
function entityToWikiPage(entity) {
|
|
@@ -31715,6 +31989,13 @@ function entityToWikiPage(entity) {
|
|
|
31715
31989
|
media: entity.media,
|
|
31716
31990
|
sections: entity.articleSections,
|
|
31717
31991
|
metadata: {
|
|
31992
|
+
linksetUrl: commonsLinksetUrl(entity.id),
|
|
31993
|
+
linksetDiscovery: {
|
|
31994
|
+
rel: "linkset",
|
|
31995
|
+
type: COMMONS_LINKSET_MEDIA_TYPE,
|
|
31996
|
+
profile: COMMONS_RELATIONSHIP_PROFILE,
|
|
31997
|
+
href: commonsLinksetUrl(entity.id)
|
|
31998
|
+
},
|
|
31718
31999
|
entityType: friendlyEntityType(entity.entityType),
|
|
31719
32000
|
disambiguationName: entity.disambiguationName,
|
|
31720
32001
|
keywords: entity.keywords,
|
|
@@ -31871,7 +32152,7 @@ async function commonsTagVocabulary() {
|
|
|
31871
32152
|
...parseJson3(record.tags_json, []),
|
|
31872
32153
|
...parseJson3(record.keywords_json, [])
|
|
31873
32154
|
]) {
|
|
31874
|
-
const cleaned =
|
|
32155
|
+
const cleaned = optionalText2(tag, 120);
|
|
31875
32156
|
if (!cleaned) continue;
|
|
31876
32157
|
counts.set(cleaned, (counts.get(cleaned) ?? 0) + 1);
|
|
31877
32158
|
}
|
|
@@ -31881,7 +32162,7 @@ async function commonsTagVocabulary() {
|
|
|
31881
32162
|
function resolveCommonsTags(candidates, vocabulary) {
|
|
31882
32163
|
const vocabularyByKey = new Map(vocabulary.map((entry) => [entry.tag.toLowerCase(), entry]));
|
|
31883
32164
|
return candidates.map((candidate) => {
|
|
31884
|
-
const cleaned =
|
|
32165
|
+
const cleaned = optionalText2(candidate, 120) ?? "";
|
|
31885
32166
|
const key = cleaned.toLowerCase();
|
|
31886
32167
|
const exact = vocabularyByKey.get(key);
|
|
31887
32168
|
if (!cleaned || cleaned.length < 2) {
|
|
@@ -31978,12 +32259,13 @@ function normalizeSubmitInput(input) {
|
|
|
31978
32259
|
slug: slug2,
|
|
31979
32260
|
entityId: normalizeEntityId(input.entityId),
|
|
31980
32261
|
entityType: normalizeEntityType(input.entityType),
|
|
31981
|
-
disambiguationName:
|
|
32262
|
+
disambiguationName: optionalText2(input.disambiguationName, 240) ?? void 0,
|
|
31982
32263
|
featuredImage: normalizeFeaturedImage(input.featuredImage),
|
|
31983
32264
|
source: normalizeSource(input.source),
|
|
31984
32265
|
tags: uniqueStrings(input.tags ?? []).slice(0, 24),
|
|
31985
32266
|
keywords: uniqueStrings(input.keywords ?? []).slice(0, 50),
|
|
31986
32267
|
relatedEntities: normalizeRelatedEntities(input.relatedEntities),
|
|
32268
|
+
claims: normalizeClaimsForRepository(input.claims),
|
|
31987
32269
|
bodyMarkdown: normalizeBody(input.bodyMarkdown, input.contentSections),
|
|
31988
32270
|
contentSections: normalizeContentSections(input.contentSections),
|
|
31989
32271
|
articleSections: normalizeArticleSections(input.articleSections),
|
|
@@ -31992,11 +32274,18 @@ function normalizeSubmitInput(input) {
|
|
|
31992
32274
|
seo: normalizeSeo(input.seo),
|
|
31993
32275
|
actorChannel: input.actorChannel ?? "mcp",
|
|
31994
32276
|
actorLabel: input.actorLabel ?? "",
|
|
31995
|
-
changeSummary:
|
|
32277
|
+
changeSummary: optionalText2(input.changeSummary, 500) ?? "",
|
|
31996
32278
|
reviewPolicy: input.reviewPolicy ?? "auto_publish_if_safe",
|
|
31997
32279
|
baseRevision: input.baseRevision
|
|
31998
32280
|
};
|
|
31999
32281
|
}
|
|
32282
|
+
function normalizeClaimsForRepository(input) {
|
|
32283
|
+
try {
|
|
32284
|
+
return normalizeCommonsClaims(input);
|
|
32285
|
+
} catch (error) {
|
|
32286
|
+
throw new CommonsRepositoryError("invalid_claims", error instanceof Error ? error.message : "Claims are invalid.");
|
|
32287
|
+
}
|
|
32288
|
+
}
|
|
32000
32289
|
function evaluatePublishSafety(input, existing) {
|
|
32001
32290
|
if (!input.featuredImage?.url) return { safe: false, reason: "A featured image is required before a Commons entity can publish." };
|
|
32002
32291
|
if (!input.bodyMarkdown.trim() && !input.source.originalUrl && !input.source.resolvedUrl) {
|
|
@@ -32142,6 +32431,84 @@ function entityStorageValues(entity) {
|
|
|
32142
32431
|
entity.revision
|
|
32143
32432
|
];
|
|
32144
32433
|
}
|
|
32434
|
+
function claimInsertStatements(claims, existingClaims, subjectEntityId, proposalId, userId, now) {
|
|
32435
|
+
const existingByIdentity = new Map(existingClaims.map((claim) => [commonsClaimIdentityKey(claim), claim]));
|
|
32436
|
+
return claims.map((claim) => {
|
|
32437
|
+
const existing = existingByIdentity.get(commonsClaimIdentityKey(claim));
|
|
32438
|
+
return {
|
|
32439
|
+
sql: `
|
|
32440
|
+
INSERT INTO commons_claims (
|
|
32441
|
+
id, subject_entity_id, predicate, predicate_label, object_entity_id, object_url,
|
|
32442
|
+
title, media_type, hreflang, qualifiers_json, references_json, rank, confidence,
|
|
32443
|
+
confidence_reason, dispute_state, valid_from, valid_to, as_of, source_family,
|
|
32444
|
+
review_state, proposal_id, created_by_user_id, updated_by_user_id, created_at, updated_at
|
|
32445
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'approved', ?, ?, ?, ?, ?)
|
|
32446
|
+
`,
|
|
32447
|
+
args: [
|
|
32448
|
+
existing?.id ?? allocateClaimId(),
|
|
32449
|
+
subjectEntityId,
|
|
32450
|
+
claim.predicate,
|
|
32451
|
+
claim.predicateLabel ?? null,
|
|
32452
|
+
claim.objectEntityId ?? null,
|
|
32453
|
+
claim.objectUrl ?? null,
|
|
32454
|
+
claim.title ?? null,
|
|
32455
|
+
claim.mediaType ?? null,
|
|
32456
|
+
claim.hreflang ? JSON.stringify(claim.hreflang) : null,
|
|
32457
|
+
JSON.stringify(claim.qualifiers ?? {}),
|
|
32458
|
+
JSON.stringify(claim.references ?? []),
|
|
32459
|
+
claim.rank ?? "normal",
|
|
32460
|
+
claim.confidence ?? 1,
|
|
32461
|
+
claim.confidenceReason ?? null,
|
|
32462
|
+
claim.disputeState ?? "undisputed",
|
|
32463
|
+
claim.validFrom ?? null,
|
|
32464
|
+
claim.validTo ?? null,
|
|
32465
|
+
claim.asOf ?? null,
|
|
32466
|
+
claim.sourceFamily ?? "unknown",
|
|
32467
|
+
proposalId,
|
|
32468
|
+
existing?.createdByUserId ?? userId,
|
|
32469
|
+
userId,
|
|
32470
|
+
existing?.createdAt ?? now,
|
|
32471
|
+
now
|
|
32472
|
+
]
|
|
32473
|
+
};
|
|
32474
|
+
});
|
|
32475
|
+
}
|
|
32476
|
+
async function getCommonsClaimsByEntityId(entityId) {
|
|
32477
|
+
const result = await getDb().execute({
|
|
32478
|
+
sql: "SELECT * FROM commons_claims WHERE subject_entity_id = ? ORDER BY predicate ASC, object_url ASC, object_entity_id ASC, id ASC",
|
|
32479
|
+
args: [entityId]
|
|
32480
|
+
});
|
|
32481
|
+
return result.rows.map((row) => rowToClaim(row));
|
|
32482
|
+
}
|
|
32483
|
+
function rowToClaim(row) {
|
|
32484
|
+
return {
|
|
32485
|
+
id: String(row.id),
|
|
32486
|
+
subjectEntityId: String(row.subject_entity_id),
|
|
32487
|
+
predicate: String(row.predicate),
|
|
32488
|
+
predicateLabel: row.predicate_label == null ? void 0 : String(row.predicate_label),
|
|
32489
|
+
objectEntityId: row.object_entity_id == null ? void 0 : String(row.object_entity_id),
|
|
32490
|
+
objectUrl: row.object_url == null ? void 0 : String(row.object_url),
|
|
32491
|
+
title: row.title == null ? void 0 : String(row.title),
|
|
32492
|
+
mediaType: row.media_type == null ? void 0 : String(row.media_type),
|
|
32493
|
+
hreflang: row.hreflang == null ? void 0 : parseJson3(row.hreflang, []),
|
|
32494
|
+
qualifiers: parseJson3(row.qualifiers_json, {}),
|
|
32495
|
+
references: parseJson3(row.references_json, []),
|
|
32496
|
+
rank: String(row.rank),
|
|
32497
|
+
confidence: Number(row.confidence),
|
|
32498
|
+
confidenceReason: row.confidence_reason == null ? void 0 : String(row.confidence_reason),
|
|
32499
|
+
disputeState: String(row.dispute_state),
|
|
32500
|
+
validFrom: row.valid_from == null ? void 0 : String(row.valid_from),
|
|
32501
|
+
validTo: row.valid_to == null ? void 0 : String(row.valid_to),
|
|
32502
|
+
asOf: row.as_of == null ? void 0 : String(row.as_of),
|
|
32503
|
+
sourceFamily: String(row.source_family),
|
|
32504
|
+
reviewState: String(row.review_state),
|
|
32505
|
+
proposalId: String(row.proposal_id),
|
|
32506
|
+
createdByUserId: row.created_by_user_id == null ? null : Number(row.created_by_user_id),
|
|
32507
|
+
updatedByUserId: row.updated_by_user_id == null ? null : Number(row.updated_by_user_id),
|
|
32508
|
+
createdAt: String(row.created_at),
|
|
32509
|
+
updatedAt: String(row.updated_at)
|
|
32510
|
+
};
|
|
32511
|
+
}
|
|
32145
32512
|
function commonsIndexStatements(entity, now) {
|
|
32146
32513
|
return commonsIndexDocuments(entity, now).map((document2) => ({
|
|
32147
32514
|
sql: `
|
|
@@ -32246,7 +32613,7 @@ function commonsIndexDocuments(entity, now) {
|
|
|
32246
32613
|
return documents;
|
|
32247
32614
|
}
|
|
32248
32615
|
function commonsIndexDocumentId(entityId, documentType, documentKey) {
|
|
32249
|
-
return `commons-index-${
|
|
32616
|
+
return `commons-index-${createHash13("sha256").update(`${entityId}
|
|
32250
32617
|
${documentType}
|
|
32251
32618
|
${documentKey}`).digest("hex").slice(0, 32)}`;
|
|
32252
32619
|
}
|
|
@@ -32421,14 +32788,14 @@ function normalizeArticleSections(sections) {
|
|
|
32421
32788
|
return {
|
|
32422
32789
|
relatedLinks: normalizeRelatedLinks(sections?.relatedLinks),
|
|
32423
32790
|
notes: Array.isArray(sections?.notes) ? sections.notes.map((note) => ({
|
|
32424
|
-
marker:
|
|
32791
|
+
marker: optionalText2(note.marker, 20) ?? void 0,
|
|
32425
32792
|
body: requiredText(note.body, "notes.body", 1, 2e3)
|
|
32426
32793
|
})).slice(0, 100) : [],
|
|
32427
32794
|
citations: normalizeCitations(sections?.citations),
|
|
32428
32795
|
externalLinks: Array.isArray(sections?.externalLinks) ? sections.externalLinks.map((link) => ({
|
|
32429
32796
|
title: requiredText(link.title, "externalLinks.title", 1, 180),
|
|
32430
32797
|
url: requiredText(link.url, "externalLinks.url", 1, 2e3),
|
|
32431
|
-
summary:
|
|
32798
|
+
summary: optionalText2(link.summary, 300) ?? void 0
|
|
32432
32799
|
})).slice(0, 100) : [],
|
|
32433
32800
|
categories: uniqueStrings(sections?.categories ?? []).slice(0, 50)
|
|
32434
32801
|
};
|
|
@@ -32437,7 +32804,7 @@ function normalizeRelatedLinks(relatedLinks) {
|
|
|
32437
32804
|
if (!Array.isArray(relatedLinks)) return [];
|
|
32438
32805
|
return relatedLinks.map((link) => {
|
|
32439
32806
|
const title = requiredText(link.title, "relatedLinks.title", 1, 180);
|
|
32440
|
-
const url =
|
|
32807
|
+
const url = optionalText2(link.url, 2e3);
|
|
32441
32808
|
const slug2 = link.slug ? normalizeSlug(link.slug) : void 0;
|
|
32442
32809
|
const entityId = normalizeEntityId(link.entityId);
|
|
32443
32810
|
const needsLink = link.needsLink === true || !url && !slug2 && !entityId;
|
|
@@ -32446,9 +32813,9 @@ function normalizeRelatedLinks(relatedLinks) {
|
|
|
32446
32813
|
url,
|
|
32447
32814
|
slug: slug2,
|
|
32448
32815
|
entityId,
|
|
32449
|
-
relationship:
|
|
32450
|
-
summary:
|
|
32451
|
-
imageUrl:
|
|
32816
|
+
relationship: optionalText2(link.relationship, 120) ?? void 0,
|
|
32817
|
+
summary: optionalText2(link.summary, 300) ?? void 0,
|
|
32818
|
+
imageUrl: optionalText2(link.imageUrl, 2e3) ?? void 0,
|
|
32452
32819
|
needsLink
|
|
32453
32820
|
};
|
|
32454
32821
|
}).slice(0, 100);
|
|
@@ -32457,20 +32824,20 @@ function normalizeCitations(citations) {
|
|
|
32457
32824
|
if (!Array.isArray(citations)) return [];
|
|
32458
32825
|
return citations.map((citation) => ({
|
|
32459
32826
|
title: requiredText(citation.title, "citation.title", 1, 240),
|
|
32460
|
-
url:
|
|
32461
|
-
source:
|
|
32462
|
-
note:
|
|
32463
|
-
accessedAt:
|
|
32827
|
+
url: optionalText2(citation.url, 2e3) ?? void 0,
|
|
32828
|
+
source: optionalText2(citation.source, 240) ?? void 0,
|
|
32829
|
+
note: optionalText2(citation.note, 1e3) ?? void 0,
|
|
32830
|
+
accessedAt: optionalText2(citation.accessedAt, 80) ?? void 0
|
|
32464
32831
|
})).slice(0, 300);
|
|
32465
32832
|
}
|
|
32466
32833
|
function normalizeFeaturedImage(image) {
|
|
32467
32834
|
if (!image?.url) return void 0;
|
|
32468
32835
|
return {
|
|
32469
32836
|
url: requiredText(image.url, "featuredImage.url", 1, 2e3),
|
|
32470
|
-
alt:
|
|
32471
|
-
caption:
|
|
32472
|
-
sourceUrl:
|
|
32473
|
-
license:
|
|
32837
|
+
alt: optionalText2(image.alt, 500) ?? void 0,
|
|
32838
|
+
caption: optionalText2(image.caption, 1e3) ?? void 0,
|
|
32839
|
+
sourceUrl: optionalText2(image.sourceUrl, 2e3) ?? void 0,
|
|
32840
|
+
license: optionalText2(image.license, 240) ?? void 0,
|
|
32474
32841
|
width: positiveInt(image.width),
|
|
32475
32842
|
height: positiveInt(image.height)
|
|
32476
32843
|
};
|
|
@@ -32479,11 +32846,11 @@ function normalizeMedia(media, featuredImage) {
|
|
|
32479
32846
|
const normalized = Array.isArray(media) ? media.map((item) => ({
|
|
32480
32847
|
type: item.type,
|
|
32481
32848
|
url: requiredText(item.url, "media.url", 1, 2e3),
|
|
32482
|
-
alt:
|
|
32483
|
-
caption:
|
|
32484
|
-
posterUrl:
|
|
32485
|
-
sourceUrl:
|
|
32486
|
-
license:
|
|
32849
|
+
alt: optionalText2(item.alt, 500) ?? void 0,
|
|
32850
|
+
caption: optionalText2(item.caption, 1e3) ?? void 0,
|
|
32851
|
+
posterUrl: optionalText2(item.posterUrl, 2e3) ?? void 0,
|
|
32852
|
+
sourceUrl: optionalText2(item.sourceUrl, 2e3) ?? void 0,
|
|
32853
|
+
license: optionalText2(item.license, 240) ?? void 0,
|
|
32487
32854
|
width: positiveInt(item.width),
|
|
32488
32855
|
height: positiveInt(item.height),
|
|
32489
32856
|
durationSeconds: positiveInt(item.durationSeconds)
|
|
@@ -32513,28 +32880,28 @@ function normalizeMedia(media, featuredImage) {
|
|
|
32513
32880
|
}
|
|
32514
32881
|
function normalizeSource(source) {
|
|
32515
32882
|
return {
|
|
32516
|
-
originalUrl:
|
|
32517
|
-
resolvedUrl:
|
|
32518
|
-
sourceCanonicalUrl:
|
|
32519
|
-
relCanonicalHref:
|
|
32520
|
-
sourceByline:
|
|
32521
|
-
publisher:
|
|
32883
|
+
originalUrl: optionalText2(source?.originalUrl, 2e3) ?? void 0,
|
|
32884
|
+
resolvedUrl: optionalText2(source?.resolvedUrl, 2e3) ?? void 0,
|
|
32885
|
+
sourceCanonicalUrl: optionalText2(source?.sourceCanonicalUrl, 2e3) ?? void 0,
|
|
32886
|
+
relCanonicalHref: optionalText2(source?.relCanonicalHref, 2e3) ?? void 0,
|
|
32887
|
+
sourceByline: optionalText2(source?.sourceByline, 240) ?? void 0,
|
|
32888
|
+
publisher: optionalText2(source?.publisher, 240) ?? void 0,
|
|
32522
32889
|
authors: uniqueStrings(source?.authors ?? []).slice(0, 20),
|
|
32523
|
-
publishedAt:
|
|
32524
|
-
capturedAt:
|
|
32525
|
-
license:
|
|
32526
|
-
rightsSummary:
|
|
32527
|
-
contentHash:
|
|
32890
|
+
publishedAt: optionalText2(source?.publishedAt, 80) ?? void 0,
|
|
32891
|
+
capturedAt: optionalText2(source?.capturedAt, 80) ?? void 0,
|
|
32892
|
+
license: optionalText2(source?.license, 240) ?? void 0,
|
|
32893
|
+
rightsSummary: optionalText2(source?.rightsSummary, 1e3) ?? void 0,
|
|
32894
|
+
contentHash: optionalText2(source?.contentHash, 200) ?? void 0
|
|
32528
32895
|
};
|
|
32529
32896
|
}
|
|
32530
32897
|
function normalizeSeo(seo) {
|
|
32531
32898
|
return {
|
|
32532
|
-
canonicalUrl:
|
|
32533
|
-
relCanonical:
|
|
32534
|
-
metaTitle:
|
|
32535
|
-
metaDescription:
|
|
32536
|
-
ogImage:
|
|
32537
|
-
schemaOrgType:
|
|
32899
|
+
canonicalUrl: optionalText2(seo?.canonicalUrl, 2e3) ?? void 0,
|
|
32900
|
+
relCanonical: optionalText2(seo?.relCanonical, 2e3) ?? void 0,
|
|
32901
|
+
metaTitle: optionalText2(seo?.metaTitle, 240) ?? void 0,
|
|
32902
|
+
metaDescription: optionalText2(seo?.metaDescription, 500) ?? void 0,
|
|
32903
|
+
ogImage: optionalText2(seo?.ogImage, 2e3) ?? void 0,
|
|
32904
|
+
schemaOrgType: optionalText2(seo?.schemaOrgType, 80) ?? void 0,
|
|
32538
32905
|
noIndex: seo?.noIndex === true
|
|
32539
32906
|
};
|
|
32540
32907
|
}
|
|
@@ -32543,37 +32910,37 @@ function normalizeRelatedEntities(related) {
|
|
|
32543
32910
|
return related.map((item) => ({
|
|
32544
32911
|
entityId: normalizeEntityId(item.entityId),
|
|
32545
32912
|
title: requiredText(item.title, "relatedEntities.title", 1, 180),
|
|
32546
|
-
relationship:
|
|
32913
|
+
relationship: optionalText2(item.relationship, 120) ?? void 0,
|
|
32547
32914
|
slug: item.slug ? normalizeSlug(item.slug) : void 0,
|
|
32548
|
-
url:
|
|
32549
|
-
description:
|
|
32915
|
+
url: optionalText2(item.url, 2e3) ?? void 0,
|
|
32916
|
+
description: optionalText2(item.description, 300) ?? void 0
|
|
32550
32917
|
})).slice(0, 200);
|
|
32551
32918
|
}
|
|
32552
32919
|
function sanitizeSearchFilters(filters) {
|
|
32553
32920
|
return {
|
|
32554
|
-
query:
|
|
32921
|
+
query: optionalText2(filters.query, 300) ?? void 0,
|
|
32555
32922
|
entityType: filters.entityType ? normalizeEntityType(filters.entityType) : void 0,
|
|
32556
|
-
tag:
|
|
32923
|
+
tag: optionalText2(filters.tag, 80) ?? void 0,
|
|
32557
32924
|
tags: uniqueStrings(filters.tags ?? []).slice(0, 20),
|
|
32558
|
-
keyword:
|
|
32925
|
+
keyword: optionalText2(filters.keyword, 120) ?? void 0,
|
|
32559
32926
|
keywords: uniqueStrings(filters.keywords ?? []).slice(0, 20),
|
|
32560
32927
|
relatedEntityId: normalizeEntityId(filters.relatedEntityId),
|
|
32561
32928
|
trailId: normalizeEntityId(filters.trailId),
|
|
32562
|
-
sourceDomain:
|
|
32929
|
+
sourceDomain: optionalText2(filters.sourceDomain, 240) ?? void 0,
|
|
32563
32930
|
hasMedia: filters.hasMedia === true ? true : void 0,
|
|
32564
32931
|
hasVideo: filters.hasVideo === true ? true : void 0,
|
|
32565
|
-
publishedAfter:
|
|
32566
|
-
updatedAfter:
|
|
32567
|
-
filterId:
|
|
32932
|
+
publishedAfter: optionalText2(filters.publishedAfter, 80) ?? void 0,
|
|
32933
|
+
updatedAfter: optionalText2(filters.updatedAfter, 80) ?? void 0,
|
|
32934
|
+
filterId: optionalText2(filters.filterId, 200) ?? void 0,
|
|
32568
32935
|
limit: clampNumber(filters.limit, 1, 100, 20),
|
|
32569
32936
|
offset: clampNumber(filters.offset, 0, 1e4, 0)
|
|
32570
32937
|
};
|
|
32571
32938
|
}
|
|
32572
32939
|
function sanitizeNeedsLinkFilters(filters) {
|
|
32573
32940
|
return {
|
|
32574
|
-
query:
|
|
32941
|
+
query: optionalText2(filters.query, 300) ?? void 0,
|
|
32575
32942
|
entityType: filters.entityType ? normalizeEntityType(filters.entityType) : void 0,
|
|
32576
|
-
tag:
|
|
32943
|
+
tag: optionalText2(filters.tag, 80) ?? void 0,
|
|
32577
32944
|
tags: uniqueStrings(filters.tags ?? []).slice(0, 20),
|
|
32578
32945
|
sourceEntityId: normalizeEntityId(filters.sourceEntityId),
|
|
32579
32946
|
sourceSlug: filters.sourceSlug ? normalizeSlug(filters.sourceSlug) : void 0,
|
|
@@ -32594,7 +32961,7 @@ function commonsIndexingPolicy() {
|
|
|
32594
32961
|
storageScope: "platform_commons_graph",
|
|
32595
32962
|
countsAgainstUserStorage: false,
|
|
32596
32963
|
embedsPrivateUserVaults: false,
|
|
32597
|
-
corpus: ["published Commons article body", "tags", "keywords", "JSON-LD metadata", "related entities", "See Also concepts marked needsLink"],
|
|
32964
|
+
corpus: ["published Commons article body", "tags", "keywords", "JSON-LD metadata", "related entities", "governed relationship claims", "See Also concepts marked needsLink"],
|
|
32598
32965
|
excluded: ["comments", "comment threads", "reader alerts", "private reading-room state"],
|
|
32599
32966
|
retrievalPattern: {
|
|
32600
32967
|
lexicalFirst: ["title", "tags", "keywords", "source metadata", "article body", "See Also concepts"],
|
|
@@ -32670,7 +33037,7 @@ function searchableText(entity) {
|
|
|
32670
33037
|
].filter(Boolean).join("\n").toLowerCase();
|
|
32671
33038
|
}
|
|
32672
33039
|
function actorLabel(input, user) {
|
|
32673
|
-
return
|
|
33040
|
+
return optionalText2(input.actorLabel, 120) || optionalText2(user.name, 120) || `mcp-user-${user.id}`;
|
|
32674
33041
|
}
|
|
32675
33042
|
function publicBaseUrl() {
|
|
32676
33043
|
return (process.env.TRANSPARENT_COMMONS_PUBLIC_BASE_URL?.trim() || DEFAULT_COMMONS_BASE_URL).replace(/\/+$/, "");
|
|
@@ -32681,13 +33048,16 @@ function publicUrlForSlug(slug2) {
|
|
|
32681
33048
|
function allocateEntityId() {
|
|
32682
33049
|
return `TPW-Q${Date.now()}${Math.floor(Math.random() * 1e3).toString().padStart(3, "0")}`;
|
|
32683
33050
|
}
|
|
33051
|
+
function allocateClaimId() {
|
|
33052
|
+
return `TPW-S${Date.now()}${Math.floor(Math.random() * 1e6).toString().padStart(6, "0")}`;
|
|
33053
|
+
}
|
|
32684
33054
|
function normalizeEntityId(value) {
|
|
32685
|
-
const text2 =
|
|
33055
|
+
const text2 = optionalText2(value, 80);
|
|
32686
33056
|
if (!text2) return void 0;
|
|
32687
33057
|
return text2.replace(/\s+/g, "").toUpperCase();
|
|
32688
33058
|
}
|
|
32689
33059
|
function normalizeEntityType(value) {
|
|
32690
|
-
const raw =
|
|
33060
|
+
const raw = optionalText2(value, 120) || DEFAULT_ENTITY_TYPE;
|
|
32691
33061
|
const squashed = raw.replace(/[\s_-]+/g, "").toLowerCase();
|
|
32692
33062
|
if (squashed === "publicarticle" || squashed === "article" || squashed === "item") return DEFAULT_ENTITY_TYPE;
|
|
32693
33063
|
if (squashed === "trail" || squashed === "readingtrail") return "Trail";
|
|
@@ -32715,7 +33085,7 @@ function requiredText(value, field, min, max) {
|
|
|
32715
33085
|
if (text2.length < min) throw new CommonsRepositoryError(`${field.replaceAll(".", "_")}_required`, `${field} must be at least ${min} characters.`);
|
|
32716
33086
|
return text2.slice(0, max);
|
|
32717
33087
|
}
|
|
32718
|
-
function
|
|
33088
|
+
function optionalText2(value, max) {
|
|
32719
33089
|
const text2 = String(value ?? "").trim();
|
|
32720
33090
|
return text2 ? text2.slice(0, max) : void 0;
|
|
32721
33091
|
}
|
|
@@ -32735,7 +33105,7 @@ function uniqueStrings(values) {
|
|
|
32735
33105
|
const seen = /* @__PURE__ */ new Set();
|
|
32736
33106
|
const out = [];
|
|
32737
33107
|
for (const value of values) {
|
|
32738
|
-
const text2 =
|
|
33108
|
+
const text2 = optionalText2(value, 120);
|
|
32739
33109
|
if (!text2) continue;
|
|
32740
33110
|
const key = text2.toLowerCase();
|
|
32741
33111
|
if (seen.has(key)) continue;
|
|
@@ -32782,7 +33152,7 @@ var CommonsRepositoryError = class extends Error {
|
|
|
32782
33152
|
};
|
|
32783
33153
|
|
|
32784
33154
|
// src/api/commons-publication-repository.ts
|
|
32785
|
-
import { createHash as
|
|
33155
|
+
import { createHash as createHash14, randomUUID as randomUUID16 } from "crypto";
|
|
32786
33156
|
var PUBLICATION_ROOT_DOMAIN = process.env.COMMONS_PUBLICATION_ROOT_DOMAIN || "transparent-commons.cc";
|
|
32787
33157
|
var RESERVED_SUBDOMAINS = /* @__PURE__ */ new Set([
|
|
32788
33158
|
"admin",
|
|
@@ -32980,7 +33350,7 @@ async function publishCommonsEditorial(input, user) {
|
|
|
32980
33350
|
JSON.stringify(editionInput.articles),
|
|
32981
33351
|
html,
|
|
32982
33352
|
rendered.filename,
|
|
32983
|
-
|
|
33353
|
+
createHash14("sha256").update(html).digest("hex"),
|
|
32984
33354
|
rendered.articleCount,
|
|
32985
33355
|
rendered.wordCount,
|
|
32986
33356
|
Buffer.byteLength(html),
|
|
@@ -33259,6 +33629,7 @@ var SubmitEntitySchema = z32.object({
|
|
|
33259
33629
|
url: z32.string().url().optional(),
|
|
33260
33630
|
description: z32.string().max(300).optional()
|
|
33261
33631
|
}).strict()).max(200).optional(),
|
|
33632
|
+
claims: z32.array(CommonsClaimInputSchema).max(300).optional(),
|
|
33262
33633
|
bodyMarkdown: z32.string().max(5e5).optional(),
|
|
33263
33634
|
contentSections: z32.array(z32.object({
|
|
33264
33635
|
id: z32.string().max(180).optional(),
|
|
@@ -33336,6 +33707,17 @@ commonsApp.get("/health", async (c) => {
|
|
|
33336
33707
|
await ensureCommonsSchema();
|
|
33337
33708
|
return c.json({ ok: true, data: commonsDatabaseReport() });
|
|
33338
33709
|
});
|
|
33710
|
+
commonsApp.get("/profiles/relationships/v1", (c) => c.json({
|
|
33711
|
+
id: COMMONS_RELATIONSHIP_PROFILE,
|
|
33712
|
+
title: "Transparent Commons governed relationship linksets",
|
|
33713
|
+
mediaType: COMMONS_LINKSET_MEDIA_TYPE,
|
|
33714
|
+
claimAuthority: "MCP Scraper authenticated proposal and contribution ledger",
|
|
33715
|
+
anchorPolicy: "Every link context is an absolute canonical Transparent Commons wiki URL.",
|
|
33716
|
+
predicatePolicy: "Predicates are curated registered link relations or absolute HTTPS extension relation URIs.",
|
|
33717
|
+
publicationPolicy: "Only approved, active, non-deprecated claims whose dispute state is undisputed or attributed are projected.",
|
|
33718
|
+
trustPolicy: "A third-party target is an asserted relationship, not an endorsement or proof that the target agrees.",
|
|
33719
|
+
source: "https://www.rfc-editor.org/rfc/rfc9264.html"
|
|
33720
|
+
}));
|
|
33339
33721
|
commonsApp.post("/publications/prepare", auth2, async (c) => {
|
|
33340
33722
|
const parsed = PreparePublicationSchema.safeParse(await c.req.json().catch(() => ({})));
|
|
33341
33723
|
if (!parsed.success) return validationError(c, parsed.error);
|
|
@@ -33466,11 +33848,32 @@ commonsApp.post("/entities/propose", auth2, async (c) => {
|
|
|
33466
33848
|
commonsApp.get("/entities/:idOrSlug", async (c) => {
|
|
33467
33849
|
const entity = await getCommonsEntity(c.req.param("idOrSlug"));
|
|
33468
33850
|
if (!entity) return c.json({ ok: false, error: "entity_not_found", message: "No published Commons entity matched that id or slug." }, 404);
|
|
33851
|
+
c.header("Link", commonsLinksetDiscoveryHeader(entity.id));
|
|
33469
33852
|
return c.json({ ok: true, data: entity });
|
|
33470
33853
|
});
|
|
33854
|
+
commonsApp.get("/entities/:idOrSlug/claims", async (c) => {
|
|
33855
|
+
const result = await getCommonsEntityLinkset(c.req.param("idOrSlug"));
|
|
33856
|
+
if (!result) return c.json({ ok: false, error: "entity_not_found", message: "No published Commons entity matched that id or slug." }, 404);
|
|
33857
|
+
c.header("Link", commonsLinksetDiscoveryHeader(result.entity.id));
|
|
33858
|
+
return c.json({ ok: true, data: { entity: result.entity, claims: result.claims, linksetUrl: result.linksetUrl } });
|
|
33859
|
+
});
|
|
33860
|
+
commonsApp.get("/entities/:idOrSlug/linkset", async (c) => {
|
|
33861
|
+
const result = await getCommonsEntityLinkset(c.req.param("idOrSlug"));
|
|
33862
|
+
if (!result) return c.json({ ok: false, error: "entity_not_found", message: "No published Commons entity matched that id or slug." }, 404);
|
|
33863
|
+
c.header("Content-Type", `${COMMONS_LINKSET_MEDIA_TYPE}; profile="${COMMONS_RELATIONSHIP_PROFILE}"`);
|
|
33864
|
+
c.header("ETag", result.etag);
|
|
33865
|
+
c.header("Link", `<${COMMONS_RELATIONSHIP_PROFILE}>; rel="profile"`);
|
|
33866
|
+
c.header("Cache-Control", "public, max-age=60, s-maxage=300");
|
|
33867
|
+
if (c.req.header("If-None-Match") === result.etag) return c.body(null, 304);
|
|
33868
|
+
if (c.req.query("envelope") === "true") {
|
|
33869
|
+
return c.json({ ok: true, data: { ...result, document: result.document } });
|
|
33870
|
+
}
|
|
33871
|
+
return c.body(JSON.stringify(result.document));
|
|
33872
|
+
});
|
|
33471
33873
|
commonsApp.get("/entities/:idOrSlug/wiki-page", async (c) => {
|
|
33472
33874
|
const entity = await getCommonsEntity(c.req.param("idOrSlug"));
|
|
33473
33875
|
if (!entity) return c.json({ ok: false, error: "entity_not_found", message: "No published Commons entity matched that id or slug." }, 404);
|
|
33876
|
+
c.header("Link", commonsLinksetDiscoveryHeader(entity.id));
|
|
33474
33877
|
return c.json({ ok: true, data: entityToWikiPage(entity) });
|
|
33475
33878
|
});
|
|
33476
33879
|
commonsApp.get("/entities/:idOrSlug/json-ld", async (c) => {
|
|
@@ -33486,6 +33889,7 @@ commonsApp.get("/entities/:idOrSlug/ledger", async (c) => {
|
|
|
33486
33889
|
commonsApp.get("/wiki/:slug", async (c) => {
|
|
33487
33890
|
const entity = await getCommonsEntity(c.req.param("slug"));
|
|
33488
33891
|
if (!entity) return c.json({ ok: false, error: "page_not_found", message: "No published Commons wiki page matched that slug." }, 404);
|
|
33892
|
+
c.header("Link", commonsLinksetDiscoveryHeader(entity.id));
|
|
33489
33893
|
return c.json({
|
|
33490
33894
|
ok: true,
|
|
33491
33895
|
data: {
|
|
@@ -33587,12 +33991,12 @@ function xmlEscape(value) {
|
|
|
33587
33991
|
import { Hono as Hono32 } from "hono";
|
|
33588
33992
|
import { createMiddleware as createMiddleware4 } from "hono/factory";
|
|
33589
33993
|
import { z as z34 } from "zod";
|
|
33590
|
-
import { createHash as
|
|
33994
|
+
import { createHash as createHash16 } from "crypto";
|
|
33591
33995
|
import Papa2 from "papaparse";
|
|
33592
33996
|
|
|
33593
33997
|
// src/api/analytics-entitlement.ts
|
|
33594
33998
|
import {
|
|
33595
|
-
createHash as
|
|
33999
|
+
createHash as createHash15,
|
|
33596
34000
|
createHmac as createHmac3,
|
|
33597
34001
|
randomBytes as randomBytes3,
|
|
33598
34002
|
timingSafeEqual as timingSafeEqual2
|
|
@@ -33807,7 +34211,7 @@ function dashboardCallbackUrl() {
|
|
|
33807
34211
|
async function createThorbitConnectUrl(userId) {
|
|
33808
34212
|
if (!bridgeConfigured()) throw new Error("Thorbit X-Ray account bridge is not configured");
|
|
33809
34213
|
const state = randomBytes3(32).toString("base64url");
|
|
33810
|
-
const stateHash =
|
|
34214
|
+
const stateHash = createHash15("sha256").update(state).digest("hex");
|
|
33811
34215
|
await getAnalyticsPool().query(
|
|
33812
34216
|
`INSERT INTO analytics_thorbit_connect_states(state_hash,user_id,expires_at)
|
|
33813
34217
|
VALUES ($1,$2,now()+interval '10 minutes')
|
|
@@ -33836,7 +34240,7 @@ function verifyThorbitAssertion(token4) {
|
|
|
33836
34240
|
return parsed.data.entitlement;
|
|
33837
34241
|
}
|
|
33838
34242
|
async function consumeThorbitConnectCallback(input) {
|
|
33839
|
-
const stateHash =
|
|
34243
|
+
const stateHash = createHash15("sha256").update(input.state).digest("hex");
|
|
33840
34244
|
const client2 = await getAnalyticsPool().connect();
|
|
33841
34245
|
try {
|
|
33842
34246
|
await client2.query("BEGIN");
|
|
@@ -34307,7 +34711,7 @@ analyticsApp.post("/forms/:publicId/submissions", async (c) => {
|
|
|
34307
34711
|
const lastName = typeof data.last_name === "string" ? data.last_name.trim() : "";
|
|
34308
34712
|
const fullName = [firstName, lastName].filter(Boolean).join(" ") || (typeof data.name === "string" ? data.name.trim() : "") || email || "Website lead";
|
|
34309
34713
|
const identitySeed = email || `${fullName}:${Date.now()}`;
|
|
34310
|
-
const suffix2 =
|
|
34714
|
+
const suffix2 = createHash16("sha256").update(identitySeed).digest("hex").slice(0, 12);
|
|
34311
34715
|
const path5 = `Leads/person-${suffix2}`;
|
|
34312
34716
|
const { key: memoryKey, error: memoryKeyError } = await getOrCreateUserMemoryKey(user);
|
|
34313
34717
|
const existing = memoryKey ? await memoryCall("getTool", { vault: "People", path: path5 }, memoryKey) : { ok: false, error: memoryKeyError || "memory_credential_unavailable" };
|
|
@@ -34406,9 +34810,9 @@ Submitted the published form.
|
|
|
34406
34810
|
occurredAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
34407
34811
|
});
|
|
34408
34812
|
const match = {
|
|
34409
|
-
...email ? { emailSha256:
|
|
34813
|
+
...email ? { emailSha256: createHash16("sha256").update(email).digest("hex") } : {},
|
|
34410
34814
|
...phone ? {
|
|
34411
|
-
phoneSha256:
|
|
34815
|
+
phoneSha256: createHash16("sha256").update(phone.replace(/\D/g, "")).digest("hex")
|
|
34412
34816
|
} : {}
|
|
34413
34817
|
};
|
|
34414
34818
|
const activationQueued = await queueAnalyticsActivation({
|
|
@@ -34836,7 +35240,7 @@ analyticsApp.post("/sites/:siteId/crm-imports", auth3, async (c) => {
|
|
|
34836
35240
|
rejectedCount += 1;
|
|
34837
35241
|
continue;
|
|
34838
35242
|
}
|
|
34839
|
-
const digest2 =
|
|
35243
|
+
const digest2 = createHash16("sha256").update(
|
|
34840
35244
|
`${parsed.data.sourceSystem}:${externalId || email || phone || `${fullName}:${index}`}`
|
|
34841
35245
|
).digest("hex").slice(0, 16);
|
|
34842
35246
|
const path5 = `Leads/person-${digest2}`;
|
|
@@ -35270,13 +35674,13 @@ import { Hono as Hono33 } from "hono";
|
|
|
35270
35674
|
import { z as z35 } from "zod";
|
|
35271
35675
|
|
|
35272
35676
|
// src/api/scheduled-artifact-owner.ts
|
|
35273
|
-
import { createHash as
|
|
35677
|
+
import { createHash as createHash17 } from "crypto";
|
|
35274
35678
|
function scheduledArtifactOwnerIdForApiKey(apiKey) {
|
|
35275
|
-
return
|
|
35679
|
+
return createHash17("sha256").update(apiKey).digest("hex").slice(0, 24);
|
|
35276
35680
|
}
|
|
35277
35681
|
|
|
35278
35682
|
// src/api/scheduled-run-view-links.ts
|
|
35279
|
-
import { createHash as
|
|
35683
|
+
import { createHash as createHash18, randomBytes as randomBytes4, randomUUID as randomUUID17 } from "crypto";
|
|
35280
35684
|
var schemaReady3 = false;
|
|
35281
35685
|
async function ensureScheduledRunViewLinksSchema() {
|
|
35282
35686
|
if (schemaReady3) return;
|
|
@@ -35330,7 +35734,7 @@ async function ensureScheduledRunViewLinksSchema() {
|
|
|
35330
35734
|
schemaReady3 = true;
|
|
35331
35735
|
}
|
|
35332
35736
|
function tokenHash2(token4) {
|
|
35333
|
-
return
|
|
35737
|
+
return createHash18("sha256").update(token4).digest("hex");
|
|
35334
35738
|
}
|
|
35335
35739
|
function mapRow(row) {
|
|
35336
35740
|
return {
|
|
@@ -35417,7 +35821,7 @@ async function revokeScheduledRunViewLink(ownerId, runId, shareId, now = /* @__P
|
|
|
35417
35821
|
}
|
|
35418
35822
|
|
|
35419
35823
|
// src/personal-authority/render.ts
|
|
35420
|
-
import { createHash as
|
|
35824
|
+
import { createHash as createHash19 } from "crypto";
|
|
35421
35825
|
function escapeHtml7(value) {
|
|
35422
35826
|
return value.replace(/[&<>"']/g, (character) => ({
|
|
35423
35827
|
"&": "&",
|
|
@@ -35477,13 +35881,13 @@ ${section(flags.finalCta && Boolean(finalCta), `<section class="section cta" id=
|
|
|
35477
35881
|
html,
|
|
35478
35882
|
filename: `${input.name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "") || "personal-authority"}.html`,
|
|
35479
35883
|
bytes,
|
|
35480
|
-
sha256:
|
|
35884
|
+
sha256: createHash19("sha256").update(html).digest("hex"),
|
|
35481
35885
|
generatedAt: generatedAtIso
|
|
35482
35886
|
};
|
|
35483
35887
|
}
|
|
35484
35888
|
|
|
35485
35889
|
// src/newsroom-publisher/render.ts
|
|
35486
|
-
import { createHash as
|
|
35890
|
+
import { createHash as createHash20 } from "crypto";
|
|
35487
35891
|
function escapeHtml8(value) {
|
|
35488
35892
|
return value.replace(/[&<>"']/g, (character) => ({
|
|
35489
35893
|
"&": "&",
|
|
@@ -35589,7 +35993,7 @@ body{overflow-x:hidden}.lead-story__body,.lead-support__item,.story-card__body{m
|
|
|
35589
35993
|
@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}}
|
|
35590
35994
|
</style></head><body data-theme="${escapeHtml8(config.theme)}" id="top" data-scheduled-renderer="newsroom_publisher_v1">${ticker}${masthead}${navigation}<main>${leadGrid}${latest}${sections}${newsletter}${pressRoom}${trustCenter}</main>${trustFooter}</body></html>`;
|
|
35591
35995
|
const bytes = Buffer.byteLength(html);
|
|
35592
|
-
const sha2563 =
|
|
35996
|
+
const sha2563 = createHash20("sha256").update(html).digest("hex");
|
|
35593
35997
|
const filename = `${brand.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "") || "newsroom"}-news-site.html`;
|
|
35594
35998
|
return { html, filename, bytes, sha256: sha2563, generatedAt: generatedAtIso };
|
|
35595
35999
|
}
|
|
@@ -35850,7 +36254,7 @@ scheduledResultApp.delete("/schedule-runs/:runId/view-links/:shareId", async (c)
|
|
|
35850
36254
|
import { Hono as Hono34 } from "hono";
|
|
35851
36255
|
|
|
35852
36256
|
// src/scheduled-artifacts/scheduled-run-artifact-store.ts
|
|
35853
|
-
import { createHash as
|
|
36257
|
+
import { createHash as createHash21 } from "crypto";
|
|
35854
36258
|
var SCHEDULED_RUN_ARTIFACT_PREFIX = "scheduled-run-artifacts/";
|
|
35855
36259
|
var SCHEDULED_RUN_ARTIFACT_DOWNLOAD_TTL_MS = 15 * 60 * 1e3;
|
|
35856
36260
|
var SCHEDULED_RUN_ARTIFACT_MAX_BYTES = 2e6;
|
|
@@ -35866,7 +36270,7 @@ function policy3() {
|
|
|
35866
36270
|
};
|
|
35867
36271
|
}
|
|
35868
36272
|
function runStorageSegment(runId) {
|
|
35869
|
-
return /^[a-zA-Z0-9_-]{1,160}$/.test(runId) ? runId : `run-${
|
|
36273
|
+
return /^[a-zA-Z0-9_-]{1,160}$/.test(runId) ? runId : `run-${createHash21("sha256").update(runId).digest("hex").slice(0, 32)}`;
|
|
35870
36274
|
}
|
|
35871
36275
|
async function createScheduledRunArtifact(args) {
|
|
35872
36276
|
if (args.rendered.bytes > SCHEDULED_RUN_ARTIFACT_MAX_BYTES) {
|
|
@@ -35973,7 +36377,7 @@ publicScheduledResultApp.get("/scheduled-run-view-links/:token/content", async (
|
|
|
35973
36377
|
import { Hono as Hono35 } from "hono";
|
|
35974
36378
|
|
|
35975
36379
|
// src/api/scheduler-integration-auth.ts
|
|
35976
|
-
import { createHash as
|
|
36380
|
+
import { createHash as createHash22, createHmac as createHmac4, timingSafeEqual as timingSafeEqual3 } from "crypto";
|
|
35977
36381
|
|
|
35978
36382
|
// src/api/service-connections.ts
|
|
35979
36383
|
import { randomUUID as randomUUID18 } from "crypto";
|
|
@@ -36271,7 +36675,7 @@ function signingSecret() {
|
|
|
36271
36675
|
return secret;
|
|
36272
36676
|
}
|
|
36273
36677
|
function schedulerIntegrationSignature(args) {
|
|
36274
|
-
const bodyHash =
|
|
36678
|
+
const bodyHash = createHash22("sha256").update(args.body).digest("hex");
|
|
36275
36679
|
return createHmac4("sha256", args.secret).update(`${args.method.toUpperCase()}
|
|
36276
36680
|
${args.path}
|
|
36277
36681
|
${args.timestamp}
|
|
@@ -36527,13 +36931,13 @@ async function reconcileSiteExtractSettlements(limit = 25) {
|
|
|
36527
36931
|
}
|
|
36528
36932
|
|
|
36529
36933
|
// src/api/page-diff.ts
|
|
36530
|
-
import { createHash as
|
|
36934
|
+
import { createHash as createHash23 } from "crypto";
|
|
36531
36935
|
import { diffLines } from "diff";
|
|
36532
36936
|
var MAX_SNAPSHOT_CONTENT_CHARS = 25e4;
|
|
36533
36937
|
var MAX_DIFF_HUNKS = 200;
|
|
36534
36938
|
var MAX_DIFF_LINES_PER_RESPONSE = 2e3;
|
|
36535
36939
|
function sha256Hex(value) {
|
|
36536
|
-
return
|
|
36940
|
+
return createHash23("sha256").update(value).digest("hex");
|
|
36537
36941
|
}
|
|
36538
36942
|
function truncateForStorage(value, maxChars = MAX_SNAPSHOT_CONTENT_CHARS) {
|
|
36539
36943
|
if (value.length <= maxChars) return { value, truncated: false };
|
|
@@ -36647,10 +37051,10 @@ async function persistScrapeBody(user, opts) {
|
|
|
36647
37051
|
}
|
|
36648
37052
|
|
|
36649
37053
|
// src/api/scrape-image-sink.ts
|
|
36650
|
-
import { createHash as
|
|
37054
|
+
import { createHash as createHash24 } from "crypto";
|
|
36651
37055
|
var MAX_IMAGES_PER_SCRAPE = 25;
|
|
36652
37056
|
function idempotencyKey2(userId, vault, input) {
|
|
36653
|
-
return `scrape-image-${
|
|
37057
|
+
return `scrape-image-${createHash24("sha256").update(`${userId}\0${vault}\0${input.sourceKind}\0${input.sourceUrl}\0${input.imageUrl ?? ""}\0${input.imageBase64 ?? ""}`).digest("hex")}`;
|
|
36654
37058
|
}
|
|
36655
37059
|
async function persistScrapeImagesToMemory(user, inputs, vault) {
|
|
36656
37060
|
const selected = inputs.slice(0, MAX_IMAGES_PER_SCRAPE);
|
|
@@ -37122,7 +37526,7 @@ function inferredWaybackCapturedAt(content) {
|
|
|
37122
37526
|
}
|
|
37123
37527
|
|
|
37124
37528
|
// src/api/connection-memory-import.ts
|
|
37125
|
-
import { createHash as
|
|
37529
|
+
import { createHash as createHash25 } from "crypto";
|
|
37126
37530
|
var CONNECTION_MEMORY_IMPORT_MAX_ARGS_BYTES = 64 * 1024;
|
|
37127
37531
|
var CONNECTION_MEMORY_IMPORT_MAX_RESULT_BYTES = 1e6;
|
|
37128
37532
|
var CONNECTION_MEMORY_IMPORT_MAX_STRING_CHARS = 256e3;
|
|
@@ -37152,7 +37556,7 @@ function canonicalJson(value) {
|
|
|
37152
37556
|
return JSON.stringify(value);
|
|
37153
37557
|
}
|
|
37154
37558
|
function sha2562(value) {
|
|
37155
|
-
return
|
|
37559
|
+
return createHash25("sha256").update(value).digest("hex");
|
|
37156
37560
|
}
|
|
37157
37561
|
function sensitiveKey(key) {
|
|
37158
37562
|
const normalized = key.toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
@@ -38163,7 +38567,7 @@ async function dbUsage(identity, plan) {
|
|
|
38163
38567
|
}
|
|
38164
38568
|
|
|
38165
38569
|
// src/api/nango-control.ts
|
|
38166
|
-
import { createHash as
|
|
38570
|
+
import { createHash as createHash27, randomUUID as randomUUID22 } from "crypto";
|
|
38167
38571
|
|
|
38168
38572
|
// src/api/slack-archive-analysis.ts
|
|
38169
38573
|
function isRecord2(value) {
|
|
@@ -38537,7 +38941,7 @@ async function exportSlackChannelPage(input, dependencies) {
|
|
|
38537
38941
|
}
|
|
38538
38942
|
|
|
38539
38943
|
// src/api/main-nango-transport.ts
|
|
38540
|
-
import { createHash as
|
|
38944
|
+
import { createHash as createHash26, randomUUID as randomUUID21 } from "crypto";
|
|
38541
38945
|
import { Client, StreamableHTTPClientTransport } from "@modelcontextprotocol/client";
|
|
38542
38946
|
|
|
38543
38947
|
// src/api/connected-tool-policy.ts
|
|
@@ -38930,7 +39334,7 @@ async function listNangoToolsDirect(identity, connectionId) {
|
|
|
38930
39334
|
});
|
|
38931
39335
|
const readTools = [...policies.values()].filter((policy4) => policy4.classification === "read").map((policy4) => policy4.name);
|
|
38932
39336
|
const actionTools = [...policies.values()].filter((policy4) => policy4.classification === "action").map((policy4) => policy4.name);
|
|
38933
|
-
const revision =
|
|
39337
|
+
const revision = createHash26("sha256").update(JSON.stringify(tools.map((tool) => ({ name: tool.name, inputSchema: tool.inputSchema })))).digest("hex");
|
|
38934
39338
|
await updateServiceConnectionTools(connection.id, readTools, actionTools, revision);
|
|
38935
39339
|
const refreshed = await getOwnedServiceConnection(identity, connection.id);
|
|
38936
39340
|
return { connection: refreshed ?? { ...connection, readTools, actionTools, toolRevision: revision }, tools };
|
|
@@ -38958,7 +39362,7 @@ async function callNangoToolDirect(args) {
|
|
|
38958
39362
|
ratePolicyVersion: CONNECTED_USAGE_RATE_POLICY_VERSION
|
|
38959
39363
|
});
|
|
38960
39364
|
const requestId = args.requestId?.trim() || randomUUID21();
|
|
38961
|
-
const idempotencyKey3 = `main-nango:${
|
|
39365
|
+
const idempotencyKey3 = `main-nango:${createHash26("sha256").update(args.identity.toLowerCase()).update("\0").update(connection.id).update("\0").update(args.tool).update("\0").update(requestId).digest("hex")}`;
|
|
38962
39366
|
const startedAt = /* @__PURE__ */ new Date();
|
|
38963
39367
|
const started = performance.now();
|
|
38964
39368
|
let result;
|
|
@@ -38983,7 +39387,7 @@ async function callNangoToolDirect(args) {
|
|
|
38983
39387
|
toolName: args.tool,
|
|
38984
39388
|
operationKind: args.operationKind ?? args.classification,
|
|
38985
39389
|
outcome: providerError ? "error" : "partial",
|
|
38986
|
-
requestId: requestId.length <= 200 ? requestId :
|
|
39390
|
+
requestId: requestId.length <= 200 ? requestId : createHash26("sha256").update(requestId).digest("hex"),
|
|
38987
39391
|
startedAt: startedAt.toISOString(),
|
|
38988
39392
|
completedAt: completedAt.toISOString()
|
|
38989
39393
|
}
|
|
@@ -39025,7 +39429,7 @@ async function describeNangoToolDirect(identity, connectionId, toolName) {
|
|
|
39025
39429
|
providerContractHash: MAIN_INTEGRATION_CONTRACT_HASH,
|
|
39026
39430
|
protocolVersion: null,
|
|
39027
39431
|
schemaSource: "live_tools_list",
|
|
39028
|
-
schemaHash:
|
|
39432
|
+
schemaHash: createHash26("sha256").update(JSON.stringify(projected)).digest("hex"),
|
|
39029
39433
|
fetchedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
39030
39434
|
};
|
|
39031
39435
|
}
|
|
@@ -39749,8 +40153,8 @@ async function setScheduleConnectionActionsEnabled(identity, connectionId, enabl
|
|
|
39749
40153
|
return data.connection.actionsEnabled === true;
|
|
39750
40154
|
}
|
|
39751
40155
|
async function callScheduleConnectionAction(identity, connectionId, input, tool, idempotencyKey3) {
|
|
39752
|
-
const requestId = `main-connected-action:${
|
|
39753
|
-
const requestDigest =
|
|
40156
|
+
const requestId = `main-connected-action:${createHash27("sha256").update(identity).update("\0").update(idempotencyKey3?.trim() || randomUUID22()).digest("hex")}`;
|
|
40157
|
+
const requestDigest = createHash27("sha256").update(connectionId).update("\0").update(tool?.trim() ?? "").update("\0").update(canonicalJson2(input)).digest("hex");
|
|
39754
40158
|
if (mainOwnsIntegrations()) {
|
|
39755
40159
|
const selectedTool = tool?.trim();
|
|
39756
40160
|
if (!selectedTool) throw new NangoControlError("An action tool is required.", 400, "invalid_request", false);
|
|
@@ -39901,7 +40305,7 @@ function canonicalJson2(value) {
|
|
|
39901
40305
|
return JSON.stringify(value);
|
|
39902
40306
|
}
|
|
39903
40307
|
function projectedToolSchemaHash(tool) {
|
|
39904
|
-
return
|
|
40308
|
+
return createHash27("sha256").update(canonicalJson2(tool)).digest("hex");
|
|
39905
40309
|
}
|
|
39906
40310
|
async function describeNangoTool(identity, connectionId, tool, fresh) {
|
|
39907
40311
|
if (mainOwnsIntegrations()) {
|
|
@@ -40180,7 +40584,7 @@ async function callMainOwnedExportPage(identity, input) {
|
|
|
40180
40584
|
}
|
|
40181
40585
|
|
|
40182
40586
|
// src/api/resend-control.ts
|
|
40183
|
-
import { createHash as
|
|
40587
|
+
import { createHash as createHash28 } from "crypto";
|
|
40184
40588
|
var DEFAULT_CONNECTION_CONTROL_URL = "https://mcp-scraper-scheduler.vercel.app";
|
|
40185
40589
|
var RESEND_PROVIDER_CONFIG_KEY = "resend";
|
|
40186
40590
|
var RESEND_LOGO_URL = "https://cdn.resend.com/brand/resend-icon-black.svg";
|
|
@@ -40439,7 +40843,7 @@ async function callResendRead(identity, connectionId, tool, args) {
|
|
|
40439
40843
|
return isRecord5(data) ? data.result ?? data : data;
|
|
40440
40844
|
}
|
|
40441
40845
|
async function callResendAction(identity, connectionId, tool, input, idempotencyKey3) {
|
|
40442
|
-
const requestId = `main-resend-action:${
|
|
40846
|
+
const requestId = `main-resend-action:${createHash28("sha256").update(identity).update("\0").update(idempotencyKey3.trim()).digest("hex")}`;
|
|
40443
40847
|
const body = await controlRequest2("/api/internal/resend/actions/call", {
|
|
40444
40848
|
method: "POST",
|
|
40445
40849
|
headers: { "x-request-id": requestId },
|
|
@@ -43763,4 +44167,4 @@ app.get("/blog/:slug/", (c) => {
|
|
|
43763
44167
|
export {
|
|
43764
44168
|
app
|
|
43765
44169
|
};
|
|
43766
|
-
//# sourceMappingURL=server-
|
|
44170
|
+
//# sourceMappingURL=server-JE7SLZLJ.js.map
|