@kozou/introspect 1.1.1 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -7,6 +7,14 @@ export type IntrospectOptions = {
7
7
  include?: string[];
8
8
  exclude?: string[];
9
9
  timeoutMs?: number;
10
+ /** Privilege-aware introspection (issue #99): when set, evaluate this role's
11
+ * table/column privileges and attach them to the raw output (consumed by
12
+ * `buildSchemaContext` to hide unreadable tables and lock non-updatable
13
+ * columns). The serving role — e.g. the Admin UI's minted-token role. When
14
+ * omitted, privileges are not evaluated and surfaces stay schema-faithful
15
+ * (the default; the MCP server deliberately leaves this unset to stay
16
+ * schema-wide). */
17
+ privilegeRole?: string;
10
18
  };
11
19
  export { KozouIntrospectError };
12
20
  export type { KozouIntrospectErrorOptions } from './errors.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAU,YAAY,EAAE,MAAM,IAAI,CAAC;AAC/C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAMpD,OAAO,EAAE,oBAAoB,EAAY,MAAM,aAAa,CAAC;AAK7D,MAAM,MAAM,iBAAiB,GAAG;IAC9B,UAAU,EAAE,MAAM,GAAG,YAAY,CAAC;IAClC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,OAAO,EAAE,oBAAoB,EAAE,CAAC;AAChC,YAAY,EAAE,2BAA2B,EAAE,MAAM,aAAa,CAAC;AAkB/D,wBAAsB,UAAU,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CA4EnF"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAU,YAAY,EAAE,MAAM,IAAI,CAAC;AAC/C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAOpD,OAAO,EAAE,oBAAoB,EAAY,MAAM,aAAa,CAAC;AAK7D,MAAM,MAAM,iBAAiB,GAAG;IAC9B,UAAU,EAAE,MAAM,GAAG,YAAY,CAAC;IAClC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;;wBAMoB;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,OAAO,EAAE,oBAAoB,EAAE,CAAC;AAChC,YAAY,EAAE,2BAA2B,EAAE,MAAM,aAAa,CAAC;AAkB/D,wBAAsB,UAAU,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAsFnF"}
package/dist/index.js CHANGED
@@ -4,6 +4,7 @@ import { fetchForeignKeys } from './fks.js';
4
4
  import { fetchChecks } from './checks.js';
5
5
  import { fetchViews } from './views.js';
6
6
  import { fetchEnums } from './enums.js';
7
+ import { fetchAndAttachPrivileges } from './privileges.js';
7
8
  import { KozouIntrospectError, runQuery } from './errors.js';
8
9
  import { filterTables, filterViews, pruneDanglingForeignKeys } from './filter.js';
9
10
  const PgClient = pkg.Client;
