@lssm/lib.contracts-runtime-core 3.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (227) hide show
  1. package/README.md +110 -0
  2. package/dist/approval.d.ts +13 -0
  3. package/dist/approval.js +2 -0
  4. package/dist/approval.test.d.ts +1 -0
  5. package/dist/browser/approval.js +1 -0
  6. package/dist/browser/collaboration.js +0 -0
  7. package/dist/browser/contracts-runtime-core.feature.js +1 -0
  8. package/dist/browser/engine/backoff.js +1 -0
  9. package/dist/browser/engine/cache-store.js +1 -0
  10. package/dist/browser/engine/conflict-registry.js +1 -0
  11. package/dist/browser/engine/conflict-resolution.js +1 -0
  12. package/dist/browser/engine/data-engine-host.js +1 -0
  13. package/dist/browser/engine/data-engine-test-helpers.js +1 -0
  14. package/dist/browser/engine/data-engine.js +1 -0
  15. package/dist/browser/engine/dedup.js +1 -0
  16. package/dist/browser/engine/events.js +1 -0
  17. package/dist/browser/engine/index.js +1 -0
  18. package/dist/browser/engine/maintenance.js +1 -0
  19. package/dist/browser/engine/mutation-engine.js +1 -0
  20. package/dist/browser/engine/mutation-queue.js +1 -0
  21. package/dist/browser/engine/mutation-types.js +0 -0
  22. package/dist/browser/engine/no-cache-store.js +1 -0
  23. package/dist/browser/engine/online-only-data-engine.js +1 -0
  24. package/dist/browser/engine/online-only-mutation-engine.js +1 -0
  25. package/dist/browser/engine/query-engine.js +1 -0
  26. package/dist/browser/engine/state.js +1 -0
  27. package/dist/browser/engine/types.js +0 -0
  28. package/dist/browser/forms-platform-csv-columns.js +1 -0
  29. package/dist/browser/forms-platform-csv.js +2 -0
  30. package/dist/browser/forms-platform-management.js +1 -0
  31. package/dist/browser/forms-platform-navigation.js +1 -0
  32. package/dist/browser/forms-platform-submission.js +1 -0
  33. package/dist/browser/forms-platform-types.js +1 -0
  34. package/dist/browser/forms-platform-utils.js +1 -0
  35. package/dist/browser/forms-platform.js +2 -0
  36. package/dist/browser/index.js +3 -0
  37. package/dist/browser/local-offline.js +1 -0
  38. package/dist/browser/observability.js +1 -0
  39. package/dist/browser/reachability.js +1 -0
  40. package/dist/browser/redaction.js +1 -0
  41. package/dist/browser/storage/indexeddb.web.js +1 -0
  42. package/dist/browser/storage/keyed-store.js +1 -0
  43. package/dist/browser/storage/memory.js +1 -0
  44. package/dist/browser/storage/port.js +1 -0
  45. package/dist/browser/transport.js +2 -0
  46. package/dist/collaboration.d.ts +57 -0
  47. package/dist/collaboration.js +1 -0
  48. package/dist/contracts-runtime-core.feature.d.ts +1 -0
  49. package/dist/contracts-runtime-core.feature.js +2 -0
  50. package/dist/engine/backoff.d.ts +16 -0
  51. package/dist/engine/backoff.js +2 -0
  52. package/dist/engine/backoff.test.d.ts +1 -0
  53. package/dist/engine/cache-store.d.ts +19 -0
  54. package/dist/engine/cache-store.js +2 -0
  55. package/dist/engine/conflict-registry.d.ts +10 -0
  56. package/dist/engine/conflict-registry.js +2 -0
  57. package/dist/engine/conflict-registry.test.d.ts +1 -0
  58. package/dist/engine/conflict-resolution.d.ts +24 -0
  59. package/dist/engine/conflict-resolution.js +2 -0
  60. package/dist/engine/conflict-resolution.test.d.ts +1 -0
  61. package/dist/engine/data-engine-host.d.ts +30 -0
  62. package/dist/engine/data-engine-host.js +2 -0
  63. package/dist/engine/data-engine-local-offline.test.d.ts +1 -0
  64. package/dist/engine/data-engine-test-helpers.d.ts +30 -0
  65. package/dist/engine/data-engine-test-helpers.js +2 -0
  66. package/dist/engine/data-engine.d.ts +46 -0
  67. package/dist/engine/data-engine.js +2 -0
  68. package/dist/engine/data-engine.test.d.ts +1 -0
  69. package/dist/engine/dedup.d.ts +9 -0
  70. package/dist/engine/dedup.js +2 -0
  71. package/dist/engine/events.d.ts +76 -0
  72. package/dist/engine/events.economic-evidence.test.d.ts +1 -0
  73. package/dist/engine/events.js +2 -0
  74. package/dist/engine/index.d.ts +17 -0
  75. package/dist/engine/index.js +2 -0
  76. package/dist/engine/maintenance.d.ts +18 -0
  77. package/dist/engine/maintenance.js +2 -0
  78. package/dist/engine/maintenance.test.d.ts +1 -0
  79. package/dist/engine/mutation-engine.d.ts +2 -0
  80. package/dist/engine/mutation-engine.js +2 -0
  81. package/dist/engine/mutation-queue.d.ts +16 -0
  82. package/dist/engine/mutation-queue.js +2 -0
  83. package/dist/engine/mutation-queue.test.d.ts +1 -0
  84. package/dist/engine/mutation-types.d.ts +118 -0
  85. package/dist/engine/mutation-types.js +1 -0
  86. package/dist/engine/no-cache-store.d.ts +3 -0
  87. package/dist/engine/no-cache-store.js +2 -0
  88. package/dist/engine/online-only-data-engine.d.ts +9 -0
  89. package/dist/engine/online-only-data-engine.js +2 -0
  90. package/dist/engine/online-only-mutation-engine.d.ts +3 -0
  91. package/dist/engine/online-only-mutation-engine.js +2 -0
  92. package/dist/engine/query-engine.d.ts +7 -0
  93. package/dist/engine/query-engine.js +2 -0
  94. package/dist/engine/query-engine.test.d.ts +1 -0
  95. package/dist/engine/state.d.ts +37 -0
  96. package/dist/engine/state.js +2 -0
  97. package/dist/engine/types.d.ts +70 -0
  98. package/dist/engine/types.js +1 -0
  99. package/dist/forms-platform-choice.test.d.ts +1 -0
  100. package/dist/forms-platform-csv-columns.d.ts +7 -0
  101. package/dist/forms-platform-csv-columns.js +2 -0
  102. package/dist/forms-platform-csv.d.ts +12 -0
  103. package/dist/forms-platform-csv.js +3 -0
  104. package/dist/forms-platform-management.d.ts +12 -0
  105. package/dist/forms-platform-management.js +2 -0
  106. package/dist/forms-platform-navigation.d.ts +2 -0
  107. package/dist/forms-platform-navigation.js +2 -0
  108. package/dist/forms-platform-submission.d.ts +7 -0
  109. package/dist/forms-platform-submission.js +2 -0
  110. package/dist/forms-platform-types.d.ts +51 -0
  111. package/dist/forms-platform-types.js +2 -0
  112. package/dist/forms-platform-utils.d.ts +6 -0
  113. package/dist/forms-platform-utils.js +2 -0
  114. package/dist/forms-platform-utils.test.d.ts +1 -0
  115. package/dist/forms-platform.d.ts +19 -0
  116. package/dist/forms-platform.js +3 -0
  117. package/dist/forms-platform.test.d.ts +1 -0
  118. package/dist/index.d.ts +25 -0
  119. package/dist/index.js +4 -0
  120. package/dist/local-offline.d.ts +17 -0
  121. package/dist/local-offline.js +2 -0
  122. package/dist/local-offline.test.d.ts +1 -0
  123. package/dist/native/approval.js +130 -0
  124. package/dist/native/collaboration.js +0 -0
  125. package/dist/native/contracts-runtime-core.feature.js +17 -0
  126. package/dist/native/engine/backoff.js +16 -0
  127. package/dist/native/engine/cache-store.js +49 -0
  128. package/dist/native/engine/conflict-registry.js +51 -0
  129. package/dist/native/engine/conflict-resolution.js +81 -0
  130. package/dist/native/engine/data-engine-host.js +1119 -0
  131. package/dist/native/engine/data-engine-test-helpers.js +117 -0
  132. package/dist/native/engine/data-engine.js +1106 -0
  133. package/dist/native/engine/dedup.js +22 -0
  134. package/dist/native/engine/events.js +19 -0
  135. package/dist/native/engine/index.js +1189 -0
  136. package/dist/native/engine/maintenance.js +36 -0
  137. package/dist/native/engine/mutation-engine.js +360 -0
  138. package/dist/native/engine/mutation-queue.js +26 -0
  139. package/dist/native/engine/mutation-types.js +0 -0
  140. package/dist/native/engine/no-cache-store.js +15 -0
  141. package/dist/native/engine/online-only-data-engine.js +422 -0
  142. package/dist/native/engine/online-only-mutation-engine.js +70 -0
  143. package/dist/native/engine/query-engine.js +360 -0
  144. package/dist/native/engine/state.js +116 -0
  145. package/dist/native/engine/types.js +0 -0
  146. package/dist/native/forms-platform-csv-columns.js +31 -0
  147. package/dist/native/forms-platform-csv.js +150 -0
  148. package/dist/native/forms-platform-management.js +179 -0
  149. package/dist/native/forms-platform-navigation.js +27 -0
  150. package/dist/native/forms-platform-submission.js +207 -0
  151. package/dist/native/forms-platform-types.js +12 -0
  152. package/dist/native/forms-platform-utils.js +69 -0
  153. package/dist/native/forms-platform.js +429 -0
  154. package/dist/native/index.js +1879 -0
  155. package/dist/native/local-offline.js +81 -0
  156. package/dist/native/observability.js +182 -0
  157. package/dist/native/reachability.js +28 -0
  158. package/dist/native/redaction.js +44 -0
  159. package/dist/native/storage/async-storage.native.js +91 -0
  160. package/dist/native/storage/keyed-store.js +74 -0
  161. package/dist/native/storage/memory.js +26 -0
  162. package/dist/native/storage/port.js +16 -0
  163. package/dist/native/transport.js +27 -0
  164. package/dist/node/approval.js +1 -0
  165. package/dist/node/collaboration.js +0 -0
  166. package/dist/node/contracts-runtime-core.feature.js +1 -0
  167. package/dist/node/engine/backoff.js +1 -0
  168. package/dist/node/engine/cache-store.js +1 -0
  169. package/dist/node/engine/conflict-registry.js +1 -0
  170. package/dist/node/engine/conflict-resolution.js +1 -0
  171. package/dist/node/engine/data-engine-host.js +1 -0
  172. package/dist/node/engine/data-engine-test-helpers.js +1 -0
  173. package/dist/node/engine/data-engine.js +1 -0
  174. package/dist/node/engine/dedup.js +1 -0
  175. package/dist/node/engine/events.js +1 -0
  176. package/dist/node/engine/index.js +1 -0
  177. package/dist/node/engine/maintenance.js +1 -0
  178. package/dist/node/engine/mutation-engine.js +1 -0
  179. package/dist/node/engine/mutation-queue.js +1 -0
  180. package/dist/node/engine/mutation-types.js +0 -0
  181. package/dist/node/engine/no-cache-store.js +1 -0
  182. package/dist/node/engine/online-only-data-engine.js +1 -0
  183. package/dist/node/engine/online-only-mutation-engine.js +1 -0
  184. package/dist/node/engine/query-engine.js +1 -0
  185. package/dist/node/engine/state.js +1 -0
  186. package/dist/node/engine/types.js +0 -0
  187. package/dist/node/forms-platform-csv-columns.js +1 -0
  188. package/dist/node/forms-platform-csv.js +2 -0
  189. package/dist/node/forms-platform-management.js +1 -0
  190. package/dist/node/forms-platform-navigation.js +1 -0
  191. package/dist/node/forms-platform-submission.js +1 -0
  192. package/dist/node/forms-platform-types.js +1 -0
  193. package/dist/node/forms-platform-utils.js +1 -0
  194. package/dist/node/forms-platform.js +2 -0
  195. package/dist/node/index.js +3 -0
  196. package/dist/node/local-offline.js +1 -0
  197. package/dist/node/observability.js +1 -0
  198. package/dist/node/reachability.js +1 -0
  199. package/dist/node/redaction.js +1 -0
  200. package/dist/node/storage/keyed-store.js +1 -0
  201. package/dist/node/storage/memory.js +1 -0
  202. package/dist/node/storage/port.js +1 -0
  203. package/dist/node/transport.js +2 -0
  204. package/dist/observability.d.ts +34 -0
  205. package/dist/observability.js +2 -0
  206. package/dist/observability.test.d.ts +1 -0
  207. package/dist/reachability.d.ts +63 -0
  208. package/dist/reachability.js +2 -0
  209. package/dist/reachability.test.d.ts +1 -0
  210. package/dist/redaction.d.ts +34 -0
  211. package/dist/redaction.js +2 -0
  212. package/dist/redaction.test.d.ts +1 -0
  213. package/dist/storage/async-storage.native.d.ts +23 -0
  214. package/dist/storage/async-storage.native.test.d.ts +1 -0
  215. package/dist/storage/indexeddb.web.d.ts +13 -0
  216. package/dist/storage/indexeddb.web.js +2 -0
  217. package/dist/storage/keyed-store.d.ts +25 -0
  218. package/dist/storage/keyed-store.js +2 -0
  219. package/dist/storage/keyed-store.test.d.ts +1 -0
  220. package/dist/storage/memory.d.ts +11 -0
  221. package/dist/storage/memory.js +2 -0
  222. package/dist/storage/memory.test.d.ts +1 -0
  223. package/dist/storage/port.d.ts +34 -0
  224. package/dist/storage/port.js +2 -0
  225. package/dist/transport.d.ts +53 -0
  226. package/dist/transport.js +3 -0
  227. package/package.json +219 -0
