@fjall/components-infrastructure 0.94.1 → 0.96.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.
Files changed (67) hide show
  1. package/dist/lib/app.d.ts +25 -109
  2. package/dist/lib/app.js +37 -136
  3. package/dist/lib/patterns/aws/account.js +5 -4
  4. package/dist/lib/patterns/aws/computeEcs.d.ts +8 -397
  5. package/dist/lib/patterns/aws/computeEcs.js +13 -9
  6. package/dist/lib/patterns/aws/computeEcsTypes.d.ts +386 -0
  7. package/dist/lib/patterns/aws/computeEcsTypes.js +2 -0
  8. package/dist/lib/patterns/aws/domain.js +4 -5
  9. package/dist/lib/patterns/aws/index.d.ts +2 -0
  10. package/dist/lib/patterns/aws/index.js +2 -0
  11. package/dist/lib/patterns/aws/interfaces/compute.d.ts +6 -0
  12. package/dist/lib/patterns/aws/interfaces/connector.d.ts +1 -1
  13. package/dist/lib/patterns/aws/interfaces/connector.js +1 -1
  14. package/dist/lib/patterns/aws/interfaces/index.d.ts +2 -1
  15. package/dist/lib/patterns/aws/interfaces/index.js +1 -1
  16. package/dist/lib/patterns/aws/interfaces/vpcPeer.d.ts +7 -0
  17. package/dist/lib/patterns/aws/interfaces/vpcPeer.js +1 -0
  18. package/dist/lib/patterns/aws/organisation.js +2 -1
  19. package/dist/lib/patterns/aws/vpcPeer.d.ts +34 -0
  20. package/dist/lib/patterns/aws/vpcPeer.js +36 -0
  21. package/dist/lib/patterns/aws/vpcPeerAccepter.d.ts +29 -0
  22. package/dist/lib/patterns/aws/vpcPeerAccepter.js +196 -0
  23. package/dist/lib/resources/aws/analytics/clickhouse.js +10 -1
  24. package/dist/lib/resources/aws/analytics/clickhouseAlarms.d.ts +34 -0
  25. package/dist/lib/resources/aws/analytics/clickhouseAlarms.js +89 -0
  26. package/dist/lib/resources/aws/analytics/clickhouseConstants.d.ts +1 -1
  27. package/dist/lib/resources/aws/analytics/clickhouseConstants.js +3 -1
  28. package/dist/lib/resources/aws/analytics/clickhouseTypes.d.ts +6 -0
  29. package/dist/lib/resources/aws/analytics/clickhouseUserData.d.ts +1 -0
  30. package/dist/lib/resources/aws/analytics/clickhouseUserData.js +3 -2
  31. package/dist/lib/resources/aws/analytics/index.d.ts +2 -0
  32. package/dist/lib/resources/aws/analytics/index.js +1 -0
  33. package/dist/lib/resources/aws/compute/ecsRemoteConnections.d.ts +38 -0
  34. package/dist/lib/resources/aws/compute/ecsRemoteConnections.js +80 -0
  35. package/dist/lib/resources/aws/compute/ecsTaskDefinition.js +8 -0
  36. package/dist/lib/resources/aws/compute/ecsTypes.d.ts +7 -0
  37. package/dist/lib/resources/aws/iam/delegationRole.js +11 -4
  38. package/dist/lib/resources/aws/networking/crossAccountDelegationRecord.js +2 -1
  39. package/dist/lib/resources/aws/networking/crossAccountReturnRoutes.d.ts +40 -0
  40. package/dist/lib/resources/aws/networking/crossAccountReturnRoutes.js +154 -0
  41. package/dist/lib/resources/aws/networking/dnsRecord/dnsRecordBase.js +2 -1
  42. package/dist/lib/resources/aws/networking/domainCertificate.js +2 -1
  43. package/dist/lib/resources/aws/networking/hostedZone.js +2 -1
  44. package/dist/lib/resources/aws/networking/index.d.ts +3 -0
  45. package/dist/lib/resources/aws/networking/index.js +3 -0
  46. package/dist/lib/resources/aws/networking/vpc.js +6 -2
  47. package/dist/lib/resources/aws/networking/vpcPeeringAccepterRole.d.ts +18 -0
  48. package/dist/lib/resources/aws/networking/vpcPeeringAccepterRole.js +61 -0
  49. package/dist/lib/resources/aws/networking/vpcPeeringConnection.d.ts +49 -0
  50. package/dist/lib/resources/aws/networking/vpcPeeringConnection.js +88 -0
  51. package/dist/lib/utils/bastionFactory.d.ts +10 -0
  52. package/dist/lib/utils/bastionFactory.js +29 -0
  53. package/dist/lib/utils/capitaliseString.d.ts +1 -1
  54. package/dist/lib/utils/capitaliseString.js +1 -1
  55. package/dist/lib/utils/cdkContext.d.ts +8 -0
  56. package/dist/lib/utils/cdkContext.js +11 -0
  57. package/dist/lib/utils/connections.d.ts +7 -1
  58. package/dist/lib/utils/connections.js +15 -0
  59. package/dist/lib/utils/connector.d.ts +18 -2
  60. package/dist/lib/utils/connector.js +6 -1
  61. package/dist/lib/utils/costAllocationTags.d.ts +6 -0
  62. package/dist/lib/utils/costAllocationTags.js +6 -0
  63. package/dist/lib/utils/index.d.ts +3 -0
  64. package/dist/lib/utils/index.js +3 -0
  65. package/dist/lib/utils/vpcPeerInterface.d.ts +22 -0
  66. package/dist/lib/utils/vpcPeerInterface.js +1 -0
  67. package/package.json +4 -3
