@happyvertical/smrt-content 0.49.3 → 0.49.4

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.
@@ -1,4092 +0,0 @@
1
- import { isContentBodyFormat } from "../body-format.js";
2
- import { DataQueryValidationError, ObjectRegistry, SmrtJunction, SmrtObject, ValidationError, createDataQueryFingerprint, crossPackageRef, field, foreignKey, normalizeDataQueryRequest, normalizeDataQueryResult, normalizeDataQuerySchema, smrt } from "@happyvertical/smrt-core";
3
- import { AssetCollection } from "@happyvertical/smrt-assets";
4
- import { ImageCollection } from "@happyvertical/smrt-images";
5
- import { definePrompt, resolvePrompt } from "@happyvertical/smrt-prompts";
6
- import { TenantScoped, getCurrentTenant, isSuperAdminBypass, isSystemContext, isTenancyEnabled, tenantId } from "@happyvertical/smrt-tenancy";
7
- import { fetchStaticMap } from "@happyvertical/geo";
8
- import { generateHeadlineCard } from "@happyvertical/images";
9
- //#region src/__smrt-register__.ts
10
- ObjectRegistry.registerPackageManifest(JSON.parse("{\"version\":\"1.0.0\",\"timestamp\":0,\"packageName\":\"@happyvertical/smrt-content\",\"packageVersion\":\"0.49.3\",\"objects\":{\"@happyvertical/smrt-content:ContentAsset\":{\"name\":\"contentasset\",\"className\":\"ContentAsset\",\"qualifiedName\":\"@happyvertical/smrt-content:ContentAsset\",\"collection\":\"contentassets\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/content/src/content-asset.ts\",\"packageName\":\"@happyvertical/smrt-content\",\"fields\":{\"tenantId\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"sqlType\":\"UUID\",\"nullable\":true,\"__tenancy\":{\"isTenantIdField\":true,\"autoFilter\":true,\"required\":false,\"autoPopulate\":true,\"nullable\":true,\"mode\":\"optional\",\"field\":\"tenantId\",\"allowSuperAdminBypass\":false}}},\"contentId\":{\"type\":\"foreignKey\",\"required\":true,\"related\":\"Content\",\"_meta\":{\"required\":true}},\"assetId\":{\"type\":\"crossPackageRef\",\"required\":true,\"related\":\"@happyvertical/smrt-assets:Asset\"},\"relationship\":{\"type\":\"text\",\"required\":true,\"_meta\":{\"required\":true}},\"sortOrder\":{\"type\":\"integer\",\"required\":true,\"default\":0}},\"methods\":{},\"decoratorConfig\":{\"tableName\":\"content_assets\",\"conflictColumns\":[\"content_id\",\"asset_id\",\"relationship\"],\"api\":false,\"mcp\":false,\"cli\":false,\"tenantScoped\":{\"mode\":\"optional\"}},\"extends\":\"SmrtObject\",\"exportName\":\"ContentAsset\",\"collectionExportName\":\"ContentAssetCollection\",\"validationRules\":[{\"field\":\"contentId\",\"rule\":\"required\",\"fieldType\":\"foreignKey\"},{\"field\":\"assetId\",\"rule\":\"required\",\"fieldType\":\"crossPackageRef\"},{\"field\":\"relationship\",\"rule\":\"required\",\"fieldType\":\"text\"},{\"field\":\"sortOrder\",\"rule\":\"required\",\"fieldType\":\"integer\"}],\"schema\":{\"tableName\":\"content_assets\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"content_assets\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"tenant_id\\\" UUID,\\n \\\"content_id\\\" UUID NOT NULL,\\n \\\"asset_id\\\" UUID NOT NULL,\\n \\\"relationship\\\" TEXT NOT NULL,\\n \\\"sort_order\\\" INTEGER NOT NULL DEFAULT 0\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"tenantId\",\"notNull\":false,\"unique\":false},\"content_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":true,\"unique\":false,\"foreignKey\":{\"table\":\"contents\",\"column\":\"id\",\"onDelete\":\"CASCADE\",\"onUpdate\":\"CASCADE\"}},\"asset_id\":{\"type\":\"UUID\",\"referenceKind\":\"crossPackageRef\",\"notNull\":true,\"unique\":false},\"relationship\":{\"type\":\"TEXT\",\"notNull\":true,\"unique\":false},\"sort_order\":{\"type\":\"INTEGER\",\"notNull\":true,\"unique\":false,\"default\":0}},\"indexes\":[{\"name\":\"content_assets_content_id_asset_id_idx\",\"columns\":[\"content_id\",\"asset_id\",\"relationship\"],\"unique\":true},{\"name\":\"content_assets_slug_context_idx\",\"columns\":[\"slug\",\"context\"]},{\"name\":\"content_assets_tenant_id_created_at_idx\",\"columns\":[\"tenant_id\",\"created_at\"]},{\"name\":\"content_assets_asset_id_idx\",\"columns\":[\"asset_id\"]}],\"version\":\"472d718d\"}},\"@happyvertical/smrt-content:ContentAssetCollection\":{\"name\":\"contentassetcollection\",\"className\":\"ContentAssetCollection\",\"qualifiedName\":\"@happyvertical/smrt-content:ContentAssetCollection\",\"collection\":\"contentassets\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/content/src/content-assets.ts\",\"packageName\":\"@happyvertical/smrt-content\",\"fields\":{},\"methods\":{\"byLeft\":{\"name\":\"byLeft\",\"async\":true,\"parameters\":[{\"name\":\"leftId\",\"type\":\"string\",\"optional\":false},{\"name\":\"opts\",\"type\":\"JunctionFilterOptions\",\"optional\":true}],\"returnType\":\"Promise<TItem[]>\",\"isStatic\":false,\"isPublic\":true},\"byRight\":{\"name\":\"byRight\",\"async\":true,\"parameters\":[{\"name\":\"rightId\",\"type\":\"string\",\"optional\":false},{\"name\":\"opts\",\"type\":\"JunctionFilterOptions\",\"optional\":true}],\"returnType\":\"Promise<TItem[]>\",\"isStatic\":false,\"isPublic\":true},\"attach\":{\"name\":\"attach\",\"async\":true,\"parameters\":[{\"name\":\"leftId\",\"type\":\"string\",\"optional\":false},{\"name\":\"rightId\",\"type\":\"string\",\"optional\":false},{\"name\":\"opts\",\"type\":\"JunctionAttachOptions\",\"optional\":true}],\"returnType\":\"Promise<TItem>\",\"isStatic\":false,\"isPublic\":true},\"detach\":{\"name\":\"detach\",\"async\":true,\"parameters\":[{\"name\":\"leftId\",\"type\":\"string\",\"optional\":false},{\"name\":\"rightId\",\"type\":\"string\",\"optional\":false},{\"name\":\"opts\",\"type\":\"JunctionFilterOptions\",\"optional\":true}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"setLinks\":{\"name\":\"setLinks\",\"async\":true,\"parameters\":[{\"name\":\"leftId\",\"type\":\"string\",\"optional\":false},{\"name\":\"rightIds\",\"type\":\"string[]\",\"optional\":false},{\"name\":\"opts\",\"type\":\"JunctionAttachOptions\",\"optional\":true}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"api\":false,\"mcp\":false,\"cli\":false,\"tableName\":\"content_assets\"},\"extends\":\"SmrtJunction\",\"extendsTypeArg\":\"ContentAsset\",\"exportName\":\"ContentAssetCollection\",\"collectionExportName\":\"ContentAssetCollectionCollection\",\"schema\":{\"tableName\":\"content_assets\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"content_assets\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"}},\"indexes\":[{\"name\":\"content_assets_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true},{\"name\":\"content_assets_created_at_idx\",\"columns\":[\"created_at\"]}],\"version\":\"35bf42e8\"}},\"@happyvertical/smrt-content:ContentContributionAttachment\":{\"name\":\"contentcontributionattachment\",\"className\":\"ContentContributionAttachment\",\"qualifiedName\":\"@happyvertical/smrt-content:ContentContributionAttachment\",\"collection\":\"contentcontributionattachments\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/content/src/content-contribution-attachment.ts\",\"packageName\":\"@happyvertical/smrt-content\",\"fields\":{\"contributionId\":{\"type\":\"foreignKey\",\"required\":true,\"related\":\"ContentContribution\",\"_meta\":{\"required\":true}},\"revisionId\":{\"type\":\"foreignKey\",\"required\":false,\"related\":\"ContentContributionRevision\"},\"filename\":{\"type\":\"text\",\"required\":false},\"mimeType\":{\"type\":\"text\",\"required\":false},\"size\":{\"type\":\"integer\",\"required\":true,\"default\":0},\"fileKey\":{\"type\":\"text\",\"required\":false},\"sourceUri\":{\"type\":\"text\",\"required\":false},\"channel\":{\"type\":\"text\",\"required\":false,\"default\":\"web\"},\"promotedAssetId\":{\"type\":\"crossPackageRef\",\"required\":false,\"related\":\"@happyvertical/smrt-assets:Asset\"},\"metadata\":{\"type\":\"text\",\"required\":false},\"tenantId\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"sqlType\":\"UUID\",\"nullable\":true,\"__tenancy\":{\"isTenantIdField\":true,\"autoFilter\":true,\"required\":false,\"autoPopulate\":true,\"nullable\":true,\"mode\":\"optional\",\"field\":\"tenantId\",\"allowSuperAdminBypass\":false}}},\"createdAt\":{\"type\":\"text\",\"required\":false},\"updatedAt\":{\"type\":\"text\",\"required\":false}},\"methods\":{\"getMetadata\":{\"name\":\"getMetadata\",\"async\":false,\"parameters\":[],\"returnType\":\"Record<string, unknown>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableName\":\"content_contribution_attachments\",\"conflictColumns\":[\"id\"],\"api\":{\"include\":[\"list\",\"get\",\"create\",\"update\",\"delete\"]},\"mcp\":{\"include\":[\"list\",\"get\",\"create\",\"update\",\"delete\"]},\"cli\":{\"skipApiCheck\":true},\"tenantScoped\":{\"mode\":\"optional\"}},\"extends\":\"SmrtObject\",\"exportName\":\"ContentContributionAttachment\",\"collectionExportName\":\"ContentContributionAttachmentCollection\",\"validationRules\":[{\"field\":\"contributionId\",\"rule\":\"required\",\"fieldType\":\"foreignKey\"},{\"field\":\"size\",\"rule\":\"required\",\"fieldType\":\"integer\"}],\"schema\":{\"tableName\":\"content_contribution_attachments\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"content_contribution_attachments\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"contribution_id\\\" UUID NOT NULL,\\n \\\"revision_id\\\" UUID,\\n \\\"filename\\\" TEXT,\\n \\\"mime_type\\\" TEXT,\\n \\\"size\\\" INTEGER NOT NULL DEFAULT 0,\\n \\\"file_key\\\" TEXT,\\n \\\"source_uri\\\" TEXT,\\n \\\"channel\\\" TEXT DEFAULT 'web',\\n \\\"promoted_asset_id\\\" UUID,\\n \\\"metadata\\\" TEXT,\\n \\\"tenant_id\\\" UUID\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"contribution_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":true,\"unique\":false,\"foreignKey\":{\"table\":\"content_contributions\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"revision_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":false,\"unique\":false,\"foreignKey\":{\"table\":\"content_contribution_revisions\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"filename\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"mime_type\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"size\":{\"type\":\"INTEGER\",\"notNull\":true,\"unique\":false,\"default\":0},\"file_key\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"source_uri\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"channel\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"web\"},\"promoted_asset_id\":{\"type\":\"UUID\",\"referenceKind\":\"crossPackageRef\",\"notNull\":false,\"unique\":false},\"metadata\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"tenantId\",\"notNull\":false,\"unique\":false}},\"indexes\":[{\"name\":\"content_contribution_attachments_slug_context_idx\",\"columns\":[\"slug\",\"context\"]},{\"name\":\"content_contribution_attachments_tenant_id_created_at_idx\",\"columns\":[\"tenant_id\",\"created_at\"]},{\"name\":\"content_contribution_attachments_contribution_id_idx\",\"columns\":[\"contribution_id\"]},{\"name\":\"content_contribution_attachments_revision_id_idx\",\"columns\":[\"revision_id\"]},{\"name\":\"content_contribution_attachments_promoted_asset_id_idx\",\"columns\":[\"promoted_asset_id\"]}],\"version\":\"83e64a1b\"}},\"@happyvertical/smrt-content:ContentContributionAttachmentCollection\":{\"name\":\"contentcontributionattachmentcollection\",\"className\":\"ContentContributionAttachmentCollection\",\"qualifiedName\":\"@happyvertical/smrt-content:ContentContributionAttachmentCollection\",\"collection\":\"contentcontributionattachments\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/content/src/content-contribution-attachments.ts\",\"packageName\":\"@happyvertical/smrt-content\",\"fields\":{},\"methods\":{\"listForContribution\":{\"name\":\"listForContribution\",\"async\":true,\"parameters\":[{\"name\":\"contributionId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<ContentContributionAttachment[]>\",\"isStatic\":false,\"isPublic\":true},\"listForRevision\":{\"name\":\"listForRevision\",\"async\":true,\"parameters\":[{\"name\":\"revisionId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<ContentContributionAttachment[]>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableName\":\"content_contribution_attachments\"},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"ContentContributionAttachment\",\"exportName\":\"ContentContributionAttachmentCollection\",\"collectionExportName\":\"ContentContributionAttachmentCollectionCollection\",\"schema\":{\"tableName\":\"content_contribution_attachments\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"content_contribution_attachments\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"}},\"indexes\":[{\"name\":\"content_contribution_attachments_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true},{\"name\":\"content_contribution_attachments_created_at_idx\",\"columns\":[\"created_at\"]}],\"version\":\"d0c8b33f\"}},\"@happyvertical/smrt-content:ContentContributionRevision\":{\"name\":\"contentcontributionrevision\",\"className\":\"ContentContributionRevision\",\"qualifiedName\":\"@happyvertical/smrt-content:ContentContributionRevision\",\"collection\":\"contentcontributionrevisions\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/content/src/content-contribution-revision.ts\",\"packageName\":\"@happyvertical/smrt-content\",\"fields\":{\"contributionId\":{\"type\":\"foreignKey\",\"required\":true,\"related\":\"ContentContribution\",\"_meta\":{\"required\":true}},\"revisionNumber\":{\"type\":\"integer\",\"required\":true,\"default\":1},\"channel\":{\"type\":\"text\",\"required\":false,\"default\":\"web\"},\"title\":{\"type\":\"text\",\"required\":false},\"description\":{\"type\":\"text\",\"required\":false},\"body\":{\"type\":\"text\",\"required\":false},\"sourceMessageId\":{\"type\":\"crossPackageRef\",\"required\":false,\"related\":\"@happyvertical/smrt-messages:Message\"},\"sourceThreadKey\":{\"type\":\"text\",\"required\":false},\"metadata\":{\"type\":\"text\",\"required\":false},\"tenantId\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"sqlType\":\"UUID\",\"nullable\":true,\"__tenancy\":{\"isTenantIdField\":true,\"autoFilter\":true,\"required\":false,\"autoPopulate\":true,\"nullable\":true,\"mode\":\"optional\",\"field\":\"tenantId\",\"allowSuperAdminBypass\":false}}},\"createdAt\":{\"type\":\"text\",\"required\":false},\"updatedAt\":{\"type\":\"text\",\"required\":false}},\"methods\":{\"getMetadata\":{\"name\":\"getMetadata\",\"async\":false,\"parameters\":[],\"returnType\":\"Record<string, unknown>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableName\":\"content_contribution_revisions\",\"conflictColumns\":[\"contribution_id\",\"revision_number\"],\"api\":{\"include\":[\"list\",\"get\",\"create\",\"update\",\"delete\"]},\"mcp\":{\"include\":[\"list\",\"get\",\"create\",\"update\",\"delete\"]},\"cli\":{\"skipApiCheck\":true},\"tenantScoped\":{\"mode\":\"optional\"}},\"extends\":\"SmrtObject\",\"exportName\":\"ContentContributionRevision\",\"collectionExportName\":\"ContentContributionRevisionCollection\",\"validationRules\":[{\"field\":\"contributionId\",\"rule\":\"required\",\"fieldType\":\"foreignKey\"},{\"field\":\"revisionNumber\",\"rule\":\"required\",\"fieldType\":\"integer\"}],\"schema\":{\"tableName\":\"content_contribution_revisions\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"content_contribution_revisions\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"contribution_id\\\" UUID NOT NULL,\\n \\\"revision_number\\\" INTEGER NOT NULL DEFAULT 1,\\n \\\"channel\\\" TEXT DEFAULT 'web',\\n \\\"title\\\" TEXT,\\n \\\"description\\\" TEXT,\\n \\\"body\\\" TEXT,\\n \\\"source_message_id\\\" UUID,\\n \\\"source_thread_key\\\" TEXT,\\n \\\"metadata\\\" TEXT,\\n \\\"tenant_id\\\" UUID\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"contribution_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":true,\"unique\":false,\"foreignKey\":{\"table\":\"content_contributions\",\"column\":\"id\",\"onDelete\":\"CASCADE\",\"onUpdate\":\"CASCADE\"}},\"revision_number\":{\"type\":\"INTEGER\",\"notNull\":true,\"unique\":false,\"default\":1},\"channel\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"web\"},\"title\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"description\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"body\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"source_message_id\":{\"type\":\"UUID\",\"referenceKind\":\"crossPackageRef\",\"notNull\":false,\"unique\":false},\"source_thread_key\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"metadata\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"tenantId\",\"notNull\":false,\"unique\":false}},\"indexes\":[{\"name\":\"content_contribution_revisions_contribution_id_r_af43e6d599_idx\",\"columns\":[\"contribution_id\",\"revision_number\"],\"unique\":true},{\"name\":\"content_contribution_revisions_slug_context_idx\",\"columns\":[\"slug\",\"context\"]},{\"name\":\"content_contribution_revisions_tenant_id_created_at_idx\",\"columns\":[\"tenant_id\",\"created_at\"]},{\"name\":\"content_contribution_revisions_source_message_id_idx\",\"columns\":[\"source_message_id\"]}],\"version\":\"5051727c\"}},\"@happyvertical/smrt-content:ContentContributionRevisionCollection\":{\"name\":\"contentcontributionrevisioncollection\",\"className\":\"ContentContributionRevisionCollection\",\"qualifiedName\":\"@happyvertical/smrt-content:ContentContributionRevisionCollection\",\"collection\":\"contentcontributionrevisions\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/content/src/content-contribution-revisions.ts\",\"packageName\":\"@happyvertical/smrt-content\",\"fields\":{},\"methods\":{\"listForContribution\":{\"name\":\"listForContribution\",\"async\":true,\"parameters\":[{\"name\":\"contributionId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<ContentContributionRevision[]>\",\"isStatic\":false,\"isPublic\":true},\"getLatestForContribution\":{\"name\":\"getLatestForContribution\",\"async\":true,\"parameters\":[{\"name\":\"contributionId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<ContentContributionRevision | null>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableName\":\"content_contribution_revisions\"},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"ContentContributionRevision\",\"exportName\":\"ContentContributionRevisionCollection\",\"collectionExportName\":\"ContentContributionRevisionCollectionCollection\",\"schema\":{\"tableName\":\"content_contribution_revisions\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"content_contribution_revisions\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"}},\"indexes\":[{\"name\":\"content_contribution_revisions_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true},{\"name\":\"content_contribution_revisions_created_at_idx\",\"columns\":[\"created_at\"]}],\"version\":\"cc3e0dfa\"}},\"@happyvertical/smrt-content:ContentContributionType\":{\"name\":\"contentcontributiontype\",\"className\":\"ContentContributionType\",\"qualifiedName\":\"@happyvertical/smrt-content:ContentContributionType\",\"collection\":\"contentcontributiontypes\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/content/src/content-contribution-type.ts\",\"packageName\":\"@happyvertical/smrt-content\",\"fields\":{\"key\":{\"type\":\"text\",\"required\":true,\"_meta\":{\"required\":true}},\"label\":{\"type\":\"text\",\"required\":false},\"enabled\":{\"type\":\"boolean\",\"required\":true,\"default\":true},\"allowedChannels\":{\"type\":\"text\",\"required\":false},\"allowText\":{\"type\":\"boolean\",\"required\":true,\"default\":true},\"allowFiles\":{\"type\":\"boolean\",\"required\":true,\"default\":false},\"allowEmptyText\":{\"type\":\"boolean\",\"required\":true,\"default\":false},\"intakeRules\":{\"type\":\"text\",\"required\":false},\"promotion\":{\"type\":\"text\",\"required\":false},\"metadata\":{\"type\":\"text\",\"required\":false},\"tenantId\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"sqlType\":\"UUID\",\"nullable\":true,\"__tenancy\":{\"isTenantIdField\":true,\"autoFilter\":true,\"required\":false,\"autoPopulate\":true,\"nullable\":true,\"mode\":\"optional\",\"field\":\"tenantId\",\"allowSuperAdminBypass\":false}}},\"createdAt\":{\"type\":\"text\",\"required\":false},\"updatedAt\":{\"type\":\"text\",\"required\":false}},\"methods\":{\"getAllowedChannels\":{\"name\":\"getAllowedChannels\",\"async\":false,\"parameters\":[],\"returnType\":\"ContentContributionChannel[]\",\"isStatic\":false,\"isPublic\":true},\"setAllowedChannels\":{\"name\":\"setAllowedChannels\",\"async\":false,\"parameters\":[{\"name\":\"channels\",\"type\":\"ContentContributionChannel[]\",\"optional\":false}],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"getIntakeRules\":{\"name\":\"getIntakeRules\",\"async\":false,\"parameters\":[],\"returnType\":\"ContentContributionIntakeRules\",\"isStatic\":false,\"isPublic\":true},\"setIntakeRules\":{\"name\":\"setIntakeRules\",\"async\":false,\"parameters\":[{\"name\":\"rules\",\"type\":\"ContentContributionIntakeRules\",\"optional\":false}],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"getPromotion\":{\"name\":\"getPromotion\",\"async\":false,\"parameters\":[],\"returnType\":\"ContentContributionPromotionMapping\",\"isStatic\":false,\"isPublic\":true},\"setPromotion\":{\"name\":\"setPromotion\",\"async\":false,\"parameters\":[{\"name\":\"promotion\",\"type\":\"ContentContributionPromotionMapping\",\"optional\":false}],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"getMetadata\":{\"name\":\"getMetadata\",\"async\":false,\"parameters\":[],\"returnType\":\"Record<string, unknown>\",\"isStatic\":false,\"isPublic\":true},\"setMetadata\":{\"name\":\"setMetadata\",\"async\":false,\"parameters\":[{\"name\":\"metadata\",\"type\":\"Record<string, unknown>\",\"optional\":false}],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"toDefinition\":{\"name\":\"toDefinition\",\"async\":false,\"parameters\":[],\"returnType\":\"ContentContributionTypeDefinition\",\"isStatic\":false,\"isPublic\":true},\"delete\":{\"name\":\"delete\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableName\":\"content_contribution_types\",\"conflictColumns\":[\"key\"],\"api\":{\"include\":[\"list\",\"get\",\"create\",\"update\",\"delete\"]},\"mcp\":{\"include\":[\"list\",\"get\",\"create\",\"update\",\"delete\"]},\"cli\":{\"skipApiCheck\":true},\"tenantScoped\":{\"mode\":\"optional\"}},\"extends\":\"SmrtObject\",\"exportName\":\"ContentContributionType\",\"collectionExportName\":\"ContentContributionTypeCollection\",\"validationRules\":[{\"field\":\"key\",\"rule\":\"required\",\"fieldType\":\"text\"},{\"field\":\"enabled\",\"rule\":\"required\",\"fieldType\":\"boolean\"},{\"field\":\"allowText\",\"rule\":\"required\",\"fieldType\":\"boolean\"},{\"field\":\"allowFiles\",\"rule\":\"required\",\"fieldType\":\"boolean\"},{\"field\":\"allowEmptyText\",\"rule\":\"required\",\"fieldType\":\"boolean\"}],\"schema\":{\"tableName\":\"content_contribution_types\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"content_contribution_types\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"key\\\" TEXT NOT NULL,\\n \\\"label\\\" TEXT,\\n \\\"enabled\\\" BOOLEAN NOT NULL DEFAULT TRUE,\\n \\\"allowed_channels\\\" TEXT,\\n \\\"allow_text\\\" BOOLEAN NOT NULL DEFAULT TRUE,\\n \\\"allow_files\\\" BOOLEAN NOT NULL DEFAULT FALSE,\\n \\\"allow_empty_text\\\" BOOLEAN NOT NULL DEFAULT FALSE,\\n \\\"intake_rules\\\" TEXT,\\n \\\"promotion\\\" TEXT,\\n \\\"metadata\\\" TEXT,\\n \\\"tenant_id\\\" UUID\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"key\":{\"type\":\"TEXT\",\"notNull\":true,\"unique\":false},\"label\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"enabled\":{\"type\":\"BOOLEAN\",\"notNull\":true,\"unique\":false,\"default\":true},\"allowed_channels\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"allow_text\":{\"type\":\"BOOLEAN\",\"notNull\":true,\"unique\":false,\"default\":true},\"allow_files\":{\"type\":\"BOOLEAN\",\"notNull\":true,\"unique\":false,\"default\":false},\"allow_empty_text\":{\"type\":\"BOOLEAN\",\"notNull\":true,\"unique\":false,\"default\":false},\"intake_rules\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"promotion\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"metadata\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"tenantId\",\"notNull\":false,\"unique\":false}},\"indexes\":[{\"name\":\"content_contribution_types_key_idx\",\"columns\":[\"key\"],\"unique\":true},{\"name\":\"content_contribution_types_slug_context_idx\",\"columns\":[\"slug\",\"context\"]},{\"name\":\"content_contribution_types_tenant_id_created_at_idx\",\"columns\":[\"tenant_id\",\"created_at\"]}],\"version\":\"35552300\"}},\"@happyvertical/smrt-content:ContentContributionTypeCollection\":{\"name\":\"contentcontributiontypecollection\",\"className\":\"ContentContributionTypeCollection\",\"qualifiedName\":\"@happyvertical/smrt-content:ContentContributionTypeCollection\",\"collection\":\"contentcontributiontypes\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/content/src/content-contribution-types.ts\",\"packageName\":\"@happyvertical/smrt-content\",\"fields\":{},\"methods\":{\"getByKey\":{\"name\":\"getByKey\",\"async\":true,\"parameters\":[{\"name\":\"key\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<ContentContributionType | null>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableName\":\"content_contribution_types\"},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"ContentContributionType\",\"exportName\":\"ContentContributionTypeCollection\",\"collectionExportName\":\"ContentContributionTypeCollectionCollection\",\"schema\":{\"tableName\":\"content_contribution_types\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"content_contribution_types\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"}},\"indexes\":[{\"name\":\"content_contribution_types_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true},{\"name\":\"content_contribution_types_created_at_idx\",\"columns\":[\"created_at\"]}],\"version\":\"9c9a0367\"}},\"@happyvertical/smrt-content:ContentContribution\":{\"name\":\"contentcontribution\",\"className\":\"ContentContribution\",\"qualifiedName\":\"@happyvertical/smrt-content:ContentContribution\",\"collection\":\"contentcontributions\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/content/src/content-contribution.ts\",\"packageName\":\"@happyvertical/smrt-content\",\"fields\":{\"contributorId\":{\"type\":\"foreignKey\",\"required\":true,\"related\":\"ContentContributor\",\"_meta\":{\"required\":true}},\"contributionTypeKey\":{\"type\":\"text\",\"required\":true,\"_meta\":{\"required\":true}},\"status\":{\"type\":\"text\",\"required\":false,\"default\":\"submitted\"},\"intakeDecision\":{\"type\":\"text\",\"required\":false,\"default\":\"accepted\"},\"channel\":{\"type\":\"text\",\"required\":false,\"default\":\"web\"},\"title\":{\"type\":\"text\",\"required\":false},\"description\":{\"type\":\"text\",\"required\":false},\"body\":{\"type\":\"text\",\"required\":false},\"contributorEmail\":{\"type\":\"text\",\"required\":false},\"contributorName\":{\"type\":\"text\",\"required\":false},\"threadKey\":{\"type\":\"text\",\"required\":false},\"sourceMessageId\":{\"type\":\"crossPackageRef\",\"required\":false,\"related\":\"@happyvertical/smrt-messages:Message\"},\"editorNotes\":{\"type\":\"text\",\"required\":false},\"promotedContentId\":{\"type\":\"foreignKey\",\"required\":false,\"related\":\"Content\",\"_meta\":{\"nullable\":true}},\"revisionCount\":{\"type\":\"integer\",\"required\":true,\"default\":0},\"approvedAt\":{\"type\":\"datetime\",\"required\":false},\"promotedAt\":{\"type\":\"datetime\",\"required\":false},\"rejectedAt\":{\"type\":\"datetime\",\"required\":false},\"withdrawnAt\":{\"type\":\"datetime\",\"required\":false},\"requestedChangesAt\":{\"type\":\"datetime\",\"required\":false},\"metadata\":{\"type\":\"text\",\"required\":false},\"tenantId\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"sqlType\":\"UUID\",\"nullable\":true,\"__tenancy\":{\"isTenantIdField\":true,\"autoFilter\":true,\"required\":false,\"autoPopulate\":true,\"nullable\":true,\"mode\":\"optional\",\"field\":\"tenantId\",\"allowSuperAdminBypass\":false}}},\"createdAt\":{\"type\":\"text\",\"required\":false},\"updatedAt\":{\"type\":\"text\",\"required\":false}},\"methods\":{\"getMetadata\":{\"name\":\"getMetadata\",\"async\":false,\"parameters\":[],\"returnType\":\"Record<string, unknown>\",\"isStatic\":false,\"isPublic\":true},\"setMetadata\":{\"name\":\"setMetadata\",\"async\":false,\"parameters\":[{\"name\":\"metadata\",\"type\":\"Record<string, unknown>\",\"optional\":false}],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"getContributor\":{\"name\":\"getContributor\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<ContentContributor | null>\",\"isStatic\":false,\"isPublic\":true},\"getRevisions\":{\"name\":\"getRevisions\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<ContentContributionRevision[]>\",\"isStatic\":false,\"isPublic\":true},\"getLatestRevision\":{\"name\":\"getLatestRevision\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<ContentContributionRevision | null>\",\"isStatic\":false,\"isPublic\":true},\"getAttachments\":{\"name\":\"getAttachments\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<ContentContributionAttachment[]>\",\"isStatic\":false,\"isPublic\":true},\"resolveContributionType\":{\"name\":\"resolveContributionType\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<ContentContributionTypeDefinition | null>\",\"isStatic\":false,\"isPublic\":true},\"appendRevisionAction\":{\"name\":\"appendRevisionAction\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"AppendContentContributionRevisionOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"requestChangesAction\":{\"name\":\"requestChangesAction\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"RequestChangesContentContributionOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"rejectAction\":{\"name\":\"rejectAction\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"RejectContentContributionOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"withdrawAction\":{\"name\":\"withdrawAction\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"WithdrawContentContributionOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"approveAction\":{\"name\":\"approveAction\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"ApproveContentContributionOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"promoteAction\":{\"name\":\"promoteAction\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"PromoteContentContributionOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableName\":\"content_contributions\",\"conflictColumns\":[\"id\"],\"api\":{\"include\":[\"list\",\"get\",\"create\",\"update\",\"delete\",\"appendRevisionAction\",\"requestChangesAction\",\"approveAction\",\"rejectAction\",\"withdrawAction\",\"promoteAction\"],\"routes\":{\"appendRevisionAction\":{\"method\":\"POST\",\"path\":\"revisions\"},\"requestChangesAction\":{\"method\":\"POST\",\"path\":\"request-changes\"},\"approveAction\":{\"method\":\"POST\",\"path\":\"approve\"},\"rejectAction\":{\"method\":\"POST\",\"path\":\"reject\"},\"withdrawAction\":{\"method\":\"POST\",\"path\":\"withdraw\"},\"promoteAction\":{\"method\":\"POST\",\"path\":\"promote\"}}},\"mcp\":{\"include\":[\"list\",\"get\",\"create\",\"update\"]},\"cli\":{\"skipApiCheck\":true},\"tenantScoped\":{\"mode\":\"optional\"}},\"extends\":\"SmrtObject\",\"exportName\":\"ContentContribution\",\"collectionExportName\":\"ContentContributionCollection\",\"validationRules\":[{\"field\":\"contributorId\",\"rule\":\"required\",\"fieldType\":\"foreignKey\"},{\"field\":\"contributionTypeKey\",\"rule\":\"required\",\"fieldType\":\"text\"},{\"field\":\"revisionCount\",\"rule\":\"required\",\"fieldType\":\"integer\"}],\"schema\":{\"tableName\":\"content_contributions\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"content_contributions\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"contributor_id\\\" UUID NOT NULL,\\n \\\"contribution_type_key\\\" TEXT NOT NULL,\\n \\\"status\\\" TEXT DEFAULT 'submitted',\\n \\\"intake_decision\\\" TEXT DEFAULT 'accepted',\\n \\\"channel\\\" TEXT DEFAULT 'web',\\n \\\"title\\\" TEXT,\\n \\\"description\\\" TEXT,\\n \\\"body\\\" TEXT,\\n \\\"contributor_email\\\" TEXT,\\n \\\"contributor_name\\\" TEXT,\\n \\\"thread_key\\\" TEXT,\\n \\\"source_message_id\\\" UUID,\\n \\\"editor_notes\\\" TEXT,\\n \\\"promoted_content_id\\\" UUID,\\n \\\"revision_count\\\" INTEGER NOT NULL DEFAULT 0,\\n \\\"approved_at\\\" TIMESTAMP,\\n \\\"promoted_at\\\" TIMESTAMP,\\n \\\"rejected_at\\\" TIMESTAMP,\\n \\\"withdrawn_at\\\" TIMESTAMP,\\n \\\"requested_changes_at\\\" TIMESTAMP,\\n \\\"metadata\\\" TEXT,\\n \\\"tenant_id\\\" UUID\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"contributor_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":true,\"unique\":false,\"foreignKey\":{\"table\":\"content_contributors\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"contribution_type_key\":{\"type\":\"TEXT\",\"notNull\":true,\"unique\":false},\"status\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"submitted\"},\"intake_decision\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"accepted\"},\"channel\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"web\"},\"title\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"description\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"body\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"contributor_email\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"contributor_name\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"thread_key\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"source_message_id\":{\"type\":\"UUID\",\"referenceKind\":\"crossPackageRef\",\"notNull\":false,\"unique\":false},\"editor_notes\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"promoted_content_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":false,\"unique\":false,\"foreignKey\":{\"table\":\"contents\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"revision_count\":{\"type\":\"INTEGER\",\"notNull\":true,\"unique\":false,\"default\":0},\"approved_at\":{\"type\":\"TIMESTAMP\",\"notNull\":false,\"unique\":false},\"promoted_at\":{\"type\":\"TIMESTAMP\",\"notNull\":false,\"unique\":false},\"rejected_at\":{\"type\":\"TIMESTAMP\",\"notNull\":false,\"unique\":false},\"withdrawn_at\":{\"type\":\"TIMESTAMP\",\"notNull\":false,\"unique\":false},\"requested_changes_at\":{\"type\":\"TIMESTAMP\",\"notNull\":false,\"unique\":false},\"metadata\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"tenantId\",\"notNull\":false,\"unique\":false}},\"indexes\":[{\"name\":\"content_contributions_slug_context_idx\",\"columns\":[\"slug\",\"context\"]},{\"name\":\"content_contributions_tenant_id_created_at_idx\",\"columns\":[\"tenant_id\",\"created_at\"]},{\"name\":\"content_contributions_contributor_id_idx\",\"columns\":[\"contributor_id\"]},{\"name\":\"content_contributions_source_message_id_idx\",\"columns\":[\"source_message_id\"]},{\"name\":\"content_contributions_promoted_content_id_idx\",\"columns\":[\"promoted_content_id\"]}],\"version\":\"ef8fd792\"}},\"@happyvertical/smrt-content:ContentContributions\":{\"name\":\"contentcontributions\",\"className\":\"ContentContributions\",\"qualifiedName\":\"@happyvertical/smrt-content:ContentContributions\",\"collection\":\"contentcontributions\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/content/src/content-contributions.ts\",\"packageName\":\"@happyvertical/smrt-content\",\"fields\":{},\"methods\":{\"getContributionTypesAction\":{\"name\":\"getContributionTypesAction\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":true,\"memberTypes\":[\"string | null\"]}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"listForContributor\":{\"name\":\"listForContributor\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":true,\"memberTypes\":[\"string\",\"string | null\"]}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"listInboxAction\":{\"name\":\"listInboxAction\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":true,\"memberTypes\":[\"string | string[]\",\"string | null\"]}],\"returnType\":\"Promise<ContentContribution[]>\",\"isStatic\":false,\"isPublic\":true},\"submitWebContribution\":{\"name\":\"submitWebContribution\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"SubmitWebContentContributionOptions\",\"optional\":false}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"ingestEmailContribution\":{\"name\":\"ingestEmailContribution\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"IngestEmailContentContributionOptions\",\"optional\":false}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"api\":{\"include\":[\"submitWebContribution\",\"ingestEmailContribution\",\"listForContributor\",\"listInboxAction\",\"getContributionTypesAction\"],\"routes\":{\"submitWebContribution\":{\"scope\":\"collection\",\"method\":\"POST\",\"path\":\"submit\"},\"ingestEmailContribution\":{\"scope\":\"collection\",\"method\":\"POST\",\"path\":\"ingest-email\"},\"listForContributor\":{\"scope\":\"collection\",\"method\":\"GET\",\"path\":\"by-contributor\"},\"listInboxAction\":{\"scope\":\"collection\",\"method\":\"GET\",\"path\":\"inbox\"},\"getContributionTypesAction\":{\"scope\":\"collection\",\"method\":\"GET\",\"path\":\"types\"}}},\"mcp\":false,\"cli\":false,\"tableName\":\"content_contributions\"},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"ContentContribution\",\"exportName\":\"ContentContributions\",\"collectionExportName\":\"ContentContributionsCollection\",\"schema\":{\"tableName\":\"content_contributions\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"content_contributions\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"}},\"indexes\":[{\"name\":\"content_contributions_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true},{\"name\":\"content_contributions_created_at_idx\",\"columns\":[\"created_at\"]}],\"version\":\"641c0cc8\"}},\"@happyvertical/smrt-content:ContentContributor\":{\"name\":\"contentcontributor\",\"className\":\"ContentContributor\",\"qualifiedName\":\"@happyvertical/smrt-content:ContentContributor\",\"collection\":\"contentcontributors\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/content/src/content-contributor.ts\",\"packageName\":\"@happyvertical/smrt-content\",\"fields\":{\"profileId\":{\"type\":\"crossPackageRef\",\"required\":false,\"related\":\"@happyvertical/smrt-profiles:Profile\"},\"email\":{\"type\":\"text\",\"required\":true,\"_meta\":{\"required\":true}},\"name\":{\"type\":\"text\",\"required\":false},\"trustLevel\":{\"type\":\"text\",\"required\":false,\"default\":\"standard\"},\"metadata\":{\"type\":\"text\",\"required\":false},\"tenantId\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"sqlType\":\"UUID\",\"nullable\":true,\"__tenancy\":{\"isTenantIdField\":true,\"autoFilter\":true,\"required\":false,\"autoPopulate\":true,\"nullable\":true,\"mode\":\"optional\",\"field\":\"tenantId\",\"allowSuperAdminBypass\":false}}},\"createdAt\":{\"type\":\"text\",\"required\":false},\"updatedAt\":{\"type\":\"text\",\"required\":false}},\"methods\":{\"getMetadata\":{\"name\":\"getMetadata\",\"async\":false,\"parameters\":[],\"returnType\":\"Record<string, unknown>\",\"isStatic\":false,\"isPublic\":true},\"setMetadata\":{\"name\":\"setMetadata\",\"async\":false,\"parameters\":[{\"name\":\"metadata\",\"type\":\"Record<string, unknown>\",\"optional\":false}],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableName\":\"content_contributors\",\"conflictColumns\":[\"email\"],\"api\":{\"include\":[\"list\",\"get\",\"create\",\"update\",\"delete\"]},\"mcp\":{\"include\":[\"list\",\"get\",\"create\",\"update\",\"delete\"]},\"cli\":{\"skipApiCheck\":true},\"tenantScoped\":{\"mode\":\"optional\"}},\"extends\":\"SmrtObject\",\"exportName\":\"ContentContributor\",\"collectionExportName\":\"ContentContributorCollection\",\"validationRules\":[{\"field\":\"email\",\"rule\":\"required\",\"fieldType\":\"text\"}],\"schema\":{\"tableName\":\"content_contributors\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"content_contributors\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"profile_id\\\" UUID,\\n \\\"email\\\" TEXT NOT NULL,\\n \\\"name\\\" TEXT,\\n \\\"trust_level\\\" TEXT DEFAULT 'standard',\\n \\\"metadata\\\" TEXT,\\n \\\"tenant_id\\\" UUID\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"profile_id\":{\"type\":\"UUID\",\"referenceKind\":\"crossPackageRef\",\"notNull\":false,\"unique\":false},\"email\":{\"type\":\"TEXT\",\"notNull\":true,\"unique\":false},\"name\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"trust_level\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"standard\"},\"metadata\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"tenantId\",\"notNull\":false,\"unique\":false}},\"indexes\":[{\"name\":\"content_contributors_email_idx\",\"columns\":[\"email\"],\"unique\":true},{\"name\":\"content_contributors_slug_context_idx\",\"columns\":[\"slug\",\"context\"]},{\"name\":\"content_contributors_tenant_id_created_at_idx\",\"columns\":[\"tenant_id\",\"created_at\"]},{\"name\":\"content_contributors_profile_id_idx\",\"columns\":[\"profile_id\"]}],\"version\":\"7eb9c661\"}},\"@happyvertical/smrt-content:ContentContributorCollection\":{\"name\":\"contentcontributorcollection\",\"className\":\"ContentContributorCollection\",\"qualifiedName\":\"@happyvertical/smrt-content:ContentContributorCollection\",\"collection\":\"contentcontributors\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/content/src/content-contributors.ts\",\"packageName\":\"@happyvertical/smrt-content\",\"fields\":{},\"methods\":{\"getByEmail\":{\"name\":\"getByEmail\",\"async\":true,\"parameters\":[{\"name\":\"email\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<ContentContributor | null>\",\"isStatic\":false,\"isPublic\":true},\"getByProfileId\":{\"name\":\"getByProfileId\",\"async\":true,\"parameters\":[{\"name\":\"profileId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<ContentContributor | null>\",\"isStatic\":false,\"isPublic\":true},\"findOrCreateByEmail\":{\"name\":\"findOrCreateByEmail\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":false,\"memberTypes\":[\"string\",\"string | null\"]}],\"returnType\":\"Promise<ContentContributor>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableName\":\"content_contributors\"},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"ContentContributor\",\"exportName\":\"ContentContributorCollection\",\"collectionExportName\":\"ContentContributorCollectionCollection\",\"schema\":{\"tableName\":\"content_contributors\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"content_contributors\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"}},\"indexes\":[{\"name\":\"content_contributors_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true},{\"name\":\"content_contributors_created_at_idx\",\"columns\":[\"created_at\"]}],\"version\":\"b457e60b\"}},\"@happyvertical/smrt-content:ContentCorrection\":{\"name\":\"contentcorrection\",\"className\":\"ContentCorrection\",\"qualifiedName\":\"@happyvertical/smrt-content:ContentCorrection\",\"collection\":\"contentcorrections\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/content/src/content-correction.ts\",\"packageName\":\"@happyvertical/smrt-content\",\"fields\":{\"contentId\":{\"type\":\"foreignKey\",\"required\":true,\"related\":\"Content\",\"_meta\":{\"required\":true}},\"contentVersionId\":{\"type\":\"foreignKey\",\"required\":false,\"related\":\"ContentVersion\"},\"factId\":{\"type\":\"crossPackageRef\",\"required\":false,\"related\":\"@happyvertical/smrt-facts:Fact\"},\"replacementFactId\":{\"type\":\"crossPackageRef\",\"required\":false,\"related\":\"@happyvertical/smrt-facts:Fact\"},\"correctionType\":{\"type\":\"text\",\"required\":false,\"default\":\"fact\"},\"status\":{\"type\":\"text\",\"required\":false,\"default\":\"draft\"},\"summary\":{\"type\":\"text\",\"required\":false},\"incorrectText\":{\"type\":\"text\",\"required\":false},\"correctedText\":{\"type\":\"text\",\"required\":false},\"publicNote\":{\"type\":\"text\",\"required\":false},\"metadata\":{\"type\":\"text\",\"required\":false},\"tenantId\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"sqlType\":\"UUID\",\"nullable\":true,\"__tenancy\":{\"isTenantIdField\":true,\"autoFilter\":true,\"required\":false,\"autoPopulate\":true,\"nullable\":true,\"mode\":\"optional\",\"field\":\"tenantId\",\"allowSuperAdminBypass\":false}}},\"publishedAt\":{\"type\":\"datetime\",\"required\":false},\"createdAt\":{\"type\":\"text\",\"required\":false},\"updatedAt\":{\"type\":\"text\",\"required\":false}},\"methods\":{\"getMetadata\":{\"name\":\"getMetadata\",\"async\":false,\"parameters\":[],\"returnType\":\"Record<string, unknown>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableName\":\"content_corrections\",\"api\":{\"include\":[\"list\",\"get\",\"create\",\"update\"]},\"mcp\":{\"include\":[\"list\",\"get\",\"create\",\"update\"]},\"cli\":{\"skipApiCheck\":true},\"tenantScoped\":{\"mode\":\"optional\"},\"conflictColumns\":[\"tenant_id\",\"slug\",\"context\"]},\"extends\":\"SmrtObject\",\"exportName\":\"ContentCorrection\",\"collectionExportName\":\"ContentCorrectionCollection\",\"validationRules\":[{\"field\":\"contentId\",\"rule\":\"required\",\"fieldType\":\"foreignKey\"}],\"schema\":{\"tableName\":\"content_corrections\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"content_corrections\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"content_id\\\" UUID NOT NULL,\\n \\\"content_version_id\\\" UUID,\\n \\\"fact_id\\\" UUID,\\n \\\"replacement_fact_id\\\" UUID,\\n \\\"correction_type\\\" TEXT DEFAULT 'fact',\\n \\\"status\\\" TEXT DEFAULT 'draft',\\n \\\"summary\\\" TEXT,\\n \\\"incorrect_text\\\" TEXT,\\n \\\"corrected_text\\\" TEXT,\\n \\\"public_note\\\" TEXT,\\n \\\"metadata\\\" TEXT,\\n \\\"tenant_id\\\" UUID,\\n \\\"published_at\\\" TIMESTAMP\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"content_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":true,\"unique\":false,\"foreignKey\":{\"table\":\"contents\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"content_version_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":false,\"unique\":false,\"foreignKey\":{\"table\":\"content_versions\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"fact_id\":{\"type\":\"UUID\",\"referenceKind\":\"crossPackageRef\",\"notNull\":false,\"unique\":false},\"replacement_fact_id\":{\"type\":\"UUID\",\"referenceKind\":\"crossPackageRef\",\"notNull\":false,\"unique\":false},\"correction_type\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"fact\"},\"status\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"draft\"},\"summary\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"incorrect_text\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"corrected_text\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"public_note\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"metadata\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"tenantId\",\"notNull\":false,\"unique\":false},\"published_at\":{\"type\":\"TIMESTAMP\",\"notNull\":false,\"unique\":false}},\"indexes\":[{\"name\":\"content_corrections_slug_context_idx\",\"columns\":[\"tenant_id\",\"slug\",\"context\"],\"unique\":true},{\"name\":\"content_corrections_tenant_id_created_at_idx\",\"columns\":[\"tenant_id\",\"created_at\"]},{\"name\":\"content_corrections_content_id_idx\",\"columns\":[\"content_id\"]},{\"name\":\"content_corrections_content_version_id_idx\",\"columns\":[\"content_version_id\"]},{\"name\":\"content_corrections_fact_id_idx\",\"columns\":[\"fact_id\"]},{\"name\":\"content_corrections_replacement_fact_id_idx\",\"columns\":[\"replacement_fact_id\"]}],\"version\":\"bf2808c7\"}},\"@happyvertical/smrt-content:ContentCorrectionCollection\":{\"name\":\"contentcorrectioncollection\",\"className\":\"ContentCorrectionCollection\",\"qualifiedName\":\"@happyvertical/smrt-content:ContentCorrectionCollection\",\"collection\":\"contentcorrections\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/content/src/content-corrections.ts\",\"packageName\":\"@happyvertical/smrt-content\",\"fields\":{},\"methods\":{\"listForContent\":{\"name\":\"listForContent\",\"async\":true,\"parameters\":[{\"name\":\"contentId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<ContentCorrection[]>\",\"isStatic\":false,\"isPublic\":true},\"getPublishedForContent\":{\"name\":\"getPublishedForContent\",\"async\":true,\"parameters\":[{\"name\":\"contentId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<ContentCorrection[]>\",\"isStatic\":false,\"isPublic\":true},\"issue\":{\"name\":\"issue\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"any\",\"optional\":false,\"typeUnresolved\":true}],\"returnType\":\"Promise<ContentCorrection>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableName\":\"content_corrections\"},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"ContentCorrection\",\"exportName\":\"ContentCorrectionCollection\",\"collectionExportName\":\"ContentCorrectionCollectionCollection\",\"schema\":{\"tableName\":\"content_corrections\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"content_corrections\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"}},\"indexes\":[{\"name\":\"content_corrections_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true},{\"name\":\"content_corrections_created_at_idx\",\"columns\":[\"created_at\"]}],\"version\":\"6ebe142d\"}},\"@happyvertical/smrt-content:ContentFeedSource\":{\"name\":\"contentfeedsource\",\"className\":\"ContentFeedSource\",\"qualifiedName\":\"@happyvertical/smrt-content:ContentFeedSource\",\"collection\":\"contentfeedsources\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/content/src/content-feed-source.ts\",\"packageName\":\"@happyvertical/smrt-content\",\"fields\":{\"tenantId\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"sqlType\":\"UUID\",\"nullable\":true,\"__tenancy\":{\"isTenantIdField\":true,\"autoFilter\":true,\"required\":false,\"autoPopulate\":true,\"nullable\":true,\"mode\":\"optional\",\"field\":\"tenantId\",\"allowSuperAdminBypass\":false}}},\"name\":{\"type\":\"text\",\"required\":true,\"_meta\":{\"required\":true}},\"feedUrl\":{\"type\":\"text\",\"required\":true,\"_meta\":{\"required\":true}},\"homepageUrl\":{\"type\":\"text\",\"required\":false},\"format\":{\"type\":\"text\",\"required\":false},\"status\":{\"type\":\"text\",\"required\":true,\"default\":\"active\",\"_meta\":{\"required\":true,\"default\":\"active\"}},\"defaultCategory\":{\"type\":\"text\",\"required\":false},\"sourceGroup\":{\"type\":\"text\",\"required\":false},\"pollIntervalMinutes\":{\"type\":\"integer\",\"required\":true,\"default\":15},\"etag\":{\"type\":\"text\",\"required\":false},\"lastModified\":{\"type\":\"text\",\"required\":false},\"lastFetchedAt\":{\"type\":\"datetime\",\"required\":false},\"lastSuccessAt\":{\"type\":\"datetime\",\"required\":false},\"lastError\":{\"type\":\"text\",\"required\":false},\"metadata\":{\"type\":\"json\",\"required\":false,\"default\":{}},\"createdAt\":{\"type\":\"text\",\"required\":false},\"updatedAt\":{\"type\":\"text\",\"required\":false}},\"methods\":{\"getMetadata\":{\"name\":\"getMetadata\",\"async\":false,\"parameters\":[],\"returnType\":\"Record<string, unknown>\",\"isStatic\":false,\"isPublic\":true},\"setMetadata\":{\"name\":\"setMetadata\",\"async\":false,\"parameters\":[{\"name\":\"metadata\",\"type\":\"Record<string, unknown>\",\"optional\":false}],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"markFetchStarted\":{\"name\":\"markFetchStarted\",\"async\":false,\"parameters\":[{\"name\":\"at\",\"type\":\"any\",\"optional\":true}],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"markFetchSucceeded\":{\"name\":\"markFetchSucceeded\",\"async\":false,\"parameters\":[{\"name\":\"at\",\"type\":\"any\",\"optional\":true},{\"name\":\"headers\",\"type\":\"object\",\"optional\":true,\"memberTypes\":[\"string | null\"]}],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"markFetchFailed\":{\"name\":\"markFetchFailed\",\"async\":false,\"parameters\":[{\"name\":\"error\",\"type\":\"unknown\",\"optional\":false},{\"name\":\"at\",\"type\":\"any\",\"optional\":true}],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableName\":\"content_feed_sources\",\"conflictColumns\":[\"tenant_id\",\"feed_url\"],\"api\":{\"include\":[\"list\",\"get\",\"create\",\"update\",\"delete\"]},\"mcp\":{\"include\":[\"list\",\"get\",\"create\",\"update\",\"delete\"]},\"cli\":{\"skipApiCheck\":true},\"tenantScoped\":{\"mode\":\"optional\"}},\"extends\":\"SmrtObject\",\"exportName\":\"ContentFeedSource\",\"collectionExportName\":\"ContentFeedSourceCollection\",\"validationRules\":[{\"field\":\"name\",\"rule\":\"required\",\"fieldType\":\"text\"},{\"field\":\"feedUrl\",\"rule\":\"required\",\"fieldType\":\"text\"},{\"field\":\"status\",\"rule\":\"required\",\"fieldType\":\"text\"},{\"field\":\"pollIntervalMinutes\",\"rule\":\"required\",\"fieldType\":\"integer\"}],\"schema\":{\"tableName\":\"content_feed_sources\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"content_feed_sources\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"tenant_id\\\" UUID,\\n \\\"name\\\" TEXT NOT NULL,\\n \\\"feed_url\\\" TEXT NOT NULL,\\n \\\"homepage_url\\\" TEXT,\\n \\\"format\\\" TEXT,\\n \\\"status\\\" TEXT NOT NULL DEFAULT 'active',\\n \\\"default_category\\\" TEXT,\\n \\\"source_group\\\" TEXT,\\n \\\"poll_interval_minutes\\\" INTEGER NOT NULL DEFAULT 15,\\n \\\"etag\\\" TEXT,\\n \\\"last_modified\\\" TEXT,\\n \\\"last_fetched_at\\\" TIMESTAMP,\\n \\\"last_success_at\\\" TIMESTAMP,\\n \\\"last_error\\\" TEXT,\\n \\\"metadata\\\" JSON DEFAULT '{}'\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"tenantId\",\"notNull\":false,\"unique\":false},\"name\":{\"type\":\"TEXT\",\"notNull\":true,\"unique\":false},\"feed_url\":{\"type\":\"TEXT\",\"notNull\":true,\"unique\":false},\"homepage_url\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"format\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"status\":{\"type\":\"TEXT\",\"notNull\":true,\"unique\":false,\"default\":\"active\"},\"default_category\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"source_group\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"poll_interval_minutes\":{\"type\":\"INTEGER\",\"notNull\":true,\"unique\":false,\"default\":15},\"etag\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"last_modified\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"last_fetched_at\":{\"type\":\"TIMESTAMP\",\"notNull\":false,\"unique\":false},\"last_success_at\":{\"type\":\"TIMESTAMP\",\"notNull\":false,\"unique\":false},\"last_error\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"metadata\":{\"type\":\"JSON\",\"notNull\":false,\"unique\":false,\"default\":{}}},\"indexes\":[{\"name\":\"content_feed_sources_tenant_id_feed_url_idx\",\"columns\":[\"tenant_id\",\"feed_url\"],\"unique\":true},{\"name\":\"content_feed_sources_slug_context_idx\",\"columns\":[\"slug\",\"context\"]},{\"name\":\"content_feed_sources_tenant_id_created_at_idx\",\"columns\":[\"tenant_id\",\"created_at\"]}],\"version\":\"bbcb36e5\"}},\"@happyvertical/smrt-content:ContentFeedSourceCollection\":{\"name\":\"contentfeedsourcecollection\",\"className\":\"ContentFeedSourceCollection\",\"qualifiedName\":\"@happyvertical/smrt-content:ContentFeedSourceCollection\",\"collection\":\"contentfeedsources\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/content/src/content-feed-sources.ts\",\"packageName\":\"@happyvertical/smrt-content\",\"fields\":{},\"methods\":{\"findActive\":{\"name\":\"findActive\",\"async\":true,\"parameters\":[{\"name\":\"tenantId\",\"type\":\"string | null\",\"optional\":true,\"unionBranches\":[{\"type\":\"string\"},{\"type\":\"null\"}]}],\"returnType\":\"Promise<ContentFeedSource[]>\",\"isStatic\":false,\"isPublic\":true},\"findByStatus\":{\"name\":\"findByStatus\",\"async\":true,\"parameters\":[{\"name\":\"status\",\"type\":\"ContentFeedSourceStatus\",\"optional\":false},{\"name\":\"tenantId\",\"type\":\"string | null\",\"optional\":true,\"unionBranches\":[{\"type\":\"string\"},{\"type\":\"null\"}]}],\"returnType\":\"Promise<ContentFeedSource[]>\",\"isStatic\":false,\"isPublic\":true},\"findByFeedUrl\":{\"name\":\"findByFeedUrl\",\"async\":true,\"parameters\":[{\"name\":\"feedUrl\",\"type\":\"string\",\"optional\":false},{\"name\":\"tenantId\",\"type\":\"string | null\",\"optional\":true,\"unionBranches\":[{\"type\":\"string\"},{\"type\":\"null\"}]}],\"returnType\":\"Promise<ContentFeedSource | null>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableName\":\"content_feed_sources\"},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"ContentFeedSource\",\"exportName\":\"ContentFeedSourceCollection\",\"collectionExportName\":\"ContentFeedSourceCollectionCollection\",\"schema\":{\"tableName\":\"content_feed_sources\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"content_feed_sources\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"}},\"indexes\":[{\"name\":\"content_feed_sources_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true},{\"name\":\"content_feed_sources_created_at_idx\",\"columns\":[\"created_at\"]}],\"version\":\"bb0cca9e\"}},\"@happyvertical/smrt-content:ContentGovernanceAssignment\":{\"name\":\"contentgovernanceassignment\",\"className\":\"ContentGovernanceAssignment\",\"qualifiedName\":\"@happyvertical/smrt-content:ContentGovernanceAssignment\",\"collection\":\"contentgovernanceassignments\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/content/src/content-governance-assignment.ts\",\"packageName\":\"@happyvertical/smrt-content\",\"fields\":{\"key\":{\"type\":\"text\",\"required\":true,\"_meta\":{\"required\":true}},\"label\":{\"type\":\"text\",\"required\":false},\"contentType\":{\"type\":\"text\",\"required\":true,\"_meta\":{\"required\":true}},\"contentVariant\":{\"type\":\"text\",\"required\":false},\"enabled\":{\"type\":\"boolean\",\"required\":true,\"default\":true},\"factLinkingEnabled\":{\"type\":\"boolean\",\"required\":true,\"default\":false},\"transparencyEnabled\":{\"type\":\"boolean\",\"required\":true,\"default\":false},\"publicationProfileKey\":{\"type\":\"text\",\"required\":false},\"correctionProfileKey\":{\"type\":\"text\",\"required\":false},\"enforcePublishReadiness\":{\"type\":\"boolean\",\"required\":true,\"default\":false},\"defaultFactRelationship\":{\"type\":\"text\",\"required\":false,\"default\":\"supports\"},\"metadata\":{\"type\":\"text\",\"required\":false},\"tenantId\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"sqlType\":\"UUID\",\"nullable\":true,\"__tenancy\":{\"isTenantIdField\":true,\"autoFilter\":true,\"required\":false,\"autoPopulate\":true,\"nullable\":true,\"mode\":\"optional\",\"field\":\"tenantId\",\"allowSuperAdminBypass\":false}}},\"createdAt\":{\"type\":\"text\",\"required\":false},\"updatedAt\":{\"type\":\"text\",\"required\":false}},\"methods\":{\"getMetadata\":{\"name\":\"getMetadata\",\"async\":false,\"parameters\":[],\"returnType\":\"Record<string, unknown>\",\"isStatic\":false,\"isPublic\":true},\"toDefinition\":{\"name\":\"toDefinition\",\"async\":false,\"parameters\":[],\"returnType\":\"ContentGovernanceAssignmentDefinition\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableName\":\"content_governance_assignments\",\"conflictColumns\":[\"key\"],\"api\":{\"include\":[\"list\",\"get\",\"create\",\"update\",\"delete\"]},\"mcp\":{\"include\":[\"list\",\"get\",\"create\",\"update\",\"delete\"]},\"cli\":{\"skipApiCheck\":true},\"tenantScoped\":{\"mode\":\"optional\"}},\"extends\":\"SmrtObject\",\"exportName\":\"ContentGovernanceAssignment\",\"collectionExportName\":\"ContentGovernanceAssignmentCollection\",\"validationRules\":[{\"field\":\"key\",\"rule\":\"required\",\"fieldType\":\"text\"},{\"field\":\"contentType\",\"rule\":\"required\",\"fieldType\":\"text\"},{\"field\":\"enabled\",\"rule\":\"required\",\"fieldType\":\"boolean\"},{\"field\":\"factLinkingEnabled\",\"rule\":\"required\",\"fieldType\":\"boolean\"},{\"field\":\"transparencyEnabled\",\"rule\":\"required\",\"fieldType\":\"boolean\"},{\"field\":\"enforcePublishReadiness\",\"rule\":\"required\",\"fieldType\":\"boolean\"}],\"schema\":{\"tableName\":\"content_governance_assignments\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"content_governance_assignments\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"key\\\" TEXT NOT NULL,\\n \\\"label\\\" TEXT,\\n \\\"content_type\\\" TEXT NOT NULL,\\n \\\"content_variant\\\" TEXT,\\n \\\"enabled\\\" BOOLEAN NOT NULL DEFAULT TRUE,\\n \\\"fact_linking_enabled\\\" BOOLEAN NOT NULL DEFAULT FALSE,\\n \\\"transparency_enabled\\\" BOOLEAN NOT NULL DEFAULT FALSE,\\n \\\"publication_profile_key\\\" TEXT,\\n \\\"correction_profile_key\\\" TEXT,\\n \\\"enforce_publish_readiness\\\" BOOLEAN NOT NULL DEFAULT FALSE,\\n \\\"default_fact_relationship\\\" TEXT DEFAULT 'supports',\\n \\\"metadata\\\" TEXT,\\n \\\"tenant_id\\\" UUID\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"key\":{\"type\":\"TEXT\",\"notNull\":true,\"unique\":false},\"label\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"content_type\":{\"type\":\"TEXT\",\"notNull\":true,\"unique\":false},\"content_variant\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"enabled\":{\"type\":\"BOOLEAN\",\"notNull\":true,\"unique\":false,\"default\":true},\"fact_linking_enabled\":{\"type\":\"BOOLEAN\",\"notNull\":true,\"unique\":false,\"default\":false},\"transparency_enabled\":{\"type\":\"BOOLEAN\",\"notNull\":true,\"unique\":false,\"default\":false},\"publication_profile_key\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"correction_profile_key\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"enforce_publish_readiness\":{\"type\":\"BOOLEAN\",\"notNull\":true,\"unique\":false,\"default\":false},\"default_fact_relationship\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"supports\"},\"metadata\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"tenantId\",\"notNull\":false,\"unique\":false}},\"indexes\":[{\"name\":\"content_governance_assignments_key_idx\",\"columns\":[\"key\"],\"unique\":true},{\"name\":\"content_governance_assignments_slug_context_idx\",\"columns\":[\"slug\",\"context\"]},{\"name\":\"content_governance_assignments_tenant_id_created_at_idx\",\"columns\":[\"tenant_id\",\"created_at\"]}],\"version\":\"00a2c610\"}},\"@happyvertical/smrt-content:ContentGovernanceAssignmentCollection\":{\"name\":\"contentgovernanceassignmentcollection\",\"className\":\"ContentGovernanceAssignmentCollection\",\"qualifiedName\":\"@happyvertical/smrt-content:ContentGovernanceAssignmentCollection\",\"collection\":\"contentgovernanceassignments\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/content/src/content-governance-assignments.ts\",\"packageName\":\"@happyvertical/smrt-content\",\"fields\":{},\"methods\":{\"getByKey\":{\"name\":\"getByKey\",\"async\":true,\"parameters\":[{\"name\":\"key\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<ContentGovernanceAssignment | null>\",\"isStatic\":false,\"isPublic\":true},\"resolveForContent\":{\"name\":\"resolveForContent\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":false,\"memberTypes\":[\"string\",\"string | null\"]}],\"returnType\":\"Promise<ContentGovernanceAssignment | null>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableName\":\"content_governance_assignments\"},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"ContentGovernanceAssignment\",\"exportName\":\"ContentGovernanceAssignmentCollection\",\"collectionExportName\":\"ContentGovernanceAssignmentCollectionCollection\",\"schema\":{\"tableName\":\"content_governance_assignments\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"content_governance_assignments\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"}},\"indexes\":[{\"name\":\"content_governance_assignments_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true},{\"name\":\"content_governance_assignments_created_at_idx\",\"columns\":[\"created_at\"]}],\"version\":\"21471529\"}},\"@happyvertical/smrt-content:ContentGovernancePolicyCollection\":{\"name\":\"contentgovernancepolicycollection\",\"className\":\"ContentGovernancePolicyCollection\",\"qualifiedName\":\"@happyvertical/smrt-content:ContentGovernancePolicyCollection\",\"collection\":\"contentgovernancepolicies\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/content/src/content-governance-policies.ts\",\"packageName\":\"@happyvertical/smrt-content\",\"fields\":{},\"methods\":{\"getByKey\":{\"name\":\"getByKey\",\"async\":true,\"parameters\":[{\"name\":\"key\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<ContentGovernancePolicy | null>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableName\":\"content_governance_policies\"},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"ContentGovernancePolicy\",\"exportName\":\"ContentGovernancePolicyCollection\",\"collectionExportName\":\"ContentGovernancePolicyCollectionCollection\",\"schema\":{\"tableName\":\"content_governance_policies\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"content_governance_policies\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"}},\"indexes\":[{\"name\":\"content_governance_policies_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true},{\"name\":\"content_governance_policies_created_at_idx\",\"columns\":[\"created_at\"]}],\"version\":\"e2da0e5b\"}},\"@happyvertical/smrt-content:ContentGovernancePolicy\":{\"name\":\"contentgovernancepolicy\",\"className\":\"ContentGovernancePolicy\",\"qualifiedName\":\"@happyvertical/smrt-content:ContentGovernancePolicy\",\"collection\":\"contentgovernancepolicies\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/content/src/content-governance-policy.ts\",\"packageName\":\"@happyvertical/smrt-content\",\"fields\":{\"key\":{\"type\":\"text\",\"required\":true,\"_meta\":{\"required\":true}},\"label\":{\"type\":\"text\",\"required\":false},\"kind\":{\"type\":\"text\",\"required\":false,\"default\":\"custom\"},\"instructions\":{\"type\":\"text\",\"required\":false},\"enabled\":{\"type\":\"boolean\",\"required\":true,\"default\":true},\"metadata\":{\"type\":\"text\",\"required\":false},\"tenantId\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"sqlType\":\"UUID\",\"nullable\":true,\"__tenancy\":{\"isTenantIdField\":true,\"autoFilter\":true,\"required\":false,\"autoPopulate\":true,\"nullable\":true,\"mode\":\"optional\",\"field\":\"tenantId\",\"allowSuperAdminBypass\":false}}},\"createdAt\":{\"type\":\"text\",\"required\":false},\"updatedAt\":{\"type\":\"text\",\"required\":false}},\"methods\":{\"getMetadata\":{\"name\":\"getMetadata\",\"async\":false,\"parameters\":[],\"returnType\":\"Record<string, unknown>\",\"isStatic\":false,\"isPublic\":true},\"toDefinition\":{\"name\":\"toDefinition\",\"async\":false,\"parameters\":[],\"returnType\":\"ContentReviewPolicyDefinition\",\"isStatic\":false,\"isPublic\":true},\"delete\":{\"name\":\"delete\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableName\":\"content_governance_policies\",\"conflictColumns\":[\"key\"],\"api\":{\"include\":[\"list\",\"get\",\"create\",\"update\",\"delete\"]},\"mcp\":{\"include\":[\"list\",\"get\",\"create\",\"update\",\"delete\"]},\"cli\":{\"skipApiCheck\":true},\"tenantScoped\":{\"mode\":\"optional\"}},\"extends\":\"SmrtObject\",\"exportName\":\"ContentGovernancePolicy\",\"collectionExportName\":\"ContentGovernancePolicyCollection\",\"validationRules\":[{\"field\":\"key\",\"rule\":\"required\",\"fieldType\":\"text\"},{\"field\":\"enabled\",\"rule\":\"required\",\"fieldType\":\"boolean\"}],\"schema\":{\"tableName\":\"content_governance_policies\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"content_governance_policies\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"key\\\" TEXT NOT NULL,\\n \\\"label\\\" TEXT,\\n \\\"kind\\\" TEXT DEFAULT 'custom',\\n \\\"instructions\\\" TEXT,\\n \\\"enabled\\\" BOOLEAN NOT NULL DEFAULT TRUE,\\n \\\"metadata\\\" TEXT,\\n \\\"tenant_id\\\" UUID\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"key\":{\"type\":\"TEXT\",\"notNull\":true,\"unique\":false},\"label\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"kind\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"custom\"},\"instructions\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"enabled\":{\"type\":\"BOOLEAN\",\"notNull\":true,\"unique\":false,\"default\":true},\"metadata\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"tenantId\",\"notNull\":false,\"unique\":false}},\"indexes\":[{\"name\":\"content_governance_policies_key_idx\",\"columns\":[\"key\"],\"unique\":true},{\"name\":\"content_governance_policies_slug_context_idx\",\"columns\":[\"slug\",\"context\"]},{\"name\":\"content_governance_policies_tenant_id_created_at_idx\",\"columns\":[\"tenant_id\",\"created_at\"]}],\"version\":\"3cc24f80\"}},\"@happyvertical/smrt-content:ContentGovernanceProfile\":{\"name\":\"contentgovernanceprofile\",\"className\":\"ContentGovernanceProfile\",\"qualifiedName\":\"@happyvertical/smrt-content:ContentGovernanceProfile\",\"collection\":\"contentgovernanceprofiles\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/content/src/content-governance-profile.ts\",\"packageName\":\"@happyvertical/smrt-content\",\"fields\":{\"key\":{\"type\":\"text\",\"required\":true,\"_meta\":{\"required\":true}},\"label\":{\"type\":\"text\",\"required\":false},\"description\":{\"type\":\"text\",\"required\":false},\"enabled\":{\"type\":\"boolean\",\"required\":true,\"default\":true},\"requirements\":{\"type\":\"text\",\"required\":false},\"metadata\":{\"type\":\"text\",\"required\":false},\"tenantId\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"sqlType\":\"UUID\",\"nullable\":true,\"__tenancy\":{\"isTenantIdField\":true,\"autoFilter\":true,\"required\":false,\"autoPopulate\":true,\"nullable\":true,\"mode\":\"optional\",\"field\":\"tenantId\",\"allowSuperAdminBypass\":false}}},\"createdAt\":{\"type\":\"text\",\"required\":false},\"updatedAt\":{\"type\":\"text\",\"required\":false}},\"methods\":{\"getRequirements\":{\"name\":\"getRequirements\",\"async\":false,\"parameters\":[],\"returnType\":\"ContentReviewRequirement[]\",\"isStatic\":false,\"isPublic\":true},\"getMetadata\":{\"name\":\"getMetadata\",\"async\":false,\"parameters\":[],\"returnType\":\"Record<string, unknown>\",\"isStatic\":false,\"isPublic\":true},\"toDefinition\":{\"name\":\"toDefinition\",\"async\":false,\"parameters\":[],\"returnType\":\"ContentGovernanceProfileDefinition\",\"isStatic\":false,\"isPublic\":true},\"delete\":{\"name\":\"delete\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableName\":\"content_governance_profiles\",\"conflictColumns\":[\"key\"],\"api\":{\"include\":[\"list\",\"get\",\"create\",\"update\",\"delete\"]},\"mcp\":{\"include\":[\"list\",\"get\",\"create\",\"update\",\"delete\"]},\"cli\":{\"skipApiCheck\":true},\"tenantScoped\":{\"mode\":\"optional\"}},\"extends\":\"SmrtObject\",\"exportName\":\"ContentGovernanceProfile\",\"collectionExportName\":\"ContentGovernanceProfileCollection\",\"validationRules\":[{\"field\":\"key\",\"rule\":\"required\",\"fieldType\":\"text\"},{\"field\":\"enabled\",\"rule\":\"required\",\"fieldType\":\"boolean\"}],\"schema\":{\"tableName\":\"content_governance_profiles\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"content_governance_profiles\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"key\\\" TEXT NOT NULL,\\n \\\"label\\\" TEXT,\\n \\\"description\\\" TEXT,\\n \\\"enabled\\\" BOOLEAN NOT NULL DEFAULT TRUE,\\n \\\"requirements\\\" TEXT,\\n \\\"metadata\\\" TEXT,\\n \\\"tenant_id\\\" UUID\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"key\":{\"type\":\"TEXT\",\"notNull\":true,\"unique\":false},\"label\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"description\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"enabled\":{\"type\":\"BOOLEAN\",\"notNull\":true,\"unique\":false,\"default\":true},\"requirements\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"metadata\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"tenantId\",\"notNull\":false,\"unique\":false}},\"indexes\":[{\"name\":\"content_governance_profiles_key_idx\",\"columns\":[\"key\"],\"unique\":true},{\"name\":\"content_governance_profiles_slug_context_idx\",\"columns\":[\"slug\",\"context\"]},{\"name\":\"content_governance_profiles_tenant_id_created_at_idx\",\"columns\":[\"tenant_id\",\"created_at\"]}],\"version\":\"4bfc2afc\"}},\"@happyvertical/smrt-content:ContentGovernanceProfileCollection\":{\"name\":\"contentgovernanceprofilecollection\",\"className\":\"ContentGovernanceProfileCollection\",\"qualifiedName\":\"@happyvertical/smrt-content:ContentGovernanceProfileCollection\",\"collection\":\"contentgovernanceprofiles\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/content/src/content-governance-profiles.ts\",\"packageName\":\"@happyvertical/smrt-content\",\"fields\":{},\"methods\":{\"getByKey\":{\"name\":\"getByKey\",\"async\":true,\"parameters\":[{\"name\":\"key\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<ContentGovernanceProfile | null>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableName\":\"content_governance_profiles\"},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"ContentGovernanceProfile\",\"exportName\":\"ContentGovernanceProfileCollection\",\"collectionExportName\":\"ContentGovernanceProfileCollectionCollection\",\"schema\":{\"tableName\":\"content_governance_profiles\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"content_governance_profiles\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"}},\"indexes\":[{\"name\":\"content_governance_profiles_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true},{\"name\":\"content_governance_profiles_created_at_idx\",\"columns\":[\"created_at\"]}],\"version\":\"496f0f56\"}},\"@happyvertical/smrt-content:ContentReference\":{\"name\":\"contentreference\",\"className\":\"ContentReference\",\"qualifiedName\":\"@happyvertical/smrt-content:ContentReference\",\"collection\":\"contentreferences\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/content/src/content-reference.ts\",\"packageName\":\"@happyvertical/smrt-content\",\"fields\":{\"tenantId\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"sqlType\":\"UUID\",\"nullable\":true,\"__tenancy\":{\"isTenantIdField\":true,\"autoFilter\":true,\"required\":false,\"autoPopulate\":true,\"nullable\":true,\"mode\":\"optional\",\"field\":\"tenantId\",\"allowSuperAdminBypass\":false}}},\"sourceId\":{\"type\":\"foreignKey\",\"required\":true,\"related\":\"Content\",\"_meta\":{\"required\":true}},\"targetId\":{\"type\":\"foreignKey\",\"required\":true,\"related\":\"Content\",\"_meta\":{\"required\":true}},\"targetVersion\":{\"type\":\"integer\",\"required\":false,\"_meta\":{\"nullable\":true}},\"createdAt\":{\"type\":\"text\",\"required\":false}},\"methods\":{},\"decoratorConfig\":{\"tableName\":\"content_references\",\"conflictColumns\":[\"source_id\",\"target_id\"],\"tenantScoped\":{\"mode\":\"optional\"}},\"extends\":\"SmrtObject\",\"exportName\":\"ContentReference\",\"collectionExportName\":\"ContentReferenceCollection\",\"validationRules\":[{\"field\":\"sourceId\",\"rule\":\"required\",\"fieldType\":\"foreignKey\"},{\"field\":\"targetId\",\"rule\":\"required\",\"fieldType\":\"foreignKey\"}],\"schema\":{\"tableName\":\"content_references\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"content_references\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"tenant_id\\\" UUID,\\n \\\"source_id\\\" UUID NOT NULL,\\n \\\"target_id\\\" UUID NOT NULL,\\n \\\"target_version\\\" INTEGER\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"tenantId\",\"notNull\":false,\"unique\":false},\"source_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":true,\"unique\":false,\"foreignKey\":{\"table\":\"contents\",\"column\":\"id\",\"onDelete\":\"CASCADE\",\"onUpdate\":\"CASCADE\"}},\"target_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":true,\"unique\":false,\"foreignKey\":{\"table\":\"contents\",\"column\":\"id\",\"onDelete\":\"CASCADE\",\"onUpdate\":\"CASCADE\"}},\"target_version\":{\"type\":\"INTEGER\",\"notNull\":false,\"unique\":false}},\"indexes\":[{\"name\":\"content_references_source_id_target_id_idx\",\"columns\":[\"source_id\",\"target_id\"],\"unique\":true},{\"name\":\"content_references_slug_context_idx\",\"columns\":[\"slug\",\"context\"]},{\"name\":\"content_references_tenant_id_created_at_idx\",\"columns\":[\"tenant_id\",\"created_at\"]},{\"name\":\"content_references_target_id_idx\",\"columns\":[\"target_id\"]}],\"version\":\"3347ea2a\"}},\"@happyvertical/smrt-content:ContentReferences\":{\"name\":\"contentreferences\",\"className\":\"ContentReferences\",\"qualifiedName\":\"@happyvertical/smrt-content:ContentReferences\",\"collection\":\"contentreferences\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/content/src/content-references.ts\",\"packageName\":\"@happyvertical/smrt-content\",\"fields\":{},\"methods\":{\"byLeft\":{\"name\":\"byLeft\",\"async\":true,\"parameters\":[{\"name\":\"leftId\",\"type\":\"string\",\"optional\":false},{\"name\":\"opts\",\"type\":\"JunctionFilterOptions\",\"optional\":true}],\"returnType\":\"Promise<TItem[]>\",\"isStatic\":false,\"isPublic\":true},\"byRight\":{\"name\":\"byRight\",\"async\":true,\"parameters\":[{\"name\":\"rightId\",\"type\":\"string\",\"optional\":false},{\"name\":\"opts\",\"type\":\"JunctionFilterOptions\",\"optional\":true}],\"returnType\":\"Promise<TItem[]>\",\"isStatic\":false,\"isPublic\":true},\"attach\":{\"name\":\"attach\",\"async\":true,\"parameters\":[{\"name\":\"sourceId\",\"type\":\"string\",\"optional\":false},{\"name\":\"targetId\",\"type\":\"string\",\"optional\":false},{\"name\":\"opts\",\"type\":\"JunctionAttachOptions\",\"optional\":true}],\"returnType\":\"Promise<ContentReference>\",\"isStatic\":false,\"isPublic\":true},\"detach\":{\"name\":\"detach\",\"async\":true,\"parameters\":[{\"name\":\"leftId\",\"type\":\"string\",\"optional\":false},{\"name\":\"rightId\",\"type\":\"string\",\"optional\":false},{\"name\":\"opts\",\"type\":\"JunctionFilterOptions\",\"optional\":true}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"setLinks\":{\"name\":\"setLinks\",\"async\":true,\"parameters\":[{\"name\":\"leftId\",\"type\":\"string\",\"optional\":false},{\"name\":\"rightIds\",\"type\":\"string[]\",\"optional\":false},{\"name\":\"opts\",\"type\":\"JunctionAttachOptions\",\"optional\":true}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"getForSource\":{\"name\":\"getForSource\",\"async\":true,\"parameters\":[{\"name\":\"sourceId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<ContentReference[]>\",\"isStatic\":false,\"isPublic\":true},\"getForTarget\":{\"name\":\"getForTarget\",\"async\":true,\"parameters\":[{\"name\":\"targetId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<ContentReference[]>\",\"isStatic\":false,\"isPublic\":true},\"unlink\":{\"name\":\"unlink\",\"async\":true,\"parameters\":[{\"name\":\"sourceId\",\"type\":\"string\",\"optional\":false},{\"name\":\"targetId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableName\":\"content_references\"},\"extends\":\"SmrtJunction\",\"extendsTypeArg\":\"ContentReference\",\"exportName\":\"ContentReferences\",\"collectionExportName\":\"ContentReferencesCollection\",\"schema\":{\"tableName\":\"content_references\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"content_references\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"}},\"indexes\":[{\"name\":\"content_references_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true},{\"name\":\"content_references_created_at_idx\",\"columns\":[\"created_at\"]}],\"version\":\"e9ad3cf0\"}},\"@happyvertical/smrt-content:ContentReview\":{\"name\":\"contentreview\",\"className\":\"ContentReview\",\"qualifiedName\":\"@happyvertical/smrt-content:ContentReview\",\"collection\":\"contentreviews\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/content/src/content-review.ts\",\"packageName\":\"@happyvertical/smrt-content\",\"fields\":{\"contentId\":{\"type\":\"foreignKey\",\"required\":true,\"related\":\"Content\",\"_meta\":{\"required\":true}},\"contentVersionId\":{\"type\":\"foreignKey\",\"required\":false,\"related\":\"ContentVersion\"},\"kind\":{\"type\":\"text\",\"required\":false,\"default\":\"custom\"},\"policyKey\":{\"type\":\"text\",\"required\":false},\"status\":{\"type\":\"text\",\"required\":false,\"default\":\"pending\"},\"summary\":{\"type\":\"text\",\"required\":false},\"findings\":{\"type\":\"text\",\"required\":false},\"reviewer\":{\"type\":\"text\",\"required\":false},\"metadata\":{\"type\":\"text\",\"required\":false},\"tenantId\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"sqlType\":\"UUID\",\"nullable\":true,\"__tenancy\":{\"isTenantIdField\":true,\"autoFilter\":true,\"required\":false,\"autoPopulate\":true,\"nullable\":true,\"mode\":\"optional\",\"field\":\"tenantId\",\"allowSuperAdminBypass\":false}}},\"createdAt\":{\"type\":\"text\",\"required\":false},\"updatedAt\":{\"type\":\"text\",\"required\":false}},\"methods\":{\"getFindings\":{\"name\":\"getFindings\",\"async\":false,\"parameters\":[],\"returnType\":\"ContentReviewFinding[]\",\"isStatic\":false,\"isPublic\":true},\"getMetadata\":{\"name\":\"getMetadata\",\"async\":false,\"parameters\":[],\"returnType\":\"Record<string, unknown>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableName\":\"content_reviews\",\"api\":{\"include\":[\"list\",\"get\",\"create\",\"update\"]},\"mcp\":{\"include\":[\"list\",\"get\",\"create\",\"update\"]},\"cli\":{\"skipApiCheck\":true},\"tenantScoped\":{\"mode\":\"optional\"},\"conflictColumns\":[\"tenant_id\",\"slug\",\"context\"]},\"extends\":\"SmrtObject\",\"exportName\":\"ContentReview\",\"collectionExportName\":\"ContentReviewCollection\",\"validationRules\":[{\"field\":\"contentId\",\"rule\":\"required\",\"fieldType\":\"foreignKey\"}],\"schema\":{\"tableName\":\"content_reviews\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"content_reviews\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"content_id\\\" UUID NOT NULL,\\n \\\"content_version_id\\\" UUID,\\n \\\"kind\\\" TEXT DEFAULT 'custom',\\n \\\"policy_key\\\" TEXT,\\n \\\"status\\\" TEXT DEFAULT 'pending',\\n \\\"summary\\\" TEXT,\\n \\\"findings\\\" TEXT,\\n \\\"reviewer\\\" TEXT,\\n \\\"metadata\\\" TEXT,\\n \\\"tenant_id\\\" UUID\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"content_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":true,\"unique\":false,\"foreignKey\":{\"table\":\"contents\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"content_version_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":false,\"unique\":false,\"foreignKey\":{\"table\":\"content_versions\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"kind\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"custom\"},\"policy_key\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"status\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"pending\"},\"summary\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"findings\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"reviewer\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"metadata\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"tenantId\",\"notNull\":false,\"unique\":false}},\"indexes\":[{\"name\":\"content_reviews_slug_context_idx\",\"columns\":[\"tenant_id\",\"slug\",\"context\"],\"unique\":true},{\"name\":\"content_reviews_tenant_id_created_at_idx\",\"columns\":[\"tenant_id\",\"created_at\"]},{\"name\":\"content_reviews_content_id_idx\",\"columns\":[\"content_id\"]},{\"name\":\"content_reviews_content_version_id_idx\",\"columns\":[\"content_version_id\"]}],\"version\":\"7b2c0ad7\"}},\"@happyvertical/smrt-content:ContentReviewCollection\":{\"name\":\"contentreviewcollection\",\"className\":\"ContentReviewCollection\",\"qualifiedName\":\"@happyvertical/smrt-content:ContentReviewCollection\",\"collection\":\"contentreviews\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/content/src/content-reviews.ts\",\"packageName\":\"@happyvertical/smrt-content\",\"fields\":{},\"methods\":{\"listForContent\":{\"name\":\"listForContent\",\"async\":true,\"parameters\":[{\"name\":\"contentId\",\"type\":\"string\",\"optional\":false},{\"name\":\"kind\",\"type\":\"ContentReviewKind\",\"optional\":true}],\"returnType\":\"Promise<ContentReview[]>\",\"isStatic\":false,\"isPublic\":true},\"getLatestForContent\":{\"name\":\"getLatestForContent\",\"async\":true,\"parameters\":[{\"name\":\"contentId\",\"type\":\"string\",\"optional\":false},{\"name\":\"kind\",\"type\":\"ContentReviewKind\",\"optional\":true}],\"returnType\":\"Promise<ContentReview | null>\",\"isStatic\":false,\"isPublic\":true},\"listForContentByPolicyKey\":{\"name\":\"listForContentByPolicyKey\",\"async\":true,\"parameters\":[{\"name\":\"contentId\",\"type\":\"string\",\"optional\":false},{\"name\":\"policyKey\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<ContentReview[]>\",\"isStatic\":false,\"isPublic\":true},\"getLatestForPolicyKey\":{\"name\":\"getLatestForPolicyKey\",\"async\":true,\"parameters\":[{\"name\":\"contentId\",\"type\":\"string\",\"optional\":false},{\"name\":\"policyKey\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<ContentReview | null>\",\"isStatic\":false,\"isPublic\":true},\"createFromResult\":{\"name\":\"createFromResult\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":false,\"memberTypes\":[\"string\",\"string | null\",\"ContentReviewKind\",\"ContentReviewResult\",\"Record<string, unknown>\"]}],\"returnType\":\"Promise<ContentReview>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableName\":\"content_reviews\"},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"ContentReview\",\"exportName\":\"ContentReviewCollection\",\"collectionExportName\":\"ContentReviewCollectionCollection\",\"schema\":{\"tableName\":\"content_reviews\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"content_reviews\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"}},\"indexes\":[{\"name\":\"content_reviews_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true},{\"name\":\"content_reviews_created_at_idx\",\"columns\":[\"created_at\"]}],\"version\":\"03b7d1d3\"}},\"@happyvertical/smrt-content:Article\":{\"name\":\"article\",\"className\":\"Article\",\"qualifiedName\":\"@happyvertical/smrt-content:Article\",\"collection\":\"contents\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/content/src/content-types.ts\",\"packageName\":\"@happyvertical/smrt-content\",\"fields\":{\"created_at\":{\"type\":\"datetime\",\"required\":false},\"updated_at\":{\"type\":\"datetime\",\"required\":false},\"tenantId\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"sqlType\":\"UUID\",\"nullable\":true,\"__tenancy\":{\"isTenantIdField\":true,\"autoFilter\":true,\"required\":false,\"autoPopulate\":true,\"nullable\":true}}},\"type\":{\"type\":\"text\",\"required\":false},\"variant\":{\"type\":\"text\",\"required\":false},\"fileKey\":{\"type\":\"text\",\"required\":false},\"author\":{\"type\":\"text\",\"required\":false},\"name\":{\"type\":\"text\",\"required\":true,\"default\":\"\",\"_meta\":{\"required\":true}},\"title\":{\"type\":\"text\",\"required\":false},\"description\":{\"type\":\"text\",\"required\":false},\"body\":{\"type\":\"text\",\"required\":false},\"bodyFormat\":{\"type\":\"text\",\"required\":false},\"publish_date\":{\"type\":\"datetime\",\"required\":false},\"url\":{\"type\":\"text\",\"required\":false},\"source\":{\"type\":\"text\",\"required\":false},\"original_url\":{\"type\":\"text\",\"required\":false},\"language\":{\"type\":\"text\",\"required\":false},\"tags\":{\"type\":\"json\",\"required\":false,\"default\":[]},\"category\":{\"type\":\"text\",\"required\":false},\"status\":{\"type\":\"text\",\"required\":false,\"default\":\"draft\"},\"state\":{\"type\":\"text\",\"required\":false,\"default\":\"active\"},\"metadata\":{\"type\":\"json\",\"required\":false,\"default\":{}},\"thumbnailAssetId\":{\"type\":\"crossPackageRef\",\"required\":false,\"related\":\"@happyvertical/smrt-assets:Asset\"}},\"methods\":{\"initialize\":{\"name\":\"initialize\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<this>\",\"isStatic\":false,\"isPublic\":true},\"save\":{\"name\":\"save\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"SmrtSaveOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"resolveGovernance\":{\"name\":\"resolveGovernance\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<ResolvedContentGovernance>\",\"isStatic\":false,\"isPublic\":true},\"loadReferences\":{\"name\":\"loadReferences\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"addReference\":{\"name\":\"addReference\",\"async\":true,\"parameters\":[{\"name\":\"content\",\"type\":\"Content | string\",\"optional\":false,\"unionBranches\":[{\"type\":\"Content\"},{\"type\":\"string\"}]},{\"name\":\"options\",\"type\":\"object\",\"optional\":true,\"memberTypes\":[\"number | null\"]}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"removeReference\":{\"name\":\"removeReference\",\"async\":true,\"parameters\":[{\"name\":\"targetId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getReferences\":{\"name\":\"getReferences\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getReferenceEdges\":{\"name\":\"getReferenceEdges\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<Array<object>>\",\"isStatic\":false,\"isPublic\":true},\"getReferenceDrift\":{\"name\":\"getReferenceDrift\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<Array<object>>\",\"isStatic\":false,\"isPublic\":true},\"isGoverned\":{\"name\":\"isGoverned\",\"async\":false,\"parameters\":[],\"returnType\":\"boolean\",\"isStatic\":false,\"isPublic\":true},\"getFactLinks\":{\"name\":\"getFactLinks\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":true,\"memberTypes\":[\"FactContentRelationship\"]}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getFacts\":{\"name\":\"getFacts\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":true,\"memberTypes\":[\"FactContentRelationship\",\"boolean\"]}],\"returnType\":\"Promise<Fact[]>\",\"isStatic\":false,\"isPublic\":true},\"addFact\":{\"name\":\"addFact\",\"async\":true,\"parameters\":[{\"name\":\"fact\",\"type\":\"Fact | string\",\"optional\":false,\"unionBranches\":[{\"type\":\"Fact\"},{\"type\":\"string\"}]},{\"name\":\"relationship\",\"type\":\"FactContentRelationship\",\"optional\":true},{\"name\":\"metadata\",\"type\":\"Record<string, unknown>\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"removeFact\":{\"name\":\"removeFact\",\"async\":true,\"parameters\":[{\"name\":\"factId\",\"type\":\"string\",\"optional\":false},{\"name\":\"relationship\",\"type\":\"FactContentRelationship\",\"optional\":true}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"syncFacts\":{\"name\":\"syncFacts\",\"async\":true,\"parameters\":[{\"name\":\"factIds\",\"type\":\"string[]\",\"optional\":false},{\"name\":\"relationship\",\"type\":\"FactContentRelationship\",\"optional\":true}],\"returnType\":\"Promise<object>\",\"isStatic\":false,\"isPublic\":true},\"browseFacts\":{\"name\":\"browseFacts\",\"async\":true,\"parameters\":[{\"name\":\"query\",\"type\":\"any\",\"optional\":true,\"default\":\"\"},{\"name\":\"options\",\"type\":\"object\",\"optional\":true,\"memberTypes\":[\"number\",\"boolean\"]}],\"returnType\":\"Promise<Fact[]>\",\"isStatic\":false,\"isPublic\":true},\"repairFactAudit\":{\"name\":\"repairFactAudit\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":true,\"memberTypes\":[\"number\",\"string\"]}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"repairFactAuditAction\":{\"name\":\"repairFactAuditAction\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":true,\"memberTypes\":[\"number\",\"string\"]}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"repairFactEvidence\":{\"name\":\"repairFactEvidence\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"FactAuditResourceRepairOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"repairFactEvidenceAction\":{\"name\":\"repairFactEvidenceAction\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"FactAuditResourceRepairOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"recheckFactClaims\":{\"name\":\"recheckFactClaims\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"FactAuditClaimRecheckOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"recheckFactClaimsAction\":{\"name\":\"recheckFactClaimsAction\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"FactAuditClaimRecheckOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"updateFactEvidenceStatus\":{\"name\":\"updateFactEvidenceStatus\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"FactEvidenceStatusUpdateOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"updateFactEvidenceStatusAction\":{\"name\":\"updateFactEvidenceStatusAction\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"FactEvidenceStatusUpdateOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getFactAuditState\":{\"name\":\"getFactAuditState\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<FactAuditState>\",\"isStatic\":false,\"isPublic\":true},\"getFactAuditStateAction\":{\"name\":\"getFactAuditStateAction\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getFactsState\":{\"name\":\"getFactsState\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":true,\"memberTypes\":[\"FactContentRelationship\"]}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"syncFactsState\":{\"name\":\"syncFactsState\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":true,\"memberTypes\":[\"string[]\",\"FactContentRelationship\"]}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"createVersion\":{\"name\":\"createVersion\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"CreateContentVersionOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getVersions\":{\"name\":\"getVersions\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"restoreFromVersion\":{\"name\":\"restoreFromVersion\",\"async\":true,\"parameters\":[{\"name\":\"versionNumber\",\"type\":\"number\",\"optional\":false}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getReviews\":{\"name\":\"getReviews\",\"async\":true,\"parameters\":[{\"name\":\"kind\",\"type\":\"any\",\"optional\":true,\"typeUnresolved\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"listReviews\":{\"name\":\"listReviews\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":true,\"typeUnresolved\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getReviewRequirements\":{\"name\":\"getReviewRequirements\",\"async\":true,\"parameters\":[{\"name\":\"profileKey\",\"type\":\"string\",\"optional\":false},{\"name\":\"governance\",\"type\":\"ResolvedContentGovernance\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getGovernanceState\":{\"name\":\"getGovernanceState\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<ContentGovernanceState>\",\"isStatic\":false,\"isPublic\":true},\"getGovernanceStateAction\":{\"name\":\"getGovernanceStateAction\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"listReviewProfilesAction\":{\"name\":\"listReviewProfilesAction\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"evaluateReviewProfile\":{\"name\":\"evaluateReviewProfile\",\"async\":true,\"parameters\":[{\"name\":\"profileKey\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<ContentReviewProfileEvaluation>\",\"isStatic\":false,\"isPublic\":true},\"evaluateReviewProfileAction\":{\"name\":\"evaluateReviewProfileAction\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":true,\"memberTypes\":[\"string\"]}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"isReadyForReviewProfile\":{\"name\":\"isReadyForReviewProfile\",\"async\":true,\"parameters\":[{\"name\":\"profileKey\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<boolean>\",\"isStatic\":false,\"isPublic\":true},\"getPublishedTransparency\":{\"name\":\"getPublishedTransparency\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getPublishedTransparencyAction\":{\"name\":\"getPublishedTransparencyAction\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"previewTransparency\":{\"name\":\"previewTransparency\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"previewTransparencyAction\":{\"name\":\"previewTransparencyAction\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"runReview\":{\"name\":\"runReview\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"RunContentReviewOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"runReviewAction\":{\"name\":\"runReviewAction\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"RunContentReviewOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"reviewFacts\":{\"name\":\"reviewFacts\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"Omit<RunContentReviewOptions, 'kind'>\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"reviewSafety\":{\"name\":\"reviewSafety\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"Omit<RunContentReviewOptions, 'kind'>\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getCorrections\":{\"name\":\"getCorrections\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"listCorrections\":{\"name\":\"listCorrections\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"issueCorrection\":{\"name\":\"issueCorrection\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"IssueContentCorrectionOptions\",\"optional\":false}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"issueCorrectionAction\":{\"name\":\"issueCorrectionAction\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"IssueContentCorrectionOptions\",\"optional\":false}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"listVersions\":{\"name\":\"listVersions\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"mutateVersionAction\":{\"name\":\"mutateVersionAction\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"any\",\"optional\":true,\"typeUnresolved\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getCategorySegments\":{\"name\":\"getCategorySegments\",\"async\":false,\"parameters\":[],\"returnType\":\"string[]\",\"isStatic\":false,\"isPublic\":true},\"getParentCategory\":{\"name\":\"getParentCategory\",\"async\":false,\"parameters\":[],\"returnType\":\"string | null\",\"isStatic\":false,\"isPublic\":true},\"getRootCategory\":{\"name\":\"getRootCategory\",\"async\":false,\"parameters\":[],\"returnType\":\"string | null\",\"isStatic\":false,\"isPublic\":true},\"getAncestorPaths\":{\"name\":\"getAncestorPaths\",\"async\":false,\"parameters\":[],\"returnType\":\"string[]\",\"isStatic\":false,\"isPublic\":true},\"isInCategory\":{\"name\":\"isInCategory\",\"async\":false,\"parameters\":[{\"name\":\"categoryPath\",\"type\":\"string\",\"optional\":false},{\"name\":\"includeChildren\",\"type\":\"any\",\"optional\":true}],\"returnType\":\"boolean\",\"isStatic\":false,\"isPublic\":true},\"getAssets\":{\"name\":\"getAssets\",\"async\":true,\"parameters\":[{\"name\":\"relationship\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<Asset[]>\",\"isStatic\":false,\"isPublic\":true},\"addAsset\":{\"name\":\"addAsset\",\"async\":true,\"parameters\":[{\"name\":\"asset\",\"type\":\"Asset\",\"optional\":false},{\"name\":\"relationship\",\"type\":\"any\",\"optional\":true,\"default\":\"attachment\"},{\"name\":\"sortOrder\",\"type\":\"any\",\"optional\":true}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"removeAsset\":{\"name\":\"removeAsset\",\"async\":true,\"parameters\":[{\"name\":\"assetId\",\"type\":\"string\",\"optional\":false},{\"name\":\"relationship\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"getMetadata\":{\"name\":\"getMetadata\",\"async\":false,\"parameters\":[],\"returnType\":\"Record<string, unknown>\",\"isStatic\":false,\"isPublic\":true},\"setMetadata\":{\"name\":\"setMetadata\",\"async\":false,\"parameters\":[{\"name\":\"metadata\",\"type\":\"Record<string, unknown> | null | undefined\",\"optional\":false,\"unionBranches\":[{\"type\":\"Record<string, unknown>\"},{\"type\":\"null\"},{\"type\":\"undefined\"}]}],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"updateMetadata\":{\"name\":\"updateMetadata\",\"async\":false,\"parameters\":[{\"name\":\"patch\",\"type\":\"Partial<Record<string, unknown>>\",\"optional\":false}],\"returnType\":\"Record<string, unknown>\",\"isStatic\":false,\"isPublic\":true},\"getThumbnail\":{\"name\":\"getThumbnail\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<Image | null>\",\"isStatic\":false,\"isPublic\":true},\"setThumbnail\":{\"name\":\"setThumbnail\",\"async\":true,\"parameters\":[{\"name\":\"image\",\"type\":\"Image\",\"optional\":false}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"generateThumbnail\":{\"name\":\"generateThumbnail\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"ThumbnailOptions\",\"optional\":false}],\"returnType\":\"Promise<Image>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableStrategy\":\"sti\",\"api\":false,\"mcp\":false,\"cli\":false,\"tableName\":\"contents\"},\"extends\":\"Content\",\"exportName\":\"Article\",\"collectionExportName\":\"ArticleCollection\",\"validationRules\":[{\"field\":\"name\",\"rule\":\"required\",\"fieldType\":\"text\"}],\"schema\":{\"tableName\":\"contents\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"contents\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"_meta_type\\\" TEXT NOT NULL,\\n \\\"_meta_data\\\" JSON,\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"tenant_id\\\" UUID,\\n \\\"type\\\" TEXT,\\n \\\"variant\\\" TEXT,\\n \\\"file_key\\\" TEXT,\\n \\\"author\\\" TEXT,\\n \\\"name\\\" TEXT DEFAULT '',\\n \\\"title\\\" TEXT,\\n \\\"description\\\" TEXT,\\n \\\"body\\\" TEXT,\\n \\\"body_format\\\" TEXT,\\n \\\"publish_date\\\" TIMESTAMP,\\n \\\"url\\\" TEXT,\\n \\\"source\\\" TEXT,\\n \\\"original_url\\\" TEXT,\\n \\\"language\\\" TEXT,\\n \\\"tags\\\" JSON DEFAULT '[]',\\n \\\"category\\\" TEXT,\\n \\\"status\\\" TEXT DEFAULT 'draft',\\n \\\"state\\\" TEXT DEFAULT 'active',\\n \\\"metadata\\\" JSON DEFAULT '{}',\\n \\\"thumbnail_asset_id\\\" UUID,\\n \\\"feed_source_id\\\" UUID,\\n \\\"source_guid\\\" TEXT,\\n \\\"source_name\\\" TEXT,\\n \\\"source_homepage_url\\\" TEXT,\\n \\\"external_url\\\" TEXT,\\n \\\"original_published_at\\\" TIMESTAMP,\\n \\\"dedupe_key\\\" TEXT\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"_meta_type\":{\"type\":\"TEXT\",\"notNull\":true},\"_meta_data\":{\"type\":\"JSON\",\"notNull\":false},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"tenantId\",\"notNull\":false},\"type\":{\"type\":\"TEXT\",\"notNull\":false},\"variant\":{\"type\":\"TEXT\",\"notNull\":false},\"file_key\":{\"type\":\"TEXT\",\"notNull\":false},\"author\":{\"type\":\"TEXT\",\"notNull\":false},\"name\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"\"},\"title\":{\"type\":\"TEXT\",\"notNull\":false},\"description\":{\"type\":\"TEXT\",\"notNull\":false},\"body\":{\"type\":\"TEXT\",\"notNull\":false},\"body_format\":{\"type\":\"TEXT\",\"notNull\":false},\"publish_date\":{\"type\":\"TIMESTAMP\",\"notNull\":false},\"url\":{\"type\":\"TEXT\",\"notNull\":false},\"source\":{\"type\":\"TEXT\",\"notNull\":false},\"original_url\":{\"type\":\"TEXT\",\"notNull\":false},\"language\":{\"type\":\"TEXT\",\"notNull\":false},\"tags\":{\"type\":\"JSON\",\"notNull\":false,\"default\":[]},\"category\":{\"type\":\"TEXT\",\"notNull\":false},\"status\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"draft\"},\"state\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"active\"},\"metadata\":{\"type\":\"JSON\",\"notNull\":false,\"default\":{}},\"thumbnail_asset_id\":{\"type\":\"UUID\",\"referenceKind\":\"crossPackageRef\",\"notNull\":false},\"feed_source_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":false,\"foreignKey\":{\"table\":\"content_feed_sources\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"source_guid\":{\"type\":\"TEXT\",\"notNull\":false},\"source_name\":{\"type\":\"TEXT\",\"notNull\":false},\"source_homepage_url\":{\"type\":\"TEXT\",\"notNull\":false},\"external_url\":{\"type\":\"TEXT\",\"notNull\":false},\"original_published_at\":{\"type\":\"TIMESTAMP\",\"notNull\":false},\"dedupe_key\":{\"type\":\"TEXT\",\"notNull\":false}},\"indexes\":[{\"name\":\"contents_slug_context_meta_type_idx\",\"columns\":[\"tenant_id\",\"slug\",\"context\",\"_meta_type\"],\"unique\":true},{\"name\":\"contents_meta_type_idx\",\"columns\":[\"_meta_type\"]},{\"name\":\"contents_tenant_id_publish_date_idx\",\"columns\":[\"tenant_id\",\"publish_date\"]},{\"name\":\"contents_tenant_id_created_at_idx\",\"columns\":[\"tenant_id\",\"created_at\"]},{\"name\":\"contents_thumbnail_asset_id_idx\",\"columns\":[\"thumbnail_asset_id\"]},{\"name\":\"contents_feed_source_id_idx\",\"columns\":[\"feed_source_id\"]}],\"version\":\"ad51267b\"}},\"@happyvertical/smrt-content:ContentDocument\":{\"name\":\"contentdocument\",\"className\":\"ContentDocument\",\"qualifiedName\":\"@happyvertical/smrt-content:ContentDocument\",\"collection\":\"contents\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/content/src/content-types.ts\",\"packageName\":\"@happyvertical/smrt-content\",\"fields\":{\"created_at\":{\"type\":\"datetime\",\"required\":false},\"updated_at\":{\"type\":\"datetime\",\"required\":false},\"tenantId\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"sqlType\":\"UUID\",\"nullable\":true,\"__tenancy\":{\"isTenantIdField\":true,\"autoFilter\":true,\"required\":false,\"autoPopulate\":true,\"nullable\":true}}},\"type\":{\"type\":\"text\",\"required\":false},\"variant\":{\"type\":\"text\",\"required\":false},\"fileKey\":{\"type\":\"text\",\"required\":false},\"author\":{\"type\":\"text\",\"required\":false},\"name\":{\"type\":\"text\",\"required\":true,\"default\":\"\",\"_meta\":{\"required\":true}},\"title\":{\"type\":\"text\",\"required\":false},\"description\":{\"type\":\"text\",\"required\":false},\"body\":{\"type\":\"text\",\"required\":false},\"bodyFormat\":{\"type\":\"text\",\"required\":false},\"publish_date\":{\"type\":\"datetime\",\"required\":false},\"url\":{\"type\":\"text\",\"required\":false},\"source\":{\"type\":\"text\",\"required\":false},\"original_url\":{\"type\":\"text\",\"required\":false},\"language\":{\"type\":\"text\",\"required\":false},\"tags\":{\"type\":\"json\",\"required\":false,\"default\":[]},\"category\":{\"type\":\"text\",\"required\":false},\"status\":{\"type\":\"text\",\"required\":false,\"default\":\"draft\"},\"state\":{\"type\":\"text\",\"required\":false,\"default\":\"active\"},\"metadata\":{\"type\":\"json\",\"required\":false,\"default\":{}},\"thumbnailAssetId\":{\"type\":\"crossPackageRef\",\"required\":false,\"related\":\"@happyvertical/smrt-assets:Asset\"}},\"methods\":{\"initialize\":{\"name\":\"initialize\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<this>\",\"isStatic\":false,\"isPublic\":true},\"save\":{\"name\":\"save\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"SmrtSaveOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"resolveGovernance\":{\"name\":\"resolveGovernance\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<ResolvedContentGovernance>\",\"isStatic\":false,\"isPublic\":true},\"loadReferences\":{\"name\":\"loadReferences\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"addReference\":{\"name\":\"addReference\",\"async\":true,\"parameters\":[{\"name\":\"content\",\"type\":\"Content | string\",\"optional\":false,\"unionBranches\":[{\"type\":\"Content\"},{\"type\":\"string\"}]},{\"name\":\"options\",\"type\":\"object\",\"optional\":true,\"memberTypes\":[\"number | null\"]}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"removeReference\":{\"name\":\"removeReference\",\"async\":true,\"parameters\":[{\"name\":\"targetId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getReferences\":{\"name\":\"getReferences\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getReferenceEdges\":{\"name\":\"getReferenceEdges\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<Array<object>>\",\"isStatic\":false,\"isPublic\":true},\"getReferenceDrift\":{\"name\":\"getReferenceDrift\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<Array<object>>\",\"isStatic\":false,\"isPublic\":true},\"isGoverned\":{\"name\":\"isGoverned\",\"async\":false,\"parameters\":[],\"returnType\":\"boolean\",\"isStatic\":false,\"isPublic\":true},\"getFactLinks\":{\"name\":\"getFactLinks\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":true,\"memberTypes\":[\"FactContentRelationship\"]}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getFacts\":{\"name\":\"getFacts\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":true,\"memberTypes\":[\"FactContentRelationship\",\"boolean\"]}],\"returnType\":\"Promise<Fact[]>\",\"isStatic\":false,\"isPublic\":true},\"addFact\":{\"name\":\"addFact\",\"async\":true,\"parameters\":[{\"name\":\"fact\",\"type\":\"Fact | string\",\"optional\":false,\"unionBranches\":[{\"type\":\"Fact\"},{\"type\":\"string\"}]},{\"name\":\"relationship\",\"type\":\"FactContentRelationship\",\"optional\":true},{\"name\":\"metadata\",\"type\":\"Record<string, unknown>\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"removeFact\":{\"name\":\"removeFact\",\"async\":true,\"parameters\":[{\"name\":\"factId\",\"type\":\"string\",\"optional\":false},{\"name\":\"relationship\",\"type\":\"FactContentRelationship\",\"optional\":true}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"syncFacts\":{\"name\":\"syncFacts\",\"async\":true,\"parameters\":[{\"name\":\"factIds\",\"type\":\"string[]\",\"optional\":false},{\"name\":\"relationship\",\"type\":\"FactContentRelationship\",\"optional\":true}],\"returnType\":\"Promise<object>\",\"isStatic\":false,\"isPublic\":true},\"browseFacts\":{\"name\":\"browseFacts\",\"async\":true,\"parameters\":[{\"name\":\"query\",\"type\":\"any\",\"optional\":true,\"default\":\"\"},{\"name\":\"options\",\"type\":\"object\",\"optional\":true,\"memberTypes\":[\"number\",\"boolean\"]}],\"returnType\":\"Promise<Fact[]>\",\"isStatic\":false,\"isPublic\":true},\"repairFactAudit\":{\"name\":\"repairFactAudit\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":true,\"memberTypes\":[\"number\",\"string\"]}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"repairFactAuditAction\":{\"name\":\"repairFactAuditAction\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":true,\"memberTypes\":[\"number\",\"string\"]}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"repairFactEvidence\":{\"name\":\"repairFactEvidence\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"FactAuditResourceRepairOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"repairFactEvidenceAction\":{\"name\":\"repairFactEvidenceAction\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"FactAuditResourceRepairOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"recheckFactClaims\":{\"name\":\"recheckFactClaims\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"FactAuditClaimRecheckOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"recheckFactClaimsAction\":{\"name\":\"recheckFactClaimsAction\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"FactAuditClaimRecheckOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"updateFactEvidenceStatus\":{\"name\":\"updateFactEvidenceStatus\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"FactEvidenceStatusUpdateOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"updateFactEvidenceStatusAction\":{\"name\":\"updateFactEvidenceStatusAction\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"FactEvidenceStatusUpdateOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getFactAuditState\":{\"name\":\"getFactAuditState\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<FactAuditState>\",\"isStatic\":false,\"isPublic\":true},\"getFactAuditStateAction\":{\"name\":\"getFactAuditStateAction\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getFactsState\":{\"name\":\"getFactsState\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":true,\"memberTypes\":[\"FactContentRelationship\"]}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"syncFactsState\":{\"name\":\"syncFactsState\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":true,\"memberTypes\":[\"string[]\",\"FactContentRelationship\"]}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"createVersion\":{\"name\":\"createVersion\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"CreateContentVersionOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getVersions\":{\"name\":\"getVersions\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"restoreFromVersion\":{\"name\":\"restoreFromVersion\",\"async\":true,\"parameters\":[{\"name\":\"versionNumber\",\"type\":\"number\",\"optional\":false}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getReviews\":{\"name\":\"getReviews\",\"async\":true,\"parameters\":[{\"name\":\"kind\",\"type\":\"any\",\"optional\":true,\"typeUnresolved\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"listReviews\":{\"name\":\"listReviews\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":true,\"typeUnresolved\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getReviewRequirements\":{\"name\":\"getReviewRequirements\",\"async\":true,\"parameters\":[{\"name\":\"profileKey\",\"type\":\"string\",\"optional\":false},{\"name\":\"governance\",\"type\":\"ResolvedContentGovernance\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getGovernanceState\":{\"name\":\"getGovernanceState\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<ContentGovernanceState>\",\"isStatic\":false,\"isPublic\":true},\"getGovernanceStateAction\":{\"name\":\"getGovernanceStateAction\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"listReviewProfilesAction\":{\"name\":\"listReviewProfilesAction\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"evaluateReviewProfile\":{\"name\":\"evaluateReviewProfile\",\"async\":true,\"parameters\":[{\"name\":\"profileKey\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<ContentReviewProfileEvaluation>\",\"isStatic\":false,\"isPublic\":true},\"evaluateReviewProfileAction\":{\"name\":\"evaluateReviewProfileAction\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":true,\"memberTypes\":[\"string\"]}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"isReadyForReviewProfile\":{\"name\":\"isReadyForReviewProfile\",\"async\":true,\"parameters\":[{\"name\":\"profileKey\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<boolean>\",\"isStatic\":false,\"isPublic\":true},\"getPublishedTransparency\":{\"name\":\"getPublishedTransparency\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getPublishedTransparencyAction\":{\"name\":\"getPublishedTransparencyAction\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"previewTransparency\":{\"name\":\"previewTransparency\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"previewTransparencyAction\":{\"name\":\"previewTransparencyAction\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"runReview\":{\"name\":\"runReview\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"RunContentReviewOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"runReviewAction\":{\"name\":\"runReviewAction\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"RunContentReviewOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"reviewFacts\":{\"name\":\"reviewFacts\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"Omit<RunContentReviewOptions, 'kind'>\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"reviewSafety\":{\"name\":\"reviewSafety\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"Omit<RunContentReviewOptions, 'kind'>\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getCorrections\":{\"name\":\"getCorrections\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"listCorrections\":{\"name\":\"listCorrections\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"issueCorrection\":{\"name\":\"issueCorrection\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"IssueContentCorrectionOptions\",\"optional\":false}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"issueCorrectionAction\":{\"name\":\"issueCorrectionAction\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"IssueContentCorrectionOptions\",\"optional\":false}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"listVersions\":{\"name\":\"listVersions\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"mutateVersionAction\":{\"name\":\"mutateVersionAction\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"any\",\"optional\":true,\"typeUnresolved\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getCategorySegments\":{\"name\":\"getCategorySegments\",\"async\":false,\"parameters\":[],\"returnType\":\"string[]\",\"isStatic\":false,\"isPublic\":true},\"getParentCategory\":{\"name\":\"getParentCategory\",\"async\":false,\"parameters\":[],\"returnType\":\"string | null\",\"isStatic\":false,\"isPublic\":true},\"getRootCategory\":{\"name\":\"getRootCategory\",\"async\":false,\"parameters\":[],\"returnType\":\"string | null\",\"isStatic\":false,\"isPublic\":true},\"getAncestorPaths\":{\"name\":\"getAncestorPaths\",\"async\":false,\"parameters\":[],\"returnType\":\"string[]\",\"isStatic\":false,\"isPublic\":true},\"isInCategory\":{\"name\":\"isInCategory\",\"async\":false,\"parameters\":[{\"name\":\"categoryPath\",\"type\":\"string\",\"optional\":false},{\"name\":\"includeChildren\",\"type\":\"any\",\"optional\":true}],\"returnType\":\"boolean\",\"isStatic\":false,\"isPublic\":true},\"getAssets\":{\"name\":\"getAssets\",\"async\":true,\"parameters\":[{\"name\":\"relationship\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<Asset[]>\",\"isStatic\":false,\"isPublic\":true},\"addAsset\":{\"name\":\"addAsset\",\"async\":true,\"parameters\":[{\"name\":\"asset\",\"type\":\"Asset\",\"optional\":false},{\"name\":\"relationship\",\"type\":\"any\",\"optional\":true,\"default\":\"attachment\"},{\"name\":\"sortOrder\",\"type\":\"any\",\"optional\":true}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"removeAsset\":{\"name\":\"removeAsset\",\"async\":true,\"parameters\":[{\"name\":\"assetId\",\"type\":\"string\",\"optional\":false},{\"name\":\"relationship\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"getMetadata\":{\"name\":\"getMetadata\",\"async\":false,\"parameters\":[],\"returnType\":\"Record<string, unknown>\",\"isStatic\":false,\"isPublic\":true},\"setMetadata\":{\"name\":\"setMetadata\",\"async\":false,\"parameters\":[{\"name\":\"metadata\",\"type\":\"Record<string, unknown> | null | undefined\",\"optional\":false,\"unionBranches\":[{\"type\":\"Record<string, unknown>\"},{\"type\":\"null\"},{\"type\":\"undefined\"}]}],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"updateMetadata\":{\"name\":\"updateMetadata\",\"async\":false,\"parameters\":[{\"name\":\"patch\",\"type\":\"Partial<Record<string, unknown>>\",\"optional\":false}],\"returnType\":\"Record<string, unknown>\",\"isStatic\":false,\"isPublic\":true},\"getThumbnail\":{\"name\":\"getThumbnail\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<Image | null>\",\"isStatic\":false,\"isPublic\":true},\"setThumbnail\":{\"name\":\"setThumbnail\",\"async\":true,\"parameters\":[{\"name\":\"image\",\"type\":\"Image\",\"optional\":false}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"generateThumbnail\":{\"name\":\"generateThumbnail\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"ThumbnailOptions\",\"optional\":false}],\"returnType\":\"Promise<Image>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableStrategy\":\"sti\",\"api\":false,\"mcp\":false,\"cli\":false,\"tableName\":\"contents\"},\"extends\":\"Content\",\"exportName\":\"ContentDocument\",\"collectionExportName\":\"ContentDocumentCollection\",\"validationRules\":[{\"field\":\"name\",\"rule\":\"required\",\"fieldType\":\"text\"}],\"schema\":{\"tableName\":\"contents\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"contents\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"_meta_type\\\" TEXT NOT NULL,\\n \\\"_meta_data\\\" JSON,\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"tenant_id\\\" UUID,\\n \\\"type\\\" TEXT,\\n \\\"variant\\\" TEXT,\\n \\\"file_key\\\" TEXT,\\n \\\"author\\\" TEXT,\\n \\\"name\\\" TEXT DEFAULT '',\\n \\\"title\\\" TEXT,\\n \\\"description\\\" TEXT,\\n \\\"body\\\" TEXT,\\n \\\"body_format\\\" TEXT,\\n \\\"publish_date\\\" TIMESTAMP,\\n \\\"url\\\" TEXT,\\n \\\"source\\\" TEXT,\\n \\\"original_url\\\" TEXT,\\n \\\"language\\\" TEXT,\\n \\\"tags\\\" JSON DEFAULT '[]',\\n \\\"category\\\" TEXT,\\n \\\"status\\\" TEXT DEFAULT 'draft',\\n \\\"state\\\" TEXT DEFAULT 'active',\\n \\\"metadata\\\" JSON DEFAULT '{}',\\n \\\"thumbnail_asset_id\\\" UUID,\\n \\\"feed_source_id\\\" UUID,\\n \\\"source_guid\\\" TEXT,\\n \\\"source_name\\\" TEXT,\\n \\\"source_homepage_url\\\" TEXT,\\n \\\"external_url\\\" TEXT,\\n \\\"original_published_at\\\" TIMESTAMP,\\n \\\"dedupe_key\\\" TEXT\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"_meta_type\":{\"type\":\"TEXT\",\"notNull\":true},\"_meta_data\":{\"type\":\"JSON\",\"notNull\":false},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"tenantId\",\"notNull\":false},\"type\":{\"type\":\"TEXT\",\"notNull\":false},\"variant\":{\"type\":\"TEXT\",\"notNull\":false},\"file_key\":{\"type\":\"TEXT\",\"notNull\":false},\"author\":{\"type\":\"TEXT\",\"notNull\":false},\"name\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"\"},\"title\":{\"type\":\"TEXT\",\"notNull\":false},\"description\":{\"type\":\"TEXT\",\"notNull\":false},\"body\":{\"type\":\"TEXT\",\"notNull\":false},\"body_format\":{\"type\":\"TEXT\",\"notNull\":false},\"publish_date\":{\"type\":\"TIMESTAMP\",\"notNull\":false},\"url\":{\"type\":\"TEXT\",\"notNull\":false},\"source\":{\"type\":\"TEXT\",\"notNull\":false},\"original_url\":{\"type\":\"TEXT\",\"notNull\":false},\"language\":{\"type\":\"TEXT\",\"notNull\":false},\"tags\":{\"type\":\"JSON\",\"notNull\":false,\"default\":[]},\"category\":{\"type\":\"TEXT\",\"notNull\":false},\"status\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"draft\"},\"state\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"active\"},\"metadata\":{\"type\":\"JSON\",\"notNull\":false,\"default\":{}},\"thumbnail_asset_id\":{\"type\":\"UUID\",\"referenceKind\":\"crossPackageRef\",\"notNull\":false},\"feed_source_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":false,\"foreignKey\":{\"table\":\"content_feed_sources\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"source_guid\":{\"type\":\"TEXT\",\"notNull\":false},\"source_name\":{\"type\":\"TEXT\",\"notNull\":false},\"source_homepage_url\":{\"type\":\"TEXT\",\"notNull\":false},\"external_url\":{\"type\":\"TEXT\",\"notNull\":false},\"original_published_at\":{\"type\":\"TIMESTAMP\",\"notNull\":false},\"dedupe_key\":{\"type\":\"TEXT\",\"notNull\":false}},\"indexes\":[{\"name\":\"contents_slug_context_meta_type_idx\",\"columns\":[\"tenant_id\",\"slug\",\"context\",\"_meta_type\"],\"unique\":true},{\"name\":\"contents_meta_type_idx\",\"columns\":[\"_meta_type\"]},{\"name\":\"contents_tenant_id_publish_date_idx\",\"columns\":[\"tenant_id\",\"publish_date\"]},{\"name\":\"contents_tenant_id_created_at_idx\",\"columns\":[\"tenant_id\",\"created_at\"]},{\"name\":\"contents_thumbnail_asset_id_idx\",\"columns\":[\"thumbnail_asset_id\"]},{\"name\":\"contents_feed_source_id_idx\",\"columns\":[\"feed_source_id\"]}],\"version\":\"8107d801\"}},\"@happyvertical/smrt-content:Mirror\":{\"name\":\"mirror\",\"className\":\"Mirror\",\"qualifiedName\":\"@happyvertical/smrt-content:Mirror\",\"collection\":\"contents\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/content/src/content-types.ts\",\"packageName\":\"@happyvertical/smrt-content\",\"fields\":{\"created_at\":{\"type\":\"datetime\",\"required\":false},\"updated_at\":{\"type\":\"datetime\",\"required\":false},\"tenantId\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"sqlType\":\"UUID\",\"nullable\":true,\"__tenancy\":{\"isTenantIdField\":true,\"autoFilter\":true,\"required\":false,\"autoPopulate\":true,\"nullable\":true}}},\"type\":{\"type\":\"text\",\"required\":false},\"variant\":{\"type\":\"text\",\"required\":false},\"fileKey\":{\"type\":\"text\",\"required\":false},\"author\":{\"type\":\"text\",\"required\":false},\"name\":{\"type\":\"text\",\"required\":true,\"default\":\"\",\"_meta\":{\"required\":true}},\"title\":{\"type\":\"text\",\"required\":false},\"description\":{\"type\":\"text\",\"required\":false},\"body\":{\"type\":\"text\",\"required\":false},\"bodyFormat\":{\"type\":\"text\",\"required\":false},\"publish_date\":{\"type\":\"datetime\",\"required\":false},\"url\":{\"type\":\"text\",\"required\":false},\"source\":{\"type\":\"text\",\"required\":false},\"original_url\":{\"type\":\"text\",\"required\":false},\"language\":{\"type\":\"text\",\"required\":false},\"tags\":{\"type\":\"json\",\"required\":false,\"default\":[]},\"category\":{\"type\":\"text\",\"required\":false},\"status\":{\"type\":\"text\",\"required\":false,\"default\":\"draft\"},\"state\":{\"type\":\"text\",\"required\":false,\"default\":\"active\"},\"metadata\":{\"type\":\"json\",\"required\":false,\"default\":{}},\"thumbnailAssetId\":{\"type\":\"crossPackageRef\",\"required\":false,\"related\":\"@happyvertical/smrt-assets:Asset\"},\"feedSourceId\":{\"type\":\"foreignKey\",\"required\":false,\"related\":\"ContentFeedSource\"},\"sourceGuid\":{\"type\":\"text\",\"required\":false},\"sourceName\":{\"type\":\"text\",\"required\":false},\"sourceHomepageUrl\":{\"type\":\"text\",\"required\":false},\"externalUrl\":{\"type\":\"text\",\"required\":false},\"originalPublishedAt\":{\"type\":\"datetime\",\"required\":false},\"dedupeKey\":{\"type\":\"text\",\"required\":false}},\"methods\":{\"initialize\":{\"name\":\"initialize\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<this>\",\"isStatic\":false,\"isPublic\":true},\"save\":{\"name\":\"save\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"SmrtSaveOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"resolveGovernance\":{\"name\":\"resolveGovernance\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<ResolvedContentGovernance>\",\"isStatic\":false,\"isPublic\":true},\"loadReferences\":{\"name\":\"loadReferences\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"addReference\":{\"name\":\"addReference\",\"async\":true,\"parameters\":[{\"name\":\"content\",\"type\":\"Content | string\",\"optional\":false,\"unionBranches\":[{\"type\":\"Content\"},{\"type\":\"string\"}]},{\"name\":\"options\",\"type\":\"object\",\"optional\":true,\"memberTypes\":[\"number | null\"]}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"removeReference\":{\"name\":\"removeReference\",\"async\":true,\"parameters\":[{\"name\":\"targetId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getReferences\":{\"name\":\"getReferences\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getReferenceEdges\":{\"name\":\"getReferenceEdges\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<Array<object>>\",\"isStatic\":false,\"isPublic\":true},\"getReferenceDrift\":{\"name\":\"getReferenceDrift\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<Array<object>>\",\"isStatic\":false,\"isPublic\":true},\"isGoverned\":{\"name\":\"isGoverned\",\"async\":false,\"parameters\":[],\"returnType\":\"boolean\",\"isStatic\":false,\"isPublic\":true},\"getFactLinks\":{\"name\":\"getFactLinks\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":true,\"memberTypes\":[\"FactContentRelationship\"]}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getFacts\":{\"name\":\"getFacts\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":true,\"memberTypes\":[\"FactContentRelationship\",\"boolean\"]}],\"returnType\":\"Promise<Fact[]>\",\"isStatic\":false,\"isPublic\":true},\"addFact\":{\"name\":\"addFact\",\"async\":true,\"parameters\":[{\"name\":\"fact\",\"type\":\"Fact | string\",\"optional\":false,\"unionBranches\":[{\"type\":\"Fact\"},{\"type\":\"string\"}]},{\"name\":\"relationship\",\"type\":\"FactContentRelationship\",\"optional\":true},{\"name\":\"metadata\",\"type\":\"Record<string, unknown>\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"removeFact\":{\"name\":\"removeFact\",\"async\":true,\"parameters\":[{\"name\":\"factId\",\"type\":\"string\",\"optional\":false},{\"name\":\"relationship\",\"type\":\"FactContentRelationship\",\"optional\":true}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"syncFacts\":{\"name\":\"syncFacts\",\"async\":true,\"parameters\":[{\"name\":\"factIds\",\"type\":\"string[]\",\"optional\":false},{\"name\":\"relationship\",\"type\":\"FactContentRelationship\",\"optional\":true}],\"returnType\":\"Promise<object>\",\"isStatic\":false,\"isPublic\":true},\"browseFacts\":{\"name\":\"browseFacts\",\"async\":true,\"parameters\":[{\"name\":\"query\",\"type\":\"any\",\"optional\":true,\"default\":\"\"},{\"name\":\"options\",\"type\":\"object\",\"optional\":true,\"memberTypes\":[\"number\",\"boolean\"]}],\"returnType\":\"Promise<Fact[]>\",\"isStatic\":false,\"isPublic\":true},\"repairFactAudit\":{\"name\":\"repairFactAudit\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":true,\"memberTypes\":[\"number\",\"string\"]}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"repairFactAuditAction\":{\"name\":\"repairFactAuditAction\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":true,\"memberTypes\":[\"number\",\"string\"]}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"repairFactEvidence\":{\"name\":\"repairFactEvidence\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"FactAuditResourceRepairOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"repairFactEvidenceAction\":{\"name\":\"repairFactEvidenceAction\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"FactAuditResourceRepairOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"recheckFactClaims\":{\"name\":\"recheckFactClaims\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"FactAuditClaimRecheckOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"recheckFactClaimsAction\":{\"name\":\"recheckFactClaimsAction\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"FactAuditClaimRecheckOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"updateFactEvidenceStatus\":{\"name\":\"updateFactEvidenceStatus\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"FactEvidenceStatusUpdateOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"updateFactEvidenceStatusAction\":{\"name\":\"updateFactEvidenceStatusAction\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"FactEvidenceStatusUpdateOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getFactAuditState\":{\"name\":\"getFactAuditState\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<FactAuditState>\",\"isStatic\":false,\"isPublic\":true},\"getFactAuditStateAction\":{\"name\":\"getFactAuditStateAction\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getFactsState\":{\"name\":\"getFactsState\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":true,\"memberTypes\":[\"FactContentRelationship\"]}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"syncFactsState\":{\"name\":\"syncFactsState\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":true,\"memberTypes\":[\"string[]\",\"FactContentRelationship\"]}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"createVersion\":{\"name\":\"createVersion\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"CreateContentVersionOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getVersions\":{\"name\":\"getVersions\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"restoreFromVersion\":{\"name\":\"restoreFromVersion\",\"async\":true,\"parameters\":[{\"name\":\"versionNumber\",\"type\":\"number\",\"optional\":false}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getReviews\":{\"name\":\"getReviews\",\"async\":true,\"parameters\":[{\"name\":\"kind\",\"type\":\"any\",\"optional\":true,\"typeUnresolved\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"listReviews\":{\"name\":\"listReviews\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":true,\"typeUnresolved\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getReviewRequirements\":{\"name\":\"getReviewRequirements\",\"async\":true,\"parameters\":[{\"name\":\"profileKey\",\"type\":\"string\",\"optional\":false},{\"name\":\"governance\",\"type\":\"ResolvedContentGovernance\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getGovernanceState\":{\"name\":\"getGovernanceState\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<ContentGovernanceState>\",\"isStatic\":false,\"isPublic\":true},\"getGovernanceStateAction\":{\"name\":\"getGovernanceStateAction\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"listReviewProfilesAction\":{\"name\":\"listReviewProfilesAction\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"evaluateReviewProfile\":{\"name\":\"evaluateReviewProfile\",\"async\":true,\"parameters\":[{\"name\":\"profileKey\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<ContentReviewProfileEvaluation>\",\"isStatic\":false,\"isPublic\":true},\"evaluateReviewProfileAction\":{\"name\":\"evaluateReviewProfileAction\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":true,\"memberTypes\":[\"string\"]}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"isReadyForReviewProfile\":{\"name\":\"isReadyForReviewProfile\",\"async\":true,\"parameters\":[{\"name\":\"profileKey\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<boolean>\",\"isStatic\":false,\"isPublic\":true},\"getPublishedTransparency\":{\"name\":\"getPublishedTransparency\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getPublishedTransparencyAction\":{\"name\":\"getPublishedTransparencyAction\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"previewTransparency\":{\"name\":\"previewTransparency\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"previewTransparencyAction\":{\"name\":\"previewTransparencyAction\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"runReview\":{\"name\":\"runReview\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"RunContentReviewOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"runReviewAction\":{\"name\":\"runReviewAction\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"RunContentReviewOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"reviewFacts\":{\"name\":\"reviewFacts\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"Omit<RunContentReviewOptions, 'kind'>\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"reviewSafety\":{\"name\":\"reviewSafety\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"Omit<RunContentReviewOptions, 'kind'>\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getCorrections\":{\"name\":\"getCorrections\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"listCorrections\":{\"name\":\"listCorrections\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"issueCorrection\":{\"name\":\"issueCorrection\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"IssueContentCorrectionOptions\",\"optional\":false}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"issueCorrectionAction\":{\"name\":\"issueCorrectionAction\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"IssueContentCorrectionOptions\",\"optional\":false}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"listVersions\":{\"name\":\"listVersions\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"mutateVersionAction\":{\"name\":\"mutateVersionAction\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"any\",\"optional\":true,\"typeUnresolved\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getCategorySegments\":{\"name\":\"getCategorySegments\",\"async\":false,\"parameters\":[],\"returnType\":\"string[]\",\"isStatic\":false,\"isPublic\":true},\"getParentCategory\":{\"name\":\"getParentCategory\",\"async\":false,\"parameters\":[],\"returnType\":\"string | null\",\"isStatic\":false,\"isPublic\":true},\"getRootCategory\":{\"name\":\"getRootCategory\",\"async\":false,\"parameters\":[],\"returnType\":\"string | null\",\"isStatic\":false,\"isPublic\":true},\"getAncestorPaths\":{\"name\":\"getAncestorPaths\",\"async\":false,\"parameters\":[],\"returnType\":\"string[]\",\"isStatic\":false,\"isPublic\":true},\"isInCategory\":{\"name\":\"isInCategory\",\"async\":false,\"parameters\":[{\"name\":\"categoryPath\",\"type\":\"string\",\"optional\":false},{\"name\":\"includeChildren\",\"type\":\"any\",\"optional\":true}],\"returnType\":\"boolean\",\"isStatic\":false,\"isPublic\":true},\"getAssets\":{\"name\":\"getAssets\",\"async\":true,\"parameters\":[{\"name\":\"relationship\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<Asset[]>\",\"isStatic\":false,\"isPublic\":true},\"addAsset\":{\"name\":\"addAsset\",\"async\":true,\"parameters\":[{\"name\":\"asset\",\"type\":\"Asset\",\"optional\":false},{\"name\":\"relationship\",\"type\":\"any\",\"optional\":true,\"default\":\"attachment\"},{\"name\":\"sortOrder\",\"type\":\"any\",\"optional\":true}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"removeAsset\":{\"name\":\"removeAsset\",\"async\":true,\"parameters\":[{\"name\":\"assetId\",\"type\":\"string\",\"optional\":false},{\"name\":\"relationship\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"getMetadata\":{\"name\":\"getMetadata\",\"async\":false,\"parameters\":[],\"returnType\":\"Record<string, unknown>\",\"isStatic\":false,\"isPublic\":true},\"setMetadata\":{\"name\":\"setMetadata\",\"async\":false,\"parameters\":[{\"name\":\"metadata\",\"type\":\"Record<string, unknown> | null | undefined\",\"optional\":false,\"unionBranches\":[{\"type\":\"Record<string, unknown>\"},{\"type\":\"null\"},{\"type\":\"undefined\"}]}],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"updateMetadata\":{\"name\":\"updateMetadata\",\"async\":false,\"parameters\":[{\"name\":\"patch\",\"type\":\"Partial<Record<string, unknown>>\",\"optional\":false}],\"returnType\":\"Record<string, unknown>\",\"isStatic\":false,\"isPublic\":true},\"getThumbnail\":{\"name\":\"getThumbnail\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<Image | null>\",\"isStatic\":false,\"isPublic\":true},\"setThumbnail\":{\"name\":\"setThumbnail\",\"async\":true,\"parameters\":[{\"name\":\"image\",\"type\":\"Image\",\"optional\":false}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"generateThumbnail\":{\"name\":\"generateThumbnail\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"ThumbnailOptions\",\"optional\":false}],\"returnType\":\"Promise<Image>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableStrategy\":\"sti\",\"api\":false,\"mcp\":false,\"cli\":false,\"tableName\":\"contents\"},\"extends\":\"Content\",\"exportName\":\"Mirror\",\"collectionExportName\":\"MirrorCollection\",\"validationRules\":[{\"field\":\"name\",\"rule\":\"required\",\"fieldType\":\"text\"}],\"schema\":{\"tableName\":\"contents\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"contents\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"_meta_type\\\" TEXT NOT NULL,\\n \\\"_meta_data\\\" JSON,\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"tenant_id\\\" UUID,\\n \\\"type\\\" TEXT,\\n \\\"variant\\\" TEXT,\\n \\\"file_key\\\" TEXT,\\n \\\"author\\\" TEXT,\\n \\\"name\\\" TEXT DEFAULT '',\\n \\\"title\\\" TEXT,\\n \\\"description\\\" TEXT,\\n \\\"body\\\" TEXT,\\n \\\"body_format\\\" TEXT,\\n \\\"publish_date\\\" TIMESTAMP,\\n \\\"url\\\" TEXT,\\n \\\"source\\\" TEXT,\\n \\\"original_url\\\" TEXT,\\n \\\"language\\\" TEXT,\\n \\\"tags\\\" JSON DEFAULT '[]',\\n \\\"category\\\" TEXT,\\n \\\"status\\\" TEXT DEFAULT 'draft',\\n \\\"state\\\" TEXT DEFAULT 'active',\\n \\\"metadata\\\" JSON DEFAULT '{}',\\n \\\"thumbnail_asset_id\\\" UUID,\\n \\\"feed_source_id\\\" UUID,\\n \\\"source_guid\\\" TEXT,\\n \\\"source_name\\\" TEXT,\\n \\\"source_homepage_url\\\" TEXT,\\n \\\"external_url\\\" TEXT,\\n \\\"original_published_at\\\" TIMESTAMP,\\n \\\"dedupe_key\\\" TEXT\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"_meta_type\":{\"type\":\"TEXT\",\"notNull\":true},\"_meta_data\":{\"type\":\"JSON\",\"notNull\":false},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"tenantId\",\"notNull\":false},\"type\":{\"type\":\"TEXT\",\"notNull\":false},\"variant\":{\"type\":\"TEXT\",\"notNull\":false},\"file_key\":{\"type\":\"TEXT\",\"notNull\":false},\"author\":{\"type\":\"TEXT\",\"notNull\":false},\"name\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"\"},\"title\":{\"type\":\"TEXT\",\"notNull\":false},\"description\":{\"type\":\"TEXT\",\"notNull\":false},\"body\":{\"type\":\"TEXT\",\"notNull\":false},\"body_format\":{\"type\":\"TEXT\",\"notNull\":false},\"publish_date\":{\"type\":\"TIMESTAMP\",\"notNull\":false},\"url\":{\"type\":\"TEXT\",\"notNull\":false},\"source\":{\"type\":\"TEXT\",\"notNull\":false},\"original_url\":{\"type\":\"TEXT\",\"notNull\":false},\"language\":{\"type\":\"TEXT\",\"notNull\":false},\"tags\":{\"type\":\"JSON\",\"notNull\":false,\"default\":[]},\"category\":{\"type\":\"TEXT\",\"notNull\":false},\"status\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"draft\"},\"state\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"active\"},\"metadata\":{\"type\":\"JSON\",\"notNull\":false,\"default\":{}},\"thumbnail_asset_id\":{\"type\":\"UUID\",\"referenceKind\":\"crossPackageRef\",\"notNull\":false},\"feed_source_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":false,\"foreignKey\":{\"table\":\"content_feed_sources\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"source_guid\":{\"type\":\"TEXT\",\"notNull\":false},\"source_name\":{\"type\":\"TEXT\",\"notNull\":false},\"source_homepage_url\":{\"type\":\"TEXT\",\"notNull\":false},\"external_url\":{\"type\":\"TEXT\",\"notNull\":false},\"original_published_at\":{\"type\":\"TIMESTAMP\",\"notNull\":false},\"dedupe_key\":{\"type\":\"TEXT\",\"notNull\":false}},\"indexes\":[{\"name\":\"contents_slug_context_meta_type_idx\",\"columns\":[\"tenant_id\",\"slug\",\"context\",\"_meta_type\"],\"unique\":true},{\"name\":\"contents_meta_type_idx\",\"columns\":[\"_meta_type\"]},{\"name\":\"contents_tenant_id_publish_date_idx\",\"columns\":[\"tenant_id\",\"publish_date\"]},{\"name\":\"contents_tenant_id_created_at_idx\",\"columns\":[\"tenant_id\",\"created_at\"]},{\"name\":\"contents_thumbnail_asset_id_idx\",\"columns\":[\"thumbnail_asset_id\"]},{\"name\":\"contents_feed_source_id_idx\",\"columns\":[\"feed_source_id\"]}],\"version\":\"088da7e4\"}},\"@happyvertical/smrt-content:ContentVersion\":{\"name\":\"contentversion\",\"className\":\"ContentVersion\",\"qualifiedName\":\"@happyvertical/smrt-content:ContentVersion\",\"collection\":\"contentversions\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/content/src/content-version.ts\",\"packageName\":\"@happyvertical/smrt-content\",\"fields\":{\"contentId\":{\"type\":\"foreignKey\",\"required\":true,\"related\":\"Content\",\"_meta\":{\"required\":true}},\"version\":{\"type\":\"integer\",\"required\":true,\"default\":1},\"kind\":{\"type\":\"text\",\"required\":false,\"default\":\"manual\"},\"title\":{\"type\":\"text\",\"required\":false},\"description\":{\"type\":\"text\",\"required\":false},\"body\":{\"type\":\"text\",\"required\":false},\"status\":{\"type\":\"text\",\"required\":false},\"summary\":{\"type\":\"text\",\"required\":false},\"snapshot\":{\"type\":\"text\",\"required\":false},\"metadata\":{\"type\":\"text\",\"required\":false},\"tenantId\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"sqlType\":\"UUID\",\"nullable\":true,\"__tenancy\":{\"isTenantIdField\":true,\"autoFilter\":true,\"required\":false,\"autoPopulate\":true,\"nullable\":true,\"mode\":\"optional\",\"field\":\"tenantId\",\"allowSuperAdminBypass\":false}}},\"createdAt\":{\"type\":\"text\",\"required\":false},\"updatedAt\":{\"type\":\"text\",\"required\":false}},\"methods\":{\"getSnapshot\":{\"name\":\"getSnapshot\",\"async\":false,\"parameters\":[],\"returnType\":\"Record<string, unknown>\",\"isStatic\":false,\"isPublic\":true},\"getMetadata\":{\"name\":\"getMetadata\",\"async\":false,\"parameters\":[],\"returnType\":\"ContentVersionMetadata\",\"isStatic\":false,\"isPublic\":true},\"getTransparency\":{\"name\":\"getTransparency\",\"async\":false,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getTransparencyAction\":{\"name\":\"getTransparencyAction\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableName\":\"content_versions\",\"conflictColumns\":[\"content_id\",\"version\"],\"api\":{\"include\":[\"list\",\"get\",\"create\",\"getTransparencyAction\"],\"routes\":{\"getTransparencyAction\":{\"method\":\"GET\",\"path\":\"transparency\"}}},\"mcp\":{\"include\":[\"list\",\"get\",\"create\"]},\"cli\":true,\"tenantScoped\":{\"mode\":\"optional\"}},\"extends\":\"SmrtObject\",\"exportName\":\"ContentVersion\",\"collectionExportName\":\"ContentVersionCollection\",\"validationRules\":[{\"field\":\"contentId\",\"rule\":\"required\",\"fieldType\":\"foreignKey\"},{\"field\":\"version\",\"rule\":\"required\",\"fieldType\":\"integer\"}],\"schema\":{\"tableName\":\"content_versions\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"content_versions\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"content_id\\\" UUID NOT NULL,\\n \\\"version\\\" INTEGER NOT NULL DEFAULT 1,\\n \\\"kind\\\" TEXT DEFAULT 'manual',\\n \\\"title\\\" TEXT,\\n \\\"description\\\" TEXT,\\n \\\"body\\\" TEXT,\\n \\\"status\\\" TEXT,\\n \\\"summary\\\" TEXT,\\n \\\"snapshot\\\" TEXT,\\n \\\"metadata\\\" TEXT,\\n \\\"tenant_id\\\" UUID\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"content_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":true,\"unique\":false,\"foreignKey\":{\"table\":\"contents\",\"column\":\"id\",\"onDelete\":\"CASCADE\",\"onUpdate\":\"CASCADE\"}},\"version\":{\"type\":\"INTEGER\",\"notNull\":true,\"unique\":false,\"default\":1},\"kind\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"manual\"},\"title\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"description\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"body\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"status\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"summary\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"snapshot\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"metadata\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"tenantId\",\"notNull\":false,\"unique\":false}},\"indexes\":[{\"name\":\"content_versions_content_id_version_idx\",\"columns\":[\"content_id\",\"version\"],\"unique\":true},{\"name\":\"content_versions_slug_context_idx\",\"columns\":[\"slug\",\"context\"]},{\"name\":\"content_versions_tenant_id_created_at_idx\",\"columns\":[\"tenant_id\",\"created_at\"]}],\"version\":\"66cda211\"}},\"@happyvertical/smrt-content:ContentVersionCollection\":{\"name\":\"contentversioncollection\",\"className\":\"ContentVersionCollection\",\"qualifiedName\":\"@happyvertical/smrt-content:ContentVersionCollection\",\"collection\":\"contentversions\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/content/src/content-versions.ts\",\"packageName\":\"@happyvertical/smrt-content\",\"fields\":{},\"methods\":{\"listForContent\":{\"name\":\"listForContent\",\"async\":true,\"parameters\":[{\"name\":\"contentId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<ContentVersion[]>\",\"isStatic\":false,\"isPublic\":true},\"getLatestForContent\":{\"name\":\"getLatestForContent\",\"async\":true,\"parameters\":[{\"name\":\"contentId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<ContentVersion | null>\",\"isStatic\":false,\"isPublic\":true},\"getLatestPublishedForContent\":{\"name\":\"getLatestPublishedForContent\",\"async\":true,\"parameters\":[{\"name\":\"contentId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<ContentVersion | null>\",\"isStatic\":false,\"isPublic\":true},\"getVersion\":{\"name\":\"getVersion\",\"async\":true,\"parameters\":[{\"name\":\"contentId\",\"type\":\"string\",\"optional\":false},{\"name\":\"versionNumber\",\"type\":\"number\",\"optional\":false}],\"returnType\":\"Promise<ContentVersion | null>\",\"isStatic\":false,\"isPublic\":true},\"getNextVersionNumber\":{\"name\":\"getNextVersionNumber\",\"async\":true,\"parameters\":[{\"name\":\"contentId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<number>\",\"isStatic\":false,\"isPublic\":true},\"createSnapshot\":{\"name\":\"createSnapshot\",\"async\":true,\"parameters\":[{\"name\":\"content\",\"type\":\"Content\",\"optional\":false},{\"name\":\"options\",\"type\":\"CreateContentVersionOptions\",\"optional\":true}],\"returnType\":\"Promise<ContentVersion>\",\"isStatic\":false,\"isPublic\":true},\"restoreIntoContent\":{\"name\":\"restoreIntoContent\",\"async\":true,\"parameters\":[{\"name\":\"content\",\"type\":\"Content\",\"optional\":false},{\"name\":\"versionNumber\",\"type\":\"number\",\"optional\":false}],\"returnType\":\"Promise<Content>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableName\":\"content_versions\"},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"ContentVersion\",\"exportName\":\"ContentVersionCollection\",\"collectionExportName\":\"ContentVersionCollectionCollection\",\"schema\":{\"tableName\":\"content_versions\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"content_versions\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"}},\"indexes\":[{\"name\":\"content_versions_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true},{\"name\":\"content_versions_created_at_idx\",\"columns\":[\"created_at\"]}],\"version\":\"56acd806\"}},\"@happyvertical/smrt-content:Content\":{\"name\":\"content\",\"className\":\"Content\",\"qualifiedName\":\"@happyvertical/smrt-content:Content\",\"collection\":\"contents\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/content/src/content.ts\",\"packageName\":\"@happyvertical/smrt-content\",\"fields\":{\"created_at\":{\"type\":\"datetime\",\"required\":false},\"updated_at\":{\"type\":\"datetime\",\"required\":false},\"tenantId\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"sqlType\":\"UUID\",\"nullable\":true,\"__tenancy\":{\"isTenantIdField\":true,\"autoFilter\":true,\"required\":false,\"autoPopulate\":true,\"nullable\":true,\"mode\":\"optional\",\"field\":\"tenantId\",\"allowSuperAdminBypass\":false}}},\"type\":{\"type\":\"text\",\"required\":false},\"variant\":{\"type\":\"text\",\"required\":false},\"fileKey\":{\"type\":\"text\",\"required\":false},\"author\":{\"type\":\"text\",\"required\":false},\"name\":{\"type\":\"text\",\"required\":true,\"default\":\"\",\"_meta\":{\"required\":true}},\"title\":{\"type\":\"text\",\"required\":false},\"description\":{\"type\":\"text\",\"required\":false},\"body\":{\"type\":\"text\",\"required\":false},\"bodyFormat\":{\"type\":\"text\",\"required\":false},\"publish_date\":{\"type\":\"datetime\",\"required\":false},\"url\":{\"type\":\"text\",\"required\":false},\"source\":{\"type\":\"text\",\"required\":false},\"original_url\":{\"type\":\"text\",\"required\":false},\"language\":{\"type\":\"text\",\"required\":false},\"tags\":{\"type\":\"json\",\"required\":false,\"default\":[]},\"category\":{\"type\":\"text\",\"required\":false},\"status\":{\"type\":\"text\",\"required\":false,\"default\":\"draft\"},\"state\":{\"type\":\"text\",\"required\":false,\"default\":\"active\"},\"metadata\":{\"type\":\"json\",\"required\":false,\"default\":{}},\"thumbnailAssetId\":{\"type\":\"crossPackageRef\",\"required\":false,\"related\":\"@happyvertical/smrt-assets:Asset\"}},\"methods\":{\"initialize\":{\"name\":\"initialize\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<this>\",\"isStatic\":false,\"isPublic\":true},\"save\":{\"name\":\"save\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"SmrtSaveOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"resolveGovernance\":{\"name\":\"resolveGovernance\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<ResolvedContentGovernance>\",\"isStatic\":false,\"isPublic\":true},\"loadReferences\":{\"name\":\"loadReferences\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"addReference\":{\"name\":\"addReference\",\"async\":true,\"parameters\":[{\"name\":\"content\",\"type\":\"Content | string\",\"optional\":false,\"unionBranches\":[{\"type\":\"Content\"},{\"type\":\"string\"}]},{\"name\":\"options\",\"type\":\"object\",\"optional\":true,\"memberTypes\":[\"number | null\"]}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"removeReference\":{\"name\":\"removeReference\",\"async\":true,\"parameters\":[{\"name\":\"targetId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getReferences\":{\"name\":\"getReferences\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getReferenceEdges\":{\"name\":\"getReferenceEdges\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<Array<object>>\",\"isStatic\":false,\"isPublic\":true},\"getReferenceDrift\":{\"name\":\"getReferenceDrift\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<Array<object>>\",\"isStatic\":false,\"isPublic\":true},\"isGoverned\":{\"name\":\"isGoverned\",\"async\":false,\"parameters\":[],\"returnType\":\"boolean\",\"isStatic\":false,\"isPublic\":true},\"getFactLinks\":{\"name\":\"getFactLinks\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":true,\"memberTypes\":[\"FactContentRelationship\"]}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getFacts\":{\"name\":\"getFacts\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":true,\"memberTypes\":[\"FactContentRelationship\",\"boolean\"]}],\"returnType\":\"Promise<Fact[]>\",\"isStatic\":false,\"isPublic\":true},\"addFact\":{\"name\":\"addFact\",\"async\":true,\"parameters\":[{\"name\":\"fact\",\"type\":\"Fact | string\",\"optional\":false,\"unionBranches\":[{\"type\":\"Fact\"},{\"type\":\"string\"}]},{\"name\":\"relationship\",\"type\":\"FactContentRelationship\",\"optional\":true},{\"name\":\"metadata\",\"type\":\"Record<string, unknown>\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"removeFact\":{\"name\":\"removeFact\",\"async\":true,\"parameters\":[{\"name\":\"factId\",\"type\":\"string\",\"optional\":false},{\"name\":\"relationship\",\"type\":\"FactContentRelationship\",\"optional\":true}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"syncFacts\":{\"name\":\"syncFacts\",\"async\":true,\"parameters\":[{\"name\":\"factIds\",\"type\":\"string[]\",\"optional\":false},{\"name\":\"relationship\",\"type\":\"FactContentRelationship\",\"optional\":true}],\"returnType\":\"Promise<object>\",\"isStatic\":false,\"isPublic\":true},\"browseFacts\":{\"name\":\"browseFacts\",\"async\":true,\"parameters\":[{\"name\":\"query\",\"type\":\"any\",\"optional\":true,\"default\":\"\"},{\"name\":\"options\",\"type\":\"object\",\"optional\":true,\"memberTypes\":[\"number\",\"boolean\"]}],\"returnType\":\"Promise<Fact[]>\",\"isStatic\":false,\"isPublic\":true},\"repairFactAudit\":{\"name\":\"repairFactAudit\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":true,\"memberTypes\":[\"number\",\"string\"]}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"repairFactAuditAction\":{\"name\":\"repairFactAuditAction\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":true,\"memberTypes\":[\"number\",\"string\"]}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"repairFactEvidence\":{\"name\":\"repairFactEvidence\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"FactAuditResourceRepairOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"repairFactEvidenceAction\":{\"name\":\"repairFactEvidenceAction\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"FactAuditResourceRepairOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"recheckFactClaims\":{\"name\":\"recheckFactClaims\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"FactAuditClaimRecheckOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"recheckFactClaimsAction\":{\"name\":\"recheckFactClaimsAction\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"FactAuditClaimRecheckOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"updateFactEvidenceStatus\":{\"name\":\"updateFactEvidenceStatus\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"FactEvidenceStatusUpdateOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"updateFactEvidenceStatusAction\":{\"name\":\"updateFactEvidenceStatusAction\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"FactEvidenceStatusUpdateOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getFactAuditState\":{\"name\":\"getFactAuditState\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<FactAuditState>\",\"isStatic\":false,\"isPublic\":true},\"getFactAuditStateAction\":{\"name\":\"getFactAuditStateAction\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getFactsState\":{\"name\":\"getFactsState\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":true,\"memberTypes\":[\"FactContentRelationship\"]}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"syncFactsState\":{\"name\":\"syncFactsState\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":true,\"memberTypes\":[\"string[]\",\"FactContentRelationship\"]}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"createVersion\":{\"name\":\"createVersion\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"CreateContentVersionOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getVersions\":{\"name\":\"getVersions\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"restoreFromVersion\":{\"name\":\"restoreFromVersion\",\"async\":true,\"parameters\":[{\"name\":\"versionNumber\",\"type\":\"number\",\"optional\":false}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getReviews\":{\"name\":\"getReviews\",\"async\":true,\"parameters\":[{\"name\":\"kind\",\"type\":\"any\",\"optional\":true,\"typeUnresolved\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"listReviews\":{\"name\":\"listReviews\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":true,\"typeUnresolved\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getReviewRequirements\":{\"name\":\"getReviewRequirements\",\"async\":true,\"parameters\":[{\"name\":\"profileKey\",\"type\":\"string\",\"optional\":false},{\"name\":\"governance\",\"type\":\"ResolvedContentGovernance\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getGovernanceState\":{\"name\":\"getGovernanceState\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<ContentGovernanceState>\",\"isStatic\":false,\"isPublic\":true},\"getGovernanceStateAction\":{\"name\":\"getGovernanceStateAction\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"listReviewProfilesAction\":{\"name\":\"listReviewProfilesAction\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"evaluateReviewProfile\":{\"name\":\"evaluateReviewProfile\",\"async\":true,\"parameters\":[{\"name\":\"profileKey\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<ContentReviewProfileEvaluation>\",\"isStatic\":false,\"isPublic\":true},\"evaluateReviewProfileAction\":{\"name\":\"evaluateReviewProfileAction\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":true,\"memberTypes\":[\"string\"]}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"isReadyForReviewProfile\":{\"name\":\"isReadyForReviewProfile\",\"async\":true,\"parameters\":[{\"name\":\"profileKey\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<boolean>\",\"isStatic\":false,\"isPublic\":true},\"getPublishedTransparency\":{\"name\":\"getPublishedTransparency\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getPublishedTransparencyAction\":{\"name\":\"getPublishedTransparencyAction\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"previewTransparency\":{\"name\":\"previewTransparency\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"previewTransparencyAction\":{\"name\":\"previewTransparencyAction\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"runReview\":{\"name\":\"runReview\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"RunContentReviewOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"runReviewAction\":{\"name\":\"runReviewAction\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"RunContentReviewOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"reviewFacts\":{\"name\":\"reviewFacts\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"Omit<RunContentReviewOptions, 'kind'>\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"reviewSafety\":{\"name\":\"reviewSafety\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"Omit<RunContentReviewOptions, 'kind'>\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getCorrections\":{\"name\":\"getCorrections\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"listCorrections\":{\"name\":\"listCorrections\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"issueCorrection\":{\"name\":\"issueCorrection\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"IssueContentCorrectionOptions\",\"optional\":false}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"issueCorrectionAction\":{\"name\":\"issueCorrectionAction\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"IssueContentCorrectionOptions\",\"optional\":false}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"listVersions\":{\"name\":\"listVersions\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"mutateVersionAction\":{\"name\":\"mutateVersionAction\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"any\",\"optional\":true,\"typeUnresolved\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getCategorySegments\":{\"name\":\"getCategorySegments\",\"async\":false,\"parameters\":[],\"returnType\":\"string[]\",\"isStatic\":false,\"isPublic\":true},\"getParentCategory\":{\"name\":\"getParentCategory\",\"async\":false,\"parameters\":[],\"returnType\":\"string | null\",\"isStatic\":false,\"isPublic\":true},\"getRootCategory\":{\"name\":\"getRootCategory\",\"async\":false,\"parameters\":[],\"returnType\":\"string | null\",\"isStatic\":false,\"isPublic\":true},\"getAncestorPaths\":{\"name\":\"getAncestorPaths\",\"async\":false,\"parameters\":[],\"returnType\":\"string[]\",\"isStatic\":false,\"isPublic\":true},\"isInCategory\":{\"name\":\"isInCategory\",\"async\":false,\"parameters\":[{\"name\":\"categoryPath\",\"type\":\"string\",\"optional\":false},{\"name\":\"includeChildren\",\"type\":\"any\",\"optional\":true}],\"returnType\":\"boolean\",\"isStatic\":false,\"isPublic\":true},\"getAssets\":{\"name\":\"getAssets\",\"async\":true,\"parameters\":[{\"name\":\"relationship\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<Asset[]>\",\"isStatic\":false,\"isPublic\":true},\"addAsset\":{\"name\":\"addAsset\",\"async\":true,\"parameters\":[{\"name\":\"asset\",\"type\":\"Asset\",\"optional\":false},{\"name\":\"relationship\",\"type\":\"any\",\"optional\":true,\"default\":\"attachment\"},{\"name\":\"sortOrder\",\"type\":\"any\",\"optional\":true}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"removeAsset\":{\"name\":\"removeAsset\",\"async\":true,\"parameters\":[{\"name\":\"assetId\",\"type\":\"string\",\"optional\":false},{\"name\":\"relationship\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"getMetadata\":{\"name\":\"getMetadata\",\"async\":false,\"parameters\":[],\"returnType\":\"Record<string, unknown>\",\"isStatic\":false,\"isPublic\":true},\"setMetadata\":{\"name\":\"setMetadata\",\"async\":false,\"parameters\":[{\"name\":\"metadata\",\"type\":\"Record<string, unknown> | null | undefined\",\"optional\":false,\"unionBranches\":[{\"type\":\"Record<string, unknown>\"},{\"type\":\"null\"},{\"type\":\"undefined\"}]}],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"updateMetadata\":{\"name\":\"updateMetadata\",\"async\":false,\"parameters\":[{\"name\":\"patch\",\"type\":\"Partial<Record<string, unknown>>\",\"optional\":false}],\"returnType\":\"Record<string, unknown>\",\"isStatic\":false,\"isPublic\":true},\"getThumbnail\":{\"name\":\"getThumbnail\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<Image | null>\",\"isStatic\":false,\"isPublic\":true},\"setThumbnail\":{\"name\":\"setThumbnail\",\"async\":true,\"parameters\":[{\"name\":\"image\",\"type\":\"Image\",\"optional\":false}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"generateThumbnail\":{\"name\":\"generateThumbnail\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"ThumbnailOptions\",\"optional\":false}],\"returnType\":\"Promise<Image>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableStrategy\":\"sti\",\"api\":{\"include\":[\"list\",\"get\",\"create\",\"update\",\"delete\",\"getFactsState\",\"syncFactsState\",\"getFactAuditStateAction\",\"repairFactAuditAction\",\"repairFactEvidenceAction\",\"recheckFactClaimsAction\",\"updateFactEvidenceStatusAction\",\"getGovernanceStateAction\",\"listReviews\",\"runReviewAction\",\"listReviewProfilesAction\",\"evaluateReviewProfileAction\",\"getPublishedTransparencyAction\",\"previewTransparencyAction\",\"listCorrections\",\"issueCorrectionAction\",\"listVersions\",\"mutateVersionAction\"],\"routes\":{\"getFactsState\":{\"method\":\"GET\",\"path\":\"facts\"},\"syncFactsState\":{\"method\":\"PUT\",\"path\":\"facts\"},\"getFactAuditStateAction\":{\"method\":\"GET\",\"path\":\"fact-audit\"},\"repairFactAuditAction\":{\"method\":\"POST\",\"path\":\"fact-audit/repair\"},\"repairFactEvidenceAction\":{\"method\":\"POST\",\"path\":\"fact-audit/evidence/repair\"},\"recheckFactClaimsAction\":{\"method\":\"POST\",\"path\":\"fact-audit/claims/recheck\"},\"updateFactEvidenceStatusAction\":{\"method\":\"PUT\",\"path\":\"fact-audit/evidence/status\"},\"getGovernanceStateAction\":{\"method\":\"GET\",\"path\":\"governance\"},\"listReviews\":{\"method\":\"GET\",\"path\":\"reviews\"},\"runReviewAction\":{\"method\":\"POST\",\"path\":\"reviews\"},\"listReviewProfilesAction\":{\"method\":\"GET\",\"path\":\"review-profiles\"},\"evaluateReviewProfileAction\":{\"method\":\"GET\",\"path\":\"review-profiles/[profileKey]\"},\"getPublishedTransparencyAction\":{\"method\":\"GET\",\"path\":\"transparency\"},\"previewTransparencyAction\":{\"method\":\"GET\",\"path\":\"transparency/preview\"},\"listCorrections\":{\"method\":\"GET\",\"path\":\"corrections\"},\"issueCorrectionAction\":{\"method\":\"POST\",\"path\":\"corrections\"},\"listVersions\":{\"method\":\"GET\",\"path\":\"versions\"},\"mutateVersionAction\":{\"method\":\"POST\",\"path\":\"versions\"}},\"serializers\":{\"item\":{\"importPath\":\"$lib/server/content-api-serializers\",\"exportName\":\"serializeContent\"}}},\"mcp\":{\"include\":[\"list\",\"get\",\"create\",\"update\"]},\"cli\":true,\"indexes\":[{\"name\":\"contents_tenant_id_publish_date_idx\",\"columns\":[\"tenantId\",\"publish_date\"]}],\"tenantScoped\":{\"mode\":\"optional\"},\"conflictColumns\":[\"tenant_id\",\"slug\",\"context\",\"_meta_type\"]},\"extends\":\"SmrtObject\",\"exportName\":\"Content\",\"collectionExportName\":\"ContentCollection\",\"validationRules\":[{\"field\":\"name\",\"rule\":\"required\",\"fieldType\":\"text\"}],\"schema\":{\"tableName\":\"contents\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"contents\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"_meta_type\\\" TEXT NOT NULL,\\n \\\"_meta_data\\\" JSON,\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"tenant_id\\\" UUID,\\n \\\"type\\\" TEXT,\\n \\\"variant\\\" TEXT,\\n \\\"file_key\\\" TEXT,\\n \\\"author\\\" TEXT,\\n \\\"name\\\" TEXT DEFAULT '',\\n \\\"title\\\" TEXT,\\n \\\"description\\\" TEXT,\\n \\\"body\\\" TEXT,\\n \\\"body_format\\\" TEXT,\\n \\\"publish_date\\\" TIMESTAMP,\\n \\\"url\\\" TEXT,\\n \\\"source\\\" TEXT,\\n \\\"original_url\\\" TEXT,\\n \\\"language\\\" TEXT,\\n \\\"tags\\\" JSON DEFAULT '[]',\\n \\\"category\\\" TEXT,\\n \\\"status\\\" TEXT DEFAULT 'draft',\\n \\\"state\\\" TEXT DEFAULT 'active',\\n \\\"metadata\\\" JSON DEFAULT '{}',\\n \\\"thumbnail_asset_id\\\" UUID,\\n \\\"feed_source_id\\\" UUID,\\n \\\"source_guid\\\" TEXT,\\n \\\"source_name\\\" TEXT,\\n \\\"source_homepage_url\\\" TEXT,\\n \\\"external_url\\\" TEXT,\\n \\\"original_published_at\\\" TIMESTAMP,\\n \\\"dedupe_key\\\" TEXT\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"_meta_type\":{\"type\":\"TEXT\",\"notNull\":true},\"_meta_data\":{\"type\":\"JSON\",\"notNull\":false},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"tenantId\",\"notNull\":false},\"type\":{\"type\":\"TEXT\",\"notNull\":false},\"variant\":{\"type\":\"TEXT\",\"notNull\":false},\"file_key\":{\"type\":\"TEXT\",\"notNull\":false},\"author\":{\"type\":\"TEXT\",\"notNull\":false},\"name\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"\"},\"title\":{\"type\":\"TEXT\",\"notNull\":false},\"description\":{\"type\":\"TEXT\",\"notNull\":false},\"body\":{\"type\":\"TEXT\",\"notNull\":false},\"body_format\":{\"type\":\"TEXT\",\"notNull\":false},\"publish_date\":{\"type\":\"TIMESTAMP\",\"notNull\":false},\"url\":{\"type\":\"TEXT\",\"notNull\":false},\"source\":{\"type\":\"TEXT\",\"notNull\":false},\"original_url\":{\"type\":\"TEXT\",\"notNull\":false},\"language\":{\"type\":\"TEXT\",\"notNull\":false},\"tags\":{\"type\":\"JSON\",\"notNull\":false,\"default\":[]},\"category\":{\"type\":\"TEXT\",\"notNull\":false},\"status\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"draft\"},\"state\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"active\"},\"metadata\":{\"type\":\"JSON\",\"notNull\":false,\"default\":{}},\"thumbnail_asset_id\":{\"type\":\"UUID\",\"referenceKind\":\"crossPackageRef\",\"notNull\":false},\"feed_source_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":false,\"foreignKey\":{\"table\":\"content_feed_sources\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"source_guid\":{\"type\":\"TEXT\",\"notNull\":false},\"source_name\":{\"type\":\"TEXT\",\"notNull\":false},\"source_homepage_url\":{\"type\":\"TEXT\",\"notNull\":false},\"external_url\":{\"type\":\"TEXT\",\"notNull\":false},\"original_published_at\":{\"type\":\"TIMESTAMP\",\"notNull\":false},\"dedupe_key\":{\"type\":\"TEXT\",\"notNull\":false}},\"indexes\":[{\"name\":\"contents_slug_context_meta_type_idx\",\"columns\":[\"tenant_id\",\"slug\",\"context\",\"_meta_type\"],\"unique\":true},{\"name\":\"contents_meta_type_idx\",\"columns\":[\"_meta_type\"]},{\"name\":\"contents_tenant_id_publish_date_idx\",\"columns\":[\"tenant_id\",\"publish_date\"]},{\"name\":\"contents_tenant_id_created_at_idx\",\"columns\":[\"tenant_id\",\"created_at\"]},{\"name\":\"contents_thumbnail_asset_id_idx\",\"columns\":[\"thumbnail_asset_id\"]},{\"name\":\"contents_feed_source_id_idx\",\"columns\":[\"feed_source_id\"]}],\"version\":\"40e4ddf4\"}},\"@happyvertical/smrt-content:Contents\":{\"name\":\"contents\",\"className\":\"Contents\",\"qualifiedName\":\"@happyvertical/smrt-content:Contents\",\"collection\":\"contents\",\"filePath\":\"/home/runner/work/smrt/smrt/packages/content/src/contents.ts\",\"packageName\":\"@happyvertical/smrt-content\",\"fields\":{\"contentDir\":{\"type\":\"text\",\"required\":false},\"loaded\":{\"type\":\"json\",\"required\":true}},\"methods\":{\"getDb\":{\"name\":\"getDb\",\"async\":false,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"initialize\":{\"name\":\"initialize\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<this>\",\"isStatic\":false,\"isPublic\":true},\"queryAction\":{\"name\":\"queryAction\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"unknown\",\"optional\":false}],\"returnType\":\"Promise<DataQueryResult>\",\"isStatic\":false,\"isPublic\":true},\"browseFacts\":{\"name\":\"browseFacts\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":true,\"memberTypes\":[\"string\",\"number | string\",\"boolean | string\",\"string | null\"]}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getBySlug\":{\"name\":\"getBySlug\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":true,\"memberTypes\":[\"string\",\"string | null\"]}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getGovernanceDefinitionsAction\":{\"name\":\"getGovernanceDefinitionsAction\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":true,\"memberTypes\":[\"string | null\"]}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"resolveGovernanceAction\":{\"name\":\"resolveGovernanceAction\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":true,\"memberTypes\":[\"string\",\"string | null\"]}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"mirror\":{\"name\":\"mirror\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":false,\"typeUnresolved\":true,\"memberTypes\":[\"string\",\"boolean\",\"ResolveHostname\"]}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"writeContentFile\":{\"name\":\"writeContentFile\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":false,\"memberTypes\":[\"Content\",\"string\"]}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"syncContentDir\":{\"name\":\"syncContentDir\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":false,\"memberTypes\":[\"string\"]}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"generateMissingThumbnails\":{\"name\":\"generateMissingThumbnails\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"GenerateMissingThumbnailsOptions\",\"optional\":false}],\"returnType\":\"Promise<object>\",\"isStatic\":false,\"isPublic\":true},\"findByTenant\":{\"name\":\"findByTenant\",\"async\":true,\"parameters\":[{\"name\":\"tenantId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Content[]>\",\"isStatic\":false,\"isPublic\":true},\"findGlobal\":{\"name\":\"findGlobal\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<Content[]>\",\"isStatic\":false,\"isPublic\":true},\"findWithGlobals\":{\"name\":\"findWithGlobals\",\"async\":true,\"parameters\":[{\"name\":\"tenantId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Content[]>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"api\":{\"include\":[\"browseFacts\",\"getBySlug\",\"getGovernanceDefinitionsAction\",\"resolveGovernanceAction\",\"queryAction\"],\"routes\":{\"queryAction\":{\"scope\":\"collection\",\"method\":\"POST\",\"path\":\"query\"},\"browseFacts\":{\"scope\":\"collection\",\"method\":\"GET\",\"path\":\"facts\"},\"getBySlug\":{\"scope\":\"collection\",\"method\":\"GET\",\"path\":\"by-slug\"},\"getGovernanceDefinitionsAction\":{\"scope\":\"collection\",\"method\":\"GET\",\"path\":\"governance\"},\"resolveGovernanceAction\":{\"scope\":\"collection\",\"method\":\"GET\",\"path\":\"governance/resolve\"}}},\"mcp\":false,\"cli\":false},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"Content\",\"exportName\":\"Contents\",\"collectionExportName\":\"ContentsCollection\",\"validationRules\":[{\"field\":\"loaded\",\"rule\":\"required\",\"fieldType\":\"json\"}],\"schema\":{\"tableName\":\"contents\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"contents\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"content_dir\\\" TEXT,\\n \\\"loaded\\\" JSON NOT NULL\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"content_dir\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false},\"loaded\":{\"type\":\"JSON\",\"notNull\":true,\"unique\":false}},\"indexes\":[{\"name\":\"contents_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true},{\"name\":\"contents_created_at_idx\",\"columns\":[\"created_at\"]}],\"version\":\"c11f9ec0\"}}},\"moduleType\":\"smrt\",\"smrtDependencies\":[\"@happyvertical/smrt-agents\",\"@happyvertical/smrt-assets\",\"@happyvertical/smrt-chat\",\"@happyvertical/smrt-core\",\"@happyvertical/smrt-facts\",\"@happyvertical/smrt-images\",\"@happyvertical/smrt-messages\",\"@happyvertical/smrt-profiles\",\"@happyvertical/smrt-prompts\",\"@happyvertical/smrt-tenancy\"]}"));
11
- //#endregion
12
- //#region src/asset-associable.ts
13
- function isAssetAssociable(value) {
14
- if (!value || typeof value !== "object") return false;
15
- const candidate = value;
16
- return typeof candidate.getAssets === "function" && typeof candidate.addAsset === "function" && typeof candidate.removeAsset === "function";
17
- }
18
- function isMetadataAccessor(value) {
19
- if (!value || typeof value !== "object") return false;
20
- const candidate = value;
21
- return typeof candidate.getMetadata === "function" && typeof candidate.setMetadata === "function" && typeof candidate.updateMetadata === "function";
22
- }
23
- function isPlainMetadataRecord(value) {
24
- if (!value || typeof value !== "object") return false;
25
- if (Array.isArray(value)) return false;
26
- const proto = Object.getPrototypeOf(value);
27
- return proto === null || proto === Object.prototype;
28
- }
29
- //#endregion
30
- //#region src/content-asset.ts
31
- var __defProp$4 = Object.defineProperty;
32
- var __getOwnPropDesc$4 = Object.getOwnPropertyDescriptor;
33
- var __decorateClass$4 = (decorators, target, key, kind) => {
34
- var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$4(target, key) : target;
35
- for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
36
- if (kind && result) __defProp$4(target, key, result);
37
- return result;
38
- };
39
- var ContentAsset = class extends SmrtObject {
40
- tenantId = null;
41
- contentId = "";
42
- assetId = "";
43
- relationship = "attachment";
44
- sortOrder = 0;
45
- constructor(options = {}) {
46
- super(options);
47
- if (options.contentId) this.contentId = options.contentId;
48
- if (options.assetId) this.assetId = options.assetId;
49
- if (options.relationship) this.relationship = options.relationship;
50
- if (options.sortOrder !== void 0) this.sortOrder = options.sortOrder;
51
- if (options.tenantId !== void 0) this.tenantId = options.tenantId;
52
- }
53
- };
54
- __decorateClass$4([tenantId({ nullable: true })], ContentAsset.prototype, "tenantId", 2);
55
- __decorateClass$4([foreignKey("Content", { required: true })], ContentAsset.prototype, "contentId", 2);
56
- __decorateClass$4([crossPackageRef("@happyvertical/smrt-assets:Asset", { required: true })], ContentAsset.prototype, "assetId", 2);
57
- __decorateClass$4([field({ required: true })], ContentAsset.prototype, "relationship", 2);
58
- __decorateClass$4([field()], ContentAsset.prototype, "sortOrder", 2);
59
- ContentAsset = __decorateClass$4([TenantScoped({ mode: "optional" }), smrt({
60
- tableName: "content_assets",
61
- conflictColumns: [
62
- "content_id",
63
- "asset_id",
64
- "relationship"
65
- ],
66
- api: false,
67
- mcp: false,
68
- cli: false
69
- })], ContentAsset);
70
- //#endregion
71
- //#region src/content-assets.ts
72
- var __defProp$3 = Object.defineProperty;
73
- var __getOwnPropDesc$3 = Object.getOwnPropertyDescriptor;
74
- var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$3(obj, key, {
75
- enumerable: true,
76
- configurable: true,
77
- writable: true,
78
- value
79
- }) : obj[key] = value;
80
- var __decorateClass$3 = (decorators, target, key, kind) => {
81
- var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$3(target, key) : target;
82
- for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
83
- if (kind && result) __defProp$3(target, key, result);
84
- return result;
85
- };
86
- var __publicField$1 = (obj, key, value) => __defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
87
- var ContentAssetCollection = class extends SmrtJunction {
88
- leftField = "contentId";
89
- rightField = "assetId";
90
- };
91
- __publicField$1(ContentAssetCollection, "_itemClass", ContentAsset);
92
- ContentAssetCollection = __decorateClass$3([smrt({
93
- api: false,
94
- mcp: false,
95
- cli: false
96
- })], ContentAssetCollection);
97
- //#endregion
98
- //#region src/content-governance.ts
99
- var DEFAULT_FACT_RELATIONSHIP = "supports";
100
- var DEFAULT_CONTENT_GOVERNANCE_CONFIG = {
101
- policies: [{
102
- key: "facts",
103
- label: "Facts Review",
104
- kind: "facts",
105
- instructions: [
106
- "Compare the draft copy against the supplied facts only.",
107
- "Flag contradictions, unsupported claims, stale claims, and places where the copy should cite or qualify a statement.",
108
- "Do not invent missing facts. If the draft makes a claim that is not supported by the provided facts, flag it clearly."
109
- ].join(" "),
110
- enabled: true
111
- }, {
112
- key: "safety",
113
- label: "Safety Review",
114
- kind: "safety",
115
- instructions: [
116
- "Review the content for legal, reputational, and user-safety risks.",
117
- "At minimum, check for defamation risk, privacy leaks, unverified allegations, unsafe instructions, and medical, legal, or financial claims that need qualification.",
118
- "Flag content that should be softened, attributed, removed, or escalated for human review."
119
- ].join(" "),
120
- enabled: true
121
- }].map(clonePolicyDefinition),
122
- profiles: [{
123
- key: "publication",
124
- label: "Publication",
125
- description: "Default publication-time editorial checks.",
126
- enabled: true,
127
- requirements: [{
128
- policyKey: "safety",
129
- label: "Safety Review",
130
- blocking: false
131
- }, {
132
- policyKey: "facts",
133
- label: "Facts Review",
134
- blocking: false
135
- }]
136
- }, {
137
- key: "correction",
138
- label: "Correction",
139
- description: "Default correction-time editorial checks.",
140
- enabled: true,
141
- requirements: [{
142
- policyKey: "safety",
143
- label: "Safety Review",
144
- blocking: false
145
- }]
146
- }].map(cloneProfileDefinition),
147
- assignments: []
148
- };
149
- var governanceConfig = cloneGovernanceConfig(DEFAULT_CONTENT_GOVERNANCE_CONFIG);
150
- function cloneReviewRequirement(requirement) {
151
- return {
152
- ...requirement,
153
- acceptedStatuses: requirement.acceptedStatuses ? [...requirement.acceptedStatuses] : void 0
154
- };
155
- }
156
- function normalizePolicyDefinition(policy) {
157
- return {
158
- key: policy.key,
159
- label: policy.label || policy.key,
160
- kind: policy.kind || getFallbackPolicyKind(policy.key),
161
- instructions: policy.instructions || "",
162
- enabled: policy.enabled !== false,
163
- metadata: policy.metadata ? { ...policy.metadata } : void 0
164
- };
165
- }
166
- function clonePolicyDefinition(policy) {
167
- return normalizePolicyDefinition(policy);
168
- }
169
- function normalizeProfileDefinition(profile) {
170
- return {
171
- key: profile.key,
172
- label: profile.label || profile.key,
173
- description: profile.description || "",
174
- enabled: profile.enabled !== false,
175
- requirements: Array.isArray(profile.requirements) ? profile.requirements.map(cloneReviewRequirement) : [],
176
- metadata: profile.metadata ? { ...profile.metadata } : void 0
177
- };
178
- }
179
- function cloneProfileDefinition(profile) {
180
- return normalizeProfileDefinition(profile);
181
- }
182
- function buildContentGovernanceAssignmentKey(contentType, contentVariant) {
183
- return `${contentType || ""}::${contentVariant || ""}`;
184
- }
185
- function normalizeAssignmentDefinition(assignment) {
186
- return {
187
- key: assignment.key || buildContentGovernanceAssignmentKey(assignment.contentType, assignment.contentVariant),
188
- label: assignment.label || "",
189
- contentType: assignment.contentType,
190
- contentVariant: assignment.contentVariant || "",
191
- enabled: assignment.enabled !== false,
192
- factLinkingEnabled: assignment.factLinkingEnabled === true,
193
- transparencyEnabled: assignment.transparencyEnabled === true,
194
- publicationProfileKey: assignment.publicationProfileKey || null,
195
- correctionProfileKey: assignment.correctionProfileKey || null,
196
- enforcePublishReadiness: assignment.enforcePublishReadiness === true,
197
- defaultFactRelationship: assignment.defaultFactRelationship || DEFAULT_FACT_RELATIONSHIP,
198
- metadata: assignment.metadata ? { ...assignment.metadata } : void 0
199
- };
200
- }
201
- function cloneAssignmentDefinition(assignment) {
202
- return normalizeAssignmentDefinition(assignment);
203
- }
204
- function cloneGovernanceConfig(config) {
205
- return {
206
- policies: config.policies.map(clonePolicyDefinition),
207
- profiles: config.profiles.map(cloneProfileDefinition),
208
- assignments: config.assignments.map(cloneAssignmentDefinition)
209
- };
210
- }
211
- function mergeByKey(previous, next, normalize) {
212
- const merged = /* @__PURE__ */ new Map();
213
- for (const value of previous) {
214
- const normalized = normalize(value);
215
- if (normalized.key) merged.set(normalized.key, normalized);
216
- }
217
- for (const value of next) {
218
- const normalized = normalize(value);
219
- if (normalized.key) merged.set(normalized.key, normalized);
220
- }
221
- return [...merged.values()];
222
- }
223
- function getFallbackPolicyKind(key) {
224
- if (key === "facts") return "facts";
225
- if (key === "safety") return "safety";
226
- return "custom";
227
- }
228
- function getPolicyMap(policies) {
229
- return new Map(policies.map((policy) => {
230
- const normalized = normalizePolicyDefinition(policy);
231
- return [normalized.key, normalized];
232
- }));
233
- }
234
- function getProfileMap(profiles) {
235
- return new Map(profiles.map((profile) => {
236
- const normalized = normalizeProfileDefinition(profile);
237
- return [normalized.key, normalized];
238
- }));
239
- }
240
- function isMissingGovernanceTableError(error) {
241
- const message = error instanceof Error ? error.message : String(error || "Unknown error");
242
- return message.includes("Run 'smrt db:migrate'") || /no such table/i.test(message) || /does not exist/i.test(message);
243
- }
244
- function getRowTimestamp(row, primaryKey) {
245
- const snakeCaseKey = primaryKey === "createdAt" ? "created_at" : "updated_at";
246
- const value = row[primaryKey] ?? row[snakeCaseKey];
247
- return typeof value === "string" && value.length > 0 ? value : null;
248
- }
249
- function getRowTenantId(row) {
250
- const value = row.tenantId ?? row.tenant_id ?? null;
251
- return typeof value === "string" && value.length > 0 ? value : null;
252
- }
253
- function getRowString(row, ...keys) {
254
- for (const key of keys) {
255
- const value = row[key];
256
- if (typeof value === "string" && value.length > 0) return value;
257
- }
258
- return null;
259
- }
260
- function safeParseJSONObject(value) {
261
- if (!value) return {};
262
- if (typeof value === "object" && !Array.isArray(value)) return { ...value };
263
- try {
264
- const parsed = JSON.parse(String(value));
265
- return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? { ...parsed } : {};
266
- } catch {
267
- return {};
268
- }
269
- }
270
- function safeParseJSONArray(value, mapEntry) {
271
- if (!value) return [];
272
- if (Array.isArray(value)) return value.map((entry) => mapEntry(entry));
273
- try {
274
- const parsed = JSON.parse(String(value));
275
- return Array.isArray(parsed) ? parsed.map((entry) => mapEntry(entry)) : [];
276
- } catch {
277
- return [];
278
- }
279
- }
280
- function resolveGovernanceTenantFilter(tenantId) {
281
- if (tenantId !== void 0) return tenantId;
282
- if (isSystemContext() || isSuperAdminBypass()) return;
283
- const currentTenant = getCurrentTenant();
284
- if (currentTenant?.tenantId) return currentTenant.tenantId;
285
- return isTenancyEnabled() ? null : void 0;
286
- }
287
- function mapPersistedPolicyRow(row) {
288
- return {
289
- id: typeof row.id === "string" ? row.id : void 0,
290
- tenantId: getRowTenantId(row),
291
- createdAt: getRowTimestamp(row, "createdAt"),
292
- updatedAt: getRowTimestamp(row, "updatedAt"),
293
- ...normalizePolicyDefinition({
294
- key: String(row.key || ""),
295
- label: String(row.label || row.key || ""),
296
- kind: row.kind || getFallbackPolicyKind(String(row.key || "")),
297
- instructions: String(row.instructions || ""),
298
- enabled: row.enabled !== false && row.enabled !== 0,
299
- metadata: safeParseJSONObject(row.metadata)
300
- })
301
- };
302
- }
303
- function mapPersistedProfileRow(row) {
304
- return {
305
- id: typeof row.id === "string" ? row.id : void 0,
306
- tenantId: getRowTenantId(row),
307
- createdAt: getRowTimestamp(row, "createdAt"),
308
- updatedAt: getRowTimestamp(row, "updatedAt"),
309
- ...normalizeProfileDefinition({
310
- key: String(row.key || ""),
311
- label: String(row.label || row.key || ""),
312
- description: String(row.description || ""),
313
- enabled: row.enabled !== false && row.enabled !== 0,
314
- requirements: safeParseJSONArray(row.requirements, cloneReviewRequirement),
315
- metadata: safeParseJSONObject(row.metadata)
316
- })
317
- };
318
- }
319
- function mapPersistedAssignmentRow(row) {
320
- return {
321
- id: typeof row.id === "string" ? row.id : void 0,
322
- tenantId: getRowTenantId(row),
323
- createdAt: getRowTimestamp(row, "createdAt"),
324
- updatedAt: getRowTimestamp(row, "updatedAt"),
325
- ...normalizeAssignmentDefinition({
326
- key: String(row.key || ""),
327
- label: String(row.label || ""),
328
- contentType: String(row.contentType || row.content_type || ""),
329
- contentVariant: String(row.contentVariant || row.content_variant || ""),
330
- enabled: row.enabled !== false && row.enabled !== 0,
331
- factLinkingEnabled: row.factLinkingEnabled === true || row.fact_linking_enabled === true || row.fact_linking_enabled === 1,
332
- transparencyEnabled: row.transparencyEnabled === true || row.transparency_enabled === true || row.transparency_enabled === 1,
333
- publicationProfileKey: getRowString(row, "publicationProfileKey", "publication_profile_key"),
334
- correctionProfileKey: getRowString(row, "correctionProfileKey", "correction_profile_key"),
335
- enforcePublishReadiness: row.enforcePublishReadiness === true || row.enforce_publish_readiness === true || row.enforce_publish_readiness === 1,
336
- defaultFactRelationship: getRowString(row, "defaultFactRelationship", "default_fact_relationship") || DEFAULT_FACT_RELATIONSHIP,
337
- metadata: safeParseJSONObject(row.metadata)
338
- })
339
- };
340
- }
341
- async function loadPersistedContentGovernanceDefinitions(options = {}) {
342
- const { db } = options;
343
- if (!db) return {
344
- policies: [],
345
- profiles: [],
346
- assignments: []
347
- };
348
- try {
349
- const tenantId = resolveGovernanceTenantFilter(options.tenantId);
350
- const listGovernanceRows = async (tableName) => {
351
- const byCreatedAt = (a, b) => String(a.created_at || a.createdAt || "").localeCompare(String(b.created_at || b.createdAt || ""));
352
- const sortRows = (rows) => rows.sort(byCreatedAt);
353
- if (tenantId === void 0) return sortRows(await db.list(tableName, {}));
354
- if (tenantId === null) return sortRows(await db.list(tableName, { tenant_id: null }));
355
- const [globalRows, tenantRows] = await Promise.all([db.list(tableName, { tenant_id: null }), db.list(tableName, { tenant_id: tenantId })]);
356
- return [...sortRows(globalRows), ...sortRows(tenantRows)];
357
- };
358
- const [policyRows, profileRows, assignmentRows] = await Promise.all([
359
- listGovernanceRows("content_governance_policies"),
360
- listGovernanceRows("content_governance_profiles"),
361
- listGovernanceRows("content_governance_assignments")
362
- ]);
363
- return {
364
- policies: policyRows.map((row) => mapPersistedPolicyRow(row)),
365
- profiles: profileRows.map((row) => mapPersistedProfileRow(row)),
366
- assignments: assignmentRows.map((row) => mapPersistedAssignmentRow(row))
367
- };
368
- } catch (error) {
369
- if (isMissingGovernanceTableError(error)) return {
370
- policies: [],
371
- profiles: [],
372
- assignments: []
373
- };
374
- throw error;
375
- }
376
- }
377
- function resolveAssignmentDefinition(assignments, options) {
378
- if (!options.contentType) return null;
379
- const exactMatch = assignments.find((assignment) => assignment.contentType === options.contentType && (assignment.contentVariant || "") === (options.contentVariant || "")) || null;
380
- if (exactMatch) return cloneAssignmentDefinition(exactMatch);
381
- const typeOnlyMatch = assignments.find((assignment) => assignment.contentType === options.contentType && !assignment.contentVariant) || null;
382
- return typeOnlyMatch ? cloneAssignmentDefinition(typeOnlyMatch) : null;
383
- }
384
- function buildResolvedGovernance(config, assignment) {
385
- const normalizedAssignment = assignment ? normalizeAssignmentDefinition(assignment) : null;
386
- if (normalizedAssignment?.enabled !== true) return {
387
- isGoverned: false,
388
- factLinkingEnabled: false,
389
- transparencyEnabled: false,
390
- publicationProfileKey: null,
391
- correctionProfileKey: null,
392
- enforcePublishReadiness: false,
393
- defaultFactRelationship: DEFAULT_FACT_RELATIONSHIP,
394
- reviewPolicies: config.policies.map(clonePolicyDefinition).filter((policy) => policy.enabled !== false),
395
- availableProfiles: config.profiles.map(cloneProfileDefinition).filter((profile) => profile.enabled !== false),
396
- assignment: normalizedAssignment
397
- };
398
- return {
399
- isGoverned: true,
400
- factLinkingEnabled: normalizedAssignment.factLinkingEnabled === true,
401
- transparencyEnabled: normalizedAssignment.transparencyEnabled === true,
402
- publicationProfileKey: normalizedAssignment.publicationProfileKey || null,
403
- correctionProfileKey: normalizedAssignment.correctionProfileKey || null,
404
- enforcePublishReadiness: normalizedAssignment.enforcePublishReadiness === true,
405
- defaultFactRelationship: normalizedAssignment.defaultFactRelationship || DEFAULT_FACT_RELATIONSHIP,
406
- reviewPolicies: config.policies.map(clonePolicyDefinition).filter((policy) => policy.enabled !== false),
407
- availableProfiles: config.profiles.map(cloneProfileDefinition).filter((profile) => profile.enabled !== false),
408
- assignment: normalizedAssignment
409
- };
410
- }
411
- function normalizeStatus(status) {
412
- switch (status) {
413
- case "pending":
414
- case "passed":
415
- case "flagged":
416
- case "failed":
417
- case "waived": return status;
418
- default: return "flagged";
419
- }
420
- }
421
- function normalizeSeverity(severity) {
422
- switch (severity) {
423
- case "info":
424
- case "warning":
425
- case "error": return severity;
426
- default: return "warning";
427
- }
428
- }
429
- function extractJSONObject(raw) {
430
- const start = raw.indexOf("{");
431
- const end = raw.lastIndexOf("}");
432
- if (start === -1 || end === -1 || end <= start) return null;
433
- return raw.slice(start, end + 1);
434
- }
435
- function getContentGovernanceConfig() {
436
- return cloneGovernanceConfig(governanceConfig);
437
- }
438
- function configureContentGovernance(config) {
439
- governanceConfig = {
440
- policies: config.policies ? mergeByKey(governanceConfig.policies, config.policies, normalizePolicyDefinition) : governanceConfig.policies.map(clonePolicyDefinition),
441
- profiles: config.profiles ? mergeByKey(governanceConfig.profiles, config.profiles, normalizeProfileDefinition) : governanceConfig.profiles.map(cloneProfileDefinition),
442
- assignments: config.assignments ? mergeByKey(governanceConfig.assignments, config.assignments, normalizeAssignmentDefinition) : governanceConfig.assignments.map(cloneAssignmentDefinition)
443
- };
444
- return getContentGovernanceConfig();
445
- }
446
- function resetContentGovernanceConfig() {
447
- governanceConfig = cloneGovernanceConfig(DEFAULT_CONTENT_GOVERNANCE_CONFIG);
448
- return getContentGovernanceConfig();
449
- }
450
- async function getEffectiveContentGovernanceConfig(options = {}) {
451
- const persisted = await loadPersistedContentGovernanceDefinitions({
452
- db: options.db,
453
- tenantId: options.tenantId
454
- });
455
- return {
456
- policies: mergeByKey(governanceConfig.policies, persisted.policies, normalizePolicyDefinition),
457
- profiles: mergeByKey(governanceConfig.profiles, persisted.profiles, normalizeProfileDefinition),
458
- assignments: mergeByKey(governanceConfig.assignments, persisted.assignments, normalizeAssignmentDefinition)
459
- };
460
- }
461
- function hasStaticContentGovernancePolicy(key) {
462
- return getPolicyMap(governanceConfig.policies).has(key);
463
- }
464
- function hasStaticContentGovernanceProfile(key) {
465
- return getProfileMap(governanceConfig.profiles).has(key);
466
- }
467
- function getContentReviewPolicy(policyKey, policies = governanceConfig.policies) {
468
- return getPolicyMap(policies).get(policyKey) || null;
469
- }
470
- function getContentReviewKind(policyKey, policies = governanceConfig.policies) {
471
- return getPolicyMap(policies).get(policyKey)?.kind || getFallbackPolicyKind(policyKey);
472
- }
473
- function getContentReviewProfile(profileKey, profiles = governanceConfig.profiles) {
474
- return getProfileMap(profiles).get(profileKey) || null;
475
- }
476
- function getContentReviewProfileKeys(profiles = governanceConfig.profiles) {
477
- return profiles.map(cloneProfileDefinition).filter((profile) => profile.enabled !== false).map((profile) => profile.key);
478
- }
479
- function getContentReviewPolicies(policies = governanceConfig.policies) {
480
- return policies.map(clonePolicyDefinition).filter((policy) => policy.enabled !== false);
481
- }
482
- function getContentReviewRequirements(profileKey, profiles = governanceConfig.profiles) {
483
- return getContentReviewProfile(profileKey, profiles)?.requirements.map(cloneReviewRequirement) || [];
484
- }
485
- function getAcceptedContentReviewStatuses(requirement) {
486
- return requirement.acceptedStatuses && requirement.acceptedStatuses.length > 0 ? [...requirement.acceptedStatuses] : ["passed", "waived"];
487
- }
488
- function resolveConfiguredContentGovernance(options) {
489
- const assignment = resolveAssignmentDefinition(governanceConfig.assignments, {
490
- contentType: options.contentType,
491
- contentVariant: options.contentVariant
492
- });
493
- return buildResolvedGovernance(governanceConfig, assignment);
494
- }
495
- async function resolveEffectiveContentGovernance(options) {
496
- const effectiveConfig = await getEffectiveContentGovernanceConfig({
497
- db: options.db,
498
- tenantId: options.tenantId
499
- });
500
- return buildResolvedGovernance(effectiveConfig, resolveAssignmentDefinition(effectiveConfig.assignments, {
501
- contentType: options.contentType,
502
- contentVariant: options.contentVariant
503
- }));
504
- }
505
- function buildContentReviewPrompt(options) {
506
- const { kind, content, facts = [], policy, customInstructions } = options;
507
- const factLines = facts.length > 0 ? facts.map((fact) => `- [${fact.id}] status=${fact.status}; confidence=${fact.confidence}; sources=${fact.sourceCount}; text=${fact.textRefined}`).join("\n") : "No facts were supplied for this review.";
508
- const policyText = customInstructions?.trim() || policy?.instructions || getContentReviewPolicy(kind)?.instructions || "";
509
- return `You are a structured editorial reviewer.
510
-
511
- Return ONLY valid JSON with this shape:
512
- {
513
- "status": "passed" | "flagged" | "failed" | "waived",
514
- "summary": "short summary",
515
- "findings": [
516
- {
517
- "severity": "info" | "warning" | "error",
518
- "title": "short title",
519
- "detail": "what is wrong and why",
520
- "factId": "optional fact id",
521
- "quote": "optional quoted text from the draft",
522
- "suggestedChange": "optional suggested fix",
523
- "ruleId": "optional policy or rule id"
524
- }
525
- ]
526
- }
527
-
528
- Review kind: ${kind}
529
- Policy key: ${policy?.key || kind}
530
- Review instructions:
531
- ${policyText}
532
-
533
- Draft content:
534
- - id: ${content.id ?? ""}
535
- - type: ${content.type ?? ""}
536
- - status: ${content.status}
537
- - state: ${content.state}
538
- - author: ${content.author ?? ""}
539
- - publish_date: ${content.publish_date?.toISOString?.() ?? ""}
540
-
541
- Title:
542
- ${content.title}
543
-
544
- Description:
545
- ${content.description ?? ""}
546
-
547
- Body:
548
- ${content.body}
549
-
550
- Relevant facts:
551
- ${factLines}`;
552
- }
553
- function parseContentReviewResponse(raw) {
554
- const normalizedRaw = raw.trim();
555
- const jsonCandidate = extractJSONObject(normalizedRaw);
556
- if (jsonCandidate) try {
557
- const parsed = JSON.parse(jsonCandidate);
558
- const findings = Array.isArray(parsed.findings) ? parsed.findings.map((rawFinding) => {
559
- const finding = rawFinding && typeof rawFinding === "object" ? rawFinding : {};
560
- return {
561
- severity: normalizeSeverity(finding.severity),
562
- title: String(finding.title || "Review finding"),
563
- detail: String(finding.detail || ""),
564
- factId: typeof finding.factId === "string" ? finding.factId : void 0,
565
- quote: typeof finding.quote === "string" ? finding.quote : void 0,
566
- suggestedChange: typeof finding.suggestedChange === "string" ? finding.suggestedChange : void 0,
567
- ruleId: typeof finding.ruleId === "string" ? finding.ruleId : void 0
568
- };
569
- }) : [];
570
- return {
571
- status: normalizeStatus(parsed.status),
572
- summary: String(parsed.summary || normalizedRaw || "Review completed"),
573
- findings
574
- };
575
- } catch {}
576
- return {
577
- status: "flagged",
578
- summary: normalizedRaw || "Review completed without structured output.",
579
- findings: normalizedRaw ? [{
580
- severity: "warning",
581
- title: "Unstructured review output",
582
- detail: normalizedRaw
583
- }] : []
584
- };
585
- }
586
- //#endregion
587
- //#region src/content-prompts.ts
588
- var smrtContentReviewPrompt = definePrompt({
589
- key: "smrtContent.review",
590
- template: `Content review request
591
-
592
- Content ID: {contentId}
593
- Review kind: {kind}
594
- Policy key: {policyKey}
595
- Title: {contentTitle}
596
- Description: {contentDescription}
597
-
598
- Body:
599
- {contentBody}
600
-
601
- {reviewPrompt}`,
602
- editable: {
603
- template: true,
604
- profile: true,
605
- model: true,
606
- params: true
607
- }
608
- });
609
- var smrtContentApplyCorrectionPrompt = definePrompt({
610
- key: "smrtContent.applyCorrection",
611
- template: `You are revising an article draft to apply a factual correction.
612
-
613
- Return only the fully revised body text, with no commentary.
614
-
615
- Current body:
616
- {body}
617
-
618
- Correction summary:
619
- {summary}
620
-
621
- Incorrect text to fix:
622
- {incorrectText}
623
-
624
- Corrected text to incorporate:
625
- {correctedText}`,
626
- editable: {
627
- template: true,
628
- profile: true,
629
- model: true,
630
- params: true
631
- }
632
- });
633
- var smrtContentThumbnailAIGeneratePrompt = definePrompt({
634
- key: "smrtContent.thumbnail.aiGenerate",
635
- 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.`,
636
- editable: {
637
- template: true,
638
- profile: true,
639
- model: true,
640
- params: true
641
- }
642
- });
643
- function promptMessageOptions(ai) {
644
- return {
645
- ...ai.params || {},
646
- ...ai.model ? { model: ai.model } : {},
647
- ...typeof ai.temperature === "number" ? { temperature: ai.temperature } : {},
648
- ...typeof ai.maxTokens === "number" ? { maxTokens: ai.maxTokens } : {}
649
- };
650
- }
651
- //#endregion
652
- //#region src/content-reference.ts
653
- var __defProp$2 = Object.defineProperty;
654
- var __getOwnPropDesc$2 = Object.getOwnPropertyDescriptor;
655
- var __decorateClass$2 = (decorators, target, key, kind) => {
656
- var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$2(target, key) : target;
657
- for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
658
- if (kind && result) __defProp$2(target, key, result);
659
- return result;
660
- };
661
- var ContentReference = class extends SmrtObject {
662
- tenantId = null;
663
- sourceId = "";
664
- targetId = "";
665
- targetVersion = null;
666
- createdAt = /* @__PURE__ */ new Date();
667
- constructor(options = {}) {
668
- super(options);
669
- if (options.sourceId) this.sourceId = options.sourceId;
670
- if (options.targetId) this.targetId = options.targetId;
671
- if (options.tenantId !== void 0) this.tenantId = options.tenantId;
672
- if (options.targetVersion !== void 0) this.targetVersion = options.targetVersion;
673
- if (options.createdAt) this.createdAt = options.createdAt;
674
- }
675
- };
676
- __decorateClass$2([tenantId({ nullable: true })], ContentReference.prototype, "tenantId", 2);
677
- __decorateClass$2([foreignKey("Content", { required: true })], ContentReference.prototype, "sourceId", 2);
678
- __decorateClass$2([foreignKey("Content", { required: true })], ContentReference.prototype, "targetId", 2);
679
- __decorateClass$2([field({
680
- type: "integer",
681
- nullable: true
682
- })], ContentReference.prototype, "targetVersion", 2);
683
- __decorateClass$2([field()], ContentReference.prototype, "createdAt", 2);
684
- ContentReference = __decorateClass$2([TenantScoped({ mode: "optional" }), smrt({
685
- tableName: "content_references",
686
- conflictColumns: ["source_id", "target_id"]
687
- })], ContentReference);
688
- //#endregion
689
- //#region src/content-references.ts
690
- var __defProp$1 = Object.defineProperty;
691
- var __getOwnPropDesc$1 = Object.getOwnPropertyDescriptor;
692
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp$1(obj, key, {
693
- enumerable: true,
694
- configurable: true,
695
- writable: true,
696
- value
697
- }) : obj[key] = value;
698
- var __decorateClass$1 = (decorators, target, key, kind) => {
699
- var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$1(target, key) : target;
700
- for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
701
- if (kind && result) __defProp$1(target, key, result);
702
- return result;
703
- };
704
- var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
705
- var ContentReferences = class extends SmrtJunction {
706
- leftField = "sourceId";
707
- rightField = "targetId";
708
- sortField = "createdAt";
709
- positionField = null;
710
- async getForSource(sourceId) {
711
- return await this.list({
712
- where: { sourceId },
713
- orderBy: "created_at ASC"
714
- });
715
- }
716
- async getForTarget(targetId) {
717
- return await this.list({
718
- where: { targetId },
719
- orderBy: "created_at ASC"
720
- });
721
- }
722
- /**
723
- * Find-or-create idempotency: if a reference already exists for
724
- * (sourceId, targetId), return the existing row unchanged instead of
725
- * upserting a new row. This preserves the existing row's `id` and
726
- * `createdAt`, which is important because reference rows are
727
- * externally addressable via `/api/v1/contentreferences/[id]`.
728
- *
729
- * The base `SmrtJunction.attach` flow (this.create → db.upsert) would
730
- * overwrite both columns on every duplicate call.
731
- *
732
- * Reference pinning (main): `opts.targetVersion` pins the citation to a
733
- * specific `ContentVersion.version` for drift detection. Re-attaching an
734
- * existing edge with a different `targetVersion` updates the pin in place;
735
- * `undefined` leaves an existing pin untouched, while a brand-new row
736
- * defaults the pin to `null` (unpinned).
737
- */
738
- async attach(sourceId, targetId, opts = {}) {
739
- const targetVersion = opts.targetVersion;
740
- const existing = await this.get({
741
- sourceId,
742
- targetId
743
- });
744
- if (existing) {
745
- if (targetVersion !== void 0 && existing.targetVersion !== targetVersion) {
746
- existing.targetVersion = targetVersion;
747
- await existing.save();
748
- }
749
- return existing;
750
- }
751
- return super.attach(sourceId, targetId, {
752
- ...opts,
753
- targetVersion: targetVersion ?? null
754
- });
755
- }
756
- async unlink(sourceId, targetId) {
757
- await this.detach(sourceId, targetId);
758
- }
759
- };
760
- __publicField(ContentReferences, "_itemClass", ContentReference);
761
- ContentReferences = __decorateClass$1([smrt()], ContentReferences);
762
- //#endregion
763
- //#region src/content-transparency.ts
764
- function asObject(value, fallback = {}) {
765
- return value && typeof value === "object" ? { ...value } : fallback;
766
- }
767
- function asString(value) {
768
- return typeof value === "string" && value.length > 0 ? value : null;
769
- }
770
- function asNumber(value) {
771
- return typeof value === "number" && Number.isFinite(value) ? value : null;
772
- }
773
- function asArray(value) {
774
- return Array.isArray(value) ? value : [];
775
- }
776
- function normalizeGeneration(value) {
777
- const generation = asObject(value);
778
- return {
779
- aiAssisted: Boolean(generation.aiAssisted),
780
- publicPrompt: asString(generation.publicPrompt),
781
- model: asString(generation.model)
782
- };
783
- }
784
- function normalizeFact(value) {
785
- const fact = asObject(value);
786
- return {
787
- ...fact,
788
- id: asString(fact.id),
789
- relationship: asString(fact.relationship),
790
- linkMetadata: asObject(fact.linkMetadata),
791
- usedInArticle: Boolean(fact.usedInArticle),
792
- sources: asArray(fact.sources).map(normalizeSource)
793
- };
794
- }
795
- function normalizeSource(value) {
796
- const source = asObject(value);
797
- return {
798
- id: asString(source.id),
799
- sourceType: asString(source.sourceType),
800
- sourceUrl: asString(source.sourceUrl),
801
- sourceTitle: asString(source.sourceTitle),
802
- credibility: asNumber(source.credibility),
803
- extractedAt: asString(source.extractedAt),
804
- metadata: asObject(source.metadata)
805
- };
806
- }
807
- function normalizeReference(value) {
808
- const reference = asObject(value);
809
- return {
810
- id: asString(reference.id),
811
- title: asString(reference.title),
812
- url: asString(reference.url),
813
- originalUrl: asString(reference.originalUrl),
814
- type: asString(reference.type),
815
- source: asString(reference.source),
816
- usedFactIds: asArray(reference.usedFactIds).filter(Boolean),
817
- extractedFacts: asArray(reference.extractedFacts).map(normalizeFact)
818
- };
819
- }
820
- function normalizePublicationVersion(value) {
821
- const publicationVersion = asObject(value);
822
- if (!publicationVersion.id && publicationVersion.version === void 0) return null;
823
- return {
824
- id: asString(publicationVersion.id),
825
- version: asNumber(publicationVersion.version),
826
- kind: asString(publicationVersion.kind),
827
- summary: typeof publicationVersion.summary === "string" ? publicationVersion.summary : "",
828
- createdAt: asString(publicationVersion.createdAt)
829
- };
830
- }
831
- function normalizeVersionHistoryItem(value) {
832
- const version = asObject(value);
833
- return {
834
- id: asString(version.id),
835
- version: asNumber(version.version),
836
- kind: asString(version.kind),
837
- summary: typeof version.summary === "string" ? version.summary : "",
838
- createdAt: asString(version.createdAt),
839
- provenance: asObject(version.provenance)
840
- };
841
- }
842
- function dedupeFacts(facts) {
843
- const byKey = /* @__PURE__ */ new Map();
844
- for (const fact of facts) {
845
- const key = fact.id || fact.textRefined || fact.textRaw || JSON.stringify(fact.metadata || {});
846
- if (!key) continue;
847
- byKey.set(key, fact);
848
- }
849
- return [...byKey.values()];
850
- }
851
- function normalizeContentTransparency(value, defaults = {}) {
852
- const snapshot = asObject(value);
853
- const references = asArray(snapshot.references).map(normalizeReference);
854
- const linkedFacts = asArray(snapshot.linkedFacts).map(normalizeFact);
855
- const factsUsed = asArray(snapshot.factsUsed).length > 0 ? asArray(snapshot.factsUsed).map(normalizeFact) : linkedFacts.filter((fact) => fact.usedInArticle);
856
- const otherExtractedFacts = asArray(snapshot.otherExtractedFacts).length > 0 ? asArray(snapshot.otherExtractedFacts).map(normalizeFact) : dedupeFacts(references.flatMap((reference) => reference.extractedFacts.filter((fact) => !fact.usedInArticle)));
857
- return {
858
- generatedAt: asString(snapshot.generatedAt) ?? defaults.generatedAt ?? null,
859
- snapshotKind: snapshot.snapshotKind === "published" ? "published" : defaults.snapshotKind || "preview",
860
- contentId: asString(snapshot.contentId) ?? defaults.contentId ?? null,
861
- currentContentStatus: asString(snapshot.currentContentStatus) ?? defaults.currentContentStatus ?? null,
862
- publicationProfileKey: asString(snapshot.publicationProfileKey) ?? asString(snapshot.publicationReviewProfileKey) ?? defaults.publicationProfileKey ?? "publication",
863
- publicationVersion: normalizePublicationVersion(snapshot.publicationVersion) ?? defaults.publicationVersion ?? null,
864
- generation: normalizeGeneration(snapshot.generation ?? defaults.generation ?? {}),
865
- factsUsed,
866
- linkedFacts,
867
- otherExtractedFacts,
868
- references,
869
- reviews: asArray(snapshot.reviews),
870
- reviewProfiles: asArray(snapshot.reviewProfiles),
871
- corrections: asArray(snapshot.corrections),
872
- versionHistory: asArray(snapshot.versionHistory).map(normalizeVersionHistoryItem)
873
- };
874
- }
875
- //#endregion
876
- //#region src/database-utils.ts
877
- function isMissingTableError(error, tableName) {
878
- const message = String(error?.message || error || "").toLowerCase();
879
- return message.includes(tableName.toLowerCase()) && (message.includes("no such table") || message.includes("does not exist") || message.includes("relation"));
880
- }
881
- function getQueryRows(result) {
882
- return Array.isArray(result) ? result : Array.isArray(result?.rows) ? result.rows ?? [] : [];
883
- }
884
- //#endregion
885
- //#region src/serialization.ts
886
- function asModel(value) {
887
- return value && typeof value === "object" ? value : {};
888
- }
889
- function toJSON(value) {
890
- const model = asModel(value);
891
- if (typeof model.toJSON === "function") {
892
- const serialized = model.toJSON();
893
- return serialized && typeof serialized === "object" ? serialized : {};
894
- }
895
- return value && typeof value === "object" ? value : {};
896
- }
897
- function serializeFact(fact) {
898
- const model = asModel(fact);
899
- const data = toJSON(fact);
900
- return {
901
- ...data,
902
- metadata: typeof model.getMetadata === "function" ? model.getMetadata() : data.metadata || {}
903
- };
904
- }
905
- function serializeFactLink(link) {
906
- const model = asModel(link);
907
- const data = toJSON(link);
908
- return {
909
- ...data,
910
- metadata: typeof model.getMetadata === "function" ? model.getMetadata() : data.metadata || {}
911
- };
912
- }
913
- function serializeContentVersion(version) {
914
- const model = asModel(version);
915
- const data = toJSON(version);
916
- return {
917
- ...data,
918
- snapshot: typeof model.getSnapshot === "function" ? model.getSnapshot() : data.snapshot || {},
919
- metadata: typeof model.getMetadata === "function" ? model.getMetadata() : data.metadata || {}
920
- };
921
- }
922
- function serializeContentReview(review) {
923
- const model = asModel(review);
924
- const data = toJSON(review);
925
- return {
926
- ...data,
927
- findings: typeof model.getFindings === "function" ? model.getFindings() : data.findings || [],
928
- metadata: typeof model.getMetadata === "function" ? model.getMetadata() : data.metadata || {}
929
- };
930
- }
931
- function serializeContentCorrection(correction) {
932
- const model = asModel(correction);
933
- const data = toJSON(correction);
934
- return {
935
- ...data,
936
- metadata: typeof model.getMetadata === "function" ? model.getMetadata() : data.metadata || {}
937
- };
938
- }
939
- async function serializeContent(content) {
940
- const model = asModel(content);
941
- const [references, assets] = await Promise.all([typeof model.getReferences === "function" ? model.getReferences() : [], typeof model.getAssets === "function" ? model.getAssets() : []]);
942
- const drift = references.length > 0 && typeof model.getReferenceDrift === "function" ? await model.getReferenceDrift() : [];
943
- const driftByTargetId = new Map(Array.isArray(drift) ? drift.map((entry) => asModel(entry)).filter((entry) => typeof entry.targetId === "string").map((entry) => {
944
- const edge = entry;
945
- return [edge.targetId, {
946
- citedVersion: edge.citedVersion ?? null,
947
- currentVersion: edge.currentVersion ?? null,
948
- isDrifted: Boolean(edge.isDrifted)
949
- }];
950
- }) : []);
951
- return {
952
- ...toJSON(content),
953
- referenceIds: references.map((reference) => asModel(reference)).map((reference) => reference.id).filter(Boolean),
954
- references: references.map((reference) => {
955
- const base = toJSON(reference);
956
- const edge = typeof base.id === "string" ? driftByTargetId.get(base.id) : null;
957
- return edge ? {
958
- ...base,
959
- citedVersion: edge.citedVersion,
960
- currentVersion: edge.currentVersion,
961
- isDrifted: edge.isDrifted
962
- } : base;
963
- }),
964
- assetIds: assets.map((asset) => asModel(asset).id).filter(Boolean),
965
- assets: assets.map((asset) => toJSON(asset))
966
- };
967
- }
968
- //#endregion
969
- //#region src/thumbnail-generator.ts
970
- function isImageGenerationClient(value) {
971
- return !!value && typeof value === "object" && typeof value.generateImage === "function";
972
- }
973
- function isAIClientOptions(value) {
974
- return !!value && typeof value === "object" && !isImageGenerationClient(value);
975
- }
976
- var ThumbnailGenerator = class {
977
- constructor(content, options = {}) {
978
- this.content = content;
979
- this.options = options;
980
- if (!this.options.db && this.options.persistence) this.options.db = this.options.persistence;
981
- }
982
- content;
983
- options;
984
- /**
985
- * Generate a thumbnail using the specified strategy
986
- */
987
- async generate(options) {
988
- switch (options.strategy) {
989
- case "headline-card": return this.generateHeadlineCard(options);
990
- case "static-map": return this.generateStaticMap(options);
991
- case "ai-generate": return this.generateWithAI(options);
992
- default: throw new Error(`Unknown thumbnail strategy: ${options.strategy}`);
993
- }
994
- }
995
- /**
996
- * Generate a headline card thumbnail
997
- */
998
- async generateHeadlineCard(options) {
999
- const result = await generateHeadlineCard(this.content.title || this.content.name || "Untitled", {
1000
- width: options.width ?? 1200,
1001
- height: options.height ?? 630,
1002
- brandColor: options.brandColor,
1003
- backgroundColor: options.backgroundColor,
1004
- subtitle: options.subtitle ?? this.content.category ?? void 0,
1005
- logoUrl: options.logoUrl,
1006
- template: options.template
1007
- });
1008
- return this.createImageFromBuffer(result.buffer, {
1009
- width: result.width,
1010
- height: result.height,
1011
- mimeType: result.mimeType,
1012
- name: `${this.content.id}-headline.png`
1013
- });
1014
- }
1015
- /**
1016
- * Generate a static map thumbnail
1017
- */
1018
- async generateStaticMap(options) {
1019
- const coordinateMetadata = this.content.metadata;
1020
- const rawLatitude = coordinateMetadata?.latitude ?? coordinateMetadata?.lat;
1021
- const rawLongitude = coordinateMetadata?.longitude ?? coordinateMetadata?.lng ?? coordinateMetadata?.lon;
1022
- if (rawLatitude == null || rawLongitude == null) throw new Error("Content metadata must contain latitude and longitude for static-map strategy");
1023
- const latitude = typeof rawLatitude === "string" ? +rawLatitude : rawLatitude;
1024
- const longitude = typeof rawLongitude === "string" ? +rawLongitude : rawLongitude;
1025
- if (!Number.isFinite(latitude) || latitude < -90 || latitude > 90) throw new Error(`Invalid latitude value "${rawLatitude}" in content metadata; expected a number between -90 and 90.`);
1026
- if (!Number.isFinite(longitude) || longitude < -180 || longitude > 180) throw new Error(`Invalid longitude value "${rawLongitude}" in content metadata; expected a number between -180 and 180.`);
1027
- const mapboxStyle = options.mapboxStyle;
1028
- const result = await fetchStaticMap(latitude, longitude, {
1029
- provider: options.mapProvider ?? "mapbox",
1030
- width: options.width ?? 1200,
1031
- height: options.height ?? 630,
1032
- zoom: options.zoom ?? 14,
1033
- markerColor: options.markerColor,
1034
- mapboxStyle,
1035
- googleMapType: options.googleMapType
1036
- });
1037
- return this.createImageFromBuffer(result.buffer, {
1038
- width: result.width,
1039
- height: result.height,
1040
- mimeType: result.mimeType,
1041
- name: `${this.content.id}-map.png`
1042
- });
1043
- }
1044
- /**
1045
- * Generate a thumbnail using AI image generation
1046
- */
1047
- async generateWithAI(options) {
1048
- const { getAI } = await import("@happyvertical/ai");
1049
- const aiInput = options.ai ?? this.options.ai;
1050
- if (!aiInput) throw new Error("AI configuration required for ai-generate strategy. Provide via options.ai or constructor options.");
1051
- const ai = isImageGenerationClient(aiInput) ? aiInput : isAIClientOptions(aiInput) ? await getAI(aiInput) : (() => {
1052
- throw new Error("AI client does not support image generation for ai-generate thumbnails.");
1053
- })();
1054
- const width = options.width ?? 1200;
1055
- const height = options.height ?? 630;
1056
- let prompt;
1057
- let aiOverrideOptions = {};
1058
- if (options.prompt) prompt = options.prompt;
1059
- else {
1060
- const built = await this.buildAIPrompt(options.style ?? "photorealistic");
1061
- prompt = built.text;
1062
- aiOverrideOptions = promptMessageOptions(built.ai);
1063
- }
1064
- const result = await ai.generateImage(prompt, {
1065
- ...aiOverrideOptions,
1066
- size: `${width}x${height}`,
1067
- outputFormat: "buffer"
1068
- });
1069
- if (!result.images || result.images.length === 0) throw new Error("AI image generation returned no results");
1070
- let buffer;
1071
- const imageData = result.images[0].data;
1072
- if (Buffer.isBuffer(imageData)) buffer = imageData;
1073
- else if (typeof imageData === "string") if (imageData.startsWith("http")) {
1074
- const response = await fetch(imageData);
1075
- if (!response.ok) throw new Error(`AI image generation URL fetch failed: ${response.status} ${response.statusText}`);
1076
- buffer = Buffer.from(await response.arrayBuffer());
1077
- } else buffer = Buffer.from(imageData, "base64");
1078
- else throw new Error("AI image generation returned unexpected format");
1079
- return this.createImageFromBuffer(buffer, {
1080
- width: options.width ?? 1200,
1081
- height: options.height ?? 630,
1082
- mimeType: "image/png",
1083
- name: `${this.content.id}-ai.png`
1084
- });
1085
- }
1086
- /**
1087
- * Build a prompt for AI image generation based on content.
1088
- *
1089
- * Resolves via `@happyvertical/smrt-prompts` so tenants can override the
1090
- * template/profile/model/params at runtime. Only non-PII content fields
1091
- * (title, description) and the caller-supplied style hint are passed.
1092
- * Internal IDs and the freeform `metadata` blob are intentionally excluded.
1093
- *
1094
- * Returns the full ResolvedPrompt (text + ai config) so the caller can
1095
- * forward `model`/`params` overrides to `ai.generateImage()`. Returning
1096
- * only the text would silently drop the editable model/params overrides.
1097
- */
1098
- async buildAIPrompt(style) {
1099
- const title = this.content.title || "Untitled";
1100
- const description = this.content.description || "";
1101
- const stylePrompts = {
1102
- photorealistic: "photorealistic, high quality, professional photography, 8k resolution",
1103
- illustration: "digital illustration, clean vector art, modern design, vibrant colors",
1104
- abstract: "abstract art, geometric shapes, modern minimalist, artistic interpretation",
1105
- minimal: "minimalist design, simple shapes, clean composition, subtle colors"
1106
- };
1107
- const styleHint = stylePrompts[style] || stylePrompts.photorealistic;
1108
- return resolvePrompt(smrtContentThumbnailAIGeneratePrompt.key, {
1109
- db: this.options.db,
1110
- tenantId: this.content.tenantId,
1111
- variables: {
1112
- style,
1113
- title,
1114
- styleHint,
1115
- descriptionClause: description ? `The article is about: ${description}. ` : ""
1116
- }
1117
- });
1118
- }
1119
- /**
1120
- * Create an Image object from a buffer
1121
- */
1122
- async createImageFromBuffer(buffer, metadata) {
1123
- return await (await ImageCollection.create({ db: this.options.db })).create({
1124
- name: metadata.name,
1125
- mimeType: metadata.mimeType,
1126
- width: metadata.width,
1127
- height: metadata.height,
1128
- sourceUri: `data:${metadata.mimeType};base64,${buffer.toString("base64")}`
1129
- });
1130
- }
1131
- };
1132
- //#endregion
1133
- //#region src/content.ts
1134
- var __defProp = Object.defineProperty;
1135
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
1136
- var __decorateClass = (decorators, target, key, kind) => {
1137
- var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
1138
- for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
1139
- if (kind && result) __defProp(target, key, result);
1140
- return result;
1141
- };
1142
- var USED_FACT_RELATIONSHIPS = /* @__PURE__ */ new Set([
1143
- "supports",
1144
- "referenced_in",
1145
- "contradicts"
1146
- ]);
1147
- var FACT_AUDIT_GENERATED_BY = "content.factAudit";
1148
- var FACT_AUDIT_DOMAIN = "content-audit";
1149
- function normalizeFingerprintValue(value) {
1150
- if (value instanceof Date) return value.toISOString();
1151
- if (Array.isArray(value)) return value.map((entry) => normalizeFingerprintValue(entry));
1152
- if (value && typeof value === "object") return Object.fromEntries(Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key, entryValue]) => [key, normalizeFingerprintValue(entryValue)]));
1153
- return value ?? null;
1154
- }
1155
- function hashFingerprint(input) {
1156
- let hash = 5381;
1157
- for (let index = 0; index < input.length; index += 1) hash = hash * 33 ^ input.charCodeAt(index);
1158
- return `fp-${(hash >>> 0).toString(16).padStart(8, "0")}`;
1159
- }
1160
- function createFingerprint(value) {
1161
- return hashFingerprint(JSON.stringify(normalizeFingerprintValue(value)));
1162
- }
1163
- function normalizeAuditText(value) {
1164
- return String(value ?? "").trim().replace(/\s+/g, " ");
1165
- }
1166
- function errorMessage(error) {
1167
- if (error instanceof Error) return error.message;
1168
- if (error && typeof error === "object" && "message" in error && typeof error.message === "string") return error.message;
1169
- return String(error);
1170
- }
1171
- function createFactAuditRunId(contentId) {
1172
- return `fact-audit-${hashFingerprint(`${contentId}:${(/* @__PURE__ */ new Date()).toISOString()}:${Math.random()}`)}`;
1173
- }
1174
- function parseAuditMetadata(value) {
1175
- if (!value) return {};
1176
- if (typeof value === "object") return value;
1177
- try {
1178
- return JSON.parse(String(value));
1179
- } catch {
1180
- return {};
1181
- }
1182
- }
1183
- function getLinkMetadata(link) {
1184
- return typeof link?.getMetadata === "function" ? link.getMetadata() : {};
1185
- }
1186
- function getFactMetadata(fact) {
1187
- return typeof fact?.getMetadata === "function" ? fact.getMetadata() : parseAuditMetadata(fact?.metadata);
1188
- }
1189
- function getGeneratedFactAuditMetadata(link) {
1190
- const metadata = getLinkMetadata(link);
1191
- if (metadata.generatedBy === FACT_AUDIT_GENERATED_BY) return metadata;
1192
- const nested = metadata.factAudit;
1193
- if (nested && typeof nested === "object" && nested.generatedBy === FACT_AUDIT_GENERATED_BY) return nested;
1194
- return null;
1195
- }
1196
- function getEvidenceMetadata(evidence) {
1197
- return typeof evidence?.getMetadata === "function" ? evidence.getMetadata() : parseAuditMetadata(evidence?.metadata);
1198
- }
1199
- function isGeneratedFactAuditEvidence(evidence, contentId) {
1200
- const metadata = getEvidenceMetadata(evidence);
1201
- return metadata.generatedBy === FACT_AUDIT_GENERATED_BY && metadata.contentId === contentId;
1202
- }
1203
- function isGeneratedArticleClaimFact(fact, contentId) {
1204
- const metadata = getFactMetadata(fact);
1205
- if (metadata.generatedBy !== FACT_AUDIT_GENERATED_BY) return false;
1206
- return ((metadata.auditFactRole || metadata.factAuditRole) === "article-claim" || metadata.claimOnly === true) && metadata.contentId === contentId;
1207
- }
1208
- function normalizeFactEvidenceStatus(value) {
1209
- return [
1210
- "supports",
1211
- "contradicts",
1212
- "unclear",
1213
- "irrelevant",
1214
- "invalid"
1215
- ].includes(value) ? value : null;
1216
- }
1217
- function sourceMatchesSelector(source, selector) {
1218
- return source.sourceKind === selector.sourceKind && source.sourceId === selector.sourceId;
1219
- }
1220
- function filterAuditSources(sources, selectors) {
1221
- if (!selectors || selectors.length === 0) return sources;
1222
- return sources.filter((source) => selectors.some((selector) => sourceMatchesSelector(source, selector)));
1223
- }
1224
- function getContentText(content) {
1225
- return [
1226
- content.title,
1227
- content.description,
1228
- content.body
1229
- ].map(normalizeAuditText).filter(Boolean).join("\n\n");
1230
- }
1231
- function readNestedString(source, path) {
1232
- let current = source;
1233
- for (const key of path) {
1234
- if (!current || typeof current !== "object") return null;
1235
- current = current[key];
1236
- }
1237
- return typeof current === "string" && current ? current : null;
1238
- }
1239
- function asRecord(value) {
1240
- if (value && typeof value === "object" && !Array.isArray(value)) return value;
1241
- if (typeof value === "string") try {
1242
- const parsed = JSON.parse(value);
1243
- return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
1244
- } catch {
1245
- return {};
1246
- }
1247
- return {};
1248
- }
1249
- function readNestedRecord(source, path) {
1250
- let current = source;
1251
- for (const key of path) {
1252
- if (!current || typeof current !== "object") return {};
1253
- current = current[key];
1254
- }
1255
- return asRecord(current);
1256
- }
1257
- function getPublicPrompt(metadata) {
1258
- return readNestedString(metadata, [
1259
- "transparency",
1260
- "generation",
1261
- "publicPrompt"
1262
- ]) || readNestedString(metadata, ["generation", "publicPrompt"]) || readNestedString(metadata, ["publicPrompt"]) || null;
1263
- }
1264
- var Content = class extends SmrtObject {
1265
- tenantId = null;
1266
- /**
1267
- * Array of referenced content objects
1268
- */
1269
- references = [];
1270
- /**
1271
- * Content type classification
1272
- */
1273
- type = null;
1274
- /**
1275
- * Content variant for namespaced classification within types
1276
- * Format: generator:domain:specific-type
1277
- * Example: "praeco:meeting:upcoming"
1278
- */
1279
- variant = null;
1280
- /**
1281
- * Reference to file storage key
1282
- */
1283
- fileKey = null;
1284
- /**
1285
- * Author of the content
1286
- */
1287
- author = null;
1288
- name = "";
1289
- /**
1290
- * Content title
1291
- */
1292
- title = "";
1293
- /**
1294
- * Short description or summary
1295
- */
1296
- description = null;
1297
- /**
1298
- * Main content body text
1299
- */
1300
- body = "";
1301
- /**
1302
- * Format used to persist the body field.
1303
- */
1304
- bodyFormat = null;
1305
- /**
1306
- * Date when content was published
1307
- */
1308
- publish_date = null;
1309
- /**
1310
- * URL source of the content
1311
- */
1312
- url = null;
1313
- /**
1314
- * Original source identifier
1315
- */
1316
- source = null;
1317
- /**
1318
- * Original URL of the content
1319
- */
1320
- original_url = null;
1321
- /**
1322
- * Content language
1323
- */
1324
- language = null;
1325
- /**
1326
- * Content tags
1327
- */
1328
- tags = [];
1329
- /**
1330
- * Hierarchical category path for URL routing
1331
- * Format: 'parent/child' (e.g., 'politics/local')
1332
- * Each content belongs to exactly ONE category
1333
- */
1334
- category = null;
1335
- /**
1336
- * Publication status
1337
- */
1338
- status = "draft";
1339
- /**
1340
- * Content state flag
1341
- */
1342
- state = "active";
1343
- /**
1344
- * Additional JSON metadata for flexible schema extension
1345
- */
1346
- metadata = {};
1347
- thumbnailAssetId = null;
1348
- /**
1349
- * Creates a new Content instance
1350
- */
1351
- constructor(options = {}) {
1352
- super(options);
1353
- this.type = options.type || null;
1354
- this.variant = options.variant || null;
1355
- this.fileKey = options.fileKey || null;
1356
- this.author = options.author || null;
1357
- if (options.name) this.name = options.name;
1358
- this.title = options.title || "";
1359
- this.description = options.description || null;
1360
- this.body = options.body || "";
1361
- this.bodyFormat = isContentBodyFormat(options.bodyFormat) ? options.bodyFormat : null;
1362
- this.publish_date = options.publish_date || null;
1363
- this.source = options.source || null;
1364
- this.original_url = options.original_url || null;
1365
- this.language = options.language || null;
1366
- this.status = options.status || "draft";
1367
- this.tags = options.tags || [];
1368
- this.category = options.category || null;
1369
- this.state = options.state || "active";
1370
- this.metadata = options.metadata || {};
1371
- this.thumbnailAssetId = options.thumbnailAssetId ?? null;
1372
- const transient = this;
1373
- if (Array.isArray(options.referenceIds)) transient.referenceIds = [...options.referenceIds];
1374
- if (Array.isArray(options.assetIds)) transient.assetIds = [...options.assetIds];
1375
- }
1376
- /**
1377
- * Initializes this content object
1378
- *
1379
- * @returns Promise that resolves to this instance
1380
- */
1381
- async initialize() {
1382
- await super.initialize();
1383
- return this;
1384
- }
1385
- async validateBeforeSave() {
1386
- if (!this.name && this.title) this.name = this.title;
1387
- if (!this.title && this.name) this.title = this.name;
1388
- await super.validateBeforeSave();
1389
- if (this.status !== "published") return;
1390
- const governance = await this.resolvePublicationGovernance();
1391
- const profileKey = governance?.publicationProfileKey;
1392
- if (!governance?.isGoverned || !governance.enforcePublishReadiness || !profileKey) return;
1393
- const blockingRequirements = (await this.evaluateReviewProfile(profileKey)).requirements.filter((requirement) => requirement.blocking && !requirement.satisfied);
1394
- if (blockingRequirements.length === 0) return;
1395
- throw new ValidationError(`Cannot publish content until the "${profileKey}" review profile is satisfied. ${blockingRequirements.map((requirement) => {
1396
- if (requirement.missing) return `${requirement.label} has not been run yet`;
1397
- if (requirement.stale) return `${requirement.label} is stale and must be rerun`;
1398
- if (requirement.latestStatus) return `${requirement.label} returned ${requirement.latestStatus}`;
1399
- return `${requirement.label} is not satisfied`;
1400
- }).join("; ")}`, "VALIDATION_PUBLISH_READINESS", {
1401
- profileKey,
1402
- blockingRequirements: blockingRequirements.map((requirement) => ({
1403
- policyKey: requirement.policyKey,
1404
- label: requirement.label,
1405
- missing: requirement.missing,
1406
- stale: requirement.stale,
1407
- latestStatus: requirement.latestStatus
1408
- }))
1409
- });
1410
- }
1411
- async save(options = {}) {
1412
- const shouldConsiderPublicationSnapshot = this.status === "published";
1413
- let governance = null;
1414
- let previous = null;
1415
- let previousPublicationFingerprint = null;
1416
- if (shouldConsiderPublicationSnapshot) {
1417
- governance = await this.resolvePublicationGovernance();
1418
- if (governance?.isGoverned && governance.transparencyEnabled) {
1419
- previous = await this.getPersistedContent();
1420
- previousPublicationFingerprint = await this.getLatestPublicationSnapshotFingerprint();
1421
- }
1422
- }
1423
- await super.save(options);
1424
- await this.syncPendingReferenceIds();
1425
- await this.syncPendingAssetIds();
1426
- if (!shouldConsiderPublicationSnapshot || !governance?.isGoverned || !governance.transparencyEnabled) return this;
1427
- const nextPublicationFingerprint = await this.buildPublicationSnapshotFingerprint(governance);
1428
- if (nextPublicationFingerprint && nextPublicationFingerprint !== previousPublicationFingerprint) await this.createVersion({
1429
- kind: "publication",
1430
- summary: previous?.status === "published" ? "Published content updated." : "Content published.",
1431
- metadata: {
1432
- publicationSnapshotFingerprint: nextPublicationFingerprint,
1433
- publicationProfileKey: governance.publicationProfileKey,
1434
- transparency: await this.buildTransparencySnapshot({
1435
- snapshotKind: "published",
1436
- governance
1437
- })
1438
- }
1439
- });
1440
- return this;
1441
- }
1442
- async getReferenceCollection() {
1443
- return ContentReferences.create({ db: this.db });
1444
- }
1445
- async getFactCollection() {
1446
- const { FactCollection } = await import("@happyvertical/smrt-facts");
1447
- return FactCollection.create(this.options);
1448
- }
1449
- async getFactContentCollection() {
1450
- const { FactContentCollection } = await import("@happyvertical/smrt-facts");
1451
- return FactContentCollection.create(this.options);
1452
- }
1453
- async getFactSourceCollection() {
1454
- const { FactSourceCollection } = await import("@happyvertical/smrt-facts");
1455
- return FactSourceCollection.create(this.options);
1456
- }
1457
- async getFactEvidenceCollection() {
1458
- const { FactEvidenceCollection } = await import("@happyvertical/smrt-facts");
1459
- return FactEvidenceCollection.create(this.options);
1460
- }
1461
- async getContentVersionCollection() {
1462
- const { ContentVersionCollection } = await import("./content-versions-DzjCS3xs.js").then((n) => n.n);
1463
- return ContentVersionCollection.create(this.options);
1464
- }
1465
- async getContentReviewCollection() {
1466
- const { ContentReviewCollection } = await import("./content-reviews-D6o0zK8s.js").then((n) => n.n);
1467
- return ContentReviewCollection.create(this.options);
1468
- }
1469
- async getContentCorrectionCollection() {
1470
- const { ContentCorrectionCollection } = await import("./content-corrections-CKuY-MSv.js").then((n) => n.n);
1471
- return ContentCorrectionCollection.create(this.options);
1472
- }
1473
- async getContentsCollection() {
1474
- const { Contents } = await import("./contents-vywEFhzL.js").then((n) => n.n);
1475
- return Contents.create({ db: this.db });
1476
- }
1477
- getConfiguredGovernance() {
1478
- return resolveConfiguredContentGovernance({
1479
- contentType: this.type,
1480
- contentVariant: this.variant
1481
- });
1482
- }
1483
- async resolveGovernance() {
1484
- return resolveEffectiveContentGovernance({
1485
- contentType: this.type,
1486
- contentVariant: this.variant,
1487
- db: this.db,
1488
- tenantId: this.tenantId ?? null
1489
- });
1490
- }
1491
- async hasPersistedGovernanceAssignments() {
1492
- if (!this.db || typeof this.db.query !== "function") return false;
1493
- try {
1494
- const exactKey = buildContentGovernanceAssignmentKey(this.type || "", this.variant || "");
1495
- const typeOnlyKey = buildContentGovernanceAssignmentKey(this.type || "");
1496
- const keys = exactKey === typeOnlyKey ? [exactKey] : [exactKey, typeOnlyKey];
1497
- const placeholders = keys.map(() => "?").join(", ");
1498
- const result = await this.db.query(`SELECT 1 AS matched FROM content_governance_assignments WHERE key IN (${placeholders}) LIMIT 1`, keys);
1499
- return (Array.isArray(result) ? result : result?.rows ?? []).length > 0;
1500
- } catch {
1501
- return false;
1502
- }
1503
- }
1504
- async resolvePublicationGovernance() {
1505
- if (this.getConfiguredGovernance().isGoverned) return this.resolveGovernance();
1506
- if (!await this.hasPersistedGovernanceAssignments()) return null;
1507
- const governance = await this.resolveGovernance();
1508
- return governance.isGoverned ? governance : null;
1509
- }
1510
- async requireGovernance(feature = "governance workflow") {
1511
- const governance = await this.resolveGovernance();
1512
- if (!governance.isGoverned) throw new Error(`Governance is not enabled for content type "${this.type || "content"}"${this.variant ? ` variant "${this.variant}"` : ""}, so ${feature} is unavailable.`);
1513
- return governance;
1514
- }
1515
- async requireFactLinking(feature = "fact linking") {
1516
- const governance = await this.requireGovernance(feature);
1517
- if (!governance.factLinkingEnabled) throw new Error(`Fact linking is not enabled for content type "${this.type || "content"}"${this.variant ? ` variant "${this.variant}"` : ""}.`);
1518
- return governance;
1519
- }
1520
- async getPersistedContent() {
1521
- if (!this.id) return null;
1522
- return await (await this.getContentsCollection()).get({ id: this.id });
1523
- }
1524
- async buildReviewFingerprint(policyKey) {
1525
- const governance = await this.resolveGovernance();
1526
- const kind = getContentReviewKind(policyKey, governance.reviewPolicies);
1527
- const policy = getContentReviewPolicy(policyKey, governance.reviewPolicies);
1528
- const [references, facts, factLinks] = await Promise.all([
1529
- this.getReferences(),
1530
- kind === "facts" && governance.factLinkingEnabled ? this.getFacts({
1531
- latestOnly: true,
1532
- includeSuperseded: false
1533
- }) : Promise.resolve([]),
1534
- kind === "facts" && governance.factLinkingEnabled ? this.getFactLinks() : Promise.resolve([])
1535
- ]);
1536
- return createFingerprint({
1537
- scope: "content-review",
1538
- policyKey,
1539
- kind,
1540
- policyInstructions: policy?.instructions || "",
1541
- content: {
1542
- id: this.id || null,
1543
- type: this.type,
1544
- variant: this.variant,
1545
- title: this.title,
1546
- description: this.description,
1547
- body: this.body,
1548
- author: this.author,
1549
- state: this.state,
1550
- publishDate: this.publish_date,
1551
- language: this.language,
1552
- category: this.category,
1553
- tags: this.tags,
1554
- metadata: this.metadata
1555
- },
1556
- referenceIds: references.map((reference) => reference.id).filter(Boolean).sort(),
1557
- facts: facts.map((fact) => ({
1558
- id: fact.id || null,
1559
- previousFactId: fact.previousFactId || null,
1560
- status: fact.status || null,
1561
- textRefined: fact.textRefined || "",
1562
- sourceCount: fact.sourceCount ?? 0,
1563
- confidence: fact.confidence ?? null,
1564
- metadata: typeof fact?.getMetadata === "function" ? fact.getMetadata() : {}
1565
- })),
1566
- factLinks: factLinks.map((link) => ({
1567
- factId: link.factId || null,
1568
- relationship: link.relationship || null,
1569
- metadata: typeof link?.getMetadata === "function" ? link.getMetadata() : {}
1570
- }))
1571
- });
1572
- }
1573
- async buildTransparencySnapshot(options = {}) {
1574
- const snapshotKind = options.snapshotKind || "preview";
1575
- const governance = options.governance || await this.resolveGovernance();
1576
- if (!governance.isGoverned || !governance.transparencyEnabled) return null;
1577
- const [references, facts, factLinks, reviews, corrections, versions, reviewProfiles] = await Promise.all([
1578
- this.getReferences(),
1579
- governance.factLinkingEnabled ? this.getFacts({
1580
- latestOnly: true,
1581
- includeSuperseded: false
1582
- }) : Promise.resolve([]),
1583
- governance.factLinkingEnabled ? this.getFactLinks() : Promise.resolve([]),
1584
- this.listReviews(),
1585
- this.listCorrections(),
1586
- this.listVersions(),
1587
- this.listReviewProfilesAction()
1588
- ]);
1589
- const factSources = await this.getFactSourceCollection();
1590
- const factSourcesByFactId = /* @__PURE__ */ new Map();
1591
- for (const fact of facts) {
1592
- const factId = fact.id;
1593
- if (!factId) continue;
1594
- const sources = await factSources.getForFact(factId);
1595
- factSourcesByFactId.set(factId, sources);
1596
- }
1597
- const usedFactIds = new Set(factLinks.filter((link) => USED_FACT_RELATIONSHIPS.has(link.relationship || "related")).map((link) => link.factId).filter(Boolean));
1598
- const linkedFacts = facts.map((fact) => {
1599
- const factId = fact.id;
1600
- const link = factLinks.find((entry) => entry.factId === factId);
1601
- const sources = (factId ? factSourcesByFactId.get(factId) : []) || [];
1602
- return {
1603
- ...serializeFact(fact),
1604
- relationship: link?.relationship || null,
1605
- linkMetadata: typeof link?.getMetadata === "function" ? link.getMetadata() : {},
1606
- usedInArticle: factId ? usedFactIds.has(factId) : false,
1607
- sources: sources.map((source) => ({
1608
- id: source.id || null,
1609
- sourceType: source.sourceType || null,
1610
- sourceUrl: source.sourceUrl || null,
1611
- sourceTitle: source.sourceTitle || null,
1612
- credibility: source.credibility ?? null,
1613
- extractedAt: source.extractedAt || null,
1614
- metadata: typeof source?.getMetadata === "function" ? source.getMetadata() : {}
1615
- }))
1616
- };
1617
- });
1618
- const referenceGroups = await Promise.all(references.map(async (reference) => {
1619
- const sourceUrls = [
1620
- reference.url,
1621
- reference.original_url,
1622
- reference.source
1623
- ].filter(Boolean);
1624
- const extractedFacts = /* @__PURE__ */ new Map();
1625
- for (const sourceUrl of sourceUrls) {
1626
- const matches = await factSources.list({
1627
- where: { sourceUrl },
1628
- orderBy: "created_at ASC"
1629
- });
1630
- for (const match of matches) {
1631
- if (!match.factId || extractedFacts.has(match.factId)) continue;
1632
- const fact = await match.getFact();
1633
- if (fact?.id) extractedFacts.set(fact.id, fact);
1634
- }
1635
- }
1636
- const extractedFactRecords = [...extractedFacts.values()].map((fact) => {
1637
- const factId = fact.id;
1638
- return {
1639
- ...serializeFact(fact),
1640
- usedInArticle: factId ? usedFactIds.has(factId) : false
1641
- };
1642
- });
1643
- return {
1644
- id: reference.id || null,
1645
- title: reference.title || reference.name || reference.url || null,
1646
- url: reference.url || null,
1647
- originalUrl: reference.original_url || null,
1648
- type: reference.type || null,
1649
- source: reference.source || null,
1650
- usedFactIds: extractedFactRecords.filter((fact) => fact.id && usedFactIds.has(fact.id)).map((fact) => fact.id),
1651
- extractedFacts: extractedFactRecords
1652
- };
1653
- }));
1654
- const publicGeneration = readNestedRecord(this.metadata, ["transparency", "generation"]);
1655
- const generationMetadata = readNestedRecord(this.metadata, ["generation"]);
1656
- const serializedCorrections = corrections.filter((correction) => correction.status === "published").map((correction) => {
1657
- const correctionMetadata = asRecord(correction.metadata);
1658
- return {
1659
- ...serializeContentCorrection(correction),
1660
- provenance: {
1661
- autoGeneratedDraft: Boolean(correctionMetadata.autoGeneratedDraft),
1662
- draftVersionId: correctionMetadata.draftVersionId || null,
1663
- draftVersionNumber: correctionMetadata.draftVersionNumber || null,
1664
- sourceCorrectionVersionId: correctionMetadata.sourceCorrectionVersionId || null,
1665
- sourceCorrectionVersionNumber: correctionMetadata.sourceCorrectionVersionNumber || null
1666
- }
1667
- };
1668
- });
1669
- const serializedVersionHistory = versions.map((version) => {
1670
- const versionMetadata = asRecord(version.metadata);
1671
- return {
1672
- id: version.id || null,
1673
- version: version.version ?? null,
1674
- kind: version.kind || null,
1675
- summary: version.summary || "",
1676
- createdAt: version.createdAt || null,
1677
- provenance: {
1678
- policyKey: versionMetadata.policyKey || null,
1679
- reviewFingerprint: versionMetadata.reviewFingerprint || versionMetadata.contentFingerprint || null,
1680
- factId: versionMetadata.factId || null,
1681
- replacementFactId: versionMetadata.replacementFactId || null,
1682
- sourceCorrectionVersionId: versionMetadata.sourceCorrectionVersionId || null,
1683
- sourceCorrectionVersionNumber: versionMetadata.sourceCorrectionVersionNumber || null,
1684
- correctionDraft: versionMetadata.correctionDraft || null,
1685
- publicationSnapshotFingerprint: versionMetadata.publicationSnapshotFingerprint || null
1686
- }
1687
- };
1688
- });
1689
- return normalizeContentTransparency({
1690
- generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
1691
- snapshotKind,
1692
- contentId: this.id || null,
1693
- currentContentStatus: this.status || null,
1694
- publicationProfileKey: governance.publicationProfileKey || void 0,
1695
- generation: {
1696
- aiAssisted: publicGeneration.aiAssisted ?? generationMetadata.aiAssisted ?? Boolean(getPublicPrompt(this.metadata)),
1697
- publicPrompt: getPublicPrompt(this.metadata),
1698
- model: publicGeneration.model || generationMetadata.model || null
1699
- },
1700
- factsUsed: linkedFacts.filter((fact) => fact.usedInArticle),
1701
- linkedFacts,
1702
- otherExtractedFacts: referenceGroups.flatMap((reference) => reference.extractedFacts.filter((fact) => !fact.usedInArticle)),
1703
- references: referenceGroups,
1704
- reviews,
1705
- reviewProfiles,
1706
- corrections: serializedCorrections,
1707
- versionHistory: serializedVersionHistory
1708
- }, {
1709
- snapshotKind,
1710
- contentId: this.id || null,
1711
- currentContentStatus: this.status || null,
1712
- publicationProfileKey: governance.publicationProfileKey || void 0
1713
- });
1714
- }
1715
- /**
1716
- * Fingerprint of the *content-bearing* publication surface only.
1717
- *
1718
- * This must converge: two byte-identical `save()`s of published content
1719
- * have to produce the same fingerprint so the publication-version writer
1720
- * (`save()`) does not append a redundant `ContentVersion` on every save.
1721
- *
1722
- * It therefore deliberately excludes everything that grows or carries a
1723
- * timestamp/ordering with each save — `versionHistory`, `reviews`,
1724
- * `corrections`, and any `generatedAt`/`createdAt`/`id` fields. The earlier
1725
- * implementation fingerprinted the full transparency snapshot (which embeds
1726
- * the growing `versionHistory`), so the stored fingerprint of vN predated vN
1727
- * and the next save's recomputed fingerprint always differed → unbounded
1728
- * redundant publication versions (#1387 blocker).
1729
- *
1730
- * The surface mirrors `buildReviewFingerprint`'s content block, plus the
1731
- * pinned reference edges (`{ targetId, targetVersion }`) — a pin change is a
1732
- * meaningful republication — and the publication profile key.
1733
- */
1734
- async buildPublicationSnapshotFingerprint(governance) {
1735
- if (!governance.isGoverned || !governance.transparencyEnabled) return null;
1736
- const referenceCollection = await this.getReferenceCollection();
1737
- const [referenceEdges, facts, factLinks] = await Promise.all([
1738
- this.id ? referenceCollection.getForSource(this.id) : Promise.resolve([]),
1739
- governance.factLinkingEnabled ? this.getFacts({
1740
- latestOnly: true,
1741
- includeSuperseded: false
1742
- }) : Promise.resolve([]),
1743
- governance.factLinkingEnabled ? this.getFactLinks() : Promise.resolve([])
1744
- ]);
1745
- return createFingerprint({
1746
- scope: "content-publication",
1747
- publicationProfileKey: governance.publicationProfileKey || null,
1748
- content: {
1749
- id: this.id || null,
1750
- type: this.type,
1751
- variant: this.variant,
1752
- title: this.title,
1753
- description: this.description,
1754
- body: this.body,
1755
- author: this.author,
1756
- state: this.state,
1757
- publishDate: this.publish_date,
1758
- language: this.language,
1759
- category: this.category,
1760
- tags: this.tags,
1761
- metadata: this.metadata
1762
- },
1763
- references: referenceEdges.map((edge) => ({
1764
- targetId: edge.targetId || null,
1765
- targetVersion: edge.targetVersion ?? null
1766
- })).sort((a, b) => String(a.targetId).localeCompare(String(b.targetId))),
1767
- facts: facts.map((fact) => ({
1768
- id: fact.id || null,
1769
- previousFactId: fact.previousFactId || null,
1770
- status: fact.status || null,
1771
- textRefined: fact.textRefined || "",
1772
- sourceCount: fact.sourceCount ?? 0,
1773
- confidence: fact.confidence ?? null,
1774
- metadata: typeof fact?.getMetadata === "function" ? fact.getMetadata() : {}
1775
- })).sort((a, b) => String(a.id).localeCompare(String(b.id))),
1776
- factLinks: factLinks.map((link) => ({
1777
- factId: link.factId || null,
1778
- relationship: link.relationship || null,
1779
- metadata: typeof link?.getMetadata === "function" ? link.getMetadata() : {}
1780
- })).sort((a, b) => String(a.factId).localeCompare(String(b.factId)))
1781
- });
1782
- }
1783
- async getLatestPublicationSnapshotFingerprint() {
1784
- const latestPublicationVersion = [...await this.getVersions()].reverse().find((version) => version.kind === "publication");
1785
- if (!latestPublicationVersion) return null;
1786
- return latestPublicationVersion.getMetadata().publicationSnapshotFingerprint || null;
1787
- }
1788
- async buildCorrectionDraftSnapshot(options, replacementFactId) {
1789
- const correctedText = options.correctedText || options.correctedFactText || "";
1790
- const incorrectText = options.incorrectText || "";
1791
- let body = this.body;
1792
- let generationMethod = "metadata";
1793
- if (incorrectText && correctedText && body.includes(incorrectText)) {
1794
- body = body.replace(incorrectText, correctedText);
1795
- generationMethod = "replace";
1796
- } else if (correctedText) {
1797
- const ai = this.ai;
1798
- if (ai?.message) {
1799
- const resolvedPrompt = await resolvePrompt(smrtContentApplyCorrectionPrompt.key, {
1800
- db: this.options.db,
1801
- tenantId: this.tenantId,
1802
- variables: {
1803
- body: this.body,
1804
- correctedText,
1805
- incorrectText: incorrectText || "Not provided",
1806
- summary: options.summary || ""
1807
- }
1808
- });
1809
- try {
1810
- const proposedBody = (await ai.message(resolvedPrompt.text, promptMessageOptions(resolvedPrompt.ai))).trim();
1811
- if (proposedBody) {
1812
- body = proposedBody;
1813
- generationMethod = "ai";
1814
- }
1815
- } catch {
1816
- generationMethod = "metadata";
1817
- }
1818
- }
1819
- }
1820
- return {
1821
- snapshot: {
1822
- title: this.title,
1823
- description: this.description,
1824
- body,
1825
- status: "draft",
1826
- metadata: {
1827
- ...this.metadata || {},
1828
- governance: {
1829
- ...asRecord(this.metadata.governance),
1830
- correctionDraft: {
1831
- summary: options.summary,
1832
- incorrectText,
1833
- correctedText,
1834
- factId: options.factId || null,
1835
- replacementFactId: replacementFactId || null,
1836
- autoGenerated: true,
1837
- generationMethod
1838
- }
1839
- }
1840
- }
1841
- },
1842
- metadata: {
1843
- summary: options.summary,
1844
- incorrectText,
1845
- correctedText,
1846
- factId: options.factId || null,
1847
- replacementFactId: replacementFactId || null,
1848
- autoGenerated: true,
1849
- generationMethod
1850
- }
1851
- };
1852
- }
1853
- async getAssetCollection() {
1854
- return AssetCollection.create({ db: this.db });
1855
- }
1856
- async getContentAssetCollection() {
1857
- return ContentAssetCollection.create({ db: this.db });
1858
- }
1859
- async getContentAssetLinks(relationship) {
1860
- if (!this.id) return [];
1861
- try {
1862
- return (await (await this.getContentAssetCollection()).byLeft(this.id, relationship ? { relationship } : {})).filter((link) => link.assetId).map((link) => ({
1863
- assetId: link.assetId,
1864
- sortOrder: link.sortOrder ?? 0
1865
- }));
1866
- } catch (error) {
1867
- if (isMissingTableError(error, "content_assets")) return [];
1868
- throw error;
1869
- }
1870
- }
1871
- async resolveAssetsForLinks(links) {
1872
- if (links.length === 0) return [];
1873
- const assetIds = [...new Set(links.map((link) => link.assetId))];
1874
- const resolved = await (await this.getAssetCollection()).listByIds(assetIds);
1875
- const assetsById = new Map(resolved.filter((asset) => asset.id).map((asset) => [asset.id, asset]));
1876
- return links.map((link) => assetsById.get(link.assetId)).filter(Boolean);
1877
- }
1878
- async resolveReferenceTarget(content) {
1879
- if (typeof content !== "string") return content;
1880
- return await (await this.getContentsCollection()).getOrUpsert({
1881
- url: content,
1882
- tenantId: this.tenantId
1883
- }, {
1884
- name: content,
1885
- title: content,
1886
- type: "reference",
1887
- tenantId: this.tenantId
1888
- });
1889
- }
1890
- /**
1891
- * Loads referenced content objects
1892
- *
1893
- * @returns Promise that resolves when references are loaded
1894
- */
1895
- async loadReferences() {
1896
- this.references = await this.getReferences();
1897
- }
1898
- getPendingReferenceIds() {
1899
- const pendingReferenceIds = this.referenceIds;
1900
- if (!Array.isArray(pendingReferenceIds)) return null;
1901
- return [...new Set(pendingReferenceIds.filter((referenceId) => typeof referenceId === "string" && referenceId.length > 0 && referenceId !== this.id))];
1902
- }
1903
- getPendingAssetIds() {
1904
- const pendingAssetIds = this.assetIds;
1905
- if (!Array.isArray(pendingAssetIds)) return null;
1906
- return [...new Set(pendingAssetIds.filter((assetId) => typeof assetId === "string" && assetId.length > 0))];
1907
- }
1908
- async syncPendingReferenceIds() {
1909
- if (!this.id) return;
1910
- const pendingReferenceIds = this.getPendingReferenceIds();
1911
- if (pendingReferenceIds === null) return;
1912
- const currentReferenceIds = (await this.getReferences()).map((reference) => reference.id).filter((referenceId) => Boolean(referenceId));
1913
- const currentReferenceIdSet = new Set(currentReferenceIds);
1914
- const pendingReferenceIdSet = new Set(pendingReferenceIds);
1915
- for (const referenceId of currentReferenceIds) if (!pendingReferenceIdSet.has(referenceId)) await this.removeReference(referenceId);
1916
- const referenceIdsToAdd = pendingReferenceIds.filter((referenceId) => !currentReferenceIdSet.has(referenceId));
1917
- if (referenceIdsToAdd.length === 0) {
1918
- this.references = await this.getReferences();
1919
- return;
1920
- }
1921
- const resolvedReferences = await (await this.getContentsCollection()).listByIds(referenceIdsToAdd);
1922
- const referencesById = new Map(resolvedReferences.filter((reference) => reference.id).map((reference) => [reference.id, reference]));
1923
- for (const referenceId of referenceIdsToAdd) {
1924
- const reference = referencesById.get(referenceId);
1925
- if (reference) await this.addReference(reference);
1926
- }
1927
- this.references = await this.getReferences();
1928
- }
1929
- async syncPendingAssetIds() {
1930
- if (!this.id) return;
1931
- const pendingAssetIds = this.getPendingAssetIds();
1932
- if (pendingAssetIds === null) return;
1933
- const currentAssetIds = (await this.getAssets()).map((asset) => asset.id).filter((assetId) => Boolean(assetId));
1934
- const currentAssetIdSet = new Set(currentAssetIds);
1935
- const pendingAssetIdSet = new Set(pendingAssetIds);
1936
- for (const assetId of currentAssetIds) if (!pendingAssetIdSet.has(assetId)) await this.removeAsset(assetId);
1937
- const assetIdsToAdd = pendingAssetIds.filter((assetId) => !currentAssetIdSet.has(assetId));
1938
- if (assetIdsToAdd.length === 0) return;
1939
- const resolvedAssets = await (await this.getAssetCollection()).listByIds(assetIdsToAdd);
1940
- const assetsById = new Map(resolvedAssets.filter((asset) => asset.id).map((asset) => [asset.id, asset]));
1941
- for (const assetId of assetIdsToAdd) {
1942
- const asset = assetsById.get(assetId);
1943
- if (asset) await this.addAsset(asset);
1944
- }
1945
- }
1946
- /**
1947
- * Adds a reference to another content object.
1948
- *
1949
- * @param content - Content object or URL to reference
1950
- * @param options.targetVersion - Optional ContentVersion.version to pin the
1951
- * citation to. Pass the target's current version (typically the latest
1952
- * publication) to enable drift detection later. Pass `null` or omit to
1953
- * leave the reference untracked.
1954
- * @returns Promise that resolves when the reference is added
1955
- */
1956
- async addReference(content, options = {}) {
1957
- if (!this.id) throw new Error("Cannot add reference to unsaved content");
1958
- const target = await this.resolveReferenceTarget(content);
1959
- if (!target.id) throw new Error("Cannot add reference to unsaved content");
1960
- if (this.id === target.id) return;
1961
- await (await this.getReferenceCollection()).attach(this.id, target.id, {
1962
- tenantId: this.tenantId,
1963
- targetVersion: options.targetVersion
1964
- });
1965
- this.references = await this.getReferences();
1966
- }
1967
- /**
1968
- * Removes a reference to another content object
1969
- *
1970
- * @param targetId - ID of the referenced content to remove
1971
- */
1972
- async removeReference(targetId) {
1973
- if (!this.id) return;
1974
- await (await this.getReferenceCollection()).detach(this.id, targetId);
1975
- this.references = this.references.filter((reference) => reference.id !== targetId);
1976
- }
1977
- /**
1978
- * Gets all referenced content objects
1979
- *
1980
- * @returns Promise resolving to an array of referenced Content objects
1981
- */
1982
- async getReferences() {
1983
- if (!this.id) return [];
1984
- const targetIds = (await (await this.getReferenceCollection()).byLeft(this.id)).map((reference) => reference.targetId);
1985
- if (targetIds.length === 0) {
1986
- this.references = [];
1987
- return this.references;
1988
- }
1989
- const resolved = await (await this.getContentsCollection()).listByIds(targetIds);
1990
- const referencesById = new Map(resolved.filter((content) => content.id).map((content) => [content.id, content]));
1991
- this.references = targetIds.map((targetId) => referencesById.get(targetId)).filter(Boolean);
1992
- return this.references;
1993
- }
1994
- /**
1995
- * Returns the raw reference edges with their citation pins
1996
- * (`{ targetId, targetVersion }`). Unlike `getReferences()` (which resolves
1997
- * to `Content` objects and loses the per-edge `targetVersion`), this keeps
1998
- * the pin so callers — notably version snapshots — can reconstruct pinned
1999
- * citations on restore. See `ContentVersionCollection.restoreIntoContent`.
2000
- */
2001
- async getReferenceEdges() {
2002
- if (!this.id) return [];
2003
- return (await (await this.getReferenceCollection()).getForSource(this.id)).filter((edge) => Boolean(edge.targetId)).map((edge) => ({
2004
- targetId: edge.targetId,
2005
- targetVersion: edge.targetVersion ?? null
2006
- }));
2007
- }
2008
- /**
2009
- * Returns one entry per reference edge with the pinned `targetVersion` and
2010
- * the target's latest version. Drift exists when both are present and
2011
- * differ — callers can use this to surface "the source you cited has been
2012
- * updated" affordances in editors or review tools.
2013
- *
2014
- * `currentVersion` is the target's latest **publication** `ContentVersion`,
2015
- * because pins are taken against the latest publication (see `addReference`).
2016
- * Auto-created `correction`/`draft`/`manual` versions bump the shared
2017
- * `(content_id, version)` counter but do NOT republish, so comparing against
2018
- * the max version of *any* kind produced false drift positives (#1387 #4).
2019
- *
2020
- * Unpinned references (`citedVersion === null`) are included with
2021
- * `currentVersion` populated when available so callers can choose to
2022
- * surface them as "pinnable" suggestions.
2023
- */
2024
- async getReferenceDrift() {
2025
- if (!this.id) return [];
2026
- const linkedReferences = await (await this.getReferenceCollection()).getForSource(this.id);
2027
- if (linkedReferences.length === 0) return [];
2028
- const versions = await this.getContentVersionCollection();
2029
- const targetIds = linkedReferences.map((reference) => reference.targetId);
2030
- const allVersions = await versions.list({
2031
- where: {
2032
- contentId: targetIds,
2033
- kind: "publication"
2034
- },
2035
- orderBy: "version DESC"
2036
- });
2037
- const latestByContentId = /* @__PURE__ */ new Map();
2038
- for (const version of allVersions) if (!latestByContentId.has(version.contentId)) latestByContentId.set(version.contentId, version.version);
2039
- return linkedReferences.map((reference) => {
2040
- const currentVersion = latestByContentId.get(reference.targetId) ?? null;
2041
- const citedVersion = reference.targetVersion ?? null;
2042
- return {
2043
- targetId: reference.targetId,
2044
- citedVersion,
2045
- currentVersion,
2046
- isDrifted: citedVersion !== null && currentVersion !== null && citedVersion !== currentVersion
2047
- };
2048
- });
2049
- }
2050
- isGoverned() {
2051
- return this.getConfiguredGovernance().isGoverned;
2052
- }
2053
- async getFactLinks(options = {}) {
2054
- const governance = await this.resolveGovernance();
2055
- if (!governance.isGoverned || !governance.factLinkingEnabled || !this.id) return [];
2056
- if (!this.id) return [];
2057
- const links = await this.getFactContentCollection();
2058
- return options.relationship ? links.byRight(this.id, { relationship: options.relationship }) : links.byRight(this.id);
2059
- }
2060
- async getFacts(options = {}) {
2061
- const governance = await this.resolveGovernance();
2062
- if (!governance.isGoverned || !governance.factLinkingEnabled || !this.id) return [];
2063
- if (!this.id) return [];
2064
- return (await this.getFactCollection()).getForContent(this.id, options);
2065
- }
2066
- async addFact(fact, relationship, metadata) {
2067
- const governance = await this.requireFactLinking("fact association");
2068
- if (!this.id) throw new Error("Cannot associate an unsaved content item with a fact");
2069
- const factId = typeof fact === "string" ? fact : fact.id;
2070
- if (!factId) throw new Error("Fact ID is required to create a content-fact link");
2071
- return (await this.getFactContentCollection()).attach(factId, this.id, {
2072
- relationship: relationship || governance.defaultFactRelationship,
2073
- metadata
2074
- });
2075
- }
2076
- async removeFact(factId, relationship) {
2077
- const governance = await this.resolveGovernance();
2078
- if (!governance.isGoverned || !governance.factLinkingEnabled) return;
2079
- if (!this.id) return;
2080
- const links = await this.getFactContentCollection();
2081
- if (relationship) {
2082
- await links.detach(factId, this.id, { relationship });
2083
- return;
2084
- }
2085
- await links.detach(factId, this.id);
2086
- }
2087
- async syncFacts(factIds, relationship) {
2088
- const governance = await this.requireFactLinking("fact sync");
2089
- if (!this.id) throw new Error("Cannot sync facts for unsaved content");
2090
- const uniqueFactIds = [...new Set(factIds.filter(Boolean))];
2091
- const links = await this.getFactContentCollection();
2092
- const resolvedRelationship = relationship || governance.defaultFactRelationship;
2093
- const existing = await links.byRight(this.id, { relationship: resolvedRelationship });
2094
- const existingIds = new Set(existing.map((link) => link.factId));
2095
- const desiredIds = new Set(uniqueFactIds);
2096
- const kept = uniqueFactIds.filter((factId) => existingIds.has(factId));
2097
- const added = uniqueFactIds.filter((factId) => !existingIds.has(factId));
2098
- const removed = existing.map((link) => link.factId).filter((factId) => !desiredIds.has(factId));
2099
- for (const factId of added) await links.attach(factId, this.id, { relationship: resolvedRelationship });
2100
- for (const factId of removed) await links.detach(factId, this.id, { relationship: resolvedRelationship });
2101
- return {
2102
- added,
2103
- kept,
2104
- removed
2105
- };
2106
- }
2107
- async browseFacts(query = "", options = {}) {
2108
- await this.requireFactLinking("fact catalog browsing");
2109
- return (await this.getFactCollection()).browseCatalog(query, {
2110
- ...options,
2111
- tenantId: this.tenantId
2112
- });
2113
- }
2114
- async getFactAuditSourceMaterials() {
2115
- const warnings = [];
2116
- const sources = [];
2117
- const references = await this.getReferences();
2118
- const assets = await this.getAssets();
2119
- for (const reference of references) {
2120
- const referenceId = reference.id || "";
2121
- const text = getContentText(reference);
2122
- const referenceSourceUrl = reference.sourceUrl;
2123
- const sourceUrl = normalizeAuditText(reference.url) || normalizeAuditText(referenceSourceUrl) || normalizeAuditText(reference.fileKey);
2124
- const sourceTitle = normalizeAuditText(reference.title) || normalizeAuditText(reference.name) || sourceUrl || referenceId;
2125
- if (!text) {
2126
- warnings.push(`Reference ${sourceTitle || referenceId} has no extracted text.`);
2127
- continue;
2128
- }
2129
- sources.push({
2130
- sourceKind: "content-reference",
2131
- sourceId: referenceId,
2132
- sourceUrl,
2133
- sourceTitle,
2134
- locator: sourceTitle,
2135
- text
2136
- });
2137
- }
2138
- for (const asset of assets) {
2139
- const metadata = typeof asset?.getMetadata === "function" ? asset.getMetadata() : parseAuditMetadata(asset?.metadata);
2140
- const text = [
2141
- metadata.extractedText,
2142
- metadata.text,
2143
- metadata.ocrText,
2144
- asset?.text,
2145
- asset?.body,
2146
- asset?.description
2147
- ].map(normalizeAuditText).filter(Boolean).join("\n\n");
2148
- const assetId = normalizeAuditText(asset?.id);
2149
- const sourceTitle = normalizeAuditText(asset?.title) || normalizeAuditText(asset?.name) || normalizeAuditText(asset?.filename) || assetId;
2150
- const sourceUrl = normalizeAuditText(asset?.url) || normalizeAuditText(asset?.sourceUrl) || normalizeAuditText(asset?.fileKey);
2151
- if (!text) {
2152
- warnings.push(`Asset ${sourceTitle || assetId} has no extracted text.`);
2153
- continue;
2154
- }
2155
- sources.push({
2156
- sourceKind: "asset",
2157
- sourceId: assetId,
2158
- sourceUrl,
2159
- sourceTitle,
2160
- locator: sourceTitle,
2161
- text
2162
- });
2163
- }
2164
- return {
2165
- sources,
2166
- warnings
2167
- };
2168
- }
2169
- factMatchesTenant(fact) {
2170
- return fact.tenantId === this.tenantId || fact.tenant_id === this.tenantId || !fact.tenantId && !fact.tenant_id && !this.tenantId;
2171
- }
2172
- async findExactArticleClaimFact(statement) {
2173
- const normalizedStatement = normalizeAuditText(statement);
2174
- const facts = await this.getFactCollection();
2175
- const linkedMatch = (await Promise.all((await this.getFactLinks({ relationship: "referenced_in" })).map((link) => facts.get({ id: link.factId })))).find((fact) => Boolean(fact) && this.factMatchesTenant(fact) && normalizeAuditText(fact.textRefined) === normalizedStatement);
2176
- if (linkedMatch) return linkedMatch;
2177
- return (await facts.list({
2178
- where: { textRefined: normalizedStatement },
2179
- orderBy: "updated_at DESC"
2180
- })).find((fact) => this.factMatchesTenant(fact) && this.id && isGeneratedArticleClaimFact(fact, this.id)) || null;
2181
- }
2182
- async safeAuditLink(factId, relationship, metadata) {
2183
- const links = await this.getFactContentCollection();
2184
- const existing = (await links.byRight(this.id, { relationship })).find((link) => link.factId === factId);
2185
- if (existing) {
2186
- const existingMetadata = getLinkMetadata(existing);
2187
- if (existingMetadata.generatedBy === FACT_AUDIT_GENERATED_BY) existing.setMetadata?.({
2188
- ...existingMetadata,
2189
- ...metadata
2190
- });
2191
- else existing.setMetadata?.({
2192
- ...existingMetadata,
2193
- factAudit: {
2194
- ...asRecord(existingMetadata.factAudit),
2195
- ...metadata
2196
- }
2197
- });
2198
- await existing.save();
2199
- return existing;
2200
- }
2201
- return links.attach(factId, this.id, {
2202
- relationship,
2203
- metadata
2204
- });
2205
- }
2206
- async clearGeneratedFactAudit() {
2207
- if (!this.id) return;
2208
- const [links, evidences] = await Promise.all([this.getFactLinks(), this.getFactEvidenceCollection()]);
2209
- for (const link of links) {
2210
- const metadata = getLinkMetadata(link);
2211
- const nestedFactAudit = asRecord(metadata.factAudit);
2212
- if (metadata.generatedBy === FACT_AUDIT_GENERATED_BY) await link.delete();
2213
- else if (metadata.factAudit && typeof metadata.factAudit === "object" && nestedFactAudit.generatedBy === FACT_AUDIT_GENERATED_BY) {
2214
- const { factAudit: _removed, ...preservedMetadata } = metadata;
2215
- link.setMetadata?.(preservedMetadata);
2216
- await link.save();
2217
- }
2218
- }
2219
- const generatedEvidence = await evidences.list({ where: { tenantId: this.tenantId ?? null } });
2220
- for (const evidence of generatedEvidence) {
2221
- const metadata = typeof evidence.getMetadata === "function" ? evidence.getMetadata() : {};
2222
- if (metadata.generatedBy === FACT_AUDIT_GENERATED_BY && metadata.contentId === this.id) await evidence.delete();
2223
- }
2224
- }
2225
- async clearGeneratedFactSourcesForSources(sources) {
2226
- if (!this.id || sources.length === 0) return [];
2227
- const sourceKeys = new Set(sources.map((source) => `${source.sourceKind}:${source.sourceId}`));
2228
- const generatedSources = await (await this.getFactSourceCollection()).list({ where: { tenantId: this.tenantId ?? null } });
2229
- const deletedSourceIds = [];
2230
- for (const source of generatedSources) {
2231
- const metadata = typeof source.getMetadata === "function" ? source.getMetadata() : {};
2232
- const sourceKey = `${source.sourceType || ""}:${metadata.sourceId || ""}`;
2233
- if (sourceKeys.has(sourceKey) && metadata.generatedBy === FACT_AUDIT_GENERATED_BY && metadata.contentId === this.id) {
2234
- if (typeof source.id === "string") deletedSourceIds.push(source.id);
2235
- await source.delete();
2236
- }
2237
- }
2238
- return deletedSourceIds;
2239
- }
2240
- async extractReferenceFactsForAudit(sources, options) {
2241
- const facts = await this.getFactCollection();
2242
- const evidences = await this.getFactEvidenceCollection();
2243
- const warnings = [];
2244
- const referenceFacts = /* @__PURE__ */ new Map();
2245
- let deletedEvidenceIds = [];
2246
- let deletedSourceIds = [];
2247
- if (options.replaceGenerated && sources.length > 0) {
2248
- deletedEvidenceIds = (await evidences.replaceGeneratedForSources(sources.map((source) => ({
2249
- sourceKind: source.sourceKind,
2250
- sourceId: source.sourceId
2251
- })), {
2252
- generatedBy: FACT_AUDIT_GENERATED_BY,
2253
- contentId: this.id,
2254
- tenantId: this.tenantId ?? null
2255
- })).deletedEvidenceIds;
2256
- deletedSourceIds = await this.clearGeneratedFactSourcesForSources(sources);
2257
- }
2258
- for (const source of sources) {
2259
- let candidates = [];
2260
- try {
2261
- candidates = await facts.extractCandidatesFromText(source.text, {
2262
- domain: FACT_AUDIT_DOMAIN,
2263
- sourceType: source.sourceKind,
2264
- context: options.context || source.sourceTitle,
2265
- maxFacts: options.maxFactsPerSource ?? 24,
2266
- tenantId: this.tenantId
2267
- });
2268
- } catch (error) {
2269
- warnings.push(`Failed to extract facts from ${source.sourceTitle}: ${errorMessage(error)}`);
2270
- continue;
2271
- }
2272
- for (const candidate of candidates) {
2273
- const result = await facts.reconcile({
2274
- rawInput: candidate.statement,
2275
- type: candidate.type || "assertion",
2276
- domain: FACT_AUDIT_DOMAIN,
2277
- tenantId: this.tenantId,
2278
- source: {
2279
- sourceType: source.sourceKind,
2280
- sourceUrl: source.sourceUrl,
2281
- sourceTitle: source.sourceTitle,
2282
- credibility: candidate.confidence ?? .75,
2283
- metadata: {
2284
- auditRunId: options.auditRunId,
2285
- generatedBy: FACT_AUDIT_GENERATED_BY,
2286
- contentId: this.id,
2287
- sourceId: source.sourceId,
2288
- quote: candidate.sourceExcerpt || null,
2289
- locator: source.locator || null
2290
- }
2291
- }
2292
- });
2293
- referenceFacts.set(result.fact.id, result.fact);
2294
- await evidences.upsertEvidence({
2295
- factId: result.fact.id,
2296
- status: "supports",
2297
- sourceKind: source.sourceKind,
2298
- sourceId: source.sourceId,
2299
- sourceUrl: source.sourceUrl,
2300
- sourceTitle: source.sourceTitle,
2301
- quote: candidate.sourceExcerpt || candidate.statement,
2302
- locator: source.locator,
2303
- extractionMethod: "ai-reference-fact",
2304
- confidence: candidate.confidence ?? .75,
2305
- tenantId: this.tenantId,
2306
- metadata: {
2307
- auditRunId: options.auditRunId,
2308
- generatedBy: FACT_AUDIT_GENERATED_BY,
2309
- contentId: this.id,
2310
- candidateMetadata: candidate.metadata || {}
2311
- }
2312
- });
2313
- }
2314
- }
2315
- return {
2316
- referenceFacts,
2317
- warnings,
2318
- referenceFactsExtracted: referenceFacts.size,
2319
- deletedEvidenceIds,
2320
- deletedSourceIds,
2321
- repairedSources: sources.map((source) => ({
2322
- sourceKind: source.sourceKind,
2323
- sourceId: source.sourceId,
2324
- sourceTitle: source.sourceTitle
2325
- }))
2326
- };
2327
- }
2328
- async getCurrentFactAuditSupportCandidates(options = {}) {
2329
- const evidences = await this.getFactEvidenceCollection();
2330
- const allFacts = await this.getFactCollection();
2331
- const candidateFacts = /* @__PURE__ */ new Map();
2332
- const candidateEvidence = /* @__PURE__ */ new Map();
2333
- const sourceKeys = new Set((options.sources || []).map((source) => `${source.sourceKind}:${source.sourceId}`));
2334
- const sourceIds = new Set(options.sourceIds || []);
2335
- const maxCandidateEvidence = Math.max(1, options.maxCandidateEvidence ?? 120);
2336
- const evidenceEntries = options.referenceFacts ? (await Promise.all([...options.referenceFacts.keys()].map((factId) => evidences.getForFact(factId)))).flat() : await evidences.list({ where: { tenantId: this.tenantId ?? null } });
2337
- for (const entry of evidenceEntries) {
2338
- if (!isGeneratedFactAuditEvidence(entry, this.id)) continue;
2339
- if (entry.sourceKind === "content") continue;
2340
- if (entry.status === "irrelevant" || entry.status === "invalid") continue;
2341
- if (sourceKeys.size > 0 && !sourceKeys.has(`${entry.sourceKind}:${entry.sourceId}`)) continue;
2342
- if (sourceIds.size > 0 && !sourceIds.has(entry.sourceId)) continue;
2343
- if (candidateEvidence.size >= maxCandidateEvidence) break;
2344
- const fact = options.referenceFacts?.get(entry.factId) || await allFacts.get({ id: entry.factId });
2345
- if (!fact) continue;
2346
- const factId = fact.id;
2347
- const existing = candidateFacts.get(factId) || {
2348
- id: factId,
2349
- statement: fact.textRefined || fact.textRaw || "",
2350
- evidence: []
2351
- };
2352
- const serializedEvidence = {
2353
- id: entry.id || null,
2354
- status: entry.status || "supports",
2355
- quote: entry.quote || null,
2356
- sourceTitle: entry.sourceTitle || null,
2357
- sourceUrl: entry.sourceUrl || null,
2358
- locator: entry.locator || null
2359
- };
2360
- existing.evidence.push(serializedEvidence);
2361
- candidateFacts.set(factId, existing);
2362
- if (typeof entry.id === "string") candidateEvidence.set(entry.id, entry);
2363
- }
2364
- return {
2365
- supportCandidates: [...candidateFacts.values()],
2366
- candidateFactIds: new Set(candidateFacts.keys()),
2367
- candidateEvidence
2368
- };
2369
- }
2370
- async repairFactAudit(options = {}) {
2371
- await this.requireFactLinking("fact audit repair");
2372
- if (!this.id) throw new Error("Cannot repair fact audit for unsaved content");
2373
- const auditRunId = createFactAuditRunId(this.id);
2374
- const facts = await this.getFactCollection();
2375
- const evidences = await this.getFactEvidenceCollection();
2376
- const warnings = [];
2377
- const articleText = getContentText(this);
2378
- const sourceMaterials = await this.getFactAuditSourceMaterials();
2379
- warnings.push(...sourceMaterials.warnings);
2380
- await this.clearGeneratedFactAudit();
2381
- const referenceRepair = await this.extractReferenceFactsForAudit(sourceMaterials.sources, {
2382
- auditRunId,
2383
- maxFactsPerSource: options.maxReferenceFactsPerSource,
2384
- context: options.context
2385
- });
2386
- warnings.push(...referenceRepair.warnings);
2387
- const referenceFacts = referenceRepair.referenceFacts;
2388
- let claims = [];
2389
- if (!articleText) warnings.push("Article has no text to audit.");
2390
- else try {
2391
- claims = await facts.extractArticleClaims(articleText, {
2392
- domain: FACT_AUDIT_DOMAIN,
2393
- sourceType: "article",
2394
- context: options.context || this.title || this.slug || "",
2395
- maxFacts: options.maxArticleClaims ?? 32,
2396
- tenantId: this.tenantId
2397
- });
2398
- } catch (error) {
2399
- warnings.push(`Failed to extract article claims: ${errorMessage(error)}`);
2400
- }
2401
- const { supportCandidates, candidateFactIds, candidateEvidence } = await this.getCurrentFactAuditSupportCandidates({ referenceFacts });
2402
- const findings = [];
2403
- for (const claim of claims) {
2404
- let assessment;
2405
- try {
2406
- assessment = await facts.assessClaimSupport(claim.statement, supportCandidates, { tenantId: this.tenantId });
2407
- } catch (error) {
2408
- warnings.push(`Failed to assess claim "${claim.statement}": ${errorMessage(error)}`);
2409
- assessment = {
2410
- status: "needs_review",
2411
- matchedFactIds: [],
2412
- matchedEvidenceIds: [],
2413
- rationale: "Support assessment failed.",
2414
- confidence: void 0
2415
- };
2416
- }
2417
- const matchedFactIds = assessment.matchedFactIds.filter((factId) => candidateFactIds.has(factId));
2418
- let claimFact = await this.findExactArticleClaimFact(claim.statement);
2419
- if (!claimFact) claimFact = await facts.create({
2420
- textRefined: claim.statement,
2421
- textRaw: claim.statement,
2422
- type: claim.type || "assertion",
2423
- domain: FACT_AUDIT_DOMAIN,
2424
- status: assessment.status === "unsupported" || assessment.status === "needs_review" ? "pending" : "active",
2425
- sourceCount: 0,
2426
- confidence: claim.confidence ?? assessment.confidence ?? .5,
2427
- tenantId: this.tenantId,
2428
- metadata: JSON.stringify({
2429
- auditRunId,
2430
- generatedBy: FACT_AUDIT_GENERATED_BY,
2431
- contentId: this.id,
2432
- auditFactRole: "article-claim",
2433
- claimOnly: matchedFactIds.length === 0
2434
- })
2435
- });
2436
- else if (this.id && isGeneratedArticleClaimFact(claimFact, this.id)) {
2437
- claimFact.status = assessment.status === "unsupported" || assessment.status === "needs_review" ? "pending" : "active";
2438
- claimFact.confidence = claim.confidence ?? assessment.confidence ?? claimFact.confidence;
2439
- claimFact.updateMetadata?.({
2440
- auditRunId,
2441
- generatedBy: FACT_AUDIT_GENERATED_BY,
2442
- contentId: this.id,
2443
- auditFactRole: "article-claim",
2444
- claimOnly: matchedFactIds.length === 0
2445
- });
2446
- await claimFact.save();
2447
- }
2448
- const articleEvidence = await evidences.upsertEvidence({
2449
- factId: claimFact.id,
2450
- status: "supports",
2451
- sourceKind: "content",
2452
- sourceId: this.id,
2453
- sourceTitle: this.title || this.slug || this.id,
2454
- quote: claim.sourceExcerpt || claim.statement,
2455
- locator: this.title || this.slug || "",
2456
- extractionMethod: "ai-article-claim",
2457
- confidence: claim.confidence ?? assessment.confidence ?? .5,
2458
- tenantId: this.tenantId,
2459
- metadata: {
2460
- auditRunId,
2461
- generatedBy: FACT_AUDIT_GENERATED_BY,
2462
- contentId: this.id,
2463
- supportStatus: assessment.status
2464
- }
2465
- });
2466
- let supportingEvidenceIds = assessment.matchedEvidenceIds.filter((evidenceId) => candidateEvidence.has(evidenceId));
2467
- for (const matchedFactId of matchedFactIds) {
2468
- if (supportingEvidenceIds.length > 0) continue;
2469
- const candidate = supportCandidates.find((entry) => entry.id === matchedFactId);
2470
- supportingEvidenceIds = [...supportingEvidenceIds, ...(candidate?.evidence || []).map((entry) => entry.id).filter((id) => typeof id === "string")];
2471
- }
2472
- supportingEvidenceIds = [...new Set(supportingEvidenceIds)];
2473
- const linkMetadata = {
2474
- auditRunId,
2475
- generatedBy: FACT_AUDIT_GENERATED_BY,
2476
- supportStatus: assessment.status,
2477
- claimQuote: claim.sourceExcerpt || claim.statement,
2478
- claimFactId: claimFact.id,
2479
- articleEvidenceId: articleEvidence.id || null,
2480
- supportingFactIds: matchedFactIds,
2481
- supportingEvidenceIds,
2482
- rationale: assessment.rationale,
2483
- confidence: assessment.confidence ?? claim.confidence ?? null
2484
- };
2485
- await this.safeAuditLink(claimFact.id, "referenced_in", linkMetadata);
2486
- for (const matchedFactId of matchedFactIds) await this.safeAuditLink(matchedFactId, assessment.status === "contradicted" ? "contradicts" : "supports", {
2487
- ...linkMetadata,
2488
- supportingEvidenceIds
2489
- });
2490
- if (assessment.status !== "supported") findings.push({
2491
- severity: assessment.status === "contradicted" ? "error" : "warning",
2492
- title: assessment.status === "contradicted" ? "Contradicted article claim" : "Unsupported article claim",
2493
- detail: assessment.rationale || "The claim needs editorial review.",
2494
- factId: claimFact.id,
2495
- quote: claim.sourceExcerpt || claim.statement,
2496
- ruleId: "fact-audit"
2497
- });
2498
- }
2499
- await (await this.getContentReviewCollection()).createFromResult({
2500
- contentId: this.id,
2501
- kind: "facts",
2502
- policyKey: "facts",
2503
- reviewer: "system",
2504
- result: {
2505
- status: findings.length > 0 ? "flagged" : "passed",
2506
- summary: findings.length > 0 ? `${findings.length} article claim(s) need review.` : "Article claims are supported by available evidence.",
2507
- findings
2508
- },
2509
- metadata: {
2510
- auditRunId,
2511
- generatedBy: FACT_AUDIT_GENERATED_BY,
2512
- warnings
2513
- },
2514
- tenantId: this.tenantId
2515
- });
2516
- return {
2517
- ...await this.getFactAuditState(),
2518
- repair: {
2519
- auditRunId,
2520
- claimsExtracted: claims.length,
2521
- referenceFactsExtracted: referenceRepair.referenceFactsExtracted,
2522
- warnings
2523
- }
2524
- };
2525
- }
2526
- async repairFactAuditAction(options = {}) {
2527
- return this.repairFactAudit(options);
2528
- }
2529
- async repairFactEvidence(options = {}) {
2530
- await this.requireFactLinking("fact evidence repair");
2531
- if (!this.id) throw new Error("Cannot repair fact evidence for unsaved content");
2532
- const auditRunId = createFactAuditRunId(this.id);
2533
- const sources = filterAuditSources((await this.getFactAuditSourceMaterials()).sources, options.sources);
2534
- const warnings = [];
2535
- if (options.sources?.length && sources.length === 0) warnings.push("No matching resource text was available for repair.");
2536
- const repair = await this.extractReferenceFactsForAudit(sources, {
2537
- auditRunId,
2538
- maxFactsPerSource: options.maxFactsPerSource,
2539
- context: options.context,
2540
- replaceGenerated: true
2541
- });
2542
- warnings.push(...repair.warnings);
2543
- return {
2544
- ...await this.getFactAuditState(),
2545
- evidenceRepair: {
2546
- auditRunId,
2547
- referenceFactsExtracted: repair.referenceFactsExtracted,
2548
- repairedSources: repair.repairedSources,
2549
- deletedEvidenceIds: repair.deletedEvidenceIds,
2550
- deletedSourceIds: repair.deletedSourceIds,
2551
- warnings
2552
- }
2553
- };
2554
- }
2555
- async repairFactEvidenceAction(options = {}) {
2556
- return this.repairFactEvidence(options);
2557
- }
2558
- async clearGeneratedSupportLinksForClaim(claimFactId, articleEvidenceId) {
2559
- const links = await this.getFactLinks();
2560
- for (const link of links) {
2561
- if (link.relationship !== "supports" && link.relationship !== "contradicts") continue;
2562
- const metadata = getGeneratedFactAuditMetadata(link);
2563
- if (!metadata) continue;
2564
- const matchesEvidence = articleEvidenceId && typeof metadata.articleEvidenceId === "string" && metadata.articleEvidenceId === articleEvidenceId;
2565
- const matchesClaim = typeof metadata.claimFactId === "string" && metadata.claimFactId === claimFactId;
2566
- if (matchesEvidence || matchesClaim) await link.delete();
2567
- }
2568
- }
2569
- async recheckFactClaims(options = {}) {
2570
- await this.requireFactLinking("claim support recheck");
2571
- if (!this.id) throw new Error("Cannot recheck fact claims for unsaved content");
2572
- const auditRunId = createFactAuditRunId(this.id);
2573
- const facts = await this.getFactCollection();
2574
- const evidences = await this.getFactEvidenceCollection();
2575
- const links = await this.getFactContentCollection();
2576
- const claimIdFilter = new Set(options.claimFactIds || []);
2577
- const { supportCandidates, candidateFactIds, candidateEvidence } = await this.getCurrentFactAuditSupportCandidates({
2578
- sources: options.sources,
2579
- sourceIds: options.sourceIds,
2580
- maxCandidateEvidence: options.maxCandidateEvidence
2581
- });
2582
- const claimLinks = (await links.byRight(this.id, { relationship: "referenced_in" })).map((link) => ({
2583
- link,
2584
- metadata: getGeneratedFactAuditMetadata(link)
2585
- })).filter((entry) => entry.metadata !== null && (claimIdFilter.size === 0 || claimIdFilter.has(entry.link.factId)));
2586
- const warnings = [];
2587
- let recheckedClaims = 0;
2588
- for (const { link, metadata } of claimLinks) {
2589
- const claimFact = await facts.get({ id: link.factId });
2590
- if (!claimFact) continue;
2591
- const claimText = normalizeAuditText(metadata.claimQuote) || normalizeAuditText(claimFact.textRefined) || normalizeAuditText(claimFact.textRaw);
2592
- if (!claimText) continue;
2593
- let assessment;
2594
- try {
2595
- assessment = await facts.assessClaimSupport(claimText, supportCandidates, { tenantId: this.tenantId });
2596
- } catch (error) {
2597
- warnings.push(`Failed to recheck claim "${claimText}": ${errorMessage(error)}`);
2598
- assessment = {
2599
- status: "needs_review",
2600
- matchedFactIds: [],
2601
- matchedEvidenceIds: [],
2602
- rationale: "Support assessment failed.",
2603
- confidence: void 0
2604
- };
2605
- }
2606
- const matchedFactIds = assessment.matchedFactIds.filter((factId) => candidateFactIds.has(factId));
2607
- let supportStatus = assessment.status;
2608
- if ((supportStatus === "supported" || supportStatus === "contradicted") && matchedFactIds.length === 0) supportStatus = "needs_review";
2609
- let supportingEvidenceIds = assessment.matchedEvidenceIds.filter((evidenceId) => candidateEvidence.has(evidenceId));
2610
- if (supportingEvidenceIds.length === 0) for (const matchedFactId of matchedFactIds) {
2611
- const candidate = supportCandidates.find((entry) => entry.id === matchedFactId);
2612
- supportingEvidenceIds.push(...(candidate?.evidence || []).map((entry) => entry.id).filter((id) => typeof id === "string"));
2613
- }
2614
- supportingEvidenceIds = [...new Set(supportingEvidenceIds)];
2615
- const articleEvidenceId = typeof metadata.articleEvidenceId === "string" ? metadata.articleEvidenceId : null;
2616
- const nextMetadata = {
2617
- ...metadata,
2618
- auditRunId,
2619
- generatedBy: FACT_AUDIT_GENERATED_BY,
2620
- supportStatus,
2621
- supportingFactIds: matchedFactIds,
2622
- supportingEvidenceIds,
2623
- rationale: assessment.rationale,
2624
- confidence: assessment.confidence ?? metadata.confidence ?? null,
2625
- claimFactId: link.factId
2626
- };
2627
- const existingMetadata = getLinkMetadata(link);
2628
- if (existingMetadata.generatedBy === FACT_AUDIT_GENERATED_BY) link.setMetadata?.(nextMetadata);
2629
- else link.setMetadata?.({
2630
- ...existingMetadata,
2631
- factAudit: nextMetadata
2632
- });
2633
- await link.save();
2634
- if (articleEvidenceId) {
2635
- const articleEvidence = await evidences.get({ id: articleEvidenceId });
2636
- if (articleEvidence) {
2637
- articleEvidence.updateMetadata({
2638
- auditRunId,
2639
- supportStatus
2640
- });
2641
- await articleEvidence.save();
2642
- }
2643
- }
2644
- await this.clearGeneratedSupportLinksForClaim(link.factId, articleEvidenceId);
2645
- for (const matchedFactId of matchedFactIds) await this.safeAuditLink(matchedFactId, supportStatus === "contradicted" ? "contradicts" : "supports", {
2646
- ...nextMetadata,
2647
- articleEvidenceId
2648
- });
2649
- recheckedClaims += 1;
2650
- }
2651
- return {
2652
- ...await this.getFactAuditState(),
2653
- claimRecheck: {
2654
- auditRunId,
2655
- recheckedClaims,
2656
- candidateFacts: supportCandidates.length,
2657
- candidateEvidence: candidateEvidence.size,
2658
- warnings
2659
- }
2660
- };
2661
- }
2662
- async recheckFactClaimsAction(options = {}) {
2663
- return this.recheckFactClaims(options);
2664
- }
2665
- async updateFactEvidenceStatus(options = {}) {
2666
- await this.requireFactLinking("evidence status update");
2667
- if (!this.id) throw new Error("Cannot update fact evidence for unsaved content");
2668
- const status = normalizeFactEvidenceStatus(options.status);
2669
- if (!status) throw new Error("A valid evidence status is required");
2670
- const requestedEvidenceIds = [...new Set((options.evidenceIds || []).filter((id) => typeof id === "string" && id.length > 0))];
2671
- const evidences = await this.getFactEvidenceCollection();
2672
- const sourceMaterials = await this.getFactAuditSourceMaterials();
2673
- const allowedSourceKeys = new Set(sourceMaterials.sources.map((source) => `${source.sourceKind}:${source.sourceId}`));
2674
- const allowedEvidenceIds = [];
2675
- for (const evidenceId of requestedEvidenceIds) {
2676
- const evidence = await evidences.get({ id: evidenceId });
2677
- if (!evidence) continue;
2678
- if (this.tenantId && evidence.tenantId && evidence.tenantId !== this.tenantId) continue;
2679
- const metadata = getEvidenceMetadata(evidence);
2680
- const sourceKey = `${evidence.sourceKind || ""}:${evidence.sourceId || ""}`;
2681
- if (metadata.contentId === this.id || evidence.sourceKind === "content" && evidence.sourceId === this.id || allowedSourceKeys.has(sourceKey)) allowedEvidenceIds.push(evidenceId);
2682
- }
2683
- const updated = await evidences.bulkUpdateStatus(allowedEvidenceIds, status, { reason: options.reason });
2684
- return {
2685
- ...await this.getFactAuditState(),
2686
- evidenceStatusUpdate: {
2687
- status,
2688
- requestedEvidenceIds,
2689
- updatedEvidenceIds: updated.map((entry) => entry.id).filter((id) => typeof id === "string"),
2690
- skippedEvidenceIds: requestedEvidenceIds.filter((id) => !allowedEvidenceIds.includes(id))
2691
- }
2692
- };
2693
- }
2694
- async updateFactEvidenceStatusAction(options = {}) {
2695
- return this.updateFactEvidenceStatus(options);
2696
- }
2697
- async getFactAuditState() {
2698
- if (!this.id) return {
2699
- counts: {
2700
- total: 0,
2701
- supported: 0,
2702
- unsupported: 0,
2703
- contradicted: 0,
2704
- needs_review: 0
2705
- },
2706
- claims: [],
2707
- resourceClaims: [],
2708
- warnings: [],
2709
- generatedBy: FACT_AUDIT_GENERATED_BY,
2710
- latestAuditRunId: null
2711
- };
2712
- const [facts, factLinks] = await Promise.all([this.getFacts({
2713
- relationship: "referenced_in",
2714
- latestOnly: false,
2715
- includeSuperseded: false
2716
- }), this.getFactLinks({ relationship: "referenced_in" })]);
2717
- const factMap = new Map(facts.filter((fact) => fact.id).map((fact) => [fact.id, fact]));
2718
- const evidences = await this.getFactEvidenceCollection();
2719
- const allFacts = await this.getFactCollection();
2720
- const generatedLinks = factLinks.map((link) => ({
2721
- link,
2722
- metadata: getGeneratedFactAuditMetadata(link)
2723
- })).filter((entry) => entry.metadata !== null);
2724
- const claims = [];
2725
- const resourceClaimsByKey = /* @__PURE__ */ new Map();
2726
- const warnings = [];
2727
- let latestAuditRunId = null;
2728
- for (const { link, metadata } of generatedLinks) {
2729
- const fact = factMap.get(link.factId);
2730
- if (!fact) continue;
2731
- latestAuditRunId = metadata.auditRunId || latestAuditRunId;
2732
- const status = metadata.supportStatus || "needs_review";
2733
- const matchedFactIds = Array.isArray(metadata.supportingFactIds) ? metadata.supportingFactIds : [];
2734
- const articleEvidenceId = typeof metadata.articleEvidenceId === "string" ? metadata.articleEvidenceId : null;
2735
- const supportingEvidenceIds = new Set(Array.isArray(metadata.supportingEvidenceIds) ? metadata.supportingEvidenceIds.filter((id) => typeof id === "string") : []);
2736
- const [allClaimEvidence, matchedFacts] = await Promise.all([evidences.getForFact(fact.id), Promise.all(matchedFactIds.map(async (factId) => {
2737
- const matchedFact = await allFacts.get({ id: factId });
2738
- const matchedEvidence = (await evidences.getForFact(factId)).filter((entry) => supportingEvidenceIds.size === 0 ? entry.sourceKind !== "content" || entry.sourceId !== this.id : supportingEvidenceIds.has(entry.id));
2739
- return matchedFact ? {
2740
- fact: serializeFact(matchedFact),
2741
- evidence: matchedEvidence.map((entry) => ({
2742
- ...serializeFact(entry),
2743
- metadata: typeof entry.getMetadata === "function" ? entry.getMetadata() : {}
2744
- }))
2745
- } : null;
2746
- }))]);
2747
- const claimEvidence = allClaimEvidence.filter((entry) => articleEvidenceId ? entry.id === articleEvidenceId : entry.sourceKind === "content" && entry.sourceId === this.id);
2748
- claims.push({
2749
- id: fact.id,
2750
- fact: serializeFact(fact),
2751
- supportStatus: status,
2752
- claimQuote: metadata.claimQuote || null,
2753
- rationale: metadata.rationale || null,
2754
- confidence: metadata.confidence ?? null,
2755
- relationship: link.relationship || null,
2756
- linkMetadata: metadata,
2757
- evidence: claimEvidence.map((entry) => ({
2758
- ...serializeFact(entry),
2759
- metadata: typeof entry.getMetadata === "function" ? entry.getMetadata() : {}
2760
- })),
2761
- matchedFacts: matchedFacts.filter(Boolean)
2762
- });
2763
- }
2764
- const generatedEvidence = await evidences.list({ where: { tenantId: this.tenantId ?? null } });
2765
- for (const evidence of generatedEvidence) {
2766
- const metadata = typeof evidence.getMetadata === "function" ? evidence.getMetadata() : {};
2767
- if (metadata.generatedBy !== FACT_AUDIT_GENERATED_BY || metadata.contentId !== this.id || evidence.sourceKind === "content") continue;
2768
- const fact = await allFacts.get({ id: evidence.factId });
2769
- if (!fact) continue;
2770
- const key = [
2771
- evidence.factId,
2772
- evidence.sourceKind,
2773
- evidence.sourceId,
2774
- evidence.evidenceKey
2775
- ].join(":");
2776
- const serializedEvidence = {
2777
- ...serializeFact(evidence),
2778
- metadata
2779
- };
2780
- const existing = resourceClaimsByKey.get(key);
2781
- if (existing) {
2782
- existing.evidence.push(serializedEvidence);
2783
- continue;
2784
- }
2785
- resourceClaimsByKey.set(key, {
2786
- id: fact.id,
2787
- fact: serializeFact(fact),
2788
- sourceKind: evidence.sourceKind || null,
2789
- sourceId: evidence.sourceId || null,
2790
- sourceUrl: evidence.sourceUrl || null,
2791
- sourceTitle: evidence.sourceTitle || null,
2792
- locator: evidence.locator || null,
2793
- quote: evidence.quote || null,
2794
- status: evidence.status || "supports",
2795
- confidence: evidence.confidence ?? null,
2796
- evidence: [serializedEvidence]
2797
- });
2798
- }
2799
- const review = await (await this.getContentReviewCollection()).getLatestForPolicyKey(this.id, "facts");
2800
- const reviewMetadata = review && typeof review.getMetadata === "function" ? review.getMetadata() : {};
2801
- if (reviewMetadata.generatedBy === FACT_AUDIT_GENERATED_BY && Array.isArray(reviewMetadata.warnings)) warnings.push(...reviewMetadata.warnings);
2802
- const counts = {
2803
- total: claims.length,
2804
- supported: 0,
2805
- unsupported: 0,
2806
- contradicted: 0,
2807
- needs_review: 0
2808
- };
2809
- for (const claim of claims) counts[claim.supportStatus] += 1;
2810
- return {
2811
- counts,
2812
- claims,
2813
- resourceClaims: [...resourceClaimsByKey.values()],
2814
- warnings,
2815
- generatedBy: FACT_AUDIT_GENERATED_BY,
2816
- latestAuditRunId
2817
- };
2818
- }
2819
- async getFactAuditStateAction() {
2820
- return this.getFactAuditState();
2821
- }
2822
- async getFactsState(options = {}) {
2823
- const governance = await this.resolveGovernance();
2824
- if (!governance.isGoverned || !governance.factLinkingEnabled) return {
2825
- factIds: [],
2826
- facts: [],
2827
- factLinks: []
2828
- };
2829
- const relationship = options.relationship;
2830
- const [facts, factLinks] = await Promise.all([this.getFacts({
2831
- relationship,
2832
- latestOnly: true,
2833
- includeSuperseded: false
2834
- }), this.getFactLinks(relationship ? { relationship } : {})]);
2835
- return {
2836
- factIds: facts.map((fact) => fact.id).filter(Boolean),
2837
- facts: facts.map(serializeFact),
2838
- factLinks: factLinks.map(serializeFactLink)
2839
- };
2840
- }
2841
- async syncFactsState(options = {}) {
2842
- const governance = await this.requireFactLinking("fact sync");
2843
- const relationship = options.relationship || governance.defaultFactRelationship;
2844
- const sync = await this.syncFacts(options.factIds || [], relationship);
2845
- return {
2846
- ...await this.getFactsState({ relationship }),
2847
- sync
2848
- };
2849
- }
2850
- async createVersion(options = {}) {
2851
- return (await this.getContentVersionCollection()).createSnapshot(this, options);
2852
- }
2853
- async getVersions() {
2854
- if (!this.id) return [];
2855
- return (await this.getContentVersionCollection()).listForContent(this.id);
2856
- }
2857
- async restoreFromVersion(versionNumber) {
2858
- return (await this.getContentVersionCollection()).restoreIntoContent(this, versionNumber);
2859
- }
2860
- async getReviews(kind) {
2861
- if (!this.id) return [];
2862
- return (await this.getContentReviewCollection()).listForContent(this.id, kind);
2863
- }
2864
- async listReviews(options = {}) {
2865
- return (await this.getReviews(options.kind)).map(serializeContentReview);
2866
- }
2867
- async getReviewRequirements(profileKey, governance) {
2868
- return getContentReviewRequirements(profileKey, (governance || await this.resolveGovernance()).availableProfiles);
2869
- }
2870
- async getGovernanceState() {
2871
- const governance = await this.resolveGovernance();
2872
- if (!governance.isGoverned) return {
2873
- ...governance,
2874
- reviewProfiles: []
2875
- };
2876
- return {
2877
- ...governance,
2878
- reviewProfiles: await this.listReviewProfilesAction()
2879
- };
2880
- }
2881
- async getGovernanceStateAction() {
2882
- return this.getGovernanceState();
2883
- }
2884
- async listReviewProfilesAction() {
2885
- const governance = await this.resolveGovernance();
2886
- if (!governance.isGoverned) return [];
2887
- return Promise.all(getContentReviewProfileKeys(governance.availableProfiles).map((profileKey) => this.evaluateReviewProfile(profileKey)));
2888
- }
2889
- async evaluateReviewProfile(profileKey) {
2890
- const governance = await this.resolveGovernance();
2891
- const requirements = await this.getReviewRequirements(profileKey, governance);
2892
- if (requirements.length === 0) return {
2893
- profileKey,
2894
- ready: true,
2895
- complete: true,
2896
- requirements: []
2897
- };
2898
- const reviews = await this.getContentReviewCollection();
2899
- const reviewFingerprintCache = /* @__PURE__ */ new Map();
2900
- const evaluatedRequirements = await Promise.all(requirements.map(async (requirement) => {
2901
- if (!reviewFingerprintCache.has(requirement.policyKey)) reviewFingerprintCache.set(requirement.policyKey, await this.buildReviewFingerprint(requirement.policyKey));
2902
- const latestReview = this.id && requirement.policyKey ? await reviews.getLatestForPolicyKey(this.id, requirement.policyKey) : null;
2903
- const acceptedStatuses = getAcceptedContentReviewStatuses(requirement);
2904
- const latestStatus = latestReview?.status ?? null;
2905
- const latestMetadata = typeof latestReview?.getMetadata === "function" ? latestReview.getMetadata() : {};
2906
- const currentFingerprint = reviewFingerprintCache.get(requirement.policyKey) || null;
2907
- const reviewedFingerprint = latestMetadata?.reviewFingerprint || latestMetadata?.contentFingerprint || null;
2908
- const missing = !latestReview;
2909
- const stale = !missing && !!reviewedFingerprint && reviewedFingerprint !== currentFingerprint;
2910
- const executed = latestStatus !== null && latestStatus !== "pending" && !stale;
2911
- const satisfied = !stale && latestStatus !== null && acceptedStatuses.includes(latestStatus);
2912
- return {
2913
- kind: getContentReviewKind(requirement.policyKey, governance.reviewPolicies),
2914
- policyKey: requirement.policyKey,
2915
- label: requirement.label || getContentReviewPolicy(requirement.policyKey, governance.reviewPolicies)?.label || requirement.policyKey,
2916
- blocking: requirement.blocking === true,
2917
- acceptedStatuses,
2918
- missing,
2919
- stale,
2920
- executed,
2921
- satisfied,
2922
- latestReviewId: latestReview?.id || null,
2923
- latestStatus,
2924
- latestSummary: latestReview?.summary || null
2925
- };
2926
- }));
2927
- return {
2928
- profileKey,
2929
- ready: evaluatedRequirements.filter((requirement) => requirement.blocking).every((requirement) => requirement.satisfied),
2930
- complete: evaluatedRequirements.every((requirement) => requirement.executed),
2931
- requirements: evaluatedRequirements
2932
- };
2933
- }
2934
- async evaluateReviewProfileAction(options = {}) {
2935
- if (!options.profileKey) throw new Error("profileKey is required");
2936
- return this.evaluateReviewProfile(options.profileKey);
2937
- }
2938
- async isReadyForReviewProfile(profileKey) {
2939
- return (await this.evaluateReviewProfile(profileKey)).ready;
2940
- }
2941
- async getPublishedTransparency() {
2942
- if (!this.id) return null;
2943
- return (await (await this.getContentVersionCollection()).getLatestPublishedForContent(this.id))?.getTransparency() || null;
2944
- }
2945
- async getPublishedTransparencyAction() {
2946
- return this.getPublishedTransparency();
2947
- }
2948
- async previewTransparency() {
2949
- const governance = await this.resolveGovernance();
2950
- if (!governance.isGoverned || !governance.transparencyEnabled) return null;
2951
- return this.buildTransparencySnapshot({
2952
- snapshotKind: "preview",
2953
- governance
2954
- });
2955
- }
2956
- async previewTransparencyAction() {
2957
- return this.previewTransparency();
2958
- }
2959
- async runReview(options = {}) {
2960
- const governance = await this.requireGovernance("review execution");
2961
- if (!this.id) throw new Error("Cannot review unsaved content");
2962
- const policyKey = options.policyKey || options.kind || "custom";
2963
- const policy = getContentReviewPolicy(policyKey, governance.reviewPolicies);
2964
- const kind = options.kind || getContentReviewKind(policyKey, governance.reviewPolicies);
2965
- const facts = options.facts !== void 0 ? options.facts : governance.factLinkingEnabled && (kind === "facts" || Boolean(options.factIds?.length)) ? await this.getFacts({
2966
- latestOnly: true,
2967
- includeSuperseded: false
2968
- }) : [];
2969
- const filteredFacts = options.factIds && options.factIds.length > 0 ? facts.filter((fact) => options.factIds?.includes(fact.id)) : facts;
2970
- const reviewPrompt = buildContentReviewPrompt({
2971
- kind,
2972
- content: this,
2973
- facts: filteredFacts,
2974
- policy,
2975
- customInstructions: options.instructions
2976
- });
2977
- const resolvedPrompt = await resolvePrompt(smrtContentReviewPrompt.key, {
2978
- db: this.options.db,
2979
- tenantId: this.tenantId,
2980
- variables: {
2981
- contentBody: this.body,
2982
- contentDescription: this.description ?? "",
2983
- contentId: this.id ?? "",
2984
- contentTitle: this.title,
2985
- kind,
2986
- policyKey: policy?.key || kind,
2987
- reviewPrompt
2988
- }
2989
- });
2990
- const reviewFingerprint = await this.buildReviewFingerprint(policyKey);
2991
- const ai = this.ai;
2992
- if (!ai?.message) throw new Error("AI client is not configured for content reviews");
2993
- const rawResponse = await ai.message(resolvedPrompt.text, promptMessageOptions(resolvedPrompt.ai));
2994
- const result = parseContentReviewResponse(rawResponse);
2995
- const persistReview = async (content) => {
2996
- if (options.expectedUpdatedAt !== void 0) await content.claimRevision(options.expectedUpdatedAt);
2997
- const version = options.createVersion === false ? null : await content.createVersion({
2998
- kind: "review",
2999
- summary: result.summary,
3000
- metadata: {
3001
- kind,
3002
- policyKey,
3003
- reviewFingerprint
3004
- }
3005
- });
3006
- return (await content.getContentReviewCollection()).createFromResult({
3007
- contentId: content.id,
3008
- contentVersionId: version?.id,
3009
- kind,
3010
- policyKey,
3011
- reviewer: options.reviewer || "system",
3012
- result,
3013
- metadata: {
3014
- ...options.metadata || {},
3015
- prompt: resolvedPrompt.text,
3016
- rawResponse,
3017
- reviewFingerprint,
3018
- factIds: filteredFacts.map((fact) => fact.id)
3019
- },
3020
- tenantId: content.tenantId
3021
- });
3022
- };
3023
- if (options.expectedUpdatedAt !== void 0) {
3024
- if (!this.db.transaction) throw new Error("Atomic content review persistence requires transaction support");
3025
- return this.withTransaction(persistReview);
3026
- }
3027
- return persistReview(this);
3028
- }
3029
- async runReviewAction(options = {}) {
3030
- let review;
3031
- if (options.kind === "facts") review = await this.reviewFacts(options);
3032
- else if (options.kind === "safety") review = await this.reviewSafety(options);
3033
- else review = await this.runReview(options);
3034
- return serializeContentReview(review);
3035
- }
3036
- async reviewFacts(options = {}) {
3037
- return this.runReview({
3038
- ...options,
3039
- kind: "facts",
3040
- policyKey: options.policyKey || "facts"
3041
- });
3042
- }
3043
- async reviewSafety(options = {}) {
3044
- const governance = await this.requireGovernance("safety review");
3045
- const baseInstructions = getContentReviewPolicy(options.policyKey || "safety", governance.reviewPolicies)?.instructions || "";
3046
- return this.runReview({
3047
- ...options,
3048
- kind: "safety",
3049
- policyKey: options.policyKey || "safety",
3050
- instructions: options.instructions && baseInstructions ? `${baseInstructions}
3051
-
3052
- Additional app-level guidance:
3053
- ${options.instructions}` : options.instructions || baseInstructions
3054
- });
3055
- }
3056
- async getCorrections() {
3057
- if (!this.id) return [];
3058
- return (await this.getContentCorrectionCollection()).listForContent(this.id);
3059
- }
3060
- async listCorrections() {
3061
- return (await this.getCorrections()).map(serializeContentCorrection);
3062
- }
3063
- async issueCorrection(options) {
3064
- const governance = await this.requireGovernance("corrections");
3065
- if (!this.id) throw new Error("Cannot issue a correction for unsaved content");
3066
- let replacementFactId = "";
3067
- if (governance.factLinkingEnabled && options.factId && options.correctedFactText) {
3068
- const facts = await this.getFactCollection();
3069
- const existing = await facts.get({ id: options.factId });
3070
- if (!existing) throw new Error(`Fact not found for correction: ${options.factId}`);
3071
- const replacement = await facts.create({
3072
- textRefined: options.correctedFactText,
3073
- textRaw: options.correctedFactText,
3074
- type: existing.getType(),
3075
- domain: existing.domain,
3076
- status: "active",
3077
- tenantId: existing.tenantId ?? this.tenantId ?? null,
3078
- previousFactId: options.factId,
3079
- evolutionType: "correction"
3080
- });
3081
- existing.status = "superseded";
3082
- await existing.save();
3083
- replacementFactId = replacement.id;
3084
- await this.addFact(replacementFactId);
3085
- }
3086
- const version = options.createVersion === false ? null : await this.createVersion({
3087
- kind: "correction",
3088
- summary: options.summary,
3089
- metadata: {
3090
- factId: options.factId || null,
3091
- replacementFactId: replacementFactId || null
3092
- }
3093
- });
3094
- const correctionDraft = options.createVersion === false ? null : await this.buildCorrectionDraftSnapshot(options, replacementFactId);
3095
- const draftVersion = options.createVersion === false || !correctionDraft ? null : await this.createVersion({
3096
- kind: "draft",
3097
- summary: `Auto-created correction draft: ${options.summary}`,
3098
- snapshot: correctionDraft.snapshot,
3099
- metadata: {
3100
- ...correctionDraft.metadata,
3101
- sourceCorrectionVersionId: version?.id || null,
3102
- sourceCorrectionVersionNumber: version?.version ?? null
3103
- }
3104
- });
3105
- const corrections = await this.getContentCorrectionCollection();
3106
- const shouldPublish = options.publish ?? this.status === "published";
3107
- return corrections.issue({
3108
- contentId: this.id,
3109
- contentVersionId: version?.id || "",
3110
- factId: options.factId || "",
3111
- replacementFactId,
3112
- correctionType: options.correctionType || "fact",
3113
- status: shouldPublish ? "published" : "draft",
3114
- summary: options.summary,
3115
- incorrectText: options.incorrectText || "",
3116
- correctedText: options.correctedText || options.correctedFactText || "",
3117
- publicNote: options.publicNote || "",
3118
- metadata: {
3119
- ...options.metadata || {},
3120
- autoGeneratedDraft: Boolean(draftVersion),
3121
- draftVersionId: draftVersion?.id || null,
3122
- draftVersionNumber: draftVersion?.version ?? null,
3123
- sourceCorrectionVersionId: version?.id || null,
3124
- sourceCorrectionVersionNumber: version?.version ?? null,
3125
- correctionProfileKey: governance.correctionProfileKey || null
3126
- },
3127
- tenantId: this.tenantId,
3128
- publishedAt: shouldPublish ? /* @__PURE__ */ new Date() : null
3129
- });
3130
- }
3131
- async issueCorrectionAction(options) {
3132
- return serializeContentCorrection(await this.issueCorrection(options));
3133
- }
3134
- async listVersions() {
3135
- return (await this.getVersions()).map(serializeContentVersion);
3136
- }
3137
- async mutateVersionAction(options = {}) {
3138
- if (options.action === "restore") {
3139
- const versionNumber = Number(options.versionNumber);
3140
- if (!Number.isFinite(versionNumber)) throw new Error("versionNumber is required to restore a version");
3141
- return serializeContent(await this.restoreFromVersion(versionNumber));
3142
- }
3143
- return serializeContentVersion(await this.createVersion(options));
3144
- }
3145
- /**
3146
- * Note: toJSON() is inherited from SmrtObject
3147
- *
3148
- * The parent implementation handles:
3149
- * - STI discriminator (_meta_type) for polymorphic queries
3150
- * - Meta field extraction (_meta_data) for child-specific fields
3151
- * - Automatic serialization of all fields from manifest
3152
- *
3153
- * DO NOT override toJSON() unless you call super.toJSON() first.
3154
- * See issue #377 for details on why this override was removed.
3155
- */
3156
- /**
3157
- * Get category segments as array
3158
- * @example 'politics/local' -> ['politics', 'local']
3159
- */
3160
- getCategorySegments() {
3161
- if (!this.category) return [];
3162
- return this.category.split("/").filter(Boolean);
3163
- }
3164
- /**
3165
- * Get parent category path
3166
- * @example 'politics/local/town' -> 'politics/local'
3167
- * @example 'politics' -> null
3168
- */
3169
- getParentCategory() {
3170
- const segments = this.getCategorySegments();
3171
- if (segments.length <= 1) return null;
3172
- return segments.slice(0, -1).join("/");
3173
- }
3174
- /**
3175
- * Get root (top-level) category
3176
- * @example 'politics/local/town' -> 'politics'
3177
- */
3178
- getRootCategory() {
3179
- return this.getCategorySegments()[0] || null;
3180
- }
3181
- /**
3182
- * Get all ancestor category paths (for breadcrumbs)
3183
- * @example 'politics/local' -> ['politics', 'politics/local']
3184
- */
3185
- getAncestorPaths() {
3186
- const segments = this.getCategorySegments();
3187
- return segments.map((_, i) => segments.slice(0, i + 1).join("/"));
3188
- }
3189
- /**
3190
- * Check if content belongs to a category (optionally including subcategories)
3191
- * @param categoryPath - Category to check
3192
- * @param includeChildren - If true, matches 'politics' for content in 'politics/local'
3193
- */
3194
- isInCategory(categoryPath, includeChildren = true) {
3195
- if (!this.category) return false;
3196
- if (includeChildren) return this.category === categoryPath || this.category.startsWith(`${categoryPath}/`);
3197
- return this.category === categoryPath;
3198
- }
3199
- /**
3200
- * Get all assets associated with this content
3201
- * @param relationship - Optional filter by relationship type (e.g., 'thumbnail', 'attachment')
3202
- * @returns Promise resolving to array of assets
3203
- */
3204
- async getAssets(relationship) {
3205
- if (!this.id) return [];
3206
- return this.resolveAssetsForLinks(await this.getContentAssetLinks(relationship));
3207
- }
3208
- /**
3209
- * Add an asset to this content with a relationship type
3210
- * @param asset - The asset to associate
3211
- * @param relationship - Relationship type (e.g., 'thumbnail', 'attachment', 'inline')
3212
- * @param sortOrder - Optional sort order for display
3213
- */
3214
- async addAsset(asset, relationship = "attachment", sortOrder = 0) {
3215
- if (!this.id || !asset.id) throw new Error("Cannot associate unsaved content or asset");
3216
- if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(relationship)) throw new Error(`Invalid relationship type "${relationship}"; must start with a letter or underscore and contain only letters, digits, and underscores`);
3217
- if (!Number.isInteger(sortOrder) || sortOrder < 0 || sortOrder > 2147483647) throw new Error(`Invalid sortOrder "${sortOrder}"; must be a non-negative integer`);
3218
- await (await this.getContentAssetCollection()).attach(this.id, asset.id, {
3219
- relationship,
3220
- sortOrder,
3221
- tenantId: this.tenantId
3222
- });
3223
- }
3224
- /**
3225
- * Remove an asset from this content
3226
- * @param assetId - ID of the asset to remove
3227
- * @param relationship - Optional specific relationship to remove (removes all if not specified)
3228
- */
3229
- async removeAsset(assetId, relationship) {
3230
- if (!this.id) return;
3231
- try {
3232
- await (await this.getContentAssetCollection()).detach(this.id, assetId, relationship ? { relationship } : {});
3233
- } catch (error) {
3234
- if (!isMissingTableError(error, "content_assets")) throw error;
3235
- }
3236
- }
3237
- /**
3238
- * Get the full metadata record. Always returns a plain object — never
3239
- * `null`, never an array — so callers can safely read nested keys without
3240
- * defensive checks.
3241
- *
3242
- * Pure read with no side-effect on `this.metadata`: if the field is
3243
- * currently `null` (e.g. fresh from the DB) or non-record-shaped, an
3244
- * empty object is returned but the field is **not** mutated. This avoids
3245
- * accidentally marking the object dirty during a read, which would
3246
- * otherwise cause SmrtObject's save lifecycle to write `{}` back over a
3247
- * NULL column on the next save. Callers that want to normalise the
3248
- * stored field should use {@link Content.setMetadata}.
3249
- */
3250
- getMetadata() {
3251
- return isPlainMetadataRecord(this.metadata) ? this.metadata : {};
3252
- }
3253
- /**
3254
- * Replace the full metadata record. Passing `null`/`undefined` (or any
3255
- * non-record value such as an array) clears it to an empty object so
3256
- * downstream readers can rely on the field always being a plain object.
3257
- */
3258
- setMetadata(metadata) {
3259
- this.metadata = isPlainMetadataRecord(metadata) ? { ...metadata } : {};
3260
- }
3261
- /**
3262
- * Shallow-merge a patch over the current metadata. Returns the resulting
3263
- * record so callers can chain reads without re-reading the field. Unlike
3264
- * {@link Content.getMetadata}, this method does intentionally write back
3265
- * to `this.metadata` because the merge is a write.
3266
- */
3267
- updateMetadata(patch) {
3268
- const next = {
3269
- ...this.getMetadata(),
3270
- ...patch ?? {}
3271
- };
3272
- this.metadata = next;
3273
- return next;
3274
- }
3275
- /**
3276
- * Get the thumbnail image for this content
3277
- * @returns Promise resolving to the thumbnail Image or null
3278
- */
3279
- async getThumbnail() {
3280
- if (!this.thumbnailAssetId) return null;
3281
- return (await ImageCollection.create({ db: this.options?.db })).get({ id: this.thumbnailAssetId });
3282
- }
3283
- /**
3284
- * Set the thumbnail image for this content
3285
- * @param image - The image to set as thumbnail
3286
- */
3287
- async setThumbnail(image) {
3288
- await this.addAsset(image, "thumbnail", 0);
3289
- this.thumbnailAssetId = image.id ?? null;
3290
- await this.save();
3291
- }
3292
- /**
3293
- * Generate a thumbnail for this content using the specified strategy
3294
- *
3295
- * @param options - Thumbnail generation options including strategy
3296
- * @returns Promise resolving to the generated Image
3297
- *
3298
- * @example Headline card thumbnail
3299
- * ```typescript
3300
- * const thumbnail = await content.generateThumbnail({
3301
- * strategy: 'headline-card',
3302
- * brandColor: '#1a56db',
3303
- * logoUrl: 'https://example.com/logo.png'
3304
- * });
3305
- * ```
3306
- *
3307
- * @example Static map thumbnail (requires metadata.latitude/longitude)
3308
- * ```typescript
3309
- * const thumbnail = await content.generateThumbnail({
3310
- * strategy: 'static-map',
3311
- * mapProvider: 'mapbox'
3312
- * });
3313
- * ```
3314
- *
3315
- * @example AI-generated thumbnail
3316
- * ```typescript
3317
- * const thumbnail = await content.generateThumbnail({
3318
- * strategy: 'ai-generate'
3319
- * });
3320
- * ```
3321
- */
3322
- async generateThumbnail(options) {
3323
- const image = await new ThumbnailGenerator(this, this.options).generate(options);
3324
- await this.setThumbnail(image);
3325
- return image;
3326
- }
3327
- };
3328
- __decorateClass([tenantId({ nullable: true })], Content.prototype, "tenantId", 2);
3329
- __decorateClass([field({ required: true })], Content.prototype, "name", 2);
3330
- __decorateClass([crossPackageRef("@happyvertical/smrt-assets:Asset")], Content.prototype, "thumbnailAssetId", 2);
3331
- Content = __decorateClass([TenantScoped({ mode: "optional" }), smrt({
3332
- tableStrategy: "sti",
3333
- api: {
3334
- include: [
3335
- "list",
3336
- "get",
3337
- "create",
3338
- "update",
3339
- "delete",
3340
- "getFactsState",
3341
- "syncFactsState",
3342
- "getFactAuditStateAction",
3343
- "repairFactAuditAction",
3344
- "repairFactEvidenceAction",
3345
- "recheckFactClaimsAction",
3346
- "updateFactEvidenceStatusAction",
3347
- "getGovernanceStateAction",
3348
- "listReviews",
3349
- "runReviewAction",
3350
- "listReviewProfilesAction",
3351
- "evaluateReviewProfileAction",
3352
- "getPublishedTransparencyAction",
3353
- "previewTransparencyAction",
3354
- "listCorrections",
3355
- "issueCorrectionAction",
3356
- "listVersions",
3357
- "mutateVersionAction"
3358
- ],
3359
- routes: {
3360
- getFactsState: {
3361
- method: "GET",
3362
- path: "facts"
3363
- },
3364
- syncFactsState: {
3365
- method: "PUT",
3366
- path: "facts"
3367
- },
3368
- getFactAuditStateAction: {
3369
- method: "GET",
3370
- path: "fact-audit"
3371
- },
3372
- repairFactAuditAction: {
3373
- method: "POST",
3374
- path: "fact-audit/repair"
3375
- },
3376
- repairFactEvidenceAction: {
3377
- method: "POST",
3378
- path: "fact-audit/evidence/repair"
3379
- },
3380
- recheckFactClaimsAction: {
3381
- method: "POST",
3382
- path: "fact-audit/claims/recheck"
3383
- },
3384
- updateFactEvidenceStatusAction: {
3385
- method: "PUT",
3386
- path: "fact-audit/evidence/status"
3387
- },
3388
- getGovernanceStateAction: {
3389
- method: "GET",
3390
- path: "governance"
3391
- },
3392
- listReviews: {
3393
- method: "GET",
3394
- path: "reviews"
3395
- },
3396
- runReviewAction: {
3397
- method: "POST",
3398
- path: "reviews"
3399
- },
3400
- listReviewProfilesAction: {
3401
- method: "GET",
3402
- path: "review-profiles"
3403
- },
3404
- evaluateReviewProfileAction: {
3405
- method: "GET",
3406
- path: "review-profiles/[profileKey]"
3407
- },
3408
- getPublishedTransparencyAction: {
3409
- method: "GET",
3410
- path: "transparency"
3411
- },
3412
- previewTransparencyAction: {
3413
- method: "GET",
3414
- path: "transparency/preview"
3415
- },
3416
- listCorrections: {
3417
- method: "GET",
3418
- path: "corrections"
3419
- },
3420
- issueCorrectionAction: {
3421
- method: "POST",
3422
- path: "corrections"
3423
- },
3424
- listVersions: {
3425
- method: "GET",
3426
- path: "versions"
3427
- },
3428
- mutateVersionAction: {
3429
- method: "POST",
3430
- path: "versions"
3431
- }
3432
- },
3433
- serializers: { item: {
3434
- importPath: "$lib/server/content-api-serializers",
3435
- exportName: "serializeContent"
3436
- } }
3437
- },
3438
- mcp: { include: [
3439
- "list",
3440
- "get",
3441
- "create",
3442
- "update"
3443
- ] },
3444
- cli: true,
3445
- indexes: [{
3446
- name: "contents_tenant_id_publish_date_idx",
3447
- columns: ["tenantId", "publish_date"]
3448
- }]
3449
- })], Content);
3450
- //#endregion
3451
- //#region src/content-query.ts
3452
- var CONTENT_QUERY_CLASS_NAME = "@happyvertical/smrt-content:Content";
3453
- var CONTENT_QUERY_IDENTITY_FIELD = "id";
3454
- var CONTENT_QUERY_DEFAULT_SORT = [{
3455
- field: "updated_at",
3456
- direction: "desc"
3457
- }, {
3458
- field: "id",
3459
- direction: "asc"
3460
- }];
3461
- var CONTENT_QUERY_DEFAULT_PAGE_LIMIT = 50;
3462
- var CONTENT_QUERY_MAX_PAGE_LIMIT = 200;
3463
- var CONTENT_QUERY_MAX_RESULT_BYTES = 1e6;
3464
- var CONTENT_QUERY_EXCLUDED_FIELD_IDS = ["body"];
3465
- var DATA_QUERY_MAX_STRING_LENGTH = 4096;
3466
- var DATA_QUERY_MAX_JSON_STRING_LENGTH = 65536;
3467
- var DATA_QUERY_MAX_JSON_CONTAINER_ITEMS = 1e3;
3468
- var DATA_QUERY_MAX_JSON_DEPTH = 16;
3469
- var DATA_QUERY_FORBIDDEN_JSON_KEYS = /* @__PURE__ */ new Set([
3470
- "__proto__",
3471
- "constructor",
3472
- "prototype"
3473
- ]);
3474
- var RESULT_ENVELOPE_RESERVE_BYTES = 4096;
3475
- var MIN_RESULT_ROW_BYTES = 512;
3476
- var CONTENT_QUERY_MIN_RESULT_BYTES = 4608;
3477
- function assertUsableResultBudget(schema) {
3478
- const budget = schema.maxResultBytes ?? 1e6;
3479
- if (budget >= 4608) return;
3480
- throw new Error(`Content query schema maxResultBytes must be at least ${CONTENT_QUERY_MIN_RESULT_BYTES} (${RESULT_ENVELOPE_RESERVE_BYTES} reserved for the result envelope, ${MIN_RESULT_ROW_BYTES} for rows); received ${budget}.`);
3481
- }
3482
- var MAX_CONTENT_QUERY_OR_BRANCHES = 128;
3483
- var encoder = new TextEncoder();
3484
- function assertContentQuerySchema(schema) {
3485
- normalizeDataQuerySchema(schema);
3486
- assertUsableResultBudget(schema);
3487
- }
3488
- function resolveContentTenantReadScope() {
3489
- if (!isTenancyEnabled()) return void 0;
3490
- if (isSuperAdminBypass() || isSystemContext()) return void 0;
3491
- return { tenantId: getCurrentTenant()?.tenantId ?? null };
3492
- }
3493
- function queryFail(message, code = "INVALID_DATA_QUERY") {
3494
- throw new DataQueryValidationError(message, code);
3495
- }
3496
- function isPlainRecord(value) {
3497
- if (!value || typeof value !== "object" || Array.isArray(value)) return false;
3498
- const prototype = Object.getPrototypeOf(value);
3499
- return prototype === Object.prototype || prototype === null;
3500
- }
3501
- function queryFieldType(type) {
3502
- switch (type) {
3503
- case "text":
3504
- case "foreignKey":
3505
- case "crossPackageRef": return "string";
3506
- case "integer":
3507
- case "decimal": return "number";
3508
- case "boolean": return "boolean";
3509
- case "datetime": return "datetime";
3510
- case "json": return "json";
3511
- default: return;
3512
- }
3513
- }
3514
- function filterOperatorsFor(type) {
3515
- switch (type) {
3516
- case "string": return [
3517
- "eq",
3518
- "ne",
3519
- "gt",
3520
- "gte",
3521
- "lt",
3522
- "lte",
3523
- "in",
3524
- "notIn",
3525
- "like"
3526
- ];
3527
- case "number":
3528
- case "datetime": return [
3529
- "eq",
3530
- "ne",
3531
- "gt",
3532
- "gte",
3533
- "lt",
3534
- "lte",
3535
- "in",
3536
- "notIn"
3537
- ];
3538
- case "boolean": return [
3539
- "eq",
3540
- "ne",
3541
- "in",
3542
- "notIn"
3543
- ];
3544
- case "json": return;
3545
- }
3546
- }
3547
- function meta(field) {
3548
- return isPlainRecord(field._meta) ? field._meta : {};
3549
- }
3550
- function isRestrictedField(field) {
3551
- const fieldMeta = meta(field);
3552
- return field.sensitive === true || fieldMeta.sensitive === true || typeof field.readPermission === "string" || typeof fieldMeta.readPermission === "string";
3553
- }
3554
- function isTransientField(field) {
3555
- return field.transient === true || meta(field).transient === true;
3556
- }
3557
- function isTenantField(name, field) {
3558
- const fieldMeta = meta(field);
3559
- return (isPlainRecord(field.__tenancy) ? field.__tenancy : isPlainRecord(fieldMeta.__tenancy) ? fieldMeta.__tenancy : void 0)?.isTenantIdField === true || name === "tenantId" || name === "tenant_id";
3560
- }
3561
- async function buildQuerySchemaForClass(qualifiedName, excluded) {
3562
- const registered = await ObjectRegistry.getAllFields(qualifiedName);
3563
- const fields = [];
3564
- for (const [name, field] of registered) {
3565
- if (name.startsWith("_")) continue;
3566
- if (excluded.has(name)) continue;
3567
- if (isRestrictedField(field)) continue;
3568
- if (isTransientField(field)) continue;
3569
- if (isTenantField(name, field)) continue;
3570
- const type = queryFieldType(field.type);
3571
- if (!type) continue;
3572
- const filterOperators = filterOperatorsFor(type);
3573
- fields.push({
3574
- id: name,
3575
- type,
3576
- projectable: true,
3577
- sortable: type !== "json",
3578
- facetable: name !== "id" && (type === "string" || type === "boolean" || type === "number"),
3579
- ...filterOperators ? { filterOperators } : {}
3580
- });
3581
- }
3582
- if (!fields.find((field) => field.id === "id")) throw new Error(`${qualifiedName} does not declare a queryable 'id' field`);
3583
- const declared = new Set(fields.map((field) => field.id));
3584
- const defaultSort = CONTENT_QUERY_DEFAULT_SORT.filter((term) => declared.has(term.field));
3585
- return {
3586
- version: 1,
3587
- identityField: "id",
3588
- fields,
3589
- defaultPageLimit: 50,
3590
- maxPageLimit: 200,
3591
- maxResultBytes: CONTENT_QUERY_MAX_RESULT_BYTES,
3592
- ...defaultSort.length > 0 ? { defaultSort } : {},
3593
- supports: {
3594
- cursorPagination: false,
3595
- consistency: false,
3596
- facets: true
3597
- }
3598
- };
3599
- }
3600
- var schemaCache = /* @__PURE__ */ new Map();
3601
- function buildDataQuerySchemaForClass(qualifiedName, options = {}) {
3602
- const excluded = [...new Set(options.exclude ?? [])].sort();
3603
- const key = `${qualifiedName}::${excluded.join(",")}`;
3604
- const cached = schemaCache.get(key);
3605
- if (cached) return cached;
3606
- const pending = buildQuerySchemaForClass(qualifiedName, new Set(excluded)).catch((cause) => {
3607
- schemaCache.delete(key);
3608
- throw cause;
3609
- });
3610
- schemaCache.set(key, pending);
3611
- return pending;
3612
- }
3613
- function buildContentQuerySchema() {
3614
- return buildDataQuerySchemaForClass(CONTENT_QUERY_CLASS_NAME, { exclude: CONTENT_QUERY_EXCLUDED_FIELD_IDS });
3615
- }
3616
- function clearContentQuerySchemaCache() {
3617
- schemaCache.clear();
3618
- }
3619
- function inverseOperator(operator) {
3620
- switch (operator) {
3621
- case "eq": return "ne";
3622
- case "ne": return "eq";
3623
- case "gt": return "lte";
3624
- case "gte": return "lt";
3625
- case "lt": return "gte";
3626
- case "lte": return "gt";
3627
- case "in": return "notIn";
3628
- case "notIn": return "in";
3629
- case "like": return queryFail("Content queries cannot negate a like predicate", "DATA_QUERY_UNSUPPORTED");
3630
- }
3631
- }
3632
- function conditionToDnf(field, operator, value, negated = false) {
3633
- const key = (suffix) => suffix ? `${field} ${suffix}` : field;
3634
- const single = (whereKey, whereValue) => [[{ [whereKey]: whereValue }]];
3635
- if (operator === "in") {
3636
- const values = value ?? [];
3637
- const nonNull = values.filter((entry) => entry !== null);
3638
- if (nonNull.length === 0) return single(field, null);
3639
- if (nonNull.length === values.length) return single(key("in"), nonNull);
3640
- return [[{ [field]: null }], [{ [key("in")]: nonNull }]];
3641
- }
3642
- if (operator === "notIn") {
3643
- const values = value ?? [];
3644
- if (values.length === 0) return queryFail("Content query notIn requires at least one value", "DATA_QUERY_UNSUPPORTED");
3645
- const inequalities = values.filter((entry) => entry !== null).map((entry) => ({ [key("!=")]: entry }));
3646
- if (values.some((entry) => entry === null)) return [[...inequalities, { [key("!=")]: null }]];
3647
- return [[{ [field]: null }], inequalities];
3648
- }
3649
- if (operator === "ne" && value !== null) return [[{ [field]: null }], [{ [key("!=")]: value }]];
3650
- const suffixes = {
3651
- eq: "",
3652
- ne: "!=",
3653
- gt: ">",
3654
- gte: ">=",
3655
- lt: "<",
3656
- lte: "<=",
3657
- like: "like"
3658
- };
3659
- if (negated && (operator === "gt" || operator === "gte" || operator === "lt" || operator === "lte")) return [[{ [field]: null }], [{ [key(suffixes[operator])]: value }]];
3660
- return single(key(suffixes[operator]), value);
3661
- }
3662
- function crossProduct(left, right) {
3663
- if (left.length * right.length > 128) return queryFail(`Content query filter expands beyond 128 OR branches`, "DATA_QUERY_UNSUPPORTED");
3664
- return left.flatMap((leftGroup) => right.map((rightGroup) => [...leftGroup, ...rightGroup]));
3665
- }
3666
- function filterToDnf(filter, declared, negate = false) {
3667
- if (filter.kind === "condition") {
3668
- if (!declared.has(filter.field)) return queryFail(`Content query filter field is not declared: ${filter.field}`, "DATA_QUERY_FILTER_NOT_ALLOWED");
3669
- return conditionToDnf(filter.field, negate ? inverseOperator(filter.operator) : filter.operator, filter.value, negate);
3670
- }
3671
- if (filter.kind === "not") return filterToDnf(filter.filter, declared, !negate);
3672
- if (filter.kind === "all" && !negate || filter.kind === "any" && negate) return filter.filters.reduce((combined, child) => crossProduct(combined, filterToDnf(child, declared, negate)), [[]]);
3673
- const branches = filter.filters.flatMap((child) => filterToDnf(child, declared, negate));
3674
- if (branches.length > 128) return queryFail(`Content query filter expands beyond 128 OR branches`, "DATA_QUERY_UNSUPPORTED");
3675
- return branches;
3676
- }
3677
- function normalizeScopeConditions(scope) {
3678
- if (scope === void 0) return [];
3679
- return (Array.isArray(scope) ? scope : [scope]).map((candidate) => {
3680
- if (!isPlainRecord(candidate) || Object.keys(candidate).length === 0) throw new Error("Content query scope conditions must be non-empty plain objects");
3681
- return { ...candidate };
3682
- });
3683
- }
3684
- var DENY_ALL_SCOPE_CONDITION = Object.freeze({ ["id"]: null });
3685
- function normalizeApplicationScope(scope) {
3686
- if (scope === void 0) return [];
3687
- const conditions = normalizeScopeConditions(scope);
3688
- return conditions.length > 0 ? conditions : [{ ...DENY_ALL_SCOPE_CONDITION }];
3689
- }
3690
- function mergeContentQueryScope(scope, callerWhere) {
3691
- const scopeConditions = normalizeApplicationScope(scope);
3692
- const merged = (callerWhere && callerWhere.length > 0 ? callerWhere : [[]]).map((branch) => [...scopeConditions, ...branch]);
3693
- if (merged.length === 1 && merged[0].length === 0) return void 0;
3694
- if (merged.some((branch) => branch.length === 0)) return queryFail("Content query filter produced an unbounded OR branch", "DATA_QUERY_UNSUPPORTED");
3695
- return merged;
3696
- }
3697
- var DATA_QUERY_MAX_WARNINGS = 100;
3698
- var DATA_QUERY_MAX_WARNING_LENGTH = 512;
3699
- function pushWarning(warnings, message) {
3700
- if (warnings.length >= 100) return;
3701
- const text = message.length > 512 ? `${message.slice(0, 511)}\u2026` : message;
3702
- if (text.length > 0) warnings.push(text);
3703
- }
3704
- function capString(value, limit = DATA_QUERY_MAX_STRING_LENGTH) {
3705
- if (value.length <= limit) return value;
3706
- const cut = value.slice(0, limit);
3707
- const last = cut.charCodeAt(cut.length - 1);
3708
- return last >= 55296 && last <= 56319 ? cut.slice(0, -1) : cut;
3709
- }
3710
- function boundJsonValue(value, descriptor, truncation, depth = 0, ancestors = /* @__PURE__ */ new Set()) {
3711
- const flag = () => {
3712
- truncation?.fields.add(descriptor.id);
3713
- };
3714
- if (value === null || value === void 0) return null;
3715
- if (typeof value === "boolean") return value;
3716
- if (typeof value === "string") {
3717
- if (value.length > 65536) {
3718
- flag();
3719
- return capString(value, DATA_QUERY_MAX_JSON_STRING_LENGTH);
3720
- }
3721
- return value;
3722
- }
3723
- if (typeof value === "number") {
3724
- if (!Number.isFinite(value)) {
3725
- flag();
3726
- return null;
3727
- }
3728
- return value;
3729
- }
3730
- if (typeof value === "bigint") {
3731
- if (!(value <= BigInt(Number.MAX_SAFE_INTEGER) && value >= BigInt(Number.MIN_SAFE_INTEGER))) {
3732
- flag();
3733
- return null;
3734
- }
3735
- return Number(value);
3736
- }
3737
- if (value instanceof Date) return Number.isNaN(value.getTime()) ? null : value.toISOString();
3738
- if (depth >= 16) {
3739
- flag();
3740
- return null;
3741
- }
3742
- if (Array.isArray(value)) {
3743
- if (ancestors.has(value)) {
3744
- flag();
3745
- return null;
3746
- }
3747
- ancestors.add(value);
3748
- try {
3749
- let entries = value;
3750
- if (entries.length > 1e3) {
3751
- flag();
3752
- entries = entries.slice(0, DATA_QUERY_MAX_JSON_CONTAINER_ITEMS);
3753
- }
3754
- return entries.map((entry) => boundJsonValue(entry, descriptor, truncation, depth + 1, ancestors));
3755
- } finally {
3756
- ancestors.delete(value);
3757
- }
3758
- }
3759
- if (!isPlainRecord(value)) {
3760
- flag();
3761
- return null;
3762
- }
3763
- if (ancestors.has(value)) {
3764
- flag();
3765
- return null;
3766
- }
3767
- ancestors.add(value);
3768
- try {
3769
- let keys = Object.keys(value);
3770
- if (keys.length > 1e3) {
3771
- flag();
3772
- keys = keys.slice(0, DATA_QUERY_MAX_JSON_CONTAINER_ITEMS);
3773
- }
3774
- const bounded = /* @__PURE__ */ Object.create(null);
3775
- for (const key of keys) {
3776
- if (key.length > 65536) {
3777
- flag();
3778
- continue;
3779
- }
3780
- if (DATA_QUERY_FORBIDDEN_JSON_KEYS.has(key)) {
3781
- flag();
3782
- continue;
3783
- }
3784
- Object.defineProperty(bounded, key, {
3785
- value: boundJsonValue(value[key], descriptor, truncation, depth + 1, ancestors),
3786
- enumerable: true,
3787
- configurable: true,
3788
- writable: true
3789
- });
3790
- }
3791
- return bounded;
3792
- } finally {
3793
- ancestors.delete(value);
3794
- }
3795
- }
3796
- function toDeclaredValue(value, descriptor, truncation) {
3797
- if (value === void 0) return null;
3798
- if (value instanceof Date) return Number.isNaN(value.getTime()) ? null : value.toISOString();
3799
- if (descriptor.type === "json") return boundJsonValue(value, descriptor, truncation);
3800
- if (typeof value === "string" && value.length > 4096) {
3801
- truncation?.fields.add(descriptor.id);
3802
- return capString(value);
3803
- }
3804
- if (typeof value === "bigint") {
3805
- if (value > BigInt(Number.MAX_SAFE_INTEGER) || value < BigInt(Number.MIN_SAFE_INTEGER)) return queryFail(`Content query value for ${descriptor.id} exceeds the safe integer range`, "DATA_QUERY_RESULT_INVALID");
3806
- return Number(value);
3807
- }
3808
- if (descriptor.type === "boolean" && typeof value === "number") return value !== 0;
3809
- return value;
3810
- }
3811
- function jsonByteLength(value) {
3812
- return encoder.encode(JSON.stringify(value) ?? "null").byteLength;
3813
- }
3814
- function capStringBytes(value, maxBytes) {
3815
- if (maxBytes <= 0) return "";
3816
- const totalBytes = encoder.encode(value).byteLength;
3817
- if (totalBytes <= maxBytes) return value;
3818
- if (totalBytes === value.length) return value.slice(0, maxBytes);
3819
- let used = 0;
3820
- let end = 0;
3821
- for (const character of value) {
3822
- const point = character.codePointAt(0) ?? 0;
3823
- const cost = point < 128 ? 1 : point < 2048 ? 2 : point < 65536 ? 3 : 4;
3824
- if (used + cost > maxBytes) break;
3825
- used += cost;
3826
- end += character.length;
3827
- }
3828
- return value.slice(0, end);
3829
- }
3830
- function reductionFor(field, value, identityField, descriptors) {
3831
- if (field === identityField || value === null) return "none";
3832
- const type = descriptors.get(field)?.type;
3833
- if (type === "json") return "null";
3834
- if (type === "datetime") return "null";
3835
- if (typeof value === "string" && value.length > 0) return "truncate";
3836
- return "none";
3837
- }
3838
- var REDUCED_VALUE_BYTES = {
3839
- truncate: 2,
3840
- null: 4,
3841
- none: 0
3842
- };
3843
- function measureRow(row, descriptors, identityField) {
3844
- const entries = Object.entries(row);
3845
- const fields = entries.map(([field, value]) => {
3846
- const declared = reductionFor(field, value, identityField, descriptors);
3847
- const valueBytes = jsonByteLength(value);
3848
- const reduction = declared === "none" || REDUCED_VALUE_BYTES[declared] < valueBytes ? declared : "none";
3849
- return {
3850
- field,
3851
- keyBytes: jsonByteLength(field),
3852
- valueBytes,
3853
- reduction,
3854
- floorBytes: reduction === "none" ? valueBytes : REDUCED_VALUE_BYTES[reduction]
3855
- };
3856
- });
3857
- const structural = entries.length === 0 ? 3 : entries.length + 2;
3858
- const overhead = fields.reduce((sum, entry) => sum + entry.keyBytes + 1, structural);
3859
- return {
3860
- fields,
3861
- structural,
3862
- cost: fields.reduce((sum, entry) => sum + entry.valueBytes, overhead),
3863
- floor: fields.reduce((sum, entry) => sum + entry.floorBytes, overhead)
3864
- };
3865
- }
3866
- function waterFillCap(sizes, available, floorBytes) {
3867
- if (sizes.length === 0) return available >= 0 ? Number.MAX_SAFE_INTEGER : void 0;
3868
- if (available < sizes.length * floorBytes) return void 0;
3869
- const sorted = [...sizes].sort((left, right) => left - right);
3870
- let prefix = 0;
3871
- for (let index = 0; index < sorted.length; index += 1) {
3872
- const remaining = sorted.length - index;
3873
- if (prefix + remaining * sorted[index] > available) return Math.max(floorBytes, Math.floor((available - prefix) / remaining));
3874
- prefix += sorted[index];
3875
- }
3876
- return Number.MAX_SAFE_INTEGER;
3877
- }
3878
- function shrinkRowToBytes(row, allowance, measured, truncation) {
3879
- if (measured.floor > allowance) return void 0;
3880
- const nulled = /* @__PURE__ */ new Set();
3881
- let cap;
3882
- for (;;) {
3883
- const kept = measured.fields.filter((entry) => entry.reduction !== "truncate" && !nulled.has(entry.field));
3884
- const truncatable = measured.fields.filter((entry) => entry.reduction === "truncate");
3885
- const fixed = kept.reduce((sum, entry) => sum + entry.valueBytes, 0);
3886
- const nulledBytes = REDUCED_VALUE_BYTES.null * nulled.size;
3887
- const available = allowance - measured.fields.reduce((sum, entry) => sum + entry.keyBytes + 1, measured.structural) - fixed - nulledBytes;
3888
- cap = waterFillCap(truncatable.map((entry) => entry.valueBytes), available, REDUCED_VALUE_BYTES.truncate);
3889
- if (cap !== void 0) break;
3890
- const biggestNullable = measured.fields.filter((entry) => entry.reduction === "null" && !nulled.has(entry.field)).sort((left, right) => right.valueBytes - left.valueBytes)[0];
3891
- if (biggestNullable === void 0) return void 0;
3892
- nulled.add(biggestNullable.field);
3893
- }
3894
- if (cap === void 0) return void 0;
3895
- const shrunk = { ...row };
3896
- for (const entry of measured.fields) {
3897
- if (nulled.has(entry.field)) {
3898
- shrunk[entry.field] = null;
3899
- truncation.fields.add(entry.field);
3900
- continue;
3901
- }
3902
- if (entry.reduction !== "truncate" || entry.valueBytes <= cap) continue;
3903
- const original = shrunk[entry.field];
3904
- let content = capStringBytes(original, cap - 2);
3905
- let guard = 0;
3906
- while (jsonByteLength(content) > cap && content.length > 0 && guard < 8) {
3907
- guard += 1;
3908
- const overshoot = jsonByteLength(content) - cap;
3909
- content = capStringBytes(content, Math.max(0, encoder.encode(content).byteLength - overshoot));
3910
- }
3911
- shrunk[entry.field] = content;
3912
- truncation.fields.add(entry.field);
3913
- }
3914
- return shrunk;
3915
- }
3916
- function allocateRowBytes(floors, costs, budget) {
3917
- const allowances = [...floors];
3918
- const seated = floors.reduce((sum, floor) => sum + floor, 0);
3919
- if (seated > budget) return allowances;
3920
- const appetites = costs.map((cost, index) => Math.max(0, cost - floors[index]));
3921
- const order = floors.map((_, index) => index).sort((left2, right) => appetites[left2] - appetites[right]);
3922
- let surplus = budget - seated;
3923
- let left = floors.length;
3924
- for (const index of order) {
3925
- const granted = Math.min(appetites[index], Math.floor(surplus / left));
3926
- allowances[index] += granted;
3927
- surplus -= granted;
3928
- left -= 1;
3929
- }
3930
- return allowances;
3931
- }
3932
- function boundRowBytes(rows, maxResultBytes, descriptors, identityField, truncation) {
3933
- const budget = Math.max(0, (maxResultBytes || 1e6) - RESULT_ENVELOPE_RESERVE_BYTES);
3934
- const framing = rows.length > 0 ? 1 : 2;
3935
- const measured = rows.map((row) => measureRow(row, descriptors, identityField));
3936
- if (measured.reduce((sum, row) => sum + row.cost, framing) <= budget) return {
3937
- rows,
3938
- truncated: false
3939
- };
3940
- if (measured.reduce((sum, row) => sum + row.floor, framing) > budget) return queryFail("Content query cannot fit its rows inside the maximum result bytes; request fewer fields or a smaller page.", "DATA_QUERY_RESULT_TOO_LARGE");
3941
- const allowances = allocateRowBytes(measured.map((row) => row.floor), measured.map((row) => row.cost), budget - framing);
3942
- return {
3943
- rows: rows.map((row, index) => {
3944
- if (measured[index].cost <= allowances[index]) return row;
3945
- const shrunk = shrinkRowToBytes(row, allowances[index], measured[index], truncation);
3946
- if (shrunk === void 0) return queryFail("Content query cannot fit a row inside its maximum result bytes; request fewer fields or a smaller page.", "DATA_QUERY_RESULT_TOO_LARGE");
3947
- return shrunk;
3948
- }),
3949
- truncated: true
3950
- };
3951
- }
3952
- function orderByTerms(sort) {
3953
- if (!sort || sort.length === 0) return void 0;
3954
- return sort.map((term) => `${term.field} ${term.direction.toUpperCase()}`);
3955
- }
3956
- async function executeContentQuery(collection, rawRequest, options = {}) {
3957
- const schema = options.schema ?? await buildContentQuerySchema();
3958
- assertUsableResultBudget(schema);
3959
- const request = normalizeDataQueryRequest(rawRequest, schema);
3960
- const queryFingerprint = createDataQueryFingerprint(request, schema);
3961
- const descriptors = new Map(schema.fields.map((field) => [field.id, field]));
3962
- const declared = new Set(descriptors.keys());
3963
- const callerWhere = request.filter ? filterToDnf(request.filter, declared) : void 0;
3964
- const scopeConditions = [...normalizeScopeConditions(resolveContentTenantReadScope()), ...normalizeApplicationScope(options.scope)];
3965
- const where = mergeContentQueryScope(scopeConditions.length > 0 ? scopeConditions : void 0, callerWhere);
3966
- const countOptions = where === void 0 ? void 0 : { where };
3967
- const warnings = [];
3968
- let truncated = false;
3969
- let facets;
3970
- if (request.mode === "rows") {
3971
- const projection = request.projection ?? [schema.identityField];
3972
- const offset = request.page?.kind === "offset" ? request.page.offset : 0;
3973
- const limit = request.page?.limit ?? schema.defaultPageLimit ?? 50;
3974
- const orderBy = orderByTerms(request.sort);
3975
- const listed = await collection.list({
3976
- select: projection,
3977
- offset,
3978
- limit,
3979
- ...orderBy ? { orderBy: orderBy.length === 1 ? orderBy[0] : orderBy } : {},
3980
- ...where === void 0 ? {} : { where }
3981
- });
3982
- const truncation = { fields: /* @__PURE__ */ new Set() };
3983
- const bounded = boundRowBytes(listed.map((row) => {
3984
- const out = {};
3985
- for (const field of projection) {
3986
- const descriptor = descriptors.get(field);
3987
- if (!descriptor) return queryFail(`Content query returned an undeclared field: ${field}`, "DATA_QUERY_RESULT_NOT_ALLOWED");
3988
- out[field] = toDeclaredValue(row[field], descriptor, truncation);
3989
- }
3990
- return out;
3991
- }), schema.maxResultBytes ?? 1e6, descriptors, schema.identityField, truncation);
3992
- const rows = bounded.rows;
3993
- truncated = bounded.truncated || truncation.fields.size > 0;
3994
- if (bounded.truncated) pushWarning(warnings, "Content query shortened values to fit its maximum result bytes; request fewer fields or a smaller page.");
3995
- if (truncation.fields.size > 0) pushWarning(warnings, `Content query shortened over-long values in: ${[...truncation.fields].sort().join(", ")}.`);
3996
- const total2 = await collection.count(countOptions);
3997
- const page = {
3998
- kind: "offset",
3999
- offset,
4000
- limit,
4001
- hasMore: offset + rows.length < total2
4002
- };
4003
- return normalizeDataQueryResult({
4004
- version: 1,
4005
- requestId: request.requestId,
4006
- queryFingerprint,
4007
- identityField: schema.identityField,
4008
- rows,
4009
- page,
4010
- total: {
4011
- kind: "exact",
4012
- value: total2
4013
- },
4014
- freshness: {
4015
- state: "fresh",
4016
- asOf: (/* @__PURE__ */ new Date()).toISOString()
4017
- },
4018
- warnings,
4019
- truncated
4020
- }, request, schema);
4021
- }
4022
- const total = await collection.count(countOptions);
4023
- if (request.mode === "facets") {
4024
- const requested = request.facets ?? [];
4025
- const sourceFacets = await collection.facets({
4026
- fields: requested.map((facet) => ({
4027
- field: facet.field,
4028
- limit: facet.limit
4029
- })),
4030
- ...where === void 0 ? {} : { where }
4031
- });
4032
- const byField = new Map(sourceFacets.map((facet) => [facet.field, facet]));
4033
- const facetTruncation = { fields: /* @__PURE__ */ new Set() };
4034
- let facetBudget = Math.max(0, (schema.maxResultBytes ?? 1e6) - RESULT_ENVELOPE_RESERVE_BYTES);
4035
- let facetBudgetExhausted = false;
4036
- facets = requested.map((facet) => {
4037
- const descriptor = descriptors.get(facet.field);
4038
- if (!descriptor) return queryFail(`Content query returned an undeclared facet: ${facet.field}`, "DATA_QUERY_RESULT_NOT_ALLOWED");
4039
- const values = byField.get(facet.field)?.values ?? [];
4040
- facetBudget -= jsonByteLength(facet.field) + 48;
4041
- const kept = [];
4042
- let boundedOut = false;
4043
- for (const entry of values.slice(0, facet.limit)) {
4044
- const value = toDeclaredValue(entry.value, descriptor, facetTruncation);
4045
- const cost = jsonByteLength({
4046
- value,
4047
- count: entry.count
4048
- }) + 1;
4049
- if (cost > facetBudget) {
4050
- boundedOut = true;
4051
- facetBudgetExhausted = true;
4052
- break;
4053
- }
4054
- facetBudget -= cost;
4055
- kept.push({
4056
- value,
4057
- count: entry.count
4058
- });
4059
- }
4060
- return {
4061
- field: facet.field,
4062
- values: kept,
4063
- truncated: boundedOut || values.length >= facet.limit
4064
- };
4065
- });
4066
- if (facetTruncation.fields.size > 0) pushWarning(warnings, `Content query shortened over-long values in: ${[...facetTruncation.fields].sort().join(", ")}.`);
4067
- if (facetBudgetExhausted) pushWarning(warnings, "Content query facets were truncated to fit their maximum result bytes; request fewer facets or a smaller facet limit.");
4068
- truncated = facets.some((facet) => facet.truncated) || facetTruncation.fields.size > 0;
4069
- }
4070
- return normalizeDataQueryResult({
4071
- version: 1,
4072
- requestId: request.requestId,
4073
- queryFingerprint,
4074
- identityField: schema.identityField,
4075
- rows: [],
4076
- total: {
4077
- kind: "exact",
4078
- value: total
4079
- },
4080
- ...facets === void 0 ? {} : { facets },
4081
- freshness: {
4082
- state: "fresh",
4083
- asOf: (/* @__PURE__ */ new Date()).toISOString()
4084
- },
4085
- warnings,
4086
- truncated
4087
- }, request, schema);
4088
- }
4089
- //#endregion
4090
- export { parseContentReviewResponse as $, normalizeContentTransparency as A, getAcceptedContentReviewStatuses as B, resolveContentTenantReadScope as C, serializeFact as D, serializeContent as E, smrtContentReviewPrompt as F, getContentReviewProfile as G, getContentReviewKind as H, smrtContentThumbnailAIGeneratePrompt as I, getEffectiveContentGovernanceConfig as J, getContentReviewProfileKeys as K, buildContentGovernanceAssignmentKey as L, ContentReference as M, promptMessageOptions as N, getQueryRows as O, smrtContentApplyCorrectionPrompt as P, loadPersistedContentGovernanceDefinitions as Q, buildContentReviewPrompt as R, mergeContentQueryScope as S, ThumbnailGenerator as T, getContentReviewPolicies as U, getContentGovernanceConfig as V, getContentReviewPolicy as W, hasStaticContentGovernancePolicy as X, getFallbackPolicyKind as Y, hasStaticContentGovernanceProfile as Z, assertContentQuerySchema as _, CONTENT_QUERY_IDENTITY_FIELD as a, isAssetAssociable as at, clearContentQuerySchemaCache as b, CONTENT_QUERY_MIN_RESULT_BYTES as c, DATA_QUERY_MAX_JSON_DEPTH as d, resetContentGovernanceConfig as et, DATA_QUERY_MAX_JSON_STRING_LENGTH as f, MAX_CONTENT_QUERY_OR_BRANCHES as g, DATA_QUERY_MAX_WARNING_LENGTH as h, CONTENT_QUERY_EXCLUDED_FIELD_IDS as i, ContentAsset as it, ContentReferences as j, isMissingTableError as k, DATA_QUERY_FORBIDDEN_JSON_KEYS as l, DATA_QUERY_MAX_WARNINGS as m, CONTENT_QUERY_DEFAULT_PAGE_LIMIT as n, resolveEffectiveContentGovernance as nt, CONTENT_QUERY_MAX_PAGE_LIMIT as o, isMetadataAccessor as ot, DATA_QUERY_MAX_STRING_LENGTH as p, getContentReviewRequirements as q, CONTENT_QUERY_DEFAULT_SORT as r, ContentAssetCollection as rt, CONTENT_QUERY_MAX_RESULT_BYTES as s, CONTENT_QUERY_CLASS_NAME as t, resolveConfiguredContentGovernance as tt, DATA_QUERY_MAX_JSON_CONTAINER_ITEMS as u, buildContentQuerySchema as v, Content as w, executeContentQuery as x, buildDataQuerySchemaForClass as y, configureContentGovernance as z };
4091
-
4092
- //# sourceMappingURL=content-query-CmjfYsO9.js.map