serverless-ircd 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/ci.yml +2 -2
- package/.github/workflows/deploy-aws.yml +1 -3
- package/.github/workflows/deploy-cf-tcp.yml +87 -0
- package/.github/workflows/deploy-cf.yml +1 -1
- package/.node-version +1 -0
- package/.nvmrc +1 -0
- package/CHANGELOG.md +174 -18
- package/README.md +63 -30
- package/apps/aws-stack/README.md +2 -2
- package/apps/aws-stack/bin/aws.ts +7 -0
- package/apps/aws-stack/package.json +4 -4
- package/apps/aws-stack/src/aws-stack.ts +118 -6
- package/apps/aws-stack/tests/stack.test.ts +98 -3
- package/apps/cf-tcp-container/Dockerfile +69 -0
- package/apps/cf-tcp-container/package.json +34 -0
- package/apps/cf-tcp-container/src/config-loader.ts +145 -0
- package/apps/cf-tcp-container/src/container-do.ts +38 -0
- package/apps/cf-tcp-container/src/container-server.ts +363 -0
- package/apps/cf-tcp-container/src/main.ts +77 -0
- package/apps/cf-tcp-container/src/persistence.ts +144 -0
- package/apps/cf-tcp-container/src/worker.ts +41 -0
- package/apps/cf-tcp-container/terraform/provider.tf +24 -0
- package/apps/cf-tcp-container/terraform/spectrum.tf +81 -0
- package/apps/cf-tcp-container/tests/config-loader.test.ts +217 -0
- package/apps/cf-tcp-container/tests/container-server.test.ts +465 -0
- package/apps/cf-tcp-container/tests/persistence.test.ts +227 -0
- package/apps/cf-tcp-container/tests/tls-e2e.test.ts +275 -0
- package/apps/cf-tcp-container/tsconfig.build.json +17 -0
- package/apps/cf-tcp-container/tsconfig.test.json +15 -0
- package/apps/cf-tcp-container/vitest.config.ts +26 -0
- package/apps/cf-tcp-container/wrangler.toml +63 -0
- package/apps/cf-worker/package.json +1 -1
- package/apps/cf-worker/wrangler.test.toml +6 -0
- package/apps/cf-worker/wrangler.toml +28 -2
- package/apps/local-cli/package.json +1 -1
- package/apps/local-cli/src/config-loader.ts +10 -0
- package/apps/local-cli/src/server.ts +20 -3
- package/package.json +14 -10
- package/packages/aws-adapter/package.json +3 -3
- package/packages/aws-adapter/src/account-store.ts +1 -1
- package/packages/aws-adapter/src/admission.ts +74 -0
- package/packages/aws-adapter/src/aws-runtime.ts +6 -4
- package/packages/aws-adapter/src/config-loader.ts +32 -0
- package/packages/aws-adapter/src/dynamo-account-store.ts +35 -96
- package/packages/aws-adapter/src/handlers/connect.ts +64 -8
- package/packages/aws-adapter/src/handlers/default.ts +35 -2
- package/packages/aws-adapter/src/handlers/index.ts +69 -3
- package/packages/aws-adapter/src/handlers/nlb-stream.ts +481 -0
- package/packages/aws-adapter/src/handlers/ping-checker.ts +1 -1
- package/packages/aws-adapter/src/index.ts +6 -0
- package/packages/aws-adapter/tests/account-store-dynamo.test.ts +45 -34
- package/packages/aws-adapter/tests/account-store.test.ts +19 -20
- package/packages/aws-adapter/tests/admission.test.ts +70 -0
- package/packages/aws-adapter/tests/aws-harness.ts +13 -1
- package/packages/aws-adapter/tests/config-loader.test.ts +20 -0
- package/packages/aws-adapter/tests/connect.test.ts +78 -0
- package/packages/aws-adapter/tests/disconnect-fanout.test.ts +47 -40
- package/packages/aws-adapter/tests/gone-exception.test.ts +31 -26
- package/packages/aws-adapter/tests/handlers.test.ts +154 -53
- package/packages/aws-adapter/tests/nlb-stream.test.ts +478 -0
- package/packages/aws-adapter/tests/ping-checker.test.ts +34 -29
- package/packages/aws-adapter/tests/sweeper.test.ts +25 -18
- package/packages/aws-adapter/tests/transactions.test.ts +25 -20
- package/packages/cf-adapter/package.json +1 -1
- package/packages/cf-adapter/src/cf-runtime.ts +2 -4
- package/packages/cf-adapter/src/config-loader.ts +33 -0
- package/packages/cf-adapter/src/connection-do.ts +111 -46
- package/packages/cf-adapter/src/d1-account-store.ts +198 -0
- package/packages/cf-adapter/src/env.ts +33 -9
- package/packages/cf-adapter/src/index.ts +9 -8
- package/packages/cf-adapter/tests/cf-harness.ts +11 -1
- package/packages/cf-adapter/tests/cf-integration.test.ts +2 -1
- package/packages/cf-adapter/tests/config-loader.test.ts +22 -0
- package/packages/cf-adapter/tests/connection-do-channel-registration.test.ts +37 -0
- package/packages/cf-adapter/tests/connection-do-no-batching-reservation.test.ts +52 -0
- package/packages/cf-adapter/tests/connection-do-sasl-d1.test.ts +166 -0
- package/packages/cf-adapter/tests/d1-account-store.test.ts +226 -0
- package/packages/cf-adapter/tests/raw-modules.d.ts +11 -0
- package/packages/cf-adapter/tests/worker/main.ts +8 -1
- package/packages/cf-adapter/wrangler.test.toml +8 -0
- package/packages/in-memory-runtime/package.json +1 -1
- package/packages/irc-core/package.json +6 -1
- package/packages/irc-core/scripts/generate-build-info.mjs +31 -0
- package/packages/irc-core/src/caps/capabilities.ts +23 -2
- package/packages/irc-core/src/cloak.ts +1 -1
- package/packages/irc-core/src/commands/cap.ts +8 -1
- package/packages/irc-core/src/commands/index.ts +9 -0
- package/packages/irc-core/src/commands/ison.ts +61 -0
- package/packages/irc-core/src/commands/quit.ts +12 -0
- package/packages/irc-core/src/commands/registration.ts +18 -12
- package/packages/irc-core/src/commands/sasl.ts +72 -9
- package/packages/irc-core/src/commands/server-info.ts +129 -0
- package/packages/irc-core/src/commands/userhost.ts +84 -0
- package/packages/irc-core/src/commands/whowas.ts +113 -0
- package/packages/irc-core/src/config.ts +58 -0
- package/packages/irc-core/src/credential-hashing.ts +124 -0
- package/packages/irc-core/src/effects.ts +6 -29
- package/packages/irc-core/src/index.ts +1 -0
- package/packages/irc-core/src/ports.ts +181 -12
- package/packages/irc-core/src/protocol/numerics.ts +14 -8
- package/packages/irc-core/src/types.ts +38 -1
- package/packages/irc-core/tests/account-store.test.ts +45 -2
- package/packages/irc-core/tests/caps/capabilities.test.ts +4 -3
- package/packages/irc-core/tests/commands/cap.test.ts +33 -1
- package/packages/irc-core/tests/commands/ison.test.ts +166 -0
- package/packages/irc-core/tests/commands/quit.test.ts +69 -2
- package/packages/irc-core/tests/commands/registration.test.ts +151 -6
- package/packages/irc-core/tests/commands/sasl.test.ts +118 -10
- package/packages/irc-core/tests/commands/server-info.test.ts +274 -0
- package/packages/irc-core/tests/commands/tagmsg.test.ts +9 -35
- package/packages/irc-core/tests/commands/userhost.test.ts +264 -0
- package/packages/irc-core/tests/commands/whowas.test.ts +312 -0
- package/packages/irc-core/tests/config.test.ts +95 -1
- package/packages/irc-core/tests/credential-hashing.test.ts +170 -0
- package/packages/irc-core/tests/effects.test.ts +0 -27
- package/packages/irc-core/tests/nick-history-store.test.ts +162 -0
- package/packages/irc-core/tests/numerics.test.ts +12 -0
- package/packages/irc-core/tests/types.test.ts +35 -1
- package/packages/irc-core/tsconfig.build.json +1 -1
- package/packages/irc-core/tsconfig.test.json +1 -1
- package/packages/irc-server/package.json +1 -1
- package/packages/irc-server/src/actor.ts +158 -14
- package/packages/irc-server/src/dispatch.ts +0 -3
- package/packages/irc-server/src/index.ts +10 -2
- package/packages/irc-server/src/routing.ts +12 -0
- package/packages/irc-server/src/transport.ts +101 -0
- package/packages/irc-server/tests/actor.test.ts +400 -3
- package/packages/irc-server/tests/dispatch.test.ts +0 -17
- package/packages/irc-server/tests/routing.test.ts +4 -0
- package/packages/irc-server/tests/transport.test.ts +230 -0
- package/packages/irc-test-support/package.json +1 -1
- package/packages/irc-test-support/src/harness.ts +44 -9
- package/packages/irc-test-support/src/in-memory-harness.ts +73 -9
- package/packages/irc-test-support/src/index.ts +3 -0
- package/packages/irc-test-support/src/scenarios.ts +132 -2
- package/packages/irc-test-support/tests/in-memory-harness.test.ts +2 -1
- package/packages/irc-test-support/tests/in-memory-scenarios.test.ts +23 -9
- package/pnpm-workspace.yaml +9 -1
- package/tools/ci-hardening/package.json +1 -1
- package/tools/package.json +4 -0
- package/tools/seed-aws-accounts.ts +5 -6
- package/tools/seed-cf-accounts.ts +104 -0
- package/tools/tcp-ws-forwarder/package.json +1 -1
- package/docs/ADR-001-pure-reducers-and-effect-system.md +0 -74
- package/docs/ADR-002-location-of-authority.md +0 -82
- package/docs/ADR-003-durable-object-sharding.md +0 -93
- package/docs/ADR-004-dynamodb-schema.md +0 -96
- package/docs/ADR-005-wss-only-transport-v1.md +0 -83
- package/docs/ADR-006-sasl-mechanism-scope.md +0 -86
- package/docs/ADR-007-deterministic-ports.md +0 -82
- package/docs/ADR-008-monorepo-tooling.md +0 -60
- package/docs/AWS-Adapter-Architecture.md +0 -496
- package/docs/AWS-Deployment.md +0 -1186
- package/docs/Cloudflare-Deployment-Guide.md +0 -660
- package/docs/Home.md +0 -11
- package/docs/Observability.md +0 -87
- package/docs/PlanIRCv3Websocket.md +0 -489
- package/docs/PlanWebClient.md +0 -451
- package/docs/Release-Process.md +0 -443
package/.github/workflows/ci.yml
CHANGED
|
@@ -39,7 +39,7 @@ jobs:
|
|
|
39
39
|
- name: Setup Node
|
|
40
40
|
uses: actions/setup-node@v4
|
|
41
41
|
with:
|
|
42
|
-
node-version:
|
|
42
|
+
node-version: 24
|
|
43
43
|
cache: pnpm
|
|
44
44
|
|
|
45
45
|
- name: Install dependencies
|
|
@@ -112,7 +112,7 @@ jobs:
|
|
|
112
112
|
- name: Setup Node
|
|
113
113
|
uses: actions/setup-node@v4
|
|
114
114
|
with:
|
|
115
|
-
node-version:
|
|
115
|
+
node-version: 24
|
|
116
116
|
cache: pnpm
|
|
117
117
|
|
|
118
118
|
- name: Install dependencies
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
name: deploy-cf-tcp
|
|
2
|
+
|
|
3
|
+
# Cloudflare TCP+TLS deploy pipeline (Spectrum + Container origin).
|
|
4
|
+
#
|
|
5
|
+
# Deploys the IRC TCP container origin (apps/cf-tcp-container) to Cloudflare
|
|
6
|
+
# Containers and applies the Spectrum TLS config (terraform). Spectrum
|
|
7
|
+
# terminates TLS on :6697 and forwards plaintext TCP to the container.
|
|
8
|
+
#
|
|
9
|
+
# This pipeline runs alongside deploy-cf.yml (the WebSocket path). The two
|
|
10
|
+
# are independent: a deployment can enable either or both transports.
|
|
11
|
+
#
|
|
12
|
+
# Secrets (configure under repo Settings → Secrets and variables → Actions):
|
|
13
|
+
# CLOUDFLARE_API_TOKEN Spectrum/Containers API token.
|
|
14
|
+
# CLOUDFLARE_ACCOUNT_ID Account ID for the target zone.
|
|
15
|
+
# CF_ZONE_ID Zone ID for the Spectrum hostname.
|
|
16
|
+
# CF_TCP_ORIGIN_ADDRESS Hostname/IP of the container origin.
|
|
17
|
+
|
|
18
|
+
on:
|
|
19
|
+
push:
|
|
20
|
+
branches: [main]
|
|
21
|
+
paths:
|
|
22
|
+
- 'apps/cf-tcp-container/**'
|
|
23
|
+
- '.github/workflows/deploy-cf-tcp.yml'
|
|
24
|
+
workflow_dispatch:
|
|
25
|
+
|
|
26
|
+
concurrency:
|
|
27
|
+
group: cf-tcp-staging
|
|
28
|
+
cancel-in-progress: false
|
|
29
|
+
|
|
30
|
+
jobs:
|
|
31
|
+
deploy-staging:
|
|
32
|
+
name: deploy cf-tcp staging
|
|
33
|
+
runs-on: ubuntu-latest
|
|
34
|
+
timeout-minutes: 15
|
|
35
|
+
steps:
|
|
36
|
+
- name: Checkout
|
|
37
|
+
uses: actions/checkout@v4
|
|
38
|
+
|
|
39
|
+
- name: Setup pnpm
|
|
40
|
+
uses: pnpm/action-setup@v4
|
|
41
|
+
|
|
42
|
+
- name: Setup Node
|
|
43
|
+
uses: actions/setup-node@v4
|
|
44
|
+
with:
|
|
45
|
+
node-version: 24
|
|
46
|
+
cache: pnpm
|
|
47
|
+
|
|
48
|
+
- name: Install dependencies
|
|
49
|
+
run: pnpm install --frozen-lockfile
|
|
50
|
+
|
|
51
|
+
- name: Build workspace
|
|
52
|
+
run: pnpm build
|
|
53
|
+
|
|
54
|
+
- name: Typecheck
|
|
55
|
+
run: pnpm typecheck
|
|
56
|
+
|
|
57
|
+
- name: Test
|
|
58
|
+
run: pnpm --filter '@serverless-ircd/cf-tcp-container' test
|
|
59
|
+
|
|
60
|
+
- name: Deploy container to staging
|
|
61
|
+
working-directory: apps/cf-tcp-container
|
|
62
|
+
env:
|
|
63
|
+
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
|
64
|
+
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
|
65
|
+
run: wrangler deploy --env staging
|
|
66
|
+
|
|
67
|
+
- name: Apply Spectrum TLS config
|
|
68
|
+
working-directory: apps/cf-tcp-container/terraform
|
|
69
|
+
env:
|
|
70
|
+
TF_VAR_zone_id: ${{ secrets.CF_ZONE_ID }}
|
|
71
|
+
TF_VAR_origin_address: ${{ secrets.CF_TCP_ORIGIN_ADDRESS }}
|
|
72
|
+
TF_VAR_hostname: irc-staging.example.com
|
|
73
|
+
run: |
|
|
74
|
+
terraform init
|
|
75
|
+
terraform apply -auto-approve
|
|
76
|
+
|
|
77
|
+
- name: Smoke e2e (irc+tls)
|
|
78
|
+
if: ${{ vars.CF_TCP_SMOKE_HOST != '' }}
|
|
79
|
+
env:
|
|
80
|
+
SMOKE_HOST: ${{ vars.CF_TCP_SMOKE_HOST }}
|
|
81
|
+
SMOKE_PORT: '6697'
|
|
82
|
+
run: |
|
|
83
|
+
# Minimal smoke: connect over TLS, register, join, privmsg, quit.
|
|
84
|
+
# Uses openssl s_client for the TLS handshake + IRC line exchange.
|
|
85
|
+
echo "NICK smoke\r\nUSER smoke 0 * :Smoke\r\nQUIT :smoke\r\n" | \
|
|
86
|
+
timeout 10 openssl s_client -connect "${SMOKE_HOST}:${SMOKE_PORT}" -quiet 2>/dev/null | \
|
|
87
|
+
grep -q "001" && echo "SMOKE PASS" || (echo "SMOKE FAIL" && exit 1)
|
package/.node-version
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
24
|
package/.nvmrc
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
24
|
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,164 @@ For the release process itself — versioning policy, pre-release checklist,
|
|
|
10
10
|
cutting a tag, rolling back — see [`docs/release.md`](docs/release.md).
|
|
11
11
|
Cross-reference `progress.md` / `tickets.md` for per-ticket detail.
|
|
12
12
|
|
|
13
|
+
## [0.4.0] - 2026-07-31
|
|
14
|
+
|
|
15
|
+
The headline is **dual transport**: both adapters now speak a real
|
|
16
|
+
`irc+tls :6697` (TLS-over-TCP) surface for stock IRC clients in
|
|
17
|
+
production — not just the local CLI — alongside the WebSocket path. This
|
|
18
|
+
lands **SASL `EXTERNAL` via mTLS**, the **remaining standard IRC verbs**
|
|
19
|
+
(WHOWAS, VERSION, TIME, ADMIN, INFO, USERHOST, ISON), a **Cloudflare
|
|
20
|
+
D1-backed SASL account store**, config-driven server identity, and a
|
|
21
|
+
**Node 24 / pnpm 11** toolchain. Phase 7 (TLS hardening & raw TCP) is
|
|
22
|
+
complete.
|
|
23
|
+
|
|
24
|
+
### Added — Dual transport: WebSocket + `irc+tls :6697`
|
|
25
|
+
|
|
26
|
+
The wss-only transport decision (ADR-005) is superseded by **ADR-009**
|
|
27
|
+
(dual transport). The shared `ConnectionActor` now drives either
|
|
28
|
+
transport through a generalized seam; the parser/reducer/dispatch
|
|
29
|
+
pipeline is unchanged.
|
|
30
|
+
|
|
31
|
+
- **Transport seam** (`@serverless-ircd/irc-server`,
|
|
32
|
+
`@serverless-ircd/irc-core`): the `\r\n` line-framing is extracted into
|
|
33
|
+
a `Transport` abstraction. `ConnectionActor` accepts a
|
|
34
|
+
`WsTextFrameTransport` (one message per WS frame, prior behavior) or a
|
|
35
|
+
`TcpByteStreamTransport` (stateful `\r\n` framing across chunks with
|
|
36
|
+
partial-line buffering). Both produce identical reducer invocations.
|
|
37
|
+
- **Cloudflare TCP+TLS** (`@serverless-ircd/cf-tcp-container`): a new
|
|
38
|
+
workspace app — **Cloudflare Spectrum** terminates TLS at the edge and
|
|
39
|
+
forwards plaintext TCP to a stateful **Container** origin running the
|
|
40
|
+
IRC core. Ships a `Dockerfile`, config loader, deploy pipeline
|
|
41
|
+
(`.github/workflows/deploy-cf-tcp.yml`), and root
|
|
42
|
+
`deploy:cf-tcp:staging` / `deploy:cf-tcp:prod` scripts.
|
|
43
|
+
- **AWS TCP+TLS** (`@serverless-ircd/aws-adapter`, `@serverless-ircd/aws-stack`):
|
|
44
|
+
a **Network Load Balancer** with a `tls` listener terminates TLS and
|
|
45
|
+
invokes a **Lambda streaming function** (`nlb-stream.ts`) as the target.
|
|
46
|
+
Connection identity is derived from NLB flow metadata; bidirectional
|
|
47
|
+
traffic flows over the Lambda response stream, reusing `AwsRuntime`.
|
|
48
|
+
CDK constructs for NLB + target group + ACM cert are added.
|
|
49
|
+
- **Transport-parametrized contract suite** (`@serverless-ircd/irc-test-support`):
|
|
50
|
+
every scenario now runs across a `Transport` dimension
|
|
51
|
+
(in-memory+WS, in-memory+TCP, …), with TCP-specific framing scenarios
|
|
52
|
+
(chunk boundaries, mixed `\r\n`/`\n` line endings, partial sends).
|
|
53
|
+
- **Docs**: `docs/Cloudflare-TCP-Deployment.md` and
|
|
54
|
+
`docs/AWS-TCP-Deployment.md` — end-to-end :6697 deployment guides
|
|
55
|
+
(prerequisites, mTLS trust-store setup, cost/ops caveats).
|
|
56
|
+
|
|
57
|
+
### Added — SASL `EXTERNAL` via mTLS (`@serverless-ircd/irc-core`, adapters)
|
|
58
|
+
|
|
59
|
+
- **mTLS support**: an `MtlsIdentityProvider` port in `irc-core` feeds
|
|
60
|
+
the verified client-certificate subject into `AccountStore`. Cloudflare
|
|
61
|
+
uses API Shield mTLS (uploaded CA pool); AWS uses API Gateway
|
|
62
|
+
custom-domain mTLS (PEM trust store, subject in the `$connect` event).
|
|
63
|
+
Identity is plumbed via a port — no cloud deps in `irc-core`.
|
|
64
|
+
- **`EXTERNAL` now authenticates** (was a stubbed `904 ERR_SASLFAIL` in
|
|
65
|
+
v0.2.0): `AUTHENTICATE EXTERNAL` against a bound provider succeeds with
|
|
66
|
+
`900 RPL_LOGGEDIN` / `903 RPL_SASLSUCCESS` when the cert maps to an
|
|
67
|
+
account.
|
|
68
|
+
- **mTLS-conditional advertisement**: the `sasl` cap value and
|
|
69
|
+
`908 ERR_SASLMECHS` are now driven by whether an mTLS provider is bound
|
|
70
|
+
— `PLAIN` only by default, `PLAIN,EXTERNAL` when one is. `AUTHENTICATE
|
|
71
|
+
EXTERNAL` without mTLS returns `908` (mechanism not available) instead
|
|
72
|
+
of the misleading `904`. Operators enable EXTERNAL by configuring edge
|
|
73
|
+
mTLS — no code change required.
|
|
74
|
+
|
|
75
|
+
### Added — Remaining IRC query verbs (`@serverless-ircd/irc-core`)
|
|
76
|
+
|
|
77
|
+
- **`WHOWAS`**: a nick-history store (port + in-memory reference impl)
|
|
78
|
+
records `(nick, connId, username, hostname, signoffTime)` on QUIT /
|
|
79
|
+
NICK-change and purges past a TTL. `WHOWAS <nick>{,<nick>} [<count>]`
|
|
80
|
+
queries it — `314 RPL_WHOWASUSER` per match, `369 RPL_ENDOFWHOWAS`
|
|
81
|
+
terminator, `406 ERR_WASNOSUCHNICK` when no match.
|
|
82
|
+
- **`VERSION`** (`351`), **`TIME`** (`391`, uses the injected `Clock`),
|
|
83
|
+
**`ADMIN`** (`256`/`257`/`258`), **`INFO`** (`371`/`374`),
|
|
84
|
+
**`USERHOST`** (`302`), **`ISON`** (`303`) — each a reducer + a route
|
|
85
|
+
case with spec-correct numerics. Completes the standard query-verb set.
|
|
86
|
+
|
|
87
|
+
### Added — Server identity from config (`@serverless-ircd/irc-core`)
|
|
88
|
+
|
|
89
|
+
- The `002` / `003` / `004` registration replies now reflect
|
|
90
|
+
`ServerConfig.serverVersion` / `createdAt` — the hardcoded
|
|
91
|
+
`'0.1.0'` / `'Phase 1'` placeholders are gone. A build step
|
|
92
|
+
(`scripts/generate-build-info.mjs`) bakes the package version and a
|
|
93
|
+
build timestamp into `RPL_CREATED` (`003`) when the config omits them.
|
|
94
|
+
|
|
95
|
+
### Added — Cloudflare D1-backed SASL account store (`@serverless-ircd/cf-adapter`, `@serverless-ircd/irc-core`)
|
|
96
|
+
|
|
97
|
+
- Brings the CF adapter to parity with the AWS `DynamoAccountStore`. A
|
|
98
|
+
persistent `AccountStore` pre-loads scrypt-hashed rows from a new
|
|
99
|
+
**D1** database (`ACCOUNTS_DB` binding) at `ConnectionDO`
|
|
100
|
+
construction.
|
|
101
|
+
- **Shared scrypt hashing**: `hashAccountCredential` /
|
|
102
|
+
`verifyHashedPassword` are extracted to `irc-core` so both adapters use
|
|
103
|
+
one implementation (never plaintext).
|
|
104
|
+
- **Table-then-env precedence**: when the D1 table has rows it is
|
|
105
|
+
authoritative; when empty or unreachable the adapter falls back to the
|
|
106
|
+
`SASL_ACCOUNTS` env-var seed, preserving current behavior.
|
|
107
|
+
- **`tools/seed-cf-accounts.ts`**: provisioning CLI that scrypt-hashes
|
|
108
|
+
`username:password` pairs into the D1 `accounts` table (re-run
|
|
109
|
+
overwrites the prior row).
|
|
110
|
+
|
|
111
|
+
### Added — AWS max-clients admission (`@serverless-ircd/aws-adapter`)
|
|
112
|
+
|
|
113
|
+
- `$connect` now enforces `serverConfig.maxClients` (was a reserved
|
|
114
|
+
no-op — `void params.serverConfig;`). Connections over the cap are
|
|
115
|
+
rejected at accept time, matching the Cloudflare admission gate.
|
|
116
|
+
|
|
117
|
+
### Changed
|
|
118
|
+
|
|
119
|
+
- **Toolchain**: bumped from Node ≥ 20 / pnpm 9 to **Node ≥ 24 / pnpm
|
|
120
|
+
11** (aligns the Lambda and Cloudflare Workers runtimes). Re-run
|
|
121
|
+
`corepack enable` to pick up the pinned pnpm.
|
|
122
|
+
- `@serverless-ircd/irc-core`: the request/response lookup `Effect`
|
|
123
|
+
variants (`LookupNick`, `GetConnectionInfo`, `GetChannelSnapshot`) are
|
|
124
|
+
removed from `effects.ts` and `dispatch` — they were dead scaffolding
|
|
125
|
+
with no producer or consumer.
|
|
126
|
+
- `@serverless-ircd/cf-adapter`: the dead channel-registration loop in
|
|
127
|
+
`ConnectionDO.webSocketMessage` and the reserved outbound-batching
|
|
128
|
+
field are removed (the latter was a never-wired optimization).
|
|
129
|
+
|
|
130
|
+
### ⚠️ Migration required
|
|
131
|
+
|
|
132
|
+
- **Cloudflare: new D1 binding for SASL accounts.** To persist SASL
|
|
133
|
+
accounts, create the D1 database and add the `ACCOUNTS_DB` binding
|
|
134
|
+
(default + staging) to `wrangler.toml`:
|
|
135
|
+
```bash
|
|
136
|
+
wrangler d1 create serverless-ircd-accounts
|
|
137
|
+
wrangler d1 execute serverless-ircd-accounts --command \
|
|
138
|
+
"CREATE TABLE IF NOT EXISTS accounts (account TEXT PRIMARY KEY, algorithm TEXT NOT NULL, salt TEXT NOT NULL, hash TEXT NOT NULL)"
|
|
139
|
+
```
|
|
140
|
+
**No action is required to keep working** — when the D1 table is empty
|
|
141
|
+
or unreachable the adapter falls back to the `SASL_ACCOUNTS` env-var
|
|
142
|
+
seed. There is **no Durable-Object persisted-state schema change**
|
|
143
|
+
(`PERSISTED_STATE_VERSION` stays `1`); code rollback across this
|
|
144
|
+
release is safe.
|
|
145
|
+
- **Local toolchain**: Node ≥ 24 / pnpm 11 is now required. Re-run
|
|
146
|
+
`corepack enable`.
|
|
147
|
+
|
|
148
|
+
### Known limitations
|
|
149
|
+
|
|
150
|
+
- The **CF TCP path requires Cloudflare Spectrum (Enterprise tier)** plus
|
|
151
|
+
a stateful Container origin; the **AWS TCP path** uses NLB + Lambda
|
|
152
|
+
streaming and is subject to Lambda idle-timeout / stream-duration
|
|
153
|
+
limits. The WebSocket path remains the zero-extra-deps default.
|
|
154
|
+
- **mTLS (for SASL `EXTERNAL`) requires a custom domain + uploaded
|
|
155
|
+
CA/trust-store** on both platforms and is not enabled by default.
|
|
156
|
+
- Oper-gated verbs (`KILL`, `REHASH`, `CONNECT`, `SQUIT`, `TRACE`,
|
|
157
|
+
`WALLOPS`, `SETNAME`, …) still return `421 ERR_UNKNOWNCOMMAND`.
|
|
158
|
+
- `serverName` still defaults to the `irc.example.com` placeholder when
|
|
159
|
+
an adapter config omits it (pending).
|
|
160
|
+
|
|
161
|
+
### Security
|
|
162
|
+
|
|
163
|
+
- SASL `EXTERNAL` no longer returns a misleading `904 ERR_SASLFAIL` when
|
|
164
|
+
mTLS isn't configured — it returns `908 ERR_SASLMECHS` and the
|
|
165
|
+
mechanism is not advertised until a trust store is bound. SASL
|
|
166
|
+
credentials remain scrypt-hashed only (never plaintext), now via a
|
|
167
|
+
single shared implementation across both adapters.
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
13
171
|
## [0.3.0] - 2026-07-25
|
|
14
172
|
|
|
15
173
|
### Added — Operator authentication (`@serverless-ircd/irc-core`)
|
|
@@ -378,31 +536,29 @@ manual per `docs/release.md` §8.3.
|
|
|
378
536
|
|
|
379
537
|
### Known limitations
|
|
380
538
|
|
|
381
|
-
- **No AWS adapter.**
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
the only deployable platform in 0.1.0.
|
|
539
|
+
- **No AWS adapter.** The CDK stack, APIGW WebSocket handlers, DynamoDB
|
|
540
|
+
transactions, EventBridge timers, deploy pipeline, and deployment doc
|
|
541
|
+
are pending. Cloudflare is the only deployable platform in 0.1.0.
|
|
385
542
|
- **No SASL.** `CAP sasl` is advertised in the capability list but
|
|
386
543
|
`AUTHENTICATE` is not wired into the dispatcher. Plain-text password
|
|
387
|
-
authentication via `PASS` is also not enforced
|
|
388
|
-
- **No flood control.** A token-bucket wrapper
|
|
389
|
-
|
|
544
|
+
authentication via `PASS` is also not enforced.
|
|
545
|
+
- **No flood control.** A token-bucket wrapper is pending. Misbehaving
|
|
546
|
+
clients can send unbounded commands.
|
|
390
547
|
- **No server-password enforcement, rate limits, cloaking, or oper
|
|
391
|
-
credentials
|
|
548
|
+
credentials.**
|
|
392
549
|
- **No config loader.** Server name, network name, MOTD, channel
|
|
393
|
-
prefixes, max clients, oper creds are hardcoded defaults
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
`[vars].MOTD_LINES`.
|
|
550
|
+
prefixes, max clients, oper creds are hardcoded defaults. The
|
|
551
|
+
`MOTD.txt` file at the repo root is informational only; the live MOTD
|
|
552
|
+
is compiled into the Worker from `[vars].MOTD_LINES`.
|
|
397
553
|
- **No CI coverage gate.** Coverage is computed and uploaded as an
|
|
398
|
-
artifact, but no threshold is enforced
|
|
554
|
+
artifact, but no threshold is enforced. Inspect
|
|
399
555
|
`packages/*/coverage/` before deploying.
|
|
400
556
|
- **No TLS / raw TCP transport.** v1 is WebSocket text frames only.
|
|
401
|
-
TLS-hardened and `irc+tls` transports are 0.x work
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
557
|
+
TLS-hardened and `irc+tls` transports are 0.x work. Stock TCP IRC
|
|
558
|
+
clients reach the server through the local `tcp-ws-forwarder` bridge.
|
|
559
|
+
- **No `chathistory` playback.** Chat-history playback is pending;
|
|
560
|
+
clients that request backlog on JOIN will see an empty batch or no
|
|
561
|
+
response.
|
|
406
562
|
|
|
407
563
|
### Security
|
|
408
564
|
|
package/README.md
CHANGED
|
@@ -4,22 +4,23 @@ A serverless IRC daemon where the IRC protocol logic lives in a pure,
|
|
|
4
4
|
platform-agnostic core, and two thin adapters run it on **Cloudflare Workers**
|
|
5
5
|
(Durable Objects) or **AWS** (API Gateway WebSockets + Lambda + DynamoDB).
|
|
6
6
|
|
|
7
|
-
One TypeScript codebase. Two serverless substrates.
|
|
7
|
+
One TypeScript codebase. Two serverless substrates.
|
|
8
8
|
|
|
9
|
-
> **Status:** **v0.
|
|
9
|
+
> **Status:** **v0.4.0 (preview).** The pure protocol core, the
|
|
10
10
|
> `IrcRuntime` port + in-memory runtime, a runnable local CLI server,
|
|
11
11
|
> the **Cloudflare Workers** adapter, and the **AWS** (API Gateway
|
|
12
12
|
> WebSocket + Lambda + DynamoDB + CDK) adapter are all functional and
|
|
13
|
-
> deployed to staging. v0.
|
|
14
|
-
>
|
|
15
|
-
>
|
|
16
|
-
>
|
|
17
|
-
>
|
|
18
|
-
>
|
|
19
|
-
>
|
|
20
|
-
>
|
|
21
|
-
>
|
|
22
|
-
>
|
|
13
|
+
> deployed to staging. v0.4.0 ships **dual transport**: both adapters
|
|
14
|
+
> now speak a real `irc+tls :6697` (TLS-over-TCP) surface for stock IRC
|
|
15
|
+
> clients — Cloudflare via Spectrum + a Container origin, AWS via a
|
|
16
|
+
> Network Load Balancer + Lambda streaming — alongside the WebSocket
|
|
17
|
+
> path. It also lands **SASL `EXTERNAL` via mTLS**, the remaining
|
|
18
|
+
> standard IRC verbs (`WHOWAS`, `VERSION`, `TIME`, `ADMIN`, `INFO`,
|
|
19
|
+
> `USERHOST`, `ISON`), a **Cloudflare D1-backed SASL account store**,
|
|
20
|
+
> config-driven server identity, and a **Node 24 / pnpm 11** toolchain.
|
|
21
|
+
> Remaining 0.x work: oper-gated verbs (`KILL`/`REHASH`/…), a
|
|
22
|
+
> required-`serverName` config gate, and load/compat testing. See
|
|
23
|
+
> `CHANGELOG.md` for the per-release manifests.
|
|
23
24
|
|
|
24
25
|
---
|
|
25
26
|
|
|
@@ -70,6 +71,16 @@ Hexagonal / ports-and-adapters. The core reasons about IRC; adapters move bytes.
|
|
|
70
71
|
`packages/in-memory-runtime` is the reference implementation of
|
|
71
72
|
`IrcRuntime`, used by integration tests and the local CLI server.
|
|
72
73
|
|
|
74
|
+
**Two transports, one core.** Both adapters accept WebSocket text frames
|
|
75
|
+
(the serverless default) **and** a raw `irc+tls :6697` (TLS-over-TCP)
|
|
76
|
+
surface for stock IRC clients. The TCP+TLS edge is platform-specific —
|
|
77
|
+
Cloudflare **Spectrum** terminates TLS and forwards plaintext TCP to a
|
|
78
|
+
stateful **Container** origin (`apps/cf-tcp-container`); AWS terminates
|
|
79
|
+
TLS at a **Network Load Balancer** and invokes a **Lambda streaming**
|
|
80
|
+
function. Both feed the same `ConnectionActor` through a `Transport`
|
|
81
|
+
seam (`WsTextFrameTransport` vs. `TcpByteStreamTransport`); the
|
|
82
|
+
parser/reducer/dispatch pipeline is identical.
|
|
83
|
+
|
|
73
84
|
### The key idea: pure reducers + location-of-authority
|
|
74
85
|
|
|
75
86
|
Each command handler is a pure function:
|
|
@@ -111,12 +122,14 @@ ServerlessIRCd/
|
|
|
111
122
|
│ └── aws-adapter/ Lambda + DynamoDB + AwsRuntime
|
|
112
123
|
├── apps/
|
|
113
124
|
│ ├── cf-worker/ worker entry, DO migrations, bindings
|
|
114
|
-
│ ├──
|
|
125
|
+
│ ├── cf-tcp-container/ Spectrum + Container origin for irc+tls :6697
|
|
126
|
+
│ ├── aws-stack/ CDK stack (APIGW WS + NLB + Lambda streaming + DynamoDB)
|
|
115
127
|
│ └── local-cli/ runnable WS + TCP server using in-memory-runtime
|
|
116
128
|
├── tools/
|
|
117
129
|
│ ├── tcp-ws-forwarder/ local TCP↔ws/wss bridge for stock IRC clients
|
|
118
130
|
│ ├── ci-hardening/ coverage-gate + mutation-config validators
|
|
119
|
-
│
|
|
131
|
+
│ ├── seed-aws-accounts.ts scrypt-hash SASL PLAIN accounts into DynamoDB
|
|
132
|
+
│ └── seed-cf-accounts.ts scrypt-hash SASL PLAIN accounts into Cloudflare D1
|
|
120
133
|
├── pnpm-workspace.yaml turbo.json tsconfig.base.json
|
|
121
134
|
└── README.md CHANGELOG.md
|
|
122
135
|
```
|
|
@@ -127,7 +140,7 @@ ServerlessIRCd/
|
|
|
127
140
|
|
|
128
141
|
| Concern | Choice |
|
|
129
142
|
|------------------|---------------------------------------------------|
|
|
130
|
-
| Runtime | Node ≥
|
|
143
|
+
| Runtime | Node ≥ 24, ES2022+ |
|
|
131
144
|
| Package mgr | pnpm workspaces |
|
|
132
145
|
| Build cache | turbo |
|
|
133
146
|
| Language | TypeScript (strict, `exactOptionalPropertyTypes`) |
|
|
@@ -141,9 +154,12 @@ ServerlessIRCd/
|
|
|
141
154
|
|
|
142
155
|
## Getting started
|
|
143
156
|
|
|
144
|
-
Requires Node ≥
|
|
157
|
+
Requires Node ≥ 24 and pnpm 11. Enable corepack so the `packageManager`
|
|
158
|
+
pin is resolved automatically:
|
|
145
159
|
|
|
146
160
|
```bash
|
|
161
|
+
corepack enable # lets the pinned pnpm@11 run on any Node ≥ 24
|
|
162
|
+
|
|
147
163
|
pnpm install # install workspace deps
|
|
148
164
|
|
|
149
165
|
pnpm build # build all packages (turbo)
|
|
@@ -322,10 +338,16 @@ cleanly. Per-release manifests live in `CHANGELOG.md`.
|
|
|
322
338
|
- **Phase 4** — AWS adapter (APIGW WS + Lambda + DynamoDB + CDK).
|
|
323
339
|
✅ landed in **v0.2.0** (staging auto-deploy via CI; prod deploy is manual).
|
|
324
340
|
- **Phase 5** — Observability, security hardening, config, CI gates.
|
|
325
|
-
✅ landed (logger port, server-password, cloaking,
|
|
326
|
-
coverage + mutation gates, OPER credential auth,
|
|
327
|
-
config loader
|
|
328
|
-
- **Phase 6** —
|
|
341
|
+
✅ landed across v0.2.0–v0.4.0 (logger port, server-password, cloaking,
|
|
342
|
+
admission limits, coverage + mutation gates, OPER credential auth, the
|
|
343
|
+
Cloudflare config loader, and AWS max-clients admission).
|
|
344
|
+
- **Phase 6** — TLS hardening & raw TCP transport (`irc+tls :6697`).
|
|
345
|
+
✅ landed in **v0.4.0**: generalized `ConnectionActor` transport seam,
|
|
346
|
+
Cloudflare Spectrum + Container origin, AWS NLB + Lambda streaming,
|
|
347
|
+
mTLS → SASL `EXTERNAL`, transport-parametrized contract suite, ADR-009.
|
|
348
|
+
- **Phase 7** — Load testing (10k concurrent connections per platform),
|
|
349
|
+
client compatibility sweep (WeeChat, HexChat, IRCCloud, TheLounge),
|
|
350
|
+
remaining ADRs.
|
|
329
351
|
|
|
330
352
|
---
|
|
331
353
|
|
|
@@ -333,25 +355,31 @@ cleanly. Per-release manifests live in `CHANGELOG.md`.
|
|
|
333
355
|
|
|
334
356
|
**Core (RFC 1459/2812 subset):** registration (`NICK`/`USER`/`CAP`/`PASS`),
|
|
335
357
|
`PING`/`PONG`, `QUIT`, `JOIN`, `PART`, `PRIVMSG`, `NOTICE`, `MODE` (user +
|
|
336
|
-
channel), `TOPIC`, `KICK`, `INVITE`, `NAMES`, `LIST`, `WHO`, `WHOIS`,
|
|
337
|
-
`AWAY`, `OPER` (credential auth → `o` user mode)
|
|
358
|
+
channel), `TOPIC`, `KICK`, `INVITE`, `NAMES`, `LIST`, `WHO`, `WHOIS`,
|
|
359
|
+
`WHOWAS`, `MOTD`, `AWAY`, `OPER` (credential auth → `o` user mode), plus
|
|
360
|
+
the query verbs `VERSION`, `TIME`, `ADMIN`, `INFO`, `USERHOST`, `ISON`.
|
|
361
|
+
(Oper-gated verbs — `KILL`/`REHASH`/`CONNECT`/`SQUIT`/`TRACE` — remain
|
|
362
|
+
deferred.)
|
|
338
363
|
|
|
339
364
|
**Channel modes:** `o v b i k l t n m s p`.
|
|
340
365
|
**User modes:** `i`, `o` (local only), `w`, `s`.
|
|
341
366
|
|
|
342
367
|
**IRCv3 extensions (negotiated via `CAP`):** `message-tags` (incl. the
|
|
343
368
|
`TAGMSG` command), `server-time`, `account-tag`, `echo-message`, `batch`,
|
|
344
|
-
`sasl` (`PLAIN`
|
|
369
|
+
`sasl` (`PLAIN` always; `EXTERNAL` via mTLS when a client-cert trust store
|
|
370
|
+
is bound),
|
|
345
371
|
`multi-prefix`, `away-notify`, `chghost`, `invite-notify`, `extended-join`,
|
|
346
372
|
`draft/chathistory`, `safelist`. Case-insensitive nick/channel comparison
|
|
347
373
|
uses **RFC 1459** case-mapping (advertised via `005 CASEMAPPING=rfc1459`).
|
|
348
374
|
|
|
349
375
|
**Transport:** deployed stacks (Cloudflare Workers, AWS API Gateway) speak
|
|
350
|
-
WebSocket text frames
|
|
351
|
-
`\r\n`-joined frames)
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
376
|
+
WebSocket text frames by default (one IRC message per frame, with tolerance
|
|
377
|
+
for `\r\n`-joined frames), and optionally expose a raw `irc+tls :6697`
|
|
378
|
+
(TLS-over-TCP) surface — Cloudflare via **Spectrum + Container**, AWS via a
|
|
379
|
+
**Network Load Balancer + Lambda streaming** function. The local CLI
|
|
380
|
+
additionally binds a plain RFC TCP listener for direct IRC-client access,
|
|
381
|
+
and the [`tcp-ws-forwarder`](#connecting-a-tcp-irc-client-to-a-deployed-stack-tcpws-forwarder)
|
|
382
|
+
bridges a stock TCP client to a deployed WebSocket endpoint.
|
|
355
383
|
|
|
356
384
|
---
|
|
357
385
|
|
|
@@ -359,8 +387,13 @@ WebSocket endpoint through the local
|
|
|
359
387
|
|
|
360
388
|
- `CHANGELOG.md` — per-release manifests (Keep a Changelog format), including
|
|
361
389
|
the v0.2.0 work (AWS adapter, SASL, flood control, security hardening, CI
|
|
362
|
-
gates)
|
|
363
|
-
ChannelRegistryDO, SASL account persistence).
|
|
390
|
+
gates), v0.3.0 (OPER, TAGMSG, RFC 1459 case-mapping, real MOTD,
|
|
391
|
+
ChannelRegistryDO, SASL account persistence), and v0.4.0 (dual transport
|
|
392
|
+
`irc+tls :6697`, SASL `EXTERNAL`/mTLS, WHOWAS + remaining verbs, D1 account
|
|
393
|
+
store, Node 24/pnpm 11).
|
|
394
|
+
- `docs/Cloudflare-TCP-Deployment.md` and `docs/AWS-TCP-Deployment.md` —
|
|
395
|
+
end-to-end guides for the `:6697` TCP+TLS variants (Spectrum/Container on
|
|
396
|
+
CF, NLB + Lambda streaming on AWS), including mTLS trust-store setup.
|
|
364
397
|
- `README.md` in each `packages/*` and `apps/*` — per-package notes (e.g.
|
|
365
398
|
`packages/aws-adapter/README.md` for the DynamoDB-Local test setup,
|
|
366
399
|
`apps/aws-stack/README.md` for CDK commands and localstack validation).
|
package/apps/aws-stack/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# `@serverless-ircd/aws-stack`
|
|
2
2
|
|
|
3
3
|
AWS CDK v2 stack that provisions the AWS substrate for ServerlessIRCd
|
|
4
|
-
(PLAN §6.2): an API Gateway v2 WebSocket API, a single Node
|
|
4
|
+
(PLAN §6.2): an API Gateway v2 WebSocket API, a single Node 24 Lambda wired
|
|
5
5
|
to the `$connect` / `$disconnect` / `$default` routes, five DynamoDB tables
|
|
6
6
|
(`Connections`, `ChannelMeta`, `ChannelMembers`, `Nicks`, `Accounts`), and the
|
|
7
7
|
least-privilege IAM glue to let the Lambda read/write the tables and post back
|
|
@@ -12,7 +12,7 @@ The Lambda handler is currently a stub (`{ statusCode: 200 }`); the real
|
|
|
12
12
|
|
|
13
13
|
## Prerequisites
|
|
14
14
|
|
|
15
|
-
- Node.js
|
|
15
|
+
- Node.js 24+
|
|
16
16
|
- pnpm (workspace root installs this package)
|
|
17
17
|
- An AWS account with credentials configured
|
|
18
18
|
(`aws configure`, `AWS_PROFILE`, or `SSO`)
|
|
@@ -38,11 +38,18 @@ const motdLines = Array.isArray(rawMotd)
|
|
|
38
38
|
? rawMotd.split('\n')
|
|
39
39
|
: undefined;
|
|
40
40
|
|
|
41
|
+
// TCP+TLS (irc+tls :6697) is opt-in: only provisioned when this context
|
|
42
|
+
// var is supplied. When omitted, only the wss (API Gateway WebSocket)
|
|
43
|
+
// path deploys (the default documented in docs/AWS-Deployment.md). See
|
|
44
|
+
// docs/AWS-TCP-Deployment.md.
|
|
45
|
+
const tcpTlsDomainName = app.node.tryGetContext('tcpTlsDomainName') as string | undefined;
|
|
46
|
+
|
|
41
47
|
const stackProps: IrcStackProps = {
|
|
42
48
|
environmentName,
|
|
43
49
|
...(serverName !== undefined ? { serverName } : {}),
|
|
44
50
|
...(networkName !== undefined ? { networkName } : {}),
|
|
45
51
|
...(motdLines !== undefined ? { motdLines } : {}),
|
|
52
|
+
...(tcpTlsDomainName !== undefined ? { tcpTlsDomainName } : {}),
|
|
46
53
|
...(account && region ? { env: { account, region } } : {}),
|
|
47
54
|
};
|
|
48
55
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@serverless-ircd/aws-stack",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"private": true,
|
|
5
5
|
"description": "AWS CDK v2 stack: API Gateway v2 WebSocket API, Lambda, DynamoDB tables, least-privilege IAM",
|
|
6
6
|
"license": "BSD-3-Clause",
|
|
@@ -19,8 +19,8 @@
|
|
|
19
19
|
"smoke:staging": "node scripts/smoke.mjs"
|
|
20
20
|
},
|
|
21
21
|
"devDependencies": {
|
|
22
|
-
"aws-cdk": "^2.
|
|
23
|
-
"aws-cdk-lib": "^2.
|
|
22
|
+
"aws-cdk": "^2.262.0",
|
|
23
|
+
"aws-cdk-lib": "^2.262.0",
|
|
24
24
|
"constructs": "^10.4.0",
|
|
25
25
|
"@types/node": "^26.1.1",
|
|
26
26
|
"@types/ws": "^8.5.13",
|
|
@@ -36,6 +36,6 @@
|
|
|
36
36
|
"@serverless-ircd/aws-adapter": "workspace:*"
|
|
37
37
|
},
|
|
38
38
|
"engines": {
|
|
39
|
-
"node": ">=
|
|
39
|
+
"node": ">=24"
|
|
40
40
|
}
|
|
41
41
|
}
|