Skip to content

feat(cloud-assembly-schema): add policy validation report schema types#1515

Merged
rix0rrr merged 14 commits into
mainfrom
conroyka/validation-report-schema
May 20, 2026
Merged

feat(cloud-assembly-schema): add policy validation report schema types#1515
rix0rrr merged 14 commits into
mainfrom
conroyka/validation-report-schema

Conversation

@kaizencc
Copy link
Copy Markdown
Contributor

@kaizencc kaizencc commented May 14, 2026

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.

Corresponding types in aws-cdk-lib

These schema types mirror the structures defined in aws-cdk-lib:

Schema 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:

RFC requirement How it's satisfied
Severity grouping (Fatal/Error/Warning) PolicyViolationJson.severity is already present. CLI groups violations by severity at display time. Defaults to Warning if absent.
Source name (e.g. "ValidationEngine (Default)", "CdkNagValidator") Derivable from PluginReportJson.summary.pluginName
Suppression/acknowledge ID Derivable as ${pluginName}::${ruleName} (both fields present). Spaces replaced with dashes per aws-cdk#37808.
Suppress instruction Computed by CLI: Acknowledge '${pluginName}::${ruleName}'. Omitted for Fatal violations.
Summary counts Computed from violation arrays at render time
Source file location ViolatingConstructJson.constructStack.location
Construct path ViolatingConstructJson.constructPath

For Construct Annotations specifically, aws-cdk-lib (via #37808) converts annotations into PolicyViolation objects before writing the report — extracting the [ack: id] tag as ruleName and 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

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>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 14, 2026

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

@aws-cdk-automation aws-cdk-automation requested a review from a team May 14, 2026 17:22
* use `PolicyViolationSeverity.custom('critical')`.
*/
export class PolicyViolationSeverity {
static readonly ERROR = new PolicyViolationSeverity('error');
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the formalism here? Property names? JSON paths? What?

/**
* The logical ID of the resource in the CloudFormation template.
*/
readonly resourceLogicalId: string;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, this cannot be required.

*
* @default - no construct path
*/
readonly constructPath?: string;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why would we ever not have a construct path?

/**
* The construct ID.
*/
readonly id: string;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ID is unnecessary, it's the last part of teh path.

*
* @default - no construct info
*/
readonly construct?: string;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
readonly construct?: string;
readonly classFqn?: string;

readonly construct?: string;

/**
* The version of the library that contains this construct.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Library name and version? Or just version?

readonly libraryVersion?: string;

/**
* The source code location where this construct was created.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean stack trace?

/**
* A report from a single validation plugin.
*/
export interface PluginReportJson {
Copy link
Copy Markdown
Contributor

@rix0rrr rix0rrr May 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a lot of data in that struct that is not a stack trace though.

kaizencc and others added 5 commits May 19, 2026 09:58
…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 {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

kaizencc and others added 3 commits May 19, 2026 12:29
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants