@happyvertical/smrt-content 0.36.2 → 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.
- package/dist/asset-associable.d.ts +2 -2
- package/dist/asset-associable.d.ts.map +1 -1
- package/dist/body-format.d.ts +18 -3
- package/dist/body-format.d.ts.map +1 -1
- package/dist/body-format.js.map +1 -1
- package/dist/content-contribution-attachment.d.ts +4 -4
- package/dist/content-contribution-attachment.d.ts.map +1 -1
- package/dist/content-contribution-config.d.ts +1 -1
- package/dist/content-contribution-config.d.ts.map +1 -1
- package/dist/content-contribution-revision.d.ts +4 -4
- package/dist/content-contribution-revision.d.ts.map +1 -1
- package/dist/content-contribution-type.d.ts +5 -5
- package/dist/content-contribution-type.d.ts.map +1 -1
- package/dist/content-contribution.d.ts +7 -7
- package/dist/content-contribution.d.ts.map +1 -1
- package/dist/content-contributions.d.ts +24 -2
- package/dist/content-contributions.d.ts.map +1 -1
- package/dist/content-contributor.d.ts +5 -5
- package/dist/content-contributor.d.ts.map +1 -1
- package/dist/content-correction.d.ts +2 -2
- package/dist/content-correction.d.ts.map +1 -1
- package/dist/content-feed-parser.d.ts.map +1 -1
- package/dist/content-feed-source.d.ts +5 -5
- package/dist/content-feed-source.d.ts.map +1 -1
- package/dist/content-governance-assignment.d.ts +2 -2
- package/dist/content-governance-assignment.d.ts.map +1 -1
- package/dist/content-governance-policy.d.ts +2 -2
- package/dist/content-governance-policy.d.ts.map +1 -1
- package/dist/content-governance-profile.d.ts +2 -2
- package/dist/content-governance-profile.d.ts.map +1 -1
- package/dist/content-governance.d.ts +7 -7
- package/dist/content-governance.d.ts.map +1 -1
- package/dist/content-review.d.ts +2 -2
- package/dist/content-review.d.ts.map +1 -1
- package/dist/content-reviews.d.ts +1 -1
- package/dist/content-reviews.d.ts.map +1 -1
- package/dist/content-transparency.d.ts +38 -7
- package/dist/content-transparency.d.ts.map +1 -1
- package/dist/content-types.d.ts +1 -1
- package/dist/content-types.d.ts.map +1 -1
- package/dist/content-version.d.ts +17 -4
- package/dist/content-version.d.ts.map +1 -1
- package/dist/content-versions.d.ts.map +1 -1
- package/dist/content.d.ts +40 -36
- package/dist/content.d.ts.map +1 -1
- package/dist/contents.d.ts +46 -31
- package/dist/contents.d.ts.map +1 -1
- package/dist/index.js +224 -118
- package/dist/index.js.map +1 -1
- package/dist/manifest.json +40 -40
- package/dist/serialization.d.ts +66 -49
- package/dist/serialization.d.ts.map +1 -1
- package/dist/smrt-knowledge.json +4 -4
- package/dist/svelte/components/ContentAgentChat.svelte +42 -24
- package/dist/svelte/components/ContentAgentChat.svelte.d.ts.map +1 -1
- package/dist/svelte/components/ContentBodyEditor.svelte +8 -3
- package/dist/svelte/components/ContentBodyEditor.svelte.d.ts +3 -3
- package/dist/svelte/components/ContentBodyEditor.svelte.d.ts.map +1 -1
- package/dist/svelte/components/ContentClaimAuditTool.svelte +6 -6
- package/dist/svelte/components/ContentCorrectionsTool.svelte +4 -4
- package/dist/svelte/components/ContentEditor.svelte +69 -30
- package/dist/svelte/components/ContentEditor.svelte.d.ts +6 -3
- package/dist/svelte/components/ContentEditor.svelte.d.ts.map +1 -1
- package/dist/svelte/components/ContentGovernanceManager.svelte +4 -2
- package/dist/svelte/components/ContentGovernanceManager.svelte.d.ts.map +1 -1
- package/dist/svelte/components/ContentGovernancePanel.svelte +21 -21
- package/dist/svelte/components/ContentList.svelte +20 -17
- package/dist/svelte/components/ContentList.svelte.d.ts +8 -7
- package/dist/svelte/components/ContentList.svelte.d.ts.map +1 -1
- package/dist/svelte/components/ContentMetadataFields.svelte +10 -1
- package/dist/svelte/components/ContentMetadataFields.svelte.d.ts +9 -1
- package/dist/svelte/components/ContentMetadataFields.svelte.d.ts.map +1 -1
- package/dist/svelte/components/ContentStatusFields.svelte +9 -1
- package/dist/svelte/components/ContentStatusFields.svelte.d.ts +8 -1
- package/dist/svelte/components/ContentStatusFields.svelte.d.ts.map +1 -1
- package/dist/svelte/components/ContentTransparencyTool.svelte +4 -2
- package/dist/svelte/components/ContentTransparencyTool.svelte.d.ts.map +1 -1
- package/dist/svelte/components/ContentVersionsTool.svelte +6 -6
- package/dist/svelte/components/GovernedContentEditor.svelte +8 -2
- package/dist/svelte/components/GovernedContentEditor.svelte.d.ts.map +1 -1
- package/dist/svelte/routes/ContentContributionsRoute.svelte +11 -10
- package/dist/svelte/routes/ContentContributionsRoute.svelte.d.ts.map +1 -1
- package/dist/svelte/routes/ContentFactsRoute.svelte +2 -2
- package/dist/svelte/routes/ContentWorkspaceRoute.svelte +6 -6
- package/dist/thumbnail-generator.d.ts.map +1 -1
- package/package.json +14 -14
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/__smrt-register__.ts","../src/asset-associable.ts","../src/content-asset.ts","../src/content-assets.ts","../src/content-governance.ts","../src/content-prompts.ts","../src/content-reference.ts","../src/content-references.ts","../src/content-transparency.ts","../src/database-utils.ts","../src/serialization.ts","../src/thumbnail-generator.ts","../src/content.ts","../src/content-chat-prompts.ts","../src/content-chat-session.ts","../src/content-chat-handlers.ts","../src/content-contribution-config.ts","../src/content-contribution.ts","../src/content-contribution-attachment.ts","../src/content-contribution-attachments.ts","../src/content-contribution-revision.ts","../src/content-contribution-revisions.ts","../src/content-contribution-type.ts","../src/content-contribution-types.ts","../src/content-contributor.ts","../src/content-contributors.ts","../src/content-contributions.ts","../src/content-correction.ts","../src/content-corrections.ts","../../../node_modules/.pnpm/fast-xml-parser@5.7.2/node_modules/fast-xml-parser/src/util.js","../../../node_modules/.pnpm/fast-xml-parser@5.7.2/node_modules/fast-xml-parser/src/validator.js","../../../node_modules/.pnpm/@nodable+entities@2.1.0/node_modules/@nodable/entities/src/entities.js","../../../node_modules/.pnpm/@nodable+entities@2.1.0/node_modules/@nodable/entities/src/EntityDecoder.js","../../../node_modules/.pnpm/fast-xml-parser@5.7.2/node_modules/fast-xml-parser/src/xmlparser/OptionsBuilder.js","../../../node_modules/.pnpm/fast-xml-parser@5.7.2/node_modules/fast-xml-parser/src/xmlparser/xmlNode.js","../../../node_modules/.pnpm/fast-xml-parser@5.7.2/node_modules/fast-xml-parser/src/xmlparser/DocTypeReader.js","../../../node_modules/.pnpm/strnum@2.2.3/node_modules/strnum/strnum.js","../../../node_modules/.pnpm/fast-xml-parser@5.7.2/node_modules/fast-xml-parser/src/ignoreAttributes.js","../../../node_modules/.pnpm/path-expression-matcher@1.5.0/node_modules/path-expression-matcher/src/Expression.js","../../../node_modules/.pnpm/path-expression-matcher@1.5.0/node_modules/path-expression-matcher/src/ExpressionSet.js","../../../node_modules/.pnpm/path-expression-matcher@1.5.0/node_modules/path-expression-matcher/src/Matcher.js","../../../node_modules/.pnpm/fast-xml-parser@5.7.2/node_modules/fast-xml-parser/src/xmlparser/OrderedObjParser.js","../../../node_modules/.pnpm/fast-xml-parser@5.7.2/node_modules/fast-xml-parser/src/xmlparser/node2json.js","../../../node_modules/.pnpm/fast-xml-parser@5.7.2/node_modules/fast-xml-parser/src/xmlparser/XMLParser.js","../src/content-feed-parser.ts","../src/content-feed-source.ts","../src/content-feed-sources.ts","../src/content-types.ts","../src/safe-remote-url.ts","../src/contents.ts","../src/content-feed-sync.ts","../src/content-governance-assignment.ts","../src/content-governance-assignments.ts","../src/content-governance-policy.ts","../src/content-governance-policies.ts","../src/content-governance-profile.ts","../src/content-governance-profiles.ts","../src/content-review.ts","../src/content-reviews.ts","../src/content-version.ts","../src/content-versions.ts","../src/utils.ts"],"sourcesContent":["/**\n * Self-registers this package's build-time manifest before any @smrt() decorator\n * in the package fires. Fixes issue #1132: in consumer runtimes (tsx, SvelteKit\n * SSR, plain `vite dev`) the decorator's synchronous manifest lookup previously\n * missed because no step populated the global manifest cache — classes got\n * registered with zero fields and `save()` / `toJSON()` silently dropped every\n * declared property.\n *\n * Import this module as the first statement in `src/index.ts` so its top-level\n * side effect runs ahead of any class module's @smrt() decorator.\n *\n * Silent no-op in dev/test, where the vitest plugin already populates manifests\n * via a different path. Only needs to succeed in the published dist output.\n *\n * @see https://github.com/happyvertical/smrt/issues/1132\n */\nimport { ObjectRegistry } from '@happyvertical/smrt-core';\n\n// `new URL('./manifest.json', import.meta.url)` resolves at runtime to the\n// manifest sitting next to this module's compiled output. Vite warns at build\n// time that it cannot pre-resolve the URL; that is the intended behavior —\n// the URL must resolve to dist/manifest.json at runtime, not be inlined.\nObjectRegistry.registerPackageManifest(\n new URL('./manifest.json', import.meta.url),\n);\n","import type { Asset } from '@happyvertical/smrt-assets';\n\n/**\n * Contract for objects that participate in the content/asset association\n * pattern.\n *\n * Any class that exposes asset-relationship methods (e.g. `Content` and its\n * STI subclasses) implements this interface explicitly so consumers can rely\n * on the methods existing instead of falling back to `typeof === 'function'`\n * duck-typing checks.\n *\n * @example\n * ```ts\n * import type { AssetAssociable } from '@happyvertical/smrt-content';\n *\n * async function attachThumbnail(\n * target: AssetAssociable,\n * image: Asset,\n * ): Promise<void> {\n * // No defensive runtime checks needed — the contract guarantees the method.\n * await target.addAsset(image, 'thumbnail', 0);\n * }\n * ```\n */\nexport interface AssetAssociable {\n /**\n * Get all assets associated with this object.\n *\n * @param relationship - Optional filter by relationship type\n * (e.g. `'thumbnail'`, `'attachment'`).\n * @returns Array of associated assets. Returns an empty array if the object\n * has not been persisted yet.\n */\n getAssets(relationship?: string): Promise<Asset[]>;\n\n /**\n * Associate an asset with this object via a typed relationship.\n *\n * @param asset - The asset to associate. Must be persisted (have an `id`).\n * @param relationship - Relationship type. Must match\n * `/^[a-zA-Z_][a-zA-Z0-9_]*$/`. Defaults to `'attachment'`.\n * @param sortOrder - Non-negative integer for display order.\n * @throws if either side is unsaved or the relationship/sort order is invalid.\n */\n addAsset(\n asset: Asset,\n relationship?: string,\n sortOrder?: number,\n ): Promise<void>;\n\n /**\n * Remove an associated asset.\n *\n * @param assetId - The asset ID to detach.\n * @param relationship - Optional specific relationship to remove. If omitted,\n * all relationships between this object and the asset are removed.\n */\n removeAsset(assetId: string, relationship?: string): Promise<void>;\n}\n\n/**\n * Contract for objects exposing typed access to a `metadata` JSON field.\n *\n * Use alongside an explicit interface (such as {@link AssetAssociable}) to\n * give consumers a stable contract for reading/writing the loose JSON bag,\n * without leaking the `metadata: Record<string, any>` type into call sites.\n */\nexport interface MetadataAccessor<\n TMetadata extends Record<string, any> = Record<string, any>,\n> {\n /**\n * Get the full metadata record. Always returns an object (never `null`).\n * The returned reference is the live object — callers should treat it as\n * read-only and use {@link MetadataAccessor.setMetadata} or\n * {@link MetadataAccessor.updateMetadata} to mutate it safely.\n */\n getMetadata(): TMetadata;\n\n /**\n * Replace the entire metadata record.\n *\n * @param metadata - The new metadata object. `null`/`undefined` clears it.\n */\n setMetadata(metadata: TMetadata | null | undefined): void;\n\n /**\n * Shallow-merge the supplied patch over the existing metadata.\n *\n * @param patch - Partial metadata. Keys present in the patch overwrite the\n * existing record; keys absent from the patch are preserved.\n * @returns The merged metadata record.\n */\n updateMetadata(patch: Partial<TMetadata>): TMetadata;\n}\n\n/**\n * Runtime type guard for {@link AssetAssociable}.\n *\n * The interface exists primarily so that statically-typed consumers can drop\n * defensive `typeof === 'function'` checks. This guard is for the rare cases\n * where a value enters the system as `unknown` (deserialised payload, plugin\n * input, etc.) and the caller needs to confirm shape before delegating.\n *\n * @example\n * ```ts\n * if (isAssetAssociable(input)) {\n * await input.addAsset(asset, 'attachment');\n * }\n * ```\n */\nexport function isAssetAssociable(value: unknown): value is AssetAssociable {\n if (!value || typeof value !== 'object') return false;\n const candidate = value as Partial<AssetAssociable>;\n return (\n typeof candidate.getAssets === 'function' &&\n typeof candidate.addAsset === 'function' &&\n typeof candidate.removeAsset === 'function'\n );\n}\n\n/**\n * Runtime type guard for {@link MetadataAccessor}.\n *\n * Mirrors {@link isAssetAssociable} for the metadata-accessor contract.\n */\nexport function isMetadataAccessor(value: unknown): value is MetadataAccessor {\n if (!value || typeof value !== 'object') return false;\n const candidate = value as Partial<MetadataAccessor>;\n return (\n typeof candidate.getMetadata === 'function' &&\n typeof candidate.setMetadata === 'function' &&\n typeof candidate.updateMetadata === 'function'\n );\n}\n\n/**\n * Returns `true` if `value` is a plain object (not an array, not `null`,\n * not a class instance with a custom prototype). Used by `Content`'s metadata\n * accessors to enforce the \"record-shaped\" contract — arrays and other\n * non-record objects are normalised to `{}` rather than silently leaked\n * through.\n *\n * @internal\n */\nexport function isPlainMetadataRecord(\n value: unknown,\n): value is Record<string, any> {\n if (!value || typeof value !== 'object') return false;\n if (Array.isArray(value)) return false;\n const proto = Object.getPrototypeOf(value);\n return proto === null || proto === Object.prototype;\n}\n","import type { SmrtObjectOptions } from '@happyvertical/smrt-core';\nimport {\n crossPackageRef,\n field,\n foreignKey,\n SmrtObject,\n smrt,\n} from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\n\nexport interface ContentAssetOptions extends SmrtObjectOptions {\n contentId?: string;\n assetId?: string;\n relationship?: string;\n sortOrder?: number;\n tenantId?: string | null;\n}\n\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableName: 'content_assets',\n conflictColumns: ['content_id', 'asset_id', 'relationship'],\n api: false,\n mcp: false,\n cli: false,\n})\nexport class ContentAsset extends SmrtObject {\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n @foreignKey('Content', { required: true })\n contentId = '';\n\n @crossPackageRef('@happyvertical/smrt-assets:Asset', { required: true })\n assetId = '';\n\n @field({ required: true })\n relationship = 'attachment';\n\n @field()\n sortOrder = 0;\n\n constructor(options: ContentAssetOptions = {}) {\n super(options);\n if (options.contentId) this.contentId = options.contentId;\n if (options.assetId) this.assetId = options.assetId;\n if (options.relationship) this.relationship = options.relationship;\n if (options.sortOrder !== undefined) this.sortOrder = options.sortOrder;\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n }\n}\n","import type { SmrtCollectionOptions } from '@happyvertical/smrt-core';\nimport { SmrtJunction, smrt } from '@happyvertical/smrt-core';\nimport { ContentAsset } from './content-asset';\n\nexport interface ContentAssetCollectionOptions extends SmrtCollectionOptions {}\n\n@smrt({\n api: false,\n mcp: false,\n cli: false,\n})\nexport class ContentAssetCollection extends SmrtJunction<ContentAsset> {\n static readonly _itemClass = ContentAsset;\n protected leftField = 'contentId';\n protected rightField = 'assetId';\n}\n","import type { Fact, FactContentRelationship } from '@happyvertical/smrt-facts';\nimport type { DatabaseInterface } from '@happyvertical/sql';\nimport type { Content } from './content';\n\nexport type ContentReviewKind = 'facts' | 'safety' | 'custom';\n\nexport type ContentReviewStatus =\n | 'pending'\n | 'passed'\n | 'flagged'\n | 'failed'\n | 'waived';\n\nexport type ContentReviewSeverity = 'info' | 'warning' | 'error';\n\nexport type ContentVersionKind =\n | 'manual'\n | 'draft'\n | 'review'\n | 'publication'\n | 'correction';\n\nexport type ContentCorrectionType = 'fact' | 'safety' | 'copy' | 'custom';\n\nexport type ContentCorrectionStatus = 'draft' | 'published' | 'retracted';\n\nexport interface ContentReviewFinding {\n severity: ContentReviewSeverity;\n title: string;\n detail: string;\n factId?: string;\n quote?: string;\n suggestedChange?: string;\n ruleId?: string;\n}\n\nexport interface ContentReviewResult {\n status: ContentReviewStatus;\n summary: string;\n findings: ContentReviewFinding[];\n}\n\nexport interface ContentReviewRequirement {\n policyKey: string;\n label?: string;\n blocking?: boolean;\n acceptedStatuses?: ContentReviewStatus[];\n}\n\nexport interface ContentReviewProfileEvaluationItem {\n kind: ContentReviewKind;\n policyKey: string;\n label: string;\n blocking: boolean;\n acceptedStatuses: ContentReviewStatus[];\n missing: boolean;\n stale: boolean;\n executed: boolean;\n satisfied: boolean;\n latestReviewId: string | null;\n latestStatus: ContentReviewStatus | null;\n latestSummary: string | null;\n}\n\nexport interface ContentReviewProfileEvaluation {\n profileKey: string;\n ready: boolean;\n complete: boolean;\n requirements: ContentReviewProfileEvaluationItem[];\n}\n\nexport interface ContentReviewPolicyDefinition {\n key: string;\n label: string;\n kind: ContentReviewKind;\n instructions: string;\n enabled?: boolean;\n metadata?: Record<string, any>;\n}\n\nexport interface ContentGovernanceProfileDefinition {\n key: string;\n label: string;\n description?: string;\n enabled?: boolean;\n requirements: ContentReviewRequirement[];\n metadata?: Record<string, any>;\n}\n\nexport interface ContentGovernanceAssignmentDefinition {\n key?: string;\n label?: string;\n contentType: string;\n contentVariant?: string | null;\n enabled?: boolean;\n factLinkingEnabled?: boolean;\n transparencyEnabled?: boolean;\n publicationProfileKey?: string | null;\n correctionProfileKey?: string | null;\n enforcePublishReadiness?: boolean;\n defaultFactRelationship?: FactContentRelationship;\n metadata?: Record<string, any>;\n}\n\nexport interface ContentGovernanceConfig {\n policies: ContentReviewPolicyDefinition[];\n profiles: ContentGovernanceProfileDefinition[];\n assignments: ContentGovernanceAssignmentDefinition[];\n}\n\nexport interface PersistedContentGovernancePolicyRecord\n extends ContentReviewPolicyDefinition {\n id?: string;\n tenantId?: string | null;\n createdAt?: string | null;\n updatedAt?: string | null;\n}\n\nexport interface PersistedContentGovernanceProfileRecord\n extends ContentGovernanceProfileDefinition {\n id?: string;\n tenantId?: string | null;\n createdAt?: string | null;\n updatedAt?: string | null;\n}\n\nexport interface PersistedContentGovernanceAssignmentRecord\n extends ContentGovernanceAssignmentDefinition {\n id?: string;\n tenantId?: string | null;\n createdAt?: string | null;\n updatedAt?: string | null;\n}\n\nexport interface PersistedContentGovernanceDefinitions {\n policies: PersistedContentGovernancePolicyRecord[];\n profiles: PersistedContentGovernanceProfileRecord[];\n assignments: PersistedContentGovernanceAssignmentRecord[];\n}\n\nexport interface ResolvedContentGovernance {\n isGoverned: boolean;\n factLinkingEnabled: boolean;\n transparencyEnabled: boolean;\n publicationProfileKey: string | null;\n correctionProfileKey: string | null;\n enforcePublishReadiness: boolean;\n defaultFactRelationship: FactContentRelationship;\n reviewPolicies: ContentReviewPolicyDefinition[];\n availableProfiles: ContentGovernanceProfileDefinition[];\n assignment: ContentGovernanceAssignmentDefinition | null;\n}\n\nexport interface ContentGovernanceState extends ResolvedContentGovernance {\n reviewProfiles: ContentReviewProfileEvaluation[];\n}\n\nexport interface CreateContentVersionOptions {\n kind?: ContentVersionKind;\n summary?: string;\n metadata?: Record<string, any>;\n snapshot?: Record<string, any>;\n}\n\nexport interface RunContentReviewOptions {\n kind?: ContentReviewKind;\n policyKey?: string;\n reviewer?: string;\n instructions?: string;\n facts?: Fact[];\n factIds?: string[];\n metadata?: Record<string, any>;\n createVersion?: boolean;\n}\n\nexport interface IssueContentCorrectionOptions {\n correctionType?: ContentCorrectionType;\n factId?: string;\n correctedFactText?: string;\n summary: string;\n incorrectText?: string;\n correctedText?: string;\n publicNote?: string;\n metadata?: Record<string, any>;\n createVersion?: boolean;\n publish?: boolean;\n}\n\nexport interface BuildContentReviewPromptOptions {\n kind: ContentReviewKind;\n content: Pick<\n Content,\n | 'id'\n | 'type'\n | 'status'\n | 'state'\n | 'title'\n | 'description'\n | 'body'\n | 'author'\n | 'publish_date'\n >;\n facts?: Fact[];\n policy?: ContentReviewPolicyDefinition | null;\n customInstructions?: string;\n}\n\nexport interface ResolveContentGovernanceOptions {\n contentType?: string | null;\n contentVariant?: string | null;\n db?: DatabaseInterface | null;\n}\n\nconst DEFAULT_FACT_RELATIONSHIP: FactContentRelationship = 'supports';\n\nconst DEFAULT_REVIEW_POLICIES: ContentReviewPolicyDefinition[] = [\n {\n key: 'facts',\n label: 'Facts Review',\n kind: 'facts',\n instructions: [\n 'Compare the draft copy against the supplied facts only.',\n 'Flag contradictions, unsupported claims, stale claims, and places where the copy should cite or qualify a statement.',\n 'Do not invent missing facts. If the draft makes a claim that is not supported by the provided facts, flag it clearly.',\n ].join(' '),\n enabled: true,\n },\n {\n key: 'safety',\n label: 'Safety Review',\n kind: 'safety',\n instructions: [\n 'Review the content for legal, reputational, and user-safety risks.',\n 'At minimum, check for defamation risk, privacy leaks, unverified allegations, unsafe instructions, and medical, legal, or financial claims that need qualification.',\n 'Flag content that should be softened, attributed, removed, or escalated for human review.',\n ].join(' '),\n enabled: true,\n },\n];\n\nconst DEFAULT_REVIEW_PROFILES: ContentGovernanceProfileDefinition[] = [\n {\n key: 'publication',\n label: 'Publication',\n description: 'Default publication-time editorial checks.',\n enabled: true,\n requirements: [\n {\n policyKey: 'safety',\n label: 'Safety Review',\n blocking: false,\n },\n {\n policyKey: 'facts',\n label: 'Facts Review',\n blocking: false,\n },\n ],\n },\n {\n key: 'correction',\n label: 'Correction',\n description: 'Default correction-time editorial checks.',\n enabled: true,\n requirements: [\n {\n policyKey: 'safety',\n label: 'Safety Review',\n blocking: false,\n },\n ],\n },\n];\n\nconst DEFAULT_CONTENT_GOVERNANCE_CONFIG: ContentGovernanceConfig = {\n policies: DEFAULT_REVIEW_POLICIES.map(clonePolicyDefinition),\n profiles: DEFAULT_REVIEW_PROFILES.map(cloneProfileDefinition),\n assignments: [],\n};\n\nlet governanceConfig: ContentGovernanceConfig = cloneGovernanceConfig(\n DEFAULT_CONTENT_GOVERNANCE_CONFIG,\n);\n// Process-global by design: apps are expected to configure governance once at\n// startup and use persisted records for runtime admin overrides.\n\nfunction cloneReviewRequirement(\n requirement: ContentReviewRequirement,\n): ContentReviewRequirement {\n return {\n ...requirement,\n acceptedStatuses: requirement.acceptedStatuses\n ? [...requirement.acceptedStatuses]\n : undefined,\n };\n}\n\nfunction normalizePolicyDefinition(\n policy: ContentReviewPolicyDefinition,\n): ContentReviewPolicyDefinition {\n return {\n key: policy.key,\n label: policy.label || policy.key,\n kind: policy.kind || getFallbackPolicyKind(policy.key),\n instructions: policy.instructions || '',\n enabled: policy.enabled !== false,\n metadata: policy.metadata ? { ...policy.metadata } : undefined,\n };\n}\n\nfunction clonePolicyDefinition(\n policy: ContentReviewPolicyDefinition,\n): ContentReviewPolicyDefinition {\n return normalizePolicyDefinition(policy);\n}\n\nfunction normalizeProfileDefinition(\n profile: ContentGovernanceProfileDefinition,\n): ContentGovernanceProfileDefinition {\n return {\n key: profile.key,\n label: profile.label || profile.key,\n description: profile.description || '',\n enabled: profile.enabled !== false,\n requirements: Array.isArray(profile.requirements)\n ? profile.requirements.map(cloneReviewRequirement)\n : [],\n metadata: profile.metadata ? { ...profile.metadata } : undefined,\n };\n}\n\nfunction cloneProfileDefinition(\n profile: ContentGovernanceProfileDefinition,\n): ContentGovernanceProfileDefinition {\n return normalizeProfileDefinition(profile);\n}\n\nexport function buildContentGovernanceAssignmentKey(\n contentType: string,\n contentVariant?: string | null,\n): string {\n return `${contentType || ''}::${contentVariant || ''}`;\n}\n\nfunction normalizeAssignmentDefinition(\n assignment: ContentGovernanceAssignmentDefinition,\n): ContentGovernanceAssignmentDefinition {\n return {\n key:\n assignment.key ||\n buildContentGovernanceAssignmentKey(\n assignment.contentType,\n assignment.contentVariant,\n ),\n label: assignment.label || '',\n contentType: assignment.contentType,\n contentVariant: assignment.contentVariant || '',\n enabled: assignment.enabled !== false,\n factLinkingEnabled: assignment.factLinkingEnabled === true,\n transparencyEnabled: assignment.transparencyEnabled === true,\n publicationProfileKey: assignment.publicationProfileKey || null,\n correctionProfileKey: assignment.correctionProfileKey || null,\n enforcePublishReadiness: assignment.enforcePublishReadiness === true,\n defaultFactRelationship:\n assignment.defaultFactRelationship || DEFAULT_FACT_RELATIONSHIP,\n metadata: assignment.metadata ? { ...assignment.metadata } : undefined,\n };\n}\n\nfunction cloneAssignmentDefinition(\n assignment: ContentGovernanceAssignmentDefinition,\n): ContentGovernanceAssignmentDefinition {\n return normalizeAssignmentDefinition(assignment);\n}\n\nfunction cloneGovernanceConfig(\n config: ContentGovernanceConfig,\n): ContentGovernanceConfig {\n return {\n policies: config.policies.map(clonePolicyDefinition),\n profiles: config.profiles.map(cloneProfileDefinition),\n assignments: config.assignments.map(cloneAssignmentDefinition),\n };\n}\n\nfunction mergeByKey<T extends { key?: string }>(\n previous: T[],\n next: T[],\n normalize: (value: T) => T,\n): T[] {\n const merged = new Map<string, T>();\n\n for (const value of previous) {\n const normalized = normalize(value);\n if (normalized.key) {\n merged.set(normalized.key, normalized);\n }\n }\n\n for (const value of next) {\n const normalized = normalize(value);\n if (normalized.key) {\n merged.set(normalized.key, normalized);\n }\n }\n\n return [...merged.values()];\n}\n\nexport function getFallbackPolicyKind(key: string): ContentReviewKind {\n if (key === 'facts') {\n return 'facts';\n }\n\n if (key === 'safety') {\n return 'safety';\n }\n\n return 'custom';\n}\n\nfunction getPolicyMap(\n policies: ContentReviewPolicyDefinition[],\n): Map<string, ContentReviewPolicyDefinition> {\n return new Map(\n policies.map((policy) => {\n const normalized = normalizePolicyDefinition(policy);\n return [normalized.key, normalized];\n }),\n );\n}\n\nfunction getProfileMap(\n profiles: ContentGovernanceProfileDefinition[],\n): Map<string, ContentGovernanceProfileDefinition> {\n return new Map(\n profiles.map((profile) => {\n const normalized = normalizeProfileDefinition(profile);\n return [normalized.key, normalized];\n }),\n );\n}\n\nfunction isMissingGovernanceTableError(error: unknown): boolean {\n const message =\n error instanceof Error ? error.message : String(error || 'Unknown error');\n\n return (\n message.includes(\"Run 'smrt db:migrate'\") ||\n /no such table/i.test(message) ||\n /does not exist/i.test(message)\n );\n}\n\nfunction getRowTimestamp(\n row: Record<string, any>,\n primaryKey: 'createdAt' | 'updatedAt',\n): string | null {\n const snakeCaseKey = primaryKey === 'createdAt' ? 'created_at' : 'updated_at';\n const value = row[primaryKey] ?? row[snakeCaseKey];\n return typeof value === 'string' && value.length > 0 ? value : null;\n}\n\nfunction getRowTenantId(row: Record<string, any>): string | null {\n const value = row.tenantId ?? row.tenant_id ?? null;\n return typeof value === 'string' && value.length > 0 ? value : null;\n}\n\nfunction safeParseJSONObject(value: unknown): Record<string, any> {\n if (!value) {\n return {};\n }\n\n if (typeof value === 'object' && !Array.isArray(value)) {\n return { ...(value as Record<string, any>) };\n }\n\n try {\n const parsed = JSON.parse(String(value));\n return parsed && typeof parsed === 'object' && !Array.isArray(parsed)\n ? { ...(parsed as Record<string, any>) }\n : {};\n } catch {\n return {};\n }\n}\n\nfunction safeParseJSONArray<T>(value: unknown, mapEntry: (entry: T) => T): T[] {\n if (!value) {\n return [];\n }\n\n if (Array.isArray(value)) {\n return value.map((entry) => mapEntry(entry as T));\n }\n\n try {\n const parsed = JSON.parse(String(value));\n return Array.isArray(parsed)\n ? parsed.map((entry) => mapEntry(entry as T))\n : [];\n } catch {\n return [];\n }\n}\n\nfunction mapPersistedPolicyRow(\n row: Record<string, any>,\n): PersistedContentGovernancePolicyRecord {\n return {\n id: typeof row.id === 'string' ? row.id : undefined,\n tenantId: getRowTenantId(row),\n createdAt: getRowTimestamp(row, 'createdAt'),\n updatedAt: getRowTimestamp(row, 'updatedAt'),\n ...normalizePolicyDefinition({\n key: String(row.key || ''),\n label: String(row.label || row.key || ''),\n kind: (row.kind ||\n getFallbackPolicyKind(String(row.key || ''))) as ContentReviewKind,\n instructions: String(row.instructions || ''),\n enabled: row.enabled !== false && row.enabled !== 0,\n metadata: safeParseJSONObject(row.metadata),\n }),\n };\n}\n\nfunction mapPersistedProfileRow(\n row: Record<string, any>,\n): PersistedContentGovernanceProfileRecord {\n return {\n id: typeof row.id === 'string' ? row.id : undefined,\n tenantId: getRowTenantId(row),\n createdAt: getRowTimestamp(row, 'createdAt'),\n updatedAt: getRowTimestamp(row, 'updatedAt'),\n ...normalizeProfileDefinition({\n key: String(row.key || ''),\n label: String(row.label || row.key || ''),\n description: String(row.description || ''),\n enabled: row.enabled !== false && row.enabled !== 0,\n requirements: safeParseJSONArray<ContentReviewRequirement>(\n row.requirements,\n cloneReviewRequirement,\n ),\n metadata: safeParseJSONObject(row.metadata),\n }),\n };\n}\n\nfunction mapPersistedAssignmentRow(\n row: Record<string, any>,\n): PersistedContentGovernanceAssignmentRecord {\n return {\n id: typeof row.id === 'string' ? row.id : undefined,\n tenantId: getRowTenantId(row),\n createdAt: getRowTimestamp(row, 'createdAt'),\n updatedAt: getRowTimestamp(row, 'updatedAt'),\n ...normalizeAssignmentDefinition({\n key: String(row.key || ''),\n label: String(row.label || ''),\n contentType: String(row.contentType || row.content_type || ''),\n contentVariant: String(row.contentVariant || row.content_variant || ''),\n enabled: row.enabled !== false && row.enabled !== 0,\n factLinkingEnabled:\n row.factLinkingEnabled === true ||\n row.fact_linking_enabled === true ||\n row.fact_linking_enabled === 1,\n transparencyEnabled:\n row.transparencyEnabled === true ||\n row.transparency_enabled === true ||\n row.transparency_enabled === 1,\n publicationProfileKey:\n row.publicationProfileKey || row.publication_profile_key || null,\n correctionProfileKey:\n row.correctionProfileKey || row.correction_profile_key || null,\n enforcePublishReadiness:\n row.enforcePublishReadiness === true ||\n row.enforce_publish_readiness === true ||\n row.enforce_publish_readiness === 1,\n defaultFactRelationship:\n row.defaultFactRelationship ||\n row.default_fact_relationship ||\n DEFAULT_FACT_RELATIONSHIP,\n metadata: safeParseJSONObject(row.metadata),\n }),\n };\n}\n\nexport async function loadPersistedContentGovernanceDefinitions(\n options: { db?: DatabaseInterface | null } = {},\n): Promise<PersistedContentGovernanceDefinitions> {\n const { db } = options;\n if (!db) {\n return {\n policies: [],\n profiles: [],\n assignments: [],\n };\n }\n\n try {\n const [policyRows, profileRows, assignmentRows] = await Promise.all([\n db.list('content_governance_policies', {}),\n db.list('content_governance_profiles', {}),\n db.list('content_governance_assignments', {}),\n ]);\n\n policyRows.sort((a: any, b: any) =>\n String(a.created_at || a.createdAt || '').localeCompare(\n String(b.created_at || b.createdAt || ''),\n ),\n );\n profileRows.sort((a: any, b: any) =>\n String(a.created_at || a.createdAt || '').localeCompare(\n String(b.created_at || b.createdAt || ''),\n ),\n );\n assignmentRows.sort((a: any, b: any) =>\n String(a.created_at || a.createdAt || '').localeCompare(\n String(b.created_at || b.createdAt || ''),\n ),\n );\n\n return {\n policies: policyRows.map((row: any) => mapPersistedPolicyRow(row)),\n profiles: profileRows.map((row: any) => mapPersistedProfileRow(row)),\n assignments: assignmentRows.map((row: any) =>\n mapPersistedAssignmentRow(row),\n ),\n };\n } catch (error) {\n if (isMissingGovernanceTableError(error)) {\n return {\n policies: [],\n profiles: [],\n assignments: [],\n };\n }\n throw error;\n }\n}\n\nfunction resolveAssignmentDefinition(\n assignments: ContentGovernanceAssignmentDefinition[],\n options: Pick<\n ResolveContentGovernanceOptions,\n 'contentType' | 'contentVariant'\n >,\n): ContentGovernanceAssignmentDefinition | null {\n if (!options.contentType) {\n return null;\n }\n\n const exactMatch =\n assignments.find(\n (assignment) =>\n assignment.contentType === options.contentType &&\n (assignment.contentVariant || '') === (options.contentVariant || ''),\n ) || null;\n\n if (exactMatch) {\n return cloneAssignmentDefinition(exactMatch);\n }\n\n const typeOnlyMatch =\n assignments.find(\n (assignment) =>\n assignment.contentType === options.contentType &&\n !assignment.contentVariant,\n ) || null;\n\n return typeOnlyMatch ? cloneAssignmentDefinition(typeOnlyMatch) : null;\n}\n\nfunction buildResolvedGovernance(\n config: ContentGovernanceConfig,\n assignment: ContentGovernanceAssignmentDefinition | null,\n): ResolvedContentGovernance {\n const normalizedAssignment = assignment\n ? normalizeAssignmentDefinition(assignment)\n : null;\n if (!normalizedAssignment || normalizedAssignment.enabled !== true) {\n return {\n isGoverned: false,\n factLinkingEnabled: false,\n transparencyEnabled: false,\n publicationProfileKey: null,\n correctionProfileKey: null,\n enforcePublishReadiness: false,\n defaultFactRelationship: DEFAULT_FACT_RELATIONSHIP,\n reviewPolicies: config.policies\n .map(clonePolicyDefinition)\n .filter((policy) => policy.enabled !== false),\n availableProfiles: config.profiles\n .map(cloneProfileDefinition)\n .filter((profile) => profile.enabled !== false),\n assignment: normalizedAssignment,\n };\n }\n\n return {\n isGoverned: true,\n factLinkingEnabled: normalizedAssignment.factLinkingEnabled === true,\n transparencyEnabled: normalizedAssignment.transparencyEnabled === true,\n publicationProfileKey: normalizedAssignment.publicationProfileKey || null,\n correctionProfileKey: normalizedAssignment.correctionProfileKey || null,\n enforcePublishReadiness:\n normalizedAssignment.enforcePublishReadiness === true,\n defaultFactRelationship:\n normalizedAssignment.defaultFactRelationship || DEFAULT_FACT_RELATIONSHIP,\n reviewPolicies: config.policies\n .map(clonePolicyDefinition)\n .filter((policy) => policy.enabled !== false),\n availableProfiles: config.profiles\n .map(cloneProfileDefinition)\n .filter((profile) => profile.enabled !== false),\n assignment: normalizedAssignment,\n };\n}\n\nfunction normalizeStatus(status: unknown): ContentReviewStatus {\n switch (status) {\n case 'pending':\n case 'passed':\n case 'flagged':\n case 'failed':\n case 'waived':\n return status;\n default:\n return 'flagged';\n }\n}\n\nfunction normalizeSeverity(severity: unknown): ContentReviewSeverity {\n switch (severity) {\n case 'info':\n case 'warning':\n case 'error':\n return severity;\n default:\n return 'warning';\n }\n}\n\nfunction extractJSONObject(raw: string): string | null {\n const start = raw.indexOf('{');\n const end = raw.lastIndexOf('}');\n if (start === -1 || end === -1 || end <= start) {\n return null;\n }\n return raw.slice(start, end + 1);\n}\n\nexport function getContentGovernanceConfig(): ContentGovernanceConfig {\n return cloneGovernanceConfig(governanceConfig);\n}\n\nexport function getStaticContentGovernanceConfig(): ContentGovernanceConfig {\n return cloneGovernanceConfig(governanceConfig);\n}\n\nexport function configureContentGovernance(\n config: Partial<ContentGovernanceConfig>,\n): ContentGovernanceConfig {\n governanceConfig = {\n policies: config.policies\n ? mergeByKey(\n governanceConfig.policies,\n config.policies,\n normalizePolicyDefinition,\n )\n : governanceConfig.policies.map(clonePolicyDefinition),\n profiles: config.profiles\n ? mergeByKey(\n governanceConfig.profiles,\n config.profiles,\n normalizeProfileDefinition,\n )\n : governanceConfig.profiles.map(cloneProfileDefinition),\n assignments: config.assignments\n ? mergeByKey(\n governanceConfig.assignments,\n config.assignments,\n normalizeAssignmentDefinition,\n )\n : governanceConfig.assignments.map(cloneAssignmentDefinition),\n };\n\n return getContentGovernanceConfig();\n}\n\nexport function resetContentGovernanceConfig(): ContentGovernanceConfig {\n governanceConfig = cloneGovernanceConfig(DEFAULT_CONTENT_GOVERNANCE_CONFIG);\n return getContentGovernanceConfig();\n}\n\nexport async function getEffectiveContentGovernanceConfig(\n options: { db?: DatabaseInterface | null } = {},\n): Promise<ContentGovernanceConfig> {\n const persisted = await loadPersistedContentGovernanceDefinitions({\n db: options.db,\n });\n\n return {\n policies: mergeByKey(\n governanceConfig.policies,\n persisted.policies,\n normalizePolicyDefinition,\n ),\n profiles: mergeByKey(\n governanceConfig.profiles,\n persisted.profiles,\n normalizeProfileDefinition,\n ),\n assignments: mergeByKey(\n governanceConfig.assignments,\n persisted.assignments,\n normalizeAssignmentDefinition,\n ),\n };\n}\n\nexport function hasStaticContentGovernancePolicy(key: string): boolean {\n return getPolicyMap(governanceConfig.policies).has(key);\n}\n\nexport function hasStaticContentGovernanceProfile(key: string): boolean {\n return getProfileMap(governanceConfig.profiles).has(key);\n}\n\nexport function getContentReviewPolicy(\n policyKey: string,\n policies: ContentReviewPolicyDefinition[] = governanceConfig.policies,\n): ContentReviewPolicyDefinition | null {\n return getPolicyMap(policies).get(policyKey) || null;\n}\n\nexport function getContentReviewKind(\n policyKey: string,\n policies: ContentReviewPolicyDefinition[] = governanceConfig.policies,\n): ContentReviewKind {\n const configuredKind = getPolicyMap(policies).get(policyKey)?.kind;\n return configuredKind || getFallbackPolicyKind(policyKey);\n}\n\nexport function getContentReviewProfile(\n profileKey: string,\n profiles: ContentGovernanceProfileDefinition[] = governanceConfig.profiles,\n): ContentGovernanceProfileDefinition | null {\n return getProfileMap(profiles).get(profileKey) || null;\n}\n\nexport function getContentReviewProfileKeys(\n profiles: ContentGovernanceProfileDefinition[] = governanceConfig.profiles,\n): string[] {\n return profiles\n .map(cloneProfileDefinition)\n .filter((profile) => profile.enabled !== false)\n .map((profile) => profile.key);\n}\n\nexport function getContentReviewPolicies(\n policies: ContentReviewPolicyDefinition[] = governanceConfig.policies,\n): ContentReviewPolicyDefinition[] {\n return policies\n .map(clonePolicyDefinition)\n .filter((policy) => policy.enabled !== false);\n}\n\nexport function getContentReviewRequirements(\n profileKey: string,\n profiles: ContentGovernanceProfileDefinition[] = governanceConfig.profiles,\n): ContentReviewRequirement[] {\n const profile = getContentReviewProfile(profileKey, profiles);\n return profile?.requirements.map(cloneReviewRequirement) || [];\n}\n\nexport function getAcceptedContentReviewStatuses(\n requirement: Pick<ContentReviewRequirement, 'acceptedStatuses'>,\n): ContentReviewStatus[] {\n return requirement.acceptedStatuses && requirement.acceptedStatuses.length > 0\n ? [...requirement.acceptedStatuses]\n : ['passed', 'waived'];\n}\n\nexport function resolveConfiguredContentGovernance(\n options: Pick<\n ResolveContentGovernanceOptions,\n 'contentType' | 'contentVariant'\n >,\n): ResolvedContentGovernance {\n const assignment = resolveAssignmentDefinition(governanceConfig.assignments, {\n contentType: options.contentType,\n contentVariant: options.contentVariant,\n });\n\n return buildResolvedGovernance(governanceConfig, assignment);\n}\n\nexport async function resolveEffectiveContentGovernance(\n options: ResolveContentGovernanceOptions,\n): Promise<ResolvedContentGovernance> {\n const effectiveConfig = await getEffectiveContentGovernanceConfig({\n db: options.db,\n });\n const assignment = resolveAssignmentDefinition(effectiveConfig.assignments, {\n contentType: options.contentType,\n contentVariant: options.contentVariant,\n });\n\n return buildResolvedGovernance(effectiveConfig, assignment);\n}\n\nexport function buildContentReviewPrompt(\n options: BuildContentReviewPromptOptions,\n): string {\n const { kind, content, facts = [], policy, customInstructions } = options;\n\n const factLines =\n facts.length > 0\n ? facts\n .map(\n (fact) =>\n `- [${fact.id}] status=${fact.status}; confidence=${fact.confidence}; sources=${fact.sourceCount}; text=${fact.textRefined}`,\n )\n .join('\\n')\n : 'No facts were supplied for this review.';\n\n const policyText =\n customInstructions?.trim() ||\n policy?.instructions ||\n getContentReviewPolicy(kind)?.instructions ||\n '';\n\n return `You are a structured editorial reviewer.\n\nReturn ONLY valid JSON with this shape:\n{\n \"status\": \"passed\" | \"flagged\" | \"failed\" | \"waived\",\n \"summary\": \"short summary\",\n \"findings\": [\n {\n \"severity\": \"info\" | \"warning\" | \"error\",\n \"title\": \"short title\",\n \"detail\": \"what is wrong and why\",\n \"factId\": \"optional fact id\",\n \"quote\": \"optional quoted text from the draft\",\n \"suggestedChange\": \"optional suggested fix\",\n \"ruleId\": \"optional policy or rule id\"\n }\n ]\n}\n\nReview kind: ${kind}\nPolicy key: ${policy?.key || kind}\nReview instructions:\n${policyText}\n\nDraft content:\n- id: ${content.id ?? ''}\n- type: ${content.type ?? ''}\n- status: ${content.status}\n- state: ${content.state}\n- author: ${content.author ?? ''}\n- publish_date: ${content.publish_date?.toISOString?.() ?? ''}\n\nTitle:\n${content.title}\n\nDescription:\n${content.description ?? ''}\n\nBody:\n${content.body}\n\nRelevant facts:\n${factLines}`;\n}\n\nexport function parseContentReviewResponse(raw: string): ContentReviewResult {\n const normalizedRaw = raw.trim();\n const jsonCandidate = extractJSONObject(normalizedRaw);\n\n if (jsonCandidate) {\n try {\n const parsed = JSON.parse(jsonCandidate) as Partial<ContentReviewResult>;\n const findings = Array.isArray(parsed.findings)\n ? parsed.findings.map((finding: any) => ({\n severity: normalizeSeverity(finding?.severity),\n title: String(finding?.title || 'Review finding'),\n detail: String(finding?.detail || ''),\n factId:\n typeof finding?.factId === 'string' ? finding.factId : undefined,\n quote:\n typeof finding?.quote === 'string' ? finding.quote : undefined,\n suggestedChange:\n typeof finding?.suggestedChange === 'string'\n ? finding.suggestedChange\n : undefined,\n ruleId:\n typeof finding?.ruleId === 'string' ? finding.ruleId : undefined,\n }))\n : [];\n\n return {\n status: normalizeStatus(parsed.status),\n summary: String(parsed.summary || normalizedRaw || 'Review completed'),\n findings,\n };\n } catch {\n // Fall through to a normalized fallback result.\n }\n }\n\n return {\n status: 'flagged',\n summary: normalizedRaw || 'Review completed without structured output.',\n findings: normalizedRaw\n ? [\n {\n severity: 'warning',\n title: 'Unstructured review output',\n detail: normalizedRaw,\n },\n ]\n : [],\n };\n}\n","import {\n definePrompt,\n type ResolvedPromptAI,\n} from '@happyvertical/smrt-prompts';\n\nexport const smrtContentReviewPrompt = definePrompt({\n key: 'smrtContent.review',\n template: `Content review request\n\nContent ID: {contentId}\nReview kind: {kind}\nPolicy key: {policyKey}\nTitle: {contentTitle}\nDescription: {contentDescription}\n\nBody:\n{contentBody}\n\n{reviewPrompt}`,\n editable: {\n template: true,\n profile: true,\n model: true,\n params: true,\n },\n});\n\nexport const smrtContentApplyCorrectionPrompt = definePrompt({\n key: 'smrtContent.applyCorrection',\n template: `You are revising an article draft to apply a factual correction.\n\nReturn only the fully revised body text, with no commentary.\n\nCurrent body:\n{body}\n\nCorrection summary:\n{summary}\n\nIncorrect text to fix:\n{incorrectText}\n\nCorrected text to incorporate:\n{correctedText}`,\n editable: {\n template: true,\n profile: true,\n model: true,\n params: true,\n },\n});\n\nexport const smrtContentThumbnailAIGeneratePrompt = definePrompt({\n key: 'smrtContent.thumbnail.aiGenerate',\n template: `Create a {style} thumbnail image for an article titled \"{title}\". {descriptionClause}Style: {styleHint}. The image should be suitable for a news article or blog post thumbnail.`,\n editable: {\n template: true,\n profile: true,\n model: true,\n params: true,\n },\n});\n\nexport function promptMessageOptions(ai: ResolvedPromptAI) {\n return {\n ...(ai.params || {}),\n ...(ai.model ? { model: ai.model } : {}),\n ...(typeof ai.temperature === 'number'\n ? { temperature: ai.temperature }\n : {}),\n ...(typeof ai.maxTokens === 'number' ? { maxTokens: ai.maxTokens } : {}),\n };\n}\n","import type { SmrtObjectOptions } from '@happyvertical/smrt-core';\nimport { field, foreignKey, SmrtObject, smrt } from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\n\nexport interface ContentReferenceOptions extends SmrtObjectOptions {\n sourceId?: string;\n targetId?: string;\n tenantId?: string | null;\n // ContentVersion.version pinned at citation time. Optional: references\n // created without a pin behave as before (they track the live target).\n // When set, callers can compare against the target's latest version to\n // surface drift between what was cited and what the target now says.\n targetVersion?: number | null;\n createdAt?: Date;\n}\n\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableName: 'content_references',\n conflictColumns: ['source_id', 'target_id'],\n})\nexport class ContentReference extends SmrtObject {\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n @foreignKey('Content', { required: true })\n sourceId = '';\n\n @foreignKey('Content', { required: true })\n targetId = '';\n\n @field({ type: 'integer', nullable: true })\n targetVersion: number | null = null;\n\n @field()\n createdAt = new Date();\n\n constructor(options: ContentReferenceOptions = {}) {\n super(options);\n if (options.sourceId) this.sourceId = options.sourceId;\n if (options.targetId) this.targetId = options.targetId;\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n if (options.targetVersion !== undefined)\n this.targetVersion = options.targetVersion;\n if (options.createdAt) this.createdAt = options.createdAt;\n }\n}\n","import type {\n JunctionAttachOptions,\n SmrtCollectionOptions,\n} from '@happyvertical/smrt-core';\nimport { SmrtJunction, smrt } from '@happyvertical/smrt-core';\nimport { ContentReference } from './content-reference';\n\nexport interface ContentReferencesOptions extends SmrtCollectionOptions {}\n\n/**\n * The `attach()` override below restores find-or-create idempotency for\n * `(sourceId, targetId)` — duplicate calls return the existing row\n * unchanged, preserving `id` and `createdAt`. This matters because\n * `ContentReference` rows are externally addressable via\n * `/api/v1/contentreferences/[id]`.\n *\n * Two REST entry points (both auto-generated by the scanner):\n * - `POST /api/v1/contentreferences` (from model CRUD) calls\n * `collection.create()` which is upsert-based — id/createdAt get\n * rewritten on conflict. Convenient for callers that don't care\n * about row id stability.\n * - `POST /api/v1/contentreferences/attach` (from the override below)\n * is idempotent. Use this for stable URLs.\n *\n * Internal callers (`Content.addReference()`) always hit the idempotent\n * path because they call the collection directly.\n *\n * The `/attach` route exists because R2 round-7 added `@smrt()` to this\n * class, which made the scanner pick up the override as a custom\n * collection method route. Pre-R2 had a `/link` route from the\n * pre-rename method name.\n */\n// Decorator with empty config — only needed so the scanner detects the\n// class. See FactContentCollection for the full rationale.\n@smrt()\nexport class ContentReferences extends SmrtJunction<ContentReference> {\n static readonly _itemClass = ContentReference;\n protected leftField = 'sourceId';\n protected rightField = 'targetId';\n // content_references has no sort_order column — preserve insertion order\n // by sorting on created_at, and disable setLinks position auto-indexing\n // so it doesn't try to write integer indices into the timestamp column.\n protected sortField: string | null = 'createdAt';\n protected positionField: string | null = null;\n\n async getForSource(sourceId: string): Promise<ContentReference[]> {\n return (await this.list({\n where: { sourceId },\n orderBy: 'created_at ASC',\n })) as ContentReference[];\n }\n\n async getForTarget(targetId: string): Promise<ContentReference[]> {\n return (await this.list({\n where: { targetId },\n orderBy: 'created_at ASC',\n })) as ContentReference[];\n }\n\n /**\n * Find-or-create idempotency: if a reference already exists for\n * (sourceId, targetId), return the existing row unchanged instead of\n * upserting a new row. This preserves the existing row's `id` and\n * `createdAt`, which is important because reference rows are\n * externally addressable via `/api/v1/contentreferences/[id]`.\n *\n * The base `SmrtJunction.attach` flow (this.create → db.upsert) would\n * overwrite both columns on every duplicate call.\n *\n * Reference pinning (main): `opts.targetVersion` pins the citation to a\n * specific `ContentVersion.version` for drift detection. Re-attaching an\n * existing edge with a different `targetVersion` updates the pin in place;\n * `undefined` leaves an existing pin untouched, while a brand-new row\n * defaults the pin to `null` (unpinned).\n */\n async attach(\n sourceId: string,\n targetId: string,\n opts: JunctionAttachOptions = {},\n ): Promise<ContentReference> {\n const targetVersion = opts.targetVersion as number | null | undefined;\n const existing = (await this.get({\n sourceId,\n targetId,\n })) as ContentReference | null;\n if (existing) {\n if (\n targetVersion !== undefined &&\n existing.targetVersion !== targetVersion\n ) {\n existing.targetVersion = targetVersion;\n await existing.save();\n }\n return existing;\n }\n return super.attach(sourceId, targetId, {\n ...opts,\n targetVersion: targetVersion ?? null,\n });\n }\n\n async unlink(sourceId: string, targetId: string): Promise<void> {\n await this.detach(sourceId, targetId);\n }\n}\n","export interface ContentTransparencyGeneration {\n aiAssisted: boolean;\n publicPrompt: string | null;\n model: string | null;\n}\n\nexport interface ContentTransparencySource {\n id: string | null;\n sourceType: string | null;\n sourceUrl: string | null;\n sourceTitle: string | null;\n credibility: number | null;\n extractedAt: string | null;\n metadata: Record<string, any>;\n}\n\nexport interface ContentTransparencyFact {\n id: string | null;\n textRaw?: string | null;\n textRefined?: string | null;\n status?: string | null;\n domain?: string | null;\n confidence?: number | null;\n sourceCount?: number | null;\n metadata?: Record<string, any>;\n relationship?: string | null;\n linkMetadata?: Record<string, any>;\n usedInArticle?: boolean;\n sources?: ContentTransparencySource[];\n}\n\nexport interface ContentTransparencyReference {\n id: string | null;\n title: string | null;\n url: string | null;\n originalUrl: string | null;\n type: string | null;\n source: string | null;\n usedFactIds: string[];\n extractedFacts: ContentTransparencyFact[];\n}\n\nexport interface ContentTransparencyPublicationVersion {\n id: string | null;\n version: number | null;\n kind: string | null;\n summary: string;\n createdAt: string | null;\n}\n\nexport interface ContentTransparencyVersionHistoryItem {\n id: string | null;\n version: number | null;\n kind: string | null;\n summary: string;\n createdAt: string | null;\n provenance: Record<string, any>;\n}\n\nexport interface ContentTransparencyData {\n generatedAt: string | null;\n snapshotKind: 'preview' | 'published';\n contentId: string | null;\n currentContentStatus: string | null;\n publicationProfileKey: string;\n publicationVersion: ContentTransparencyPublicationVersion | null;\n generation: ContentTransparencyGeneration;\n factsUsed: ContentTransparencyFact[];\n linkedFacts: ContentTransparencyFact[];\n otherExtractedFacts: ContentTransparencyFact[];\n references: ContentTransparencyReference[];\n reviews: Record<string, any>[];\n reviewProfiles: Record<string, any>[];\n corrections: Record<string, any>[];\n versionHistory: ContentTransparencyVersionHistoryItem[];\n}\n\nfunction asObject(\n value: unknown,\n fallback: Record<string, any> = {},\n): Record<string, any> {\n return value && typeof value === 'object' ? { ...(value as any) } : fallback;\n}\n\nfunction asString(value: unknown): string | null {\n return typeof value === 'string' && value.length > 0 ? value : null;\n}\n\nfunction asNumber(value: unknown): number | null {\n return typeof value === 'number' && Number.isFinite(value) ? value : null;\n}\n\nfunction asArray<T>(value: unknown): T[] {\n return Array.isArray(value) ? (value as T[]) : [];\n}\n\nfunction normalizeGeneration(value: unknown): ContentTransparencyGeneration {\n const generation = asObject(value);\n return {\n aiAssisted: Boolean(generation.aiAssisted),\n publicPrompt: asString(generation.publicPrompt),\n model: asString(generation.model),\n };\n}\n\nfunction normalizeFact(value: unknown): ContentTransparencyFact {\n const fact = asObject(value);\n return {\n ...fact,\n id: asString(fact.id),\n relationship: asString(fact.relationship),\n linkMetadata: asObject(fact.linkMetadata),\n usedInArticle: Boolean(fact.usedInArticle),\n sources: asArray<unknown>(fact.sources).map(normalizeSource),\n };\n}\n\nfunction normalizeSource(value: unknown): ContentTransparencySource {\n const source = asObject(value);\n return {\n id: asString(source.id),\n sourceType: asString(source.sourceType),\n sourceUrl: asString(source.sourceUrl),\n sourceTitle: asString(source.sourceTitle),\n credibility: asNumber(source.credibility),\n extractedAt: asString(source.extractedAt),\n metadata: asObject(source.metadata),\n };\n}\n\nfunction normalizeReference(value: unknown): ContentTransparencyReference {\n const reference = asObject(value);\n return {\n id: asString(reference.id),\n title: asString(reference.title),\n url: asString(reference.url),\n originalUrl: asString(reference.originalUrl),\n type: asString(reference.type),\n source: asString(reference.source),\n usedFactIds: asArray<string>(reference.usedFactIds).filter(Boolean),\n extractedFacts: asArray<unknown>(reference.extractedFacts).map(\n normalizeFact,\n ),\n };\n}\n\nfunction normalizePublicationVersion(\n value: unknown,\n): ContentTransparencyPublicationVersion | null {\n const publicationVersion = asObject(value);\n if (!publicationVersion.id && publicationVersion.version === undefined) {\n return null;\n }\n\n return {\n id: asString(publicationVersion.id),\n version: asNumber(publicationVersion.version),\n kind: asString(publicationVersion.kind),\n summary:\n typeof publicationVersion.summary === 'string'\n ? publicationVersion.summary\n : '',\n createdAt: asString(publicationVersion.createdAt),\n };\n}\n\nfunction normalizeVersionHistoryItem(\n value: unknown,\n): ContentTransparencyVersionHistoryItem {\n const version = asObject(value);\n return {\n id: asString(version.id),\n version: asNumber(version.version),\n kind: asString(version.kind),\n summary: typeof version.summary === 'string' ? version.summary : '',\n createdAt: asString(version.createdAt),\n provenance: asObject(version.provenance),\n };\n}\n\nfunction dedupeFacts(facts: ContentTransparencyFact[]) {\n const byKey = new Map<string, ContentTransparencyFact>();\n\n for (const fact of facts) {\n // Collapse effectively empty facts into a single placeholder bucket rather\n // than rendering duplicate blank entries in the public transparency view.\n const key =\n fact.id ||\n fact.textRefined ||\n fact.textRaw ||\n JSON.stringify(fact.metadata || {});\n if (!key) {\n continue;\n }\n\n byKey.set(key, fact);\n }\n\n return [...byKey.values()];\n}\n\nexport function normalizeContentTransparency(\n value: unknown,\n defaults: Partial<ContentTransparencyData> = {},\n): ContentTransparencyData {\n const snapshot = asObject(value);\n const references = asArray<unknown>(snapshot.references).map(\n normalizeReference,\n );\n const linkedFacts = asArray<unknown>(snapshot.linkedFacts).map(normalizeFact);\n const factsUsed =\n asArray<unknown>(snapshot.factsUsed).length > 0\n ? asArray<unknown>(snapshot.factsUsed).map(normalizeFact)\n : linkedFacts.filter((fact) => fact.usedInArticle);\n const otherExtractedFacts =\n asArray<unknown>(snapshot.otherExtractedFacts).length > 0\n ? asArray<unknown>(snapshot.otherExtractedFacts).map(normalizeFact)\n : dedupeFacts(\n references.flatMap((reference) =>\n reference.extractedFacts.filter((fact) => !fact.usedInArticle),\n ),\n );\n\n return {\n generatedAt: asString(snapshot.generatedAt) ?? defaults.generatedAt ?? null,\n snapshotKind:\n snapshot.snapshotKind === 'published'\n ? 'published'\n : defaults.snapshotKind || 'preview',\n contentId: asString(snapshot.contentId) ?? defaults.contentId ?? null,\n currentContentStatus:\n asString(snapshot.currentContentStatus) ??\n defaults.currentContentStatus ??\n null,\n publicationProfileKey:\n asString(snapshot.publicationProfileKey) ??\n asString(snapshot.publicationReviewProfileKey) ??\n defaults.publicationProfileKey ??\n 'publication',\n publicationVersion:\n normalizePublicationVersion(snapshot.publicationVersion) ??\n defaults.publicationVersion ??\n null,\n generation: normalizeGeneration(\n snapshot.generation ?? defaults.generation ?? {},\n ),\n factsUsed,\n linkedFacts,\n otherExtractedFacts,\n references,\n reviews: asArray<Record<string, any>>(snapshot.reviews),\n reviewProfiles: asArray<Record<string, any>>(snapshot.reviewProfiles),\n corrections: asArray<Record<string, any>>(snapshot.corrections),\n versionHistory: asArray<unknown>(snapshot.versionHistory).map(\n normalizeVersionHistoryItem,\n ),\n };\n}\n","export function isMissingTableError(\n error: unknown,\n tableName: string,\n): boolean {\n const message = String(\n (error as Error)?.message || error || '',\n ).toLowerCase();\n\n return (\n message.includes(tableName.toLowerCase()) &&\n (message.includes('no such table') ||\n message.includes('does not exist') ||\n message.includes('relation'))\n );\n}\n\nexport function getQueryRows(result: unknown): Record<string, unknown>[] {\n return Array.isArray(result)\n ? (result as Record<string, unknown>[])\n : Array.isArray((result as { rows?: Record<string, unknown>[] })?.rows)\n ? ((result as { rows: Record<string, unknown>[] }).rows ?? [])\n : [];\n}\n","function toJSON<T extends Record<string, any>>(value: any): T {\n if (value && typeof value.toJSON === 'function') {\n const serialized = value.toJSON();\n return serialized && typeof serialized === 'object'\n ? serialized\n : ({} as T);\n }\n\n return value && typeof value === 'object' ? value : ({} as T);\n}\n\nexport function serializeFact(fact: any) {\n const data = toJSON<Record<string, any>>(fact);\n return {\n ...data,\n metadata:\n typeof fact?.getMetadata === 'function'\n ? fact.getMetadata()\n : data.metadata || {},\n };\n}\n\nexport function serializeFactLink(link: any) {\n const data = toJSON<Record<string, any>>(link);\n return {\n ...data,\n metadata:\n typeof link?.getMetadata === 'function'\n ? link.getMetadata()\n : data.metadata || {},\n };\n}\n\nexport function serializeContentVersion(version: any) {\n const data = toJSON<Record<string, any>>(version);\n return {\n ...data,\n snapshot:\n typeof version?.getSnapshot === 'function'\n ? version.getSnapshot()\n : data.snapshot || {},\n metadata:\n typeof version?.getMetadata === 'function'\n ? version.getMetadata()\n : data.metadata || {},\n };\n}\n\nexport function serializeContentReview(review: any) {\n const data = toJSON<Record<string, any>>(review);\n return {\n ...data,\n findings:\n typeof review?.getFindings === 'function'\n ? review.getFindings()\n : data.findings || [],\n metadata:\n typeof review?.getMetadata === 'function'\n ? review.getMetadata()\n : data.metadata || {},\n };\n}\n\nexport function serializeContentCorrection(correction: any) {\n const data = toJSON<Record<string, any>>(correction);\n return {\n ...data,\n metadata:\n typeof correction?.getMetadata === 'function'\n ? correction.getMetadata()\n : data.metadata || {},\n };\n}\n\nexport function serializeContentContributor(contributor: any) {\n const data = toJSON<Record<string, any>>(contributor);\n return {\n ...data,\n metadata:\n typeof contributor?.getMetadata === 'function'\n ? contributor.getMetadata()\n : data.metadata || {},\n };\n}\n\nexport function serializeContentContributionType(contributionType: any) {\n const data = toJSON<Record<string, any>>(contributionType);\n return {\n ...data,\n allowedChannels:\n typeof contributionType?.getAllowedChannels === 'function'\n ? contributionType.getAllowedChannels()\n : data.allowedChannels || [],\n intakeRules:\n typeof contributionType?.getIntakeRules === 'function'\n ? contributionType.getIntakeRules()\n : data.intakeRules || {},\n promotion:\n typeof contributionType?.getPromotion === 'function'\n ? contributionType.getPromotion()\n : data.promotion || {},\n metadata:\n typeof contributionType?.getMetadata === 'function'\n ? contributionType.getMetadata()\n : data.metadata || {},\n };\n}\n\nexport function serializeContentContributionRevision(revision: any) {\n const data = toJSON<Record<string, any>>(revision);\n return {\n ...data,\n sourceMessageId: data.sourceMessageId || null,\n sourceThreadKey: data.sourceThreadKey || null,\n metadata:\n typeof revision?.getMetadata === 'function'\n ? revision.getMetadata()\n : data.metadata || {},\n };\n}\n\nexport function serializeContentContributionAttachment(attachment: any) {\n const data = toJSON<Record<string, any>>(attachment);\n return {\n ...data,\n revisionId: data.revisionId || null,\n fileKey: data.fileKey || null,\n sourceUri: data.sourceUri || null,\n promotedAssetId: data.promotedAssetId || null,\n metadata:\n typeof attachment?.getMetadata === 'function'\n ? attachment.getMetadata()\n : data.metadata || {},\n };\n}\n\nexport async function serializeContentContribution(contribution: any) {\n const [revisions, attachments, contributor] = await Promise.all([\n typeof contribution?.getRevisions === 'function'\n ? contribution.getRevisions()\n : [],\n typeof contribution?.getAttachments === 'function'\n ? contribution.getAttachments()\n : [],\n typeof contribution?.getContributor === 'function'\n ? contribution.getContributor()\n : null,\n ]);\n\n return {\n ...toJSON<Record<string, any>>(contribution),\n contributor: contributor ? serializeContentContributor(contributor) : null,\n revisions: revisions.map(serializeContentContributionRevision),\n attachments: attachments.map(serializeContentContributionAttachment),\n metadata:\n typeof contribution?.getMetadata === 'function'\n ? contribution.getMetadata()\n : contribution?.metadata || {},\n };\n}\n\nexport function serializeContentReviewProfileEvaluation(profile: any) {\n const data = toJSON<Record<string, any>>(profile);\n return {\n ...data,\n requirements: Array.isArray(data.requirements) ? data.requirements : [],\n };\n}\n\nexport function serializeContentReviewPolicy(policy: any) {\n return {\n ...toJSON<Record<string, any>>(policy),\n };\n}\n\nexport function serializeContentGovernanceProfile(profile: any) {\n const data = toJSON<Record<string, any>>(profile);\n return {\n ...data,\n requirements: Array.isArray(data.requirements) ? data.requirements : [],\n metadata:\n typeof profile?.getMetadata === 'function'\n ? profile.getMetadata()\n : data.metadata || {},\n };\n}\n\nexport function serializeContentGovernanceAssignment(assignment: any) {\n const data = toJSON<Record<string, any>>(assignment);\n return {\n ...data,\n metadata:\n typeof assignment?.getMetadata === 'function'\n ? assignment.getMetadata()\n : data.metadata || {},\n };\n}\n\nexport function serializeContentGovernanceState(state: any) {\n const data = toJSON<Record<string, any>>(state);\n return {\n ...data,\n reviewPolicies: Array.isArray(data.reviewPolicies)\n ? data.reviewPolicies.map(serializeContentReviewPolicy)\n : [],\n availableProfiles: Array.isArray(data.availableProfiles)\n ? data.availableProfiles.map(serializeContentGovernanceProfile)\n : [],\n reviewProfiles: Array.isArray(data.reviewProfiles)\n ? data.reviewProfiles.map(serializeContentReviewProfileEvaluation)\n : [],\n };\n}\n\nexport async function serializeContent(content: any) {\n const [references, assets] = await Promise.all([\n typeof content?.getReferences === 'function' ? content.getReferences() : [],\n typeof content?.getAssets === 'function' ? content.getAssets() : [],\n ]);\n\n // Only resolve drift when there are references to drift against — list\n // endpoints serializing many ref-less items shouldn't pay the version\n // lookup cost.\n const drift =\n references.length > 0 && typeof content?.getReferenceDrift === 'function'\n ? await content.getReferenceDrift()\n : [];\n\n const driftByTargetId = new Map<\n string,\n {\n citedVersion: number | null;\n currentVersion: number | null;\n isDrifted: boolean;\n }\n >(\n Array.isArray(drift)\n ? drift\n .filter((entry: any) => entry && typeof entry.targetId === 'string')\n .map((entry: any) => [\n entry.targetId,\n {\n citedVersion: entry.citedVersion ?? null,\n currentVersion: entry.currentVersion ?? null,\n isDrifted: Boolean(entry.isDrifted),\n },\n ])\n : [],\n );\n\n return {\n ...toJSON<Record<string, any>>(content),\n referenceIds: references\n .map((reference: any) => reference?.id)\n .filter(Boolean),\n references: references.map((reference: any) => {\n const base = toJSON<Record<string, any>>(reference);\n const edge = base?.id ? driftByTargetId.get(base.id as string) : null;\n return edge\n ? {\n ...base,\n citedVersion: edge.citedVersion,\n currentVersion: edge.currentVersion,\n isDrifted: edge.isDrifted,\n }\n : base;\n }),\n assetIds: assets.map((asset: any) => asset?.id).filter(Boolean),\n assets: assets.map((asset: any) => toJSON<Record<string, any>>(asset)),\n };\n}\n","/**\n * Thumbnail Generator for Content\n *\n * Generates thumbnail images for content using various strategies:\n * - headline-card: Draws article title on branded background\n * - static-map: Uses static maps API for location-based content\n * - ai-generate: Uses AI image generation for creative thumbnails\n */\n\nimport type { AIClient, AIClientOptions } from '@happyvertical/ai';\nimport { fetchStaticMap, type StaticMapProvider } from '@happyvertical/geo';\nimport {\n generateHeadlineCard,\n type HeadlineCardTemplate,\n} from '@happyvertical/images';\nimport type { DatabaseConfig } from '@happyvertical/smrt-core';\nimport type { Image } from '@happyvertical/smrt-images';\nimport { ImageCollection } from '@happyvertical/smrt-images';\nimport {\n type ResolvedPrompt,\n resolvePrompt,\n} from '@happyvertical/smrt-prompts';\nimport type { Content } from './content';\nimport {\n promptMessageOptions,\n smrtContentThumbnailAIGeneratePrompt,\n} from './content-prompts';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Available thumbnail generation strategies\n */\nexport type ThumbnailStrategy = 'headline-card' | 'static-map' | 'ai-generate';\n\n/**\n * Base options for all strategies\n */\ninterface BaseThumbnailOptions {\n /**\n * Generation strategy\n */\n strategy: ThumbnailStrategy;\n\n /**\n * Width in pixels\n * @default 1200\n */\n width?: number;\n\n /**\n * Height in pixels\n * @default 630\n */\n height?: number;\n}\n\n/**\n * Options for headline card strategy\n */\nexport interface HeadlineCardThumbnailOptions extends BaseThumbnailOptions {\n strategy: 'headline-card';\n\n /**\n * Primary brand color (hex)\n * @default '#3b82f6'\n */\n brandColor?: string;\n\n /**\n * Background color (hex)\n * @default '#ffffff'\n */\n backgroundColor?: string;\n\n /**\n * Optional subtitle/category text\n */\n subtitle?: string;\n\n /**\n * Optional logo URL\n */\n logoUrl?: string;\n\n /**\n * Template style\n * @default 'default'\n */\n template?: HeadlineCardTemplate;\n}\n\n/**\n * Options for static map strategy\n */\nexport interface StaticMapThumbnailOptions extends BaseThumbnailOptions {\n strategy: 'static-map';\n\n /**\n * Map provider\n * @default 'mapbox'\n */\n mapProvider?: StaticMapProvider;\n\n /**\n * Zoom level (1-20)\n * @default 14\n */\n zoom?: number;\n\n /**\n * Marker color\n * @default 'e74c3c'\n */\n markerColor?: string;\n\n /**\n * Mapbox style (if using mapbox provider)\n */\n mapboxStyle?: string;\n\n /**\n * Google map type (if using google provider)\n */\n googleMapType?: 'roadmap' | 'satellite' | 'terrain' | 'hybrid';\n}\n\n/**\n * Options for AI generation strategy\n */\nexport interface AIGenerateThumbnailOptions extends BaseThumbnailOptions {\n strategy: 'ai-generate';\n\n /**\n * AI provider configuration\n */\n ai?: AIClientOptions | AIClient;\n\n /**\n * Custom prompt for image generation\n * If not provided, generates based on content title/body\n */\n prompt?: string;\n\n /**\n * Style hint for image generation\n * @default 'photorealistic'\n */\n style?: 'photorealistic' | 'illustration' | 'abstract' | 'minimal';\n}\n\n/**\n * Union type for all thumbnail options\n */\nexport type ThumbnailOptions =\n | HeadlineCardThumbnailOptions\n | StaticMapThumbnailOptions\n | AIGenerateThumbnailOptions;\n\n// ============================================================================\n// Generator Class\n// ============================================================================\n\n/**\n * Options for ThumbnailGenerator\n */\nexport interface ThumbnailGeneratorOptions {\n /**\n * Database configuration for storing generated images\n */\n db?: DatabaseConfig;\n\n /**\n * Alias for `db` — mirrors the `SmrtClassOptions.persistence` alias so\n * callers can pass the same options shape they use for SmrtObject/Collection.\n *\n * @deprecated Prefer `db`. Retained for parity with `SmrtClassOptions`.\n */\n persistence?: DatabaseConfig;\n\n /**\n * AI client configuration for AI-generated thumbnails\n */\n ai?: AIClientOptions | AIClient;\n}\n\ninterface ImageGenerationClient {\n generateImage(\n prompt: string,\n options?: Record<string, unknown>,\n ): Promise<{\n images?: Array<{ data?: Buffer | string }>;\n }>;\n}\n\nfunction isImageGenerationClient(\n value: AIClientOptions | AIClient,\n): value is AIClient & ImageGenerationClient {\n return (\n !!value &&\n typeof value === 'object' &&\n typeof (value as Record<string, unknown>).generateImage === 'function'\n );\n}\n\nfunction isAIClientOptions(\n value: AIClientOptions | AIClient,\n): value is AIClientOptions {\n return (\n !!value && typeof value === 'object' && !isImageGenerationClient(value)\n );\n}\n\n/**\n * ThumbnailGenerator creates thumbnails for content using various strategies\n */\nexport class ThumbnailGenerator {\n constructor(\n private content: Content,\n private options: ThumbnailGeneratorOptions = {},\n ) {\n // Normalize the `persistence` alias to `db` once so every downstream call\n // (prompt resolution, ImageCollection.create, save sites) sees the same\n // database regardless of which option name the caller used. Without this,\n // a caller passing `persistence: ...` would have prompt resolution honor\n // the alias while image saving silently used `undefined`.\n if (!this.options.db && this.options.persistence) {\n this.options.db = this.options.persistence;\n }\n }\n\n /**\n * Generate a thumbnail using the specified strategy\n */\n async generate(options: ThumbnailOptions): Promise<Image> {\n switch (options.strategy) {\n case 'headline-card':\n return this.generateHeadlineCard(options);\n case 'static-map':\n return this.generateStaticMap(options);\n case 'ai-generate':\n return this.generateWithAI(options);\n default:\n throw new Error(\n `Unknown thumbnail strategy: ${(options as any).strategy}`,\n );\n }\n }\n\n /**\n * Generate a headline card thumbnail\n */\n private async generateHeadlineCard(\n options: HeadlineCardThumbnailOptions,\n ): Promise<Image> {\n const title = this.content.title || this.content.name || 'Untitled';\n\n const result = await generateHeadlineCard(title, {\n width: options.width ?? 1200,\n height: options.height ?? 630,\n brandColor: options.brandColor,\n backgroundColor: options.backgroundColor,\n subtitle: options.subtitle ?? this.content.category ?? undefined,\n logoUrl: options.logoUrl,\n template: options.template,\n });\n\n return this.createImageFromBuffer(result.buffer, {\n width: result.width,\n height: result.height,\n mimeType: result.mimeType,\n name: `${this.content.id}-headline.png`,\n });\n }\n\n /**\n * Generate a static map thumbnail\n */\n private async generateStaticMap(\n options: StaticMapThumbnailOptions,\n ): Promise<Image> {\n const rawLatitude =\n this.content.metadata?.latitude ?? this.content.metadata?.lat;\n const rawLongitude =\n this.content.metadata?.longitude ??\n this.content.metadata?.lng ??\n this.content.metadata?.lon;\n\n if (rawLatitude == null || rawLongitude == null) {\n throw new Error(\n 'Content metadata must contain latitude and longitude for static-map strategy',\n );\n }\n\n // Parse and validate coordinates\n // Use unary + for strict parsing (rejects \"45invalid\" unlike parseFloat)\n const latitude =\n typeof rawLatitude === 'string' ? +rawLatitude : rawLatitude;\n const longitude =\n typeof rawLongitude === 'string' ? +rawLongitude : rawLongitude;\n\n if (!Number.isFinite(latitude) || latitude < -90 || latitude > 90) {\n throw new Error(\n `Invalid latitude value \"${rawLatitude}\" in content metadata; expected a number between -90 and 90.`,\n );\n }\n\n if (!Number.isFinite(longitude) || longitude < -180 || longitude > 180) {\n throw new Error(\n `Invalid longitude value \"${rawLongitude}\" in content metadata; expected a number between -180 and 180.`,\n );\n }\n\n type FetchStaticMapOptions = NonNullable<\n Parameters<typeof fetchStaticMap>[2]\n >;\n const mapboxStyle = options.mapboxStyle as\n | FetchStaticMapOptions['mapboxStyle']\n | undefined;\n\n const result = await fetchStaticMap(latitude, longitude, {\n provider: options.mapProvider ?? 'mapbox',\n width: options.width ?? 1200,\n height: options.height ?? 630,\n zoom: options.zoom ?? 14,\n markerColor: options.markerColor,\n mapboxStyle,\n googleMapType: options.googleMapType,\n });\n\n return this.createImageFromBuffer(result.buffer, {\n width: result.width,\n height: result.height,\n mimeType: result.mimeType,\n name: `${this.content.id}-map.png`,\n });\n }\n\n /**\n * Generate a thumbnail using AI image generation\n */\n private async generateWithAI(\n options: AIGenerateThumbnailOptions,\n ): Promise<Image> {\n // Dynamic import to avoid requiring AI package when not using this strategy\n const { getAI } = await import('@happyvertical/ai');\n\n const aiInput = options.ai ?? this.options.ai;\n if (!aiInput) {\n throw new Error(\n 'AI configuration required for ai-generate strategy. Provide via options.ai or constructor options.',\n );\n }\n\n const ai = isImageGenerationClient(aiInput)\n ? aiInput\n : isAIClientOptions(aiInput)\n ? await getAI(aiInput)\n : (() => {\n throw new Error(\n 'AI client does not support image generation for ai-generate thumbnails.',\n );\n })();\n\n // Generate prompt if not provided. When the caller supplies a literal\n // prompt we skip prompt resolution entirely (no tenant override path).\n // When we resolve from the registry we also forward the resolved AI\n // options (model, params) so `editable: { model, params }` actually\n // takes effect for thumbnail generation.\n const width = options.width ?? 1200;\n const height = options.height ?? 630;\n let prompt: string;\n let aiOverrideOptions: Record<string, unknown> = {};\n if (options.prompt) {\n prompt = options.prompt;\n } else {\n const built = await this.buildAIPrompt(options.style ?? 'photorealistic');\n prompt = built.text;\n aiOverrideOptions = promptMessageOptions(built.ai);\n }\n\n const result = await ai.generateImage(prompt, {\n ...aiOverrideOptions,\n size: `${width}x${height}`,\n outputFormat: 'buffer',\n });\n\n if (!result.images || result.images.length === 0) {\n throw new Error('AI image generation returned no results');\n }\n\n // Handle buffer or base64 responses\n let buffer: Buffer;\n const imageData = result.images[0].data;\n if (Buffer.isBuffer(imageData)) {\n buffer = imageData;\n } else if (typeof imageData === 'string') {\n // Could be base64 or URL - try base64 first\n if (imageData.startsWith('http')) {\n const response = await fetch(imageData);\n if (!response.ok) {\n throw new Error(\n `AI image generation URL fetch failed: ${response.status} ${response.statusText}`,\n );\n }\n buffer = Buffer.from(await response.arrayBuffer());\n } else {\n buffer = Buffer.from(imageData, 'base64');\n }\n } else {\n throw new Error('AI image generation returned unexpected format');\n }\n\n return this.createImageFromBuffer(buffer, {\n width: options.width ?? 1200,\n height: options.height ?? 630,\n mimeType: 'image/png',\n name: `${this.content.id}-ai.png`,\n });\n }\n\n /**\n * Build a prompt for AI image generation based on content.\n *\n * Resolves via `@happyvertical/smrt-prompts` so tenants can override the\n * template/profile/model/params at runtime. Only non-PII content fields\n * (title, description) and the caller-supplied style hint are passed.\n * Internal IDs and the freeform `metadata` blob are intentionally excluded.\n *\n * Returns the full ResolvedPrompt (text + ai config) so the caller can\n * forward `model`/`params` overrides to `ai.generateImage()`. Returning\n * only the text would silently drop the editable model/params overrides.\n */\n private async buildAIPrompt(style: string): Promise<ResolvedPrompt> {\n const title = this.content.title || 'Untitled';\n const description = this.content.description || '';\n\n const stylePrompts: Record<string, string> = {\n photorealistic:\n 'photorealistic, high quality, professional photography, 8k resolution',\n illustration:\n 'digital illustration, clean vector art, modern design, vibrant colors',\n abstract:\n 'abstract art, geometric shapes, modern minimalist, artistic interpretation',\n minimal:\n 'minimalist design, simple shapes, clean composition, subtle colors',\n };\n\n const styleHint = stylePrompts[style] || stylePrompts.photorealistic;\n\n return resolvePrompt(smrtContentThumbnailAIGeneratePrompt.key, {\n db: this.options.db,\n tenantId: this.content.tenantId,\n variables: {\n style,\n title,\n styleHint,\n descriptionClause: description\n ? `The article is about: ${description}. `\n : '',\n },\n });\n }\n\n /**\n * Create an Image object from a buffer\n */\n private async createImageFromBuffer(\n buffer: Buffer,\n metadata: {\n width: number;\n height: number;\n mimeType: string;\n name: string;\n },\n ): Promise<Image> {\n const images = await (ImageCollection as any).create({\n db: this.options.db,\n });\n\n // Create the image record. `SmrtCollection.create()` already persists\n // (upsert) the row, so a follow-up `image.save()` was redundant (#1387).\n const image = await images.create({\n name: metadata.name,\n mimeType: metadata.mimeType,\n width: metadata.width,\n height: metadata.height,\n sourceUri: `data:${metadata.mimeType};base64,${buffer.toString('base64')}`,\n });\n\n return image;\n }\n}\n","import { type Asset, AssetCollection } from '@happyvertical/smrt-assets';\nimport type { SmrtObjectOptions } from '@happyvertical/smrt-core';\nimport {\n crossPackageRef,\n field,\n SmrtObject,\n smrt,\n ValidationError,\n} from '@happyvertical/smrt-core';\nimport type {\n Fact,\n FactClaimSupportAssessment,\n FactClaimSupportStatus,\n FactContentRelationship,\n FactEvidenceStatus,\n FactExtractionCandidate,\n} from '@happyvertical/smrt-facts';\nimport type { Image } from '@happyvertical/smrt-images';\nimport { ImageCollection } from '@happyvertical/smrt-images';\nimport { resolvePrompt } from '@happyvertical/smrt-prompts';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport type { AssetAssociable, MetadataAccessor } from './asset-associable';\nimport { isPlainMetadataRecord } from './asset-associable';\nimport type { ContentBodyFormat } from './body-format';\nimport { isContentBodyFormat } from './body-format';\nimport { ContentAssetCollection } from './content-assets';\nimport {\n buildContentGovernanceAssignmentKey,\n buildContentReviewPrompt,\n type ContentGovernanceState,\n type ContentReviewFinding,\n type ContentReviewProfileEvaluation,\n type CreateContentVersionOptions,\n getAcceptedContentReviewStatuses,\n getContentReviewKind,\n getContentReviewPolicy,\n getContentReviewProfileKeys,\n getContentReviewRequirements,\n type IssueContentCorrectionOptions,\n parseContentReviewResponse,\n type ResolvedContentGovernance,\n type RunContentReviewOptions,\n resolveConfiguredContentGovernance,\n resolveEffectiveContentGovernance,\n} from './content-governance';\nimport {\n promptMessageOptions,\n smrtContentApplyCorrectionPrompt,\n smrtContentReviewPrompt,\n} from './content-prompts';\nimport { ContentReferences } from './content-references';\nimport type { ContentReview } from './content-review';\nimport { normalizeContentTransparency } from './content-transparency';\nimport { isMissingTableError } from './database-utils';\nimport {\n serializeContent,\n serializeContentCorrection,\n serializeContentReview,\n serializeContentVersion,\n serializeFact,\n serializeFactLink,\n} from './serialization';\nimport type { ThumbnailOptions } from './thumbnail-generator';\nimport { ThumbnailGenerator } from './thumbnail-generator';\n\nconst USED_FACT_RELATIONSHIPS = new Set<FactContentRelationship>([\n 'supports',\n 'referenced_in',\n 'contradicts',\n]);\nconst FACT_AUDIT_GENERATED_BY = 'content.factAudit';\nconst FACT_AUDIT_DOMAIN = 'content-audit';\n\ntype FactAuditSourceMaterial = {\n sourceKind: string;\n sourceId: string;\n sourceUrl: string;\n sourceTitle: string;\n locator: string;\n text: string;\n};\n\ntype FactAuditSourceSelector = {\n sourceKind: string;\n sourceId: string;\n};\n\ntype FactAuditResourceRepairOptions = {\n sources?: FactAuditSourceSelector[];\n maxFactsPerSource?: number;\n context?: string;\n};\n\ntype FactAuditClaimRecheckOptions = {\n claimFactIds?: string[];\n sourceIds?: string[];\n sources?: FactAuditSourceSelector[];\n maxCandidateEvidence?: number;\n};\n\ntype FactEvidenceStatusUpdateOptions = {\n evidenceIds?: string[];\n status?: FactEvidenceStatus;\n reason?: string;\n};\n\ntype FactAuditClaim = {\n id: string | null;\n fact: Record<string, any>;\n supportStatus: FactClaimSupportStatus;\n claimQuote: string | null;\n rationale: string | null;\n confidence: number | null;\n relationship: string | null;\n linkMetadata: Record<string, any>;\n evidence: Record<string, any>[];\n matchedFacts: Array<{\n fact: Record<string, any>;\n evidence: Record<string, any>[];\n }>;\n};\n\ntype FactAuditResourceClaim = {\n id: string | null;\n fact: Record<string, any>;\n sourceKind: string | null;\n sourceId: string | null;\n sourceUrl: string | null;\n sourceTitle: string | null;\n locator: string | null;\n quote: string | null;\n status: FactEvidenceStatus;\n confidence: number | null;\n evidence: Record<string, any>[];\n};\n\ntype FactAuditState = {\n counts: Record<FactClaimSupportStatus | 'total', number>;\n claims: FactAuditClaim[];\n resourceClaims: FactAuditResourceClaim[];\n warnings: string[];\n generatedBy: string;\n latestAuditRunId: string | null;\n};\n\nfunction normalizeFingerprintValue(value: unknown): unknown {\n if (value instanceof Date) {\n return value.toISOString();\n }\n\n if (Array.isArray(value)) {\n return value.map((entry) => normalizeFingerprintValue(entry));\n }\n\n if (value && typeof value === 'object') {\n return Object.fromEntries(\n Object.entries(value as Record<string, unknown>)\n .sort(([left], [right]) => left.localeCompare(right))\n .map(([key, entryValue]) => [\n key,\n normalizeFingerprintValue(entryValue),\n ]),\n );\n }\n\n return value ?? null;\n}\n\nfunction hashFingerprint(input: string): string {\n let hash = 5381;\n\n for (let index = 0; index < input.length; index += 1) {\n hash = (hash * 33) ^ input.charCodeAt(index);\n }\n\n return `fp-${(hash >>> 0).toString(16).padStart(8, '0')}`;\n}\n\nfunction createFingerprint(value: unknown): string {\n return hashFingerprint(JSON.stringify(normalizeFingerprintValue(value)));\n}\n\nfunction normalizeAuditText(value: unknown): string {\n return String(value ?? '')\n .trim()\n .replace(/\\s+/g, ' ');\n}\n\nfunction createFactAuditRunId(contentId: string): string {\n return `fact-audit-${hashFingerprint(\n `${contentId}:${new Date().toISOString()}:${Math.random()}`,\n )}`;\n}\n\nfunction parseAuditMetadata(value: unknown): Record<string, any> {\n if (!value) return {};\n if (typeof value === 'object') return value as Record<string, any>;\n try {\n return JSON.parse(String(value)) as Record<string, any>;\n } catch {\n return {};\n }\n}\n\nfunction getLinkMetadata(link: any): Record<string, any> {\n return typeof link?.getMetadata === 'function' ? link.getMetadata() : {};\n}\n\nfunction getFactMetadata(fact: any): Record<string, any> {\n return typeof fact?.getMetadata === 'function'\n ? fact.getMetadata()\n : parseAuditMetadata(fact?.metadata);\n}\n\nfunction getGeneratedFactAuditMetadata(link: any): Record<string, any> | null {\n const metadata = getLinkMetadata(link);\n if (metadata.generatedBy === FACT_AUDIT_GENERATED_BY) {\n return metadata;\n }\n\n if (\n metadata.factAudit &&\n typeof metadata.factAudit === 'object' &&\n metadata.factAudit.generatedBy === FACT_AUDIT_GENERATED_BY\n ) {\n return metadata.factAudit as Record<string, any>;\n }\n\n return null;\n}\n\nfunction getEvidenceMetadata(evidence: any): Record<string, any> {\n return typeof evidence?.getMetadata === 'function'\n ? evidence.getMetadata()\n : parseAuditMetadata(evidence?.metadata);\n}\n\nfunction isGeneratedFactAuditEvidence(\n evidence: any,\n contentId: string,\n): boolean {\n const metadata = getEvidenceMetadata(evidence);\n return (\n metadata.generatedBy === FACT_AUDIT_GENERATED_BY &&\n metadata.contentId === contentId\n );\n}\n\nfunction isGeneratedArticleClaimFact(fact: any, contentId: string): boolean {\n const metadata = getFactMetadata(fact);\n if (metadata.generatedBy !== FACT_AUDIT_GENERATED_BY) {\n return false;\n }\n\n const role = metadata.auditFactRole || metadata.factAuditRole;\n const isArticleClaim =\n role === 'article-claim' || metadata.claimOnly === true;\n\n return isArticleClaim && metadata.contentId === contentId;\n}\n\nfunction normalizeFactEvidenceStatus(\n value: unknown,\n): FactEvidenceStatus | null {\n const allowed: FactEvidenceStatus[] = [\n 'supports',\n 'contradicts',\n 'unclear',\n 'irrelevant',\n 'invalid',\n ];\n\n return allowed.includes(value as FactEvidenceStatus)\n ? (value as FactEvidenceStatus)\n : null;\n}\n\nfunction sourceMatchesSelector(\n source: FactAuditSourceMaterial,\n selector: FactAuditSourceSelector,\n): boolean {\n return (\n source.sourceKind === selector.sourceKind &&\n source.sourceId === selector.sourceId\n );\n}\n\nfunction filterAuditSources(\n sources: FactAuditSourceMaterial[],\n selectors: FactAuditSourceSelector[] | undefined,\n): FactAuditSourceMaterial[] {\n if (!selectors || selectors.length === 0) {\n return sources;\n }\n\n return sources.filter((source) =>\n selectors.some((selector) => sourceMatchesSelector(source, selector)),\n );\n}\n\nfunction getContentText(content: Content): string {\n return [content.title, content.description, content.body]\n .map(normalizeAuditText)\n .filter(Boolean)\n .join('\\n\\n');\n}\n\nfunction getPublicPrompt(metadata: Record<string, any>): string | null {\n return (\n metadata?.transparency?.generation?.publicPrompt ||\n metadata?.generation?.publicPrompt ||\n metadata?.publicPrompt ||\n null\n );\n}\n\n/**\n * Options for Content initialization\n */\nexport interface ContentOptions extends SmrtObjectOptions {\n /**\n * Content type classification\n */\n type?: string | null;\n\n /**\n * Content variant for namespaced classification within types\n * Format: generator:domain:specific-type\n * Example: \"praeco:meeting:upcoming\"\n */\n variant?: string | null;\n\n /**\n * Reference to file storage key\n */\n fileKey?: string | null;\n\n /**\n * Author of the content\n */\n author?: string | null;\n\n /**\n * Content title\n */\n title?: string | null;\n\n /**\n * Short description or summary\n */\n description?: string | null;\n\n /**\n * Main content body text\n */\n body?: string | null;\n\n /**\n * Stored body format.\n */\n bodyFormat?: ContentBodyFormat | null;\n\n /**\n * Date when content was published\n */\n publish_date?: Date | null;\n\n /**\n * URL source of the content\n */\n url?: string | null;\n\n /**\n * Original source identifier\n */\n source?: string | null;\n\n /**\n * Publication status\n */\n status?: 'published' | 'draft' | 'review' | 'archived' | 'deleted' | null;\n\n /**\n * Content state flag\n */\n state?: 'deprecated' | 'active' | 'highlighted' | null;\n\n /**\n * Original URL of the content\n */\n original_url?: string | null;\n\n /**\n * Content language\n */\n language?: string | null;\n\n /**\n * Content tags\n */\n tags?: string[];\n\n /**\n * Hierarchical category path for URL routing\n * Format: 'parent/child' (e.g., 'politics/local')\n * Each content belongs to exactly ONE category\n */\n category?: string | null;\n\n /**\n * Additional metadata\n */\n metadata?: Record<string, any>;\n\n /**\n * ID of the thumbnail asset for this content\n */\n thumbnailAssetId?: string | null;\n\n /**\n * Transient reference IDs used by editors and API payloads.\n * These are synchronized into ContentReference links during save.\n */\n referenceIds?: string[];\n\n /**\n * Transient asset IDs used by editors and API payloads.\n */\n assetIds?: string[];\n\n /**\n * Tenant ID for multi-tenant isolation\n */\n tenantId?: string | null;\n}\n\n/**\n * Structured content object with metadata and body text\n *\n * Content represents any text-based content with metadata such as\n * title, author, description, and publishing information. It supports\n * referencing related content objects.\n */\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableStrategy: 'sti',\n api: {\n include: [\n 'list',\n 'get',\n 'create',\n 'update',\n 'delete',\n 'getFactsState',\n 'syncFactsState',\n 'getFactAuditStateAction',\n 'repairFactAuditAction',\n 'repairFactEvidenceAction',\n 'recheckFactClaimsAction',\n 'updateFactEvidenceStatusAction',\n 'getGovernanceStateAction',\n 'listReviews',\n 'runReviewAction',\n 'listReviewProfilesAction',\n 'evaluateReviewProfileAction',\n 'getPublishedTransparencyAction',\n 'previewTransparencyAction',\n 'listCorrections',\n 'issueCorrectionAction',\n 'listVersions',\n 'mutateVersionAction',\n ],\n routes: {\n getFactsState: { method: 'GET', path: 'facts' },\n syncFactsState: { method: 'PUT', path: 'facts' },\n getFactAuditStateAction: { method: 'GET', path: 'fact-audit' },\n repairFactAuditAction: { method: 'POST', path: 'fact-audit/repair' },\n repairFactEvidenceAction: {\n method: 'POST',\n path: 'fact-audit/evidence/repair',\n },\n recheckFactClaimsAction: {\n method: 'POST',\n path: 'fact-audit/claims/recheck',\n },\n updateFactEvidenceStatusAction: {\n method: 'PUT',\n path: 'fact-audit/evidence/status',\n },\n getGovernanceStateAction: { method: 'GET', path: 'governance' },\n listReviews: { method: 'GET', path: 'reviews' },\n runReviewAction: { method: 'POST', path: 'reviews' },\n listReviewProfilesAction: { method: 'GET', path: 'review-profiles' },\n evaluateReviewProfileAction: {\n method: 'GET',\n path: 'review-profiles/[profileKey]',\n },\n getPublishedTransparencyAction: {\n method: 'GET',\n path: 'transparency',\n },\n previewTransparencyAction: {\n method: 'GET',\n path: 'transparency/preview',\n },\n listCorrections: { method: 'GET', path: 'corrections' },\n issueCorrectionAction: { method: 'POST', path: 'corrections' },\n listVersions: { method: 'GET', path: 'versions' },\n mutateVersionAction: { method: 'POST', path: 'versions' },\n },\n serializers: {\n item: {\n importPath: '$lib/server/content-api-serializers',\n exportName: 'serializeContent',\n },\n },\n },\n mcp: {\n include: ['list', 'get', 'create', 'update'], // AI tools for content management\n },\n cli: true, // Enable CLI commands for content management\n})\nexport class Content\n extends SmrtObject\n implements AssetAssociable, MetadataAccessor\n{\n /**\n * Tenant ID for multi-tenant isolation\n * Nullable to support both tenant-scoped and global content\n */\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n /**\n * Array of referenced content objects\n */\n protected references: Content[] = [];\n\n /**\n * Content type classification\n */\n public type: string | null = null;\n\n /**\n * Content variant for namespaced classification within types\n * Format: generator:domain:specific-type\n * Example: \"praeco:meeting:upcoming\"\n */\n public variant: string | null = null;\n\n /**\n * Reference to file storage key\n */\n public fileKey: string | null = null;\n\n /**\n * Author of the content\n */\n public author: string | null = null;\n\n /**\n * Human-readable name for SMRT framework compatibility\n */\n @field({ required: true })\n public name: string = '';\n\n /**\n * Content title\n */\n public title = '';\n\n /**\n * Short description or summary\n */\n public description: string | null = null;\n\n /**\n * Main content body text\n */\n public body = '';\n\n /**\n * Format used to persist the body field.\n */\n public bodyFormat: ContentBodyFormat | null = null;\n\n /**\n * Date when content was published\n */\n public publish_date: Date | null = null;\n\n /**\n * URL source of the content\n */\n public url: string | null = null;\n\n /**\n * Original source identifier\n */\n public source: string | null = null;\n\n /**\n * Original URL of the content\n */\n public original_url: string | null = null;\n\n /**\n * Content language\n */\n public language: string | null = null;\n\n /**\n * Content tags\n */\n public tags: string[] = [];\n\n /**\n * Hierarchical category path for URL routing\n * Format: 'parent/child' (e.g., 'politics/local')\n * Each content belongs to exactly ONE category\n */\n public category: string | null = null;\n\n /**\n * Publication status\n */\n public status: 'published' | 'draft' | 'review' | 'archived' | 'deleted' =\n 'draft';\n\n /**\n * Content state flag\n */\n public state: 'deprecated' | 'active' | 'highlighted' = 'active';\n\n /**\n * Additional JSON metadata for flexible schema extension\n */\n public metadata: Record<string, any> = {};\n\n /**\n * ID of the thumbnail asset for this content\n */\n @crossPackageRef('@happyvertical/smrt-assets:Asset')\n public thumbnailAssetId: string | null = null;\n\n /**\n * Creates a new Content instance\n */\n constructor(options: ContentOptions = {}) {\n super(options);\n this.type = options.type || null;\n this.variant = options.variant || null;\n this.fileKey = options.fileKey || null;\n this.author = options.author || null;\n if (options.name) this.name = options.name;\n this.title = options.title || '';\n this.description = options.description || null;\n this.body = options.body || '';\n this.bodyFormat = isContentBodyFormat(options.bodyFormat)\n ? options.bodyFormat\n : null;\n this.publish_date = options.publish_date || null;\n this.source = options.source || null;\n this.original_url = options.original_url || null;\n this.language = options.language || null;\n this.status = options.status || 'draft';\n this.tags = options.tags || [];\n this.category = options.category || null;\n this.state = options.state || 'active';\n this.metadata = options.metadata || {};\n this.thumbnailAssetId = options.thumbnailAssetId ?? null;\n if (Array.isArray(options.referenceIds)) {\n (this as any).referenceIds = [...options.referenceIds];\n }\n if (Array.isArray(options.assetIds)) {\n (this as any).assetIds = [...options.assetIds];\n }\n }\n\n /**\n * Initializes this content object\n *\n * @returns Promise that resolves to this instance\n */\n async initialize(): Promise<this> {\n await super.initialize();\n return this;\n }\n\n protected override async validateBeforeSave(): Promise<void> {\n if (!this.name && this.title) {\n this.name = this.title;\n }\n\n if (!this.title && this.name) {\n this.title = this.name;\n }\n\n await super.validateBeforeSave();\n\n if (this.status !== 'published') {\n return;\n }\n\n const governance = await this.resolvePublicationGovernance();\n const profileKey = governance?.publicationProfileKey;\n\n if (\n !governance?.isGoverned ||\n !governance.enforcePublishReadiness ||\n !profileKey\n ) {\n return;\n }\n\n const evaluation = await this.evaluateReviewProfile(profileKey);\n const blockingRequirements = evaluation.requirements.filter(\n (requirement) => requirement.blocking && !requirement.satisfied,\n );\n\n if (blockingRequirements.length === 0) {\n return;\n }\n\n const details = blockingRequirements.map((requirement) => {\n if (requirement.missing) {\n return `${requirement.label} has not been run yet`;\n }\n\n if (requirement.stale) {\n return `${requirement.label} is stale and must be rerun`;\n }\n\n if (requirement.latestStatus) {\n return `${requirement.label} returned ${requirement.latestStatus}`;\n }\n\n return `${requirement.label} is not satisfied`;\n });\n\n throw new ValidationError(\n `Cannot publish content until the \"${profileKey}\" review profile is satisfied. ${details.join('; ')}`,\n 'VALIDATION_PUBLISH_READINESS',\n {\n profileKey,\n blockingRequirements: blockingRequirements.map((requirement) => ({\n policyKey: requirement.policyKey,\n label: requirement.label,\n missing: requirement.missing,\n stale: requirement.stale,\n latestStatus: requirement.latestStatus,\n })),\n },\n );\n }\n\n override async save() {\n const shouldConsiderPublicationSnapshot = this.status === 'published';\n\n let governance: ResolvedContentGovernance | null = null;\n let previous: Content | null = null;\n let previousPublicationFingerprint: string | null = null;\n\n if (shouldConsiderPublicationSnapshot) {\n governance = await this.resolvePublicationGovernance();\n\n if (governance?.isGoverned && governance.transparencyEnabled) {\n previous = await this.getPersistedContent();\n previousPublicationFingerprint =\n await this.getLatestPublicationSnapshotFingerprint();\n }\n }\n\n await super.save();\n await this.syncPendingReferenceIds();\n await this.syncPendingAssetIds();\n\n if (\n !shouldConsiderPublicationSnapshot ||\n !governance?.isGoverned ||\n !governance.transparencyEnabled\n ) {\n return this;\n }\n\n const nextPublicationFingerprint =\n await this.buildPublicationSnapshotFingerprint(governance);\n\n if (\n nextPublicationFingerprint &&\n nextPublicationFingerprint !== previousPublicationFingerprint\n ) {\n await this.createVersion({\n kind: 'publication',\n summary:\n previous?.status === 'published'\n ? 'Published content updated.'\n : 'Content published.',\n metadata: {\n publicationSnapshotFingerprint: nextPublicationFingerprint,\n publicationProfileKey: governance.publicationProfileKey,\n transparency: await this.buildTransparencySnapshot({\n snapshotKind: 'published',\n governance,\n }),\n },\n });\n }\n\n return this;\n }\n\n private async getReferenceCollection() {\n return ContentReferences.create({ db: this.db });\n }\n\n private async getFactCollection() {\n const { FactCollection } = await import('@happyvertical/smrt-facts');\n return FactCollection.create(this.options);\n }\n\n private async getFactContentCollection() {\n const { FactContentCollection } = await import('@happyvertical/smrt-facts');\n return FactContentCollection.create(this.options);\n }\n\n private async getFactSourceCollection() {\n const { FactSourceCollection } = await import('@happyvertical/smrt-facts');\n return FactSourceCollection.create(this.options);\n }\n\n private async getFactEvidenceCollection() {\n const { FactEvidenceCollection } = await import(\n '@happyvertical/smrt-facts'\n );\n return FactEvidenceCollection.create(this.options);\n }\n\n private async getContentVersionCollection() {\n const { ContentVersionCollection } = await import('./content-versions');\n return ContentVersionCollection.create(this.options);\n }\n\n private async getContentReviewCollection() {\n const { ContentReviewCollection } = await import('./content-reviews');\n return ContentReviewCollection.create(this.options);\n }\n\n private async getContentCorrectionCollection() {\n const { ContentCorrectionCollection } = await import(\n './content-corrections'\n );\n return ContentCorrectionCollection.create(this.options);\n }\n\n private async getContentsCollection() {\n const { Contents } = await import('./contents');\n return Contents.create({ db: this.db });\n }\n\n private getConfiguredGovernance(): ResolvedContentGovernance {\n return resolveConfiguredContentGovernance({\n contentType: this.type,\n contentVariant: this.variant,\n });\n }\n\n public async resolveGovernance(): Promise<ResolvedContentGovernance> {\n return resolveEffectiveContentGovernance({\n contentType: this.type,\n contentVariant: this.variant,\n db: this.db,\n });\n }\n\n private async hasPersistedGovernanceAssignments(): Promise<boolean> {\n if (!this.db || typeof this.db.query !== 'function') {\n return false;\n }\n\n try {\n const exactKey = buildContentGovernanceAssignmentKey(\n this.type || '',\n this.variant || '',\n );\n const typeOnlyKey = buildContentGovernanceAssignmentKey(this.type || '');\n const keys =\n exactKey === typeOnlyKey ? [exactKey] : [exactKey, typeOnlyKey];\n const placeholders = keys.map(() => '?').join(', ');\n const result = await this.db.query(\n `SELECT 1 AS matched FROM content_governance_assignments WHERE key IN (${placeholders}) LIMIT 1`,\n keys,\n );\n const rows = Array.isArray(result) ? result : (result?.rows ?? []);\n return rows.length > 0;\n } catch {\n return false;\n }\n }\n\n private async resolvePublicationGovernance(): Promise<ResolvedContentGovernance | null> {\n const configuredGovernance = this.getConfiguredGovernance();\n\n if (configuredGovernance.isGoverned) {\n return this.resolveGovernance();\n }\n\n if (!(await this.hasPersistedGovernanceAssignments())) {\n return null;\n }\n\n const governance = await this.resolveGovernance();\n return governance.isGoverned ? governance : null;\n }\n\n private async requireGovernance(\n feature = 'governance workflow',\n ): Promise<ResolvedContentGovernance> {\n const governance = await this.resolveGovernance();\n\n if (!governance.isGoverned) {\n throw new Error(\n `Governance is not enabled for content type \"${this.type || 'content'}\"${this.variant ? ` variant \"${this.variant}\"` : ''}, so ${feature} is unavailable.`,\n );\n }\n\n return governance;\n }\n\n private async requireFactLinking(\n feature = 'fact linking',\n ): Promise<ResolvedContentGovernance> {\n const governance = await this.requireGovernance(feature);\n\n if (!governance.factLinkingEnabled) {\n throw new Error(\n `Fact linking is not enabled for content type \"${this.type || 'content'}\"${this.variant ? ` variant \"${this.variant}\"` : ''}.`,\n );\n }\n\n return governance;\n }\n\n private async getPersistedContent(): Promise<Content | null> {\n if (!this.id) {\n return null;\n }\n\n const contents = await this.getContentsCollection();\n return (await contents.get({ id: this.id as string })) as Content | null;\n }\n\n private async buildReviewFingerprint(policyKey: string): Promise<string> {\n const governance = await this.resolveGovernance();\n const kind = getContentReviewKind(policyKey, governance.reviewPolicies);\n const policy = getContentReviewPolicy(policyKey, governance.reviewPolicies);\n const [references, facts, factLinks] = await Promise.all([\n this.getReferences(),\n kind === 'facts' && governance.factLinkingEnabled\n ? this.getFacts({\n latestOnly: true,\n includeSuperseded: false,\n })\n : Promise.resolve([]),\n kind === 'facts' && governance.factLinkingEnabled\n ? this.getFactLinks()\n : Promise.resolve([]),\n ]);\n\n return createFingerprint({\n scope: 'content-review',\n policyKey,\n kind,\n policyInstructions: policy?.instructions || '',\n content: {\n id: this.id || null,\n type: this.type,\n variant: this.variant,\n title: this.title,\n description: this.description,\n body: this.body,\n author: this.author,\n state: this.state,\n publishDate: this.publish_date,\n language: this.language,\n category: this.category,\n tags: this.tags,\n metadata: this.metadata,\n },\n referenceIds: references\n .map((reference) => reference.id)\n .filter(Boolean)\n .sort(),\n facts: facts.map((fact: any) => ({\n id: fact.id || null,\n // Pre-R3-C this was `parentId`; renamed to `previousFactId` in\n // smrt-facts. Existing cached fingerprints will invalidate, which\n // is the correct behaviour — the review surface (a key in the\n // hash) changed.\n previousFactId: fact.previousFactId || null,\n status: fact.status || null,\n textRefined: fact.textRefined || '',\n sourceCount: fact.sourceCount ?? 0,\n confidence: fact.confidence ?? null,\n metadata:\n typeof fact?.getMetadata === 'function' ? fact.getMetadata() : {},\n })),\n factLinks: factLinks.map((link: any) => ({\n factId: link.factId || null,\n relationship: link.relationship || null,\n metadata:\n typeof link?.getMetadata === 'function' ? link.getMetadata() : {},\n })),\n });\n }\n\n private async buildTransparencySnapshot(\n options: {\n snapshotKind?: 'preview' | 'published';\n governance?: ResolvedContentGovernance;\n } = {},\n ) {\n const snapshotKind = options.snapshotKind || 'preview';\n const governance = options.governance || (await this.resolveGovernance());\n\n if (!governance.isGoverned || !governance.transparencyEnabled) {\n return null;\n }\n\n const [\n references,\n facts,\n factLinks,\n reviews,\n corrections,\n versions,\n reviewProfiles,\n ] = await Promise.all([\n this.getReferences(),\n governance.factLinkingEnabled\n ? this.getFacts({\n latestOnly: true,\n includeSuperseded: false,\n })\n : Promise.resolve([]),\n governance.factLinkingEnabled ? this.getFactLinks() : Promise.resolve([]),\n this.listReviews(),\n this.listCorrections(),\n this.listVersions(),\n this.listReviewProfilesAction(),\n ]);\n\n const factSources = await this.getFactSourceCollection();\n const factSourcesByFactId = new Map<string, any[]>();\n\n for (const fact of facts) {\n const factId = fact.id as string | undefined;\n if (!factId) {\n continue;\n }\n\n const sources = await factSources.getForFact(factId);\n factSourcesByFactId.set(factId, sources);\n }\n\n const usedFactIds = new Set(\n factLinks\n .filter((link: any) =>\n USED_FACT_RELATIONSHIPS.has(\n (link.relationship || 'related') as FactContentRelationship,\n ),\n )\n .map((link: any) => link.factId)\n .filter(Boolean),\n );\n\n const linkedFacts = facts.map((fact: any) => {\n const factId = fact.id as string | undefined;\n const link = factLinks.find((entry: any) => entry.factId === factId);\n const sources = (factId ? factSourcesByFactId.get(factId) : []) || [];\n\n return {\n ...serializeFact(fact),\n relationship: link?.relationship || null,\n linkMetadata:\n typeof link?.getMetadata === 'function' ? link.getMetadata() : {},\n usedInArticle: factId ? usedFactIds.has(factId) : false,\n sources: sources.map((source: any) => ({\n id: source.id || null,\n sourceType: source.sourceType || null,\n sourceUrl: source.sourceUrl || null,\n sourceTitle: source.sourceTitle || null,\n credibility: source.credibility ?? null,\n extractedAt: source.extractedAt || null,\n metadata:\n typeof source?.getMetadata === 'function'\n ? source.getMetadata()\n : {},\n })),\n };\n });\n\n const referenceGroups = await Promise.all(\n references.map(async (reference) => {\n const sourceUrls = [\n reference.url,\n reference.original_url,\n reference.source,\n ].filter(Boolean) as string[];\n\n const extractedFacts = new Map<string, any>();\n for (const sourceUrl of sourceUrls) {\n const matches = await factSources.list({\n where: { sourceUrl },\n orderBy: 'created_at ASC',\n });\n\n for (const match of matches) {\n if (!match.factId || extractedFacts.has(match.factId)) {\n continue;\n }\n\n const fact = await match.getFact();\n if (fact?.id) {\n extractedFacts.set(fact.id as string, fact);\n }\n }\n }\n\n const extractedFactRecords = [...extractedFacts.values()].map(\n (fact) => {\n const factId = fact.id as string | undefined;\n return {\n ...serializeFact(fact),\n usedInArticle: factId ? usedFactIds.has(factId) : false,\n };\n },\n );\n\n return {\n id: reference.id || null,\n title: reference.title || reference.name || reference.url || null,\n url: reference.url || null,\n originalUrl: reference.original_url || null,\n type: reference.type || null,\n source: reference.source || null,\n usedFactIds: extractedFactRecords\n .filter((fact: any) => fact.id && usedFactIds.has(fact.id))\n .map((fact: any) => fact.id),\n extractedFacts: extractedFactRecords,\n };\n }),\n );\n\n const publicGeneration = (this.metadata?.transparency?.generation ??\n {}) as Record<string, any>;\n const generationMetadata = (this.metadata?.generation ?? {}) as Record<\n string,\n any\n >;\n const serializedCorrections = corrections\n .filter((correction: any) => correction.status === 'published')\n .map((correction: any) => {\n const correctionMetadata =\n typeof correction?.getMetadata === 'function'\n ? correction.getMetadata()\n : (correction.metadata as Record<string, any>) || {};\n\n return {\n ...serializeContentCorrection(correction),\n provenance: {\n autoGeneratedDraft: Boolean(correctionMetadata.autoGeneratedDraft),\n draftVersionId: correctionMetadata.draftVersionId || null,\n draftVersionNumber: correctionMetadata.draftVersionNumber || null,\n sourceCorrectionVersionId:\n correctionMetadata.sourceCorrectionVersionId || null,\n sourceCorrectionVersionNumber:\n correctionMetadata.sourceCorrectionVersionNumber || null,\n },\n };\n });\n const serializedVersionHistory = versions.map((version: any) => {\n const versionMetadata =\n typeof version?.getMetadata === 'function'\n ? version.getMetadata()\n : (version.metadata as Record<string, any>) || {};\n\n return {\n id: version.id || null,\n version: version.version ?? null,\n kind: version.kind || null,\n summary: version.summary || '',\n createdAt: version.createdAt || null,\n provenance: {\n policyKey: versionMetadata.policyKey || null,\n reviewFingerprint:\n versionMetadata.reviewFingerprint ||\n versionMetadata.contentFingerprint ||\n null,\n factId: versionMetadata.factId || null,\n replacementFactId: versionMetadata.replacementFactId || null,\n sourceCorrectionVersionId:\n versionMetadata.sourceCorrectionVersionId || null,\n sourceCorrectionVersionNumber:\n versionMetadata.sourceCorrectionVersionNumber || null,\n correctionDraft: versionMetadata.correctionDraft || null,\n publicationSnapshotFingerprint:\n versionMetadata.publicationSnapshotFingerprint || null,\n },\n };\n });\n\n return normalizeContentTransparency(\n {\n generatedAt: new Date().toISOString(),\n snapshotKind,\n contentId: (this.id as string) || null,\n currentContentStatus: this.status || null,\n publicationProfileKey: governance.publicationProfileKey || undefined,\n generation: {\n aiAssisted:\n publicGeneration.aiAssisted ??\n generationMetadata.aiAssisted ??\n Boolean(getPublicPrompt(this.metadata)),\n publicPrompt: getPublicPrompt(this.metadata),\n model: publicGeneration.model || generationMetadata.model || null,\n },\n factsUsed: linkedFacts.filter((fact) => fact.usedInArticle),\n linkedFacts,\n otherExtractedFacts: referenceGroups.flatMap((reference) =>\n reference.extractedFacts.filter((fact: any) => !fact.usedInArticle),\n ),\n references: referenceGroups,\n reviews,\n reviewProfiles,\n corrections: serializedCorrections,\n versionHistory: serializedVersionHistory,\n },\n {\n snapshotKind,\n contentId: (this.id as string) || null,\n currentContentStatus: this.status || null,\n publicationProfileKey: governance.publicationProfileKey || undefined,\n },\n );\n }\n\n /**\n * Fingerprint of the *content-bearing* publication surface only.\n *\n * This must converge: two byte-identical `save()`s of published content\n * have to produce the same fingerprint so the publication-version writer\n * (`save()`) does not append a redundant `ContentVersion` on every save.\n *\n * It therefore deliberately excludes everything that grows or carries a\n * timestamp/ordering with each save — `versionHistory`, `reviews`,\n * `corrections`, and any `generatedAt`/`createdAt`/`id` fields. The earlier\n * implementation fingerprinted the full transparency snapshot (which embeds\n * the growing `versionHistory`), so the stored fingerprint of vN predated vN\n * and the next save's recomputed fingerprint always differed → unbounded\n * redundant publication versions (#1387 blocker).\n *\n * The surface mirrors `buildReviewFingerprint`'s content block, plus the\n * pinned reference edges (`{ targetId, targetVersion }`) — a pin change is a\n * meaningful republication — and the publication profile key.\n */\n private async buildPublicationSnapshotFingerprint(\n governance: ResolvedContentGovernance,\n ): Promise<string | null> {\n if (!governance.isGoverned || !governance.transparencyEnabled) {\n return null;\n }\n\n const referenceCollection = await this.getReferenceCollection();\n const [referenceEdges, facts, factLinks] = await Promise.all([\n this.id ? referenceCollection.getForSource(this.id) : Promise.resolve([]),\n governance.factLinkingEnabled\n ? this.getFacts({ latestOnly: true, includeSuperseded: false })\n : Promise.resolve([]),\n governance.factLinkingEnabled ? this.getFactLinks() : Promise.resolve([]),\n ]);\n\n return createFingerprint({\n scope: 'content-publication',\n publicationProfileKey: governance.publicationProfileKey || null,\n content: {\n id: this.id || null,\n type: this.type,\n variant: this.variant,\n title: this.title,\n description: this.description,\n body: this.body,\n author: this.author,\n state: this.state,\n publishDate: this.publish_date,\n language: this.language,\n category: this.category,\n tags: this.tags,\n metadata: this.metadata,\n },\n // Pinned reference edges only — ordering-independent so it converges.\n references: referenceEdges\n .map((edge) => ({\n targetId: edge.targetId || null,\n targetVersion: edge.targetVersion ?? null,\n }))\n .sort((a, b) => String(a.targetId).localeCompare(String(b.targetId))),\n facts: facts\n .map((fact: any) => ({\n id: fact.id || null,\n previousFactId: fact.previousFactId || null,\n status: fact.status || null,\n textRefined: fact.textRefined || '',\n sourceCount: fact.sourceCount ?? 0,\n confidence: fact.confidence ?? null,\n metadata:\n typeof fact?.getMetadata === 'function' ? fact.getMetadata() : {},\n }))\n .sort((a: any, b: any) => String(a.id).localeCompare(String(b.id))),\n factLinks: factLinks\n .map((link: any) => ({\n factId: link.factId || null,\n relationship: link.relationship || null,\n metadata:\n typeof link?.getMetadata === 'function' ? link.getMetadata() : {},\n }))\n .sort((a: any, b: any) =>\n String(a.factId).localeCompare(String(b.factId)),\n ),\n });\n }\n\n private async getLatestPublicationSnapshotFingerprint(): Promise<\n string | null\n > {\n const versions = await this.getVersions();\n const latestPublicationVersion = [...versions]\n .reverse()\n .find((version) => version.kind === 'publication');\n\n if (!latestPublicationVersion) {\n return null;\n }\n\n return (\n latestPublicationVersion.getMetadata().publicationSnapshotFingerprint ||\n null\n );\n }\n\n private async buildCorrectionDraftSnapshot(\n options: IssueContentCorrectionOptions,\n replacementFactId: string,\n ): Promise<{\n snapshot: Record<string, any>;\n metadata: Record<string, any>;\n }> {\n const correctedText =\n options.correctedText || options.correctedFactText || '';\n const incorrectText = options.incorrectText || '';\n let body = this.body;\n let generationMethod = 'metadata';\n\n if (incorrectText && correctedText && body.includes(incorrectText)) {\n body = body.replace(incorrectText, correctedText);\n generationMethod = 'replace';\n } else if (correctedText) {\n const ai = this.ai as {\n message?: (\n prompt: string,\n options?: Record<string, unknown>,\n ) => Promise<string>;\n };\n if (ai?.message) {\n const resolvedPrompt = await resolvePrompt(\n smrtContentApplyCorrectionPrompt.key,\n {\n db: this.options.db,\n tenantId: this.tenantId,\n variables: {\n body: this.body,\n correctedText,\n incorrectText: incorrectText || 'Not provided',\n summary: options.summary || '',\n },\n },\n );\n\n try {\n const proposedBody = (\n await ai.message(\n resolvedPrompt.text,\n promptMessageOptions(resolvedPrompt.ai),\n )\n ).trim();\n if (proposedBody) {\n body = proposedBody;\n generationMethod = 'ai';\n }\n } catch {\n generationMethod = 'metadata';\n }\n }\n }\n\n return {\n snapshot: {\n title: this.title,\n description: this.description,\n body,\n status: 'draft',\n metadata: {\n ...(this.metadata || {}),\n governance: {\n ...((this.metadata?.governance || {}) as Record<string, any>),\n correctionDraft: {\n summary: options.summary,\n incorrectText,\n correctedText,\n factId: options.factId || null,\n replacementFactId: replacementFactId || null,\n autoGenerated: true,\n generationMethod,\n },\n },\n },\n },\n metadata: {\n summary: options.summary,\n incorrectText,\n correctedText,\n factId: options.factId || null,\n replacementFactId: replacementFactId || null,\n autoGenerated: true,\n generationMethod,\n },\n };\n }\n\n private async getAssetCollection() {\n return AssetCollection.create({ db: this.db });\n }\n\n private async getContentAssetCollection() {\n return ContentAssetCollection.create({ db: this.db });\n }\n\n private async getContentAssetLinks(\n relationship?: string,\n ): Promise<Array<{ assetId: string; sortOrder: number }>> {\n if (!this.id) {\n return [];\n }\n\n try {\n const contentAssets = await this.getContentAssetCollection();\n const links = await contentAssets.byLeft(\n this.id,\n relationship ? { relationship } : {},\n );\n\n return links\n .filter((link) => link.assetId)\n .map((link) => ({\n assetId: link.assetId,\n sortOrder: link.sortOrder ?? 0,\n }));\n } catch (error) {\n if (isMissingTableError(error, 'content_assets')) {\n return [];\n }\n\n throw error;\n }\n }\n\n private async resolveAssetsForLinks(\n links: Array<{ assetId: string; sortOrder: number }>,\n ): Promise<Asset[]> {\n if (links.length === 0) {\n return [];\n }\n\n const assetIds = [...new Set(links.map((link) => link.assetId))];\n const assets = await this.getAssetCollection();\n const resolved = await assets.listByIds(assetIds);\n const assetsById = new Map(\n resolved\n .filter((asset) => asset.id)\n .map((asset) => [asset.id as string, asset]),\n );\n\n return links\n .map((link) => assetsById.get(link.assetId))\n .filter(Boolean) as Asset[];\n }\n\n private async resolveReferenceTarget(content: Content | string) {\n if (typeof content !== 'string') {\n return content;\n }\n\n const contents = await this.getContentsCollection();\n\n return (await contents.getOrUpsert(\n {\n url: content,\n tenantId: this.tenantId,\n },\n {\n name: content,\n title: content,\n type: 'reference',\n tenantId: this.tenantId,\n },\n )) as Content;\n }\n\n /**\n * Loads referenced content objects\n *\n * @returns Promise that resolves when references are loaded\n */\n public async loadReferences() {\n this.references = await this.getReferences();\n }\n\n private getPendingReferenceIds(): string[] | null {\n const pendingReferenceIds = (this as any).referenceIds;\n\n if (!Array.isArray(pendingReferenceIds)) {\n return null;\n }\n\n return [\n ...new Set(\n pendingReferenceIds.filter(\n (referenceId): referenceId is string =>\n typeof referenceId === 'string' &&\n referenceId.length > 0 &&\n referenceId !== this.id,\n ),\n ),\n ];\n }\n\n private getPendingAssetIds(): string[] | null {\n const pendingAssetIds = (this as any).assetIds;\n\n if (!Array.isArray(pendingAssetIds)) {\n return null;\n }\n\n return [\n ...new Set(\n pendingAssetIds.filter(\n (assetId): assetId is string =>\n typeof assetId === 'string' && assetId.length > 0,\n ),\n ),\n ];\n }\n\n private async syncPendingReferenceIds(): Promise<void> {\n if (!this.id) {\n return;\n }\n\n const pendingReferenceIds = this.getPendingReferenceIds();\n if (pendingReferenceIds === null) {\n return;\n }\n\n const currentReferences = await this.getReferences();\n const currentReferenceIds = currentReferences\n .map((reference) => reference.id)\n .filter((referenceId): referenceId is string => Boolean(referenceId));\n const currentReferenceIdSet = new Set(currentReferenceIds);\n const pendingReferenceIdSet = new Set(pendingReferenceIds);\n\n for (const referenceId of currentReferenceIds) {\n if (!pendingReferenceIdSet.has(referenceId)) {\n await this.removeReference(referenceId);\n }\n }\n\n const referenceIdsToAdd = pendingReferenceIds.filter(\n (referenceId) => !currentReferenceIdSet.has(referenceId),\n );\n\n if (referenceIdsToAdd.length === 0) {\n this.references = await this.getReferences();\n return;\n }\n\n const contents = await this.getContentsCollection();\n const resolvedReferences = await contents.listByIds(referenceIdsToAdd);\n const referencesById = new Map(\n resolvedReferences\n .filter((reference) => reference.id)\n .map((reference) => [reference.id as string, reference]),\n );\n\n for (const referenceId of referenceIdsToAdd) {\n const reference = referencesById.get(referenceId);\n if (reference) {\n await this.addReference(reference);\n }\n }\n\n this.references = await this.getReferences();\n }\n\n private async syncPendingAssetIds(): Promise<void> {\n if (!this.id) {\n return;\n }\n\n const pendingAssetIds = this.getPendingAssetIds();\n if (pendingAssetIds === null) {\n return;\n }\n\n const currentAssets = await this.getAssets();\n const currentAssetIds = currentAssets\n .map((asset) => asset.id)\n .filter((assetId): assetId is string => Boolean(assetId));\n const currentAssetIdSet = new Set(currentAssetIds);\n const pendingAssetIdSet = new Set(pendingAssetIds);\n\n for (const assetId of currentAssetIds) {\n if (!pendingAssetIdSet.has(assetId)) {\n await this.removeAsset(assetId);\n }\n }\n\n const assetIdsToAdd = pendingAssetIds.filter(\n (assetId) => !currentAssetIdSet.has(assetId),\n );\n\n if (assetIdsToAdd.length === 0) {\n return;\n }\n\n const assets = await this.getAssetCollection();\n const resolvedAssets = await assets.listByIds(assetIdsToAdd);\n const assetsById = new Map(\n resolvedAssets\n .filter((asset) => asset.id)\n .map((asset) => [asset.id as string, asset]),\n );\n\n for (const assetId of assetIdsToAdd) {\n const asset = assetsById.get(assetId);\n if (asset) {\n await this.addAsset(asset);\n }\n }\n }\n\n /**\n * Adds a reference to another content object.\n *\n * @param content - Content object or URL to reference\n * @param options.targetVersion - Optional ContentVersion.version to pin the\n * citation to. Pass the target's current version (typically the latest\n * publication) to enable drift detection later. Pass `null` or omit to\n * leave the reference untracked.\n * @returns Promise that resolves when the reference is added\n */\n public async addReference(\n content: Content | string,\n options: { targetVersion?: number | null } = {},\n ) {\n if (!this.id) {\n throw new Error('Cannot add reference to unsaved content');\n }\n\n const target = await this.resolveReferenceTarget(content);\n\n if (!target.id) {\n throw new Error('Cannot add reference to unsaved content');\n }\n if (this.id === target.id) {\n return;\n }\n\n const references = await this.getReferenceCollection();\n // R2 junction `attach` carries extra row fields via its opts bag, so the\n // tenant scope and main's citation pin (targetVersion) ride along together.\n await references.attach(this.id, target.id, {\n tenantId: this.tenantId,\n targetVersion: options.targetVersion,\n });\n this.references = await this.getReferences();\n }\n\n /**\n * Removes a reference to another content object\n *\n * @param targetId - ID of the referenced content to remove\n */\n public async removeReference(targetId: string) {\n if (!this.id) {\n return;\n }\n\n const references = await this.getReferenceCollection();\n await references.detach(this.id, targetId);\n this.references = this.references.filter(\n (reference) => reference.id !== targetId,\n );\n }\n\n /**\n * Gets all referenced content objects\n *\n * @returns Promise resolving to an array of referenced Content objects\n */\n public async getReferences() {\n if (!this.id) {\n return [];\n }\n\n const references = await this.getReferenceCollection();\n const linkedReferences = await references.byLeft(this.id);\n const targetIds = linkedReferences.map((reference) => reference.targetId);\n\n if (targetIds.length === 0) {\n this.references = [];\n return this.references;\n }\n\n const contents = await this.getContentsCollection();\n const resolved = await contents.listByIds(targetIds);\n const referencesById = new Map(\n resolved\n .filter((content) => content.id)\n .map((content) => [content.id as string, content]),\n );\n\n this.references = targetIds\n .map((targetId) => referencesById.get(targetId))\n .filter(Boolean) as Content[];\n return this.references;\n }\n\n /**\n * Returns the raw reference edges with their citation pins\n * (`{ targetId, targetVersion }`). Unlike `getReferences()` (which resolves\n * to `Content` objects and loses the per-edge `targetVersion`), this keeps\n * the pin so callers — notably version snapshots — can reconstruct pinned\n * citations on restore. See `ContentVersionCollection.restoreIntoContent`.\n */\n public async getReferenceEdges(): Promise<\n Array<{ targetId: string; targetVersion: number | null }>\n > {\n if (!this.id) {\n return [];\n }\n\n const references = await this.getReferenceCollection();\n const linkedReferences = await references.getForSource(this.id);\n return linkedReferences\n .filter((edge) => Boolean(edge.targetId))\n .map((edge) => ({\n targetId: edge.targetId as string,\n targetVersion: edge.targetVersion ?? null,\n }));\n }\n\n /**\n * Returns one entry per reference edge with the pinned `targetVersion` and\n * the target's latest version. Drift exists when both are present and\n * differ — callers can use this to surface \"the source you cited has been\n * updated\" affordances in editors or review tools.\n *\n * `currentVersion` is the target's latest **publication** `ContentVersion`,\n * because pins are taken against the latest publication (see `addReference`).\n * Auto-created `correction`/`draft`/`manual` versions bump the shared\n * `(content_id, version)` counter but do NOT republish, so comparing against\n * the max version of *any* kind produced false drift positives (#1387 #4).\n *\n * Unpinned references (`citedVersion === null`) are included with\n * `currentVersion` populated when available so callers can choose to\n * surface them as \"pinnable\" suggestions.\n */\n public async getReferenceDrift(): Promise<\n Array<{\n targetId: string;\n citedVersion: number | null;\n currentVersion: number | null;\n isDrifted: boolean;\n }>\n > {\n if (!this.id) {\n return [];\n }\n\n const references = await this.getReferenceCollection();\n const linkedReferences = await references.getForSource(this.id);\n if (linkedReferences.length === 0) {\n return [];\n }\n\n const versions = await this.getContentVersionCollection();\n const targetIds = linkedReferences.map((reference) => reference.targetId);\n\n // Single query for all target *publication* versions; pick the max per\n // contentId. Pins are taken against the latest publication, so only\n // publication versions count as drift (#1387 #4). Filtering by kind here\n // also avoids the N+1 of loading each version to inspect its kind.\n const allVersions = await versions.list({\n where: { contentId: targetIds, kind: 'publication' },\n orderBy: 'version DESC',\n });\n const latestByContentId = new Map<string, number>();\n for (const version of allVersions) {\n if (!latestByContentId.has(version.contentId)) {\n latestByContentId.set(version.contentId, version.version);\n }\n }\n\n return linkedReferences.map((reference) => {\n const currentVersion = latestByContentId.get(reference.targetId) ?? null;\n const citedVersion = reference.targetVersion ?? null;\n return {\n targetId: reference.targetId,\n citedVersion,\n currentVersion,\n isDrifted:\n citedVersion !== null &&\n currentVersion !== null &&\n citedVersion !== currentVersion,\n };\n });\n }\n\n public isGoverned(): boolean {\n return this.getConfiguredGovernance().isGoverned;\n }\n\n public async getFactLinks(\n options: { relationship?: FactContentRelationship } = {},\n ) {\n const governance = await this.resolveGovernance();\n if (!governance.isGoverned || !governance.factLinkingEnabled || !this.id) {\n return [];\n }\n\n if (!this.id) {\n return [];\n }\n\n const links = await this.getFactContentCollection();\n return options.relationship\n ? links.byRight(this.id as string, { relationship: options.relationship })\n : links.byRight(this.id as string);\n }\n\n public async getFacts(\n options: {\n relationship?: FactContentRelationship;\n includeSuperseded?: boolean;\n latestOnly?: boolean;\n } = {},\n ): Promise<Fact[]> {\n const governance = await this.resolveGovernance();\n if (!governance.isGoverned || !governance.factLinkingEnabled || !this.id) {\n return [];\n }\n\n if (!this.id) {\n return [];\n }\n\n const facts = await this.getFactCollection();\n return facts.getForContent(this.id as string, options);\n }\n\n public async addFact(\n fact: Fact | string,\n relationship?: FactContentRelationship,\n metadata?: Record<string, any>,\n ) {\n const governance = await this.requireFactLinking('fact association');\n\n if (!this.id) {\n throw new Error('Cannot associate an unsaved content item with a fact');\n }\n\n const factId = typeof fact === 'string' ? fact : (fact.id as string);\n if (!factId) {\n throw new Error('Fact ID is required to create a content-fact link');\n }\n\n const links = await this.getFactContentCollection();\n return links.attach(factId, this.id as string, {\n relationship: relationship || governance.defaultFactRelationship,\n metadata,\n });\n }\n\n public async removeFact(\n factId: string,\n relationship?: FactContentRelationship,\n ): Promise<void> {\n const governance = await this.resolveGovernance();\n if (!governance.isGoverned || !governance.factLinkingEnabled) {\n return;\n }\n\n if (!this.id) {\n return;\n }\n\n const links = await this.getFactContentCollection();\n if (relationship) {\n await links.detach(factId, this.id as string, { relationship });\n return;\n }\n\n await links.detach(factId, this.id as string);\n }\n\n public async syncFacts(\n factIds: string[],\n relationship?: FactContentRelationship,\n ): Promise<{ added: string[]; kept: string[]; removed: string[] }> {\n const governance = await this.requireFactLinking('fact sync');\n\n if (!this.id) {\n throw new Error('Cannot sync facts for unsaved content');\n }\n\n const uniqueFactIds = [...new Set(factIds.filter(Boolean))];\n const links = await this.getFactContentCollection();\n const resolvedRelationship =\n relationship || governance.defaultFactRelationship;\n const existing = await links.byRight(this.id as string, {\n relationship: resolvedRelationship,\n });\n\n const existingIds = new Set(existing.map((link) => link.factId));\n const desiredIds = new Set(uniqueFactIds);\n\n const kept = uniqueFactIds.filter((factId) => existingIds.has(factId));\n const added = uniqueFactIds.filter((factId) => !existingIds.has(factId));\n const removed = existing\n .map((link) => link.factId)\n .filter((factId) => !desiredIds.has(factId));\n\n for (const factId of added) {\n await links.attach(factId, this.id as string, {\n relationship: resolvedRelationship,\n });\n }\n\n for (const factId of removed) {\n await links.detach(factId, this.id as string, {\n relationship: resolvedRelationship,\n });\n }\n\n return { added, kept, removed };\n }\n\n public async browseFacts(\n query = '',\n options: {\n limit?: number;\n offset?: number;\n minSimilarity?: number;\n includeSuperseded?: boolean;\n latestOnly?: boolean;\n } = {},\n ): Promise<Fact[]> {\n await this.requireFactLinking('fact catalog browsing');\n const facts = await this.getFactCollection();\n return facts.browseCatalog(query, {\n ...options,\n tenantId: this.tenantId,\n });\n }\n\n private async getFactAuditSourceMaterials(): Promise<{\n sources: FactAuditSourceMaterial[];\n warnings: string[];\n }> {\n const warnings: string[] = [];\n const sources: FactAuditSourceMaterial[] = [];\n const references = await this.getReferences();\n const assets = await this.getAssets();\n\n for (const reference of references) {\n const referenceId = (reference.id as string | undefined) || '';\n const text = getContentText(reference);\n const sourceUrl =\n normalizeAuditText((reference as any).url) ||\n normalizeAuditText((reference as any).sourceUrl) ||\n normalizeAuditText((reference as any).fileKey);\n const sourceTitle =\n normalizeAuditText(reference.title) ||\n normalizeAuditText((reference as any).name) ||\n sourceUrl ||\n referenceId;\n\n if (!text) {\n warnings.push(\n `Reference ${sourceTitle || referenceId} has no extracted text.`,\n );\n continue;\n }\n\n sources.push({\n sourceKind: 'content-reference',\n sourceId: referenceId,\n sourceUrl,\n sourceTitle,\n locator: sourceTitle,\n text,\n });\n }\n\n for (const asset of assets as any[]) {\n const metadata =\n typeof asset?.getMetadata === 'function'\n ? asset.getMetadata()\n : parseAuditMetadata(asset?.metadata);\n const text = [\n metadata.extractedText,\n metadata.text,\n metadata.ocrText,\n asset?.text,\n asset?.body,\n asset?.description,\n ]\n .map(normalizeAuditText)\n .filter(Boolean)\n .join('\\n\\n');\n const assetId = normalizeAuditText(asset?.id);\n const sourceTitle =\n normalizeAuditText(asset?.title) ||\n normalizeAuditText(asset?.name) ||\n normalizeAuditText(asset?.filename) ||\n assetId;\n const sourceUrl =\n normalizeAuditText(asset?.url) ||\n normalizeAuditText(asset?.sourceUrl) ||\n normalizeAuditText(asset?.fileKey);\n\n if (!text) {\n warnings.push(`Asset ${sourceTitle || assetId} has no extracted text.`);\n continue;\n }\n\n sources.push({\n sourceKind: 'asset',\n sourceId: assetId,\n sourceUrl,\n sourceTitle,\n locator: sourceTitle,\n text,\n });\n }\n\n return { sources, warnings };\n }\n\n private factMatchesTenant(fact: any): boolean {\n return (\n fact.tenantId === this.tenantId ||\n fact.tenant_id === this.tenantId ||\n (!fact.tenantId && !fact.tenant_id && !this.tenantId)\n );\n }\n\n private async findExactArticleClaimFact(\n statement: string,\n ): Promise<Fact | null> {\n const normalizedStatement = normalizeAuditText(statement);\n const facts = await this.getFactCollection();\n const linkedClaimFacts = await Promise.all(\n (await this.getFactLinks({ relationship: 'referenced_in' })).map(\n (link: any) => facts.get({ id: link.factId }),\n ),\n );\n const linkedMatch = linkedClaimFacts.find(\n (fact: any): fact is Fact =>\n Boolean(fact) &&\n this.factMatchesTenant(fact) &&\n normalizeAuditText(fact.textRefined) === normalizedStatement,\n );\n if (linkedMatch) {\n return linkedMatch;\n }\n\n const matches = await facts.list({\n where: { textRefined: normalizedStatement },\n orderBy: 'updated_at DESC',\n });\n\n return (\n matches.find(\n (fact: any) =>\n this.factMatchesTenant(fact) &&\n this.id &&\n isGeneratedArticleClaimFact(fact, this.id as string),\n ) || null\n );\n }\n\n private async safeAuditLink(\n factId: string,\n relationship: FactContentRelationship,\n metadata: Record<string, any>,\n ) {\n const links = await this.getFactContentCollection();\n const existing = (\n await links.byRight(this.id as string, { relationship })\n ).find((link: any) => link.factId === factId);\n\n if (existing) {\n const existingMetadata = getLinkMetadata(existing);\n if (existingMetadata.generatedBy === FACT_AUDIT_GENERATED_BY) {\n existing.setMetadata?.({\n ...existingMetadata,\n ...metadata,\n });\n } else {\n existing.setMetadata?.({\n ...existingMetadata,\n factAudit: {\n ...(existingMetadata.factAudit &&\n typeof existingMetadata.factAudit === 'object'\n ? existingMetadata.factAudit\n : {}),\n ...metadata,\n },\n });\n }\n await existing.save();\n return existing;\n }\n\n return links.attach(factId, this.id as string, { relationship, metadata });\n }\n\n private async clearGeneratedFactAudit(): Promise<void> {\n if (!this.id) {\n return;\n }\n\n const [links, evidences] = await Promise.all([\n this.getFactLinks(),\n this.getFactEvidenceCollection(),\n ]);\n\n for (const link of links as any[]) {\n const metadata = getLinkMetadata(link);\n if (metadata.generatedBy === FACT_AUDIT_GENERATED_BY) {\n await link.delete();\n } else if (\n metadata.factAudit &&\n typeof metadata.factAudit === 'object' &&\n metadata.factAudit.generatedBy === FACT_AUDIT_GENERATED_BY\n ) {\n const { factAudit: _removed, ...preservedMetadata } = metadata;\n link.setMetadata?.(preservedMetadata);\n await link.save();\n }\n }\n\n const generatedEvidence = await evidences.list({\n where: { tenantId: this.tenantId ?? null },\n });\n for (const evidence of generatedEvidence as any[]) {\n const metadata =\n typeof evidence.getMetadata === 'function'\n ? evidence.getMetadata()\n : {};\n if (\n metadata.generatedBy === FACT_AUDIT_GENERATED_BY &&\n metadata.contentId === this.id\n ) {\n await evidence.delete();\n }\n }\n }\n\n private async clearGeneratedFactSourcesForSources(\n sources: FactAuditSourceMaterial[],\n ): Promise<string[]> {\n if (!this.id || sources.length === 0) {\n return [];\n }\n\n const sourceKeys = new Set(\n sources.map((source) => `${source.sourceKind}:${source.sourceId}`),\n );\n const factSources = await this.getFactSourceCollection();\n const generatedSources = await factSources.list({\n where: { tenantId: this.tenantId ?? null },\n });\n const deletedSourceIds: string[] = [];\n\n for (const source of generatedSources as any[]) {\n const metadata =\n typeof source.getMetadata === 'function' ? source.getMetadata() : {};\n const sourceKey = `${source.sourceType || ''}:${metadata.sourceId || ''}`;\n if (\n sourceKeys.has(sourceKey) &&\n metadata.generatedBy === FACT_AUDIT_GENERATED_BY &&\n metadata.contentId === this.id\n ) {\n if (typeof source.id === 'string') {\n deletedSourceIds.push(source.id);\n }\n await source.delete();\n }\n }\n\n return deletedSourceIds;\n }\n\n private async extractReferenceFactsForAudit(\n sources: FactAuditSourceMaterial[],\n options: {\n auditRunId: string;\n maxFactsPerSource?: number;\n context?: string;\n replaceGenerated?: boolean;\n },\n ) {\n const facts = await this.getFactCollection();\n const evidences = await this.getFactEvidenceCollection();\n const warnings: string[] = [];\n const referenceFacts = new Map<string, Fact>();\n let deletedEvidenceIds: string[] = [];\n let deletedSourceIds: string[] = [];\n\n if (options.replaceGenerated && sources.length > 0) {\n const replacement = await evidences.replaceGeneratedForSources(\n sources.map((source) => ({\n sourceKind: source.sourceKind,\n sourceId: source.sourceId,\n })),\n {\n generatedBy: FACT_AUDIT_GENERATED_BY,\n contentId: this.id as string,\n tenantId: this.tenantId ?? null,\n },\n );\n deletedEvidenceIds = replacement.deletedEvidenceIds;\n deletedSourceIds =\n await this.clearGeneratedFactSourcesForSources(sources);\n }\n\n for (const source of sources) {\n let candidates: FactExtractionCandidate[] = [];\n try {\n candidates = await facts.extractCandidatesFromText(source.text, {\n domain: FACT_AUDIT_DOMAIN,\n sourceType: source.sourceKind,\n context: options.context || source.sourceTitle,\n maxFacts: options.maxFactsPerSource ?? 24,\n tenantId: this.tenantId,\n });\n } catch (error: any) {\n warnings.push(\n `Failed to extract facts from ${source.sourceTitle}: ${error.message || error}`,\n );\n continue;\n }\n\n for (const candidate of candidates) {\n const result = await facts.reconcile({\n rawInput: candidate.statement,\n type: candidate.type || 'assertion',\n domain: FACT_AUDIT_DOMAIN,\n tenantId: this.tenantId,\n source: {\n sourceType: source.sourceKind,\n sourceUrl: source.sourceUrl,\n sourceTitle: source.sourceTitle,\n credibility: candidate.confidence ?? 0.75,\n metadata: {\n auditRunId: options.auditRunId,\n generatedBy: FACT_AUDIT_GENERATED_BY,\n contentId: this.id,\n sourceId: source.sourceId,\n quote: candidate.sourceExcerpt || null,\n locator: source.locator || null,\n },\n },\n });\n referenceFacts.set(result.fact.id as string, result.fact);\n\n await evidences.upsertEvidence({\n factId: result.fact.id as string,\n status: 'supports',\n sourceKind: source.sourceKind,\n sourceId: source.sourceId,\n sourceUrl: source.sourceUrl,\n sourceTitle: source.sourceTitle,\n quote: candidate.sourceExcerpt || candidate.statement,\n locator: source.locator,\n extractionMethod: 'ai-reference-fact',\n confidence: candidate.confidence ?? 0.75,\n tenantId: this.tenantId,\n metadata: {\n auditRunId: options.auditRunId,\n generatedBy: FACT_AUDIT_GENERATED_BY,\n contentId: this.id,\n candidateMetadata: candidate.metadata || {},\n },\n });\n }\n }\n\n return {\n referenceFacts,\n warnings,\n referenceFactsExtracted: referenceFacts.size,\n deletedEvidenceIds,\n deletedSourceIds,\n repairedSources: sources.map((source) => ({\n sourceKind: source.sourceKind,\n sourceId: source.sourceId,\n sourceTitle: source.sourceTitle,\n })),\n };\n }\n\n private async getCurrentFactAuditSupportCandidates(\n options: {\n referenceFacts?: Map<string, Fact>;\n sources?: FactAuditSourceSelector[];\n sourceIds?: string[];\n maxCandidateEvidence?: number;\n } = {},\n ) {\n const evidences = await this.getFactEvidenceCollection();\n const allFacts = await this.getFactCollection();\n const candidateFacts = new Map<string, any>();\n const candidateEvidence = new Map<string, any>();\n const sourceKeys = new Set(\n (options.sources || []).map(\n (source) => `${source.sourceKind}:${source.sourceId}`,\n ),\n );\n const sourceIds = new Set(options.sourceIds || []);\n const maxCandidateEvidence = Math.max(\n 1,\n options.maxCandidateEvidence ?? 120,\n );\n\n const evidenceEntries = options.referenceFacts\n ? (\n await Promise.all(\n [...options.referenceFacts.keys()].map((factId) =>\n evidences.getForFact(factId),\n ),\n )\n ).flat()\n : await evidences.list({\n where: { tenantId: this.tenantId ?? null },\n });\n\n for (const entry of evidenceEntries as any[]) {\n if (!isGeneratedFactAuditEvidence(entry, this.id as string)) {\n continue;\n }\n if (entry.sourceKind === 'content') {\n continue;\n }\n if (entry.status === 'irrelevant' || entry.status === 'invalid') {\n continue;\n }\n if (\n sourceKeys.size > 0 &&\n !sourceKeys.has(`${entry.sourceKind}:${entry.sourceId}`)\n ) {\n continue;\n }\n if (sourceIds.size > 0 && !sourceIds.has(entry.sourceId)) {\n continue;\n }\n if (candidateEvidence.size >= maxCandidateEvidence) {\n break;\n }\n\n const fact =\n options.referenceFacts?.get(entry.factId) ||\n (await allFacts.get({ id: entry.factId }));\n if (!fact) {\n continue;\n }\n\n const factId = fact.id as string;\n const existing = candidateFacts.get(factId) || {\n id: factId,\n statement: fact.textRefined || fact.textRaw || '',\n evidence: [],\n };\n const serializedEvidence = {\n id: entry.id || null,\n status: entry.status || 'supports',\n quote: entry.quote || null,\n sourceTitle: entry.sourceTitle || null,\n sourceUrl: entry.sourceUrl || null,\n locator: entry.locator || null,\n };\n existing.evidence.push(serializedEvidence);\n candidateFacts.set(factId, existing);\n if (typeof entry.id === 'string') {\n candidateEvidence.set(entry.id, entry);\n }\n }\n\n return {\n supportCandidates: [...candidateFacts.values()],\n candidateFactIds: new Set(candidateFacts.keys()),\n candidateEvidence,\n };\n }\n\n public async repairFactAudit(\n options: {\n maxReferenceFactsPerSource?: number;\n maxArticleClaims?: number;\n context?: string;\n } = {},\n ) {\n await this.requireFactLinking('fact audit repair');\n if (!this.id) {\n throw new Error('Cannot repair fact audit for unsaved content');\n }\n\n const auditRunId = createFactAuditRunId(this.id as string);\n const facts = await this.getFactCollection();\n const evidences = await this.getFactEvidenceCollection();\n const warnings: string[] = [];\n const articleText = getContentText(this);\n\n const sourceMaterials = await this.getFactAuditSourceMaterials();\n warnings.push(...sourceMaterials.warnings);\n await this.clearGeneratedFactAudit();\n const referenceRepair = await this.extractReferenceFactsForAudit(\n sourceMaterials.sources,\n {\n auditRunId,\n maxFactsPerSource: options.maxReferenceFactsPerSource,\n context: options.context,\n },\n );\n warnings.push(...referenceRepair.warnings);\n const referenceFacts = referenceRepair.referenceFacts;\n\n let claims: FactExtractionCandidate[] = [];\n if (!articleText) {\n warnings.push('Article has no text to audit.');\n } else {\n try {\n claims = await facts.extractArticleClaims(articleText, {\n domain: FACT_AUDIT_DOMAIN,\n sourceType: 'article',\n context: options.context || this.title || this.slug || '',\n maxFacts: options.maxArticleClaims ?? 32,\n tenantId: this.tenantId,\n });\n } catch (error: any) {\n warnings.push(\n `Failed to extract article claims: ${error.message || error}`,\n );\n }\n }\n\n const { supportCandidates, candidateFactIds, candidateEvidence } =\n await this.getCurrentFactAuditSupportCandidates({\n referenceFacts,\n });\n\n const findings: ContentReviewFinding[] = [];\n\n for (const claim of claims) {\n let assessment: FactClaimSupportAssessment;\n try {\n assessment = await facts.assessClaimSupport(\n claim.statement,\n supportCandidates,\n { tenantId: this.tenantId },\n );\n } catch (error: any) {\n warnings.push(\n `Failed to assess claim \"${claim.statement}\": ${error.message || error}`,\n );\n assessment = {\n status: 'needs_review' as FactClaimSupportStatus,\n matchedFactIds: [],\n matchedEvidenceIds: [],\n rationale: 'Support assessment failed.',\n confidence: undefined,\n };\n }\n\n const matchedFactIds = assessment.matchedFactIds.filter((factId) =>\n candidateFactIds.has(factId),\n );\n let claimFact = await this.findExactArticleClaimFact(claim.statement);\n\n if (!claimFact) {\n claimFact = await facts.create({\n textRefined: claim.statement,\n textRaw: claim.statement,\n type: claim.type || 'assertion',\n domain: FACT_AUDIT_DOMAIN,\n status:\n assessment.status === 'unsupported' ||\n assessment.status === 'needs_review'\n ? 'pending'\n : 'active',\n sourceCount: 0,\n confidence: claim.confidence ?? assessment.confidence ?? 0.5,\n tenantId: this.tenantId,\n metadata: JSON.stringify({\n auditRunId,\n generatedBy: FACT_AUDIT_GENERATED_BY,\n contentId: this.id,\n auditFactRole: 'article-claim',\n claimOnly: matchedFactIds.length === 0,\n }),\n });\n } else if (\n this.id &&\n isGeneratedArticleClaimFact(claimFact, this.id as string)\n ) {\n claimFact.status =\n assessment.status === 'unsupported' ||\n assessment.status === 'needs_review'\n ? 'pending'\n : 'active';\n claimFact.confidence =\n claim.confidence ?? assessment.confidence ?? claimFact.confidence;\n claimFact.updateMetadata?.({\n auditRunId,\n generatedBy: FACT_AUDIT_GENERATED_BY,\n contentId: this.id,\n auditFactRole: 'article-claim',\n claimOnly: matchedFactIds.length === 0,\n });\n await claimFact.save();\n }\n\n const articleEvidence = await evidences.upsertEvidence({\n factId: claimFact.id as string,\n status: 'supports',\n sourceKind: 'content',\n sourceId: this.id as string,\n sourceTitle: this.title || this.slug || (this.id as string),\n quote: claim.sourceExcerpt || claim.statement,\n locator: this.title || this.slug || '',\n extractionMethod: 'ai-article-claim',\n confidence: claim.confidence ?? assessment.confidence ?? 0.5,\n tenantId: this.tenantId,\n metadata: {\n auditRunId,\n generatedBy: FACT_AUDIT_GENERATED_BY,\n contentId: this.id,\n supportStatus: assessment.status,\n },\n });\n\n let supportingEvidenceIds = assessment.matchedEvidenceIds.filter(\n (evidenceId) => candidateEvidence.has(evidenceId),\n );\n for (const matchedFactId of matchedFactIds) {\n if (supportingEvidenceIds.length > 0) {\n continue;\n }\n const candidate = supportCandidates.find(\n (entry: any) => entry.id === matchedFactId,\n );\n supportingEvidenceIds = [\n ...supportingEvidenceIds,\n ...(candidate?.evidence || [])\n .map((entry: any) => entry.id)\n .filter((id: unknown): id is string => typeof id === 'string'),\n ];\n }\n supportingEvidenceIds = [...new Set(supportingEvidenceIds)];\n\n const linkMetadata = {\n auditRunId,\n generatedBy: FACT_AUDIT_GENERATED_BY,\n supportStatus: assessment.status,\n claimQuote: claim.sourceExcerpt || claim.statement,\n claimFactId: claimFact.id as string,\n articleEvidenceId: articleEvidence.id || null,\n supportingFactIds: matchedFactIds,\n supportingEvidenceIds,\n rationale: assessment.rationale,\n confidence: assessment.confidence ?? claim.confidence ?? null,\n };\n\n await this.safeAuditLink(\n claimFact.id as string,\n 'referenced_in',\n linkMetadata,\n );\n\n for (const matchedFactId of matchedFactIds) {\n await this.safeAuditLink(\n matchedFactId,\n assessment.status === 'contradicted' ? 'contradicts' : 'supports',\n {\n ...linkMetadata,\n supportingEvidenceIds,\n },\n );\n }\n\n if (assessment.status !== 'supported') {\n findings.push({\n severity: assessment.status === 'contradicted' ? 'error' : 'warning',\n title:\n assessment.status === 'contradicted'\n ? 'Contradicted article claim'\n : 'Unsupported article claim',\n detail: assessment.rationale || 'The claim needs editorial review.',\n factId: claimFact.id as string,\n quote: claim.sourceExcerpt || claim.statement,\n ruleId: 'fact-audit',\n });\n }\n }\n\n const reviews = await this.getContentReviewCollection();\n await reviews.createFromResult({\n contentId: this.id as string,\n kind: 'facts',\n policyKey: 'facts',\n reviewer: 'system',\n result: {\n status: findings.length > 0 ? 'flagged' : 'passed',\n summary:\n findings.length > 0\n ? `${findings.length} article claim(s) need review.`\n : 'Article claims are supported by available evidence.',\n findings,\n },\n metadata: {\n auditRunId,\n generatedBy: FACT_AUDIT_GENERATED_BY,\n warnings,\n },\n tenantId: this.tenantId,\n });\n\n const state = await this.getFactAuditState();\n return {\n ...state,\n repair: {\n auditRunId,\n claimsExtracted: claims.length,\n referenceFactsExtracted: referenceRepair.referenceFactsExtracted,\n warnings,\n },\n };\n }\n\n public async repairFactAuditAction(\n options: {\n maxReferenceFactsPerSource?: number;\n maxArticleClaims?: number;\n context?: string;\n } = {},\n ) {\n return this.repairFactAudit(options);\n }\n\n public async repairFactEvidence(\n options: FactAuditResourceRepairOptions = {},\n ) {\n await this.requireFactLinking('fact evidence repair');\n if (!this.id) {\n throw new Error('Cannot repair fact evidence for unsaved content');\n }\n\n const auditRunId = createFactAuditRunId(this.id as string);\n const sourceMaterials = await this.getFactAuditSourceMaterials();\n const sources = filterAuditSources(\n sourceMaterials.sources,\n options.sources,\n );\n const warnings: string[] = [];\n\n if (options.sources?.length && sources.length === 0) {\n warnings.push('No matching resource text was available for repair.');\n }\n\n const repair = await this.extractReferenceFactsForAudit(sources, {\n auditRunId,\n maxFactsPerSource: options.maxFactsPerSource,\n context: options.context,\n replaceGenerated: true,\n });\n warnings.push(...repair.warnings);\n\n const state = await this.getFactAuditState();\n return {\n ...state,\n evidenceRepair: {\n auditRunId,\n referenceFactsExtracted: repair.referenceFactsExtracted,\n repairedSources: repair.repairedSources,\n deletedEvidenceIds: repair.deletedEvidenceIds,\n deletedSourceIds: repair.deletedSourceIds,\n warnings,\n },\n };\n }\n\n public async repairFactEvidenceAction(\n options: FactAuditResourceRepairOptions = {},\n ) {\n return this.repairFactEvidence(options);\n }\n\n private async clearGeneratedSupportLinksForClaim(\n claimFactId: string,\n articleEvidenceId: string | null,\n ): Promise<void> {\n const links = await this.getFactLinks();\n\n for (const link of links as any[]) {\n if (\n link.relationship !== 'supports' &&\n link.relationship !== 'contradicts'\n ) {\n continue;\n }\n\n const metadata = getGeneratedFactAuditMetadata(link);\n if (!metadata) {\n continue;\n }\n\n const matchesEvidence =\n articleEvidenceId &&\n typeof metadata.articleEvidenceId === 'string' &&\n metadata.articleEvidenceId === articleEvidenceId;\n const matchesClaim =\n typeof metadata.claimFactId === 'string' &&\n metadata.claimFactId === claimFactId;\n\n if (matchesEvidence || matchesClaim) {\n await link.delete();\n }\n }\n }\n\n public async recheckFactClaims(options: FactAuditClaimRecheckOptions = {}) {\n await this.requireFactLinking('claim support recheck');\n if (!this.id) {\n throw new Error('Cannot recheck fact claims for unsaved content');\n }\n\n const auditRunId = createFactAuditRunId(this.id as string);\n const facts = await this.getFactCollection();\n const evidences = await this.getFactEvidenceCollection();\n const links = await this.getFactContentCollection();\n const claimIdFilter = new Set(options.claimFactIds || []);\n const { supportCandidates, candidateFactIds, candidateEvidence } =\n await this.getCurrentFactAuditSupportCandidates({\n sources: options.sources,\n sourceIds: options.sourceIds,\n maxCandidateEvidence: options.maxCandidateEvidence,\n });\n const claimLinks = (\n await links.byRight(this.id as string, { relationship: 'referenced_in' })\n )\n .map((link: any) => ({\n link,\n metadata: getGeneratedFactAuditMetadata(link),\n }))\n .filter(\n (entry): entry is { link: any; metadata: Record<string, any> } =>\n entry.metadata !== null &&\n (claimIdFilter.size === 0 || claimIdFilter.has(entry.link.factId)),\n );\n const warnings: string[] = [];\n let recheckedClaims = 0;\n\n for (const { link, metadata } of claimLinks) {\n const claimFact = await facts.get({ id: link.factId });\n if (!claimFact) {\n continue;\n }\n\n const claimText =\n normalizeAuditText(metadata.claimQuote) ||\n normalizeAuditText(claimFact.textRefined) ||\n normalizeAuditText(claimFact.textRaw);\n if (!claimText) {\n continue;\n }\n\n let assessment: FactClaimSupportAssessment;\n try {\n assessment = await facts.assessClaimSupport(\n claimText,\n supportCandidates,\n { tenantId: this.tenantId },\n );\n } catch (error: any) {\n warnings.push(\n `Failed to recheck claim \"${claimText}\": ${error.message || error}`,\n );\n assessment = {\n status: 'needs_review',\n matchedFactIds: [],\n matchedEvidenceIds: [],\n rationale: 'Support assessment failed.',\n confidence: undefined,\n };\n }\n\n const matchedFactIds = assessment.matchedFactIds.filter((factId) =>\n candidateFactIds.has(factId),\n );\n let supportStatus = assessment.status;\n if (\n (supportStatus === 'supported' || supportStatus === 'contradicted') &&\n matchedFactIds.length === 0\n ) {\n supportStatus = 'needs_review';\n }\n let supportingEvidenceIds = assessment.matchedEvidenceIds.filter(\n (evidenceId) => candidateEvidence.has(evidenceId),\n );\n if (supportingEvidenceIds.length === 0) {\n for (const matchedFactId of matchedFactIds) {\n const candidate = supportCandidates.find(\n (entry: any) => entry.id === matchedFactId,\n );\n supportingEvidenceIds.push(\n ...(candidate?.evidence || [])\n .map((entry: any) => entry.id)\n .filter((id: unknown): id is string => typeof id === 'string'),\n );\n }\n }\n supportingEvidenceIds = [...new Set(supportingEvidenceIds)];\n\n const articleEvidenceId =\n typeof metadata.articleEvidenceId === 'string'\n ? metadata.articleEvidenceId\n : null;\n const nextMetadata = {\n ...metadata,\n auditRunId,\n generatedBy: FACT_AUDIT_GENERATED_BY,\n supportStatus,\n supportingFactIds: matchedFactIds,\n supportingEvidenceIds,\n rationale: assessment.rationale,\n confidence: assessment.confidence ?? metadata.confidence ?? null,\n claimFactId: link.factId,\n };\n const existingMetadata = getLinkMetadata(link);\n if (existingMetadata.generatedBy === FACT_AUDIT_GENERATED_BY) {\n link.setMetadata?.(nextMetadata);\n } else {\n link.setMetadata?.({\n ...existingMetadata,\n factAudit: nextMetadata,\n });\n }\n await link.save();\n\n if (articleEvidenceId) {\n const articleEvidence = await evidences.get({ id: articleEvidenceId });\n if (articleEvidence) {\n articleEvidence.updateMetadata({\n auditRunId,\n supportStatus,\n });\n await articleEvidence.save();\n }\n }\n\n await this.clearGeneratedSupportLinksForClaim(\n link.factId,\n articleEvidenceId,\n );\n for (const matchedFactId of matchedFactIds) {\n await this.safeAuditLink(\n matchedFactId,\n supportStatus === 'contradicted' ? 'contradicts' : 'supports',\n {\n ...nextMetadata,\n articleEvidenceId,\n },\n );\n }\n\n recheckedClaims += 1;\n }\n\n const state = await this.getFactAuditState();\n return {\n ...state,\n claimRecheck: {\n auditRunId,\n recheckedClaims,\n candidateFacts: supportCandidates.length,\n candidateEvidence: candidateEvidence.size,\n warnings,\n },\n };\n }\n\n public async recheckFactClaimsAction(\n options: FactAuditClaimRecheckOptions = {},\n ) {\n return this.recheckFactClaims(options);\n }\n\n public async updateFactEvidenceStatus(\n options: FactEvidenceStatusUpdateOptions = {},\n ) {\n await this.requireFactLinking('evidence status update');\n if (!this.id) {\n throw new Error('Cannot update fact evidence for unsaved content');\n }\n\n const status = normalizeFactEvidenceStatus(options.status);\n if (!status) {\n throw new Error('A valid evidence status is required');\n }\n\n const requestedEvidenceIds = [\n ...new Set(\n (options.evidenceIds || []).filter(\n (id): id is string => typeof id === 'string' && id.length > 0,\n ),\n ),\n ];\n const evidences = await this.getFactEvidenceCollection();\n const sourceMaterials = await this.getFactAuditSourceMaterials();\n const allowedSourceKeys = new Set(\n sourceMaterials.sources.map(\n (source: FactAuditSourceMaterial) =>\n `${source.sourceKind}:${source.sourceId}`,\n ),\n );\n const allowedEvidenceIds: string[] = [];\n\n for (const evidenceId of requestedEvidenceIds) {\n const evidence = (await evidences.get({ id: evidenceId })) as any;\n if (!evidence) {\n continue;\n }\n\n if (\n this.tenantId &&\n evidence.tenantId &&\n evidence.tenantId !== this.tenantId\n ) {\n continue;\n }\n\n const metadata = getEvidenceMetadata(evidence);\n const sourceKey = `${evidence.sourceKind || ''}:${\n evidence.sourceId || ''\n }`;\n if (\n metadata.contentId === this.id ||\n (evidence.sourceKind === 'content' && evidence.sourceId === this.id) ||\n allowedSourceKeys.has(sourceKey)\n ) {\n allowedEvidenceIds.push(evidenceId);\n }\n }\n\n const updated = await evidences.bulkUpdateStatus(\n allowedEvidenceIds,\n status,\n {\n reason: options.reason,\n },\n );\n const state = await this.getFactAuditState();\n\n return {\n ...state,\n evidenceStatusUpdate: {\n status,\n requestedEvidenceIds,\n updatedEvidenceIds: updated\n .map((entry: any) => entry.id)\n .filter((id: unknown): id is string => typeof id === 'string'),\n skippedEvidenceIds: requestedEvidenceIds.filter(\n (id) => !allowedEvidenceIds.includes(id),\n ),\n },\n };\n }\n\n public async updateFactEvidenceStatusAction(\n options: FactEvidenceStatusUpdateOptions = {},\n ) {\n return this.updateFactEvidenceStatus(options);\n }\n\n public async getFactAuditState(): Promise<FactAuditState> {\n if (!this.id) {\n return {\n counts: {\n total: 0,\n supported: 0,\n unsupported: 0,\n contradicted: 0,\n needs_review: 0,\n },\n claims: [],\n resourceClaims: [],\n warnings: [],\n generatedBy: FACT_AUDIT_GENERATED_BY,\n latestAuditRunId: null,\n };\n }\n\n const [facts, factLinks] = await Promise.all([\n this.getFacts({\n relationship: 'referenced_in',\n latestOnly: false,\n includeSuperseded: false,\n }),\n this.getFactLinks({ relationship: 'referenced_in' }),\n ]);\n const factMap = new Map(\n facts\n .filter((fact: any) => fact.id)\n .map((fact: any) => [fact.id as string, fact]),\n );\n const evidences = await this.getFactEvidenceCollection();\n const allFacts = await this.getFactCollection();\n const generatedLinks = factLinks\n .map((link: any) => ({\n link,\n metadata: getGeneratedFactAuditMetadata(link),\n }))\n .filter(\n (entry): entry is { link: any; metadata: Record<string, any> } =>\n entry.metadata !== null,\n );\n const claims: FactAuditClaim[] = [];\n const resourceClaimsByKey = new Map<string, FactAuditResourceClaim>();\n const warnings: string[] = [];\n let latestAuditRunId: string | null = null;\n\n for (const { link, metadata } of generatedLinks) {\n const fact = factMap.get(link.factId);\n if (!fact) {\n continue;\n }\n\n latestAuditRunId = metadata.auditRunId || latestAuditRunId;\n const status = (metadata.supportStatus ||\n 'needs_review') as FactClaimSupportStatus;\n const matchedFactIds = Array.isArray(metadata.supportingFactIds)\n ? metadata.supportingFactIds\n : [];\n const articleEvidenceId =\n typeof metadata.articleEvidenceId === 'string'\n ? metadata.articleEvidenceId\n : null;\n const supportingEvidenceIds = new Set(\n Array.isArray(metadata.supportingEvidenceIds)\n ? metadata.supportingEvidenceIds.filter(\n (id: unknown): id is string => typeof id === 'string',\n )\n : [],\n );\n const [allClaimEvidence, matchedFacts] = await Promise.all([\n evidences.getForFact(fact.id as string),\n Promise.all(\n matchedFactIds.map(async (factId: string) => {\n const matchedFact = await allFacts.get({ id: factId });\n const matchedEvidence = (await evidences.getForFact(factId)).filter(\n (entry: any) =>\n supportingEvidenceIds.size === 0\n ? entry.sourceKind !== 'content' || entry.sourceId !== this.id\n : supportingEvidenceIds.has(entry.id),\n );\n return matchedFact\n ? {\n fact: serializeFact(matchedFact),\n evidence: matchedEvidence.map((entry: any) => ({\n ...serializeFact(entry),\n metadata:\n typeof entry.getMetadata === 'function'\n ? entry.getMetadata()\n : {},\n })),\n }\n : null;\n }),\n ),\n ]);\n const claimEvidence = allClaimEvidence.filter((entry: any) =>\n articleEvidenceId\n ? entry.id === articleEvidenceId\n : entry.sourceKind === 'content' && entry.sourceId === this.id,\n );\n\n claims.push({\n id: fact.id as string,\n fact: serializeFact(fact),\n supportStatus: status,\n claimQuote: metadata.claimQuote || null,\n rationale: metadata.rationale || null,\n confidence: metadata.confidence ?? null,\n relationship: link.relationship || null,\n linkMetadata: metadata,\n evidence: claimEvidence.map((entry: any) => ({\n ...serializeFact(entry),\n metadata:\n typeof entry.getMetadata === 'function' ? entry.getMetadata() : {},\n })),\n matchedFacts: matchedFacts.filter(\n Boolean,\n ) as FactAuditClaim['matchedFacts'],\n });\n }\n\n const generatedEvidence = await evidences.list({\n where: { tenantId: this.tenantId ?? null },\n });\n for (const evidence of generatedEvidence as any[]) {\n const metadata =\n typeof evidence.getMetadata === 'function'\n ? evidence.getMetadata()\n : {};\n if (\n metadata.generatedBy !== FACT_AUDIT_GENERATED_BY ||\n metadata.contentId !== this.id ||\n evidence.sourceKind === 'content'\n ) {\n continue;\n }\n\n const fact = await allFacts.get({ id: evidence.factId });\n if (!fact) {\n continue;\n }\n\n const key = [\n evidence.factId,\n evidence.sourceKind,\n evidence.sourceId,\n evidence.evidenceKey,\n ].join(':');\n const serializedEvidence = {\n ...serializeFact(evidence),\n metadata,\n };\n const existing = resourceClaimsByKey.get(key);\n if (existing) {\n existing.evidence.push(serializedEvidence);\n continue;\n }\n\n resourceClaimsByKey.set(key, {\n id: fact.id as string,\n fact: serializeFact(fact),\n sourceKind: evidence.sourceKind || null,\n sourceId: evidence.sourceId || null,\n sourceUrl: evidence.sourceUrl || null,\n sourceTitle: evidence.sourceTitle || null,\n locator: evidence.locator || null,\n quote: evidence.quote || null,\n status: evidence.status || 'supports',\n confidence: evidence.confidence ?? null,\n evidence: [serializedEvidence],\n });\n }\n\n const latestReview = (\n await this.getContentReviewCollection()\n ).getLatestForPolicyKey(this.id as string, 'facts');\n const review = await latestReview;\n const reviewMetadata =\n review && typeof review.getMetadata === 'function'\n ? review.getMetadata()\n : {};\n if (\n reviewMetadata.generatedBy === FACT_AUDIT_GENERATED_BY &&\n Array.isArray(reviewMetadata.warnings)\n ) {\n warnings.push(...reviewMetadata.warnings);\n }\n\n const counts = {\n total: claims.length,\n supported: 0,\n unsupported: 0,\n contradicted: 0,\n needs_review: 0,\n };\n for (const claim of claims) {\n counts[claim.supportStatus] += 1;\n }\n\n return {\n counts,\n claims,\n resourceClaims: [...resourceClaimsByKey.values()],\n warnings,\n generatedBy: FACT_AUDIT_GENERATED_BY,\n latestAuditRunId,\n };\n }\n\n public async getFactAuditStateAction() {\n return this.getFactAuditState();\n }\n\n public async getFactsState(\n options: { relationship?: FactContentRelationship } = {},\n ) {\n const governance = await this.resolveGovernance();\n if (!governance.isGoverned || !governance.factLinkingEnabled) {\n return {\n factIds: [],\n facts: [],\n factLinks: [],\n };\n }\n\n const relationship = options.relationship;\n const [facts, factLinks] = await Promise.all([\n this.getFacts({\n relationship,\n latestOnly: true,\n includeSuperseded: false,\n }),\n this.getFactLinks(relationship ? { relationship } : {}),\n ]);\n\n return {\n factIds: facts.map((fact: any) => fact.id).filter(Boolean),\n facts: facts.map(serializeFact),\n factLinks: factLinks.map(serializeFactLink),\n };\n }\n\n public async syncFactsState(\n options: {\n factIds?: string[];\n relationship?: FactContentRelationship;\n } = {},\n ) {\n const governance = await this.requireFactLinking('fact sync');\n const relationship =\n options.relationship || governance.defaultFactRelationship;\n const sync = await this.syncFacts(options.factIds || [], relationship);\n const state = await this.getFactsState({ relationship });\n return {\n ...state,\n sync,\n };\n }\n\n public async createVersion(options: CreateContentVersionOptions = {}) {\n const versions = await this.getContentVersionCollection();\n return versions.createSnapshot(this, options);\n }\n\n public async getVersions() {\n if (!this.id) {\n return [];\n }\n\n const versions = await this.getContentVersionCollection();\n return versions.listForContent(this.id as string);\n }\n\n public async restoreFromVersion(versionNumber: number) {\n const versions = await this.getContentVersionCollection();\n return versions.restoreIntoContent(this, versionNumber);\n }\n\n public async getReviews(kind?: RunContentReviewOptions['kind']) {\n if (!this.id) {\n return [];\n }\n\n const reviews = await this.getContentReviewCollection();\n return reviews.listForContent(this.id as string, kind);\n }\n\n public async listReviews(\n options: { kind?: RunContentReviewOptions['kind'] } = {},\n ) {\n const reviews = await this.getReviews(options.kind);\n return reviews.map(serializeContentReview);\n }\n\n public async getReviewRequirements(\n profileKey: string,\n governance?: ResolvedContentGovernance,\n ) {\n const resolvedGovernance = governance || (await this.resolveGovernance());\n return getContentReviewRequirements(\n profileKey,\n resolvedGovernance.availableProfiles,\n );\n }\n\n public async getGovernanceState(): Promise<ContentGovernanceState> {\n const governance = await this.resolveGovernance();\n\n if (!governance.isGoverned) {\n return {\n ...governance,\n reviewProfiles: [],\n };\n }\n\n return {\n ...governance,\n reviewProfiles: await this.listReviewProfilesAction(),\n };\n }\n\n public async getGovernanceStateAction() {\n return this.getGovernanceState();\n }\n\n public async listReviewProfilesAction() {\n const governance = await this.resolveGovernance();\n if (!governance.isGoverned) {\n return [];\n }\n\n return Promise.all(\n getContentReviewProfileKeys(governance.availableProfiles).map(\n (profileKey) => this.evaluateReviewProfile(profileKey),\n ),\n );\n }\n\n public async evaluateReviewProfile(\n profileKey: string,\n ): Promise<ContentReviewProfileEvaluation> {\n const governance = await this.resolveGovernance();\n const requirements = await this.getReviewRequirements(\n profileKey,\n governance,\n );\n\n if (requirements.length === 0) {\n return {\n profileKey,\n ready: true,\n complete: true,\n requirements: [],\n };\n }\n\n const reviews = await this.getContentReviewCollection();\n const reviewFingerprintCache = new Map<string, string>();\n const evaluatedRequirements = await Promise.all(\n requirements.map(async (requirement) => {\n if (!reviewFingerprintCache.has(requirement.policyKey)) {\n reviewFingerprintCache.set(\n requirement.policyKey,\n await this.buildReviewFingerprint(requirement.policyKey),\n );\n }\n\n const latestReview =\n this.id && requirement.policyKey\n ? await reviews.getLatestForPolicyKey(\n this.id as string,\n requirement.policyKey,\n )\n : null;\n const acceptedStatuses = getAcceptedContentReviewStatuses(requirement);\n const latestStatus = latestReview?.status ?? null;\n const latestMetadata =\n typeof latestReview?.getMetadata === 'function'\n ? latestReview.getMetadata()\n : {};\n const currentFingerprint =\n reviewFingerprintCache.get(requirement.policyKey) || null;\n const reviewedFingerprint =\n latestMetadata?.reviewFingerprint ||\n latestMetadata?.contentFingerprint ||\n null;\n const missing = !latestReview;\n const stale =\n !missing &&\n !!reviewedFingerprint &&\n reviewedFingerprint !== currentFingerprint;\n const executed =\n latestStatus !== null && latestStatus !== 'pending' && !stale;\n const satisfied =\n !stale &&\n latestStatus !== null &&\n acceptedStatuses.includes(latestStatus);\n\n return {\n kind: getContentReviewKind(\n requirement.policyKey,\n governance.reviewPolicies,\n ),\n policyKey: requirement.policyKey,\n label:\n requirement.label ||\n getContentReviewPolicy(\n requirement.policyKey,\n governance.reviewPolicies,\n )?.label ||\n requirement.policyKey,\n blocking: requirement.blocking === true,\n acceptedStatuses,\n missing,\n stale,\n executed,\n satisfied,\n latestReviewId: (latestReview?.id as string) || null,\n latestStatus,\n latestSummary: latestReview?.summary || null,\n };\n }),\n );\n\n return {\n profileKey,\n ready: evaluatedRequirements\n .filter((requirement) => requirement.blocking)\n .every((requirement) => requirement.satisfied),\n complete: evaluatedRequirements.every(\n (requirement) => requirement.executed,\n ),\n requirements: evaluatedRequirements,\n };\n }\n\n public async evaluateReviewProfileAction(\n options: { profileKey?: string } = {},\n ) {\n if (!options.profileKey) {\n throw new Error('profileKey is required');\n }\n\n return this.evaluateReviewProfile(options.profileKey);\n }\n\n public async isReadyForReviewProfile(profileKey: string): Promise<boolean> {\n const evaluation = await this.evaluateReviewProfile(profileKey);\n return evaluation.ready;\n }\n\n public async getPublishedTransparency() {\n if (!this.id) {\n return null;\n }\n\n const versions = await this.getContentVersionCollection();\n const latestPublicationVersion =\n await versions.getLatestPublishedForContent(this.id as string);\n\n return latestPublicationVersion?.getTransparency() || null;\n }\n\n public async getPublishedTransparencyAction() {\n return this.getPublishedTransparency();\n }\n\n public async previewTransparency() {\n const governance = await this.resolveGovernance();\n if (!governance.isGoverned || !governance.transparencyEnabled) {\n return null;\n }\n\n return this.buildTransparencySnapshot({\n snapshotKind: 'preview',\n governance,\n });\n }\n\n public async previewTransparencyAction() {\n return this.previewTransparency();\n }\n\n public async runReview(options: RunContentReviewOptions = {}) {\n const governance = await this.requireGovernance('review execution');\n\n if (!this.id) {\n throw new Error('Cannot review unsaved content');\n }\n\n const policyKey = options.policyKey || options.kind || 'custom';\n const policy = getContentReviewPolicy(policyKey, governance.reviewPolicies);\n const kind =\n options.kind ||\n getContentReviewKind(policyKey, governance.reviewPolicies);\n const facts =\n options.facts !== undefined\n ? options.facts\n : governance.factLinkingEnabled &&\n (kind === 'facts' || Boolean(options.factIds?.length))\n ? await this.getFacts({\n latestOnly: true,\n includeSuperseded: false,\n })\n : [];\n const filteredFacts =\n options.factIds && options.factIds.length > 0\n ? facts.filter((fact) => options.factIds?.includes(fact.id as string))\n : facts;\n const reviewPrompt = buildContentReviewPrompt({\n kind,\n content: this,\n facts: filteredFacts,\n policy,\n customInstructions: options.instructions,\n });\n const resolvedPrompt = await resolvePrompt(smrtContentReviewPrompt.key, {\n db: this.options.db,\n tenantId: this.tenantId,\n variables: {\n contentBody: this.body,\n contentDescription: this.description ?? '',\n contentId: this.id ?? '',\n contentTitle: this.title,\n kind,\n policyKey: policy?.key || kind,\n reviewPrompt,\n },\n });\n const reviewFingerprint = await this.buildReviewFingerprint(policyKey);\n const ai = this.ai as {\n message?: (\n prompt: string,\n options?: Record<string, unknown>,\n ) => Promise<string>;\n };\n if (!ai?.message) {\n throw new Error('AI client is not configured for content reviews');\n }\n\n const rawResponse = await ai.message(\n resolvedPrompt.text,\n promptMessageOptions(resolvedPrompt.ai),\n );\n const result = parseContentReviewResponse(rawResponse);\n const version =\n options.createVersion === false\n ? null\n : await this.createVersion({\n kind: 'review',\n summary: result.summary,\n metadata: {\n kind,\n policyKey,\n reviewFingerprint,\n },\n });\n\n const reviews = await this.getContentReviewCollection();\n return reviews.createFromResult({\n contentId: this.id as string,\n contentVersionId: version?.id as string | undefined,\n kind,\n policyKey,\n reviewer: options.reviewer || 'system',\n result,\n metadata: {\n ...(options.metadata || {}),\n prompt: resolvedPrompt.text,\n rawResponse,\n reviewFingerprint,\n factIds: filteredFacts.map((fact) => fact.id),\n },\n tenantId: this.tenantId,\n });\n }\n\n public async runReviewAction(options: RunContentReviewOptions = {}) {\n let review: ContentReview;\n\n if (options.kind === 'facts') {\n review = await this.reviewFacts(options);\n } else if (options.kind === 'safety') {\n review = await this.reviewSafety(options);\n } else {\n review = await this.runReview(options);\n }\n\n return serializeContentReview(review);\n }\n\n public async reviewFacts(\n options: Omit<RunContentReviewOptions, 'kind'> = {},\n ) {\n return this.runReview({\n ...options,\n kind: 'facts',\n policyKey: options.policyKey || 'facts',\n });\n }\n\n public async reviewSafety(\n options: Omit<RunContentReviewOptions, 'kind'> = {},\n ) {\n const governance = await this.requireGovernance('safety review');\n const safetyPolicy = getContentReviewPolicy(\n options.policyKey || 'safety',\n governance.reviewPolicies,\n );\n const baseInstructions = safetyPolicy?.instructions || '';\n\n return this.runReview({\n ...options,\n kind: 'safety',\n policyKey: options.policyKey || 'safety',\n instructions:\n options.instructions && baseInstructions\n ? `${baseInstructions}\\n\\nAdditional app-level guidance:\\n${options.instructions}`\n : options.instructions || baseInstructions,\n });\n }\n\n public async getCorrections() {\n if (!this.id) {\n return [];\n }\n\n const corrections = await this.getContentCorrectionCollection();\n return corrections.listForContent(this.id as string);\n }\n\n public async listCorrections() {\n const corrections = await this.getCorrections();\n return corrections.map(serializeContentCorrection);\n }\n\n public async issueCorrection(options: IssueContentCorrectionOptions) {\n const governance = await this.requireGovernance('corrections');\n\n if (!this.id) {\n throw new Error('Cannot issue a correction for unsaved content');\n }\n\n let replacementFactId = '';\n if (\n governance.factLinkingEnabled &&\n options.factId &&\n options.correctedFactText\n ) {\n const facts = await this.getFactCollection();\n const existing = await facts.get({ id: options.factId });\n if (!existing) {\n throw new Error(`Fact not found for correction: ${options.factId}`);\n }\n\n // Create the correction branch directly so editorial corrections do not\n // block on synchronous embedding generation inside facts.branch().\n const replacement = await facts.create({\n textRefined: options.correctedFactText,\n textRaw: options.correctedFactText,\n type: existing.getType(),\n domain: existing.domain,\n status: 'active',\n tenantId: existing.tenantId ?? this.tenantId ?? null,\n previousFactId: options.factId,\n evolutionType: 'correction',\n } as any);\n existing.status = 'superseded';\n await existing.save();\n replacementFactId = replacement.id as string;\n await this.addFact(replacementFactId);\n }\n\n const version =\n options.createVersion === false\n ? null\n : await this.createVersion({\n kind: 'correction',\n summary: options.summary,\n metadata: {\n factId: options.factId || null,\n replacementFactId: replacementFactId || null,\n },\n });\n const correctionDraft =\n options.createVersion === false\n ? null\n : await this.buildCorrectionDraftSnapshot(options, replacementFactId);\n const draftVersion =\n options.createVersion === false || !correctionDraft\n ? null\n : await this.createVersion({\n kind: 'draft',\n summary: `Auto-created correction draft: ${options.summary}`,\n snapshot: correctionDraft.snapshot,\n metadata: {\n ...correctionDraft.metadata,\n sourceCorrectionVersionId: (version?.id as string) || null,\n sourceCorrectionVersionNumber: version?.version ?? null,\n },\n });\n\n const corrections = await this.getContentCorrectionCollection();\n const shouldPublish = options.publish ?? this.status === 'published';\n return corrections.issue({\n contentId: this.id as string,\n contentVersionId: (version?.id as string) || '',\n factId: options.factId || '',\n replacementFactId,\n correctionType: options.correctionType || 'fact',\n status: shouldPublish ? 'published' : 'draft',\n summary: options.summary,\n incorrectText: options.incorrectText || '',\n correctedText: options.correctedText || options.correctedFactText || '',\n publicNote: options.publicNote || '',\n metadata: {\n ...(options.metadata || {}),\n autoGeneratedDraft: Boolean(draftVersion),\n draftVersionId: (draftVersion?.id as string) || null,\n draftVersionNumber: draftVersion?.version ?? null,\n sourceCorrectionVersionId: (version?.id as string) || null,\n sourceCorrectionVersionNumber: version?.version ?? null,\n correctionProfileKey: governance.correctionProfileKey || null,\n },\n tenantId: this.tenantId,\n publishedAt: shouldPublish ? new Date() : null,\n });\n }\n\n public async issueCorrectionAction(options: IssueContentCorrectionOptions) {\n const correction = await this.issueCorrection(options);\n return serializeContentCorrection(correction);\n }\n\n public async listVersions() {\n const versions = await this.getVersions();\n return versions.map(serializeContentVersion);\n }\n\n public async mutateVersionAction(\n options: CreateContentVersionOptions & {\n action?: string;\n versionNumber?: number | string;\n } = {},\n ) {\n if (options.action === 'restore') {\n const versionNumber = Number(options.versionNumber);\n if (!Number.isFinite(versionNumber)) {\n throw new Error('versionNumber is required to restore a version');\n }\n\n const restored = await this.restoreFromVersion(versionNumber);\n return serializeContent(restored);\n }\n\n const version = await this.createVersion(options);\n return serializeContentVersion(version);\n }\n\n /**\n * Note: toJSON() is inherited from SmrtObject\n *\n * The parent implementation handles:\n * - STI discriminator (_meta_type) for polymorphic queries\n * - Meta field extraction (_meta_data) for child-specific fields\n * - Automatic serialization of all fields from manifest\n *\n * DO NOT override toJSON() unless you call super.toJSON() first.\n * See issue #377 for details on why this override was removed.\n */\n\n // ============================================\n // Category Helper Methods\n // ============================================\n\n /**\n * Get category segments as array\n * @example 'politics/local' -> ['politics', 'local']\n */\n getCategorySegments(): string[] {\n if (!this.category) return [];\n return this.category.split('/').filter(Boolean);\n }\n\n /**\n * Get parent category path\n * @example 'politics/local/town' -> 'politics/local'\n * @example 'politics' -> null\n */\n getParentCategory(): string | null {\n const segments = this.getCategorySegments();\n if (segments.length <= 1) return null;\n return segments.slice(0, -1).join('/');\n }\n\n /**\n * Get root (top-level) category\n * @example 'politics/local/town' -> 'politics'\n */\n getRootCategory(): string | null {\n const segments = this.getCategorySegments();\n return segments[0] || null;\n }\n\n /**\n * Get all ancestor category paths (for breadcrumbs)\n * @example 'politics/local' -> ['politics', 'politics/local']\n */\n getAncestorPaths(): string[] {\n const segments = this.getCategorySegments();\n return segments.map((_, i) => segments.slice(0, i + 1).join('/'));\n }\n\n /**\n * Check if content belongs to a category (optionally including subcategories)\n * @param categoryPath - Category to check\n * @param includeChildren - If true, matches 'politics' for content in 'politics/local'\n */\n isInCategory(categoryPath: string, includeChildren = true): boolean {\n if (!this.category) return false;\n if (includeChildren) {\n return (\n this.category === categoryPath ||\n this.category.startsWith(`${categoryPath}/`)\n );\n }\n return this.category === categoryPath;\n }\n\n // ============================================\n // Asset Relationship Methods\n // ============================================\n\n /**\n * Get all assets associated with this content\n * @param relationship - Optional filter by relationship type (e.g., 'thumbnail', 'attachment')\n * @returns Promise resolving to array of assets\n */\n async getAssets(relationship?: string): Promise<Asset[]> {\n if (!this.id) {\n return [];\n }\n\n return this.resolveAssetsForLinks(\n await this.getContentAssetLinks(relationship),\n );\n }\n\n /**\n * Add an asset to this content with a relationship type\n * @param asset - The asset to associate\n * @param relationship - Relationship type (e.g., 'thumbnail', 'attachment', 'inline')\n * @param sortOrder - Optional sort order for display\n */\n async addAsset(\n asset: Asset,\n relationship = 'attachment',\n sortOrder = 0,\n ): Promise<void> {\n if (!this.id || !asset.id) {\n throw new Error('Cannot associate unsaved content or asset');\n }\n\n // Validate relationship - must start with letter/underscore, contain only alphanumeric and underscores\n if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(relationship)) {\n throw new Error(\n `Invalid relationship type \"${relationship}\"; must start with a letter or underscore and contain only letters, digits, and underscores`,\n );\n }\n\n // Validate sortOrder is a reasonable integer\n if (\n !Number.isInteger(sortOrder) ||\n sortOrder < 0 ||\n sortOrder > 2147483647\n ) {\n throw new Error(\n `Invalid sortOrder \"${sortOrder}\"; must be a non-negative integer`,\n );\n }\n\n const contentAssets = await this.getContentAssetCollection();\n await contentAssets.attach(this.id, asset.id, {\n relationship,\n sortOrder,\n tenantId: this.tenantId,\n });\n }\n\n /**\n * Remove an asset from this content\n * @param assetId - ID of the asset to remove\n * @param relationship - Optional specific relationship to remove (removes all if not specified)\n */\n async removeAsset(assetId: string, relationship?: string): Promise<void> {\n if (!this.id) {\n return;\n }\n\n try {\n const contentAssets = await this.getContentAssetCollection();\n await contentAssets.detach(\n this.id,\n assetId,\n relationship ? { relationship } : {},\n );\n } catch (error) {\n if (!isMissingTableError(error, 'content_assets')) {\n throw error;\n }\n }\n }\n\n // ============================================\n // Metadata Accessors (MetadataAccessor contract)\n // ============================================\n\n /**\n * Get the full metadata record. Always returns a plain object — never\n * `null`, never an array — so callers can safely read nested keys without\n * defensive checks.\n *\n * Pure read with no side-effect on `this.metadata`: if the field is\n * currently `null` (e.g. fresh from the DB) or non-record-shaped, an\n * empty object is returned but the field is **not** mutated. This avoids\n * accidentally marking the object dirty during a read, which would\n * otherwise cause SmrtObject's save lifecycle to write `{}` back over a\n * NULL column on the next save. Callers that want to normalise the\n * stored field should use {@link Content.setMetadata}.\n */\n getMetadata(): Record<string, any> {\n return isPlainMetadataRecord(this.metadata) ? this.metadata : {};\n }\n\n /**\n * Replace the full metadata record. Passing `null`/`undefined` (or any\n * non-record value such as an array) clears it to an empty object so\n * downstream readers can rely on the field always being a plain object.\n */\n setMetadata(metadata: Record<string, any> | null | undefined): void {\n this.metadata = isPlainMetadataRecord(metadata) ? { ...metadata } : {};\n }\n\n /**\n * Shallow-merge a patch over the current metadata. Returns the resulting\n * record so callers can chain reads without re-reading the field. Unlike\n * {@link Content.getMetadata}, this method does intentionally write back\n * to `this.metadata` because the merge is a write.\n */\n updateMetadata(patch: Partial<Record<string, any>>): Record<string, any> {\n const next = { ...this.getMetadata(), ...(patch ?? {}) };\n this.metadata = next;\n return next;\n }\n\n // ============================================\n // Thumbnail Convenience Methods\n // ============================================\n\n /**\n * Get the thumbnail image for this content\n * @returns Promise resolving to the thumbnail Image or null\n */\n async getThumbnail(): Promise<Image | null> {\n if (!this.thumbnailAssetId) {\n return null;\n }\n\n const images = await (ImageCollection as any).create({\n db: (this as any).options?.db,\n });\n\n return images.get({ id: this.thumbnailAssetId });\n }\n\n /**\n * Set the thumbnail image for this content\n * @param image - The image to set as thumbnail\n */\n async setThumbnail(image: Image): Promise<void> {\n // Add as asset with 'thumbnail' relationship\n await this.addAsset(image, 'thumbnail', 0);\n\n // Update thumbnailAssetId\n this.thumbnailAssetId = image.id ?? null;\n await this.save();\n }\n\n /**\n * Generate a thumbnail for this content using the specified strategy\n *\n * @param options - Thumbnail generation options including strategy\n * @returns Promise resolving to the generated Image\n *\n * @example Headline card thumbnail\n * ```typescript\n * const thumbnail = await content.generateThumbnail({\n * strategy: 'headline-card',\n * brandColor: '#1a56db',\n * logoUrl: 'https://example.com/logo.png'\n * });\n * ```\n *\n * @example Static map thumbnail (requires metadata.latitude/longitude)\n * ```typescript\n * const thumbnail = await content.generateThumbnail({\n * strategy: 'static-map',\n * mapProvider: 'mapbox'\n * });\n * ```\n *\n * @example AI-generated thumbnail\n * ```typescript\n * const thumbnail = await content.generateThumbnail({\n * strategy: 'ai-generate'\n * });\n * ```\n */\n async generateThumbnail(options: ThumbnailOptions): Promise<Image> {\n const generator = new ThumbnailGenerator(this, (this as any).options);\n const image = await generator.generate(options);\n await this.setThumbnail(image);\n return image;\n }\n}\n","import { definePrompt } from '@happyvertical/smrt-prompts';\n\nexport const contentEditorSessionPrompt = definePrompt({\n key: 'content.chat.contentEditorSession',\n template:\n 'You are an AI assistant collaborating with the user to edit and improve a specific piece of content.',\n ai: {\n temperature: 0.7,\n maxTokens: 2000,\n },\n editable: {\n template: true,\n profile: true,\n model: true,\n params: true,\n },\n});\n\nexport const contentEditorInteractionPrompt = definePrompt({\n key: 'content.chat.contentEditorInteraction',\n template: `CURRENT CONTENT FORM STATE:\n- title: {title}\n- description: {description}\n- type: {type}\n- status: {status}\n- state: {state}\n- body:\n{body}\n{references}\n\nINSTRUCTIONS FOR CO-AUTHORING:\nYou are a content co-author. You can update any of the above fields.\n\nWhen you want to make changes to the content, output a JSON code block with a top-level \"fields\" object containing only the fields you want to change.\n\nValid field names: title, description, type, status, state, body.\nValid status values: draft, published, archived.\nValid state values: active, highlighted, deprecated.\nValid type values: article, document, mirror.\n\nRULES:\n- Only include fields you are actually changing.\n- If the user asks to write or rewrite content, update the \"body\" field.\n- If the user asks to change the title, update the \"title\" field.\n- You can change multiple fields at once.\n- Always respond conversationally before the JSON block.\n- The JSON block will be automatically applied to the editor.`,\n ai: {\n temperature: 0.7,\n maxTokens: 2000,\n },\n editable: {\n template: true,\n profile: true,\n model: true,\n params: true,\n },\n});\n","import type { ResolvedPrompt } from '@happyvertical/smrt-prompts';\n\ntype SessionContext = Record<string, unknown>;\n\nexport interface ContentChatAISelection {\n profile: string | null;\n provider: string | null;\n model: string | null;\n allowedModels: string[] | null;\n temperature: number | null;\n maxTokens: number | null;\n}\n\nexport interface ContentEditorInteractionInput {\n fields?: Record<string, unknown> | null;\n currentEditorState?: unknown;\n references?: string | null;\n}\n\nconst CONTENT_PROMPT_DELIMITER = 'SMRT_CONTENT_FIELD';\n\nfunction readString(\n context: SessionContext,\n key: keyof ContentChatAISelection,\n): string | null {\n const value = context[key];\n return typeof value === 'string' && value.length > 0 ? value : null;\n}\n\nfunction readNumber(\n context: SessionContext,\n key: keyof ContentChatAISelection,\n): number | null {\n const value = context[key];\n return typeof value === 'number' ? value : null;\n}\n\nexport function inferProviderFromModel(model: string): string {\n const normalized = model.toLowerCase();\n const providerPrefix = normalized.match(/^([a-z0-9_-]+)\\//)?.[1];\n if (providerPrefix === 'openrouter') {\n return 'openrouter';\n }\n if (providerPrefix === 'anthropic') {\n return 'anthropic';\n }\n if (providerPrefix === 'gemini' || providerPrefix === 'google') {\n return 'gemini';\n }\n if (providerPrefix === 'openai') {\n return 'openai';\n }\n\n const modelTokens = normalized.split(/[^a-z0-9]+/).filter(Boolean);\n if (\n modelTokens.includes('claude') ||\n modelTokens.includes('sonnet') ||\n modelTokens.includes('haiku') ||\n modelTokens.includes('opus')\n ) {\n return 'anthropic';\n }\n\n if (modelTokens.includes('gemini')) {\n return 'gemini';\n }\n\n return 'openai';\n}\n\nexport function getContentChatAISelection(\n context: SessionContext,\n): ContentChatAISelection {\n const allowedModels = context.allowedModels;\n return {\n profile: readString(context, 'profile'),\n provider: readString(context, 'provider'),\n model: readString(context, 'model'),\n allowedModels:\n Array.isArray(allowedModels) &&\n allowedModels.every((value) => typeof value === 'string')\n ? allowedModels\n : null,\n temperature: readNumber(context, 'temperature'),\n maxTokens: readNumber(context, 'maxTokens'),\n };\n}\n\nexport function resolveContentChatModelSelection(\n context: SessionContext,\n requestedModel: string | null | undefined,\n fallbackModel: string,\n): { model: string; provider: string } {\n const stored = getContentChatAISelection(context);\n const model = requestedModel || stored.model || fallbackModel;\n const provider =\n stored.provider && stored.model && model === stored.model\n ? stored.provider\n : inferProviderFromModel(model);\n\n return { model, provider };\n}\n\nexport function buildContentChatModelUpdates(\n context: SessionContext,\n requestedModel: string | null | undefined,\n fallbackModel: string,\n): Record<string, string | null> {\n const stored = getContentChatAISelection(context);\n const { model, provider } = resolveContentChatModelSelection(\n context,\n requestedModel,\n fallbackModel,\n );\n\n return {\n model,\n provider,\n ...(stored.profile && stored.model && model !== stored.model\n ? { profile: null }\n : {}),\n };\n}\n\nexport function buildContentEditorSessionContext(\n contentId: string,\n prompt: ResolvedPrompt,\n): SessionContext {\n return {\n contentId,\n ...(prompt.ai.profile ? { profile: prompt.ai.profile } : {}),\n ...(prompt.ai.provider ? { provider: prompt.ai.provider } : {}),\n ...(prompt.ai.model ? { model: prompt.ai.model } : {}),\n ...(prompt.ai.allowedModels\n ? { allowedModels: prompt.ai.allowedModels }\n : {}),\n ...(prompt.ai.temperature !== undefined\n ? { temperature: prompt.ai.temperature }\n : {}),\n ...(prompt.ai.maxTokens !== undefined\n ? { maxTokens: prompt.ai.maxTokens }\n : {}),\n };\n}\n\nfunction displayValue(value: unknown, fallback = '(empty)'): string {\n if (typeof value === 'string') {\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : fallback;\n }\n\n if (value === undefined || value === null) {\n return fallback;\n }\n\n return String(value);\n}\n\nfunction delimitPromptValue(name: string, value: string): string {\n // Strip any forged SMRT_ delimiter markers from the user value so it can't\n // close the wrapper early or open a fake field. The previous `[^>]*` stopped\n // at the first `>` (so `<<<SMRT_X>injected>>>` slipped through) and was\n // case-sensitive (so `<<<smrt_...>>>` slipped through). `[\\s\\S]*?` is\n // non-greedy and `>`-tolerant, and the `i` flag closes the case bypass\n // (#1387 minor).\n const sanitizedValue = value.replace(/<<<\\s*(?:END_)?SMRT_[\\s\\S]*?>>>/gi, '');\n return `<<<${CONTENT_PROMPT_DELIMITER} name=${name}>>>\\n${sanitizedValue}\\n<<<END_${CONTENT_PROMPT_DELIMITER}>>>`;\n}\n\nexport function buildContentEditorInteractionVariables(\n input: ContentEditorInteractionInput,\n): Record<string, string> {\n const fields = input.fields ?? {};\n\n return {\n title: delimitPromptValue('title', displayValue(fields.title)),\n description: delimitPromptValue(\n 'description',\n displayValue(fields.description),\n ),\n type: displayValue(fields.type, 'article'),\n status: displayValue(fields.status, 'draft'),\n state: displayValue(fields.state, 'active'),\n body: delimitPromptValue(\n 'body',\n displayValue(fields.body ?? input.currentEditorState),\n ),\n references: input.references ?? '',\n };\n}\n","import { type AIClientOptions, getAI } from '@happyvertical/ai';\nimport { ChatService } from '@happyvertical/smrt-chat';\nimport { sendAgentReply } from '@happyvertical/smrt-chat/internal/agent-runtime';\nimport {\n type ResolvedPrompt,\n resolvePrompt,\n} from '@happyvertical/smrt-prompts';\nimport type { DatabaseInterface } from '@happyvertical/sql';\nimport { sanitizeHtml, stripHtml } from './body-format';\nimport {\n contentEditorInteractionPrompt,\n contentEditorSessionPrompt,\n} from './content-chat-prompts';\nimport {\n buildContentChatModelUpdates,\n buildContentEditorInteractionVariables,\n buildContentEditorSessionContext,\n getContentChatAISelection,\n resolveContentChatModelSelection,\n} from './content-chat-session';\n\nconst CONTENT_EDITOR_AGENT_ID = 'content_editor';\nconst REFERENCE_TITLE_MAX_LENGTH = 200;\nconst REFERENCE_BODY_MAX_LENGTH = 2000;\nconst MAX_REFERENCE_IDS = 20;\n\nexport type ContentChatAIConfig = AIClientOptions & {\n apiKey?: string;\n allowedModels?: string[];\n model?: string;\n defaultModel?: string;\n provider?: string;\n type?: string;\n};\n\nexport interface ContentChatCollectionLike {\n db: DatabaseInterface;\n // Accepts either a raw id or a bound `{ id, tenantId }` filter so the content\n // lookup can be tenant-bound at the query level (S5 #1392) rather than doing a\n // cross-tenant `get(id)` followed only by a post-filter. A real SmrtCollection\n // satisfies this — its `get` takes `string | Record<string, any>`.\n get(filter: string | Record<string, unknown>): Promise<unknown>;\n}\n\nexport interface ContentChatSessionInput {\n db: DatabaseInterface;\n contents?: ContentChatCollectionLike;\n tenantId?: string | null;\n profileId?: string | null;\n contentId: string;\n resolvePromptFn?: typeof resolvePrompt;\n}\n\nexport interface CreateContentChatThreadInput extends ContentChatSessionInput {\n title: string;\n sessionId: string;\n model?: string | null;\n initializeChatCollections?: () => Promise<void>;\n}\n\nexport interface ListContentChatThreadMessagesInput {\n db: DatabaseInterface;\n contents?: ContentChatCollectionLike;\n tenantId?: string | null;\n profileId?: string | null;\n contentId: string;\n threadId: string;\n}\n\nexport interface SendContentChatThreadMessageInput {\n contents: ContentChatCollectionLike;\n tenantId?: string | null;\n profileId?: string | null;\n contentId: string;\n threadId: string;\n content: string;\n sessionId: string;\n model?: string | null;\n currentEditorState?: unknown;\n referenceIds?: unknown;\n formFields?: Record<string, unknown> | null;\n aiConfig?: ContentChatAIConfig | null;\n env?: Record<string, string | undefined>;\n resolvePromptFn?: typeof resolvePrompt;\n getAIClient?: typeof getAI;\n resolveAI?: (\n input: ResolveContentChatAIInput,\n ) => Promise<ResolvedContentChatAI | null> | ResolvedContentChatAI | null;\n}\n\nexport interface ResolveContentChatAIInput {\n aiConfig: ContentChatAIConfig;\n env: Record<string, string | undefined>;\n sessionContext: Record<string, unknown>;\n requestedModel?: string | null;\n interactionPrompt: ResolvedPrompt;\n}\n\nexport interface ResolvedContentChatAI {\n clientOptions: ContentChatAIConfig;\n model: string;\n provider?: string | null;\n profile?: string | null;\n temperature?: number | null;\n maxTokens?: number | null;\n}\n\nfunction resolveTenantScope(value: string | null | undefined): string | null {\n return asNonEmptyString(value);\n}\n\nfunction resolveChatTenantId(value: string | null | undefined): string {\n return resolveTenantScope(value) ?? 'global';\n}\n\nfunction resolveProfileId(value: string | null | undefined): string {\n return value || 'system';\n}\n\nfunction asNonEmptyString(value: unknown): string | null {\n return typeof value === 'string' && value.trim().length > 0\n ? value.trim()\n : null;\n}\n\nfunction parseJsonObject(value: unknown): Record<string, unknown> {\n if (value && typeof value === 'object' && !Array.isArray(value)) {\n return value as Record<string, unknown>;\n }\n if (typeof value !== 'string' || value.length === 0) {\n return {};\n }\n try {\n const parsed = JSON.parse(value) as unknown;\n return parsed && typeof parsed === 'object' && !Array.isArray(parsed)\n ? (parsed as Record<string, unknown>)\n : {};\n } catch {\n return {};\n }\n}\n\nfunction getSessionContext(session: unknown): Record<string, unknown> {\n const candidate = session as {\n getSessionContext?: () => Record<string, unknown>;\n sessionContext?: unknown;\n };\n return typeof candidate.getSessionContext === 'function'\n ? candidate.getSessionContext()\n : parseJsonObject(candidate.sessionContext);\n}\n\nfunction isActiveSession(session: unknown): boolean {\n const candidate = session as { isActive?: () => boolean; status?: string };\n return typeof candidate?.isActive === 'function'\n ? candidate.isActive()\n : candidate?.status === 'active';\n}\n\nfunction isSchemaMissingError(error: unknown): boolean {\n const message = String((error as { message?: unknown })?.message ?? '');\n return (\n (error as { code?: string })?.code === 'DB_SCHEMA_MISSING' ||\n /^no such table:\\s+(?:agent_sessions|chat_(?:rooms|threads|messages|participants|reactions))\\b/i.test(\n message,\n ) ||\n /relation [\"']?(?:agent_sessions|chat_(?:rooms|threads|messages|participants|reactions))[\"']? does not exist/i.test(\n message,\n )\n );\n}\n\nexport function contentChatSessionMatchesContent(\n session: unknown,\n contentId: string,\n): boolean {\n const context = getSessionContext(session);\n return asNonEmptyString(context.contentId) === contentId;\n}\n\n/**\n * Stable agent-session key scoping a content-editor session to its content\n * (S5 #1392).\n *\n * `createAgentSession` reuses ANY active session for the same\n * agent/profile/tenant unless a `sessionKey` is supplied. The content-editor\n * agent (`content_editor`) opens a distinct conversation per content, so a\n * keyless create would reuse — and the handler would then REWRITE — a session\n * created for a different content, returning the other content's room/threads.\n * Keying the session on the content id makes a new content always create a\n * distinct session/room.\n */\nexport function contentChatSessionKey(contentId: string): string {\n return `content:${contentId}`;\n}\n\n/**\n * Tenant-bound content lookup (S5 #1392).\n *\n * Binds `tenantId` (including the `null` \"global\" scope) into the lookup itself\n * so a content row from another tenant can never be RESOLVED first and only\n * rejected after the fact. The `referenceBelongsToTenant` post-filter at every\n * call site remains as defense-in-depth.\n */\nfunction getContentForTenant(\n contents: ContentChatCollectionLike,\n tenantScope: string | null,\n id: string,\n): Promise<unknown> {\n return contents.get({ id, tenantId: tenantScope });\n}\n\nasync function assertContentExistsForTenant(\n contents: ContentChatCollectionLike | undefined,\n tenantScope: string | null,\n contentId: string,\n): Promise<void> {\n if (!contents) {\n return;\n }\n\n const content = await getContentForTenant(contents, tenantScope, contentId);\n if (!content || !referenceBelongsToTenant(content, tenantScope)) {\n throw new Error('Content not found');\n }\n}\n\nexport function contentChatSessionIsAuthorized(\n session: unknown,\n input: {\n profileId: string;\n contentId: string;\n },\n): boolean {\n const candidate = session as {\n agentId?: string;\n participantProfileId?: string;\n };\n return (\n Boolean(session) &&\n isActiveSession(session) &&\n candidate.agentId === CONTENT_EDITOR_AGENT_ID &&\n candidate.participantProfileId === input.profileId &&\n contentChatSessionMatchesContent(session, input.contentId)\n );\n}\n\nexport function contentChatMessageToJSON(\n message: unknown,\n): Record<string, unknown> {\n return typeof (message as { toJSON?: () => unknown })?.toJSON === 'function'\n ? ((message as { toJSON: () => unknown }).toJSON() as Record<\n string,\n unknown\n >)\n : (message as Record<string, unknown>);\n}\n\nexport function serializeContentChatMessageForUI(\n message: unknown,\n): Record<string, unknown> {\n const json = contentChatMessageToJSON(message);\n return {\n ...json,\n senderName: json.role === 'user' ? 'You' : 'AI Assistant',\n senderAvatarUrl: json.senderAvatarUrl || '',\n };\n}\n\nexport async function getOrCreateContentEditorChatSession(\n input: ContentChatSessionInput,\n) {\n const tenantScope = resolveTenantScope(input.tenantId);\n const tenantId = resolveChatTenantId(input.tenantId);\n const profileId = resolveProfileId(input.profileId);\n const chatService = await ChatService.create({ tenantId, db: input.db });\n await chatService.initialize();\n await assertContentExistsForTenant(\n input.contents,\n tenantScope,\n input.contentId,\n );\n\n let activeSession = null;\n try {\n // Tenant-bound session list via the ChatService facade (S5 #1392): the raw\n // `agentSessions.list({ where })` reach-in was tenant-UNBOUND and could\n // surface a session from another tenant before authorization.\n const agentSessions = await chatService.findActiveAgentSessions({\n tenantId,\n agentId: CONTENT_EDITOR_AGENT_ID,\n participantProfileId: profileId,\n });\n activeSession =\n agentSessions.find((session: unknown) =>\n contentChatSessionMatchesContent(session, input.contentId),\n ) ?? null;\n } catch (error) {\n if (!isSchemaMissingError(error)) {\n throw error;\n }\n // Chat tables may not exist yet. createAgentSession will surface the\n // concrete schema error if the runtime cannot create/use them.\n }\n\n if (!activeSession) {\n const resolvedPrompt = await (input.resolvePromptFn ?? resolvePrompt)(\n contentEditorSessionPrompt.key,\n {\n db: input.db,\n tenantId,\n },\n );\n // Scope the session to this content (S5 #1392) so a new contentId can never\n // reuse — and have its context rewritten over — a session/room created for a\n // different content. The handler-side `contentChatSessionMatchesContent`\n // filter above already narrows reads; this binds the create/reuse path too.\n const { session } = await chatService.createAgentSession({\n tenantId,\n agentId: CONTENT_EDITOR_AGENT_ID,\n actorProfileId: profileId,\n systemPrompt: resolvedPrompt.text,\n sessionKey: contentChatSessionKey(input.contentId),\n });\n await session.updateSessionContext(\n buildContentEditorSessionContext(input.contentId, resolvedPrompt),\n );\n activeSession = session;\n }\n\n let threads: unknown[] = [];\n try {\n const chatRoomId = (activeSession as { chatRoomId?: string | null })\n .chatRoomId;\n if (!chatRoomId) {\n throw new Error('Agent session is missing a chat room');\n }\n // Membership- and tenant-gated thread list via the facade (S5 #1392); the\n // editor (profileId) is the room owner, so the membership check passes.\n threads = await chatService.listRoomThreads({\n roomId: chatRoomId,\n actorProfileId: profileId,\n tenantId,\n });\n } catch {\n // Threads table may not exist yet.\n }\n\n return {\n chatService,\n session: activeSession,\n threads,\n };\n}\n\nexport async function createContentEditorChatThread(\n input: CreateContentChatThreadInput,\n) {\n await input.initializeChatCollections?.();\n\n const tenantScope = resolveTenantScope(input.tenantId);\n const tenantId = resolveChatTenantId(input.tenantId);\n const profileId = resolveProfileId(input.profileId);\n const chatService = await ChatService.create({ tenantId, db: input.db });\n await assertContentExistsForTenant(\n input.contents,\n tenantScope,\n input.contentId,\n );\n // Tenant-bound session lookup via the facade (S5 #1392): the raw\n // `agentSessions.get(id)` was tenant-UNBOUND and could select a session from\n // another tenant before the ownership/context check below.\n const session = await chatService.getAgentSession({\n agentSessionId: input.sessionId,\n tenantId,\n });\n\n if (\n !contentChatSessionIsAuthorized(session, {\n profileId,\n contentId: input.contentId,\n })\n ) {\n throw new Error('Active session not found');\n }\n\n const chatRoomId = (session as { chatRoomId?: string | null }).chatRoomId;\n if (!chatRoomId) {\n throw new Error('Active session is missing a chat room');\n }\n\n let updates: Record<string, string | null> | null = null;\n if (input.model) {\n const ctx = getSessionContext(session);\n const allowedModels = Array.isArray(ctx.allowedModels)\n ? ctx.allowedModels\n : [];\n if (allowedModels.length > 0 && !allowedModels.includes(input.model)) {\n throw new Error('AI model is not allowed for content chat');\n }\n updates = buildContentChatModelUpdates(ctx, input.model, input.model);\n }\n\n // Member-checked thread creation via the facade (S5 #1392): the editor owns\n // the agent room, so the membership check passes. Replaces the raw\n // `threads.create(...)` that skipped the facade entirely.\n const thread = await chatService.startThread({\n tenantId,\n roomId: chatRoomId,\n actorProfileId: profileId,\n title: input.title,\n });\n\n if (updates) {\n const ctx = getSessionContext(session);\n if (Object.entries(updates).some(([key, value]) => ctx[key] !== value)) {\n await (\n session as { updateSessionContext: (value: unknown) => Promise<void> }\n ).updateSessionContext(updates);\n }\n }\n\n return { chatService, session, thread };\n}\n\nexport async function listContentEditorChatThreadMessages(\n input: ListContentChatThreadMessagesInput,\n) {\n const tenantScope = resolveTenantScope(input.tenantId);\n const tenantId = resolveChatTenantId(input.tenantId);\n const profileId = resolveProfileId(input.profileId);\n const chatService = await ChatService.create({ tenantId, db: input.db });\n await assertContentExistsForTenant(\n input.contents,\n tenantScope,\n input.contentId,\n );\n // Tenant-bound thread + session lookups via the facade (S5 #1392): the raw\n // `threads.get(id)` / `agentSessions.list({ where })` reach-ins were\n // tenant-UNBOUND and could select cross-tenant chat state before authZ.\n const thread = await chatService.getThread({\n threadId: input.threadId,\n tenantId,\n });\n if (!thread) {\n throw new Error('Thread not found');\n }\n\n const roomId = (thread as { roomId?: string }).roomId;\n const activeSessions = await chatService.findActiveAgentSessions({\n tenantId,\n agentId: CONTENT_EDITOR_AGENT_ID,\n participantProfileId: profileId,\n });\n const authorizedSession = activeSessions.find(\n (session: unknown) =>\n (session as { chatRoomId?: string }).chatRoomId === roomId &&\n contentChatSessionMatchesContent(session, input.contentId),\n );\n if (!authorizedSession) {\n throw new Error('Thread not found');\n }\n\n // Membership- + tenant-gated thread message read via the facade (S5 #1392);\n // the editor owns the room, so the membership check passes. Returned\n // chronological (oldest-first) by the facade.\n const messages = await chatService.getThreadMessages({\n threadId: input.threadId,\n actorProfileId: profileId,\n tenantId,\n limit: 100,\n });\n\n return {\n chatService,\n thread,\n messages,\n };\n}\n\nfunction getEnvApiKey(\n provider: string,\n env: Record<string, string | undefined>,\n): string | undefined {\n return provider === 'anthropic'\n ? env.ANTHROPIC_API_KEY\n : provider === 'gemini'\n ? env.GEMINI_API_KEY\n : env.OPENAI_API_KEY;\n}\n\nfunction defaultEnv(): Record<string, string | undefined> {\n return typeof process !== 'undefined' ? process.env : {};\n}\n\nexport function resolveDefaultContentChatAI(\n input: ResolveContentChatAIInput,\n): ResolvedContentChatAI {\n const storedSelection = getContentChatAISelection(input.sessionContext);\n const fallbackModel =\n storedSelection.model ??\n input.aiConfig.model ??\n input.aiConfig.defaultModel ??\n input.requestedModel ??\n null;\n if (!fallbackModel) {\n throw new Error('AI model is not configured for content chat');\n }\n\n const { model, provider } = resolveContentChatModelSelection(\n input.sessionContext,\n input.requestedModel,\n fallbackModel,\n );\n const allowedModels =\n input.aiConfig.allowedModels ??\n input.interactionPrompt.ai.allowedModels ??\n storedSelection.allowedModels;\n if (\n Array.isArray(allowedModels) &&\n allowedModels.length > 0 &&\n !allowedModels.includes(model)\n ) {\n throw new Error('AI model is not allowed for content chat');\n }\n const apiKey = input.aiConfig.apiKey || getEnvApiKey(provider, input.env);\n\n return {\n clientOptions: {\n ...input.aiConfig,\n provider,\n apiKey,\n model,\n },\n model,\n provider,\n temperature: storedSelection.temperature ?? 0.7,\n maxTokens: storedSelection.maxTokens ?? 2000,\n };\n}\n\nfunction sanitizeReferenceText(value: unknown, maxLength: number): string {\n const text = stripHtml(sanitizeHtml(String(value ?? '')))\n .replace(/<<<(?:END_)?SMRT_[^>]*>>>/g, '')\n .replace(/<{2,}/g, '< <')\n .replace(/>{2,}/g, '> >')\n .replace(/\\s+/g, ' ')\n .trim();\n\n return text.length > maxLength ? `${text.slice(0, maxLength)}...` : text;\n}\n\nfunction sanitizeReferenceId(value: string): string {\n return value.replace(/[^\\w:.-]/g, '_').slice(0, 128);\n}\n\nfunction getReferenceTenantId(value: unknown): string | null {\n const candidate = value as {\n tenantId?: unknown;\n tenant_id?: unknown;\n } | null;\n return (\n asNonEmptyString(candidate?.tenantId) ??\n asNonEmptyString(candidate?.tenant_id)\n );\n}\n\nfunction referenceBelongsToTenant(\n ref: unknown,\n tenantScope: string | null,\n): boolean {\n const refTenantId = getReferenceTenantId(ref);\n if (tenantScope === null) {\n return !refTenantId;\n }\n return refTenantId === tenantScope;\n}\n\nasync function buildReferenceContext(\n contents: ContentChatCollectionLike,\n tenantScope: string | null,\n referenceIds: unknown,\n): Promise<string> {\n if (!Array.isArray(referenceIds) || referenceIds.length === 0) {\n return '';\n }\n\n const refTexts: string[] = [];\n const ids = [\n ...new Set(\n referenceIds\n .map(asNonEmptyString)\n .filter((id): id is string => Boolean(id)),\n ),\n ].slice(0, MAX_REFERENCE_IDS);\n for (const id of ids) {\n // Tenant-bound lookup (S5 #1392): bind tenantId into the query rather than\n // a cross-tenant get(id) + post-filter. The post-filter below stays as\n // defense-in-depth.\n const ref = (await getContentForTenant(contents, tenantScope, id)) as {\n title?: string;\n body?: string;\n tenantId?: string;\n tenant_id?: string;\n } | null;\n if (ref && referenceBelongsToTenant(ref, tenantScope)) {\n const safeTitle = sanitizeReferenceText(\n ref.title,\n REFERENCE_TITLE_MAX_LENGTH,\n );\n const safeBody = sanitizeReferenceText(\n ref.body,\n REFERENCE_BODY_MAX_LENGTH,\n );\n refTexts.push(\n `<<<SMRT_REFERENCE id=${sanitizeReferenceId(id)}>>>\\nTitle: ${safeTitle}\\nBody: ${safeBody}\\n<<<END_SMRT_REFERENCE>>>`,\n );\n }\n }\n\n return refTexts.length > 0\n ? `\\n\\nATTACHED REFERENCE MATERIALS:\\n${refTexts.join('\\n\\n')}\\n`\n : '';\n}\n\nexport async function sendContentEditorChatThreadMessage(\n input: SendContentChatThreadMessageInput,\n) {\n const tenantScope = resolveTenantScope(input.tenantId);\n const tenantId = resolveChatTenantId(input.tenantId);\n const profileId = resolveProfileId(input.profileId);\n const chatService = await ChatService.create({\n tenantId,\n db: input.contents.db,\n });\n await assertContentExistsForTenant(\n input.contents,\n tenantScope,\n input.contentId,\n );\n\n // Tenant-bound session + thread lookups via the facade (S5 #1392): the raw\n // `agentSessions.get(id)` / `threads.get(id)` reach-ins were tenant-UNBOUND\n // and could select cross-tenant chat state before the authorization below.\n const session = await chatService.getAgentSession({\n agentSessionId: input.sessionId,\n tenantId,\n });\n if (\n !contentChatSessionIsAuthorized(session, {\n profileId,\n contentId: input.contentId,\n })\n ) {\n throw new Error('Active session not found');\n }\n\n const thread = await chatService.getThread({\n threadId: input.threadId,\n tenantId,\n });\n if (\n !thread ||\n (thread as { roomId?: string }).roomId !==\n (session as { chatRoomId?: string | null }).chatRoomId\n ) {\n throw new Error('Thread not found');\n }\n\n const chatRoomId = (session as { chatRoomId?: string | null }).chatRoomId;\n if (!chatRoomId) {\n throw new Error('Active session is missing a chat room');\n }\n\n const references = await buildReferenceContext(\n input.contents,\n tenantScope,\n input.referenceIds,\n );\n const interactionPrompt = await (input.resolvePromptFn ?? resolvePrompt)(\n contentEditorInteractionPrompt.key,\n {\n db: input.contents.db,\n tenantId,\n variables: buildContentEditorInteractionVariables({\n fields: input.formFields,\n currentEditorState: input.currentEditorState,\n references,\n }),\n },\n );\n\n const sessionContext = getSessionContext(session);\n const aiConfig = input.aiConfig ?? {};\n const resolvedAI =\n (await input.resolveAI?.({\n aiConfig,\n env: input.env ?? defaultEnv(),\n sessionContext,\n requestedModel: input.model,\n interactionPrompt,\n })) ??\n resolveDefaultContentChatAI({\n aiConfig,\n env: input.env ?? defaultEnv(),\n sessionContext,\n requestedModel: input.model,\n interactionPrompt,\n });\n\n const userMessage = await chatService.sendMessage({\n tenantId,\n roomId: chatRoomId,\n threadId: (thread as { id: string }).id,\n actorProfileId: profileId,\n content: input.content,\n agentSessionId: (session as { id: string }).id,\n });\n\n // Membership- + tenant-gated thread history via the facade (S5 #1392); the\n // editor owns the room. Returned chronological (oldest-first) by the facade.\n const history = await chatService.getThreadMessages({\n threadId: (thread as { id: string }).id,\n actorProfileId: profileId,\n tenantId,\n limit: 10,\n });\n\n const conversation = history.map((message: unknown) => {\n const json = contentChatMessageToJSON(message);\n return {\n role: json.role as 'user' | 'assistant' | 'system',\n content: String(json.content ?? ''),\n };\n });\n\n const ai = await (input.getAIClient ?? getAI)(resolvedAI.clientOptions);\n\n const fullSystemPrompt =\n typeof (session as { systemPrompt?: unknown }).systemPrompt === 'string'\n ? (session as { systemPrompt: string }).systemPrompt\n : '';\n conversation.unshift({\n role: 'system',\n content: `${fullSystemPrompt}\\n\\n${interactionPrompt.text}`,\n });\n\n const response = await ai.chat(conversation, {\n model: resolvedAI.model,\n temperature: resolvedAI.temperature ?? 0.7,\n maxTokens: resolvedAI.maxTokens ?? 2000,\n });\n\n // Author the assistant reply AS the session's agent via the trusted internal\n // agent-runtime surface — never via the public sendMessage (which would force\n // the message to the caller's identity with role 'user') (S5 #1392).\n const agentMessage = await sendAgentReply(chatService, {\n tenantId,\n agentSessionId: (session as { id: string }).id,\n threadId: (thread as { id: string }).id,\n content: response.content,\n kind: 'assistant',\n });\n\n const updates = buildContentChatModelUpdates(\n sessionContext,\n input.model,\n resolvedAI.model,\n );\n updates.model = resolvedAI.model;\n if (resolvedAI.provider !== undefined) {\n updates.provider = resolvedAI.provider;\n }\n if (resolvedAI.profile !== undefined) {\n updates.profile = resolvedAI.profile;\n }\n if (\n Object.entries(updates).some(\n ([key, value]) => sessionContext[key] !== value,\n )\n ) {\n await (\n session as { updateSessionContext: (value: unknown) => Promise<void> }\n ).updateSessionContext(updates);\n }\n\n return {\n chatService,\n session,\n thread,\n userMessage,\n agentMessage,\n };\n}\n","import type { DatabaseInterface } from '@happyvertical/sql';\n\nexport type ContentContributionChannel = 'web' | 'email';\n\nexport type ContentContributionStatus =\n | 'submitted'\n | 'quarantined'\n | 'needs_changes'\n | 'approved'\n | 'promoted'\n | 'rejected'\n | 'withdrawn';\n\nexport type ContentContributionIntakeDecision =\n | 'accepted'\n | 'quarantined'\n | 'rejected';\n\nexport type ContentContributorTrustLevel = 'standard' | 'trusted' | 'blocked';\n\nexport interface ContentContributionIntakeRules {\n maxFiles?: number | null;\n maxTotalBytes?: number | null;\n allowedMimePatterns?: string[];\n blockedMimePatterns?: string[];\n quarantineMimePatterns?: string[];\n blockedTextPatterns?: string[];\n quarantineTextPatterns?: string[];\n trustedOnly?: boolean;\n}\n\nexport interface ContentContributionPromotionMapping {\n targetContentType?: string | null;\n targetContentVariant?: string | null;\n targetContentStatus?: 'draft' | 'review';\n autoPromoteTrusted?: boolean;\n createAssets?: boolean;\n assetRelationship?: string;\n}\n\nexport interface ContentContributionTypeDefinition {\n key: string;\n label: string;\n enabled?: boolean;\n allowedChannels?: ContentContributionChannel[];\n allowText?: boolean;\n allowFiles?: boolean;\n allowEmptyText?: boolean;\n intakeRules?: ContentContributionIntakeRules;\n promotion?: ContentContributionPromotionMapping;\n metadata?: Record<string, any>;\n}\n\nexport interface PersistedContentContributionTypeRecord\n extends ContentContributionTypeDefinition {\n id?: string;\n tenantId?: string | null;\n createdAt?: string | null;\n updatedAt?: string | null;\n}\n\nexport interface ContentContributionConfig {\n types: ContentContributionTypeDefinition[];\n}\n\nexport interface ResolvedContentContributionType\n extends ContentContributionTypeDefinition {}\n\nexport interface ContentContributionTypeConfigState {\n effective: ContentContributionTypeDefinition[];\n persisted: PersistedContentContributionTypeRecord[];\n}\n\nexport interface EvaluateContributionIntakeOptions {\n contributionType: ContentContributionTypeDefinition;\n trustLevel?: ContentContributorTrustLevel;\n channel: ContentContributionChannel;\n title?: string | null;\n description?: string | null;\n body?: string | null;\n attachments?: Array<{\n mimeType?: string | null;\n size?: number | null;\n }>;\n}\n\nexport interface EvaluateContributionIntakeResult {\n decision: ContentContributionIntakeDecision;\n reasons: string[];\n}\n\nconst DEFAULT_CONTENT_CONTRIBUTION_CONFIG: ContentContributionConfig = {\n types: [],\n};\n\nlet contributionConfig = cloneContributionConfig(\n DEFAULT_CONTENT_CONTRIBUTION_CONFIG,\n);\n\nfunction cloneJSONArray<T>(items: T[] | null | undefined): T[] {\n return Array.isArray(items) ? items.map((item) => structuredClone(item)) : [];\n}\n\nfunction safeParseJSONObject(raw: unknown): Record<string, any> {\n if (!raw) {\n return {};\n }\n\n if (typeof raw === 'object') {\n return { ...(raw as Record<string, any>) };\n }\n\n if (typeof raw !== 'string') {\n return {};\n }\n\n try {\n const parsed = JSON.parse(raw);\n return parsed && typeof parsed === 'object' ? parsed : {};\n } catch {\n return {};\n }\n}\n\nfunction safeParseJSONArray<T>(raw: unknown): T[] {\n if (!raw) {\n return [];\n }\n\n if (Array.isArray(raw)) {\n return raw.map((item) => structuredClone(item)) as T[];\n }\n\n if (typeof raw !== 'string') {\n return [];\n }\n\n try {\n const parsed = JSON.parse(raw);\n return Array.isArray(parsed) ? (parsed as T[]) : [];\n } catch {\n return [];\n }\n}\n\nfunction cloneIntakeRules(\n rules: ContentContributionIntakeRules | null | undefined,\n): ContentContributionIntakeRules {\n return {\n maxFiles:\n typeof rules?.maxFiles === 'number' ? Math.max(0, rules.maxFiles) : null,\n maxTotalBytes:\n typeof rules?.maxTotalBytes === 'number'\n ? Math.max(0, rules.maxTotalBytes)\n : null,\n allowedMimePatterns: cloneJSONArray(rules?.allowedMimePatterns),\n blockedMimePatterns: cloneJSONArray(rules?.blockedMimePatterns),\n quarantineMimePatterns: cloneJSONArray(rules?.quarantineMimePatterns),\n blockedTextPatterns: cloneJSONArray(rules?.blockedTextPatterns),\n quarantineTextPatterns: cloneJSONArray(rules?.quarantineTextPatterns),\n trustedOnly: rules?.trustedOnly === true,\n };\n}\n\nfunction clonePromotionMapping(\n promotion: ContentContributionPromotionMapping | null | undefined,\n): ContentContributionPromotionMapping {\n return {\n targetContentType: promotion?.targetContentType || null,\n targetContentVariant: promotion?.targetContentVariant || null,\n targetContentStatus:\n promotion?.targetContentStatus === 'review' ? 'review' : 'draft',\n autoPromoteTrusted: promotion?.autoPromoteTrusted === true,\n createAssets: promotion?.createAssets !== false,\n assetRelationship: promotion?.assetRelationship || 'attachment',\n };\n}\n\nfunction cloneTypeDefinition(\n type: ContentContributionTypeDefinition,\n): ContentContributionTypeDefinition {\n return {\n key: type.key,\n label: type.label,\n enabled: type.enabled !== false,\n allowedChannels:\n type.allowedChannels && type.allowedChannels.length > 0\n ? [...type.allowedChannels]\n : ['web'],\n allowText: type.allowText !== false,\n allowFiles: type.allowFiles === true,\n allowEmptyText: type.allowEmptyText === true,\n intakeRules: cloneIntakeRules(type.intakeRules),\n promotion: clonePromotionMapping(type.promotion),\n metadata: safeParseJSONObject(type.metadata),\n };\n}\n\nfunction clonePersistedTypeRecord(\n type: PersistedContentContributionTypeRecord,\n): PersistedContentContributionTypeRecord {\n return {\n ...cloneTypeDefinition(type),\n id: type.id,\n tenantId: type.tenantId ?? null,\n createdAt: type.createdAt ?? null,\n updatedAt: type.updatedAt ?? null,\n };\n}\n\nfunction cloneContributionConfig(\n config: ContentContributionConfig,\n): ContentContributionConfig {\n return {\n types: config.types.map(cloneTypeDefinition),\n };\n}\n\nfunction mergeByKey<T extends { key: string }>(\n baseItems: T[],\n overrides: T[],\n normalize: (item: T) => T,\n): T[] {\n const merged = new Map<string, T>();\n\n for (const item of baseItems.map(normalize)) {\n merged.set(item.key, item);\n }\n\n for (const item of overrides.map(normalize)) {\n merged.set(item.key, item);\n }\n\n return [...merged.values()];\n}\n\nfunction isMissingContributionTypesTableError(error: unknown): boolean {\n const message = String(\n (error as Error)?.message || error || '',\n ).toLowerCase();\n return (\n message.includes('content_contribution_types') &&\n (message.includes('no such table') ||\n message.includes('does not exist') ||\n message.includes('relation'))\n );\n}\n\nfunction mapPersistedTypeRow(\n row: Record<string, any>,\n): PersistedContentContributionTypeRecord {\n return {\n id: row.id || null,\n key: String(row.key || ''),\n label: String(row.label || row.key || ''),\n enabled: row.enabled !== false && row.enabled !== 0,\n allowedChannels: safeParseJSONArray<ContentContributionChannel>(\n row.allowedChannels || row.allowed_channels,\n ),\n allowText:\n row.allowText === undefined && row.allow_text === undefined\n ? true\n : row.allowText !== false && row.allow_text !== 0,\n allowFiles:\n row.allowFiles === true ||\n row.allow_files === true ||\n row.allow_files === 1,\n allowEmptyText:\n row.allowEmptyText === true ||\n row.allow_empty_text === true ||\n row.allow_empty_text === 1,\n intakeRules: safeParseJSONObject(row.intakeRules || row.intake_rules),\n promotion: safeParseJSONObject(row.promotion || row.promotion_mapping),\n metadata: safeParseJSONObject(row.metadata),\n tenantId: row.tenantId ?? row.tenant_id ?? null,\n createdAt: row.createdAt || row.created_at || null,\n updatedAt: row.updatedAt || row.updated_at || null,\n };\n}\n\nexport function getContentContributionConfig(): ContentContributionConfig {\n return cloneContributionConfig(contributionConfig);\n}\n\nexport function configureContentContributions(\n config: Partial<ContentContributionConfig>,\n): ContentContributionConfig {\n contributionConfig = {\n types: config.types\n ? mergeByKey(contributionConfig.types, config.types, cloneTypeDefinition)\n : contributionConfig.types.map(cloneTypeDefinition),\n };\n\n return getContentContributionConfig();\n}\n\nexport function resetContentContributionConfig(): ContentContributionConfig {\n contributionConfig = cloneContributionConfig(\n DEFAULT_CONTENT_CONTRIBUTION_CONFIG,\n );\n return getContentContributionConfig();\n}\n\nexport function hasStaticContentContributionType(key: string): boolean {\n return contributionConfig.types.some((type) => type.key === key);\n}\n\nexport async function loadPersistedContentContributionTypes(\n options: { db?: DatabaseInterface | null } = {},\n): Promise<PersistedContentContributionTypeRecord[]> {\n if (!options.db) {\n return [];\n }\n\n try {\n const rows = await options.db.list('content_contribution_types', {});\n rows.sort((a: any, b: any) =>\n String(a.created_at || a.createdAt || '').localeCompare(\n String(b.created_at || b.createdAt || ''),\n ),\n );\n return rows.map((row: any) => mapPersistedTypeRow(row));\n } catch (error) {\n if (isMissingContributionTypesTableError(error)) {\n return [];\n }\n\n throw error;\n }\n}\n\nexport async function getEffectiveContentContributionConfig(\n options: { db?: DatabaseInterface | null } = {},\n): Promise<ContentContributionConfig> {\n const persisted = await loadPersistedContentContributionTypes({\n db: options.db,\n });\n\n return {\n types: mergeByKey(\n contributionConfig.types,\n persisted,\n cloneTypeDefinition as (\n item: ContentContributionTypeDefinition,\n ) => ContentContributionTypeDefinition,\n ),\n };\n}\n\nexport async function getContentContributionTypeConfigState(\n options: { db?: DatabaseInterface | null } = {},\n): Promise<ContentContributionTypeConfigState> {\n const [effective, persisted] = await Promise.all([\n getEffectiveContentContributionConfig(options),\n loadPersistedContentContributionTypes(options),\n ]);\n\n return {\n effective: effective.types,\n persisted: persisted.map(clonePersistedTypeRecord),\n };\n}\n\nexport async function resolveEffectiveContentContributionType(\n key: string,\n options: { db?: DatabaseInterface | null } = {},\n): Promise<ResolvedContentContributionType | null> {\n const effective = await getEffectiveContentContributionConfig(options);\n const type = effective.types.find((entry) => entry.key === key);\n return type ? cloneTypeDefinition(type) : null;\n}\n\nfunction matchesMimePattern(mimeType: string, pattern: string): boolean {\n if (!pattern) {\n return false;\n }\n\n if (pattern.endsWith('/*')) {\n return mimeType.startsWith(pattern.slice(0, -1));\n }\n\n return mimeType === pattern;\n}\n\nfunction matchesAnyMimePattern(mimeType: string, patterns: string[]): boolean {\n return patterns.some((pattern) => matchesMimePattern(mimeType, pattern));\n}\n\nfunction containsPattern(text: string, patterns: string[]): boolean {\n const lowerText = text.toLowerCase();\n return patterns.some((pattern) => lowerText.includes(pattern.toLowerCase()));\n}\n\nexport function evaluateContributionIntake(\n options: EvaluateContributionIntakeOptions,\n): EvaluateContributionIntakeResult {\n const type = cloneTypeDefinition(options.contributionType);\n const rules = cloneIntakeRules(type.intakeRules);\n const trustLevel = options.trustLevel || 'standard';\n const attachments = options.attachments || [];\n const text = [options.title, options.description, options.body]\n .filter(Boolean)\n .join('\\n')\n .trim();\n const hasText = text.length > 0;\n const hasFiles = attachments.length > 0;\n const totalBytes = attachments.reduce(\n (sum, attachment) => sum + Math.max(0, attachment.size || 0),\n 0,\n );\n const reasons: string[] = [];\n\n if (type.enabled === false) {\n return {\n decision: 'rejected',\n reasons: ['This contribution type is currently disabled.'],\n };\n }\n\n if (\n Array.isArray(type.allowedChannels) &&\n type.allowedChannels.length > 0 &&\n !type.allowedChannels.includes(options.channel)\n ) {\n return {\n decision: 'rejected',\n reasons: [\n `${options.channel} submissions are not allowed for this type.`,\n ],\n };\n }\n\n if (trustLevel === 'blocked') {\n return {\n decision: 'rejected',\n reasons: ['This contributor is blocked from submitting new material.'],\n };\n }\n\n if (rules.trustedOnly && trustLevel !== 'trusted') {\n return {\n decision: 'rejected',\n reasons: ['This contribution type is limited to trusted contributors.'],\n };\n }\n\n if (type.allowText === false && hasText) {\n return {\n decision: 'rejected',\n reasons: ['This contribution type does not accept text submissions.'],\n };\n }\n\n if (type.allowFiles !== true && hasFiles) {\n return {\n decision: 'rejected',\n reasons: ['This contribution type does not accept file attachments.'],\n };\n }\n\n if (\n type.allowText === true &&\n type.allowEmptyText !== true &&\n !hasText &&\n !hasFiles\n ) {\n return {\n decision: 'rejected',\n reasons: ['A text body or at least one attachment is required.'],\n };\n }\n\n if (\n typeof rules.maxFiles === 'number' &&\n attachments.length > rules.maxFiles\n ) {\n return {\n decision: 'rejected',\n reasons: [\n `This contribution type accepts at most ${rules.maxFiles} files.`,\n ],\n };\n }\n\n if (\n typeof rules.maxTotalBytes === 'number' &&\n totalBytes > rules.maxTotalBytes\n ) {\n return {\n decision: 'rejected',\n reasons: [\n 'The attached files exceed the size limit for this contribution type.',\n ],\n };\n }\n\n const mimeTypes = attachments\n .map((attachment) => attachment.mimeType || '')\n .filter(Boolean);\n\n if (\n rules.allowedMimePatterns &&\n rules.allowedMimePatterns.length > 0 &&\n mimeTypes.some(\n (mimeType) =>\n !matchesAnyMimePattern(mimeType, rules.allowedMimePatterns || []),\n )\n ) {\n return {\n decision: 'rejected',\n reasons: ['One or more attachments use a file type that is not allowed.'],\n };\n }\n\n if (\n mimeTypes.some((mimeType) =>\n matchesAnyMimePattern(mimeType, rules.blockedMimePatterns || []),\n )\n ) {\n return {\n decision: 'rejected',\n reasons: ['One or more attachments match blocked file-type rules.'],\n };\n }\n\n if (containsPattern(text, rules.blockedTextPatterns || [])) {\n return {\n decision: 'rejected',\n reasons: ['The submission body matches blocked intake rules.'],\n };\n }\n\n if (\n mimeTypes.some((mimeType) =>\n matchesAnyMimePattern(mimeType, rules.quarantineMimePatterns || []),\n )\n ) {\n reasons.push('One or more attachments triggered quarantine file rules.');\n }\n\n if (containsPattern(text, rules.quarantineTextPatterns || [])) {\n reasons.push('The submission body triggered quarantine text rules.');\n }\n\n if (reasons.length > 0) {\n return {\n decision: 'quarantined',\n reasons,\n };\n }\n\n return {\n decision: 'accepted',\n reasons: [],\n };\n}\n","import {\n AssetCollection,\n AssetStatusCollection,\n AssetTypeCollection,\n} from '@happyvertical/smrt-assets';\nimport type { SmrtObjectOptions } from '@happyvertical/smrt-core';\nimport {\n crossPackageRef,\n field,\n foreignKey,\n SmrtObject,\n smrt,\n} from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport type { ContentContributionAttachment } from './content-contribution-attachment';\nimport {\n type ContentContributionChannel,\n type ContentContributionIntakeDecision,\n type ContentContributionStatus,\n type ContentContributionTypeDefinition,\n resolveEffectiveContentContributionType,\n} from './content-contribution-config';\nimport type { ContentContributionRevision } from './content-contribution-revision';\nimport type { ContentContributor } from './content-contributor';\n\nexport interface ContentContributionAttachmentInput {\n filename: string;\n mimeType?: string | null;\n size?: number | null;\n fileKey?: string | null;\n sourceUri?: string | null;\n metadata?: Record<string, any>;\n}\n\nexport interface AppendContentContributionRevisionOptions {\n title?: string | null;\n description?: string | null;\n body?: string | null;\n channel?: ContentContributionChannel;\n sourceMessageId?: string | null;\n sourceThreadKey?: string | null;\n attachments?: ContentContributionAttachmentInput[];\n metadata?: Record<string, any>;\n}\n\nexport interface ApproveContentContributionOptions {\n editorNote?: string | null;\n promote?: boolean;\n targetStatus?: 'draft' | 'review';\n}\n\nexport interface RejectContentContributionOptions {\n editorNote?: string | null;\n}\n\nexport interface RequestChangesContentContributionOptions {\n editorNote?: string | null;\n}\n\nexport interface WithdrawContentContributionOptions {\n reason?: string | null;\n}\n\nexport interface PromoteContentContributionOptions {\n editorNote?: string | null;\n targetStatus?: 'draft' | 'review';\n}\n\nexport interface ContentContributionOptions extends SmrtObjectOptions {\n contributorId?: string;\n contributionTypeKey?: string;\n status?: ContentContributionStatus;\n intakeDecision?: ContentContributionIntakeDecision;\n channel?: ContentContributionChannel;\n title?: string | null;\n description?: string | null;\n body?: string | null;\n contributorEmail?: string | null;\n contributorName?: string | null;\n threadKey?: string | null;\n sourceMessageId?: string | null;\n editorNotes?: string | null;\n promotedContentId?: string | null;\n revisionCount?: number;\n approvedAt?: Date | null;\n promotedAt?: Date | null;\n rejectedAt?: Date | null;\n withdrawnAt?: Date | null;\n requestedChangesAt?: Date | null;\n metadata?: Record<string, any> | string;\n tenantId?: string | null;\n createdAt?: Date;\n updatedAt?: Date;\n}\n\nfunction parseMetadata(raw: unknown): Record<string, any> {\n if (!raw) {\n return {};\n }\n\n if (typeof raw === 'object') {\n return { ...(raw as Record<string, any>) };\n }\n\n if (typeof raw !== 'string') {\n return {};\n }\n\n try {\n const parsed = JSON.parse(raw);\n return parsed && typeof parsed === 'object'\n ? (parsed as Record<string, any>)\n : {};\n } catch {\n return {};\n }\n}\n\nfunction inferAssetTypeSlug(mimeType: string): string {\n if (mimeType.startsWith('image/')) {\n return 'image';\n }\n if (mimeType.startsWith('video/')) {\n return 'video';\n }\n if (mimeType.startsWith('audio/')) {\n return 'audio';\n }\n return 'document';\n}\n\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableName: 'content_contributions',\n conflictColumns: ['id'],\n api: {\n include: [\n 'list',\n 'get',\n 'create',\n 'update',\n 'delete',\n 'appendRevisionAction',\n 'requestChangesAction',\n 'approveAction',\n 'rejectAction',\n 'withdrawAction',\n 'promoteAction',\n ],\n routes: {\n appendRevisionAction: { method: 'POST', path: 'revisions' },\n requestChangesAction: { method: 'POST', path: 'request-changes' },\n approveAction: { method: 'POST', path: 'approve' },\n rejectAction: { method: 'POST', path: 'reject' },\n withdrawAction: { method: 'POST', path: 'withdraw' },\n promoteAction: { method: 'POST', path: 'promote' },\n },\n },\n mcp: { include: ['list', 'get', 'create', 'update'] },\n cli: true,\n})\nexport class ContentContribution extends SmrtObject {\n @foreignKey('ContentContributor', { required: true })\n contributorId = '';\n\n @field({ required: true })\n contributionTypeKey = '';\n\n status: ContentContributionStatus = 'submitted';\n intakeDecision: ContentContributionIntakeDecision = 'accepted';\n channel: ContentContributionChannel = 'web';\n title = '';\n description = '';\n body = '';\n contributorEmail = '';\n contributorName = '';\n threadKey = '';\n\n @crossPackageRef('@happyvertical/smrt-messages:Message')\n sourceMessageId = '';\n\n editorNotes = '';\n\n @foreignKey('Content')\n promotedContentId = '';\n revisionCount = 0;\n approvedAt: Date | null = null;\n promotedAt: Date | null = null;\n rejectedAt: Date | null = null;\n withdrawnAt: Date | null = null;\n requestedChangesAt: Date | null = null;\n metadata = '';\n\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n createdAt = new Date();\n updatedAt = new Date();\n\n constructor(options: ContentContributionOptions = {}) {\n super(options);\n if (options.contributorId !== undefined)\n this.contributorId = options.contributorId;\n if (options.contributionTypeKey !== undefined)\n this.contributionTypeKey = options.contributionTypeKey;\n if (options.status !== undefined) this.status = options.status;\n if (options.intakeDecision !== undefined)\n this.intakeDecision = options.intakeDecision;\n if (options.channel !== undefined) this.channel = options.channel;\n if (options.title !== undefined) this.title = options.title || '';\n if (options.description !== undefined)\n this.description = options.description || '';\n if (options.body !== undefined) this.body = options.body || '';\n if (options.contributorEmail !== undefined)\n this.contributorEmail = options.contributorEmail || '';\n if (options.contributorName !== undefined)\n this.contributorName = options.contributorName || '';\n if (options.threadKey !== undefined)\n this.threadKey = options.threadKey || '';\n if (options.sourceMessageId !== undefined)\n this.sourceMessageId = options.sourceMessageId || '';\n if (options.editorNotes !== undefined)\n this.editorNotes = options.editorNotes || '';\n if (options.promotedContentId !== undefined)\n this.promotedContentId = options.promotedContentId || '';\n if (options.revisionCount !== undefined)\n this.revisionCount = options.revisionCount;\n if (options.approvedAt !== undefined) this.approvedAt = options.approvedAt;\n if (options.promotedAt !== undefined) this.promotedAt = options.promotedAt;\n if (options.rejectedAt !== undefined) this.rejectedAt = options.rejectedAt;\n if (options.withdrawnAt !== undefined)\n this.withdrawnAt = options.withdrawnAt;\n if (options.requestedChangesAt !== undefined)\n this.requestedChangesAt = options.requestedChangesAt;\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n if (options.createdAt) this.createdAt = options.createdAt;\n if (options.updatedAt) this.updatedAt = options.updatedAt;\n if (options.metadata !== undefined) {\n this.metadata =\n typeof options.metadata === 'string'\n ? options.metadata\n : JSON.stringify(options.metadata);\n }\n }\n\n getMetadata(): Record<string, any> {\n return parseMetadata(this.metadata);\n }\n\n setMetadata(metadata: Record<string, any>): void {\n this.metadata = JSON.stringify(metadata || {});\n }\n\n protected override transformJSON(json: Record<string, any>) {\n return {\n ...json,\n description: this.description || null,\n body: this.body || null,\n contributorEmail: this.contributorEmail || null,\n contributorName: this.contributorName || null,\n threadKey: this.threadKey || null,\n sourceMessageId: this.sourceMessageId || null,\n editorNotes: this.editorNotes || null,\n promotedContentId: this.promotedContentId || null,\n metadata: this.getMetadata(),\n };\n }\n\n private async getRevisionCollection() {\n const { ContentContributionRevisionCollection } = await import(\n './content-contribution-revisions'\n );\n return ContentContributionRevisionCollection.create(this.options);\n }\n\n private async getAttachmentCollection() {\n const { ContentContributionAttachmentCollection } = await import(\n './content-contribution-attachments'\n );\n return ContentContributionAttachmentCollection.create(this.options);\n }\n\n private async getContributorCollection() {\n const { ContentContributorCollection } = await import(\n './content-contributors'\n );\n return ContentContributorCollection.create(this.options);\n }\n\n private async getContentsCollection() {\n const { Contents } = await import('./contents');\n return Contents.create({ db: this.db });\n }\n\n private async getAssetCollection() {\n return AssetCollection.create(this.options);\n }\n\n private async getAssetStatusCollection() {\n return AssetStatusCollection.create(this.options);\n }\n\n private async getAssetTypeCollection() {\n return AssetTypeCollection.create(this.options);\n }\n\n async getContributor(): Promise<ContentContributor | null> {\n if (!this.contributorId) {\n return null;\n }\n\n const contributors = await this.getContributorCollection();\n return contributors.get({ id: this.contributorId });\n }\n\n async getRevisions(): Promise<ContentContributionRevision[]> {\n if (!this.id) {\n return [];\n }\n\n const revisions = await this.getRevisionCollection();\n return revisions.listForContribution(this.id);\n }\n\n async getLatestRevision(): Promise<ContentContributionRevision | null> {\n if (!this.id) {\n return null;\n }\n\n const revisions = await this.getRevisionCollection();\n return revisions.getLatestForContribution(this.id);\n }\n\n async getAttachments(): Promise<ContentContributionAttachment[]> {\n if (!this.id) {\n return [];\n }\n\n const attachments = await this.getAttachmentCollection();\n return attachments.listForContribution(this.id);\n }\n\n async resolveContributionType(): Promise<ContentContributionTypeDefinition | null> {\n return resolveEffectiveContentContributionType(this.contributionTypeKey, {\n db: this.db,\n });\n }\n\n private ensureEditable(): void {\n if (\n this.revisionCount > 0 &&\n ['rejected', 'withdrawn', 'promoted'].includes(this.status)\n ) {\n throw new Error(\n `Contribution \"${this.id || 'new'}\" cannot be edited once it is ${this.status}.`,\n );\n }\n }\n\n private async createRevision(\n options: AppendContentContributionRevisionOptions,\n ): Promise<ContentContributionRevision> {\n if (!this.id) {\n throw new Error('Contribution must be saved before creating revisions.');\n }\n\n const revisions = await this.getRevisionCollection();\n const nextRevisionNumber = Math.max(1, this.revisionCount + 1);\n const revision = await revisions.create({\n contributionId: this.id,\n revisionNumber: nextRevisionNumber,\n channel: options.channel || this.channel,\n title: options.title ?? this.title,\n description: options.description ?? this.description,\n body: options.body ?? this.body,\n sourceMessageId: options.sourceMessageId || '',\n sourceThreadKey: options.sourceThreadKey || this.threadKey || '',\n metadata: JSON.stringify(options.metadata || {}),\n tenantId: this.tenantId,\n });\n\n return revision;\n }\n\n private async createHeldAttachments(\n revisionId: string | null,\n attachments: ContentContributionAttachmentInput[],\n channel: ContentContributionChannel,\n ): Promise<ContentContributionAttachment[]> {\n if (!this.id || attachments.length === 0) {\n return [];\n }\n\n const records = await this.getAttachmentCollection();\n const created: ContentContributionAttachment[] = [];\n for (const attachment of attachments) {\n const item = await records.create({\n contributionId: this.id,\n revisionId: revisionId || '',\n filename: attachment.filename,\n mimeType: attachment.mimeType || 'application/octet-stream',\n size: Math.max(0, attachment.size || 0),\n fileKey: attachment.fileKey || '',\n sourceUri: attachment.sourceUri || '',\n channel,\n tenantId: this.tenantId,\n metadata: JSON.stringify(attachment.metadata || {}),\n });\n created.push(item);\n }\n\n return created;\n }\n\n async appendRevisionAction(\n options: AppendContentContributionRevisionOptions = {},\n ) {\n this.ensureEditable();\n\n const revision = await this.createRevision(options);\n await this.createHeldAttachments(\n revision.id || null,\n options.attachments || [],\n options.channel || this.channel,\n );\n\n this.title = options.title ?? this.title;\n this.description = options.description ?? this.description;\n this.body = options.body ?? this.body;\n this.channel = options.channel || this.channel;\n this.sourceMessageId = options.sourceMessageId || this.sourceMessageId;\n this.threadKey = options.sourceThreadKey || this.threadKey;\n this.revisionCount = revision.revisionNumber;\n\n if (this.status === 'needs_changes') {\n this.status = 'submitted';\n this.requestedChangesAt = null;\n }\n\n const metadata = this.getMetadata();\n metadata.lastRevisionId = revision.id || null;\n metadata.lastRevisionAt = revision.createdAt.toISOString();\n this.setMetadata(metadata);\n await this.save();\n\n return {\n contribution: this.toJSON(),\n revision: revision.toJSON(),\n attachments: (await this.getAttachments()).map((item) => item.toJSON()),\n };\n }\n\n async requestChangesAction(\n options: RequestChangesContentContributionOptions = {},\n ) {\n if (['rejected', 'withdrawn', 'promoted'].includes(this.status)) {\n throw new Error(\n `Contribution \"${this.id || 'new'}\" cannot request changes after ${this.status}.`,\n );\n }\n\n this.status = 'needs_changes';\n this.requestedChangesAt = new Date();\n this.editorNotes = options.editorNote || this.editorNotes;\n\n const metadata = this.getMetadata();\n const requestHistory = Array.isArray(metadata.requestChangesHistory)\n ? metadata.requestChangesHistory\n : [];\n requestHistory.push({\n note: options.editorNote || '',\n at: this.requestedChangesAt.toISOString(),\n });\n metadata.requestChangesHistory = requestHistory;\n this.setMetadata(metadata);\n\n await this.save();\n return this.toJSON();\n }\n\n async rejectAction(options: RejectContentContributionOptions = {}) {\n if (this.status === 'promoted') {\n throw new Error('Promoted contributions cannot be rejected.');\n }\n\n this.status = 'rejected';\n this.rejectedAt = new Date();\n this.editorNotes = options.editorNote || this.editorNotes;\n\n const metadata = this.getMetadata();\n metadata.rejection = {\n note: options.editorNote || '',\n at: this.rejectedAt.toISOString(),\n };\n this.setMetadata(metadata);\n\n await this.save();\n return this.toJSON();\n }\n\n async withdrawAction(options: WithdrawContentContributionOptions = {}) {\n if (this.status === 'promoted') {\n throw new Error('Promoted contributions cannot be withdrawn.');\n }\n\n this.status = 'withdrawn';\n this.withdrawnAt = new Date();\n\n const metadata = this.getMetadata();\n metadata.withdrawal = {\n reason: options.reason || '',\n at: this.withdrawnAt.toISOString(),\n };\n this.setMetadata(metadata);\n\n await this.save();\n return this.toJSON();\n }\n\n async approveAction(options: ApproveContentContributionOptions = {}) {\n if (['rejected', 'withdrawn', 'promoted'].includes(this.status)) {\n throw new Error(\n `Contribution \"${this.id || 'new'}\" cannot be approved after ${this.status}.`,\n );\n }\n\n this.status = 'approved';\n this.approvedAt = new Date();\n this.editorNotes = options.editorNote || this.editorNotes;\n await this.save();\n\n if (options.promote === false) {\n return {\n contribution: this.toJSON(),\n content: null,\n assets: [],\n };\n }\n\n return this.promoteAction({\n editorNote: options.editorNote,\n targetStatus: options.targetStatus,\n });\n }\n\n async promoteAction(options: PromoteContentContributionOptions = {}) {\n if (this.promotedContentId) {\n const contents = await this.getContentsCollection();\n const content = await contents.get({ id: this.promotedContentId });\n return {\n contribution: this.toJSON(),\n content: content ? content.toJSON() : null,\n assets: await this.getAttachments().then((items) =>\n items\n .filter((item) => item.promotedAssetId)\n .map((item) => ({\n attachmentId: item.id,\n assetId: item.promotedAssetId,\n })),\n ),\n };\n }\n\n const type = await this.resolveContributionType();\n if (!type) {\n throw new Error(\n `Contribution type \"${this.contributionTypeKey}\" is not configured.`,\n );\n }\n\n const promotion = type.promotion || {};\n if (!promotion.targetContentType) {\n throw new Error(\n `Contribution type \"${type.key}\" is missing promotion.targetContentType.`,\n );\n }\n\n const contributor = await this.getContributor();\n const latestRevision = await this.getLatestRevision();\n const attachments = await this.getAttachments();\n\n const contents = await this.getContentsCollection();\n const content = await contents.create({\n tenantId: this.tenantId,\n type: promotion.targetContentType,\n variant: promotion.targetContentVariant || null,\n source: 'contribution',\n status: options.targetStatus || promotion.targetContentStatus || 'draft',\n title: latestRevision?.title || this.title,\n description: latestRevision?.description || this.description || null,\n body: latestRevision?.body || this.body || '',\n author:\n contributor?.name ||\n this.contributorName ||\n this.contributorEmail ||\n null,\n name:\n latestRevision?.title ||\n this.title ||\n `${type.label || type.key} contribution`,\n metadata: {\n contribution: {\n contributionId: this.id || null,\n contributorId: this.contributorId || null,\n contributorEmail: this.contributorEmail || null,\n contributorName: this.contributorName || null,\n contributionTypeKey: this.contributionTypeKey,\n revisionCount: this.revisionCount,\n sourceMessageId: this.sourceMessageId || null,\n threadKey: this.threadKey || null,\n },\n },\n });\n await content.save();\n\n const promotedAssets: Array<{\n attachmentId: string | null;\n assetId: string | null;\n }> = [];\n\n if (promotion.createAssets !== false && attachments.length > 0) {\n const [assets, statuses, typesCollection] = await Promise.all([\n this.getAssetCollection(),\n this.getAssetStatusCollection(),\n this.getAssetTypeCollection(),\n ]);\n\n await Promise.all([\n statuses.initializeCommonStatuses(),\n typesCollection.initializeCommonTypes(),\n ]);\n\n for (const [index, attachment] of attachments.entries()) {\n const asset = await assets.create({\n tenantId: this.tenantId,\n ownerProfileId: contributor?.profileId || null,\n name: attachment.filename || `Contribution attachment ${index + 1}`,\n description: `Promoted from contribution ${this.id || ''}`.trim(),\n mimeType: attachment.mimeType || 'application/octet-stream',\n sourceUri:\n attachment.sourceUri ||\n attachment.fileKey ||\n `held://content-contribution/${attachment.id || index}`,\n typeSlug: inferAssetTypeSlug(attachment.mimeType || ''),\n statusSlug: 'draft',\n sourceType: 'content-contribution',\n externalId: attachment.id || '',\n });\n await asset.save();\n\n await content.addAsset(\n asset,\n promotion.assetRelationship || 'attachment',\n index,\n );\n\n attachment.promotedAssetId = asset.id || '';\n await attachment.save();\n promotedAssets.push({\n attachmentId: attachment.id || null,\n assetId: asset.id || null,\n });\n }\n }\n\n this.promotedContentId = content.id || '';\n this.promotedAt = new Date();\n this.status = 'promoted';\n this.editorNotes = options.editorNote || this.editorNotes;\n\n const metadata = this.getMetadata();\n metadata.promotion = {\n contentId: content.id || null,\n contentStatus: content.status || null,\n promotedAt: this.promotedAt.toISOString(),\n assetIds: promotedAssets.map((item) => item.assetId).filter(Boolean),\n };\n this.setMetadata(metadata);\n await this.save();\n\n return {\n contribution: this.toJSON(),\n content: content.toJSON(),\n assets: promotedAssets,\n };\n }\n}\n","import type { SmrtObjectOptions } from '@happyvertical/smrt-core';\nimport {\n crossPackageRef,\n foreignKey,\n SmrtObject,\n smrt,\n} from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport type { ContentContributionChannel } from './content-contribution-config';\n\nexport interface ContentContributionAttachmentOptions\n extends SmrtObjectOptions {\n contributionId?: string;\n revisionId?: string | null;\n filename?: string;\n mimeType?: string;\n size?: number;\n fileKey?: string | null;\n sourceUri?: string | null;\n channel?: ContentContributionChannel;\n promotedAssetId?: string | null;\n metadata?: Record<string, any> | string;\n tenantId?: string | null;\n createdAt?: Date;\n updatedAt?: Date;\n}\n\nfunction parseMetadata(raw: unknown): Record<string, any> {\n if (!raw) {\n return {};\n }\n\n if (typeof raw === 'object') {\n return { ...(raw as Record<string, any>) };\n }\n\n if (typeof raw !== 'string') {\n return {};\n }\n\n try {\n const parsed = JSON.parse(raw);\n return parsed && typeof parsed === 'object'\n ? (parsed as Record<string, any>)\n : {};\n } catch {\n return {};\n }\n}\n\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableName: 'content_contribution_attachments',\n conflictColumns: ['id'],\n api: { include: ['list', 'get', 'create', 'update', 'delete'] },\n mcp: { include: ['list', 'get', 'create', 'update', 'delete'] },\n cli: true,\n})\nexport class ContentContributionAttachment extends SmrtObject {\n @foreignKey('ContentContribution', { required: true })\n contributionId = '';\n\n @foreignKey('ContentContributionRevision')\n revisionId = '';\n\n filename = '';\n mimeType = '';\n size = 0;\n fileKey = '';\n sourceUri = '';\n channel: ContentContributionChannel = 'web';\n\n @crossPackageRef('@happyvertical/smrt-assets:Asset')\n promotedAssetId = '';\n\n metadata = '';\n\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n createdAt = new Date();\n updatedAt = new Date();\n\n constructor(options: ContentContributionAttachmentOptions = {}) {\n super(options);\n if (options.contributionId !== undefined)\n this.contributionId = options.contributionId;\n if (options.revisionId !== undefined)\n this.revisionId = options.revisionId || '';\n if (options.filename !== undefined) this.filename = options.filename;\n if (options.mimeType !== undefined) this.mimeType = options.mimeType;\n if (options.size !== undefined) this.size = options.size;\n if (options.fileKey !== undefined) this.fileKey = options.fileKey || '';\n if (options.sourceUri !== undefined)\n this.sourceUri = options.sourceUri || '';\n if (options.channel !== undefined) this.channel = options.channel;\n if (options.promotedAssetId !== undefined)\n this.promotedAssetId = options.promotedAssetId || '';\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n if (options.createdAt) this.createdAt = options.createdAt;\n if (options.updatedAt) this.updatedAt = options.updatedAt;\n if (options.metadata !== undefined) {\n this.metadata =\n typeof options.metadata === 'string'\n ? options.metadata\n : JSON.stringify(options.metadata);\n }\n }\n\n getMetadata(): Record<string, any> {\n return parseMetadata(this.metadata);\n }\n\n protected override transformJSON(json: Record<string, any>) {\n return {\n ...json,\n revisionId: this.revisionId || null,\n fileKey: this.fileKey || null,\n sourceUri: this.sourceUri || null,\n promotedAssetId: this.promotedAssetId || null,\n metadata: this.getMetadata(),\n };\n }\n}\n","import { SmrtCollection } from '@happyvertical/smrt-core';\nimport { ContentContributionAttachment } from './content-contribution-attachment';\n\nexport class ContentContributionAttachmentCollection extends SmrtCollection<ContentContributionAttachment> {\n static readonly _itemClass = ContentContributionAttachment;\n\n async listForContribution(\n contributionId: string,\n ): Promise<ContentContributionAttachment[]> {\n return this.list({\n where: { contributionId },\n orderBy: 'created_at ASC',\n });\n }\n\n async listForRevision(\n revisionId: string,\n ): Promise<ContentContributionAttachment[]> {\n return this.list({\n where: { revisionId },\n orderBy: 'created_at ASC',\n });\n }\n}\n","import type { SmrtObjectOptions } from '@happyvertical/smrt-core';\nimport {\n crossPackageRef,\n foreignKey,\n SmrtObject,\n smrt,\n} from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport type { ContentContributionChannel } from './content-contribution-config';\n\nexport interface ContentContributionRevisionOptions extends SmrtObjectOptions {\n contributionId?: string;\n revisionNumber?: number;\n channel?: ContentContributionChannel;\n title?: string;\n description?: string | null;\n body?: string | null;\n sourceMessageId?: string | null;\n sourceThreadKey?: string | null;\n metadata?: Record<string, any> | string;\n tenantId?: string | null;\n createdAt?: Date;\n updatedAt?: Date;\n}\n\nfunction parseMetadata(raw: unknown): Record<string, any> {\n if (!raw) {\n return {};\n }\n\n if (typeof raw === 'object') {\n return { ...(raw as Record<string, any>) };\n }\n\n if (typeof raw !== 'string') {\n return {};\n }\n\n try {\n const parsed = JSON.parse(raw);\n return parsed && typeof parsed === 'object'\n ? (parsed as Record<string, any>)\n : {};\n } catch {\n return {};\n }\n}\n\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableName: 'content_contribution_revisions',\n conflictColumns: ['contribution_id', 'revision_number'],\n api: { include: ['list', 'get', 'create', 'update', 'delete'] },\n mcp: { include: ['list', 'get', 'create', 'update', 'delete'] },\n cli: true,\n})\nexport class ContentContributionRevision extends SmrtObject {\n @foreignKey('ContentContribution', { required: true })\n contributionId = '';\n\n revisionNumber = 1;\n channel: ContentContributionChannel = 'web';\n title = '';\n description = '';\n body = '';\n\n @crossPackageRef('@happyvertical/smrt-messages:Message')\n sourceMessageId = '';\n\n sourceThreadKey = '';\n metadata = '';\n\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n createdAt = new Date();\n updatedAt = new Date();\n\n constructor(options: ContentContributionRevisionOptions = {}) {\n super(options);\n if (options.contributionId !== undefined)\n this.contributionId = options.contributionId;\n if (options.revisionNumber !== undefined)\n this.revisionNumber = options.revisionNumber;\n if (options.channel !== undefined) this.channel = options.channel;\n if (options.title !== undefined) this.title = options.title;\n if (options.description !== undefined)\n this.description = options.description || '';\n if (options.body !== undefined) this.body = options.body || '';\n if (options.sourceMessageId !== undefined)\n this.sourceMessageId = options.sourceMessageId || '';\n if (options.sourceThreadKey !== undefined)\n this.sourceThreadKey = options.sourceThreadKey || '';\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n if (options.createdAt) this.createdAt = options.createdAt;\n if (options.updatedAt) this.updatedAt = options.updatedAt;\n if (options.metadata !== undefined) {\n this.metadata =\n typeof options.metadata === 'string'\n ? options.metadata\n : JSON.stringify(options.metadata);\n }\n }\n\n getMetadata(): Record<string, any> {\n return parseMetadata(this.metadata);\n }\n\n protected override transformJSON(json: Record<string, any>) {\n return {\n ...json,\n sourceMessageId: this.sourceMessageId || null,\n sourceThreadKey: this.sourceThreadKey || null,\n metadata: this.getMetadata(),\n };\n }\n}\n","import { SmrtCollection } from '@happyvertical/smrt-core';\nimport { ContentContributionRevision } from './content-contribution-revision';\n\nexport class ContentContributionRevisionCollection extends SmrtCollection<ContentContributionRevision> {\n static readonly _itemClass = ContentContributionRevision;\n\n async listForContribution(\n contributionId: string,\n ): Promise<ContentContributionRevision[]> {\n return this.list({\n where: { contributionId },\n orderBy: 'revision_number ASC',\n });\n }\n\n async getLatestForContribution(\n contributionId: string,\n ): Promise<ContentContributionRevision | null> {\n const revisions = await this.list({\n where: { contributionId },\n orderBy: 'revision_number DESC',\n limit: 1,\n });\n\n return revisions[0] || null;\n }\n}\n","import type { SmrtObjectOptions } from '@happyvertical/smrt-core';\nimport { field, SmrtObject, smrt } from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport {\n type ContentContributionChannel,\n type ContentContributionIntakeRules,\n type ContentContributionPromotionMapping,\n type ContentContributionTypeDefinition,\n hasStaticContentContributionType,\n} from './content-contribution-config';\nimport { getQueryRows, isMissingTableError } from './database-utils';\n\nexport interface ContentContributionTypeOptions extends SmrtObjectOptions {\n key?: string;\n label?: string;\n enabled?: boolean;\n allowedChannels?: ContentContributionChannel[] | string;\n allowText?: boolean;\n allowFiles?: boolean;\n allowEmptyText?: boolean;\n intakeRules?: ContentContributionIntakeRules | string;\n promotion?: ContentContributionPromotionMapping | string;\n metadata?: Record<string, any> | string;\n tenantId?: string | null;\n createdAt?: Date;\n updatedAt?: Date;\n}\n\nfunction parseJSON<T>(raw: unknown, fallback: T): T {\n if (!raw) {\n return fallback;\n }\n\n if (typeof raw === 'object') {\n return structuredClone(raw as T);\n }\n\n if (typeof raw !== 'string') {\n return fallback;\n }\n\n try {\n const parsed = JSON.parse(raw);\n return parsed && typeof parsed === 'object' ? (parsed as T) : fallback;\n } catch {\n return fallback;\n }\n}\n\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableName: 'content_contribution_types',\n conflictColumns: ['key'],\n api: { include: ['list', 'get', 'create', 'update', 'delete'] },\n mcp: { include: ['list', 'get', 'create', 'update', 'delete'] },\n cli: true,\n})\nexport class ContentContributionType extends SmrtObject {\n @field({ required: true })\n key = '';\n\n label = '';\n enabled = true;\n allowedChannels = '';\n allowText = true;\n allowFiles = false;\n allowEmptyText = false;\n intakeRules = '';\n promotion = '';\n metadata = '';\n\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n createdAt = new Date();\n updatedAt = new Date();\n\n constructor(options: ContentContributionTypeOptions = {}) {\n super(options);\n if (options.key !== undefined) this.key = options.key;\n if (options.label !== undefined) this.label = options.label;\n if (options.enabled !== undefined) this.enabled = options.enabled;\n if (options.allowText !== undefined) this.allowText = options.allowText;\n if (options.allowFiles !== undefined) this.allowFiles = options.allowFiles;\n if (options.allowEmptyText !== undefined)\n this.allowEmptyText = options.allowEmptyText;\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n if (options.createdAt) this.createdAt = options.createdAt;\n if (options.updatedAt) this.updatedAt = options.updatedAt;\n\n if (options.allowedChannels !== undefined) {\n this.allowedChannels =\n typeof options.allowedChannels === 'string'\n ? options.allowedChannels\n : JSON.stringify(options.allowedChannels);\n }\n\n if (options.intakeRules !== undefined) {\n this.intakeRules =\n typeof options.intakeRules === 'string'\n ? options.intakeRules\n : JSON.stringify(options.intakeRules);\n }\n\n if (options.promotion !== undefined) {\n this.promotion =\n typeof options.promotion === 'string'\n ? options.promotion\n : JSON.stringify(options.promotion);\n }\n\n if (options.metadata !== undefined) {\n this.metadata =\n typeof options.metadata === 'string'\n ? options.metadata\n : JSON.stringify(options.metadata);\n }\n }\n\n getAllowedChannels(): ContentContributionChannel[] {\n const channels = parseJSON<ContentContributionChannel[]>(\n this.allowedChannels,\n [],\n );\n return channels.length > 0 ? channels : ['web'];\n }\n\n setAllowedChannels(channels: ContentContributionChannel[]): void {\n this.allowedChannels = JSON.stringify(channels);\n }\n\n getIntakeRules(): ContentContributionIntakeRules {\n return parseJSON<ContentContributionIntakeRules>(this.intakeRules, {});\n }\n\n setIntakeRules(rules: ContentContributionIntakeRules): void {\n this.intakeRules = JSON.stringify(rules || {});\n }\n\n getPromotion(): ContentContributionPromotionMapping {\n return parseJSON<ContentContributionPromotionMapping>(this.promotion, {});\n }\n\n setPromotion(promotion: ContentContributionPromotionMapping): void {\n this.promotion = JSON.stringify(promotion || {});\n }\n\n getMetadata(): Record<string, any> {\n return parseJSON<Record<string, any>>(this.metadata, {});\n }\n\n setMetadata(metadata: Record<string, any>): void {\n this.metadata = JSON.stringify(metadata || {});\n }\n\n toDefinition(): ContentContributionTypeDefinition {\n return {\n key: this.key,\n label: this.label || this.key,\n enabled: this.enabled !== false,\n allowedChannels: this.getAllowedChannels(),\n allowText: this.allowText !== false,\n allowFiles: this.allowFiles === true,\n allowEmptyText: this.allowEmptyText === true,\n intakeRules: this.getIntakeRules(),\n promotion: this.getPromotion(),\n metadata: this.getMetadata(),\n };\n }\n\n protected override transformJSON(json: Record<string, any>) {\n return {\n ...json,\n allowedChannels: this.getAllowedChannels(),\n intakeRules: this.getIntakeRules(),\n promotion: this.getPromotion(),\n metadata: this.getMetadata(),\n };\n }\n\n protected override async validateBeforeSave(): Promise<void> {\n await super.validateBeforeSave();\n\n if (!this.key) {\n throw new Error('Contribution type key is required.');\n }\n\n const promotion = this.getPromotion();\n if (!promotion.targetContentType) {\n throw new Error(\n `Contribution type \"${this.key}\" must define promotion.targetContentType.`,\n );\n }\n }\n\n override async delete(): Promise<void> {\n if (!this.db) {\n return super.delete();\n }\n\n const hasFallback = hasStaticContentContributionType(this.key);\n\n if (!hasFallback) {\n try {\n const existing = await this.db.query(\n 'SELECT id FROM content_contributions WHERE contribution_type_key = ? LIMIT 1',\n this.key,\n );\n const rows = getQueryRows(existing);\n\n if (rows.length > 0) {\n throw new Error(\n `Cannot delete contribution type \"${this.key}\" because contributions already reference it.`,\n );\n }\n } catch (error) {\n if (\n error instanceof Error &&\n error.message.includes('already reference it')\n ) {\n throw error;\n }\n if (!isMissingTableError(error, 'content_contributions')) {\n throw error;\n }\n }\n }\n\n return super.delete();\n }\n}\n","import { SmrtCollection } from '@happyvertical/smrt-core';\nimport { ContentContributionType } from './content-contribution-type';\n\nexport class ContentContributionTypeCollection extends SmrtCollection<ContentContributionType> {\n static readonly _itemClass = ContentContributionType;\n\n async getByKey(key: string): Promise<ContentContributionType | null> {\n return this.get({ key });\n }\n}\n","import type { SmrtObjectOptions } from '@happyvertical/smrt-core';\nimport {\n crossPackageRef,\n field,\n SmrtObject,\n smrt,\n} from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport type { ContentContributorTrustLevel } from './content-contribution-config';\n\nexport interface ContentContributorOptions extends SmrtObjectOptions {\n profileId?: string | null;\n email?: string;\n name?: string;\n trustLevel?: ContentContributorTrustLevel;\n metadata?: Record<string, any> | string;\n tenantId?: string | null;\n createdAt?: Date;\n updatedAt?: Date;\n}\n\nfunction parseMetadata(raw: unknown): Record<string, any> {\n if (!raw) {\n return {};\n }\n\n if (typeof raw === 'object') {\n return { ...(raw as Record<string, any>) };\n }\n\n if (typeof raw !== 'string') {\n return {};\n }\n\n try {\n const parsed = JSON.parse(raw);\n return parsed && typeof parsed === 'object'\n ? (parsed as Record<string, any>)\n : {};\n } catch {\n return {};\n }\n}\n\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableName: 'content_contributors',\n conflictColumns: ['email'],\n api: { include: ['list', 'get', 'create', 'update', 'delete'] },\n mcp: { include: ['list', 'get', 'create', 'update', 'delete'] },\n cli: true,\n})\nexport class ContentContributor extends SmrtObject {\n @crossPackageRef('@happyvertical/smrt-profiles:Profile')\n profileId = '';\n\n @field({ required: true })\n email = '';\n\n name = '';\n trustLevel: ContentContributorTrustLevel = 'standard';\n metadata = '';\n\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n createdAt = new Date();\n updatedAt = new Date();\n\n constructor(options: ContentContributorOptions = {}) {\n super(options);\n if (options.profileId !== undefined)\n this.profileId = options.profileId || '';\n if (options.email !== undefined)\n this.email = options.email.toLowerCase().trim();\n if (options.name !== undefined) this.name = options.name;\n if (options.trustLevel !== undefined) this.trustLevel = options.trustLevel;\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n if (options.createdAt) this.createdAt = options.createdAt;\n if (options.updatedAt) this.updatedAt = options.updatedAt;\n if (options.metadata !== undefined) {\n this.metadata =\n typeof options.metadata === 'string'\n ? options.metadata\n : JSON.stringify(options.metadata);\n }\n }\n\n getMetadata(): Record<string, any> {\n return parseMetadata(this.metadata);\n }\n\n setMetadata(metadata: Record<string, any>): void {\n this.metadata = JSON.stringify(metadata || {});\n }\n\n protected override transformJSON(json: Record<string, any>) {\n return {\n ...json,\n profileId: this.profileId || null,\n metadata: this.getMetadata(),\n };\n }\n}\n","import { SmrtCollection } from '@happyvertical/smrt-core';\nimport {\n ProfileCollection,\n ProfileTypeCollection,\n} from '@happyvertical/smrt-profiles';\nimport { ContentContributor } from './content-contributor';\n\nexport class ContentContributorCollection extends SmrtCollection<ContentContributor> {\n static readonly _itemClass = ContentContributor;\n\n async getByEmail(email: string): Promise<ContentContributor | null> {\n return this.get({ email: email.toLowerCase().trim() });\n }\n\n async getByProfileId(profileId: string): Promise<ContentContributor | null> {\n return this.get({ profileId });\n }\n\n async findOrCreateByEmail(options: {\n email: string;\n name?: string | null;\n tenantId?: string | null;\n }): Promise<ContentContributor> {\n const normalizedEmail = options.email.toLowerCase().trim();\n const existing = await this.getByEmail(normalizedEmail);\n if (existing) {\n if (options.name && !existing.name) {\n existing.name = options.name;\n await existing.save();\n }\n return existing;\n }\n\n const profileCollection = await ProfileCollection.create(this.options);\n let profile = await profileCollection.findByEmail(normalizedEmail);\n\n if (!profile) {\n const profileTypes = await ProfileTypeCollection.create(this.options);\n const personType = await profileTypes.getOrCreateBySlug('person', {\n name: 'Person',\n description: 'Individual person',\n });\n\n profile = await profileCollection.create({\n typeId: personType.id || undefined,\n email: normalizedEmail,\n name: options.name || normalizedEmail.split('@')[0],\n tenantId: options.tenantId || undefined,\n });\n await profile.save();\n }\n\n const contributor = await this.create({\n email: normalizedEmail,\n name: options.name || profile.name || normalizedEmail.split('@')[0],\n profileId: profile.id || undefined,\n tenantId: options.tenantId || undefined,\n trustLevel: 'standard',\n });\n await contributor.save();\n return contributor;\n }\n}\n","import { SmrtCollection, smrt } from '@happyvertical/smrt-core';\nimport {\n AttachmentCollection,\n EmailCollection,\n} from '@happyvertical/smrt-messages';\nimport type { ContentContributionAttachmentInput } from './content-contribution';\nimport { ContentContribution } from './content-contribution';\nimport type { ContentContributionTypeDefinition } from './content-contribution-config';\nimport {\n evaluateContributionIntake,\n getContentContributionTypeConfigState,\n getEffectiveContentContributionConfig,\n} from './content-contribution-config';\nimport { ContentContributorCollection } from './content-contributors';\n\nexport interface SubmitWebContentContributionOptions {\n typeKey: string;\n contributorEmail: string;\n contributorName?: string | null;\n title?: string | null;\n description?: string | null;\n body?: string | null;\n attachments?: ContentContributionAttachmentInput[];\n metadata?: Record<string, any>;\n tenantId?: string | null;\n}\n\nexport interface IngestEmailContentContributionOptions {\n emailId: string;\n typeKey?: string | null;\n tenantId?: string | null;\n}\n\nfunction toContributionStatus(\n decision: ReturnType<typeof evaluateContributionIntake>['decision'],\n) {\n if (decision === 'quarantined') {\n return 'quarantined' as const;\n }\n\n if (decision === 'rejected') {\n return 'rejected' as const;\n }\n\n return 'submitted' as const;\n}\n\nfunction pickDefaultEmailType(\n types: ContentContributionTypeDefinition[],\n): ContentContributionTypeDefinition | null {\n const emailTypes = types.filter(\n (type) =>\n type.enabled !== false && (type.allowedChannels || []).includes('email'),\n );\n\n return emailTypes.length === 1 ? emailTypes[0] : null;\n}\n\n@smrt({\n api: {\n include: [\n 'submitWebContribution',\n 'ingestEmailContribution',\n 'listForContributor',\n 'listInboxAction',\n 'getContributionTypesAction',\n ],\n routes: {\n submitWebContribution: {\n scope: 'collection',\n method: 'POST',\n path: 'submit',\n },\n ingestEmailContribution: {\n scope: 'collection',\n method: 'POST',\n path: 'ingest-email',\n },\n listForContributor: {\n scope: 'collection',\n method: 'GET',\n path: 'by-contributor',\n },\n listInboxAction: {\n scope: 'collection',\n method: 'GET',\n path: 'inbox',\n },\n getContributionTypesAction: {\n scope: 'collection',\n method: 'GET',\n path: 'types',\n },\n },\n },\n mcp: false,\n cli: false,\n})\nexport class ContentContributions extends SmrtCollection<ContentContribution> {\n static readonly _itemClass = ContentContribution;\n\n private async getContributorCollection() {\n return ContentContributorCollection.create(this.options);\n }\n\n private async getEmailCollection() {\n return EmailCollection.create(this.options);\n }\n\n private async getAttachmentCollection() {\n return AttachmentCollection.create(this.options);\n }\n\n private async resolveSubmissionType(\n typeKey: string | null | undefined,\n ): Promise<ContentContributionTypeDefinition> {\n const effective = await getEffectiveContentContributionConfig({\n db: this.db,\n });\n\n if (typeKey) {\n const match = effective.types.find((type) => type.key === typeKey);\n if (match) {\n return match;\n }\n throw new Error(`Unknown contribution type \"${typeKey}\".`);\n }\n\n const defaultType = pickDefaultEmailType(effective.types);\n if (!defaultType) {\n throw new Error(\n 'A contribution type key is required unless there is exactly one email-enabled type.',\n );\n }\n\n return defaultType;\n }\n\n async getContributionTypesAction() {\n return getContentContributionTypeConfigState({ db: this.db });\n }\n\n async listForContributor(\n options: { contributorId?: string; contributorEmail?: string } = {},\n ) {\n let contributorId = options.contributorId;\n\n if (!contributorId && options.contributorEmail) {\n const contributors = await this.getContributorCollection();\n const contributor = await contributors.getByEmail(\n options.contributorEmail,\n );\n contributorId = contributor?.id || undefined;\n }\n\n if (!contributorId) {\n return [];\n }\n\n return this.list({\n where: { contributorId },\n orderBy: 'updated_at DESC',\n });\n }\n\n async listInboxAction(\n options: { statuses?: string | string[] } = {},\n ): Promise<ContentContribution[]> {\n const requested = Array.isArray(options.statuses)\n ? options.statuses\n : typeof options.statuses === 'string'\n ? options.statuses.split(',').map((item) => item.trim())\n : ['submitted', 'quarantined', 'needs_changes', 'approved'];\n\n const contributions = await this.list({\n orderBy: 'updated_at DESC',\n });\n\n return contributions.filter((contribution) =>\n requested.includes(contribution.status),\n );\n }\n\n async submitWebContribution(options: SubmitWebContentContributionOptions) {\n const type = await this.resolveSubmissionType(options.typeKey);\n const contributors = await this.getContributorCollection();\n const contributor = await contributors.findOrCreateByEmail({\n email: options.contributorEmail,\n name: options.contributorName || null,\n tenantId: options.tenantId ?? null,\n });\n\n const intake = evaluateContributionIntake({\n contributionType: type,\n trustLevel: contributor.trustLevel,\n channel: 'web',\n title: options.title || null,\n description: options.description || null,\n body: options.body || null,\n attachments: options.attachments || [],\n });\n\n const status = toContributionStatus(intake.decision);\n\n const contribution = await this.create({\n contributorId: contributor.id || '',\n contributionTypeKey: type.key,\n status,\n intakeDecision: intake.decision,\n channel: 'web',\n title: options.title || '',\n description: options.description || '',\n body: options.body || '',\n contributorEmail: contributor.email,\n contributorName: contributor.name,\n editorNotes: intake.reasons.join('\\n'),\n tenantId: options.tenantId ?? null,\n metadata: JSON.stringify({\n intake: {\n decision: intake.decision,\n reasons: intake.reasons,\n },\n submission: options.metadata || {},\n }),\n });\n await contribution.save();\n\n await contribution.appendRevisionAction({\n title: options.title,\n description: options.description,\n body: options.body,\n attachments: options.attachments || [],\n channel: 'web',\n metadata: {\n source: 'web',\n },\n });\n\n if (\n contributor.trustLevel === 'trusted' &&\n intake.decision === 'accepted' &&\n type.promotion?.autoPromoteTrusted === true\n ) {\n return contribution.approveAction({\n editorNote: 'Auto-promoted trusted contributor submission.',\n targetStatus: type.promotion?.targetContentStatus || 'draft',\n });\n }\n\n return {\n contribution: contribution.toJSON(),\n intake,\n };\n }\n\n async ingestEmailContribution(\n options: IngestEmailContentContributionOptions,\n ) {\n const emailCollection = await this.getEmailCollection();\n const email = (await emailCollection.get({ id: options.emailId })) as any;\n if (!email) {\n throw new Error(`Email \"${options.emailId}\" not found.`);\n }\n\n const type = await this.resolveSubmissionType(options.typeKey);\n const contributors = await this.getContributorCollection();\n const contributor = await contributors.findOrCreateByEmail({\n email: email.fromAddress,\n name: email.fromName || null,\n tenantId: options.tenantId ?? null,\n });\n\n const attachmentCollection = await this.getAttachmentCollection();\n const inboundAttachments = await attachmentCollection.getByMessage(\n email.id || '',\n );\n const normalizedAttachments: ContentContributionAttachmentInput[] =\n inboundAttachments\n .filter((attachment: any) => !attachment.isInline())\n .map((attachment: any) => ({\n filename: attachment.filename || 'attachment',\n mimeType: attachment.contentType || 'application/octet-stream',\n size: attachment.size || 0,\n sourceUri: attachment.filePath || attachment.sourceUrl || null,\n metadata: {\n messageId: email.id || null,\n attachmentId: attachment.id || null,\n },\n }));\n\n const threadKey =\n email.threadId || email.messageId || email.inReplyTo || email.id || '';\n\n const intake = evaluateContributionIntake({\n contributionType: type,\n trustLevel: contributor.trustLevel,\n channel: 'email',\n title: email.subject || null,\n body: email.textBody || email.body || null,\n attachments: normalizedAttachments,\n });\n\n const existing =\n threadKey &&\n (await this.get({\n threadKey,\n contributorId: contributor.id || '',\n }));\n\n if (existing) {\n existing.intakeDecision = intake.decision;\n existing.editorNotes = intake.reasons.join('\\n');\n\n const metadata = existing.getMetadata();\n metadata.lastEmailIntake = {\n decision: intake.decision,\n reasons: intake.reasons,\n emailId: email.id || null,\n };\n existing.setMetadata(metadata);\n\n if (intake.decision === 'rejected') {\n existing.status = 'rejected';\n existing.rejectedAt = new Date();\n await existing.save();\n\n return {\n contribution: existing.toJSON(),\n intake,\n revision: null,\n attachments: (await existing.getAttachments()).map((item: any) =>\n item.toJSON(),\n ),\n };\n }\n\n existing.status = toContributionStatus(intake.decision);\n await existing.save();\n\n const appended = await existing.appendRevisionAction({\n title: email.subject || existing.title,\n body: email.textBody || email.body || '',\n channel: 'email',\n sourceMessageId: email.id || '',\n sourceThreadKey: threadKey,\n attachments: normalizedAttachments,\n metadata: {\n source: 'email-reply',\n emailId: email.id || null,\n },\n });\n\n return {\n ...appended,\n intake,\n };\n }\n\n const status = toContributionStatus(intake.decision);\n\n const contribution = await this.create({\n contributorId: contributor.id || '',\n contributionTypeKey: type.key,\n status,\n intakeDecision: intake.decision,\n channel: 'email',\n title: email.subject || '',\n description: '',\n body: email.textBody || email.body || '',\n contributorEmail: contributor.email,\n contributorName: contributor.name,\n threadKey,\n sourceMessageId: email.id || '',\n editorNotes: intake.reasons.join('\\n'),\n tenantId: options.tenantId ?? null,\n metadata: JSON.stringify({\n intake: {\n decision: intake.decision,\n reasons: intake.reasons,\n },\n email: {\n emailId: email.id || null,\n messageId: email.messageId || null,\n inReplyTo: email.inReplyTo || null,\n threadId: email.threadId || null,\n },\n }),\n });\n await contribution.save();\n\n await contribution.appendRevisionAction({\n title: email.subject || '',\n body: email.textBody || email.body || '',\n channel: 'email',\n sourceMessageId: email.id || null,\n sourceThreadKey: threadKey,\n attachments: normalizedAttachments,\n metadata: {\n source: 'email',\n emailId: email.id || null,\n },\n });\n\n if (\n contributor.trustLevel === 'trusted' &&\n intake.decision === 'accepted' &&\n type.promotion?.autoPromoteTrusted === true\n ) {\n return contribution.approveAction({\n editorNote: 'Auto-promoted trusted contributor email submission.',\n targetStatus: type.promotion?.targetContentStatus || 'draft',\n });\n }\n\n return {\n contribution: contribution.toJSON(),\n intake,\n };\n }\n}\n","import type { SmrtObjectOptions } from '@happyvertical/smrt-core';\nimport {\n crossPackageRef,\n foreignKey,\n SmrtObject,\n smrt,\n} from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport type {\n ContentCorrectionStatus,\n ContentCorrectionType,\n} from './content-governance';\n\nexport interface ContentCorrectionOptions extends SmrtObjectOptions {\n contentId?: string;\n contentVersionId?: string;\n factId?: string;\n replacementFactId?: string;\n correctionType?: ContentCorrectionType;\n status?: ContentCorrectionStatus;\n summary?: string;\n incorrectText?: string;\n correctedText?: string;\n publicNote?: string;\n metadata?: string | Record<string, any>;\n tenantId?: string | null;\n publishedAt?: Date | null;\n createdAt?: Date;\n updatedAt?: Date;\n}\n\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableName: 'content_corrections',\n api: { include: ['list', 'get', 'create', 'update'] },\n mcp: { include: ['list', 'get', 'create', 'update'] },\n cli: true,\n})\nexport class ContentCorrection extends SmrtObject {\n @foreignKey('Content', { required: true })\n contentId = '';\n\n @foreignKey('ContentVersion')\n contentVersionId = '';\n\n @crossPackageRef('@happyvertical/smrt-facts:Fact')\n factId = '';\n\n @crossPackageRef('@happyvertical/smrt-facts:Fact')\n replacementFactId = '';\n correctionType: ContentCorrectionType = 'fact';\n status: ContentCorrectionStatus = 'draft';\n summary = '';\n incorrectText = '';\n correctedText = '';\n publicNote = '';\n metadata = '';\n\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n publishedAt: Date | null = null;\n createdAt = new Date();\n updatedAt = new Date();\n\n constructor(options: ContentCorrectionOptions = {}) {\n super(options);\n if (options.contentId) this.contentId = options.contentId;\n if (options.contentVersionId !== undefined)\n this.contentVersionId = options.contentVersionId;\n if (options.factId !== undefined) this.factId = options.factId;\n if (options.replacementFactId !== undefined)\n this.replacementFactId = options.replacementFactId;\n if (options.correctionType !== undefined)\n this.correctionType = options.correctionType;\n if (options.status !== undefined) this.status = options.status;\n if (options.summary !== undefined) this.summary = options.summary;\n if (options.incorrectText !== undefined)\n this.incorrectText = options.incorrectText;\n if (options.correctedText !== undefined)\n this.correctedText = options.correctedText;\n if (options.publicNote !== undefined) this.publicNote = options.publicNote;\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n if (options.publishedAt !== undefined)\n this.publishedAt = options.publishedAt;\n if (options.createdAt) this.createdAt = options.createdAt;\n if (options.updatedAt) this.updatedAt = options.updatedAt;\n\n if (options.metadata !== undefined) {\n this.metadata =\n typeof options.metadata === 'string'\n ? options.metadata\n : JSON.stringify(options.metadata);\n }\n }\n\n getMetadata(): Record<string, any> {\n try {\n return this.metadata ? JSON.parse(this.metadata) : {};\n } catch {\n return {};\n }\n }\n}\n","import { SmrtCollection } from '@happyvertical/smrt-core';\nimport { ContentCorrection } from './content-correction';\n\nexport class ContentCorrectionCollection extends SmrtCollection<ContentCorrection> {\n static readonly _itemClass = ContentCorrection;\n\n async listForContent(contentId: string): Promise<ContentCorrection[]> {\n return this.list({\n where: { contentId },\n orderBy: 'created_at DESC',\n });\n }\n\n async getPublishedForContent(\n contentId: string,\n ): Promise<ContentCorrection[]> {\n return this.list({\n where: { contentId, status: 'published' },\n orderBy: 'published_at DESC',\n });\n }\n\n async issue(\n options: ConstructorParameters<typeof ContentCorrection>[0],\n ): Promise<ContentCorrection> {\n if (!options) {\n return this.create({});\n }\n\n return this.create({\n ...options,\n metadata:\n typeof options.metadata === 'string'\n ? options.metadata\n : options.metadata\n ? JSON.stringify(options.metadata)\n : undefined,\n });\n }\n}\n","'use strict';\n\nconst nameStartChar = ':A-Za-z_\\\\u00C0-\\\\u00D6\\\\u00D8-\\\\u00F6\\\\u00F8-\\\\u02FF\\\\u0370-\\\\u037D\\\\u037F-\\\\u1FFF\\\\u200C-\\\\u200D\\\\u2070-\\\\u218F\\\\u2C00-\\\\u2FEF\\\\u3001-\\\\uD7FF\\\\uF900-\\\\uFDCF\\\\uFDF0-\\\\uFFFD';\nconst nameChar = nameStartChar + '\\\\-.\\\\d\\\\u00B7\\\\u0300-\\\\u036F\\\\u203F-\\\\u2040';\nexport const nameRegexp = '[' + nameStartChar + '][' + nameChar + ']*';\nconst regexName = new RegExp('^' + nameRegexp + '$');\n\nexport function getAllMatches(string, regex) {\n const matches = [];\n let match = regex.exec(string);\n while (match) {\n const allmatches = [];\n allmatches.startIndex = regex.lastIndex - match[0].length;\n const len = match.length;\n for (let index = 0; index < len; index++) {\n allmatches.push(match[index]);\n }\n matches.push(allmatches);\n match = regex.exec(string);\n }\n return matches;\n}\n\nexport const isName = function (string) {\n const match = regexName.exec(string);\n return !(match === null || typeof match === 'undefined');\n}\n\nexport function isExist(v) {\n return typeof v !== 'undefined';\n}\n\nexport function isEmptyObject(obj) {\n return Object.keys(obj).length === 0;\n}\n\nexport function getValue(v) {\n if (exports.isExist(v)) {\n return v;\n } else {\n return '';\n }\n}\n\n/**\n * Dangerous property names that could lead to prototype pollution or security issues\n */\nexport const DANGEROUS_PROPERTY_NAMES = [\n // '__proto__',\n // 'constructor',\n // 'prototype',\n 'hasOwnProperty',\n 'toString',\n 'valueOf',\n '__defineGetter__',\n '__defineSetter__',\n '__lookupGetter__',\n '__lookupSetter__'\n];\n\nexport const criticalProperties = [\"__proto__\", \"constructor\", \"prototype\"];","'use strict';\n\nimport { getAllMatches, isName } from './util.js';\n\nconst defaultOptions = {\n allowBooleanAttributes: false, //A tag can have attributes without any value\n unpairedTags: []\n};\n\n//const tagsPattern = new RegExp(\"<\\\\/?([\\\\w:\\\\-_\\.]+)\\\\s*\\/?>\",\"g\");\nexport function validate(xmlData, options) {\n options = Object.assign({}, defaultOptions, options);\n\n //xmlData = xmlData.replace(/(\\r\\n|\\n|\\r)/gm,\"\");//make it single line\n //xmlData = xmlData.replace(/(^\\s*<\\?xml.*?\\?>)/g,\"\");//Remove XML starting tag\n //xmlData = xmlData.replace(/(<!DOCTYPE[\\s\\w\\\"\\.\\/\\-\\:]+(\\[.*\\])*\\s*>)/g,\"\");//Remove DOCTYPE\n const tags = [];\n let tagFound = false;\n\n //indicates that the root tag has been closed (aka. depth 0 has been reached)\n let reachedRoot = false;\n\n if (xmlData[0] === '\\ufeff') {\n // check for byte order mark (BOM)\n xmlData = xmlData.substr(1);\n }\n\n for (let i = 0; i < xmlData.length; i++) {\n\n if (xmlData[i] === '<' && xmlData[i + 1] === '?') {\n i += 2;\n i = readPI(xmlData, i);\n if (i.err) return i;\n } else if (xmlData[i] === '<') {\n //starting of tag\n //read until you reach to '>' avoiding any '>' in attribute value\n let tagStartPos = i;\n i++;\n\n if (xmlData[i] === '!') {\n i = readCommentAndCDATA(xmlData, i);\n continue;\n } else {\n let closingTag = false;\n if (xmlData[i] === '/') {\n //closing tag\n closingTag = true;\n i++;\n }\n //read tagname\n let tagName = '';\n for (; i < xmlData.length &&\n xmlData[i] !== '>' &&\n xmlData[i] !== ' ' &&\n xmlData[i] !== '\\t' &&\n xmlData[i] !== '\\n' &&\n xmlData[i] !== '\\r'; i++\n ) {\n tagName += xmlData[i];\n }\n tagName = tagName.trim();\n //console.log(tagName);\n\n if (tagName[tagName.length - 1] === '/') {\n //self closing tag without attributes\n tagName = tagName.substring(0, tagName.length - 1);\n //continue;\n i--;\n }\n if (!validateTagName(tagName)) {\n let msg;\n if (tagName.trim().length === 0) {\n msg = \"Invalid space after '<'.\";\n } else {\n msg = \"Tag '\" + tagName + \"' is an invalid name.\";\n }\n return getErrorObject('InvalidTag', msg, getLineNumberForPosition(xmlData, i));\n }\n\n const result = readAttributeStr(xmlData, i);\n if (result === false) {\n return getErrorObject('InvalidAttr', \"Attributes for '\" + tagName + \"' have open quote.\", getLineNumberForPosition(xmlData, i));\n }\n let attrStr = result.value;\n i = result.index;\n\n if (attrStr[attrStr.length - 1] === '/') {\n //self closing tag\n const attrStrStart = i - attrStr.length;\n attrStr = attrStr.substring(0, attrStr.length - 1);\n const isValid = validateAttributeString(attrStr, options);\n if (isValid === true) {\n tagFound = true;\n //continue; //text may presents after self closing tag\n } else {\n //the result from the nested function returns the position of the error within the attribute\n //in order to get the 'true' error line, we need to calculate the position where the attribute begins (i - attrStr.length) and then add the position within the attribute\n //this gives us the absolute index in the entire xml, which we can use to find the line at last\n return getErrorObject(isValid.err.code, isValid.err.msg, getLineNumberForPosition(xmlData, attrStrStart + isValid.err.line));\n }\n } else if (closingTag) {\n if (!result.tagClosed) {\n return getErrorObject('InvalidTag', \"Closing tag '\" + tagName + \"' doesn't have proper closing.\", getLineNumberForPosition(xmlData, i));\n } else if (attrStr.trim().length > 0) {\n return getErrorObject('InvalidTag', \"Closing tag '\" + tagName + \"' can't have attributes or invalid starting.\", getLineNumberForPosition(xmlData, tagStartPos));\n } else if (tags.length === 0) {\n return getErrorObject('InvalidTag', \"Closing tag '\" + tagName + \"' has not been opened.\", getLineNumberForPosition(xmlData, tagStartPos));\n } else {\n const otg = tags.pop();\n if (tagName !== otg.tagName) {\n let openPos = getLineNumberForPosition(xmlData, otg.tagStartPos);\n return getErrorObject('InvalidTag',\n \"Expected closing tag '\" + otg.tagName + \"' (opened in line \" + openPos.line + \", col \" + openPos.col + \") instead of closing tag '\" + tagName + \"'.\",\n getLineNumberForPosition(xmlData, tagStartPos));\n }\n\n //when there are no more tags, we reached the root level.\n if (tags.length == 0) {\n reachedRoot = true;\n }\n }\n } else {\n const isValid = validateAttributeString(attrStr, options);\n if (isValid !== true) {\n //the result from the nested function returns the position of the error within the attribute\n //in order to get the 'true' error line, we need to calculate the position where the attribute begins (i - attrStr.length) and then add the position within the attribute\n //this gives us the absolute index in the entire xml, which we can use to find the line at last\n return getErrorObject(isValid.err.code, isValid.err.msg, getLineNumberForPosition(xmlData, i - attrStr.length + isValid.err.line));\n }\n\n //if the root level has been reached before ...\n if (reachedRoot === true) {\n return getErrorObject('InvalidXml', 'Multiple possible root nodes found.', getLineNumberForPosition(xmlData, i));\n } else if (options.unpairedTags.indexOf(tagName) !== -1) {\n //don't push into stack\n } else {\n tags.push({ tagName, tagStartPos });\n }\n tagFound = true;\n }\n\n //skip tag text value\n //It may include comments and CDATA value\n for (i++; i < xmlData.length; i++) {\n if (xmlData[i] === '<') {\n if (xmlData[i + 1] === '!') {\n //comment or CADATA\n i++;\n i = readCommentAndCDATA(xmlData, i);\n continue;\n } else if (xmlData[i + 1] === '?') {\n i = readPI(xmlData, ++i);\n if (i.err) return i;\n } else {\n break;\n }\n } else if (xmlData[i] === '&') {\n const afterAmp = validateAmpersand(xmlData, i);\n if (afterAmp == -1)\n return getErrorObject('InvalidChar', \"char '&' is not expected.\", getLineNumberForPosition(xmlData, i));\n i = afterAmp;\n } else {\n if (reachedRoot === true && !isWhiteSpace(xmlData[i])) {\n return getErrorObject('InvalidXml', \"Extra text at the end\", getLineNumberForPosition(xmlData, i));\n }\n }\n } //end of reading tag text value\n if (xmlData[i] === '<') {\n i--;\n }\n }\n } else {\n if (isWhiteSpace(xmlData[i])) {\n continue;\n }\n return getErrorObject('InvalidChar', \"char '\" + xmlData[i] + \"' is not expected.\", getLineNumberForPosition(xmlData, i));\n }\n }\n\n if (!tagFound) {\n return getErrorObject('InvalidXml', 'Start tag expected.', 1);\n } else if (tags.length == 1) {\n return getErrorObject('InvalidTag', \"Unclosed tag '\" + tags[0].tagName + \"'.\", getLineNumberForPosition(xmlData, tags[0].tagStartPos));\n } else if (tags.length > 0) {\n return getErrorObject('InvalidXml', \"Invalid '\" +\n JSON.stringify(tags.map(t => t.tagName), null, 4).replace(/\\r?\\n/g, '') +\n \"' found.\", { line: 1, col: 1 });\n }\n\n return true;\n};\n\nfunction isWhiteSpace(char) {\n return char === ' ' || char === '\\t' || char === '\\n' || char === '\\r';\n}\n/**\n * Read Processing insstructions and skip\n * @param {*} xmlData\n * @param {*} i\n */\nfunction readPI(xmlData, i) {\n const start = i;\n for (; i < xmlData.length; i++) {\n if (xmlData[i] == '?' || xmlData[i] == ' ') {\n //tagname\n const tagname = xmlData.substr(start, i - start);\n if (i > 5 && tagname === 'xml') {\n return getErrorObject('InvalidXml', 'XML declaration allowed only at the start of the document.', getLineNumberForPosition(xmlData, i));\n } else if (xmlData[i] == '?' && xmlData[i + 1] == '>') {\n //check if valid attribut string\n i++;\n break;\n } else {\n continue;\n }\n }\n }\n return i;\n}\n\nfunction readCommentAndCDATA(xmlData, i) {\n if (xmlData.length > i + 5 && xmlData[i + 1] === '-' && xmlData[i + 2] === '-') {\n //comment\n for (i += 3; i < xmlData.length; i++) {\n if (xmlData[i] === '-' && xmlData[i + 1] === '-' && xmlData[i + 2] === '>') {\n i += 2;\n break;\n }\n }\n } else if (\n xmlData.length > i + 8 &&\n xmlData[i + 1] === 'D' &&\n xmlData[i + 2] === 'O' &&\n xmlData[i + 3] === 'C' &&\n xmlData[i + 4] === 'T' &&\n xmlData[i + 5] === 'Y' &&\n xmlData[i + 6] === 'P' &&\n xmlData[i + 7] === 'E'\n ) {\n let angleBracketsCount = 1;\n for (i += 8; i < xmlData.length; i++) {\n if (xmlData[i] === '<') {\n angleBracketsCount++;\n } else if (xmlData[i] === '>') {\n angleBracketsCount--;\n if (angleBracketsCount === 0) {\n break;\n }\n }\n }\n } else if (\n xmlData.length > i + 9 &&\n xmlData[i + 1] === '[' &&\n xmlData[i + 2] === 'C' &&\n xmlData[i + 3] === 'D' &&\n xmlData[i + 4] === 'A' &&\n xmlData[i + 5] === 'T' &&\n xmlData[i + 6] === 'A' &&\n xmlData[i + 7] === '['\n ) {\n for (i += 8; i < xmlData.length; i++) {\n if (xmlData[i] === ']' && xmlData[i + 1] === ']' && xmlData[i + 2] === '>') {\n i += 2;\n break;\n }\n }\n }\n\n return i;\n}\n\nconst doubleQuote = '\"';\nconst singleQuote = \"'\";\n\n/**\n * Keep reading xmlData until '<' is found outside the attribute value.\n * @param {string} xmlData\n * @param {number} i\n */\nfunction readAttributeStr(xmlData, i) {\n let attrStr = '';\n let startChar = '';\n let tagClosed = false;\n for (; i < xmlData.length; i++) {\n if (xmlData[i] === doubleQuote || xmlData[i] === singleQuote) {\n if (startChar === '') {\n startChar = xmlData[i];\n } else if (startChar !== xmlData[i]) {\n //if vaue is enclosed with double quote then single quotes are allowed inside the value and vice versa\n } else {\n startChar = '';\n }\n } else if (xmlData[i] === '>') {\n if (startChar === '') {\n tagClosed = true;\n break;\n }\n }\n attrStr += xmlData[i];\n }\n if (startChar !== '') {\n return false;\n }\n\n return {\n value: attrStr,\n index: i,\n tagClosed: tagClosed\n };\n}\n\n/**\n * Select all the attributes whether valid or invalid.\n */\nconst validAttrStrRegxp = new RegExp('(\\\\s*)([^\\\\s=]+)(\\\\s*=)?(\\\\s*([\\'\"])(([\\\\s\\\\S])*?)\\\\5)?', 'g');\n\n//attr, =\"sd\", a=\"amit's\", a=\"sd\"b=\"saf\", ab cd=\"\"\n\nfunction validateAttributeString(attrStr, options) {\n //console.log(\"start:\"+attrStr+\":end\");\n\n //if(attrStr.trim().length === 0) return true; //empty string\n\n const matches = getAllMatches(attrStr, validAttrStrRegxp);\n const attrNames = {};\n\n for (let i = 0; i < matches.length; i++) {\n if (matches[i][1].length === 0) {\n //nospace before attribute name: a=\"sd\"b=\"saf\"\n return getErrorObject('InvalidAttr', \"Attribute '\" + matches[i][2] + \"' has no space in starting.\", getPositionFromMatch(matches[i]))\n } else if (matches[i][3] !== undefined && matches[i][4] === undefined) {\n return getErrorObject('InvalidAttr', \"Attribute '\" + matches[i][2] + \"' is without value.\", getPositionFromMatch(matches[i]));\n } else if (matches[i][3] === undefined && !options.allowBooleanAttributes) {\n //independent attribute: ab\n return getErrorObject('InvalidAttr', \"boolean attribute '\" + matches[i][2] + \"' is not allowed.\", getPositionFromMatch(matches[i]));\n }\n /* else if(matches[i][6] === undefined){//attribute without value: ab=\n return { err: { code:\"InvalidAttr\",msg:\"attribute \" + matches[i][2] + \" has no value assigned.\"}};\n } */\n const attrName = matches[i][2];\n if (!validateAttrName(attrName)) {\n return getErrorObject('InvalidAttr', \"Attribute '\" + attrName + \"' is an invalid name.\", getPositionFromMatch(matches[i]));\n }\n if (!Object.prototype.hasOwnProperty.call(attrNames, attrName)) {\n //check for duplicate attribute.\n attrNames[attrName] = 1;\n } else {\n return getErrorObject('InvalidAttr', \"Attribute '\" + attrName + \"' is repeated.\", getPositionFromMatch(matches[i]));\n }\n }\n\n return true;\n}\n\nfunction validateNumberAmpersand(xmlData, i) {\n let re = /\\d/;\n if (xmlData[i] === 'x') {\n i++;\n re = /[\\da-fA-F]/;\n }\n for (; i < xmlData.length; i++) {\n if (xmlData[i] === ';')\n return i;\n if (!xmlData[i].match(re))\n break;\n }\n return -1;\n}\n\nfunction validateAmpersand(xmlData, i) {\n // https://www.w3.org/TR/xml/#dt-charref\n i++;\n if (xmlData[i] === ';')\n return -1;\n if (xmlData[i] === '#') {\n i++;\n return validateNumberAmpersand(xmlData, i);\n }\n let count = 0;\n for (; i < xmlData.length; i++, count++) {\n if (xmlData[i].match(/\\w/) && count < 20)\n continue;\n if (xmlData[i] === ';')\n break;\n return -1;\n }\n return i;\n}\n\nfunction getErrorObject(code, message, lineNumber) {\n return {\n err: {\n code: code,\n msg: message,\n line: lineNumber.line || lineNumber,\n col: lineNumber.col,\n },\n };\n}\n\nfunction validateAttrName(attrName) {\n return isName(attrName);\n}\n\n// const startsWithXML = /^xml/i;\n\nfunction validateTagName(tagname) {\n return isName(tagname) /* && !tagname.match(startsWithXML) */;\n}\n\n//this function returns the line number for the character at the given index\nfunction getLineNumberForPosition(xmlData, index) {\n const lines = xmlData.substring(0, index).split(/\\r?\\n/);\n return {\n line: lines.length,\n\n // column number is last line's length + 1, because column numbering starts at 1:\n col: lines[lines.length - 1].length + 1\n };\n}\n\n//this function returns the position of the first character of match within attrStr\nfunction getPositionFromMatch(match) {\n return match.startIndex + match[1].length;\n}\n","// ---------------------------------------------------------------------------\n// Complete HTML5 named entity reference\n// Organized by logical categories for easy maintenance and selective importing\n// ---------------------------------------------------------------------------\n\n/**\n * Basic Latin & Special Characters\n * @type {Record<string, string>}\n */\nexport const BASIC_LATIN = {\n amp: '&',\n AMP: '&',\n lt: '<',\n LT: '<',\n gt: '>',\n GT: '>',\n quot: '\"',\n QUOT: '\"',\n apos: \"'\",\n lsquo: '‘',\n rsquo: '’',\n ldquo: '“',\n rdquo: '”',\n lsquor: '‚',\n rsquor: '’',\n ldquor: '„',\n bdquo: '„',\n comma: ',',\n period: '.',\n colon: ':',\n semi: ';',\n excl: '!',\n quest: '?',\n num: '#',\n dollar: '$',\n percent: '%',\n amp: '&',\n ast: '*',\n commat: '@',\n lowbar: '_',\n verbar: '|',\n vert: '|',\n sol: '/',\n bsol: '\\\\',\n lbrace: '{',\n rbrace: '}',\n lbrack: '[',\n rbrack: ']',\n lpar: '(',\n rpar: ')',\n nbsp: '\\u00a0',\n iexcl: '¡',\n cent: '¢',\n pound: '£',\n curren: '¤',\n yen: '¥',\n brvbar: '¦',\n sect: '§',\n uml: '¨',\n copy: '©',\n COPY: '©',\n ordf: 'ª',\n laquo: '«',\n not: '¬',\n shy: '\\u00ad',\n reg: '®',\n REG: '®',\n macr: '¯',\n deg: '°',\n plusmn: '±',\n sup2: '²',\n sup3: '³',\n acute: '´',\n micro: 'µ',\n para: '¶',\n middot: '·',\n cedil: '¸',\n sup1: '¹',\n ordm: 'º',\n raquo: '»',\n frac14: '¼',\n frac12: '½',\n half: '½',\n frac34: '¾',\n iquest: '¿',\n times: '×',\n div: '÷',\n divide: '÷',\n};\n\n/**\n * Latin Extended & Accented Letters (A-Z)\n * @type {Record<string, string>}\n */\nexport const LATIN_ACCENTS = {\n Agrave: 'À',\n agrave: 'à',\n Aacute: 'Á',\n aacute: 'á',\n Acirc: 'Â',\n acirc: 'â',\n Atilde: 'Ã',\n atilde: 'ã',\n Auml: 'Ä',\n auml: 'ä',\n Aring: 'Å',\n aring: 'å',\n AElig: 'Æ',\n aelig: 'æ',\n Ccedil: 'Ç',\n ccedil: 'ç',\n Egrave: 'È',\n egrave: 'è',\n Eacute: 'É',\n eacute: 'é',\n Ecirc: 'Ê',\n ecirc: 'ê',\n Euml: 'Ë',\n euml: 'ë',\n Igrave: 'Ì',\n igrave: 'ì',\n Iacute: 'Í',\n iacute: 'í',\n Icirc: 'Î',\n icirc: 'î',\n Iuml: 'Ï',\n iuml: 'ï',\n ETH: 'Ð',\n eth: 'ð',\n Ntilde: 'Ñ',\n ntilde: 'ñ',\n Ograve: 'Ò',\n ograve: 'ò',\n Oacute: 'Ó',\n oacute: 'ó',\n Ocirc: 'Ô',\n ocirc: 'ô',\n Otilde: 'Õ',\n otilde: 'õ',\n Ouml: 'Ö',\n ouml: 'ö',\n Oslash: 'Ø',\n oslash: 'ø',\n Ugrave: 'Ù',\n ugrave: 'ù',\n Uacute: 'Ú',\n uacute: 'ú',\n Ucirc: 'Û',\n ucirc: 'û',\n Uuml: 'Ü',\n uuml: 'ü',\n Yacute: 'Ý',\n yacute: 'ý',\n THORN: 'Þ',\n thorn: 'þ',\n szlig: 'ß',\n yuml: 'ÿ',\n Yuml: 'Ÿ',\n};\n\n/**\n * Latin Extended (Letters with diacritics)\n * @type {Record<string, string>}\n */\nexport const LATIN_EXTENDED = {\n Amacr: 'Ā',\n amacr: 'ā',\n Abreve: 'Ă',\n abreve: 'ă',\n Aogon: 'Ą',\n aogon: 'ą',\n Cacute: 'Ć',\n cacute: 'ć',\n Ccirc: 'Ĉ',\n ccirc: 'ĉ',\n Cdot: 'Ċ',\n cdot: 'ċ',\n Ccaron: 'Č',\n ccaron: 'č',\n Dcaron: 'Ď',\n dcaron: 'ď',\n Dstrok: 'Đ',\n dstrok: 'đ',\n Emacr: 'Ē',\n emacr: 'ē',\n Ecaron: 'Ě',\n ecaron: 'ě',\n Edot: 'Ė',\n edot: 'ė',\n Eogon: 'Ę',\n eogon: 'ę',\n Gcirc: 'Ĝ',\n gcirc: 'ĝ',\n Gbreve: 'Ğ',\n gbreve: 'ğ',\n Gdot: 'Ġ',\n gdot: 'ġ',\n Gcedil: 'Ģ',\n Hcirc: 'Ĥ',\n hcirc: 'ĥ',\n Hstrok: 'Ħ',\n hstrok: 'ħ',\n Itilde: 'Ĩ',\n itilde: 'ĩ',\n Imacr: 'Ī',\n imacr: 'ī',\n Iogon: 'Į',\n iogon: 'į',\n Idot: 'İ',\n IJlig: 'IJ',\n ijlig: 'ij',\n Jcirc: 'Ĵ',\n jcirc: 'ĵ',\n Kcedil: 'Ķ',\n kcedil: 'ķ',\n kgreen: 'ĸ',\n Lacute: 'Ĺ',\n lacute: 'ĺ',\n Lcedil: 'Ļ',\n lcedil: 'ļ',\n Lcaron: 'Ľ',\n lcaron: 'ľ',\n Lmidot: 'Ŀ',\n lmidot: 'ŀ',\n Lstrok: 'Ł',\n lstrok: 'ł',\n Nacute: 'Ń',\n nacute: 'ń',\n Ncaron: 'Ň',\n ncaron: 'ň',\n Ncedil: 'Ņ',\n ncedil: 'ņ',\n ENG: 'Ŋ',\n eng: 'ŋ',\n Omacr: 'Ō',\n omacr: 'ō',\n Odblac: 'Ő',\n odblac: 'ő',\n OElig: 'Œ',\n oelig: 'œ',\n Racute: 'Ŕ',\n racute: 'ŕ',\n Rcaron: 'Ř',\n rcaron: 'ř',\n Rcedil: 'Ŗ',\n rcedil: 'ŗ',\n Sacute: 'Ś',\n sacute: 'ś',\n Scirc: 'Ŝ',\n scirc: 'ŝ',\n Scedil: 'Ş',\n scedil: 'ş',\n Scaron: 'Š',\n scaron: 'š',\n Tcedil: 'Ţ',\n tcedil: 'ţ',\n Tcaron: 'Ť',\n tcaron: 'ť',\n Tstrok: 'Ŧ',\n tstrok: 'ŧ',\n Utilde: 'Ũ',\n utilde: 'ũ',\n Umacr: 'Ū',\n umacr: 'ū',\n Ubreve: 'Ŭ',\n ubreve: 'ŭ',\n Uring: 'Ů',\n uring: 'ů',\n Udblac: 'Ű',\n udblac: 'ű',\n Uogon: 'Ų',\n uogon: 'ų',\n Wcirc: 'Ŵ',\n wcirc: 'ŵ',\n Ycirc: 'Ŷ',\n ycirc: 'ŷ',\n Zacute: 'Ź',\n zacute: 'ź',\n Zdot: 'Ż',\n zdot: 'ż',\n Zcaron: 'Ž',\n zcaron: 'ž',\n};\n\n/**\n * Greek Letters\n * @type {Record<string, string>}\n */\nexport const GREEK = {\n Alpha: 'Α',\n alpha: 'α',\n Beta: 'Β',\n beta: 'β',\n Gamma: 'Γ',\n gamma: 'γ',\n Delta: 'Δ',\n delta: 'δ',\n Epsilon: 'Ε',\n epsilon: 'ε',\n epsiv: 'ϵ',\n varepsilon: 'ϵ',\n Zeta: 'Ζ',\n zeta: 'ζ',\n Eta: 'Η',\n eta: 'η',\n Theta: 'Θ',\n theta: 'θ',\n thetasym: 'ϑ',\n vartheta: 'ϑ',\n Iota: 'Ι',\n iota: 'ι',\n Kappa: 'Κ',\n kappa: 'κ',\n kappav: 'ϰ',\n varkappa: 'ϰ',\n Lambda: 'Λ',\n lambda: 'λ',\n Mu: 'Μ',\n mu: 'μ',\n Nu: 'Ν',\n nu: 'ν',\n Xi: 'Ξ',\n xi: 'ξ',\n Omicron: 'Ο',\n omicron: 'ο',\n Pi: 'Π',\n pi: 'π',\n piv: 'ϖ',\n varpi: 'ϖ',\n Rho: 'Ρ',\n rho: 'ρ',\n rhov: 'ϱ',\n varrho: 'ϱ',\n Sigma: 'Σ',\n sigma: 'σ',\n sigmaf: 'ς',\n sigmav: 'ς',\n varsigma: 'ς',\n Tau: 'Τ',\n tau: 'τ',\n Upsilon: 'Υ',\n upsilon: 'υ',\n upsi: 'υ',\n Upsi: 'ϒ',\n upsih: 'ϒ',\n Phi: 'Φ',\n phi: 'φ',\n phiv: 'ϕ',\n varphi: 'ϕ',\n Chi: 'Χ',\n chi: 'χ',\n Psi: 'Ψ',\n psi: 'ψ',\n Omega: 'Ω',\n omega: 'ω',\n ohm: 'Ω',\n Gammad: 'Ϝ',\n gammad: 'ϝ',\n digamma: 'ϝ',\n};\n\n/**\n * Cyrillic Letters\n * @type {Record<string, string>}\n */\nexport const CYRILLIC = {\n Afr: '𝔄',\n afr: '𝔞',\n Acy: 'А',\n acy: 'а',\n Bcy: 'Б',\n bcy: 'б',\n Vcy: 'В',\n vcy: 'в',\n Gcy: 'Г',\n gcy: 'г',\n Dcy: 'Д',\n dcy: 'д',\n IEcy: 'Е',\n iecy: 'е',\n IOcy: 'Ё',\n iocy: 'ё',\n ZHcy: 'Ж',\n zhcy: 'ж',\n Zcy: 'З',\n zcy: 'з',\n Icy: 'И',\n icy: 'и',\n Jcy: 'Й',\n jcy: 'й',\n Kcy: 'К',\n kcy: 'к',\n Lcy: 'Л',\n lcy: 'л',\n Mcy: 'М',\n mcy: 'м',\n Ncy: 'Н',\n ncy: 'н',\n Ocy: 'О',\n ocy: 'о',\n Pcy: 'П',\n pcy: 'п',\n Rcy: 'Р',\n rcy: 'р',\n Scy: 'С',\n scy: 'с',\n Tcy: 'Т',\n tcy: 'т',\n Ucy: 'У',\n ucy: 'у',\n Fcy: 'Ф',\n fcy: 'ф',\n KHcy: 'Х',\n khcy: 'х',\n TScy: 'Ц',\n tscy: 'ц',\n CHcy: 'Ч',\n chcy: 'ч',\n SHcy: 'Ш',\n shcy: 'ш',\n SHCHcy: 'Щ',\n shchcy: 'щ',\n HARDcy: 'Ъ',\n hardcy: 'ъ',\n Ycy: 'Ы',\n ycy: 'ы',\n SOFTcy: 'Ь',\n softcy: 'ь',\n Ecy: 'Э',\n ecy: 'э',\n YUcy: 'Ю',\n yucy: 'ю',\n YAcy: 'Я',\n yacy: 'я',\n DJcy: 'Ђ',\n djcy: 'ђ',\n GJcy: 'Ѓ',\n gjcy: 'ѓ',\n Jukcy: 'Є',\n jukcy: 'є',\n DScy: 'Ѕ',\n dscy: 'ѕ',\n Iukcy: 'І',\n iukcy: 'і',\n YIcy: 'Ї',\n yicy: 'ї',\n Jsercy: 'Ј',\n jsercy: 'ј',\n LJcy: 'Љ',\n ljcy: 'љ',\n NJcy: 'Њ',\n njcy: 'њ',\n TSHcy: 'Ћ',\n tshcy: 'ћ',\n KJcy: 'Ќ',\n kjcy: 'ќ',\n Ubrcy: 'Ў',\n ubrcy: 'ў',\n DZcy: 'Џ',\n dzcy: 'џ',\n};\n\n/**\n * Mathematical Operators & Relations\n * @type {Record<string, string>}\n */\nexport const MATH = {\n plus: '+',\n minus: '−',\n mnplus: '∓',\n mp: '∓',\n pm: '±',\n times: '×',\n div: '÷',\n divide: '÷',\n sdot: '⋅',\n star: '☆',\n starf: '★',\n bigstar: '★',\n lowast: '∗',\n ast: '*',\n midast: '*',\n compfn: '∘',\n smallcircle: '∘',\n bullet: '•',\n bull: '•',\n nbsp: '\\u00a0',\n hellip: '…',\n mldr: '…',\n prime: '′',\n Prime: '″',\n tprime: '‴',\n bprime: '‵',\n backprime: '‵',\n minus: '−',\n minusd: '∸',\n dotminus: '∸',\n plusdo: '∔',\n dotplus: '∔',\n plusmn: '±',\n minusplus: '∓',\n mnplus: '∓',\n mp: '∓',\n setminus: '∖',\n smallsetminus: '∖',\n Backslash: '∖',\n setmn: '∖',\n ssetmn: '∖',\n lowbar: '_',\n verbar: '|',\n vert: '|',\n VerticalLine: '|',\n colon: ':',\n Colon: '∷',\n Proportion: '∷',\n ratio: '∶',\n equals: '=',\n ne: '≠',\n nequiv: '≢',\n equiv: '≡',\n Congruent: '≡',\n sim: '∼',\n thicksim: '∼',\n thksim: '∼',\n sime: '≃',\n simeq: '≃',\n TildeEqual: '≃',\n asymp: '≈',\n approx: '≈',\n thickapprox: '≈',\n thkap: '≈',\n TildeTilde: '≈',\n ncong: '≇',\n cong: '≅',\n TildeFullEqual: '≅',\n asympeq: '≍',\n CupCap: '≍',\n bump: '≎',\n Bumpeq: '≎',\n HumpDownHump: '≎',\n bumpe: '≏',\n bumpeq: '≏',\n HumpEqual: '≏',\n dotminus: '∸',\n minusd: '∸',\n plusdo: '∔',\n dotplus: '∔',\n le: '≤',\n LessEqual: '≤',\n ge: '≥',\n GreaterEqual: '≥',\n lesseqgtr: '⋚',\n lesseqqgtr: '⪋',\n greater: '>',\n less: '<',\n};\n\n/**\n * Mathematical Operators (Advanced)\n * @type {Record<string, string>}\n */\nexport const MATH_ADVANCED = {\n alefsym: 'ℵ',\n aleph: 'ℵ',\n beth: 'ℶ',\n gimel: 'ℷ',\n daleth: 'ℸ',\n forall: '∀',\n ForAll: '∀',\n part: '∂',\n PartialD: '∂',\n exist: '∃',\n Exists: '∃',\n nexist: '∄',\n nexists: '∄',\n empty: '∅',\n emptyset: '∅',\n emptyv: '∅',\n varnothing: '∅',\n nabla: '∇',\n Del: '∇',\n isin: '∈',\n isinv: '∈',\n in: '∈',\n Element: '∈',\n notin: '∉',\n notinva: '∉',\n ni: '∋',\n niv: '∋',\n SuchThat: '∋',\n ReverseElement: '∋',\n notni: '∌',\n notniva: '∌',\n prod: '∏',\n Product: '∏',\n coprod: '∐',\n Coproduct: '∐',\n sum: '∑',\n Sum: '∑',\n minus: '−',\n mp: '∓',\n plusdo: '∔',\n dotplus: '∔',\n setminus: '∖',\n lowast: '∗',\n radic: '√',\n Sqrt: '√',\n prop: '∝',\n propto: '∝',\n Proportional: '∝',\n varpropto: '∝',\n infin: '∞',\n infintie: '⧝',\n ang: '∠',\n angle: '∠',\n angmsd: '∡',\n measuredangle: '∡',\n angsph: '∢',\n mid: '∣',\n VerticalBar: '∣',\n nmid: '∤',\n nsmid: '∤',\n npar: '∦',\n parallel: '∥',\n spar: '∥',\n nparallel: '∦',\n nspar: '∦',\n and: '∧',\n wedge: '∧',\n or: '∨',\n vee: '∨',\n cap: '∩',\n cup: '∪',\n int: '∫',\n Integral: '∫',\n conint: '∮',\n ContourIntegral: '∮',\n Conint: '∯',\n DoubleContourIntegral: '∯',\n Cconint: '∰',\n there4: '∴',\n therefore: '∴',\n Therefore: '∴',\n becaus: '∵',\n because: '∵',\n Because: '∵',\n ratio: '∶',\n Proportion: '∷',\n minusd: '∸',\n dotminus: '∸',\n mDDot: '∺',\n homtht: '∻',\n sim: '∼',\n bsimg: '∽',\n backsim: '∽',\n ac: '∾',\n mstpos: '∾',\n acd: '∿',\n VerticalTilde: '≀',\n wr: '≀',\n wreath: '≀',\n nsime: '≄',\n nsimeq: '≄',\n nsimeq: '≄',\n ncong: '≇',\n simne: '≆',\n ncongdot: '⩭̸',\n ngsim: '≵',\n nsim: '≁',\n napprox: '≉',\n nap: '≉',\n ngeq: '≱',\n nge: '≱',\n nleq: '≰',\n nle: '≰',\n ngtr: '≯',\n ngt: '≯',\n nless: '≮',\n nlt: '≮',\n nprec: '⊀',\n npr: '⊀',\n nsucc: '⊁',\n nsc: '⊁',\n};\n\n/**\n * Arrows\n * @type {Record<string, string>}\n */\nexport const ARROWS = {\n larr: '←',\n leftarrow: '←',\n LeftArrow: '←',\n uarr: '↑',\n uparrow: '↑',\n UpArrow: '↑',\n rarr: '→',\n rightarrow: '→',\n RightArrow: '→',\n darr: '↓',\n downarrow: '↓',\n DownArrow: '↓',\n harr: '↔',\n leftrightarrow: '↔',\n LeftRightArrow: '↔',\n varr: '↕',\n updownarrow: '↕',\n UpDownArrow: '↕',\n nwarr: '↖',\n nwarrow: '↖',\n UpperLeftArrow: '↖',\n nearr: '↗',\n nearrow: '↗',\n UpperRightArrow: '↗',\n searr: '↘',\n searrow: '↘',\n LowerRightArrow: '↘',\n swarr: '↙',\n swarrow: '↙',\n LowerLeftArrow: '↙',\n lArr: '⇐',\n Leftarrow: '⇐',\n uArr: '⇑',\n Uparrow: '⇑',\n rArr: '⇒',\n Rightarrow: '⇒',\n dArr: '⇓',\n Downarrow: '⇓',\n hArr: '⇔',\n Leftrightarrow: '⇔',\n iff: '⇔',\n vArr: '⇕',\n Updownarrow: '⇕',\n lAarr: '⇚',\n Lleftarrow: '⇚',\n rAarr: '⇛',\n Rrightarrow: '⇛',\n lrarr: '⇆',\n leftrightarrows: '⇆',\n rlarr: '⇄',\n rightleftarrows: '⇄',\n lrhar: '⇋',\n leftrightharpoons: '⇋',\n ReverseEquilibrium: '⇋',\n rlhar: '⇌',\n rightleftharpoons: '⇌',\n Equilibrium: '⇌',\n udarr: '⇅',\n UpArrowDownArrow: '⇅',\n duarr: '⇵',\n DownArrowUpArrow: '⇵',\n llarr: '⇇',\n leftleftarrows: '⇇',\n rrarr: '⇉',\n rightrightarrows: '⇉',\n ddarr: '⇊',\n downdownarrows: '⇊',\n har: '↽',\n lhard: '↽',\n leftharpoondown: '↽',\n lharu: '↼',\n leftharpoonup: '↼',\n rhard: '⇁',\n rightharpoondown: '⇁',\n rharu: '⇀',\n rightharpoonup: '⇀',\n lsh: '↰',\n Lsh: '↰',\n rsh: '↱',\n Rsh: '↱',\n ldsh: '↲',\n rdsh: '↳',\n hookleftarrow: '↩',\n hookrightarrow: '↪',\n mapstoleft: '↤',\n mapstoup: '↥',\n map: '↦',\n mapsto: '↦',\n mapstodown: '↧',\n crarr: '↵',\n nwarrow: '↖',\n nearrow: '↗',\n searrow: '↘',\n swarrow: '↙',\n nleftarrow: '↚',\n nleftrightarrow: '↮',\n nrightarrow: '↛',\n nrarr: '↛',\n larrtl: '↢',\n rarrtl: '↣',\n leftarrowtail: '↢',\n rightarrowtail: '↣',\n twoheadleftarrow: '↞',\n twoheadrightarrow: '↠',\n Larr: '↞',\n Rarr: '↠',\n larrhk: '↩',\n rarrhk: '↪',\n larrlp: '↫',\n looparrowleft: '↫',\n rarrlp: '↬',\n looparrowright: '↬',\n harrw: '↭',\n leftrightsquigarrow: '↭',\n nrarrw: '↝̸',\n rarrw: '↝',\n rightsquigarrow: '↝',\n larrbfs: '⤟',\n rarrbfs: '⤠',\n nvHarr: '⤄',\n nvlArr: '⤂',\n nvrArr: '⤃',\n larrfs: '⤝',\n rarrfs: '⤞',\n Map: '⤅',\n larrsim: '⥳',\n rarrsim: '⥴',\n harrcir: '⥈',\n Uarrocir: '⥉',\n lurdshar: '⥊',\n ldrdhar: '⥧',\n ldrushar: '⥋',\n rdldhar: '⥩',\n lrhard: '⥭',\n rlhar: '⇌',\n uharr: '↾',\n uharl: '↿',\n dharr: '⇂',\n dharl: '⇃',\n Uarr: '↟',\n Darr: '↡',\n zigrarr: '⇝',\n nwArr: '⇖',\n neArr: '⇗',\n seArr: '⇘',\n swArr: '⇙',\n nharr: '↮',\n nhArr: '⇎',\n nlarr: '↚',\n nlArr: '⇍',\n nrarr: '↛',\n nrArr: '⇏',\n larrb: '⇤',\n LeftArrowBar: '⇤',\n rarrb: '⇥',\n RightArrowBar: '⇥',\n};\n\n/**\n * Geometric Shapes\n * @type {Record<string, string>}\n */\nexport const SHAPES = {\n square: '□',\n Square: '□',\n squ: '□',\n squf: '▪',\n squarf: '▪',\n blacksquar: '▪',\n blacksquare: '▪',\n FilledVerySmallSquare: '▪',\n blk34: '▓',\n blk12: '▒',\n blk14: '░',\n block: '█',\n srect: '▭',\n rect: '▭',\n sdot: '⋅',\n sdotb: '⊡',\n dotsquare: '⊡',\n triangle: '▵',\n tri: '▵',\n trine: '▵',\n utri: '▵',\n triangledown: '▿',\n dtri: '▿',\n tridown: '▿',\n triangleleft: '◃',\n ltri: '◃',\n triangleright: '▹',\n rtri: '▹',\n blacktriangle: '▴',\n utrif: '▴',\n blacktriangledown: '▾',\n dtrif: '▾',\n blacktriangleleft: '◂',\n ltrif: '◂',\n blacktriangleright: '▸',\n rtrif: '▸',\n loz: '◊',\n lozenge: '◊',\n blacklozenge: '⧫',\n lozf: '⧫',\n bigcirc: '◯',\n xcirc: '◯',\n circ: 'ˆ',\n Circle: '○',\n cir: '○',\n o: '○',\n bullet: '•',\n bull: '•',\n hellip: '…',\n mldr: '…',\n nldr: '‥',\n boxh: '─',\n HorizontalLine: '─',\n boxv: '│',\n boxdr: '┌',\n boxdl: '┐',\n boxur: '└',\n boxul: '┘',\n boxvr: '├',\n boxvl: '┤',\n boxhd: '┬',\n boxhu: '┴',\n boxvh: '┼',\n boxH: '═',\n boxV: '║',\n boxdR: '╒',\n boxDr: '╓',\n boxDR: '╔',\n boxDl: '╕',\n boxdL: '╖',\n boxDL: '╗',\n boxuR: '╘',\n boxUr: '╙',\n boxUR: '╚',\n boxUl: '╜',\n boxuL: '╛',\n boxUL: '╝',\n boxvR: '╞',\n boxVr: '╟',\n boxVR: '╠',\n boxVl: '╢',\n boxvL: '╡',\n boxVL: '╣',\n boxHd: '╤',\n boxhD: '╥',\n boxHD: '╦',\n boxHu: '╧',\n boxhU: '╨',\n boxHU: '╩',\n boxvH: '╪',\n boxVh: '╫',\n boxVH: '╬',\n};\n\n/**\n * Punctuation & Diacritics\n * @type {Record<string, string>}\n */\nexport const PUNCTUATION = {\n excl: '!',\n iexcl: '¡',\n brvbar: '¦',\n sect: '§',\n uml: '¨',\n copy: '©',\n ordf: 'ª',\n laquo: '«',\n not: '¬',\n shy: '\\u00ad',\n reg: '®',\n macr: '¯',\n deg: '°',\n plusmn: '±',\n sup2: '²',\n sup3: '³',\n acute: '´',\n micro: 'µ',\n para: '¶',\n middot: '·',\n cedil: '¸',\n sup1: '¹',\n ordm: 'º',\n raquo: '»',\n frac14: '¼',\n frac12: '½',\n frac34: '¾',\n iquest: '¿',\n nbsp: '\\u00a0',\n comma: ',',\n period: '.',\n colon: ':',\n semi: ';',\n vert: '|',\n Verbar: '‖',\n verbar: '|',\n dblac: '˝',\n circ: 'ˆ',\n caron: 'ˇ',\n breve: '˘',\n dot: '˙',\n ring: '˚',\n ogon: '˛',\n tilde: '˜',\n DiacriticalGrave: '`',\n DiacriticalAcute: '´',\n DiacriticalTilde: '˜',\n DiacriticalDot: '˙',\n DiacriticalDoubleAcute: '˝',\n grave: '`',\n acute: '´',\n};\n\n/**\n * Currency Symbols\n * @type {Record<string, string>}\n */\nexport const CURRENCY = {\n cent: '¢',\n pound: '£',\n curren: '¤',\n yen: '¥',\n euro: '€',\n dollar: '$',\n euro: '€',\n fnof: 'ƒ',\n inr: '₹',\n af: '؋',\n birr: 'ብር',\n peso: '₱',\n rub: '₽',\n won: '₩',\n yuan: '¥',\n cedil: '¸',\n};\n\n/**\n * Fractions\n * @type {Record<string, string>}\n */\nexport const FRACTIONS = {\n frac12: '½',\n half: '½',\n frac13: '⅓',\n frac14: '¼',\n frac15: '⅕',\n frac16: '⅙',\n frac18: '⅛',\n frac23: '⅔',\n frac25: '⅖',\n frac34: '¾',\n frac35: '⅗',\n frac38: '⅜',\n frac45: '⅘',\n frac56: '⅚',\n frac58: '⅝',\n frac78: '⅞',\n frasl: '⁄',\n};\n\n/**\n * Miscellaneous Symbols\n * @type {Record<string, string>}\n */\nexport const MISC_SYMBOLS = {\n trade: '™',\n TRADE: '™',\n telrec: '⌕',\n target: '⌖',\n ulcorn: '⌜',\n ulcorner: '⌜',\n urcorn: '⌝',\n urcorner: '⌝',\n dlcorn: '⌞',\n llcorner: '⌞',\n drcorn: '⌟',\n lrcorner: '⌟',\n intercal: '⊺',\n intcal: '⊺',\n oplus: '⊕',\n CirclePlus: '⊕',\n ominus: '⊖',\n CircleMinus: '⊖',\n otimes: '⊗',\n CircleTimes: '⊗',\n osol: '⊘',\n odot: '⊙',\n CircleDot: '⊙',\n oast: '⊛',\n circledast: '⊛',\n odash: '⊝',\n circleddash: '⊝',\n ocirc: '⊚',\n circledcirc: '⊚',\n boxplus: '⊞',\n plusb: '⊞',\n boxminus: '⊟',\n minusb: '⊟',\n boxtimes: '⊠',\n timesb: '⊠',\n boxdot: '⊡',\n sdotb: '⊡',\n veebar: '⊻',\n vee: '∨',\n barvee: '⊽',\n and: '∧',\n wedge: '∧',\n Cap: '⋒',\n Cup: '⋓',\n Fork: '⋔',\n pitchfork: '⋔',\n epar: '⋕',\n ltlarr: '⥶',\n nvap: '≍⃒',\n nvsim: '∼⃒',\n nvge: '≥⃒',\n nvle: '≤⃒',\n nvlt: '<⃒',\n nvgt: '>⃒',\n nvltrie: '⊴⃒',\n nvrtrie: '⊵⃒',\n Vdash: '⊩',\n dashv: '⊣',\n vDash: '⊨',\n Vdash: '⊩',\n Vvdash: '⊪',\n nvdash: '⊬',\n nvDash: '⊭',\n nVdash: '⊮',\n nVDash: '⊯',\n};\n\n/**\n * All entities combined (if you need everything)\n * @type {Record<string, string>}\n */\nexport const ALL_ENTITIES = {\n ...BASIC_LATIN,\n ...LATIN_ACCENTS,\n ...LATIN_EXTENDED,\n ...GREEK,\n ...CYRILLIC,\n ...MATH,\n ...MATH_ADVANCED,\n ...ARROWS,\n ...SHAPES,\n ...PUNCTUATION,\n ...CURRENCY,\n ...FRACTIONS,\n ...MISC_SYMBOLS,\n};\n\nexport const XML = {\n amp: \"&\",\n apos: \"'\",\n gt: \">\",\n lt: \"<\",\n quot: \"\\\"\"\n}\nexport const COMMON_HTML = {\n nbsp: '\\u00a0',\n copy: '\\u00a9',\n reg: '\\u00ae',\n trade: '\\u2122',\n mdash: '\\u2014',\n ndash: '\\u2013',\n hellip: '\\u2026',\n laquo: '\\u00ab',\n raquo: '\\u00bb',\n lsquo: '\\u2018',\n rsquo: '\\u2019',\n ldquo: '\\u201c',\n rdquo: '\\u201d',\n bull: '\\u2022',\n para: '\\u00b6',\n sect: '\\u00a7',\n deg: '\\u00b0',\n frac12: '\\u00bd',\n frac14: '\\u00bc',\n frac34: '\\u00be',\n}\n// ---------------------------------------------------------------------------\n// Note: NUMERIC_ENTITIES (&#NNN; / &#xHH;) are handled by the scanner directly\n// via String.fromCodePoint() without any map lookup.\n// ---------------------------------------------------------------------------","// ---------------------------------------------------------------------------\n// Built-in named entity map (name → replacement string)\n// No regex, no {regex,val} objects — just flat key/value pairs.\n// ---------------------------------------------------------------------------\n\nimport { XML as DEFAULT_XML_ENTITIES } from \"./entities.js\"\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nconst SPECIAL_CHARS = new Set('!?\\\\\\\\/[]$%{}^&*()<>|+');\n\n/**\n * Validate that an entity name contains no dangerous characters.\n * @param {string} name\n * @returns {string} the name, unchanged\n * @throws {Error} on invalid characters\n */\nfunction validateEntityName(name) {\n if (name[0] === '#') {\n throw new Error(`[EntityReplacer] Invalid character '#' in entity name: \"${name}\"`);\n }\n for (const ch of name) {\n if (SPECIAL_CHARS.has(ch)) {\n throw new Error(`[EntityReplacer] Invalid character '${ch}' in entity name: \"${name}\"`);\n }\n }\n return name;\n}\n\n/**\n * Merge one or more entity maps into a flat name→string map.\n * Accepts either:\n * - plain string values: { amp: '&' }\n * - legacy {regex,val} / {regx,val}: { lt: { regex: /.../, val: '<' } }\n *\n * Values containing '&' are skipped (recursive expansion risk).\n *\n * @param {...object} maps\n * @returns {Record<string, string>}\n */\nfunction mergeEntityMaps(...maps) {\n const out = Object.create(null);\n for (const map of maps) {\n if (!map) continue;\n for (const key of Object.keys(map)) {\n const raw = map[key];\n if (typeof raw === 'string') {\n out[key] = raw;\n } else if (raw && typeof raw === 'object' && raw.val !== undefined) {\n // Legacy {regex,val} or {regx,val} — extract the string val only\n const val = raw.val;\n if (typeof val === 'string') {\n out[key] = val;\n }\n // function vals are not supported in the scanner — skip\n }\n }\n }\n return out;\n}\n\n// ---------------------------------------------------------------------------\n// applyLimitsTo helpers\n// ---------------------------------------------------------------------------\n\nconst LIMIT_TIER_EXTERNAL = 'external'; // input/runtime + persistent external maps\nconst LIMIT_TIER_BASE = 'base'; // DEFAULT_XML_ENTITIES + namedEntities (system) maps\nconst LIMIT_TIER_ALL = 'all'; // every entity regardless of tier\n\n/**\n * Resolve `applyLimitsTo` option into a normalised Set of tier strings.\n * Accepted values: 'external' | 'base' | 'all' | string[]\n * Default: 'external' (only untrusted injected entities are counted).\n * @param {string|string[]|undefined} raw\n * @returns {Set<string>}\n */\nfunction parseLimitTiers(raw) {\n if (!raw || raw === LIMIT_TIER_EXTERNAL) return new Set([LIMIT_TIER_EXTERNAL]);\n if (raw === LIMIT_TIER_ALL) return new Set([LIMIT_TIER_ALL]);\n if (raw === LIMIT_TIER_BASE) return new Set([LIMIT_TIER_BASE]);\n if (Array.isArray(raw)) return new Set(raw);\n return new Set([LIMIT_TIER_EXTERNAL]); // safe default for unrecognised values\n}\n\n// ---------------------------------------------------------------------------\n// NCR (Numeric Character Reference) classification\n// ---------------------------------------------------------------------------\n\n// Severity order — higher number = stricter action.\n// Used to enforce minimum action levels for specific codepoint ranges.\nconst NCR_LEVEL = Object.freeze({ allow: 0, leave: 1, remove: 2, throw: 3 });\n\n// XML 1.0 §2.2: allowed chars are #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]\n// Restricted C0: U+0001–U+001F excluding U+0009, U+000A, U+000D\nconst XML10_ALLOWED_C0 = new Set([0x09, 0x0A, 0x0D]);\n\n/**\n * Parse the `ncr` constructor option into flat, hot-path-friendly fields.\n * @param {object|undefined} ncr\n * @returns {{ xmlVersion: number, onLevel: number, nullLevel: number }}\n */\nfunction parseNCRConfig(ncr) {\n if (!ncr) {\n return { xmlVersion: 1.0, onLevel: NCR_LEVEL.allow, nullLevel: NCR_LEVEL.remove };\n }\n const xmlVersion = ncr.xmlVersion === 1.1 ? 1.1 : 1.0;\n const onLevel = NCR_LEVEL[ncr.onNCR] ?? NCR_LEVEL.allow;\n const nullLevel = NCR_LEVEL[ncr.nullNCR] ?? NCR_LEVEL.remove;\n // 'allow' is not meaningful for null — clamp to at least 'remove'\n const clampedNull = Math.max(nullLevel, NCR_LEVEL.remove);\n return { xmlVersion, onLevel, nullLevel: clampedNull };\n}\n\n// ---------------------------------------------------------------------------\n// EntityReplacer\n// ---------------------------------------------------------------------------\n\n/**\n * Single-pass, zero-regex entity replacer for XML/HTML content.\n *\n * Algorithm: scan the string once for '&', read to ';', resolve via map\n * or direct codepoint conversion, build output chunks, join once at the end.\n *\n * Entity lookup priority (highest → lowest):\n * 1. input / runtime (DOCTYPE entities for current document)\n * 2. persistent external (survive across documents)\n * 3. base named map (DEFAULT_XML_ENTITIES + user-supplied namedEntities)\n *\n * Both input and external resolve as the 'external' tier for limit purposes.\n * Base map entities resolve as the 'base' tier.\n *\n * Numeric / hex references (&#NNN; / &#xHH;) are resolved directly via\n * String.fromCodePoint() — no map needed. They count as 'base' tier.\n *\n * @example\n * const replacer = new EntityReplacer({ namedEntities: COMMON_HTML });\n * replacer.setExternalEntities({ brand: 'Acme' });\n *\n * const instance = replacer.reset();\n * instance.addInputEntities({ version: '1.0' });\n * instance.encode('&brand; v&version; <'); // 'Acme v1.0 <'\n */\nexport default class EntityDecoder {\n /**\n * @param {object} [options]\n * @param {object|null} [options.namedEntities] — extra named entities merged into base map\n * @param {object} [options.limit] — security limits\n * @param {number} [options.limit.maxTotalExpansions=0] — 0 = unlimited\n * @param {number} [options.limit.maxExpandedLength=0] — 0 = unlimited\n * @param {'external'|'base'|'all'|string[]} [options.limit.applyLimitsTo='external']\n * Which entity tiers count against the security limits:\n * - 'external' (default) — only input/runtime + persistent external entities\n * - 'base' — only DEFAULT_XML_ENTITIES + namedEntities\n * - 'all' — every entity regardless of tier\n * - string[] — explicit combination, e.g. ['external', 'base']\n * @param {((resolved: string, original: string) => string)|null} [options.postCheck=null]\n * @param {string[]} [options.remove=[]] — entity names (e.g. ['nbsp', '#13']) to delete (replace with empty string)\n * @param {string[]} [options.leave=[]] — entity names to keep as literal (unchanged in output)\n * @param {object} [options.ncr] — Numeric Character Reference controls\n * @param {1.0|1.1} [options.ncr.xmlVersion=1.0]\n * XML version governing which codepoint ranges are restricted:\n * - 1.0 — C0 controls U+0001–U+001F (except U+0009/000A/000D) are prohibited\n * - 1.1 — C0 controls are allowed when written as NCRs; C1 (U+007F–U+009F) decoded as-is\n * @param {'allow'|'leave'|'remove'|'throw'} [options.ncr.onNCR='allow']\n * Base action for numeric references. Severity order: allow < leave < remove < throw.\n * For codepoint ranges that carry a minimum level (surrogates → remove, XML 1.0 C0 → remove),\n * the effective action is max(onNCR, rangeMinimum).\n * @param {'remove'|'throw'} [options.ncr.nullNCR='remove']\n * Action for U+0000 (null). 'allow' and 'leave' are clamped to 'remove' since null is never safe.\n */\n constructor(options = {}) {\n this._limit = options.limit || {};\n this._maxTotalExpansions = this._limit.maxTotalExpansions || 0;\n this._maxExpandedLength = this._limit.maxExpandedLength || 0;\n this._postCheck = typeof options.postCheck === 'function' ? options.postCheck : r => r;\n this._limitTiers = parseLimitTiers(this._limit.applyLimitsTo ?? LIMIT_TIER_EXTERNAL);\n this._numericAllowed = options.numericAllowed ?? true;\n // Base map: DEFAULT_XML_ENTITIES + user-supplied extras. Immutable after construction.\n this._baseMap = mergeEntityMaps(DEFAULT_XML_ENTITIES, options.namedEntities || null);\n\n // Persistent external entities — survive across documents.\n // Stored as a separate map so reset() never touches them.\n /** @type {Record<string, string>} */\n this._externalMap = Object.create(null);\n\n // Input / runtime entities — current document only, wiped on reset().\n /** @type {Record<string, string>} */\n this._inputMap = Object.create(null);\n\n // Per-document counters\n this._totalExpansions = 0;\n this._expandedLength = 0;\n\n // --- New: remove / leave sets ---\n /** @type {Set<string>} */\n this._removeSet = new Set(options.remove && Array.isArray(options.remove) ? options.remove : []);\n /** @type {Set<string>} */\n this._leaveSet = new Set(options.leave && Array.isArray(options.leave) ? options.leave : []);\n\n // --- NCR config (parsed into flat fields for hot-path speed) ---\n const ncrCfg = parseNCRConfig(options.ncr);\n this._ncrXmlVersion = ncrCfg.xmlVersion;\n this._ncrOnLevel = ncrCfg.onLevel;\n this._ncrNullLevel = ncrCfg.nullLevel;\n }\n\n // -------------------------------------------------------------------------\n // Persistent external entity registration\n // -------------------------------------------------------------------------\n\n /**\n * Replace the full set of persistent external entities.\n * All keys are validated — throws on invalid characters.\n * @param {Record<string, string | { regex?: RegExp, val: string }>} map\n */\n setExternalEntities(map) {\n if (map) {\n for (const key of Object.keys(map)) {\n validateEntityName(key);\n }\n }\n this._externalMap = mergeEntityMaps(map);\n }\n\n /**\n * Add a single persistent external entity.\n * @param {string} key\n * @param {string} value\n */\n addExternalEntity(key, value) {\n validateEntityName(key);\n if (typeof value === 'string' && value.indexOf('&') === -1) {\n this._externalMap[key] = value;\n }\n }\n\n // -------------------------------------------------------------------------\n // Input / runtime entity registration (per document)\n // -------------------------------------------------------------------------\n\n /**\n * Inject DOCTYPE entities for the current document.\n * Also resets per-document expansion counters.\n * @param {Record<string, string | { regx?: RegExp, regex?: RegExp, val: string }>} map\n */\n addInputEntities(map) {\n this._totalExpansions = 0;\n this._expandedLength = 0;\n this._inputMap = mergeEntityMaps(map);\n }\n\n // -------------------------------------------------------------------------\n // Per-document reset\n // -------------------------------------------------------------------------\n\n /**\n * Wipe input/runtime entities and reset counters.\n * Call this before processing each new document.\n * @returns {this}\n */\n reset() {\n this._inputMap = Object.create(null);\n this._totalExpansions = 0;\n this._expandedLength = 0;\n return this;\n }\n\n // -------------------------------------------------------------------------\n // XML version (can be set after construction, e.g. once parser reads <?xml?>)\n // -------------------------------------------------------------------------\n\n /**\n * Update the XML version used for NCR classification.\n * Call this as soon as the document's `<?xml version=\"...\">` declaration is parsed.\n * @param {1.0|1.1|number} version\n */\n setXmlVersion(version) {\n this._ncrXmlVersion = version === 1.1 ? 1.1 : 1.0;\n }\n\n // -------------------------------------------------------------------------\n // Primary API\n // -------------------------------------------------------------------------\n\n /**\n * Replace all entity references in `str` in a single pass.\n *\n * @param {string} str\n * @returns {string}\n */\n decode(str) {\n if (typeof str !== 'string' || str.length === 0) return str;\n //TODO: check if needed\n //if (str.indexOf('&') === -1) return str; // fast path — no entities at all\n\n const original = str;\n const chunks = [];\n const len = str.length;\n let last = 0; // start of next unprocessed literal chunk\n let i = 0;\n\n const limitExpansions = this._maxTotalExpansions > 0;\n const limitLength = this._maxExpandedLength > 0;\n const checkLimits = limitExpansions || limitLength;\n\n while (i < len) {\n // Scan forward to next '&'\n if (str.charCodeAt(i) !== 38 /* '&' */) { i++; continue; }\n\n // --- Found '&' at position i ---\n\n // Scan forward to ';'\n let j = i + 1;\n while (j < len && str.charCodeAt(j) !== 59 /* ';' */ && (j - i) <= 32) j++;\n\n if (j >= len || str.charCodeAt(j) !== 59) {\n // No closing ';' within window — treat '&' as literal\n i++;\n continue;\n }\n\n // Raw token between '&' and ';' (exclusive)\n const token = str.slice(i + 1, j);\n if (token.length === 0) { i++; continue; }\n\n let replacement;\n let tier; // which limit tier this entity belongs to\n\n if (this._removeSet.has(token)) {\n // Remove entity: replace with empty string\n replacement = '';\n // If entity was unknown (replacement undefined), we still need a tier for limits.\n // Treat as external tier because it's user-directed removal of an unknown reference.\n if (tier === undefined) {\n tier = LIMIT_TIER_EXTERNAL;\n }\n } else if (this._leaveSet.has(token)) {\n // Do not replace — keep original &token; as literal\n i++;\n continue;\n } else if (token.charCodeAt(0) === 35 /* '#' */) {\n // ---- Numeric / NCR reference ----\n // NCR classification always runs first — prohibited codepoints must be\n // caught regardless of numericAllowed.\n const ncrResult = this._resolveNCR(token);\n if (ncrResult === undefined) {\n // 'leave' action — keep original &token; as-is\n i++;\n continue;\n }\n replacement = ncrResult; // '' for remove, char string for allow\n tier = LIMIT_TIER_BASE;\n } else {\n // ---- Named reference ----\n const resolved = this._resolveName(token);\n replacement = resolved?.value;\n tier = resolved?.tier;\n }\n\n if (replacement === undefined) {\n // Unknown entity — leave as-is, advance past '&' only\n i++;\n continue;\n }\n\n // Flush literal chunk before this entity\n if (i > last) chunks.push(str.slice(last, i));\n chunks.push(replacement);\n last = j + 1; // skip past ';'\n i = last;\n\n // Apply expansion limits only if this tier is being tracked\n if (checkLimits && this._tierCounts(tier)) {\n if (limitExpansions) {\n this._totalExpansions++;\n if (this._totalExpansions > this._maxTotalExpansions) {\n throw new Error(\n `[EntityReplacer] Entity expansion count limit exceeded: ` +\n `${this._totalExpansions} > ${this._maxTotalExpansions}`\n );\n }\n }\n if (limitLength) {\n // delta: replacement.length minus the raw &token; length (token.length + 2 for '&' and ';')\n const delta = replacement.length - (token.length + 2);\n if (delta > 0) {\n this._expandedLength += delta;\n if (this._expandedLength > this._maxExpandedLength) {\n throw new Error(\n `[EntityReplacer] Expanded content length limit exceeded: ` +\n `${this._expandedLength} > ${this._maxExpandedLength}`\n );\n }\n }\n }\n }\n }\n\n // Flush trailing literal\n if (last < len) chunks.push(str.slice(last));\n\n // If nothing was replaced, chunks is empty — return original\n const result = chunks.length === 0 ? str : chunks.join('');\n\n return this._postCheck(result, original);\n }\n\n // -------------------------------------------------------------------------\n // Private: limit tier check\n // -------------------------------------------------------------------------\n\n /**\n * Returns true if a resolved entity of the given tier should count\n * against the expansion/length limits.\n * @param {string} tier — LIMIT_TIER_EXTERNAL | LIMIT_TIER_BASE\n * @returns {boolean}\n */\n _tierCounts(tier) {\n if (this._limitTiers.has(LIMIT_TIER_ALL)) return true;\n return this._limitTiers.has(tier);\n }\n\n // -------------------------------------------------------------------------\n // Private: entity resolution\n // -------------------------------------------------------------------------\n\n /**\n * Resolve a named entity token (without & and ;).\n * Priority: inputMap > externalMap > baseMap\n * Returns the resolved value tagged with its limit tier.\n *\n * @param {string} name\n * @returns {{ value: string, tier: string }|undefined}\n */\n _resolveName(name) {\n // input and external both count as 'external' tier for limit purposes —\n // they are injected at runtime and are the untrusted surface.\n if (name in this._inputMap) return { value: this._inputMap[name], tier: LIMIT_TIER_EXTERNAL };\n if (name in this._externalMap) return { value: this._externalMap[name], tier: LIMIT_TIER_EXTERNAL };\n if (name in this._baseMap) return { value: this._baseMap[name], tier: LIMIT_TIER_BASE };\n return undefined;\n }\n\n /**\n * Classify a codepoint and return the minimum action level that must be applied.\n * Returns -1 when no minimum is imposed (normal allow path).\n *\n * Ranges checked (in priority order):\n * 1. U+0000 — null, governed by nullNCR (always ≥ remove)\n * 2. U+D800–U+DFFF — surrogates, always prohibited (min: remove)\n * 3. U+0001–U+001F \\ {0x09,0x0A,0x0D} — XML 1.0 restricted C0 (min: remove)\n * (skipped in XML 1.1 — C0 controls are allowed when written as NCRs)\n *\n * @param {number} cp — codepoint\n * @returns {number} — minimum NCR_LEVEL value, or -1 for no restriction\n */\n _classifyNCR(cp) {\n // 1. Null\n if (cp === 0) return this._ncrNullLevel;\n\n // 2. Surrogates — always prohibited, minimum 'remove'\n if (cp >= 0xD800 && cp <= 0xDFFF) return NCR_LEVEL.remove;\n\n // 3. XML 1.0 restricted C0 controls\n if (this._ncrXmlVersion === 1.0) {\n if (cp >= 0x01 && cp <= 0x1F && !XML10_ALLOWED_C0.has(cp)) return NCR_LEVEL.remove;\n }\n\n return -1; // no restriction\n }\n\n /**\n * Execute a resolved NCR action.\n *\n * @param {number} action — NCR_LEVEL value\n * @param {string} token — raw token (e.g. '#38') for error messages\n * @param {number} cp — codepoint, used only for error messages\n * @returns {string|undefined}\n * - decoded character string → 'allow'\n * - '' → 'remove'\n * - undefined → 'leave' (caller must skip past '&' only)\n * - throws Error → 'throw'\n */\n _applyNCRAction(action, token, cp) {\n switch (action) {\n case NCR_LEVEL.allow: return String.fromCodePoint(cp);\n case NCR_LEVEL.remove: return '';\n case NCR_LEVEL.leave: return undefined; // signal: keep literal\n case NCR_LEVEL.throw:\n throw new Error(\n `[EntityDecoder] Prohibited numeric character reference ` +\n `&${token}; (U+${cp.toString(16).toUpperCase().padStart(4, '0')})`\n );\n default: return String.fromCodePoint(cp);\n }\n }\n\n /**\n * Full NCR resolution pipeline for a numeric token.\n *\n * Steps:\n * 1. Parse the codepoint (decimal or hex).\n * 2. Validate the raw codepoint range (NaN, <0, >0x10FFFF).\n * 3. If numericAllowed is false and no minimum restriction applies → leave as-is.\n * 4. Classify the codepoint to find the minimum required action level.\n * 5. Resolve effective action = max(onNCR, minimum).\n * 6. Apply and return.\n *\n * @param {string} token — e.g. '#38', '#x26', '#X26'\n * @returns {string|undefined}\n * - string (incl. '') — replacement ('' = remove)\n * - undefined — leave original &token; as-is\n */\n _resolveNCR(token) {\n // Step 1: parse codepoint\n const second = token.charCodeAt(1);\n let cp;\n if (second === 120 /* x */ || second === 88 /* X */) {\n cp = parseInt(token.slice(2), 16);\n } else {\n cp = parseInt(token.slice(1), 10);\n }\n\n // Step 2: out-of-range → leave as-is unconditionally\n if (Number.isNaN(cp) || cp < 0 || cp > 0x10FFFF) return undefined;\n\n // Step 3: classify to get minimum action level\n const minimum = this._classifyNCR(cp);\n\n // Step 4: if numericAllowed is false and no hard minimum → leave\n if (!this._numericAllowed && minimum < NCR_LEVEL.remove) return undefined;\n\n // Step 5: effective action = max(configured onNCR, range minimum)\n const effective = minimum === -1\n ? this._ncrOnLevel\n : Math.max(this._ncrOnLevel, minimum);\n\n // Step 6: apply\n return this._applyNCRAction(effective, token, cp);\n }\n}","import { DANGEROUS_PROPERTY_NAMES, criticalProperties } from \"../util.js\";\nimport { COMMON_HTML, CURRENCY } from '@nodable/entities';\n\nconst defaultOnDangerousProperty = (name) => {\n if (DANGEROUS_PROPERTY_NAMES.includes(name)) {\n return \"__\" + name;\n }\n return name;\n};\n\n\nexport const defaultOptions = {\n preserveOrder: false,\n attributeNamePrefix: '@_',\n attributesGroupName: false,\n textNodeName: '#text',\n ignoreAttributes: true,\n removeNSPrefix: false, // remove NS from tag name or attribute name if true\n allowBooleanAttributes: false, //a tag can have attributes without any value\n //ignoreRootElement : false,\n parseTagValue: true,\n parseAttributeValue: false,\n trimValues: true, //Trim string values of tag and attributes\n cdataPropName: false,\n numberParseOptions: {\n hex: true,\n leadingZeros: true,\n eNotation: true\n },\n tagValueProcessor: function (tagName, val) {\n return val;\n },\n attributeValueProcessor: function (attrName, val) {\n return val;\n },\n stopNodes: [], //nested tags will not be parsed even for errors\n alwaysCreateTextNode: false,\n isArray: () => false,\n commentPropName: false,\n unpairedTags: [],\n processEntities: true,\n htmlEntities: false,\n entityDecoder: null,\n ignoreDeclaration: false,\n ignorePiTags: false,\n transformTagName: false,\n transformAttributeName: false,\n updateTag: function (tagName, jPath, attrs) {\n return tagName\n },\n // skipEmptyListItem: false\n captureMetaData: false,\n maxNestedTags: 100,\n strictReservedNames: true,\n jPath: true, // if true, pass jPath string to callbacks; if false, pass matcher instance\n onDangerousProperty: defaultOnDangerousProperty\n};\n\n\n/**\n * Validates that a property name is safe to use\n * @param {string} propertyName - The property name to validate\n * @param {string} optionName - The option field name (for error message)\n * @throws {Error} If property name is dangerous\n */\nfunction validatePropertyName(propertyName, optionName) {\n if (typeof propertyName !== 'string') {\n return; // Only validate string property names\n }\n\n const normalized = propertyName.toLowerCase();\n if (DANGEROUS_PROPERTY_NAMES.some(dangerous => normalized === dangerous.toLowerCase())) {\n throw new Error(\n `[SECURITY] Invalid ${optionName}: \"${propertyName}\" is a reserved JavaScript keyword that could cause prototype pollution`\n );\n }\n\n if (criticalProperties.some(dangerous => normalized === dangerous.toLowerCase())) {\n throw new Error(\n `[SECURITY] Invalid ${optionName}: \"${propertyName}\" is a reserved JavaScript keyword that could cause prototype pollution`\n );\n }\n}\n\n/**\n * Normalizes processEntities option for backward compatibility\n * @param {boolean|object} value \n * @returns {object} Always returns normalized object\n */\nfunction normalizeProcessEntities(value, htmlEntities) {\n // Boolean backward compatibility\n if (typeof value === 'boolean') {\n return {\n enabled: value, // true or false\n maxEntitySize: 10000,\n maxExpansionDepth: 10000,\n maxTotalExpansions: Infinity,\n maxExpandedLength: 100000,\n maxEntityCount: 1000,\n allowedTags: null,\n tagFilter: null,\n appliesTo: \"all\",\n };\n }\n\n // Object config - merge with defaults\n if (typeof value === 'object' && value !== null) {\n return {\n enabled: value.enabled !== false,\n maxEntitySize: Math.max(1, value.maxEntitySize ?? 10000),\n maxExpansionDepth: Math.max(1, value.maxExpansionDepth ?? 10000),\n maxTotalExpansions: Math.max(1, value.maxTotalExpansions ?? Infinity),\n maxExpandedLength: Math.max(1, value.maxExpandedLength ?? 100000),\n maxEntityCount: Math.max(1, value.maxEntityCount ?? 1000),\n allowedTags: value.allowedTags ?? null,\n tagFilter: value.tagFilter ?? null,\n appliesTo: value.appliesTo ?? \"all\",\n };\n }\n\n // Default to enabled with limits\n return normalizeProcessEntities(true);\n}\n\nexport const buildOptions = function (options) {\n const built = Object.assign({}, defaultOptions, options);\n\n // Validate property names to prevent prototype pollution\n const propertyNameOptions = [\n { value: built.attributeNamePrefix, name: 'attributeNamePrefix' },\n { value: built.attributesGroupName, name: 'attributesGroupName' },\n { value: built.textNodeName, name: 'textNodeName' },\n { value: built.cdataPropName, name: 'cdataPropName' },\n { value: built.commentPropName, name: 'commentPropName' }\n ];\n\n for (const { value, name } of propertyNameOptions) {\n if (value) {\n validatePropertyName(value, name);\n }\n }\n\n if (built.onDangerousProperty === null) {\n built.onDangerousProperty = defaultOnDangerousProperty;\n }\n\n // Always normalize processEntities for backward compatibility and validation\n built.processEntities = normalizeProcessEntities(built.processEntities, built.htmlEntities);\n built.unpairedTagsSet = new Set(built.unpairedTags);\n // Convert old-style stopNodes for backward compatibility\n if (built.stopNodes && Array.isArray(built.stopNodes)) {\n built.stopNodes = built.stopNodes.map(node => {\n if (typeof node === 'string' && node.startsWith('*.')) {\n // Old syntax: *.tagname meant \"tagname anywhere\"\n // Convert to new syntax: ..tagname\n return '..' + node.substring(2);\n }\n return node;\n });\n }\n //console.debug(built.processEntities)\n return built;\n};","'use strict';\n\nlet METADATA_SYMBOL;\n\nif (typeof Symbol !== \"function\") {\n METADATA_SYMBOL = \"@@xmlMetadata\";\n} else {\n METADATA_SYMBOL = Symbol(\"XML Node Metadata\");\n}\n\nexport default class XmlNode {\n constructor(tagname) {\n this.tagname = tagname;\n this.child = []; //nested tags, text, cdata, comments in order\n this[\":@\"] = Object.create(null); //attributes map\n }\n add(key, val) {\n // this.child.push( {name : key, val: val, isCdata: isCdata });\n if (key === \"__proto__\") key = \"#__proto__\";\n this.child.push({ [key]: val });\n }\n addChild(node, startIndex) {\n if (node.tagname === \"__proto__\") node.tagname = \"#__proto__\";\n if (node[\":@\"] && Object.keys(node[\":@\"]).length > 0) {\n this.child.push({ [node.tagname]: node.child, [\":@\"]: node[\":@\"] });\n } else {\n this.child.push({ [node.tagname]: node.child });\n }\n // if requested, add the startIndex\n if (startIndex !== undefined) {\n // Note: for now we just overwrite the metadata. If we had more complex metadata,\n // we might need to do an object append here: metadata = { ...metadata, startIndex }\n this.child[this.child.length - 1][METADATA_SYMBOL] = { startIndex };\n }\n }\n /** symbol used for metadata */\n static getMetaDataSymbol() {\n return METADATA_SYMBOL;\n }\n}\n","import { isName } from '../util.js';\n\nexport default class DocTypeReader {\n constructor(options) {\n this.suppressValidationErr = !options;\n this.options = options;\n }\n\n readDocType(xmlData, i) {\n const entities = Object.create(null);\n let entityCount = 0;\n\n if (xmlData[i + 3] === 'O' &&\n xmlData[i + 4] === 'C' &&\n xmlData[i + 5] === 'T' &&\n xmlData[i + 6] === 'Y' &&\n xmlData[i + 7] === 'P' &&\n xmlData[i + 8] === 'E') {\n i = i + 9;\n let angleBracketsCount = 1;\n let hasBody = false, comment = false;\n let exp = \"\";\n for (; i < xmlData.length; i++) {\n if (xmlData[i] === '<' && !comment) { //Determine the tag type\n if (hasBody && hasSeq(xmlData, \"!ENTITY\", i)) {\n i += 7;\n let entityName, val;\n [entityName, val, i] = this.readEntityExp(xmlData, i + 1, this.suppressValidationErr);\n if (val.indexOf(\"&\") === -1) { //Parameter entities are not supported\n if (this.options.enabled !== false &&\n this.options.maxEntityCount != null &&\n entityCount >= this.options.maxEntityCount) {\n throw new Error(\n `Entity count (${entityCount + 1}) exceeds maximum allowed (${this.options.maxEntityCount})`\n );\n }\n //const escaped = entityName.replace(/[.\\-+*:]/g, '\\\\.');\n //const escaped = entityName.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n entities[entityName] = val;\n entityCount++;\n }\n }\n else if (hasBody && hasSeq(xmlData, \"!ELEMENT\", i)) {\n i += 8;//Not supported\n const { index } = this.readElementExp(xmlData, i + 1);\n i = index;\n } else if (hasBody && hasSeq(xmlData, \"!ATTLIST\", i)) {\n i += 8;//Not supported\n // const {index} = this.readAttlistExp(xmlData,i+1);\n // i = index;\n } else if (hasBody && hasSeq(xmlData, \"!NOTATION\", i)) {\n i += 9;//Not supported\n const { index } = this.readNotationExp(xmlData, i + 1, this.suppressValidationErr);\n i = index;\n } else if (hasSeq(xmlData, \"!--\", i)) comment = true;\n else throw new Error(`Invalid DOCTYPE`);\n\n angleBracketsCount++;\n exp = \"\";\n } else if (xmlData[i] === '>') { //Read tag content\n if (comment) {\n if (xmlData[i - 1] === \"-\" && xmlData[i - 2] === \"-\") {\n comment = false;\n angleBracketsCount--;\n }\n } else {\n angleBracketsCount--;\n }\n if (angleBracketsCount === 0) {\n break;\n }\n } else if (xmlData[i] === '[') {\n hasBody = true;\n } else {\n exp += xmlData[i];\n }\n }\n if (angleBracketsCount !== 0) {\n throw new Error(`Unclosed DOCTYPE`);\n }\n } else {\n throw new Error(`Invalid Tag instead of DOCTYPE`);\n }\n return { entities, i };\n }\n readEntityExp(xmlData, i) {\n //External entities are not supported\n // <!ENTITY ext SYSTEM \"http://normal-website.com\" >\n\n //Parameter entities are not supported\n // <!ENTITY entityname \"&anotherElement;\">\n\n //Internal entities are supported\n // <!ENTITY entityname \"replacement text\">\n\n // Skip leading whitespace after <!ENTITY\n i = skipWhitespace(xmlData, i);\n\n // Read entity name\n const startIndex = i;\n while (i < xmlData.length && !/\\s/.test(xmlData[i]) && xmlData[i] !== '\"' && xmlData[i] !== \"'\") {\n i++;\n }\n let entityName = xmlData.substring(startIndex, i);\n\n validateEntityName(entityName);\n\n // Skip whitespace after entity name\n i = skipWhitespace(xmlData, i);\n\n // Check for unsupported constructs (external entities or parameter entities)\n if (!this.suppressValidationErr) {\n if (xmlData.substring(i, i + 6).toUpperCase() === \"SYSTEM\") {\n throw new Error(\"External entities are not supported\");\n } else if (xmlData[i] === \"%\") {\n throw new Error(\"Parameter entities are not supported\");\n }\n }\n\n // Read entity value (internal entity)\n let entityValue = \"\";\n [i, entityValue] = this.readIdentifierVal(xmlData, i, \"entity\");\n\n // Validate entity size\n if (this.options.enabled !== false &&\n this.options.maxEntitySize != null &&\n entityValue.length > this.options.maxEntitySize) {\n throw new Error(\n `Entity \"${entityName}\" size (${entityValue.length}) exceeds maximum allowed size (${this.options.maxEntitySize})`\n );\n }\n\n i--;\n return [entityName, entityValue, i];\n }\n\n readNotationExp(xmlData, i) {\n // Skip leading whitespace after <!NOTATION\n i = skipWhitespace(xmlData, i);\n\n // Read notation name\n\n const startIndex = i;\n while (i < xmlData.length && !/\\s/.test(xmlData[i])) {\n i++;\n }\n let notationName = xmlData.substring(startIndex, i);\n\n !this.suppressValidationErr && validateEntityName(notationName);\n\n // Skip whitespace after notation name\n i = skipWhitespace(xmlData, i);\n\n // Check identifier type (SYSTEM or PUBLIC)\n const identifierType = xmlData.substring(i, i + 6).toUpperCase();\n if (!this.suppressValidationErr && identifierType !== \"SYSTEM\" && identifierType !== \"PUBLIC\") {\n throw new Error(`Expected SYSTEM or PUBLIC, found \"${identifierType}\"`);\n }\n i += identifierType.length;\n\n // Skip whitespace after identifier type\n i = skipWhitespace(xmlData, i);\n\n // Read public identifier (if PUBLIC)\n let publicIdentifier = null;\n let systemIdentifier = null;\n\n if (identifierType === \"PUBLIC\") {\n [i, publicIdentifier] = this.readIdentifierVal(xmlData, i, \"publicIdentifier\");\n\n // Skip whitespace after public identifier\n i = skipWhitespace(xmlData, i);\n\n // Optionally read system identifier\n if (xmlData[i] === '\"' || xmlData[i] === \"'\") {\n [i, systemIdentifier] = this.readIdentifierVal(xmlData, i, \"systemIdentifier\");\n }\n } else if (identifierType === \"SYSTEM\") {\n // Read system identifier (mandatory for SYSTEM)\n [i, systemIdentifier] = this.readIdentifierVal(xmlData, i, \"systemIdentifier\");\n\n if (!this.suppressValidationErr && !systemIdentifier) {\n throw new Error(\"Missing mandatory system identifier for SYSTEM notation\");\n }\n }\n\n return { notationName, publicIdentifier, systemIdentifier, index: --i };\n }\n\n readIdentifierVal(xmlData, i, type) {\n let identifierVal = \"\";\n const startChar = xmlData[i];\n if (startChar !== '\"' && startChar !== \"'\") {\n throw new Error(`Expected quoted string, found \"${startChar}\"`);\n }\n i++;\n\n const startIndex = i;\n while (i < xmlData.length && xmlData[i] !== startChar) {\n i++;\n }\n identifierVal = xmlData.substring(startIndex, i);\n\n if (xmlData[i] !== startChar) {\n throw new Error(`Unterminated ${type} value`);\n }\n i++;\n return [i, identifierVal];\n }\n\n readElementExp(xmlData, i) {\n // <!ELEMENT br EMPTY>\n // <!ELEMENT div ANY>\n // <!ELEMENT title (#PCDATA)>\n // <!ELEMENT book (title, author+)>\n // <!ELEMENT name (content-model)>\n\n // Skip leading whitespace after <!ELEMENT\n i = skipWhitespace(xmlData, i);\n\n // Read element name\n const startIndex = i;\n while (i < xmlData.length && !/\\s/.test(xmlData[i])) {\n i++;\n }\n let elementName = xmlData.substring(startIndex, i);\n\n // Validate element name\n if (!this.suppressValidationErr && !isName(elementName)) {\n throw new Error(`Invalid element name: \"${elementName}\"`);\n }\n\n // Skip whitespace after element name\n i = skipWhitespace(xmlData, i);\n let contentModel = \"\";\n // Expect '(' to start content model\n if (xmlData[i] === \"E\" && hasSeq(xmlData, \"MPTY\", i)) i += 4;\n else if (xmlData[i] === \"A\" && hasSeq(xmlData, \"NY\", i)) i += 2;\n else if (xmlData[i] === \"(\") {\n i++; // Move past '('\n\n // Read content model\n const startIndex = i;\n while (i < xmlData.length && xmlData[i] !== \")\") {\n i++;\n }\n contentModel = xmlData.substring(startIndex, i);\n\n if (xmlData[i] !== \")\") {\n throw new Error(\"Unterminated content model\");\n }\n\n } else if (!this.suppressValidationErr) {\n throw new Error(`Invalid Element Expression, found \"${xmlData[i]}\"`);\n }\n\n return {\n elementName,\n contentModel: contentModel.trim(),\n index: i\n };\n }\n\n readAttlistExp(xmlData, i) {\n // Skip leading whitespace after <!ATTLIST\n i = skipWhitespace(xmlData, i);\n\n // Read element name\n let startIndex = i;\n while (i < xmlData.length && !/\\s/.test(xmlData[i])) {\n i++;\n }\n let elementName = xmlData.substring(startIndex, i);\n\n // Validate element name\n validateEntityName(elementName)\n\n // Skip whitespace after element name\n i = skipWhitespace(xmlData, i);\n\n // Read attribute name\n startIndex = i;\n while (i < xmlData.length && !/\\s/.test(xmlData[i])) {\n i++;\n }\n let attributeName = xmlData.substring(startIndex, i);\n\n // Validate attribute name\n if (!validateEntityName(attributeName)) {\n throw new Error(`Invalid attribute name: \"${attributeName}\"`);\n }\n\n // Skip whitespace after attribute name\n i = skipWhitespace(xmlData, i);\n\n // Read attribute type\n let attributeType = \"\";\n if (xmlData.substring(i, i + 8).toUpperCase() === \"NOTATION\") {\n attributeType = \"NOTATION\";\n i += 8; // Move past \"NOTATION\"\n\n // Skip whitespace after \"NOTATION\"\n i = skipWhitespace(xmlData, i);\n\n // Expect '(' to start the list of notations\n if (xmlData[i] !== \"(\") {\n throw new Error(`Expected '(', found \"${xmlData[i]}\"`);\n }\n i++; // Move past '('\n\n // Read the list of allowed notations\n let allowedNotations = [];\n while (i < xmlData.length && xmlData[i] !== \")\") {\n\n\n const startIndex = i;\n while (i < xmlData.length && xmlData[i] !== \"|\" && xmlData[i] !== \")\") {\n i++;\n }\n let notation = xmlData.substring(startIndex, i);\n\n // Validate notation name\n notation = notation.trim();\n if (!validateEntityName(notation)) {\n throw new Error(`Invalid notation name: \"${notation}\"`);\n }\n\n allowedNotations.push(notation);\n\n // Skip '|' separator or exit loop\n if (xmlData[i] === \"|\") {\n i++; // Move past '|'\n i = skipWhitespace(xmlData, i); // Skip optional whitespace after '|'\n }\n }\n\n if (xmlData[i] !== \")\") {\n throw new Error(\"Unterminated list of notations\");\n }\n i++; // Move past ')'\n\n // Store the allowed notations as part of the attribute type\n attributeType += \" (\" + allowedNotations.join(\"|\") + \")\";\n } else {\n // Handle simple types (e.g., CDATA, ID, IDREF, etc.)\n const startIndex = i;\n while (i < xmlData.length && !/\\s/.test(xmlData[i])) {\n i++;\n }\n attributeType += xmlData.substring(startIndex, i);\n\n // Validate simple attribute type\n const validTypes = [\"CDATA\", \"ID\", \"IDREF\", \"IDREFS\", \"ENTITY\", \"ENTITIES\", \"NMTOKEN\", \"NMTOKENS\"];\n if (!this.suppressValidationErr && !validTypes.includes(attributeType.toUpperCase())) {\n throw new Error(`Invalid attribute type: \"${attributeType}\"`);\n }\n }\n\n // Skip whitespace after attribute type\n i = skipWhitespace(xmlData, i);\n\n // Read default value\n let defaultValue = \"\";\n if (xmlData.substring(i, i + 8).toUpperCase() === \"#REQUIRED\") {\n defaultValue = \"#REQUIRED\";\n i += 8;\n } else if (xmlData.substring(i, i + 7).toUpperCase() === \"#IMPLIED\") {\n defaultValue = \"#IMPLIED\";\n i += 7;\n } else {\n [i, defaultValue] = this.readIdentifierVal(xmlData, i, \"ATTLIST\");\n }\n\n return {\n elementName,\n attributeName,\n attributeType,\n defaultValue,\n index: i\n }\n }\n}\n\n\n\nconst skipWhitespace = (data, index) => {\n while (index < data.length && /\\s/.test(data[index])) {\n index++;\n }\n return index;\n};\n\n\n\nfunction hasSeq(data, seq, i) {\n for (let j = 0; j < seq.length; j++) {\n if (seq[j] !== data[i + j + 1]) return false;\n }\n return true;\n}\n\nfunction validateEntityName(name) {\n if (isName(name))\n return name;\n else\n throw new Error(`Invalid entity name ${name}`);\n}","const hexRegex = /^[-+]?0x[a-fA-F0-9]+$/;\nconst numRegex = /^([\\-\\+])?(0*)([0-9]*(\\.[0-9]*)?)$/;\n// const octRegex = /^0x[a-z0-9]+/;\n// const binRegex = /0x[a-z0-9]+/;\n\n\nconst consider = {\n hex: true,\n // oct: false,\n leadingZeros: true,\n decimalPoint: \"\\.\",\n eNotation: true,\n //skipLike: /regex/,\n infinity: \"original\", // \"null\", \"infinity\" (Infinity type), \"string\" (\"Infinity\" (the string literal))\n};\n\nexport default function toNumber(str, options = {}) {\n options = Object.assign({}, consider, options);\n if (!str || typeof str !== \"string\") return str;\n\n let trimmedStr = str.trim();\n\n if (trimmedStr.length === 0) return str;\n else if (options.skipLike !== undefined && options.skipLike.test(trimmedStr)) return str;\n else if (trimmedStr === \"0\") return 0;\n else if (options.hex && hexRegex.test(trimmedStr)) {\n return parse_int(trimmedStr, 16);\n // }else if (options.oct && octRegex.test(str)) {\n // return Number.parseInt(val, 8);\n } else if (!isFinite(trimmedStr)) { //Infinity\n return handleInfinity(str, Number(trimmedStr), options);\n } else if (trimmedStr.includes('e') || trimmedStr.includes('E')) { //eNotation\n return resolveEnotation(str, trimmedStr, options);\n // }else if (options.parseBin && binRegex.test(str)) {\n // return Number.parseInt(val, 2);\n } else {\n //separate negative sign, leading zeros, and rest number\n const match = numRegex.exec(trimmedStr);\n // +00.123 => [ , '+', '00', '.123', ..\n if (match) {\n const sign = match[1] || \"\";\n const leadingZeros = match[2];\n let numTrimmedByZeros = trimZeros(match[3]); //complete num without leading zeros\n const decimalAdjacentToLeadingZeros = sign ? // 0., -00., 000.\n str[leadingZeros.length + 1] === \".\"\n : str[leadingZeros.length] === \".\";\n\n //trim ending zeros for floating number\n if (!options.leadingZeros //leading zeros are not allowed\n && (leadingZeros.length > 1\n || (leadingZeros.length === 1 && !decimalAdjacentToLeadingZeros))) {\n // 00, 00.3, +03.24, 03, 03.24\n return str;\n }\n else {//no leading zeros or leading zeros are allowed\n const num = Number(trimmedStr);\n const parsedStr = String(num);\n\n if (num === 0) return num;\n if (parsedStr.search(/[eE]/) !== -1) { //given number is long and parsed to eNotation\n if (options.eNotation) return num;\n else return str;\n } else if (trimmedStr.indexOf(\".\") !== -1) { //floating number\n if (parsedStr === \"0\") return num; //0.0\n else if (parsedStr === numTrimmedByZeros) return num; //0.456. 0.79000\n else if (parsedStr === `${sign}${numTrimmedByZeros}`) return num;\n else return str;\n }\n\n let n = leadingZeros ? numTrimmedByZeros : trimmedStr;\n if (leadingZeros) {\n // -009 => -9\n return (n === parsedStr) || (sign + n === parsedStr) ? num : str\n } else {\n // +9\n return (n === parsedStr) || (n === sign + parsedStr) ? num : str\n }\n }\n } else { //non-numeric string\n return str;\n }\n }\n}\n\nconst eNotationRegx = /^([-+])?(0*)(\\d*(\\.\\d*)?[eE][-\\+]?\\d+)$/;\nfunction resolveEnotation(str, trimmedStr, options) {\n if (!options.eNotation) return str;\n const notation = trimmedStr.match(eNotationRegx);\n if (notation) {\n let sign = notation[1] || \"\";\n const eChar = notation[3].indexOf(\"e\") === -1 ? \"E\" : \"e\";\n const leadingZeros = notation[2];\n const eAdjacentToLeadingZeros = sign ? // 0E.\n str[leadingZeros.length + 1] === eChar\n : str[leadingZeros.length] === eChar;\n\n if (leadingZeros.length > 1 && eAdjacentToLeadingZeros) return str;\n else if (leadingZeros.length === 1\n && (notation[3].startsWith(`.${eChar}`) || notation[3][0] === eChar)) {\n return Number(trimmedStr);\n } else if (leadingZeros.length > 0) {\n // Has leading zeros — only accept if leadingZeros option allows it\n if (options.leadingZeros && !eAdjacentToLeadingZeros) {\n trimmedStr = (notation[1] || \"\") + notation[3];\n return Number(trimmedStr);\n } else return str;\n } else {\n // No leading zeros — always valid e-notation, parse it\n return Number(trimmedStr);\n }\n } else {\n return str;\n }\n}\n\n/**\n * \n * @param {string} numStr without leading zeros\n * @returns \n */\nfunction trimZeros(numStr) {\n if (numStr && numStr.indexOf(\".\") !== -1) {//float\n numStr = numStr.replace(/0+$/, \"\"); //remove ending zeros\n if (numStr === \".\") numStr = \"0\";\n else if (numStr[0] === \".\") numStr = \"0\" + numStr;\n else if (numStr[numStr.length - 1] === \".\") numStr = numStr.substring(0, numStr.length - 1);\n return numStr;\n }\n return numStr;\n}\n\nfunction parse_int(numStr, base) {\n //polyfill\n if (parseInt) return parseInt(numStr, base);\n else if (Number.parseInt) return Number.parseInt(numStr, base);\n else if (window && window.parseInt) return window.parseInt(numStr, base);\n else throw new Error(\"parseInt, Number.parseInt, window.parseInt are not supported\")\n}\n\n/**\n * Handle infinite values based on user option\n * @param {string} str - original input string\n * @param {number} num - parsed number (Infinity or -Infinity)\n * @param {object} options - user options\n * @returns {string|number|null} based on infinity option\n */\nfunction handleInfinity(str, num, options) {\n const isPositive = num === Infinity;\n\n switch (options.infinity.toLowerCase()) {\n case \"null\":\n return null;\n case \"infinity\":\n return num; // Return Infinity or -Infinity\n case \"string\":\n return isPositive ? \"Infinity\" : \"-Infinity\";\n case \"original\":\n default:\n return str; // Return original string like \"1e1000\"\n }\n}","export default function getIgnoreAttributesFn(ignoreAttributes) {\n if (typeof ignoreAttributes === 'function') {\n return ignoreAttributes\n }\n if (Array.isArray(ignoreAttributes)) {\n return (attrName) => {\n for (const pattern of ignoreAttributes) {\n if (typeof pattern === 'string' && attrName === pattern) {\n return true\n }\n if (pattern instanceof RegExp && pattern.test(attrName)) {\n return true\n }\n }\n }\n }\n return () => false\n}","/**\n * Expression - Parses and stores a tag pattern expression\n * \n * Patterns are parsed once and stored in an optimized structure for fast matching.\n * \n * @example\n * const expr = new Expression(\"root.users.user\");\n * const expr2 = new Expression(\"..user[id]:first\");\n * const expr3 = new Expression(\"root/users/user\", { separator: '/' });\n */\nexport default class Expression {\n /**\n * Create a new Expression\n * @param {string} pattern - Pattern string (e.g., \"root.users.user\", \"..user[id]\")\n * @param {Object} options - Configuration options\n * @param {string} options.separator - Path separator (default: '.')\n */\n constructor(pattern, options = {}, data) {\n this.pattern = pattern;\n this.separator = options.separator || '.';\n this.segments = this._parse(pattern);\n this.data = data;\n // Cache expensive checks for performance (O(1) instead of O(n))\n this._hasDeepWildcard = this.segments.some(seg => seg.type === 'deep-wildcard');\n this._hasAttributeCondition = this.segments.some(seg => seg.attrName !== undefined);\n this._hasPositionSelector = this.segments.some(seg => seg.position !== undefined);\n }\n\n /**\n * Parse pattern string into segments\n * @private\n * @param {string} pattern - Pattern to parse\n * @returns {Array} Array of segment objects\n */\n _parse(pattern) {\n const segments = [];\n\n // Split by separator but handle \"..\" specially\n let i = 0;\n let currentPart = '';\n\n while (i < pattern.length) {\n if (pattern[i] === this.separator) {\n // Check if next char is also separator (deep wildcard)\n if (i + 1 < pattern.length && pattern[i + 1] === this.separator) {\n // Flush current part if any\n if (currentPart.trim()) {\n segments.push(this._parseSegment(currentPart.trim()));\n currentPart = '';\n }\n // Add deep wildcard\n segments.push({ type: 'deep-wildcard' });\n i += 2; // Skip both separators\n } else {\n // Regular separator\n if (currentPart.trim()) {\n segments.push(this._parseSegment(currentPart.trim()));\n }\n currentPart = '';\n i++;\n }\n } else {\n currentPart += pattern[i];\n i++;\n }\n }\n\n // Flush remaining part\n if (currentPart.trim()) {\n segments.push(this._parseSegment(currentPart.trim()));\n }\n\n return segments;\n }\n\n /**\n * Parse a single segment\n * @private\n * @param {string} part - Segment string (e.g., \"user\", \"ns::user\", \"user[id]\", \"ns::user:first\")\n * @returns {Object} Segment object\n */\n _parseSegment(part) {\n const segment = { type: 'tag' };\n\n // NEW NAMESPACE SYNTAX (v2.0):\n // ============================\n // Namespace uses DOUBLE colon (::)\n // Position uses SINGLE colon (:)\n // \n // Examples:\n // \"user\" → tag\n // \"user:first\" → tag + position\n // \"user[id]\" → tag + attribute\n // \"user[id]:first\" → tag + attribute + position\n // \"ns::user\" → namespace + tag\n // \"ns::user:first\" → namespace + tag + position\n // \"ns::user[id]\" → namespace + tag + attribute\n // \"ns::user[id]:first\" → namespace + tag + attribute + position\n // \"ns::first\" → namespace + tag named \"first\" (NO ambiguity!)\n //\n // This eliminates all ambiguity:\n // :: = namespace separator\n // : = position selector\n // [] = attributes\n\n // Step 1: Extract brackets [attr] or [attr=value]\n let bracketContent = null;\n let withoutBrackets = part;\n\n const bracketMatch = part.match(/^([^\\[]+)(\\[[^\\]]*\\])(.*)$/);\n if (bracketMatch) {\n withoutBrackets = bracketMatch[1] + bracketMatch[3];\n if (bracketMatch[2]) {\n const content = bracketMatch[2].slice(1, -1);\n if (content) {\n bracketContent = content;\n }\n }\n }\n\n // Step 2: Check for namespace (double colon ::)\n let namespace = undefined;\n let tagAndPosition = withoutBrackets;\n\n if (withoutBrackets.includes('::')) {\n const nsIndex = withoutBrackets.indexOf('::');\n namespace = withoutBrackets.substring(0, nsIndex).trim();\n tagAndPosition = withoutBrackets.substring(nsIndex + 2).trim(); // Skip ::\n\n if (!namespace) {\n throw new Error(`Invalid namespace in pattern: ${part}`);\n }\n }\n\n // Step 3: Parse tag and position (single colon :)\n let tag = undefined;\n let positionMatch = null;\n\n if (tagAndPosition.includes(':')) {\n const colonIndex = tagAndPosition.lastIndexOf(':'); // Use last colon for position\n const tagPart = tagAndPosition.substring(0, colonIndex).trim();\n const posPart = tagAndPosition.substring(colonIndex + 1).trim();\n\n // Verify position is a valid keyword\n const isPositionKeyword = ['first', 'last', 'odd', 'even'].includes(posPart) ||\n /^nth\\(\\d+\\)$/.test(posPart);\n\n if (isPositionKeyword) {\n tag = tagPart;\n positionMatch = posPart;\n } else {\n // Not a valid position keyword, treat whole thing as tag\n tag = tagAndPosition;\n }\n } else {\n tag = tagAndPosition;\n }\n\n if (!tag) {\n throw new Error(`Invalid segment pattern: ${part}`);\n }\n\n segment.tag = tag;\n if (namespace) {\n segment.namespace = namespace;\n }\n\n // Step 4: Parse attributes\n if (bracketContent) {\n if (bracketContent.includes('=')) {\n const eqIndex = bracketContent.indexOf('=');\n segment.attrName = bracketContent.substring(0, eqIndex).trim();\n segment.attrValue = bracketContent.substring(eqIndex + 1).trim();\n } else {\n segment.attrName = bracketContent.trim();\n }\n }\n\n // Step 5: Parse position selector\n if (positionMatch) {\n const nthMatch = positionMatch.match(/^nth\\((\\d+)\\)$/);\n if (nthMatch) {\n segment.position = 'nth';\n segment.positionValue = parseInt(nthMatch[1], 10);\n } else {\n segment.position = positionMatch;\n }\n }\n\n return segment;\n }\n\n /**\n * Get the number of segments\n * @returns {number}\n */\n get length() {\n return this.segments.length;\n }\n\n /**\n * Check if expression contains deep wildcard\n * @returns {boolean}\n */\n hasDeepWildcard() {\n return this._hasDeepWildcard;\n }\n\n /**\n * Check if expression has attribute conditions\n * @returns {boolean}\n */\n hasAttributeCondition() {\n return this._hasAttributeCondition;\n }\n\n /**\n * Check if expression has position selectors\n * @returns {boolean}\n */\n hasPositionSelector() {\n return this._hasPositionSelector;\n }\n\n /**\n * Get string representation\n * @returns {string}\n */\n toString() {\n return this.pattern;\n }\n}","/**\n * ExpressionSet - An indexed collection of Expressions for efficient bulk matching\n *\n * Instead of iterating all expressions on every tag, ExpressionSet pre-indexes\n * them at insertion time by depth and terminal tag name. At match time, only\n * the relevant bucket is evaluated — typically reducing checks from O(E) to O(1)\n * lookup plus O(small bucket) matches.\n *\n * Three buckets are maintained:\n * - `_byDepthAndTag` — exact depth + exact tag name (tightest, used first)\n * - `_wildcardByDepth` — exact depth + wildcard tag `*` (depth-matched only)\n * - `_deepWildcards` — expressions containing `..` (cannot be depth-indexed)\n *\n * @example\n * import { Expression, ExpressionSet } from 'fast-xml-tagger';\n *\n * // Build once at config time\n * const stopNodes = new ExpressionSet();\n * stopNodes.add(new Expression('root.users.user'));\n * stopNodes.add(new Expression('root.config.setting'));\n * stopNodes.add(new Expression('..script'));\n *\n * // Query on every tag — hot path\n * if (stopNodes.matchesAny(matcher)) { ... }\n */\nexport default class ExpressionSet {\n constructor() {\n /** @type {Map<string, import('./Expression.js').default[]>} depth:tag → expressions */\n this._byDepthAndTag = new Map();\n\n /** @type {Map<number, import('./Expression.js').default[]>} depth → wildcard-tag expressions */\n this._wildcardByDepth = new Map();\n\n /** @type {import('./Expression.js').default[]} expressions containing deep wildcard (..) */\n this._deepWildcards = [];\n\n /** @type {Set<string>} pattern strings already added — used for deduplication */\n this._patterns = new Set();\n\n /** @type {boolean} whether the set is sealed against further additions */\n this._sealed = false;\n }\n\n /**\n * Add an Expression to the set.\n * Duplicate patterns (same pattern string) are silently ignored.\n *\n * @param {import('./Expression.js').default} expression - A pre-constructed Expression instance\n * @returns {this} for chaining\n * @throws {TypeError} if called after seal()\n *\n * @example\n * set.add(new Expression('root.users.user'));\n * set.add(new Expression('..script'));\n */\n add(expression) {\n if (this._sealed) {\n throw new TypeError(\n 'ExpressionSet is sealed. Create a new ExpressionSet to add more expressions.'\n );\n }\n\n // Deduplicate by pattern string\n if (this._patterns.has(expression.pattern)) return this;\n this._patterns.add(expression.pattern);\n\n if (expression.hasDeepWildcard()) {\n this._deepWildcards.push(expression);\n return this;\n }\n\n const depth = expression.length;\n const lastSeg = expression.segments[expression.segments.length - 1];\n const tag = lastSeg?.tag;\n\n if (!tag || tag === '*') {\n // Can index by depth but not by tag\n if (!this._wildcardByDepth.has(depth)) this._wildcardByDepth.set(depth, []);\n this._wildcardByDepth.get(depth).push(expression);\n } else {\n // Tightest bucket: depth + tag\n const key = `${depth}:${tag}`;\n if (!this._byDepthAndTag.has(key)) this._byDepthAndTag.set(key, []);\n this._byDepthAndTag.get(key).push(expression);\n }\n\n return this;\n }\n\n /**\n * Add multiple expressions at once.\n *\n * @param {import('./Expression.js').default[]} expressions - Array of Expression instances\n * @returns {this} for chaining\n *\n * @example\n * set.addAll([\n * new Expression('root.users.user'),\n * new Expression('root.config.setting'),\n * ]);\n */\n addAll(expressions) {\n for (const expr of expressions) this.add(expr);\n return this;\n }\n\n /**\n * Check whether a pattern string is already present in the set.\n *\n * @param {import('./Expression.js').default} expression\n * @returns {boolean}\n */\n has(expression) {\n return this._patterns.has(expression.pattern);\n }\n\n /**\n * Number of expressions in the set.\n * @type {number}\n */\n get size() {\n return this._patterns.size;\n }\n\n /**\n * Seal the set against further modifications.\n * Useful to prevent accidental mutations after config is built.\n * Calling add() or addAll() on a sealed set throws a TypeError.\n *\n * @returns {this}\n */\n seal() {\n this._sealed = true;\n return this;\n }\n\n /**\n * Whether the set has been sealed.\n * @type {boolean}\n */\n get isSealed() {\n return this._sealed;\n }\n\n /**\n * Test whether the matcher's current path matches any expression in the set.\n *\n * Evaluation order (cheapest → most expensive):\n * 1. Exact depth + tag bucket — O(1) lookup, typically 0–2 expressions\n * 2. Depth-only wildcard bucket — O(1) lookup, rare\n * 3. Deep-wildcard list — always checked, but usually small\n *\n * @param {import('./Matcher.js').default} matcher - Matcher instance (or readOnly view)\n * @returns {boolean} true if any expression matches the current path\n *\n * @example\n * if (stopNodes.matchesAny(matcher)) {\n * // handle stop node\n * }\n */\n matchesAny(matcher) {\n return this.findMatch(matcher) !== null;\n }\n /**\n * Find and return the first Expression that matches the matcher's current path.\n *\n * Uses the same evaluation order as matchesAny (cheapest → most expensive):\n * 1. Exact depth + tag bucket\n * 2. Depth-only wildcard bucket\n * 3. Deep-wildcard list\n *\n * @param {import('./Matcher.js').default} matcher - Matcher instance (or readOnly view)\n * @returns {import('./Expression.js').default | null} the first matching Expression, or null\n *\n * @example\n * const expr = stopNodes.findMatch(matcher);\n * if (expr) {\n * // access expr.config, expr.pattern, etc.\n * }\n */\n findMatch(matcher) {\n const depth = matcher.getDepth();\n const tag = matcher.getCurrentTag();\n\n // 1. Tightest bucket — most expressions live here\n const exactKey = `${depth}:${tag}`;\n const exactBucket = this._byDepthAndTag.get(exactKey);\n if (exactBucket) {\n for (let i = 0; i < exactBucket.length; i++) {\n if (matcher.matches(exactBucket[i])) return exactBucket[i];\n }\n }\n\n // 2. Depth-matched wildcard-tag expressions\n const wildcardBucket = this._wildcardByDepth.get(depth);\n if (wildcardBucket) {\n for (let i = 0; i < wildcardBucket.length; i++) {\n if (matcher.matches(wildcardBucket[i])) return wildcardBucket[i];\n }\n }\n\n // 3. Deep wildcards — cannot be pre-filtered by depth or tag\n for (let i = 0; i < this._deepWildcards.length; i++) {\n if (matcher.matches(this._deepWildcards[i])) return this._deepWildcards[i];\n }\n\n return null;\n }\n}\n","import ExpressionSet from \"./ExpressionSet.js\";\n\n/**\n * MatcherView - A lightweight read-only view over a Matcher's internal state.\n *\n * Created once by Matcher and reused across all callbacks. Holds a direct\n * reference to the parent Matcher so it always reflects current parser state\n * with zero copying or freezing overhead.\n *\n * Users receive this via {@link Matcher#readOnly} or directly from parser\n * callbacks. It exposes all query and matching methods but has no mutation\n * methods — misuse is caught at the TypeScript level rather than at runtime.\n *\n * @example\n * const matcher = new Matcher();\n * const view = matcher.readOnly();\n *\n * matcher.push(\"root\", {});\n * view.getCurrentTag(); // \"root\"\n * view.getDepth(); // 1\n */\nexport class MatcherView {\n /**\n * @param {Matcher} matcher - The parent Matcher instance to read from.\n */\n constructor(matcher) {\n this._matcher = matcher;\n }\n\n /**\n * Get the path separator used by the parent matcher.\n * @returns {string}\n */\n get separator() {\n return this._matcher.separator;\n }\n\n /**\n * Get current tag name.\n * @returns {string|undefined}\n */\n getCurrentTag() {\n const path = this._matcher.path;\n return path.length > 0 ? path[path.length - 1].tag : undefined;\n }\n\n /**\n * Get current namespace.\n * @returns {string|undefined}\n */\n getCurrentNamespace() {\n const path = this._matcher.path;\n return path.length > 0 ? path[path.length - 1].namespace : undefined;\n }\n\n /**\n * Get current node's attribute value.\n * @param {string} attrName\n * @returns {*}\n */\n getAttrValue(attrName) {\n const path = this._matcher.path;\n if (path.length === 0) return undefined;\n return path[path.length - 1].values?.[attrName];\n }\n\n /**\n * Check if current node has an attribute.\n * @param {string} attrName\n * @returns {boolean}\n */\n hasAttr(attrName) {\n const path = this._matcher.path;\n if (path.length === 0) return false;\n const current = path[path.length - 1];\n return current.values !== undefined && attrName in current.values;\n }\n\n /**\n * Get current node's sibling position (child index in parent).\n * @returns {number}\n */\n getPosition() {\n const path = this._matcher.path;\n if (path.length === 0) return -1;\n return path[path.length - 1].position ?? 0;\n }\n\n /**\n * Get current node's repeat counter (occurrence count of this tag name).\n * @returns {number}\n */\n getCounter() {\n const path = this._matcher.path;\n if (path.length === 0) return -1;\n return path[path.length - 1].counter ?? 0;\n }\n\n /**\n * Get current node's sibling index (alias for getPosition).\n * @returns {number}\n * @deprecated Use getPosition() or getCounter() instead\n */\n getIndex() {\n return this.getPosition();\n }\n\n /**\n * Get current path depth.\n * @returns {number}\n */\n getDepth() {\n return this._matcher.path.length;\n }\n\n /**\n * Get path as string.\n * @param {string} [separator] - Optional separator (uses default if not provided)\n * @param {boolean} [includeNamespace=true]\n * @returns {string}\n */\n toString(separator, includeNamespace = true) {\n return this._matcher.toString(separator, includeNamespace);\n }\n\n /**\n * Get path as array of tag names.\n * @returns {string[]}\n */\n toArray() {\n return this._matcher.path.map(n => n.tag);\n }\n\n /**\n * Match current path against an Expression.\n * @param {Expression} expression\n * @returns {boolean}\n */\n matches(expression) {\n return this._matcher.matches(expression);\n }\n\n /**\n * Match any expression in the given set against the current path.\n * @param {ExpressionSet} exprSet\n * @returns {boolean}\n */\n matchesAny(exprSet) {\n return exprSet.matchesAny(this._matcher);\n }\n}\n\n/**\n * Matcher - Tracks current path in XML/JSON tree and matches against Expressions.\n *\n * The matcher maintains a stack of nodes representing the current path from root to\n * current tag. It only stores attribute values for the current (top) node to minimize\n * memory usage. Sibling tracking is used to auto-calculate position and counter.\n *\n * Use {@link Matcher#readOnly} to obtain a {@link MatcherView} safe to pass to\n * user callbacks — it always reflects current state with no Proxy overhead.\n *\n * @example\n * const matcher = new Matcher();\n * matcher.push(\"root\", {});\n * matcher.push(\"users\", {});\n * matcher.push(\"user\", { id: \"123\", type: \"admin\" });\n *\n * const expr = new Expression(\"root.users.user\");\n * matcher.matches(expr); // true\n */\nexport default class Matcher {\n /**\n * Create a new Matcher.\n * @param {Object} [options={}]\n * @param {string} [options.separator='.'] - Default path separator\n */\n constructor(options = {}) {\n this.separator = options.separator || '.';\n this.path = [];\n this.siblingStacks = [];\n // Each path node: { tag, values, position, counter, namespace? }\n // values only present for current (last) node\n // Each siblingStacks entry: Map<tagName, count> tracking occurrences at each level\n this._pathStringCache = null;\n this._view = new MatcherView(this);\n }\n\n /**\n * Push a new tag onto the path.\n * @param {string} tagName\n * @param {Object|null} [attrValues=null]\n * @param {string|null} [namespace=null]\n */\n push(tagName, attrValues = null, namespace = null) {\n this._pathStringCache = null;\n\n // Remove values from previous current node (now becoming ancestor)\n if (this.path.length > 0) {\n this.path[this.path.length - 1].values = undefined;\n }\n\n // Get or create sibling tracking for current level\n const currentLevel = this.path.length;\n if (!this.siblingStacks[currentLevel]) {\n this.siblingStacks[currentLevel] = new Map();\n }\n\n const siblings = this.siblingStacks[currentLevel];\n\n // Create a unique key for sibling tracking that includes namespace\n const siblingKey = namespace ? `${namespace}:${tagName}` : tagName;\n\n // Calculate counter (how many times this tag appeared at this level)\n const counter = siblings.get(siblingKey) || 0;\n\n // Calculate position (total children at this level so far)\n let position = 0;\n for (const count of siblings.values()) {\n position += count;\n }\n\n // Update sibling count for this tag\n siblings.set(siblingKey, counter + 1);\n\n // Create new node\n const node = {\n tag: tagName,\n position: position,\n counter: counter\n };\n\n if (namespace !== null && namespace !== undefined) {\n node.namespace = namespace;\n }\n\n if (attrValues !== null && attrValues !== undefined) {\n node.values = attrValues;\n }\n\n this.path.push(node);\n }\n\n /**\n * Pop the last tag from the path.\n * @returns {Object|undefined} The popped node\n */\n pop() {\n if (this.path.length === 0) return undefined;\n this._pathStringCache = null;\n\n const node = this.path.pop();\n\n if (this.siblingStacks.length > this.path.length + 1) {\n this.siblingStacks.length = this.path.length + 1;\n }\n\n return node;\n }\n\n /**\n * Update current node's attribute values.\n * Useful when attributes are parsed after push.\n * @param {Object} attrValues\n */\n updateCurrent(attrValues) {\n if (this.path.length > 0) {\n const current = this.path[this.path.length - 1];\n if (attrValues !== null && attrValues !== undefined) {\n current.values = attrValues;\n }\n }\n }\n\n /**\n * Get current tag name.\n * @returns {string|undefined}\n */\n getCurrentTag() {\n return this.path.length > 0 ? this.path[this.path.length - 1].tag : undefined;\n }\n\n /**\n * Get current namespace.\n * @returns {string|undefined}\n */\n getCurrentNamespace() {\n return this.path.length > 0 ? this.path[this.path.length - 1].namespace : undefined;\n }\n\n /**\n * Get current node's attribute value.\n * @param {string} attrName\n * @returns {*}\n */\n getAttrValue(attrName) {\n if (this.path.length === 0) return undefined;\n return this.path[this.path.length - 1].values?.[attrName];\n }\n\n /**\n * Check if current node has an attribute.\n * @param {string} attrName\n * @returns {boolean}\n */\n hasAttr(attrName) {\n if (this.path.length === 0) return false;\n const current = this.path[this.path.length - 1];\n return current.values !== undefined && attrName in current.values;\n }\n\n /**\n * Get current node's sibling position (child index in parent).\n * @returns {number}\n */\n getPosition() {\n if (this.path.length === 0) return -1;\n return this.path[this.path.length - 1].position ?? 0;\n }\n\n /**\n * Get current node's repeat counter (occurrence count of this tag name).\n * @returns {number}\n */\n getCounter() {\n if (this.path.length === 0) return -1;\n return this.path[this.path.length - 1].counter ?? 0;\n }\n\n /**\n * Get current node's sibling index (alias for getPosition).\n * @returns {number}\n * @deprecated Use getPosition() or getCounter() instead\n */\n getIndex() {\n return this.getPosition();\n }\n\n /**\n * Get current path depth.\n * @returns {number}\n */\n getDepth() {\n return this.path.length;\n }\n\n /**\n * Get path as string.\n * @param {string} [separator] - Optional separator (uses default if not provided)\n * @param {boolean} [includeNamespace=true]\n * @returns {string}\n */\n toString(separator, includeNamespace = true) {\n const sep = separator || this.separator;\n const isDefault = (sep === this.separator && includeNamespace === true);\n\n if (isDefault) {\n if (this._pathStringCache !== null) {\n return this._pathStringCache;\n }\n const result = this.path.map(n =>\n (n.namespace) ? `${n.namespace}:${n.tag}` : n.tag\n ).join(sep);\n this._pathStringCache = result;\n return result;\n }\n\n return this.path.map(n =>\n (includeNamespace && n.namespace) ? `${n.namespace}:${n.tag}` : n.tag\n ).join(sep);\n }\n\n /**\n * Get path as array of tag names.\n * @returns {string[]}\n */\n toArray() {\n return this.path.map(n => n.tag);\n }\n\n /**\n * Reset the path to empty.\n */\n reset() {\n this._pathStringCache = null;\n this.path = [];\n this.siblingStacks = [];\n }\n\n /**\n * Match current path against an Expression.\n * @param {Expression} expression\n * @returns {boolean}\n */\n matches(expression) {\n const segments = expression.segments;\n\n if (segments.length === 0) {\n return false;\n }\n\n if (expression.hasDeepWildcard()) {\n return this._matchWithDeepWildcard(segments);\n }\n\n return this._matchSimple(segments);\n }\n\n /**\n * @private\n */\n _matchSimple(segments) {\n if (this.path.length !== segments.length) {\n return false;\n }\n\n for (let i = 0; i < segments.length; i++) {\n if (!this._matchSegment(segments[i], this.path[i], i === this.path.length - 1)) {\n return false;\n }\n }\n\n return true;\n }\n\n /**\n * @private\n */\n _matchWithDeepWildcard(segments) {\n let pathIdx = this.path.length - 1;\n let segIdx = segments.length - 1;\n\n while (segIdx >= 0 && pathIdx >= 0) {\n const segment = segments[segIdx];\n\n if (segment.type === 'deep-wildcard') {\n segIdx--;\n\n if (segIdx < 0) {\n return true;\n }\n\n const nextSeg = segments[segIdx];\n let found = false;\n\n for (let i = pathIdx; i >= 0; i--) {\n if (this._matchSegment(nextSeg, this.path[i], i === this.path.length - 1)) {\n pathIdx = i - 1;\n segIdx--;\n found = true;\n break;\n }\n }\n\n if (!found) {\n return false;\n }\n } else {\n if (!this._matchSegment(segment, this.path[pathIdx], pathIdx === this.path.length - 1)) {\n return false;\n }\n pathIdx--;\n segIdx--;\n }\n }\n\n return segIdx < 0;\n }\n\n /**\n * @private\n */\n _matchSegment(segment, node, isCurrentNode) {\n if (segment.tag !== '*' && segment.tag !== node.tag) {\n return false;\n }\n\n if (segment.namespace !== undefined) {\n if (segment.namespace !== '*' && segment.namespace !== node.namespace) {\n return false;\n }\n }\n\n if (segment.attrName !== undefined) {\n if (!isCurrentNode) {\n return false;\n }\n\n if (!node.values || !(segment.attrName in node.values)) {\n return false;\n }\n\n if (segment.attrValue !== undefined) {\n if (String(node.values[segment.attrName]) !== String(segment.attrValue)) {\n return false;\n }\n }\n }\n\n if (segment.position !== undefined) {\n if (!isCurrentNode) {\n return false;\n }\n\n const counter = node.counter ?? 0;\n\n if (segment.position === 'first' && counter !== 0) {\n return false;\n } else if (segment.position === 'odd' && counter % 2 !== 1) {\n return false;\n } else if (segment.position === 'even' && counter % 2 !== 0) {\n return false;\n } else if (segment.position === 'nth' && counter !== segment.positionValue) {\n return false;\n }\n }\n\n return true;\n }\n\n /**\n * Match any expression in the given set against the current path.\n * @param {ExpressionSet} exprSet\n * @returns {boolean}\n */\n matchesAny(exprSet) {\n return exprSet.matchesAny(this);\n }\n\n /**\n * Create a snapshot of current state.\n * @returns {Object}\n */\n snapshot() {\n return {\n path: this.path.map(node => ({ ...node })),\n siblingStacks: this.siblingStacks.map(map => new Map(map))\n };\n }\n\n /**\n * Restore state from snapshot.\n * @param {Object} snapshot\n */\n restore(snapshot) {\n this._pathStringCache = null;\n this.path = snapshot.path.map(node => ({ ...node }));\n this.siblingStacks = snapshot.siblingStacks.map(map => new Map(map));\n }\n\n /**\n * Return the read-only {@link MatcherView} for this matcher.\n *\n * The same instance is returned on every call — no allocation occurs.\n * It always reflects the current parser state and is safe to pass to\n * user callbacks without risk of accidental mutation.\n *\n * @returns {MatcherView}\n *\n * @example\n * const view = matcher.readOnly();\n * // pass view to callbacks — it stays in sync automatically\n * view.matches(expr); // ✓\n * view.getCurrentTag(); // ✓\n * // view.push(...) // ✗ method does not exist — caught by TypeScript\n */\n readOnly() {\n return this._view;\n }\n}","'use strict';\n///@ts-check\n\nimport { getAllMatches, isExist, DANGEROUS_PROPERTY_NAMES, criticalProperties } from '../util.js';\nimport xmlNode from './xmlNode.js';\nimport DocTypeReader from './DocTypeReader.js';\nimport toNumber from \"strnum\";\nimport getIgnoreAttributesFn from \"../ignoreAttributes.js\";\nimport { Expression, Matcher } from 'path-expression-matcher';\nimport { ExpressionSet } from 'path-expression-matcher';\nimport { EntityDecoder, XML, CURRENCY, COMMON_HTML } from '@nodable/entities';\n\n// const regx =\n// '<((!\\\\[CDATA\\\\[([\\\\s\\\\S]*?)(]]>))|((NAME:)?(NAME))([^>]*)>|((\\\\/)(NAME)\\\\s*>))([^<]*)'\n// .replace(/NAME/g, util.nameRegexp);\n\n//const tagsRegx = new RegExp(\"<(\\\\/?[\\\\w:\\\\-\\._]+)([^>]*)>(\\\\s*\"+cdataRegx+\")*([^<]+)?\",\"g\");\n//const tagsRegx = new RegExp(\"<(\\\\/?)((\\\\w*:)?([\\\\w:\\\\-\\._]+))([^>]*)>([^<]*)(\"+cdataRegx+\"([^<]*))*([^<]+)?\",\"g\");\n\n// Helper functions for attribute and namespace handling\n\n/**\n * Extract raw attributes (without prefix) from prefixed attribute map\n * @param {object} prefixedAttrs - Attributes with prefix from buildAttributesMap\n * @param {object} options - Parser options containing attributeNamePrefix\n * @returns {object} Raw attributes for matcher\n */\nfunction extractRawAttributes(prefixedAttrs, options) {\n if (!prefixedAttrs) return {};\n\n // Handle attributesGroupName option\n const attrs = options.attributesGroupName\n ? prefixedAttrs[options.attributesGroupName]\n : prefixedAttrs;\n\n if (!attrs) return {};\n\n const rawAttrs = {};\n for (const key in attrs) {\n // Remove the attribute prefix to get raw name\n if (key.startsWith(options.attributeNamePrefix)) {\n const rawName = key.substring(options.attributeNamePrefix.length);\n rawAttrs[rawName] = attrs[key];\n } else {\n // Attribute without prefix (shouldn't normally happen, but be safe)\n rawAttrs[key] = attrs[key];\n }\n }\n return rawAttrs;\n}\n\n/**\n * Extract namespace from raw tag name\n * @param {string} rawTagName - Tag name possibly with namespace (e.g., \"soap:Envelope\")\n * @returns {string|undefined} Namespace or undefined\n */\nfunction extractNamespace(rawTagName) {\n if (!rawTagName || typeof rawTagName !== 'string') return undefined;\n\n const colonIndex = rawTagName.indexOf(':');\n if (colonIndex !== -1 && colonIndex > 0) {\n const ns = rawTagName.substring(0, colonIndex);\n // Don't treat xmlns as a namespace\n if (ns !== 'xmlns') {\n return ns;\n }\n }\n return undefined;\n}\n\nexport default class OrderedObjParser {\n constructor(options, externalEntities) {\n this.options = options;\n this.currentNode = null;\n this.tagsNodeStack = [];\n this.parseXml = parseXml;\n this.parseTextData = parseTextData;\n this.resolveNameSpace = resolveNameSpace;\n this.buildAttributesMap = buildAttributesMap;\n this.isItStopNode = isItStopNode;\n this.replaceEntitiesValue = replaceEntitiesValue;\n this.readStopNodeData = readStopNodeData;\n this.saveTextToParentTag = saveTextToParentTag;\n this.addChild = addChild;\n this.ignoreAttributesFn = getIgnoreAttributesFn(this.options.ignoreAttributes)\n this.entityExpansionCount = 0;\n this.currentExpandedLength = 0;\n let namedEntities = { ...XML };\n if (this.options.entityDecoder) {\n this.entityDecoder = this.options.entityDecoder\n } else {\n if (typeof this.options.htmlEntities === \"object\") namedEntities = this.options.htmlEntities;\n else if (this.options.htmlEntities === true) namedEntities = { ...COMMON_HTML, ...CURRENCY };\n this.entityDecoder = new EntityDecoder({\n namedEntities: { ...namedEntities, ...externalEntities },\n numericAllowed: this.options.htmlEntities,\n limit: {\n maxTotalExpansions: this.options.processEntities.maxTotalExpansions,\n maxExpandedLength: this.options.processEntities.maxExpandedLength,\n applyLimitsTo: this.options.processEntities.appliesTo,\n }\n //postCheck: resolved => resolved\n });\n }\n\n // Initialize path matcher for path-expression-matcher\n this.matcher = new Matcher();\n\n // Live read-only proxy of matcher — PEM creates and caches this internally.\n // All user callbacks receive this instead of the mutable matcher.\n this.readonlyMatcher = this.matcher.readOnly();\n\n // Flag to track if current node is a stop node (optimization)\n this.isCurrentNodeStopNode = false;\n\n // Pre-compile stopNodes expressions\n this.stopNodeExpressionsSet = new ExpressionSet();\n const stopNodesOpts = this.options.stopNodes;\n if (stopNodesOpts && stopNodesOpts.length > 0) {\n for (let i = 0; i < stopNodesOpts.length; i++) {\n const stopNodeExp = stopNodesOpts[i];\n if (typeof stopNodeExp === 'string') {\n // Convert string to Expression object\n this.stopNodeExpressionsSet.add(new Expression(stopNodeExp));\n } else if (stopNodeExp instanceof Expression) {\n // Already an Expression object\n this.stopNodeExpressionsSet.add(stopNodeExp);\n }\n }\n this.stopNodeExpressionsSet.seal();\n }\n }\n\n}\n\n\n/**\n * @param {string} val\n * @param {string} tagName\n * @param {string|Matcher} jPath - jPath string or Matcher instance based on options.jPath\n * @param {boolean} dontTrim\n * @param {boolean} hasAttributes\n * @param {boolean} isLeafNode\n * @param {boolean} escapeEntities\n */\nfunction parseTextData(val, tagName, jPath, dontTrim, hasAttributes, isLeafNode, escapeEntities) {\n const options = this.options;\n if (val !== undefined) {\n if (options.trimValues && !dontTrim) {\n val = val.trim();\n }\n if (val.length > 0) {\n if (!escapeEntities) val = this.replaceEntitiesValue(val, tagName, jPath);\n\n // Pass jPath string or matcher based on options.jPath setting\n const jPathOrMatcher = options.jPath ? jPath.toString() : jPath;\n const newval = options.tagValueProcessor(tagName, val, jPathOrMatcher, hasAttributes, isLeafNode);\n if (newval === null || newval === undefined) {\n //don't parse\n return val;\n } else if (typeof newval !== typeof val || newval !== val) {\n //overwrite\n return newval;\n } else if (options.trimValues) {\n return parseValue(val, options.parseTagValue, options.numberParseOptions);\n } else {\n const trimmedVal = val.trim();\n if (trimmedVal === val) {\n return parseValue(val, options.parseTagValue, options.numberParseOptions);\n } else {\n return val;\n }\n }\n }\n }\n}\n\nfunction resolveNameSpace(tagname) {\n if (this.options.removeNSPrefix) {\n const tags = tagname.split(':');\n const prefix = tagname.charAt(0) === '/' ? '/' : '';\n if (tags[0] === 'xmlns') {\n return '';\n }\n if (tags.length === 2) {\n tagname = prefix + tags[1];\n }\n }\n return tagname;\n}\n\n//TODO: change regex to capture NS\n//const attrsRegx = new RegExp(\"([\\\\w\\\\-\\\\.\\\\:]+)\\\\s*=\\\\s*(['\\\"])((.|\\n)*?)\\\\2\",\"gm\");\nconst attrsRegx = new RegExp('([^\\\\s=]+)\\\\s*(=\\\\s*([\\'\"])([\\\\s\\\\S]*?)\\\\3)?', 'gm');\n\nfunction buildAttributesMap(attrStr, jPath, tagName, force = false) {\n const options = this.options;\n if (force === true || (options.ignoreAttributes !== true && typeof attrStr === 'string')) {\n // attrStr = attrStr.replace(/\\r?\\n/g, ' ');\n //attrStr = attrStr || attrStr.trim();\n\n const matches = getAllMatches(attrStr, attrsRegx);\n const len = matches.length; //don't make it inline\n const attrs = {};\n\n // Pre-process values once: trim + entity replacement\n // Reused in both matcher update and second pass\n const processedVals = new Array(len);\n let hasRawAttrs = false;\n const rawAttrsForMatcher = {};\n\n for (let i = 0; i < len; i++) {\n const attrName = this.resolveNameSpace(matches[i][1]);\n const oldVal = matches[i][4];\n\n if (attrName.length && oldVal !== undefined) {\n let val = oldVal;\n if (options.trimValues) val = val.trim();\n val = this.replaceEntitiesValue(val, tagName, this.readonlyMatcher);\n processedVals[i] = val;\n\n rawAttrsForMatcher[attrName] = val;\n hasRawAttrs = true;\n }\n }\n\n // Update matcher ONCE before second pass, if applicable\n if (hasRawAttrs && typeof jPath === 'object' && jPath.updateCurrent) {\n jPath.updateCurrent(rawAttrsForMatcher);\n }\n\n // Hoist toString() once — path doesn't change during attribute processing\n const jPathStr = options.jPath ? jPath.toString() : this.readonlyMatcher;\n\n // Second pass: apply processors, build final attrs\n let hasAttrs = false;\n for (let i = 0; i < len; i++) {\n const attrName = this.resolveNameSpace(matches[i][1]);\n\n if (this.ignoreAttributesFn(attrName, jPathStr)) continue;\n\n let aName = options.attributeNamePrefix + attrName;\n\n if (attrName.length) {\n if (options.transformAttributeName) {\n aName = options.transformAttributeName(aName);\n }\n aName = sanitizeName(aName, options);\n\n if (matches[i][4] !== undefined) {\n // Reuse already-processed value — no double entity replacement\n const oldVal = processedVals[i];\n\n const newVal = options.attributeValueProcessor(attrName, oldVal, jPathStr);\n if (newVal === null || newVal === undefined) {\n attrs[aName] = oldVal;\n } else if (typeof newVal !== typeof oldVal || newVal !== oldVal) {\n attrs[aName] = newVal;\n } else {\n attrs[aName] = parseValue(oldVal, options.parseAttributeValue, options.numberParseOptions);\n }\n hasAttrs = true;\n } else if (options.allowBooleanAttributes) {\n attrs[aName] = true;\n hasAttrs = true;\n }\n }\n }\n\n if (!hasAttrs) return;\n\n if (options.attributesGroupName && !options.preserveOrder) {\n const attrCollection = {};\n attrCollection[options.attributesGroupName] = attrs;\n return attrCollection;\n }\n return attrs;\n }\n}\nconst parseXml = function (xmlData) {\n xmlData = xmlData.replace(/\\r\\n?/g, \"\\n\"); //TODO: remove this line\n const xmlObj = new xmlNode('!xml');\n let currentNode = xmlObj;\n let textData = \"\";\n\n // Reset matcher for new document\n this.matcher.reset();\n this.entityDecoder.reset();\n\n // Reset entity expansion counters for this document\n this.entityExpansionCount = 0;\n this.currentExpandedLength = 0;\n const options = this.options;\n const docTypeReader = new DocTypeReader(options.processEntities);\n const xmlLen = xmlData.length;\n for (let i = 0; i < xmlLen; i++) {//for each char in XML data\n const ch = xmlData[i];\n if (ch === '<') {\n // const nextIndex = i+1;\n // const _2ndChar = xmlData[nextIndex];\n const c1 = xmlData.charCodeAt(i + 1);\n if (c1 === 47) {//Closing Tag '/'\n const closeIndex = findClosingIndex(xmlData, \">\", i, \"Closing Tag is not closed.\")\n let tagName = xmlData.substring(i + 2, closeIndex).trim();\n\n if (options.removeNSPrefix) {\n const colonIndex = tagName.indexOf(\":\");\n if (colonIndex !== -1) {\n tagName = tagName.substr(colonIndex + 1);\n }\n }\n\n tagName = transformTagName(options.transformTagName, tagName, \"\", options).tagName;\n\n if (currentNode) {\n textData = this.saveTextToParentTag(textData, currentNode, this.readonlyMatcher);\n }\n\n //check if last tag of nested tag was unpaired tag\n const lastTagName = this.matcher.getCurrentTag();\n if (tagName && options.unpairedTagsSet.has(tagName)) {\n throw new Error(`Unpaired tag can not be used as closing tag: </${tagName}>`);\n }\n if (lastTagName && options.unpairedTagsSet.has(lastTagName)) {\n // Pop the unpaired tag\n this.matcher.pop();\n this.tagsNodeStack.pop();\n }\n // Pop the closing tag\n this.matcher.pop();\n this.isCurrentNodeStopNode = false; // Reset flag when closing tag\n\n currentNode = this.tagsNodeStack.pop();//avoid recursion, set the parent tag scope\n textData = \"\";\n i = closeIndex;\n } else if (c1 === 63) { //'?'\n\n let tagData = readTagExp(xmlData, i, false, \"?>\");\n if (!tagData) throw new Error(\"Pi Tag is not closed.\");\n\n textData = this.saveTextToParentTag(textData, currentNode, this.readonlyMatcher);\n const attsMap = this.buildAttributesMap(tagData.tagExp, this.matcher, tagData.tagName, true);\n if (attsMap) {\n const ver = attsMap[this.options.attributeNamePrefix + \"version\"];\n this.entityDecoder.setXmlVersion(Number(ver) || 1.0);\n }\n if ((options.ignoreDeclaration && tagData.tagName === \"?xml\") || options.ignorePiTags) {\n //do nothing\n } else {\n\n const childNode = new xmlNode(tagData.tagName);\n childNode.add(options.textNodeName, \"\");\n\n if (tagData.tagName !== tagData.tagExp && tagData.attrExpPresent && options.ignoreAttributes !== true) {\n childNode[\":@\"] = attsMap\n }\n this.addChild(currentNode, childNode, this.readonlyMatcher, i);\n }\n\n\n i = tagData.closeIndex + 1;\n } else if (c1 === 33\n && xmlData.charCodeAt(i + 2) === 45\n && xmlData.charCodeAt(i + 3) === 45) { //'!--'\n const endIndex = findClosingIndex(xmlData, \"-->\", i + 4, \"Comment is not closed.\")\n if (options.commentPropName) {\n const comment = xmlData.substring(i + 4, endIndex - 2);\n\n textData = this.saveTextToParentTag(textData, currentNode, this.readonlyMatcher);\n\n currentNode.add(options.commentPropName, [{ [options.textNodeName]: comment }]);\n }\n i = endIndex;\n } else if (c1 === 33\n && xmlData.charCodeAt(i + 2) === 68) { //'!D'\n const result = docTypeReader.readDocType(xmlData, i);\n this.entityDecoder.addInputEntities(result.entities);\n i = result.i;\n } else if (c1 === 33\n && xmlData.charCodeAt(i + 2) === 91) { // '!['\n const closeIndex = findClosingIndex(xmlData, \"]]>\", i, \"CDATA is not closed.\") - 2;\n const tagExp = xmlData.substring(i + 9, closeIndex);\n\n textData = this.saveTextToParentTag(textData, currentNode, this.readonlyMatcher);\n\n let val = this.parseTextData(tagExp, currentNode.tagname, this.readonlyMatcher, true, false, true, true);\n if (val == undefined) val = \"\";\n\n //cdata should be set even if it is 0 length string\n if (options.cdataPropName) {\n currentNode.add(options.cdataPropName, [{ [options.textNodeName]: tagExp }]);\n } else {\n currentNode.add(options.textNodeName, val);\n }\n\n i = closeIndex + 2;\n } else {//Opening tag\n let result = readTagExp(xmlData, i, options.removeNSPrefix);\n\n // Safety check: readTagExp can return undefined\n if (!result) {\n // Log context for debugging\n const context = xmlData.substring(Math.max(0, i - 50), Math.min(xmlLen, i + 50));\n throw new Error(`readTagExp returned undefined at position ${i}. Context: \"${context}\"`);\n }\n\n let tagName = result.tagName;\n const rawTagName = result.rawTagName;\n let tagExp = result.tagExp;\n let attrExpPresent = result.attrExpPresent;\n let closeIndex = result.closeIndex;\n\n ({ tagName, tagExp } = transformTagName(options.transformTagName, tagName, tagExp, options));\n\n if (options.strictReservedNames &&\n (tagName === options.commentPropName\n || tagName === options.cdataPropName\n || tagName === options.textNodeName\n || tagName === options.attributesGroupName\n )) {\n throw new Error(`Invalid tag name: ${tagName}`);\n }\n\n //save text as child node\n if (currentNode && textData) {\n if (currentNode.tagname !== '!xml') {\n //when nested tag is found\n textData = this.saveTextToParentTag(textData, currentNode, this.readonlyMatcher, false);\n }\n }\n\n //check if last tag was unpaired tag\n const lastTag = currentNode;\n if (lastTag && options.unpairedTagsSet.has(lastTag.tagname)) {\n currentNode = this.tagsNodeStack.pop();\n this.matcher.pop();\n }\n\n // Clean up self-closing syntax BEFORE processing attributes\n // This is where tagExp gets the trailing / removed\n let isSelfClosing = false;\n if (tagExp.length > 0 && tagExp.lastIndexOf(\"/\") === tagExp.length - 1) {\n isSelfClosing = true;\n if (tagName[tagName.length - 1] === \"/\") {\n tagName = tagName.substr(0, tagName.length - 1);\n tagExp = tagName;\n } else {\n tagExp = tagExp.substr(0, tagExp.length - 1);\n }\n\n // Re-check attrExpPresent after cleaning\n attrExpPresent = (tagName !== tagExp);\n }\n\n // Now process attributes with CLEAN tagExp (no trailing /)\n let prefixedAttrs = null;\n let rawAttrs = {};\n let namespace = undefined;\n\n // Extract namespace from rawTagName\n namespace = extractNamespace(rawTagName);\n\n // Push tag to matcher FIRST (with empty attrs for now) so callbacks see correct path\n if (tagName !== xmlObj.tagname) {\n this.matcher.push(tagName, {}, namespace);\n }\n\n // Now build attributes - callbacks will see correct matcher state\n if (tagName !== tagExp && attrExpPresent) {\n // Build attributes (returns prefixed attributes for the tree)\n // Note: buildAttributesMap now internally updates the matcher with raw attributes\n prefixedAttrs = this.buildAttributesMap(tagExp, this.matcher, tagName);\n\n if (prefixedAttrs) {\n // Extract raw attributes (without prefix) for our use\n //TODO: seems a performance overhead\n rawAttrs = extractRawAttributes(prefixedAttrs, options);\n }\n }\n\n // Now check if this is a stop node (after attributes are set)\n if (tagName !== xmlObj.tagname) {\n this.isCurrentNodeStopNode = this.isItStopNode();\n }\n\n const startIndex = i;\n if (this.isCurrentNodeStopNode) {\n let tagContent = \"\";\n\n // For self-closing tags, content is empty\n if (isSelfClosing) {\n i = result.closeIndex;\n }\n //unpaired tag\n else if (options.unpairedTagsSet.has(tagName)) {\n i = result.closeIndex;\n }\n //normal tag\n else {\n //read until closing tag is found\n const result = this.readStopNodeData(xmlData, rawTagName, closeIndex + 1);\n if (!result) throw new Error(`Unexpected end of ${rawTagName}`);\n i = result.i;\n tagContent = result.tagContent;\n }\n\n const childNode = new xmlNode(tagName);\n\n if (prefixedAttrs) {\n childNode[\":@\"] = prefixedAttrs;\n }\n\n // For stop nodes, store raw content as-is without any processing\n childNode.add(options.textNodeName, tagContent);\n\n this.matcher.pop(); // Pop the stop node tag\n this.isCurrentNodeStopNode = false; // Reset flag\n\n this.addChild(currentNode, childNode, this.readonlyMatcher, startIndex);\n } else {\n //selfClosing tag\n if (isSelfClosing) {\n ({ tagName, tagExp } = transformTagName(options.transformTagName, tagName, tagExp, options));\n\n const childNode = new xmlNode(tagName);\n if (prefixedAttrs) {\n childNode[\":@\"] = prefixedAttrs;\n }\n this.addChild(currentNode, childNode, this.readonlyMatcher, startIndex);\n this.matcher.pop(); // Pop self-closing tag\n this.isCurrentNodeStopNode = false; // Reset flag\n }\n else if (options.unpairedTagsSet.has(tagName)) {//unpaired tag\n const childNode = new xmlNode(tagName);\n if (prefixedAttrs) {\n childNode[\":@\"] = prefixedAttrs;\n }\n this.addChild(currentNode, childNode, this.readonlyMatcher, startIndex);\n this.matcher.pop(); // Pop unpaired tag\n this.isCurrentNodeStopNode = false; // Reset flag\n i = result.closeIndex;\n // Continue to next iteration without changing currentNode\n continue;\n }\n //opening tag\n else {\n const childNode = new xmlNode(tagName);\n if (this.tagsNodeStack.length > options.maxNestedTags) {\n throw new Error(\"Maximum nested tags exceeded\");\n }\n this.tagsNodeStack.push(currentNode);\n\n if (prefixedAttrs) {\n childNode[\":@\"] = prefixedAttrs;\n }\n this.addChild(currentNode, childNode, this.readonlyMatcher, startIndex);\n currentNode = childNode;\n }\n textData = \"\";\n i = closeIndex;\n }\n }\n } else {\n textData += xmlData[i];\n }\n }\n return xmlObj.child;\n}\n\nfunction addChild(currentNode, childNode, matcher, startIndex) {\n // unset startIndex if not requested\n if (!this.options.captureMetaData) startIndex = undefined;\n\n // Pass jPath string or matcher based on options.jPath setting\n const jPathOrMatcher = this.options.jPath ? matcher.toString() : matcher;\n const result = this.options.updateTag(childNode.tagname, jPathOrMatcher, childNode[\":@\"])\n if (result === false) {\n //do nothing\n } else if (typeof result === \"string\") {\n childNode.tagname = result\n currentNode.addChild(childNode, startIndex);\n } else {\n currentNode.addChild(childNode, startIndex);\n }\n}\n\n/**\n * @param {object} val - Entity object with regex and val properties\n * @param {string} tagName - Tag name\n * @param {string|Matcher} jPath - jPath string or Matcher instance based on options.jPath\n */\nfunction replaceEntitiesValue(val, tagName, jPath) {\n const entityConfig = this.options.processEntities;\n\n if (!entityConfig || !entityConfig.enabled) {\n return val;\n }\n\n // Check if tag is allowed to contain entities\n if (entityConfig.allowedTags) {\n const jPathOrMatcher = this.options.jPath ? jPath.toString() : jPath;\n const allowed = Array.isArray(entityConfig.allowedTags)\n ? entityConfig.allowedTags.includes(tagName)\n : entityConfig.allowedTags(tagName, jPathOrMatcher);\n\n if (!allowed) {\n return val;\n }\n }\n\n // Apply custom tag filter if provided\n if (entityConfig.tagFilter) {\n const jPathOrMatcher = this.options.jPath ? jPath.toString() : jPath;\n if (!entityConfig.tagFilter(tagName, jPathOrMatcher)) {\n return val; // Skip based on custom filter\n }\n }\n\n return this.entityDecoder.decode(val);\n}\n\n\nfunction saveTextToParentTag(textData, parentNode, matcher, isLeafNode) {\n if (textData) { //store previously collected data as textNode\n if (isLeafNode === undefined) isLeafNode = parentNode.child.length === 0\n\n textData = this.parseTextData(textData,\n parentNode.tagname,\n matcher,\n false,\n parentNode[\":@\"] ? Object.keys(parentNode[\":@\"]).length !== 0 : false,\n isLeafNode);\n\n if (textData !== undefined && textData !== \"\")\n parentNode.add(this.options.textNodeName, textData);\n textData = \"\";\n }\n return textData;\n}\n\n/**\n * @param {Array<Expression>} stopNodeExpressions - Array of compiled Expression objects\n * @param {Matcher} matcher - Current path matcher\n */\nfunction isItStopNode() {\n if (this.stopNodeExpressionsSet.size === 0) return false;\n\n return this.matcher.matchesAny(this.stopNodeExpressionsSet);\n}\n\n/**\n * Returns the tag Expression and where it is ending handling single-double quotes situation\n * @param {string} xmlData \n * @param {number} i starting index\n * @returns \n */\nfunction tagExpWithClosingIndex(xmlData, i, closingChar = \">\") {\n //TODO: ignore boolean attributes in tag expression\n //TODO: if ignore attributes, dont read full attribute expression but the end. But read for xml declaration\n let attrBoundary = 0;\n const len = xmlData.length;\n const closeCode0 = closingChar.charCodeAt(0);\n const closeCode1 = closingChar.length > 1 ? closingChar.charCodeAt(1) : -1;\n\n let result = '';\n let segmentStart = i;\n\n for (let index = i; index < len; index++) {\n const code = xmlData.charCodeAt(index);\n\n if (attrBoundary) {\n if (code === attrBoundary) attrBoundary = 0;\n } else if (code === 34 || code === 39) { // \" or '\n attrBoundary = code;\n } else if (code === closeCode0) {\n if (closeCode1 !== -1) {\n if (xmlData.charCodeAt(index + 1) === closeCode1) {\n result += xmlData.substring(segmentStart, index);\n return { data: result, index };\n }\n } else {\n result += xmlData.substring(segmentStart, index);\n return { data: result, index };\n }\n } else if (code === 9 && !attrBoundary) { // \\t - only replace with space outside attribute values\n // Flush accumulated segment, add space, start new segment\n result += xmlData.substring(segmentStart, index) + ' ';\n segmentStart = index + 1;\n }\n }\n}\n\nfunction findClosingIndex(xmlData, str, i, errMsg) {\n const closingIndex = xmlData.indexOf(str, i);\n if (closingIndex === -1) {\n throw new Error(errMsg)\n } else {\n return closingIndex + str.length - 1;\n }\n}\n\nfunction findClosingChar(xmlData, char, i, errMsg) {\n const closingIndex = xmlData.indexOf(char, i);\n if (closingIndex === -1) throw new Error(errMsg);\n return closingIndex; // no offset needed\n}\n\nfunction readTagExp(xmlData, i, removeNSPrefix, closingChar = \">\") {\n const result = tagExpWithClosingIndex(xmlData, i + 1, closingChar);\n if (!result) return;\n let tagExp = result.data;\n const closeIndex = result.index;\n const separatorIndex = tagExp.search(/\\s/);\n let tagName = tagExp;\n let attrExpPresent = true;\n if (separatorIndex !== -1) {//separate tag name and attributes expression\n tagName = tagExp.substring(0, separatorIndex);\n tagExp = tagExp.substring(separatorIndex + 1).trimStart();\n }\n\n const rawTagName = tagName;\n if (removeNSPrefix) {\n const colonIndex = tagName.indexOf(\":\");\n if (colonIndex !== -1) {\n tagName = tagName.substr(colonIndex + 1);\n attrExpPresent = tagName !== result.data.substr(colonIndex + 1);\n }\n }\n\n return {\n tagName: tagName,\n tagExp: tagExp,\n closeIndex: closeIndex,\n attrExpPresent: attrExpPresent,\n rawTagName: rawTagName,\n }\n}\n/**\n * find paired tag for a stop node\n * @param {string} xmlData \n * @param {string} tagName \n * @param {number} i \n */\nfunction readStopNodeData(xmlData, tagName, i) {\n const startIndex = i;\n // Starting at 1 since we already have an open tag\n let openTagCount = 1;\n\n const xmllen = xmlData.length;\n for (; i < xmllen; i++) {\n if (xmlData[i] === \"<\") {\n const c1 = xmlData.charCodeAt(i + 1);\n if (c1 === 47) {//close tag '/'\n const closeIndex = findClosingChar(xmlData, \">\", i, `${tagName} is not closed`);\n let closeTagName = xmlData.substring(i + 2, closeIndex).trim();\n if (closeTagName === tagName) {\n openTagCount--;\n if (openTagCount === 0) {\n return {\n tagContent: xmlData.substring(startIndex, i),\n i: closeIndex\n }\n }\n }\n i = closeIndex;\n } else if (c1 === 63) { //?\n const closeIndex = findClosingIndex(xmlData, \"?>\", i + 1, \"StopNode is not closed.\")\n i = closeIndex;\n } else if (c1 === 33\n && xmlData.charCodeAt(i + 2) === 45\n && xmlData.charCodeAt(i + 3) === 45) { // '!--'\n const closeIndex = findClosingIndex(xmlData, \"-->\", i + 3, \"StopNode is not closed.\")\n i = closeIndex;\n } else if (c1 === 33\n && xmlData.charCodeAt(i + 2) === 91) { // '!['\n const closeIndex = findClosingIndex(xmlData, \"]]>\", i, \"StopNode is not closed.\") - 2;\n i = closeIndex;\n } else {\n const tagData = readTagExp(xmlData, i, '>')\n\n if (tagData) {\n const openTagName = tagData && tagData.tagName;\n if (openTagName === tagName && tagData.tagExp[tagData.tagExp.length - 1] !== \"/\") {\n openTagCount++;\n }\n i = tagData.closeIndex;\n }\n }\n }\n }//end for loop\n}\n\nfunction parseValue(val, shouldParse, options) {\n if (shouldParse && typeof val === 'string') {\n //console.log(options)\n const newval = val.trim();\n if (newval === 'true') return true;\n else if (newval === 'false') return false;\n else return toNumber(val, options);\n } else {\n if (isExist(val)) {\n return val;\n } else {\n return '';\n }\n }\n}\n\nfunction fromCodePoint(str, base, prefix) {\n const codePoint = Number.parseInt(str, base);\n\n if (codePoint >= 0 && codePoint <= 0x10FFFF) {\n return String.fromCodePoint(codePoint);\n } else {\n return prefix + str + \";\";\n }\n}\n\nfunction transformTagName(fn, tagName, tagExp, options) {\n if (fn) {\n const newTagName = fn(tagName);\n if (tagExp === tagName) {\n tagExp = newTagName\n }\n tagName = newTagName;\n }\n tagName = sanitizeName(tagName, options);\n return { tagName, tagExp };\n}\n\n\n\nfunction sanitizeName(name, options) {\n if (criticalProperties.includes(name)) {\n throw new Error(`[SECURITY] Invalid name: \"${name}\" is a reserved JavaScript keyword that could cause prototype pollution`);\n } else if (DANGEROUS_PROPERTY_NAMES.includes(name)) {\n return options.onDangerousProperty(name);\n }\n return name;\n}","'use strict';\n\nimport XmlNode from './xmlNode.js';\nimport { Matcher } from 'path-expression-matcher';\n\nconst METADATA_SYMBOL = XmlNode.getMetaDataSymbol();\n\n/**\n * Helper function to strip attribute prefix from attribute map\n * @param {object} attrs - Attributes with prefix (e.g., {\"@_class\": \"code\"})\n * @param {string} prefix - Attribute prefix to remove (e.g., \"@_\")\n * @returns {object} Attributes without prefix (e.g., {\"class\": \"code\"})\n */\nfunction stripAttributePrefix(attrs, prefix) {\n if (!attrs || typeof attrs !== 'object') return {};\n if (!prefix) return attrs;\n\n const rawAttrs = {};\n for (const key in attrs) {\n if (key.startsWith(prefix)) {\n const rawName = key.substring(prefix.length);\n rawAttrs[rawName] = attrs[key];\n } else {\n // Attribute without prefix (shouldn't normally happen, but be safe)\n rawAttrs[key] = attrs[key];\n }\n }\n return rawAttrs;\n}\n\n/**\n * \n * @param {array} node \n * @param {any} options \n * @param {Matcher} matcher - Path matcher instance\n * @returns \n */\nexport default function prettify(node, options, matcher, readonlyMatcher) {\n return compress(node, options, matcher, readonlyMatcher);\n}\n\n/**\n * @param {array} arr \n * @param {object} options \n * @param {Matcher} matcher - Path matcher instance\n * @returns object\n */\nfunction compress(arr, options, matcher, readonlyMatcher) {\n let text;\n const compressedObj = {}; //This is intended to be a plain object\n for (let i = 0; i < arr.length; i++) {\n const tagObj = arr[i];\n const property = propName(tagObj);\n\n // Push current property to matcher WITH RAW ATTRIBUTES (no prefix)\n if (property !== undefined && property !== options.textNodeName) {\n const rawAttrs = stripAttributePrefix(\n tagObj[\":@\"] || {},\n options.attributeNamePrefix\n );\n matcher.push(property, rawAttrs);\n }\n\n if (property === options.textNodeName) {\n if (text === undefined) text = tagObj[property];\n else text += \"\" + tagObj[property];\n } else if (property === undefined) {\n continue;\n } else if (tagObj[property]) {\n\n let val = compress(tagObj[property], options, matcher, readonlyMatcher);\n const isLeaf = isLeafTag(val, options);\n\n if (tagObj[\":@\"]) {\n assignAttributes(val, tagObj[\":@\"], readonlyMatcher, options);\n } else if (Object.keys(val).length === 1 && val[options.textNodeName] !== undefined && !options.alwaysCreateTextNode) {\n val = val[options.textNodeName];\n } else if (Object.keys(val).length === 0) {\n if (options.alwaysCreateTextNode) val[options.textNodeName] = \"\";\n else val = \"\";\n }\n\n if (tagObj[METADATA_SYMBOL] !== undefined && typeof val === \"object\" && val !== null) {\n val[METADATA_SYMBOL] = tagObj[METADATA_SYMBOL]; // copy over metadata\n }\n\n\n if (compressedObj[property] !== undefined && Object.prototype.hasOwnProperty.call(compressedObj, property)) {\n if (!Array.isArray(compressedObj[property])) {\n compressedObj[property] = [compressedObj[property]];\n }\n compressedObj[property].push(val);\n } else {\n //TODO: if a node is not an array, then check if it should be an array\n //also determine if it is a leaf node\n\n // Pass jPath string or readonlyMatcher based on options.jPath setting\n const jPathOrMatcher = options.jPath ? readonlyMatcher.toString() : readonlyMatcher;\n if (options.isArray(property, jPathOrMatcher, isLeaf)) {\n compressedObj[property] = [val];\n } else {\n compressedObj[property] = val;\n }\n }\n\n // Pop property from matcher after processing\n if (property !== undefined && property !== options.textNodeName) {\n matcher.pop();\n }\n }\n\n }\n // if(text && text.length > 0) compressedObj[options.textNodeName] = text;\n if (typeof text === \"string\") {\n if (text.length > 0) compressedObj[options.textNodeName] = text;\n } else if (text !== undefined) compressedObj[options.textNodeName] = text;\n\n\n return compressedObj;\n}\n\nfunction propName(obj) {\n const keys = Object.keys(obj);\n for (let i = 0; i < keys.length; i++) {\n const key = keys[i];\n if (key !== \":@\") return key;\n }\n}\n\nfunction assignAttributes(obj, attrMap, readonlyMatcher, options) {\n if (attrMap) {\n const keys = Object.keys(attrMap);\n const len = keys.length; //don't make it inline\n for (let i = 0; i < len; i++) {\n const atrrName = keys[i]; // This is the PREFIXED name (e.g., \"@_class\")\n\n // Strip prefix for matcher path (for isArray callback)\n const rawAttrName = atrrName.startsWith(options.attributeNamePrefix)\n ? atrrName.substring(options.attributeNamePrefix.length)\n : atrrName;\n\n // For attributes, we need to create a temporary path\n // Pass jPath string or matcher based on options.jPath setting\n const jPathOrMatcher = options.jPath\n ? readonlyMatcher.toString() + \".\" + rawAttrName\n : readonlyMatcher;\n\n if (options.isArray(atrrName, jPathOrMatcher, true, true)) {\n obj[atrrName] = [attrMap[atrrName]];\n } else {\n obj[atrrName] = attrMap[atrrName];\n }\n }\n }\n}\n\nfunction isLeafTag(obj, options) {\n const { textNodeName } = options;\n const propCount = Object.keys(obj).length;\n\n if (propCount === 0) {\n return true;\n }\n\n if (\n propCount === 1 &&\n (obj[textNodeName] || typeof obj[textNodeName] === \"boolean\" || obj[textNodeName] === 0)\n ) {\n return true;\n }\n\n return false;\n}","import { buildOptions } from './OptionsBuilder.js';\nimport OrderedObjParser from './OrderedObjParser.js';\nimport prettify from './node2json.js';\nimport { validate } from \"../validator.js\";\nimport XmlNode from './xmlNode.js';\n\nexport default class XMLParser {\n\n constructor(options) {\n this.externalEntities = {};\n this.options = buildOptions(options);\n\n }\n /**\n * Parse XML dats to JS object \n * @param {string|Uint8Array} xmlData \n * @param {boolean|Object} validationOption \n */\n parse(xmlData, validationOption) {\n if (typeof xmlData !== \"string\" && xmlData.toString) {\n xmlData = xmlData.toString();\n } else if (typeof xmlData !== \"string\") {\n throw new Error(\"XML data is accepted in String or Bytes[] form.\")\n }\n\n if (validationOption) {\n if (validationOption === true) validationOption = {}; //validate with default options\n\n const result = validate(xmlData, validationOption);\n if (result !== true) {\n throw Error(`${result.err.msg}:${result.err.line}:${result.err.col}`)\n }\n }\n const orderedObjParser = new OrderedObjParser(this.options, this.externalEntities);\n // orderedObjParser.entityDecoder.setExternalEntities(this.externalEntities);\n const orderedResult = orderedObjParser.parseXml(xmlData);\n if (this.options.preserveOrder || orderedResult === undefined) return orderedResult;\n else return prettify(orderedResult, this.options, orderedObjParser.matcher, orderedObjParser.readonlyMatcher);\n }\n\n /**\n * Add Entity which is not by default supported by this library\n * @param {string} key \n * @param {string} value \n */\n addEntity(key, value) {\n if (value.indexOf(\"&\") !== -1) {\n throw new Error(\"Entity value can't have '&'\")\n } else if (key.indexOf(\"&\") !== -1 || key.indexOf(\";\") !== -1) {\n throw new Error(\"An entity must be set without '&' and ';'. Eg. use '#xD' for '
'\")\n } else if (value === \"&\") {\n throw new Error(\"An entity with value '&' is not permitted\");\n } else {\n this.externalEntities[key] = value;\n }\n }\n\n /**\n * Returns a Symbol that can be used to access the metadata\n * property on a node.\n * \n * If Symbol is not available in the environment, an ordinary property is used\n * and the name of the property is here returned.\n * \n * The XMLMetaData property is only present when `captureMetaData`\n * is true in the options.\n */\n static getMetaDataSymbol() {\n return XmlNode.getMetaDataSymbol();\n }\n}","import { XMLParser } from 'fast-xml-parser';\n\nexport type ContentFeedFormat = 'rss' | 'atom';\n\nexport interface ParsedContentFeedItem {\n title: string;\n url: string;\n guid: string | null;\n author: string | null;\n publishedAt: Date | null;\n updatedAt: Date | null;\n summary: string | null;\n categories: string[];\n}\n\nexport interface ParsedContentFeed {\n format: ContentFeedFormat;\n title: string | null;\n homepageUrl: string | null;\n items: ParsedContentFeedItem[];\n}\n\nfunction asArray<T>(value: T | T[] | null | undefined): T[] {\n if (value === null || value === undefined) return [];\n return Array.isArray(value) ? value : [value];\n}\n\nfunction textFromNode(value: unknown): string {\n if (value === null || value === undefined) return '';\n if (typeof value === 'string' || typeof value === 'number') {\n return String(value).trim();\n }\n if (typeof value !== 'object') return '';\n\n const record = value as Record<string, unknown>;\n return String(record['#text'] ?? record.__cdata ?? record.href ?? '').trim();\n}\n\nfunction firstText(...values: unknown[]): string {\n for (const value of values) {\n const text = textFromNode(value);\n if (text) return text;\n }\n return '';\n}\n\nfunction parseDate(value: unknown): Date | null {\n const text = textFromNode(value);\n if (!text) return null;\n const parsed = new Date(text);\n return Number.isNaN(parsed.getTime()) ? null : parsed;\n}\n\nfunction stripHtml(value: string): string {\n return value\n .replace(/<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi, '')\n .replace(/<style\\b[^<]*(?:(?!<\\/style>)<[^<]*)*<\\/style>/gi, '')\n .replace(/<[^>]+>/g, ' ')\n .replace(/ /g, ' ')\n .replace(/&/g, '&')\n .replace(/"/g, '\"')\n .replace(/'/g, \"'\")\n .replace(/'/g, \"'\")\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\\s+/g, ' ')\n .trim();\n}\n\nfunction excerpt(value: unknown): string | null {\n const text = stripHtml(textFromNode(value));\n if (!text) return null;\n return text.length > 500 ? `${text.slice(0, 497).trim()}...` : text;\n}\n\nfunction parseCategories(value: unknown): string[] {\n return Array.from(\n new Set(\n asArray(value)\n .map((entry) => {\n if (entry && typeof entry === 'object') {\n return firstText(entry, (entry as Record<string, unknown>).term);\n }\n return textFromNode(entry);\n })\n .map((entry) => entry.trim())\n .filter(Boolean),\n ),\n );\n}\n\nfunction parseAuthor(value: unknown): string | null {\n if (Array.isArray(value)) return parseAuthor(value[0]);\n if (value && typeof value === 'object') {\n return firstText((value as Record<string, unknown>).name, value) || null;\n }\n return textFromNode(value) || null;\n}\n\nfunction resolveUrl(value: string, baseUrl?: string | null): string {\n if (!value) return '';\n if (!baseUrl) return value;\n\n try {\n return new URL(value, baseUrl).toString();\n } catch {\n return value;\n }\n}\n\nfunction parseRssLink(value: unknown, baseUrl?: string | null): string {\n if (value && typeof value === 'object') {\n const record = value as Record<string, unknown>;\n return resolveUrl(\n firstText(record.href, record['#text'], record.__cdata),\n baseUrl,\n );\n }\n return resolveUrl(textFromNode(value), baseUrl);\n}\n\nfunction parseAtomLink(value: unknown, baseUrl?: string | null): string {\n const links = asArray(value);\n const alternate =\n links.find((entry) => {\n if (!entry || typeof entry !== 'object') return false;\n return (\n String((entry as Record<string, unknown>).rel ?? 'alternate') ===\n 'alternate'\n );\n }) ?? links[0];\n\n if (alternate && typeof alternate === 'object') {\n return resolveUrl(\n firstText((alternate as Record<string, unknown>).href, alternate),\n baseUrl,\n );\n }\n return resolveUrl(textFromNode(alternate), baseUrl);\n}\n\nfunction dedupeItems(items: ParsedContentFeedItem[]): ParsedContentFeedItem[] {\n const seen = new Set<string>();\n return items.filter((item) => {\n const key = item.guid || item.url;\n if (seen.has(key)) return false;\n seen.add(key);\n return true;\n });\n}\n\nexport function parseContentFeed(\n xml: string,\n baseUrl?: string | null,\n): ParsedContentFeed {\n const parser = new XMLParser({\n ignoreAttributes: false,\n attributeNamePrefix: '',\n cdataPropName: '__cdata',\n textNodeName: '#text',\n removeNSPrefix: true,\n trimValues: true,\n });\n const doc = parser.parse(xml) as Record<string, any>;\n\n if (doc.rss?.channel || doc.channel) {\n const channel = doc.rss?.channel ?? doc.channel;\n return {\n format: 'rss',\n title: firstText(channel.title) || null,\n homepageUrl: parseRssLink(channel.link, baseUrl) || null,\n items: dedupeItems(\n asArray(channel.item)\n .map(\n (item): ParsedContentFeedItem => ({\n title: firstText(item.title),\n url:\n parseRssLink(item.link, baseUrl) ||\n resolveUrl(firstText(item.guid), baseUrl),\n guid: firstText(item.guid, item.id) || null,\n author: parseAuthor(item.author ?? item.creator),\n publishedAt: parseDate(\n item.pubDate ?? item.published ?? item.date,\n ),\n updatedAt: parseDate(item.updated),\n summary: excerpt(\n item.description ?? item.summary ?? item.content,\n ),\n categories: parseCategories(item.category),\n }),\n )\n .filter((item) => item.title && item.url),\n ),\n };\n }\n\n if (doc.feed) {\n const feed = doc.feed;\n return {\n format: 'atom',\n title: firstText(feed.title) || null,\n homepageUrl: parseAtomLink(feed.link, baseUrl) || null,\n items: dedupeItems(\n asArray(feed.entry)\n .map(\n (entry): ParsedContentFeedItem => ({\n title: firstText(entry.title),\n url: parseAtomLink(entry.link, baseUrl),\n guid: firstText(entry.id) || null,\n author: parseAuthor(entry.author),\n publishedAt: parseDate(entry.published ?? entry.updated),\n updatedAt: parseDate(entry.updated),\n summary: excerpt(entry.summary ?? entry.content),\n categories: parseCategories(entry.category),\n }),\n )\n .filter((item) => item.title && item.url),\n ),\n };\n }\n\n throw new Error('Unsupported feed format');\n}\n","import type { SmrtObjectOptions } from '@happyvertical/smrt-core';\nimport { field, SmrtObject, smrt } from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport type { ContentFeedFormat } from './content-feed-parser';\n\nexport type ContentFeedSourceStatus =\n | 'active'\n | 'paused'\n | 'error'\n | 'archived';\n\nexport interface ContentFeedSourceOptions extends SmrtObjectOptions {\n tenantId?: string | null;\n name?: string;\n feedUrl?: string;\n homepageUrl?: string | null;\n format?: ContentFeedFormat | null;\n status?: ContentFeedSourceStatus;\n defaultCategory?: string | null;\n sourceGroup?: string | null;\n pollIntervalMinutes?: number;\n etag?: string | null;\n lastModified?: string | null;\n lastFetchedAt?: Date | string | null;\n lastSuccessAt?: Date | string | null;\n lastError?: string | null;\n metadata?: Record<string, any> | string;\n createdAt?: Date | string;\n updatedAt?: Date | string;\n}\n\nconst SOURCE_STATUSES = new Set<ContentFeedSourceStatus>([\n 'active',\n 'paused',\n 'error',\n 'archived',\n]);\n\nfunction parseDate(value: Date | string | null | undefined): Date | null {\n if (!value) return null;\n if (value instanceof Date) return value;\n const parsed = new Date(value);\n return Number.isNaN(parsed.getTime()) ? null : parsed;\n}\n\nfunction parseMetadata(\n value: Record<string, any> | string | undefined,\n): Record<string, any> {\n if (!value) return {};\n if (typeof value === 'object') return structuredClone(value);\n\n try {\n const parsed = JSON.parse(value);\n return parsed && typeof parsed === 'object' ? parsed : {};\n } catch {\n return {};\n }\n}\n\nfunction normalizePollIntervalMinutes(value: unknown): number {\n const parsed = Number(value);\n return Number.isFinite(parsed) && parsed > 0 ? Math.floor(parsed) : 15;\n}\n\nfunction normalizeStatus(value: unknown): ContentFeedSourceStatus {\n return typeof value === 'string' &&\n SOURCE_STATUSES.has(value as ContentFeedSourceStatus)\n ? (value as ContentFeedSourceStatus)\n : 'active';\n}\n\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableName: 'content_feed_sources',\n conflictColumns: ['tenant_id', 'feed_url'],\n api: { include: ['list', 'get', 'create', 'update', 'delete'] },\n mcp: { include: ['list', 'get', 'create', 'update', 'delete'] },\n cli: true,\n})\nexport class ContentFeedSource extends SmrtObject {\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n @field({ required: true })\n name = '';\n\n @field({ required: true })\n feedUrl = '';\n\n homepageUrl: string | null = null;\n format: ContentFeedFormat | null = null;\n @field({ type: 'text', required: true, default: 'active' })\n status: ContentFeedSourceStatus = 'active';\n defaultCategory: string | null = null;\n sourceGroup: string | null = null;\n pollIntervalMinutes = 15;\n etag: string | null = null;\n lastModified: string | null = null;\n lastFetchedAt: Date | null = null;\n lastSuccessAt: Date | null = null;\n lastError: string | null = null;\n metadata: Record<string, any> = {};\n createdAt = new Date();\n updatedAt = new Date();\n\n constructor(options: ContentFeedSourceOptions = {}) {\n super(options);\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n if (options.name !== undefined) this.name = options.name;\n if (options.feedUrl !== undefined) this.feedUrl = options.feedUrl;\n if (options.homepageUrl !== undefined)\n this.homepageUrl = options.homepageUrl;\n if (options.format !== undefined) this.format = options.format;\n if (options.status !== undefined)\n this.status = normalizeStatus(options.status);\n if (options.defaultCategory !== undefined)\n this.defaultCategory = options.defaultCategory;\n if (options.sourceGroup !== undefined)\n this.sourceGroup = options.sourceGroup;\n if (options.pollIntervalMinutes !== undefined) {\n this.pollIntervalMinutes = normalizePollIntervalMinutes(\n options.pollIntervalMinutes,\n );\n }\n if (options.etag !== undefined) this.etag = options.etag;\n if (options.lastModified !== undefined)\n this.lastModified = options.lastModified;\n if (options.lastFetchedAt !== undefined)\n this.lastFetchedAt = parseDate(options.lastFetchedAt);\n if (options.lastSuccessAt !== undefined)\n this.lastSuccessAt = parseDate(options.lastSuccessAt);\n if (options.lastError !== undefined) this.lastError = options.lastError;\n if (options.metadata !== undefined)\n this.metadata = parseMetadata(options.metadata);\n if (options.createdAt !== undefined)\n this.createdAt = parseDate(options.createdAt) ?? new Date();\n if (options.updatedAt !== undefined)\n this.updatedAt = parseDate(options.updatedAt) ?? new Date();\n }\n\n getMetadata(): Record<string, any> {\n return structuredClone(this.metadata);\n }\n\n setMetadata(metadata: Record<string, any>): void {\n this.metadata = structuredClone(metadata);\n this.updatedAt = new Date();\n }\n\n markFetchStarted(at = new Date()): void {\n this.lastFetchedAt = at;\n this.updatedAt = at;\n }\n\n markFetchSucceeded(\n at = new Date(),\n headers: { etag?: string | null; lastModified?: string | null } = {},\n ): void {\n this.status = 'active';\n this.lastFetchedAt = at;\n this.lastSuccessAt = at;\n this.lastError = null;\n if (headers.etag !== undefined) this.etag = headers.etag;\n if (headers.lastModified !== undefined)\n this.lastModified = headers.lastModified;\n this.updatedAt = at;\n }\n\n markFetchFailed(error: unknown, at = new Date()): void {\n this.status = 'error';\n this.lastFetchedAt = at;\n this.lastError = error instanceof Error ? error.message : String(error);\n this.updatedAt = at;\n }\n\n protected override transformJSON(\n json: Record<string, any>,\n ): Record<string, unknown> {\n return {\n ...json,\n tenantId: this.tenantId,\n name: this.name,\n feedUrl: this.feedUrl,\n homepageUrl: this.homepageUrl,\n format: this.format,\n status: this.status,\n defaultCategory: this.defaultCategory,\n sourceGroup: this.sourceGroup,\n pollIntervalMinutes: this.pollIntervalMinutes,\n etag: this.etag,\n lastModified: this.lastModified,\n lastFetchedAt: this.lastFetchedAt?.toISOString() ?? null,\n lastSuccessAt: this.lastSuccessAt?.toISOString() ?? null,\n lastError: this.lastError,\n metadata: this.metadata,\n createdAt: this.createdAt.toISOString(),\n updatedAt: this.updatedAt.toISOString(),\n };\n }\n}\n","import type { SmrtCollectionOptions } from '@happyvertical/smrt-core';\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport {\n ContentFeedSource,\n type ContentFeedSourceStatus,\n} from './content-feed-source';\n\nexport interface ContentFeedSourceCollectionOptions\n extends SmrtCollectionOptions {}\n\nexport class ContentFeedSourceCollection extends SmrtCollection<ContentFeedSource> {\n static readonly _itemClass = ContentFeedSource;\n\n async findActive(tenantId?: string | null): Promise<ContentFeedSource[]> {\n const where: Record<string, unknown> = { status: 'active' };\n if (tenantId !== undefined) where.tenantId = tenantId;\n return this.list({ where, orderBy: 'name ASC' });\n }\n\n async findByStatus(\n status: ContentFeedSourceStatus,\n tenantId?: string | null,\n ): Promise<ContentFeedSource[]> {\n const where: Record<string, unknown> = { status };\n if (tenantId !== undefined) where.tenantId = tenantId;\n return this.list({ where, orderBy: 'name ASC' });\n }\n\n async findByFeedUrl(\n feedUrl: string,\n tenantId?: string | null,\n ): Promise<ContentFeedSource | null> {\n const where: Record<string, unknown> = { feedUrl };\n if (tenantId !== undefined) where.tenantId = tenantId;\n const rows = await this.list({ where, limit: 1 });\n return rows[0] ?? null;\n }\n}\n","/**\n * Content subclasses for STI (Single Table Inheritance)\n *\n * These classes inherit from Content and automatically use the shared\n * contents table with _meta_type discriminator.\n */\n\nimport { foreignKey, smrt } from '@happyvertical/smrt-core';\nimport { Content, type ContentOptions } from './content';\n\n/**\n * Article content type\n *\n * Represents editorial content like blog posts, news articles, and written pieces.\n */\n@smrt({\n tableStrategy: 'sti',\n api: false,\n mcp: false,\n cli: false,\n})\nexport class Article extends Content {\n constructor(options: ContentOptions = {}) {\n super(options);\n // Article-specific initialization can go here\n }\n}\n\n/**\n * ContentDocument content type\n *\n * Represents structured documents like PDFs, reports, and technical documentation.\n */\n@smrt({\n tableStrategy: 'sti',\n api: false,\n mcp: false,\n cli: false,\n})\nexport class ContentDocument extends Content {\n constructor(options: ContentOptions = {}) {\n super(options);\n // ContentDocument-specific initialization can go here\n }\n}\n\nexport interface MirrorOptions extends ContentOptions {\n feedSourceId?: string | null;\n sourceGuid?: string | null;\n sourceName?: string | null;\n sourceHomepageUrl?: string | null;\n externalUrl?: string | null;\n originalPublishedAt?: Date | string | null;\n dedupeKey?: string | null;\n}\n\nfunction parseOptionalDate(\n value: Date | string | null | undefined,\n): Date | null {\n if (!value) return null;\n if (value instanceof Date) return value;\n const parsed = new Date(value);\n return Number.isNaN(parsed.getTime()) ? null : parsed;\n}\n\n/**\n * Mirror content type\n *\n * Represents mirrored/cached content from external feed or web sources.\n */\n@smrt({\n tableStrategy: 'sti',\n api: false,\n mcp: false,\n cli: false,\n})\nexport class Mirror extends Content {\n @foreignKey('ContentFeedSource')\n feedSourceId: string | null = null;\n sourceGuid: string | null = null;\n sourceName: string | null = null;\n sourceHomepageUrl: string | null = null;\n externalUrl: string | null = null;\n originalPublishedAt: Date | null = null;\n dedupeKey: string | null = null;\n\n constructor(options: MirrorOptions = {}) {\n super(options);\n if (options.feedSourceId !== undefined)\n this.feedSourceId = options.feedSourceId;\n if (options.sourceGuid !== undefined) this.sourceGuid = options.sourceGuid;\n if (options.sourceName !== undefined) this.sourceName = options.sourceName;\n if (options.sourceHomepageUrl !== undefined)\n this.sourceHomepageUrl = options.sourceHomepageUrl;\n if (options.externalUrl !== undefined)\n this.externalUrl = options.externalUrl;\n if (options.originalPublishedAt !== undefined) {\n this.originalPublishedAt = parseOptionalDate(options.originalPublishedAt);\n }\n if (options.dedupeKey !== undefined) this.dedupeKey = options.dedupeKey;\n }\n\n protected override transformJSON(json: Record<string, any>) {\n return {\n ...json,\n feedSourceId: this.feedSourceId,\n sourceGuid: this.sourceGuid,\n sourceName: this.sourceName,\n sourceHomepageUrl: this.sourceHomepageUrl,\n externalUrl: this.externalUrl,\n originalPublishedAt: this.originalPublishedAt?.toISOString() ?? null,\n dedupeKey: this.dedupeKey,\n };\n }\n}\n","/**\n * Shared SSRF guard for content's outbound fetches (feed sync, mirroring).\n *\n * Any code path that fetches a caller-supplied URL — RSS/Atom feeds, the\n * `Mirror` content type, link previews — is an SSRF vector: an attacker who can\n * influence the URL can make the server fetch `169.254.169.254` cloud metadata,\n * `localhost` admin panels, or other internal services. This module rejects\n * URLs that resolve to private, loopback, link-local, CGNAT, or cloud-metadata\n * ranges before any request is made, and re-validates redirect hops.\n *\n * Unlike a literal-IP-only check, {@link assertSafeRemoteUrl} resolves hostnames\n * via DNS so a public name pointing at a private IP is also caught (S5 #1388).\n */\nimport { lookup as dnsLookup } from 'node:dns/promises';\nimport { isIP } from 'node:net';\n\nexport type ResolvedAddress = { address: string; family?: number };\nexport type ResolveHostname = (hostname: string) => Promise<ResolvedAddress[]>;\n\nexport interface SafeRemoteUrlOptions {\n /** Skip the private-network checks (trusted callers only, e.g. local dev). */\n allowPrivateNetworkHosts?: boolean;\n /** Injectable resolver for tests; defaults to {@link defaultResolveHostname}. */\n resolveHostname?: ResolveHostname;\n}\n\nexport async function defaultResolveHostname(\n hostname: string,\n): Promise<ResolvedAddress[]> {\n return dnsLookup(hostname, { all: true, verbatim: false });\n}\n\nexport function isBlockedIPv4(address: string): boolean {\n const parts = address.split('.');\n if (parts.length !== 4) return true;\n // Strict per-octet validation: `Number('')` is 0, so without a digit check a\n // malformed input like `1..2.3` would parse to `[1,0,2,3]` and be treated as a\n // valid (and possibly allowed) address. Anything not 1-3 digits in 0-255 is\n // unparseable → blocked (review #1562).\n const octets = parts.map((part) =>\n /^\\d{1,3}$/.test(part) ? Number(part) : Number.NaN,\n );\n if (octets.some((n) => !Number.isInteger(n) || n < 0 || n > 255)) {\n return true;\n }\n\n const [first, second] = octets;\n return (\n first === 0 ||\n first === 10 ||\n first === 127 ||\n first >= 224 ||\n (first === 100 && second >= 64 && second <= 127) ||\n (first === 169 && second === 254) ||\n (first === 172 && second >= 16 && second <= 31) ||\n (first === 192 && second === 168) ||\n (first === 198 && (second === 18 || second === 19))\n );\n}\n\n/**\n * Expand an IPv6 string to its 8 hextets (numbers), or null if unparseable.\n * Handles `::` compression, an embedded dotted-IPv4 tail, and bracketed forms.\n */\nfunction expandIPv6(address: string): number[] | null {\n let work = address.toLowerCase().replace(/^\\[|\\]$/g, '');\n if (work.includes('.')) {\n // Embedded dotted IPv4 tail (e.g. ::ffff:127.0.0.1) → convert to 2 hextets.\n const m = work.match(/(\\d{1,3}(?:\\.\\d{1,3}){3})$/);\n if (!m) return null;\n const o = m[1].split('.').map(Number);\n if (o.some((n) => !Number.isInteger(n) || n < 0 || n > 255)) return null;\n const hi = ((o[0] << 8) | o[1]).toString(16);\n const lo = ((o[2] << 8) | o[3]).toString(16);\n work = `${work.slice(0, work.length - m[1].length)}${hi}:${lo}`;\n }\n const halves = work.split('::');\n if (halves.length > 2) return null;\n const head = halves[0] ? halves[0].split(':') : [];\n const tail = halves.length === 2 && halves[1] ? halves[1].split(':') : [];\n const groups =\n halves.length === 2\n ? [\n ...head,\n ...Array(Math.max(0, 8 - head.length - tail.length)).fill('0'),\n ...tail,\n ]\n : head;\n if (groups.length !== 8) return null;\n const hextets = groups.map((g) =>\n /^[0-9a-f]{1,4}$/.test(g) ? Number.parseInt(g, 16) : Number.NaN,\n );\n return hextets.some((n) => Number.isNaN(n)) ? null : hextets;\n}\n\nexport function isBlockedIPv6(address: string): boolean {\n const hextets = expandIPv6(address);\n if (hextets) {\n // IPv4-mapped (::ffff:a.b.c.d) and IPv4-compatible (::a.b.c.d, deprecated)\n // both embed an IPv4 in the last 2 hextets — decode and apply the IPv4\n // blocklist so a loopback/private IPv4 can't be smuggled through any IPv6\n // encoding (compressed, expanded, dotted, or hex) (review #1562, P1).\n const firstFiveZero = hextets.slice(0, 5).every((h) => h === 0);\n if (firstFiveZero && (hextets[5] === 0xffff || hextets[5] === 0)) {\n const [, , , , , , g6, g7] = hextets;\n const ipv4 = `${g6 >> 8}.${g6 & 0xff}.${g7 >> 8}.${g7 & 0xff}`;\n return isBlockedIPv4(ipv4);\n }\n }\n\n const normalized = address.toLowerCase().replace(/^\\[|\\]$/g, '');\n return (\n normalized === '::' ||\n normalized === '::1' ||\n normalized.startsWith('fc') ||\n normalized.startsWith('fd') ||\n /^fe[89ab]/.test(normalized) ||\n normalized.startsWith('ff')\n );\n}\n\nexport function isBlockedAddress(address: string): boolean {\n const family = isIP(address);\n if (family === 4) return isBlockedIPv4(address);\n if (family === 6) return isBlockedIPv6(address);\n // Anything that isn't a recognisable IP literal (after DNS resolution should\n // have produced one) is treated as unsafe.\n return true;\n}\n\n/**\n * Parse and validate a remote URL for outbound fetching. Rejects non-http(s)\n * schemes, embedded credentials, and hosts that resolve to non-public ranges.\n * Returns the parsed {@link URL} on success; throws a descriptive `Error`\n * otherwise.\n */\nexport async function assertSafeRemoteUrl(\n rawUrl: string,\n options: SafeRemoteUrlOptions = {},\n): Promise<URL> {\n let url: URL;\n try {\n url = new URL(rawUrl);\n } catch {\n throw new Error('Remote URL must be an absolute URL');\n }\n\n if (url.protocol !== 'http:' && url.protocol !== 'https:') {\n throw new Error('Remote URL must use http or https');\n }\n if (url.username || url.password) {\n throw new Error('Remote URL must not include credentials');\n }\n if (!url.hostname) {\n throw new Error('Remote URL must include a hostname');\n }\n\n if (options.allowPrivateNetworkHosts) return url;\n\n const resolver = options.resolveHostname ?? defaultResolveHostname;\n const addresses =\n isIP(url.hostname) === 0\n ? await resolver(url.hostname)\n : [{ address: url.hostname }];\n\n if (\n !addresses.length ||\n addresses.some(({ address }) => isBlockedAddress(address))\n ) {\n throw new Error('Remote URL must resolve to a public network address');\n }\n\n return url;\n}\n\n/** Redirect status codes that reroute a request to a new Location. */\nconst REDIRECT_STATUSES = new Set([301, 302, 303, 307, 308]);\nconst DEFAULT_MAX_REDIRECTS = 5;\nconst DEFAULT_RESOLVE_TIMEOUT_MS = 10_000;\n\nexport interface SafeRedirectOptions extends SafeRemoteUrlOptions {\n /** Maximum redirect hops to follow before failing. Default 5. */\n maxRedirects?: number;\n /** Per-hop timeout in ms. Default 10s. */\n timeoutMs?: number;\n /** Injectable fetch (primarily for tests). Defaults to global `fetch`. */\n fetchImpl?: typeof fetch;\n}\n\n/**\n * Resolve a URL's redirect chain and return the final safe {@link URL}, with\n * EVERY hop re-validated through {@link assertSafeRemoteUrl}.\n *\n * Use this before handing a URL to a fetcher that follows redirects on its own\n * (e.g. `fetchDocument`): the up-front {@link assertSafeRemoteUrl} check alone\n * can't stop an allowed public host from `30x`-redirecting into an internal /\n * loopback / metadata host, which would defeat the SSRF guard (review #1562).\n *\n * Redirects are followed with `GET` + `redirect: 'manual'` to match downstream\n * GET-based fetchers; response bodies are discarded (the redirect bodies are\n * empty and the terminal body is left for the caller to re-fetch), so this does\n * not double-download content.\n */\nexport async function resolveSafeFinalUrl(\n rawUrl: string,\n options: SafeRedirectOptions = {},\n): Promise<URL> {\n const fetchImpl = options.fetchImpl ?? fetch;\n const maxRedirects = options.maxRedirects ?? DEFAULT_MAX_REDIRECTS;\n const timeoutMs = options.timeoutMs ?? DEFAULT_RESOLVE_TIMEOUT_MS;\n let current = await assertSafeRemoteUrl(rawUrl, options);\n\n for (let hop = 0; hop <= maxRedirects; hop += 1) {\n const response = await fetchImpl(current, {\n method: 'GET',\n redirect: 'manual',\n signal: AbortSignal.timeout(timeoutMs),\n });\n // Release the connection without downloading the body.\n try {\n await response.body?.cancel();\n } catch {\n // best-effort\n }\n\n if (!REDIRECT_STATUSES.has(response.status)) {\n return current;\n }\n const location = response.headers.get('location');\n if (!location) return current;\n // Re-validate the resolved redirect target before following it.\n current = await assertSafeRemoteUrl(\n new URL(location, current).toString(),\n options,\n );\n }\n\n throw new Error('Remote URL exceeded the maximum number of redirects');\n}\n\n/**\n * Strip userinfo (`user:pass@`) from a URL so it can be safely logged or echoed\n * in an error message. Returns a placeholder for unparseable input. Never let a\n * credential-bearing URL reach logs/errors verbatim (review #1562).\n */\nexport function redactUrlCredentials(raw: string): string {\n try {\n const url = new URL(raw);\n if (url.username || url.password) {\n url.username = '';\n url.password = '';\n return url.toString();\n }\n return raw;\n } catch {\n return '[unparseable url]';\n }\n}\n","import { writeFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport type { AIClientOptions } from '@happyvertical/ai';\nimport { fetchDocument } from '@happyvertical/documents';\nimport { ensureDirectoryExists } from '@happyvertical/files';\nimport { createLogger } from '@happyvertical/logger';\nimport type { SmrtCollectionOptions } from '@happyvertical/smrt-core';\nimport { SmrtCollection, smrt } from '@happyvertical/smrt-core';\nimport type { Image } from '@happyvertical/smrt-images';\nimport { queryGlobal, queryWithGlobals } from '@happyvertical/smrt-tenancy';\nimport { makeSlug } from '@happyvertical/utils';\nimport YAML from 'yaml';\nimport { htmlToMarkdown, resolveBodyFormat } from './body-format';\nimport { Content } from './content';\nimport {\n getEffectiveContentGovernanceConfig,\n loadPersistedContentGovernanceDefinitions,\n resolveEffectiveContentGovernance,\n} from './content-governance';\nimport {\n type ResolveHostname,\n redactUrlCredentials,\n resolveSafeFinalUrl,\n} from './safe-remote-url';\nimport { serializeContent, serializeFact } from './serialization';\nimport type {\n ThumbnailOptions,\n ThumbnailStrategy,\n} from './thumbnail-generator';\n\nconst logger = createLogger({ level: 'info' });\n\n/**\n * Configuration options for Contents collection\n */\nexport interface ContentsOptions extends SmrtCollectionOptions {\n /**\n * Directory to store content files\n */\n contentDir?: string;\n}\n\nfunction isAIClientOptions(\n ai: SmrtCollectionOptions['ai'],\n): ai is AIClientOptions {\n return (\n !!ai &&\n typeof ai === 'object' &&\n !('embed' in ai) &&\n !('generateImage' in ai)\n );\n}\n\n/**\n * Collection for managing Content objects\n *\n * The Contents collection provides functionality for managing and manipulating\n * collections of Content objects, including saving to the filesystem and\n * mirroring content from remote URLs.\n */\n@smrt({\n api: {\n include: [\n 'browseFacts',\n 'getBySlug',\n 'getGovernanceDefinitionsAction',\n 'resolveGovernanceAction',\n ],\n routes: {\n browseFacts: {\n scope: 'collection',\n method: 'GET',\n path: 'facts',\n },\n getBySlug: {\n scope: 'collection',\n method: 'GET',\n path: 'by-slug',\n },\n getGovernanceDefinitionsAction: {\n scope: 'collection',\n method: 'GET',\n path: 'governance',\n },\n resolveGovernanceAction: {\n scope: 'collection',\n method: 'GET',\n path: 'governance/resolve',\n },\n },\n },\n mcp: false,\n cli: false,\n})\nexport class Contents extends SmrtCollection<Content> {\n /**\n * Class constructor for collection items\n */\n static _itemClass = Content;\n\n /**\n * Configuration options\n */\n public options: ContentsOptions = {} as ContentsOptions;\n\n /**\n * Directory to store content files\n */\n public contentDir?: string;\n\n /**\n * Cache for loaded content\n */\n public loaded: Map<string, Content>;\n\n /**\n * Creates a new Contents collection\n *\n * Use the static `create()` method inherited from SmrtCollection for proper initialization.\n *\n * @param options - Configuration options\n */\n constructor(options: ContentsOptions = {}) {\n super(options);\n this.options = options;\n this.loaded = new Map();\n }\n\n /**\n * Gets the database interface\n *\n * @returns Database interface\n */\n getDb() {\n return this._db;\n }\n\n /**\n * Initializes the collection\n *\n * @returns Promise that resolves to this instance\n */\n public async initialize(): Promise<this> {\n await super.initialize();\n return this;\n }\n\n private async getFactCollection() {\n const { FactCollection } = await import('@happyvertical/smrt-facts');\n return FactCollection.create(this.options);\n }\n\n public async browseFacts(\n options: {\n q?: string;\n query?: string;\n limit?: number | string;\n offset?: number | string;\n minSimilarity?: number | string;\n includeSuperseded?: boolean | string;\n latestOnly?: boolean | string;\n tenantId?: string | null;\n } = {},\n ) {\n try {\n const facts = await this.getFactCollection();\n const query = options.query || options.q || '';\n const limit =\n options.limit !== undefined ? Number(options.limit) : undefined;\n const offset =\n options.offset !== undefined ? Number(options.offset) : undefined;\n const minSimilarity =\n options.minSimilarity !== undefined\n ? Number(options.minSimilarity)\n : undefined;\n const includeSuperseded =\n options.includeSuperseded === true ||\n options.includeSuperseded === 'true';\n const latestOnly =\n options.latestOnly === undefined\n ? true\n : options.latestOnly === true || options.latestOnly === 'true';\n\n const results = await facts.browseCatalog(query, {\n limit: Number.isFinite(limit) ? limit : undefined,\n offset: Number.isFinite(offset) ? offset : undefined,\n minSimilarity: Number.isFinite(minSimilarity)\n ? minSimilarity\n : undefined,\n includeSuperseded,\n latestOnly,\n tenantId: options.tenantId ?? null,\n });\n\n return results.map(serializeFact);\n } catch (error: any) {\n // Gracefully handle missing facts table (cross-package dependency)\n if (error?.code === 'DB_SCHEMA_MISSING') {\n return [];\n }\n throw error;\n }\n }\n\n public async getBySlug(\n options: { slug?: string; context?: string; status?: string } = {},\n ) {\n if (!options.slug) {\n throw new Error('slug is required');\n }\n\n const content = await this.get({\n slug: options.slug,\n context: options.context || '',\n });\n\n if (!content) {\n return null;\n }\n\n if (options.status && content.status !== options.status) {\n return null;\n }\n\n return serializeContent(content);\n }\n\n public async getGovernanceDefinitionsAction() {\n const [effective, persisted] = await Promise.all([\n getEffectiveContentGovernanceConfig({ db: this.db }),\n loadPersistedContentGovernanceDefinitions({ db: this.db }),\n ]);\n\n return {\n effective: {\n policies: effective.policies.map((policy) => ({\n ...policy,\n ...(persisted.policies.find((item) => item.key === policy.key) || {}),\n })),\n profiles: effective.profiles.map((profile) => ({\n ...profile,\n ...(persisted.profiles.find((item) => item.key === profile.key) ||\n {}),\n })),\n assignments: effective.assignments.map((assignment) => ({\n ...assignment,\n ...(persisted.assignments.find(\n (item) => item.key === assignment.key,\n ) || {}),\n })),\n },\n persisted: {\n policies: persisted.policies,\n profiles: persisted.profiles,\n assignments: persisted.assignments,\n },\n };\n }\n\n public async resolveGovernanceAction(\n options: { type?: string; variant?: string | null } = {},\n ) {\n return resolveEffectiveContentGovernance({\n contentType: options.type || null,\n contentVariant: options.variant || null,\n db: this.db,\n });\n }\n\n /**\n * Mirrors content from a remote URL\n *\n * Downloads and stores content from a remote URL, extracting text\n * and saving it as a Content object.\n *\n * @param options - Mirror options\n * @param options.url - URL to mirror\n * @param options.mirrorDir - Directory for caching mirrored files\n * @param options.context - Context for the mirrored content\n * @returns Promise resolving to the mirrored Content object\n * @throws Error if URL is invalid or missing\n */\n public async mirror(options: {\n url: string;\n mirrorDir?: string;\n context?: string;\n /**\n * Skip the SSRF host-blocking checks. Only set this for fully trusted,\n * operator-supplied URLs (e.g. local development), never for URLs that\n * originate from end users or external content.\n */\n allowPrivateNetworkHosts?: boolean;\n /** Injectable DNS resolver (primarily for tests). */\n resolveHostname?: ResolveHostname;\n /** Injectable fetch for redirect resolution (primarily for tests). */\n fetchImpl?: typeof fetch;\n }) {\n if (!options.url) {\n throw new Error('No URL provided');\n }\n // Validate the URL AND block private/loopback/link-local/metadata hosts\n // before fetching — `mirror()` fetches an arbitrary caller-supplied URL,\n // which is a classic SSRF sink (e.g. http://169.254.169.254/ metadata).\n // `fetchDocument` follows redirects on its own, so we resolve the redirect\n // chain ourselves first — re-validating every hop — and hand it the\n // already-validated terminal URL, closing the public-host-30x-to-internal\n // bypass (S5 #1388 / review #1562).\n let url: URL;\n try {\n url = await resolveSafeFinalUrl(options.url, {\n allowPrivateNetworkHosts: options.allowPrivateNetworkHosts,\n resolveHostname: options.resolveHostname,\n fetchImpl: options.fetchImpl,\n });\n } catch (error) {\n // Never echo the raw URL — it may carry userinfo credentials (review #1562).\n const safeUrl = redactUrlCredentials(options.url);\n logger.error('Refusing to mirror unsafe URL', { error, url: safeUrl });\n throw new Error(`Invalid URL provided: ${safeUrl}`);\n }\n const existing = await this.get({ url: options.url });\n if (existing) {\n return existing;\n }\n\n // Fetch and process the document via the already-validated terminal URL.\n const doc = await fetchDocument(url.toString(), {\n cacheDir: options?.mirrorDir,\n });\n\n const filename = url.pathname.split('/').pop();\n const nameWithoutExtension = filename?.replace(/\\.[^/.]+$/, '');\n const title = nameWithoutExtension?.replace(/[-_]/g, ' ');\n const slug = makeSlug(title as string);\n\n // Extract text from all document parts\n const body = doc.parts.map((part) => part.content).join('\\n\\n');\n if (body) {\n const content = new Content({\n url: options.url,\n type: 'mirror',\n title,\n slug,\n context: options.context || '',\n body,\n } as any);\n await content.initialize();\n await content.save();\n return content;\n }\n }\n\n /**\n * Writes a Content object to the filesystem as a markdown file\n *\n * @param options - Options for writing the content file\n * @param options.content - Content object to write\n * @param options.contentDir - Directory to write the file to\n * @returns Promise that resolves when the file is written\n * @throws Error if contentDir is not provided\n */\n public async writeContentFile(options: {\n content: Content;\n contentDir: string;\n }) {\n const { content, contentDir } = options;\n if (!contentDir) {\n throw new Error('No content dir provided');\n }\n\n const { body } = content;\n const frontMatter = {\n title: content.title,\n slug: content.slug,\n context: content.context,\n author: content.author,\n publish_date: content.publish_date,\n };\n\n let output = '';\n if (frontMatter && Object.keys(frontMatter).length > 0) {\n output += '---\\n';\n output += YAML.stringify(frontMatter);\n output += '---\\n';\n }\n\n // Filesystem exports are markdown regardless of the editor save format.\n let formattedBody = body || '';\n const bodyFormat = resolveBodyFormat(content.bodyFormat, body);\n if (bodyFormat === 'html') {\n formattedBody = htmlToMarkdown(body || '');\n } else if (body && !this.isMarkdown(body)) {\n formattedBody = this.formatAsMarkdown(body);\n }\n output += formattedBody;\n\n const pathParts = [\n contentDir,\n content.context || '', // if empty, use empty string\n content.slug,\n 'index.md',\n ].filter(Boolean); // remove empty strings\n\n const outputFile = path.join(...(pathParts as string[]));\n\n // `context` and `slug` are persisted, caller-influenced fields. Without a\n // guard, a value like `../../etc/cron.d/x` escapes `contentDir` and lets an\n // export overwrite arbitrary files (path traversal). Confirm the joined\n // path still lives under the resolved content directory (S5 #1388).\n const resolvedDir = path.resolve(contentDir);\n const resolvedFile = path.resolve(outputFile);\n if (\n resolvedFile !== resolvedDir &&\n !resolvedFile.startsWith(resolvedDir + path.sep)\n ) {\n throw new Error(\n 'Refusing to write content file outside of the content directory',\n );\n }\n\n await ensureDirectoryExists(path.dirname(outputFile));\n await writeFile(outputFile, output);\n }\n\n /**\n * Checks if text appears to be in markdown format\n *\n * @param text - Text to check\n * @returns Boolean indicating if the text contains markdown syntax\n */\n private isMarkdown(text: string): boolean {\n // Basic check for common markdown indicators\n const markdownIndicators = [\n /^#\\s/m, // Headers\n /\\*\\*.+\\*\\*/, // Bold\n /\\*.+\\*/, // Italic\n /\\[.+\\]\\(.+\\)/, // Links\n /^\\s*[-*+]\\s/m, // Lists\n /^\\s*\\d+\\.\\s/m, // Numbered lists\n /```[\\s\\S]*```/, // Code blocks\n /^\\s*>/m, // Blockquotes\n ];\n\n return markdownIndicators.some((indicator) => indicator.test(text));\n }\n\n /**\n * Formats plain text as simple markdown\n *\n * @param text - Plain text to format\n * @returns Text formatted as basic markdown\n */\n private formatAsMarkdown(text: string): string {\n // Basic formatting of plain text to markdown\n return text\n .split(/\\n\\n+/)\n .map((paragraph) => paragraph.trim())\n .filter(Boolean)\n .join('\\n\\n');\n }\n\n /**\n * Synchronizes content to the filesystem\n *\n * Writes all article-type Content objects to the filesystem\n * as markdown files.\n *\n * @param options - Sync options\n * @param options.contentDir - Directory to write content files to\n * @returns Promise that resolves when synchronization is complete\n */\n public async syncContentDir(options: { contentDir?: string }) {\n const contentFilter = {\n type: 'article',\n };\n\n const contents = await this.list({ where: contentFilter });\n for (const content of contents) {\n await this.writeContentFile({\n content,\n contentDir: options.contentDir || this.options.contentDir || '',\n });\n }\n }\n\n /**\n * Generate thumbnails for content that doesn't have one\n *\n * @param options - Options for bulk thumbnail generation\n * @returns Promise resolving to result object with generated images and failed content IDs\n *\n * @example Generate headline cards for all published articles\n * ```typescript\n * const result = await contents.generateMissingThumbnails({\n * strategy: 'headline-card',\n * where: { type: 'article', status: 'published' },\n * brandColor: '#1a56db'\n * });\n * console.log(`Generated ${result.images.length} thumbnails`);\n * if (result.failed.length > 0) {\n * console.warn(`Failed to generate ${result.failed.length} thumbnails`);\n * }\n * ```\n */\n public async generateMissingThumbnails(options: {\n /**\n * Thumbnail generation strategy\n */\n strategy: ThumbnailStrategy;\n\n /**\n * Optional filter for content to process\n */\n where?: Record<string, any>;\n\n /**\n * Maximum number of thumbnails to generate\n */\n limit?: number;\n\n // Headline card options\n brandColor?: string;\n backgroundColor?: string;\n logoUrl?: string;\n template?: 'default' | 'news' | 'minimal';\n\n // Static map options\n mapProvider?: 'mapbox' | 'google';\n zoom?: number;\n\n // AI options\n style?: 'photorealistic' | 'illustration' | 'abstract' | 'minimal';\n\n // Common options\n width?: number;\n height?: number;\n }): Promise<{\n images: Image[];\n failed: Array<{ contentId: string; error: string }>;\n }> {\n // Merge with thumbnail config from smrt.config.js (passed via constructor)\n // This allows CLI users to configure defaults in smrt.config.js:\n // thumbnail: { strategy: 'headline-card', brandColor: '#1976d2' }\n const configDefaults = (this.options as any)?.thumbnail || {};\n const mergedOptions = {\n ...configDefaults,\n ...options,\n };\n\n // Build query for content missing thumbnails\n const whereClause = {\n ...mergedOptions.where,\n thumbnailAssetId: null,\n };\n\n const contents = await this.list({\n where: whereClause,\n limit: mergedOptions.limit,\n });\n\n const generatedImages: Image[] = [];\n const failed: Array<{ contentId: string; error: string }> = [];\n\n for (const content of contents) {\n try {\n // Build thumbnail options based on strategy\n let thumbnailOptions: ThumbnailOptions;\n\n switch (mergedOptions.strategy) {\n case 'headline-card':\n thumbnailOptions = {\n strategy: 'headline-card',\n brandColor: mergedOptions.brandColor,\n backgroundColor: mergedOptions.backgroundColor,\n logoUrl: mergedOptions.logoUrl,\n template: mergedOptions.template,\n width: mergedOptions.width,\n height: mergedOptions.height,\n };\n break;\n\n case 'static-map':\n thumbnailOptions = {\n strategy: 'static-map',\n mapProvider: mergedOptions.mapProvider,\n zoom: mergedOptions.zoom,\n width: mergedOptions.width,\n height: mergedOptions.height,\n };\n break;\n\n case 'ai-generate':\n thumbnailOptions = {\n strategy: 'ai-generate',\n style: mergedOptions.style,\n width: mergedOptions.width,\n height: mergedOptions.height,\n ai: isAIClientOptions(this.options.ai)\n ? this.options.ai\n : undefined,\n };\n break;\n\n default:\n throw new Error(`Unknown strategy: ${mergedOptions.strategy}`);\n }\n\n const image = await content.generateThumbnail(thumbnailOptions);\n generatedImages.push(image);\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n logger.error(\n `Failed to generate thumbnail for content ${content.id}: ${errorMessage}`,\n );\n failed.push({\n contentId: content.id ?? 'unknown',\n error: errorMessage,\n });\n }\n }\n\n return { images: generatedImages, failed };\n }\n\n // ============================================\n // Tenant Helper Methods\n // ============================================\n\n /**\n * Find all content belonging to a specific tenant\n *\n * @param tenantId - The tenant ID to filter by\n * @returns Promise resolving to array of Content objects for the tenant\n *\n * @example\n * ```typescript\n * const tenantContent = await contents.findByTenant('tenant-123');\n * ```\n */\n async findByTenant(tenantId: string): Promise<Content[]> {\n return this.list({ where: { tenantId } });\n }\n\n /**\n * Find all global content (not associated with any tenant).\n *\n * Routes through the shared tenant-global helper so it does not throw under\n * an active tenant context (an explicit `tenant_id IS NULL` filter would be\n * flagged as an isolation violation). (#1600)\n *\n * @returns Promise resolving to array of global Content objects\n *\n * @example\n * ```typescript\n * const globalContent = await contents.findGlobal();\n * ```\n */\n async findGlobal(): Promise<Content[]> {\n return queryGlobal<Content>(this);\n }\n\n /**\n * Find content for a tenant including global content.\n *\n * This returns both tenant-specific content and global content (tenantId is null),\n * useful for showing a tenant their content plus any shared/global resources.\n *\n * Fails closed if an active tenant context requests a different tenant's\n * rows; the admin/system path keeps the cross-tenant capability. (#1600)\n *\n * @param tenantId - The tenant ID to include\n * @returns Promise resolving to array of Content objects (tenant + global)\n *\n * @example\n * ```typescript\n * const allAccessibleContent = await contents.findWithGlobals('tenant-123');\n * ```\n */\n async findWithGlobals(tenantId: string): Promise<Content[]> {\n return queryWithGlobals<Content>(this, tenantId, 'Content.findWithGlobals');\n }\n}\n","import { randomUUID } from 'node:crypto';\nimport {\n ObjectRegistry,\n type SmrtCollectionOptions,\n} from '@happyvertical/smrt-core';\nimport {\n type ParsedContentFeedItem,\n parseContentFeed,\n} from './content-feed-parser';\nimport type { ContentFeedSource } from './content-feed-source';\nimport { Mirror } from './content-types';\nimport { Contents } from './contents';\nimport { assertSafeRemoteUrl, type ResolveHostname } from './safe-remote-url';\n\nexport interface ContentFeedSyncOptions extends SmrtCollectionOptions {\n fetch?: typeof fetch;\n maxItems?: number;\n maxResponseBytes?: number;\n fetchTimeoutMs?: number;\n allowPrivateNetworkHosts?: boolean;\n resolveHostname?: ResolveHostname;\n status?: 'published' | 'draft';\n now?: () => Date;\n}\n\nexport interface ContentFeedSyncResult {\n source: ContentFeedSource;\n fetched: boolean;\n notModified: boolean;\n imported: number;\n updated: number;\n skipped: number;\n}\n\ntype QueryableCollection = Pick<Contents, 'query'>;\n\nconst DEFAULT_MAX_RESPONSE_BYTES = 2_000_000;\nconst DEFAULT_FETCH_TIMEOUT_MS = 10_000;\nconst MAX_FEED_REDIRECTS = 5;\nconst REDIRECT_STATUSES = new Set([301, 302, 303, 307, 308]);\nconst FALLBACK_MIRROR_META_TYPE = '@happyvertical/smrt-content:Mirror';\n\nfunction getMirrorMetaType(): string {\n return (\n ObjectRegistry.getClassByConstructor(Mirror)?.qualifiedName ??\n FALLBACK_MIRROR_META_TYPE\n );\n}\n\nfunction slugify(value: string): string {\n const slug = value\n .toLowerCase()\n .replace(/&/g, ' and ')\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '')\n .slice(0, 80);\n return slug || 'feed';\n}\n\nfunction normalizeUrlIdentity(value: string): string {\n try {\n const url = new URL(value);\n url.hash = '';\n url.searchParams.sort();\n return url.toString().replace(/\\/$/, '');\n } catch {\n return value.trim();\n }\n}\n\nfunction hashString(value: string): string {\n let hash = 5381;\n for (let index = 0; index < value.length; index += 1) {\n hash = (hash * 33) ^ value.charCodeAt(index);\n }\n return (hash >>> 0).toString(36);\n}\n\nfunction createDedupeKey(\n source: ContentFeedSource,\n item: ParsedContentFeedItem,\n): string {\n return `feed:${source.id ?? source.feedUrl}:${item.guid || normalizeUrlIdentity(item.url)}`;\n}\n\nasync function validateFeedFetchUrl(\n feedUrl: string,\n options: ContentFeedSyncOptions,\n): Promise<URL> {\n return assertSafeRemoteUrl(feedUrl, {\n allowPrivateNetworkHosts: options.allowPrivateNetworkHosts,\n resolveHostname: options.resolveHostname,\n });\n}\n\nfunction createTimeoutSignal(timeoutMs: number): AbortSignal | undefined {\n if (timeoutMs <= 0) return undefined;\n return AbortSignal.timeout(timeoutMs);\n}\n\n/**\n * Fetch a feed following redirects manually so every hop's target is\n * re-validated through {@link validateFeedFetchUrl}. `fetch()`'s default\n * `redirect: 'follow'` would let an allowed public feed 30x-redirect to an\n * internal/link-local/metadata host, defeating the up-front SSRF check\n * (S5 #1388). Returns the response together with the final validated URL so\n * the parser uses the redirect target as the feed base.\n */\nasync function fetchFeedWithRedirectGuard(\n fetchImpl: typeof fetch,\n startUrl: URL,\n headers: Record<string, string>,\n options: ContentFeedSyncOptions,\n): Promise<{ response: Response; finalUrl: URL }> {\n let current = startUrl;\n\n for (let hop = 0; hop <= MAX_FEED_REDIRECTS; hop += 1) {\n const response = await fetchImpl(current, {\n headers,\n redirect: 'manual',\n signal: createTimeoutSignal(\n options.fetchTimeoutMs ?? DEFAULT_FETCH_TIMEOUT_MS,\n ),\n });\n\n // Only the redirect statuses (not 304 Not Modified / 305 / 306) reroute the\n // request; everything else (200, 304, 4xx, 5xx) is returned to the caller.\n if (REDIRECT_STATUSES.has(response.status)) {\n const location = response.headers.get('location');\n if (!location) {\n throw new Error('Feed redirect response missing Location header');\n }\n // Re-run the full SSRF validation against the resolved redirect target.\n current = await validateFeedFetchUrl(\n new URL(location, current).toString(),\n options,\n );\n continue;\n }\n\n return { response, finalUrl: current };\n }\n\n throw new Error('Feed URL exceeded the maximum number of redirects');\n}\n\nasync function readResponseText(\n response: Response,\n maxBytes: number,\n): Promise<string> {\n const contentLength = response.headers.get('content-length');\n if (contentLength && Number(contentLength) > maxBytes) {\n throw new Error(`Feed response exceeds ${maxBytes} bytes`);\n }\n\n if (!response.body) {\n const text = await response.text();\n if (new TextEncoder().encode(text).byteLength > maxBytes) {\n throw new Error(`Feed response exceeds ${maxBytes} bytes`);\n }\n return text;\n }\n\n const reader = response.body.getReader();\n const chunks: Uint8Array[] = [];\n let totalBytes = 0;\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n if (!value) continue;\n totalBytes += value.byteLength;\n if (totalBytes > maxBytes) {\n await reader.cancel();\n throw new Error(`Feed response exceeds ${maxBytes} bytes`);\n }\n chunks.push(value);\n }\n\n const buffer = new Uint8Array(totalBytes);\n let offset = 0;\n for (const chunk of chunks) {\n buffer.set(chunk, offset);\n offset += chunk.byteLength;\n }\n\n return new TextDecoder().decode(buffer);\n}\n\nasync function findExistingMirror(\n contents: QueryableCollection,\n source: ContentFeedSource,\n item: ParsedContentFeedItem,\n dedupeKey: string,\n): Promise<{ id: string; status: string | null } | null> {\n const tenantWhere = source.tenantId ? 'tenant_id = ?' : 'tenant_id IS NULL';\n const params: unknown[] = [getMirrorMetaType()];\n if (source.tenantId) params.push(source.tenantId);\n\n if (item.guid) {\n const result = await contents.query(\n `SELECT id, status\n FROM contents\n WHERE _meta_type = ?\n AND ${tenantWhere}\n AND feed_source_id = ?\n AND source_guid = ?\n LIMIT 1`,\n [...params, source.id, item.guid],\n );\n if (result[0]) return result[0] as { id: string; status: string | null };\n }\n\n const result = await contents.query(\n `SELECT id, status\n FROM contents\n WHERE _meta_type = ?\n AND ${tenantWhere}\n AND feed_source_id = ?\n AND dedupe_key = ?\n LIMIT 1`,\n [...params, source.id, dedupeKey],\n );\n return (\n (result[0] as { id: string; status: string | null } | undefined) ?? null\n );\n}\n\nasync function upsertMirrorItem(\n contents: QueryableCollection,\n source: ContentFeedSource,\n item: ParsedContentFeedItem,\n status: 'published' | 'draft',\n now: Date,\n): Promise<'imported' | 'updated'> {\n const dedupeKey = createDedupeKey(source, item);\n const existing = await findExistingMirror(contents, source, item, dedupeKey);\n const publishedAt = (item.publishedAt ?? item.updatedAt ?? now).toISOString();\n const sourceSlug = slugify(\n source.sourceGroup || source.name || source.feedUrl,\n );\n const category = source.defaultCategory || item.categories[0] || null;\n const tags = JSON.stringify(item.categories);\n\n if (existing) {\n await contents.query(\n `UPDATE contents\n SET title = ?,\n name = ?,\n description = ?,\n source = ?,\n original_url = ?,\n url = ?,\n feed_source_id = ?,\n source_guid = ?,\n source_name = ?,\n source_homepage_url = ?,\n external_url = ?,\n original_published_at = ?,\n dedupe_key = ?,\n publish_date = ?,\n author = ?,\n category = ?,\n tags = ?,\n status = ?,\n updated_at = ?\n WHERE id = ?`,\n [\n item.title,\n item.title,\n item.summary,\n source.name,\n item.url,\n item.url,\n source.id,\n item.guid,\n source.name,\n source.homepageUrl,\n item.url,\n publishedAt,\n dedupeKey,\n publishedAt,\n item.author,\n category,\n tags,\n existing.status || status,\n now.toISOString(),\n existing.id,\n ],\n );\n return 'updated';\n }\n\n const id = randomUUID();\n await contents.query(\n `INSERT INTO contents (\n id, slug, context, _meta_type, title, name, description, body,\n status, state, metadata, source, original_url, url, feed_source_id,\n source_guid, source_name, source_homepage_url, external_url,\n original_published_at, dedupe_key, tenant_id, publish_date, author,\n category, tags, created_at, updated_at\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n [\n id,\n `mirror-${sourceSlug}-${hashString(dedupeKey)}`,\n '',\n getMirrorMetaType(),\n item.title,\n item.title,\n item.summary,\n '',\n status,\n 'active',\n '{}',\n source.name,\n item.url,\n item.url,\n source.id,\n item.guid,\n source.name,\n source.homepageUrl,\n item.url,\n publishedAt,\n dedupeKey,\n source.tenantId,\n publishedAt,\n item.author,\n category,\n tags,\n now.toISOString(),\n now.toISOString(),\n ],\n );\n return 'imported';\n}\n\nexport async function syncContentFeedSource(\n source: ContentFeedSource,\n options: ContentFeedSyncOptions = {},\n): Promise<ContentFeedSyncResult> {\n if (source.status === 'paused' || source.status === 'archived') {\n return {\n source,\n fetched: false,\n notModified: false,\n imported: 0,\n updated: 0,\n skipped: 0,\n };\n }\n\n const fetchImpl = options.fetch ?? globalThis.fetch;\n if (!fetchImpl) throw new Error('No fetch implementation available');\n\n const headers: Record<string, string> = {\n Accept:\n 'application/rss+xml, application/atom+xml, application/xml, text/xml',\n 'User-Agent': '@happyvertical/smrt-content feed sync',\n };\n if (source.etag) headers['If-None-Match'] = source.etag;\n if (source.lastModified) headers['If-Modified-Since'] = source.lastModified;\n\n const now = options.now?.() ?? new Date();\n source.markFetchStarted(now);\n await source.save();\n\n try {\n const feedUrl = await validateFeedFetchUrl(source.feedUrl, options);\n const { response, finalUrl } = await fetchFeedWithRedirectGuard(\n fetchImpl,\n feedUrl,\n headers,\n options,\n );\n\n if (response.status === 304) {\n source.markFetchSucceeded(now);\n await source.save();\n return {\n source,\n fetched: true,\n notModified: true,\n imported: 0,\n updated: 0,\n skipped: 0,\n };\n }\n\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n }\n\n const parsed = parseContentFeed(\n await readResponseText(\n response,\n options.maxResponseBytes ?? DEFAULT_MAX_RESPONSE_BYTES,\n ),\n finalUrl.toString(),\n );\n source.format = parsed.format;\n source.homepageUrl = source.homepageUrl || parsed.homepageUrl;\n if (!source.name && parsed.title) source.name = parsed.title;\n\n const contents = await Contents.create(options);\n let imported = 0;\n let updated = 0;\n let skipped = 0;\n\n for (const item of parsed.items.slice(0, options.maxItems)) {\n try {\n const result = await upsertMirrorItem(\n contents,\n source,\n item,\n options.status ?? 'published',\n now,\n );\n if (result === 'imported') imported += 1;\n else updated += 1;\n } catch {\n skipped += 1;\n }\n }\n\n source.markFetchSucceeded(now, {\n etag: response.headers.get('etag'),\n lastModified: response.headers.get('last-modified'),\n });\n await source.save();\n\n return {\n source,\n fetched: true,\n notModified: false,\n imported,\n updated,\n skipped,\n };\n } catch (error) {\n source.markFetchFailed(error, now);\n await source.save();\n throw error;\n }\n}\n","import type { SmrtObjectOptions } from '@happyvertical/smrt-core';\nimport { field, SmrtObject, smrt } from '@happyvertical/smrt-core';\nimport type { FactContentRelationship } from '@happyvertical/smrt-facts';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport {\n buildContentGovernanceAssignmentKey,\n type ContentGovernanceAssignmentDefinition,\n getEffectiveContentGovernanceConfig,\n} from './content-governance';\n\nexport interface ContentGovernanceAssignmentOptions extends SmrtObjectOptions {\n key?: string;\n label?: string;\n contentType?: string;\n contentVariant?: string | null;\n enabled?: boolean;\n factLinkingEnabled?: boolean;\n transparencyEnabled?: boolean;\n publicationProfileKey?: string | null;\n correctionProfileKey?: string | null;\n enforcePublishReadiness?: boolean;\n defaultFactRelationship?: FactContentRelationship;\n metadata?: string | Record<string, any>;\n tenantId?: string | null;\n createdAt?: Date;\n updatedAt?: Date;\n}\n\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableName: 'content_governance_assignments',\n conflictColumns: ['key'],\n api: { include: ['list', 'get', 'create', 'update', 'delete'] },\n mcp: { include: ['list', 'get', 'create', 'update', 'delete'] },\n cli: true,\n})\nexport class ContentGovernanceAssignment extends SmrtObject {\n @field({ required: true })\n key = '';\n\n label = '';\n\n @field({ required: true })\n contentType = '';\n\n contentVariant = '';\n enabled = true;\n factLinkingEnabled = false;\n transparencyEnabled = false;\n publicationProfileKey = '';\n correctionProfileKey = '';\n enforcePublishReadiness = false;\n defaultFactRelationship: FactContentRelationship = 'supports';\n metadata = '';\n\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n createdAt = new Date();\n updatedAt = new Date();\n\n constructor(options: ContentGovernanceAssignmentOptions = {}) {\n super(options);\n if (options.contentType !== undefined)\n this.contentType = options.contentType;\n if (options.contentVariant !== undefined)\n this.contentVariant = options.contentVariant || '';\n if (options.label !== undefined) this.label = options.label;\n if (options.enabled !== undefined) this.enabled = options.enabled;\n if (options.factLinkingEnabled !== undefined)\n this.factLinkingEnabled = options.factLinkingEnabled;\n if (options.transparencyEnabled !== undefined)\n this.transparencyEnabled = options.transparencyEnabled;\n if (options.publicationProfileKey !== undefined)\n this.publicationProfileKey = options.publicationProfileKey || '';\n if (options.correctionProfileKey !== undefined)\n this.correctionProfileKey = options.correctionProfileKey || '';\n if (options.enforcePublishReadiness !== undefined)\n this.enforcePublishReadiness = options.enforcePublishReadiness;\n if (options.defaultFactRelationship !== undefined)\n this.defaultFactRelationship = options.defaultFactRelationship;\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n if (options.createdAt) this.createdAt = options.createdAt;\n if (options.updatedAt) this.updatedAt = options.updatedAt;\n\n this.key =\n options.key ||\n buildContentGovernanceAssignmentKey(\n this.contentType,\n this.contentVariant,\n );\n\n if (options.metadata !== undefined) {\n this.metadata =\n typeof options.metadata === 'string'\n ? options.metadata\n : JSON.stringify(options.metadata);\n }\n }\n\n getMetadata(): Record<string, any> {\n if (this.metadata && typeof this.metadata === 'object') {\n return { ...(this.metadata as Record<string, any>) };\n }\n\n try {\n return this.metadata ? JSON.parse(this.metadata) : {};\n } catch {\n return {};\n }\n }\n\n toDefinition(): ContentGovernanceAssignmentDefinition {\n return {\n key: this.key,\n label: this.label || '',\n contentType: this.contentType,\n contentVariant: this.contentVariant || '',\n enabled: this.enabled !== false,\n factLinkingEnabled: this.factLinkingEnabled === true,\n transparencyEnabled: this.transparencyEnabled === true,\n publicationProfileKey: this.publicationProfileKey || null,\n correctionProfileKey: this.correctionProfileKey || null,\n enforcePublishReadiness: this.enforcePublishReadiness === true,\n defaultFactRelationship: this.defaultFactRelationship || 'supports',\n metadata: this.getMetadata(),\n };\n }\n\n protected override async validateBeforeSave(): Promise<void> {\n await super.validateBeforeSave();\n\n this.key = buildContentGovernanceAssignmentKey(\n this.contentType,\n this.contentVariant,\n );\n\n const effective = await getEffectiveContentGovernanceConfig({\n db: this.db,\n });\n const availableProfileKeys = new Set(\n effective.profiles.map((profile) => profile.key),\n );\n const missingProfiles = [\n this.publicationProfileKey,\n this.correctionProfileKey,\n ].filter(\n (profileKey) => profileKey && !availableProfileKeys.has(profileKey),\n );\n\n if (missingProfiles.length > 0) {\n throw new Error(\n `Cannot save governance assignment \"${this.key}\" because these profiles are missing: ${missingProfiles.join(', ')}`,\n );\n }\n }\n}\n","import { SmrtCollection } from '@happyvertical/smrt-core';\nimport { ContentGovernanceAssignment } from './content-governance-assignment';\n\nexport class ContentGovernanceAssignmentCollection extends SmrtCollection<ContentGovernanceAssignment> {\n static readonly _itemClass = ContentGovernanceAssignment;\n\n async getByKey(key: string): Promise<ContentGovernanceAssignment | null> {\n return this.get({ key });\n }\n\n async resolveForContent(options: {\n contentType: string;\n contentVariant?: string | null;\n }): Promise<ContentGovernanceAssignment | null> {\n const exact =\n (await this.get({\n key: `${options.contentType}::${options.contentVariant || ''}`,\n })) || null;\n\n if (exact) {\n return exact;\n }\n\n return this.get({\n key: `${options.contentType}::`,\n });\n }\n}\n","import type { SmrtObjectOptions } from '@happyvertical/smrt-core';\nimport { field, SmrtObject, smrt } from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport {\n type ContentReviewKind,\n type ContentReviewPolicyDefinition,\n getEffectiveContentGovernanceConfig,\n getFallbackPolicyKind,\n hasStaticContentGovernancePolicy,\n} from './content-governance';\n\nexport interface ContentGovernancePolicyOptions extends SmrtObjectOptions {\n key?: string;\n label?: string;\n kind?: ContentReviewKind;\n instructions?: string;\n enabled?: boolean;\n metadata?: string | Record<string, any>;\n tenantId?: string | null;\n createdAt?: Date;\n updatedAt?: Date;\n}\n\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableName: 'content_governance_policies',\n conflictColumns: ['key'],\n api: { include: ['list', 'get', 'create', 'update', 'delete'] },\n mcp: { include: ['list', 'get', 'create', 'update', 'delete'] },\n cli: true,\n})\nexport class ContentGovernancePolicy extends SmrtObject {\n @field({ required: true })\n key = '';\n\n label = '';\n kind: ContentReviewKind = 'custom';\n instructions = '';\n enabled = true;\n metadata = '';\n\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n createdAt = new Date();\n updatedAt = new Date();\n\n constructor(options: ContentGovernancePolicyOptions = {}) {\n super(options);\n if (options.key !== undefined) this.key = options.key;\n if (options.label !== undefined) this.label = options.label;\n if (options.kind !== undefined) this.kind = options.kind;\n if (options.instructions !== undefined)\n this.instructions = options.instructions;\n if (options.enabled !== undefined) this.enabled = options.enabled;\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n if (options.createdAt) this.createdAt = options.createdAt;\n if (options.updatedAt) this.updatedAt = options.updatedAt;\n\n if (options.metadata !== undefined) {\n this.metadata =\n typeof options.metadata === 'string'\n ? options.metadata\n : JSON.stringify(options.metadata);\n }\n }\n\n getMetadata(): Record<string, any> {\n if (this.metadata && typeof this.metadata === 'object') {\n return { ...(this.metadata as Record<string, any>) };\n }\n\n try {\n return this.metadata ? JSON.parse(this.metadata) : {};\n } catch {\n return {};\n }\n }\n\n toDefinition(): ContentReviewPolicyDefinition {\n return {\n key: this.key,\n label: this.label || this.key,\n kind: this.kind || getFallbackPolicyKind(this.key),\n instructions: this.instructions || '',\n enabled: this.enabled !== false,\n metadata: this.getMetadata(),\n };\n }\n\n override async delete(): Promise<void> {\n const effective = await getEffectiveContentGovernanceConfig({\n db: this.db,\n });\n const hasFallback = hasStaticContentGovernancePolicy(this.key);\n const referencedBy = effective.profiles\n .filter((profile) =>\n profile.requirements.some(\n (requirement) => requirement.policyKey === this.key,\n ),\n )\n .map((profile) => profile.key);\n\n if (!hasFallback && referencedBy.length > 0) {\n throw new Error(\n `Cannot delete governance policy \"${this.key}\" because it is referenced by profiles: ${referencedBy.join(', ')}`,\n );\n }\n\n return super.delete();\n }\n}\n","import { SmrtCollection } from '@happyvertical/smrt-core';\nimport { ContentGovernancePolicy } from './content-governance-policy';\n\nexport class ContentGovernancePolicyCollection extends SmrtCollection<ContentGovernancePolicy> {\n static readonly _itemClass = ContentGovernancePolicy;\n\n async getByKey(key: string): Promise<ContentGovernancePolicy | null> {\n return this.get({ key });\n }\n}\n","import type { SmrtObjectOptions } from '@happyvertical/smrt-core';\nimport { field, SmrtObject, smrt } from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport {\n type ContentGovernanceProfileDefinition,\n type ContentReviewRequirement,\n getEffectiveContentGovernanceConfig,\n hasStaticContentGovernanceProfile,\n} from './content-governance';\n\nexport interface ContentGovernanceProfileOptions extends SmrtObjectOptions {\n key?: string;\n label?: string;\n description?: string;\n enabled?: boolean;\n requirements?: string | ContentReviewRequirement[];\n metadata?: string | Record<string, any>;\n tenantId?: string | null;\n createdAt?: Date;\n updatedAt?: Date;\n}\n\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableName: 'content_governance_profiles',\n conflictColumns: ['key'],\n api: { include: ['list', 'get', 'create', 'update', 'delete'] },\n mcp: { include: ['list', 'get', 'create', 'update', 'delete'] },\n cli: true,\n})\nexport class ContentGovernanceProfile extends SmrtObject {\n @field({ required: true })\n key = '';\n\n label = '';\n description = '';\n enabled = true;\n requirements = '[]';\n metadata = '';\n\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n createdAt = new Date();\n updatedAt = new Date();\n\n constructor(options: ContentGovernanceProfileOptions = {}) {\n super(options);\n if (options.key !== undefined) this.key = options.key;\n if (options.label !== undefined) this.label = options.label;\n if (options.description !== undefined)\n this.description = options.description;\n if (options.enabled !== undefined) this.enabled = options.enabled;\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n if (options.createdAt) this.createdAt = options.createdAt;\n if (options.updatedAt) this.updatedAt = options.updatedAt;\n\n if (options.requirements !== undefined) {\n this.requirements =\n typeof options.requirements === 'string'\n ? options.requirements\n : JSON.stringify(options.requirements);\n }\n\n if (options.metadata !== undefined) {\n this.metadata =\n typeof options.metadata === 'string'\n ? options.metadata\n : JSON.stringify(options.metadata);\n }\n }\n\n getRequirements(): ContentReviewRequirement[] {\n if (Array.isArray(this.requirements)) {\n return this.requirements as ContentReviewRequirement[];\n }\n\n try {\n return this.requirements ? JSON.parse(this.requirements) : [];\n } catch {\n return [];\n }\n }\n\n getMetadata(): Record<string, any> {\n if (this.metadata && typeof this.metadata === 'object') {\n return { ...(this.metadata as Record<string, any>) };\n }\n\n try {\n return this.metadata ? JSON.parse(this.metadata) : {};\n } catch {\n return {};\n }\n }\n\n toDefinition(): ContentGovernanceProfileDefinition {\n return {\n key: this.key,\n label: this.label || this.key,\n description: this.description || '',\n enabled: this.enabled !== false,\n requirements: this.getRequirements(),\n metadata: this.getMetadata(),\n };\n }\n\n protected override async validateBeforeSave(): Promise<void> {\n await super.validateBeforeSave();\n\n const effective = await getEffectiveContentGovernanceConfig({\n db: this.db,\n });\n const availablePolicyKeys = new Set(\n effective.policies.map((policy) => policy.key),\n );\n const missingPolicies = this.getRequirements()\n .map((requirement) => requirement.policyKey)\n .filter((policyKey) => !availablePolicyKeys.has(policyKey));\n\n if (missingPolicies.length > 0) {\n throw new Error(\n `Cannot save governance profile \"${this.key}\" because these policies are missing: ${missingPolicies.join(', ')}`,\n );\n }\n }\n\n override async delete(): Promise<void> {\n const effective = await getEffectiveContentGovernanceConfig({\n db: this.db,\n });\n const hasFallback = hasStaticContentGovernanceProfile(this.key);\n const referencedBy = effective.assignments\n .filter(\n (assignment) =>\n assignment.publicationProfileKey === this.key ||\n assignment.correctionProfileKey === this.key,\n )\n .map((assignment) => assignment.key || assignment.contentType);\n\n if (!hasFallback && referencedBy.length > 0) {\n throw new Error(\n `Cannot delete governance profile \"${this.key}\" because it is referenced by assignments: ${referencedBy.join(', ')}`,\n );\n }\n\n return super.delete();\n }\n}\n","import { SmrtCollection } from '@happyvertical/smrt-core';\nimport { ContentGovernanceProfile } from './content-governance-profile';\n\nexport class ContentGovernanceProfileCollection extends SmrtCollection<ContentGovernanceProfile> {\n static readonly _itemClass = ContentGovernanceProfile;\n\n async getByKey(key: string): Promise<ContentGovernanceProfile | null> {\n return this.get({ key });\n }\n}\n","import type { SmrtObjectOptions } from '@happyvertical/smrt-core';\nimport { foreignKey, SmrtObject, smrt } from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport type {\n ContentReviewFinding,\n ContentReviewKind,\n ContentReviewStatus,\n} from './content-governance';\n\nexport interface ContentReviewOptions extends SmrtObjectOptions {\n contentId?: string;\n contentVersionId?: string;\n kind?: ContentReviewKind;\n policyKey?: string;\n status?: ContentReviewStatus;\n summary?: string;\n findings?: string | ContentReviewFinding[];\n reviewer?: string;\n metadata?: string | Record<string, any>;\n tenantId?: string | null;\n createdAt?: Date;\n updatedAt?: Date;\n}\n\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableName: 'content_reviews',\n api: { include: ['list', 'get', 'create', 'update'] },\n mcp: { include: ['list', 'get', 'create', 'update'] },\n cli: true,\n})\nexport class ContentReview extends SmrtObject {\n @foreignKey('Content', { required: true })\n contentId = '';\n\n @foreignKey('ContentVersion')\n contentVersionId = '';\n kind: ContentReviewKind = 'custom';\n policyKey = '';\n status: ContentReviewStatus = 'pending';\n summary = '';\n findings = '[]';\n reviewer = 'system';\n metadata = '';\n\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n createdAt = new Date();\n updatedAt = new Date();\n\n constructor(options: ContentReviewOptions = {}) {\n super(options);\n if (options.contentId) this.contentId = options.contentId;\n if (options.contentVersionId !== undefined)\n this.contentVersionId = options.contentVersionId;\n if (options.kind !== undefined) this.kind = options.kind;\n if (options.policyKey !== undefined) this.policyKey = options.policyKey;\n if (options.status !== undefined) this.status = options.status;\n if (options.summary !== undefined) this.summary = options.summary;\n if (options.reviewer !== undefined) this.reviewer = options.reviewer;\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n if (options.createdAt) this.createdAt = options.createdAt;\n if (options.updatedAt) this.updatedAt = options.updatedAt;\n\n if (options.findings !== undefined) {\n this.findings =\n typeof options.findings === 'string'\n ? options.findings\n : JSON.stringify(options.findings);\n }\n\n if (options.metadata !== undefined) {\n this.metadata =\n typeof options.metadata === 'string'\n ? options.metadata\n : JSON.stringify(options.metadata);\n }\n }\n\n getFindings(): ContentReviewFinding[] {\n if (Array.isArray(this.findings)) {\n return this.findings as ContentReviewFinding[];\n }\n\n try {\n return this.findings ? JSON.parse(this.findings) : [];\n } catch {\n return [];\n }\n }\n\n getMetadata(): Record<string, any> {\n if (this.metadata && typeof this.metadata === 'object') {\n return { ...(this.metadata as Record<string, any>) };\n }\n\n try {\n return this.metadata ? JSON.parse(this.metadata) : {};\n } catch {\n return {};\n }\n }\n}\n","import { SmrtCollection } from '@happyvertical/smrt-core';\nimport type {\n ContentReviewKind,\n ContentReviewResult,\n} from './content-governance';\nimport { ContentReview } from './content-review';\n\nexport class ContentReviewCollection extends SmrtCollection<ContentReview> {\n static readonly _itemClass = ContentReview;\n\n async listForContent(\n contentId: string,\n kind?: ContentReviewKind,\n ): Promise<ContentReview[]> {\n return this.list({\n where: kind ? { contentId, kind } : { contentId },\n orderBy: 'created_at DESC',\n });\n }\n\n async getLatestForContent(\n contentId: string,\n kind?: ContentReviewKind,\n ): Promise<ContentReview | null> {\n const reviews = await this.listForContent(contentId, kind);\n return reviews[0] ?? null;\n }\n\n async listForContentByPolicyKey(\n contentId: string,\n policyKey: string,\n ): Promise<ContentReview[]> {\n return this.list({\n where: { contentId, policyKey },\n orderBy: 'created_at DESC',\n });\n }\n\n async getLatestForPolicyKey(\n contentId: string,\n policyKey: string,\n ): Promise<ContentReview | null> {\n const reviews = await this.listForContentByPolicyKey(contentId, policyKey);\n return reviews[0] ?? null;\n }\n\n async createFromResult(options: {\n contentId: string;\n contentVersionId?: string | null;\n kind: ContentReviewKind;\n policyKey: string;\n reviewer?: string;\n result: ContentReviewResult;\n metadata?: Record<string, any>;\n tenantId?: string | null;\n }): Promise<ContentReview> {\n return this.create({\n contentId: options.contentId,\n contentVersionId: options.contentVersionId || '',\n kind: options.kind,\n policyKey: options.policyKey,\n status: options.result.status,\n summary: options.result.summary,\n findings: JSON.stringify(options.result.findings),\n reviewer: options.reviewer || 'system',\n metadata: JSON.stringify(options.metadata || {}),\n tenantId: options.tenantId ?? null,\n });\n }\n}\n","import type { SmrtObjectOptions } from '@happyvertical/smrt-core';\nimport { foreignKey, SmrtObject, smrt } from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport type { ContentVersionKind } from './content-governance';\nimport { normalizeContentTransparency } from './content-transparency';\n\nexport interface ContentVersionOptions extends SmrtObjectOptions {\n contentId?: string;\n version?: number;\n kind?: ContentVersionKind;\n title?: string;\n description?: string;\n body?: string;\n status?: string;\n summary?: string;\n snapshot?: string | Record<string, any>;\n metadata?: string | Record<string, any>;\n tenantId?: string | null;\n createdAt?: Date;\n updatedAt?: Date;\n}\n\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableName: 'content_versions',\n conflictColumns: ['content_id', 'version'],\n api: {\n include: ['list', 'get', 'create', 'getTransparencyAction'],\n routes: {\n getTransparencyAction: { method: 'GET', path: 'transparency' },\n },\n },\n mcp: { include: ['list', 'get', 'create'] },\n cli: true,\n})\nexport class ContentVersion extends SmrtObject {\n @foreignKey('Content', { required: true })\n contentId = '';\n\n version = 1;\n kind: ContentVersionKind = 'manual';\n title = '';\n description = '';\n body = '';\n status = 'draft';\n summary = '';\n snapshot = '{}';\n metadata = '';\n\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n createdAt = new Date();\n updatedAt = new Date();\n\n constructor(options: ContentVersionOptions = {}) {\n super(options);\n if (options.contentId) this.contentId = options.contentId;\n if (options.version !== undefined) this.version = options.version;\n if (options.kind !== undefined) this.kind = options.kind;\n if (options.title !== undefined) this.title = options.title;\n if (options.description !== undefined)\n this.description = options.description;\n if (options.body !== undefined) this.body = options.body;\n if (options.status !== undefined) this.status = options.status;\n if (options.summary !== undefined) this.summary = options.summary;\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n if (options.createdAt) this.createdAt = options.createdAt;\n if (options.updatedAt) this.updatedAt = options.updatedAt;\n\n if (options.snapshot !== undefined) {\n this.snapshot =\n typeof options.snapshot === 'string'\n ? options.snapshot\n : JSON.stringify(options.snapshot);\n }\n\n if (options.metadata !== undefined) {\n this.metadata =\n typeof options.metadata === 'string'\n ? options.metadata\n : JSON.stringify(options.metadata);\n }\n }\n\n getSnapshot(): Record<string, any> {\n try {\n return this.snapshot ? JSON.parse(this.snapshot) : {};\n } catch {\n return {};\n }\n }\n\n getMetadata(): Record<string, any> {\n try {\n return this.metadata ? JSON.parse(this.metadata) : {};\n } catch {\n return {};\n }\n }\n\n getTransparency() {\n const metadata = this.getMetadata();\n const snapshot = this.getSnapshot();\n\n return normalizeContentTransparency(metadata.transparency, {\n snapshotKind: this.kind === 'publication' ? 'published' : 'preview',\n contentId: this.contentId || (snapshot.contentId as string) || null,\n currentContentStatus:\n this.status || (snapshot.status as string) || 'draft',\n publicationVersion: {\n id: (this.id as string) || null,\n version: this.version ?? null,\n kind: this.kind || null,\n summary: this.summary || '',\n createdAt:\n this.createdAt instanceof Date ? this.createdAt.toISOString() : null,\n },\n });\n }\n\n async getTransparencyAction() {\n return this.getTransparency();\n }\n}\n","import { SmrtCollection } from '@happyvertical/smrt-core';\nimport type { FactContentRelationship } from '@happyvertical/smrt-facts';\nimport type { Content } from './content';\nimport type { CreateContentVersionOptions } from './content-governance';\nimport { resolveEffectiveContentGovernance } from './content-governance';\nimport { ContentVersion } from './content-version';\n\nexport class ContentVersionCollection extends SmrtCollection<ContentVersion> {\n static readonly _itemClass = ContentVersion;\n\n private buildSnapshotFactRelationships(\n snapshot: Record<string, any>,\n defaultRelationship: FactContentRelationship,\n ): Map<FactContentRelationship, string[]> {\n const byRelationship = new Map<FactContentRelationship, string[]>();\n const rawLinks = Array.isArray(snapshot.factLinks)\n ? snapshot.factLinks\n : [];\n\n for (const link of rawLinks) {\n const factId =\n typeof link?.factId === 'string' && link.factId.length > 0\n ? link.factId\n : null;\n const relationship =\n typeof link?.relationship === 'string' && link.relationship.length > 0\n ? (link.relationship as FactContentRelationship)\n : defaultRelationship;\n\n if (!factId) {\n continue;\n }\n\n byRelationship.set(relationship, [\n ...(byRelationship.get(relationship) || []),\n factId,\n ]);\n }\n\n if (\n byRelationship.size === 0 &&\n Array.isArray(snapshot.factIds) &&\n snapshot.factIds.length > 0\n ) {\n byRelationship.set(\n defaultRelationship,\n snapshot.factIds.filter(\n (factId: unknown): factId is string =>\n typeof factId === 'string' && factId.length > 0,\n ),\n );\n }\n\n return byRelationship;\n }\n\n async listForContent(contentId: string): Promise<ContentVersion[]> {\n return this.list({\n where: { contentId },\n orderBy: 'version ASC',\n });\n }\n\n async getLatestForContent(contentId: string): Promise<ContentVersion | null> {\n const versions = await this.listForContent(contentId);\n return versions.length > 0 ? versions[versions.length - 1] : null;\n }\n\n async getLatestPublishedForContent(\n contentId: string,\n ): Promise<ContentVersion | null> {\n const versions = await this.list({\n where: {\n contentId,\n kind: 'publication',\n },\n orderBy: 'version DESC',\n });\n\n return versions[0] || null;\n }\n\n async getVersion(\n contentId: string,\n versionNumber: number,\n ): Promise<ContentVersion | null> {\n return this.get({\n contentId,\n version: versionNumber,\n });\n }\n\n async getNextVersionNumber(contentId: string): Promise<number> {\n const latest = await this.getLatestForContent(contentId);\n return latest ? latest.version + 1 : 1;\n }\n\n async createSnapshot(\n content: Content,\n options: CreateContentVersionOptions = {},\n ): Promise<ContentVersion> {\n if (!content.id) {\n throw new Error('Cannot create a version for unsaved content');\n }\n\n const version = await this.getNextVersionNumber(content.id as string);\n const governance = await resolveEffectiveContentGovernance({\n contentType: content.type,\n contentVariant: content.variant,\n db: this.db,\n });\n const [references, referenceEdges, assets, factsState] = await Promise.all([\n typeof content.getReferences === 'function'\n ? content.getReferences()\n : [],\n // Capture per-edge citation pins so restore can reconstruct them.\n // `getReferences()` resolves to Content objects and loses targetVersion.\n typeof content.getReferenceEdges === 'function'\n ? content.getReferenceEdges()\n : Promise.resolve([]),\n typeof content.getAssets === 'function' ? content.getAssets() : [],\n typeof content.getFactsState === 'function' &&\n governance.factLinkingEnabled\n ? content.getFactsState()\n : {\n factIds: [],\n facts: [],\n factLinks: [],\n },\n ]);\n\n const baseSnapshot = {\n id: content.id,\n slug: content.slug,\n context: content.context,\n name: content.name,\n type: content.type,\n variant: content.variant,\n fileKey: content.fileKey,\n author: content.author,\n title: content.title,\n description: content.description,\n body: content.body,\n bodyFormat: content.bodyFormat,\n publish_date: content.publish_date,\n url: content.url,\n source: content.source,\n original_url: content.original_url,\n language: content.language,\n tags: [...content.tags],\n category: content.category,\n status: content.status,\n state: content.state,\n metadata: content.metadata,\n thumbnailAssetId: content.thumbnailAssetId,\n referenceIds: references.map((reference) => reference.id).filter(Boolean),\n // Full edges with citation pins; `referenceIds` retained for back-compat\n // with snapshots written before pin-aware restore (#1387 #3).\n referenceEdges: referenceEdges.filter((edge) => Boolean(edge.targetId)),\n assetIds: assets.map((asset) => asset.id).filter(Boolean),\n factIds: factsState.factIds,\n factLinks: factsState.factLinks,\n tenantId: content.tenantId,\n _meta_type: content.toJSON()._meta_type,\n };\n const snapshot = {\n ...baseSnapshot,\n ...(options.snapshot || {}),\n };\n const versionSlugBase =\n snapshot.slug ||\n content.slug ||\n content.name ||\n content.title ||\n content.id;\n const versionSlug = `${versionSlugBase}-v${version}`;\n\n return this.create({\n slug: versionSlug,\n context: content.context || '',\n contentId: content.id as string,\n version,\n kind: options.kind || 'manual',\n title: snapshot.title || '',\n description: snapshot.description || '',\n body: snapshot.body || '',\n status: snapshot.status || 'draft',\n summary: options.summary || '',\n snapshot: JSON.stringify(snapshot),\n metadata: JSON.stringify(options.metadata || {}),\n tenantId: content.tenantId,\n });\n }\n\n async restoreIntoContent(\n content: Content,\n versionNumber: number,\n ): Promise<Content> {\n if (!content.id) {\n throw new Error('Cannot restore an unsaved content item');\n }\n\n const version = await this.getVersion(content.id as string, versionNumber);\n if (!version) {\n throw new Error(\n `Content version ${versionNumber} not found for content ${content.id}`,\n );\n }\n\n const snapshot = version.getSnapshot();\n const keysToRestore = [\n 'name',\n 'type',\n 'variant',\n 'fileKey',\n 'author',\n 'title',\n 'description',\n 'body',\n 'bodyFormat',\n 'publish_date',\n 'url',\n 'source',\n 'original_url',\n 'language',\n 'tags',\n 'category',\n 'status',\n 'state',\n 'metadata',\n 'thumbnailAssetId',\n ];\n\n for (const key of keysToRestore) {\n if (snapshot[key] !== undefined) {\n (content as any)[key] = snapshot[key];\n }\n }\n\n // Reference edges with citation pins (#1387 #3). Newer snapshots carry\n // `referenceEdges` ({ targetId, targetVersion }); older ones only have\n // `referenceIds`. Either way, seed the pending `referenceIds` from the\n // target ids so `save()` reconciles the set (adds missing, removes extra),\n // then re-apply the saved pins below so restoring \"to vN\" reconstructs the\n // citation pins that existed at vN instead of dropping them to unpinned.\n const snapshotEdges: Array<{\n targetId: string;\n targetVersion: number | null;\n }> = Array.isArray(snapshot.referenceEdges)\n ? snapshot.referenceEdges\n .filter(\n (edge: any) =>\n edge &&\n typeof edge.targetId === 'string' &&\n edge.targetId.length > 0,\n )\n .map((edge: any) => ({\n targetId: edge.targetId as string,\n targetVersion:\n typeof edge.targetVersion === 'number'\n ? edge.targetVersion\n : null,\n }))\n : Array.isArray(snapshot.referenceIds)\n ? snapshot.referenceIds\n .filter(\n (id: unknown): id is string =>\n typeof id === 'string' && id.length > 0,\n )\n .map((targetId: string) => ({ targetId, targetVersion: null }))\n : [];\n\n if (\n Array.isArray(snapshot.referenceEdges) ||\n Array.isArray(snapshot.referenceIds)\n ) {\n (content as any).referenceIds = snapshotEdges.map(\n (edge) => edge.targetId,\n );\n }\n\n if (Array.isArray(snapshot.assetIds)) {\n (content as any).assetIds = [...snapshot.assetIds];\n }\n\n await content.save();\n\n // Re-apply the citation pin of EVERY snapshot edge — including UNPINNED\n // ones (`targetVersion: null`). `save()` only reconciles the target-id set\n // (adds missing / removes extra edges) and leaves the pin of an edge that\n // already existed untouched. So restoring an *unpinned* snapshot over an\n // edge that is currently *pinned* must explicitly clear that pin, otherwise\n // the live pin survives the restore and drift never resets. Passing\n // `addReference(target, { targetVersion: null })` clears the pin in place\n // (the junction's `attach` updates the row when `null !== existing`), while\n // a non-null value (re)sets it — so \"restore to vN\" reconstructs exactly\n // the pins that existed at vN.\n //\n // We pass the resolved Content object (not the raw id) because\n // `addReference(string)` treats the string as a URL, not a content id.\n // `addReference` is idempotent on (source, target) and only adjusts\n // targetVersion.\n if (\n snapshotEdges.length > 0 &&\n typeof content.getReferences === 'function' &&\n typeof content.addReference === 'function'\n ) {\n const resolvedReferences = await content.getReferences();\n const resolvedById = new Map(\n resolvedReferences\n .filter((reference) => reference.id)\n .map((reference) => [reference.id as string, reference]),\n );\n for (const edge of snapshotEdges) {\n const target = resolvedById.get(edge.targetId);\n if (target) {\n await content.addReference(target, {\n targetVersion: edge.targetVersion,\n });\n }\n }\n }\n\n const governance = await resolveEffectiveContentGovernance({\n contentType: content.type,\n contentVariant: content.variant,\n db: this.db,\n });\n\n if (\n governance.isGoverned &&\n governance.factLinkingEnabled &&\n typeof content.getFactLinks === 'function' &&\n typeof content.syncFacts === 'function'\n ) {\n const desiredByRelationship = this.buildSnapshotFactRelationships(\n snapshot,\n governance.defaultFactRelationship,\n );\n const currentLinks = await content.getFactLinks();\n const currentRelationships = new Set(\n currentLinks.map(\n (link: any) =>\n (link.relationship as FactContentRelationship) ||\n governance.defaultFactRelationship,\n ),\n );\n const relationshipsToSync = new Set<FactContentRelationship>([\n ...currentRelationships,\n ...desiredByRelationship.keys(),\n ]);\n\n for (const relationship of relationshipsToSync) {\n await content.syncFacts(\n desiredByRelationship.get(relationship) || [],\n relationship,\n );\n }\n }\n\n return content;\n }\n}\n","import yaml from 'yaml';\nimport type { Content } from './content';\n\n/**\n * Converts a Content object to a string with YAML frontmatter\n *\n * @param content - Content object to convert\n * @returns String with YAML frontmatter and body content\n */\nexport function contentToString(content: Content) {\n const { body, ...frontmatter } = content;\n const separator = '---';\n const frontmatterYAML = yaml.stringify(frontmatter);\n return `${separator}\\n${frontmatterYAML}\\n${separator}\\n${body}`;\n}\n\n/**\n * Converts a string with YAML frontmatter to a Content object\n *\n * @param data - String with YAML frontmatter and body content\n * @returns Object with parsed frontmatter and body content\n */\nexport function stringToContent(data: string) {\n const separator = '---';\n const frontmatterStart = data.indexOf(separator);\n\n let frontmatter = {};\n let body = data;\n\n if (frontmatterStart !== -1) {\n const frontmatterEnd = data.indexOf(\n separator,\n frontmatterStart + separator.length,\n );\n\n if (frontmatterEnd !== -1) {\n const frontmatterYAML = data\n .substring(frontmatterStart + separator.length, frontmatterEnd)\n .trim();\n // yaml.parse() THROWS on malformed YAML — `|| {}` only covers an\n // empty/null parse. Wrap so a bad frontmatter block degrades to \"no\n // frontmatter\" instead of crashing the caller (#1387).\n try {\n frontmatter = yaml.parse(frontmatterYAML) || {};\n } catch {\n frontmatter = {};\n }\n body = data.substring(frontmatterEnd + separator.length).trim();\n }\n }\n\n return {\n ...frontmatter,\n body,\n };\n}\n"],"names":["__decorateClass","__publicField","mergeByKey","safeParseJSONObject","safeParseJSONArray","normalizeStatus","asArray","isAIClientOptions","getAI","ContentVersionCollection","ContentReviewCollection","ContentCorrectionCollection","Contents","contents","tenantId","stripHtml","parseMetadata","ContentContributionRevisionCollection","ContentContributionAttachmentCollection","ContentContributorCollection","content","defaultOptions","validateEntityName","DEFAULT_XML_ENTITIES","METADATA_SYMBOL","startIndex","path","xmlNode","result","parseDate","dnsLookup","REDIRECT_STATUSES","YAML"],"mappings":"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","x_google_ignoreList":[29,30,31,32,33,34,35,36,37,38,39,40,41,42,43]}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/__smrt-register__.ts","../src/asset-associable.ts","../src/content-asset.ts","../src/content-assets.ts","../src/content-governance.ts","../src/content-prompts.ts","../src/content-reference.ts","../src/content-references.ts","../src/content-transparency.ts","../src/database-utils.ts","../src/serialization.ts","../src/thumbnail-generator.ts","../src/content.ts","../src/content-chat-prompts.ts","../src/content-chat-session.ts","../src/content-chat-handlers.ts","../src/content-contribution-config.ts","../src/content-contribution.ts","../src/content-contribution-attachment.ts","../src/content-contribution-attachments.ts","../src/content-contribution-revision.ts","../src/content-contribution-revisions.ts","../src/content-contribution-type.ts","../src/content-contribution-types.ts","../src/content-contributor.ts","../src/content-contributors.ts","../src/content-contributions.ts","../src/content-correction.ts","../src/content-corrections.ts","../../../node_modules/.pnpm/fast-xml-parser@5.7.2/node_modules/fast-xml-parser/src/util.js","../../../node_modules/.pnpm/fast-xml-parser@5.7.2/node_modules/fast-xml-parser/src/validator.js","../../../node_modules/.pnpm/@nodable+entities@2.1.0/node_modules/@nodable/entities/src/entities.js","../../../node_modules/.pnpm/@nodable+entities@2.1.0/node_modules/@nodable/entities/src/EntityDecoder.js","../../../node_modules/.pnpm/fast-xml-parser@5.7.2/node_modules/fast-xml-parser/src/xmlparser/OptionsBuilder.js","../../../node_modules/.pnpm/fast-xml-parser@5.7.2/node_modules/fast-xml-parser/src/xmlparser/xmlNode.js","../../../node_modules/.pnpm/fast-xml-parser@5.7.2/node_modules/fast-xml-parser/src/xmlparser/DocTypeReader.js","../../../node_modules/.pnpm/strnum@2.2.3/node_modules/strnum/strnum.js","../../../node_modules/.pnpm/fast-xml-parser@5.7.2/node_modules/fast-xml-parser/src/ignoreAttributes.js","../../../node_modules/.pnpm/path-expression-matcher@1.5.0/node_modules/path-expression-matcher/src/Expression.js","../../../node_modules/.pnpm/path-expression-matcher@1.5.0/node_modules/path-expression-matcher/src/ExpressionSet.js","../../../node_modules/.pnpm/path-expression-matcher@1.5.0/node_modules/path-expression-matcher/src/Matcher.js","../../../node_modules/.pnpm/fast-xml-parser@5.7.2/node_modules/fast-xml-parser/src/xmlparser/OrderedObjParser.js","../../../node_modules/.pnpm/fast-xml-parser@5.7.2/node_modules/fast-xml-parser/src/xmlparser/node2json.js","../../../node_modules/.pnpm/fast-xml-parser@5.7.2/node_modules/fast-xml-parser/src/xmlparser/XMLParser.js","../src/content-feed-parser.ts","../src/content-feed-source.ts","../src/content-feed-sources.ts","../src/content-types.ts","../src/safe-remote-url.ts","../src/contents.ts","../src/content-feed-sync.ts","../src/content-governance-assignment.ts","../src/content-governance-assignments.ts","../src/content-governance-policy.ts","../src/content-governance-policies.ts","../src/content-governance-profile.ts","../src/content-governance-profiles.ts","../src/content-review.ts","../src/content-reviews.ts","../src/content-version.ts","../src/content-versions.ts","../src/utils.ts"],"sourcesContent":["/**\n * Self-registers this package's build-time manifest before any @smrt() decorator\n * in the package fires. Fixes issue #1132: in consumer runtimes (tsx, SvelteKit\n * SSR, plain `vite dev`) the decorator's synchronous manifest lookup previously\n * missed because no step populated the global manifest cache — classes got\n * registered with zero fields and `save()` / `toJSON()` silently dropped every\n * declared property.\n *\n * Import this module as the first statement in `src/index.ts` so its top-level\n * side effect runs ahead of any class module's @smrt() decorator.\n *\n * Silent no-op in dev/test, where the vitest plugin already populates manifests\n * via a different path. Only needs to succeed in the published dist output.\n *\n * @see https://github.com/happyvertical/smrt/issues/1132\n */\nimport { ObjectRegistry } from '@happyvertical/smrt-core';\n\n// `new URL('./manifest.json', import.meta.url)` resolves at runtime to the\n// manifest sitting next to this module's compiled output. Vite warns at build\n// time that it cannot pre-resolve the URL; that is the intended behavior —\n// the URL must resolve to dist/manifest.json at runtime, not be inlined.\nObjectRegistry.registerPackageManifest(\n new URL('./manifest.json', import.meta.url),\n);\n","import type { Asset } from '@happyvertical/smrt-assets';\n\n/**\n * Contract for objects that participate in the content/asset association\n * pattern.\n *\n * Any class that exposes asset-relationship methods (e.g. `Content` and its\n * STI subclasses) implements this interface explicitly so consumers can rely\n * on the methods existing instead of falling back to `typeof === 'function'`\n * duck-typing checks.\n *\n * @example\n * ```ts\n * import type { AssetAssociable } from '@happyvertical/smrt-content';\n *\n * async function attachThumbnail(\n * target: AssetAssociable,\n * image: Asset,\n * ): Promise<void> {\n * // No defensive runtime checks needed — the contract guarantees the method.\n * await target.addAsset(image, 'thumbnail', 0);\n * }\n * ```\n */\nexport interface AssetAssociable {\n /**\n * Get all assets associated with this object.\n *\n * @param relationship - Optional filter by relationship type\n * (e.g. `'thumbnail'`, `'attachment'`).\n * @returns Array of associated assets. Returns an empty array if the object\n * has not been persisted yet.\n */\n getAssets(relationship?: string): Promise<Asset[]>;\n\n /**\n * Associate an asset with this object via a typed relationship.\n *\n * @param asset - The asset to associate. Must be persisted (have an `id`).\n * @param relationship - Relationship type. Must match\n * `/^[a-zA-Z_][a-zA-Z0-9_]*$/`. Defaults to `'attachment'`.\n * @param sortOrder - Non-negative integer for display order.\n * @throws if either side is unsaved or the relationship/sort order is invalid.\n */\n addAsset(\n asset: Asset,\n relationship?: string,\n sortOrder?: number,\n ): Promise<void>;\n\n /**\n * Remove an associated asset.\n *\n * @param assetId - The asset ID to detach.\n * @param relationship - Optional specific relationship to remove. If omitted,\n * all relationships between this object and the asset are removed.\n */\n removeAsset(assetId: string, relationship?: string): Promise<void>;\n}\n\n/**\n * Contract for objects exposing typed access to a `metadata` JSON field.\n *\n * Use alongside an explicit interface (such as {@link AssetAssociable}) to\n * give consumers a stable contract for reading/writing the loose JSON bag,\n * without leaking the `metadata: Record<string, any>` type into call sites.\n */\nexport interface MetadataAccessor<\n TMetadata extends Record<string, unknown> = Record<string, unknown>,\n> {\n /**\n * Get the full metadata record. Always returns an object (never `null`).\n * The returned reference is the live object — callers should treat it as\n * read-only and use {@link MetadataAccessor.setMetadata} or\n * {@link MetadataAccessor.updateMetadata} to mutate it safely.\n */\n getMetadata(): TMetadata;\n\n /**\n * Replace the entire metadata record.\n *\n * @param metadata - The new metadata object. `null`/`undefined` clears it.\n */\n setMetadata(metadata: TMetadata | null | undefined): void;\n\n /**\n * Shallow-merge the supplied patch over the existing metadata.\n *\n * @param patch - Partial metadata. Keys present in the patch overwrite the\n * existing record; keys absent from the patch are preserved.\n * @returns The merged metadata record.\n */\n updateMetadata(patch: Partial<TMetadata>): TMetadata;\n}\n\n/**\n * Runtime type guard for {@link AssetAssociable}.\n *\n * The interface exists primarily so that statically-typed consumers can drop\n * defensive `typeof === 'function'` checks. This guard is for the rare cases\n * where a value enters the system as `unknown` (deserialised payload, plugin\n * input, etc.) and the caller needs to confirm shape before delegating.\n *\n * @example\n * ```ts\n * if (isAssetAssociable(input)) {\n * await input.addAsset(asset, 'attachment');\n * }\n * ```\n */\nexport function isAssetAssociable(value: unknown): value is AssetAssociable {\n if (!value || typeof value !== 'object') return false;\n const candidate = value as Partial<AssetAssociable>;\n return (\n typeof candidate.getAssets === 'function' &&\n typeof candidate.addAsset === 'function' &&\n typeof candidate.removeAsset === 'function'\n );\n}\n\n/**\n * Runtime type guard for {@link MetadataAccessor}.\n *\n * Mirrors {@link isAssetAssociable} for the metadata-accessor contract.\n */\nexport function isMetadataAccessor(value: unknown): value is MetadataAccessor {\n if (!value || typeof value !== 'object') return false;\n const candidate = value as Partial<MetadataAccessor>;\n return (\n typeof candidate.getMetadata === 'function' &&\n typeof candidate.setMetadata === 'function' &&\n typeof candidate.updateMetadata === 'function'\n );\n}\n\n/**\n * Returns `true` if `value` is a plain object (not an array, not `null`,\n * not a class instance with a custom prototype). Used by `Content`'s metadata\n * accessors to enforce the \"record-shaped\" contract — arrays and other\n * non-record objects are normalised to `{}` rather than silently leaked\n * through.\n *\n * @internal\n */\nexport function isPlainMetadataRecord(\n value: unknown,\n): value is Record<string, unknown> {\n if (!value || typeof value !== 'object') return false;\n if (Array.isArray(value)) return false;\n const proto = Object.getPrototypeOf(value);\n return proto === null || proto === Object.prototype;\n}\n","import type { SmrtObjectOptions } from '@happyvertical/smrt-core';\nimport {\n crossPackageRef,\n field,\n foreignKey,\n SmrtObject,\n smrt,\n} from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\n\nexport interface ContentAssetOptions extends SmrtObjectOptions {\n contentId?: string;\n assetId?: string;\n relationship?: string;\n sortOrder?: number;\n tenantId?: string | null;\n}\n\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableName: 'content_assets',\n conflictColumns: ['content_id', 'asset_id', 'relationship'],\n api: false,\n mcp: false,\n cli: false,\n})\nexport class ContentAsset extends SmrtObject {\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n @foreignKey('Content', { required: true })\n contentId = '';\n\n @crossPackageRef('@happyvertical/smrt-assets:Asset', { required: true })\n assetId = '';\n\n @field({ required: true })\n relationship = 'attachment';\n\n @field()\n sortOrder = 0;\n\n constructor(options: ContentAssetOptions = {}) {\n super(options);\n if (options.contentId) this.contentId = options.contentId;\n if (options.assetId) this.assetId = options.assetId;\n if (options.relationship) this.relationship = options.relationship;\n if (options.sortOrder !== undefined) this.sortOrder = options.sortOrder;\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n }\n}\n","import type { SmrtCollectionOptions } from '@happyvertical/smrt-core';\nimport { SmrtJunction, smrt } from '@happyvertical/smrt-core';\nimport { ContentAsset } from './content-asset';\n\nexport interface ContentAssetCollectionOptions extends SmrtCollectionOptions {}\n\n@smrt({\n api: false,\n mcp: false,\n cli: false,\n})\nexport class ContentAssetCollection extends SmrtJunction<ContentAsset> {\n static readonly _itemClass = ContentAsset;\n protected leftField = 'contentId';\n protected rightField = 'assetId';\n}\n","import type { Fact, FactContentRelationship } from '@happyvertical/smrt-facts';\nimport type { DatabaseInterface } from '@happyvertical/sql';\nimport type { Content } from './content';\n\nexport type ContentReviewKind = 'facts' | 'safety' | 'custom';\n\nexport type ContentReviewStatus =\n | 'pending'\n | 'passed'\n | 'flagged'\n | 'failed'\n | 'waived';\n\nexport type ContentReviewSeverity = 'info' | 'warning' | 'error';\n\nexport type ContentVersionKind =\n | 'manual'\n | 'draft'\n | 'review'\n | 'publication'\n | 'correction';\n\nexport type ContentCorrectionType = 'fact' | 'safety' | 'copy' | 'custom';\n\nexport type ContentCorrectionStatus = 'draft' | 'published' | 'retracted';\n\nexport interface ContentReviewFinding {\n severity: ContentReviewSeverity;\n title: string;\n detail: string;\n factId?: string;\n quote?: string;\n suggestedChange?: string;\n ruleId?: string;\n}\n\nexport interface ContentReviewResult {\n status: ContentReviewStatus;\n summary: string;\n findings: ContentReviewFinding[];\n}\n\nexport interface ContentReviewRequirement {\n policyKey: string;\n label?: string;\n blocking?: boolean;\n acceptedStatuses?: ContentReviewStatus[];\n}\n\nexport interface ContentReviewProfileEvaluationItem {\n kind: ContentReviewKind;\n policyKey: string;\n label: string;\n blocking: boolean;\n acceptedStatuses: ContentReviewStatus[];\n missing: boolean;\n stale: boolean;\n executed: boolean;\n satisfied: boolean;\n latestReviewId: string | null;\n latestStatus: ContentReviewStatus | null;\n latestSummary: string | null;\n}\n\nexport interface ContentReviewProfileEvaluation {\n profileKey: string;\n ready: boolean;\n complete: boolean;\n requirements: ContentReviewProfileEvaluationItem[];\n}\n\nexport interface ContentReviewPolicyDefinition {\n key: string;\n label: string;\n kind: ContentReviewKind;\n instructions: string;\n enabled?: boolean;\n metadata?: Record<string, unknown>;\n}\n\nexport interface ContentGovernanceProfileDefinition {\n key: string;\n label: string;\n description?: string;\n enabled?: boolean;\n requirements: ContentReviewRequirement[];\n metadata?: Record<string, unknown>;\n}\n\nexport interface ContentGovernanceAssignmentDefinition {\n key?: string;\n label?: string;\n contentType: string;\n contentVariant?: string | null;\n enabled?: boolean;\n factLinkingEnabled?: boolean;\n transparencyEnabled?: boolean;\n publicationProfileKey?: string | null;\n correctionProfileKey?: string | null;\n enforcePublishReadiness?: boolean;\n defaultFactRelationship?: FactContentRelationship;\n metadata?: Record<string, unknown>;\n}\n\nexport interface ContentGovernanceConfig {\n policies: ContentReviewPolicyDefinition[];\n profiles: ContentGovernanceProfileDefinition[];\n assignments: ContentGovernanceAssignmentDefinition[];\n}\n\nexport interface PersistedContentGovernancePolicyRecord\n extends ContentReviewPolicyDefinition {\n id?: string;\n tenantId?: string | null;\n createdAt?: string | null;\n updatedAt?: string | null;\n}\n\nexport interface PersistedContentGovernanceProfileRecord\n extends ContentGovernanceProfileDefinition {\n id?: string;\n tenantId?: string | null;\n createdAt?: string | null;\n updatedAt?: string | null;\n}\n\nexport interface PersistedContentGovernanceAssignmentRecord\n extends ContentGovernanceAssignmentDefinition {\n id?: string;\n tenantId?: string | null;\n createdAt?: string | null;\n updatedAt?: string | null;\n}\n\nexport interface PersistedContentGovernanceDefinitions {\n policies: PersistedContentGovernancePolicyRecord[];\n profiles: PersistedContentGovernanceProfileRecord[];\n assignments: PersistedContentGovernanceAssignmentRecord[];\n}\n\nexport interface ResolvedContentGovernance {\n isGoverned: boolean;\n factLinkingEnabled: boolean;\n transparencyEnabled: boolean;\n publicationProfileKey: string | null;\n correctionProfileKey: string | null;\n enforcePublishReadiness: boolean;\n defaultFactRelationship: FactContentRelationship;\n reviewPolicies: ContentReviewPolicyDefinition[];\n availableProfiles: ContentGovernanceProfileDefinition[];\n assignment: ContentGovernanceAssignmentDefinition | null;\n}\n\nexport interface ContentGovernanceState extends ResolvedContentGovernance {\n reviewProfiles: ContentReviewProfileEvaluation[];\n}\n\nexport interface CreateContentVersionOptions {\n kind?: ContentVersionKind;\n summary?: string;\n metadata?: Record<string, unknown>;\n snapshot?: Record<string, unknown>;\n}\n\nexport interface RunContentReviewOptions {\n kind?: ContentReviewKind;\n policyKey?: string;\n reviewer?: string;\n instructions?: string;\n facts?: Fact[];\n factIds?: string[];\n metadata?: Record<string, unknown>;\n createVersion?: boolean;\n}\n\nexport interface IssueContentCorrectionOptions {\n correctionType?: ContentCorrectionType;\n factId?: string;\n correctedFactText?: string;\n summary: string;\n incorrectText?: string;\n correctedText?: string;\n publicNote?: string;\n metadata?: Record<string, unknown>;\n createVersion?: boolean;\n publish?: boolean;\n}\n\nexport interface BuildContentReviewPromptOptions {\n kind: ContentReviewKind;\n content: Pick<\n Content,\n | 'id'\n | 'type'\n | 'status'\n | 'state'\n | 'title'\n | 'description'\n | 'body'\n | 'author'\n | 'publish_date'\n >;\n facts?: Fact[];\n policy?: ContentReviewPolicyDefinition | null;\n customInstructions?: string;\n}\n\nexport interface ResolveContentGovernanceOptions {\n contentType?: string | null;\n contentVariant?: string | null;\n db?: DatabaseInterface | null;\n}\n\nconst DEFAULT_FACT_RELATIONSHIP: FactContentRelationship = 'supports';\n\nconst DEFAULT_REVIEW_POLICIES: ContentReviewPolicyDefinition[] = [\n {\n key: 'facts',\n label: 'Facts Review',\n kind: 'facts',\n instructions: [\n 'Compare the draft copy against the supplied facts only.',\n 'Flag contradictions, unsupported claims, stale claims, and places where the copy should cite or qualify a statement.',\n 'Do not invent missing facts. If the draft makes a claim that is not supported by the provided facts, flag it clearly.',\n ].join(' '),\n enabled: true,\n },\n {\n key: 'safety',\n label: 'Safety Review',\n kind: 'safety',\n instructions: [\n 'Review the content for legal, reputational, and user-safety risks.',\n 'At minimum, check for defamation risk, privacy leaks, unverified allegations, unsafe instructions, and medical, legal, or financial claims that need qualification.',\n 'Flag content that should be softened, attributed, removed, or escalated for human review.',\n ].join(' '),\n enabled: true,\n },\n];\n\nconst DEFAULT_REVIEW_PROFILES: ContentGovernanceProfileDefinition[] = [\n {\n key: 'publication',\n label: 'Publication',\n description: 'Default publication-time editorial checks.',\n enabled: true,\n requirements: [\n {\n policyKey: 'safety',\n label: 'Safety Review',\n blocking: false,\n },\n {\n policyKey: 'facts',\n label: 'Facts Review',\n blocking: false,\n },\n ],\n },\n {\n key: 'correction',\n label: 'Correction',\n description: 'Default correction-time editorial checks.',\n enabled: true,\n requirements: [\n {\n policyKey: 'safety',\n label: 'Safety Review',\n blocking: false,\n },\n ],\n },\n];\n\nconst DEFAULT_CONTENT_GOVERNANCE_CONFIG: ContentGovernanceConfig = {\n policies: DEFAULT_REVIEW_POLICIES.map(clonePolicyDefinition),\n profiles: DEFAULT_REVIEW_PROFILES.map(cloneProfileDefinition),\n assignments: [],\n};\n\nlet governanceConfig: ContentGovernanceConfig = cloneGovernanceConfig(\n DEFAULT_CONTENT_GOVERNANCE_CONFIG,\n);\n// Process-global by design: apps are expected to configure governance once at\n// startup and use persisted records for runtime admin overrides.\n\nfunction cloneReviewRequirement(\n requirement: ContentReviewRequirement,\n): ContentReviewRequirement {\n return {\n ...requirement,\n acceptedStatuses: requirement.acceptedStatuses\n ? [...requirement.acceptedStatuses]\n : undefined,\n };\n}\n\nfunction normalizePolicyDefinition(\n policy: ContentReviewPolicyDefinition,\n): ContentReviewPolicyDefinition {\n return {\n key: policy.key,\n label: policy.label || policy.key,\n kind: policy.kind || getFallbackPolicyKind(policy.key),\n instructions: policy.instructions || '',\n enabled: policy.enabled !== false,\n metadata: policy.metadata ? { ...policy.metadata } : undefined,\n };\n}\n\nfunction clonePolicyDefinition(\n policy: ContentReviewPolicyDefinition,\n): ContentReviewPolicyDefinition {\n return normalizePolicyDefinition(policy);\n}\n\nfunction normalizeProfileDefinition(\n profile: ContentGovernanceProfileDefinition,\n): ContentGovernanceProfileDefinition {\n return {\n key: profile.key,\n label: profile.label || profile.key,\n description: profile.description || '',\n enabled: profile.enabled !== false,\n requirements: Array.isArray(profile.requirements)\n ? profile.requirements.map(cloneReviewRequirement)\n : [],\n metadata: profile.metadata ? { ...profile.metadata } : undefined,\n };\n}\n\nfunction cloneProfileDefinition(\n profile: ContentGovernanceProfileDefinition,\n): ContentGovernanceProfileDefinition {\n return normalizeProfileDefinition(profile);\n}\n\nexport function buildContentGovernanceAssignmentKey(\n contentType: string,\n contentVariant?: string | null,\n): string {\n return `${contentType || ''}::${contentVariant || ''}`;\n}\n\nfunction normalizeAssignmentDefinition(\n assignment: ContentGovernanceAssignmentDefinition,\n): ContentGovernanceAssignmentDefinition {\n return {\n key:\n assignment.key ||\n buildContentGovernanceAssignmentKey(\n assignment.contentType,\n assignment.contentVariant,\n ),\n label: assignment.label || '',\n contentType: assignment.contentType,\n contentVariant: assignment.contentVariant || '',\n enabled: assignment.enabled !== false,\n factLinkingEnabled: assignment.factLinkingEnabled === true,\n transparencyEnabled: assignment.transparencyEnabled === true,\n publicationProfileKey: assignment.publicationProfileKey || null,\n correctionProfileKey: assignment.correctionProfileKey || null,\n enforcePublishReadiness: assignment.enforcePublishReadiness === true,\n defaultFactRelationship:\n assignment.defaultFactRelationship || DEFAULT_FACT_RELATIONSHIP,\n metadata: assignment.metadata ? { ...assignment.metadata } : undefined,\n };\n}\n\nfunction cloneAssignmentDefinition(\n assignment: ContentGovernanceAssignmentDefinition,\n): ContentGovernanceAssignmentDefinition {\n return normalizeAssignmentDefinition(assignment);\n}\n\nfunction cloneGovernanceConfig(\n config: ContentGovernanceConfig,\n): ContentGovernanceConfig {\n return {\n policies: config.policies.map(clonePolicyDefinition),\n profiles: config.profiles.map(cloneProfileDefinition),\n assignments: config.assignments.map(cloneAssignmentDefinition),\n };\n}\n\nfunction mergeByKey<T extends { key?: string }>(\n previous: T[],\n next: T[],\n normalize: (value: T) => T,\n): T[] {\n const merged = new Map<string, T>();\n\n for (const value of previous) {\n const normalized = normalize(value);\n if (normalized.key) {\n merged.set(normalized.key, normalized);\n }\n }\n\n for (const value of next) {\n const normalized = normalize(value);\n if (normalized.key) {\n merged.set(normalized.key, normalized);\n }\n }\n\n return [...merged.values()];\n}\n\nexport function getFallbackPolicyKind(key: string): ContentReviewKind {\n if (key === 'facts') {\n return 'facts';\n }\n\n if (key === 'safety') {\n return 'safety';\n }\n\n return 'custom';\n}\n\nfunction getPolicyMap(\n policies: ContentReviewPolicyDefinition[],\n): Map<string, ContentReviewPolicyDefinition> {\n return new Map(\n policies.map((policy) => {\n const normalized = normalizePolicyDefinition(policy);\n return [normalized.key, normalized];\n }),\n );\n}\n\nfunction getProfileMap(\n profiles: ContentGovernanceProfileDefinition[],\n): Map<string, ContentGovernanceProfileDefinition> {\n return new Map(\n profiles.map((profile) => {\n const normalized = normalizeProfileDefinition(profile);\n return [normalized.key, normalized];\n }),\n );\n}\n\nfunction isMissingGovernanceTableError(error: unknown): boolean {\n const message =\n error instanceof Error ? error.message : String(error || 'Unknown error');\n\n return (\n message.includes(\"Run 'smrt db:migrate'\") ||\n /no such table/i.test(message) ||\n /does not exist/i.test(message)\n );\n}\n\nfunction getRowTimestamp(\n row: Record<string, unknown>,\n primaryKey: 'createdAt' | 'updatedAt',\n): string | null {\n const snakeCaseKey = primaryKey === 'createdAt' ? 'created_at' : 'updated_at';\n const value = row[primaryKey] ?? row[snakeCaseKey];\n return typeof value === 'string' && value.length > 0 ? value : null;\n}\n\nfunction getRowTenantId(row: Record<string, unknown>): string | null {\n const value = row.tenantId ?? row.tenant_id ?? null;\n return typeof value === 'string' && value.length > 0 ? value : null;\n}\n\nfunction getRowString(\n row: Record<string, unknown>,\n ...keys: string[]\n): string | null {\n for (const key of keys) {\n const value = row[key];\n if (typeof value === 'string' && value.length > 0) {\n return value;\n }\n }\n return null;\n}\n\nfunction safeParseJSONObject(value: unknown): Record<string, unknown> {\n if (!value) {\n return {};\n }\n\n if (typeof value === 'object' && !Array.isArray(value)) {\n return { ...(value as Record<string, unknown>) };\n }\n\n try {\n const parsed = JSON.parse(String(value));\n return parsed && typeof parsed === 'object' && !Array.isArray(parsed)\n ? { ...(parsed as Record<string, unknown>) }\n : {};\n } catch {\n return {};\n }\n}\n\nfunction safeParseJSONArray<T>(value: unknown, mapEntry: (entry: T) => T): T[] {\n if (!value) {\n return [];\n }\n\n if (Array.isArray(value)) {\n return value.map((entry) => mapEntry(entry as T));\n }\n\n try {\n const parsed = JSON.parse(String(value));\n return Array.isArray(parsed)\n ? parsed.map((entry) => mapEntry(entry as T))\n : [];\n } catch {\n return [];\n }\n}\n\nfunction mapPersistedPolicyRow(\n row: Record<string, unknown>,\n): PersistedContentGovernancePolicyRecord {\n return {\n id: typeof row.id === 'string' ? row.id : undefined,\n tenantId: getRowTenantId(row),\n createdAt: getRowTimestamp(row, 'createdAt'),\n updatedAt: getRowTimestamp(row, 'updatedAt'),\n ...normalizePolicyDefinition({\n key: String(row.key || ''),\n label: String(row.label || row.key || ''),\n kind: (row.kind ||\n getFallbackPolicyKind(String(row.key || ''))) as ContentReviewKind,\n instructions: String(row.instructions || ''),\n enabled: row.enabled !== false && row.enabled !== 0,\n metadata: safeParseJSONObject(row.metadata),\n }),\n };\n}\n\nfunction mapPersistedProfileRow(\n row: Record<string, unknown>,\n): PersistedContentGovernanceProfileRecord {\n return {\n id: typeof row.id === 'string' ? row.id : undefined,\n tenantId: getRowTenantId(row),\n createdAt: getRowTimestamp(row, 'createdAt'),\n updatedAt: getRowTimestamp(row, 'updatedAt'),\n ...normalizeProfileDefinition({\n key: String(row.key || ''),\n label: String(row.label || row.key || ''),\n description: String(row.description || ''),\n enabled: row.enabled !== false && row.enabled !== 0,\n requirements: safeParseJSONArray<ContentReviewRequirement>(\n row.requirements,\n cloneReviewRequirement,\n ),\n metadata: safeParseJSONObject(row.metadata),\n }),\n };\n}\n\nfunction mapPersistedAssignmentRow(\n row: Record<string, unknown>,\n): PersistedContentGovernanceAssignmentRecord {\n return {\n id: typeof row.id === 'string' ? row.id : undefined,\n tenantId: getRowTenantId(row),\n createdAt: getRowTimestamp(row, 'createdAt'),\n updatedAt: getRowTimestamp(row, 'updatedAt'),\n ...normalizeAssignmentDefinition({\n key: String(row.key || ''),\n label: String(row.label || ''),\n contentType: String(row.contentType || row.content_type || ''),\n contentVariant: String(row.contentVariant || row.content_variant || ''),\n enabled: row.enabled !== false && row.enabled !== 0,\n factLinkingEnabled:\n row.factLinkingEnabled === true ||\n row.fact_linking_enabled === true ||\n row.fact_linking_enabled === 1,\n transparencyEnabled:\n row.transparencyEnabled === true ||\n row.transparency_enabled === true ||\n row.transparency_enabled === 1,\n publicationProfileKey: getRowString(\n row,\n 'publicationProfileKey',\n 'publication_profile_key',\n ),\n correctionProfileKey: getRowString(\n row,\n 'correctionProfileKey',\n 'correction_profile_key',\n ),\n enforcePublishReadiness:\n row.enforcePublishReadiness === true ||\n row.enforce_publish_readiness === true ||\n row.enforce_publish_readiness === 1,\n // The relationship is stored as a string; trust the persisted value and\n // fall back to the default when absent.\n defaultFactRelationship:\n (getRowString(\n row,\n 'defaultFactRelationship',\n 'default_fact_relationship',\n ) as FactContentRelationship | null) || DEFAULT_FACT_RELATIONSHIP,\n metadata: safeParseJSONObject(row.metadata),\n }),\n };\n}\n\nexport async function loadPersistedContentGovernanceDefinitions(\n options: { db?: DatabaseInterface | null } = {},\n): Promise<PersistedContentGovernanceDefinitions> {\n const { db } = options;\n if (!db) {\n return {\n policies: [],\n profiles: [],\n assignments: [],\n };\n }\n\n try {\n const [policyRows, profileRows, assignmentRows] = await Promise.all([\n db.list('content_governance_policies', {}),\n db.list('content_governance_profiles', {}),\n db.list('content_governance_assignments', {}),\n ]);\n\n const byCreatedAt = (\n a: Record<string, unknown>,\n b: Record<string, unknown>,\n ): number =>\n String(a.created_at || a.createdAt || '').localeCompare(\n String(b.created_at || b.createdAt || ''),\n );\n\n policyRows.sort(byCreatedAt);\n profileRows.sort(byCreatedAt);\n assignmentRows.sort(byCreatedAt);\n\n return {\n policies: policyRows.map((row: Record<string, unknown>) =>\n mapPersistedPolicyRow(row),\n ),\n profiles: profileRows.map((row: Record<string, unknown>) =>\n mapPersistedProfileRow(row),\n ),\n assignments: assignmentRows.map((row: Record<string, unknown>) =>\n mapPersistedAssignmentRow(row),\n ),\n };\n } catch (error) {\n if (isMissingGovernanceTableError(error)) {\n return {\n policies: [],\n profiles: [],\n assignments: [],\n };\n }\n throw error;\n }\n}\n\nfunction resolveAssignmentDefinition(\n assignments: ContentGovernanceAssignmentDefinition[],\n options: Pick<\n ResolveContentGovernanceOptions,\n 'contentType' | 'contentVariant'\n >,\n): ContentGovernanceAssignmentDefinition | null {\n if (!options.contentType) {\n return null;\n }\n\n const exactMatch =\n assignments.find(\n (assignment) =>\n assignment.contentType === options.contentType &&\n (assignment.contentVariant || '') === (options.contentVariant || ''),\n ) || null;\n\n if (exactMatch) {\n return cloneAssignmentDefinition(exactMatch);\n }\n\n const typeOnlyMatch =\n assignments.find(\n (assignment) =>\n assignment.contentType === options.contentType &&\n !assignment.contentVariant,\n ) || null;\n\n return typeOnlyMatch ? cloneAssignmentDefinition(typeOnlyMatch) : null;\n}\n\nfunction buildResolvedGovernance(\n config: ContentGovernanceConfig,\n assignment: ContentGovernanceAssignmentDefinition | null,\n): ResolvedContentGovernance {\n const normalizedAssignment = assignment\n ? normalizeAssignmentDefinition(assignment)\n : null;\n if (!normalizedAssignment || normalizedAssignment.enabled !== true) {\n return {\n isGoverned: false,\n factLinkingEnabled: false,\n transparencyEnabled: false,\n publicationProfileKey: null,\n correctionProfileKey: null,\n enforcePublishReadiness: false,\n defaultFactRelationship: DEFAULT_FACT_RELATIONSHIP,\n reviewPolicies: config.policies\n .map(clonePolicyDefinition)\n .filter((policy) => policy.enabled !== false),\n availableProfiles: config.profiles\n .map(cloneProfileDefinition)\n .filter((profile) => profile.enabled !== false),\n assignment: normalizedAssignment,\n };\n }\n\n return {\n isGoverned: true,\n factLinkingEnabled: normalizedAssignment.factLinkingEnabled === true,\n transparencyEnabled: normalizedAssignment.transparencyEnabled === true,\n publicationProfileKey: normalizedAssignment.publicationProfileKey || null,\n correctionProfileKey: normalizedAssignment.correctionProfileKey || null,\n enforcePublishReadiness:\n normalizedAssignment.enforcePublishReadiness === true,\n defaultFactRelationship:\n normalizedAssignment.defaultFactRelationship || DEFAULT_FACT_RELATIONSHIP,\n reviewPolicies: config.policies\n .map(clonePolicyDefinition)\n .filter((policy) => policy.enabled !== false),\n availableProfiles: config.profiles\n .map(cloneProfileDefinition)\n .filter((profile) => profile.enabled !== false),\n assignment: normalizedAssignment,\n };\n}\n\nfunction normalizeStatus(status: unknown): ContentReviewStatus {\n switch (status) {\n case 'pending':\n case 'passed':\n case 'flagged':\n case 'failed':\n case 'waived':\n return status;\n default:\n return 'flagged';\n }\n}\n\nfunction normalizeSeverity(severity: unknown): ContentReviewSeverity {\n switch (severity) {\n case 'info':\n case 'warning':\n case 'error':\n return severity;\n default:\n return 'warning';\n }\n}\n\nfunction extractJSONObject(raw: string): string | null {\n const start = raw.indexOf('{');\n const end = raw.lastIndexOf('}');\n if (start === -1 || end === -1 || end <= start) {\n return null;\n }\n return raw.slice(start, end + 1);\n}\n\nexport function getContentGovernanceConfig(): ContentGovernanceConfig {\n return cloneGovernanceConfig(governanceConfig);\n}\n\nexport function getStaticContentGovernanceConfig(): ContentGovernanceConfig {\n return cloneGovernanceConfig(governanceConfig);\n}\n\nexport function configureContentGovernance(\n config: Partial<ContentGovernanceConfig>,\n): ContentGovernanceConfig {\n governanceConfig = {\n policies: config.policies\n ? mergeByKey(\n governanceConfig.policies,\n config.policies,\n normalizePolicyDefinition,\n )\n : governanceConfig.policies.map(clonePolicyDefinition),\n profiles: config.profiles\n ? mergeByKey(\n governanceConfig.profiles,\n config.profiles,\n normalizeProfileDefinition,\n )\n : governanceConfig.profiles.map(cloneProfileDefinition),\n assignments: config.assignments\n ? mergeByKey(\n governanceConfig.assignments,\n config.assignments,\n normalizeAssignmentDefinition,\n )\n : governanceConfig.assignments.map(cloneAssignmentDefinition),\n };\n\n return getContentGovernanceConfig();\n}\n\nexport function resetContentGovernanceConfig(): ContentGovernanceConfig {\n governanceConfig = cloneGovernanceConfig(DEFAULT_CONTENT_GOVERNANCE_CONFIG);\n return getContentGovernanceConfig();\n}\n\nexport async function getEffectiveContentGovernanceConfig(\n options: { db?: DatabaseInterface | null } = {},\n): Promise<ContentGovernanceConfig> {\n const persisted = await loadPersistedContentGovernanceDefinitions({\n db: options.db,\n });\n\n return {\n policies: mergeByKey(\n governanceConfig.policies,\n persisted.policies,\n normalizePolicyDefinition,\n ),\n profiles: mergeByKey(\n governanceConfig.profiles,\n persisted.profiles,\n normalizeProfileDefinition,\n ),\n assignments: mergeByKey(\n governanceConfig.assignments,\n persisted.assignments,\n normalizeAssignmentDefinition,\n ),\n };\n}\n\nexport function hasStaticContentGovernancePolicy(key: string): boolean {\n return getPolicyMap(governanceConfig.policies).has(key);\n}\n\nexport function hasStaticContentGovernanceProfile(key: string): boolean {\n return getProfileMap(governanceConfig.profiles).has(key);\n}\n\nexport function getContentReviewPolicy(\n policyKey: string,\n policies: ContentReviewPolicyDefinition[] = governanceConfig.policies,\n): ContentReviewPolicyDefinition | null {\n return getPolicyMap(policies).get(policyKey) || null;\n}\n\nexport function getContentReviewKind(\n policyKey: string,\n policies: ContentReviewPolicyDefinition[] = governanceConfig.policies,\n): ContentReviewKind {\n const configuredKind = getPolicyMap(policies).get(policyKey)?.kind;\n return configuredKind || getFallbackPolicyKind(policyKey);\n}\n\nexport function getContentReviewProfile(\n profileKey: string,\n profiles: ContentGovernanceProfileDefinition[] = governanceConfig.profiles,\n): ContentGovernanceProfileDefinition | null {\n return getProfileMap(profiles).get(profileKey) || null;\n}\n\nexport function getContentReviewProfileKeys(\n profiles: ContentGovernanceProfileDefinition[] = governanceConfig.profiles,\n): string[] {\n return profiles\n .map(cloneProfileDefinition)\n .filter((profile) => profile.enabled !== false)\n .map((profile) => profile.key);\n}\n\nexport function getContentReviewPolicies(\n policies: ContentReviewPolicyDefinition[] = governanceConfig.policies,\n): ContentReviewPolicyDefinition[] {\n return policies\n .map(clonePolicyDefinition)\n .filter((policy) => policy.enabled !== false);\n}\n\nexport function getContentReviewRequirements(\n profileKey: string,\n profiles: ContentGovernanceProfileDefinition[] = governanceConfig.profiles,\n): ContentReviewRequirement[] {\n const profile = getContentReviewProfile(profileKey, profiles);\n return profile?.requirements.map(cloneReviewRequirement) || [];\n}\n\nexport function getAcceptedContentReviewStatuses(\n requirement: Pick<ContentReviewRequirement, 'acceptedStatuses'>,\n): ContentReviewStatus[] {\n return requirement.acceptedStatuses && requirement.acceptedStatuses.length > 0\n ? [...requirement.acceptedStatuses]\n : ['passed', 'waived'];\n}\n\nexport function resolveConfiguredContentGovernance(\n options: Pick<\n ResolveContentGovernanceOptions,\n 'contentType' | 'contentVariant'\n >,\n): ResolvedContentGovernance {\n const assignment = resolveAssignmentDefinition(governanceConfig.assignments, {\n contentType: options.contentType,\n contentVariant: options.contentVariant,\n });\n\n return buildResolvedGovernance(governanceConfig, assignment);\n}\n\nexport async function resolveEffectiveContentGovernance(\n options: ResolveContentGovernanceOptions,\n): Promise<ResolvedContentGovernance> {\n const effectiveConfig = await getEffectiveContentGovernanceConfig({\n db: options.db,\n });\n const assignment = resolveAssignmentDefinition(effectiveConfig.assignments, {\n contentType: options.contentType,\n contentVariant: options.contentVariant,\n });\n\n return buildResolvedGovernance(effectiveConfig, assignment);\n}\n\nexport function buildContentReviewPrompt(\n options: BuildContentReviewPromptOptions,\n): string {\n const { kind, content, facts = [], policy, customInstructions } = options;\n\n const factLines =\n facts.length > 0\n ? facts\n .map(\n (fact) =>\n `- [${fact.id}] status=${fact.status}; confidence=${fact.confidence}; sources=${fact.sourceCount}; text=${fact.textRefined}`,\n )\n .join('\\n')\n : 'No facts were supplied for this review.';\n\n const policyText =\n customInstructions?.trim() ||\n policy?.instructions ||\n getContentReviewPolicy(kind)?.instructions ||\n '';\n\n return `You are a structured editorial reviewer.\n\nReturn ONLY valid JSON with this shape:\n{\n \"status\": \"passed\" | \"flagged\" | \"failed\" | \"waived\",\n \"summary\": \"short summary\",\n \"findings\": [\n {\n \"severity\": \"info\" | \"warning\" | \"error\",\n \"title\": \"short title\",\n \"detail\": \"what is wrong and why\",\n \"factId\": \"optional fact id\",\n \"quote\": \"optional quoted text from the draft\",\n \"suggestedChange\": \"optional suggested fix\",\n \"ruleId\": \"optional policy or rule id\"\n }\n ]\n}\n\nReview kind: ${kind}\nPolicy key: ${policy?.key || kind}\nReview instructions:\n${policyText}\n\nDraft content:\n- id: ${content.id ?? ''}\n- type: ${content.type ?? ''}\n- status: ${content.status}\n- state: ${content.state}\n- author: ${content.author ?? ''}\n- publish_date: ${content.publish_date?.toISOString?.() ?? ''}\n\nTitle:\n${content.title}\n\nDescription:\n${content.description ?? ''}\n\nBody:\n${content.body}\n\nRelevant facts:\n${factLines}`;\n}\n\nexport function parseContentReviewResponse(raw: string): ContentReviewResult {\n const normalizedRaw = raw.trim();\n const jsonCandidate = extractJSONObject(normalizedRaw);\n\n if (jsonCandidate) {\n try {\n const parsed = JSON.parse(jsonCandidate) as {\n status?: unknown;\n summary?: unknown;\n findings?: unknown;\n };\n const findings = Array.isArray(parsed.findings)\n ? parsed.findings.map((rawFinding): ContentReviewFinding => {\n const finding =\n rawFinding && typeof rawFinding === 'object'\n ? (rawFinding as Record<string, unknown>)\n : {};\n return {\n severity: normalizeSeverity(finding.severity),\n title: String(finding.title || 'Review finding'),\n detail: String(finding.detail || ''),\n factId:\n typeof finding.factId === 'string' ? finding.factId : undefined,\n quote:\n typeof finding.quote === 'string' ? finding.quote : undefined,\n suggestedChange:\n typeof finding.suggestedChange === 'string'\n ? finding.suggestedChange\n : undefined,\n ruleId:\n typeof finding.ruleId === 'string' ? finding.ruleId : undefined,\n };\n })\n : [];\n\n return {\n status: normalizeStatus(parsed.status),\n summary: String(parsed.summary || normalizedRaw || 'Review completed'),\n findings,\n };\n } catch {\n // Fall through to a normalized fallback result.\n }\n }\n\n return {\n status: 'flagged',\n summary: normalizedRaw || 'Review completed without structured output.',\n findings: normalizedRaw\n ? [\n {\n severity: 'warning',\n title: 'Unstructured review output',\n detail: normalizedRaw,\n },\n ]\n : [],\n };\n}\n","import {\n definePrompt,\n type ResolvedPromptAI,\n} from '@happyvertical/smrt-prompts';\n\nexport const smrtContentReviewPrompt = definePrompt({\n key: 'smrtContent.review',\n template: `Content review request\n\nContent ID: {contentId}\nReview kind: {kind}\nPolicy key: {policyKey}\nTitle: {contentTitle}\nDescription: {contentDescription}\n\nBody:\n{contentBody}\n\n{reviewPrompt}`,\n editable: {\n template: true,\n profile: true,\n model: true,\n params: true,\n },\n});\n\nexport const smrtContentApplyCorrectionPrompt = definePrompt({\n key: 'smrtContent.applyCorrection',\n template: `You are revising an article draft to apply a factual correction.\n\nReturn only the fully revised body text, with no commentary.\n\nCurrent body:\n{body}\n\nCorrection summary:\n{summary}\n\nIncorrect text to fix:\n{incorrectText}\n\nCorrected text to incorporate:\n{correctedText}`,\n editable: {\n template: true,\n profile: true,\n model: true,\n params: true,\n },\n});\n\nexport const smrtContentThumbnailAIGeneratePrompt = definePrompt({\n key: 'smrtContent.thumbnail.aiGenerate',\n template: `Create a {style} thumbnail image for an article titled \"{title}\". {descriptionClause}Style: {styleHint}. The image should be suitable for a news article or blog post thumbnail.`,\n editable: {\n template: true,\n profile: true,\n model: true,\n params: true,\n },\n});\n\nexport function promptMessageOptions(ai: ResolvedPromptAI) {\n return {\n ...(ai.params || {}),\n ...(ai.model ? { model: ai.model } : {}),\n ...(typeof ai.temperature === 'number'\n ? { temperature: ai.temperature }\n : {}),\n ...(typeof ai.maxTokens === 'number' ? { maxTokens: ai.maxTokens } : {}),\n };\n}\n","import type { SmrtObjectOptions } from '@happyvertical/smrt-core';\nimport { field, foreignKey, SmrtObject, smrt } from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\n\nexport interface ContentReferenceOptions extends SmrtObjectOptions {\n sourceId?: string;\n targetId?: string;\n tenantId?: string | null;\n // ContentVersion.version pinned at citation time. Optional: references\n // created without a pin behave as before (they track the live target).\n // When set, callers can compare against the target's latest version to\n // surface drift between what was cited and what the target now says.\n targetVersion?: number | null;\n createdAt?: Date;\n}\n\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableName: 'content_references',\n conflictColumns: ['source_id', 'target_id'],\n})\nexport class ContentReference extends SmrtObject {\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n @foreignKey('Content', { required: true })\n sourceId = '';\n\n @foreignKey('Content', { required: true })\n targetId = '';\n\n @field({ type: 'integer', nullable: true })\n targetVersion: number | null = null;\n\n @field()\n createdAt = new Date();\n\n constructor(options: ContentReferenceOptions = {}) {\n super(options);\n if (options.sourceId) this.sourceId = options.sourceId;\n if (options.targetId) this.targetId = options.targetId;\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n if (options.targetVersion !== undefined)\n this.targetVersion = options.targetVersion;\n if (options.createdAt) this.createdAt = options.createdAt;\n }\n}\n","import type {\n JunctionAttachOptions,\n SmrtCollectionOptions,\n} from '@happyvertical/smrt-core';\nimport { SmrtJunction, smrt } from '@happyvertical/smrt-core';\nimport { ContentReference } from './content-reference';\n\nexport interface ContentReferencesOptions extends SmrtCollectionOptions {}\n\n/**\n * The `attach()` override below restores find-or-create idempotency for\n * `(sourceId, targetId)` — duplicate calls return the existing row\n * unchanged, preserving `id` and `createdAt`. This matters because\n * `ContentReference` rows are externally addressable via\n * `/api/v1/contentreferences/[id]`.\n *\n * Two REST entry points (both auto-generated by the scanner):\n * - `POST /api/v1/contentreferences` (from model CRUD) calls\n * `collection.create()` which is upsert-based — id/createdAt get\n * rewritten on conflict. Convenient for callers that don't care\n * about row id stability.\n * - `POST /api/v1/contentreferences/attach` (from the override below)\n * is idempotent. Use this for stable URLs.\n *\n * Internal callers (`Content.addReference()`) always hit the idempotent\n * path because they call the collection directly.\n *\n * The `/attach` route exists because R2 round-7 added `@smrt()` to this\n * class, which made the scanner pick up the override as a custom\n * collection method route. Pre-R2 had a `/link` route from the\n * pre-rename method name.\n */\n// Decorator with empty config — only needed so the scanner detects the\n// class. See FactContentCollection for the full rationale.\n@smrt()\nexport class ContentReferences extends SmrtJunction<ContentReference> {\n static readonly _itemClass = ContentReference;\n protected leftField = 'sourceId';\n protected rightField = 'targetId';\n // content_references has no sort_order column — preserve insertion order\n // by sorting on created_at, and disable setLinks position auto-indexing\n // so it doesn't try to write integer indices into the timestamp column.\n protected sortField: string | null = 'createdAt';\n protected positionField: string | null = null;\n\n async getForSource(sourceId: string): Promise<ContentReference[]> {\n return (await this.list({\n where: { sourceId },\n orderBy: 'created_at ASC',\n })) as ContentReference[];\n }\n\n async getForTarget(targetId: string): Promise<ContentReference[]> {\n return (await this.list({\n where: { targetId },\n orderBy: 'created_at ASC',\n })) as ContentReference[];\n }\n\n /**\n * Find-or-create idempotency: if a reference already exists for\n * (sourceId, targetId), return the existing row unchanged instead of\n * upserting a new row. This preserves the existing row's `id` and\n * `createdAt`, which is important because reference rows are\n * externally addressable via `/api/v1/contentreferences/[id]`.\n *\n * The base `SmrtJunction.attach` flow (this.create → db.upsert) would\n * overwrite both columns on every duplicate call.\n *\n * Reference pinning (main): `opts.targetVersion` pins the citation to a\n * specific `ContentVersion.version` for drift detection. Re-attaching an\n * existing edge with a different `targetVersion` updates the pin in place;\n * `undefined` leaves an existing pin untouched, while a brand-new row\n * defaults the pin to `null` (unpinned).\n */\n async attach(\n sourceId: string,\n targetId: string,\n opts: JunctionAttachOptions = {},\n ): Promise<ContentReference> {\n const targetVersion = opts.targetVersion as number | null | undefined;\n const existing = (await this.get({\n sourceId,\n targetId,\n })) as ContentReference | null;\n if (existing) {\n if (\n targetVersion !== undefined &&\n existing.targetVersion !== targetVersion\n ) {\n existing.targetVersion = targetVersion;\n await existing.save();\n }\n return existing;\n }\n return super.attach(sourceId, targetId, {\n ...opts,\n targetVersion: targetVersion ?? null,\n });\n }\n\n async unlink(sourceId: string, targetId: string): Promise<void> {\n await this.detach(sourceId, targetId);\n }\n}\n","export interface ContentTransparencyGeneration {\n aiAssisted: boolean;\n publicPrompt: string | null;\n model: string | null;\n}\n\nexport interface ContentTransparencySource {\n id: string | null;\n sourceType: string | null;\n sourceUrl: string | null;\n sourceTitle: string | null;\n credibility: number | null;\n extractedAt: string | null;\n metadata: Record<string, unknown>;\n}\n\nexport interface ContentTransparencyFact {\n id: string | null;\n textRaw?: string | null;\n textRefined?: string | null;\n status?: string | null;\n domain?: string | null;\n confidence?: number | null;\n sourceCount?: number | null;\n metadata?: Record<string, unknown>;\n relationship?: string | null;\n linkMetadata?: Record<string, unknown>;\n usedInArticle?: boolean;\n sources?: ContentTransparencySource[];\n}\n\nexport interface ContentTransparencyReference {\n id: string | null;\n title: string | null;\n url: string | null;\n originalUrl: string | null;\n type: string | null;\n source: string | null;\n usedFactIds: string[];\n extractedFacts: ContentTransparencyFact[];\n}\n\nexport interface ContentTransparencyPublicationVersion {\n id: string | null;\n version: number | null;\n kind: string | null;\n summary: string;\n createdAt: string | null;\n}\n\nexport interface ContentTransparencyVersionHistoryItem {\n id: string | null;\n version: number | null;\n kind: string | null;\n summary: string;\n createdAt: string | null;\n provenance: Record<string, unknown>;\n}\n\n/**\n * Serialized review record carried in a transparency snapshot. Only the fields\n * consumers read are named; the index signature preserves the remaining\n * serialized properties.\n */\nexport interface ContentTransparencyReview {\n id?: string | null;\n kind?: string | null;\n policyKey?: string | null;\n status?: string | null;\n summary?: string | null;\n createdAt?: string | null;\n [key: string]: unknown;\n}\n\n/**\n * Serialized review-profile evaluation carried in a transparency snapshot.\n */\nexport interface ContentTransparencyReviewProfile {\n profileKey?: string | null;\n [key: string]: unknown;\n}\n\n/**\n * Serialized correction record carried in a transparency snapshot.\n */\nexport interface ContentTransparencyCorrection {\n id?: string | null;\n summary?: string | null;\n publicNote?: string | null;\n publishedAt?: string | null;\n [key: string]: unknown;\n}\n\nexport interface ContentTransparencyData {\n generatedAt: string | null;\n snapshotKind: 'preview' | 'published';\n contentId: string | null;\n currentContentStatus: string | null;\n publicationProfileKey: string;\n publicationVersion: ContentTransparencyPublicationVersion | null;\n generation: ContentTransparencyGeneration;\n factsUsed: ContentTransparencyFact[];\n linkedFacts: ContentTransparencyFact[];\n otherExtractedFacts: ContentTransparencyFact[];\n references: ContentTransparencyReference[];\n reviews: ContentTransparencyReview[];\n reviewProfiles: ContentTransparencyReviewProfile[];\n corrections: ContentTransparencyCorrection[];\n versionHistory: ContentTransparencyVersionHistoryItem[];\n}\n\nfunction asObject(\n value: unknown,\n fallback: Record<string, unknown> = {},\n): Record<string, unknown> {\n return value && typeof value === 'object'\n ? { ...(value as Record<string, unknown>) }\n : fallback;\n}\n\nfunction asString(value: unknown): string | null {\n return typeof value === 'string' && value.length > 0 ? value : null;\n}\n\nfunction asNumber(value: unknown): number | null {\n return typeof value === 'number' && Number.isFinite(value) ? value : null;\n}\n\nfunction asArray<T>(value: unknown): T[] {\n return Array.isArray(value) ? (value as T[]) : [];\n}\n\nfunction normalizeGeneration(value: unknown): ContentTransparencyGeneration {\n const generation = asObject(value);\n return {\n aiAssisted: Boolean(generation.aiAssisted),\n publicPrompt: asString(generation.publicPrompt),\n model: asString(generation.model),\n };\n}\n\nfunction normalizeFact(value: unknown): ContentTransparencyFact {\n const fact = asObject(value);\n return {\n ...fact,\n id: asString(fact.id),\n relationship: asString(fact.relationship),\n linkMetadata: asObject(fact.linkMetadata),\n usedInArticle: Boolean(fact.usedInArticle),\n sources: asArray<unknown>(fact.sources).map(normalizeSource),\n };\n}\n\nfunction normalizeSource(value: unknown): ContentTransparencySource {\n const source = asObject(value);\n return {\n id: asString(source.id),\n sourceType: asString(source.sourceType),\n sourceUrl: asString(source.sourceUrl),\n sourceTitle: asString(source.sourceTitle),\n credibility: asNumber(source.credibility),\n extractedAt: asString(source.extractedAt),\n metadata: asObject(source.metadata),\n };\n}\n\nfunction normalizeReference(value: unknown): ContentTransparencyReference {\n const reference = asObject(value);\n return {\n id: asString(reference.id),\n title: asString(reference.title),\n url: asString(reference.url),\n originalUrl: asString(reference.originalUrl),\n type: asString(reference.type),\n source: asString(reference.source),\n usedFactIds: asArray<string>(reference.usedFactIds).filter(Boolean),\n extractedFacts: asArray<unknown>(reference.extractedFacts).map(\n normalizeFact,\n ),\n };\n}\n\nfunction normalizePublicationVersion(\n value: unknown,\n): ContentTransparencyPublicationVersion | null {\n const publicationVersion = asObject(value);\n if (!publicationVersion.id && publicationVersion.version === undefined) {\n return null;\n }\n\n return {\n id: asString(publicationVersion.id),\n version: asNumber(publicationVersion.version),\n kind: asString(publicationVersion.kind),\n summary:\n typeof publicationVersion.summary === 'string'\n ? publicationVersion.summary\n : '',\n createdAt: asString(publicationVersion.createdAt),\n };\n}\n\nfunction normalizeVersionHistoryItem(\n value: unknown,\n): ContentTransparencyVersionHistoryItem {\n const version = asObject(value);\n return {\n id: asString(version.id),\n version: asNumber(version.version),\n kind: asString(version.kind),\n summary: typeof version.summary === 'string' ? version.summary : '',\n createdAt: asString(version.createdAt),\n provenance: asObject(version.provenance),\n };\n}\n\nfunction dedupeFacts(facts: ContentTransparencyFact[]) {\n const byKey = new Map<string, ContentTransparencyFact>();\n\n for (const fact of facts) {\n // Collapse effectively empty facts into a single placeholder bucket rather\n // than rendering duplicate blank entries in the public transparency view.\n const key =\n fact.id ||\n fact.textRefined ||\n fact.textRaw ||\n JSON.stringify(fact.metadata || {});\n if (!key) {\n continue;\n }\n\n byKey.set(key, fact);\n }\n\n return [...byKey.values()];\n}\n\nexport function normalizeContentTransparency(\n value: unknown,\n defaults: Partial<ContentTransparencyData> = {},\n): ContentTransparencyData {\n const snapshot = asObject(value);\n const references = asArray<unknown>(snapshot.references).map(\n normalizeReference,\n );\n const linkedFacts = asArray<unknown>(snapshot.linkedFacts).map(normalizeFact);\n const factsUsed =\n asArray<unknown>(snapshot.factsUsed).length > 0\n ? asArray<unknown>(snapshot.factsUsed).map(normalizeFact)\n : linkedFacts.filter((fact) => fact.usedInArticle);\n const otherExtractedFacts =\n asArray<unknown>(snapshot.otherExtractedFacts).length > 0\n ? asArray<unknown>(snapshot.otherExtractedFacts).map(normalizeFact)\n : dedupeFacts(\n references.flatMap((reference) =>\n reference.extractedFacts.filter((fact) => !fact.usedInArticle),\n ),\n );\n\n return {\n generatedAt: asString(snapshot.generatedAt) ?? defaults.generatedAt ?? null,\n snapshotKind:\n snapshot.snapshotKind === 'published'\n ? 'published'\n : defaults.snapshotKind || 'preview',\n contentId: asString(snapshot.contentId) ?? defaults.contentId ?? null,\n currentContentStatus:\n asString(snapshot.currentContentStatus) ??\n defaults.currentContentStatus ??\n null,\n publicationProfileKey:\n asString(snapshot.publicationProfileKey) ??\n asString(snapshot.publicationReviewProfileKey) ??\n defaults.publicationProfileKey ??\n 'publication',\n publicationVersion:\n normalizePublicationVersion(snapshot.publicationVersion) ??\n defaults.publicationVersion ??\n null,\n generation: normalizeGeneration(\n snapshot.generation ?? defaults.generation ?? {},\n ),\n factsUsed,\n linkedFacts,\n otherExtractedFacts,\n references,\n reviews: asArray<ContentTransparencyReview>(snapshot.reviews),\n reviewProfiles: asArray<ContentTransparencyReviewProfile>(\n snapshot.reviewProfiles,\n ),\n corrections: asArray<ContentTransparencyCorrection>(snapshot.corrections),\n versionHistory: asArray<unknown>(snapshot.versionHistory).map(\n normalizeVersionHistoryItem,\n ),\n };\n}\n","export function isMissingTableError(\n error: unknown,\n tableName: string,\n): boolean {\n const message = String(\n (error as Error)?.message || error || '',\n ).toLowerCase();\n\n return (\n message.includes(tableName.toLowerCase()) &&\n (message.includes('no such table') ||\n message.includes('does not exist') ||\n message.includes('relation'))\n );\n}\n\nexport function getQueryRows(result: unknown): Record<string, unknown>[] {\n return Array.isArray(result)\n ? (result as Record<string, unknown>[])\n : Array.isArray((result as { rows?: Record<string, unknown>[] })?.rows)\n ? ((result as { rows: Record<string, unknown>[] }).rows ?? [])\n : [];\n}\n","/**\n * Plain JSON shape produced by serializing a SMRT model instance. Values are\n * intentionally `unknown` — callers spread these records into API responses and\n * narrow individual fields where they need a concrete type.\n */\ntype SerializedRecord = Record<string, unknown>;\n\n/**\n * Minimal structural view of the model instances passed to the serializers.\n * Every model used here exposes `toJSON()` plus optional accessor methods for\n * its JSON-backed fields; the accessors are typed loosely because each model\n * returns a different concrete shape.\n */\ninterface SerializableModel {\n toJSON?: () => unknown;\n getMetadata?: () => unknown;\n getSnapshot?: () => unknown;\n getFindings?: () => unknown;\n getAllowedChannels?: () => unknown;\n getIntakeRules?: () => unknown;\n getPromotion?: () => unknown;\n getRevisions?: () => Promise<unknown[]> | unknown[];\n getAttachments?: () => Promise<unknown[]> | unknown[];\n getContributor?: () => Promise<unknown> | unknown;\n getReferences?: () => Promise<unknown[]> | unknown[];\n getAssets?: () => Promise<unknown[]> | unknown[];\n getReferenceDrift?: () => Promise<unknown> | unknown;\n metadata?: unknown;\n}\n\nfunction asModel(value: unknown): SerializableModel {\n return value && typeof value === 'object' ? (value as SerializableModel) : {};\n}\n\nfunction toJSON(value: unknown): SerializedRecord {\n const model = asModel(value);\n if (typeof model.toJSON === 'function') {\n const serialized = model.toJSON();\n return serialized && typeof serialized === 'object'\n ? (serialized as SerializedRecord)\n : {};\n }\n\n return value && typeof value === 'object' ? (value as SerializedRecord) : {};\n}\n\nexport function serializeFact(fact: unknown) {\n const model = asModel(fact);\n const data = toJSON(fact);\n return {\n ...data,\n metadata:\n typeof model.getMetadata === 'function'\n ? model.getMetadata()\n : data.metadata || {},\n };\n}\n\nexport function serializeFactLink(link: unknown) {\n const model = asModel(link);\n const data = toJSON(link);\n return {\n ...data,\n metadata:\n typeof model.getMetadata === 'function'\n ? model.getMetadata()\n : data.metadata || {},\n };\n}\n\nexport function serializeContentVersion(version: unknown) {\n const model = asModel(version);\n const data = toJSON(version);\n return {\n ...data,\n snapshot:\n typeof model.getSnapshot === 'function'\n ? model.getSnapshot()\n : data.snapshot || {},\n metadata:\n typeof model.getMetadata === 'function'\n ? model.getMetadata()\n : data.metadata || {},\n };\n}\n\nexport function serializeContentReview(review: unknown) {\n const model = asModel(review);\n const data = toJSON(review);\n return {\n ...data,\n findings:\n typeof model.getFindings === 'function'\n ? model.getFindings()\n : data.findings || [],\n metadata:\n typeof model.getMetadata === 'function'\n ? model.getMetadata()\n : data.metadata || {},\n };\n}\n\nexport function serializeContentCorrection(correction: unknown) {\n const model = asModel(correction);\n const data = toJSON(correction);\n return {\n ...data,\n metadata:\n typeof model.getMetadata === 'function'\n ? model.getMetadata()\n : data.metadata || {},\n };\n}\n\nexport function serializeContentContributor(contributor: unknown) {\n const model = asModel(contributor);\n const data = toJSON(contributor);\n return {\n ...data,\n metadata:\n typeof model.getMetadata === 'function'\n ? model.getMetadata()\n : data.metadata || {},\n };\n}\n\nexport function serializeContentContributionType(contributionType: unknown) {\n const model = asModel(contributionType);\n const data = toJSON(contributionType);\n return {\n ...data,\n allowedChannels:\n typeof model.getAllowedChannels === 'function'\n ? model.getAllowedChannels()\n : data.allowedChannels || [],\n intakeRules:\n typeof model.getIntakeRules === 'function'\n ? model.getIntakeRules()\n : data.intakeRules || {},\n promotion:\n typeof model.getPromotion === 'function'\n ? model.getPromotion()\n : data.promotion || {},\n metadata:\n typeof model.getMetadata === 'function'\n ? model.getMetadata()\n : data.metadata || {},\n };\n}\n\nexport function serializeContentContributionRevision(revision: unknown) {\n const model = asModel(revision);\n const data = toJSON(revision);\n return {\n ...data,\n sourceMessageId: data.sourceMessageId || null,\n sourceThreadKey: data.sourceThreadKey || null,\n metadata:\n typeof model.getMetadata === 'function'\n ? model.getMetadata()\n : data.metadata || {},\n };\n}\n\nexport function serializeContentContributionAttachment(attachment: unknown) {\n const model = asModel(attachment);\n const data = toJSON(attachment);\n return {\n ...data,\n revisionId: data.revisionId || null,\n fileKey: data.fileKey || null,\n sourceUri: data.sourceUri || null,\n promotedAssetId: data.promotedAssetId || null,\n metadata:\n typeof model.getMetadata === 'function'\n ? model.getMetadata()\n : data.metadata || {},\n };\n}\n\nexport async function serializeContentContribution(contribution: unknown) {\n const model = asModel(contribution);\n const [revisions, attachments, contributor] = await Promise.all([\n typeof model.getRevisions === 'function' ? model.getRevisions() : [],\n typeof model.getAttachments === 'function' ? model.getAttachments() : [],\n typeof model.getContributor === 'function' ? model.getContributor() : null,\n ]);\n\n return {\n ...toJSON(contribution),\n contributor: contributor ? serializeContentContributor(contributor) : null,\n revisions: revisions.map(serializeContentContributionRevision),\n attachments: attachments.map(serializeContentContributionAttachment),\n metadata:\n typeof model.getMetadata === 'function'\n ? model.getMetadata()\n : model.metadata || {},\n };\n}\n\nexport function serializeContentReviewProfileEvaluation(profile: unknown) {\n const data = toJSON(profile);\n return {\n ...data,\n requirements: Array.isArray(data.requirements) ? data.requirements : [],\n };\n}\n\nexport function serializeContentReviewPolicy(policy: unknown) {\n return {\n ...toJSON(policy),\n };\n}\n\nexport function serializeContentGovernanceProfile(profile: unknown) {\n const model = asModel(profile);\n const data = toJSON(profile);\n return {\n ...data,\n requirements: Array.isArray(data.requirements) ? data.requirements : [],\n metadata:\n typeof model.getMetadata === 'function'\n ? model.getMetadata()\n : data.metadata || {},\n };\n}\n\nexport function serializeContentGovernanceAssignment(assignment: unknown) {\n const model = asModel(assignment);\n const data = toJSON(assignment);\n return {\n ...data,\n metadata:\n typeof model.getMetadata === 'function'\n ? model.getMetadata()\n : data.metadata || {},\n };\n}\n\nexport function serializeContentGovernanceState(state: unknown) {\n const data = toJSON(state);\n return {\n ...data,\n reviewPolicies: Array.isArray(data.reviewPolicies)\n ? data.reviewPolicies.map(serializeContentReviewPolicy)\n : [],\n availableProfiles: Array.isArray(data.availableProfiles)\n ? data.availableProfiles.map(serializeContentGovernanceProfile)\n : [],\n reviewProfiles: Array.isArray(data.reviewProfiles)\n ? data.reviewProfiles.map(serializeContentReviewProfileEvaluation)\n : [],\n };\n}\n\n/**\n * Reference-drift edge keyed by target content id. Mirrors the shape returned\n * by `Content.getReferenceDrift()`.\n */\ninterface ReferenceDriftEdge {\n citedVersion: number | null;\n currentVersion: number | null;\n isDrifted: boolean;\n}\n\nexport async function serializeContent(content: unknown) {\n const model = asModel(content);\n const [references, assets] = await Promise.all([\n typeof model.getReferences === 'function' ? model.getReferences() : [],\n typeof model.getAssets === 'function' ? model.getAssets() : [],\n ]);\n\n // Only resolve drift when there are references to drift against — list\n // endpoints serializing many ref-less items shouldn't pay the version\n // lookup cost.\n const drift =\n references.length > 0 && typeof model.getReferenceDrift === 'function'\n ? await model.getReferenceDrift()\n : [];\n\n const driftByTargetId = new Map<string, ReferenceDriftEdge>(\n Array.isArray(drift)\n ? drift\n .map((entry) => asModel(entry))\n .filter(\n (entry): entry is SerializableModel & { targetId: string } =>\n typeof (entry as { targetId?: unknown }).targetId === 'string',\n )\n .map((entry) => {\n const edge = entry as {\n targetId: string;\n citedVersion?: unknown;\n currentVersion?: unknown;\n isDrifted?: unknown;\n };\n return [\n edge.targetId,\n {\n citedVersion: (edge.citedVersion as number | null) ?? null,\n currentVersion: (edge.currentVersion as number | null) ?? null,\n isDrifted: Boolean(edge.isDrifted),\n },\n ] satisfies [string, ReferenceDriftEdge];\n })\n : [],\n );\n\n return {\n ...toJSON(content),\n referenceIds: references\n .map((reference) => asModel(reference) as { id?: unknown })\n .map((reference) => reference.id)\n .filter(Boolean),\n references: references.map((reference) => {\n const base = toJSON(reference);\n const edge =\n typeof base.id === 'string' ? driftByTargetId.get(base.id) : null;\n return edge\n ? {\n ...base,\n citedVersion: edge.citedVersion,\n currentVersion: edge.currentVersion,\n isDrifted: edge.isDrifted,\n }\n : base;\n }),\n assetIds: assets\n .map((asset) => (asModel(asset) as { id?: unknown }).id)\n .filter(Boolean),\n assets: assets.map((asset) => toJSON(asset)),\n };\n}\n","/**\n * Thumbnail Generator for Content\n *\n * Generates thumbnail images for content using various strategies:\n * - headline-card: Draws article title on branded background\n * - static-map: Uses static maps API for location-based content\n * - ai-generate: Uses AI image generation for creative thumbnails\n */\n\nimport type { AIClient, AIClientOptions } from '@happyvertical/ai';\nimport { fetchStaticMap, type StaticMapProvider } from '@happyvertical/geo';\nimport {\n generateHeadlineCard,\n type HeadlineCardTemplate,\n} from '@happyvertical/images';\nimport type { DatabaseConfig } from '@happyvertical/smrt-core';\nimport type { Image } from '@happyvertical/smrt-images';\nimport { ImageCollection } from '@happyvertical/smrt-images';\nimport {\n type ResolvedPrompt,\n resolvePrompt,\n} from '@happyvertical/smrt-prompts';\nimport type { Content } from './content';\nimport {\n promptMessageOptions,\n smrtContentThumbnailAIGeneratePrompt,\n} from './content-prompts';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Available thumbnail generation strategies\n */\nexport type ThumbnailStrategy = 'headline-card' | 'static-map' | 'ai-generate';\n\n/**\n * Base options for all strategies\n */\ninterface BaseThumbnailOptions {\n /**\n * Generation strategy\n */\n strategy: ThumbnailStrategy;\n\n /**\n * Width in pixels\n * @default 1200\n */\n width?: number;\n\n /**\n * Height in pixels\n * @default 630\n */\n height?: number;\n}\n\n/**\n * Options for headline card strategy\n */\nexport interface HeadlineCardThumbnailOptions extends BaseThumbnailOptions {\n strategy: 'headline-card';\n\n /**\n * Primary brand color (hex)\n * @default '#3b82f6'\n */\n brandColor?: string;\n\n /**\n * Background color (hex)\n * @default '#ffffff'\n */\n backgroundColor?: string;\n\n /**\n * Optional subtitle/category text\n */\n subtitle?: string;\n\n /**\n * Optional logo URL\n */\n logoUrl?: string;\n\n /**\n * Template style\n * @default 'default'\n */\n template?: HeadlineCardTemplate;\n}\n\n/**\n * Options for static map strategy\n */\nexport interface StaticMapThumbnailOptions extends BaseThumbnailOptions {\n strategy: 'static-map';\n\n /**\n * Map provider\n * @default 'mapbox'\n */\n mapProvider?: StaticMapProvider;\n\n /**\n * Zoom level (1-20)\n * @default 14\n */\n zoom?: number;\n\n /**\n * Marker color\n * @default 'e74c3c'\n */\n markerColor?: string;\n\n /**\n * Mapbox style (if using mapbox provider)\n */\n mapboxStyle?: string;\n\n /**\n * Google map type (if using google provider)\n */\n googleMapType?: 'roadmap' | 'satellite' | 'terrain' | 'hybrid';\n}\n\n/**\n * Options for AI generation strategy\n */\nexport interface AIGenerateThumbnailOptions extends BaseThumbnailOptions {\n strategy: 'ai-generate';\n\n /**\n * AI provider configuration\n */\n ai?: AIClientOptions | AIClient;\n\n /**\n * Custom prompt for image generation\n * If not provided, generates based on content title/body\n */\n prompt?: string;\n\n /**\n * Style hint for image generation\n * @default 'photorealistic'\n */\n style?: 'photorealistic' | 'illustration' | 'abstract' | 'minimal';\n}\n\n/**\n * Union type for all thumbnail options\n */\nexport type ThumbnailOptions =\n | HeadlineCardThumbnailOptions\n | StaticMapThumbnailOptions\n | AIGenerateThumbnailOptions;\n\n// ============================================================================\n// Generator Class\n// ============================================================================\n\n/**\n * Options for ThumbnailGenerator\n */\nexport interface ThumbnailGeneratorOptions {\n /**\n * Database configuration for storing generated images\n */\n db?: DatabaseConfig;\n\n /**\n * Alias for `db` — mirrors the `SmrtClassOptions.persistence` alias so\n * callers can pass the same options shape they use for SmrtObject/Collection.\n *\n * @deprecated Prefer `db`. Retained for parity with `SmrtClassOptions`.\n */\n persistence?: DatabaseConfig;\n\n /**\n * AI client configuration for AI-generated thumbnails\n */\n ai?: AIClientOptions | AIClient;\n}\n\ninterface ImageGenerationClient {\n generateImage(\n prompt: string,\n options?: Record<string, unknown>,\n ): Promise<{\n images?: Array<{ data?: Buffer | string }>;\n }>;\n}\n\nfunction isImageGenerationClient(\n value: AIClientOptions | AIClient,\n): value is AIClient & ImageGenerationClient {\n return (\n !!value &&\n typeof value === 'object' &&\n typeof (value as Record<string, unknown>).generateImage === 'function'\n );\n}\n\nfunction isAIClientOptions(\n value: AIClientOptions | AIClient,\n): value is AIClientOptions {\n return (\n !!value && typeof value === 'object' && !isImageGenerationClient(value)\n );\n}\n\n/**\n * ThumbnailGenerator creates thumbnails for content using various strategies\n */\nexport class ThumbnailGenerator {\n constructor(\n private content: Content,\n private options: ThumbnailGeneratorOptions = {},\n ) {\n // Normalize the `persistence` alias to `db` once so every downstream call\n // (prompt resolution, ImageCollection.create, save sites) sees the same\n // database regardless of which option name the caller used. Without this,\n // a caller passing `persistence: ...` would have prompt resolution honor\n // the alias while image saving silently used `undefined`.\n if (!this.options.db && this.options.persistence) {\n this.options.db = this.options.persistence;\n }\n }\n\n /**\n * Generate a thumbnail using the specified strategy\n */\n async generate(options: ThumbnailOptions): Promise<Image> {\n switch (options.strategy) {\n case 'headline-card':\n return this.generateHeadlineCard(options);\n case 'static-map':\n return this.generateStaticMap(options);\n case 'ai-generate':\n return this.generateWithAI(options);\n default:\n throw new Error(\n // `options` is narrowed to `never` here (exhaustive switch); read the\n // runtime discriminant through a minimal structural view.\n `Unknown thumbnail strategy: ${(options as { strategy: string }).strategy}`,\n );\n }\n }\n\n /**\n * Generate a headline card thumbnail\n */\n private async generateHeadlineCard(\n options: HeadlineCardThumbnailOptions,\n ): Promise<Image> {\n const title = this.content.title || this.content.name || 'Untitled';\n\n const result = await generateHeadlineCard(title, {\n width: options.width ?? 1200,\n height: options.height ?? 630,\n brandColor: options.brandColor,\n backgroundColor: options.backgroundColor,\n subtitle: options.subtitle ?? this.content.category ?? undefined,\n logoUrl: options.logoUrl,\n template: options.template,\n });\n\n return this.createImageFromBuffer(result.buffer, {\n width: result.width,\n height: result.height,\n mimeType: result.mimeType,\n name: `${this.content.id}-headline.png`,\n });\n }\n\n /**\n * Generate a static map thumbnail\n */\n private async generateStaticMap(\n options: StaticMapThumbnailOptions,\n ): Promise<Image> {\n // Coordinates live in the loose `metadata` bag (typed `unknown` values);\n // read them at a documented `string | number` boundary for arithmetic.\n const coordinateMetadata = this.content.metadata as Record<\n string,\n string | number | null | undefined\n >;\n const rawLatitude =\n coordinateMetadata?.latitude ?? coordinateMetadata?.lat;\n const rawLongitude =\n coordinateMetadata?.longitude ??\n coordinateMetadata?.lng ??\n coordinateMetadata?.lon;\n\n if (rawLatitude == null || rawLongitude == null) {\n throw new Error(\n 'Content metadata must contain latitude and longitude for static-map strategy',\n );\n }\n\n // Parse and validate coordinates\n // Use unary + for strict parsing (rejects \"45invalid\" unlike parseFloat)\n const latitude =\n typeof rawLatitude === 'string' ? +rawLatitude : rawLatitude;\n const longitude =\n typeof rawLongitude === 'string' ? +rawLongitude : rawLongitude;\n\n if (!Number.isFinite(latitude) || latitude < -90 || latitude > 90) {\n throw new Error(\n `Invalid latitude value \"${rawLatitude}\" in content metadata; expected a number between -90 and 90.`,\n );\n }\n\n if (!Number.isFinite(longitude) || longitude < -180 || longitude > 180) {\n throw new Error(\n `Invalid longitude value \"${rawLongitude}\" in content metadata; expected a number between -180 and 180.`,\n );\n }\n\n type FetchStaticMapOptions = NonNullable<\n Parameters<typeof fetchStaticMap>[2]\n >;\n const mapboxStyle = options.mapboxStyle as\n | FetchStaticMapOptions['mapboxStyle']\n | undefined;\n\n const result = await fetchStaticMap(latitude, longitude, {\n provider: options.mapProvider ?? 'mapbox',\n width: options.width ?? 1200,\n height: options.height ?? 630,\n zoom: options.zoom ?? 14,\n markerColor: options.markerColor,\n mapboxStyle,\n googleMapType: options.googleMapType,\n });\n\n return this.createImageFromBuffer(result.buffer, {\n width: result.width,\n height: result.height,\n mimeType: result.mimeType,\n name: `${this.content.id}-map.png`,\n });\n }\n\n /**\n * Generate a thumbnail using AI image generation\n */\n private async generateWithAI(\n options: AIGenerateThumbnailOptions,\n ): Promise<Image> {\n // Dynamic import to avoid requiring AI package when not using this strategy\n const { getAI } = await import('@happyvertical/ai');\n\n const aiInput = options.ai ?? this.options.ai;\n if (!aiInput) {\n throw new Error(\n 'AI configuration required for ai-generate strategy. Provide via options.ai or constructor options.',\n );\n }\n\n const ai = isImageGenerationClient(aiInput)\n ? aiInput\n : isAIClientOptions(aiInput)\n ? await getAI(aiInput)\n : (() => {\n throw new Error(\n 'AI client does not support image generation for ai-generate thumbnails.',\n );\n })();\n\n // Generate prompt if not provided. When the caller supplies a literal\n // prompt we skip prompt resolution entirely (no tenant override path).\n // When we resolve from the registry we also forward the resolved AI\n // options (model, params) so `editable: { model, params }` actually\n // takes effect for thumbnail generation.\n const width = options.width ?? 1200;\n const height = options.height ?? 630;\n let prompt: string;\n let aiOverrideOptions: Record<string, unknown> = {};\n if (options.prompt) {\n prompt = options.prompt;\n } else {\n const built = await this.buildAIPrompt(options.style ?? 'photorealistic');\n prompt = built.text;\n aiOverrideOptions = promptMessageOptions(built.ai);\n }\n\n const result = await ai.generateImage(prompt, {\n ...aiOverrideOptions,\n size: `${width}x${height}`,\n outputFormat: 'buffer',\n });\n\n if (!result.images || result.images.length === 0) {\n throw new Error('AI image generation returned no results');\n }\n\n // Handle buffer or base64 responses\n let buffer: Buffer;\n const imageData = result.images[0].data;\n if (Buffer.isBuffer(imageData)) {\n buffer = imageData;\n } else if (typeof imageData === 'string') {\n // Could be base64 or URL - try base64 first\n if (imageData.startsWith('http')) {\n const response = await fetch(imageData);\n if (!response.ok) {\n throw new Error(\n `AI image generation URL fetch failed: ${response.status} ${response.statusText}`,\n );\n }\n buffer = Buffer.from(await response.arrayBuffer());\n } else {\n buffer = Buffer.from(imageData, 'base64');\n }\n } else {\n throw new Error('AI image generation returned unexpected format');\n }\n\n return this.createImageFromBuffer(buffer, {\n width: options.width ?? 1200,\n height: options.height ?? 630,\n mimeType: 'image/png',\n name: `${this.content.id}-ai.png`,\n });\n }\n\n /**\n * Build a prompt for AI image generation based on content.\n *\n * Resolves via `@happyvertical/smrt-prompts` so tenants can override the\n * template/profile/model/params at runtime. Only non-PII content fields\n * (title, description) and the caller-supplied style hint are passed.\n * Internal IDs and the freeform `metadata` blob are intentionally excluded.\n *\n * Returns the full ResolvedPrompt (text + ai config) so the caller can\n * forward `model`/`params` overrides to `ai.generateImage()`. Returning\n * only the text would silently drop the editable model/params overrides.\n */\n private async buildAIPrompt(style: string): Promise<ResolvedPrompt> {\n const title = this.content.title || 'Untitled';\n const description = this.content.description || '';\n\n const stylePrompts: Record<string, string> = {\n photorealistic:\n 'photorealistic, high quality, professional photography, 8k resolution',\n illustration:\n 'digital illustration, clean vector art, modern design, vibrant colors',\n abstract:\n 'abstract art, geometric shapes, modern minimalist, artistic interpretation',\n minimal:\n 'minimalist design, simple shapes, clean composition, subtle colors',\n };\n\n const styleHint = stylePrompts[style] || stylePrompts.photorealistic;\n\n return resolvePrompt(smrtContentThumbnailAIGeneratePrompt.key, {\n db: this.options.db,\n tenantId: this.content.tenantId,\n variables: {\n style,\n title,\n styleHint,\n descriptionClause: description\n ? `The article is about: ${description}. `\n : '',\n },\n });\n }\n\n /**\n * Create an Image object from a buffer\n */\n private async createImageFromBuffer(\n buffer: Buffer,\n metadata: {\n width: number;\n height: number;\n mimeType: string;\n name: string;\n },\n ): Promise<Image> {\n const images = await ImageCollection.create({\n db: this.options.db,\n });\n\n // Create the image record. `SmrtCollection.create()` already persists\n // (upsert) the row, so a follow-up `image.save()` was redundant (#1387).\n const image = await images.create({\n name: metadata.name,\n mimeType: metadata.mimeType,\n width: metadata.width,\n height: metadata.height,\n sourceUri: `data:${metadata.mimeType};base64,${buffer.toString('base64')}`,\n });\n\n return image;\n }\n}\n","import { type Asset, AssetCollection } from '@happyvertical/smrt-assets';\nimport type { SmrtObjectOptions } from '@happyvertical/smrt-core';\nimport {\n crossPackageRef,\n field,\n SmrtObject,\n smrt,\n ValidationError,\n} from '@happyvertical/smrt-core';\nimport type {\n Fact,\n FactClaimSupportAssessment,\n FactClaimSupportStatus,\n FactContent,\n FactContentRelationship,\n FactEvidence,\n FactEvidenceStatus,\n FactExtractionCandidate,\n FactSource,\n} from '@happyvertical/smrt-facts';\nimport type { Image } from '@happyvertical/smrt-images';\nimport { ImageCollection } from '@happyvertical/smrt-images';\nimport { resolvePrompt } from '@happyvertical/smrt-prompts';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport type { AssetAssociable, MetadataAccessor } from './asset-associable';\nimport { isPlainMetadataRecord } from './asset-associable';\nimport type { ContentBodyFormat } from './body-format';\nimport { isContentBodyFormat } from './body-format';\nimport { ContentAssetCollection } from './content-assets';\nimport {\n buildContentGovernanceAssignmentKey,\n buildContentReviewPrompt,\n type ContentGovernanceState,\n type ContentReviewFinding,\n type ContentReviewProfileEvaluation,\n type CreateContentVersionOptions,\n getAcceptedContentReviewStatuses,\n getContentReviewKind,\n getContentReviewPolicy,\n getContentReviewProfileKeys,\n getContentReviewRequirements,\n type IssueContentCorrectionOptions,\n parseContentReviewResponse,\n type ResolvedContentGovernance,\n type RunContentReviewOptions,\n resolveConfiguredContentGovernance,\n resolveEffectiveContentGovernance,\n} from './content-governance';\nimport {\n promptMessageOptions,\n smrtContentApplyCorrectionPrompt,\n smrtContentReviewPrompt,\n} from './content-prompts';\nimport { ContentReferences } from './content-references';\nimport type { ContentReview } from './content-review';\nimport { normalizeContentTransparency } from './content-transparency';\nimport { isMissingTableError } from './database-utils';\nimport {\n serializeContent,\n serializeContentCorrection,\n serializeContentReview,\n serializeContentVersion,\n serializeFact,\n serializeFactLink,\n} from './serialization';\nimport type { ThumbnailOptions } from './thumbnail-generator';\nimport { ThumbnailGenerator } from './thumbnail-generator';\n\nconst USED_FACT_RELATIONSHIPS = new Set<FactContentRelationship>([\n 'supports',\n 'referenced_in',\n 'contradicts',\n]);\nconst FACT_AUDIT_GENERATED_BY = 'content.factAudit';\nconst FACT_AUDIT_DOMAIN = 'content-audit';\n\ntype FactAuditSourceMaterial = {\n sourceKind: string;\n sourceId: string;\n sourceUrl: string;\n sourceTitle: string;\n locator: string;\n text: string;\n};\n\ntype FactAuditSourceSelector = {\n sourceKind: string;\n sourceId: string;\n};\n\ntype FactAuditResourceRepairOptions = {\n sources?: FactAuditSourceSelector[];\n maxFactsPerSource?: number;\n context?: string;\n};\n\ntype FactAuditClaimRecheckOptions = {\n claimFactIds?: string[];\n sourceIds?: string[];\n sources?: FactAuditSourceSelector[];\n maxCandidateEvidence?: number;\n};\n\ntype FactEvidenceStatusUpdateOptions = {\n evidenceIds?: string[];\n status?: FactEvidenceStatus;\n reason?: string;\n};\n\ntype FactAuditClaim = {\n id: string | null;\n fact: Record<string, unknown>;\n supportStatus: FactClaimSupportStatus;\n claimQuote: string | null;\n rationale: string | null;\n confidence: number | null;\n relationship: string | null;\n linkMetadata: Record<string, unknown>;\n evidence: Record<string, unknown>[];\n matchedFacts: Array<{\n fact: Record<string, unknown>;\n evidence: Record<string, unknown>[];\n }>;\n};\n\ntype FactAuditResourceClaim = {\n id: string | null;\n fact: Record<string, unknown>;\n sourceKind: string | null;\n sourceId: string | null;\n sourceUrl: string | null;\n sourceTitle: string | null;\n locator: string | null;\n quote: string | null;\n status: FactEvidenceStatus;\n confidence: number | null;\n evidence: Record<string, unknown>[];\n};\n\n/**\n * Minimal structural view of a metadata-bearing SMRT record (fact link,\n * fact, evidence, source, version, review, correction). The fact-audit and\n * transparency code paths interact with these entities loosely via their\n * accessor methods rather than importing the concrete cross-package classes\n * (which would create circular dependencies). `getMetadata`/`setMetadata`\n * are optional because some paths receive plain serialized records.\n */\ninterface MetadataBearer {\n getMetadata?: () => Record<string, unknown>;\n setMetadata?: (metadata: Record<string, unknown>) => void;\n updateMetadata?: (patch: Record<string, unknown>) => unknown;\n metadata?: unknown;\n}\n\n/**\n * Structural view of a content↔fact link as consumed by the fact-audit\n * pipeline. Backed by `FactContent` from `@happyvertical/smrt-facts`.\n */\ninterface FactAuditLinkLike extends MetadataBearer {\n factId?: string | null;\n relationship?: string | null;\n save?: () => Promise<unknown>;\n delete?: () => Promise<unknown>;\n}\n\n/**\n * Structural view of a fact-evidence record as consumed by the fact-audit\n * pipeline. Backed by `FactEvidence` from `@happyvertical/smrt-facts`.\n */\ninterface FactAuditEvidenceLike extends MetadataBearer {\n id?: string | null;\n factId?: string | null;\n status?: string | null;\n sourceKind?: string | null;\n sourceId?: string | null;\n sourceUrl?: string | null;\n sourceTitle?: string | null;\n locator?: string | null;\n quote?: string | null;\n confidence?: number | null;\n evidenceKey?: string | null;\n tenantId?: string | null;\n delete?: () => Promise<unknown>;\n}\n\n/**\n * Structural view of a fact-source record as consumed by the fact-audit\n * pipeline. Backed by `FactSource` from `@happyvertical/smrt-facts`.\n */\ninterface FactAuditSourceLike extends MetadataBearer {\n id?: string | null;\n sourceType?: string | null;\n delete?: () => Promise<unknown>;\n}\n\n/**\n * Loosely-read extra fields the fact-audit source scanner probes on an\n * {@link Asset}. These are not declared `Asset` fields (assets vary by\n * provider); they are read defensively and normalized via `normalizeAuditText`.\n */\ninterface FactAuditAssetExtraFields {\n text?: unknown;\n body?: unknown;\n title?: unknown;\n filename?: unknown;\n url?: unknown;\n sourceUrl?: unknown;\n fileKey?: unknown;\n}\n\n/**\n * Structural view of a support candidate carried through claim assessment.\n * The `evidence` array holds the serialized evidence summaries built in\n * {@link Content.getCurrentFactAuditSupportCandidates}.\n */\ninterface FactAuditSupportCandidate {\n id: string;\n statement: string;\n evidence: Array<{ id?: string | null; [key: string]: unknown }>;\n}\n\n/**\n * Loose view of a serialized record produced by the `serialize*` helpers\n * (which return index-signature records that erase named keys at the type\n * level). Adds back the few keys the transparency snapshot reads while keeping\n * the rest as `unknown`.\n */\ninterface SerializedRecord {\n id?: string | null;\n status?: unknown;\n usedInArticle?: boolean;\n metadata?: unknown;\n [key: string]: unknown;\n}\n\n/**\n * Transient, non-persisted fields synchronized into junction links during\n * `save()`. They are attached dynamically from constructor options rather\n * than declared as ORM-managed fields, so callers narrow `this` to this\n * shape instead of reaching in untyped.\n */\ninterface ContentTransientLinkIds {\n referenceIds?: string[];\n assetIds?: string[];\n}\n\ntype FactAuditState = {\n counts: Record<FactClaimSupportStatus | 'total', number>;\n claims: FactAuditClaim[];\n resourceClaims: FactAuditResourceClaim[];\n warnings: string[];\n generatedBy: string;\n latestAuditRunId: string | null;\n};\n\nfunction normalizeFingerprintValue(value: unknown): unknown {\n if (value instanceof Date) {\n return value.toISOString();\n }\n\n if (Array.isArray(value)) {\n return value.map((entry) => normalizeFingerprintValue(entry));\n }\n\n if (value && typeof value === 'object') {\n return Object.fromEntries(\n Object.entries(value as Record<string, unknown>)\n .sort(([left], [right]) => left.localeCompare(right))\n .map(([key, entryValue]) => [\n key,\n normalizeFingerprintValue(entryValue),\n ]),\n );\n }\n\n return value ?? null;\n}\n\nfunction hashFingerprint(input: string): string {\n let hash = 5381;\n\n for (let index = 0; index < input.length; index += 1) {\n hash = (hash * 33) ^ input.charCodeAt(index);\n }\n\n return `fp-${(hash >>> 0).toString(16).padStart(8, '0')}`;\n}\n\nfunction createFingerprint(value: unknown): string {\n return hashFingerprint(JSON.stringify(normalizeFingerprintValue(value)));\n}\n\nfunction normalizeAuditText(value: unknown): string {\n return String(value ?? '')\n .trim()\n .replace(/\\s+/g, ' ');\n}\n\n/**\n * Extract a human-readable message from an unknown caught value. Mirrors the\n * previous `error.message || error` template interpolation without relying on\n * an `any`-typed catch binding.\n */\nfunction errorMessage(error: unknown): string {\n if (error instanceof Error) {\n return error.message;\n }\n if (\n error &&\n typeof error === 'object' &&\n 'message' in error &&\n typeof (error as { message?: unknown }).message === 'string'\n ) {\n return (error as { message: string }).message;\n }\n return String(error);\n}\n\nfunction createFactAuditRunId(contentId: string): string {\n return `fact-audit-${hashFingerprint(\n `${contentId}:${new Date().toISOString()}:${Math.random()}`,\n )}`;\n}\n\nfunction parseAuditMetadata(value: unknown): Record<string, unknown> {\n if (!value) return {};\n if (typeof value === 'object') return value as Record<string, unknown>;\n try {\n return JSON.parse(String(value)) as Record<string, unknown>;\n } catch {\n return {};\n }\n}\n\nfunction getLinkMetadata(link: MetadataBearer): Record<string, unknown> {\n return typeof link?.getMetadata === 'function' ? link.getMetadata() : {};\n}\n\nfunction getFactMetadata(fact: MetadataBearer): Record<string, unknown> {\n return typeof fact?.getMetadata === 'function'\n ? fact.getMetadata()\n : parseAuditMetadata(fact?.metadata);\n}\n\nfunction getGeneratedFactAuditMetadata(\n link: MetadataBearer,\n): Record<string, unknown> | null {\n const metadata = getLinkMetadata(link);\n if (metadata.generatedBy === FACT_AUDIT_GENERATED_BY) {\n return metadata;\n }\n\n const nested = metadata.factAudit;\n if (\n nested &&\n typeof nested === 'object' &&\n (nested as Record<string, unknown>).generatedBy === FACT_AUDIT_GENERATED_BY\n ) {\n return nested as Record<string, unknown>;\n }\n\n return null;\n}\n\nfunction getEvidenceMetadata(\n evidence: MetadataBearer,\n): Record<string, unknown> {\n return typeof evidence?.getMetadata === 'function'\n ? evidence.getMetadata()\n : parseAuditMetadata(evidence?.metadata);\n}\n\nfunction isGeneratedFactAuditEvidence(\n evidence: MetadataBearer,\n contentId: string,\n): boolean {\n const metadata = getEvidenceMetadata(evidence);\n return (\n metadata.generatedBy === FACT_AUDIT_GENERATED_BY &&\n metadata.contentId === contentId\n );\n}\n\nfunction isGeneratedArticleClaimFact(\n fact: MetadataBearer,\n contentId: string,\n): boolean {\n const metadata = getFactMetadata(fact);\n if (metadata.generatedBy !== FACT_AUDIT_GENERATED_BY) {\n return false;\n }\n\n const role = metadata.auditFactRole || metadata.factAuditRole;\n const isArticleClaim =\n role === 'article-claim' || metadata.claimOnly === true;\n\n return isArticleClaim && metadata.contentId === contentId;\n}\n\nfunction normalizeFactEvidenceStatus(\n value: unknown,\n): FactEvidenceStatus | null {\n const allowed: FactEvidenceStatus[] = [\n 'supports',\n 'contradicts',\n 'unclear',\n 'irrelevant',\n 'invalid',\n ];\n\n return allowed.includes(value as FactEvidenceStatus)\n ? (value as FactEvidenceStatus)\n : null;\n}\n\nfunction sourceMatchesSelector(\n source: FactAuditSourceMaterial,\n selector: FactAuditSourceSelector,\n): boolean {\n return (\n source.sourceKind === selector.sourceKind &&\n source.sourceId === selector.sourceId\n );\n}\n\nfunction filterAuditSources(\n sources: FactAuditSourceMaterial[],\n selectors: FactAuditSourceSelector[] | undefined,\n): FactAuditSourceMaterial[] {\n if (!selectors || selectors.length === 0) {\n return sources;\n }\n\n return sources.filter((source) =>\n selectors.some((selector) => sourceMatchesSelector(source, selector)),\n );\n}\n\nfunction getContentText(content: Content): string {\n return [content.title, content.description, content.body]\n .map(normalizeAuditText)\n .filter(Boolean)\n .join('\\n\\n');\n}\n\nfunction readNestedString(\n source: Record<string, unknown>,\n path: string[],\n): string | null {\n let current: unknown = source;\n for (const key of path) {\n if (!current || typeof current !== 'object') {\n return null;\n }\n current = (current as Record<string, unknown>)[key];\n }\n return typeof current === 'string' && current ? current : null;\n}\n\n/**\n * Coerce an unknown value into a plain record. Objects pass through; JSON\n * strings are parsed (falling back to `{}` on failure); anything else yields\n * an empty record. Used to read loosely-typed `metadata` fields that may be\n * stored either as parsed objects or JSON strings.\n */\nfunction asRecord(value: unknown): Record<string, unknown> {\n if (value && typeof value === 'object' && !Array.isArray(value)) {\n return value as Record<string, unknown>;\n }\n if (typeof value === 'string') {\n try {\n const parsed = JSON.parse(value);\n return parsed && typeof parsed === 'object' && !Array.isArray(parsed)\n ? (parsed as Record<string, unknown>)\n : {};\n } catch {\n return {};\n }\n }\n return {};\n}\n\n/**\n * Walk a nested record path, returning the record at the end of the path or\n * an empty record if any segment is missing/non-record-shaped.\n */\nfunction readNestedRecord(\n source: Record<string, unknown>,\n path: string[],\n): Record<string, unknown> {\n let current: unknown = source;\n for (const key of path) {\n if (!current || typeof current !== 'object') {\n return {};\n }\n current = (current as Record<string, unknown>)[key];\n }\n return asRecord(current);\n}\n\nfunction getPublicPrompt(metadata: Record<string, unknown>): string | null {\n return (\n readNestedString(metadata, ['transparency', 'generation', 'publicPrompt']) ||\n readNestedString(metadata, ['generation', 'publicPrompt']) ||\n readNestedString(metadata, ['publicPrompt']) ||\n null\n );\n}\n\n/**\n * Options for Content initialization\n */\nexport interface ContentOptions extends SmrtObjectOptions {\n /**\n * Content type classification\n */\n type?: string | null;\n\n /**\n * Content variant for namespaced classification within types\n * Format: generator:domain:specific-type\n * Example: \"praeco:meeting:upcoming\"\n */\n variant?: string | null;\n\n /**\n * Reference to file storage key\n */\n fileKey?: string | null;\n\n /**\n * Author of the content\n */\n author?: string | null;\n\n /**\n * Content title\n */\n title?: string | null;\n\n /**\n * Short description or summary\n */\n description?: string | null;\n\n /**\n * Main content body text\n */\n body?: string | null;\n\n /**\n * Stored body format.\n */\n bodyFormat?: ContentBodyFormat | null;\n\n /**\n * Date when content was published\n */\n publish_date?: Date | null;\n\n /**\n * URL source of the content\n */\n url?: string | null;\n\n /**\n * Original source identifier\n */\n source?: string | null;\n\n /**\n * Publication status\n */\n status?: 'published' | 'draft' | 'review' | 'archived' | 'deleted' | null;\n\n /**\n * Content state flag\n */\n state?: 'deprecated' | 'active' | 'highlighted' | null;\n\n /**\n * Original URL of the content\n */\n original_url?: string | null;\n\n /**\n * Content language\n */\n language?: string | null;\n\n /**\n * Content tags\n */\n tags?: string[];\n\n /**\n * Hierarchical category path for URL routing\n * Format: 'parent/child' (e.g., 'politics/local')\n * Each content belongs to exactly ONE category\n */\n category?: string | null;\n\n /**\n * Additional metadata\n */\n metadata?: Record<string, unknown>;\n\n /**\n * ID of the thumbnail asset for this content\n */\n thumbnailAssetId?: string | null;\n\n /**\n * Transient reference IDs used by editors and API payloads.\n * These are synchronized into ContentReference links during save.\n */\n referenceIds?: string[];\n\n /**\n * Transient asset IDs used by editors and API payloads.\n */\n assetIds?: string[];\n\n /**\n * Tenant ID for multi-tenant isolation\n */\n tenantId?: string | null;\n}\n\n/**\n * Structured content object with metadata and body text\n *\n * Content represents any text-based content with metadata such as\n * title, author, description, and publishing information. It supports\n * referencing related content objects.\n */\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableStrategy: 'sti',\n api: {\n include: [\n 'list',\n 'get',\n 'create',\n 'update',\n 'delete',\n 'getFactsState',\n 'syncFactsState',\n 'getFactAuditStateAction',\n 'repairFactAuditAction',\n 'repairFactEvidenceAction',\n 'recheckFactClaimsAction',\n 'updateFactEvidenceStatusAction',\n 'getGovernanceStateAction',\n 'listReviews',\n 'runReviewAction',\n 'listReviewProfilesAction',\n 'evaluateReviewProfileAction',\n 'getPublishedTransparencyAction',\n 'previewTransparencyAction',\n 'listCorrections',\n 'issueCorrectionAction',\n 'listVersions',\n 'mutateVersionAction',\n ],\n routes: {\n getFactsState: { method: 'GET', path: 'facts' },\n syncFactsState: { method: 'PUT', path: 'facts' },\n getFactAuditStateAction: { method: 'GET', path: 'fact-audit' },\n repairFactAuditAction: { method: 'POST', path: 'fact-audit/repair' },\n repairFactEvidenceAction: {\n method: 'POST',\n path: 'fact-audit/evidence/repair',\n },\n recheckFactClaimsAction: {\n method: 'POST',\n path: 'fact-audit/claims/recheck',\n },\n updateFactEvidenceStatusAction: {\n method: 'PUT',\n path: 'fact-audit/evidence/status',\n },\n getGovernanceStateAction: { method: 'GET', path: 'governance' },\n listReviews: { method: 'GET', path: 'reviews' },\n runReviewAction: { method: 'POST', path: 'reviews' },\n listReviewProfilesAction: { method: 'GET', path: 'review-profiles' },\n evaluateReviewProfileAction: {\n method: 'GET',\n path: 'review-profiles/[profileKey]',\n },\n getPublishedTransparencyAction: {\n method: 'GET',\n path: 'transparency',\n },\n previewTransparencyAction: {\n method: 'GET',\n path: 'transparency/preview',\n },\n listCorrections: { method: 'GET', path: 'corrections' },\n issueCorrectionAction: { method: 'POST', path: 'corrections' },\n listVersions: { method: 'GET', path: 'versions' },\n mutateVersionAction: { method: 'POST', path: 'versions' },\n },\n serializers: {\n item: {\n importPath: '$lib/server/content-api-serializers',\n exportName: 'serializeContent',\n },\n },\n },\n mcp: {\n include: ['list', 'get', 'create', 'update'], // AI tools for content management\n },\n cli: true, // Enable CLI commands for content management\n})\nexport class Content\n extends SmrtObject\n implements AssetAssociable, MetadataAccessor<Record<string, unknown>>\n{\n /**\n * Tenant ID for multi-tenant isolation\n * Nullable to support both tenant-scoped and global content\n */\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n /**\n * Array of referenced content objects\n */\n protected references: Content[] = [];\n\n /**\n * Content type classification\n */\n public type: string | null = null;\n\n /**\n * Content variant for namespaced classification within types\n * Format: generator:domain:specific-type\n * Example: \"praeco:meeting:upcoming\"\n */\n public variant: string | null = null;\n\n /**\n * Reference to file storage key\n */\n public fileKey: string | null = null;\n\n /**\n * Author of the content\n */\n public author: string | null = null;\n\n /**\n * Human-readable name for SMRT framework compatibility\n */\n @field({ required: true })\n public name: string = '';\n\n /**\n * Content title\n */\n public title = '';\n\n /**\n * Short description or summary\n */\n public description: string | null = null;\n\n /**\n * Main content body text\n */\n public body = '';\n\n /**\n * Format used to persist the body field.\n */\n public bodyFormat: ContentBodyFormat | null = null;\n\n /**\n * Date when content was published\n */\n public publish_date: Date | null = null;\n\n /**\n * URL source of the content\n */\n public url: string | null = null;\n\n /**\n * Original source identifier\n */\n public source: string | null = null;\n\n /**\n * Original URL of the content\n */\n public original_url: string | null = null;\n\n /**\n * Content language\n */\n public language: string | null = null;\n\n /**\n * Content tags\n */\n public tags: string[] = [];\n\n /**\n * Hierarchical category path for URL routing\n * Format: 'parent/child' (e.g., 'politics/local')\n * Each content belongs to exactly ONE category\n */\n public category: string | null = null;\n\n /**\n * Publication status\n */\n public status: 'published' | 'draft' | 'review' | 'archived' | 'deleted' =\n 'draft';\n\n /**\n * Content state flag\n */\n public state: 'deprecated' | 'active' | 'highlighted' = 'active';\n\n /**\n * Additional JSON metadata for flexible schema extension\n */\n public metadata: Record<string, unknown> = {};\n\n /**\n * ID of the thumbnail asset for this content\n */\n @crossPackageRef('@happyvertical/smrt-assets:Asset')\n public thumbnailAssetId: string | null = null;\n\n /**\n * Creates a new Content instance\n */\n constructor(options: ContentOptions = {}) {\n super(options);\n this.type = options.type || null;\n this.variant = options.variant || null;\n this.fileKey = options.fileKey || null;\n this.author = options.author || null;\n if (options.name) this.name = options.name;\n this.title = options.title || '';\n this.description = options.description || null;\n this.body = options.body || '';\n this.bodyFormat = isContentBodyFormat(options.bodyFormat)\n ? options.bodyFormat\n : null;\n this.publish_date = options.publish_date || null;\n this.source = options.source || null;\n this.original_url = options.original_url || null;\n this.language = options.language || null;\n this.status = options.status || 'draft';\n this.tags = options.tags || [];\n this.category = options.category || null;\n this.state = options.state || 'active';\n this.metadata = options.metadata || {};\n this.thumbnailAssetId = options.thumbnailAssetId ?? null;\n const transient = this as Content & ContentTransientLinkIds;\n if (Array.isArray(options.referenceIds)) {\n transient.referenceIds = [...options.referenceIds];\n }\n if (Array.isArray(options.assetIds)) {\n transient.assetIds = [...options.assetIds];\n }\n }\n\n /**\n * Initializes this content object\n *\n * @returns Promise that resolves to this instance\n */\n async initialize(): Promise<this> {\n await super.initialize();\n return this;\n }\n\n protected override async validateBeforeSave(): Promise<void> {\n if (!this.name && this.title) {\n this.name = this.title;\n }\n\n if (!this.title && this.name) {\n this.title = this.name;\n }\n\n await super.validateBeforeSave();\n\n if (this.status !== 'published') {\n return;\n }\n\n const governance = await this.resolvePublicationGovernance();\n const profileKey = governance?.publicationProfileKey;\n\n if (\n !governance?.isGoverned ||\n !governance.enforcePublishReadiness ||\n !profileKey\n ) {\n return;\n }\n\n const evaluation = await this.evaluateReviewProfile(profileKey);\n const blockingRequirements = evaluation.requirements.filter(\n (requirement) => requirement.blocking && !requirement.satisfied,\n );\n\n if (blockingRequirements.length === 0) {\n return;\n }\n\n const details = blockingRequirements.map((requirement) => {\n if (requirement.missing) {\n return `${requirement.label} has not been run yet`;\n }\n\n if (requirement.stale) {\n return `${requirement.label} is stale and must be rerun`;\n }\n\n if (requirement.latestStatus) {\n return `${requirement.label} returned ${requirement.latestStatus}`;\n }\n\n return `${requirement.label} is not satisfied`;\n });\n\n throw new ValidationError(\n `Cannot publish content until the \"${profileKey}\" review profile is satisfied. ${details.join('; ')}`,\n 'VALIDATION_PUBLISH_READINESS',\n {\n profileKey,\n blockingRequirements: blockingRequirements.map((requirement) => ({\n policyKey: requirement.policyKey,\n label: requirement.label,\n missing: requirement.missing,\n stale: requirement.stale,\n latestStatus: requirement.latestStatus,\n })),\n },\n );\n }\n\n override async save() {\n const shouldConsiderPublicationSnapshot = this.status === 'published';\n\n let governance: ResolvedContentGovernance | null = null;\n let previous: Content | null = null;\n let previousPublicationFingerprint: string | null = null;\n\n if (shouldConsiderPublicationSnapshot) {\n governance = await this.resolvePublicationGovernance();\n\n if (governance?.isGoverned && governance.transparencyEnabled) {\n previous = await this.getPersistedContent();\n previousPublicationFingerprint =\n await this.getLatestPublicationSnapshotFingerprint();\n }\n }\n\n await super.save();\n await this.syncPendingReferenceIds();\n await this.syncPendingAssetIds();\n\n if (\n !shouldConsiderPublicationSnapshot ||\n !governance?.isGoverned ||\n !governance.transparencyEnabled\n ) {\n return this;\n }\n\n const nextPublicationFingerprint =\n await this.buildPublicationSnapshotFingerprint(governance);\n\n if (\n nextPublicationFingerprint &&\n nextPublicationFingerprint !== previousPublicationFingerprint\n ) {\n await this.createVersion({\n kind: 'publication',\n summary:\n previous?.status === 'published'\n ? 'Published content updated.'\n : 'Content published.',\n metadata: {\n publicationSnapshotFingerprint: nextPublicationFingerprint,\n publicationProfileKey: governance.publicationProfileKey,\n transparency: await this.buildTransparencySnapshot({\n snapshotKind: 'published',\n governance,\n }),\n },\n });\n }\n\n return this;\n }\n\n private async getReferenceCollection() {\n return ContentReferences.create({ db: this.db });\n }\n\n private async getFactCollection() {\n const { FactCollection } = await import('@happyvertical/smrt-facts');\n return FactCollection.create(this.options);\n }\n\n private async getFactContentCollection() {\n const { FactContentCollection } = await import('@happyvertical/smrt-facts');\n return FactContentCollection.create(this.options);\n }\n\n private async getFactSourceCollection() {\n const { FactSourceCollection } = await import('@happyvertical/smrt-facts');\n return FactSourceCollection.create(this.options);\n }\n\n private async getFactEvidenceCollection() {\n const { FactEvidenceCollection } = await import(\n '@happyvertical/smrt-facts'\n );\n return FactEvidenceCollection.create(this.options);\n }\n\n private async getContentVersionCollection() {\n const { ContentVersionCollection } = await import('./content-versions');\n return ContentVersionCollection.create(this.options);\n }\n\n private async getContentReviewCollection() {\n const { ContentReviewCollection } = await import('./content-reviews');\n return ContentReviewCollection.create(this.options);\n }\n\n private async getContentCorrectionCollection() {\n const { ContentCorrectionCollection } = await import(\n './content-corrections'\n );\n return ContentCorrectionCollection.create(this.options);\n }\n\n private async getContentsCollection() {\n const { Contents } = await import('./contents');\n return Contents.create({ db: this.db });\n }\n\n private getConfiguredGovernance(): ResolvedContentGovernance {\n return resolveConfiguredContentGovernance({\n contentType: this.type,\n contentVariant: this.variant,\n });\n }\n\n public async resolveGovernance(): Promise<ResolvedContentGovernance> {\n return resolveEffectiveContentGovernance({\n contentType: this.type,\n contentVariant: this.variant,\n db: this.db,\n });\n }\n\n private async hasPersistedGovernanceAssignments(): Promise<boolean> {\n if (!this.db || typeof this.db.query !== 'function') {\n return false;\n }\n\n try {\n const exactKey = buildContentGovernanceAssignmentKey(\n this.type || '',\n this.variant || '',\n );\n const typeOnlyKey = buildContentGovernanceAssignmentKey(this.type || '');\n const keys =\n exactKey === typeOnlyKey ? [exactKey] : [exactKey, typeOnlyKey];\n const placeholders = keys.map(() => '?').join(', ');\n const result = await this.db.query(\n `SELECT 1 AS matched FROM content_governance_assignments WHERE key IN (${placeholders}) LIMIT 1`,\n keys,\n );\n const rows = Array.isArray(result) ? result : (result?.rows ?? []);\n return rows.length > 0;\n } catch {\n return false;\n }\n }\n\n private async resolvePublicationGovernance(): Promise<ResolvedContentGovernance | null> {\n const configuredGovernance = this.getConfiguredGovernance();\n\n if (configuredGovernance.isGoverned) {\n return this.resolveGovernance();\n }\n\n if (!(await this.hasPersistedGovernanceAssignments())) {\n return null;\n }\n\n const governance = await this.resolveGovernance();\n return governance.isGoverned ? governance : null;\n }\n\n private async requireGovernance(\n feature = 'governance workflow',\n ): Promise<ResolvedContentGovernance> {\n const governance = await this.resolveGovernance();\n\n if (!governance.isGoverned) {\n throw new Error(\n `Governance is not enabled for content type \"${this.type || 'content'}\"${this.variant ? ` variant \"${this.variant}\"` : ''}, so ${feature} is unavailable.`,\n );\n }\n\n return governance;\n }\n\n private async requireFactLinking(\n feature = 'fact linking',\n ): Promise<ResolvedContentGovernance> {\n const governance = await this.requireGovernance(feature);\n\n if (!governance.factLinkingEnabled) {\n throw new Error(\n `Fact linking is not enabled for content type \"${this.type || 'content'}\"${this.variant ? ` variant \"${this.variant}\"` : ''}.`,\n );\n }\n\n return governance;\n }\n\n private async getPersistedContent(): Promise<Content | null> {\n if (!this.id) {\n return null;\n }\n\n const contents = await this.getContentsCollection();\n return (await contents.get({ id: this.id as string })) as Content | null;\n }\n\n private async buildReviewFingerprint(policyKey: string): Promise<string> {\n const governance = await this.resolveGovernance();\n const kind = getContentReviewKind(policyKey, governance.reviewPolicies);\n const policy = getContentReviewPolicy(policyKey, governance.reviewPolicies);\n const [references, facts, factLinks] = await Promise.all([\n this.getReferences(),\n kind === 'facts' && governance.factLinkingEnabled\n ? this.getFacts({\n latestOnly: true,\n includeSuperseded: false,\n })\n : Promise.resolve([]),\n kind === 'facts' && governance.factLinkingEnabled\n ? this.getFactLinks()\n : Promise.resolve([]),\n ]);\n\n return createFingerprint({\n scope: 'content-review',\n policyKey,\n kind,\n policyInstructions: policy?.instructions || '',\n content: {\n id: this.id || null,\n type: this.type,\n variant: this.variant,\n title: this.title,\n description: this.description,\n body: this.body,\n author: this.author,\n state: this.state,\n publishDate: this.publish_date,\n language: this.language,\n category: this.category,\n tags: this.tags,\n metadata: this.metadata,\n },\n referenceIds: references\n .map((reference) => reference.id)\n .filter(Boolean)\n .sort(),\n facts: facts.map((fact) => ({\n id: fact.id || null,\n // Pre-R3-C this was `parentId`; renamed to `previousFactId` in\n // smrt-facts. Existing cached fingerprints will invalidate, which\n // is the correct behaviour — the review surface (a key in the\n // hash) changed.\n previousFactId: fact.previousFactId || null,\n status: fact.status || null,\n textRefined: fact.textRefined || '',\n sourceCount: fact.sourceCount ?? 0,\n confidence: fact.confidence ?? null,\n metadata:\n typeof fact?.getMetadata === 'function' ? fact.getMetadata() : {},\n })),\n factLinks: factLinks.map((link) => ({\n factId: link.factId || null,\n relationship: link.relationship || null,\n metadata:\n typeof link?.getMetadata === 'function' ? link.getMetadata() : {},\n })),\n });\n }\n\n private async buildTransparencySnapshot(\n options: {\n snapshotKind?: 'preview' | 'published';\n governance?: ResolvedContentGovernance;\n } = {},\n ) {\n const snapshotKind = options.snapshotKind || 'preview';\n const governance = options.governance || (await this.resolveGovernance());\n\n if (!governance.isGoverned || !governance.transparencyEnabled) {\n return null;\n }\n\n const [\n references,\n facts,\n factLinks,\n reviews,\n corrections,\n versions,\n reviewProfiles,\n ] = await Promise.all([\n this.getReferences(),\n governance.factLinkingEnabled\n ? this.getFacts({\n latestOnly: true,\n includeSuperseded: false,\n })\n : Promise.resolve([]),\n governance.factLinkingEnabled ? this.getFactLinks() : Promise.resolve([]),\n this.listReviews(),\n this.listCorrections(),\n this.listVersions(),\n this.listReviewProfilesAction(),\n ]);\n\n const factSources = await this.getFactSourceCollection();\n const factSourcesByFactId = new Map<string, FactSource[]>();\n\n for (const fact of facts) {\n const factId = fact.id as string | undefined;\n if (!factId) {\n continue;\n }\n\n const sources = await factSources.getForFact(factId);\n factSourcesByFactId.set(factId, sources);\n }\n\n const usedFactIds = new Set(\n factLinks\n .filter((link) =>\n USED_FACT_RELATIONSHIPS.has(\n (link.relationship || 'related') as FactContentRelationship,\n ),\n )\n .map((link) => link.factId)\n .filter(Boolean),\n );\n\n const linkedFacts = facts.map((fact) => {\n const factId = fact.id as string | undefined;\n const link = factLinks.find((entry) => entry.factId === factId);\n const sources = (factId ? factSourcesByFactId.get(factId) : []) || [];\n\n return {\n ...serializeFact(fact),\n relationship: link?.relationship || null,\n linkMetadata:\n typeof link?.getMetadata === 'function' ? link.getMetadata() : {},\n usedInArticle: factId ? usedFactIds.has(factId) : false,\n sources: sources.map((source) => ({\n id: source.id || null,\n sourceType: source.sourceType || null,\n sourceUrl: source.sourceUrl || null,\n sourceTitle: source.sourceTitle || null,\n credibility: source.credibility ?? null,\n extractedAt: source.extractedAt || null,\n metadata:\n typeof source?.getMetadata === 'function'\n ? source.getMetadata()\n : {},\n })),\n };\n });\n\n const referenceGroups = await Promise.all(\n references.map(async (reference) => {\n const sourceUrls = [\n reference.url,\n reference.original_url,\n reference.source,\n ].filter(Boolean) as string[];\n\n const extractedFacts = new Map<string, Fact>();\n for (const sourceUrl of sourceUrls) {\n const matches = await factSources.list({\n where: { sourceUrl },\n orderBy: 'created_at ASC',\n });\n\n for (const match of matches) {\n if (!match.factId || extractedFacts.has(match.factId)) {\n continue;\n }\n\n const fact = await match.getFact();\n if (fact?.id) {\n extractedFacts.set(fact.id as string, fact);\n }\n }\n }\n\n const extractedFactRecords: SerializedRecord[] = [\n ...extractedFacts.values(),\n ].map((fact) => {\n const factId = fact.id as string | undefined;\n return {\n ...serializeFact(fact),\n usedInArticle: factId ? usedFactIds.has(factId) : false,\n };\n });\n\n return {\n id: reference.id || null,\n title: reference.title || reference.name || reference.url || null,\n url: reference.url || null,\n originalUrl: reference.original_url || null,\n type: reference.type || null,\n source: reference.source || null,\n usedFactIds: extractedFactRecords\n .filter((fact) => fact.id && usedFactIds.has(fact.id))\n .map((fact) => fact.id),\n extractedFacts: extractedFactRecords,\n };\n }),\n );\n\n const publicGeneration = readNestedRecord(this.metadata, [\n 'transparency',\n 'generation',\n ]);\n const generationMetadata = readNestedRecord(this.metadata, ['generation']);\n const serializedCorrections = (corrections as SerializedRecord[])\n .filter((correction) => correction.status === 'published')\n .map((correction) => {\n // `corrections` is already serialized to plain records, so the\n // metadata is the parsed object on `correction.metadata`.\n const correctionMetadata = asRecord(correction.metadata);\n\n return {\n ...serializeContentCorrection(correction),\n provenance: {\n autoGeneratedDraft: Boolean(correctionMetadata.autoGeneratedDraft),\n draftVersionId: correctionMetadata.draftVersionId || null,\n draftVersionNumber: correctionMetadata.draftVersionNumber || null,\n sourceCorrectionVersionId:\n correctionMetadata.sourceCorrectionVersionId || null,\n sourceCorrectionVersionNumber:\n correctionMetadata.sourceCorrectionVersionNumber || null,\n },\n };\n });\n const serializedVersionHistory = (versions as SerializedRecord[]).map(\n (version) => {\n // `versions` is already serialized to plain records.\n const versionMetadata = asRecord(version.metadata);\n\n return {\n id: version.id || null,\n version: version.version ?? null,\n kind: version.kind || null,\n summary: version.summary || '',\n createdAt: version.createdAt || null,\n provenance: {\n policyKey: versionMetadata.policyKey || null,\n reviewFingerprint:\n versionMetadata.reviewFingerprint ||\n versionMetadata.contentFingerprint ||\n null,\n factId: versionMetadata.factId || null,\n replacementFactId: versionMetadata.replacementFactId || null,\n sourceCorrectionVersionId:\n versionMetadata.sourceCorrectionVersionId || null,\n sourceCorrectionVersionNumber:\n versionMetadata.sourceCorrectionVersionNumber || null,\n correctionDraft: versionMetadata.correctionDraft || null,\n publicationSnapshotFingerprint:\n versionMetadata.publicationSnapshotFingerprint || null,\n },\n };\n },\n );\n\n return normalizeContentTransparency(\n {\n generatedAt: new Date().toISOString(),\n snapshotKind,\n contentId: (this.id as string) || null,\n currentContentStatus: this.status || null,\n publicationProfileKey: governance.publicationProfileKey || undefined,\n generation: {\n aiAssisted:\n publicGeneration.aiAssisted ??\n generationMetadata.aiAssisted ??\n Boolean(getPublicPrompt(this.metadata)),\n publicPrompt: getPublicPrompt(this.metadata),\n model: publicGeneration.model || generationMetadata.model || null,\n },\n factsUsed: linkedFacts.filter((fact) => fact.usedInArticle),\n linkedFacts,\n otherExtractedFacts: referenceGroups.flatMap((reference) =>\n reference.extractedFacts.filter((fact) => !fact.usedInArticle),\n ),\n references: referenceGroups,\n reviews,\n reviewProfiles,\n corrections: serializedCorrections,\n versionHistory: serializedVersionHistory,\n },\n {\n snapshotKind,\n contentId: (this.id as string) || null,\n currentContentStatus: this.status || null,\n publicationProfileKey: governance.publicationProfileKey || undefined,\n },\n );\n }\n\n /**\n * Fingerprint of the *content-bearing* publication surface only.\n *\n * This must converge: two byte-identical `save()`s of published content\n * have to produce the same fingerprint so the publication-version writer\n * (`save()`) does not append a redundant `ContentVersion` on every save.\n *\n * It therefore deliberately excludes everything that grows or carries a\n * timestamp/ordering with each save — `versionHistory`, `reviews`,\n * `corrections`, and any `generatedAt`/`createdAt`/`id` fields. The earlier\n * implementation fingerprinted the full transparency snapshot (which embeds\n * the growing `versionHistory`), so the stored fingerprint of vN predated vN\n * and the next save's recomputed fingerprint always differed → unbounded\n * redundant publication versions (#1387 blocker).\n *\n * The surface mirrors `buildReviewFingerprint`'s content block, plus the\n * pinned reference edges (`{ targetId, targetVersion }`) — a pin change is a\n * meaningful republication — and the publication profile key.\n */\n private async buildPublicationSnapshotFingerprint(\n governance: ResolvedContentGovernance,\n ): Promise<string | null> {\n if (!governance.isGoverned || !governance.transparencyEnabled) {\n return null;\n }\n\n const referenceCollection = await this.getReferenceCollection();\n const [referenceEdges, facts, factLinks] = await Promise.all([\n this.id ? referenceCollection.getForSource(this.id) : Promise.resolve([]),\n governance.factLinkingEnabled\n ? this.getFacts({ latestOnly: true, includeSuperseded: false })\n : Promise.resolve([]),\n governance.factLinkingEnabled ? this.getFactLinks() : Promise.resolve([]),\n ]);\n\n return createFingerprint({\n scope: 'content-publication',\n publicationProfileKey: governance.publicationProfileKey || null,\n content: {\n id: this.id || null,\n type: this.type,\n variant: this.variant,\n title: this.title,\n description: this.description,\n body: this.body,\n author: this.author,\n state: this.state,\n publishDate: this.publish_date,\n language: this.language,\n category: this.category,\n tags: this.tags,\n metadata: this.metadata,\n },\n // Pinned reference edges only — ordering-independent so it converges.\n references: referenceEdges\n .map((edge) => ({\n targetId: edge.targetId || null,\n targetVersion: edge.targetVersion ?? null,\n }))\n .sort((a, b) => String(a.targetId).localeCompare(String(b.targetId))),\n facts: facts\n .map((fact) => ({\n id: fact.id || null,\n previousFactId: fact.previousFactId || null,\n status: fact.status || null,\n textRefined: fact.textRefined || '',\n sourceCount: fact.sourceCount ?? 0,\n confidence: fact.confidence ?? null,\n metadata:\n typeof fact?.getMetadata === 'function' ? fact.getMetadata() : {},\n }))\n .sort((a, b) => String(a.id).localeCompare(String(b.id))),\n factLinks: factLinks\n .map((link) => ({\n factId: link.factId || null,\n relationship: link.relationship || null,\n metadata:\n typeof link?.getMetadata === 'function' ? link.getMetadata() : {},\n }))\n .sort((a, b) => String(a.factId).localeCompare(String(b.factId))),\n });\n }\n\n private async getLatestPublicationSnapshotFingerprint(): Promise<\n string | null\n > {\n const versions = await this.getVersions();\n const latestPublicationVersion = [...versions]\n .reverse()\n .find((version) => version.kind === 'publication');\n\n if (!latestPublicationVersion) {\n return null;\n }\n\n return (\n latestPublicationVersion.getMetadata().publicationSnapshotFingerprint ||\n null\n );\n }\n\n private async buildCorrectionDraftSnapshot(\n options: IssueContentCorrectionOptions,\n replacementFactId: string,\n ): Promise<{\n snapshot: Record<string, unknown>;\n metadata: Record<string, unknown>;\n }> {\n const correctedText =\n options.correctedText || options.correctedFactText || '';\n const incorrectText = options.incorrectText || '';\n let body = this.body;\n let generationMethod = 'metadata';\n\n if (incorrectText && correctedText && body.includes(incorrectText)) {\n body = body.replace(incorrectText, correctedText);\n generationMethod = 'replace';\n } else if (correctedText) {\n const ai = this.ai as {\n message?: (\n prompt: string,\n options?: Record<string, unknown>,\n ) => Promise<string>;\n };\n if (ai?.message) {\n const resolvedPrompt = await resolvePrompt(\n smrtContentApplyCorrectionPrompt.key,\n {\n db: this.options.db,\n tenantId: this.tenantId,\n variables: {\n body: this.body,\n correctedText,\n incorrectText: incorrectText || 'Not provided',\n summary: options.summary || '',\n },\n },\n );\n\n try {\n const proposedBody = (\n await ai.message(\n resolvedPrompt.text,\n promptMessageOptions(resolvedPrompt.ai),\n )\n ).trim();\n if (proposedBody) {\n body = proposedBody;\n generationMethod = 'ai';\n }\n } catch {\n generationMethod = 'metadata';\n }\n }\n }\n\n return {\n snapshot: {\n title: this.title,\n description: this.description,\n body,\n status: 'draft',\n metadata: {\n ...(this.metadata || {}),\n governance: {\n ...asRecord(this.metadata.governance),\n correctionDraft: {\n summary: options.summary,\n incorrectText,\n correctedText,\n factId: options.factId || null,\n replacementFactId: replacementFactId || null,\n autoGenerated: true,\n generationMethod,\n },\n },\n },\n },\n metadata: {\n summary: options.summary,\n incorrectText,\n correctedText,\n factId: options.factId || null,\n replacementFactId: replacementFactId || null,\n autoGenerated: true,\n generationMethod,\n },\n };\n }\n\n private async getAssetCollection() {\n return AssetCollection.create({ db: this.db });\n }\n\n private async getContentAssetCollection() {\n return ContentAssetCollection.create({ db: this.db });\n }\n\n private async getContentAssetLinks(\n relationship?: string,\n ): Promise<Array<{ assetId: string; sortOrder: number }>> {\n if (!this.id) {\n return [];\n }\n\n try {\n const contentAssets = await this.getContentAssetCollection();\n const links = await contentAssets.byLeft(\n this.id,\n relationship ? { relationship } : {},\n );\n\n return links\n .filter((link) => link.assetId)\n .map((link) => ({\n assetId: link.assetId,\n sortOrder: link.sortOrder ?? 0,\n }));\n } catch (error) {\n if (isMissingTableError(error, 'content_assets')) {\n return [];\n }\n\n throw error;\n }\n }\n\n private async resolveAssetsForLinks(\n links: Array<{ assetId: string; sortOrder: number }>,\n ): Promise<Asset[]> {\n if (links.length === 0) {\n return [];\n }\n\n const assetIds = [...new Set(links.map((link) => link.assetId))];\n const assets = await this.getAssetCollection();\n const resolved = await assets.listByIds(assetIds);\n const assetsById = new Map(\n resolved\n .filter((asset) => asset.id)\n .map((asset) => [asset.id as string, asset]),\n );\n\n return links\n .map((link) => assetsById.get(link.assetId))\n .filter(Boolean) as Asset[];\n }\n\n private async resolveReferenceTarget(content: Content | string) {\n if (typeof content !== 'string') {\n return content;\n }\n\n const contents = await this.getContentsCollection();\n\n return (await contents.getOrUpsert(\n {\n url: content,\n tenantId: this.tenantId,\n },\n {\n name: content,\n title: content,\n type: 'reference',\n tenantId: this.tenantId,\n },\n )) as Content;\n }\n\n /**\n * Loads referenced content objects\n *\n * @returns Promise that resolves when references are loaded\n */\n public async loadReferences() {\n this.references = await this.getReferences();\n }\n\n private getPendingReferenceIds(): string[] | null {\n const pendingReferenceIds = (this as Content & ContentTransientLinkIds)\n .referenceIds;\n\n if (!Array.isArray(pendingReferenceIds)) {\n return null;\n }\n\n return [\n ...new Set(\n pendingReferenceIds.filter(\n (referenceId): referenceId is string =>\n typeof referenceId === 'string' &&\n referenceId.length > 0 &&\n referenceId !== this.id,\n ),\n ),\n ];\n }\n\n private getPendingAssetIds(): string[] | null {\n const pendingAssetIds = (this as Content & ContentTransientLinkIds)\n .assetIds;\n\n if (!Array.isArray(pendingAssetIds)) {\n return null;\n }\n\n return [\n ...new Set(\n pendingAssetIds.filter(\n (assetId): assetId is string =>\n typeof assetId === 'string' && assetId.length > 0,\n ),\n ),\n ];\n }\n\n private async syncPendingReferenceIds(): Promise<void> {\n if (!this.id) {\n return;\n }\n\n const pendingReferenceIds = this.getPendingReferenceIds();\n if (pendingReferenceIds === null) {\n return;\n }\n\n const currentReferences = await this.getReferences();\n const currentReferenceIds = currentReferences\n .map((reference) => reference.id)\n .filter((referenceId): referenceId is string => Boolean(referenceId));\n const currentReferenceIdSet = new Set(currentReferenceIds);\n const pendingReferenceIdSet = new Set(pendingReferenceIds);\n\n for (const referenceId of currentReferenceIds) {\n if (!pendingReferenceIdSet.has(referenceId)) {\n await this.removeReference(referenceId);\n }\n }\n\n const referenceIdsToAdd = pendingReferenceIds.filter(\n (referenceId) => !currentReferenceIdSet.has(referenceId),\n );\n\n if (referenceIdsToAdd.length === 0) {\n this.references = await this.getReferences();\n return;\n }\n\n const contents = await this.getContentsCollection();\n const resolvedReferences = await contents.listByIds(referenceIdsToAdd);\n const referencesById = new Map(\n resolvedReferences\n .filter((reference) => reference.id)\n .map((reference) => [reference.id as string, reference]),\n );\n\n for (const referenceId of referenceIdsToAdd) {\n const reference = referencesById.get(referenceId);\n if (reference) {\n await this.addReference(reference);\n }\n }\n\n this.references = await this.getReferences();\n }\n\n private async syncPendingAssetIds(): Promise<void> {\n if (!this.id) {\n return;\n }\n\n const pendingAssetIds = this.getPendingAssetIds();\n if (pendingAssetIds === null) {\n return;\n }\n\n const currentAssets = await this.getAssets();\n const currentAssetIds = currentAssets\n .map((asset) => asset.id)\n .filter((assetId): assetId is string => Boolean(assetId));\n const currentAssetIdSet = new Set(currentAssetIds);\n const pendingAssetIdSet = new Set(pendingAssetIds);\n\n for (const assetId of currentAssetIds) {\n if (!pendingAssetIdSet.has(assetId)) {\n await this.removeAsset(assetId);\n }\n }\n\n const assetIdsToAdd = pendingAssetIds.filter(\n (assetId) => !currentAssetIdSet.has(assetId),\n );\n\n if (assetIdsToAdd.length === 0) {\n return;\n }\n\n const assets = await this.getAssetCollection();\n const resolvedAssets = await assets.listByIds(assetIdsToAdd);\n const assetsById = new Map(\n resolvedAssets\n .filter((asset) => asset.id)\n .map((asset) => [asset.id as string, asset]),\n );\n\n for (const assetId of assetIdsToAdd) {\n const asset = assetsById.get(assetId);\n if (asset) {\n await this.addAsset(asset);\n }\n }\n }\n\n /**\n * Adds a reference to another content object.\n *\n * @param content - Content object or URL to reference\n * @param options.targetVersion - Optional ContentVersion.version to pin the\n * citation to. Pass the target's current version (typically the latest\n * publication) to enable drift detection later. Pass `null` or omit to\n * leave the reference untracked.\n * @returns Promise that resolves when the reference is added\n */\n public async addReference(\n content: Content | string,\n options: { targetVersion?: number | null } = {},\n ) {\n if (!this.id) {\n throw new Error('Cannot add reference to unsaved content');\n }\n\n const target = await this.resolveReferenceTarget(content);\n\n if (!target.id) {\n throw new Error('Cannot add reference to unsaved content');\n }\n if (this.id === target.id) {\n return;\n }\n\n const references = await this.getReferenceCollection();\n // R2 junction `attach` carries extra row fields via its opts bag, so the\n // tenant scope and main's citation pin (targetVersion) ride along together.\n await references.attach(this.id, target.id, {\n tenantId: this.tenantId,\n targetVersion: options.targetVersion,\n });\n this.references = await this.getReferences();\n }\n\n /**\n * Removes a reference to another content object\n *\n * @param targetId - ID of the referenced content to remove\n */\n public async removeReference(targetId: string) {\n if (!this.id) {\n return;\n }\n\n const references = await this.getReferenceCollection();\n await references.detach(this.id, targetId);\n this.references = this.references.filter(\n (reference) => reference.id !== targetId,\n );\n }\n\n /**\n * Gets all referenced content objects\n *\n * @returns Promise resolving to an array of referenced Content objects\n */\n public async getReferences() {\n if (!this.id) {\n return [];\n }\n\n const references = await this.getReferenceCollection();\n const linkedReferences = await references.byLeft(this.id);\n const targetIds = linkedReferences.map((reference) => reference.targetId);\n\n if (targetIds.length === 0) {\n this.references = [];\n return this.references;\n }\n\n const contents = await this.getContentsCollection();\n const resolved = await contents.listByIds(targetIds);\n const referencesById = new Map(\n resolved\n .filter((content) => content.id)\n .map((content) => [content.id as string, content]),\n );\n\n this.references = targetIds\n .map((targetId) => referencesById.get(targetId))\n .filter(Boolean) as Content[];\n return this.references;\n }\n\n /**\n * Returns the raw reference edges with their citation pins\n * (`{ targetId, targetVersion }`). Unlike `getReferences()` (which resolves\n * to `Content` objects and loses the per-edge `targetVersion`), this keeps\n * the pin so callers — notably version snapshots — can reconstruct pinned\n * citations on restore. See `ContentVersionCollection.restoreIntoContent`.\n */\n public async getReferenceEdges(): Promise<\n Array<{ targetId: string; targetVersion: number | null }>\n > {\n if (!this.id) {\n return [];\n }\n\n const references = await this.getReferenceCollection();\n const linkedReferences = await references.getForSource(this.id);\n return linkedReferences\n .filter((edge) => Boolean(edge.targetId))\n .map((edge) => ({\n targetId: edge.targetId as string,\n targetVersion: edge.targetVersion ?? null,\n }));\n }\n\n /**\n * Returns one entry per reference edge with the pinned `targetVersion` and\n * the target's latest version. Drift exists when both are present and\n * differ — callers can use this to surface \"the source you cited has been\n * updated\" affordances in editors or review tools.\n *\n * `currentVersion` is the target's latest **publication** `ContentVersion`,\n * because pins are taken against the latest publication (see `addReference`).\n * Auto-created `correction`/`draft`/`manual` versions bump the shared\n * `(content_id, version)` counter but do NOT republish, so comparing against\n * the max version of *any* kind produced false drift positives (#1387 #4).\n *\n * Unpinned references (`citedVersion === null`) are included with\n * `currentVersion` populated when available so callers can choose to\n * surface them as \"pinnable\" suggestions.\n */\n public async getReferenceDrift(): Promise<\n Array<{\n targetId: string;\n citedVersion: number | null;\n currentVersion: number | null;\n isDrifted: boolean;\n }>\n > {\n if (!this.id) {\n return [];\n }\n\n const references = await this.getReferenceCollection();\n const linkedReferences = await references.getForSource(this.id);\n if (linkedReferences.length === 0) {\n return [];\n }\n\n const versions = await this.getContentVersionCollection();\n const targetIds = linkedReferences.map((reference) => reference.targetId);\n\n // Single query for all target *publication* versions; pick the max per\n // contentId. Pins are taken against the latest publication, so only\n // publication versions count as drift (#1387 #4). Filtering by kind here\n // also avoids the N+1 of loading each version to inspect its kind.\n const allVersions = await versions.list({\n where: { contentId: targetIds, kind: 'publication' },\n orderBy: 'version DESC',\n });\n const latestByContentId = new Map<string, number>();\n for (const version of allVersions) {\n if (!latestByContentId.has(version.contentId)) {\n latestByContentId.set(version.contentId, version.version);\n }\n }\n\n return linkedReferences.map((reference) => {\n const currentVersion = latestByContentId.get(reference.targetId) ?? null;\n const citedVersion = reference.targetVersion ?? null;\n return {\n targetId: reference.targetId,\n citedVersion,\n currentVersion,\n isDrifted:\n citedVersion !== null &&\n currentVersion !== null &&\n citedVersion !== currentVersion,\n };\n });\n }\n\n public isGoverned(): boolean {\n return this.getConfiguredGovernance().isGoverned;\n }\n\n public async getFactLinks(\n options: { relationship?: FactContentRelationship } = {},\n ) {\n const governance = await this.resolveGovernance();\n if (!governance.isGoverned || !governance.factLinkingEnabled || !this.id) {\n return [];\n }\n\n if (!this.id) {\n return [];\n }\n\n const links = await this.getFactContentCollection();\n return options.relationship\n ? links.byRight(this.id as string, { relationship: options.relationship })\n : links.byRight(this.id as string);\n }\n\n public async getFacts(\n options: {\n relationship?: FactContentRelationship;\n includeSuperseded?: boolean;\n latestOnly?: boolean;\n } = {},\n ): Promise<Fact[]> {\n const governance = await this.resolveGovernance();\n if (!governance.isGoverned || !governance.factLinkingEnabled || !this.id) {\n return [];\n }\n\n if (!this.id) {\n return [];\n }\n\n const facts = await this.getFactCollection();\n return facts.getForContent(this.id as string, options);\n }\n\n public async addFact(\n fact: Fact | string,\n relationship?: FactContentRelationship,\n metadata?: Record<string, unknown>,\n ) {\n const governance = await this.requireFactLinking('fact association');\n\n if (!this.id) {\n throw new Error('Cannot associate an unsaved content item with a fact');\n }\n\n const factId = typeof fact === 'string' ? fact : (fact.id as string);\n if (!factId) {\n throw new Error('Fact ID is required to create a content-fact link');\n }\n\n const links = await this.getFactContentCollection();\n return links.attach(factId, this.id as string, {\n relationship: relationship || governance.defaultFactRelationship,\n metadata,\n });\n }\n\n public async removeFact(\n factId: string,\n relationship?: FactContentRelationship,\n ): Promise<void> {\n const governance = await this.resolveGovernance();\n if (!governance.isGoverned || !governance.factLinkingEnabled) {\n return;\n }\n\n if (!this.id) {\n return;\n }\n\n const links = await this.getFactContentCollection();\n if (relationship) {\n await links.detach(factId, this.id as string, { relationship });\n return;\n }\n\n await links.detach(factId, this.id as string);\n }\n\n public async syncFacts(\n factIds: string[],\n relationship?: FactContentRelationship,\n ): Promise<{ added: string[]; kept: string[]; removed: string[] }> {\n const governance = await this.requireFactLinking('fact sync');\n\n if (!this.id) {\n throw new Error('Cannot sync facts for unsaved content');\n }\n\n const uniqueFactIds = [...new Set(factIds.filter(Boolean))];\n const links = await this.getFactContentCollection();\n const resolvedRelationship =\n relationship || governance.defaultFactRelationship;\n const existing = await links.byRight(this.id as string, {\n relationship: resolvedRelationship,\n });\n\n const existingIds = new Set(existing.map((link) => link.factId));\n const desiredIds = new Set(uniqueFactIds);\n\n const kept = uniqueFactIds.filter((factId) => existingIds.has(factId));\n const added = uniqueFactIds.filter((factId) => !existingIds.has(factId));\n const removed = existing\n .map((link) => link.factId)\n .filter((factId) => !desiredIds.has(factId));\n\n for (const factId of added) {\n await links.attach(factId, this.id as string, {\n relationship: resolvedRelationship,\n });\n }\n\n for (const factId of removed) {\n await links.detach(factId, this.id as string, {\n relationship: resolvedRelationship,\n });\n }\n\n return { added, kept, removed };\n }\n\n public async browseFacts(\n query = '',\n options: {\n limit?: number;\n offset?: number;\n minSimilarity?: number;\n includeSuperseded?: boolean;\n latestOnly?: boolean;\n } = {},\n ): Promise<Fact[]> {\n await this.requireFactLinking('fact catalog browsing');\n const facts = await this.getFactCollection();\n return facts.browseCatalog(query, {\n ...options,\n tenantId: this.tenantId,\n });\n }\n\n private async getFactAuditSourceMaterials(): Promise<{\n sources: FactAuditSourceMaterial[];\n warnings: string[];\n }> {\n const warnings: string[] = [];\n const sources: FactAuditSourceMaterial[] = [];\n const references = await this.getReferences();\n const assets = await this.getAssets();\n\n for (const reference of references) {\n const referenceId = (reference.id as string | undefined) || '';\n const text = getContentText(reference);\n // `sourceUrl` is not a declared Content field; read it structurally.\n const referenceSourceUrl = (reference as { sourceUrl?: unknown })\n .sourceUrl;\n const sourceUrl =\n normalizeAuditText(reference.url) ||\n normalizeAuditText(referenceSourceUrl) ||\n normalizeAuditText(reference.fileKey);\n const sourceTitle =\n normalizeAuditText(reference.title) ||\n normalizeAuditText(reference.name) ||\n sourceUrl ||\n referenceId;\n\n if (!text) {\n warnings.push(\n `Reference ${sourceTitle || referenceId} has no extracted text.`,\n );\n continue;\n }\n\n sources.push({\n sourceKind: 'content-reference',\n sourceId: referenceId,\n sourceUrl,\n sourceTitle,\n locator: sourceTitle,\n text,\n });\n }\n\n for (const asset of assets as Array<Asset & FactAuditAssetExtraFields>) {\n const metadata =\n typeof asset?.getMetadata === 'function'\n ? asset.getMetadata()\n : parseAuditMetadata(asset?.metadata);\n const text = [\n metadata.extractedText,\n metadata.text,\n metadata.ocrText,\n asset?.text,\n asset?.body,\n asset?.description,\n ]\n .map(normalizeAuditText)\n .filter(Boolean)\n .join('\\n\\n');\n const assetId = normalizeAuditText(asset?.id);\n const sourceTitle =\n normalizeAuditText(asset?.title) ||\n normalizeAuditText(asset?.name) ||\n normalizeAuditText(asset?.filename) ||\n assetId;\n const sourceUrl =\n normalizeAuditText(asset?.url) ||\n normalizeAuditText(asset?.sourceUrl) ||\n normalizeAuditText(asset?.fileKey);\n\n if (!text) {\n warnings.push(`Asset ${sourceTitle || assetId} has no extracted text.`);\n continue;\n }\n\n sources.push({\n sourceKind: 'asset',\n sourceId: assetId,\n sourceUrl,\n sourceTitle,\n locator: sourceTitle,\n text,\n });\n }\n\n return { sources, warnings };\n }\n\n private factMatchesTenant(fact: {\n tenantId?: string | null;\n tenant_id?: string | null;\n }): boolean {\n return (\n fact.tenantId === this.tenantId ||\n fact.tenant_id === this.tenantId ||\n (!fact.tenantId && !fact.tenant_id && !this.tenantId)\n );\n }\n\n private async findExactArticleClaimFact(\n statement: string,\n ): Promise<Fact | null> {\n const normalizedStatement = normalizeAuditText(statement);\n const facts = await this.getFactCollection();\n const linkedClaimFacts = await Promise.all(\n (await this.getFactLinks({ relationship: 'referenced_in' })).map((link) =>\n facts.get({ id: link.factId }),\n ),\n );\n const linkedMatch = linkedClaimFacts.find(\n (fact): fact is Fact =>\n Boolean(fact) &&\n this.factMatchesTenant(fact as Fact) &&\n normalizeAuditText((fact as Fact).textRefined) === normalizedStatement,\n );\n if (linkedMatch) {\n return linkedMatch;\n }\n\n const matches = await facts.list({\n where: { textRefined: normalizedStatement },\n orderBy: 'updated_at DESC',\n });\n\n return (\n matches.find(\n (fact) =>\n this.factMatchesTenant(fact) &&\n this.id &&\n isGeneratedArticleClaimFact(fact, this.id as string),\n ) || null\n );\n }\n\n private async safeAuditLink(\n factId: string,\n relationship: FactContentRelationship,\n metadata: Record<string, unknown>,\n ) {\n const links = await this.getFactContentCollection();\n const existing = (\n await links.byRight(this.id as string, { relationship })\n ).find((link) => link.factId === factId);\n\n if (existing) {\n const existingMetadata = getLinkMetadata(existing);\n if (existingMetadata.generatedBy === FACT_AUDIT_GENERATED_BY) {\n existing.setMetadata?.({\n ...existingMetadata,\n ...metadata,\n });\n } else {\n existing.setMetadata?.({\n ...existingMetadata,\n factAudit: {\n ...asRecord(existingMetadata.factAudit),\n ...metadata,\n },\n });\n }\n await existing.save();\n return existing;\n }\n\n return links.attach(factId, this.id as string, { relationship, metadata });\n }\n\n private async clearGeneratedFactAudit(): Promise<void> {\n if (!this.id) {\n return;\n }\n\n const [links, evidences] = await Promise.all([\n this.getFactLinks(),\n this.getFactEvidenceCollection(),\n ]);\n\n for (const link of links) {\n const metadata = getLinkMetadata(link);\n const nestedFactAudit = asRecord(metadata.factAudit);\n if (metadata.generatedBy === FACT_AUDIT_GENERATED_BY) {\n await link.delete();\n } else if (\n metadata.factAudit &&\n typeof metadata.factAudit === 'object' &&\n nestedFactAudit.generatedBy === FACT_AUDIT_GENERATED_BY\n ) {\n const { factAudit: _removed, ...preservedMetadata } = metadata;\n link.setMetadata?.(preservedMetadata);\n await link.save();\n }\n }\n\n const generatedEvidence = await evidences.list({\n where: { tenantId: this.tenantId ?? null },\n });\n for (const evidence of generatedEvidence) {\n const metadata =\n typeof evidence.getMetadata === 'function'\n ? evidence.getMetadata()\n : {};\n if (\n metadata.generatedBy === FACT_AUDIT_GENERATED_BY &&\n metadata.contentId === this.id\n ) {\n await evidence.delete();\n }\n }\n }\n\n private async clearGeneratedFactSourcesForSources(\n sources: FactAuditSourceMaterial[],\n ): Promise<string[]> {\n if (!this.id || sources.length === 0) {\n return [];\n }\n\n const sourceKeys = new Set(\n sources.map((source) => `${source.sourceKind}:${source.sourceId}`),\n );\n const factSources = await this.getFactSourceCollection();\n const generatedSources = await factSources.list({\n where: { tenantId: this.tenantId ?? null },\n });\n const deletedSourceIds: string[] = [];\n\n for (const source of generatedSources) {\n const metadata =\n typeof source.getMetadata === 'function' ? source.getMetadata() : {};\n const sourceKey = `${source.sourceType || ''}:${metadata.sourceId || ''}`;\n if (\n sourceKeys.has(sourceKey) &&\n metadata.generatedBy === FACT_AUDIT_GENERATED_BY &&\n metadata.contentId === this.id\n ) {\n if (typeof source.id === 'string') {\n deletedSourceIds.push(source.id);\n }\n await source.delete();\n }\n }\n\n return deletedSourceIds;\n }\n\n private async extractReferenceFactsForAudit(\n sources: FactAuditSourceMaterial[],\n options: {\n auditRunId: string;\n maxFactsPerSource?: number;\n context?: string;\n replaceGenerated?: boolean;\n },\n ) {\n const facts = await this.getFactCollection();\n const evidences = await this.getFactEvidenceCollection();\n const warnings: string[] = [];\n const referenceFacts = new Map<string, Fact>();\n let deletedEvidenceIds: string[] = [];\n let deletedSourceIds: string[] = [];\n\n if (options.replaceGenerated && sources.length > 0) {\n const replacement = await evidences.replaceGeneratedForSources(\n sources.map((source) => ({\n sourceKind: source.sourceKind,\n sourceId: source.sourceId,\n })),\n {\n generatedBy: FACT_AUDIT_GENERATED_BY,\n contentId: this.id as string,\n tenantId: this.tenantId ?? null,\n },\n );\n deletedEvidenceIds = replacement.deletedEvidenceIds;\n deletedSourceIds =\n await this.clearGeneratedFactSourcesForSources(sources);\n }\n\n for (const source of sources) {\n let candidates: FactExtractionCandidate[] = [];\n try {\n candidates = await facts.extractCandidatesFromText(source.text, {\n domain: FACT_AUDIT_DOMAIN,\n sourceType: source.sourceKind,\n context: options.context || source.sourceTitle,\n maxFacts: options.maxFactsPerSource ?? 24,\n tenantId: this.tenantId,\n });\n } catch (error) {\n warnings.push(\n `Failed to extract facts from ${source.sourceTitle}: ${errorMessage(error)}`,\n );\n continue;\n }\n\n for (const candidate of candidates) {\n const result = await facts.reconcile({\n rawInput: candidate.statement,\n type: candidate.type || 'assertion',\n domain: FACT_AUDIT_DOMAIN,\n tenantId: this.tenantId,\n source: {\n sourceType: source.sourceKind,\n sourceUrl: source.sourceUrl,\n sourceTitle: source.sourceTitle,\n credibility: candidate.confidence ?? 0.75,\n metadata: {\n auditRunId: options.auditRunId,\n generatedBy: FACT_AUDIT_GENERATED_BY,\n contentId: this.id,\n sourceId: source.sourceId,\n quote: candidate.sourceExcerpt || null,\n locator: source.locator || null,\n },\n },\n });\n referenceFacts.set(result.fact.id as string, result.fact);\n\n await evidences.upsertEvidence({\n factId: result.fact.id as string,\n status: 'supports',\n sourceKind: source.sourceKind,\n sourceId: source.sourceId,\n sourceUrl: source.sourceUrl,\n sourceTitle: source.sourceTitle,\n quote: candidate.sourceExcerpt || candidate.statement,\n locator: source.locator,\n extractionMethod: 'ai-reference-fact',\n confidence: candidate.confidence ?? 0.75,\n tenantId: this.tenantId,\n metadata: {\n auditRunId: options.auditRunId,\n generatedBy: FACT_AUDIT_GENERATED_BY,\n contentId: this.id,\n candidateMetadata: candidate.metadata || {},\n },\n });\n }\n }\n\n return {\n referenceFacts,\n warnings,\n referenceFactsExtracted: referenceFacts.size,\n deletedEvidenceIds,\n deletedSourceIds,\n repairedSources: sources.map((source) => ({\n sourceKind: source.sourceKind,\n sourceId: source.sourceId,\n sourceTitle: source.sourceTitle,\n })),\n };\n }\n\n private async getCurrentFactAuditSupportCandidates(\n options: {\n referenceFacts?: Map<string, Fact>;\n sources?: FactAuditSourceSelector[];\n sourceIds?: string[];\n maxCandidateEvidence?: number;\n } = {},\n ) {\n const evidences = await this.getFactEvidenceCollection();\n const allFacts = await this.getFactCollection();\n const candidateFacts = new Map<string, FactAuditSupportCandidate>();\n const candidateEvidence = new Map<string, FactEvidence>();\n const sourceKeys = new Set(\n (options.sources || []).map(\n (source) => `${source.sourceKind}:${source.sourceId}`,\n ),\n );\n const sourceIds = new Set(options.sourceIds || []);\n const maxCandidateEvidence = Math.max(\n 1,\n options.maxCandidateEvidence ?? 120,\n );\n\n const evidenceEntries = options.referenceFacts\n ? (\n await Promise.all(\n [...options.referenceFacts.keys()].map((factId) =>\n evidences.getForFact(factId),\n ),\n )\n ).flat()\n : await evidences.list({\n where: { tenantId: this.tenantId ?? null },\n });\n\n for (const entry of evidenceEntries) {\n if (!isGeneratedFactAuditEvidence(entry, this.id as string)) {\n continue;\n }\n if (entry.sourceKind === 'content') {\n continue;\n }\n if (entry.status === 'irrelevant' || entry.status === 'invalid') {\n continue;\n }\n if (\n sourceKeys.size > 0 &&\n !sourceKeys.has(`${entry.sourceKind}:${entry.sourceId}`)\n ) {\n continue;\n }\n if (sourceIds.size > 0 && !sourceIds.has(entry.sourceId)) {\n continue;\n }\n if (candidateEvidence.size >= maxCandidateEvidence) {\n break;\n }\n\n const fact =\n options.referenceFacts?.get(entry.factId) ||\n (await allFacts.get({ id: entry.factId }));\n if (!fact) {\n continue;\n }\n\n const factId = fact.id as string;\n const existing = candidateFacts.get(factId) || {\n id: factId,\n statement: fact.textRefined || fact.textRaw || '',\n evidence: [],\n };\n const serializedEvidence = {\n id: entry.id || null,\n status: entry.status || 'supports',\n quote: entry.quote || null,\n sourceTitle: entry.sourceTitle || null,\n sourceUrl: entry.sourceUrl || null,\n locator: entry.locator || null,\n };\n existing.evidence.push(serializedEvidence);\n candidateFacts.set(factId, existing);\n if (typeof entry.id === 'string') {\n candidateEvidence.set(entry.id, entry);\n }\n }\n\n return {\n supportCandidates: [...candidateFacts.values()],\n candidateFactIds: new Set(candidateFacts.keys()),\n candidateEvidence,\n };\n }\n\n public async repairFactAudit(\n options: {\n maxReferenceFactsPerSource?: number;\n maxArticleClaims?: number;\n context?: string;\n } = {},\n ) {\n await this.requireFactLinking('fact audit repair');\n if (!this.id) {\n throw new Error('Cannot repair fact audit for unsaved content');\n }\n\n const auditRunId = createFactAuditRunId(this.id as string);\n const facts = await this.getFactCollection();\n const evidences = await this.getFactEvidenceCollection();\n const warnings: string[] = [];\n const articleText = getContentText(this);\n\n const sourceMaterials = await this.getFactAuditSourceMaterials();\n warnings.push(...sourceMaterials.warnings);\n await this.clearGeneratedFactAudit();\n const referenceRepair = await this.extractReferenceFactsForAudit(\n sourceMaterials.sources,\n {\n auditRunId,\n maxFactsPerSource: options.maxReferenceFactsPerSource,\n context: options.context,\n },\n );\n warnings.push(...referenceRepair.warnings);\n const referenceFacts = referenceRepair.referenceFacts;\n\n let claims: FactExtractionCandidate[] = [];\n if (!articleText) {\n warnings.push('Article has no text to audit.');\n } else {\n try {\n claims = await facts.extractArticleClaims(articleText, {\n domain: FACT_AUDIT_DOMAIN,\n sourceType: 'article',\n context: options.context || this.title || this.slug || '',\n maxFacts: options.maxArticleClaims ?? 32,\n tenantId: this.tenantId,\n });\n } catch (error) {\n warnings.push(\n `Failed to extract article claims: ${errorMessage(error)}`,\n );\n }\n }\n\n const { supportCandidates, candidateFactIds, candidateEvidence } =\n await this.getCurrentFactAuditSupportCandidates({\n referenceFacts,\n });\n\n const findings: ContentReviewFinding[] = [];\n\n for (const claim of claims) {\n let assessment: FactClaimSupportAssessment;\n try {\n assessment = await facts.assessClaimSupport(\n claim.statement,\n supportCandidates,\n { tenantId: this.tenantId },\n );\n } catch (error) {\n warnings.push(\n `Failed to assess claim \"${claim.statement}\": ${errorMessage(error)}`,\n );\n assessment = {\n status: 'needs_review' as FactClaimSupportStatus,\n matchedFactIds: [],\n matchedEvidenceIds: [],\n rationale: 'Support assessment failed.',\n confidence: undefined,\n };\n }\n\n const matchedFactIds = assessment.matchedFactIds.filter((factId) =>\n candidateFactIds.has(factId),\n );\n let claimFact = await this.findExactArticleClaimFact(claim.statement);\n\n if (!claimFact) {\n claimFact = await facts.create({\n textRefined: claim.statement,\n textRaw: claim.statement,\n type: claim.type || 'assertion',\n domain: FACT_AUDIT_DOMAIN,\n status:\n assessment.status === 'unsupported' ||\n assessment.status === 'needs_review'\n ? 'pending'\n : 'active',\n sourceCount: 0,\n confidence: claim.confidence ?? assessment.confidence ?? 0.5,\n tenantId: this.tenantId,\n metadata: JSON.stringify({\n auditRunId,\n generatedBy: FACT_AUDIT_GENERATED_BY,\n contentId: this.id,\n auditFactRole: 'article-claim',\n claimOnly: matchedFactIds.length === 0,\n }),\n });\n } else if (\n this.id &&\n isGeneratedArticleClaimFact(claimFact, this.id as string)\n ) {\n claimFact.status =\n assessment.status === 'unsupported' ||\n assessment.status === 'needs_review'\n ? 'pending'\n : 'active';\n claimFact.confidence =\n claim.confidence ?? assessment.confidence ?? claimFact.confidence;\n claimFact.updateMetadata?.({\n auditRunId,\n generatedBy: FACT_AUDIT_GENERATED_BY,\n contentId: this.id,\n auditFactRole: 'article-claim',\n claimOnly: matchedFactIds.length === 0,\n });\n await claimFact.save();\n }\n\n const articleEvidence = await evidences.upsertEvidence({\n factId: claimFact.id as string,\n status: 'supports',\n sourceKind: 'content',\n sourceId: this.id as string,\n sourceTitle: this.title || this.slug || (this.id as string),\n quote: claim.sourceExcerpt || claim.statement,\n locator: this.title || this.slug || '',\n extractionMethod: 'ai-article-claim',\n confidence: claim.confidence ?? assessment.confidence ?? 0.5,\n tenantId: this.tenantId,\n metadata: {\n auditRunId,\n generatedBy: FACT_AUDIT_GENERATED_BY,\n contentId: this.id,\n supportStatus: assessment.status,\n },\n });\n\n let supportingEvidenceIds = assessment.matchedEvidenceIds.filter(\n (evidenceId) => candidateEvidence.has(evidenceId),\n );\n for (const matchedFactId of matchedFactIds) {\n if (supportingEvidenceIds.length > 0) {\n continue;\n }\n const candidate = supportCandidates.find(\n (entry) => entry.id === matchedFactId,\n );\n supportingEvidenceIds = [\n ...supportingEvidenceIds,\n ...(candidate?.evidence || [])\n .map((entry) => entry.id)\n .filter((id: unknown): id is string => typeof id === 'string'),\n ];\n }\n supportingEvidenceIds = [...new Set(supportingEvidenceIds)];\n\n const linkMetadata = {\n auditRunId,\n generatedBy: FACT_AUDIT_GENERATED_BY,\n supportStatus: assessment.status,\n claimQuote: claim.sourceExcerpt || claim.statement,\n claimFactId: claimFact.id as string,\n articleEvidenceId: articleEvidence.id || null,\n supportingFactIds: matchedFactIds,\n supportingEvidenceIds,\n rationale: assessment.rationale,\n confidence: assessment.confidence ?? claim.confidence ?? null,\n };\n\n await this.safeAuditLink(\n claimFact.id as string,\n 'referenced_in',\n linkMetadata,\n );\n\n for (const matchedFactId of matchedFactIds) {\n await this.safeAuditLink(\n matchedFactId,\n assessment.status === 'contradicted' ? 'contradicts' : 'supports',\n {\n ...linkMetadata,\n supportingEvidenceIds,\n },\n );\n }\n\n if (assessment.status !== 'supported') {\n findings.push({\n severity: assessment.status === 'contradicted' ? 'error' : 'warning',\n title:\n assessment.status === 'contradicted'\n ? 'Contradicted article claim'\n : 'Unsupported article claim',\n detail: assessment.rationale || 'The claim needs editorial review.',\n factId: claimFact.id as string,\n quote: claim.sourceExcerpt || claim.statement,\n ruleId: 'fact-audit',\n });\n }\n }\n\n const reviews = await this.getContentReviewCollection();\n await reviews.createFromResult({\n contentId: this.id as string,\n kind: 'facts',\n policyKey: 'facts',\n reviewer: 'system',\n result: {\n status: findings.length > 0 ? 'flagged' : 'passed',\n summary:\n findings.length > 0\n ? `${findings.length} article claim(s) need review.`\n : 'Article claims are supported by available evidence.',\n findings,\n },\n metadata: {\n auditRunId,\n generatedBy: FACT_AUDIT_GENERATED_BY,\n warnings,\n },\n tenantId: this.tenantId,\n });\n\n const state = await this.getFactAuditState();\n return {\n ...state,\n repair: {\n auditRunId,\n claimsExtracted: claims.length,\n referenceFactsExtracted: referenceRepair.referenceFactsExtracted,\n warnings,\n },\n };\n }\n\n public async repairFactAuditAction(\n options: {\n maxReferenceFactsPerSource?: number;\n maxArticleClaims?: number;\n context?: string;\n } = {},\n ) {\n return this.repairFactAudit(options);\n }\n\n public async repairFactEvidence(\n options: FactAuditResourceRepairOptions = {},\n ) {\n await this.requireFactLinking('fact evidence repair');\n if (!this.id) {\n throw new Error('Cannot repair fact evidence for unsaved content');\n }\n\n const auditRunId = createFactAuditRunId(this.id as string);\n const sourceMaterials = await this.getFactAuditSourceMaterials();\n const sources = filterAuditSources(\n sourceMaterials.sources,\n options.sources,\n );\n const warnings: string[] = [];\n\n if (options.sources?.length && sources.length === 0) {\n warnings.push('No matching resource text was available for repair.');\n }\n\n const repair = await this.extractReferenceFactsForAudit(sources, {\n auditRunId,\n maxFactsPerSource: options.maxFactsPerSource,\n context: options.context,\n replaceGenerated: true,\n });\n warnings.push(...repair.warnings);\n\n const state = await this.getFactAuditState();\n return {\n ...state,\n evidenceRepair: {\n auditRunId,\n referenceFactsExtracted: repair.referenceFactsExtracted,\n repairedSources: repair.repairedSources,\n deletedEvidenceIds: repair.deletedEvidenceIds,\n deletedSourceIds: repair.deletedSourceIds,\n warnings,\n },\n };\n }\n\n public async repairFactEvidenceAction(\n options: FactAuditResourceRepairOptions = {},\n ) {\n return this.repairFactEvidence(options);\n }\n\n private async clearGeneratedSupportLinksForClaim(\n claimFactId: string,\n articleEvidenceId: string | null,\n ): Promise<void> {\n const links = await this.getFactLinks();\n\n for (const link of links) {\n if (\n link.relationship !== 'supports' &&\n link.relationship !== 'contradicts'\n ) {\n continue;\n }\n\n const metadata = getGeneratedFactAuditMetadata(link);\n if (!metadata) {\n continue;\n }\n\n const matchesEvidence =\n articleEvidenceId &&\n typeof metadata.articleEvidenceId === 'string' &&\n metadata.articleEvidenceId === articleEvidenceId;\n const matchesClaim =\n typeof metadata.claimFactId === 'string' &&\n metadata.claimFactId === claimFactId;\n\n if (matchesEvidence || matchesClaim) {\n await link.delete();\n }\n }\n }\n\n public async recheckFactClaims(options: FactAuditClaimRecheckOptions = {}) {\n await this.requireFactLinking('claim support recheck');\n if (!this.id) {\n throw new Error('Cannot recheck fact claims for unsaved content');\n }\n\n const auditRunId = createFactAuditRunId(this.id as string);\n const facts = await this.getFactCollection();\n const evidences = await this.getFactEvidenceCollection();\n const links = await this.getFactContentCollection();\n const claimIdFilter = new Set(options.claimFactIds || []);\n const { supportCandidates, candidateFactIds, candidateEvidence } =\n await this.getCurrentFactAuditSupportCandidates({\n sources: options.sources,\n sourceIds: options.sourceIds,\n maxCandidateEvidence: options.maxCandidateEvidence,\n });\n const claimLinks = (\n await links.byRight(this.id as string, { relationship: 'referenced_in' })\n )\n .map((link) => ({\n link,\n metadata: getGeneratedFactAuditMetadata(link),\n }))\n .filter(\n (\n entry,\n ): entry is { link: FactContent; metadata: Record<string, unknown> } =>\n entry.metadata !== null &&\n (claimIdFilter.size === 0 || claimIdFilter.has(entry.link.factId)),\n );\n const warnings: string[] = [];\n let recheckedClaims = 0;\n\n for (const { link, metadata } of claimLinks) {\n const claimFact = await facts.get({ id: link.factId });\n if (!claimFact) {\n continue;\n }\n\n const claimText =\n normalizeAuditText(metadata.claimQuote) ||\n normalizeAuditText(claimFact.textRefined) ||\n normalizeAuditText(claimFact.textRaw);\n if (!claimText) {\n continue;\n }\n\n let assessment: FactClaimSupportAssessment;\n try {\n assessment = await facts.assessClaimSupport(\n claimText,\n supportCandidates,\n { tenantId: this.tenantId },\n );\n } catch (error) {\n warnings.push(\n `Failed to recheck claim \"${claimText}\": ${errorMessage(error)}`,\n );\n assessment = {\n status: 'needs_review',\n matchedFactIds: [],\n matchedEvidenceIds: [],\n rationale: 'Support assessment failed.',\n confidence: undefined,\n };\n }\n\n const matchedFactIds = assessment.matchedFactIds.filter((factId) =>\n candidateFactIds.has(factId),\n );\n let supportStatus = assessment.status;\n if (\n (supportStatus === 'supported' || supportStatus === 'contradicted') &&\n matchedFactIds.length === 0\n ) {\n supportStatus = 'needs_review';\n }\n let supportingEvidenceIds = assessment.matchedEvidenceIds.filter(\n (evidenceId) => candidateEvidence.has(evidenceId),\n );\n if (supportingEvidenceIds.length === 0) {\n for (const matchedFactId of matchedFactIds) {\n const candidate = supportCandidates.find(\n (entry) => entry.id === matchedFactId,\n );\n supportingEvidenceIds.push(\n ...(candidate?.evidence || [])\n .map((entry) => entry.id)\n .filter((id: unknown): id is string => typeof id === 'string'),\n );\n }\n }\n supportingEvidenceIds = [...new Set(supportingEvidenceIds)];\n\n const articleEvidenceId =\n typeof metadata.articleEvidenceId === 'string'\n ? metadata.articleEvidenceId\n : null;\n const nextMetadata = {\n ...metadata,\n auditRunId,\n generatedBy: FACT_AUDIT_GENERATED_BY,\n supportStatus,\n supportingFactIds: matchedFactIds,\n supportingEvidenceIds,\n rationale: assessment.rationale,\n confidence: assessment.confidence ?? metadata.confidence ?? null,\n claimFactId: link.factId,\n };\n const existingMetadata = getLinkMetadata(link);\n if (existingMetadata.generatedBy === FACT_AUDIT_GENERATED_BY) {\n link.setMetadata?.(nextMetadata);\n } else {\n link.setMetadata?.({\n ...existingMetadata,\n factAudit: nextMetadata,\n });\n }\n await link.save();\n\n if (articleEvidenceId) {\n const articleEvidence = await evidences.get({ id: articleEvidenceId });\n if (articleEvidence) {\n articleEvidence.updateMetadata({\n auditRunId,\n supportStatus,\n });\n await articleEvidence.save();\n }\n }\n\n await this.clearGeneratedSupportLinksForClaim(\n link.factId,\n articleEvidenceId,\n );\n for (const matchedFactId of matchedFactIds) {\n await this.safeAuditLink(\n matchedFactId,\n supportStatus === 'contradicted' ? 'contradicts' : 'supports',\n {\n ...nextMetadata,\n articleEvidenceId,\n },\n );\n }\n\n recheckedClaims += 1;\n }\n\n const state = await this.getFactAuditState();\n return {\n ...state,\n claimRecheck: {\n auditRunId,\n recheckedClaims,\n candidateFacts: supportCandidates.length,\n candidateEvidence: candidateEvidence.size,\n warnings,\n },\n };\n }\n\n public async recheckFactClaimsAction(\n options: FactAuditClaimRecheckOptions = {},\n ) {\n return this.recheckFactClaims(options);\n }\n\n public async updateFactEvidenceStatus(\n options: FactEvidenceStatusUpdateOptions = {},\n ) {\n await this.requireFactLinking('evidence status update');\n if (!this.id) {\n throw new Error('Cannot update fact evidence for unsaved content');\n }\n\n const status = normalizeFactEvidenceStatus(options.status);\n if (!status) {\n throw new Error('A valid evidence status is required');\n }\n\n const requestedEvidenceIds = [\n ...new Set(\n (options.evidenceIds || []).filter(\n (id): id is string => typeof id === 'string' && id.length > 0,\n ),\n ),\n ];\n const evidences = await this.getFactEvidenceCollection();\n const sourceMaterials = await this.getFactAuditSourceMaterials();\n const allowedSourceKeys = new Set(\n sourceMaterials.sources.map(\n (source: FactAuditSourceMaterial) =>\n `${source.sourceKind}:${source.sourceId}`,\n ),\n );\n const allowedEvidenceIds: string[] = [];\n\n for (const evidenceId of requestedEvidenceIds) {\n const evidence = await evidences.get({ id: evidenceId });\n if (!evidence) {\n continue;\n }\n\n if (\n this.tenantId &&\n evidence.tenantId &&\n evidence.tenantId !== this.tenantId\n ) {\n continue;\n }\n\n const metadata = getEvidenceMetadata(evidence);\n const sourceKey = `${evidence.sourceKind || ''}:${\n evidence.sourceId || ''\n }`;\n if (\n metadata.contentId === this.id ||\n (evidence.sourceKind === 'content' && evidence.sourceId === this.id) ||\n allowedSourceKeys.has(sourceKey)\n ) {\n allowedEvidenceIds.push(evidenceId);\n }\n }\n\n const updated = await evidences.bulkUpdateStatus(\n allowedEvidenceIds,\n status,\n {\n reason: options.reason,\n },\n );\n const state = await this.getFactAuditState();\n\n return {\n ...state,\n evidenceStatusUpdate: {\n status,\n requestedEvidenceIds,\n updatedEvidenceIds: updated\n .map((entry) => entry.id)\n .filter((id: unknown): id is string => typeof id === 'string'),\n skippedEvidenceIds: requestedEvidenceIds.filter(\n (id) => !allowedEvidenceIds.includes(id),\n ),\n },\n };\n }\n\n public async updateFactEvidenceStatusAction(\n options: FactEvidenceStatusUpdateOptions = {},\n ) {\n return this.updateFactEvidenceStatus(options);\n }\n\n public async getFactAuditState(): Promise<FactAuditState> {\n if (!this.id) {\n return {\n counts: {\n total: 0,\n supported: 0,\n unsupported: 0,\n contradicted: 0,\n needs_review: 0,\n },\n claims: [],\n resourceClaims: [],\n warnings: [],\n generatedBy: FACT_AUDIT_GENERATED_BY,\n latestAuditRunId: null,\n };\n }\n\n const [facts, factLinks] = await Promise.all([\n this.getFacts({\n relationship: 'referenced_in',\n latestOnly: false,\n includeSuperseded: false,\n }),\n this.getFactLinks({ relationship: 'referenced_in' }),\n ]);\n const factMap = new Map(\n facts\n .filter((fact) => fact.id)\n .map((fact) => [fact.id as string, fact] as const),\n );\n const evidences = await this.getFactEvidenceCollection();\n const allFacts = await this.getFactCollection();\n const generatedLinks = factLinks\n .map((link) => ({\n link,\n metadata: getGeneratedFactAuditMetadata(link),\n }))\n .filter(\n (\n entry,\n ): entry is { link: FactContent; metadata: Record<string, unknown> } =>\n entry.metadata !== null,\n );\n const claims: FactAuditClaim[] = [];\n const resourceClaimsByKey = new Map<string, FactAuditResourceClaim>();\n const warnings: string[] = [];\n let latestAuditRunId: string | null = null;\n\n for (const { link, metadata } of generatedLinks) {\n const fact = factMap.get(link.factId);\n if (!fact) {\n continue;\n }\n\n // Opaque audit-link metadata values; cast at the read boundary.\n latestAuditRunId =\n (metadata.auditRunId as string | null) || latestAuditRunId;\n const status = (metadata.supportStatus ||\n 'needs_review') as FactClaimSupportStatus;\n const matchedFactIds = Array.isArray(metadata.supportingFactIds)\n ? metadata.supportingFactIds\n : [];\n const articleEvidenceId =\n typeof metadata.articleEvidenceId === 'string'\n ? metadata.articleEvidenceId\n : null;\n const supportingEvidenceIds = new Set(\n Array.isArray(metadata.supportingEvidenceIds)\n ? metadata.supportingEvidenceIds.filter(\n (id: unknown): id is string => typeof id === 'string',\n )\n : [],\n );\n const [allClaimEvidence, matchedFacts] = await Promise.all([\n evidences.getForFact(fact.id as string),\n Promise.all(\n matchedFactIds.map(async (factId: string) => {\n const matchedFact = await allFacts.get({ id: factId });\n const matchedEvidence = (await evidences.getForFact(factId)).filter(\n (entry) =>\n supportingEvidenceIds.size === 0\n ? entry.sourceKind !== 'content' || entry.sourceId !== this.id\n : supportingEvidenceIds.has(entry.id as string),\n );\n return matchedFact\n ? {\n fact: serializeFact(matchedFact),\n evidence: matchedEvidence.map((entry) => ({\n ...serializeFact(entry),\n metadata:\n typeof entry.getMetadata === 'function'\n ? entry.getMetadata()\n : {},\n })),\n }\n : null;\n }),\n ),\n ]);\n const claimEvidence = allClaimEvidence.filter((entry) =>\n articleEvidenceId\n ? entry.id === articleEvidenceId\n : entry.sourceKind === 'content' && entry.sourceId === this.id,\n );\n\n claims.push({\n id: fact.id as string,\n fact: serializeFact(fact),\n supportStatus: status,\n // Opaque audit-link metadata values; cast at the read boundary.\n claimQuote: (metadata.claimQuote as string | null) || null,\n rationale: (metadata.rationale as string | null) || null,\n confidence: (metadata.confidence as number | null) ?? null,\n relationship: link.relationship || null,\n linkMetadata: metadata,\n evidence: claimEvidence.map((entry) => ({\n ...serializeFact(entry),\n metadata:\n typeof entry.getMetadata === 'function' ? entry.getMetadata() : {},\n })),\n matchedFacts: matchedFacts.filter(\n Boolean,\n ) as FactAuditClaim['matchedFacts'],\n });\n }\n\n const generatedEvidence = await evidences.list({\n where: { tenantId: this.tenantId ?? null },\n });\n for (const evidence of generatedEvidence) {\n const metadata =\n typeof evidence.getMetadata === 'function'\n ? evidence.getMetadata()\n : {};\n if (\n metadata.generatedBy !== FACT_AUDIT_GENERATED_BY ||\n metadata.contentId !== this.id ||\n evidence.sourceKind === 'content'\n ) {\n continue;\n }\n\n const fact = await allFacts.get({ id: evidence.factId });\n if (!fact) {\n continue;\n }\n\n const key = [\n evidence.factId,\n evidence.sourceKind,\n evidence.sourceId,\n evidence.evidenceKey,\n ].join(':');\n const serializedEvidence = {\n ...serializeFact(evidence),\n metadata,\n };\n const existing = resourceClaimsByKey.get(key);\n if (existing) {\n existing.evidence.push(serializedEvidence);\n continue;\n }\n\n resourceClaimsByKey.set(key, {\n id: fact.id as string,\n fact: serializeFact(fact),\n sourceKind: evidence.sourceKind || null,\n sourceId: evidence.sourceId || null,\n sourceUrl: evidence.sourceUrl || null,\n sourceTitle: evidence.sourceTitle || null,\n locator: evidence.locator || null,\n quote: evidence.quote || null,\n status: evidence.status || 'supports',\n confidence: evidence.confidence ?? null,\n evidence: [serializedEvidence],\n });\n }\n\n const latestReview = (\n await this.getContentReviewCollection()\n ).getLatestForPolicyKey(this.id as string, 'facts');\n const review = await latestReview;\n const reviewMetadata =\n review && typeof review.getMetadata === 'function'\n ? review.getMetadata()\n : {};\n if (\n reviewMetadata.generatedBy === FACT_AUDIT_GENERATED_BY &&\n Array.isArray(reviewMetadata.warnings)\n ) {\n warnings.push(...reviewMetadata.warnings);\n }\n\n const counts = {\n total: claims.length,\n supported: 0,\n unsupported: 0,\n contradicted: 0,\n needs_review: 0,\n };\n for (const claim of claims) {\n counts[claim.supportStatus] += 1;\n }\n\n return {\n counts,\n claims,\n resourceClaims: [...resourceClaimsByKey.values()],\n warnings,\n generatedBy: FACT_AUDIT_GENERATED_BY,\n latestAuditRunId,\n };\n }\n\n public async getFactAuditStateAction() {\n return this.getFactAuditState();\n }\n\n public async getFactsState(\n options: { relationship?: FactContentRelationship } = {},\n ) {\n const governance = await this.resolveGovernance();\n if (!governance.isGoverned || !governance.factLinkingEnabled) {\n return {\n factIds: [],\n facts: [],\n factLinks: [],\n };\n }\n\n const relationship = options.relationship;\n const [facts, factLinks] = await Promise.all([\n this.getFacts({\n relationship,\n latestOnly: true,\n includeSuperseded: false,\n }),\n this.getFactLinks(relationship ? { relationship } : {}),\n ]);\n\n return {\n factIds: facts.map((fact) => fact.id).filter(Boolean),\n facts: facts.map(serializeFact),\n factLinks: factLinks.map(serializeFactLink),\n };\n }\n\n public async syncFactsState(\n options: {\n factIds?: string[];\n relationship?: FactContentRelationship;\n } = {},\n ) {\n const governance = await this.requireFactLinking('fact sync');\n const relationship =\n options.relationship || governance.defaultFactRelationship;\n const sync = await this.syncFacts(options.factIds || [], relationship);\n const state = await this.getFactsState({ relationship });\n return {\n ...state,\n sync,\n };\n }\n\n public async createVersion(options: CreateContentVersionOptions = {}) {\n const versions = await this.getContentVersionCollection();\n return versions.createSnapshot(this, options);\n }\n\n public async getVersions() {\n if (!this.id) {\n return [];\n }\n\n const versions = await this.getContentVersionCollection();\n return versions.listForContent(this.id as string);\n }\n\n public async restoreFromVersion(versionNumber: number) {\n const versions = await this.getContentVersionCollection();\n return versions.restoreIntoContent(this, versionNumber);\n }\n\n public async getReviews(kind?: RunContentReviewOptions['kind']) {\n if (!this.id) {\n return [];\n }\n\n const reviews = await this.getContentReviewCollection();\n return reviews.listForContent(this.id as string, kind);\n }\n\n public async listReviews(\n options: { kind?: RunContentReviewOptions['kind'] } = {},\n ) {\n const reviews = await this.getReviews(options.kind);\n return reviews.map(serializeContentReview);\n }\n\n public async getReviewRequirements(\n profileKey: string,\n governance?: ResolvedContentGovernance,\n ) {\n const resolvedGovernance = governance || (await this.resolveGovernance());\n return getContentReviewRequirements(\n profileKey,\n resolvedGovernance.availableProfiles,\n );\n }\n\n public async getGovernanceState(): Promise<ContentGovernanceState> {\n const governance = await this.resolveGovernance();\n\n if (!governance.isGoverned) {\n return {\n ...governance,\n reviewProfiles: [],\n };\n }\n\n return {\n ...governance,\n reviewProfiles: await this.listReviewProfilesAction(),\n };\n }\n\n public async getGovernanceStateAction() {\n return this.getGovernanceState();\n }\n\n public async listReviewProfilesAction() {\n const governance = await this.resolveGovernance();\n if (!governance.isGoverned) {\n return [];\n }\n\n return Promise.all(\n getContentReviewProfileKeys(governance.availableProfiles).map(\n (profileKey) => this.evaluateReviewProfile(profileKey),\n ),\n );\n }\n\n public async evaluateReviewProfile(\n profileKey: string,\n ): Promise<ContentReviewProfileEvaluation> {\n const governance = await this.resolveGovernance();\n const requirements = await this.getReviewRequirements(\n profileKey,\n governance,\n );\n\n if (requirements.length === 0) {\n return {\n profileKey,\n ready: true,\n complete: true,\n requirements: [],\n };\n }\n\n const reviews = await this.getContentReviewCollection();\n const reviewFingerprintCache = new Map<string, string>();\n const evaluatedRequirements = await Promise.all(\n requirements.map(async (requirement) => {\n if (!reviewFingerprintCache.has(requirement.policyKey)) {\n reviewFingerprintCache.set(\n requirement.policyKey,\n await this.buildReviewFingerprint(requirement.policyKey),\n );\n }\n\n const latestReview =\n this.id && requirement.policyKey\n ? await reviews.getLatestForPolicyKey(\n this.id as string,\n requirement.policyKey,\n )\n : null;\n const acceptedStatuses = getAcceptedContentReviewStatuses(requirement);\n const latestStatus = latestReview?.status ?? null;\n const latestMetadata =\n typeof latestReview?.getMetadata === 'function'\n ? latestReview.getMetadata()\n : {};\n const currentFingerprint =\n reviewFingerprintCache.get(requirement.policyKey) || null;\n const reviewedFingerprint =\n latestMetadata?.reviewFingerprint ||\n latestMetadata?.contentFingerprint ||\n null;\n const missing = !latestReview;\n const stale =\n !missing &&\n !!reviewedFingerprint &&\n reviewedFingerprint !== currentFingerprint;\n const executed =\n latestStatus !== null && latestStatus !== 'pending' && !stale;\n const satisfied =\n !stale &&\n latestStatus !== null &&\n acceptedStatuses.includes(latestStatus);\n\n return {\n kind: getContentReviewKind(\n requirement.policyKey,\n governance.reviewPolicies,\n ),\n policyKey: requirement.policyKey,\n label:\n requirement.label ||\n getContentReviewPolicy(\n requirement.policyKey,\n governance.reviewPolicies,\n )?.label ||\n requirement.policyKey,\n blocking: requirement.blocking === true,\n acceptedStatuses,\n missing,\n stale,\n executed,\n satisfied,\n latestReviewId: (latestReview?.id as string) || null,\n latestStatus,\n latestSummary: latestReview?.summary || null,\n };\n }),\n );\n\n return {\n profileKey,\n ready: evaluatedRequirements\n .filter((requirement) => requirement.blocking)\n .every((requirement) => requirement.satisfied),\n complete: evaluatedRequirements.every(\n (requirement) => requirement.executed,\n ),\n requirements: evaluatedRequirements,\n };\n }\n\n public async evaluateReviewProfileAction(\n options: { profileKey?: string } = {},\n ) {\n if (!options.profileKey) {\n throw new Error('profileKey is required');\n }\n\n return this.evaluateReviewProfile(options.profileKey);\n }\n\n public async isReadyForReviewProfile(profileKey: string): Promise<boolean> {\n const evaluation = await this.evaluateReviewProfile(profileKey);\n return evaluation.ready;\n }\n\n public async getPublishedTransparency() {\n if (!this.id) {\n return null;\n }\n\n const versions = await this.getContentVersionCollection();\n const latestPublicationVersion =\n await versions.getLatestPublishedForContent(this.id as string);\n\n return latestPublicationVersion?.getTransparency() || null;\n }\n\n public async getPublishedTransparencyAction() {\n return this.getPublishedTransparency();\n }\n\n public async previewTransparency() {\n const governance = await this.resolveGovernance();\n if (!governance.isGoverned || !governance.transparencyEnabled) {\n return null;\n }\n\n return this.buildTransparencySnapshot({\n snapshotKind: 'preview',\n governance,\n });\n }\n\n public async previewTransparencyAction() {\n return this.previewTransparency();\n }\n\n public async runReview(options: RunContentReviewOptions = {}) {\n const governance = await this.requireGovernance('review execution');\n\n if (!this.id) {\n throw new Error('Cannot review unsaved content');\n }\n\n const policyKey = options.policyKey || options.kind || 'custom';\n const policy = getContentReviewPolicy(policyKey, governance.reviewPolicies);\n const kind =\n options.kind ||\n getContentReviewKind(policyKey, governance.reviewPolicies);\n const facts =\n options.facts !== undefined\n ? options.facts\n : governance.factLinkingEnabled &&\n (kind === 'facts' || Boolean(options.factIds?.length))\n ? await this.getFacts({\n latestOnly: true,\n includeSuperseded: false,\n })\n : [];\n const filteredFacts =\n options.factIds && options.factIds.length > 0\n ? facts.filter((fact) => options.factIds?.includes(fact.id as string))\n : facts;\n const reviewPrompt = buildContentReviewPrompt({\n kind,\n content: this,\n facts: filteredFacts,\n policy,\n customInstructions: options.instructions,\n });\n const resolvedPrompt = await resolvePrompt(smrtContentReviewPrompt.key, {\n db: this.options.db,\n tenantId: this.tenantId,\n variables: {\n contentBody: this.body,\n contentDescription: this.description ?? '',\n contentId: this.id ?? '',\n contentTitle: this.title,\n kind,\n policyKey: policy?.key || kind,\n reviewPrompt,\n },\n });\n const reviewFingerprint = await this.buildReviewFingerprint(policyKey);\n const ai = this.ai as {\n message?: (\n prompt: string,\n options?: Record<string, unknown>,\n ) => Promise<string>;\n };\n if (!ai?.message) {\n throw new Error('AI client is not configured for content reviews');\n }\n\n const rawResponse = await ai.message(\n resolvedPrompt.text,\n promptMessageOptions(resolvedPrompt.ai),\n );\n const result = parseContentReviewResponse(rawResponse);\n const version =\n options.createVersion === false\n ? null\n : await this.createVersion({\n kind: 'review',\n summary: result.summary,\n metadata: {\n kind,\n policyKey,\n reviewFingerprint,\n },\n });\n\n const reviews = await this.getContentReviewCollection();\n return reviews.createFromResult({\n contentId: this.id as string,\n contentVersionId: version?.id as string | undefined,\n kind,\n policyKey,\n reviewer: options.reviewer || 'system',\n result,\n metadata: {\n ...(options.metadata || {}),\n prompt: resolvedPrompt.text,\n rawResponse,\n reviewFingerprint,\n factIds: filteredFacts.map((fact) => fact.id),\n },\n tenantId: this.tenantId,\n });\n }\n\n public async runReviewAction(options: RunContentReviewOptions = {}) {\n let review: ContentReview;\n\n if (options.kind === 'facts') {\n review = await this.reviewFacts(options);\n } else if (options.kind === 'safety') {\n review = await this.reviewSafety(options);\n } else {\n review = await this.runReview(options);\n }\n\n return serializeContentReview(review);\n }\n\n public async reviewFacts(\n options: Omit<RunContentReviewOptions, 'kind'> = {},\n ) {\n return this.runReview({\n ...options,\n kind: 'facts',\n policyKey: options.policyKey || 'facts',\n });\n }\n\n public async reviewSafety(\n options: Omit<RunContentReviewOptions, 'kind'> = {},\n ) {\n const governance = await this.requireGovernance('safety review');\n const safetyPolicy = getContentReviewPolicy(\n options.policyKey || 'safety',\n governance.reviewPolicies,\n );\n const baseInstructions = safetyPolicy?.instructions || '';\n\n return this.runReview({\n ...options,\n kind: 'safety',\n policyKey: options.policyKey || 'safety',\n instructions:\n options.instructions && baseInstructions\n ? `${baseInstructions}\\n\\nAdditional app-level guidance:\\n${options.instructions}`\n : options.instructions || baseInstructions,\n });\n }\n\n public async getCorrections() {\n if (!this.id) {\n return [];\n }\n\n const corrections = await this.getContentCorrectionCollection();\n return corrections.listForContent(this.id as string);\n }\n\n public async listCorrections() {\n const corrections = await this.getCorrections();\n return corrections.map(serializeContentCorrection);\n }\n\n public async issueCorrection(options: IssueContentCorrectionOptions) {\n const governance = await this.requireGovernance('corrections');\n\n if (!this.id) {\n throw new Error('Cannot issue a correction for unsaved content');\n }\n\n let replacementFactId = '';\n if (\n governance.factLinkingEnabled &&\n options.factId &&\n options.correctedFactText\n ) {\n const facts = await this.getFactCollection();\n const existing = await facts.get({ id: options.factId });\n if (!existing) {\n throw new Error(`Fact not found for correction: ${options.factId}`);\n }\n\n // Create the correction branch directly so editorial corrections do not\n // block on synchronous embedding generation inside facts.branch().\n const replacement = await facts.create({\n textRefined: options.correctedFactText,\n textRaw: options.correctedFactText,\n type: existing.getType(),\n domain: existing.domain,\n status: 'active',\n tenantId: existing.tenantId ?? this.tenantId ?? null,\n previousFactId: options.factId,\n evolutionType: 'correction',\n });\n existing.status = 'superseded';\n await existing.save();\n replacementFactId = replacement.id as string;\n await this.addFact(replacementFactId);\n }\n\n const version =\n options.createVersion === false\n ? null\n : await this.createVersion({\n kind: 'correction',\n summary: options.summary,\n metadata: {\n factId: options.factId || null,\n replacementFactId: replacementFactId || null,\n },\n });\n const correctionDraft =\n options.createVersion === false\n ? null\n : await this.buildCorrectionDraftSnapshot(options, replacementFactId);\n const draftVersion =\n options.createVersion === false || !correctionDraft\n ? null\n : await this.createVersion({\n kind: 'draft',\n summary: `Auto-created correction draft: ${options.summary}`,\n snapshot: correctionDraft.snapshot,\n metadata: {\n ...correctionDraft.metadata,\n sourceCorrectionVersionId: (version?.id as string) || null,\n sourceCorrectionVersionNumber: version?.version ?? null,\n },\n });\n\n const corrections = await this.getContentCorrectionCollection();\n const shouldPublish = options.publish ?? this.status === 'published';\n return corrections.issue({\n contentId: this.id as string,\n contentVersionId: (version?.id as string) || '',\n factId: options.factId || '',\n replacementFactId,\n correctionType: options.correctionType || 'fact',\n status: shouldPublish ? 'published' : 'draft',\n summary: options.summary,\n incorrectText: options.incorrectText || '',\n correctedText: options.correctedText || options.correctedFactText || '',\n publicNote: options.publicNote || '',\n metadata: {\n ...(options.metadata || {}),\n autoGeneratedDraft: Boolean(draftVersion),\n draftVersionId: (draftVersion?.id as string) || null,\n draftVersionNumber: draftVersion?.version ?? null,\n sourceCorrectionVersionId: (version?.id as string) || null,\n sourceCorrectionVersionNumber: version?.version ?? null,\n correctionProfileKey: governance.correctionProfileKey || null,\n },\n tenantId: this.tenantId,\n publishedAt: shouldPublish ? new Date() : null,\n });\n }\n\n public async issueCorrectionAction(options: IssueContentCorrectionOptions) {\n const correction = await this.issueCorrection(options);\n return serializeContentCorrection(correction);\n }\n\n public async listVersions() {\n const versions = await this.getVersions();\n return versions.map(serializeContentVersion);\n }\n\n public async mutateVersionAction(\n options: CreateContentVersionOptions & {\n action?: string;\n versionNumber?: number | string;\n } = {},\n ) {\n if (options.action === 'restore') {\n const versionNumber = Number(options.versionNumber);\n if (!Number.isFinite(versionNumber)) {\n throw new Error('versionNumber is required to restore a version');\n }\n\n const restored = await this.restoreFromVersion(versionNumber);\n return serializeContent(restored);\n }\n\n const version = await this.createVersion(options);\n return serializeContentVersion(version);\n }\n\n /**\n * Note: toJSON() is inherited from SmrtObject\n *\n * The parent implementation handles:\n * - STI discriminator (_meta_type) for polymorphic queries\n * - Meta field extraction (_meta_data) for child-specific fields\n * - Automatic serialization of all fields from manifest\n *\n * DO NOT override toJSON() unless you call super.toJSON() first.\n * See issue #377 for details on why this override was removed.\n */\n\n // ============================================\n // Category Helper Methods\n // ============================================\n\n /**\n * Get category segments as array\n * @example 'politics/local' -> ['politics', 'local']\n */\n getCategorySegments(): string[] {\n if (!this.category) return [];\n return this.category.split('/').filter(Boolean);\n }\n\n /**\n * Get parent category path\n * @example 'politics/local/town' -> 'politics/local'\n * @example 'politics' -> null\n */\n getParentCategory(): string | null {\n const segments = this.getCategorySegments();\n if (segments.length <= 1) return null;\n return segments.slice(0, -1).join('/');\n }\n\n /**\n * Get root (top-level) category\n * @example 'politics/local/town' -> 'politics'\n */\n getRootCategory(): string | null {\n const segments = this.getCategorySegments();\n return segments[0] || null;\n }\n\n /**\n * Get all ancestor category paths (for breadcrumbs)\n * @example 'politics/local' -> ['politics', 'politics/local']\n */\n getAncestorPaths(): string[] {\n const segments = this.getCategorySegments();\n return segments.map((_, i) => segments.slice(0, i + 1).join('/'));\n }\n\n /**\n * Check if content belongs to a category (optionally including subcategories)\n * @param categoryPath - Category to check\n * @param includeChildren - If true, matches 'politics' for content in 'politics/local'\n */\n isInCategory(categoryPath: string, includeChildren = true): boolean {\n if (!this.category) return false;\n if (includeChildren) {\n return (\n this.category === categoryPath ||\n this.category.startsWith(`${categoryPath}/`)\n );\n }\n return this.category === categoryPath;\n }\n\n // ============================================\n // Asset Relationship Methods\n // ============================================\n\n /**\n * Get all assets associated with this content\n * @param relationship - Optional filter by relationship type (e.g., 'thumbnail', 'attachment')\n * @returns Promise resolving to array of assets\n */\n async getAssets(relationship?: string): Promise<Asset[]> {\n if (!this.id) {\n return [];\n }\n\n return this.resolveAssetsForLinks(\n await this.getContentAssetLinks(relationship),\n );\n }\n\n /**\n * Add an asset to this content with a relationship type\n * @param asset - The asset to associate\n * @param relationship - Relationship type (e.g., 'thumbnail', 'attachment', 'inline')\n * @param sortOrder - Optional sort order for display\n */\n async addAsset(\n asset: Asset,\n relationship = 'attachment',\n sortOrder = 0,\n ): Promise<void> {\n if (!this.id || !asset.id) {\n throw new Error('Cannot associate unsaved content or asset');\n }\n\n // Validate relationship - must start with letter/underscore, contain only alphanumeric and underscores\n if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(relationship)) {\n throw new Error(\n `Invalid relationship type \"${relationship}\"; must start with a letter or underscore and contain only letters, digits, and underscores`,\n );\n }\n\n // Validate sortOrder is a reasonable integer\n if (\n !Number.isInteger(sortOrder) ||\n sortOrder < 0 ||\n sortOrder > 2147483647\n ) {\n throw new Error(\n `Invalid sortOrder \"${sortOrder}\"; must be a non-negative integer`,\n );\n }\n\n const contentAssets = await this.getContentAssetCollection();\n await contentAssets.attach(this.id, asset.id, {\n relationship,\n sortOrder,\n tenantId: this.tenantId,\n });\n }\n\n /**\n * Remove an asset from this content\n * @param assetId - ID of the asset to remove\n * @param relationship - Optional specific relationship to remove (removes all if not specified)\n */\n async removeAsset(assetId: string, relationship?: string): Promise<void> {\n if (!this.id) {\n return;\n }\n\n try {\n const contentAssets = await this.getContentAssetCollection();\n await contentAssets.detach(\n this.id,\n assetId,\n relationship ? { relationship } : {},\n );\n } catch (error) {\n if (!isMissingTableError(error, 'content_assets')) {\n throw error;\n }\n }\n }\n\n // ============================================\n // Metadata Accessors (MetadataAccessor contract)\n // ============================================\n\n /**\n * Get the full metadata record. Always returns a plain object — never\n * `null`, never an array — so callers can safely read nested keys without\n * defensive checks.\n *\n * Pure read with no side-effect on `this.metadata`: if the field is\n * currently `null` (e.g. fresh from the DB) or non-record-shaped, an\n * empty object is returned but the field is **not** mutated. This avoids\n * accidentally marking the object dirty during a read, which would\n * otherwise cause SmrtObject's save lifecycle to write `{}` back over a\n * NULL column on the next save. Callers that want to normalise the\n * stored field should use {@link Content.setMetadata}.\n */\n getMetadata(): Record<string, unknown> {\n return isPlainMetadataRecord(this.metadata) ? this.metadata : {};\n }\n\n /**\n * Replace the full metadata record. Passing `null`/`undefined` (or any\n * non-record value such as an array) clears it to an empty object so\n * downstream readers can rely on the field always being a plain object.\n */\n setMetadata(metadata: Record<string, unknown> | null | undefined): void {\n this.metadata = isPlainMetadataRecord(metadata) ? { ...metadata } : {};\n }\n\n /**\n * Shallow-merge a patch over the current metadata. Returns the resulting\n * record so callers can chain reads without re-reading the field. Unlike\n * {@link Content.getMetadata}, this method does intentionally write back\n * to `this.metadata` because the merge is a write.\n */\n updateMetadata(\n patch: Partial<Record<string, unknown>>,\n ): Record<string, unknown> {\n const next = { ...this.getMetadata(), ...(patch ?? {}) };\n this.metadata = next;\n return next;\n }\n\n // ============================================\n // Thumbnail Convenience Methods\n // ============================================\n\n /**\n * Get the thumbnail image for this content\n * @returns Promise resolving to the thumbnail Image or null\n */\n async getThumbnail(): Promise<Image | null> {\n if (!this.thumbnailAssetId) {\n return null;\n }\n\n const images = await ImageCollection.create({\n db: this.options?.db,\n });\n\n return images.get({ id: this.thumbnailAssetId });\n }\n\n /**\n * Set the thumbnail image for this content\n * @param image - The image to set as thumbnail\n */\n async setThumbnail(image: Image): Promise<void> {\n // Add as asset with 'thumbnail' relationship\n await this.addAsset(image, 'thumbnail', 0);\n\n // Update thumbnailAssetId\n this.thumbnailAssetId = image.id ?? null;\n await this.save();\n }\n\n /**\n * Generate a thumbnail for this content using the specified strategy\n *\n * @param options - Thumbnail generation options including strategy\n * @returns Promise resolving to the generated Image\n *\n * @example Headline card thumbnail\n * ```typescript\n * const thumbnail = await content.generateThumbnail({\n * strategy: 'headline-card',\n * brandColor: '#1a56db',\n * logoUrl: 'https://example.com/logo.png'\n * });\n * ```\n *\n * @example Static map thumbnail (requires metadata.latitude/longitude)\n * ```typescript\n * const thumbnail = await content.generateThumbnail({\n * strategy: 'static-map',\n * mapProvider: 'mapbox'\n * });\n * ```\n *\n * @example AI-generated thumbnail\n * ```typescript\n * const thumbnail = await content.generateThumbnail({\n * strategy: 'ai-generate'\n * });\n * ```\n */\n async generateThumbnail(options: ThumbnailOptions): Promise<Image> {\n const generator = new ThumbnailGenerator(this, this.options);\n const image = await generator.generate(options);\n await this.setThumbnail(image);\n return image;\n }\n}\n","import { definePrompt } from '@happyvertical/smrt-prompts';\n\nexport const contentEditorSessionPrompt = definePrompt({\n key: 'content.chat.contentEditorSession',\n template:\n 'You are an AI assistant collaborating with the user to edit and improve a specific piece of content.',\n ai: {\n temperature: 0.7,\n maxTokens: 2000,\n },\n editable: {\n template: true,\n profile: true,\n model: true,\n params: true,\n },\n});\n\nexport const contentEditorInteractionPrompt = definePrompt({\n key: 'content.chat.contentEditorInteraction',\n template: `CURRENT CONTENT FORM STATE:\n- title: {title}\n- description: {description}\n- type: {type}\n- status: {status}\n- state: {state}\n- body:\n{body}\n{references}\n\nINSTRUCTIONS FOR CO-AUTHORING:\nYou are a content co-author. You can update any of the above fields.\n\nWhen you want to make changes to the content, output a JSON code block with a top-level \"fields\" object containing only the fields you want to change.\n\nValid field names: title, description, type, status, state, body.\nValid status values: draft, published, archived.\nValid state values: active, highlighted, deprecated.\nValid type values: article, document, mirror.\n\nRULES:\n- Only include fields you are actually changing.\n- If the user asks to write or rewrite content, update the \"body\" field.\n- If the user asks to change the title, update the \"title\" field.\n- You can change multiple fields at once.\n- Always respond conversationally before the JSON block.\n- The JSON block will be automatically applied to the editor.`,\n ai: {\n temperature: 0.7,\n maxTokens: 2000,\n },\n editable: {\n template: true,\n profile: true,\n model: true,\n params: true,\n },\n});\n","import type { ResolvedPrompt } from '@happyvertical/smrt-prompts';\n\ntype SessionContext = Record<string, unknown>;\n\nexport interface ContentChatAISelection {\n profile: string | null;\n provider: string | null;\n model: string | null;\n allowedModels: string[] | null;\n temperature: number | null;\n maxTokens: number | null;\n}\n\nexport interface ContentEditorInteractionInput {\n fields?: Record<string, unknown> | null;\n currentEditorState?: unknown;\n references?: string | null;\n}\n\nconst CONTENT_PROMPT_DELIMITER = 'SMRT_CONTENT_FIELD';\n\nfunction readString(\n context: SessionContext,\n key: keyof ContentChatAISelection,\n): string | null {\n const value = context[key];\n return typeof value === 'string' && value.length > 0 ? value : null;\n}\n\nfunction readNumber(\n context: SessionContext,\n key: keyof ContentChatAISelection,\n): number | null {\n const value = context[key];\n return typeof value === 'number' ? value : null;\n}\n\nexport function inferProviderFromModel(model: string): string {\n const normalized = model.toLowerCase();\n const providerPrefix = normalized.match(/^([a-z0-9_-]+)\\//)?.[1];\n if (providerPrefix === 'openrouter') {\n return 'openrouter';\n }\n if (providerPrefix === 'anthropic') {\n return 'anthropic';\n }\n if (providerPrefix === 'gemini' || providerPrefix === 'google') {\n return 'gemini';\n }\n if (providerPrefix === 'openai') {\n return 'openai';\n }\n\n const modelTokens = normalized.split(/[^a-z0-9]+/).filter(Boolean);\n if (\n modelTokens.includes('claude') ||\n modelTokens.includes('sonnet') ||\n modelTokens.includes('haiku') ||\n modelTokens.includes('opus')\n ) {\n return 'anthropic';\n }\n\n if (modelTokens.includes('gemini')) {\n return 'gemini';\n }\n\n return 'openai';\n}\n\nexport function getContentChatAISelection(\n context: SessionContext,\n): ContentChatAISelection {\n const allowedModels = context.allowedModels;\n return {\n profile: readString(context, 'profile'),\n provider: readString(context, 'provider'),\n model: readString(context, 'model'),\n allowedModels:\n Array.isArray(allowedModels) &&\n allowedModels.every((value) => typeof value === 'string')\n ? allowedModels\n : null,\n temperature: readNumber(context, 'temperature'),\n maxTokens: readNumber(context, 'maxTokens'),\n };\n}\n\nexport function resolveContentChatModelSelection(\n context: SessionContext,\n requestedModel: string | null | undefined,\n fallbackModel: string,\n): { model: string; provider: string } {\n const stored = getContentChatAISelection(context);\n const model = requestedModel || stored.model || fallbackModel;\n const provider =\n stored.provider && stored.model && model === stored.model\n ? stored.provider\n : inferProviderFromModel(model);\n\n return { model, provider };\n}\n\nexport function buildContentChatModelUpdates(\n context: SessionContext,\n requestedModel: string | null | undefined,\n fallbackModel: string,\n): Record<string, string | null> {\n const stored = getContentChatAISelection(context);\n const { model, provider } = resolveContentChatModelSelection(\n context,\n requestedModel,\n fallbackModel,\n );\n\n return {\n model,\n provider,\n ...(stored.profile && stored.model && model !== stored.model\n ? { profile: null }\n : {}),\n };\n}\n\nexport function buildContentEditorSessionContext(\n contentId: string,\n prompt: ResolvedPrompt,\n): SessionContext {\n return {\n contentId,\n ...(prompt.ai.profile ? { profile: prompt.ai.profile } : {}),\n ...(prompt.ai.provider ? { provider: prompt.ai.provider } : {}),\n ...(prompt.ai.model ? { model: prompt.ai.model } : {}),\n ...(prompt.ai.allowedModels\n ? { allowedModels: prompt.ai.allowedModels }\n : {}),\n ...(prompt.ai.temperature !== undefined\n ? { temperature: prompt.ai.temperature }\n : {}),\n ...(prompt.ai.maxTokens !== undefined\n ? { maxTokens: prompt.ai.maxTokens }\n : {}),\n };\n}\n\nfunction displayValue(value: unknown, fallback = '(empty)'): string {\n if (typeof value === 'string') {\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : fallback;\n }\n\n if (value === undefined || value === null) {\n return fallback;\n }\n\n return String(value);\n}\n\nfunction delimitPromptValue(name: string, value: string): string {\n // Strip any forged SMRT_ delimiter markers from the user value so it can't\n // close the wrapper early or open a fake field. The previous `[^>]*` stopped\n // at the first `>` (so `<<<SMRT_X>injected>>>` slipped through) and was\n // case-sensitive (so `<<<smrt_...>>>` slipped through). `[\\s\\S]*?` is\n // non-greedy and `>`-tolerant, and the `i` flag closes the case bypass\n // (#1387 minor).\n const sanitizedValue = value.replace(/<<<\\s*(?:END_)?SMRT_[\\s\\S]*?>>>/gi, '');\n return `<<<${CONTENT_PROMPT_DELIMITER} name=${name}>>>\\n${sanitizedValue}\\n<<<END_${CONTENT_PROMPT_DELIMITER}>>>`;\n}\n\nexport function buildContentEditorInteractionVariables(\n input: ContentEditorInteractionInput,\n): Record<string, string> {\n const fields = input.fields ?? {};\n\n return {\n title: delimitPromptValue('title', displayValue(fields.title)),\n description: delimitPromptValue(\n 'description',\n displayValue(fields.description),\n ),\n type: displayValue(fields.type, 'article'),\n status: displayValue(fields.status, 'draft'),\n state: displayValue(fields.state, 'active'),\n body: delimitPromptValue(\n 'body',\n displayValue(fields.body ?? input.currentEditorState),\n ),\n references: input.references ?? '',\n };\n}\n","import { type AIClientOptions, getAI } from '@happyvertical/ai';\nimport { ChatService } from '@happyvertical/smrt-chat';\nimport { sendAgentReply } from '@happyvertical/smrt-chat/internal/agent-runtime';\nimport {\n type ResolvedPrompt,\n resolvePrompt,\n} from '@happyvertical/smrt-prompts';\nimport type { DatabaseInterface } from '@happyvertical/sql';\nimport { sanitizeHtml, stripHtml } from './body-format';\nimport {\n contentEditorInteractionPrompt,\n contentEditorSessionPrompt,\n} from './content-chat-prompts';\nimport {\n buildContentChatModelUpdates,\n buildContentEditorInteractionVariables,\n buildContentEditorSessionContext,\n getContentChatAISelection,\n resolveContentChatModelSelection,\n} from './content-chat-session';\n\nconst CONTENT_EDITOR_AGENT_ID = 'content_editor';\nconst REFERENCE_TITLE_MAX_LENGTH = 200;\nconst REFERENCE_BODY_MAX_LENGTH = 2000;\nconst MAX_REFERENCE_IDS = 20;\n\nexport type ContentChatAIConfig = AIClientOptions & {\n apiKey?: string;\n allowedModels?: string[];\n model?: string;\n defaultModel?: string;\n provider?: string;\n type?: string;\n};\n\nexport interface ContentChatCollectionLike {\n db: DatabaseInterface;\n // Accepts either a raw id or a bound `{ id, tenantId }` filter so the content\n // lookup can be tenant-bound at the query level (S5 #1392) rather than doing a\n // cross-tenant `get(id)` followed only by a post-filter. A real SmrtCollection\n // satisfies this — its `get` takes `string | Record<string, any>`.\n get(filter: string | Record<string, unknown>): Promise<unknown>;\n}\n\nexport interface ContentChatSessionInput {\n db: DatabaseInterface;\n contents?: ContentChatCollectionLike;\n tenantId?: string | null;\n profileId?: string | null;\n contentId: string;\n resolvePromptFn?: typeof resolvePrompt;\n}\n\nexport interface CreateContentChatThreadInput extends ContentChatSessionInput {\n title: string;\n sessionId: string;\n model?: string | null;\n initializeChatCollections?: () => Promise<void>;\n}\n\nexport interface ListContentChatThreadMessagesInput {\n db: DatabaseInterface;\n contents?: ContentChatCollectionLike;\n tenantId?: string | null;\n profileId?: string | null;\n contentId: string;\n threadId: string;\n}\n\nexport interface SendContentChatThreadMessageInput {\n contents: ContentChatCollectionLike;\n tenantId?: string | null;\n profileId?: string | null;\n contentId: string;\n threadId: string;\n content: string;\n sessionId: string;\n model?: string | null;\n currentEditorState?: unknown;\n referenceIds?: unknown;\n formFields?: Record<string, unknown> | null;\n aiConfig?: ContentChatAIConfig | null;\n env?: Record<string, string | undefined>;\n resolvePromptFn?: typeof resolvePrompt;\n getAIClient?: typeof getAI;\n resolveAI?: (\n input: ResolveContentChatAIInput,\n ) => Promise<ResolvedContentChatAI | null> | ResolvedContentChatAI | null;\n}\n\nexport interface ResolveContentChatAIInput {\n aiConfig: ContentChatAIConfig;\n env: Record<string, string | undefined>;\n sessionContext: Record<string, unknown>;\n requestedModel?: string | null;\n interactionPrompt: ResolvedPrompt;\n}\n\nexport interface ResolvedContentChatAI {\n clientOptions: ContentChatAIConfig;\n model: string;\n provider?: string | null;\n profile?: string | null;\n temperature?: number | null;\n maxTokens?: number | null;\n}\n\nfunction resolveTenantScope(value: string | null | undefined): string | null {\n return asNonEmptyString(value);\n}\n\nfunction resolveChatTenantId(value: string | null | undefined): string {\n return resolveTenantScope(value) ?? 'global';\n}\n\nfunction resolveProfileId(value: string | null | undefined): string {\n return value || 'system';\n}\n\nfunction asNonEmptyString(value: unknown): string | null {\n return typeof value === 'string' && value.trim().length > 0\n ? value.trim()\n : null;\n}\n\nfunction parseJsonObject(value: unknown): Record<string, unknown> {\n if (value && typeof value === 'object' && !Array.isArray(value)) {\n return value as Record<string, unknown>;\n }\n if (typeof value !== 'string' || value.length === 0) {\n return {};\n }\n try {\n const parsed = JSON.parse(value) as unknown;\n return parsed && typeof parsed === 'object' && !Array.isArray(parsed)\n ? (parsed as Record<string, unknown>)\n : {};\n } catch {\n return {};\n }\n}\n\nfunction getSessionContext(session: unknown): Record<string, unknown> {\n const candidate = session as {\n getSessionContext?: () => Record<string, unknown>;\n sessionContext?: unknown;\n };\n return typeof candidate.getSessionContext === 'function'\n ? candidate.getSessionContext()\n : parseJsonObject(candidate.sessionContext);\n}\n\nfunction isActiveSession(session: unknown): boolean {\n const candidate = session as { isActive?: () => boolean; status?: string };\n return typeof candidate?.isActive === 'function'\n ? candidate.isActive()\n : candidate?.status === 'active';\n}\n\nfunction isSchemaMissingError(error: unknown): boolean {\n const message = String((error as { message?: unknown })?.message ?? '');\n return (\n (error as { code?: string })?.code === 'DB_SCHEMA_MISSING' ||\n /^no such table:\\s+(?:agent_sessions|chat_(?:rooms|threads|messages|participants|reactions))\\b/i.test(\n message,\n ) ||\n /relation [\"']?(?:agent_sessions|chat_(?:rooms|threads|messages|participants|reactions))[\"']? does not exist/i.test(\n message,\n )\n );\n}\n\nexport function contentChatSessionMatchesContent(\n session: unknown,\n contentId: string,\n): boolean {\n const context = getSessionContext(session);\n return asNonEmptyString(context.contentId) === contentId;\n}\n\n/**\n * Stable agent-session key scoping a content-editor session to its content\n * (S5 #1392).\n *\n * `createAgentSession` reuses ANY active session for the same\n * agent/profile/tenant unless a `sessionKey` is supplied. The content-editor\n * agent (`content_editor`) opens a distinct conversation per content, so a\n * keyless create would reuse — and the handler would then REWRITE — a session\n * created for a different content, returning the other content's room/threads.\n * Keying the session on the content id makes a new content always create a\n * distinct session/room.\n */\nexport function contentChatSessionKey(contentId: string): string {\n return `content:${contentId}`;\n}\n\n/**\n * Tenant-bound content lookup (S5 #1392).\n *\n * Binds `tenantId` (including the `null` \"global\" scope) into the lookup itself\n * so a content row from another tenant can never be RESOLVED first and only\n * rejected after the fact. The `referenceBelongsToTenant` post-filter at every\n * call site remains as defense-in-depth.\n */\nfunction getContentForTenant(\n contents: ContentChatCollectionLike,\n tenantScope: string | null,\n id: string,\n): Promise<unknown> {\n return contents.get({ id, tenantId: tenantScope });\n}\n\nasync function assertContentExistsForTenant(\n contents: ContentChatCollectionLike | undefined,\n tenantScope: string | null,\n contentId: string,\n): Promise<void> {\n if (!contents) {\n return;\n }\n\n const content = await getContentForTenant(contents, tenantScope, contentId);\n if (!content || !referenceBelongsToTenant(content, tenantScope)) {\n throw new Error('Content not found');\n }\n}\n\nexport function contentChatSessionIsAuthorized(\n session: unknown,\n input: {\n profileId: string;\n contentId: string;\n },\n): boolean {\n const candidate = session as {\n agentId?: string;\n participantProfileId?: string;\n };\n return (\n Boolean(session) &&\n isActiveSession(session) &&\n candidate.agentId === CONTENT_EDITOR_AGENT_ID &&\n candidate.participantProfileId === input.profileId &&\n contentChatSessionMatchesContent(session, input.contentId)\n );\n}\n\nexport function contentChatMessageToJSON(\n message: unknown,\n): Record<string, unknown> {\n return typeof (message as { toJSON?: () => unknown })?.toJSON === 'function'\n ? ((message as { toJSON: () => unknown }).toJSON() as Record<\n string,\n unknown\n >)\n : (message as Record<string, unknown>);\n}\n\nexport function serializeContentChatMessageForUI(\n message: unknown,\n): Record<string, unknown> {\n const json = contentChatMessageToJSON(message);\n return {\n ...json,\n senderName: json.role === 'user' ? 'You' : 'AI Assistant',\n senderAvatarUrl: json.senderAvatarUrl || '',\n };\n}\n\nexport async function getOrCreateContentEditorChatSession(\n input: ContentChatSessionInput,\n) {\n const tenantScope = resolveTenantScope(input.tenantId);\n const tenantId = resolveChatTenantId(input.tenantId);\n const profileId = resolveProfileId(input.profileId);\n const chatService = await ChatService.create({ tenantId, db: input.db });\n await chatService.initialize();\n await assertContentExistsForTenant(\n input.contents,\n tenantScope,\n input.contentId,\n );\n\n let activeSession = null;\n try {\n // Tenant-bound session list via the ChatService facade (S5 #1392): the raw\n // `agentSessions.list({ where })` reach-in was tenant-UNBOUND and could\n // surface a session from another tenant before authorization.\n const agentSessions = await chatService.findActiveAgentSessions({\n tenantId,\n agentId: CONTENT_EDITOR_AGENT_ID,\n participantProfileId: profileId,\n });\n activeSession =\n agentSessions.find((session: unknown) =>\n contentChatSessionMatchesContent(session, input.contentId),\n ) ?? null;\n } catch (error) {\n if (!isSchemaMissingError(error)) {\n throw error;\n }\n // Chat tables may not exist yet. createAgentSession will surface the\n // concrete schema error if the runtime cannot create/use them.\n }\n\n if (!activeSession) {\n const resolvedPrompt = await (input.resolvePromptFn ?? resolvePrompt)(\n contentEditorSessionPrompt.key,\n {\n db: input.db,\n tenantId,\n },\n );\n // Scope the session to this content (S5 #1392) so a new contentId can never\n // reuse — and have its context rewritten over — a session/room created for a\n // different content. The handler-side `contentChatSessionMatchesContent`\n // filter above already narrows reads; this binds the create/reuse path too.\n const { session } = await chatService.createAgentSession({\n tenantId,\n agentId: CONTENT_EDITOR_AGENT_ID,\n actorProfileId: profileId,\n systemPrompt: resolvedPrompt.text,\n sessionKey: contentChatSessionKey(input.contentId),\n });\n await session.updateSessionContext(\n buildContentEditorSessionContext(input.contentId, resolvedPrompt),\n );\n activeSession = session;\n }\n\n let threads: unknown[] = [];\n try {\n const chatRoomId = (activeSession as { chatRoomId?: string | null })\n .chatRoomId;\n if (!chatRoomId) {\n throw new Error('Agent session is missing a chat room');\n }\n // Membership- and tenant-gated thread list via the facade (S5 #1392); the\n // editor (profileId) is the room owner, so the membership check passes.\n threads = await chatService.listRoomThreads({\n roomId: chatRoomId,\n actorProfileId: profileId,\n tenantId,\n });\n } catch {\n // Threads table may not exist yet.\n }\n\n return {\n chatService,\n session: activeSession,\n threads,\n };\n}\n\nexport async function createContentEditorChatThread(\n input: CreateContentChatThreadInput,\n) {\n await input.initializeChatCollections?.();\n\n const tenantScope = resolveTenantScope(input.tenantId);\n const tenantId = resolveChatTenantId(input.tenantId);\n const profileId = resolveProfileId(input.profileId);\n const chatService = await ChatService.create({ tenantId, db: input.db });\n await assertContentExistsForTenant(\n input.contents,\n tenantScope,\n input.contentId,\n );\n // Tenant-bound session lookup via the facade (S5 #1392): the raw\n // `agentSessions.get(id)` was tenant-UNBOUND and could select a session from\n // another tenant before the ownership/context check below.\n const session = await chatService.getAgentSession({\n agentSessionId: input.sessionId,\n tenantId,\n });\n\n if (\n !contentChatSessionIsAuthorized(session, {\n profileId,\n contentId: input.contentId,\n })\n ) {\n throw new Error('Active session not found');\n }\n\n const chatRoomId = (session as { chatRoomId?: string | null }).chatRoomId;\n if (!chatRoomId) {\n throw new Error('Active session is missing a chat room');\n }\n\n let updates: Record<string, string | null> | null = null;\n if (input.model) {\n const ctx = getSessionContext(session);\n const allowedModels = Array.isArray(ctx.allowedModels)\n ? ctx.allowedModels\n : [];\n if (allowedModels.length > 0 && !allowedModels.includes(input.model)) {\n throw new Error('AI model is not allowed for content chat');\n }\n updates = buildContentChatModelUpdates(ctx, input.model, input.model);\n }\n\n // Member-checked thread creation via the facade (S5 #1392): the editor owns\n // the agent room, so the membership check passes. Replaces the raw\n // `threads.create(...)` that skipped the facade entirely.\n const thread = await chatService.startThread({\n tenantId,\n roomId: chatRoomId,\n actorProfileId: profileId,\n title: input.title,\n });\n\n if (updates) {\n const ctx = getSessionContext(session);\n if (Object.entries(updates).some(([key, value]) => ctx[key] !== value)) {\n await (\n session as { updateSessionContext: (value: unknown) => Promise<void> }\n ).updateSessionContext(updates);\n }\n }\n\n return { chatService, session, thread };\n}\n\nexport async function listContentEditorChatThreadMessages(\n input: ListContentChatThreadMessagesInput,\n) {\n const tenantScope = resolveTenantScope(input.tenantId);\n const tenantId = resolveChatTenantId(input.tenantId);\n const profileId = resolveProfileId(input.profileId);\n const chatService = await ChatService.create({ tenantId, db: input.db });\n await assertContentExistsForTenant(\n input.contents,\n tenantScope,\n input.contentId,\n );\n // Tenant-bound thread + session lookups via the facade (S5 #1392): the raw\n // `threads.get(id)` / `agentSessions.list({ where })` reach-ins were\n // tenant-UNBOUND and could select cross-tenant chat state before authZ.\n const thread = await chatService.getThread({\n threadId: input.threadId,\n tenantId,\n });\n if (!thread) {\n throw new Error('Thread not found');\n }\n\n const roomId = (thread as { roomId?: string }).roomId;\n const activeSessions = await chatService.findActiveAgentSessions({\n tenantId,\n agentId: CONTENT_EDITOR_AGENT_ID,\n participantProfileId: profileId,\n });\n const authorizedSession = activeSessions.find(\n (session: unknown) =>\n (session as { chatRoomId?: string }).chatRoomId === roomId &&\n contentChatSessionMatchesContent(session, input.contentId),\n );\n if (!authorizedSession) {\n throw new Error('Thread not found');\n }\n\n // Membership- + tenant-gated thread message read via the facade (S5 #1392);\n // the editor owns the room, so the membership check passes. Returned\n // chronological (oldest-first) by the facade.\n const messages = await chatService.getThreadMessages({\n threadId: input.threadId,\n actorProfileId: profileId,\n tenantId,\n limit: 100,\n });\n\n return {\n chatService,\n thread,\n messages,\n };\n}\n\nfunction getEnvApiKey(\n provider: string,\n env: Record<string, string | undefined>,\n): string | undefined {\n return provider === 'anthropic'\n ? env.ANTHROPIC_API_KEY\n : provider === 'gemini'\n ? env.GEMINI_API_KEY\n : env.OPENAI_API_KEY;\n}\n\nfunction defaultEnv(): Record<string, string | undefined> {\n return typeof process !== 'undefined' ? process.env : {};\n}\n\nexport function resolveDefaultContentChatAI(\n input: ResolveContentChatAIInput,\n): ResolvedContentChatAI {\n const storedSelection = getContentChatAISelection(input.sessionContext);\n const fallbackModel =\n storedSelection.model ??\n input.aiConfig.model ??\n input.aiConfig.defaultModel ??\n input.requestedModel ??\n null;\n if (!fallbackModel) {\n throw new Error('AI model is not configured for content chat');\n }\n\n const { model, provider } = resolveContentChatModelSelection(\n input.sessionContext,\n input.requestedModel,\n fallbackModel,\n );\n const allowedModels =\n input.aiConfig.allowedModels ??\n input.interactionPrompt.ai.allowedModels ??\n storedSelection.allowedModels;\n if (\n Array.isArray(allowedModels) &&\n allowedModels.length > 0 &&\n !allowedModels.includes(model)\n ) {\n throw new Error('AI model is not allowed for content chat');\n }\n const apiKey = input.aiConfig.apiKey || getEnvApiKey(provider, input.env);\n\n return {\n clientOptions: {\n ...input.aiConfig,\n provider,\n apiKey,\n model,\n },\n model,\n provider,\n temperature: storedSelection.temperature ?? 0.7,\n maxTokens: storedSelection.maxTokens ?? 2000,\n };\n}\n\nfunction sanitizeReferenceText(value: unknown, maxLength: number): string {\n const text = stripHtml(sanitizeHtml(String(value ?? '')))\n .replace(/<<<(?:END_)?SMRT_[^>]*>>>/g, '')\n .replace(/<{2,}/g, '< <')\n .replace(/>{2,}/g, '> >')\n .replace(/\\s+/g, ' ')\n .trim();\n\n return text.length > maxLength ? `${text.slice(0, maxLength)}...` : text;\n}\n\nfunction sanitizeReferenceId(value: string): string {\n return value.replace(/[^\\w:.-]/g, '_').slice(0, 128);\n}\n\nfunction getReferenceTenantId(value: unknown): string | null {\n const candidate = value as {\n tenantId?: unknown;\n tenant_id?: unknown;\n } | null;\n return (\n asNonEmptyString(candidate?.tenantId) ??\n asNonEmptyString(candidate?.tenant_id)\n );\n}\n\nfunction referenceBelongsToTenant(\n ref: unknown,\n tenantScope: string | null,\n): boolean {\n const refTenantId = getReferenceTenantId(ref);\n if (tenantScope === null) {\n return !refTenantId;\n }\n return refTenantId === tenantScope;\n}\n\nasync function buildReferenceContext(\n contents: ContentChatCollectionLike,\n tenantScope: string | null,\n referenceIds: unknown,\n): Promise<string> {\n if (!Array.isArray(referenceIds) || referenceIds.length === 0) {\n return '';\n }\n\n const refTexts: string[] = [];\n const ids = [\n ...new Set(\n referenceIds\n .map(asNonEmptyString)\n .filter((id): id is string => Boolean(id)),\n ),\n ].slice(0, MAX_REFERENCE_IDS);\n for (const id of ids) {\n // Tenant-bound lookup (S5 #1392): bind tenantId into the query rather than\n // a cross-tenant get(id) + post-filter. The post-filter below stays as\n // defense-in-depth.\n const ref = (await getContentForTenant(contents, tenantScope, id)) as {\n title?: string;\n body?: string;\n tenantId?: string;\n tenant_id?: string;\n } | null;\n if (ref && referenceBelongsToTenant(ref, tenantScope)) {\n const safeTitle = sanitizeReferenceText(\n ref.title,\n REFERENCE_TITLE_MAX_LENGTH,\n );\n const safeBody = sanitizeReferenceText(\n ref.body,\n REFERENCE_BODY_MAX_LENGTH,\n );\n refTexts.push(\n `<<<SMRT_REFERENCE id=${sanitizeReferenceId(id)}>>>\\nTitle: ${safeTitle}\\nBody: ${safeBody}\\n<<<END_SMRT_REFERENCE>>>`,\n );\n }\n }\n\n return refTexts.length > 0\n ? `\\n\\nATTACHED REFERENCE MATERIALS:\\n${refTexts.join('\\n\\n')}\\n`\n : '';\n}\n\nexport async function sendContentEditorChatThreadMessage(\n input: SendContentChatThreadMessageInput,\n) {\n const tenantScope = resolveTenantScope(input.tenantId);\n const tenantId = resolveChatTenantId(input.tenantId);\n const profileId = resolveProfileId(input.profileId);\n const chatService = await ChatService.create({\n tenantId,\n db: input.contents.db,\n });\n await assertContentExistsForTenant(\n input.contents,\n tenantScope,\n input.contentId,\n );\n\n // Tenant-bound session + thread lookups via the facade (S5 #1392): the raw\n // `agentSessions.get(id)` / `threads.get(id)` reach-ins were tenant-UNBOUND\n // and could select cross-tenant chat state before the authorization below.\n const session = await chatService.getAgentSession({\n agentSessionId: input.sessionId,\n tenantId,\n });\n if (\n !contentChatSessionIsAuthorized(session, {\n profileId,\n contentId: input.contentId,\n })\n ) {\n throw new Error('Active session not found');\n }\n\n const thread = await chatService.getThread({\n threadId: input.threadId,\n tenantId,\n });\n if (\n !thread ||\n (thread as { roomId?: string }).roomId !==\n (session as { chatRoomId?: string | null }).chatRoomId\n ) {\n throw new Error('Thread not found');\n }\n\n const chatRoomId = (session as { chatRoomId?: string | null }).chatRoomId;\n if (!chatRoomId) {\n throw new Error('Active session is missing a chat room');\n }\n\n const references = await buildReferenceContext(\n input.contents,\n tenantScope,\n input.referenceIds,\n );\n const interactionPrompt = await (input.resolvePromptFn ?? resolvePrompt)(\n contentEditorInteractionPrompt.key,\n {\n db: input.contents.db,\n tenantId,\n variables: buildContentEditorInteractionVariables({\n fields: input.formFields,\n currentEditorState: input.currentEditorState,\n references,\n }),\n },\n );\n\n const sessionContext = getSessionContext(session);\n const aiConfig = input.aiConfig ?? {};\n const resolvedAI =\n (await input.resolveAI?.({\n aiConfig,\n env: input.env ?? defaultEnv(),\n sessionContext,\n requestedModel: input.model,\n interactionPrompt,\n })) ??\n resolveDefaultContentChatAI({\n aiConfig,\n env: input.env ?? defaultEnv(),\n sessionContext,\n requestedModel: input.model,\n interactionPrompt,\n });\n\n const userMessage = await chatService.sendMessage({\n tenantId,\n roomId: chatRoomId,\n threadId: (thread as { id: string }).id,\n actorProfileId: profileId,\n content: input.content,\n agentSessionId: (session as { id: string }).id,\n });\n\n // Membership- + tenant-gated thread history via the facade (S5 #1392); the\n // editor owns the room. Returned chronological (oldest-first) by the facade.\n const history = await chatService.getThreadMessages({\n threadId: (thread as { id: string }).id,\n actorProfileId: profileId,\n tenantId,\n limit: 10,\n });\n\n const conversation = history.map((message: unknown) => {\n const json = contentChatMessageToJSON(message);\n return {\n role: json.role as 'user' | 'assistant' | 'system',\n content: String(json.content ?? ''),\n };\n });\n\n const ai = await (input.getAIClient ?? getAI)(resolvedAI.clientOptions);\n\n const fullSystemPrompt =\n typeof (session as { systemPrompt?: unknown }).systemPrompt === 'string'\n ? (session as { systemPrompt: string }).systemPrompt\n : '';\n conversation.unshift({\n role: 'system',\n content: `${fullSystemPrompt}\\n\\n${interactionPrompt.text}`,\n });\n\n const response = await ai.chat(conversation, {\n model: resolvedAI.model,\n temperature: resolvedAI.temperature ?? 0.7,\n maxTokens: resolvedAI.maxTokens ?? 2000,\n });\n\n // Author the assistant reply AS the session's agent via the trusted internal\n // agent-runtime surface — never via the public sendMessage (which would force\n // the message to the caller's identity with role 'user') (S5 #1392).\n const agentMessage = await sendAgentReply(chatService, {\n tenantId,\n agentSessionId: (session as { id: string }).id,\n threadId: (thread as { id: string }).id,\n content: response.content,\n kind: 'assistant',\n });\n\n const updates = buildContentChatModelUpdates(\n sessionContext,\n input.model,\n resolvedAI.model,\n );\n updates.model = resolvedAI.model;\n if (resolvedAI.provider !== undefined) {\n updates.provider = resolvedAI.provider;\n }\n if (resolvedAI.profile !== undefined) {\n updates.profile = resolvedAI.profile;\n }\n if (\n Object.entries(updates).some(\n ([key, value]) => sessionContext[key] !== value,\n )\n ) {\n await (\n session as { updateSessionContext: (value: unknown) => Promise<void> }\n ).updateSessionContext(updates);\n }\n\n return {\n chatService,\n session,\n thread,\n userMessage,\n agentMessage,\n };\n}\n","import type { DatabaseInterface } from '@happyvertical/sql';\n\nexport type ContentContributionChannel = 'web' | 'email';\n\nexport type ContentContributionStatus =\n | 'submitted'\n | 'quarantined'\n | 'needs_changes'\n | 'approved'\n | 'promoted'\n | 'rejected'\n | 'withdrawn';\n\nexport type ContentContributionIntakeDecision =\n | 'accepted'\n | 'quarantined'\n | 'rejected';\n\nexport type ContentContributorTrustLevel = 'standard' | 'trusted' | 'blocked';\n\nexport interface ContentContributionIntakeRules {\n maxFiles?: number | null;\n maxTotalBytes?: number | null;\n allowedMimePatterns?: string[];\n blockedMimePatterns?: string[];\n quarantineMimePatterns?: string[];\n blockedTextPatterns?: string[];\n quarantineTextPatterns?: string[];\n trustedOnly?: boolean;\n}\n\nexport interface ContentContributionPromotionMapping {\n targetContentType?: string | null;\n targetContentVariant?: string | null;\n targetContentStatus?: 'draft' | 'review';\n autoPromoteTrusted?: boolean;\n createAssets?: boolean;\n assetRelationship?: string;\n}\n\nexport interface ContentContributionTypeDefinition {\n key: string;\n label: string;\n enabled?: boolean;\n allowedChannels?: ContentContributionChannel[];\n allowText?: boolean;\n allowFiles?: boolean;\n allowEmptyText?: boolean;\n intakeRules?: ContentContributionIntakeRules;\n promotion?: ContentContributionPromotionMapping;\n metadata?: Record<string, unknown>;\n}\n\nexport interface PersistedContentContributionTypeRecord\n extends ContentContributionTypeDefinition {\n id?: string;\n tenantId?: string | null;\n createdAt?: string | null;\n updatedAt?: string | null;\n}\n\nexport interface ContentContributionConfig {\n types: ContentContributionTypeDefinition[];\n}\n\nexport interface ResolvedContentContributionType\n extends ContentContributionTypeDefinition {}\n\nexport interface ContentContributionTypeConfigState {\n effective: ContentContributionTypeDefinition[];\n persisted: PersistedContentContributionTypeRecord[];\n}\n\nexport interface EvaluateContributionIntakeOptions {\n contributionType: ContentContributionTypeDefinition;\n trustLevel?: ContentContributorTrustLevel;\n channel: ContentContributionChannel;\n title?: string | null;\n description?: string | null;\n body?: string | null;\n attachments?: Array<{\n mimeType?: string | null;\n size?: number | null;\n }>;\n}\n\nexport interface EvaluateContributionIntakeResult {\n decision: ContentContributionIntakeDecision;\n reasons: string[];\n}\n\nconst DEFAULT_CONTENT_CONTRIBUTION_CONFIG: ContentContributionConfig = {\n types: [],\n};\n\nlet contributionConfig = cloneContributionConfig(\n DEFAULT_CONTENT_CONTRIBUTION_CONFIG,\n);\n\nfunction cloneJSONArray<T>(items: T[] | null | undefined): T[] {\n return Array.isArray(items) ? items.map((item) => structuredClone(item)) : [];\n}\n\nfunction safeParseJSONObject(raw: unknown): Record<string, unknown> {\n if (!raw) {\n return {};\n }\n\n if (typeof raw === 'object') {\n return { ...(raw as Record<string, unknown>) };\n }\n\n if (typeof raw !== 'string') {\n return {};\n }\n\n try {\n const parsed = JSON.parse(raw);\n return parsed && typeof parsed === 'object' ? parsed : {};\n } catch {\n return {};\n }\n}\n\nfunction safeParseJSONArray<T>(raw: unknown): T[] {\n if (!raw) {\n return [];\n }\n\n if (Array.isArray(raw)) {\n return raw.map((item) => structuredClone(item)) as T[];\n }\n\n if (typeof raw !== 'string') {\n return [];\n }\n\n try {\n const parsed = JSON.parse(raw);\n return Array.isArray(parsed) ? (parsed as T[]) : [];\n } catch {\n return [];\n }\n}\n\nfunction cloneIntakeRules(\n rules: ContentContributionIntakeRules | null | undefined,\n): ContentContributionIntakeRules {\n return {\n maxFiles:\n typeof rules?.maxFiles === 'number' ? Math.max(0, rules.maxFiles) : null,\n maxTotalBytes:\n typeof rules?.maxTotalBytes === 'number'\n ? Math.max(0, rules.maxTotalBytes)\n : null,\n allowedMimePatterns: cloneJSONArray(rules?.allowedMimePatterns),\n blockedMimePatterns: cloneJSONArray(rules?.blockedMimePatterns),\n quarantineMimePatterns: cloneJSONArray(rules?.quarantineMimePatterns),\n blockedTextPatterns: cloneJSONArray(rules?.blockedTextPatterns),\n quarantineTextPatterns: cloneJSONArray(rules?.quarantineTextPatterns),\n trustedOnly: rules?.trustedOnly === true,\n };\n}\n\nfunction clonePromotionMapping(\n promotion: ContentContributionPromotionMapping | null | undefined,\n): ContentContributionPromotionMapping {\n return {\n targetContentType: promotion?.targetContentType || null,\n targetContentVariant: promotion?.targetContentVariant || null,\n targetContentStatus:\n promotion?.targetContentStatus === 'review' ? 'review' : 'draft',\n autoPromoteTrusted: promotion?.autoPromoteTrusted === true,\n createAssets: promotion?.createAssets !== false,\n assetRelationship: promotion?.assetRelationship || 'attachment',\n };\n}\n\nfunction cloneTypeDefinition(\n type: ContentContributionTypeDefinition,\n): ContentContributionTypeDefinition {\n return {\n key: type.key,\n label: type.label,\n enabled: type.enabled !== false,\n allowedChannels:\n type.allowedChannels && type.allowedChannels.length > 0\n ? [...type.allowedChannels]\n : ['web'],\n allowText: type.allowText !== false,\n allowFiles: type.allowFiles === true,\n allowEmptyText: type.allowEmptyText === true,\n intakeRules: cloneIntakeRules(type.intakeRules),\n promotion: clonePromotionMapping(type.promotion),\n metadata: safeParseJSONObject(type.metadata),\n };\n}\n\nfunction clonePersistedTypeRecord(\n type: PersistedContentContributionTypeRecord,\n): PersistedContentContributionTypeRecord {\n return {\n ...cloneTypeDefinition(type),\n id: type.id,\n tenantId: type.tenantId ?? null,\n createdAt: type.createdAt ?? null,\n updatedAt: type.updatedAt ?? null,\n };\n}\n\nfunction cloneContributionConfig(\n config: ContentContributionConfig,\n): ContentContributionConfig {\n return {\n types: config.types.map(cloneTypeDefinition),\n };\n}\n\nfunction mergeByKey<T extends { key: string }>(\n baseItems: T[],\n overrides: T[],\n normalize: (item: T) => T,\n): T[] {\n const merged = new Map<string, T>();\n\n for (const item of baseItems.map(normalize)) {\n merged.set(item.key, item);\n }\n\n for (const item of overrides.map(normalize)) {\n merged.set(item.key, item);\n }\n\n return [...merged.values()];\n}\n\nfunction isMissingContributionTypesTableError(error: unknown): boolean {\n const message = String(\n (error as Error)?.message || error || '',\n ).toLowerCase();\n return (\n message.includes('content_contribution_types') &&\n (message.includes('no such table') ||\n message.includes('does not exist') ||\n message.includes('relation'))\n );\n}\n\nfunction mapPersistedTypeRow(\n row: Record<string, unknown>,\n): PersistedContentContributionTypeRecord {\n return {\n // `id` is an optional string column; coerce non-string/empty driver\n // values to undefined so a numeric id can't leak past the `id?: string`\n // shape (mirrors the getRowString pattern used elsewhere).\n id: typeof row.id === 'string' && row.id ? row.id : undefined,\n key: String(row.key || ''),\n label: String(row.label || row.key || ''),\n enabled: row.enabled !== false && row.enabled !== 0,\n allowedChannels: safeParseJSONArray<ContentContributionChannel>(\n row.allowedChannels || row.allowed_channels,\n ),\n allowText:\n row.allowText === undefined && row.allow_text === undefined\n ? true\n : row.allowText !== false && row.allow_text !== 0,\n allowFiles:\n row.allowFiles === true ||\n row.allow_files === true ||\n row.allow_files === 1,\n allowEmptyText:\n row.allowEmptyText === true ||\n row.allow_empty_text === true ||\n row.allow_empty_text === 1,\n // Persisted JSON blobs deserialize to the documented intake/promotion\n // shapes; they are re-normalized structurally by clone* helpers downstream.\n intakeRules: safeParseJSONObject(\n row.intakeRules || row.intake_rules,\n ) as ContentContributionIntakeRules,\n promotion: safeParseJSONObject(\n row.promotion || row.promotion_mapping,\n ) as ContentContributionPromotionMapping,\n metadata: safeParseJSONObject(row.metadata),\n tenantId: (row.tenantId ?? row.tenant_id ?? null) as string | null,\n createdAt: (row.createdAt || row.created_at || null) as string | null,\n updatedAt: (row.updatedAt || row.updated_at || null) as string | null,\n };\n}\n\nexport function getContentContributionConfig(): ContentContributionConfig {\n return cloneContributionConfig(contributionConfig);\n}\n\nexport function configureContentContributions(\n config: Partial<ContentContributionConfig>,\n): ContentContributionConfig {\n contributionConfig = {\n types: config.types\n ? mergeByKey(contributionConfig.types, config.types, cloneTypeDefinition)\n : contributionConfig.types.map(cloneTypeDefinition),\n };\n\n return getContentContributionConfig();\n}\n\nexport function resetContentContributionConfig(): ContentContributionConfig {\n contributionConfig = cloneContributionConfig(\n DEFAULT_CONTENT_CONTRIBUTION_CONFIG,\n );\n return getContentContributionConfig();\n}\n\nexport function hasStaticContentContributionType(key: string): boolean {\n return contributionConfig.types.some((type) => type.key === key);\n}\n\nexport async function loadPersistedContentContributionTypes(\n options: { db?: DatabaseInterface | null } = {},\n): Promise<PersistedContentContributionTypeRecord[]> {\n if (!options.db) {\n return [];\n }\n\n try {\n const rows = (await options.db.list(\n 'content_contribution_types',\n {},\n )) as Record<string, unknown>[];\n rows.sort((a, b) =>\n String(a.created_at || a.createdAt || '').localeCompare(\n String(b.created_at || b.createdAt || ''),\n ),\n );\n return rows.map((row) => mapPersistedTypeRow(row));\n } catch (error) {\n if (isMissingContributionTypesTableError(error)) {\n return [];\n }\n\n throw error;\n }\n}\n\nexport async function getEffectiveContentContributionConfig(\n options: { db?: DatabaseInterface | null } = {},\n): Promise<ContentContributionConfig> {\n const persisted = await loadPersistedContentContributionTypes({\n db: options.db,\n });\n\n return {\n types: mergeByKey(\n contributionConfig.types,\n persisted,\n cloneTypeDefinition as (\n item: ContentContributionTypeDefinition,\n ) => ContentContributionTypeDefinition,\n ),\n };\n}\n\nexport async function getContentContributionTypeConfigState(\n options: { db?: DatabaseInterface | null } = {},\n): Promise<ContentContributionTypeConfigState> {\n const [effective, persisted] = await Promise.all([\n getEffectiveContentContributionConfig(options),\n loadPersistedContentContributionTypes(options),\n ]);\n\n return {\n effective: effective.types,\n persisted: persisted.map(clonePersistedTypeRecord),\n };\n}\n\nexport async function resolveEffectiveContentContributionType(\n key: string,\n options: { db?: DatabaseInterface | null } = {},\n): Promise<ResolvedContentContributionType | null> {\n const effective = await getEffectiveContentContributionConfig(options);\n const type = effective.types.find((entry) => entry.key === key);\n return type ? cloneTypeDefinition(type) : null;\n}\n\nfunction matchesMimePattern(mimeType: string, pattern: string): boolean {\n if (!pattern) {\n return false;\n }\n\n if (pattern.endsWith('/*')) {\n return mimeType.startsWith(pattern.slice(0, -1));\n }\n\n return mimeType === pattern;\n}\n\nfunction matchesAnyMimePattern(mimeType: string, patterns: string[]): boolean {\n return patterns.some((pattern) => matchesMimePattern(mimeType, pattern));\n}\n\nfunction containsPattern(text: string, patterns: string[]): boolean {\n const lowerText = text.toLowerCase();\n return patterns.some((pattern) => lowerText.includes(pattern.toLowerCase()));\n}\n\nexport function evaluateContributionIntake(\n options: EvaluateContributionIntakeOptions,\n): EvaluateContributionIntakeResult {\n const type = cloneTypeDefinition(options.contributionType);\n const rules = cloneIntakeRules(type.intakeRules);\n const trustLevel = options.trustLevel || 'standard';\n const attachments = options.attachments || [];\n const text = [options.title, options.description, options.body]\n .filter(Boolean)\n .join('\\n')\n .trim();\n const hasText = text.length > 0;\n const hasFiles = attachments.length > 0;\n const totalBytes = attachments.reduce(\n (sum, attachment) => sum + Math.max(0, attachment.size || 0),\n 0,\n );\n const reasons: string[] = [];\n\n if (type.enabled === false) {\n return {\n decision: 'rejected',\n reasons: ['This contribution type is currently disabled.'],\n };\n }\n\n if (\n Array.isArray(type.allowedChannels) &&\n type.allowedChannels.length > 0 &&\n !type.allowedChannels.includes(options.channel)\n ) {\n return {\n decision: 'rejected',\n reasons: [\n `${options.channel} submissions are not allowed for this type.`,\n ],\n };\n }\n\n if (trustLevel === 'blocked') {\n return {\n decision: 'rejected',\n reasons: ['This contributor is blocked from submitting new material.'],\n };\n }\n\n if (rules.trustedOnly && trustLevel !== 'trusted') {\n return {\n decision: 'rejected',\n reasons: ['This contribution type is limited to trusted contributors.'],\n };\n }\n\n if (type.allowText === false && hasText) {\n return {\n decision: 'rejected',\n reasons: ['This contribution type does not accept text submissions.'],\n };\n }\n\n if (type.allowFiles !== true && hasFiles) {\n return {\n decision: 'rejected',\n reasons: ['This contribution type does not accept file attachments.'],\n };\n }\n\n if (\n type.allowText === true &&\n type.allowEmptyText !== true &&\n !hasText &&\n !hasFiles\n ) {\n return {\n decision: 'rejected',\n reasons: ['A text body or at least one attachment is required.'],\n };\n }\n\n if (\n typeof rules.maxFiles === 'number' &&\n attachments.length > rules.maxFiles\n ) {\n return {\n decision: 'rejected',\n reasons: [\n `This contribution type accepts at most ${rules.maxFiles} files.`,\n ],\n };\n }\n\n if (\n typeof rules.maxTotalBytes === 'number' &&\n totalBytes > rules.maxTotalBytes\n ) {\n return {\n decision: 'rejected',\n reasons: [\n 'The attached files exceed the size limit for this contribution type.',\n ],\n };\n }\n\n const mimeTypes = attachments\n .map((attachment) => attachment.mimeType || '')\n .filter(Boolean);\n\n if (\n rules.allowedMimePatterns &&\n rules.allowedMimePatterns.length > 0 &&\n mimeTypes.some(\n (mimeType) =>\n !matchesAnyMimePattern(mimeType, rules.allowedMimePatterns || []),\n )\n ) {\n return {\n decision: 'rejected',\n reasons: ['One or more attachments use a file type that is not allowed.'],\n };\n }\n\n if (\n mimeTypes.some((mimeType) =>\n matchesAnyMimePattern(mimeType, rules.blockedMimePatterns || []),\n )\n ) {\n return {\n decision: 'rejected',\n reasons: ['One or more attachments match blocked file-type rules.'],\n };\n }\n\n if (containsPattern(text, rules.blockedTextPatterns || [])) {\n return {\n decision: 'rejected',\n reasons: ['The submission body matches blocked intake rules.'],\n };\n }\n\n if (\n mimeTypes.some((mimeType) =>\n matchesAnyMimePattern(mimeType, rules.quarantineMimePatterns || []),\n )\n ) {\n reasons.push('One or more attachments triggered quarantine file rules.');\n }\n\n if (containsPattern(text, rules.quarantineTextPatterns || [])) {\n reasons.push('The submission body triggered quarantine text rules.');\n }\n\n if (reasons.length > 0) {\n return {\n decision: 'quarantined',\n reasons,\n };\n }\n\n return {\n decision: 'accepted',\n reasons: [],\n };\n}\n","import {\n AssetCollection,\n AssetStatusCollection,\n AssetTypeCollection,\n} from '@happyvertical/smrt-assets';\nimport type { SmrtObjectOptions } from '@happyvertical/smrt-core';\nimport {\n crossPackageRef,\n field,\n foreignKey,\n SmrtObject,\n smrt,\n} from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport type { ContentContributionAttachment } from './content-contribution-attachment';\nimport {\n type ContentContributionChannel,\n type ContentContributionIntakeDecision,\n type ContentContributionStatus,\n type ContentContributionTypeDefinition,\n resolveEffectiveContentContributionType,\n} from './content-contribution-config';\nimport type { ContentContributionRevision } from './content-contribution-revision';\nimport type { ContentContributor } from './content-contributor';\n\nexport interface ContentContributionAttachmentInput {\n filename: string;\n mimeType?: string | null;\n size?: number | null;\n fileKey?: string | null;\n sourceUri?: string | null;\n metadata?: Record<string, unknown>;\n}\n\nexport interface AppendContentContributionRevisionOptions {\n title?: string | null;\n description?: string | null;\n body?: string | null;\n channel?: ContentContributionChannel;\n sourceMessageId?: string | null;\n sourceThreadKey?: string | null;\n attachments?: ContentContributionAttachmentInput[];\n metadata?: Record<string, unknown>;\n}\n\nexport interface ApproveContentContributionOptions {\n editorNote?: string | null;\n promote?: boolean;\n targetStatus?: 'draft' | 'review';\n}\n\nexport interface RejectContentContributionOptions {\n editorNote?: string | null;\n}\n\nexport interface RequestChangesContentContributionOptions {\n editorNote?: string | null;\n}\n\nexport interface WithdrawContentContributionOptions {\n reason?: string | null;\n}\n\nexport interface PromoteContentContributionOptions {\n editorNote?: string | null;\n targetStatus?: 'draft' | 'review';\n}\n\nexport interface ContentContributionOptions extends SmrtObjectOptions {\n contributorId?: string;\n contributionTypeKey?: string;\n status?: ContentContributionStatus;\n intakeDecision?: ContentContributionIntakeDecision;\n channel?: ContentContributionChannel;\n title?: string | null;\n description?: string | null;\n body?: string | null;\n contributorEmail?: string | null;\n contributorName?: string | null;\n threadKey?: string | null;\n sourceMessageId?: string | null;\n editorNotes?: string | null;\n promotedContentId?: string | null;\n revisionCount?: number;\n approvedAt?: Date | null;\n promotedAt?: Date | null;\n rejectedAt?: Date | null;\n withdrawnAt?: Date | null;\n requestedChangesAt?: Date | null;\n metadata?: Record<string, unknown> | string;\n tenantId?: string | null;\n createdAt?: Date;\n updatedAt?: Date;\n}\n\nfunction parseMetadata(raw: unknown): Record<string, unknown> {\n if (!raw) {\n return {};\n }\n\n if (typeof raw === 'object') {\n return { ...(raw as Record<string, unknown>) };\n }\n\n if (typeof raw !== 'string') {\n return {};\n }\n\n try {\n const parsed = JSON.parse(raw);\n return parsed && typeof parsed === 'object'\n ? (parsed as Record<string, unknown>)\n : {};\n } catch {\n return {};\n }\n}\n\nfunction inferAssetTypeSlug(mimeType: string): string {\n if (mimeType.startsWith('image/')) {\n return 'image';\n }\n if (mimeType.startsWith('video/')) {\n return 'video';\n }\n if (mimeType.startsWith('audio/')) {\n return 'audio';\n }\n return 'document';\n}\n\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableName: 'content_contributions',\n conflictColumns: ['id'],\n api: {\n include: [\n 'list',\n 'get',\n 'create',\n 'update',\n 'delete',\n 'appendRevisionAction',\n 'requestChangesAction',\n 'approveAction',\n 'rejectAction',\n 'withdrawAction',\n 'promoteAction',\n ],\n routes: {\n appendRevisionAction: { method: 'POST', path: 'revisions' },\n requestChangesAction: { method: 'POST', path: 'request-changes' },\n approveAction: { method: 'POST', path: 'approve' },\n rejectAction: { method: 'POST', path: 'reject' },\n withdrawAction: { method: 'POST', path: 'withdraw' },\n promoteAction: { method: 'POST', path: 'promote' },\n },\n },\n mcp: { include: ['list', 'get', 'create', 'update'] },\n cli: true,\n})\nexport class ContentContribution extends SmrtObject {\n @foreignKey('ContentContributor', { required: true })\n contributorId = '';\n\n @field({ required: true })\n contributionTypeKey = '';\n\n status: ContentContributionStatus = 'submitted';\n intakeDecision: ContentContributionIntakeDecision = 'accepted';\n channel: ContentContributionChannel = 'web';\n title = '';\n description = '';\n body = '';\n contributorEmail = '';\n contributorName = '';\n threadKey = '';\n\n @crossPackageRef('@happyvertical/smrt-messages:Message')\n sourceMessageId = '';\n\n editorNotes = '';\n\n @foreignKey('Content')\n promotedContentId = '';\n revisionCount = 0;\n approvedAt: Date | null = null;\n promotedAt: Date | null = null;\n rejectedAt: Date | null = null;\n withdrawnAt: Date | null = null;\n requestedChangesAt: Date | null = null;\n metadata = '';\n\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n createdAt = new Date();\n updatedAt = new Date();\n\n constructor(options: ContentContributionOptions = {}) {\n super(options);\n if (options.contributorId !== undefined)\n this.contributorId = options.contributorId;\n if (options.contributionTypeKey !== undefined)\n this.contributionTypeKey = options.contributionTypeKey;\n if (options.status !== undefined) this.status = options.status;\n if (options.intakeDecision !== undefined)\n this.intakeDecision = options.intakeDecision;\n if (options.channel !== undefined) this.channel = options.channel;\n if (options.title !== undefined) this.title = options.title || '';\n if (options.description !== undefined)\n this.description = options.description || '';\n if (options.body !== undefined) this.body = options.body || '';\n if (options.contributorEmail !== undefined)\n this.contributorEmail = options.contributorEmail || '';\n if (options.contributorName !== undefined)\n this.contributorName = options.contributorName || '';\n if (options.threadKey !== undefined)\n this.threadKey = options.threadKey || '';\n if (options.sourceMessageId !== undefined)\n this.sourceMessageId = options.sourceMessageId || '';\n if (options.editorNotes !== undefined)\n this.editorNotes = options.editorNotes || '';\n if (options.promotedContentId !== undefined)\n this.promotedContentId = options.promotedContentId || '';\n if (options.revisionCount !== undefined)\n this.revisionCount = options.revisionCount;\n if (options.approvedAt !== undefined) this.approvedAt = options.approvedAt;\n if (options.promotedAt !== undefined) this.promotedAt = options.promotedAt;\n if (options.rejectedAt !== undefined) this.rejectedAt = options.rejectedAt;\n if (options.withdrawnAt !== undefined)\n this.withdrawnAt = options.withdrawnAt;\n if (options.requestedChangesAt !== undefined)\n this.requestedChangesAt = options.requestedChangesAt;\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n if (options.createdAt) this.createdAt = options.createdAt;\n if (options.updatedAt) this.updatedAt = options.updatedAt;\n if (options.metadata !== undefined) {\n this.metadata =\n typeof options.metadata === 'string'\n ? options.metadata\n : JSON.stringify(options.metadata);\n }\n }\n\n getMetadata(): Record<string, unknown> {\n return parseMetadata(this.metadata);\n }\n\n setMetadata(metadata: Record<string, unknown>): void {\n this.metadata = JSON.stringify(metadata || {});\n }\n\n protected override transformJSON(json: Record<string, unknown>) {\n return {\n ...json,\n description: this.description || null,\n body: this.body || null,\n contributorEmail: this.contributorEmail || null,\n contributorName: this.contributorName || null,\n threadKey: this.threadKey || null,\n sourceMessageId: this.sourceMessageId || null,\n editorNotes: this.editorNotes || null,\n promotedContentId: this.promotedContentId || null,\n metadata: this.getMetadata(),\n };\n }\n\n private async getRevisionCollection() {\n const { ContentContributionRevisionCollection } = await import(\n './content-contribution-revisions'\n );\n return ContentContributionRevisionCollection.create(this.options);\n }\n\n private async getAttachmentCollection() {\n const { ContentContributionAttachmentCollection } = await import(\n './content-contribution-attachments'\n );\n return ContentContributionAttachmentCollection.create(this.options);\n }\n\n private async getContributorCollection() {\n const { ContentContributorCollection } = await import(\n './content-contributors'\n );\n return ContentContributorCollection.create(this.options);\n }\n\n private async getContentsCollection() {\n const { Contents } = await import('./contents');\n return Contents.create({ db: this.db });\n }\n\n private async getAssetCollection() {\n return AssetCollection.create(this.options);\n }\n\n private async getAssetStatusCollection() {\n return AssetStatusCollection.create(this.options);\n }\n\n private async getAssetTypeCollection() {\n return AssetTypeCollection.create(this.options);\n }\n\n async getContributor(): Promise<ContentContributor | null> {\n if (!this.contributorId) {\n return null;\n }\n\n const contributors = await this.getContributorCollection();\n return contributors.get({ id: this.contributorId });\n }\n\n async getRevisions(): Promise<ContentContributionRevision[]> {\n if (!this.id) {\n return [];\n }\n\n const revisions = await this.getRevisionCollection();\n return revisions.listForContribution(this.id);\n }\n\n async getLatestRevision(): Promise<ContentContributionRevision | null> {\n if (!this.id) {\n return null;\n }\n\n const revisions = await this.getRevisionCollection();\n return revisions.getLatestForContribution(this.id);\n }\n\n async getAttachments(): Promise<ContentContributionAttachment[]> {\n if (!this.id) {\n return [];\n }\n\n const attachments = await this.getAttachmentCollection();\n return attachments.listForContribution(this.id);\n }\n\n async resolveContributionType(): Promise<ContentContributionTypeDefinition | null> {\n return resolveEffectiveContentContributionType(this.contributionTypeKey, {\n db: this.db,\n });\n }\n\n private ensureEditable(): void {\n if (\n this.revisionCount > 0 &&\n ['rejected', 'withdrawn', 'promoted'].includes(this.status)\n ) {\n throw new Error(\n `Contribution \"${this.id || 'new'}\" cannot be edited once it is ${this.status}.`,\n );\n }\n }\n\n private async createRevision(\n options: AppendContentContributionRevisionOptions,\n ): Promise<ContentContributionRevision> {\n if (!this.id) {\n throw new Error('Contribution must be saved before creating revisions.');\n }\n\n const revisions = await this.getRevisionCollection();\n const nextRevisionNumber = Math.max(1, this.revisionCount + 1);\n const revision = await revisions.create({\n contributionId: this.id,\n revisionNumber: nextRevisionNumber,\n channel: options.channel || this.channel,\n title: options.title ?? this.title,\n description: options.description ?? this.description,\n body: options.body ?? this.body,\n sourceMessageId: options.sourceMessageId || '',\n sourceThreadKey: options.sourceThreadKey || this.threadKey || '',\n metadata: JSON.stringify(options.metadata || {}),\n tenantId: this.tenantId,\n });\n\n return revision;\n }\n\n private async createHeldAttachments(\n revisionId: string | null,\n attachments: ContentContributionAttachmentInput[],\n channel: ContentContributionChannel,\n ): Promise<ContentContributionAttachment[]> {\n if (!this.id || attachments.length === 0) {\n return [];\n }\n\n const records = await this.getAttachmentCollection();\n const created: ContentContributionAttachment[] = [];\n for (const attachment of attachments) {\n const item = await records.create({\n contributionId: this.id,\n revisionId: revisionId || '',\n filename: attachment.filename,\n mimeType: attachment.mimeType || 'application/octet-stream',\n size: Math.max(0, attachment.size || 0),\n fileKey: attachment.fileKey || '',\n sourceUri: attachment.sourceUri || '',\n channel,\n tenantId: this.tenantId,\n metadata: JSON.stringify(attachment.metadata || {}),\n });\n created.push(item);\n }\n\n return created;\n }\n\n async appendRevisionAction(\n options: AppendContentContributionRevisionOptions = {},\n ) {\n this.ensureEditable();\n\n const revision = await this.createRevision(options);\n await this.createHeldAttachments(\n revision.id || null,\n options.attachments || [],\n options.channel || this.channel,\n );\n\n this.title = options.title ?? this.title;\n this.description = options.description ?? this.description;\n this.body = options.body ?? this.body;\n this.channel = options.channel || this.channel;\n this.sourceMessageId = options.sourceMessageId || this.sourceMessageId;\n this.threadKey = options.sourceThreadKey || this.threadKey;\n this.revisionCount = revision.revisionNumber;\n\n if (this.status === 'needs_changes') {\n this.status = 'submitted';\n this.requestedChangesAt = null;\n }\n\n const metadata = this.getMetadata();\n metadata.lastRevisionId = revision.id || null;\n metadata.lastRevisionAt = revision.createdAt.toISOString();\n this.setMetadata(metadata);\n await this.save();\n\n return {\n contribution: this.toJSON(),\n revision: revision.toJSON(),\n attachments: (await this.getAttachments()).map((item) => item.toJSON()),\n };\n }\n\n async requestChangesAction(\n options: RequestChangesContentContributionOptions = {},\n ) {\n if (['rejected', 'withdrawn', 'promoted'].includes(this.status)) {\n throw new Error(\n `Contribution \"${this.id || 'new'}\" cannot request changes after ${this.status}.`,\n );\n }\n\n this.status = 'needs_changes';\n this.requestedChangesAt = new Date();\n this.editorNotes = options.editorNote || this.editorNotes;\n\n const metadata = this.getMetadata();\n const requestHistory = Array.isArray(metadata.requestChangesHistory)\n ? metadata.requestChangesHistory\n : [];\n requestHistory.push({\n note: options.editorNote || '',\n at: this.requestedChangesAt.toISOString(),\n });\n metadata.requestChangesHistory = requestHistory;\n this.setMetadata(metadata);\n\n await this.save();\n return this.toJSON();\n }\n\n async rejectAction(options: RejectContentContributionOptions = {}) {\n if (this.status === 'promoted') {\n throw new Error('Promoted contributions cannot be rejected.');\n }\n\n this.status = 'rejected';\n this.rejectedAt = new Date();\n this.editorNotes = options.editorNote || this.editorNotes;\n\n const metadata = this.getMetadata();\n metadata.rejection = {\n note: options.editorNote || '',\n at: this.rejectedAt.toISOString(),\n };\n this.setMetadata(metadata);\n\n await this.save();\n return this.toJSON();\n }\n\n async withdrawAction(options: WithdrawContentContributionOptions = {}) {\n if (this.status === 'promoted') {\n throw new Error('Promoted contributions cannot be withdrawn.');\n }\n\n this.status = 'withdrawn';\n this.withdrawnAt = new Date();\n\n const metadata = this.getMetadata();\n metadata.withdrawal = {\n reason: options.reason || '',\n at: this.withdrawnAt.toISOString(),\n };\n this.setMetadata(metadata);\n\n await this.save();\n return this.toJSON();\n }\n\n async approveAction(options: ApproveContentContributionOptions = {}) {\n if (['rejected', 'withdrawn', 'promoted'].includes(this.status)) {\n throw new Error(\n `Contribution \"${this.id || 'new'}\" cannot be approved after ${this.status}.`,\n );\n }\n\n this.status = 'approved';\n this.approvedAt = new Date();\n this.editorNotes = options.editorNote || this.editorNotes;\n await this.save();\n\n if (options.promote === false) {\n return {\n contribution: this.toJSON(),\n content: null,\n assets: [],\n };\n }\n\n return this.promoteAction({\n editorNote: options.editorNote,\n targetStatus: options.targetStatus,\n });\n }\n\n async promoteAction(options: PromoteContentContributionOptions = {}) {\n if (this.promotedContentId) {\n const contents = await this.getContentsCollection();\n const content = await contents.get({ id: this.promotedContentId });\n return {\n contribution: this.toJSON(),\n content: content ? content.toJSON() : null,\n assets: await this.getAttachments().then((items) =>\n items\n .filter((item) => item.promotedAssetId)\n .map((item) => ({\n attachmentId: item.id,\n assetId: item.promotedAssetId,\n })),\n ),\n };\n }\n\n const type = await this.resolveContributionType();\n if (!type) {\n throw new Error(\n `Contribution type \"${this.contributionTypeKey}\" is not configured.`,\n );\n }\n\n const promotion = type.promotion || {};\n if (!promotion.targetContentType) {\n throw new Error(\n `Contribution type \"${type.key}\" is missing promotion.targetContentType.`,\n );\n }\n\n const contributor = await this.getContributor();\n const latestRevision = await this.getLatestRevision();\n const attachments = await this.getAttachments();\n\n const contents = await this.getContentsCollection();\n const content = await contents.create({\n tenantId: this.tenantId,\n type: promotion.targetContentType,\n variant: promotion.targetContentVariant || null,\n source: 'contribution',\n status: options.targetStatus || promotion.targetContentStatus || 'draft',\n title: latestRevision?.title || this.title,\n description: latestRevision?.description || this.description || null,\n body: latestRevision?.body || this.body || '',\n author:\n contributor?.name ||\n this.contributorName ||\n this.contributorEmail ||\n null,\n name:\n latestRevision?.title ||\n this.title ||\n `${type.label || type.key} contribution`,\n metadata: {\n contribution: {\n contributionId: this.id || null,\n contributorId: this.contributorId || null,\n contributorEmail: this.contributorEmail || null,\n contributorName: this.contributorName || null,\n contributionTypeKey: this.contributionTypeKey,\n revisionCount: this.revisionCount,\n sourceMessageId: this.sourceMessageId || null,\n threadKey: this.threadKey || null,\n },\n },\n });\n await content.save();\n\n const promotedAssets: Array<{\n attachmentId: string | null;\n assetId: string | null;\n }> = [];\n\n if (promotion.createAssets !== false && attachments.length > 0) {\n const [assets, statuses, typesCollection] = await Promise.all([\n this.getAssetCollection(),\n this.getAssetStatusCollection(),\n this.getAssetTypeCollection(),\n ]);\n\n await Promise.all([\n statuses.initializeCommonStatuses(),\n typesCollection.initializeCommonTypes(),\n ]);\n\n for (const [index, attachment] of attachments.entries()) {\n const asset = await assets.create({\n tenantId: this.tenantId,\n ownerProfileId: contributor?.profileId || null,\n name: attachment.filename || `Contribution attachment ${index + 1}`,\n description: `Promoted from contribution ${this.id || ''}`.trim(),\n mimeType: attachment.mimeType || 'application/octet-stream',\n sourceUri:\n attachment.sourceUri ||\n attachment.fileKey ||\n `held://content-contribution/${attachment.id || index}`,\n typeSlug: inferAssetTypeSlug(attachment.mimeType || ''),\n statusSlug: 'draft',\n sourceType: 'content-contribution',\n externalId: attachment.id || '',\n });\n await asset.save();\n\n await content.addAsset(\n asset,\n promotion.assetRelationship || 'attachment',\n index,\n );\n\n attachment.promotedAssetId = asset.id || '';\n await attachment.save();\n promotedAssets.push({\n attachmentId: attachment.id || null,\n assetId: asset.id || null,\n });\n }\n }\n\n this.promotedContentId = content.id || '';\n this.promotedAt = new Date();\n this.status = 'promoted';\n this.editorNotes = options.editorNote || this.editorNotes;\n\n const metadata = this.getMetadata();\n metadata.promotion = {\n contentId: content.id || null,\n contentStatus: content.status || null,\n promotedAt: this.promotedAt.toISOString(),\n assetIds: promotedAssets.map((item) => item.assetId).filter(Boolean),\n };\n this.setMetadata(metadata);\n await this.save();\n\n return {\n contribution: this.toJSON(),\n content: content.toJSON(),\n assets: promotedAssets,\n };\n }\n}\n","import type { SmrtObjectOptions } from '@happyvertical/smrt-core';\nimport {\n crossPackageRef,\n foreignKey,\n SmrtObject,\n smrt,\n} from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport type { ContentContributionChannel } from './content-contribution-config';\n\nexport interface ContentContributionAttachmentOptions\n extends SmrtObjectOptions {\n contributionId?: string;\n revisionId?: string | null;\n filename?: string;\n mimeType?: string;\n size?: number;\n fileKey?: string | null;\n sourceUri?: string | null;\n channel?: ContentContributionChannel;\n promotedAssetId?: string | null;\n metadata?: Record<string, unknown> | string;\n tenantId?: string | null;\n createdAt?: Date;\n updatedAt?: Date;\n}\n\nfunction parseMetadata(raw: unknown): Record<string, unknown> {\n if (!raw) {\n return {};\n }\n\n if (typeof raw === 'object') {\n return { ...(raw as Record<string, unknown>) };\n }\n\n if (typeof raw !== 'string') {\n return {};\n }\n\n try {\n const parsed = JSON.parse(raw);\n return parsed && typeof parsed === 'object'\n ? (parsed as Record<string, unknown>)\n : {};\n } catch {\n return {};\n }\n}\n\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableName: 'content_contribution_attachments',\n conflictColumns: ['id'],\n api: { include: ['list', 'get', 'create', 'update', 'delete'] },\n mcp: { include: ['list', 'get', 'create', 'update', 'delete'] },\n cli: true,\n})\nexport class ContentContributionAttachment extends SmrtObject {\n @foreignKey('ContentContribution', { required: true })\n contributionId = '';\n\n @foreignKey('ContentContributionRevision')\n revisionId = '';\n\n filename = '';\n mimeType = '';\n size = 0;\n fileKey = '';\n sourceUri = '';\n channel: ContentContributionChannel = 'web';\n\n @crossPackageRef('@happyvertical/smrt-assets:Asset')\n promotedAssetId = '';\n\n metadata = '';\n\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n createdAt = new Date();\n updatedAt = new Date();\n\n constructor(options: ContentContributionAttachmentOptions = {}) {\n super(options);\n if (options.contributionId !== undefined)\n this.contributionId = options.contributionId;\n if (options.revisionId !== undefined)\n this.revisionId = options.revisionId || '';\n if (options.filename !== undefined) this.filename = options.filename;\n if (options.mimeType !== undefined) this.mimeType = options.mimeType;\n if (options.size !== undefined) this.size = options.size;\n if (options.fileKey !== undefined) this.fileKey = options.fileKey || '';\n if (options.sourceUri !== undefined)\n this.sourceUri = options.sourceUri || '';\n if (options.channel !== undefined) this.channel = options.channel;\n if (options.promotedAssetId !== undefined)\n this.promotedAssetId = options.promotedAssetId || '';\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n if (options.createdAt) this.createdAt = options.createdAt;\n if (options.updatedAt) this.updatedAt = options.updatedAt;\n if (options.metadata !== undefined) {\n this.metadata =\n typeof options.metadata === 'string'\n ? options.metadata\n : JSON.stringify(options.metadata);\n }\n }\n\n getMetadata(): Record<string, unknown> {\n return parseMetadata(this.metadata);\n }\n\n protected override transformJSON(json: Record<string, unknown>) {\n return {\n ...json,\n revisionId: this.revisionId || null,\n fileKey: this.fileKey || null,\n sourceUri: this.sourceUri || null,\n promotedAssetId: this.promotedAssetId || null,\n metadata: this.getMetadata(),\n };\n }\n}\n","import { SmrtCollection } from '@happyvertical/smrt-core';\nimport { ContentContributionAttachment } from './content-contribution-attachment';\n\nexport class ContentContributionAttachmentCollection extends SmrtCollection<ContentContributionAttachment> {\n static readonly _itemClass = ContentContributionAttachment;\n\n async listForContribution(\n contributionId: string,\n ): Promise<ContentContributionAttachment[]> {\n return this.list({\n where: { contributionId },\n orderBy: 'created_at ASC',\n });\n }\n\n async listForRevision(\n revisionId: string,\n ): Promise<ContentContributionAttachment[]> {\n return this.list({\n where: { revisionId },\n orderBy: 'created_at ASC',\n });\n }\n}\n","import type { SmrtObjectOptions } from '@happyvertical/smrt-core';\nimport {\n crossPackageRef,\n foreignKey,\n SmrtObject,\n smrt,\n} from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport type { ContentContributionChannel } from './content-contribution-config';\n\nexport interface ContentContributionRevisionOptions extends SmrtObjectOptions {\n contributionId?: string;\n revisionNumber?: number;\n channel?: ContentContributionChannel;\n title?: string;\n description?: string | null;\n body?: string | null;\n sourceMessageId?: string | null;\n sourceThreadKey?: string | null;\n metadata?: Record<string, unknown> | string;\n tenantId?: string | null;\n createdAt?: Date;\n updatedAt?: Date;\n}\n\nfunction parseMetadata(raw: unknown): Record<string, unknown> {\n if (!raw) {\n return {};\n }\n\n if (typeof raw === 'object') {\n return { ...(raw as Record<string, unknown>) };\n }\n\n if (typeof raw !== 'string') {\n return {};\n }\n\n try {\n const parsed = JSON.parse(raw);\n return parsed && typeof parsed === 'object'\n ? (parsed as Record<string, unknown>)\n : {};\n } catch {\n return {};\n }\n}\n\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableName: 'content_contribution_revisions',\n conflictColumns: ['contribution_id', 'revision_number'],\n api: { include: ['list', 'get', 'create', 'update', 'delete'] },\n mcp: { include: ['list', 'get', 'create', 'update', 'delete'] },\n cli: true,\n})\nexport class ContentContributionRevision extends SmrtObject {\n @foreignKey('ContentContribution', { required: true })\n contributionId = '';\n\n revisionNumber = 1;\n channel: ContentContributionChannel = 'web';\n title = '';\n description = '';\n body = '';\n\n @crossPackageRef('@happyvertical/smrt-messages:Message')\n sourceMessageId = '';\n\n sourceThreadKey = '';\n metadata = '';\n\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n createdAt = new Date();\n updatedAt = new Date();\n\n constructor(options: ContentContributionRevisionOptions = {}) {\n super(options);\n if (options.contributionId !== undefined)\n this.contributionId = options.contributionId;\n if (options.revisionNumber !== undefined)\n this.revisionNumber = options.revisionNumber;\n if (options.channel !== undefined) this.channel = options.channel;\n if (options.title !== undefined) this.title = options.title;\n if (options.description !== undefined)\n this.description = options.description || '';\n if (options.body !== undefined) this.body = options.body || '';\n if (options.sourceMessageId !== undefined)\n this.sourceMessageId = options.sourceMessageId || '';\n if (options.sourceThreadKey !== undefined)\n this.sourceThreadKey = options.sourceThreadKey || '';\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n if (options.createdAt) this.createdAt = options.createdAt;\n if (options.updatedAt) this.updatedAt = options.updatedAt;\n if (options.metadata !== undefined) {\n this.metadata =\n typeof options.metadata === 'string'\n ? options.metadata\n : JSON.stringify(options.metadata);\n }\n }\n\n getMetadata(): Record<string, unknown> {\n return parseMetadata(this.metadata);\n }\n\n protected override transformJSON(json: Record<string, unknown>) {\n return {\n ...json,\n sourceMessageId: this.sourceMessageId || null,\n sourceThreadKey: this.sourceThreadKey || null,\n metadata: this.getMetadata(),\n };\n }\n}\n","import { SmrtCollection } from '@happyvertical/smrt-core';\nimport { ContentContributionRevision } from './content-contribution-revision';\n\nexport class ContentContributionRevisionCollection extends SmrtCollection<ContentContributionRevision> {\n static readonly _itemClass = ContentContributionRevision;\n\n async listForContribution(\n contributionId: string,\n ): Promise<ContentContributionRevision[]> {\n return this.list({\n where: { contributionId },\n orderBy: 'revision_number ASC',\n });\n }\n\n async getLatestForContribution(\n contributionId: string,\n ): Promise<ContentContributionRevision | null> {\n const revisions = await this.list({\n where: { contributionId },\n orderBy: 'revision_number DESC',\n limit: 1,\n });\n\n return revisions[0] || null;\n }\n}\n","import type { SmrtObjectOptions } from '@happyvertical/smrt-core';\nimport { field, SmrtObject, smrt } from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport {\n type ContentContributionChannel,\n type ContentContributionIntakeRules,\n type ContentContributionPromotionMapping,\n type ContentContributionTypeDefinition,\n hasStaticContentContributionType,\n} from './content-contribution-config';\nimport { getQueryRows, isMissingTableError } from './database-utils';\n\nexport interface ContentContributionTypeOptions extends SmrtObjectOptions {\n key?: string;\n label?: string;\n enabled?: boolean;\n allowedChannels?: ContentContributionChannel[] | string;\n allowText?: boolean;\n allowFiles?: boolean;\n allowEmptyText?: boolean;\n intakeRules?: ContentContributionIntakeRules | string;\n promotion?: ContentContributionPromotionMapping | string;\n metadata?: Record<string, unknown> | string;\n tenantId?: string | null;\n createdAt?: Date;\n updatedAt?: Date;\n}\n\nfunction parseJSON<T>(raw: unknown, fallback: T): T {\n if (!raw) {\n return fallback;\n }\n\n if (typeof raw === 'object') {\n return structuredClone(raw as T);\n }\n\n if (typeof raw !== 'string') {\n return fallback;\n }\n\n try {\n const parsed = JSON.parse(raw);\n return parsed && typeof parsed === 'object' ? (parsed as T) : fallback;\n } catch {\n return fallback;\n }\n}\n\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableName: 'content_contribution_types',\n conflictColumns: ['key'],\n api: { include: ['list', 'get', 'create', 'update', 'delete'] },\n mcp: { include: ['list', 'get', 'create', 'update', 'delete'] },\n cli: true,\n})\nexport class ContentContributionType extends SmrtObject {\n @field({ required: true })\n key = '';\n\n label = '';\n enabled = true;\n allowedChannels = '';\n allowText = true;\n allowFiles = false;\n allowEmptyText = false;\n intakeRules = '';\n promotion = '';\n metadata = '';\n\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n createdAt = new Date();\n updatedAt = new Date();\n\n constructor(options: ContentContributionTypeOptions = {}) {\n super(options);\n if (options.key !== undefined) this.key = options.key;\n if (options.label !== undefined) this.label = options.label;\n if (options.enabled !== undefined) this.enabled = options.enabled;\n if (options.allowText !== undefined) this.allowText = options.allowText;\n if (options.allowFiles !== undefined) this.allowFiles = options.allowFiles;\n if (options.allowEmptyText !== undefined)\n this.allowEmptyText = options.allowEmptyText;\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n if (options.createdAt) this.createdAt = options.createdAt;\n if (options.updatedAt) this.updatedAt = options.updatedAt;\n\n if (options.allowedChannels !== undefined) {\n this.allowedChannels =\n typeof options.allowedChannels === 'string'\n ? options.allowedChannels\n : JSON.stringify(options.allowedChannels);\n }\n\n if (options.intakeRules !== undefined) {\n this.intakeRules =\n typeof options.intakeRules === 'string'\n ? options.intakeRules\n : JSON.stringify(options.intakeRules);\n }\n\n if (options.promotion !== undefined) {\n this.promotion =\n typeof options.promotion === 'string'\n ? options.promotion\n : JSON.stringify(options.promotion);\n }\n\n if (options.metadata !== undefined) {\n this.metadata =\n typeof options.metadata === 'string'\n ? options.metadata\n : JSON.stringify(options.metadata);\n }\n }\n\n getAllowedChannels(): ContentContributionChannel[] {\n const channels = parseJSON<ContentContributionChannel[]>(\n this.allowedChannels,\n [],\n );\n return channels.length > 0 ? channels : ['web'];\n }\n\n setAllowedChannels(channels: ContentContributionChannel[]): void {\n this.allowedChannels = JSON.stringify(channels);\n }\n\n getIntakeRules(): ContentContributionIntakeRules {\n return parseJSON<ContentContributionIntakeRules>(this.intakeRules, {});\n }\n\n setIntakeRules(rules: ContentContributionIntakeRules): void {\n this.intakeRules = JSON.stringify(rules || {});\n }\n\n getPromotion(): ContentContributionPromotionMapping {\n return parseJSON<ContentContributionPromotionMapping>(this.promotion, {});\n }\n\n setPromotion(promotion: ContentContributionPromotionMapping): void {\n this.promotion = JSON.stringify(promotion || {});\n }\n\n getMetadata(): Record<string, unknown> {\n return parseJSON<Record<string, unknown>>(this.metadata, {});\n }\n\n setMetadata(metadata: Record<string, unknown>): void {\n this.metadata = JSON.stringify(metadata || {});\n }\n\n toDefinition(): ContentContributionTypeDefinition {\n return {\n key: this.key,\n label: this.label || this.key,\n enabled: this.enabled !== false,\n allowedChannels: this.getAllowedChannels(),\n allowText: this.allowText !== false,\n allowFiles: this.allowFiles === true,\n allowEmptyText: this.allowEmptyText === true,\n intakeRules: this.getIntakeRules(),\n promotion: this.getPromotion(),\n metadata: this.getMetadata(),\n };\n }\n\n protected override transformJSON(json: Record<string, unknown>) {\n return {\n ...json,\n allowedChannels: this.getAllowedChannels(),\n intakeRules: this.getIntakeRules(),\n promotion: this.getPromotion(),\n metadata: this.getMetadata(),\n };\n }\n\n protected override async validateBeforeSave(): Promise<void> {\n await super.validateBeforeSave();\n\n if (!this.key) {\n throw new Error('Contribution type key is required.');\n }\n\n const promotion = this.getPromotion();\n if (!promotion.targetContentType) {\n throw new Error(\n `Contribution type \"${this.key}\" must define promotion.targetContentType.`,\n );\n }\n }\n\n override async delete(): Promise<void> {\n if (!this.db) {\n return super.delete();\n }\n\n const hasFallback = hasStaticContentContributionType(this.key);\n\n if (!hasFallback) {\n try {\n const existing = await this.db.query(\n 'SELECT id FROM content_contributions WHERE contribution_type_key = ? LIMIT 1',\n this.key,\n );\n const rows = getQueryRows(existing);\n\n if (rows.length > 0) {\n throw new Error(\n `Cannot delete contribution type \"${this.key}\" because contributions already reference it.`,\n );\n }\n } catch (error) {\n if (\n error instanceof Error &&\n error.message.includes('already reference it')\n ) {\n throw error;\n }\n if (!isMissingTableError(error, 'content_contributions')) {\n throw error;\n }\n }\n }\n\n return super.delete();\n }\n}\n","import { SmrtCollection } from '@happyvertical/smrt-core';\nimport { ContentContributionType } from './content-contribution-type';\n\nexport class ContentContributionTypeCollection extends SmrtCollection<ContentContributionType> {\n static readonly _itemClass = ContentContributionType;\n\n async getByKey(key: string): Promise<ContentContributionType | null> {\n return this.get({ key });\n }\n}\n","import type { SmrtObjectOptions } from '@happyvertical/smrt-core';\nimport {\n crossPackageRef,\n field,\n SmrtObject,\n smrt,\n} from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport type { ContentContributorTrustLevel } from './content-contribution-config';\n\nexport interface ContentContributorOptions extends SmrtObjectOptions {\n profileId?: string | null;\n email?: string;\n name?: string;\n trustLevel?: ContentContributorTrustLevel;\n metadata?: Record<string, unknown> | string;\n tenantId?: string | null;\n createdAt?: Date;\n updatedAt?: Date;\n}\n\nfunction parseMetadata(raw: unknown): Record<string, unknown> {\n if (!raw) {\n return {};\n }\n\n if (typeof raw === 'object') {\n return { ...(raw as Record<string, unknown>) };\n }\n\n if (typeof raw !== 'string') {\n return {};\n }\n\n try {\n const parsed = JSON.parse(raw);\n return parsed && typeof parsed === 'object'\n ? (parsed as Record<string, unknown>)\n : {};\n } catch {\n return {};\n }\n}\n\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableName: 'content_contributors',\n conflictColumns: ['email'],\n api: { include: ['list', 'get', 'create', 'update', 'delete'] },\n mcp: { include: ['list', 'get', 'create', 'update', 'delete'] },\n cli: true,\n})\nexport class ContentContributor extends SmrtObject {\n @crossPackageRef('@happyvertical/smrt-profiles:Profile')\n profileId = '';\n\n @field({ required: true })\n email = '';\n\n name = '';\n trustLevel: ContentContributorTrustLevel = 'standard';\n metadata = '';\n\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n createdAt = new Date();\n updatedAt = new Date();\n\n constructor(options: ContentContributorOptions = {}) {\n super(options);\n if (options.profileId !== undefined)\n this.profileId = options.profileId || '';\n if (options.email !== undefined)\n this.email = options.email.toLowerCase().trim();\n if (options.name !== undefined) this.name = options.name;\n if (options.trustLevel !== undefined) this.trustLevel = options.trustLevel;\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n if (options.createdAt) this.createdAt = options.createdAt;\n if (options.updatedAt) this.updatedAt = options.updatedAt;\n if (options.metadata !== undefined) {\n this.metadata =\n typeof options.metadata === 'string'\n ? options.metadata\n : JSON.stringify(options.metadata);\n }\n }\n\n getMetadata(): Record<string, unknown> {\n return parseMetadata(this.metadata);\n }\n\n setMetadata(metadata: Record<string, unknown>): void {\n this.metadata = JSON.stringify(metadata || {});\n }\n\n protected override transformJSON(json: Record<string, unknown>) {\n return {\n ...json,\n profileId: this.profileId || null,\n metadata: this.getMetadata(),\n };\n }\n}\n","import { SmrtCollection } from '@happyvertical/smrt-core';\nimport {\n ProfileCollection,\n ProfileTypeCollection,\n} from '@happyvertical/smrt-profiles';\nimport { ContentContributor } from './content-contributor';\n\nexport class ContentContributorCollection extends SmrtCollection<ContentContributor> {\n static readonly _itemClass = ContentContributor;\n\n async getByEmail(email: string): Promise<ContentContributor | null> {\n return this.get({ email: email.toLowerCase().trim() });\n }\n\n async getByProfileId(profileId: string): Promise<ContentContributor | null> {\n return this.get({ profileId });\n }\n\n async findOrCreateByEmail(options: {\n email: string;\n name?: string | null;\n tenantId?: string | null;\n }): Promise<ContentContributor> {\n const normalizedEmail = options.email.toLowerCase().trim();\n const existing = await this.getByEmail(normalizedEmail);\n if (existing) {\n if (options.name && !existing.name) {\n existing.name = options.name;\n await existing.save();\n }\n return existing;\n }\n\n const profileCollection = await ProfileCollection.create(this.options);\n let profile = await profileCollection.findByEmail(normalizedEmail);\n\n if (!profile) {\n const profileTypes = await ProfileTypeCollection.create(this.options);\n const personType = await profileTypes.getOrCreateBySlug('person', {\n name: 'Person',\n description: 'Individual person',\n });\n\n profile = await profileCollection.create({\n typeId: personType.id || undefined,\n email: normalizedEmail,\n name: options.name || normalizedEmail.split('@')[0],\n tenantId: options.tenantId || undefined,\n });\n await profile.save();\n }\n\n const contributor = await this.create({\n email: normalizedEmail,\n name: options.name || profile.name || normalizedEmail.split('@')[0],\n profileId: profile.id || undefined,\n tenantId: options.tenantId || undefined,\n trustLevel: 'standard',\n });\n await contributor.save();\n return contributor;\n }\n}\n","import { SmrtCollection, smrt } from '@happyvertical/smrt-core';\nimport {\n AttachmentCollection,\n type Email,\n EmailCollection,\n} from '@happyvertical/smrt-messages';\nimport type { ContentContributionAttachmentInput } from './content-contribution';\nimport { ContentContribution } from './content-contribution';\nimport type { ContentContributionTypeDefinition } from './content-contribution-config';\nimport {\n evaluateContributionIntake,\n getContentContributionTypeConfigState,\n getEffectiveContentContributionConfig,\n} from './content-contribution-config';\nimport { ContentContributorCollection } from './content-contributors';\n\nexport interface SubmitWebContentContributionOptions {\n typeKey: string;\n contributorEmail: string;\n contributorName?: string | null;\n title?: string | null;\n description?: string | null;\n body?: string | null;\n attachments?: ContentContributionAttachmentInput[];\n metadata?: Record<string, unknown>;\n tenantId?: string | null;\n}\n\nexport interface IngestEmailContentContributionOptions {\n emailId: string;\n typeKey?: string | null;\n tenantId?: string | null;\n}\n\nfunction toContributionStatus(\n decision: ReturnType<typeof evaluateContributionIntake>['decision'],\n) {\n if (decision === 'quarantined') {\n return 'quarantined' as const;\n }\n\n if (decision === 'rejected') {\n return 'rejected' as const;\n }\n\n return 'submitted' as const;\n}\n\nfunction pickDefaultEmailType(\n types: ContentContributionTypeDefinition[],\n): ContentContributionTypeDefinition | null {\n const emailTypes = types.filter(\n (type) =>\n type.enabled !== false && (type.allowedChannels || []).includes('email'),\n );\n\n return emailTypes.length === 1 ? emailTypes[0] : null;\n}\n\n@smrt({\n api: {\n include: [\n 'submitWebContribution',\n 'ingestEmailContribution',\n 'listForContributor',\n 'listInboxAction',\n 'getContributionTypesAction',\n ],\n routes: {\n submitWebContribution: {\n scope: 'collection',\n method: 'POST',\n path: 'submit',\n },\n ingestEmailContribution: {\n scope: 'collection',\n method: 'POST',\n path: 'ingest-email',\n },\n listForContributor: {\n scope: 'collection',\n method: 'GET',\n path: 'by-contributor',\n },\n listInboxAction: {\n scope: 'collection',\n method: 'GET',\n path: 'inbox',\n },\n getContributionTypesAction: {\n scope: 'collection',\n method: 'GET',\n path: 'types',\n },\n },\n },\n mcp: false,\n cli: false,\n})\nexport class ContentContributions extends SmrtCollection<ContentContribution> {\n static readonly _itemClass = ContentContribution;\n\n private async getContributorCollection() {\n return ContentContributorCollection.create(this.options);\n }\n\n private async getEmailCollection() {\n return EmailCollection.create(this.options);\n }\n\n private async getAttachmentCollection() {\n return AttachmentCollection.create(this.options);\n }\n\n private async resolveSubmissionType(\n typeKey: string | null | undefined,\n ): Promise<ContentContributionTypeDefinition> {\n const effective = await getEffectiveContentContributionConfig({\n db: this.db,\n });\n\n if (typeKey) {\n const match = effective.types.find((type) => type.key === typeKey);\n if (match) {\n return match;\n }\n throw new Error(`Unknown contribution type \"${typeKey}\".`);\n }\n\n const defaultType = pickDefaultEmailType(effective.types);\n if (!defaultType) {\n throw new Error(\n 'A contribution type key is required unless there is exactly one email-enabled type.',\n );\n }\n\n return defaultType;\n }\n\n async getContributionTypesAction() {\n return getContentContributionTypeConfigState({ db: this.db });\n }\n\n async listForContributor(\n options: { contributorId?: string; contributorEmail?: string } = {},\n ) {\n let contributorId = options.contributorId;\n\n if (!contributorId && options.contributorEmail) {\n const contributors = await this.getContributorCollection();\n const contributor = await contributors.getByEmail(\n options.contributorEmail,\n );\n contributorId = contributor?.id || undefined;\n }\n\n if (!contributorId) {\n return [];\n }\n\n return this.list({\n where: { contributorId },\n orderBy: 'updated_at DESC',\n });\n }\n\n async listInboxAction(\n options: { statuses?: string | string[] } = {},\n ): Promise<ContentContribution[]> {\n const requested = Array.isArray(options.statuses)\n ? options.statuses\n : typeof options.statuses === 'string'\n ? options.statuses.split(',').map((item) => item.trim())\n : ['submitted', 'quarantined', 'needs_changes', 'approved'];\n\n const contributions = await this.list({\n orderBy: 'updated_at DESC',\n });\n\n return contributions.filter((contribution) =>\n requested.includes(contribution.status),\n );\n }\n\n async submitWebContribution(options: SubmitWebContentContributionOptions) {\n const type = await this.resolveSubmissionType(options.typeKey);\n const contributors = await this.getContributorCollection();\n const contributor = await contributors.findOrCreateByEmail({\n email: options.contributorEmail,\n name: options.contributorName || null,\n tenantId: options.tenantId ?? null,\n });\n\n const intake = evaluateContributionIntake({\n contributionType: type,\n trustLevel: contributor.trustLevel,\n channel: 'web',\n title: options.title || null,\n description: options.description || null,\n body: options.body || null,\n attachments: options.attachments || [],\n });\n\n const status = toContributionStatus(intake.decision);\n\n const contribution = await this.create({\n contributorId: contributor.id || '',\n contributionTypeKey: type.key,\n status,\n intakeDecision: intake.decision,\n channel: 'web',\n title: options.title || '',\n description: options.description || '',\n body: options.body || '',\n contributorEmail: contributor.email,\n contributorName: contributor.name,\n editorNotes: intake.reasons.join('\\n'),\n tenantId: options.tenantId ?? null,\n metadata: JSON.stringify({\n intake: {\n decision: intake.decision,\n reasons: intake.reasons,\n },\n submission: options.metadata || {},\n }),\n });\n await contribution.save();\n\n await contribution.appendRevisionAction({\n title: options.title,\n description: options.description,\n body: options.body,\n attachments: options.attachments || [],\n channel: 'web',\n metadata: {\n source: 'web',\n },\n });\n\n if (\n contributor.trustLevel === 'trusted' &&\n intake.decision === 'accepted' &&\n type.promotion?.autoPromoteTrusted === true\n ) {\n return contribution.approveAction({\n editorNote: 'Auto-promoted trusted contributor submission.',\n targetStatus: type.promotion?.targetContentStatus || 'draft',\n });\n }\n\n return {\n contribution: contribution.toJSON(),\n intake,\n };\n }\n\n async ingestEmailContribution(\n options: IngestEmailContentContributionOptions,\n ) {\n const emailCollection = await this.getEmailCollection();\n // EmailCollection.get() is typed as the Message base; the rows it returns\n // are Emails, so narrow to Email to read the email-specific fields below.\n const email = (await emailCollection.get({\n id: options.emailId,\n })) as Email | null;\n if (!email) {\n throw new Error(`Email \"${options.emailId}\" not found.`);\n }\n\n const type = await this.resolveSubmissionType(options.typeKey);\n const contributors = await this.getContributorCollection();\n const contributor = await contributors.findOrCreateByEmail({\n email: email.fromAddress,\n name: email.fromName || null,\n tenantId: options.tenantId ?? null,\n });\n\n const attachmentCollection = await this.getAttachmentCollection();\n const inboundAttachments = await attachmentCollection.getByMessage(\n email.id || '',\n );\n const normalizedAttachments: ContentContributionAttachmentInput[] =\n inboundAttachments\n .filter((attachment) => !attachment.isInline())\n .map((attachment) => ({\n filename: attachment.filename || 'attachment',\n mimeType: attachment.contentType || 'application/octet-stream',\n size: attachment.size || 0,\n sourceUri: attachment.filePath || attachment.sourceUrl || null,\n metadata: {\n messageId: email.id || null,\n attachmentId: attachment.id || null,\n },\n }));\n\n const threadKey =\n email.threadId || email.messageId || email.inReplyTo || email.id || '';\n\n const intake = evaluateContributionIntake({\n contributionType: type,\n trustLevel: contributor.trustLevel,\n channel: 'email',\n title: email.subject || null,\n body: email.textBody || email.body || null,\n attachments: normalizedAttachments,\n });\n\n const existing =\n threadKey &&\n (await this.get({\n threadKey,\n contributorId: contributor.id || '',\n }));\n\n if (existing) {\n existing.intakeDecision = intake.decision;\n existing.editorNotes = intake.reasons.join('\\n');\n\n const metadata = existing.getMetadata();\n metadata.lastEmailIntake = {\n decision: intake.decision,\n reasons: intake.reasons,\n emailId: email.id || null,\n };\n existing.setMetadata(metadata);\n\n if (intake.decision === 'rejected') {\n existing.status = 'rejected';\n existing.rejectedAt = new Date();\n await existing.save();\n\n return {\n contribution: existing.toJSON(),\n intake,\n revision: null,\n attachments: (await existing.getAttachments()).map((item) =>\n item.toJSON(),\n ),\n };\n }\n\n existing.status = toContributionStatus(intake.decision);\n await existing.save();\n\n const appended = await existing.appendRevisionAction({\n title: email.subject || existing.title,\n body: email.textBody || email.body || '',\n channel: 'email',\n sourceMessageId: email.id || '',\n sourceThreadKey: threadKey,\n attachments: normalizedAttachments,\n metadata: {\n source: 'email-reply',\n emailId: email.id || null,\n },\n });\n\n return {\n ...appended,\n intake,\n };\n }\n\n const status = toContributionStatus(intake.decision);\n\n const contribution = await this.create({\n contributorId: contributor.id || '',\n contributionTypeKey: type.key,\n status,\n intakeDecision: intake.decision,\n channel: 'email',\n title: email.subject || '',\n description: '',\n body: email.textBody || email.body || '',\n contributorEmail: contributor.email,\n contributorName: contributor.name,\n threadKey,\n sourceMessageId: email.id || '',\n editorNotes: intake.reasons.join('\\n'),\n tenantId: options.tenantId ?? null,\n metadata: JSON.stringify({\n intake: {\n decision: intake.decision,\n reasons: intake.reasons,\n },\n email: {\n emailId: email.id || null,\n messageId: email.messageId || null,\n inReplyTo: email.inReplyTo || null,\n threadId: email.threadId || null,\n },\n }),\n });\n await contribution.save();\n\n await contribution.appendRevisionAction({\n title: email.subject || '',\n body: email.textBody || email.body || '',\n channel: 'email',\n sourceMessageId: email.id || null,\n sourceThreadKey: threadKey,\n attachments: normalizedAttachments,\n metadata: {\n source: 'email',\n emailId: email.id || null,\n },\n });\n\n if (\n contributor.trustLevel === 'trusted' &&\n intake.decision === 'accepted' &&\n type.promotion?.autoPromoteTrusted === true\n ) {\n return contribution.approveAction({\n editorNote: 'Auto-promoted trusted contributor email submission.',\n targetStatus: type.promotion?.targetContentStatus || 'draft',\n });\n }\n\n return {\n contribution: contribution.toJSON(),\n intake,\n };\n }\n}\n","import type { SmrtObjectOptions } from '@happyvertical/smrt-core';\nimport {\n crossPackageRef,\n foreignKey,\n SmrtObject,\n smrt,\n} from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport type {\n ContentCorrectionStatus,\n ContentCorrectionType,\n} from './content-governance';\n\nexport interface ContentCorrectionOptions extends SmrtObjectOptions {\n contentId?: string;\n contentVersionId?: string;\n factId?: string;\n replacementFactId?: string;\n correctionType?: ContentCorrectionType;\n status?: ContentCorrectionStatus;\n summary?: string;\n incorrectText?: string;\n correctedText?: string;\n publicNote?: string;\n metadata?: string | Record<string, unknown>;\n tenantId?: string | null;\n publishedAt?: Date | null;\n createdAt?: Date;\n updatedAt?: Date;\n}\n\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableName: 'content_corrections',\n api: { include: ['list', 'get', 'create', 'update'] },\n mcp: { include: ['list', 'get', 'create', 'update'] },\n cli: true,\n})\nexport class ContentCorrection extends SmrtObject {\n @foreignKey('Content', { required: true })\n contentId = '';\n\n @foreignKey('ContentVersion')\n contentVersionId = '';\n\n @crossPackageRef('@happyvertical/smrt-facts:Fact')\n factId = '';\n\n @crossPackageRef('@happyvertical/smrt-facts:Fact')\n replacementFactId = '';\n correctionType: ContentCorrectionType = 'fact';\n status: ContentCorrectionStatus = 'draft';\n summary = '';\n incorrectText = '';\n correctedText = '';\n publicNote = '';\n metadata = '';\n\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n publishedAt: Date | null = null;\n createdAt = new Date();\n updatedAt = new Date();\n\n constructor(options: ContentCorrectionOptions = {}) {\n super(options);\n if (options.contentId) this.contentId = options.contentId;\n if (options.contentVersionId !== undefined)\n this.contentVersionId = options.contentVersionId;\n if (options.factId !== undefined) this.factId = options.factId;\n if (options.replacementFactId !== undefined)\n this.replacementFactId = options.replacementFactId;\n if (options.correctionType !== undefined)\n this.correctionType = options.correctionType;\n if (options.status !== undefined) this.status = options.status;\n if (options.summary !== undefined) this.summary = options.summary;\n if (options.incorrectText !== undefined)\n this.incorrectText = options.incorrectText;\n if (options.correctedText !== undefined)\n this.correctedText = options.correctedText;\n if (options.publicNote !== undefined) this.publicNote = options.publicNote;\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n if (options.publishedAt !== undefined)\n this.publishedAt = options.publishedAt;\n if (options.createdAt) this.createdAt = options.createdAt;\n if (options.updatedAt) this.updatedAt = options.updatedAt;\n\n if (options.metadata !== undefined) {\n this.metadata =\n typeof options.metadata === 'string'\n ? options.metadata\n : JSON.stringify(options.metadata);\n }\n }\n\n getMetadata(): Record<string, unknown> {\n try {\n return this.metadata ? JSON.parse(this.metadata) : {};\n } catch {\n return {};\n }\n }\n}\n","import { SmrtCollection } from '@happyvertical/smrt-core';\nimport { ContentCorrection } from './content-correction';\n\nexport class ContentCorrectionCollection extends SmrtCollection<ContentCorrection> {\n static readonly _itemClass = ContentCorrection;\n\n async listForContent(contentId: string): Promise<ContentCorrection[]> {\n return this.list({\n where: { contentId },\n orderBy: 'created_at DESC',\n });\n }\n\n async getPublishedForContent(\n contentId: string,\n ): Promise<ContentCorrection[]> {\n return this.list({\n where: { contentId, status: 'published' },\n orderBy: 'published_at DESC',\n });\n }\n\n async issue(\n options: ConstructorParameters<typeof ContentCorrection>[0],\n ): Promise<ContentCorrection> {\n if (!options) {\n return this.create({});\n }\n\n return this.create({\n ...options,\n metadata:\n typeof options.metadata === 'string'\n ? options.metadata\n : options.metadata\n ? JSON.stringify(options.metadata)\n : undefined,\n });\n }\n}\n","'use strict';\n\nconst nameStartChar = ':A-Za-z_\\\\u00C0-\\\\u00D6\\\\u00D8-\\\\u00F6\\\\u00F8-\\\\u02FF\\\\u0370-\\\\u037D\\\\u037F-\\\\u1FFF\\\\u200C-\\\\u200D\\\\u2070-\\\\u218F\\\\u2C00-\\\\u2FEF\\\\u3001-\\\\uD7FF\\\\uF900-\\\\uFDCF\\\\uFDF0-\\\\uFFFD';\nconst nameChar = nameStartChar + '\\\\-.\\\\d\\\\u00B7\\\\u0300-\\\\u036F\\\\u203F-\\\\u2040';\nexport const nameRegexp = '[' + nameStartChar + '][' + nameChar + ']*';\nconst regexName = new RegExp('^' + nameRegexp + '$');\n\nexport function getAllMatches(string, regex) {\n const matches = [];\n let match = regex.exec(string);\n while (match) {\n const allmatches = [];\n allmatches.startIndex = regex.lastIndex - match[0].length;\n const len = match.length;\n for (let index = 0; index < len; index++) {\n allmatches.push(match[index]);\n }\n matches.push(allmatches);\n match = regex.exec(string);\n }\n return matches;\n}\n\nexport const isName = function (string) {\n const match = regexName.exec(string);\n return !(match === null || typeof match === 'undefined');\n}\n\nexport function isExist(v) {\n return typeof v !== 'undefined';\n}\n\nexport function isEmptyObject(obj) {\n return Object.keys(obj).length === 0;\n}\n\nexport function getValue(v) {\n if (exports.isExist(v)) {\n return v;\n } else {\n return '';\n }\n}\n\n/**\n * Dangerous property names that could lead to prototype pollution or security issues\n */\nexport const DANGEROUS_PROPERTY_NAMES = [\n // '__proto__',\n // 'constructor',\n // 'prototype',\n 'hasOwnProperty',\n 'toString',\n 'valueOf',\n '__defineGetter__',\n '__defineSetter__',\n '__lookupGetter__',\n '__lookupSetter__'\n];\n\nexport const criticalProperties = [\"__proto__\", \"constructor\", \"prototype\"];","'use strict';\n\nimport { getAllMatches, isName } from './util.js';\n\nconst defaultOptions = {\n allowBooleanAttributes: false, //A tag can have attributes without any value\n unpairedTags: []\n};\n\n//const tagsPattern = new RegExp(\"<\\\\/?([\\\\w:\\\\-_\\.]+)\\\\s*\\/?>\",\"g\");\nexport function validate(xmlData, options) {\n options = Object.assign({}, defaultOptions, options);\n\n //xmlData = xmlData.replace(/(\\r\\n|\\n|\\r)/gm,\"\");//make it single line\n //xmlData = xmlData.replace(/(^\\s*<\\?xml.*?\\?>)/g,\"\");//Remove XML starting tag\n //xmlData = xmlData.replace(/(<!DOCTYPE[\\s\\w\\\"\\.\\/\\-\\:]+(\\[.*\\])*\\s*>)/g,\"\");//Remove DOCTYPE\n const tags = [];\n let tagFound = false;\n\n //indicates that the root tag has been closed (aka. depth 0 has been reached)\n let reachedRoot = false;\n\n if (xmlData[0] === '\\ufeff') {\n // check for byte order mark (BOM)\n xmlData = xmlData.substr(1);\n }\n\n for (let i = 0; i < xmlData.length; i++) {\n\n if (xmlData[i] === '<' && xmlData[i + 1] === '?') {\n i += 2;\n i = readPI(xmlData, i);\n if (i.err) return i;\n } else if (xmlData[i] === '<') {\n //starting of tag\n //read until you reach to '>' avoiding any '>' in attribute value\n let tagStartPos = i;\n i++;\n\n if (xmlData[i] === '!') {\n i = readCommentAndCDATA(xmlData, i);\n continue;\n } else {\n let closingTag = false;\n if (xmlData[i] === '/') {\n //closing tag\n closingTag = true;\n i++;\n }\n //read tagname\n let tagName = '';\n for (; i < xmlData.length &&\n xmlData[i] !== '>' &&\n xmlData[i] !== ' ' &&\n xmlData[i] !== '\\t' &&\n xmlData[i] !== '\\n' &&\n xmlData[i] !== '\\r'; i++\n ) {\n tagName += xmlData[i];\n }\n tagName = tagName.trim();\n //console.log(tagName);\n\n if (tagName[tagName.length - 1] === '/') {\n //self closing tag without attributes\n tagName = tagName.substring(0, tagName.length - 1);\n //continue;\n i--;\n }\n if (!validateTagName(tagName)) {\n let msg;\n if (tagName.trim().length === 0) {\n msg = \"Invalid space after '<'.\";\n } else {\n msg = \"Tag '\" + tagName + \"' is an invalid name.\";\n }\n return getErrorObject('InvalidTag', msg, getLineNumberForPosition(xmlData, i));\n }\n\n const result = readAttributeStr(xmlData, i);\n if (result === false) {\n return getErrorObject('InvalidAttr', \"Attributes for '\" + tagName + \"' have open quote.\", getLineNumberForPosition(xmlData, i));\n }\n let attrStr = result.value;\n i = result.index;\n\n if (attrStr[attrStr.length - 1] === '/') {\n //self closing tag\n const attrStrStart = i - attrStr.length;\n attrStr = attrStr.substring(0, attrStr.length - 1);\n const isValid = validateAttributeString(attrStr, options);\n if (isValid === true) {\n tagFound = true;\n //continue; //text may presents after self closing tag\n } else {\n //the result from the nested function returns the position of the error within the attribute\n //in order to get the 'true' error line, we need to calculate the position where the attribute begins (i - attrStr.length) and then add the position within the attribute\n //this gives us the absolute index in the entire xml, which we can use to find the line at last\n return getErrorObject(isValid.err.code, isValid.err.msg, getLineNumberForPosition(xmlData, attrStrStart + isValid.err.line));\n }\n } else if (closingTag) {\n if (!result.tagClosed) {\n return getErrorObject('InvalidTag', \"Closing tag '\" + tagName + \"' doesn't have proper closing.\", getLineNumberForPosition(xmlData, i));\n } else if (attrStr.trim().length > 0) {\n return getErrorObject('InvalidTag', \"Closing tag '\" + tagName + \"' can't have attributes or invalid starting.\", getLineNumberForPosition(xmlData, tagStartPos));\n } else if (tags.length === 0) {\n return getErrorObject('InvalidTag', \"Closing tag '\" + tagName + \"' has not been opened.\", getLineNumberForPosition(xmlData, tagStartPos));\n } else {\n const otg = tags.pop();\n if (tagName !== otg.tagName) {\n let openPos = getLineNumberForPosition(xmlData, otg.tagStartPos);\n return getErrorObject('InvalidTag',\n \"Expected closing tag '\" + otg.tagName + \"' (opened in line \" + openPos.line + \", col \" + openPos.col + \") instead of closing tag '\" + tagName + \"'.\",\n getLineNumberForPosition(xmlData, tagStartPos));\n }\n\n //when there are no more tags, we reached the root level.\n if (tags.length == 0) {\n reachedRoot = true;\n }\n }\n } else {\n const isValid = validateAttributeString(attrStr, options);\n if (isValid !== true) {\n //the result from the nested function returns the position of the error within the attribute\n //in order to get the 'true' error line, we need to calculate the position where the attribute begins (i - attrStr.length) and then add the position within the attribute\n //this gives us the absolute index in the entire xml, which we can use to find the line at last\n return getErrorObject(isValid.err.code, isValid.err.msg, getLineNumberForPosition(xmlData, i - attrStr.length + isValid.err.line));\n }\n\n //if the root level has been reached before ...\n if (reachedRoot === true) {\n return getErrorObject('InvalidXml', 'Multiple possible root nodes found.', getLineNumberForPosition(xmlData, i));\n } else if (options.unpairedTags.indexOf(tagName) !== -1) {\n //don't push into stack\n } else {\n tags.push({ tagName, tagStartPos });\n }\n tagFound = true;\n }\n\n //skip tag text value\n //It may include comments and CDATA value\n for (i++; i < xmlData.length; i++) {\n if (xmlData[i] === '<') {\n if (xmlData[i + 1] === '!') {\n //comment or CADATA\n i++;\n i = readCommentAndCDATA(xmlData, i);\n continue;\n } else if (xmlData[i + 1] === '?') {\n i = readPI(xmlData, ++i);\n if (i.err) return i;\n } else {\n break;\n }\n } else if (xmlData[i] === '&') {\n const afterAmp = validateAmpersand(xmlData, i);\n if (afterAmp == -1)\n return getErrorObject('InvalidChar', \"char '&' is not expected.\", getLineNumberForPosition(xmlData, i));\n i = afterAmp;\n } else {\n if (reachedRoot === true && !isWhiteSpace(xmlData[i])) {\n return getErrorObject('InvalidXml', \"Extra text at the end\", getLineNumberForPosition(xmlData, i));\n }\n }\n } //end of reading tag text value\n if (xmlData[i] === '<') {\n i--;\n }\n }\n } else {\n if (isWhiteSpace(xmlData[i])) {\n continue;\n }\n return getErrorObject('InvalidChar', \"char '\" + xmlData[i] + \"' is not expected.\", getLineNumberForPosition(xmlData, i));\n }\n }\n\n if (!tagFound) {\n return getErrorObject('InvalidXml', 'Start tag expected.', 1);\n } else if (tags.length == 1) {\n return getErrorObject('InvalidTag', \"Unclosed tag '\" + tags[0].tagName + \"'.\", getLineNumberForPosition(xmlData, tags[0].tagStartPos));\n } else if (tags.length > 0) {\n return getErrorObject('InvalidXml', \"Invalid '\" +\n JSON.stringify(tags.map(t => t.tagName), null, 4).replace(/\\r?\\n/g, '') +\n \"' found.\", { line: 1, col: 1 });\n }\n\n return true;\n};\n\nfunction isWhiteSpace(char) {\n return char === ' ' || char === '\\t' || char === '\\n' || char === '\\r';\n}\n/**\n * Read Processing insstructions and skip\n * @param {*} xmlData\n * @param {*} i\n */\nfunction readPI(xmlData, i) {\n const start = i;\n for (; i < xmlData.length; i++) {\n if (xmlData[i] == '?' || xmlData[i] == ' ') {\n //tagname\n const tagname = xmlData.substr(start, i - start);\n if (i > 5 && tagname === 'xml') {\n return getErrorObject('InvalidXml', 'XML declaration allowed only at the start of the document.', getLineNumberForPosition(xmlData, i));\n } else if (xmlData[i] == '?' && xmlData[i + 1] == '>') {\n //check if valid attribut string\n i++;\n break;\n } else {\n continue;\n }\n }\n }\n return i;\n}\n\nfunction readCommentAndCDATA(xmlData, i) {\n if (xmlData.length > i + 5 && xmlData[i + 1] === '-' && xmlData[i + 2] === '-') {\n //comment\n for (i += 3; i < xmlData.length; i++) {\n if (xmlData[i] === '-' && xmlData[i + 1] === '-' && xmlData[i + 2] === '>') {\n i += 2;\n break;\n }\n }\n } else if (\n xmlData.length > i + 8 &&\n xmlData[i + 1] === 'D' &&\n xmlData[i + 2] === 'O' &&\n xmlData[i + 3] === 'C' &&\n xmlData[i + 4] === 'T' &&\n xmlData[i + 5] === 'Y' &&\n xmlData[i + 6] === 'P' &&\n xmlData[i + 7] === 'E'\n ) {\n let angleBracketsCount = 1;\n for (i += 8; i < xmlData.length; i++) {\n if (xmlData[i] === '<') {\n angleBracketsCount++;\n } else if (xmlData[i] === '>') {\n angleBracketsCount--;\n if (angleBracketsCount === 0) {\n break;\n }\n }\n }\n } else if (\n xmlData.length > i + 9 &&\n xmlData[i + 1] === '[' &&\n xmlData[i + 2] === 'C' &&\n xmlData[i + 3] === 'D' &&\n xmlData[i + 4] === 'A' &&\n xmlData[i + 5] === 'T' &&\n xmlData[i + 6] === 'A' &&\n xmlData[i + 7] === '['\n ) {\n for (i += 8; i < xmlData.length; i++) {\n if (xmlData[i] === ']' && xmlData[i + 1] === ']' && xmlData[i + 2] === '>') {\n i += 2;\n break;\n }\n }\n }\n\n return i;\n}\n\nconst doubleQuote = '\"';\nconst singleQuote = \"'\";\n\n/**\n * Keep reading xmlData until '<' is found outside the attribute value.\n * @param {string} xmlData\n * @param {number} i\n */\nfunction readAttributeStr(xmlData, i) {\n let attrStr = '';\n let startChar = '';\n let tagClosed = false;\n for (; i < xmlData.length; i++) {\n if (xmlData[i] === doubleQuote || xmlData[i] === singleQuote) {\n if (startChar === '') {\n startChar = xmlData[i];\n } else if (startChar !== xmlData[i]) {\n //if vaue is enclosed with double quote then single quotes are allowed inside the value and vice versa\n } else {\n startChar = '';\n }\n } else if (xmlData[i] === '>') {\n if (startChar === '') {\n tagClosed = true;\n break;\n }\n }\n attrStr += xmlData[i];\n }\n if (startChar !== '') {\n return false;\n }\n\n return {\n value: attrStr,\n index: i,\n tagClosed: tagClosed\n };\n}\n\n/**\n * Select all the attributes whether valid or invalid.\n */\nconst validAttrStrRegxp = new RegExp('(\\\\s*)([^\\\\s=]+)(\\\\s*=)?(\\\\s*([\\'\"])(([\\\\s\\\\S])*?)\\\\5)?', 'g');\n\n//attr, =\"sd\", a=\"amit's\", a=\"sd\"b=\"saf\", ab cd=\"\"\n\nfunction validateAttributeString(attrStr, options) {\n //console.log(\"start:\"+attrStr+\":end\");\n\n //if(attrStr.trim().length === 0) return true; //empty string\n\n const matches = getAllMatches(attrStr, validAttrStrRegxp);\n const attrNames = {};\n\n for (let i = 0; i < matches.length; i++) {\n if (matches[i][1].length === 0) {\n //nospace before attribute name: a=\"sd\"b=\"saf\"\n return getErrorObject('InvalidAttr', \"Attribute '\" + matches[i][2] + \"' has no space in starting.\", getPositionFromMatch(matches[i]))\n } else if (matches[i][3] !== undefined && matches[i][4] === undefined) {\n return getErrorObject('InvalidAttr', \"Attribute '\" + matches[i][2] + \"' is without value.\", getPositionFromMatch(matches[i]));\n } else if (matches[i][3] === undefined && !options.allowBooleanAttributes) {\n //independent attribute: ab\n return getErrorObject('InvalidAttr', \"boolean attribute '\" + matches[i][2] + \"' is not allowed.\", getPositionFromMatch(matches[i]));\n }\n /* else if(matches[i][6] === undefined){//attribute without value: ab=\n return { err: { code:\"InvalidAttr\",msg:\"attribute \" + matches[i][2] + \" has no value assigned.\"}};\n } */\n const attrName = matches[i][2];\n if (!validateAttrName(attrName)) {\n return getErrorObject('InvalidAttr', \"Attribute '\" + attrName + \"' is an invalid name.\", getPositionFromMatch(matches[i]));\n }\n if (!Object.prototype.hasOwnProperty.call(attrNames, attrName)) {\n //check for duplicate attribute.\n attrNames[attrName] = 1;\n } else {\n return getErrorObject('InvalidAttr', \"Attribute '\" + attrName + \"' is repeated.\", getPositionFromMatch(matches[i]));\n }\n }\n\n return true;\n}\n\nfunction validateNumberAmpersand(xmlData, i) {\n let re = /\\d/;\n if (xmlData[i] === 'x') {\n i++;\n re = /[\\da-fA-F]/;\n }\n for (; i < xmlData.length; i++) {\n if (xmlData[i] === ';')\n return i;\n if (!xmlData[i].match(re))\n break;\n }\n return -1;\n}\n\nfunction validateAmpersand(xmlData, i) {\n // https://www.w3.org/TR/xml/#dt-charref\n i++;\n if (xmlData[i] === ';')\n return -1;\n if (xmlData[i] === '#') {\n i++;\n return validateNumberAmpersand(xmlData, i);\n }\n let count = 0;\n for (; i < xmlData.length; i++, count++) {\n if (xmlData[i].match(/\\w/) && count < 20)\n continue;\n if (xmlData[i] === ';')\n break;\n return -1;\n }\n return i;\n}\n\nfunction getErrorObject(code, message, lineNumber) {\n return {\n err: {\n code: code,\n msg: message,\n line: lineNumber.line || lineNumber,\n col: lineNumber.col,\n },\n };\n}\n\nfunction validateAttrName(attrName) {\n return isName(attrName);\n}\n\n// const startsWithXML = /^xml/i;\n\nfunction validateTagName(tagname) {\n return isName(tagname) /* && !tagname.match(startsWithXML) */;\n}\n\n//this function returns the line number for the character at the given index\nfunction getLineNumberForPosition(xmlData, index) {\n const lines = xmlData.substring(0, index).split(/\\r?\\n/);\n return {\n line: lines.length,\n\n // column number is last line's length + 1, because column numbering starts at 1:\n col: lines[lines.length - 1].length + 1\n };\n}\n\n//this function returns the position of the first character of match within attrStr\nfunction getPositionFromMatch(match) {\n return match.startIndex + match[1].length;\n}\n","// ---------------------------------------------------------------------------\n// Complete HTML5 named entity reference\n// Organized by logical categories for easy maintenance and selective importing\n// ---------------------------------------------------------------------------\n\n/**\n * Basic Latin & Special Characters\n * @type {Record<string, string>}\n */\nexport const BASIC_LATIN = {\n amp: '&',\n AMP: '&',\n lt: '<',\n LT: '<',\n gt: '>',\n GT: '>',\n quot: '\"',\n QUOT: '\"',\n apos: \"'\",\n lsquo: '‘',\n rsquo: '’',\n ldquo: '“',\n rdquo: '”',\n lsquor: '‚',\n rsquor: '’',\n ldquor: '„',\n bdquo: '„',\n comma: ',',\n period: '.',\n colon: ':',\n semi: ';',\n excl: '!',\n quest: '?',\n num: '#',\n dollar: '$',\n percent: '%',\n amp: '&',\n ast: '*',\n commat: '@',\n lowbar: '_',\n verbar: '|',\n vert: '|',\n sol: '/',\n bsol: '\\\\',\n lbrace: '{',\n rbrace: '}',\n lbrack: '[',\n rbrack: ']',\n lpar: '(',\n rpar: ')',\n nbsp: '\\u00a0',\n iexcl: '¡',\n cent: '¢',\n pound: '£',\n curren: '¤',\n yen: '¥',\n brvbar: '¦',\n sect: '§',\n uml: '¨',\n copy: '©',\n COPY: '©',\n ordf: 'ª',\n laquo: '«',\n not: '¬',\n shy: '\\u00ad',\n reg: '®',\n REG: '®',\n macr: '¯',\n deg: '°',\n plusmn: '±',\n sup2: '²',\n sup3: '³',\n acute: '´',\n micro: 'µ',\n para: '¶',\n middot: '·',\n cedil: '¸',\n sup1: '¹',\n ordm: 'º',\n raquo: '»',\n frac14: '¼',\n frac12: '½',\n half: '½',\n frac34: '¾',\n iquest: '¿',\n times: '×',\n div: '÷',\n divide: '÷',\n};\n\n/**\n * Latin Extended & Accented Letters (A-Z)\n * @type {Record<string, string>}\n */\nexport const LATIN_ACCENTS = {\n Agrave: 'À',\n agrave: 'à',\n Aacute: 'Á',\n aacute: 'á',\n Acirc: 'Â',\n acirc: 'â',\n Atilde: 'Ã',\n atilde: 'ã',\n Auml: 'Ä',\n auml: 'ä',\n Aring: 'Å',\n aring: 'å',\n AElig: 'Æ',\n aelig: 'æ',\n Ccedil: 'Ç',\n ccedil: 'ç',\n Egrave: 'È',\n egrave: 'è',\n Eacute: 'É',\n eacute: 'é',\n Ecirc: 'Ê',\n ecirc: 'ê',\n Euml: 'Ë',\n euml: 'ë',\n Igrave: 'Ì',\n igrave: 'ì',\n Iacute: 'Í',\n iacute: 'í',\n Icirc: 'Î',\n icirc: 'î',\n Iuml: 'Ï',\n iuml: 'ï',\n ETH: 'Ð',\n eth: 'ð',\n Ntilde: 'Ñ',\n ntilde: 'ñ',\n Ograve: 'Ò',\n ograve: 'ò',\n Oacute: 'Ó',\n oacute: 'ó',\n Ocirc: 'Ô',\n ocirc: 'ô',\n Otilde: 'Õ',\n otilde: 'õ',\n Ouml: 'Ö',\n ouml: 'ö',\n Oslash: 'Ø',\n oslash: 'ø',\n Ugrave: 'Ù',\n ugrave: 'ù',\n Uacute: 'Ú',\n uacute: 'ú',\n Ucirc: 'Û',\n ucirc: 'û',\n Uuml: 'Ü',\n uuml: 'ü',\n Yacute: 'Ý',\n yacute: 'ý',\n THORN: 'Þ',\n thorn: 'þ',\n szlig: 'ß',\n yuml: 'ÿ',\n Yuml: 'Ÿ',\n};\n\n/**\n * Latin Extended (Letters with diacritics)\n * @type {Record<string, string>}\n */\nexport const LATIN_EXTENDED = {\n Amacr: 'Ā',\n amacr: 'ā',\n Abreve: 'Ă',\n abreve: 'ă',\n Aogon: 'Ą',\n aogon: 'ą',\n Cacute: 'Ć',\n cacute: 'ć',\n Ccirc: 'Ĉ',\n ccirc: 'ĉ',\n Cdot: 'Ċ',\n cdot: 'ċ',\n Ccaron: 'Č',\n ccaron: 'č',\n Dcaron: 'Ď',\n dcaron: 'ď',\n Dstrok: 'Đ',\n dstrok: 'đ',\n Emacr: 'Ē',\n emacr: 'ē',\n Ecaron: 'Ě',\n ecaron: 'ě',\n Edot: 'Ė',\n edot: 'ė',\n Eogon: 'Ę',\n eogon: 'ę',\n Gcirc: 'Ĝ',\n gcirc: 'ĝ',\n Gbreve: 'Ğ',\n gbreve: 'ğ',\n Gdot: 'Ġ',\n gdot: 'ġ',\n Gcedil: 'Ģ',\n Hcirc: 'Ĥ',\n hcirc: 'ĥ',\n Hstrok: 'Ħ',\n hstrok: 'ħ',\n Itilde: 'Ĩ',\n itilde: 'ĩ',\n Imacr: 'Ī',\n imacr: 'ī',\n Iogon: 'Į',\n iogon: 'į',\n Idot: 'İ',\n IJlig: 'IJ',\n ijlig: 'ij',\n Jcirc: 'Ĵ',\n jcirc: 'ĵ',\n Kcedil: 'Ķ',\n kcedil: 'ķ',\n kgreen: 'ĸ',\n Lacute: 'Ĺ',\n lacute: 'ĺ',\n Lcedil: 'Ļ',\n lcedil: 'ļ',\n Lcaron: 'Ľ',\n lcaron: 'ľ',\n Lmidot: 'Ŀ',\n lmidot: 'ŀ',\n Lstrok: 'Ł',\n lstrok: 'ł',\n Nacute: 'Ń',\n nacute: 'ń',\n Ncaron: 'Ň',\n ncaron: 'ň',\n Ncedil: 'Ņ',\n ncedil: 'ņ',\n ENG: 'Ŋ',\n eng: 'ŋ',\n Omacr: 'Ō',\n omacr: 'ō',\n Odblac: 'Ő',\n odblac: 'ő',\n OElig: 'Œ',\n oelig: 'œ',\n Racute: 'Ŕ',\n racute: 'ŕ',\n Rcaron: 'Ř',\n rcaron: 'ř',\n Rcedil: 'Ŗ',\n rcedil: 'ŗ',\n Sacute: 'Ś',\n sacute: 'ś',\n Scirc: 'Ŝ',\n scirc: 'ŝ',\n Scedil: 'Ş',\n scedil: 'ş',\n Scaron: 'Š',\n scaron: 'š',\n Tcedil: 'Ţ',\n tcedil: 'ţ',\n Tcaron: 'Ť',\n tcaron: 'ť',\n Tstrok: 'Ŧ',\n tstrok: 'ŧ',\n Utilde: 'Ũ',\n utilde: 'ũ',\n Umacr: 'Ū',\n umacr: 'ū',\n Ubreve: 'Ŭ',\n ubreve: 'ŭ',\n Uring: 'Ů',\n uring: 'ů',\n Udblac: 'Ű',\n udblac: 'ű',\n Uogon: 'Ų',\n uogon: 'ų',\n Wcirc: 'Ŵ',\n wcirc: 'ŵ',\n Ycirc: 'Ŷ',\n ycirc: 'ŷ',\n Zacute: 'Ź',\n zacute: 'ź',\n Zdot: 'Ż',\n zdot: 'ż',\n Zcaron: 'Ž',\n zcaron: 'ž',\n};\n\n/**\n * Greek Letters\n * @type {Record<string, string>}\n */\nexport const GREEK = {\n Alpha: 'Α',\n alpha: 'α',\n Beta: 'Β',\n beta: 'β',\n Gamma: 'Γ',\n gamma: 'γ',\n Delta: 'Δ',\n delta: 'δ',\n Epsilon: 'Ε',\n epsilon: 'ε',\n epsiv: 'ϵ',\n varepsilon: 'ϵ',\n Zeta: 'Ζ',\n zeta: 'ζ',\n Eta: 'Η',\n eta: 'η',\n Theta: 'Θ',\n theta: 'θ',\n thetasym: 'ϑ',\n vartheta: 'ϑ',\n Iota: 'Ι',\n iota: 'ι',\n Kappa: 'Κ',\n kappa: 'κ',\n kappav: 'ϰ',\n varkappa: 'ϰ',\n Lambda: 'Λ',\n lambda: 'λ',\n Mu: 'Μ',\n mu: 'μ',\n Nu: 'Ν',\n nu: 'ν',\n Xi: 'Ξ',\n xi: 'ξ',\n Omicron: 'Ο',\n omicron: 'ο',\n Pi: 'Π',\n pi: 'π',\n piv: 'ϖ',\n varpi: 'ϖ',\n Rho: 'Ρ',\n rho: 'ρ',\n rhov: 'ϱ',\n varrho: 'ϱ',\n Sigma: 'Σ',\n sigma: 'σ',\n sigmaf: 'ς',\n sigmav: 'ς',\n varsigma: 'ς',\n Tau: 'Τ',\n tau: 'τ',\n Upsilon: 'Υ',\n upsilon: 'υ',\n upsi: 'υ',\n Upsi: 'ϒ',\n upsih: 'ϒ',\n Phi: 'Φ',\n phi: 'φ',\n phiv: 'ϕ',\n varphi: 'ϕ',\n Chi: 'Χ',\n chi: 'χ',\n Psi: 'Ψ',\n psi: 'ψ',\n Omega: 'Ω',\n omega: 'ω',\n ohm: 'Ω',\n Gammad: 'Ϝ',\n gammad: 'ϝ',\n digamma: 'ϝ',\n};\n\n/**\n * Cyrillic Letters\n * @type {Record<string, string>}\n */\nexport const CYRILLIC = {\n Afr: '𝔄',\n afr: '𝔞',\n Acy: 'А',\n acy: 'а',\n Bcy: 'Б',\n bcy: 'б',\n Vcy: 'В',\n vcy: 'в',\n Gcy: 'Г',\n gcy: 'г',\n Dcy: 'Д',\n dcy: 'д',\n IEcy: 'Е',\n iecy: 'е',\n IOcy: 'Ё',\n iocy: 'ё',\n ZHcy: 'Ж',\n zhcy: 'ж',\n Zcy: 'З',\n zcy: 'з',\n Icy: 'И',\n icy: 'и',\n Jcy: 'Й',\n jcy: 'й',\n Kcy: 'К',\n kcy: 'к',\n Lcy: 'Л',\n lcy: 'л',\n Mcy: 'М',\n mcy: 'м',\n Ncy: 'Н',\n ncy: 'н',\n Ocy: 'О',\n ocy: 'о',\n Pcy: 'П',\n pcy: 'п',\n Rcy: 'Р',\n rcy: 'р',\n Scy: 'С',\n scy: 'с',\n Tcy: 'Т',\n tcy: 'т',\n Ucy: 'У',\n ucy: 'у',\n Fcy: 'Ф',\n fcy: 'ф',\n KHcy: 'Х',\n khcy: 'х',\n TScy: 'Ц',\n tscy: 'ц',\n CHcy: 'Ч',\n chcy: 'ч',\n SHcy: 'Ш',\n shcy: 'ш',\n SHCHcy: 'Щ',\n shchcy: 'щ',\n HARDcy: 'Ъ',\n hardcy: 'ъ',\n Ycy: 'Ы',\n ycy: 'ы',\n SOFTcy: 'Ь',\n softcy: 'ь',\n Ecy: 'Э',\n ecy: 'э',\n YUcy: 'Ю',\n yucy: 'ю',\n YAcy: 'Я',\n yacy: 'я',\n DJcy: 'Ђ',\n djcy: 'ђ',\n GJcy: 'Ѓ',\n gjcy: 'ѓ',\n Jukcy: 'Є',\n jukcy: 'є',\n DScy: 'Ѕ',\n dscy: 'ѕ',\n Iukcy: 'І',\n iukcy: 'і',\n YIcy: 'Ї',\n yicy: 'ї',\n Jsercy: 'Ј',\n jsercy: 'ј',\n LJcy: 'Љ',\n ljcy: 'љ',\n NJcy: 'Њ',\n njcy: 'њ',\n TSHcy: 'Ћ',\n tshcy: 'ћ',\n KJcy: 'Ќ',\n kjcy: 'ќ',\n Ubrcy: 'Ў',\n ubrcy: 'ў',\n DZcy: 'Џ',\n dzcy: 'џ',\n};\n\n/**\n * Mathematical Operators & Relations\n * @type {Record<string, string>}\n */\nexport const MATH = {\n plus: '+',\n minus: '−',\n mnplus: '∓',\n mp: '∓',\n pm: '±',\n times: '×',\n div: '÷',\n divide: '÷',\n sdot: '⋅',\n star: '☆',\n starf: '★',\n bigstar: '★',\n lowast: '∗',\n ast: '*',\n midast: '*',\n compfn: '∘',\n smallcircle: '∘',\n bullet: '•',\n bull: '•',\n nbsp: '\\u00a0',\n hellip: '…',\n mldr: '…',\n prime: '′',\n Prime: '″',\n tprime: '‴',\n bprime: '‵',\n backprime: '‵',\n minus: '−',\n minusd: '∸',\n dotminus: '∸',\n plusdo: '∔',\n dotplus: '∔',\n plusmn: '±',\n minusplus: '∓',\n mnplus: '∓',\n mp: '∓',\n setminus: '∖',\n smallsetminus: '∖',\n Backslash: '∖',\n setmn: '∖',\n ssetmn: '∖',\n lowbar: '_',\n verbar: '|',\n vert: '|',\n VerticalLine: '|',\n colon: ':',\n Colon: '∷',\n Proportion: '∷',\n ratio: '∶',\n equals: '=',\n ne: '≠',\n nequiv: '≢',\n equiv: '≡',\n Congruent: '≡',\n sim: '∼',\n thicksim: '∼',\n thksim: '∼',\n sime: '≃',\n simeq: '≃',\n TildeEqual: '≃',\n asymp: '≈',\n approx: '≈',\n thickapprox: '≈',\n thkap: '≈',\n TildeTilde: '≈',\n ncong: '≇',\n cong: '≅',\n TildeFullEqual: '≅',\n asympeq: '≍',\n CupCap: '≍',\n bump: '≎',\n Bumpeq: '≎',\n HumpDownHump: '≎',\n bumpe: '≏',\n bumpeq: '≏',\n HumpEqual: '≏',\n dotminus: '∸',\n minusd: '∸',\n plusdo: '∔',\n dotplus: '∔',\n le: '≤',\n LessEqual: '≤',\n ge: '≥',\n GreaterEqual: '≥',\n lesseqgtr: '⋚',\n lesseqqgtr: '⪋',\n greater: '>',\n less: '<',\n};\n\n/**\n * Mathematical Operators (Advanced)\n * @type {Record<string, string>}\n */\nexport const MATH_ADVANCED = {\n alefsym: 'ℵ',\n aleph: 'ℵ',\n beth: 'ℶ',\n gimel: 'ℷ',\n daleth: 'ℸ',\n forall: '∀',\n ForAll: '∀',\n part: '∂',\n PartialD: '∂',\n exist: '∃',\n Exists: '∃',\n nexist: '∄',\n nexists: '∄',\n empty: '∅',\n emptyset: '∅',\n emptyv: '∅',\n varnothing: '∅',\n nabla: '∇',\n Del: '∇',\n isin: '∈',\n isinv: '∈',\n in: '∈',\n Element: '∈',\n notin: '∉',\n notinva: '∉',\n ni: '∋',\n niv: '∋',\n SuchThat: '∋',\n ReverseElement: '∋',\n notni: '∌',\n notniva: '∌',\n prod: '∏',\n Product: '∏',\n coprod: '∐',\n Coproduct: '∐',\n sum: '∑',\n Sum: '∑',\n minus: '−',\n mp: '∓',\n plusdo: '∔',\n dotplus: '∔',\n setminus: '∖',\n lowast: '∗',\n radic: '√',\n Sqrt: '√',\n prop: '∝',\n propto: '∝',\n Proportional: '∝',\n varpropto: '∝',\n infin: '∞',\n infintie: '⧝',\n ang: '∠',\n angle: '∠',\n angmsd: '∡',\n measuredangle: '∡',\n angsph: '∢',\n mid: '∣',\n VerticalBar: '∣',\n nmid: '∤',\n nsmid: '∤',\n npar: '∦',\n parallel: '∥',\n spar: '∥',\n nparallel: '∦',\n nspar: '∦',\n and: '∧',\n wedge: '∧',\n or: '∨',\n vee: '∨',\n cap: '∩',\n cup: '∪',\n int: '∫',\n Integral: '∫',\n conint: '∮',\n ContourIntegral: '∮',\n Conint: '∯',\n DoubleContourIntegral: '∯',\n Cconint: '∰',\n there4: '∴',\n therefore: '∴',\n Therefore: '∴',\n becaus: '∵',\n because: '∵',\n Because: '∵',\n ratio: '∶',\n Proportion: '∷',\n minusd: '∸',\n dotminus: '∸',\n mDDot: '∺',\n homtht: '∻',\n sim: '∼',\n bsimg: '∽',\n backsim: '∽',\n ac: '∾',\n mstpos: '∾',\n acd: '∿',\n VerticalTilde: '≀',\n wr: '≀',\n wreath: '≀',\n nsime: '≄',\n nsimeq: '≄',\n nsimeq: '≄',\n ncong: '≇',\n simne: '≆',\n ncongdot: '⩭̸',\n ngsim: '≵',\n nsim: '≁',\n napprox: '≉',\n nap: '≉',\n ngeq: '≱',\n nge: '≱',\n nleq: '≰',\n nle: '≰',\n ngtr: '≯',\n ngt: '≯',\n nless: '≮',\n nlt: '≮',\n nprec: '⊀',\n npr: '⊀',\n nsucc: '⊁',\n nsc: '⊁',\n};\n\n/**\n * Arrows\n * @type {Record<string, string>}\n */\nexport const ARROWS = {\n larr: '←',\n leftarrow: '←',\n LeftArrow: '←',\n uarr: '↑',\n uparrow: '↑',\n UpArrow: '↑',\n rarr: '→',\n rightarrow: '→',\n RightArrow: '→',\n darr: '↓',\n downarrow: '↓',\n DownArrow: '↓',\n harr: '↔',\n leftrightarrow: '↔',\n LeftRightArrow: '↔',\n varr: '↕',\n updownarrow: '↕',\n UpDownArrow: '↕',\n nwarr: '↖',\n nwarrow: '↖',\n UpperLeftArrow: '↖',\n nearr: '↗',\n nearrow: '↗',\n UpperRightArrow: '↗',\n searr: '↘',\n searrow: '↘',\n LowerRightArrow: '↘',\n swarr: '↙',\n swarrow: '↙',\n LowerLeftArrow: '↙',\n lArr: '⇐',\n Leftarrow: '⇐',\n uArr: '⇑',\n Uparrow: '⇑',\n rArr: '⇒',\n Rightarrow: '⇒',\n dArr: '⇓',\n Downarrow: '⇓',\n hArr: '⇔',\n Leftrightarrow: '⇔',\n iff: '⇔',\n vArr: '⇕',\n Updownarrow: '⇕',\n lAarr: '⇚',\n Lleftarrow: '⇚',\n rAarr: '⇛',\n Rrightarrow: '⇛',\n lrarr: '⇆',\n leftrightarrows: '⇆',\n rlarr: '⇄',\n rightleftarrows: '⇄',\n lrhar: '⇋',\n leftrightharpoons: '⇋',\n ReverseEquilibrium: '⇋',\n rlhar: '⇌',\n rightleftharpoons: '⇌',\n Equilibrium: '⇌',\n udarr: '⇅',\n UpArrowDownArrow: '⇅',\n duarr: '⇵',\n DownArrowUpArrow: '⇵',\n llarr: '⇇',\n leftleftarrows: '⇇',\n rrarr: '⇉',\n rightrightarrows: '⇉',\n ddarr: '⇊',\n downdownarrows: '⇊',\n har: '↽',\n lhard: '↽',\n leftharpoondown: '↽',\n lharu: '↼',\n leftharpoonup: '↼',\n rhard: '⇁',\n rightharpoondown: '⇁',\n rharu: '⇀',\n rightharpoonup: '⇀',\n lsh: '↰',\n Lsh: '↰',\n rsh: '↱',\n Rsh: '↱',\n ldsh: '↲',\n rdsh: '↳',\n hookleftarrow: '↩',\n hookrightarrow: '↪',\n mapstoleft: '↤',\n mapstoup: '↥',\n map: '↦',\n mapsto: '↦',\n mapstodown: '↧',\n crarr: '↵',\n nwarrow: '↖',\n nearrow: '↗',\n searrow: '↘',\n swarrow: '↙',\n nleftarrow: '↚',\n nleftrightarrow: '↮',\n nrightarrow: '↛',\n nrarr: '↛',\n larrtl: '↢',\n rarrtl: '↣',\n leftarrowtail: '↢',\n rightarrowtail: '↣',\n twoheadleftarrow: '↞',\n twoheadrightarrow: '↠',\n Larr: '↞',\n Rarr: '↠',\n larrhk: '↩',\n rarrhk: '↪',\n larrlp: '↫',\n looparrowleft: '↫',\n rarrlp: '↬',\n looparrowright: '↬',\n harrw: '↭',\n leftrightsquigarrow: '↭',\n nrarrw: '↝̸',\n rarrw: '↝',\n rightsquigarrow: '↝',\n larrbfs: '⤟',\n rarrbfs: '⤠',\n nvHarr: '⤄',\n nvlArr: '⤂',\n nvrArr: '⤃',\n larrfs: '⤝',\n rarrfs: '⤞',\n Map: '⤅',\n larrsim: '⥳',\n rarrsim: '⥴',\n harrcir: '⥈',\n Uarrocir: '⥉',\n lurdshar: '⥊',\n ldrdhar: '⥧',\n ldrushar: '⥋',\n rdldhar: '⥩',\n lrhard: '⥭',\n rlhar: '⇌',\n uharr: '↾',\n uharl: '↿',\n dharr: '⇂',\n dharl: '⇃',\n Uarr: '↟',\n Darr: '↡',\n zigrarr: '⇝',\n nwArr: '⇖',\n neArr: '⇗',\n seArr: '⇘',\n swArr: '⇙',\n nharr: '↮',\n nhArr: '⇎',\n nlarr: '↚',\n nlArr: '⇍',\n nrarr: '↛',\n nrArr: '⇏',\n larrb: '⇤',\n LeftArrowBar: '⇤',\n rarrb: '⇥',\n RightArrowBar: '⇥',\n};\n\n/**\n * Geometric Shapes\n * @type {Record<string, string>}\n */\nexport const SHAPES = {\n square: '□',\n Square: '□',\n squ: '□',\n squf: '▪',\n squarf: '▪',\n blacksquar: '▪',\n blacksquare: '▪',\n FilledVerySmallSquare: '▪',\n blk34: '▓',\n blk12: '▒',\n blk14: '░',\n block: '█',\n srect: '▭',\n rect: '▭',\n sdot: '⋅',\n sdotb: '⊡',\n dotsquare: '⊡',\n triangle: '▵',\n tri: '▵',\n trine: '▵',\n utri: '▵',\n triangledown: '▿',\n dtri: '▿',\n tridown: '▿',\n triangleleft: '◃',\n ltri: '◃',\n triangleright: '▹',\n rtri: '▹',\n blacktriangle: '▴',\n utrif: '▴',\n blacktriangledown: '▾',\n dtrif: '▾',\n blacktriangleleft: '◂',\n ltrif: '◂',\n blacktriangleright: '▸',\n rtrif: '▸',\n loz: '◊',\n lozenge: '◊',\n blacklozenge: '⧫',\n lozf: '⧫',\n bigcirc: '◯',\n xcirc: '◯',\n circ: 'ˆ',\n Circle: '○',\n cir: '○',\n o: '○',\n bullet: '•',\n bull: '•',\n hellip: '…',\n mldr: '…',\n nldr: '‥',\n boxh: '─',\n HorizontalLine: '─',\n boxv: '│',\n boxdr: '┌',\n boxdl: '┐',\n boxur: '└',\n boxul: '┘',\n boxvr: '├',\n boxvl: '┤',\n boxhd: '┬',\n boxhu: '┴',\n boxvh: '┼',\n boxH: '═',\n boxV: '║',\n boxdR: '╒',\n boxDr: '╓',\n boxDR: '╔',\n boxDl: '╕',\n boxdL: '╖',\n boxDL: '╗',\n boxuR: '╘',\n boxUr: '╙',\n boxUR: '╚',\n boxUl: '╜',\n boxuL: '╛',\n boxUL: '╝',\n boxvR: '╞',\n boxVr: '╟',\n boxVR: '╠',\n boxVl: '╢',\n boxvL: '╡',\n boxVL: '╣',\n boxHd: '╤',\n boxhD: '╥',\n boxHD: '╦',\n boxHu: '╧',\n boxhU: '╨',\n boxHU: '╩',\n boxvH: '╪',\n boxVh: '╫',\n boxVH: '╬',\n};\n\n/**\n * Punctuation & Diacritics\n * @type {Record<string, string>}\n */\nexport const PUNCTUATION = {\n excl: '!',\n iexcl: '¡',\n brvbar: '¦',\n sect: '§',\n uml: '¨',\n copy: '©',\n ordf: 'ª',\n laquo: '«',\n not: '¬',\n shy: '\\u00ad',\n reg: '®',\n macr: '¯',\n deg: '°',\n plusmn: '±',\n sup2: '²',\n sup3: '³',\n acute: '´',\n micro: 'µ',\n para: '¶',\n middot: '·',\n cedil: '¸',\n sup1: '¹',\n ordm: 'º',\n raquo: '»',\n frac14: '¼',\n frac12: '½',\n frac34: '¾',\n iquest: '¿',\n nbsp: '\\u00a0',\n comma: ',',\n period: '.',\n colon: ':',\n semi: ';',\n vert: '|',\n Verbar: '‖',\n verbar: '|',\n dblac: '˝',\n circ: 'ˆ',\n caron: 'ˇ',\n breve: '˘',\n dot: '˙',\n ring: '˚',\n ogon: '˛',\n tilde: '˜',\n DiacriticalGrave: '`',\n DiacriticalAcute: '´',\n DiacriticalTilde: '˜',\n DiacriticalDot: '˙',\n DiacriticalDoubleAcute: '˝',\n grave: '`',\n acute: '´',\n};\n\n/**\n * Currency Symbols\n * @type {Record<string, string>}\n */\nexport const CURRENCY = {\n cent: '¢',\n pound: '£',\n curren: '¤',\n yen: '¥',\n euro: '€',\n dollar: '$',\n euro: '€',\n fnof: 'ƒ',\n inr: '₹',\n af: '؋',\n birr: 'ብር',\n peso: '₱',\n rub: '₽',\n won: '₩',\n yuan: '¥',\n cedil: '¸',\n};\n\n/**\n * Fractions\n * @type {Record<string, string>}\n */\nexport const FRACTIONS = {\n frac12: '½',\n half: '½',\n frac13: '⅓',\n frac14: '¼',\n frac15: '⅕',\n frac16: '⅙',\n frac18: '⅛',\n frac23: '⅔',\n frac25: '⅖',\n frac34: '¾',\n frac35: '⅗',\n frac38: '⅜',\n frac45: '⅘',\n frac56: '⅚',\n frac58: '⅝',\n frac78: '⅞',\n frasl: '⁄',\n};\n\n/**\n * Miscellaneous Symbols\n * @type {Record<string, string>}\n */\nexport const MISC_SYMBOLS = {\n trade: '™',\n TRADE: '™',\n telrec: '⌕',\n target: '⌖',\n ulcorn: '⌜',\n ulcorner: '⌜',\n urcorn: '⌝',\n urcorner: '⌝',\n dlcorn: '⌞',\n llcorner: '⌞',\n drcorn: '⌟',\n lrcorner: '⌟',\n intercal: '⊺',\n intcal: '⊺',\n oplus: '⊕',\n CirclePlus: '⊕',\n ominus: '⊖',\n CircleMinus: '⊖',\n otimes: '⊗',\n CircleTimes: '⊗',\n osol: '⊘',\n odot: '⊙',\n CircleDot: '⊙',\n oast: '⊛',\n circledast: '⊛',\n odash: '⊝',\n circleddash: '⊝',\n ocirc: '⊚',\n circledcirc: '⊚',\n boxplus: '⊞',\n plusb: '⊞',\n boxminus: '⊟',\n minusb: '⊟',\n boxtimes: '⊠',\n timesb: '⊠',\n boxdot: '⊡',\n sdotb: '⊡',\n veebar: '⊻',\n vee: '∨',\n barvee: '⊽',\n and: '∧',\n wedge: '∧',\n Cap: '⋒',\n Cup: '⋓',\n Fork: '⋔',\n pitchfork: '⋔',\n epar: '⋕',\n ltlarr: '⥶',\n nvap: '≍⃒',\n nvsim: '∼⃒',\n nvge: '≥⃒',\n nvle: '≤⃒',\n nvlt: '<⃒',\n nvgt: '>⃒',\n nvltrie: '⊴⃒',\n nvrtrie: '⊵⃒',\n Vdash: '⊩',\n dashv: '⊣',\n vDash: '⊨',\n Vdash: '⊩',\n Vvdash: '⊪',\n nvdash: '⊬',\n nvDash: '⊭',\n nVdash: '⊮',\n nVDash: '⊯',\n};\n\n/**\n * All entities combined (if you need everything)\n * @type {Record<string, string>}\n */\nexport const ALL_ENTITIES = {\n ...BASIC_LATIN,\n ...LATIN_ACCENTS,\n ...LATIN_EXTENDED,\n ...GREEK,\n ...CYRILLIC,\n ...MATH,\n ...MATH_ADVANCED,\n ...ARROWS,\n ...SHAPES,\n ...PUNCTUATION,\n ...CURRENCY,\n ...FRACTIONS,\n ...MISC_SYMBOLS,\n};\n\nexport const XML = {\n amp: \"&\",\n apos: \"'\",\n gt: \">\",\n lt: \"<\",\n quot: \"\\\"\"\n}\nexport const COMMON_HTML = {\n nbsp: '\\u00a0',\n copy: '\\u00a9',\n reg: '\\u00ae',\n trade: '\\u2122',\n mdash: '\\u2014',\n ndash: '\\u2013',\n hellip: '\\u2026',\n laquo: '\\u00ab',\n raquo: '\\u00bb',\n lsquo: '\\u2018',\n rsquo: '\\u2019',\n ldquo: '\\u201c',\n rdquo: '\\u201d',\n bull: '\\u2022',\n para: '\\u00b6',\n sect: '\\u00a7',\n deg: '\\u00b0',\n frac12: '\\u00bd',\n frac14: '\\u00bc',\n frac34: '\\u00be',\n}\n// ---------------------------------------------------------------------------\n// Note: NUMERIC_ENTITIES (&#NNN; / &#xHH;) are handled by the scanner directly\n// via String.fromCodePoint() without any map lookup.\n// ---------------------------------------------------------------------------","// ---------------------------------------------------------------------------\n// Built-in named entity map (name → replacement string)\n// No regex, no {regex,val} objects — just flat key/value pairs.\n// ---------------------------------------------------------------------------\n\nimport { XML as DEFAULT_XML_ENTITIES } from \"./entities.js\"\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nconst SPECIAL_CHARS = new Set('!?\\\\\\\\/[]$%{}^&*()<>|+');\n\n/**\n * Validate that an entity name contains no dangerous characters.\n * @param {string} name\n * @returns {string} the name, unchanged\n * @throws {Error} on invalid characters\n */\nfunction validateEntityName(name) {\n if (name[0] === '#') {\n throw new Error(`[EntityReplacer] Invalid character '#' in entity name: \"${name}\"`);\n }\n for (const ch of name) {\n if (SPECIAL_CHARS.has(ch)) {\n throw new Error(`[EntityReplacer] Invalid character '${ch}' in entity name: \"${name}\"`);\n }\n }\n return name;\n}\n\n/**\n * Merge one or more entity maps into a flat name→string map.\n * Accepts either:\n * - plain string values: { amp: '&' }\n * - legacy {regex,val} / {regx,val}: { lt: { regex: /.../, val: '<' } }\n *\n * Values containing '&' are skipped (recursive expansion risk).\n *\n * @param {...object} maps\n * @returns {Record<string, string>}\n */\nfunction mergeEntityMaps(...maps) {\n const out = Object.create(null);\n for (const map of maps) {\n if (!map) continue;\n for (const key of Object.keys(map)) {\n const raw = map[key];\n if (typeof raw === 'string') {\n out[key] = raw;\n } else if (raw && typeof raw === 'object' && raw.val !== undefined) {\n // Legacy {regex,val} or {regx,val} — extract the string val only\n const val = raw.val;\n if (typeof val === 'string') {\n out[key] = val;\n }\n // function vals are not supported in the scanner — skip\n }\n }\n }\n return out;\n}\n\n// ---------------------------------------------------------------------------\n// applyLimitsTo helpers\n// ---------------------------------------------------------------------------\n\nconst LIMIT_TIER_EXTERNAL = 'external'; // input/runtime + persistent external maps\nconst LIMIT_TIER_BASE = 'base'; // DEFAULT_XML_ENTITIES + namedEntities (system) maps\nconst LIMIT_TIER_ALL = 'all'; // every entity regardless of tier\n\n/**\n * Resolve `applyLimitsTo` option into a normalised Set of tier strings.\n * Accepted values: 'external' | 'base' | 'all' | string[]\n * Default: 'external' (only untrusted injected entities are counted).\n * @param {string|string[]|undefined} raw\n * @returns {Set<string>}\n */\nfunction parseLimitTiers(raw) {\n if (!raw || raw === LIMIT_TIER_EXTERNAL) return new Set([LIMIT_TIER_EXTERNAL]);\n if (raw === LIMIT_TIER_ALL) return new Set([LIMIT_TIER_ALL]);\n if (raw === LIMIT_TIER_BASE) return new Set([LIMIT_TIER_BASE]);\n if (Array.isArray(raw)) return new Set(raw);\n return new Set([LIMIT_TIER_EXTERNAL]); // safe default for unrecognised values\n}\n\n// ---------------------------------------------------------------------------\n// NCR (Numeric Character Reference) classification\n// ---------------------------------------------------------------------------\n\n// Severity order — higher number = stricter action.\n// Used to enforce minimum action levels for specific codepoint ranges.\nconst NCR_LEVEL = Object.freeze({ allow: 0, leave: 1, remove: 2, throw: 3 });\n\n// XML 1.0 §2.2: allowed chars are #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]\n// Restricted C0: U+0001–U+001F excluding U+0009, U+000A, U+000D\nconst XML10_ALLOWED_C0 = new Set([0x09, 0x0A, 0x0D]);\n\n/**\n * Parse the `ncr` constructor option into flat, hot-path-friendly fields.\n * @param {object|undefined} ncr\n * @returns {{ xmlVersion: number, onLevel: number, nullLevel: number }}\n */\nfunction parseNCRConfig(ncr) {\n if (!ncr) {\n return { xmlVersion: 1.0, onLevel: NCR_LEVEL.allow, nullLevel: NCR_LEVEL.remove };\n }\n const xmlVersion = ncr.xmlVersion === 1.1 ? 1.1 : 1.0;\n const onLevel = NCR_LEVEL[ncr.onNCR] ?? NCR_LEVEL.allow;\n const nullLevel = NCR_LEVEL[ncr.nullNCR] ?? NCR_LEVEL.remove;\n // 'allow' is not meaningful for null — clamp to at least 'remove'\n const clampedNull = Math.max(nullLevel, NCR_LEVEL.remove);\n return { xmlVersion, onLevel, nullLevel: clampedNull };\n}\n\n// ---------------------------------------------------------------------------\n// EntityReplacer\n// ---------------------------------------------------------------------------\n\n/**\n * Single-pass, zero-regex entity replacer for XML/HTML content.\n *\n * Algorithm: scan the string once for '&', read to ';', resolve via map\n * or direct codepoint conversion, build output chunks, join once at the end.\n *\n * Entity lookup priority (highest → lowest):\n * 1. input / runtime (DOCTYPE entities for current document)\n * 2. persistent external (survive across documents)\n * 3. base named map (DEFAULT_XML_ENTITIES + user-supplied namedEntities)\n *\n * Both input and external resolve as the 'external' tier for limit purposes.\n * Base map entities resolve as the 'base' tier.\n *\n * Numeric / hex references (&#NNN; / &#xHH;) are resolved directly via\n * String.fromCodePoint() — no map needed. They count as 'base' tier.\n *\n * @example\n * const replacer = new EntityReplacer({ namedEntities: COMMON_HTML });\n * replacer.setExternalEntities({ brand: 'Acme' });\n *\n * const instance = replacer.reset();\n * instance.addInputEntities({ version: '1.0' });\n * instance.encode('&brand; v&version; <'); // 'Acme v1.0 <'\n */\nexport default class EntityDecoder {\n /**\n * @param {object} [options]\n * @param {object|null} [options.namedEntities] — extra named entities merged into base map\n * @param {object} [options.limit] — security limits\n * @param {number} [options.limit.maxTotalExpansions=0] — 0 = unlimited\n * @param {number} [options.limit.maxExpandedLength=0] — 0 = unlimited\n * @param {'external'|'base'|'all'|string[]} [options.limit.applyLimitsTo='external']\n * Which entity tiers count against the security limits:\n * - 'external' (default) — only input/runtime + persistent external entities\n * - 'base' — only DEFAULT_XML_ENTITIES + namedEntities\n * - 'all' — every entity regardless of tier\n * - string[] — explicit combination, e.g. ['external', 'base']\n * @param {((resolved: string, original: string) => string)|null} [options.postCheck=null]\n * @param {string[]} [options.remove=[]] — entity names (e.g. ['nbsp', '#13']) to delete (replace with empty string)\n * @param {string[]} [options.leave=[]] — entity names to keep as literal (unchanged in output)\n * @param {object} [options.ncr] — Numeric Character Reference controls\n * @param {1.0|1.1} [options.ncr.xmlVersion=1.0]\n * XML version governing which codepoint ranges are restricted:\n * - 1.0 — C0 controls U+0001–U+001F (except U+0009/000A/000D) are prohibited\n * - 1.1 — C0 controls are allowed when written as NCRs; C1 (U+007F–U+009F) decoded as-is\n * @param {'allow'|'leave'|'remove'|'throw'} [options.ncr.onNCR='allow']\n * Base action for numeric references. Severity order: allow < leave < remove < throw.\n * For codepoint ranges that carry a minimum level (surrogates → remove, XML 1.0 C0 → remove),\n * the effective action is max(onNCR, rangeMinimum).\n * @param {'remove'|'throw'} [options.ncr.nullNCR='remove']\n * Action for U+0000 (null). 'allow' and 'leave' are clamped to 'remove' since null is never safe.\n */\n constructor(options = {}) {\n this._limit = options.limit || {};\n this._maxTotalExpansions = this._limit.maxTotalExpansions || 0;\n this._maxExpandedLength = this._limit.maxExpandedLength || 0;\n this._postCheck = typeof options.postCheck === 'function' ? options.postCheck : r => r;\n this._limitTiers = parseLimitTiers(this._limit.applyLimitsTo ?? LIMIT_TIER_EXTERNAL);\n this._numericAllowed = options.numericAllowed ?? true;\n // Base map: DEFAULT_XML_ENTITIES + user-supplied extras. Immutable after construction.\n this._baseMap = mergeEntityMaps(DEFAULT_XML_ENTITIES, options.namedEntities || null);\n\n // Persistent external entities — survive across documents.\n // Stored as a separate map so reset() never touches them.\n /** @type {Record<string, string>} */\n this._externalMap = Object.create(null);\n\n // Input / runtime entities — current document only, wiped on reset().\n /** @type {Record<string, string>} */\n this._inputMap = Object.create(null);\n\n // Per-document counters\n this._totalExpansions = 0;\n this._expandedLength = 0;\n\n // --- New: remove / leave sets ---\n /** @type {Set<string>} */\n this._removeSet = new Set(options.remove && Array.isArray(options.remove) ? options.remove : []);\n /** @type {Set<string>} */\n this._leaveSet = new Set(options.leave && Array.isArray(options.leave) ? options.leave : []);\n\n // --- NCR config (parsed into flat fields for hot-path speed) ---\n const ncrCfg = parseNCRConfig(options.ncr);\n this._ncrXmlVersion = ncrCfg.xmlVersion;\n this._ncrOnLevel = ncrCfg.onLevel;\n this._ncrNullLevel = ncrCfg.nullLevel;\n }\n\n // -------------------------------------------------------------------------\n // Persistent external entity registration\n // -------------------------------------------------------------------------\n\n /**\n * Replace the full set of persistent external entities.\n * All keys are validated — throws on invalid characters.\n * @param {Record<string, string | { regex?: RegExp, val: string }>} map\n */\n setExternalEntities(map) {\n if (map) {\n for (const key of Object.keys(map)) {\n validateEntityName(key);\n }\n }\n this._externalMap = mergeEntityMaps(map);\n }\n\n /**\n * Add a single persistent external entity.\n * @param {string} key\n * @param {string} value\n */\n addExternalEntity(key, value) {\n validateEntityName(key);\n if (typeof value === 'string' && value.indexOf('&') === -1) {\n this._externalMap[key] = value;\n }\n }\n\n // -------------------------------------------------------------------------\n // Input / runtime entity registration (per document)\n // -------------------------------------------------------------------------\n\n /**\n * Inject DOCTYPE entities for the current document.\n * Also resets per-document expansion counters.\n * @param {Record<string, string | { regx?: RegExp, regex?: RegExp, val: string }>} map\n */\n addInputEntities(map) {\n this._totalExpansions = 0;\n this._expandedLength = 0;\n this._inputMap = mergeEntityMaps(map);\n }\n\n // -------------------------------------------------------------------------\n // Per-document reset\n // -------------------------------------------------------------------------\n\n /**\n * Wipe input/runtime entities and reset counters.\n * Call this before processing each new document.\n * @returns {this}\n */\n reset() {\n this._inputMap = Object.create(null);\n this._totalExpansions = 0;\n this._expandedLength = 0;\n return this;\n }\n\n // -------------------------------------------------------------------------\n // XML version (can be set after construction, e.g. once parser reads <?xml?>)\n // -------------------------------------------------------------------------\n\n /**\n * Update the XML version used for NCR classification.\n * Call this as soon as the document's `<?xml version=\"...\">` declaration is parsed.\n * @param {1.0|1.1|number} version\n */\n setXmlVersion(version) {\n this._ncrXmlVersion = version === 1.1 ? 1.1 : 1.0;\n }\n\n // -------------------------------------------------------------------------\n // Primary API\n // -------------------------------------------------------------------------\n\n /**\n * Replace all entity references in `str` in a single pass.\n *\n * @param {string} str\n * @returns {string}\n */\n decode(str) {\n if (typeof str !== 'string' || str.length === 0) return str;\n //TODO: check if needed\n //if (str.indexOf('&') === -1) return str; // fast path — no entities at all\n\n const original = str;\n const chunks = [];\n const len = str.length;\n let last = 0; // start of next unprocessed literal chunk\n let i = 0;\n\n const limitExpansions = this._maxTotalExpansions > 0;\n const limitLength = this._maxExpandedLength > 0;\n const checkLimits = limitExpansions || limitLength;\n\n while (i < len) {\n // Scan forward to next '&'\n if (str.charCodeAt(i) !== 38 /* '&' */) { i++; continue; }\n\n // --- Found '&' at position i ---\n\n // Scan forward to ';'\n let j = i + 1;\n while (j < len && str.charCodeAt(j) !== 59 /* ';' */ && (j - i) <= 32) j++;\n\n if (j >= len || str.charCodeAt(j) !== 59) {\n // No closing ';' within window — treat '&' as literal\n i++;\n continue;\n }\n\n // Raw token between '&' and ';' (exclusive)\n const token = str.slice(i + 1, j);\n if (token.length === 0) { i++; continue; }\n\n let replacement;\n let tier; // which limit tier this entity belongs to\n\n if (this._removeSet.has(token)) {\n // Remove entity: replace with empty string\n replacement = '';\n // If entity was unknown (replacement undefined), we still need a tier for limits.\n // Treat as external tier because it's user-directed removal of an unknown reference.\n if (tier === undefined) {\n tier = LIMIT_TIER_EXTERNAL;\n }\n } else if (this._leaveSet.has(token)) {\n // Do not replace — keep original &token; as literal\n i++;\n continue;\n } else if (token.charCodeAt(0) === 35 /* '#' */) {\n // ---- Numeric / NCR reference ----\n // NCR classification always runs first — prohibited codepoints must be\n // caught regardless of numericAllowed.\n const ncrResult = this._resolveNCR(token);\n if (ncrResult === undefined) {\n // 'leave' action — keep original &token; as-is\n i++;\n continue;\n }\n replacement = ncrResult; // '' for remove, char string for allow\n tier = LIMIT_TIER_BASE;\n } else {\n // ---- Named reference ----\n const resolved = this._resolveName(token);\n replacement = resolved?.value;\n tier = resolved?.tier;\n }\n\n if (replacement === undefined) {\n // Unknown entity — leave as-is, advance past '&' only\n i++;\n continue;\n }\n\n // Flush literal chunk before this entity\n if (i > last) chunks.push(str.slice(last, i));\n chunks.push(replacement);\n last = j + 1; // skip past ';'\n i = last;\n\n // Apply expansion limits only if this tier is being tracked\n if (checkLimits && this._tierCounts(tier)) {\n if (limitExpansions) {\n this._totalExpansions++;\n if (this._totalExpansions > this._maxTotalExpansions) {\n throw new Error(\n `[EntityReplacer] Entity expansion count limit exceeded: ` +\n `${this._totalExpansions} > ${this._maxTotalExpansions}`\n );\n }\n }\n if (limitLength) {\n // delta: replacement.length minus the raw &token; length (token.length + 2 for '&' and ';')\n const delta = replacement.length - (token.length + 2);\n if (delta > 0) {\n this._expandedLength += delta;\n if (this._expandedLength > this._maxExpandedLength) {\n throw new Error(\n `[EntityReplacer] Expanded content length limit exceeded: ` +\n `${this._expandedLength} > ${this._maxExpandedLength}`\n );\n }\n }\n }\n }\n }\n\n // Flush trailing literal\n if (last < len) chunks.push(str.slice(last));\n\n // If nothing was replaced, chunks is empty — return original\n const result = chunks.length === 0 ? str : chunks.join('');\n\n return this._postCheck(result, original);\n }\n\n // -------------------------------------------------------------------------\n // Private: limit tier check\n // -------------------------------------------------------------------------\n\n /**\n * Returns true if a resolved entity of the given tier should count\n * against the expansion/length limits.\n * @param {string} tier — LIMIT_TIER_EXTERNAL | LIMIT_TIER_BASE\n * @returns {boolean}\n */\n _tierCounts(tier) {\n if (this._limitTiers.has(LIMIT_TIER_ALL)) return true;\n return this._limitTiers.has(tier);\n }\n\n // -------------------------------------------------------------------------\n // Private: entity resolution\n // -------------------------------------------------------------------------\n\n /**\n * Resolve a named entity token (without & and ;).\n * Priority: inputMap > externalMap > baseMap\n * Returns the resolved value tagged with its limit tier.\n *\n * @param {string} name\n * @returns {{ value: string, tier: string }|undefined}\n */\n _resolveName(name) {\n // input and external both count as 'external' tier for limit purposes —\n // they are injected at runtime and are the untrusted surface.\n if (name in this._inputMap) return { value: this._inputMap[name], tier: LIMIT_TIER_EXTERNAL };\n if (name in this._externalMap) return { value: this._externalMap[name], tier: LIMIT_TIER_EXTERNAL };\n if (name in this._baseMap) return { value: this._baseMap[name], tier: LIMIT_TIER_BASE };\n return undefined;\n }\n\n /**\n * Classify a codepoint and return the minimum action level that must be applied.\n * Returns -1 when no minimum is imposed (normal allow path).\n *\n * Ranges checked (in priority order):\n * 1. U+0000 — null, governed by nullNCR (always ≥ remove)\n * 2. U+D800–U+DFFF — surrogates, always prohibited (min: remove)\n * 3. U+0001–U+001F \\ {0x09,0x0A,0x0D} — XML 1.0 restricted C0 (min: remove)\n * (skipped in XML 1.1 — C0 controls are allowed when written as NCRs)\n *\n * @param {number} cp — codepoint\n * @returns {number} — minimum NCR_LEVEL value, or -1 for no restriction\n */\n _classifyNCR(cp) {\n // 1. Null\n if (cp === 0) return this._ncrNullLevel;\n\n // 2. Surrogates — always prohibited, minimum 'remove'\n if (cp >= 0xD800 && cp <= 0xDFFF) return NCR_LEVEL.remove;\n\n // 3. XML 1.0 restricted C0 controls\n if (this._ncrXmlVersion === 1.0) {\n if (cp >= 0x01 && cp <= 0x1F && !XML10_ALLOWED_C0.has(cp)) return NCR_LEVEL.remove;\n }\n\n return -1; // no restriction\n }\n\n /**\n * Execute a resolved NCR action.\n *\n * @param {number} action — NCR_LEVEL value\n * @param {string} token — raw token (e.g. '#38') for error messages\n * @param {number} cp — codepoint, used only for error messages\n * @returns {string|undefined}\n * - decoded character string → 'allow'\n * - '' → 'remove'\n * - undefined → 'leave' (caller must skip past '&' only)\n * - throws Error → 'throw'\n */\n _applyNCRAction(action, token, cp) {\n switch (action) {\n case NCR_LEVEL.allow: return String.fromCodePoint(cp);\n case NCR_LEVEL.remove: return '';\n case NCR_LEVEL.leave: return undefined; // signal: keep literal\n case NCR_LEVEL.throw:\n throw new Error(\n `[EntityDecoder] Prohibited numeric character reference ` +\n `&${token}; (U+${cp.toString(16).toUpperCase().padStart(4, '0')})`\n );\n default: return String.fromCodePoint(cp);\n }\n }\n\n /**\n * Full NCR resolution pipeline for a numeric token.\n *\n * Steps:\n * 1. Parse the codepoint (decimal or hex).\n * 2. Validate the raw codepoint range (NaN, <0, >0x10FFFF).\n * 3. If numericAllowed is false and no minimum restriction applies → leave as-is.\n * 4. Classify the codepoint to find the minimum required action level.\n * 5. Resolve effective action = max(onNCR, minimum).\n * 6. Apply and return.\n *\n * @param {string} token — e.g. '#38', '#x26', '#X26'\n * @returns {string|undefined}\n * - string (incl. '') — replacement ('' = remove)\n * - undefined — leave original &token; as-is\n */\n _resolveNCR(token) {\n // Step 1: parse codepoint\n const second = token.charCodeAt(1);\n let cp;\n if (second === 120 /* x */ || second === 88 /* X */) {\n cp = parseInt(token.slice(2), 16);\n } else {\n cp = parseInt(token.slice(1), 10);\n }\n\n // Step 2: out-of-range → leave as-is unconditionally\n if (Number.isNaN(cp) || cp < 0 || cp > 0x10FFFF) return undefined;\n\n // Step 3: classify to get minimum action level\n const minimum = this._classifyNCR(cp);\n\n // Step 4: if numericAllowed is false and no hard minimum → leave\n if (!this._numericAllowed && minimum < NCR_LEVEL.remove) return undefined;\n\n // Step 5: effective action = max(configured onNCR, range minimum)\n const effective = minimum === -1\n ? this._ncrOnLevel\n : Math.max(this._ncrOnLevel, minimum);\n\n // Step 6: apply\n return this._applyNCRAction(effective, token, cp);\n }\n}","import { DANGEROUS_PROPERTY_NAMES, criticalProperties } from \"../util.js\";\nimport { COMMON_HTML, CURRENCY } from '@nodable/entities';\n\nconst defaultOnDangerousProperty = (name) => {\n if (DANGEROUS_PROPERTY_NAMES.includes(name)) {\n return \"__\" + name;\n }\n return name;\n};\n\n\nexport const defaultOptions = {\n preserveOrder: false,\n attributeNamePrefix: '@_',\n attributesGroupName: false,\n textNodeName: '#text',\n ignoreAttributes: true,\n removeNSPrefix: false, // remove NS from tag name or attribute name if true\n allowBooleanAttributes: false, //a tag can have attributes without any value\n //ignoreRootElement : false,\n parseTagValue: true,\n parseAttributeValue: false,\n trimValues: true, //Trim string values of tag and attributes\n cdataPropName: false,\n numberParseOptions: {\n hex: true,\n leadingZeros: true,\n eNotation: true\n },\n tagValueProcessor: function (tagName, val) {\n return val;\n },\n attributeValueProcessor: function (attrName, val) {\n return val;\n },\n stopNodes: [], //nested tags will not be parsed even for errors\n alwaysCreateTextNode: false,\n isArray: () => false,\n commentPropName: false,\n unpairedTags: [],\n processEntities: true,\n htmlEntities: false,\n entityDecoder: null,\n ignoreDeclaration: false,\n ignorePiTags: false,\n transformTagName: false,\n transformAttributeName: false,\n updateTag: function (tagName, jPath, attrs) {\n return tagName\n },\n // skipEmptyListItem: false\n captureMetaData: false,\n maxNestedTags: 100,\n strictReservedNames: true,\n jPath: true, // if true, pass jPath string to callbacks; if false, pass matcher instance\n onDangerousProperty: defaultOnDangerousProperty\n};\n\n\n/**\n * Validates that a property name is safe to use\n * @param {string} propertyName - The property name to validate\n * @param {string} optionName - The option field name (for error message)\n * @throws {Error} If property name is dangerous\n */\nfunction validatePropertyName(propertyName, optionName) {\n if (typeof propertyName !== 'string') {\n return; // Only validate string property names\n }\n\n const normalized = propertyName.toLowerCase();\n if (DANGEROUS_PROPERTY_NAMES.some(dangerous => normalized === dangerous.toLowerCase())) {\n throw new Error(\n `[SECURITY] Invalid ${optionName}: \"${propertyName}\" is a reserved JavaScript keyword that could cause prototype pollution`\n );\n }\n\n if (criticalProperties.some(dangerous => normalized === dangerous.toLowerCase())) {\n throw new Error(\n `[SECURITY] Invalid ${optionName}: \"${propertyName}\" is a reserved JavaScript keyword that could cause prototype pollution`\n );\n }\n}\n\n/**\n * Normalizes processEntities option for backward compatibility\n * @param {boolean|object} value \n * @returns {object} Always returns normalized object\n */\nfunction normalizeProcessEntities(value, htmlEntities) {\n // Boolean backward compatibility\n if (typeof value === 'boolean') {\n return {\n enabled: value, // true or false\n maxEntitySize: 10000,\n maxExpansionDepth: 10000,\n maxTotalExpansions: Infinity,\n maxExpandedLength: 100000,\n maxEntityCount: 1000,\n allowedTags: null,\n tagFilter: null,\n appliesTo: \"all\",\n };\n }\n\n // Object config - merge with defaults\n if (typeof value === 'object' && value !== null) {\n return {\n enabled: value.enabled !== false,\n maxEntitySize: Math.max(1, value.maxEntitySize ?? 10000),\n maxExpansionDepth: Math.max(1, value.maxExpansionDepth ?? 10000),\n maxTotalExpansions: Math.max(1, value.maxTotalExpansions ?? Infinity),\n maxExpandedLength: Math.max(1, value.maxExpandedLength ?? 100000),\n maxEntityCount: Math.max(1, value.maxEntityCount ?? 1000),\n allowedTags: value.allowedTags ?? null,\n tagFilter: value.tagFilter ?? null,\n appliesTo: value.appliesTo ?? \"all\",\n };\n }\n\n // Default to enabled with limits\n return normalizeProcessEntities(true);\n}\n\nexport const buildOptions = function (options) {\n const built = Object.assign({}, defaultOptions, options);\n\n // Validate property names to prevent prototype pollution\n const propertyNameOptions = [\n { value: built.attributeNamePrefix, name: 'attributeNamePrefix' },\n { value: built.attributesGroupName, name: 'attributesGroupName' },\n { value: built.textNodeName, name: 'textNodeName' },\n { value: built.cdataPropName, name: 'cdataPropName' },\n { value: built.commentPropName, name: 'commentPropName' }\n ];\n\n for (const { value, name } of propertyNameOptions) {\n if (value) {\n validatePropertyName(value, name);\n }\n }\n\n if (built.onDangerousProperty === null) {\n built.onDangerousProperty = defaultOnDangerousProperty;\n }\n\n // Always normalize processEntities for backward compatibility and validation\n built.processEntities = normalizeProcessEntities(built.processEntities, built.htmlEntities);\n built.unpairedTagsSet = new Set(built.unpairedTags);\n // Convert old-style stopNodes for backward compatibility\n if (built.stopNodes && Array.isArray(built.stopNodes)) {\n built.stopNodes = built.stopNodes.map(node => {\n if (typeof node === 'string' && node.startsWith('*.')) {\n // Old syntax: *.tagname meant \"tagname anywhere\"\n // Convert to new syntax: ..tagname\n return '..' + node.substring(2);\n }\n return node;\n });\n }\n //console.debug(built.processEntities)\n return built;\n};","'use strict';\n\nlet METADATA_SYMBOL;\n\nif (typeof Symbol !== \"function\") {\n METADATA_SYMBOL = \"@@xmlMetadata\";\n} else {\n METADATA_SYMBOL = Symbol(\"XML Node Metadata\");\n}\n\nexport default class XmlNode {\n constructor(tagname) {\n this.tagname = tagname;\n this.child = []; //nested tags, text, cdata, comments in order\n this[\":@\"] = Object.create(null); //attributes map\n }\n add(key, val) {\n // this.child.push( {name : key, val: val, isCdata: isCdata });\n if (key === \"__proto__\") key = \"#__proto__\";\n this.child.push({ [key]: val });\n }\n addChild(node, startIndex) {\n if (node.tagname === \"__proto__\") node.tagname = \"#__proto__\";\n if (node[\":@\"] && Object.keys(node[\":@\"]).length > 0) {\n this.child.push({ [node.tagname]: node.child, [\":@\"]: node[\":@\"] });\n } else {\n this.child.push({ [node.tagname]: node.child });\n }\n // if requested, add the startIndex\n if (startIndex !== undefined) {\n // Note: for now we just overwrite the metadata. If we had more complex metadata,\n // we might need to do an object append here: metadata = { ...metadata, startIndex }\n this.child[this.child.length - 1][METADATA_SYMBOL] = { startIndex };\n }\n }\n /** symbol used for metadata */\n static getMetaDataSymbol() {\n return METADATA_SYMBOL;\n }\n}\n","import { isName } from '../util.js';\n\nexport default class DocTypeReader {\n constructor(options) {\n this.suppressValidationErr = !options;\n this.options = options;\n }\n\n readDocType(xmlData, i) {\n const entities = Object.create(null);\n let entityCount = 0;\n\n if (xmlData[i + 3] === 'O' &&\n xmlData[i + 4] === 'C' &&\n xmlData[i + 5] === 'T' &&\n xmlData[i + 6] === 'Y' &&\n xmlData[i + 7] === 'P' &&\n xmlData[i + 8] === 'E') {\n i = i + 9;\n let angleBracketsCount = 1;\n let hasBody = false, comment = false;\n let exp = \"\";\n for (; i < xmlData.length; i++) {\n if (xmlData[i] === '<' && !comment) { //Determine the tag type\n if (hasBody && hasSeq(xmlData, \"!ENTITY\", i)) {\n i += 7;\n let entityName, val;\n [entityName, val, i] = this.readEntityExp(xmlData, i + 1, this.suppressValidationErr);\n if (val.indexOf(\"&\") === -1) { //Parameter entities are not supported\n if (this.options.enabled !== false &&\n this.options.maxEntityCount != null &&\n entityCount >= this.options.maxEntityCount) {\n throw new Error(\n `Entity count (${entityCount + 1}) exceeds maximum allowed (${this.options.maxEntityCount})`\n );\n }\n //const escaped = entityName.replace(/[.\\-+*:]/g, '\\\\.');\n //const escaped = entityName.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n entities[entityName] = val;\n entityCount++;\n }\n }\n else if (hasBody && hasSeq(xmlData, \"!ELEMENT\", i)) {\n i += 8;//Not supported\n const { index } = this.readElementExp(xmlData, i + 1);\n i = index;\n } else if (hasBody && hasSeq(xmlData, \"!ATTLIST\", i)) {\n i += 8;//Not supported\n // const {index} = this.readAttlistExp(xmlData,i+1);\n // i = index;\n } else if (hasBody && hasSeq(xmlData, \"!NOTATION\", i)) {\n i += 9;//Not supported\n const { index } = this.readNotationExp(xmlData, i + 1, this.suppressValidationErr);\n i = index;\n } else if (hasSeq(xmlData, \"!--\", i)) comment = true;\n else throw new Error(`Invalid DOCTYPE`);\n\n angleBracketsCount++;\n exp = \"\";\n } else if (xmlData[i] === '>') { //Read tag content\n if (comment) {\n if (xmlData[i - 1] === \"-\" && xmlData[i - 2] === \"-\") {\n comment = false;\n angleBracketsCount--;\n }\n } else {\n angleBracketsCount--;\n }\n if (angleBracketsCount === 0) {\n break;\n }\n } else if (xmlData[i] === '[') {\n hasBody = true;\n } else {\n exp += xmlData[i];\n }\n }\n if (angleBracketsCount !== 0) {\n throw new Error(`Unclosed DOCTYPE`);\n }\n } else {\n throw new Error(`Invalid Tag instead of DOCTYPE`);\n }\n return { entities, i };\n }\n readEntityExp(xmlData, i) {\n //External entities are not supported\n // <!ENTITY ext SYSTEM \"http://normal-website.com\" >\n\n //Parameter entities are not supported\n // <!ENTITY entityname \"&anotherElement;\">\n\n //Internal entities are supported\n // <!ENTITY entityname \"replacement text\">\n\n // Skip leading whitespace after <!ENTITY\n i = skipWhitespace(xmlData, i);\n\n // Read entity name\n const startIndex = i;\n while (i < xmlData.length && !/\\s/.test(xmlData[i]) && xmlData[i] !== '\"' && xmlData[i] !== \"'\") {\n i++;\n }\n let entityName = xmlData.substring(startIndex, i);\n\n validateEntityName(entityName);\n\n // Skip whitespace after entity name\n i = skipWhitespace(xmlData, i);\n\n // Check for unsupported constructs (external entities or parameter entities)\n if (!this.suppressValidationErr) {\n if (xmlData.substring(i, i + 6).toUpperCase() === \"SYSTEM\") {\n throw new Error(\"External entities are not supported\");\n } else if (xmlData[i] === \"%\") {\n throw new Error(\"Parameter entities are not supported\");\n }\n }\n\n // Read entity value (internal entity)\n let entityValue = \"\";\n [i, entityValue] = this.readIdentifierVal(xmlData, i, \"entity\");\n\n // Validate entity size\n if (this.options.enabled !== false &&\n this.options.maxEntitySize != null &&\n entityValue.length > this.options.maxEntitySize) {\n throw new Error(\n `Entity \"${entityName}\" size (${entityValue.length}) exceeds maximum allowed size (${this.options.maxEntitySize})`\n );\n }\n\n i--;\n return [entityName, entityValue, i];\n }\n\n readNotationExp(xmlData, i) {\n // Skip leading whitespace after <!NOTATION\n i = skipWhitespace(xmlData, i);\n\n // Read notation name\n\n const startIndex = i;\n while (i < xmlData.length && !/\\s/.test(xmlData[i])) {\n i++;\n }\n let notationName = xmlData.substring(startIndex, i);\n\n !this.suppressValidationErr && validateEntityName(notationName);\n\n // Skip whitespace after notation name\n i = skipWhitespace(xmlData, i);\n\n // Check identifier type (SYSTEM or PUBLIC)\n const identifierType = xmlData.substring(i, i + 6).toUpperCase();\n if (!this.suppressValidationErr && identifierType !== \"SYSTEM\" && identifierType !== \"PUBLIC\") {\n throw new Error(`Expected SYSTEM or PUBLIC, found \"${identifierType}\"`);\n }\n i += identifierType.length;\n\n // Skip whitespace after identifier type\n i = skipWhitespace(xmlData, i);\n\n // Read public identifier (if PUBLIC)\n let publicIdentifier = null;\n let systemIdentifier = null;\n\n if (identifierType === \"PUBLIC\") {\n [i, publicIdentifier] = this.readIdentifierVal(xmlData, i, \"publicIdentifier\");\n\n // Skip whitespace after public identifier\n i = skipWhitespace(xmlData, i);\n\n // Optionally read system identifier\n if (xmlData[i] === '\"' || xmlData[i] === \"'\") {\n [i, systemIdentifier] = this.readIdentifierVal(xmlData, i, \"systemIdentifier\");\n }\n } else if (identifierType === \"SYSTEM\") {\n // Read system identifier (mandatory for SYSTEM)\n [i, systemIdentifier] = this.readIdentifierVal(xmlData, i, \"systemIdentifier\");\n\n if (!this.suppressValidationErr && !systemIdentifier) {\n throw new Error(\"Missing mandatory system identifier for SYSTEM notation\");\n }\n }\n\n return { notationName, publicIdentifier, systemIdentifier, index: --i };\n }\n\n readIdentifierVal(xmlData, i, type) {\n let identifierVal = \"\";\n const startChar = xmlData[i];\n if (startChar !== '\"' && startChar !== \"'\") {\n throw new Error(`Expected quoted string, found \"${startChar}\"`);\n }\n i++;\n\n const startIndex = i;\n while (i < xmlData.length && xmlData[i] !== startChar) {\n i++;\n }\n identifierVal = xmlData.substring(startIndex, i);\n\n if (xmlData[i] !== startChar) {\n throw new Error(`Unterminated ${type} value`);\n }\n i++;\n return [i, identifierVal];\n }\n\n readElementExp(xmlData, i) {\n // <!ELEMENT br EMPTY>\n // <!ELEMENT div ANY>\n // <!ELEMENT title (#PCDATA)>\n // <!ELEMENT book (title, author+)>\n // <!ELEMENT name (content-model)>\n\n // Skip leading whitespace after <!ELEMENT\n i = skipWhitespace(xmlData, i);\n\n // Read element name\n const startIndex = i;\n while (i < xmlData.length && !/\\s/.test(xmlData[i])) {\n i++;\n }\n let elementName = xmlData.substring(startIndex, i);\n\n // Validate element name\n if (!this.suppressValidationErr && !isName(elementName)) {\n throw new Error(`Invalid element name: \"${elementName}\"`);\n }\n\n // Skip whitespace after element name\n i = skipWhitespace(xmlData, i);\n let contentModel = \"\";\n // Expect '(' to start content model\n if (xmlData[i] === \"E\" && hasSeq(xmlData, \"MPTY\", i)) i += 4;\n else if (xmlData[i] === \"A\" && hasSeq(xmlData, \"NY\", i)) i += 2;\n else if (xmlData[i] === \"(\") {\n i++; // Move past '('\n\n // Read content model\n const startIndex = i;\n while (i < xmlData.length && xmlData[i] !== \")\") {\n i++;\n }\n contentModel = xmlData.substring(startIndex, i);\n\n if (xmlData[i] !== \")\") {\n throw new Error(\"Unterminated content model\");\n }\n\n } else if (!this.suppressValidationErr) {\n throw new Error(`Invalid Element Expression, found \"${xmlData[i]}\"`);\n }\n\n return {\n elementName,\n contentModel: contentModel.trim(),\n index: i\n };\n }\n\n readAttlistExp(xmlData, i) {\n // Skip leading whitespace after <!ATTLIST\n i = skipWhitespace(xmlData, i);\n\n // Read element name\n let startIndex = i;\n while (i < xmlData.length && !/\\s/.test(xmlData[i])) {\n i++;\n }\n let elementName = xmlData.substring(startIndex, i);\n\n // Validate element name\n validateEntityName(elementName)\n\n // Skip whitespace after element name\n i = skipWhitespace(xmlData, i);\n\n // Read attribute name\n startIndex = i;\n while (i < xmlData.length && !/\\s/.test(xmlData[i])) {\n i++;\n }\n let attributeName = xmlData.substring(startIndex, i);\n\n // Validate attribute name\n if (!validateEntityName(attributeName)) {\n throw new Error(`Invalid attribute name: \"${attributeName}\"`);\n }\n\n // Skip whitespace after attribute name\n i = skipWhitespace(xmlData, i);\n\n // Read attribute type\n let attributeType = \"\";\n if (xmlData.substring(i, i + 8).toUpperCase() === \"NOTATION\") {\n attributeType = \"NOTATION\";\n i += 8; // Move past \"NOTATION\"\n\n // Skip whitespace after \"NOTATION\"\n i = skipWhitespace(xmlData, i);\n\n // Expect '(' to start the list of notations\n if (xmlData[i] !== \"(\") {\n throw new Error(`Expected '(', found \"${xmlData[i]}\"`);\n }\n i++; // Move past '('\n\n // Read the list of allowed notations\n let allowedNotations = [];\n while (i < xmlData.length && xmlData[i] !== \")\") {\n\n\n const startIndex = i;\n while (i < xmlData.length && xmlData[i] !== \"|\" && xmlData[i] !== \")\") {\n i++;\n }\n let notation = xmlData.substring(startIndex, i);\n\n // Validate notation name\n notation = notation.trim();\n if (!validateEntityName(notation)) {\n throw new Error(`Invalid notation name: \"${notation}\"`);\n }\n\n allowedNotations.push(notation);\n\n // Skip '|' separator or exit loop\n if (xmlData[i] === \"|\") {\n i++; // Move past '|'\n i = skipWhitespace(xmlData, i); // Skip optional whitespace after '|'\n }\n }\n\n if (xmlData[i] !== \")\") {\n throw new Error(\"Unterminated list of notations\");\n }\n i++; // Move past ')'\n\n // Store the allowed notations as part of the attribute type\n attributeType += \" (\" + allowedNotations.join(\"|\") + \")\";\n } else {\n // Handle simple types (e.g., CDATA, ID, IDREF, etc.)\n const startIndex = i;\n while (i < xmlData.length && !/\\s/.test(xmlData[i])) {\n i++;\n }\n attributeType += xmlData.substring(startIndex, i);\n\n // Validate simple attribute type\n const validTypes = [\"CDATA\", \"ID\", \"IDREF\", \"IDREFS\", \"ENTITY\", \"ENTITIES\", \"NMTOKEN\", \"NMTOKENS\"];\n if (!this.suppressValidationErr && !validTypes.includes(attributeType.toUpperCase())) {\n throw new Error(`Invalid attribute type: \"${attributeType}\"`);\n }\n }\n\n // Skip whitespace after attribute type\n i = skipWhitespace(xmlData, i);\n\n // Read default value\n let defaultValue = \"\";\n if (xmlData.substring(i, i + 8).toUpperCase() === \"#REQUIRED\") {\n defaultValue = \"#REQUIRED\";\n i += 8;\n } else if (xmlData.substring(i, i + 7).toUpperCase() === \"#IMPLIED\") {\n defaultValue = \"#IMPLIED\";\n i += 7;\n } else {\n [i, defaultValue] = this.readIdentifierVal(xmlData, i, \"ATTLIST\");\n }\n\n return {\n elementName,\n attributeName,\n attributeType,\n defaultValue,\n index: i\n }\n }\n}\n\n\n\nconst skipWhitespace = (data, index) => {\n while (index < data.length && /\\s/.test(data[index])) {\n index++;\n }\n return index;\n};\n\n\n\nfunction hasSeq(data, seq, i) {\n for (let j = 0; j < seq.length; j++) {\n if (seq[j] !== data[i + j + 1]) return false;\n }\n return true;\n}\n\nfunction validateEntityName(name) {\n if (isName(name))\n return name;\n else\n throw new Error(`Invalid entity name ${name}`);\n}","const hexRegex = /^[-+]?0x[a-fA-F0-9]+$/;\nconst numRegex = /^([\\-\\+])?(0*)([0-9]*(\\.[0-9]*)?)$/;\n// const octRegex = /^0x[a-z0-9]+/;\n// const binRegex = /0x[a-z0-9]+/;\n\n\nconst consider = {\n hex: true,\n // oct: false,\n leadingZeros: true,\n decimalPoint: \"\\.\",\n eNotation: true,\n //skipLike: /regex/,\n infinity: \"original\", // \"null\", \"infinity\" (Infinity type), \"string\" (\"Infinity\" (the string literal))\n};\n\nexport default function toNumber(str, options = {}) {\n options = Object.assign({}, consider, options);\n if (!str || typeof str !== \"string\") return str;\n\n let trimmedStr = str.trim();\n\n if (trimmedStr.length === 0) return str;\n else if (options.skipLike !== undefined && options.skipLike.test(trimmedStr)) return str;\n else if (trimmedStr === \"0\") return 0;\n else if (options.hex && hexRegex.test(trimmedStr)) {\n return parse_int(trimmedStr, 16);\n // }else if (options.oct && octRegex.test(str)) {\n // return Number.parseInt(val, 8);\n } else if (!isFinite(trimmedStr)) { //Infinity\n return handleInfinity(str, Number(trimmedStr), options);\n } else if (trimmedStr.includes('e') || trimmedStr.includes('E')) { //eNotation\n return resolveEnotation(str, trimmedStr, options);\n // }else if (options.parseBin && binRegex.test(str)) {\n // return Number.parseInt(val, 2);\n } else {\n //separate negative sign, leading zeros, and rest number\n const match = numRegex.exec(trimmedStr);\n // +00.123 => [ , '+', '00', '.123', ..\n if (match) {\n const sign = match[1] || \"\";\n const leadingZeros = match[2];\n let numTrimmedByZeros = trimZeros(match[3]); //complete num without leading zeros\n const decimalAdjacentToLeadingZeros = sign ? // 0., -00., 000.\n str[leadingZeros.length + 1] === \".\"\n : str[leadingZeros.length] === \".\";\n\n //trim ending zeros for floating number\n if (!options.leadingZeros //leading zeros are not allowed\n && (leadingZeros.length > 1\n || (leadingZeros.length === 1 && !decimalAdjacentToLeadingZeros))) {\n // 00, 00.3, +03.24, 03, 03.24\n return str;\n }\n else {//no leading zeros or leading zeros are allowed\n const num = Number(trimmedStr);\n const parsedStr = String(num);\n\n if (num === 0) return num;\n if (parsedStr.search(/[eE]/) !== -1) { //given number is long and parsed to eNotation\n if (options.eNotation) return num;\n else return str;\n } else if (trimmedStr.indexOf(\".\") !== -1) { //floating number\n if (parsedStr === \"0\") return num; //0.0\n else if (parsedStr === numTrimmedByZeros) return num; //0.456. 0.79000\n else if (parsedStr === `${sign}${numTrimmedByZeros}`) return num;\n else return str;\n }\n\n let n = leadingZeros ? numTrimmedByZeros : trimmedStr;\n if (leadingZeros) {\n // -009 => -9\n return (n === parsedStr) || (sign + n === parsedStr) ? num : str\n } else {\n // +9\n return (n === parsedStr) || (n === sign + parsedStr) ? num : str\n }\n }\n } else { //non-numeric string\n return str;\n }\n }\n}\n\nconst eNotationRegx = /^([-+])?(0*)(\\d*(\\.\\d*)?[eE][-\\+]?\\d+)$/;\nfunction resolveEnotation(str, trimmedStr, options) {\n if (!options.eNotation) return str;\n const notation = trimmedStr.match(eNotationRegx);\n if (notation) {\n let sign = notation[1] || \"\";\n const eChar = notation[3].indexOf(\"e\") === -1 ? \"E\" : \"e\";\n const leadingZeros = notation[2];\n const eAdjacentToLeadingZeros = sign ? // 0E.\n str[leadingZeros.length + 1] === eChar\n : str[leadingZeros.length] === eChar;\n\n if (leadingZeros.length > 1 && eAdjacentToLeadingZeros) return str;\n else if (leadingZeros.length === 1\n && (notation[3].startsWith(`.${eChar}`) || notation[3][0] === eChar)) {\n return Number(trimmedStr);\n } else if (leadingZeros.length > 0) {\n // Has leading zeros — only accept if leadingZeros option allows it\n if (options.leadingZeros && !eAdjacentToLeadingZeros) {\n trimmedStr = (notation[1] || \"\") + notation[3];\n return Number(trimmedStr);\n } else return str;\n } else {\n // No leading zeros — always valid e-notation, parse it\n return Number(trimmedStr);\n }\n } else {\n return str;\n }\n}\n\n/**\n * \n * @param {string} numStr without leading zeros\n * @returns \n */\nfunction trimZeros(numStr) {\n if (numStr && numStr.indexOf(\".\") !== -1) {//float\n numStr = numStr.replace(/0+$/, \"\"); //remove ending zeros\n if (numStr === \".\") numStr = \"0\";\n else if (numStr[0] === \".\") numStr = \"0\" + numStr;\n else if (numStr[numStr.length - 1] === \".\") numStr = numStr.substring(0, numStr.length - 1);\n return numStr;\n }\n return numStr;\n}\n\nfunction parse_int(numStr, base) {\n //polyfill\n if (parseInt) return parseInt(numStr, base);\n else if (Number.parseInt) return Number.parseInt(numStr, base);\n else if (window && window.parseInt) return window.parseInt(numStr, base);\n else throw new Error(\"parseInt, Number.parseInt, window.parseInt are not supported\")\n}\n\n/**\n * Handle infinite values based on user option\n * @param {string} str - original input string\n * @param {number} num - parsed number (Infinity or -Infinity)\n * @param {object} options - user options\n * @returns {string|number|null} based on infinity option\n */\nfunction handleInfinity(str, num, options) {\n const isPositive = num === Infinity;\n\n switch (options.infinity.toLowerCase()) {\n case \"null\":\n return null;\n case \"infinity\":\n return num; // Return Infinity or -Infinity\n case \"string\":\n return isPositive ? \"Infinity\" : \"-Infinity\";\n case \"original\":\n default:\n return str; // Return original string like \"1e1000\"\n }\n}","export default function getIgnoreAttributesFn(ignoreAttributes) {\n if (typeof ignoreAttributes === 'function') {\n return ignoreAttributes\n }\n if (Array.isArray(ignoreAttributes)) {\n return (attrName) => {\n for (const pattern of ignoreAttributes) {\n if (typeof pattern === 'string' && attrName === pattern) {\n return true\n }\n if (pattern instanceof RegExp && pattern.test(attrName)) {\n return true\n }\n }\n }\n }\n return () => false\n}","/**\n * Expression - Parses and stores a tag pattern expression\n * \n * Patterns are parsed once and stored in an optimized structure for fast matching.\n * \n * @example\n * const expr = new Expression(\"root.users.user\");\n * const expr2 = new Expression(\"..user[id]:first\");\n * const expr3 = new Expression(\"root/users/user\", { separator: '/' });\n */\nexport default class Expression {\n /**\n * Create a new Expression\n * @param {string} pattern - Pattern string (e.g., \"root.users.user\", \"..user[id]\")\n * @param {Object} options - Configuration options\n * @param {string} options.separator - Path separator (default: '.')\n */\n constructor(pattern, options = {}, data) {\n this.pattern = pattern;\n this.separator = options.separator || '.';\n this.segments = this._parse(pattern);\n this.data = data;\n // Cache expensive checks for performance (O(1) instead of O(n))\n this._hasDeepWildcard = this.segments.some(seg => seg.type === 'deep-wildcard');\n this._hasAttributeCondition = this.segments.some(seg => seg.attrName !== undefined);\n this._hasPositionSelector = this.segments.some(seg => seg.position !== undefined);\n }\n\n /**\n * Parse pattern string into segments\n * @private\n * @param {string} pattern - Pattern to parse\n * @returns {Array} Array of segment objects\n */\n _parse(pattern) {\n const segments = [];\n\n // Split by separator but handle \"..\" specially\n let i = 0;\n let currentPart = '';\n\n while (i < pattern.length) {\n if (pattern[i] === this.separator) {\n // Check if next char is also separator (deep wildcard)\n if (i + 1 < pattern.length && pattern[i + 1] === this.separator) {\n // Flush current part if any\n if (currentPart.trim()) {\n segments.push(this._parseSegment(currentPart.trim()));\n currentPart = '';\n }\n // Add deep wildcard\n segments.push({ type: 'deep-wildcard' });\n i += 2; // Skip both separators\n } else {\n // Regular separator\n if (currentPart.trim()) {\n segments.push(this._parseSegment(currentPart.trim()));\n }\n currentPart = '';\n i++;\n }\n } else {\n currentPart += pattern[i];\n i++;\n }\n }\n\n // Flush remaining part\n if (currentPart.trim()) {\n segments.push(this._parseSegment(currentPart.trim()));\n }\n\n return segments;\n }\n\n /**\n * Parse a single segment\n * @private\n * @param {string} part - Segment string (e.g., \"user\", \"ns::user\", \"user[id]\", \"ns::user:first\")\n * @returns {Object} Segment object\n */\n _parseSegment(part) {\n const segment = { type: 'tag' };\n\n // NEW NAMESPACE SYNTAX (v2.0):\n // ============================\n // Namespace uses DOUBLE colon (::)\n // Position uses SINGLE colon (:)\n // \n // Examples:\n // \"user\" → tag\n // \"user:first\" → tag + position\n // \"user[id]\" → tag + attribute\n // \"user[id]:first\" → tag + attribute + position\n // \"ns::user\" → namespace + tag\n // \"ns::user:first\" → namespace + tag + position\n // \"ns::user[id]\" → namespace + tag + attribute\n // \"ns::user[id]:first\" → namespace + tag + attribute + position\n // \"ns::first\" → namespace + tag named \"first\" (NO ambiguity!)\n //\n // This eliminates all ambiguity:\n // :: = namespace separator\n // : = position selector\n // [] = attributes\n\n // Step 1: Extract brackets [attr] or [attr=value]\n let bracketContent = null;\n let withoutBrackets = part;\n\n const bracketMatch = part.match(/^([^\\[]+)(\\[[^\\]]*\\])(.*)$/);\n if (bracketMatch) {\n withoutBrackets = bracketMatch[1] + bracketMatch[3];\n if (bracketMatch[2]) {\n const content = bracketMatch[2].slice(1, -1);\n if (content) {\n bracketContent = content;\n }\n }\n }\n\n // Step 2: Check for namespace (double colon ::)\n let namespace = undefined;\n let tagAndPosition = withoutBrackets;\n\n if (withoutBrackets.includes('::')) {\n const nsIndex = withoutBrackets.indexOf('::');\n namespace = withoutBrackets.substring(0, nsIndex).trim();\n tagAndPosition = withoutBrackets.substring(nsIndex + 2).trim(); // Skip ::\n\n if (!namespace) {\n throw new Error(`Invalid namespace in pattern: ${part}`);\n }\n }\n\n // Step 3: Parse tag and position (single colon :)\n let tag = undefined;\n let positionMatch = null;\n\n if (tagAndPosition.includes(':')) {\n const colonIndex = tagAndPosition.lastIndexOf(':'); // Use last colon for position\n const tagPart = tagAndPosition.substring(0, colonIndex).trim();\n const posPart = tagAndPosition.substring(colonIndex + 1).trim();\n\n // Verify position is a valid keyword\n const isPositionKeyword = ['first', 'last', 'odd', 'even'].includes(posPart) ||\n /^nth\\(\\d+\\)$/.test(posPart);\n\n if (isPositionKeyword) {\n tag = tagPart;\n positionMatch = posPart;\n } else {\n // Not a valid position keyword, treat whole thing as tag\n tag = tagAndPosition;\n }\n } else {\n tag = tagAndPosition;\n }\n\n if (!tag) {\n throw new Error(`Invalid segment pattern: ${part}`);\n }\n\n segment.tag = tag;\n if (namespace) {\n segment.namespace = namespace;\n }\n\n // Step 4: Parse attributes\n if (bracketContent) {\n if (bracketContent.includes('=')) {\n const eqIndex = bracketContent.indexOf('=');\n segment.attrName = bracketContent.substring(0, eqIndex).trim();\n segment.attrValue = bracketContent.substring(eqIndex + 1).trim();\n } else {\n segment.attrName = bracketContent.trim();\n }\n }\n\n // Step 5: Parse position selector\n if (positionMatch) {\n const nthMatch = positionMatch.match(/^nth\\((\\d+)\\)$/);\n if (nthMatch) {\n segment.position = 'nth';\n segment.positionValue = parseInt(nthMatch[1], 10);\n } else {\n segment.position = positionMatch;\n }\n }\n\n return segment;\n }\n\n /**\n * Get the number of segments\n * @returns {number}\n */\n get length() {\n return this.segments.length;\n }\n\n /**\n * Check if expression contains deep wildcard\n * @returns {boolean}\n */\n hasDeepWildcard() {\n return this._hasDeepWildcard;\n }\n\n /**\n * Check if expression has attribute conditions\n * @returns {boolean}\n */\n hasAttributeCondition() {\n return this._hasAttributeCondition;\n }\n\n /**\n * Check if expression has position selectors\n * @returns {boolean}\n */\n hasPositionSelector() {\n return this._hasPositionSelector;\n }\n\n /**\n * Get string representation\n * @returns {string}\n */\n toString() {\n return this.pattern;\n }\n}","/**\n * ExpressionSet - An indexed collection of Expressions for efficient bulk matching\n *\n * Instead of iterating all expressions on every tag, ExpressionSet pre-indexes\n * them at insertion time by depth and terminal tag name. At match time, only\n * the relevant bucket is evaluated — typically reducing checks from O(E) to O(1)\n * lookup plus O(small bucket) matches.\n *\n * Three buckets are maintained:\n * - `_byDepthAndTag` — exact depth + exact tag name (tightest, used first)\n * - `_wildcardByDepth` — exact depth + wildcard tag `*` (depth-matched only)\n * - `_deepWildcards` — expressions containing `..` (cannot be depth-indexed)\n *\n * @example\n * import { Expression, ExpressionSet } from 'fast-xml-tagger';\n *\n * // Build once at config time\n * const stopNodes = new ExpressionSet();\n * stopNodes.add(new Expression('root.users.user'));\n * stopNodes.add(new Expression('root.config.setting'));\n * stopNodes.add(new Expression('..script'));\n *\n * // Query on every tag — hot path\n * if (stopNodes.matchesAny(matcher)) { ... }\n */\nexport default class ExpressionSet {\n constructor() {\n /** @type {Map<string, import('./Expression.js').default[]>} depth:tag → expressions */\n this._byDepthAndTag = new Map();\n\n /** @type {Map<number, import('./Expression.js').default[]>} depth → wildcard-tag expressions */\n this._wildcardByDepth = new Map();\n\n /** @type {import('./Expression.js').default[]} expressions containing deep wildcard (..) */\n this._deepWildcards = [];\n\n /** @type {Set<string>} pattern strings already added — used for deduplication */\n this._patterns = new Set();\n\n /** @type {boolean} whether the set is sealed against further additions */\n this._sealed = false;\n }\n\n /**\n * Add an Expression to the set.\n * Duplicate patterns (same pattern string) are silently ignored.\n *\n * @param {import('./Expression.js').default} expression - A pre-constructed Expression instance\n * @returns {this} for chaining\n * @throws {TypeError} if called after seal()\n *\n * @example\n * set.add(new Expression('root.users.user'));\n * set.add(new Expression('..script'));\n */\n add(expression) {\n if (this._sealed) {\n throw new TypeError(\n 'ExpressionSet is sealed. Create a new ExpressionSet to add more expressions.'\n );\n }\n\n // Deduplicate by pattern string\n if (this._patterns.has(expression.pattern)) return this;\n this._patterns.add(expression.pattern);\n\n if (expression.hasDeepWildcard()) {\n this._deepWildcards.push(expression);\n return this;\n }\n\n const depth = expression.length;\n const lastSeg = expression.segments[expression.segments.length - 1];\n const tag = lastSeg?.tag;\n\n if (!tag || tag === '*') {\n // Can index by depth but not by tag\n if (!this._wildcardByDepth.has(depth)) this._wildcardByDepth.set(depth, []);\n this._wildcardByDepth.get(depth).push(expression);\n } else {\n // Tightest bucket: depth + tag\n const key = `${depth}:${tag}`;\n if (!this._byDepthAndTag.has(key)) this._byDepthAndTag.set(key, []);\n this._byDepthAndTag.get(key).push(expression);\n }\n\n return this;\n }\n\n /**\n * Add multiple expressions at once.\n *\n * @param {import('./Expression.js').default[]} expressions - Array of Expression instances\n * @returns {this} for chaining\n *\n * @example\n * set.addAll([\n * new Expression('root.users.user'),\n * new Expression('root.config.setting'),\n * ]);\n */\n addAll(expressions) {\n for (const expr of expressions) this.add(expr);\n return this;\n }\n\n /**\n * Check whether a pattern string is already present in the set.\n *\n * @param {import('./Expression.js').default} expression\n * @returns {boolean}\n */\n has(expression) {\n return this._patterns.has(expression.pattern);\n }\n\n /**\n * Number of expressions in the set.\n * @type {number}\n */\n get size() {\n return this._patterns.size;\n }\n\n /**\n * Seal the set against further modifications.\n * Useful to prevent accidental mutations after config is built.\n * Calling add() or addAll() on a sealed set throws a TypeError.\n *\n * @returns {this}\n */\n seal() {\n this._sealed = true;\n return this;\n }\n\n /**\n * Whether the set has been sealed.\n * @type {boolean}\n */\n get isSealed() {\n return this._sealed;\n }\n\n /**\n * Test whether the matcher's current path matches any expression in the set.\n *\n * Evaluation order (cheapest → most expensive):\n * 1. Exact depth + tag bucket — O(1) lookup, typically 0–2 expressions\n * 2. Depth-only wildcard bucket — O(1) lookup, rare\n * 3. Deep-wildcard list — always checked, but usually small\n *\n * @param {import('./Matcher.js').default} matcher - Matcher instance (or readOnly view)\n * @returns {boolean} true if any expression matches the current path\n *\n * @example\n * if (stopNodes.matchesAny(matcher)) {\n * // handle stop node\n * }\n */\n matchesAny(matcher) {\n return this.findMatch(matcher) !== null;\n }\n /**\n * Find and return the first Expression that matches the matcher's current path.\n *\n * Uses the same evaluation order as matchesAny (cheapest → most expensive):\n * 1. Exact depth + tag bucket\n * 2. Depth-only wildcard bucket\n * 3. Deep-wildcard list\n *\n * @param {import('./Matcher.js').default} matcher - Matcher instance (or readOnly view)\n * @returns {import('./Expression.js').default | null} the first matching Expression, or null\n *\n * @example\n * const expr = stopNodes.findMatch(matcher);\n * if (expr) {\n * // access expr.config, expr.pattern, etc.\n * }\n */\n findMatch(matcher) {\n const depth = matcher.getDepth();\n const tag = matcher.getCurrentTag();\n\n // 1. Tightest bucket — most expressions live here\n const exactKey = `${depth}:${tag}`;\n const exactBucket = this._byDepthAndTag.get(exactKey);\n if (exactBucket) {\n for (let i = 0; i < exactBucket.length; i++) {\n if (matcher.matches(exactBucket[i])) return exactBucket[i];\n }\n }\n\n // 2. Depth-matched wildcard-tag expressions\n const wildcardBucket = this._wildcardByDepth.get(depth);\n if (wildcardBucket) {\n for (let i = 0; i < wildcardBucket.length; i++) {\n if (matcher.matches(wildcardBucket[i])) return wildcardBucket[i];\n }\n }\n\n // 3. Deep wildcards — cannot be pre-filtered by depth or tag\n for (let i = 0; i < this._deepWildcards.length; i++) {\n if (matcher.matches(this._deepWildcards[i])) return this._deepWildcards[i];\n }\n\n return null;\n }\n}\n","import ExpressionSet from \"./ExpressionSet.js\";\n\n/**\n * MatcherView - A lightweight read-only view over a Matcher's internal state.\n *\n * Created once by Matcher and reused across all callbacks. Holds a direct\n * reference to the parent Matcher so it always reflects current parser state\n * with zero copying or freezing overhead.\n *\n * Users receive this via {@link Matcher#readOnly} or directly from parser\n * callbacks. It exposes all query and matching methods but has no mutation\n * methods — misuse is caught at the TypeScript level rather than at runtime.\n *\n * @example\n * const matcher = new Matcher();\n * const view = matcher.readOnly();\n *\n * matcher.push(\"root\", {});\n * view.getCurrentTag(); // \"root\"\n * view.getDepth(); // 1\n */\nexport class MatcherView {\n /**\n * @param {Matcher} matcher - The parent Matcher instance to read from.\n */\n constructor(matcher) {\n this._matcher = matcher;\n }\n\n /**\n * Get the path separator used by the parent matcher.\n * @returns {string}\n */\n get separator() {\n return this._matcher.separator;\n }\n\n /**\n * Get current tag name.\n * @returns {string|undefined}\n */\n getCurrentTag() {\n const path = this._matcher.path;\n return path.length > 0 ? path[path.length - 1].tag : undefined;\n }\n\n /**\n * Get current namespace.\n * @returns {string|undefined}\n */\n getCurrentNamespace() {\n const path = this._matcher.path;\n return path.length > 0 ? path[path.length - 1].namespace : undefined;\n }\n\n /**\n * Get current node's attribute value.\n * @param {string} attrName\n * @returns {*}\n */\n getAttrValue(attrName) {\n const path = this._matcher.path;\n if (path.length === 0) return undefined;\n return path[path.length - 1].values?.[attrName];\n }\n\n /**\n * Check if current node has an attribute.\n * @param {string} attrName\n * @returns {boolean}\n */\n hasAttr(attrName) {\n const path = this._matcher.path;\n if (path.length === 0) return false;\n const current = path[path.length - 1];\n return current.values !== undefined && attrName in current.values;\n }\n\n /**\n * Get current node's sibling position (child index in parent).\n * @returns {number}\n */\n getPosition() {\n const path = this._matcher.path;\n if (path.length === 0) return -1;\n return path[path.length - 1].position ?? 0;\n }\n\n /**\n * Get current node's repeat counter (occurrence count of this tag name).\n * @returns {number}\n */\n getCounter() {\n const path = this._matcher.path;\n if (path.length === 0) return -1;\n return path[path.length - 1].counter ?? 0;\n }\n\n /**\n * Get current node's sibling index (alias for getPosition).\n * @returns {number}\n * @deprecated Use getPosition() or getCounter() instead\n */\n getIndex() {\n return this.getPosition();\n }\n\n /**\n * Get current path depth.\n * @returns {number}\n */\n getDepth() {\n return this._matcher.path.length;\n }\n\n /**\n * Get path as string.\n * @param {string} [separator] - Optional separator (uses default if not provided)\n * @param {boolean} [includeNamespace=true]\n * @returns {string}\n */\n toString(separator, includeNamespace = true) {\n return this._matcher.toString(separator, includeNamespace);\n }\n\n /**\n * Get path as array of tag names.\n * @returns {string[]}\n */\n toArray() {\n return this._matcher.path.map(n => n.tag);\n }\n\n /**\n * Match current path against an Expression.\n * @param {Expression} expression\n * @returns {boolean}\n */\n matches(expression) {\n return this._matcher.matches(expression);\n }\n\n /**\n * Match any expression in the given set against the current path.\n * @param {ExpressionSet} exprSet\n * @returns {boolean}\n */\n matchesAny(exprSet) {\n return exprSet.matchesAny(this._matcher);\n }\n}\n\n/**\n * Matcher - Tracks current path in XML/JSON tree and matches against Expressions.\n *\n * The matcher maintains a stack of nodes representing the current path from root to\n * current tag. It only stores attribute values for the current (top) node to minimize\n * memory usage. Sibling tracking is used to auto-calculate position and counter.\n *\n * Use {@link Matcher#readOnly} to obtain a {@link MatcherView} safe to pass to\n * user callbacks — it always reflects current state with no Proxy overhead.\n *\n * @example\n * const matcher = new Matcher();\n * matcher.push(\"root\", {});\n * matcher.push(\"users\", {});\n * matcher.push(\"user\", { id: \"123\", type: \"admin\" });\n *\n * const expr = new Expression(\"root.users.user\");\n * matcher.matches(expr); // true\n */\nexport default class Matcher {\n /**\n * Create a new Matcher.\n * @param {Object} [options={}]\n * @param {string} [options.separator='.'] - Default path separator\n */\n constructor(options = {}) {\n this.separator = options.separator || '.';\n this.path = [];\n this.siblingStacks = [];\n // Each path node: { tag, values, position, counter, namespace? }\n // values only present for current (last) node\n // Each siblingStacks entry: Map<tagName, count> tracking occurrences at each level\n this._pathStringCache = null;\n this._view = new MatcherView(this);\n }\n\n /**\n * Push a new tag onto the path.\n * @param {string} tagName\n * @param {Object|null} [attrValues=null]\n * @param {string|null} [namespace=null]\n */\n push(tagName, attrValues = null, namespace = null) {\n this._pathStringCache = null;\n\n // Remove values from previous current node (now becoming ancestor)\n if (this.path.length > 0) {\n this.path[this.path.length - 1].values = undefined;\n }\n\n // Get or create sibling tracking for current level\n const currentLevel = this.path.length;\n if (!this.siblingStacks[currentLevel]) {\n this.siblingStacks[currentLevel] = new Map();\n }\n\n const siblings = this.siblingStacks[currentLevel];\n\n // Create a unique key for sibling tracking that includes namespace\n const siblingKey = namespace ? `${namespace}:${tagName}` : tagName;\n\n // Calculate counter (how many times this tag appeared at this level)\n const counter = siblings.get(siblingKey) || 0;\n\n // Calculate position (total children at this level so far)\n let position = 0;\n for (const count of siblings.values()) {\n position += count;\n }\n\n // Update sibling count for this tag\n siblings.set(siblingKey, counter + 1);\n\n // Create new node\n const node = {\n tag: tagName,\n position: position,\n counter: counter\n };\n\n if (namespace !== null && namespace !== undefined) {\n node.namespace = namespace;\n }\n\n if (attrValues !== null && attrValues !== undefined) {\n node.values = attrValues;\n }\n\n this.path.push(node);\n }\n\n /**\n * Pop the last tag from the path.\n * @returns {Object|undefined} The popped node\n */\n pop() {\n if (this.path.length === 0) return undefined;\n this._pathStringCache = null;\n\n const node = this.path.pop();\n\n if (this.siblingStacks.length > this.path.length + 1) {\n this.siblingStacks.length = this.path.length + 1;\n }\n\n return node;\n }\n\n /**\n * Update current node's attribute values.\n * Useful when attributes are parsed after push.\n * @param {Object} attrValues\n */\n updateCurrent(attrValues) {\n if (this.path.length > 0) {\n const current = this.path[this.path.length - 1];\n if (attrValues !== null && attrValues !== undefined) {\n current.values = attrValues;\n }\n }\n }\n\n /**\n * Get current tag name.\n * @returns {string|undefined}\n */\n getCurrentTag() {\n return this.path.length > 0 ? this.path[this.path.length - 1].tag : undefined;\n }\n\n /**\n * Get current namespace.\n * @returns {string|undefined}\n */\n getCurrentNamespace() {\n return this.path.length > 0 ? this.path[this.path.length - 1].namespace : undefined;\n }\n\n /**\n * Get current node's attribute value.\n * @param {string} attrName\n * @returns {*}\n */\n getAttrValue(attrName) {\n if (this.path.length === 0) return undefined;\n return this.path[this.path.length - 1].values?.[attrName];\n }\n\n /**\n * Check if current node has an attribute.\n * @param {string} attrName\n * @returns {boolean}\n */\n hasAttr(attrName) {\n if (this.path.length === 0) return false;\n const current = this.path[this.path.length - 1];\n return current.values !== undefined && attrName in current.values;\n }\n\n /**\n * Get current node's sibling position (child index in parent).\n * @returns {number}\n */\n getPosition() {\n if (this.path.length === 0) return -1;\n return this.path[this.path.length - 1].position ?? 0;\n }\n\n /**\n * Get current node's repeat counter (occurrence count of this tag name).\n * @returns {number}\n */\n getCounter() {\n if (this.path.length === 0) return -1;\n return this.path[this.path.length - 1].counter ?? 0;\n }\n\n /**\n * Get current node's sibling index (alias for getPosition).\n * @returns {number}\n * @deprecated Use getPosition() or getCounter() instead\n */\n getIndex() {\n return this.getPosition();\n }\n\n /**\n * Get current path depth.\n * @returns {number}\n */\n getDepth() {\n return this.path.length;\n }\n\n /**\n * Get path as string.\n * @param {string} [separator] - Optional separator (uses default if not provided)\n * @param {boolean} [includeNamespace=true]\n * @returns {string}\n */\n toString(separator, includeNamespace = true) {\n const sep = separator || this.separator;\n const isDefault = (sep === this.separator && includeNamespace === true);\n\n if (isDefault) {\n if (this._pathStringCache !== null) {\n return this._pathStringCache;\n }\n const result = this.path.map(n =>\n (n.namespace) ? `${n.namespace}:${n.tag}` : n.tag\n ).join(sep);\n this._pathStringCache = result;\n return result;\n }\n\n return this.path.map(n =>\n (includeNamespace && n.namespace) ? `${n.namespace}:${n.tag}` : n.tag\n ).join(sep);\n }\n\n /**\n * Get path as array of tag names.\n * @returns {string[]}\n */\n toArray() {\n return this.path.map(n => n.tag);\n }\n\n /**\n * Reset the path to empty.\n */\n reset() {\n this._pathStringCache = null;\n this.path = [];\n this.siblingStacks = [];\n }\n\n /**\n * Match current path against an Expression.\n * @param {Expression} expression\n * @returns {boolean}\n */\n matches(expression) {\n const segments = expression.segments;\n\n if (segments.length === 0) {\n return false;\n }\n\n if (expression.hasDeepWildcard()) {\n return this._matchWithDeepWildcard(segments);\n }\n\n return this._matchSimple(segments);\n }\n\n /**\n * @private\n */\n _matchSimple(segments) {\n if (this.path.length !== segments.length) {\n return false;\n }\n\n for (let i = 0; i < segments.length; i++) {\n if (!this._matchSegment(segments[i], this.path[i], i === this.path.length - 1)) {\n return false;\n }\n }\n\n return true;\n }\n\n /**\n * @private\n */\n _matchWithDeepWildcard(segments) {\n let pathIdx = this.path.length - 1;\n let segIdx = segments.length - 1;\n\n while (segIdx >= 0 && pathIdx >= 0) {\n const segment = segments[segIdx];\n\n if (segment.type === 'deep-wildcard') {\n segIdx--;\n\n if (segIdx < 0) {\n return true;\n }\n\n const nextSeg = segments[segIdx];\n let found = false;\n\n for (let i = pathIdx; i >= 0; i--) {\n if (this._matchSegment(nextSeg, this.path[i], i === this.path.length - 1)) {\n pathIdx = i - 1;\n segIdx--;\n found = true;\n break;\n }\n }\n\n if (!found) {\n return false;\n }\n } else {\n if (!this._matchSegment(segment, this.path[pathIdx], pathIdx === this.path.length - 1)) {\n return false;\n }\n pathIdx--;\n segIdx--;\n }\n }\n\n return segIdx < 0;\n }\n\n /**\n * @private\n */\n _matchSegment(segment, node, isCurrentNode) {\n if (segment.tag !== '*' && segment.tag !== node.tag) {\n return false;\n }\n\n if (segment.namespace !== undefined) {\n if (segment.namespace !== '*' && segment.namespace !== node.namespace) {\n return false;\n }\n }\n\n if (segment.attrName !== undefined) {\n if (!isCurrentNode) {\n return false;\n }\n\n if (!node.values || !(segment.attrName in node.values)) {\n return false;\n }\n\n if (segment.attrValue !== undefined) {\n if (String(node.values[segment.attrName]) !== String(segment.attrValue)) {\n return false;\n }\n }\n }\n\n if (segment.position !== undefined) {\n if (!isCurrentNode) {\n return false;\n }\n\n const counter = node.counter ?? 0;\n\n if (segment.position === 'first' && counter !== 0) {\n return false;\n } else if (segment.position === 'odd' && counter % 2 !== 1) {\n return false;\n } else if (segment.position === 'even' && counter % 2 !== 0) {\n return false;\n } else if (segment.position === 'nth' && counter !== segment.positionValue) {\n return false;\n }\n }\n\n return true;\n }\n\n /**\n * Match any expression in the given set against the current path.\n * @param {ExpressionSet} exprSet\n * @returns {boolean}\n */\n matchesAny(exprSet) {\n return exprSet.matchesAny(this);\n }\n\n /**\n * Create a snapshot of current state.\n * @returns {Object}\n */\n snapshot() {\n return {\n path: this.path.map(node => ({ ...node })),\n siblingStacks: this.siblingStacks.map(map => new Map(map))\n };\n }\n\n /**\n * Restore state from snapshot.\n * @param {Object} snapshot\n */\n restore(snapshot) {\n this._pathStringCache = null;\n this.path = snapshot.path.map(node => ({ ...node }));\n this.siblingStacks = snapshot.siblingStacks.map(map => new Map(map));\n }\n\n /**\n * Return the read-only {@link MatcherView} for this matcher.\n *\n * The same instance is returned on every call — no allocation occurs.\n * It always reflects the current parser state and is safe to pass to\n * user callbacks without risk of accidental mutation.\n *\n * @returns {MatcherView}\n *\n * @example\n * const view = matcher.readOnly();\n * // pass view to callbacks — it stays in sync automatically\n * view.matches(expr); // ✓\n * view.getCurrentTag(); // ✓\n * // view.push(...) // ✗ method does not exist — caught by TypeScript\n */\n readOnly() {\n return this._view;\n }\n}","'use strict';\n///@ts-check\n\nimport { getAllMatches, isExist, DANGEROUS_PROPERTY_NAMES, criticalProperties } from '../util.js';\nimport xmlNode from './xmlNode.js';\nimport DocTypeReader from './DocTypeReader.js';\nimport toNumber from \"strnum\";\nimport getIgnoreAttributesFn from \"../ignoreAttributes.js\";\nimport { Expression, Matcher } from 'path-expression-matcher';\nimport { ExpressionSet } from 'path-expression-matcher';\nimport { EntityDecoder, XML, CURRENCY, COMMON_HTML } from '@nodable/entities';\n\n// const regx =\n// '<((!\\\\[CDATA\\\\[([\\\\s\\\\S]*?)(]]>))|((NAME:)?(NAME))([^>]*)>|((\\\\/)(NAME)\\\\s*>))([^<]*)'\n// .replace(/NAME/g, util.nameRegexp);\n\n//const tagsRegx = new RegExp(\"<(\\\\/?[\\\\w:\\\\-\\._]+)([^>]*)>(\\\\s*\"+cdataRegx+\")*([^<]+)?\",\"g\");\n//const tagsRegx = new RegExp(\"<(\\\\/?)((\\\\w*:)?([\\\\w:\\\\-\\._]+))([^>]*)>([^<]*)(\"+cdataRegx+\"([^<]*))*([^<]+)?\",\"g\");\n\n// Helper functions for attribute and namespace handling\n\n/**\n * Extract raw attributes (without prefix) from prefixed attribute map\n * @param {object} prefixedAttrs - Attributes with prefix from buildAttributesMap\n * @param {object} options - Parser options containing attributeNamePrefix\n * @returns {object} Raw attributes for matcher\n */\nfunction extractRawAttributes(prefixedAttrs, options) {\n if (!prefixedAttrs) return {};\n\n // Handle attributesGroupName option\n const attrs = options.attributesGroupName\n ? prefixedAttrs[options.attributesGroupName]\n : prefixedAttrs;\n\n if (!attrs) return {};\n\n const rawAttrs = {};\n for (const key in attrs) {\n // Remove the attribute prefix to get raw name\n if (key.startsWith(options.attributeNamePrefix)) {\n const rawName = key.substring(options.attributeNamePrefix.length);\n rawAttrs[rawName] = attrs[key];\n } else {\n // Attribute without prefix (shouldn't normally happen, but be safe)\n rawAttrs[key] = attrs[key];\n }\n }\n return rawAttrs;\n}\n\n/**\n * Extract namespace from raw tag name\n * @param {string} rawTagName - Tag name possibly with namespace (e.g., \"soap:Envelope\")\n * @returns {string|undefined} Namespace or undefined\n */\nfunction extractNamespace(rawTagName) {\n if (!rawTagName || typeof rawTagName !== 'string') return undefined;\n\n const colonIndex = rawTagName.indexOf(':');\n if (colonIndex !== -1 && colonIndex > 0) {\n const ns = rawTagName.substring(0, colonIndex);\n // Don't treat xmlns as a namespace\n if (ns !== 'xmlns') {\n return ns;\n }\n }\n return undefined;\n}\n\nexport default class OrderedObjParser {\n constructor(options, externalEntities) {\n this.options = options;\n this.currentNode = null;\n this.tagsNodeStack = [];\n this.parseXml = parseXml;\n this.parseTextData = parseTextData;\n this.resolveNameSpace = resolveNameSpace;\n this.buildAttributesMap = buildAttributesMap;\n this.isItStopNode = isItStopNode;\n this.replaceEntitiesValue = replaceEntitiesValue;\n this.readStopNodeData = readStopNodeData;\n this.saveTextToParentTag = saveTextToParentTag;\n this.addChild = addChild;\n this.ignoreAttributesFn = getIgnoreAttributesFn(this.options.ignoreAttributes)\n this.entityExpansionCount = 0;\n this.currentExpandedLength = 0;\n let namedEntities = { ...XML };\n if (this.options.entityDecoder) {\n this.entityDecoder = this.options.entityDecoder\n } else {\n if (typeof this.options.htmlEntities === \"object\") namedEntities = this.options.htmlEntities;\n else if (this.options.htmlEntities === true) namedEntities = { ...COMMON_HTML, ...CURRENCY };\n this.entityDecoder = new EntityDecoder({\n namedEntities: { ...namedEntities, ...externalEntities },\n numericAllowed: this.options.htmlEntities,\n limit: {\n maxTotalExpansions: this.options.processEntities.maxTotalExpansions,\n maxExpandedLength: this.options.processEntities.maxExpandedLength,\n applyLimitsTo: this.options.processEntities.appliesTo,\n }\n //postCheck: resolved => resolved\n });\n }\n\n // Initialize path matcher for path-expression-matcher\n this.matcher = new Matcher();\n\n // Live read-only proxy of matcher — PEM creates and caches this internally.\n // All user callbacks receive this instead of the mutable matcher.\n this.readonlyMatcher = this.matcher.readOnly();\n\n // Flag to track if current node is a stop node (optimization)\n this.isCurrentNodeStopNode = false;\n\n // Pre-compile stopNodes expressions\n this.stopNodeExpressionsSet = new ExpressionSet();\n const stopNodesOpts = this.options.stopNodes;\n if (stopNodesOpts && stopNodesOpts.length > 0) {\n for (let i = 0; i < stopNodesOpts.length; i++) {\n const stopNodeExp = stopNodesOpts[i];\n if (typeof stopNodeExp === 'string') {\n // Convert string to Expression object\n this.stopNodeExpressionsSet.add(new Expression(stopNodeExp));\n } else if (stopNodeExp instanceof Expression) {\n // Already an Expression object\n this.stopNodeExpressionsSet.add(stopNodeExp);\n }\n }\n this.stopNodeExpressionsSet.seal();\n }\n }\n\n}\n\n\n/**\n * @param {string} val\n * @param {string} tagName\n * @param {string|Matcher} jPath - jPath string or Matcher instance based on options.jPath\n * @param {boolean} dontTrim\n * @param {boolean} hasAttributes\n * @param {boolean} isLeafNode\n * @param {boolean} escapeEntities\n */\nfunction parseTextData(val, tagName, jPath, dontTrim, hasAttributes, isLeafNode, escapeEntities) {\n const options = this.options;\n if (val !== undefined) {\n if (options.trimValues && !dontTrim) {\n val = val.trim();\n }\n if (val.length > 0) {\n if (!escapeEntities) val = this.replaceEntitiesValue(val, tagName, jPath);\n\n // Pass jPath string or matcher based on options.jPath setting\n const jPathOrMatcher = options.jPath ? jPath.toString() : jPath;\n const newval = options.tagValueProcessor(tagName, val, jPathOrMatcher, hasAttributes, isLeafNode);\n if (newval === null || newval === undefined) {\n //don't parse\n return val;\n } else if (typeof newval !== typeof val || newval !== val) {\n //overwrite\n return newval;\n } else if (options.trimValues) {\n return parseValue(val, options.parseTagValue, options.numberParseOptions);\n } else {\n const trimmedVal = val.trim();\n if (trimmedVal === val) {\n return parseValue(val, options.parseTagValue, options.numberParseOptions);\n } else {\n return val;\n }\n }\n }\n }\n}\n\nfunction resolveNameSpace(tagname) {\n if (this.options.removeNSPrefix) {\n const tags = tagname.split(':');\n const prefix = tagname.charAt(0) === '/' ? '/' : '';\n if (tags[0] === 'xmlns') {\n return '';\n }\n if (tags.length === 2) {\n tagname = prefix + tags[1];\n }\n }\n return tagname;\n}\n\n//TODO: change regex to capture NS\n//const attrsRegx = new RegExp(\"([\\\\w\\\\-\\\\.\\\\:]+)\\\\s*=\\\\s*(['\\\"])((.|\\n)*?)\\\\2\",\"gm\");\nconst attrsRegx = new RegExp('([^\\\\s=]+)\\\\s*(=\\\\s*([\\'\"])([\\\\s\\\\S]*?)\\\\3)?', 'gm');\n\nfunction buildAttributesMap(attrStr, jPath, tagName, force = false) {\n const options = this.options;\n if (force === true || (options.ignoreAttributes !== true && typeof attrStr === 'string')) {\n // attrStr = attrStr.replace(/\\r?\\n/g, ' ');\n //attrStr = attrStr || attrStr.trim();\n\n const matches = getAllMatches(attrStr, attrsRegx);\n const len = matches.length; //don't make it inline\n const attrs = {};\n\n // Pre-process values once: trim + entity replacement\n // Reused in both matcher update and second pass\n const processedVals = new Array(len);\n let hasRawAttrs = false;\n const rawAttrsForMatcher = {};\n\n for (let i = 0; i < len; i++) {\n const attrName = this.resolveNameSpace(matches[i][1]);\n const oldVal = matches[i][4];\n\n if (attrName.length && oldVal !== undefined) {\n let val = oldVal;\n if (options.trimValues) val = val.trim();\n val = this.replaceEntitiesValue(val, tagName, this.readonlyMatcher);\n processedVals[i] = val;\n\n rawAttrsForMatcher[attrName] = val;\n hasRawAttrs = true;\n }\n }\n\n // Update matcher ONCE before second pass, if applicable\n if (hasRawAttrs && typeof jPath === 'object' && jPath.updateCurrent) {\n jPath.updateCurrent(rawAttrsForMatcher);\n }\n\n // Hoist toString() once — path doesn't change during attribute processing\n const jPathStr = options.jPath ? jPath.toString() : this.readonlyMatcher;\n\n // Second pass: apply processors, build final attrs\n let hasAttrs = false;\n for (let i = 0; i < len; i++) {\n const attrName = this.resolveNameSpace(matches[i][1]);\n\n if (this.ignoreAttributesFn(attrName, jPathStr)) continue;\n\n let aName = options.attributeNamePrefix + attrName;\n\n if (attrName.length) {\n if (options.transformAttributeName) {\n aName = options.transformAttributeName(aName);\n }\n aName = sanitizeName(aName, options);\n\n if (matches[i][4] !== undefined) {\n // Reuse already-processed value — no double entity replacement\n const oldVal = processedVals[i];\n\n const newVal = options.attributeValueProcessor(attrName, oldVal, jPathStr);\n if (newVal === null || newVal === undefined) {\n attrs[aName] = oldVal;\n } else if (typeof newVal !== typeof oldVal || newVal !== oldVal) {\n attrs[aName] = newVal;\n } else {\n attrs[aName] = parseValue(oldVal, options.parseAttributeValue, options.numberParseOptions);\n }\n hasAttrs = true;\n } else if (options.allowBooleanAttributes) {\n attrs[aName] = true;\n hasAttrs = true;\n }\n }\n }\n\n if (!hasAttrs) return;\n\n if (options.attributesGroupName && !options.preserveOrder) {\n const attrCollection = {};\n attrCollection[options.attributesGroupName] = attrs;\n return attrCollection;\n }\n return attrs;\n }\n}\nconst parseXml = function (xmlData) {\n xmlData = xmlData.replace(/\\r\\n?/g, \"\\n\"); //TODO: remove this line\n const xmlObj = new xmlNode('!xml');\n let currentNode = xmlObj;\n let textData = \"\";\n\n // Reset matcher for new document\n this.matcher.reset();\n this.entityDecoder.reset();\n\n // Reset entity expansion counters for this document\n this.entityExpansionCount = 0;\n this.currentExpandedLength = 0;\n const options = this.options;\n const docTypeReader = new DocTypeReader(options.processEntities);\n const xmlLen = xmlData.length;\n for (let i = 0; i < xmlLen; i++) {//for each char in XML data\n const ch = xmlData[i];\n if (ch === '<') {\n // const nextIndex = i+1;\n // const _2ndChar = xmlData[nextIndex];\n const c1 = xmlData.charCodeAt(i + 1);\n if (c1 === 47) {//Closing Tag '/'\n const closeIndex = findClosingIndex(xmlData, \">\", i, \"Closing Tag is not closed.\")\n let tagName = xmlData.substring(i + 2, closeIndex).trim();\n\n if (options.removeNSPrefix) {\n const colonIndex = tagName.indexOf(\":\");\n if (colonIndex !== -1) {\n tagName = tagName.substr(colonIndex + 1);\n }\n }\n\n tagName = transformTagName(options.transformTagName, tagName, \"\", options).tagName;\n\n if (currentNode) {\n textData = this.saveTextToParentTag(textData, currentNode, this.readonlyMatcher);\n }\n\n //check if last tag of nested tag was unpaired tag\n const lastTagName = this.matcher.getCurrentTag();\n if (tagName && options.unpairedTagsSet.has(tagName)) {\n throw new Error(`Unpaired tag can not be used as closing tag: </${tagName}>`);\n }\n if (lastTagName && options.unpairedTagsSet.has(lastTagName)) {\n // Pop the unpaired tag\n this.matcher.pop();\n this.tagsNodeStack.pop();\n }\n // Pop the closing tag\n this.matcher.pop();\n this.isCurrentNodeStopNode = false; // Reset flag when closing tag\n\n currentNode = this.tagsNodeStack.pop();//avoid recursion, set the parent tag scope\n textData = \"\";\n i = closeIndex;\n } else if (c1 === 63) { //'?'\n\n let tagData = readTagExp(xmlData, i, false, \"?>\");\n if (!tagData) throw new Error(\"Pi Tag is not closed.\");\n\n textData = this.saveTextToParentTag(textData, currentNode, this.readonlyMatcher);\n const attsMap = this.buildAttributesMap(tagData.tagExp, this.matcher, tagData.tagName, true);\n if (attsMap) {\n const ver = attsMap[this.options.attributeNamePrefix + \"version\"];\n this.entityDecoder.setXmlVersion(Number(ver) || 1.0);\n }\n if ((options.ignoreDeclaration && tagData.tagName === \"?xml\") || options.ignorePiTags) {\n //do nothing\n } else {\n\n const childNode = new xmlNode(tagData.tagName);\n childNode.add(options.textNodeName, \"\");\n\n if (tagData.tagName !== tagData.tagExp && tagData.attrExpPresent && options.ignoreAttributes !== true) {\n childNode[\":@\"] = attsMap\n }\n this.addChild(currentNode, childNode, this.readonlyMatcher, i);\n }\n\n\n i = tagData.closeIndex + 1;\n } else if (c1 === 33\n && xmlData.charCodeAt(i + 2) === 45\n && xmlData.charCodeAt(i + 3) === 45) { //'!--'\n const endIndex = findClosingIndex(xmlData, \"-->\", i + 4, \"Comment is not closed.\")\n if (options.commentPropName) {\n const comment = xmlData.substring(i + 4, endIndex - 2);\n\n textData = this.saveTextToParentTag(textData, currentNode, this.readonlyMatcher);\n\n currentNode.add(options.commentPropName, [{ [options.textNodeName]: comment }]);\n }\n i = endIndex;\n } else if (c1 === 33\n && xmlData.charCodeAt(i + 2) === 68) { //'!D'\n const result = docTypeReader.readDocType(xmlData, i);\n this.entityDecoder.addInputEntities(result.entities);\n i = result.i;\n } else if (c1 === 33\n && xmlData.charCodeAt(i + 2) === 91) { // '!['\n const closeIndex = findClosingIndex(xmlData, \"]]>\", i, \"CDATA is not closed.\") - 2;\n const tagExp = xmlData.substring(i + 9, closeIndex);\n\n textData = this.saveTextToParentTag(textData, currentNode, this.readonlyMatcher);\n\n let val = this.parseTextData(tagExp, currentNode.tagname, this.readonlyMatcher, true, false, true, true);\n if (val == undefined) val = \"\";\n\n //cdata should be set even if it is 0 length string\n if (options.cdataPropName) {\n currentNode.add(options.cdataPropName, [{ [options.textNodeName]: tagExp }]);\n } else {\n currentNode.add(options.textNodeName, val);\n }\n\n i = closeIndex + 2;\n } else {//Opening tag\n let result = readTagExp(xmlData, i, options.removeNSPrefix);\n\n // Safety check: readTagExp can return undefined\n if (!result) {\n // Log context for debugging\n const context = xmlData.substring(Math.max(0, i - 50), Math.min(xmlLen, i + 50));\n throw new Error(`readTagExp returned undefined at position ${i}. Context: \"${context}\"`);\n }\n\n let tagName = result.tagName;\n const rawTagName = result.rawTagName;\n let tagExp = result.tagExp;\n let attrExpPresent = result.attrExpPresent;\n let closeIndex = result.closeIndex;\n\n ({ tagName, tagExp } = transformTagName(options.transformTagName, tagName, tagExp, options));\n\n if (options.strictReservedNames &&\n (tagName === options.commentPropName\n || tagName === options.cdataPropName\n || tagName === options.textNodeName\n || tagName === options.attributesGroupName\n )) {\n throw new Error(`Invalid tag name: ${tagName}`);\n }\n\n //save text as child node\n if (currentNode && textData) {\n if (currentNode.tagname !== '!xml') {\n //when nested tag is found\n textData = this.saveTextToParentTag(textData, currentNode, this.readonlyMatcher, false);\n }\n }\n\n //check if last tag was unpaired tag\n const lastTag = currentNode;\n if (lastTag && options.unpairedTagsSet.has(lastTag.tagname)) {\n currentNode = this.tagsNodeStack.pop();\n this.matcher.pop();\n }\n\n // Clean up self-closing syntax BEFORE processing attributes\n // This is where tagExp gets the trailing / removed\n let isSelfClosing = false;\n if (tagExp.length > 0 && tagExp.lastIndexOf(\"/\") === tagExp.length - 1) {\n isSelfClosing = true;\n if (tagName[tagName.length - 1] === \"/\") {\n tagName = tagName.substr(0, tagName.length - 1);\n tagExp = tagName;\n } else {\n tagExp = tagExp.substr(0, tagExp.length - 1);\n }\n\n // Re-check attrExpPresent after cleaning\n attrExpPresent = (tagName !== tagExp);\n }\n\n // Now process attributes with CLEAN tagExp (no trailing /)\n let prefixedAttrs = null;\n let rawAttrs = {};\n let namespace = undefined;\n\n // Extract namespace from rawTagName\n namespace = extractNamespace(rawTagName);\n\n // Push tag to matcher FIRST (with empty attrs for now) so callbacks see correct path\n if (tagName !== xmlObj.tagname) {\n this.matcher.push(tagName, {}, namespace);\n }\n\n // Now build attributes - callbacks will see correct matcher state\n if (tagName !== tagExp && attrExpPresent) {\n // Build attributes (returns prefixed attributes for the tree)\n // Note: buildAttributesMap now internally updates the matcher with raw attributes\n prefixedAttrs = this.buildAttributesMap(tagExp, this.matcher, tagName);\n\n if (prefixedAttrs) {\n // Extract raw attributes (without prefix) for our use\n //TODO: seems a performance overhead\n rawAttrs = extractRawAttributes(prefixedAttrs, options);\n }\n }\n\n // Now check if this is a stop node (after attributes are set)\n if (tagName !== xmlObj.tagname) {\n this.isCurrentNodeStopNode = this.isItStopNode();\n }\n\n const startIndex = i;\n if (this.isCurrentNodeStopNode) {\n let tagContent = \"\";\n\n // For self-closing tags, content is empty\n if (isSelfClosing) {\n i = result.closeIndex;\n }\n //unpaired tag\n else if (options.unpairedTagsSet.has(tagName)) {\n i = result.closeIndex;\n }\n //normal tag\n else {\n //read until closing tag is found\n const result = this.readStopNodeData(xmlData, rawTagName, closeIndex + 1);\n if (!result) throw new Error(`Unexpected end of ${rawTagName}`);\n i = result.i;\n tagContent = result.tagContent;\n }\n\n const childNode = new xmlNode(tagName);\n\n if (prefixedAttrs) {\n childNode[\":@\"] = prefixedAttrs;\n }\n\n // For stop nodes, store raw content as-is without any processing\n childNode.add(options.textNodeName, tagContent);\n\n this.matcher.pop(); // Pop the stop node tag\n this.isCurrentNodeStopNode = false; // Reset flag\n\n this.addChild(currentNode, childNode, this.readonlyMatcher, startIndex);\n } else {\n //selfClosing tag\n if (isSelfClosing) {\n ({ tagName, tagExp } = transformTagName(options.transformTagName, tagName, tagExp, options));\n\n const childNode = new xmlNode(tagName);\n if (prefixedAttrs) {\n childNode[\":@\"] = prefixedAttrs;\n }\n this.addChild(currentNode, childNode, this.readonlyMatcher, startIndex);\n this.matcher.pop(); // Pop self-closing tag\n this.isCurrentNodeStopNode = false; // Reset flag\n }\n else if (options.unpairedTagsSet.has(tagName)) {//unpaired tag\n const childNode = new xmlNode(tagName);\n if (prefixedAttrs) {\n childNode[\":@\"] = prefixedAttrs;\n }\n this.addChild(currentNode, childNode, this.readonlyMatcher, startIndex);\n this.matcher.pop(); // Pop unpaired tag\n this.isCurrentNodeStopNode = false; // Reset flag\n i = result.closeIndex;\n // Continue to next iteration without changing currentNode\n continue;\n }\n //opening tag\n else {\n const childNode = new xmlNode(tagName);\n if (this.tagsNodeStack.length > options.maxNestedTags) {\n throw new Error(\"Maximum nested tags exceeded\");\n }\n this.tagsNodeStack.push(currentNode);\n\n if (prefixedAttrs) {\n childNode[\":@\"] = prefixedAttrs;\n }\n this.addChild(currentNode, childNode, this.readonlyMatcher, startIndex);\n currentNode = childNode;\n }\n textData = \"\";\n i = closeIndex;\n }\n }\n } else {\n textData += xmlData[i];\n }\n }\n return xmlObj.child;\n}\n\nfunction addChild(currentNode, childNode, matcher, startIndex) {\n // unset startIndex if not requested\n if (!this.options.captureMetaData) startIndex = undefined;\n\n // Pass jPath string or matcher based on options.jPath setting\n const jPathOrMatcher = this.options.jPath ? matcher.toString() : matcher;\n const result = this.options.updateTag(childNode.tagname, jPathOrMatcher, childNode[\":@\"])\n if (result === false) {\n //do nothing\n } else if (typeof result === \"string\") {\n childNode.tagname = result\n currentNode.addChild(childNode, startIndex);\n } else {\n currentNode.addChild(childNode, startIndex);\n }\n}\n\n/**\n * @param {object} val - Entity object with regex and val properties\n * @param {string} tagName - Tag name\n * @param {string|Matcher} jPath - jPath string or Matcher instance based on options.jPath\n */\nfunction replaceEntitiesValue(val, tagName, jPath) {\n const entityConfig = this.options.processEntities;\n\n if (!entityConfig || !entityConfig.enabled) {\n return val;\n }\n\n // Check if tag is allowed to contain entities\n if (entityConfig.allowedTags) {\n const jPathOrMatcher = this.options.jPath ? jPath.toString() : jPath;\n const allowed = Array.isArray(entityConfig.allowedTags)\n ? entityConfig.allowedTags.includes(tagName)\n : entityConfig.allowedTags(tagName, jPathOrMatcher);\n\n if (!allowed) {\n return val;\n }\n }\n\n // Apply custom tag filter if provided\n if (entityConfig.tagFilter) {\n const jPathOrMatcher = this.options.jPath ? jPath.toString() : jPath;\n if (!entityConfig.tagFilter(tagName, jPathOrMatcher)) {\n return val; // Skip based on custom filter\n }\n }\n\n return this.entityDecoder.decode(val);\n}\n\n\nfunction saveTextToParentTag(textData, parentNode, matcher, isLeafNode) {\n if (textData) { //store previously collected data as textNode\n if (isLeafNode === undefined) isLeafNode = parentNode.child.length === 0\n\n textData = this.parseTextData(textData,\n parentNode.tagname,\n matcher,\n false,\n parentNode[\":@\"] ? Object.keys(parentNode[\":@\"]).length !== 0 : false,\n isLeafNode);\n\n if (textData !== undefined && textData !== \"\")\n parentNode.add(this.options.textNodeName, textData);\n textData = \"\";\n }\n return textData;\n}\n\n/**\n * @param {Array<Expression>} stopNodeExpressions - Array of compiled Expression objects\n * @param {Matcher} matcher - Current path matcher\n */\nfunction isItStopNode() {\n if (this.stopNodeExpressionsSet.size === 0) return false;\n\n return this.matcher.matchesAny(this.stopNodeExpressionsSet);\n}\n\n/**\n * Returns the tag Expression and where it is ending handling single-double quotes situation\n * @param {string} xmlData \n * @param {number} i starting index\n * @returns \n */\nfunction tagExpWithClosingIndex(xmlData, i, closingChar = \">\") {\n //TODO: ignore boolean attributes in tag expression\n //TODO: if ignore attributes, dont read full attribute expression but the end. But read for xml declaration\n let attrBoundary = 0;\n const len = xmlData.length;\n const closeCode0 = closingChar.charCodeAt(0);\n const closeCode1 = closingChar.length > 1 ? closingChar.charCodeAt(1) : -1;\n\n let result = '';\n let segmentStart = i;\n\n for (let index = i; index < len; index++) {\n const code = xmlData.charCodeAt(index);\n\n if (attrBoundary) {\n if (code === attrBoundary) attrBoundary = 0;\n } else if (code === 34 || code === 39) { // \" or '\n attrBoundary = code;\n } else if (code === closeCode0) {\n if (closeCode1 !== -1) {\n if (xmlData.charCodeAt(index + 1) === closeCode1) {\n result += xmlData.substring(segmentStart, index);\n return { data: result, index };\n }\n } else {\n result += xmlData.substring(segmentStart, index);\n return { data: result, index };\n }\n } else if (code === 9 && !attrBoundary) { // \\t - only replace with space outside attribute values\n // Flush accumulated segment, add space, start new segment\n result += xmlData.substring(segmentStart, index) + ' ';\n segmentStart = index + 1;\n }\n }\n}\n\nfunction findClosingIndex(xmlData, str, i, errMsg) {\n const closingIndex = xmlData.indexOf(str, i);\n if (closingIndex === -1) {\n throw new Error(errMsg)\n } else {\n return closingIndex + str.length - 1;\n }\n}\n\nfunction findClosingChar(xmlData, char, i, errMsg) {\n const closingIndex = xmlData.indexOf(char, i);\n if (closingIndex === -1) throw new Error(errMsg);\n return closingIndex; // no offset needed\n}\n\nfunction readTagExp(xmlData, i, removeNSPrefix, closingChar = \">\") {\n const result = tagExpWithClosingIndex(xmlData, i + 1, closingChar);\n if (!result) return;\n let tagExp = result.data;\n const closeIndex = result.index;\n const separatorIndex = tagExp.search(/\\s/);\n let tagName = tagExp;\n let attrExpPresent = true;\n if (separatorIndex !== -1) {//separate tag name and attributes expression\n tagName = tagExp.substring(0, separatorIndex);\n tagExp = tagExp.substring(separatorIndex + 1).trimStart();\n }\n\n const rawTagName = tagName;\n if (removeNSPrefix) {\n const colonIndex = tagName.indexOf(\":\");\n if (colonIndex !== -1) {\n tagName = tagName.substr(colonIndex + 1);\n attrExpPresent = tagName !== result.data.substr(colonIndex + 1);\n }\n }\n\n return {\n tagName: tagName,\n tagExp: tagExp,\n closeIndex: closeIndex,\n attrExpPresent: attrExpPresent,\n rawTagName: rawTagName,\n }\n}\n/**\n * find paired tag for a stop node\n * @param {string} xmlData \n * @param {string} tagName \n * @param {number} i \n */\nfunction readStopNodeData(xmlData, tagName, i) {\n const startIndex = i;\n // Starting at 1 since we already have an open tag\n let openTagCount = 1;\n\n const xmllen = xmlData.length;\n for (; i < xmllen; i++) {\n if (xmlData[i] === \"<\") {\n const c1 = xmlData.charCodeAt(i + 1);\n if (c1 === 47) {//close tag '/'\n const closeIndex = findClosingChar(xmlData, \">\", i, `${tagName} is not closed`);\n let closeTagName = xmlData.substring(i + 2, closeIndex).trim();\n if (closeTagName === tagName) {\n openTagCount--;\n if (openTagCount === 0) {\n return {\n tagContent: xmlData.substring(startIndex, i),\n i: closeIndex\n }\n }\n }\n i = closeIndex;\n } else if (c1 === 63) { //?\n const closeIndex = findClosingIndex(xmlData, \"?>\", i + 1, \"StopNode is not closed.\")\n i = closeIndex;\n } else if (c1 === 33\n && xmlData.charCodeAt(i + 2) === 45\n && xmlData.charCodeAt(i + 3) === 45) { // '!--'\n const closeIndex = findClosingIndex(xmlData, \"-->\", i + 3, \"StopNode is not closed.\")\n i = closeIndex;\n } else if (c1 === 33\n && xmlData.charCodeAt(i + 2) === 91) { // '!['\n const closeIndex = findClosingIndex(xmlData, \"]]>\", i, \"StopNode is not closed.\") - 2;\n i = closeIndex;\n } else {\n const tagData = readTagExp(xmlData, i, '>')\n\n if (tagData) {\n const openTagName = tagData && tagData.tagName;\n if (openTagName === tagName && tagData.tagExp[tagData.tagExp.length - 1] !== \"/\") {\n openTagCount++;\n }\n i = tagData.closeIndex;\n }\n }\n }\n }//end for loop\n}\n\nfunction parseValue(val, shouldParse, options) {\n if (shouldParse && typeof val === 'string') {\n //console.log(options)\n const newval = val.trim();\n if (newval === 'true') return true;\n else if (newval === 'false') return false;\n else return toNumber(val, options);\n } else {\n if (isExist(val)) {\n return val;\n } else {\n return '';\n }\n }\n}\n\nfunction fromCodePoint(str, base, prefix) {\n const codePoint = Number.parseInt(str, base);\n\n if (codePoint >= 0 && codePoint <= 0x10FFFF) {\n return String.fromCodePoint(codePoint);\n } else {\n return prefix + str + \";\";\n }\n}\n\nfunction transformTagName(fn, tagName, tagExp, options) {\n if (fn) {\n const newTagName = fn(tagName);\n if (tagExp === tagName) {\n tagExp = newTagName\n }\n tagName = newTagName;\n }\n tagName = sanitizeName(tagName, options);\n return { tagName, tagExp };\n}\n\n\n\nfunction sanitizeName(name, options) {\n if (criticalProperties.includes(name)) {\n throw new Error(`[SECURITY] Invalid name: \"${name}\" is a reserved JavaScript keyword that could cause prototype pollution`);\n } else if (DANGEROUS_PROPERTY_NAMES.includes(name)) {\n return options.onDangerousProperty(name);\n }\n return name;\n}","'use strict';\n\nimport XmlNode from './xmlNode.js';\nimport { Matcher } from 'path-expression-matcher';\n\nconst METADATA_SYMBOL = XmlNode.getMetaDataSymbol();\n\n/**\n * Helper function to strip attribute prefix from attribute map\n * @param {object} attrs - Attributes with prefix (e.g., {\"@_class\": \"code\"})\n * @param {string} prefix - Attribute prefix to remove (e.g., \"@_\")\n * @returns {object} Attributes without prefix (e.g., {\"class\": \"code\"})\n */\nfunction stripAttributePrefix(attrs, prefix) {\n if (!attrs || typeof attrs !== 'object') return {};\n if (!prefix) return attrs;\n\n const rawAttrs = {};\n for (const key in attrs) {\n if (key.startsWith(prefix)) {\n const rawName = key.substring(prefix.length);\n rawAttrs[rawName] = attrs[key];\n } else {\n // Attribute without prefix (shouldn't normally happen, but be safe)\n rawAttrs[key] = attrs[key];\n }\n }\n return rawAttrs;\n}\n\n/**\n * \n * @param {array} node \n * @param {any} options \n * @param {Matcher} matcher - Path matcher instance\n * @returns \n */\nexport default function prettify(node, options, matcher, readonlyMatcher) {\n return compress(node, options, matcher, readonlyMatcher);\n}\n\n/**\n * @param {array} arr \n * @param {object} options \n * @param {Matcher} matcher - Path matcher instance\n * @returns object\n */\nfunction compress(arr, options, matcher, readonlyMatcher) {\n let text;\n const compressedObj = {}; //This is intended to be a plain object\n for (let i = 0; i < arr.length; i++) {\n const tagObj = arr[i];\n const property = propName(tagObj);\n\n // Push current property to matcher WITH RAW ATTRIBUTES (no prefix)\n if (property !== undefined && property !== options.textNodeName) {\n const rawAttrs = stripAttributePrefix(\n tagObj[\":@\"] || {},\n options.attributeNamePrefix\n );\n matcher.push(property, rawAttrs);\n }\n\n if (property === options.textNodeName) {\n if (text === undefined) text = tagObj[property];\n else text += \"\" + tagObj[property];\n } else if (property === undefined) {\n continue;\n } else if (tagObj[property]) {\n\n let val = compress(tagObj[property], options, matcher, readonlyMatcher);\n const isLeaf = isLeafTag(val, options);\n\n if (tagObj[\":@\"]) {\n assignAttributes(val, tagObj[\":@\"], readonlyMatcher, options);\n } else if (Object.keys(val).length === 1 && val[options.textNodeName] !== undefined && !options.alwaysCreateTextNode) {\n val = val[options.textNodeName];\n } else if (Object.keys(val).length === 0) {\n if (options.alwaysCreateTextNode) val[options.textNodeName] = \"\";\n else val = \"\";\n }\n\n if (tagObj[METADATA_SYMBOL] !== undefined && typeof val === \"object\" && val !== null) {\n val[METADATA_SYMBOL] = tagObj[METADATA_SYMBOL]; // copy over metadata\n }\n\n\n if (compressedObj[property] !== undefined && Object.prototype.hasOwnProperty.call(compressedObj, property)) {\n if (!Array.isArray(compressedObj[property])) {\n compressedObj[property] = [compressedObj[property]];\n }\n compressedObj[property].push(val);\n } else {\n //TODO: if a node is not an array, then check if it should be an array\n //also determine if it is a leaf node\n\n // Pass jPath string or readonlyMatcher based on options.jPath setting\n const jPathOrMatcher = options.jPath ? readonlyMatcher.toString() : readonlyMatcher;\n if (options.isArray(property, jPathOrMatcher, isLeaf)) {\n compressedObj[property] = [val];\n } else {\n compressedObj[property] = val;\n }\n }\n\n // Pop property from matcher after processing\n if (property !== undefined && property !== options.textNodeName) {\n matcher.pop();\n }\n }\n\n }\n // if(text && text.length > 0) compressedObj[options.textNodeName] = text;\n if (typeof text === \"string\") {\n if (text.length > 0) compressedObj[options.textNodeName] = text;\n } else if (text !== undefined) compressedObj[options.textNodeName] = text;\n\n\n return compressedObj;\n}\n\nfunction propName(obj) {\n const keys = Object.keys(obj);\n for (let i = 0; i < keys.length; i++) {\n const key = keys[i];\n if (key !== \":@\") return key;\n }\n}\n\nfunction assignAttributes(obj, attrMap, readonlyMatcher, options) {\n if (attrMap) {\n const keys = Object.keys(attrMap);\n const len = keys.length; //don't make it inline\n for (let i = 0; i < len; i++) {\n const atrrName = keys[i]; // This is the PREFIXED name (e.g., \"@_class\")\n\n // Strip prefix for matcher path (for isArray callback)\n const rawAttrName = atrrName.startsWith(options.attributeNamePrefix)\n ? atrrName.substring(options.attributeNamePrefix.length)\n : atrrName;\n\n // For attributes, we need to create a temporary path\n // Pass jPath string or matcher based on options.jPath setting\n const jPathOrMatcher = options.jPath\n ? readonlyMatcher.toString() + \".\" + rawAttrName\n : readonlyMatcher;\n\n if (options.isArray(atrrName, jPathOrMatcher, true, true)) {\n obj[atrrName] = [attrMap[atrrName]];\n } else {\n obj[atrrName] = attrMap[atrrName];\n }\n }\n }\n}\n\nfunction isLeafTag(obj, options) {\n const { textNodeName } = options;\n const propCount = Object.keys(obj).length;\n\n if (propCount === 0) {\n return true;\n }\n\n if (\n propCount === 1 &&\n (obj[textNodeName] || typeof obj[textNodeName] === \"boolean\" || obj[textNodeName] === 0)\n ) {\n return true;\n }\n\n return false;\n}","import { buildOptions } from './OptionsBuilder.js';\nimport OrderedObjParser from './OrderedObjParser.js';\nimport prettify from './node2json.js';\nimport { validate } from \"../validator.js\";\nimport XmlNode from './xmlNode.js';\n\nexport default class XMLParser {\n\n constructor(options) {\n this.externalEntities = {};\n this.options = buildOptions(options);\n\n }\n /**\n * Parse XML dats to JS object \n * @param {string|Uint8Array} xmlData \n * @param {boolean|Object} validationOption \n */\n parse(xmlData, validationOption) {\n if (typeof xmlData !== \"string\" && xmlData.toString) {\n xmlData = xmlData.toString();\n } else if (typeof xmlData !== \"string\") {\n throw new Error(\"XML data is accepted in String or Bytes[] form.\")\n }\n\n if (validationOption) {\n if (validationOption === true) validationOption = {}; //validate with default options\n\n const result = validate(xmlData, validationOption);\n if (result !== true) {\n throw Error(`${result.err.msg}:${result.err.line}:${result.err.col}`)\n }\n }\n const orderedObjParser = new OrderedObjParser(this.options, this.externalEntities);\n // orderedObjParser.entityDecoder.setExternalEntities(this.externalEntities);\n const orderedResult = orderedObjParser.parseXml(xmlData);\n if (this.options.preserveOrder || orderedResult === undefined) return orderedResult;\n else return prettify(orderedResult, this.options, orderedObjParser.matcher, orderedObjParser.readonlyMatcher);\n }\n\n /**\n * Add Entity which is not by default supported by this library\n * @param {string} key \n * @param {string} value \n */\n addEntity(key, value) {\n if (value.indexOf(\"&\") !== -1) {\n throw new Error(\"Entity value can't have '&'\")\n } else if (key.indexOf(\"&\") !== -1 || key.indexOf(\";\") !== -1) {\n throw new Error(\"An entity must be set without '&' and ';'. Eg. use '#xD' for '
'\")\n } else if (value === \"&\") {\n throw new Error(\"An entity with value '&' is not permitted\");\n } else {\n this.externalEntities[key] = value;\n }\n }\n\n /**\n * Returns a Symbol that can be used to access the metadata\n * property on a node.\n * \n * If Symbol is not available in the environment, an ordinary property is used\n * and the name of the property is here returned.\n * \n * The XMLMetaData property is only present when `captureMetaData`\n * is true in the options.\n */\n static getMetaDataSymbol() {\n return XmlNode.getMetaDataSymbol();\n }\n}","import { XMLParser } from 'fast-xml-parser';\n\nexport type ContentFeedFormat = 'rss' | 'atom';\n\nexport interface ParsedContentFeedItem {\n title: string;\n url: string;\n guid: string | null;\n author: string | null;\n publishedAt: Date | null;\n updatedAt: Date | null;\n summary: string | null;\n categories: string[];\n}\n\nexport interface ParsedContentFeed {\n format: ContentFeedFormat;\n title: string | null;\n homepageUrl: string | null;\n items: ParsedContentFeedItem[];\n}\n\nfunction asArray<T>(value: T | T[] | null | undefined): T[] {\n if (value === null || value === undefined) return [];\n return Array.isArray(value) ? value : [value];\n}\n\nfunction textFromNode(value: unknown): string {\n if (value === null || value === undefined) return '';\n if (typeof value === 'string' || typeof value === 'number') {\n return String(value).trim();\n }\n if (typeof value !== 'object') return '';\n\n const record = value as Record<string, unknown>;\n return String(record['#text'] ?? record.__cdata ?? record.href ?? '').trim();\n}\n\nfunction firstText(...values: unknown[]): string {\n for (const value of values) {\n const text = textFromNode(value);\n if (text) return text;\n }\n return '';\n}\n\nfunction parseDate(value: unknown): Date | null {\n const text = textFromNode(value);\n if (!text) return null;\n const parsed = new Date(text);\n return Number.isNaN(parsed.getTime()) ? null : parsed;\n}\n\nfunction stripHtml(value: string): string {\n return value\n .replace(/<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi, '')\n .replace(/<style\\b[^<]*(?:(?!<\\/style>)<[^<]*)*<\\/style>/gi, '')\n .replace(/<[^>]+>/g, ' ')\n .replace(/ /g, ' ')\n .replace(/&/g, '&')\n .replace(/"/g, '\"')\n .replace(/'/g, \"'\")\n .replace(/'/g, \"'\")\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\\s+/g, ' ')\n .trim();\n}\n\nfunction excerpt(value: unknown): string | null {\n const text = stripHtml(textFromNode(value));\n if (!text) return null;\n return text.length > 500 ? `${text.slice(0, 497).trim()}...` : text;\n}\n\nfunction parseCategories(value: unknown): string[] {\n return Array.from(\n new Set(\n asArray(value)\n .map((entry) => {\n if (entry && typeof entry === 'object') {\n return firstText(entry, (entry as Record<string, unknown>).term);\n }\n return textFromNode(entry);\n })\n .map((entry) => entry.trim())\n .filter(Boolean),\n ),\n );\n}\n\nfunction parseAuthor(value: unknown): string | null {\n if (Array.isArray(value)) return parseAuthor(value[0]);\n if (value && typeof value === 'object') {\n return firstText((value as Record<string, unknown>).name, value) || null;\n }\n return textFromNode(value) || null;\n}\n\nfunction resolveUrl(value: string, baseUrl?: string | null): string {\n if (!value) return '';\n if (!baseUrl) return value;\n\n try {\n return new URL(value, baseUrl).toString();\n } catch {\n return value;\n }\n}\n\nfunction parseRssLink(value: unknown, baseUrl?: string | null): string {\n if (value && typeof value === 'object') {\n const record = value as Record<string, unknown>;\n return resolveUrl(\n firstText(record.href, record['#text'], record.__cdata),\n baseUrl,\n );\n }\n return resolveUrl(textFromNode(value), baseUrl);\n}\n\nfunction parseAtomLink(value: unknown, baseUrl?: string | null): string {\n const links = asArray(value);\n const alternate =\n links.find((entry) => {\n if (!entry || typeof entry !== 'object') return false;\n return (\n String((entry as Record<string, unknown>).rel ?? 'alternate') ===\n 'alternate'\n );\n }) ?? links[0];\n\n if (alternate && typeof alternate === 'object') {\n return resolveUrl(\n firstText((alternate as Record<string, unknown>).href, alternate),\n baseUrl,\n );\n }\n return resolveUrl(textFromNode(alternate), baseUrl);\n}\n\nfunction dedupeItems(items: ParsedContentFeedItem[]): ParsedContentFeedItem[] {\n const seen = new Set<string>();\n return items.filter((item) => {\n const key = item.guid || item.url;\n if (seen.has(key)) return false;\n seen.add(key);\n return true;\n });\n}\n\nexport function parseContentFeed(\n xml: string,\n baseUrl?: string | null,\n): ParsedContentFeed {\n const parser = new XMLParser({\n ignoreAttributes: false,\n attributeNamePrefix: '',\n cdataPropName: '__cdata',\n textNodeName: '#text',\n removeNSPrefix: true,\n trimValues: true,\n });\n // Parsed XML is an untyped node tree; every field is read through the\n // unknown-tolerant helpers above, so a loose record shape is sufficient.\n type FeedNode = Record<string, unknown>;\n const doc = parser.parse(xml) as {\n rss?: { channel?: FeedNode };\n channel?: FeedNode;\n feed?: FeedNode;\n };\n\n if (doc.rss?.channel || doc.channel) {\n const channel = (doc.rss?.channel ?? doc.channel) as FeedNode;\n return {\n format: 'rss',\n title: firstText(channel.title) || null,\n homepageUrl: parseRssLink(channel.link, baseUrl) || null,\n items: dedupeItems(\n asArray<FeedNode>(channel.item as FeedNode | FeedNode[] | undefined)\n .map(\n (item): ParsedContentFeedItem => ({\n title: firstText(item.title),\n url:\n parseRssLink(item.link, baseUrl) ||\n resolveUrl(firstText(item.guid), baseUrl),\n guid: firstText(item.guid, item.id) || null,\n author: parseAuthor(item.author ?? item.creator),\n publishedAt: parseDate(\n item.pubDate ?? item.published ?? item.date,\n ),\n updatedAt: parseDate(item.updated),\n summary: excerpt(\n item.description ?? item.summary ?? item.content,\n ),\n categories: parseCategories(item.category),\n }),\n )\n .filter((item) => item.title && item.url),\n ),\n };\n }\n\n if (doc.feed) {\n const feed = doc.feed;\n return {\n format: 'atom',\n title: firstText(feed.title) || null,\n homepageUrl: parseAtomLink(feed.link, baseUrl) || null,\n items: dedupeItems(\n asArray<FeedNode>(feed.entry as FeedNode | FeedNode[] | undefined)\n .map(\n (entry): ParsedContentFeedItem => ({\n title: firstText(entry.title),\n url: parseAtomLink(entry.link, baseUrl),\n guid: firstText(entry.id) || null,\n author: parseAuthor(entry.author),\n publishedAt: parseDate(entry.published ?? entry.updated),\n updatedAt: parseDate(entry.updated),\n summary: excerpt(entry.summary ?? entry.content),\n categories: parseCategories(entry.category),\n }),\n )\n .filter((item) => item.title && item.url),\n ),\n };\n }\n\n throw new Error('Unsupported feed format');\n}\n","import type { SmrtObjectOptions } from '@happyvertical/smrt-core';\nimport { field, SmrtObject, smrt } from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport type { ContentFeedFormat } from './content-feed-parser';\n\nexport type ContentFeedSourceStatus =\n | 'active'\n | 'paused'\n | 'error'\n | 'archived';\n\nexport interface ContentFeedSourceOptions extends SmrtObjectOptions {\n tenantId?: string | null;\n name?: string;\n feedUrl?: string;\n homepageUrl?: string | null;\n format?: ContentFeedFormat | null;\n status?: ContentFeedSourceStatus;\n defaultCategory?: string | null;\n sourceGroup?: string | null;\n pollIntervalMinutes?: number;\n etag?: string | null;\n lastModified?: string | null;\n lastFetchedAt?: Date | string | null;\n lastSuccessAt?: Date | string | null;\n lastError?: string | null;\n metadata?: Record<string, unknown> | string;\n createdAt?: Date | string;\n updatedAt?: Date | string;\n}\n\nconst SOURCE_STATUSES = new Set<ContentFeedSourceStatus>([\n 'active',\n 'paused',\n 'error',\n 'archived',\n]);\n\nfunction parseDate(value: Date | string | null | undefined): Date | null {\n if (!value) return null;\n if (value instanceof Date) return value;\n const parsed = new Date(value);\n return Number.isNaN(parsed.getTime()) ? null : parsed;\n}\n\nfunction parseMetadata(\n value: Record<string, unknown> | string | undefined,\n): Record<string, unknown> {\n if (!value) return {};\n if (typeof value === 'object') return structuredClone(value);\n\n try {\n const parsed = JSON.parse(value);\n return parsed && typeof parsed === 'object' ? parsed : {};\n } catch {\n return {};\n }\n}\n\nfunction normalizePollIntervalMinutes(value: unknown): number {\n const parsed = Number(value);\n return Number.isFinite(parsed) && parsed > 0 ? Math.floor(parsed) : 15;\n}\n\nfunction normalizeStatus(value: unknown): ContentFeedSourceStatus {\n return typeof value === 'string' &&\n SOURCE_STATUSES.has(value as ContentFeedSourceStatus)\n ? (value as ContentFeedSourceStatus)\n : 'active';\n}\n\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableName: 'content_feed_sources',\n conflictColumns: ['tenant_id', 'feed_url'],\n api: { include: ['list', 'get', 'create', 'update', 'delete'] },\n mcp: { include: ['list', 'get', 'create', 'update', 'delete'] },\n cli: true,\n})\nexport class ContentFeedSource extends SmrtObject {\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n @field({ required: true })\n name = '';\n\n @field({ required: true })\n feedUrl = '';\n\n homepageUrl: string | null = null;\n format: ContentFeedFormat | null = null;\n @field({ type: 'text', required: true, default: 'active' })\n status: ContentFeedSourceStatus = 'active';\n defaultCategory: string | null = null;\n sourceGroup: string | null = null;\n pollIntervalMinutes = 15;\n etag: string | null = null;\n lastModified: string | null = null;\n lastFetchedAt: Date | null = null;\n lastSuccessAt: Date | null = null;\n lastError: string | null = null;\n metadata: Record<string, unknown> = {};\n createdAt = new Date();\n updatedAt = new Date();\n\n constructor(options: ContentFeedSourceOptions = {}) {\n super(options);\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n if (options.name !== undefined) this.name = options.name;\n if (options.feedUrl !== undefined) this.feedUrl = options.feedUrl;\n if (options.homepageUrl !== undefined)\n this.homepageUrl = options.homepageUrl;\n if (options.format !== undefined) this.format = options.format;\n if (options.status !== undefined)\n this.status = normalizeStatus(options.status);\n if (options.defaultCategory !== undefined)\n this.defaultCategory = options.defaultCategory;\n if (options.sourceGroup !== undefined)\n this.sourceGroup = options.sourceGroup;\n if (options.pollIntervalMinutes !== undefined) {\n this.pollIntervalMinutes = normalizePollIntervalMinutes(\n options.pollIntervalMinutes,\n );\n }\n if (options.etag !== undefined) this.etag = options.etag;\n if (options.lastModified !== undefined)\n this.lastModified = options.lastModified;\n if (options.lastFetchedAt !== undefined)\n this.lastFetchedAt = parseDate(options.lastFetchedAt);\n if (options.lastSuccessAt !== undefined)\n this.lastSuccessAt = parseDate(options.lastSuccessAt);\n if (options.lastError !== undefined) this.lastError = options.lastError;\n if (options.metadata !== undefined)\n this.metadata = parseMetadata(options.metadata);\n if (options.createdAt !== undefined)\n this.createdAt = parseDate(options.createdAt) ?? new Date();\n if (options.updatedAt !== undefined)\n this.updatedAt = parseDate(options.updatedAt) ?? new Date();\n }\n\n getMetadata(): Record<string, unknown> {\n return structuredClone(this.metadata);\n }\n\n setMetadata(metadata: Record<string, unknown>): void {\n this.metadata = structuredClone(metadata);\n this.updatedAt = new Date();\n }\n\n markFetchStarted(at = new Date()): void {\n this.lastFetchedAt = at;\n this.updatedAt = at;\n }\n\n markFetchSucceeded(\n at = new Date(),\n headers: { etag?: string | null; lastModified?: string | null } = {},\n ): void {\n this.status = 'active';\n this.lastFetchedAt = at;\n this.lastSuccessAt = at;\n this.lastError = null;\n if (headers.etag !== undefined) this.etag = headers.etag;\n if (headers.lastModified !== undefined)\n this.lastModified = headers.lastModified;\n this.updatedAt = at;\n }\n\n markFetchFailed(error: unknown, at = new Date()): void {\n this.status = 'error';\n this.lastFetchedAt = at;\n this.lastError = error instanceof Error ? error.message : String(error);\n this.updatedAt = at;\n }\n\n protected override transformJSON(\n json: Record<string, unknown>,\n ): Record<string, unknown> {\n return {\n ...json,\n tenantId: this.tenantId,\n name: this.name,\n feedUrl: this.feedUrl,\n homepageUrl: this.homepageUrl,\n format: this.format,\n status: this.status,\n defaultCategory: this.defaultCategory,\n sourceGroup: this.sourceGroup,\n pollIntervalMinutes: this.pollIntervalMinutes,\n etag: this.etag,\n lastModified: this.lastModified,\n lastFetchedAt: this.lastFetchedAt?.toISOString() ?? null,\n lastSuccessAt: this.lastSuccessAt?.toISOString() ?? null,\n lastError: this.lastError,\n metadata: this.metadata,\n createdAt: this.createdAt.toISOString(),\n updatedAt: this.updatedAt.toISOString(),\n };\n }\n}\n","import type { SmrtCollectionOptions } from '@happyvertical/smrt-core';\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport {\n ContentFeedSource,\n type ContentFeedSourceStatus,\n} from './content-feed-source';\n\nexport interface ContentFeedSourceCollectionOptions\n extends SmrtCollectionOptions {}\n\nexport class ContentFeedSourceCollection extends SmrtCollection<ContentFeedSource> {\n static readonly _itemClass = ContentFeedSource;\n\n async findActive(tenantId?: string | null): Promise<ContentFeedSource[]> {\n const where: Record<string, unknown> = { status: 'active' };\n if (tenantId !== undefined) where.tenantId = tenantId;\n return this.list({ where, orderBy: 'name ASC' });\n }\n\n async findByStatus(\n status: ContentFeedSourceStatus,\n tenantId?: string | null,\n ): Promise<ContentFeedSource[]> {\n const where: Record<string, unknown> = { status };\n if (tenantId !== undefined) where.tenantId = tenantId;\n return this.list({ where, orderBy: 'name ASC' });\n }\n\n async findByFeedUrl(\n feedUrl: string,\n tenantId?: string | null,\n ): Promise<ContentFeedSource | null> {\n const where: Record<string, unknown> = { feedUrl };\n if (tenantId !== undefined) where.tenantId = tenantId;\n const rows = await this.list({ where, limit: 1 });\n return rows[0] ?? null;\n }\n}\n","/**\n * Content subclasses for STI (Single Table Inheritance)\n *\n * These classes inherit from Content and automatically use the shared\n * contents table with _meta_type discriminator.\n */\n\nimport { foreignKey, smrt } from '@happyvertical/smrt-core';\nimport { Content, type ContentOptions } from './content';\n\n/**\n * Article content type\n *\n * Represents editorial content like blog posts, news articles, and written pieces.\n */\n@smrt({\n tableStrategy: 'sti',\n api: false,\n mcp: false,\n cli: false,\n})\nexport class Article extends Content {\n constructor(options: ContentOptions = {}) {\n super(options);\n // Article-specific initialization can go here\n }\n}\n\n/**\n * ContentDocument content type\n *\n * Represents structured documents like PDFs, reports, and technical documentation.\n */\n@smrt({\n tableStrategy: 'sti',\n api: false,\n mcp: false,\n cli: false,\n})\nexport class ContentDocument extends Content {\n constructor(options: ContentOptions = {}) {\n super(options);\n // ContentDocument-specific initialization can go here\n }\n}\n\nexport interface MirrorOptions extends ContentOptions {\n feedSourceId?: string | null;\n sourceGuid?: string | null;\n sourceName?: string | null;\n sourceHomepageUrl?: string | null;\n externalUrl?: string | null;\n originalPublishedAt?: Date | string | null;\n dedupeKey?: string | null;\n}\n\nfunction parseOptionalDate(\n value: Date | string | null | undefined,\n): Date | null {\n if (!value) return null;\n if (value instanceof Date) return value;\n const parsed = new Date(value);\n return Number.isNaN(parsed.getTime()) ? null : parsed;\n}\n\n/**\n * Mirror content type\n *\n * Represents mirrored/cached content from external feed or web sources.\n */\n@smrt({\n tableStrategy: 'sti',\n api: false,\n mcp: false,\n cli: false,\n})\nexport class Mirror extends Content {\n @foreignKey('ContentFeedSource')\n feedSourceId: string | null = null;\n sourceGuid: string | null = null;\n sourceName: string | null = null;\n sourceHomepageUrl: string | null = null;\n externalUrl: string | null = null;\n originalPublishedAt: Date | null = null;\n dedupeKey: string | null = null;\n\n constructor(options: MirrorOptions = {}) {\n super(options);\n if (options.feedSourceId !== undefined)\n this.feedSourceId = options.feedSourceId;\n if (options.sourceGuid !== undefined) this.sourceGuid = options.sourceGuid;\n if (options.sourceName !== undefined) this.sourceName = options.sourceName;\n if (options.sourceHomepageUrl !== undefined)\n this.sourceHomepageUrl = options.sourceHomepageUrl;\n if (options.externalUrl !== undefined)\n this.externalUrl = options.externalUrl;\n if (options.originalPublishedAt !== undefined) {\n this.originalPublishedAt = parseOptionalDate(options.originalPublishedAt);\n }\n if (options.dedupeKey !== undefined) this.dedupeKey = options.dedupeKey;\n }\n\n protected override transformJSON(json: Record<string, unknown>) {\n return {\n ...json,\n feedSourceId: this.feedSourceId,\n sourceGuid: this.sourceGuid,\n sourceName: this.sourceName,\n sourceHomepageUrl: this.sourceHomepageUrl,\n externalUrl: this.externalUrl,\n originalPublishedAt: this.originalPublishedAt?.toISOString() ?? null,\n dedupeKey: this.dedupeKey,\n };\n }\n}\n","/**\n * Shared SSRF guard for content's outbound fetches (feed sync, mirroring).\n *\n * Any code path that fetches a caller-supplied URL — RSS/Atom feeds, the\n * `Mirror` content type, link previews — is an SSRF vector: an attacker who can\n * influence the URL can make the server fetch `169.254.169.254` cloud metadata,\n * `localhost` admin panels, or other internal services. This module rejects\n * URLs that resolve to private, loopback, link-local, CGNAT, or cloud-metadata\n * ranges before any request is made, and re-validates redirect hops.\n *\n * Unlike a literal-IP-only check, {@link assertSafeRemoteUrl} resolves hostnames\n * via DNS so a public name pointing at a private IP is also caught (S5 #1388).\n */\nimport { lookup as dnsLookup } from 'node:dns/promises';\nimport { isIP } from 'node:net';\n\nexport type ResolvedAddress = { address: string; family?: number };\nexport type ResolveHostname = (hostname: string) => Promise<ResolvedAddress[]>;\n\nexport interface SafeRemoteUrlOptions {\n /** Skip the private-network checks (trusted callers only, e.g. local dev). */\n allowPrivateNetworkHosts?: boolean;\n /** Injectable resolver for tests; defaults to {@link defaultResolveHostname}. */\n resolveHostname?: ResolveHostname;\n}\n\nexport async function defaultResolveHostname(\n hostname: string,\n): Promise<ResolvedAddress[]> {\n return dnsLookup(hostname, { all: true, verbatim: false });\n}\n\nexport function isBlockedIPv4(address: string): boolean {\n const parts = address.split('.');\n if (parts.length !== 4) return true;\n // Strict per-octet validation: `Number('')` is 0, so without a digit check a\n // malformed input like `1..2.3` would parse to `[1,0,2,3]` and be treated as a\n // valid (and possibly allowed) address. Anything not 1-3 digits in 0-255 is\n // unparseable → blocked (review #1562).\n const octets = parts.map((part) =>\n /^\\d{1,3}$/.test(part) ? Number(part) : Number.NaN,\n );\n if (octets.some((n) => !Number.isInteger(n) || n < 0 || n > 255)) {\n return true;\n }\n\n const [first, second] = octets;\n return (\n first === 0 ||\n first === 10 ||\n first === 127 ||\n first >= 224 ||\n (first === 100 && second >= 64 && second <= 127) ||\n (first === 169 && second === 254) ||\n (first === 172 && second >= 16 && second <= 31) ||\n (first === 192 && second === 168) ||\n (first === 198 && (second === 18 || second === 19))\n );\n}\n\n/**\n * Expand an IPv6 string to its 8 hextets (numbers), or null if unparseable.\n * Handles `::` compression, an embedded dotted-IPv4 tail, and bracketed forms.\n */\nfunction expandIPv6(address: string): number[] | null {\n let work = address.toLowerCase().replace(/^\\[|\\]$/g, '');\n if (work.includes('.')) {\n // Embedded dotted IPv4 tail (e.g. ::ffff:127.0.0.1) → convert to 2 hextets.\n const m = work.match(/(\\d{1,3}(?:\\.\\d{1,3}){3})$/);\n if (!m) return null;\n const o = m[1].split('.').map(Number);\n if (o.some((n) => !Number.isInteger(n) || n < 0 || n > 255)) return null;\n const hi = ((o[0] << 8) | o[1]).toString(16);\n const lo = ((o[2] << 8) | o[3]).toString(16);\n work = `${work.slice(0, work.length - m[1].length)}${hi}:${lo}`;\n }\n const halves = work.split('::');\n if (halves.length > 2) return null;\n const head = halves[0] ? halves[0].split(':') : [];\n const tail = halves.length === 2 && halves[1] ? halves[1].split(':') : [];\n const groups =\n halves.length === 2\n ? [\n ...head,\n ...Array(Math.max(0, 8 - head.length - tail.length)).fill('0'),\n ...tail,\n ]\n : head;\n if (groups.length !== 8) return null;\n const hextets = groups.map((g) =>\n /^[0-9a-f]{1,4}$/.test(g) ? Number.parseInt(g, 16) : Number.NaN,\n );\n return hextets.some((n) => Number.isNaN(n)) ? null : hextets;\n}\n\nexport function isBlockedIPv6(address: string): boolean {\n const hextets = expandIPv6(address);\n if (hextets) {\n // IPv4-mapped (::ffff:a.b.c.d) and IPv4-compatible (::a.b.c.d, deprecated)\n // both embed an IPv4 in the last 2 hextets — decode and apply the IPv4\n // blocklist so a loopback/private IPv4 can't be smuggled through any IPv6\n // encoding (compressed, expanded, dotted, or hex) (review #1562, P1).\n const firstFiveZero = hextets.slice(0, 5).every((h) => h === 0);\n if (firstFiveZero && (hextets[5] === 0xffff || hextets[5] === 0)) {\n const [, , , , , , g6, g7] = hextets;\n const ipv4 = `${g6 >> 8}.${g6 & 0xff}.${g7 >> 8}.${g7 & 0xff}`;\n return isBlockedIPv4(ipv4);\n }\n }\n\n const normalized = address.toLowerCase().replace(/^\\[|\\]$/g, '');\n return (\n normalized === '::' ||\n normalized === '::1' ||\n normalized.startsWith('fc') ||\n normalized.startsWith('fd') ||\n /^fe[89ab]/.test(normalized) ||\n normalized.startsWith('ff')\n );\n}\n\nexport function isBlockedAddress(address: string): boolean {\n const family = isIP(address);\n if (family === 4) return isBlockedIPv4(address);\n if (family === 6) return isBlockedIPv6(address);\n // Anything that isn't a recognisable IP literal (after DNS resolution should\n // have produced one) is treated as unsafe.\n return true;\n}\n\n/**\n * Parse and validate a remote URL for outbound fetching. Rejects non-http(s)\n * schemes, embedded credentials, and hosts that resolve to non-public ranges.\n * Returns the parsed {@link URL} on success; throws a descriptive `Error`\n * otherwise.\n */\nexport async function assertSafeRemoteUrl(\n rawUrl: string,\n options: SafeRemoteUrlOptions = {},\n): Promise<URL> {\n let url: URL;\n try {\n url = new URL(rawUrl);\n } catch {\n throw new Error('Remote URL must be an absolute URL');\n }\n\n if (url.protocol !== 'http:' && url.protocol !== 'https:') {\n throw new Error('Remote URL must use http or https');\n }\n if (url.username || url.password) {\n throw new Error('Remote URL must not include credentials');\n }\n if (!url.hostname) {\n throw new Error('Remote URL must include a hostname');\n }\n\n if (options.allowPrivateNetworkHosts) return url;\n\n const resolver = options.resolveHostname ?? defaultResolveHostname;\n const addresses =\n isIP(url.hostname) === 0\n ? await resolver(url.hostname)\n : [{ address: url.hostname }];\n\n if (\n !addresses.length ||\n addresses.some(({ address }) => isBlockedAddress(address))\n ) {\n throw new Error('Remote URL must resolve to a public network address');\n }\n\n return url;\n}\n\n/** Redirect status codes that reroute a request to a new Location. */\nconst REDIRECT_STATUSES = new Set([301, 302, 303, 307, 308]);\nconst DEFAULT_MAX_REDIRECTS = 5;\nconst DEFAULT_RESOLVE_TIMEOUT_MS = 10_000;\n\nexport interface SafeRedirectOptions extends SafeRemoteUrlOptions {\n /** Maximum redirect hops to follow before failing. Default 5. */\n maxRedirects?: number;\n /** Per-hop timeout in ms. Default 10s. */\n timeoutMs?: number;\n /** Injectable fetch (primarily for tests). Defaults to global `fetch`. */\n fetchImpl?: typeof fetch;\n}\n\n/**\n * Resolve a URL's redirect chain and return the final safe {@link URL}, with\n * EVERY hop re-validated through {@link assertSafeRemoteUrl}.\n *\n * Use this before handing a URL to a fetcher that follows redirects on its own\n * (e.g. `fetchDocument`): the up-front {@link assertSafeRemoteUrl} check alone\n * can't stop an allowed public host from `30x`-redirecting into an internal /\n * loopback / metadata host, which would defeat the SSRF guard (review #1562).\n *\n * Redirects are followed with `GET` + `redirect: 'manual'` to match downstream\n * GET-based fetchers; response bodies are discarded (the redirect bodies are\n * empty and the terminal body is left for the caller to re-fetch), so this does\n * not double-download content.\n */\nexport async function resolveSafeFinalUrl(\n rawUrl: string,\n options: SafeRedirectOptions = {},\n): Promise<URL> {\n const fetchImpl = options.fetchImpl ?? fetch;\n const maxRedirects = options.maxRedirects ?? DEFAULT_MAX_REDIRECTS;\n const timeoutMs = options.timeoutMs ?? DEFAULT_RESOLVE_TIMEOUT_MS;\n let current = await assertSafeRemoteUrl(rawUrl, options);\n\n for (let hop = 0; hop <= maxRedirects; hop += 1) {\n const response = await fetchImpl(current, {\n method: 'GET',\n redirect: 'manual',\n signal: AbortSignal.timeout(timeoutMs),\n });\n // Release the connection without downloading the body.\n try {\n await response.body?.cancel();\n } catch {\n // best-effort\n }\n\n if (!REDIRECT_STATUSES.has(response.status)) {\n return current;\n }\n const location = response.headers.get('location');\n if (!location) return current;\n // Re-validate the resolved redirect target before following it.\n current = await assertSafeRemoteUrl(\n new URL(location, current).toString(),\n options,\n );\n }\n\n throw new Error('Remote URL exceeded the maximum number of redirects');\n}\n\n/**\n * Strip userinfo (`user:pass@`) from a URL so it can be safely logged or echoed\n * in an error message. Returns a placeholder for unparseable input. Never let a\n * credential-bearing URL reach logs/errors verbatim (review #1562).\n */\nexport function redactUrlCredentials(raw: string): string {\n try {\n const url = new URL(raw);\n if (url.username || url.password) {\n url.username = '';\n url.password = '';\n return url.toString();\n }\n return raw;\n } catch {\n return '[unparseable url]';\n }\n}\n","import { writeFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport type { AIClientOptions } from '@happyvertical/ai';\nimport { fetchDocument } from '@happyvertical/documents';\nimport { ensureDirectoryExists } from '@happyvertical/files';\nimport { createLogger } from '@happyvertical/logger';\nimport type { SmrtCollectionOptions } from '@happyvertical/smrt-core';\nimport { SmrtCollection, smrt } from '@happyvertical/smrt-core';\nimport type { Image } from '@happyvertical/smrt-images';\nimport { queryGlobal, queryWithGlobals } from '@happyvertical/smrt-tenancy';\nimport { makeSlug } from '@happyvertical/utils';\nimport YAML from 'yaml';\nimport { htmlToMarkdown, resolveBodyFormat } from './body-format';\nimport { Content } from './content';\nimport {\n getEffectiveContentGovernanceConfig,\n loadPersistedContentGovernanceDefinitions,\n resolveEffectiveContentGovernance,\n} from './content-governance';\nimport {\n type ResolveHostname,\n redactUrlCredentials,\n resolveSafeFinalUrl,\n} from './safe-remote-url';\nimport { serializeContent, serializeFact } from './serialization';\nimport type {\n ThumbnailOptions,\n ThumbnailStrategy,\n} from './thumbnail-generator';\n\nconst logger = createLogger({ level: 'info' });\n\n/**\n * Options accepted by {@link Contents.generateMissingThumbnails}. Also reused\n * (as a `Partial`) for the `thumbnail` config block passed through the\n * collection constructor from `smrt.config.js`.\n */\nexport interface GenerateMissingThumbnailsOptions {\n /**\n * Thumbnail generation strategy\n */\n strategy: ThumbnailStrategy;\n\n /**\n * Optional filter for content to process\n */\n where?: Record<string, unknown>;\n\n /**\n * Maximum number of thumbnails to generate\n */\n limit?: number;\n\n // Headline card options\n brandColor?: string;\n backgroundColor?: string;\n logoUrl?: string;\n template?: 'default' | 'news' | 'minimal';\n\n // Static map options\n mapProvider?: 'mapbox' | 'google';\n zoom?: number;\n\n // AI options\n style?: 'photorealistic' | 'illustration' | 'abstract' | 'minimal';\n\n // Common options\n width?: number;\n height?: number;\n}\n\n/**\n * Configuration options for Contents collection\n */\nexport interface ContentsOptions extends SmrtCollectionOptions {\n /**\n * Directory to store content files\n */\n contentDir?: string;\n\n /**\n * Default thumbnail-generation settings sourced from `smrt.config.js`. Merged\n * under per-call options in `generateMissingThumbnails`.\n */\n thumbnail?: Partial<GenerateMissingThumbnailsOptions>;\n}\n\nfunction isAIClientOptions(\n ai: SmrtCollectionOptions['ai'],\n): ai is AIClientOptions {\n return (\n !!ai &&\n typeof ai === 'object' &&\n !('embed' in ai) &&\n !('generateImage' in ai)\n );\n}\n\n/**\n * Collection for managing Content objects\n *\n * The Contents collection provides functionality for managing and manipulating\n * collections of Content objects, including saving to the filesystem and\n * mirroring content from remote URLs.\n */\n@smrt({\n api: {\n include: [\n 'browseFacts',\n 'getBySlug',\n 'getGovernanceDefinitionsAction',\n 'resolveGovernanceAction',\n ],\n routes: {\n browseFacts: {\n scope: 'collection',\n method: 'GET',\n path: 'facts',\n },\n getBySlug: {\n scope: 'collection',\n method: 'GET',\n path: 'by-slug',\n },\n getGovernanceDefinitionsAction: {\n scope: 'collection',\n method: 'GET',\n path: 'governance',\n },\n resolveGovernanceAction: {\n scope: 'collection',\n method: 'GET',\n path: 'governance/resolve',\n },\n },\n },\n mcp: false,\n cli: false,\n})\nexport class Contents extends SmrtCollection<Content> {\n /**\n * Class constructor for collection items\n */\n static _itemClass = Content;\n\n /**\n * Configuration options\n */\n public options: ContentsOptions = {} as ContentsOptions;\n\n /**\n * Directory to store content files\n */\n public contentDir?: string;\n\n /**\n * Cache for loaded content\n */\n public loaded: Map<string, Content>;\n\n /**\n * Creates a new Contents collection\n *\n * Use the static `create()` method inherited from SmrtCollection for proper initialization.\n *\n * @param options - Configuration options\n */\n constructor(options: ContentsOptions = {}) {\n super(options);\n this.options = options;\n this.loaded = new Map();\n }\n\n /**\n * Gets the database interface\n *\n * @returns Database interface\n */\n getDb() {\n return this._db;\n }\n\n /**\n * Initializes the collection\n *\n * @returns Promise that resolves to this instance\n */\n public async initialize(): Promise<this> {\n await super.initialize();\n return this;\n }\n\n private async getFactCollection() {\n const { FactCollection } = await import('@happyvertical/smrt-facts');\n return FactCollection.create(this.options);\n }\n\n public async browseFacts(\n options: {\n q?: string;\n query?: string;\n limit?: number | string;\n offset?: number | string;\n minSimilarity?: number | string;\n includeSuperseded?: boolean | string;\n latestOnly?: boolean | string;\n tenantId?: string | null;\n } = {},\n ) {\n try {\n const facts = await this.getFactCollection();\n const query = options.query || options.q || '';\n const limit =\n options.limit !== undefined ? Number(options.limit) : undefined;\n const offset =\n options.offset !== undefined ? Number(options.offset) : undefined;\n const minSimilarity =\n options.minSimilarity !== undefined\n ? Number(options.minSimilarity)\n : undefined;\n const includeSuperseded =\n options.includeSuperseded === true ||\n options.includeSuperseded === 'true';\n const latestOnly =\n options.latestOnly === undefined\n ? true\n : options.latestOnly === true || options.latestOnly === 'true';\n\n const results = await facts.browseCatalog(query, {\n limit: Number.isFinite(limit) ? limit : undefined,\n offset: Number.isFinite(offset) ? offset : undefined,\n minSimilarity: Number.isFinite(minSimilarity)\n ? minSimilarity\n : undefined,\n includeSuperseded,\n latestOnly,\n tenantId: options.tenantId ?? null,\n });\n\n return results.map(serializeFact);\n } catch (error) {\n // Gracefully handle missing facts table (cross-package dependency)\n if (\n typeof error === 'object' &&\n error !== null &&\n (error as { code?: unknown }).code === 'DB_SCHEMA_MISSING'\n ) {\n return [];\n }\n throw error;\n }\n }\n\n public async getBySlug(\n options: { slug?: string; context?: string; status?: string } = {},\n ) {\n if (!options.slug) {\n throw new Error('slug is required');\n }\n\n const content = await this.get({\n slug: options.slug,\n context: options.context || '',\n });\n\n if (!content) {\n return null;\n }\n\n if (options.status && content.status !== options.status) {\n return null;\n }\n\n return serializeContent(content);\n }\n\n public async getGovernanceDefinitionsAction() {\n const [effective, persisted] = await Promise.all([\n getEffectiveContentGovernanceConfig({ db: this.db }),\n loadPersistedContentGovernanceDefinitions({ db: this.db }),\n ]);\n\n return {\n effective: {\n policies: effective.policies.map((policy) => ({\n ...policy,\n ...(persisted.policies.find((item) => item.key === policy.key) || {}),\n })),\n profiles: effective.profiles.map((profile) => ({\n ...profile,\n ...(persisted.profiles.find((item) => item.key === profile.key) ||\n {}),\n })),\n assignments: effective.assignments.map((assignment) => ({\n ...assignment,\n ...(persisted.assignments.find(\n (item) => item.key === assignment.key,\n ) || {}),\n })),\n },\n persisted: {\n policies: persisted.policies,\n profiles: persisted.profiles,\n assignments: persisted.assignments,\n },\n };\n }\n\n public async resolveGovernanceAction(\n options: { type?: string; variant?: string | null } = {},\n ) {\n return resolveEffectiveContentGovernance({\n contentType: options.type || null,\n contentVariant: options.variant || null,\n db: this.db,\n });\n }\n\n /**\n * Mirrors content from a remote URL\n *\n * Downloads and stores content from a remote URL, extracting text\n * and saving it as a Content object.\n *\n * @param options - Mirror options\n * @param options.url - URL to mirror\n * @param options.mirrorDir - Directory for caching mirrored files\n * @param options.context - Context for the mirrored content\n * @returns Promise resolving to the mirrored Content object\n * @throws Error if URL is invalid or missing\n */\n public async mirror(options: {\n url: string;\n mirrorDir?: string;\n context?: string;\n /**\n * Skip the SSRF host-blocking checks. Only set this for fully trusted,\n * operator-supplied URLs (e.g. local development), never for URLs that\n * originate from end users or external content.\n */\n allowPrivateNetworkHosts?: boolean;\n /** Injectable DNS resolver (primarily for tests). */\n resolveHostname?: ResolveHostname;\n /** Injectable fetch for redirect resolution (primarily for tests). */\n fetchImpl?: typeof fetch;\n }) {\n if (!options.url) {\n throw new Error('No URL provided');\n }\n // Validate the URL AND block private/loopback/link-local/metadata hosts\n // before fetching — `mirror()` fetches an arbitrary caller-supplied URL,\n // which is a classic SSRF sink (e.g. http://169.254.169.254/ metadata).\n // `fetchDocument` follows redirects on its own, so we resolve the redirect\n // chain ourselves first — re-validating every hop — and hand it the\n // already-validated terminal URL, closing the public-host-30x-to-internal\n // bypass (S5 #1388 / review #1562).\n let url: URL;\n try {\n url = await resolveSafeFinalUrl(options.url, {\n allowPrivateNetworkHosts: options.allowPrivateNetworkHosts,\n resolveHostname: options.resolveHostname,\n fetchImpl: options.fetchImpl,\n });\n } catch (error) {\n // Never echo the raw URL — it may carry userinfo credentials (review #1562).\n const safeUrl = redactUrlCredentials(options.url);\n logger.error('Refusing to mirror unsafe URL', { error, url: safeUrl });\n throw new Error(`Invalid URL provided: ${safeUrl}`);\n }\n const existing = await this.get({ url: options.url });\n if (existing) {\n return existing;\n }\n\n // Fetch and process the document via the already-validated terminal URL.\n const doc = await fetchDocument(url.toString(), {\n cacheDir: options?.mirrorDir,\n });\n\n const filename = url.pathname.split('/').pop();\n const nameWithoutExtension = filename?.replace(/\\.[^/.]+$/, '');\n const title = nameWithoutExtension?.replace(/[-_]/g, ' ');\n const slug = makeSlug(title as string);\n\n // Extract text from all document parts\n const body = doc.parts.map((part) => part.content).join('\\n\\n');\n if (body) {\n const content = new Content({\n url: options.url,\n type: 'mirror',\n title,\n slug,\n context: options.context || '',\n body,\n });\n await content.initialize();\n await content.save();\n return content;\n }\n }\n\n /**\n * Writes a Content object to the filesystem as a markdown file\n *\n * @param options - Options for writing the content file\n * @param options.content - Content object to write\n * @param options.contentDir - Directory to write the file to\n * @returns Promise that resolves when the file is written\n * @throws Error if contentDir is not provided\n */\n public async writeContentFile(options: {\n content: Content;\n contentDir: string;\n }) {\n const { content, contentDir } = options;\n if (!contentDir) {\n throw new Error('No content dir provided');\n }\n\n const { body } = content;\n const frontMatter = {\n title: content.title,\n slug: content.slug,\n context: content.context,\n author: content.author,\n publish_date: content.publish_date,\n };\n\n let output = '';\n if (frontMatter && Object.keys(frontMatter).length > 0) {\n output += '---\\n';\n output += YAML.stringify(frontMatter);\n output += '---\\n';\n }\n\n // Filesystem exports are markdown regardless of the editor save format.\n let formattedBody = body || '';\n const bodyFormat = resolveBodyFormat(content.bodyFormat, body);\n if (bodyFormat === 'html') {\n formattedBody = htmlToMarkdown(body || '');\n } else if (body && !this.isMarkdown(body)) {\n formattedBody = this.formatAsMarkdown(body);\n }\n output += formattedBody;\n\n const pathParts = [\n contentDir,\n content.context || '', // if empty, use empty string\n content.slug,\n 'index.md',\n ].filter(Boolean); // remove empty strings\n\n const outputFile = path.join(...(pathParts as string[]));\n\n // `context` and `slug` are persisted, caller-influenced fields. Without a\n // guard, a value like `../../etc/cron.d/x` escapes `contentDir` and lets an\n // export overwrite arbitrary files (path traversal). Confirm the joined\n // path still lives under the resolved content directory (S5 #1388).\n const resolvedDir = path.resolve(contentDir);\n const resolvedFile = path.resolve(outputFile);\n if (\n resolvedFile !== resolvedDir &&\n !resolvedFile.startsWith(resolvedDir + path.sep)\n ) {\n throw new Error(\n 'Refusing to write content file outside of the content directory',\n );\n }\n\n await ensureDirectoryExists(path.dirname(outputFile));\n await writeFile(outputFile, output);\n }\n\n /**\n * Checks if text appears to be in markdown format\n *\n * @param text - Text to check\n * @returns Boolean indicating if the text contains markdown syntax\n */\n private isMarkdown(text: string): boolean {\n // Basic check for common markdown indicators\n const markdownIndicators = [\n /^#\\s/m, // Headers\n /\\*\\*.+\\*\\*/, // Bold\n /\\*.+\\*/, // Italic\n /\\[.+\\]\\(.+\\)/, // Links\n /^\\s*[-*+]\\s/m, // Lists\n /^\\s*\\d+\\.\\s/m, // Numbered lists\n /```[\\s\\S]*```/, // Code blocks\n /^\\s*>/m, // Blockquotes\n ];\n\n return markdownIndicators.some((indicator) => indicator.test(text));\n }\n\n /**\n * Formats plain text as simple markdown\n *\n * @param text - Plain text to format\n * @returns Text formatted as basic markdown\n */\n private formatAsMarkdown(text: string): string {\n // Basic formatting of plain text to markdown\n return text\n .split(/\\n\\n+/)\n .map((paragraph) => paragraph.trim())\n .filter(Boolean)\n .join('\\n\\n');\n }\n\n /**\n * Synchronizes content to the filesystem\n *\n * Writes all article-type Content objects to the filesystem\n * as markdown files.\n *\n * @param options - Sync options\n * @param options.contentDir - Directory to write content files to\n * @returns Promise that resolves when synchronization is complete\n */\n public async syncContentDir(options: { contentDir?: string }) {\n const contentFilter = {\n type: 'article',\n };\n\n const contents = await this.list({ where: contentFilter });\n for (const content of contents) {\n await this.writeContentFile({\n content,\n contentDir: options.contentDir || this.options.contentDir || '',\n });\n }\n }\n\n /**\n * Generate thumbnails for content that doesn't have one\n *\n * @param options - Options for bulk thumbnail generation\n * @returns Promise resolving to result object with generated images and failed content IDs\n *\n * @example Generate headline cards for all published articles\n * ```typescript\n * const result = await contents.generateMissingThumbnails({\n * strategy: 'headline-card',\n * where: { type: 'article', status: 'published' },\n * brandColor: '#1a56db'\n * });\n * console.log(`Generated ${result.images.length} thumbnails`);\n * if (result.failed.length > 0) {\n * console.warn(`Failed to generate ${result.failed.length} thumbnails`);\n * }\n * ```\n */\n public async generateMissingThumbnails(\n options: GenerateMissingThumbnailsOptions,\n ): Promise<{\n images: Image[];\n failed: Array<{ contentId: string; error: string }>;\n }> {\n // Merge with thumbnail config from smrt.config.js (passed via constructor)\n // This allows CLI users to configure defaults in smrt.config.js:\n // thumbnail: { strategy: 'headline-card', brandColor: '#1976d2' }\n const configDefaults = this.options?.thumbnail || {};\n const mergedOptions = {\n ...configDefaults,\n ...options,\n };\n\n // Build query for content missing thumbnails\n const whereClause = {\n ...mergedOptions.where,\n thumbnailAssetId: null,\n };\n\n const contents = await this.list({\n where: whereClause,\n limit: mergedOptions.limit,\n });\n\n const generatedImages: Image[] = [];\n const failed: Array<{ contentId: string; error: string }> = [];\n\n for (const content of contents) {\n try {\n // Build thumbnail options based on strategy\n let thumbnailOptions: ThumbnailOptions;\n\n switch (mergedOptions.strategy) {\n case 'headline-card':\n thumbnailOptions = {\n strategy: 'headline-card',\n brandColor: mergedOptions.brandColor,\n backgroundColor: mergedOptions.backgroundColor,\n logoUrl: mergedOptions.logoUrl,\n template: mergedOptions.template,\n width: mergedOptions.width,\n height: mergedOptions.height,\n };\n break;\n\n case 'static-map':\n thumbnailOptions = {\n strategy: 'static-map',\n mapProvider: mergedOptions.mapProvider,\n zoom: mergedOptions.zoom,\n width: mergedOptions.width,\n height: mergedOptions.height,\n };\n break;\n\n case 'ai-generate':\n thumbnailOptions = {\n strategy: 'ai-generate',\n style: mergedOptions.style,\n width: mergedOptions.width,\n height: mergedOptions.height,\n ai: isAIClientOptions(this.options.ai)\n ? this.options.ai\n : undefined,\n };\n break;\n\n default:\n throw new Error(`Unknown strategy: ${mergedOptions.strategy}`);\n }\n\n const image = await content.generateThumbnail(thumbnailOptions);\n generatedImages.push(image);\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n logger.error(\n `Failed to generate thumbnail for content ${content.id}: ${errorMessage}`,\n );\n failed.push({\n contentId: content.id ?? 'unknown',\n error: errorMessage,\n });\n }\n }\n\n return { images: generatedImages, failed };\n }\n\n // ============================================\n // Tenant Helper Methods\n // ============================================\n\n /**\n * Find all content belonging to a specific tenant\n *\n * @param tenantId - The tenant ID to filter by\n * @returns Promise resolving to array of Content objects for the tenant\n *\n * @example\n * ```typescript\n * const tenantContent = await contents.findByTenant('tenant-123');\n * ```\n */\n async findByTenant(tenantId: string): Promise<Content[]> {\n return this.list({ where: { tenantId } });\n }\n\n /**\n * Find all global content (not associated with any tenant).\n *\n * Routes through the shared tenant-global helper so it does not throw under\n * an active tenant context (an explicit `tenant_id IS NULL` filter would be\n * flagged as an isolation violation). (#1600)\n *\n * @returns Promise resolving to array of global Content objects\n *\n * @example\n * ```typescript\n * const globalContent = await contents.findGlobal();\n * ```\n */\n async findGlobal(): Promise<Content[]> {\n return queryGlobal<Content>(this);\n }\n\n /**\n * Find content for a tenant including global content.\n *\n * This returns both tenant-specific content and global content (tenantId is null),\n * useful for showing a tenant their content plus any shared/global resources.\n *\n * Fails closed if an active tenant context requests a different tenant's\n * rows; the admin/system path keeps the cross-tenant capability. (#1600)\n *\n * @param tenantId - The tenant ID to include\n * @returns Promise resolving to array of Content objects (tenant + global)\n *\n * @example\n * ```typescript\n * const allAccessibleContent = await contents.findWithGlobals('tenant-123');\n * ```\n */\n async findWithGlobals(tenantId: string): Promise<Content[]> {\n return queryWithGlobals<Content>(this, tenantId, 'Content.findWithGlobals');\n }\n}\n","import { randomUUID } from 'node:crypto';\nimport {\n ObjectRegistry,\n type SmrtCollectionOptions,\n} from '@happyvertical/smrt-core';\nimport {\n type ParsedContentFeedItem,\n parseContentFeed,\n} from './content-feed-parser';\nimport type { ContentFeedSource } from './content-feed-source';\nimport { Mirror } from './content-types';\nimport { Contents } from './contents';\nimport { assertSafeRemoteUrl, type ResolveHostname } from './safe-remote-url';\n\nexport interface ContentFeedSyncOptions extends SmrtCollectionOptions {\n fetch?: typeof fetch;\n maxItems?: number;\n maxResponseBytes?: number;\n fetchTimeoutMs?: number;\n allowPrivateNetworkHosts?: boolean;\n resolveHostname?: ResolveHostname;\n status?: 'published' | 'draft';\n now?: () => Date;\n}\n\nexport interface ContentFeedSyncResult {\n source: ContentFeedSource;\n fetched: boolean;\n notModified: boolean;\n imported: number;\n updated: number;\n skipped: number;\n}\n\ntype QueryableCollection = Pick<Contents, 'query'>;\n\nconst DEFAULT_MAX_RESPONSE_BYTES = 2_000_000;\nconst DEFAULT_FETCH_TIMEOUT_MS = 10_000;\nconst MAX_FEED_REDIRECTS = 5;\nconst REDIRECT_STATUSES = new Set([301, 302, 303, 307, 308]);\nconst FALLBACK_MIRROR_META_TYPE = '@happyvertical/smrt-content:Mirror';\n\nfunction getMirrorMetaType(): string {\n return (\n ObjectRegistry.getClassByConstructor(Mirror)?.qualifiedName ??\n FALLBACK_MIRROR_META_TYPE\n );\n}\n\nfunction slugify(value: string): string {\n const slug = value\n .toLowerCase()\n .replace(/&/g, ' and ')\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '')\n .slice(0, 80);\n return slug || 'feed';\n}\n\nfunction normalizeUrlIdentity(value: string): string {\n try {\n const url = new URL(value);\n url.hash = '';\n url.searchParams.sort();\n return url.toString().replace(/\\/$/, '');\n } catch {\n return value.trim();\n }\n}\n\nfunction hashString(value: string): string {\n let hash = 5381;\n for (let index = 0; index < value.length; index += 1) {\n hash = (hash * 33) ^ value.charCodeAt(index);\n }\n return (hash >>> 0).toString(36);\n}\n\nfunction createDedupeKey(\n source: ContentFeedSource,\n item: ParsedContentFeedItem,\n): string {\n return `feed:${source.id ?? source.feedUrl}:${item.guid || normalizeUrlIdentity(item.url)}`;\n}\n\nasync function validateFeedFetchUrl(\n feedUrl: string,\n options: ContentFeedSyncOptions,\n): Promise<URL> {\n return assertSafeRemoteUrl(feedUrl, {\n allowPrivateNetworkHosts: options.allowPrivateNetworkHosts,\n resolveHostname: options.resolveHostname,\n });\n}\n\nfunction createTimeoutSignal(timeoutMs: number): AbortSignal | undefined {\n if (timeoutMs <= 0) return undefined;\n return AbortSignal.timeout(timeoutMs);\n}\n\n/**\n * Fetch a feed following redirects manually so every hop's target is\n * re-validated through {@link validateFeedFetchUrl}. `fetch()`'s default\n * `redirect: 'follow'` would let an allowed public feed 30x-redirect to an\n * internal/link-local/metadata host, defeating the up-front SSRF check\n * (S5 #1388). Returns the response together with the final validated URL so\n * the parser uses the redirect target as the feed base.\n */\nasync function fetchFeedWithRedirectGuard(\n fetchImpl: typeof fetch,\n startUrl: URL,\n headers: Record<string, string>,\n options: ContentFeedSyncOptions,\n): Promise<{ response: Response; finalUrl: URL }> {\n let current = startUrl;\n\n for (let hop = 0; hop <= MAX_FEED_REDIRECTS; hop += 1) {\n const response = await fetchImpl(current, {\n headers,\n redirect: 'manual',\n signal: createTimeoutSignal(\n options.fetchTimeoutMs ?? DEFAULT_FETCH_TIMEOUT_MS,\n ),\n });\n\n // Only the redirect statuses (not 304 Not Modified / 305 / 306) reroute the\n // request; everything else (200, 304, 4xx, 5xx) is returned to the caller.\n if (REDIRECT_STATUSES.has(response.status)) {\n const location = response.headers.get('location');\n if (!location) {\n throw new Error('Feed redirect response missing Location header');\n }\n // Re-run the full SSRF validation against the resolved redirect target.\n current = await validateFeedFetchUrl(\n new URL(location, current).toString(),\n options,\n );\n continue;\n }\n\n return { response, finalUrl: current };\n }\n\n throw new Error('Feed URL exceeded the maximum number of redirects');\n}\n\nasync function readResponseText(\n response: Response,\n maxBytes: number,\n): Promise<string> {\n const contentLength = response.headers.get('content-length');\n if (contentLength && Number(contentLength) > maxBytes) {\n throw new Error(`Feed response exceeds ${maxBytes} bytes`);\n }\n\n if (!response.body) {\n const text = await response.text();\n if (new TextEncoder().encode(text).byteLength > maxBytes) {\n throw new Error(`Feed response exceeds ${maxBytes} bytes`);\n }\n return text;\n }\n\n const reader = response.body.getReader();\n const chunks: Uint8Array[] = [];\n let totalBytes = 0;\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n if (!value) continue;\n totalBytes += value.byteLength;\n if (totalBytes > maxBytes) {\n await reader.cancel();\n throw new Error(`Feed response exceeds ${maxBytes} bytes`);\n }\n chunks.push(value);\n }\n\n const buffer = new Uint8Array(totalBytes);\n let offset = 0;\n for (const chunk of chunks) {\n buffer.set(chunk, offset);\n offset += chunk.byteLength;\n }\n\n return new TextDecoder().decode(buffer);\n}\n\nasync function findExistingMirror(\n contents: QueryableCollection,\n source: ContentFeedSource,\n item: ParsedContentFeedItem,\n dedupeKey: string,\n): Promise<{ id: string; status: string | null } | null> {\n const tenantWhere = source.tenantId ? 'tenant_id = ?' : 'tenant_id IS NULL';\n const params: unknown[] = [getMirrorMetaType()];\n if (source.tenantId) params.push(source.tenantId);\n\n if (item.guid) {\n const result = await contents.query(\n `SELECT id, status\n FROM contents\n WHERE _meta_type = ?\n AND ${tenantWhere}\n AND feed_source_id = ?\n AND source_guid = ?\n LIMIT 1`,\n [...params, source.id, item.guid],\n );\n if (result[0]) return result[0] as { id: string; status: string | null };\n }\n\n const result = await contents.query(\n `SELECT id, status\n FROM contents\n WHERE _meta_type = ?\n AND ${tenantWhere}\n AND feed_source_id = ?\n AND dedupe_key = ?\n LIMIT 1`,\n [...params, source.id, dedupeKey],\n );\n return (\n (result[0] as { id: string; status: string | null } | undefined) ?? null\n );\n}\n\nasync function upsertMirrorItem(\n contents: QueryableCollection,\n source: ContentFeedSource,\n item: ParsedContentFeedItem,\n status: 'published' | 'draft',\n now: Date,\n): Promise<'imported' | 'updated'> {\n const dedupeKey = createDedupeKey(source, item);\n const existing = await findExistingMirror(contents, source, item, dedupeKey);\n const publishedAt = (item.publishedAt ?? item.updatedAt ?? now).toISOString();\n const sourceSlug = slugify(\n source.sourceGroup || source.name || source.feedUrl,\n );\n const category = source.defaultCategory || item.categories[0] || null;\n const tags = JSON.stringify(item.categories);\n\n if (existing) {\n await contents.query(\n `UPDATE contents\n SET title = ?,\n name = ?,\n description = ?,\n source = ?,\n original_url = ?,\n url = ?,\n feed_source_id = ?,\n source_guid = ?,\n source_name = ?,\n source_homepage_url = ?,\n external_url = ?,\n original_published_at = ?,\n dedupe_key = ?,\n publish_date = ?,\n author = ?,\n category = ?,\n tags = ?,\n status = ?,\n updated_at = ?\n WHERE id = ?`,\n [\n item.title,\n item.title,\n item.summary,\n source.name,\n item.url,\n item.url,\n source.id,\n item.guid,\n source.name,\n source.homepageUrl,\n item.url,\n publishedAt,\n dedupeKey,\n publishedAt,\n item.author,\n category,\n tags,\n existing.status || status,\n now.toISOString(),\n existing.id,\n ],\n );\n return 'updated';\n }\n\n const id = randomUUID();\n await contents.query(\n `INSERT INTO contents (\n id, slug, context, _meta_type, title, name, description, body,\n status, state, metadata, source, original_url, url, feed_source_id,\n source_guid, source_name, source_homepage_url, external_url,\n original_published_at, dedupe_key, tenant_id, publish_date, author,\n category, tags, created_at, updated_at\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n [\n id,\n `mirror-${sourceSlug}-${hashString(dedupeKey)}`,\n '',\n getMirrorMetaType(),\n item.title,\n item.title,\n item.summary,\n '',\n status,\n 'active',\n '{}',\n source.name,\n item.url,\n item.url,\n source.id,\n item.guid,\n source.name,\n source.homepageUrl,\n item.url,\n publishedAt,\n dedupeKey,\n source.tenantId,\n publishedAt,\n item.author,\n category,\n tags,\n now.toISOString(),\n now.toISOString(),\n ],\n );\n return 'imported';\n}\n\nexport async function syncContentFeedSource(\n source: ContentFeedSource,\n options: ContentFeedSyncOptions = {},\n): Promise<ContentFeedSyncResult> {\n if (source.status === 'paused' || source.status === 'archived') {\n return {\n source,\n fetched: false,\n notModified: false,\n imported: 0,\n updated: 0,\n skipped: 0,\n };\n }\n\n const fetchImpl = options.fetch ?? globalThis.fetch;\n if (!fetchImpl) throw new Error('No fetch implementation available');\n\n const headers: Record<string, string> = {\n Accept:\n 'application/rss+xml, application/atom+xml, application/xml, text/xml',\n 'User-Agent': '@happyvertical/smrt-content feed sync',\n };\n if (source.etag) headers['If-None-Match'] = source.etag;\n if (source.lastModified) headers['If-Modified-Since'] = source.lastModified;\n\n const now = options.now?.() ?? new Date();\n source.markFetchStarted(now);\n await source.save();\n\n try {\n const feedUrl = await validateFeedFetchUrl(source.feedUrl, options);\n const { response, finalUrl } = await fetchFeedWithRedirectGuard(\n fetchImpl,\n feedUrl,\n headers,\n options,\n );\n\n if (response.status === 304) {\n source.markFetchSucceeded(now);\n await source.save();\n return {\n source,\n fetched: true,\n notModified: true,\n imported: 0,\n updated: 0,\n skipped: 0,\n };\n }\n\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n }\n\n const parsed = parseContentFeed(\n await readResponseText(\n response,\n options.maxResponseBytes ?? DEFAULT_MAX_RESPONSE_BYTES,\n ),\n finalUrl.toString(),\n );\n source.format = parsed.format;\n source.homepageUrl = source.homepageUrl || parsed.homepageUrl;\n if (!source.name && parsed.title) source.name = parsed.title;\n\n const contents = await Contents.create(options);\n let imported = 0;\n let updated = 0;\n let skipped = 0;\n\n for (const item of parsed.items.slice(0, options.maxItems)) {\n try {\n const result = await upsertMirrorItem(\n contents,\n source,\n item,\n options.status ?? 'published',\n now,\n );\n if (result === 'imported') imported += 1;\n else updated += 1;\n } catch {\n skipped += 1;\n }\n }\n\n source.markFetchSucceeded(now, {\n etag: response.headers.get('etag'),\n lastModified: response.headers.get('last-modified'),\n });\n await source.save();\n\n return {\n source,\n fetched: true,\n notModified: false,\n imported,\n updated,\n skipped,\n };\n } catch (error) {\n source.markFetchFailed(error, now);\n await source.save();\n throw error;\n }\n}\n","import type { SmrtObjectOptions } from '@happyvertical/smrt-core';\nimport { field, SmrtObject, smrt } from '@happyvertical/smrt-core';\nimport type { FactContentRelationship } from '@happyvertical/smrt-facts';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport {\n buildContentGovernanceAssignmentKey,\n type ContentGovernanceAssignmentDefinition,\n getEffectiveContentGovernanceConfig,\n} from './content-governance';\n\nexport interface ContentGovernanceAssignmentOptions extends SmrtObjectOptions {\n key?: string;\n label?: string;\n contentType?: string;\n contentVariant?: string | null;\n enabled?: boolean;\n factLinkingEnabled?: boolean;\n transparencyEnabled?: boolean;\n publicationProfileKey?: string | null;\n correctionProfileKey?: string | null;\n enforcePublishReadiness?: boolean;\n defaultFactRelationship?: FactContentRelationship;\n metadata?: string | Record<string, unknown>;\n tenantId?: string | null;\n createdAt?: Date;\n updatedAt?: Date;\n}\n\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableName: 'content_governance_assignments',\n conflictColumns: ['key'],\n api: { include: ['list', 'get', 'create', 'update', 'delete'] },\n mcp: { include: ['list', 'get', 'create', 'update', 'delete'] },\n cli: true,\n})\nexport class ContentGovernanceAssignment extends SmrtObject {\n @field({ required: true })\n key = '';\n\n label = '';\n\n @field({ required: true })\n contentType = '';\n\n contentVariant = '';\n enabled = true;\n factLinkingEnabled = false;\n transparencyEnabled = false;\n publicationProfileKey = '';\n correctionProfileKey = '';\n enforcePublishReadiness = false;\n defaultFactRelationship: FactContentRelationship = 'supports';\n metadata = '';\n\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n createdAt = new Date();\n updatedAt = new Date();\n\n constructor(options: ContentGovernanceAssignmentOptions = {}) {\n super(options);\n if (options.contentType !== undefined)\n this.contentType = options.contentType;\n if (options.contentVariant !== undefined)\n this.contentVariant = options.contentVariant || '';\n if (options.label !== undefined) this.label = options.label;\n if (options.enabled !== undefined) this.enabled = options.enabled;\n if (options.factLinkingEnabled !== undefined)\n this.factLinkingEnabled = options.factLinkingEnabled;\n if (options.transparencyEnabled !== undefined)\n this.transparencyEnabled = options.transparencyEnabled;\n if (options.publicationProfileKey !== undefined)\n this.publicationProfileKey = options.publicationProfileKey || '';\n if (options.correctionProfileKey !== undefined)\n this.correctionProfileKey = options.correctionProfileKey || '';\n if (options.enforcePublishReadiness !== undefined)\n this.enforcePublishReadiness = options.enforcePublishReadiness;\n if (options.defaultFactRelationship !== undefined)\n this.defaultFactRelationship = options.defaultFactRelationship;\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n if (options.createdAt) this.createdAt = options.createdAt;\n if (options.updatedAt) this.updatedAt = options.updatedAt;\n\n this.key =\n options.key ||\n buildContentGovernanceAssignmentKey(\n this.contentType,\n this.contentVariant,\n );\n\n if (options.metadata !== undefined) {\n this.metadata =\n typeof options.metadata === 'string'\n ? options.metadata\n : JSON.stringify(options.metadata);\n }\n }\n\n getMetadata(): Record<string, unknown> {\n if (this.metadata && typeof this.metadata === 'object') {\n return { ...(this.metadata as Record<string, unknown>) };\n }\n\n try {\n return this.metadata ? JSON.parse(this.metadata) : {};\n } catch {\n return {};\n }\n }\n\n toDefinition(): ContentGovernanceAssignmentDefinition {\n return {\n key: this.key,\n label: this.label || '',\n contentType: this.contentType,\n contentVariant: this.contentVariant || '',\n enabled: this.enabled !== false,\n factLinkingEnabled: this.factLinkingEnabled === true,\n transparencyEnabled: this.transparencyEnabled === true,\n publicationProfileKey: this.publicationProfileKey || null,\n correctionProfileKey: this.correctionProfileKey || null,\n enforcePublishReadiness: this.enforcePublishReadiness === true,\n defaultFactRelationship: this.defaultFactRelationship || 'supports',\n metadata: this.getMetadata(),\n };\n }\n\n protected override async validateBeforeSave(): Promise<void> {\n await super.validateBeforeSave();\n\n this.key = buildContentGovernanceAssignmentKey(\n this.contentType,\n this.contentVariant,\n );\n\n const effective = await getEffectiveContentGovernanceConfig({\n db: this.db,\n });\n const availableProfileKeys = new Set(\n effective.profiles.map((profile) => profile.key),\n );\n const missingProfiles = [\n this.publicationProfileKey,\n this.correctionProfileKey,\n ].filter(\n (profileKey) => profileKey && !availableProfileKeys.has(profileKey),\n );\n\n if (missingProfiles.length > 0) {\n throw new Error(\n `Cannot save governance assignment \"${this.key}\" because these profiles are missing: ${missingProfiles.join(', ')}`,\n );\n }\n }\n}\n","import { SmrtCollection } from '@happyvertical/smrt-core';\nimport { ContentGovernanceAssignment } from './content-governance-assignment';\n\nexport class ContentGovernanceAssignmentCollection extends SmrtCollection<ContentGovernanceAssignment> {\n static readonly _itemClass = ContentGovernanceAssignment;\n\n async getByKey(key: string): Promise<ContentGovernanceAssignment | null> {\n return this.get({ key });\n }\n\n async resolveForContent(options: {\n contentType: string;\n contentVariant?: string | null;\n }): Promise<ContentGovernanceAssignment | null> {\n const exact =\n (await this.get({\n key: `${options.contentType}::${options.contentVariant || ''}`,\n })) || null;\n\n if (exact) {\n return exact;\n }\n\n return this.get({\n key: `${options.contentType}::`,\n });\n }\n}\n","import type { SmrtObjectOptions } from '@happyvertical/smrt-core';\nimport { field, SmrtObject, smrt } from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport {\n type ContentReviewKind,\n type ContentReviewPolicyDefinition,\n getEffectiveContentGovernanceConfig,\n getFallbackPolicyKind,\n hasStaticContentGovernancePolicy,\n} from './content-governance';\n\nexport interface ContentGovernancePolicyOptions extends SmrtObjectOptions {\n key?: string;\n label?: string;\n kind?: ContentReviewKind;\n instructions?: string;\n enabled?: boolean;\n metadata?: string | Record<string, unknown>;\n tenantId?: string | null;\n createdAt?: Date;\n updatedAt?: Date;\n}\n\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableName: 'content_governance_policies',\n conflictColumns: ['key'],\n api: { include: ['list', 'get', 'create', 'update', 'delete'] },\n mcp: { include: ['list', 'get', 'create', 'update', 'delete'] },\n cli: true,\n})\nexport class ContentGovernancePolicy extends SmrtObject {\n @field({ required: true })\n key = '';\n\n label = '';\n kind: ContentReviewKind = 'custom';\n instructions = '';\n enabled = true;\n metadata = '';\n\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n createdAt = new Date();\n updatedAt = new Date();\n\n constructor(options: ContentGovernancePolicyOptions = {}) {\n super(options);\n if (options.key !== undefined) this.key = options.key;\n if (options.label !== undefined) this.label = options.label;\n if (options.kind !== undefined) this.kind = options.kind;\n if (options.instructions !== undefined)\n this.instructions = options.instructions;\n if (options.enabled !== undefined) this.enabled = options.enabled;\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n if (options.createdAt) this.createdAt = options.createdAt;\n if (options.updatedAt) this.updatedAt = options.updatedAt;\n\n if (options.metadata !== undefined) {\n this.metadata =\n typeof options.metadata === 'string'\n ? options.metadata\n : JSON.stringify(options.metadata);\n }\n }\n\n getMetadata(): Record<string, unknown> {\n if (this.metadata && typeof this.metadata === 'object') {\n return { ...(this.metadata as Record<string, unknown>) };\n }\n\n try {\n return this.metadata ? JSON.parse(this.metadata) : {};\n } catch {\n return {};\n }\n }\n\n toDefinition(): ContentReviewPolicyDefinition {\n return {\n key: this.key,\n label: this.label || this.key,\n kind: this.kind || getFallbackPolicyKind(this.key),\n instructions: this.instructions || '',\n enabled: this.enabled !== false,\n metadata: this.getMetadata(),\n };\n }\n\n override async delete(): Promise<void> {\n const effective = await getEffectiveContentGovernanceConfig({\n db: this.db,\n });\n const hasFallback = hasStaticContentGovernancePolicy(this.key);\n const referencedBy = effective.profiles\n .filter((profile) =>\n profile.requirements.some(\n (requirement) => requirement.policyKey === this.key,\n ),\n )\n .map((profile) => profile.key);\n\n if (!hasFallback && referencedBy.length > 0) {\n throw new Error(\n `Cannot delete governance policy \"${this.key}\" because it is referenced by profiles: ${referencedBy.join(', ')}`,\n );\n }\n\n return super.delete();\n }\n}\n","import { SmrtCollection } from '@happyvertical/smrt-core';\nimport { ContentGovernancePolicy } from './content-governance-policy';\n\nexport class ContentGovernancePolicyCollection extends SmrtCollection<ContentGovernancePolicy> {\n static readonly _itemClass = ContentGovernancePolicy;\n\n async getByKey(key: string): Promise<ContentGovernancePolicy | null> {\n return this.get({ key });\n }\n}\n","import type { SmrtObjectOptions } from '@happyvertical/smrt-core';\nimport { field, SmrtObject, smrt } from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport {\n type ContentGovernanceProfileDefinition,\n type ContentReviewRequirement,\n getEffectiveContentGovernanceConfig,\n hasStaticContentGovernanceProfile,\n} from './content-governance';\n\nexport interface ContentGovernanceProfileOptions extends SmrtObjectOptions {\n key?: string;\n label?: string;\n description?: string;\n enabled?: boolean;\n requirements?: string | ContentReviewRequirement[];\n metadata?: string | Record<string, unknown>;\n tenantId?: string | null;\n createdAt?: Date;\n updatedAt?: Date;\n}\n\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableName: 'content_governance_profiles',\n conflictColumns: ['key'],\n api: { include: ['list', 'get', 'create', 'update', 'delete'] },\n mcp: { include: ['list', 'get', 'create', 'update', 'delete'] },\n cli: true,\n})\nexport class ContentGovernanceProfile extends SmrtObject {\n @field({ required: true })\n key = '';\n\n label = '';\n description = '';\n enabled = true;\n requirements = '[]';\n metadata = '';\n\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n createdAt = new Date();\n updatedAt = new Date();\n\n constructor(options: ContentGovernanceProfileOptions = {}) {\n super(options);\n if (options.key !== undefined) this.key = options.key;\n if (options.label !== undefined) this.label = options.label;\n if (options.description !== undefined)\n this.description = options.description;\n if (options.enabled !== undefined) this.enabled = options.enabled;\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n if (options.createdAt) this.createdAt = options.createdAt;\n if (options.updatedAt) this.updatedAt = options.updatedAt;\n\n if (options.requirements !== undefined) {\n this.requirements =\n typeof options.requirements === 'string'\n ? options.requirements\n : JSON.stringify(options.requirements);\n }\n\n if (options.metadata !== undefined) {\n this.metadata =\n typeof options.metadata === 'string'\n ? options.metadata\n : JSON.stringify(options.metadata);\n }\n }\n\n getRequirements(): ContentReviewRequirement[] {\n if (Array.isArray(this.requirements)) {\n return this.requirements as ContentReviewRequirement[];\n }\n\n try {\n return this.requirements ? JSON.parse(this.requirements) : [];\n } catch {\n return [];\n }\n }\n\n getMetadata(): Record<string, unknown> {\n if (this.metadata && typeof this.metadata === 'object') {\n return { ...(this.metadata as Record<string, unknown>) };\n }\n\n try {\n return this.metadata ? JSON.parse(this.metadata) : {};\n } catch {\n return {};\n }\n }\n\n toDefinition(): ContentGovernanceProfileDefinition {\n return {\n key: this.key,\n label: this.label || this.key,\n description: this.description || '',\n enabled: this.enabled !== false,\n requirements: this.getRequirements(),\n metadata: this.getMetadata(),\n };\n }\n\n protected override async validateBeforeSave(): Promise<void> {\n await super.validateBeforeSave();\n\n const effective = await getEffectiveContentGovernanceConfig({\n db: this.db,\n });\n const availablePolicyKeys = new Set(\n effective.policies.map((policy) => policy.key),\n );\n const missingPolicies = this.getRequirements()\n .map((requirement) => requirement.policyKey)\n .filter((policyKey) => !availablePolicyKeys.has(policyKey));\n\n if (missingPolicies.length > 0) {\n throw new Error(\n `Cannot save governance profile \"${this.key}\" because these policies are missing: ${missingPolicies.join(', ')}`,\n );\n }\n }\n\n override async delete(): Promise<void> {\n const effective = await getEffectiveContentGovernanceConfig({\n db: this.db,\n });\n const hasFallback = hasStaticContentGovernanceProfile(this.key);\n const referencedBy = effective.assignments\n .filter(\n (assignment) =>\n assignment.publicationProfileKey === this.key ||\n assignment.correctionProfileKey === this.key,\n )\n .map((assignment) => assignment.key || assignment.contentType);\n\n if (!hasFallback && referencedBy.length > 0) {\n throw new Error(\n `Cannot delete governance profile \"${this.key}\" because it is referenced by assignments: ${referencedBy.join(', ')}`,\n );\n }\n\n return super.delete();\n }\n}\n","import { SmrtCollection } from '@happyvertical/smrt-core';\nimport { ContentGovernanceProfile } from './content-governance-profile';\n\nexport class ContentGovernanceProfileCollection extends SmrtCollection<ContentGovernanceProfile> {\n static readonly _itemClass = ContentGovernanceProfile;\n\n async getByKey(key: string): Promise<ContentGovernanceProfile | null> {\n return this.get({ key });\n }\n}\n","import type { SmrtObjectOptions } from '@happyvertical/smrt-core';\nimport { foreignKey, SmrtObject, smrt } from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport type {\n ContentReviewFinding,\n ContentReviewKind,\n ContentReviewStatus,\n} from './content-governance';\n\nexport interface ContentReviewOptions extends SmrtObjectOptions {\n contentId?: string;\n contentVersionId?: string;\n kind?: ContentReviewKind;\n policyKey?: string;\n status?: ContentReviewStatus;\n summary?: string;\n findings?: string | ContentReviewFinding[];\n reviewer?: string;\n metadata?: string | Record<string, unknown>;\n tenantId?: string | null;\n createdAt?: Date;\n updatedAt?: Date;\n}\n\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableName: 'content_reviews',\n api: { include: ['list', 'get', 'create', 'update'] },\n mcp: { include: ['list', 'get', 'create', 'update'] },\n cli: true,\n})\nexport class ContentReview extends SmrtObject {\n @foreignKey('Content', { required: true })\n contentId = '';\n\n @foreignKey('ContentVersion')\n contentVersionId = '';\n kind: ContentReviewKind = 'custom';\n policyKey = '';\n status: ContentReviewStatus = 'pending';\n summary = '';\n findings = '[]';\n reviewer = 'system';\n metadata = '';\n\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n createdAt = new Date();\n updatedAt = new Date();\n\n constructor(options: ContentReviewOptions = {}) {\n super(options);\n if (options.contentId) this.contentId = options.contentId;\n if (options.contentVersionId !== undefined)\n this.contentVersionId = options.contentVersionId;\n if (options.kind !== undefined) this.kind = options.kind;\n if (options.policyKey !== undefined) this.policyKey = options.policyKey;\n if (options.status !== undefined) this.status = options.status;\n if (options.summary !== undefined) this.summary = options.summary;\n if (options.reviewer !== undefined) this.reviewer = options.reviewer;\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n if (options.createdAt) this.createdAt = options.createdAt;\n if (options.updatedAt) this.updatedAt = options.updatedAt;\n\n if (options.findings !== undefined) {\n this.findings =\n typeof options.findings === 'string'\n ? options.findings\n : JSON.stringify(options.findings);\n }\n\n if (options.metadata !== undefined) {\n this.metadata =\n typeof options.metadata === 'string'\n ? options.metadata\n : JSON.stringify(options.metadata);\n }\n }\n\n getFindings(): ContentReviewFinding[] {\n if (Array.isArray(this.findings)) {\n return this.findings as ContentReviewFinding[];\n }\n\n try {\n return this.findings ? JSON.parse(this.findings) : [];\n } catch {\n return [];\n }\n }\n\n getMetadata(): Record<string, unknown> {\n if (this.metadata && typeof this.metadata === 'object') {\n return { ...(this.metadata as Record<string, unknown>) };\n }\n\n try {\n return this.metadata ? JSON.parse(this.metadata) : {};\n } catch {\n return {};\n }\n }\n}\n","import { SmrtCollection } from '@happyvertical/smrt-core';\nimport type {\n ContentReviewKind,\n ContentReviewResult,\n} from './content-governance';\nimport { ContentReview } from './content-review';\n\nexport class ContentReviewCollection extends SmrtCollection<ContentReview> {\n static readonly _itemClass = ContentReview;\n\n async listForContent(\n contentId: string,\n kind?: ContentReviewKind,\n ): Promise<ContentReview[]> {\n return this.list({\n where: kind ? { contentId, kind } : { contentId },\n orderBy: 'created_at DESC',\n });\n }\n\n async getLatestForContent(\n contentId: string,\n kind?: ContentReviewKind,\n ): Promise<ContentReview | null> {\n const reviews = await this.listForContent(contentId, kind);\n return reviews[0] ?? null;\n }\n\n async listForContentByPolicyKey(\n contentId: string,\n policyKey: string,\n ): Promise<ContentReview[]> {\n return this.list({\n where: { contentId, policyKey },\n orderBy: 'created_at DESC',\n });\n }\n\n async getLatestForPolicyKey(\n contentId: string,\n policyKey: string,\n ): Promise<ContentReview | null> {\n const reviews = await this.listForContentByPolicyKey(contentId, policyKey);\n return reviews[0] ?? null;\n }\n\n async createFromResult(options: {\n contentId: string;\n contentVersionId?: string | null;\n kind: ContentReviewKind;\n policyKey: string;\n reviewer?: string;\n result: ContentReviewResult;\n metadata?: Record<string, unknown>;\n tenantId?: string | null;\n }): Promise<ContentReview> {\n return this.create({\n contentId: options.contentId,\n contentVersionId: options.contentVersionId || '',\n kind: options.kind,\n policyKey: options.policyKey,\n status: options.result.status,\n summary: options.result.summary,\n findings: JSON.stringify(options.result.findings),\n reviewer: options.reviewer || 'system',\n metadata: JSON.stringify(options.metadata || {}),\n tenantId: options.tenantId ?? null,\n });\n }\n}\n","import type { SmrtObjectOptions } from '@happyvertical/smrt-core';\nimport { foreignKey, SmrtObject, smrt } from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport type { ContentVersionKind } from './content-governance';\nimport { normalizeContentTransparency } from './content-transparency';\n\n/**\n * Shape of the loosely-structured `metadata` JSON bag stored on a content\n * version. Known fields are typed; unrecognized keys remain accessible via the\n * index signature.\n */\nexport interface ContentVersionMetadata {\n /**\n * Fingerprint of the snapshot captured for the latest publication version,\n * used to detect post-publication drift.\n */\n publicationSnapshotFingerprint?: string;\n [key: string]: unknown;\n}\n\nexport interface ContentVersionOptions extends SmrtObjectOptions {\n contentId?: string;\n version?: number;\n kind?: ContentVersionKind;\n title?: string;\n description?: string;\n body?: string;\n status?: string;\n summary?: string;\n snapshot?: string | Record<string, unknown>;\n metadata?: string | Record<string, unknown>;\n tenantId?: string | null;\n createdAt?: Date;\n updatedAt?: Date;\n}\n\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableName: 'content_versions',\n conflictColumns: ['content_id', 'version'],\n api: {\n include: ['list', 'get', 'create', 'getTransparencyAction'],\n routes: {\n getTransparencyAction: { method: 'GET', path: 'transparency' },\n },\n },\n mcp: { include: ['list', 'get', 'create'] },\n cli: true,\n})\nexport class ContentVersion extends SmrtObject {\n @foreignKey('Content', { required: true })\n contentId = '';\n\n version = 1;\n kind: ContentVersionKind = 'manual';\n title = '';\n description = '';\n body = '';\n status = 'draft';\n summary = '';\n snapshot = '{}';\n metadata = '';\n\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n createdAt = new Date();\n updatedAt = new Date();\n\n constructor(options: ContentVersionOptions = {}) {\n super(options);\n if (options.contentId) this.contentId = options.contentId;\n if (options.version !== undefined) this.version = options.version;\n if (options.kind !== undefined) this.kind = options.kind;\n if (options.title !== undefined) this.title = options.title;\n if (options.description !== undefined)\n this.description = options.description;\n if (options.body !== undefined) this.body = options.body;\n if (options.status !== undefined) this.status = options.status;\n if (options.summary !== undefined) this.summary = options.summary;\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n if (options.createdAt) this.createdAt = options.createdAt;\n if (options.updatedAt) this.updatedAt = options.updatedAt;\n\n if (options.snapshot !== undefined) {\n this.snapshot =\n typeof options.snapshot === 'string'\n ? options.snapshot\n : JSON.stringify(options.snapshot);\n }\n\n if (options.metadata !== undefined) {\n this.metadata =\n typeof options.metadata === 'string'\n ? options.metadata\n : JSON.stringify(options.metadata);\n }\n }\n\n getSnapshot(): Record<string, unknown> {\n try {\n return this.snapshot ? JSON.parse(this.snapshot) : {};\n } catch {\n return {};\n }\n }\n\n getMetadata(): ContentVersionMetadata {\n try {\n return this.metadata ? JSON.parse(this.metadata) : {};\n } catch {\n return {};\n }\n }\n\n getTransparency() {\n const metadata = this.getMetadata();\n const snapshot = this.getSnapshot();\n\n return normalizeContentTransparency(metadata.transparency, {\n snapshotKind: this.kind === 'publication' ? 'published' : 'preview',\n contentId: this.contentId || (snapshot.contentId as string) || null,\n currentContentStatus:\n this.status || (snapshot.status as string) || 'draft',\n publicationVersion: {\n id: (this.id as string) || null,\n version: this.version ?? null,\n kind: this.kind || null,\n summary: this.summary || '',\n createdAt:\n this.createdAt instanceof Date ? this.createdAt.toISOString() : null,\n },\n });\n }\n\n async getTransparencyAction() {\n return this.getTransparency();\n }\n}\n","import { SmrtCollection } from '@happyvertical/smrt-core';\nimport type { FactContentRelationship } from '@happyvertical/smrt-facts';\nimport type { Content } from './content';\nimport type { CreateContentVersionOptions } from './content-governance';\nimport { resolveEffectiveContentGovernance } from './content-governance';\nimport { ContentVersion } from './content-version';\n\nexport class ContentVersionCollection extends SmrtCollection<ContentVersion> {\n static readonly _itemClass = ContentVersion;\n\n private buildSnapshotFactRelationships(\n snapshot: Record<string, unknown>,\n defaultRelationship: FactContentRelationship,\n ): Map<FactContentRelationship, string[]> {\n const byRelationship = new Map<FactContentRelationship, string[]>();\n const rawLinks: unknown[] = Array.isArray(snapshot.factLinks)\n ? snapshot.factLinks\n : [];\n\n for (const rawLink of rawLinks) {\n const link = rawLink as {\n factId?: unknown;\n relationship?: unknown;\n } | null;\n const factId =\n typeof link?.factId === 'string' && link.factId.length > 0\n ? link.factId\n : null;\n const relationship =\n typeof link?.relationship === 'string' && link.relationship.length > 0\n ? (link.relationship as FactContentRelationship)\n : defaultRelationship;\n\n if (!factId) {\n continue;\n }\n\n byRelationship.set(relationship, [\n ...(byRelationship.get(relationship) || []),\n factId,\n ]);\n }\n\n if (\n byRelationship.size === 0 &&\n Array.isArray(snapshot.factIds) &&\n snapshot.factIds.length > 0\n ) {\n byRelationship.set(\n defaultRelationship,\n snapshot.factIds.filter(\n (factId: unknown): factId is string =>\n typeof factId === 'string' && factId.length > 0,\n ),\n );\n }\n\n return byRelationship;\n }\n\n async listForContent(contentId: string): Promise<ContentVersion[]> {\n return this.list({\n where: { contentId },\n orderBy: 'version ASC',\n });\n }\n\n async getLatestForContent(contentId: string): Promise<ContentVersion | null> {\n const versions = await this.listForContent(contentId);\n return versions.length > 0 ? versions[versions.length - 1] : null;\n }\n\n async getLatestPublishedForContent(\n contentId: string,\n ): Promise<ContentVersion | null> {\n const versions = await this.list({\n where: {\n contentId,\n kind: 'publication',\n },\n orderBy: 'version DESC',\n });\n\n return versions[0] || null;\n }\n\n async getVersion(\n contentId: string,\n versionNumber: number,\n ): Promise<ContentVersion | null> {\n return this.get({\n contentId,\n version: versionNumber,\n });\n }\n\n async getNextVersionNumber(contentId: string): Promise<number> {\n const latest = await this.getLatestForContent(contentId);\n return latest ? latest.version + 1 : 1;\n }\n\n async createSnapshot(\n content: Content,\n options: CreateContentVersionOptions = {},\n ): Promise<ContentVersion> {\n if (!content.id) {\n throw new Error('Cannot create a version for unsaved content');\n }\n\n const version = await this.getNextVersionNumber(content.id as string);\n const governance = await resolveEffectiveContentGovernance({\n contentType: content.type,\n contentVariant: content.variant,\n db: this.db,\n });\n const [references, referenceEdges, assets, factsState] = await Promise.all([\n typeof content.getReferences === 'function'\n ? content.getReferences()\n : [],\n // Capture per-edge citation pins so restore can reconstruct them.\n // `getReferences()` resolves to Content objects and loses targetVersion.\n typeof content.getReferenceEdges === 'function'\n ? content.getReferenceEdges()\n : Promise.resolve([]),\n typeof content.getAssets === 'function' ? content.getAssets() : [],\n typeof content.getFactsState === 'function' &&\n governance.factLinkingEnabled\n ? content.getFactsState()\n : {\n factIds: [],\n facts: [],\n factLinks: [],\n },\n ]);\n\n const baseSnapshot = {\n id: content.id,\n slug: content.slug,\n context: content.context,\n name: content.name,\n type: content.type,\n variant: content.variant,\n fileKey: content.fileKey,\n author: content.author,\n title: content.title,\n description: content.description,\n body: content.body,\n bodyFormat: content.bodyFormat,\n publish_date: content.publish_date,\n url: content.url,\n source: content.source,\n original_url: content.original_url,\n language: content.language,\n tags: [...content.tags],\n category: content.category,\n status: content.status,\n state: content.state,\n metadata: content.metadata,\n thumbnailAssetId: content.thumbnailAssetId,\n referenceIds: references.map((reference) => reference.id).filter(Boolean),\n // Full edges with citation pins; `referenceIds` retained for back-compat\n // with snapshots written before pin-aware restore (#1387 #3).\n referenceEdges: referenceEdges.filter((edge) => Boolean(edge.targetId)),\n assetIds: assets.map((asset) => asset.id).filter(Boolean),\n factIds: factsState.factIds,\n factLinks: factsState.factLinks,\n tenantId: content.tenantId,\n _meta_type: content.toJSON()._meta_type,\n };\n const snapshot = {\n ...baseSnapshot,\n ...(options.snapshot || {}),\n };\n const versionSlugBase =\n snapshot.slug ||\n content.slug ||\n content.name ||\n content.title ||\n content.id;\n const versionSlug = `${versionSlugBase}-v${version}`;\n\n return this.create({\n slug: versionSlug,\n context: content.context || '',\n contentId: content.id as string,\n version,\n kind: options.kind || 'manual',\n title: snapshot.title || '',\n description: snapshot.description || '',\n body: snapshot.body || '',\n status: snapshot.status || 'draft',\n summary: options.summary || '',\n snapshot: JSON.stringify(snapshot),\n metadata: JSON.stringify(options.metadata || {}),\n tenantId: content.tenantId,\n });\n }\n\n async restoreIntoContent(\n content: Content,\n versionNumber: number,\n ): Promise<Content> {\n if (!content.id) {\n throw new Error('Cannot restore an unsaved content item');\n }\n\n const version = await this.getVersion(content.id as string, versionNumber);\n if (!version) {\n throw new Error(\n `Content version ${versionNumber} not found for content ${content.id}`,\n );\n }\n\n const snapshot = version.getSnapshot();\n const keysToRestore = [\n 'name',\n 'type',\n 'variant',\n 'fileKey',\n 'author',\n 'title',\n 'description',\n 'body',\n 'bodyFormat',\n 'publish_date',\n 'url',\n 'source',\n 'original_url',\n 'language',\n 'tags',\n 'category',\n 'status',\n 'state',\n 'metadata',\n 'thumbnailAssetId',\n ];\n\n // Restore snapshot values onto the live Content instance by field name.\n // Indexing a class instance by an arbitrary string key requires a record\n // view; the keys are a fixed, known set of Content fields.\n const writableContent = content as unknown as Record<string, unknown>;\n for (const key of keysToRestore) {\n if (snapshot[key] !== undefined) {\n writableContent[key] = snapshot[key];\n }\n }\n\n // Reference edges with citation pins (#1387 #3). Newer snapshots carry\n // `referenceEdges` ({ targetId, targetVersion }); older ones only have\n // `referenceIds`. Either way, seed the pending `referenceIds` from the\n // target ids so `save()` reconciles the set (adds missing, removes extra),\n // then re-apply the saved pins below so restoring \"to vN\" reconstructs the\n // citation pins that existed at vN instead of dropping them to unpinned.\n const snapshotEdges: Array<{\n targetId: string;\n targetVersion: number | null;\n }> = Array.isArray(snapshot.referenceEdges)\n ? (snapshot.referenceEdges as unknown[])\n .filter(\n (edge): edge is { targetId: string; targetVersion?: unknown } =>\n !!edge &&\n typeof edge === 'object' &&\n typeof (edge as { targetId?: unknown }).targetId === 'string' &&\n (edge as { targetId: string }).targetId.length > 0,\n )\n .map((edge) => ({\n targetId: edge.targetId,\n targetVersion:\n typeof edge.targetVersion === 'number'\n ? edge.targetVersion\n : null,\n }))\n : Array.isArray(snapshot.referenceIds)\n ? snapshot.referenceIds\n .filter(\n (id: unknown): id is string =>\n typeof id === 'string' && id.length > 0,\n )\n .map((targetId: string) => ({ targetId, targetVersion: null }))\n : [];\n\n if (\n Array.isArray(snapshot.referenceEdges) ||\n Array.isArray(snapshot.referenceIds)\n ) {\n writableContent.referenceIds = snapshotEdges.map((edge) => edge.targetId);\n }\n\n if (Array.isArray(snapshot.assetIds)) {\n writableContent.assetIds = [...snapshot.assetIds];\n }\n\n await content.save();\n\n // Re-apply the citation pin of EVERY snapshot edge — including UNPINNED\n // ones (`targetVersion: null`). `save()` only reconciles the target-id set\n // (adds missing / removes extra edges) and leaves the pin of an edge that\n // already existed untouched. So restoring an *unpinned* snapshot over an\n // edge that is currently *pinned* must explicitly clear that pin, otherwise\n // the live pin survives the restore and drift never resets. Passing\n // `addReference(target, { targetVersion: null })` clears the pin in place\n // (the junction's `attach` updates the row when `null !== existing`), while\n // a non-null value (re)sets it — so \"restore to vN\" reconstructs exactly\n // the pins that existed at vN.\n //\n // We pass the resolved Content object (not the raw id) because\n // `addReference(string)` treats the string as a URL, not a content id.\n // `addReference` is idempotent on (source, target) and only adjusts\n // targetVersion.\n if (\n snapshotEdges.length > 0 &&\n typeof content.getReferences === 'function' &&\n typeof content.addReference === 'function'\n ) {\n const resolvedReferences = await content.getReferences();\n const resolvedById = new Map(\n resolvedReferences\n .filter((reference) => reference.id)\n .map((reference) => [reference.id as string, reference]),\n );\n for (const edge of snapshotEdges) {\n const target = resolvedById.get(edge.targetId);\n if (target) {\n await content.addReference(target, {\n targetVersion: edge.targetVersion,\n });\n }\n }\n }\n\n const governance = await resolveEffectiveContentGovernance({\n contentType: content.type,\n contentVariant: content.variant,\n db: this.db,\n });\n\n if (\n governance.isGoverned &&\n governance.factLinkingEnabled &&\n typeof content.getFactLinks === 'function' &&\n typeof content.syncFacts === 'function'\n ) {\n const desiredByRelationship = this.buildSnapshotFactRelationships(\n snapshot,\n governance.defaultFactRelationship,\n );\n const currentLinks = await content.getFactLinks();\n const currentRelationships = new Set(\n currentLinks.map(\n (link) =>\n (link.relationship as FactContentRelationship) ||\n governance.defaultFactRelationship,\n ),\n );\n const relationshipsToSync = new Set<FactContentRelationship>([\n ...currentRelationships,\n ...desiredByRelationship.keys(),\n ]);\n\n for (const relationship of relationshipsToSync) {\n await content.syncFacts(\n desiredByRelationship.get(relationship) || [],\n relationship,\n );\n }\n }\n\n return content;\n }\n}\n","import yaml from 'yaml';\nimport type { Content } from './content';\n\n/**\n * Converts a Content object to a string with YAML frontmatter\n *\n * @param content - Content object to convert\n * @returns String with YAML frontmatter and body content\n */\nexport function contentToString(content: Content) {\n const { body, ...frontmatter } = content;\n const separator = '---';\n const frontmatterYAML = yaml.stringify(frontmatter);\n return `${separator}\\n${frontmatterYAML}\\n${separator}\\n${body}`;\n}\n\n/**\n * Converts a string with YAML frontmatter to a Content object\n *\n * @param data - String with YAML frontmatter and body content\n * @returns Object with parsed frontmatter and body content\n */\nexport function stringToContent(data: string) {\n const separator = '---';\n const frontmatterStart = data.indexOf(separator);\n\n let frontmatter = {};\n let body = data;\n\n if (frontmatterStart !== -1) {\n const frontmatterEnd = data.indexOf(\n separator,\n frontmatterStart + separator.length,\n );\n\n if (frontmatterEnd !== -1) {\n const frontmatterYAML = data\n .substring(frontmatterStart + separator.length, frontmatterEnd)\n .trim();\n // yaml.parse() THROWS on malformed YAML — `|| {}` only covers an\n // empty/null parse. Wrap so a bad frontmatter block degrades to \"no\n // frontmatter\" instead of crashing the caller (#1387).\n try {\n frontmatter = yaml.parse(frontmatterYAML) || {};\n } catch {\n frontmatter = {};\n }\n body = data.substring(frontmatterEnd + separator.length).trim();\n }\n }\n\n return {\n ...frontmatter,\n body,\n };\n}\n"],"names":["__decorateClass","__publicField","mergeByKey","safeParseJSONObject","safeParseJSONArray","normalizeStatus","asArray","isAIClientOptions","getAI","path","ContentVersionCollection","ContentReviewCollection","ContentCorrectionCollection","Contents","contents","tenantId","stripHtml","parseMetadata","ContentContributionRevisionCollection","ContentContributionAttachmentCollection","ContentContributorCollection","content","defaultOptions","validateEntityName","DEFAULT_XML_ENTITIES","METADATA_SYMBOL","startIndex","xmlNode","result","parseDate","dnsLookup","REDIRECT_STATUSES","YAML","errorMessage"],"mappings":"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","x_google_ignoreList":[29,30,31,32,33,34,35,36,37,38,39,40,41,42,43]}
|