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.
@@ -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-PTABZABJ.js";
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-IAXQIHNS.js";
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 createHash12, randomUUID as randomUUID15 } from "crypto";
30877
- var COMMONS_SCHEMA_VERSION = "2026-08-04.3";
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("related_entities_json LIKE ?");
31235
- args.push(jsonLikeValue(mergedFilters.relatedEntityId));
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("search_text LIKE ?");
31258
- args.push(`%${escapeLike(term)}%`);
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 = optionalText(input.title, 180) ?? "";
31511
+ const title = optionalText2(input.title, 180) ?? "";
31281
31512
  const slug2 = normalizeSlug(input.slug || title);
31282
- const schemaOrgType = optionalText(input.schemaOrgType, 80);
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 = optionalText(input.title, 180);
31341
- const description = optionalText(input.description, 600);
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(changedFieldPaths(existing, nextEntity)),
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(entityLedgerSnapshot(existing)) : null,
31508
- JSON.stringify(entityLedgerSnapshot(nextEntity)),
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 = optionalText(input.description, 500);
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 = optionalText(tag, 120);
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 = optionalText(candidate, 120) ?? "";
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: optionalText(input.disambiguationName, 240) ?? void 0,
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: optionalText(input.changeSummary, 500) ?? "",
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-${createHash12("sha256").update(`${entityId}
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: optionalText(note.marker, 20) ?? void 0,
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: optionalText(link.summary, 300) ?? void 0
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 = optionalText(link.url, 2e3);
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: optionalText(link.relationship, 120) ?? void 0,
32450
- summary: optionalText(link.summary, 300) ?? void 0,
32451
- imageUrl: optionalText(link.imageUrl, 2e3) ?? void 0,
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: optionalText(citation.url, 2e3) ?? void 0,
32461
- source: optionalText(citation.source, 240) ?? void 0,
32462
- note: optionalText(citation.note, 1e3) ?? void 0,
32463
- accessedAt: optionalText(citation.accessedAt, 80) ?? void 0
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: optionalText(image.alt, 500) ?? void 0,
32471
- caption: optionalText(image.caption, 1e3) ?? void 0,
32472
- sourceUrl: optionalText(image.sourceUrl, 2e3) ?? void 0,
32473
- license: optionalText(image.license, 240) ?? void 0,
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: optionalText(item.alt, 500) ?? void 0,
32483
- caption: optionalText(item.caption, 1e3) ?? void 0,
32484
- posterUrl: optionalText(item.posterUrl, 2e3) ?? void 0,
32485
- sourceUrl: optionalText(item.sourceUrl, 2e3) ?? void 0,
32486
- license: optionalText(item.license, 240) ?? void 0,
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: optionalText(source?.originalUrl, 2e3) ?? void 0,
32517
- resolvedUrl: optionalText(source?.resolvedUrl, 2e3) ?? void 0,
32518
- sourceCanonicalUrl: optionalText(source?.sourceCanonicalUrl, 2e3) ?? void 0,
32519
- relCanonicalHref: optionalText(source?.relCanonicalHref, 2e3) ?? void 0,
32520
- sourceByline: optionalText(source?.sourceByline, 240) ?? void 0,
32521
- publisher: optionalText(source?.publisher, 240) ?? void 0,
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: optionalText(source?.publishedAt, 80) ?? void 0,
32524
- capturedAt: optionalText(source?.capturedAt, 80) ?? void 0,
32525
- license: optionalText(source?.license, 240) ?? void 0,
32526
- rightsSummary: optionalText(source?.rightsSummary, 1e3) ?? void 0,
32527
- contentHash: optionalText(source?.contentHash, 200) ?? void 0
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: optionalText(seo?.canonicalUrl, 2e3) ?? void 0,
32533
- relCanonical: optionalText(seo?.relCanonical, 2e3) ?? void 0,
32534
- metaTitle: optionalText(seo?.metaTitle, 240) ?? void 0,
32535
- metaDescription: optionalText(seo?.metaDescription, 500) ?? void 0,
32536
- ogImage: optionalText(seo?.ogImage, 2e3) ?? void 0,
32537
- schemaOrgType: optionalText(seo?.schemaOrgType, 80) ?? void 0,
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: optionalText(item.relationship, 120) ?? void 0,
32913
+ relationship: optionalText2(item.relationship, 120) ?? void 0,
32547
32914
  slug: item.slug ? normalizeSlug(item.slug) : void 0,
32548
- url: optionalText(item.url, 2e3) ?? void 0,
32549
- description: optionalText(item.description, 300) ?? void 0
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: optionalText(filters.query, 300) ?? void 0,
32921
+ query: optionalText2(filters.query, 300) ?? void 0,
32555
32922
  entityType: filters.entityType ? normalizeEntityType(filters.entityType) : void 0,
32556
- tag: optionalText(filters.tag, 80) ?? void 0,
32923
+ tag: optionalText2(filters.tag, 80) ?? void 0,
32557
32924
  tags: uniqueStrings(filters.tags ?? []).slice(0, 20),
32558
- keyword: optionalText(filters.keyword, 120) ?? void 0,
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: optionalText(filters.sourceDomain, 240) ?? void 0,
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: optionalText(filters.publishedAfter, 80) ?? void 0,
32566
- updatedAfter: optionalText(filters.updatedAfter, 80) ?? void 0,
32567
- filterId: optionalText(filters.filterId, 200) ?? void 0,
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: optionalText(filters.query, 300) ?? void 0,
32941
+ query: optionalText2(filters.query, 300) ?? void 0,
32575
32942
  entityType: filters.entityType ? normalizeEntityType(filters.entityType) : void 0,
32576
- tag: optionalText(filters.tag, 80) ?? void 0,
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 optionalText(input.actorLabel, 120) || optionalText(user.name, 120) || `mcp-user-${user.id}`;
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 = optionalText(value, 80);
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 = optionalText(value, 120) || DEFAULT_ENTITY_TYPE;
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 optionalText(value, max) {
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 = optionalText(value, 120);
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 createHash13, randomUUID as randomUUID16 } from "crypto";
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
- createHash13("sha256").update(html).digest("hex"),
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 createHash15 } from "crypto";
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 createHash14,
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 = createHash14("sha256").update(state).digest("hex");
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 = createHash14("sha256").update(input.state).digest("hex");
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 = createHash15("sha256").update(identitySeed).digest("hex").slice(0, 12);
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: createHash15("sha256").update(email).digest("hex") } : {},
34813
+ ...email ? { emailSha256: createHash16("sha256").update(email).digest("hex") } : {},
34410
34814
  ...phone ? {
34411
- phoneSha256: createHash15("sha256").update(phone.replace(/\D/g, "")).digest("hex")
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 = createHash15("sha256").update(
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 createHash16 } from "crypto";
35677
+ import { createHash as createHash17 } from "crypto";
35274
35678
  function scheduledArtifactOwnerIdForApiKey(apiKey) {
35275
- return createHash16("sha256").update(apiKey).digest("hex").slice(0, 24);
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 createHash17, randomBytes as randomBytes4, randomUUID as randomUUID17 } from "crypto";
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 createHash17("sha256").update(token4).digest("hex");
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 createHash18 } from "crypto";
35824
+ import { createHash as createHash19 } from "crypto";
35421
35825
  function escapeHtml7(value) {
35422
35826
  return value.replace(/[&<>"']/g, (character) => ({
35423
35827
  "&": "&amp;",
@@ -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: createHash18("sha256").update(html).digest("hex"),
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 createHash19 } from "crypto";
35890
+ import { createHash as createHash20 } from "crypto";
35487
35891
  function escapeHtml8(value) {
35488
35892
  return value.replace(/[&<>"']/g, (character) => ({
35489
35893
  "&": "&amp;",
@@ -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 = createHash19("sha256").update(html).digest("hex");
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 createHash20 } from "crypto";
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-${createHash20("sha256").update(runId).digest("hex").slice(0, 32)}`;
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 createHash21, createHmac as createHmac4, timingSafeEqual as timingSafeEqual3 } from "crypto";
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 = createHash21("sha256").update(args.body).digest("hex");
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 createHash22 } from "crypto";
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 createHash22("sha256").update(value).digest("hex");
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 createHash23 } from "crypto";
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-${createHash23("sha256").update(`${userId}\0${vault}\0${input.sourceKind}\0${input.sourceUrl}\0${input.imageUrl ?? ""}\0${input.imageBase64 ?? ""}`).digest("hex")}`;
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 createHash24 } from "crypto";
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 createHash24("sha256").update(value).digest("hex");
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 createHash26, randomUUID as randomUUID22 } from "crypto";
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 createHash25, randomUUID as randomUUID21 } from "crypto";
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 = createHash25("sha256").update(JSON.stringify(tools.map((tool) => ({ name: tool.name, inputSchema: tool.inputSchema })))).digest("hex");
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:${createHash25("sha256").update(args.identity.toLowerCase()).update("\0").update(connection.id).update("\0").update(args.tool).update("\0").update(requestId).digest("hex")}`;
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 : createHash25("sha256").update(requestId).digest("hex"),
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: createHash25("sha256").update(JSON.stringify(projected)).digest("hex"),
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:${createHash26("sha256").update(identity).update("\0").update(idempotencyKey3?.trim() || randomUUID22()).digest("hex")}`;
39753
- const requestDigest = createHash26("sha256").update(connectionId).update("\0").update(tool?.trim() ?? "").update("\0").update(canonicalJson2(input)).digest("hex");
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 createHash26("sha256").update(canonicalJson2(tool)).digest("hex");
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 createHash27 } from "crypto";
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:${createHash27("sha256").update(identity).update("\0").update(idempotencyKey3.trim()).digest("hex")}`;
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-EVTCL3KB.js.map
44170
+ //# sourceMappingURL=server-JE7SLZLJ.js.map