@byok-sdk/cloud-dataplane 0.12.0 → 0.13.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 +231 -29
- package/dist/index.js.map +1 -1
- package/dist/runtime.js +231 -29
- package/dist/runtime.js.map +1 -1
- package/dist/sql/0018_task_attempt_claimed_runtime.sql +23 -0
- package/dist/sql/0019_agent_ref_replay_keys.sql +36 -0
- package/dist/sql/0020_agent_ref_request_keys.sql +7 -0
- package/dist/stores/agent-egress.d.ts +2 -1
- package/dist/stores/approval-timeline.d.ts +2 -1
- package/dist/stores/dedup.d.ts +8 -5
- package/dist/stores/task-attempts.d.ts +8 -2
- package/package.json +4 -4
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
-- The claim-time runtime snapshot on the task attempt.
|
|
2
|
+
--
|
|
3
|
+
-- Two columns, one fact: what the daemon that WON the ownership CAS reported
|
|
4
|
+
-- about itself on its own `task.claim` — its runtime id and that adapter's own
|
|
5
|
+
-- capability block. Both are written by the guarded claim UPDATE and by nothing
|
|
6
|
+
-- else, so they are set exactly once, at the `offered -> claimed` transition,
|
|
7
|
+
-- and a redelivered or losing claim can never restamp them.
|
|
8
|
+
--
|
|
9
|
+
-- They are ATTRIBUTION, not execution state: they stop changing the moment
|
|
10
|
+
-- ownership is decided, which is what keeps them inside what ADR-028 allows the
|
|
11
|
+
-- coordination plane to hold. `ByokCloud.steerTask` reads
|
|
12
|
+
-- `claimed_runtime_capabilities` as the single input to its steer gate; the
|
|
13
|
+
-- connection-level capability snapshot on the device row is deliberately not an
|
|
14
|
+
-- input, because it describes a device build rather than the adapter that took
|
|
15
|
+
-- this task.
|
|
16
|
+
--
|
|
17
|
+
-- Additive and nullable with NO backfill, deliberately. A task claimed before
|
|
18
|
+
-- this migration has no snapshot to reconstruct — the claim that carried it is
|
|
19
|
+
-- long gone — and inventing one would open the steer gate on a guess. NULL
|
|
20
|
+
-- means "unknown", and the gate refuses an unknown.
|
|
21
|
+
|
|
22
|
+
ALTER TABLE task ADD COLUMN claimed_runtime text;
|
|
23
|
+
ALTER TABLE task ADD COLUMN claimed_runtime_capabilities jsonb;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
-- Strict Agent reliability identities.
|
|
2
|
+
--
|
|
3
|
+
-- A device may host many Agents. The old device-plus-envelope/event primary
|
|
4
|
+
-- keys therefore let Agent A suppress Agent B when they independently used
|
|
5
|
+
-- the same reliable id. This migration cuts those keys forward: physical facts
|
|
6
|
+
-- retain the empty Agent scope, while every Agent-bound caller must supply the
|
|
7
|
+
-- exact AgentRef. The empty pair is not an AgentRef and is never a read
|
|
8
|
+
-- fallback; it is the explicit keyspace for facts such as conn.hello that have
|
|
9
|
+
-- no Agent authority.
|
|
10
|
+
|
|
11
|
+
ALTER TABLE inbound_dedup
|
|
12
|
+
ADD COLUMN agent_id text NOT NULL DEFAULT '',
|
|
13
|
+
ADD COLUMN agent_profile_revision text NOT NULL DEFAULT '';
|
|
14
|
+
|
|
15
|
+
ALTER TABLE inbound_dedup
|
|
16
|
+
ADD CONSTRAINT inbound_dedup_agent_scope_shape CHECK (
|
|
17
|
+
(agent_id = '' AND agent_profile_revision = '') OR
|
|
18
|
+
(
|
|
19
|
+
octet_length(agent_id) BETWEEN 1 AND 160
|
|
20
|
+
AND octet_length(agent_profile_revision) BETWEEN 1 AND 160
|
|
21
|
+
AND agent_id !~ '[[:cntrl:]]'
|
|
22
|
+
AND agent_profile_revision !~ '[[:cntrl:]]'
|
|
23
|
+
)
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
ALTER TABLE inbound_dedup DROP CONSTRAINT inbound_dedup_pkey;
|
|
27
|
+
ALTER TABLE inbound_dedup
|
|
28
|
+
ADD PRIMARY KEY (tenant_id, device_id, agent_id, agent_profile_revision, envelope_id);
|
|
29
|
+
|
|
30
|
+
DROP INDEX inbound_dedup_reclaim_idx;
|
|
31
|
+
CREATE INDEX inbound_dedup_reclaim_idx
|
|
32
|
+
ON inbound_dedup (tenant_id, device_id, agent_id, agent_profile_revision, recorded_seq);
|
|
33
|
+
|
|
34
|
+
ALTER TABLE agent_egress_event DROP CONSTRAINT agent_egress_event_pkey;
|
|
35
|
+
ALTER TABLE agent_egress_event
|
|
36
|
+
ADD PRIMARY KEY (tenant_id, device_id, agent_id, agent_profile_revision, event_id);
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
-- Agent reliability identities are exact to the attempt's AgentRef. The
|
|
2
|
+
-- task-bound primary key already supplies that authority through `task`; a
|
|
3
|
+
-- device-wide message-id uniqueness constraint would instead let one Agent
|
|
4
|
+
-- suppress another active Agent on the same device.
|
|
5
|
+
|
|
6
|
+
ALTER TABLE agent_message_admission
|
|
7
|
+
DROP CONSTRAINT agent_message_admission_tenant_id_device_id_message_id_key;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type AgentEgressReliablePayload } from '@byok-sdk/protocol';
|
|
1
2
|
import type { AgentEgressRecord, AgentEgressStore } from '@byok-sdk/cloud';
|
|
2
3
|
import type { Clock, TenantId } from '@byok-sdk/core';
|
|
3
4
|
import type { Pool } from 'pg';
|
|
@@ -10,5 +11,5 @@ export declare class PostgresAgentEgressStore implements AgentEgressStore {
|
|
|
10
11
|
readonly record: AgentEgressRecord;
|
|
11
12
|
readonly created: boolean;
|
|
12
13
|
}>;
|
|
13
|
-
get(tenant: TenantId, deviceId: string, eventId: string): Promise<AgentEgressRecord | undefined>;
|
|
14
|
+
get(tenant: TenantId, deviceId: string, agentRef: AgentEgressReliablePayload['agentRef'], eventId: string): Promise<AgentEgressRecord | undefined>;
|
|
14
15
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type ApprovalTimelineAppendInput, type ApprovalTimelineStore, type ApprovalTimelineTail } from '@byok-sdk/cloud';
|
|
1
|
+
import { type ApprovalTimelineAppendInput, type ApprovalTimelineResolvePendingInput, type ApprovalTimelineResolvePendingResult, type ApprovalTimelineStore, type ApprovalTimelineTail } from '@byok-sdk/cloud';
|
|
2
2
|
import type { Clock, TenantId } from '@byok-sdk/core';
|
|
3
3
|
import type { Pool } from 'pg';
|
|
4
4
|
export declare class PostgresApprovalTimelineStore implements ApprovalTimelineStore {
|
|
@@ -6,5 +6,6 @@ export declare class PostgresApprovalTimelineStore implements ApprovalTimelineSt
|
|
|
6
6
|
private readonly clock;
|
|
7
7
|
constructor(pool: Pool, clock: Clock);
|
|
8
8
|
append(tenant: TenantId, input: ApprovalTimelineAppendInput): Promise<ApprovalTimelineTail>;
|
|
9
|
+
resolvePending(tenant: TenantId, input: ApprovalTimelineResolvePendingInput): Promise<ApprovalTimelineResolvePendingResult>;
|
|
9
10
|
read(tenant: TenantId, taskId: string): Promise<ApprovalTimelineTail | undefined>;
|
|
10
11
|
}
|
package/dist/stores/dedup.d.ts
CHANGED
|
@@ -6,17 +6,20 @@
|
|
|
6
6
|
* primary key does the deciding, and zero returned rows means "already seen".
|
|
7
7
|
*
|
|
8
8
|
* Reclaim runs only on the path that actually grew the table, and it deletes
|
|
9
|
-
* oldest-first down to `DEDUP_RING_CAPACITY` rows for that
|
|
10
|
-
* bound the in-memory ring holds. The ids most
|
|
11
|
-
* recent ones, so dropping the oldest is the
|
|
12
|
-
* behavior. An unbounded set would pass every
|
|
13
|
-
* one chatty device grow this table
|
|
9
|
+
* oldest-first down to `DEDUP_RING_CAPACITY` rows for that exact physical or
|
|
10
|
+
* Agent-bound key — the same bound the in-memory ring holds. The ids most
|
|
11
|
+
* likely to be redelivered are the recent ones, so dropping the oldest is the
|
|
12
|
+
* retention that matches the wire's behavior. An unbounded set would pass every
|
|
13
|
+
* duplicate assertion and still let one chatty device or Agent grow this table
|
|
14
|
+
* without limit.
|
|
14
15
|
*/
|
|
15
16
|
import { type InboundDedupStore } from '@byok-sdk/cloud';
|
|
16
17
|
import type { TenantId } from '@byok-sdk/core';
|
|
18
|
+
import type { AgentRef } from '@byok-sdk/protocol';
|
|
17
19
|
import type { Pool } from 'pg';
|
|
18
20
|
export declare class PostgresInboundDedupStore implements InboundDedupStore {
|
|
19
21
|
#private;
|
|
20
22
|
constructor(pool: Pool, capacity?: number);
|
|
21
23
|
checkAndRecord(tenant: TenantId, deviceId: string, envelopeId: string): Promise<boolean>;
|
|
24
|
+
checkAndRecordAgent(tenant: TenantId, deviceId: string, agentRef: AgentRef, envelopeId: string): Promise<boolean>;
|
|
22
25
|
}
|
|
@@ -14,8 +14,9 @@
|
|
|
14
14
|
* `claim` and `recordStatus` on a task this tenant never offered write nothing
|
|
15
15
|
* and return `undefined`.
|
|
16
16
|
*/
|
|
17
|
-
import { type AgentMessageAdmission, type AgentRef, type TaskAttempt, type TaskAttemptStatus, type TaskAttemptStore } from '@byok-sdk/cloud';
|
|
17
|
+
import { type AgentMessageAdmission, type AgentRef, type TaskAttempt, type TaskAttemptListQuery, type TaskAttemptPage, type TaskAttemptStatus, type TaskAttemptStore } from '@byok-sdk/cloud';
|
|
18
18
|
import type { Clock, TenantId } from '@byok-sdk/core';
|
|
19
|
+
import type { RuntimeCapabilities, RuntimeId } from '@byok-sdk/protocol';
|
|
19
20
|
import type { Pool } from 'pg';
|
|
20
21
|
export interface TaskRow {
|
|
21
22
|
readonly tenant_id: string;
|
|
@@ -29,9 +30,11 @@ export interface TaskRow {
|
|
|
29
30
|
readonly cancel_requested_at: Date | null;
|
|
30
31
|
readonly cancel_reason: string | null;
|
|
31
32
|
readonly cancel_message_id: string | null;
|
|
33
|
+
readonly claimed_runtime: string | null;
|
|
34
|
+
readonly claimed_runtime_capabilities: RuntimeCapabilities | null;
|
|
32
35
|
readonly updated_at: Date;
|
|
33
36
|
}
|
|
34
|
-
export declare const 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";
|
|
37
|
+
export declare const 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, claimed_runtime, claimed_runtime_capabilities, updated_at";
|
|
35
38
|
export declare function taskRowToAttempt(row: TaskRow): TaskAttempt;
|
|
36
39
|
export declare class PostgresTaskAttemptStore implements TaskAttemptStore {
|
|
37
40
|
#private;
|
|
@@ -70,9 +73,12 @@ export declare class PostgresTaskAttemptStore implements TaskAttemptStore {
|
|
|
70
73
|
}): Promise<AgentMessageAdmission | undefined>;
|
|
71
74
|
get(tenant: TenantId, taskId: string): Promise<TaskAttempt | undefined>;
|
|
72
75
|
getMany(tenant: TenantId, taskIds: readonly string[]): Promise<readonly TaskAttempt[]>;
|
|
76
|
+
list(tenant: TenantId, query: TaskAttemptListQuery): Promise<TaskAttemptPage>;
|
|
73
77
|
claim(tenant: TenantId, input: {
|
|
74
78
|
readonly taskId: string;
|
|
75
79
|
readonly deviceId: string;
|
|
80
|
+
readonly runtime?: RuntimeId;
|
|
81
|
+
readonly capabilities?: RuntimeCapabilities;
|
|
76
82
|
}): Promise<TaskAttempt | undefined>;
|
|
77
83
|
recordStatus(tenant: TenantId, input: {
|
|
78
84
|
readonly taskId: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@byok-sdk/cloud-dataplane",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"description": "BYOK SDK hosted data plane: canonical Postgres + R2 stores, migrations, truth transactions, and maintenance",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -49,9 +49,9 @@
|
|
|
49
49
|
"clean": "rm -rf dist"
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {
|
|
52
|
-
"@byok-sdk/cloud": "0.
|
|
53
|
-
"@byok-sdk/core": "0.
|
|
54
|
-
"@byok-sdk/protocol": "0.
|
|
52
|
+
"@byok-sdk/cloud": "0.13.0",
|
|
53
|
+
"@byok-sdk/core": "0.13.0",
|
|
54
|
+
"@byok-sdk/protocol": "0.13.0",
|
|
55
55
|
"aws4fetch": "1.0.20",
|
|
56
56
|
"fast-xml-parser": "^5.10.1",
|
|
57
57
|
"pg": "^8.22.0"
|