@happyvertical/smrt-ingestion 0.57.4 → 0.57.6

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.
package/dist/server.d.ts CHANGED
@@ -53,6 +53,17 @@ export interface AnalysisLease {
53
53
  fence: number;
54
54
  token: string;
55
55
  }
56
+ /** A server-owned dispatch route, retained independently of source metadata. */
57
+ export interface IntakeDispatchTarget {
58
+ version: 1;
59
+ objectType: string;
60
+ method: string;
61
+ }
62
+ export interface DispatchRouteInspection {
63
+ status: 'bound' | 'unknown' | 'conflict';
64
+ fingerprint: string;
65
+ target: IntakeDispatchTarget | null;
66
+ }
56
67
  /** Trusted integration points; no provider or application-policy implementation. */
57
68
  export interface IngestionOptions {
58
69
  /** Optional server-owned interpretation configuration; independent of execution. */
@@ -76,6 +87,18 @@ export interface IngestionOptions {
76
87
  objectType: string;
77
88
  method: string;
78
89
  };
90
+ /** Explicit operator authority for provenance-free legacy receipts; closed when omitted.
91
+ * Does not replace the normal current/captured process authorization.
92
+ */
93
+ dispatchRecovery?: {
94
+ authorize(input: {
95
+ scope: IngestionScope;
96
+ itemId: string;
97
+ capturedCeiling: Record<string, unknown>;
98
+ evidenceRef: string;
99
+ db: DatabaseInterface;
100
+ }): Promise<boolean>;
101
+ };
79
102
  /** Purge host-owned embeddings/previews/caches; retries must be idempotent. */
80
103
  purgeDerived(input: {
81
104
  tenantId: string;
@@ -90,6 +113,7 @@ export declare class IngestionService {
90
113
  private readonly options;
91
114
  private readonly db;
92
115
  private readonly scope;
116
+ private readonly dispatchTarget;
93
117
  constructor(options: IngestionOptions);
94
118
  private execution;
95
119
  previewProposal(input: PreviewProposalInput): Promise<import("./execution-dto.js").ProposalReview>;
@@ -136,6 +160,19 @@ export declare class IngestionService {
136
160
  /** Preserve every original before acknowledgment; retries retain receipt identity. */
137
161
  receive(input: ReceiveInput): Promise<ReceiptResult>;
138
162
  private preserve;
163
+ /** Inspect retained route provenance without changing state or enqueuing work. */
164
+ inspectDispatchRoute(itemId: string): Promise<DispatchRouteInspection>;
165
+ /** Explicitly bind a provenance-free legacy receipt to this trusted host's route.
166
+ * Never accepts a route from the caller, rewrites original authority, or enqueues.
167
+ */
168
+ recoverDispatchRoute(input: {
169
+ itemId: string;
170
+ expectedFingerprint: string;
171
+ evidenceRef: string;
172
+ }): Promise<DispatchRouteInspection>;
173
+ private matchesDispatchRoute;
174
+ private bindDispatchRoute;
175
+ private dispatchRouteState;
139
176
  /** Repair lost enqueue/mark writes and deleted/failed jobs. Duplicate jobs are safe. */
140
177
  repairDispatches(): Promise<number>;
141
178
  /** List only authorized active items; omitted items do not contribute counts. */
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
package/dist/server.js CHANGED
@@ -787,10 +787,16 @@ var IngestionService = class {
787
787
  if (!["sqlite", "postgres"].includes(engine) || !this.db.transaction) throw new Error("Ingestion requires transactional SQLite or PostgreSQL");
788
788
  nonempty(options.jobTarget.objectType);
789
789
  nonempty(options.jobTarget.method);
790
+ this.dispatchTarget = Object.freeze({
791
+ version: 1,
792
+ objectType: options.jobTarget.objectType,
793
+ method: options.jobTarget.method
794
+ });
790
795
  }
791
796
  options;
792
797
  db;
793
798
  scope;
799
+ dispatchTarget;
794
800
  async execution() {
795
801
  if (!this.options.execution) throw new Error("Intake execution is not configured");
796
802
  const { IntakeExecutionService } = await import("./execution.js");
@@ -1017,11 +1023,12 @@ var IngestionService = class {
1017
1023
  capturedCeiling: input.capturedCeiling,
1018
1024
  limits: input.limits,
1019
1025
  retentionVersion: input.retention.version,
1020
- deliveredAt: date(input.deliveredAt)
1026
+ deliveredAt: date(input.deliveredAt),
1027
+ dispatchTarget: this.dispatchTarget
1021
1028
  })
1022
1029
  }, "tenant_id,source_id,delivery_key");
1023
1030
  const item2 = (await db.query("SELECT * FROM intake_items WHERE tenant_id = ? AND source_id = ? AND delivery_key = ?", this.scope.tenantId, input.sourceId, input.deliveryKey)).rows[0];
1024
- if (item2.scope_digest !== scopeDigest || item2.payload_digest !== payloadDigest) return { kind: "conflict" };
1031
+ if (item2.scope_digest !== scopeDigest || item2.payload_digest !== payloadDigest || !await this.matchesDispatchRoute(db, item2)) return { kind: "conflict" };
1025
1032
  if (item2.visibility !== "active" || persistedDate(item2.replay_until) <= now || persistedDate(item2.expires_at) <= now) return { kind: "expired" };
1026
1033
  if (inserted.length) {
1027
1034
  const evidenceIds = new Map(parts.map((p) => [p.partId, randomUUID()]));
@@ -1092,7 +1099,7 @@ var IngestionService = class {
1092
1099
  state: "pending",
1093
1100
  job_id: "",
1094
1101
  deliveries: 0,
1095
- data: "{}"
1102
+ data: canonical({ dispatchTarget: this.dispatchTarget })
1096
1103
  }, "tenant_id,item_id,stage,revision");
1097
1104
  });
1098
1105
  await this.point("ready");
@@ -1157,23 +1164,187 @@ var IngestionService = class {
1157
1164
  await db.query("UPDATE intake_evidence SET state='durable' WHERE tenant_id=? AND confidential_scope_id=? AND id=?", this.scope.tenantId, this.scope.confidentialScopeId, evidence.id);
1158
1165
  });
