@suss/ir-core 0.5.10 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -7,7 +7,7 @@ Primitives shared across suss's intermediate representations: the pieces every I
7
7
  The types that any suss IR is built from:
8
8
 
9
9
  - `TypeShape`: the structure of a value, for body / payload / field comparison.
10
- - `BoundaryBinding` + the `Semantics` variants (rest, function-call, graphql-resolver, graphql-operation, runtime-config, storage-relational, message-bus), plus the eight blessed binding constructors (`restBinding`, `functionCallBinding`, …).
10
+ - `BoundaryBinding` + the `Semantics` variants (rest, function-call, graphql-resolver, graphql-operation, runtime-config, storage, message-bus), plus the eight blessed binding constructors (`restBinding`, `functionCallBinding`, …).
11
11
  - `SourceLocation` and `Confidence` (`source` + `level`).
12
12
 
13
13
  ```ts
@@ -414,29 +414,43 @@ var runtimeConfigSemantics = defineBoundarySemantics({
414
414
  }
415
415
  });
416
416
 
417
- // src/semantics/storageRelational.ts
417
+ // src/semantics/storage.ts
418
418
  import { z as z8 } from "zod";
419
- var StorageRelationalSemanticsSchema = z8.object({
420
- name: z8.literal("storage-relational"),
421
- storageSystem: z8.enum(["postgres", "mysql", "sqlite"]),
419
+ var StorageSemanticsSchema = z8.object({
420
+ name: z8.literal("storage"),
422
421
  /**
423
- * The ORM or driver scope. A single-database setup uses `"default"`,
424
- * and a monorepo with several schemas gives each one its own value.
422
+ * Which store this is: postgres, mysql, sqlite, dynamodb. Two
423
+ * products' containers can share a name, so this keeps them apart,
424
+ * and it is what a finding message calls the store.
425
+ */
426
+ storageSystem: z8.string(),
427
+ /**
428
+ * The ORM, schema, or deployment scope. A single-database setup uses
429
+ * `"default"`, and a monorepo with several schemas gives each one its
430
+ * own value.
425
431
  */
426
432
  scope: z8.string(),
427
433
  /**
428
- * The table or model name as the schema declares it, or null when
429
- * the source states one this reader could not settle. A null table
430
- * pairs with nothing, rather than with whatever its source text
431
- * happens to spell.
434
+ * The table, bucket, collection, or index, as the source declares
435
+ * it, or null when the source states one this reader could not
436
+ * settle. A null container pairs with nothing, rather than with
437
+ * whatever its source text happens to spell.
438
+ */
439
+ container: z8.string().nullable(),
440
+ /**
441
+ * A secondary way into the container, a DynamoDB global secondary
442
+ * index or an Elasticsearch alias, each with its own key fields.
443
+ * Null means the container's own primary way in. A query through an
444
+ * index and a query through the table are different accesses, so
445
+ * they pair separately.
432
446
  */
433
- table: z8.string().nullable()
447
+ accessPath: z8.string().nullable()
434
448
  });
435
- var storageRelationalSemantics = defineBoundarySemantics({
436
- name: "storage-relational",
437
- schema: StorageRelationalSemanticsSchema,
449
+ var storageSemantics = defineBoundarySemantics({
450
+ name: "storage",
451
+ schema: StorageSemanticsSchema,
438
452
  behavior: {
439
- /** A query returns rows, not a status and a body. */
453
+ /** A query returns rows or items, not a status and a body. */
440
454
  exchangesHttpResponses: false,
441
455
  reportsUnpairedItself: false,
442
456
  identityKey: () => null
@@ -450,7 +464,7 @@ var SemanticsSchema = z9.discriminatedUnion("name", [
450
464
  graphqlResolverSemantics.schema,
451
465
  graphqlOperationSemantics.schema,
452
466
  runtimeConfigSemantics.schema,
453
- storageRelationalSemantics.schema,
467
+ storageSemantics.schema,
454
468
  messageBusSemantics.schema
455
469
  ]);
456
470
  var DEFINITIONS = [
@@ -459,7 +473,7 @@ var DEFINITIONS = [
459
473
  graphqlResolverSemantics,
460
474
  graphqlOperationSemantics,
461
475
  runtimeConfigSemantics,
462
- storageRelationalSemantics,
476
+ storageSemantics,
463
477
  messageBusSemantics
464
478
  ];
465
479
  var BY_NAME = new Map(
@@ -614,7 +628,7 @@ export {
614
628
  DeployableUnitSchema,
615
629
  ecsContainerInstanceName,
616
630
  RuntimeConfigSemanticsSchema,
617
- StorageRelationalSemanticsSchema,
631
+ StorageSemanticsSchema,
618
632
  SemanticsSchema,
619
633
  behaviorOf,
620
634
  allBehaviors,
package/dist/index.cjs CHANGED
@@ -34,7 +34,7 @@ __export(index_exports, {
34
34
  RuntimeConfigSemanticsSchema: () => RuntimeConfigSemanticsSchema,
35
35
  SemanticsSchema: () => SemanticsSchema,
36
36
  SourceLocationSchema: () => SourceLocationSchema,
37
- StorageRelationalSemanticsSchema: () => StorageRelationalSemanticsSchema,
37
+ StorageSemanticsSchema: () => StorageSemanticsSchema,
38
38
  SuppressionFileSchema: () => SuppressionFileSchema,
39
39
  SuppressionRuleSchema: () => SuppressionRuleSchema,
40
40
  TypeShapeSchema: () => TypeShapeSchema,
@@ -59,9 +59,13 @@ __export(index_exports, {
59
59
  gqlIdentityKey: () => gqlIdentityKey,
60
60
  graphqlOperationBinding: () => graphqlOperationBinding,
61
61
  graphqlResolverBinding: () => graphqlResolverBinding,
62
+ hasNameHole: () => hasNameHole,
62
63
  isGraphqlOperationBinding: () => isGraphqlOperationBinding,
63
64
  messageBusBinding: () => messageBusBinding,
64
65
  methodsAgree: () => methodsAgree,
66
+ namePatternFromSub: () => namePatternFromSub,
67
+ namePatternKey: () => namePatternKey,
68
+ namesAgree: () => namesAgree,
65
69
  normalizePath: () => normalizePath,
66
70
  normalizeRuleBoundary: () => normalizeRuleBoundary,
67
71
  packageExportBinding: () => packageExportBinding,
@@ -74,7 +78,7 @@ __export(index_exports, {
74
78
  runtimeConfigBinding: () => runtimeConfigBinding,
75
79
  semanticsAgree: () => semanticsAgree,
76
80
  servesRequest: () => servesRequest,
77
- storageRelationalBinding: () => storageRelationalBinding,
81
+ storageBinding: () => storageBinding,
78
82
  typeDefinitionKey: () => typeDefinitionKey,
79
83
  validateRule: () => validateRule,
80
84
  withDefinitionsInlined: () => withDefinitionsInlined
@@ -497,29 +501,43 @@ var runtimeConfigSemantics = defineBoundarySemantics({
497
501
  }
498
502
  });
499
503
 
500
- // src/semantics/storageRelational.ts
504
+ // src/semantics/storage.ts
501
505
  var import_zod8 = require("zod");
502
- var StorageRelationalSemanticsSchema = import_zod8.z.object({
503
- name: import_zod8.z.literal("storage-relational"),
504
- storageSystem: import_zod8.z.enum(["postgres", "mysql", "sqlite"]),
506
+ var StorageSemanticsSchema = import_zod8.z.object({
507
+ name: import_zod8.z.literal("storage"),
505
508
  /**
506
- * The ORM or driver scope. A single-database setup uses `"default"`,
507
- * and a monorepo with several schemas gives each one its own value.
509
+ * Which store this is: postgres, mysql, sqlite, dynamodb. Two
510
+ * products' containers can share a name, so this keeps them apart,
511
+ * and it is what a finding message calls the store.
512
+ */
513
+ storageSystem: import_zod8.z.string(),
514
+ /**
515
+ * The ORM, schema, or deployment scope. A single-database setup uses
516
+ * `"default"`, and a monorepo with several schemas gives each one its
517
+ * own value.
508
518
  */
509
519
  scope: import_zod8.z.string(),
510
520
  /**
511
- * The table or model name as the schema declares it, or null when
512
- * the source states one this reader could not settle. A null table
513
- * pairs with nothing, rather than with whatever its source text
514
- * happens to spell.
521
+ * The table, bucket, collection, or index, as the source declares
522
+ * it, or null when the source states one this reader could not
523
+ * settle. A null container pairs with nothing, rather than with
524
+ * whatever its source text happens to spell.
525
+ */
526
+ container: import_zod8.z.string().nullable(),
527
+ /**
528
+ * A secondary way into the container, a DynamoDB global secondary
529
+ * index or an Elasticsearch alias, each with its own key fields.
530
+ * Null means the container's own primary way in. A query through an
531
+ * index and a query through the table are different accesses, so
532
+ * they pair separately.
515
533
  */
516
- table: import_zod8.z.string().nullable()
534
+ accessPath: import_zod8.z.string().nullable()
517
535
  });
518
- var storageRelationalSemantics = defineBoundarySemantics({
519
- name: "storage-relational",
520
- schema: StorageRelationalSemanticsSchema,
536
+ var storageSemantics = defineBoundarySemantics({
537
+ name: "storage",
538
+ schema: StorageSemanticsSchema,
521
539
  behavior: {
522
- /** A query returns rows, not a status and a body. */
540
+ /** A query returns rows or items, not a status and a body. */
523
541
  exchangesHttpResponses: false,
524
542
  reportsUnpairedItself: false,
525
543
  identityKey: () => null
@@ -533,7 +551,7 @@ var SemanticsSchema = import_zod9.z.discriminatedUnion("name", [
533
551
  graphqlResolverSemantics.schema,
534
552
  graphqlOperationSemantics.schema,
535
553
  runtimeConfigSemantics.schema,
536
- storageRelationalSemantics.schema,
554
+ storageSemantics.schema,
537
555
  messageBusSemantics.schema
538
556
  ]);
539
557
  var DEFINITIONS = [
@@ -542,7 +560,7 @@ var DEFINITIONS = [
542
560
  graphqlResolverSemantics,
543
561
  graphqlOperationSemantics,
544
562
  runtimeConfigSemantics,
545
- storageRelationalSemantics,
563
+ storageSemantics,
546
564
  messageBusSemantics
547
565
  ];
548
566
  var BY_NAME = new Map(
@@ -749,6 +767,53 @@ function dispatchByType(table, value) {
749
767
  return handler(value);
750
768
  }
751
769
 
770
+ // src/namePattern.ts
771
+ var HOLE = /\{[^}]*\}/g;
772
+ var SUB_TOKEN = /\$\{([^}]*)\}/g;
773
+ var SUB_ESCAPE = /\$\{!/;
774
+ function namePatternFromSub(value) {
775
+ if (Array.isArray(value)) {
776
+ return typeof value[0] === "string" ? namePatternFromSub(value[0]) : null;
777
+ }
778
+ if (typeof value !== "string") {
779
+ return null;
780
+ }
781
+ if (SUB_ESCAPE.test(value)) {
782
+ return null;
783
+ }
784
+ return value.replace(SUB_TOKEN, (_whole, inner) => `{${inner}}`);
785
+ }
786
+ function hasNameHole(name) {
787
+ HOLE.lastIndex = 0;
788
+ return HOLE.test(name);
789
+ }
790
+ function namePatternKey(name) {
791
+ return name.replace(HOLE, "{}");
792
+ }
793
+ function admits(pattern, name) {
794
+ const source = pattern.split(/(\{[^}]*\})/).map(
795
+ (part) => part.startsWith("{") && part.endsWith("}") ? ".+" : part.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")
796
+ ).join("");
797
+ return new RegExp(`^${source}$`).test(name);
798
+ }
799
+ function namesAgree(a, b) {
800
+ if (a === b) {
801
+ return true;
802
+ }
803
+ const aHasHole = hasNameHole(a);
804
+ const bHasHole = hasNameHole(b);
805
+ if (aHasHole && bHasHole) {
806
+ return namePatternKey(a) === namePatternKey(b);
807
+ }
808
+ if (aHasHole) {
809
+ return admits(a, b);
810
+ }
811
+ if (bHasHole) {
812
+ return admits(b, a);
813
+ }
814
+ return false;
815
+ }
816
+
752
817
  // src/suppressions.ts
753
818
  var import_zod11 = require("zod");
754
819
  var SuppressionSideSchema = import_zod11.z.object({
@@ -1089,14 +1154,15 @@ function runtimeConfigBinding(opts) {
1089
1154
  recognition: opts.recognition
1090
1155
  };
1091
1156
  }
1092
- function storageRelationalBinding(opts) {
1157
+ function storageBinding(opts) {
1093
1158
  return {
1094
- transport: opts.storageSystem,
1159
+ transport: opts.transport ?? opts.storageSystem,
1095
1160
  semantics: {
1096
- name: "storage-relational",
1161
+ name: "storage",
1097
1162
  storageSystem: opts.storageSystem,
1098
1163
  scope: opts.scope,
1099
- table: namedOrNull(opts.table, "storage table")
1164
+ container: namedOrNull(opts.container, "storage container"),
1165
+ accessPath: opts.accessPath ?? null
1100
1166
  },
1101
1167
  recognition: opts.recognition
1102
1168
  };
@@ -1128,7 +1194,7 @@ function messageBusBinding(opts) {
1128
1194
  RuntimeConfigSemanticsSchema,
1129
1195
  SemanticsSchema,
1130
1196
  SourceLocationSchema,
1131
- StorageRelationalSemanticsSchema,
1197
+ StorageSemanticsSchema,
1132
1198
  SuppressionFileSchema,
1133
1199
  SuppressionRuleSchema,
1134
1200
  TypeShapeSchema,
@@ -1153,9 +1219,13 @@ function messageBusBinding(opts) {
1153
1219
  gqlIdentityKey,
1154
1220
  graphqlOperationBinding,
1155
1221
  graphqlResolverBinding,
1222
+ hasNameHole,
1156
1223
  isGraphqlOperationBinding,
1157
1224
  messageBusBinding,
1158
1225
  methodsAgree,
1226
+ namePatternFromSub,
1227
+ namePatternKey,
1228
+ namesAgree,
1159
1229
  normalizePath,
1160
1230
  normalizeRuleBoundary,
1161
1231
  packageExportBinding,
@@ -1168,7 +1238,7 @@ function messageBusBinding(opts) {
1168
1238
  runtimeConfigBinding,
1169
1239
  semanticsAgree,
1170
1240
  servesRequest,
1171
- storageRelationalBinding,
1241
+ storageBinding,
1172
1242
  typeDefinitionKey,
1173
1243
  validateRule,
1174
1244
  withDefinitionsInlined
package/dist/index.d.cts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { z } from 'zod';
2
- import { T as TypeShape, M as MessageBusSemantics, S as Semantics, B as BoundaryBindingSchema, C as ConfidenceInfoSchema, a as ConfidenceLevelSchema, b as ConfidenceSourceSchema, c as CorroborationSchema, d as SourceLocationSchema, e as MessageBusTechnology } from './schemas-N9GyG0Sn.cjs';
3
- export { D as DeployableUnit, f as DeployableUnitSchema, F as FunctionCallSemantics, g as FunctionCallSemanticsSchema, G as GraphqlOperationSemantics, h as GraphqlOperationSemanticsSchema, i as GraphqlResolverSemantics, j as GraphqlResolverSemanticsSchema, k as MessageBusSemanticsSchema, R as RestSemantics, l as RestSemanticsSchema, m as RuntimeConfigSemantics, n as RuntimeConfigSemanticsSchema, o as SemanticsSchema, p as StorageRelationalSemantics, q as StorageRelationalSemanticsSchema, r as TypeShapeSchema, s as ecsContainerInstanceName, t as methodsAgree, u as normalizePath, v as routePathAdmits, w as typeDefinitionKey, x as withDefinitionsInlined } from './schemas-N9GyG0Sn.cjs';
2
+ import { T as TypeShape, M as MessageBusSemantics, S as Semantics, B as BoundaryBindingSchema, C as ConfidenceInfoSchema, a as ConfidenceLevelSchema, b as ConfidenceSourceSchema, c as CorroborationSchema, d as SourceLocationSchema, e as MessageBusTechnology } from './schemas-D6hKT-zV.cjs';
3
+ export { D as DeployableUnit, f as DeployableUnitSchema, F as FunctionCallSemantics, g as FunctionCallSemanticsSchema, G as GraphqlOperationSemantics, h as GraphqlOperationSemanticsSchema, i as GraphqlResolverSemantics, j as GraphqlResolverSemanticsSchema, k as MessageBusSemanticsSchema, R as RestSemantics, l as RestSemanticsSchema, m as RuntimeConfigSemantics, n as RuntimeConfigSemanticsSchema, o as SemanticsSchema, p as StorageSemantics, q as StorageSemanticsSchema, r as TypeShapeSchema, s as ecsContainerInstanceName, t as methodsAgree, u as normalizePath, v as routePathAdmits, w as typeDefinitionKey, x as withDefinitionsInlined } from './schemas-D6hKT-zV.cjs';
4
4
 
5
5
  /**
6
6
  * Comparing two TypeShapes structurally.
@@ -262,6 +262,42 @@ declare function dispatchByType<T extends {
262
262
  type: string;
263
263
  }, R>(table: DispatchTable<T, R>, value: T): R;
264
264
 
265
+ /**
266
+ * A name two sides state with a hole in it.
267
+ *
268
+ * A deployed resource is often called something built at deploy time:
269
+ * a template writes `!Sub "${StageName}-orders-v1"` and the code writes
270
+ * `` `${stage}-orders-v1` ``. Neither side states a string, both agree
271
+ * about the fixed text, and each spells the parameter its own way. So a
272
+ * name is written here as fixed text with `{}` holes, the way a REST
273
+ * path is written with `{id}`, and two names agree when their fixed
274
+ * parts line up.
275
+ *
276
+ * A hole covers a whole parameter rather than one path segment,
277
+ * because a name has no separator that every project agrees on.
278
+ */
279
+ /**
280
+ * The name a CloudFormation `Fn::Sub` value states. The array form
281
+ * takes its template from the first element, and the variable map only
282
+ * says where a substitution comes from, which does not change the name.
283
+ */
284
+ declare function namePatternFromSub(value: unknown): string | null;
285
+ /** Whether a name has anything a source left for deploy time to fill. */
286
+ declare function hasNameHole(name: string): boolean;
287
+ /**
288
+ * The form two patterns are compared in: every hole reduced to the same
289
+ * token, since the two sides pick their own name for the parameter.
290
+ */
291
+ declare function namePatternKey(name: string): string;
292
+ /**
293
+ * Whether two names are the same name. Two patterns agree when their
294
+ * fixed parts line up, since a hole on one side meets a hole on the
295
+ * other. A pattern and a concrete name agree when the fixed parts are
296
+ * where the pattern says they are, which is what happens when one side
297
+ * hardcoded what the other parameterized.
298
+ */
299
+ declare function namesAgree(a: string, b: string): boolean;
300
+
265
301
  /**
266
302
  * The suppression pipeline, over the smallest finding both checkers share.
267
303
  *
@@ -475,17 +511,21 @@ declare function runtimeConfigBinding(opts: {
475
511
  instanceName: string;
476
512
  }): BoundaryBinding;
477
513
  /**
478
- * Build a storage-relational binding, the provider side of a relational
479
- * storage table. Transport stores the `storageSystem` value, which keeps
480
- * the layering informative without needing a separate wire-protocol
481
- * taxonomy.
514
+ * Build a storage binding, the side of a store that both a schema
515
+ * reader and a call site can spell. `transport` defaults to the store's
516
+ * own name, which is right for a database whose product and wire
517
+ * protocol are the same word, and a store reached over an SDK passes
518
+ * its wire instead.
482
519
  */
483
- declare function storageRelationalBinding(opts: {
520
+ declare function storageBinding(opts: {
484
521
  recognition: string;
485
- storageSystem: "postgres" | "mysql" | "sqlite";
522
+ storageSystem: string;
523
+ transport?: string;
486
524
  scope: string;
487
- /** Null when the source names a table this reader could not settle. */
488
- table: string | null;
525
+ /** Null when the source gives a container this reader could not settle. */
526
+ container: string | null;
527
+ /** A secondary index or alias, or null for the container's own primary key. */
528
+ accessPath?: string | null;
489
529
  }): BoundaryBinding;
490
530
  /**
491
531
  * Build a message-bus binding, the boundary between a producer that
@@ -498,4 +538,4 @@ declare function messageBusBinding(opts: {
498
538
  channel: string | null;
499
539
  }): BoundaryBinding;
500
540
 
501
- export { type BoundaryBehavior, type BoundaryBinding, BoundaryBindingSchema, type BoundarySemanticsDefinition, type BusIdentityKey, type Channel, type ConfidenceInfo, ConfidenceInfoSchema, type ConfidenceLevel, ConfidenceLevelSchema, type ConfidenceSource, ConfidenceSourceSchema, type Corroboration, CorroborationSchema, type DispatchTable, type FindingSuppression, type FnIdentityKey, type GqlIdentityKey, type MatchResult, MessageBusSemantics, MessageBusTechnology, type ParsedChannel, Semantics, type SourceLocation, SourceLocationSchema, type SuppressableSeverity, type SuppressibleFinding, type SuppressionFile, SuppressionFileSchema, type SuppressionRule, SuppressionRuleSchema, TypeShape, applySuppressionsToFindings, bodyShapesMatch, boundaryKey, boundaryLabel, busIdentityKey, busesAgree, canPair, channelsPair, codeScopePath, countsForThreshold, dispatchByType, displayLabel, exchangesHttpResponses, fileInCodeScope, fnIdentityKey, formatChannel, functionCallBinding, gqlIdentityKey, graphqlOperationBinding, graphqlResolverBinding, isGraphqlOperationBinding, messageBusBinding, normalizeRuleBoundary, packageExportBinding, pairingKey, parseChannel, reportsUnpairedItself, restBinding, ruleBoundaryMatchesKey, runtimeConfigBinding, semanticsAgree, servesRequest, storageRelationalBinding, validateRule };
541
+ export { type BoundaryBehavior, type BoundaryBinding, BoundaryBindingSchema, type BoundarySemanticsDefinition, type BusIdentityKey, type Channel, type ConfidenceInfo, ConfidenceInfoSchema, type ConfidenceLevel, ConfidenceLevelSchema, type ConfidenceSource, ConfidenceSourceSchema, type Corroboration, CorroborationSchema, type DispatchTable, type FindingSuppression, type FnIdentityKey, type GqlIdentityKey, type MatchResult, MessageBusSemantics, MessageBusTechnology, type ParsedChannel, Semantics, type SourceLocation, SourceLocationSchema, type SuppressableSeverity, type SuppressibleFinding, type SuppressionFile, SuppressionFileSchema, type SuppressionRule, SuppressionRuleSchema, TypeShape, applySuppressionsToFindings, bodyShapesMatch, boundaryKey, boundaryLabel, busIdentityKey, busesAgree, canPair, channelsPair, codeScopePath, countsForThreshold, dispatchByType, displayLabel, exchangesHttpResponses, fileInCodeScope, fnIdentityKey, formatChannel, functionCallBinding, gqlIdentityKey, graphqlOperationBinding, graphqlResolverBinding, hasNameHole, isGraphqlOperationBinding, messageBusBinding, namePatternFromSub, namePatternKey, namesAgree, normalizeRuleBoundary, packageExportBinding, pairingKey, parseChannel, reportsUnpairedItself, restBinding, ruleBoundaryMatchesKey, runtimeConfigBinding, semanticsAgree, servesRequest, storageBinding, validateRule };
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { z } from 'zod';
2
- import { T as TypeShape, M as MessageBusSemantics, S as Semantics, B as BoundaryBindingSchema, C as ConfidenceInfoSchema, a as ConfidenceLevelSchema, b as ConfidenceSourceSchema, c as CorroborationSchema, d as SourceLocationSchema, e as MessageBusTechnology } from './schemas-N9GyG0Sn.js';
3
- export { D as DeployableUnit, f as DeployableUnitSchema, F as FunctionCallSemantics, g as FunctionCallSemanticsSchema, G as GraphqlOperationSemantics, h as GraphqlOperationSemanticsSchema, i as GraphqlResolverSemantics, j as GraphqlResolverSemanticsSchema, k as MessageBusSemanticsSchema, R as RestSemantics, l as RestSemanticsSchema, m as RuntimeConfigSemantics, n as RuntimeConfigSemanticsSchema, o as SemanticsSchema, p as StorageRelationalSemantics, q as StorageRelationalSemanticsSchema, r as TypeShapeSchema, s as ecsContainerInstanceName, t as methodsAgree, u as normalizePath, v as routePathAdmits, w as typeDefinitionKey, x as withDefinitionsInlined } from './schemas-N9GyG0Sn.js';
2
+ import { T as TypeShape, M as MessageBusSemantics, S as Semantics, B as BoundaryBindingSchema, C as ConfidenceInfoSchema, a as ConfidenceLevelSchema, b as ConfidenceSourceSchema, c as CorroborationSchema, d as SourceLocationSchema, e as MessageBusTechnology } from './schemas-D6hKT-zV.js';
3
+ export { D as DeployableUnit, f as DeployableUnitSchema, F as FunctionCallSemantics, g as FunctionCallSemanticsSchema, G as GraphqlOperationSemantics, h as GraphqlOperationSemanticsSchema, i as GraphqlResolverSemantics, j as GraphqlResolverSemanticsSchema, k as MessageBusSemanticsSchema, R as RestSemantics, l as RestSemanticsSchema, m as RuntimeConfigSemantics, n as RuntimeConfigSemanticsSchema, o as SemanticsSchema, p as StorageSemantics, q as StorageSemanticsSchema, r as TypeShapeSchema, s as ecsContainerInstanceName, t as methodsAgree, u as normalizePath, v as routePathAdmits, w as typeDefinitionKey, x as withDefinitionsInlined } from './schemas-D6hKT-zV.js';
4
4
 
5
5
  /**
6
6
  * Comparing two TypeShapes structurally.
@@ -262,6 +262,42 @@ declare function dispatchByType<T extends {
262
262
  type: string;
263
263
  }, R>(table: DispatchTable<T, R>, value: T): R;
264
264
 
265
+ /**
266
+ * A name two sides state with a hole in it.
267
+ *
268
+ * A deployed resource is often called something built at deploy time:
269
+ * a template writes `!Sub "${StageName}-orders-v1"` and the code writes
270
+ * `` `${stage}-orders-v1` ``. Neither side states a string, both agree
271
+ * about the fixed text, and each spells the parameter its own way. So a
272
+ * name is written here as fixed text with `{}` holes, the way a REST
273
+ * path is written with `{id}`, and two names agree when their fixed
274
+ * parts line up.
275
+ *
276
+ * A hole covers a whole parameter rather than one path segment,
277
+ * because a name has no separator that every project agrees on.
278
+ */
279
+ /**
280
+ * The name a CloudFormation `Fn::Sub` value states. The array form
281
+ * takes its template from the first element, and the variable map only
282
+ * says where a substitution comes from, which does not change the name.
283
+ */
284
+ declare function namePatternFromSub(value: unknown): string | null;
285
+ /** Whether a name has anything a source left for deploy time to fill. */
286
+ declare function hasNameHole(name: string): boolean;
287
+ /**
288
+ * The form two patterns are compared in: every hole reduced to the same
289
+ * token, since the two sides pick their own name for the parameter.
290
+ */
291
+ declare function namePatternKey(name: string): string;
292
+ /**
293
+ * Whether two names are the same name. Two patterns agree when their
294
+ * fixed parts line up, since a hole on one side meets a hole on the
295
+ * other. A pattern and a concrete name agree when the fixed parts are
296
+ * where the pattern says they are, which is what happens when one side
297
+ * hardcoded what the other parameterized.
298
+ */
299
+ declare function namesAgree(a: string, b: string): boolean;
300
+
265
301
  /**
266
302
  * The suppression pipeline, over the smallest finding both checkers share.
267
303
  *
@@ -475,17 +511,21 @@ declare function runtimeConfigBinding(opts: {
475
511
  instanceName: string;
476
512
  }): BoundaryBinding;
477
513
  /**
478
- * Build a storage-relational binding, the provider side of a relational
479
- * storage table. Transport stores the `storageSystem` value, which keeps
480
- * the layering informative without needing a separate wire-protocol
481
- * taxonomy.
514
+ * Build a storage binding, the side of a store that both a schema
515
+ * reader and a call site can spell. `transport` defaults to the store's
516
+ * own name, which is right for a database whose product and wire
517
+ * protocol are the same word, and a store reached over an SDK passes
518
+ * its wire instead.
482
519
  */
483
- declare function storageRelationalBinding(opts: {
520
+ declare function storageBinding(opts: {
484
521
  recognition: string;
485
- storageSystem: "postgres" | "mysql" | "sqlite";
522
+ storageSystem: string;
523
+ transport?: string;
486
524
  scope: string;
487
- /** Null when the source names a table this reader could not settle. */
488
- table: string | null;
525
+ /** Null when the source gives a container this reader could not settle. */
526
+ container: string | null;
527
+ /** A secondary index or alias, or null for the container's own primary key. */
528
+ accessPath?: string | null;
489
529
  }): BoundaryBinding;
490
530
  /**
491
531
  * Build a message-bus binding, the boundary between a producer that
@@ -498,4 +538,4 @@ declare function messageBusBinding(opts: {
498
538
  channel: string | null;
499
539
  }): BoundaryBinding;
500
540
 
501
- export { type BoundaryBehavior, type BoundaryBinding, BoundaryBindingSchema, type BoundarySemanticsDefinition, type BusIdentityKey, type Channel, type ConfidenceInfo, ConfidenceInfoSchema, type ConfidenceLevel, ConfidenceLevelSchema, type ConfidenceSource, ConfidenceSourceSchema, type Corroboration, CorroborationSchema, type DispatchTable, type FindingSuppression, type FnIdentityKey, type GqlIdentityKey, type MatchResult, MessageBusSemantics, MessageBusTechnology, type ParsedChannel, Semantics, type SourceLocation, SourceLocationSchema, type SuppressableSeverity, type SuppressibleFinding, type SuppressionFile, SuppressionFileSchema, type SuppressionRule, SuppressionRuleSchema, TypeShape, applySuppressionsToFindings, bodyShapesMatch, boundaryKey, boundaryLabel, busIdentityKey, busesAgree, canPair, channelsPair, codeScopePath, countsForThreshold, dispatchByType, displayLabel, exchangesHttpResponses, fileInCodeScope, fnIdentityKey, formatChannel, functionCallBinding, gqlIdentityKey, graphqlOperationBinding, graphqlResolverBinding, isGraphqlOperationBinding, messageBusBinding, normalizeRuleBoundary, packageExportBinding, pairingKey, parseChannel, reportsUnpairedItself, restBinding, ruleBoundaryMatchesKey, runtimeConfigBinding, semanticsAgree, servesRequest, storageRelationalBinding, validateRule };
541
+ export { type BoundaryBehavior, type BoundaryBinding, BoundaryBindingSchema, type BoundarySemanticsDefinition, type BusIdentityKey, type Channel, type ConfidenceInfo, ConfidenceInfoSchema, type ConfidenceLevel, ConfidenceLevelSchema, type ConfidenceSource, ConfidenceSourceSchema, type Corroboration, CorroborationSchema, type DispatchTable, type FindingSuppression, type FnIdentityKey, type GqlIdentityKey, type MatchResult, MessageBusSemantics, MessageBusTechnology, type ParsedChannel, Semantics, type SourceLocation, SourceLocationSchema, type SuppressableSeverity, type SuppressibleFinding, type SuppressionFile, SuppressionFileSchema, type SuppressionRule, SuppressionRuleSchema, TypeShape, applySuppressionsToFindings, bodyShapesMatch, boundaryKey, boundaryLabel, busIdentityKey, busesAgree, canPair, channelsPair, codeScopePath, countsForThreshold, dispatchByType, displayLabel, exchangesHttpResponses, fileInCodeScope, fnIdentityKey, formatChannel, functionCallBinding, gqlIdentityKey, graphqlOperationBinding, graphqlResolverBinding, hasNameHole, isGraphqlOperationBinding, messageBusBinding, namePatternFromSub, namePatternKey, namesAgree, normalizeRuleBoundary, packageExportBinding, pairingKey, parseChannel, reportsUnpairedItself, restBinding, ruleBoundaryMatchesKey, runtimeConfigBinding, semanticsAgree, servesRequest, storageBinding, validateRule };
package/dist/index.js CHANGED
@@ -13,7 +13,7 @@ import {
13
13
  RuntimeConfigSemanticsSchema,
14
14
  SemanticsSchema,
15
15
  SourceLocationSchema,
16
- StorageRelationalSemanticsSchema,
16
+ StorageSemanticsSchema,
17
17
  TypeShapeSchema,
18
18
  allBehaviors,
19
19
  behaviorOf,
@@ -30,7 +30,7 @@ import {
30
30
  routePathAdmits,
31
31
  typeDefinitionKey,
32
32
  withDefinitionsInlined
33
- } from "./chunk-WKR5SU4N.js";
33
+ } from "./chunk-TEXSN75M.js";
34
34
 
35
35
  // src/boundaryKey.ts
36
36
  function boundaryKey(binding) {
@@ -103,6 +103,53 @@ function dispatchByType(table, value) {
103
103
  return handler(value);
104
104
  }
105
105
 
106
+ // src/namePattern.ts
107
+ var HOLE = /\{[^}]*\}/g;
108
+ var SUB_TOKEN = /\$\{([^}]*)\}/g;
109
+ var SUB_ESCAPE = /\$\{!/;
110
+ function namePatternFromSub(value) {
111
+ if (Array.isArray(value)) {
112
+ return typeof value[0] === "string" ? namePatternFromSub(value[0]) : null;
113
+ }
114
+ if (typeof value !== "string") {
115
+ return null;
116
+ }
117
+ if (SUB_ESCAPE.test(value)) {
118
+ return null;
119
+ }
120
+ return value.replace(SUB_TOKEN, (_whole, inner) => `{${inner}}`);
121
+ }
122
+ function hasNameHole(name) {
123
+ HOLE.lastIndex = 0;
124
+ return HOLE.test(name);
125
+ }
126
+ function namePatternKey(name) {
127
+ return name.replace(HOLE, "{}");
128
+ }
129
+ function admits(pattern, name) {
130
+ const source = pattern.split(/(\{[^}]*\})/).map(
131
+ (part) => part.startsWith("{") && part.endsWith("}") ? ".+" : part.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")
132
+ ).join("");
133
+ return new RegExp(`^${source}$`).test(name);
134
+ }
135
+ function namesAgree(a, b) {
136
+ if (a === b) {
137
+ return true;
138
+ }
139
+ const aHasHole = hasNameHole(a);
140
+ const bHasHole = hasNameHole(b);
141
+ if (aHasHole && bHasHole) {
142
+ return namePatternKey(a) === namePatternKey(b);
143
+ }
144
+ if (aHasHole) {
145
+ return admits(a, b);
146
+ }
147
+ if (bHasHole) {
148
+ return admits(b, a);
149
+ }
150
+ return false;
151
+ }
152
+
106
153
  // src/suppressions.ts
107
154
  import { z } from "zod";
108
155
  var SuppressionSideSchema = z.object({
@@ -443,14 +490,15 @@ function runtimeConfigBinding(opts) {
443
490
  recognition: opts.recognition
444
491
  };
445
492
  }
446
- function storageRelationalBinding(opts) {
493
+ function storageBinding(opts) {
447
494
  return {
448
- transport: opts.storageSystem,
495
+ transport: opts.transport ?? opts.storageSystem,
449
496
  semantics: {
450
- name: "storage-relational",
497
+ name: "storage",
451
498
  storageSystem: opts.storageSystem,
452
499
  scope: opts.scope,
453
- table: namedOrNull(opts.table, "storage table")
500
+ container: namedOrNull(opts.container, "storage container"),
501
+ accessPath: opts.accessPath ?? null
454
502
  },
455
503
  recognition: opts.recognition
456
504
  };
@@ -481,7 +529,7 @@ export {
481
529
  RuntimeConfigSemanticsSchema,
482
530
  SemanticsSchema,
483
531
  SourceLocationSchema,
484
- StorageRelationalSemanticsSchema,
532
+ StorageSemanticsSchema,
485
533
  SuppressionFileSchema,
486
534
  SuppressionRuleSchema,
487
535
  TypeShapeSchema,
@@ -506,9 +554,13 @@ export {
506
554
  gqlIdentityKey,
507
555
  graphqlOperationBinding,
508
556
  graphqlResolverBinding,
557
+ hasNameHole,
509
558
  isGraphqlOperationBinding,
510
559
  messageBusBinding,
511
560
  methodsAgree,
561
+ namePatternFromSub,
562
+ namePatternKey,
563
+ namesAgree,
512
564
  normalizePath,
513
565
  normalizeRuleBoundary,
514
566
  packageExportBinding,
@@ -521,7 +573,7 @@ export {
521
573
  runtimeConfigBinding,
522
574
  semanticsAgree,
523
575
  servesRequest,
524
- storageRelationalBinding,
576
+ storageBinding,
525
577
  typeDefinitionKey,
526
578
  validateRule,
527
579
  withDefinitionsInlined