@happyvertical/smrt-core 0.49.3 → 0.49.5

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.
Files changed (156) hide show
  1. package/README.md +20 -0
  2. package/agents/change-feed.md +19 -0
  3. package/agents/collection-reads.md +21 -0
  4. package/agents/generators.md +5 -0
  5. package/agents/memory.md +23 -3
  6. package/agents/null-equal-indexes.md +88 -0
  7. package/agents/object-runtime.md +85 -0
  8. package/agents/schema-paths.md +7 -7
  9. package/dist/browser.js +2 -2
  10. package/dist/cascade.d.ts.map +1 -1
  11. package/dist/cascade.js +13 -10
  12. package/dist/cascade.js.map +1 -1
  13. package/dist/change-feed.d.ts +22 -0
  14. package/dist/change-feed.d.ts.map +1 -1
  15. package/dist/change-feed.js +147 -6
  16. package/dist/change-feed.js.map +1 -1
  17. package/dist/class.js +1 -1
  18. package/dist/collection-cache.d.ts +10 -1
  19. package/dist/collection-cache.d.ts.map +1 -1
  20. package/dist/collection-cache.js +65 -10
  21. package/dist/collection-cache.js.map +1 -1
  22. package/dist/collection.d.ts +69 -2
  23. package/dist/collection.d.ts.map +1 -1
  24. package/dist/collection.js +142 -9
  25. package/dist/collection.js.map +1 -1
  26. package/dist/consumer-plugin/artifact-publication.d.ts +27 -0
  27. package/dist/consumer-plugin/artifact-publication.d.ts.map +1 -0
  28. package/dist/consumer-plugin/artifact-publication.js +80 -0
  29. package/dist/consumer-plugin/artifact-publication.js.map +1 -0
  30. package/dist/consumer-plugin/index.d.ts.map +1 -1
  31. package/dist/consumer-plugin/index.js +44 -6
  32. package/dist/consumer-plugin/index.js.map +1 -1
  33. package/dist/db-errors.js +1 -1
  34. package/dist/db-errors.js.map +1 -1
  35. package/dist/embedded-write-queue.d.ts +1 -1
  36. package/dist/embedded-write-queue.d.ts.map +1 -1
  37. package/dist/embedded-write-queue.js +16 -6
  38. package/dist/embedded-write-queue.js.map +1 -1
  39. package/dist/embeddings/storage.d.ts +16 -0
  40. package/dist/embeddings/storage.d.ts.map +1 -1
  41. package/dist/embeddings/storage.js +40 -0
  42. package/dist/embeddings/storage.js.map +1 -1
  43. package/dist/index.d.ts +1 -1
  44. package/dist/index.d.ts.map +1 -1
  45. package/dist/index.js +3 -3
  46. package/dist/interceptors.d.ts +22 -0
  47. package/dist/interceptors.d.ts.map +1 -1
  48. package/dist/interceptors.js +12 -0
  49. package/dist/interceptors.js.map +1 -1
  50. package/dist/junction.d.ts +12 -3
  51. package/dist/junction.d.ts.map +1 -1
  52. package/dist/junction.js +34 -4
  53. package/dist/junction.js.map +1 -1
  54. package/dist/knowledge-config.d.ts +6 -0
  55. package/dist/knowledge-config.d.ts.map +1 -0
  56. package/dist/knowledge-config.js +48 -0
  57. package/dist/knowledge-config.js.map +1 -0
  58. package/dist/manifest/static-manifest.d.ts.map +1 -1
  59. package/dist/manifest/static-manifest.js +91 -1
  60. package/dist/manifest/static-manifest.js.map +1 -1
  61. package/dist/manifest/store.js +1 -1
  62. package/dist/manifest/store.js.map +1 -1
  63. package/dist/manifest.json +104 -1
  64. package/dist/migrations/differ.d.ts.map +1 -1
  65. package/dist/migrations/differ.js +2 -0
  66. package/dist/migrations/differ.js.map +1 -1
  67. package/dist/migrations/generator.d.ts.map +1 -1
  68. package/dist/migrations/generator.js +2 -0
  69. package/dist/migrations/generator.js.map +1 -1
  70. package/dist/migrations/index.d.ts +1 -0
  71. package/dist/migrations/index.d.ts.map +1 -1
  72. package/dist/migrations/index.js +2 -1
  73. package/dist/migrations/null-equal-indexes.d.ts +37 -0
  74. package/dist/migrations/null-equal-indexes.d.ts.map +1 -0
  75. package/dist/migrations/null-equal-indexes.js +133 -0
  76. package/dist/migrations/null-equal-indexes.js.map +1 -0
  77. package/dist/migrations/tracker.d.ts.map +1 -1
  78. package/dist/migrations/tracker.js +6 -0
  79. package/dist/migrations/tracker.js.map +1 -1
  80. package/dist/migrations.js +2 -1
  81. package/dist/object.d.ts +33 -0
  82. package/dist/object.d.ts.map +1 -1
  83. package/dist/object.js +316 -46
  84. package/dist/object.js.map +1 -1
  85. package/dist/plain-json.d.ts +6 -0
  86. package/dist/plain-json.d.ts.map +1 -0
  87. package/dist/plain-json.js +41 -0
  88. package/dist/plain-json.js.map +1 -0
  89. package/dist/postgres-permissions.d.ts.map +1 -1
  90. package/dist/postgres-permissions.js +6 -2
  91. package/dist/postgres-permissions.js.map +1 -1
  92. package/dist/prebuild/index.d.ts.map +1 -1
  93. package/dist/prebuild/index.js +3 -3
  94. package/dist/prebuild/index.js.map +1 -1
  95. package/dist/registry/class-registration.d.ts.map +1 -1
  96. package/dist/registry/class-registration.js +4 -1
  97. package/dist/registry/class-registration.js.map +1 -1
  98. package/dist/registry/schema-builder.d.ts.map +1 -1
  99. package/dist/registry/schema-builder.js +4 -3
  100. package/dist/registry/schema-builder.js.map +1 -1
  101. package/dist/registry/validator.d.ts +1 -0
  102. package/dist/registry/validator.d.ts.map +1 -1
  103. package/dist/registry/validator.js +8 -1
  104. package/dist/registry/validator.js.map +1 -1
  105. package/dist/registry.js +1 -1
  106. package/dist/scanner/manifest-generator.d.ts.map +1 -1
  107. package/dist/scanner/manifest-generator.js +21 -0
  108. package/dist/scanner/manifest-generator.js.map +1 -1
  109. package/dist/scanner/types.d.ts +2 -0
  110. package/dist/scanner/types.d.ts.map +1 -1
  111. package/dist/scanner/types.js.map +1 -1
  112. package/dist/schema/conflict-target.d.ts +8 -2
  113. package/dist/schema/conflict-target.d.ts.map +1 -1
  114. package/dist/schema/conflict-target.js +11 -3
  115. package/dist/schema/conflict-target.js.map +1 -1
  116. package/dist/schema/ddl/null-equal-index.d.ts +5 -0
  117. package/dist/schema/ddl/null-equal-index.d.ts.map +1 -0
  118. package/dist/schema/ddl/null-equal-index.js +17 -0
  119. package/dist/schema/ddl/null-equal-index.js.map +1 -0
  120. package/dist/schema/ddl/postgres-strategy.d.ts +2 -1
  121. package/dist/schema/ddl/postgres-strategy.d.ts.map +1 -1
  122. package/dist/schema/ddl/postgres-strategy.js +7 -0
  123. package/dist/schema/ddl/postgres-strategy.js.map +1 -1
  124. package/dist/schema/generator.d.ts.map +1 -1
  125. package/dist/schema/generator.js +8 -3
  126. package/dist/schema/generator.js.map +1 -1
  127. package/dist/schema/manifest-schema.d.ts +2 -1
  128. package/dist/schema/manifest-schema.d.ts.map +1 -1
  129. package/dist/schema/manifest-schema.js +12 -4
  130. package/dist/schema/manifest-schema.js.map +1 -1
  131. package/dist/schema/schema-manager.d.ts.map +1 -1
  132. package/dist/schema/schema-manager.js +1 -1
  133. package/dist/schema/schema-manager.js.map +1 -1
  134. package/dist/schema/types.d.ts +2 -0
  135. package/dist/schema/types.d.ts.map +1 -1
  136. package/dist/scripts/browser-plain-json-regression.mjs +85 -0
  137. package/dist/smrt-knowledge.json +73 -15
  138. package/dist/system/schema.d.ts +14 -3
  139. package/dist/system/schema.d.ts.map +1 -1
  140. package/dist/system/schema.js +120 -2
  141. package/dist/system/schema.js.map +1 -1
  142. package/dist/vite-plugin/api-client-entries.d.ts.map +1 -1
  143. package/dist/vite-plugin/api-client-entries.js +9 -7
  144. package/dist/vite-plugin/api-client-entries.js.map +1 -1
  145. package/dist/vite-plugin/index.d.ts +24 -0
  146. package/dist/vite-plugin/index.d.ts.map +1 -1
  147. package/dist/vite-plugin/index.js +48 -115
  148. package/dist/vite-plugin/index.js.map +1 -1
  149. package/dist/vite-plugin/sveltekit-generator.d.ts.map +1 -1
  150. package/dist/vite-plugin/sveltekit-generator.js +2 -2
  151. package/dist/vite-plugin/sveltekit-generator.js.map +1 -1
  152. package/dist/vite-plugin/web-collections.d.ts +18 -0
  153. package/dist/vite-plugin/web-collections.d.ts.map +1 -1
  154. package/dist/vite-plugin/web-collections.js +55 -2
  155. package/dist/vite-plugin/web-collections.js.map +1 -1
  156. package/package.json +5 -4