package/dist/lib/app.d.ts CHANGED
@@ -8,6 +8,8 @@ import { type Ecr } from "./resources/aws/storage/ecr.js";
8
8
  import { type AnyDatabase } from "./patterns/aws/database.js";
9
9
  import { type INetworkProps, type Network } from "./patterns/aws/network.js";
10
10
  import { type Cdn } from "./patterns/aws/cdn.js";
11
+ import { type VpcPeer } from "./patterns/aws/vpcPeer.js";
12
+ import { type VpcPeerAccepter } from "./patterns/aws/vpcPeerAccepter.js";
11
13
  import { type AnyMessaging } from "./patterns/aws/messaging.js";
12
14
  import { type AnyCompute } from "./patterns/aws/compute.js";
13
15
  import { type Storage, type StorageFactoryFn } from "./patterns/aws/storage.js";
@@ -85,63 +87,19 @@ export declare class App extends CdkApp {
85
87
  private resourceInventory?;
86
88
  private manifestCollector;
87
89
  private constructor();
88
- /**
89
- * Apply backup tier tag to all resources in the app.
90
- * Maps tier names to AWS Backup plan tag values.
91
- */
92
90
  private applyBackupTag;
93
- /**
94
- * Initialise the tunnel bastion in the network stack.
95
- * Creates a minimal EC2 instance for SSM port forwarding to databases.
96
- */
97
91
  private initialiseTunnel;
98
- /**
99
- * Initialise the network (VPC) for this application.
100
- */
101
92
  private initialiseNetwork;
102
- /**
103
- * Get the application name.
104
- * @returns {string} The application name
105
- */
106
93
  getName(): string;
107
- /**
108
- * Get/Create a basic Fjall Application with standard tags applied.
109
- *
110
- * @param name Application name
111
- * @param options Configuration options including network settings
112
- * @returns {App}
113
- *
114
- * @example
115
- * // Create app with new VPC
116
- * const app = App.getApp(appName, {
117
- * network: { maxAzs: 2, natGateways: false }
118
- * });
119
- *
120
- * @example
121
- * // Create app using existing VPC
122
- * const app = App.getApp(appName, {
123
- * network: { useExisting: "vpc-12345678" }
124
- * });
125
- *
126
- * @example
127
- * // Create app without network (S3-only apps)
128
- * const app = App.getApp(appName, { network: false });
129
- */
130
94
  static getApp(name?: string, options?: IAppOptions): App;
131
- /**
132
- * Get/Create the singleton instance of the App
133
- * @param name Application name
134
- * @param options Configuration options including network settings
135
- * @returns {App}
136
- */
137
95
  static getInstance(name?: string, options?: IAppOptions): App;
96
+ static resetForTesting(): void;
138
97
  /**
139
98
  * Retrieve a stack by key. If the stack does not exist, it will be created.
140
99
  * Dependencies are only applied the first time a stack is created.
141
100
  *
142
101
  * @param key - The key of the stack
143
102
  * @param dependencies - The stack(s) that this stack depends on
144
- * @returns {AwsStack}
145
103
  */
146
104
  getStack(key: string, dependencies?: AwsStack | AwsStack[]): AwsStack;
147
105
  /**
@@ -149,23 +107,18 @@ export declare class App extends CdkApp {
149
107
  *
150
108
  * Only depends on Network. Database dependency is added automatically
151
109
  * by CDK when compute resources reference database resources.
152
- *
153
- * @returns {AwsStack}
154
110
  */
155
111
  getDefaultComputeStack(): AwsStack;
156
112
  /**
157
113
  * Retrieve default network stack - named as `${this.name}Network`
158
- * @returns {AwsStack}
159
114
  */
160
115
  getDefaultNetworkStack(): AwsStack;
161
116
  /**
162
117
  * Retrieve default database stack - named as `${this.name}Database`
163
- * @returns {AwsStack}
164
118
  */
165
119
  getDefaultDatabaseStack(): AwsStack;
166
120
  /**
167
121
  * Retrieve default storage stack - named as `${this.name}Storage`
168
- * @returns {AwsStack}
169
122
  */
170
123
  getDefaultStorageStack(): AwsStack;
171
124
  /**
@@ -173,8 +126,6 @@ export declare class App extends CdkApp {
173
126
  *
174
127
  * Depends on Network. Compute/Storage dependencies are added automatically
175
128
  * by CDK when CDN resources reference ALB or S3 bucket resources.
176
- *
177
- * @returns {AwsStack}
178
129
  */
179
130
  getDefaultCdnStack(): AwsStack;
180
131
  /**
@@ -183,8 +134,6 @@ export declare class App extends CdkApp {
183
134
  * Used for SQS queues, SNS topics, and EventBridge event buses.
184
135
  * Depends on Network only. These are regional services that don't
185
136
  * require VPC, but we maintain consistent stack dependency patterns.
186
- *
187
- * @returns {AwsStack}
188
137
  */
189
138
  getDefaultMessagingStack(): AwsStack;
190
139
  /**
@@ -194,20 +143,10 @@ export declare class App extends CdkApp {
194
143
  * Network must be configured via App.getApp() options or app.addNetwork().
195
144
  *
196
145
  * @param name - Optional name of the VPC to retrieve. If not provided, returns the default VPC.
197
- * @returns {IVpc} The configured VPC
198
146
  * @throws {Error} If network is disabled, not configured, or named VPC not found
199
147
  */
200
148
  getVpc(name?: string): IVpc;
201
- /**
202
- * Get the names of all available VPCs.
203
- *
204
- * @returns {string[]} Array of VPC names. Includes "default" if the default VPC is configured.
205
- */
206
149
  getVpcNames(): string[];
207
- /**
208
- * Retrieve the default application container registry. If the registry does not exist
209
- * it will be created.
210
- */
211
150
  getDefaultContainerRegistry(): Ecr;
212
151
  /**
213
152
  * Create a cross-account audit role in the Network stack that allows
@@ -218,18 +157,9 @@ export declare class App extends CdkApp {
218
157
  *
219
158
  * @param webappAccountId - Optional AWS account ID of the Fjall webapp. Defaults to configured platform account.
220
159
  * @param externalId - Optional external ID for additional security. If not provided, a unique ID will be generated.
221
- * @returns {Role} The created audit role
222
160
  */
223
161
  createAuditRole(webappAccountId?: string, externalId?: string): Role;
224
- /**
225
- * Get the external ID used for the audit role
226
- * @returns {string | undefined} The external ID if audit role has been created
227
- */
228
162
  getAuditRoleExternalId(): string | undefined;
229
- /**
230
- * Generate a unique external ID for audit role
231
- * Format: fjall-audit-{appName}-{timestamp}
232
- */
233
163
  private generateAuditExternalId;
234
164
  /**
235
165
  * Add a compute resource to the default compute stack using the factory pattern.
@@ -255,10 +185,7 @@ export declare class App extends CdkApp {
255
185
  * }));
256
186
  * worker.getFunction("process"); // Available on LambdaCompute
257
187
  */
258
- addCompute<T extends AnyCompute>(fn: (app: App, scope: Construct) => T): T;
259
- /**
260
- * Manually add a resource to the default compute stack.
261
- */
188
+ addCompute<T extends AnyCompute & Construct>(fn: (app: App, scope: Construct) => T): T;
262
189
  addComputeResource(resource: Construct): void;
263
190
  /**
264
191
  * Add a database resource to the default database stack using the factory pattern.
@@ -280,10 +207,7 @@ export declare class App extends CdkApp {
280
207
  * }));
281
208
  * cache.getTableName(); // Available
282
209
  */
283
- addDatabase<T extends AnyDatabase>(fn: (app: App, scope: Construct) => T): T;
284
- /**
285
- * Type guard for IConnectable — checks if a construct has a connections property.
286
- */
210
+ addDatabase<T extends AnyDatabase & Construct>(fn: (app: App, scope: Construct) => T): T;
287
211
  private isConnectable;
288
212
  /**
289
213
  * Add a storage resource (S3) to the default storage stack using the factory pattern.
@@ -322,6 +246,22 @@ export declare class App extends CdkApp {
322
246
  * }));
323
247
  */
324
248
  addCdn(fn: (app: App, scope: Construct) => Cdn): Cdn;
249
+ /**
250
+ * Peer this app's VPC with a remote app's VPC.
251
+ *
252
+ * Creates the peering connection plus routes on both sides. The remote app
253
+ * must have deployed a `VpcPeerAccepter` first. Note: `app.getVpc(peerAppName)`
254
+ * does NOT return the peer's VPC — callers wanting the remote handle must use
255
+ * the returned `VpcPeer` instance.
256
+ */
257
+ addVpcPeer(fn: (app: App, scope: Construct) => VpcPeer): VpcPeer;
258
+ /**
259
+ * Accept VPC peering requests from remote apps.
260
+ *
261
+ * Creates an IAM role for cross-account peering acceptance and return-route
262
+ * management, and publishes VPC metadata to SSM for discovery.
263
+ */
264
+ addVpcPeerAccepter(fn: (app: App, scope: Construct) => VpcPeerAccepter): VpcPeerAccepter;
325
265
  /**
326
266
  * Add a messaging resource to the default queue stack using the factory pattern.
327
267
  *
@@ -347,7 +287,7 @@ export declare class App extends CdkApp {
347
287
  * contentBasedDeduplication: true
348
288
  * }));
349
289
  */
350
- addMessaging<T extends AnyMessaging>(fn: (app: App, scope: Construct) => T): T;
290
+ addMessaging<T extends AnyMessaging & Construct>(fn: (app: App, scope: Construct) => T): T;
351
291
  /**
352
292
  * Add a high-level infrastructure pattern to the application.
353
293
  *
@@ -375,7 +315,7 @@ export declare class App extends CdkApp {
375
315
  * payload.getServer().getLambdaFunction().addEnvironment("CUSTOM", "value");
376
316
  * payload.getCdn().getDistribution().addBehavior("/custom/*", customOrigin);
377
317
  */
378
- addPattern<T extends AnyPattern>(fn: (app: App, scope: Construct) => T): T;
318
+ addPattern<T extends AnyPattern & Construct>(fn: (app: App, scope: Construct) => T): T;
379
319
  /**
380
320
  * Add an additional network (VPC) to the application.
381
321
  *
@@ -383,7 +323,6 @@ export declare class App extends CdkApp {
383
323
  * Additional VPCs can be retrieved by name using app.getVpc(name).
384
324
  *
385
325
  * @param fn - Factory function that creates the Network construct
386
- * @returns {Network} The created Network construct
387
326
  *
388
327
  * @example
389
328
  * const isolatedVpc = app.addNetwork(
@@ -391,21 +330,9 @@ export declare class App extends CdkApp {
391
330
  * );
392
331
  */
393
332
  addNetwork(fn: (app: App, scope: Construct) => Network): Network;
394
- /**
395
- * Manually add a resource to the default database stack.
396
- */
397
333
  addDatabaseResource(resource: Construct): void;
398
- /**
399
- * Manually add a resource to the default storage stack.
400
- */
401
334
  addStorageResource(resource: Construct): void;
402
- /**
403
- * Initialise standard tags
404
- */
405
335
  private initialiseStandardTags;
406
- /**
407
- * Apply all tags using CDK's native Tags.of().add() API
408
- */
409
336
  private applyTagsAspect;
410
337
  /**
411
338
  * Add custom tags to all resources in the app.
@@ -414,27 +341,16 @@ export declare class App extends CdkApp {
414
341
  * @example
415
342
  * app.addTags({
416
343
  * "fjall:costAllocation:owner": "platform-team",
417
- * "fjall:costAllocation:cost-center": "CC-123",
344
+ * "fjall:costAllocation:cost-centre": "CC-123",
418
345
  * "team:slack-channel": "#platform-alerts"
419
346
  * });
420
347
  */
421
348
  addTags(tags: {
422
349
  [key: string]: string;
423
350
  }): App;
424
- /**
425
- * Export resource inventory collected during synthesis
426
- * Call this after app.synth() to get complete resource inventory
427
- * @returns {ResourceInventory} Complete inventory of all resources in the app
428
- */
351
+ /** Call after app.synth() — inventory is not available before synthesis. */
429
352
  exportResourceInventory(): ResourceInventory;
430
- /**
431
- * Get the manifest collector for registering services and patterns.
432
- * Used by ComputeFactory and PatternFactory to register their configurations.
433
- */
434
353
  getManifestCollector(): ManifestCollector;
435
- /**
436
- * Override synth to automatically export resource inventory and manifest
437
- */
438
354
  synth(options?: StageSynthesisOptions): CloudAssembly;
439
355
  }
