serverless-ircd 0.2.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.
Files changed (221) hide show
  1. package/.github/workflows/ci.yml +2 -2
  2. package/.github/workflows/deploy-aws.yml +1 -3
  3. package/.github/workflows/deploy-cf-tcp.yml +87 -0
  4. package/.github/workflows/deploy-cf.yml +1 -1
  5. package/.node-version +1 -0
  6. package/.nvmrc +1 -0
  7. package/CHANGELOG.md +258 -18
  8. package/README.md +72 -30
  9. package/apps/aws-stack/README.md +2 -2
  10. package/apps/aws-stack/bin/aws.ts +7 -0
  11. package/apps/aws-stack/package.json +4 -4
  12. package/apps/aws-stack/src/aws-stack.ts +118 -6
  13. package/apps/aws-stack/tests/stack.test.ts +98 -3
  14. package/apps/cf-tcp-container/Dockerfile +69 -0
  15. package/apps/cf-tcp-container/package.json +34 -0
  16. package/apps/cf-tcp-container/src/config-loader.ts +145 -0
  17. package/apps/cf-tcp-container/src/container-do.ts +38 -0
  18. package/apps/cf-tcp-container/src/container-server.ts +363 -0
  19. package/apps/cf-tcp-container/src/main.ts +77 -0
  20. package/apps/cf-tcp-container/src/persistence.ts +144 -0
  21. package/apps/cf-tcp-container/src/worker.ts +41 -0
  22. package/apps/cf-tcp-container/terraform/provider.tf +24 -0
  23. package/apps/cf-tcp-container/terraform/spectrum.tf +81 -0
  24. package/apps/cf-tcp-container/tests/config-loader.test.ts +217 -0
  25. package/apps/cf-tcp-container/tests/container-server.test.ts +465 -0
  26. package/apps/cf-tcp-container/tests/persistence.test.ts +227 -0
  27. package/apps/cf-tcp-container/tests/tls-e2e.test.ts +275 -0
  28. package/apps/cf-tcp-container/tsconfig.build.json +17 -0
  29. package/apps/cf-tcp-container/tsconfig.test.json +15 -0
  30. package/apps/cf-tcp-container/vitest.config.ts +26 -0
  31. package/apps/cf-tcp-container/wrangler.toml +63 -0
  32. package/apps/cf-worker/package.json +1 -1
  33. package/apps/cf-worker/scripts/smoke.mjs +0 -0
  34. package/apps/cf-worker/src/worker.ts +8 -2
  35. package/apps/cf-worker/tests/smoke.test.ts +1 -0
  36. package/apps/cf-worker/wrangler.test.toml +11 -1
  37. package/apps/cf-worker/wrangler.toml +69 -19
  38. package/apps/local-cli/package.json +1 -1
  39. package/apps/local-cli/src/config-loader.ts +11 -0
  40. package/apps/local-cli/src/main.ts +1 -1
  41. package/apps/local-cli/src/server.ts +46 -3
  42. package/apps/local-cli/tests/e2e.test.ts +52 -0
  43. package/package.json +19 -16
  44. package/packages/aws-adapter/package.json +3 -3
  45. package/packages/aws-adapter/src/account-store.ts +121 -0
  46. package/packages/aws-adapter/src/admission.ts +74 -0
  47. package/packages/aws-adapter/src/aws-runtime.ts +124 -34
  48. package/packages/aws-adapter/src/cdk-table-defs.ts +5 -1
  49. package/packages/aws-adapter/src/config-loader.ts +62 -0
  50. package/packages/aws-adapter/src/dynamo-account-store.ts +95 -0
  51. package/packages/aws-adapter/src/handlers/connect.ts +64 -8
  52. package/packages/aws-adapter/src/handlers/default.ts +43 -2
  53. package/packages/aws-adapter/src/handlers/disconnect.ts +27 -8
  54. package/packages/aws-adapter/src/handlers/index.ts +120 -9
  55. package/packages/aws-adapter/src/handlers/nlb-stream.ts +481 -0
  56. package/packages/aws-adapter/src/handlers/ping-checker.ts +1 -1
  57. package/packages/aws-adapter/src/index.ts +13 -0
  58. package/packages/aws-adapter/tests/account-store-dynamo.test.ts +182 -0
  59. package/packages/aws-adapter/tests/account-store.test.ts +279 -0
  60. package/packages/aws-adapter/tests/admission.test.ts +70 -0
  61. package/packages/aws-adapter/tests/aws-harness.ts +13 -1
  62. package/packages/aws-adapter/tests/config-loader.test.ts +75 -0
  63. package/packages/aws-adapter/tests/connect.test.ts +78 -0
  64. package/packages/aws-adapter/tests/disconnect-fanout.test.ts +343 -0
  65. package/packages/aws-adapter/tests/gone-exception.test.ts +31 -26
  66. package/packages/aws-adapter/tests/handlers.test.ts +194 -47
  67. package/packages/aws-adapter/tests/nlb-stream.test.ts +478 -0
  68. package/packages/aws-adapter/tests/ping-checker.test.ts +34 -29
  69. package/packages/aws-adapter/tests/sweeper.test.ts +25 -18
  70. package/packages/aws-adapter/tests/transactions.test.ts +25 -20
  71. package/packages/cf-adapter/package.json +1 -1
  72. package/packages/cf-adapter/src/cf-runtime.ts +40 -22
  73. package/packages/cf-adapter/src/channel-do.ts +40 -1
  74. package/packages/cf-adapter/src/channel-registry-do.ts +58 -0
  75. package/packages/cf-adapter/src/config-loader.ts +62 -0
  76. package/packages/cf-adapter/src/connection-do.ts +181 -31
  77. package/packages/cf-adapter/src/d1-account-store.ts +198 -0
  78. package/packages/cf-adapter/src/env.ts +58 -8
  79. package/packages/cf-adapter/src/index.ts +11 -9
  80. package/packages/cf-adapter/tests/cf-harness.ts +11 -1
  81. package/packages/cf-adapter/tests/cf-integration.test.ts +2 -1
  82. package/packages/cf-adapter/tests/cf-runtime.test.ts +91 -0
  83. package/packages/cf-adapter/tests/config-loader.test.ts +22 -0
  84. package/packages/cf-adapter/tests/connection-do-channel-registration.test.ts +37 -0
  85. package/packages/cf-adapter/tests/connection-do-no-batching-reservation.test.ts +52 -0
  86. package/packages/cf-adapter/tests/connection-do-sasl-d1.test.ts +166 -0
  87. package/packages/cf-adapter/tests/connection-do.test.ts +40 -0
  88. package/packages/cf-adapter/tests/d1-account-store.test.ts +226 -0
  89. package/packages/cf-adapter/tests/raw-modules.d.ts +11 -0
  90. package/packages/cf-adapter/tests/worker/main.ts +9 -1
  91. package/packages/cf-adapter/tests/worker/stubs/channel-stub.ts +7 -1
  92. package/packages/cf-adapter/wrangler.test.toml +18 -1
  93. package/packages/in-memory-runtime/package.json +1 -1
  94. package/packages/in-memory-runtime/src/in-memory-runtime.ts +14 -28
  95. package/packages/in-memory-runtime/tests/in-memory-runtime.test.ts +19 -0
  96. package/packages/irc-core/package.json +8 -2
  97. package/packages/irc-core/scripts/generate-build-info.mjs +31 -0
  98. package/packages/irc-core/src/caps/capabilities.ts +23 -2
  99. package/packages/irc-core/src/case-fold.ts +64 -0
  100. package/packages/irc-core/src/cloak.ts +1 -1
  101. package/packages/irc-core/src/commands/cap.ts +8 -1
  102. package/packages/irc-core/src/commands/index.ts +11 -0
  103. package/packages/irc-core/src/commands/invite.ts +6 -9
  104. package/packages/irc-core/src/commands/ison.ts +61 -0
  105. package/packages/irc-core/src/commands/isupport.ts +1 -1
  106. package/packages/irc-core/src/commands/join.ts +4 -3
  107. package/packages/irc-core/src/commands/kick.ts +4 -11
  108. package/packages/irc-core/src/commands/list.ts +5 -4
  109. package/packages/irc-core/src/commands/mode.ts +5 -9
  110. package/packages/irc-core/src/commands/motd-lines.ts +127 -0
  111. package/packages/irc-core/src/commands/motd.ts +6 -110
  112. package/packages/irc-core/src/commands/oper.ts +151 -0
  113. package/packages/irc-core/src/commands/quit.ts +12 -0
  114. package/packages/irc-core/src/commands/registration.ts +26 -19
  115. package/packages/irc-core/src/commands/sasl.ts +72 -9
  116. package/packages/irc-core/src/commands/server-info.ts +129 -0
  117. package/packages/irc-core/src/commands/tagmsg.ts +205 -0
  118. package/packages/irc-core/src/commands/userhost.ts +84 -0
  119. package/packages/irc-core/src/commands/whowas.ts +113 -0
  120. package/packages/irc-core/src/config.ts +84 -3
  121. package/packages/irc-core/src/credential-hashing.ts +124 -0
  122. package/packages/irc-core/src/effects.ts +6 -29
  123. package/packages/irc-core/src/index.ts +3 -0
  124. package/packages/irc-core/src/ports.ts +240 -7
  125. package/packages/irc-core/src/protocol/numerics.ts +14 -8
  126. package/packages/irc-core/src/types.ts +60 -1
  127. package/packages/irc-core/tests/account-store.test.ts +131 -0
  128. package/packages/irc-core/tests/caps/capabilities.test.ts +4 -3
  129. package/packages/irc-core/tests/case-fold.test.ts +80 -0
  130. package/packages/irc-core/tests/commands/cap.test.ts +33 -1
  131. package/packages/irc-core/tests/commands/ison.test.ts +166 -0
  132. package/packages/irc-core/tests/commands/kick.test.ts +15 -0
  133. package/packages/irc-core/tests/commands/oper.test.ts +257 -0
  134. package/packages/irc-core/tests/commands/quit.test.ts +69 -2
  135. package/packages/irc-core/tests/commands/registration.test.ts +256 -19
  136. package/packages/irc-core/tests/commands/sasl.test.ts +118 -10
  137. package/packages/irc-core/tests/commands/server-info.test.ts +274 -0
  138. package/packages/irc-core/tests/commands/tagmsg.test.ts +662 -0
  139. package/packages/irc-core/tests/commands/userhost.test.ts +264 -0
  140. package/packages/irc-core/tests/commands/who.test.ts +22 -4
  141. package/packages/irc-core/tests/commands/whois.test.ts +8 -1
  142. package/packages/irc-core/tests/commands/whowas.test.ts +312 -0
  143. package/packages/irc-core/tests/config.test.ts +170 -1
  144. package/packages/irc-core/tests/credential-hashing.test.ts +170 -0
  145. package/packages/irc-core/tests/effects.test.ts +0 -27
  146. package/packages/irc-core/tests/nick-history-store.test.ts +162 -0
  147. package/packages/irc-core/tests/numerics.test.ts +12 -0
  148. package/packages/irc-core/tests/types.test.ts +35 -1
  149. package/packages/irc-core/tsconfig.build.json +1 -1
  150. package/packages/irc-core/tsconfig.test.json +1 -1
  151. package/packages/irc-server/package.json +1 -1
  152. package/packages/irc-server/src/actor.ts +182 -14
  153. package/packages/irc-server/src/dispatch.ts +0 -3
  154. package/packages/irc-server/src/index.ts +10 -2
  155. package/packages/irc-server/src/routing.ts +21 -0
  156. package/packages/irc-server/src/transport.ts +101 -0
  157. package/packages/irc-server/tests/actor.test.ts +617 -1
  158. package/packages/irc-server/tests/dispatch.test.ts +0 -17
  159. package/packages/irc-server/tests/routing.test.ts +7 -0
  160. package/packages/irc-server/tests/transport.test.ts +230 -0
  161. package/packages/irc-test-support/package.json +1 -1
  162. package/packages/irc-test-support/src/harness.ts +44 -9
  163. package/packages/irc-test-support/src/in-memory-harness.ts +78 -13
  164. package/packages/irc-test-support/src/index.ts +3 -0
  165. package/packages/irc-test-support/src/scenarios.ts +132 -2
  166. package/packages/irc-test-support/tests/in-memory-harness.test.ts +2 -1
  167. package/packages/irc-test-support/tests/in-memory-scenarios.test.ts +23 -9
  168. package/pnpm-workspace.yaml +9 -0
  169. package/tools/ci-hardening/package.json +1 -1
  170. package/tools/package.json +4 -0
  171. package/tools/seed-aws-accounts.ts +79 -0
  172. package/tools/seed-cf-accounts.ts +104 -0
  173. package/tools/tcp-ws-forwarder/package.json +1 -1
  174. package/AGENTS.md +0 -5
  175. package/MOTD.txt +0 -3
  176. package/PLAN-FIXES.md +0 -358
  177. package/PLAN.md +0 -420
  178. package/dashboards/cloudwatch-irc.json +0 -139
  179. package/docs/AWS-Adapter-Architecture.md +0 -494
  180. package/docs/AWS-Deployment.md +0 -1107
  181. package/docs/Cloudflare-Deployment-Guide.md +0 -660
  182. package/docs/Home.md +0 -1
  183. package/docs/Observability.md +0 -87
  184. package/docs/PlanIRCv3Websocket.md +0 -489
  185. package/docs/PlanWebClient.md +0 -451
  186. package/docs/Release-Process.md +0 -440
  187. package/progress.md +0 -107
  188. package/tickets.md +0 -2485
  189. package/webircgateway/LICENSE +0 -201
  190. package/webircgateway/Makefile +0 -44
  191. package/webircgateway/README.md +0 -134
  192. package/webircgateway/config.conf.example +0 -135
  193. package/webircgateway/go.mod +0 -16
  194. package/webircgateway/go.sum +0 -89
  195. package/webircgateway/main.go +0 -118
  196. package/webircgateway/pkg/dnsbl/dnsbl.go +0 -121
  197. package/webircgateway/pkg/identd/identd.go +0 -86
  198. package/webircgateway/pkg/identd/rpcclient.go +0 -59
  199. package/webircgateway/pkg/irc/isupport.go +0 -56
  200. package/webircgateway/pkg/irc/message.go +0 -217
  201. package/webircgateway/pkg/irc/state.go +0 -79
  202. package/webircgateway/pkg/proxy/proxy.go +0 -129
  203. package/webircgateway/pkg/proxy/server.go +0 -237
  204. package/webircgateway/pkg/recaptcha/recaptcha.go +0 -59
  205. package/webircgateway/pkg/webircgateway/client.go +0 -741
  206. package/webircgateway/pkg/webircgateway/client_command_handlers.go +0 -495
  207. package/webircgateway/pkg/webircgateway/config.go +0 -385
  208. package/webircgateway/pkg/webircgateway/gateway.go +0 -278
  209. package/webircgateway/pkg/webircgateway/gateway_utils.go +0 -133
  210. package/webircgateway/pkg/webircgateway/hooks.go +0 -152
  211. package/webircgateway/pkg/webircgateway/letsencrypt.go +0 -41
  212. package/webircgateway/pkg/webircgateway/messagetags.go +0 -103
  213. package/webircgateway/pkg/webircgateway/transport_kiwiirc.go +0 -206
  214. package/webircgateway/pkg/webircgateway/transport_sockjs.go +0 -107
  215. package/webircgateway/pkg/webircgateway/transport_tcp.go +0 -113
  216. package/webircgateway/pkg/webircgateway/transport_websocket.go +0 -126
  217. package/webircgateway/pkg/webircgateway/utils.go +0 -147
  218. package/webircgateway/plugins/example/plugin.go +0 -11
  219. package/webircgateway/plugins/stats/plugin.go +0 -52
  220. package/webircgateway/staticcheck.conf +0 -1
  221. package/webircgateway/webircgateway.svg +0 -3
