@pipeline-builder/pipeline-manager 0.0.1

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.
Files changed (222) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +145 -0
  3. package/cdk.json +91 -0
  4. package/config.yml +94 -0
  5. package/dist/agent/ai.d.ts +48 -0
  6. package/dist/agent/ai.d.ts.map +1 -0
  7. package/dist/agent/ai.js +149 -0
  8. package/dist/agent/bootstrap.d.ts +39 -0
  9. package/dist/agent/bootstrap.d.ts.map +1 -0
  10. package/dist/agent/bootstrap.js +66 -0
  11. package/dist/agent/env-file.d.ts +17 -0
  12. package/dist/agent/env-file.d.ts.map +1 -0
  13. package/dist/agent/env-file.js +47 -0
  14. package/dist/agent/executor.d.ts +30 -0
  15. package/dist/agent/executor.d.ts.map +1 -0
  16. package/dist/agent/executor.js +60 -0
  17. package/dist/agent/health.d.ts +43 -0
  18. package/dist/agent/health.d.ts.map +1 -0
  19. package/dist/agent/health.js +109 -0
  20. package/dist/agent/ports.d.ts +26 -0
  21. package/dist/agent/ports.d.ts.map +1 -0
  22. package/dist/agent/ports.js +132 -0
  23. package/dist/agent/post-steps.d.ts +61 -0
  24. package/dist/agent/post-steps.d.ts.map +1 -0
  25. package/dist/agent/post-steps.js +131 -0
  26. package/dist/agent/prereqs.d.ts +26 -0
  27. package/dist/agent/prereqs.d.ts.map +1 -0
  28. package/dist/agent/prereqs.js +134 -0
  29. package/dist/agent/targets.d.ts +128 -0
  30. package/dist/agent/targets.d.ts.map +1 -0
  31. package/dist/agent/targets.js +265 -0
  32. package/dist/agent/tools.d.ts +13 -0
  33. package/dist/agent/tools.d.ts.map +1 -0
  34. package/dist/agent/tools.js +75 -0
  35. package/dist/agent/troubleshoot.d.ts +30 -0
  36. package/dist/agent/troubleshoot.d.ts.map +1 -0
  37. package/dist/agent/troubleshoot.js +87 -0
  38. package/dist/boilerplate.d.ts +3 -0
  39. package/dist/boilerplate.d.ts.map +1 -0
  40. package/dist/boilerplate.js +54 -0
  41. package/dist/cdk.json +91 -0
  42. package/dist/cli.d.ts +62 -0
  43. package/dist/cli.d.ts.map +1 -0
  44. package/dist/cli.js +463 -0
  45. package/dist/commands/audit-stacks.d.ts +24 -0
  46. package/dist/commands/audit-stacks.d.ts.map +1 -0
  47. package/dist/commands/audit-stacks.js +182 -0
  48. package/dist/commands/audit-tokens.d.ts +21 -0
  49. package/dist/commands/audit-tokens.d.ts.map +1 -0
  50. package/dist/commands/audit-tokens.js +153 -0
  51. package/dist/commands/bootstrap.d.ts +11 -0
  52. package/dist/commands/bootstrap.d.ts.map +1 -0
  53. package/dist/commands/bootstrap.js +159 -0
  54. package/dist/commands/create-pat.d.ts +27 -0
  55. package/dist/commands/create-pat.d.ts.map +1 -0
  56. package/dist/commands/create-pat.js +194 -0
  57. package/dist/commands/create-pipeline.d.ts +12 -0
  58. package/dist/commands/create-pipeline.d.ts.map +1 -0
  59. package/dist/commands/create-pipeline.js +315 -0
  60. package/dist/commands/deploy.d.ts +15 -0
  61. package/dist/commands/deploy.d.ts.map +1 -0
  62. package/dist/commands/deploy.js +157 -0
  63. package/dist/commands/entity-get.d.ts +51 -0
  64. package/dist/commands/entity-get.d.ts.map +1 -0
  65. package/dist/commands/entity-get.js +69 -0
  66. package/dist/commands/entity-list.d.ts +39 -0
  67. package/dist/commands/entity-list.d.ts.map +1 -0
  68. package/dist/commands/entity-list.js +88 -0
  69. package/dist/commands/get-pipeline.d.ts +13 -0
  70. package/dist/commands/get-pipeline.d.ts.map +1 -0
  71. package/dist/commands/get-pipeline.js +49 -0
  72. package/dist/commands/get-plugin.d.ts +13 -0
  73. package/dist/commands/get-plugin.d.ts.map +1 -0
  74. package/dist/commands/get-plugin.js +51 -0
  75. package/dist/commands/instantiate-template.d.ts +20 -0
  76. package/dist/commands/instantiate-template.d.ts.map +1 -0
  77. package/dist/commands/instantiate-template.js +274 -0
  78. package/dist/commands/list-pipelines.d.ts +20 -0
  79. package/dist/commands/list-pipelines.d.ts.map +1 -0
  80. package/dist/commands/list-pipelines.js +99 -0
  81. package/dist/commands/list-plugins.d.ts +20 -0
  82. package/dist/commands/list-plugins.d.ts.map +1 -0
  83. package/dist/commands/list-plugins.js +92 -0
  84. package/dist/commands/login.d.ts +21 -0
  85. package/dist/commands/login.d.ts.map +1 -0
  86. package/dist/commands/login.js +174 -0
  87. package/dist/commands/new-plugin.d.ts +12 -0
  88. package/dist/commands/new-plugin.d.ts.map +1 -0
  89. package/dist/commands/new-plugin.js +129 -0
  90. package/dist/commands/org-export.d.ts +25 -0
  91. package/dist/commands/org-export.d.ts.map +1 -0
  92. package/dist/commands/org-export.js +100 -0
  93. package/dist/commands/provision.d.ts +122 -0
  94. package/dist/commands/provision.d.ts.map +1 -0
  95. package/dist/commands/provision.js +867 -0
  96. package/dist/commands/redrive-events.d.ts +24 -0
  97. package/dist/commands/redrive-events.d.ts.map +1 -0
  98. package/dist/commands/redrive-events.js +127 -0
  99. package/dist/commands/register.d.ts +38 -0
  100. package/dist/commands/register.d.ts.map +1 -0
  101. package/dist/commands/register.js +160 -0
  102. package/dist/commands/setup-events.d.ts +15 -0
  103. package/dist/commands/setup-events.d.ts.map +1 -0
  104. package/dist/commands/setup-events.js +168 -0
  105. package/dist/commands/status.d.ts +11 -0
  106. package/dist/commands/status.d.ts.map +1 -0
  107. package/dist/commands/status.js +81 -0
  108. package/dist/commands/store-token.d.ts +26 -0
  109. package/dist/commands/store-token.d.ts.map +1 -0
  110. package/dist/commands/store-token.js +305 -0
  111. package/dist/commands/synth.d.ts +21 -0
  112. package/dist/commands/synth.d.ts.map +1 -0
  113. package/dist/commands/synth.js +158 -0
  114. package/dist/commands/upload-plugin.d.ts +21 -0
  115. package/dist/commands/upload-plugin.d.ts.map +1 -0
  116. package/dist/commands/upload-plugin.js +275 -0
  117. package/dist/commands/validate-plugin.d.ts +12 -0
  118. package/dist/commands/validate-plugin.d.ts.map +1 -0
  119. package/dist/commands/validate-plugin.js +175 -0
  120. package/dist/commands/validate-templates.d.ts +11 -0
  121. package/dist/commands/validate-templates.d.ts.map +1 -0
  122. package/dist/commands/validate-templates.js +116 -0
  123. package/dist/commands/version.d.ts +12 -0
  124. package/dist/commands/version.d.ts.map +1 -0
  125. package/dist/commands/version.js +216 -0
  126. package/dist/config/cli.constants.d.ts +116 -0
  127. package/dist/config/cli.constants.d.ts.map +1 -0
  128. package/dist/config/cli.constants.js +194 -0
  129. package/dist/config.yml +94 -0
  130. package/dist/lambda/token-renew-handler.d.ts +2 -0
  131. package/dist/lambda/token-renew-handler.d.ts.map +1 -0
  132. package/dist/lambda/token-renew-handler.js +125 -0
  133. package/dist/templates/events-stack.json +174 -0
  134. package/dist/templates/token-renew-stack.json +122 -0
  135. package/dist/types/config.d.ts +53 -0
  136. package/dist/types/config.d.ts.map +1 -0
  137. package/dist/types/config.js +4 -0
  138. package/dist/types/error.d.ts +61 -0
  139. package/dist/types/error.d.ts.map +1 -0
  140. package/dist/types/error.js +35 -0
  141. package/dist/types/index.d.ts +9 -0
  142. package/dist/types/index.d.ts.map +1 -0
  143. package/dist/types/index.js +11 -0
  144. package/dist/types/pipeline-template.d.ts +48 -0
  145. package/dist/types/pipeline-template.d.ts.map +1 -0
  146. package/dist/types/pipeline-template.js +4 -0
  147. package/dist/types/pipeline.d.ts +121 -0
  148. package/dist/types/pipeline.d.ts.map +1 -0
  149. package/dist/types/pipeline.js +4 -0
  150. package/dist/types/plugin.d.ts +135 -0
  151. package/dist/types/plugin.d.ts.map +1 -0
  152. package/dist/types/plugin.js +4 -0
  153. package/dist/utils/api-client.d.ts +26 -0
  154. package/dist/utils/api-client.d.ts.map +1 -0
  155. package/dist/utils/api-client.js +151 -0
  156. package/dist/utils/audit-log.d.ts +8 -0
  157. package/dist/utils/audit-log.d.ts.map +1 -0
  158. package/dist/utils/audit-log.js +57 -0
  159. package/dist/utils/auth-guard.d.ts +20 -0
  160. package/dist/utils/auth-guard.d.ts.map +1 -0
  161. package/dist/utils/auth-guard.js +22 -0
  162. package/dist/utils/auth-utils.d.ts +68 -0
  163. package/dist/utils/auth-utils.d.ts.map +1 -0
  164. package/dist/utils/auth-utils.js +77 -0
  165. package/dist/utils/aws-env.d.ts +21 -0
  166. package/dist/utils/aws-env.d.ts.map +1 -0
  167. package/dist/utils/aws-env.js +34 -0
  168. package/dist/utils/aws-secrets.d.ts +48 -0
  169. package/dist/utils/aws-secrets.d.ts.map +1 -0
  170. package/dist/utils/aws-secrets.js +115 -0
  171. package/dist/utils/banner.d.ts +19 -0
  172. package/dist/utils/banner.d.ts.map +1 -0
  173. package/dist/utils/banner.js +52 -0
  174. package/dist/utils/cdk-utils.d.ts +74 -0
  175. package/dist/utils/cdk-utils.d.ts.map +1 -0
  176. package/dist/utils/cdk-utils.js +152 -0
  177. package/dist/utils/command-utils.d.ts +75 -0
  178. package/dist/utils/command-utils.d.ts.map +1 -0
  179. package/dist/utils/command-utils.js +155 -0
  180. package/dist/utils/config-loader.d.ts +33 -0
  181. package/dist/utils/config-loader.d.ts.map +1 -0
  182. package/dist/utils/config-loader.js +154 -0
  183. package/dist/utils/cron.d.ts +28 -0
  184. package/dist/utils/cron.d.ts.map +1 -0
  185. package/dist/utils/cron.js +119 -0
  186. package/dist/utils/deploy-runner.d.ts +38 -0
  187. package/dist/utils/deploy-runner.d.ts.map +1 -0
  188. package/dist/utils/deploy-runner.js +112 -0
  189. package/dist/utils/error-handler.d.ts +29 -0
  190. package/dist/utils/error-handler.d.ts.map +1 -0
  191. package/dist/utils/error-handler.js +302 -0
  192. package/dist/utils/list-command-utils.d.ts +23 -0
  193. package/dist/utils/list-command-utils.d.ts.map +1 -0
  194. package/dist/utils/list-command-utils.js +57 -0
  195. package/dist/utils/output-utils.d.ts +40 -0
  196. package/dist/utils/output-utils.d.ts.map +1 -0
  197. package/dist/utils/output-utils.js +250 -0
  198. package/dist/utils/pipeline-config.d.ts +33 -0
  199. package/dist/utils/pipeline-config.d.ts.map +1 -0
  200. package/dist/utils/pipeline-config.js +55 -0
  201. package/dist/utils/platform-secret.d.ts +27 -0
  202. package/dist/utils/platform-secret.d.ts.map +1 -0
  203. package/dist/utils/platform-secret.js +92 -0
  204. package/dist/utils/plugin-resolver.d.ts +17 -0
  205. package/dist/utils/plugin-resolver.d.ts.map +1 -0
  206. package/dist/utils/plugin-resolver.js +101 -0
  207. package/dist/utils/preflight.d.ts +26 -0
  208. package/dist/utils/preflight.d.ts.map +1 -0
  209. package/dist/utils/preflight.js +59 -0
  210. package/dist/utils/rate-limiter.d.ts +15 -0
  211. package/dist/utils/rate-limiter.d.ts.map +1 -0
  212. package/dist/utils/rate-limiter.js +164 -0
  213. package/dist/utils/registry.d.ts +86 -0
  214. package/dist/utils/registry.d.ts.map +1 -0
  215. package/dist/utils/registry.js +140 -0
  216. package/dist/utils/response-utils.d.ts +21 -0
  217. package/dist/utils/response-utils.d.ts.map +1 -0
  218. package/dist/utils/response-utils.js +70 -0
  219. package/dist/utils/tls.d.ts +52 -0
  220. package/dist/utils/tls.d.ts.map +1 -0
  221. package/dist/utils/tls.js +88 -0
  222. package/package.json +181 -0
