@suss/ir-core 0.8.0 → 0.10.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/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, D as DeployableUnit } from './schemas-BLS4PXwc.cjs';
3
- export { 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-BLS4PXwc.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, D as DeployableUnit } from './schemas-CGR6qjFf.cjs';
3
+ export { 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-CGR6qjFf.cjs';
4
4
 
5
5
  /**
6
6
  * Comparing two TypeShapes structurally.
@@ -49,8 +49,33 @@ declare function bodyShapesMatch(actual: TypeShape, declared: TypeShape): MatchR
49
49
  * because a published summary has to mean the same thing to a reader
50
50
  * who never installed the pack that wrote it. If a pack needs a
51
51
  * protocol nobody has defined yet, add a module here.
52
+ *
53
+ * A protocol also says which of its words come from OpenTelemetry's
54
+ * semantic conventions, in `semconv`. The README says why that
55
+ * matters and where it stops.
52
56
  */
53
57
 
58
+ /** One identity field written as an OpenTelemetry attribute. */
59
+ interface SemconvAttribute {
60
+ /** The attribute name, as the semantic conventions spell it. */
61
+ name: string;
62
+ /**
63
+ * Values suss writes where the source named none. A span never says
64
+ * them, so the projection leaves the attribute off rather than
65
+ * emitting a string that could only ever mismatch.
66
+ */
67
+ placeholderValues?: readonly string[];
68
+ }
69
+ /**
70
+ * Which identity fields the semantic conventions have an attribute
71
+ * for. A field is absent when they have no attribute for it, or when
72
+ * our value is our own string rather than the one a span gets.
73
+ */
74
+ type SemconvMapping<S extends {
75
+ name: string;
76
+ }> = {
77
+ readonly [K in Exclude<keyof S, "name">]?: SemconvAttribute;
78
+ };
54
79
  /**
55
80
  * How one semantics variant keys its boundaries and pairs them up. Each
56
81
  * variant fills this in inside its own module, and nothing else in the
@@ -123,6 +148,11 @@ interface BoundarySemanticsDefinition<Z extends z.ZodType<{
123
148
  name: z.infer<Z>["name"];
124
149
  schema: Z;
125
150
  behavior: BoundaryBehavior<z.infer<Z>>;
151
+ /**
152
+ * Every protocol declares this, empty included, so that adding one
153
+ * means deciding where its words come from.
154
+ */
155
+ semconv: SemconvMapping<z.infer<Z>>;
126
156
  }
127
157
 
128
158
  declare const IdentityKeyBrand: unique symbol;
@@ -141,6 +171,39 @@ type BusIdentityKey = `bus:${MessageBusSemantics["messageBus"]} ${string}` & {
141
171
  readonly [IdentityKeyBrand]: "bus";
142
172
  };
143
173
  declare function busIdentityKey(messageBus: MessageBusSemantics["messageBus"], subject: string): BusIdentityKey;
174
+ /** `metric:system type`, the key both sides of a metric pair on. */
175
+ type MetricIdentityKey = `metric:${string} ${string}` & {
176
+ readonly [IdentityKeyBrand]: "metric";
177
+ };
178
+ declare function metricIdentityKey(metricSystem: string, metricType: string): MetricIdentityKey;
179
+
180
+ declare const MetricSemanticsSchema: z.ZodObject<{
181
+ name: z.ZodLiteral<"metric">;
182
+ metricSystem: z.ZodString;
183
+ metricType: z.ZodNullable<z.ZodString>;
184
+ }, z.core.$strip>;
185
+ type MetricSemantics = z.infer<typeof MetricSemanticsSchema>;
186
+
187
+ /**
188
+ * A boundary binding read as OpenTelemetry attributes.
189
+ *
190
+ * A summary says what a unit can reach and a span says what it did
191
+ * reach. Joining the two means both sides spelling the boundary the
192
+ * same way, so suss writes the value a span gets wherever the semantic
193
+ * conventions have a word for it, and this projection puts those
194
+ * values under the attributes a trace store already indexes.
195
+ *
196
+ * Which fields those are is each protocol's own declaration, in its
197
+ * module under `semantics/`. Nothing here knows about any protocol.
198
+ */
199
+
200
+ /**
201
+ * The attributes a boundary states, by name. A field the source never
202
+ * gave, a placeholder, and a field the conventions have no attribute
203
+ * for are all left out, so every pair here compares byte for byte
204
+ * against the same attribute on a span.
205
+ */
206
+ declare function semconvAttributes(binding: BoundaryBinding): Record<string, string>;
144
207
 
