@happyvertical/smrt-content 0.36.1 → 0.36.3

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.
Files changed (86) hide show
  1. package/dist/asset-associable.d.ts +2 -2
  2. package/dist/asset-associable.d.ts.map +1 -1
  3. package/dist/body-format.d.ts +18 -3
  4. package/dist/body-format.d.ts.map +1 -1
  5. package/dist/body-format.js.map +1 -1
  6. package/dist/content-contribution-attachment.d.ts +4 -4
  7. package/dist/content-contribution-attachment.d.ts.map +1 -1
  8. package/dist/content-contribution-config.d.ts +1 -1
  9. package/dist/content-contribution-config.d.ts.map +1 -1
  10. package/dist/content-contribution-revision.d.ts +4 -4
  11. package/dist/content-contribution-revision.d.ts.map +1 -1
  12. package/dist/content-contribution-type.d.ts +5 -5
  13. package/dist/content-contribution-type.d.ts.map +1 -1
  14. package/dist/content-contribution.d.ts +7 -7
  15. package/dist/content-contribution.d.ts.map +1 -1
  16. package/dist/content-contributions.d.ts +24 -2
  17. package/dist/content-contributions.d.ts.map +1 -1
  18. package/dist/content-contributor.d.ts +5 -5
  19. package/dist/content-contributor.d.ts.map +1 -1
  20. package/dist/content-correction.d.ts +2 -2
  21. package/dist/content-correction.d.ts.map +1 -1
  22. package/dist/content-feed-parser.d.ts.map +1 -1
  23. package/dist/content-feed-source.d.ts +5 -5
  24. package/dist/content-feed-source.d.ts.map +1 -1
  25. package/dist/content-governance-assignment.d.ts +2 -2
  26. package/dist/content-governance-assignment.d.ts.map +1 -1
  27. package/dist/content-governance-policy.d.ts +2 -2
  28. package/dist/content-governance-policy.d.ts.map +1 -1
  29. package/dist/content-governance-profile.d.ts +2 -2
  30. package/dist/content-governance-profile.d.ts.map +1 -1
  31. package/dist/content-governance.d.ts +7 -7
  32. package/dist/content-governance.d.ts.map +1 -1
  33. package/dist/content-review.d.ts +2 -2
  34. package/dist/content-review.d.ts.map +1 -1
  35. package/dist/content-reviews.d.ts +1 -1
  36. package/dist/content-reviews.d.ts.map +1 -1
  37. package/dist/content-transparency.d.ts +38 -7
  38. package/dist/content-transparency.d.ts.map +1 -1
  39. package/dist/content-types.d.ts +1 -1
  40. package/dist/content-types.d.ts.map +1 -1
  41. package/dist/content-version.d.ts +17 -4
  42. package/dist/content-version.d.ts.map +1 -1
  43. package/dist/content-versions.d.ts.map +1 -1
  44. package/dist/content.d.ts +40 -36
  45. package/dist/content.d.ts.map +1 -1
  46. package/dist/contents.d.ts +46 -31
  47. package/dist/contents.d.ts.map +1 -1
  48. package/dist/index.js +224 -118
  49. package/dist/index.js.map +1 -1
  50. package/dist/manifest.json +40 -40
  51. package/dist/serialization.d.ts +66 -49
  52. package/dist/serialization.d.ts.map +1 -1
  53. package/dist/smrt-knowledge.json +4 -4
  54. package/dist/svelte/components/ContentAgentChat.svelte +42 -24
  55. package/dist/svelte/components/ContentAgentChat.svelte.d.ts.map +1 -1
  56. package/dist/svelte/components/ContentBodyEditor.svelte +8 -3
  57. package/dist/svelte/components/ContentBodyEditor.svelte.d.ts +3 -3
  58. package/dist/svelte/components/ContentBodyEditor.svelte.d.ts.map +1 -1
  59. package/dist/svelte/components/ContentClaimAuditTool.svelte +6 -6
  60. package/dist/svelte/components/ContentCorrectionsTool.svelte +4 -4
  61. package/dist/svelte/components/ContentEditor.svelte +69 -30
  62. package/dist/svelte/components/ContentEditor.svelte.d.ts +6 -3
  63. package/dist/svelte/components/ContentEditor.svelte.d.ts.map +1 -1
  64. package/dist/svelte/components/ContentGovernanceManager.svelte +4 -2
  65. package/dist/svelte/components/ContentGovernanceManager.svelte.d.ts.map +1 -1
  66. package/dist/svelte/components/ContentGovernancePanel.svelte +21 -21
  67. package/dist/svelte/components/ContentList.svelte +20 -17
  68. package/dist/svelte/components/ContentList.svelte.d.ts +8 -7
  69. package/dist/svelte/components/ContentList.svelte.d.ts.map +1 -1
  70. package/dist/svelte/components/ContentMetadataFields.svelte +10 -1
  71. package/dist/svelte/components/ContentMetadataFields.svelte.d.ts +9 -1
  72. package/dist/svelte/components/ContentMetadataFields.svelte.d.ts.map +1 -1
  73. package/dist/svelte/components/ContentStatusFields.svelte +9 -1
  74. package/dist/svelte/components/ContentStatusFields.svelte.d.ts +8 -1
  75. package/dist/svelte/components/ContentStatusFields.svelte.d.ts.map +1 -1
  76. package/dist/svelte/components/ContentTransparencyTool.svelte +4 -2
  77. package/dist/svelte/components/ContentTransparencyTool.svelte.d.ts.map +1 -1
  78. package/dist/svelte/components/ContentVersionsTool.svelte +6 -6
  79. package/dist/svelte/components/GovernedContentEditor.svelte +8 -2
  80. package/dist/svelte/components/GovernedContentEditor.svelte.d.ts.map +1 -1
  81. package/dist/svelte/routes/ContentContributionsRoute.svelte +11 -10
  82. package/dist/svelte/routes/ContentContributionsRoute.svelte.d.ts.map +1 -1
  83. package/dist/svelte/routes/ContentFactsRoute.svelte +2 -2
  84. package/dist/svelte/routes/ContentWorkspaceRoute.svelte +6 -6
  85. package/dist/thumbnail-generator.d.ts.map +1 -1
  86. package/package.json +14 -14