@@ -1,440 +0,0 @@
1
- # Release Process
2
-
3
- End-to-end runbook for cutting, publishing, and rolling back a
4
- ServerlessIRCd release. This is the canonical process — every release
5
- follows this document top-to-bottom.
6
-
7
- **Distribution model.** All workspace packages are `"private": true`. A
8
- release is a **signed git tag** plus a **GitHub Release** whose body is
9
- copied from `CHANGELOG.md`. There is no npm publish step in 0.x. See
10
- §10 (Future: npm publish) for the criteria that would flip that on.
11
-
12
- **Current cadence.** 0.x is "tag when ready" — there is no fixed
13
- calendar release. Anyone with push rights may propose a release by
14
- opening a PR that bumps versions and updates `CHANGELOG.md`; the
15
- maintainer team cuts the tag.
16
-
17
- Cross-reference: `README.md` (Roadmap), `progress.md` / `tickets.md`
18
- (release content), `docs/deployment-cf.md` (prod deploy step §6),
19
- `.github/workflows/ci.yml`, `.github/workflows/deploy-cf.yml`.
20
-
21
- ---
22
-
23
- ## 1. Versioning
24
-
25
- ServerlessIRCd follows [Semantic Versioning](https://semver.org/) with
26
- the 0.x convention:
27
-
28
- | Bump | When |
29
- |-------------|-----------------------------------------------------------------|
30
- | `0.x.0 → 0.(x+1).0` | Any user-visible behavior change, new command/cap, new adapter, schema change to persisted DO state. |
31
- | `0.x.y → 0.x.(y+1)`* | Internal-only fixes: tests, docs, refactors that don't change runtime behavior, perf work with identical output. (*Reserved for after 1.0; in 0.x every change is allowed to be a minor.) |
32
- | `1.0.0` | The Cloudflare **and** AWS adapters are deployed to staging, the parametrized contract suite passes on both, ≥3 reference clients connect cleanly (PLAN §9 exit criteria). |
33
-
34
- **The 0.x disclaimer.** Per SemVer 0.x, anything may change at any
35
- minor bump. Consumers of `@serverless-ircd/*` packages (today: only
36
- this repo itself) should pin exact versions.
37
-
38
- ### 1.1 Workspace version lock
39
-
40
- All eight `package.json` files (root + 7 workspace packages) carry the
41
- **same** version string. They are bumped together in the release
42
- commit. The pre-release checklist in §4 enforces this.
43
-
44
- Rationale: even though the packages are private today, keeping a single
45
- version simplifies future npm publishing, release notes, and
46
- bug-report triage ("what version are you on?" has one answer).
47
-
48
- ### 1.2 Persisted-state schema
49
-
50
- A change to `PERSISTED_STATE_VERSION` in
51
- `packages/cf-adapter/src/serialize.ts` (or any equivalent versioned
52
- blob in a future adapter) is a **minor bump minimum**, and requires a
53
- migration entry in `CHANGELOG.md` under a **⚠️ Migration required**
54
- heading. See §9 (Rollback) for why rollback across such a bump is
55
- not always possible.
56
-
57
- ---
58
-
59
- ## 2. Roles & permissions
60
-
61
- | Role | Who has it today | Required for |
62
- |-----------------------------|--------------------------|---------------------------------------|
63
- | Push to `main` | Maintainers | Merging the release PR. |
64
- | Push tags (`v*`) | Maintainers | `git push origin v0.x.0`. |
65
- | Create GitHub Release | Maintainers | Publishing the release notes. |
66
- | `CLOUDFLARE_API_TOKEN` secret | Repo Settings → Secrets | Local prod deploys. CI staging deploys. |
67
- | `CF_SMOKE_URL` variable | Repo Settings → Variables | Staging smoke e2e in CI. |
68
-
69
- There is no separate "release engineer" role. The maintainer who cuts
70
- the tag owns the release end-to-end, including the production deploy
71
- and the post-release smoke check.
72
-
73
- ---
74
-
75
- ## 3. Branch & tag conventions
76
-
77
- - **Releases are cut from `main`.** No release branches in 0.x.
78
- - **Tags** are annotated, signed where possible, formatted `v<semver>`
79
- (e.g. `v0.1.0`, `v0.1.1`, `v1.0.0-rc.1`).
80
- - **Pre-release tags** use SemVer suffixes: `v0.2.0-rc.1`,
81
- `v1.0.0-beta.3`. GitHub marks the release as a pre-release
82
- automatically based on the suffix.
83
- - The release commit message is `chore(release): vX.Y.Z` (matches the
84
- tag).
85
-
86
- ---
87
-
88
- ## 4. Pre-release checklist
89
-
90
- Run every box before tagging. Most are verifiable from the repo root.
91
-
92
- ```bash
93
- # 0. Sanity: clean tree on main, up to date with origin.
94
- git status # working tree clean
95
- git checkout main
96
- git pull --ff-only origin main
97
-
98
- # 1. All desired work merged. No pending tickets targeted for this release.
99
- # Cross-check progress.md — every ticket listed under this release is ✅.
100
-
101
- # 2. CI is green on the tip of main.
102
- # Open: https://github.com/<owner>/<repo>/actions
103
- # - CI workflow: lint / typecheck / coverage all green.
104
- # - deploy-cf workflow: staging deploy + smoke e2e green.
105
-
106
- # 3. Local full verify.
107
- pnpm install --frozen-lockfile
108
- pnpm lint # biome check .
109
- pnpm typecheck # tsc --noEmit across workspace
110
- pnpm test # full suite
111
- pnpm build # every package produces dist/
112
-
113
- # 4. Coverage gate.
114
- # NOTE: the 90% coverage gate (TICKET-048) is not yet wired in CI.
115
- # Until it lands, manually inspect packages/*/coverage/ for regressions
116
- # vs. the previous release. Any drop > 2 percentage points blocks the
117
- # release unless explicitly justified in CHANGELOG.md.
118
-
119
- # 5. Staging smoke e2e passes against the deployed tip-of-main.
120
- node apps/cf-worker/scripts/smoke.mjs \
121
- --url wss://serverless-ircd-staging.<subdomain>.workers.dev
122
-
123
- # 6. CHANGELOG.md is complete and accurate (§5).
124
- # 7. All package.json versions are bumped and lock-step (§6).
125
- # 8. The Release PR is merged (§7).
126
- ```
127
-
128
- If any box fails, **stop**. Fix forward on `main` and restart the
129
- checklist — do not tag over a broken tip.
130
-
131
- ### 4.1 What is explicitly out of scope for a 0.x release
132
-
133
- - AWS adapter (TICKET-039 through TICKET-044).
134
- - SASL authentication (TICKET-026).
135
- - Flood control (TICKET-028).
136
- - Server password / rate limits / cloaking (TICKET-046).
137
- - Config loader (TICKET-047).
138
- - CI coverage gate ≥90% (TICKET-048).
139
-
140
- These belong in a later 0.x release. Their absence is **not** a
141
- blocker and should be called out under "Known limitations" in the
142
- GitHub Release body.
143
-
144
- ---
145
-
146
- ## 5. Writing `CHANGELOG.md`
147
-
148
- Format: [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), newest
149
- entry first. One `## [X.Y.Z] - YYYY-MM-DD` section per release.
150
-
151
- Categories (use only what applies):
152
-
153
- - **Added** — new features, commands, caps, adapters.
154
- - **Changed** — behavior changes in existing functionality.
155
- - **⚠️ Migration required** — anything that needs operator action on
156
- upgrade (DO schema bumps, persisted-state version bumps, config
157
- shape changes). One bullet per action item.
158
- - **Deprecated** — functionality scheduled for removal.
159
- - **Removed** — functionality removed in this release.
160
- - **Fixed** — bug fixes.
161
- - **Security** — vulnerability fixes (also request a CVE).
162
- - **Known limitations** — explicit "not in this release" list so
163
- operators aren't surprised.
164
-
165
- Source material for the entry:
166
-
167
- 1. `progress.md` — the ticket table. Every `✅` row since the previous
168
- release tag is a candidate bullet.
169
- 2. `tickets.md` — the per-ticket **Description** field, for the prose.
170
- 3. `git log v<previous>..HEAD --oneline` — for fixes that don't have a
171
- ticket.
172
-
173
- Group by user-facing theme (Registration, Channel ops, IRCv3,
174
- Cloudflare adapter, …) rather than by ticket number. Operators read
175
- themes; developers cross-reference tickets.
176
-
177
- Rule of thumb: a new operator reading only `CHANGELOG.md` should
178
- understand what changed and what they need to do.
179
-
180
- ---
181
-
182
- ## 6. Bumping versions
183
-
184
- There are eight `package.json` files. They must end up at the same
185
- version:
186
-
187
- ```
188
- ./package.json (workspace root)
189
- packages/irc-core/package.json
190
- packages/irc-server/package.json
191
- packages/in-memory-runtime/package.json
192
- packages/cf-adapter/package.json
193
- apps/local-cli/package.json
194
- apps/cf-worker/package.json
195
- tools/tcp-ws-forwarder/package.json
196
- ```
197
-
198
- To cut `v0.X.Y`:
199
-
200
- ```bash
201
- # from the repo root, on a fresh branch off main:
202
- git checkout -b release/v0.X.Y
203
-
204
- # bump each file. The version field is the only change.
205
- # (Optional helper: `pnpm -r exec -- node -e '...'` if you script it.)
206
-
207
- # verify all eight files agree:
208
- rg '"version":' package.json packages/*/package.json apps/*/package.json tools/*/package.json
209
- ```
210
-
211
- The lockfile (`pnpm-lock.yaml`) is unaffected — none of the workspace
212
- dependencies are version-pinned to the workspace root.
213
-
214
- Do **not** run `pnpm publish` or `npm version` — those are for npm
215
- distribution, which is not the current model.
216
-
217
- ---
218
-
219
- ## 7. The release PR
220
-
221
- The release PR contains **exactly two files changed**:
222
-
223
- 1. `CHANGELOG.md` (new entry under the version being cut).
224
- 2. Every `package.json` listed in §6 (version bump).
225
-
226
- Nothing else. If a code change is needed for the release, it lands in
227
- a separate PR first and the release PR is opened only after that PR
228
- merges.
229
-
230
- **PR title:** `chore(release): v0.X.Y`
231
- **PR body:**
232
-
233
- ```
234
- This cuts v0.X.Y. See CHANGELOG.md for the full diff vs. v0.W.Z.
235
-
236
- Pre-release checklist: docs/release.md §4 — all green.
237
- Out-of-scope tickets: docs/release.md §4.1.
238
-
239
- After merge: tag + GitHub Release + manual prod deploy per
240
- docs/release.md §8.
241
- ```
242
-
243
- The PR is squash-merged with the same title as the commit message.
244
-
245
- ---
246
-
247
- ## 8. Cutting the release
248
-
249
- Run **immediately** after the release PR merges, so the tag points at
250
- the exact commit the changelog describes.
251
-
252
- ```bash
253
- git checkout main
254
- git pull --ff-only origin main
255
-
256
- # Confirm the tip commit is the squashed release PR.
257
- git log -1 --oneline # expect: chore(release): v0.X.Y
258
-
259
- # Confirm versions are at the new release.
260
- rg '"version":' package.json packages/*/package.json apps/*/package.json tools/*/package.json
261
- ```
262
-
263
- ### 8.1 Tag and push
264
-
265
- ```bash
266
- git tag -a v0.X.Y -m "v0.X.Y"
267
- git push origin v0.X.Y
268
- ```
269
-
270
- Annotated (`-a`) tags carry tagger + date + message; use them over
271
- lightweight tags. Sign with `-s` if you have a GPG / SSH signing key
272
- configured (`git config tag.gpgSign true`).
273
-
274
- ### 8.2 Create the GitHub Release
275
-
276
- 1. <https://github.com/<owner>/<repo>/releases/new> → choose the tag
277
- just pushed.
278
- 2. **Title:** `v0.X.Y` (matches the tag, nothing fancier).
279
- 3. **Body:** paste the matching section from `CHANGELOG.md`. Strip the
280
- `## [X.Y.Z] - YYYY-MM-DD` heading line (it's redundant with the
281
- release title).
282
- 4. **Set as latest release** unless this is a pre-release. Pre-release
283
- tags (`-rc.N`, `-beta.N`, etc.) get the "Set as a pre-release"
284
- checkbox instead.
285
- 5. **Publish release.**
286
-
287
- ### 8.3 Production deploy (manual)
288
-
289
- There is **no CI auto-deploy to production**. The maintainer runs the
290
- prod deploy by hand, from a clean checkout on the tag:
291
-
292
- ```bash
293
- git checkout v0.X.Y
294
-
295
- # Sanity-check the tag matches the released commit.
296
- git log -1 --oneline # expect: chore(release): v0.X.Y
297
-
298
- pnpm install --frozen-lockfile
299
- pnpm build
300
- pnpm typecheck
301
- pnpm test
302
-
303
- # Deploy the Cloudflare Worker to production.
304
- pnpm deploy:cf:prod
305
- # → wrangler deploy (default env = production)
306
-
307
- # Tail prod logs while the first connections arrive.
308
- npx wrangler tail
309
-
310
- # Smoke-check prod with the same script CI uses on staging.
311
- # You must point it at the prod wss:// URL:
312
- node apps/cf-worker/scripts/smoke.mjs \
313
- --url wss://<prod-workers-subdomain>.workers.dev
314
- ```
315
-
316
- If smoke fails on prod:
317
-
318
- 1. **Do not roll forward blindly.** Tail logs, identify the regression.
319
- 2. If a rollback is required, follow §9.
320
- 3. If the regression is in the *deployed Worker code* (not the
321
- protocol core), a hotfix follows the same process as a normal
322
- release (new patch / minor → tag → GitHub Release → prod deploy).
323
-
324
- ### 8.4 Announce
325
-
326
- - Update `progress.md` Status header (if a "current release" marker
327
- was added there) — not currently present, optional.
328
- - Open an issue with the body "v0.X.Y released" if external tracking
329
- is desired. (Not currently wired to any external channel.)
330
-
331
- ---
332
-
333
- ## 9. Rollback
334
-
335
- There are two independent rollback axes: **code** and **data**.
336
-
337
- ### 9.1 Code rollback
338
-
339
- To redeploy a previous release:
340
-
341
- ```bash
342
- git checkout v0.W.Z # the previous tag
343
- pnpm install --frozen-lockfile
344
- pnpm build
345
- pnpm deploy:cf:prod
346
- ```
347
-
348
- This works as long as the previous release's code is compatible with
349
- the persisted DO state shape (see 9.2).
350
-
351
- There is no in-CI "prod rollback" workflow. The maintainer runs the
352
- commands above from a checkout.
353
-
354
- ### 9.2 Data rollback (persisted DO state)
355
-
356
- **Persisted-state version is one-way.** Once
357
- `packages/cf-adapter/src/serialize.ts` ships a new
358
- `PERSISTED_STATE_VERSION`, old code reading new blobs will reject
359
- them, and new code reading old blobs may or may not migrate them
360
- depending on whether a forward migration was shipped alongside.
361
-
362
- Rules of thumb:
363
-
364
- - If the release's `CHANGELOG.md` has **no ⚠️ Migration required**
365
- entry, code rollback to the previous tag is safe — DO storage is
366
- forward- and backward-compatible.
367
- - If it **does** have a migration entry, assume code rollback will
368
- not work without losing or transforming state. The migration entry
369
- in `CHANGELOG.md` must spell out the recovery procedure.
370
-
371
- In a catastrophic prod failure where the new version's migration
372
- already ran, the path forward is:
373
-
374
- 1. Freeze new connections (set `MOTD_LINES` to a maintenance banner,
375
- or block at the edge with a Route rule).
376
- 2. Decide: fix forward on the new code, or wipe staging-state (NOT
377
- prod-state) and re-test the migration offline.
378
- 3. **Production DO namespaces must never be deleted** — the data is
379
- gone permanently (per `docs/deployment-cf.md` §12.1).
380
-
381
- ---
382
-
383
- ## 10. Future: npm publish
384
-
385
- When `@serverless-ircd/irc-core` becomes the first package consumers
386
- outside this repo depend on (likely: the in-memory runtime is pulled
387
- into a third-party test harness, or someone ships an alternate
388
- adapter), the following gates apply before flipping `"private": false`:
389
-
390
- 1. **Public API audit.** Every export from `src/index.ts` is one we're
391
- willing to support across a minor. Anything experimental goes under
392
- a `/internal` subpath.
393
- 2. **Stable type surface.** No `any`, no `@ts-expect-error` in the
394
- public surface, no `exactOptionalPropertyTypes` surprises.
395
- 3. **README per package**, not just the root.
396
- 4. **`CHANGELOG.md` is already disciplined** (Keep a Changelog format,
397
- one section per version, dated).
398
- 5. **CI coverage gate ≥90%** (TICKET-048) is wired and green.
399
- 6. **Provenance & provenanced verification** — npm publish from CI
400
- with Sigstore signatures, not a local laptop.
401
-
402
- At that point this document grows a §11 "Publishing to npm" with
403
- `pnpm -r publish --filter @serverless-ircd/irc-core --access public`
404
- and a new `publish.yml` workflow. The git-tag-plus-GitHub-Release flow
405
- above stays unchanged — npm publish becomes an *additional* step, not
406
- a replacement.
407
-
408
- ---
409
-
410
- ## 11. Quick reference: cutting v0.X.Y
411
-
412
- ```bash
413
- # 1. Pre-release checklist (docs/release.md §4).
414
- git checkout main && git pull --ff-only origin main
415
- pnpm install --frozen-lockfile
416
- pnpm lint && pnpm typecheck && pnpm test && pnpm build
417
-
418
- # 2. Branch, bump versions + CHANGELOG, open PR (§6, §7).
419
- git checkout -b release/v0.X.Y
420
- # ... edit 8 × package.json + CHANGELOG.md ...
421
- git commit -am "chore(release): v0.X.Y"
422
- git push -u origin release/v0.X.Y
423
- # ... open PR, get it merged ...
424
-
425
- # 3. Tag and push (§8.1).
426
- git checkout main && git pull --ff-only origin main
427
- git tag -a v0.X.Y -m "v0.X.Y"
428
- git push origin v0.X.Y
429
-
430
- # 4. GitHub Release (§8.2): paste CHANGELOG entry, publish.
431
-
432
- # 5. Prod deploy (§8.3).
433
- git checkout v0.X.Y
434
- pnpm install --frozen-lockfile && pnpm build
435
- pnpm deploy:cf:prod
436
- node apps/cf-worker/scripts/smoke.mjs --url wss://<prod>.workers.dev
437
- ```
438
-
439
- Total wall-clock for a routine 0.x release: ~30 minutes including the
440
- prod deploy and smoke check.
package/progress.md DELETED
@@ -1,107 +0,0 @@
1
- # ServerlessIRCd — Progress
2
-
3
- Tickets derived from `PLAN.md` §7 (Phase 0 already complete). See
4
- `tickets.md` for full detail.
5
-
6
- | Status | Ticket | Points | Title |
7
- |:------:|:-------|-------:|:------|
8
- | ✅ | — | — | **Phase 0 — Foundation (DONE before ticketing)** |
9
- | ✅ | TICKET-001 | 5 | Core state shapes, `Effect` taxonomy, `dispatch` interpreter |
10
- | ✅ | TICKET-002 | 1 | `PING` / `PONG` reducer |
11
- | ✅ | TICKET-003 | 2 | `QUIT` reducer |
12
- | ✅ | TICKET-004 | 5 | Registration reducers: `NICK` / `USER` / `PASS` (core) |
13
- | ✅ | TICKET-005 | 5 | `JOIN` reducer |
14
- | ✅ | TICKET-006 | 2 | `PART` reducer |
15
- | ✅ | TICKET-007 | 3 | `PRIVMSG` / `NOTICE` reducer (channel + private) |
16
- | ✅ | TICKET-008 | 3 | `TOPIC` reducer |
17
- | ✅ | TICKET-009 | 2 | `NAMES` reducer |
18
- | ✅ | TICKET-010 | 1 | `MOTD` reducer |
19
- | ✅ | TICKET-011 | 8 | `MODE` reducer (channel + user) |
20
- | ✅ | TICKET-012 | 3 | `KICK` reducer |
21
- | ✅ | TICKET-013 | 3 | `INVITE` reducer |
22
- | ✅ | TICKET-014 | 3 | `WHO` reducer |
23
- | ✅ | TICKET-015 | 3 | `WHOIS` reducer |
24
- | ✅ | TICKET-016 | 2 | `LIST` reducer |
25
- | ✅ | TICKET-017 | 3 | IRCv3 `CAP` negotiation (`LS`/`REQ`/`ACK`/`NAK`/`END`/`LIST`/`NEW`/`DEL`) |
26
- | ✅ | TICKET-018 | 3 | IRCv3 `message-tags` + `server-time` |
27
- | ✅ | TICKET-019 | 1 | IRCv3 `echo-message` |
28
- | ✅ | TICKET-020 | 2 | IRCv3 `multi-prefix` |
29
- | ✅ | TICKET-021 | 1 | IRCv3 `extended-join` |
30
- | ✅ | TICKET-022 | 2 | IRCv3 `chghost` |
31
- | ✅ | TICKET-023 | 2 | IRCv3 `away-notify` |
32
- | ✅ | TICKET-024 | 1 | IRCv3 `invite-notify` |
33
- | ✅ | TICKET-025 | 5 | IRCv3 `batch` |
34
- | ✅ | TICKET-026 | 5 | SASL authentication (`PLAIN` via `AccountStore`, `EXTERNAL` stubbed) |
35
- | ✅ | TICKET-027 | 2 | `isupport` (`005`) generator |
36
- | ✅ | TICKET-028 | 3 | Flood control (token bucket) as pure reducer wrapper |
37
- | ✅ | TICKET-029 | 5 | Define `IrcRuntime` port; implement `in-memory-runtime` |
38
- | ✅ | TICKET-030 | 5 | `ConnectionActor`: bytes → framed messages → reducer → dispatch |
39
- | ✅ | TICKET-031 | 3 | `apps/local-cli`: runnable WebSocket server using in-memory runtime |
40
- | ✅ | TICKET-032 | 5 | Parametrized integration test suite over `IrcRuntime` |
41
- | ✅ | TICKET-033 | 8 | `ConnectionDO` (hibernatable WS), state migration, alarms |
42
- | ✅ | TICKET-034 | 5 | `RegistryDO` with sharding plan |
43
- | ✅ | TICKET-035 | 8 | `ChannelDO` (roster + modes + fanout via ConnectionDO stubs) |
44
- | ✅ | TICKET-036 | 5 | `CfRuntime` implementing `IrcRuntime` |
45
- | ✅ | TICKET-037 | 3 | Cloudflare deploy pipeline (wrangler), staging env, smoke e2e |
46
- | ✅ | TICKET-038 | 1 | Docs: `docs/deployment-cf.md` |
47
- | ✅ | TICKET-039 | 8 | CDK stack: APIGW WebSocket, Lambda, DynamoDB tables, IAM |
48
- | ✅ | TICKET-040 | 8 | `$connect` / `$disconnect` / `$default` handlers + `AwsRuntime` |
49
- | ✅ | TICKET-041 | 5 | DynamoDB transactions for membership; gone-connection sweep |
50
- | ✅ | TICKET-042 | 3 | EventBridge idle / PING timers |
51
- | ✅ | TICKET-043 | 3 | AWS deploy pipeline (CDK), staging env, smoke e2e |
52
- | ✅ | TICKET-044 | 1 | Docs: `docs/deployment-aws.md` |
53
- | ✅ | TICKET-045 | 3 | Observability: structured logs, trace IDs, dashboards |
54
- | ✅ | TICKET-046 | 5 | Security: server password, SASL, cloaking, rate limits, caps |
55
- | ✅ | TICKET-047 | 2 | Config: MOTD, server/network name, channel prefixes, max clients, oper creds |
56
- | ✅ | TICKET-048 | 3 | CI hardening: coverage gate ≥90%, contract tests on every PR, mutation testing |
57
- | ⬜ | TICKET-049 | 5 | Load test: 10k concurrent connections per platform |
58
- | ⬜ | TICKET-050 | 3 | Compatibility sweep: WeeChat, HexChat, IRCCloud, TheLounge, matrix-IRC bridge |
59
- | ⬜ | TICKET-051 | 2 | ADRs for irreversible decisions |
60
- | ⬜ | — | — | **Phase 7 — TLS hardening & raw TCP transport (v1.x)** |
61
- | ⬜ | TICKET-052 | 2 | Revise transport decision: dual wss + irc+tls (ADR); update PLAN §3/§9 |
62
- | ⬜ | TICKET-053 | 3 | Generalize `ConnectionActor` transport seam (TCP byte-stream framing) |
63
- | ⬜ | TICKET-054 | 5 | mTLS support: edge config + `AccountStore` plumbing (enables SASL EXTERNAL) |
64
- | ⬜ | TICKET-055 | 8 | CF TCP+TLS adapter via Cloudflare Spectrum + Container origin |
65
- | ⬜ | TICKET-056 | 8 | AWS TCP+TLS adapter via Network Load Balancer (TLS) + Lambda streaming |
66
- | ⬜ | TICKET-057 | 3 | Extend integration contract suite over transport (wss × TCP+TLS) |
67
- | ⬜ | TICKET-058 | 2 | Docs: `deployment-cf-tcp.md` and `deployment-aws-tcp.md` (TCP+TLS variants) |
68
- | ✅ | TICKET-059 | 2 | Wire `WHOIS` into the `ConnectionActor` dispatcher |
69
- | ✅ | TICKET-060 | 1 | Wire `AUTHENTICATE` into the `ConnectionActor` dispatcher |
70
- | ✅ | TICKET-061 | 1 | Wire `AWAY` into the `ConnectionActor` dispatcher |
71
- | ✅ | TICKET-062 | 1 | IRCv3 `safelist` capability + `SAFELIST` ISUPPORT token |
72
- | ✅ | TICKET-063 | 8 | IRCv3 `draft/chathistory` playback (bouncer-style backlog on JOIN + explicit query) |
73
- | ✅ | TICKET-064 | 2 | Flood control: per-command cost + control-plane exemption |
74
- | ✅ | TICKET-065 | 3 | Wire `wrapWithFloodControl` into the `ConnectionActor` |
75
- | ✅ | TICKET-066 | 3 | CDK `environmentName` parameter + prefixed resource names |
76
- | ✅ | TICKET-067 | 1 | Fix MOTD parsing mismatch (CDK default vs config loader) |
77
- | ✅ | TICKET-068 | 2 | Make hardcoded stack identity vars configurable via construct props |
78
-
79
- | ✅ | TICKET-069 | 3 | Wire `CHATHISTORY` into the `ConnectionActor` dispatcher + `MessageStore` plumbing |
80
- | ⬜ | — | — | **Phase 8 — PLAN-FIXES Remediation** |
81
- | ✅ | TICKET-070 | 5 | Wire `MessageStore` into all three adapters (chathistory end-to-end) |
82
- | ⬜ | TICKET-071 | 8 | Wire `AccountStore` into the `ConnectionActor` (SASL PLAIN end-to-end) |
83
- | ⬜ | TICKET-072 | 8 | Decide fate of AWS `Accounts` DynamoDB table (implement AccountStore or remove) |
84
- | ⬜ | TICKET-073 | 13 | Cloudflare runtime: implement stubbed `getConnection`/`getChannelConnections`/`listChannels`/cross-connection `disconnect` |
85
- | ⬜ | TICKET-074 | 5 | AWS disconnect: broadcast QUIT to peers |
86
- | ⬜ | TICKET-075 | 5 | Implement `OPER` command (verify creds, set oper mode, emit `381`) |
87
- | ⬜ | TICKET-076 | 3 | Implement `TAGMSG` command (IRCv3 `message-tags` recorder) |
88
- | ⬜ | TICKET-077 | 5 | Implement `WHOWAS` (or drop the numerics) |
89
- | ⬜ | TICKET-078 | 5 | Implement (or drop) remaining standard IRC verbs |
90
- | ⬜ | TICKET-079 | 2 | SASL `EXTERNAL`: implement mTLS-backed auth OR stop advertising |
91
- | ⬜ | TICKET-080 | 2 | Welcome MOTD: drive from `MotdProvider` instead of hardcoded placeholder |
92
- | ⬜ | TICKET-081 | 3 | Registration placeholders: drive `SERVER_VERSION`/`CREATED_TEXT` from `ServerConfig` |
93
- | ⬜ | TICKET-082 | 3 | Require `serverName` at adapter config-load (drop `irc.example.com` placeholder) |
94
- | ⬜ | TICKET-083 | 5 | AWS `handleConnect`: implement max-clients admission gating |
95
- | ⬜ | TICKET-084 | 1 | AWS Lambda transport `disconnect` no-op: document the platform limit |
96
- | ⬜ | TICKET-085 | 2 | CF `webSocketMessage` channel-registration: wire ChannelDO registration OR remove dead loop |
97
- | ⬜ | TICKET-086 | 2 | Remove (or wire) dead lookup Effects: `LookupNick`, `GetConnectionInfo`, `GetChannelSnapshot` |
98
- | ⬜ | TICKET-087 | 2 | CF outbound batching: implement OR drop the reserved optimization |
99
- | ⬜ | TICKET-088 | 2 | Update stale doc-comments advertising DOs as stubbed |
100
- | ⬜ | TICKET-089 | 5 | Implement rfc1459 case-mapping (replace ad-hoc `toLowerCase`) |
101
- | ⬜ | TICKET-090 | 1 | Remove unused `_disabledRecordId()` helper |
102
- | ⬜ | TICKET-091 | 1 | Update stale CLI doc comment ("fuller config-loader lands in a later ticket") |
103
- | ⬜ | TICKET-092 | 1 | Update stale release-process doc (90% coverage gate IS wired in CI) |
104
-
105
- **Totals:** 92 tickets · 322 points
106
-
107
- **Status legend:** ⬜ pending · 🔄 in-progress · ✅ done · 🚫 blocked