@prisma-next/target-postgres 0.14.0-dev.60 → 0.14.0-dev.62

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 (127) hide show
  1. package/dist/{authoring-WkqG_MkU.mjs → authoring-CdIZ0yvD.mjs} +147 -38
  2. package/dist/authoring-CdIZ0yvD.mjs.map +1 -0
  3. package/dist/contract-free.d.mts +1 -1
  4. package/dist/contract-free.d.mts.map +1 -1
  5. package/dist/contract-free.mjs +2 -2
  6. package/dist/{control-policy-Co_13Hxa.mjs → control-policy-DKp0HKpY.mjs} +203 -45
  7. package/dist/control-policy-DKp0HKpY.mjs.map +1 -0
  8. package/dist/control.mjs +22 -25
  9. package/dist/control.mjs.map +1 -1
  10. package/dist/{ddl-B-krEXY1.mjs → ddl-gmxHf68z.mjs} +20 -4
  11. package/dist/{ddl-B-krEXY1.mjs.map → ddl-gmxHf68z.mjs.map} +1 -1
  12. package/dist/ddl.d.mts +2 -2
  13. package/dist/ddl.mjs +2 -2
  14. package/dist/{descriptor-meta-BOcKPaLE.mjs → descriptor-meta-DEuXJfpR.mjs} +3 -3
  15. package/dist/{descriptor-meta-BOcKPaLE.mjs.map → descriptor-meta-DEuXJfpR.mjs.map} +1 -1
  16. package/dist/{diff-database-schema-BOsDnH64.mjs → diff-database-schema-D2sjvMw9.mjs} +55 -19
  17. package/dist/diff-database-schema-D2sjvMw9.mjs.map +1 -0
  18. package/dist/diff-database-schema.d.mts +4 -4
  19. package/dist/diff-database-schema.d.mts.map +1 -1
  20. package/dist/diff-database-schema.mjs +1 -1
  21. package/dist/issue-planner.d.mts +1 -1
  22. package/dist/issue-planner.d.mts.map +1 -1
  23. package/dist/issue-planner.mjs +1 -1
  24. package/dist/migration.d.mts +2 -2
  25. package/dist/migration.mjs +2 -2
  26. package/dist/{nodes-BtQyZha6.d.mts → nodes-Bc2N3tMy.d.mts} +27 -3
  27. package/dist/nodes-Bc2N3tMy.d.mts.map +1 -0
  28. package/dist/{nodes-B815pj_X.mjs → nodes-DJC5B8Id.mjs} +32 -2
  29. package/dist/nodes-DJC5B8Id.mjs.map +1 -0
  30. package/dist/{op-factory-call-DxNNKUeZ.mjs → op-factory-call-C4flTtTG.mjs} +105 -6
  31. package/dist/op-factory-call-C4flTtTG.mjs.map +1 -0
  32. package/dist/{op-factory-call-D6_7-7Vc.d.mts → op-factory-call-CSIg5XDu.d.mts} +26 -3
  33. package/dist/{op-factory-call-D6_7-7Vc.d.mts.map → op-factory-call-CSIg5XDu.d.mts.map} +1 -1
  34. package/dist/op-factory-call.d.mts +2 -2
  35. package/dist/op-factory-call.mjs +2 -2
  36. package/dist/pack.d.mts +146 -3
  37. package/dist/pack.d.mts.map +1 -1
  38. package/dist/pack.mjs +1 -1
  39. package/dist/{planner-CNrc1Odu.mjs → planner-BtEd5LMr.mjs} +32 -64
  40. package/dist/planner-BtEd5LMr.mjs.map +1 -0
  41. package/dist/{planner-ddl-builders-B8Nn6nHN.mjs → planner-ddl-builders-BKlmGDJl.mjs} +7 -3
  42. package/dist/planner-ddl-builders-BKlmGDJl.mjs.map +1 -0
  43. package/dist/planner-ddl-builders.d.mts.map +1 -1
  44. package/dist/planner-ddl-builders.mjs +1 -1
  45. package/dist/{planner-produced-postgres-migration-a-tjfKsA.d.mts → planner-produced-postgres-migration-CXue-6M9.d.mts} +2 -2
  46. package/dist/{planner-produced-postgres-migration-a-tjfKsA.d.mts.map → planner-produced-postgres-migration-CXue-6M9.d.mts.map} +1 -1
  47. package/dist/{planner-produced-postgres-migration-NI-oGKcw.mjs → planner-produced-postgres-migration-Jat3hg4u.mjs} +2 -2
  48. package/dist/{planner-produced-postgres-migration-NI-oGKcw.mjs.map → planner-produced-postgres-migration-Jat3hg4u.mjs.map} +1 -1
  49. package/dist/planner-produced-postgres-migration.d.mts +1 -1
  50. package/dist/planner-produced-postgres-migration.mjs +1 -1
  51. package/dist/{planner-sql-checks-AXoxB1Jl.mjs → planner-sql-checks-Br1c_QsH.mjs} +3 -3
  52. package/dist/{planner-sql-checks-AXoxB1Jl.mjs.map → planner-sql-checks-Br1c_QsH.mjs.map} +1 -1
  53. package/dist/planner-sql-checks.mjs +1 -1
  54. package/dist/planner.d.mts +3 -3
  55. package/dist/planner.d.mts.map +1 -1
  56. package/dist/planner.mjs +2 -2
  57. package/dist/{postgres-contract-view-Dg-N7KA7.mjs → postgres-contract-view-BAPW0ec1.mjs} +3 -3
  58. package/dist/{postgres-contract-view-Dg-N7KA7.mjs.map → postgres-contract-view-BAPW0ec1.mjs.map} +1 -1
  59. package/dist/{postgres-database-schema-node-CfdTY-Qs.d.mts → postgres-database-schema-node-CJv5bfbs.d.mts} +70 -26
  60. package/dist/postgres-database-schema-node-CJv5bfbs.d.mts.map +1 -0
  61. package/dist/{postgres-migration-ChyRsWvE.mjs → postgres-migration-ChLMQRd-.mjs} +19 -3
  62. package/dist/postgres-migration-ChLMQRd-.mjs.map +1 -0
  63. package/dist/{postgres-migration-Bzzi0Asr.d.mts → postgres-migration-DkmgGNcv.d.mts} +21 -2
  64. package/dist/postgres-migration-DkmgGNcv.d.mts.map +1 -0
  65. package/dist/{postgres-role-schema-node-BiSTCTNg.mjs → postgres-role-schema-node-Cm-j0ZGM.mjs} +20 -25
  66. package/dist/postgres-role-schema-node-Cm-j0ZGM.mjs.map +1 -0
  67. package/dist/{postgres-schema-DTLA_aRi.mjs → postgres-schema-DWQ0-CPb.mjs} +32 -4
  68. package/dist/postgres-schema-DWQ0-CPb.mjs.map +1 -0
  69. package/dist/{postgres-schema-CU4gF6QZ.d.mts → postgres-schema-DsrtYp2v.d.mts} +13 -1
  70. package/dist/postgres-schema-DsrtYp2v.d.mts.map +1 -0
  71. package/dist/{postgres-table-schema-node-9FCtCUz2.mjs → postgres-table-schema-node-D6LvInCe.mjs} +71 -8
  72. package/dist/postgres-table-schema-node-D6LvInCe.mjs.map +1 -0
  73. package/dist/{resolve-ddl-schema-Ca88Tg6W.mjs → resolve-ddl-schema-CAza65Iy.mjs} +2 -2
  74. package/dist/{resolve-ddl-schema-Ca88Tg6W.mjs.map → resolve-ddl-schema-CAza65Iy.mjs.map} +1 -1
  75. package/dist/runtime.mjs +1 -1
  76. package/dist/schema-ir-annotations.mjs +1 -1
  77. package/dist/{sql-utils-DcfMz4MQ.mjs → sql-utils-SU4FDvIV.mjs} +12 -3
  78. package/dist/{sql-utils-DcfMz4MQ.mjs.map → sql-utils-SU4FDvIV.mjs.map} +1 -1
  79. package/dist/sql-utils.d.mts +8 -1
  80. package/dist/sql-utils.d.mts.map +1 -1
  81. package/dist/sql-utils.mjs +2 -2
  82. package/dist/types.d.mts +3 -3
  83. package/dist/types.mjs +4 -4
  84. package/package.json +20 -20
  85. package/src/contract-free/ddl.ts +27 -0
  86. package/src/core/authoring.ts +136 -25
  87. package/src/core/ddl/nodes.ts +44 -0
  88. package/src/core/migrations/contract-to-postgres-database-schema-node.ts +12 -1
  89. package/src/core/migrations/control-policy.ts +172 -45
  90. package/src/core/migrations/diff-database-schema.ts +48 -13
  91. package/src/core/migrations/issue-planner.ts +77 -4
  92. package/src/core/migrations/op-factory-call.ts +84 -0
  93. package/src/core/migrations/operations/native-enum-types.ts +62 -0
  94. package/src/core/migrations/planner-ddl-builders.ts +12 -2
  95. package/src/core/migrations/planner.ts +30 -62
  96. package/src/core/migrations/postgres-migration.ts +31 -0
  97. package/src/core/migrations/verify-postgres-namespaces.ts +0 -1
  98. package/src/core/postgres-role.ts +22 -0
  99. package/src/core/postgres-schema.ts +22 -1
  100. package/src/core/postgres-validators.ts +1 -0
  101. package/src/core/psl-infer/infer-psl-contract.ts +7 -16
  102. package/src/core/schema-ir/node-storage-coordinate.ts +26 -0
  103. package/src/core/schema-ir/postgres-database-schema-node.ts +5 -4
  104. package/src/core/schema-ir/postgres-namespace-schema-node.ts +18 -27
  105. package/src/core/schema-ir/postgres-native-enum-schema-node.ts +83 -0
  106. package/src/core/schema-ir/postgres-role-schema-node.ts +4 -2
  107. package/src/core/schema-ir/schema-node-kinds.ts +19 -3
  108. package/src/core/sql-utils.ts +15 -2
  109. package/src/exports/ddl.ts +2 -0
  110. package/src/exports/op-factory-call.ts +2 -0
  111. package/src/exports/sql-utils.ts +1 -0
  112. package/src/exports/types.ts +4 -1
  113. package/dist/authoring-WkqG_MkU.mjs.map +0 -1
  114. package/dist/control-policy-Co_13Hxa.mjs.map +0 -1
  115. package/dist/diff-database-schema-BOsDnH64.mjs.map +0 -1
  116. package/dist/nodes-B815pj_X.mjs.map +0 -1
  117. package/dist/nodes-BtQyZha6.d.mts.map +0 -1
  118. package/dist/op-factory-call-DxNNKUeZ.mjs.map +0 -1
  119. package/dist/planner-CNrc1Odu.mjs.map +0 -1
  120. package/dist/planner-ddl-builders-B8Nn6nHN.mjs.map +0 -1
  121. package/dist/postgres-database-schema-node-CfdTY-Qs.d.mts.map +0 -1
  122. package/dist/postgres-migration-Bzzi0Asr.d.mts.map +0 -1
  123. package/dist/postgres-migration-ChyRsWvE.mjs.map +0 -1
  124. package/dist/postgres-role-schema-node-BiSTCTNg.mjs.map +0 -1
  125. package/dist/postgres-schema-CU4gF6QZ.d.mts.map +0 -1
  126. package/dist/postgres-schema-DTLA_aRi.mjs.map +0 -1
  127. package/dist/postgres-table-schema-node-9FCtCUz2.mjs.map +0 -1