package/dist/index.js CHANGED
@@ -300,6 +300,15 @@ function getRowTenantId(row) {
300
300
  const value = row.tenantId ?? row.tenant_id ?? null;
301
301
  return typeof value === "string" && value.length > 0 ? value : null;
302
302
  }
303
+ function getRowString(row, ...keys) {
304
+ for (const key of keys) {
305
+ const value = row[key];
306
+ if (typeof value === "string" && value.length > 0) {
307
+ return value;
308
+ }
309
+ }
310
+ return null;
311
+ }
303
312
  function safeParseJSONObject$1(value) {
304
313
  if (!value) {
305
314
  return {};
@@ -377,10 +386,24 @@ function mapPersistedAssignmentRow(row) {
377
386
  enabled: row.enabled !== false && row.enabled !== 0,
378
387
  factLinkingEnabled: row.factLinkingEnabled === true || row.fact_linking_enabled === true || row.fact_linking_enabled === 1,
379
388
  transparencyEnabled: row.transparencyEnabled === true || row.transparency_enabled === true || row.transparency_enabled === 1,
380
- publicationProfileKey: row.publicationProfileKey || row.publication_profile_key || null,
381
- correctionProfileKey: row.correctionProfileKey || row.correction_profile_key || null,
389
+ publicationProfileKey: getRowString(
390
+ row,
391
+ "publicationProfileKey",
392
+ "publication_profile_key"
393
+ ),
394
+ correctionProfileKey: getRowString(
395
+ row,
396
+ "correctionProfileKey",
397
+ "correction_profile_key"
398
+ ),
382
399
  enforcePublishReadiness: row.enforcePublishReadiness === true || row.enforce_publish_readiness === true || row.enforce_publish_readiness === 1,
383
- defaultFactRelationship: row.defaultFactRelationship || row.default_fact_relationship || DEFAULT_FACT_RELATIONSHIP,
400
+ // The relationship is stored as a string; trust the persisted value and
401
+ // fall back to the default when absent.
402
+ defaultFactRelationship: getRowString(
403
+ row,
404
+ "defaultFactRelationship",
405
+ "default_fact_relationship"
406
+ ) || DEFAULT_FACT_RELATIONSHIP,
384
407
  metadata: safeParseJSONObject$1(row.metadata)
385
408
  })
386
409
  };
@@ -400,24 +423,19 @@ async function loadPersistedContentGovernanceDefinitions(options = {}) {
400
423
  db.list("content_governance_profiles", {}),
401
424
  db.list("content_governance_assignments", {})
402
425
  ]);
