@czap/astro 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (159) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +19 -0
  3. package/dist/Satellite.d.ts +42 -0
  4. package/dist/Satellite.d.ts.map +1 -0
  5. package/dist/Satellite.js +55 -0
  6. package/dist/Satellite.js.map +1 -0
  7. package/dist/client-directives/gpu.d.ts +3 -0
  8. package/dist/client-directives/gpu.d.ts.map +1 -0
  9. package/dist/client-directives/gpu.js +5 -0
  10. package/dist/client-directives/gpu.js.map +1 -0
  11. package/dist/client-directives/llm.d.ts +3 -0
  12. package/dist/client-directives/llm.d.ts.map +1 -0
  13. package/dist/client-directives/llm.js +5 -0
  14. package/dist/client-directives/llm.js.map +1 -0
  15. package/dist/client-directives/satellite.d.ts +3 -0
  16. package/dist/client-directives/satellite.d.ts.map +1 -0
  17. package/dist/client-directives/satellite.js +5 -0
  18. package/dist/client-directives/satellite.js.map +1 -0
  19. package/dist/client-directives/stream.d.ts +3 -0
  20. package/dist/client-directives/stream.d.ts.map +1 -0
  21. package/dist/client-directives/stream.js +5 -0
  22. package/dist/client-directives/stream.js.map +1 -0
  23. package/dist/client-directives/wasm.d.ts +3 -0
  24. package/dist/client-directives/wasm.d.ts.map +1 -0
  25. package/dist/client-directives/wasm.js +6 -0
  26. package/dist/client-directives/wasm.js.map +1 -0
  27. package/dist/client-directives/worker.d.ts +3 -0
  28. package/dist/client-directives/worker.d.ts.map +1 -0
  29. package/dist/client-directives/worker.js +5 -0
  30. package/dist/client-directives/worker.js.map +1 -0
  31. package/dist/detect-upgrade.d.ts +16 -0
  32. package/dist/detect-upgrade.d.ts.map +1 -0
  33. package/dist/detect-upgrade.js +105 -0
  34. package/dist/detect-upgrade.js.map +1 -0
  35. package/dist/headers.d.ts +45 -0
  36. package/dist/headers.d.ts.map +1 -0
  37. package/dist/headers.js +64 -0
  38. package/dist/headers.js.map +1 -0
  39. package/dist/index.d.ts +30 -0
  40. package/dist/index.d.ts.map +1 -0
  41. package/dist/index.js +26 -0
  42. package/dist/index.js.map +1 -0
  43. package/dist/integration.d.ts +76 -0
  44. package/dist/integration.d.ts.map +1 -0
  45. package/dist/integration.js +240 -0
  46. package/dist/integration.js.map +1 -0
  47. package/dist/middleware.d.ts +69 -0
  48. package/dist/middleware.d.ts.map +1 -0
  49. package/dist/middleware.js +75 -0
  50. package/dist/middleware.js.map +1 -0
  51. package/dist/quantize.d.ts +50 -0
  52. package/dist/quantize.d.ts.map +1 -0
  53. package/dist/quantize.js +122 -0
  54. package/dist/quantize.js.map +1 -0
  55. package/dist/runtime/boundary.d.ts +123 -0
  56. package/dist/runtime/boundary.d.ts.map +1 -0
  57. package/dist/runtime/boundary.js +164 -0
  58. package/dist/runtime/boundary.js.map +1 -0
  59. package/dist/runtime/globals.d.ts +32 -0
  60. package/dist/runtime/globals.d.ts.map +1 -0
  61. package/dist/runtime/globals.js +45 -0
  62. package/dist/runtime/globals.js.map +1 -0
  63. package/dist/runtime/gpu.d.ts +15 -0
  64. package/dist/runtime/gpu.d.ts.map +1 -0
  65. package/dist/runtime/gpu.js +266 -0
  66. package/dist/runtime/gpu.js.map +1 -0
  67. package/dist/runtime/index.d.ts +7 -0
  68. package/dist/runtime/index.d.ts.map +1 -0
  69. package/dist/runtime/index.js +5 -0
  70. package/dist/runtime/index.js.map +1 -0
  71. package/dist/runtime/llm-receipt-tracker.d.ts +21 -0
  72. package/dist/runtime/llm-receipt-tracker.d.ts.map +1 -0
  73. package/dist/runtime/llm-receipt-tracker.js +60 -0
  74. package/dist/runtime/llm-receipt-tracker.js.map +1 -0
  75. package/dist/runtime/llm-render-pipeline.d.ts +89 -0
  76. package/dist/runtime/llm-render-pipeline.d.ts.map +1 -0
  77. package/dist/runtime/llm-render-pipeline.js +241 -0
  78. package/dist/runtime/llm-render-pipeline.js.map +1 -0
  79. package/dist/runtime/llm-session.d.ts +126 -0
  80. package/dist/runtime/llm-session.d.ts.map +1 -0
  81. package/dist/runtime/llm-session.js +385 -0
  82. package/dist/runtime/llm-session.js.map +1 -0
  83. package/dist/runtime/llm.d.ts +16 -0
  84. package/dist/runtime/llm.d.ts.map +1 -0
  85. package/dist/runtime/llm.js +273 -0
  86. package/dist/runtime/llm.js.map +1 -0
  87. package/dist/runtime/policy.d.ts +100 -0
  88. package/dist/runtime/policy.d.ts.map +1 -0
  89. package/dist/runtime/policy.js +147 -0
  90. package/dist/runtime/policy.js.map +1 -0
  91. package/dist/runtime/receipt-chain.d.ts +22 -0
  92. package/dist/runtime/receipt-chain.d.ts.map +1 -0
  93. package/dist/runtime/receipt-chain.js +80 -0
  94. package/dist/runtime/receipt-chain.js.map +1 -0
  95. package/dist/runtime/runtime-session.d.ts +34 -0
  96. package/dist/runtime/runtime-session.d.ts.map +1 -0
  97. package/dist/runtime/runtime-session.js +102 -0
  98. package/dist/runtime/runtime-session.js.map +1 -0
  99. package/dist/runtime/satellite.d.ts +13 -0
  100. package/dist/runtime/satellite.d.ts.map +1 -0
  101. package/dist/runtime/satellite.js +59 -0
  102. package/dist/runtime/satellite.js.map +1 -0
  103. package/dist/runtime/slots.d.ts +34 -0
  104. package/dist/runtime/slots.d.ts.map +1 -0
  105. package/dist/runtime/slots.js +108 -0
  106. package/dist/runtime/slots.js.map +1 -0
  107. package/dist/runtime/stream-session.d.ts +47 -0
  108. package/dist/runtime/stream-session.d.ts.map +1 -0
  109. package/dist/runtime/stream-session.js +82 -0
  110. package/dist/runtime/stream-session.js.map +1 -0
  111. package/dist/runtime/stream.d.ts +9 -0
  112. package/dist/runtime/stream.d.ts.map +1 -0
  113. package/dist/runtime/stream.js +308 -0
  114. package/dist/runtime/stream.js.map +1 -0
  115. package/dist/runtime/url-policy.d.ts +28 -0
  116. package/dist/runtime/url-policy.d.ts.map +1 -0
  117. package/dist/runtime/url-policy.js +87 -0
  118. package/dist/runtime/url-policy.js.map +1 -0
  119. package/dist/runtime/wasm.d.ts +20 -0
  120. package/dist/runtime/wasm.d.ts.map +1 -0
  121. package/dist/runtime/wasm.js +70 -0
  122. package/dist/runtime/wasm.js.map +1 -0
  123. package/dist/runtime/worker.d.ts +11 -0
  124. package/dist/runtime/worker.d.ts.map +1 -0
  125. package/dist/runtime/worker.js +249 -0
  126. package/dist/runtime/worker.js.map +1 -0
  127. package/package.json +106 -0
  128. package/src/Satellite.astro +39 -0
  129. package/src/Satellite.ts +84 -0
  130. package/src/client-directives/gpu.ts +5 -0
  131. package/src/client-directives/llm.ts +5 -0
  132. package/src/client-directives/satellite.ts +5 -0
  133. package/src/client-directives/stream.ts +5 -0
  134. package/src/client-directives/wasm.ts +6 -0
  135. package/src/client-directives/worker.ts +5 -0
  136. package/src/detect-upgrade.ts +105 -0
  137. package/src/headers.ts +84 -0
  138. package/src/index.ts +30 -0
  139. package/src/integration.ts +309 -0
  140. package/src/middleware.ts +133 -0
  141. package/src/quantize.ts +173 -0
  142. package/src/runtime/boundary.ts +263 -0
  143. package/src/runtime/globals.ts +57 -0
  144. package/src/runtime/gpu.ts +291 -0
  145. package/src/runtime/index.ts +12 -0
  146. package/src/runtime/llm-receipt-tracker.ts +88 -0
  147. package/src/runtime/llm-render-pipeline.ts +366 -0
  148. package/src/runtime/llm-session.ts +548 -0
  149. package/src/runtime/llm.ts +344 -0
  150. package/src/runtime/policy.ts +229 -0
  151. package/src/runtime/receipt-chain.ts +106 -0
  152. package/src/runtime/runtime-session.ts +139 -0
  153. package/src/runtime/satellite.ts +80 -0
  154. package/src/runtime/slots.ts +136 -0
  155. package/src/runtime/stream-session.ts +125 -0
  156. package/src/runtime/stream.ts +407 -0
  157. package/src/runtime/url-policy.ts +107 -0
  158. package/src/runtime/wasm.ts +85 -0
  159. package/src/runtime/worker.ts +307 -0
