serverless-ircd 0.8.0 → 0.10.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 +4 -0
- package/.github/workflows/deploy-aws.yml +156 -32
- package/.github/workflows/deploy-cf-tcp.yml +11 -9
- package/.github/workflows/deploy-cf.yml +14 -14
- package/CHANGELOG.md +550 -0
- package/README.md +275 -222
- package/apps/aws-stack/README.md +3 -5
- package/apps/aws-stack/bin/aws.ts +82 -9
- package/apps/aws-stack/cdk.json +0 -3
- package/apps/aws-stack/package.json +3 -4
- package/apps/aws-stack/src/aws-stack.ts +177 -52
- package/apps/aws-stack/src/static-site.ts +323 -0
- package/apps/aws-stack/tests/smoke-helpers.test.ts +1 -1
- package/apps/aws-stack/tests/stack.test.ts +267 -92
- package/apps/aws-stack/tests/static-site.test.ts +491 -0
- package/apps/aws-stack/tests/synth-no-bundle.test.ts +0 -1
- package/apps/cf-tcp-container/package.json +2 -3
- package/apps/cf-tcp-container/src/container-server.ts +33 -10
- package/apps/cf-tcp-container/tests/config-loader.test.ts +43 -0
- package/apps/cf-tcp-container/tests/container-server.test.ts +249 -1
- package/apps/cf-tcp-container/tests/persistence.test.ts +9 -0
- package/apps/cf-tcp-container/tests/tls-e2e.test.ts +24 -5
- package/apps/cf-tcp-container/wrangler.toml +1 -10
- package/apps/cf-worker/package.json +3 -4
- package/apps/cf-worker/wrangler.toml +12 -71
- package/apps/local-cli/package.json +1 -1
- package/apps/local-cli/src/server.ts +115 -48
- package/apps/local-cli/tests/config-resolution.test.ts +65 -0
- package/apps/local-cli/tests/motd-file-non-error.test.ts +29 -0
- package/apps/local-cli/tests/rehash.test.ts +147 -0
- package/apps/local-cli/tests/server-helpers.test.ts +63 -0
- package/apps/local-cli/tests/tcp.test.ts +89 -0
- package/apps/local-cli/tests/ws-subprotocol.test.ts +92 -0
- package/apps/web/landing/favicon.ico +0 -0
- package/apps/web/landing/index.html +227 -3
- package/apps/web/package.json +3 -2
- package/apps/web/scripts/build.mjs +91 -6
- package/apps/web/src/build-env.ts +125 -4
- package/apps/web/src/config-schema.ts +20 -6
- package/apps/web/src/render-docs.ts +292 -0
- package/apps/web/static/{config.staging.json → config.prod-aws.json} +3 -2
- package/apps/web/tests/build-env.test.ts +210 -9
- package/apps/web/tests/build-smoke.test.ts +33 -4
- package/apps/web/tests/config-schema.test.ts +149 -25
- package/apps/web/tests/landing-content.test.ts +103 -0
- package/apps/web/tests/render-docs.test.ts +198 -0
- package/docs/AWS-Adapter-Architecture.md +3 -2
- package/docs/AWS-Deployment.md +670 -96
- package/docs/AWS-TCP-Deployment.md +20 -45
- package/docs/Cloudflare-Deployment-Guide.md +87 -113
- package/docs/Cloudflare-TCP-Deployment.md +25 -49
- package/docs/Release-Process.md +27 -23
- package/docs/Services.md +102 -23
- package/docs/WebClientGuide.md +35 -26
- package/package.json +7 -10
- package/packages/aws-adapter/package.json +1 -1
- package/packages/aws-adapter/src/aws-runtime.ts +15 -1
- package/packages/aws-adapter/src/cdk-table-defs.ts +6 -11
- package/packages/aws-adapter/src/config-loader.ts +19 -2
- package/packages/aws-adapter/src/dynamo-services-store.ts +7 -0
- package/packages/aws-adapter/src/handlers/connect.ts +26 -0
- package/packages/aws-adapter/src/handlers/default.ts +190 -123
- package/packages/aws-adapter/src/handlers/index.ts +67 -23
- package/packages/aws-adapter/src/handlers/nlb-stream.ts +13 -8
- package/packages/aws-adapter/src/index.ts +5 -7
- package/packages/aws-adapter/src/origin-allowlist.ts +94 -0
- package/packages/aws-adapter/src/serialize.ts +15 -0
- package/packages/aws-adapter/src/tables.ts +2 -12
- package/packages/aws-adapter/tests/aws-harness.ts +0 -1
- package/packages/aws-adapter/tests/aws-runtime.test.ts +23 -1
- package/packages/aws-adapter/tests/config-loader.test.ts +66 -0
- package/packages/aws-adapter/tests/connect.test.ts +124 -1
- package/packages/aws-adapter/tests/connection-counter.test.ts +17 -0
- package/packages/aws-adapter/tests/default-occ.test.ts +219 -0
- package/packages/aws-adapter/tests/dynamo-services-store-unit.test.ts +11 -0
- package/packages/aws-adapter/tests/global-setup.ts +28 -1
- package/packages/aws-adapter/tests/gone-exception.test.ts +21 -2
- package/packages/aws-adapter/tests/handlers.test.ts +117 -11
- package/packages/aws-adapter/tests/migrate-accounts-to-services.test.ts +164 -0
- package/packages/aws-adapter/tests/nlb-stream.test.ts +29 -1
- package/packages/aws-adapter/tests/origin-allowlist.test.ts +110 -0
- package/packages/aws-adapter/tests/ping-checker.test.ts +0 -1
- package/packages/aws-adapter/tests/stats.test.ts +0 -3
- package/packages/aws-adapter/tests/sweeper.test.ts +20 -1
- package/packages/aws-adapter/tests/tables.test.ts +1 -8
- package/packages/aws-adapter/tests/transactions.test.ts +0 -1
- package/packages/cf-adapter/package.json +1 -5
- package/packages/cf-adapter/src/cf-runtime.ts +59 -8
- package/packages/cf-adapter/src/channel-do.ts +13 -3
- package/packages/cf-adapter/src/connection-do.ts +284 -115
- package/packages/cf-adapter/src/d1-services-store.ts +63 -26
- package/packages/cf-adapter/src/env.ts +11 -10
- package/packages/cf-adapter/src/index.ts +0 -6
- package/packages/cf-adapter/tests/cf-runtime.test.ts +101 -1
- package/packages/cf-adapter/tests/channel-do.test.ts +118 -1
- package/packages/cf-adapter/tests/connection-do-coverage.test.ts +460 -0
- package/packages/cf-adapter/tests/connection-do-pure.test.ts +222 -51
- package/packages/cf-adapter/tests/connection-do-sasl-d1.test.ts +62 -38
- package/packages/cf-adapter/tests/d1-services-store.test.ts +53 -2
- package/packages/cf-adapter/tests/serialize.test.ts +25 -0
- package/packages/in-memory-runtime/package.json +1 -1
- package/packages/irc-core/package.json +1 -1
- package/packages/irc-core/src/account-migration.ts +140 -0
- package/packages/irc-core/src/commands/account-auth.ts +60 -35
- package/packages/irc-core/src/commands/chanserv.ts +288 -4
- package/packages/irc-core/src/commands/hostserv.ts +38 -3
- package/packages/irc-core/src/commands/index.ts +1 -0
- package/packages/irc-core/src/commands/join.ts +41 -35
- package/packages/irc-core/src/commands/memoserv.ts +1 -1
- package/packages/irc-core/src/commands/nickserv.ts +138 -15
- package/packages/irc-core/src/commands/registration.ts +28 -17
- package/packages/irc-core/src/commands/sasl.ts +22 -31
- package/packages/irc-core/src/commands/service-aliases.ts +52 -0
- package/packages/irc-core/src/commands/topic.ts +23 -10
- package/packages/irc-core/src/config.ts +35 -9
- package/packages/irc-core/src/credential-hashing.ts +11 -54
- package/packages/irc-core/src/index.ts +1 -0
- package/packages/irc-core/src/ports.ts +159 -179
- package/packages/irc-core/src/state/channel.ts +17 -0
- package/packages/irc-core/src/types.ts +38 -10
- package/packages/irc-core/tests/account-migration.test.ts +133 -0
- package/packages/irc-core/tests/commands/chanserv.test.ts +668 -1
- package/packages/irc-core/tests/commands/hostserv.test.ts +71 -0
- package/packages/irc-core/tests/commands/join.test.ts +179 -0
- package/packages/irc-core/tests/commands/markread.test.ts +54 -0
- package/packages/irc-core/tests/commands/memoserv.test.ts +19 -0
- package/packages/irc-core/tests/commands/nickserv.test.ts +422 -3
- package/packages/irc-core/tests/commands/oper.test.ts +15 -0
- package/packages/irc-core/tests/commands/registration.test.ts +336 -108
- package/packages/irc-core/tests/commands/sasl.test.ts +194 -169
- package/packages/irc-core/tests/commands/service-aliases.test.ts +52 -0
- package/packages/irc-core/tests/commands/unified-account.test.ts +102 -84
- package/packages/irc-core/tests/credential-hashing.test.ts +0 -78
- package/packages/irc-core/tests/message-store.test.ts +5 -0
- package/packages/irc-core/tests/persistent-services-store.test.ts +71 -12
- package/packages/irc-core/tests/ports.test.ts +71 -0
- package/packages/irc-core/tests/services-store.test.ts +204 -0
- package/packages/irc-core/vitest.config.ts +6 -1
- package/packages/irc-server/package.json +1 -1
- package/packages/irc-server/src/actor.ts +80 -44
- package/packages/irc-server/tests/actor.test.ts +384 -50
- package/packages/irc-test-support/package.json +1 -1
- package/packages/irc-test-support/src/in-memory-harness.ts +8 -5
- package/packages/irc-test-support/src/scenarios.ts +21 -6
- package/packages/irc-test-support/tests/in-memory-harness.test.ts +19 -0
- package/packages/irc-test-support/vitest.config.ts +6 -1
- package/pnpm-workspace.yaml +1 -0
- package/scripts/__tests__/deploy-web-aws.test.ts +491 -0
- package/scripts/deploy-web-aws.mjs +290 -0
- package/scripts/package.json +23 -0
- package/scripts/tsconfig.test.json +12 -0
- package/scripts/vitest.config.ts +19 -0
- package/tools/ci-hardening/package.json +1 -1
- package/tools/ci-hardening/src/index.ts +2 -0
- package/tools/ci-hardening/src/validate.ts +57 -0
- package/tools/ci-hardening/tests/deploy-aws-oidc.test.ts +96 -0
- package/tools/ci-hardening/tests/validate.test.ts +42 -0
- package/tools/load-test/package.json +1 -1
- package/tools/load-test/src/client.ts +13 -13
- package/tools/load-test/tests/client.test.ts +258 -2
- package/tools/load-test/tests/config.test.ts +39 -0
- package/tools/load-test/tests/harness.test.ts +21 -0
- package/tools/load-test/tests/metrics.test.ts +7 -0
- package/tools/migrate-accounts-to-services.ts +270 -0
- package/tools/package.json +2 -1
- package/tools/seed-aws-accounts.ts +35 -10
- package/tools/seed-cf-accounts.ts +42 -9
- package/tools/tcp-ws-forwarder/package.json +1 -1
- package/tools/tcp-ws-forwarder/tests/close-error.test.ts +40 -0
- package/tools/tcp-ws-forwarder/tests/defensive-branches.test.ts +78 -0
- package/tools/tcp-ws-forwarder/tests/forwarder.test.ts +51 -0
- package/tools/tcp-ws-forwarder/tests/logger.test.ts +31 -1
- package/packages/aws-adapter/src/account-store.ts +0 -121
- package/packages/aws-adapter/src/dynamo-account-store.ts +0 -95
- package/packages/aws-adapter/tests/account-store-dynamo.test.ts +0 -223
- package/packages/aws-adapter/tests/account-store.test.ts +0 -276
- package/packages/cf-adapter/src/d1-account-store.ts +0 -198
- package/packages/cf-adapter/tests/d1-account-store.test.ts +0 -274
- package/packages/irc-core/tests/account-store.test.ts +0 -131
|
@@ -12,7 +12,7 @@ CDK stack and a deployment can enable either or both.
|
|
|
12
12
|
> This doc covers the *how*.
|
|
13
13
|
|
|
14
14
|
**Acceptance criterion (TICKET-058):** a new contributor can deploy
|
|
15
|
-
their own TCP+TLS
|
|
15
|
+
their own TCP+TLS instance following only this doc.
|
|
16
16
|
|
|
17
17
|
Cross-reference: `apps/aws-stack/src/aws-stack.ts` (CDK), the wss path
|
|
18
18
|
(`AWS-Deployment.md`), TICKET-054 (mTLS), ADR-006 (SASL scope).
|
|
@@ -102,7 +102,6 @@ The `IrcAwsStack` construct accepts an optional prop
|
|
|
102
102
|
|
|
103
103
|
```ts
|
|
104
104
|
export interface IrcStackProps extends StackProps {
|
|
105
|
-
readonly environmentName?: string;
|
|
106
105
|
readonly serverName?: string;
|
|
107
106
|
readonly networkName?: string;
|
|
108
107
|
readonly motdLines?: string[];
|
|
@@ -130,21 +129,20 @@ deploys — the existing pipeline stays green.
|
|
|
130
129
|
|
|
131
130
|
---
|
|
132
131
|
|
|
133
|
-
## 4. Deploy
|
|
132
|
+
## 4. Deploy (TCP+TLS)
|
|
134
133
|
|
|
135
134
|
```bash
|
|
136
135
|
# From the repo root:
|
|
137
|
-
pnpm deploy:aws
|
|
138
|
-
-c
|
|
139
|
-
-c tcpTlsDomainName=irc-staging.example.com
|
|
136
|
+
pnpm deploy:aws -- \
|
|
137
|
+
-c tcpTlsDomainName=irc.example.com
|
|
140
138
|
```
|
|
141
139
|
|
|
142
140
|
This is the same `cdk deploy --all` the wss path uses
|
|
143
|
-
(`apps/aws-stack/package.json` `deploy
|
|
141
|
+
(`apps/aws-stack/package.json` `deploy`), just with the extra
|
|
144
142
|
context var. The deploy will:
|
|
145
143
|
|
|
146
|
-
1. Create the ACM certificate for `irc
|
|
147
|
-
validation via Route
|
|
144
|
+
1. Create the ACM certificate for `irc.example.com` (DNS
|
|
145
|
+
validation via Route 53; if the hosted zone is not in this account,
|
|
148
146
|
validate out-of-band and import the cert ARN — see §9.2).
|
|
149
147
|
2. Provision `NlbVpc`, the internet-facing NLB, the `TLS` listener on
|
|
150
148
|
`:6697`, and the `IrcNlbHandler` Lambda target group.
|
|
@@ -165,15 +163,15 @@ unchanged** — enabling TCP does not disable wss.
|
|
|
165
163
|
The first deploy can take several minutes while ACM validates the
|
|
166
164
|
certificate. `cdk deploy` waits on the certificate resource; do not
|
|
167
165
|
interrupt it. If validation times out, confirm the hosted zone for the
|
|
168
|
-
domain is in this account and Route
|
|
166
|
+
domain is in this account and Route 53 can write the `_acme-challenge`
|
|
169
167
|
CNAME.
|
|
170
168
|
|
|
171
169
|
### 4.2 Point a DNS record at the NLB (recommended)
|
|
172
170
|
|
|
173
171
|
The NLB prints a long `.elb.amazonaws.com` DNS name. For a stable,
|
|
174
|
-
owned hostname, create an **alias A record** (Route
|
|
175
|
-
pointing `irc
|
|
176
|
-
connect to `irc
|
|
172
|
+
owned hostname, create an **alias A record** (Route 53) or a CNAME
|
|
173
|
+
pointing `irc.example.com` → the NLB DNS name. Clients then
|
|
174
|
+
connect to `irc.example.com:6697`.
|
|
177
175
|
|
|
178
176
|
(You can connect directly to the raw NLB DNS, but the cert is issued for
|
|
179
177
|
your domain, so TLS SNI/hostname verification wants the owned name.)
|
|
@@ -182,28 +180,12 @@ your domain, so TLS SNI/hostname verification wants the owned name.)
|
|
|
182
180
|
|
|
183
181
|
```bash
|
|
184
182
|
printf 'NICK smoke\r\nUSER smoke 0 * :Smoke\r\nQUIT :smoke\r\n' | \
|
|
185
|
-
timeout 10 openssl s_client -connect irc
|
|
183
|
+
timeout 10 openssl s_client -connect irc.example.com:6697 -quiet | \
|
|
186
184
|
grep -q '001' && echo "SMOKE PASS" || echo "SMOKE FAIL"
|
|
187
185
|
```
|
|
188
186
|
|
|
189
187
|
---
|
|
190
188
|
|
|
191
|
-
## 5. Deploy production
|
|
192
|
-
|
|
193
|
-
```bash
|
|
194
|
-
pnpm deploy:aws:prod -- \
|
|
195
|
-
-c environmentName=production \
|
|
196
|
-
-c tcpTlsDomainName=irc.example.com
|
|
197
|
-
```
|
|
198
|
-
|
|
199
|
-
Production deploys are manual. The staging CI workflow
|
|
200
|
-
(`deploy-aws.yml`) deploys only the wss path (`-c environmentName=staging`
|
|
201
|
-
without `tcpTlsDomainName`); there is **no auto-deploy for the TCP path
|
|
202
|
-
yet** — add a `deploy-aws-tcp.yml` workflow (mirroring `deploy-cf-tcp.yml`)
|
|
203
|
-
as a follow-up when the TCP path is ready for continuous staging.
|
|
204
|
-
|
|
205
|
-
---
|
|
206
|
-
|
|
207
189
|
## 6. Operational model & limits
|
|
208
190
|
|
|
209
191
|
The NLB + Lambda streaming model has hard platform limits the wss path
|
|
@@ -240,17 +222,16 @@ TCP-specific ones:
|
|
|
240
222
|
| Knob (context var / prop) | Purpose | Default when omitted |
|
|
241
223
|
|-------------------------------|--------------------------------------------------|----------------------------|
|
|
242
224
|
| `tcpTlsDomainName` | Domain for the ACM cert + NLB TLS listener. | *(TCP path not provisioned)* |
|
|
243
|
-
| `environmentName` | Env prefix for table names + stack id. | `staging` |
|
|
244
225
|
|
|
245
226
|
The NLB handler Lambda inherits the **same** identity/table knobs as the
|
|
246
|
-
wss handler (`serverName`, `networkName`, `motd
|
|
247
|
-
|
|
227
|
+
wss handler (`serverName`, `networkName`, `motd`), injected in
|
|
228
|
+
`aws-stack.ts`:
|
|
248
229
|
|
|
249
230
|
- `SERVER_NAME`, `NETWORK_NAME`, `MOTD` (read by the shared
|
|
250
231
|
`config-loader.ts`).
|
|
251
232
|
- `MANAGEMENT_URL` — the wss stage's callback URL, so cross-connection
|
|
252
233
|
fanout reaches recipients on either transport.
|
|
253
|
-
- `<TABLE>_TABLE` for each of the five tables (
|
|
234
|
+
- `<TABLE>_TABLE` for each of the five tables (bare logical ids).
|
|
254
235
|
|
|
255
236
|
The Lambda handler entry is the same file
|
|
256
237
|
(`packages/aws-adapter/src/handlers/index.ts`); esbuild tree-shakes to
|
|
@@ -372,25 +353,19 @@ RFC-compliant clients that need it.
|
|
|
372
353
|
## 11. Quick reference
|
|
373
354
|
|
|
374
355
|
```bash
|
|
375
|
-
#
|
|
376
|
-
pnpm deploy:aws
|
|
377
|
-
-c
|
|
378
|
-
-c tcpTlsDomainName=irc-staging.example.com
|
|
356
|
+
# Deploy (TCP+TLS added alongside wss)
|
|
357
|
+
pnpm deploy:aws -- \
|
|
358
|
+
-c tcpTlsDomainName=irc.example.com
|
|
379
359
|
|
|
380
360
|
# Read the TCP endpoint from stack outputs
|
|
381
361
|
aws cloudformation describe-stacks \
|
|
382
|
-
--stack-name IrcAwsStack
|
|
362
|
+
--stack-name IrcAwsStack \
|
|
383
363
|
--query 'Stacks[0].Outputs[?OutputKey==`TcpConnectUrl`].OutputValue' \
|
|
384
364
|
--output text
|
|
385
365
|
|
|
386
366
|
# Smoke over TLS
|
|
387
367
|
printf 'NICK smoke\r\nUSER smoke 0 * :Smoke\r\nQUIT :smoke\r\n' | \
|
|
388
|
-
openssl s_client -connect irc
|
|
389
|
-
|
|
390
|
-
# Production (manual)
|
|
391
|
-
pnpm deploy:aws:prod -- \
|
|
392
|
-
-c environmentName=production \
|
|
393
|
-
-c tcpTlsDomainName=irc.example.com
|
|
368
|
+
openssl s_client -connect irc.example.com:6697 -quiet | grep '001'
|
|
394
369
|
|
|
395
370
|
# Tests (synth-time assertions for the NLB path)
|
|
396
371
|
pnpm --filter @serverless-ircd/aws-stack test
|
|
@@ -2,15 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
End-to-end guide for deploying ServerlessIRCd to Cloudflare Workers
|
|
4
4
|
(Phase 3 of `PLAN.md`). Covers prerequisites, first-time account setup,
|
|
5
|
-
local development,
|
|
6
|
-
|
|
5
|
+
local development, deploy, configuration, secrets, sharding, CI/CD,
|
|
6
|
+
cost, and troubleshooting.
|
|
7
7
|
|
|
8
8
|
Cross-reference: `PLAN.md` §6.1 (CF mapping), `apps/cf-worker/wrangler.toml`,
|
|
9
9
|
`packages/cf-adapter/`, `.github/workflows/deploy-cf.yml`. For the AWS
|
|
10
|
-
equivalent, see `docs/
|
|
10
|
+
equivalent, see `docs/AWS-Deployment.md`.
|
|
11
11
|
|
|
12
12
|
**Acceptance criterion (TICKET-038):** a new contributor can deploy their
|
|
13
|
-
own
|
|
13
|
+
own instance following only this doc.
|
|
14
14
|
|
|
15
15
|
---
|
|
16
16
|
|
|
@@ -52,8 +52,10 @@ connection's `ConnectionDO`. All IRC protocol logic lives in the shared
|
|
|
52
52
|
`irc-core` reducers, run by `ConnectionActor` inside the DO. No state is
|
|
53
53
|
held in the Worker process itself.
|
|
54
54
|
|
|
55
|
-
|
|
56
|
-
|
|
55
|
+
There is a single deploy target — the staging/prod split was collapsed.
|
|
56
|
+
The same `wrangler.toml` ships to whichever Cloudflare account the
|
|
57
|
+
deploy credentials target; staging vs production isolation is by
|
|
58
|
+
account, not by a `[env.staging]` block.
|
|
57
59
|
|
|
58
60
|
---
|
|
59
61
|
|
|
@@ -63,15 +65,15 @@ is the `--env` flag and the `[env.staging]` block in `wrangler.toml`.
|
|
|
63
65
|
|-----------------------|--------------------------------------------------------|
|
|
64
66
|
| Node.js | ≥ 20 (matches CI; `engines.node` in root `package.json`)|
|
|
65
67
|
| pnpm | 9.x (`packageManager: pnpm@9.15.9` in root `package.json`)|
|
|
66
|
-
| Cloudflare account | Free tier is enough
|
|
67
|
-
| | (USD $5/mo) is recommended for
|
|
68
|
+
| Cloudflare account | Free tier is enough to bring up the Worker. Workers Paid |
|
|
69
|
+
| | plan (USD $5/mo) is recommended for real traffic — see §10.|
|
|
68
70
|
| `wrangler` CLI | Comes from `apps/cf-worker/devDependencies`; no global install needed. |
|
|
69
|
-
| Git checkout | Clean working tree on `main` for
|
|
71
|
+
| Git checkout | Clean working tree on `main` for deploys. |
|
|
70
72
|
|
|
71
|
-
A **Workers Paid plan** is not strictly required
|
|
72
|
-
Durable Objects only run on the Paid plan in any meaningful
|
|
73
|
-
scenario. The free tier caps DO requests and disables
|
|
74
|
-
budget headroom. See §10 (Cost).
|
|
73
|
+
A **Workers Paid plan** is not strictly required to bring the Worker
|
|
74
|
+
up, but Durable Objects only run on the Paid plan in any meaningful
|
|
75
|
+
production scenario. The free tier caps DO requests and disables
|
|
76
|
+
hibernation budget headroom. See §10 (Cost).
|
|
75
77
|
|
|
76
78
|
Confirm the local environment:
|
|
77
79
|
|
|
@@ -136,9 +138,8 @@ export CLOUDFLARE_ACCOUNT_ID=...
|
|
|
136
138
|
```
|
|
137
139
|
|
|
138
140
|
When `CLOUDFLARE_API_TOKEN` is set in the environment, `wrangler` uses
|
|
139
|
-
it directly and skips the OAuth store. The deploy
|
|
140
|
-
`apps/cf-worker/package.json` (`deploy
|
|
141
|
-
both.
|
|
141
|
+
it directly and skips the OAuth store. The deploy command in
|
|
142
|
+
`apps/cf-worker/package.json` (`deploy`) honors both.
|
|
142
143
|
|
|
143
144
|
---
|
|
144
145
|
|
|
@@ -172,7 +173,7 @@ Expected output (success):
|
|
|
172
173
|
The smoke script (`scripts/smoke.mjs`) replays
|
|
173
174
|
CONNECT → NICK/USER → JOIN #smoke → PRIVMSG → QUIT and asserts the
|
|
174
175
|
server emits `001`, `376`, `353`, `366`, and closes the socket. It is
|
|
175
|
-
the exact same script CI runs against the deployed
|
|
176
|
+
the exact same script CI runs against the deployed URL.
|
|
176
177
|
|
|
177
178
|
The unit + integration suites live in `packages/cf-adapter/tests/` and
|
|
178
179
|
`apps/cf-worker/tests/`; both run under `@cloudflare/vitest-pool-workers`
|
|
@@ -185,29 +186,29 @@ pnpm --filter @serverless-ircd/cf-worker test
|
|
|
185
186
|
|
|
186
187
|
---
|
|
187
188
|
|
|
188
|
-
## 5. Deploy
|
|
189
|
+
## 5. Deploy
|
|
189
190
|
|
|
190
|
-
|
|
191
|
-
also deploy
|
|
191
|
+
The deploy is `workflow_dispatch`-only (a maintainer triggers it by
|
|
192
|
+
hand); you can also deploy manually from a clean checkout.
|
|
192
193
|
|
|
193
194
|
### 5.1 Deploy from your machine
|
|
194
195
|
|
|
195
196
|
```bash
|
|
196
197
|
# From the repo root:
|
|
197
|
-
pnpm deploy:cf
|
|
198
|
+
pnpm deploy:cf
|
|
198
199
|
# Equivalent to:
|
|
199
|
-
# pnpm --filter @serverless-ircd/cf-worker deploy
|
|
200
|
-
# → wrangler deploy
|
|
200
|
+
# pnpm --filter @serverless-ircd/cf-worker run deploy
|
|
201
|
+
# → wrangler deploy
|
|
201
202
|
```
|
|
202
203
|
|
|
203
204
|
The first deploy of a given account will:
|
|
204
205
|
|
|
205
|
-
1. Create the Worker `serverless-ircd
|
|
206
|
-
2. Apply the `[[
|
|
207
|
-
`
|
|
208
|
-
provisions the
|
|
206
|
+
1. Create the Worker `serverless-ircd`.
|
|
207
|
+
2. Apply the `[[migrations]]` block (`tag = "v1"`,
|
|
208
|
+
`new_sqlite_classes = [ConnectionDO, RegistryDO, ChannelDO,
|
|
209
|
+
ChannelRegistryDO]`). This is what provisions the DO namespaces.
|
|
209
210
|
3. Print the deployed URL, e.g.
|
|
210
|
-
`https://serverless-ircd
|
|
211
|
+
`https://serverless-ircd.example.workers.dev`.
|
|
211
212
|
|
|
212
213
|
If you see `Migration tag has already been applied`, the namespaces
|
|
213
214
|
already exist; subsequent deploys just update the Worker code.
|
|
@@ -216,7 +217,7 @@ already exist; subsequent deploys just update the Worker code.
|
|
|
216
217
|
|
|
217
218
|
```bash
|
|
218
219
|
node apps/cf-worker/scripts/smoke.mjs \
|
|
219
|
-
--url wss://serverless-ircd
|
|
220
|
+
--url wss://serverless-ircd.example.workers.dev
|
|
220
221
|
```
|
|
221
222
|
|
|
222
223
|
The same JSON `level: "info"` line on stdout means the full
|
|
@@ -228,7 +229,7 @@ Point any RFC-compliant WebSocket-aware IRC client at the deployed URL.
|
|
|
228
229
|
For WeeChat:
|
|
229
230
|
|
|
230
231
|
```
|
|
231
|
-
/server add ircd serverless-ircd
|
|
232
|
+
/server add ircd serverless-ircd.example.workers.dev/443
|
|
232
233
|
/set irc.server.ircd.ssl on
|
|
233
234
|
/connect ircd
|
|
234
235
|
/join #test
|
|
@@ -241,18 +242,14 @@ section.
|
|
|
241
242
|
|
|
242
243
|
---
|
|
243
244
|
|
|
244
|
-
## 6.
|
|
245
|
+
## 6. Production hardening
|
|
245
246
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
247
|
+
There is a single deploy target per platform (`pnpm deploy:cf`). The
|
|
248
|
+
staging/prod split was collapsed — there is no `[env.staging]` block
|
|
249
|
+
and no `--env` flag. The Worker is always named `serverless-ircd`.
|
|
249
250
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
pnpm deploy:cf:prod
|
|
253
|
-
```
|
|
254
|
-
|
|
255
|
-
Before your first production deploy, edit `apps/cf-worker/wrangler.toml`:
|
|
251
|
+
Before your first deploy against a real account, edit
|
|
252
|
+
`apps/cf-worker/wrangler.toml`:
|
|
256
253
|
|
|
257
254
|
1. Set `[vars].SERVER_NAME` to the public hostname clients should see
|
|
258
255
|
in numerics (`001`, `005`, etc.) — e.g. `irc.your-domain.com`.
|
|
@@ -263,29 +260,27 @@ Before your first production deploy, edit `apps/cf-worker/wrangler.toml`:
|
|
|
263
260
|
3. Set `[vars].MOTD_LINES` to your message-of-the-day (newline-delimited).
|
|
264
261
|
4. (Optional) Add a custom-domain Route under `[[routes]]` — see §8.4.
|
|
265
262
|
|
|
266
|
-
**First-time
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
§9.2).
|
|
263
|
+
**First-time migration:** the `[[migrations]]` block applies on the
|
|
264
|
+
first deploy and creates the DO classes. This is one-way: once a DO
|
|
265
|
+
namespace has data, you cannot rename or delete a class without an
|
|
266
|
+
explicit migration entry (see §9.2).
|
|
271
267
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
`main`.
|
|
268
|
+
Staging vs production isolation is by **Cloudflare account** — point a
|
|
269
|
+
separate account's `CLOUDFLARE_API_TOKEN` at the deploy to ship to a
|
|
270
|
+
different Worker namespace.
|
|
276
271
|
|
|
277
272
|
---
|
|
278
273
|
|
|
279
274
|
## 7. Configuration reference
|
|
280
275
|
|
|
281
276
|
All deployment knobs live in `apps/cf-worker/wrangler.toml`. The file
|
|
282
|
-
is the single source of truth for
|
|
277
|
+
is the single source of truth for the Worker.
|
|
283
278
|
|
|
284
279
|
### 7.1 Top-level / `[vars]`
|
|
285
280
|
|
|
286
281
|
| Var | Purpose | Default |
|
|
287
282
|
|-----------------|----------------------------------------------------|--------------------------------------|
|
|
288
|
-
| `name` | Worker name.
|
|
283
|
+
| `name` | Worker name. | `serverless-ircd` |
|
|
289
284
|
| `main` | Worker entry. | `src/worker.ts` |
|
|
290
285
|
| `compatibility_date` | Pins Workers runtime behavior. | `2024-11-01` |
|
|
291
286
|
| `compatibility_flags` | `nodejs_compat` enables Node-style APIs. | `["nodejs_compat"]` |
|
|
@@ -298,23 +293,7 @@ These are read by `ConnectionDO` via `Env` (see
|
|
|
298
293
|
`connection-do.ts:337`). They are **not** secrets — they ship in the
|
|
299
294
|
bundle and are visible in the dashboard.
|
|
300
295
|
|
|
301
|
-
### 7.2
|
|
302
|
-
|
|
303
|
-
The staging block overrides `name` and `[vars]` only. The DO bindings
|
|
304
|
-
and migrations must be redeclared per-environment (wrangler requires
|
|
305
|
-
explicit per-env blocks — they do not inherit):
|
|
306
|
-
|
|
307
|
-
```toml
|
|
308
|
-
[env.staging]
|
|
309
|
-
name = "serverless-ircd-staging"
|
|
310
|
-
|
|
311
|
-
[env.staging.vars]
|
|
312
|
-
SERVER_NAME = "irc-staging.example.com"
|
|
313
|
-
NETWORK_NAME = "ServerlessIRCd (staging)"
|
|
314
|
-
MOTD_LINES = "..."
|
|
315
|
-
```
|
|
316
|
-
|
|
317
|
-
### 7.3 Durable Object bindings
|
|
296
|
+
### 7.2 Durable Object bindings
|
|
318
297
|
|
|
319
298
|
Three DO classes are exported from `src/worker.ts` (re-exported from
|
|
320
299
|
`@serverless-ircd/cf-adapter`) and bound in `wrangler.toml`:
|
|
@@ -328,12 +307,12 @@ Three DO classes are exported from `src/worker.ts` (re-exported from
|
|
|
328
307
|
The class names in `wrangler.toml`'s `class_name` field MUST match the
|
|
329
308
|
re-exports at the top of `apps/cf-worker/src/worker.ts:29`.
|
|
330
309
|
|
|
331
|
-
### 7.
|
|
310
|
+
### 7.3 Migrations
|
|
332
311
|
|
|
333
312
|
```toml
|
|
334
313
|
[[migrations]]
|
|
335
314
|
tag = "v1"
|
|
336
|
-
|
|
315
|
+
new_sqlite_classes = ["ConnectionDO", "RegistryDO", "ChannelDO", "ChannelRegistryDO"]
|
|
337
316
|
```
|
|
338
317
|
|
|
339
318
|
`tag` is the migration id (string, monotonically tracked by wrangler).
|
|
@@ -342,10 +321,10 @@ new_classes = ["ConnectionDO", "RegistryDO", "ChannelDO"]
|
|
|
342
321
|
block with `tag = "v2"` (etc.) and a `renamed_classes` or `deleted_classes`
|
|
343
322
|
entry. See <https://developers.cloudflare.com/durable-objects/reference/durable-objects-migrations/>.
|
|
344
323
|
|
|
345
|
-
|
|
346
|
-
|
|
324
|
+
There is a single migration list — the `[env.staging]` block was
|
|
325
|
+
removed when staging/prod collapsed into one target.
|
|
347
326
|
|
|
348
|
-
### 7.
|
|
327
|
+
### 7.4 Custom domain (optional)
|
|
349
328
|
|
|
350
329
|
To serve the Worker on `irc.example.com` instead of the workers.dev
|
|
351
330
|
subdomain, add a route and bind a Cloudflare-managed DNS record:
|
|
@@ -357,9 +336,9 @@ zone_name = "example.com"
|
|
|
357
336
|
custom_domain = false # true if you'd rather use a Worker Custom Domain
|
|
358
337
|
```
|
|
359
338
|
|
|
360
|
-
Custom domains are optional for
|
|
361
|
-
(many IRC clients expect a stable, owned hostname). DNS
|
|
362
|
-
managed separately in the dashboard.
|
|
339
|
+
Custom domains are optional for a first deploy and recommended for
|
|
340
|
+
real traffic (many IRC clients expect a stable, owned hostname). DNS
|
|
341
|
+
records are managed separately in the dashboard.
|
|
363
342
|
|
|
364
343
|
---
|
|
365
344
|
|
|
@@ -372,7 +351,7 @@ disabled (the default). Configure it as a wrangler secret, never a
|
|
|
372
351
|
plaintext `[vars]` entry:
|
|
373
352
|
|
|
374
353
|
```bash
|
|
375
|
-
wrangler secret put SERVER_PASSWORD
|
|
354
|
+
wrangler secret put SERVER_PASSWORD
|
|
376
355
|
# → prompts for the value; stores it in the Workers secret store,
|
|
377
356
|
# NOT in wrangler.toml or the repo.
|
|
378
357
|
```
|
|
@@ -463,8 +442,7 @@ node --import tsx tools/seed-cf-accounts.ts \
|
|
|
463
442
|
--accounts alice:change-me bob:also-change-me
|
|
464
443
|
```
|
|
465
444
|
|
|
466
|
-
|
|
467
|
-
seed CLI hashes each password locally and executes the `INSERT OR REPLACE`
|
|
445
|
+
The seed CLI hashes each password locally and executes the `INSERT OR REPLACE`
|
|
468
446
|
via `wrangler d1 execute`.
|
|
469
447
|
|
|
470
448
|
> The `SASL_ACCOUNTS` env var remains the quick-start path (no D1 needed):
|
|
@@ -548,9 +526,9 @@ the public list price as of 2024-11; verify current pricing at
|
|
|
548
526
|
|
|
549
527
|
Practical numbers:
|
|
550
528
|
|
|
551
|
-
- **Workers Free plan**: sufficient to bring up
|
|
529
|
+
- **Workers Free plan**: sufficient to bring up the Worker, exercise the
|
|
552
530
|
smoke e2e, and validate a handful of concurrent connections. Not
|
|
553
|
-
suitable for
|
|
531
|
+
suitable for sustained traffic (request caps, no reserved DO
|
|
554
532
|
compute).
|
|
555
533
|
- **Workers Paid plan** (USD $5/mo base + usage): enough headroom for a
|
|
556
534
|
small production network. The dominant cost driver at scale is
|
|
@@ -572,10 +550,10 @@ mitigations (batched fanout, per-channel send-list cache).
|
|
|
572
550
|
|
|
573
551
|
## 11. CI/CD
|
|
574
552
|
|
|
575
|
-
The GitHub Actions workflow at `.github/workflows/deploy-cf.yml`
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
553
|
+
The GitHub Actions workflow at `.github/workflows/deploy-cf.yml` is
|
|
554
|
+
`workflow_dispatch`-only (a maintainer triggers it by hand); there is
|
|
555
|
+
no automatic push-to-main deploy. It deploys the single Worker target
|
|
556
|
+
and replays the smoke e2e.
|
|
579
557
|
|
|
580
558
|
Steps performed by the workflow (in order):
|
|
581
559
|
|
|
@@ -584,13 +562,13 @@ Steps performed by the workflow (in order):
|
|
|
584
562
|
3. `pnpm install --frozen-lockfile`.
|
|
585
563
|
4. `pnpm build` — builds all workspace packages.
|
|
586
564
|
5. `pnpm typecheck` and `pnpm test` — gate the deploy.
|
|
587
|
-
6. `pnpm deploy:cf
|
|
565
|
+
6. `pnpm deploy:cf` — `wrangler deploy`.
|
|
588
566
|
7. Resolve the smoke URL from the `CF_SMOKE_URL` repo variable. If
|
|
589
567
|
unset, the smoke step is skipped with a warning.
|
|
590
568
|
8. Run `node scripts/smoke.mjs --url "$SMOKE_URL"`. Failure fails the
|
|
591
569
|
build.
|
|
592
570
|
|
|
593
|
-
Concurrency is serialized via `concurrency.group: cf-
|
|
571
|
+
Concurrency is serialized via `concurrency.group: cf-deploy` so two
|
|
594
572
|
deploys cannot race the same DO namespace.
|
|
595
573
|
|
|
596
574
|
Required repo configuration (under Settings → Secrets and variables →
|
|
@@ -599,12 +577,12 @@ Actions):
|
|
|
599
577
|
- **Secret `CLOUDFLARE_API_TOKEN`** — required.
|
|
600
578
|
- **Secret `CLOUDFLARE_ACCOUNT_ID`** — required if the token's account
|
|
601
579
|
context is ambiguous.
|
|
602
|
-
- **Variable `CF_SMOKE_URL`** — set to the
|
|
580
|
+
- **Variable `CF_SMOKE_URL`** — set to the Worker's `wss://`
|
|
603
581
|
URL. Without it, the smoke step silently no-ops.
|
|
604
582
|
|
|
605
|
-
There is
|
|
606
|
-
|
|
607
|
-
|
|
583
|
+
There is a single deploy target — the staging/prod split was collapsed,
|
|
584
|
+
so the same workflow + account ships to whichever Worker namespace the
|
|
585
|
+
credentials target.
|
|
608
586
|
|
|
609
587
|
---
|
|
610
588
|
|
|
@@ -619,10 +597,10 @@ the `[[migrations]]` block, wrangler refuses to proceed.
|
|
|
619
597
|
- If you intentionally changed the DO schema, append a new
|
|
620
598
|
`[[migrations]]` block with `tag = "v2"` (and `renamed_classes` /
|
|
621
599
|
`deleted_classes` as needed). Never edit an already-applied `tag`.
|
|
622
|
-
- If the
|
|
600
|
+
- If the namespace has stale state from an aborted experiment,
|
|
623
601
|
you can destroy and recreate it from the dashboard (Workers & Pages →
|
|
624
|
-
Durable Objects → namespaces). **
|
|
625
|
-
deleted** — that data is gone permanently.
|
|
602
|
+
Durable Objects → namespaces). **Namespaces carrying real traffic must
|
|
603
|
+
never be deleted** — that data is gone permanently.
|
|
626
604
|
|
|
627
605
|
### 12.2 `Cannot find module '@serverless-ircd/cf-adapter'`
|
|
628
606
|
|
|
@@ -636,10 +614,10 @@ The connection upgrade succeeded but registration didn't complete.
|
|
|
636
614
|
Common causes:
|
|
637
615
|
|
|
638
616
|
- The deployed Worker is reachable but the DO threw on the first frame.
|
|
639
|
-
Tail the logs: `wrangler tail
|
|
617
|
+
Tail the logs: `wrangler tail` and reproduce.
|
|
640
618
|
- The `MOTD_LINES` or `SERVER_NAME` var was deleted — `ConnectionDO`'s
|
|
641
619
|
`serverConfig()` falls back to defaults, but a malformed value can
|
|
642
|
-
break parsing. Check the `[
|
|
620
|
+
break parsing. Check the `[vars]` block.
|
|
643
621
|
- Client connected over `ws://` to a Worker that requires `wss://`.
|
|
644
622
|
Use the `wss://` URL the deploy step printed.
|
|
645
623
|
|
|
@@ -649,8 +627,8 @@ The DO alarm fired but the handler threw. The most likely cause is a
|
|
|
649
627
|
stale persisted-state version after a code change; the serializer in
|
|
650
628
|
`packages/cf-adapter/src/serialize.ts` carries `PERSISTED_STATE_VERSION`
|
|
651
629
|
and will reject incompatible blobs. If this happens after an upgrade,
|
|
652
|
-
ship a `deserialize` migration that upgrades the old version (or, on
|
|
653
|
-
|
|
630
|
+
ship a `deserialize` migration that upgrades the old version (or, on a
|
|
631
|
+
throwaway deployment, clear the DO storage from the dashboard).
|
|
654
632
|
|
|
655
633
|
### 12.5 Nick reservation always fails
|
|
656
634
|
|
|
@@ -658,9 +636,9 @@ A client's `NICK` command always returns `433 ERR_NICKNAMEINUSE`, even
|
|
|
658
636
|
for nicknames that should be free. This happens when two deployments
|
|
659
637
|
share a `RegistryDO` namespace but were supposed to be separate —
|
|
660
638
|
e.g., staging and production point at the same DO class name. Verify
|
|
661
|
-
that each
|
|
662
|
-
|
|
663
|
-
|
|
639
|
+
that each deployment has its own DO namespace (a distinct Worker name
|
|
640
|
+
per Cloudflare account means wrangler allocates a distinct namespace
|
|
641
|
+
per Worker).
|
|
664
642
|
|
|
665
643
|
### 12.6 High request cost / DO request spike
|
|
666
644
|
|
|
@@ -687,9 +665,9 @@ appears lost, either:
|
|
|
687
665
|
- The persisted-state version changed without a deserialize migration
|
|
688
666
|
(see 12.4).
|
|
689
667
|
|
|
690
|
-
For
|
|
691
|
-
re-test. For
|
|
692
|
-
blocker requiring a runbook entry.
|
|
668
|
+
For a throwaway deployment, the fastest recovery is usually to clear DO
|
|
669
|
+
storage and re-test. For real traffic, treat any migration tag change
|
|
670
|
+
as a release blocker requiring a runbook entry.
|
|
693
671
|
|
|
694
672
|
---
|
|
695
673
|
|
|
@@ -705,15 +683,11 @@ pnpm build
|
|
|
705
683
|
pnpm --filter @serverless-ircd/cf-worker dev # http://localhost:8787
|
|
706
684
|
node apps/cf-worker/scripts/smoke.mjs # smoke against localhost
|
|
707
685
|
|
|
708
|
-
#
|
|
709
|
-
pnpm deploy:cf
|
|
686
|
+
# Deploy (single target — staging vs prod is which account you point at)
|
|
687
|
+
pnpm deploy:cf
|
|
710
688
|
node apps/cf-worker/scripts/smoke.mjs \
|
|
711
|
-
--url wss://serverless-ircd
|
|
712
|
-
npx wrangler tail
|
|
713
|
-
|
|
714
|
-
# Production (manual only)
|
|
715
|
-
pnpm deploy:cf:prod
|
|
716
|
-
npx wrangler tail # default env = production
|
|
689
|
+
--url wss://serverless-ircd.<subdomain>.workers.dev
|
|
690
|
+
npx wrangler tail # live logs
|
|
717
691
|
|
|
718
692
|
# Tests / lint
|
|
719
693
|
pnpm test # full workspace
|
|
@@ -732,4 +706,4 @@ Key files:
|
|
|
732
706
|
| `packages/cf-adapter/src/` | `ConnectionDO`, `RegistryDO`, `ChannelDO`, `CfRuntime`, sharding. |
|
|
733
707
|
| `packages/cf-adapter/src/sharding.ts` | Shard function + `DEFAULT_REGISTRY_SHARDS`. |
|
|
734
708
|
| `packages/cf-adapter/src/env.ts` | `Env` interface (binding contract). |
|
|
735
|
-
| `.github/workflows/deploy-cf.yml` |
|
|
709
|
+
| `.github/workflows/deploy-cf.yml` | Deploy + smoke e2e CI (manual dispatch). |
|