145
208
  /**
146
209
  * Keys for a boundary binding, and whether two of them agree. Every
@@ -180,6 +243,115 @@ declare function reportsUnpairedItself(binding: BoundaryBinding): boolean;
180
243
  */
181
244
  declare function servesRequest(binding: BoundaryBinding, method: string, path: string): MatchResult | null;
182
245
 
246
+ /**
247
+ * The boundary-name syntax, parsed and printed in one place.
248
+ *
249
+ * A name in a summary means one of three things, told apart by the
250
+ * braces alone: a literal (`orders-v1`), a pattern with deploy-time
251
+ * holes (`{stage}-orders-v1`), or a reference saying where to go and
252
+ * ask (`{location.bucket}`, `{ORDER_TABLE}`). A second parser can
253
+ * disagree about which is which, and a second printer can spell a
254
+ * value this one cannot read back, so everything that touches the
255
+ * braces calls this module: `parseBoundaryName` and
256
+ * `boundaryNameString` are the two directions, and the helpers below
257
+ * are views over them. The package README tells the longer story,
258
+ * including why REST route paths and message-bus channels stay apart.
259
+ */
260
+ /** One piece of a pattern: text the writer stated, or a hole. */
261
+ type NamePart = {
262
+ type: "text";
263
+ text: string;
264
+ } | {
265
+ type: "hole";
266
+ label: string;
267
+ };
268
+ /**
269
+ * What a name string means. A `reference` keeps its raw dot-separated
270
+ * path, and `referenceOf` is the view that checks the parts are all
271
+ * present, so a malformed spelling still classifies as a reference and
272
+ * still pairs with nothing.
273
+ */
274
+ type BoundaryName = {
275
+ type: "literal";
276
+ value: string;
277
+ } | {
278
+ type: "pattern";
279
+ parts: NamePart[];
280
+ } | {
281
+ type: "reference";
282
+ path: string[];
283
+ };
284
+ /** What a name string means. The exact inverse of `boundaryNameString`. */
285
+ declare function parseBoundaryName(name: string): BoundaryName;
286
+ /** The one serializer. Everything a summary spells goes through here. */
287
+ declare function boundaryNameString(name: BoundaryName): string;
288
+ /**
289
+ * How a hole is spelled. A reader that assembles a pattern a part at a
290
+ * time, the way the adapter's name reader does, mints each hole here
291
+ * so the spelling cannot drift from the parse above.
292
+ */
293
+ declare function patternHole(label: string): string;
294
+ /**
295
+ * The name a CloudFormation `Fn::Sub` value states. The array form
296
+ * takes its template from the first element, and the variable map only
297
+ * says where a substitution comes from, which does not change the name.
298
+ */
299
+ declare function namePatternFromSub(value: unknown): string | null;
300
+ /**
301
+ * Whether a name says only that somebody else knows it. A wrapper that
302
+ * takes its bucket as an argument states `{location.bucket}` and
303
+ * nothing more, which says which parameter to ask rather than which
304
+ * bucket. A name like that agrees with nothing until something grounds
305
+ * it, since otherwise it would agree with every name there is.
306
+ */
307
+ declare function namesNothing(name: string): boolean;
308
+ /** Whether a name has anything a source left for deploy time to fill. */
309
+ declare function hasNameHole(name: string): boolean;
310
+ /**
311
+ * The form two patterns are compared in: every hole reduced to the same
312
+ * token, since the two sides pick their own name for the parameter.
313
+ */
314
+ declare function namePatternKey(name: string): string;
315
+ /** How much of a name the writer stated rather than left for deploy time. */
316
+ declare function fixedTextLength(name: string): number;
317
+ /**
318
+ * Whether two names are the same name. Two patterns agree when their
319
+ * fixed parts line up, since a hole on one side meets a hole on the
320
+ * other. A pattern and a concrete name agree when the fixed parts are
321
+ * where the pattern says they are, which is what happens when one side
322
+ * hardcoded what the other parameterized. A reference agrees with
323
+ * nothing on either side.
324
+ */
325
+ declare function namesAgree(a: string, b: string): boolean;
326
+ /** Where a reference says to go and ask. */
327
+ interface Reference {
328
+ /**
329
+ * The value the code starts from: a parameter of the unit the
330
+ * reference was written in, or a variable the deployment sets. Which
331
+ * of those it is depends on the unit's inputs, so the reader that
332
+ * grounds a reference decides, not the string.
333
+ */
334
+ root: string;
335
+ /** The fields to read inside it, outermost first. */
336
+ fields: string[];
337
+ }
338
+ /**
339
+ * How a reference is written. Null when a part of it is empty, since a
340
+ * reference has to say what to ask about.
341
+ */
342
+ declare function referenceName(reference: Reference): string | null;
343
+ /**
344
+ * The place a parsed reference says to ask, or null for a name that is
345
+ * not a reference, or for a reference with a part missing, which says
346
+ * nothing anybody could answer.
347
+ */
348
+ declare function referenceOf(name: BoundaryName): Reference | null;
349
+ /**
350
+ * The reference a name states, or null when the name states a name
351
+ * rather than where to go and ask.
352
+ */
353
+ declare function referenceFromName(name: string): Reference | null;
354
+
183
355
  /**
184
356
  * Deciding when two message-bus channel strings mean the same thing.
185
357
  *
@@ -262,50 +434,6 @@ declare function dispatchByType<T extends {
262
434
  type: string;
263
435
  }, R>(table: DispatchTable<T, R>, value: T): R;
264
436
 
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
- /**
286
- * Whether a name says only that somebody else knows it. A wrapper that
287
- * takes its bucket as an argument states `{location.bucket}` and
288
- * nothing more, which says which parameter to ask rather than which
289
- * bucket. A name like that agrees with nothing until something grounds
290
- * it, since otherwise it would agree with every name there is.
291
- */
292
- declare function namesNothing(name: string): boolean;
293
- /** Whether a name has anything a source left for deploy time to fill. */
294
- declare function hasNameHole(name: string): boolean;
295
- /**
296
- * The form two patterns are compared in: every hole reduced to the same
297
- * token, since the two sides pick their own name for the parameter.
298
- */
299
- declare function namePatternKey(name: string): string;
300
- /**
301
- * Whether two names are the same name. Two patterns agree when their
302
- * fixed parts line up, since a hole on one side meets a hole on the
303
- * other. A pattern and a concrete name agree when the fixed parts are
304
- * where the pattern says they are, which is what happens when one side
305
- * hardcoded what the other parameterized.
306
- */
307
- declare function namesAgree(a: string, b: string): boolean;
308
-
309
437
  /**
310
438
  * The suppression pipeline, over the smallest finding both checkers share.
311
439
  *
@@ -545,5 +673,15 @@ declare function messageBusBinding(opts: {
545
673
  /** Null when this source does not say which channel. */
