@byok-sdk/cloud-dataplane 0.6.0 → 0.7.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.
- package/dist/index.js +161 -17
- package/dist/index.js.map +1 -1
- package/dist/runtime.js +160 -16
- package/dist/runtime.js.map +1 -1
- package/dist/sql/0012_agent_home_contract.sql +41 -0
- package/dist/sql/0013_agent_egress_contract.sql +47 -0
- package/dist/stores/agent-egress.d.ts +14 -0
- package/dist/stores/devices.d.ts +4 -0
- package/dist/stores/index.d.ts +2 -1
- package/dist/stores/task-attempts.d.ts +16 -2
- package/dist/tenant-erasure.d.ts +2 -2
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -3,11 +3,11 @@ import { DEDUP_RING_CAPACITY, NONCE_TTL_MS, validateActivityAppend, projectTimel
|
|
|
3
3
|
import { contentHash, ByokCoreError, assertCanonicalTimestamp, isContentHash, tenantObjectKey, objectKeyPrefix, CoreConflictError, isLegalBoardTransition, checkSkillPackManifest, checkSkillPackEntry, SKILL_PACK_ENTRY_PATH, tenantId, SKILL_PACK_MANIFEST_SCHEMA_ID } from '@byok-sdk/core';
|
|
4
4
|
import { AwsClient } from 'aws4fetch';
|
|
5
5
|
import { XMLParser } from 'fast-xml-parser';
|
|
6
|
+
import { decodeEnvelope, isServerToDaemonType, EnvelopeSchema, encodeEnvelope, AgentEgressReliablePayloadSchema } from '@byok-sdk/protocol';
|
|
6
7
|
import { createHash, randomUUID } from 'crypto';
|
|
7
8
|
import { readdir, readFile } from 'fs/promises';
|
|
8
9
|
import { join } from 'path';
|
|
9
10
|
import { fileURLToPath } from 'url';
|
|
10
|
-
import { decodeEnvelope, isServerToDaemonType, EnvelopeSchema, encodeEnvelope } from '@byok-sdk/protocol';
|
|
11
11
|
|
|
12
12
|
// src/pool.ts
|
|
13
13
|
var defaultTypeParser = pg.types.getTypeParser;
|
|
@@ -802,10 +802,11 @@ function toRecord(row) {
|
|
|
802
802
|
devicePublicKey: row.device_public_key,
|
|
803
803
|
proofKeyId: row.proof_key_id,
|
|
804
804
|
proofKeyEpoch: row.proof_key_epoch,
|
|
805
|
-
revoked: row.revoked
|
|
805
|
+
revoked: row.revoked,
|
|
806
|
+
...row.capabilities == null ? {} : { capabilities: Object.freeze([...row.capabilities]) }
|
|
806
807
|
};
|
|
807
808
|
}
|
|
808
|
-
var SELECT_COLUMNS = "tenant_id, device_id, product_id, device_name, device_public_key, proof_key_id, proof_key_epoch, revoked";
|
|
809
|
+
var SELECT_COLUMNS = "tenant_id, device_id, product_id, device_name, device_public_key, proof_key_id, proof_key_epoch, revoked, capabilities";
|
|
809
810
|
var PostgresDeviceDirectory = class {
|
|
810
811
|
#pool;
|
|
811
812
|
#clock;
|
|
@@ -826,7 +827,8 @@ var PostgresDeviceDirectory = class {
|
|
|
826
827
|
device_public_key = EXCLUDED.device_public_key,
|
|
827
828
|
proof_key_id = EXCLUDED.proof_key_id,
|
|
828
829
|
proof_key_epoch = EXCLUDED.proof_key_epoch,
|
|
829
|
-
revoked = false
|
|
830
|
+
revoked = false,
|
|
831
|
+
capabilities = NULL
|
|
830
832
|
RETURNING ${SELECT_COLUMNS}`,
|
|
831
833
|
[
|
|
832
834
|
tenant,
|
|
@@ -854,6 +856,17 @@ var PostgresDeviceDirectory = class {
|
|
|
854
856
|
deviceId
|
|
855
857
|
]);
|
|
856
858
|
}
|
|
859
|
+
async recordCapabilities(tenant, input) {
|
|
860
|
+
const result = await this.#pool.query(
|
|
861
|
+
`UPDATE device
|
|
862
|
+
SET capabilities = $3::jsonb
|
|
863
|
+
WHERE tenant_id = $1 AND device_id = $2 AND revoked = false
|
|
864
|
+
RETURNING ${SELECT_COLUMNS}`,
|
|
865
|
+
[tenant, input.deviceId, JSON.stringify([...input.capabilities])]
|
|
866
|
+
);
|
|
867
|
+
const row = result.rows[0];
|
|
868
|
+
return row === void 0 ? void 0 : toRecord(row);
|
|
869
|
+
}
|
|
857
870
|
async list(tenant) {
|
|
858
871
|
const result = await this.#pool.query(
|
|
859
872
|
`SELECT ${SELECT_COLUMNS} FROM device WHERE tenant_id = $1 ORDER BY device_id`,
|
|
@@ -1151,18 +1164,25 @@ var PostgresProofRequestReceiptStore = class {
|
|
|
1151
1164
|
};
|
|
1152
1165
|
|
|
1153
1166
|
// src/stores/task-attempts.ts
|
|
1154
|
-
var TASK_SELECT_COLUMNS = "tenant_id, task_id, device_id, owner_device_id, status, cancel_requested_at, cancel_reason, cancel_message_id, updated_at";
|
|
1167
|
+
var TASK_SELECT_COLUMNS = "tenant_id, task_id, device_id, agent_id, agent_profile_revision, owner_device_id, status, terminal_cause, cancel_requested_at, cancel_reason, cancel_message_id, updated_at";
|
|
1155
1168
|
function taskRowToAttempt(row) {
|
|
1156
1169
|
return {
|
|
1157
1170
|
tenantId: row.tenant_id,
|
|
1158
1171
|
taskId: row.task_id,
|
|
1159
1172
|
deviceId: row.device_id,
|
|
1173
|
+
...row.agent_id == null || row.agent_profile_revision == null ? {} : {
|
|
1174
|
+
agentRef: {
|
|
1175
|
+
agentId: row.agent_id,
|
|
1176
|
+
profileRevision: row.agent_profile_revision
|
|
1177
|
+
}
|
|
1178
|
+
},
|
|
1160
1179
|
// `exactOptionalPropertyTypes` is off here, but an explicit absent key is
|
|
1161
1180
|
// still what the in-memory reference produces for an unclaimed attempt, and
|
|
1162
1181
|
// `toEqual` in the suite treats `undefined` and absent alike only for the
|
|
1163
1182
|
// former.
|
|
1164
1183
|
...row.owner_device_id === null ? {} : { ownerDeviceId: row.owner_device_id },
|
|
1165
1184
|
status: row.status,
|
|
1185
|
+
...row.terminal_cause == null ? {} : { terminalCause: row.terminal_cause },
|
|
1166
1186
|
...row.cancel_requested_at === null ? {} : {
|
|
1167
1187
|
cancellation: {
|
|
1168
1188
|
requestedAt: row.cancel_requested_at.toISOString(),
|
|
@@ -1181,11 +1201,21 @@ var PostgresTaskAttemptStore = class {
|
|
|
1181
1201
|
}
|
|
1182
1202
|
async open(tenant, input) {
|
|
1183
1203
|
const inserted = await this.#pool.query(
|
|
1184
|
-
`INSERT INTO task (
|
|
1185
|
-
|
|
1204
|
+
`INSERT INTO task (
|
|
1205
|
+
tenant_id, task_id, device_id, agent_id, agent_profile_revision,
|
|
1206
|
+
owner_device_id, status, updated_at
|
|
1207
|
+
)
|
|
1208
|
+
VALUES ($1, $2, $3, $4, $5, NULL, 'offered', $6)
|
|
1186
1209
|
ON CONFLICT (tenant_id, task_id) DO NOTHING
|
|
1187
1210
|
RETURNING ${TASK_SELECT_COLUMNS}`,
|
|
1188
|
-
[
|
|
1211
|
+
[
|
|
1212
|
+
tenant,
|
|
1213
|
+
input.taskId,
|
|
1214
|
+
input.deviceId,
|
|
1215
|
+
input.agentRef?.agentId ?? null,
|
|
1216
|
+
input.agentRef?.profileRevision ?? null,
|
|
1217
|
+
this.#now()
|
|
1218
|
+
]
|
|
1189
1219
|
);
|
|
1190
1220
|
const created = inserted.rows[0];
|
|
1191
1221
|
if (created !== void 0) return taskRowToAttempt(created);
|
|
@@ -1193,6 +1223,23 @@ var PostgresTaskAttemptStore = class {
|
|
|
1193
1223
|
if (existing === void 0) throw new Error(`task ${input.taskId} vanished during open`);
|
|
1194
1224
|
return existing;
|
|
1195
1225
|
}
|
|
1226
|
+
async reserveAgentOffer(tenant, input) {
|
|
1227
|
+
const inserted = await this.#pool.query(
|
|
1228
|
+
`INSERT INTO task (
|
|
1229
|
+
tenant_id, task_id, device_id, agent_id, agent_profile_revision,
|
|
1230
|
+
owner_device_id, status, updated_at
|
|
1231
|
+
)
|
|
1232
|
+
VALUES ($1, $2, $3, $4, $5, NULL, 'offered', $6)
|
|
1233
|
+
ON CONFLICT (tenant_id, task_id) DO NOTHING
|
|
1234
|
+
RETURNING ${TASK_SELECT_COLUMNS}`,
|
|
1235
|
+
[tenant, input.taskId, input.deviceId, input.agentRef.agentId, input.agentRef.profileRevision, this.#now()]
|
|
1236
|
+
);
|
|
1237
|
+
const created = inserted.rows[0];
|
|
1238
|
+
if (created !== void 0) return { attempt: taskRowToAttempt(created), created: true };
|
|
1239
|
+
const existing = await this.get(tenant, input.taskId);
|
|
1240
|
+
if (existing === void 0) throw new Error(`task ${input.taskId} vanished during Agent offer reservation`);
|
|
1241
|
+
return { attempt: existing, created: false };
|
|
1242
|
+
}
|
|
1196
1243
|
async get(tenant, taskId) {
|
|
1197
1244
|
const result = await this.#pool.query(
|
|
1198
1245
|
`SELECT ${TASK_SELECT_COLUMNS} FROM task WHERE tenant_id = $1 AND task_id = $2`,
|
|
@@ -1225,14 +1272,28 @@ var PostgresTaskAttemptStore = class {
|
|
|
1225
1272
|
async recordStatus(tenant, input) {
|
|
1226
1273
|
const result = await this.#pool.query(
|
|
1227
1274
|
`UPDATE task
|
|
1228
|
-
SET status = $3,
|
|
1275
|
+
SET status = $3,
|
|
1276
|
+
terminal_cause = COALESCE($7, terminal_cause),
|
|
1277
|
+
updated_at = $4
|
|
1229
1278
|
WHERE tenant_id = $1 AND task_id = $2
|
|
1279
|
+
AND (
|
|
1280
|
+
(agent_id IS NULL AND agent_profile_revision IS NULL AND $5::text IS NULL AND $6::text IS NULL)
|
|
1281
|
+
OR (agent_id = $5 AND agent_profile_revision = $6)
|
|
1282
|
+
)
|
|
1230
1283
|
AND (
|
|
1231
1284
|
(cancel_requested_at IS NULL AND status NOT IN ('complete', 'failed', 'cancelled'))
|
|
1232
1285
|
OR (cancel_requested_at IS NOT NULL AND $3 = 'cancelled' AND status <> 'cancelled')
|
|
1233
1286
|
)
|
|
1234
1287
|
RETURNING ${TASK_SELECT_COLUMNS}`,
|
|
1235
|
-
[
|
|
1288
|
+
[
|
|
1289
|
+
tenant,
|
|
1290
|
+
input.taskId,
|
|
1291
|
+
input.status,
|
|
1292
|
+
this.#now(),
|
|
1293
|
+
input.agentRef?.agentId ?? null,
|
|
1294
|
+
input.agentRef?.profileRevision ?? null,
|
|
1295
|
+
input.terminalCause ?? null
|
|
1296
|
+
]
|
|
1236
1297
|
);
|
|
1237
1298
|
const row = result.rows[0];
|
|
1238
1299
|
return row === void 0 ? this.get(tenant, input.taskId) : taskRowToAttempt(row);
|
|
@@ -1790,6 +1851,87 @@ var PostgresApprovalTimelineStore = class {
|
|
|
1790
1851
|
return row === void 0 ? void 0 : toTail2(row);
|
|
1791
1852
|
}
|
|
1792
1853
|
};
|
|
1854
|
+
var SELECT_COLUMNS4 = [
|
|
1855
|
+
"tenant_id",
|
|
1856
|
+
"device_id",
|
|
1857
|
+
"event_id",
|
|
1858
|
+
"agent_id",
|
|
1859
|
+
"agent_profile_revision",
|
|
1860
|
+
"session_ref",
|
|
1861
|
+
"policy_revision",
|
|
1862
|
+
"cursor",
|
|
1863
|
+
"payload_json",
|
|
1864
|
+
"content_hash",
|
|
1865
|
+
"byte_count",
|
|
1866
|
+
"receipt_id",
|
|
1867
|
+
"recorded_at"
|
|
1868
|
+
].join(", ");
|
|
1869
|
+
function toRecord2(row) {
|
|
1870
|
+
const payload = AgentEgressReliablePayloadSchema.parse({
|
|
1871
|
+
agentRef: { agentId: row.agent_id, profileRevision: row.agent_profile_revision },
|
|
1872
|
+
sessionRef: row.session_ref,
|
|
1873
|
+
policyRevision: row.policy_revision,
|
|
1874
|
+
eventId: row.event_id,
|
|
1875
|
+
cursor: Number(row.cursor),
|
|
1876
|
+
payload: row.payload_json,
|
|
1877
|
+
contentHash: row.content_hash,
|
|
1878
|
+
byteCount: row.byte_count
|
|
1879
|
+
});
|
|
1880
|
+
return {
|
|
1881
|
+
tenantId: row.tenant_id,
|
|
1882
|
+
deviceId: row.device_id,
|
|
1883
|
+
payload,
|
|
1884
|
+
receiptId: row.receipt_id,
|
|
1885
|
+
recordedAt: row.recorded_at.toISOString()
|
|
1886
|
+
};
|
|
1887
|
+
}
|
|
1888
|
+
var PostgresAgentEgressStore = class {
|
|
1889
|
+
constructor(pool, clock) {
|
|
1890
|
+
this.pool = pool;
|
|
1891
|
+
this.clock = clock;
|
|
1892
|
+
}
|
|
1893
|
+
pool;
|
|
1894
|
+
clock;
|
|
1895
|
+
async record(tenant, input) {
|
|
1896
|
+
const payload = AgentEgressReliablePayloadSchema.parse(input.payload);
|
|
1897
|
+
const inserted = await this.pool.query(
|
|
1898
|
+
`INSERT INTO agent_egress_event (${SELECT_COLUMNS4})
|
|
1899
|
+
VALUES ($1, $2, $3::uuid, $4, $5, $6, $7, $8::bigint, $9::jsonb, $10, $11::integer, $12::uuid, $13)
|
|
1900
|
+
ON CONFLICT (tenant_id, device_id, event_id) DO NOTHING
|
|
1901
|
+
RETURNING ${SELECT_COLUMNS4}`,
|
|
1902
|
+
[
|
|
1903
|
+
tenant,
|
|
1904
|
+
input.deviceId,
|
|
1905
|
+
payload.eventId,
|
|
1906
|
+
payload.agentRef.agentId,
|
|
1907
|
+
payload.agentRef.profileRevision,
|
|
1908
|
+
payload.sessionRef,
|
|
1909
|
+
payload.policyRevision,
|
|
1910
|
+
payload.cursor,
|
|
1911
|
+
JSON.stringify(payload.payload),
|
|
1912
|
+
payload.contentHash,
|
|
1913
|
+
payload.byteCount,
|
|
1914
|
+
input.receiptId,
|
|
1915
|
+
this.clock.now().toISOString()
|
|
1916
|
+
]
|
|
1917
|
+
);
|
|
1918
|
+
const row = inserted.rows[0];
|
|
1919
|
+
if (row !== void 0) return { record: toRecord2(row), created: true };
|
|
1920
|
+
const existing = await this.get(tenant, input.deviceId, payload.eventId);
|
|
1921
|
+
if (existing === void 0) throw new Error(`Agent egress ${payload.eventId} vanished during first-write record.`);
|
|
1922
|
+
return { record: existing, created: false };
|
|
1923
|
+
}
|
|
1924
|
+
async get(tenant, deviceId, eventId) {
|
|
1925
|
+
const result = await this.pool.query(
|
|
1926
|
+
`SELECT ${SELECT_COLUMNS4}
|
|
1927
|
+
FROM agent_egress_event
|
|
1928
|
+
WHERE tenant_id = $1 AND device_id = $2 AND event_id = $3::uuid`,
|
|
1929
|
+
[tenant, deviceId, eventId]
|
|
1930
|
+
);
|
|
1931
|
+
const row = result.rows[0];
|
|
1932
|
+
return row === void 0 ? void 0 : toRecord2(row);
|
|
1933
|
+
}
|
|
1934
|
+
};
|
|
1793
1935
|
|
|
1794
1936
|
// src/stores/device-assertion-replay.ts
|
|
1795
1937
|
var PostgresDeviceAssertionReplayAuthority = class {
|
|
@@ -1853,6 +1995,7 @@ function createPostgresCloudStores(options) {
|
|
|
1853
1995
|
tasks: new PostgresTaskAttemptStore(pool, clock),
|
|
1854
1996
|
cancellations: new PostgresTaskCancellationStore(pool, clock),
|
|
1855
1997
|
receipts: new PostgresRequestReceiptStore(pool, clock),
|
|
1998
|
+
egress: new PostgresAgentEgressStore(pool, clock),
|
|
1856
1999
|
proofReceipts: new PostgresProofRequestReceiptStore(pool, clock),
|
|
1857
2000
|
// A second `PostgresObjectStore` instance, not a shared one: it is a
|
|
1858
2001
|
// stateless wrapper over the pool, so the two read and write the same rows
|
|
@@ -2929,7 +3072,7 @@ var RECORD_COLUMNS = "tenant_id, kind, subject_id, rev, content_hash, byte_size,
|
|
|
2929
3072
|
function toBody(row) {
|
|
2930
3073
|
return row.body_kind === "inline" ? { kind: "inline", body: row.body_inline ?? "" } : { kind: "object", hash: row.body_object_hash ?? "" };
|
|
2931
3074
|
}
|
|
2932
|
-
function
|
|
3075
|
+
function toRecord3(row) {
|
|
2933
3076
|
return {
|
|
2934
3077
|
tenantId: row.tenant_id,
|
|
2935
3078
|
kind: row.kind,
|
|
@@ -2974,7 +3117,7 @@ var PostgresTruthStore = class {
|
|
|
2974
3117
|
]
|
|
2975
3118
|
);
|
|
2976
3119
|
const row = inserted.rows[0];
|
|
2977
|
-
if (row !== void 0) return
|
|
3120
|
+
if (row !== void 0) return toRecord3(row);
|
|
2978
3121
|
const existing = await this.getRecord(tenant, {
|
|
2979
3122
|
kind: "task.terminal",
|
|
2980
3123
|
recordKey: input.taskId
|
|
@@ -3040,7 +3183,7 @@ var PostgresTruthStore = class {
|
|
|
3040
3183
|
]
|
|
3041
3184
|
);
|
|
3042
3185
|
const row = written.rows[0];
|
|
3043
|
-
if (row !== void 0) return
|
|
3186
|
+
if (row !== void 0) return toRecord3(row);
|
|
3044
3187
|
const current = await this.getRecord(tenant, {
|
|
3045
3188
|
kind: input.kind,
|
|
3046
3189
|
recordKey: input.recordKey
|
|
@@ -3059,7 +3202,7 @@ var PostgresTruthStore = class {
|
|
|
3059
3202
|
[tenant, selector.kind, selector.recordKey]
|
|
3060
3203
|
);
|
|
3061
3204
|
const row = result.rows[0];
|
|
3062
|
-
return row === void 0 ? void 0 :
|
|
3205
|
+
return row === void 0 ? void 0 : toRecord3(row);
|
|
3063
3206
|
}
|
|
3064
3207
|
async listManifest(tenant, query) {
|
|
3065
3208
|
const result = await this.#pool.query(
|
|
@@ -3107,7 +3250,7 @@ var RECEIPT_COLUMNS = "tenant_id, device_id, request_id, operation, resource, bo
|
|
|
3107
3250
|
function toBody2(row) {
|
|
3108
3251
|
return row.body_kind === "inline" ? { kind: "inline", body: row.body_inline ?? "" } : { kind: "object", hash: row.body_object_hash ?? "" };
|
|
3109
3252
|
}
|
|
3110
|
-
function
|
|
3253
|
+
function toRecord4(tenant, row) {
|
|
3111
3254
|
return {
|
|
3112
3255
|
tenantId: tenant,
|
|
3113
3256
|
kind: row.kind,
|
|
@@ -3284,7 +3427,7 @@ var PostgresTruthCommitter = class {
|
|
|
3284
3427
|
);
|
|
3285
3428
|
current.set(
|
|
3286
3429
|
writeKey(write),
|
|
3287
|
-
result.rows[0] === void 0 ? void 0 :
|
|
3430
|
+
result.rows[0] === void 0 ? void 0 : toRecord4(tenant, result.rows[0])
|
|
3288
3431
|
);
|
|
3289
3432
|
}
|
|
3290
3433
|
return current;
|
|
@@ -3497,7 +3640,7 @@ var PostgresTruthCommitter = class {
|
|
|
3497
3640
|
applied.push({
|
|
3498
3641
|
input: write,
|
|
3499
3642
|
before,
|
|
3500
|
-
record:
|
|
3643
|
+
record: toRecord4(tenant, result.rows[0]),
|
|
3501
3644
|
mutated: true
|
|
3502
3645
|
});
|
|
3503
3646
|
}
|
|
@@ -4761,6 +4904,7 @@ var TENANT_ERASURE_TABLES = [
|
|
|
4761
4904
|
"board_item",
|
|
4762
4905
|
"tenant_stream",
|
|
4763
4906
|
"outbox",
|
|
4907
|
+
"agent_egress_event",
|
|
4764
4908
|
"device_request_receipts",
|
|
4765
4909
|
"proof_request_receipt",
|
|
4766
4910
|
"task",
|