@happyvertical/smrt-ingestion 0.57.4 → 0.57.5
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/README.md +42 -0
- package/REVIEW.md +16 -0
- package/dist/manifest.json +1 -1
- package/dist/models.js +1 -1
- package/dist/models.js.map +1 -1
- package/dist/server.d.ts +37 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +183 -10
- package/dist/server.js.map +1 -1
- package/dist/smrt-knowledge.json +7 -7
- package/dist/svelte/components/InboxView.svelte +17 -4
- package/dist/svelte/components/InboxView.svelte.d.ts.map +1 -1
- package/package.json +17 -17
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. */
|
package/dist/server.d.ts.map
CHANGED
|
@@ -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.
|
|
1192
|
-
method: this.
|
|
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),
|