@prisma-next/family-sql 0.14.0-dev.4 → 0.14.0-dev.40

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 (66) hide show
  1. package/dist/{authoring-type-constructors-CjFfO6LM.mjs → authoring-type-constructors-CXd-8ydc.mjs} +7 -30
  2. package/dist/authoring-type-constructors-CXd-8ydc.mjs.map +1 -0
  3. package/dist/contract-to-schema-ir-S-evq8E6.mjs +264 -0
  4. package/dist/contract-to-schema-ir-S-evq8E6.mjs.map +1 -0
  5. package/dist/{control-adapter-Cmw9LvEP.d.mts → control-adapter-DHYFuOBy.d.mts} +12 -7
  6. package/dist/{control-adapter-Cmw9LvEP.d.mts.map → control-adapter-DHYFuOBy.d.mts.map} +1 -1
  7. package/dist/control-adapter.d.mts +1 -1
  8. package/dist/control.d.mts +18 -3
  9. package/dist/control.d.mts.map +1 -1
  10. package/dist/control.mjs +81 -943
  11. package/dist/control.mjs.map +1 -1
  12. package/dist/{schema-verify.d.mts → diff.d.mts} +5 -5
  13. package/dist/diff.d.mts.map +1 -0
  14. package/dist/{verify-sql-schema-xT4udQLQ.mjs → diff.mjs} +169 -253
  15. package/dist/diff.mjs.map +1 -0
  16. package/dist/ir.d.mts +9 -6
  17. package/dist/ir.d.mts.map +1 -1
  18. package/dist/ir.mjs +1 -1
  19. package/dist/migration.d.mts +11 -2
  20. package/dist/migration.d.mts.map +1 -1
  21. package/dist/migration.mjs +7 -0
  22. package/dist/migration.mjs.map +1 -1
  23. package/dist/pack.mjs +1 -1
  24. package/dist/psl-infer.d.mts +80 -0
  25. package/dist/psl-infer.d.mts.map +1 -0
  26. package/dist/psl-infer.mjs +334 -0
  27. package/dist/psl-infer.mjs.map +1 -0
  28. package/dist/{sql-contract-serializer-BR2vC7Z-.mjs → sql-contract-serializer-CYtXg_zs.mjs} +17 -20
  29. package/dist/sql-contract-serializer-CYtXg_zs.mjs.map +1 -0
  30. package/dist/{verify-sql-schema-thU-jKpf.d.mts → sql-schema-diff-6z36dZt6.d.mts} +44 -5
  31. package/dist/sql-schema-diff-6z36dZt6.d.mts.map +1 -0
  32. package/dist/{types-kgstZ_Zd.d.mts → types-CkOIJXxU.d.mts} +84 -17
  33. package/dist/types-CkOIJXxU.d.mts.map +1 -0
  34. package/package.json +23 -23
  35. package/src/core/authoring-entity-types.ts +12 -37
  36. package/src/core/control-adapter.ts +10 -5
  37. package/src/core/control-instance.ts +174 -41
  38. package/src/core/{schema-verify/verify-sql-schema.ts → diff/sql-schema-diff.ts} +208 -16
  39. package/src/core/{schema-verify → diff}/verify-helpers.ts +12 -0
  40. package/src/core/ir/sql-contract-serializer-base.ts +23 -55
  41. package/src/core/ir/sql-contract-serializer.ts +5 -7
  42. package/src/core/migrations/contract-to-schema-ir.ts +49 -12
  43. package/src/core/migrations/field-event-planner.ts +2 -2
  44. package/src/core/migrations/schema-differ.ts +40 -0
  45. package/src/core/migrations/types.ts +43 -2
  46. package/src/core/psl-contract-infer/printer-config.ts +0 -6
  47. package/src/core/sql-migration.ts +12 -1
  48. package/src/exports/control.ts +1 -0
  49. package/src/exports/diff.ts +18 -0
  50. package/src/exports/psl-infer.ts +36 -0
  51. package/dist/authoring-type-constructors-CjFfO6LM.mjs.map +0 -1
  52. package/dist/schema-verify.d.mts.map +0 -1
  53. package/dist/schema-verify.mjs +0 -2
  54. package/dist/sql-contract-serializer-BR2vC7Z-.mjs.map +0 -1
  55. package/dist/test-utils.d.mts +0 -2
  56. package/dist/test-utils.mjs +0 -2
  57. package/dist/types-kgstZ_Zd.d.mts.map +0 -1
  58. package/dist/verify-sql-schema-thU-jKpf.d.mts.map +0 -1
  59. package/dist/verify-sql-schema-xT4udQLQ.mjs.map +0 -1
  60. package/src/core/psl-contract-infer/postgres-default-mapping.ts +0 -16
  61. package/src/core/psl-contract-infer/postgres-type-map.ts +0 -157
  62. package/src/core/psl-contract-infer/sql-schema-ir-to-psl-ast.ts +0 -795
  63. package/src/exports/schema-verify.ts +0 -18
  64. package/src/exports/test-utils.ts +0 -9
  65. /package/src/core/{schema-verify → diff}/control-verify-emit.ts +0 -0
  66. /package/src/core/{schema-verify → diff}/verifier-disposition.ts +0 -0