440
356
  export default App;
package/dist/lib/app.js CHANGED
@@ -1,7 +1,6 @@
1
1
  import { App as CdkApp, Aspects, Tags } from "aws-cdk-lib";
2
2
  import { Vpc } from "./resources/aws/networking/vpc.js";
3
- import { CfnOutput } from "aws-cdk-lib";
4
- import { Ec2Instance } from "./resources/aws/compute/ec2.js";
3
+ import { createBastion } from "./utils/bastionFactory.js";
5
4
  import { AwsStack } from "./resources/index.js";
6
5
  import { EcrFactory } from "./resources/aws/storage/ecr.js";
7
6
  import { NetworkFactory } from "./patterns/aws/network.js";
@@ -14,8 +13,7 @@ import { FJALL_AUDIT_CONFIG } from "./config/audit.js";
14
13
  import { FjallLogger } from "./utils/validationLogger.js";
15
14
  import { getManifestCollector, writeManifest } from "./utils/manifestWriter.js";
16
15
  import { toPascalCase, toKebab } from "./utils/capitaliseString.js";
17
- const COST_ALLOCATION_ENVIRONMENT_TAG = "fjall:costAllocation:environment";
18
- const COST_ALLOCATION_SERVICE_TAG = "fjall:costAllocation:service";
16
+ import { COST_ALLOCATION_TAGS } from "./utils/costAllocationTags.js";
19
17
  /**
20
18
  * The basic corner-stone of all Fjall-hosted applications.
21
19
  * This class is a singleton and should be used to create and manage
@@ -62,48 +60,16 @@ export class App extends CdkApp {
62
60
  this.initialiseTunnel(options.tunnel);
63
61
  }
64
62
  }
65
- /**
66
- * Apply backup tier tag to all resources in the app.
67
- * Maps tier names to AWS Backup plan tag values.
68
- */
69
63
  applyBackupTag(tier) {
70
64
  this.globalTags[BACKUP_TIER_TAG_KEY] = BACKUP_TIER_TAG_MAP[tier];
71
65
  }