1159
1166
  }
1167
+ /** Inspect retained route provenance without changing state or enqueuing work. */
1168
+ async inspectDispatchRoute(itemId) {
1169
+ const item = await this.item(itemId, "read");
1170
+ return this.dispatchRouteState(this.db, item);
1171
+ }
1172
+ /** Explicitly bind a provenance-free legacy receipt to this trusted host's route.
1173
+ * Never accepts a route from the caller, rewrites original authority, or enqueues.
1174
+ */
1175
+ async recoverDispatchRoute(input) {
1176
+ nonempty(input.evidenceRef);
1177
+ if (!/^[a-f0-9]{64}$/.test(input.expectedFingerprint)) throw new Error("Invalid dispatch recovery fingerprint");
1178
+ if (!this.options.dispatchRecovery) throw new Error("Dispatch recovery unavailable");
1179
+ return this.tx(async (db) => {
1180
+ await this.lock(db, input.itemId);
1181
+ const item = await this.item(input.itemId, "process", db);
1182
+ const data = object(item.data);
1183
+ if (!await this.options.dispatchRecovery.authorize({
1184
+ scope: this.scope,
1185
+ itemId: input.itemId,
1186
+ capturedCeiling: object(data.capturedCeiling),
1187
+ evidenceRef: input.evidenceRef,
1188
+ db
1189
+ })) throw new Error("Dispatch recovery unavailable");
1190
+ const current = await this.dispatchRouteState(db, item);
1191
+ const recovery = data.dispatchRecovery === void 0 ? null : object(data.dispatchRecovery);
1192
+ if (recovery && recovery.expectedFingerprint === input.expectedFingerprint && recovery.evidenceRef === input.evidenceRef && current.status === "bound" && canonical(current.target) === canonical(this.dispatchTarget)) return current;
1193
+ if (current.status !== "unknown" || current.fingerprint !== input.expectedFingerprint) throw new Error("Dispatch recovery conflict");
1194
+ data.dispatchRecovery = {
1195
+ version: 1,
1196
+ expectedFingerprint: input.expectedFingerprint,
1197
+ evidenceRef: input.evidenceRef,
1198
+ actorId: this.scope.actorId,
1199
+ recordedAt: date(this.now()),
1200
+ target: this.dispatchTarget
1201
+ };
1202
+ item.data = canonical(data);
1203
+ await this.bindDispatchRoute(db, item);
1204
+ await this.point("dispatch:recovered");
1205
+ const [updated] = await this.rows(db, "intake_items", "id=?", [item.id]);
1206
+ return this.dispatchRouteState(db, updated);
1207
+ });
1208
+ }
1209
+ async matchesDispatchRoute(db, item) {
1210
+ const route = await this.dispatchRouteState(db, item);
1211
+ return route.status === "bound" && canonical(route.target) === canonical(this.dispatchTarget);
1212
+ }
1213
+ async bindDispatchRoute(db, item) {
1214
+ const data = object(item.data);
1215
+ if (data.dispatchTarget === void 0) await db.query("UPDATE intake_items SET data=? WHERE tenant_id=? AND confidential_scope_id=? AND id=?", canonical({
1216
+ ...data,
1217
+ dispatchTarget: this.dispatchTarget
1218
+ }), this.scope.tenantId, this.scope.confidentialScopeId, item.id);
1219
+ const intents = await this.rows(db, "intake_dispatches", "item_id=?", [item.id]);
1220
+ for (const intent of intents) {
1221
+ const retained = object(intent.data);
1222
+ if (retained.dispatchTarget === void 0) await db.query("UPDATE intake_dispatches SET data=? WHERE tenant_id=? AND confidential_scope_id=? AND id=?", canonical({
1223
+ ...retained,
1224
+ dispatchTarget: this.dispatchTarget
1225
+ }), this.scope.tenantId, this.scope.confidentialScopeId, intent.id);
1226
+ }
1227
+ }
1228
+ async dispatchRouteState(db, item) {
1229
+ let invalid = false;
1230
+ const malformed = [];
1231
+ const payload = (value) => {
1232
+ try {
1233
+ return object(value);
1234
+ } catch {
1235
+ invalid = true;
1236
+ malformed.push(digest(value));
1237
+ return {};
1238
+ }
1239
+ };
1240
+ const data = payload(item.data);
1241
+ const intents = (await this.rows(db, "intake_dispatches", "item_id=?", [item.id])).sort((a, b) => String(a.id).localeCompare(String(b.id)));
1242
+ const targets = [];
1243
+ const lineage = [];
1244
+ const retain = (value) => {
1245
+ if (value === void 0) return;
1246
+ try {
1247
+ const target = object(value);
1248
+ nonempty(target.objectType);
1249
+ nonempty(target.method);
1250
+ if (target.version !== 1) throw new Error("Unsupported dispatch route");
1251
+ targets.push({
1252
+ version: 1,
1253
+ objectType: target.objectType,
1254
+ method: target.method
1255
+ });
1256
+ } catch {
1257
+ invalid = true;
1258
+ }
1259
+ };
1260
+ retain(data.dispatchTarget);
1261
+ if (data.dispatchRecovery !== void 0) {
1262
+ const recovery = payload(data.dispatchRecovery);
1263
+ if (recovery.version !== 1 || recovery.target === void 0) invalid = true;
1264
+ retain(recovery.target);
1265
+ }
1266
+ const jobs = await SmrtJobCollection.create({ db });
1267
+ for (const intent of intents) {
1268
+ retain(payload(intent.data).dispatchTarget);
1269
+ if (!intent.job_id) continue;
1270
+ const job = await withTenant({ tenantId: this.scope.tenantId }, () => jobs.get({ id: String(intent.job_id) }));
1271
+ if (!job) {
1272
+ lineage.push({
1273
+ id: intent.job_id,
1274
+ missing: true
1275
+ });
1276
+ continue;
1277
+ }
1278
+ const args = payload(job.args);
1279
+ if (job.tenantId !== this.scope.tenantId || job.queue !== "ingestion" || job.objectId || args.itemId !== item.id || args.dispatchId !== intent.id || args.revision !== Number(intent.revision)) {
1280
+ invalid = true;
1281
+ lineage.push({
1282
+ id: intent.job_id,
1283
+ valid: false
1284
+ });
1285
+ continue;
1286
+ }
1287
+ const target = {
1288
+ version: 1,
1289
+ objectType: job.objectType,
1290
+ method: job.method
1291
+ };
1292
+ retain(target);
1293
+ lineage.push({
1294
+ id: job.id,
1295
+ target,
1296
+ args
1297
+ });
1298
+ }
1299
+ if (targets.some((target) => canonical(target) !== canonical(targets[0]))) invalid = true;
1300
+ const status = invalid ? "conflict" : targets.length ? "bound" : "unknown";
1301
+ return {
1302
+ status,
1303
+ target: status === "bound" ? targets[0] : null,
1304
+ fingerprint: digest({
1305
+ itemId: item.id,
1306
+ tenantId: item.tenant_id,
1307
+ confidentialScopeId: item.confidential_scope_id,
1308
+ sourceId: item.source_id,
1309
+ sourceVersion: item.source_version,
1310
+ payloadDigest: item.payload_digest,
1311
+ scopeDigest: item.scope_digest,
1312
+ revision: item.analysis_revision,
1313
+ data,
1314
+ intents: intents.map((intent) => ({
1315
+ id: intent.id,
1316
+ revision: intent.revision,
1317
+ data: payload(intent.data),
1318
+ jobId: intent.job_id
1319
+ })),
1320
+ lineage,
1321
+ malformed
1322
+ })
1323
+ };
1324
+ }
1160
1325
  /** Repair lost enqueue/mark writes and deleted/failed jobs. Duplicate jobs are safe. */