403
- policyRows.sort(
404
- (a, b) => String(a.created_at || a.createdAt || "").localeCompare(
405
- String(b.created_at || b.createdAt || "")
406
- )
407
- );
408
- profileRows.sort(
409
- (a, b) => String(a.created_at || a.createdAt || "").localeCompare(
410
- String(b.created_at || b.createdAt || "")
411
- )
412
- );
413
- assignmentRows.sort(
414
- (a, b) => String(a.created_at || a.createdAt || "").localeCompare(
415
- String(b.created_at || b.createdAt || "")
416
- )
426
+ const byCreatedAt = (a, b) => String(a.created_at || a.createdAt || "").localeCompare(
427
+ String(b.created_at || b.createdAt || "")
417
428
  );
429
+ policyRows.sort(byCreatedAt);
430
+ profileRows.sort(byCreatedAt);
431
+ assignmentRows.sort(byCreatedAt);
418
432
  return {
419
- policies: policyRows.map((row) => mapPersistedPolicyRow(row)),
420
- profiles: profileRows.map((row) => mapPersistedProfileRow(row)),
433
+ policies: policyRows.map(
434
+ (row) => mapPersistedPolicyRow(row)
435
+ ),
436
+ profiles: profileRows.map(
437
+ (row) => mapPersistedProfileRow(row)
438
+ ),
421
439
  assignments: assignmentRows.map(
422
440
  (row) => mapPersistedAssignmentRow(row)
423
441
  )
@@ -658,15 +676,18 @@ function parseContentReviewResponse(raw) {
658
676
  if (jsonCandidate) {
659
677
  try {
660
678
  const parsed = JSON.parse(jsonCandidate);
661
- const findings = Array.isArray(parsed.findings) ? parsed.findings.map((finding) => ({
662
- severity: normalizeSeverity(finding?.severity),
663
- title: String(finding?.title || "Review finding"),
664
- detail: String(finding?.detail || ""),
665
- factId: typeof finding?.factId === "string" ? finding.factId : void 0,
666
- quote: typeof finding?.quote === "string" ? finding.quote : void 0,
667
- suggestedChange: typeof finding?.suggestedChange === "string" ? finding.suggestedChange : void 0,
668
- ruleId: typeof finding?.ruleId === "string" ? finding.ruleId : void 0
669
- })) : [];
679
+ const findings = Array.isArray(parsed.findings) ? parsed.findings.map((rawFinding) => {
680
+ const finding = rawFinding && typeof rawFinding === "object" ? rawFinding : {};
681
+ return {
682
+ severity: normalizeSeverity(finding.severity),
683
+ title: String(finding.title || "Review finding"),
684
+ detail: String(finding.detail || ""),
685
+ factId: typeof finding.factId === "string" ? finding.factId : void 0,
686
+ quote: typeof finding.quote === "string" ? finding.quote : void 0,
687
+ suggestedChange: typeof finding.suggestedChange === "string" ? finding.suggestedChange : void 0,
688
+ ruleId: typeof finding.ruleId === "string" ? finding.ruleId : void 0
689
+ };
690
+ }) : [];
670
691
  return {
671
692
  status: normalizeStatus$1(parsed.status),
672
693
  summary: String(parsed.summary || normalizedRaw || "Review completed"),
@@ -991,7 +1012,9 @@ function normalizeContentTransparency(value, defaults = {}) {
991
1012
  otherExtractedFacts,
992
1013
  references,
993
1014
  reviews: asArray$1(snapshot.reviews),
994
- reviewProfiles: asArray$1(snapshot.reviewProfiles),
1015
+ reviewProfiles: asArray$1(
1016
+ snapshot.reviewProfiles
1017
+ ),
995
1018
  corrections: asArray$1(snapshot.corrections),
996
1019
  versionHistory: asArray$1(snapshot.versionHistory).map(
997
1020
  normalizeVersionHistoryItem
@@ -1007,72 +1030,87 @@ function isMissingTableError(error, tableName) {
1007
1030
  function getQueryRows(result) {
1008
1031
  return Array.isArray(result) ? result : Array.isArray(result?.rows) ? result.rows ?? [] : [];
1009
1032
  }
1033
+ function asModel(value) {
1034
+ return value && typeof value === "object" ? value : {};
1035
+ }
1010
1036
  function toJSON(value) {
1011
- if (value && typeof value.toJSON === "function") {
1012
- const serialized = value.toJSON();
1037
+ const model = asModel(value);
1038
+ if (typeof model.toJSON === "function") {
1039
+ const serialized = model.toJSON();
1013
1040
  return serialized && typeof serialized === "object" ? serialized : {};
1014
1041
  }
1015
1042
  return value && typeof value === "object" ? value : {};
1016
1043
  }
1017
1044
  function serializeFact(fact) {
1045
+ const model = asModel(fact);
1018
1046
  const data = toJSON(fact);
1019
1047
  return {
1020
1048
  ...data,
1021
- metadata: typeof fact?.getMetadata === "function" ? fact.getMetadata() : data.metadata || {}
1049
+ metadata: typeof model.getMetadata === "function" ? model.getMetadata() : data.metadata || {}
1022
1050
  };
1023
1051
  }
1024
1052
  function serializeFactLink(link) {
1053
+ const model = asModel(link);
1025
1054
  const data = toJSON(link);
1026
1055
  return {
1027
1056
  ...data,
1028
- metadata: typeof link?.getMetadata === "function" ? link.getMetadata() : data.metadata || {}
1057
+ metadata: typeof model.getMetadata === "function" ? model.getMetadata() : data.metadata || {}
1029
1058
  };
1030
1059
  }
1031
1060
  function serializeContentVersion(version) {
1061
+ const model = asModel(version);
1032
1062
  const data = toJSON(version);
1033
1063
  return {
1034
1064
  ...data,
1035
- snapshot: typeof version?.getSnapshot === "function" ? version.getSnapshot() : data.snapshot || {},
1036
- metadata: typeof version?.getMetadata === "function" ? version.getMetadata() : data.metadata || {}
1065
+ snapshot: typeof model.getSnapshot === "function" ? model.getSnapshot() : data.snapshot || {},
1066
+ metadata: typeof model.getMetadata === "function" ? model.getMetadata() : data.metadata || {}
1037
1067
  };
1038
1068
  }
1039
1069
  function serializeContentReview(review) {
1070
+ const model = asModel(review);
1040
1071
  const data = toJSON(review);
1041
1072
  return {
1042
1073
  ...data,
1043
- findings: typeof review?.getFindings === "function" ? review.getFindings() : data.findings || [],
1044
- metadata: typeof review?.getMetadata === "function" ? review.getMetadata() : data.metadata || {}
1074
+ findings: typeof model.getFindings === "function" ? model.getFindings() : data.findings || [],
1075
+ metadata: typeof model.getMetadata === "function" ? model.getMetadata() : data.metadata || {}
1045
1076
  };
1046
1077
  }
1047
1078
  function serializeContentCorrection(correction) {
1079
+ const model = asModel(correction);
1048
1080
  const data = toJSON(correction);
1049
1081
  return {
1050
1082
  ...data,
1051
- metadata: typeof correction?.getMetadata === "function" ? correction.getMetadata() : data.metadata || {}
1083
+ metadata: typeof model.getMetadata === "function" ? model.getMetadata() : data.metadata || {}
1052
1084
  };
1053
1085
  }
1054
1086
  async function serializeContent(content) {
1087
+ const model = asModel(content);
1055
1088
  const [references, assets] = await Promise.all([
1056
- typeof content?.getReferences === "function" ? content.getReferences() : [],
1057
- typeof content?.getAssets === "function" ? content.getAssets() : []
1089
+ typeof model.getReferences === "function" ? model.getReferences() : [],
1090
+ typeof model.getAssets === "function" ? model.getAssets() : []
1058
1091
  ]);
1059
- const drift = references.length > 0 && typeof content?.getReferenceDrift === "function" ? await content.getReferenceDrift() : [];
1092
+ const drift = references.length > 0 && typeof model.getReferenceDrift === "function" ? await model.getReferenceDrift() : [];
1060
1093
  const driftByTargetId = new Map(
1061
- Array.isArray(drift) ? drift.filter((entry) => entry && typeof entry.targetId === "string").map((entry) => [
1062
- entry.targetId,
1063
- {
1064
- citedVersion: entry.citedVersion ?? null,
1065
- currentVersion: entry.currentVersion ?? null,
1066
- isDrifted: Boolean(entry.isDrifted)
1067
- }
1068
- ]) : []
1094
+ Array.isArray(drift) ? drift.map((entry) => asModel(entry)).filter(
1095
+ (entry) => typeof entry.targetId === "string"
1096
+ ).map((entry) => {
1097
+ const edge = entry;
1098
+ return [
1099
+ edge.targetId,
1100
+ {
1101
+ citedVersion: edge.citedVersion ?? null,
1102
+ currentVersion: edge.currentVersion ?? null,
1103
+ isDrifted: Boolean(edge.isDrifted)
1104
+ }
1105
+ ];
1106
+ }) : []
1069
1107
  );
1070
1108
  return {
1071
1109
  ...toJSON(content),
1072
- referenceIds: references.map((reference) => reference?.id).filter(Boolean),
1110
+ referenceIds: references.map((reference) => asModel(reference)).map((reference) => reference.id).filter(Boolean),
1073
1111
  references: references.map((reference) => {
1074
1112
  const base = toJSON(reference);
1075
- const edge = base?.id ? driftByTargetId.get(base.id) : null;
1113
+ const edge = typeof base.id === "string" ? driftByTargetId.get(base.id) : null;
1076
1114
  return edge ? {
1077
1115
  ...base,
1078
1116
  citedVersion: edge.citedVersion,
@@ -1080,7 +1118,7 @@ async function serializeContent(content) {
1080
1118
  isDrifted: edge.isDrifted
1081
1119
  } : base;
1082
1120
  }),
1083
- assetIds: assets.map((asset) => asset?.id).filter(Boolean),
1121
+ assetIds: assets.map((asset) => asModel(asset).id).filter(Boolean),
1084
1122
  assets: assets.map((asset) => toJSON(asset))
1085
1123
  };
1086
1124
  }
@@ -1113,6 +1151,8 @@ class ThumbnailGenerator {
1113
1151
  return this.generateWithAI(options);
1114
1152
  default:
1115
1153
  throw new Error(
1154
+ // `options` is narrowed to `never` here (exhaustive switch); read the
1155
+ // runtime discriminant through a minimal structural view.
1116
1156
  `Unknown thumbnail strategy: ${options.strategy}`
1117
1157
  );
1118
1158
  }
@@ -1142,8 +1182,9 @@ class ThumbnailGenerator {
1142
1182
  * Generate a static map thumbnail
1143
1183
  */
1144
1184
  async generateStaticMap(options) {
1145
- const rawLatitude = this.content.metadata?.latitude ?? this.content.metadata?.lat;
1146
- const rawLongitude = this.content.metadata?.longitude ?? this.content.metadata?.lng ?? this.content.metadata?.lon;
1185
+ const coordinateMetadata = this.content.metadata;
1186
+ const rawLatitude = coordinateMetadata?.latitude ?? coordinateMetadata?.lat;
1187
+ const rawLongitude = coordinateMetadata?.longitude ?? coordinateMetadata?.lng ?? coordinateMetadata?.lon;
1147
1188
  if (rawLatitude == null || rawLongitude == null) {
1148
1189
  throw new Error(
1149
1190
  "Content metadata must contain latitude and longitude for static-map strategy"
@@ -1336,6 +1377,15 @@ function createFingerprint(value) {
1336
1377
  function normalizeAuditText(value) {
1337
1378
  return String(value ?? "").trim().replace(/\s+/g, " ");
1338
1379
  }
1380
+ function errorMessage(error) {
1381
+ if (error instanceof Error) {
1382
+ return error.message;
1383
+ }
1384
+ if (error && typeof error === "object" && "message" in error && typeof error.message === "string") {
1385
+ return error.message;
1386
+ }
1387
+ return String(error);
1388
+ }
1339
1389
  function createFactAuditRunId(contentId) {
1340
1390
  return `fact-audit-${hashFingerprint(
1341
1391
  `${contentId}:${(/* @__PURE__ */ new Date()).toISOString()}:${Math.random()}`
@@ -1361,8 +1411,9 @@ function getGeneratedFactAuditMetadata(link) {
1361
1411
  if (metadata.generatedBy === FACT_AUDIT_GENERATED_BY) {
1362
1412
  return metadata;
1363
1413
  }
1364
- if (metadata.factAudit && typeof metadata.factAudit === "object" && metadata.factAudit.generatedBy === FACT_AUDIT_GENERATED_BY) {
1365
- return metadata.factAudit;
1414
+ const nested = metadata.factAudit;
1415
+ if (nested && typeof nested === "object" && nested.generatedBy === FACT_AUDIT_GENERATED_BY) {
1416
+ return nested;
1366
1417
  }
1367
1418
  return null;
1368
1419
  }
@@ -1406,8 +1457,42 @@ function filterAuditSources(sources, selectors) {
1406
1457
  function getContentText(content) {
1407
1458
  return [content.title, content.description, content.body].map(normalizeAuditText).filter(Boolean).join("\n\n");
1408
1459
  }
1460
+ function readNestedString(source, path2) {
1461
+ let current = source;
1462
+ for (const key of path2) {
1463
+ if (!current || typeof current !== "object") {
1464
+ return null;
1465
+ }
1466
+ current = current[key];
1467
+ }
1468
+ return typeof current === "string" && current ? current : null;
1469
+ }
1470
+ function asRecord(value) {
1471
+ if (value && typeof value === "object" && !Array.isArray(value)) {
1472
+ return value;
1473
+ }
1474
+ if (typeof value === "string") {
1475
+ try {
1476
+ const parsed = JSON.parse(value);
1477
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
1478
+ } catch {
1479
+ return {};
1480
+ }
1481
+ }
1482
+ return {};
1483
+ }
1484
+ function readNestedRecord(source, path2) {
1485
+ let current = source;
1486
+ for (const key of path2) {
1487
+ if (!current || typeof current !== "object") {
1488
+ return {};
1489
+ }
1490
+ current = current[key];
1491
+ }
1492
+ return asRecord(current);
1493
+ }
1409
1494
  function getPublicPrompt(metadata) {
1410
- return metadata?.transparency?.generation?.publicPrompt || metadata?.generation?.publicPrompt || metadata?.publicPrompt || null;
1495
+ return readNestedString(metadata, ["transparency", "generation", "publicPrompt"]) || readNestedString(metadata, ["generation", "publicPrompt"]) || readNestedString(metadata, ["publicPrompt"]) || null;
1411
1496
  }
1412
1497
  let Content = class extends SmrtObject {
1413
1498
  tenantId = null;
@@ -1517,11 +1602,12 @@ let Content = class extends SmrtObject {
1517
1602
  this.state = options.state || "active";
1518
1603
  this.metadata = options.metadata || {};
1519
1604
  this.thumbnailAssetId = options.thumbnailAssetId ?? null;
1605
+ const transient = this;
1520
1606
  if (Array.isArray(options.referenceIds)) {
1521
- this.referenceIds = [...options.referenceIds];
1607
+ transient.referenceIds = [...options.referenceIds];
1522
1608
  }
1523
1609
  if (Array.isArray(options.assetIds)) {
1524
- this.assetIds = [...options.assetIds];
1610
+ transient.assetIds = [...options.assetIds];
1525
1611
  }
1526
1612
  }
1527
1613
  /**
@@ -1863,15 +1949,15 @@ let Content = class extends SmrtObject {
1863
1949
  }
1864
1950
  }
1865
1951
  }
1866
- const extractedFactRecords = [...extractedFacts.values()].map(
1867
- (fact) => {
1868
- const factId = fact.id;
1869
- return {
1870
- ...serializeFact(fact),
1871
- usedInArticle: factId ? usedFactIds.has(factId) : false
1872
- };
1873
- }
1874
- );
1952
+ const extractedFactRecords = [
1953
+ ...extractedFacts.values()
1954
+ ].map((fact) => {
1955
+ const factId = fact.id;
1956
+ return {
1957
+ ...serializeFact(fact),
1958
+ usedInArticle: factId ? usedFactIds.has(factId) : false
1959
+ };
1960
+ });
1875
1961
  return {
1876
1962
  id: reference.id || null,
1877
1963
  title: reference.title || reference.name || reference.url || null,
@@ -1884,10 +1970,13 @@ let Content = class extends SmrtObject {
1884
1970
  };
1885
1971
  })
1886
1972
  );
1887
- const publicGeneration = this.metadata?.transparency?.generation ?? {};
1888
- const generationMetadata = this.metadata?.generation ?? {};
1973
+ const publicGeneration = readNestedRecord(this.metadata, [
1974
+ "transparency",
1975
+ "generation"
1976
+ ]);
1977
+ const generationMetadata = readNestedRecord(this.metadata, ["generation"]);
1889
1978
  const serializedCorrections = corrections.filter((correction) => correction.status === "published").map((correction) => {
1890
- const correctionMetadata = typeof correction?.getMetadata === "function" ? correction.getMetadata() : correction.metadata || {};
1979
+ const correctionMetadata = asRecord(correction.metadata);
1891
1980
  return {
1892
1981
  ...serializeContentCorrection(correction),
1893
1982
  provenance: {
@@ -1899,26 +1988,28 @@ let Content = class extends SmrtObject {
1899
1988
  }
1900
1989
  };
1901
1990
  });
1902
- const serializedVersionHistory = versions.map((version) => {
1903
- const versionMetadata = typeof version?.getMetadata === "function" ? version.getMetadata() : version.metadata || {};
1904
- return {
1905
- id: version.id || null,
1906
- version: version.version ?? null,
1907
- kind: version.kind || null,
1908
- summary: version.summary || "",
1909
- createdAt: version.createdAt || null,
1910
- provenance: {
1911
- policyKey: versionMetadata.policyKey || null,
1912
- reviewFingerprint: versionMetadata.reviewFingerprint || versionMetadata.contentFingerprint || null,
1913
- factId: versionMetadata.factId || null,
1914
- replacementFactId: versionMetadata.replacementFactId || null,
1915
- sourceCorrectionVersionId: versionMetadata.sourceCorrectionVersionId || null,
1916
- sourceCorrectionVersionNumber: versionMetadata.sourceCorrectionVersionNumber || null,
1917
- correctionDraft: versionMetadata.correctionDraft || null,
1918
- publicationSnapshotFingerprint: versionMetadata.publicationSnapshotFingerprint || null
1919
- }
1920
- };
1921
- });
1991
+ const serializedVersionHistory = versions.map(
1992
+ (version) => {
1993
+ const versionMetadata = asRecord(version.metadata);
1994
+ return {
1995
+ id: version.id || null,
1996
+ version: version.version ?? null,
1997
+ kind: version.kind || null,
1998
+ summary: version.summary || "",
1999
+ createdAt: version.createdAt || null,
2000
+ provenance: {
2001
+ policyKey: versionMetadata.policyKey || null,
2002
+ reviewFingerprint: versionMetadata.reviewFingerprint || versionMetadata.contentFingerprint || null,
2003
+ factId: versionMetadata.factId || null,
2004
+ replacementFactId: versionMetadata.replacementFactId || null,
2005
+ sourceCorrectionVersionId: versionMetadata.sourceCorrectionVersionId || null,
2006
+ sourceCorrectionVersionNumber: versionMetadata.sourceCorrectionVersionNumber || null,
2007
+ correctionDraft: versionMetadata.correctionDraft || null,
2008
+ publicationSnapshotFingerprint: versionMetadata.publicationSnapshotFingerprint || null
2009
+ }
2010
+ };
2011
+ }
2012
+ );
1922
2013
  return normalizeContentTransparency(
1923
2014
  {
1924
2015
  generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
@@ -2015,9 +2106,7 @@ let Content = class extends SmrtObject {
2015
2106
  factId: link.factId || null,
2016
2107
  relationship: link.relationship || null,
2017
2108
  metadata: typeof link?.getMetadata === "function" ? link.getMetadata() : {}
2018
- })).sort(
2019
- (a, b) => String(a.factId).localeCompare(String(b.factId))
2020
- )
2109
+ })).sort((a, b) => String(a.factId).localeCompare(String(b.factId)))
2021
2110
  });
2022
2111
  }
2023
2112
  async getLatestPublicationSnapshotFingerprint() {
@@ -2075,7 +2164,7 @@ let Content = class extends SmrtObject {
2075
2164
  metadata: {
2076
2165
  ...this.metadata || {},
2077
2166
  governance: {
2078
- ...this.metadata?.governance || {},
2167
+ ...asRecord(this.metadata.governance),
2079
2168
  correctionDraft: {
2080
2169
  summary: options.summary,
2081
2170
  incorrectText,
@@ -2494,7 +2583,8 @@ let Content = class extends SmrtObject {
2494
2583
  for (const reference of references) {
2495
2584
  const referenceId = reference.id || "";
2496
2585
  const text = getContentText(reference);
2497
- const sourceUrl = normalizeAuditText(reference.url) || normalizeAuditText(reference.sourceUrl) || normalizeAuditText(reference.fileKey);
2586
+ const referenceSourceUrl = reference.sourceUrl;
2587
+ const sourceUrl = normalizeAuditText(reference.url) || normalizeAuditText(referenceSourceUrl) || normalizeAuditText(reference.fileKey);
2498
2588
  const sourceTitle = normalizeAuditText(reference.title) || normalizeAuditText(reference.name) || sourceUrl || referenceId;
2499
2589
  if (!text) {
2500
2590
  warnings.push(
@@ -2578,7 +2668,7 @@ let Content = class extends SmrtObject {
2578
2668
  existing.setMetadata?.({
2579
2669
  ...existingMetadata,
2580
2670
  factAudit: {
2581
- ...existingMetadata.factAudit && typeof existingMetadata.factAudit === "object" ? existingMetadata.factAudit : {},
2671
+ ...asRecord(existingMetadata.factAudit),
2582
2672
  ...metadata
2583
2673
  }
2584
2674
  });
@@ -2598,9 +2688,10 @@ let Content = class extends SmrtObject {
2598
2688
  ]);
2599
2689
  for (const link of links) {
2600
2690
  const metadata = getLinkMetadata(link);
2691
+ const nestedFactAudit = asRecord(metadata.factAudit);
2601
2692
  if (metadata.generatedBy === FACT_AUDIT_GENERATED_BY) {
2602
2693
  await link.delete();
2603
- } else if (metadata.factAudit && typeof metadata.factAudit === "object" && metadata.factAudit.generatedBy === FACT_AUDIT_GENERATED_BY) {
2694
+ } else if (metadata.factAudit && typeof metadata.factAudit === "object" && nestedFactAudit.generatedBy === FACT_AUDIT_GENERATED_BY) {
2604
2695
  const { factAudit: _removed, ...preservedMetadata } = metadata;
2605
2696
  link.setMetadata?.(preservedMetadata);
2606
2697
  await link.save();
@@ -2674,7 +2765,7 @@ let Content = class extends SmrtObject {
2674
2765
  });
2675
2766
  } catch (error) {
2676
2767
  warnings.push(
2677
- `Failed to extract facts from ${source.sourceTitle}: ${error.message || error}`
2768
+ `Failed to extract facts from ${source.sourceTitle}: ${errorMessage(error)}`
2678
2769
  );
2679
2770
  continue;
2680
2771
  }
@@ -2842,7 +2933,7 @@ let Content = class extends SmrtObject {
2842
2933
  });
2843
2934
  } catch (error) {
2844
2935
  warnings.push(
2845
- `Failed to extract article claims: ${error.message || error}`
2936
+ `Failed to extract article claims: ${errorMessage(error)}`
2846
2937
  );
2847
2938
  }
2848
2939
  }
@@ -2860,7 +2951,7 @@ let Content = class extends SmrtObject {
2860
2951
  );
2861
2952
  } catch (error) {
2862
2953
  warnings.push(
2863
- `Failed to assess claim "${claim.statement}": ${error.message || error}`
2954
+ `Failed to assess claim "${claim.statement}": ${errorMessage(error)}`
2864
2955
  );
2865
2956
  assessment = {
2866
2957
  status: "needs_review",
@@ -3104,7 +3195,7 @@ let Content = class extends SmrtObject {
3104
3195
  );
3105
3196
  } catch (error) {
3106
3197
  warnings.push(
3107
- `Failed to recheck claim "${claimText}": ${error.message || error}`
3198
+ `Failed to recheck claim "${claimText}": ${errorMessage(error)}`
3108
3199
  );
3109
3200
  assessment = {
3110
3201
  status: "needs_review",
@@ -3338,6 +3429,7 @@ let Content = class extends SmrtObject {
3338
3429
  id: fact.id,
3339
3430
  fact: serializeFact(fact),
3340
3431
  supportStatus: status,
3432
+ // Opaque audit-link metadata values; cast at the read boundary.
3341
3433
  claimQuote: metadata.claimQuote || null,
3342
3434
  rationale: metadata.rationale || null,
3343
3435
  confidence: metadata.confidence ?? null,
@@ -4869,7 +4961,10 @@ function isMissingContributionTypesTableError(error) {
4869
4961
  }
4870
4962
  function mapPersistedTypeRow(row) {
4871
4963
  return {
4872
- id: row.id || null,
4964
+ // `id` is an optional string column; coerce non-string/empty driver
4965
+ // values to undefined so a numeric id can't leak past the `id?: string`
4966
+ // shape (mirrors the getRowString pattern used elsewhere).
4967
+ id: typeof row.id === "string" && row.id ? row.id : void 0,
4873
4968
  key: String(row.key || ""),
4874
4969
  label: String(row.label || row.key || ""),
4875
4970
  enabled: row.enabled !== false && row.enabled !== 0,
@@ -4879,8 +4974,14 @@ function mapPersistedTypeRow(row) {
4879
4974
  allowText: row.allowText === void 0 && row.allow_text === void 0 ? true : row.allowText !== false && row.allow_text !== 0,
4880
4975
  allowFiles: row.allowFiles === true || row.allow_files === true || row.allow_files === 1,
4881
4976
  allowEmptyText: row.allowEmptyText === true || row.allow_empty_text === true || row.allow_empty_text === 1,
4882
- intakeRules: safeParseJSONObject(row.intakeRules || row.intake_rules),
4883
- promotion: safeParseJSONObject(row.promotion || row.promotion_mapping),
4977
+ // Persisted JSON blobs deserialize to the documented intake/promotion
4978
+ // shapes; they are re-normalized structurally by clone* helpers downstream.
4979
+ intakeRules: safeParseJSONObject(
4980
+ row.intakeRules || row.intake_rules
4981
+ ),
4982
+ promotion: safeParseJSONObject(
4983
+ row.promotion || row.promotion_mapping
4984
+ ),
4884
4985
  metadata: safeParseJSONObject(row.metadata),
4885
4986
  tenantId: row.tenantId ?? row.tenant_id ?? null,
4886
4987
  createdAt: row.createdAt || row.created_at || null,
@@ -4910,7 +5011,10 @@ async function loadPersistedContentContributionTypes(options = {}) {
4910
5011
  return [];
4911
5012
  }
4912
5013
  try {
4913
- const rows = await options.db.list("content_contribution_types", {});
5014
+ const rows = await options.db.list(
5015
+ "content_contribution_types",
5016
+ {}
5017
+ );
4914
5018
  rows.sort(
4915
5019
  (a, b) => String(a.created_at || a.createdAt || "").localeCompare(
4916
5020
  String(b.created_at || b.createdAt || "")
@@ -6272,7 +6376,9 @@ let ContentContributions = class extends SmrtCollection {
6272
6376
  }
6273
6377
  async ingestEmailContribution(options) {
6274
6378
  const emailCollection = await this.getEmailCollection();
6275
- const email = await emailCollection.get({ id: options.emailId });
6379
+ const email = await emailCollection.get({
6380
+ id: options.emailId
6381
+ });
6276
6382
  if (!email) {
6277
6383
  throw new Error(`Email "${options.emailId}" not found.`);
6278
6384
  }
@@ -10031,7 +10137,7 @@ let Contents = class extends SmrtCollection {
10031
10137
  });
10032
10138
  return results.map(serializeFact);
10033
10139
  } catch (error) {
10034
- if (error?.code === "DB_SCHEMA_MISSING") {
10140
+ if (typeof error === "object" && error !== null && error.code === "DB_SCHEMA_MISSING") {
10035
10141
  return [];
10036
10142
  }
10037
10143
  throw error;
@@ -10330,13 +10436,13 @@ let Contents = class extends SmrtCollection {
10330
10436
  const image = await content.generateThumbnail(thumbnailOptions);
10331
10437
  generatedImages.push(image);
10332
10438
  } catch (error) {
10333
- const errorMessage = error instanceof Error ? error.message : String(error);
10439
+ const errorMessage2 = error instanceof Error ? error.message : String(error);
10334
10440
  logger.error(
10335
- `Failed to generate thumbnail for content ${content.id}: ${errorMessage}`
10441
+ `Failed to generate thumbnail for content ${content.id}: ${errorMessage2}`
10336
10442
  );
10337
10443
  failed.push({
10338
10444
  contentId: content.id ?? "unknown",
10339
- error: errorMessage
10445
+ error: errorMessage2
10340
10446
  });
10341
10447
  }
10342
10448
  }
@@ -11349,7 +11455,8 @@ class ContentVersionCollection extends SmrtCollection {
11349
11455
  buildSnapshotFactRelationships(snapshot, defaultRelationship) {
11350
11456
  const byRelationship = /* @__PURE__ */ new Map();
11351
11457
  const rawLinks = Array.isArray(snapshot.factLinks) ? snapshot.factLinks : [];
11352
- for (const link of rawLinks) {
11458
+ for (const rawLink of rawLinks) {
11459
+ const link = rawLink;
11353
11460
  const factId = typeof link?.factId === "string" && link.factId.length > 0 ? link.factId : null;
11354
11461
  const relationship = typeof link?.relationship === "string" && link.relationship.length > 0 ? link.relationship : defaultRelationship;
11355
11462
  if (!factId) {
@@ -11511,13 +11618,14 @@ class ContentVersionCollection extends SmrtCollection {
11511
11618
  "metadata",
11512
11619
  "thumbnailAssetId"
11513
11620
  ];
11621
+ const writableContent = content;
11514
11622
  for (const key of keysToRestore) {
11515
11623
  if (snapshot[key] !== void 0) {
11516
- content[key] = snapshot[key];
11624
+ writableContent[key] = snapshot[key];
11517
11625
  }
11518
11626
  }
11519
11627
  const snapshotEdges = Array.isArray(snapshot.referenceEdges) ? snapshot.referenceEdges.filter(
11520
- (edge) => edge && typeof edge.targetId === "string" && edge.targetId.length > 0
11628
+ (edge) => !!edge && typeof edge === "object" && typeof edge.targetId === "string" && edge.targetId.length > 0
11521
11629
  ).map((edge) => ({
11522
11630
  targetId: edge.targetId,
11523
11631
  targetVersion: typeof edge.targetVersion === "number" ? edge.targetVersion : null
@@ -11525,12 +11633,10 @@ class ContentVersionCollection extends SmrtCollection {
11525
11633
  (id) => typeof id === "string" && id.length > 0
11526
11634
  ).map((targetId) => ({ targetId, targetVersion: null })) : [];
11527
11635
  if (Array.isArray(snapshot.referenceEdges) || Array.isArray(snapshot.referenceIds)) {
11528
- content.referenceIds = snapshotEdges.map(
11529
- (edge) => edge.targetId
11530
- );
11636
+ writableContent.referenceIds = snapshotEdges.map((edge) => edge.targetId);
11531
11637
  }
11532
11638
  if (Array.isArray(snapshot.assetIds)) {
11533
- content.assetIds = [...snapshot.assetIds];
11639
+ writableContent.assetIds = [...snapshot.assetIds];
11534
11640
  }
11535
11641
  await content.save();
11536
11642
  if (snapshotEdges.length > 0 && typeof content.getReferences === "function" && typeof content.addReference === "function") {