72
- /**
73
- * Initialise the tunnel bastion in the network stack.
74
- * Creates a minimal EC2 instance for SSM port forwarding to databases.
75
- */
76
66
  initialiseTunnel(config) {
77
67
  if (this.networkDisabled || !this.vpc) {
78
68
  throw new Error("Tunnel requires a network. Configure network before enabling tunnel.");
79
69
  }
80
- const instanceType = typeof config === "object" && config.instanceType
81
- ? config.instanceType
82
- : "t4g.micro";
83
- const networkStack = this.getDefaultNetworkStack();
84
- const bastionId = `${this.stackPrefix}Bastion`;
85
- this.bastion = new Ec2Instance(networkStack.getStack(), bastionId, {
86
- serviceName: `${this.stackPrefix}Bastion`,
87
- instanceType,
88
- vpc: this.vpc,
89
- enableSSH: false,
90
- minCapacity: 1,
91
- maxCapacity: 1
92
- });
93
- networkStack.addConstruct(this.bastion);
94
- const outputPrefix = toPascalCase(this.name);
95
- new CfnOutput(networkStack.getStack(), `${outputPrefix}BastionInstanceId`, {
96
- value: this.bastion.getAutoScalingGroup().autoScalingGroupName,
97
- description: "Bastion ASG name for SSM tunnel discovery"
98
- });
99
- new CfnOutput(networkStack.getStack(), `${outputPrefix}BastionSecurityGroupId`, {
100
- value: this.bastion.asgSecurityGroup.securityGroupId,
101
- description: "Bastion security group ID"
102
- });
70
+ const { bastion } = createBastion(this.getDefaultNetworkStack(), this.name, this.stackPrefix, this.vpc, config);
71
+ this.bastion = bastion;
103
72
  }