546
674
  channel: string | null;
547
675
  }): BoundaryBinding;
676
+ /**
677
+ * Build a metric binding, the boundary between whatever declares a
678
+ * named series of measurements and whatever reads it back by that name.
679
+ */
680
+ declare function metricBinding(opts: {
681
+ recognition: string;
682
+ metricSystem: string;
683
+ /** Null when this source states a metric it could not name. */
684
+ metricType: string | null;
685
+ }): BoundaryBinding;
548
686
 
549
- export { type BoundaryBehavior, type BoundaryBinding, BoundaryBindingSchema, type BoundarySemanticsDefinition, type BusIdentityKey, type Channel, type ConfidenceInfo, ConfidenceInfoSchema, type ConfidenceLevel, ConfidenceLevelSchema, type ConfidenceSource, ConfidenceSourceSchema, type Corroboration, CorroborationSchema, DeployableUnit, 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, namesNothing, normalizeRuleBoundary, packageExportBinding, pairingKey, parseChannel, reportsUnpairedItself, restBinding, ruleBoundaryMatchesKey, runtimeConfigBinding, semanticsAgree, servesRequest, storageBinding, validateRule };
687
+ export { type BoundaryBehavior, type BoundaryBinding, BoundaryBindingSchema, type BoundaryName, type BoundarySemanticsDefinition, type BusIdentityKey, type Channel, type ConfidenceInfo, ConfidenceInfoSchema, type ConfidenceLevel, ConfidenceLevelSchema, type ConfidenceSource, ConfidenceSourceSchema, type Corroboration, CorroborationSchema, DeployableUnit, type DispatchTable, type FindingSuppression, type FnIdentityKey, type GqlIdentityKey, type MatchResult, MessageBusSemantics, MessageBusTechnology, type MetricIdentityKey, type MetricSemantics, MetricSemanticsSchema, type NamePart, type ParsedChannel, type Reference, Semantics, type SemconvAttribute, type SemconvMapping, type SourceLocation, SourceLocationSchema, type SuppressableSeverity, type SuppressibleFinding, type SuppressionFile, SuppressionFileSchema, type SuppressionRule, SuppressionRuleSchema, TypeShape, applySuppressionsToFindings, bodyShapesMatch, boundaryKey, boundaryLabel, boundaryNameString, busIdentityKey, busesAgree, canPair, channelsPair, codeScopePath, countsForThreshold, dispatchByType, displayLabel, exchangesHttpResponses, fileInCodeScope, fixedTextLength, fnIdentityKey, formatChannel, functionCallBinding, gqlIdentityKey, graphqlOperationBinding, graphqlResolverBinding, hasNameHole, isGraphqlOperationBinding, messageBusBinding, metricBinding, metricIdentityKey, namePatternFromSub, namePatternKey, namesAgree, namesNothing, normalizeRuleBoundary, packageExportBinding, pairingKey, parseBoundaryName, parseChannel, patternHole, referenceFromName, referenceName, referenceOf, reportsUnpairedItself, restBinding, ruleBoundaryMatchesKey, runtimeConfigBinding, semanticsAgree, semconvAttributes, 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, D as DeployableUnit } from './schemas-BLS4PXwc.js';
3
- export { 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-BLS4PXwc.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, D as DeployableUnit } from './schemas-CGR6qjFf.js';
3
+ export { 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-CGR6qjFf.js';
4
4
 
5
5
  /**
6
6
  * Comparing two TypeShapes structurally.
@@ -49,8 +49,33 @@ declare function bodyShapesMatch(actual: TypeShape, declared: TypeShape): MatchR
49
49
  * because a published summary has to mean the same thing to a reader
50
50
  * who never installed the pack that wrote it. If a pack needs a
51
51
  * protocol nobody has defined yet, add a module here.
52
+ *
53
+ * A protocol also says which of its words come from OpenTelemetry's
54
+ * semantic conventions, in `semconv`. The README says why that
55
+ * matters and where it stops.
52
56
  */
53
57
 
58
+ /** One identity field written as an OpenTelemetry attribute. */
59
+ interface SemconvAttribute {
60
+ /** The attribute name, as the semantic conventions spell it. */
61
+ name: string;
62
+ /**
63
+ * Values suss writes where the source named none. A span never says
64
+ * them, so the projection leaves the attribute off rather than
65
+ * emitting a string that could only ever mismatch.
66
+ */
67
+ placeholderValues?: readonly string[];
68
+ }
69
+ /**
70
+ * Which identity fields the semantic conventions have an attribute
71
+ * for. A field is absent when they have no attribute for it, or when
72
+ * our value is our own string rather than the one a span gets.
73
+ */
74
+ type SemconvMapping<S extends {
75
+ name: string;
76
+ }> = {
77
+ readonly [K in Exclude<keyof S, "name">]?: SemconvAttribute;
78
+ };
54
79
  /**
55
80
  * How one semantics variant keys its boundaries and pairs them up. Each
56
81
  * variant fills this in inside its own module, and nothing else in the
@@ -123,6 +148,11 @@ interface BoundarySemanticsDefinition<Z extends z.ZodType<{
123
148
  name: z.infer<Z>["name"];
124
149
  schema: Z;
125
150
  behavior: BoundaryBehavior<z.infer<Z>>;
151
+ /**
152
+ * Every protocol declares this, empty included, so that adding one
153
+ * means deciding where its words come from.
154
+ */
155
+ semconv: SemconvMapping<z.infer<Z>>;
126
156
  }
