@intentius/chant-lexicon-aws 0.124.31 → 0.124.32
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/actions/dynamodb.js +41 -0
- package/dist/actions/ecr.js +9 -0
- package/dist/actions/ecs.js +5 -0
- package/dist/actions/iam.js +3 -0
- package/dist/actions/index.js +9 -0
- package/dist/actions/lambda.js +11 -0
- package/dist/actions/logs.js +4 -0
- package/dist/actions/s3.js +40 -0
- package/dist/actions/sns.js +5 -0
- package/dist/actions/sqs.js +15 -0
- package/dist/agentcore/trace-fetch.d.ts.map +1 -1
- package/dist/agentcore/trace-fetch.js +472 -0
- package/dist/agentcore/trace-render.js +359 -0
- package/dist/ambient.js +148 -0
- package/dist/api/credential-chain.d.ts +30 -3
- package/dist/api/credential-chain.d.ts.map +1 -1
- package/dist/api/credential-chain.js +509 -0
- package/dist/api/read-client.d.ts +16 -43
- package/dist/api/read-client.d.ts.map +1 -1
- package/dist/api/read-client.js +458 -0
- package/dist/api/sigv4.d.ts +4 -4
- package/dist/api/sigv4.js +185 -0
- package/dist/behaviour-kinds.js +114 -0
- package/dist/caller-identity.d.ts +3 -5
- package/dist/caller-identity.d.ts.map +1 -1
- package/dist/caller-identity.js +146 -0
- package/dist/codegen/docs-cli.js +2 -0
- package/dist/codegen/docs.js +120 -0
- package/dist/codegen/enum-overlay.js +162 -0
- package/dist/codegen/extensions.js +139 -0
- package/dist/codegen/fallback.js +32 -0
- package/dist/codegen/generate-cli.js +15 -0
- package/dist/codegen/generate-lexicon.js +70 -0
- package/dist/codegen/generate-typescript.js +226 -0
- package/dist/codegen/generate.d.ts.map +1 -1
- package/dist/codegen/generate.js +234 -0
- package/dist/codegen/naming.js +135 -0
- package/dist/codegen/package.js +67 -0
- package/dist/codegen/patches.d.ts +26 -1
- package/dist/codegen/patches.d.ts.map +1 -1
- package/dist/codegen/patches.js +90 -0
- package/dist/codegen/property-overlay.js +85 -0
- package/dist/codegen/property-overlay.json +1 -16
- package/dist/codegen/sam.js +402 -0
- package/dist/codegen/typecheck.js +4 -0
- package/dist/codegen/versions.js +31 -0
- package/dist/components/__tests__/mock-cloud-executor.js +326 -0
- package/dist/components/apply.d.ts +44 -1
- package/dist/components/apply.d.ts.map +1 -1
- package/dist/components/apply.js +752 -0
- package/dist/components/builders.js +37 -0
- package/dist/components/capability-plugin.js +66 -0
- package/dist/components/cloud-executor.d.ts +35 -0
- package/dist/components/cloud-executor.d.ts.map +1 -1
- package/dist/components/cloud-executor.js +576 -0
- package/dist/components/config-bom.js +207 -0
- package/dist/components/host-delivery.js +117 -0
- package/dist/components/index.js +18 -0
- package/dist/components/job-submission.js +77 -0
- package/dist/components/publish.js +234 -0
- package/dist/components/safety.js +62 -0
- package/dist/components/wait-aws.js +68 -0
- package/dist/composites/agentcore-agent.js +187 -0
- package/dist/composites/agentcore-trust-policy.js +13 -0
- package/dist/composites/alb-shared.js +84 -0
- package/dist/composites/bucket-deployment.js +93 -0
- package/dist/composites/catalog.js +2714 -0
- package/dist/composites/dynamodb-table.js +66 -0
- package/dist/composites/ec2-instance-bundle.js +75 -0
- package/dist/composites/ec2-instance-role.js +26 -0
- package/dist/composites/ecr-repository.js +64 -0
- package/dist/composites/ecs-trust-policy.js +10 -0
- package/dist/composites/efs-with-access-point.js +44 -0
- package/dist/composites/eks-cluster.js +118 -0
- package/dist/composites/fargate-alb.js +216 -0
- package/dist/composites/fargate-service.js +222 -0
- package/dist/composites/index.js +28 -0
- package/dist/composites/lambda-api.js +15 -0
- package/dist/composites/lambda-dynamodb.js +77 -0
- package/dist/composites/lambda-eventbridge.js +27 -0
- package/dist/composites/lambda-function.js +54 -0
- package/dist/composites/lambda-s3.js +93 -0
- package/dist/composites/lambda-sns.js +23 -0
- package/dist/composites/lambda-sqs.js +34 -0
- package/dist/composites/landing-zone.js +82 -0
- package/dist/composites/microvm-app.js +293 -0
- package/dist/composites/minimal-vpc.js +40 -0
- package/dist/composites/monitoring-stack.js +105 -0
- package/dist/composites/nlb-service.js +61 -0
- package/dist/composites/rds-instance.js +98 -0
- package/dist/composites/scheduled-lambda.js +28 -0
- package/dist/composites/solr-fargate-service.js +33 -0
- package/dist/composites/step-functions-workflow.js +78 -0
- package/dist/composites/vpc-default.js +132 -0
- package/dist/condition.js +43 -0
- package/dist/coverage.js +4 -0
- package/dist/deep-observe.d.ts.map +1 -1
- package/dist/deep-observe.js +709 -0
- package/dist/deep-topology.js +226 -0
- package/dist/default-tags.js +50 -0
- package/dist/defaults.js +85 -0
- package/dist/dependencies.js +269 -0
- package/dist/detect.js +21 -0
- package/dist/disruption.d.ts.map +1 -1
- package/dist/disruption.js +129 -0
- package/dist/effect-receipt-row.js +107 -0
- package/dist/generated/index.d.ts +1297 -82
- package/dist/generated/index.d.ts.map +1 -1
- package/dist/generated/index.js +12382 -0
- package/dist/generated/runtime.js +4 -0
- package/dist/governance.js +131 -0
- package/dist/identity-observe.d.ts.map +1 -1
- package/dist/identity-observe.js +127 -0
- package/dist/import/generator.js +757 -0
- package/dist/import/live-export.js +34 -0
- package/dist/import/parser.js +394 -0
- package/dist/index.js +69 -0
- package/dist/integrity.json +6 -6
- package/dist/intrinsics.js +393 -0
- package/dist/lint/audit-catalog.js +87 -0
- package/dist/lint/audit-lineage.js +150 -0
- package/dist/lint/post-synth/cf-refs.js +247 -0
- package/dist/lint/post-synth/cor020.js +60 -0
- package/dist/lint/post-synth/ext001.d.ts.map +1 -1
- package/dist/lint/post-synth/ext001.js +197 -0
- package/dist/lint/post-synth/index.js +124 -0
- package/dist/lint/post-synth/waw010.js +41 -0
- package/dist/lint/post-synth/waw011.js +41 -0
- package/dist/lint/post-synth/waw013.js +38 -0
- package/dist/lint/post-synth/waw014.js +42 -0
- package/dist/lint/post-synth/waw015.js +88 -0
- package/dist/lint/post-synth/waw016.d.ts.map +1 -1
- package/dist/lint/post-synth/waw016.js +116 -0
- package/dist/lint/post-synth/waw017.js +43 -0
- package/dist/lint/post-synth/waw018.js +61 -0
- package/dist/lint/post-synth/waw019.js +64 -0
- package/dist/lint/post-synth/waw020.js +56 -0
- package/dist/lint/post-synth/waw021.js +44 -0
- package/dist/lint/post-synth/waw022.js +36 -0
- package/dist/lint/post-synth/waw023.js +40 -0
- package/dist/lint/post-synth/waw024.js +46 -0
- package/dist/lint/post-synth/waw025.js +36 -0
- package/dist/lint/post-synth/waw026.js +38 -0
- package/dist/lint/post-synth/waw027.js +41 -0
- package/dist/lint/post-synth/waw028.js +39 -0
- package/dist/lint/post-synth/waw029.js +54 -0
- package/dist/lint/post-synth/waw030.js +282 -0
- package/dist/lint/post-synth/waw031.js +58 -0
- package/dist/lint/post-synth/waw032.js +45 -0
- package/dist/lint/post-synth/waw033.js +75 -0
- package/dist/lint/post-synth/waw034.js +52 -0
- package/dist/lint/post-synth/waw035.js +56 -0
- package/dist/lint/post-synth/waw036.js +79 -0
- package/dist/lint/post-synth/waw037.js +67 -0
- package/dist/lint/post-synth/waw038.js +42 -0
- package/dist/lint/post-synth/waw039.js +42 -0
- package/dist/lint/post-synth/waw040.js +45 -0
- package/dist/lint/post-synth/waw041.js +40 -0
- package/dist/lint/post-synth/waw042.js +99 -0
- package/dist/lint/post-synth/waw043.js +51 -0
- package/dist/lint/post-synth/waw044.js +64 -0
- package/dist/lint/post-synth/waw045.js +49 -0
- package/dist/lint/post-synth/waw046.js +52 -0
- package/dist/lint/post-synth/waw047.js +43 -0
- package/dist/lint/post-synth/waw048.js +40 -0
- package/dist/lint/post-synth/waw049.js +78 -0
- package/dist/lint/post-synth/waw050.js +44 -0
- package/dist/lint/post-synth/waw051.js +41 -0
- package/dist/lint/post-synth/waw052.js +43 -0
- package/dist/lint/post-synth/waw053.js +43 -0
- package/dist/lint/post-synth/waw054.js +41 -0
- package/dist/lint/post-synth/waw055.js +41 -0
- package/dist/lint/post-synth/waw056.js +65 -0
- package/dist/lint/post-synth/waw057.js +43 -0
- package/dist/lint/post-synth/waw058.js +61 -0
- package/dist/lint/post-synth/waw059.js +338 -0
- package/dist/lint/post-synth/waw060.js +83 -0
- package/dist/lint/post-synth/waw061.js +60 -0
- package/dist/lint/post-synth/waw062.js +0 -0
- package/dist/lint/post-synth/waw063.js +0 -0
- package/dist/lint/post-synth/waw064.js +45 -0
- package/dist/lint/post-synth/waw065.js +104 -0
- package/dist/lint/post-synth/waw066.js +145 -0
- package/dist/lint/post-synth/waw067.js +115 -0
- package/dist/lint/post-synth/waw068.js +69 -0
- package/dist/lint/post-synth/waw069.js +0 -0
- package/dist/lint/rules/hardcoded-region.js +38 -0
- package/dist/lint/rules/iam-wildcard.js +60 -0
- package/dist/lint/rules/index.js +6 -0
- package/dist/lint/rules/s3-encryption.js +60 -0
- package/dist/live-attrs.js +42 -0
- package/dist/lsp/completions.d.ts.map +1 -1
- package/dist/lsp/completions.js +18 -0
- package/dist/lsp/hover.d.ts.map +1 -1
- package/dist/lsp/hover.js +66 -0
- package/dist/manifest.json +1 -1
- package/dist/mapping.js +33 -0
- package/dist/meta.json +17359 -784
- package/dist/nested-stack.js +95 -0
- package/dist/okf/index.md +203 -0
- package/dist/okf/rules/EXT001.md +1 -0
- package/dist/okf/rules/WAW016.md +2 -0
- package/dist/okf/rules/WAW019.md +1 -0
- package/dist/okf/rules/WAW028.md +1 -0
- package/dist/okf/rules/WAW030.md +2 -0
- package/dist/okf/rules/WAW039.md +1 -0
- package/dist/okf/rules/WAW049.md +1 -0
- package/dist/okf/rules/WAW056.md +1 -0
- package/dist/okf/rules/WAW058.md +1 -0
- package/dist/okf/rules/WAW062.md +1 -0
- package/dist/okf/rules/WAW064.md +1 -0
- package/dist/okf/rules/WAW065.md +1 -0
- package/dist/okf/rules/WAW066.md +1 -0
- package/dist/okf/rules/WAW067.md +1 -0
- package/dist/okf/rules/WAW068.md +1 -0
- package/dist/okf/rules/WAW069.md +4 -0
- package/dist/okf/types/AIWorkloadConfig.md +23 -0
- package/dist/okf/types/ARCRegionSwitchPlan.md +1 -0
- package/dist/okf/types/AccountAccessApplication.md +28 -0
- package/dist/okf/types/AccountAccessEntitlement.md +22 -0
- package/dist/okf/types/ActionTarget.md +20 -0
- package/dist/okf/types/AdConfiguration.md +21 -0
- package/dist/okf/types/Adapter.md +26 -0
- package/dist/okf/types/AgentContext.md +35 -0
- package/dist/okf/types/AgentGoal.md +31 -0
- package/dist/okf/types/AgentProfile.md +34 -0
- package/dist/okf/types/Alarm.md +3 -1
- package/dist/okf/types/AlarmModel.md +14 -9
- package/dist/okf/types/AmplifyWebhook.md +25 -0
- package/dist/okf/types/ApiCache.md +8 -8
- package/dist/okf/types/ApiGatewayManagedOverrides.md +5 -5
- package/dist/okf/types/AppAuthorization.md +35 -0
- package/dist/okf/types/AppBlockBuilder.md +1 -0
- package/dist/okf/types/AppInstance.md +2 -2
- package/dist/okf/types/AppInstanceBot.md +2 -2
- package/dist/okf/types/AppStreamFleet.md +3 -2
- package/dist/okf/types/AppSyncApiKey.md +6 -6
- package/dist/okf/types/AppSyncType.md +22 -0
- package/dist/okf/types/ApplicationStatusCheck.md +36 -0
- package/dist/okf/types/ApplicationVersion.md +4 -1
- package/dist/okf/types/ApplicationsList.md +26 -0
- package/dist/okf/types/ApprovalPolicy.md +28 -0
- package/dist/okf/types/ArchiveRule.md +24 -0
- package/dist/okf/types/Asset.md +30 -0
- package/dist/okf/types/Backup.md +31 -0
- package/dist/okf/types/BedrockAgentCoreDataset.md +1 -1
- package/dist/okf/types/BedrockAgentCoreGateway.md +3 -0
- package/dist/okf/types/BedrockSession.md +28 -0
- package/dist/okf/types/BillEstimate.md +35 -0
- package/dist/okf/types/Brand.md +32 -0
- package/dist/okf/types/CallAnalyticsCategory.md +25 -0
- package/dist/okf/types/Campaign.md +28 -0
- package/dist/okf/types/CapacityProvider.md +30 -0
- package/dist/okf/types/Case.md +24 -0
- package/dist/okf/types/CertificateAssociation.md +13 -0
- package/dist/okf/types/ChangeSet.md +36 -0
- package/dist/okf/types/ChannelFlow.md +29 -0
- package/dist/okf/types/ChimeChannel.md +39 -0
- package/dist/okf/types/Classifier.md +6 -6
- package/dist/okf/types/ClientVpnAuthorizationRule.md +6 -6
- package/dist/okf/types/ClientVpnEndpoint.md +2 -0
- package/dist/okf/types/ClientVpnRoute.md +5 -5
- package/dist/okf/types/CloudConnector.md +29 -0
- package/dist/okf/types/Cluster.md +39 -0
- package/dist/okf/types/ClusterSchedulerConfig.md +30 -0
- package/dist/okf/types/CodeCommitRepository.md +12 -12
- package/dist/okf/types/CodeConnectionsHost.md +26 -0
- package/dist/okf/types/CodeRepository.md +5 -5
- package/dist/okf/types/CompositeAlarm.md +1 -0
- package/dist/okf/types/ComputeEnvironment.md +2 -0
- package/dist/okf/types/ComputeNodeGroup.md +1 -1
- package/dist/okf/types/ComputeQuota.md +34 -0
- package/dist/okf/types/ConfigRule.md +1 -1
- package/dist/okf/types/ConfigurationRecorder.md +7 -6
- package/dist/okf/types/ConnectAttachment.md +2 -0
- package/dist/okf/types/ConnectQueue.md +5 -1
- package/dist/okf/types/ConnectVocabulary.md +28 -0
- package/dist/okf/types/ConnectionType.md +24 -0
- package/dist/okf/types/ConsentPortal.md +33 -0
- package/dist/okf/types/ContactMethod.md +29 -0
- package/dist/okf/types/ContainerAssociation.md +26 -0
- package/dist/okf/types/ContainerFleet.md +1 -1
- package/dist/okf/types/ContainerGroupDefinition.md +1 -1
- package/dist/okf/types/Content.md +40 -0
- package/dist/okf/types/ContentAssociation.md +28 -0
- package/dist/okf/types/CustomDetectionRuleAssociation.md +28 -0
- package/dist/okf/types/CustomEntityType.md +4 -9
- package/dist/okf/types/Customization.md +22 -0
- package/dist/okf/types/CwIntegration.md +31 -0
- package/dist/okf/types/DAXParameterGroup.md +3 -8
- package/dist/okf/types/DAXSubnetGroup.md +0 -5
- package/dist/okf/types/DBClusterEndpoint.md +31 -0
- package/dist/okf/types/DBProxyTargetGroup.md +1 -0
- package/dist/okf/types/DBSnapshot.md +62 -0
- package/dist/okf/types/DLMLifecyclePolicy.md +12 -12
- package/dist/okf/types/DLPSetting.md +31 -0
- package/dist/okf/types/DMSInstanceProfile.md +1 -1
- package/dist/okf/types/DRSLaunchConfigurationTemplate.md +28 -0
- package/dist/okf/types/Daemon.md +1 -0
- package/dist/okf/types/DataExchangeDataSet.md +29 -0
- package/dist/okf/types/DataIntegrationFlow.md +27 -0
- package/dist/okf/types/DataMigration.md +1 -1
- package/dist/okf/types/DataProvider.md +2 -1
- package/dist/okf/types/DataQualityRuleset.md +6 -11
- package/dist/okf/types/DataSource.md +23 -0
- package/dist/okf/types/Dataset.md +20 -0
- package/dist/okf/types/DatasetIntegration.md +23 -0
- package/dist/okf/types/DbCluster.md +1 -1
- package/dist/okf/types/DbInstance.md +8 -2
- package/dist/okf/types/DeadlineBudget.md +29 -0
- package/dist/okf/types/DelegationSet.md +23 -0
- package/dist/okf/types/DeliveryChannel.md +6 -11
- package/dist/okf/types/DevOpsAgentAgentSpace.md +4 -0
- package/dist/okf/types/DevOpsAgentService.md +1 -0
- package/dist/okf/types/DevOpsAgentTrigger.md +28 -0
- package/dist/okf/types/DirectConnectGatewayAttachment.md +2 -0
- package/dist/okf/types/Directory.md +60 -0
- package/dist/okf/types/DocDBDBClusterParameterGroup.md +5 -10
- package/dist/okf/types/DocDBDBSubnetGroup.md +4 -9
- package/dist/okf/types/DocDBElasticClusterSnapshot.md +36 -0
- package/dist/okf/types/DocumentClassifierEndpoint.md +27 -0
- package/dist/okf/types/Domain.md +27 -0
- package/dist/okf/types/EKSCertificateAuthority.md +42 -0
- package/dist/okf/types/EKSCluster.md +8 -0
- package/dist/okf/types/EcSnapshot.md +66 -0
- package/dist/okf/types/EmailIdentityCertificate.md +15 -0
- package/dist/okf/types/EndpointConfig.md +14 -13
- package/dist/okf/types/EntityRecognizer.md +27 -0
- package/dist/okf/types/EntityRecognizerEndpoint.md +31 -0
- package/dist/okf/types/EnvironmentEC2.md +13 -13
- package/dist/okf/types/EvaluationForm.md +1 -0
- package/dist/okf/types/Evaluator.md +6 -2
- package/dist/okf/types/EventAction.md +26 -0
- package/dist/okf/types/EventRule.md +2 -0
- package/dist/okf/types/EventSource.md +30 -0
- package/dist/okf/types/EventTracker.md +22 -0
- package/dist/okf/types/EventsV2EventBus.md +28 -0
- package/dist/okf/types/EventsV2ResourcePolicy.md +19 -0
- package/dist/okf/types/EventsV2Subscriber.md +39 -0
- package/dist/okf/types/ExperimentDefinition.md +39 -0
- package/dist/okf/types/ExperimentRun.md +33 -0
- package/dist/okf/types/ExperimentTrialComponent.md +13 -11
- package/dist/okf/types/FHIRDatastore.md +3 -0
- package/dist/okf/types/FSxSnapshot.md +5 -5
- package/dist/okf/types/FSxVolume.md +9 -9
- package/dist/okf/types/FeaturedResultsSet.md +26 -0
- package/dist/okf/types/Feed.md +1 -0
- package/dist/okf/types/FieldLevelEncryptionConfig.md +25 -0
- package/dist/okf/types/FieldLevelEncryptionProfile.md +22 -0
- package/dist/okf/types/FileCache.md +45 -0
- package/dist/okf/types/Filter.md +27 -0
- package/dist/okf/types/Firewall.md +6 -0
- package/dist/okf/types/FlowMediaStream.md +28 -0
- package/dist/okf/types/FlowOutput.md +1 -0
- package/dist/okf/types/FpgaImage.md +38 -0
- package/dist/okf/types/Function.md +2 -2
- package/dist/okf/types/Gateway.md +41 -0
- package/dist/okf/types/GatewayClusterAssociations.md +23 -0
- package/dist/okf/types/GatewayRateLimit.md +26 -0
- package/dist/okf/types/GatewayRule.md +32 -0
- package/dist/okf/types/GlobalReplicationGroup.md +3 -0
- package/dist/okf/types/GlobalResolver.md +1 -1
- package/dist/okf/types/GlobalTable.md +1 -0
- package/dist/okf/types/GlueConnection.md +5 -4
- package/dist/okf/types/GlueSecurityConfiguration.md +1 -6
- package/dist/okf/types/GlueSession.md +38 -0
- package/dist/okf/types/GlueTable.md +5 -10
- package/dist/okf/types/GlueWorkflow.md +5 -10
- package/dist/okf/types/Group.md +27 -0
- package/dist/okf/types/Harness.md +1 -0
- package/dist/okf/types/HostKey.md +33 -0
- package/dist/okf/types/HostedZone.md +1 -0
- package/dist/okf/types/HttpApi.md +2 -0
- package/dist/okf/types/HttpNamespace.md +5 -5
- package/dist/okf/types/HubV2.md +1 -0
- package/dist/okf/types/HumanTaskUi.md +22 -0
- package/dist/okf/types/IPv4Pool.md +28 -0
- package/dist/okf/types/ImageBuilder.md +1 -0
- package/dist/okf/types/ImageBuilderImage.md +1 -1
- package/dist/okf/types/ImagePipeline.md +1 -1
- package/dist/okf/types/InferenceComponent.md +5 -1
- package/dist/okf/types/InfluxDBBackup.md +65 -0
- package/dist/okf/types/InfluxDBCluster.md +3 -0
- package/dist/okf/types/InfrastructureConfiguration.md +2 -0
- package/dist/okf/types/IngestionDestination.md +28 -0
- package/dist/okf/types/InputSecurityGroup.md +6 -4
- package/dist/okf/types/InspectorV2Connector.md +38 -0
- package/dist/okf/types/InstanceEventWindow.md +25 -0
- package/dist/okf/types/InstanceFleetConfig.md +10 -10
- package/dist/okf/types/InstanceGroupConfig.md +3 -3
- package/dist/okf/types/InstrumentationConfig.md +31 -0
- package/dist/okf/types/IntegrationAssociation.md +3 -0
- package/dist/okf/types/IoTSiteWiseApplication.md +34 -0
- package/dist/okf/types/IoTSiteWiseDataset.md +5 -2
- package/dist/okf/types/IoTSiteWiseTask.md +24 -0
- package/dist/okf/types/IpamExternalResourceVerificationToken.md +35 -0
- package/dist/okf/types/IpamInternetRegistryAssociation.md +32 -0
- package/dist/okf/types/Job.md +35 -0
- package/dist/okf/types/JobTemplate.md +26 -0
- package/dist/okf/types/KinesisChannel.md +31 -0
- package/dist/okf/types/KinesisStream.md +1 -0
- package/dist/okf/types/LambdaResourcePolicy.md +14 -0
- package/dist/okf/types/Lexicon.md +34 -0
- package/dist/okf/types/LicenseAssetGroup.md +23 -0
- package/dist/okf/types/LicenseConfiguration.md +33 -0
- package/dist/okf/types/LicenseServerEndpoint.md +32 -0
- package/dist/okf/types/LightsailKeyPair.md +29 -0
- package/dist/okf/types/LimitsProfile.md +27 -0
- package/dist/okf/types/LocationAzureBlob.md +2 -1
- package/dist/okf/types/LocationObjectStorage.md +1 -0
- package/dist/okf/types/LogAlarm.md +2 -0
- package/dist/okf/types/MGNConnector.md +23 -0
- package/dist/okf/types/MGNLaunchConfigurationTemplate.md +37 -0
- package/dist/okf/types/MLTransform.md +15 -15
- package/dist/okf/types/MWAAServerlessWorkflow.md +3 -0
- package/dist/okf/types/ManagedNotificationAccountContactAssociation.md +1 -0
- package/dist/okf/types/ManagedNotificationAdditionalChannelAssociation.md +1 -0
- package/dist/okf/types/MediaConvertJobTemplate.md +11 -13
- package/dist/okf/types/MediaConvertQueue.md +8 -10
- package/dist/okf/types/MediaInsightsPipelineConfiguration.md +28 -0
- package/dist/okf/types/MediaLiveInput.md +41 -18
- package/dist/okf/types/MediaPackageV2Channel.md +3 -0
- package/dist/okf/types/MediaPackageV2OriginEndpoint.md +1 -0
- package/dist/okf/types/MediaPipelineKinesisVideoStreamPool.md +28 -0
- package/dist/okf/types/MediaTailorFunction.md +27 -0
- package/dist/okf/types/MedicalVocabulary.md +21 -0
- package/dist/okf/types/Member.md +26 -0
- package/dist/okf/types/Memory.md +6 -0
- package/dist/okf/types/MemoryDBSnapshot.md +29 -0
- package/dist/okf/types/Metric.md +59 -0
- package/dist/okf/types/MetricAttribution.md +23 -0
- package/dist/okf/types/MicrosoftAD.md +11 -11
- package/dist/okf/types/MigrationProject.md +8 -1
- package/dist/okf/types/Monitor.md +26 -0
- package/dist/okf/types/NFSFileShare.md +44 -0
- package/dist/okf/types/NeptuneGraphGraph.md +1 -0
- package/dist/okf/types/NetworkConnector.md +4 -0
- package/dist/okf/types/NetworkFlowMonitorScope.md +23 -0
- package/dist/okf/types/NetworkMigrationDefinition.md +31 -0
- package/dist/okf/types/NetworkSecurityManagerDeployment.md +31 -0
- package/dist/okf/types/NetworkSecurityManagerPolicy.md +32 -0
- package/dist/okf/types/NetworkSecurityManagerScope.md +29 -0
- package/dist/okf/types/NotebookInstance.md +18 -18
- package/dist/okf/types/NotebookInstanceLifecycleConfig.md +6 -5
- package/dist/okf/types/NotifyConfiguration.md +35 -0
- package/dist/okf/types/OTelEnrichment.md +2 -0
- package/dist/okf/types/OnlineEvaluationConfig.md +0 -1
- package/dist/okf/types/OrganizationConfigRule.md +7 -7
- package/dist/okf/types/Outpost.md +32 -0
- package/dist/okf/types/ParallelData.md +40 -0
- package/dist/okf/types/Partition.md +5 -5
- package/dist/okf/types/PaymentConnector.md +4 -1
- package/dist/okf/types/Pentest.md +1 -0
- package/dist/okf/types/PerfReports.md +28 -0
- package/dist/okf/types/PermissionAssociation.md +30 -0
- package/dist/okf/types/PersonalizeDataset.md +1 -0
- package/dist/okf/types/PersonalizeDatasetGroup.md +1 -0
- package/dist/okf/types/PersonalizeSchema.md +1 -0
- package/dist/okf/types/Pipeline.md +25 -0
- package/dist/okf/types/PlaybackConfiguration.md +1 -0
- package/dist/okf/types/PolicyAssociation.md +1 -1
- package/dist/okf/types/PolicyGrant.md +2 -2
- package/dist/okf/types/PolicyPrincipalAttachment.md +2 -7
- package/dist/okf/types/PortalProduct.md +24 -0
- package/dist/okf/types/PrefetchSchedule.md +25 -0
- package/dist/okf/types/PricingPlanManagerSubscription.md +31 -0
- package/dist/okf/types/PrincipalAssociation.md +27 -0
- package/dist/okf/types/PrivateDnsNamespace.md +8 -8
- package/dist/okf/types/PrivateVirtualInterface.md +1 -0
- package/dist/okf/types/ProcurementPortalPreference.md +45 -0
- package/dist/okf/types/Program.md +33 -0
- package/dist/okf/types/ProjectMembership.md +1 -1
- package/dist/okf/types/ProtocolsList.md +26 -0
- package/dist/okf/types/PublicDnsNamespace.md +7 -7
- package/dist/okf/types/PublicVirtualInterface.md +1 -0
- package/dist/okf/types/QEV2IdcApplication.md +25 -0
- package/dist/okf/types/QueryLoggingConfig.md +21 -0
- package/dist/okf/types/QuerySuggestionsBlockList.md +25 -0
- package/dist/okf/types/QuickSightAssignment.md +24 -0
- package/dist/okf/types/RAMResourceAssociation.md +27 -0
- package/dist/okf/types/RDSClusterSnapshot.md +54 -0
- package/dist/okf/types/RDSDBParameterGroup.md +5 -0
- package/dist/okf/types/RDSDeployment.md +41 -0
- package/dist/okf/types/RcsAgent.md +38 -0
- package/dist/okf/types/ReceiptRule.md +5 -5
- package/dist/okf/types/ReceiptRuleSet.md +1 -6
- package/dist/okf/types/RecommenderFilter.md +27 -0
- package/dist/okf/types/RecommenderSchema.md +25 -0
- package/dist/okf/types/RecordSet.md +16 -22
- package/dist/okf/types/RecoveryPlan.md +28 -0
- package/dist/okf/types/RedshiftIdcApplication.md +31 -0
- package/dist/okf/types/RedshiftSnapshot.md +59 -0
- package/dist/okf/types/RegistrationAttachment.md +28 -0
- package/dist/okf/types/Registry.md +41 -0
- package/dist/okf/types/RegistryRecord.md +38 -0
- package/dist/okf/types/RelatedItem.md +24 -0
- package/dist/okf/types/ReplicationConfigurationTemplate.md +35 -0
- package/dist/okf/types/ReplicationSubnetGroup.md +4 -9
- package/dist/okf/types/ReplicationTask.md +14 -14
- package/dist/okf/types/ReportGenerator.md +29 -0
- package/dist/okf/types/ReportGroup.md +1 -3
- package/dist/okf/types/ResilienceHubV2Policy.md +1 -0
- package/dist/okf/types/ResilienceHubV2Service.md +1 -0
- package/dist/okf/types/ResourceConfiguration.md +1 -1
- package/dist/okf/types/ResourceMetricsConfiguration.md +21 -0
- package/dist/okf/types/RestApi.md +1 -0
- package/dist/okf/types/RetrievalInstruction.md +32 -0
- package/dist/okf/types/RouterOutput.md +1 -0
- package/dist/okf/types/Rule.md +31 -0
- package/dist/okf/types/RunCache.md +29 -0
- package/dist/okf/types/Runtime.md +2 -1
- package/dist/okf/types/SCNInstance.md +33 -0
- package/dist/okf/types/SDBDomain.md +2 -2
- package/dist/okf/types/SMBFileShare.md +49 -0
- package/dist/okf/types/SageMakerArtifact.md +27 -0
- package/dist/okf/types/SageMakerEndpoint.md +0 -1
- package/dist/okf/types/ScalableTarget.md +1 -0
- package/dist/okf/types/ScalingPlan.md +6 -6
- package/dist/okf/types/ScheduledReport.md +31 -0
- package/dist/okf/types/SecondaryNetwork.md +26 -0
- package/dist/okf/types/SecurityAgentArtifact.md +25 -0
- package/dist/okf/types/SecurityAgentIntegration.md +31 -0
- package/dist/okf/types/Server.md +1 -0
- package/dist/okf/types/ServerlessCache.md +2 -0
- package/dist/okf/types/ServerlessCacheSnapshot.md +31 -0
- package/dist/okf/types/ServerlessRepoApplication.md +32 -0
- package/dist/okf/types/ServiceDiscoveryInstance.md +3 -7
- package/dist/okf/types/SipMediaApplication.md +27 -0
- package/dist/okf/types/SiteToSiteVpnAttachment.md +2 -0
- package/dist/okf/types/SnapshotCopyGrant.md +20 -0
- package/dist/okf/types/Solution.md +1 -0
- package/dist/okf/types/SourceAssociation.md +25 -0
- package/dist/okf/types/SourceCredential.md +6 -6
- package/dist/okf/types/SourceNetwork.md +23 -0
- package/dist/okf/types/StackFleetAssociation.md +2 -7
- package/dist/okf/types/StorageTierPolicy.md +20 -0
- package/dist/okf/types/StorageVirtualMachine.md +9 -9
- package/dist/okf/types/Stream.md +28 -0
- package/dist/okf/types/SubnetCidrReservation.md +26 -0
- package/dist/okf/types/SubscriptionProvider.md +26 -0
- package/dist/okf/types/SupportPermit.md +29 -0
- package/dist/okf/types/Table.md +2 -1
- package/dist/okf/types/TableOptimizer.md +5 -10
- package/dist/okf/types/Tape.md +31 -0
- package/dist/okf/types/Template.md +36 -0
- package/dist/okf/types/Tenant.md +2 -0
- package/dist/okf/types/Terminology.md +39 -0
- package/dist/okf/types/Thesaurus.md +25 -0
- package/dist/okf/types/ThingPrincipalAttachment.md +3 -8
- package/dist/okf/types/Topic.md +1 -0
- package/dist/okf/types/TopicRuleDestination.md +1 -0
- package/dist/okf/types/TrafficPolicy.md +26 -0
- package/dist/okf/types/TrafficPolicyInstance.md +28 -0
- package/dist/okf/types/TranscribeVocabulary.md +27 -0
- package/dist/okf/types/TransitGatewayRouteTableAttachment.md +2 -0
- package/dist/okf/types/TransitVirtualInterface.md +1 -0
- package/dist/okf/types/Tunnel.md +25 -0
- package/dist/okf/types/UsageLimit.md +26 -0
- package/dist/okf/types/UseCase.md +23 -0
- package/dist/okf/types/User.md +47 -0
- package/dist/okf/types/VPCEndpoint.md +1 -1
- package/dist/okf/types/VPCEndpointService.md +6 -0
- package/dist/okf/types/VPCPeeringConnection.md +2 -2
- package/dist/okf/types/VPNConcentrator.md +1 -1
- package/dist/okf/types/VPNConnection.md +1 -1
- package/dist/okf/types/VerifiedDestinationNumber.md +25 -0
- package/dist/okf/types/View.md +27 -0
- package/dist/okf/types/VoiceConnector.md +30 -0
- package/dist/okf/types/Volume.md +44 -0
- package/dist/okf/types/Vpc.md +1 -1
- package/dist/okf/types/VpcAttachment.md +2 -0
- package/dist/okf/types/WebFunction.md +27 -0
- package/dist/okf/types/WebFunctionEndpoint.md +44 -0
- package/dist/okf/types/WebFunctionRevision.md +32 -0
- package/dist/okf/types/WickrNetwork.md +27 -0
- package/dist/okf/types/Worker.md +29 -0
- package/dist/okf/types/Workforce.md +26 -0
- package/dist/okf/types/Workload.md +35 -0
- package/dist/okf/types/WorkloadEstimate.md +35 -0
- package/dist/okf/types/Workspace.md +28 -0
- package/dist/okf/types/Workteam.md +8 -8
- package/dist/op/activities/aws-apply.js +214 -0
- package/dist/op/activities/floci.js +97 -0
- package/dist/op/activities/index.js +32 -0
- package/dist/op/builders.js +50 -0
- package/dist/ownership.js +52 -0
- package/dist/package-cli.js +25 -0
- package/dist/parameter.js +19 -0
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +1006 -0
- package/dist/properties.js +166 -0
- package/dist/pseudo.js +25 -0
- package/dist/receipt-store.d.ts.map +1 -1
- package/dist/receipt-store.js +233 -0
- package/dist/reference-catalog.js +106 -0
- package/dist/rules/ext001.ts +3 -3
- package/dist/rules/waw016.ts +2 -2
- package/dist/serializer.js +529 -0
- package/dist/spec/fetch.js +193 -0
- package/dist/spec/parse.js +259 -0
- package/dist/spec/pin.js +185 -0
- package/dist/spec/pinned-types.json +203 -0
- package/dist/stack-errors.js +14 -0
- package/dist/taggable.d.ts.map +1 -1
- package/dist/taggable.js +33 -0
- package/dist/teardown.js +199 -0
- package/dist/template-sections.js +53 -0
- package/dist/template-transform.js +50 -0
- package/dist/types/index.d.ts +18847 -1124
- package/dist/validate-cli.js +16 -0
- package/dist/validate.js +33 -0
- package/package.json +9 -9
- package/src/agentcore/trace-fetch.ts +2 -1
- package/src/api/credential-chain.ts +119 -9
- package/src/api/credential-isolation.test.ts +72 -0
- package/src/api/read-client-chain.test.ts +159 -0
- package/src/api/read-client.ts +42 -6
- package/src/api/sigv4.ts +4 -4
- package/src/caller-identity.ts +3 -5
- package/src/codegen/any-budget.test.ts +12 -2
- package/src/codegen/generate.ts +9 -0
- package/src/codegen/package.ts +2 -2
- package/src/codegen/patches.test.ts +95 -0
- package/src/codegen/patches.ts +53 -9
- package/src/codegen/property-overlay.json +1 -16
- package/src/components/apply.ts +218 -6
- package/src/components/cfn-plan-floci.e2e.test.ts +76 -0
- package/src/components/cfn-plan.test.ts +225 -16
- package/src/components/cloud-executor.ts +73 -25
- package/src/deep-observe.ts +2 -1
- package/src/disruption.ts +2 -1
- package/src/generated/index.d.ts +18847 -1124
- package/src/generated/index.ts +1376 -161
- package/src/generated/lexicon-aws.json +17359 -784
- package/src/identity-observe.ts +2 -1
- package/src/lint/post-synth/ext001.ts +3 -3
- package/src/lint/post-synth/waw016.ts +2 -2
- package/src/lsp/completions.ts +2 -1
- package/src/lsp/hover.ts +2 -1
- package/src/plugin.ts +2 -1
- package/src/receipt-store.ts +2 -1
- package/src/spec/pin.ts +3 -3
- package/src/spec/pinned-types.json +203 -0
- package/src/taggable.ts +2 -2
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import { homedir } from "os";
|
|
2
|
+
import { join } from "path";
|
|
3
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
4
|
+
import { execFile } from "child_process";
|
|
5
|
+
import { promisify } from "util";
|
|
6
|
+
import { fetchWithCache, extractFromZip, clearCacheFile } from "@intentius/chant/codegen/fetch";
|
|
7
|
+
import { RELEASE_GATE_ENV } from "@intentius/chant/codegen/validate";
|
|
8
|
+
import { ACCEPT_ENV, AWS_SPEC_PIN, specContentDigest } from "./pin.js";
|
|
9
|
+
/** Per-attempt download timeout for a multi-megabyte archive. */
|
|
10
|
+
const ARCHIVE_ATTEMPT_TIMEOUT_MS = 120000;
|
|
11
|
+
const SCHEMA_ZIP_URL = "https://schema.cloudformation.us-east-1.amazonaws.com/CloudformationSchema.zip";
|
|
12
|
+
const CACHE_DIR = join(homedir(), ".chant");
|
|
13
|
+
const CACHE_FILE = join(CACHE_DIR, "CloudformationSchema.zip");
|
|
14
|
+
/**
|
|
15
|
+
* The pinned-spec store (chant #1511): assets on one dedicated GitHub release,
|
|
16
|
+
* named by content digest, in a public repo — so nothing binary ever enters
|
|
17
|
+
* git history, and the download needs no auth anywhere (CI included).
|
|
18
|
+
*
|
|
19
|
+
* Why a store at all: `prepack` regenerates from upstream, and the registry
|
|
20
|
+
* serves a single mutable "latest" artifact — on 2026-08-05 four distinct
|
|
21
|
+
* contents were observed in one day, two *contradicting* each other about the
|
|
22
|
+
* same resources, so the surface gate compared artifacts built from whichever
|
|
23
|
+
* variant that fetch happened to hit. Publishing aws was a retry lottery
|
|
24
|
+
* (v0.41.1 and v0.41.2 both stranded it). The accepted content itself is the
|
|
25
|
+
* only deterministic input; the accept uploads it, every build downloads it
|
|
26
|
+
* by digest and verifies before trusting it.
|
|
27
|
+
*/
|
|
28
|
+
const SPEC_PIN_RELEASE_TAG = "aws-spec-pin";
|
|
29
|
+
const SPEC_PIN_REPO = "INTENTIUS/chant";
|
|
30
|
+
/** Verified-by-digest local copies of pin assets, so repeat builds skip the download. Content-addressed: no TTL, never invalidated. */
|
|
31
|
+
const PIN_CACHE_DIR = join(CACHE_DIR, "spec-pin");
|
|
32
|
+
/** `<first 12 digest hex>.zip` — the asset (and local cache) name for a pin. */
|
|
33
|
+
export function pinAssetName(pin = AWS_SPEC_PIN) {
|
|
34
|
+
return `${pin.digest.replace(/^sha256:/, "").slice(0, 12)}.zip`;
|
|
35
|
+
}
|
|
36
|
+
/** Public, unauthenticated download URL for a pin's asset. */
|
|
37
|
+
export function pinAssetUrl(pin = AWS_SPEC_PIN) {
|
|
38
|
+
return `https://github.com/${SPEC_PIN_REPO}/releases/download/${SPEC_PIN_RELEASE_TAG}/${pinAssetName(pin)}`;
|
|
39
|
+
}
|
|
40
|
+
const downloadPinAsset = async (url) => {
|
|
41
|
+
try {
|
|
42
|
+
const res = await fetch(url, { redirect: "follow" });
|
|
43
|
+
if (!res.ok)
|
|
44
|
+
return undefined;
|
|
45
|
+
return Buffer.from(await res.arrayBuffer());
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* Load and verify the pinned spec: the local verified cache first, then the
|
|
53
|
+
* release asset. Returns undefined when neither is available (offline and
|
|
54
|
+
* cold, or the accept never uploaded) — the caller falls back to the live
|
|
55
|
+
* fetch and the pin's existing advisory drift report. Content that does not
|
|
56
|
+
* digest to the pin throws: a tampered or half-uploaded asset must never
|
|
57
|
+
* silently pass as the accepted spec, wherever it came from.
|
|
58
|
+
*/
|
|
59
|
+
export async function loadPinnedSchemas(options = {}) {
|
|
60
|
+
const pin = options.pin ?? AWS_SPEC_PIN;
|
|
61
|
+
const cacheDir = options.cacheDir ?? PIN_CACHE_DIR;
|
|
62
|
+
const cachePath = join(cacheDir, pinAssetName(pin));
|
|
63
|
+
const verify = async (zipData, source) => {
|
|
64
|
+
const schemas = await extractRawSchemas(zipData);
|
|
65
|
+
const digest = specContentDigest(schemas);
|
|
66
|
+
if (digest !== pin.digest) {
|
|
67
|
+
throw new Error(`pinned spec from ${source} extracts to ${digest}, but the pin declares ${pin.digest} — ` +
|
|
68
|
+
`refusing to build from it. Re-run the accept (${ACCEPT_ENV}=1 npm run generate) to ` +
|
|
69
|
+
`upload the content the pin actually names.`);
|
|
70
|
+
}
|
|
71
|
+
return schemas;
|
|
72
|
+
};
|
|
73
|
+
if (existsSync(cachePath)) {
|
|
74
|
+
return verify(readFileSync(cachePath), cachePath);
|
|
75
|
+
}
|
|
76
|
+
const url = pinAssetUrl(pin);
|
|
77
|
+
const zipData = await (options.download ?? downloadPinAsset)(url);
|
|
78
|
+
if (zipData === undefined)
|
|
79
|
+
return undefined;
|
|
80
|
+
const schemas = await verify(zipData, url);
|
|
81
|
+
// Cache only after verification, so the cache can never hold a bad copy.
|
|
82
|
+
mkdirSync(cacheDir, { recursive: true });
|
|
83
|
+
writeFileSync(cachePath, zipData);
|
|
84
|
+
return schemas;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* The accept flow's upload half: push the just-accepted zip to the pin
|
|
88
|
+
* release via `gh` (dev-machine path — publishes never upload). Creates the
|
|
89
|
+
* rolling `aws-spec-pin` release on first use. Assets are content-addressed
|
|
90
|
+
* and never overwritten. A missing/unauthenticated `gh` degrades to printing
|
|
91
|
+
* the exact command to run by hand — the accept still completes, and the pin
|
|
92
|
+
* block still prints.
|
|
93
|
+
*/
|
|
94
|
+
async function uploadPinAsset(zipData, digest) {
|
|
95
|
+
const pin = { ...AWS_SPEC_PIN, digest };
|
|
96
|
+
mkdirSync(PIN_CACHE_DIR, { recursive: true });
|
|
97
|
+
const localPath = join(PIN_CACHE_DIR, pinAssetName(pin));
|
|
98
|
+
writeFileSync(localPath, zipData);
|
|
99
|
+
const run = promisify(execFile);
|
|
100
|
+
try {
|
|
101
|
+
try {
|
|
102
|
+
await run("gh", ["release", "view", SPEC_PIN_RELEASE_TAG, "--repo", SPEC_PIN_REPO]);
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
await run("gh", [
|
|
106
|
+
"release", "create", SPEC_PIN_RELEASE_TAG,
|
|
107
|
+
"--repo", SPEC_PIN_REPO,
|
|
108
|
+
"--title", "aws spec pin assets",
|
|
109
|
+
"--notes", "Content-addressed CloudFormation registry archives, one per accepted spec pin (chant #1511). Uploaded by the accept flow; downloaded and digest-verified by every build. Not a chant release.",
|
|
110
|
+
]);
|
|
111
|
+
}
|
|
112
|
+
await run("gh", ["release", "upload", SPEC_PIN_RELEASE_TAG, localPath, "--repo", SPEC_PIN_REPO]);
|
|
113
|
+
console.error(`Accepted spec uploaded: ${pinAssetUrl(pin)}`);
|
|
114
|
+
}
|
|
115
|
+
catch (err) {
|
|
116
|
+
console.error(`Could not upload the accepted spec via gh (${err instanceof Error ? err.message.split("\n")[0] : String(err)}).\n` +
|
|
117
|
+
`Upload it yourself before merging the pin:\n` +
|
|
118
|
+
` gh release upload ${SPEC_PIN_RELEASE_TAG} ${localPath} --repo ${SPEC_PIN_REPO}`);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Fetch the CloudFormation Registry schema zip and extract per-resource JSON schemas.
|
|
123
|
+
* Returns a Map keyed by typeName (e.g. "AWS::S3::Bucket") to raw JSON bytes.
|
|
124
|
+
*
|
|
125
|
+
* chant #1511 — the pinned release asset is the primary source: when it
|
|
126
|
+
* resolves and digest-verifies, generation uses the content a human accepted
|
|
127
|
+
* rather than whatever upstream variant this fetch happens to hit, so every
|
|
128
|
+
* build (CI, prepack, publish) is deterministic. The live fetch remains for:
|
|
129
|
+
* `force`, the accept flow (`CHANT_ACCEPT_AWS_SPEC=1`, which must sample
|
|
130
|
+
* upstream — and bypasses the 24h cache for the same reason), and when the
|
|
131
|
+
* asset is unreachable. The live path keeps its 24h local cache.
|
|
132
|
+
*
|
|
133
|
+
* chant #1481 — the fallback is what made two workflows disagree about one
|
|
134
|
+
* commit. The live archive is served from CloudFront and two fetches seconds
|
|
135
|
+
* apart can get different variants; under the release gate, building from
|
|
136
|
+
* it would ship a surface nobody reviewed on a retry lottery, so the gate
|
|
137
|
+
* refuses instead. Anywhere else the fallback stays, but says so, because a
|
|
138
|
+
* silent fallback is indistinguishable from the pinned path in a CI log.
|
|
139
|
+
*/
|
|
140
|
+
export async function fetchSchemaZip(force = false, options = {}) {
|
|
141
|
+
const env = options.env ?? process.env;
|
|
142
|
+
const accepting = !!env[ACCEPT_ENV];
|
|
143
|
+
if (!force && !accepting) {
|
|
144
|
+
const pinned = await loadPinnedSchemas({ download: options.download, cacheDir: options.pinCacheDir });
|
|
145
|
+
if (pinned)
|
|
146
|
+
return pinned;
|
|
147
|
+
if (env[RELEASE_GATE_ENV] === "1") {
|
|
148
|
+
throw new Error(`${RELEASE_GATE_ENV}=1 and the pinned spec asset could not be loaded (${pinAssetUrl()}) — ` +
|
|
149
|
+
`refusing to build a release from the live CloudFormation archive, which is not the content ` +
|
|
150
|
+
`the pin was reviewed against. Check the asset exists on the ${SPEC_PIN_RELEASE_TAG} release ` +
|
|
151
|
+
`(the accept flow uploads it: ${ACCEPT_ENV}=1 npm run generate).`);
|
|
152
|
+
}
|
|
153
|
+
console.error(`pinned spec asset unavailable (${pinAssetUrl()}); falling back to the live CloudFormation archive`);
|
|
154
|
+
}
|
|
155
|
+
const zipData = await fetchWithCache({ url: SCHEMA_ZIP_URL, cacheFile: CACHE_FILE, attemptTimeoutMs: ARCHIVE_ATTEMPT_TIMEOUT_MS }, force || accepting);
|
|
156
|
+
const schemas = await extractRawSchemas(zipData);
|
|
157
|
+
if (accepting) {
|
|
158
|
+
await uploadPinAsset(zipData, specContentDigest(schemas));
|
|
159
|
+
}
|
|
160
|
+
return schemas;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Extract raw JSON schema bytes from the zip, keyed by typeName.
|
|
164
|
+
*/
|
|
165
|
+
async function extractRawSchemas(zipData) {
|
|
166
|
+
const files = await extractFromZip(zipData, (name) => name.endsWith(".json"));
|
|
167
|
+
const schemas = new Map();
|
|
168
|
+
for (const [_name, data] of files) {
|
|
169
|
+
try {
|
|
170
|
+
const text = data.toString("utf-8");
|
|
171
|
+
const partial = JSON.parse(text);
|
|
172
|
+
if (!partial.typeName)
|
|
173
|
+
continue;
|
|
174
|
+
schemas.set(partial.typeName, data);
|
|
175
|
+
}
|
|
176
|
+
catch {
|
|
177
|
+
// Skip files that can't be parsed
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
return schemas;
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Get the cache file path (for testing)
|
|
184
|
+
*/
|
|
185
|
+
export function getCachePath() {
|
|
186
|
+
return CACHE_FILE;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Clear the cache (for testing)
|
|
190
|
+
*/
|
|
191
|
+
export function clearCache() {
|
|
192
|
+
clearCacheFile(CACHE_FILE);
|
|
193
|
+
}
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CloudFormation Registry JSON Schema parser.
|
|
3
|
+
*
|
|
4
|
+
* Parses each CFNSchema into typed structures suitable for code generation:
|
|
5
|
+
* resources with properties and attributes, property types from definitions,
|
|
6
|
+
* and enum types from string enum definitions.
|
|
7
|
+
*/
|
|
8
|
+
import { resolvePropertyType as coreResolvePropertyType, extractConstraints as coreExtractConstraints, constraintsIsEmpty as coreConstraintsIsEmpty, isEnumDefinition as coreIsEnumDefinition, } from "@intentius/chant/codegen/json-schema";
|
|
9
|
+
import { boundPropertyTypes } from "@intentius/chant/codegen/bound-property-types";
|
|
10
|
+
/**
|
|
11
|
+
* Maximum nesting depth of generated property-type interfaces. Bounds the
|
|
12
|
+
* shipped `.d.ts` size: property types reachable from a resource's top-level
|
|
13
|
+
* properties within this depth stay typed; deeper ones are loosened to
|
|
14
|
+
* `Record<string, unknown>`. Set high enough that the shapes composites consume
|
|
15
|
+
* (which reach a few levels into CFN config) remain typed. (#440)
|
|
16
|
+
*/
|
|
17
|
+
const MAX_PROPERTY_TYPE_DEPTH = 3;
|
|
18
|
+
/**
|
|
19
|
+
* Prose signals that a property description is describing a deprecation.
|
|
20
|
+
* A hit is a guess, not a reading — see `ParsedResource.inferredDeprecations`.
|
|
21
|
+
*/
|
|
22
|
+
const DEPRECATION_RE = /\bdeprecated\b|\blegacy\b|no longer (available|recommended|used|supported)|is not recommended|has been discontinued/i;
|
|
23
|
+
/**
|
|
24
|
+
* Parse a CloudFormation Registry JSON Schema into typed structures.
|
|
25
|
+
*/
|
|
26
|
+
export function parseCFNSchema(data) {
|
|
27
|
+
const schema = JSON.parse(typeof data === "string" ? data : data.toString("utf-8"));
|
|
28
|
+
const requiredSet = new Set(schema.required ?? []);
|
|
29
|
+
const shortName = cfnShortName(schema.typeName);
|
|
30
|
+
// Parse top-level properties
|
|
31
|
+
const props = [];
|
|
32
|
+
if (schema.properties) {
|
|
33
|
+
for (const [name, prop] of Object.entries(schema.properties)) {
|
|
34
|
+
const tsType = resolvePropertyType(prop, schema);
|
|
35
|
+
props.push({
|
|
36
|
+
name,
|
|
37
|
+
tsType,
|
|
38
|
+
required: requiredSet.has(name),
|
|
39
|
+
description: prop.description,
|
|
40
|
+
enum: prop.enum,
|
|
41
|
+
constraints: extractConstraints(prop),
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
// Parse readOnlyProperties as attributes
|
|
46
|
+
// Deduplicate — some upstream schemas (e.g. aws-s3files-filesystem) list the same
|
|
47
|
+
// property twice in readOnlyProperties, which would produce duplicate class members.
|
|
48
|
+
const attrs = [];
|
|
49
|
+
const seenAttrs = new Set();
|
|
50
|
+
for (const path of schema.readOnlyProperties ?? []) {
|
|
51
|
+
const attrName = stripPointerPath(path, schema);
|
|
52
|
+
// Flatten nested paths: "Endpoint/Address" → attr name "Endpoint.Address"
|
|
53
|
+
const cfnAttr = attrName.replace(/\//g, ".");
|
|
54
|
+
if (seenAttrs.has(cfnAttr))
|
|
55
|
+
continue;
|
|
56
|
+
seenAttrs.add(cfnAttr);
|
|
57
|
+
let tsType = "string";
|
|
58
|
+
// For top-level attrs, look up type from properties
|
|
59
|
+
if (!cfnAttr.includes(".") && schema.properties?.[cfnAttr]) {
|
|
60
|
+
tsType = resolvePropertyType(schema.properties[cfnAttr], schema);
|
|
61
|
+
}
|
|
62
|
+
// For nested attrs, type is always string (CF GetAtt returns strings for leaf values)
|
|
63
|
+
attrs.push({ name: cfnAttr, tsType });
|
|
64
|
+
}
|
|
65
|
+
// Parse definitions into property types and enums
|
|
66
|
+
const propertyTypes = [];
|
|
67
|
+
const enums = [];
|
|
68
|
+
if (schema.definitions) {
|
|
69
|
+
for (const [defName, def] of Object.entries(schema.definitions)) {
|
|
70
|
+
if (isEnumDefinition(def)) {
|
|
71
|
+
enums.push({
|
|
72
|
+
name: `${shortName}_${defName}`,
|
|
73
|
+
values: def.enum,
|
|
74
|
+
});
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
if (def.properties) {
|
|
78
|
+
const defRequired = new Set(def.required ?? []);
|
|
79
|
+
const defProps = [];
|
|
80
|
+
for (const [propName, prop] of Object.entries(def.properties)) {
|
|
81
|
+
const tsType = resolvePropertyType(prop, schema);
|
|
82
|
+
defProps.push({
|
|
83
|
+
name: propName,
|
|
84
|
+
tsType,
|
|
85
|
+
required: defRequired.has(propName),
|
|
86
|
+
description: prop.description,
|
|
87
|
+
enum: prop.enum,
|
|
88
|
+
constraints: extractConstraints(prop),
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
propertyTypes.push({
|
|
92
|
+
name: `${shortName}_${defName}`,
|
|
93
|
+
specType: defName,
|
|
94
|
+
properties: defProps,
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
// --- Deprecated properties: declared upstream, plus description-mined ---
|
|
100
|
+
// The declared half is what the Registry schema states. The mined half is a
|
|
101
|
+
// regex over English prose and is recorded separately (#1701): a description
|
|
102
|
+
// can mention the deprecation of a sibling property, of an enum value, or of
|
|
103
|
+
// something the property merely configures.
|
|
104
|
+
const deprecatedSet = new Set(stripPointerPaths(schema.deprecatedProperties ?? [], schema));
|
|
105
|
+
const inferredDeprecations = [];
|
|
106
|
+
// Mine top-level property descriptions
|
|
107
|
+
if (schema.properties) {
|
|
108
|
+
for (const [name, prop] of Object.entries(schema.properties)) {
|
|
109
|
+
if (!prop.description || !DEPRECATION_RE.test(prop.description))
|
|
110
|
+
continue;
|
|
111
|
+
// A hit upstream already declares adds nothing, and is not an inference.
|
|
112
|
+
if (deprecatedSet.has(name))
|
|
113
|
+
continue;
|
|
114
|
+
deprecatedSet.add(name);
|
|
115
|
+
inferredDeprecations.push(name);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
// --- Tagging ---
|
|
119
|
+
let tagging;
|
|
120
|
+
if (schema.tagging && schema.tagging.taggable) {
|
|
121
|
+
tagging = {
|
|
122
|
+
taggable: true,
|
|
123
|
+
tagOnCreate: schema.tagging.tagOnCreate ?? false,
|
|
124
|
+
tagUpdatable: schema.tagging.tagUpdatable ?? false,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
// --- Replacement strategy ---
|
|
128
|
+
let replacementStrategy;
|
|
129
|
+
if (schema.replacementStrategy === "delete_then_create" || schema.replacementStrategy === "create_then_delete") {
|
|
130
|
+
replacementStrategy = schema.replacementStrategy;
|
|
131
|
+
}
|
|
132
|
+
// Bound the emitted property types to keep the shipped declaration small while
|
|
133
|
+
// preserving the shapes composites and shallow authoring rely on (#440).
|
|
134
|
+
const boundedPropertyTypes = boundPropertyTypes(shortName, props, propertyTypes, new Set(enums.map((e) => e.name)), { maxDepth: MAX_PROPERTY_TYPE_DEPTH });
|
|
135
|
+
return {
|
|
136
|
+
resource: {
|
|
137
|
+
typeName: schema.typeName,
|
|
138
|
+
properties: props,
|
|
139
|
+
attributes: attrs,
|
|
140
|
+
createOnly: stripPointerPaths(schema.createOnlyProperties ?? [], schema),
|
|
141
|
+
writeOnly: stripPointerPaths(schema.writeOnlyProperties ?? [], schema),
|
|
142
|
+
primaryIdentifier: stripPointerPaths(schema.primaryIdentifier ?? [], schema),
|
|
143
|
+
deprecatedProperties: [...deprecatedSet],
|
|
144
|
+
inferredDeprecations,
|
|
145
|
+
conditionalCreateOnly: stripPointerPaths(schema.conditionalCreateOnlyProperties ?? [], schema),
|
|
146
|
+
...(replacementStrategy && { replacementStrategy }),
|
|
147
|
+
...(tagging && { tagging }),
|
|
148
|
+
},
|
|
149
|
+
propertyTypes: boundedPropertyTypes,
|
|
150
|
+
enums,
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
// --- Type resolution (delegated to core) ---
|
|
154
|
+
function resolvePropertyType(prop, schema) {
|
|
155
|
+
const shortName = cfnShortName(schema.typeName);
|
|
156
|
+
return coreResolvePropertyType(prop, schema, (defName) => `${shortName}_${defName}`);
|
|
157
|
+
}
|
|
158
|
+
function extractConstraints(prop) {
|
|
159
|
+
return coreExtractConstraints(prop);
|
|
160
|
+
}
|
|
161
|
+
export const constraintsIsEmpty = coreConstraintsIsEmpty;
|
|
162
|
+
function isEnumDefinition(def) {
|
|
163
|
+
return coreIsEnumDefinition(def);
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Extract short resource name: "AWS::S3::Bucket" → "Bucket"
|
|
167
|
+
*/
|
|
168
|
+
export function cfnShortName(typeName) {
|
|
169
|
+
const parts = typeName.split("::");
|
|
170
|
+
return parts.length >= 3 ? parts[2] : typeName;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Extract service name: "AWS::S3::Bucket" → "S3"
|
|
174
|
+
*/
|
|
175
|
+
export function cfnServiceName(typeName) {
|
|
176
|
+
const parts = typeName.split("::");
|
|
177
|
+
return parts.length >= 2 ? parts[1] : typeName;
|
|
178
|
+
}
|
|
179
|
+
/** Bound on the `$ref` walk that resolves a definition-scoped pointer. */
|
|
180
|
+
const MAX_DEFINITION_PATH_DEPTH = 6;
|
|
181
|
+
/** The definition a `#/definitions/Name` ref names, or undefined for anything else. */
|
|
182
|
+
function refDefinitionName(ref) {
|
|
183
|
+
const prefix = "#/definitions/";
|
|
184
|
+
return ref?.startsWith(prefix) ? ref.slice(prefix.length) : undefined;
|
|
185
|
+
}
|
|
186
|
+
function pushProperties(queue, path, properties) {
|
|
187
|
+
for (const [name, prop] of Object.entries(properties))
|
|
188
|
+
queue.push({ path: [...path, name], node: prop });
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* The property path that reaches `defName`, searched breadth-first from the
|
|
192
|
+
* top-level properties so the shortest one wins. Undefined when nothing
|
|
193
|
+
* declared reaches the definition; the pointer is then left as the Registry
|
|
194
|
+
* wrote it rather than naming a key no template has.
|
|
195
|
+
*/
|
|
196
|
+
function definitionPropertyPath(defName, schema) {
|
|
197
|
+
const defs = schema.definitions ?? {};
|
|
198
|
+
const expanded = new Set();
|
|
199
|
+
const queue = [];
|
|
200
|
+
pushProperties(queue, [], schema.properties ?? {});
|
|
201
|
+
while (queue.length > 0) {
|
|
202
|
+
const { path, node } = queue.shift();
|
|
203
|
+
if (path.length > MAX_DEFINITION_PATH_DEPTH)
|
|
204
|
+
continue;
|
|
205
|
+
const ref = refDefinitionName(node.$ref);
|
|
206
|
+
if (ref === defName)
|
|
207
|
+
return path.join("/");
|
|
208
|
+
if (ref !== undefined) {
|
|
209
|
+
// Shortest path wins, so a definition already reached needs no second visit.
|
|
210
|
+
if (expanded.has(ref))
|
|
211
|
+
continue;
|
|
212
|
+
expanded.add(ref);
|
|
213
|
+
const def = defs[ref];
|
|
214
|
+
if (def?.properties)
|
|
215
|
+
pushProperties(queue, path, def.properties);
|
|
216
|
+
continue;
|
|
217
|
+
}
|
|
218
|
+
if (node.items) {
|
|
219
|
+
queue.push({ path: [...path, "*"], node: node.items });
|
|
220
|
+
continue;
|
|
221
|
+
}
|
|
222
|
+
if (node.properties)
|
|
223
|
+
pushProperties(queue, path, node.properties);
|
|
224
|
+
}
|
|
225
|
+
return undefined;
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Flatten a CloudFormation Registry JSON pointer to the property path a
|
|
229
|
+
* template expresses, `/`-joined.
|
|
230
|
+
*
|
|
231
|
+
* Three shapes occur upstream. `/properties/BucketName` is the plain one.
|
|
232
|
+
* A pointer can re-enter the `properties` keyword mid-path
|
|
233
|
+
* (`/properties/DistributionConfig/properties/S3Origin`), which a template
|
|
234
|
+
* never writes. And a pointer can be scoped to a shared definition
|
|
235
|
+
* (`/definitions/ContinuousDeploymentPolicyConfig/properties/Type`), which a
|
|
236
|
+
* template expresses only through whichever property carries that definition.
|
|
237
|
+
*
|
|
238
|
+
* Array positions stay as `*`. `readOnlyProperties` attribute names are
|
|
239
|
+
* generated from this output, so dropping the wildcard would rename them.
|
|
240
|
+
*/
|
|
241
|
+
export function stripPointerPath(path, schema) {
|
|
242
|
+
if (!path.startsWith("/"))
|
|
243
|
+
return path;
|
|
244
|
+
const segments = path.split("/").filter((s) => s.length > 0);
|
|
245
|
+
if (segments[0] === "definitions") {
|
|
246
|
+
const prefix = segments[1] && schema ? definitionPropertyPath(segments[1], schema) : undefined;
|
|
247
|
+
if (prefix === undefined)
|
|
248
|
+
return path;
|
|
249
|
+
return [prefix, ...segments.slice(2).filter((s) => s !== "properties")].join("/");
|
|
250
|
+
}
|
|
251
|
+
if (segments[0] !== "properties")
|
|
252
|
+
return path;
|
|
253
|
+
return segments.slice(1).filter((s) => s !== "properties").join("/");
|
|
254
|
+
}
|
|
255
|
+
function stripPointerPaths(paths, schema) {
|
|
256
|
+
if (paths.length === 0)
|
|
257
|
+
return [];
|
|
258
|
+
return paths.map((p) => stripPointerPath(p, schema));
|
|
259
|
+
}
|
package/dist/spec/pin.js
ADDED
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Content pin for the CloudFormation Registry schema (#1390).
|
|
3
|
+
*
|
|
4
|
+
* cfn-lint is pinned to a git tag (`PINNED_VERSIONS.cfnLint`). The registry
|
|
5
|
+
* schema could not be: it is a single "latest" artifact with no version in the
|
|
6
|
+
* path, republished constantly —
|
|
7
|
+
*
|
|
8
|
+
* $ curl -sI .../CloudformationSchema.zip
|
|
9
|
+
* Last-Modified: Mon, 03 Aug 2026 01:29:20 GMT
|
|
10
|
+
*
|
|
11
|
+
* — so `npm run --prefix lexicons/aws prepack`, which CI runs on every build and
|
|
12
|
+
* any local codegen or docs task triggers, resolved to whatever CloudFormation
|
|
13
|
+
* shipped that morning. During the #1312 docs work a docs-only branch twice
|
|
14
|
+
* picked up a resource-count move with nothing in the commit explaining it. The
|
|
15
|
+
* count was only the visible symptom; the same regeneration rewrites generated
|
|
16
|
+
* types and the resource registry.
|
|
17
|
+
*
|
|
18
|
+
* Since there is no version to pin, the pin is over content. Specifically over
|
|
19
|
+
* the **extracted schemas**, not the zip: AWS repackaging the archive changes
|
|
20
|
+
* its `ETag` and its bytes while the schemas are identical, and a pin that fires
|
|
21
|
+
* on that would be noise. Sorted `typeName` → `sha256(schema)`, hashed in order,
|
|
22
|
+
* moves exactly when a schema does.
|
|
23
|
+
*
|
|
24
|
+
* Advisory is not enough here, unlike the emulator image pins (#808). An
|
|
25
|
+
* emulator that drifts fails a test you can see; a spec that drifts silently
|
|
26
|
+
* rewrites committed artifacts in a branch about something else. So a mismatch
|
|
27
|
+
* refuses, and accepting is a deliberate act that lands as its own commit.
|
|
28
|
+
*/
|
|
29
|
+
import { createHash } from "crypto";
|
|
30
|
+
import pinnedTypes from "./pinned-types.json" with { type: "json" };
|
|
31
|
+
/**
|
|
32
|
+
* The resource types the pinned archive contained.
|
|
33
|
+
*
|
|
34
|
+
* Committed beside the digest so accepting a new spec is reviewable as a diff:
|
|
35
|
+
* the PR that moves the pin shows exactly which types AWS added or removed,
|
|
36
|
+
* rather than one opaque hash replacing another. The generated artifacts cannot
|
|
37
|
+
* play that role — `src/generated/` is not committed.
|
|
38
|
+
*/
|
|
39
|
+
export const PINNED_TYPE_NAMES = new Set(pinnedTypes);
|
|
40
|
+
/**
|
|
41
|
+
* The accepted upstream spec.
|
|
42
|
+
*
|
|
43
|
+
* To move it: run generation, read the refusal, confirm the delta is one you
|
|
44
|
+
* want, and paste the printed pin here in its own commit.
|
|
45
|
+
*/
|
|
46
|
+
export const AWS_SPEC_PIN = {
|
|
47
|
+
digest: "sha256:398259716cca4a83d8ffc719fb214caf3ed6239c6be775e6d21952ce7ad8dae4",
|
|
48
|
+
resources: 1856,
|
|
49
|
+
accepted: "2026-10-19",
|
|
50
|
+
};
|
|
51
|
+
/** Env var that accepts whatever upstream currently serves, printing the new pin. */
|
|
52
|
+
export const ACCEPT_ENV = "CHANT_ACCEPT_AWS_SPEC";
|
|
53
|
+
/**
|
|
54
|
+
* Digest the extracted schemas. Stable against repackaging; changes when any
|
|
55
|
+
* schema's bytes change, or when a type is added or removed.
|
|
56
|
+
*/
|
|
57
|
+
export function specContentDigest(schemas) {
|
|
58
|
+
const hash = createHash("sha256");
|
|
59
|
+
for (const typeName of [...schemas.keys()].sort()) {
|
|
60
|
+
hash.update(typeName);
|
|
61
|
+
hash.update(createHash("sha256").update(schemas.get(typeName)).digest());
|
|
62
|
+
}
|
|
63
|
+
return `sha256:${hash.digest("hex")}`;
|
|
64
|
+
}
|
|
65
|
+
/** Compare a freshly fetched archive against a pin. `null` when it matches. */
|
|
66
|
+
export function specDrift(schemas, pinnedNames, pin = AWS_SPEC_PIN) {
|
|
67
|
+
const digest = specContentDigest(schemas);
|
|
68
|
+
if (digest === pin.digest)
|
|
69
|
+
return null;
|
|
70
|
+
const names = new Set(schemas.keys());
|
|
71
|
+
return {
|
|
72
|
+
digest,
|
|
73
|
+
resources: names.size,
|
|
74
|
+
// Type names are only known when a caller supplies the previous set;
|
|
75
|
+
// without it the count delta still tells a reader the shape of the change.
|
|
76
|
+
added: pinnedNames ? [...names].filter((n) => !pinnedNames.has(n)).sort() : [],
|
|
77
|
+
removed: pinnedNames ? [...pinnedNames].filter((n) => !names.has(n)).sort() : [],
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
/** The refusal a mismatch produces, or the acceptance notice under {@link ACCEPT_ENV}. */
|
|
81
|
+
export function driftMessage(drift, pin = AWS_SPEC_PIN, options = {}) {
|
|
82
|
+
const fatal = options.fatal ?? true;
|
|
83
|
+
const delta = drift.resources - pin.resources;
|
|
84
|
+
const countLine = delta === 0
|
|
85
|
+
? `${drift.resources} resource types, unchanged in count`
|
|
86
|
+
: `${drift.resources} resource types, ${delta > 0 ? "+" : ""}${delta} against the pin`;
|
|
87
|
+
const lines = [
|
|
88
|
+
"The upstream CloudFormation schema has moved since the pinned one.",
|
|
89
|
+
"",
|
|
90
|
+
` pinned ${pin.digest} (${pin.resources} resources, accepted ${pin.accepted})`,
|
|
91
|
+
` upstream ${drift.digest} (${countLine})`,
|
|
92
|
+
];
|
|
93
|
+
if (drift.added.length > 0) {
|
|
94
|
+
lines.push(` added ${drift.added.slice(0, 5).join(", ")}${drift.added.length > 5 ? ` (+${drift.added.length - 5} more)` : ""}`);
|
|
95
|
+
}
|
|
96
|
+
if (drift.removed.length > 0) {
|
|
97
|
+
lines.push(` removed ${drift.removed.slice(0, 5).join(", ")}${drift.removed.length > 5 ? ` (+${drift.removed.length - 5} more)` : ""}`);
|
|
98
|
+
}
|
|
99
|
+
if (fatal) {
|
|
100
|
+
lines.push("", "Generation refuses rather than regenerating against a spec nobody chose:", "a docs or codegen task on an unrelated branch would otherwise rewrite the", "generated types and resource registry with no commit saying why.");
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
// chant #1473 — the type set is identical, so this is upstream editing
|
|
104
|
+
// schemas in place, not a spec swap. Generation continues; whether it
|
|
105
|
+
// changed anything visible is decided by the surface snapshot.
|
|
106
|
+
lines.push("", "The resource set is unchanged, so this is upstream editing schemas in", "place rather than a different spec. Generation continues — whether it", "changed the published API is decided by surface.snapshot.json, which is", "checked against the generated artifacts before anything is packed.");
|
|
107
|
+
}
|
|
108
|
+
lines.push("", "To refresh the pin, confirm the delta is one you want and update", "lexicons/aws/src/spec/pin.ts, in its own commit:", "", ` digest: "${drift.digest}",`, ` resources: ${drift.resources},`, ` accepted: "<today>",`);
|
|
109
|
+
if (fatal) {
|
|
110
|
+
lines.push("", `Or re-run with ${ACCEPT_ENV}=1 to proceed this once and print the same block.`);
|
|
111
|
+
}
|
|
112
|
+
return lines.join("\n");
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Refuse a fetched archive whose RESOURCE SET does not match the pin.
|
|
116
|
+
*
|
|
117
|
+
* Under {@link ACCEPT_ENV} it warns with the same detail instead, so the
|
|
118
|
+
* accept-then-paste loop is one command rather than two.
|
|
119
|
+
*
|
|
120
|
+
* ## Why byte drift alone is a warning (chant #1473)
|
|
121
|
+
*
|
|
122
|
+
* This originally threw on any digest mismatch, which made the aws lexicon
|
|
123
|
+
* unpublishable. `prepack` runs `generate`, `generate` fetches from upstream,
|
|
124
|
+
* and CloudFormation republishes individual schemas several times a day: three
|
|
125
|
+
* distinct digests were observed on 2026-08-03 alone, all with an unchanged
|
|
126
|
+
* count of 1650, and two fetches two hours apart differed in 4 of 1650 files.
|
|
127
|
+
* `chant-v0.39.0` published 13 packages and failed on aws for exactly this,
|
|
128
|
+
* with a pin ~18 hours old.
|
|
129
|
+
*
|
|
130
|
+
* A pin that goes stale by itself within hours cannot gate a release: it does
|
|
131
|
+
* not distinguish "someone regenerated against a spec nobody chose" from
|
|
132
|
+
* "AWS edited a description this afternoon".
|
|
133
|
+
*
|
|
134
|
+
* So the two cases are separated:
|
|
135
|
+
*
|
|
136
|
+
* - **The resource set moved** (a type added or removed) — still a refusal.
|
|
137
|
+
* That always changes the published API, and it is the case #1390 was filed
|
|
138
|
+
* about.
|
|
139
|
+
* - **Only bytes moved**, with an identical type set — a warning. Whether it
|
|
140
|
+
* matters is decided downstream by the surface gate in core's
|
|
141
|
+
* `validateLexiconArtifacts`, which compares the generated API against the
|
|
142
|
+
* committed `surface.snapshot.json`. That gate is exact: a byte change that
|
|
143
|
+
* alters the emitted surface fails the build, and one that does not is
|
|
144
|
+
* correctly ignored.
|
|
145
|
+
*
|
|
146
|
+
* The guarantee is unchanged in substance — nothing ships whose surface was
|
|
147
|
+
* not reviewed — and it is now enforced against the thing that actually
|
|
148
|
+
* matters rather than against an archive that is not stable enough to pin.
|
|
149
|
+
*/
|
|
150
|
+
export function assertPinnedSpec(schemas, options = {}) {
|
|
151
|
+
const pin = options.pin ?? AWS_SPEC_PIN;
|
|
152
|
+
const pinnedNames = options.pinnedNames ?? PINNED_TYPE_NAMES;
|
|
153
|
+
const drift = specDrift(schemas, pinnedNames, pin);
|
|
154
|
+
if (!drift)
|
|
155
|
+
return;
|
|
156
|
+
const env = options.env ?? process.env;
|
|
157
|
+
const warn = options.warn ?? ((m) => console.error(m));
|
|
158
|
+
if (env[ACCEPT_ENV]) {
|
|
159
|
+
warn(driftMessage(drift, pin));
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
// chant #1473 — an identical type set with different bytes is upstream
|
|
163
|
+
// churn, not an unchosen spec. Reported so a stale pin stays visible, but
|
|
164
|
+
// not fatal; the surface gate decides whether it changed anything.
|
|
165
|
+
//
|
|
166
|
+
// Guarded on actually HAVING a previous type set: `specDrift` reports empty
|
|
167
|
+
// added/removed when it has nothing to compare against, which would
|
|
168
|
+
// otherwise read as "no type moved" and downgrade every mismatch.
|
|
169
|
+
// chant #1473 — the pin reports, it does not gate.
|
|
170
|
+
//
|
|
171
|
+
// Refusing here made every aws PR hostage to CloudFormation: the archive
|
|
172
|
+
// gains and edits types through the day, and `generate` runs on every CI
|
|
173
|
+
// job, so an unrelated change goes red the moment upstream moves. Both the
|
|
174
|
+
// 0.39.0 and 0.40.1 releases died this way, and a PR *accepting* the drift
|
|
175
|
+
// was itself refused by a newer drift that arrived while its CI queued.
|
|
176
|
+
//
|
|
177
|
+
// Enforcement lives where the consequence is: core's
|
|
178
|
+
// `validateLexiconArtifacts` compares the generated API against the reviewed
|
|
179
|
+
// `surface.snapshot.json` and, armed by CHANT_RELEASE_GATE, refuses to
|
|
180
|
+
// publish a surface nobody reviewed. A new or removed type always shows up
|
|
181
|
+
// there, so nothing is lost by reporting rather than throwing here — while a
|
|
182
|
+
// description edit, which changes the digest and no declaration, stops
|
|
183
|
+
// costing a red build.
|
|
184
|
+
warn(driftMessage(drift, pin, { fatal: drift.added.length > 0 || drift.removed.length > 0 }));
|
|
185
|
+
}
|