@weatherboard/cms 0.9.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/fact-guard.ts"],
4
+ "sourcesContent": ["/** Registration seam for the later manifest guard; historical exclusions require evidence. */\nexport const FACT_SURFACE_MANIFEST_VERSION = 1 as const;\nexport type FactSurfaceManifest = {\n facts: readonly { key: string; literals: readonly string[] }[];\n surfaces: readonly { id: string; path: string; semantics: \"current\" | \"historical\" }[];\n exclusions: readonly { path: string; literal: string; asOf: string; evidence: string }[];\n};\n"],
5
+ "mappings": "AACO,IAAMA,EAAgC",
6
+ "names": ["FACT_SURFACE_MANIFEST_VERSION"]
7
+ }
package/dist/facts.cjs ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";var d=Object.defineProperty;var x=Object.getOwnPropertyDescriptor;var R=Object.getOwnPropertyNames;var A=Object.prototype.hasOwnProperty;var S=(e,t)=>{for(var n in t)d(e,n,{get:t[n],enumerable:!0})},w=(e,t,n,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let a of R(t))!A.call(e,a)&&a!==n&&d(e,a,{get:()=>t[a],enumerable:!(r=x(t,a))||r.enumerable});return e};var h=e=>w(d({},"__esModule",{value:!0}),e);var k={};S(k,{FACT_ALIASES:()=>g,FACT_DISPLAY_RULES:()=>I,FACT_EXPIRY_MS:()=>m,FACT_KEY:()=>y,FACT_TYPES:()=>V,assertFactKey:()=>p,businessFactId:()=>D,canonicalFactJson:()=>l,expandFactPlaceholders:()=>P,formatFact:()=>v,hashFactRevision:()=>_,parseFactDisplayRule:()=>b,parseFactValue:()=>c,parseStoredFactValue:()=>O,storeFactValue:()=>j});module.exports=h(k);var V=["integer","decimal","boolean","date","string","enum","reference"],I=["identity/v1","floorHundredsPlus/v1"],y=/^[a-z][a-zA-Z0-9]*(?:\.[a-zA-Z][a-zA-Z0-9]*)*$/,g={pubCount:"coverage.pubCount"},m={computed:72*36e5,operational:30*864e5,technical:90*864e5};function O(e){let t=f(e),n=t.type==="integer"?t.numberValue:t.type==="boolean"?t.booleanValue:t.type==="reference"?{documentId:t.documentId,documentRevision:t.documentRevision}:t.textValue;return c({type:t.type,value:n,allowedValues:t.allowedValues})}function j(e){let t=c(e);return t.type==="integer"?{type:t.type,numberValue:t.value}:t.type==="boolean"?{type:t.type,booleanValue:t.value}:t.type==="reference"?{type:t.type,...t.value}:t.type==="enum"?{type:t.type,textValue:t.value,allowedValues:t.allowedValues}:{type:t.type,textValue:t.value}}function s(){throw new Error("Invalid business fact contract")}function f(e){return!e||typeof e!="object"||Array.isArray(e)?s():e}function o(e){return typeof e=="string"&&e.trim()!==""?e:s()}function p(e){(e.length>48||!y.test(e))&&s()}function D(e){return p(e),"businessFact-"+Array.from(new TextEncoder().encode(e),t=>t.toString(16).padStart(2,"0")).join("")}function c(e){let t=f(e),n=t.value;switch(t.type){case"integer":return Number.isSafeInteger(n)?{type:"integer",value:n}:s();case"decimal":return typeof n=="string"&&/^(?:0|-?[1-9]\d*)(?:\.\d*[1-9])?$|^-0\.\d*[1-9]$/.test(n)?{type:"decimal",value:n}:s();case"boolean":return typeof n=="boolean"?{type:"boolean",value:n}:s();case"string":return typeof n=="string"?{type:"string",value:n}:s();case"date":return typeof n=="string"&&/^\d{4}-\d{2}-\d{2}$/.test(n)&&!Number.isNaN(Date.parse(n))&&new Date(n).toISOString().slice(0,10)===n?{type:"date",value:n}:s();case"enum":{let r=t.allowedValues;return!Array.isArray(r)||!r.length||!r.every(a=>typeof a=="string"&&a!=="")||new Set(r).size!==r.length||!r.includes(n)?s():{type:"enum",value:o(n),allowedValues:[...r].sort()}}case"reference":{let r=f(n);return{type:"reference",value:{documentId:o(r.documentId),documentRevision:o(r.documentRevision)}}}default:return s()}}function b(e){return e!=="identity/v1"&&e!=="floorHundredsPlus/v1"?s():e}function v(e,t){let n=c(e);return b(t)==="floorHundredsPlus/v1"?n.type!=="integer"||n.value<0?s():n.value<100?String(n.value):`${(Math.floor(n.value/100)*100).toLocaleString("en-GB")}+`:n.type==="reference"?n.value.documentId:String(n.value)}function P(e,t,n){return["htmlText","htmlAttribute","json"].includes(n)?e.replace(/\{([^{}]*)\}/g,(r,a)=>{p(a);let u=Object.hasOwn(g,a)?g[a]:a;if(!Object.hasOwn(t,u))throw new Error(`Unknown fact placeholder: ${a}`);let i=t[u];return n==="json"?JSON.stringify(i).slice(1,-1).replace(/</g,"\\u003c").replace(/>/g,"\\u003e").replace(/&/g,"\\u0026").replace(/\u2028/g,"\\u2028").replace(/\u2029/g,"\\u2029"):i.replace(/[&<>"']/g,F=>({"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"})[F])}):s()}function l(e){return e===null||typeof e=="boolean"||typeof e=="string"||typeof e=="number"&&Number.isFinite(e)?JSON.stringify(e):Array.isArray(e)?`[${Array.from(e,l).join(",")}]`:typeof e!="object"||e===null||Object.getPrototypeOf(e)!==Object.prototype?s():`{${Object.entries(e).sort(([t],[n])=>t<n?-1:t>n?1:0).map(([t,n])=>`${JSON.stringify(t)}:${l(n)}`).join(",")}}`}async function _(e){let t=e.fact;p(t.key);let n=c(t.publicValue);v(n,t.displayRule),(!Number.isSafeInteger(e.revision)||e.revision<1||e.baseRevision!==null&&(!Number.isSafeInteger(e.baseRevision)||e.baseRevision<1||e.baseRevision>=e.revision))&&s(),o(e.projectId),o(t.accountableOwner),o(t.source.definition),o(t.source.version),(!["computed","observed","attested"].includes(t.source.kind)||!Object.hasOwn(m,t.freshness)||typeof t.optional!="boolean"||t.unit!==null&&typeof t.unit!="string")&&s(),t.timezone!==null&&new Intl.DateTimeFormat("en-GB",{timeZone:o(t.timezone)});let r=i=>((!/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{3})?Z$/.test(i)||!Number.isFinite(Date.parse(i))||new Date(i).toISOString()!==i.replace(/(?<=:\d{2})Z$/,".000Z"))&&s(),Date.parse(i));(r(e.expiresAt)<=r(e.effectiveAt)||r(e.evidence.expiresAt)<=r(e.evidence.observedAt)||!/^[0-9a-f]{64}$/.test(e.evidence.digest)||typeof e.evidence.complete!="boolean")&&s(),o(e.evidence.reference),o(e.evidence.runId);for(let i of t.surfaces)o(i.id),i.semantics==="historical"?c({type:"date",value:i.asOf}):(i.semantics!=="current"||i.asOf!==null)&&s();let a={projectId:e.projectId,revision:e.revision,baseRevision:e.baseRevision,fact:{key:t.key,publicValue:n,unit:t.unit,timezone:t.timezone,displayRule:t.displayRule,source:{kind:t.source.kind,definition:t.source.definition,version:t.source.version},accountableOwner:t.accountableOwner,freshness:t.freshness,optional:t.optional,surfaces:t.surfaces.map(i=>({id:i.id,semantics:i.semantics,asOf:i.asOf}))},evidence:{reference:e.evidence.reference,digest:e.evidence.digest,complete:e.evidence.complete,runId:e.evidence.runId,observedAt:new Date(r(e.evidence.observedAt)).toISOString(),expiresAt:new Date(r(e.evidence.expiresAt)).toISOString()},effectiveAt:new Date(r(e.effectiveAt)).toISOString(),expiresAt:new Date(r(e.expiresAt)).toISOString()},u=await crypto.subtle.digest("SHA-256",new TextEncoder().encode(l(a)));return Array.from(new Uint8Array(u),i=>i.toString(16).padStart(2,"0")).join("")}0&&(module.exports={FACT_ALIASES,FACT_DISPLAY_RULES,FACT_EXPIRY_MS,FACT_KEY,FACT_TYPES,assertFactKey,businessFactId,canonicalFactJson,expandFactPlaceholders,formatFact,hashFactRevision,parseFactDisplayRule,parseFactValue,parseStoredFactValue,storeFactValue});
2
+ //# sourceMappingURL=facts.cjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/facts.ts", "../src/contracts/facts.ts"],
4
+ "sourcesContent": ["// Dedicated entry reserved for the published snapshot reader; no runtime transport in this foundation.\nexport * from \"./contracts/facts.js\";\n", "/** Public contracts only. Evidence and approval identities never enter the CMS document. */\nexport const FACT_TYPES = [\"integer\", \"decimal\", \"boolean\", \"date\", \"string\", \"enum\", \"reference\"] as const;\nexport const FACT_DISPLAY_RULES = [\"identity/v1\", \"floorHundredsPlus/v1\"] as const;\nexport type FactDisplayRule = typeof FACT_DISPLAY_RULES[number];\nexport const FACT_KEY = /^[a-z][a-zA-Z0-9]*(?:\\.[a-zA-Z][a-zA-Z0-9]*)*$/;\nexport const FACT_ALIASES: Readonly<Record<string, string>> = { pubCount: \"coverage.pubCount\" };\nexport type FactValue =\n | { type: \"integer\"; value: number }\n // Decimal strings avoid binary floating-point loss; canonical form has no trailing fractional zeroes.\n | { type: \"decimal\"; value: string }\n | { type: \"boolean\"; value: boolean }\n | { type: \"date\" | \"string\"; value: string }\n | { type: \"enum\"; value: string; allowedValues: readonly string[] }\n | { type: \"reference\"; value: { documentId: string; documentRevision: string } };\nexport type FactSource = { kind: \"computed\" | \"observed\" | \"attested\"; definition: string; version: string };\nexport type BusinessFact = {\n key: string; publicValue: FactValue; unit: string | null; timezone: string | null;\n displayRule: FactDisplayRule; source: FactSource; accountableOwner: string;\n freshness: \"computed\" | \"operational\" | \"technical\"; optional: boolean;\n surfaces: readonly { id: string; semantics: \"current\" | \"historical\"; asOf: string | null }[];\n};\nexport const FACT_EXPIRY_MS = { computed: 72 * 3_600_000, operational: 30 * 86_400_000, technical: 90 * 86_400_000 } as const;\nexport type FactEvidence = { reference: string; digest: string; observedAt: string; expiresAt: string; complete: boolean; runId: string };\nexport type FactRevision = {\n projectId: string; revision: number; baseRevision: number | null; fact: BusinessFact;\n evidence: FactEvidence; effectiveAt: string; expiresAt: string;\n};\nexport type ApprovedFactRevision = FactRevision & {\n hash: string; approvedAt: string;\n approval: { kind: \"signer\"; signerId: string } | { kind: \"policy\"; policyVersion: string };\n};\nexport type FactPublicationReceipt = {\n intentId: string; projectId: string; revision: number; hash: string;\n destination: { projectId: string; dataset: string }; expectedDocumentRevision: string | null;\n cms: { transactionId: string; documentRevision: string; readBackHash: string; at: string } | null;\n invalidation: { deliveryKey: string; target: string; type: \"businessFact\"; id: string; at: string } | null;\n render: { url: string; deploymentId: string; revision: number; hash: string; at: string } | null;\n};\nexport type PublicBusinessFact = Pick<BusinessFact, \"key\" | \"publicValue\" | \"unit\" | \"timezone\" | \"displayRule\"> & {\n _type: \"businessFact\"; _id: string; approvedRevision: number; approvedHash: string;\n effectiveAt: string; expiresAt: string; provenanceSummary: string;\n};\n/** A request supplies one snapshot to every surface. Missing and unavailable are distinct from an empty snapshot. */\nexport type FactSnapshot = Readonly<Record<string, PublicBusinessFact>>;\nexport type FactReadResult = { status: \"available\"; snapshot: FactSnapshot } | { status: \"unavailable\"; reason: string };\nexport type FactReader = () => Promise<FactReadResult>;\nexport type FactPlaceholderContext = \"htmlText\" | \"htmlAttribute\" | \"json\";\n/** Stored Sanity projection: scalar unions use named slots, never private revision fields. */\nexport type StoredFactValue = { type: FactValue[\"type\"]; numberValue?: number; textValue?: string;\n booleanValue?: boolean; allowedValues?: readonly string[]; documentId?: string; documentRevision?: string };\nexport function parseStoredFactValue(input: unknown): FactValue {\n const entry = record(input);\n const value = entry.type === \"integer\" ? entry.numberValue : entry.type === \"boolean\" ? entry.booleanValue\n : entry.type === \"reference\" ? { documentId: entry.documentId, documentRevision: entry.documentRevision } : entry.textValue;\n return parseFactValue({ type: entry.type, value, allowedValues: entry.allowedValues });\n}\nexport function storeFactValue(input: FactValue): StoredFactValue {\n const entry = parseFactValue(input);\n if (entry.type === \"integer\") return { type: entry.type, numberValue: entry.value };\n if (entry.type === \"boolean\") return { type: entry.type, booleanValue: entry.value };\n if (entry.type === \"reference\") return { type: entry.type, ...entry.value };\n return entry.type === \"enum\" ? { type: entry.type, textValue: entry.value, allowedValues: entry.allowedValues }\n : { type: entry.type, textValue: entry.value };\n}\nexport type StoredBusinessFact = Omit<PublicBusinessFact, \"publicValue\"> & { publicValue: StoredFactValue };\n\nfunction invalid(): never { throw new Error(\"Invalid business fact contract\"); }\nfunction record(value: unknown): Record<string, unknown> {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return invalid();\n return value as Record<string, unknown>;\n}\nfunction text(value: unknown): string { return typeof value === \"string\" && value.trim() !== \"\" ? value : invalid(); }\nexport function assertFactKey(key: string): void {\n if (key.length > 48 || !FACT_KEY.test(key)) invalid();\n}\nexport function businessFactId(key: string): string {\n assertFactKey(key);\n // Dataset-local, injective encoding; never a draft ID or a key containing a path separator.\n return \"businessFact-\" + Array.from(new TextEncoder().encode(key), (byte) => byte.toString(16).padStart(2, \"0\")).join(\"\");\n}\nexport function parseFactValue(input: unknown): FactValue {\n const entry = record(input), value = entry.value;\n switch (entry.type) {\n case \"integer\": return Number.isSafeInteger(value) ? { type: \"integer\", value: value as number } : invalid();\n case \"decimal\": return typeof value === \"string\" && /^(?:0|-?[1-9]\\d*)(?:\\.\\d*[1-9])?$|^-0\\.\\d*[1-9]$/.test(value)\n ? { type: \"decimal\", value } : invalid();\n case \"boolean\": return typeof value === \"boolean\" ? { type: \"boolean\", value } : invalid();\n case \"string\": return typeof value === \"string\" ? { type: \"string\", value } : invalid();\n case \"date\": return typeof value === \"string\" && /^\\d{4}-\\d{2}-\\d{2}$/.test(value)\n && !Number.isNaN(Date.parse(value)) && new Date(value).toISOString().slice(0, 10) === value ? { type: \"date\", value } : invalid();\n case \"enum\": {\n const allowed = entry.allowedValues;\n if (!Array.isArray(allowed) || !allowed.length || !allowed.every((item) => typeof item === \"string\" && item !== \"\")\n || new Set(allowed).size !== allowed.length || !allowed.includes(value)) return invalid();\n return { type: \"enum\", value: text(value), allowedValues: [...allowed].sort() as string[] };\n }\n case \"reference\": {\n const ref = record(value);\n return { type: \"reference\", value: { documentId: text(ref.documentId), documentRevision: text(ref.documentRevision) } };\n }\n default: return invalid();\n }\n}\nexport function parseFactDisplayRule(input: unknown): FactDisplayRule {\n if (input !== \"identity/v1\" && input !== \"floorHundredsPlus/v1\") return invalid();\n return input;\n}\nexport function formatFact(input: FactValue, rule: FactDisplayRule): string {\n const value = parseFactValue(input);\n if (parseFactDisplayRule(rule) === \"floorHundredsPlus/v1\") {\n if (value.type !== \"integer\" || value.value < 0) return invalid();\n return value.value < 100 ? String(value.value) : `${(Math.floor(value.value / 100) * 100).toLocaleString(\"en-GB\")}+`;\n }\n return value.type === \"reference\" ? value.value.documentId : String(value.value);\n}\n/** Escape each replacement, not the surrounding trusted template. JSON returns string content without quotes;\n * callers serialize complete structured objects and keep numeric properties as exact values. Attributes must be quoted.\n * Raw text/React children use the formatter directly; never HTML-unescape an expanded string.\n */\nexport function expandFactPlaceholders(template: string, values: Readonly<Record<string, string>>, context: FactPlaceholderContext): string {\n if (![\"htmlText\", \"htmlAttribute\", \"json\"].includes(context)) return invalid();\n return template.replace(/\\{([^{}]*)\\}/g, (_match, key: string) => {\n assertFactKey(key);\n const resolved = Object.hasOwn(FACT_ALIASES, key) ? FACT_ALIASES[key]! : key;\n if (!Object.hasOwn(values, resolved)) throw new Error(`Unknown fact placeholder: ${key}`);\n const value = values[resolved]!;\n if (context === \"json\") return JSON.stringify(value).slice(1, -1)\n .replace(/</g, \"\\\\u003c\").replace(/>/g, \"\\\\u003e\").replace(/&/g, \"\\\\u0026\")\n .replace(/\\u2028/g, \"\\\\u2028\").replace(/\\u2029/g, \"\\\\u2029\");\n return value.replace(/[&<>\"']/g, (char) => ({ \"&\": \"&amp;\", \"<\": \"&lt;\", \">\": \"&gt;\", '\"': \"&quot;\", \"'\": \"&#39;\" })[char]!);\n });\n}\n/** Fixed JSON domain, sorted object keys, array order preserved, finite numbers only. */\nexport function canonicalFactJson(value: unknown): string {\n if (value === null || typeof value === \"boolean\" || typeof value === \"string\") return JSON.stringify(value);\n if (typeof value === \"number\" && Number.isFinite(value)) return JSON.stringify(value);\n if (Array.isArray(value)) return `[${Array.from(value, canonicalFactJson).join(\",\")}]`;\n if (typeof value !== \"object\" || value === null || Object.getPrototypeOf(value) !== Object.prototype) return invalid();\n return `{${Object.entries(value).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0)\n .map(([key, item]) => `${JSON.stringify(key)}:${canonicalFactJson(item)}`).join(\",\")}}`;\n}\n/** SHA-256 of contract fields only; unknown fields and approval are ignored. Instants use UTC milliseconds. */\nexport async function hashFactRevision(revision: FactRevision): Promise<string> {\n const fact = revision.fact;\n assertFactKey(fact.key);\n const publicValue = parseFactValue(fact.publicValue);\n formatFact(publicValue, fact.displayRule);\n if (!Number.isSafeInteger(revision.revision) || revision.revision < 1\n || (revision.baseRevision !== null && (!Number.isSafeInteger(revision.baseRevision) || revision.baseRevision < 1 || revision.baseRevision >= revision.revision))) invalid();\n text(revision.projectId); text(fact.accountableOwner); text(fact.source.definition); text(fact.source.version);\n if (![\"computed\", \"observed\", \"attested\"].includes(fact.source.kind) || !Object.hasOwn(FACT_EXPIRY_MS, fact.freshness)\n || typeof fact.optional !== \"boolean\" || (fact.unit !== null && typeof fact.unit !== \"string\")) invalid();\n if (fact.timezone !== null) new Intl.DateTimeFormat(\"en-GB\", { timeZone: text(fact.timezone) });\n const instant = (value: string) => {\n if (!/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d{3})?Z$/.test(value) || !Number.isFinite(Date.parse(value))\n || new Date(value).toISOString() !== value.replace(/(?<=:\\d{2})Z$/, \".000Z\")) invalid();\n return Date.parse(value);\n };\n if (instant(revision.expiresAt) <= instant(revision.effectiveAt)\n || instant(revision.evidence.expiresAt) <= instant(revision.evidence.observedAt)\n || !/^[0-9a-f]{64}$/.test(revision.evidence.digest) || typeof revision.evidence.complete !== \"boolean\") invalid();\n text(revision.evidence.reference); text(revision.evidence.runId);\n for (const surface of fact.surfaces) {\n text(surface.id);\n if (surface.semantics === \"historical\") parseFactValue({ type: \"date\", value: surface.asOf });\n else if (surface.semantics !== \"current\" || surface.asOf !== null) invalid();\n }\n const candidate: FactRevision = {\n projectId: revision.projectId, revision: revision.revision, baseRevision: revision.baseRevision,\n fact: {\n key: fact.key, publicValue, unit: fact.unit, timezone: fact.timezone, displayRule: fact.displayRule,\n source: { kind: fact.source.kind, definition: fact.source.definition, version: fact.source.version },\n accountableOwner: fact.accountableOwner, freshness: fact.freshness, optional: fact.optional,\n surfaces: fact.surfaces.map((surface) => ({ id: surface.id, semantics: surface.semantics, asOf: surface.asOf })),\n },\n evidence: {\n reference: revision.evidence.reference, digest: revision.evidence.digest, complete: revision.evidence.complete,\n runId: revision.evidence.runId, observedAt: new Date(instant(revision.evidence.observedAt)).toISOString(),\n expiresAt: new Date(instant(revision.evidence.expiresAt)).toISOString(),\n },\n effectiveAt: new Date(instant(revision.effectiveAt)).toISOString(),\n expiresAt: new Date(instant(revision.expiresAt)).toISOString(),\n };\n const digest = await crypto.subtle.digest(\"SHA-256\", new TextEncoder().encode(canonicalFactJson(candidate)));\n return Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, \"0\")).join(\"\");\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["facts_exports", "__export", "FACT_ALIASES", "FACT_DISPLAY_RULES", "FACT_EXPIRY_MS", "FACT_KEY", "FACT_TYPES", "assertFactKey", "businessFactId", "canonicalFactJson", "expandFactPlaceholders", "formatFact", "hashFactRevision", "parseFactDisplayRule", "parseFactValue", "parseStoredFactValue", "storeFactValue", "__toCommonJS", "FACT_TYPES", "FACT_DISPLAY_RULES", "FACT_KEY", "FACT_ALIASES", "FACT_EXPIRY_MS", "parseStoredFactValue", "input", "entry", "record", "value", "parseFactValue", "storeFactValue", "invalid", "text", "assertFactKey", "key", "businessFactId", "byte", "allowed", "item", "ref", "parseFactDisplayRule", "formatFact", "rule", "expandFactPlaceholders", "template", "values", "context", "_match", "resolved", "char", "canonicalFactJson", "a", "b", "hashFactRevision", "revision", "fact", "publicValue", "instant", "surface", "candidate", "digest"]
7
+ }
@@ -0,0 +1 @@
1
+ export * from "./contracts/facts.cjs";
@@ -0,0 +1 @@
1
+ export * from "./contracts/facts.mjs";
@@ -0,0 +1 @@
1
+ export * from "./contracts/facts.js";
package/dist/facts.mjs ADDED
@@ -0,0 +1,2 @@
1
+ var F=["integer","decimal","boolean","date","string","enum","reference"],x=["identity/v1","floorHundredsPlus/v1"],y=/^[a-z][a-zA-Z0-9]*(?:\.[a-zA-Z][a-zA-Z0-9]*)*$/,g={pubCount:"coverage.pubCount"},m={computed:72*36e5,operational:30*864e5,technical:90*864e5};function R(e){let t=l(e),n=t.type==="integer"?t.numberValue:t.type==="boolean"?t.booleanValue:t.type==="reference"?{documentId:t.documentId,documentRevision:t.documentRevision}:t.textValue;return c({type:t.type,value:n,allowedValues:t.allowedValues})}function A(e){let t=c(e);return t.type==="integer"?{type:t.type,numberValue:t.value}:t.type==="boolean"?{type:t.type,booleanValue:t.value}:t.type==="reference"?{type:t.type,...t.value}:t.type==="enum"?{type:t.type,textValue:t.value,allowedValues:t.allowedValues}:{type:t.type,textValue:t.value}}function s(){throw new Error("Invalid business fact contract")}function l(e){return!e||typeof e!="object"||Array.isArray(e)?s():e}function a(e){return typeof e=="string"&&e.trim()!==""?e:s()}function d(e){(e.length>48||!y.test(e))&&s()}function S(e){return d(e),"businessFact-"+Array.from(new TextEncoder().encode(e),t=>t.toString(16).padStart(2,"0")).join("")}function c(e){let t=l(e),n=t.value;switch(t.type){case"integer":return Number.isSafeInteger(n)?{type:"integer",value:n}:s();case"decimal":return typeof n=="string"&&/^(?:0|-?[1-9]\d*)(?:\.\d*[1-9])?$|^-0\.\d*[1-9]$/.test(n)?{type:"decimal",value:n}:s();case"boolean":return typeof n=="boolean"?{type:"boolean",value:n}:s();case"string":return typeof n=="string"?{type:"string",value:n}:s();case"date":return typeof n=="string"&&/^\d{4}-\d{2}-\d{2}$/.test(n)&&!Number.isNaN(Date.parse(n))&&new Date(n).toISOString().slice(0,10)===n?{type:"date",value:n}:s();case"enum":{let r=t.allowedValues;return!Array.isArray(r)||!r.length||!r.every(o=>typeof o=="string"&&o!=="")||new Set(r).size!==r.length||!r.includes(n)?s():{type:"enum",value:a(n),allowedValues:[...r].sort()}}case"reference":{let r=l(n);return{type:"reference",value:{documentId:a(r.documentId),documentRevision:a(r.documentRevision)}}}default:return s()}}function b(e){return e!=="identity/v1"&&e!=="floorHundredsPlus/v1"?s():e}function v(e,t){let n=c(e);return b(t)==="floorHundredsPlus/v1"?n.type!=="integer"||n.value<0?s():n.value<100?String(n.value):`${(Math.floor(n.value/100)*100).toLocaleString("en-GB")}+`:n.type==="reference"?n.value.documentId:String(n.value)}function w(e,t,n){return["htmlText","htmlAttribute","json"].includes(n)?e.replace(/\{([^{}]*)\}/g,(r,o)=>{d(o);let u=Object.hasOwn(g,o)?g[o]:o;if(!Object.hasOwn(t,u))throw new Error(`Unknown fact placeholder: ${o}`);let i=t[u];return n==="json"?JSON.stringify(i).slice(1,-1).replace(/</g,"\\u003c").replace(/>/g,"\\u003e").replace(/&/g,"\\u0026").replace(/\u2028/g,"\\u2028").replace(/\u2029/g,"\\u2029"):i.replace(/[&<>"']/g,f=>({"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"})[f])}):s()}function p(e){return e===null||typeof e=="boolean"||typeof e=="string"||typeof e=="number"&&Number.isFinite(e)?JSON.stringify(e):Array.isArray(e)?`[${Array.from(e,p).join(",")}]`:typeof e!="object"||e===null||Object.getPrototypeOf(e)!==Object.prototype?s():`{${Object.entries(e).sort(([t],[n])=>t<n?-1:t>n?1:0).map(([t,n])=>`${JSON.stringify(t)}:${p(n)}`).join(",")}}`}async function h(e){let t=e.fact;d(t.key);let n=c(t.publicValue);v(n,t.displayRule),(!Number.isSafeInteger(e.revision)||e.revision<1||e.baseRevision!==null&&(!Number.isSafeInteger(e.baseRevision)||e.baseRevision<1||e.baseRevision>=e.revision))&&s(),a(e.projectId),a(t.accountableOwner),a(t.source.definition),a(t.source.version),(!["computed","observed","attested"].includes(t.source.kind)||!Object.hasOwn(m,t.freshness)||typeof t.optional!="boolean"||t.unit!==null&&typeof t.unit!="string")&&s(),t.timezone!==null&&new Intl.DateTimeFormat("en-GB",{timeZone:a(t.timezone)});let r=i=>((!/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{3})?Z$/.test(i)||!Number.isFinite(Date.parse(i))||new Date(i).toISOString()!==i.replace(/(?<=:\d{2})Z$/,".000Z"))&&s(),Date.parse(i));(r(e.expiresAt)<=r(e.effectiveAt)||r(e.evidence.expiresAt)<=r(e.evidence.observedAt)||!/^[0-9a-f]{64}$/.test(e.evidence.digest)||typeof e.evidence.complete!="boolean")&&s(),a(e.evidence.reference),a(e.evidence.runId);for(let i of t.surfaces)a(i.id),i.semantics==="historical"?c({type:"date",value:i.asOf}):(i.semantics!=="current"||i.asOf!==null)&&s();let o={projectId:e.projectId,revision:e.revision,baseRevision:e.baseRevision,fact:{key:t.key,publicValue:n,unit:t.unit,timezone:t.timezone,displayRule:t.displayRule,source:{kind:t.source.kind,definition:t.source.definition,version:t.source.version},accountableOwner:t.accountableOwner,freshness:t.freshness,optional:t.optional,surfaces:t.surfaces.map(i=>({id:i.id,semantics:i.semantics,asOf:i.asOf}))},evidence:{reference:e.evidence.reference,digest:e.evidence.digest,complete:e.evidence.complete,runId:e.evidence.runId,observedAt:new Date(r(e.evidence.observedAt)).toISOString(),expiresAt:new Date(r(e.evidence.expiresAt)).toISOString()},effectiveAt:new Date(r(e.effectiveAt)).toISOString(),expiresAt:new Date(r(e.expiresAt)).toISOString()},u=await crypto.subtle.digest("SHA-256",new TextEncoder().encode(p(o)));return Array.from(new Uint8Array(u),i=>i.toString(16).padStart(2,"0")).join("")}export{g as FACT_ALIASES,x as FACT_DISPLAY_RULES,m as FACT_EXPIRY_MS,y as FACT_KEY,F as FACT_TYPES,d as assertFactKey,S as businessFactId,p as canonicalFactJson,w as expandFactPlaceholders,v as formatFact,h as hashFactRevision,b as parseFactDisplayRule,c as parseFactValue,R as parseStoredFactValue,A as storeFactValue};
2
+ //# sourceMappingURL=facts.mjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/contracts/facts.ts"],
4
+ "sourcesContent": ["/** Public contracts only. Evidence and approval identities never enter the CMS document. */\nexport const FACT_TYPES = [\"integer\", \"decimal\", \"boolean\", \"date\", \"string\", \"enum\", \"reference\"] as const;\nexport const FACT_DISPLAY_RULES = [\"identity/v1\", \"floorHundredsPlus/v1\"] as const;\nexport type FactDisplayRule = typeof FACT_DISPLAY_RULES[number];\nexport const FACT_KEY = /^[a-z][a-zA-Z0-9]*(?:\\.[a-zA-Z][a-zA-Z0-9]*)*$/;\nexport const FACT_ALIASES: Readonly<Record<string, string>> = { pubCount: \"coverage.pubCount\" };\nexport type FactValue =\n | { type: \"integer\"; value: number }\n // Decimal strings avoid binary floating-point loss; canonical form has no trailing fractional zeroes.\n | { type: \"decimal\"; value: string }\n | { type: \"boolean\"; value: boolean }\n | { type: \"date\" | \"string\"; value: string }\n | { type: \"enum\"; value: string; allowedValues: readonly string[] }\n | { type: \"reference\"; value: { documentId: string; documentRevision: string } };\nexport type FactSource = { kind: \"computed\" | \"observed\" | \"attested\"; definition: string; version: string };\nexport type BusinessFact = {\n key: string; publicValue: FactValue; unit: string | null; timezone: string | null;\n displayRule: FactDisplayRule; source: FactSource; accountableOwner: string;\n freshness: \"computed\" | \"operational\" | \"technical\"; optional: boolean;\n surfaces: readonly { id: string; semantics: \"current\" | \"historical\"; asOf: string | null }[];\n};\nexport const FACT_EXPIRY_MS = { computed: 72 * 3_600_000, operational: 30 * 86_400_000, technical: 90 * 86_400_000 } as const;\nexport type FactEvidence = { reference: string; digest: string; observedAt: string; expiresAt: string; complete: boolean; runId: string };\nexport type FactRevision = {\n projectId: string; revision: number; baseRevision: number | null; fact: BusinessFact;\n evidence: FactEvidence; effectiveAt: string; expiresAt: string;\n};\nexport type ApprovedFactRevision = FactRevision & {\n hash: string; approvedAt: string;\n approval: { kind: \"signer\"; signerId: string } | { kind: \"policy\"; policyVersion: string };\n};\nexport type FactPublicationReceipt = {\n intentId: string; projectId: string; revision: number; hash: string;\n destination: { projectId: string; dataset: string }; expectedDocumentRevision: string | null;\n cms: { transactionId: string; documentRevision: string; readBackHash: string; at: string } | null;\n invalidation: { deliveryKey: string; target: string; type: \"businessFact\"; id: string; at: string } | null;\n render: { url: string; deploymentId: string; revision: number; hash: string; at: string } | null;\n};\nexport type PublicBusinessFact = Pick<BusinessFact, \"key\" | \"publicValue\" | \"unit\" | \"timezone\" | \"displayRule\"> & {\n _type: \"businessFact\"; _id: string; approvedRevision: number; approvedHash: string;\n effectiveAt: string; expiresAt: string; provenanceSummary: string;\n};\n/** A request supplies one snapshot to every surface. Missing and unavailable are distinct from an empty snapshot. */\nexport type FactSnapshot = Readonly<Record<string, PublicBusinessFact>>;\nexport type FactReadResult = { status: \"available\"; snapshot: FactSnapshot } | { status: \"unavailable\"; reason: string };\nexport type FactReader = () => Promise<FactReadResult>;\nexport type FactPlaceholderContext = \"htmlText\" | \"htmlAttribute\" | \"json\";\n/** Stored Sanity projection: scalar unions use named slots, never private revision fields. */\nexport type StoredFactValue = { type: FactValue[\"type\"]; numberValue?: number; textValue?: string;\n booleanValue?: boolean; allowedValues?: readonly string[]; documentId?: string; documentRevision?: string };\nexport function parseStoredFactValue(input: unknown): FactValue {\n const entry = record(input);\n const value = entry.type === \"integer\" ? entry.numberValue : entry.type === \"boolean\" ? entry.booleanValue\n : entry.type === \"reference\" ? { documentId: entry.documentId, documentRevision: entry.documentRevision } : entry.textValue;\n return parseFactValue({ type: entry.type, value, allowedValues: entry.allowedValues });\n}\nexport function storeFactValue(input: FactValue): StoredFactValue {\n const entry = parseFactValue(input);\n if (entry.type === \"integer\") return { type: entry.type, numberValue: entry.value };\n if (entry.type === \"boolean\") return { type: entry.type, booleanValue: entry.value };\n if (entry.type === \"reference\") return { type: entry.type, ...entry.value };\n return entry.type === \"enum\" ? { type: entry.type, textValue: entry.value, allowedValues: entry.allowedValues }\n : { type: entry.type, textValue: entry.value };\n}\nexport type StoredBusinessFact = Omit<PublicBusinessFact, \"publicValue\"> & { publicValue: StoredFactValue };\n\nfunction invalid(): never { throw new Error(\"Invalid business fact contract\"); }\nfunction record(value: unknown): Record<string, unknown> {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return invalid();\n return value as Record<string, unknown>;\n}\nfunction text(value: unknown): string { return typeof value === \"string\" && value.trim() !== \"\" ? value : invalid(); }\nexport function assertFactKey(key: string): void {\n if (key.length > 48 || !FACT_KEY.test(key)) invalid();\n}\nexport function businessFactId(key: string): string {\n assertFactKey(key);\n // Dataset-local, injective encoding; never a draft ID or a key containing a path separator.\n return \"businessFact-\" + Array.from(new TextEncoder().encode(key), (byte) => byte.toString(16).padStart(2, \"0\")).join(\"\");\n}\nexport function parseFactValue(input: unknown): FactValue {\n const entry = record(input), value = entry.value;\n switch (entry.type) {\n case \"integer\": return Number.isSafeInteger(value) ? { type: \"integer\", value: value as number } : invalid();\n case \"decimal\": return typeof value === \"string\" && /^(?:0|-?[1-9]\\d*)(?:\\.\\d*[1-9])?$|^-0\\.\\d*[1-9]$/.test(value)\n ? { type: \"decimal\", value } : invalid();\n case \"boolean\": return typeof value === \"boolean\" ? { type: \"boolean\", value } : invalid();\n case \"string\": return typeof value === \"string\" ? { type: \"string\", value } : invalid();\n case \"date\": return typeof value === \"string\" && /^\\d{4}-\\d{2}-\\d{2}$/.test(value)\n && !Number.isNaN(Date.parse(value)) && new Date(value).toISOString().slice(0, 10) === value ? { type: \"date\", value } : invalid();\n case \"enum\": {\n const allowed = entry.allowedValues;\n if (!Array.isArray(allowed) || !allowed.length || !allowed.every((item) => typeof item === \"string\" && item !== \"\")\n || new Set(allowed).size !== allowed.length || !allowed.includes(value)) return invalid();\n return { type: \"enum\", value: text(value), allowedValues: [...allowed].sort() as string[] };\n }\n case \"reference\": {\n const ref = record(value);\n return { type: \"reference\", value: { documentId: text(ref.documentId), documentRevision: text(ref.documentRevision) } };\n }\n default: return invalid();\n }\n}\nexport function parseFactDisplayRule(input: unknown): FactDisplayRule {\n if (input !== \"identity/v1\" && input !== \"floorHundredsPlus/v1\") return invalid();\n return input;\n}\nexport function formatFact(input: FactValue, rule: FactDisplayRule): string {\n const value = parseFactValue(input);\n if (parseFactDisplayRule(rule) === \"floorHundredsPlus/v1\") {\n if (value.type !== \"integer\" || value.value < 0) return invalid();\n return value.value < 100 ? String(value.value) : `${(Math.floor(value.value / 100) * 100).toLocaleString(\"en-GB\")}+`;\n }\n return value.type === \"reference\" ? value.value.documentId : String(value.value);\n}\n/** Escape each replacement, not the surrounding trusted template. JSON returns string content without quotes;\n * callers serialize complete structured objects and keep numeric properties as exact values. Attributes must be quoted.\n * Raw text/React children use the formatter directly; never HTML-unescape an expanded string.\n */\nexport function expandFactPlaceholders(template: string, values: Readonly<Record<string, string>>, context: FactPlaceholderContext): string {\n if (![\"htmlText\", \"htmlAttribute\", \"json\"].includes(context)) return invalid();\n return template.replace(/\\{([^{}]*)\\}/g, (_match, key: string) => {\n assertFactKey(key);\n const resolved = Object.hasOwn(FACT_ALIASES, key) ? FACT_ALIASES[key]! : key;\n if (!Object.hasOwn(values, resolved)) throw new Error(`Unknown fact placeholder: ${key}`);\n const value = values[resolved]!;\n if (context === \"json\") return JSON.stringify(value).slice(1, -1)\n .replace(/</g, \"\\\\u003c\").replace(/>/g, \"\\\\u003e\").replace(/&/g, \"\\\\u0026\")\n .replace(/\\u2028/g, \"\\\\u2028\").replace(/\\u2029/g, \"\\\\u2029\");\n return value.replace(/[&<>\"']/g, (char) => ({ \"&\": \"&amp;\", \"<\": \"&lt;\", \">\": \"&gt;\", '\"': \"&quot;\", \"'\": \"&#39;\" })[char]!);\n });\n}\n/** Fixed JSON domain, sorted object keys, array order preserved, finite numbers only. */\nexport function canonicalFactJson(value: unknown): string {\n if (value === null || typeof value === \"boolean\" || typeof value === \"string\") return JSON.stringify(value);\n if (typeof value === \"number\" && Number.isFinite(value)) return JSON.stringify(value);\n if (Array.isArray(value)) return `[${Array.from(value, canonicalFactJson).join(\",\")}]`;\n if (typeof value !== \"object\" || value === null || Object.getPrototypeOf(value) !== Object.prototype) return invalid();\n return `{${Object.entries(value).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0)\n .map(([key, item]) => `${JSON.stringify(key)}:${canonicalFactJson(item)}`).join(\",\")}}`;\n}\n/** SHA-256 of contract fields only; unknown fields and approval are ignored. Instants use UTC milliseconds. */\nexport async function hashFactRevision(revision: FactRevision): Promise<string> {\n const fact = revision.fact;\n assertFactKey(fact.key);\n const publicValue = parseFactValue(fact.publicValue);\n formatFact(publicValue, fact.displayRule);\n if (!Number.isSafeInteger(revision.revision) || revision.revision < 1\n || (revision.baseRevision !== null && (!Number.isSafeInteger(revision.baseRevision) || revision.baseRevision < 1 || revision.baseRevision >= revision.revision))) invalid();\n text(revision.projectId); text(fact.accountableOwner); text(fact.source.definition); text(fact.source.version);\n if (![\"computed\", \"observed\", \"attested\"].includes(fact.source.kind) || !Object.hasOwn(FACT_EXPIRY_MS, fact.freshness)\n || typeof fact.optional !== \"boolean\" || (fact.unit !== null && typeof fact.unit !== \"string\")) invalid();\n if (fact.timezone !== null) new Intl.DateTimeFormat(\"en-GB\", { timeZone: text(fact.timezone) });\n const instant = (value: string) => {\n if (!/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d{3})?Z$/.test(value) || !Number.isFinite(Date.parse(value))\n || new Date(value).toISOString() !== value.replace(/(?<=:\\d{2})Z$/, \".000Z\")) invalid();\n return Date.parse(value);\n };\n if (instant(revision.expiresAt) <= instant(revision.effectiveAt)\n || instant(revision.evidence.expiresAt) <= instant(revision.evidence.observedAt)\n || !/^[0-9a-f]{64}$/.test(revision.evidence.digest) || typeof revision.evidence.complete !== \"boolean\") invalid();\n text(revision.evidence.reference); text(revision.evidence.runId);\n for (const surface of fact.surfaces) {\n text(surface.id);\n if (surface.semantics === \"historical\") parseFactValue({ type: \"date\", value: surface.asOf });\n else if (surface.semantics !== \"current\" || surface.asOf !== null) invalid();\n }\n const candidate: FactRevision = {\n projectId: revision.projectId, revision: revision.revision, baseRevision: revision.baseRevision,\n fact: {\n key: fact.key, publicValue, unit: fact.unit, timezone: fact.timezone, displayRule: fact.displayRule,\n source: { kind: fact.source.kind, definition: fact.source.definition, version: fact.source.version },\n accountableOwner: fact.accountableOwner, freshness: fact.freshness, optional: fact.optional,\n surfaces: fact.surfaces.map((surface) => ({ id: surface.id, semantics: surface.semantics, asOf: surface.asOf })),\n },\n evidence: {\n reference: revision.evidence.reference, digest: revision.evidence.digest, complete: revision.evidence.complete,\n runId: revision.evidence.runId, observedAt: new Date(instant(revision.evidence.observedAt)).toISOString(),\n expiresAt: new Date(instant(revision.evidence.expiresAt)).toISOString(),\n },\n effectiveAt: new Date(instant(revision.effectiveAt)).toISOString(),\n expiresAt: new Date(instant(revision.expiresAt)).toISOString(),\n };\n const digest = await crypto.subtle.digest(\"SHA-256\", new TextEncoder().encode(canonicalFactJson(candidate)));\n return Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, \"0\")).join(\"\");\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["FACT_TYPES", "FACT_DISPLAY_RULES", "FACT_KEY", "FACT_ALIASES", "FACT_EXPIRY_MS", "parseStoredFactValue", "input", "entry", "record", "value", "parseFactValue", "storeFactValue", "invalid", "text", "assertFactKey", "key", "businessFactId", "byte", "allowed", "item", "ref", "parseFactDisplayRule", "formatFact", "rule", "expandFactPlaceholders", "template", "values", "context", "_match", "resolved", "char", "canonicalFactJson", "a", "b", "hashFactRevision", "revision", "fact", "publicValue", "instant", "surface", "candidate", "digest"]
7
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@weatherboard/cms",
3
- "version": "0.9.0",
3
+ "version": "0.11.0",
4
4
  "private": false,
5
5
  "description": "Published-content contracts, server readers, adapters and portable content tooling.",
6
6
  "license": "MIT",
@@ -93,6 +93,36 @@
93
93
  "types": "./dist/guard.d.cts",
94
94
  "default": "./dist/guard.cjs"
95
95
  }
96
+ },
97
+ "./facts": {
98
+ "import": {
99
+ "types": "./dist/facts.d.mts",
100
+ "default": "./dist/facts.mjs"
101
+ },
102
+ "require": {
103
+ "types": "./dist/facts.d.cts",
104
+ "default": "./dist/facts.cjs"
105
+ }
106
+ },
107
+ "./fact-guard": {
108
+ "import": {
109
+ "types": "./dist/fact-guard.d.mts",
110
+ "default": "./dist/fact-guard.mjs"
111
+ },
112
+ "require": {
113
+ "types": "./dist/fact-guard.d.cts",
114
+ "default": "./dist/fact-guard.cjs"
115
+ }
116
+ },
117
+ "./content-manifest": {
118
+ "import": {
119
+ "types": "./dist/content-manifest.d.mts",
120
+ "default": "./dist/content-manifest.mjs"
121
+ },
122
+ "require": {
123
+ "types": "./dist/content-manifest.d.cts",
124
+ "default": "./dist/content-manifest.cjs"
125
+ }
96
126
  }
97
127
  },
98
128
  "main": "./dist/index.cjs",
@@ -109,7 +139,10 @@
109
139
  "next": 16384,
110
140
  "sanity": 16384,
111
141
  "webhook": 16384,
112
- "site-content": 32768
142
+ "site-content": 32768,
143
+ "facts": 8192,
144
+ "fact-guard": 8192,
145
+ "content-manifest": 8192
113
146
  },
114
147
  "dependencies": {
115
148
  "server-only": "0.0.1"