@deployfoundation/foundation-deploy 0.2.10 → 0.2.13

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,12 @@
1
+ {
2
+ "name": "open-slide-toolchain",
3
+ "private": true,
4
+ "type": "module",
5
+ "description": "Pinned open-slide toolchain baked into the agent image at /opt/open-slide (skills/slides). Not a workspace.",
6
+ "dependencies": {
7
+ "@open-slide/core": "2.0.1",
8
+ "playwright-core": "1.63.0",
9
+ "react": "19.2.8",
10
+ "react-dom": "19.2.8"
11
+ }
12
+ }
package/dist/bin/app.js CHANGED
@@ -7,12 +7,12 @@ import {
7
7
  FoundationNetwork,
8
8
  FoundationPipeline,
9
9
  NewsletterStack
10
- } from "../chunk-sxvts8bf.js";
10
+ } from "../chunk-ww9chzp9.js";
11
11
  import {
12
12
  adminsFor,
13
13
  instanceNames,
14
14
  loadInstanceFile
15
- } from "../chunk-n8qzcdq4.js";
15
+ } from "../chunk-7qn00ny1.js";
16
16
 
17
17
  // bin/app.ts
18
18
  import { execFileSync } from "node:child_process";
@@ -29,7 +29,7 @@ import {
29
29
  stackExists,
30
30
  stackOutput,
31
31
  toolVersion
32
- } from "../chunk-2kqazxx6.js";
32
+ } from "../chunk-e9vs85ah.js";
33
33
  import {
34
34
  BASE_SLACK_EVENTS,
35
35
  CAPABILITY_IDS,
@@ -45,7 +45,7 @@ import {
45
45
  requiredSlackScopes,
46
46
  skillsKey,
47
47
  slackCommandPrefix
48
- } from "../chunk-n8qzcdq4.js";
48
+ } from "../chunk-7qn00ny1.js";
49
49
 
50
50
  // src/deploy/config-sync.ts
51
51
  import { existsSync, mkdirSync, mkdtempSync, readdirSync } from "node:fs";
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env bun
2
2
  import {
3
3
  DEFAULT_RELEASE_BUCKET
4
- } from "../chunk-2kqazxx6.js";
5
- import"../chunk-n8qzcdq4.js";
4
+ } from "../chunk-e9vs85ah.js";
5
+ import"../chunk-7qn00ny1.js";
6
6
 
7
7
  // bin/release-account.ts
8
8
  import * as cdk2 from "aws-cdk-lib";
@@ -572,6 +572,14 @@ var RawProactive = z2.object({
572
572
  channels: z2.array(z2.string().regex(/^[CG][A-Z0-9]{8,}$/)).default([]),
573
573
  maxPerHour: z2.number().int().min(1).max(500).default(20)
574
574
  }).strict().default({ channels: [] });