@@ -48,6 +49,9 @@ export async function introspect(opts) {
48
49
  mergeTableMetadata(allTables, fks, checks);
49
50
  const allViews = await fetchViews(client, validSchemas);
50
51
  const enums = await fetchEnums(client, validSchemas);
52
+ if (opts.privilegeRole !== undefined) {
53
+ await fetchAndAttachPrivileges(client, validSchemas, opts.privilegeRole, allTables, allViews);
54
+ }
51
55
  const filterOpts = { include: opts.include, exclude: opts.exclude };
52
56
  const tables = filterTables(allTables, filterOpts);
53
57
  pruneDanglingForeignKeys(tables);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,IAAI,CAAC;AAGrB,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,oBAAoB,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AAElF,MAAM,QAAQ,GAAG,GAAG,CAAC,MAAM,CAAC;AAU5B,OAAO,EAAE,oBAAoB,EAAE,CAAC;AAKhC,SAAS,aAAa,CAAC,KAAc;IACnC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,CAAC;AACrD,CAAC;AAED,KAAK,UAAU,oBAAoB,CAAC,MAAc,EAAE,OAAiB;IACnE,MAAM,IAAI,GAAG,MAAM,QAAQ,CACzB,MAAM,EACN,iFAAiF,EACjF,CAAC,OAAO,CAAC,EACT,sBAAsB,CACvB,CAAC;IACF,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;AACxC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,IAAuB;IACtD,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC3C,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,MAAM,CAAC;IAE3C,MAAM,UAAU,GACd,OAAO,IAAI,CAAC,UAAU,KAAK,QAAQ;QACjC,CAAC,CAAC,EAAE,gBAAgB,EAAE,IAAI,CAAC,UAAU,EAAE;QACvC,CAAC,CAAC,EAAE,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;IAC7B,MAAM,YAAY,GAAiB,EAAE,GAAG,UAAU,EAAE,iBAAiB,EAAE,SAAS,EAAE,CAAC;IAEnF,MAAM,MAAM,GAAG,IAAI,QAAQ,CAAC,YAAY,CAAC,CAAC;IAE1C,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,OAAO,EAAE,CAAC;IACzB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,KAAK,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5C,MAAM,IAAI,oBAAoB,CAC5B,oCAAoC,KAAK,CAAC,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC,EAAE,EAClE,EAAE,WAAW,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,CACxC,CAAC;IACJ,CAAC;IAED,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC5B,MAAM,MAAM,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC;QAEhD,MAAM,UAAU,GAAG,MAAM,QAAQ,CAC/B,MAAM,EACN,qBAAqB,EACrB,EAAE,EACF,mBAAmB,CACpB,CAAC;QACF,MAAM,aAAa,GAAG,UAAU,CAAC,CAAC,CAAC,EAAE,cAAc,IAAI,SAAS,CAAC;QAEjE,MAAM,QAAQ,GAAG,MAAM,oBAAoB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAC7D,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;YACxB,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC1B,OAAO,CAAC,IAAI,CAAC,+BAA+B,CAAC,yBAAyB,CAAC,CAAC;YAC1E,CAAC;QACH,CAAC;QACD,MAAM,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;QAEjE,MAAM,SAAS,GAAG,MAAM,WAAW,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;QAC1D,MAAM,GAAG,GAAG,MAAM,gBAAgB,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;QACzD,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;QACvD,kBAAkB,CAAC,SAAS,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;QAE3C,MAAM,QAAQ,GAAG,MAAM,UAAU,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;QACxD,MAAM,KAAK,GAAG,MAAM,UAAU,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;QAErD,MAAM,UAAU,GAAG,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC;QACpE,MAAM,MAAM,GAAG,YAAY,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;QACnD,wBAAwB,CAAC,MAAM,CAAC,CAAC;QACjC,MAAM,KAAK,GAAG,WAAW,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;QAEhD,OAAO;YACL,aAAa;YACb,cAAc,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACxC,OAAO;YACP,MAAM;YACN,KAAK;YACL,KAAK;YACL,SAAS,EAAE,EAAE;SACd,CAAC;IACJ,CAAC;YAAS,CAAC;QACT,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QACjC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,IAAI,CAAC,kDAAkD,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChF,CAAC;QACD,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,GAAG,EAAE,CAAC;QACrB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,IAAI,CAAC,oDAAoD,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAClF,CAAC;IACH,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import type { Client } from 'pg';
2
+ import type { RawTable, RawView } from '@kozou/core';
3
+ /**
4
+ * Evaluate the privileges of `role` on every base table / view (and base-table
5
+ * columns) in `schemas`, and attach them to the matching `RawTable` /
6
+ * `RawColumn` / `RawView`. Mutates the inputs in place (mirrors
7
+ * `mergeTableMetadata`). Call only when privilege-aware mode is on; otherwise
8
+ * the privilege fields stay `undefined`.
9
+ */
10
+ export declare function fetchAndAttachPrivileges(client: Client, schemas: string[], role: string, tables: RawTable[], views: RawView[]): Promise<void>;
11
+ //# sourceMappingURL=privileges.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"privileges.d.ts","sourceRoot":"","sources":["../src/privileges.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,IAAI,CAAC;AACjC,OAAO,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAqDrD;;;;;;GAMG;AACH,wBAAsB,wBAAwB,CAC5C,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EAAE,EACjB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,QAAQ,EAAE,EAClB,KAAK,EAAE,OAAO,EAAE,GACf,OAAO,CAAC,IAAI,CAAC,CA6Ff"}
@@ -0,0 +1,102 @@
1
+ import { KozouIntrospectError, runQuery } from './errors.js';
2
+ const tableKey = (schema, name) => `${schema}.${name}`;
3
+ /** Throw a clear error if the configured privilege role does not exist, rather
4
+ * than letting `has_table_privilege` fail mid-query with a terse pg message. */
5
+ async function assertRoleExists(client, role) {
6
+ const rows = await runQuery(client, 'SELECT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = $1) AS exists', [role], 'fetchPrivileges (role check)');
7
+ if (rows[0]?.exists !== true) {
8
+ throw new KozouIntrospectError(`introspection.respectPrivileges is on but the role "${role}" does not exist. ` +
9
+ 'Set it to the role the Admin UI assumes (auth.ui.role / auth.defaultRole), ' +
10
+ 'or turn privilege-aware introspection off.');
11
+ }
12
+ }
13
+ /**
14
+ * Evaluate the privileges of `role` on every base table / view (and base-table
15
+ * columns) in `schemas`, and attach them to the matching `RawTable` /
16
+ * `RawColumn` / `RawView`. Mutates the inputs in place (mirrors
17
+ * `mergeTableMetadata`). Call only when privilege-aware mode is on; otherwise
18
+ * the privilege fields stay `undefined`.
19
+ */
20
+ export async function fetchAndAttachPrivileges(client, schemas, role, tables, views) {
21
+ if (schemas.length === 0 || (tables.length === 0 && views.length === 0))
22
+ return;
23
+ await assertRoleExists(client, role);
24
+ // Every privilege is gated by schema USAGE: a role may hold a table/column
25
+ // grant yet still be denied at query time without USAGE on the schema, which
26
+ // would otherwise make the surface advertise access the role does not have.
27
+ // Relations covers base tables ('r'), views ('v'), and materialized views
28
+ // ('m') so views are hidden by the same SELECT/USAGE rule as tables.
29
+ const tableRows = await runQuery(client, `SELECT
30
+ n.nspname AS schema,
31
+ c.relname AS name,
32
+ has_schema_privilege($2, n.nspname, 'USAGE') AS usage,
33
+ has_table_privilege($2, c.oid, 'SELECT') AS sel,
34
+ has_table_privilege($2, c.oid, 'INSERT') AS ins,
35
+ has_table_privilege($2, c.oid, 'UPDATE') AS upd,
36
+ has_table_privilege($2, c.oid, 'DELETE') AS del
37
+ FROM pg_class c
38
+ JOIN pg_namespace n ON n.oid = c.relnamespace
39
+ WHERE c.relkind IN ('r', 'v', 'm')
40
+ AND n.nspname = ANY($1)`, [schemas, role], 'fetchPrivileges (relations)');
41
+ // `has_column_privilege` reports a column privilege as held when it is
42
+ // granted at the column level *or* table-wide, so this already subsumes
43
+ // table grants — exactly the "may the role write this column" question.
44
+ // Still gated by schema USAGE for the same reason as the table grants.
45
+ const columnRows = await runQuery(client, `SELECT
46
+ n.nspname AS schema,
47
+ c.relname AS table,
48
+ a.attname AS name,
49
+ has_schema_privilege($2, n.nspname, 'USAGE') AS usage,
50
+ has_column_privilege($2, c.oid, a.attname, 'INSERT') AS ins,
51
+ has_column_privilege($2, c.oid, a.attname, 'UPDATE') AS upd
52
+ FROM pg_attribute a
53
+ JOIN pg_class c ON c.oid = a.attrelid
54
+ JOIN pg_namespace n ON n.oid = c.relnamespace
55
+ WHERE c.relkind = 'r'
56
+ AND n.nspname = ANY($1)
57
+ AND a.attnum > 0
58
+ AND NOT a.attisdropped`, [schemas, role], 'fetchPrivileges (columns)');
59
+ const tablePrivByKey = new Map();
60
+ for (const row of tableRows)
61
+ tablePrivByKey.set(tableKey(row.schema, row.name), row);
62
+ const columnPrivByKey = new Map();
63
+ for (const row of columnRows) {
64
+ const key = tableKey(row.schema, row.table);
65
+ if (!columnPrivByKey.has(key))
66
+ columnPrivByKey.set(key, new Map());
67
+ columnPrivByKey.get(key).set(row.name, row);
68
+ }
69
+ // Gate each grant by schema USAGE so the attached privileges reflect what the
70
+ // role can actually do at query time (not just the relation ACL).
71
+ const gate = (tp) => ({
72
+ role,
73
+ select: tp.usage && tp.sel,
74
+ insert: tp.usage && tp.ins,
75
+ update: tp.usage && tp.upd,
76
+ delete: tp.usage && tp.del,
77
+ });
78
+ for (const table of tables) {
79
+ const key = tableKey(table.schema, table.name);
80
+ const tp = tablePrivByKey.get(key);
81
+ if (tp !== undefined)
82
+ table.privileges = gate(tp);
83
+ const cols = columnPrivByKey.get(key);
84
+ if (cols !== undefined) {
85
+ for (const column of table.columns) {
86
+ const cp = cols.get(column.name);
87
+ if (cp !== undefined) {
88
+ column.privileges = { insert: cp.usage && cp.ins, update: cp.usage && cp.upd };
89
+ }
90
+ }
91
+ }
92
+ }
93
+ // Views are hidden by the same USAGE + SELECT rule (a view the role cannot
94
+ // read would otherwise show in the nav and error on open). View columns are
95
+ // read-only in the Admin UI, so per-column privileges are not attached.
96
+ for (const view of views) {
97
+ const vp = tablePrivByKey.get(tableKey(view.schema, view.name));
98
+ if (vp !== undefined)
99
+ view.privileges = gate(vp);
100
+ }
101
+ }
102
+ //# sourceMappingURL=privileges.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"privileges.js","sourceRoot":"","sources":["../src/privileges.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kozou/introspect",
3
- "version": "1.1.1",
3
+ "version": "1.3.0",
4
4
  "description": "PostgreSQL DDL / COMMENT / VIEW introspection.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -31,7 +31,7 @@
31
31
  },
32
32
  "dependencies": {
33
33
  "pg": "^8.13.0",
34
- "@kozou/core": "1.1.1"
34
+ "@kozou/core": "1.3.0"
35
35
  },
36
36
  "devDependencies": {
37
37
  "@types/pg": "^8.11.0",