feat(cloud-assembly-schema): add policy validation report schema types#1515
Conversation
Define the JSON schema types for `policy-validation-report.json` in the shared cloud-assembly-schema package. This file is written by aws-cdk-lib during synthesis and consumed by toolkit-lib's validate command. Having the types in the shared contract prevents drift between producer and consumer. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Dependency Review✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.Scanned FilesNone |
…t coverage threshold
| * use `PolicyViolationSeverity.custom('critical')`. | ||
| */ | ||
| export class PolicyViolationSeverity { | ||
| static readonly ERROR = new PolicyViolationSeverity('error'); |
There was a problem hiding this comment.
This is a schema library. We have no need of values, and I have a suspicion they will hinder more than they will help.
| readonly constructStack?: ConstructTraceJson; | ||
|
|
||
| /** | ||
| * Locations within the construct where the violation was detected. |
There was a problem hiding this comment.
What is the formalism here? Property names? JSON paths? What?
| /** | ||
| * The logical ID of the resource in the CloudFormation template. | ||
| */ | ||
| readonly resourceLogicalId: string; |
There was a problem hiding this comment.
Needs to be optional if this is about constructs.
(In fact: how do we have optional construct PATHS, but definitely logical IDs?)
| /** | ||
| * The path to the CloudFormation template containing this resource. | ||
| */ | ||
| readonly templatePath: string; |
There was a problem hiding this comment.
Same here, this cannot be required.
| * | ||
| * @default - no construct path | ||
| */ | ||
| readonly constructPath?: string; |
There was a problem hiding this comment.
Why would we ever not have a construct path?
| /** | ||
| * The construct ID. | ||
| */ | ||
| readonly id: string; |
There was a problem hiding this comment.
ID is unnecessary, it's the last part of teh path.
| * | ||
| * @default - no construct info | ||
| */ | ||
| readonly construct?: string; |
There was a problem hiding this comment.
| readonly construct?: string; | |
| readonly classFqn?: string; |
| readonly construct?: string; | ||
|
|
||
| /** | ||
| * The version of the library that contains this construct. |
There was a problem hiding this comment.
Library name and version? Or just version?
| readonly libraryVersion?: string; | ||
|
|
||
| /** | ||
| * The source code location where this construct was created. |
| /** | ||
| * A report from a single validation plugin. | ||
| */ | ||
| export interface PluginReportJson { |
There was a problem hiding this comment.
Should we not report on suppressions in here as well? cdk-nag needs that, doesn't it?
| readonly constructPath?: string; | ||
|
|
||
| /** | ||
| * The construct creation stack trace. |
There was a problem hiding this comment.
There is a lot of data in that struct that is not a stack trace though.
…SON schema validation Add validation-report.schema.json and a loadValidationReport() method on Manifest, following the same pattern as loadAssetManifest/loadIntegManifest. Consumers can now load and validate the policy validation report in one call.
Test valid reports load correctly, optional fields are preserved, and invalid reports (missing required fields, invalid enum values) throw validation errors.
…m validate() The validate() method's `asserts manifest is AssemblyManifest` narrowing caused type errors when loadManifest was used for non-AssemblyManifest schemas (like the validation report). Changed to `void` since validate is used purely for its side effect (throwing on invalid schemas).
| schema: jsonschema.Schema, | ||
| options?: LoadManifestOptions, | ||
| ): asserts manifest is assembly.AssemblyManifest { | ||
| ): void { |
There was a problem hiding this comment.
validate() is called in saveManifest and loadManifest for its side effect (throwing on invalid input). It happens to work for the other loaders because AssetManifest and IntegManifest both have version: string, making them structurally compatible with AssemblyManifest. We can't get it to work for PolicyValidationReportJson because it has no version field. The asserts narrowing isn't meant to be there — validate() validates against arbitrary schemas, not specifically AssemblyManifest
There was a problem hiding this comment.
Subsequent research shows me that we should actually have a version: string property if we want the policy report as part of the manifest. So I've added it in, and now this line would work as is. However, it's still wrong for many of the functions in Manifest, and just happens to work because they all share version: string. So I'm keeping this change
Add required `version` field to PolicyValidationReportJson, matching the pattern used by AssemblyManifest and AssetManifest. This enables the existing version compatibility check in Manifest.validate() and prepares the report for inclusion in the cloud assembly protocol.
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Define the JSON schema types for
policy-validation-report.jsonin the shared cloud-assembly-schema package. This file is written by aws-cdk-lib during synthesis and consumed by toolkit-lib's validate command. Having the types in the shared contract prevents drift between producer and consumer.Corresponding types in aws-cdk-lib
These schema types mirror the structures defined in aws-cdk-lib:
packages/aws-cdk-lib/core/lib/validation/validation.ts—IPolicyValidationPluginBeta1,PolicyViolationBeta1,PolicyViolatingResourceBeta1packages/aws-cdk-lib/core/lib/validation/private/report.ts— report formatting and JSON serializationSchema sufficiency for RFC 899
We evaluated whether schema changes are needed to support CDK Comprehensive Validation (RFC 899) and its proposed output format. The existing schema is sufficient — all data required by the RFC is either already present or derivable at display time:
PolicyViolationJson.severityis already present. CLI groups violations by severity at display time. Defaults to Warning if absent.PluginReportJson.summary.pluginName${pluginName}::${ruleName}(both fields present). Spaces replaced with dashes per aws-cdk#37808.Acknowledge '${pluginName}::${ruleName}'. Omitted for Fatal violations.ViolatingConstructJson.constructStack.locationViolatingConstructJson.constructPathFor Construct Annotations specifically, aws-cdk-lib (via #37808) converts annotations into
PolicyViolationobjects before writing the report — extracting the[ack: id]tag asruleNameand mapping the level to severity. By the time the CLI reads the report, it's already structured.No additional schema fields are needed. The RFC output is purely a CLI display concern.
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license