serverless-ircd 0.9.0 → 0.11.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 +28 -0
- package/.github/workflows/deploy-aws.yml +156 -32
- package/.github/workflows/deploy-cf-tcp.yml +35 -9
- package/.github/workflows/deploy-cf.yml +40 -14
- package/CHANGELOG.md +594 -0
- package/README.md +286 -60
- package/apps/aws-stack/README.md +3 -5
- package/apps/aws-stack/bin/aws.ts +118 -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 +398 -67
- 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 +714 -105
- 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/Dockerfile +37 -5
- package/apps/cf-tcp-container/package.json +7 -3
- package/apps/cf-tcp-container/src/config-loader.ts +113 -2
- package/apps/cf-tcp-container/src/container-server.ts +267 -87
- package/apps/cf-tcp-container/src/main.ts +22 -7
- package/apps/cf-tcp-container/src/proxy-protocol.ts +112 -0
- package/apps/cf-tcp-container/terraform/spectrum.tf +40 -11
- package/apps/cf-tcp-container/tests/config-loader.test.ts +170 -0
- package/apps/cf-tcp-container/tests/container-server-tls.test.ts +382 -0
- package/apps/cf-tcp-container/tests/container-server.test.ts +358 -31
- package/apps/cf-tcp-container/tests/dockerfile.test.ts +110 -0
- package/apps/cf-tcp-container/tests/proxy-protocol.test.ts +187 -0
- package/apps/cf-tcp-container/tests/spectrum-terraform.test.ts +135 -0
- package/apps/cf-tcp-container/tests/tls-e2e.test.ts +5 -1
- package/apps/cf-tcp-container/wrangler.toml +18 -14
- package/apps/cf-worker/package.json +3 -4
- package/apps/cf-worker/src/worker.ts +77 -5
- package/apps/cf-worker/tests/raw-modules.d.ts +11 -0
- package/apps/cf-worker/tests/smoke.test.ts +4 -0
- package/apps/cf-worker/tests/wrangler-config.test.ts +47 -0
- package/apps/cf-worker/tests/ws-admission.test.ts +112 -0
- package/apps/cf-worker/tests/ws-rate-limit.test.ts +133 -0
- package/apps/cf-worker/wrangler.test.toml +15 -1
- package/apps/cf-worker/wrangler.toml +95 -77
- package/apps/local-cli/package.json +1 -1
- package/apps/local-cli/src/config-loader.ts +14 -2
- package/apps/local-cli/src/line-scanner.ts +26 -0
- package/apps/local-cli/src/server.ts +44 -19
- package/apps/local-cli/tests/line-scanner.test.ts +64 -0
- package/apps/local-cli/tests/tcp.test.ts +29 -0
- package/apps/web/landing/favicon.ico +0 -0
- package/apps/web/landing/index.html +1 -0
- package/apps/web/package.json +2 -2
- package/apps/web/scripts/build.mjs +66 -4
- package/apps/web/src/build-env.ts +125 -4
- package/apps/web/src/config-schema.ts +20 -6
- 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 +2 -2
- package/apps/web/tests/config-schema.test.ts +149 -25
- package/docs/AWS-Deployment.md +793 -118
- package/docs/AWS-TCP-Deployment.md +57 -47
- package/docs/Chat-History.md +55 -0
- package/docs/Cloudflare-Deployment-Guide.md +95 -114
- package/docs/Cloudflare-TCP-Deployment.md +160 -101
- package/docs/Release-Process.md +27 -23
- package/docs/SASL-EXTERNAL.md +175 -0
- package/docs/Services.md +69 -22
- package/docs/WebClientGuide.md +35 -26
- package/package.json +7 -10
- package/packages/aws-adapter/package.json +1 -1
- package/packages/aws-adapter/src/admission.ts +28 -13
- package/packages/aws-adapter/src/aws-runtime.ts +30 -3
- package/packages/aws-adapter/src/cdk-table-defs.ts +39 -16
- package/packages/aws-adapter/src/config-loader.ts +153 -8
- package/packages/aws-adapter/src/dynamo-services-store.ts +19 -0
- package/packages/aws-adapter/src/handlers/connect.ts +73 -1
- package/packages/aws-adapter/src/handlers/default.ts +279 -123
- package/packages/aws-adapter/src/handlers/index.ts +98 -25
- package/packages/aws-adapter/src/handlers/nlb-stream.ts +135 -14
- package/packages/aws-adapter/src/index.ts +5 -7
- package/packages/aws-adapter/src/ip-admission.ts +79 -0
- package/packages/aws-adapter/src/origin-allowlist.ts +94 -0
- package/packages/aws-adapter/src/serialize.ts +23 -0
- package/packages/aws-adapter/src/tables.ts +11 -12
- package/packages/aws-adapter/tests/admission.test.ts +60 -2
- package/packages/aws-adapter/tests/aws-harness.ts +23 -2
- package/packages/aws-adapter/tests/aws-runtime.test.ts +64 -0
- package/packages/aws-adapter/tests/config-loader.test.ts +217 -0
- package/packages/aws-adapter/tests/connect.test.ts +323 -3
- package/packages/aws-adapter/tests/default-frame-limit.test.ts +231 -0
- package/packages/aws-adapter/tests/default-occ.test.ts +226 -0
- package/packages/aws-adapter/tests/dynamo-services-store-unit.test.ts +134 -1
- package/packages/aws-adapter/tests/handlers.test.ts +174 -12
- package/packages/aws-adapter/tests/migrate-accounts-to-services.test.ts +164 -0
- package/packages/aws-adapter/tests/nlb-secure.test.ts +362 -0
- package/packages/aws-adapter/tests/nlb-stream.test.ts +628 -9
- 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 +0 -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 +100 -10
- package/packages/cf-adapter/src/channel-do.ts +13 -3
- package/packages/cf-adapter/src/config-loader.ts +133 -8
- package/packages/cf-adapter/src/connection-do.ts +406 -116
- package/packages/cf-adapter/src/counter-do.ts +142 -0
- package/packages/cf-adapter/src/d1-services-store.ts +105 -26
- package/packages/cf-adapter/src/env.ts +99 -10
- package/packages/cf-adapter/src/index.ts +17 -7
- package/packages/cf-adapter/src/rate-limit-do.ts +87 -0
- package/packages/cf-adapter/tests/cf-runtime.test.ts +205 -16
- package/packages/cf-adapter/tests/channel-do.test.ts +118 -1
- package/packages/cf-adapter/tests/config-loader.test.ts +159 -0
- package/packages/cf-adapter/tests/connection-do-counter.test.ts +165 -0
- package/packages/cf-adapter/tests/connection-do-coverage.test.ts +460 -0
- package/packages/cf-adapter/tests/connection-do-frame-limit.test.ts +177 -0
- package/packages/cf-adapter/tests/connection-do-pure.test.ts +164 -54
- package/packages/cf-adapter/tests/connection-do-sasl-d1.test.ts +62 -38
- package/packages/cf-adapter/tests/connection-do-ws-spec-contract.test.ts +7 -4
- package/packages/cf-adapter/tests/counter-do.test.ts +181 -0
- package/packages/cf-adapter/tests/d1-services-store.test.ts +245 -3
- package/packages/cf-adapter/tests/rate-limit-do.test.ts +160 -0
- package/packages/cf-adapter/tests/serialize.test.ts +25 -0
- package/packages/cf-adapter/tests/worker/main.ts +4 -0
- package/packages/cf-adapter/wrangler.test.toml +18 -1
- package/packages/in-memory-runtime/package.json +1 -1
- package/packages/in-memory-runtime/src/in-memory-runtime.ts +25 -0
- package/packages/in-memory-runtime/tests/in-memory-runtime.test.ts +74 -0
- package/packages/irc-core/package.json +1 -1
- package/packages/irc-core/src/account-migration.ts +140 -0
- package/packages/irc-core/src/caps/capabilities.ts +20 -10
- package/packages/irc-core/src/certfp.ts +178 -0
- package/packages/irc-core/src/commands/account-auth.ts +16 -19
- package/packages/irc-core/src/commands/cap.ts +10 -2
- package/packages/irc-core/src/commands/chanserv.ts +117 -14
- package/packages/irc-core/src/commands/chathistory.ts +13 -5
- package/packages/irc-core/src/commands/hostserv.ts +84 -8
- package/packages/irc-core/src/commands/index.ts +2 -1
- package/packages/irc-core/src/commands/invite.ts +1 -7
- package/packages/irc-core/src/commands/join.ts +1 -16
- package/packages/irc-core/src/commands/kick.ts +1 -8
- package/packages/irc-core/src/commands/list.ts +1 -8
- package/packages/irc-core/src/commands/memoserv.ts +1 -1
- package/packages/irc-core/src/commands/mode.ts +1 -8
- package/packages/irc-core/src/commands/multiline.ts +4 -10
- package/packages/irc-core/src/commands/names.ts +53 -13
- package/packages/irc-core/src/commands/nickserv.ts +161 -11
- package/packages/irc-core/src/commands/oper.ts +361 -8
- package/packages/irc-core/src/commands/part.ts +4 -10
- package/packages/irc-core/src/commands/privmsg.ts +8 -4
- package/packages/irc-core/src/commands/registration.ts +148 -4
- package/packages/irc-core/src/commands/sasl.ts +154 -46
- package/packages/irc-core/src/commands/topic.ts +10 -12
- package/packages/irc-core/src/commands/who.ts +1 -8
- package/packages/irc-core/src/config.ts +424 -25
- package/packages/irc-core/src/credential-hashing.ts +11 -54
- package/packages/irc-core/src/effects.ts +24 -0
- package/packages/irc-core/src/flood-control.ts +10 -10
- package/packages/irc-core/src/frame-rate-limit.ts +82 -0
- package/packages/irc-core/src/index.ts +9 -0
- package/packages/irc-core/src/oper-hashing.ts +43 -0
- package/packages/irc-core/src/oper-lockout.ts +87 -0
- package/packages/irc-core/src/ports.ts +529 -190
- package/packages/irc-core/src/protocol/bytes.ts +65 -0
- package/packages/irc-core/src/protocol/channel-name.ts +37 -0
- package/packages/irc-core/src/protocol/index.ts +12 -1
- package/packages/irc-core/src/protocol/outbound.ts +43 -10
- package/packages/irc-core/src/protocol/parser.ts +79 -10
- package/packages/irc-core/src/state/connection.ts +13 -0
- package/packages/irc-core/src/types.ts +266 -23
- package/packages/irc-core/src/ws-framing.ts +5 -4
- package/packages/irc-core/tests/account-migration.test.ts +133 -0
- package/packages/irc-core/tests/bytes.test.ts +89 -0
- package/packages/irc-core/tests/certfp.test.ts +117 -0
- package/packages/irc-core/tests/commands/cap.test.ts +76 -2
- package/packages/irc-core/tests/commands/chanserv.test.ts +166 -0
- package/packages/irc-core/tests/commands/chathistory.test.ts +140 -0
- package/packages/irc-core/tests/commands/hostserv.test.ts +316 -0
- package/packages/irc-core/tests/commands/join.test.ts +78 -1
- 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/names.test.ts +193 -0
- package/packages/irc-core/tests/commands/nickserv.test.ts +419 -3
- package/packages/irc-core/tests/commands/oper.test.ts +574 -1
- package/packages/irc-core/tests/commands/privmsg.test.ts +16 -0
- package/packages/irc-core/tests/commands/registration.test.ts +602 -133
- package/packages/irc-core/tests/commands/sasl.test.ts +742 -172
- package/packages/irc-core/tests/commands/topic.test.ts +137 -2
- package/packages/irc-core/tests/commands/unified-account.test.ts +104 -84
- package/packages/irc-core/tests/config.test.ts +534 -2
- package/packages/irc-core/tests/credential-hashing.test.ts +0 -78
- package/packages/irc-core/tests/effects.test.ts +14 -0
- package/packages/irc-core/tests/flood-control.test.ts +29 -1
- package/packages/irc-core/tests/frame-rate-limit.test.ts +98 -0
- package/packages/irc-core/tests/message-store.test.ts +5 -0
- package/packages/irc-core/tests/oper-hashing.test.ts +60 -0
- package/packages/irc-core/tests/oper-lockout.test.ts +74 -0
- package/packages/irc-core/tests/outbound.test.ts +148 -0
- package/packages/irc-core/tests/parser.test.ts +287 -5
- package/packages/irc-core/tests/persistent-services-store.test.ts +212 -12
- package/packages/irc-core/tests/ports.test.ts +170 -7
- package/packages/irc-core/tests/services-store.test.ts +567 -1
- package/packages/irc-core/tests/ws-framing.test.ts +45 -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 +123 -22
- package/packages/irc-server/src/dispatch.ts +1 -0
- package/packages/irc-server/src/index.ts +7 -0
- package/packages/irc-server/src/redact.ts +159 -0
- package/packages/irc-server/src/runtime.ts +14 -0
- package/packages/irc-server/src/transport.ts +28 -1
- package/packages/irc-server/tests/actor.test.ts +563 -54
- package/packages/irc-server/tests/dispatch.test.ts +31 -0
- package/packages/irc-server/tests/redact.test.ts +198 -0
- package/packages/irc-server/tests/runtime.test.ts +2 -0
- package/packages/irc-server/tests/transport.test.ts +66 -0
- package/packages/irc-test-support/package.json +1 -1
- package/packages/irc-test-support/src/in-memory-harness.ts +4 -0
- 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 +2 -2
- package/tools/ci-hardening/src/cf-deploy-cli.ts +3 -0
- package/tools/ci-hardening/src/cf-deploy.ts +118 -0
- package/tools/ci-hardening/src/deploy-hostname.ts +118 -0
- package/tools/ci-hardening/src/env-var-drift.ts +192 -0
- package/tools/ci-hardening/src/hostname-guard.ts +11 -0
- package/tools/ci-hardening/src/index.ts +19 -0
- package/tools/ci-hardening/src/validate.ts +57 -0
- package/tools/ci-hardening/tests/__wrangler_missing__.toml +2 -0
- package/tools/ci-hardening/tests/__wrangler_placeholder__.toml +3 -0
- package/tools/ci-hardening/tests/__wrangler_real__.toml +3 -0
- package/tools/ci-hardening/tests/cf-deploy.test.ts +200 -0
- package/tools/ci-hardening/tests/deploy-aws-oidc.test.ts +96 -0
- package/tools/ci-hardening/tests/deploy-hostname.test.ts +348 -0
- package/tools/ci-hardening/tests/env-var-drift.test.ts +284 -0
- package/tools/ci-hardening/tests/validate.test.ts +42 -0
- package/tools/ci-hardening/vitest.config.ts +5 -1
- package/tools/hash-oper-cred.ts +85 -0
- package/tools/load-test/package.json +1 -1
- 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/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
|
@@ -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,60 +260,46 @@ 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"]` |
|
|
292
287
|
| `SERVER_NAME` | Server name sent in `001`/`005` numerics. **Required** — the CF config loader fails fast at boot when unset. | _No default; must be set in `wrangler.toml`._ |
|
|
293
288
|
| `NETWORK_NAME` | Network label in `005 NETWORK=…`. | `ServerlessIRCd` |
|
|
294
289
|
| `MOTD_LINES` | Message-of-the-day, `\n`-delimited. | Welcome banner string. |
|
|
290
|
+
| `MAX_CLIENTS` | Global live-connection cap (enforced by `CounterDO` at the edge). | schema default |
|
|
291
|
+
| `MAX_CONNECTIONS_PER_IP` | Per-IP simultaneous-connection cap (in-memory admission in `ConnectionDO`). | schema default (10) |
|
|
292
|
+
| `PER_IP_CONNECTION_RATE_MAX` | Per-IP upgrade rate budget — how many WebSocket upgrades one `CF-Connecting-IP` may open per sliding window. Enforced at the edge by `RateLimitDO` (429 when over budget). | schema default (5) |
|
|
293
|
+
| `PER_IP_CONNECTION_RATE_WINDOW_MS` | Sliding-window length in ms for the upgrade rate budget. Setting only one half of the pair falls back to the schema default (60 000 ms) for the other. | schema default (60 000) |
|
|
295
294
|
|
|
296
295
|
These are read by `ConnectionDO` via `Env` (see
|
|
297
296
|
`packages/cf-adapter/src/env.ts:20` and the `serverConfig()` method in
|
|
298
297
|
`connection-do.ts:337`). They are **not** secrets — they ship in the
|
|
299
298
|
bundle and are visible in the dashboard.
|
|
300
299
|
|
|
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):
|
|
300
|
+
### 7.2 Durable Object bindings
|
|
306
301
|
|
|
307
|
-
|
|
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
|
|
318
|
-
|
|
319
|
-
Three DO classes are exported from `src/worker.ts` (re-exported from
|
|
302
|
+
The DO classes are exported from `src/worker.ts` (re-exported from
|
|
320
303
|
`@serverless-ircd/cf-adapter`) and bound in `wrangler.toml`:
|
|
321
304
|
|
|
322
305
|
| Binding name | Class | Owned state |
|
|
@@ -324,16 +307,19 @@ Three DO classes are exported from `src/worker.ts` (re-exported from
|
|
|
324
307
|
| `CONNECTION_DO` | `ConnectionDO` | Socket + ConnectionState + PING alarms. |
|
|
325
308
|
| `REGISTRY_DO` | `RegistryDO` | Nick uniqueness, nick→connId map (sharded).|
|
|
326
309
|
| `CHANNEL_DO` | `ChannelDO` | Per-channel roster, modes, topic, fanout. |
|
|
310
|
+
| `CHANNEL_REGISTRY_DO` | `ChannelRegistryDO` | The channel-name registry (shard index). |
|
|
311
|
+
| `COUNTER_DO` | `CounterDO` | Global live-connection counter (`maxClients` cap, TICKET-194). |
|
|
312
|
+
| `RATE_LIMIT_DO` | `RateLimitDO` | Per-IP upgrade rate limiter — one sliding-window admission list per `CF-Connecting-IP`; the Worker edge checks the budget before forwarding an upgrade and rejects over-budget IPs with `429` (the per-IP layer of the connect throttling; runs before the `maxClients` counter so a flooding IP cannot consume global slots). |
|
|
327
313
|
|
|
328
314
|
The class names in `wrangler.toml`'s `class_name` field MUST match the
|
|
329
315
|
re-exports at the top of `apps/cf-worker/src/worker.ts:29`.
|
|
330
316
|
|
|
331
|
-
### 7.
|
|
317
|
+
### 7.3 Migrations
|
|
332
318
|
|
|
333
319
|
```toml
|
|
334
320
|
[[migrations]]
|
|
335
321
|
tag = "v1"
|
|
336
|
-
|
|
322
|
+
new_sqlite_classes = ["ConnectionDO", "RegistryDO", "ChannelDO", "ChannelRegistryDO", "CounterDO", "RateLimitDO"]
|
|
337
323
|
```
|
|
338
324
|
|
|
339
325
|
`tag` is the migration id (string, monotonically tracked by wrangler).
|
|
@@ -342,10 +328,10 @@ new_classes = ["ConnectionDO", "RegistryDO", "ChannelDO"]
|
|
|
342
328
|
block with `tag = "v2"` (etc.) and a `renamed_classes` or `deleted_classes`
|
|
343
329
|
entry. See <https://developers.cloudflare.com/durable-objects/reference/durable-objects-migrations/>.
|
|
344
330
|
|
|
345
|
-
|
|
346
|
-
|
|
331
|
+
There is a single migration list — the `[env.staging]` block was
|
|
332
|
+
removed when staging/prod collapsed into one target.
|
|
347
333
|
|
|
348
|
-
### 7.
|
|
334
|
+
### 7.4 Custom domain (optional)
|
|
349
335
|
|
|
350
336
|
To serve the Worker on `irc.example.com` instead of the workers.dev
|
|
351
337
|
subdomain, add a route and bind a Cloudflare-managed DNS record:
|
|
@@ -357,9 +343,9 @@ zone_name = "example.com"
|
|
|
357
343
|
custom_domain = false # true if you'd rather use a Worker Custom Domain
|
|
358
344
|
```
|
|
359
345
|
|
|
360
|
-
Custom domains are optional for
|
|
361
|
-
(many IRC clients expect a stable, owned hostname). DNS
|
|
362
|
-
managed separately in the dashboard.
|
|
346
|
+
Custom domains are optional for a first deploy and recommended for
|
|
347
|
+
real traffic (many IRC clients expect a stable, owned hostname). DNS
|
|
348
|
+
records are managed separately in the dashboard.
|
|
363
349
|
|
|
364
350
|
---
|
|
365
351
|
|
|
@@ -372,7 +358,7 @@ disabled (the default). Configure it as a wrangler secret, never a
|
|
|
372
358
|
plaintext `[vars]` entry:
|
|
373
359
|
|
|
374
360
|
```bash
|
|
375
|
-
wrangler secret put SERVER_PASSWORD
|
|
361
|
+
wrangler secret put SERVER_PASSWORD
|
|
376
362
|
# → prompts for the value; stores it in the Workers secret store,
|
|
377
363
|
# NOT in wrangler.toml or the repo.
|
|
378
364
|
```
|
|
@@ -463,8 +449,7 @@ node --import tsx tools/seed-cf-accounts.ts \
|
|
|
463
449
|
--accounts alice:change-me bob:also-change-me
|
|
464
450
|
```
|
|
465
451
|
|
|
466
|
-
|
|
467
|
-
seed CLI hashes each password locally and executes the `INSERT OR REPLACE`
|
|
452
|
+
The seed CLI hashes each password locally and executes the `INSERT OR REPLACE`
|
|
468
453
|
via `wrangler d1 execute`.
|
|
469
454
|
|
|
470
455
|
> The `SASL_ACCOUNTS` env var remains the quick-start path (no D1 needed):
|
|
@@ -548,9 +533,9 @@ the public list price as of 2024-11; verify current pricing at
|
|
|
548
533
|
|
|
549
534
|
Practical numbers:
|
|
550
535
|
|
|
551
|
-
- **Workers Free plan**: sufficient to bring up
|
|
536
|
+
- **Workers Free plan**: sufficient to bring up the Worker, exercise the
|
|
552
537
|
smoke e2e, and validate a handful of concurrent connections. Not
|
|
553
|
-
suitable for
|
|
538
|
+
suitable for sustained traffic (request caps, no reserved DO
|
|
554
539
|
compute).
|
|
555
540
|
- **Workers Paid plan** (USD $5/mo base + usage): enough headroom for a
|
|
556
541
|
small production network. The dominant cost driver at scale is
|
|
@@ -572,10 +557,10 @@ mitigations (batched fanout, per-channel send-list cache).
|
|
|
572
557
|
|
|
573
558
|
## 11. CI/CD
|
|
574
559
|
|
|
575
|
-
The GitHub Actions workflow at `.github/workflows/deploy-cf.yml`
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
560
|
+
The GitHub Actions workflow at `.github/workflows/deploy-cf.yml` is
|
|
561
|
+
`workflow_dispatch`-only (a maintainer triggers it by hand); there is
|
|
562
|
+
no automatic push-to-main deploy. It deploys the single Worker target
|
|
563
|
+
and replays the smoke e2e.
|
|
579
564
|
|
|
580
565
|
Steps performed by the workflow (in order):
|
|
581
566
|
|
|
@@ -584,13 +569,13 @@ Steps performed by the workflow (in order):
|
|
|
584
569
|
3. `pnpm install --frozen-lockfile`.
|
|
585
570
|
4. `pnpm build` — builds all workspace packages.
|
|
586
571
|
5. `pnpm typecheck` and `pnpm test` — gate the deploy.
|
|
587
|
-
6. `pnpm deploy:cf
|
|
572
|
+
6. `pnpm deploy:cf` — `wrangler deploy`.
|
|
588
573
|
7. Resolve the smoke URL from the `CF_SMOKE_URL` repo variable. If
|
|
589
574
|
unset, the smoke step is skipped with a warning.
|
|
590
575
|
8. Run `node scripts/smoke.mjs --url "$SMOKE_URL"`. Failure fails the
|
|
591
576
|
build.
|
|
592
577
|
|
|
593
|
-
Concurrency is serialized via `concurrency.group: cf-
|
|
578
|
+
Concurrency is serialized via `concurrency.group: cf-deploy` so two
|
|
594
579
|
deploys cannot race the same DO namespace.
|
|
595
580
|
|
|
596
581
|
Required repo configuration (under Settings → Secrets and variables →
|
|
@@ -599,12 +584,12 @@ Actions):
|
|
|
599
584
|
- **Secret `CLOUDFLARE_API_TOKEN`** — required.
|
|
600
585
|
- **Secret `CLOUDFLARE_ACCOUNT_ID`** — required if the token's account
|
|
601
586
|
context is ambiguous.
|
|
602
|
-
- **Variable `CF_SMOKE_URL`** — set to the
|
|
587
|
+
- **Variable `CF_SMOKE_URL`** — set to the Worker's `wss://`
|
|
603
588
|
URL. Without it, the smoke step silently no-ops.
|
|
604
589
|
|
|
605
|
-
There is
|
|
606
|
-
|
|
607
|
-
|
|
590
|
+
There is a single deploy target — the staging/prod split was collapsed,
|
|
591
|
+
so the same workflow + account ships to whichever Worker namespace the
|
|
592
|
+
credentials target.
|
|
608
593
|
|
|
609
594
|
---
|
|
610
595
|
|
|
@@ -619,10 +604,10 @@ the `[[migrations]]` block, wrangler refuses to proceed.
|
|
|
619
604
|
- If you intentionally changed the DO schema, append a new
|
|
620
605
|
`[[migrations]]` block with `tag = "v2"` (and `renamed_classes` /
|
|
621
606
|
`deleted_classes` as needed). Never edit an already-applied `tag`.
|
|
622
|
-
- If the
|
|
607
|
+
- If the namespace has stale state from an aborted experiment,
|
|
623
608
|
you can destroy and recreate it from the dashboard (Workers & Pages →
|
|
624
|
-
Durable Objects → namespaces). **
|
|
625
|
-
deleted** — that data is gone permanently.
|
|
609
|
+
Durable Objects → namespaces). **Namespaces carrying real traffic must
|
|
610
|
+
never be deleted** — that data is gone permanently.
|
|
626
611
|
|
|
627
612
|
### 12.2 `Cannot find module '@serverless-ircd/cf-adapter'`
|
|
628
613
|
|
|
@@ -636,10 +621,10 @@ The connection upgrade succeeded but registration didn't complete.
|
|
|
636
621
|
Common causes:
|
|
637
622
|
|
|
638
623
|
- The deployed Worker is reachable but the DO threw on the first frame.
|
|
639
|
-
Tail the logs: `wrangler tail
|
|
624
|
+
Tail the logs: `wrangler tail` and reproduce.
|
|
640
625
|
- The `MOTD_LINES` or `SERVER_NAME` var was deleted — `ConnectionDO`'s
|
|
641
626
|
`serverConfig()` falls back to defaults, but a malformed value can
|
|
642
|
-
break parsing. Check the `[
|
|
627
|
+
break parsing. Check the `[vars]` block.
|
|
643
628
|
- Client connected over `ws://` to a Worker that requires `wss://`.
|
|
644
629
|
Use the `wss://` URL the deploy step printed.
|
|
645
630
|
|
|
@@ -649,8 +634,8 @@ The DO alarm fired but the handler threw. The most likely cause is a
|
|
|
649
634
|
stale persisted-state version after a code change; the serializer in
|
|
650
635
|
`packages/cf-adapter/src/serialize.ts` carries `PERSISTED_STATE_VERSION`
|
|
651
636
|
and will reject incompatible blobs. If this happens after an upgrade,
|
|
652
|
-
ship a `deserialize` migration that upgrades the old version (or, on
|
|
653
|
-
|
|
637
|
+
ship a `deserialize` migration that upgrades the old version (or, on a
|
|
638
|
+
throwaway deployment, clear the DO storage from the dashboard).
|
|
654
639
|
|
|
655
640
|
### 12.5 Nick reservation always fails
|
|
656
641
|
|
|
@@ -658,9 +643,9 @@ A client's `NICK` command always returns `433 ERR_NICKNAMEINUSE`, even
|
|
|
658
643
|
for nicknames that should be free. This happens when two deployments
|
|
659
644
|
share a `RegistryDO` namespace but were supposed to be separate —
|
|
660
645
|
e.g., staging and production point at the same DO class name. Verify
|
|
661
|
-
that each
|
|
662
|
-
|
|
663
|
-
|
|
646
|
+
that each deployment has its own DO namespace (a distinct Worker name
|
|
647
|
+
per Cloudflare account means wrangler allocates a distinct namespace
|
|
648
|
+
per Worker).
|
|
664
649
|
|
|
665
650
|
### 12.6 High request cost / DO request spike
|
|
666
651
|
|
|
@@ -687,9 +672,9 @@ appears lost, either:
|
|
|
687
672
|
- The persisted-state version changed without a deserialize migration
|
|
688
673
|
(see 12.4).
|
|
689
674
|
|
|
690
|
-
For
|
|
691
|
-
re-test. For
|
|
692
|
-
blocker requiring a runbook entry.
|
|
675
|
+
For a throwaway deployment, the fastest recovery is usually to clear DO
|
|
676
|
+
storage and re-test. For real traffic, treat any migration tag change
|
|
677
|
+
as a release blocker requiring a runbook entry.
|
|
693
678
|
|
|
694
679
|
---
|
|
695
680
|
|
|
@@ -705,15 +690,11 @@ pnpm build
|
|
|
705
690
|
pnpm --filter @serverless-ircd/cf-worker dev # http://localhost:8787
|
|
706
691
|
node apps/cf-worker/scripts/smoke.mjs # smoke against localhost
|
|
707
692
|
|
|
708
|
-
#
|
|
709
|
-
pnpm deploy:cf
|
|
693
|
+
# Deploy (single target — staging vs prod is which account you point at)
|
|
694
|
+
pnpm deploy:cf
|
|
710
695
|
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
|
|
696
|
+
--url wss://serverless-ircd.<subdomain>.workers.dev
|
|
697
|
+
npx wrangler tail # live logs
|
|
717
698
|
|
|
718
699
|
# Tests / lint
|
|
719
700
|
pnpm test # full workspace
|
|
@@ -732,4 +713,4 @@ Key files:
|
|
|
732
713
|
| `packages/cf-adapter/src/` | `ConnectionDO`, `RegistryDO`, `ChannelDO`, `CfRuntime`, sharding. |
|
|
733
714
|
| `packages/cf-adapter/src/sharding.ts` | Shard function + `DEFAULT_REGISTRY_SHARDS`. |
|
|
734
715
|
| `packages/cf-adapter/src/env.ts` | `Env` interface (binding contract). |
|
|
735
|
-
| `.github/workflows/deploy-cf.yml` |
|
|
716
|
+
| `.github/workflows/deploy-cf.yml` | Deploy + smoke e2e CI (manual dispatch). |
|