@continuous-excellence/ze-great-dashboard-aws 0.5.0 → 0.6.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
@@ -74,10 +74,16 @@ npm exec -- ze-great-dashboard-aws doctor \
74
74
  --region us-east-1
75
75
  ```
76
76
 
77
- If you retain a captured GitHub OIDC stack, add `--github-oidc-stack-json
78
- github-oidc-deployed-stack.json` to have the doctor warn when the installed package contains a
79
- newer bootstrap template revision. The warning is advisory and does not make the application
80
- deployment perform bootstrap changes.
77
+ After assuming the generated GitHub deploy role, run the canonical blocking consistency check before
78
+ packaging or deployment:
79
+
80
+ ```sh
81
+ npm exec -- ze-great-dashboard-aws bootstrap check \
82
+ --config dashboard-bootstrap.json --format text
83
+ ```
84
+
85
+ Add `--resource-drift` only for a slower scheduled or manually dispatched CloudFormation drift
86
+ audit. Neither form updates stack resources.
81
87
 
82
88
  Package the release. This validates the board and writes `lambda.zip`, `release.json`, and
83
89
  `template.yml` to the output directory:
@@ -127,7 +133,7 @@ does not grant public Lambda invoke permission.
127
133
  To upgrade, install a newer exact package version and repeat package, upload, and deploy. A change to
128
134
  `board.yaml` follows the same path; it does not require a package change.
129
135
 
130
- After upgrading, also check the [bootstrap upgrade guidance](https://github.com/robertfmurdock/ze-great-dashboard/blob/main/docs/aws-bootstrap.md#check-the-bootstrap-template-on-package-upgrades).
136
+ After upgrading, also check the [bootstrap consistency guidance](https://github.com/robertfmurdock/ze-great-dashboard/blob/main/docs/aws-bootstrap.md#check-bootstrap-consistency-on-every-deployment).
131
137
  Compatible releases may add optional bootstrap capabilities without changing the contract version.
132
138
  If your workflow verifies a consumer-owned gateway stack, add `githubOidc.consumerGatewayStackName`
133
139
  to the reviewed manifest and update the GitHub OIDC stack; other consumers do not need to rerun
@@ -144,7 +150,7 @@ for the supported secret reference and integration boundary.
144
150
  | `doctor` | Read-only preflight for an existing parameter file. |
145
151
  | `parameters` | Generate or update application CloudFormation parameters. |
146
152
  | `package` | Validate board YAML and build a deployable Lambda release. |
147
- | `bootstrap` | Produce bootstrap templates, parameters, preflight, and guidance; administrators run AWS commands explicitly. |
153
+ | `bootstrap` | Plan and guide administrator bootstrap work; `bootstrap check` is the explicit live diagnostic used by CI. |
148
154
  | `publish-assets` | Provider-only: publish immutable client assets. Normal consumers use the hosted client. |
149
155
  | `deploy` | Provider-only: automation helper for a provider-managed asset and Lambda deployment. |
150
156
 
@@ -105,6 +105,7 @@ Resources:
105
105
 
106
106
  Outputs:
107
107
  BootstrapContractVersion: { Value: '1' }
108
+ BootstrapTemplateRevision: { Value: '1.1' }
108
109
  ArtifactBucketName: { Value: !Ref ArtifactBucket }
109
110
  ArtifactBucketArn: { Value: !GetAtt ArtifactBucket.Arn }
110
111
  CloudFormationExecutionRoleArn: { Value: !GetAtt CloudFormationExecutionRole.Arn }
@@ -7,6 +7,7 @@ Parameters:
7
7
  GitHubOwnerId: { Type: String, Description: Immutable numeric GitHub owner id }
8
8
  GitHubRepositoryId: { Type: String, Description: Immutable numeric GitHub repository id }
9
9
  GitHubEnvironment: { Type: String, Description: Protected GitHub Environment name }
10
+ CoreBootstrapStackName: { Type: String }
10
11
  ApplicationStackName: { Type: String }
11
12
  ConsumerGatewayStackName:
12
13
  Type: String
@@ -56,6 +57,31 @@ Resources:
56
57
  Effect: Allow
57
58
  Action: [cloudformation:CreateChangeSet, cloudformation:DescribeChangeSet, cloudformation:ExecuteChangeSet, cloudformation:DeleteChangeSet, cloudformation:DescribeStacks, cloudformation:DescribeStackEvents, cloudformation:GetTemplate, cloudformation:GetTemplateSummary]
58
59
  Resource: !Sub 'arn:${AWS::Partition}:cloudformation:${AWS::Region}:${AWS::AccountId}:stack/${ApplicationStackName}/*'
60
+ - Sid: InspectBootstrapStacks
61
+ Effect: Allow
62
+ Action: [cloudformation:DescribeStacks, cloudformation:DetectStackDrift, cloudformation:DescribeStackResourceDrifts]
63
+ Resource:
64
+ - !Sub 'arn:${AWS::Partition}:cloudformation:${AWS::Region}:${AWS::AccountId}:stack/${CoreBootstrapStackName}/*'
65
+ - !Sub 'arn:${AWS::Partition}:cloudformation:${AWS::Region}:${AWS::AccountId}:stack/${AWS::StackName}/*'
66
+ # Detection-status requests are keyed by an opaque detection id, so AWS does not
67
+ # support scoping this one read action to a stack ARN.
68
+ - Sid: ReadBootstrapDriftDetectionStatus
69
+ Effect: Allow
70
+ Action: cloudformation:DescribeStackDriftDetectionStatus
71
+ Resource: '*'
72
+ # CloudFormation uses the caller's read permissions when these administrator-created
73
+ # stacks have no service role. Keep resource inspection on the exact bootstrap bucket
74
+ # and roles whose properties drift detection evaluates.
75
+ - Sid: InspectBootstrapBucketConfiguration
76
+ Effect: Allow
77
+ Action: [s3:GetBucketAcl, s3:GetBucketPolicy, s3:GetBucketPublicAccessBlock, s3:GetEncryptionConfiguration, s3:GetBucketOwnershipControls, s3:GetBucketTagging]
78
+ Resource: !Sub 'arn:${AWS::Partition}:s3:::${ArtifactBucketName}'
79
+ - Sid: InspectBootstrapRoleConfiguration
80
+ Effect: Allow
81
+ Action: [iam:GetRole, iam:GetRolePolicy, iam:ListRolePolicies, iam:ListAttachedRolePolicies, iam:ListRoleTags]
82
+ Resource:
83
+ - !Ref CloudFormationExecutionRoleArn
84
+ - !Sub 'arn:${AWS::Partition}:iam::${AWS::AccountId}:role/${ApplicationStackName}-github-deploy'
59
85
  - !If
60
86
  - HasConsumerGatewayStack
61
87
  - Sid: ReadConsumerGatewayStack
@@ -71,5 +97,5 @@ Resources:
71
97
 
72
98
  Outputs:
73
99
  BootstrapContractVersion: { Value: '2' }
74
- BootstrapTemplateRevision: { Value: '2.1' }
100
+ BootstrapTemplateRevision: { Value: '2.2' }
75
101
  GitHubDeployRoleArn: { Value: !GetAtt GitHubDeployRole.Arn }
@@ -0,0 +1,45 @@
1
+ import { type BootstrapConfig, type BootstrapConsistency, type BootstrapKind } from './bootstrap.js';
2
+ export type BootstrapResourceDifference = {
3
+ path?: string;
4
+ differenceType?: string;
5
+ expectedValue?: string;
6
+ actualValue?: string;
7
+ };
8
+ export type BootstrapResourceDrift = {
9
+ logicalId: string;
10
+ resourceType?: string;
11
+ status?: string;
12
+ differences: BootstrapResourceDifference[];
13
+ };
14
+ export type BootstrapResourceDriftResult = {
15
+ ok: boolean;
16
+ status: string;
17
+ detectionId?: string;
18
+ reason?: string;
19
+ resources: BootstrapResourceDrift[];
20
+ };
21
+ export type BootstrapStackCheck = {
22
+ kind: BootstrapKind;
23
+ stackName: string;
24
+ stackStatus?: string;
25
+ contractVersion: string;
26
+ templateRevision?: string;
27
+ templateSha256: string;
28
+ consistency: BootstrapConsistency;
29
+ resourceDrift?: BootstrapResourceDriftResult;
30
+ };
31
+ export type BootstrapCheck = {
32
+ ok: boolean;
33
+ packageVersion: string;
34
+ stacks: BootstrapStackCheck[];
35
+ };
36
+ export type BootstrapCheckDependencies = {
37
+ execute(command: string, args: string[]): Promise<string>;
38
+ sleep?(milliseconds: number): Promise<void>;
39
+ now?(): number;
40
+ };
41
+ export declare function formatBootstrapCheckText(result: BootstrapCheck): string;
42
+ /** Runs the explicitly named live bootstrap diagnostic; it never changes stack resources. */
43
+ export declare function checkBootstrap(config: BootstrapConfig, options: {
44
+ resourceDrift?: boolean;
45
+ }, dependencies: BootstrapCheckDependencies): Promise<BootstrapCheck>;
@@ -5,6 +5,9 @@ export type CloudFormationParameterValue = {
5
5
  UsePreviousValue?: boolean;
6
6
  };
7
7
  export type DeployedBootstrapStack = {
8
+ StackName?: string;
9
+ StackId?: string;
10
+ StackStatus?: string;
8
11
  Parameters?: CloudFormationParameterValue[];
9
12
  Outputs?: {
10
13
  OutputKey: string;
@@ -31,10 +34,36 @@ export type BootstrapConfig = {
31
34
  consumerGatewayStackName?: string;
32
35
  };
33
36
  };
37
+ export type BootstrapTemplateInspection = {
38
+ kind: BootstrapKind;
39
+ path: string;
40
+ contractVersion: string;
41
+ templateRevision?: string;
42
+ sha256: string;
43
+ resources: {
44
+ logicalId: string;
45
+ type: string;
46
+ }[];
47
+ iamActions: string[];
48
+ };
49
+ export type BootstrapPlan = {
50
+ packageVersion: string;
51
+ packageTemplates: BootstrapTemplateInspection[];
52
+ configuration: BootstrapConfig;
53
+ notes: string[];
54
+ };
55
+ export type BootstrapConsistency = {
56
+ ok: boolean;
57
+ mismatches: string[];
58
+ };
34
59
  export declare function bootstrapTemplatePath(kind: BootstrapKind): Promise<string>;
35
60
  export declare function bootstrapTemplate(kind: BootstrapKind): Promise<string>;
36
61
  export declare function bootstrapContractVersion(template: string): string;
37
62
  export declare function bootstrapTemplateRevision(template: string): string;
63
+ /** Returns installed templates and a reviewable, non-secret plan without external calls. */
64
+ export declare function bootstrapPlan(config: BootstrapConfig): Promise<BootstrapPlan>;
65
+ /** Compares describe-stacks data with manifest and installed-template values without network access. */
66
+ export declare function bootstrapConsistency(kind: BootstrapKind, config: BootstrapConfig, stackInput: unknown, expectedContract: string, expectedRevision?: string, coreOutputs?: Record<string, string | undefined>): BootstrapConsistency;
38
67
  /** Merges a new parameter set with deployed values without silently dropping configuration. */
39
68
  export declare function mergeBootstrapParameters(requested: CloudFormationParameterValue[], deployed: CloudFormationParameterValue[]): CloudFormationParameterValue[];
40
69
  /** Validates a caller-captured `describe-stacks` result before an upgrade merges it locally. */