1161
1326
  async repairDispatches() {
1162
1327
  let repaired = 0;
1163
1328
  const intents = await this.rows(this.db, "intake_dispatches", "state <> 'completed'");
1164
1329
  const jobs = await SmrtJobCollection.create({ db: this.db });
1165
1330
  for (const intent of intents) {
1331
+ const [candidate] = await this.rows(this.db, "intake_items", "id=?", [intent.item_id]);
1332
+ if (!candidate || !await this.matchesDispatchRoute(this.db, candidate)) continue;
1166
1333
  const item = await this.item(String(intent.item_id), "process", this.db, true);
1167
1334
  if (item.visibility !== "active" || item.cancelled || persistedDate(item.expires_at) <= this.now()) continue;
1168
- if (intent.job_id && Number(intent.revision) === Math.max(1, Number(item.analysis_revision))) {
1169
- const job2 = await withTenant({ tenantId: this.scope.tenantId }, () => jobs.get({ id: String(intent.job_id) }));
1170
- if (job2 && ["pending", "running"].includes(job2.status)) continue;
1171
- }
1172
1335
  if (!await this.tx(async (db) => {
1173
1336
  await this.lock(db, String(item.id));
1337
+ const [routedItem] = await this.rows(db, "intake_items", "id=?", [item.id]);
1338
+ if (!routedItem || !await this.matchesDispatchRoute(db, routedItem)) return false;
1339
+ await this.bindDispatchRoute(db, routedItem);
1174
1340
  const currentItem = await this.item(String(item.id), "process", db);
1175
1341
  const [currentIntent] = await this.rows(db, "intake_dispatches", "id=? AND item_id=?", [intent.id, item.id]);
1176
1342
  if (!currentIntent || currentIntent.state === "completed") return false;
1343
+ if (currentIntent.job_id && Number(currentIntent.revision) === Math.max(1, Number(currentItem.analysis_revision))) {
1344
+ const currentJobs = await SmrtJobCollection.create({ db });
1345
+ const job2 = await withTenant({ tenantId: this.scope.tenantId }, () => currentJobs.get({ id: String(currentIntent.job_id) }));
1346
+ if (job2 && ["pending", "running"].includes(job2.status)) return false;
1347
+ }
1177
1348
  if (currentItem.cancelled || Number(currentIntent.revision) !== Math.max(1, Number(currentItem.analysis_revision))) {
1178
1349
  await db.query("UPDATE intake_dispatches SET state='completed' WHERE tenant_id=? AND confidential_scope_id=? AND id=?", this.scope.tenantId, this.scope.confidentialScopeId, currentIntent.id);
1179
1350
  return false;
@@ -1188,8 +1359,8 @@ var IngestionService = class {
1188
1359
  })) continue;
1189
1360
  const job = await withTenant({ tenantId: this.scope.tenantId }, () => jobs.enqueueJob({
1190
1361
  tenantId: this.scope.tenantId,
1191
- objectType: this.options.jobTarget.objectType,
1192
- method: this.options.jobTarget.method,
1362
+ objectType: this.dispatchTarget.objectType,
1363
+ method: this.dispatchTarget.method,
1193
1364
  args: {
1194
1365
  itemId: intent.item_id,
1195
1366
  revision: Number(intent.revision),
@@ -1260,6 +1431,8 @@ var IngestionService = class {
1260
1431
  const configDigest = digest(configuration);
1261
1432
  await this.lock(db, itemId);
1262
1433
  const item = await this.item(itemId, "process", db);
1434
+ if (!await this.matchesDispatchRoute(db, item)) throw new Error("Intake dispatch route unavailable");
1435
+ await this.bindDispatchRoute(db, item);
1263
1436
  if (item.receipt_state !== "ready" || item.cancelled) throw new Error("Intake not processable");
1264
1437
  const replay = (await this.rows(db, "intake_analyses", "item_id=?", [itemId])).find((a) => object(a.data).requestKey === requestKey);
1265
1438
  if (replay) {
@@ -1304,7 +1477,7 @@ var IngestionService = class {
1304
1477
  state: "pending",
1305
1478
  job_id: "",
1306
1479
  deliveries: 0,
1307
- data: "{}"
1480
+ data: canonical({ dispatchTarget: this.dispatchTarget })
1308
1481
  }, "tenant_id,item_id,stage,revision");
1309
1482
  return {
1310
1483
  id: String(analysis.id),