@opendatalabs/personal-server-ts-core 1.8.0 → 1.10.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 (93) hide show
  1. package/dist/api/index.d.ts +19 -0
  2. package/dist/api/index.d.ts.map +1 -1
  3. package/dist/api/index.js +23 -0
  4. package/dist/api/index.js.map +1 -1
  5. package/dist/derivatives/api.d.ts +33 -0
  6. package/dist/derivatives/api.d.ts.map +1 -0
  7. package/dist/derivatives/api.js +216 -0
  8. package/dist/derivatives/api.js.map +1 -0
  9. package/dist/derivatives/compute.d.ts +106 -0
  10. package/dist/derivatives/compute.d.ts.map +1 -0
  11. package/dist/derivatives/compute.js +380 -0
  12. package/dist/derivatives/compute.js.map +1 -0
  13. package/dist/derivatives/e2ee/aad.d.ts +22 -0
  14. package/dist/derivatives/e2ee/aad.d.ts.map +1 -0
  15. package/dist/derivatives/e2ee/aad.js +32 -0
  16. package/dist/derivatives/e2ee/aad.js.map +1 -0
  17. package/dist/derivatives/e2ee/attestation.d.ts +122 -0
  18. package/dist/derivatives/e2ee/attestation.d.ts.map +1 -0
  19. package/dist/derivatives/e2ee/attestation.js +217 -0
  20. package/dist/derivatives/e2ee/attestation.js.map +1 -0
  21. package/dist/derivatives/e2ee/index.d.ts +6 -0
  22. package/dist/derivatives/e2ee/index.d.ts.map +1 -0
  23. package/dist/derivatives/e2ee/index.js +6 -0
  24. package/dist/derivatives/e2ee/index.js.map +1 -0
  25. package/dist/derivatives/e2ee/jcs.d.ts +17 -0
  26. package/dist/derivatives/e2ee/jcs.d.ts.map +1 -0
  27. package/dist/derivatives/e2ee/jcs.js +55 -0
  28. package/dist/derivatives/e2ee/jcs.js.map +1 -0
  29. package/dist/derivatives/e2ee/phala.d.ts +55 -0
  30. package/dist/derivatives/e2ee/phala.d.ts.map +1 -0
  31. package/dist/derivatives/e2ee/phala.js +167 -0
  32. package/dist/derivatives/e2ee/phala.js.map +1 -0
  33. package/dist/derivatives/e2ee/suite.d.ts +56 -0
  34. package/dist/derivatives/e2ee/suite.d.ts.map +1 -0
  35. package/dist/derivatives/e2ee/suite.js +164 -0
  36. package/dist/derivatives/e2ee/suite.js.map +1 -0
  37. package/dist/derivatives/index.d.ts +10 -0
  38. package/dist/derivatives/index.d.ts.map +1 -0
  39. package/dist/derivatives/index.js +10 -0
  40. package/dist/derivatives/index.js.map +1 -0
  41. package/dist/derivatives/inference.d.ts +134 -0
  42. package/dist/derivatives/inference.d.ts.map +1 -0
  43. package/dist/derivatives/inference.js +223 -0
  44. package/dist/derivatives/inference.js.map +1 -0
  45. package/dist/derivatives/prompt.d.ts +64 -0
  46. package/dist/derivatives/prompt.d.ts.map +1 -0
  47. package/dist/derivatives/prompt.js +186 -0
  48. package/dist/derivatives/prompt.js.map +1 -0
  49. package/dist/derivatives/registration.d.ts +53 -0
  50. package/dist/derivatives/registration.d.ts.map +1 -0
  51. package/dist/derivatives/registration.js +163 -0
  52. package/dist/derivatives/registration.js.map +1 -0
  53. package/dist/derivatives/scheduler.d.ts +56 -0
  54. package/dist/derivatives/scheduler.d.ts.map +1 -0
  55. package/dist/derivatives/scheduler.js +151 -0
  56. package/dist/derivatives/scheduler.js.map +1 -0
  57. package/dist/derivatives/store.d.ts +14 -0
  58. package/dist/derivatives/store.d.ts.map +1 -0
  59. package/dist/derivatives/store.js +75 -0
  60. package/dist/derivatives/store.js.map +1 -0
  61. package/dist/derivatives/types.d.ts +72 -0
  62. package/dist/derivatives/types.d.ts.map +1 -0
  63. package/dist/derivatives/types.js +25 -0
  64. package/dist/derivatives/types.js.map +1 -0
  65. package/dist/errors/catalog.d.ts +20 -0
  66. package/dist/errors/catalog.d.ts.map +1 -1
  67. package/dist/errors/catalog.js +26 -0
  68. package/dist/errors/catalog.js.map +1 -1
  69. package/dist/schemas/server-config.d.ts +14 -0
  70. package/dist/schemas/server-config.d.ts.map +1 -1
  71. package/dist/schemas/server-config.js +34 -0
  72. package/dist/schemas/server-config.js.map +1 -1
  73. package/dist/sync/workers/download.d.ts +14 -0
  74. package/dist/sync/workers/download.d.ts.map +1 -1
  75. package/dist/sync/workers/download.js +23 -0
  76. package/dist/sync/workers/download.js.map +1 -1
  77. package/dist/test-utils/e2ee-fixtures.d.ts +94 -0
  78. package/dist/test-utils/e2ee-fixtures.d.ts.map +1 -0
  79. package/dist/test-utils/e2ee-fixtures.js +116 -0
  80. package/dist/test-utils/e2ee-fixtures.js.map +1 -0
  81. package/dist/test-utils/e2ee-gateway.d.ts +61 -0
  82. package/dist/test-utils/e2ee-gateway.d.ts.map +1 -0
  83. package/dist/test-utils/e2ee-gateway.js +248 -0
  84. package/dist/test-utils/e2ee-gateway.js.map +1 -0
  85. package/dist/test-utils/index.d.ts +3 -0
  86. package/dist/test-utils/index.d.ts.map +1 -1
  87. package/dist/test-utils/index.js +3 -0
  88. package/dist/test-utils/index.js.map +1 -1
  89. package/dist/test-utils/memory-storage.d.ts +12 -0
  90. package/dist/test-utils/memory-storage.d.ts.map +1 -0
  91. package/dist/test-utils/memory-storage.js +146 -0
  92. package/dist/test-utils/memory-storage.js.map +1 -0
  93. package/package.json +5 -1
