@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/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 (tenant_id, task_id, device_id, owner_device_id, status, updated_at)
1180
- VALUES ($1, $2, $3, NULL, 'offered', $4)
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
- [tenant, input.taskId, input.deviceId, this.#now()]
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, updated_at = $4
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
- [tenant, input.taskId, input.status, this.#now()]
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 toRecord2(row) {
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 toRecord2(row);
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 toRecord2(row);
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 : toRecord2(row);
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 toRecord3(tenant, row) {
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 : toRecord3(tenant, result.rows[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: toRecord3(tenant, result.rows[0]),
3639
+ record: toRecord4(tenant, result.rows[0]),
3496
3640
  mutated: true
3497
3641
  });
3498
3642
  }