127
157
 
128
158
  declare const IdentityKeyBrand: unique symbol;
@@ -141,6 +171,39 @@ type BusIdentityKey = `bus:${MessageBusSemantics["messageBus"]} ${string}` & {
141
171
  readonly [IdentityKeyBrand]: "bus";
142
172
  };
143
173
  declare function busIdentityKey(messageBus: MessageBusSemantics["messageBus"], subject: string): BusIdentityKey;
174
+ /** `metric:system type`, the key both sides of a metric pair on. */
175
+ type MetricIdentityKey = `metric:${string} ${string}` & {
176
+ readonly [IdentityKeyBrand]: "metric";
177
+ };
178
+ declare function metricIdentityKey(metricSystem: string, metricType: string): MetricIdentityKey;
179
+
180
+ declare const MetricSemanticsSchema: z.ZodObject<{
181
+ name: z.ZodLiteral<"metric">;
182
+ metricSystem: z.ZodString;
183
+ metricType: z.ZodNullable<z.ZodString>;
184
+ }, z.core.$strip>;
185
+ type MetricSemantics = z.infer<typeof MetricSemanticsSchema>;
186
+
187
+ /**
188
+ * A boundary binding read as OpenTelemetry attributes.
189
+ *
190
+ * A summary says what a unit can reach and a span says what it did
191
+ * reach. Joining the two means both sides spelling the boundary the
192
+ * same way, so suss writes the value a span gets wherever the semantic
193
+ * conventions have a word for it, and this projection puts those
194
+ * values under the attributes a trace store already indexes.
195
+ *
196
+ * Which fields those are is each protocol's own declaration, in its
197
+ * module under `semantics/`. Nothing here knows about any protocol.
198
+ */
199
+
200
+ /**
201
+ * The attributes a boundary states, by name. A field the source never
202
+ * gave, a placeholder, and a field the conventions have no attribute
203
+ * for are all left out, so every pair here compares byte for byte
204
+ * against the same attribute on a span.
205
+ */
206
+ declare function semconvAttributes(binding: BoundaryBinding): Record<string, string>;
144
207
 