@@ -0,0 +1,6 @@
1
+ export type BoxedPrimitiveKind = 'bigint' | 'boolean' | 'number' | 'string';
2
+ export declare function getBoxedPrimitiveKind(value: object): BoxedPrimitiveKind | undefined;
3
+ export declare function isRawJSON(value: object): value is {
4
+ rawJSON: string;
5
+ };
6
+ //# sourceMappingURL=plain-json.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plain-json.d.ts","sourceRoot":"","sources":["../src/plain-json.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,kBAAkB,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAyB5E,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,MAAM,GACZ,kBAAkB,GAAG,SAAS,CA0BhC;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,CAOrE"}
@@ -0,0 +1,41 @@
1
+ //#region src/plain-json.ts
2
+ var nodeTypes = (() => {
3
+ const nodeProcess = globalThis.process;
4
+ const getBuiltinModule = nodeProcess?.getBuiltinModule;
5
+ if (typeof getBuiltinModule !== "function") return void 0;
6
+ return Reflect.apply(getBuiltinModule, nodeProcess, ["node:util"]).types;
7
+ })();
8
+ function getBoxedPrimitiveKind(value) {
9
+ if (nodeTypes) {
10
+ if (!nodeTypes.isBoxedPrimitive(value)) return void 0;
11
+ if (nodeTypes.isNumberObject(value)) return "number";
12
+ if (nodeTypes.isStringObject(value)) return "string";
13
+ if (nodeTypes.isBooleanObject(value)) return "boolean";
14
+ if (nodeTypes.isBigIntObject(value)) return "bigint";
15
+ return;
16
+ }
17
+ try {
18
+ Number.prototype.valueOf.call(value);
19
+ return "number";
20
+ } catch {}
21
+ try {
22
+ String.prototype.valueOf.call(value);
23
+ return "string";
24
+ } catch {}
25
+ try {
26
+ Boolean.prototype.valueOf.call(value);
27
+ return "boolean";
28
+ } catch {}
29
+ try {
30
+ BigInt.prototype.valueOf.call(value);
31
+ return "bigint";
32
+ } catch {}
33
+ }
34
+ function isRawJSON(value) {
35
+ const nativeJSON = JSON;
36
+ return typeof nativeJSON.isRawJSON === "function" && nativeJSON.isRawJSON(value);
37
+ }
38
+ //#endregion
39
+ export { getBoxedPrimitiveKind, isRawJSON };
40
+
41
+ //# sourceMappingURL=plain-json.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plain-json.js","names":[],"sources":["../src/plain-json.ts"],"sourcesContent":["export type BoxedPrimitiveKind = 'bigint' | 'boolean' | 'number' | 'string';\n\ntype NodeUtilTypes = {\n isBigIntObject(value: object): boolean;\n isBooleanObject(value: object): boolean;\n isBoxedPrimitive(value: object): boolean;\n isNumberObject(value: object): boolean;\n isStringObject(value: object): boolean;\n};\n\nconst nodeTypes = (() => {\n const nodeProcess = (\n globalThis as typeof globalThis & {\n process?: { getBuiltinModule?: (id: string) => unknown };\n }\n ).process;\n const getBuiltinModule = nodeProcess?.getBuiltinModule;\n if (typeof getBuiltinModule !== 'function') return undefined;\n return (\n Reflect.apply(getBuiltinModule, nodeProcess, ['node:util']) as {\n types?: NodeUtilTypes;\n }\n ).types;\n})();\n\nexport function getBoxedPrimitiveKind(\n value: object,\n): BoxedPrimitiveKind | undefined {\n if (nodeTypes) {\n if (!nodeTypes.isBoxedPrimitive(value)) return undefined;\n if (nodeTypes.isNumberObject(value)) return 'number';\n if (nodeTypes.isStringObject(value)) return 'string';\n if (nodeTypes.isBooleanObject(value)) return 'boolean';\n if (nodeTypes.isBigIntObject(value)) return 'bigint';\n return undefined;\n }\n try {\n Number.prototype.valueOf.call(value);\n return 'number';\n } catch {}\n try {\n String.prototype.valueOf.call(value);\n return 'string';\n } catch {}\n try {\n Boolean.prototype.valueOf.call(value);\n return 'boolean';\n } catch {}\n try {\n BigInt.prototype.valueOf.call(value);\n return 'bigint';\n } catch {}\n return undefined;\n}\n\nexport function isRawJSON(value: object): value is { rawJSON: string } {\n const nativeJSON = JSON as typeof JSON & {\n isRawJSON?: (value: unknown) => value is { rawJSON: string };\n };\n return (\n typeof nativeJSON.isRawJSON === 'function' && nativeJSON.isRawJSON(value)\n );\n}\n"],"mappings":";AAUA,IAAM,mBAAmB;CACvB,MAAM,cACJ,WAGA;CACF,MAAM,mBAAmB,aAAa;CACtC,IAAI,OAAO,qBAAqB,YAAY,OAAO,KAAA;CACnD,OACE,QAAQ,MAAM,kBAAkB,aAAa,CAAC,WAAW,CAAC,CAAC,CAG3D;AACJ,EAAA,CAAG;AAEH,SAAgB,sBACd,OACgC;CAChC,IAAI,WAAW;EACb,IAAI,CAAC,UAAU,iBAAiB,KAAK,GAAG,OAAO,KAAA;EAC/C,IAAI,UAAU,eAAe,KAAK,GAAG,OAAO;EAC5C,IAAI,UAAU,eAAe,KAAK,GAAG,OAAO;EAC5C,IAAI,UAAU,gBAAgB,KAAK,GAAG,OAAO;EAC7C,IAAI,UAAU,eAAe,KAAK,GAAG,OAAO;EAC5C;CACF;CACA,IAAI;EACF,OAAO,UAAU,QAAQ,KAAK,KAAK;EACnC,OAAO;CACT,QAAQ,CAAC;CACT,IAAI;EACF,OAAO,UAAU,QAAQ,KAAK,KAAK;EACnC,OAAO;CACT,QAAQ,CAAC;CACT,IAAI;EACF,QAAQ,UAAU,QAAQ,KAAK,KAAK;EACpC,OAAO;CACT,QAAQ,CAAC;CACT,IAAI;EACF,OAAO,UAAU,QAAQ,KAAK,KAAK;EACnC,OAAO;CACT,QAAQ,CAAC;AAEX;AAEA,SAAgB,UAAU,OAA6C;CACrE,MAAM,aAAa;CAGnB,OACE,OAAO,WAAW,cAAc,cAAc,WAAW,UAAU,KAAK;AAE5E"}
@@ -1 +1 @@
1
- {"version":3,"file":"postgres-permissions.d.ts","sourceRoot":"","sources":["../src/postgres-permissions.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAS5D,0EAA0E;AAC1E,MAAM,WAAW,0BAA0B;IACzC,MAAM,EAAE,MAAM,CAAC;IACf,+EAA+E;IAC/E,eAAe,EAAE,IAAI,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,gFAAgF;IAChF,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,0EAA0E;IAC1E,uBAAuB,CAAC,EAAE,MAAM,EAAE,CAAC;IACnC,OAAO,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAA;KAAE,CAAC;CAC9D;AAED,MAAM,WAAW,4BAA4B;IAC3C,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,SAAS,GAAG,WAAW,GAAG,aAAa,CAAC;IAClD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,0BAA0B,CAAC;IACrC,WAAW,EAAE,4BAA4B,EAAE,CAAC;IAC5C,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,KAAK,oCAAoC,GAAG,0BAA0B,GAAG;IACvE,uBAAuB,EAAE,MAAM,EAAE,CAAC;IAClC,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B,CAAC;AAEF,KAAK,QAAQ,GAAG,IAAI,CAAC,iBAAiB,EAAE,OAAO,CAAC,CAAC;AA2JjD,uFAAuF;AACvF,wBAAgB,kCAAkC,CAChD,KAAK,EAAE,OAAO,GACb,oCAAoC,CA2GtC;AA2+BD,oFAAoF;AACpF,wBAAsB,uBAAuB,CAC3C,EAAE,EAAE,QAAQ,EACZ,QAAQ,EAAE,0BAA0B,GACnC,OAAO,CAAC,sBAAsB,CAAC,CAEjC;AAED,iFAAiF;AACjF,wBAAsB,wBAAwB,CAC5C,EAAE,EAAE,iBAAiB,EACrB,QAAQ,EAAE,0BAA0B,EACpC,OAAO,EAAE;IAAE,mBAAmB,EAAE,MAAM,CAAA;CAAE,GACvC,OAAO,CAAC,sBAAsB,CAAC,CA8CjC"}
1
+ {"version":3,"file":"postgres-permissions.d.ts","sourceRoot":"","sources":["../src/postgres-permissions.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAW5D,0EAA0E;AAC1E,MAAM,WAAW,0BAA0B;IACzC,MAAM,EAAE,MAAM,CAAC;IACf,+EAA+E;IAC/E,eAAe,EAAE,IAAI,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,gFAAgF;IAChF,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,0EAA0E;IAC1E,uBAAuB,CAAC,EAAE,MAAM,EAAE,CAAC;IACnC,OAAO,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAA;KAAE,CAAC;CAC9D;AAED,MAAM,WAAW,4BAA4B;IAC3C,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,SAAS,GAAG,WAAW,GAAG,aAAa,CAAC;IAClD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,0BAA0B,CAAC;IACrC,WAAW,EAAE,4BAA4B,EAAE,CAAC;IAC5C,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,KAAK,oCAAoC,GAAG,0BAA0B,GAAG;IACvE,uBAAuB,EAAE,MAAM,EAAE,CAAC;IAClC,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B,CAAC;AAEF,KAAK,QAAQ,GAAG,IAAI,CAAC,iBAAiB,EAAE,OAAO,CAAC,CAAC;AA+JjD,uFAAuF;AACvF,wBAAgB,kCAAkC,CAChD,KAAK,EAAE,OAAO,GACb,oCAAoC,CA2GtC;AA2+BD,oFAAoF;AACpF,wBAAsB,uBAAuB,CAC3C,EAAE,EAAE,QAAQ,EACZ,QAAQ,EAAE,0BAA0B,GACnC,OAAO,CAAC,sBAAsB,CAAC,CAEjC;AAED,iFAAiF;AACjF,wBAAsB,wBAAwB,CAC5C,EAAE,EAAE,iBAAiB,EACrB,QAAQ,EAAE,0BAA0B,EACpC,OAAO,EAAE;IAAE,mBAAmB,EAAE,MAAM,CAAA;CAAE,GACvC,OAAO,CAAC,sBAAsB,CAAC,CA8CjC"}
@@ -1,4 +1,4 @@
1
- import { CREATE_POSTGRES_CHANGE_FEED_APPEND_FUNCTION, CREATE_POSTGRES_CHANGE_FEED_DRAIN_FUNCTION, POSTGRES_CHANGE_FEED_APPEND_FUNCTION_IDENTITY, POSTGRES_CHANGE_FEED_DRAIN_BATCH, POSTGRES_CHANGE_FEED_DRAIN_FUNCTION_IDENTITY } from "./system/schema.js";
1
+ import { CREATE_POSTGRES_CHANGE_FEED_APPEND_BATCH_FUNCTION, CREATE_POSTGRES_CHANGE_FEED_APPEND_FUNCTION, CREATE_POSTGRES_CHANGE_FEED_DRAIN_FUNCTION, POSTGRES_CHANGE_FEED_APPEND_BATCH_FUNCTION_IDENTITY, POSTGRES_CHANGE_FEED_APPEND_FUNCTION_IDENTITY, POSTGRES_CHANGE_FEED_DRAIN_BATCH, POSTGRES_CHANGE_FEED_DRAIN_FUNCTION_IDENTITY } from "./system/schema.js";
2
2
  import { createHash } from "node:crypto";
3
3
  //#region src/postgres-permissions.ts
4
4
  var bookkeeping = /* @__PURE__ */ new Set([
@@ -33,7 +33,11 @@ function frameworkRoutine(identity, ddl) {
33
33
  source: sourceFromFunctionDdl(ddl)
34
34
  };
35
35
  }
36
- var frameworkRoutines = [frameworkRoutine(POSTGRES_CHANGE_FEED_APPEND_FUNCTION_IDENTITY, CREATE_POSTGRES_CHANGE_FEED_APPEND_FUNCTION), frameworkRoutine(POSTGRES_CHANGE_FEED_DRAIN_FUNCTION_IDENTITY, CREATE_POSTGRES_CHANGE_FEED_DRAIN_FUNCTION)];
36
+ var frameworkRoutines = [
37
+ frameworkRoutine(POSTGRES_CHANGE_FEED_APPEND_FUNCTION_IDENTITY, CREATE_POSTGRES_CHANGE_FEED_APPEND_FUNCTION),
38
+ frameworkRoutine(POSTGRES_CHANGE_FEED_APPEND_BATCH_FUNCTION_IDENTITY, CREATE_POSTGRES_CHANGE_FEED_APPEND_BATCH_FUNCTION),
39
+ frameworkRoutine(POSTGRES_CHANGE_FEED_DRAIN_FUNCTION_IDENTITY, CREATE_POSTGRES_CHANGE_FEED_DRAIN_FUNCTION)
40
+ ];
37
41
  function object(value, keys, label) {
38
42
  if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error(`${label} must be an object.`);
39
43
  for (const key of Object.keys(value)) if (!keys.includes(key)) throw new Error(`Unknown ${label} property: ${key}.`);
@@ -1 +1 @@
1
- {"version":3,"file":"postgres-permissions.js","names":[],"sources":["../src/postgres-permissions.ts"],"sourcesContent":["import { createHash } from 'node:crypto';\nimport type { DatabaseInterface } from '@happyvertical/sql';\nimport {\n CREATE_POSTGRES_CHANGE_FEED_APPEND_FUNCTION,\n CREATE_POSTGRES_CHANGE_FEED_DRAIN_FUNCTION,\n POSTGRES_CHANGE_FEED_APPEND_FUNCTION_IDENTITY,\n POSTGRES_CHANGE_FEED_DRAIN_BATCH,\n POSTGRES_CHANGE_FEED_DRAIN_FUNCTION_IDENTITY,\n} from './system/schema.js';\n\n/** PostgreSQL ACLs only; this is not application authorization or RLS. */\nexport interface PostgresPermissionContract {\n schema: string;\n /** Defaults affect every future object created by migrationOwner in schema. */\n schemaExclusive: true;\n migrationOwner: string;\n runtimeRole: string;\n managedTables: string[];\n /** Existing operator-owned tables retained outside the runtime data surface. */\n retainedTables?: string[];\n /** Exact zero-argument trigger functions bound only to managed tables. */\n managedTriggerFunctions?: string[];\n monitor?: { role: string; tables: Record<string, string[]> };\n}\n\nexport interface PostgresPermissionDiagnostic {\n code: string;\n severity: 'missing' | 'excessive' | 'unsupported';\n role?: string;\n resource: string;\n message: string;\n}\n\nexport interface PostgresPermissionPlan {\n contract: PostgresPermissionContract;\n diagnostics: PostgresPermissionDiagnostic[];\n statements: string[];\n canApply: boolean;\n fingerprint: string;\n limitations: string[];\n}\n\ntype NormalizedPostgresPermissionContract = PostgresPermissionContract & {\n managedTriggerFunctions: string[];\n retainedTables: string[];\n};\n\ntype Executor = Pick<DatabaseInterface, 'query'>;\ninterface Row {\n [key: string]: unknown;\n oid: string;\n name: string;\n schema: string;\n identity: string;\n argument_types: string;\n argument_count: string;\n argument_defaults: string | null;\n return_type: string;\n result: string;\n cost: string;\n rows: string;\n support: string;\n language: string;\n security_definer: boolean;\n config: unknown;\n source: string;\n volatility: string;\n parallel: string;\n leakproof: boolean;\n strict: boolean;\n function_oid: string;\n table_name: string;\n enabled: string;\n internal: boolean;\n owner: string;\n acl: Acl[];\n kind: string;\n rolname: string;\n member: string;\n parent: string;\n relation: string;\n parent_table: string | null;\n child_schema: string;\n child_table: string;\n parent_schema: string;\n delete_action: string;\n update_action: string;\n rule_name: string;\n referenced_schema: string;\n referenced_table: string;\n version: string;\n executor: string;\n superuser: boolean;\n rls: boolean;\n}\ntype Acl = {\n grantee: string;\n privilege: string;\n grantable: boolean;\n grantor?: string;\n};\nconst bookkeeping = new Set([\n '_smrt_migrations',\n '_smrt_schema_migrations',\n '_smrt_backfills',\n]);\nconst identifier = (value: string) => `\"${value.replaceAll('\"', '\"\"')}\"`;\nconst literal = (value: string) =>\n `E'${value.replaceAll('\\\\', '\\\\\\\\').replaceAll(\"'\", \"''\")}'`;\nconst qualified = (schema: string, name: string) =>\n `${identifier(schema)}.${identifier(name)}`;\n\nconst normalizeFunctionSource = (value: string) =>\n value.replaceAll('\\r\\n', '\\n').trim();\nconst normalizeArgumentTypes = (value: string) =>\n value.replaceAll(/\\s*,\\s*/g, ',');\nconst normalizeFunctionResult = (value: string) =>\n value\n .replaceAll(/\\s+/g, ' ')\n .replaceAll(/\\s*,\\s*/g, ',')\n .replaceAll(/\\(\\s*/g, '(')\n .replaceAll(/\\s*\\)/g, ')')\n .trim()\n .toLowerCase();\n\nfunction sourceFromFunctionDdl(ddl: string): string {\n const match = ddl.match(\n /\\bAS\\s+\\$([A-Za-z_][A-Za-z0-9_]*)\\$\\n([\\s\\S]*?)\\n\\$\\1\\$;/,\n );\n if (!match)\n throw new Error('Framework function DDL has no dollar-quoted body.');\n return normalizeFunctionSource(match[2]);\n}\n\nfunction resultFromFunctionDdl(ddl: string): string {\n const match = ddl.match(/\\bRETURNS\\s+([\\s\\S]*?)\\nLANGUAGE\\s+/);\n if (!match) throw new Error('Framework function DDL has no return result.');\n return normalizeFunctionResult(match[1]);\n}\n\ntype FrameworkRoutine = {\n name: string;\n argumentTypes: string;\n argumentDefaults: string | null;\n result: string;\n source: string;\n};\n\nfunction frameworkRoutine(identity: string, ddl: string): FrameworkRoutine {\n const match = identity.match(/^([^()]+)\\((.*)\\)$/);\n if (!match)\n throw new Error(`Invalid framework function identity: ${identity}`);\n return {\n name: match[1],\n argumentTypes: normalizeArgumentTypes(match[2]),\n argumentDefaults:\n match[1] === '_smrt_drain_changes'\n ? String(POSTGRES_CHANGE_FEED_DRAIN_BATCH)\n : null,\n result: resultFromFunctionDdl(ddl),\n source: sourceFromFunctionDdl(ddl),\n };\n}\n\nconst frameworkRoutines = [\n frameworkRoutine(\n POSTGRES_CHANGE_FEED_APPEND_FUNCTION_IDENTITY,\n CREATE_POSTGRES_CHANGE_FEED_APPEND_FUNCTION,\n ),\n frameworkRoutine(\n POSTGRES_CHANGE_FEED_DRAIN_FUNCTION_IDENTITY,\n CREATE_POSTGRES_CHANGE_FEED_DRAIN_FUNCTION,\n ),\n];\n\nfunction object(\n value: unknown,\n keys: string[],\n label: string,\n): Record<string, unknown> {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n throw new Error(`${label} must be an object.`);\n }\n for (const key of Object.keys(value)) {\n if (!keys.includes(key))\n throw new Error(`Unknown ${label} property: ${key}.`);\n }\n return value as Record<string, unknown>;\n}\nfunction name(value: unknown, label: string): string {\n if (\n typeof value !== 'string' ||\n !value.length ||\n value.includes('\\0') ||\n Buffer.byteLength(value) > 63\n ) {\n throw new Error(\n `${label} must be a nonempty PostgreSQL identifier (at most 63 bytes).`,\n );\n }\n return value;\n}\n/** Validate configuration before opening a connection; unknown options fail closed. */\nexport function validatePostgresPermissionContract(\n value: unknown,\n): NormalizedPostgresPermissionContract {\n const input = object(\n value,\n [\n 'schema',\n 'schemaExclusive',\n 'migrationOwner',\n 'runtimeRole',\n 'managedTables',\n 'retainedTables',\n 'managedTriggerFunctions',\n 'monitor',\n ],\n 'postgresPermissions',\n );\n if (input.schemaExclusive !== true)\n throw new Error(\n 'postgresPermissions.schemaExclusive must explicitly be true.',\n );\n const schema = name(input.schema, 'schema');\n if (schema === 'information_schema' || schema.startsWith('pg_'))\n throw new Error('A dedicated application schema is required.');\n const migrationOwner = name(input.migrationOwner, 'migrationOwner');\n const runtimeRole = name(input.runtimeRole, 'runtimeRole');\n if (!Array.isArray(input.managedTables))\n throw new Error('managedTables must be an array.');\n const managedTables = [\n ...new Set(\n input.managedTables.map((table) => name(table, 'managedTables entry')),\n ),\n ].sort();\n if (\n input.retainedTables !== undefined &&\n !Array.isArray(input.retainedTables)\n )\n throw new Error('retainedTables must be an array.');\n const retainedTables = [\n ...new Set(\n (input.retainedTables ?? []).map((table) =>\n name(table, 'retainedTables entry'),\n ),\n ),\n ].sort();\n const overlap = retainedTables.find((table) => managedTables.includes(table));\n if (overlap)\n throw new Error(`Table ${overlap} cannot be both managed and retained.`);\n if (\n input.managedTriggerFunctions !== undefined &&\n !Array.isArray(input.managedTriggerFunctions)\n )\n throw new Error('managedTriggerFunctions must be an array.');\n const managedTriggerFunctions = [\n ...new Set(\n (input.managedTriggerFunctions ?? []).map((routine) =>\n name(routine, 'managedTriggerFunctions entry'),\n ),\n ),\n ].sort();\n let monitor: PostgresPermissionContract['monitor'];\n if (input.monitor !== undefined) {\n const entry = object(input.monitor, ['role', 'tables'], 'monitor');\n const role = name(entry.role, 'monitor.role');\n if (\n !entry.tables ||\n typeof entry.tables !== 'object' ||\n Array.isArray(entry.tables)\n )\n throw new Error('monitor.tables must map tables to column arrays.');\n const tables: Record<string, string[]> = Object.create(null);\n for (const [table, columns] of Object.entries(entry.tables).sort(\n ([a], [b]) => a.localeCompare(b),\n )) {\n name(table, 'monitor table');\n if (!Array.isArray(columns) || !columns.length)\n throw new Error(\n `monitor table ${table} requires a nonempty column array.`,\n );\n tables[table] = [\n ...new Set(columns.map((column) => name(column, 'monitor column'))),\n ].sort();\n }\n monitor = { role, tables };\n }\n const roles = [\n migrationOwner,\n runtimeRole,\n ...(monitor ? [monitor.role] : []),\n ];\n if (\n new Set(roles).size !== roles.length ||\n roles.some(\n (role) => role.toUpperCase() === 'PUBLIC' || role.startsWith('pg_'),\n )\n )\n throw new Error(\n 'Migration, runtime and monitor roles must be distinct non-system roles.',\n );\n return {\n schema,\n schemaExclusive: true,\n migrationOwner,\n runtimeRole,\n managedTables,\n retainedTables,\n managedTriggerFunctions,\n ...(monitor ? { monitor } : {}),\n };\n}\n\nconst acl = (expression: string) =>\n `COALESCE((SELECT json_agg(json_build_object('grantee', CASE WHEN a.grantee = 0 THEN 'PUBLIC' ELSE pg_get_userbyid(a.grantee) END, 'grantor', pg_get_userbyid(a.grantor), 'privilege', a.privilege_type, 'grantable', a.is_grantable) ORDER BY a.grantee, a.privilege_type, a.grantor) FROM aclexplode(${expression}) a), '[]'::json)`;\n\nasync function snapshot(\n db: Executor,\n contract: NormalizedPostgresPermissionContract,\n): Promise<Record<string, Row[]>> {\n const roleNames = [\n contract.migrationOwner,\n contract.runtimeRole,\n ...(contract.monitor ? [contract.monitor.role] : []),\n ]\n .map(literal)\n .join(',');\n const restrictedRoleNames = [\n contract.runtimeRole,\n ...(contract.monitor ? [contract.monitor.role] : []),\n ]\n .map(literal)\n .join(',');\n // information_schema.sql runs after initial ACL recording. Trust only its\n // explicitly PUBLIC-readable stock relations, never internal metadata views.\n // Normal-operation OIDs start at 16384:\n // https://www.postgresql.org/docs/16/system-catalog-initial-data.html\n // Source: postgres/postgres REL_14_STABLE..REL_18_STABLE,\n // GRANT SELECT [ON TABLE] ... TO PUBLIC in:\n // https://github.com/postgres/postgres/blob/REL_14_STABLE/src/backend/catalog/information_schema.sql\n // https://github.com/postgres/postgres/blob/REL_18_STABLE/src/backend/catalog/information_schema.sql\n const informationSchemaPublicSelect =\n \"'administrable_role_authorizations','applicable_roles','attributes','character_sets','check_constraint_routine_usage','check_constraints','collation_character_set_applicability','collations','column_column_usage','column_domain_usage','column_options','column_privileges','column_udt_usage','columns','constraint_column_usage','constraint_table_usage','data_type_privileges','domain_constraints','domain_udt_usage','domains','element_types','enabled_roles','foreign_data_wrapper_options','foreign_data_wrappers','foreign_server_options','foreign_servers','foreign_table_options','foreign_tables','information_schema_catalog_name','key_column_usage','parameters','referential_constraints','role_column_grants','role_routine_grants','role_table_grants','role_udt_grants','role_usage_grants','routine_column_usage','routine_privileges','routine_routine_usage','routine_sequence_usage','routine_table_usage','routines','schemata','sequences','sql_features','sql_implementation_info','sql_sizing','table_constraints','table_privileges','tables','triggered_update_columns','triggers','udt_privileges','usage_privileges','user_defined_types','user_mapping_options','user_mappings','view_column_usage','view_routine_usage','view_table_usage','views'\";\n // pg_init_privs records non-default initial ACLs. Missing entries use the\n // PostgreSQL object-kind default; extension-provided ACLs are not stock trust.\n // https://www.postgresql.org/docs/current/catalog-pg-init-privs.html\n const initialAcl = (fallback: string) =>\n `CASE WHEN i.privtype='i' THEN i.initprivs WHEN i.privtype='e' THEN NULL::aclitem[] ELSE ${fallback} END`;\n // Only a type referenced by another type's typarray is its generated array.\n // Nonzero typelem also describes non-array types (point); domains over arrays\n // remain independent privilege targets and must not be filtered out.\n const queries: Record<string, string> = {\n server: `SELECT current_setting('server_version_num') AS version, current_database() AS database, current_user AS executor, (SELECT rolsuper FROM pg_roles WHERE rolname=current_user) AS superuser`,\n roles: `SELECT oid::text, rolname, rolsuper, rolcreaterole, rolcreatedb, rolreplication, rolbypassrls FROM pg_roles WHERE rolname IN (${roleNames}) ORDER BY rolname`,\n memberships: `SELECT pg_get_userbyid(member) AS member, pg_get_userbyid(roleid) AS parent FROM pg_auth_members WHERE member IN (SELECT oid FROM pg_roles WHERE rolname IN (${roleNames})) OR roleid IN (SELECT oid FROM pg_roles WHERE rolname IN (${roleNames})) ORDER BY member, roleid`,\n database: `SELECT datname AS name, pg_get_userbyid(datdba) AS owner, ${acl(\"COALESCE(datacl, acldefault('d',datdba))\")} AS acl FROM pg_database WHERE datname=current_database()`,\n schemas: `SELECT nspname AS name, pg_get_userbyid(nspowner) AS owner, ${acl(\"COALESCE(nspacl, acldefault('n',nspowner))\")} AS acl FROM pg_namespace WHERE left(nspname,3) <> 'pg_' AND nspname <> 'information_schema' ORDER BY nspname`,\n relations: `SELECT c.oid::text, n.nspname AS schema, c.relname AS name, c.relkind AS kind, pg_get_userbyid(c.relowner) AS owner, c.relrowsecurity AS rls, (SELECT parent.relname FROM pg_depend d JOIN pg_class parent ON parent.oid=d.refobjid JOIN pg_namespace parent_schema ON parent_schema.oid=parent.relnamespace WHERE d.classid='pg_class'::regclass AND d.objid=c.oid AND d.refclassid='pg_class'::regclass AND d.deptype IN ('a','i') AND parent_schema.oid=n.oid LIMIT 1) AS parent_table, ${acl(\"COALESCE(c.relacl, acldefault(CASE WHEN c.relkind='S' THEN 's'::\\\"char\\\" ELSE 'r'::\\\"char\\\" END,c.relowner))\")} AS acl FROM pg_class c JOIN pg_namespace n ON n.oid=c.relnamespace WHERE left(n.nspname,3) <> 'pg_' AND n.nspname <> 'information_schema' AND c.relkind IN ('r','p','v','m','f','S') ORDER BY n.nspname,c.relname`,\n inherits: `SELECT child_schema.nspname AS child_schema, child.relname AS child_table, parent_schema.nspname AS parent_schema, parent.relname AS parent_table FROM pg_inherits i JOIN pg_class child ON child.oid=i.inhrelid JOIN pg_namespace child_schema ON child_schema.oid=child.relnamespace JOIN pg_class parent ON parent.oid=i.inhparent JOIN pg_namespace parent_schema ON parent_schema.oid=parent.relnamespace ORDER BY child_schema.nspname,child.relname,parent_schema.nspname,parent.relname`,\n foreignKeys: `SELECT child_schema.nspname AS child_schema, child.relname AS child_table, parent_schema.nspname AS parent_schema, parent.relname AS parent_table, con.confdeltype::text AS delete_action, con.confupdtype::text AS update_action FROM pg_constraint con JOIN pg_class child ON child.oid=con.conrelid JOIN pg_namespace child_schema ON child_schema.oid=child.relnamespace JOIN pg_class parent ON parent.oid=con.confrelid JOIN pg_namespace parent_schema ON parent_schema.oid=parent.relnamespace WHERE con.contype='f' ORDER BY child_schema.nspname,child.relname,parent_schema.nspname,parent.relname,con.conname`,\n rewriteRules: `WITH RECURSIVE rule_dependencies AS (SELECT r.oid AS rule_oid, r.ev_class AS source_oid, r.rulename AS rule_name, d.refobjid AS referenced_oid FROM pg_rewrite r JOIN pg_depend d ON d.classid='pg_rewrite'::regclass AND d.objid=r.oid AND d.refclassid='pg_class'::regclass WHERE r.rulename <> '_RETURN' UNION SELECT dependencies.rule_oid, dependencies.source_oid, dependencies.rule_name, d.refobjid FROM rule_dependencies dependencies JOIN pg_rewrite view_rule ON view_rule.ev_class=dependencies.referenced_oid AND view_rule.rulename='_RETURN' JOIN pg_depend d ON d.classid='pg_rewrite'::regclass AND d.objid=view_rule.oid AND d.refclassid='pg_class'::regclass) SELECT n.nspname AS schema, c.relname AS table_name, dependencies.rule_name, referenced_schema.nspname AS referenced_schema, referenced.relname AS referenced_table FROM rule_dependencies dependencies JOIN pg_class c ON c.oid=dependencies.source_oid JOIN pg_namespace n ON n.oid=c.relnamespace JOIN pg_class referenced ON referenced.oid=dependencies.referenced_oid JOIN pg_namespace referenced_schema ON referenced_schema.oid=referenced.relnamespace ORDER BY n.nspname,c.relname,dependencies.rule_name,referenced_schema.nspname,referenced.relname`,\n columns: `SELECT c.oid::text AS relation, a.attname AS name, ${acl('a.attacl')} AS acl FROM pg_attribute a JOIN pg_class c ON c.oid=a.attrelid JOIN pg_namespace n ON n.oid=c.relnamespace WHERE left(n.nspname,3) <> 'pg_' AND n.nspname <> 'information_schema' AND c.relkind IN ('r','p','v','m','f') AND a.attnum>0 AND NOT a.attisdropped ORDER BY c.oid,a.attnum`,\n routines: `SELECT n.nspname AS schema, p.oid::text, p.proname AS name, format('%I.%I(%s)', n.nspname, p.proname, oidvectortypes(p.proargtypes)) AS identity, oidvectortypes(p.proargtypes) AS argument_types, pg_get_expr(p.proargdefaults,0) AS argument_defaults, p.prokind AS kind, p.prorettype::regtype::text AS return_type, pg_get_function_result(p.oid) AS result, p.procost::text AS cost, p.prorows::text AS rows, p.prosupport::regproc::text AS support, p.pronargs::text AS argument_count, l.lanname AS language, p.prosecdef AS security_definer, p.provolatile::text AS volatility, p.proparallel::text AS parallel, p.proleakproof AS leakproof, p.proisstrict AS strict, COALESCE(to_json(p.proconfig),'[]'::json) AS config, p.prosrc AS source, CASE WHEN p.prokind='f' THEN pg_get_functiondef(p.oid) END AS definition, pg_get_userbyid(p.proowner) AS owner, ${acl(\"COALESCE(p.proacl, acldefault('f',p.proowner))\")} AS acl FROM pg_proc p JOIN pg_namespace n ON n.oid=p.pronamespace JOIN pg_language l ON l.oid=p.prolang WHERE left(n.nspname,3) <> 'pg_' AND n.nspname <> 'information_schema' ORDER BY n.nspname,p.oid`,\n triggers: `SELECT t.oid::text, n.nspname AS schema, c.relname AS table_name, t.tgname AS name, t.tgfoid::text AS function_oid, t.tgenabled AS enabled, t.tgisinternal AS internal, t.tgtype::text AS type, encode(t.tgargs,'hex') AS arguments, pg_get_triggerdef(t.oid, true) AS definition FROM pg_trigger t JOIN pg_class c ON c.oid=t.tgrelid JOIN pg_namespace n ON n.oid=c.relnamespace WHERE left(n.nspname,3) <> 'pg_' AND n.nspname <> 'information_schema' ORDER BY n.nspname,c.oid,t.oid`,\n types: `SELECT n.nspname AS schema, t.typname AS name, pg_get_userbyid(t.typowner) AS owner, ${acl(\"COALESCE(t.typacl, acldefault('T',t.typowner))\")} AS acl FROM pg_type t JOIN pg_namespace n ON n.oid=t.typnamespace LEFT JOIN pg_class c ON c.oid=t.typrelid WHERE left(n.nspname,3) <> 'pg_' AND n.nspname <> 'information_schema' AND NOT EXISTS (SELECT 1 FROM pg_type element WHERE element.typarray=t.oid) AND (t.typrelid=0 OR c.relkind='c') ORDER BY n.nspname,t.typname`,\n systemSchemas: `SELECT nspname AS name, pg_get_userbyid(nspowner) AS owner, ${acl(\"COALESCE(nspacl, acldefault('n',nspowner))\")} AS acl FROM pg_namespace WHERE left(nspname,3)='pg_' OR nspname='information_schema' ORDER BY nspname`,\n systemPrivileges: `WITH resources AS (\n SELECT n.nspname AS schema, c.relname AS name, c.oid::text AS oid, CASE WHEN c.relkind='S' THEN 'sequence' ELSE 'relation' END AS kind, pg_get_userbyid(c.relowner) AS owner,\n COALESCE(c.relacl,acldefault(CASE WHEN c.relkind='S' THEN 's'::\"char\" ELSE 'r'::\"char\" END,c.relowner)) AS current_acl,\n CASE WHEN i.objoid IS NULL AND n.nspname='information_schema' AND c.oid<16384 AND c.relname IN (${informationSchemaPublicSelect}) THEN ARRAY[makeaclitem(0,c.relowner,'SELECT',false)] ELSE ${initialAcl(\"acldefault(CASE WHEN c.relkind='S' THEN 's'::\\\"char\\\" ELSE 'r'::\\\"char\\\" END,c.relowner)\")} END AS initial_acl\n FROM pg_class c JOIN pg_namespace n ON n.oid=c.relnamespace\n LEFT JOIN pg_init_privs i ON i.objoid=c.oid AND i.classoid='pg_class'::regclass AND i.objsubid=0\n WHERE (left(n.nspname,3)='pg_' OR n.nspname='information_schema') AND c.relkind IN ('r','p','v','m','f','S')\n UNION ALL\n SELECT n.nspname, c.relname || '.' || a.attname, c.oid::text || ':' || a.attnum::text, 'column', pg_get_userbyid(c.relowner),\n a.attacl, ${initialAcl('NULL::aclitem[]')}\n FROM pg_attribute a JOIN pg_class c ON c.oid=a.attrelid JOIN pg_namespace n ON n.oid=c.relnamespace\n LEFT JOIN pg_init_privs i ON i.objoid=c.oid AND i.classoid='pg_class'::regclass AND i.objsubid=a.attnum\n WHERE (left(n.nspname,3)='pg_' OR n.nspname='information_schema') AND a.attnum>0 AND NOT a.attisdropped\n UNION ALL\n SELECT n.nspname, p.proname, p.oid::text, 'routine', pg_get_userbyid(p.proowner), COALESCE(p.proacl,acldefault('f',p.proowner)), ${initialAcl(\"CASE WHEN p.oid<16384 THEN acldefault('f',p.proowner) ELSE NULL::aclitem[] END\")}\n FROM pg_proc p JOIN pg_namespace n ON n.oid=p.pronamespace\n LEFT JOIN pg_init_privs i ON i.objoid=p.oid AND i.classoid='pg_proc'::regclass AND i.objsubid=0\n WHERE left(n.nspname,3)='pg_' OR n.nspname='information_schema'\n UNION ALL\n SELECT n.nspname, t.typname, t.oid::text, 'type', pg_get_userbyid(t.typowner), COALESCE(t.typacl,acldefault('T',t.typowner)), ${initialAcl(\"CASE WHEN t.oid<16384 THEN acldefault('T',t.typowner) ELSE NULL::aclitem[] END\")}\n FROM pg_type t JOIN pg_namespace n ON n.oid=t.typnamespace LEFT JOIN pg_class c ON c.oid=t.typrelid\n LEFT JOIN pg_init_privs i ON i.objoid=t.oid AND i.classoid='pg_type'::regclass AND i.objsubid=0\n WHERE (left(n.nspname,3)='pg_' OR n.nspname='information_schema') AND NOT EXISTS (SELECT 1 FROM pg_type element WHERE element.typarray=t.oid) AND (t.typrelid=0 OR c.relkind='c')\n ) SELECT r.schema,r.name,r.oid,r.kind,r.owner,COALESCE(d.acl,'[]'::json) AS acl FROM resources r\n CROSS JOIN LATERAL (\n SELECT json_agg(json_build_object('grantee', CASE WHEN a.grantee=0 THEN 'PUBLIC' ELSE pg_get_userbyid(a.grantee) END,\n 'grantor',pg_get_userbyid(a.grantor),'privilege',a.privilege_type,'grantable',a.is_grantable)\n ORDER BY a.grantee,a.privilege_type,a.grantor) AS acl\n FROM aclexplode(r.current_acl) a\n WHERE a.grantee IN (SELECT oid FROM pg_roles WHERE rolname IN (${restrictedRoleNames}))\n OR (a.grantee=0 AND NOT EXISTS (SELECT 1 FROM aclexplode(r.initial_acl) b WHERE b.grantee=0 AND b.privilege_type=a.privilege_type AND (b.is_grantable OR NOT a.is_grantable)))\n ) d WHERE d.acl IS NOT NULL OR (r.kind<>'column' AND r.owner IN (${restrictedRoleNames})) ORDER BY r.schema,r.kind,r.name,r.oid`,\n largeObjects: `SELECT oid::text, pg_get_userbyid(lomowner) AS owner, ${acl(\"COALESCE(lomacl, acldefault('L',lomowner))\")} AS acl FROM pg_largeobject_metadata ORDER BY oid`,\n largeObjectSettings: `SELECT setting,reset_val,source FROM pg_settings WHERE name='lo_compat_privileges'`,\n largeObjectRoleSettings: `SELECT s.setdatabase::text AS database, CASE WHEN s.setrole=0 THEN 'ALL ROLES' ELSE pg_get_userbyid(s.setrole) END AS role, split_part(config.value,'=',2) AS setting FROM pg_db_role_setting s CROSS JOIN LATERAL unnest(s.setconfig) config(value) WHERE s.setdatabase IN (0,(SELECT oid FROM pg_database WHERE datname=current_database())) AND (s.setrole=0 OR s.setrole IN (SELECT oid FROM pg_roles WHERE rolname IN (${restrictedRoleNames}))) AND split_part(config.value,'=',1)='lo_compat_privileges' ORDER BY s.setdatabase,s.setrole,config.value`,\n parameters: `SELECT parname AS name, ${acl('paracl')} AS acl FROM pg_parameter_acl ORDER BY parname`,\n defaults: `SELECT pg_get_userbyid(d.defaclrole) AS owner, COALESCE(n.nspname,'') AS schema, d.defaclobjtype AS kind, ${acl('d.defaclacl')} AS acl FROM pg_default_acl d LEFT JOIN pg_namespace n ON n.oid=d.defaclnamespace ORDER BY d.defaclrole,d.defaclnamespace,d.defaclobjtype`,\n };\n const result: Record<string, Row[]> = {};\n // A transaction executor must never have concurrent statements dispatched to it.\n for (const [key, query] of Object.entries(queries)) {\n // Parameter ACLs were introduced in PostgreSQL 15.\n if (key === 'parameters' && Number(result.server[0].version) < 150000) {\n result[key] = [];\n continue;\n }\n result[key] = (await db.query(query)).rows as Row[];\n }\n return result;\n}\n\nasync function plan(\n db: Executor,\n input: unknown,\n): Promise<PostgresPermissionPlan> {\n const contract = validatePostgresPermissionContract(input);\n const state = await snapshot(db, contract);\n const diagnostics: PostgresPermissionDiagnostic[] = [];\n const statements: string[] = [];\n const roles = [\n contract.runtimeRole,\n ...(contract.monitor ? [contract.monitor.role] : []),\n ];\n const add = (\n severity: PostgresPermissionDiagnostic['severity'],\n code: string,\n resource: string,\n message: string,\n role?: string,\n ) =>\n diagnostics.push({\n severity,\n code,\n resource,\n message,\n ...(role ? { role } : {}),\n });\n const unsupported = (\n code: string,\n resource: string,\n message: string,\n role?: string,\n ) => add('unsupported', code, resource, message, role);\n if (Number(state.server[0].version) < 140000)\n unsupported(\n 'server-version',\n 'database',\n 'PostgreSQL 14 or later is required.',\n );\n for (const role of [contract.migrationOwner, ...roles]) {\n const row = state.roles.find((entry) => entry.rolname === role);\n if (!row) {\n unsupported(\n 'missing-role',\n role,\n 'Infrastructure must create this role.',\n role,\n );\n continue;\n }\n if (\n roles.includes(role) &&\n [\n 'rolsuper',\n 'rolcreaterole',\n 'rolcreatedb',\n 'rolreplication',\n 'rolbypassrls',\n ].some((key) => row[key])\n )\n unsupported(\n 'privileged-role',\n role,\n 'Remove SUPERUSER, CREATEROLE, CREATEDB, REPLICATION and BYPASSRLS authority using infrastructure role management.',\n role,\n );\n }\n for (const membership of state.memberships)\n unsupported(\n 'role-membership',\n membership.member,\n `Role ${membership.member} is a member of ${membership.parent}; inbound and outbound membership, inherited privileges, and SET ROLE authority require infrastructure review. Memberships are never modified.`,\n membership.member,\n );\n const schema = state.schemas.find((entry) => entry.name === contract.schema);\n if (!schema)\n unsupported(\n 'missing-schema',\n contract.schema,\n 'Create the dedicated schema as the migration owner before reconciliation.',\n );\n else if (schema.owner !== contract.migrationOwner)\n unsupported(\n 'schema-owner',\n contract.schema,\n `Schema must be owned by ${contract.migrationOwner}; ownership is never changed.`,\n );\n const database = state.database[0];\n if (roles.includes(database.owner))\n unsupported(\n 'database-owner',\n database.name,\n 'Runtime and monitor must not own the database.',\n database.owner,\n );\n\n const relevant = (entries: Acl[], role: string) =>\n entries.filter(\n (entry) => entry.grantee === role || entry.grantee === 'PUBLIC',\n );\n function reconcile(\n kind: string,\n resource: string,\n entries: Acl[],\n role: string,\n desired: string[],\n suffix = '',\n ) {\n for (const entry of entries)\n if (entry.grantor === role && entry.grantee !== role)\n unsupported(\n 'dependent-grant',\n resource,\n `Configured role granted ${entry.privilege} to ${entry.grantee}; grant chains require infrastructure review to preserve other roles.`,\n role,\n );\n for (const entry of entries) {\n if (\n entry.grantee === 'PUBLIC' &&\n !(\n kind === 'DATABASE' &&\n entry.privilege === 'CONNECT' &&\n !entry.grantable\n )\n ) {\n unsupported(\n 'public-privilege',\n resource,\n `PUBLIC ${entry.privilege} is outside the explicit role contract; infrastructure must review it without changing unrelated access.`,\n role,\n );\n }\n }\n const effective = relevant(entries, role);\n const excess = effective.filter(\n (entry) => !desired.includes(entry.privilege) || entry.grantable,\n );\n const missing = desired.filter(\n (privilege) =>\n !entries.some(\n (entry) => entry.grantee === role && entry.privilege === privilege,\n ),\n );\n for (const entry of excess) {\n add(\n 'excessive',\n 'excessive-privilege',\n resource,\n `${entry.privilege}${entry.grantable ? ' WITH GRANT OPTION' : ''} is not declared (source: ${entry.grantee}).`,\n role,\n );\n if (entry.grantee === 'PUBLIC')\n unsupported(\n 'public-privilege',\n resource,\n `PUBLIC ${entry.privilege} requires infrastructure review; revoking it would affect other roles.`,\n role,\n );\n }\n for (const privilege of missing)\n add(\n 'missing',\n 'missing-privilege',\n resource,\n `${privilege} is required.`,\n role,\n );\n if (!excess.length && !missing.length) return;\n statements.push(\n `REVOKE ALL PRIVILEGES${suffix} ON ${kind} ${resource} FROM ${identifier(role)}`,\n );\n if (desired.length)\n statements.push(\n `GRANT ${desired.join(', ')}${suffix} ON ${kind} ${resource} TO ${identifier(role)}`,\n );\n }\n function reconcileRoutine(\n resource: string,\n entries: Acl[],\n desiredByRole: ReadonlyMap<string, readonly string[]>,\n ) {\n const grantee = (role: string) =>\n role === 'PUBLIC' ? 'PUBLIC' : identifier(role);\n for (const entry of entries)\n if (\n roles.includes(entry.grantor ?? '') &&\n entry.grantee !== entry.grantor\n )\n unsupported(\n 'dependent-routine-grant',\n resource,\n `Configured role granted ${entry.privilege} to ${entry.grantee}; grant chains require infrastructure review to preserve other roles.`,\n entry.grantor,\n );\n const managedGrantees = new Set([\n contract.migrationOwner,\n ...roles,\n 'PUBLIC',\n ]);\n for (const entry of entries)\n if (!managedGrantees.has(entry.grantee))\n unsupported(\n 'outside-routine-grant',\n resource,\n `${entry.grantee} has ${entry.privilege}; direct routine access outside the declared roles requires infrastructure review.`,\n entry.grantee,\n );\n for (const role of [...roles, 'PUBLIC']) {\n const desired = desiredByRole.get(role) ?? [];\n const effective = entries.filter((entry) => entry.grantee === role);\n const excess = effective.filter(\n (entry) => !desired.includes(entry.privilege) || entry.grantable,\n );\n const missing = desired.filter(\n (privilege) =>\n !entries.some(\n (entry) => entry.grantee === role && entry.privilege === privilege,\n ),\n );\n for (const entry of excess)\n add(\n 'excessive',\n 'excessive-routine-privilege',\n resource,\n `${entry.privilege}${entry.grantable ? ' WITH GRANT OPTION' : ''} is not declared.`,\n role,\n );\n for (const privilege of missing)\n add(\n 'missing',\n 'missing-routine-privilege',\n resource,\n `${privilege} is required.`,\n role,\n );\n if (!excess.length && !missing.length) continue;\n statements.push(\n `REVOKE ALL PRIVILEGES ON FUNCTION ${resource} FROM ${grantee(role)}`,\n );\n if (desired.length)\n statements.push(\n `GRANT ${desired.join(', ')} ON FUNCTION ${resource} TO ${grantee(role)}`,\n );\n }\n }\n for (const role of roles) {\n reconcile('DATABASE', identifier(database.name), database.acl, role, [\n 'CONNECT',\n ]);\n for (const entry of state.schemas) {\n if (entry.owner === role)\n unsupported(\n 'resource-owner',\n entry.name,\n 'Configured role owns a schema and has DDL authority.',\n role,\n );\n if (entry.name === contract.schema)\n reconcile('SCHEMA', identifier(entry.name), entry.acl, role, ['USAGE']);\n else if (\n relevant(entry.acl, role).some((grant) => grant.privilege === 'CREATE')\n )\n unsupported(\n 'outside-schema-create',\n entry.name,\n 'Effective CREATE outside the dedicated schema requires infrastructure repair.',\n role,\n );\n }\n }\n for (const schema of state.systemSchemas) {\n for (const role of roles) {\n if (schema.owner === role) {\n unsupported(\n 'system-schema-owner',\n schema.name,\n 'Configured roles must not own system schemas; infrastructure must restore separate ownership. System schema ownership is never modified.',\n role,\n );\n }\n for (const grant of relevant(schema.acl, role)) {\n if (grant.privilege === 'CREATE') {\n unsupported(\n 'system-schema-authority',\n schema.name,\n `Effective CREATE on a system schema (source: ${grant.grantee}) gives DDL authority and requires infrastructure repair. System schema ACLs are never modified.`,\n role,\n );\n }\n }\n }\n }\n for (const resource of state.systemPrivileges) {\n if (resource.kind !== 'column' && roles.includes(resource.owner)) {\n unsupported(\n 'system-object-owner',\n qualified(resource.schema, resource.name),\n `Configured role owns a system ${resource.kind}; ownership retains implicit alteration and grant authority even when its ordinary ACLs are revoked. Infrastructure must restore ownership; SMRT never changes it.`,\n resource.owner,\n );\n }\n for (const grant of resource.acl) {\n unsupported(\n 'system-privilege-delta',\n qualified(resource.schema, resource.name),\n `${grant.grantee} has exceptional ${grant.privilege}${grant.grantable ? ' WITH GRANT OPTION' : ''} on a system ${resource.kind}; review infrastructure grants against PostgreSQL initial ACLs. System ACLs are never modified.`,\n grant.grantee === 'PUBLIC' ? undefined : grant.grantee,\n );\n }\n }\n for (const resource of state.largeObjects) {\n if (roles.includes(resource.owner)) {\n unsupported(\n 'large-object-owner',\n `large object ${resource.oid}`,\n 'Configured role owns a large object outside the declared table/column contract. Infrastructure must review ownership; SMRT never changes it.',\n resource.owner,\n );\n }\n for (const grant of resource.acl) {\n if (roles.includes(grant.grantee) || grant.grantee === 'PUBLIC') {\n unsupported(\n 'large-object-privilege',\n `large object ${resource.oid}`,\n `${grant.grantee} has ${grant.privilege}${grant.grantable ? ' WITH GRANT OPTION' : ''} outside the declared table/column contract. Infrastructure must review this ACL; SMRT neither reads payloads nor changes large-object permissions.`,\n grant.grantee === 'PUBLIC' ? undefined : grant.grantee,\n );\n }\n }\n }\n const explicitlyOff = (value: unknown) =>\n ['off', 'false', 'no', '0'].includes(String(value).toLowerCase());\n if (state.largeObjectSettings.length !== 1) {\n unsupported(\n 'large-object-compatibility',\n 'lo_compat_privileges',\n 'The large-object ACL compatibility setting could not be established; qualification requires an observable disabled setting.',\n );\n }\n for (const settings of state.largeObjectSettings) {\n if (\n !explicitlyOff(settings.setting) ||\n !explicitlyOff(settings.reset_val) ||\n !['default', 'configuration file', 'command line', 'database'].includes(\n String(settings.source),\n )\n ) {\n unsupported(\n 'large-object-compatibility',\n 'lo_compat_privileges',\n 'Large-object ACL checks must be enabled for every configured role. An enabled or operator-specific lo_compat_privileges override cannot establish that baseline; review deployment settings and reconnect without an operator-specific override.',\n );\n }\n }\n for (const settings of state.largeObjectRoleSettings) {\n if (!explicitlyOff(settings.setting)) {\n unsupported(\n 'large-object-compatibility',\n 'lo_compat_privileges',\n `Role/database defaults enable or do not establish large-object ACL checks (${String(settings.role)}, database OID ${String(settings.database)}). Infrastructure must disable compatibility mode before qualification.`,\n settings.role === 'ALL ROLES' ? undefined : String(settings.role),\n );\n }\n }\n for (const parameter of state.parameters) {\n for (const role of roles) {\n for (const grant of relevant(parameter.acl, role)) {\n unsupported(\n 'parameter-privilege',\n parameter.name,\n `Effective ${grant.privilege} on a PostgreSQL configuration parameter (source: ${grant.grantee}) requires infrastructure review; parameter ACLs are never modified.`,\n role,\n );\n }\n }\n }\n const tables = state.relations.filter(\n (entry) => entry.schema === contract.schema && entry.kind !== 'S',\n );\n for (const table of bookkeeping) {\n if (!tables.some((entry) => entry.name === table)) {\n unsupported(\n 'missing-bookkeeping-table',\n qualified(contract.schema, table),\n 'Bootstrap all framework bookkeeping tables as the migration owner before permission setup. Stop runtime and monitoring access during migrations or restores, then reconcile before reactivation.',\n );\n }\n }\n const declared = new Set(contract.managedTables);\n const retained = new Set(contract.retainedTables);\n // Framework feature tables are owned by SMRT even when absent from manifests.\n for (const table of tables)\n if (table.name.startsWith('_smrt_')) declared.add(table.name);\n for (const table of retained)\n if (declared.has(table))\n unsupported(\n 'retained-managed-table',\n qualified(contract.schema, table),\n 'Retained tables must be outside the managed and framework table surfaces.',\n );\n for (const table of declared)\n if (!tables.some((entry) => entry.name === table))\n unsupported(\n 'missing-table',\n qualified(contract.schema, table),\n 'Run supported schema migrations before reconciling permissions.',\n );\n for (const table of retained)\n if (!tables.some((entry) => entry.name === table))\n unsupported(\n 'missing-retained-table',\n qualified(contract.schema, table),\n 'Retained tables must already exist before permission reconciliation.',\n );\n for (const relation of state.inherits) {\n const managedParent =\n relation.parent_schema === contract.schema &&\n declared.has(relation.parent_table ?? '');\n const childRetained =\n relation.child_schema === contract.schema &&\n retained.has(relation.child_table);\n const parentRetained =\n relation.parent_schema === contract.schema &&\n retained.has(relation.parent_table ?? '');\n if (managedParent && relation.child_schema !== contract.schema)\n unsupported(\n 'managed-inheritance',\n qualified(relation.child_schema, relation.child_table),\n 'Managed tables may not have external inheritance or partition children: parent table privileges can invoke external triggers outside the retained-table isolation boundary.',\n );\n else if (childRetained !== parentRetained)\n unsupported(\n 'retained-inheritance',\n qualified(relation.child_schema, relation.child_table),\n 'Retained tables may inherit only from retained tables in the dedicated schema; an accessible parent can otherwise expose retained rows.',\n );\n }\n for (const relation of state.foreignKeys) {\n const managedParent =\n relation.parent_schema === contract.schema &&\n declared.has(relation.parent_table ?? '');\n const childRetained =\n relation.child_schema === contract.schema &&\n retained.has(relation.child_table);\n const parentRetained =\n relation.parent_schema === contract.schema &&\n retained.has(relation.parent_table ?? '');\n if (managedParent && relation.child_schema !== contract.schema) {\n unsupported(\n 'managed-foreign-key',\n `${qualified(relation.child_schema, relation.child_table)} -> ${qualified(relation.parent_schema, relation.parent_table ?? '')}`,\n 'Managed tables may not have external foreign-key children: referential actions can invoke external triggers outside the retained-table isolation boundary.',\n );\n continue;\n }\n if (childRetained === parentRetained) continue;\n unsupported(\n 'retained-foreign-key',\n `${qualified(relation.child_schema, relation.child_table)} -> ${qualified(relation.parent_schema, relation.parent_table ?? '')}`,\n 'Retained tables may reference only retained tables; referential actions from an accessible table can otherwise mutate retained rows.',\n );\n }\n for (const rule of state.rewriteRules) {\n const managedSource =\n rule.schema === contract.schema && declared.has(rule.table_name);\n const retainedSource =\n rule.schema === contract.schema && retained.has(rule.table_name);\n const managedTarget =\n rule.referenced_schema === contract.schema &&\n declared.has(rule.referenced_table);\n if (retainedSource && managedTarget)\n unsupported(\n 'user-rewrite-rule',\n `${qualified(rule.schema, rule.table_name)} (${rule.rule_name})`,\n 'Retained tables may not reference managed tables through rewrite rules.',\n );\n else if (managedSource && rule.referenced_schema !== contract.schema)\n unsupported(\n 'user-rewrite-rule',\n `${qualified(rule.schema, rule.table_name)} (${rule.rule_name})`,\n 'Managed rewrite rules may not reference external relations: rule-owner table privileges can invoke external triggers outside the retained-table isolation boundary.',\n );\n else if (\n rule.referenced_schema === contract.schema &&\n retained.has(rule.referenced_table)\n )\n unsupported(\n 'user-rewrite-rule',\n `${qualified(rule.schema, rule.table_name)} (${rule.rule_name})`,\n 'User-defined rewrite rules are unsupported because rule-owner privileges can write retained tables indirectly.',\n );\n }\n for (const [table, columns] of Object.entries(\n contract.monitor?.tables ?? {},\n )) {\n const relation = tables.find((entry) => entry.name === table);\n if (!declared.has(table) || retained.has(table) || !relation)\n unsupported(\n 'monitor-table',\n table,\n 'Monitor tables must exist and belong to the managed or framework table surface, never retained tables.',\n );\n for (const column of columns)\n if (\n !relation ||\n !state.columns.some(\n (entry) => entry.relation === relation.oid && entry.name === column,\n )\n )\n unsupported(\n 'monitor-column',\n `${table}.${column}`,\n 'The declared monitoring column does not exist.',\n );\n }\n for (const relation of state.relations) {\n const resource = qualified(relation.schema, relation.name);\n const columns = state.columns.filter(\n (entry) => entry.relation === relation.oid,\n );\n if (relation.schema !== contract.schema) {\n for (const role of roles)\n if (\n relation.owner === role ||\n relevant(relation.acl, role).length ||\n columns.some((column) => relevant(column.acl, role).length)\n )\n unsupported(\n 'outside-resource-access',\n resource,\n 'Effective access to an unrelated relation requires infrastructure review; unrelated ACLs are preserved.',\n role,\n );\n continue;\n }\n if (relation.owner !== contract.migrationOwner)\n unsupported(\n 'resource-owner',\n resource,\n `Managed resources must be owned by ${contract.migrationOwner}; ownership is never changed.`,\n );\n if (\n relation.kind !== 'S' &&\n !declared.has(relation.name) &&\n !retained.has(relation.name)\n )\n unsupported(\n 'undeclared-table',\n resource,\n 'The dedicated schema contains an undeclared table; defaults cannot safely cover a mixed schema.',\n );\n if (\n relation.kind === 'S' &&\n (!relation.parent_table ||\n (!declared.has(relation.parent_table) &&\n !retained.has(relation.parent_table)))\n )\n unsupported(\n 'undeclared-sequence',\n resource,\n 'Sequences must belong to a declared managed or retained table before permission reconciliation.',\n );\n if (!['r', 'p', 'S'].includes(relation.kind))\n unsupported(\n 'unsupported-relation',\n resource,\n `Relation kind ${relation.kind} requires a separate security review.`,\n );\n if (relation.rls)\n unsupported(\n 'row-level-security',\n resource,\n 'RLS policies require a separate application authorization review; ACL verification cannot establish allowed row operations.',\n );\n for (const role of roles) {\n const isRuntime = role === contract.runtimeRole;\n const desired = isRuntime\n ? relation.kind === 'S'\n ? retained.has(relation.parent_table ?? '')\n ? []\n : ['USAGE']\n : retained.has(relation.name)\n ? []\n : bookkeeping.has(relation.name)\n ? ['SELECT']\n : ['SELECT', 'INSERT', 'UPDATE', 'DELETE']\n : [];\n reconcile(\n relation.kind === 'S' ? 'SEQUENCE' : 'TABLE',\n resource,\n relation.acl,\n role,\n desired,\n );\n for (const column of columns) {\n const wanted =\n !isRuntime &&\n !retained.has(relation.name) &&\n (contract.monitor?.tables[relation.name] ?? []).includes(column.name)\n ? ['SELECT']\n : [];\n reconcile(\n 'TABLE',\n resource,\n column.acl,\n role,\n wanted,\n ` (${identifier(column.name)})`,\n );\n }\n }\n }\n const triggerRoutineNames = new Set(contract.managedTriggerFunctions);\n const acceptedTriggerRoutineNames = new Set<string>();\n const acceptedTriggerRoutineOids = new Set<string>();\n const routineConfigIsEmpty = (value: unknown) =>\n (Array.isArray(value) && value.length === 0) || value === '[]';\n for (const resource of state.routines) {\n const resourceName = qualified(resource.schema, resource.name);\n const framework = frameworkRoutines.find(\n (expected) =>\n resource.schema === contract.schema &&\n resource.name === expected.name &&\n normalizeArgumentTypes(resource.argument_types) ===\n expected.argumentTypes,\n );\n if (framework) {\n const valid =\n resource.owner === contract.migrationOwner &&\n resource.kind === 'f' &&\n resource.language === 'plpgsql' &&\n resource.security_definer === false &&\n resource.argument_defaults === framework.argumentDefaults &&\n normalizeFunctionResult(resource.result) === framework.result &&\n resource.cost === '100' &&\n resource.rows === '1000' &&\n resource.support === '-' &&\n resource.volatility === 'v' &&\n resource.parallel === 'u' &&\n resource.leakproof === false &&\n resource.strict === false &&\n routineConfigIsEmpty(resource.config) &&\n normalizeFunctionSource(String(resource.source)) === framework.source;\n if (!valid)\n unsupported(\n 'framework-routine-definition',\n resourceName,\n 'Framework routine must retain its canonical identity, owner, invoker security, defaults, execution properties, settings and generated body.',\n );\n else\n reconcileRoutine(\n resource.identity,\n resource.acl,\n new Map([[contract.runtimeRole, ['EXECUTE']]]),\n );\n continue;\n }\n const bindings = state.triggers.filter(\n (trigger) => trigger.function_oid === resource.oid,\n );\n const triggerRoutine =\n resource.schema === contract.schema &&\n triggerRoutineNames.has(resource.name) &&\n resource.kind === 'f' &&\n resource.return_type === 'trigger' &&\n resource.argument_types === '' &&\n resource.argument_count === '0' &&\n resource.owner === contract.migrationOwner &&\n resource.language === 'plpgsql' &&\n resource.security_definer === false &&\n routineConfigIsEmpty(resource.config) &&\n bindings.length > 0 &&\n bindings.every(\n (trigger) =>\n trigger.schema === contract.schema &&\n trigger.internal === false &&\n (trigger.enabled === 'O' || trigger.enabled === 'A') &&\n declared.has(trigger.table_name),\n );\n if (triggerRoutine) {\n acceptedTriggerRoutineNames.add(resource.name);\n acceptedTriggerRoutineOids.add(resource.oid);\n reconcileRoutine(resource.identity, resource.acl, new Map());\n continue;\n }\n for (const role of roles)\n if (\n resource.schema === contract.schema ||\n resource.owner === role ||\n relevant(resource.acl, role).length\n )\n unsupported(\n 'unsupported-routines',\n resourceName,\n triggerRoutineNames.has(resource.name)\n ? 'Declared trigger routines must be migration-owner invoker PL/pgSQL functions returning trigger with no declared arguments, no function settings, and enabled non-internal bindings only to declared managed tables.'\n : 'User-defined routines are outside the supported table/sequence and declared trigger contract; review their effective privileges explicitly.',\n role,\n );\n }\n for (const name of triggerRoutineNames)\n if (!acceptedTriggerRoutineNames.has(name))\n unsupported(\n 'missing-managed-trigger-function',\n qualified(contract.schema, name),\n 'Run the migration that creates this exact managed trigger function and its enabled binding before reconciling permissions.',\n );\n for (const trigger of state.triggers)\n if (\n trigger.schema === contract.schema &&\n declared.has(trigger.table_name) &&\n trigger.internal === false &&\n (trigger.enabled === 'O' || trigger.enabled === 'A') &&\n !acceptedTriggerRoutineOids.has(trigger.function_oid)\n )\n unsupported(\n 'unsupported-managed-trigger',\n `${qualified(trigger.schema, trigger.table_name)} (${trigger.name})`,\n 'Enabled managed-table triggers must use an exact declared invoker trigger routine; undeclared or SECURITY DEFINER trigger functions can bypass retained-table isolation.',\n );\n for (const resource of state.types)\n for (const role of roles)\n if (\n resource.schema === contract.schema ||\n resource.owner === role ||\n relevant(resource.acl, role).length\n )\n unsupported(\n 'unsupported-types',\n qualified(resource.schema, resource.name),\n 'User-defined types are outside the supported table/sequence contract; review their effective privileges explicitly.',\n role,\n );\n // Global grants combine with schema grants: a schema REVOKE cannot cancel them.\n for (const defaults of state.defaults) {\n const resource = `DEFAULT ${defaults.kind} (${defaults.schema || 'global'})`;\n if (\n defaults.owner !== contract.migrationOwner &&\n defaults.acl.some((entry: Acl) => roles.includes(entry.grantee))\n )\n unsupported(\n 'other-creator-access',\n resource,\n `Creator ${defaults.owner} grants configured roles future access outside this contract.`,\n );\n if (\n defaults.schema !== contract.schema &&\n defaults.schema !== '' &&\n defaults.acl.some(\n (entry: Acl) =>\n entry.grantee === 'PUBLIC' || roles.includes(entry.grantee),\n )\n )\n unsupported(\n 'outside-default-privilege',\n resource,\n 'Defaults outside the managed schema grant future access and require infrastructure review.',\n );\n if (\n defaults.schema === '' &&\n defaults.acl.some(\n (entry: Acl) =>\n roles.includes(entry.grantee) ||\n (entry.grantee === 'PUBLIC' &&\n ['r', 'S', 'n'].includes(defaults.kind)),\n )\n )\n unsupported(\n 'global-default-privilege',\n resource,\n 'Global creator defaults grant configured roles or PUBLIC access and cannot be repaired within this schema.',\n );\n if (\n defaults.schema === contract.schema &&\n defaults.owner !== contract.migrationOwner\n )\n unsupported(\n 'other-creator-default',\n resource,\n `Defaults for creator ${defaults.owner} require separate ownership review.`,\n );\n if (\n defaults.schema === contract.schema &&\n !['r', 'S'].includes(defaults.kind) &&\n defaults.acl.some(\n (entry: Acl) =>\n roles.includes(entry.grantee) || entry.grantee === 'PUBLIC',\n )\n )\n unsupported(\n 'unsupported-default',\n resource,\n 'Only table and sequence schema defaults are supported.',\n );\n }\n for (const [kind, sqlKind, runtime] of [\n ['r', 'TABLES', ['SELECT', 'INSERT', 'UPDATE', 'DELETE']],\n ['S', 'SEQUENCES', ['USAGE']],\n ] as const) {\n const entry = state.defaults.find(\n (item) =>\n item.schema === contract.schema &&\n item.owner === contract.migrationOwner &&\n item.kind === kind,\n );\n if (entry?.acl.some((grant) => grant.grantee === 'PUBLIC')) {\n unsupported(\n 'public-default',\n `${contract.schema} ${sqlKind}`,\n 'PUBLIC creator defaults are outside the explicit role contract and require infrastructure review.',\n );\n }\n for (const role of roles) {\n const desired: readonly string[] =\n role === contract.runtimeRole ? runtime : [];\n const effective = relevant(entry?.acl ?? [], role);\n const extra = effective.filter(\n (grant) => !desired.includes(grant.privilege) || grant.grantable,\n );\n const missing = desired.filter(\n (privilege) =>\n !(entry?.acl ?? []).some(\n (grant) => grant.grantee === role && grant.privilege === privilege,\n ),\n );\n if (!extra.length && !missing.length) continue;\n for (const grant of extra) {\n add(\n 'excessive',\n 'default-excessive',\n `${contract.schema} ${sqlKind}`,\n `${grant.privilege} default from ${grant.grantee} is not declared.`,\n role,\n );\n if (grant.grantee === 'PUBLIC')\n unsupported(\n 'public-default',\n contract.schema,\n 'PUBLIC defaults affect other roles and require infrastructure repair.',\n );\n }\n for (const privilege of missing)\n add(\n 'missing',\n 'default-missing',\n `${contract.schema} ${sqlKind}`,\n `Creator ${contract.migrationOwner} must default ${privilege}.`,\n role,\n );\n const prefix = `ALTER DEFAULT PRIVILEGES FOR ROLE ${identifier(contract.migrationOwner)} IN SCHEMA ${identifier(contract.schema)}`;\n statements.push(\n `${prefix} REVOKE ALL PRIVILEGES ON ${sqlKind} FROM ${identifier(role)}`,\n );\n if (desired.length)\n statements.push(\n `${prefix} GRANT ${desired.join(', ')} ON ${sqlKind} TO ${identifier(role)}`,\n );\n }\n }\n const executor = state.server[0];\n if (\n statements.length &&\n !executor.superuser &&\n executor.executor !== contract.migrationOwner\n )\n unsupported(\n 'execution-authority',\n 'database',\n 'Apply requires the migration owner or a superuser; plan and apply must use the same actor.',\n );\n if (\n statements.some((sql) => sql.includes(' ON DATABASE ')) &&\n !executor.superuser &&\n database.owner !== executor.executor\n )\n unsupported(\n 'database-authority',\n database.name,\n 'Database ACL remediation requires its owner or a superuser.',\n );\n return {\n contract,\n diagnostics,\n limitations: [\n 'Only PostgreSQL table, column, sequence, schema and database ACLs are qualified; application authorization and RLS are separate. Large-object ownership/access is unsupported, and lo_compat_privileges must remain off for deployed roles.',\n 'Future user-defined routines and types are unsupported. PostgreSQL implicit global defaults grant PUBLIC EXECUTE/USAGE; rerun diagnostics after every migration before activating runtime roles.',\n 'Pause migrations and external ACL/role writers during planning and apply. The advisory lock coordinates SMRT permission writers only.',\n 'All framework bookkeeping tables must exist before setup. Stop runtime and monitor access throughout migrations, restores and repair: recreated bookkeeping tables temporarily receive creator CRUD defaults and require explicit reconciliation before either role is reactivated.',\n 'Retained tables are operator-owned data outside the runtime and monitor surfaces. Creator defaults initially grant runtime access to every new table and sequence, so create or restore every retained table first, then apply its reviewed plan and verify access is revoked before reactivating restricted roles.',\n ],\n statements: [...new Set(statements)],\n canApply: !diagnostics.some((entry) => entry.severity === 'unsupported'),\n fingerprint: createHash('sha256')\n .update(JSON.stringify({ contract, state }))\n .digest('hex'),\n };\n}\n\n/** Read-only catalog inspection. No application records or credentials are read. */\nexport async function planPostgresPermissions(\n db: Executor,\n contract: PostgresPermissionContract,\n): Promise<PostgresPermissionPlan> {\n return plan(db, contract);\n}\n\n/** Apply the reviewed contract atomically, rejecting stale catalog snapshots. */\nexport async function applyPostgresPermissions(\n db: DatabaseInterface,\n contract: PostgresPermissionContract,\n options: { expectedFingerprint: string },\n): Promise<PostgresPermissionPlan> {\n const normalizedContract = validatePostgresPermissionContract(contract);\n if (!options || !/^[a-f0-9]{64}$/.test(options.expectedFingerprint))\n throw new Error(\n 'An expectedFingerprint from a reviewed permission plan is required.',\n );\n if (!db.transaction)\n throw new Error(\n 'PostgreSQL permissions require a transaction-capable database.',\n );\n return db.transaction(async (tx) => {\n await tx.query(\"SET LOCAL lock_timeout = '5s'\");\n await tx.query(\"SET LOCAL statement_timeout = '30s'\");\n // Cooperating permission writers serialize; operators must quiesce migrations.\n await tx.query(\n `SELECT pg_advisory_xact_lock(hashtext(${literal(`smrt-permissions:${normalizedContract.schema}`)}))`,\n );\n const before = await plan(tx, normalizedContract);\n if (before.fingerprint !== options.expectedFingerprint)\n throw new Error(\n 'Permission plan is stale; generate and review a new plan.',\n );\n if (!before.canApply)\n throw new Error(\n 'Permission plan has unsupported privilege sources or missing prerequisites; resolve its diagnostics first.',\n );\n const executor = (\n await tx.query(\n 'SELECT current_user AS name, rolsuper FROM pg_roles WHERE rolname=current_user',\n )\n ).rows[0];\n if (\n !executor.rolsuper &&\n executor.name !== normalizedContract.migrationOwner\n )\n throw new Error(\n 'Apply must execute as the migration owner or a PostgreSQL superuser.',\n );\n for (const statement of before.statements) await tx.query(statement);\n const after = await plan(tx, normalizedContract);\n if (!after.canApply || after.diagnostics.length)\n throw new Error(\n 'Permission verification failed; all permission changes have been rolled back.',\n );\n return after;\n });\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"postgres-permissions.js","names":[],"sources":["../src/postgres-permissions.ts"],"sourcesContent":["import { createHash } from 'node:crypto';\nimport type { DatabaseInterface } from '@happyvertical/sql';\nimport {\n CREATE_POSTGRES_CHANGE_FEED_APPEND_BATCH_FUNCTION,\n CREATE_POSTGRES_CHANGE_FEED_APPEND_FUNCTION,\n CREATE_POSTGRES_CHANGE_FEED_DRAIN_FUNCTION,\n POSTGRES_CHANGE_FEED_APPEND_BATCH_FUNCTION_IDENTITY,\n POSTGRES_CHANGE_FEED_APPEND_FUNCTION_IDENTITY,\n POSTGRES_CHANGE_FEED_DRAIN_BATCH,\n POSTGRES_CHANGE_FEED_DRAIN_FUNCTION_IDENTITY,\n} from './system/schema.js';\n\n/** PostgreSQL ACLs only; this is not application authorization or RLS. */\nexport interface PostgresPermissionContract {\n schema: string;\n /** Defaults affect every future object created by migrationOwner in schema. */\n schemaExclusive: true;\n migrationOwner: string;\n runtimeRole: string;\n managedTables: string[];\n /** Existing operator-owned tables retained outside the runtime data surface. */\n retainedTables?: string[];\n /** Exact zero-argument trigger functions bound only to managed tables. */\n managedTriggerFunctions?: string[];\n monitor?: { role: string; tables: Record<string, string[]> };\n}\n\nexport interface PostgresPermissionDiagnostic {\n code: string;\n severity: 'missing' | 'excessive' | 'unsupported';\n role?: string;\n resource: string;\n message: string;\n}\n\nexport interface PostgresPermissionPlan {\n contract: PostgresPermissionContract;\n diagnostics: PostgresPermissionDiagnostic[];\n statements: string[];\n canApply: boolean;\n fingerprint: string;\n limitations: string[];\n}\n\ntype NormalizedPostgresPermissionContract = PostgresPermissionContract & {\n managedTriggerFunctions: string[];\n retainedTables: string[];\n};\n\ntype Executor = Pick<DatabaseInterface, 'query'>;\ninterface Row {\n [key: string]: unknown;\n oid: string;\n name: string;\n schema: string;\n identity: string;\n argument_types: string;\n argument_count: string;\n argument_defaults: string | null;\n return_type: string;\n result: string;\n cost: string;\n rows: string;\n support: string;\n language: string;\n security_definer: boolean;\n config: unknown;\n source: string;\n volatility: string;\n parallel: string;\n leakproof: boolean;\n strict: boolean;\n function_oid: string;\n table_name: string;\n enabled: string;\n internal: boolean;\n owner: string;\n acl: Acl[];\n kind: string;\n rolname: string;\n member: string;\n parent: string;\n relation: string;\n parent_table: string | null;\n child_schema: string;\n child_table: string;\n parent_schema: string;\n delete_action: string;\n update_action: string;\n rule_name: string;\n referenced_schema: string;\n referenced_table: string;\n version: string;\n executor: string;\n superuser: boolean;\n rls: boolean;\n}\ntype Acl = {\n grantee: string;\n privilege: string;\n grantable: boolean;\n grantor?: string;\n};\nconst bookkeeping = new Set([\n '_smrt_migrations',\n '_smrt_schema_migrations',\n '_smrt_backfills',\n]);\nconst identifier = (value: string) => `\"${value.replaceAll('\"', '\"\"')}\"`;\nconst literal = (value: string) =>\n `E'${value.replaceAll('\\\\', '\\\\\\\\').replaceAll(\"'\", \"''\")}'`;\nconst qualified = (schema: string, name: string) =>\n `${identifier(schema)}.${identifier(name)}`;\n\nconst normalizeFunctionSource = (value: string) =>\n value.replaceAll('\\r\\n', '\\n').trim();\nconst normalizeArgumentTypes = (value: string) =>\n value.replaceAll(/\\s*,\\s*/g, ',');\nconst normalizeFunctionResult = (value: string) =>\n value\n .replaceAll(/\\s+/g, ' ')\n .replaceAll(/\\s*,\\s*/g, ',')\n .replaceAll(/\\(\\s*/g, '(')\n .replaceAll(/\\s*\\)/g, ')')\n .trim()\n .toLowerCase();\n\nfunction sourceFromFunctionDdl(ddl: string): string {\n const match = ddl.match(\n /\\bAS\\s+\\$([A-Za-z_][A-Za-z0-9_]*)\\$\\n([\\s\\S]*?)\\n\\$\\1\\$;/,\n );\n if (!match)\n throw new Error('Framework function DDL has no dollar-quoted body.');\n return normalizeFunctionSource(match[2]);\n}\n\nfunction resultFromFunctionDdl(ddl: string): string {\n const match = ddl.match(/\\bRETURNS\\s+([\\s\\S]*?)\\nLANGUAGE\\s+/);\n if (!match) throw new Error('Framework function DDL has no return result.');\n return normalizeFunctionResult(match[1]);\n}\n\ntype FrameworkRoutine = {\n name: string;\n argumentTypes: string;\n argumentDefaults: string | null;\n result: string;\n source: string;\n};\n\nfunction frameworkRoutine(identity: string, ddl: string): FrameworkRoutine {\n const match = identity.match(/^([^()]+)\\((.*)\\)$/);\n if (!match)\n throw new Error(`Invalid framework function identity: ${identity}`);\n return {\n name: match[1],\n argumentTypes: normalizeArgumentTypes(match[2]),\n argumentDefaults:\n match[1] === '_smrt_drain_changes'\n ? String(POSTGRES_CHANGE_FEED_DRAIN_BATCH)\n : null,\n result: resultFromFunctionDdl(ddl),\n source: sourceFromFunctionDdl(ddl),\n };\n}\n\nconst frameworkRoutines = [\n frameworkRoutine(\n POSTGRES_CHANGE_FEED_APPEND_FUNCTION_IDENTITY,\n CREATE_POSTGRES_CHANGE_FEED_APPEND_FUNCTION,\n ),\n frameworkRoutine(\n POSTGRES_CHANGE_FEED_APPEND_BATCH_FUNCTION_IDENTITY,\n CREATE_POSTGRES_CHANGE_FEED_APPEND_BATCH_FUNCTION,\n ),\n frameworkRoutine(\n POSTGRES_CHANGE_FEED_DRAIN_FUNCTION_IDENTITY,\n CREATE_POSTGRES_CHANGE_FEED_DRAIN_FUNCTION,\n ),\n];\n\nfunction object(\n value: unknown,\n keys: string[],\n label: string,\n): Record<string, unknown> {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n throw new Error(`${label} must be an object.`);\n }\n for (const key of Object.keys(value)) {\n if (!keys.includes(key))\n throw new Error(`Unknown ${label} property: ${key}.`);\n }\n return value as Record<string, unknown>;\n}\nfunction name(value: unknown, label: string): string {\n if (\n typeof value !== 'string' ||\n !value.length ||\n value.includes('\\0') ||\n Buffer.byteLength(value) > 63\n ) {\n throw new Error(\n `${label} must be a nonempty PostgreSQL identifier (at most 63 bytes).`,\n );\n }\n return value;\n}\n/** Validate configuration before opening a connection; unknown options fail closed. */\nexport function validatePostgresPermissionContract(\n value: unknown,\n): NormalizedPostgresPermissionContract {\n const input = object(\n value,\n [\n 'schema',\n 'schemaExclusive',\n 'migrationOwner',\n 'runtimeRole',\n 'managedTables',\n 'retainedTables',\n 'managedTriggerFunctions',\n 'monitor',\n ],\n 'postgresPermissions',\n );\n if (input.schemaExclusive !== true)\n throw new Error(\n 'postgresPermissions.schemaExclusive must explicitly be true.',\n );\n const schema = name(input.schema, 'schema');\n if (schema === 'information_schema' || schema.startsWith('pg_'))\n throw new Error('A dedicated application schema is required.');\n const migrationOwner = name(input.migrationOwner, 'migrationOwner');\n const runtimeRole = name(input.runtimeRole, 'runtimeRole');\n if (!Array.isArray(input.managedTables))\n throw new Error('managedTables must be an array.');\n const managedTables = [\n ...new Set(\n input.managedTables.map((table) => name(table, 'managedTables entry')),\n ),\n ].sort();\n if (\n input.retainedTables !== undefined &&\n !Array.isArray(input.retainedTables)\n )\n throw new Error('retainedTables must be an array.');\n const retainedTables = [\n ...new Set(\n (input.retainedTables ?? []).map((table) =>\n name(table, 'retainedTables entry'),\n ),\n ),\n ].sort();\n const overlap = retainedTables.find((table) => managedTables.includes(table));\n if (overlap)\n throw new Error(`Table ${overlap} cannot be both managed and retained.`);\n if (\n input.managedTriggerFunctions !== undefined &&\n !Array.isArray(input.managedTriggerFunctions)\n )\n throw new Error('managedTriggerFunctions must be an array.');\n const managedTriggerFunctions = [\n ...new Set(\n (input.managedTriggerFunctions ?? []).map((routine) =>\n name(routine, 'managedTriggerFunctions entry'),\n ),\n ),\n ].sort();\n let monitor: PostgresPermissionContract['monitor'];\n if (input.monitor !== undefined) {\n const entry = object(input.monitor, ['role', 'tables'], 'monitor');\n const role = name(entry.role, 'monitor.role');\n if (\n !entry.tables ||\n typeof entry.tables !== 'object' ||\n Array.isArray(entry.tables)\n )\n throw new Error('monitor.tables must map tables to column arrays.');\n const tables: Record<string, string[]> = Object.create(null);\n for (const [table, columns] of Object.entries(entry.tables).sort(\n ([a], [b]) => a.localeCompare(b),\n )) {\n name(table, 'monitor table');\n if (!Array.isArray(columns) || !columns.length)\n throw new Error(\n `monitor table ${table} requires a nonempty column array.`,\n );\n tables[table] = [\n ...new Set(columns.map((column) => name(column, 'monitor column'))),\n ].sort();\n }\n monitor = { role, tables };\n }\n const roles = [\n migrationOwner,\n runtimeRole,\n ...(monitor ? [monitor.role] : []),\n ];\n if (\n new Set(roles).size !== roles.length ||\n roles.some(\n (role) => role.toUpperCase() === 'PUBLIC' || role.startsWith('pg_'),\n )\n )\n throw new Error(\n 'Migration, runtime and monitor roles must be distinct non-system roles.',\n );\n return {\n schema,\n schemaExclusive: true,\n migrationOwner,\n runtimeRole,\n managedTables,\n retainedTables,\n managedTriggerFunctions,\n ...(monitor ? { monitor } : {}),\n };\n}\n\nconst acl = (expression: string) =>\n `COALESCE((SELECT json_agg(json_build_object('grantee', CASE WHEN a.grantee = 0 THEN 'PUBLIC' ELSE pg_get_userbyid(a.grantee) END, 'grantor', pg_get_userbyid(a.grantor), 'privilege', a.privilege_type, 'grantable', a.is_grantable) ORDER BY a.grantee, a.privilege_type, a.grantor) FROM aclexplode(${expression}) a), '[]'::json)`;\n\nasync function snapshot(\n db: Executor,\n contract: NormalizedPostgresPermissionContract,\n): Promise<Record<string, Row[]>> {\n const roleNames = [\n contract.migrationOwner,\n contract.runtimeRole,\n ...(contract.monitor ? [contract.monitor.role] : []),\n ]\n .map(literal)\n .join(',');\n const restrictedRoleNames = [\n contract.runtimeRole,\n ...(contract.monitor ? [contract.monitor.role] : []),\n ]\n .map(literal)\n .join(',');\n // information_schema.sql runs after initial ACL recording. Trust only its\n // explicitly PUBLIC-readable stock relations, never internal metadata views.\n // Normal-operation OIDs start at 16384:\n // https://www.postgresql.org/docs/16/system-catalog-initial-data.html\n // Source: postgres/postgres REL_14_STABLE..REL_18_STABLE,\n // GRANT SELECT [ON TABLE] ... TO PUBLIC in:\n // https://github.com/postgres/postgres/blob/REL_14_STABLE/src/backend/catalog/information_schema.sql\n // https://github.com/postgres/postgres/blob/REL_18_STABLE/src/backend/catalog/information_schema.sql\n const informationSchemaPublicSelect =\n \"'administrable_role_authorizations','applicable_roles','attributes','character_sets','check_constraint_routine_usage','check_constraints','collation_character_set_applicability','collations','column_column_usage','column_domain_usage','column_options','column_privileges','column_udt_usage','columns','constraint_column_usage','constraint_table_usage','data_type_privileges','domain_constraints','domain_udt_usage','domains','element_types','enabled_roles','foreign_data_wrapper_options','foreign_data_wrappers','foreign_server_options','foreign_servers','foreign_table_options','foreign_tables','information_schema_catalog_name','key_column_usage','parameters','referential_constraints','role_column_grants','role_routine_grants','role_table_grants','role_udt_grants','role_usage_grants','routine_column_usage','routine_privileges','routine_routine_usage','routine_sequence_usage','routine_table_usage','routines','schemata','sequences','sql_features','sql_implementation_info','sql_sizing','table_constraints','table_privileges','tables','triggered_update_columns','triggers','udt_privileges','usage_privileges','user_defined_types','user_mapping_options','user_mappings','view_column_usage','view_routine_usage','view_table_usage','views'\";\n // pg_init_privs records non-default initial ACLs. Missing entries use the\n // PostgreSQL object-kind default; extension-provided ACLs are not stock trust.\n // https://www.postgresql.org/docs/current/catalog-pg-init-privs.html\n const initialAcl = (fallback: string) =>\n `CASE WHEN i.privtype='i' THEN i.initprivs WHEN i.privtype='e' THEN NULL::aclitem[] ELSE ${fallback} END`;\n // Only a type referenced by another type's typarray is its generated array.\n // Nonzero typelem also describes non-array types (point); domains over arrays\n // remain independent privilege targets and must not be filtered out.\n const queries: Record<string, string> = {\n server: `SELECT current_setting('server_version_num') AS version, current_database() AS database, current_user AS executor, (SELECT rolsuper FROM pg_roles WHERE rolname=current_user) AS superuser`,\n roles: `SELECT oid::text, rolname, rolsuper, rolcreaterole, rolcreatedb, rolreplication, rolbypassrls FROM pg_roles WHERE rolname IN (${roleNames}) ORDER BY rolname`,\n memberships: `SELECT pg_get_userbyid(member) AS member, pg_get_userbyid(roleid) AS parent FROM pg_auth_members WHERE member IN (SELECT oid FROM pg_roles WHERE rolname IN (${roleNames})) OR roleid IN (SELECT oid FROM pg_roles WHERE rolname IN (${roleNames})) ORDER BY member, roleid`,\n database: `SELECT datname AS name, pg_get_userbyid(datdba) AS owner, ${acl(\"COALESCE(datacl, acldefault('d',datdba))\")} AS acl FROM pg_database WHERE datname=current_database()`,\n schemas: `SELECT nspname AS name, pg_get_userbyid(nspowner) AS owner, ${acl(\"COALESCE(nspacl, acldefault('n',nspowner))\")} AS acl FROM pg_namespace WHERE left(nspname,3) <> 'pg_' AND nspname <> 'information_schema' ORDER BY nspname`,\n relations: `SELECT c.oid::text, n.nspname AS schema, c.relname AS name, c.relkind AS kind, pg_get_userbyid(c.relowner) AS owner, c.relrowsecurity AS rls, (SELECT parent.relname FROM pg_depend d JOIN pg_class parent ON parent.oid=d.refobjid JOIN pg_namespace parent_schema ON parent_schema.oid=parent.relnamespace WHERE d.classid='pg_class'::regclass AND d.objid=c.oid AND d.refclassid='pg_class'::regclass AND d.deptype IN ('a','i') AND parent_schema.oid=n.oid LIMIT 1) AS parent_table, ${acl(\"COALESCE(c.relacl, acldefault(CASE WHEN c.relkind='S' THEN 's'::\\\"char\\\" ELSE 'r'::\\\"char\\\" END,c.relowner))\")} AS acl FROM pg_class c JOIN pg_namespace n ON n.oid=c.relnamespace WHERE left(n.nspname,3) <> 'pg_' AND n.nspname <> 'information_schema' AND c.relkind IN ('r','p','v','m','f','S') ORDER BY n.nspname,c.relname`,\n inherits: `SELECT child_schema.nspname AS child_schema, child.relname AS child_table, parent_schema.nspname AS parent_schema, parent.relname AS parent_table FROM pg_inherits i JOIN pg_class child ON child.oid=i.inhrelid JOIN pg_namespace child_schema ON child_schema.oid=child.relnamespace JOIN pg_class parent ON parent.oid=i.inhparent JOIN pg_namespace parent_schema ON parent_schema.oid=parent.relnamespace ORDER BY child_schema.nspname,child.relname,parent_schema.nspname,parent.relname`,\n foreignKeys: `SELECT child_schema.nspname AS child_schema, child.relname AS child_table, parent_schema.nspname AS parent_schema, parent.relname AS parent_table, con.confdeltype::text AS delete_action, con.confupdtype::text AS update_action FROM pg_constraint con JOIN pg_class child ON child.oid=con.conrelid JOIN pg_namespace child_schema ON child_schema.oid=child.relnamespace JOIN pg_class parent ON parent.oid=con.confrelid JOIN pg_namespace parent_schema ON parent_schema.oid=parent.relnamespace WHERE con.contype='f' ORDER BY child_schema.nspname,child.relname,parent_schema.nspname,parent.relname,con.conname`,\n rewriteRules: `WITH RECURSIVE rule_dependencies AS (SELECT r.oid AS rule_oid, r.ev_class AS source_oid, r.rulename AS rule_name, d.refobjid AS referenced_oid FROM pg_rewrite r JOIN pg_depend d ON d.classid='pg_rewrite'::regclass AND d.objid=r.oid AND d.refclassid='pg_class'::regclass WHERE r.rulename <> '_RETURN' UNION SELECT dependencies.rule_oid, dependencies.source_oid, dependencies.rule_name, d.refobjid FROM rule_dependencies dependencies JOIN pg_rewrite view_rule ON view_rule.ev_class=dependencies.referenced_oid AND view_rule.rulename='_RETURN' JOIN pg_depend d ON d.classid='pg_rewrite'::regclass AND d.objid=view_rule.oid AND d.refclassid='pg_class'::regclass) SELECT n.nspname AS schema, c.relname AS table_name, dependencies.rule_name, referenced_schema.nspname AS referenced_schema, referenced.relname AS referenced_table FROM rule_dependencies dependencies JOIN pg_class c ON c.oid=dependencies.source_oid JOIN pg_namespace n ON n.oid=c.relnamespace JOIN pg_class referenced ON referenced.oid=dependencies.referenced_oid JOIN pg_namespace referenced_schema ON referenced_schema.oid=referenced.relnamespace ORDER BY n.nspname,c.relname,dependencies.rule_name,referenced_schema.nspname,referenced.relname`,\n columns: `SELECT c.oid::text AS relation, a.attname AS name, ${acl('a.attacl')} AS acl FROM pg_attribute a JOIN pg_class c ON c.oid=a.attrelid JOIN pg_namespace n ON n.oid=c.relnamespace WHERE left(n.nspname,3) <> 'pg_' AND n.nspname <> 'information_schema' AND c.relkind IN ('r','p','v','m','f') AND a.attnum>0 AND NOT a.attisdropped ORDER BY c.oid,a.attnum`,\n routines: `SELECT n.nspname AS schema, p.oid::text, p.proname AS name, format('%I.%I(%s)', n.nspname, p.proname, oidvectortypes(p.proargtypes)) AS identity, oidvectortypes(p.proargtypes) AS argument_types, pg_get_expr(p.proargdefaults,0) AS argument_defaults, p.prokind AS kind, p.prorettype::regtype::text AS return_type, pg_get_function_result(p.oid) AS result, p.procost::text AS cost, p.prorows::text AS rows, p.prosupport::regproc::text AS support, p.pronargs::text AS argument_count, l.lanname AS language, p.prosecdef AS security_definer, p.provolatile::text AS volatility, p.proparallel::text AS parallel, p.proleakproof AS leakproof, p.proisstrict AS strict, COALESCE(to_json(p.proconfig),'[]'::json) AS config, p.prosrc AS source, CASE WHEN p.prokind='f' THEN pg_get_functiondef(p.oid) END AS definition, pg_get_userbyid(p.proowner) AS owner, ${acl(\"COALESCE(p.proacl, acldefault('f',p.proowner))\")} AS acl FROM pg_proc p JOIN pg_namespace n ON n.oid=p.pronamespace JOIN pg_language l ON l.oid=p.prolang WHERE left(n.nspname,3) <> 'pg_' AND n.nspname <> 'information_schema' ORDER BY n.nspname,p.oid`,\n triggers: `SELECT t.oid::text, n.nspname AS schema, c.relname AS table_name, t.tgname AS name, t.tgfoid::text AS function_oid, t.tgenabled AS enabled, t.tgisinternal AS internal, t.tgtype::text AS type, encode(t.tgargs,'hex') AS arguments, pg_get_triggerdef(t.oid, true) AS definition FROM pg_trigger t JOIN pg_class c ON c.oid=t.tgrelid JOIN pg_namespace n ON n.oid=c.relnamespace WHERE left(n.nspname,3) <> 'pg_' AND n.nspname <> 'information_schema' ORDER BY n.nspname,c.oid,t.oid`,\n types: `SELECT n.nspname AS schema, t.typname AS name, pg_get_userbyid(t.typowner) AS owner, ${acl(\"COALESCE(t.typacl, acldefault('T',t.typowner))\")} AS acl FROM pg_type t JOIN pg_namespace n ON n.oid=t.typnamespace LEFT JOIN pg_class c ON c.oid=t.typrelid WHERE left(n.nspname,3) <> 'pg_' AND n.nspname <> 'information_schema' AND NOT EXISTS (SELECT 1 FROM pg_type element WHERE element.typarray=t.oid) AND (t.typrelid=0 OR c.relkind='c') ORDER BY n.nspname,t.typname`,\n systemSchemas: `SELECT nspname AS name, pg_get_userbyid(nspowner) AS owner, ${acl(\"COALESCE(nspacl, acldefault('n',nspowner))\")} AS acl FROM pg_namespace WHERE left(nspname,3)='pg_' OR nspname='information_schema' ORDER BY nspname`,\n systemPrivileges: `WITH resources AS (\n SELECT n.nspname AS schema, c.relname AS name, c.oid::text AS oid, CASE WHEN c.relkind='S' THEN 'sequence' ELSE 'relation' END AS kind, pg_get_userbyid(c.relowner) AS owner,\n COALESCE(c.relacl,acldefault(CASE WHEN c.relkind='S' THEN 's'::\"char\" ELSE 'r'::\"char\" END,c.relowner)) AS current_acl,\n CASE WHEN i.objoid IS NULL AND n.nspname='information_schema' AND c.oid<16384 AND c.relname IN (${informationSchemaPublicSelect}) THEN ARRAY[makeaclitem(0,c.relowner,'SELECT',false)] ELSE ${initialAcl(\"acldefault(CASE WHEN c.relkind='S' THEN 's'::\\\"char\\\" ELSE 'r'::\\\"char\\\" END,c.relowner)\")} END AS initial_acl\n FROM pg_class c JOIN pg_namespace n ON n.oid=c.relnamespace\n LEFT JOIN pg_init_privs i ON i.objoid=c.oid AND i.classoid='pg_class'::regclass AND i.objsubid=0\n WHERE (left(n.nspname,3)='pg_' OR n.nspname='information_schema') AND c.relkind IN ('r','p','v','m','f','S')\n UNION ALL\n SELECT n.nspname, c.relname || '.' || a.attname, c.oid::text || ':' || a.attnum::text, 'column', pg_get_userbyid(c.relowner),\n a.attacl, ${initialAcl('NULL::aclitem[]')}\n FROM pg_attribute a JOIN pg_class c ON c.oid=a.attrelid JOIN pg_namespace n ON n.oid=c.relnamespace\n LEFT JOIN pg_init_privs i ON i.objoid=c.oid AND i.classoid='pg_class'::regclass AND i.objsubid=a.attnum\n WHERE (left(n.nspname,3)='pg_' OR n.nspname='information_schema') AND a.attnum>0 AND NOT a.attisdropped\n UNION ALL\n SELECT n.nspname, p.proname, p.oid::text, 'routine', pg_get_userbyid(p.proowner), COALESCE(p.proacl,acldefault('f',p.proowner)), ${initialAcl(\"CASE WHEN p.oid<16384 THEN acldefault('f',p.proowner) ELSE NULL::aclitem[] END\")}\n FROM pg_proc p JOIN pg_namespace n ON n.oid=p.pronamespace\n LEFT JOIN pg_init_privs i ON i.objoid=p.oid AND i.classoid='pg_proc'::regclass AND i.objsubid=0\n WHERE left(n.nspname,3)='pg_' OR n.nspname='information_schema'\n UNION ALL\n SELECT n.nspname, t.typname, t.oid::text, 'type', pg_get_userbyid(t.typowner), COALESCE(t.typacl,acldefault('T',t.typowner)), ${initialAcl(\"CASE WHEN t.oid<16384 THEN acldefault('T',t.typowner) ELSE NULL::aclitem[] END\")}\n FROM pg_type t JOIN pg_namespace n ON n.oid=t.typnamespace LEFT JOIN pg_class c ON c.oid=t.typrelid\n LEFT JOIN pg_init_privs i ON i.objoid=t.oid AND i.classoid='pg_type'::regclass AND i.objsubid=0\n WHERE (left(n.nspname,3)='pg_' OR n.nspname='information_schema') AND NOT EXISTS (SELECT 1 FROM pg_type element WHERE element.typarray=t.oid) AND (t.typrelid=0 OR c.relkind='c')\n ) SELECT r.schema,r.name,r.oid,r.kind,r.owner,COALESCE(d.acl,'[]'::json) AS acl FROM resources r\n CROSS JOIN LATERAL (\n SELECT json_agg(json_build_object('grantee', CASE WHEN a.grantee=0 THEN 'PUBLIC' ELSE pg_get_userbyid(a.grantee) END,\n 'grantor',pg_get_userbyid(a.grantor),'privilege',a.privilege_type,'grantable',a.is_grantable)\n ORDER BY a.grantee,a.privilege_type,a.grantor) AS acl\n FROM aclexplode(r.current_acl) a\n WHERE a.grantee IN (SELECT oid FROM pg_roles WHERE rolname IN (${restrictedRoleNames}))\n OR (a.grantee=0 AND NOT EXISTS (SELECT 1 FROM aclexplode(r.initial_acl) b WHERE b.grantee=0 AND b.privilege_type=a.privilege_type AND (b.is_grantable OR NOT a.is_grantable)))\n ) d WHERE d.acl IS NOT NULL OR (r.kind<>'column' AND r.owner IN (${restrictedRoleNames})) ORDER BY r.schema,r.kind,r.name,r.oid`,\n largeObjects: `SELECT oid::text, pg_get_userbyid(lomowner) AS owner, ${acl(\"COALESCE(lomacl, acldefault('L',lomowner))\")} AS acl FROM pg_largeobject_metadata ORDER BY oid`,\n largeObjectSettings: `SELECT setting,reset_val,source FROM pg_settings WHERE name='lo_compat_privileges'`,\n largeObjectRoleSettings: `SELECT s.setdatabase::text AS database, CASE WHEN s.setrole=0 THEN 'ALL ROLES' ELSE pg_get_userbyid(s.setrole) END AS role, split_part(config.value,'=',2) AS setting FROM pg_db_role_setting s CROSS JOIN LATERAL unnest(s.setconfig) config(value) WHERE s.setdatabase IN (0,(SELECT oid FROM pg_database WHERE datname=current_database())) AND (s.setrole=0 OR s.setrole IN (SELECT oid FROM pg_roles WHERE rolname IN (${restrictedRoleNames}))) AND split_part(config.value,'=',1)='lo_compat_privileges' ORDER BY s.setdatabase,s.setrole,config.value`,\n parameters: `SELECT parname AS name, ${acl('paracl')} AS acl FROM pg_parameter_acl ORDER BY parname`,\n defaults: `SELECT pg_get_userbyid(d.defaclrole) AS owner, COALESCE(n.nspname,'') AS schema, d.defaclobjtype AS kind, ${acl('d.defaclacl')} AS acl FROM pg_default_acl d LEFT JOIN pg_namespace n ON n.oid=d.defaclnamespace ORDER BY d.defaclrole,d.defaclnamespace,d.defaclobjtype`,\n };\n const result: Record<string, Row[]> = {};\n // A transaction executor must never have concurrent statements dispatched to it.\n for (const [key, query] of Object.entries(queries)) {\n // Parameter ACLs were introduced in PostgreSQL 15.\n if (key === 'parameters' && Number(result.server[0].version) < 150000) {\n result[key] = [];\n continue;\n }\n result[key] = (await db.query(query)).rows as Row[];\n }\n return result;\n}\n\nasync function plan(\n db: Executor,\n input: unknown,\n): Promise<PostgresPermissionPlan> {\n const contract = validatePostgresPermissionContract(input);\n const state = await snapshot(db, contract);\n const diagnostics: PostgresPermissionDiagnostic[] = [];\n const statements: string[] = [];\n const roles = [\n contract.runtimeRole,\n ...(contract.monitor ? [contract.monitor.role] : []),\n ];\n const add = (\n severity: PostgresPermissionDiagnostic['severity'],\n code: string,\n resource: string,\n message: string,\n role?: string,\n ) =>\n diagnostics.push({\n severity,\n code,\n resource,\n message,\n ...(role ? { role } : {}),\n });\n const unsupported = (\n code: string,\n resource: string,\n message: string,\n role?: string,\n ) => add('unsupported', code, resource, message, role);\n if (Number(state.server[0].version) < 140000)\n unsupported(\n 'server-version',\n 'database',\n 'PostgreSQL 14 or later is required.',\n );\n for (const role of [contract.migrationOwner, ...roles]) {\n const row = state.roles.find((entry) => entry.rolname === role);\n if (!row) {\n unsupported(\n 'missing-role',\n role,\n 'Infrastructure must create this role.',\n role,\n );\n continue;\n }\n if (\n roles.includes(role) &&\n [\n 'rolsuper',\n 'rolcreaterole',\n 'rolcreatedb',\n 'rolreplication',\n 'rolbypassrls',\n ].some((key) => row[key])\n )\n unsupported(\n 'privileged-role',\n role,\n 'Remove SUPERUSER, CREATEROLE, CREATEDB, REPLICATION and BYPASSRLS authority using infrastructure role management.',\n role,\n );\n }\n for (const membership of state.memberships)\n unsupported(\n 'role-membership',\n membership.member,\n `Role ${membership.member} is a member of ${membership.parent}; inbound and outbound membership, inherited privileges, and SET ROLE authority require infrastructure review. Memberships are never modified.`,\n membership.member,\n );\n const schema = state.schemas.find((entry) => entry.name === contract.schema);\n if (!schema)\n unsupported(\n 'missing-schema',\n contract.schema,\n 'Create the dedicated schema as the migration owner before reconciliation.',\n );\n else if (schema.owner !== contract.migrationOwner)\n unsupported(\n 'schema-owner',\n contract.schema,\n `Schema must be owned by ${contract.migrationOwner}; ownership is never changed.`,\n );\n const database = state.database[0];\n if (roles.includes(database.owner))\n unsupported(\n 'database-owner',\n database.name,\n 'Runtime and monitor must not own the database.',\n database.owner,\n );\n\n const relevant = (entries: Acl[], role: string) =>\n entries.filter(\n (entry) => entry.grantee === role || entry.grantee === 'PUBLIC',\n );\n function reconcile(\n kind: string,\n resource: string,\n entries: Acl[],\n role: string,\n desired: string[],\n suffix = '',\n ) {\n for (const entry of entries)\n if (entry.grantor === role && entry.grantee !== role)\n unsupported(\n 'dependent-grant',\n resource,\n `Configured role granted ${entry.privilege} to ${entry.grantee}; grant chains require infrastructure review to preserve other roles.`,\n role,\n );\n for (const entry of entries) {\n if (\n entry.grantee === 'PUBLIC' &&\n !(\n kind === 'DATABASE' &&\n entry.privilege === 'CONNECT' &&\n !entry.grantable\n )\n ) {\n unsupported(\n 'public-privilege',\n resource,\n `PUBLIC ${entry.privilege} is outside the explicit role contract; infrastructure must review it without changing unrelated access.`,\n role,\n );\n }\n }\n const effective = relevant(entries, role);\n const excess = effective.filter(\n (entry) => !desired.includes(entry.privilege) || entry.grantable,\n );\n const missing = desired.filter(\n (privilege) =>\n !entries.some(\n (entry) => entry.grantee === role && entry.privilege === privilege,\n ),\n );\n for (const entry of excess) {\n add(\n 'excessive',\n 'excessive-privilege',\n resource,\n `${entry.privilege}${entry.grantable ? ' WITH GRANT OPTION' : ''} is not declared (source: ${entry.grantee}).`,\n role,\n );\n if (entry.grantee === 'PUBLIC')\n unsupported(\n 'public-privilege',\n resource,\n `PUBLIC ${entry.privilege} requires infrastructure review; revoking it would affect other roles.`,\n role,\n );\n }\n for (const privilege of missing)\n add(\n 'missing',\n 'missing-privilege',\n resource,\n `${privilege} is required.`,\n role,\n );\n if (!excess.length && !missing.length) return;\n statements.push(\n `REVOKE ALL PRIVILEGES${suffix} ON ${kind} ${resource} FROM ${identifier(role)}`,\n );\n if (desired.length)\n statements.push(\n `GRANT ${desired.join(', ')}${suffix} ON ${kind} ${resource} TO ${identifier(role)}`,\n );\n }\n function reconcileRoutine(\n resource: string,\n entries: Acl[],\n desiredByRole: ReadonlyMap<string, readonly string[]>,\n ) {\n const grantee = (role: string) =>\n role === 'PUBLIC' ? 'PUBLIC' : identifier(role);\n for (const entry of entries)\n if (\n roles.includes(entry.grantor ?? '') &&\n entry.grantee !== entry.grantor\n )\n unsupported(\n 'dependent-routine-grant',\n resource,\n `Configured role granted ${entry.privilege} to ${entry.grantee}; grant chains require infrastructure review to preserve other roles.`,\n entry.grantor,\n );\n const managedGrantees = new Set([\n contract.migrationOwner,\n ...roles,\n 'PUBLIC',\n ]);\n for (const entry of entries)\n if (!managedGrantees.has(entry.grantee))\n unsupported(\n 'outside-routine-grant',\n resource,\n `${entry.grantee} has ${entry.privilege}; direct routine access outside the declared roles requires infrastructure review.`,\n entry.grantee,\n );\n for (const role of [...roles, 'PUBLIC']) {\n const desired = desiredByRole.get(role) ?? [];\n const effective = entries.filter((entry) => entry.grantee === role);\n const excess = effective.filter(\n (entry) => !desired.includes(entry.privilege) || entry.grantable,\n );\n const missing = desired.filter(\n (privilege) =>\n !entries.some(\n (entry) => entry.grantee === role && entry.privilege === privilege,\n ),\n );\n for (const entry of excess)\n add(\n 'excessive',\n 'excessive-routine-privilege',\n resource,\n `${entry.privilege}${entry.grantable ? ' WITH GRANT OPTION' : ''} is not declared.`,\n role,\n );\n for (const privilege of missing)\n add(\n 'missing',\n 'missing-routine-privilege',\n resource,\n `${privilege} is required.`,\n role,\n );\n if (!excess.length && !missing.length) continue;\n statements.push(\n `REVOKE ALL PRIVILEGES ON FUNCTION ${resource} FROM ${grantee(role)}`,\n );\n if (desired.length)\n statements.push(\n `GRANT ${desired.join(', ')} ON FUNCTION ${resource} TO ${grantee(role)}`,\n );\n }\n }\n for (const role of roles) {\n reconcile('DATABASE', identifier(database.name), database.acl, role, [\n 'CONNECT',\n ]);\n for (const entry of state.schemas) {\n if (entry.owner === role)\n unsupported(\n 'resource-owner',\n entry.name,\n 'Configured role owns a schema and has DDL authority.',\n role,\n );\n if (entry.name === contract.schema)\n reconcile('SCHEMA', identifier(entry.name), entry.acl, role, ['USAGE']);\n else if (\n relevant(entry.acl, role).some((grant) => grant.privilege === 'CREATE')\n )\n unsupported(\n 'outside-schema-create',\n entry.name,\n 'Effective CREATE outside the dedicated schema requires infrastructure repair.',\n role,\n );\n }\n }\n for (const schema of state.systemSchemas) {\n for (const role of roles) {\n if (schema.owner === role) {\n unsupported(\n 'system-schema-owner',\n schema.name,\n 'Configured roles must not own system schemas; infrastructure must restore separate ownership. System schema ownership is never modified.',\n role,\n );\n }\n for (const grant of relevant(schema.acl, role)) {\n if (grant.privilege === 'CREATE') {\n unsupported(\n 'system-schema-authority',\n schema.name,\n `Effective CREATE on a system schema (source: ${grant.grantee}) gives DDL authority and requires infrastructure repair. System schema ACLs are never modified.`,\n role,\n );\n }\n }\n }\n }\n for (const resource of state.systemPrivileges) {\n if (resource.kind !== 'column' && roles.includes(resource.owner)) {\n unsupported(\n 'system-object-owner',\n qualified(resource.schema, resource.name),\n `Configured role owns a system ${resource.kind}; ownership retains implicit alteration and grant authority even when its ordinary ACLs are revoked. Infrastructure must restore ownership; SMRT never changes it.`,\n resource.owner,\n );\n }\n for (const grant of resource.acl) {\n unsupported(\n 'system-privilege-delta',\n qualified(resource.schema, resource.name),\n `${grant.grantee} has exceptional ${grant.privilege}${grant.grantable ? ' WITH GRANT OPTION' : ''} on a system ${resource.kind}; review infrastructure grants against PostgreSQL initial ACLs. System ACLs are never modified.`,\n grant.grantee === 'PUBLIC' ? undefined : grant.grantee,\n );\n }\n }\n for (const resource of state.largeObjects) {\n if (roles.includes(resource.owner)) {\n unsupported(\n 'large-object-owner',\n `large object ${resource.oid}`,\n 'Configured role owns a large object outside the declared table/column contract. Infrastructure must review ownership; SMRT never changes it.',\n resource.owner,\n );\n }\n for (const grant of resource.acl) {\n if (roles.includes(grant.grantee) || grant.grantee === 'PUBLIC') {\n unsupported(\n 'large-object-privilege',\n `large object ${resource.oid}`,\n `${grant.grantee} has ${grant.privilege}${grant.grantable ? ' WITH GRANT OPTION' : ''} outside the declared table/column contract. Infrastructure must review this ACL; SMRT neither reads payloads nor changes large-object permissions.`,\n grant.grantee === 'PUBLIC' ? undefined : grant.grantee,\n );\n }\n }\n }\n const explicitlyOff = (value: unknown) =>\n ['off', 'false', 'no', '0'].includes(String(value).toLowerCase());\n if (state.largeObjectSettings.length !== 1) {\n unsupported(\n 'large-object-compatibility',\n 'lo_compat_privileges',\n 'The large-object ACL compatibility setting could not be established; qualification requires an observable disabled setting.',\n );\n }\n for (const settings of state.largeObjectSettings) {\n if (\n !explicitlyOff(settings.setting) ||\n !explicitlyOff(settings.reset_val) ||\n !['default', 'configuration file', 'command line', 'database'].includes(\n String(settings.source),\n )\n ) {\n unsupported(\n 'large-object-compatibility',\n 'lo_compat_privileges',\n 'Large-object ACL checks must be enabled for every configured role. An enabled or operator-specific lo_compat_privileges override cannot establish that baseline; review deployment settings and reconnect without an operator-specific override.',\n );\n }\n }\n for (const settings of state.largeObjectRoleSettings) {\n if (!explicitlyOff(settings.setting)) {\n unsupported(\n 'large-object-compatibility',\n 'lo_compat_privileges',\n `Role/database defaults enable or do not establish large-object ACL checks (${String(settings.role)}, database OID ${String(settings.database)}). Infrastructure must disable compatibility mode before qualification.`,\n settings.role === 'ALL ROLES' ? undefined : String(settings.role),\n );\n }\n }\n for (const parameter of state.parameters) {\n for (const role of roles) {\n for (const grant of relevant(parameter.acl, role)) {\n unsupported(\n 'parameter-privilege',\n parameter.name,\n `Effective ${grant.privilege} on a PostgreSQL configuration parameter (source: ${grant.grantee}) requires infrastructure review; parameter ACLs are never modified.`,\n role,\n );\n }\n }\n }\n const tables = state.relations.filter(\n (entry) => entry.schema === contract.schema && entry.kind !== 'S',\n );\n for (const table of bookkeeping) {\n if (!tables.some((entry) => entry.name === table)) {\n unsupported(\n 'missing-bookkeeping-table',\n qualified(contract.schema, table),\n 'Bootstrap all framework bookkeeping tables as the migration owner before permission setup. Stop runtime and monitoring access during migrations or restores, then reconcile before reactivation.',\n );\n }\n }\n const declared = new Set(contract.managedTables);\n const retained = new Set(contract.retainedTables);\n // Framework feature tables are owned by SMRT even when absent from manifests.\n for (const table of tables)\n if (table.name.startsWith('_smrt_')) declared.add(table.name);\n for (const table of retained)\n if (declared.has(table))\n unsupported(\n 'retained-managed-table',\n qualified(contract.schema, table),\n 'Retained tables must be outside the managed and framework table surfaces.',\n );\n for (const table of declared)\n if (!tables.some((entry) => entry.name === table))\n unsupported(\n 'missing-table',\n qualified(contract.schema, table),\n 'Run supported schema migrations before reconciling permissions.',\n );\n for (const table of retained)\n if (!tables.some((entry) => entry.name === table))\n unsupported(\n 'missing-retained-table',\n qualified(contract.schema, table),\n 'Retained tables must already exist before permission reconciliation.',\n );\n for (const relation of state.inherits) {\n const managedParent =\n relation.parent_schema === contract.schema &&\n declared.has(relation.parent_table ?? '');\n const childRetained =\n relation.child_schema === contract.schema &&\n retained.has(relation.child_table);\n const parentRetained =\n relation.parent_schema === contract.schema &&\n retained.has(relation.parent_table ?? '');\n if (managedParent && relation.child_schema !== contract.schema)\n unsupported(\n 'managed-inheritance',\n qualified(relation.child_schema, relation.child_table),\n 'Managed tables may not have external inheritance or partition children: parent table privileges can invoke external triggers outside the retained-table isolation boundary.',\n );\n else if (childRetained !== parentRetained)\n unsupported(\n 'retained-inheritance',\n qualified(relation.child_schema, relation.child_table),\n 'Retained tables may inherit only from retained tables in the dedicated schema; an accessible parent can otherwise expose retained rows.',\n );\n }\n for (const relation of state.foreignKeys) {\n const managedParent =\n relation.parent_schema === contract.schema &&\n declared.has(relation.parent_table ?? '');\n const childRetained =\n relation.child_schema === contract.schema &&\n retained.has(relation.child_table);\n const parentRetained =\n relation.parent_schema === contract.schema &&\n retained.has(relation.parent_table ?? '');\n if (managedParent && relation.child_schema !== contract.schema) {\n unsupported(\n 'managed-foreign-key',\n `${qualified(relation.child_schema, relation.child_table)} -> ${qualified(relation.parent_schema, relation.parent_table ?? '')}`,\n 'Managed tables may not have external foreign-key children: referential actions can invoke external triggers outside the retained-table isolation boundary.',\n );\n continue;\n }\n if (childRetained === parentRetained) continue;\n unsupported(\n 'retained-foreign-key',\n `${qualified(relation.child_schema, relation.child_table)} -> ${qualified(relation.parent_schema, relation.parent_table ?? '')}`,\n 'Retained tables may reference only retained tables; referential actions from an accessible table can otherwise mutate retained rows.',\n );\n }\n for (const rule of state.rewriteRules) {\n const managedSource =\n rule.schema === contract.schema && declared.has(rule.table_name);\n const retainedSource =\n rule.schema === contract.schema && retained.has(rule.table_name);\n const managedTarget =\n rule.referenced_schema === contract.schema &&\n declared.has(rule.referenced_table);\n if (retainedSource && managedTarget)\n unsupported(\n 'user-rewrite-rule',\n `${qualified(rule.schema, rule.table_name)} (${rule.rule_name})`,\n 'Retained tables may not reference managed tables through rewrite rules.',\n );\n else if (managedSource && rule.referenced_schema !== contract.schema)\n unsupported(\n 'user-rewrite-rule',\n `${qualified(rule.schema, rule.table_name)} (${rule.rule_name})`,\n 'Managed rewrite rules may not reference external relations: rule-owner table privileges can invoke external triggers outside the retained-table isolation boundary.',\n );\n else if (\n rule.referenced_schema === contract.schema &&\n retained.has(rule.referenced_table)\n )\n unsupported(\n 'user-rewrite-rule',\n `${qualified(rule.schema, rule.table_name)} (${rule.rule_name})`,\n 'User-defined rewrite rules are unsupported because rule-owner privileges can write retained tables indirectly.',\n );\n }\n for (const [table, columns] of Object.entries(\n contract.monitor?.tables ?? {},\n )) {\n const relation = tables.find((entry) => entry.name === table);\n if (!declared.has(table) || retained.has(table) || !relation)\n unsupported(\n 'monitor-table',\n table,\n 'Monitor tables must exist and belong to the managed or framework table surface, never retained tables.',\n );\n for (const column of columns)\n if (\n !relation ||\n !state.columns.some(\n (entry) => entry.relation === relation.oid && entry.name === column,\n )\n )\n unsupported(\n 'monitor-column',\n `${table}.${column}`,\n 'The declared monitoring column does not exist.',\n );\n }\n for (const relation of state.relations) {\n const resource = qualified(relation.schema, relation.name);\n const columns = state.columns.filter(\n (entry) => entry.relation === relation.oid,\n );\n if (relation.schema !== contract.schema) {\n for (const role of roles)\n if (\n relation.owner === role ||\n relevant(relation.acl, role).length ||\n columns.some((column) => relevant(column.acl, role).length)\n )\n unsupported(\n 'outside-resource-access',\n resource,\n 'Effective access to an unrelated relation requires infrastructure review; unrelated ACLs are preserved.',\n role,\n );\n continue;\n }\n if (relation.owner !== contract.migrationOwner)\n unsupported(\n 'resource-owner',\n resource,\n `Managed resources must be owned by ${contract.migrationOwner}; ownership is never changed.`,\n );\n if (\n relation.kind !== 'S' &&\n !declared.has(relation.name) &&\n !retained.has(relation.name)\n )\n unsupported(\n 'undeclared-table',\n resource,\n 'The dedicated schema contains an undeclared table; defaults cannot safely cover a mixed schema.',\n );\n if (\n relation.kind === 'S' &&\n (!relation.parent_table ||\n (!declared.has(relation.parent_table) &&\n !retained.has(relation.parent_table)))\n )\n unsupported(\n 'undeclared-sequence',\n resource,\n 'Sequences must belong to a declared managed or retained table before permission reconciliation.',\n );\n if (!['r', 'p', 'S'].includes(relation.kind))\n unsupported(\n 'unsupported-relation',\n resource,\n `Relation kind ${relation.kind} requires a separate security review.`,\n );\n if (relation.rls)\n unsupported(\n 'row-level-security',\n resource,\n 'RLS policies require a separate application authorization review; ACL verification cannot establish allowed row operations.',\n );\n for (const role of roles) {\n const isRuntime = role === contract.runtimeRole;\n const desired = isRuntime\n ? relation.kind === 'S'\n ? retained.has(relation.parent_table ?? '')\n ? []\n : ['USAGE']\n : retained.has(relation.name)\n ? []\n : bookkeeping.has(relation.name)\n ? ['SELECT']\n : ['SELECT', 'INSERT', 'UPDATE', 'DELETE']\n : [];\n reconcile(\n relation.kind === 'S' ? 'SEQUENCE' : 'TABLE',\n resource,\n relation.acl,\n role,\n desired,\n );\n for (const column of columns) {\n const wanted =\n !isRuntime &&\n !retained.has(relation.name) &&\n (contract.monitor?.tables[relation.name] ?? []).includes(column.name)\n ? ['SELECT']\n : [];\n reconcile(\n 'TABLE',\n resource,\n column.acl,\n role,\n wanted,\n ` (${identifier(column.name)})`,\n );\n }\n }\n }\n const triggerRoutineNames = new Set(contract.managedTriggerFunctions);\n const acceptedTriggerRoutineNames = new Set<string>();\n const acceptedTriggerRoutineOids = new Set<string>();\n const routineConfigIsEmpty = (value: unknown) =>\n (Array.isArray(value) && value.length === 0) || value === '[]';\n for (const resource of state.routines) {\n const resourceName = qualified(resource.schema, resource.name);\n const framework = frameworkRoutines.find(\n (expected) =>\n resource.schema === contract.schema &&\n resource.name === expected.name &&\n normalizeArgumentTypes(resource.argument_types) ===\n expected.argumentTypes,\n );\n if (framework) {\n const valid =\n resource.owner === contract.migrationOwner &&\n resource.kind === 'f' &&\n resource.language === 'plpgsql' &&\n resource.security_definer === false &&\n resource.argument_defaults === framework.argumentDefaults &&\n normalizeFunctionResult(resource.result) === framework.result &&\n resource.cost === '100' &&\n resource.rows === '1000' &&\n resource.support === '-' &&\n resource.volatility === 'v' &&\n resource.parallel === 'u' &&\n resource.leakproof === false &&\n resource.strict === false &&\n routineConfigIsEmpty(resource.config) &&\n normalizeFunctionSource(String(resource.source)) === framework.source;\n if (!valid)\n unsupported(\n 'framework-routine-definition',\n resourceName,\n 'Framework routine must retain its canonical identity, owner, invoker security, defaults, execution properties, settings and generated body.',\n );\n else\n reconcileRoutine(\n resource.identity,\n resource.acl,\n new Map([[contract.runtimeRole, ['EXECUTE']]]),\n );\n continue;\n }\n const bindings = state.triggers.filter(\n (trigger) => trigger.function_oid === resource.oid,\n );\n const triggerRoutine =\n resource.schema === contract.schema &&\n triggerRoutineNames.has(resource.name) &&\n resource.kind === 'f' &&\n resource.return_type === 'trigger' &&\n resource.argument_types === '' &&\n resource.argument_count === '0' &&\n resource.owner === contract.migrationOwner &&\n resource.language === 'plpgsql' &&\n resource.security_definer === false &&\n routineConfigIsEmpty(resource.config) &&\n bindings.length > 0 &&\n bindings.every(\n (trigger) =>\n trigger.schema === contract.schema &&\n trigger.internal === false &&\n (trigger.enabled === 'O' || trigger.enabled === 'A') &&\n declared.has(trigger.table_name),\n );\n if (triggerRoutine) {\n acceptedTriggerRoutineNames.add(resource.name);\n acceptedTriggerRoutineOids.add(resource.oid);\n reconcileRoutine(resource.identity, resource.acl, new Map());\n continue;\n }\n for (const role of roles)\n if (\n resource.schema === contract.schema ||\n resource.owner === role ||\n relevant(resource.acl, role).length\n )\n unsupported(\n 'unsupported-routines',\n resourceName,\n triggerRoutineNames.has(resource.name)\n ? 'Declared trigger routines must be migration-owner invoker PL/pgSQL functions returning trigger with no declared arguments, no function settings, and enabled non-internal bindings only to declared managed tables.'\n : 'User-defined routines are outside the supported table/sequence and declared trigger contract; review their effective privileges explicitly.',\n role,\n );\n }\n for (const name of triggerRoutineNames)\n if (!acceptedTriggerRoutineNames.has(name))\n unsupported(\n 'missing-managed-trigger-function',\n qualified(contract.schema, name),\n 'Run the migration that creates this exact managed trigger function and its enabled binding before reconciling permissions.',\n );\n for (const trigger of state.triggers)\n if (\n trigger.schema === contract.schema &&\n declared.has(trigger.table_name) &&\n trigger.internal === false &&\n (trigger.enabled === 'O' || trigger.enabled === 'A') &&\n !acceptedTriggerRoutineOids.has(trigger.function_oid)\n )\n unsupported(\n 'unsupported-managed-trigger',\n `${qualified(trigger.schema, trigger.table_name)} (${trigger.name})`,\n 'Enabled managed-table triggers must use an exact declared invoker trigger routine; undeclared or SECURITY DEFINER trigger functions can bypass retained-table isolation.',\n );\n for (const resource of state.types)\n for (const role of roles)\n if (\n resource.schema === contract.schema ||\n resource.owner === role ||\n relevant(resource.acl, role).length\n )\n unsupported(\n 'unsupported-types',\n qualified(resource.schema, resource.name),\n 'User-defined types are outside the supported table/sequence contract; review their effective privileges explicitly.',\n role,\n );\n // Global grants combine with schema grants: a schema REVOKE cannot cancel them.\n for (const defaults of state.defaults) {\n const resource = `DEFAULT ${defaults.kind} (${defaults.schema || 'global'})`;\n if (\n defaults.owner !== contract.migrationOwner &&\n defaults.acl.some((entry: Acl) => roles.includes(entry.grantee))\n )\n unsupported(\n 'other-creator-access',\n resource,\n `Creator ${defaults.owner} grants configured roles future access outside this contract.`,\n );\n if (\n defaults.schema !== contract.schema &&\n defaults.schema !== '' &&\n defaults.acl.some(\n (entry: Acl) =>\n entry.grantee === 'PUBLIC' || roles.includes(entry.grantee),\n )\n )\n unsupported(\n 'outside-default-privilege',\n resource,\n 'Defaults outside the managed schema grant future access and require infrastructure review.',\n );\n if (\n defaults.schema === '' &&\n defaults.acl.some(\n (entry: Acl) =>\n roles.includes(entry.grantee) ||\n (entry.grantee === 'PUBLIC' &&\n ['r', 'S', 'n'].includes(defaults.kind)),\n )\n )\n unsupported(\n 'global-default-privilege',\n resource,\n 'Global creator defaults grant configured roles or PUBLIC access and cannot be repaired within this schema.',\n );\n if (\n defaults.schema === contract.schema &&\n defaults.owner !== contract.migrationOwner\n )\n unsupported(\n 'other-creator-default',\n resource,\n `Defaults for creator ${defaults.owner} require separate ownership review.`,\n );\n if (\n defaults.schema === contract.schema &&\n !['r', 'S'].includes(defaults.kind) &&\n defaults.acl.some(\n (entry: Acl) =>\n roles.includes(entry.grantee) || entry.grantee === 'PUBLIC',\n )\n )\n unsupported(\n 'unsupported-default',\n resource,\n 'Only table and sequence schema defaults are supported.',\n );\n }\n for (const [kind, sqlKind, runtime] of [\n ['r', 'TABLES', ['SELECT', 'INSERT', 'UPDATE', 'DELETE']],\n ['S', 'SEQUENCES', ['USAGE']],\n ] as const) {\n const entry = state.defaults.find(\n (item) =>\n item.schema === contract.schema &&\n item.owner === contract.migrationOwner &&\n item.kind === kind,\n );\n if (entry?.acl.some((grant) => grant.grantee === 'PUBLIC')) {\n unsupported(\n 'public-default',\n `${contract.schema} ${sqlKind}`,\n 'PUBLIC creator defaults are outside the explicit role contract and require infrastructure review.',\n );\n }\n for (const role of roles) {\n const desired: readonly string[] =\n role === contract.runtimeRole ? runtime : [];\n const effective = relevant(entry?.acl ?? [], role);\n const extra = effective.filter(\n (grant) => !desired.includes(grant.privilege) || grant.grantable,\n );\n const missing = desired.filter(\n (privilege) =>\n !(entry?.acl ?? []).some(\n (grant) => grant.grantee === role && grant.privilege === privilege,\n ),\n );\n if (!extra.length && !missing.length) continue;\n for (const grant of extra) {\n add(\n 'excessive',\n 'default-excessive',\n `${contract.schema} ${sqlKind}`,\n `${grant.privilege} default from ${grant.grantee} is not declared.`,\n role,\n );\n if (grant.grantee === 'PUBLIC')\n unsupported(\n 'public-default',\n contract.schema,\n 'PUBLIC defaults affect other roles and require infrastructure repair.',\n );\n }\n for (const privilege of missing)\n add(\n 'missing',\n 'default-missing',\n `${contract.schema} ${sqlKind}`,\n `Creator ${contract.migrationOwner} must default ${privilege}.`,\n role,\n );\n const prefix = `ALTER DEFAULT PRIVILEGES FOR ROLE ${identifier(contract.migrationOwner)} IN SCHEMA ${identifier(contract.schema)}`;\n statements.push(\n `${prefix} REVOKE ALL PRIVILEGES ON ${sqlKind} FROM ${identifier(role)}`,\n );\n if (desired.length)\n statements.push(\n `${prefix} GRANT ${desired.join(', ')} ON ${sqlKind} TO ${identifier(role)}`,\n );\n }\n }\n const executor = state.server[0];\n if (\n statements.length &&\n !executor.superuser &&\n executor.executor !== contract.migrationOwner\n )\n unsupported(\n 'execution-authority',\n 'database',\n 'Apply requires the migration owner or a superuser; plan and apply must use the same actor.',\n );\n if (\n statements.some((sql) => sql.includes(' ON DATABASE ')) &&\n !executor.superuser &&\n database.owner !== executor.executor\n )\n unsupported(\n 'database-authority',\n database.name,\n 'Database ACL remediation requires its owner or a superuser.',\n );\n return {\n contract,\n diagnostics,\n limitations: [\n 'Only PostgreSQL table, column, sequence, schema and database ACLs are qualified; application authorization and RLS are separate. Large-object ownership/access is unsupported, and lo_compat_privileges must remain off for deployed roles.',\n 'Future user-defined routines and types are unsupported. PostgreSQL implicit global defaults grant PUBLIC EXECUTE/USAGE; rerun diagnostics after every migration before activating runtime roles.',\n 'Pause migrations and external ACL/role writers during planning and apply. The advisory lock coordinates SMRT permission writers only.',\n 'All framework bookkeeping tables must exist before setup. Stop runtime and monitor access throughout migrations, restores and repair: recreated bookkeeping tables temporarily receive creator CRUD defaults and require explicit reconciliation before either role is reactivated.',\n 'Retained tables are operator-owned data outside the runtime and monitor surfaces. Creator defaults initially grant runtime access to every new table and sequence, so create or restore every retained table first, then apply its reviewed plan and verify access is revoked before reactivating restricted roles.',\n ],\n statements: [...new Set(statements)],\n canApply: !diagnostics.some((entry) => entry.severity === 'unsupported'),\n fingerprint: createHash('sha256')\n .update(JSON.stringify({ contract, state }))\n .digest('hex'),\n };\n}\n\n/** Read-only catalog inspection. No application records or credentials are read. */\nexport async function planPostgresPermissions(\n db: Executor,\n contract: PostgresPermissionContract,\n): Promise<PostgresPermissionPlan> {\n return plan(db, contract);\n}\n\n/** Apply the reviewed contract atomically, rejecting stale catalog snapshots. */\nexport async function applyPostgresPermissions(\n db: DatabaseInterface,\n contract: PostgresPermissionContract,\n options: { expectedFingerprint: string },\n): Promise<PostgresPermissionPlan> {\n const normalizedContract = validatePostgresPermissionContract(contract);\n if (!options || !/^[a-f0-9]{64}$/.test(options.expectedFingerprint))\n throw new Error(\n 'An expectedFingerprint from a reviewed permission plan is required.',\n );\n if (!db.transaction)\n throw new Error(\n 'PostgreSQL permissions require a transaction-capable database.',\n );\n return db.transaction(async (tx) => {\n await tx.query(\"SET LOCAL lock_timeout = '5s'\");\n await tx.query(\"SET LOCAL statement_timeout = '30s'\");\n // Cooperating permission writers serialize; operators must quiesce migrations.\n await tx.query(\n `SELECT pg_advisory_xact_lock(hashtext(${literal(`smrt-permissions:${normalizedContract.schema}`)}))`,\n );\n const before = await plan(tx, normalizedContract);\n if (before.fingerprint !== options.expectedFingerprint)\n throw new Error(\n 'Permission plan is stale; generate and review a new plan.',\n );\n if (!before.canApply)\n throw new Error(\n 'Permission plan has unsupported privilege sources or missing prerequisites; resolve its diagnostics first.',\n );\n const executor = (\n await tx.query(\n 'SELECT current_user AS name, rolsuper FROM pg_roles WHERE rolname=current_user',\n )\n ).rows[0];\n if (\n !executor.rolsuper &&\n executor.name !== normalizedContract.migrationOwner\n )\n throw new Error(\n 'Apply must execute as the migration owner or a PostgreSQL superuser.',\n );\n for (const statement of before.statements) await tx.query(statement);\n const after = await plan(tx, normalizedContract);\n if (!after.canApply || after.diagnostics.length)\n throw new Error(\n 'Permission verification failed; all permission changes have been rolled back.',\n );\n return after;\n });\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/prebuild/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAW5D,MAAM,WAAW,eAAe;IAC9B,+CAA+C;IAC/C,QAAQ,EAAE,MAAM,GAAG,mBAAmB,CAAC;IACvC,2CAA2C;IAC3C,MAAM,EAAE,MAAM,CAAC;IACf,0CAA0C;IAC1C,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,sCAAsC;IACtC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,qDAAqD;IACrD,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC,IAAI,CAAC,CAkCf;AA4aD;;GAEG;AACH,wBAAsB,2BAA2B,CAC/C,IAAI,EAAE,MAAM,EAAE,GACb,OAAO,CAAC,IAAI,CAAC,CAkBf"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/prebuild/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAW5D,MAAM,WAAW,eAAe;IAC9B,+CAA+C;IAC/C,QAAQ,EAAE,MAAM,GAAG,mBAAmB,CAAC;IACvC,2CAA2C;IAC3C,MAAM,EAAE,MAAM,CAAC;IACf,0CAA0C;IAC1C,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,sCAAsC;IACtC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,qDAAqD;IACrD,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC,IAAI,CAAC,CAkCf;AA+ZD;;GAEG;AACH,wBAAsB,2BAA2B,CAC/C,IAAI,EAAE,MAAM,EAAE,GACb,OAAO,CAAC,IAAI,CAAC,CAkBf"}
@@ -1,4 +1,4 @@
1
- import { compareText, selectWebCollectionEntries } from "../vite-plugin/web-collections.js";
1
+ import { orderedManifestObjectEntries, selectWebCollectionEntries } from "../vite-plugin/web-collections.js";
2
2
  import { renderApiClientCrudType, renderApiClientCustomMethodParameters, selectApiClientEntries } from "../vite-plugin/api-client-entries.js";
3
3
  import * as fs from "node:fs";
4
4
  import * as path from "node:path";
@@ -25,7 +25,7 @@ async function generateDeclarations(options) {
25
25
  */
26
26
  async function generateObjectTypeDeclarations(manifest, outDir) {
27
27
  const interfaces = [];
28
- const sortedObjectEntries = Object.entries(manifest.objects).sort(([leftKey, left], [rightKey, right]) => compareText(left.qualifiedName || leftKey, right.qualifiedName || rightKey) || compareText(leftKey, rightKey));
28
+ const sortedObjectEntries = orderedManifestObjectEntries(manifest);
29
29
  for (const [_objectName, objectMeta] of sortedObjectEntries) {
30
30
  const fields = objectMeta.fields || {};
31
31
  const propertyLines = [];
@@ -192,7 +192,7 @@ declare module '@smrt/mcp' {
192
192
  * Auto-generated types module declaration
193
193
  */
194
194
  declare module '@smrt/types' {
195
- ${Object.entries(manifest.objects).sort(([leftKey, left], [rightKey, right]) => compareText(left.qualifiedName || leftKey, right.qualifiedName || rightKey) || compareText(leftKey, rightKey)).map(([, obj]) => ` export type ${obj.className}Data = import('./smrt-objects').${obj.className}Data;`).join("\n")}
195
+ ${orderedManifestObjectEntries(manifest).map(([, obj]) => ` export type ${obj.className}Data = import('./smrt-objects').${obj.className}Data;`).join("\n")}
196
196
 
197
197
  export interface Request {
198
198
  params: Record<string, string>;