@@ -1,9 +1,9 @@
1
- import { r as isPostgresSchema } from "./postgres-schema-DTLA_aRi.mjs";
2
- import { i as quoteIdentifier } from "./sql-utils-DcfMz4MQ.mjs";
3
- import { n as PostgresSchemaNodeKind, t as PostgresTableSchemaNode } from "./postgres-table-schema-node-9FCtCUz2.mjs";
4
- import { A as buildTargetDetails, C as DropTableCall, D as SetDefaultCall, O as SetNotNullCall, T as RawSqlCall, _ as DropColumnCall, a as AddNotNullColumnWithTempDefaultCall, b as DropIndexCall, c as AlterColumnTypeCall, f as CreateSchemaCall, g as DropCheckConstraintCall, h as DisableRowLevelSecurityCall, i as AddNotNullColumnDirectCall, k as postgresDefaultToDdlColumnDefault, m as DataTransformCall, n as AddColumnCall, o as AddPrimaryKeyCall, p as CreateTableCall, r as AddForeignKeyCall, s as AddUniqueCall, t as AddCheckConstraintCall, u as CreateIndexCall, v as DropConstraintCall, w as EnableRowLevelSecurityCall, x as DropNotNullCall, y as DropDefaultCall } from "./op-factory-call-DxNNKUeZ.mjs";
5
- import { t as buildExpectedFormatType } from "./planner-sql-checks-AXoxB1Jl.mjs";
6
- import { n as buildColumnTypeSql, t as buildColumnDefaultSql } from "./planner-ddl-builders-B8Nn6nHN.mjs";
1
+ import { r as isPostgresSchema } from "./postgres-schema-DWQ0-CPb.mjs";
2
+ import { i as quoteIdentifier } from "./sql-utils-SU4FDvIV.mjs";
3
+ import { n as PostgresNativeEnumSchemaNode, o as postgresNodeEntityKind, r as PostgresSchemaNodeKind, t as PostgresTableSchemaNode } from "./postgres-table-schema-node-D6LvInCe.mjs";
4
+ import { A as SetNotNullCall, C as DropNotNullCall, D as RawSqlCall, E as EnableRowLevelSecurityCall, M as buildTargetDetails, S as DropNativeEnumTypeCall, T as DropTableCall, _ as DropCheckConstraintCall, a as AddNotNullColumnWithTempDefaultCall, b as DropDefaultCall, c as AlterColumnTypeCall, d as CreateNativeEnumTypeCall, g as DisableRowLevelSecurityCall, h as DataTransformCall, i as AddNotNullColumnDirectCall, j as postgresDefaultToDdlColumnDefault, k as SetDefaultCall, m as CreateTableCall, n as AddColumnCall, o as AddPrimaryKeyCall, p as CreateSchemaCall, r as AddForeignKeyCall, s as AddUniqueCall, t as AddCheckConstraintCall, u as CreateIndexCall, v as DropColumnCall, x as DropIndexCall, y as DropConstraintCall } from "./op-factory-call-C4flTtTG.mjs";
5
+ import { t as buildExpectedFormatType } from "./planner-sql-checks-Br1c_QsH.mjs";
6
+ import { n as buildColumnTypeSql, t as buildColumnDefaultSql } from "./planner-ddl-builders-BKlmGDJl.mjs";
7
7
  import { n as resolveIdentityValue } from "./planner-identity-values-CJPha2Sz.mjs";
