@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
|
@@ -18,11 +18,73 @@ begin
|
|
|
18
18
|
role_name
|
|
19
19
|
);
|
|
20
20
|
end if;
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
if exists (
|
|
22
|
+
select 1 from pg_roles where rolname=role_name and (
|
|
23
|
+
rolcanlogin or not rolinherit or rolsuper or rolcreatedb or rolcreaterole
|
|
24
|
+
or rolreplication or rolbypassrls or rolconnlimit<>-1
|
|
25
|
+
)
|
|
26
|
+
) then
|
|
27
|
+
raise exception 'Agent Bridge control role % has unsafe attributes',role_name;
|
|
28
|
+
end if;
|
|
29
|
+
if current_setting('server_version_num')::integer>=160000 then
|
|
30
|
+
if not exists (
|
|
31
|
+
select 1 from pg_catalog.pg_auth_members membership
|
|
32
|
+
join pg_catalog.pg_roles granted on granted.oid=membership.roleid
|
|
33
|
+
join pg_catalog.pg_roles member on member.oid=membership.member
|
|
34
|
+
where granted.rolname=role_name and member.rolname=current_user
|
|
35
|
+
and membership.admin_option
|
|
36
|
+
) then
|
|
37
|
+
execute format(
|
|
38
|
+
'grant %I to %I with admin true,inherit true,set true',role_name,current_user
|
|
39
|
+
);
|
|
40
|
+
elsif not exists (
|
|
41
|
+
select 1 from pg_catalog.pg_auth_members membership
|
|
42
|
+
join pg_catalog.pg_roles granted on granted.oid=membership.roleid
|
|
43
|
+
join pg_catalog.pg_roles member on member.oid=membership.member
|
|
44
|
+
where granted.rolname=role_name and member.rolname=current_user
|
|
45
|
+
and coalesce((to_jsonb(membership)->>'inherit_option')::boolean,true)
|
|
46
|
+
and coalesce((to_jsonb(membership)->>'set_option')::boolean,true)
|
|
47
|
+
) then
|
|
48
|
+
execute format('grant %I to %I with inherit true,set true',role_name,current_user);
|
|
49
|
+
end if;
|
|
50
|
+
elsif not exists (
|
|
51
|
+
select 1 from pg_catalog.pg_auth_members membership
|
|
52
|
+
join pg_catalog.pg_roles granted on granted.oid=membership.roleid
|
|
53
|
+
join pg_catalog.pg_roles member on member.oid=membership.member
|
|
54
|
+
where granted.rolname=role_name and member.rolname=current_user
|
|
55
|
+
and membership.admin_option
|
|
56
|
+
) then
|
|
57
|
+
execute format('grant %I to %I with admin option',role_name,current_user);
|
|
58
|
+
end if;
|
|
59
|
+
if not exists (
|
|
60
|
+
select 1 from pg_catalog.pg_auth_members membership
|
|
61
|
+
join pg_catalog.pg_roles granted on granted.oid=membership.roleid
|
|
62
|
+
join pg_catalog.pg_roles member on member.oid=membership.member
|
|
63
|
+
where granted.rolname=role_name and member.rolname=current_user
|
|
64
|
+
and membership.admin_option
|
|
65
|
+
) or not exists (
|
|
66
|
+
select 1 from pg_catalog.pg_auth_members membership
|
|
67
|
+
join pg_catalog.pg_roles granted on granted.oid=membership.roleid
|
|
68
|
+
join pg_catalog.pg_roles member on member.oid=membership.member
|
|
69
|
+
where granted.rolname=role_name and member.rolname=current_user
|
|
70
|
+
and coalesce((to_jsonb(membership)->>'inherit_option')::boolean,true)
|
|
71
|
+
and coalesce((to_jsonb(membership)->>'set_option')::boolean,true)
|
|
72
|
+
) or exists (
|
|
73
|
+
select 1 from pg_catalog.pg_auth_members membership
|
|
74
|
+
join pg_catalog.pg_roles granted on granted.oid=membership.roleid
|
|
75
|
+
join pg_catalog.pg_roles member on member.oid=membership.member
|
|
76
|
+
where granted.rolname=role_name and member.rolname=current_user
|
|
77
|
+
and not (
|
|
78
|
+
(membership.grantor=10 and membership.admin_option
|
|
79
|
+
and coalesce((to_jsonb(membership)->>'inherit_option')::boolean,true)
|
|
80
|
+
=coalesce((to_jsonb(membership)->>'set_option')::boolean,true))
|
|
81
|
+
or (membership.grantor=member.oid
|
|
82
|
+
and coalesce((to_jsonb(membership)->>'inherit_option')::boolean,true)
|
|
83
|
+
and coalesce((to_jsonb(membership)->>'set_option')::boolean,true))
|
|
84
|
+
)
|
|
85
|
+
) then
|
|
86
|
+
raise exception 'Agent Bridge control role % has unsafe owner authority',role_name;
|
|
87
|
+
end if;
|
|
26
88
|
end loop;
|
|
27
89
|
end
|
|
28
90
|
$roles$;
|
|
@@ -144,27 +206,38 @@ begin
|
|
|
144
206
|
where event.member_role=session_user and event.control_role in ('operator','auditor')
|
|
145
207
|
order by event.control_role,event.sequence desc
|
|
146
208
|
), direct_membership as (
|
|
147
|
-
select granted.rolname control_role,
|
|
148
|
-
|
|
149
|
-
coalesce((to_jsonb(membership)->>'
|
|
150
|
-
|
|
209
|
+
select granted.rolname control_role,
|
|
210
|
+
bool_or(membership.admin_option) admin_option,
|
|
211
|
+
bool_or(coalesce((to_jsonb(membership)->>'inherit_option')::boolean,true)) inherit_option,
|
|
212
|
+
bool_or(coalesce((to_jsonb(membership)->>'set_option')::boolean,true)) set_option,
|
|
213
|
+
bool_and(case when member.rolname=schema_owner then
|
|
214
|
+
(membership.grantor=10 and membership.admin_option
|
|
215
|
+
and coalesce((to_jsonb(membership)->>'inherit_option')::boolean,true)
|
|
216
|
+
=coalesce((to_jsonb(membership)->>'set_option')::boolean,true))
|
|
217
|
+
or (membership.grantor=member.oid
|
|
218
|
+
and coalesce((to_jsonb(membership)->>'inherit_option')::boolean,true)
|
|
219
|
+
and coalesce((to_jsonb(membership)->>'set_option')::boolean,true))
|
|
220
|
+
else membership.grantor=(select oid from pg_catalog.pg_roles where rolname=schema_owner)
|
|
221
|
+
and not membership.admin_option
|
|
222
|
+
and coalesce((to_jsonb(membership)->>'inherit_option')::boolean,true)
|
|
223
|
+
and coalesce((to_jsonb(membership)->>'set_option')::boolean,true) end) grants_valid
|
|
151
224
|
from pg_catalog.pg_auth_members membership
|
|
152
225
|
join pg_catalog.pg_roles granted on granted.oid=membership.roleid
|
|
153
226
|
join pg_catalog.pg_roles member on member.oid=membership.member
|
|
154
|
-
join pg_catalog.pg_roles grantor on grantor.oid=membership.grantor
|
|
155
227
|
where member.rolname=session_user and granted.rolname in (operator_role,auditor_role)
|
|
228
|
+
group by granted.rolname
|
|
156
229
|
)
|
|
157
230
|
select
|
|
158
231
|
coalesce(bool_or(membership.control_role=operator_role
|
|
159
232
|
and membership.inherit_option and membership.set_option
|
|
160
|
-
and membership.
|
|
233
|
+
and membership.grants_valid and (
|
|
161
234
|
(session_user=schema_owner and membership.admin_option)
|
|
162
235
|
or (latest.control_role='operator' and latest.action='register'
|
|
163
236
|
and not membership.admin_option)
|
|
164
237
|
)),false),
|
|
165
238
|
coalesce(bool_or(membership.control_role=auditor_role
|
|
166
239
|
and membership.inherit_option and membership.set_option
|
|
167
|
-
and membership.
|
|
240
|
+
and membership.grants_valid and (
|
|
168
241
|
(session_user=schema_owner and membership.admin_option)
|
|
169
242
|
or (latest.control_role='auditor' and latest.action='register'
|
|
170
243
|
and not membership.admin_option)
|
|
@@ -937,15 +1010,15 @@ language sql stable set search_path = '' set timezone = 'UTC' as $$
|
|
|
937
1010
|
from pg_catalog.pg_roles role where role.rolname in (select role_name from control_roles)
|
|
938
1011
|
union all
|
|
939
1012
|
select 'membership',granted.rolname||'->'||member.rolname,
|
|
940
|
-
|
|
941
|
-
coalesce(to_jsonb(membership)->>'inherit_option',
|
|
942
|
-
coalesce(to_jsonb(membership)->>'set_option',
|
|
1013
|
+
bool_or(membership.admin_option)::text||':'||
|
|
1014
|
+
bool_or(coalesce((to_jsonb(membership)->>'inherit_option')::boolean,true))::text||':'||
|
|
1015
|
+
bool_or(coalesce((to_jsonb(membership)->>'set_option')::boolean,true))::text
|
|
943
1016
|
from pg_catalog.pg_auth_members membership
|
|
944
1017
|
join pg_catalog.pg_roles granted on granted.oid=membership.roleid
|
|
945
1018
|
join pg_catalog.pg_roles member on member.oid=membership.member
|
|
946
|
-
join pg_catalog.pg_roles grantor on grantor.oid=membership.grantor
|
|
947
1019
|
where member.rolname in (select role_name from control_roles)
|
|
948
1020
|
or granted.rolname=(select owner_role from names)
|
|
1021
|
+
group by granted.rolname,member.rolname
|
|
949
1022
|
union all
|
|
950
1023
|
select 'schema',namespace.nspname,pg_catalog.pg_get_userbyid(namespace.nspowner)
|
|
951
1024
|
from pg_catalog.pg_namespace namespace where namespace.nspname='agent_bridge'
|
|
@@ -1106,27 +1179,42 @@ returns boolean language sql stable security definer set search_path = '' as $$
|
|
|
1106
1179
|
), active_registry as (
|
|
1107
1180
|
select member_role,control_role from latest_registry where action='register'
|
|
1108
1181
|
), expected_memberships as (
|
|
1109
|
-
select names.owner_role granted_role,names.schema_owner member_role,
|
|
1182
|
+
select names.owner_role granted_role,names.schema_owner member_role,
|
|
1183
|
+
true admin_option,true inherit_option,true set_option
|
|
1110
1184
|
from names
|
|
1111
|
-
union all select names.operator_role,names.schema_owner,true from names
|
|
1112
|
-
union all select names.auditor_role,names.schema_owner,true from names
|
|
1185
|
+
union all select names.operator_role,names.schema_owner,true,true,true from names
|
|
1186
|
+
union all select names.auditor_role,names.schema_owner,true,true,true from names
|
|
1113
1187
|
union all
|
|
1114
1188
|
select case registry.control_role when 'operator' then names.operator_role
|
|
1115
|
-
else names.auditor_role end,registry.member_role,false
|
|
1189
|
+
else names.auditor_role end,registry.member_role,false,true,true
|
|
1116
1190
|
from active_registry registry cross join names
|
|
1117
|
-
),
|
|
1191
|
+
), raw_memberships as (
|
|
1118
1192
|
select granted.rolname::name granted_role,member.rolname::name member_role,
|
|
1119
1193
|
membership.admin_option,
|
|
1120
1194
|
coalesce((to_jsonb(membership)->>'inherit_option')::boolean,true) inherit_option,
|
|
1121
1195
|
coalesce((to_jsonb(membership)->>'set_option')::boolean,true) set_option,
|
|
1122
|
-
grantor.
|
|
1196
|
+
membership.grantor,member.oid member_oid
|
|
1123
1197
|
from pg_catalog.pg_auth_members membership
|
|
1124
1198
|
join pg_catalog.pg_roles granted on granted.oid=membership.roleid
|
|
1125
1199
|
join pg_catalog.pg_roles member on member.oid=membership.member
|
|
1126
|
-
join pg_catalog.pg_roles grantor on grantor.oid=membership.grantor
|
|
1127
1200
|
where granted.rolname in (
|
|
1128
1201
|
(select owner_role from names),(select operator_role from names),(select auditor_role from names)
|
|
1129
1202
|
)
|
|
1203
|
+
), actual_memberships as (
|
|
1204
|
+
select membership.granted_role,membership.member_role,
|
|
1205
|
+
bool_or(membership.admin_option) admin_option,
|
|
1206
|
+
bool_or(membership.inherit_option) inherit_option,
|
|
1207
|
+
bool_or(membership.set_option) set_option,
|
|
1208
|
+
bool_and(case when membership.member_role=names.schema_owner then
|
|
1209
|
+
(membership.grantor=10 and membership.admin_option
|
|
1210
|
+
and membership.inherit_option=membership.set_option)
|
|
1211
|
+
or (membership.grantor=membership.member_oid
|
|
1212
|
+
and membership.inherit_option and membership.set_option)
|
|
1213
|
+
else membership.grantor=(select oid from pg_catalog.pg_roles where rolname=names.schema_owner)
|
|
1214
|
+
and not membership.admin_option
|
|
1215
|
+
and membership.inherit_option and membership.set_option end) grants_valid
|
|
1216
|
+
from raw_memberships membership cross join names
|
|
1217
|
+
group by membership.granted_role,membership.member_role
|
|
1130
1218
|
), authority_closure as (
|
|
1131
1219
|
select control_role.granted_role,candidate.rolname::name member_role
|
|
1132
1220
|
from names
|
|
@@ -1145,16 +1233,14 @@ returns boolean language sql stable security definer set search_path = '' as $$
|
|
|
1145
1233
|
) from agent_bridge.owner_control_attestations attestation
|
|
1146
1234
|
where attestation.name='owner-control-v1')
|
|
1147
1235
|
and not exists (
|
|
1148
|
-
(select granted_role,member_role,admin_option from actual_memberships
|
|
1149
|
-
except select granted_role,member_role,admin_option from expected_memberships)
|
|
1236
|
+
(select granted_role,member_role,admin_option,inherit_option,set_option from actual_memberships
|
|
1237
|
+
except select granted_role,member_role,admin_option,inherit_option,set_option from expected_memberships)
|
|
1150
1238
|
union all
|
|
1151
|
-
(select granted_role,member_role,admin_option from expected_memberships
|
|
1152
|
-
except select granted_role,member_role,admin_option from actual_memberships)
|
|
1239
|
+
(select granted_role,member_role,admin_option,inherit_option,set_option from expected_memberships
|
|
1240
|
+
except select granted_role,member_role,admin_option,inherit_option,set_option from actual_memberships)
|
|
1153
1241
|
)
|
|
1154
1242
|
and not exists (
|
|
1155
|
-
select 1 from actual_memberships membership
|
|
1156
|
-
where not membership.inherit_option or not membership.set_option
|
|
1157
|
-
or membership.grantor_role<>names.schema_owner
|
|
1243
|
+
select 1 from actual_memberships membership where not membership.grants_valid
|
|
1158
1244
|
)
|
|
1159
1245
|
and not exists (
|
|
1160
1246
|
select 1 from active_registry registry
|
|
@@ -1216,6 +1302,7 @@ declare
|
|
|
1216
1302
|
membership_record record;
|
|
1217
1303
|
relation_record record;
|
|
1218
1304
|
begin
|
|
1305
|
+
execute format('grant usage,create on schema agent_bridge to %I',owner_role);
|
|
1219
1306
|
execute format('alter table agent_bridge.control_requests owner to %I',owner_role);
|
|
1220
1307
|
execute format('alter table agent_bridge.control_events owner to %I',owner_role);
|
|
1221
1308
|
execute format('alter table agent_bridge.owner_control_attestations owner to %I',owner_role);
|
|
@@ -1230,6 +1317,7 @@ begin
|
|
|
1230
1317
|
'control_revoke_credential(uuid,uuid,text)','owner_control_catalog_definition()',
|
|
1231
1318
|
'owner_control_plane_ready()'
|
|
1232
1319
|
] loop execute format('alter function agent_bridge.%s owner to %I',role_name,owner_role); end loop;
|
|
1320
|
+
execute format('revoke create on schema agent_bridge from %I',owner_role);
|
|
1233
1321
|
|
|
1234
1322
|
for membership_record in
|
|
1235
1323
|
select granted.rolname granted_name,member.rolname member_name
|
|
@@ -1287,7 +1375,7 @@ begin
|
|
|
1287
1375
|
execute format('grant usage on schema agent_bridge to %I,%I,%I',owner_role,operator_role,auditor_role);
|
|
1288
1376
|
execute format('grant select,insert,update(request_id) on agent_bridge.control_requests to %I',owner_role);
|
|
1289
1377
|
execute format('grant insert on agent_bridge.control_events to %I',owner_role);
|
|
1290
|
-
execute format('grant select on agent_bridge.owner_control_attestations to %I',owner_role);
|
|
1378
|
+
execute format('grant select,insert on agent_bridge.owner_control_attestations to %I',owner_role);
|
|
1291
1379
|
execute format('grant select,insert on agent_bridge.control_membership_events to %I',owner_role);
|
|
1292
1380
|
execute format('grant usage on sequence agent_bridge.control_events_sequence_seq to %I',owner_role);
|
|
1293
1381
|
execute format('grant usage on sequence agent_bridge.control_membership_events_sequence_seq to %I',owner_role);
|
|
@@ -1306,6 +1394,7 @@ begin
|
|
|
1306
1394
|
execute format('grant execute on function agent_bridge.control_revoke_credential(uuid,uuid,text) to %I',operator_role);
|
|
1307
1395
|
execute format('grant execute on function agent_bridge.control_credential_inventory(text,timestamp with time zone,uuid,integer) to %I,%I',operator_role,auditor_role);
|
|
1308
1396
|
execute format('grant execute on function agent_bridge.owner_control_plane_ready() to %I',runtime_role);
|
|
1397
|
+
execute format('grant execute on function agent_bridge.owner_control_plane_ready() to %I',current_user);
|
|
1309
1398
|
execute format('revoke execute on function agent_bridge.replace_credential(uuid,character,text[],text,text,timestamp with time zone,timestamp with time zone,text,uuid) from %I,%I,%I',operator_role,auditor_role,runtime_role);
|
|
1310
1399
|
execute format('revoke execute on function agent_bridge.revoke_credential(uuid,text,text,uuid) from %I,%I,%I',operator_role,auditor_role,runtime_role);
|
|
1311
1400
|
foreach role_name in array array['anon','authenticated'] loop
|
|
@@ -1632,8 +1721,12 @@ begin
|
|
|
1632
1721
|
end
|
|
1633
1722
|
$preflight$;
|
|
1634
1723
|
|
|
1724
|
+
select set_config(
|
|
1725
|
+
'role','agent_bridge_control_owner_'||substr(md5(current_database()),1,16),false
|
|
1726
|
+
);
|
|
1635
1727
|
insert into agent_bridge.owner_control_attestations(name,catalog_definition)
|
|
1636
1728
|
values('owner-control-v1',agent_bridge.owner_control_catalog_definition());
|
|
1729
|
+
reset role;
|
|
1637
1730
|
|
|
1638
1731
|
insert into agent_bridge.schema_migrations(version,name,checksum)
|
|
1639
1732
|
values(14,'owner_control_plane','__AGENT_BRIDGE_MIGRATION_CHECKSUM__');
|
|
@@ -26,11 +26,73 @@ begin
|
|
|
26
26
|
role_name
|
|
27
27
|
);
|
|
28
28
|
end if;
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
29
|
+
if exists (
|
|
30
|
+
select 1 from pg_catalog.pg_roles where rolname=role_name and (
|
|
31
|
+
rolcanlogin or not rolinherit or rolsuper or rolcreatedb or rolcreaterole
|
|
32
|
+
or rolreplication or rolbypassrls or rolconnlimit<>-1
|
|
33
|
+
)
|
|
34
|
+
) then
|
|
35
|
+
raise exception 'Agent Bridge archive role has unsafe attributes';
|
|
36
|
+
end if;
|
|
37
|
+
if current_setting('server_version_num')::integer>=160000 then
|
|
38
|
+
if not exists (
|
|
39
|
+
select 1 from pg_catalog.pg_auth_members membership
|
|
40
|
+
join pg_catalog.pg_roles granted on granted.oid=membership.roleid
|
|
41
|
+
join pg_catalog.pg_roles member on member.oid=membership.member
|
|
42
|
+
where granted.rolname=role_name and member.rolname=current_user
|
|
43
|
+
and membership.admin_option
|
|
44
|
+
) then
|
|
45
|
+
execute format(
|
|
46
|
+
'grant %I to %I with admin true,inherit true,set true',role_name,current_user
|
|
47
|
+
);
|
|
48
|
+
elsif not exists (
|
|
49
|
+
select 1 from pg_catalog.pg_auth_members membership
|
|
50
|
+
join pg_catalog.pg_roles granted on granted.oid=membership.roleid
|
|
51
|
+
join pg_catalog.pg_roles member on member.oid=membership.member
|
|
52
|
+
where granted.rolname=role_name and member.rolname=current_user
|
|
53
|
+
and coalesce((to_jsonb(membership)->>'inherit_option')::boolean,true)
|
|
54
|
+
and coalesce((to_jsonb(membership)->>'set_option')::boolean,true)
|
|
55
|
+
) then
|
|
56
|
+
execute format('grant %I to %I with inherit true,set true',role_name,current_user);
|
|
57
|
+
end if;
|
|
58
|
+
elsif not exists (
|
|
59
|
+
select 1 from pg_catalog.pg_auth_members membership
|
|
60
|
+
join pg_catalog.pg_roles granted on granted.oid=membership.roleid
|
|
61
|
+
join pg_catalog.pg_roles member on member.oid=membership.member
|
|
62
|
+
where granted.rolname=role_name and member.rolname=current_user
|
|
63
|
+
and membership.admin_option
|
|
64
|
+
) then
|
|
65
|
+
execute format('grant %I to %I with admin option',role_name,current_user);
|
|
66
|
+
end if;
|
|
67
|
+
if not exists (
|
|
68
|
+
select 1 from pg_catalog.pg_auth_members membership
|
|
69
|
+
join pg_catalog.pg_roles granted on granted.oid=membership.roleid
|
|
70
|
+
join pg_catalog.pg_roles member on member.oid=membership.member
|
|
71
|
+
where granted.rolname=role_name and member.rolname=current_user
|
|
72
|
+
and membership.admin_option
|
|
73
|
+
) or not exists (
|
|
74
|
+
select 1 from pg_catalog.pg_auth_members membership
|
|
75
|
+
join pg_catalog.pg_roles granted on granted.oid=membership.roleid
|
|
76
|
+
join pg_catalog.pg_roles member on member.oid=membership.member
|
|
77
|
+
where granted.rolname=role_name and member.rolname=current_user
|
|
78
|
+
and coalesce((to_jsonb(membership)->>'inherit_option')::boolean,true)
|
|
79
|
+
and coalesce((to_jsonb(membership)->>'set_option')::boolean,true)
|
|
80
|
+
) or exists (
|
|
81
|
+
select 1 from pg_catalog.pg_auth_members membership
|
|
82
|
+
join pg_catalog.pg_roles granted on granted.oid=membership.roleid
|
|
83
|
+
join pg_catalog.pg_roles member on member.oid=membership.member
|
|
84
|
+
where granted.rolname=role_name and member.rolname=current_user
|
|
85
|
+
and not (
|
|
86
|
+
(membership.grantor=10 and membership.admin_option
|
|
87
|
+
and coalesce((to_jsonb(membership)->>'inherit_option')::boolean,true)
|
|
88
|
+
=coalesce((to_jsonb(membership)->>'set_option')::boolean,true))
|
|
89
|
+
or (membership.grantor=member.oid
|
|
90
|
+
and coalesce((to_jsonb(membership)->>'inherit_option')::boolean,true)
|
|
91
|
+
and coalesce((to_jsonb(membership)->>'set_option')::boolean,true))
|
|
92
|
+
)
|
|
93
|
+
) then
|
|
94
|
+
raise exception 'Agent Bridge archive role has unsafe owner authority';
|
|
95
|
+
end if;
|
|
34
96
|
end
|
|
35
97
|
$roles$;
|
|
36
98
|
|
|
@@ -215,19 +277,28 @@ begin
|
|
|
215
277
|
select event.action from agent_bridge.archive_membership_events event
|
|
216
278
|
where event.member_role=session_user order by event.sequence desc limit 1
|
|
217
279
|
), direct_membership as (
|
|
218
|
-
select membership.admin_option,
|
|
219
|
-
coalesce((to_jsonb(membership)->>'inherit_option')::boolean,true) inherit_option,
|
|
220
|
-
coalesce((to_jsonb(membership)->>'set_option')::boolean,true) set_option,
|
|
221
|
-
|
|
280
|
+
select bool_or(membership.admin_option) admin_option,
|
|
281
|
+
bool_or(coalesce((to_jsonb(membership)->>'inherit_option')::boolean,true)) inherit_option,
|
|
282
|
+
bool_or(coalesce((to_jsonb(membership)->>'set_option')::boolean,true)) set_option,
|
|
283
|
+
bool_and(case when member.rolname=schema_owner then
|
|
284
|
+
(membership.grantor=10 and membership.admin_option
|
|
285
|
+
and coalesce((to_jsonb(membership)->>'inherit_option')::boolean,true)
|
|
286
|
+
=coalesce((to_jsonb(membership)->>'set_option')::boolean,true))
|
|
287
|
+
or (membership.grantor=member.oid
|
|
288
|
+
and coalesce((to_jsonb(membership)->>'inherit_option')::boolean,true)
|
|
289
|
+
and coalesce((to_jsonb(membership)->>'set_option')::boolean,true))
|
|
290
|
+
else membership.grantor=(select oid from pg_catalog.pg_roles where rolname=schema_owner)
|
|
291
|
+
and not membership.admin_option
|
|
292
|
+
and coalesce((to_jsonb(membership)->>'inherit_option')::boolean,true)
|
|
293
|
+
and coalesce((to_jsonb(membership)->>'set_option')::boolean,true) end) grants_valid
|
|
222
294
|
from pg_catalog.pg_auth_members membership
|
|
223
295
|
join pg_catalog.pg_roles granted on granted.oid=membership.roleid
|
|
224
296
|
join pg_catalog.pg_roles member on member.oid=membership.member
|
|
225
|
-
join pg_catalog.pg_roles grantor on grantor.oid=membership.grantor
|
|
226
297
|
where member.rolname=session_user and granted.rolname=archive_role
|
|
227
298
|
)
|
|
228
299
|
select coalesce(bool_or(
|
|
229
300
|
membership.inherit_option and membership.set_option
|
|
230
|
-
and membership.
|
|
301
|
+
and membership.grants_valid and (
|
|
231
302
|
(session_user=schema_owner and membership.admin_option)
|
|
232
303
|
or (latest.action='register' and not membership.admin_option)
|
|
233
304
|
)
|
|
@@ -1396,15 +1467,15 @@ returns text language sql stable set search_path = '' set timezone = 'UTC' as $$
|
|
|
1396
1467
|
from pg_catalog.pg_roles role where role.rolname=(select archive_role from names)
|
|
1397
1468
|
union all
|
|
1398
1469
|
select 'owner_membership',granted.rolname||'->'||member.rolname,
|
|
1399
|
-
|
|
1400
|
-
coalesce(to_jsonb(membership)->>'inherit_option',
|
|
1401
|
-
coalesce(to_jsonb(membership)->>'set_option',
|
|
1470
|
+
bool_or(membership.admin_option)::text||':'||
|
|
1471
|
+
bool_or(coalesce((to_jsonb(membership)->>'inherit_option')::boolean,true))::text||':'||
|
|
1472
|
+
bool_or(coalesce((to_jsonb(membership)->>'set_option')::boolean,true))::text
|
|
1402
1473
|
from pg_catalog.pg_auth_members membership
|
|
1403
1474
|
join pg_catalog.pg_roles granted on granted.oid=membership.roleid
|
|
1404
1475
|
join pg_catalog.pg_roles member on member.oid=membership.member
|
|
1405
|
-
join pg_catalog.pg_roles grantor on grantor.oid=membership.grantor
|
|
1406
1476
|
where granted.rolname=(select archive_role from names)
|
|
1407
1477
|
and member.oid=(select schema_owner from names)
|
|
1478
|
+
group by granted.rolname,member.rolname
|
|
1408
1479
|
union all
|
|
1409
1480
|
select 'schema','agent_bridge',pg_catalog.pg_get_userbyid(namespace.nspowner)
|
|
1410
1481
|
from pg_catalog.pg_namespace namespace where namespace.oid=(select schema_oid from names)
|
|
@@ -1542,19 +1613,35 @@ returns boolean language sql stable security definer set search_path = '' as $$
|
|
|
1542
1613
|
), active_registry as (
|
|
1543
1614
|
select member_role from latest_registry where action='register'
|
|
1544
1615
|
), expected_memberships as (
|
|
1545
|
-
select names.archive_role granted_role,names.schema_owner member_role,
|
|
1546
|
-
|
|
1547
|
-
|
|
1616
|
+
select names.archive_role granted_role,names.schema_owner member_role,
|
|
1617
|
+
true admin_option,true inherit_option,true set_option from names
|
|
1618
|
+
union all select names.archive_role,registry.member_role,false,true,true
|
|
1619
|
+
from active_registry registry cross join names
|
|
1620
|
+
), raw_memberships as (
|
|
1548
1621
|
select granted.rolname::name granted_role,member.rolname::name member_role,
|
|
1549
1622
|
membership.admin_option,
|
|
1550
1623
|
coalesce((to_jsonb(membership)->>'inherit_option')::boolean,true) inherit_option,
|
|
1551
1624
|
coalesce((to_jsonb(membership)->>'set_option')::boolean,true) set_option,
|
|
1552
|
-
grantor.
|
|
1625
|
+
membership.grantor,member.oid member_oid
|
|
1553
1626
|
from pg_catalog.pg_auth_members membership
|
|
1554
1627
|
join pg_catalog.pg_roles granted on granted.oid=membership.roleid
|
|
1555
1628
|
join pg_catalog.pg_roles member on member.oid=membership.member
|
|
1556
|
-
join pg_catalog.pg_roles grantor on grantor.oid=membership.grantor
|
|
1557
1629
|
where granted.rolname=(select archive_role from names)
|
|
1630
|
+
), actual_memberships as (
|
|
1631
|
+
select membership.granted_role,membership.member_role,
|
|
1632
|
+
bool_or(membership.admin_option) admin_option,
|
|
1633
|
+
bool_or(membership.inherit_option) inherit_option,
|
|
1634
|
+
bool_or(membership.set_option) set_option,
|
|
1635
|
+
bool_and(case when membership.member_role=names.schema_owner then
|
|
1636
|
+
(membership.grantor=10 and membership.admin_option
|
|
1637
|
+
and membership.inherit_option=membership.set_option)
|
|
1638
|
+
or (membership.grantor=membership.member_oid
|
|
1639
|
+
and membership.inherit_option and membership.set_option)
|
|
1640
|
+
else membership.grantor=(select oid from pg_catalog.pg_roles where rolname=names.schema_owner)
|
|
1641
|
+
and not membership.admin_option
|
|
1642
|
+
and membership.inherit_option and membership.set_option end) grants_valid
|
|
1643
|
+
from raw_memberships membership cross join names
|
|
1644
|
+
group by membership.granted_role,membership.member_role
|
|
1558
1645
|
)
|
|
1559
1646
|
select current_setting('server_version_num')::integer/10000=any(array[15,16,17,18])
|
|
1560
1647
|
and exists(select 1 from pg_catalog.pg_roles role,names where role.rolname=names.archive_role
|
|
@@ -1565,15 +1652,13 @@ returns boolean language sql stable security definer set search_path = '' as $$
|
|
|
1565
1652
|
) from agent_bridge.portable_archive_attestations attestation
|
|
1566
1653
|
where attestation.name='portable-archive-v1')
|
|
1567
1654
|
and not exists(
|
|
1568
|
-
(select granted_role,member_role,admin_option from actual_memberships
|
|
1569
|
-
except select granted_role,member_role,admin_option from expected_memberships)
|
|
1655
|
+
(select granted_role,member_role,admin_option,inherit_option,set_option from actual_memberships
|
|
1656
|
+
except select granted_role,member_role,admin_option,inherit_option,set_option from expected_memberships)
|
|
1570
1657
|
union all
|
|
1571
|
-
(select granted_role,member_role,admin_option from expected_memberships
|
|
1572
|
-
except select granted_role,member_role,admin_option from actual_memberships)
|
|
1658
|
+
(select granted_role,member_role,admin_option,inherit_option,set_option from expected_memberships
|
|
1659
|
+
except select granted_role,member_role,admin_option,inherit_option,set_option from actual_memberships)
|
|
1573
1660
|
)
|
|
1574
|
-
and not exists(select 1 from actual_memberships membership
|
|
1575
|
-
where not membership.inherit_option or not membership.set_option
|
|
1576
|
-
or membership.grantor_role<>names.schema_owner)
|
|
1661
|
+
and not exists(select 1 from actual_memberships membership where not membership.grants_valid)
|
|
1577
1662
|
and not exists(select 1 from active_registry registry
|
|
1578
1663
|
left join pg_catalog.pg_roles role on role.rolname=registry.member_role
|
|
1579
1664
|
where role.oid is null or not role.rolcanlogin or role.rolsuper or role.rolcreaterole
|
|
@@ -1706,27 +1791,42 @@ returns boolean language sql stable security definer set search_path = '' as $$
|
|
|
1706
1791
|
), active_registry as (
|
|
1707
1792
|
select member_role,control_role from latest_registry where action='register'
|
|
1708
1793
|
), expected_memberships as (
|
|
1709
|
-
select names.owner_role granted_role,names.schema_owner member_role,
|
|
1794
|
+
select names.owner_role granted_role,names.schema_owner member_role,
|
|
1795
|
+
true admin_option,true inherit_option,true set_option
|
|
1710
1796
|
from names
|
|
1711
|
-
union all select names.operator_role,names.schema_owner,true from names
|
|
1712
|
-
union all select names.auditor_role,names.schema_owner,true from names
|
|
1797
|
+
union all select names.operator_role,names.schema_owner,true,true,true from names
|
|
1798
|
+
union all select names.auditor_role,names.schema_owner,true,true,true from names
|
|
1713
1799
|
union all
|
|
1714
1800
|
select case registry.control_role when 'operator' then names.operator_role
|
|
1715
|
-
else names.auditor_role end,registry.member_role,false
|
|
1801
|
+
else names.auditor_role end,registry.member_role,false,true,true
|
|
1716
1802
|
from active_registry registry cross join names
|
|
1717
|
-
),
|
|
1803
|
+
), raw_memberships as (
|
|
1718
1804
|
select granted.rolname::name granted_role,member.rolname::name member_role,
|
|
1719
1805
|
membership.admin_option,
|
|
1720
1806
|
coalesce((to_jsonb(membership)->>'inherit_option')::boolean,true) inherit_option,
|
|
1721
1807
|
coalesce((to_jsonb(membership)->>'set_option')::boolean,true) set_option,
|
|
1722
|
-
grantor.
|
|
1808
|
+
membership.grantor,member.oid member_oid
|
|
1723
1809
|
from pg_catalog.pg_auth_members membership
|
|
1724
1810
|
join pg_catalog.pg_roles granted on granted.oid=membership.roleid
|
|
1725
1811
|
join pg_catalog.pg_roles member on member.oid=membership.member
|
|
1726
|
-
join pg_catalog.pg_roles grantor on grantor.oid=membership.grantor
|
|
1727
1812
|
where granted.rolname in (
|
|
1728
1813
|
(select owner_role from names),(select operator_role from names),(select auditor_role from names)
|
|
1729
1814
|
)
|
|
1815
|
+
), actual_memberships as (
|
|
1816
|
+
select membership.granted_role,membership.member_role,
|
|
1817
|
+
bool_or(membership.admin_option) admin_option,
|
|
1818
|
+
bool_or(membership.inherit_option) inherit_option,
|
|
1819
|
+
bool_or(membership.set_option) set_option,
|
|
1820
|
+
bool_and(case when membership.member_role=names.schema_owner then
|
|
1821
|
+
(membership.grantor=10 and membership.admin_option
|
|
1822
|
+
and membership.inherit_option=membership.set_option)
|
|
1823
|
+
or (membership.grantor=membership.member_oid
|
|
1824
|
+
and membership.inherit_option and membership.set_option)
|
|
1825
|
+
else membership.grantor=(select oid from pg_catalog.pg_roles where rolname=names.schema_owner)
|
|
1826
|
+
and not membership.admin_option
|
|
1827
|
+
and membership.inherit_option and membership.set_option end) grants_valid
|
|
1828
|
+
from raw_memberships membership cross join names
|
|
1829
|
+
group by membership.granted_role,membership.member_role
|
|
1730
1830
|
), authority_closure as (
|
|
1731
1831
|
select control_role.granted_role,candidate.rolname::name member_role
|
|
1732
1832
|
from names
|
|
@@ -1745,16 +1845,14 @@ returns boolean language sql stable security definer set search_path = '' as $$
|
|
|
1745
1845
|
) from agent_bridge.owner_control_attestations attestation
|
|
1746
1846
|
where attestation.name='owner-control-v2')
|
|
1747
1847
|
and not exists (
|
|
1748
|
-
(select granted_role,member_role,admin_option from actual_memberships
|
|
1749
|
-
except select granted_role,member_role,admin_option from expected_memberships)
|
|
1848
|
+
(select granted_role,member_role,admin_option,inherit_option,set_option from actual_memberships
|
|
1849
|
+
except select granted_role,member_role,admin_option,inherit_option,set_option from expected_memberships)
|
|
1750
1850
|
union all
|
|
1751
|
-
(select granted_role,member_role,admin_option from expected_memberships
|
|
1752
|
-
except select granted_role,member_role,admin_option from actual_memberships)
|
|
1851
|
+
(select granted_role,member_role,admin_option,inherit_option,set_option from expected_memberships
|
|
1852
|
+
except select granted_role,member_role,admin_option,inherit_option,set_option from actual_memberships)
|
|
1753
1853
|
)
|
|
1754
1854
|
and not exists (
|
|
1755
|
-
select 1 from actual_memberships membership
|
|
1756
|
-
where not membership.inherit_option or not membership.set_option
|
|
1757
|
-
or membership.grantor_role<>names.schema_owner
|
|
1855
|
+
select 1 from actual_memberships membership where not membership.grants_valid
|
|
1758
1856
|
)
|
|
1759
1857
|
and not exists (
|
|
1760
1858
|
select 1 from active_registry registry
|
|
@@ -1792,8 +1890,12 @@ returns boolean language sql stable security definer set search_path = '' as $$
|
|
|
1792
1890
|
)
|
|
1793
1891
|
$$;
|
|
1794
1892
|
|
|
1893
|
+
select set_config(
|
|
1894
|
+
'role','agent_bridge_control_owner_'||substr(md5(current_database()),1,16),false
|
|
1895
|
+
);
|
|
1795
1896
|
insert into agent_bridge.owner_control_attestations(name,catalog_definition)
|
|
1796
1897
|
values('owner-control-v2',agent_bridge.owner_control_catalog_definition());
|
|
1898
|
+
reset role;
|
|
1797
1899
|
|
|
1798
1900
|
insert into agent_bridge.portable_archive_attestations(name,catalog_definition)
|
|
1799
1901
|
values('portable-archive-v1',agent_bridge.portable_archive_catalog_definition());
|