@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/runtime.js
CHANGED
|
@@ -3,6 +3,7 @@ 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, 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 { AgentEgressReliablePayloadSchema } from '@byok-sdk/protocol';
|
|
6
7
|
|
|
7
8
|
// src/pool.ts
|
|
8
9
|
var defaultTypeParser = pg.types.getTypeParser;
|
|
@@ -797,10 +798,11 @@ function toRecord(row) {
|
|
|
797
798
|
devicePublicKey: row.device_public_key,
|
|
798
799
|
proofKeyId: row.proof_key_id,
|
|
799
800
|
proofKeyEpoch: row.proof_key_epoch,
|
|
800
|
-
revoked: row.revoked
|
|
801
|
+
revoked: row.revoked,
|
|
802
|
+
...row.capabilities == null ? {} : { capabilities: Object.freeze([...row.capabilities]) }
|
|
801
803
|
};
|
|
802
804
|
}
|
|
803
|
-
var SELECT_COLUMNS = "tenant_id, device_id, product_id, device_name, device_public_key, proof_key_id, proof_key_epoch, revoked";
|
|
805
|
+
var SELECT_COLUMNS = "tenant_id, device_id, product_id, device_name, device_public_key, proof_key_id, proof_key_epoch, revoked, capabilities";
|
|
804
806
|
var PostgresDeviceDirectory = class {
|
|
805
807
|
#pool;
|
|
806
808
|
#clock;
|
|
@@ -821,7 +823,8 @@ var PostgresDeviceDirectory = class {
|
|
|
821
823
|
device_public_key = EXCLUDED.device_public_key,
|
|
822
824
|
proof_key_id = EXCLUDED.proof_key_id,
|
|
823
825
|
proof_key_epoch = EXCLUDED.proof_key_epoch,
|
|
824
|
-
revoked = false
|
|
826
|
+
revoked = false,
|
|
827
|
+
capabilities = NULL
|
|
825
828
|
RETURNING ${SELECT_COLUMNS}`,
|
|
826
829
|
[
|
|
827
830
|
tenant,
|
|
@@ -849,6 +852,17 @@ var PostgresDeviceDirectory = class {
|
|
|
849
852
|
deviceId
|
|
850
853
|
]);
|
|
851
854
|
}
|
|
855
|
+
async recordCapabilities(tenant, input) {
|
|
856
|
+
const result = await this.#pool.query(
|
|
857
|
+
`UPDATE device
|
|
858
|
+
SET capabilities = $3::jsonb
|
|
859
|
+
WHERE tenant_id = $1 AND device_id = $2 AND revoked = false
|
|
860
|
+
RETURNING ${SELECT_COLUMNS}`,
|
|
861
|
+
[tenant, input.deviceId, JSON.stringify([...input.capabilities])]
|
|
862
|
+
);
|
|
863
|
+
const row = result.rows[0];
|
|
864
|
+
return row === void 0 ? void 0 : toRecord(row);
|
|
865
|
+
}
|
|
852
866
|
async list(tenant) {
|
|
853
867
|
const result = await this.#pool.query(
|
|
854
868
|
`SELECT ${SELECT_COLUMNS} FROM device WHERE tenant_id = $1 ORDER BY device_id`,
|
|
@@ -1146,18 +1160,25 @@ var PostgresProofRequestReceiptStore = class {
|
|
|
1146
1160
|
};
|
|
1147
1161
|
|
|
1148
1162
|
// src/stores/task-attempts.ts
|
|
1149
|
-
var TASK_SELECT_COLUMNS = "tenant_id, task_id, device_id, owner_device_id, status, cancel_requested_at, cancel_reason, cancel_message_id, updated_at";
|
|
1163
|
+
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";
|
|
1150
1164
|
function taskRowToAttempt(row) {
|
|
1151
1165
|
return {
|
|
1152
1166
|
tenantId: row.tenant_id,
|
|
1153
1167
|
taskId: row.task_id,
|
|
1154
1168
|
deviceId: row.device_id,
|
|
1169
|
+
...row.agent_id == null || row.agent_profile_revision == null ? {} : {
|
|
1170
|
+
agentRef: {
|
|
1171
|
+
agentId: row.agent_id,
|
|
1172
|
+
profileRevision: row.agent_profile_revision
|
|
1173
|
+
}
|
|
1174
|
+
},
|
|
1155
1175
|
// `exactOptionalPropertyTypes` is off here, but an explicit absent key is
|
|
1156
1176
|
// still what the in-memory reference produces for an unclaimed attempt, and
|
|
1157
1177
|
// `toEqual` in the suite treats `undefined` and absent alike only for the
|
|
1158
1178
|
// former.
|
|
1159
1179
|
...row.owner_device_id === null ? {} : { ownerDeviceId: row.owner_device_id },
|
|
1160
1180
|
status: row.status,
|
|
1181
|
+
...row.terminal_cause == null ? {} : { terminalCause: row.terminal_cause },
|
|
1161
1182
|
...row.cancel_requested_at === null ? {} : {
|
|
1162
1183
|
cancellation: {
|
|
1163
1184
|
requestedAt: row.cancel_requested_at.toISOString(),
|
|
@@ -1176,11 +1197,21 @@ var PostgresTaskAttemptStore = class {
|
|
|
1176
1197
|
}
|
|
1177
1198
|
async open(tenant, input) {
|
|
1178
1199
|
const inserted = await this.#pool.query(
|
|
1179
|
-
`INSERT INTO task (
|
|
1180
|
-
|
|
1200
|
+
`INSERT INTO task (
|
|
1201
|
+
tenant_id, task_id, device_id, agent_id, agent_profile_revision,
|
|
1202
|
+
owner_device_id, status, updated_at
|
|
1203
|
+
)
|
|
1204
|
+
VALUES ($1, $2, $3, $4, $5, NULL, 'offered', $6)
|
|
1181
1205
|
ON CONFLICT (tenant_id, task_id) DO NOTHING
|
|
1182
1206
|
RETURNING ${TASK_SELECT_COLUMNS}`,
|
|
1183
|
-
[
|
|
1207
|
+
[
|
|
1208
|
+
tenant,
|
|
1209
|
+
input.taskId,
|
|
1210
|
+
input.deviceId,
|
|
1211
|
+
input.agentRef?.agentId ?? null,
|
|
1212
|
+
input.agentRef?.profileRevision ?? null,
|
|
1213
|
+
this.#now()
|
|
1214
|
+
]
|
|
1184
1215
|
);
|
|
1185
1216
|
const created = inserted.rows[0];
|
|
1186
1217
|
if (created !== void 0) return taskRowToAttempt(created);
|
|
@@ -1188,6 +1219,23 @@ var PostgresTaskAttemptStore = class {
|
|
|
1188
1219
|
if (existing === void 0) throw new Error(`task ${input.taskId} vanished during open`);
|
|
1189
1220
|
return existing;
|
|
1190
1221
|
}
|
|
1222
|
+
async reserveAgentOffer(tenant, input) {
|
|
1223
|
+
const inserted = await this.#pool.query(
|
|
1224
|
+
`INSERT INTO task (
|
|
1225
|
+
tenant_id, task_id, device_id, agent_id, agent_profile_revision,
|
|
1226
|
+
owner_device_id, status, updated_at
|
|
1227
|
+
)
|
|
1228
|
+
VALUES ($1, $2, $3, $4, $5, NULL, 'offered', $6)
|
|
1229
|
+
ON CONFLICT (tenant_id, task_id) DO NOTHING
|
|
1230
|
+
RETURNING ${TASK_SELECT_COLUMNS}`,
|
|
1231
|
+
[tenant, input.taskId, input.deviceId, input.agentRef.agentId, input.agentRef.profileRevision, this.#now()]
|
|
1232
|
+
);
|
|
1233
|
+
const created = inserted.rows[0];
|
|
1234
|
+
if (created !== void 0) return { attempt: taskRowToAttempt(created), created: true };
|
|
1235
|
+
const existing = await this.get(tenant, input.taskId);
|
|
1236
|
+
if (existing === void 0) throw new Error(`task ${input.taskId} vanished during Agent offer reservation`);
|
|
1237
|
+
return { attempt: existing, created: false };
|
|
1238
|
+
}
|
|
1191
1239
|
async get(tenant, taskId) {
|
|
1192
1240
|
const result = await this.#pool.query(
|
|
1193
1241
|
`SELECT ${TASK_SELECT_COLUMNS} FROM task WHERE tenant_id = $1 AND task_id = $2`,
|
|
@@ -1220,14 +1268,28 @@ var PostgresTaskAttemptStore = class {
|
|
|
1220
1268
|
async recordStatus(tenant, input) {
|
|
1221
1269
|
const result = await this.#pool.query(
|
|
1222
1270
|
`UPDATE task
|
|
1223
|
-
SET status = $3,
|
|
1271
|
+
SET status = $3,
|
|
1272
|
+
terminal_cause = COALESCE($7, terminal_cause),
|
|
1273
|
+
updated_at = $4
|
|
1224
1274
|
WHERE tenant_id = $1 AND task_id = $2
|
|
1275
|
+
AND (
|
|
1276
|
+
(agent_id IS NULL AND agent_profile_revision IS NULL AND $5::text IS NULL AND $6::text IS NULL)
|
|
1277
|
+
OR (agent_id = $5 AND agent_profile_revision = $6)
|
|
1278
|
+
)
|
|
1225
1279
|
AND (
|
|
1226
1280
|
(cancel_requested_at IS NULL AND status NOT IN ('complete', 'failed', 'cancelled'))
|
|
1227
1281
|
OR (cancel_requested_at IS NOT NULL AND $3 = 'cancelled' AND status <> 'cancelled')
|
|
1228
1282
|
)
|
|
1229
1283
|
RETURNING ${TASK_SELECT_COLUMNS}`,
|
|
1230
|
-
[
|
|
1284
|
+
[
|
|
1285
|
+
tenant,
|
|
1286
|
+
input.taskId,
|
|
1287
|
+
input.status,
|
|
1288
|
+
this.#now(),
|
|
1289
|
+
input.agentRef?.agentId ?? null,
|
|
1290
|
+
input.agentRef?.profileRevision ?? null,
|
|
1291
|
+
input.terminalCause ?? null
|
|
1292
|
+
]
|
|
1231
1293
|
);
|
|
1232
1294
|
const row = result.rows[0];
|
|
1233
1295
|
return row === void 0 ? this.get(tenant, input.taskId) : taskRowToAttempt(row);
|
|
@@ -1785,6 +1847,87 @@ var PostgresApprovalTimelineStore = class {
|
|
|
1785
1847
|
return row === void 0 ? void 0 : toTail2(row);
|
|
1786
1848
|
}
|
|
1787
1849
|
};
|
|
1850
|
+
var SELECT_COLUMNS4 = [
|
|
1851
|
+
"tenant_id",
|
|
1852
|
+
"device_id",
|
|
1853
|
+
"event_id",
|
|
1854
|
+
"agent_id",
|
|
1855
|
+
"agent_profile_revision",
|
|
1856
|
+
"session_ref",
|
|
1857
|
+
"policy_revision",
|
|
1858
|
+
"cursor",
|
|
1859
|
+
"payload_json",
|
|
1860
|
+
"content_hash",
|
|
1861
|
+
"byte_count",
|
|
1862
|
+
"receipt_id",
|
|
1863
|
+
"recorded_at"
|
|
1864
|
+
].join(", ");
|
|
1865
|
+
function toRecord2(row) {
|
|
1866
|
+
const payload = AgentEgressReliablePayloadSchema.parse({
|
|
1867
|
+
agentRef: { agentId: row.agent_id, profileRevision: row.agent_profile_revision },
|
|
1868
|
+
sessionRef: row.session_ref,
|
|
1869
|
+
policyRevision: row.policy_revision,
|
|
1870
|
+
eventId: row.event_id,
|
|
1871
|
+
cursor: Number(row.cursor),
|
|
1872
|
+
payload: row.payload_json,
|
|
1873
|
+
contentHash: row.content_hash,
|
|
1874
|
+
byteCount: row.byte_count
|
|
1875
|
+
});
|
|
1876
|
+
return {
|
|
1877
|
+
tenantId: row.tenant_id,
|
|
1878
|
+
deviceId: row.device_id,
|
|
1879
|
+
payload,
|
|
1880
|
+
receiptId: row.receipt_id,
|
|
1881
|
+
recordedAt: row.recorded_at.toISOString()
|
|
1882
|
+
};
|
|
1883
|
+
}
|
|
1884
|
+
var PostgresAgentEgressStore = class {
|
|
1885
|
+
constructor(pool, clock) {
|
|
1886
|
+
this.pool = pool;
|
|
1887
|
+
this.clock = clock;
|
|
1888
|
+
}
|
|
1889
|
+
pool;
|
|
1890
|
+
clock;
|
|
1891
|
+
async record(tenant, input) {
|
|
1892
|
+
const payload = AgentEgressReliablePayloadSchema.parse(input.payload);
|
|
1893
|
+
const inserted = await this.pool.query(
|
|
1894
|
+
`INSERT INTO agent_egress_event (${SELECT_COLUMNS4})
|
|
1895
|
+
VALUES ($1, $2, $3::uuid, $4, $5, $6, $7, $8::bigint, $9::jsonb, $10, $11::integer, $12::uuid, $13)
|
|
1896
|
+
ON CONFLICT (tenant_id, device_id, event_id) DO NOTHING
|
|
1897
|
+
RETURNING ${SELECT_COLUMNS4}`,
|
|
1898
|
+
[
|
|
1899
|
+
tenant,
|
|
1900
|
+
input.deviceId,
|
|
1901
|
+
payload.eventId,
|
|
1902
|
+
payload.agentRef.agentId,
|
|
1903
|
+
payload.agentRef.profileRevision,
|
|
1904
|
+
payload.sessionRef,
|
|
1905
|
+
payload.policyRevision,
|
|
1906
|
+
payload.cursor,
|
|
1907
|
+
JSON.stringify(payload.payload),
|
|
1908
|
+
payload.contentHash,
|
|
1909
|
+
payload.byteCount,
|
|
1910
|
+
input.receiptId,
|
|
1911
|
+
this.clock.now().toISOString()
|
|
1912
|
+
]
|
|
1913
|
+
);
|
|
1914
|
+
const row = inserted.rows[0];
|
|
1915
|
+
if (row !== void 0) return { record: toRecord2(row), created: true };
|
|
1916
|
+
const existing = await this.get(tenant, input.deviceId, payload.eventId);
|
|
1917
|
+
if (existing === void 0) throw new Error(`Agent egress ${payload.eventId} vanished during first-write record.`);
|
|
1918
|
+
return { record: existing, created: false };
|
|
1919
|
+
}
|
|
1920
|
+
async get(tenant, deviceId, eventId) {
|
|
1921
|
+
const result = await this.pool.query(
|
|
1922
|
+
`SELECT ${SELECT_COLUMNS4}
|
|
1923
|
+
FROM agent_egress_event
|
|
1924
|
+
WHERE tenant_id = $1 AND device_id = $2 AND event_id = $3::uuid`,
|
|
1925
|
+
[tenant, deviceId, eventId]
|
|
1926
|
+
);
|
|
1927
|
+
const row = result.rows[0];
|
|
1928
|
+
return row === void 0 ? void 0 : toRecord2(row);
|
|
1929
|
+
}
|
|
1930
|
+
};
|
|
1788
1931
|
|
|
1789
1932
|
// src/stores/device-assertion-replay.ts
|
|
1790
1933
|
var PostgresDeviceAssertionReplayAuthority = class {
|
|
@@ -1848,6 +1991,7 @@ function createPostgresCloudStores(options) {
|
|
|
1848
1991
|
tasks: new PostgresTaskAttemptStore(pool, clock),
|
|
1849
1992
|
cancellations: new PostgresTaskCancellationStore(pool, clock),
|
|
1850
1993
|
receipts: new PostgresRequestReceiptStore(pool, clock),
|
|
1994
|
+
egress: new PostgresAgentEgressStore(pool, clock),
|
|
1851
1995
|
proofReceipts: new PostgresProofRequestReceiptStore(pool, clock),
|
|
1852
1996
|
// A second `PostgresObjectStore` instance, not a shared one: it is a
|
|
1853
1997
|
// stateless wrapper over the pool, so the two read and write the same rows
|
|
@@ -2924,7 +3068,7 @@ var RECORD_COLUMNS = "tenant_id, kind, subject_id, rev, content_hash, byte_size,
|
|
|
2924
3068
|
function toBody(row) {
|
|
2925
3069
|
return row.body_kind === "inline" ? { kind: "inline", body: row.body_inline ?? "" } : { kind: "object", hash: row.body_object_hash ?? "" };
|
|
2926
3070
|
}
|
|
2927
|
-
function
|
|
3071
|
+
function toRecord3(row) {
|
|
2928
3072
|
return {
|
|
2929
3073
|
tenantId: row.tenant_id,
|
|
2930
3074
|
kind: row.kind,
|
|
@@ -2969,7 +3113,7 @@ var PostgresTruthStore = class {
|
|
|
2969
3113
|
]
|
|
2970
3114
|
);
|
|
2971
3115
|
const row = inserted.rows[0];
|
|
2972
|
-
if (row !== void 0) return
|
|
3116
|
+
if (row !== void 0) return toRecord3(row);
|
|
2973
3117
|
const existing = await this.getRecord(tenant, {
|
|
2974
3118
|
kind: "task.terminal",
|
|
2975
3119
|
recordKey: input.taskId
|
|
@@ -3035,7 +3179,7 @@ var PostgresTruthStore = class {
|
|
|
3035
3179
|
]
|
|
3036
3180
|
);
|
|
3037
3181
|
const row = written.rows[0];
|
|
3038
|
-
if (row !== void 0) return
|
|
3182
|
+
if (row !== void 0) return toRecord3(row);
|
|
3039
3183
|
const current = await this.getRecord(tenant, {
|
|
3040
3184
|
kind: input.kind,
|
|
3041
3185
|
recordKey: input.recordKey
|
|
@@ -3054,7 +3198,7 @@ var PostgresTruthStore = class {
|
|
|
3054
3198
|
[tenant, selector.kind, selector.recordKey]
|
|
3055
3199
|
);
|
|
3056
3200
|
const row = result.rows[0];
|
|
3057
|
-
return row === void 0 ? void 0 :
|
|
3201
|
+
return row === void 0 ? void 0 : toRecord3(row);
|
|
3058
3202
|
}
|
|
3059
3203
|
async listManifest(tenant, query) {
|
|
3060
3204
|
const result = await this.#pool.query(
|
|
@@ -3102,7 +3246,7 @@ var RECEIPT_COLUMNS = "tenant_id, device_id, request_id, operation, resource, bo
|
|
|
3102
3246
|
function toBody2(row) {
|
|
3103
3247
|
return row.body_kind === "inline" ? { kind: "inline", body: row.body_inline ?? "" } : { kind: "object", hash: row.body_object_hash ?? "" };
|
|
3104
3248
|
}
|
|
3105
|
-
function
|
|
3249
|
+
function toRecord4(tenant, row) {
|
|
3106
3250
|
return {
|
|
3107
3251
|
tenantId: tenant,
|
|
3108
3252
|
kind: row.kind,
|
|
@@ -3279,7 +3423,7 @@ var PostgresTruthCommitter = class {
|
|
|
3279
3423
|
);
|
|
3280
3424
|
current.set(
|
|
3281
3425
|
writeKey(write),
|
|
3282
|
-
result.rows[0] === void 0 ? void 0 :
|
|
3426
|
+
result.rows[0] === void 0 ? void 0 : toRecord4(tenant, result.rows[0])
|
|
3283
3427
|
);
|
|
3284
3428
|
}
|
|
3285
3429
|
return current;
|
|
@@ -3492,7 +3636,7 @@ var PostgresTruthCommitter = class {
|
|
|
3492
3636
|
applied.push({
|
|
3493
3637
|
input: write,
|
|
3494
3638
|
before,
|
|
3495
|
-
record:
|
|
3639
|
+
record: toRecord4(tenant, result.rows[0]),
|
|
3496
3640
|
mutated: true
|
|
3497
3641
|
});
|
|
3498
3642
|
}
|