104
- /**
105
- * Initialise the network (VPC) for this application.
106
- */
107
73
  initialiseNetwork(config) {
108
74
  const networkStack = this.getDefaultNetworkStack();
109
75
  if ("useExisting" in config) {
@@ -117,45 +83,12 @@ export class App extends CdkApp {
117
83
  this.vpc = network.getVpc();
118
84
  }
119
85
  }
120
- /**
121
- * Get the application name.
122
- * @returns {string} The application name
123
- */
124
86
  getName() {
125
87
  return this.name;
126
88
  }
127
- /**
128
- * Get/Create a basic Fjall Application with standard tags applied.
129
- *
130
- * @param name Application name
131
- * @param options Configuration options including network settings
132
- * @returns {App}
133
- *
134
- * @example
135
- * // Create app with new VPC
136
- * const app = App.getApp(appName, {
137
- * network: { maxAzs: 2, natGateways: false }
138
- * });
139
- *
140
- * @example
141
- * // Create app using existing VPC
142
- * const app = App.getApp(appName, {
143
- * network: { useExisting: "vpc-12345678" }
144
- * });
145
- *
146
- * @example
147
- * // Create app without network (S3-only apps)
148
- * const app = App.getApp(appName, { network: false });
149
- */
150
89
  static getApp(name, options) {
151
90
  return App.getInstance(name, options);
152
91
  }
153
- /**
154
- * Get/Create the singleton instance of the App
155
- * @param name Application name
156
- * @param options Configuration options including network settings
157
- * @returns {App}
158
- */
159
92
  static getInstance(name, options) {
160
93
  // Despite supporting multiple stacks you can still only ever
161
94
  // have a single Application per CDK deployment
@@ -198,13 +131,15 @@ export class App extends CdkApp {
198
131
  }
199
132
  return App.instance;
200
133
  }
134
+ static resetForTesting() {
135
+ App.instance = null;
136
+ }
201
137
  /**
202
138
  * Retrieve a stack by key. If the stack does not exist, it will be created.
203
139
  * Dependencies are only applied the first time a stack is created.
204
140
  *
205
141
  * @param key - The key of the stack
206
142
  * @param dependencies - The stack(s) that this stack depends on
207
- * @returns {AwsStack}
208
143
  */
209
144
  getStack(key, dependencies) {
210
145
  // Apply the aspect once before creating the first stack
@@ -223,29 +158,24 @@ export class App extends CdkApp {
223
158
  *
224
159
  * Only depends on Network. Database dependency is added automatically
225
160
  * by CDK when compute resources reference database resources.
226
- *
227
- * @returns {AwsStack}
228
161
  */
229
162
  getDefaultComputeStack() {
230
163
  return this.getStack(`${this.stackPrefix}Compute`, this.getDefaultNetworkStack());
231
164
  }
232
165
  /**
233
166
  * Retrieve default network stack - named as `${this.name}Network`
234
- * @returns {AwsStack}
235
167
  */
236
168
  getDefaultNetworkStack() {
237
169
  return this.getStack(`${this.stackPrefix}Network`);
238
170
  }
239
171
  /**
240
172
  * Retrieve default database stack - named as `${this.name}Database`
241
- * @returns {AwsStack}
242
173
  */
243
174
  getDefaultDatabaseStack() {
244
175
  return this.getStack(`${this.stackPrefix}Database`, this.getDefaultNetworkStack());
245
176
  }
246
177
  /**
247
178
  * Retrieve default storage stack - named as `${this.name}Storage`
248
- * @returns {AwsStack}
249
179
  */
250
180
  getDefaultStorageStack() {
251
181
  return this.getStack(`${this.stackPrefix}Storage`, this.getDefaultNetworkStack());
@@ -255,8 +185,6 @@ export class App extends CdkApp {
255
185
  *
256
186
  * Depends on Network. Compute/Storage dependencies are added automatically
257
187
  * by CDK when CDN resources reference ALB or S3 bucket resources.
258
- *
259
- * @returns {AwsStack}
260
188
  */
261
189
  getDefaultCdnStack() {
262
190
  return this.getStack(`${this.stackPrefix}Cdn`, this.getDefaultNetworkStack());
@@ -267,8 +195,6 @@ export class App extends CdkApp {
267
195
  * Used for SQS queues, SNS topics, and EventBridge event buses.
268
196
  * Depends on Network only. These are regional services that don't
269
197
  * require VPC, but we maintain consistent stack dependency patterns.
270
- *
271
- * @returns {AwsStack}
272
198
  */
273
199
  getDefaultMessagingStack() {
274
200
  return this.getStack(`${this.stackPrefix}Messaging`, this.getDefaultNetworkStack());
@@ -280,7 +206,6 @@ export class App extends CdkApp {
280
206
  * Network must be configured via App.getApp() options or app.addNetwork().
281
207
  *
282
208
  * @param name - Optional name of the VPC to retrieve. If not provided, returns the default VPC.
283
- * @returns {IVpc} The configured VPC
284
209
  * @throws {Error} If network is disabled, not configured, or named VPC not found
285
210
  */
286
211
  getVpc(name) {
@@ -304,11 +229,6 @@ export class App extends CdkApp {
304
229
  }
305
230
  return this.vpc;
306
231
  }
307
- /**
308
- * Get the names of all available VPCs.
309
- *
310
- * @returns {string[]} Array of VPC names. Includes "default" if the default VPC is configured.
311
- */
312
232
  getVpcNames() {
313
233
  const names = [];
314
234
  if (this.vpc) {
@@ -317,10 +237,6 @@ export class App extends CdkApp {
317
237
  names.push(...this.additionalVpcs.keys());
318
238
  return names;
319
239
  }
320
- /**
321
- * Retrieve the default application container registry. If the registry does not exist
322
- * it will be created.
323
- */
324
240
  getDefaultContainerRegistry() {
325
241
  if (!this.defaultEcr) {
326
242
  const networkStack = this.getDefaultNetworkStack();
@@ -341,7 +257,6 @@ export class App extends CdkApp {
341
257
  *
342
258
  * @param webappAccountId - Optional AWS account ID of the Fjall webapp. Defaults to configured platform account.
343
259
  * @param externalId - Optional external ID for additional security. If not provided, a unique ID will be generated.
344
- * @returns {Role} The created audit role
345
260
  */
346
261
  createAuditRole(webappAccountId, externalId) {
347
262
  if (!this.defaultAuditRole) {
@@ -361,17 +276,9 @@ export class App extends CdkApp {
361
276
  }
362
277
  return this.defaultAuditRole;
363
278
  }
364
- /**
365
- * Get the external ID used for the audit role
366
- * @returns {string | undefined} The external ID if audit role has been created
367
- */
368
279
  getAuditRoleExternalId() {
369
280
  return this.auditRoleExternalId;
370
281
  }
371
- /**
372
- * Generate a unique external ID for audit role
373
- * Format: fjall-audit-{appName}-{timestamp}
374
- */
375
282
  generateAuditExternalId() {
376
283
  const uniqueId = randomBytes(8).toString("hex");
377
284
  return `fjall-audit-${toKebab(this.name)}-${uniqueId}`;
@@ -406,9 +313,6 @@ export class App extends CdkApp {
406
313
  computeStack.addConstruct(construct);
407
314
  return construct;
408
315
  }
409
- /**
410
- * Manually add a resource to the default compute stack.
411
- */
412
316
  addComputeResource(resource) {
413
317
  const computeStack = this.getDefaultComputeStack();
414
318
  computeStack.addConstruct(resource);
@@ -443,9 +347,6 @@ export class App extends CdkApp {
443
347
  }
444
348
  return databaseConstruct;
445
349
  }
446
- /**
447
- * Type guard for IConnectable — checks if a construct has a connections property.
448
- */
449
350
  isConnectable(construct) {
450
351
  return (typeof construct === "object" &&
451
352
  construct !== null &&
@@ -509,6 +410,32 @@ export class App extends CdkApp {
509
410
  cdnStack.addConstruct(cdn);
510
411
  return cdn;
511
412
  }
413
+ /**
414
+ * Peer this app's VPC with a remote app's VPC.
415
+ *
416
+ * Creates the peering connection plus routes on both sides. The remote app
417
+ * must have deployed a `VpcPeerAccepter` first. Note: `app.getVpc(peerAppName)`
418
+ * does NOT return the peer's VPC — callers wanting the remote handle must use
419
+ * the returned `VpcPeer` instance.
420
+ */
421
+ addVpcPeer(fn) {
422
+ const networkStack = this.getDefaultNetworkStack();
423
+ const peer = fn(this, networkStack.getStack());
424
+ networkStack.addConstruct(peer);
425
+ return peer;
426
+ }
427
+ /**
428
+ * Accept VPC peering requests from remote apps.
429
+ *
430
+ * Creates an IAM role for cross-account peering acceptance and return-route
431
+ * management, and publishes VPC metadata to SSM for discovery.
432
+ */
433
+ addVpcPeerAccepter(fn) {
434
+ const networkStack = this.getDefaultNetworkStack();
435
+ const accepter = fn(this, networkStack.getStack());
436
+ networkStack.addConstruct(accepter);
437
+ return accepter;
438
+ }
512
439
  /**
513
440
  * Add a messaging resource to the default queue stack using the factory pattern.
514
441
  *
@@ -580,7 +507,6 @@ export class App extends CdkApp {
580
507
  * Additional VPCs can be retrieved by name using app.getVpc(name).
581
508
  *
582
509
  * @param fn - Factory function that creates the Network construct
583
- * @returns {Network} The created Network construct
584
510
  *
585
511
  * @example
586
512
  * const isolatedVpc = app.addNetwork(
@@ -596,33 +522,19 @@ export class App extends CdkApp {
596
522
  networkStack.addConstruct(network);
597
523
  return network;
598
524
  }
599
- /**
600
- * Manually add a resource to the default database stack.
601
- */
602
525
  addDatabaseResource(resource) {
603
526
  const databaseStack = this.getDefaultDatabaseStack();
604
527
  databaseStack.addConstruct(resource);
605
528
  }
606
- /**
607
- * Manually add a resource to the default storage stack.
608
- */
609
529
  addStorageResource(resource) {
610
530
  const storageStack = this.getDefaultStorageStack();
611
531
  storageStack.addConstruct(resource);
612
532
  }
613
- /**
614
- * Initialise standard tags
615
- */
616
533
  initialiseStandardTags() {
617
534
  const config = getConfig();
618
- this.globalTags = {
619
- [COST_ALLOCATION_ENVIRONMENT_TAG]: config.environment,
620
- [COST_ALLOCATION_SERVICE_TAG]: this.name
621
- };
535
+ this.globalTags[COST_ALLOCATION_TAGS.ENVIRONMENT] = config.environment;
536
+ this.globalTags[COST_ALLOCATION_TAGS.SERVICE] = this.name;
622
537
  }
623
- /**
624
- * Apply all tags using CDK's native Tags.of().add() API
625
- */
626
538
  applyTagsAspect() {
627
539
  if (!this.aspectApplied && Object.keys(this.globalTags).length > 0) {
628
540
  // Apply standard tags using Tags.of(this).add()
@@ -641,7 +553,7 @@ export class App extends CdkApp {
641
553
  * @example
642
554
  * app.addTags({
643
555
  * "fjall:costAllocation:owner": "platform-team",
644
- * "fjall:costAllocation:cost-center": "CC-123",
556
+ * "fjall:costAllocation:cost-centre": "CC-123",
645
557
  * "team:slack-channel": "#platform-alerts"
646
558
  * });
647
559
  */
@@ -656,11 +568,7 @@ export class App extends CdkApp {
656
568
  }
657
569
  return this;
658
570
  }
659
- /**
660
- * Export resource inventory collected during synthesis
661
- * Call this after app.synth() to get complete resource inventory
662
- * @returns {ResourceInventory} Complete inventory of all resources in the app
663
- */
571
+ /** Call after app.synth() — inventory is not available before synthesis. */
664
572
  exportResourceInventory() {
665
573
  if (!this.resourceInventory) {
666
574
  throw new Error("Resource inventory not available. Ensure a ResourceInventoryAspect has been added before calling exportResourceInventory().");
@@ -671,16 +579,9 @@ export class App extends CdkApp {
671
579
  appName: this.name
672
580
  };
673
581
  }
674
- /**
675
- * Get the manifest collector for registering services and patterns.
676
- * Used by ComputeFactory and PatternFactory to register their configurations.
677
- */
678
582
  getManifestCollector() {
679
583
  return this.manifestCollector;
680
584
  }
681
- /**
682
- * Override synth to automatically export resource inventory and manifest
683
- */
684
585
  synth(options) {
685
586
  // Call parent synth first
686
587
  const assembly = super.synth(options);
@@ -4,6 +4,7 @@ import { ManagementEventsTrail } from "../../config/aws/cloudTrail.js";
4
4
  import { OidcConnector } from "../../config/aws/oidcConnector.js";
5
5
  import { AccountMonitoringRole } from "../../config/aws/accountMonitoringRole.js";
6
6
  import { AccountAuditRole } from "../../config/aws/accountAuditRole.js";
7
+ import { CDK_CONTEXT_KEYS } from "../../utils/cdkContext.js";
7
8
  import { getConfig } from "../../utils/getConfig.js";
8
9
  import { DisasterRecovery } from "../../config/aws/disasterRecovery.js";
9
10
  import { S3BlockPublicAccess } from "../../config/aws/s3BlockPublicAccess.js";
@@ -27,7 +28,7 @@ export class Account extends Stack {
27
28
  const env = props.env ?? { region, account: accountId };
28
29
  super(scope, id, { ...props, env });
29
30
  this.resolvedRegion = region ?? this.region;
30
- const orgId = this.node.tryGetContext("orgId");
31
+ const orgId = this.node.tryGetContext(CDK_CONTEXT_KEYS.ORG_ID);
31
32
  if (orgId) {
32
33
  new CfnOutput(this, "OrganisationIdOutput", {
33
34
  key: "OrganisationId",
@@ -66,10 +67,10 @@ export class Account extends Stack {
66
67
  }
67
68
  new ManagementEventsTrail(this, "CloudTrail", {
68
69
  accountId: this.account,
69
- region
70
+ region: this.resolvedRegion
70
71
  });
71
72
  new EcrDefaultImage(this, "EcrDefaultImage", {
72
- region,
73
+ region: this.resolvedRegion,
73
74
  accountId: this.account,
74
75
  eventBusArn: eventBus.defaultEventBusArn.value
75
76
  });
@@ -78,7 +79,7 @@ export class Account extends Stack {
78
79
  const isComplianceAccount = environment === "compliance";
79
80
  if (environment === "production" || isComplianceAccount) {
80
81
  new DisasterRecovery(this, "DisasterRecovery", {
81
- region,
82
+ region: this.resolvedRegion,
82
83
  accountId
83
84
  });
84
85
  }