@@ -0,0 +1,106 @@
1
+ /**
2
+ * The compute job: answer one registered question from local data and
3
+ * write the answer as a derivative record (owner path, `$lineage` = the
4
+ * source data points).
5
+ */
6
+ import type { ScopeDeletionTracker } from "../sync/scope-deletions.js";
7
+ import type { DataStoragePort, RuntimeAvailabilityPort } from "../ports/index.js";
8
+ import { type DataWritePolicyPorts } from "../policy/data-write.js";
9
+ import { type InferenceProvider } from "./inference.js";
10
+ import type { QuestionRegistration, QuestionStore } from "./types.js";
11
+ export interface ComputeLogger {
12
+ info?(payload: Record<string, unknown>, message: string): void;
13
+ warn?(payload: Record<string, unknown>, message: string): void;
14
+ }
15
+ export interface ComputeSyncNotifier {
16
+ notifyNewData?(): void;
17
+ trigger?(): Promise<void>;
18
+ }
19
+ export interface QuestionComputeDeps {
20
+ storage: DataStoragePort;
21
+ store: QuestionStore;
22
+ provider: InferenceProvider;
23
+ /** Required: lineage ids are keccak256(owner, scope). */
24
+ serverOwner: `0x${string}` | undefined;
25
+ /** Newest-first items kept per source scope (default 50). */
26
+ maxSourceItems?: number;
27
+ maxSourceChars?: number;
28
+ maxTokens?: number;
29
+ /** Uploads the derivative after it is written locally. */
30
+ syncManager?: ComputeSyncNotifier | null;
31
+ /** Re-add marker, same as an HTTP ingest (see api/index.ts). */
32
+ scopeDeletions?: ScopeDeletionTracker;
33
+ /**
34
+ * When present, a builder-registered question re-checks its write grant
35
+ * before every compute (revoked / expired / scope no longer covered =>
36
+ * failed, no inference call). Owner registrations skip the check.
37
+ */
38
+ writePolicyPorts?: DataWritePolicyPorts;
39
+ /**
40
+ * Called after the derivative is written and the question marked ready,
41
+ * so a question that reads THIS derived scope recomputes in turn
42
+ * (A -> B -> C chains). The compute path never goes through the HTTP
43
+ * ingest hook.
44
+ */
45
+ onDerivedWritten?: (event: {
46
+ scope: string;
47
+ collectedAt: string;
48
+ lineageSources: string[];
49
+ }) => void;
50
+ /** When unavailable the compute is skipped and the status left as is. */
51
+ runtimeAvailability?: RuntimeAvailabilityPort;
52
+ /**
53
+ * Backoff between retries of a transient inference or gateway failure
54
+ * (default 1s, 4s: three attempts). Tests pass zeros.
55
+ */
56
+ retryDelaysMs?: readonly number[];
57
+ sleep?: (ms: number) => Promise<void>;
58
+ now?: () => Date;
59
+ logger?: ComputeLogger;
60
+ }
61
+ export type ComputeOutcome = {
62
+ status: "ready";
63
+ registration: QuestionRegistration;
64
+ } | {
65
+ status: "failed";
66
+ registration: QuestionRegistration;
67
+ error: string;
68
+ } | {
69
+ status: "skipped";
70
+ reason: "unknown-question" | "runtime-unavailable";
71
+ };
72
+ /** The record written into the derived scope. */
73
+ export interface DerivativeAnswerRecord {
74
+ questionId: string;
75
+ question: string;
76
+ answer: string;
77
+ evidence: string | null;
78
+ model: string;
79
+ computedAt: string;
80
+ sources: Array<{
81
+ scope: string;
82
+ version: number;
83
+ collectedAt: string;
84
+ }>;
85
+ /** Caller-side lineage field, mirrored by the server into `$lineage`. */
86
+ lineage: `0x${string}`[];
87
+ inference?: {
88
+ receiptId?: string;
89
+ aciIdentity?: string;
90
+ };
91
+ [key: string]: unknown;
92
+ }
93
+ /**
94
+ * Version stamp for the derived record, second precision like an HTTP
95
+ * ingest. A recompute inside the same second as the previous one would
96
+ * collide on the (scope, collectedAt) path, so the stamp advances past any
97
+ * version the scope already holds (bounded: at most one minute ahead).
98
+ */
99
+ export declare function collectedAtStamp(now: () => Date, isTaken: (collectedAt: string) => boolean): string;
100
+ /**
101
+ * Compute one question end to end. Never throws for a compute failure: the
102
+ * registration is marked `failed` with a short reason and the outcome says
103
+ * so. Throws only when the store itself fails.
104
+ */
105
+ export declare function computeQuestion(questionId: string, deps: QuestionComputeDeps): Promise<ComputeOutcome>;
106
+ //# sourceMappingURL=compute.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compute.d.ts","sourceRoot":"","sources":["../../src/derivatives/compute.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,380 @@
1
+ /**
2
+ * The compute job: answer one registered question from local data and
3
+ * write the answer as a derivative record (owner path, `$lineage` = the
4
+ * source data points).
5
+ */
6
+ import { DerivativeCycleError, DerivativeSourceNotGrantedError, ProtocolError, } from "../errors/catalog.js";
7
+ import { resolveReadDeletion } from "../api/index.js";
8
+ import { LOCAL_SCOPE_SCAN_PAGE, readStoredLineage, } from "../lineage/lineage.js";
9
+ import { uncoveredSourceScopes } from "./registration.js";
10
+ import { ingestDataContract } from "../contracts/data.js";
11
+ import { isBinaryEnvelope } from "../contracts/binary.js";
12
+ import { assertDerivedScopeNaming } from "../lineage/lineage.js";
13
+ import { computeDataPointId } from "../sync/data-point-id.js";
14
+ import { verifyDataWritePolicy, } from "../policy/data-write.js";
15
+ import { InferenceRequestError } from "./inference.js";
16
+ import { buildQuestionMessages, parseAnswer, trimSourceData, } from "./prompt.js";
17
+ const DEFAULT_RETRY_DELAYS_MS = [1_000, 4_000];
18
+ /**
19
+ * Transient: no response, rate limited or a provider-side failure. An
20
+ * explicit `retryable` hint (E2EE key verification or decryption failures
21
+ * are permanent) wins over the status rule.
22
+ */
23
+ function isRetryableInferenceError(err) {
24
+ if (!(err instanceof InferenceRequestError))
25
+ return false;
26
+ if (err.retryable !== undefined)
27
+ return err.retryable;
28
+ return err.status === null || err.status === 429 || err.status >= 500;
29
+ }
30
+ /**
31
+ * Run `attempt` up to `delays.length + 1` times while `retryable(err)`;
32
+ * anything else (a ProtocolError, a permanent status) surfaces at once.
33
+ */
34
+ async function withRetries(deps, attempt, retryable) {
35
+ const delays = deps.retryDelaysMs ?? DEFAULT_RETRY_DELAYS_MS;
36
+ const sleep = deps.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
37
+ for (let index = 0;; index += 1) {
38
+ try {
39
+ return await attempt();
40
+ }
41
+ catch (err) {
42
+ if (index >= delays.length || !retryable(err))
43
+ throw err;
44
+ await sleep(delays[index]);
45
+ }
46
+ }
47
+ }
48
+ /** A failure message safe to persist: never the prompt, never the data. */
49
+ class ComputeFailure extends Error {
50
+ constructor(message) {
51
+ super(message);
52
+ this.name = "ComputeFailure";
53
+ }
54
+ }
55
+ function shortError(err) {
56
+ if (err instanceof ComputeFailure)
57
+ return err.message;
58
+ if (err instanceof InferenceRequestError)
59
+ return err.message;
60
+ if (err instanceof ProtocolError)
61
+ return `${err.errorCode}: ${err.message}`;
62
+ // Unknown errors may quote data (a JSON parse error echoes its input);
63
+ // keep the class name only.
64
+ return `compute failed (${err instanceof Error ? err.name : "Error"})`;
65
+ }
66
+ /**
67
+ * Version stamp for the derived record, second precision like an HTTP
68
+ * ingest. A recompute inside the same second as the previous one would
69
+ * collide on the (scope, collectedAt) path, so the stamp advances past any
70
+ * version the scope already holds (bounded: at most one minute ahead).
71
+ */
72
+ export function collectedAtStamp(now, isTaken) {
73
+ const base = now();
74
+ base.setUTCMilliseconds(0);
75
+ for (let bump = 0; bump < 60; bump += 1) {
76
+ const candidate = new Date(base.getTime() + bump * 1000)
77
+ .toISOString()
78
+ .replace(/\.\d{3}Z$/, "Z");
79
+ if (!isTaken(candidate))
80
+ return candidate;
81
+ }
82
+ throw new ComputeFailure("could not allocate a version stamp");
83
+ }
84
+ async function tombstoneMarker(scopeDeletions, scope) {
85
+ if (!scopeDeletions)
86
+ return null;
87
+ const verdict = await scopeDeletions.resolve(scope);
88
+ if (!verdict.deleted || verdict.version === null)
89
+ return null;
90
+ const version = Number(verdict.version);
91
+ return Number.isSafeInteger(version) ? version : null;
92
+ }
93
+ /**
94
+ * `dataPointId -> scope` for every scope in the local index, used to walk
95
+ * stored lineage locally. Paged like the lineage resolver.
96
+ */
97
+ function localScopesById(storage, serverOwner) {
98
+ const byId = new Map();
99
+ for (let offset = 0;; offset += LOCAL_SCOPE_SCAN_PAGE) {
100
+ const { scopes, total } = storage.listScopes({
101
+ limit: LOCAL_SCOPE_SCAN_PAGE,
102
+ offset,
103
+ });
104
+ for (const summary of scopes) {
105
+ byId.set(computeDataPointId(serverOwner, summary.scope), summary.scope);
106
+ }
107
+ if (scopes.length === 0 || offset + scopes.length >= total)
108
+ break;
109
+ }
110
+ return byId;
111
+ }
112
+ /**
113
+ * Cycle guard on ACTUAL lineage, for cycles the per-store registration
114
+ * check cannot see (two replicas each holding one half: B <- A here, A <- B
115
+ * there, ping-ponging through sync). Walks `$lineage` from every source's
116
+ * latest local version through the local index; reaching the derived data
117
+ * point id means this question would consume its own output. Bounded by
118
+ * the visited set.
119
+ */
120
+ async function assertNoLineageCycle(deps, registration, serverOwner, sourceLineage) {
121
+ const derivedId = computeDataPointId(serverOwner, registration.derivedScope);
122
+ let byId = null;
123
+ const visited = new Set();
124
+ const stack = [];
125
+ for (const [scope, sources] of sourceLineage) {
126
+ for (const id of sources)
127
+ stack.push({ id, path: [scope] });
128
+ }
129
+ while (stack.length > 0) {
130
+ const { id, path } = stack.pop();
131
+ if (id === derivedId) {
132
+ throw new DerivativeCycleError({
133
+ derivedScope: registration.derivedScope,
134
+ path: [registration.derivedScope, ...path, registration.derivedScope],
135
+ });
136
+ }
137
+ if (visited.has(id))
138
+ continue;
139
+ visited.add(id);
140
+ byId ??= localScopesById(deps.storage, serverOwner);
141
+ const scope = byId.get(id);
142
+ if (!scope)
143
+ continue;
144
+ const entry = deps.storage.findEntry({ scope });
145
+ if (!entry)
146
+ continue;
147
+ let sources = [];
148
+ try {
149
+ const envelope = await deps.storage.readEnvelope(scope, entry.collectedAt);
150
+ sources = readStoredLineage(envelope.data)?.sources ?? [];
151
+ }
152
+ catch {
153
+ // Unreadable or malformed lineage: nothing further to walk here.
154
+ }
155
+ for (const next of sources)
156
+ stack.push({ id: next, path: [...path, scope] });
157
+ }
158
+ }
159
+ async function loadSource(deps, scope) {
160
+ const entry = deps.storage.findEntry({ scope });
161
+ // The same deletion gate a read applies: a tombstoned scope is refused
162
+ // (410 on the read path) whether or not a stale local copy remains.
163
+ const deletion = await resolveReadDeletion({ scopeDeletions: deps.scopeDeletions, serverOwner: deps.serverOwner }, scope, entry);
164
+ if (deletion) {
165
+ throw new ComputeFailure(`source scope ${scope} is deleted`);
166
+ }
167
+ if (!entry) {
168
+ throw new ComputeFailure(`source scope ${scope} has no local data`);
169
+ }
170
+ let envelope;
171
+ try {
172
+ envelope = await deps.storage.readEnvelope(scope, entry.collectedAt);
173
+ }
174
+ catch {
175
+ throw new ComputeFailure(`source scope ${scope} could not be read`);
176
+ }
177
+ let lineageSources = [];
178
+ try {
179
+ lineageSources = readStoredLineage(envelope.data)?.sources ?? [];
180
+ }
181
+ catch {
182
+ // Malformed stored lineage: treated as a root for the cycle walk.
183
+ }
184
+ const raw = isBinaryEnvelope(envelope)
185
+ ? {
186
+ binary: true,
187
+ note: "binary record; its content is not included in the prompt",
188
+ }
189
+ : envelope.data;
190
+ const trimmed = trimSourceData(raw, {
191
+ maxItems: deps.maxSourceItems,
192
+ maxChars: deps.maxSourceChars,
193
+ });
194
+ return {
195
+ source: {
196
+ scope,
197
+ collectedAt: entry.collectedAt,
198
+ version: entry.version,
199
+ data: trimmed.data,
200
+ kept: trimmed.kept,
201
+ total: trimmed.total,
202
+ truncated: trimmed.truncated,
203
+ },
204
+ lineageSources,
205
+ };
206
+ }
207
+ /**
208
+ * A builder question re-checks its grant before every compute: the write
209
+ * permission on the derived scope (revocation, expiry, coverage) AND read
210
+ * coverage of every source scope, since the answer exposes the sources to
211
+ * the builder. Gateway transport failures are retried; policy failures
212
+ * (ProtocolErrors) fail closed at once.
213
+ */
214
+ async function assertGrantStillValid(deps, registration) {
215
+ if (registration.registeredBy.kind !== "builder")
216
+ return;
217
+ if (!deps.writePolicyPorts) {
218
+ throw new ComputeFailure("builder grant verification is not configured");
219
+ }
220
+ if (!deps.serverOwner) {
221
+ throw new ComputeFailure("server owner is not configured");
222
+ }
223
+ const { builder, grantId } = registration.registeredBy;
224
+ const ports = deps.writePolicyPorts;
225
+ const serverOwner = deps.serverOwner;
226
+ const grant = await withRetries(deps, () => verifyDataWritePolicy({
227
+ signer: builder,
228
+ grantId,
229
+ requestedScope: registration.derivedScope,
230
+ serverOwner,
231
+ }, ports), (err) => !(err instanceof ProtocolError));
232
+ const uncovered = uncoveredSourceScopes(registration.sourceScopes, grant.scopes ?? []);
233
+ if (uncovered.length > 0) {
234
+ throw new DerivativeSourceNotGrantedError({ scopes: uncovered });
235
+ }
236
+ }
237
+ /**
238
+ * Compute one question end to end. Never throws for a compute failure: the
239
+ * registration is marked `failed` with a short reason and the outcome says
240
+ * so. Throws only when the store itself fails.
241
+ */
242
+ export async function computeQuestion(questionId, deps) {
243
+ const now = deps.now ?? (() => new Date());
244
+ if ((await deps.runtimeAvailability?.isAvailable()) === false) {
245
+ return { status: "skipped", reason: "runtime-unavailable" };
246
+ }
247
+ const registration = await deps.store.get(questionId);
248
+ if (!registration)
249
+ return { status: "skipped", reason: "unknown-question" };
250
+ try {
251
+ if (!deps.serverOwner) {
252
+ throw new ComputeFailure("server owner is not configured");
253
+ }
254
+ const serverOwner = deps.serverOwner;
255
+ await assertGrantStillValid(deps, registration);
256
+ // Defense in depth: the rule was checked at registration; a registration
257
+ // row edited by hand must still not produce a leaking derivative.
258
+ assertDerivedScopeNaming(registration.derivedScope, registration.sourceScopes);
259
+ const sources = [];
260
+ const sourceLineage = new Map();
261
+ for (const scope of registration.sourceScopes) {
262
+ const loaded = await loadSource(deps, scope);
263
+ sources.push(loaded.source);
264
+ sourceLineage.set(scope, loaded.lineageSources);
265
+ }
266
+ await assertNoLineageCycle(deps, registration, serverOwner, sourceLineage);
267
+ const messages = buildQuestionMessages({
268
+ question: registration.question,
269
+ sources,
270
+ });
271
+ const model = registration.model ?? deps.provider.defaultModel;
272
+ const reply = await withRetries(deps, () => deps.provider.chat({ model, messages, maxTokens: deps.maxTokens }), isRetryableInferenceError);
273
+ const parsed = parseAnswer(reply.content);
274
+ const computedAt = now().toISOString();
275
+ const lineageIds = registration.sourceScopes.map((scope) => computeDataPointId(serverOwner, scope));
276
+ const record = {
277
+ questionId: registration.questionId,
278
+ question: registration.question,
279
+ answer: parsed.answer,
280
+ evidence: parsed.evidence,
281
+ model,
282
+ computedAt,
283
+ sources: sources.map((source) => ({
284
+ scope: source.scope,
285
+ version: source.version,
286
+ collectedAt: source.collectedAt,
287
+ })),
288
+ lineage: lineageIds,
289
+ ...(reply.receiptId || reply.aciIdentity
290
+ ? {
291
+ inference: {
292
+ ...(reply.receiptId ? { receiptId: reply.receiptId } : {}),
293
+ ...(reply.aciIdentity ? { aciIdentity: reply.aciIdentity } : {}),
294
+ },
295
+ }
296
+ : {}),
297
+ };
298
+ const lineage = {
299
+ sources: lineageIds,
300
+ writtenAt: computedAt,
301
+ };
302
+ // `findEntry({ at })` may answer the closest version, so compare exactly.
303
+ const collectedAt = collectedAtStamp(now, (candidate) => deps.storage.findEntry({
304
+ scope: registration.derivedScope,
305
+ at: candidate,
306
+ })?.collectedAt === candidate);
307
+ const written = await ingestDataContract({
308
+ storage: deps.storage,
309
+ scopeParam: registration.derivedScope,
310
+ body: record,
311
+ collectedAt,
312
+ status: deps.syncManager ? "syncing" : "stored",
313
+ lineage,
314
+ afterTombstoneVersion: await tombstoneMarker(deps.scopeDeletions, registration.derivedScope),
315
+ });
316
+ if (!written.ok) {
317
+ throw new ComputeFailure(`derived record rejected: ${written.body.error}`);
318
+ }
319
+ const entry = deps.storage.findEntry({
320
+ scope: registration.derivedScope,
321
+ at: collectedAt,
322
+ });
323
+ const updated = await deps.store.update(questionId, {
324
+ status: "ready",
325
+ error: null,
326
+ updatedAt: computedAt,
327
+ lastComputedAt: computedAt,
328
+ derivedVersion: entry?.version ?? null,
329
+ derivedCollectedAt: collectedAt,
330
+ });
331
+ if (deps.syncManager?.notifyNewData) {
332
+ deps.syncManager.notifyNewData();
333
+ }
334
+ else if (deps.syncManager?.trigger) {
335
+ void deps.syncManager.trigger().catch(() => undefined);
336
+ }
337
+ try {
338
+ deps.onDerivedWritten?.({
339
+ scope: registration.derivedScope,
340
+ collectedAt,
341
+ lineageSources: lineageIds,
342
+ });
343
+ }
344
+ catch (err) {
345
+ deps.logger?.warn?.({
346
+ questionId,
347
+ derivedScope: registration.derivedScope,
348
+ error: err instanceof Error ? err.name : String(err),
349
+ }, "onDerivedWritten hook failed; derivative already written");
350
+ }
351
+ deps.logger?.info?.({
352
+ questionId,
353
+ derivedScope: registration.derivedScope,
354
+ sourceScopes: registration.sourceScopes,
355
+ model,
356
+ version: entry?.version ?? null,
357
+ receiptId: reply.receiptId ?? null,
358
+ }, "Derivative question computed");
359
+ return {
360
+ status: "ready",
361
+ registration: updated ?? { ...registration, status: "ready" },
362
+ };
363
+ }
364
+ catch (err) {
365
+ const error = shortError(err);
366
+ const at = now().toISOString();
367
+ const updated = await deps.store.update(questionId, {
368
+ status: "failed",
369
+ error,
370
+ updatedAt: at,
371
+ });
372
+ deps.logger?.warn?.({ questionId, derivedScope: registration.derivedScope, error }, "Derivative question compute failed");
373
+ return {
374
+ status: "failed",
375
+ registration: updated ?? { ...registration, status: "failed", error },
376
+ error,
377
+ };
378
+ }
379
+ }
380
+ //# sourceMappingURL=compute.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compute.js","sourceRoot":"","sources":["../../src/derivatives/compute.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * E2EE v2 associated data (spec section 6): RFC 8785 JCS bytes binding every
3
+ * ciphertext to its field path and request context. Byte-exact examples are
4
+ * pinned by the spec test vectors in aad.test.ts.
5
+ */
6
+ export declare const E2EE_REQUEST_AAD_PURPOSE = "aci.e2ee.request.v2";
7
+ export declare const E2EE_RESPONSE_AAD_PURPOSE = "aci.e2ee.response.v2";
8
+ export interface E2eeRequestContext {
9
+ /** The selected service key's `algo`. */
10
+ algo: string;
11
+ /** The request's top-level `model`, byte-exact. */
12
+ model: string;
13
+ /** `X-E2EE-Nonce`, 64 hex characters. */
14
+ nonce: string;
15
+ /** `X-E2EE-Timestamp`, Unix seconds. */
16
+ ts: number;
17
+ }
18
+ export declare function requestFieldAad(context: E2eeRequestContext, field: string): Uint8Array;
19
+ export declare function responseFieldAad(context: E2eeRequestContext, field: string,
20
+ /** The clear response `id`, or "" when the response has none. */
21
+ id: string): Uint8Array;
22
+ //# sourceMappingURL=aad.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aad.d.ts","sourceRoot":"","sources":["../../../src/derivatives/e2ee/aad.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,eAAO,MAAM,wBAAwB,wBAAwB,CAAC;AAC9D,eAAO,MAAM,yBAAyB,yBAAyB,CAAC;AAEhE,MAAM,WAAW,kBAAkB;IACjC,yCAAyC;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,mDAAmD;IACnD,KAAK,EAAE,MAAM,CAAC;IACd,yCAAyC;IACzC,KAAK,EAAE,MAAM,CAAC;IACd,wCAAwC;IACxC,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,wBAAgB,eAAe,CAC7B,OAAO,EAAE,kBAAkB,EAC3B,KAAK,EAAE,MAAM,GACZ,UAAU,CASZ;AAED,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,kBAAkB,EAC3B,KAAK,EAAE,MAAM;AACb,iEAAiE;AACjE,EAAE,EAAE,MAAM,GACT,UAAU,CAUZ"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * E2EE v2 associated data (spec section 6): RFC 8785 JCS bytes binding every
3
+ * ciphertext to its field path and request context. Byte-exact examples are
4
+ * pinned by the spec test vectors in aad.test.ts.
5
+ */
6
+ import { canonicalJsonBytes } from "./jcs.js";
7
+ export const E2EE_REQUEST_AAD_PURPOSE = "aci.e2ee.request.v2";
8
+ export const E2EE_RESPONSE_AAD_PURPOSE = "aci.e2ee.response.v2";
9
+ export function requestFieldAad(context, field) {
10
+ return canonicalJsonBytes({
11
+ purpose: E2EE_REQUEST_AAD_PURPOSE,
12
+ algo: context.algo,
13
+ model: context.model,
14
+ field,
15
+ nonce: context.nonce,
16
+ ts: context.ts,
17
+ });
18
+ }
19
+ export function responseFieldAad(context, field,
20
+ /** The clear response `id`, or "" when the response has none. */
21
+ id) {
22
+ return canonicalJsonBytes({
23
+ purpose: E2EE_RESPONSE_AAD_PURPOSE,
24
+ algo: context.algo,
25
+ model: context.model,
26
+ id,
27
+ field,
28
+ nonce: context.nonce,
29
+ ts: context.ts,
30
+ });
31
+ }
32
+ //# sourceMappingURL=aad.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aad.js","sourceRoot":"","sources":["../../../src/derivatives/e2ee/aad.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAE9C,MAAM,CAAC,MAAM,wBAAwB,GAAG,qBAAqB,CAAC;AAC9D,MAAM,CAAC,MAAM,yBAAyB,GAAG,sBAAsB,CAAC;AAahE,MAAM,UAAU,eAAe,CAC7B,OAA2B,EAC3B,KAAa;IAEb,OAAO,kBAAkB,CAAC;QACxB,OAAO,EAAE,wBAAwB;QACjC,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,KAAK;QACL,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,EAAE,EAAE,OAAO,CAAC,EAAE;KACf,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,gBAAgB,CAC9B,OAA2B,EAC3B,KAAa;AACb,iEAAiE;AACjE,EAAU;IAEV,OAAO,kBAAkB,CAAC;QACxB,OAAO,EAAE,yBAAyB;QAClC,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,EAAE;QACF,KAAK;QACL,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,EAAE,EAAE,OAAO,CAAC,EAAE;KACf,CAAC,CAAC;AACL,CAAC"}