@raindancers/raindancers-crew 0.0.1 → 0.0.2

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.
@@ -0,0 +1,247 @@
1
+ import * as autoscaling from 'aws-cdk-lib/aws-autoscaling';
2
+ import * as ec2 from 'aws-cdk-lib/aws-ec2';
3
+ import * as ecs from 'aws-cdk-lib/aws-ecs';
4
+ import * as iam from 'aws-cdk-lib/aws-iam';
5
+ import { Construct } from 'constructs';
6
+ import { FargateCrew } from './fargate-crew';
7
+ import { FargateCrewBase } from './fargate-crew-base';
8
+ import { CrewArchitecture, ICrewBackupBucket } from './remote-crew-instance-props';
9
+ /**
10
+ * How a per-crew durable EBS volume is exposed to the host and its container.
11
+ *
12
+ * The device name the construct asks for (for example `/dev/sdf`) is NOT the
13
+ * kernel device name on Nitro/Graviton, where every EBS volume surfaces as an
14
+ * unpredictable `/dev/nvmeXn1`. The bootstrap therefore resolves each volume by
15
+ * a stable filesystem LABEL, never by the device path.
16
+ */
17
+ export interface CrewDataVolume {
18
+ /** The crew this volume belongs to. */
19
+ readonly crew: string;
20
+ /** The block device name requested at attach time (a hint, not the kernel name). */
21
+ readonly deviceName: string;
22
+ /** The stable filesystem label the bootstrap resolves and mounts by. */
23
+ readonly label: string;
24
+ /** The host mount path the container bind-mounts for `~/.kiro/crew`. */
25
+ readonly mountPath: string;
26
+ }
27
+ /**
28
+ * Properties for {@link EcsCrewHost}.
29
+ */
30
+ export interface EcsCrewHostProps {
31
+ /**
32
+ * VPC to run in. Passed in, never created here.
33
+ *
34
+ * The construct consumes a two-subnet host-NAT topology it does not build:
35
+ * one PUBLIC subnet (host ENI + Elastic IP + IGW route) and one PRIVATE
36
+ * subnet (task ENIs, `0.0.0.0/0` -> the host ENI, no IGW route). Select them
37
+ * with {@link hostSubnets} and {@link taskSubnets}.
38
+ */
39
+ readonly vpc: ec2.IVpc;
40
+ /**
41
+ * ARN of an IAM permissions boundary applied to the host instance role.
42
+ *
43
+ * The host runs a prompt-injectable agent per crew, so its role MUST carry a
44
+ * boundary that caps blast radius. Required, not optional, matching
45
+ * {@link RemoteCrewInstanceProps.permissionsBoundaryArn}. Any valid managed-
46
+ * policy ARN is accepted here (this is the EC2/host boundary).
47
+ *
48
+ * The per-crew task/execution roles take {@link crewPermissionsBoundaryArn},
49
+ * which is validated separately against the `kirocrew-crew-boundary` pattern
50
+ * the crew roles require.
51
+ */
52
+ readonly permissionsBoundaryArn: string;
53
+ /**
54
+ * ARN of the pre-created shared crew permissions boundary
55
+ * (`arn:aws:iam::<account>:policy/kirocrew-crew-boundary`), applied to every
56
+ * per-crew task and execution role.
57
+ *
58
+ * Separate from {@link permissionsBoundaryArn} because the crew roles enforce
59
+ * the `kirocrew-crew-boundary` policy name (a different boundary from the
60
+ * host's), and validating them together would force one ARN to satisfy two
61
+ * distinct patterns. Optional, mirroring {@link FargateCrew}'s declared
62
+ * degraded mode: omit it only when no crew-boundary creator exists yet.
63
+ *
64
+ * @default - no crew boundary (declared degraded mode; see FargateCrew)
65
+ */
66
+ readonly crewPermissionsBoundaryArn?: string;
67
+ /**
68
+ * EC2 instance type for the single ECS-registered host.
69
+ *
70
+ * The type STAYS a settable prop: the 55minutes consumer passes
71
+ * `new ec2.InstanceType('m9g.xlarge')`. Never hardcoded to one family.
72
+ *
73
+ * @default - m7g.2xlarge (arm64) / m7i.2xlarge (x86_64), matching
74
+ * RemoteCrewInstance
75
+ */
76
+ readonly instanceType?: ec2.InstanceType;
77
+ /**
78
+ * CPU architecture of the host and the crew container images. Must match
79
+ * {@link instanceType} when that is set.
80
+ *
81
+ * @default CrewArchitecture.ARM64
82
+ */
83
+ readonly architecture?: CrewArchitecture;
84
+ /**
85
+ * Number of Kiro Crew instances to host, each one ECS task/service.
86
+ *
87
+ * DEFAULT 1 — identical to today's single-crew behaviour, so existing
88
+ * consumers gain nothing new. The 55minutes consumer passes 3. Validated
89
+ * 1..8: awsvpc gives each task its own ENI, and (crewCount + 1) ENIs (the
90
+ * host ENI plus one per task) must fit the instance type's ENI budget.
91
+ *
92
+ * @default 1
93
+ */
94
+ readonly crewCount?: number;
95
+ /**
96
+ * Explicit crew names. Each must match the {@link FargateCrew} regex
97
+ * `^[a-z0-9]([a-z0-9-]{0,30}[a-z0-9])?$`; the log group, roles, and secret
98
+ * namespace are derived from it. When omitted, names are generated as
99
+ * `crew-1`..`crew-<crewCount>`. When set, the list length must equal
100
+ * {@link crewCount}.
101
+ *
102
+ * @default - crew-1 .. crew-<crewCount>
103
+ */
104
+ readonly crews?: string[];
105
+ /**
106
+ * Subnet selection for the host ENI. This is the PUBLIC subnet (IGW-routed,
107
+ * carries the Elastic IP), because the host does the NAT for the tasks.
108
+ *
109
+ * @default - one public subnet in the VPC
110
+ */
111
+ readonly hostSubnets?: ec2.SubnetSelection;
112
+ /**
113
+ * Subnet selection for the crew task ENIs. This is the PRIVATE subnet whose
114
+ * `0.0.0.0/0` route points at the host ENI (no IGW route). Tasks get no
115
+ * public IP.
116
+ *
117
+ * @default - the VPC's private-with-egress subnets
118
+ */
119
+ readonly taskSubnets?: ec2.SubnetSelection;
120
+ /**
121
+ * gp3 root volume size in GiB for the host. Always encrypted.
122
+ *
123
+ * @default 60
124
+ */
125
+ readonly rootVolumeSizeGb?: number;
126
+ /**
127
+ * Per-crew durable EBS data volume size in GiB. Always encrypted, always
128
+ * `deleteOnTermination: false` (a crew's `~/.kiro/crew` learnings must
129
+ * outlive an instance replacement, matching the CrewBackupBucket RETAIN
130
+ * intent).
131
+ *
132
+ * @default 20
133
+ */
134
+ readonly crewDataVolumeSizeGb?: number;
135
+ /**
136
+ * Per-crew EBS volume type.
137
+ *
138
+ * @default ec2.EbsDeviceVolumeType.GP3
139
+ */
140
+ readonly crewDataVolumeType?: ec2.EbsDeviceVolumeType;
141
+ /**
142
+ * SOFT memory reservation (MiB) per crew container. ECS uses it for
143
+ * placement; a crew may burst above it when the host has spare RAM, so idle
144
+ * crews cost little.
145
+ *
146
+ * @default 1024
147
+ */
148
+ readonly crewMemoryReservationMiB?: number;
149
+ /**
150
+ * HARD memory cap (MiB) per crew container. A crew is OOM-killed at this
151
+ * ceiling, so no single crew can consume the whole host. Set the SUM of hard
152
+ * caps at or below (physical RAM minus host + ECS-agent headroom) for a hard
153
+ * cross-crew guarantee — see the host-OOM caution in the README.
154
+ *
155
+ * @default 2048
156
+ */
157
+ readonly crewMemoryHardLimitMiB?: number;
158
+ /**
159
+ * Optional SOFT CPU shares per crew container (1024 = one vCPU). Omit to
160
+ * leave CPU unconstrained (crews share the host CPU fairly under contention).
161
+ *
162
+ * @default - unset (shared CPU)
163
+ */
164
+ readonly crewCpuShares?: number;
165
+ /**
166
+ * ARN of the private ECR repository holding the crew image. Leave unset when
167
+ * the image is pulled from a public registry. When set, each per-crew
168
+ * execution role gets a pull grant scoped to this one repository.
169
+ *
170
+ * @default - public registry; no pull grant
171
+ */
172
+ readonly ecrRepositoryArn?: string;
173
+ /**
174
+ * Container image reference for the crew task. When {@link ecrRepositoryArn}
175
+ * is set this is typically the repo URI with a tag; otherwise a public
176
+ * registry reference.
177
+ *
178
+ * @default 'public.ecr.aws/kirocrew/crew:latest'
179
+ */
180
+ readonly crewImage?: string;
181
+ /**
182
+ * Days a crew's task logs are kept. One of the CloudWatch retention values
183
+ * (see {@link FargateCrew}).
184
+ *
185
+ * @default 30
186
+ */
187
+ readonly logRetentionDays?: number;
188
+ /**
189
+ * An S3 backup bucket. When set, each per-crew TASK role is granted write so
190
+ * the running container pushes its own snapshots off-box.
191
+ *
192
+ * @default - no off-box backup
193
+ */
194
+ readonly backupBucket?: ICrewBackupBucket;
195
+ /**
196
+ * Discovery tag value written as `kirocrew:ecs-host`. Must match
197
+ * `[a-zA-Z0-9-]{1,51}`. The cluster is named `kirocrew-crew-<stackTag>`.
198
+ *
199
+ * @default 'kirocrew'
200
+ */
201
+ readonly stackTag?: string;
202
+ }
203
+ /**
204
+ * One self-provisioned EC2 host running the ECS agent, hosting `crewCount`
205
+ * Kiro Crew instances as ECS-on-EC2 container tasks.
206
+ *
207
+ * The host registers to the {@link FargateCrewBase} cluster and does the NAT
208
+ * for the crew tasks itself, so the tasks stay fully private with no public
209
+ * IPs and no NAT Gateway, fck-nat, VPC endpoints, or ALB. Each task runs in
210
+ * awsvpc mode with its own ENI and private VPC IP; each crew keeps its durable
211
+ * `~/.kiro/crew` state on its own encrypted EBS volume that survives instance
212
+ * replacement.
213
+ *
214
+ * Isolation is container-level (shared kernel), accepted as sufficient:
215
+ * Graviton Nitro protects the box from other AWS tenants, containers cover
216
+ * crew-to-crew separation. See the host-OOM caution: hard per-task memory caps
217
+ * bound each crew's ceiling but a busy crew can still pressure siblings when
218
+ * the sum of actual usage exceeds physical RAM.
219
+ *
220
+ * `crewCount` defaults to 1, identical to the single-crew shape, so a plain
221
+ * instantiation with no new props gains no extra resources.
222
+ */
223
+ export declare class EcsCrewHost extends Construct {
224
+ /** The shared ECS scaffolding (cluster + egress-only task SG). */
225
+ readonly base: FargateCrewBase;
226
+ /** The size-1 Auto Scaling Group holding the single ECS-registered EC2 host. */
227
+ readonly autoScalingGroup: autoscaling.AutoScalingGroup;
228
+ /** The capacity provider registering the host with the cluster. */
229
+ readonly capacityProvider: ecs.AsgCapacityProvider;
230
+ /** The host instance's IAM role (carries the permissions boundary). */
231
+ readonly role: iam.Role;
232
+ /** The host's SSM-only security group (no inbound). */
233
+ readonly hostSecurityGroup: ec2.SecurityGroup;
234
+ /** The per-crew scaffolding (roles + log group), one per crew. */
235
+ readonly crews: FargateCrew[];
236
+ /** The per-crew EC2 services. */
237
+ readonly services: ecs.Ec2Service[];
238
+ /** The per-crew durable data volumes (device/label/mount metadata). */
239
+ readonly dataVolumes: CrewDataVolume[];
240
+ /** The discovery tag value written as `kirocrew:ecs-host`. */
241
+ readonly stackTag: string;
242
+ /** The resolved crew names. */
243
+ readonly crewNames: string[];
244
+ constructor(scope: Construct, id: string, props: EcsCrewHostProps);
245
+ /** The region the host runs in (read from the stack env, never a prop). */
246
+ get region(): string;
247
+ }