@@ -0,0 +1,182 @@
1
+ // Copyright 2026 Pipeline Builder Contributors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import { CloudFormationClient, DescribeStacksCommand } from '@aws-sdk/client-cloudformation';
4
+ import { Command } from 'commander';
5
+ import { applyAwsProfile, resolveAwsRegion } from '../utils/aws-env.js';
6
+ import { createAuthenticatedClientAsync, printCommandHeader, printSslWarning, withProfileOption, withRegionOption, withSslOptions } from '../utils/command-utils.js';
7
+ import { ERROR_CODES, handleError } from '../utils/error-handler.js';
8
+ import { printError, printInfo, printSection, printSuccess, printWarning } from '../utils/output-utils.js';
9
+ const ACTIVE_STATUSES = [
10
+ 'CREATE_COMPLETE', 'UPDATE_COMPLETE', 'UPDATE_ROLLBACK_COMPLETE',
11
+ 'IMPORT_COMPLETE', 'IMPORT_ROLLBACK_COMPLETE',
12
+ ];
13
+ /**
14
+ * Registers the `audit-stacks` command with the CLI program.
15
+ *
16
+ * Diffs CloudFormation stacks (filtered to those tagged with `pipeline-builder`)
17
+ * against the platform's `pipeline_registry` table. Surfaces:
18
+ * - **Orphaned stacks**: tagged stacks with no DB record (likely leftovers after
19
+ * a pipeline was deleted from the dashboard but the CDK stack stayed in AWS).
20
+ * - **Missing stacks**: registry entries pointing to stacks that no longer exist
21
+ * in CloudFormation (likely after a manual `aws cloudformation delete-stack`).
22
+ *
23
+ * Designed for cron use:
24
+ * - Exits 0 when there are no findings.
25
+ * - Exits 1 when at least one orphaned or missing stack is found.
26
+ * - Exits 2 on AWS errors / scan failures.
27
+ *
28
+ * @example
29
+ * ```bash
30
+ * pipeline-manager audit stacks --region us-east-1
31
+ * pipeline-manager audit stacks --org acme --json
32
+ * ```
33
+ */
34
+ export function auditStacks(program) {
35
+ withSslOptions(withProfileOption(withRegionOption(program
36
+ .command('stacks')
37
+ .description('Diff CloudFormation stacks vs pipeline_registry to find orphaned or missing CDK deployments')))
38
+ .option('--org <orgId>', 'Filter both registry and stack scan to a single org')
39
+ .option('--json', 'Output results as JSON', false))
40
+ .action(async (options) => {
41
+ const executionId = printCommandHeader('Audit Stacks', undefined, { quiet: options.json });
42
+ printSslWarning(options.verifySsl);
43
+ const region = resolveAwsRegion(options.region);
44
+ // Honor --profile for the SDK CloudFormation client below (without this, the
45
+ // scan always hit the default account and could diff the registry against
46
+ // the WRONG account's stacks → bogus orphaned/missing findings).
47
+ applyAwsProfile(options.profile);
48
+ try {
49
+ // Fetch the platform's view of registered pipelines.
50
+ // Progress goes to stdout, so suppress it in --json mode to keep the JSON payload clean for piping.
51
+ if (!options.json)
52
+ printInfo('Fetching pipeline registry from platform', { org: options.org ?? '(all)' });
53
+ const client = await createAuthenticatedClientAsync(options);
54
+ const registryRes = await client.get(`/api/pipelines/registry${options.org ? `?orgId=${encodeURIComponent(options.org)}` : ''}`);
55
+ const entries = registryRes?.entries
56
+ ?? registryRes?.data?.entries
57
+ ?? [];
58
+ // Fetch stacks from CloudFormation. DescribeStacks (no StackName) returns every
59
+ // active stack WITH its tags in one paginated sweep — avoiding the N+1
60
+ // DescribeStacks-per-stack the old ListStacks path needed (ListStacks omits tags)
61
+ // and the API throttling it caused on accounts with many stacks.
62
+ if (!options.json)
63
+ printInfo('Listing CloudFormation stacks', { region });
64
+ const cfn = new CloudFormationClient({ region });
65
+ const stacks = [];
66
+ const activeStatuses = new Set(ACTIVE_STATUSES);
67
+ let nextToken;
68
+ let pages = 0;
69
+ // Backstop only (~20k stacks at ~100/page), not an expected limit. A FULL scan
70
+ // matters: truncating would diff the registry against an incomplete stack set and
71
+ // report live stacks as `missing-stack`. So if this is ever hit, warn LOUDLY rather
72
+ // than silently under-reporting (the previous code capped at 20 pages silently).
73
+ const MAX_PAGES = 200;
74
+ let truncated = false;
75
+ do {
76
+ const resp = await cfn.send(new DescribeStacksCommand({ NextToken: nextToken }));
77
+ for (const stack of resp.Stacks ?? []) {
78
+ if (!stack.StackName)
79
+ continue;
80
+ if (!activeStatuses.has(stack.StackStatus ?? ''))
81
+ continue; // skip in-progress/rolled-back/deleted
82
+ const tags = stack.Tags ?? [];
83
+ const pbTag = tags.find((t) => t.Key === 'pipeline-builder')?.Value;
84
+ const orgTag = tags.find((t) => t.Key === 'OrgId' || t.Key === 'orgId')?.Value;
85
+ if (!pbTag)
86
+ continue; // Not a pipeline-builder stack.
87
+ if (options.org && orgTag && orgTag !== options.org)
88
+ continue; // Wrong org filter.
89
+ stacks.push({
90
+ stackName: stack.StackName,
91
+ stackStatus: stack.StackStatus ?? 'UNKNOWN',
92
+ region,
93
+ pipelineBuilderTag: pbTag,
94
+ orgIdTag: orgTag,
95
+ creationTime: stack.CreationTime,
96
+ });
97
+ }
98
+ nextToken = resp.NextToken;
99
+ pages++;
100
+ if (nextToken && pages >= MAX_PAGES) {
101
+ truncated = true;
102
+ break;
103
+ }
104
+ } while (nextToken);
105
+ if (truncated) {
106
+ printWarning(`Stack scan hit the ${MAX_PAGES}-page safety cap — results may be INCOMPLETE and 'missing-stack' findings could be false. Narrow by --region/--org, or raise MAX_PAGES.`);
107
+ }
108
+ // Diff.
109
+ const registryStackNames = new Set(entries.map((e) => e.stackName).filter((n) => !!n));
110
+ const cfnStackNames = new Set(stacks.map((s) => s.stackName));
111
+ const findings = [];
112
+ for (const stack of stacks) {
113
+ if (!registryStackNames.has(stack.stackName)) {
114
+ findings.push({
115
+ type: 'orphaned-stack',
116
+ stackName: stack.stackName,
117
+ detail: `CloudFormation stack tagged pipeline-builder=${stack.pipelineBuilderTag ?? '(unset)'} has no matching pipeline_registry entry`,
118
+ });
119
+ }
120
+ }
121
+ for (const entry of entries) {
122
+ if (entry.stackName && !cfnStackNames.has(entry.stackName)) {
123
+ findings.push({
124
+ type: 'missing-stack',
125
+ stackName: entry.stackName,
126
+ pipelineId: entry.pipelineId,
127
+ pipelineName: entry.pipelineName,
128
+ detail: `Registry entry references stack ${entry.stackName} but no such stack exists in CloudFormation`,
129
+ });
130
+ }
131
+ }
132
+ // A truncated (incomplete) scan is a finding in itself: it can both miss
133
+ // real drift AND emit false missing-stack findings, so it must exit
134
+ // non-zero and be visible in the JSON (mirrors audit-tokens).
135
+ const exitCode = (findings.length > 0 || truncated) ? 1 : 0;
136
+ if (options.json) {
137
+ console.log(JSON.stringify({
138
+ scannedAt: new Date().toISOString(),
139
+ region,
140
+ orgFilter: options.org,
141
+ registryEntries: entries.length,
142
+ cfnStacks: stacks.length,
143
+ truncated,
144
+ findings,
145
+ executionId,
146
+ }, null, 2));
147
+ }
148
+ else {
149
+ printSection('Audit Results');
150
+ printInfo('Counts', {
151
+ registryEntries: String(entries.length),
152
+ cfnStacks: String(stacks.length),
153
+ findings: String(findings.length),
154
+ });
155
+ if (findings.length === 0) {
156
+ printSuccess('No drift between pipeline_registry and CloudFormation');
157
+ }
158
+ else {
159
+ for (const f of findings) {
160
+ if (f.type === 'orphaned-stack') {
161
+ printWarning(`ORPHANED ${f.stackName} — ${f.detail}`);
162
+ }
163
+ else {
164
+ printWarning(`MISSING ${f.stackName} (pipeline ${f.pipelineId ?? '?'}) — ${f.detail}`);
165
+ }
166
+ }
167
+ printError(`${findings.length} drift finding${findings.length === 1 ? '' : 's'}. Review and reconcile manually.`);
168
+ }
169
+ }
170
+ process.exit(exitCode);
171
+ }
172
+ catch (error) {
173
+ handleError(error, ERROR_CODES.API_REQUEST, {
174
+ debug: program.opts().debug,
175
+ exit: false,
176
+ context: { command: 'audit-stacks', executionId },
177
+ });
178
+ process.exit(2);
179
+ }
180
+ });
181
+ }
182
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXVkaXQtc3RhY2tzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NvbW1hbmRzL2F1ZGl0LXN0YWNrcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwrQ0FBK0M7QUFDL0Msc0NBQXNDO0FBRXRDLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxxQkFBcUIsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBQzdGLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFDcEMsT0FBTyxFQUFFLGVBQWUsRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ3hFLE9BQU8sRUFBRSw4QkFBOEIsRUFBRSxrQkFBa0IsRUFBRSxlQUFlLEVBQUUsaUJBQWlCLEVBQUUsZ0JBQWdCLEVBQUUsY0FBYyxFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDckssT0FBTyxFQUFFLFdBQVcsRUFBRSxXQUFXLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUNyRSxPQUFPLEVBQUUsVUFBVSxFQUFFLFNBQVMsRUFBRSxZQUFZLEVBQUUsWUFBWSxFQUFFLFlBQVksRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBMkIzRyxNQUFNLGVBQWUsR0FBRztJQUN0QixpQkFBaUIsRUFBRSxpQkFBaUIsRUFBRSwwQkFBMEI7SUFDaEUsaUJBQWlCLEVBQUUsMEJBQTBCO0NBQzlDLENBQUM7QUFFRjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FvQkc7QUFDSCxNQUFNLFVBQVUsV0FBVyxDQUFDLE9BQWdCO0lBQzFDLGNBQWMsQ0FDWixpQkFBaUIsQ0FDZixnQkFBZ0IsQ0FBQyxPQUFPO1NBQ3JCLE9BQU8sQ0FBQyxRQUFRLENBQUM7U0FDakIsV0FBVyxDQUFDLDZGQUE2RixDQUFDLENBQUMsQ0FDL0c7U0FDRSxNQUFNLENBQUMsZUFBZSxFQUFFLHFEQUFxRCxDQUFDO1NBQzlFLE1BQU0sQ0FBQyxRQUFRLEVBQUUsd0JBQXdCLEVBQUUsS0FBSyxDQUFDLENBQ3JEO1NB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QUMsQ0FBQzt3QkFDM0YsQ0FBQztvQkFDSCxDQUFDO29CQUNELFVBQVUsQ0FBQyxHQUFHLFFBQVEsQ0FBQyxNQUFNLGlCQUFpQixRQUFRLENBQUMsTUFBTSxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxHQUFHLGtDQUFrQyxDQUFDLENBQUM7Z0JBQ3BILENBQUM7WUFDSCxDQUFDO1lBQ0QsT0FBTyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUN6QixDQUFDO1FBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztZQUNmLFdBQVcsQ0FBQyxLQUFLLEVBQUUsV0FBVyxDQUFDLFdBQVcsRUFBRTtnQkFDMUMsS0FBSyxFQUFFLE9BQU8sQ0FBQyxJQUFJLEVBQUUsQ0FBQyxLQUFLO2dCQUMzQixJQUFJLEVBQUUsS0FBSztnQkFDWCxPQUFPLEVBQUUsRUFBRSxPQUFPLEVBQUUsY0FBYyxFQUFFLFdBQVcsRUFBRTthQUNsRCxDQUFDLENBQUM7WUFDSCxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ2xCLENBQUM7SUFDSCxDQUFDLENBQUMsQ0FBQztBQUNQLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgMjAyNiBQaXBlbGluZSBCdWlsZGVyIENvbnRyaWJ1dG9yc1xuLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcblxuaW1wb3J0IHsgQ2xvdWRGb3JtYXRpb25DbGllbnQsIERlc2NyaWJlU3RhY2tzQ29tbWFuZCB9IGZyb20gJ0Bhd3Mtc2RrL2NsaWVudC1jbG91ZGZvcm1hdGlvbic7XG5pbXBvcnQgeyBDb21tYW5kIH0gZnJvbSAnY29tbWFuZGVyJztcbmltcG9ydCB7IGFwcGx5QXdzUHJvZmlsZSwgcmVzb2x2ZUF3c1JlZ2lvbiB9IGZyb20gJy4uL3V0aWxzL2F3cy1lbnYuanMnO1xuaW1wb3J0IHsgY3JlYXRlQXV0aGVudGljYXRlZENsaWVudEFzeW5jLCBwcmludENvbW1hbmRIZWFkZXIsIHByaW50U3NsV2FybmluZywgd2l0aFByb2ZpbGVPcHRpb24sIHdpdGhSZWdpb25PcHRpb24sIHdpdGhTc2xPcHRpb25zIH0gZnJvbSAnLi4vdXRpbHMvY29tbWFuZC11dGlscy5qcyc7XG5pbXBvcnQgeyBFUlJPUl9DT0RFUywgaGFuZGxlRXJyb3IgfSBmcm9tICcuLi91dGlscy9lcnJvci1oYW5kbGVyLmpzJztcbmltcG9ydCB7IHByaW50RXJyb3IsIHByaW50SW5mbywgcHJpbnRTZWN0aW9uLCBwcmludFN1Y2Nlc3MsIHByaW50V2FybmluZyB9IGZyb20gJy4uL3V0aWxzL291dHB1dC11dGlscy5qcyc7XG5cbmludGVyZmFjZSBSZWdpc3RyeUVudHJ5IHtcbiAgcGlwZWxpbmVJZDogc3RyaW5nO1xuICBwaXBlbGluZUFybjogc3RyaW5nO1xuICBwaXBlbGluZU5hbWU6IHN0cmluZztcbiAgc3RhY2tOYW1lPzogc3RyaW5nO1xuICByZWdpb24/OiBzdHJpbmc7XG59XG5cbmludGVyZmFjZSBTdGFja0luZm8ge1xuICBzdGFja05hbWU6IHN0cmluZztcbiAgc3RhY2tTdGF0dXM6IHN0cmluZztcbiAgcmVnaW9uOiBzdHJpbmc7XG4gIHBpcGVsaW5lQnVpbGRlclRhZz86IHN0cmluZztcbiAgb3JnSWRUYWc/OiBzdHJpbmc7XG4gIGNyZWF0aW9uVGltZT86IERhdGU7XG59XG5cbmludGVyZmFjZSBBdWRpdEZpbmRpbmcge1xuICB0eXBlOiAnb3JwaGFuZWQtc3RhY2snIHwgJ21pc3Npbmctc3RhY2snO1xuICBzdGFja05hbWU/OiBzdHJpbmc7XG4gIHBpcGVsaW5lSWQ/OiBzdHJpbmc7XG4gIHBpcGVsaW5lTmFtZT86IHN0cmluZztcbiAgZGV0YWlsOiBzdHJpbmc7XG59XG5cbmNvbnN0IEFDVElWRV9TVEFUVVNFUyA9IFtcbiAgJ0NSRUFURV9DT01QTEVURScsICdVUERBVEVfQ09NUExFVEUnLCAnVVBEQVRFX1JPTExCQUNLX0NPTVBMRVRFJyxcbiAgJ0lNUE9SVF9DT01QTEVURScsICdJTVBPUlRfUk9MTEJBQ0tfQ09NUExFVEUnLFxuXTtcblxuLyoqXG4gKiBSZWdpc3RlcnMgdGhlIGBhdWRpdC1zdGFja3NgIGNvbW1hbmQgd2l0aCB0aGUgQ0xJIHByb2dyYW0uXG4gKlxuICogRGlmZnMgQ2xvdWRGb3JtYXRpb24gc3RhY2tzIChmaWx0ZXJlZCB0byB0aG9zZSB0YWdnZWQgd2l0aCBgcGlwZWxpbmUtYnVpbGRlcmApXG4gKiBhZ2FpbnN0IHRoZSBwbGF0Zm9ybSdzIGBwaXBlbGluZV9yZWdpc3RyeWAgdGFibGUuIFN1cmZhY2VzOlxuICogICAtICoqT3JwaGFuZWQgc3RhY2tzKio6IHRhZ2dlZCBzdGFja3Mgd2l0aCBubyBEQiByZWNvcmQgKGxpa2VseSBsZWZ0b3ZlcnMgYWZ0ZXJcbiAqICAgICBhIHBpcGVsaW5lIHdhcyBkZWxldGVkIGZyb20gdGhlIGRhc2hib2FyZCBidXQgdGhlIENESyBzdGFjayBzdGF5ZWQgaW4gQVdTKS5cbiAqICAgLSAqKk1pc3Npbmcgc3RhY2tzKio6IHJlZ2lzdHJ5IGVudHJpZXMgcG9pbnRpbmcgdG8gc3RhY2tzIHRoYXQgbm8gbG9uZ2VyIGV4aXN0XG4gKiAgICAgaW4gQ2xvdWRGb3JtYXRpb24gKGxpa2VseSBhZnRlciBhIG1hbnVhbCBgYXdzIGNsb3VkZm9ybWF0aW9uIGRlbGV0ZS1zdGFja2ApLlxuICpcbiAqIERlc2lnbmVkIGZvciBjcm9uIHVzZTpcbiAqICAgLSBFeGl0cyAwIHdoZW4gdGhlcmUgYXJlIG5vIGZpbmRpbmdzLlxuICogICAtIEV4aXRzIDEgd2hlbiBhdCBsZWFzdCBvbmUgb3JwaGFuZWQgb3IgbWlzc2luZyBzdGFjayBpcyBmb3VuZC5cbiAqICAgLSBFeGl0cyAyIG9uIEFXUyBlcnJvcnMgLyBzY2FuIGZhaWx1cmVzLlxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGBiYXNoXG4gKiBwaXBlbGluZS1tYW5hZ2VyIGF1ZGl0IHN0YWNrcyAtLXJlZ2lvbiB1cy1lYXN0LTFcbiAqIHBpcGVsaW5lLW1hbmFnZXIgYXVkaXQgc3RhY2tzIC0tb3JnIGFjbWUgLS1qc29uXG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGF1ZGl0U3RhY2tzKHByb2dyYW06IENvbW1hbmQpOiB2b2lkIHtcbiAgd2l0aFNzbE9wdGlvbnMoXG4gICAgd2l0aFByb2ZpbGVPcHRpb24oXG4gICAgICB3aXRoUmVnaW9uT3B0aW9uKHByb2dyYW1cbiAgICAgICAgLmNvbW1hbmQoJ3N0YWNrcycpXG4gICAgICAgIC5kZXNjcmlwdGlvbignRGlmZiBDbG91ZEZvcm1hdGlvbiBzdGFja3MgdnMgcGlwZWxpbmVfcmVnaXN0cnkgdG8gZmluZCBvcnBoYW5lZCBvciBtaXNzaW5nIENESyBkZXBsb3ltZW50cycpKSxcbiAgICApXG4gICAgICAub3B0aW9uKCctLW9yZyA8b3JnSWQ+JywgJ0ZpbHRlciBib3RoIHJlZ2lzdHJ5IGFuZCBzdGFjayBzY2FuIHRvIGEgc2luZ2xlIG9yZycpXG4gICAgICAub3B0aW9uKCctLWpzb24nLCAnT3V0cHV0IHJlc3VsdHMgYXMgSlNPTicsIGZhbHNlKSxcbiAgKVxuICAgIC5hY3Rpb24oYXN5bmMgKG9wdGlvbnMpID0+IHtcbiAgICAgIGNvbnN0IGV4ZWN1dGlvbklkID0gcHJpbnRDb21tYW5kSGVhZGVyKCdBdWRpdCBTdGFja3MnLCB1bmRlZmluZWQsIHsgcXVpZXQ6IG9wdGlvbnMuanNvbiB9KTtcbiAgICAgIHByaW50U3NsV2FybmluZyhvcHRpb25zLnZlcmlmeVNzbCk7XG5cbiAgICAgIGNvbnN0IHJlZ2lvbiA9IHJlc29sdmVBd3NSZWdpb24ob3B0aW9ucy5yZWdpb24pO1xuICAgICAgLy8gSG9ub3IgLS1wcm9maWxlIGZvciB0aGUgU0RLIENsb3VkRm9ybWF0aW9uIGNsaWVudCBiZWxvdyAod2l0aG91dCB0aGlzLCB0aGVcbiAgICAgIC8vIHNjYW4gYWx3YXlzIGhpdCB0aGUgZGVmYXVsdCBhY2NvdW50IGFuZCBjb3VsZCBkaWZmIHRoZSByZWdpc3RyeSBhZ2FpbnN0XG4gICAgICAvLyB0aGUgV1JPTkcgYWNjb3VudCdzIHN0YWNrcyDihpIgYm9ndXMgb3JwaGFuZWQvbWlzc2luZyBmaW5kaW5ncykuXG4gICAgICBhcHBseUF3c1Byb2ZpbGUob3B0aW9ucy5wcm9maWxlKTtcblxuICAgICAgdHJ5IHtcbiAgICAgICAgLy8gRmV0Y2ggdGhlIHBsYXRmb3JtJ3MgdmlldyBvZiByZWdpc3RlcmVkIHBpcGVsaW5lcy5cbiAgICAgICAgLy8gUHJvZ3Jlc3MgZ29lcyB0byBzdGRvdXQsIHNvIHN1cHByZXNzIGl0IGluIC0tanNvbiBtb2RlIHRvIGtlZXAgdGhlIEpTT04gcGF5bG9hZCBjbGVhbiBmb3IgcGlwaW5nLlxuICAgICAgICBpZiAoIW9wdGlvbnMuanNvbikgcHJpbnRJbmZvKCdGZXRjaGluZyBwaXBlbGluZSByZWdpc3RyeSBmcm9tIHBsYXRmb3JtJywgeyBvcmc6IG9wdGlvbnMub3JnID8/ICcoYWxsKScgfSk7XG4gICAgICAgIGNvbnN0IGNsaWVudCA9IGF3YWl0IGNyZWF0ZUF1dGhlbnRpY2F0ZWRDbGllbnRBc3luYyhvcHRpb25zKTtcbiAgICAgICAgY29uc3QgcmVnaXN0cnlSZXMgPSBhd2FpdCBjbGllbnQuZ2V0PHsgZW50cmllczogUmVnaXN0cnlFbnRyeVtdIH0+KFxuICAgICAgICAgIGAvYXBpL3BpcGVsaW5lcy9yZWdpc3RyeSR7b3B0aW9ucy5vcmcgPyBgP29yZ0lkPSR7ZW5jb2RlVVJJQ29tcG9uZW50KG9wdGlvbnMub3JnKX1gIDogJyd9YCxcbiAgICAgICAgKTtcbiAgICAgICAgY29uc3QgZW50cmllczogUmVnaXN0cnlFbnRyeVtdID0gKHJlZ2lzdHJ5UmVzIGFzIHsgZW50cmllcz86IFJlZ2lzdHJ5RW50cnlbXSB9KT8uZW50cmllc1xuICAgICAgICAgID8/IChyZWdpc3RyeVJlcyBhcyB7IGRhdGE/OiB7IGVudHJpZXM/OiBSZWdpc3RyeUVudHJ5W10gfSB9KT8uZGF0YT8uZW50cmllc1xuICAgICAgICAgID8/IFtdO1xuXG4gICAgICAgIC8vIEZldGNoIHN0YWNrcyBmcm9tIENsb3VkRm9ybWF0aW9uLiBEZXNjcmliZVN0YWNrcyAobm8gU3RhY2tOYW1lKSByZXR1cm5zIGV2ZXJ5XG4gICAgICAgIC8vIGFjdGl2ZSBzdGFjayBXSVRIIGl0cyB0YWdzIGluIG9uZSBwYWdpbmF0ZWQgc3dlZXAg4oCUIGF2b2lkaW5nIHRoZSBOKzFcbiAgICAgICAgLy8gRGVzY3JpYmVTdGFja3MtcGVyLXN0YWNrIHRoZSBvbGQgTGlzdFN0YWNrcyBwYXRoIG5lZWRlZCAoTGlzdFN0YWNrcyBvbWl0cyB0YWdzKVxuICAgICAgICAvLyBhbmQgdGhlIEFQSSB0aHJvdHRsaW5nIGl0IGNhdXNlZCBvbiBhY2NvdW50cyB3aXRoIG1hbnkgc3RhY2tzLlxuICAgICAgICBpZiAoIW9wdGlvbnMuanNvbikgcHJpbnRJbmZvKCdMaXN0aW5nIENsb3VkRm9ybWF0aW9uIHN0YWNrcycsIHsgcmVnaW9uIH0pO1xuICAgICAgICBjb25zdCBjZm4gPSBuZXcgQ2xvdWRGb3JtYXRpb25DbGllbnQoeyByZWdpb24gfSk7XG4gICAgICAgIGNvbnN0IHN0YWNrczogU3RhY2tJbmZvW10gPSBbXTtcbiAgICAgICAgY29uc3QgYWN0aXZlU3RhdHVzZXMgPSBuZXcgU2V0KEFDVElWRV9TVEFUVVNFUyk7XG4gICAgICAgIGxldCBuZXh0VG9rZW46IHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgICAgICAgbGV0IHBhZ2VzID0gMDtcbiAgICAgICAgLy8gQmFja3N0b3Agb25seSAofjIwayBzdGFja3MgYXQgfjEwMC9wYWdlKSwgbm90IGFuIGV4cGVjdGVkIGxpbWl0LiBBIEZVTEwgc2NhblxuICAgICAgICAvLyBtYXR0ZXJzOiB0cnVuY2F0aW5nIHdvdWxkIGRpZmYgdGhlIHJlZ2lzdHJ5IGFnYWluc3QgYW4gaW5jb21wbGV0ZSBzdGFjayBzZXQgYW5kXG4gICAgICAgIC8vIHJlcG9ydCBsaXZlIHN0YWNrcyBhcyBgbWlzc2luZy1zdGFja2AuIFNvIGlmIHRoaXMgaXMgZXZlciBoaXQsIHdhcm4gTE9VRExZIHJhdGhlclxuICAgICAgICAvLyB0aGFuIHNpbGVudGx5IHVuZGVyLXJlcG9ydGluZyAodGhlIHByZXZpb3VzIGNvZGUgY2FwcGVkIGF0IDIwIHBhZ2VzIHNpbGVudGx5KS5cbiAgICAgICAgY29uc3QgTUFYX1BBR0VTID0gMjAwO1xuICAgICAgICBsZXQgdHJ1bmNhdGVkID0gZmFsc2U7XG4gICAgICAgIGRvIHtcbiAgICAgICAgICBjb25zdCByZXNwID0gYXdhaXQgY2ZuLnNlbmQobmV3IERlc2NyaWJlU3RhY2tzQ29tbWFuZCh7IE5leHRUb2tlbjogbmV4dFRva2VuIH0pKTtcbiAgICAgICAgICBmb3IgKGNvbnN0IHN0YWNrIG9mIHJlc3AuU3RhY2tzID8/IFtdKSB7XG4gICAgICAgICAgICBpZiAoIXN0YWNrLlN0YWNrTmFtZSkgY29udGludWU7XG4gICAgICAgICAgICBpZiAoIWFjdGl2ZVN0YXR1c2VzLmhhcyhzdGFjay5TdGFja1N0YXR1cyA/PyAnJykpIGNvbnRpbnVlOyAvLyBza2lwIGluLXByb2dyZXNzL3JvbGxlZC1iYWNrL2RlbGV0ZWRcbiAgICAgICAgICAgIGNvbnN0IHRhZ3MgPSBzdGFjay5UYWdzID8/IFtdO1xuICAgICAgICAgICAgY29uc3QgcGJUYWcgPSB0YWdzLmZpbmQoKHQpID0+IHQuS2V5ID09PSAncGlwZWxpbmUtYnVpbGRlcicpPy5WYWx1ZTtcbiAgICAgICAgICAgIGNvbnN0IG9yZ1RhZyA9IHRhZ3MuZmluZCgodCkgPT4gdC5LZXkgPT09ICdPcmdJZCcgfHwgdC5LZXkgPT09ICdvcmdJZCcpPy5WYWx1ZTtcbiAgICAgICAgICAgIGlmICghcGJUYWcpIGNvbnRpbnVlOyAvLyBOb3QgYSBwaXBlbGluZS1idWlsZGVyIHN0YWNrLlxuICAgICAgICAgICAgaWYgKG9wdGlvbnMub3JnICYmIG9yZ1RhZyAmJiBvcmdUYWcgIT09IG9wdGlvbnMub3JnKSBjb250aW51ZTsgLy8gV3Jvbmcgb3JnIGZpbHRlci5cbiAgICAgICAgICAgIHN0YWNrcy5wdXNoKHtcbiAgICAgICAgICAgICAgc3RhY2tOYW1lOiBzdGFjay5TdGFja05hbWUsXG4gICAgICAgICAgICAgIHN0YWNrU3RhdHVzOiBzdGFjay5TdGFja1N0YXR1cyA/PyAnVU5LTk9XTicsXG4gICAgICAgICAgICAgIHJlZ2lvbixcbiAgICAgICAgICAgICAgcGlwZWxpbmVCdWlsZGVyVGFnOiBwYlRhZyxcbiAgICAgICAgICAgICAgb3JnSWRUYWc6IG9yZ1RhZyxcbiAgICAgICAgICAgICAgY3JlYXRpb25UaW1lOiBzdGFjay5DcmVhdGlvblRpbWUsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgICAgbmV4dFRva2VuID0gcmVzcC5OZXh0VG9rZW47XG4gICAgICAgICAgcGFnZXMrKztcbiAgICAgICAgICBpZiAobmV4dFRva2VuICYmIHBhZ2VzID49IE1BWF9QQUdFUykgeyB0cnVuY2F0ZWQgPSB0cnVlOyBicmVhazsgfVxuICAgICAgICB9IHdoaWxlIChuZXh0VG9rZW4pO1xuICAgICAgICBpZiAodHJ1bmNhdGVkKSB7XG4gICAgICAgICAgcHJpbnRXYXJuaW5nKGBTdGFjayBzY2FuIGhpdCB0aGUgJHtNQVhfUEFHRVN9LXBhZ2Ugc2FmZXR5IGNhcCDigJQgcmVzdWx0cyBtYXkgYmUgSU5DT01QTEVURSBhbmQgJ21pc3Npbmctc3RhY2snIGZpbmRpbmdzIGNvdWxkIGJlIGZhbHNlLiBOYXJyb3cgYnkgLS1yZWdpb24vLS1vcmcsIG9yIHJhaXNlIE1BWF9QQUdFUy5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIERpZmYuXG4gICAgICAgIGNvbnN0IHJlZ2lzdHJ5U3RhY2tOYW1lcyA9IG5ldyBTZXQoZW50cmllcy5tYXAoKGUpID0+IGUuc3RhY2tOYW1lKS5maWx0ZXIoKG4pOiBuIGlzIHN0cmluZyA9PiAhIW4pKTtcbiAgICAgICAgY29uc3QgY2ZuU3RhY2tOYW1lcyA9IG5ldyBTZXQoc3RhY2tzLm1hcCgocykgPT4gcy5zdGFja05hbWUpKTtcblxuICAgICAgICBjb25zdCBmaW5kaW5nczogQXVkaXRGaW5kaW5nW10gPSBbXTtcbiAgICAgICAgZm9yIChjb25zdCBzdGFjayBvZiBzdGFja3MpIHtcbiAgICAgICAgICBpZiAoIXJlZ2lzdHJ5U3RhY2tOYW1lcy5oYXMoc3RhY2suc3RhY2tOYW1lKSkge1xuICAgICAgICAgICAgZmluZGluZ3MucHVzaCh7XG4gICAgICAgICAgICAgIHR5cGU6ICdvcnBoYW5lZC1zdGFjaycsXG4gICAgICAgICAgICAgIHN0YWNrTmFtZTogc3RhY2suc3RhY2tOYW1lLFxuICAgICAgICAgICAgICBkZXRhaWw6IGBDbG91ZEZvcm1hdGlvbiBzdGFjayB0YWdnZWQgcGlwZWxpbmUtYnVpbGRlcj0ke3N0YWNrLnBpcGVsaW5lQnVpbGRlclRhZyA/PyAnKHVuc2V0KSd9IGhhcyBubyBtYXRjaGluZyBwaXBlbGluZV9yZWdpc3RyeSBlbnRyeWAsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZm9yIChjb25zdCBlbnRyeSBvZiBlbnRyaWVzKSB7XG4gICAgICAgICAgaWYgKGVudHJ5LnN0YWNrTmFtZSAmJiAhY2ZuU3RhY2tOYW1lcy5oYXMoZW50cnkuc3RhY2tOYW1lKSkge1xuICAgICAgICAgICAgZmluZGluZ3MucHVzaCh7XG4gICAgICAgICAgICAgIHR5cGU6ICdtaXNzaW5nLXN0YWNrJyxcbiAgICAgICAgICAgICAgc3RhY2tOYW1lOiBlbnRyeS5zdGFja05hbWUsXG4gICAgICAgICAgICAgIHBpcGVsaW5lSWQ6IGVudHJ5LnBpcGVsaW5lSWQsXG4gICAgICAgICAgICAgIHBpcGVsaW5lTmFtZTogZW50cnkucGlwZWxpbmVOYW1lLFxuICAgICAgICAgICAgICBkZXRhaWw6IGBSZWdpc3RyeSBlbnRyeSByZWZlcmVuY2VzIHN0YWNrICR7ZW50cnkuc3RhY2tOYW1lfSBidXQgbm8gc3VjaCBzdGFjayBleGlzdHMgaW4gQ2xvdWRGb3JtYXRpb25gLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gQSB0cnVuY2F0ZWQgKGluY29tcGxldGUpIHNjYW4gaXMgYSBmaW5kaW5nIGluIGl0c2VsZjogaXQgY2FuIGJvdGggbWlzc1xuICAgICAgICAvLyByZWFsIGRyaWZ0IEFORCBlbWl0IGZhbHNlIG1pc3Npbmctc3RhY2sgZmluZGluZ3MsIHNvIGl0IG11c3QgZXhpdFxuICAgICAgICAvLyBub24temVybyBhbmQgYmUgdmlzaWJsZSBpbiB0aGUgSlNPTiAobWlycm9ycyBhdWRpdC10b2tlbnMpLlxuICAgICAgICBjb25zdCBleGl0Q29kZSA9IChmaW5kaW5ncy5sZW5ndGggPiAwIHx8IHRydW5jYXRlZCkgPyAxIDogMDtcblxuICAgICAgICBpZiAob3B0aW9ucy5qc29uKSB7XG4gICAgICAgICAgY29uc29sZS5sb2coSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICAgICAgc2Nhbm5lZEF0OiBuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCksXG4gICAgICAgICAgICByZWdpb24sXG4gICAgICAgICAgICBvcmdGaWx0ZXI6IG9wdGlvbnMub3JnLFxuICAgICAgICAgICAgcmVnaXN0cnlFbnRyaWVzOiBlbnRyaWVzLmxlbmd0aCxcbiAgICAgICAgICAgIGNmblN0YWNrczogc3RhY2tzLmxlbmd0aCxcbiAgICAgICAgICAgIHRydW5jYXRlZCxcbiAgICAgICAgICAgIGZpbmRpbmdzLFxuICAgICAgICAgICAgZXhlY3V0aW9uSWQsXG4gICAgICAgICAgfSwgbnVsbCwgMikpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHByaW50U2VjdGlvbignQXVkaXQgUmVzdWx0cycpO1xuICAgICAgICAgIHByaW50SW5mbygnQ291bnRzJywge1xuICAgICAgICAgICAgcmVnaXN0cnlFbnRyaWVzOiBTdHJpbmcoZW50cmllcy5sZW5ndGgpLFxuICAgICAgICAgICAgY2ZuU3RhY2tzOiBTdHJpbmcoc3RhY2tzLmxlbmd0aCksXG4gICAgICAgICAgICBmaW5kaW5nczogU3RyaW5nKGZpbmRpbmdzLmxlbmd0aCksXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgaWYgKGZpbmRpbmdzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgcHJpbnRTdWNjZXNzKCdObyBkcmlmdCBiZXR3ZWVuIHBpcGVsaW5lX3JlZ2lzdHJ5IGFuZCBDbG91ZEZvcm1hdGlvbicpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IGYgb2YgZmluZGluZ3MpIHtcbiAgICAgICAgICAgICAgaWYgKGYudHlwZSA9PT0gJ29ycGhhbmVkLXN0YWNrJykge1xuICAgICAgICAgICAgICAgIHByaW50V2FybmluZyhgT1JQSEFORUQgICR7Zi5zdGFja05hbWV9IOKAlCAke2YuZGV0YWlsfWApO1xuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHByaW50V2FybmluZyhgTUlTU0lORyAgICR7Zi5zdGFja05hbWV9IChwaXBlbGluZSAke2YucGlwZWxpbmVJZCA/PyAnPyd9KSDigJQgJHtmLmRldGFpbH1gKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcHJpbnRFcnJvcihgJHtmaW5kaW5ncy5sZW5ndGh9IGRyaWZ0IGZpbmRpbmcke2ZpbmRpbmdzLmxlbmd0aCA9PT0gMSA/ICcnIDogJ3MnfS4gUmV2aWV3IGFuZCByZWNvbmNpbGUgbWFudWFsbHkuYCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHByb2Nlc3MuZXhpdChleGl0Q29kZSk7XG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICBoYW5kbGVFcnJvcihlcnJvciwgRVJST1JfQ09ERVMuQVBJX1JFUVVFU1QsIHtcbiAgICAgICAgICBkZWJ1ZzogcHJvZ3JhbS5vcHRzKCkuZGVidWcsXG4gICAgICAgICAgZXhpdDogZmFsc2UsXG4gICAgICAgICAgY29udGV4dDogeyBjb21tYW5kOiAnYXVkaXQtc3RhY2tzJywgZXhlY3V0aW9uSWQgfSxcbiAgICAgICAgfSk7XG4gICAgICAgIHByb2Nlc3MuZXhpdCgyKTtcbiAgICAgIH1cbiAgICB9KTtcbn1cbiJdfQ==
@@ -0,0 +1,21 @@
1
+ import { Command } from 'commander';
2
+ /**
3
+ * Registers the `audit-tokens` command with the CLI program.
4
+ *
5
+ * Scans AWS Secrets Manager for stored platform JWTs (matching the
6
+ * `pipeline-builder/<orgId>/platform` naming convention used by `store-token`)
7
+ * and reports which secrets are expired or close to expiring.
8
+ *
9
+ * Designed for cron use:
10
+ * - Exits 0 when nothing is at-risk.
11
+ * - Exits 1 when at least one secret is expired or expires within `--warn-days`.
12
+ * - Exits 2 on AWS errors / scan failures.
13
+ *
14
+ * @example
15
+ * ```bash
16
+ * pipeline-manager audit tokens --region us-east-1 --warn-days 7
17
+ * pipeline-manager audit tokens --region us-east-1 --json
18
+ * ```
19
+ */
20
+ export declare function auditTokens(program: Command): void;
21
+ //# sourceMappingURL=audit-tokens.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit-tokens.d.ts","sourceRoot":"","sources":["../../src/commands/audit-tokens.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAgBpC;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA+HlD"}
@@ -0,0 +1,153 @@
1
+ // Copyright 2026 Pipeline Builder Contributors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import { CoreConstants } from '@pipeline-builder/pipeline-core';
4
+ import { Command } from 'commander';
5
+ import { decodeTokenPayload } from '../utils/auth-guard.js';
6
+ import { resolveAwsRegion } from '../utils/aws-env.js';
7
+ import { getSecretValue, listSecrets } from '../utils/aws-secrets.js';
8
+ import { printCommandHeader, withProfileOption, withRegionOption } from '../utils/command-utils.js';
9
+ import { ERROR_CODES, handleError } from '../utils/error-handler.js';
10
+ import { printError, printInfo, printSection, printSuccess, printWarning } from '../utils/output-utils.js';
11
+ /**
12
+ * Registers the `audit-tokens` command with the CLI program.
13
+ *
14
+ * Scans AWS Secrets Manager for stored platform JWTs (matching the
15
+ * `pipeline-builder/<orgId>/platform` naming convention used by `store-token`)
16
+ * and reports which secrets are expired or close to expiring.
17
+ *
18
+ * Designed for cron use:
19
+ * - Exits 0 when nothing is at-risk.
20
+ * - Exits 1 when at least one secret is expired or expires within `--warn-days`.
21
+ * - Exits 2 on AWS errors / scan failures.
22
+ *
23
+ * @example
24
+ * ```bash
25
+ * pipeline-manager audit tokens --region us-east-1 --warn-days 7
26
+ * pipeline-manager audit tokens --region us-east-1 --json
27
+ * ```
28
+ */
29
+ export function auditTokens(program) {
30
+ withProfileOption(withRegionOption(program
31
+ .command('tokens')
32
+ .description('Scan stored platform tokens in AWS Secrets Manager and report upcoming expirations')))
33
+ .option('--warn-days <days>', 'Flag tokens expiring within N days as at-risk', '7')
34
+ .option('--prefix <prefix>', 'Secrets Manager name prefix to scan', `${CoreConstants.SECRETS_PATH_PREFIX}/`)
35
+ .option('--json', 'Output results as JSON', false)
36
+ .action(async (options) => {
37
+ const executionId = printCommandHeader('Audit Tokens', undefined, { quiet: options.json });
38
+ const region = resolveAwsRegion(options.region);
39
+ const warnDays = parseInt(options.warnDays, 10);
40
+ if (!Number.isFinite(warnDays) || warnDays < 0) {
41
+ printError('Invalid --warn-days value', { provided: options.warnDays });
42
+ process.exit(2);
43
+ }
44
+ try {
45
+ // Progress goes to stdout, so suppress it in --json mode to keep the JSON payload clean for piping.
46
+ if (!options.json)
47
+ printInfo('Listing secrets', { region, prefix: options.prefix });
48
+ const { secrets, truncated } = await listSecrets(options.prefix, { region, profile: options.profile });
49
+ if (truncated) {
50
+ // A truncated sweep means an expiring token past the cap could be missed —
51
+ // never report "all clear" from an incomplete scan (mirrors audit-stacks).
52
+ printWarning('Secret listing was TRUNCATED (paging cap hit) — results may be INCOMPLETE and an expiring token could be missed. Narrow by --prefix/--region.');
53
+ }
54
+ // Audit both the full-privilege platform token (`<prefix>/<orgId>/platform`)
55
+ // AND the scoped event-ingestion token (`.../reporting-ingest`, minted by
56
+ // `store-token --scope reporting:ingest`) — both expire and both are
57
+ // auto-renewed, so a stalled renewal on either must surface here.
58
+ const platformSecrets = secrets.filter((s) => s.name.endsWith('/platform') || s.name.endsWith('/reporting-ingest'));
59
+ const entries = [];
60
+ const now = Date.now();
61
+ const warnCutoff = now + warnDays * 24 * 60 * 60 * 1000;
62
+ for (const s of platformSecrets) {
63
+ let raw;
64
+ try {
65
+ raw = await getSecretValue(s.name, { region, profile: options.profile });
66
+ }
67
+ catch (err) {
68
+ printWarning(`Could not read ${s.name}: ${err instanceof Error ? err.message : String(err)}`);
69
+ continue;
70
+ }
71
+ let parsed;
72
+ try {
73
+ parsed = JSON.parse(raw);
74
+ }
75
+ catch {
76
+ printWarning(`Secret ${s.name} is not valid JSON, skipping`);
77
+ continue;
78
+ }
79
+ // Prefer the explicit expiresAt field written by store-token; fall back
80
+ // to decoding the JWT's exp claim if the field is missing.
81
+ let expiresAt;
82
+ if (parsed.expiresAt) {
83
+ const d = new Date(parsed.expiresAt);
84
+ if (!Number.isNaN(d.getTime()))
85
+ expiresAt = d;
86
+ }
87
+ // `store-token` writes the JWT to the canonical `password` field.
88
+ if (!expiresAt && parsed.password) {
89
+ const payload = decodeTokenPayload(parsed.password);
90
+ if (payload?.exp && typeof payload.exp === 'number') {
91
+ expiresAt = new Date(payload.exp * 1000);
92
+ }
93
+ }
94
+ if (!expiresAt) {
95
+ printWarning(`Secret ${s.name} has no expiry information, skipping`);
96
+ continue;
97
+ }
98
+ const daysUntilExpiry = Math.floor((expiresAt.getTime() - now) / (24 * 60 * 60 * 1000));
99
+ const status = expiresAt.getTime() < now ? 'expired'
100
+ : expiresAt.getTime() < warnCutoff ? 'expiring-soon'
101
+ : 'ok';
102
+ entries.push({ secretName: s.name, arn: s.arn, expiresAt, daysUntilExpiry, status });
103
+ }
104
+ const atRisk = entries.filter((e) => e.status !== 'ok');
105
+ // A truncated scan is itself a failure condition: exit non-zero so cron
106
+ // doesn't read an incomplete "all clear" as success.
107
+ const exitCode = (atRisk.length > 0 || truncated) ? 1 : 0;
108
+ if (options.json) {
109
+ console.log(JSON.stringify({
110
+ scannedAt: new Date().toISOString(),
111
+ region,
112
+ warnDays,
113
+ totalScanned: entries.length,
114
+ atRiskCount: atRisk.length,
115
+ truncated,
116
+ entries: entries.map((e) => ({ ...e, expiresAt: e.expiresAt.toISOString() })),
117
+ executionId,
118
+ }, null, 2));
119
+ }
120
+ else {
121
+ printSection('Audit Results');
122
+ printInfo(`Scanned ${entries.length} platform secret${entries.length === 1 ? '' : 's'}`);
123
+ if (atRisk.length === 0) {
124
+ if (truncated) {
125
+ printWarning('No at-risk tokens in the scanned pages, but the scan was truncated — some secrets were not checked.');
126
+ }
127
+ else {
128
+ printSuccess(`All tokens valid for at least ${warnDays} days`);
129
+ }
130
+ }
131
+ else {
132
+ for (const e of atRisk) {
133
+ const label = e.status === 'expired'
134
+ ? `EXPIRED ${Math.abs(e.daysUntilExpiry)} day${e.daysUntilExpiry === -1 ? '' : 's'} ago`
135
+ : `expires in ${e.daysUntilExpiry} day${e.daysUntilExpiry === 1 ? '' : 's'}`;
136
+ printWarning(`${e.secretName} — ${label}`);
137
+ }
138
+ printError(`${atRisk.length} secret${atRisk.length === 1 ? '' : 's'} need rotation. Run \`pipeline-manager infra store-token --days <N>\` to refresh.`);
139
+ }
140
+ }
141
+ process.exit(exitCode);
142
+ }
143
+ catch (error) {
144
+ handleError(error, ERROR_CODES.API_REQUEST, {
145
+ debug: program.opts().debug,
146
+ exit: false,
147
+ context: { command: 'audit-tokens', executionId },
148
+ });
149
+ process.exit(2);
150
+ }
151
+ });
152
+ }
153
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXVkaXQtdG9rZW5zLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NvbW1hbmRzL2F1ZGl0LXRva2Vucy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwrQ0FBK0M7QUFDL0Msc0NBQXNDO0FBRXRDLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUNoRSxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQ3BDLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQzVELE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ3ZELE9BQU8sRUFBRSxjQUFjLEVBQUUsV0FBVyxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDdEUsT0FBTyxFQUFFLGtCQUFrQixFQUFFLGlCQUFpQixFQUFFLGdCQUFnQixFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDcEcsT0FBTyxFQUFFLFdBQVcsRUFBRSxXQUFXLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUNyRSxPQUFPLEVBQUUsVUFBVSxFQUFFLFNBQVMsRUFBRSxZQUFZLEVBQUUsWUFBWSxFQUFFLFlBQVksRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBVTNHOzs7Ozs7Ozs7Ozs7Ozs7OztHQWlCRztBQUNILE1BQU0sVUFBVSxXQUFXLENBQUMsT0FBZ0I7SUFDMUMsaUJBQWlCLENBQ2YsZ0JBQWdCLENBQUMsT0FBTztTQUNyQixPQUFPLENBQUMsUUFBUSxDQUFDO1NBQ2pCLFdBQVcsQ0FBQyxvRkFBb0YsQ0FBQyxDQUFDLENBQ3RHO1NBQ0UsTUFBTSxDQUFDLG9CQUFvQixFQUFFLCtDQUErQyxFQUFFLEdBQUcsQ0FBQztTQUNsRixNQUFNLENBQUMsbUJBQW1CLEVBQUUscUNBQXFDLEVBQUUsR0FBRyxhQUFhLENBQUMsbUJBQW1CLEdBQUcsQ0FBQztTQUMzRyxNQUFNLENBQUMsUUFBUSxFQUFFLHdCQUF3QixFQUFF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LE9BQU8sQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDekIsQ0FBQztRQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7WUFDZixXQUFXLENBQUMsS0FBSyxFQUFFLFdBQVcsQ0FBQyxXQUFXLEVBQUU7Z0JBQzFDLEtBQUssRUFBRSxPQUFPLENBQUMsSUFBSSxFQUFFLENBQUMsS0FBSztnQkFDM0IsSUFBSSxFQUFFLEtBQUs7Z0JBQ1gsT0FBTyxFQUFFLEVBQUUsT0FBTyxFQUFFLGNBQWMsRUFBRSxXQUFXLEVBQUU7YUFDbEQsQ0FBQyxDQUFDO1lBQ0gsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNsQixDQUFDO0lBQ0gsQ0FBQyxDQUFDLENBQUM7QUFDUCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IDIwMjYgUGlwZWxpbmUgQnVpbGRlciBDb250cmlidXRvcnNcbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG5cbmltcG9ydCB7IENvcmVDb25zdGFudHMgfSBmcm9tICdAcGlwZWxpbmUtYnVpbGRlci9waXBlbGluZS1jb3JlJztcbmltcG9ydCB7IENvbW1hbmQgfSBmcm9tICdjb21tYW5kZXInO1xuaW1wb3J0IHsgZGVjb2RlVG9rZW5QYXlsb2FkIH0gZnJvbSAnLi4vdXRpbHMvYXV0aC1ndWFyZC5qcyc7XG5pbXBvcnQgeyByZXNvbHZlQXdzUmVnaW9uIH0gZnJvbSAnLi4vdXRpbHMvYXdzLWVudi5qcyc7XG5pbXBvcnQgeyBnZXRTZWNyZXRWYWx1ZSwgbGlzdFNlY3JldHMgfSBmcm9tICcuLi91dGlscy9hd3Mtc2VjcmV0cy5qcyc7XG5pbXBvcnQgeyBwcmludENvbW1hbmRIZWFkZXIsIHdpdGhQcm9maWxlT3B0aW9uLCB3aXRoUmVnaW9uT3B0aW9uIH0gZnJvbSAnLi4vdXRpbHMvY29tbWFuZC11dGlscy5qcyc7XG5pbXBvcnQgeyBFUlJPUl9DT0RFUywgaGFuZGxlRXJyb3IgfSBmcm9tICcuLi91dGlscy9lcnJvci1oYW5kbGVyLmpzJztcbmltcG9ydCB7IHByaW50RXJyb3IsIHByaW50SW5mbywgcHJpbnRTZWN0aW9uLCBwcmludFN1Y2Nlc3MsIHByaW50V2FybmluZyB9IGZyb20gJy4uL3V0aWxzL291dHB1dC11dGlscy5qcyc7XG5cbmludGVyZmFjZSBUb2tlbkF1ZGl0RW50cnkge1xuICBzZWNyZXROYW1lOiBzdHJpbmc7XG4gIGFybjogc3RyaW5nO1xuICBleHBpcmVzQXQ6IERhdGU7XG4gIGRheXNVbnRpbEV4cGlyeTogbnVtYmVyO1xuICBzdGF0dXM6ICdleHBpcmVkJyB8ICdleHBpcmluZy1zb29uJyB8ICdvayc7XG59XG5cbi8qKlxuICogUmVnaXN0ZXJzIHRoZSBgYXVkaXQtdG9rZW5zYCBjb21tYW5kIHdpdGggdGhlIENMSSBwcm9ncmFtLlxuICpcbiAqIFNjYW5zIEFXUyBTZWNyZXRzIE1hbmFnZXIgZm9yIHN0b3JlZCBwbGF0Zm9ybSBKV1RzIChtYXRjaGluZyB0aGVcbiAqIGBwaXBlbGluZS1idWlsZGVyLzxvcmdJZD4vcGxhdGZvcm1gIG5hbWluZyBjb252ZW50aW9uIHVzZWQgYnkgYHN0b3JlLXRva2VuYClcbiAqIGFuZCByZXBvcnRzIHdoaWNoIHNlY3JldHMgYXJlIGV4cGlyZWQgb3IgY2xvc2UgdG8gZXhwaXJpbmcuXG4gKlxuICogRGVzaWduZWQgZm9yIGNyb24gdXNlOlxuICogICAtIEV4aXRzIDAgd2hlbiBub3RoaW5nIGlzIGF0LXJpc2suXG4gKiAgIC0gRXhpdHMgMSB3aGVuIGF0IGxlYXN0IG9uZSBzZWNyZXQgaXMgZXhwaXJlZCBvciBleHBpcmVzIHdpdGhpbiBgLS13YXJuLWRheXNgLlxuICogICAtIEV4aXRzIDIgb24gQVdTIGVycm9ycyAvIHNjYW4gZmFpbHVyZXMuXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYGJhc2hcbiAqIHBpcGVsaW5lLW1hbmFnZXIgYXVkaXQgdG9rZW5zIC0tcmVnaW9uIHVzLWVhc3QtMSAtLXdhcm4tZGF5cyA3XG4gKiBwaXBlbGluZS1tYW5hZ2VyIGF1ZGl0IHRva2VucyAtLXJlZ2lvbiB1cy1lYXN0LTEgLS1qc29uXG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGF1ZGl0VG9rZW5zKHByb2dyYW06IENvbW1hbmQpOiB2b2lkIHtcbiAgd2l0aFByb2ZpbGVPcHRpb24oXG4gICAgd2l0aFJlZ2lvbk9wdGlvbihwcm9ncmFtXG4gICAgICAuY29tbWFuZCgndG9rZW5zJylcbiAgICAgIC5kZXNjcmlwdGlvbignU2NhbiBzdG9yZWQgcGxhdGZvcm0gdG9rZW5zIGluIEFXUyBTZWNyZXRzIE1hbmFnZXIgYW5kIHJlcG9ydCB1cGNvbWluZyBleHBpcmF0aW9ucycpKSxcbiAgKVxuICAgIC5vcHRpb24oJy0td2Fybi1kYXlzIDxkYXlzPicsICdGbGFnIHRva2VucyBleHBpcmluZyB3aXRoaW4gTiBkYXlzIGFzIGF0LXJpc2snLCAnNycpXG4gICAgLm9wdGlvbignLS1wcmVmaXggPHByZWZpeD4nLCAnU2VjcmV0cyBNYW5hZ2VyIG5hbWUgcHJlZml4IHRvIHNjYW4nLCBgJHtDb3JlQ29uc3RhbnRzLlNFQ1JFVFNfUEFUSF9QUkVGSVh9L2ApXG4gICAgLm9wdGlvbignLS1qc29uJywgJ091dHB1dCByZXN1bHRzIGFzIEpTT04nLCBmYWxzZSlcbiAgICAuYWN0aW9uKGFzeW5jIChvcHRpb25zKSA9PiB7XG4gICAgICBjb25zdCBleGVjdXRpb25JZCA9IHByaW50Q29tbWFuZEhlYWRlcignQXVkaXQgVG9rZW5zJywgdW5kZWZpbmVkLCB7IHF1aWV0OiBvcHRpb25zLmpzb24gfSk7XG4gICAgICBjb25zdCByZWdpb24gPSByZXNvbHZlQXdzUmVnaW9uKG9wdGlvbnMucmVnaW9uKTtcbiAgICAgIGNvbnN0IHdhcm5EYXlzID0gcGFyc2VJbnQob3B0aW9ucy53YXJuRGF5cywgMTApO1xuICAgICAgaWYgKCFOdW1iZXIuaXNGaW5pdGUod2FybkRheXMpIHx8IHdhcm5EYXlzIDwgMCkge1xuICAgICAgICBwcmludEVycm9yKCdJbnZhbGlkIC0td2Fybi1kYXlzIHZhbHVlJywgeyBwcm92aWRlZDogb3B0aW9ucy53YXJuRGF5cyB9KTtcbiAgICAgICAgcHJvY2Vzcy5leGl0KDIpO1xuICAgICAgfVxuXG4gICAgICB0cnkge1xuICAgICAgICAvLyBQcm9ncmVzcyBnb2VzIHRvIHN0ZG91dCwgc28gc3VwcHJlc3MgaXQgaW4gLS1qc29uIG1vZGUgdG8ga2VlcCB0aGUgSlNPTiBwYXlsb2FkIGNsZWFuIGZvciBwaXBpbmcuXG4gICAgICAgIGlmICghb3B0aW9ucy5qc29uKSBwcmludEluZm8oJ0xpc3Rpbmcgc2VjcmV0cycsIHsgcmVnaW9uLCBwcmVmaXg6IG9wdGlvbnMucHJlZml4IH0pO1xuICAgICAgICBjb25zdCB7IHNlY3JldHMsIHRydW5jYXRlZCB9ID0gYXdhaXQgbGlzdFNlY3JldHMob3B0aW9ucy5wcmVmaXgsIHsgcmVnaW9uLCBwcm9maWxlOiBvcHRpb25zLnByb2ZpbGUgfSk7XG4gICAgICAgIGlmICh0cnVuY2F0ZWQpIHtcbiAgICAgICAgICAvLyBBIHRydW5jYXRlZCBzd2VlcCBtZWFucyBhbiBleHBpcmluZyB0b2tlbiBwYXN0IHRoZSBjYXAgY291bGQgYmUgbWlzc2VkIOKAlFxuICAgICAgICAgIC8vIG5ldmVyIHJlcG9ydCBcImFsbCBjbGVhclwiIGZyb20gYW4gaW5jb21wbGV0ZSBzY2FuIChtaXJyb3JzIGF1ZGl0LXN0YWNrcykuXG4gICAgICAgICAgcHJpbnRXYXJuaW5nKCdTZWNyZXQgbGlzdGluZyB3YXMgVFJVTkNBVEVEIChwYWdpbmcgY2FwIGhpdCkg4oCUIHJlc3VsdHMgbWF5IGJlIElOQ09NUExFVEUgYW5kIGFuIGV4cGlyaW5nIHRva2VuIGNvdWxkIGJlIG1pc3NlZC4gTmFycm93IGJ5IC0tcHJlZml4Ly0tcmVnaW9uLicpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQXVkaXQgYm90aCB0aGUgZnVsbC1wcml2aWxlZ2UgcGxhdGZvcm0gdG9rZW4gKGA8cHJlZml4Pi88b3JnSWQ+L3BsYXRmb3JtYClcbiAgICAgICAgLy8gQU5EIHRoZSBzY29wZWQgZXZlbnQtaW5nZXN0aW9uIHRva2VuIChgLi4uL3JlcG9ydGluZy1pbmdlc3RgLCBtaW50ZWQgYnlcbiAgICAgICAgLy8gYHN0b3JlLXRva2VuIC0tc2NvcGUgcmVwb3J0aW5nOmluZ2VzdGApIOKAlCBib3RoIGV4cGlyZSBhbmQgYm90aCBhcmVcbiAgICAgICAgLy8gYXV0by1yZW5ld2VkLCBzbyBhIHN0YWxsZWQgcmVuZXdhbCBvbiBlaXRoZXIgbXVzdCBzdXJmYWNlIGhlcmUuXG4gICAgICAgIGNvbnN0IHBsYXRmb3JtU2VjcmV0cyA9IHNlY3JldHMuZmlsdGVyKChzKSA9PiBzLm5hbWUuZW5kc1dpdGgoJy9wbGF0Zm9ybScpIHx8IHMubmFtZS5lbmRzV2l0aCgnL3JlcG9ydGluZy1pbmdlc3QnKSk7XG5cbiAgICAgICAgY29uc3QgZW50cmllczogVG9rZW5BdWRpdEVudHJ5W10gPSBbXTtcbiAgICAgICAgY29uc3Qgbm93ID0gRGF0ZS5ub3coKTtcbiAgICAgICAgY29uc3Qgd2FybkN1dG9mZiA9IG5vdyArIHdhcm5EYXlzICogMjQgKiA2MCAqIDYwICogMTAwMDtcblxuICAgICAgICBmb3IgKGNvbnN0IHMgb2YgcGxhdGZvcm1TZWNyZXRzKSB7XG4gICAgICAgICAgbGV0IHJhdzogc3RyaW5nO1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICByYXcgPSBhd2FpdCBnZXRTZWNyZXRWYWx1ZShzLm5hbWUsIHsgcmVnaW9uLCBwcm9maWxlOiBvcHRpb25zLnByb2ZpbGUgfSk7XG4gICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICBwcmludFdhcm5pbmcoYENvdWxkIG5vdCByZWFkICR7cy5uYW1lfTogJHtlcnIgaW5zdGFuY2VvZiBFcnJvciA/IGVyci5tZXNzYWdlIDogU3RyaW5nKGVycil9YCk7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBsZXQgcGFyc2VkOiB7IHBhc3N3b3JkPzogc3RyaW5nOyBleHBpcmVzQXQ/OiBzdHJpbmcgfTtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgcGFyc2VkID0gSlNPTi5wYXJzZShyYXcpO1xuICAgICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgICAgcHJpbnRXYXJuaW5nKGBTZWNyZXQgJHtzLm5hbWV9IGlzIG5vdCB2YWxpZCBKU09OLCBza2lwcGluZ2ApO1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgLy8gUHJlZmVyIHRoZSBleHBsaWNpdCBleHBpcmVzQXQgZmllbGQgd3JpdHRlbiBieSBzdG9yZS10b2tlbjsgZmFsbCBiYWNrXG4gICAgICAgICAgLy8gdG8gZGVjb2RpbmcgdGhlIEpXVCdzIGV4cCBjbGFpbSBpZiB0aGUgZmllbGQgaXMgbWlzc2luZy5cbiAgICAgICAgICBsZXQgZXhwaXJlc0F0OiBEYXRlIHwgdW5kZWZpbmVkO1xuICAgICAgICAgIGlmIChwYXJzZWQuZXhwaXJlc0F0KSB7XG4gICAgICAgICAgICBjb25zdCBkID0gbmV3IERhdGUocGFyc2VkLmV4cGlyZXNBdCk7XG4gICAgICAgICAgICBpZiAoIU51bWJlci5pc05hTihkLmdldFRpbWUoKSkpIGV4cGlyZXNBdCA9IGQ7XG4gICAgICAgICAgfVxuICAgICAgICAgIC8vIGBzdG9yZS10b2tlbmAgd3JpdGVzIHRoZSBKV1QgdG8gdGhlIGNhbm9uaWNhbCBgcGFzc3dvcmRgIGZpZWxkLlxuICAgICAgICAgIGlmICghZXhwaXJlc0F0ICYmIHBhcnNlZC5wYXNzd29yZCkge1xuICAgICAgICAgICAgY29uc3QgcGF5bG9hZCA9IGRlY29kZVRva2VuUGF5bG9hZChwYXJzZWQucGFzc3dvcmQpO1xuICAgICAgICAgICAgaWYgKHBheWxvYWQ/LmV4cCAmJiB0eXBlb2YgcGF5bG9hZC5leHAgPT09ICdudW1iZXInKSB7XG4gICAgICAgICAgICAgIGV4cGlyZXNBdCA9IG5ldyBEYXRlKHBheWxvYWQuZXhwICogMTAwMCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmICghZXhwaXJlc0F0KSB7XG4gICAgICAgICAgICBwcmludFdhcm5pbmcoYFNlY3JldCAke3MubmFtZX0gaGFzIG5vIGV4cGlyeSBpbmZvcm1hdGlvbiwgc2tpcHBpbmdgKTtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGNvbnN0IGRheXNVbnRpbEV4cGlyeSA9IE1hdGguZmxvb3IoKGV4cGlyZXNBdC5nZXRUaW1lKCkgLSBub3cpIC8gKDI0ICogNjAgKiA2MCAqIDEwMDApKTtcbiAgICAgICAgICBjb25zdCBzdGF0dXM6IFRva2VuQXVkaXRFbnRyeVsnc3RhdHVzJ10gPVxuICAgICAgICAgICAgZXhwaXJlc0F0LmdldFRpbWUoKSA8IG5vdyA/ICdleHBpcmVkJ1xuICAgICAgICAgICAgICA6IGV4cGlyZXNBdC5nZXRUaW1lKCkgPCB3YXJuQ3V0b2ZmID8gJ2V4cGlyaW5nLXNvb24nXG4gICAgICAgICAgICAgICAgOiAnb2snO1xuICAgICAgICAgIGVudHJpZXMucHVzaCh7IHNlY3JldE5hbWU6IHMubmFtZSwgYXJuOiBzLmFybiwgZXhwaXJlc0F0LCBkYXlzVW50aWxFeHBpcnksIHN0YXR1cyB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGF0UmlzayA9IGVudHJpZXMuZmlsdGVyKChlKSA9PiBlLnN0YXR1cyAhPT0gJ29rJyk7XG4gICAgICAgIC8vIEEgdHJ1bmNhdGVkIHNjYW4gaXMgaXRzZWxmIGEgZmFpbHVyZSBjb25kaXRpb246IGV4aXQgbm9uLXplcm8gc28gY3JvblxuICAgICAgICAvLyBkb2Vzbid0IHJlYWQgYW4gaW5jb21wbGV0ZSBcImFsbCBjbGVhclwiIGFzIHN1Y2Nlc3MuXG4gICAgICAgIGNvbnN0IGV4aXRDb2RlID0gKGF0Umlzay5sZW5ndGggPiAwIHx8IHRydW5jYXRlZCkgPyAxIDogMDtcblxuICAgICAgICBpZiAob3B0aW9ucy5qc29uKSB7XG4gICAgICAgICAgY29uc29sZS5sb2coSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICAgICAgc2Nhbm5lZEF0OiBuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCksXG4gICAgICAgICAgICByZWdpb24sXG4gICAgICAgICAgICB3YXJuRGF5cyxcbiAgICAgICAgICAgIHRvdGFsU2Nhbm5lZDogZW50cmllcy5sZW5ndGgsXG4gICAgICAgICAgICBhdFJpc2tDb3VudDogYXRSaXNrLmxlbmd0aCxcbiAgICAgICAgICAgIHRydW5jYXRlZCxcbiAgICAgICAgICAgIGVudHJpZXM6IGVudHJpZXMubWFwKChlKSA9PiAoeyAuLi5lLCBleHBpcmVzQXQ6IGUuZXhwaXJlc0F0LnRvSVNPU3RyaW5nKCkgfSkpLFxuICAgICAgICAgICAgZXhlY3V0aW9uSWQsXG4gICAgICAgICAgfSwgbnVsbCwgMikpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHByaW50U2VjdGlvbignQXVkaXQgUmVzdWx0cycpO1xuICAgICAgICAgIHByaW50SW5mbyhgU2Nhbm5lZCAke2VudHJpZXMubGVuZ3RofSBwbGF0Zm9ybSBzZWNyZXQke2VudHJpZXMubGVuZ3RoID09PSAxID8gJycgOiAncyd9YCk7XG4gICAgICAgICAgaWYgKGF0Umlzay5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIGlmICh0cnVuY2F0ZWQpIHtcbiAgICAgICAgICAgICAgcHJpbnRXYXJuaW5nKCdObyBhdC1yaXNrIHRva2VucyBpbiB0aGUgc2Nhbm5lZCBwYWdlcywgYnV0IHRoZSBzY2FuIHdhcyB0cnVuY2F0ZWQg4oCUIHNvbWUgc2VjcmV0cyB3ZXJlIG5vdCBjaGVja2VkLicpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgcHJpbnRTdWNjZXNzKGBBbGwgdG9rZW5zIHZhbGlkIGZvciBhdCBsZWFzdCAke3dhcm5EYXlzfSBkYXlzYCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGZvciAoY29uc3QgZSBvZiBhdFJpc2spIHtcbiAgICAgICAgICAgICAgY29uc3QgbGFiZWwgPSBlLnN0YXR1cyA9PT0gJ2V4cGlyZWQnXG4gICAgICAgICAgICAgICAgPyBgRVhQSVJFRCAke01hdGguYWJzKGUuZGF5c1VudGlsRXhwaXJ5KX0gZGF5JHtlLmRheXNVbnRpbEV4cGlyeSA9PT0gLTEgPyAnJyA6ICdzJ30gYWdvYFxuICAgICAgICAgICAgICAgIDogYGV4cGlyZXMgaW4gJHtlLmRheXNVbnRpbEV4cGlyeX0gZGF5JHtlLmRheXNVbnRpbEV4cGlyeSA9PT0gMSA/ICcnIDogJ3MnfWA7XG4gICAgICAgICAgICAgIHByaW50V2FybmluZyhgJHtlLnNlY3JldE5hbWV9IOKAlCAke2xhYmVsfWApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcHJpbnRFcnJvcihgJHthdFJpc2subGVuZ3RofSBzZWNyZXQke2F0Umlzay5sZW5ndGggPT09IDEgPyAnJyA6ICdzJ30gbmVlZCByb3RhdGlvbi4gUnVuIFxcYHBpcGVsaW5lLW1hbmFnZXIgaW5mcmEgc3RvcmUtdG9rZW4gLS1kYXlzIDxOPlxcYCB0byByZWZyZXNoLmApO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBwcm9jZXNzLmV4aXQoZXhpdENvZGUpO1xuICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgaGFuZGxlRXJyb3IoZXJyb3IsIEVSUk9SX0NPREVTLkFQSV9SRVFVRVNULCB7XG4gICAgICAgICAgZGVidWc6IHByb2dyYW0ub3B0cygpLmRlYnVnLFxuICAgICAgICAgIGV4aXQ6IGZhbHNlLFxuICAgICAgICAgIGNvbnRleHQ6IHsgY29tbWFuZDogJ2F1ZGl0LXRva2VucycsIGV4ZWN1dGlvbklkIH0sXG4gICAgICAgIH0pO1xuICAgICAgICBwcm9jZXNzLmV4aXQoMik7XG4gICAgICB9XG4gICAgfSk7XG59XG4iXX0=
@@ -0,0 +1,11 @@
1
+ import { Command } from 'commander';
2
+ /**
3
+ * Registers the `bootstrap` command with the CLI program.
4
+ *
5
+ * Provisions the CDK toolkit stack in the target AWS account/region
6
+ * so that CDK deployments can proceed.
7
+ *
8
+ * @param program - The root Commander program instance to attach the command to.
9
+ */
10
+ export declare function bootstrap(program: Command): void;
11
+ //# sourceMappingURL=bootstrap.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bootstrap.d.ts","sourceRoot":"","sources":["../../src/commands/bootstrap.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA4EpC;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAgGhD"}