@@ -1,8 +1,10 @@
1
1
  import type {
2
2
  Contract,
3
3
  ContractMarkerRecord,
4
+ ControlPolicy,
4
5
  LedgerEntryRecord,
5
6
  } from '@prisma-next/contract/types';
7
+ import { effectiveControlPolicy } from '@prisma-next/contract/types';
6
8
  import type {
7
9
  TargetBoundComponentDescriptor,
8
10
  TargetDescriptor,
@@ -15,6 +17,7 @@ import type {
15
17
  OperationPreview,
16
18
  OperationPreviewCapable,
17
19
  PslContractInferCapable,
20
+ SchemaDiffIssue,
18
21
  SchemaViewCapable,
19
22
  SignDatabaseResult,
20
23
  VerifyDatabaseResult,
@@ -22,12 +25,14 @@ import type {
22
25
  } from '@prisma-next/framework-components/control';
23
26
  import {
24
27
  APP_SPACE_ID,
28
+ dispositionForCategory,
25
29
  SchemaTreeNode,
26
30
  VERIFY_CODE_HASH_MISMATCH,
27
31
  VERIFY_CODE_MARKER_MISSING,
28
32
  VERIFY_CODE_TARGET_MISMATCH,
29
33
  } from '@prisma-next/framework-components/control';
30
34
  import type { TypesImportSpec } from '@prisma-next/framework-components/emission';
35
+ import { isPlainRecord } from '@prisma-next/framework-components/ir';
31
36
  import type { PslDocumentAst } from '@prisma-next/framework-components/psl-ast';
32
37
  import { assertDescriptorSelfConsistency } from '@prisma-next/migration-tools/spaces';
33
38
  import { sqlContractCanonicalizationHooks } from '@prisma-next/sql-contract/canonicalization-hooks';
@@ -39,17 +44,17 @@ import type {
39
44
  SqlExecuteRequest,
40
45
  } from '@prisma-next/sql-relational-core/ast';
41
46
  import { defaultIndexName } from '@prisma-next/sql-schema-ir/naming';
42
- import type { SqlSchemaIR, SqlTableIR } from '@prisma-next/sql-schema-ir/types';
47
+ import type { SqlSchemaIRNode, SqlTableIR } from '@prisma-next/sql-schema-ir/types';
48
+ import { blindCast } from '@prisma-next/utils/casts';
43
49
  import { ifDefined } from '@prisma-next/utils/defined';
44
50
  import type { SqlControlAdapter } from './control-adapter';
45
51
  import { SqlContractSerializer } from './ir/sql-contract-serializer';
52
+ import type { DiffDatabaseSchemaInput } from './migrations/schema-differ';
46
53
  import type {
47
54
  SqlControlAdapterDescriptor,
48
55
  SqlControlExtensionDescriptor,
49
56
  } from './migrations/types';
50
57
  import { sqlOperationsToPreview } from './operation-preview';
51
- import { sqlSchemaIrToPslAst } from './psl-contract-infer/sql-schema-ir-to-psl-ast';
52
- import { verifySqlSchema } from './schema-verify/verify-sql-schema';
53
58
  import { collectSupportedCodecTypeIds } from './verify';
54
59
 
55
60
  function extractCodecTypeIdsFromContract(contract: unknown): readonly string[] {
@@ -186,9 +191,9 @@ interface SqlFamilyInstanceState {
186
191
  }
187
192
 
188
193
  export interface SqlControlFamilyInstance
189
- extends ControlFamilyInstance<'sql', SqlSchemaIR>,
190
- SchemaViewCapable<SqlSchemaIR>,
191
- PslContractInferCapable<SqlSchemaIR>,
194
+ extends ControlFamilyInstance<'sql', SqlSchemaIRNode>,
195
+ SchemaViewCapable<SqlSchemaIRNode>,
196
+ PslContractInferCapable<SqlSchemaIRNode>,
192
197
  OperationPreviewCapable,
193
198
  SqlFamilyInstanceState {
194
199
  /**
@@ -210,18 +215,17 @@ export interface SqlControlFamilyInstance
210
215
  }): Promise<VerifyDatabaseResult>;
211
216
 
212
217
  /**
213
- * Verify a contract against an already-introspected schema slice.
218
+ * Verify a contract against an already-introspected schema.
214
219
  *
215
220
  * Callers that need to verify against the live database compose
216
221
  * `introspect({ driver })` + `verifySchema({ contract, schema, ... })`.
217
- * The aggregate verifier projects each member's claimed slice via
218
- * `projectSchemaToSpace` and hands the projected slice inthis
219
- * keeps per-member verification from surfacing sibling-space tables
220
- * as `extras`.
222
+ * The aggregate verifier hands in the full introspected schema and scopes
223
+ * the returned result to each member's contract space afterwards so
224
+ * sibling-space tables never survive as `extras`.
221
225
  */
222
226
  verifySchema(options: {
223
227
  readonly contract: unknown;
224
- readonly schema: SqlSchemaIR;
228
+ readonly schema: SqlSchemaIRNode;
225
229
  readonly strict: boolean;
226
230
  readonly frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<'sql', string>>;
227
231
  }): VerifyDatabaseSchemaResult;
@@ -236,9 +240,9 @@ export interface SqlControlFamilyInstance
236
240
  introspect(options: {
237
241
  readonly driver: SqlControlDriverInstance<string>;
238
242
  readonly contract?: unknown;
239
- }): Promise<SqlSchemaIR>;
243
+ }): Promise<SqlSchemaIRNode>;
240
244
 
241
- inferPslContract(schemaIR: SqlSchemaIR): PslDocumentAst;
245
+ inferPslContract(schemaIR: SqlSchemaIRNode): PslDocumentAst;
242
246
 
243
247
  lowerAst(
244
248
  ast: AnyQueryAst | DdlNode,
@@ -294,8 +298,6 @@ export interface SqlControlFamilyInstance
294
298
 
295
299
  bootstrapControlTableQueries(): readonly DdlNode[];
296
300
 
297
- bootstrapSignMarkerQueries(): readonly DdlNode[];
298
-
299
301
  toOperationPreview(operations: readonly MigrationPlanOperation[]): OperationPreview;
300
302
  }
301
303
 
@@ -523,12 +525,49 @@ export function createSqlFamilyInstance<TTargetId extends string>(
523
525
 
524
526
  const targetSerializer = (
525
527
  target as unknown as {
526
- contractSerializer?: { deserializeContract(json: unknown): Contract<SqlStorage> };
528
+ contractSerializer?: {
529
+ deserializeContract(json: unknown): Contract<SqlStorage>;
530
+ serializeContract(contract: Contract<SqlStorage>): unknown;
531
+ };
527
532
  }
528
533
  ).contractSerializer;
529
- const deserializeWithTargetSerializer = (contractJson: unknown): Contract<SqlStorage> => {
534
+ // Database→PSL inference is target logic (it owns the dialect type/default
535
+ // maps and walks its own schema tree), so it is read off the descriptor like
536
+ // `contractSerializer`. Absent for targets without `contract infer` (Mongo).
537
+ const targetInferPslContract = blindCast<
538
+ { readonly inferPslContract?: (schema: SqlSchemaIRNode) => PslDocumentAst },
539
+ 'reading the optional target-descriptor inferPslContract hook'
540
+ >(target).inferPslContract;
541
+ // The combined database-schema verify is a required target-descriptor
542
+ // operation: every SQL target provides it, wrapping the same comparison
543
+ // `diffDatabaseSchema` runs in the verify envelope plus the pass/warn/fail
544
+ // tree the CLI renders. Read it off the descriptor like the other
545
+ // target-owned hooks.
546
+ const verifyDatabaseSchema = blindCast<
547
+ {
548
+ readonly verifyDatabaseSchema?: (
549
+ input: DiffDatabaseSchemaInput,
550
+ ) => VerifyDatabaseSchemaResult;
551
+ },
552
+ 'reading the required target-descriptor verifyDatabaseSchema hook'
553
+ >(target).verifyDatabaseSchema;
554
+ if (!verifyDatabaseSchema) {
555
+ throw new Error(
556
+ `SQL target "${target.targetId}" is missing the required verifyDatabaseSchema descriptor operation`,
557
+ );
558
+ }
559
+ const deserializeWithTargetSerializer = (contractOrJson: unknown): Contract<SqlStorage> => {
530
560
  const serializer = targetSerializer ?? new SqlContractSerializer();
531
- return serializer.deserializeContract(contractJson) as Contract<SqlStorage>;
561
+ const json =
562
+ targetSerializer !== undefined && !isPlainRecord(contractOrJson)
563
+ ? targetSerializer.serializeContract(
564
+ blindCast<
565
+ Contract<SqlStorage>,
566
+ 'isPlainRecord returned false, so contractOrJson is a class instance, not raw JSON'
567
+ >(contractOrJson),
568
+ )
569
+ : contractOrJson;
570
+ return serializer.deserializeContract(json) as Contract<SqlStorage>;
532
571
  };
533
572
 
534
573
  return {
@@ -669,21 +708,47 @@ export function createSqlFamilyInstance<TTargetId extends string>(
669
708
 
670
709
  verifySchema(options: {
671
710
  readonly contract: unknown;
672
- readonly schema: SqlSchemaIR;
711
+ readonly schema: SqlSchemaIRNode;
673
712
  readonly strict: boolean;
674
713
  readonly frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<'sql', string>>;
675
714
  }): VerifyDatabaseSchemaResult {
676
715
  const contract = deserializeWithTargetSerializer(options.contract) as Contract<SqlStorage>;
677
- const controlAdapter = getControlAdapter();
678
- return verifySqlSchema({
716
+ // Verify is a thin consumer of the target's black-box comparison: it
717
+ // introspects the actual schema (already in `options.schema`), calls the
718
+ // target's required `verifyDatabaseSchema`, and rejects when a surviving
719
+ // issue is a failure. It composes no diffing itself and is blind to how
720
+ // the comparison works.
721
+ const sqlResult = verifyDatabaseSchema({
679
722
  contract,
680
723
  schema: options.schema,
681
724
  strict: options.strict,
682
725
  typeMetadataRegistry,
683
726
  frameworkComponents: options.frameworkComponents,
684
- ...ifDefined('normalizeDefault', controlAdapter.normalizeDefault),
685
- ...ifDefined('normalizeNativeType', controlAdapter.normalizeNativeType),
686
727
  });
728
+ // Control-policy suppression of the structural (e.g. RLS policy) diff
729
+ // issues is a verify-side post-step — the combined diff returns them
730
+ // ownership-filtered, and a suppressed control policy drops them here.
731
+ const schemaDiffIssues = filterSchemaDiffIssues(
732
+ sqlResult.schema.schemaDiffIssues,
733
+ contract.defaultControlPolicy,
734
+ );
735
+ const relationalFails = sqlResult.schema.counts.fail;
736
+ if (schemaDiffIssues.length === 0) {
737
+ if (schemaDiffIssues === sqlResult.schema.schemaDiffIssues) return sqlResult;
738
+ return { ...sqlResult, schema: { ...sqlResult.schema, schemaDiffIssues } };
739
+ }
740
+ const totalFails = relationalFails + schemaDiffIssues.length;
741
+ return {
742
+ ...sqlResult,
743
+ ok: false,
744
+ code: sqlResult.code ?? 'PN-RUN-3010',
745
+ summary: `Database schema does not satisfy contract (${totalFails} failure${totalFails === 1 ? '' : 's'})`,
746
+ schema: {
747
+ ...sqlResult.schema,
748
+ schemaDiffIssues,
749
+ counts: { ...sqlResult.schema.counts, fail: totalFails },
750
+ },
751
+ };
687
752
  },
688
753
  async sign(options: {
689
754
  readonly driver: SqlControlDriverInstance<string>;
@@ -848,12 +913,17 @@ export function createSqlFamilyInstance<TTargetId extends string>(
848
913
  async introspect(options: {
849
914
  readonly driver: SqlControlDriverInstance<string>;
850
915
  readonly contract?: unknown;
851
- }): Promise<SqlSchemaIR> {
916
+ }): Promise<SqlSchemaIRNode> {
852
917
  return getControlAdapter().introspect(options.driver, options.contract);
853
918
  },
854
919
 
855
- inferPslContract(schemaIR: SqlSchemaIR): PslDocumentAst {
856
- return sqlSchemaIrToPslAst(schemaIR);
920
+ inferPslContract(schemaIR: SqlSchemaIRNode): PslDocumentAst {
921
+ if (!targetInferPslContract) {
922
+ throw new Error(
923
+ `Target "${target.targetId}" does not support contract infer (no inferPslContract on its descriptor).`,
924
+ );
925
+ }
926
+ return targetInferPslContract(schemaIR);
857
927
  },
858
928
 
859
929
  lowerAst(
@@ -867,17 +937,52 @@ export function createSqlFamilyInstance<TTargetId extends string>(
867
937
  return getControlAdapter().bootstrapControlTableQueries();
868
938
  },
869
939
 
870
- bootstrapSignMarkerQueries(): readonly DdlNode[] {
871
- return getControlAdapter().bootstrapSignMarkerQueries();
872
- },
873
-
874
940
  toOperationPreview(operations: readonly MigrationPlanOperation[]): OperationPreview {
875
941
  return sqlOperationsToPreview(operations);
876
942
  },
877
943
 
878
- toSchemaView(schema: SqlSchemaIR): CoreSchemaView {
879
- const tableNodes: readonly SchemaTreeNode[] = Object.entries(schema.tables).map(
880
- ([tableName, table]: [string, SqlTableIR]) => {
944
+ toSchemaView(schema: SqlSchemaIRNode): CoreSchemaView {
945
+ // Walk the schema-IR tree's own structure (root → namespaces → tables)
946
+ // into one flat list of table nodes. A root that exposes a `namespaces`
947
+ // record (Postgres) contributes each namespace's tables; a flat root
948
+ // (SQLite) is its own single namespace. The single-schema common case
949
+ // renders the same table-level view as today — no synthetic namespace
950
+ // level.
951
+ const root = blindCast<
952
+ {
953
+ readonly namespaces?: Readonly<
954
+ Record<string, { readonly tables: Record<string, SqlTableIR> }>
955
+ >;
956
+ readonly tables?: Record<string, SqlTableIR>;
957
+ },
958
+ 'structural read of the schema-IR tree own namespaces/tables records'
959
+ >(schema);
960
+ // A multi-namespace root qualifies every table's display name with its
961
+ // namespace key, so same-named tables in different namespaces (e.g.
962
+ // public.thing and auth.thing) render distinct ids and labels. The
963
+ // single-namespace case (and a flat SQLite root) keeps today's bare
964
+ // names. Synthesized constraint/index fallback names keep the bare table
965
+ // name — that is the name the database derives them from.
966
+ const namespaceEntries: ReadonlyArray<[string | undefined, Record<string, SqlTableIR>]> =
967
+ root.namespaces !== undefined
968
+ ? Object.entries(root.namespaces).map(
969
+ ([namespaceKey, namespace]): [string, Record<string, SqlTableIR>] => [
970
+ namespaceKey,
971
+ namespace.tables,
972
+ ],
973
+ )
974
+ : [[undefined, root.tables ?? {}]];
975
+ const qualify = namespaceEntries.length > 1;
976
+ const tableEntries: ReadonlyArray<[string, string, SqlTableIR]> = namespaceEntries.flatMap(
977
+ ([namespaceKey, tables]) =>
978
+ Object.entries(tables).map(([tableName, table]): [string, string, SqlTableIR] => [
979
+ qualify && namespaceKey !== undefined ? `${namespaceKey}.${tableName}` : tableName,
980
+ tableName,
981
+ table,
982
+ ]),
983
+ );
984
+ const tableNodes: readonly SchemaTreeNode[] = tableEntries.map(
985
+ ([displayName, tableName, table]: [string, string, SqlTableIR]) => {
881
986
  const children: SchemaTreeNode[] = [];
882
987
 
883
988
  const columnNodes: SchemaTreeNode[] = [];
@@ -888,7 +993,7 @@ export function createSqlFamilyInstance<TTargetId extends string>(
888
993
  columnNodes.push(
889
994
  new SchemaTreeNode({
890
995
  kind: 'field',
891
- id: `column-${tableName}-${columnName}`,
996
+ id: `column-${displayName}-${columnName}`,
892
997
  label,
893
998
  meta: {
894
999
  nativeType: column.nativeType,
@@ -903,7 +1008,7 @@ export function createSqlFamilyInstance<TTargetId extends string>(
903
1008
  children.push(
904
1009
  new SchemaTreeNode({
905
1010
  kind: 'collection',
906
- id: `columns-${tableName}`,
1011
+ id: `columns-${displayName}`,
907
1012
  label: 'columns',
908
1013
  children: columnNodes,
909
1014
  }),
@@ -915,7 +1020,7 @@ export function createSqlFamilyInstance<TTargetId extends string>(
915
1020
  children.push(
916
1021
  new SchemaTreeNode({
917
1022
  kind: 'index',
918
- id: `primary-key-${tableName}`,
1023
+ id: `primary-key-${displayName}`,
919
1024
  label: `primary key: ${pkColumns}`,
920
1025
  meta: {
921
1026
  columns: table.primaryKey.columns,
@@ -931,7 +1036,7 @@ export function createSqlFamilyInstance<TTargetId extends string>(
931
1036
  children.push(
932
1037
  new SchemaTreeNode({
933
1038
  kind: 'index',
934
- id: `unique-${tableName}-${name}`,
1039
+ id: `unique-${displayName}-${name}`,
935
1040
  label,
936
1041
  meta: {
937
1042
  columns: unique.columns,
@@ -947,7 +1052,7 @@ export function createSqlFamilyInstance<TTargetId extends string>(
947
1052
  children.push(
948
1053
  new SchemaTreeNode({
949
1054
  kind: 'index',
950
- id: `index-${tableName}-${name}`,
1055
+ id: `index-${displayName}-${name}`,
951
1056
  label,
952
1057
  meta: {
953
1058
  columns: index.columns,
@@ -975,8 +1080,8 @@ export function createSqlFamilyInstance<TTargetId extends string>(
975
1080
 
976
1081
  return new SchemaTreeNode({
977
1082
  kind: 'entity',
978
- id: `table-${tableName}`,
979
- label: `table ${tableName}`,
1083
+ id: `table-${displayName}`,
1084
+ label: `table ${displayName}`,
980
1085
  ...(Object.keys(tableMeta).length > 0 ? { meta: tableMeta } : {}),
981
1086
  ...(children.length > 0 ? { children } : {}),
982
1087
  });
@@ -994,3 +1099,31 @@ export function createSqlFamilyInstance<TTargetId extends string>(
994
1099
  },
995
1100
  };
996
1101
  }
1102
+
1103
+ /**
1104
+ * Filters the structural schema-diff issues (from `diffDatabaseSchema`) through
1105
+ * the contract's `defaultControlPolicy`. Issues whose outcome maps to a suppressed
1106
+ * category under the effective policy are removed. This mirrors the control-policy
1107
+ * filtering applied by `verifySqlSchema` for table/column-level findings.
1108
+ *
1109
+ * Outcome → category mapping:
1110
+ * - `'extra'` → `'extraAuxiliary'` (an extra auxiliary entity, e.g. an RLS policy)
1111
+ * - `'missing'` → `'declaredMissing'`
1112
+ * - `'mismatch'` → `'declaredIncompatible'`
1113
+ */
1114
+ export function filterSchemaDiffIssues(
1115
+ issues: readonly SchemaDiffIssue[],
1116
+ defaultControlPolicy: ControlPolicy | undefined,
1117
+ ): readonly SchemaDiffIssue[] {
1118
+ if (issues.length === 0) return issues;
1119
+ const policy = effectiveControlPolicy(undefined, defaultControlPolicy);
1120
+ return issues.filter((issue) => {
1121
+ const category =
1122
+ issue.outcome === 'extra'
1123
+ ? ('extraAuxiliary' as const)
1124
+ : issue.outcome === 'missing'
1125
+ ? ('declaredMissing' as const)
1126
+ : ('declaredIncompatible' as const);
1127
+ return dispositionForCategory(policy, category) !== 'suppress';
1128
+ });
1129
+ }