145
208
  /**
146
209
  * Keys for a boundary binding, and whether two of them agree. Every
@@ -180,6 +243,115 @@ declare function reportsUnpairedItself(binding: BoundaryBinding): boolean;
180
243
  */
181
244
  declare function servesRequest(binding: BoundaryBinding, method: string, path: string): MatchResult | null;
182
245
 
246
+ /**
247
+ * The boundary-name syntax, parsed and printed in one place.
248
+ *
249
+ * A name in a summary means one of three things, told apart by the
250
+ * braces alone: a literal (`orders-v1`), a pattern with deploy-time
251
+ * holes (`{stage}-orders-v1`), or a reference saying where to go and
252
+ * ask (`{location.bucket}`, `{ORDER_TABLE}`). A second parser can
253
+ * disagree about which is which, and a second printer can spell a
254
+ * value this one cannot read back, so everything that touches the
255
+ * braces calls this module: `parseBoundaryName` and
256
+ * `boundaryNameString` are the two directions, and the helpers below
257
+ * are views over them. The package README tells the longer story,
258
+ * including why REST route paths and message-bus channels stay apart.
259
+ */
260
+ /** One piece of a pattern: text the writer stated, or a hole. */
261
+ type NamePart = {
262
+ type: "text";
263
+ text: string;
264
+ } | {
265
+ type: "hole";
266
+ label: string;
267
+ };
268
+ /**
269
+ * What a name string means. A `reference` keeps its raw dot-separated
270
+ * path, and `referenceOf` is the view that checks the parts are all
271
+ * present, so a malformed spelling still classifies as a reference and
272
+ * still pairs with nothing.
273
+ */
274
+ type BoundaryName = {
275
+ type: "literal";
276
+ value: string;
277
+ } | {
278
+ type: "pattern";
279
+ parts: NamePart[];
280
+ } | {
281
+ type: "reference";
282
+ path: string[];
283
+ };
284
+ /** What a name string means. The exact inverse of `boundaryNameString`. */
285
+ declare function parseBoundaryName(name: string): BoundaryName;
286
+ /** The one serializer. Everything a summary spells goes through here. */
287
+ declare function boundaryNameString(name: BoundaryName): string;
288
+ /**
289
+ * How a hole is spelled. A reader that assembles a pattern a part at a
290
+ * time, the way the adapter's name reader does, mints each hole here
291
+ * so the spelling cannot drift from the parse above.
292
+ */
293
+ declare function patternHole(label: string): string;
294
+ /**
295
+ * The name a CloudFormation `Fn::Sub` value states. The array form
296
+ * takes its template from the first element, and the variable map only
297
+ * says where a substitution comes from, which does not change the name.
298
+ */
299
+ declare function namePatternFromSub(value: unknown): string | null;
300
+ /**
301
+ * Whether a name says only that somebody else knows it. A wrapper that
302
+ * takes its bucket as an argument states `{location.bucket}` and
303
+ * nothing more, which says which parameter to ask rather than which
304
+ * bucket. A name like that agrees with nothing until something grounds
305
+ * it, since otherwise it would agree with every name there is.
306
+ */
307
+ declare function namesNothing(name: string): boolean;
308
+ /** Whether a name has anything a source left for deploy time to fill. */
309
+ declare function hasNameHole(name: string): boolean;
310
+ /**
311
+ * The form two patterns are compared in: every hole reduced to the same
312
+ * token, since the two sides pick their own name for the parameter.
313
+ */
314
+ declare function namePatternKey(name: string): string;
315
+ /** How much of a name the writer stated rather than left for deploy time. */
316
+ declare function fixedTextLength(name: string): number;
317
+ /**
318
+ * Whether two names are the same name. Two patterns agree when their
319
+ * fixed parts line up, since a hole on one side meets a hole on the
320
+ * other. A pattern and a concrete name agree when the fixed parts are
321
+ * where the pattern says they are, which is what happens when one side
322
+ * hardcoded what the other parameterized. A reference agrees with
323
+ * nothing on either side.
324
+ */
325
+ declare function namesAgree(a: string, b: string): boolean;
326
+ /** Where a reference says to go and ask. */
327
+ interface Reference {
328
+ /**
329
+ * The value the code starts from: a parameter of the unit the
330
+ * reference was written in, or a variable the deployment sets. Which
331
+ * of those it is depends on the unit's inputs, so the reader that
332
+ * grounds a reference decides, not the string.
333
+ */
334
+ root: string;
335
+ /** The fields to read inside it, outermost first. */
336
+ fields: string[];
337
+ }
338
+ /**
339
+ * How a reference is written. Null when a part of it is empty, since a
340
+ * reference has to say what to ask about.
341
+ */
342
+ declare function referenceName(reference: Reference): string | null;
343
+ /**
344
+ * The place a parsed reference says to ask, or null for a name that is
345
+ * not a reference, or for a reference with a part missing, which says
346
+ * nothing anybody could answer.
347
+ */
348
+ declare function referenceOf(name: BoundaryName): Reference | null;
349
+ /**
350
+ * The reference a name states, or null when the name states a name
351
+ * rather than where to go and ask.
352
+ */
353
+ declare function referenceFromName(name: string): Reference | null;
354
+
183
355
  /**
184
356
  * Deciding when two message-bus channel strings mean the same thing.
185
357
  *
@@ -262,50 +434,6 @@ declare function dispatchByType<T extends {
262
434
  type: string;
263
435
  }, R>(table: DispatchTable<T, R>, value: T): R;
264
436
 
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
- /**
286
- * Whether a name says only that somebody else knows it. A wrapper that
287
- * takes its bucket as an argument states `{location.bucket}` and
288
- * nothing more, which says which parameter to ask rather than which
289
- * bucket. A name like that agrees with nothing until something grounds
290
- * it, since otherwise it would agree with every name there is.
291
- */
292
- declare function namesNothing(name: string): boolean;
293
- /** Whether a name has anything a source left for deploy time to fill. */
294
- declare function hasNameHole(name: string): boolean;
295
- /**
296
- * The form two patterns are compared in: every hole reduced to the same
297
- * token, since the two sides pick their own name for the parameter.
298
- */
299
- declare function namePatternKey(name: string): string;
300
- /**
301
- * Whether two names are the same name. Two patterns agree when their
302
- * fixed parts line up, since a hole on one side meets a hole on the
303
- * other. A pattern and a concrete name agree when the fixed parts are
304
- * where the pattern says they are, which is what happens when one side
305
- * hardcoded what the other parameterized.
306
- */
307
- declare function namesAgree(a: string, b: string): boolean;
308
-
309
437
  /**
310
438
  * The suppression pipeline, over the smallest finding both checkers share.
311
439
  *
@@ -545,5 +673,15 @@ declare function messageBusBinding(opts: {
545
673
  /** Null when this source does not say which channel. */