8
8
  import { i as hasUniqueConstraint, n as hasForeignKey, t as buildSchemaLookupMap } from "./planner-schema-lookup-CiVaAQP-.mjs";
9
9
  import { UNBOUND_NAMESPACE_ID, entityAt } from "@prisma-next/framework-components/ir";
@@ -15,6 +15,31 @@ import * as contractFree from "@prisma-next/sql-relational-core/contract-free";
15
15
  import { RelationalSchemaNodeKind, SqlSchemaIR } from "@prisma-next/sql-schema-ir/types";
16
16
  import { defaultIndexName } from "@prisma-next/sql-schema-ir/naming";
17
17
  import { notOk, ok } from "@prisma-next/utils/result";
18
+ //#region src/core/schema-ir/node-storage-coordinate.ts
19
+ /**
20
+ * The storage-`entries` coordinate `(entityKind, entityName)` a Postgres diff
21
+ * node addresses — a table by its name, a native enum by its physical type
22
+ * name. `undefined` for a node that is not a whole storage entity (a namespace,
23
+ * a column, a policy). Lets ownership/subject resolution treat every entity kind
24
+ * uniformly, the node self-describing its storage identity.
25
+ */
26
+ function postgresNodeStorageCoordinate(node) {
27
+ if (PostgresTableSchemaNode.is(node)) {
28
+ const entityKind = postgresNodeEntityKind(node.nodeKind);
29
+ return entityKind === void 0 ? void 0 : {
30
+ entityKind,
31
+ entityName: node.name
32
+ };
33
+ }
34
+ if (PostgresNativeEnumSchemaNode.is(node)) {
35
+ const entityKind = postgresNodeEntityKind(node.nodeKind);
36
+ return entityKind === void 0 ? void 0 : {
37
+ entityKind,
38
+ entityName: node.typeName
39
+ };
40
+ }
41
+ }
42
+ //#endregion
18
43
  //#region src/core/migrations/column-ddl-rendering.ts
