@creatornader/agent-bridge 0.3.1 → 0.5.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/CHANGELOG.md +222 -1
- package/README.md +312 -12
- package/ROADMAP.md +88 -7
- package/SECURITY.md +78 -5
- package/SKILL.md +108 -1
- package/dist/archive.d.ts +2 -2
- package/dist/archive.js +2 -2
- package/dist/{bridge-service-hX1ZQp4W.d.ts → bridge-service-CNBKdYXh.d.ts} +2 -1
- package/dist/{bridge-store-DPVSCwfs.d.ts → bridge-store-ByJ6CaJk.d.ts} +3 -0
- package/dist/bridge.d.ts +25 -8
- package/dist/bridge.js +19 -9
- package/dist/{chunk-MBPZXTJA.js → chunk-7VJI2MXI.js} +285 -42
- package/dist/chunk-7VJI2MXI.js.map +1 -0
- package/dist/{chunk-4VB44KJU.js → chunk-AWE3DFZV.js} +3 -2
- package/dist/chunk-AWE3DFZV.js.map +1 -0
- package/dist/{chunk-GADH244D.js → chunk-E4OWHGUE.js} +16 -5
- package/dist/chunk-E4OWHGUE.js.map +1 -0
- package/dist/{chunk-NCO7RLBM.js → chunk-GTK4KOED.js} +108 -8
- package/dist/chunk-GTK4KOED.js.map +1 -0
- package/dist/{chunk-SPSMZOCJ.js → chunk-HUHG7XTB.js} +6 -5
- package/dist/chunk-HUHG7XTB.js.map +1 -0
- package/dist/{chunk-5GMB3A77.js → chunk-IVG4XWWS.js} +26 -14
- package/dist/chunk-IVG4XWWS.js.map +1 -0
- package/dist/{chunk-WAI2IYIQ.js → chunk-P635FAN4.js} +50 -7
- package/dist/chunk-P635FAN4.js.map +1 -0
- package/dist/{chunk-45BZGB77.js → chunk-QNXHDOJ5.js} +218 -24
- package/dist/chunk-QNXHDOJ5.js.map +1 -0
- package/dist/{chunk-UAHMP6GC.js → chunk-QPC6JHA3.js} +10 -7
- package/dist/chunk-QPC6JHA3.js.map +1 -0
- package/dist/{chunk-Q6PPMXJC.js → chunk-SN7PIVDF.js} +377 -21
- package/dist/chunk-SN7PIVDF.js.map +1 -0
- package/dist/{chunk-A6W4QALF.js → chunk-TC6A7GMF.js} +2 -2
- package/dist/{chunk-2DFNOLMO.js → chunk-XDNT6ZNZ.js} +9 -6
- package/dist/chunk-XDNT6ZNZ.js.map +1 -0
- package/dist/{chunk-CEXBMOI5.js → chunk-Z6JP6MYD.js} +2 -2
- package/dist/cli.js +5867 -438
- package/dist/cli.js.map +1 -1
- package/dist/client-runtime.d.ts +4 -2
- package/dist/client-runtime.js +7 -7
- package/dist/contracts/generate.js +1 -1
- package/dist/dr.d.ts +9 -2
- package/dist/dr.js +6 -4
- package/dist/{gateway-CggQ8vTC.d.ts → gateway-CW-61lvs.d.ts} +27 -3
- package/dist/gateway-main.js +71 -7
- package/dist/gateway-main.js.map +1 -1
- package/dist/gateway.d.ts +3 -3
- package/dist/gateway.js +3 -3
- package/dist/index.js +8 -8
- package/dist/{postgres-bridge-store-Bfd3hRId.d.ts → postgres-bridge-store-C9KG9Z69.d.ts} +1 -1
- package/dist/postgres-production-preflight.d.ts +32 -0
- package/dist/postgres-production-preflight.js +249 -0
- package/dist/postgres-production-preflight.js.map +1 -0
- package/dist/server.js +8 -8
- package/dist/sqlite-edge-store-CdMIOrho.d.ts +148 -0
- package/dist/sqlite.d.ts +19 -80
- package/dist/sqlite.js +11 -3
- package/docs/architecture-v2.md +292 -15
- package/docs/decisions/0004-client-lifecycle-and-endpoint-migration.md +204 -0
- package/docs/deployment.md +349 -0
- package/docs/troubleshooting.md +23 -0
- package/llms.txt +69 -1
- package/openapi/agent-bridge-v2.openapi.json +1151 -124
- package/package.json +10 -2
- package/schemas/agent-bridge-v2.capabilities.json +26 -1
- package/schemas/agent-bridge-v2.mcp.json +11 -1
- package/schemas/agent-bridge-v2.schema.json +167 -0
- package/sql/migrations/007_runtime_role.sql +8 -4
- package/sql/migrations/013_row_isolation.sql +71 -8
- package/sql/migrations/014_owner_control_plane.sql +124 -31
- package/sql/migrations/015_portable_archives.sql +143 -41
- package/sql/migrations/016_native_dr_fence.sql +102 -35
- package/sql/migrations/017_gateway_authority_binding.sql +99 -0
- package/sql/migrations/018_endpoint_migration_challenges.sql +1054 -0
- package/sql/migrations/019_endpoint_migration_same_successor.sql +348 -0
- package/sql/migrations/020_managed_authority_compat.sql +698 -0
- package/sql/migrations/021_native_backup_reader.sql +421 -0
- package/sql/setup.sql +1 -3
- package/dist/chunk-2DFNOLMO.js.map +0 -1
- package/dist/chunk-45BZGB77.js.map +0 -1
- package/dist/chunk-4VB44KJU.js.map +0 -1
- package/dist/chunk-5GMB3A77.js.map +0 -1
- package/dist/chunk-GADH244D.js.map +0 -1
- package/dist/chunk-MBPZXTJA.js.map +0 -1
- package/dist/chunk-NCO7RLBM.js.map +0 -1
- package/dist/chunk-Q6PPMXJC.js.map +0 -1
- package/dist/chunk-SPSMZOCJ.js.map +0 -1
- package/dist/chunk-UAHMP6GC.js.map +0 -1
- package/dist/chunk-WAI2IYIQ.js.map +0 -1
- /package/dist/{chunk-A6W4QALF.js.map → chunk-TC6A7GMF.js.map} +0 -0
- /package/dist/{chunk-CEXBMOI5.js.map → chunk-Z6JP6MYD.js.map} +0 -0
|
@@ -0,0 +1,421 @@
|
|
|
1
|
+
begin;
|
|
2
|
+
|
|
3
|
+
select pg_advisory_xact_lock(1646705660);
|
|
4
|
+
|
|
5
|
+
do $preflight$
|
|
6
|
+
begin
|
|
7
|
+
if not agent_bridge.security_schema_ready() then
|
|
8
|
+
raise exception 'native backup reader security readiness validation failed';
|
|
9
|
+
elsif not agent_bridge.owner_control_plane_ready() then
|
|
10
|
+
raise exception 'native backup reader owner readiness validation failed';
|
|
11
|
+
elsif not agent_bridge.gateway_authority_ready() then
|
|
12
|
+
raise exception 'native backup reader gateway readiness validation failed';
|
|
13
|
+
elsif not agent_bridge.endpoint_migration_challenge_ready() then
|
|
14
|
+
raise exception 'native backup reader endpoint readiness validation failed';
|
|
15
|
+
elsif not agent_bridge.portable_archive_ready() then
|
|
16
|
+
raise exception 'native backup reader archive readiness validation failed';
|
|
17
|
+
elsif not exists(select 1 from agent_bridge.row_isolation_attestations attestation
|
|
18
|
+
where attestation.name='domain-v1'
|
|
19
|
+
and attestation.catalog_definition=agent_bridge.row_isolation_catalog_definition()) then
|
|
20
|
+
raise exception 'native backup reader row-isolation attestation validation failed';
|
|
21
|
+
elsif (select nspowner<>current_user::regrole::oid from pg_catalog.pg_namespace
|
|
22
|
+
where nspname='agent_bridge') then
|
|
23
|
+
raise exception 'native backup reader migration authority must own the Agent Bridge schema';
|
|
24
|
+
end if;
|
|
25
|
+
end
|
|
26
|
+
$preflight$;
|
|
27
|
+
|
|
28
|
+
do $role$
|
|
29
|
+
declare
|
|
30
|
+
backup_role text := 'agent_bridge_backup_reader_'||substr(md5(current_database()),1,16);
|
|
31
|
+
begin
|
|
32
|
+
if exists(select 1 from pg_catalog.pg_roles where rolname=backup_role) then
|
|
33
|
+
raise exception 'reserved Agent Bridge native backup role already exists';
|
|
34
|
+
end if;
|
|
35
|
+
execute format(
|
|
36
|
+
'create role %I nologin inherit nosuperuser nocreatedb nocreaterole noreplication nobypassrls',
|
|
37
|
+
backup_role
|
|
38
|
+
);
|
|
39
|
+
if current_setting('server_version_num')::integer>=160000 and not exists(
|
|
40
|
+
select 1 from pg_catalog.pg_auth_members membership
|
|
41
|
+
join pg_catalog.pg_roles granted on granted.oid=membership.roleid
|
|
42
|
+
join pg_catalog.pg_roles member on member.oid=membership.member
|
|
43
|
+
where granted.rolname=backup_role and member.rolname=current_user
|
|
44
|
+
and membership.admin_option
|
|
45
|
+
) then
|
|
46
|
+
execute format(
|
|
47
|
+
'grant %I to %I with admin true,inherit true,set true',backup_role,current_user
|
|
48
|
+
);
|
|
49
|
+
elsif current_setting('server_version_num')::integer>=160000 and not exists(
|
|
50
|
+
select 1 from pg_catalog.pg_auth_members membership
|
|
51
|
+
join pg_catalog.pg_roles granted on granted.oid=membership.roleid
|
|
52
|
+
join pg_catalog.pg_roles member on member.oid=membership.member
|
|
53
|
+
where granted.rolname=backup_role and member.rolname=current_user
|
|
54
|
+
and coalesce((to_jsonb(membership)->>'inherit_option')::boolean,true)
|
|
55
|
+
and coalesce((to_jsonb(membership)->>'set_option')::boolean,true)
|
|
56
|
+
) then
|
|
57
|
+
execute format(
|
|
58
|
+
'grant %I to %I with admin false,inherit true,set true',backup_role,current_user
|
|
59
|
+
);
|
|
60
|
+
else
|
|
61
|
+
if current_setting('server_version_num')::integer<160000 then
|
|
62
|
+
execute format('grant %I to %I with admin option',backup_role,current_user);
|
|
63
|
+
end if;
|
|
64
|
+
end if;
|
|
65
|
+
end
|
|
66
|
+
$role$;
|
|
67
|
+
|
|
68
|
+
create table agent_bridge.native_backup_attestations (
|
|
69
|
+
name text primary key,
|
|
70
|
+
catalog_definition text not null,
|
|
71
|
+
attested_at timestamptz not null default now(),
|
|
72
|
+
constraint native_backup_attestation_name check(name='native-backup-v1')
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
create function agent_bridge.reject_native_backup_attestation_mutation()
|
|
76
|
+
returns trigger language plpgsql set search_path = '' as $$
|
|
77
|
+
begin
|
|
78
|
+
raise exception 'native backup attestations are append-only';
|
|
79
|
+
end
|
|
80
|
+
$$;
|
|
81
|
+
|
|
82
|
+
create trigger native_backup_attestations_append_only
|
|
83
|
+
before update or delete on agent_bridge.native_backup_attestations
|
|
84
|
+
for each row execute function agent_bridge.reject_native_backup_attestation_mutation();
|
|
85
|
+
|
|
86
|
+
create trigger native_backup_attestations_no_truncate
|
|
87
|
+
before truncate on agent_bridge.native_backup_attestations
|
|
88
|
+
for each statement execute function agent_bridge.reject_native_backup_attestation_mutation();
|
|
89
|
+
|
|
90
|
+
do $grants$
|
|
91
|
+
declare
|
|
92
|
+
backup_role text := 'agent_bridge_backup_reader_'||substr(md5(current_database()),1,16);
|
|
93
|
+
begin
|
|
94
|
+
execute format('revoke all on schema agent_bridge from %I',backup_role);
|
|
95
|
+
execute format('revoke all on all tables in schema agent_bridge from %I',backup_role);
|
|
96
|
+
execute format('revoke all on all sequences in schema agent_bridge from %I',backup_role);
|
|
97
|
+
execute format('revoke execute on all functions in schema agent_bridge from %I',backup_role);
|
|
98
|
+
execute format('grant usage on schema agent_bridge to %I',backup_role);
|
|
99
|
+
execute format('grant select on all tables in schema agent_bridge to %I',backup_role);
|
|
100
|
+
execute format('grant select on all sequences in schema agent_bridge to %I',backup_role);
|
|
101
|
+
end
|
|
102
|
+
$grants$;
|
|
103
|
+
|
|
104
|
+
create function agent_bridge.native_backup_catalog_definition()
|
|
105
|
+
returns text language sql stable set search_path = '' as $$
|
|
106
|
+
with names as (select
|
|
107
|
+
('agent_bridge_backup_reader_'||substr(md5(current_database()),1,16))::name backup_role,
|
|
108
|
+
(select nspowner from pg_catalog.pg_namespace where nspname='agent_bridge') schema_owner
|
|
109
|
+
), catalog_objects(kind,identity,definition) as (
|
|
110
|
+
select 'role',role.rolname,
|
|
111
|
+
role.rolcanlogin::text||':'||role.rolinherit::text||':'||role.rolsuper::text||':'||
|
|
112
|
+
role.rolcreatedb::text||':'||role.rolcreaterole::text||':'||
|
|
113
|
+
role.rolreplication::text||':'||role.rolbypassrls::text||':'||role.rolconnlimit::text
|
|
114
|
+
from pg_catalog.pg_roles role where role.rolname=(select backup_role from names)
|
|
115
|
+
union all
|
|
116
|
+
select 'membership',granted.rolname||'->'||member.rolname,
|
|
117
|
+
bool_or(membership.admin_option)::text||':'||
|
|
118
|
+
bool_or(coalesce((to_jsonb(membership)->>'inherit_option')::boolean,true))::text||':'||
|
|
119
|
+
bool_or(coalesce((to_jsonb(membership)->>'set_option')::boolean,true))::text
|
|
120
|
+
from pg_catalog.pg_auth_members membership
|
|
121
|
+
join pg_catalog.pg_roles granted on granted.oid=membership.roleid
|
|
122
|
+
join pg_catalog.pg_roles member on member.oid=membership.member
|
|
123
|
+
where membership.roleid=(select oid from pg_catalog.pg_roles
|
|
124
|
+
where rolname=(select backup_role from names))
|
|
125
|
+
or membership.member=(select oid from pg_catalog.pg_roles
|
|
126
|
+
where rolname=(select backup_role from names))
|
|
127
|
+
group by granted.rolname,member.rolname
|
|
128
|
+
union all
|
|
129
|
+
select 'schema_acl','agent_bridge',
|
|
130
|
+
pg_catalog.pg_get_userbyid(privilege.grantor)||':'||
|
|
131
|
+
privilege.privilege_type||':'||privilege.is_grantable::text
|
|
132
|
+
from pg_catalog.pg_namespace namespace
|
|
133
|
+
cross join lateral pg_catalog.aclexplode(coalesce(namespace.nspacl,
|
|
134
|
+
pg_catalog.acldefault('n',namespace.nspowner))) privilege
|
|
135
|
+
where namespace.nspname='agent_bridge'
|
|
136
|
+
and privilege.grantee=(select oid from pg_catalog.pg_roles
|
|
137
|
+
where rolname=(select backup_role from names))
|
|
138
|
+
union all
|
|
139
|
+
select 'relation',relation.oid::regclass::text,
|
|
140
|
+
relation.relkind::text||':'||pg_catalog.pg_get_userbyid(relation.relowner)||':'||
|
|
141
|
+
coalesce(string_agg(privilege.privilege_type||':'||privilege.is_grantable::text,','
|
|
142
|
+
order by privilege.privilege_type),'missing')
|
|
143
|
+
from pg_catalog.pg_class relation
|
|
144
|
+
join pg_catalog.pg_namespace namespace on namespace.oid=relation.relnamespace
|
|
145
|
+
left join lateral pg_catalog.aclexplode(coalesce(relation.relacl,
|
|
146
|
+
pg_catalog.acldefault(case when relation.relkind='S' then 'S'::"char" else 'r'::"char" end,
|
|
147
|
+
relation.relowner))) privilege on privilege.grantee=(select oid from pg_catalog.pg_roles
|
|
148
|
+
where rolname=(select backup_role from names))
|
|
149
|
+
where namespace.nspname='agent_bridge' and relation.relkind in ('r','p','v','m','f','S')
|
|
150
|
+
group by relation.oid,relation.relkind,relation.relowner
|
|
151
|
+
union all
|
|
152
|
+
select 'function',procedure.oid::regprocedure::text,
|
|
153
|
+
pg_catalog.pg_get_userbyid(procedure.proowner)||':'||procedure.prosecdef::text||':'||
|
|
154
|
+
procedure.provolatile::text||':'||coalesce(array_to_string(procedure.proconfig,','),'')||':'||
|
|
155
|
+
pg_catalog.pg_get_functiondef(procedure.oid)
|
|
156
|
+
from pg_catalog.pg_proc procedure
|
|
157
|
+
join pg_catalog.pg_namespace namespace on namespace.oid=procedure.pronamespace
|
|
158
|
+
where namespace.nspname='agent_bridge' and procedure.proname in (
|
|
159
|
+
'reject_native_backup_attestation_mutation','native_backup_catalog_definition',
|
|
160
|
+
'native_backup_ready'
|
|
161
|
+
)
|
|
162
|
+
union all
|
|
163
|
+
select 'trigger',trigger.tgrelid::regclass::text||'.'||trigger.tgname,
|
|
164
|
+
trigger.tgenabled::text||':'||pg_catalog.pg_get_triggerdef(trigger.oid,true)
|
|
165
|
+
from pg_catalog.pg_trigger trigger
|
|
166
|
+
where trigger.tgrelid='agent_bridge.native_backup_attestations'::regclass
|
|
167
|
+
and not trigger.tgisinternal
|
|
168
|
+
)
|
|
169
|
+
select string_agg(kind||E'\x1f'||identity||E'\x1f'||definition,E'\x1e'
|
|
170
|
+
order by kind,identity,definition) from catalog_objects
|
|
171
|
+
$$;
|
|
172
|
+
|
|
173
|
+
create function agent_bridge.native_backup_ready()
|
|
174
|
+
returns boolean language sql stable security definer set search_path = '' as $$
|
|
175
|
+
with names as (select
|
|
176
|
+
('agent_bridge_backup_reader_'||substr(md5(current_database()),1,16))::name backup_role,
|
|
177
|
+
('agent_bridge_runtime_'||substr(md5(current_database()),1,16))::name runtime_role,
|
|
178
|
+
(select nspowner from pg_catalog.pg_namespace where nspname='agent_bridge') schema_owner
|
|
179
|
+
), semantic_membership as (
|
|
180
|
+
select count(distinct member.oid)=1
|
|
181
|
+
and bool_and(member.oid=(select schema_owner from names))
|
|
182
|
+
and bool_or(membership.admin_option)
|
|
183
|
+
and bool_or(coalesce((to_jsonb(membership)->>'inherit_option')::boolean,true))
|
|
184
|
+
and bool_or(coalesce((to_jsonb(membership)->>'set_option')::boolean,true)) ready
|
|
185
|
+
from pg_catalog.pg_auth_members membership
|
|
186
|
+
join pg_catalog.pg_roles granted on granted.oid=membership.roleid
|
|
187
|
+
join pg_catalog.pg_roles member on member.oid=membership.member
|
|
188
|
+
where granted.rolname=(select backup_role from names)
|
|
189
|
+
), raw_membership as (
|
|
190
|
+
select count(*)::integer row_count,
|
|
191
|
+
count(*) filter(where membership.grantor=10 and membership.admin_option
|
|
192
|
+
and not coalesce((to_jsonb(membership)->>'inherit_option')::boolean,true)
|
|
193
|
+
and not coalesce((to_jsonb(membership)->>'set_option')::boolean,true)) bootstrap_admin,
|
|
194
|
+
count(*) filter(where membership.grantor=member.oid and not membership.admin_option
|
|
195
|
+
and coalesce((to_jsonb(membership)->>'inherit_option')::boolean,true)
|
|
196
|
+
and coalesce((to_jsonb(membership)->>'set_option')::boolean,true)) self_inherit,
|
|
197
|
+
count(*) filter(where membership.admin_option
|
|
198
|
+
and coalesce((to_jsonb(membership)->>'inherit_option')::boolean,true)
|
|
199
|
+
and coalesce((to_jsonb(membership)->>'set_option')::boolean,true)
|
|
200
|
+
and membership.grantor in (10,member.oid)) combined
|
|
201
|
+
from pg_catalog.pg_auth_members membership
|
|
202
|
+
join pg_catalog.pg_roles granted on granted.oid=membership.roleid
|
|
203
|
+
join pg_catalog.pg_roles member on member.oid=membership.member
|
|
204
|
+
where granted.rolname=(select backup_role from names)
|
|
205
|
+
and member.oid=(select schema_owner from names)
|
|
206
|
+
)
|
|
207
|
+
select
|
|
208
|
+
exists(select 1 from pg_catalog.pg_roles role,names where role.rolname=names.backup_role
|
|
209
|
+
and not role.rolcanlogin and role.rolinherit and not role.rolsuper
|
|
210
|
+
and not role.rolcreatedb and not role.rolcreaterole and not role.rolreplication
|
|
211
|
+
and not role.rolbypassrls and role.rolconnlimit=-1)
|
|
212
|
+
and exists(select 1 from pg_catalog.pg_roles role,names
|
|
213
|
+
where (role.oid=names.schema_owner and (role.rolsuper or role.rolbypassrls))
|
|
214
|
+
or (role.rolname=session_user and role.rolsuper))
|
|
215
|
+
and (select ready from semantic_membership)
|
|
216
|
+
and (select case when current_setting('server_version_num')::integer<160000
|
|
217
|
+
then row_count=1 and combined=1
|
|
218
|
+
else (row_count=1 and combined=1)
|
|
219
|
+
or (row_count=2 and bootstrap_admin=1 and self_inherit=1)
|
|
220
|
+
end from raw_membership)
|
|
221
|
+
and not exists(
|
|
222
|
+
select 1 from pg_catalog.pg_auth_members membership
|
|
223
|
+
join pg_catalog.pg_roles member on member.oid=membership.member
|
|
224
|
+
cross join names
|
|
225
|
+
where membership.roleid=(select oid from pg_catalog.pg_roles
|
|
226
|
+
where rolname=names.backup_role) and (
|
|
227
|
+
member.oid<>names.schema_owner or not (
|
|
228
|
+
(membership.grantor=10 and membership.admin_option
|
|
229
|
+
and coalesce((to_jsonb(membership)->>'inherit_option')::boolean,true)
|
|
230
|
+
=coalesce((to_jsonb(membership)->>'set_option')::boolean,true))
|
|
231
|
+
or (membership.grantor=member.oid
|
|
232
|
+
and coalesce((to_jsonb(membership)->>'inherit_option')::boolean,true)
|
|
233
|
+
and coalesce((to_jsonb(membership)->>'set_option')::boolean,true))
|
|
234
|
+
)
|
|
235
|
+
)
|
|
236
|
+
)
|
|
237
|
+
and not exists(
|
|
238
|
+
select 1 from pg_catalog.pg_auth_members membership
|
|
239
|
+
cross join names
|
|
240
|
+
where membership.member=(select oid from pg_catalog.pg_roles
|
|
241
|
+
where rolname=names.backup_role)
|
|
242
|
+
)
|
|
243
|
+
and has_schema_privilege((select backup_role from names),'agent_bridge','USAGE')
|
|
244
|
+
and not has_schema_privilege((select backup_role from names),'agent_bridge','CREATE')
|
|
245
|
+
and not exists(
|
|
246
|
+
select 1 from pg_catalog.pg_namespace namespace,names
|
|
247
|
+
cross join lateral pg_catalog.aclexplode(coalesce(namespace.nspacl,
|
|
248
|
+
pg_catalog.acldefault('n',namespace.nspowner))) privilege
|
|
249
|
+
where namespace.nspname='agent_bridge'
|
|
250
|
+
and privilege.grantee=(select oid from pg_catalog.pg_roles where rolname=names.backup_role)
|
|
251
|
+
and (privilege.privilege_type<>'USAGE' or privilege.is_grantable)
|
|
252
|
+
)
|
|
253
|
+
and not exists(
|
|
254
|
+
select 1 from pg_catalog.pg_class relation
|
|
255
|
+
join pg_catalog.pg_namespace namespace on namespace.oid=relation.relnamespace,names
|
|
256
|
+
where namespace.nspname='agent_bridge' and relation.relkind in ('r','p','v','m','f','S')
|
|
257
|
+
and not case when relation.relkind='S'
|
|
258
|
+
then has_sequence_privilege(names.backup_role,relation.oid,'SELECT')
|
|
259
|
+
and not has_sequence_privilege(names.backup_role,relation.oid,'USAGE,UPDATE')
|
|
260
|
+
else has_table_privilege(names.backup_role,relation.oid,'SELECT')
|
|
261
|
+
and not has_table_privilege(names.backup_role,relation.oid,
|
|
262
|
+
'INSERT,UPDATE,DELETE,TRUNCATE,REFERENCES,TRIGGER')
|
|
263
|
+
end
|
|
264
|
+
)
|
|
265
|
+
and not exists(
|
|
266
|
+
select 1 from pg_catalog.pg_class relation
|
|
267
|
+
join pg_catalog.pg_namespace namespace on namespace.oid=relation.relnamespace,names
|
|
268
|
+
cross join lateral pg_catalog.aclexplode(coalesce(relation.relacl,
|
|
269
|
+
pg_catalog.acldefault(case when relation.relkind='S' then 'S'::"char" else 'r'::"char" end,
|
|
270
|
+
relation.relowner))) privilege
|
|
271
|
+
where namespace.nspname='agent_bridge' and relation.relkind in ('r','p','v','m','f','S')
|
|
272
|
+
and privilege.grantee=(select oid from pg_catalog.pg_roles where rolname=names.backup_role)
|
|
273
|
+
and (privilege.privilege_type<>'SELECT' or privilege.is_grantable)
|
|
274
|
+
)
|
|
275
|
+
and not exists(
|
|
276
|
+
select 1 from pg_catalog.pg_attribute attribute
|
|
277
|
+
join pg_catalog.pg_class relation on relation.oid=attribute.attrelid
|
|
278
|
+
join pg_catalog.pg_namespace namespace on namespace.oid=relation.relnamespace,names
|
|
279
|
+
cross join lateral pg_catalog.aclexplode(attribute.attacl) privilege
|
|
280
|
+
where namespace.nspname='agent_bridge' and attribute.attnum>0 and not attribute.attisdropped
|
|
281
|
+
and privilege.grantee=(select oid from pg_catalog.pg_roles where rolname=names.backup_role)
|
|
282
|
+
)
|
|
283
|
+
and not exists(
|
|
284
|
+
select 1 from pg_catalog.pg_proc procedure
|
|
285
|
+
join pg_catalog.pg_namespace namespace on namespace.oid=procedure.pronamespace,names
|
|
286
|
+
where namespace.nspname='agent_bridge'
|
|
287
|
+
and has_function_privilege(names.backup_role,procedure.oid,'EXECUTE')
|
|
288
|
+
)
|
|
289
|
+
and (select count(*)=3 and bool_and(
|
|
290
|
+
procedure.proowner=(select schema_owner from names)
|
|
291
|
+
and procedure.proconfig @> array['search_path=""']::text[]
|
|
292
|
+
and case procedure.proname when 'native_backup_ready' then procedure.prosecdef
|
|
293
|
+
else not procedure.prosecdef end
|
|
294
|
+
and case procedure.proname when 'reject_native_backup_attestation_mutation'
|
|
295
|
+
then procedure.provolatile='v' else procedure.provolatile='s' end
|
|
296
|
+
) from pg_catalog.pg_proc procedure
|
|
297
|
+
join pg_catalog.pg_namespace namespace on namespace.oid=procedure.pronamespace
|
|
298
|
+
where namespace.nspname='agent_bridge' and procedure.proname in (
|
|
299
|
+
'reject_native_backup_attestation_mutation','native_backup_catalog_definition',
|
|
300
|
+
'native_backup_ready'))
|
|
301
|
+
and has_function_privilege((select runtime_role from names),
|
|
302
|
+
'agent_bridge.native_backup_ready()','EXECUTE')
|
|
303
|
+
and not has_function_privilege('public','agent_bridge.native_backup_ready()','EXECUTE')
|
|
304
|
+
and not has_function_privilege((select backup_role from names),
|
|
305
|
+
'agent_bridge.native_backup_ready()','EXECUTE')
|
|
306
|
+
and not exists(select 1 from pg_catalog.pg_proc procedure,names
|
|
307
|
+
where procedure.oid in (
|
|
308
|
+
'agent_bridge.reject_native_backup_attestation_mutation()'::regprocedure,
|
|
309
|
+
'agent_bridge.native_backup_catalog_definition()'::regprocedure
|
|
310
|
+
) and (has_function_privilege(names.runtime_role,procedure.oid,'EXECUTE')
|
|
311
|
+
or has_function_privilege('public',procedure.oid,'EXECUTE')
|
|
312
|
+
or has_function_privilege(names.backup_role,procedure.oid,'EXECUTE')))
|
|
313
|
+
and (select count(*)=2 and bool_and(trigger.tgenabled='O')
|
|
314
|
+
from pg_catalog.pg_trigger trigger
|
|
315
|
+
where trigger.tgrelid='agent_bridge.native_backup_attestations'::regclass
|
|
316
|
+
and trigger.tgname in ('native_backup_attestations_append_only',
|
|
317
|
+
'native_backup_attestations_no_truncate') and not trigger.tgisinternal)
|
|
318
|
+
and (select count(*)=1 and bool_and(
|
|
319
|
+
attestation.catalog_definition=agent_bridge.native_backup_catalog_definition())
|
|
320
|
+
from agent_bridge.native_backup_attestations attestation
|
|
321
|
+
where attestation.name='native-backup-v1')
|
|
322
|
+
$$;
|
|
323
|
+
|
|
324
|
+
revoke all on function agent_bridge.reject_native_backup_attestation_mutation() from public;
|
|
325
|
+
revoke all on function agent_bridge.native_backup_catalog_definition() from public;
|
|
326
|
+
revoke all on function agent_bridge.native_backup_ready() from public;
|
|
327
|
+
|
|
328
|
+
do $function_grants$
|
|
329
|
+
declare
|
|
330
|
+
runtime_role text := 'agent_bridge_runtime_'||substr(md5(current_database()),1,16);
|
|
331
|
+
backup_role text := 'agent_bridge_backup_reader_'||substr(md5(current_database()),1,16);
|
|
332
|
+
begin
|
|
333
|
+
execute format('revoke execute on function agent_bridge.reject_native_backup_attestation_mutation() from %I,%I',runtime_role,backup_role);
|
|
334
|
+
execute format('revoke execute on function agent_bridge.native_backup_catalog_definition() from %I,%I',runtime_role,backup_role);
|
|
335
|
+
execute format('revoke execute on function agent_bridge.native_backup_ready() from %I',backup_role);
|
|
336
|
+
execute format('grant execute on function agent_bridge.native_backup_ready() to %I',runtime_role);
|
|
337
|
+
end
|
|
338
|
+
$function_grants$;
|
|
339
|
+
|
|
340
|
+
do $readiness_versions$
|
|
341
|
+
declare
|
|
342
|
+
owner_definition text;
|
|
343
|
+
archive_definition text;
|
|
344
|
+
endpoint_definition text;
|
|
345
|
+
begin
|
|
346
|
+
select pg_catalog.pg_get_functiondef(
|
|
347
|
+
'agent_bridge.owner_control_plane_ready()'::regprocedure
|
|
348
|
+
) into owner_definition;
|
|
349
|
+
if owner_definition not like '%owner-control-v7%' then
|
|
350
|
+
raise exception 'owner readiness contract is not the migration 020 definition';
|
|
351
|
+
end if;
|
|
352
|
+
execute replace(owner_definition,'owner-control-v7','owner-control-v8');
|
|
353
|
+
|
|
354
|
+
select pg_catalog.pg_get_functiondef(
|
|
355
|
+
'agent_bridge.portable_archive_ready()'::regprocedure
|
|
356
|
+
) into archive_definition;
|
|
357
|
+
if archive_definition not like '%portable-archive-v4%' then
|
|
358
|
+
raise exception 'archive readiness contract is not the migration 020 definition';
|
|
359
|
+
end if;
|
|
360
|
+
execute replace(archive_definition,'portable-archive-v4','portable-archive-v5');
|
|
361
|
+
|
|
362
|
+
select pg_catalog.pg_get_functiondef(
|
|
363
|
+
'agent_bridge.endpoint_migration_challenge_ready()'::regprocedure
|
|
364
|
+
) into endpoint_definition;
|
|
365
|
+
if endpoint_definition not like '%endpoint-migration-v2%' then
|
|
366
|
+
raise exception 'endpoint readiness contract is not the migration 019 definition';
|
|
367
|
+
end if;
|
|
368
|
+
execute replace(endpoint_definition,'endpoint-migration-v2','endpoint-migration-v3');
|
|
369
|
+
end
|
|
370
|
+
$readiness_versions$;
|
|
371
|
+
|
|
372
|
+
alter table agent_bridge.endpoint_migration_challenge_attestations
|
|
373
|
+
drop constraint endpoint_migration_challenge_attestation_name;
|
|
374
|
+
alter table agent_bridge.endpoint_migration_challenge_attestations
|
|
375
|
+
add constraint endpoint_migration_challenge_attestation_name
|
|
376
|
+
check(name in ('endpoint-migration-v1','endpoint-migration-v2','endpoint-migration-v3'));
|
|
377
|
+
|
|
378
|
+
select set_config(
|
|
379
|
+
'role','agent_bridge_control_owner_'||substr(md5(current_database()),1,16),false
|
|
380
|
+
);
|
|
381
|
+
insert into agent_bridge.owner_control_attestations(name,catalog_definition)
|
|
382
|
+
values('owner-control-v8',agent_bridge.owner_control_attestation_definition());
|
|
383
|
+
reset role;
|
|
384
|
+
|
|
385
|
+
insert into agent_bridge.portable_archive_attestations(name,catalog_definition)
|
|
386
|
+
values('portable-archive-v5',agent_bridge.portable_archive_attestation_definition());
|
|
387
|
+
|
|
388
|
+
insert into agent_bridge.endpoint_migration_challenge_attestations(name,catalog_definition)
|
|
389
|
+
values('endpoint-migration-v3',agent_bridge.endpoint_migration_challenge_catalog_definition());
|
|
390
|
+
|
|
391
|
+
insert into agent_bridge.native_backup_attestations(name,catalog_definition)
|
|
392
|
+
values('native-backup-v1',agent_bridge.native_backup_catalog_definition());
|
|
393
|
+
|
|
394
|
+
do $final_readiness$
|
|
395
|
+
begin
|
|
396
|
+
if not agent_bridge.security_schema_ready() then
|
|
397
|
+
raise exception 'native backup reader final security readiness validation failed';
|
|
398
|
+
elsif not agent_bridge.owner_control_plane_ready() then
|
|
399
|
+
raise exception 'native backup reader final owner readiness validation failed';
|
|
400
|
+
elsif not agent_bridge.gateway_authority_ready() then
|
|
401
|
+
raise exception 'native backup reader final gateway readiness validation failed';
|
|
402
|
+
elsif not agent_bridge.endpoint_migration_challenge_ready() then
|
|
403
|
+
raise exception 'native backup reader final endpoint readiness validation failed';
|
|
404
|
+
elsif not agent_bridge.portable_archive_ready() then
|
|
405
|
+
raise exception 'native backup reader final archive readiness validation failed';
|
|
406
|
+
elsif not exists(select 1 from agent_bridge.row_isolation_attestations attestation
|
|
407
|
+
where attestation.name='domain-v1'
|
|
408
|
+
and attestation.catalog_definition=agent_bridge.row_isolation_catalog_definition()) then
|
|
409
|
+
raise exception 'native backup reader final row-isolation attestation validation failed';
|
|
410
|
+
elsif not agent_bridge.native_backup_ready() then
|
|
411
|
+
raise exception 'native backup reader final readiness validation failed';
|
|
412
|
+
end if;
|
|
413
|
+
exception when others then
|
|
414
|
+
raise exception 'native backup reader final validation failed: %',sqlerrm;
|
|
415
|
+
end
|
|
416
|
+
$final_readiness$;
|
|
417
|
+
|
|
418
|
+
insert into agent_bridge.schema_migrations(version,name,checksum)
|
|
419
|
+
values(21,'native_backup_reader','__AGENT_BRIDGE_MIGRATION_CHECKSUM__');
|
|
420
|
+
|
|
421
|
+
commit;
|
package/sql/setup.sql
CHANGED
|
@@ -63,6 +63,4 @@ end;
|
|
|
63
63
|
$$;
|
|
64
64
|
|
|
65
65
|
comment on column shared_context.atrib_receipt_id is
|
|
66
|
-
'Optional signed atrib record receipt_id (record_hash "." creator_key, base64url) '
|
|
67
|
-
'emitted by an atrib-signing wrapper at insert time. ' ||
|
|
68
|
-
'Consumers use this as the informed_by anchor for cross-process causal edges.';
|
|
66
|
+
'Optional signed atrib record receipt_id (record_hash "." creator_key, base64url) emitted by an atrib-signing wrapper at insert time. Consumers use this as the informed_by anchor for cross-process causal edges.';
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/postgres-bridge-store.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport {\n DeliveryStateConflictError,\n decodeCursor,\n decodeScopedCursor,\n encodeCursor,\n encodeScopedCursor,\n cursorScope,\n scopedCursorScope,\n validateDeliveryCursorPosition,\n validateEventCursorPosition,\n type AgentPresence,\n type BridgeDelivery,\n type BridgeDeliveryEvent,\n type BridgeMessage,\n type BridgePrincipal,\n type DeliveryPolicy,\n} from \"./bridge-domain.js\";\nimport type {\n BridgeStore,\n BridgeDiagnostics,\n ClaimOptions,\n InsertMessageResult,\n MessagePage,\n MessageQuery,\n DeliveryQuery,\n} from \"./bridge-store.js\";\nimport { assertIdempotentReplay } from \"./idempotency.js\";\n\nexport interface PgQueryable {\n query<T extends Record<string, unknown> = Record<string, unknown>>(\n sql: string,\n values?: unknown[],\n ): Promise<{ rows: T[]; rowCount: number | null }>;\n connect?(): Promise<PgTransactionClient>;\n release?(): void;\n /** True when the queryable is already owned by an explicit request transaction. */\n inTransaction?: boolean;\n}\nexport interface PgTransactionClient {\n query<T extends Record<string, unknown> = Record<string, unknown>>(\n sql: string,\n values?: unknown[],\n ): Promise<{ rows: T[]; rowCount: number | null }>;\n release(error?: Error | boolean): void;\n}\n\ntype Row = Record<string, any>;\n\nfunction json(value: unknown): string | null {\n return value === undefined ? null : JSON.stringify(value);\n}\n\nfunction parse(value: unknown): any {\n return typeof value === \"string\" ? JSON.parse(value) : value;\n}\n\nfunction asTimestamp(value: unknown): string | undefined {\n if (value === undefined || value === null) return undefined;\n if (value instanceof Date) return value.toISOString();\n return String(value);\n}\n\nfunction asMessage(row: Row): BridgeMessage {\n const deliveryPolicy: DeliveryPolicy = row.delivery_mode === \"mailbox\"\n ? { mode: \"mailbox\" }\n : {\n mode: \"leased\",\n maxAttempts: Number(row.delivery_max_attempts),\n retryBaseDelayMs: Number(row.delivery_retry_base_delay_ms),\n retryMaxDelayMs: Number(row.delivery_retry_max_delay_ms),\n retryJitterRatio: Number(row.delivery_retry_jitter_ratio),\n ...(row.delivery_not_before ? { notBefore: asTimestamp(row.delivery_not_before) } : {}),\n };\n return {\n id: String(row.id),\n workspace: String(row.workspace),\n project: row.project ?? undefined,\n source: String(row.source),\n sequence: String(row.sequence),\n type: String(row.type),\n content: String(row.content),\n contentType: String(row.content_type),\n data: parse(row.data),\n targets: parse(row.targets) ?? [],\n threadId: row.thread_id ?? undefined,\n replyToId: row.reply_to_id ?? undefined,\n correlationId: row.correlation_id ?? undefined,\n causationId: row.causation_id ?? undefined,\n priority: row.priority,\n expiresAt: asTimestamp(row.expires_at),\n idempotencyKey: row.idempotency_key ?? undefined,\n atribReceiptId: row.atrib_receipt_id ?? undefined,\n informedBy: parse(row.informed_by),\n metadata: parse(row.metadata),\n deliveryPolicy,\n createdAt: asTimestamp(row.created_at) ?? \"\",\n };\n}\n\nfunction asDelivery(row: Row): BridgeDelivery {\n return {\n id: String(row.id),\n messageId: String(row.message_id),\n workspace: String(row.workspace),\n recipient: String(row.recipient),\n state: row.state,\n attempt: Number(row.attempt),\n cycleAttempt: Number(row.cycle_attempt ?? row.attempt),\n requeueCount: Number(row.requeue_count ?? 0),\n createdAt: asTimestamp(row.created_at) ?? \"\",\n priorityRank: Number(row.priority_rank),\n availableAt: asTimestamp(row.available_at) ?? \"\",\n leaseToken: row.lease_token ?? undefined,\n leaseOwner: row.lease_owner ?? undefined,\n leaseExpiresAt: asTimestamp(row.lease_expires_at),\n lastError: row.last_error ?? undefined,\n lastActor: row.last_actor ?? undefined,\n lastAction: row.last_action,\n };\n}\n\nfunction asPresence(row: Row): AgentPresence {\n return {\n workspace: String(row.workspace), agent: String(row.agent), instance: String(row.instance),\n runtimeType: row.runtime_type ?? undefined, capabilities: parse(row.capabilities) ?? [],\n leaseExpiresAt: asTimestamp(row.lease_expires_at) ?? \"\", lastSeenAt: asTimestamp(row.last_seen_at) ?? \"\",\n };\n}\n\nfunction asDeliveryEvent(row: Row): BridgeDeliveryEvent {\n return {\n sequence: String(row.sequence), deliveryId: String(row.delivery_id),\n messageId: String(row.message_id), workspace: String(row.workspace),\n recipient: String(row.recipient),\n fromState: row.from_state == null ? undefined : row.from_state as BridgeDeliveryEvent[\"fromState\"],\n toState: row.to_state as BridgeDeliveryEvent[\"toState\"], attempt: Number(row.attempt),\n cycleAttempt: Number(row.cycle_attempt), requeueCount: Number(row.requeue_count),\n leaseOwner: row.lease_owner ?? undefined, error: row.error ?? undefined,\n actor: String(row.actor), action: row.action,\n createdAt: asTimestamp(row.created_at) ?? \"\",\n };\n}\n\nasync function transaction<T>(db: PgQueryable, work: (client: PgQueryable) => Promise<T>): Promise<T> {\n if (db.inTransaction) return work(db);\n const borrowed = !db.release && Boolean(db.connect);\n const client = borrowed ? await db.connect!() : db;\n try {\n await client.query(\"BEGIN\");\n const result = await work(client);\n await client.query(\"COMMIT\");\n return result;\n } catch (error) {\n await client.query(\"ROLLBACK\").catch(() => undefined);\n throw error;\n } finally {\n if (borrowed && \"release\" in client && typeof client.release === \"function\") client.release();\n }\n}\n\nexport class PostgresBridgeStore implements BridgeStore {\n constructor(private readonly db: PgQueryable) {}\n\n async initialize(): Promise<void> {\n // Deployments apply ordered migrations before starting the service.\n }\n\n async insertMessage(\n input: Omit<BridgeMessage, \"sequence\" | \"createdAt\">,\n ): Promise<InsertMessageResult> {\n const values = [\n input.id,\n input.workspace,\n input.project ?? null,\n input.source,\n input.type,\n input.content,\n input.contentType,\n json(input.data),\n json(input.targets),\n input.threadId ?? null,\n input.replyToId ?? null,\n input.correlationId ?? null,\n input.causationId ?? null,\n input.priority,\n input.expiresAt ?? null,\n input.idempotencyKey ?? null,\n input.atribReceiptId ?? null,\n json(input.informedBy),\n json(input.metadata),\n input.deliveryPolicy.mode,\n input.deliveryPolicy.mode === \"leased\" ? input.deliveryPolicy.maxAttempts : null,\n input.deliveryPolicy.mode === \"leased\" ? input.deliveryPolicy.retryBaseDelayMs : null,\n input.deliveryPolicy.mode === \"leased\" ? input.deliveryPolicy.retryMaxDelayMs : null,\n input.deliveryPolicy.mode === \"leased\" ? input.deliveryPolicy.retryJitterRatio : null,\n input.deliveryPolicy.mode === \"leased\" ? input.deliveryPolicy.notBefore ?? null : null,\n ];\n\n const result = await this.db.query<Row>(\n `WITH inserted AS (\n INSERT INTO agent_bridge.messages (\n id, workspace, project, source, type, content, content_type, data, targets,\n thread_id, reply_to_id, correlation_id, causation_id, priority,\n expires_at, idempotency_key, atrib_receipt_id, informed_by, metadata,\n delivery_mode, delivery_max_attempts, delivery_retry_base_delay_ms,\n delivery_retry_max_delay_ms, delivery_retry_jitter_ratio, delivery_not_before\n )\n VALUES (\n $1, $2, $3, $4, $5, $6, $7, $8::jsonb, $9::jsonb,\n $10, $11, $12, $13, $14, $15, $16, $17, $18::jsonb, $19::jsonb,\n $20, $21, $22, $23, $24, $25\n )\n ON CONFLICT (workspace, source, idempotency_key)\n WHERE idempotency_key IS NOT NULL\n DO NOTHING\n RETURNING *, true AS created\n ), selected AS (\n SELECT * FROM inserted\n UNION ALL\n SELECT existing.*, false AS created\n FROM agent_bridge.messages existing\n WHERE $16::text IS NOT NULL\n AND existing.workspace = $2\n AND existing.source = $4\n AND existing.idempotency_key = $16\n AND NOT EXISTS (SELECT 1 FROM inserted)\n LIMIT 1\n ), delivery_rows AS (\n INSERT INTO agent_bridge.deliveries (\n id, message_id, workspace, publisher, recipient, state, available_at,\n created_at, priority_rank, last_actor, last_action\n )\n SELECT gen_random_uuid(), inserted.id, inserted.workspace, inserted.source, target, 'pending',\n greatest(now(), coalesce(inserted.delivery_not_before, now())),\n inserted.created_at,\n case inserted.priority when 'urgent' then 0 when 'high' then 1 else 2 end,\n inserted.source, 'created'\n FROM inserted\n CROSS JOIN LATERAL jsonb_array_elements_text(inserted.targets) AS target\n WHERE inserted.delivery_mode = 'leased'\n ON CONFLICT (message_id, recipient) DO NOTHING\n )\n SELECT * FROM selected`,\n values,\n );\n\n let row = result.rows[0];\n if (!row && input.idempotencyKey) {\n const existing = await this.db.query<Row>(\n `SELECT *, false AS created\n FROM agent_bridge.messages\n WHERE workspace=$1 AND source=$2 AND idempotency_key=$3`,\n [input.workspace, input.source, input.idempotencyKey],\n );\n row = existing.rows[0];\n }\n if (!row) throw new Error(\"message insert did not return a row\");\n const message = asMessage(row);\n if (row.created !== true) assertIdempotentReplay(message, input);\n return { message, created: row.created === true };\n }\n\n async listMessages(\n principal: BridgePrincipal,\n query: MessageQuery = {},\n ): Promise<MessagePage> {\n const scope = cursorScope(principal, query);\n const cursor = decodeCursor(query.cursor, scope) ?? \"0\";\n const limit = Math.min(Math.max(Math.trunc(query.limit ?? 50), 1), 200);\n const boundary = query.latest ? undefined : await this.db.query<{ sequence: string | null }>(\n \"SELECT max(sequence)::text AS sequence FROM agent_bridge.messages WHERE workspace=$1\",\n [principal.workspace],\n );\n const highWater = boundary?.rows[0]?.sequence;\n const values: unknown[] = query.latest\n ? [principal.workspace, principal.agent]\n : [principal.workspace, cursor, principal.agent];\n const mailbox = query.mailbox ?? \"inbox\";\n const agentParam = query.latest ? 2 : 3;\n const visibility = mailbox === \"sent\" ? `source=$${agentParam}`\n : mailbox === \"all\" ? `(source=$${agentParam} OR targets='[]'::jsonb OR targets ? $${agentParam})`\n : `(targets='[]'::jsonb OR targets ? $${agentParam})`;\n let sql = `SELECT * FROM agent_bridge.messages WHERE workspace=$1 ${query.latest ? \"\" : \"AND sequence>$2::bigint \"}AND ${visibility}`;\n\n if (highWater) {\n values.push(highWater);\n sql += ` AND sequence <= $${values.length}::bigint`;\n }\n\n if (!query.includeExpired) {\n sql += \" AND (expires_at IS NULL OR expires_at > now())\";\n }\n if (query.types?.length) {\n values.push(query.types);\n sql += ` AND type = ANY($${values.length})`;\n }\n if (query.source) {\n values.push(query.source);\n sql += ` AND source = $${values.length}`;\n }\n if (query.project) {\n values.push(query.project);\n sql += ` AND project = $${values.length}`;\n }\n if (query.since) {\n values.push(query.since);\n sql += ` AND created_at >= $${values.length}::timestamptz`;\n }\n if (query.receiptState && query.receiptState !== \"any\") {\n sql += ` AND ${query.receiptState === \"unread\" ? \"NOT \" : \"\"}EXISTS (\n SELECT 1 FROM agent_bridge.receipts receipt\n WHERE receipt.workspace=agent_bridge.messages.workspace\n AND receipt.message_id=agent_bridge.messages.id\n AND receipt.principal=$${agentParam}\n )`;\n }\n if (query.threadId) {\n values.push(query.threadId);\n sql += ` AND thread_id = $${values.length}`;\n }\n\n values.push(limit);\n const result = await this.db.query<Row>(\n `${sql} ORDER BY sequence ${query.latest ? \"DESC\" : \"ASC\"} LIMIT $${values.length}`,\n values,\n );\n const messages = result.rows.map(asMessage);\n const last = messages[messages.length - 1];\n if (query.latest) return { messages, cursor: messages[0] ? encodeCursor(messages[0].sequence, scope) : query.cursor };\n if (messages.length === limit) return { messages, cursor: encodeCursor(last!.sequence, scope) };\n return { messages, cursor: highWater ? encodeCursor(highWater, scope) : query.cursor };\n }\n\n async recordReceipt(\n principal: BridgePrincipal,\n ids: string[],\n readAt = new Date(),\n ): Promise<number> {\n const result = await this.db.query(\n `INSERT INTO agent_bridge.receipts (workspace, message_id, principal, read_at)\n SELECT message.workspace, message.id, $3, $4\n FROM agent_bridge.messages message\n WHERE message.workspace = $1 AND message.id = ANY($2::uuid[])\n AND (message.targets='[]'::jsonb OR message.targets ? $3)\n ON CONFLICT DO NOTHING`,\n [principal.workspace, ids, principal.agent, readAt],\n );\n return result.rowCount ?? 0;\n }\n\n async claimDelivery(\n principal: BridgePrincipal,\n options: ClaimOptions,\n ): Promise<BridgeDelivery | null> {\n return transaction(this.db, async (db) => {\n await db.query(\n `UPDATE agent_bridge.deliveries delivery\n SET state='dead', last_error='message expired', lease_token=NULL,\n lease_owner=NULL, lease_expires_at=NULL,\n last_actor='agent-bridge', last_action='message_expired'\n FROM agent_bridge.messages message\n WHERE delivery.workspace=$1 AND delivery.recipient=$2\n AND delivery.state IN ('pending','retrying','claimed')\n AND message.workspace=delivery.workspace AND message.id=delivery.message_id\n AND message.expires_at IS NOT NULL AND message.expires_at<=now()`,\n [principal.workspace, principal.agent],\n );\n await db.query(\n `UPDATE agent_bridge.deliveries delivery\n SET state='dead', last_error='maximum attempts reached', lease_token=NULL,\n lease_owner=NULL, lease_expires_at=NULL,\n last_actor='agent-bridge', last_action='attempts_exhausted'\n FROM agent_bridge.messages message\n WHERE delivery.workspace=$1 AND delivery.recipient=$2\n AND message.workspace=delivery.workspace AND message.id=delivery.message_id\n AND delivery.cycle_attempt>=message.delivery_max_attempts\n AND (delivery.state IN ('pending','retrying')\n OR (delivery.state='claimed' AND delivery.lease_expires_at<=now()))`,\n [principal.workspace, principal.agent],\n );\n await db.query(\n `UPDATE agent_bridge.deliveries delivery\n SET state='retrying', available_at=now(), lease_token=NULL,\n lease_owner=NULL, lease_expires_at=NULL,\n last_error='lease expired', last_actor='agent-bridge', last_action='lease_expired'\n FROM agent_bridge.messages message\n WHERE delivery.workspace=$1 AND delivery.recipient=$2\n AND message.workspace=delivery.workspace AND message.id=delivery.message_id\n AND delivery.state='claimed' AND delivery.lease_expires_at<=now()\n AND delivery.cycle_attempt<message.delivery_max_attempts`,\n [principal.workspace, principal.agent],\n );\n const candidate = await db.query<Row>(\n `SELECT delivery.id\n FROM agent_bridge.deliveries delivery\n JOIN agent_bridge.messages message\n ON message.workspace=delivery.workspace AND message.id=delivery.message_id\n WHERE delivery.workspace=$1 AND delivery.recipient=$2\n AND delivery.state IN ('pending','retrying')\n AND delivery.available_at<=now()\n AND delivery.cycle_attempt<message.delivery_max_attempts\n AND (message.expires_at IS NULL OR message.expires_at>now())\n ORDER BY delivery.priority_rank, delivery.available_at, delivery.created_at, delivery.id\n FOR UPDATE OF delivery SKIP LOCKED\n LIMIT 1`,\n [principal.workspace, principal.agent],\n );\n if (!candidate.rows[0]) return null;\n const token = randomUUID();\n const owner = principal.instance ?? principal.agent;\n const claimed = await db.query<Row>(\n `UPDATE agent_bridge.deliveries\n SET state='claimed', attempt=attempt+1, cycle_attempt=cycle_attempt+1,\n lease_token=$1, lease_owner=$2,\n lease_expires_at=now()+($3*interval '1 millisecond'),\n last_error=NULL, last_actor=$4, last_action='claim'\n WHERE id=$5\n RETURNING *`,\n [token, owner, options.leaseMs, principal.agent, candidate.rows[0].id],\n );\n return asDelivery(claimed.rows[0]!);\n });\n }\n\n async renewDelivery(\n principal: BridgePrincipal,\n id: string,\n token: string,\n leaseMs: number,\n ): Promise<BridgeDelivery | null> {\n const result = await this.db.query<Row>(\n `UPDATE agent_bridge.deliveries\n SET lease_expires_at=now() + ($1 * interval '1 millisecond')\n WHERE workspace=$2 AND recipient=$3 AND lease_owner=$4 AND id=$5 AND lease_token=$6\n AND state='claimed' AND lease_expires_at>now()\n RETURNING *`,\n [leaseMs, principal.workspace, principal.agent, principal.instance ?? principal.agent, id, token],\n );\n return result.rows[0] ? asDelivery(result.rows[0]) : null;\n }\n\n async settleDelivery(\n principal: BridgePrincipal,\n id: string,\n token: string,\n state: \"acked\" | \"retrying\" | \"dead\",\n error?: string,\n _retryPolicy?: import(\"./bridge-domain.js\").RetryPolicy,\n ): Promise<BridgeDelivery | null> {\n const result = await this.db.query<Row>(\n `UPDATE agent_bridge.deliveries delivery\n SET state=CASE\n WHEN $1='retrying' AND cycle_attempt>=message.delivery_max_attempts THEN 'dead'\n ELSE $1\n END,\n available_at=CASE\n WHEN $1='retrying' AND cycle_attempt<message.delivery_max_attempts THEN\n now() + (\n LEAST(message.delivery_retry_max_delay_ms::double precision,\n message.delivery_retry_base_delay_ms::double precision * power(2, GREATEST(cycle_attempt - 1, 0)))\n * (1 + ((random() * 2) - 1) * message.delivery_retry_jitter_ratio)\n * interval '1 millisecond'\n )\n ELSE available_at\n END,\n last_error=$2, lease_token=NULL, lease_owner=NULL, lease_expires_at=NULL,\n last_actor=$4,\n last_action=CASE\n WHEN $1='acked' THEN 'ack'\n WHEN $1='dead' THEN 'nack_dead'\n WHEN cycle_attempt>=message.delivery_max_attempts THEN 'attempts_exhausted'\n ELSE 'nack_retry'\n END\n FROM agent_bridge.messages message\n WHERE delivery.workspace=$3 AND delivery.recipient=$4 AND delivery.lease_owner=$5\n AND message.workspace=delivery.workspace AND message.id=delivery.message_id\n AND delivery.id=$6 AND delivery.lease_token=$7 AND delivery.state='claimed' AND delivery.lease_expires_at>now()\n RETURNING delivery.*`,\n [\n state,\n error?.slice(0, 1024) ?? null,\n principal.workspace,\n principal.agent,\n principal.instance ?? principal.agent,\n id,\n token,\n ],\n );\n return result.rows[0] ? asDelivery(result.rows[0]) : null;\n }\n\n async listDeliveries(principal: BridgePrincipal, query: DeliveryQuery = {}) {\n const filters = {\n role: query.role ?? \"all\",\n states: [...(query.states ?? [])].sort(),\n messageId: query.messageId ?? null,\n recipient: query.recipient ?? null,\n };\n const scope = scopedCursorScope(\"deliveries\", principal, filters);\n const boundary = validateDeliveryCursorPosition(decodeScopedCursor(query.cursor, scope));\n const createdAt = boundary?.createdAt;\n const id = boundary?.id;\n const limit = query.limit ?? 50;\n const values: unknown[] = [principal.workspace, principal.agent];\n const clauses = [\"delivery.workspace=$1\"];\n const role = query.role ?? \"all\";\n clauses.push(role === \"recipient\" ? \"delivery.recipient=$2\" : role === \"publisher\" ? \"message.source=$2\" : \"(delivery.recipient=$2 OR message.source=$2)\");\n if (createdAt && id) {\n values.push(createdAt, id);\n clauses.push(`(delivery.created_at,delivery.id)>($${values.length - 1}::timestamptz,$${values.length}::uuid)`);\n }\n if (query.messageId) { values.push(query.messageId); clauses.push(`delivery.message_id=$${values.length}`); }\n if (query.recipient) { values.push(query.recipient); clauses.push(`delivery.recipient=$${values.length}`); }\n if (query.states?.length) { values.push(query.states); clauses.push(`delivery.state=ANY($${values.length}::text[])`); }\n values.push(limit);\n const result = await this.db.query<Row>(\n `SELECT delivery.* FROM agent_bridge.deliveries delivery\n JOIN agent_bridge.messages message ON message.workspace=delivery.workspace AND message.id=delivery.message_id\n WHERE ${clauses.join(\" AND \")}\n ORDER BY delivery.created_at,delivery.id LIMIT $${values.length}`,\n values,\n );\n const deliveries = result.rows.map(asDelivery);\n const last = deliveries[deliveries.length - 1];\n return { deliveries, cursor: deliveries.length === limit && last ? encodeScopedCursor(scope, { createdAt: last.createdAt, id: last.id }) : undefined };\n }\n\n async listDeliveryEvents(principal: BridgePrincipal, id: string, query: { cursor?: string; limit?: number } = {}) {\n const limit = Math.min(Math.max(query.limit ?? 50, 1), 200);\n const scope = scopedCursorScope(\"delivery-events\", principal, { deliveryId: id });\n const position = validateEventCursorPosition(decodeScopedCursor(query.cursor, scope));\n const result = await this.db.query<Row>(\n `SELECT event.* FROM agent_bridge.delivery_events event\n JOIN agent_bridge.messages message ON message.workspace=event.workspace AND message.id=event.message_id\n WHERE event.workspace=$1 AND event.delivery_id=$2 AND event.sequence>$3::bigint\n AND (event.recipient=$4 OR message.source=$4)\n ORDER BY event.sequence LIMIT $5`,\n [principal.workspace, id, position ?? \"0\", principal.agent, limit],\n );\n const events = result.rows.map(asDeliveryEvent);\n const last = events[events.length - 1];\n return { events, cursor: events.length === limit && last ? encodeScopedCursor(scope, last.sequence) : undefined };\n }\n\n async cancelDelivery(principal: BridgePrincipal, id: string) {\n return transaction(this.db, async (db) => {\n const visible = await db.query<Row>(\n `SELECT delivery.* FROM agent_bridge.deliveries delivery\n JOIN agent_bridge.messages message ON message.workspace=delivery.workspace AND message.id=delivery.message_id\n WHERE delivery.id=$1 AND delivery.workspace=$2 AND message.source=$3 FOR UPDATE OF delivery`,\n [id, principal.workspace, principal.agent],\n );\n const current = visible.rows[0];\n if (!current) return null;\n if (current.state === \"cancelled\") return asDelivery(current);\n if (![\"pending\", \"retrying\", \"claimed\"].includes(current.state)) {\n throw new DeliveryStateConflictError(`cannot cancel a ${current.state} delivery`);\n }\n const result = await db.query<Row>(\n `UPDATE agent_bridge.deliveries SET state='cancelled', lease_token=NULL,\n lease_owner=NULL, lease_expires_at=NULL, last_error=NULL,\n last_actor=$1, last_action='cancel' WHERE id=$2 RETURNING *`,\n [principal.agent, id],\n );\n return asDelivery(result.rows[0]!);\n });\n }\n\n async requeueDelivery(principal: BridgePrincipal, id: string) {\n return transaction(this.db, async (db) => {\n const visible = await db.query<Row>(\n `SELECT delivery.*,message.expires_at,message.delivery_not_before\n FROM agent_bridge.deliveries delivery\n JOIN agent_bridge.messages message ON message.workspace=delivery.workspace AND message.id=delivery.message_id\n WHERE delivery.id=$1 AND delivery.workspace=$2 AND message.source=$3 FOR UPDATE OF delivery`,\n [id, principal.workspace, principal.agent],\n );\n const current = visible.rows[0];\n if (!current) return null;\n if (![\"dead\", \"cancelled\"].includes(current.state)) {\n throw new DeliveryStateConflictError(`cannot requeue a ${current.state} delivery`);\n }\n if (current.expires_at && new Date(current.expires_at).getTime() <= Date.now()) {\n throw new DeliveryStateConflictError(\"cannot requeue an expired message\");\n }\n const result = await db.query<Row>(\n `UPDATE agent_bridge.deliveries SET state='pending',\n available_at=greatest(now(),coalesce($1::timestamptz,now())),\n cycle_attempt=0,requeue_count=requeue_count+1,\n lease_token=NULL,lease_owner=NULL,lease_expires_at=NULL,last_error=NULL,\n last_actor=$2,last_action='requeue' WHERE id=$3 RETURNING *`,\n [current.delivery_not_before, principal.agent, id],\n );\n return asDelivery(result.rows[0]!);\n });\n }\n\n async diagnostics(principal: BridgePrincipal): Promise<BridgeDiagnostics> {\n const result = await this.db.query<Row>(\n `SELECT\n count(*) FILTER (WHERE state='pending')::integer AS pending,\n count(*) FILTER (WHERE state='claimed')::integer AS claimed,\n count(*) FILTER (WHERE state='retrying')::integer AS retrying,\n count(*) FILTER (WHERE state='dead')::integer AS dead,\n count(*) FILTER (WHERE state='cancelled')::integer AS cancelled,\n min(available_at) FILTER (WHERE state IN ('pending','retrying')) AS oldest_available,\n count(*) FILTER (WHERE state IN ('pending','retrying') AND available_at<=now())::integer AS due,\n count(*) FILTER (WHERE state IN ('pending','retrying') AND available_at>now())::integer AS scheduled,\n count(*) FILTER (WHERE state='claimed' AND lease_expires_at<=now())::integer AS expired_leases,\n min(available_at) FILTER (WHERE state IN ('pending','retrying') AND available_at<=now()) AS oldest_due,\n coalesce(greatest(0,extract(epoch FROM (now()-min(available_at) FILTER (WHERE state IN ('pending','retrying') AND available_at<=now())))*1000),0)::bigint AS queue_lag_ms\n FROM agent_bridge.deliveries WHERE workspace=$1 AND recipient=$2`,\n [principal.workspace, principal.agent],\n );\n const queue = result.rows[0] ?? {};\n return {\n schemaVersion: \"postgres-v2\",\n deliverySupported: true,\n pending: Number(queue.pending ?? 0),\n claimed: Number(queue.claimed ?? 0),\n retrying: Number(queue.retrying ?? 0),\n dead: Number(queue.dead ?? 0),\n cancelled: Number(queue.cancelled ?? 0),\n oldestAvailableAt: asTimestamp(queue.oldest_available),\n due: Number(queue.due ?? 0),\n scheduled: Number(queue.scheduled ?? 0),\n expiredLeases: Number(queue.expired_leases ?? 0),\n oldestDueAt: asTimestamp(queue.oldest_due),\n queueLagMs: Number(queue.queue_lag_ms ?? 0),\n };\n }\n\n async heartbeat(principal: BridgePrincipal, leaseMs: number, runtimeType?: string, capabilities: string[] = []): Promise<AgentPresence> {\n await this.db.query(\n \"DELETE FROM agent_bridge.agent_instances WHERE workspace=$1 AND lease_expires_at<=now()\",\n [principal.workspace],\n );\n const result = await this.db.query<Row>(\n `WITH locked AS (\n SELECT pg_advisory_xact_lock(hashtextextended($1, 0))\n )\n INSERT INTO agent_bridge.agent_instances (workspace,agent,instance,runtime_type,capabilities,lease_expires_at,last_seen_at)\n SELECT $1,$2,$3,$4,$5::jsonb,now() + ($6 * interval '1 millisecond'),now()\n FROM locked\n WHERE EXISTS (\n SELECT 1 FROM agent_bridge.agent_instances\n WHERE workspace=$1 AND agent=$2 AND instance=$3\n ) OR ((\n SELECT count(*) < 128 FROM agent_bridge.agent_instances\n WHERE workspace=$1 AND agent=$2\n ) AND (\n SELECT count(*) < 4096 FROM agent_bridge.agent_instances\n WHERE workspace=$1\n )\n )\n ON CONFLICT (workspace,agent,instance) DO UPDATE SET runtime_type=excluded.runtime_type,capabilities=excluded.capabilities,lease_expires_at=excluded.lease_expires_at,last_seen_at=excluded.last_seen_at\n RETURNING *`,\n [principal.workspace, principal.agent, principal.instance, runtimeType ?? null, JSON.stringify(capabilities), leaseMs],\n );\n if (!result.rows[0]) {\n throw Object.assign(new Error(\"active instance limit reached\"), {\n status: 429,\n code: \"presence_limit\",\n });\n }\n return asPresence(result.rows[0]!);\n }\n\n async listPresence(principal: BridgePrincipal): Promise<AgentPresence[]> {\n await this.db.query(\n \"DELETE FROM agent_bridge.agent_instances WHERE workspace=$1 AND lease_expires_at<=now()\",\n [principal.workspace],\n );\n const result = await this.db.query<Row>(\n \"SELECT * FROM agent_bridge.agent_instances WHERE workspace=$1 ORDER BY agent,instance\",\n [principal.workspace],\n );\n return result.rows.map(asPresence);\n }\n\n}\n"],"mappings":"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","names":[]}
|