546
674
  channel: string | null;
547
675
  }): BoundaryBinding;
676
+ /**
677
+ * Build a metric binding, the boundary between whatever declares a
678
+ * named series of measurements and whatever reads it back by that name.
679
+ */
680
+ declare function metricBinding(opts: {
681
+ recognition: string;
682
+ metricSystem: string;
683
+ /** Null when this source states a metric it could not name. */
684
+ metricType: string | null;
685
+ }): BoundaryBinding;
548
686
 
549
- export { type BoundaryBehavior, type BoundaryBinding, BoundaryBindingSchema, type BoundarySemanticsDefinition, type BusIdentityKey, type Channel, type ConfidenceInfo, ConfidenceInfoSchema, type ConfidenceLevel, ConfidenceLevelSchema, type ConfidenceSource, ConfidenceSourceSchema, type Corroboration, CorroborationSchema, DeployableUnit, 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, namesNothing, normalizeRuleBoundary, packageExportBinding, pairingKey, parseChannel, reportsUnpairedItself, restBinding, ruleBoundaryMatchesKey, runtimeConfigBinding, semanticsAgree, servesRequest, storageBinding, validateRule };
687
+ export { type BoundaryBehavior, type BoundaryBinding, BoundaryBindingSchema, type BoundaryName, type BoundarySemanticsDefinition, type BusIdentityKey, type Channel, type ConfidenceInfo, ConfidenceInfoSchema, type ConfidenceLevel, ConfidenceLevelSchema, type ConfidenceSource, ConfidenceSourceSchema, type Corroboration, CorroborationSchema, DeployableUnit, type DispatchTable, type FindingSuppression, type FnIdentityKey, type GqlIdentityKey, type MatchResult, MessageBusSemantics, MessageBusTechnology, type MetricIdentityKey, type MetricSemantics, MetricSemanticsSchema, type NamePart, type ParsedChannel, type Reference, Semantics, type SemconvAttribute, type SemconvMapping, type SourceLocation, SourceLocationSchema, type SuppressableSeverity, type SuppressibleFinding, type SuppressionFile, SuppressionFileSchema, type SuppressionRule, SuppressionRuleSchema, TypeShape, applySuppressionsToFindings, bodyShapesMatch, boundaryKey, boundaryLabel, boundaryNameString, busIdentityKey, busesAgree, canPair, channelsPair, codeScopePath, countsForThreshold, dispatchByType, displayLabel, exchangesHttpResponses, fileInCodeScope, fixedTextLength, fnIdentityKey, formatChannel, functionCallBinding, gqlIdentityKey, graphqlOperationBinding, graphqlResolverBinding, hasNameHole, isGraphqlOperationBinding, messageBusBinding, metricBinding, metricIdentityKey, namePatternFromSub, namePatternKey, namesAgree, namesNothing, normalizeRuleBoundary, packageExportBinding, pairingKey, parseBoundaryName, parseChannel, patternHole, referenceFromName, referenceName, referenceOf, reportsUnpairedItself, restBinding, ruleBoundaryMatchesKey, runtimeConfigBinding, semanticsAgree, semconvAttributes, servesRequest, storageBinding, validateRule };