@creatornader/agent-bridge 0.4.0 → 0.5.1
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 +85 -1
- package/README.md +76 -7
- package/ROADMAP.md +29 -0
- package/SECURITY.md +30 -0
- package/SKILL.md +5 -1
- package/dist/archive.d.ts +2 -2
- package/dist/{bridge-service-YTjGr91A.d.ts → bridge-service-CNBKdYXh.d.ts} +2 -1
- package/dist/{bridge-store-Boaj-ZbO.d.ts → bridge-store-ByJ6CaJk.d.ts} +1 -0
- package/dist/bridge.d.ts +15 -8
- package/dist/bridge.js +10 -8
- package/dist/{chunk-PDIHDBP3.js → chunk-7VJI2MXI.js} +116 -26
- 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-IHZFI7TH.js → chunk-E4OWHGUE.js} +5 -2
- package/dist/chunk-E4OWHGUE.js.map +1 -0
- package/dist/{chunk-SYGONYMM.js → chunk-HUHG7XTB.js} +6 -5
- package/dist/chunk-HUHG7XTB.js.map +1 -0
- package/dist/{chunk-DQOZJJZ2.js → chunk-IVG4XWWS.js} +5 -5
- package/dist/{chunk-DQOZJJZ2.js.map → chunk-IVG4XWWS.js.map} +1 -1
- package/dist/{chunk-3YHVUPU2.js → chunk-P635FAN4.js} +4 -4
- package/dist/chunk-P635FAN4.js.map +1 -0
- package/dist/{chunk-6BTJE6D4.js → chunk-QNXHDOJ5.js} +56 -23
- package/dist/chunk-QNXHDOJ5.js.map +1 -0
- package/dist/{chunk-MCKKVNCE.js → chunk-QPC6JHA3.js} +5 -5
- package/dist/{chunk-SV3SVBYS.js → chunk-SN7PIVDF.js} +2 -2
- package/dist/{chunk-2DFNOLMO.js → chunk-XDNT6ZNZ.js} +9 -6
- package/dist/chunk-XDNT6ZNZ.js.map +1 -0
- package/dist/{chunk-LAHNQZDN.js → chunk-Z6JP6MYD.js} +2 -2
- package/dist/cli.js +9 -9
- package/dist/cli.js.map +1 -1
- package/dist/client-runtime.d.ts +3 -3
- package/dist/client-runtime.js +6 -6
- package/dist/contracts/generate.js +1 -1
- package/dist/dr.js +3 -3
- package/dist/{gateway-BQHpV-MZ.d.ts → gateway-CW-61lvs.d.ts} +2 -2
- 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 +7 -7
- package/dist/{postgres-bridge-store-WASumj26.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 +7 -7
- package/dist/{sqlite-edge-store-Bc15DvpX.d.ts → sqlite-edge-store-CdMIOrho.d.ts} +1 -1
- package/dist/sqlite.d.ts +3 -3
- package/dist/sqlite.js +2 -2
- package/docs/architecture-v2.md +36 -5
- package/docs/deployment.md +157 -0
- package/llms.txt +2 -1
- package/openapi/agent-bridge-v2.openapi.json +5 -1
- package/package.json +5 -1
- package/schemas/agent-bridge-v2.capabilities.json +2 -1
- package/schemas/agent-bridge-v2.mcp.json +5 -1
- package/schemas/agent-bridge-v2.schema.json +4 -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/018_endpoint_migration_challenges.sql +36 -10
- package/sql/migrations/019_endpoint_migration_same_successor.sql +34 -10
- 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-3YHVUPU2.js.map +0 -1
- package/dist/chunk-4VB44KJU.js.map +0 -1
- package/dist/chunk-6BTJE6D4.js.map +0 -1
- package/dist/chunk-IHZFI7TH.js.map +0 -1
- package/dist/chunk-PDIHDBP3.js.map +0 -1
- package/dist/chunk-SYGONYMM.js.map +0 -1
- /package/dist/{chunk-MCKKVNCE.js.map → chunk-QPC6JHA3.js.map} +0 -0
- /package/dist/{chunk-SV3SVBYS.js.map → chunk-SN7PIVDF.js.map} +0 -0
- /package/dist/{chunk-LAHNQZDN.js.map → chunk-Z6JP6MYD.js.map} +0 -0
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
isSupportedLocalSqliteSchemaContract,
|
|
11
11
|
sqliteSchemaContractHash,
|
|
12
12
|
verifySqliteHealth
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-IVG4XWWS.js";
|
|
14
14
|
import {
|
|
15
15
|
preparePrivateFileLocation,
|
|
16
16
|
preparePrivateSqliteLocation,
|
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
import {
|
|
22
22
|
NATIVE_DR_ADVISORY_LOCK_KEY,
|
|
23
23
|
rowIsolationReady
|
|
24
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-QNXHDOJ5.js";
|
|
25
25
|
|
|
26
26
|
// src/native-dr-bundle.ts
|
|
27
27
|
import { createHash } from "crypto";
|
|
@@ -487,7 +487,7 @@ var SSL_PARAMETERS = /* @__PURE__ */ new Set([
|
|
|
487
487
|
"sslrootcert",
|
|
488
488
|
"sslsni"
|
|
489
489
|
]);
|
|
490
|
-
var DERIVED_ROLE = /^agent_bridge_(?:runtime|data_owner|context_reader|event_writer|control_owner|control_operator|control_auditor|archive_operator)_[0-9a-f]{16}$/;
|
|
490
|
+
var DERIVED_ROLE = /^agent_bridge_(?:runtime|data_owner|context_reader|event_writer|control_owner|control_operator|control_auditor|archive_operator|backup_reader)_[0-9a-f]{16}$/;
|
|
491
491
|
var ROLE_NAME = /^[^\u0000-\u001f\u007f]{1,63}$/u;
|
|
492
492
|
function validPostgresIdentifier(value) {
|
|
493
493
|
return value !== "PUBLIC" && !value.includes(":") && ROLE_NAME.test(value) && Buffer.byteLength(value, "utf8") <= 63;
|
|
@@ -934,21 +934,62 @@ function buildPostgresMembershipStatements(inventory, serverMajor2) {
|
|
|
934
934
|
if (!Number.isSafeInteger(serverMajor2) || serverMajor2 < 15 || serverMajor2 > 18) {
|
|
935
935
|
throw new Error("PostgreSQL membership target major must be between 15 and 18");
|
|
936
936
|
}
|
|
937
|
-
|
|
937
|
+
const validated = validatePostgresRoleInventory(inventory);
|
|
938
|
+
const schemaOwner = validated.roles.find((role) => role.kind === "schema-owner");
|
|
939
|
+
const rolesByName = new Map(validated.roles.map((role) => [role.name, role]));
|
|
940
|
+
const orderedMemberships = [...validated.memberships].sort((left, right) => {
|
|
941
|
+
const leftOwnerAuthority = left.member === schemaOwner.name ? 0 : 1;
|
|
942
|
+
const rightOwnerAuthority = right.member === schemaOwner.name ? 0 : 1;
|
|
943
|
+
return leftOwnerAuthority - rightOwnerAuthority || left.role.localeCompare(right.role) || left.member.localeCompare(right.member);
|
|
944
|
+
});
|
|
945
|
+
return orderedMemberships.filter(
|
|
946
|
+
(membership) => rolesByName.get(membership.member).kind !== "external-principal"
|
|
947
|
+
).map((membership) => {
|
|
948
|
+
let grant;
|
|
938
949
|
if (serverMajor2 === 15) {
|
|
939
950
|
if (!membership.inheritOption || !membership.setOption) {
|
|
940
951
|
throw new Error("PostgreSQL 15 cannot preserve membership INHERIT FALSE or SET FALSE semantics");
|
|
941
952
|
}
|
|
942
|
-
|
|
943
|
-
}
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
953
|
+
grant = `GRANT ${quoteIdentifier(membership.role)} TO ${quoteIdentifier(membership.member)}${membership.adminOption ? " WITH ADMIN OPTION" : ""};`;
|
|
954
|
+
} else {
|
|
955
|
+
const options = [
|
|
956
|
+
`ADMIN ${membership.adminOption ? "OPTION" : "FALSE"}`,
|
|
957
|
+
`INHERIT ${membership.inheritOption ? "TRUE" : "FALSE"}`,
|
|
958
|
+
`SET ${membership.setOption ? "TRUE" : "FALSE"}`
|
|
959
|
+
].join(", ");
|
|
960
|
+
grant = `GRANT ${quoteIdentifier(membership.role)} TO ${quoteIdentifier(membership.member)} WITH ${options};`;
|
|
961
|
+
}
|
|
962
|
+
const role = rolesByName.get(membership.role);
|
|
963
|
+
const schemaOwnerGrantedDerivedMembership = membership.member !== schemaOwner.name && role.kind === "derived";
|
|
964
|
+
return schemaOwnerGrantedDerivedMembership ? `SET LOCAL ROLE ${quoteIdentifier(schemaOwner.name)}; ${grant} RESET ROLE;` : grant;
|
|
950
965
|
});
|
|
951
966
|
}
|
|
967
|
+
function suspendedPostgresMemberships(inventory) {
|
|
968
|
+
const suffix = createHash2("md5").update(inventory.databaseName).digest("hex").slice(0, 16);
|
|
969
|
+
const recognizedRoles = /* @__PURE__ */ new Map([
|
|
970
|
+
[`agent_bridge_control_operator_${suffix}`, "operator"],
|
|
971
|
+
[`agent_bridge_control_auditor_${suffix}`, "auditor"],
|
|
972
|
+
[`agent_bridge_archive_operator_${suffix}`, "archive"]
|
|
973
|
+
]);
|
|
974
|
+
const rolesByName = new Map(inventory.roles.map((role) => [role.name, role]));
|
|
975
|
+
const suspended = [];
|
|
976
|
+
for (const membership of inventory.memberships) {
|
|
977
|
+
if (rolesByName.get(membership.member)?.kind !== "external-principal") continue;
|
|
978
|
+
const recognized = recognizedRoles.get(membership.role);
|
|
979
|
+
if (recognized === "archive") {
|
|
980
|
+
suspended.push({ kind: "archive", member: membership.member });
|
|
981
|
+
continue;
|
|
982
|
+
}
|
|
983
|
+
if (recognized === "operator" || recognized === "auditor") {
|
|
984
|
+
suspended.push({
|
|
985
|
+
kind: "control",
|
|
986
|
+
member: membership.member,
|
|
987
|
+
controlRole: recognized
|
|
988
|
+
});
|
|
989
|
+
}
|
|
990
|
+
}
|
|
991
|
+
return suspended;
|
|
992
|
+
}
|
|
952
993
|
var DEFAULT_PRIVILEGE_OBJECTS = {
|
|
953
994
|
r: "TABLES",
|
|
954
995
|
S: "SEQUENCES",
|
|
@@ -1221,7 +1262,8 @@ async function collectPostgresRoleInventory(client, databaseName) {
|
|
|
1221
1262
|
FROM unnest(ARRAY[
|
|
1222
1263
|
'agent_bridge_runtime_','agent_bridge_data_owner_','agent_bridge_context_reader_',
|
|
1223
1264
|
'agent_bridge_event_writer_','agent_bridge_control_owner_','agent_bridge_control_operator_',
|
|
1224
|
-
'agent_bridge_control_auditor_','agent_bridge_archive_operator_'
|
|
1265
|
+
'agent_bridge_control_auditor_','agent_bridge_archive_operator_',
|
|
1266
|
+
'agent_bridge_backup_reader_'
|
|
1225
1267
|
]) prefix
|
|
1226
1268
|
), object_roles AS (
|
|
1227
1269
|
SELECT namespace.nspowner AS oid, 'schema-owner'::text AS kind
|
|
@@ -1300,13 +1342,14 @@ async function collectPostgresRoleInventory(client, databaseName) {
|
|
|
1300
1342
|
const names = roleRows.rows.map((row) => row.name);
|
|
1301
1343
|
const membershipRows = names.length === 0 ? { rows: [], rowCount: 0 } : await client.query(`
|
|
1302
1344
|
SELECT granted.rolname AS role, member.rolname AS member,
|
|
1303
|
-
membership.admin_option AS "adminOption",
|
|
1304
|
-
coalesce((to_jsonb(membership)->>'inherit_option')::boolean,true) AS "inheritOption",
|
|
1305
|
-
coalesce((to_jsonb(membership)->>'set_option')::boolean,true) AS "setOption"
|
|
1345
|
+
bool_or(membership.admin_option) AS "adminOption",
|
|
1346
|
+
bool_or(coalesce((to_jsonb(membership)->>'inherit_option')::boolean,true)) AS "inheritOption",
|
|
1347
|
+
bool_or(coalesce((to_jsonb(membership)->>'set_option')::boolean,true)) AS "setOption"
|
|
1306
1348
|
FROM pg_catalog.pg_auth_members membership
|
|
1307
1349
|
JOIN pg_catalog.pg_roles granted ON granted.oid=membership.roleid
|
|
1308
1350
|
JOIN pg_catalog.pg_roles member ON member.oid=membership.member
|
|
1309
1351
|
WHERE granted.rolname=ANY($1::text[]) AND member.rolname=ANY($1::text[])
|
|
1352
|
+
GROUP BY granted.rolname,member.rolname
|
|
1310
1353
|
ORDER BY granted.rolname,member.rolname`, [names]);
|
|
1311
1354
|
if (names.length > 0) {
|
|
1312
1355
|
const boundary = await client.query(`
|
|
@@ -1395,8 +1438,11 @@ async function collectSnapshotMetadata(client, checkRowReady) {
|
|
|
1395
1438
|
if (migrations.length === 0) throw new PostgresNativeDrError("SOURCE_SCHEMA_EMPTY", "source has no Agent Bridge migrations");
|
|
1396
1439
|
const schemaVersion = Math.max(...migrations.map((migration) => migration.version));
|
|
1397
1440
|
const tableRows = await client.query(`
|
|
1398
|
-
SELECT
|
|
1399
|
-
|
|
1441
|
+
SELECT relation.relname AS "tableName"
|
|
1442
|
+
FROM pg_catalog.pg_class relation
|
|
1443
|
+
JOIN pg_catalog.pg_namespace namespace ON namespace.oid=relation.relnamespace
|
|
1444
|
+
WHERE namespace.nspname='agent_bridge' AND relation.relkind IN ('r','p')
|
|
1445
|
+
ORDER BY relation.relname`);
|
|
1400
1446
|
const tableCounts = {};
|
|
1401
1447
|
for (const row of tableRows.rows) {
|
|
1402
1448
|
const qualified = `agent_bridge.${row.tableName}`;
|
|
@@ -1407,6 +1453,9 @@ async function collectSnapshotMetadata(client, checkRowReady) {
|
|
|
1407
1453
|
if (!value || !/^(?:0|[1-9][0-9]*)$/u.test(value)) throw new PostgresNativeDrError("SOURCE_COUNT_INVALID", `source count is invalid for ${qualified}`);
|
|
1408
1454
|
tableCounts[qualified] = value;
|
|
1409
1455
|
}
|
|
1456
|
+
if (!tableRows.rows.some((row) => row.tableName === "deliveries")) {
|
|
1457
|
+
throw new PostgresNativeDrError("SOURCE_COUNT_INVALID", "source deliveries table is unavailable");
|
|
1458
|
+
}
|
|
1410
1459
|
const claimed = await client.query(
|
|
1411
1460
|
`SELECT count(*)::text AS count FROM agent_bridge.deliveries WHERE state='claimed'`
|
|
1412
1461
|
);
|
|
@@ -1418,6 +1467,7 @@ async function collectSnapshotMetadata(client, checkRowReady) {
|
|
|
1418
1467
|
SELECT agent_bridge.security_schema_ready() AS security,
|
|
1419
1468
|
agent_bridge.owner_control_plane_ready() AS "ownerControl",
|
|
1420
1469
|
agent_bridge.portable_archive_ready() AS "portableArchive",
|
|
1470
|
+
${schemaVersion >= 21 ? 'agent_bridge.native_backup_ready() AS "nativeBackup",' : ""}
|
|
1421
1471
|
agent_bridge.credential_security_prerequisite_definition() AS "securityDefinition",
|
|
1422
1472
|
agent_bridge.row_isolation_catalog_definition() AS "rowIsolationDefinition",
|
|
1423
1473
|
agent_bridge.owner_control_attestation_definition() AS "ownerControlDefinition",
|
|
@@ -1425,7 +1475,7 @@ async function collectSnapshotMetadata(client, checkRowReady) {
|
|
|
1425
1475
|
const ready = readiness.rows[0];
|
|
1426
1476
|
const rowReady = await checkRowReady(client);
|
|
1427
1477
|
const authorityReady = await gatewayAuthorityReady(client, schemaVersion);
|
|
1428
|
-
if (!ready?.security || !rowReady || !ready.ownerControl || !ready.portableArchive || !authorityReady || typeof ready.securityDefinition !== "string" || typeof ready.rowIsolationDefinition !== "string" || typeof ready.ownerControlDefinition !== "string" || typeof ready.portableArchiveDefinition !== "string") {
|
|
1478
|
+
if (!ready?.security || !rowReady || !ready.ownerControl || !ready.portableArchive || schemaVersion >= 21 && !ready.nativeBackup || !authorityReady || typeof ready.securityDefinition !== "string" || typeof ready.rowIsolationDefinition !== "string" || typeof ready.ownerControlDefinition !== "string" || typeof ready.portableArchiveDefinition !== "string") {
|
|
1429
1479
|
throw new PostgresNativeDrError("SOURCE_NOT_READY", "source PostgreSQL schema failed readiness attestation");
|
|
1430
1480
|
}
|
|
1431
1481
|
return {
|
|
@@ -1819,12 +1869,24 @@ async function targetTableCounts(client) {
|
|
|
1819
1869
|
}
|
|
1820
1870
|
return counts;
|
|
1821
1871
|
}
|
|
1822
|
-
function expectedRestoredTableCounts(schema) {
|
|
1872
|
+
function expectedRestoredTableCounts(schema, suspendedMemberships) {
|
|
1823
1873
|
const expected = { ...schema.tableCounts };
|
|
1824
1874
|
for (const table of excludedDataTablesForSchemaVersion(schema.schemaVersion)) expected[table] = "0";
|
|
1825
1875
|
const deliveryEvents = expected["agent_bridge.delivery_events"];
|
|
1826
1876
|
if (deliveryEvents === void 0) throw new PostgresNativeDrError("INVALID_MANIFEST", "PostgreSQL delivery event count is missing");
|
|
1827
1877
|
expected["agent_bridge.delivery_events"] = (BigInt(deliveryEvents) + BigInt(schema.claimedDeliveryCount)).toString();
|
|
1878
|
+
for (const [kind, table] of [
|
|
1879
|
+
["control", "agent_bridge.control_membership_events"],
|
|
1880
|
+
["archive", "agent_bridge.archive_membership_events"]
|
|
1881
|
+
]) {
|
|
1882
|
+
const increment = suspendedMemberships.filter((membership) => membership.kind === kind).length;
|
|
1883
|
+
if (increment === 0) continue;
|
|
1884
|
+
const current = expected[table];
|
|
1885
|
+
if (current === void 0) {
|
|
1886
|
+
throw new PostgresNativeDrError("INVALID_MANIFEST", `PostgreSQL ${kind} membership event count is missing`);
|
|
1887
|
+
}
|
|
1888
|
+
expected[table] = (BigInt(current) + BigInt(increment)).toString();
|
|
1889
|
+
}
|
|
1828
1890
|
return expected;
|
|
1829
1891
|
}
|
|
1830
1892
|
function compareStringMaps(actual, expected, label) {
|
|
@@ -1915,11 +1977,17 @@ async function restorePostgresNativeDrInternal(options) {
|
|
|
1915
1977
|
if (metadata.schemaExists || !metadata.databaseFresh) {
|
|
1916
1978
|
throw new PostgresNativeDrError("TARGET_NOT_FRESH", "target must be a dedicated fresh database without user objects or default ACLs");
|
|
1917
1979
|
}
|
|
1980
|
+
const schemaOwner = inventory.roles.find((role) => role.kind === "schema-owner");
|
|
1918
1981
|
const conflicts = await target.query(
|
|
1919
|
-
`SELECT rolname AS name
|
|
1982
|
+
`SELECT rolname AS name,rolname=current_user AS "isCurrentUser",
|
|
1983
|
+
rolsuper "isSuperuser"
|
|
1984
|
+
FROM pg_catalog.pg_roles WHERE rolname=ANY($1::text[]) ORDER BY rolname`,
|
|
1920
1985
|
[inventory.roles.map((role) => role.name)]
|
|
1921
1986
|
);
|
|
1922
|
-
|
|
1987
|
+
const reusesSchemaOwner = conflicts.rows.length === 1 && conflicts.rows[0]?.name === schemaOwner.name && conflicts.rows[0].isCurrentUser && conflicts.rows[0].isSuperuser;
|
|
1988
|
+
if (conflicts.rows.length > 0 && !reusesSchemaOwner) {
|
|
1989
|
+
throw new PostgresNativeDrError("TARGET_ROLE_CONFLICT", "target contains a role required by the backup");
|
|
1990
|
+
}
|
|
1923
1991
|
await assertPostgresRestoreAuthority(target);
|
|
1924
1992
|
admin = deps.createClient(administrativeDatabaseUrl(targetUrl, metadata.databaseName));
|
|
1925
1993
|
await admin.connect();
|
|
@@ -1929,12 +1997,13 @@ async function restorePostgresNativeDrInternal(options) {
|
|
|
1929
1997
|
securePrivatePath(schemaAclListPath, "file");
|
|
1930
1998
|
verifyPrivatePathAccess(schemaAclListPath, "file");
|
|
1931
1999
|
for (const [index, statement] of buildPostgresRoleShellStatements(inventory).entries()) {
|
|
2000
|
+
const role = inventory.roles[index];
|
|
2001
|
+
if (reusesSchemaOwner && role.name === schemaOwner.name) continue;
|
|
1932
2002
|
phase = "role shell creation";
|
|
1933
2003
|
restoreStarted = true;
|
|
1934
2004
|
await target.query(statement);
|
|
1935
|
-
createdRoles.push(
|
|
2005
|
+
createdRoles.push(role.name);
|
|
1936
2006
|
}
|
|
1937
|
-
const schemaOwner = inventory.roles.find((role) => role.kind === "schema-owner");
|
|
1938
2007
|
phase = "schema creation";
|
|
1939
2008
|
await target.query(`CREATE SCHEMA agent_bridge AUTHORIZATION ${quoteIdentifier(schemaOwner.name)}`);
|
|
1940
2009
|
phase = "schema ACL restore";
|
|
@@ -1965,6 +2034,25 @@ async function restorePostgresNativeDrInternal(options) {
|
|
|
1965
2034
|
transactionOpen = true;
|
|
1966
2035
|
phase = "membership restore";
|
|
1967
2036
|
for (const statement of buildPostgresMembershipStatements(inventory, major)) await target.query(statement);
|
|
2037
|
+
const suspendedMemberships = suspendedPostgresMemberships(inventory);
|
|
2038
|
+
phase = "external membership suspension";
|
|
2039
|
+
for (const membership of suspendedMemberships) {
|
|
2040
|
+
if (membership.kind === "control") {
|
|
2041
|
+
await target.query(
|
|
2042
|
+
`INSERT INTO agent_bridge.control_membership_events(
|
|
2043
|
+
request_id,action,member_role,control_role,actor
|
|
2044
|
+
) VALUES($1::uuid,'revoke',$2::name,$3,$4::name)`,
|
|
2045
|
+
[deps.randomId(), membership.member, membership.controlRole, schemaOwner.name]
|
|
2046
|
+
);
|
|
2047
|
+
} else {
|
|
2048
|
+
await target.query(
|
|
2049
|
+
`INSERT INTO agent_bridge.archive_membership_events(
|
|
2050
|
+
request_id,action,member_role,actor
|
|
2051
|
+
) VALUES($1::uuid,'revoke',$2::name,$3::name)`,
|
|
2052
|
+
[deps.randomId(), membership.member, schemaOwner.name]
|
|
2053
|
+
);
|
|
2054
|
+
}
|
|
2055
|
+
}
|
|
1968
2056
|
phase = "default privilege restore";
|
|
1969
2057
|
for (const statement of buildPostgresDefaultPrivilegeStatements(inventory)) await target.query(statement);
|
|
1970
2058
|
phase = "claim normalization";
|
|
@@ -1990,12 +2078,13 @@ async function restorePostgresNativeDrInternal(options) {
|
|
|
1990
2078
|
}
|
|
1991
2079
|
phase = "table count validation";
|
|
1992
2080
|
const counts = await targetTableCounts(target);
|
|
1993
|
-
compareStringMaps(counts, expectedRestoredTableCounts(schema), "restored PostgreSQL");
|
|
2081
|
+
compareStringMaps(counts, expectedRestoredTableCounts(schema, suspendedMemberships), "restored PostgreSQL");
|
|
1994
2082
|
phase = "readiness validation";
|
|
1995
2083
|
const readiness = await target.query(`
|
|
1996
2084
|
SELECT agent_bridge.security_schema_ready() AS security,
|
|
1997
2085
|
agent_bridge.owner_control_plane_ready() AS "ownerControl",
|
|
1998
2086
|
agent_bridge.portable_archive_ready() AS "portableArchive",
|
|
2087
|
+
${schema.schemaVersion >= 21 ? 'agent_bridge.native_backup_ready() AS "nativeBackup",' : ""}
|
|
1999
2088
|
agent_bridge.credential_security_prerequisite_definition() AS "securityDefinition",
|
|
2000
2089
|
agent_bridge.row_isolation_catalog_definition() AS "rowIsolationDefinition",
|
|
2001
2090
|
agent_bridge.owner_control_attestation_definition() AS "ownerControlDefinition",
|
|
@@ -2008,6 +2097,7 @@ async function restorePostgresNativeDrInternal(options) {
|
|
|
2008
2097
|
!restoredRowReady ? "row-isolation" : void 0,
|
|
2009
2098
|
!ready?.ownerControl ? "owner-control" : void 0,
|
|
2010
2099
|
!ready?.portableArchive ? "portable-archive" : void 0,
|
|
2100
|
+
schema.schemaVersion >= 21 && !ready?.nativeBackup ? "native-backup" : void 0,
|
|
2011
2101
|
!restoredGatewayAuthorityReady ? "gateway-authority" : void 0
|
|
2012
2102
|
].filter(Boolean);
|
|
2013
2103
|
if (failedReadiness.length > 0) {
|
|
@@ -2578,4 +2668,4 @@ export {
|
|
|
2578
2668
|
restoreLocalSqlite,
|
|
2579
2669
|
SQLITE_EDGE_APPLICATION_ID
|
|
2580
2670
|
};
|
|
2581
|
-
//# sourceMappingURL=chunk-
|
|
2671
|
+
//# sourceMappingURL=chunk-7VJI2MXI.js.map
|