@@ -0,0 +1,273 @@
1
+ import { Diagnostics } from '@czap/core';
2
+ import { createLLMSession } from './llm-session.js';
3
+ import { readRuntimeHtmlPolicy, readRuntimeEndpointPolicy } from './policy.js';
4
+ import { allowRuntimeEndpointUrl } from './url-policy.js';
5
+ const SAFE_LLM_TARGET_SELECTOR = /^(?:#[A-Za-z][\w-]*|\.[A-Za-z_][\w-]*|\[data-czap-target="[-:A-Za-z0-9_]+"\])$/;
6
+ const parseJSONUnknown = (text) => JSON.parse(text);
7
+ function normalizeToolDeltaContent(content, toolArgs) {
8
+ if (typeof content === 'string') {
9
+ return content;
10
+ }
11
+ if (typeof toolArgs === 'string') {
12
+ return toolArgs;
13
+ }
14
+ if (toolArgs && typeof toolArgs === 'object') {
15
+ return JSON.stringify(toolArgs);
16
+ }
17
+ return undefined;
18
+ }
19
+ function firstMeaningfulCharCode(raw) {
20
+ for (let index = 0; index < raw.length; index++) {
21
+ const code = raw.charCodeAt(index);
22
+ if (code !== 32 && code !== 9 && code !== 10 && code !== 13) {
23
+ return code;
24
+ }
25
+ }
26
+ return -1;
27
+ }
28
+ function toStructuredChunk(type, partial, content, toolName, toolArgs) {
29
+ const normalizedToolName = typeof toolName === 'string' ? toolName : undefined;
30
+ const normalizedContent = type === 'tool-call-delta'
31
+ ? normalizeToolDeltaContent(content, toolArgs)
32
+ : typeof content === 'string'
33
+ ? content
34
+ : undefined;
35
+ return {
36
+ type,
37
+ partial: partial === true,
38
+ content: normalizedContent,
39
+ toolName: normalizedToolName,
40
+ toolArgs,
41
+ };
42
+ }
43
+ /**
44
+ * Parse a raw `MessageEvent` payload into an {@link LLMChunk}. Returns
45
+ * `null` when the payload is unrecognised so callers can drop
46
+ * non-chunk events (metrics, heartbeats, ...) silently.
47
+ */
48
+ export function parseLLMChunk(event) {
49
+ const decoded = decodeLLMEventData(event.data);
50
+ return decoded.type === 'chunk' ? decoded.chunk : null;
51
+ }
52
+ function mapDeviceTier() {
53
+ switch (document.documentElement.getAttribute('data-czap-tier')) {
54
+ case 'static':
55
+ return 'none';
56
+ case 'styled':
57
+ return 'transitions';
58
+ case 'gpu':
59
+ return 'compute';
60
+ case 'animated':
61
+ return 'physics';
62
+ default:
63
+ return 'animations';
64
+ }
65
+ }
66
+ function parseLLMError(error) {
67
+ if (typeof error.content === 'string') {
68
+ return error.content;
69
+ }
70
+ if (typeof error.message === 'string') {
71
+ return error.message;
72
+ }
73
+ return 'unknown error';
74
+ }
75
+ function isStructuredLLMEvent(value) {
76
+ return typeof value === 'object' && value !== null;
77
+ }
78
+ function decodeStructuredLLMEventData(data) {
79
+ if (!isStructuredLLMEvent(data)) {
80
+ return { type: 'ignored' };
81
+ }
82
+ switch (data.type) {
83
+ case 'receipt':
84
+ return isReceiptEnvelope(data.data) ? { type: 'receipt', envelope: data.data } : { type: 'ignored' };
85
+ case 'error': {
86
+ return { type: 'error', message: parseLLMError(data) };
87
+ }
88
+ case 'text':
89
+ case 'tool-call-start':
90
+ case 'tool-call-delta':
91
+ case 'tool-call-end':
92
+ case 'done':
93
+ return {
94
+ type: 'chunk',
95
+ chunk: toStructuredChunk(data.type, data.partial, data.content, data.toolName, data.toolArgs),
96
+ };
97
+ default:
98
+ return { type: 'ignored' };
99
+ }
100
+ }
101
+ function decodeLLMEventData(data) {
102
+ if (typeof data === 'string') {
103
+ const firstChar = firstMeaningfulCharCode(data);
104
+ if (firstChar === -1) {
105
+ return { type: 'ignored' };
106
+ }
107
+ if (firstChar !== 123 && firstChar !== 91) {
108
+ return {
109
+ type: 'chunk',
110
+ chunk: {
111
+ type: 'text',
112
+ partial: false,
113
+ content: data,
114
+ toolName: undefined,
115
+ toolArgs: undefined,
116
+ },
117
+ };
118
+ }
119
+ let parsed;
120
+ let syntaxError = false;
121
+ try {
122
+ parsed = parseJSONUnknown(data);
123
+ }
124
+ catch (error) {
125
+ if (error instanceof SyntaxError) {
126
+ syntaxError = true;
127
+ }
128
+ else {
129
+ throw error;
130
+ }
131
+ }
132
+ if (syntaxError) {
133
+ return { type: 'ignored' };
134
+ }
135
+ return decodeStructuredLLMEventData(parsed);
136
+ }
137
+ return decodeStructuredLLMEventData(data);
138
+ }
139
+ function isReceiptEnvelope(value) {
140
+ if (typeof value !== 'object' || value === null)
141
+ return false;
142
+ if (!('hash' in value) || !('previous' in value))
143
+ return false;
144
+ return typeof value.hash === 'string';
145
+ }
146
+ function resolveLLMTarget(element, selector) {
147
+ if (!selector || !SAFE_LLM_TARGET_SELECTOR.test(selector)) {
148
+ return element;
149
+ }
150
+ try {
151
+ const found = element.querySelector(selector);
152
+ return found instanceof HTMLElement ? found : element;
153
+ }
154
+ catch {
155
+ return element;
156
+ }
157
+ }
158
+ /**
159
+ * Entry point used by the `client:llm` directive to start a streaming
160
+ * LLM session on `element`. Reads `data-czap-llm-url` (plus optional
161
+ * target / mode attributes), validates it against the runtime
162
+ * endpoint policy, opens an SSE stream, and drives an
163
+ * {@link LLMSessionShape} to completion.
164
+ */
165
+ export function initLLMDirective(load, element) {
166
+ const endpointPolicy = readRuntimeEndpointPolicy();
167
+ const htmlPolicy = readRuntimeHtmlPolicy();
168
+ const llmUrl = allowRuntimeEndpointUrl(element.getAttribute('data-czap-llm-url'), 'llm', 'czap/astro.llm', {
169
+ crossOriginRejected: 'llm-cross-origin-url-rejected',
170
+ malformedUrl: 'llm-malformed-url-rejected',
171
+ originNotAllowed: 'llm-origin-not-allowed',
172
+ endpointKindNotPermitted: 'llm-endpoint-kind-not-permitted',
173
+ }, endpointPolicy);
174
+ if (!llmUrl) {
175
+ return;
176
+ }
177
+ const mode = element.getAttribute('data-czap-llm-mode') ?? 'append';
178
+ const targetSelector = element.getAttribute('data-czap-llm-target');
179
+ const resolveTarget = () => resolveLLMTarget(element, targetSelector);
180
+ const resetTarget = (target) => {
181
+ target.replaceChildren();
182
+ };
183
+ let source = null;
184
+ const session = createLLMSession({
185
+ element,
186
+ target: resolveTarget(),
187
+ mode,
188
+ getDeviceTier: mapDeviceTier,
189
+ htmlPolicy: htmlPolicy.llmDefault,
190
+ allowTrustedHtml: htmlPolicy.allowTrustedHtml,
191
+ });
192
+ const cleanupSource = () => {
193
+ if (source) {
194
+ source.onopen = null;
195
+ source.onmessage = null;
196
+ source.onerror = null;
197
+ }
198
+ source?.close();
199
+ source = null;
200
+ };
201
+ const cleanup = () => {
202
+ cleanupSource();
203
+ session.dispose();
204
+ };
205
+ const handleDisconnect = () => {
206
+ cleanupSource();
207
+ session.beginReconnect();
208
+ const strategy = session.replayGap();
209
+ if (strategy.type === 'replay') {
210
+ return;
211
+ }
212
+ element.dispatchEvent(new CustomEvent('czap:llm-error', {
213
+ detail: { reason: 'connection-error', strategy: strategy.type },
214
+ bubbles: true,
215
+ }));
216
+ };
217
+ const connect = () => {
218
+ cleanupSource();
219
+ const target = resolveTarget();
220
+ resetTarget(target);
221
+ session.reset(target);
222
+ source = new EventSource(llmUrl);
223
+ source.onopen = () => {
224
+ session.activate();
225
+ element.dispatchEvent(new CustomEvent('czap:llm-start', { bubbles: true }));
226
+ };
227
+ source.onmessage = (event) => {
228
+ const decoded = decodeLLMEventData(event.data);
229
+ switch (decoded.type) {
230
+ case 'receipt':
231
+ session.rememberEnvelope(decoded.envelope);
232
+ return;
233
+ case 'error':
234
+ element.dispatchEvent(new CustomEvent('czap:llm-error', {
235
+ detail: { message: decoded.message },
236
+ bubbles: true,
237
+ }));
238
+ cleanupSource();
239
+ return;
240
+ case 'ignored':
241
+ return;
242
+ case 'chunk':
243
+ if (session.ingest(decoded.chunk) === 'done') {
244
+ cleanupSource();
245
+ }
246
+ return;
247
+ }
248
+ };
249
+ source.onerror = () => {
250
+ handleDisconnect();
251
+ };
252
+ };
253
+ try {
254
+ connect();
255
+ }
256
+ catch (error) {
257
+ Diagnostics.error({
258
+ source: 'czap/astro.llm',
259
+ code: 'llm-runtime-init-failed',
260
+ message: 'The shared LLM runtime could not initialize.',
261
+ detail: error instanceof Error ? error.message : String(error),
262
+ });
263
+ cleanup();
264
+ }
265
+ element.addEventListener('czap:reinit', () => {
266
+ connect();
267
+ });
268
+ element.addEventListener('czap:dispose', () => {
269
+ cleanup();
270
+ });
271
+ load();
272
+ }
273
+ //# sourceMappingURL=llm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"llm.js","sourceRoot":"","sources":["../../src/runtime/llm.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,100 @@
1
+ /**
2
+ * Runtime security-policy data model: how `@czap/astro`'s client
3
+ * directives decide which endpoints they may fetch and how to treat
4
+ * HTML returned from those endpoints.
5
+ *
6
+ * @module
7
+ */
8
+ import type { HtmlPolicy, RuntimeEndpointKind, RuntimeEndpointPolicy } from '@czap/web';
9
+ /**
10
+ * User-supplied HTML policy. Directives fall back to conservative
11
+ * defaults (`text` for LLM output, `sanitized-html` for stream
12
+ * payloads) when individual fields are omitted.
13
+ */
14
+ export interface RuntimeHtmlPolicy {
15
+ /** Default HTML trust level for `client:llm` text sinks. */
16
+ readonly llmDefault?: HtmlPolicy;
17
+ /** Default HTML trust level for `client:stream` payloads. */
18
+ readonly streamDefault?: HtmlPolicy;
19
+ /** Opt-in to `trusted-html` system-wide. */
20
+ readonly allowTrustedHtml?: boolean;
21
+ }
22
+ /**
23
+ * Combined runtime security policy (endpoint + HTML). Passed to
24
+ * {@link configureRuntimePolicy} and persisted on `window` for
25
+ * directive consumption.
26
+ */
27
+ export interface RuntimeSecurityPolicy {
28
+ /** Endpoint allowlist configuration. */
29
+ readonly endpointPolicy?: RuntimeEndpointPolicy;
30
+ /** HTML policy configuration. */
31
+ readonly htmlPolicy?: RuntimeHtmlPolicy;
32
+ }
33
+ /**
34
+ * Frozen, fully-populated form of {@link RuntimeEndpointPolicy}. Every
35
+ * `RuntimeEndpointKind` has an allowlist (possibly empty) so callers
36
+ * can index safely without presence checks.
37
+ */
38
+ export interface NormalizedRuntimeEndpointPolicy {
39
+ readonly mode: RuntimeEndpointPolicy['mode'];
40
+ readonly allowOrigins: readonly string[];
41
+ readonly byKind: Readonly<Record<RuntimeEndpointKind, readonly string[]>>;
42
+ }
43
+ /**
44
+ * Frozen form of {@link RuntimeSecurityPolicy} with every optional
45
+ * field materialised to its default. Produced by
46
+ * {@link normalizeRuntimeSecurityPolicy}.
47
+ */
48
+ export interface NormalizedRuntimeSecurityPolicy {
49
+ readonly endpointPolicy: NormalizedRuntimeEndpointPolicy;
50
+ readonly htmlPolicy: {
51
+ readonly llmDefault: HtmlPolicy;
52
+ readonly streamDefault: HtmlPolicy;
53
+ readonly allowTrustedHtml: boolean;
54
+ };
55
+ }
56
+ /**
57
+ * Freeze a user-supplied security policy into the fully-populated
58
+ * {@link NormalizedRuntimeSecurityPolicy} form. Applies conservative
59
+ * defaults for any missing fields.
60
+ */
61
+ export declare function normalizeRuntimeSecurityPolicy(policy?: RuntimeSecurityPolicy): NormalizedRuntimeSecurityPolicy;
62
+ /**
63
+ * Normalise `policy` and install it as the active runtime configuration.
64
+ *
65
+ * The first call in a given realm publishes the value to
66
+ * `window.__CZAP_RUNTIME_POLICY__` with `configurable: false` and
67
+ * `writable: false`, so an attacker cannot redefine the global via
68
+ * `Object.defineProperty` to install a permissive policy. Subsequent
69
+ * calls (HMR, test re-initialisation) update the module-private store
70
+ * only — the window global stays locked at the first published value.
71
+ *
72
+ * Production callers run `configureRuntimePolicy` once during the
73
+ * integration boot script. Test harnesses re-call it freely; reads
74
+ * via `readRuntimePolicy()` return the latest configured value
75
+ * because the module-private store is checked first.
76
+ */
77
+ export declare function configureRuntimePolicy(policy?: RuntimeSecurityPolicy): NormalizedRuntimeSecurityPolicy;
78
+ /**
79
+ * Read the active runtime policy. Prefers the module-private store
80
+ * (the canonical source of truth), falls back to the cross-bundle
81
+ * window broadcast for consumers loaded as a separate bundle, and
82
+ * finally to a default normalised policy when nothing has been
83
+ * configured (e.g. in tests that haven't called
84
+ * `configureRuntimePolicy` yet).
85
+ */
86
+ export declare function readRuntimePolicy(): NormalizedRuntimeSecurityPolicy;
87
+ /**
88
+ * Reset the module-private policy store to its uninitialised state.
89
+ * Test-only: production code must not call this. The window-global
90
+ * broadcast is intentionally NOT cleared (the descriptor is
91
+ * non-configurable and cannot be redefined within a single realm).
92
+ *
93
+ * @internal
94
+ */
95
+ export declare function _resetRuntimePolicyForTests(): void;
96
+ /** Convenience accessor for the endpoint sub-policy. */
97
+ export declare function readRuntimeEndpointPolicy(): NormalizedRuntimeEndpointPolicy;
98
+ /** Convenience accessor for the HTML sub-policy. */
99
+ export declare function readRuntimeHtmlPolicy(): NormalizedRuntimeSecurityPolicy['htmlPolicy'];
100
+ //# sourceMappingURL=policy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policy.d.ts","sourceRoot":"","sources":["../../src/runtime/policy.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AAGxF;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAChC,4DAA4D;IAC5D,QAAQ,CAAC,UAAU,CAAC,EAAE,UAAU,CAAC;IACjC,6DAA6D;IAC7D,QAAQ,CAAC,aAAa,CAAC,EAAE,UAAU,CAAC;IACpC,4CAA4C;IAC5C,QAAQ,CAAC,gBAAgB,CAAC,EAAE,OAAO,CAAC;CACrC;AAED;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IACpC,wCAAwC;IACxC,QAAQ,CAAC,cAAc,CAAC,EAAE,qBAAqB,CAAC;IAChD,iCAAiC;IACjC,QAAQ,CAAC,UAAU,CAAC,EAAE,iBAAiB,CAAC;CACzC;AAED;;;;GAIG;AACH,MAAM,WAAW,+BAA+B;IAC9C,QAAQ,CAAC,IAAI,EAAE,qBAAqB,CAAC,MAAM,CAAC,CAAC;IAC7C,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IACzC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,mBAAmB,EAAE,SAAS,MAAM,EAAE,CAAC,CAAC,CAAC;CAC3E;AAED;;;;GAIG;AACH,MAAM,WAAW,+BAA+B;IAC9C,QAAQ,CAAC,cAAc,EAAE,+BAA+B,CAAC;IACzD,QAAQ,CAAC,UAAU,EAAE;QACnB,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;QAChC,QAAQ,CAAC,aAAa,EAAE,UAAU,CAAC;QACnC,QAAQ,CAAC,gBAAgB,EAAE,OAAO,CAAC;KACpC,CAAC;CACH;AAiED;;;;GAIG;AACH,wBAAgB,8BAA8B,CAAC,MAAM,CAAC,EAAE,qBAAqB,GAAG,+BAA+B,CAS9G;AA4BD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,CAAC,EAAE,qBAAqB,GAAG,+BAA+B,CAUtG;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,IAAI,+BAA+B,CAKnE;AAED;;;;;;;GAOG;AACH,wBAAgB,2BAA2B,IAAI,IAAI,CAElD;AAED,wDAAwD;AACxD,wBAAgB,yBAAyB,IAAI,+BAA+B,CAE3E;AAED,oDAAoD;AACpD,wBAAgB,qBAAqB,IAAI,+BAA+B,CAAC,YAAY,CAAC,CAErF"}
@@ -0,0 +1,147 @@
1
+ import { readRuntimeGlobal, writeRuntimeGlobal } from './globals.js';
2
+ function isNormalizedRuntimeSecurityPolicy(value) {
3
+ return (typeof value === 'object' &&
4
+ value !== null &&
5
+ 'endpointPolicy' in value &&
6
+ 'htmlPolicy' in value &&
7
+ typeof value.endpointPolicy === 'object' &&
8
+ value.endpointPolicy !== null &&
9
+ typeof value.htmlPolicy === 'object' &&
10
+ value.htmlPolicy !== null);
11
+ }
12
+ const DEFAULT_ENDPOINT_POLICY = Object.freeze({
13
+ mode: 'same-origin',
14
+ allowOrigins: Object.freeze([]),
15
+ byKind: Object.freeze({
16
+ stream: Object.freeze([]),
17
+ snapshot: Object.freeze([]),
18
+ replay: Object.freeze([]),
19
+ llm: Object.freeze([]),
20
+ 'gpu-shader': Object.freeze([]),
21
+ wasm: Object.freeze([]),
22
+ }),
23
+ });
24
+ const DEFAULT_HTML_POLICY = Object.freeze({
25
+ llmDefault: 'text',
26
+ streamDefault: 'sanitized-html',
27
+ allowTrustedHtml: false,
28
+ });
29
+ function freezeOrigins(origins) {
30
+ return Object.freeze((origins ?? []).map((origin) => origin.trim()).filter((origin) => origin.length > 0));
31
+ }
32
+ function freezeEndpointPolicy(policy) {
33
+ if (!policy) {
34
+ return DEFAULT_ENDPOINT_POLICY;
35
+ }
36
+ // Fully populate every kind up-front so the record is typed correctly
37
+ // from the initializer, without an empty-literal cast.
38
+ const byKind = {
39
+ stream: freezeOrigins(policy.byKind?.stream),
40
+ snapshot: freezeOrigins(policy.byKind?.snapshot),
41
+ replay: freezeOrigins(policy.byKind?.replay),
42
+ llm: freezeOrigins(policy.byKind?.llm),
43
+ 'gpu-shader': freezeOrigins(policy.byKind?.['gpu-shader']),
44
+ wasm: freezeOrigins(policy.byKind?.wasm),
45
+ };
46
+ return Object.freeze({
47
+ mode: policy.mode,
48
+ allowOrigins: freezeOrigins(policy.allowOrigins),
49
+ byKind: Object.freeze(byKind),
50
+ });
51
+ }
52
+ /**
53
+ * Freeze a user-supplied security policy into the fully-populated
54
+ * {@link NormalizedRuntimeSecurityPolicy} form. Applies conservative
55
+ * defaults for any missing fields.
56
+ */
57
+ export function normalizeRuntimeSecurityPolicy(policy) {
58
+ return Object.freeze({
59
+ endpointPolicy: freezeEndpointPolicy(policy?.endpointPolicy),
60
+ htmlPolicy: Object.freeze({
61
+ llmDefault: policy?.htmlPolicy?.llmDefault ?? DEFAULT_HTML_POLICY.llmDefault,
62
+ streamDefault: policy?.htmlPolicy?.streamDefault ?? DEFAULT_HTML_POLICY.streamDefault,
63
+ allowTrustedHtml: policy?.htmlPolicy?.allowTrustedHtml ?? DEFAULT_HTML_POLICY.allowTrustedHtml,
64
+ }),
65
+ });
66
+ }
67
+ /**
68
+ * Module-private source of truth for the active runtime policy. Lives
69
+ * in a closure no external script can `Object.defineProperty` past;
70
+ * the window global is a discoverable broadcast and a cross-bundle
71
+ * bridge, not the canonical store. Production callers always go
72
+ * through `configureRuntimePolicy` / `readRuntimePolicy`, both of
73
+ * which read the closure first.
74
+ *
75
+ * @internal
76
+ */
77
+ let _currentPolicy = null;
78
+ /**
79
+ * Tracks whether the cross-bundle window broadcast has been published.
80
+ * The broadcast happens once per realm with `configurable: false` so
81
+ * an attacker with script execution cannot redefine the property on
82
+ * later loaders. Subsequent `configureRuntimePolicy` calls (HMR,
83
+ * tests) update the module-private store but skip a re-broadcast,
84
+ * which would throw against the locked descriptor. The broadcast is
85
+ * informational; consumers in the same module-graph see updates
86
+ * through the closure regardless.
87
+ *
88
+ * @internal
89
+ */
90
+ let _windowGlobalPublished = false;
91
+ /**
92
+ * Normalise `policy` and install it as the active runtime configuration.
93
+ *
94
+ * The first call in a given realm publishes the value to
95
+ * `window.__CZAP_RUNTIME_POLICY__` with `configurable: false` and
96
+ * `writable: false`, so an attacker cannot redefine the global via
97
+ * `Object.defineProperty` to install a permissive policy. Subsequent
98
+ * calls (HMR, test re-initialisation) update the module-private store
99
+ * only — the window global stays locked at the first published value.
100
+ *
101
+ * Production callers run `configureRuntimePolicy` once during the
102
+ * integration boot script. Test harnesses re-call it freely; reads
103
+ * via `readRuntimePolicy()` return the latest configured value
104
+ * because the module-private store is checked first.
105
+ */
106
+ export function configureRuntimePolicy(policy) {
107
+ const normalized = normalizeRuntimeSecurityPolicy(policy);
108
+ _currentPolicy = normalized;
109
+ if (!_windowGlobalPublished) {
110
+ writeRuntimeGlobal('__CZAP_RUNTIME_POLICY__', normalized, { configurable: false });
111
+ _windowGlobalPublished = true;
112
+ }
113
+ return normalized;
114
+ }
115
+ /**
116
+ * Read the active runtime policy. Prefers the module-private store
117
+ * (the canonical source of truth), falls back to the cross-bundle
118
+ * window broadcast for consumers loaded as a separate bundle, and
119
+ * finally to a default normalised policy when nothing has been
120
+ * configured (e.g. in tests that haven't called
121
+ * `configureRuntimePolicy` yet).
122
+ */
123
+ export function readRuntimePolicy() {
124
+ if (_currentPolicy)
125
+ return _currentPolicy;
126
+ return (readRuntimeGlobal('__CZAP_RUNTIME_POLICY__', isNormalizedRuntimeSecurityPolicy) ?? normalizeRuntimeSecurityPolicy());
127
+ }
128
+ /**
129
+ * Reset the module-private policy store to its uninitialised state.
130
+ * Test-only: production code must not call this. The window-global
131
+ * broadcast is intentionally NOT cleared (the descriptor is
132
+ * non-configurable and cannot be redefined within a single realm).
133
+ *
134
+ * @internal
135
+ */
136
+ export function _resetRuntimePolicyForTests() {
137
+ _currentPolicy = null;
138
+ }
139
+ /** Convenience accessor for the endpoint sub-policy. */
140
+ export function readRuntimeEndpointPolicy() {
141
+ return readRuntimePolicy().endpointPolicy;
142
+ }
143
+ /** Convenience accessor for the HTML sub-policy. */
144
+ export function readRuntimeHtmlPolicy() {
145
+ return readRuntimePolicy().htmlPolicy;
146
+ }
147
+ //# sourceMappingURL=policy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policy.js","sourceRoot":"","sources":["../../src/runtime/policy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import type { Receipt, UIFrame } from '@czap/core';
2
+ type ReceiptEnvelope = Receipt.Envelope;
3
+ type ReceiptTrustMode = 'advisory-unverified';
4
+ interface ReceiptChainShape {
5
+ rememberFrame(frame: UIFrame): void;
6
+ ingestEnvelope(envelope: ReceiptEnvelope): boolean;
7
+ hasFramesAfter(receiptId: string | null): boolean;
8
+ getFramesAfter(receiptId: string | null): readonly UIFrame[];
9
+ latestReceiptId(): string | null;
10
+ trustMode(): ReceiptTrustMode;
11
+ }
12
+ /**
13
+ * Build a new in-memory receipt chain. Owns a DAG of ingested receipt
14
+ * envelopes plus a map of remembered frames keyed by receipt id, so
15
+ * the LLM directive can replay gaps when the SSE stream reconnects.
16
+ *
17
+ * The chain currently treats signatures as advisory; a diagnostic is
18
+ * emitted when signed envelopes arrive without a configured verifier.
19
+ */
20
+ export declare function createReceiptChain(): ReceiptChainShape;
21
+ export {};
22
+ //# sourceMappingURL=receipt-chain.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"receipt-chain.d.ts","sourceRoot":"","sources":["../../src/runtime/receipt-chain.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAEnD,KAAK,eAAe,GAAG,OAAO,CAAC,QAAQ,CAAC;AACxC,KAAK,gBAAgB,GAAG,qBAAqB,CAAC;AAE9C,UAAU,iBAAiB;IACzB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;IACpC,cAAc,CAAC,QAAQ,EAAE,eAAe,GAAG,OAAO,CAAC;IACnD,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC;IAClD,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,OAAO,EAAE,CAAC;IAC7D,eAAe,IAAI,MAAM,GAAG,IAAI,CAAC;IACjC,SAAS,IAAI,gBAAgB,CAAC;CAC/B;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,IAAI,iBAAiB,CAkFtD"}
@@ -0,0 +1,80 @@
1
+ import { DAG, Diagnostics } from '@czap/core';
2
+ /**
3
+ * Build a new in-memory receipt chain. Owns a DAG of ingested receipt
4
+ * envelopes plus a map of remembered frames keyed by receipt id, so
5
+ * the LLM directive can replay gaps when the SSE stream reconnects.
6
+ *
7
+ * The chain currently treats signatures as advisory; a diagnostic is
8
+ * emitted when signed envelopes arrive without a configured verifier.
9
+ */
10
+ export function createReceiptChain() {
11
+ let dag = DAG.empty();
12
+ const framesByReceipt = new Map();
13
+ const orderedReceipts = [];
14
+ const orderedFrameIds = () => {
15
+ if (DAG.size(dag) > 0) {
16
+ const ids = DAG.linearize(dag)
17
+ .map((envelope) => envelope.hash)
18
+ .filter((hash) => framesByReceipt.has(hash));
19
+ if (ids.length > 0) {
20
+ return ids;
21
+ }
22
+ }
23
+ return orderedReceipts;
24
+ };
25
+ return {
26
+ rememberFrame(frame) {
27
+ framesByReceipt.set(frame.receiptId, frame);
28
+ if (!orderedReceipts.includes(frame.receiptId)) {
29
+ orderedReceipts.push(frame.receiptId);
30
+ }
31
+ },
32
+ ingestEnvelope(envelope) {
33
+ if (envelope.signature) {
34
+ Diagnostics.warnOnce({
35
+ source: 'czap/astro.receipt-chain',
36
+ code: 'receipt-signature-unverified',
37
+ message: 'Receipt signatures are present but runtime ingestion treats them as advisory metadata until verification is configured.',
38
+ });
39
+ }
40
+ dag = DAG.ingest(dag, envelope);
41
+ return true;
42
+ },
43
+ hasFramesAfter(receiptId) {
44
+ const ids = orderedFrameIds();
45
+ if (ids.length === 0) {
46
+ return false;
47
+ }
48
+ if (receiptId === null) {
49
+ return ids.length > 0;
50
+ }
51
+ const index = ids.indexOf(receiptId);
52
+ if (index === -1) {
53
+ return false;
54
+ }
55
+ return index < ids.length - 1;
56
+ },
57
+ getFramesAfter(receiptId) {
58
+ const ids = orderedFrameIds();
59
+ if (receiptId === null) {
60
+ return ids.map((id) => framesByReceipt.get(id)).filter(Boolean);
61
+ }
62
+ const index = ids.indexOf(receiptId);
63
+ if (index === -1) {
64
+ return [];
65
+ }
66
+ return ids
67
+ .slice(index + 1)
68
+ .map((id) => framesByReceipt.get(id))
69
+ .filter(Boolean);
70
+ },
71
+ latestReceiptId() {
72
+ const ids = orderedFrameIds();
73
+ return ids.length > 0 ? ids[ids.length - 1] : null;
74
+ },
75
+ trustMode() {
76
+ return 'advisory-unverified';
77
+ },
78
+ };
79
+ }
80
+ //# sourceMappingURL=receipt-chain.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"receipt-chain.js","sourceRoot":"","sources":["../../src/runtime/receipt-chain.ts"],"names":[],"mappings":"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"}