@suss/ir-core 0.20.0 → 0.21.1

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.
@@ -1,8 +1,8 @@
1
1
  // src/schemas.ts
2
- import { z as z11 } from "zod";
2
+ import { z as z12 } from "zod";
3
3
 
4
4
  // src/semantics/registry.ts
5
- import { z as z10 } from "zod";
5
+ import { z as z11 } from "zod";
6
6
 
7
7
  // src/semantics/functionCall.ts
8
8
  import { z } from "zod";
@@ -17,6 +17,9 @@ function fnIdentityKey(packageName, exportPath) {
17
17
  function busIdentityKey(messageBus, subject) {
18
18
  return `bus:${messageBus} ${subject}`;
19
19
  }
20
+ function unitIdentityKey(deploymentTarget, instanceName) {
21
+ return `unit:${deploymentTarget} ${instanceName}`;
22
+ }
20
23
  function metricIdentityKey(metricSystem, metricType) {
21
24
  return `metric:${metricSystem} ${metricType}`;
22
25
  }
@@ -320,6 +323,141 @@ var metricSemantics = defineBoundarySemantics({
320
323
  // src/semantics/rest.ts
321
324
  import { z as z6 } from "zod";
322
325
 
326
+ // src/dispatch.ts
327
+ function dispatchByType(table, value) {
328
+ const handler = table[value.type];
329
+ return handler(value);
330
+ }
331
+
332
+ // src/boundaryName.ts
333
+ var HOLE_SPLIT = /(\{[^}]*\})/;
334
+ var SUB_TOKEN = /\$\{([^}]*)\}/g;
335
+ var SUB_ESCAPE = /\$\{!/;
336
+ function isHole(piece) {
337
+ return piece.startsWith("{") && piece.endsWith("}");
338
+ }
339
+ function parseBoundaryName(name) {
340
+ const parts = name.split(HOLE_SPLIT).filter((piece) => piece !== "").map(
341
+ (piece) => isHole(piece) ? { type: "hole", label: piece.slice(1, -1) } : { type: "text", text: piece }
342
+ );
343
+ const only = parts.length === 1 ? parts[0] : void 0;
344
+ if (only !== void 0 && only.type === "hole") {
345
+ return { type: "reference", path: only.label.split(".") };
346
+ }
347
+ if (parts.some((part) => part.type === "hole")) {
348
+ return { type: "pattern", parts };
349
+ }
350
+ return { type: "literal", value: name };
351
+ }
352
+ var partString = {
353
+ text: (part) => part.text,
354
+ hole: (part) => patternHole(part.label)
355
+ };
356
+ var nameString = {
357
+ literal: (name) => name.value,
358
+ pattern: (name) => name.parts.map((part) => dispatchByType(partString, part)).join(""),
359
+ reference: (name) => patternHole(name.path.join("."))
360
+ };
361
+ function boundaryNameString(name) {
362
+ return dispatchByType(nameString, name);
363
+ }
364
+ function patternHole(label) {
365
+ return `{${label}}`;
366
+ }
367
+ function namePatternFromSub(value) {
368
+ if (Array.isArray(value)) {
369
+ return typeof value[0] === "string" ? namePatternFromSub(value[0]) : null;
370
+ }
371
+ if (typeof value !== "string") {
372
+ return null;
373
+ }
374
+ if (SUB_ESCAPE.test(value)) {
375
+ return null;
376
+ }
377
+ return value.replace(
378
+ SUB_TOKEN,
379
+ (_whole, inner) => patternHole(inner)
380
+ );
381
+ }
382
+ function namesNothing(name) {
383
+ return parseBoundaryName(name).type === "reference";
384
+ }
385
+ function hasNameHole(name) {
386
+ return parseBoundaryName(name).type !== "literal";
387
+ }
388
+ function namePatternKey(name) {
389
+ return dispatchByType(
390
+ {
391
+ literal: (parsed) => parsed.value,
392
+ pattern: (parsed) => boundaryNameString({
393
+ type: "pattern",
394
+ parts: parsed.parts.map(
395
+ (part) => part.type === "hole" ? { type: "hole", label: "" } : part
396
+ )
397
+ }),
398
+ reference: () => patternHole("")
399
+ },
400
+ parseBoundaryName(name)
401
+ );
402
+ }
403
+ function fixedTextLength(name) {
404
+ return dispatchByType(
405
+ {
406
+ literal: (parsed) => parsed.value.length,
407
+ pattern: (parsed) => parsed.parts.reduce(
408
+ (total, part) => total + (part.type === "text" ? part.text.length : 0),
409
+ 0
410
+ ),
411
+ reference: () => 0
412
+ },
413
+ parseBoundaryName(name)
414
+ );
415
+ }
416
+ function quote(text) {
417
+ return text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
418
+ }
419
+ function admits(pattern, name) {
420
+ const source = pattern.parts.map((part) => part.type === "hole" ? ".+" : quote(part.text)).join("");
421
+ return new RegExp(`^${source}$`).test(name);
422
+ }
423
+ function namesAgree(a, b) {
424
+ const left = parseBoundaryName(a);
425
+ const right = parseBoundaryName(b);
426
+ if (left.type === "reference" || right.type === "reference") {
427
+ return false;
428
+ }
429
+ if (left.type === "pattern" && right.type === "pattern") {
430
+ return namePatternKey(a) === namePatternKey(b);
431
+ }
432
+ if (left.type === "pattern") {
433
+ return admits(left, b);
434
+ }
435
+ if (right.type === "pattern") {
436
+ return admits(right, a);
437
+ }
438
+ return a === b;
439
+ }
440
+ function referenceName(reference) {
441
+ const path = [reference.root, ...reference.fields];
442
+ if (path.some((part) => part === "")) {
443
+ return null;
444
+ }
445
+ return boundaryNameString({ type: "reference", path });
446
+ }
447
+ function referenceOf(name) {
448
+ if (name.type !== "reference") {
449
+ return null;
450
+ }
451
+ const root = name.path[0];
452
+ if (root === void 0 || name.path.some((part) => part === "")) {
453
+ return null;
454
+ }
455
+ return { root, fields: name.path.slice(1) };
456
+ }
457
+ function referenceFromName(name) {
458
+ return referenceOf(parseBoundaryName(name));
459
+ }
460
+
323
461
  // src/urlPath.ts
324
462
  var SCHEME_ORIGIN = /^[a-zA-Z][a-zA-Z\d+.-]*:\/\/[^/]*/;
325
463
  var PROTOCOL_RELATIVE_ORIGIN = /^\/\/[^/]*/;
@@ -352,9 +490,9 @@ var RestSemanticsSchema = z6.object({
352
490
  declaredResponses: z6.array(z6.number()).optional()
353
491
  });
354
492
  var OPENING_HOLE = /^\{([^{}]+)\}(.*)$/;
355
- function variableOf(label) {
356
- const parts = label.split(".");
357
- return parts[parts.length - 1] ?? label;
493
+ function baseUrlReference(semantics) {
494
+ const label = OPENING_HOLE.exec(semantics.path ?? "")?.[1];
495
+ return label === void 0 ? null : referenceFromName(patternHole(label));
358
496
  }
359
497
  function normalizePath(path) {
360
498
  let normalized = path.replace(/:([a-zA-Z_]\w*)/g, "{$1}");
@@ -465,6 +603,14 @@ var restSemantics = defineBoundarySemantics({
465
603
  }
466
604
  return routePathAdmits(semantics.path, path) ? "match" : "nomatch";
467
605
  },
606
+ /**
607
+ * A route the registration pattern admits is inside it. A route
608
+ * whose path this source never gave is left outside, because
609
+ * nothing here can show it is one the pattern covers.
610
+ */
611
+ withinScope(semantics, scope) {
612
+ return semantics.path !== null && routePathAdmits(scope, semantics.path);
613
+ },
468
614
  /**
469
615
  * A call whose base URL the deployment fills in, resolved to the
470
616
  * path it reaches.
@@ -480,22 +626,20 @@ var restSemantics = defineBoundarySemantics({
480
626
  * route parameter, and `/orders/{id}` means every id rather than a
481
627
  * variable somebody set.
482
628
  */
483
- groundName(semantics, deployedAs) {
484
- if (semantics.path === null) {
629
+ groundName(semantics, deployment) {
630
+ const reference = baseUrlReference(semantics);
631
+ if (reference === null) {
485
632
  return null;
486
633
  }
487
- const opening = OPENING_HOLE.exec(semantics.path);
488
- if (opening === null) {
489
- return null;
490
- }
491
- const [, label, rest] = opening;
492
- const base = deployedAs(variableOf(label));
634
+ const base = deployment.setTo(reference);
493
635
  if (base === null) {
494
636
  return null;
495
637
  }
638
+ const rest = OPENING_HOLE.exec(semantics.path ?? "")?.[2] ?? "";
496
639
  const grounded = pathAfterOrigin(`${base}${rest}`);
497
640
  return { ...semantics, path: grounded === "" ? "/" : grounded };
498
641
  },
642
+ nameReference: baseUrlReference,
499
643
  ruleBoundary: {
500
644
  // "METHOD /path": one leading token, then an absolute path.
501
645
  claims(raw) {
@@ -585,6 +729,9 @@ var StorageSemanticsSchema = z9.object({
585
729
  */
586
730
  accessPath: z9.string().nullable()
587
731
  });
732
+ function containerReference(semantics) {
733
+ return semantics.container === null ? null : referenceFromName(semantics.container);
734
+ }
588
735
  var storageSemantics = defineBoundarySemantics({
589
736
  name: "storage",
590
737
  schema: StorageSemanticsSchema,
@@ -600,12 +747,109 @@ var storageSemantics = defineBoundarySemantics({
600
747
  /** A query returns rows or items, not a status and a body. */
601
748
  exchangesHttpResponses: false,
602
749
  reportsUnpairedItself: false,
603
- identityKey: () => null
750
+ identityKey: () => null,
751
+ displayLabel: storageLabel,
752
+ /**
753
+ * A container the source states as a variable is whatever the
754
+ * deployment sets that variable to. `{SUBSCRIBERS_TABLE}` in the
755
+ * code and `prod-subscribers-v1` in the manifest are one table.
756
+ */
757
+ groundName(semantics, deployment) {
758
+ const reference = containerReference(semantics);
759
+ if (reference === null) {
760
+ return null;
761
+ }
762
+ const name = deployment.setTo(reference);
763
+ return name === null ? null : { ...semantics, container: name };
764
+ },
765
+ nameReference: containerReference
766
+ }
767
+ });
768
+ function storageLabel(semantics) {
769
+ return `${semantics.storageSystem}:${storageContainerLabel(semantics)}`;
770
+ }
771
+ var EVERY_FIELD = "*";
772
+ function storageContainerLabel(semantics) {
773
+ const container = semantics.container ?? "<unnamed container>";
774
+ const addressed = semantics.accessPath === null ? container : `${container}#${semantics.accessPath}`;
775
+ return semantics.scope === "default" ? addressed : `${semantics.scope}/${addressed}`;
776
+ }
777
+
778
+ // src/semantics/unitInvocation.ts
779
+ import { z as z10 } from "zod";
780
+ var UnitInvocationSemanticsSchema = DeployableUnitSchema.extend({
781
+ name: z10.literal("unit-invocation"),
782
+ instanceName: DeployableUnitSchema.shape.instanceName.nullable()
783
+ });
784
+ function calleeReference(semantics) {
785
+ return semantics.instanceName === null ? null : referenceFromName(semantics.instanceName);
786
+ }
787
+ var unitInvocationSemantics = defineBoundarySemantics({
788
+ name: "unit-invocation",
789
+ schema: UnitInvocationSemanticsSchema,
790
+ // faas.name is the deployed function's own name and instanceName is
791
+ // the deployment template's logical id, which is a different string.
792
+ // Runtime config leaves the pair off for the same reason.
793
+ semconv: {},
794
+ behavior: {
795
+ /**
796
+ * A synchronous invoke gives back whatever the handler returned,
797
+ * which is a value rather than a status and a body. A handler's
798
+ * return only becomes an HTTP response under a proxy integration,
799
+ * and that route gets a REST binding instead of this one.
800
+ */
801
+ exchangesHttpResponses: false,
802
+ /**
803
+ * A unit nothing in the run invokes is the ordinary case, since
804
+ * most services are reached from a stack suss never read. So an
805
+ * uninvoked unit stays in the generic unmatched list rather than
806
+ * being reported as a problem here.
807
+ */
808
+ reportsUnpairedItself: false,
809
+ /**
810
+ * A callee the source states only as a variable is not a name for
811
+ * anything until the deployment fills it in, so it keys as nothing
812
+ * rather than as a bucket that would agree with itself alone.
813
+ */
814
+ identityKey(semantics) {
815
+ if (semantics.instanceName === null || namesNothing(semantics.instanceName)) {
816
+ return null;
817
+ }
818
+ return unitIdentityKey(
819
+ semantics.deploymentTarget,
820
+ semantics.instanceName
821
+ );
822
+ },
823
+ displayLabel(semantics) {
824
+ if (semantics.instanceName === null) {
825
+ return `unit:${semantics.deploymentTarget} (named at runtime)`;
826
+ }
827
+ return unitIdentityKey(
828
+ semantics.deploymentTarget,
829
+ semantics.instanceName
830
+ );
831
+ },
832
+ /**
833
+ * A call that reads its callee's name out of the environment
834
+ * reaches whichever resource the template wires that variable to.
835
+ * The logical id is the answer rather than the deployed name,
836
+ * because the invoked unit's own summary is keyed by the logical
837
+ * id and neither side ever writes the other's string.
838
+ */
839
+ groundName(semantics, deployment) {
840
+ const reference = calleeReference(semantics);
841
+ if (reference === null) {
842
+ return null;
843
+ }
844
+ const logicalId = deployment.pointsAt(reference);
845
+ return logicalId === null ? null : { ...semantics, instanceName: logicalId };
846
+ },
847
+ nameReference: calleeReference
604
848
  }
605
849
  });
606
850
 
607
851
  // src/semantics/registry.ts
608
- var SemanticsSchema = z10.discriminatedUnion("name", [
852
+ var SemanticsSchema = z11.discriminatedUnion("name", [
609
853
  restSemantics.schema,
610
854
  functionCallSemantics.schema,
611
855
  graphqlResolverSemantics.schema,
@@ -613,7 +857,8 @@ var SemanticsSchema = z10.discriminatedUnion("name", [
613
857
  runtimeConfigSemantics.schema,
614
858
  storageSemantics.schema,
615
859
  messageBusSemantics.schema,
616
- metricSemantics.schema
860
+ metricSemantics.schema,
861
+ unitInvocationSemantics.schema
617
862
  ]);
618
863
  var DEFINITIONS = [
619
864
  restSemantics,
@@ -623,7 +868,8 @@ var DEFINITIONS = [
623
868
  runtimeConfigSemantics,
624
869
  storageSemantics,
625
870
  messageBusSemantics,
626
- metricSemantics
871
+ metricSemantics,
872
+ unitInvocationSemantics
627
873
  ];
628
874
  var BY_NAME = new Map(
629
875
  DEFINITIONS.map((d) => [d.name, d])
@@ -646,31 +892,31 @@ function allBehaviors() {
646
892
  }
647
893
 
648
894
  // src/schemas.ts
649
- var ConfidenceSourceSchema = z11.enum([
895
+ var ConfidenceSourceSchema = z12.enum([
650
896
  "inferred_static",
651
897
  "inferred_ai",
652
898
  "declared",
653
899
  "derived"
654
900
  ]);
655
- var ConfidenceLevelSchema = z11.enum(["high", "medium", "low"]);
656
- var CorroborationSchema = z11.object({
657
- outcome: z11.enum(["observed", "refuted", "untested"]),
901
+ var ConfidenceLevelSchema = z12.enum(["high", "medium", "low"]);
902
+ var CorroborationSchema = z12.object({
903
+ outcome: z12.enum(["observed", "refuted", "untested"]),
658
904
  /** Executions that produced a verdict for this claim. */
659
- runs: z11.number(),
905
+ runs: z12.number(),
660
906
  /** Present when refuted: the input and observation that disagreed. */
661
- counterexample: z11.unknown().optional(),
907
+ counterexample: z12.unknown().optional(),
662
908
  /** Present when untested: why no verdict was reachable. */
663
- reason: z11.string().optional()
909
+ reason: z12.string().optional()
664
910
  });
665
- var ConfidenceInfoSchema = z11.object({
911
+ var ConfidenceInfoSchema = z12.object({
666
912
  source: ConfidenceSourceSchema,
667
913
  level: ConfidenceLevelSchema,
668
914
  corroboration: CorroborationSchema.optional()
669
915
  });
670
- var SourceLocationSchema = z11.object({
671
- file: z11.string(),
916
+ var SourceLocationSchema = z12.object({
917
+ file: z12.string(),
672
918
  /** Line numbers, for a person reading the summary or an editor link. */
673
- range: z11.object({ start: z11.number(), end: z11.number() }),
919
+ range: z12.object({ start: z12.number(), end: z12.number() }),
674
920
  /**
675
921
  * Character offsets of the unit in its file. Identity and joins
676
922
  * measure with these, since two functions can share a line and never
@@ -678,8 +924,8 @@ var SourceLocationSchema = z11.object({
678
924
  * same place. Absent on summaries no source position backs, a
679
925
  * contract artifact's say.
680
926
  */
681
- span: z11.object({ start: z11.number(), end: z11.number() }).optional(),
682
- exportName: z11.string().nullable(),
927
+ span: z12.object({ start: z12.number(), end: z12.number() }).optional(),
928
+ exportName: z12.string().nullable(),
683
929
  /**
684
930
  * The project the extract was pointed at, by the name that project
685
931
  * calls itself.
@@ -689,47 +935,47 @@ var SourceLocationSchema = z11.object({
689
935
  * summaries puts them on top of each other. This field is what tells
690
936
  * them apart, and what a reader groups by.
691
937
  */
692
- workspace: z11.string().optional()
938
+ workspace: z12.string().optional()
693
939
  });
694
- var BoundaryBindingSchema = z11.object({
695
- transport: z11.string(),
940
+ var BoundaryBindingSchema = z12.object({
941
+ transport: z12.string(),
696
942
  semantics: SemanticsSchema,
697
- recognition: z11.string()
943
+ recognition: z12.string()
698
944
  });
699
945
  function typeDefinitionKey(ref) {
700
946
  return ref.def ?? null;
701
947
  }
702
- var TypeShapeSchema = z11.lazy(
703
- () => z11.discriminatedUnion("type", [
704
- z11.object({
705
- type: z11.literal("record"),
706
- properties: z11.record(z11.string(), TypeShapeSchema),
707
- spreads: z11.array(z11.object({ sourceText: z11.string() })).optional()
948
+ var TypeShapeSchema = z12.lazy(
949
+ () => z12.discriminatedUnion("type", [
950
+ z12.object({
951
+ type: z12.literal("record"),
952
+ properties: z12.record(z12.string(), TypeShapeSchema),
953
+ spreads: z12.array(z12.object({ sourceText: z12.string() })).optional()
708
954
  }),
709
- z11.object({ type: z11.literal("dictionary"), values: TypeShapeSchema }),
710
- z11.object({ type: z11.literal("array"), items: TypeShapeSchema }),
711
- z11.object({
712
- type: z11.literal("literal"),
713
- value: z11.union([z11.string(), z11.number(), z11.boolean()]),
714
- raw: z11.string().optional()
955
+ z12.object({ type: z12.literal("dictionary"), values: TypeShapeSchema }),
956
+ z12.object({ type: z12.literal("array"), items: TypeShapeSchema }),
957
+ z12.object({
958
+ type: z12.literal("literal"),
959
+ value: z12.union([z12.string(), z12.number(), z12.boolean()]),
960
+ raw: z12.string().optional()
715
961
  }),
716
- z11.object({ type: z11.literal("text") }),
717
- z11.object({ type: z11.literal("integer") }),
718
- z11.object({ type: z11.literal("number") }),
719
- z11.object({ type: z11.literal("boolean") }),
720
- z11.object({ type: z11.literal("null") }),
721
- z11.object({ type: z11.literal("undefined") }),
722
- z11.object({
723
- type: z11.literal("union"),
724
- variants: z11.array(TypeShapeSchema)
962
+ z12.object({ type: z12.literal("text") }),
963
+ z12.object({ type: z12.literal("integer") }),
964
+ z12.object({ type: z12.literal("number") }),
965
+ z12.object({ type: z12.literal("boolean") }),
966
+ z12.object({ type: z12.literal("null") }),
967
+ z12.object({ type: z12.literal("undefined") }),
968
+ z12.object({
969
+ type: z12.literal("union"),
970
+ variants: z12.array(TypeShapeSchema)
725
971
  }),
726
- z11.object({
727
- type: z11.literal("ref"),
728
- name: z11.string(),
729
- from: z11.string().optional(),
730
- def: z11.string().optional()
972
+ z12.object({
973
+ type: z12.literal("ref"),
974
+ name: z12.string(),
975
+ from: z12.string().optional(),
976
+ def: z12.string().optional()
731
977
  }),
732
- z11.object({ type: z11.literal("unknown") })
978
+ z12.object({ type: z12.literal("unknown") })
733
979
  ])
734
980
  );
735
981
  var MAX_DEFINITION_DEPTH = 6;
@@ -778,6 +1024,7 @@ export {
778
1024
  gqlIdentityKey,
779
1025
  fnIdentityKey,
780
1026
  busIdentityKey,
1027
+ unitIdentityKey,
781
1028
  metricIdentityKey,
782
1029
  FunctionCallSemanticsSchema,
783
1030
  GraphqlResolverSemanticsSchema,
@@ -787,6 +1034,19 @@ export {
787
1034
  channelsPair,
788
1035
  MessageBusSemanticsSchema,
789
1036
  MetricSemanticsSchema,
1037
+ dispatchByType,
1038
+ parseBoundaryName,
1039
+ boundaryNameString,
1040
+ patternHole,
1041
+ namePatternFromSub,
1042
+ namesNothing,
1043
+ hasNameHole,
1044
+ namePatternKey,
1045
+ fixedTextLength,
1046
+ namesAgree,
1047
+ referenceName,
1048
+ referenceOf,
1049
+ referenceFromName,
790
1050
  pathAfterOrigin,
791
1051
  statesAnOrigin,
792
1052
  RestSemanticsSchema,
@@ -798,6 +1058,10 @@ export {
798
1058
  ecsContainerInstanceName,
799
1059
  RuntimeConfigSemanticsSchema,
800
1060
  StorageSemanticsSchema,
1061
+ storageLabel,
1062
+ EVERY_FIELD,
1063
+ storageContainerLabel,
1064
+ UnitInvocationSemanticsSchema,
801
1065
  SemanticsSchema,
802
1066
  behaviorOf,
803
1067
  semconvMappingOf,