19
44
  /**
20
45
  * Reconstructs the `StorageColumn`-shaped fields the DDL builder functions
@@ -542,8 +567,10 @@ function issueConflict(kind, summary, location) {
542
567
  function classifyCall(call) {
543
568
  switch (call.factoryName) {
544
569
  case "createExtension":
545
- case "createSchema": return "dep";
570
+ case "createSchema":
571
+ case "createNativeEnumType": return "dep";
546
572
  case "dropTable":
573
+ case "dropNativeEnumType":
547
574
  case "dropColumn":
548
575
  case "dropConstraint":
549
576
  case "dropCheckConstraint":
@@ -594,11 +621,16 @@ function conflictKindForCall(call) {
594
621
  function locationForCall(call) {
595
622
  const anyCall = call;
596
623
  const location = {};
597
- if (anyCall.tableName) location.table = anyCall.tableName;
624
+ if (anyCall.tableName) {
625
+ location.entityKind = "table";
626
+ location.entityName = anyCall.tableName;
627
+ } else if (anyCall.typeName) {
628
+ location.entityKind = "native_enum";
629
+ location.entityName = anyCall.typeName;
630
+ }
598
631
  if (anyCall.columnName) location.column = anyCall.columnName;
599
632
  if (anyCall.indexName) location.index = anyCall.indexName;
600
633
  if (anyCall.constraintName) location.constraint = anyCall.constraintName;
601
- if (anyCall.typeName) location.type = anyCall.typeName;
602
634
  return Object.keys(location).length > 0 ? location : void 0;
603
635
  }
604
636
  function conflictForDisallowedCall(call, allowed) {
@@ -674,6 +706,7 @@ function nodeIssueOrder(issue) {
674
706
  if (node === void 0) return 99;
675
707
  switch (node.nodeKind) {
676
708
  case PostgresSchemaNodeKind.namespace: return 1;
709
+ case PostgresSchemaNodeKind.nativeEnum: return issue.reason === "not-expected" ? 17 : 2;
677
710
  case RelationalSchemaNodeKind.foreignKey: return issue.reason === "not-expected" ? 10 : 60;
678
711
  case RelationalSchemaNodeKind.unique: return issue.reason === "not-expected" ? 11 : 51;
679
712
  case RelationalSchemaNodeKind.primaryKey: return issue.reason === "not-expected" ? 12 : 50;
@@ -759,6 +792,27 @@ function buildCreateTableCallsFromNode(schemaName, ddlSchemaName, table, codecHo
759
792
  function nodeConflict(kind, message) {
760
793
  return issueConflict(kind, message);
761
794
  }
795
+ /**
796
+ * Managed native-enum issue -> op lowering. A missing declared type creates
797
+ * it; an unclaimed live type drops it (ownership-scoped upstream by
798
+ * `retainUnownedExtras`, destructiveness gated by the operation-class
799
+ * policy); a paired member-value mismatch is a NAMED unsupported diagnostic
800
+ * — never a silent no-op and never a drop-and-recreate. Slice B replaces the
801
+ * diagnostic with order-aware `ALTER TYPE ... ADD VALUE` / refusal semantics.
802
+ */
803
+ function mapNativeEnumNodeIssue(issue, ctx) {
804
+ const ddlSchemaName = issueSchemaName(issue);
805
+ if (ddlSchemaName === void 0) return notOk(nodeConflict("unsupportedOperation", `Enum issue has no schema in its path: ${issue.path.join("/")}`));
806
+ const schemaName = emissionSchemaName(ctx, ddlSchemaName);
807
+ if (issue.reason === "not-found") {
808
+ const expected = blindCast(issue.expected);
809
+ return ok([new CreateNativeEnumTypeCall(schemaName, expected.typeName, expected.members)]);
810
+ }
811
+ if (issue.reason === "not-expected") return ok([new DropNativeEnumTypeCall(schemaName, blindCast(issue.actual).typeName)]);
812
+ const expected = blindCast(issue.expected);
813
+ const actualMembers = blindCast(issue.actual).members;
814
+ return notOk(nodeConflict("unsupportedOperation", `Native enum type "${ddlSchemaName}"."${expected.typeName}" member values changed (contract declares [${expected.members.join(", ")}], database has [${actualMembers.join(", ")}]); enum value changes are not auto-migrated yet. Author the change manually with \`migration new\`.`));
815
+ }
762
816
  function mapTableNodeIssue(issue, schemaName, ddlSchemaName, codecHooks) {
763
817
  if (issue.reason === "not-found") return ok(buildCreateTableCallsFromNode(schemaName, ddlSchemaName, blindCast(issue.expected), codecHooks));
764
818
  if (issue.reason === "not-expected") return ok([new DropTableCall(schemaName, blindCast(issue.actual).name)]);
@@ -853,6 +907,7 @@ function mapNodeIssueToCall(issue, ctx) {
853
907
  if (issue.reason !== "not-found") return notOk(nodeConflict("unsupportedOperation", `Unexpected namespace drift: ${issue.path.join("/")}`));
854
908
  return ok([new CreateSchemaCall(blindCast(issue.expected).schemaName)]);
855
909
  }
910
+ if (node.nodeKind === PostgresSchemaNodeKind.nativeEnum) return mapNativeEnumNodeIssue(issue, ctx);
856
911
  const ddlSchemaName = issueSchemaName(issue);
857
912
  const tableName = issueTableName(issue);
858
913
  if (ddlSchemaName === void 0 || tableName === void 0) return notOk(nodeConflict("unsupportedOperation", `Issue has no schema/table in its path: ${issue.path.join("/")}`));
@@ -972,13 +1027,16 @@ function planIssues(options) {
972
1027
  * and is fail-closed. Any call not listed here — including future or
973
1028
  * extension-contributed factories — is treated as NOT object-creation, so it
974
1029
  * is suppressed under `tolerated` rather than permissively emitted.
1030
+ *
1031
+ * Lists the creation factories that actually reach the call-side resolver
1032
+ * (`resolvePostgresCallControlPolicySubject`) — today only RLS policy
1033
+ * creation, from `planPostgresSchemaDiff`. Every other whole-object create
1034
+ * (table, schema, native enum, and RLS enablement) is constructed inside
1035
+ * `planIssues` and graded on the node side by
1036
+ * `resolvePostgresNodeIssueCreationFactoryName`, so none of them are listed
1037
+ * here.
975
1038
  */
976
- const OBJECT_CREATION_FACTORIES = new Set([
977
- "createTable",
978
- "createSchema",
979
- "createRlsPolicy",
980
- "enableRowLevelSecurity"
981
- ]);
1039
+ const OBJECT_CREATION_FACTORIES = new Set(["createRlsPolicy"]);
982
1040
  function createsNewTopLevelObject(call) {
983
1041
  return OBJECT_CREATION_FACTORIES.has(call.factoryName);
984
1042
  }
@@ -986,17 +1044,33 @@ function ddlSchemaNameForNamespace(contract, namespaceId) {
986
1044
  const namespace = contract.storage.namespaces[namespaceId];
987
1045
  return isPostgresSchema(namespace) ? namespace.ddlSchemaName(contract.storage) : namespaceId;
988
1046
  }
989
- function resolveNamespaceIdForTable(contract, tableName, ddlSchemaName) {
1047
+ /**
1048
+ * Resolve the namespace a declared storage entity lives in by walking every
1049
+ * namespace for one whose `entries` map actually contains the coordinate —
1050
+ * a table by its name, a native enum by its physical type name (see
1051
+ * {@link postgresNodeStorageCoordinate}). When `ddlSchemaName` is given, the
1052
+ * match must also land in that DDL schema (disambiguates same-named entities
1053
+ * declared under different namespaces); when omitted, the first namespace
1054
+ * that declares the entity wins. Falls back to {@link UNBOUND_NAMESPACE_ID}
1055
+ * when no namespace declares it — e.g. an extra/dropped entity the contract
1056
+ * doesn't claim at all.
1057
+ */
1058
+ function resolveNamespaceIdForEntity(contract, coordinate, ddlSchemaName) {
990
1059
  for (const namespaceId of Object.keys(contract.storage.namespaces)) {
991
1060
  if (!entityAt(contract.storage, {
992
1061
  namespaceId,
993
- entityKind: "table",
994
- entityName: tableName
1062
+ ...coordinate
995
1063
  })) continue;
996
1064
  if (ddlSchemaName === void 0 || ddlSchemaNameForNamespace(contract, namespaceId) === ddlSchemaName) return namespaceId;
997
1065
  }
998
1066
  return UNBOUND_NAMESPACE_ID;
999
1067
  }
1068
+ function resolveNamespaceIdForTable(contract, tableName, ddlSchemaName) {
1069
+ return resolveNamespaceIdForEntity(contract, {
1070
+ entityKind: "table",
1071
+ entityName: tableName
1072
+ }, ddlSchemaName);
1073
+ }
1000
1074
  function resolveNamespaceIdForDdlSchema(contract, ddlSchemaName) {
1001
1075
  for (const namespaceId of Object.keys(contract.storage.namespaces)) {
1002
1076
  const ns = contract.storage.namespaces[namespaceId];
@@ -1012,9 +1086,42 @@ function postgresCallFields(call) {
1012
1086
  ...ifDefined("columnName", "columnName" in call ? call.columnName : void 0)
1013
1087
  };
1014
1088
  }
1015
- function formatPostgresControlPolicySubjectLabel(factoryName, subject, contract) {
1016
- if (subject?.table) return `${factoryName}(${ddlSchemaNameForNamespace(contract, subject.namespaceId)}.${subject.table})`;
1017
- return factoryName;
1089
+ function formatSuppressionSubjectLabel(subject, contract) {
1090
+ if (subject === void 0) return "unknown";
1091
+ const ddlSchema = ddlSchemaNameForNamespace(contract, subject.namespaceId);
1092
+ if (subject.entityKind !== void 0 && subject.entityName !== void 0) return `${subject.entityKind} "${ddlSchema}.${subject.entityName}"`;
1093
+ return `namespace "${ddlSchema}"`;
1094
+ }
1095
+ function postgresSuppressionSummary(subjectLabel, subject, policy) {
1096
+ const namespace = subject?.namespaceId ?? "unknown";
1097
+ const declared = subject?.explicitNodeControlPolicy;
1098
+ if (policy === "external" && declared === "managed") return `control policy suppressed: ${subjectLabel} — namespace '${namespace}' has effective control 'external' but declared 'managed'`;
1099
+ return `control policy suppressed: ${subjectLabel} — namespace '${namespace}' has effective control '${policy}'${declared ? ` but declared '${declared}'` : ""}`;
1100
+ }
1101
+ /**
1102
+ * Render one family {@link SuppressionRecord} into a target `SqlPlannerConflict`.
1103
+ * The family decides *that* a subject is suppressed and hands over the raw
1104
+ * coordinate + policy; the label, message, and location are rendered here,
1105
+ * driven entirely by the subject's own `(entityKind, entityName)` coordinate
1106
+ * — no target-owned table-vs-enum vocabulary.
1107
+ */
1108
+ function renderPostgresSuppression(record, contract) {
1109
+ const subject = record.subject;
1110
+ return {
1111
+ kind: "controlPolicySuppressedCall",
1112
+ summary: postgresSuppressionSummary(formatSuppressionSubjectLabel(subject, contract), subject, record.policy),
1113
+ location: {
1114
+ ...ifDefined("namespaceId", subject?.namespaceId),
1115
+ ...ifDefined("entityKind", subject?.entityKind),
1116
+ ...ifDefined("entityName", subject?.entityName),
1117
+ ...ifDefined("column", subject?.column)
1118
+ },
1119
+ meta: {
1120
+ controlPolicy: record.policy,
1121
+ ...ifDefined("factoryName", record.factoryName),
1122
+ ...ifDefined("declaredControlPolicy", subject?.explicitNodeControlPolicy)
1123
+ }
1124
+ };
1018
1125
  }
1019
1126
  function resolvePostgresCallControlPolicySubject(call, contract) {
1020
1127
  const callFields = postgresCallFields(call);
@@ -1032,9 +1139,10 @@ function resolvePostgresCallControlPolicySubject(call, contract) {
1032
1139
  })?.control;
1033
1140
  return {
1034
1141
  namespaceId,
1035
- ...ifDefined("explicitNodeControlPolicy", tableControlPolicy),
1036
- table: callFields.tableName,
1142
+ entityKind: "table",
1143
+ entityName: callFields.tableName,
1037
1144
  ...ifDefined("column", callFields.columnName),
1145
+ ...ifDefined("explicitNodeControlPolicy", tableControlPolicy),
1038
1146
  createsNewObject
1039
1147
  };
1040
1148
  }
@@ -1044,10 +1152,10 @@ function resolvePostgresCallControlPolicySubject(call, contract) {
1044
1152
  };
1045
1153
  }
1046
1154
  /**
1047
- * Node kinds that describe the absence of a whole, top-level Postgres
1048
- * object the same objects `createsNewTopLevelObject` recognises for calls.
1049
- * Used by {@link resolvePostgresNodeIssueCreationFactoryName} to decide
1050
- * whether a `tolerated` subject permits the issue to flow into the planner
1155
+ * Node kinds whose *absence* is the creation of a whole, top-level Postgres
1156
+ * object: a namespace, a table, or a native enum. Used by
1157
+ * {@link resolvePostgresNodeIssueCreationFactoryName} to decide whether a
1158
+ * `tolerated` subject permits the issue to flow into the planner
1051
1159
  * (create-if-absent) and to seed the suppressed-subject warning's
1052
1160
  * `factoryName` when the planner is skipped. RLS policy creation is not
1053
1161
  * listed here — policy issues never reach this issue-based partition (they
@@ -1056,13 +1164,15 @@ function resolvePostgresCallControlPolicySubject(call, contract) {
1056
1164
  */
1057
1165
  const POSTGRES_NODE_CREATION_FACTORY = Object.freeze({
1058
1166
  [PostgresSchemaNodeKind.namespace]: "createSchema",
1059
- [PostgresSchemaNodeKind.table]: "createTable"
1167
+ [PostgresSchemaNodeKind.table]: "createTable",
1168
+ [PostgresSchemaNodeKind.nativeEnum]: "createNativeEnumType"
1060
1169
  });
1061
1170
  /**
1062
1171
  * A table `not-equal` issue whose `rlsEnabled` flips OFF→ON (expected on,
1063
- * actual off) is enablement toward `ENABLE ROW LEVEL SECURITY`
1064
- * creation-class per `OBJECT_CREATION_FACTORIES` ('enableRowLevelSecurity'
1065
- * is a member): enabling RLS establishes the fail-closed guard the declared
1172
+ * actual off) is enablement toward `ENABLE ROW LEVEL SECURITY`. It is
1173
+ * creation-class on the node side because `isEnablementCreationIssue` and
1174
+ * {@link resolvePostgresNodeIssueCreationFactoryName} treat this OFF→ON delta
1175
+ * as a creation: enabling RLS establishes the fail-closed guard the declared
1066
1176
  * policy set attaches to, the same grant `tolerated` extends to creating the
1067
1177
  * policies themselves. The opposite direction (`DISABLE`) is a modification
1068
1178
  * and stays managed-only. Keying on the actual delta (not just the expected
@@ -1087,15 +1197,36 @@ function resolvePostgresNodeIssueCreationFactoryName(issue) {
1087
1197
  * {@link SchemaDiffIssue}. Mirrors the resolution
1088
1198
  * `resolvePostgresCallControlPolicySubject` performs for a generated DDL
1089
1199
  * call, but works *off the issue* — so the planner can partition issues by
1090
- * effective policy before the diff engine runs. `createsNewObject` is
1091
- * derived from the node kind + reason: a `not-found` schema/table describes
1092
- * a brand-new top-level object; everything else touches an existing object.
1200
+ * effective policy before the diff engine runs.
1201
+ *
1202
+ * A whole storage entity (table or native enum) resolves generically off
1203
+ * {@link postgresNodeStorageCoordinate} — the node self-describes its
1204
+ * `(entityKind, entityName)`, so table and enum issues share one code path
1205
+ * with no per-kind branch. A sub-entity issue (a column/constraint drift
1206
+ * inside an owned table) carries no such coordinate on its own node, so it
1207
+ * falls back to reading the enclosing table name off the issue path.
1208
+ *
1209
+ * `createsNewObject` is delegated to {@link resolvePostgresNodeIssueCreationFactoryName}
1210
+ * in every branch below — that function already encodes exactly which
1211
+ * node-kind/reason combinations describe a brand-new top-level object
1212
+ * (a `not-found` table/enum, or an RLS-enablement `not-equal`).
1213
+ *
1214
+ * A `not-expected` (extra/dropped) entity carries no contract namespace
1215
+ * coordinate — the live object isn't claimed by any contract namespace — so
1216
+ * the subject's `namespaceId` falls back to {@link UNBOUND_NAMESPACE_ID} via
1217
+ * `resolveNamespaceIdForEntity`'s own fallback, matching how the call-side
1218
+ * resolver treats the `DropTableCall`/`DropNativeEnumTypeCall` it produces.
1093
1219
  *
1094
- * A `not-expected` table carries no contract namespace coordinate (the live
1095
- * table isn't claimed by any contract namespace), so the subject's
1096
- * `namespaceId` falls back to {@link UNBOUND_NAMESPACE_ID} via
1097
- * `resolveNamespaceIdForTable`'s own fallbackthe call-side resolver does
1098
- * the same for the `DropTableCall` it produces.
1220
+ * A role node resolves against the `PostgresRole` contract entity at that
1221
+ * role's name (roles are root-level diff subjects, so the name is the
1222
+ * second path segment after the tree root). A `not-found` role is declared,
1223
+ * so the entity is always found and its `control` read directlywhich is
1224
+ * always {@link ROLE_DEFAULT_CONTROL_POLICY} today, since no authoring
1225
+ * surface sets it otherwise. A `not-expected` role has no contract entity
1226
+ * (an undeclared live role, by definition), so the subject falls back to
1227
+ * the same default — roles are referenced but never owned, so an
1228
+ * undeclared role gets exactly the same governance as a declared one.
1229
+ * Never creates a new object: role provisioning is a non-goal.
1099
1230
  */
1100
1231
  function resolvePostgresNodeIssueControlPolicySubject(issue, contract) {
1101
1232
  const node = issue.expected ?? issue.actual;
@@ -1104,6 +1235,33 @@ function resolvePostgresNodeIssueControlPolicySubject(issue, contract) {
1104
1235
  namespaceId: resolveNamespaceIdForDdlSchema(contract, blindCast(node).schemaName),
1105
1236
  createsNewObject: issue.reason === "not-found"
1106
1237
  };
1238
+ if (node.nodeKind === PostgresSchemaNodeKind.role) {
1239
+ const roleName = issue.path[1];
1240
+ return {
1241
+ namespaceId: UNBOUND_NAMESPACE_ID,
1242
+ explicitNodeControlPolicy: (roleName === void 0 ? void 0 : entityAt(contract.storage, {
1243
+ namespaceId: UNBOUND_NAMESPACE_ID,
1244
+ entityKind: "role",
1245
+ entityName: roleName
1246
+ }))?.control ?? "external",
1247
+ createsNewObject: false
1248
+ };
1249
+ }
1250
+ const coordinate = postgresNodeStorageCoordinate(node);
1251
+ if (coordinate !== void 0) {
1252
+ const namespaceId = resolveNamespaceIdForEntity(contract, coordinate, issue.path[1]);
1253
+ const entityControl = entityAt(contract.storage, {
1254
+ namespaceId,
1255
+ ...coordinate
1256
+ })?.control;
1257
+ return {
1258
+ namespaceId,
1259
+ ...coordinate,
1260
+ ...ifDefined("column", issueColumnName(issue)),
1261
+ ...ifDefined("explicitNodeControlPolicy", entityControl),
1262
+ createsNewObject: resolvePostgresNodeIssueCreationFactoryName(issue) !== void 0
1263
+ };
1264
+ }
1107
1265
  const tableName = issue.path[2];
1108
1266
  if (tableName === void 0) return void 0;
1109
1267
  const ddlSchemaName = issue.path[1];
@@ -1113,16 +1271,16 @@ function resolvePostgresNodeIssueControlPolicySubject(issue, contract) {
1113
1271
  entityKind: "table",
1114
1272
  entityName: tableName
1115
1273
  });
1116
- const createsNewObject = node.nodeKind === PostgresSchemaNodeKind.table && issue.reason === "not-found" || isEnablementCreationIssue(issue);
1117
1274
  return {
1118
1275
  namespaceId,
1119
- ...ifDefined("explicitNodeControlPolicy", table?.control),
1120
- table: tableName,
1276
+ entityKind: "table",
1277
+ entityName: tableName,
1121
1278
  ...ifDefined("column", issueColumnName(issue)),
1122
- createsNewObject
1279
+ ...ifDefined("explicitNodeControlPolicy", table?.control),
1280
+ createsNewObject: resolvePostgresNodeIssueCreationFactoryName(issue) !== void 0
1123
1281
  };
1124
1282
  }
1125
1283
  //#endregion
1126
- export { resolvePostgresNodeIssueCreationFactoryName as a, issueSchemaName as c, postgresPlannerStrategies as d, resolvePostgresNodeIssueControlPolicySubject as i, issueTableName as l, resolveNamespaceIdForDdlSchema as n, coalesceSubtreeIssues as o, resolvePostgresCallControlPolicySubject as r, issueNode as s, formatPostgresControlPolicySubjectLabel as t, planIssues as u };
1284
+ export { resolvePostgresNodeIssueCreationFactoryName as a, issueSchemaName as c, postgresNodeStorageCoordinate as d, resolvePostgresNodeIssueControlPolicySubject as i, planIssues as l, resolveNamespaceIdForDdlSchema as n, coalesceSubtreeIssues as o, resolvePostgresCallControlPolicySubject as r, issueNode as s, renderPostgresSuppression as t, postgresPlannerStrategies as u };
1127
1285
 
1128
- //# sourceMappingURL=control-policy-Co_13Hxa.mjs.map
1286
+ //# sourceMappingURL=control-policy-DKp0HKpY.mjs.map