@suss/contract-aws-apigateway 0.33.0 → 0.34.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
@@ -1,14 +1,14 @@
1
1
  # @suss/contract-aws-apigateway
2
2
 
3
- Part of [suss](https://github.com/nimbuscloud-ai/suss), which reads both sides of every call in a repository and says where the two disagree.
3
+ Part of [suss](https://github.com/nimbuscloud-ai/suss), which reads both sides of every call in a repository and reports where the two disagree.
4
4
 
5
- Generate suss `BehavioralSummary[]` for AWS API Gateway resources (REST + HTTP API), independent of how they were deployed.
5
+ This package builds suss `BehavioralSummary[]` for AWS API Gateway resources (REST and HTTP API), however they were deployed.
6
6
 
7
7
  ## What this package is
8
8
 
9
- `@suss/contract-aws-apigateway` is a **resource-semantics stub**: given a normalized configuration, it knows what an API Gateway endpoint *does* (status codes, authorizer behavior, CORS preflight, throttling). It does **not** know how someone wrote that configuration; a manifest reader does that job (`@suss/contract-cloudformation`, future CDK/Terraform readers), parsing its source format and handing a normalized config to this package.
9
+ `@suss/contract-aws-apigateway` is a **resource-semantics stub**. Given a normalized configuration, it works out what an API Gateway endpoint *does*: its status codes, authorizer behavior, CORS preflight and throttling. It does **not** read the configuration as someone wrote it. A manifest reader does that: `@suss/contract-cloudformation` today, and `@suss/contract-serverless` through it. The reader parses its own source format and passes a normalized config to this package. `@suss/contract-terraform` exists, but it does not read API Gateway resources yet, and there is no CDK reader.
10
10
 
11
- This separation means: configure your API in CloudFormation, CDK, SAM, or Terraform, and the same resource semantics produce the same summary.
11
+ Because of that split, an API configured in CloudFormation, SAM or a `serverless.yml` gets the same resource semantics and the same summary. A CDK or Terraform reader would pass its config to the same code.
12
12
 
13
13
  ## Where it fits
14
14
 
@@ -17,15 +17,16 @@ packages/contract/
17
17
  openapi/ # Spec → summaries (declares what the API claims to be)
18
18
  aws-apigateway/ # Resource semantics: what AWS API Gateway actually does
19
19
  cloudformation/ # Manifest reader: walks CFN/SAM, builds configs, delegates here
20
+ serverless/ # Rewrites serverless.yml as SAM and hands it to cloudformation/
21
+ terraform/ # Reads Terraform; does not read API Gateway resources yet
20
22
  (future) cdk-synth/ # Same delegation pattern
21
- (future) terraform/ # Same delegation pattern
22
23
  ```
23
24
 
24
25
  ## Why configuration matters
25
26
 
26
- A handler that only returns `200` produces a *much* larger behavioral envelope once it's deployed behind API Gateway: an authorizer adds `401`/`403`, request validation adds `400`, throttling adds `429`, integration timeouts add `504`, CORS adds an `OPTIONS` preflight endpoint. Without modeling these, a consumer that handles `429` looks like it has a dead branch, when in reality the platform produces `429` even though the handler doesn't.
27
+ A handler that only returns `200` can respond in *many* more ways once it is deployed behind API Gateway. An authorizer adds `401`/`403`, request validation adds `400`, throttling adds `429`, integration timeouts add `504`, and CORS adds an `OPTIONS` preflight endpoint. If suss did not model these, a consumer that handles `429` would look like it had a dead branch, when the platform does produce `429` even though the handler never does.
27
28
 
28
- These transitions are emitted with `confidence.source: "derived"` and an opaque `Predicate` of the form `platform:apiGateway:<contract>`. Each transition's `metadata` records where the transition came from (which configuration field introduced it) for `inspect`/`diff` output, so consumers do not have to work out the platform cause themselves.
29
+ These transitions come out with `confidence.source: "derived"` and an opaque `Predicate` of the form `platform:apiGateway:<contract>`. Each transition's `metadata` records which configuration field introduced it, for `inspect`/`diff` output, so consumers do not have to work out the platform cause themselves.
29
30
 
30
31
  ## More
31
32
 
package/dist/index.cjs CHANGED
@@ -317,10 +317,6 @@ function buildRouteSummary(route, parsed, api, sourceFile) {
317
317
  statusCode
318
318
  }))
319
319
  },
320
- // Additive pointer to the code that implements this route (SAM
321
- // Lambda proxy Handler), so a checker can correlate the declared
322
- // route with the extracted handler summary carrying the same
323
- // REST binding.
324
320
  ...route.implementingHandler !== void 0 ? { implementingHandler: route.implementingHandler } : {}
325
321
  }
326
322
  )
@@ -483,13 +479,9 @@ function buildEndpointSummary(endpoint, api, sourceFile) {
483
479
  integrationType: endpoint.integration.type
484
480
  },
485
481
  {
486
- // The integration's declared status codes (from MethodResponses
487
- // in the CFN template) are the declared contract here.
488
- // Platform-injected transitions (authorizer 401/403, throttle
489
- // 429, etc.) come from SEPARATE config fields and so are
490
- // independent from this contract: contract-consistency
491
- // comparison is meaningful and will surface template-internal
492
- // inconsistencies.
482
+ // The platform's responses come from other settings than
483
+ // MethodResponses, so comparing them with this contract can find
484
+ // a template that contradicts itself.
493
485
  declaredContract: {
494
486
  framework: FRAMEWORK,
495
487
  provenance: "independent",
@@ -497,10 +489,6 @@ function buildEndpointSummary(endpoint, api, sourceFile) {
497
489
  statusCode
498
490
  }))
499
491
  },
500
- // Additive pointer to the code that implements this endpoint
501
- // (SAM Lambda proxy Handler), so a checker can correlate the
502
- // declared route with the extracted handler summary carrying the
503
- // same REST binding.
504
492
  ...endpoint.implementingHandler !== void 0 ? { implementingHandler: endpoint.implementingHandler } : {}
505
493
  }
506
494
  )
package/dist/index.d.cts CHANGED
@@ -1,11 +1,18 @@
1
1
  import { BehavioralSummary } from '@suss/behavioral-ir';
2
2
 
3
3
  /**
4
- * Reference back into the source manifest that introduced a piece of
5
- * configuration. Carried in `Transition.metadata.configRef` so inspect/
6
- * diff can attribute platform-injected transitions to the file + path
7
- * where the user authored them. Always emit an absolute file path; the
8
- * pointer is a JSON-Pointer-ish hint, intentionally not validated.
4
+ * The configuration a manifest reader builds and passes to
5
+ * restApiToSummaries or httpApiToSummaries, whatever format it read.
6
+ *
7
+ * Besides routes, it includes the settings that change behavior:
8
+ * authorizers, CORS, throttling and request validation. Each one adds
9
+ * responses the platform returns that no handler code shows.
10
+ */
11
+ /**
12
+ * Where in the source manifest a piece of configuration was written.
13
+ * Inspect and diff use it to point a platform-added response at the line
14
+ * that caused it. The file is always absolute, and the pointer is a hint
15
+ * in the style of a JSON Pointer that nothing validates.
9
16
  */
10
17
  interface ConfigRef {
11
18
  /** Absolute path to the source manifest file. */
@@ -14,20 +21,18 @@ interface ConfigRef {
14
21
  pointer: string;
15
22
  }
16
23
  /**
17
- * One of the well-known platform contracts that produce extra response
18
- * transitions. Used as the `cause` token in opaque predicates and as a
19
- * key for collapsing per-status transitions. Closed enum so the checker
20
- * and renderers can switch on it.
24
+ * The platform behaviors that add responses. Each value is the `cause` in
25
+ * a platform transition's metadata, and every cause that lands on one
26
+ * status code is merged into a single transition.
21
27
  */
22
28
  type PlatformCause = "authorization" | "api-key" | "request-validation" | "throttle" | "integration-timeout" | "integration-failure" | "cors-preflight";
23
29
  type AuthorizerType = "iam" | "cognito" | "lambda-token" | "lambda-request" | "jwt";
24
30
  interface AuthorizerConfig {
25
31
  type: AuthorizerType;
26
32
  /**
27
- * When true, missing/invalid credentials produce 401; authenticated
28
- * but denied produces 403. When false, the authorizer is configured
29
- * but anonymous calls bypass it (mostly relevant for public-fallback
30
- * IAM and Lambda authorizers with caching off).
33
+ * When true or unset, missing or invalid credentials return 401 and a
34
+ * denied caller gets 403. When false, anonymous calls pass the
35
+ * authorizer, so only 403 is added.
31
36
  */
32
37
  identitySourceRequired?: boolean;
33
38
  configRef?: ConfigRef;
@@ -53,22 +58,20 @@ interface RequestValidationConfig {
53
58
  configRef?: ConfigRef;
54
59
  }
55
60
  /**
56
- * Pointer from a declared route to the code that implements it. A
57
- * manifest reader (CFN/SAM, CDK, Terraform) fills this in when it knows
58
- * which module + export backs the route, e.g. a SAM Lambda proxy
59
- * integration whose `Handler` gives the file and export. The fields are
60
- * generic "where is the code" identity, not any one manifest's
61
- * semantics; `aws-apigateway` puts the pointer onto the summary
62
- * (`metadata.http.implementingHandler`) without interpreting it, so a
63
- * checker can later correlate the declared route with the extracted
64
- * handler summary with the same REST binding.
61
+ * The code that implements a declared route. A manifest reader fills it
62
+ * in when it can tell which module and export serve the route, as with a
63
+ * SAM Lambda proxy integration whose `Handler` gives both.
64
+ *
65
+ * This package copies it to `metadata.http.implementingHandler` without
66
+ * reading it, so the checker can match the declared route to the handler
67
+ * summary extracted from that code.
65
68
  */
66
69
  interface HandlerPointer {
67
70
  /** Raw handler reference, e.g. "src/handlers/confirmToken.handler". */
68
71
  handler: string;
69
72
  /** Module-path portion (before the final dot), e.g. "src/handlers/confirmToken". */
70
73
  modulePath: string;
71
- /** Exported symbol the handler names, e.g. "handler". */
74
+ /** The exported function, e.g. "handler". */
72
75
  exportName: string;
73
76
  /** Base directory the module path resolves against (SAM CodeUri). */
74
77
  codeUri?: string;
@@ -77,28 +80,24 @@ interface HandlerPointer {
77
80
  }
78
81
  type IntegrationType = "lambda" | "lambda-proxy" | "http" | "http-proxy" | "mock" | "aws-service" | "vpc-link"
79
82
  /**
80
- * The manifest declared an endpoint but didn't specify the integration
81
- * type. We can't claim 502/504 will fire without knowing what's behind
82
- * the route, so platform-failure transitions are suppressed for this
83
- * type. Used by manifest readers as a fallback rather than fabricating
84
- * a guessed integration.
83
+ * The manifest declared an endpoint without an integration type. A
84
+ * reader uses this in place of a guess, and no 502 or 504 is added,
85
+ * because nothing is known about the backend.
85
86
  */
86
87
  | "unknown";
87
88
  interface IntegrationConfig {
88
89
  type: IntegrationType;
89
90
  /**
90
- * Status codes the backend integration can produce. For proxy
91
- * integrations this is what the handler emits; for non-proxy it's
92
- * what `IntegrationResponses` map to. Empty array is allowed and
93
- * means "we don't know", only platform-injected transitions will
94
- * be emitted.
91
+ * Status codes the backend can return: what the handler returns for a
92
+ * proxy integration, or what `IntegrationResponses` map to otherwise.
93
+ * An empty array means they are unknown, and only the platform's
94
+ * responses are emitted.
95
95
  */
96
96
  statusCodes: number[];
97
97
  /**
98
- * REST API Gateway hard cap is 29s; HTTP API is 30s. When set,
99
- * a synthetic 504 is added if the integration could exceed it.
100
- * Default behavior: emit 504 unconditionally for lambda/http/aws-service
101
- * integrations because the timeout *can* fire.
98
+ * The integration timeout from the manifest. Summaries do not read it
99
+ * yet: a 504 is added for every integration that can time out, since
100
+ * the platform cap (29s for REST, 30s for HTTP APIs) always applies.
102
101
  */
103
102
  timeoutMs?: number;
104
103
  configRef?: ConfigRef;
@@ -109,38 +108,35 @@ interface RestEndpointConfig {
109
108
  path: string;
110
109
  integration: IntegrationConfig;
111
110
  /**
112
- * `null` (or undefined) means no authorizer. To opt out of an
113
- * inherited API-level default, pass `null` explicitly.
111
+ * Undefined inherits the API's default authorizer, and `null` turns it
112
+ * off for this endpoint.
114
113
  */
115
114
  authorizer?: AuthorizerConfig | null;
116
115
  apiKeyRequired?: boolean;
117
116
  requestValidation?: RequestValidationConfig;
118
117
  throttle?: ThrottleConfig;
119
- /**
120
- * Optional override label for the synthesized handler name. Defaults
121
- * to `${method.toUpperCase()} ${path}`.
122
- */
118
+ /** The summary's name. Defaults to `<api id>:<METHOD>:<path>`. */
123
119
  name?: string;
124
120
  /**
125
- * Code that implements this endpoint, when the manifest says which
126
- * (SAM Lambda proxy `Handler`). Emitted as
127
- * `metadata.http.implementingHandler`; purely additive.
121
+ * The code behind this endpoint, when the manifest says which, as a SAM
122
+ * Lambda proxy `Handler` does. Copied to
123
+ * `metadata.http.implementingHandler`.
128
124
  */
129
125
  implementingHandler?: HandlerPointer;
130
126
  configRef?: ConfigRef;
131
127
  }
132
128
  interface RestApiConfig {
133
- /** Logical identifier for the API (used in summary identity). */
129
+ /** The API's logical id, used in each summary's name. */
134
130
  id: string;
135
131
  /** Recorded as `SourceLocation.file` on each summary. */
136
132
  source?: string;
137
133
  endpoints: RestEndpointConfig[];
138
- /** API-level defaults that cascade onto endpoints unless overridden. */
134
+ /** Applies to every endpoint that does not set its own. */
139
135
  defaultAuthorizer?: AuthorizerConfig;
140
136
  defaultThrottle?: ThrottleConfig;
141
- /** API-level CORS: produces an OPTIONS endpoint per resource path. */
137
+ /** Adds an OPTIONS preflight summary for each resource path. */
142
138
  cors?: CorsConfig;
143
- /** Binary media types declared on the API; doesn't affect transitions. */
139
+ /** Recorded from the manifest. No transition depends on it. */
144
140
  binaryMediaTypes?: string[];
145
141
  }
146
142
  type HttpAuthorizerType = "jwt" | "lambda-request" | "iam";
@@ -151,9 +147,9 @@ interface HttpAuthorizerConfig {
151
147
  }
152
148
  interface HttpRouteConfig {
153
149
  /**
154
- * Route key in API Gateway's native form: `"<METHOD> <path>"`, or
155
- * `"$default"` for the catch-all route. The package re-parses this
156
- * to fill `BoundaryBinding.method` / `path`.
150
+ * API Gateway's route key, `"<METHOD> <path>"`, or `"$default"` for the
151
+ * catch-all route. The method and path in the binding are parsed from
152
+ * it, and a `$default` route gets no summary.
157
153
  */
158
154
  routeKey: string;
159
155
  integration: IntegrationConfig;
@@ -161,9 +157,9 @@ interface HttpRouteConfig {
161
157
  throttle?: ThrottleConfig;
162
158
  name?: string;
163
159
  /**
164
- * Code that implements this route, when the manifest says which (SAM
165
- * Lambda proxy `Handler`). Emitted as
166
- * `metadata.http.implementingHandler`; purely additive.
160
+ * The code behind this route, when the manifest says which, as a SAM
161
+ * Lambda proxy `Handler` does. Copied to
162
+ * `metadata.http.implementingHandler`.
167
163
  */
168
164
  implementingHandler?: HandlerPointer;
169
165
  configRef?: ConfigRef;
@@ -177,8 +173,19 @@ interface HttpApiConfig {
177
173
  cors?: CorsConfig;
178
174
  }
179
175
 
176
+ /**
177
+ * Turns an HttpApiConfig (API Gateway v2) into one summary per route. The
178
+ * platform adds the same status codes as for a REST API, except that an
179
+ * HTTP API has no API keys and no request validation.
180
+ */
181
+
180
182
  declare function httpApiToSummaries(config: HttpApiConfig): BehavioralSummary[];
181
183
 
184
+ /**
185
+ * Turns a RestApiConfig into one summary per endpoint, adding the
186
+ * responses API Gateway v1 (REST) returns for each configuration setting.
187
+ */
188
+
182
189
  declare function restApiToSummaries(config: RestApiConfig): BehavioralSummary[];
183
190
 
184
191
  export { type AuthorizerConfig, type AuthorizerType, type ConfigRef, type CorsConfig, type HandlerPointer, type HttpApiConfig, type HttpAuthorizerConfig, type HttpAuthorizerType, type HttpRouteConfig, type IntegrationConfig, type IntegrationType, type PlatformCause, type RequestValidationConfig, type RestApiConfig, type RestEndpointConfig, type ThrottleConfig, httpApiToSummaries, restApiToSummaries };
package/dist/index.d.ts CHANGED
@@ -1,11 +1,18 @@
1
1
  import { BehavioralSummary } from '@suss/behavioral-ir';
2
2
 
3
3
  /**
4
- * Reference back into the source manifest that introduced a piece of
5
- * configuration. Carried in `Transition.metadata.configRef` so inspect/
6
- * diff can attribute platform-injected transitions to the file + path
7
- * where the user authored them. Always emit an absolute file path; the
8
- * pointer is a JSON-Pointer-ish hint, intentionally not validated.
4
+ * The configuration a manifest reader builds and passes to
5
+ * restApiToSummaries or httpApiToSummaries, whatever format it read.
6
+ *
7
+ * Besides routes, it includes the settings that change behavior:
8
+ * authorizers, CORS, throttling and request validation. Each one adds
9
+ * responses the platform returns that no handler code shows.
10
+ */
11
+ /**
12
+ * Where in the source manifest a piece of configuration was written.
13
+ * Inspect and diff use it to point a platform-added response at the line
14
+ * that caused it. The file is always absolute, and the pointer is a hint
15
+ * in the style of a JSON Pointer that nothing validates.
9
16
  */
10
17
  interface ConfigRef {
11
18
  /** Absolute path to the source manifest file. */
@@ -14,20 +21,18 @@ interface ConfigRef {
14
21
  pointer: string;
15
22
  }
16
23
  /**
17
- * One of the well-known platform contracts that produce extra response
18
- * transitions. Used as the `cause` token in opaque predicates and as a
19
- * key for collapsing per-status transitions. Closed enum so the checker
20
- * and renderers can switch on it.
24
+ * The platform behaviors that add responses. Each value is the `cause` in
25
+ * a platform transition's metadata, and every cause that lands on one
26
+ * status code is merged into a single transition.
21
27
  */
22
28
  type PlatformCause = "authorization" | "api-key" | "request-validation" | "throttle" | "integration-timeout" | "integration-failure" | "cors-preflight";
23
29
  type AuthorizerType = "iam" | "cognito" | "lambda-token" | "lambda-request" | "jwt";
24
30
  interface AuthorizerConfig {
25
31
  type: AuthorizerType;
26
32
  /**
27
- * When true, missing/invalid credentials produce 401; authenticated
28
- * but denied produces 403. When false, the authorizer is configured
29
- * but anonymous calls bypass it (mostly relevant for public-fallback
30
- * IAM and Lambda authorizers with caching off).
33
+ * When true or unset, missing or invalid credentials return 401 and a
34
+ * denied caller gets 403. When false, anonymous calls pass the
35
+ * authorizer, so only 403 is added.
31
36
  */
32
37
  identitySourceRequired?: boolean;
33
38
  configRef?: ConfigRef;
@@ -53,22 +58,20 @@ interface RequestValidationConfig {
53
58
  configRef?: ConfigRef;
54
59
  }
55
60
  /**
56
- * Pointer from a declared route to the code that implements it. A
57
- * manifest reader (CFN/SAM, CDK, Terraform) fills this in when it knows
58
- * which module + export backs the route, e.g. a SAM Lambda proxy
59
- * integration whose `Handler` gives the file and export. The fields are
60
- * generic "where is the code" identity, not any one manifest's
61
- * semantics; `aws-apigateway` puts the pointer onto the summary
62
- * (`metadata.http.implementingHandler`) without interpreting it, so a
63
- * checker can later correlate the declared route with the extracted
64
- * handler summary with the same REST binding.
61
+ * The code that implements a declared route. A manifest reader fills it
62
+ * in when it can tell which module and export serve the route, as with a
63
+ * SAM Lambda proxy integration whose `Handler` gives both.
64
+ *
65
+ * This package copies it to `metadata.http.implementingHandler` without
66
+ * reading it, so the checker can match the declared route to the handler
67
+ * summary extracted from that code.
65
68
  */
66
69
  interface HandlerPointer {
67
70
  /** Raw handler reference, e.g. "src/handlers/confirmToken.handler". */
68
71
  handler: string;
69
72
  /** Module-path portion (before the final dot), e.g. "src/handlers/confirmToken". */
70
73
  modulePath: string;
71
- /** Exported symbol the handler names, e.g. "handler". */
74
+ /** The exported function, e.g. "handler". */
72
75
  exportName: string;
73
76
  /** Base directory the module path resolves against (SAM CodeUri). */
74
77
  codeUri?: string;
@@ -77,28 +80,24 @@ interface HandlerPointer {
77
80
  }
78
81
  type IntegrationType = "lambda" | "lambda-proxy" | "http" | "http-proxy" | "mock" | "aws-service" | "vpc-link"
79
82
  /**
80
- * The manifest declared an endpoint but didn't specify the integration
81
- * type. We can't claim 502/504 will fire without knowing what's behind
82
- * the route, so platform-failure transitions are suppressed for this
83
- * type. Used by manifest readers as a fallback rather than fabricating
84
- * a guessed integration.
83
+ * The manifest declared an endpoint without an integration type. A
84
+ * reader uses this in place of a guess, and no 502 or 504 is added,
85
+ * because nothing is known about the backend.
85
86
  */
86
87
  | "unknown";
87
88
  interface IntegrationConfig {
88
89
  type: IntegrationType;
89
90
  /**
90
- * Status codes the backend integration can produce. For proxy
91
- * integrations this is what the handler emits; for non-proxy it's
92
- * what `IntegrationResponses` map to. Empty array is allowed and
93
- * means "we don't know", only platform-injected transitions will
94
- * be emitted.
91
+ * Status codes the backend can return: what the handler returns for a
92
+ * proxy integration, or what `IntegrationResponses` map to otherwise.
93
+ * An empty array means they are unknown, and only the platform's
94
+ * responses are emitted.
95
95
  */
96
96
  statusCodes: number[];
97
97
  /**
98
- * REST API Gateway hard cap is 29s; HTTP API is 30s. When set,
99
- * a synthetic 504 is added if the integration could exceed it.
100
- * Default behavior: emit 504 unconditionally for lambda/http/aws-service
101
- * integrations because the timeout *can* fire.
98
+ * The integration timeout from the manifest. Summaries do not read it
99
+ * yet: a 504 is added for every integration that can time out, since
100
+ * the platform cap (29s for REST, 30s for HTTP APIs) always applies.
102
101
  */
103
102
  timeoutMs?: number;
104
103
  configRef?: ConfigRef;
@@ -109,38 +108,35 @@ interface RestEndpointConfig {
109
108
  path: string;
110
109
  integration: IntegrationConfig;
111
110
  /**
112
- * `null` (or undefined) means no authorizer. To opt out of an
113
- * inherited API-level default, pass `null` explicitly.
111
+ * Undefined inherits the API's default authorizer, and `null` turns it
112
+ * off for this endpoint.
114
113
  */
115
114
  authorizer?: AuthorizerConfig | null;
116
115
  apiKeyRequired?: boolean;
117
116
  requestValidation?: RequestValidationConfig;
118
117
  throttle?: ThrottleConfig;
119
- /**
120
- * Optional override label for the synthesized handler name. Defaults
121
- * to `${method.toUpperCase()} ${path}`.
122
- */
118
+ /** The summary's name. Defaults to `<api id>:<METHOD>:<path>`. */
123
119
  name?: string;
124
120
  /**
125
- * Code that implements this endpoint, when the manifest says which
126
- * (SAM Lambda proxy `Handler`). Emitted as
127
- * `metadata.http.implementingHandler`; purely additive.
121
+ * The code behind this endpoint, when the manifest says which, as a SAM
122
+ * Lambda proxy `Handler` does. Copied to
123
+ * `metadata.http.implementingHandler`.
128
124
  */
129
125
  implementingHandler?: HandlerPointer;
130
126
  configRef?: ConfigRef;
131
127
  }
132
128
  interface RestApiConfig {
133
- /** Logical identifier for the API (used in summary identity). */
129
+ /** The API's logical id, used in each summary's name. */
134
130
  id: string;
135
131
  /** Recorded as `SourceLocation.file` on each summary. */
136
132
  source?: string;
137
133
  endpoints: RestEndpointConfig[];
138
- /** API-level defaults that cascade onto endpoints unless overridden. */
134
+ /** Applies to every endpoint that does not set its own. */
139
135
  defaultAuthorizer?: AuthorizerConfig;
140
136
  defaultThrottle?: ThrottleConfig;
141
- /** API-level CORS: produces an OPTIONS endpoint per resource path. */
137
+ /** Adds an OPTIONS preflight summary for each resource path. */
142
138
  cors?: CorsConfig;
143
- /** Binary media types declared on the API; doesn't affect transitions. */
139
+ /** Recorded from the manifest. No transition depends on it. */
144
140
  binaryMediaTypes?: string[];
145
141
  }
146
142
  type HttpAuthorizerType = "jwt" | "lambda-request" | "iam";
@@ -151,9 +147,9 @@ interface HttpAuthorizerConfig {
151
147
  }
152
148
  interface HttpRouteConfig {
153
149
  /**
154
- * Route key in API Gateway's native form: `"<METHOD> <path>"`, or
155
- * `"$default"` for the catch-all route. The package re-parses this
156
- * to fill `BoundaryBinding.method` / `path`.
150
+ * API Gateway's route key, `"<METHOD> <path>"`, or `"$default"` for the
151
+ * catch-all route. The method and path in the binding are parsed from
152
+ * it, and a `$default` route gets no summary.
157
153
  */
158
154
  routeKey: string;
159
155
  integration: IntegrationConfig;
@@ -161,9 +157,9 @@ interface HttpRouteConfig {
161
157
  throttle?: ThrottleConfig;
162
158
  name?: string;
163
159
  /**
164
- * Code that implements this route, when the manifest says which (SAM
165
- * Lambda proxy `Handler`). Emitted as
166
- * `metadata.http.implementingHandler`; purely additive.
160
+ * The code behind this route, when the manifest says which, as a SAM
161
+ * Lambda proxy `Handler` does. Copied to
162
+ * `metadata.http.implementingHandler`.
167
163
  */
168
164
  implementingHandler?: HandlerPointer;
169
165
  configRef?: ConfigRef;
@@ -177,8 +173,19 @@ interface HttpApiConfig {
177
173
  cors?: CorsConfig;
178
174
  }
179
175
 
176
+ /**
177
+ * Turns an HttpApiConfig (API Gateway v2) into one summary per route. The
178
+ * platform adds the same status codes as for a REST API, except that an
179
+ * HTTP API has no API keys and no request validation.
180
+ */
181
+
180
182
  declare function httpApiToSummaries(config: HttpApiConfig): BehavioralSummary[];
181
183
 
184
+ /**
185
+ * Turns a RestApiConfig into one summary per endpoint, adding the
186
+ * responses API Gateway v1 (REST) returns for each configuration setting.
187
+ */
188
+
182
189
  declare function restApiToSummaries(config: RestApiConfig): BehavioralSummary[];
183
190
 
184
191
  export { type AuthorizerConfig, type AuthorizerType, type ConfigRef, type CorsConfig, type HandlerPointer, type HttpApiConfig, type HttpAuthorizerConfig, type HttpAuthorizerType, type HttpRouteConfig, type IntegrationConfig, type IntegrationType, type PlatformCause, type RequestValidationConfig, type RestApiConfig, type RestEndpointConfig, type ThrottleConfig, httpApiToSummaries, restApiToSummaries };
package/dist/index.js CHANGED
@@ -290,10 +290,6 @@ function buildRouteSummary(route, parsed, api, sourceFile) {
290
290
  statusCode
291
291
  }))
292
292
  },
293
- // Additive pointer to the code that implements this route (SAM
294
- // Lambda proxy Handler), so a checker can correlate the declared
295
- // route with the extracted handler summary carrying the same
296
- // REST binding.
297
293
  ...route.implementingHandler !== void 0 ? { implementingHandler: route.implementingHandler } : {}
298
294
  }
299
295
  )
@@ -456,13 +452,9 @@ function buildEndpointSummary(endpoint, api, sourceFile) {
456
452
  integrationType: endpoint.integration.type
457
453
  },
458
454
  {
459
- // The integration's declared status codes (from MethodResponses
460
- // in the CFN template) are the declared contract here.
461
- // Platform-injected transitions (authorizer 401/403, throttle
462
- // 429, etc.) come from SEPARATE config fields and so are
463
- // independent from this contract: contract-consistency
464
- // comparison is meaningful and will surface template-internal
465
- // inconsistencies.
455
+ // The platform's responses come from other settings than
456
+ // MethodResponses, so comparing them with this contract can find
457
+ // a template that contradicts itself.
466
458
  declaredContract: {
467
459
  framework: FRAMEWORK,
468
460
  provenance: "independent",
@@ -470,10 +462,6 @@ function buildEndpointSummary(endpoint, api, sourceFile) {
470
462
  statusCode
471
463
  }))
472
464
  },
473
- // Additive pointer to the code that implements this endpoint
474
- // (SAM Lambda proxy Handler), so a checker can correlate the
475
- // declared route with the extracted handler summary carrying the
476
- // same REST binding.
477
465
  ...endpoint.implementingHandler !== void 0 ? { implementingHandler: endpoint.implementingHandler } : {}
478
466
  }
479
467
  )
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@suss/contract-aws-apigateway",
3
- "version": "0.33.0",
3
+ "version": "0.34.0",
4
4
  "type": "module",
5
5
  "description": "Turn an AWS API Gateway REST or HTTP API into a suss contract and check it against the Lambda handlers and clients that use it.",
6
6
  "keywords": [
@@ -14,7 +14,7 @@
14
14
  ],
15
15
  "license": "Apache-2.0",
16
16
  "author": "Nimbus Cloud AI LLC",
17
- "homepage": "https://github.com/nimbuscloud-ai/suss/tree/main/packages/contract/aws-apigateway#readme",
17
+ "homepage": "https://suss.sh",
18
18
  "repository": {
19
19
  "type": "git",
20
20
  "url": "git+https://github.com/nimbuscloud-ai/suss.git",
@@ -47,7 +47,7 @@
47
47
  "typecheck": "tsc --noEmit"
48
48
  },
49
49
  "dependencies": {
50
- "@suss/behavioral-ir": "0.33.0"
50
+ "@suss/behavioral-ir": "0.34.0"
51
51
  },
52
52
  "devDependencies": {
53
53
  "tsup": "*",