575
+ var RawRuntime = z2.object({
576
+ idleTimeoutMinutes: z2.number().int().min(5).max(480).default(15),
577
+ maxLifetimeHours: z2.number().int().min(1).max(8).default(8)
578
+ }).strict().default({});
579
+ var RawNetwork = z2.object({
580
+ natGateways: z2.union([z2.literal(1), z2.literal(2)]).default(1),
581
+ endpointAzs: z2.union([z2.literal(1), z2.literal(2)]).default(1)
582
+ }).strict().default({});
575
583
  var RawNaming = z2.object({
576
584
  prefix: z2.string().min(1).max(32).regex(/^[A-Z][A-Za-z0-9]*$/),
577
585
  secretPrefix: z2.string().min(1).max(40).regex(/^[a-z][a-z0-9-]*$/),
@@ -711,6 +719,8 @@ var RawInstance = z2.object({
711
719
  license: RawLicense.optional(),
712
720
  config: z2.string().min(1),
713
721
  proactive: RawProactive,
722
+ runtime: RawRuntime,
723
+ network: RawNetwork,
714
724
  integrations: RawIntegrations,
715
725
  newsletter: RawNewsletter
716
726
  }).strict().superRefine((doc, ctx) => {
@@ -6,7 +6,7 @@ import {
6
6
  manifestKey,
7
7
  releaseCacheDir,
8
8
  verifyManifest
9
- } from "./chunk-n8qzcdq4.js";
9
+ } from "./chunk-7qn00ny1.js";
10
10
 
11
11
  // src/deploy/release.ts
12
12
  import { existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2 } from "node:fs";
@@ -19,7 +19,7 @@ import {
19
19
  scheduledJobBindings,
20
20
  slackCommandPrefixes,
21
21
  webhookJobBindings
22
- } from "./chunk-n8qzcdq4.js";
22
+ } from "./chunk-7qn00ny1.js";
23
23
 
24
24
  // src/stacks/agent-stack.ts
25
25
  import * as cdk from "aws-cdk-lib";
@@ -118,8 +118,8 @@ class FoundationAgent extends cdk.Stack {
118
118
  }
119
119
  ],
120
120
  LifecycleConfiguration: {
121
- IdleRuntimeSessionTimeout: 3600,
122
- MaxLifetime: 28800
121
+ IdleRuntimeSessionTimeout: props.instance.runtime.idleTimeoutMinutes * 60,
122
+ MaxLifetime: props.instance.runtime.maxLifetimeHours * 3600
123
123
  },
124
124
  RoleArn: this.executionRole.roleArn,
125
125
  EnvironmentVariables: {
@@ -2043,7 +2043,7 @@ class FoundationNetwork extends cdk5.Stack {
2043
2043
  } else {
2044
2044
  this.vpc = new ec2.Vpc(this, "FoundationVpc", {
2045
2045
  maxAzs: 2,
2046
- natGateways: 2,
2046
+ natGateways: props.instance.network.natGateways,
2047
2047
  subnetConfiguration: [
2048
2048
  { name: "ingress", subnetType: ec2.SubnetType.PUBLIC, cidrMask: 24 },
2049
2049
  { name: "egress", subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS, cidrMask: 24 },
@@ -2088,7 +2088,12 @@ class FoundationNetwork extends cdk5.Stack {
2088
2088
  });
2089
2089
  endpointSg.addIngressRule(ec2.Peer.ipv4(this.vpc.vpcCidrBlock), ec2.Port.tcp(443), "HTTPS from VPC");
2090
2090
  this.endpointSecurityGroup = endpointSg;
2091
- const endpointSubnets = importedVpcId ? { subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS } : { subnetGroupName: "app" };
2091
+ const endpointSubnets = importedVpcId ? { subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS, onePerAz: true } : { subnetGroupName: "app", onePerAz: true };
2092
+ if (props.instance.network.endpointAzs === 1) {
2093
+ const zones = this.vpc.selectSubnets(endpointSubnets).availabilityZones;
2094
+ if (zones.length > 1)
2095
+ Object.assign(endpointSubnets, { availabilityZones: [zones[0]] });
2096
+ }
2092
2097
  const gatewayEndpointSubnets = importedVpcId ? [{ subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS }] : [{ subnetGroupName: "app" }, { subnetGroupName: "egress" }];
2093
2098
  const sameAccountOnly = new iam6.PolicyStatement({
2094
2099
  effect: iam6.Effect.ALLOW,
package/dist/src/index.js CHANGED
@@ -9,7 +9,7 @@ import {
9
9
  FoundationPipeline,
10
10
  NewsletterStack,
11
11
  deployStatements
12
- } from "../chunk-sxvts8bf.js";
12
+ } from "../chunk-ww9chzp9.js";
13
13
  import {
14
14
  BUN_VERSION,
15
15
  LAMBDA_ENTRY_POINTS,
@@ -42,7 +42,7 @@ import {
42
42
  skillsKey,
43
43
  skipBundle,
44
44
  verifyManifest
45
- } from "../chunk-n8qzcdq4.js";
45
+ } from "../chunk-7qn00ny1.js";
46
46
  export {
47
47
  BUILD_TIMEOUT,
48
48
  BUN_VERSION,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deployfoundation/foundation-deploy",
3
- "version": "0.2.10",
3
+ "version": "0.2.13",
4
4
  "description": "Deploys one Foundation instance from a published, signed release: the CDK app and the deploy tool.",
5
5
  "license": "UNLICENSED",
6
6
  "private": false,
@@ -227,9 +227,11 @@ export class FoundationAgent extends cdk.Stack {
227
227
  },
228
228
  },
229
229
  ],
230
+ // Idle sessions are billed for their memory: see `runtime` in the
231
+ // instance schema for why the default is 15 minutes, not 60.
230
232
  LifecycleConfiguration: {
231
- IdleRuntimeSessionTimeout: 3600,
232
- MaxLifetime: 28800,
233
+ IdleRuntimeSessionTimeout: props.instance.runtime.idleTimeoutMinutes * 60,
234
+ MaxLifetime: props.instance.runtime.maxLifetimeHours * 3600,
233
235
  },
234
236
  RoleArn: this.executionRole.roleArn,
235
237
  EnvironmentVariables: {
@@ -70,9 +70,9 @@ export class FoundationNetwork extends cdk.Stack {
70
70
  } else {
71
71
  this.vpc = new ec2.Vpc(this, "FoundationVpc", {
72
72
  maxAzs: 2,
73
- // One NAT per AZ: the Slack ack / chat.update path must survive a
74
- // single-AZ failure.
75
- natGateways: 2,
73
+ // One NAT by default: a second (AZ-failure tolerance for egress) is
74
+ // about $33/month, opted into with `network.natGateways: 2`.
75
+ natGateways: props.instance.network.natGateways,
76
76
  subnetConfiguration: [
77
77
  { name: "ingress", subnetType: ec2.SubnetType.PUBLIC, cidrMask: 24 },
78
78
  { name: "egress", subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS, cidrMask: 24 },
@@ -82,7 +82,7 @@ export class FoundationNetwork extends cdk.Stack {
82
82
  this.egressSubnets = { subnetGroupName: "egress" };
83
83
  // The addresses everything in the VPC leaves through, so a third party
84
84
  // (an Atlas IP allowlist, say) can name this instance and no other.
85
- // One per AZ, matching `natGateways: 2` above.
85
+ // One per NAT gateway (`network.natGateways`).
86
86
  new cdk.CfnOutput(this, "NatEgressIp", {
87
87
  value: cdk.Fn.join(
88
88
  ",",
@@ -191,9 +191,16 @@ export class FoundationNetwork extends cdk.Stack {
191
191
  // Interface endpoints sit in the isolated app tier when we created the
192
192
  // VPC; on an imported VPC they land in its private subnets. Private DNS
193
193
  // makes them authoritative for the whole VPC either way.
194
+ // One AZ by default (`network.endpointAzs`): the other AZ reaches the
195
+ // same endpoint through private DNS, for a little cross-AZ traffic
196
+ // instead of a second set of endpoint-hours.
194
197
  const endpointSubnets: ec2.SubnetSelection = importedVpcId
195
- ? { subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS }
196
- : { subnetGroupName: "app" };
198
+ ? { subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS, onePerAz: true }
199
+ : { subnetGroupName: "app", onePerAz: true };
200
+ if (props.instance.network.endpointAzs === 1) {
201
+ const zones = this.vpc.selectSubnets(endpointSubnets).availabilityZones;
202
+ if (zones.length > 1) Object.assign(endpointSubnets, { availabilityZones: [zones[0]] });
203
+ }
197
204
  // Gateway endpoints attach to every private route table (app + egress) so
198
205
  // S3/DynamoDB traffic from the NAT tier also stays on AWS's network.
199
206
  const gatewayEndpointSubnets: ec2.SubnetSelection[] = importedVpcId