@@ -0,0 +1 @@
1
+ import{createQueryKey as i}from"@lssm/lib.contracts-spec/query/key";import{contractOk as u}from"@lssm/lib.contracts-spec/results";var l={operation:{key:"user.get",version:"1.0.0"},input:{id:"u1"},tags:[{entity:"user",id:"u1"}],cache:{staleTimeMs:60000}},m={operation:{key:"user.update",version:"1.0.0"},input:{id:"u1",name:"Local"},tags:[{entity:"user",id:"u1"}],versionToken:"v1"},p=i(l),v=[{key:p,data:{id:"u1",name:"Local"},versionToken:"v1"}];function h(t){let e={signal:t,since:0},r=new Set;return{source:{getSnapshot:()=>e,subscribe:(n)=>(r.add(n),()=>r.delete(n))},set:(n)=>{e={signal:n,since:0};for(let s of r)s(e)}}}function c(t,e){return{ok:!1,code:"CONFLICT",status:409,problem:{type:"about:blank",title:"Conflict",status:409,code:"CONFLICT",category:"conflict",severity:"warning",retryable:!1,versionToken:t,metadata:{serverData:e}}}}function a(t,e,r){return{ok:!1,code:t,status:e==="auth"?401:503,problem:{type:"about:blank",title:t,status:e==="auth"?401:503,code:t,category:e,severity:"error",retryable:r}}}function b(){let t={id:"u1",name:"Server"},e="v1",r="ok",n=0,s=[];return{transport:{execute:async(o)=>{if(s.push(o.operation.key),o.operation.key==="user.update"){if(r==="conflict")return c("v2",t);if(r==="auth")return a("UNAUTHENTICATED","auth",!1);if(r==="retry"&&n>0)return n-=1,a("SERVICE_UNAVAILABLE","dependency",!0);e="v2",t={...t,name:o.input.name}}return u({data:t,versionToken:e},{versionToken:e})}},calls:s,setMode:(o)=>{r=o},setRetryFails:(o)=>{n=o}}}export{p as KEY,m as MUTATION,l as QUERY,h as mutableReachability,v as optimisticLocal,b as scriptedTransport};
@@ -0,0 +1 @@
1
+ var ce=new Set(["online-only","memory-cache","offline-capable"]),Y={"online-only":"online-only",online:"online-only",disabled:"online-only",false:"online-only",off:"online-only","memory-cache":"memory-cache",memory:"memory-cache",cache:"memory-cache","offline-capable":"offline-capable",offline:"offline-capable",enabled:"offline-capable",true:"offline-capable",on:"offline-capable"};function be(e){return typeof e==="string"&&ce.has(e)}function I(e={}){let t=e.defaultMode===void 0?{mode:"online-only",source:"default",reason:"No local/offline policy input was supplied."}:z(e.defaultMode,"explicit")??{mode:"online-only",source:"explicit"},n=z(ue(e.env),"env",{allowUnknown:!0});return z(e.flag,"feature-flag")??n??t}function ue(e){if(typeof e!=="object"||e===null)return e;if("CONTRACTSPEC_LOCAL_OFFLINE"in e)return e.CONTRACTSPEC_LOCAL_OFFLINE;if("mode"in e)return e;return}function z(e,t,n={}){if(e===void 0||e===null||e==="")return;if(typeof e==="boolean")return{mode:e?"offline-capable":"online-only",source:t};if(typeof e==="string"){let a=Y[e.trim().toLowerCase()];if(a!==void 0)return{mode:a,source:t};if(n.allowUnknown)return}if(typeof e==="object"&&e!==null&&"mode"in e){let a=e,i=typeof a.mode==="string"?Y[a.mode.trim().toLowerCase()]:void 0;if(i!==void 0)return{mode:i,source:t,...typeof a.reason==="string"?{reason:a.reason}:{}};if(n.allowUnknown)return}throw Error(`Unsupported localOffline policy value: ${String(e)}`)}function O(e){return e!=="offline"}function R(e="online"){let t={signal:e,since:Date.now()};return{getSnapshot:()=>t,subscribe:()=>()=>{}}}var ke={id:"docs.contracts-runtime-core.reachability",title:"Reachability input port (tri-state)",summary:"Engine-owned reachability input port; integrations feed it, the engine never imports them.",kind:"reference",visibility:"internal",route:"/docs/contracts-runtime-core/reachability",domain:"contracts-runtime-core",owners:["@contractspec-core"],tags:["contracts-runtime-core","reachability","offline","port"],body:"Tri-state OnlineSignal ('online' | 'restricted' | 'offline'). 'online' allows normal fetch + queue drain. 'restricted' is online-degraded: the engine fetches and drains the queue as if online but may mark results stale-eligible; it never suspends network nor activates the offline queue. Only 'offline' suspends outbound network and activates the durable offline mutation queue. The engine reads reachability solely through ReachabilitySource and MUST NOT import integrations/* — concrete sources (runtime-local networkReachability) are wired via an integration→port adapter (plan §2.3/§4.2, Architect finding 1). isNetworkAllowed mirrors runtime-local's outboundNetworkAllowed = reachability !== 'offline'. createStaticReachabilitySource('online') is the B1a default and online test fixture."};function _(){let e=new Map;return{get:async(t)=>{let n=e.get(t);return n===void 0?void 0:structuredClone(n)},set:async(t,n)=>{e.set(t,structuredClone(n))},remove:async(t)=>{e.delete(t)},keys:async(t)=>{let n=[...e.keys()];return t===void 0?n:n.filter((a)=>a.startsWith(t))},clear:async()=>{e.clear()}}}import{invalidationTagMatches as le}from"@lssm/lib.contracts-spec/query/invalidation";var Z="cache:";function U(e){let t=new Map,n=(a)=>`${Z}${a}`;return{read:(a)=>e.get(n(a)),write:async(a)=>{t.set(a.key,a.tags),await e.set(n(a.key),a)},remove:async(a)=>{t.delete(a),await e.remove(n(a))},entries:async()=>{let a=await e.keys(Z),i=[];for(let u of a){let r=await e.get(u);if(r!==void 0)i.push(r)}return i},invalidate:async(a,i)=>{let u=[];for(let[r,y]of t.entries()){if(!y.some((h)=>a.some((E)=>le(h,E))))continue;let T=await e.get(n(r));if(T===void 0)continue;await e.set(n(r),{...T,status:"stale",staleAt:i}),u.push(r)}return u}}}function fe(e){let{serverData:t,localData:n}=e,a=e.mergeFields??[];if(typeof t!=="object"||t===null||typeof n!=="object"||n===null)return{outcome:"surface"};let i={...t},u=n;for(let r of a)if(r in u)i[r]=u[r];return{outcome:"merged",data:i}}function F(){let e=new Map;return{register(t,n){e.set(t,n)},has(t){return e.has(t)},async resolve(t){switch(t.strategy){case"server-wins":return{outcome:"use-server",data:t.serverData};case"client-wins":return{outcome:"use-client",data:t.localData};case"field-merge":return fe(t);case"surface":return{outcome:"surface"};default:{let n=t.policy.resolver,a=n===void 0?void 0:e.get(n);if(a===void 0)return{outcome:"surface"};return a(t)}}}}}function A(){let e=new Set;return{emit(t){for(let n of e)n(t)},subscribe(t){return e.add(t),()=>{e.delete(t)}}}}function ee(e){return{async collectGarbage(){let t=e.now(),n=0;for(let a of await e.cache.entries())if(a.expiresAt!==void 0&&t>=a.expiresAt)await e.cache.remove(a.key),n+=1;return e.events.emit({type:"gc-collected",evicted:n}),n},async revalidateStale(){let t=e.revalidate;if(t===void 0)return 0;let n=e.now(),a=0;for(let i of await e.cache.entries()){if(!(i.staleAt!==void 0&&n>=i.staleAt)||i.envelope===void 0)continue;await t(i.envelope),e.events.emit({type:"revalidated",key:i.key}),a+=1}return a}}}import{mergeSafeEconomicEvidenceRefIds as me,parseSafeEconomicEvidenceRefId as pe}from"@lssm/lib.contracts-spec/operations";import{defaultConflictPolicy as ye}from"@lssm/lib.contracts-spec/query/conflict-policy";function te(e,t={}){let n=t.baseMs??200,a=t.factor??2,i=t.maxMs??30000,u=t.jitter??Math.random,r=Math.max(0,e-1),y=Math.min(i,n*a**r);return Math.round(y*(0.5+u()*0.5))}import{defaultConflictPolicy as de}from"@lssm/lib.contracts-spec/query/conflict-policy";async function N(e,t){for(let n of e)if(n.previous===void 0)await t.remove(n.key);else await t.write(n.previous)}async function ne(e,t,n){let a=e.conflictPolicy??de(),i=e.rollback[0]?.key,u=i===void 0?void 0:await n.cache.read(i),r=t.metadata?.serverData,y=await n.resolvers.resolve({strategy:a.strategy,policy:a,localData:u?.data,serverData:r,localVersion:e.versionToken,serverVersion:t.versionToken,mergeFields:a.mergeFields});switch(n.events.emit({type:"mutation-conflict",id:e.id,strategy:a.strategy,outcome:y.outcome}),y.outcome){case"use-server":{await N(e.rollback,n.cache),await n.cache.invalidate(e.tags,n.now());for(let M of e.rollback)await n.queryEngine?.refresh(M.key);return"resolved"}case"use-client":return await n.queue.update({...e,versionToken:t.versionToken,status:"pending"}),"re-enqueued";case"merged":{if(i!==void 0&&u!==void 0)await n.cache.write({...u,data:y.data,versionToken:t.versionToken,status:"warm",storedAt:n.now()}),await n.queryEngine?.refresh(i);return await n.queue.update({...e,versionToken:t.versionToken,status:"pending"}),"re-enqueued"}default:{if(i!==void 0)await n.queryEngine?.emitConflict(i,{versionToken:t.versionToken,serverData:r,clientData:u?.data,strategy:a.strategy});return"resolved"}}}var ge=5;function W(...e){return me(...e)}function ve(e){let t=pe(e);if(!t)throw Error("EconomicEvidenceInvalidRef: unsafe or invalid economic evidence ref");return t}function ae(e){let{transport:t,cache:n,queue:a,reachability:i,resolvers:u,events:r}=e,y=e.now??(()=>Date.now()),M=e.maxAttempts??ge,T={cache:n,queue:a,resolvers:u,events:r,now:y,queryEngine:e.queryEngine},h=!1,E=0,S=null,D=new Map,q=(o,l=o.economicEvidenceRefs)=>({operation:o.operation,input:o.input,tags:o.tags,economicEvidenceRefs:l});async function v(o){let l=[];for(let f of o){let g=await n.read(f.key);l.push({key:f.key,previous:g}),await n.write({key:f.key,data:f.data,versionToken:f.versionToken??g?.versionToken,status:"warm",tags:g?.tags??[],storedAt:y(),staleAt:g?.staleAt,expiresAt:g?.expiresAt}),await e.queryEngine?.refresh(f.key)}return l}async function w(o,l){for(let f of o.rollback){let g=await n.read(f.key);if(g!==void 0)await n.write({...g,versionToken:l.versionToken??g.versionToken,status:"stale",staleAt:y()});await e.queryEngine?.refresh(f.key)}await n.invalidate(o.tags,y())}async function m(o){let l;try{l=W(o.economicEvidenceRefs)}catch{await N(o.rollback,n);for(let b of o.rollback)await e.queryEngine?.refresh(b.key);return await a.remove(o.id),r.emit({type:"mutation-failed",id:o.id,code:"ECONOMIC_EVIDENCE_INVALID_REF"}),D.set(o.id,{id:o.id,status:"failed",problem:{type:"about:blank",title:"Economic evidence ref rejected",status:422,code:"ECONOMIC_EVIDENCE_INVALID_REF",category:"validation",severity:"error",retryable:!1}}),!0}let f=o.attempts+1;await a.update({...o,status:"in-flight",attempts:f});let g=await t.execute(q(o,l),e.contextProvider?.());if(g.ok){let b=W(l,g.data.economicEvidenceRefs);if(await w(o,g.data),await a.remove(o.id),r.emit({type:"mutation-replayed",id:o.id,queueDepth:await a.depth()}),b.length>0)r.emit({type:"economic-evidence-attached",operationKey:o.operation.key,evidenceRefs:b.map(ve)});return D.set(o.id,{id:o.id,status:"done",data:g.data.data,economicEvidenceRefs:b}),!0}let{problem:k}=g;if(k.category==="auth"){if(h=!0,await a.update({...o,status:"paused-auth",attempts:f}),r.emit({type:"auth-expired",id:o.id}),D.set(o.id,{id:o.id,status:"paused-auth",problem:k}),e.refreshAuth!==void 0&&await e.refreshAuth())return h=!1,await a.update({...o,status:"pending",attempts:f}),!0;return!1}if(k.category==="conflict"){if(await ne(o,k,T)==="resolved")await a.remove(o.id),D.set(o.id,{id:o.id,status:"done",problem:k});return!0}if(k.retryable&&f<M){let b=te(f,e.backoff);return await a.update({...o,status:"failed",attempts:f}),r.emit({type:"mutation-retry",id:o.id,attempt:f,delayMs:b}),D.set(o.id,{id:o.id,status:"failed",problem:k}),e.schedule?.(()=>{d()},b),!0}await N(o.rollback,n);for(let b of o.rollback)await e.queryEngine?.refresh(b.key);return await a.remove(o.id),r.emit({type:"mutation-failed",id:o.id,code:g.code}),D.set(o.id,{id:o.id,status:"failed",problem:k}),!0}async function c(){if(h)return;if(!O(i.getSnapshot().signal))return;for(let o of await a.list()){if(o.status==="paused-auth")continue;if(!await m(o))return}r.emit({type:"queue-drained",remaining:await a.depth()})}function d(){if(S!==null)return S;return S=c().finally(()=>{S=null}),S}async function s(o,l={}){W(o.economicEvidenceRefs);let f=y();E+=1;let g=`${f}-${E}`,k=l.optimistic?await v(l.optimistic):[];if(await a.enqueue({...o,conflictPolicy:o.conflictPolicy??ye(),id:g,enqueuedAt:f,attempts:0,status:"pending",rollback:k}),r.emit({type:"mutation-enqueued",id:g,queueDepth:await a.depth()}),!h&&O(i.getSnapshot().signal))await d();return D.get(g)??{id:g,status:"pending"}}async function p(){h=!1;for(let o of await a.list())if(o.status==="paused-auth")await a.update({...o,status:"pending"});await d()}let C=i.subscribe((o)=>{if(!h&&O(o.signal))d()});return{mutate:s,drain:d,resume:p,dispose:C}}function oe(e){let t=(a)=>`queue:${a}`;async function n(){let a=await e.keys("queue:"),i=[];for(let u of a){let r=await e.get(u);if(r!==void 0)i.push(r)}return i.sort((u,r)=>u.enqueuedAt===r.enqueuedAt?u.id.localeCompare(r.id):u.enqueuedAt-r.enqueuedAt),i}return{enqueue:(a)=>e.set(t(a.id),a),update:(a)=>e.set(t(a.id),a),remove:(a)=>e.remove(t(a)),list:()=>n(),depth:async()=>(await e.keys("queue:")).length}}import{createQueryKey as G}from"@lssm/lib.contracts-spec/query/key";function Q(e,t){if(e?.staleAt===void 0)return!1;return t>=e.staleAt}function L(){return{status:"idle",fetchStatus:"idle",cacheStatus:"empty",isStale:!1,isOffline:!1}}function V(e,t){if(e===void 0)return{status:"loading",fetchStatus:"fetching",cacheStatus:"empty",isStale:!1,isOffline:!1};let n=Q(e,t);return{status:"success",fetchStatus:"fetching",data:e.data,cacheStatus:n?"stale":e.status,isStale:n,isOffline:!1,versionToken:e.versionToken,dataUpdatedAt:e.storedAt,...e.pageInfo===void 0?{}:{pageInfo:e.pageInfo}}}function x(e,t){let n=Q(e,t);return{status:"success",fetchStatus:"idle",data:e.data,cacheStatus:n?"stale":e.status,isStale:n,isOffline:!1,versionToken:e.versionToken,dataUpdatedAt:e.storedAt,...e.pageInfo===void 0?{}:{pageInfo:e.pageInfo}}}function j(e,t,n){return{status:"error",fetchStatus:"idle",data:t?.data,error:e,cacheStatus:t===void 0?"empty":t.status,isStale:Q(t,n),isOffline:!1,versionToken:t?.versionToken,dataUpdatedAt:t?.storedAt,errorUpdatedAt:n}}function B(e,t,n){return{status:"auth-expired",fetchStatus:"idle",data:t?.data,error:e,cacheStatus:t===void 0?"empty":t.status,isStale:Q(t,n),isOffline:!1,versionToken:t?.versionToken,dataUpdatedAt:t?.storedAt,errorUpdatedAt:n}}function K(e,t,n){return{status:e===void 0?"idle":"success",fetchStatus:"idle",data:e?.data,cacheStatus:"conflict",isStale:Q(e,n),isOffline:!1,conflict:t,versionToken:t.versionToken??e?.versionToken,dataUpdatedAt:e?.storedAt}}function X(e,t){return{status:e===void 0?"idle":"success",fetchStatus:"idle",data:e?.data,cacheStatus:"offline",isStale:Q(e,t),isOffline:!0,versionToken:e?.versionToken,dataUpdatedAt:e?.storedAt,...e?.pageInfo===void 0?{}:{pageInfo:e.pageInfo}}}function ie(e,t){let{transport:n}=e,a=e.advanced??{},i=a.now??(()=>Date.now()),u=a.reachability??R("online"),r=a.events??A(),y=a.resolvers??F(),M=t??I({defaultMode:e.localOffline,env:e.env,flag:e.flag}),T=new Map,h=new Map,E=0;function S(v,w){T.set(v,w);for(let m of h.get(v)??[])m(w)}return{...{async query(v,w){let m=G(v),c=u.getSnapshot().signal;if(!O(c)){let l=X(void 0,i());return S(m,l),l}S(m,V(void 0,i()));let d=i(),s=await n.execute(v,w),p=i();if(!s.ok){r.emit({type:"fetch-error",key:m,code:s.code,latencyMs:p-d});let l=s.problem.category==="auth"?B(s.problem,void 0,p):j(s.problem,void 0,p);return S(m,l),l}r.emit({type:"fetch-success",key:m,latencyMs:p-d});let C={key:m,data:s.data.data,versionToken:s.data.versionToken??s.versionToken,status:c==="restricted"?"warm":"fresh",tags:[],storedAt:p,...s.data.pageInfo===void 0?{}:{pageInfo:s.data.pageInfo}},o=x(C,p);return S(m,o),o},getState(v){return T.get(G(v))??L()},subscribe(v,w){let m=G(v),c=h.get(m);if(c===void 0)c=new Set,h.set(m,c);return c.add(w),()=>c?.delete(w)},async invalidateTags(){return[]},async refresh(v){let w=T.get(v)??L();return S(v,w),w},async emitConflict(v,w){let m=K(void 0,w,i());return S(v,m),m}},...{async mutate(v,w={}){E+=1;let m=`${i()}-${E}`;if(!O(u.getSnapshot().signal))return{id:m,status:"disabled-offline",problem:he()};let c=await n.execute({operation:v.operation,input:v.input,tags:v.tags},w.ctx??a.contextProvider?.());if(c.ok)return{id:m,status:"done",data:c.data.data};if(c.problem.category==="auth")return{id:m,status:"paused-auth",problem:c.problem};return{id:m,status:"failed",problem:c.problem}},async drain(){},async resume(){},dispose(){}},maintenance:{collectGarbage:async()=>0,revalidateStale:async()=>0},events:r,resolvers:y,localOffline:M}}function he(){return{type:"about:blank",title:"Offline mutation queue disabled",status:409,code:"OFFLINE_QUEUE_DISABLED",category:"conflict",severity:"warning",retryable:!1,detail:"localOffline=online-only does not cache local data or queue offline mutations."}}import{createQueryKey as H}from"@lssm/lib.contracts-spec/query/key";function re(){let e=new Map;return{run(t,n){let a=e.get(t);if(a!==void 0)return a;let i=n().finally(()=>{e.delete(t)});return e.set(t,i),i},size(){return e.size}}}var Ee=0;function se(e){let{transport:t}=e,n=e.storage??_(),a=e.reachability??R("online"),i=e.now??(()=>Date.now()),u=e.defaultStaleTimeMs??Ee,r=e.cacheStore??U(n),y=e.events??A(),M=re(),T=new Map,h=new Map;function E(c,d){T.set(c,d);let s=h.get(c);if(s===void 0)return;for(let p of s)p(d)}async function S(c,d){let s=H(c),p=a.getSnapshot().signal,C=await r.read(s);if(!O(p)){let P=X(C,i());return E(s,P),P}if(C!==void 0&&!Q(C,i())){y.emit({type:"cache-hit",key:s});let P=x(C,i());return E(s,P),P}y.emit({type:"cache-miss",key:s}),E(s,V(C,i()));let o=i(),l=await M.run(s,()=>t.execute(c,d)),f=i();if(!l.ok){y.emit({type:"fetch-error",key:s,code:l.code,latencyMs:f-o});let P=l.problem.category==="auth"?B(l.problem,C,f):j(l.problem,C,f);return E(s,P),P}y.emit({type:"fetch-success",key:s,latencyMs:f-o});let g=c.cache?.staleTimeMs??u,k=c.cache?.cacheTimeMs,b={key:s,data:l.data.data,versionToken:l.data.versionToken??l.versionToken,status:p==="restricted"?"warm":"fresh",tags:c.tags??[],storedAt:f,staleAt:f+g,envelope:c,...k===void 0?{}:{expiresAt:f+k},...l.data.pageInfo===void 0?{}:{pageInfo:l.data.pageInfo}};await r.write(b);let J=x(b,f);return E(s,J),J}async function D(c){let d=await r.read(c),s=d===void 0?L():x(d,i());return E(c,s),s}async function q(c,d){let s=await r.read(c),p=K(s,d,i());return E(c,p),p}function v(c){return T.get(H(c))??L()}function w(c,d){let s=H(c),p=h.get(s);if(p===void 0)p=new Set,h.set(s,p);return p.add(d),()=>{h.get(s)?.delete(d)}}async function m(c){let d=await r.invalidate(c,i());for(let s of d){let p=await r.read(s);if(p!==void 0)E(s,x(p,i()))}return d}return{query:S,getState:v,subscribe:w,invalidateTags:m,refresh:D,emitConflict:q}}function gt(e){Se(e);let t=e.advanced??{},n=I({defaultMode:e.localOffline,env:e.env,flag:e.flag});if(we(n.mode,t),n.mode==="online-only")return ie(e,n);let a=t.now??(()=>Date.now()),i=t.storage??_(),u=t.events??A(),r=t.cacheStore??U(i),y=t.reachability??R("online"),M=t.resolvers??F(),T=oe(i),h=se({...t,transport:e.transport,now:a,storage:i,events:u,cacheStore:r,reachability:y}),E=ae({transport:e.transport,cache:r,queue:T,reachability:y,resolvers:M,events:u,now:a,maxAttempts:t.maxAttempts,queryEngine:h,contextProvider:t.contextProvider,refreshAuth:t.refreshAuth,schedule:t.schedule,backoff:t.backoff}),S=ee({cache:r,events:u,now:a,revalidate:(D)=>h.query(D)});return{...h,...E,maintenance:S,events:u,resolvers:M,localOffline:n}}function we(e,t){if(e==="offline-capable"){if(t.storage===void 0)throw Error("localOffline=offline-capable requires advanced.storage; pass a durable StoragePort or explicit platform storage adapter.");return}if(t.storage!==void 0)throw Error(`localOffline=${e} rejects advanced.storage; this mode must not use durable local persistence.`);if(t.cacheStore!==void 0)throw Error(`localOffline=${e} rejects advanced.cacheStore; this mode owns cache semantics.`)}function Se(e){let t=e;if(t.storage!==void 0)throw Error("Use advanced.storage instead of top-level storage.");if(t.cacheStore!==void 0)throw Error("Use advanced.cacheStore instead of top-level cacheStore.")}export{gt as createDataEngine};
@@ -0,0 +1 @@
1
+ function s(){let e=new Map;return{run(n,t){let r=e.get(n);if(r!==void 0)return r;let i=t().finally(()=>{e.delete(n)});return e.set(n,i),i},size(){return e.size}}}export{s as createInflightRegistry};
@@ -0,0 +1 @@
1
+ function i(){let t=new Set;return{emit(e){for(let n of t)n(e)},subscribe(e){return t.add(e),()=>{t.delete(e)}}}}export{i as createEngineEvents};
@@ -0,0 +1 @@
1
+ function W(e,t={}){let n=t.baseMs??200,a=t.factor??2,i=t.maxMs??30000,u=t.jitter??Math.random,r=Math.max(0,e-1),d=Math.min(i,n*a**r);return Math.round(d*(0.5+u()*0.5))}import{invalidationTagMatches as le}from"@lssm/lib.contracts-spec/query/invalidation";var re="cache:";function L(e){let t=new Map,n=(a)=>`${re}${a}`;return{read:(a)=>e.get(n(a)),write:async(a)=>{t.set(a.key,a.tags),await e.set(n(a.key),a)},remove:async(a)=>{t.delete(a),await e.remove(n(a))},entries:async()=>{let a=await e.keys(re),i=[];for(let u of a){let r=await e.get(u);if(r!==void 0)i.push(r)}return i},invalidate:async(a,i)=>{let u=[];for(let[r,d]of t.entries()){if(!d.some((h)=>a.some((E)=>le(h,E))))continue;let T=await e.get(n(r));if(T===void 0)continue;await e.set(n(r),{...T,status:"stale",staleAt:i}),u.push(r)}return u}}}function fe(e){let{serverData:t,localData:n}=e,a=e.mergeFields??[];if(typeof t!=="object"||t===null||typeof n!=="object"||n===null)return{outcome:"surface"};let i={...t},u=n;for(let r of a)if(r in u)i[r]=u[r];return{outcome:"merged",data:i}}function I(){let e=new Map;return{register(t,n){e.set(t,n)},has(t){return e.has(t)},async resolve(t){switch(t.strategy){case"server-wins":return{outcome:"use-server",data:t.serverData};case"client-wins":return{outcome:"use-client",data:t.localData};case"field-merge":return fe(t);case"surface":return{outcome:"surface"};default:{let n=t.policy.resolver,a=n===void 0?void 0:e.get(n);if(a===void 0)return{outcome:"surface"};return a(t)}}}}}import{defaultConflictPolicy as de}from"@lssm/lib.contracts-spec/query/conflict-policy";async function _(e,t){for(let n of e)if(n.previous===void 0)await t.remove(n.key);else await t.write(n.previous)}async function z(e,t,n){let a=e.conflictPolicy??de(),i=e.rollback[0]?.key,u=i===void 0?void 0:await n.cache.read(i),r=t.metadata?.serverData,d=await n.resolvers.resolve({strategy:a.strategy,policy:a,localData:u?.data,serverData:r,localVersion:e.versionToken,serverVersion:t.versionToken,mergeFields:a.mergeFields});switch(n.events.emit({type:"mutation-conflict",id:e.id,strategy:a.strategy,outcome:d.outcome}),d.outcome){case"use-server":{await _(e.rollback,n.cache),await n.cache.invalidate(e.tags,n.now());for(let M of e.rollback)await n.queryEngine?.refresh(M.key);return"resolved"}case"use-client":return await n.queue.update({...e,versionToken:t.versionToken,status:"pending"}),"re-enqueued";case"merged":{if(i!==void 0&&u!==void 0)await n.cache.write({...u,data:d.data,versionToken:t.versionToken,status:"warm",storedAt:n.now()}),await n.queryEngine?.refresh(i);return await n.queue.update({...e,versionToken:t.versionToken,status:"pending"}),"re-enqueued"}default:{if(i!==void 0)await n.queryEngine?.emitConflict(i,{versionToken:t.versionToken,serverData:r,clientData:u?.data,strategy:a.strategy});return"resolved"}}}var pe=new Set(["online-only","memory-cache","offline-capable"]),se={"online-only":"online-only",online:"online-only",disabled:"online-only",false:"online-only",off:"online-only","memory-cache":"memory-cache",memory:"memory-cache",cache:"memory-cache","offline-capable":"offline-capable",offline:"offline-capable",enabled:"offline-capable",true:"offline-capable",on:"offline-capable"};function Le(e){return typeof e==="string"&&pe.has(e)}function K(e={}){let t=e.defaultMode===void 0?{mode:"online-only",source:"default",reason:"No local/offline policy input was supplied."}:G(e.defaultMode,"explicit")??{mode:"online-only",source:"explicit"},n=G(me(e.env),"env",{allowUnknown:!0});return G(e.flag,"feature-flag")??n??t}function me(e){if(typeof e!=="object"||e===null)return e;if("CONTRACTSPEC_LOCAL_OFFLINE"in e)return e.CONTRACTSPEC_LOCAL_OFFLINE;if("mode"in e)return e;return}function G(e,t,n={}){if(e===void 0||e===null||e==="")return;if(typeof e==="boolean")return{mode:e?"offline-capable":"online-only",source:t};if(typeof e==="string"){let a=se[e.trim().toLowerCase()];if(a!==void 0)return{mode:a,source:t};if(n.allowUnknown)return}if(typeof e==="object"&&e!==null&&"mode"in e){let a=e,i=typeof a.mode==="string"?se[a.mode.trim().toLowerCase()]:void 0;if(i!==void 0)return{mode:i,source:t,...typeof a.reason==="string"?{reason:a.reason}:{}};if(n.allowUnknown)return}throw Error(`Unsupported localOffline policy value: ${String(e)}`)}function C(e){return e!=="offline"}function q(e="online"){let t={signal:e,since:Date.now()};return{getSnapshot:()=>t,subscribe:()=>()=>{}}}var _e={id:"docs.contracts-runtime-core.reachability",title:"Reachability input port (tri-state)",summary:"Engine-owned reachability input port; integrations feed it, the engine never imports them.",kind:"reference",visibility:"internal",route:"/docs/contracts-runtime-core/reachability",domain:"contracts-runtime-core",owners:["@contractspec-core"],tags:["contracts-runtime-core","reachability","offline","port"],body:"Tri-state OnlineSignal ('online' | 'restricted' | 'offline'). 'online' allows normal fetch + queue drain. 'restricted' is online-degraded: the engine fetches and drains the queue as if online but may mark results stale-eligible; it never suspends network nor activates the offline queue. Only 'offline' suspends outbound network and activates the durable offline mutation queue. The engine reads reachability solely through ReachabilitySource and MUST NOT import integrations/* — concrete sources (runtime-local networkReachability) are wired via an integration→port adapter (plan §2.3/§4.2, Architect finding 1). isNetworkAllowed mirrors runtime-local's outboundNetworkAllowed = reachability !== 'offline'. createStaticReachabilitySource('online') is the B1a default and online test fixture."};function X(){let e=new Map;return{get:async(t)=>{let n=e.get(t);return n===void 0?void 0:structuredClone(n)},set:async(t,n)=>{e.set(t,structuredClone(n))},remove:async(t)=>{e.delete(t)},keys:async(t)=>{let n=[...e.keys()];return t===void 0?n:n.filter((a)=>a.startsWith(t))},clear:async()=>{e.clear()}}}function P(){let e=new Set;return{emit(t){for(let n of e)n(t)},subscribe(t){return e.add(t),()=>{e.delete(t)}}}}function H(e){return{async collectGarbage(){let t=e.now(),n=0;for(let a of await e.cache.entries())if(a.expiresAt!==void 0&&t>=a.expiresAt)await e.cache.remove(a.key),n+=1;return e.events.emit({type:"gc-collected",evicted:n}),n},async revalidateStale(){let t=e.revalidate;if(t===void 0)return 0;let n=e.now(),a=0;for(let i of await e.cache.entries()){if(!(i.staleAt!==void 0&&n>=i.staleAt)||i.envelope===void 0)continue;await t(i.envelope),e.events.emit({type:"revalidated",key:i.key}),a+=1}return a}}}import{mergeSafeEconomicEvidenceRefIds as ye,parseSafeEconomicEvidenceRefId as ge}from"@lssm/lib.contracts-spec/operations";import{defaultConflictPolicy as ve}from"@lssm/lib.contracts-spec/query/conflict-policy";var he=5;function J(...e){return ye(...e)}function Ee(e){let t=ge(e);if(!t)throw Error("EconomicEvidenceInvalidRef: unsafe or invalid economic evidence ref");return t}function Y(e){let{transport:t,cache:n,queue:a,reachability:i,resolvers:u,events:r}=e,d=e.now??(()=>Date.now()),M=e.maxAttempts??he,T={cache:n,queue:a,resolvers:u,events:r,now:d,queryEngine:e.queryEngine},h=!1,E=0,S=null,D=new Map,j=(o,l=o.economicEvidenceRefs)=>({operation:o.operation,input:o.input,tags:o.tags,economicEvidenceRefs:l});async function v(o){let l=[];for(let f of o){let g=await n.read(f.key);l.push({key:f.key,previous:g}),await n.write({key:f.key,data:f.data,versionToken:f.versionToken??g?.versionToken,status:"warm",tags:g?.tags??[],storedAt:d(),staleAt:g?.staleAt,expiresAt:g?.expiresAt}),await e.queryEngine?.refresh(f.key)}return l}async function w(o,l){for(let f of o.rollback){let g=await n.read(f.key);if(g!==void 0)await n.write({...g,versionToken:l.versionToken??g.versionToken,status:"stale",staleAt:d()});await e.queryEngine?.refresh(f.key)}await n.invalidate(o.tags,d())}async function m(o){let l;try{l=J(o.economicEvidenceRefs)}catch{await _(o.rollback,n);for(let b of o.rollback)await e.queryEngine?.refresh(b.key);return await a.remove(o.id),r.emit({type:"mutation-failed",id:o.id,code:"ECONOMIC_EVIDENCE_INVALID_REF"}),D.set(o.id,{id:o.id,status:"failed",problem:{type:"about:blank",title:"Economic evidence ref rejected",status:422,code:"ECONOMIC_EVIDENCE_INVALID_REF",category:"validation",severity:"error",retryable:!1}}),!0}let f=o.attempts+1;await a.update({...o,status:"in-flight",attempts:f});let g=await t.execute(j(o,l),e.contextProvider?.());if(g.ok){let b=J(l,g.data.economicEvidenceRefs);if(await w(o,g.data),await a.remove(o.id),r.emit({type:"mutation-replayed",id:o.id,queueDepth:await a.depth()}),b.length>0)r.emit({type:"economic-evidence-attached",operationKey:o.operation.key,evidenceRefs:b.map(Ee)});return D.set(o.id,{id:o.id,status:"done",data:g.data.data,economicEvidenceRefs:b}),!0}let{problem:k}=g;if(k.category==="auth"){if(h=!0,await a.update({...o,status:"paused-auth",attempts:f}),r.emit({type:"auth-expired",id:o.id}),D.set(o.id,{id:o.id,status:"paused-auth",problem:k}),e.refreshAuth!==void 0&&await e.refreshAuth())return h=!1,await a.update({...o,status:"pending",attempts:f}),!0;return!1}if(k.category==="conflict"){if(await z(o,k,T)==="resolved")await a.remove(o.id),D.set(o.id,{id:o.id,status:"done",problem:k});return!0}if(k.retryable&&f<M){let b=W(f,e.backoff);return await a.update({...o,status:"failed",attempts:f}),r.emit({type:"mutation-retry",id:o.id,attempt:f,delayMs:b}),D.set(o.id,{id:o.id,status:"failed",problem:k}),e.schedule?.(()=>{p()},b),!0}await _(o.rollback,n);for(let b of o.rollback)await e.queryEngine?.refresh(b.key);return await a.remove(o.id),r.emit({type:"mutation-failed",id:o.id,code:g.code}),D.set(o.id,{id:o.id,status:"failed",problem:k}),!0}async function c(){if(h)return;if(!C(i.getSnapshot().signal))return;for(let o of await a.list()){if(o.status==="paused-auth")continue;if(!await m(o))return}r.emit({type:"queue-drained",remaining:await a.depth()})}function p(){if(S!==null)return S;return S=c().finally(()=>{S=null}),S}async function s(o,l={}){J(o.economicEvidenceRefs);let f=d();E+=1;let g=`${f}-${E}`,k=l.optimistic?await v(l.optimistic):[];if(await a.enqueue({...o,conflictPolicy:o.conflictPolicy??ve(),id:g,enqueuedAt:f,attempts:0,status:"pending",rollback:k}),r.emit({type:"mutation-enqueued",id:g,queueDepth:await a.depth()}),!h&&C(i.getSnapshot().signal))await p();return D.get(g)??{id:g,status:"pending"}}async function y(){h=!1;for(let o of await a.list())if(o.status==="paused-auth")await a.update({...o,status:"pending"});await p()}let O=i.subscribe((o)=>{if(!h&&C(o.signal))p()});return{mutate:s,drain:p,resume:y,dispose:O}}function Z(e){let t=(a)=>`queue:${a}`;async function n(){let a=await e.keys("queue:"),i=[];for(let u of a){let r=await e.get(u);if(r!==void 0)i.push(r)}return i.sort((u,r)=>u.enqueuedAt===r.enqueuedAt?u.id.localeCompare(r.id):u.enqueuedAt-r.enqueuedAt),i}return{enqueue:(a)=>e.set(t(a.id),a),update:(a)=>e.set(t(a.id),a),remove:(a)=>e.remove(t(a)),list:()=>n(),depth:async()=>(await e.keys("queue:")).length}}import{createQueryKey as ee}from"@lssm/lib.contracts-spec/query/key";function x(e,t){if(e?.staleAt===void 0)return!1;return t>=e.staleAt}function A(){return{status:"idle",fetchStatus:"idle",cacheStatus:"empty",isStale:!1,isOffline:!1}}function U(e,t){if(e===void 0)return{status:"loading",fetchStatus:"fetching",cacheStatus:"empty",isStale:!1,isOffline:!1};let n=x(e,t);return{status:"success",fetchStatus:"fetching",data:e.data,cacheStatus:n?"stale":e.status,isStale:n,isOffline:!1,versionToken:e.versionToken,dataUpdatedAt:e.storedAt,...e.pageInfo===void 0?{}:{pageInfo:e.pageInfo}}}function Q(e,t){let n=x(e,t);return{status:"success",fetchStatus:"idle",data:e.data,cacheStatus:n?"stale":e.status,isStale:n,isOffline:!1,versionToken:e.versionToken,dataUpdatedAt:e.storedAt,...e.pageInfo===void 0?{}:{pageInfo:e.pageInfo}}}function F(e,t,n){return{status:"error",fetchStatus:"idle",data:t?.data,error:e,cacheStatus:t===void 0?"empty":t.status,isStale:x(t,n),isOffline:!1,versionToken:t?.versionToken,dataUpdatedAt:t?.storedAt,errorUpdatedAt:n}}function N(e,t,n){return{status:"auth-expired",fetchStatus:"idle",data:t?.data,error:e,cacheStatus:t===void 0?"empty":t.status,isStale:x(t,n),isOffline:!1,versionToken:t?.versionToken,dataUpdatedAt:t?.storedAt,errorUpdatedAt:n}}function V(e,t,n){return{status:e===void 0?"idle":"success",fetchStatus:"idle",data:e?.data,cacheStatus:"conflict",isStale:x(e,n),isOffline:!1,conflict:t,versionToken:t.versionToken??e?.versionToken,dataUpdatedAt:e?.storedAt}}function B(e,t){return{status:e===void 0?"idle":"success",fetchStatus:"idle",data:e?.data,cacheStatus:"offline",isStale:x(e,t),isOffline:!0,versionToken:e?.versionToken,dataUpdatedAt:e?.storedAt,...e?.pageInfo===void 0?{}:{pageInfo:e.pageInfo}}}function ce(e,t){let{transport:n}=e,a=e.advanced??{},i=a.now??(()=>Date.now()),u=a.reachability??q("online"),r=a.events??P(),d=a.resolvers??I(),M=t??K({defaultMode:e.localOffline,env:e.env,flag:e.flag}),T=new Map,h=new Map,E=0;function S(v,w){T.set(v,w);for(let m of h.get(v)??[])m(w)}return{...{async query(v,w){let m=ee(v),c=u.getSnapshot().signal;if(!C(c)){let l=B(void 0,i());return S(m,l),l}S(m,U(void 0,i()));let p=i(),s=await n.execute(v,w),y=i();if(!s.ok){r.emit({type:"fetch-error",key:m,code:s.code,latencyMs:y-p});let l=s.problem.category==="auth"?N(s.problem,void 0,y):F(s.problem,void 0,y);return S(m,l),l}r.emit({type:"fetch-success",key:m,latencyMs:y-p});let O={key:m,data:s.data.data,versionToken:s.data.versionToken??s.versionToken,status:c==="restricted"?"warm":"fresh",tags:[],storedAt:y,...s.data.pageInfo===void 0?{}:{pageInfo:s.data.pageInfo}},o=Q(O,y);return S(m,o),o},getState(v){return T.get(ee(v))??A()},subscribe(v,w){let m=ee(v),c=h.get(m);if(c===void 0)c=new Set,h.set(m,c);return c.add(w),()=>c?.delete(w)},async invalidateTags(){return[]},async refresh(v){let w=T.get(v)??A();return S(v,w),w},async emitConflict(v,w){let m=V(void 0,w,i());return S(v,m),m}},...{async mutate(v,w={}){E+=1;let m=`${i()}-${E}`;if(!C(u.getSnapshot().signal))return{id:m,status:"disabled-offline",problem:we()};let c=await n.execute({operation:v.operation,input:v.input,tags:v.tags},w.ctx??a.contextProvider?.());if(c.ok)return{id:m,status:"done",data:c.data.data};if(c.problem.category==="auth")return{id:m,status:"paused-auth",problem:c.problem};return{id:m,status:"failed",problem:c.problem}},async drain(){},async resume(){},dispose(){}},maintenance:{collectGarbage:async()=>0,revalidateStale:async()=>0},events:r,resolvers:d,localOffline:M}}function we(){return{type:"about:blank",title:"Offline mutation queue disabled",status:409,code:"OFFLINE_QUEUE_DISABLED",category:"conflict",severity:"warning",retryable:!1,detail:"localOffline=online-only does not cache local data or queue offline mutations."}}import{createQueryKey as ne}from"@lssm/lib.contracts-spec/query/key";function te(){let e=new Map;return{run(t,n){let a=e.get(t);if(a!==void 0)return a;let i=n().finally(()=>{e.delete(t)});return e.set(t,i),i},size(){return e.size}}}var Se=0;function ae(e){let{transport:t}=e,n=e.storage??X(),a=e.reachability??q("online"),i=e.now??(()=>Date.now()),u=e.defaultStaleTimeMs??Se,r=e.cacheStore??L(n),d=e.events??P(),M=te(),T=new Map,h=new Map;function E(c,p){T.set(c,p);let s=h.get(c);if(s===void 0)return;for(let y of s)y(p)}async function S(c,p){let s=ne(c),y=a.getSnapshot().signal,O=await r.read(s);if(!C(y)){let R=B(O,i());return E(s,R),R}if(O!==void 0&&!x(O,i())){d.emit({type:"cache-hit",key:s});let R=Q(O,i());return E(s,R),R}d.emit({type:"cache-miss",key:s}),E(s,U(O,i()));let o=i(),l=await M.run(s,()=>t.execute(c,p)),f=i();if(!l.ok){d.emit({type:"fetch-error",key:s,code:l.code,latencyMs:f-o});let R=l.problem.category==="auth"?N(l.problem,O,f):F(l.problem,O,f);return E(s,R),R}d.emit({type:"fetch-success",key:s,latencyMs:f-o});let g=c.cache?.staleTimeMs??u,k=c.cache?.cacheTimeMs,b={key:s,data:l.data.data,versionToken:l.data.versionToken??l.versionToken,status:y==="restricted"?"warm":"fresh",tags:c.tags??[],storedAt:f,staleAt:f+g,envelope:c,...k===void 0?{}:{expiresAt:f+k},...l.data.pageInfo===void 0?{}:{pageInfo:l.data.pageInfo}};await r.write(b);let ie=Q(b,f);return E(s,ie),ie}async function D(c){let p=await r.read(c),s=p===void 0?A():Q(p,i());return E(c,s),s}async function j(c,p){let s=await r.read(c),y=V(s,p,i());return E(c,y),y}function v(c){return T.get(ne(c))??A()}function w(c,p){let s=ne(c),y=h.get(s);if(y===void 0)y=new Set,h.set(s,y);return y.add(p),()=>{h.get(s)?.delete(p)}}async function m(c){let p=await r.invalidate(c,i());for(let s of p){let y=await r.read(s);if(y!==void 0)E(s,Q(y,i()))}return p}return{query:S,getState:v,subscribe:w,invalidateTags:m,refresh:D,emitConflict:j}}function oe(e){Te(e);let t=e.advanced??{},n=K({defaultMode:e.localOffline,env:e.env,flag:e.flag});if(be(n.mode,t),n.mode==="online-only")return ce(e,n);let a=t.now??(()=>Date.now()),i=t.storage??X(),u=t.events??P(),r=t.cacheStore??L(i),d=t.reachability??q("online"),M=t.resolvers??I(),T=Z(i),h=ae({...t,transport:e.transport,now:a,storage:i,events:u,cacheStore:r,reachability:d}),E=Y({transport:e.transport,cache:r,queue:T,reachability:d,resolvers:M,events:u,now:a,maxAttempts:t.maxAttempts,queryEngine:h,contextProvider:t.contextProvider,refreshAuth:t.refreshAuth,schedule:t.schedule,backoff:t.backoff}),S=H({cache:r,events:u,now:a,revalidate:(D)=>h.query(D)});return{...h,...E,maintenance:S,events:u,resolvers:M,localOffline:n}}function be(e,t){if(e==="offline-capable"){if(t.storage===void 0)throw Error("localOffline=offline-capable requires advanced.storage; pass a durable StoragePort or explicit platform storage adapter.");return}if(t.storage!==void 0)throw Error(`localOffline=${e} rejects advanced.storage; this mode must not use durable local persistence.`);if(t.cacheStore!==void 0)throw Error(`localOffline=${e} rejects advanced.cacheStore; this mode owns cache semantics.`)}function Te(e){let t=e;if(t.storage!==void 0)throw Error("Use advanced.storage instead of top-level storage.");if(t.cacheStore!==void 0)throw Error("Use advanced.cacheStore instead of top-level cacheStore.")}function ue(){return globalThis.process?.env}function ke(e){return oe({...e,env:e.env??ue()})}function De(){return{read:async(e)=>{return},write:async()=>{},remove:async()=>{},entries:async()=>[],invalidate:async(e,t)=>[]}}function Me(){return{type:"https://contractspec.io/problems/offline-queue-disabled",title:"Offline mutation queue disabled",status:503,code:"OFFLINE_QUEUE_DISABLED",category:"policy",severity:"warning",retryable:!0,detail:"localOffline is online-only; offline mutations are not queued or replayed."}}var Oe=(e)=>({operation:e.operation,input:e.input,tags:e.tags});function Ce(e){let t=e.now??(()=>Date.now()),n=0;async function a(i,u={}){n+=1;let r=`${t()}-${n}`;if(!C(e.reachability.getSnapshot().signal))return{id:r,status:"disabled-offline",problem:Me()};let d=await e.transport.execute(Oe(i),u.ctx);if(d.ok)return{id:r,status:"done",data:d.data.data};return{id:r,status:"failed",problem:d.problem}}return{mutate:a,drain:async()=>{},resume:async()=>{},dispose:()=>{}}}export{N as authExpiredState,W as backoffDelayMs,x as computeIsStale,V as conflictState,L as createCacheStore,I as createConflictResolverRegistry,oe as createDataEngine,ke as createDataEngineFromEnv,P as createEngineEvents,te as createInflightRegistry,H as createMaintenance,Y as createMutationEngine,Z as createMutationQueue,De as createNoCacheStore,Ce as createOnlineOnlyMutationEngine,ae as createQueryEngine,F as errorState,A as idleState,U as loadingState,B as offlineState,ue as readHostEnv,z as resolveQueuedConflict,_ as restoreSnapshots,Q as successState};
@@ -0,0 +1 @@
1
+ function o(e){return{async collectGarbage(){let r=e.now(),n=0;for(let t of await e.cache.entries())if(t.expiresAt!==void 0&&r>=t.expiresAt)await e.cache.remove(t.key),n+=1;return e.events.emit({type:"gc-collected",evicted:n}),n},async revalidateStale(){let r=e.revalidate;if(r===void 0)return 0;let n=e.now(),t=0;for(let a of await e.cache.entries()){if(!(a.staleAt!==void 0&&n>=a.staleAt)||a.envelope===void 0)continue;await r(a.envelope),e.events.emit({type:"revalidated",key:a.key}),t+=1}return t}}}export{o as createMaintenance};
@@ -0,0 +1 @@
1
+ import{mergeSafeEconomicEvidenceRefIds as Q,parseSafeEconomicEvidenceRefId as F}from"@lssm/lib.contracts-spec/operations";import{defaultConflictPolicy as I}from"@lssm/lib.contracts-spec/query/conflict-policy";function g(t){return t!=="offline"}function U(t="online"){let n={signal:t,since:Date.now()};return{getSnapshot:()=>n,subscribe:()=>()=>{}}}var B={id:"docs.contracts-runtime-core.reachability",title:"Reachability input port (tri-state)",summary:"Engine-owned reachability input port; integrations feed it, the engine never imports them.",kind:"reference",visibility:"internal",route:"/docs/contracts-runtime-core/reachability",domain:"contracts-runtime-core",owners:["@contractspec-core"],tags:["contracts-runtime-core","reachability","offline","port"],body:"Tri-state OnlineSignal ('online' | 'restricted' | 'offline'). 'online' allows normal fetch + queue drain. 'restricted' is online-degraded: the engine fetches and drains the queue as if online but may mark results stale-eligible; it never suspends network nor activates the offline queue. Only 'offline' suspends outbound network and activates the durable offline mutation queue. The engine reads reachability solely through ReachabilitySource and MUST NOT import integrations/* — concrete sources (runtime-local networkReachability) are wired via an integration→port adapter (plan §2.3/§4.2, Architect finding 1). isNetworkAllowed mirrors runtime-local's outboundNetworkAllowed = reachability !== 'offline'. createStaticReachabilitySource('online') is the B1a default and online test fixture."};function M(t,n={}){let i=n.baseMs??200,a=n.factor??2,u=n.maxMs??30000,m=n.jitter??Math.random,s=Math.max(0,t-1),l=Math.min(u,i*a**s);return Math.round(l*(0.5+m()*0.5))}import{defaultConflictPolicy as _}from"@lssm/lib.contracts-spec/query/conflict-policy";async function w(t,n){for(let i of t)if(i.previous===void 0)await n.remove(i.key);else await n.write(i.previous)}async function R(t,n,i){let a=t.conflictPolicy??_(),u=t.rollback[0]?.key,m=u===void 0?void 0:await i.cache.read(u),s=n.metadata?.serverData,l=await i.resolvers.resolve({strategy:a.strategy,policy:a,localData:m?.data,serverData:s,localVersion:t.versionToken,serverVersion:n.versionToken,mergeFields:a.mergeFields});switch(i.events.emit({type:"mutation-conflict",id:t.id,strategy:a.strategy,outcome:l.outcome}),l.outcome){case"use-server":{await w(t.rollback,i.cache),await i.cache.invalidate(t.tags,i.now());for(let E of t.rollback)await i.queryEngine?.refresh(E.key);return"resolved"}case"use-client":return await i.queue.update({...t,versionToken:n.versionToken,status:"pending"}),"re-enqueued";case"merged":{if(u!==void 0&&m!==void 0)await i.cache.write({...m,data:l.data,versionToken:n.versionToken,status:"warm",storedAt:i.now()}),await i.queryEngine?.refresh(u);return await i.queue.update({...t,versionToken:n.versionToken,status:"pending"}),"re-enqueued"}default:{if(u!==void 0)await i.queryEngine?.emitConflict(u,{versionToken:n.versionToken,serverData:s,clientData:m?.data,strategy:a.strategy});return"resolved"}}}var L=5;function b(...t){return Q(...t)}function N(t){let n=F(t);if(!n)throw Error("EconomicEvidenceInvalidRef: unsafe or invalid economic evidence ref");return n}function Y(t){let{transport:n,cache:i,queue:a,reachability:u,resolvers:m,events:s}=t,l=t.now??(()=>Date.now()),E=t.maxAttempts??L,S={cache:i,queue:a,resolvers:m,events:s,now:l,queryEngine:t.queryEngine},h=!1,k=0,y=null,p=new Map,T=(e,c=e.economicEvidenceRefs)=>({operation:e.operation,input:e.input,tags:e.tags,economicEvidenceRefs:c});async function A(e){let c=[];for(let r of e){let o=await i.read(r.key);c.push({key:r.key,previous:o}),await i.write({key:r.key,data:r.data,versionToken:r.versionToken??o?.versionToken,status:"warm",tags:o?.tags??[],storedAt:l(),staleAt:o?.staleAt,expiresAt:o?.expiresAt}),await t.queryEngine?.refresh(r.key)}return c}async function D(e,c){for(let r of e.rollback){let o=await i.read(r.key);if(o!==void 0)await i.write({...o,versionToken:c.versionToken??o.versionToken,status:"stale",staleAt:l()});await t.queryEngine?.refresh(r.key)}await i.invalidate(e.tags,l())}async function q(e){let c;try{c=b(e.economicEvidenceRefs)}catch{await w(e.rollback,i);for(let d of e.rollback)await t.queryEngine?.refresh(d.key);return await a.remove(e.id),s.emit({type:"mutation-failed",id:e.id,code:"ECONOMIC_EVIDENCE_INVALID_REF"}),p.set(e.id,{id:e.id,status:"failed",problem:{type:"about:blank",title:"Economic evidence ref rejected",status:422,code:"ECONOMIC_EVIDENCE_INVALID_REF",category:"validation",severity:"error",retryable:!1}}),!0}let r=e.attempts+1;await a.update({...e,status:"in-flight",attempts:r});let o=await n.execute(T(e,c),t.contextProvider?.());if(o.ok){let d=b(c,o.data.economicEvidenceRefs);if(await D(e,o.data),await a.remove(e.id),s.emit({type:"mutation-replayed",id:e.id,queueDepth:await a.depth()}),d.length>0)s.emit({type:"economic-evidence-attached",operationKey:e.operation.key,evidenceRefs:d.map(N)});return p.set(e.id,{id:e.id,status:"done",data:o.data.data,economicEvidenceRefs:d}),!0}let{problem:f}=o;if(f.category==="auth"){if(h=!0,await a.update({...e,status:"paused-auth",attempts:r}),s.emit({type:"auth-expired",id:e.id}),p.set(e.id,{id:e.id,status:"paused-auth",problem:f}),t.refreshAuth!==void 0&&await t.refreshAuth())return h=!1,await a.update({...e,status:"pending",attempts:r}),!0;return!1}if(f.category==="conflict"){if(await R(e,f,S)==="resolved")await a.remove(e.id),p.set(e.id,{id:e.id,status:"done",problem:f});return!0}if(f.retryable&&r<E){let d=M(r,t.backoff);return await a.update({...e,status:"failed",attempts:r}),s.emit({type:"mutation-retry",id:e.id,attempt:r,delayMs:d}),p.set(e.id,{id:e.id,status:"failed",problem:f}),t.schedule?.(()=>{v()},d),!0}await w(e.rollback,i);for(let d of e.rollback)await t.queryEngine?.refresh(d.key);return await a.remove(e.id),s.emit({type:"mutation-failed",id:e.id,code:o.code}),p.set(e.id,{id:e.id,status:"failed",problem:f}),!0}async function x(){if(h)return;if(!g(u.getSnapshot().signal))return;for(let e of await a.list()){if(e.status==="paused-auth")continue;if(!await q(e))return}s.emit({type:"queue-drained",remaining:await a.depth()})}function v(){if(y!==null)return y;return y=x().finally(()=>{y=null}),y}async function C(e,c={}){b(e.economicEvidenceRefs);let r=l();k+=1;let o=`${r}-${k}`,f=c.optimistic?await A(c.optimistic):[];if(await a.enqueue({...e,conflictPolicy:e.conflictPolicy??I(),id:o,enqueuedAt:r,attempts:0,status:"pending",rollback:f}),s.emit({type:"mutation-enqueued",id:o,queueDepth:await a.depth()}),!h&&g(u.getSnapshot().signal))await v();return p.get(o)??{id:o,status:"pending"}}async function O(){h=!1;for(let e of await a.list())if(e.status==="paused-auth")await a.update({...e,status:"pending"});await v()}let P=u.subscribe((e)=>{if(!h&&g(e.signal))v()});return{mutate:C,drain:v,resume:O,dispose:P}}export{Y as createMutationEngine};
@@ -0,0 +1 @@
1
+ function s(t){let o=(e)=>`queue:${e}`;async function r(){let e=await t.keys("queue:"),i=[];for(let n of e){let u=await t.get(n);if(u!==void 0)i.push(u)}return i.sort((n,u)=>n.enqueuedAt===u.enqueuedAt?n.id.localeCompare(u.id):n.enqueuedAt-u.enqueuedAt),i}return{enqueue:(e)=>t.set(o(e.id),e),update:(e)=>t.set(o(e.id),e),remove:(e)=>t.remove(o(e)),list:()=>r(),depth:async()=>(await t.keys("queue:")).length}}export{s as createMutationQueue};
File without changes
@@ -0,0 +1 @@
1
+ function n(){return{read:async(e)=>{return},write:async()=>{},remove:async()=>{},entries:async()=>[],invalidate:async(e,a)=>[]}}export{n as createNoCacheStore};
@@ -0,0 +1 @@
1
+ import{createQueryKey as T}from"@lssm/lib.contracts-spec/query/key";var F=new Set(["online-only","memory-cache","offline-capable"]),O={"online-only":"online-only",online:"online-only",disabled:"online-only",false:"online-only",off:"online-only","memory-cache":"memory-cache",memory:"memory-cache",cache:"memory-cache","offline-capable":"offline-capable",offline:"offline-capable",enabled:"offline-capable",true:"offline-capable",on:"offline-capable"};function G(e){return typeof e==="string"&&F.has(e)}function D(e={}){let t=e.defaultMode===void 0?{mode:"online-only",source:"default",reason:"No local/offline policy input was supplied."}:b(e.defaultMode,"explicit")??{mode:"online-only",source:"explicit"},n=b(_(e.env),"env",{allowUnknown:!0});return b(e.flag,"feature-flag")??n??t}function _(e){if(typeof e!=="object"||e===null)return e;if("CONTRACTSPEC_LOCAL_OFFLINE"in e)return e.CONTRACTSPEC_LOCAL_OFFLINE;if("mode"in e)return e;return}function b(e,t,n={}){if(e===void 0||e===null||e==="")return;if(typeof e==="boolean")return{mode:e?"offline-capable":"online-only",source:t};if(typeof e==="string"){let o=O[e.trim().toLowerCase()];if(o!==void 0)return{mode:o,source:t};if(n.allowUnknown)return}if(typeof e==="object"&&e!==null&&"mode"in e){let o=e,l=typeof o.mode==="string"?O[o.mode.trim().toLowerCase()]:void 0;if(l!==void 0)return{mode:l,source:t,...typeof o.reason==="string"?{reason:o.reason}:{}};if(n.allowUnknown)return}throw Error(`Unsupported localOffline policy value: ${String(e)}`)}function S(e){return e!=="offline"}function C(e="online"){let t={signal:e,since:Date.now()};return{getSnapshot:()=>t,subscribe:()=>()=>{}}}var H={id:"docs.contracts-runtime-core.reachability",title:"Reachability input port (tri-state)",summary:"Engine-owned reachability input port; integrations feed it, the engine never imports them.",kind:"reference",visibility:"internal",route:"/docs/contracts-runtime-core/reachability",domain:"contracts-runtime-core",owners:["@contractspec-core"],tags:["contracts-runtime-core","reachability","offline","port"],body:"Tri-state OnlineSignal ('online' | 'restricted' | 'offline'). 'online' allows normal fetch + queue drain. 'restricted' is online-degraded: the engine fetches and drains the queue as if online but may mark results stale-eligible; it never suspends network nor activates the offline queue. Only 'offline' suspends outbound network and activates the durable offline mutation queue. The engine reads reachability solely through ReachabilitySource and MUST NOT import integrations/* — concrete sources (runtime-local networkReachability) are wired via an integration→port adapter (plan §2.3/§4.2, Architect finding 1). isNetworkAllowed mirrors runtime-local's outboundNetworkAllowed = reachability !== 'offline'. createStaticReachabilitySource('online') is the B1a default and online test fixture."};function j(e){let{serverData:t,localData:n}=e,o=e.mergeFields??[];if(typeof t!=="object"||t===null||typeof n!=="object"||n===null)return{outcome:"surface"};let l={...t},y=n;for(let u of o)if(u in y)l[u]=y[u];return{outcome:"merged",data:l}}function R(){let e=new Map;return{register(t,n){e.set(t,n)},has(t){return e.has(t)},async resolve(t){switch(t.strategy){case"server-wins":return{outcome:"use-server",data:t.serverData};case"client-wins":return{outcome:"use-client",data:t.localData};case"field-merge":return j(t);case"surface":return{outcome:"surface"};default:{let n=t.policy.resolver,o=n===void 0?void 0:e.get(n);if(o===void 0)return{outcome:"surface"};return o(t)}}}}}function L(){let e=new Set;return{emit(t){for(let n of e)n(t)},subscribe(t){return e.add(t),()=>{e.delete(t)}}}}function p(e,t){if(e?.staleAt===void 0)return!1;return t>=e.staleAt}function v(){return{status:"idle",fetchStatus:"idle",cacheStatus:"empty",isStale:!1,isOffline:!1}}function x(e,t){if(e===void 0)return{status:"loading",fetchStatus:"fetching",cacheStatus:"empty",isStale:!1,isOffline:!1};let n=p(e,t);return{status:"success",fetchStatus:"fetching",data:e.data,cacheStatus:n?"stale":e.status,isStale:n,isOffline:!1,versionToken:e.versionToken,dataUpdatedAt:e.storedAt,...e.pageInfo===void 0?{}:{pageInfo:e.pageInfo}}}function A(e,t){let n=p(e,t);return{status:"success",fetchStatus:"idle",data:e.data,cacheStatus:n?"stale":e.status,isStale:n,isOffline:!1,versionToken:e.versionToken,dataUpdatedAt:e.storedAt,...e.pageInfo===void 0?{}:{pageInfo:e.pageInfo}}}function M(e,t,n){return{status:"error",fetchStatus:"idle",data:t?.data,error:e,cacheStatus:t===void 0?"empty":t.status,isStale:p(t,n),isOffline:!1,versionToken:t?.versionToken,dataUpdatedAt:t?.storedAt,errorUpdatedAt:n}}function Q(e,t,n){return{status:"auth-expired",fetchStatus:"idle",data:t?.data,error:e,cacheStatus:t===void 0?"empty":t.status,isStale:p(t,n),isOffline:!1,versionToken:t?.versionToken,dataUpdatedAt:t?.storedAt,errorUpdatedAt:n}}function P(e,t,n){return{status:e===void 0?"idle":"success",fetchStatus:"idle",data:e?.data,cacheStatus:"conflict",isStale:p(e,n),isOffline:!1,conflict:t,versionToken:t.versionToken??e?.versionToken,dataUpdatedAt:e?.storedAt}}function I(e,t){return{status:e===void 0?"idle":"success",fetchStatus:"idle",data:e?.data,cacheStatus:"offline",isStale:p(e,t),isOffline:!0,versionToken:e?.versionToken,dataUpdatedAt:e?.storedAt,...e?.pageInfo===void 0?{}:{pageInfo:e.pageInfo}}}function ie(e,t){let{transport:n}=e,o=e.advanced??{},l=o.now??(()=>Date.now()),y=o.reachability??C("online"),u=o.events??L(),q=o.resolvers??R(),U=t??D({defaultMode:e.localOffline,env:e.env,flag:e.flag}),g=new Map,h=new Map,w=0;function f(i,r){g.set(i,r);for(let a of h.get(i)??[])a(r)}return{...{async query(i,r){let a=T(i),s=y.getSnapshot().signal;if(!S(s)){let m=I(void 0,l());return f(a,m),m}f(a,x(void 0,l()));let k=l(),c=await n.execute(i,r),d=l();if(!c.ok){u.emit({type:"fetch-error",key:a,code:c.code,latencyMs:d-k});let m=c.problem.category==="auth"?Q(c.problem,void 0,d):M(c.problem,void 0,d);return f(a,m),m}u.emit({type:"fetch-success",key:a,latencyMs:d-k});let N={key:a,data:c.data.data,versionToken:c.data.versionToken??c.versionToken,status:s==="restricted"?"warm":"fresh",tags:[],storedAt:d,...c.data.pageInfo===void 0?{}:{pageInfo:c.data.pageInfo}},E=A(N,d);return f(a,E),E},getState(i){return g.get(T(i))??v()},subscribe(i,r){let a=T(i),s=h.get(a);if(s===void 0)s=new Set,h.set(a,s);return s.add(r),()=>s?.delete(r)},async invalidateTags(){return[]},async refresh(i){let r=g.get(i)??v();return f(i,r),r},async emitConflict(i,r){let a=P(void 0,r,l());return f(i,a),a}},...{async mutate(i,r={}){w+=1;let a=`${l()}-${w}`;if(!S(y.getSnapshot().signal))return{id:a,status:"disabled-offline",problem:B()};let s=await n.execute({operation:i.operation,input:i.input,tags:i.tags},r.ctx??o.contextProvider?.());if(s.ok)return{id:a,status:"done",data:s.data.data};if(s.problem.category==="auth")return{id:a,status:"paused-auth",problem:s.problem};return{id:a,status:"failed",problem:s.problem}},async drain(){},async resume(){},dispose(){}},maintenance:{collectGarbage:async()=>0,revalidateStale:async()=>0},events:u,resolvers:q,localOffline:U}}function B(){return{type:"about:blank",title:"Offline mutation queue disabled",status:409,code:"OFFLINE_QUEUE_DISABLED",category:"conflict",severity:"warning",retryable:!1,detail:"localOffline=online-only does not cache local data or queue offline mutations."}}export{ie as createOnlineOnlyDataEngine};
@@ -0,0 +1 @@
1
+ function a(e){return e!=="offline"}function p(e="online"){let t={signal:e,since:Date.now()};return{getSnapshot:()=>t,subscribe:()=>()=>{}}}var d={id:"docs.contracts-runtime-core.reachability",title:"Reachability input port (tri-state)",summary:"Engine-owned reachability input port; integrations feed it, the engine never imports them.",kind:"reference",visibility:"internal",route:"/docs/contracts-runtime-core/reachability",domain:"contracts-runtime-core",owners:["@contractspec-core"],tags:["contracts-runtime-core","reachability","offline","port"],body:"Tri-state OnlineSignal ('online' | 'restricted' | 'offline'). 'online' allows normal fetch + queue drain. 'restricted' is online-degraded: the engine fetches and drains the queue as if online but may mark results stale-eligible; it never suspends network nor activates the offline queue. Only 'offline' suspends outbound network and activates the durable offline mutation queue. The engine reads reachability solely through ReachabilitySource and MUST NOT import integrations/* — concrete sources (runtime-local networkReachability) are wired via an integration→port adapter (plan §2.3/§4.2, Architect finding 1). isNetworkAllowed mirrors runtime-local's outboundNetworkAllowed = reachability !== 'offline'. createStaticReachabilitySource('online') is the B1a default and online test fixture."};function c(){return{type:"https://contractspec.io/problems/offline-queue-disabled",title:"Offline mutation queue disabled",status:503,code:"OFFLINE_QUEUE_DISABLED",category:"policy",severity:"warning",retryable:!0,detail:"localOffline is online-only; offline mutations are not queued or replayed."}}var u=(e)=>({operation:e.operation,input:e.input,tags:e.tags});function y(e){let t=e.now??(()=>Date.now()),o=0;async function r(s,l={}){o+=1;let n=`${t()}-${o}`;if(!a(e.reachability.getSnapshot().signal))return{id:n,status:"disabled-offline",problem:c()};let i=await e.transport.execute(u(s),l.ctx);if(i.ok)return{id:n,status:"done",data:i.data.data};return{id:n,status:"failed",problem:i.problem}}return{mutate:r,drain:async()=>{},resume:async()=>{},dispose:()=>{}}}export{y as createOnlineOnlyMutationEngine};
@@ -0,0 +1 @@
1
+ import{createQueryKey as w}from"@lssm/lib.contracts-spec/query/key";function Q(e){return e!=="offline"}function A(e="online"){let t={signal:e,since:Date.now()};return{getSnapshot:()=>t,subscribe:()=>()=>{}}}var G={id:"docs.contracts-runtime-core.reachability",title:"Reachability input port (tri-state)",summary:"Engine-owned reachability input port; integrations feed it, the engine never imports them.",kind:"reference",visibility:"internal",route:"/docs/contracts-runtime-core/reachability",domain:"contracts-runtime-core",owners:["@contractspec-core"],tags:["contracts-runtime-core","reachability","offline","port"],body:"Tri-state OnlineSignal ('online' | 'restricted' | 'offline'). 'online' allows normal fetch + queue drain. 'restricted' is online-degraded: the engine fetches and drains the queue as if online but may mark results stale-eligible; it never suspends network nor activates the offline queue. Only 'offline' suspends outbound network and activates the durable offline mutation queue. The engine reads reachability solely through ReachabilitySource and MUST NOT import integrations/* — concrete sources (runtime-local networkReachability) are wired via an integration→port adapter (plan §2.3/§4.2, Architect finding 1). isNetworkAllowed mirrors runtime-local's outboundNetworkAllowed = reachability !== 'offline'. createStaticReachabilitySource('online') is the B1a default and online test fixture."};function P(){let e=new Map;return{get:async(t)=>{let n=e.get(t);return n===void 0?void 0:structuredClone(n)},set:async(t,n)=>{e.set(t,structuredClone(n))},remove:async(t)=>{e.delete(t)},keys:async(t)=>{let n=[...e.keys()];return t===void 0?n:n.filter((r)=>r.startsWith(t))},clear:async()=>{e.clear()}}}import{invalidationTagMatches as W}from"@lssm/lib.contracts-spec/query/invalidation";var I="cache:";function R(e){let t=new Map,n=(r)=>`${I}${r}`;return{read:(r)=>e.get(n(r)),write:async(r)=>{t.set(r.key,r.tags),await e.set(n(r.key),r)},remove:async(r)=>{t.delete(r),await e.remove(n(r))},entries:async()=>{let r=await e.keys(I),s=[];for(let g of r){let u=await e.get(g);if(u!==void 0)s.push(u)}return s},invalidate:async(r,s)=>{let g=[];for(let[u,h]of t.entries()){if(!h.some((T)=>r.some((l)=>W(T,l))))continue;let S=await e.get(n(u));if(S===void 0)continue;await e.set(n(u),{...S,status:"stale",staleAt:s}),g.push(u)}return g}}}function M(){let e=new Map;return{run(t,n){let r=e.get(t);if(r!==void 0)return r;let s=n().finally(()=>{e.delete(t)});return e.set(t,s),s},size(){return e.size}}}function O(){let e=new Set;return{emit(t){for(let n of e)n(t)},subscribe(t){return e.add(t),()=>{e.delete(t)}}}}function m(e,t){if(e?.staleAt===void 0)return!1;return t>=e.staleAt}function v(){return{status:"idle",fetchStatus:"idle",cacheStatus:"empty",isStale:!1,isOffline:!1}}function q(e,t){if(e===void 0)return{status:"loading",fetchStatus:"fetching",cacheStatus:"empty",isStale:!1,isOffline:!1};let n=m(e,t);return{status:"success",fetchStatus:"fetching",data:e.data,cacheStatus:n?"stale":e.status,isStale:n,isOffline:!1,versionToken:e.versionToken,dataUpdatedAt:e.storedAt,...e.pageInfo===void 0?{}:{pageInfo:e.pageInfo}}}function b(e,t){let n=m(e,t);return{status:"success",fetchStatus:"idle",data:e.data,cacheStatus:n?"stale":e.status,isStale:n,isOffline:!1,versionToken:e.versionToken,dataUpdatedAt:e.storedAt,...e.pageInfo===void 0?{}:{pageInfo:e.pageInfo}}}function L(e,t,n){return{status:"error",fetchStatus:"idle",data:t?.data,error:e,cacheStatus:t===void 0?"empty":t.status,isStale:m(t,n),isOffline:!1,versionToken:t?.versionToken,dataUpdatedAt:t?.storedAt,errorUpdatedAt:n}}function V(e,t,n){return{status:"auth-expired",fetchStatus:"idle",data:t?.data,error:e,cacheStatus:t===void 0?"empty":t.status,isStale:m(t,n),isOffline:!1,versionToken:t?.versionToken,dataUpdatedAt:t?.storedAt,errorUpdatedAt:n}}function U(e,t,n){return{status:e===void 0?"idle":"success",fetchStatus:"idle",data:e?.data,cacheStatus:"conflict",isStale:m(e,n),isOffline:!1,conflict:t,versionToken:t.versionToken??e?.versionToken,dataUpdatedAt:e?.storedAt}}function N(e,t){return{status:e===void 0?"idle":"success",fetchStatus:"idle",data:e?.data,cacheStatus:"offline",isStale:m(e,t),isOffline:!0,versionToken:e?.versionToken,dataUpdatedAt:e?.storedAt,...e?.pageInfo===void 0?{}:{pageInfo:e.pageInfo}}}var X=0;function de(e){let{transport:t}=e,n=e.storage??P(),r=e.reachability??A("online"),s=e.now??(()=>Date.now()),g=e.defaultStaleTimeMs??X,u=e.cacheStore??R(n),h=e.events??O(),D=M(),S=new Map,T=new Map;function l(i,o){S.set(i,o);let a=T.get(i);if(a===void 0)return;for(let c of a)c(o)}async function K(i,o){let a=w(i),c=r.getSnapshot().signal,y=await u.read(a);if(!Q(c)){let p=N(y,s());return l(a,p),p}if(y!==void 0&&!m(y,s())){h.emit({type:"cache-hit",key:a});let p=b(y,s());return l(a,p),p}h.emit({type:"cache-miss",key:a}),l(a,q(y,s()));let k=s(),d=await D.run(a,()=>t.execute(i,o)),f=s();if(!d.ok){h.emit({type:"fetch-error",key:a,code:d.code,latencyMs:f-k});let p=d.problem.category==="auth"?V(d.problem,y,f):L(d.problem,y,f);return l(a,p),p}h.emit({type:"fetch-success",key:a,latencyMs:f-k});let H=i.cache?.staleTimeMs??g,E=i.cache?.cacheTimeMs,C={key:a,data:d.data.data,versionToken:d.data.versionToken??d.versionToken,status:c==="restricted"?"warm":"fresh",tags:i.tags??[],storedAt:f,staleAt:f+H,envelope:i,...E===void 0?{}:{expiresAt:f+E},...d.data.pageInfo===void 0?{}:{pageInfo:d.data.pageInfo}};await u.write(C);let x=b(C,f);return l(a,x),x}async function _(i){let o=await u.read(i),a=o===void 0?v():b(o,s());return l(i,a),a}async function z(i,o){let a=await u.read(i),c=U(a,o,s());return l(i,c),c}function B(i){return S.get(w(i))??v()}function F(i,o){let a=w(i),c=T.get(a);if(c===void 0)c=new Set,T.set(a,c);return c.add(o),()=>{T.get(a)?.delete(o)}}async function j(i){let o=await u.invalidate(i,s());for(let a of o){let c=await u.read(a);if(c!==void 0)l(a,b(c,s()))}return o}return{query:K,getState:B,subscribe:F,invalidateTags:j,refresh:_,emitConflict:z}}export{de as createQueryEngine};
@@ -0,0 +1 @@
1
+ function s(t,e){if(t?.staleAt===void 0)return!1;return e>=t.staleAt}function n(){return{status:"idle",fetchStatus:"idle",cacheStatus:"empty",isStale:!1,isOffline:!1}}function u(t,e){if(t===void 0)return{status:"loading",fetchStatus:"fetching",cacheStatus:"empty",isStale:!1,isOffline:!1};let a=s(t,e);return{status:"success",fetchStatus:"fetching",data:t.data,cacheStatus:a?"stale":t.status,isStale:a,isOffline:!1,versionToken:t.versionToken,dataUpdatedAt:t.storedAt,...t.pageInfo===void 0?{}:{pageInfo:t.pageInfo}}}function o(t,e){let a=s(t,e);return{status:"success",fetchStatus:"idle",data:t.data,cacheStatus:a?"stale":t.status,isStale:a,isOffline:!1,versionToken:t.versionToken,dataUpdatedAt:t.storedAt,...t.pageInfo===void 0?{}:{pageInfo:t.pageInfo}}}function i(t,e,a){return{status:"error",fetchStatus:"idle",data:e?.data,error:t,cacheStatus:e===void 0?"empty":e.status,isStale:s(e,a),isOffline:!1,versionToken:e?.versionToken,dataUpdatedAt:e?.storedAt,errorUpdatedAt:a}}function d(t,e,a){return{status:"auth-expired",fetchStatus:"idle",data:e?.data,error:t,cacheStatus:e===void 0?"empty":e.status,isStale:s(e,a),isOffline:!1,versionToken:e?.versionToken,dataUpdatedAt:e?.storedAt,errorUpdatedAt:a}}function f(t,e,a){return{status:t===void 0?"idle":"success",fetchStatus:"idle",data:t?.data,cacheStatus:"conflict",isStale:s(t,a),isOffline:!1,conflict:e,versionToken:e.versionToken??t?.versionToken,dataUpdatedAt:t?.storedAt}}function r(t,e){return{status:t===void 0?"idle":"success",fetchStatus:"idle",data:t?.data,cacheStatus:"offline",isStale:s(t,e),isOffline:!0,versionToken:t?.versionToken,dataUpdatedAt:t?.storedAt,...t?.pageInfo===void 0?{}:{pageInfo:t.pageInfo}}}export{d as authExpiredState,s as computeIsStale,f as conflictState,i as errorState,n as idleState,u as loadingState,r as offlineState,o as successState};
File without changes
@@ -0,0 +1 @@
1
+ import{flattenPortableFormFields as p}from"@lssm/lib.contracts-spec/forms";function u(e){let r=new Set(e.questions.map(({name:o})=>o)),l=e.questions.map(c),s=new Set(e.formSpec?.policy?.pii??[]),m=p(e.formSpec?.fields??[]),a=Object.entries(e.formSpec?.modelFields??{}).flatMap(([o,i])=>{if(r.has(o))return[];let t=m.find((n)=>n.name===o);return[{id:o,labelKey:t?.labelI18n??o,sensitive:s.has(o)||[...s].some((n)=>n.startsWith(`${o}.`))||t?.kind==="email"||t?.kind==="phone"||i.type==="email"||i.type==="phone"}]});return[...l,...a]}function c(e){return{id:e.id,labelKey:e.labelKey,sensitive:e.sensitive===!0||e.kind==="email"||e.kind==="phone"}}export{u as formCsvColumns};
@@ -0,0 +1,2 @@
1
+ import{flattenPortableFormFields as v}from"@lssm/lib.contracts-spec/forms";function u(e){let o=new Set(e.questions.map(({name:t})=>t)),n=e.questions.map(y),r=new Set(e.formSpec?.policy?.pii??[]),i=v(e.formSpec?.fields??[]),m=Object.entries(e.formSpec?.modelFields??{}).flatMap(([t,c])=>{if(o.has(t))return[];let s=i.find((p)=>p.name===t);return[{id:t,labelKey:s?.labelI18n??t,sensitive:r.has(t)||[...r].some((p)=>p.startsWith(`${t}.`))||s?.kind==="email"||s?.kind==="phone"||c.type==="email"||c.type==="phone"}]});return[...n,...m]}function y(e){return{id:e.id,labelKey:e.labelKey,sensitive:e.sensitive===!0||e.kind==="email"||e.kind==="phone"}}import{compileFormDocument as g,validateFormDocument as R}from"@lssm/lib.contracts-spec/forms";class a extends Error{code;constructor(e,o){super(o);this.code=e;this.name="FormsPlatformError"}}function O(e,o){let n=e?.owner.product===o.product&&e.owner.tenantRef===o.tenantRef&&e.owner.workspaceRef===o.workspaceRef&&e.owner.ownerRef===o.ownerRef;if(!e||!n)throw new a("FORM_NOT_FOUND","Form definition was not found in the caller scope");return e}function P(e){let o=R(e);if(o.length)throw new a("INVALID_FORM_DOCUMENT",o.map((n)=>n.message).join("; "));g(e)}function b(e,o){if(o==="none")return!0;if(o==="either")return e!=="anonymous";if(o==="both")return e==="both";return e===o||e==="both"}function x(e,o){if(b(o,e.verification.requirement))return"completed";return e.verification.unverifiedDisposition==="pending-hidden"?"pending-verification":"completed-unverified"}function f(e,o){let n=new Set(e.content.enabledLocales.map((r)=>r.toLowerCase()));for(let r of o){if(!r)continue;let i=r.trim().toLowerCase(),m=e.content.enabledLocales.find((s)=>s.toLowerCase()===i);if(n.has(i)&&m)return m;let t=i.split("-")[0],c=e.content.enabledLocales.find((s)=>s.toLowerCase().split("-")[0]===t);if(c)return c}return e.content.defaultLocale}var D="response_extensions:AI follow-ups";function w(e){let o=Array.isArray(e)?e.every((r)=>typeof r!=="object")?e.join(";"):JSON.stringify(e):e==null?"":typeof e==="object"?JSON.stringify(e):String(e);return`"${(/^[\s]*[=+\-@]/.test(o)?`'${o}`:o).replaceAll('"','""')}"`}function l(e){return`${e.map(w).join(",")}\r
2
+ `}function d(e,o,n){if(o.revisionId!==e.id)throw Error("CSV responses must belong to the exported revision");let r=u(e.document),i=new Set(r.map(({id:t})=>t)),m=Object.fromEntries(Object.entries(o.answers).filter(([t])=>!i.has(t)));return[o.id,o.status,o.locale,o.submittedAt??"",...r.map((t)=>{if(!(n.includeSensitive&&n.sensitiveGrant?.authorized)&&t.sensitive)return"[REDACTED]";return o.answers[t.id]}),n.includeSensitive&&n.sensitiveGrant?.authorized?m:"[REDACTED]"]}function F(e,o){let n=f(e.document,[o]),r=e.document.content.catalogs[n]??{};return["response_id","status","locale","submitted_at",...u(e.document).map((i)=>`${i.id}:${r[i.labelKey]??i.labelKey}`),D]}function _(e,o,n={}){return`\uFEFF${l(F(e,n.locale))}${o.map((r)=>l(d(e,r,n))).join("")}`}async function*N(e,o,n={}){yield`\uFEFF${l(F(e,n.locale))}`;for await(let r of o)yield l(d(e,r,n))}export{_ as serializeFormResponsesCsv,N as streamFormResponsesCsv};
@@ -0,0 +1 @@
1
+ class a extends Error{code;constructor(o,e){super(e);this.code=o;this.name="FormsPlatformError"}}import{compileFormDocument as l,validateFormDocument as p}from"@lssm/lib.contracts-spec/forms";function f(o,e){let t=o?.owner.product===e.product&&o.owner.tenantRef===e.tenantRef&&o.owner.workspaceRef===e.workspaceRef&&o.owner.ownerRef===e.ownerRef;if(!o||!t)throw new a("FORM_NOT_FOUND","Form definition was not found in the caller scope");return o}function d(o){let e=p(o);if(e.length)throw new a("INVALID_FORM_DOCUMENT",e.map((t)=>t.message).join("; "));l(o)}function w(o,e){if(e==="none")return!0;if(e==="either")return o!=="anonymous";if(e==="both")return o==="both";return o===e||o==="both"}function R(o,e){if(w(e,o.verification.requirement))return"completed";return o.verification.unverifiedDisposition==="pending-hidden"?"pending-verification":"completed-unverified"}function h(o,e){let t=new Set(o.content.enabledLocales.map((r)=>r.toLowerCase()));for(let r of e){if(!r)continue;let n=r.trim().toLowerCase(),i=o.content.enabledLocales.find((c)=>c.toLowerCase()===n);if(t.has(n)&&i)return i;let s=n.split("-")[0],m=o.content.enabledLocales.find((c)=>c.toLowerCase().split("-")[0]===s);if(m)return m}return o.content.defaultLocale}function P(o){let e=async(t,r)=>o.emit?.(t,r);return{async create(t,r){d(r);let n=o.now(),i={id:o.id("definition"),owner:t,status:"draft",draft:r,draftVersion:1,createdAt:n,updatedAt:n};return await o.store.insertDefinition(i),await e("forms.definition.created",{definitionId:i.id,occurredAt:n}),i},async saveDraft(t,r,n,i){d(i);let s=f(await o.store.getDefinition(t,r),t);if(s.status==="archived")throw new a("FORM_ARCHIVED","Archived forms cannot be edited");let m={...s,draft:i,draftVersion:n+1,updatedAt:o.now()};if(!await o.store.updateDefinition(m,n))throw new a("DRAFT_CONFLICT","The form draft changed; reload before saving");return await e("forms.draft.saved",{definitionId:r,occurredAt:m.updatedAt}),m},async publish(t,r,n){return o.store.transaction(async(i)=>{let s=f(await i.getDefinition(t,r),t);if(s.draftVersion!==n)throw new a("DRAFT_CONFLICT","The form draft changed before publish");d(s.draft);let m=s.publishedRevisionId?await i.getRevision(s.publishedRevisionId):void 0,c=o.now(),u={id:o.id("revision"),definitionId:r,revision:(m?.revision??0)+1,document:structuredClone(s.draft),digest:await o.digest(JSON.stringify(s.draft)),publishedAt:c},F={...s,status:"published",publishedRevisionId:u.id,publicToken:s.publicToken??o.publicToken(),updatedAt:c};if(await i.insertRevision(u),!await i.updateDefinition(F,n))throw new a("DRAFT_CONFLICT","The form changed during publish");return await e("forms.definition.published",{definitionId:r,revisionId:u.id,occurredAt:c}),{definition:F,revision:u}})},async close(t,r){let n=f(await o.store.getDefinition(t,r),t);if(n.status!=="published")throw new a("FORM_NOT_PUBLISHED","Only a published form can be closed");let i={...n,status:"closed",updatedAt:o.now()};return await o.store.updateDefinition(i),await e("forms.definition.closed",{definitionId:r,occurredAt:i.updatedAt}),i},async archive(t,r){let n=f(await o.store.getDefinition(t,r),t);if(n.status==="archived")return n;let i={...n,status:"archived",updatedAt:o.now()};return await o.store.updateDefinition(i),await e("forms.definition.archived",{definitionId:r,occurredAt:i.updatedAt}),i}}}export{P as createFormsManagementService};
@@ -0,0 +1 @@
1
+ import{evalPredicate as s}from"@lssm/lib.contracts-spec/forms";class n extends Error{code;constructor(e,i){super(i);this.code=e;this.name="FormsPlatformError"}}function p(e,i,t){let o=e.pages.findIndex((r)=>r.id===i);if(o<0)throw new n("PAGE_NOT_FOUND","Current form page does not exist");return e.pages[o]?.nextPageRules?.find((r)=>s(t,r.when))?.nextPageId??e.pages[o]?.defaultNextPageId??e.pages[o+1]?.id}export{p as resolveNextFormPage};
@@ -0,0 +1 @@
1
+ import{buildZodWithRelations as b,compileFormDocument as y,FORM_AI_FULL_DATA_CONSENT_NOTICE_VERSION as I}from"@lssm/lib.contracts-spec/forms";class s extends Error{code;constructor(e,o){super(o);this.code=e;this.name="FormsPlatformError"}}import{compileFormDocument as R,validateFormDocument as g}from"@lssm/lib.contracts-spec/forms";function N(e,o){let r=e?.owner.product===o.product&&e.owner.tenantRef===o.tenantRef&&e.owner.workspaceRef===o.workspaceRef&&e.owner.ownerRef===o.ownerRef;if(!e||!r)throw new s("FORM_NOT_FOUND","Form definition was not found in the caller scope");return e}function _(e){let o=g(e);if(o.length)throw new s("INVALID_FORM_DOCUMENT",o.map((r)=>r.message).join("; "));R(e)}function f(e,o){if(o==="none")return!0;if(o==="either")return e!=="anonymous";if(o==="both")return e==="both";return e===o||e==="both"}function F(e,o){if(f(o,e.verification.requirement))return"completed";return e.verification.unverifiedDisposition==="pending-hidden"?"pending-verification":"completed-unverified"}function l(e,o){let r=new Set(e.content.enabledLocales.map((n)=>n.toLowerCase()));for(let n of o){if(!n)continue;let t=n.trim().toLowerCase(),m=e.content.enabledLocales.find((c)=>c.toLowerCase()===t);if(r.has(t)&&m)return m;let a=t.split("-")[0],i=e.content.enabledLocales.find((c)=>c.toLowerCase().split("-")[0]===a);if(i)return i}return e.content.defaultLocale}function D(e,o){let r=new Map(e.questions.map((i)=>[i.id,i])),n=new Set(Object.keys(e.formSpec?.modelFields??{})),t=Object.keys(o).filter((i)=>!r.has(i)&&!n.has(i));if(t.length)throw new s("INVALID_RESPONSE",`Unknown question IDs: ${t.join(", ")}`);for(let i of e.questions){if(!["single-choice","multi-select","dropdown"].includes(i.kind))continue;let c=o[i.id];if(c==null)continue;let d=new Set(i.options?.map((u)=>u.value));if(!(i.kind==="multi-select"?Array.isArray(c)&&c.every((u)=>typeof u==="string"&&d.has(u)):typeof c==="string"&&d.has(c)))throw new s("INVALID_RESPONSE",`Answer for ${i.id} is not a declared option`)}let m=Object.fromEntries(Object.entries(o).map(([i,c])=>[r.get(i)?.name??i,c])),a=b(y(e)).safeParse(m);if(!a.success)throw new s("INVALID_RESPONSE",`Response does not match the published form: ${String(a.error)}`)}function A(e){let{kind:o,version:r,id:n,titleKey:t,descriptionKey:m,content:a,questions:i,pages:c,verification:d,formSpec:p,ai:u,beforeDestination:w,afterDestination:v}=e;return structuredClone({kind:o,version:r,id:n,titleKey:t,descriptionKey:m,content:a,questions:i,pages:c,verification:d,formSpec:p,ai:{mode:u.mode,dataMode:u.dataMode,...u.dataMode==="full-with-consent"?{consentNoticeVersion:I}:{}},beforeDestination:w,afterDestination:v})}async function h(e,o,r,n){if(!o)return"anonymous";if(!e.resolveAssurance)throw new s("VERIFICATION_UNAVAILABLE","Verification evidence cannot be resolved");return e.resolveAssurance(o,r,n)}function V(e){return{async getPublic(o,r){let n=await e.store.getDefinitionByPublicToken(o);if(!n||n.status!=="published"||!n.publishedRevisionId)throw new s("FORM_NOT_FOUND","Published form was not found");let t=await e.store.getRevision(n.publishedRevisionId,{publicToken:o});if(!t)throw new s("REVISION_NOT_FOUND","Published form revision was not found");return{definitionId:n.id,revisionId:t.id,revision:t.revision,document:A(t.document),locale:l(t.document,r)}},async submit(o){let r=await e.store.getDefinitionByPublicToken(o.publicToken);if(!r||r.status!=="published")throw new s("FORM_NOT_FOUND","Form is not accepting responses");let n=await e.store.getRevision(o.revisionId,{publicToken:o.publicToken});if(!n||n.definitionId!==r.id)throw new s("REVISION_MISMATCH","Response revision does not match the public session");D(n.document,o.answers);let t=await h(e,o.verificationEvidenceRef,r.id,o.publicToken);if(n.document.verification.timing==="before"&&!f(t,n.document.verification.requirement))throw new s("VERIFICATION_REQUIRED","Verification is required before submission");let m=e.now(),a={id:e.id("response"),definitionId:r.id,revisionId:n.id,locale:l(n.document,[o.locale]),status:F(n.document,t),authorAssurance:t,answers:structuredClone(o.answers),createdAt:m,updatedAt:m,submittedAt:m},i=await e.store.insertResponseIdempotently(a,o.publicToken,o.idempotencyKey);if(!i.inserted)return i.response;return await e.emit?.("forms.response.submitted",{definitionId:a.definitionId,revisionId:a.revisionId,responseId:a.id,occurredAt:m}),i.response}}}export{V as createFormsSubmissionService,D as validateCanonicalFormAnswers};
@@ -0,0 +1 @@
1
+ class i extends Error{code;constructor(o,e){super(e);this.code=o;this.name="FormsPlatformError"}}export{i as FormsPlatformError};
@@ -0,0 +1 @@
1
+ import{compileFormDocument as f,validateFormDocument as u}from"@lssm/lib.contracts-spec/forms";class i extends Error{code;constructor(e,o){super(o);this.code=e;this.name="FormsPlatformError"}}function g(e,o){let r=e?.owner.product===o.product&&e.owner.tenantRef===o.tenantRef&&e.owner.workspaceRef===o.workspaceRef&&e.owner.ownerRef===o.ownerRef;if(!e||!r)throw new i("FORM_NOT_FOUND","Form definition was not found in the caller scope");return e}function D(e){let o=u(e);if(o.length)throw new i("INVALID_FORM_DOCUMENT",o.map((r)=>r.message).join("; "));f(e)}function p(e,o){if(o==="none")return!0;if(o==="either")return e!=="anonymous";if(o==="both")return e==="both";return e===o||e==="both"}function v(e,o){if(p(o,e.verification.requirement))return"completed";return e.verification.unverifiedDisposition==="pending-hidden"?"pending-verification":"completed-unverified"}function R(e,o){let r=new Set(e.content.enabledLocales.map((n)=>n.toLowerCase()));for(let n of o){if(!n)continue;let t=n.trim().toLowerCase(),m=e.content.enabledLocales.find((s)=>s.toLowerCase()===t);if(r.has(t)&&m)return m;let a=t.split("-")[0],c=e.content.enabledLocales.find((s)=>s.toLowerCase().split("-")[0]===a);if(c)return c}return e.content.defaultLocale}export{p as formAssuranceMeetsRequirement,g as requireFormDefinition,R as resolveFormLocale,v as resolveFormResponseStatus,D as validateRuntimeFormDocument};
@@ -0,0 +1,2 @@
1
+ class m extends Error{code;constructor(e,o){super(o);this.code=e;this.name="FormsPlatformError"}}import{compileFormDocument as P,validateFormDocument as S}from"@lssm/lib.contracts-spec/forms";function p(e,o){let t=e?.owner.product===o.product&&e.owner.tenantRef===o.tenantRef&&e.owner.workspaceRef===o.workspaceRef&&e.owner.ownerRef===o.ownerRef;if(!e||!t)throw new m("FORM_NOT_FOUND","Form definition was not found in the caller scope");return e}function F(e){let o=S(e);if(o.length)throw new m("INVALID_FORM_DOCUMENT",o.map((t)=>t.message).join("; "));P(e)}function w(e,o){if(o==="none")return!0;if(o==="either")return e!=="anonymous";if(o==="both")return e==="both";return e===o||e==="both"}function b(e,o){if(w(o,e.verification.requirement))return"completed";return e.verification.unverifiedDisposition==="pending-hidden"?"pending-verification":"completed-unverified"}function l(e,o){let t=new Set(e.content.enabledLocales.map((r)=>r.toLowerCase()));for(let r of o){if(!r)continue;let n=r.trim().toLowerCase(),i=e.content.enabledLocales.find((c)=>c.toLowerCase()===n);if(t.has(n)&&i)return i;let s=n.split("-")[0],a=e.content.enabledLocales.find((c)=>c.toLowerCase().split("-")[0]===s);if(a)return a}return e.content.defaultLocale}function y(e){let o=async(t,r)=>e.emit?.(t,r);return{async create(t,r){F(r);let n=e.now(),i={id:e.id("definition"),owner:t,status:"draft",draft:r,draftVersion:1,createdAt:n,updatedAt:n};return await e.store.insertDefinition(i),await o("forms.definition.created",{definitionId:i.id,occurredAt:n}),i},async saveDraft(t,r,n,i){F(i);let s=p(await e.store.getDefinition(t,r),t);if(s.status==="archived")throw new m("FORM_ARCHIVED","Archived forms cannot be edited");let a={...s,draft:i,draftVersion:n+1,updatedAt:e.now()};if(!await e.store.updateDefinition(a,n))throw new m("DRAFT_CONFLICT","The form draft changed; reload before saving");return await o("forms.draft.saved",{definitionId:r,occurredAt:a.updatedAt}),a},async publish(t,r,n){return e.store.transaction(async(i)=>{let s=p(await i.getDefinition(t,r),t);if(s.draftVersion!==n)throw new m("DRAFT_CONFLICT","The form draft changed before publish");F(s.draft);let a=s.publishedRevisionId?await i.getRevision(s.publishedRevisionId):void 0,c=e.now(),u={id:e.id("revision"),definitionId:r,revision:(a?.revision??0)+1,document:structuredClone(s.draft),digest:await e.digest(JSON.stringify(s.draft)),publishedAt:c},d={...s,status:"published",publishedRevisionId:u.id,publicToken:s.publicToken??e.publicToken(),updatedAt:c};if(await i.insertRevision(u),!await i.updateDefinition(d,n))throw new m("DRAFT_CONFLICT","The form changed during publish");return await o("forms.definition.published",{definitionId:r,revisionId:u.id,occurredAt:c}),{definition:d,revision:u}})},async close(t,r){let n=p(await e.store.getDefinition(t,r),t);if(n.status!=="published")throw new m("FORM_NOT_PUBLISHED","Only a published form can be closed");let i={...n,status:"closed",updatedAt:e.now()};return await e.store.updateDefinition(i),await o("forms.definition.closed",{definitionId:r,occurredAt:i.updatedAt}),i},async archive(t,r){let n=p(await e.store.getDefinition(t,r),t);if(n.status==="archived")return n;let i={...n,status:"archived",updatedAt:e.now()};return await e.store.updateDefinition(i),await o("forms.definition.archived",{definitionId:r,occurredAt:i.updatedAt}),i}}}import{buildZodWithRelations as O,compileFormDocument as E,FORM_AI_FULL_DATA_CONSENT_NOTICE_VERSION as N}from"@lssm/lib.contracts-spec/forms";function C(e,o){let t=new Map(e.questions.map((a)=>[a.id,a])),r=new Set(Object.keys(e.formSpec?.modelFields??{})),n=Object.keys(o).filter((a)=>!t.has(a)&&!r.has(a));if(n.length)throw new m("INVALID_RESPONSE",`Unknown question IDs: ${n.join(", ")}`);for(let a of e.questions){if(!["single-choice","multi-select","dropdown"].includes(a.kind))continue;let c=o[a.id];if(c==null)continue;let u=new Set(a.options?.map((f)=>f.value));if(!(a.kind==="multi-select"?Array.isArray(c)&&c.every((f)=>typeof f==="string"&&u.has(f)):typeof c==="string"&&u.has(c)))throw new m("INVALID_RESPONSE",`Answer for ${a.id} is not a declared option`)}let i=Object.fromEntries(Object.entries(o).map(([a,c])=>[t.get(a)?.name??a,c])),s=O(E(e)).safeParse(i);if(!s.success)throw new m("INVALID_RESPONSE",`Response does not match the published form: ${String(s.error)}`)}function x(e){let{kind:o,version:t,id:r,titleKey:n,descriptionKey:i,content:s,questions:a,pages:c,verification:u,formSpec:d,ai:f,beforeDestination:A,afterDestination:I}=e;return structuredClone({kind:o,version:t,id:r,titleKey:n,descriptionKey:i,content:s,questions:a,pages:c,verification:u,formSpec:d,ai:{mode:f.mode,dataMode:f.dataMode,...f.dataMode==="full-with-consent"?{consentNoticeVersion:N}:{}},beforeDestination:A,afterDestination:I})}async function T(e,o,t,r){if(!o)return"anonymous";if(!e.resolveAssurance)throw new m("VERIFICATION_UNAVAILABLE","Verification evidence cannot be resolved");return e.resolveAssurance(o,t,r)}function R(e){return{async getPublic(o,t){let r=await e.store.getDefinitionByPublicToken(o);if(!r||r.status!=="published"||!r.publishedRevisionId)throw new m("FORM_NOT_FOUND","Published form was not found");let n=await e.store.getRevision(r.publishedRevisionId,{publicToken:o});if(!n)throw new m("REVISION_NOT_FOUND","Published form revision was not found");return{definitionId:r.id,revisionId:n.id,revision:n.revision,document:x(n.document),locale:l(n.document,t)}},async submit(o){let t=await e.store.getDefinitionByPublicToken(o.publicToken);if(!t||t.status!=="published")throw new m("FORM_NOT_FOUND","Form is not accepting responses");let r=await e.store.getRevision(o.revisionId,{publicToken:o.publicToken});if(!r||r.definitionId!==t.id)throw new m("REVISION_MISMATCH","Response revision does not match the public session");C(r.document,o.answers);let n=await T(e,o.verificationEvidenceRef,t.id,o.publicToken);if(r.document.verification.timing==="before"&&!w(n,r.document.verification.requirement))throw new m("VERIFICATION_REQUIRED","Verification is required before submission");let i=e.now(),s={id:e.id("response"),definitionId:t.id,revisionId:r.id,locale:l(r.document,[o.locale]),status:b(r.document,n),authorAssurance:n,answers:structuredClone(o.answers),createdAt:i,updatedAt:i,submittedAt:i},a=await e.store.insertResponseIdempotently(s,o.publicToken,o.idempotencyKey);if(!a.inserted)return a.response;return await e.emit?.("forms.response.submitted",{definitionId:s.definitionId,revisionId:s.revisionId,responseId:s.id,occurredAt:i}),a.response}}}import{flattenPortableFormFields as _}from"@lssm/lib.contracts-spec/forms";function g(e){let o=new Set(e.questions.map(({name:s})=>s)),t=e.questions.map(k),r=new Set(e.formSpec?.policy?.pii??[]),n=_(e.formSpec?.fields??[]),i=Object.entries(e.formSpec?.modelFields??{}).flatMap(([s,a])=>{if(o.has(s))return[];let c=n.find((u)=>u.name===s);return[{id:s,labelKey:c?.labelI18n??s,sensitive:r.has(s)||[...r].some((u)=>u.startsWith(`${s}.`))||c?.kind==="email"||c?.kind==="phone"||a.type==="email"||a.type==="phone"}]});return[...t,...i]}function k(e){return{id:e.id,labelKey:e.labelKey,sensitive:e.sensitive===!0||e.kind==="email"||e.kind==="phone"}}var L="response_extensions:AI follow-ups";function V(e){let o=Array.isArray(e)?e.every((r)=>typeof r!=="object")?e.join(";"):JSON.stringify(e):e==null?"":typeof e==="object"?JSON.stringify(e):String(e);return`"${(/^[\s]*[=+\-@]/.test(o)?`'${o}`:o).replaceAll('"','""')}"`}function v(e){return`${e.map(V).join(",")}\r
2
+ `}function D(e,o,t){if(o.revisionId!==e.id)throw Error("CSV responses must belong to the exported revision");let r=g(e.document),n=new Set(r.map(({id:s})=>s)),i=Object.fromEntries(Object.entries(o.answers).filter(([s])=>!n.has(s)));return[o.id,o.status,o.locale,o.submittedAt??"",...r.map((s)=>{if(!(t.includeSensitive&&t.sensitiveGrant?.authorized)&&s.sensitive)return"[REDACTED]";return o.answers[s.id]}),t.includeSensitive&&t.sensitiveGrant?.authorized?i:"[REDACTED]"]}function h(e,o){let t=l(e.document,[o]),r=e.document.content.catalogs[t]??{};return["response_id","status","locale","submitted_at",...g(e.document).map((n)=>`${n.id}:${r[n.labelKey]??n.labelKey}`),L]}function M(e,o,t={}){return`\uFEFF${v(h(e,t.locale))}${o.map((r)=>v(D(e,r,t))).join("")}`}async function*j(e,o,t={}){yield`\uFEFF${v(h(e,t.locale))}`;for await(let r of o)yield v(D(e,r,t))}import{evalPredicate as U}from"@lssm/lib.contracts-spec/forms";function K(e,o,t){let r=e.pages.findIndex((i)=>i.id===o);if(r<0)throw new m("PAGE_NOT_FOUND","Current form page does not exist");return e.pages[r]?.nextPageRules?.find((i)=>U(t,i.when))?.nextPageId??e.pages[r]?.defaultNextPageId??e.pages[r+1]?.id}function ue(e){return{...y(e),...R(e)}}export{m as FormsPlatformError,ue as createFormsPlatformService,l as resolveFormLocale,K as resolveNextFormPage,M as serializeFormResponsesCsv,j as streamFormResponsesCsv};
@@ -0,0 +1,3 @@
1
+ import{OPERATION_EXECUTION_EFFECTS as Ce}from"@lssm/lib.contracts-spec/operations";function he(e=()=>new Date){let t=new Map;return{async consume(o,n){let r=e().getTime();for(let[a,i]of t)if(i<=r)t.delete(a);if(t.has(o))return!1;return t.set(o,Date.parse(n)),!0}}}function Fe(e={}){let t=e.now??(()=>new Date),o=e.nonceStore??he(t);return{async authorize(n){let r=await Pe(n,t(),e.verifyEvidence);if(r)return r;if(!await o.consume(n.receipt.nonce,n.receipt.expiresAt))return{effect:"deny",reason:"replayed_receipt"};return{effect:"allow",receiptId:n.receipt.id,nonce:n.receipt.nonce}}}}async function we(e){let t=new TextEncoder().encode(Z(e)),o=await globalThis.crypto.subtle.digest("SHA-256",t);return`sha256:${Array.from(new Uint8Array(o),(n)=>n.toString(16).padStart(2,"0")).join("")}`}async function Pe(e,t,o){let{receipt:n}=e,r=Date.parse(n.issuedAt),a=Date.parse(n.expiresAt);if(!n.id||!n.nonce||!n.issuer||!n.evidenceRef||!Me(n.subject)||n.effects.some((s)=>!Ce.includes(s))||!Number.isFinite(r)||!Number.isFinite(a)||a<=r)return F("malformed_receipt");if(a<=t.getTime())return F("expired_receipt");if(r>t.getTime())return F("not_yet_valid");if(!ve(n.subject,e.subject,["actor","userId"]))return F("wrong_subject");if(!ve(n.subject,e.subject,["tenantId","workspaceId","organizationId"]))return F("wrong_tenant");if(n.operation.key!==e.operation.key||n.operation.version!==e.operation.version)return F("wrong_operation");if(n.inputDigest!==await we(e.input))return F("wrong_input");let i=new Set(n.effects);if(e.requiredEffects.some((s)=>!i.has(s)))return F("insufficient_effects");if(!xe(n,e))return F("insufficient_cost_ceiling");if(o&&!await o(n))return F("invalid_evidence");return}function ve(e,t,o){return o.every((n)=>{let r=t[n];return r==null||e[n]===r})}function xe(e,t){if(!t.requestedCost)return!0;if(!Number.isFinite(t.requestedCost.amount)||t.requestedCost.amount<0)return!1;let o=e.costCeiling;if(!o||!Number.isFinite(o.amount)||o.amount<0)return!1;return o.amount>=t.requestedCost.amount&&(!t.requestedCost.currency||o.currency===t.requestedCost.currency)&&(!t.requestedCost.unit||o.unit===t.requestedCost.unit)}function Me(e){return Object.values(e).some((t)=>typeof t==="string"&&t.length>0)}function F(e){return{effect:"deny",reason:e}}function Z(e){if(e===null||typeof e==="string"||typeof e==="boolean")return JSON.stringify(e);if(typeof e==="number"){if(!Number.isFinite(e))throw TypeError("Approval input is not JSON.");return JSON.stringify(e)}if(Array.isArray(e))return`[${e.map(Z).join(",")}]`;if(e instanceof Date)return JSON.stringify(e.toISOString());if(typeof e==="object")return`{${Object.entries(e).filter(([,o])=>o!==void 0).sort(([o],[n])=>o.localeCompare(n)).map(([o,n])=>`${JSON.stringify(o)}:${Z(n)}`).join(",")}}`;throw TypeError("Approval input is not JSON.")}import{defineFeature as Ie}from"@lssm/lib.contracts-spec/features";var Qe=Ie({meta:{key:"libs.contracts-runtime-core",version:"1.0.0",title:"Contracts Runtime Core",description:"Framework-neutral in-house query/cache/offline engine and Transport port for ContractSpec data fetching.",domain:"contracts-runtime-core",owners:["@contractspec-core"],tags:["package","libs","contracts-runtime-core"],stability:"experimental"}});function ee(e,t={}){let o=t.baseMs??200,n=t.factor??2,r=t.maxMs??30000,a=t.jitter??Math.random,i=Math.max(0,e-1),s=Math.min(r,o*n**i);return Math.round(s*(0.5+a()*0.5))}import{invalidationTagMatches as Le}from"@lssm/lib.contracts-spec/query/invalidation";var be="cache:";function _(e){let t=new Map,o=(n)=>`${be}${n}`;return{read:(n)=>e.get(o(n)),write:async(n)=>{t.set(n.key,n.tags),await e.set(o(n.key),n)},remove:async(n)=>{t.delete(n),await e.remove(o(n))},entries:async()=>{let n=await e.keys(be),r=[];for(let a of n){let i=await e.get(a);if(i!==void 0)r.push(i)}return r},invalidate:async(n,r)=>{let a=[];for(let[i,s]of t.entries()){if(!s.some((d)=>n.some((g)=>Le(d,g))))continue;let p=await e.get(o(i));if(p===void 0)continue;await e.set(o(i),{...p,status:"stale",staleAt:r}),a.push(i)}return a}}}function Ne(e){let{serverData:t,localData:o}=e,n=e.mergeFields??[];if(typeof t!=="object"||t===null||typeof o!=="object"||o===null)return{outcome:"surface"};let r={...t},a=o;for(let i of n)if(i in a)r[i]=a[i];return{outcome:"merged",data:r}}function q(){let e=new Map;return{register(t,o){e.set(t,o)},has(t){return e.has(t)},async resolve(t){switch(t.strategy){case"server-wins":return{outcome:"use-server",data:t.serverData};case"client-wins":return{outcome:"use-client",data:t.localData};case"field-merge":return Ne(t);case"surface":return{outcome:"surface"};default:{let o=t.policy.resolver,n=o===void 0?void 0:e.get(o);if(n===void 0)return{outcome:"surface"};return n(t)}}}}}import{defaultConflictPolicy as _e}from"@lssm/lib.contracts-spec/query/conflict-policy";async function V(e,t){for(let o of e)if(o.previous===void 0)await t.remove(o.key);else await t.write(o.previous)}async function te(e,t,o){let n=e.conflictPolicy??_e(),r=e.rollback[0]?.key,a=r===void 0?void 0:await o.cache.read(r),i=t.metadata?.serverData,s=await o.resolvers.resolve({strategy:n.strategy,policy:n,localData:a?.data,serverData:i,localVersion:e.versionToken,serverVersion:t.versionToken,mergeFields:n.mergeFields});switch(o.events.emit({type:"mutation-conflict",id:e.id,strategy:n.strategy,outcome:s.outcome}),s.outcome){case"use-server":{await V(e.rollback,o.cache),await o.cache.invalidate(e.tags,o.now());for(let u of e.rollback)await o.queryEngine?.refresh(u.key);return"resolved"}case"use-client":return await o.queue.update({...e,versionToken:t.versionToken,status:"pending"}),"re-enqueued";case"merged":{if(r!==void 0&&a!==void 0)await o.cache.write({...a,data:s.data,versionToken:t.versionToken,status:"warm",storedAt:o.now()}),await o.queryEngine?.refresh(r);return await o.queue.update({...e,versionToken:t.versionToken,status:"pending"}),"re-enqueued"}default:{if(r!==void 0)await o.queryEngine?.emitConflict(r,{versionToken:t.versionToken,serverData:i,clientData:a?.data,strategy:n.strategy});return"resolved"}}}var qe=new Set(["online-only","memory-cache","offline-capable"]),Ee={"online-only":"online-only",online:"online-only",disabled:"online-only",false:"online-only",off:"online-only","memory-cache":"memory-cache",memory:"memory-cache",cache:"memory-cache","offline-capable":"offline-capable",offline:"offline-capable",enabled:"offline-capable",true:"offline-capable",on:"offline-capable"};function Ve(e){return typeof e==="string"&&qe.has(e)}function U(e={}){let t=e.defaultMode===void 0?{mode:"online-only",source:"default",reason:"No local/offline policy input was supplied."}:ne(e.defaultMode,"explicit")??{mode:"online-only",source:"explicit"},o=ne(Ue(e.env),"env",{allowUnknown:!0});return ne(e.flag,"feature-flag")??o??t}function Ue(e){if(typeof e!=="object"||e===null)return e;if("CONTRACTSPEC_LOCAL_OFFLINE"in e)return e.CONTRACTSPEC_LOCAL_OFFLINE;if("mode"in e)return e;return}function ne(e,t,o={}){if(e===void 0||e===null||e==="")return;if(typeof e==="boolean")return{mode:e?"offline-capable":"online-only",source:t};if(typeof e==="string"){let n=Ee[e.trim().toLowerCase()];if(n!==void 0)return{mode:n,source:t};if(o.allowUnknown)return}if(typeof e==="object"&&e!==null&&"mode"in e){let n=e,r=typeof n.mode==="string"?Ee[n.mode.trim().toLowerCase()]:void 0;if(r!==void 0)return{mode:r,source:t,...typeof n.reason==="string"?{reason:n.reason}:{}};if(o.allowUnknown)return}throw Error(`Unsupported localOffline policy value: ${String(e)}`)}function A(e){return e!=="offline"}function I(e="online"){let t={signal:e,since:Date.now()};return{getSnapshot:()=>t,subscribe:()=>()=>{}}}var je={id:"docs.contracts-runtime-core.reachability",title:"Reachability input port (tri-state)",summary:"Engine-owned reachability input port; integrations feed it, the engine never imports them.",kind:"reference",visibility:"internal",route:"/docs/contracts-runtime-core/reachability",domain:"contracts-runtime-core",owners:["@contractspec-core"],tags:["contracts-runtime-core","reachability","offline","port"],body:"Tri-state OnlineSignal ('online' | 'restricted' | 'offline'). 'online' allows normal fetch + queue drain. 'restricted' is online-degraded: the engine fetches and drains the queue as if online but may mark results stale-eligible; it never suspends network nor activates the offline queue. Only 'offline' suspends outbound network and activates the durable offline mutation queue. The engine reads reachability solely through ReachabilitySource and MUST NOT import integrations/* — concrete sources (runtime-local networkReachability) are wired via an integration→port adapter (plan §2.3/§4.2, Architect finding 1). isNetworkAllowed mirrors runtime-local's outboundNetworkAllowed = reachability !== 'offline'. createStaticReachabilitySource('online') is the B1a default and online test fixture."};function j(){let e=new Map;return{get:async(t)=>{let o=e.get(t);return o===void 0?void 0:structuredClone(o)},set:async(t,o)=>{e.set(t,structuredClone(o))},remove:async(t)=>{e.delete(t)},keys:async(t)=>{let o=[...e.keys()];return t===void 0?o:o.filter((n)=>n.startsWith(t))},clear:async()=>{e.clear()}}}function Q(){let e=new Set;return{emit(t){for(let o of e)o(t)},subscribe(t){return e.add(t),()=>{e.delete(t)}}}}function oe(e){return{async collectGarbage(){let t=e.now(),o=0;for(let n of await e.cache.entries())if(n.expiresAt!==void 0&&t>=n.expiresAt)await e.cache.remove(n.key),o+=1;return e.events.emit({type:"gc-collected",evicted:o}),o},async revalidateStale(){let t=e.revalidate;if(t===void 0)return 0;let o=e.now(),n=0;for(let r of await e.cache.entries()){if(!(r.staleAt!==void 0&&o>=r.staleAt)||r.envelope===void 0)continue;await t(r.envelope),e.events.emit({type:"revalidated",key:r.key}),n+=1}return n}}}import{mergeSafeEconomicEvidenceRefIds as Ke,parseSafeEconomicEvidenceRefId as $e}from"@lssm/lib.contracts-spec/operations";import{defaultConflictPolicy as Be}from"@lssm/lib.contracts-spec/query/conflict-policy";var ze=5;function re(...e){return Ke(...e)}function Je(e){let t=$e(e);if(!t)throw Error("EconomicEvidenceInvalidRef: unsafe or invalid economic evidence ref");return t}function ie(e){let{transport:t,cache:o,queue:n,reachability:r,resolvers:a,events:i}=e,s=e.now??(()=>Date.now()),u=e.maxAttempts??ze,p={cache:o,queue:n,resolvers:a,events:i,now:s,queryEngine:e.queryEngine},d=!1,g=0,D=null,k=new Map,W=(c,m=c.economicEvidenceRefs)=>({operation:c.operation,input:c.input,tags:c.tags,economicEvidenceRefs:m});async function S(c){let m=[];for(let y of c){let b=await o.read(y.key);m.push({key:y.key,previous:b}),await o.write({key:y.key,data:y.data,versionToken:y.versionToken??b?.versionToken,status:"warm",tags:b?.tags??[],storedAt:s(),staleAt:b?.staleAt,expiresAt:b?.expiresAt}),await e.queryEngine?.refresh(y.key)}return m}async function T(c,m){for(let y of c.rollback){let b=await o.read(y.key);if(b!==void 0)await o.write({...b,versionToken:m.versionToken??b.versionToken,status:"stale",staleAt:s()});await e.queryEngine?.refresh(y.key)}await o.invalidate(c.tags,s())}async function h(c){let m;try{m=re(c.economicEvidenceRefs)}catch{await V(c.rollback,o);for(let O of c.rollback)await e.queryEngine?.refresh(O.key);return await n.remove(c.id),i.emit({type:"mutation-failed",id:c.id,code:"ECONOMIC_EVIDENCE_INVALID_REF"}),k.set(c.id,{id:c.id,status:"failed",problem:{type:"about:blank",title:"Economic evidence ref rejected",status:422,code:"ECONOMIC_EVIDENCE_INVALID_REF",category:"validation",severity:"error",retryable:!1}}),!0}let y=c.attempts+1;await n.update({...c,status:"in-flight",attempts:y});let b=await t.execute(W(c,m),e.contextProvider?.());if(b.ok){let O=re(m,b.data.economicEvidenceRefs);if(await T(c,b.data),await n.remove(c.id),i.emit({type:"mutation-replayed",id:c.id,queueDepth:await n.depth()}),O.length>0)i.emit({type:"economic-evidence-attached",operationKey:c.operation.key,evidenceRefs:O.map(Je)});return k.set(c.id,{id:c.id,status:"done",data:b.data.data,economicEvidenceRefs:O}),!0}let{problem:R}=b;if(R.category==="auth"){if(d=!0,await n.update({...c,status:"paused-auth",attempts:y}),i.emit({type:"auth-expired",id:c.id}),k.set(c.id,{id:c.id,status:"paused-auth",problem:R}),e.refreshAuth!==void 0&&await e.refreshAuth())return d=!1,await n.update({...c,status:"pending",attempts:y}),!0;return!1}if(R.category==="conflict"){if(await te(c,R,p)==="resolved")await n.remove(c.id),k.set(c.id,{id:c.id,status:"done",problem:R});return!0}if(R.retryable&&y<u){let O=ee(y,e.backoff);return await n.update({...c,status:"failed",attempts:y}),i.emit({type:"mutation-retry",id:c.id,attempt:y,delayMs:O}),k.set(c.id,{id:c.id,status:"failed",problem:R}),e.schedule?.(()=>{v()},O),!0}await V(c.rollback,o);for(let O of c.rollback)await e.queryEngine?.refresh(O.key);return await n.remove(c.id),i.emit({type:"mutation-failed",id:c.id,code:b.code}),k.set(c.id,{id:c.id,status:"failed",problem:R}),!0}async function f(){if(d)return;if(!A(r.getSnapshot().signal))return;for(let c of await n.list()){if(c.status==="paused-auth")continue;if(!await h(c))return}i.emit({type:"queue-drained",remaining:await n.depth()})}function v(){if(D!==null)return D;return D=f().finally(()=>{D=null}),D}async function l(c,m={}){re(c.economicEvidenceRefs);let y=s();g+=1;let b=`${y}-${g}`,R=m.optimistic?await S(m.optimistic):[];if(await n.enqueue({...c,conflictPolicy:c.conflictPolicy??Be(),id:b,enqueuedAt:y,attempts:0,status:"pending",rollback:R}),i.emit({type:"mutation-enqueued",id:b,queueDepth:await n.depth()}),!d&&A(r.getSnapshot().signal))await v();return k.get(b)??{id:b,status:"pending"}}async function w(){d=!1;for(let c of await n.list())if(c.status==="paused-auth")await n.update({...c,status:"pending"});await v()}let C=r.subscribe((c)=>{if(!d&&A(c.signal))v()});return{mutate:l,drain:v,resume:w,dispose:C}}function ae(e){let t=(n)=>`queue:${n}`;async function o(){let n=await e.keys("queue:"),r=[];for(let a of n){let i=await e.get(a);if(i!==void 0)r.push(i)}return r.sort((a,i)=>a.enqueuedAt===i.enqueuedAt?a.id.localeCompare(i.id):a.enqueuedAt-i.enqueuedAt),r}return{enqueue:(n)=>e.set(t(n.id),n),update:(n)=>e.set(t(n.id),n),remove:(n)=>e.remove(t(n)),list:()=>o(),depth:async()=>(await e.keys("queue:")).length}}import{createQueryKey as se}from"@lssm/lib.contracts-spec/query/key";function P(e,t){if(e?.staleAt===void 0)return!1;return t>=e.staleAt}function L(){return{status:"idle",fetchStatus:"idle",cacheStatus:"empty",isStale:!1,isOffline:!1}}function K(e,t){if(e===void 0)return{status:"loading",fetchStatus:"fetching",cacheStatus:"empty",isStale:!1,isOffline:!1};let o=P(e,t);return{status:"success",fetchStatus:"fetching",data:e.data,cacheStatus:o?"stale":e.status,isStale:o,isOffline:!1,versionToken:e.versionToken,dataUpdatedAt:e.storedAt,...e.pageInfo===void 0?{}:{pageInfo:e.pageInfo}}}function M(e,t){let o=P(e,t);return{status:"success",fetchStatus:"idle",data:e.data,cacheStatus:o?"stale":e.status,isStale:o,isOffline:!1,versionToken:e.versionToken,dataUpdatedAt:e.storedAt,...e.pageInfo===void 0?{}:{pageInfo:e.pageInfo}}}function B(e,t,o){return{status:"error",fetchStatus:"idle",data:t?.data,error:e,cacheStatus:t===void 0?"empty":t.status,isStale:P(t,o),isOffline:!1,versionToken:t?.versionToken,dataUpdatedAt:t?.storedAt,errorUpdatedAt:o}}function z(e,t,o){return{status:"auth-expired",fetchStatus:"idle",data:t?.data,error:e,cacheStatus:t===void 0?"empty":t.status,isStale:P(t,o),isOffline:!1,versionToken:t?.versionToken,dataUpdatedAt:t?.storedAt,errorUpdatedAt:o}}function J(e,t,o){return{status:e===void 0?"idle":"success",fetchStatus:"idle",data:e?.data,cacheStatus:"conflict",isStale:P(e,o),isOffline:!1,conflict:t,versionToken:t.versionToken??e?.versionToken,dataUpdatedAt:e?.storedAt}}function G(e,t){return{status:e===void 0?"idle":"success",fetchStatus:"idle",data:e?.data,cacheStatus:"offline",isStale:P(e,t),isOffline:!0,versionToken:e?.versionToken,dataUpdatedAt:e?.storedAt,...e?.pageInfo===void 0?{}:{pageInfo:e.pageInfo}}}function Se(e,t){let{transport:o}=e,n=e.advanced??{},r=n.now??(()=>Date.now()),a=n.reachability??I("online"),i=n.events??Q(),s=n.resolvers??q(),u=t??U({defaultMode:e.localOffline,env:e.env,flag:e.flag}),p=new Map,d=new Map,g=0;function D(S,T){p.set(S,T);for(let h of d.get(S)??[])h(T)}return{...{async query(S,T){let h=se(S),f=a.getSnapshot().signal;if(!A(f)){let m=G(void 0,r());return D(h,m),m}D(h,K(void 0,r()));let v=r(),l=await o.execute(S,T),w=r();if(!l.ok){i.emit({type:"fetch-error",key:h,code:l.code,latencyMs:w-v});let m=l.problem.category==="auth"?z(l.problem,void 0,w):B(l.problem,void 0,w);return D(h,m),m}i.emit({type:"fetch-success",key:h,latencyMs:w-v});let C={key:h,data:l.data.data,versionToken:l.data.versionToken??l.versionToken,status:f==="restricted"?"warm":"fresh",tags:[],storedAt:w,...l.data.pageInfo===void 0?{}:{pageInfo:l.data.pageInfo}},c=M(C,w);return D(h,c),c},getState(S){return p.get(se(S))??L()},subscribe(S,T){let h=se(S),f=d.get(h);if(f===void 0)f=new Set,d.set(h,f);return f.add(T),()=>f?.delete(T)},async invalidateTags(){return[]},async refresh(S){let T=p.get(S)??L();return D(S,T),T},async emitConflict(S,T){let h=J(void 0,T,r());return D(S,h),h}},...{async mutate(S,T={}){g+=1;let h=`${r()}-${g}`;if(!A(a.getSnapshot().signal))return{id:h,status:"disabled-offline",problem:Ge()};let f=await o.execute({operation:S.operation,input:S.input,tags:S.tags},T.ctx??n.contextProvider?.());if(f.ok)return{id:h,status:"done",data:f.data.data};if(f.problem.category==="auth")return{id:h,status:"paused-auth",problem:f.problem};return{id:h,status:"failed",problem:f.problem}},async drain(){},async resume(){},dispose(){}},maintenance:{collectGarbage:async()=>0,revalidateStale:async()=>0},events:i,resolvers:s,localOffline:u}}function Ge(){return{type:"about:blank",title:"Offline mutation queue disabled",status:409,code:"OFFLINE_QUEUE_DISABLED",category:"conflict",severity:"warning",retryable:!1,detail:"localOffline=online-only does not cache local data or queue offline mutations."}}import{createQueryKey as ue}from"@lssm/lib.contracts-spec/query/key";function ce(){let e=new Map;return{run(t,o){let n=e.get(t);if(n!==void 0)return n;let r=o().finally(()=>{e.delete(t)});return e.set(t,r),r},size(){return e.size}}}var He=0;function le(e){let{transport:t}=e,o=e.storage??j(),n=e.reachability??I("online"),r=e.now??(()=>Date.now()),a=e.defaultStaleTimeMs??He,i=e.cacheStore??_(o),s=e.events??Q(),u=ce(),p=new Map,d=new Map;function g(f,v){p.set(f,v);let l=d.get(f);if(l===void 0)return;for(let w of l)w(v)}async function D(f,v){let l=ue(f),w=n.getSnapshot().signal,C=await i.read(l);if(!A(w)){let x=G(C,r());return g(l,x),x}if(C!==void 0&&!P(C,r())){s.emit({type:"cache-hit",key:l});let x=M(C,r());return g(l,x),x}s.emit({type:"cache-miss",key:l}),g(l,K(C,r()));let c=r(),m=await u.run(l,()=>t.execute(f,v)),y=r();if(!m.ok){s.emit({type:"fetch-error",key:l,code:m.code,latencyMs:y-c});let x=m.problem.category==="auth"?z(m.problem,C,y):B(m.problem,C,y);return g(l,x),x}s.emit({type:"fetch-success",key:l,latencyMs:y-c});let b=f.cache?.staleTimeMs??a,R=f.cache?.cacheTimeMs,O={key:l,data:m.data.data,versionToken:m.data.versionToken??m.versionToken,status:w==="restricted"?"warm":"fresh",tags:f.tags??[],storedAt:y,staleAt:y+b,envelope:f,...R===void 0?{}:{expiresAt:y+R},...m.data.pageInfo===void 0?{}:{pageInfo:m.data.pageInfo}};await i.write(O);let ge=M(O,y);return g(l,ge),ge}async function k(f){let v=await i.read(f),l=v===void 0?L():M(v,r());return g(f,l),l}async function W(f,v){let l=await i.read(f),w=J(l,v,r());return g(f,w),w}function S(f){return p.get(ue(f))??L()}function T(f,v){let l=ue(f),w=d.get(l);if(w===void 0)w=new Set,d.set(l,w);return w.add(v),()=>{d.get(l)?.delete(v)}}async function h(f){let v=await i.invalidate(f,r());for(let l of v){let w=await i.read(l);if(w!==void 0)g(l,M(w,r()))}return v}return{query:D,getState:S,subscribe:T,invalidateTags:h,refresh:k,emitConflict:W}}function fe(e){Xe(e);let t=e.advanced??{},o=U({defaultMode:e.localOffline,env:e.env,flag:e.flag});if(We(o.mode,t),o.mode==="online-only")return Se(e,o);let n=t.now??(()=>Date.now()),r=t.storage??j(),a=t.events??Q(),i=t.cacheStore??_(r),s=t.reachability??I("online"),u=t.resolvers??q(),p=ae(r),d=le({...t,transport:e.transport,now:n,storage:r,events:a,cacheStore:i,reachability:s}),g=ie({transport:e.transport,cache:i,queue:p,reachability:s,resolvers:u,events:a,now:n,maxAttempts:t.maxAttempts,queryEngine:d,contextProvider:t.contextProvider,refreshAuth:t.refreshAuth,schedule:t.schedule,backoff:t.backoff}),D=oe({cache:i,events:a,now:n,revalidate:(k)=>d.query(k)});return{...d,...g,maintenance:D,events:a,resolvers:u,localOffline:o}}function We(e,t){if(e==="offline-capable"){if(t.storage===void 0)throw Error("localOffline=offline-capable requires advanced.storage; pass a durable StoragePort or explicit platform storage adapter.");return}if(t.storage!==void 0)throw Error(`localOffline=${e} rejects advanced.storage; this mode must not use durable local persistence.`);if(t.cacheStore!==void 0)throw Error(`localOffline=${e} rejects advanced.cacheStore; this mode owns cache semantics.`)}function Xe(e){let t=e;if(t.storage!==void 0)throw Error("Use advanced.storage instead of top-level storage.");if(t.cacheStore!==void 0)throw Error("Use advanced.cacheStore instead of top-level cacheStore.")}function De(){return globalThis.process?.env}function Ye(e){return fe({...e,env:e.env??De()})}function Ze(){return{read:async(e)=>{return},write:async()=>{},remove:async()=>{},entries:async()=>[],invalidate:async(e,t)=>[]}}function et(){return{type:"https://contractspec.io/problems/offline-queue-disabled",title:"Offline mutation queue disabled",status:503,code:"OFFLINE_QUEUE_DISABLED",category:"policy",severity:"warning",retryable:!0,detail:"localOffline is online-only; offline mutations are not queued or replayed."}}var tt=(e)=>({operation:e.operation,input:e.input,tags:e.tags});function nt(e){let t=e.now??(()=>Date.now()),o=0;async function n(r,a={}){o+=1;let i=`${t()}-${o}`;if(!A(e.reachability.getSnapshot().signal))return{id:i,status:"disabled-offline",problem:et()};let s=await e.transport.execute(tt(r),a.ctx);if(s.ok)return{id:i,status:"done",data:s.data.data};return{id:i,status:"failed",problem:s.problem}}return{mutate:n,drain:async()=>{},resume:async()=>{},dispose:()=>{}}}class E extends Error{code;constructor(e,t){super(t);this.code=e;this.name="FormsPlatformError"}}import{compileFormDocument as ot,validateFormDocument as rt}from"@lssm/lib.contracts-spec/forms";function H(e,t){let o=e?.owner.product===t.product&&e.owner.tenantRef===t.tenantRef&&e.owner.workspaceRef===t.workspaceRef&&e.owner.ownerRef===t.ownerRef;if(!e||!o)throw new E("FORM_NOT_FOUND","Form definition was not found in the caller scope");return e}function X(e){let t=rt(e);if(t.length)throw new E("INVALID_FORM_DOCUMENT",t.map((o)=>o.message).join("; "));ot(e)}function pe(e,t){if(t==="none")return!0;if(t==="either")return e!=="anonymous";if(t==="both")return e==="both";return e===t||e==="both"}function Te(e,t){if(pe(t,e.verification.requirement))return"completed";return e.verification.unverifiedDisposition==="pending-hidden"?"pending-verification":"completed-unverified"}function N(e,t){let o=new Set(e.content.enabledLocales.map((n)=>n.toLowerCase()));for(let n of t){if(!n)continue;let r=n.trim().toLowerCase(),a=e.content.enabledLocales.find((u)=>u.toLowerCase()===r);if(o.has(r)&&a)return a;let i=r.split("-")[0],s=e.content.enabledLocales.find((u)=>u.toLowerCase().split("-")[0]===i);if(s)return s}return e.content.defaultLocale}function ke(e){let t=async(o,n)=>e.emit?.(o,n);return{async create(o,n){X(n);let r=e.now(),a={id:e.id("definition"),owner:o,status:"draft",draft:n,draftVersion:1,createdAt:r,updatedAt:r};return await e.store.insertDefinition(a),await t("forms.definition.created",{definitionId:a.id,occurredAt:r}),a},async saveDraft(o,n,r,a){X(a);let i=H(await e.store.getDefinition(o,n),o);if(i.status==="archived")throw new E("FORM_ARCHIVED","Archived forms cannot be edited");let s={...i,draft:a,draftVersion:r+1,updatedAt:e.now()};if(!await e.store.updateDefinition(s,r))throw new E("DRAFT_CONFLICT","The form draft changed; reload before saving");return await t("forms.draft.saved",{definitionId:n,occurredAt:s.updatedAt}),s},async publish(o,n,r){return e.store.transaction(async(a)=>{let i=H(await a.getDefinition(o,n),o);if(i.draftVersion!==r)throw new E("DRAFT_CONFLICT","The form draft changed before publish");X(i.draft);let s=i.publishedRevisionId?await a.getRevision(i.publishedRevisionId):void 0,u=e.now(),p={id:e.id("revision"),definitionId:n,revision:(s?.revision??0)+1,document:structuredClone(i.draft),digest:await e.digest(JSON.stringify(i.draft)),publishedAt:u},d={...i,status:"published",publishedRevisionId:p.id,publicToken:i.publicToken??e.publicToken(),updatedAt:u};if(await a.insertRevision(p),!await a.updateDefinition(d,r))throw new E("DRAFT_CONFLICT","The form changed during publish");return await t("forms.definition.published",{definitionId:n,revisionId:p.id,occurredAt:u}),{definition:d,revision:p}})},async close(o,n){let r=H(await e.store.getDefinition(o,n),o);if(r.status!=="published")throw new E("FORM_NOT_PUBLISHED","Only a published form can be closed");let a={...r,status:"closed",updatedAt:e.now()};return await e.store.updateDefinition(a),await t("forms.definition.closed",{definitionId:n,occurredAt:a.updatedAt}),a},async archive(o,n){let r=H(await e.store.getDefinition(o,n),o);if(r.status==="archived")return r;let a={...r,status:"archived",updatedAt:e.now()};return await e.store.updateDefinition(a),await t("forms.definition.archived",{definitionId:n,occurredAt:a.updatedAt}),a}}}import{buildZodWithRelations as it,compileFormDocument as at,FORM_AI_FULL_DATA_CONSENT_NOTICE_VERSION as st}from"@lssm/lib.contracts-spec/forms";function ct(e,t){let o=new Map(e.questions.map((s)=>[s.id,s])),n=new Set(Object.keys(e.formSpec?.modelFields??{})),r=Object.keys(t).filter((s)=>!o.has(s)&&!n.has(s));if(r.length)throw new E("INVALID_RESPONSE",`Unknown question IDs: ${r.join(", ")}`);for(let s of e.questions){if(!["single-choice","multi-select","dropdown"].includes(s.kind))continue;let u=t[s.id];if(u==null)continue;let p=new Set(s.options?.map((g)=>g.value));if(!(s.kind==="multi-select"?Array.isArray(u)&&u.every((g)=>typeof g==="string"&&p.has(g)):typeof u==="string"&&p.has(u)))throw new E("INVALID_RESPONSE",`Answer for ${s.id} is not a declared option`)}let a=Object.fromEntries(Object.entries(t).map(([s,u])=>[o.get(s)?.name??s,u])),i=it(at(e)).safeParse(a);if(!i.success)throw new E("INVALID_RESPONSE",`Response does not match the published form: ${String(i.error)}`)}function ut(e){let{kind:t,version:o,id:n,titleKey:r,descriptionKey:a,content:i,questions:s,pages:u,verification:p,formSpec:d,ai:g,beforeDestination:D,afterDestination:k}=e;return structuredClone({kind:t,version:o,id:n,titleKey:r,descriptionKey:a,content:i,questions:s,pages:u,verification:p,formSpec:d,ai:{mode:g.mode,dataMode:g.dataMode,...g.dataMode==="full-with-consent"?{consentNoticeVersion:st}:{}},beforeDestination:D,afterDestination:k})}async function lt(e,t,o,n){if(!t)return"anonymous";if(!e.resolveAssurance)throw new E("VERIFICATION_UNAVAILABLE","Verification evidence cannot be resolved");return e.resolveAssurance(t,o,n)}function Oe(e){return{async getPublic(t,o){let n=await e.store.getDefinitionByPublicToken(t);if(!n||n.status!=="published"||!n.publishedRevisionId)throw new E("FORM_NOT_FOUND","Published form was not found");let r=await e.store.getRevision(n.publishedRevisionId,{publicToken:t});if(!r)throw new E("REVISION_NOT_FOUND","Published form revision was not found");return{definitionId:n.id,revisionId:r.id,revision:r.revision,document:ut(r.document),locale:N(r.document,o)}},async submit(t){let o=await e.store.getDefinitionByPublicToken(t.publicToken);if(!o||o.status!=="published")throw new E("FORM_NOT_FOUND","Form is not accepting responses");let n=await e.store.getRevision(t.revisionId,{publicToken:t.publicToken});if(!n||n.definitionId!==o.id)throw new E("REVISION_MISMATCH","Response revision does not match the public session");ct(n.document,t.answers);let r=await lt(e,t.verificationEvidenceRef,o.id,t.publicToken);if(n.document.verification.timing==="before"&&!pe(r,n.document.verification.requirement))throw new E("VERIFICATION_REQUIRED","Verification is required before submission");let a=e.now(),i={id:e.id("response"),definitionId:o.id,revisionId:n.id,locale:N(n.document,[t.locale]),status:Te(n.document,r),authorAssurance:r,answers:structuredClone(t.answers),createdAt:a,updatedAt:a,submittedAt:a},s=await e.store.insertResponseIdempotently(i,t.publicToken,t.idempotencyKey);if(!s.inserted)return s.response;return await e.emit?.("forms.response.submitted",{definitionId:i.definitionId,revisionId:i.revisionId,responseId:i.id,occurredAt:a}),s.response}}}import{flattenPortableFormFields as ft}from"@lssm/lib.contracts-spec/forms";function de(e){let t=new Set(e.questions.map(({name:i})=>i)),o=e.questions.map(pt),n=new Set(e.formSpec?.policy?.pii??[]),r=ft(e.formSpec?.fields??[]),a=Object.entries(e.formSpec?.modelFields??{}).flatMap(([i,s])=>{if(t.has(i))return[];let u=r.find((p)=>p.name===i);return[{id:i,labelKey:u?.labelI18n??i,sensitive:n.has(i)||[...n].some((p)=>p.startsWith(`${i}.`))||u?.kind==="email"||u?.kind==="phone"||s.type==="email"||s.type==="phone"}]});return[...o,...a]}function pt(e){return{id:e.id,labelKey:e.labelKey,sensitive:e.sensitive===!0||e.kind==="email"||e.kind==="phone"}}var dt="response_extensions:AI follow-ups";function mt(e){let t=Array.isArray(e)?e.every((n)=>typeof n!=="object")?e.join(";"):JSON.stringify(e):e==null?"":typeof e==="object"?JSON.stringify(e):String(e);return`"${(/^[\s]*[=+\-@]/.test(t)?`'${t}`:t).replaceAll('"','""')}"`}function Y(e){return`${e.map(mt).join(",")}\r
2
+ `}function Re(e,t,o){if(t.revisionId!==e.id)throw Error("CSV responses must belong to the exported revision");let n=de(e.document),r=new Set(n.map(({id:i})=>i)),a=Object.fromEntries(Object.entries(t.answers).filter(([i])=>!r.has(i)));return[t.id,t.status,t.locale,t.submittedAt??"",...n.map((i)=>{if(!(o.includeSensitive&&o.sensitiveGrant?.authorized)&&i.sensitive)return"[REDACTED]";return t.answers[i.id]}),o.includeSensitive&&o.sensitiveGrant?.authorized?a:"[REDACTED]"]}function Ae(e,t){let o=N(e.document,[t]),n=e.document.content.catalogs[o]??{};return["response_id","status","locale","submitted_at",...de(e.document).map((r)=>`${r.id}:${n[r.labelKey]??r.labelKey}`),dt]}function yt(e,t,o={}){return`\uFEFF${Y(Ae(e,o.locale))}${t.map((n)=>Y(Re(e,n,o))).join("")}`}async function*gt(e,t,o={}){yield`\uFEFF${Y(Ae(e,o.locale))}`;for await(let n of t)yield Y(Re(e,n,o))}import{evalPredicate as vt}from"@lssm/lib.contracts-spec/forms";function ht(e,t,o){let n=e.pages.findIndex((a)=>a.id===t);if(n<0)throw new E("PAGE_NOT_FOUND","Current form page does not exist");return e.pages[n]?.nextPageRules?.find((a)=>vt(o,a.when))?.nextPageId??e.pages[n]?.defaultNextPageId??e.pages[n+1]?.id}function fo(e){return{...ke(e),...Oe(e)}}var wt=/(?:token|secret|password|passwd|authorization|api[_-]?key|credential|cookie|session)/i;function me(e){if(Array.isArray(e))return e.map(me);if(e===null||typeof e!=="object")return e;let t={};for(let[o,n]of Object.entries(e))t[o]=wt.test(o)?"[REDACTED]":me(n);return t}var ye={encrypt:(e)=>e,decrypt:(e)=>e};function bt(e){let t=2166136261;for(let o=0;o<e.length;o+=1)t^=e.charCodeAt(o),t=Math.imul(t,16777619);return(t>>>0).toString(16).padStart(8,"0")}var Et={id:"docs.contracts-runtime-core.redaction",title:"Persisted-state redaction + encryption-at-rest seam",summary:"Secret redaction for durable state plus an encryption-at-rest seam and a PII-safe key hash for logs.",kind:"reference",visibility:"internal",route:"/docs/contracts-runtime-core/redaction",domain:"contracts-runtime-core",owners:["@contractspec-core"],tags:["contracts-runtime-core","security","redaction","encryption"],body:"redactSecrets recursively strips secret-ish keys (token/secret/password/authorization/api-key/credential/cookie/session) so durable cache+queue state never persists secrets (AC12). EncryptionSeam is the encryption-at-rest seam — default identityEncryption (no-op); sensitive entities plug a real cipher transparently to the storage core. hashKey (FNV-1a) lets observability correlate on a stable key id without logging the raw query key (which embeds input/PII)."};function St(e,t={}){let o=t.encryption??ye,n=t.redact,r=t.namespace??"",a=(s)=>`${r}${s}`,i=(s)=>r!==""&&s.startsWith(r)?s.slice(r.length):s;return{async get(s){let u=await e.getItem(a(s));if(u===null)return;let p=await o.decrypt(u);return JSON.parse(p)},async set(s,u){let p=JSON.stringify(n===void 0?u:n(u));await e.setItem(a(s),await o.encrypt(p))},async remove(s){await e.removeItem(a(s))},async keys(s){let u=await e.keys(),p=r===""?u:u.filter((d)=>d.startsWith(r)).map(i);return s===void 0?p:p.filter((d)=>d.startsWith(s))},async clear(){await e.clear()}}}var Dt={id:"docs.contracts-runtime-core.storage-port",title:"Durable storage port (I/O-free contract)",summary:"Value-agnostic durable key/value port; platform impls own serialization, redaction, and encryption-at-rest.",kind:"reference",visibility:"internal",route:"/docs/contracts-runtime-core/storage-port",domain:"contracts-runtime-core",owners:["@contractspec-core"],tags:["contracts-runtime-core","storage","persistence","port"],body:"Durable key/value StoragePort: get/set/remove/keys/clear. Intentionally value-agnostic — the engine layers CacheEntry and MutationQueueEntry shapes on top and namespaces by key prefix. keys(prefix?) supports GC and offline-queue scans. Implementations persist JSON-serializable values and own serialization, per-contract secret redaction, and the encryption-at-rest seam (AC12). B1a ships an in-memory default (createMemoryStorage); IndexedDB (web) and SQLite/AsyncStorage (native) platform variants land in B1b/#7 behind this same contract."};var Tt={id:"docs.contracts-runtime-core.transport",title:"Transport port + absorbed data-transmission concept map",summary:"One Transport port carries the canonical protocol; each former data-transmission concept has an explicit home.",kind:"reference",visibility:"internal",route:"/docs/contracts-runtime-core/transport",domain:"contracts-runtime-core",owners:["@contractspec-core"],tags:["contracts-runtime-core","transport","data-transmission","port"],body:["The single Transport port: execute(envelope, ctx) → Promise<ContractResult<QueryResultEnvelope>>, plus an optional subscribe(tags, handler) realtime seam. REST/MCP/WebSocket/in-memory are interchangeable adapters behind it.","","Absorbed data-transmission concept map (each former concept has exactly one explicit home — no parallel transport types):","- idempotency → ContractResult success field (ContractResultIdempotency{key,replayed?,firstSeenAt?} on ContractSuccess.idempotency). NOT a transport argument.","- subscriptions → Transport.subscribe(tags, handler) seam (no spec type, by design); the version token doubles as the realtime invalidation token. Full delivery is a follow-on; the realtime worker migrates onto this seam in Phase 7.","- invalidation → the InvalidationTag{entity,id?} vocabulary (contracts-spec/query/invalidation) shared by optimistic updates, offline-queue replay, and realtime broadcast; mutations declare the tags they invalidate.","- consistency levels → the typed QueryEnvelope.consistency request field and ContractSuccess.consistency applied field (QueryConsistency = eventual | read-your-writes | strong, default read-your-writes). Typed, never prose. Subsumes the former DataFetchConsistency incl. read-your-writes.","","TransportContext.principal is opaque and carried end-to-end unchanged (AC14, no-strip); policy.auth enforcement stays in authos/identity-rbac."].join(`
3
+ `)};export{Qe as ContractsRuntimeCoreFeature,E as FormsPlatformError,z as authExpiredState,ee as backoffDelayMs,P as computeIsStale,J as conflictState,_ as createCacheStore,q as createConflictResolverRegistry,fe as createDataEngine,Ye as createDataEngineFromEnv,Q as createEngineEvents,fo as createFormsPlatformService,ce as createInflightRegistry,St as createKeyedStorage,oe as createMaintenance,he as createMemoryApprovalNonceStore,j as createMemoryStorage,ie as createMutationEngine,ae as createMutationQueue,Ze as createNoCacheStore,nt as createOnlineOnlyMutationEngine,Fe as createOperationApprovalPort,le as createQueryEngine,I as createStaticReachabilitySource,B as errorState,bt as hashKey,ye as identityEncryption,L as idleState,Ve as isLocalOfflineMode,A as isNetworkAllowed,K as loadingState,G as offlineState,we as operationApprovalInputDigest,je as reachabilityPortDoc,De as readHostEnv,me as redactSecrets,Et as redactionDoc,N as resolveFormLocale,U as resolveLocalOfflinePolicy,ht as resolveNextFormPage,te as resolveQueuedConflict,V as restoreSnapshots,yt as serializeFormResponsesCsv,Dt as storagePortDoc,gt as streamFormResponsesCsv,M as successState,Tt as transportPortDoc};
@@ -0,0 +1 @@
1
+ var c=new Set(["online-only","memory-cache","offline-capable"]),i={"online-only":"online-only",online:"online-only",disabled:"online-only",false:"online-only",off:"online-only","memory-cache":"memory-cache",memory:"memory-cache",cache:"memory-cache","offline-capable":"offline-capable",offline:"offline-capable",enabled:"offline-capable",true:"offline-capable",on:"offline-capable"};function d(e){return typeof e==="string"&&c.has(e)}function t(e={}){let o=e.defaultMode===void 0?{mode:"online-only",source:"default",reason:"No local/offline policy input was supplied."}:f(e.defaultMode,"explicit")??{mode:"online-only",source:"explicit"},l=f(r(e.env),"env",{allowUnknown:!0});return f(e.flag,"feature-flag")??l??o}function r(e){if(typeof e!=="object"||e===null)return e;if("CONTRACTSPEC_LOCAL_OFFLINE"in e)return e.CONTRACTSPEC_LOCAL_OFFLINE;if("mode"in e)return e;return}function f(e,o,l={}){if(e===void 0||e===null||e==="")return;if(typeof e==="boolean")return{mode:e?"offline-capable":"online-only",source:o};if(typeof e==="string"){let n=i[e.trim().toLowerCase()];if(n!==void 0)return{mode:n,source:o};if(l.allowUnknown)return}if(typeof e==="object"&&e!==null&&"mode"in e){let n=e,a=typeof n.mode==="string"?i[n.mode.trim().toLowerCase()]:void 0;if(a!==void 0)return{mode:a,source:o,...typeof n.reason==="string"?{reason:n.reason}:{}};if(l.allowUnknown)return}throw Error(`Unsupported localOffline policy value: ${String(e)}`)}export{d as isLocalOfflineMode,t as resolveLocalOfflinePolicy};
@@ -0,0 +1 @@
1
+ import{isSafeEconomicEvidenceRefId as p}from"@lssm/lib.contracts-spec/operations";import{createCounter as c,createHistogram as f,logger as b}from"@lssm/lib.observability";var g=/(?:token|secret|password|passwd|authorization|api[_-]?key|credential|cookie|session)/i;function d(r){if(Array.isArray(r))return r.map(d);if(r===null||typeof r!=="object")return r;let i={};for(let[t,n]of Object.entries(r))i[t]=g.test(t)?"[REDACTED]":d(n);return i}var R={encrypt:(r)=>r,decrypt:(r)=>r};function u(r){let i=2166136261;for(let t=0;t<r.length;t+=1)i^=r.charCodeAt(t),i=Math.imul(i,16777619);return(i>>>0).toString(16).padStart(8,"0")}var w={id:"docs.contracts-runtime-core.redaction",title:"Persisted-state redaction + encryption-at-rest seam",summary:"Secret redaction for durable state plus an encryption-at-rest seam and a PII-safe key hash for logs.",kind:"reference",visibility:"internal",route:"/docs/contracts-runtime-core/redaction",domain:"contracts-runtime-core",owners:["@contractspec-core"],tags:["contracts-runtime-core","security","redaction","encryption"],body:"redactSecrets recursively strips secret-ish keys (token/secret/password/authorization/api-key/credential/cookie/session) so durable cache+queue state never persists secrets (AC12). EncryptionSeam is the encryption-at-rest seam — default identityEncryption (no-op); sensitive entities plug a real cipher transparently to the storage core. hashKey (FNV-1a) lets observability correlate on a stable key id without logging the raw query key (which embeds input/PII)."};function x(r,i={}){let t=i.logger??b,n=i.hashKeys===!1?(e)=>e:u,l=c("contracts_runtime_cache_hits_total","Cache hits"),m=c("contracts_runtime_cache_misses_total","Cache misses"),a=f("contracts_runtime_fetch_latency_ms","Fetch latency (ms)"),y=c("contracts_runtime_conflicts_total","Mutation conflicts"),h=c("contracts_runtime_economic_evidence_refs_total","Safe economic evidence refs attached to runtime operations"),o=i.correlationId===void 0?{}:{correlationId:i.correlationId};return r.subscribe((e)=>{switch(e.type){case"cache-hit":l.add(1),t.debug("cache.hit",{...o,key:n(e.key)});break;case"cache-miss":m.add(1),t.debug("cache.miss",{...o,key:n(e.key)});break;case"fetch-success":a.record(e.latencyMs),t.info("fetch.success",{...o,key:n(e.key),latencyMs:e.latencyMs});break;case"fetch-error":a.record(e.latencyMs),t.warn("fetch.error",{...o,key:n(e.key),code:e.code,latencyMs:e.latencyMs});break;case"mutation-enqueued":t.info("mutation.enqueued",{...o,id:e.id,queueDepth:e.queueDepth});break;case"mutation-replayed":t.info("mutation.replayed",{...o,id:e.id,queueDepth:e.queueDepth});break;case"mutation-conflict":y.add(1,{strategy:e.strategy,outcome:e.outcome}),t.warn("mutation.conflict",{...o,id:e.id,strategy:e.strategy,outcome:e.outcome});break;case"mutation-retry":t.warn("mutation.retry",{...o,id:e.id,attempt:e.attempt,delayMs:e.delayMs});break;case"mutation-failed":t.error("mutation.failed",{...o,id:e.id,code:e.code});break;case"economic-evidence-attached":{let s=E(e.evidenceRefs);h.add(s.length,{operationKey:e.operationKey}),t.info("economic.evidence.attached",{...o,operationKey:e.operationKey,evidenceRefCount:s.length,evidenceRefs:s,latencyMs:e.latencyMs});break}case"auth-expired":t.warn("auth.expired",{...o,id:e.id});break;case"queue-drained":t.info("queue.drained",{...o,remaining:e.remaining});break;case"gc-collected":t.info("cache.gc",{...o,evicted:e.evicted});break;case"revalidated":t.debug("cache.revalidated",{...o,key:n(e.key)});break}})}var k=new Set(["usage","cost","budget","replay","projection"]);function E(r){return r.flatMap((i)=>{if(typeof i.id!=="string"||!p(i.id)||!k.has(i.kind))return[];return[{id:i.id,kind:i.kind,...typeof i.source==="string"?{source:i.source}:{}}]})}var M={id:"docs.contracts-runtime-core.observability",title:"Engine observability binding (no PII)",summary:"Binds the engine EngineEvents stream to the observability lib with hashed keys, safe economic evidence refs, and structured metrics.",kind:"reference",visibility:"internal",route:"/docs/contracts-runtime-core/observability",domain:"contracts-runtime-core",owners:["@contractspec-core"],tags:["contracts-runtime-core","observability","metrics","logging"],body:"attachObservability subscribes to the framework-neutral EngineEvents stream (emitted by the engine, zero deps) and forwards it to @lssm/lib.observability: structured logs via Logger (debug/info/warn/error) and metrics (cache hit/miss counters, fetch-latency histogram, conflict counter tagged by strategy+outcome, economic evidence ref counter). Query keys embed input, so they are hashed (FNV-1a via hashKey) before logging — never raw (AC12, no PII). economic-evidence-attached events are serialized through a deny-by-default allowlist: ref id, kind, and optional source only; raw provider receipts, prompts, payloads, and unrecognized fields are dropped before log/replay sinks consume them. Optional correlationId is attached to every entry. Lives behind the ./observability subpath so the OTel-backed lib stays out of the main entry bundle; no console.* — logging is the lib's concern."};export{x as attachObservability,M as observabilityDoc};
@@ -0,0 +1 @@
1
+ function i(e){return e!=="offline"}function n(e="online"){let t={signal:e,since:Date.now()};return{getSnapshot:()=>t,subscribe:()=>()=>{}}}var a={id:"docs.contracts-runtime-core.reachability",title:"Reachability input port (tri-state)",summary:"Engine-owned reachability input port; integrations feed it, the engine never imports them.",kind:"reference",visibility:"internal",route:"/docs/contracts-runtime-core/reachability",domain:"contracts-runtime-core",owners:["@contractspec-core"],tags:["contracts-runtime-core","reachability","offline","port"],body:"Tri-state OnlineSignal ('online' | 'restricted' | 'offline'). 'online' allows normal fetch + queue drain. 'restricted' is online-degraded: the engine fetches and drains the queue as if online but may mark results stale-eligible; it never suspends network nor activates the offline queue. Only 'offline' suspends outbound network and activates the durable offline mutation queue. The engine reads reachability solely through ReachabilitySource and MUST NOT import integrations/* — concrete sources (runtime-local networkReachability) are wired via an integration→port adapter (plan §2.3/§4.2, Architect finding 1). isNetworkAllowed mirrors runtime-local's outboundNetworkAllowed = reachability !== 'offline'. createStaticReachabilitySource('online') is the B1a default and online test fixture."};export{n as createStaticReachabilitySource,i as isNetworkAllowed,a as reachabilityPortDoc};
@@ -0,0 +1 @@
1
+ var s=/(?:token|secret|password|passwd|authorization|api[_-]?key|credential|cookie|session)/i;function n(t){if(Array.isArray(t))return t.map(n);if(t===null||typeof t!=="object")return t;let e={};for(let[r,o]of Object.entries(t))e[r]=s.test(r)?"[REDACTED]":n(o);return e}var i={encrypt:(t)=>t,decrypt:(t)=>t};function c(t){let e=2166136261;for(let r=0;r<t.length;r+=1)e^=t.charCodeAt(r),e=Math.imul(e,16777619);return(e>>>0).toString(16).padStart(8,"0")}var a={id:"docs.contracts-runtime-core.redaction",title:"Persisted-state redaction + encryption-at-rest seam",summary:"Secret redaction for durable state plus an encryption-at-rest seam and a PII-safe key hash for logs.",kind:"reference",visibility:"internal",route:"/docs/contracts-runtime-core/redaction",domain:"contracts-runtime-core",owners:["@contractspec-core"],tags:["contracts-runtime-core","security","redaction","encryption"],body:"redactSecrets recursively strips secret-ish keys (token/secret/password/authorization/api-key/credential/cookie/session) so durable cache+queue state never persists secrets (AC12). EncryptionSeam is the encryption-at-rest seam — default identityEncryption (no-op); sensitive entities plug a real cipher transparently to the storage core. hashKey (FNV-1a) lets observability correlate on a stable key id without logging the raw query key (which embeds input/PII)."};export{c as hashKey,i as identityEncryption,n as redactSecrets,a as redactionDoc};
@@ -0,0 +1 @@
1
+ var u=/(?:token|secret|password|passwd|authorization|api[_-]?key|credential|cookie|session)/i;function p(t){if(Array.isArray(t))return t.map(p);if(t===null||typeof t!=="object")return t;let r={};for(let[n,c]of Object.entries(t))r[n]=u.test(n)?"[REDACTED]":p(c);return r}var d={encrypt:(t)=>t,decrypt:(t)=>t};function g(t){let r=2166136261;for(let n=0;n<t.length;n+=1)r^=t.charCodeAt(n),r=Math.imul(r,16777619);return(r>>>0).toString(16).padStart(8,"0")}var l={id:"docs.contracts-runtime-core.redaction",title:"Persisted-state redaction + encryption-at-rest seam",summary:"Secret redaction for durable state plus an encryption-at-rest seam and a PII-safe key hash for logs.",kind:"reference",visibility:"internal",route:"/docs/contracts-runtime-core/redaction",domain:"contracts-runtime-core",owners:["@contractspec-core"],tags:["contracts-runtime-core","security","redaction","encryption"],body:"redactSecrets recursively strips secret-ish keys (token/secret/password/authorization/api-key/credential/cookie/session) so durable cache+queue state never persists secrets (AC12). EncryptionSeam is the encryption-at-rest seam — default identityEncryption (no-op); sensitive entities plug a real cipher transparently to the storage core. hashKey (FNV-1a) lets observability correlate on a stable key id without logging the raw query key (which embeds input/PII)."};function k(t,r={}){let n=r.encryption??d,c=r.redact,o=r.namespace??"",a=(e)=>`${o}${e}`,m=(e)=>o!==""&&e.startsWith(o)?e.slice(o.length):e;return{async get(e){let i=await t.getItem(a(e));if(i===null)return;let s=await n.decrypt(i);return JSON.parse(s)},async set(e,i){let s=JSON.stringify(c===void 0?i:c(i));await t.setItem(a(e),await n.encrypt(s))},async remove(e){await t.removeItem(a(e))},async keys(e){let i=await t.keys(),s=o===""?i:i.filter((y)=>y.startsWith(o)).map(m);return e===void 0?s:s.filter((y)=>y.startsWith(e))},async clear(){await t.clear()}}}export{k as createKeyedStorage};
@@ -0,0 +1 @@
1
+ function o(){let r=new Map;return{get:async(e)=>{let n=r.get(e);return n===void 0?void 0:structuredClone(n)},set:async(e,n)=>{r.set(e,structuredClone(n))},remove:async(e)=>{r.delete(e)},keys:async(e)=>{let n=[...r.keys()];return e===void 0?n:n.filter((t)=>t.startsWith(e))},clear:async()=>{r.clear()}}}export{o as createMemoryStorage};
@@ -0,0 +1 @@
1
+ var e={id:"docs.contracts-runtime-core.storage-port",title:"Durable storage port (I/O-free contract)",summary:"Value-agnostic durable key/value port; platform impls own serialization, redaction, and encryption-at-rest.",kind:"reference",visibility:"internal",route:"/docs/contracts-runtime-core/storage-port",domain:"contracts-runtime-core",owners:["@contractspec-core"],tags:["contracts-runtime-core","storage","persistence","port"],body:"Durable key/value StoragePort: get/set/remove/keys/clear. Intentionally value-agnostic — the engine layers CacheEntry and MutationQueueEntry shapes on top and namespaces by key prefix. keys(prefix?) supports GC and offline-queue scans. Implementations persist JSON-serializable values and own serialization, per-contract secret redaction, and the encryption-at-rest seam (AC12). B1a ships an in-memory default (createMemoryStorage); IndexedDB (web) and SQLite/AsyncStorage (native) platform variants land in B1b/#7 behind this same contract."};export{e as storagePortDoc};
@@ -0,0 +1,2 @@
1
+ var e={id:"docs.contracts-runtime-core.transport",title:"Transport port + absorbed data-transmission concept map",summary:"One Transport port carries the canonical protocol; each former data-transmission concept has an explicit home.",kind:"reference",visibility:"internal",route:"/docs/contracts-runtime-core/transport",domain:"contracts-runtime-core",owners:["@contractspec-core"],tags:["contracts-runtime-core","transport","data-transmission","port"],body:["The single Transport port: execute(envelope, ctx) → Promise<ContractResult<QueryResultEnvelope>>, plus an optional subscribe(tags, handler) realtime seam. REST/MCP/WebSocket/in-memory are interchangeable adapters behind it.","","Absorbed data-transmission concept map (each former concept has exactly one explicit home — no parallel transport types):","- idempotency → ContractResult success field (ContractResultIdempotency{key,replayed?,firstSeenAt?} on ContractSuccess.idempotency). NOT a transport argument.","- subscriptions → Transport.subscribe(tags, handler) seam (no spec type, by design); the version token doubles as the realtime invalidation token. Full delivery is a follow-on; the realtime worker migrates onto this seam in Phase 7.","- invalidation → the InvalidationTag{entity,id?} vocabulary (contracts-spec/query/invalidation) shared by optimistic updates, offline-queue replay, and realtime broadcast; mutations declare the tags they invalidate.","- consistency levels → the typed QueryEnvelope.consistency request field and ContractSuccess.consistency applied field (QueryConsistency = eventual | read-your-writes | strong, default read-your-writes). Typed, never prose. Subsumes the former DataFetchConsistency incl. read-your-writes.","","TransportContext.principal is opaque and carried end-to-end unchanged (AC14, no-strip); policy.auth enforcement stays in authos/identity-rbac."].join(`
2
+ `)};export{e as transportPortDoc};
@@ -0,0 +1,34 @@
1
+ import type { EngineEvents } from './engine/events.js';
2
+ /** Structural logger surface (the lib's `Logger` instance satisfies it). */
3
+ export interface LoggerLike {
4
+ debug(message: string, meta?: Record<string, unknown>): void;
5
+ info(message: string, meta?: Record<string, unknown>): void;
6
+ warn(message: string, meta?: Record<string, unknown>): void;
7
+ error(message: string, meta?: Record<string, unknown>): void;
8
+ }
9
+ export interface ObservabilityOptions {
10
+ logger?: LoggerLike;
11
+ correlationId?: string;
12
+ /** Hash query keys before logging (keys may embed input/PII). Default true. */
13
+ hashKeys?: boolean;
14
+ }
15
+ /**
16
+ * Wire the engine's {@link EngineEvents} stream into `@lssm/lib.observability`:
17
+ * structured logs (correlation id, hashed keys — never raw input/PII) plus
18
+ * metrics (cache hit/miss counters, fetch-latency histogram, conflict counter,
19
+ * economic evidence ref counter).
20
+ * Returns an unsubscribe function. No `console.*` — logging goes through the lib.
21
+ */
22
+ export declare function attachObservability(events: EngineEvents, options?: ObservabilityOptions): () => void;
23
+ export declare const observabilityDoc: {
24
+ id: string;
25
+ title: string;
26
+ summary: string;
27
+ kind: "reference";
28
+ visibility: "internal";
29
+ route: string;
30
+ domain: string;
31
+ owners: string[];
32
+ tags: string[];
33
+ body: string;
34
+ };
@@ -0,0 +1,2 @@
1
+ // @bun
2
+ import{isSafeEconomicEvidenceRefId as p}from"@lssm/lib.contracts-spec/operations";import{createCounter as c,createHistogram as f,logger as b}from"@lssm/lib.observability";var g=/(?:token|secret|password|passwd|authorization|api[_-]?key|credential|cookie|session)/i;function d(r){if(Array.isArray(r))return r.map(d);if(r===null||typeof r!=="object")return r;let i={};for(let[t,n]of Object.entries(r))i[t]=g.test(t)?"[REDACTED]":d(n);return i}var R={encrypt:(r)=>r,decrypt:(r)=>r};function u(r){let i=2166136261;for(let t=0;t<r.length;t+=1)i^=r.charCodeAt(t),i=Math.imul(i,16777619);return(i>>>0).toString(16).padStart(8,"0")}var w={id:"docs.contracts-runtime-core.redaction",title:"Persisted-state redaction + encryption-at-rest seam",summary:"Secret redaction for durable state plus an encryption-at-rest seam and a PII-safe key hash for logs.",kind:"reference",visibility:"internal",route:"/docs/contracts-runtime-core/redaction",domain:"contracts-runtime-core",owners:["@contractspec-core"],tags:["contracts-runtime-core","security","redaction","encryption"],body:"redactSecrets recursively strips secret-ish keys (token/secret/password/authorization/api-key/credential/cookie/session) so durable cache+queue state never persists secrets (AC12). EncryptionSeam is the encryption-at-rest seam \u2014 default identityEncryption (no-op); sensitive entities plug a real cipher transparently to the storage core. hashKey (FNV-1a) lets observability correlate on a stable key id without logging the raw query key (which embeds input/PII)."};function x(r,i={}){let t=i.logger??b,n=i.hashKeys===!1?(e)=>e:u,l=c("contracts_runtime_cache_hits_total","Cache hits"),m=c("contracts_runtime_cache_misses_total","Cache misses"),a=f("contracts_runtime_fetch_latency_ms","Fetch latency (ms)"),y=c("contracts_runtime_conflicts_total","Mutation conflicts"),h=c("contracts_runtime_economic_evidence_refs_total","Safe economic evidence refs attached to runtime operations"),o=i.correlationId===void 0?{}:{correlationId:i.correlationId};return r.subscribe((e)=>{switch(e.type){case"cache-hit":l.add(1),t.debug("cache.hit",{...o,key:n(e.key)});break;case"cache-miss":m.add(1),t.debug("cache.miss",{...o,key:n(e.key)});break;case"fetch-success":a.record(e.latencyMs),t.info("fetch.success",{...o,key:n(e.key),latencyMs:e.latencyMs});break;case"fetch-error":a.record(e.latencyMs),t.warn("fetch.error",{...o,key:n(e.key),code:e.code,latencyMs:e.latencyMs});break;case"mutation-enqueued":t.info("mutation.enqueued",{...o,id:e.id,queueDepth:e.queueDepth});break;case"mutation-replayed":t.info("mutation.replayed",{...o,id:e.id,queueDepth:e.queueDepth});break;case"mutation-conflict":y.add(1,{strategy:e.strategy,outcome:e.outcome}),t.warn("mutation.conflict",{...o,id:e.id,strategy:e.strategy,outcome:e.outcome});break;case"mutation-retry":t.warn("mutation.retry",{...o,id:e.id,attempt:e.attempt,delayMs:e.delayMs});break;case"mutation-failed":t.error("mutation.failed",{...o,id:e.id,code:e.code});break;case"economic-evidence-attached":{let s=E(e.evidenceRefs);h.add(s.length,{operationKey:e.operationKey}),t.info("economic.evidence.attached",{...o,operationKey:e.operationKey,evidenceRefCount:s.length,evidenceRefs:s,latencyMs:e.latencyMs});break}case"auth-expired":t.warn("auth.expired",{...o,id:e.id});break;case"queue-drained":t.info("queue.drained",{...o,remaining:e.remaining});break;case"gc-collected":t.info("cache.gc",{...o,evicted:e.evicted});break;case"revalidated":t.debug("cache.revalidated",{...o,key:n(e.key)});break}})}var k=new Set(["usage","cost","budget","replay","projection"]);function E(r){return r.flatMap((i)=>{if(typeof i.id!=="string"||!p(i.id)||!k.has(i.kind))return[];return[{id:i.id,kind:i.kind,...typeof i.source==="string"?{source:i.source}:{}}]})}var M={id:"docs.contracts-runtime-core.observability",title:"Engine observability binding (no PII)",summary:"Binds the engine EngineEvents stream to the observability lib with hashed keys, safe economic evidence refs, and structured metrics.",kind:"reference",visibility:"internal",route:"/docs/contracts-runtime-core/observability",domain:"contracts-runtime-core",owners:["@contractspec-core"],tags:["contracts-runtime-core","observability","metrics","logging"],body:"attachObservability subscribes to the framework-neutral EngineEvents stream (emitted by the engine, zero deps) and forwards it to @lssm/lib.observability: structured logs via Logger (debug/info/warn/error) and metrics (cache hit/miss counters, fetch-latency histogram, conflict counter tagged by strategy+outcome, economic evidence ref counter). Query keys embed input, so they are hashed (FNV-1a via hashKey) before logging \u2014 never raw (AC12, no PII). economic-evidence-attached events are serialized through a deny-by-default allowlist: ref id, kind, and optional source only; raw provider receipts, prompts, payloads, and unrecognized fields are dropped before log/replay sinks consume them. Optional correlationId is attached to every entry. Lives behind the ./observability subpath so the OTel-backed lib stays out of the main entry bundle; no console.* \u2014 logging is the lib's concern."};export{x as attachObservability,M as observabilityDoc};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Tri-state network reachability, modelled as an input the engine *reads*
3
+ * rather than a capability it *owns*.
4
+ *
5
+ * - `online` — outbound network is fully available; normal fetch + queue drain.
6
+ * - `restricted` — online-degraded: the engine still fetches and drains the
7
+ * offline queue (treats this as online for liveness), but may apply degraded
8
+ * expectations (e.g. mark results stale-eligible / prefer revalidation). It
9
+ * does NOT suspend network and does NOT activate the offline mutation queue.
10
+ * - `offline` — the only state that suspends outbound network and activates the
11
+ * durable offline mutation queue.
12
+ */
13
+ export type OnlineSignal = 'online' | 'restricted' | 'offline';
14
+ /** A point-in-time reachability observation. */
15
+ export interface ReachabilitySnapshot {
16
+ signal: OnlineSignal;
17
+ /** Epoch ms when this signal was observed. */
18
+ since: number;
19
+ }
20
+ /** Listener notified whenever the reachability signal changes. */
21
+ export type ReachabilityListener = (snapshot: ReachabilitySnapshot) => void;
22
+ /**
23
+ * Reachability INPUT PORT, typed inside `contracts-runtime-core`.
24
+ *
25
+ * The engine consumes reachability exclusively through this port and MUST NOT
26
+ * import `@lssm/integration.*`. Concrete sources (e.g. a runtime profile's
27
+ * `networkReachability`) are wired in by the integration layer via an
28
+ * integration→port adapter, preserving the downward dependency rule
29
+ * (Architect finding 1 / plan §2.3 + §4.2).
30
+ */
31
+ export interface ReachabilitySource {
32
+ /** Current reachability snapshot. */
33
+ getSnapshot(): ReachabilitySnapshot;
34
+ /** Subscribe to reachability changes. Returns an unsubscribe function. */
35
+ subscribe(listener: ReachabilityListener): () => void;
36
+ }
37
+ /**
38
+ * Engine predicate: outbound network is allowed unless fully `offline`.
39
+ *
40
+ * Mirrors the existing runtime-local convention
41
+ * `outboundNetworkAllowed = reachability !== 'offline'`, so `restricted` is
42
+ * treated as online-degraded rather than offline.
43
+ */
44
+ export declare function isNetworkAllowed(signal: OnlineSignal): boolean;
45
+ /**
46
+ * Static reachability source: emits a single, never-changing signal. The
47
+ * default (`online`) is the B1a synchronous-engine baseline and the test
48
+ * fixture for online paths. Durable/observed sources arrive via the
49
+ * integration→port adapter (#10), not from this lib.
50
+ */
51
+ export declare function createStaticReachabilitySource(signal?: OnlineSignal): ReachabilitySource;
52
+ export declare const reachabilityPortDoc: {
53
+ id: string;
54
+ title: string;
55
+ summary: string;
56
+ kind: "reference";
57
+ visibility: "internal";
58
+ route: string;
59
+ domain: string;
60
+ owners: string[];
61
+ tags: string[];
62
+ body: string;
63
+ };
@@ -0,0 +1,2 @@
1
+ // @bun
2
+ function i(e){return e!=="offline"}function n(e="online"){let t={signal:e,since:Date.now()};return{getSnapshot:()=>t,subscribe:()=>()=>{}}}var a={id:"docs.contracts-runtime-core.reachability",title:"Reachability input port (tri-state)",summary:"Engine-owned reachability input port; integrations feed it, the engine never imports them.",kind:"reference",visibility:"internal",route:"/docs/contracts-runtime-core/reachability",domain:"contracts-runtime-core",owners:["@contractspec-core"],tags:["contracts-runtime-core","reachability","offline","port"],body:"Tri-state OnlineSignal ('online' | 'restricted' | 'offline'). 'online' allows normal fetch + queue drain. 'restricted' is online-degraded: the engine fetches and drains the queue as if online but may mark results stale-eligible; it never suspends network nor activates the offline queue. Only 'offline' suspends outbound network and activates the durable offline mutation queue. The engine reads reachability solely through ReachabilitySource and MUST NOT import integrations/* \u2014 concrete sources (runtime-local networkReachability) are wired via an integration\u2192port adapter (plan \xA72.3/\xA74.2, Architect finding 1). isNetworkAllowed mirrors runtime-local's outboundNetworkAllowed = reachability !== 'offline'. createStaticReachabilitySource('online') is the B1a default and online test fixture."};export{n as createStaticReachabilitySource,i as isNetworkAllowed,a as reachabilityPortDoc};
@@ -0,0 +1 @@
1
+ export {};