pg-admin-mcp 0.0.0-stage → 0.1.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/README.md +608 -2
- package/dist/config/env.js +67 -0
- package/dist/config/env.js.map +1 -0
- package/dist/config/profiles.js +257 -0
- package/dist/config/profiles.js.map +1 -0
- package/dist/core/audit-context.js +21 -0
- package/dist/core/audit-context.js.map +1 -0
- package/dist/core/audit.js +91 -0
- package/dist/core/audit.js.map +1 -0
- package/dist/core/brands.js +24 -0
- package/dist/core/brands.js.map +1 -0
- package/dist/core/classifier.js +279 -0
- package/dist/core/classifier.js.map +1 -0
- package/dist/core/errors.js +197 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/format.js +258 -0
- package/dist/core/format.js.map +1 -0
- package/dist/core/guards.js +513 -0
- package/dist/core/guards.js.map +1 -0
- package/dist/core/identifiers.js +431 -0
- package/dist/core/identifiers.js.map +1 -0
- package/dist/core/limits.js +79 -0
- package/dist/core/limits.js.map +1 -0
- package/dist/core/logger.js +34 -0
- package/dist/core/logger.js.map +1 -0
- package/dist/core/paginate.js +195 -0
- package/dist/core/paginate.js.map +1 -0
- package/dist/core/paths.js +392 -0
- package/dist/core/paths.js.map +1 -0
- package/dist/core/policy.js +98 -0
- package/dist/core/policy.js.map +1 -0
- package/dist/core/shutdown.js +10 -0
- package/dist/core/shutdown.js.map +1 -0
- package/dist/core/stdout-guard.js +25 -0
- package/dist/core/stdout-guard.js.map +1 -0
- package/dist/db/catalog.js +1006 -0
- package/dist/db/catalog.js.map +1 -0
- package/dist/db/pool.js +158 -0
- package/dist/db/pool.js.map +1 -0
- package/dist/db/session.js +258 -0
- package/dist/db/session.js.map +1 -0
- package/dist/db/types.js +2 -0
- package/dist/db/types.js.map +1 -0
- package/dist/index.js +91 -0
- package/dist/index.js.map +1 -0
- package/dist/resources/index.js +88 -0
- package/dist/resources/index.js.map +1 -0
- package/dist/runtime/binaries.js +356 -0
- package/dist/runtime/binaries.js.map +1 -0
- package/dist/runtime/env-file.js +62 -0
- package/dist/runtime/env-file.js.map +1 -0
- package/dist/runtime/environment.js +34 -0
- package/dist/runtime/environment.js.map +1 -0
- package/dist/server.js +106 -0
- package/dist/server.js.map +1 -0
- package/dist/snapshot/capture.js +189 -0
- package/dist/snapshot/capture.js.map +1 -0
- package/dist/snapshot/diff.js +254 -0
- package/dist/snapshot/diff.js.map +1 -0
- package/dist/snapshot/migrate.js +1596 -0
- package/dist/snapshot/migrate.js.map +1 -0
- package/dist/snapshot/model.js +80 -0
- package/dist/snapshot/model.js.map +1 -0
- package/dist/tools/_archive_meta.js +138 -0
- package/dist/tools/_archive_meta.js.map +1 -0
- package/dist/tools/_batch_shared.js +73 -0
- package/dist/tools/_batch_shared.js.map +1 -0
- package/dist/tools/_export_format.js +107 -0
- package/dist/tools/_export_format.js.map +1 -0
- package/dist/tools/_object_kinds.js +97 -0
- package/dist/tools/_object_kinds.js.map +1 -0
- package/dist/tools/_relation_detail.js +55 -0
- package/dist/tools/_relation_detail.js.map +1 -0
- package/dist/tools/_shared.js +17 -0
- package/dist/tools/_shared.js.map +1 -0
- package/dist/tools/_snapshot_io.js +238 -0
- package/dist/tools/_snapshot_io.js.map +1 -0
- package/dist/tools/admin/_shared.js +18 -0
- package/dist/tools/admin/_shared.js.map +1 -0
- package/dist/tools/admin/extensions.js +80 -0
- package/dist/tools/admin/extensions.js.map +1 -0
- package/dist/tools/admin/grants.js +207 -0
- package/dist/tools/admin/grants.js.map +1 -0
- package/dist/tools/admin/index.js +138 -0
- package/dist/tools/admin/index.js.map +1 -0
- package/dist/tools/admin/maintenance.js +106 -0
- package/dist/tools/admin/maintenance.js.map +1 -0
- package/dist/tools/admin/roles.js +144 -0
- package/dist/tools/admin/roles.js.map +1 -0
- package/dist/tools/admin/sessions.js +104 -0
- package/dist/tools/admin/sessions.js.map +1 -0
- package/dist/tools/admin/stats.js +63 -0
- package/dist/tools/admin/stats.js.map +1 -0
- package/dist/tools/backup.js +288 -0
- package/dist/tools/backup.js.map +1 -0
- package/dist/tools/connection_status.js +138 -0
- package/dist/tools/connection_status.js.map +1 -0
- package/dist/tools/copy.js +355 -0
- package/dist/tools/copy.js.map +1 -0
- package/dist/tools/delete_batch.js +73 -0
- package/dist/tools/delete_batch.js.map +1 -0
- package/dist/tools/describe_object.js +87 -0
- package/dist/tools/describe_object.js.map +1 -0
- package/dist/tools/execute_sql.js +395 -0
- package/dist/tools/execute_sql.js.map +1 -0
- package/dist/tools/explain.js +134 -0
- package/dist/tools/explain.js.map +1 -0
- package/dist/tools/export.js +215 -0
- package/dist/tools/export.js.map +1 -0
- package/dist/tools/get_schema.js +148 -0
- package/dist/tools/get_schema.js.map +1 -0
- package/dist/tools/index.js +40 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/insert_batch.js +212 -0
- package/dist/tools/insert_batch.js.map +1 -0
- package/dist/tools/list_objects.js +160 -0
- package/dist/tools/list_objects.js.map +1 -0
- package/dist/tools/prepare_migration.js +112 -0
- package/dist/tools/prepare_migration.js.map +1 -0
- package/dist/tools/restore.js +301 -0
- package/dist/tools/restore.js.map +1 -0
- package/dist/tools/schema_diff.js +79 -0
- package/dist/tools/schema_diff.js.map +1 -0
- package/dist/tools/schema_snapshot.js +57 -0
- package/dist/tools/schema_snapshot.js.map +1 -0
- package/dist/tools/select.js +162 -0
- package/dist/tools/select.js.map +1 -0
- package/dist/tools/update_batch.js +154 -0
- package/dist/tools/update_batch.js.map +1 -0
- package/package.json +47 -5
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { PgMcpError } from '../../core/errors.js';
|
|
3
|
+
import { CONFIRM_PROTOCOL_DESCRIPTION, runGuardedMutation } from '../../core/guards.js';
|
|
4
|
+
import { resolveCurrentDatabase, resolveFunctionSignature, resolveRelation, resolveRole, resolveSchemaIdent, resolveSequence } from '../../core/identifiers.js';
|
|
5
|
+
import { getPermissionsByKind } from '../../db/catalog.js';
|
|
6
|
+
import { withSession } from '../../db/session.js';
|
|
7
|
+
import { confirmFragment, toExpectToken } from '../_batch_shared.js';
|
|
8
|
+
import { reportList } from './_shared.js';
|
|
9
|
+
/**
|
|
10
|
+
* `grants` sub-operation. `grants_get` (read-only, no capability) reports
|
|
11
|
+
* effective privileges via `getPermissionsByKind`, which is the fix for the
|
|
12
|
+
* `acldefault('r', …)` bug: table/sequence/function/database/schema each get
|
|
13
|
+
* their own `aclexplode` type code.
|
|
14
|
+
*
|
|
15
|
+
* `grants_grant`/`grants_revoke` require `admin` — matching
|
|
16
|
+
* `execute_sql.ts`'s `WRITE_PATH_CAPABILITY` table, which already maps
|
|
17
|
+
* GRANT/REVOKE to `admin`. Unlike `execute_sql`'s raw-SQL path, this tool
|
|
18
|
+
* does not additionally require `write`: `postgres_admin` is a
|
|
19
|
+
* purpose-built administrative tool, and an operator who wants to hand out
|
|
20
|
+
* grants without also opening the DML write path should not have to enable
|
|
21
|
+
* both.
|
|
22
|
+
*
|
|
23
|
+
* Mutation is supported for table/sequence/schema/function objects.
|
|
24
|
+
* Database-level GRANT is deliberately out of scope (read-only via
|
|
25
|
+
* `grants_get` only) to avoid adding a caller-supplied database-name
|
|
26
|
+
* resolver purely for a rarely-used case — see `resolveCurrentDatabase`'s
|
|
27
|
+
* doc comment for why database grants always target the profile's own
|
|
28
|
+
* database when read.
|
|
29
|
+
*/
|
|
30
|
+
const readObjectKind = z.enum(['table', 'sequence', 'function', 'database', 'schema']);
|
|
31
|
+
const mutableObjectKind = z.enum(['table', 'sequence', 'schema', 'function']);
|
|
32
|
+
const PRIVILEGES_BY_KIND = {
|
|
33
|
+
table: ['SELECT', 'INSERT', 'UPDATE', 'DELETE', 'TRUNCATE', 'REFERENCES', 'TRIGGER', 'ALL'],
|
|
34
|
+
sequence: ['SELECT', 'UPDATE', 'USAGE', 'ALL'],
|
|
35
|
+
schema: ['CREATE', 'USAGE', 'ALL'],
|
|
36
|
+
function: ['EXECUTE', 'ALL'],
|
|
37
|
+
};
|
|
38
|
+
const ON_WORD = {
|
|
39
|
+
table: 'TABLE',
|
|
40
|
+
sequence: 'SEQUENCE',
|
|
41
|
+
schema: 'SCHEMA',
|
|
42
|
+
function: 'FUNCTION',
|
|
43
|
+
};
|
|
44
|
+
export const grantsGetSchema = z
|
|
45
|
+
.object({
|
|
46
|
+
op: z.literal('grants_get'),
|
|
47
|
+
objectKind: readObjectKind,
|
|
48
|
+
schema: z.string().min(1).optional(),
|
|
49
|
+
name: z.string().min(1).optional().describe('Object name. Not used (and not required) when objectKind is "schema" or "database".'),
|
|
50
|
+
})
|
|
51
|
+
.superRefine((v, ctx) => {
|
|
52
|
+
if (v.objectKind === 'database')
|
|
53
|
+
return;
|
|
54
|
+
if (v.objectKind === 'schema') {
|
|
55
|
+
if (v.schema === undefined)
|
|
56
|
+
ctx.addIssue({ code: 'custom', message: 'objectKind "schema" requires "schema"' });
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
if (v.schema === undefined || v.name === undefined) {
|
|
60
|
+
ctx.addIssue({ code: 'custom', message: `objectKind "${v.objectKind}" requires both "schema" and "name"` });
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
const grantsMutationBase = {
|
|
64
|
+
objectKind: mutableObjectKind,
|
|
65
|
+
schema: z.string().min(1),
|
|
66
|
+
name: z.string().min(1).optional().describe('Required unless objectKind is "schema" (the schema itself is the object).'),
|
|
67
|
+
roles: z.array(z.string().min(1)).min(1).describe('Grantee role names, or "PUBLIC".'),
|
|
68
|
+
privileges: z.array(z.string().min(1)).min(1).describe('Privilege keywords valid for objectKind, e.g. SELECT/INSERT/UPDATE/DELETE for a table, USAGE for a schema, EXECUTE for a function, or ALL.'),
|
|
69
|
+
};
|
|
70
|
+
export const grantsGrantSchema = z
|
|
71
|
+
.object({
|
|
72
|
+
op: z.literal('grants_grant'),
|
|
73
|
+
...grantsMutationBase,
|
|
74
|
+
grantOption: z.boolean().optional().default(false).describe('Adds WITH GRANT OPTION.'),
|
|
75
|
+
...confirmFragment,
|
|
76
|
+
})
|
|
77
|
+
.superRefine((v, ctx) => {
|
|
78
|
+
if (v.objectKind !== 'schema' && v.name === undefined)
|
|
79
|
+
ctx.addIssue({ code: 'custom', message: `objectKind "${v.objectKind}" requires "name"` });
|
|
80
|
+
});
|
|
81
|
+
export const grantsRevokeSchema = z
|
|
82
|
+
.object({
|
|
83
|
+
op: z.literal('grants_revoke'),
|
|
84
|
+
...grantsMutationBase,
|
|
85
|
+
cascade: z.boolean().optional().default(false),
|
|
86
|
+
...confirmFragment,
|
|
87
|
+
})
|
|
88
|
+
.superRefine((v, ctx) => {
|
|
89
|
+
if (v.objectKind !== 'schema' && v.name === undefined)
|
|
90
|
+
ctx.addIssue({ code: 'custom', message: `objectKind "${v.objectKind}" requires "name"` });
|
|
91
|
+
});
|
|
92
|
+
async function resolveGrantObject(profile, objectKind, schema, name) {
|
|
93
|
+
switch (objectKind) {
|
|
94
|
+
case 'table': {
|
|
95
|
+
const rel = await resolveRelation(profile, schema, name);
|
|
96
|
+
return { target: `${rel.schema}.${rel.name}`, aclKind: 'table' };
|
|
97
|
+
}
|
|
98
|
+
case 'sequence': {
|
|
99
|
+
const seq = await resolveSequence(profile, schema, name);
|
|
100
|
+
return { target: `${seq.schema}.${seq.name}`, aclKind: 'sequence' };
|
|
101
|
+
}
|
|
102
|
+
case 'function': {
|
|
103
|
+
const fn = await resolveFunctionSignature(profile, schema, name);
|
|
104
|
+
return { target: fn.signature, aclKind: 'function' };
|
|
105
|
+
}
|
|
106
|
+
case 'schema': {
|
|
107
|
+
const sch = await resolveSchemaIdent(profile, schema);
|
|
108
|
+
return { target: sch.name, aclKind: 'schema' };
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
async function resolveGranteeIdent(profile, name) {
|
|
113
|
+
if (name.toUpperCase() === 'PUBLIC')
|
|
114
|
+
return 'PUBLIC';
|
|
115
|
+
const role = await resolveRole(profile, name);
|
|
116
|
+
return role.name;
|
|
117
|
+
}
|
|
118
|
+
function validatePrivileges(objectKind, privileges) {
|
|
119
|
+
const allowed = PRIVILEGES_BY_KIND[objectKind];
|
|
120
|
+
const normalized = privileges.map((p) => p.toUpperCase());
|
|
121
|
+
for (const p of normalized) {
|
|
122
|
+
if (!allowed.includes(p)) {
|
|
123
|
+
throw new PgMcpError({
|
|
124
|
+
code: 'PG_ERROR',
|
|
125
|
+
message: `privilege "${p}" is not valid for objectKind "${objectKind}"`,
|
|
126
|
+
hint: `valid privileges for "${objectKind}": ${allowed.join(', ')}`,
|
|
127
|
+
details: { objectKind, privilege: p, allowed },
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return normalized;
|
|
132
|
+
}
|
|
133
|
+
export async function handleGrantsGet(profile, args) {
|
|
134
|
+
let aclKind;
|
|
135
|
+
let oid;
|
|
136
|
+
let label;
|
|
137
|
+
if (args.objectKind === 'database') {
|
|
138
|
+
const db = await resolveCurrentDatabase(profile);
|
|
139
|
+
aclKind = 'database';
|
|
140
|
+
oid = db.oid;
|
|
141
|
+
label = profile.database;
|
|
142
|
+
}
|
|
143
|
+
else if (args.objectKind === 'schema') {
|
|
144
|
+
const sch = await resolveSchemaIdent(profile, args.schema);
|
|
145
|
+
aclKind = 'schema';
|
|
146
|
+
oid = sch.oid;
|
|
147
|
+
label = args.schema;
|
|
148
|
+
}
|
|
149
|
+
else if (args.objectKind === 'sequence') {
|
|
150
|
+
const seq = await resolveSequence(profile, args.schema, args.name);
|
|
151
|
+
aclKind = 'sequence';
|
|
152
|
+
oid = seq.oid;
|
|
153
|
+
label = `${args.schema}.${args.name}`;
|
|
154
|
+
}
|
|
155
|
+
else if (args.objectKind === 'function') {
|
|
156
|
+
const fn = await resolveFunctionSignature(profile, args.schema, args.name);
|
|
157
|
+
aclKind = 'function';
|
|
158
|
+
oid = fn.oid;
|
|
159
|
+
label = `${args.schema}.${args.name}`;
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
const rel = await resolveRelation(profile, args.schema, args.name);
|
|
163
|
+
aclKind = 'table';
|
|
164
|
+
oid = rel.oid;
|
|
165
|
+
label = `${args.schema}.${args.name}`;
|
|
166
|
+
}
|
|
167
|
+
const perms = await withSession(profile, (client) => getPermissionsByKind(client, aclKind, oid), { operation: 'admin_grants_get' });
|
|
168
|
+
return reportList(profile, perms.map((p) => ({ object: label, objectKind: args.objectKind, ...p })));
|
|
169
|
+
}
|
|
170
|
+
export async function handleGrantsGrant(profile, args) {
|
|
171
|
+
const { target } = await resolveGrantObject(profile, args.objectKind, args.schema, args.name);
|
|
172
|
+
const privileges = validatePrivileges(args.objectKind, args.privileges);
|
|
173
|
+
const grantees = await Promise.all(args.roles.map((r) => resolveGranteeIdent(profile, r)));
|
|
174
|
+
const sql = `GRANT ${privileges.join(', ')} ON ${ON_WORD[args.objectKind]} ${target} TO ${grantees.join(', ')}${args.grantOption ? ' WITH GRANT OPTION' : ''}`;
|
|
175
|
+
return runGuardedMutation({
|
|
176
|
+
profile,
|
|
177
|
+
capability: 'admin',
|
|
178
|
+
operation: 'admin_grants_grant',
|
|
179
|
+
sql,
|
|
180
|
+
params: [],
|
|
181
|
+
keyColumns: [],
|
|
182
|
+
confirm: args.confirm,
|
|
183
|
+
expect: toExpectToken(args.expect),
|
|
184
|
+
allowRowDrift: args.allowRowDrift,
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
export async function handleGrantsRevoke(profile, args) {
|
|
188
|
+
const { target } = await resolveGrantObject(profile, args.objectKind, args.schema, args.name);
|
|
189
|
+
const privileges = validatePrivileges(args.objectKind, args.privileges);
|
|
190
|
+
const grantees = await Promise.all(args.roles.map((r) => resolveGranteeIdent(profile, r)));
|
|
191
|
+
const sql = `REVOKE ${privileges.join(', ')} ON ${ON_WORD[args.objectKind]} ${target} FROM ${grantees.join(', ')}${args.cascade ? ' CASCADE' : ''}`;
|
|
192
|
+
return runGuardedMutation({
|
|
193
|
+
profile,
|
|
194
|
+
capability: 'admin',
|
|
195
|
+
operation: 'admin_grants_revoke',
|
|
196
|
+
sql,
|
|
197
|
+
params: [],
|
|
198
|
+
keyColumns: [],
|
|
199
|
+
confirm: args.confirm,
|
|
200
|
+
expect: toExpectToken(args.expect),
|
|
201
|
+
allowRowDrift: args.allowRowDrift,
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
export const GRANTS_DESCRIPTION = `\`grants_get\` (read-only, no capability) inspects effective privileges — correct aclexplode/acldefault type code per object kind ` +
|
|
205
|
+
`('r' table, 'S' sequence, 'f' function, 'd' database, 'n' schema). \`grants_grant\`/\`grants_revoke\` require \`admin\` (matching ` +
|
|
206
|
+
`execute_sql's GRANT/REVOKE routing) and support table/sequence/schema/function objects; database-level GRANT is read-only here. ${CONFIRM_PROTOCOL_DESCRIPTION}`;
|
|
207
|
+
//# sourceMappingURL=grants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grants.js","sourceRoot":"","sources":["../../../src/tools/admin/grants.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { loadProfiles } from '../../config/profiles.js';
|
|
3
|
+
import { toToolResult } from '../../core/errors.js';
|
|
4
|
+
import { formatOutcome } from '../../core/format.js';
|
|
5
|
+
import { assertNever, defineTool, profileParam } from '../_shared.js';
|
|
6
|
+
import { extensionsCreateSchema, extensionsDropSchema, extensionsListSchema, EXTENSIONS_DESCRIPTION, handleExtensionsCreate, handleExtensionsDrop, handleExtensionsList } from './extensions.js';
|
|
7
|
+
import { grantsGetSchema, grantsGrantSchema, grantsRevokeSchema, GRANTS_DESCRIPTION, handleGrantsGet, handleGrantsGrant, handleGrantsRevoke } from './grants.js';
|
|
8
|
+
import { handleMaintenanceAnalyze, handleMaintenanceReindex, handleMaintenanceVacuum, maintenanceAnalyzeSchema, maintenanceReindexSchema, maintenanceVacuumSchema, MAINTENANCE_DESCRIPTION } from './maintenance.js';
|
|
9
|
+
import { handleRolesAlter, handleRolesCreate, handleRolesDrop, handleRolesList, rolesAlterSchema, rolesCreateSchema, rolesDropSchema, rolesListSchema, ROLES_DESCRIPTION } from './roles.js';
|
|
10
|
+
import { handleSessionsCancel, handleSessionsList, handleSessionsTerminate, sessionsCancelSchema, sessionsListSchema, sessionsTerminateSchema, SESSIONS_DESCRIPTION } from './sessions.js';
|
|
11
|
+
import { handleStatsActivity, handleStatsIndexes, handleStatsTables, statsActivitySchema, statsIndexesSchema, statsTablesSchema, STATS_DESCRIPTION } from './stats.js';
|
|
12
|
+
/**
|
|
13
|
+
* `postgres_admin` — one dispatcher, six sub-operations, each its own file.
|
|
14
|
+
* The widest-blast-radius tool in this server: it can create/alter/drop
|
|
15
|
+
* roles, grant/revoke privileges, install/remove extensions (arbitrary SQL
|
|
16
|
+
* as superuser), cancel/terminate other sessions, and run maintenance that
|
|
17
|
+
* takes locks. Every mutating op requires `admin`; every destructive one
|
|
18
|
+
* routes through `runGuardedMutation`'s confirm protocol or, where that
|
|
19
|
+
* protocol cannot be honest (see `maintenance.ts`/`sessions.ts`), a plain
|
|
20
|
+
* `confirm: true` gate with no dry run offered rather than a fake one.
|
|
21
|
+
*
|
|
22
|
+
* One flat `z.discriminatedUnion('op', [...])` rather than nested unions —
|
|
23
|
+
* Zod's nested-discriminated-union support is friction for nineteen leaf
|
|
24
|
+
* shapes with no shared parent shape worth factoring out, and a flat union
|
|
25
|
+
* still gives each `op` its own independently typed argument shape with
|
|
26
|
+
* schema-level rejection of any invalid op/argument combination.
|
|
27
|
+
*/
|
|
28
|
+
const inputSchema = z.discriminatedUnion('op', [
|
|
29
|
+
rolesListSchema,
|
|
30
|
+
rolesCreateSchema,
|
|
31
|
+
rolesAlterSchema,
|
|
32
|
+
rolesDropSchema,
|
|
33
|
+
grantsGetSchema,
|
|
34
|
+
grantsGrantSchema,
|
|
35
|
+
grantsRevokeSchema,
|
|
36
|
+
extensionsListSchema,
|
|
37
|
+
extensionsCreateSchema,
|
|
38
|
+
extensionsDropSchema,
|
|
39
|
+
sessionsListSchema,
|
|
40
|
+
sessionsCancelSchema,
|
|
41
|
+
sessionsTerminateSchema,
|
|
42
|
+
maintenanceVacuumSchema,
|
|
43
|
+
maintenanceAnalyzeSchema,
|
|
44
|
+
maintenanceReindexSchema,
|
|
45
|
+
statsTablesSchema,
|
|
46
|
+
statsIndexesSchema,
|
|
47
|
+
statsActivitySchema,
|
|
48
|
+
]);
|
|
49
|
+
// z.discriminatedUnion does not support spreading profileParam into each
|
|
50
|
+
// branch without repeating it in all nineteen schemas, so profile is layered
|
|
51
|
+
// on as an intersection instead: `profileParam` first (broad), intersected
|
|
52
|
+
// with the discriminated union (narrow, decides `op`'s shape). TypeScript
|
|
53
|
+
// still narrows `args.op` correctly through the intersection — verified: an
|
|
54
|
+
// intersection of an object type with a union distributes for discriminant
|
|
55
|
+
// narrowing the same way the union alone would.
|
|
56
|
+
const adminInputSchema = z.intersection(z.object(profileParam), inputSchema);
|
|
57
|
+
export const adminTool = defineTool('postgres_admin', {
|
|
58
|
+
title: 'PostgreSQL administrative operations',
|
|
59
|
+
description: 'Widest-blast-radius tool in this server. Six sub-operations selected by `op`: roles_* (create/alter/drop a role), ' +
|
|
60
|
+
'grants_* (GRANT/REVOKE), extensions_* (CREATE/DROP EXTENSION — installing runs arbitrary SQL as superuser), ' +
|
|
61
|
+
'sessions_* (cancel/terminate another backend), maintenance_* (VACUUM/ANALYZE/REINDEX), stats_* (read-only). Every ' +
|
|
62
|
+
'mutating op requires the `admin` capability. ' +
|
|
63
|
+
`${ROLES_DESCRIPTION} ${GRANTS_DESCRIPTION} ${EXTENSIONS_DESCRIPTION} ${SESSIONS_DESCRIPTION} ${MAINTENANCE_DESCRIPTION} ${STATS_DESCRIPTION}`,
|
|
64
|
+
inputSchema: adminInputSchema,
|
|
65
|
+
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: true },
|
|
66
|
+
}, async (args) => {
|
|
67
|
+
try {
|
|
68
|
+
const registry = loadProfiles();
|
|
69
|
+
const profile = registry.get(args.profile);
|
|
70
|
+
let outcome;
|
|
71
|
+
switch (args.op) {
|
|
72
|
+
case 'roles_list':
|
|
73
|
+
outcome = await handleRolesList(profile, args);
|
|
74
|
+
break;
|
|
75
|
+
case 'roles_create':
|
|
76
|
+
outcome = await handleRolesCreate(profile, args);
|
|
77
|
+
break;
|
|
78
|
+
case 'roles_alter':
|
|
79
|
+
outcome = await handleRolesAlter(profile, args);
|
|
80
|
+
break;
|
|
81
|
+
case 'roles_drop':
|
|
82
|
+
outcome = await handleRolesDrop(profile, args);
|
|
83
|
+
break;
|
|
84
|
+
case 'grants_get':
|
|
85
|
+
outcome = await handleGrantsGet(profile, args);
|
|
86
|
+
break;
|
|
87
|
+
case 'grants_grant':
|
|
88
|
+
outcome = await handleGrantsGrant(profile, args);
|
|
89
|
+
break;
|
|
90
|
+
case 'grants_revoke':
|
|
91
|
+
outcome = await handleGrantsRevoke(profile, args);
|
|
92
|
+
break;
|
|
93
|
+
case 'extensions_list':
|
|
94
|
+
outcome = await handleExtensionsList(profile, args);
|
|
95
|
+
break;
|
|
96
|
+
case 'extensions_create':
|
|
97
|
+
outcome = await handleExtensionsCreate(profile, args);
|
|
98
|
+
break;
|
|
99
|
+
case 'extensions_drop':
|
|
100
|
+
outcome = await handleExtensionsDrop(profile, args);
|
|
101
|
+
break;
|
|
102
|
+
case 'sessions_list':
|
|
103
|
+
outcome = await handleSessionsList(profile, args);
|
|
104
|
+
break;
|
|
105
|
+
case 'sessions_cancel':
|
|
106
|
+
outcome = await handleSessionsCancel(profile, args);
|
|
107
|
+
break;
|
|
108
|
+
case 'sessions_terminate':
|
|
109
|
+
outcome = await handleSessionsTerminate(profile, args);
|
|
110
|
+
break;
|
|
111
|
+
case 'maintenance_vacuum':
|
|
112
|
+
outcome = await handleMaintenanceVacuum(profile, args);
|
|
113
|
+
break;
|
|
114
|
+
case 'maintenance_analyze':
|
|
115
|
+
outcome = await handleMaintenanceAnalyze(profile, args);
|
|
116
|
+
break;
|
|
117
|
+
case 'maintenance_reindex':
|
|
118
|
+
outcome = await handleMaintenanceReindex(profile, args);
|
|
119
|
+
break;
|
|
120
|
+
case 'stats_tables':
|
|
121
|
+
outcome = await handleStatsTables(profile, args);
|
|
122
|
+
break;
|
|
123
|
+
case 'stats_indexes':
|
|
124
|
+
outcome = await handleStatsIndexes(profile, args);
|
|
125
|
+
break;
|
|
126
|
+
case 'stats_activity':
|
|
127
|
+
outcome = await handleStatsActivity(profile, args);
|
|
128
|
+
break;
|
|
129
|
+
default:
|
|
130
|
+
return assertNever(args);
|
|
131
|
+
}
|
|
132
|
+
return formatOutcome(outcome);
|
|
133
|
+
}
|
|
134
|
+
catch (err) {
|
|
135
|
+
return toToolResult(err);
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/tools/admin/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { CONFIRM_PROTOCOL_DESCRIPTION, runGuardedMutation } from '../../core/guards.js';
|
|
3
|
+
import { resolveIndex, resolveRelation } from '../../core/identifiers.js';
|
|
4
|
+
import { requireCapability } from '../../core/policy.js';
|
|
5
|
+
import { withSession } from '../../db/session.js';
|
|
6
|
+
import { confirmFragment, toExpectToken } from '../_batch_shared.js';
|
|
7
|
+
/**
|
|
8
|
+
* `maintenance` sub-operation: VACUUM, ANALYZE, REINDEX. All require `admin`.
|
|
9
|
+
*
|
|
10
|
+
* **The transaction-block problem, and the decision.** `runGuardedMutation`
|
|
11
|
+
* always opens a transaction (`withTx`, for both the dry-run and the confirm
|
|
12
|
+
* call — confirmed by reading it end to end, there is no code path that
|
|
13
|
+
* skips `BEGIN`). PostgreSQL refuses `VACUUM` inside a transaction block
|
|
14
|
+
* unconditionally, and refuses `REINDEX ... CONCURRENTLY` inside one too
|
|
15
|
+
* (plain `REINDEX TABLE`/`REINDEX INDEX` on a single object CAN run inside a
|
|
16
|
+
* transaction). Wrapping either operation in a `GuardedExecutor` would not
|
|
17
|
+
* help: an executor's `run(client)` still executes inside whatever
|
|
18
|
+
* transaction `withTx` opened around it — it does not escape it. So:
|
|
19
|
+
*
|
|
20
|
+
* - `maintenance_vacuum` and `maintenance_analyze` never go through
|
|
21
|
+
* `runGuardedMutation`. They run immediately via `withSession` (no
|
|
22
|
+
* transaction at all), gated by an explicit `requireCapability('admin', …)`
|
|
23
|
+
* call since there is no guard to do it for them. No dry run is offered —
|
|
24
|
+
* one is not possible, and pretending otherwise (e.g. by wrapping VACUUM in
|
|
25
|
+
* a transaction that always rolls back) would either lie about what
|
|
26
|
+
* happened or simply fail with PostgreSQL's own
|
|
27
|
+
* `25001 VACUUM cannot run inside a transaction block`. Neither VACUUM nor
|
|
28
|
+
* ANALYZE deletes or hides live rows a caller can see — the honest
|
|
29
|
+
* description is "no dry run because none is possible for a
|
|
30
|
+
* non-transactional operation", not "defeats the guard".
|
|
31
|
+
* - `maintenance_reindex` with `concurrently: false` (default) targets a
|
|
32
|
+
* single table or index, which CAN run inside a transaction — it goes
|
|
33
|
+
* through `runGuardedMutation` like any other DDL-shaped mutation
|
|
34
|
+
* (`keyColumns: []`, no `RETURNING`). Its dry run genuinely rebuilds the
|
|
35
|
+
* index and then rolls back: a truthful, if I/O-costly, proof that the
|
|
36
|
+
* REINDEX will succeed — unlike VACUUM, this one is not a lie.
|
|
37
|
+
* - `maintenance_reindex` with `concurrently: true` cannot run inside a
|
|
38
|
+
* transaction block either (PostgreSQL's own restriction), so it takes the
|
|
39
|
+
* same immediate/no-dry-run path as VACUUM, documented the same way.
|
|
40
|
+
*/
|
|
41
|
+
const targetKind = z.enum(['table', 'index']);
|
|
42
|
+
export const maintenanceVacuumSchema = z.object({
|
|
43
|
+
op: z.literal('maintenance_vacuum'),
|
|
44
|
+
schema: z.string().min(1),
|
|
45
|
+
table: z.string().min(1),
|
|
46
|
+
full: z.boolean().optional().default(false).describe('VACUUM FULL rewrites the table and takes ACCESS EXCLUSIVE — no dry run either way.'),
|
|
47
|
+
analyze: z.boolean().optional().default(false).describe('Also update planner statistics in the same pass.'),
|
|
48
|
+
});
|
|
49
|
+
export const maintenanceAnalyzeSchema = z.object({
|
|
50
|
+
op: z.literal('maintenance_analyze'),
|
|
51
|
+
schema: z.string().min(1),
|
|
52
|
+
table: z.string().min(1),
|
|
53
|
+
});
|
|
54
|
+
export const maintenanceReindexSchema = z.object({
|
|
55
|
+
op: z.literal('maintenance_reindex'),
|
|
56
|
+
target: targetKind,
|
|
57
|
+
schema: z.string().min(1),
|
|
58
|
+
name: z.string().min(1),
|
|
59
|
+
concurrently: z.boolean().optional().default(false).describe('REINDEX CONCURRENTLY cannot run inside a transaction block, so no dry run is offered when true.'),
|
|
60
|
+
...confirmFragment,
|
|
61
|
+
});
|
|
62
|
+
export async function handleMaintenanceVacuum(profile, args) {
|
|
63
|
+
requireCapability('admin', profile);
|
|
64
|
+
const rel = await resolveRelation(profile, args.schema, args.table);
|
|
65
|
+
const options = [args.full ? 'FULL' : null, args.analyze ? 'ANALYZE' : null].filter((o) => o !== null);
|
|
66
|
+
const sql = options.length > 0 ? `VACUUM (${options.join(', ')}) ${rel.schema}.${rel.name}` : `VACUUM ${rel.schema}.${rel.name}`;
|
|
67
|
+
await withSession(profile, (client) => client.query({ text: sql, values: [], queryMode: 'extended' }), { operation: 'admin_maintenance_vacuum' });
|
|
68
|
+
return { kind: 'mutation', rowCount: 0, committed: true };
|
|
69
|
+
}
|
|
70
|
+
export async function handleMaintenanceAnalyze(profile, args) {
|
|
71
|
+
requireCapability('admin', profile);
|
|
72
|
+
const rel = await resolveRelation(profile, args.schema, args.table);
|
|
73
|
+
const sql = `ANALYZE ${rel.schema}.${rel.name}`;
|
|
74
|
+
await withSession(profile, (client) => client.query({ text: sql, values: [], queryMode: 'extended' }), { operation: 'admin_maintenance_analyze' });
|
|
75
|
+
return { kind: 'mutation', rowCount: 0, committed: true };
|
|
76
|
+
}
|
|
77
|
+
export async function handleMaintenanceReindex(profile, args) {
|
|
78
|
+
const targetIdent = args.target === 'table' ? await resolveRelation(profile, args.schema, args.name) : await resolveIndex(profile, args.schema, args.name);
|
|
79
|
+
const onWord = args.target === 'table' ? 'TABLE' : 'INDEX';
|
|
80
|
+
const object = `${targetIdent.schema}.${targetIdent.name}`;
|
|
81
|
+
if (args.concurrently) {
|
|
82
|
+
requireCapability('admin', profile);
|
|
83
|
+
const sql = `REINDEX ${onWord} CONCURRENTLY ${object}`;
|
|
84
|
+
await withSession(profile, (client) => client.query({ text: sql, values: [], queryMode: 'extended' }), { operation: 'admin_maintenance_reindex_concurrently' });
|
|
85
|
+
return { kind: 'mutation', rowCount: 0, committed: true };
|
|
86
|
+
}
|
|
87
|
+
const sql = `REINDEX ${onWord} ${object}`;
|
|
88
|
+
return runGuardedMutation({
|
|
89
|
+
profile,
|
|
90
|
+
capability: 'admin',
|
|
91
|
+
operation: 'admin_maintenance_reindex',
|
|
92
|
+
sql,
|
|
93
|
+
params: [],
|
|
94
|
+
keyColumns: [],
|
|
95
|
+
confirm: args.confirm,
|
|
96
|
+
expect: toExpectToken(args.expect),
|
|
97
|
+
allowRowDrift: args.allowRowDrift,
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
export const MAINTENANCE_DESCRIPTION = '`maintenance_vacuum`/`maintenance_analyze` require `admin` and run immediately with NO dry run — VACUUM cannot run inside a transaction ' +
|
|
101
|
+
'block at all, so no truthful preview is possible; neither operation deletes or hides live rows. `maintenance_reindex` with ' +
|
|
102
|
+
'concurrently:false (default, single table/index) DOES support a real dry run through the usual confirm protocol — it actually rebuilds ' +
|
|
103
|
+
'the index inside a rolled-back transaction. concurrently:true cannot run inside a transaction either, so it also runs immediately with ' +
|
|
104
|
+
'no dry run. REINDEX without CONCURRENTLY takes an ACCESS EXCLUSIVE lock on the target — expect it to block other queries on a busy ' +
|
|
105
|
+
`table. ${CONFIRM_PROTOCOL_DESCRIPTION}`;
|
|
106
|
+
//# sourceMappingURL=maintenance.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"maintenance.js","sourceRoot":"","sources":["../../../src/tools/admin/maintenance.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { PgMcpError } from '../../core/errors.js';
|
|
3
|
+
import { CONFIRM_PROTOCOL_DESCRIPTION, runGuardedMutation } from '../../core/guards.js';
|
|
4
|
+
import { assertRoleAvailable, resolveRole } from '../../core/identifiers.js';
|
|
5
|
+
import { requireCapability } from '../../core/policy.js';
|
|
6
|
+
import { getRoleDependencies, listRoles } from '../../db/catalog.js';
|
|
7
|
+
import { withSession } from '../../db/session.js';
|
|
8
|
+
import { confirmFragment, toExpectToken } from '../_batch_shared.js';
|
|
9
|
+
import { reportList } from './_shared.js';
|
|
10
|
+
/**
|
|
11
|
+
* `roles` sub-operation: list roles/attributes/memberships (read-only, no
|
|
12
|
+
* capability), and create/alter/drop a role (requires `admin`, guarded via
|
|
13
|
+
* `runGuardedMutation` — no `RETURNING`, so `keyColumns` is always empty and
|
|
14
|
+
* the dry run's row count is not meaningful for these, same caveat as DDL in
|
|
15
|
+
* `execute_sql`).
|
|
16
|
+
*/
|
|
17
|
+
export const rolesListSchema = z.object({
|
|
18
|
+
op: z.literal('roles_list'),
|
|
19
|
+
namePattern: z.string().optional().describe('SQL ILIKE pattern to filter role names, e.g. "app_%".'),
|
|
20
|
+
});
|
|
21
|
+
export const rolesCreateSchema = z.object({
|
|
22
|
+
op: z.literal('roles_create'),
|
|
23
|
+
role: z.string().min(1),
|
|
24
|
+
login: z.boolean().optional().default(false),
|
|
25
|
+
superuser: z.boolean().optional().default(false),
|
|
26
|
+
createDb: z.boolean().optional().default(false),
|
|
27
|
+
createRole: z.boolean().optional().default(false),
|
|
28
|
+
replication: z.boolean().optional().default(false),
|
|
29
|
+
connectionLimit: z.number().int().optional().describe('-1 (default in PostgreSQL) means unlimited.'),
|
|
30
|
+
...confirmFragment,
|
|
31
|
+
});
|
|
32
|
+
export const rolesAlterSchema = z.object({
|
|
33
|
+
op: z.literal('roles_alter'),
|
|
34
|
+
role: z.string().min(1),
|
|
35
|
+
set: z
|
|
36
|
+
.object({
|
|
37
|
+
login: z.boolean().optional(),
|
|
38
|
+
superuser: z.boolean().optional(),
|
|
39
|
+
createDb: z.boolean().optional(),
|
|
40
|
+
createRole: z.boolean().optional(),
|
|
41
|
+
replication: z.boolean().optional(),
|
|
42
|
+
connectionLimit: z.number().int().optional(),
|
|
43
|
+
validUntil: z.string().datetime().nullable().optional().describe('ISO 8601 timestamp; null clears it to VALID UNTIL infinity.'),
|
|
44
|
+
})
|
|
45
|
+
.refine((v) => Object.values(v).some((x) => x !== undefined), { message: 'set must include at least one attribute to change' })
|
|
46
|
+
.describe('Attributes to change. Password changes are out of scope for postgres_admin — use postgres_execute_sql on a profile with ALLOW_DDL for ALTER ROLE ... PASSWORD.'),
|
|
47
|
+
...confirmFragment,
|
|
48
|
+
});
|
|
49
|
+
export const rolesDropSchema = z.object({
|
|
50
|
+
op: z.literal('roles_drop'),
|
|
51
|
+
role: z.string().min(1),
|
|
52
|
+
...confirmFragment,
|
|
53
|
+
});
|
|
54
|
+
export async function handleRolesList(profile, args) {
|
|
55
|
+
const roles = await withSession(profile, (client) => listRoles(client, args.namePattern), { operation: 'admin_roles_list' });
|
|
56
|
+
return reportList(profile, roles);
|
|
57
|
+
}
|
|
58
|
+
function alterOptionClause(set) {
|
|
59
|
+
const parts = [];
|
|
60
|
+
if (set.login !== undefined)
|
|
61
|
+
parts.push(set.login ? 'LOGIN' : 'NOLOGIN');
|
|
62
|
+
if (set.superuser !== undefined)
|
|
63
|
+
parts.push(set.superuser ? 'SUPERUSER' : 'NOSUPERUSER');
|
|
64
|
+
if (set.createDb !== undefined)
|
|
65
|
+
parts.push(set.createDb ? 'CREATEDB' : 'NOCREATEDB');
|
|
66
|
+
if (set.createRole !== undefined)
|
|
67
|
+
parts.push(set.createRole ? 'CREATEROLE' : 'NOCREATEROLE');
|
|
68
|
+
if (set.replication !== undefined)
|
|
69
|
+
parts.push(set.replication ? 'REPLICATION' : 'NOREPLICATION');
|
|
70
|
+
if (set.connectionLimit !== undefined)
|
|
71
|
+
parts.push(`CONNECTION LIMIT ${set.connectionLimit}`);
|
|
72
|
+
return parts;
|
|
73
|
+
}
|
|
74
|
+
export async function handleRolesCreate(profile, args) {
|
|
75
|
+
const roleIdent = await assertRoleAvailable(profile, args.role);
|
|
76
|
+
const parts = alterOptionClause(args);
|
|
77
|
+
const sql = `CREATE ROLE ${roleIdent} WITH ${parts.join(' ')}`;
|
|
78
|
+
return runGuardedMutation({
|
|
79
|
+
profile,
|
|
80
|
+
capability: 'admin',
|
|
81
|
+
operation: 'admin_roles_create',
|
|
82
|
+
sql,
|
|
83
|
+
params: [],
|
|
84
|
+
keyColumns: [],
|
|
85
|
+
confirm: args.confirm,
|
|
86
|
+
expect: toExpectToken(args.expect),
|
|
87
|
+
allowRowDrift: args.allowRowDrift,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
export async function handleRolesAlter(profile, args) {
|
|
91
|
+
const role = await resolveRole(profile, args.role);
|
|
92
|
+
const parts = alterOptionClause(args.set);
|
|
93
|
+
if (args.set.validUntil !== undefined) {
|
|
94
|
+
const escaped = (args.set.validUntil ?? 'infinity').replace(/'/g, "''");
|
|
95
|
+
parts.push(`VALID UNTIL '${escaped}'`);
|
|
96
|
+
}
|
|
97
|
+
const sql = `ALTER ROLE ${role.name} WITH ${parts.join(' ')}`;
|
|
98
|
+
return runGuardedMutation({
|
|
99
|
+
profile,
|
|
100
|
+
capability: 'admin',
|
|
101
|
+
operation: 'admin_roles_alter',
|
|
102
|
+
sql,
|
|
103
|
+
params: [],
|
|
104
|
+
keyColumns: [],
|
|
105
|
+
confirm: args.confirm,
|
|
106
|
+
expect: toExpectToken(args.expect),
|
|
107
|
+
allowRowDrift: args.allowRowDrift,
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
export async function handleRolesDrop(profile, args) {
|
|
111
|
+
// Extra catalog work (the dependency precheck) happens outside
|
|
112
|
+
// runGuardedMutation, so it needs its own gate — resolveRole/create/alter
|
|
113
|
+
// above rely on runGuardedMutation's internal check, same as
|
|
114
|
+
// delete_batch.ts's resolveRelation-before-guard convention.
|
|
115
|
+
requireCapability('admin', profile);
|
|
116
|
+
const role = await resolveRole(profile, args.role);
|
|
117
|
+
const deps = await withSession(profile, (client) => getRoleDependencies(client, role.oid), { operation: 'admin_roles_drop_precheck' });
|
|
118
|
+
if (deps.length > 0) {
|
|
119
|
+
const shown = deps.slice(0, 20);
|
|
120
|
+
throw new PgMcpError({
|
|
121
|
+
code: 'PG_ERROR',
|
|
122
|
+
message: `role "${args.role}" owns or is referenced by ${deps.length} object(s) and cannot be dropped as-is: ${shown.join('; ')}${deps.length > shown.length ? ', …' : ''}`,
|
|
123
|
+
hint: 'reassign ownership first — e.g. `REASSIGN OWNED BY <role> TO <new_owner>; DROP OWNED BY <role>;` via postgres_execute_sql on a profile with ' +
|
|
124
|
+
`ALLOW_DDL — or run \`SELECT * FROM pg_shdepend WHERE refobjid = '${args.role}'::regrole\` to see every dependent yourself, then retry roles_drop`,
|
|
125
|
+
details: { profile: profile.alias, role: args.role, dependents: deps },
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
const sql = `DROP ROLE ${role.name}`;
|
|
129
|
+
return runGuardedMutation({
|
|
130
|
+
profile,
|
|
131
|
+
capability: 'admin',
|
|
132
|
+
operation: 'admin_roles_drop',
|
|
133
|
+
sql,
|
|
134
|
+
params: [],
|
|
135
|
+
keyColumns: [],
|
|
136
|
+
confirm: args.confirm,
|
|
137
|
+
expect: toExpectToken(args.expect),
|
|
138
|
+
allowRowDrift: args.allowRowDrift,
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
export const ROLES_DESCRIPTION = `\`roles_list\` (read-only, no capability) lists roles with attributes and memberships. \`roles_create\`/\`roles_alter\`/\`roles_drop\` ` +
|
|
142
|
+
`require the \`admin\` capability. Password changes are out of scope — use postgres_execute_sql for those. \`roles_drop\` checks ` +
|
|
143
|
+
`pg_shdepend first and refuses with the exact dependent objects instead of PostgreSQL's raw error when the role still owns something. ${CONFIRM_PROTOCOL_DESCRIPTION}`;
|
|
144
|
+
//# sourceMappingURL=roles.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"roles.js","sourceRoot":"","sources":["../../../src/tools/admin/roles.ts"],"names":[],"mappings":"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"}
|