serverless-ircd 0.2.0 → 0.3.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 (134) hide show
  1. package/CHANGELOG.md +84 -0
  2. package/README.md +28 -19
  3. package/apps/cf-worker/package.json +1 -1
  4. package/apps/cf-worker/scripts/smoke.mjs +0 -0
  5. package/apps/cf-worker/src/worker.ts +8 -2
  6. package/apps/cf-worker/tests/smoke.test.ts +1 -0
  7. package/apps/cf-worker/wrangler.test.toml +5 -1
  8. package/apps/cf-worker/wrangler.toml +41 -17
  9. package/apps/local-cli/package.json +1 -1
  10. package/apps/local-cli/src/config-loader.ts +1 -0
  11. package/apps/local-cli/src/main.ts +1 -1
  12. package/apps/local-cli/src/server.ts +28 -2
  13. package/apps/local-cli/tests/e2e.test.ts +52 -0
  14. package/docs/ADR-001-pure-reducers-and-effect-system.md +74 -0
  15. package/docs/ADR-002-location-of-authority.md +82 -0
  16. package/docs/ADR-003-durable-object-sharding.md +93 -0
  17. package/docs/ADR-004-dynamodb-schema.md +96 -0
  18. package/docs/ADR-005-wss-only-transport-v1.md +83 -0
  19. package/docs/ADR-006-sasl-mechanism-scope.md +86 -0
  20. package/docs/ADR-007-deterministic-ports.md +82 -0
  21. package/docs/ADR-008-monorepo-tooling.md +60 -0
  22. package/docs/AWS-Adapter-Architecture.md +6 -4
  23. package/docs/AWS-Deployment.md +86 -7
  24. package/docs/Cloudflare-Deployment-Guide.md +5 -5
  25. package/docs/Home.md +11 -1
  26. package/docs/Release-Process.md +9 -6
  27. package/package.json +14 -15
  28. package/packages/aws-adapter/package.json +1 -1
  29. package/packages/aws-adapter/src/account-store.ts +121 -0
  30. package/packages/aws-adapter/src/aws-runtime.ts +118 -30
  31. package/packages/aws-adapter/src/cdk-table-defs.ts +5 -1
  32. package/packages/aws-adapter/src/config-loader.ts +30 -0
  33. package/packages/aws-adapter/src/dynamo-account-store.ts +156 -0
  34. package/packages/aws-adapter/src/handlers/default.ts +8 -0
  35. package/packages/aws-adapter/src/handlers/disconnect.ts +27 -8
  36. package/packages/aws-adapter/src/handlers/index.ts +51 -6
  37. package/packages/aws-adapter/src/index.ts +7 -0
  38. package/packages/aws-adapter/tests/account-store-dynamo.test.ts +171 -0
  39. package/packages/aws-adapter/tests/account-store.test.ts +280 -0
  40. package/packages/aws-adapter/tests/config-loader.test.ts +55 -0
  41. package/packages/aws-adapter/tests/disconnect-fanout.test.ts +336 -0
  42. package/packages/aws-adapter/tests/handlers.test.ts +46 -0
  43. package/packages/cf-adapter/package.json +1 -1
  44. package/packages/cf-adapter/src/cf-runtime.ts +42 -22
  45. package/packages/cf-adapter/src/channel-do.ts +40 -1
  46. package/packages/cf-adapter/src/channel-registry-do.ts +58 -0
  47. package/packages/cf-adapter/src/config-loader.ts +29 -0
  48. package/packages/cf-adapter/src/connection-do.ts +85 -0
  49. package/packages/cf-adapter/src/env.ts +27 -1
  50. package/packages/cf-adapter/src/index.ts +2 -1
  51. package/packages/cf-adapter/tests/cf-runtime.test.ts +91 -0
  52. package/packages/cf-adapter/tests/connection-do.test.ts +40 -0
  53. package/packages/cf-adapter/tests/worker/main.ts +2 -1
  54. package/packages/cf-adapter/tests/worker/stubs/channel-stub.ts +7 -1
  55. package/packages/cf-adapter/wrangler.test.toml +10 -1
  56. package/packages/in-memory-runtime/package.json +1 -1
  57. package/packages/in-memory-runtime/src/in-memory-runtime.ts +14 -28
  58. package/packages/in-memory-runtime/tests/in-memory-runtime.test.ts +19 -0
  59. package/packages/irc-core/package.json +3 -2
  60. package/packages/irc-core/src/case-fold.ts +64 -0
  61. package/packages/irc-core/src/commands/index.ts +2 -0
  62. package/packages/irc-core/src/commands/invite.ts +6 -9
  63. package/packages/irc-core/src/commands/isupport.ts +1 -1
  64. package/packages/irc-core/src/commands/join.ts +4 -3
  65. package/packages/irc-core/src/commands/kick.ts +4 -11
  66. package/packages/irc-core/src/commands/list.ts +5 -4
  67. package/packages/irc-core/src/commands/mode.ts +5 -9
  68. package/packages/irc-core/src/commands/motd-lines.ts +127 -0
  69. package/packages/irc-core/src/commands/motd.ts +6 -110
  70. package/packages/irc-core/src/commands/oper.ts +151 -0
  71. package/packages/irc-core/src/commands/registration.ts +8 -7
  72. package/packages/irc-core/src/commands/tagmsg.ts +205 -0
  73. package/packages/irc-core/src/config.ts +26 -3
  74. package/packages/irc-core/src/index.ts +2 -0
  75. package/packages/irc-core/src/ports.ts +68 -4
  76. package/packages/irc-core/src/types.ts +22 -0
  77. package/packages/irc-core/tests/account-store.test.ts +88 -0
  78. package/packages/irc-core/tests/case-fold.test.ts +80 -0
  79. package/packages/irc-core/tests/commands/kick.test.ts +15 -0
  80. package/packages/irc-core/tests/commands/oper.test.ts +257 -0
  81. package/packages/irc-core/tests/commands/registration.test.ts +106 -14
  82. package/packages/irc-core/tests/commands/tagmsg.test.ts +688 -0
  83. package/packages/irc-core/tests/commands/who.test.ts +22 -4
  84. package/packages/irc-core/tests/commands/whois.test.ts +8 -1
  85. package/packages/irc-core/tests/config.test.ts +75 -0
  86. package/packages/irc-server/package.json +1 -1
  87. package/packages/irc-server/src/actor.ts +24 -0
  88. package/packages/irc-server/src/routing.ts +9 -0
  89. package/packages/irc-server/tests/actor.test.ts +220 -1
  90. package/packages/irc-server/tests/routing.test.ts +3 -0
  91. package/packages/irc-test-support/package.json +1 -1
  92. package/packages/irc-test-support/src/in-memory-harness.ts +5 -4
  93. package/pnpm-workspace.yaml +1 -0
  94. package/tools/seed-aws-accounts.ts +80 -0
  95. package/AGENTS.md +0 -5
  96. package/MOTD.txt +0 -3
  97. package/PLAN-FIXES.md +0 -358
  98. package/PLAN.md +0 -420
  99. package/dashboards/cloudwatch-irc.json +0 -139
  100. package/progress.md +0 -107
  101. package/tickets.md +0 -2485
  102. package/webircgateway/LICENSE +0 -201
  103. package/webircgateway/Makefile +0 -44
  104. package/webircgateway/README.md +0 -134
  105. package/webircgateway/config.conf.example +0 -135
  106. package/webircgateway/go.mod +0 -16
  107. package/webircgateway/go.sum +0 -89
  108. package/webircgateway/main.go +0 -118
  109. package/webircgateway/pkg/dnsbl/dnsbl.go +0 -121
  110. package/webircgateway/pkg/identd/identd.go +0 -86
  111. package/webircgateway/pkg/identd/rpcclient.go +0 -59
  112. package/webircgateway/pkg/irc/isupport.go +0 -56
  113. package/webircgateway/pkg/irc/message.go +0 -217
  114. package/webircgateway/pkg/irc/state.go +0 -79
  115. package/webircgateway/pkg/proxy/proxy.go +0 -129
  116. package/webircgateway/pkg/proxy/server.go +0 -237
  117. package/webircgateway/pkg/recaptcha/recaptcha.go +0 -59
  118. package/webircgateway/pkg/webircgateway/client.go +0 -741
  119. package/webircgateway/pkg/webircgateway/client_command_handlers.go +0 -495
  120. package/webircgateway/pkg/webircgateway/config.go +0 -385
  121. package/webircgateway/pkg/webircgateway/gateway.go +0 -278
  122. package/webircgateway/pkg/webircgateway/gateway_utils.go +0 -133
  123. package/webircgateway/pkg/webircgateway/hooks.go +0 -152
  124. package/webircgateway/pkg/webircgateway/letsencrypt.go +0 -41
  125. package/webircgateway/pkg/webircgateway/messagetags.go +0 -103
  126. package/webircgateway/pkg/webircgateway/transport_kiwiirc.go +0 -206
  127. package/webircgateway/pkg/webircgateway/transport_sockjs.go +0 -107
  128. package/webircgateway/pkg/webircgateway/transport_tcp.go +0 -113
  129. package/webircgateway/pkg/webircgateway/transport_websocket.go +0 -126
  130. package/webircgateway/pkg/webircgateway/utils.go +0 -147
  131. package/webircgateway/plugins/example/plugin.go +0 -11
  132. package/webircgateway/plugins/stats/plugin.go +0 -52
  133. package/webircgateway/staticcheck.conf +0 -1
  134. package/webircgateway/webircgateway.svg +0 -3
@@ -0,0 +1,80 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Seed SASL PLAIN accounts into the DynamoDB `Accounts` table.
4
+ *
5
+ * Usage:
6
+ * node --import tsx tools/seed-aws-accounts.ts \
7
+ * --table StagingAccounts \
8
+ * --endpoint http://localhost:8000 \
9
+ * --accounts alice:s3cret bob:password2
10
+ *
11
+ * Or read from a file (newline-delimited `username:password`):
12
+ * node --import tsx tools/seed-aws-accounts.ts \
13
+ * --table StagingAccounts \
14
+ * --file accounts.txt
15
+ *
16
+ * The script hashes each password with scrypt (never writes plaintext).
17
+ * Re-running with the same username overwrites the prior row.
18
+ */
19
+
20
+ import { parseArgs } from 'node:util';
21
+ import { readFileSync } from 'node:fs';
22
+ import {
23
+ createDynamoDocumentClient,
24
+ putAccountCredential,
25
+ } from '@serverless-ircd/aws-adapter';
26
+
27
+ const { values } = parseArgs({
28
+ options: {
29
+ table: { type: 'string' },
30
+ endpoint: { type: 'string', default: undefined },
31
+ region: { type: 'string', default: undefined },
32
+ accounts: { type: 'string', multiple: true, default: [] },
33
+ file: { type: 'string', default: undefined },
34
+ },
35
+ });
36
+
37
+ if (values.table === undefined) {
38
+ console.error('Usage: seed-aws-accounts --table <TableName> [--endpoint <url>] [--accounts user:pass ...] [--file <path>]');
39
+ process.exit(1);
40
+ }
41
+
42
+ const clientOptions: Record<string, string> = {};
43
+ if (values.endpoint !== undefined) clientOptions.endpoint = values.endpoint;
44
+ if (values.region !== undefined) clientOptions.region = values.region;
45
+
46
+ const docClient = createDynamoDocumentClient(clientOptions);
47
+
48
+ const pairs: Array<{ username: string; password: string }> = [];
49
+
50
+ for (const pair of values.accounts) {
51
+ const sep = pair.indexOf(':');
52
+ if (sep <= 0) {
53
+ console.error(`Skipping malformed entry (no colon): ${pair}`);
54
+ continue;
55
+ }
56
+ pairs.push({ username: pair.slice(0, sep), password: pair.slice(sep + 1) });
57
+ }
58
+
59
+ if (values.file !== undefined) {
60
+ const content = readFileSync(values.file, 'utf-8');
61
+ for (const line of content.split('\n')) {
62
+ const trimmed = line.trim();
63
+ if (trimmed.length === 0) continue;
64
+ const sep = trimmed.indexOf(':');
65
+ if (sep <= 0) continue;
66
+ pairs.push({ username: trimmed.slice(0, sep), password: trimmed.slice(sep + 1) });
67
+ }
68
+ }
69
+
70
+ if (pairs.length === 0) {
71
+ console.error('No accounts to seed. Use --accounts or --file.');
72
+ process.exit(1);
73
+ }
74
+
75
+ for (const { username, password } of pairs) {
76
+ const entry = await putAccountCredential(docClient, values.table, username, password);
77
+ console.log(`Seeded ${username} (algorithm=${entry.algorithm})`);
78
+ }
79
+
80
+ console.log(`Done: ${pairs.length} account(s) written to ${values.table}.`);
package/AGENTS.md DELETED
@@ -1,5 +0,0 @@
1
- # AGENTS.md
2
-
3
- ## Code Style
4
-
5
- - **Do not reference ticket IDs in source files.** Never put `TICKET-###` or similar ticket-tracker tokens in `.ts` or `.js` files (code or comments). Describe the intent or cross-reference by feature/command name instead. Ticket tracking lives in `progress.md` / `tickets.md`, not in source.
package/MOTD.txt DELETED
@@ -1,3 +0,0 @@
1
- Welcome to the test network for Serverless IRCd project.
2
-
3
- Join #general for chat.
package/PLAN-FIXES.md DELETED
@@ -1,358 +0,0 @@
1
- # PLAN-FIXES.md
2
-
3
- Audit of stubbed, incomplete, and not-fully-wired-up functionality in ServerlessIRCd.
4
- Each item lists location, current behavior, expected behavior, and impact.
5
-
6
- Findings are grouped by severity: **Critical** > **Partial** > **Minor / Dead scaffolding**.
7
-
8
- ---
9
-
10
- ## Critical
11
-
12
- ### 1. `MessageStore` (IRCv3 `draft/chathistory`) wired into no adapter
13
-
14
- `ConnectionActor` accepts `messages?: MessageStore` (`packages/irc-server/src/actor.ts:105`),
15
- and `irc-core` ships a complete `InMemoryMessageStore`, the `CHATHISTORY` reducer, and
16
- JOIN auto-playback. None of the three adapters pass it:
17
-
18
- - `packages/cf-adapter/src/connection-do.ts:303-312`
19
- - `packages/aws-adapter/src/handlers/default.ts:103-111`
20
- - `apps/local-cli/src/server.ts:480-501`
21
-
22
- **Impact:** chathistory recording and playback are dead code outside unit tests.
23
- `ctx.messages` is always `undefined` in any deployment.
24
-
25
- **Fix:** construct and pass a `MessageStore` instance at each actor-construction site.
26
-
27
- ---
28
-
29
- ### 2. `AccountStore` (SASL) not accepted by the actor
30
-
31
- `ConnectionActorOptions` (`packages/irc-server/src/actor.ts:89-119`) has **no `accounts`**
32
- field, and `route()` -> `buildCtx()` (`actor.ts:238-245`) never supplies one, even though
33
- `buildCtx` supports it (`packages/irc-core/src/types.ts:143`).
34
-
35
- **Impact:** SASL PLAIN authentication can never succeed in any adapter. A client completing
36
- `AUTHENTICATE PLAIN` always receives `904 ERR_SASLFAIL` because `ctx.accounts` is `undefined`.
37
- Only unit tests (which call `buildCtx` directly) exercise the happy path.
38
-
39
- **Fix:** add `accounts?: AccountStore` to `ConnectionActorOptions`, forward it through
40
- `route()` into `buildCtx`, and supply an implementation in each adapter.
41
-
42
- ---
43
-
44
- ### 3. Cloudflare runtime stubs (`packages/cf-adapter/src/cf-runtime.ts`)
45
-
46
- The AWS runtime fully implements all 16 `IrcRuntime` methods against DynamoDB. The CF
47
- runtime has explicit stubs that break three commands for anything beyond the local connection.
48
-
49
- | Method | Line | Stub | Impact |
50
- |---|---|---|---|
51
- | `getConnection()` | cf-runtime.ts:234-244 | returns `null` for remote conns | Remote WHOIS broken (only `401` + `318`) |
52
- | `getChannelConnections()` | cf-runtime.ts:246-251 | returns empty `Map` | WHO broken on CF |
53
- | `listChannels()` | cf-runtime.ts:253-258 | returns `[]` | LIST returns no channels on CF |
54
- | `disconnect()` | cf-runtime.ts:115-126 | cross-connection disconnect is a no-op | KICK of a remote user does not close their socket |
55
-
56
- **Fix:** add the missing ConnectionDO RPCs (`getConnState`, channel-membership enumeration,
57
- channel registry) and a cross-connection `disconnect` RPC; wire `cf-runtime.ts` to call them.
58
-
59
- ---
60
-
61
- ### 4. AWS disconnect never broadcasts QUIT to peers
62
-
63
- `packages/aws-adapter/src/aws-runtime.ts:645` -- `cleanupConnection` explicitly discards
64
- `managementApi` (`void managementApi;`) and never broadcasts QUIT. Confirmed at the call
65
- site: `packages/aws-adapter/src/handlers/disconnect.ts:28` hardcodes `null`.
66
-
67
- **Impact:** when a connection tears down, peers in shared channels never receive the QUIT
68
- fanout. Their local rosters go stale until a subsequent broadcast prunes the ghost member.
69
-
70
- **Fix:** thread the `managementApi` through `handleDisconnect` and implement QUIT fanout
71
- to all connections sharing channels with the disconnecting client.
72
-
73
- ---
74
-
75
- ### 5. AWS `Accounts` DynamoDB table deployed with no runtime consumer
76
-
77
- Provisioned in CDK (`packages/aws-adapter/src/cdk-table-defs.ts:61-65`) and required by
78
- `tablesConfigFromNames`, but no runtime code reads or writes it. No `AccountStore`
79
- implementation is backed by it.
80
-
81
- **Impact:** paid-for infrastructure with no consumer; also blocks SASL account persistence
82
- (see #2).
83
-
84
- **Fix:** either implement a DynamoDB-backed `AccountStore` against this table, or remove
85
- the table from the CDK stack and config loader until it is needed.
86
-
87
- ---
88
-
89
- ## Absent IRC commands (scaffolded or advertised, no handler)
90
-
91
- Implemented reducers (JOIN/PART/TOPIC/NAMES/KICK/INVITE/MOTD/PRIVMSG/NOTICE/MODE/LIST/
92
- WHO/WHOIS/CAP/AUTHENTICATE/AWAY/CHATHISTORY) are genuinely complete. The gaps below either
93
- fall through to `421 ERR_UNKNOWNCOMMAND` or have partial scaffolding.
94
-
95
- ### 6. `OPER` -- absent, but heavily scaffolded
96
-
97
- No `OPER` case in `actor.ts` `route()` switch, no reducer, no entry in
98
- `packages/irc-core/src/commands/index.ts`. Referenced everywhere:
99
-
100
- - `packages/irc-core/src/commands/mode.ts:15` -- "The oper flag (`+o`) is granted via the
101
- future OPER command, not via MODE"
102
- - `packages/irc-core/src/commands/mode.ts:547,612-624` -- user `MODE +o` hard-rejected
103
- with `481 ERR_NOPRIVILEGES`, gated on an OPER command that does not exist.
104
- - `operCreds` is defined, validated, and loaded by **all three adapters**
105
- (`packages/cf-adapter/src/config-loader.ts:65`,
106
- `packages/aws-adapter/src/config-loader.ts:59`,
107
- `apps/local-cli/src/config-loader.ts:27`) but no runtime code ever reads
108
- `serverConfig.operCreds`.
109
- - Reserved-but-unused numerics: `RPL_YOUREOPER: 381`, `RPL_REHASHING: 382`,
110
- `ERR_NOOPERHOST: 491` (`packages/irc-core/src/numerics.ts:75-76,138`).
111
-
112
- **Impact:** `state.userModes.oper` can never become `true` via any command flow, so the
113
- `RPL_WHOISOPERATOR` (`313`) branch in `packages/irc-core/src/commands/whois.ts:132-136`
114
- and the WHO `*` oper flag (`packages/irc-core/src/commands/who.ts:69`) are unreachable.
115
-
116
- **Fix:** implement the `OPER` reducer (verify credentials against `operCreds`, set the
117
- `oper` user mode, emit `381`), add it to the route switch, and wire the dependent
118
- WHOIS/WHO branches.
119
-
120
- ---
121
-
122
- ### 7. `TAGMSG` -- replay path exists, no recorder
123
-
124
- `StoredCommand = 'PRIVMSG' | 'NOTICE' | 'TAGMSG'` (`packages/irc-core/src/ports.ts:200`)
125
- and `packages/irc-core/src/commands/chathistory.ts:237-238` contain real replay code for
126
- a stored TAGMSG. But nothing ever records one: the only call to `ctx.messages.record(...)`
127
- is `packages/irc-core/src/commands/privmsg.ts:188`, which records `PRIVMSG`/`NOTICE` only.
128
-
129
- **Impact:** the `message-tags` cap is advertised (`packages/irc-core/src/caps/capabilities.ts:33`)
130
- with no command that consumes it. The TAGMSG replay branch is dead code.
131
-
132
- **Fix:** add a `TAGMSG` reducer + route case that records the message-tag set via
133
- `ctx.messages.record({ command: 'TAGMSG', ... })`.
134
-
135
- ---
136
-
137
- ### 8. `WHOWAS` -- numerics present, no handler
138
-
139
- `RPL_ENDOFWHOWAS: 369`, `ERR_WASNOSUCHNICK: 406` defined
140
- (`packages/irc-core/src/numerics.ts:65,97`); no reducer, no route case.
141
-
142
- **Fix:** implement a `WHOWAS` reducer against the nick history (or decide to drop the
143
- numerics if the feature is not planned).
144
-
145
- ---
146
-
147
- ### 9. Other unimplemented standard verbs
148
-
149
- Currently return `421 ERR_UNKNOWNCOMMAND` via `actor.ts:318-319` (graceful, not broken):
150
-
151
- `VERSION`, `ADMIN`, `INFO`, `TIME`, `STATS`, `LUSERS`, `LINKS`, `USERHOST`, `ISON`,
152
- `WALLOPS`, `SETNAME`, `KILL`, `REHASH`, `CONNECT`, `TRACE`, `SQUIT`, `SERVICE`,
153
- `SUMMON`, `USERS`.
154
-
155
- Several have dedicated numerics defined but unused (`RPL_USERHOST: 302`, `RPL_ISON: 303`,
156
- `RPL_INFO: 371`, `RPL_LINKS: 364`, `RPL_TIME: 391`, `RPL_ADMINME: 256`).
157
-
158
- **Fix:** implement the subset that matters for client compatibility, or remove unused
159
- numerics to avoid advertising false capability.
160
-
161
- ---
162
-
163
- ## Partial
164
-
165
- ### 10. SASL `EXTERNAL` -- hardcoded to fail
166
-
167
- `packages/irc-core/src/commands/sasl.ts:95-97` recognizes `AUTHENTICATE EXTERNAL` but
168
- unconditionally returns `904 ERR_SASLFAIL`. The `sasl` cap advertises `PLAIN,EXTERNAL`
169
- (`packages/irc-core/src/caps/capabilities.ts:36`,
170
- `packages/irc-core/src/commands/sasl.ts:42` `SUPPORTED_MECHS = 'PLAIN,EXTERNAL'`).
171
-
172
- **Impact:** EXTERNAL is advertised but non-functional. (PLAIN is fully implemented but
173
- see #2.)
174
-
175
- **Fix:** either implement EXTERNAL (mTLS client-cert extraction), or stop advertising it
176
- in `SUPPORTED_MECHS` until it lands.
177
-
178
- ---
179
-
180
- ### 11. Welcome MOTD is a hardcoded placeholder
181
-
182
- `packages/irc-core/src/commands/registration.ts:84-87` always emits:
183
-
184
- ```
185
- 375 <nick> :- <server> Message of the day -
186
- 372 <nick> :- MOTD placeholder
187
- 376 <nick> :End of MOTD command
188
- ```
189
-
190
- regardless of the configured `MotdProvider`. The comment claims "filled via MotdProvider
191
- elsewhere" but it is not. The standalone `MOTD` command correctly uses `ctx.motd.lines()`
192
- (`packages/irc-core/src/commands/motd.ts:59`).
193
-
194
- **Impact:** every client sees `372 <nick> :- MOTD placeholder` on connect regardless of
195
- configuration.
196
-
197
- **Fix:** call `ctx.motd.lines()` in `buildWelcomeLines` and emit the real lines.
198
-
199
- ---
200
-
201
- ### 12. Placeholder constants in registration
202
-
203
- `packages/irc-core/src/commands/registration.ts:29,32`:
204
-
205
- - `SERVER_VERSION = '0.1.0'` -- "Placeholder until a config-driven version lands"
206
- - `CREATED_TEXT = 'Phase 1'` -- "Placeholder"
207
-
208
- Surfaced verbatim in `002`/`003`/`004` replies.
209
-
210
- **Fix:** drive these from `ServerConfig` (read `package.json` version at build time, or
211
- add `serverVersion`/`createdAt` config fields).
212
-
213
- ---
214
-
215
- ### 13. `DEFAULT_SERVER_CONFIG` ships a placeholder server name
216
-
217
- `packages/irc-core/src/config.ts:244-247` -- `serverName: 'irc.example.com'` as the
218
- baseline. Documented as a boot/test baseline that adapters overlay, and
219
- `docs/AWS-Deployment.md:414` warns "(placeholder -- override!)".
220
-
221
- **Impact:** if a deployment forgets to override, the server advertises `irc.example.com`.
222
-
223
- **Fix:** require `serverName` at adapter config-load time (fail fast if unset) rather
224
- than relying on a placeholder default.
225
-
226
- ---
227
-
228
- ### 14. AWS `handleConnect` ignores `serverConfig`
229
-
230
- `packages/aws-adapter/src/handlers/connect.ts:36` -- `void params.serverConfig;`
231
- ("reserved for max-clients gating").
232
-
233
- **Impact:** connection-count admission gating at connect time is unimplemented.
234
-
235
- **Fix:** implement max-clients admission using the supplied config.
236
-
237
- ---
238
-
239
- ### 15. AWS Lambda transport `disconnect` is a no-op
240
-
241
- `packages/aws-adapter/src/handlers/default.ts:86-89` -- `AwsRuntimeHandlers.disconnect`
242
- does nothing. Documented as a platform limit (a Lambda cannot close its own APIGW socket;
243
- the canonical close is the `$disconnect` route).
244
-
245
- **Impact:** effect-driven `Disconnect` on the bound connection never reaches the transport
246
- from within a `$default` invocation.
247
-
248
- **Fix:** documented platform limitation; no code fix possible without an APIGW feature.
249
- Consider noting this in operator docs.
250
-
251
- ---
252
-
253
- ### 16. CF `webSocketMessage` newly-joined-channel registration is a no-op
254
-
255
- `packages/cf-adapter/src/connection-do.ts:150-156` -- the loop body is `void chan;`.
256
-
257
- **Impact:** no real channel-registration work happens on join beyond the
258
- `ApplyChannelDelta` already emitted by the reducer.
259
-
260
- **Fix:** wire channel-DO registration here, or remove the dead loop.
261
-
262
- ---
263
-
264
- ## Minor / Dead scaffolding
265
-
266
- ### 17. Three lookup Effect variants are dead
267
-
268
- `LookupNick`, `GetConnectionInfo`, `GetChannelSnapshot` are defined in
269
- `packages/irc-core/src/effects.ts:74-87` and `:170-178` (and included in the `Effect`
270
- union at `:112-114`), but their dispatch results are discarded via `noop`
271
- (`packages/irc-server/src/dispatch.ts:36-38`) and no reducer ever emits them. The
272
- runtime methods they wrap (`lookupNick`/`getConnectionInfo`/`getChannelSnapshot`) are
273
- used elsewhere, so only the Effect path is dead.
274
-
275
- **Fix:** either wire these effects to real consumers, or remove the variants and their
276
- dispatch arms.
277
-
278
- ---
279
-
280
- ### 18. CF outbound batching optimization reserved/disabled
281
-
282
- `packages/cf-adapter/src/connection-do.ts:100-101` -- a field for batching outbound line
283
- drains is commented out, explicitly deferred.
284
-
285
- **Fix:** implement the batching optimization, or drop the reserved comment.
286
-
287
- ---
288
-
289
- ### 19. Stale doc-comments advertise DOs as stubbed
290
-
291
- `packages/cf-adapter/src/env.ts:23-36` -- still describes `REGISTRY_DO` as
292
- "Stubbed now (033); real impl in 034" and `CHANNEL_DO` as "Stubbed now; real in 035",
293
- even though `registry-do.ts` and `channel-do.ts` now contain real implementations.
294
-
295
- `packages/cf-adapter/src/connection-do.ts:148-153, 291-293, 337-338, 504-506, 549` contain
296
- similar stale "stub" language; `:546-549` exports `applyChannelDelta` purely to keep an
297
- import used by tests.
298
-
299
- **Fix:** update comments to reflect the implemented state; drop the test-only re-export
300
- or move it behind a test boundary.
301
-
302
- ---
303
-
304
- ### 20. Case-mapping mismatch vs. advertised ISUPPORT
305
-
306
- `packages/irc-core/src/isupport.ts:43` advertises `CASEMAPPING=rfc1459`, but
307
- `packages/irc-core/src/commands/kick.ts:57-60` (and the duplicated `lowerNick`/`lower`
308
- helpers in `mode.ts`, `invite.ts`, `join.ts`, `packages/in-memory-runtime/src/in-memory-runtime.ts`)
309
- use bare ASCII `toLowerCase()`. The advertised case-mapping and the actual folding diverge
310
- for the `[]\^` special chars.
311
-
312
- **Fix:** implement rfc1459 case folding in a single shared helper and use it everywhere.
313
-
314
- ---
315
-
316
- ### 21. `_disabledRecordId()` generates IDs never consulted
317
-
318
- `packages/in-memory-runtime/src/in-memory-runtime.ts:61-69` -- mints admission record ids
319
- whose own doc comment states "The id is never consulted (no `AdmissionStats` exists)."
320
- Called at `:116` when admission is disabled; the returned `recordId` flows nowhere.
321
-
322
- **Fix:** remove the helper and its call site, or implement the `AdmissionStats` consumer.
323
-
324
- ---
325
-
326
- ### 22. Stale CLI doc comment
327
-
328
- `apps/local-cli/src/main.ts:17` -- "a fuller config-loader lands in a later ticket."
329
- `apps/local-cli/src/config-loader.ts` already exists and fully validates via
330
- `ServerConfigSchema`.
331
-
332
- **Fix:** update the comment.
333
-
334
- ---
335
-
336
- ### 23. Stale release-process doc
337
-
338
- `docs/Release-Process.md:114` -- "the 90% coverage gate (TICKET-048) is not yet wired in CI."
339
- `.github/workflows/ci.yml:57-60` shows the gate **is** wired and enforced per package
340
- (100% on irc-core/irc-server/in-memory-runtime, >=90% elsewhere).
341
-
342
- **Fix:** update the doc to reflect the enforced gate.
343
-
344
- ---
345
-
346
- ## Summary
347
-
348
- | Severity | Count | Items |
349
- |---|---|---|
350
- | Critical | 5 | #1 MessageStore unwired; #2 AccountStore unwired; #3 CF runtime stubs; #4 AWS no QUIT fanout; #5 AWS Accounts table unused |
351
- | Absent commands | 4 | #6 OPER; #7 TAGMSG; #8 WHOWAS; #9 misc standard verbs |
352
- | Partial | 7 | #10 SASL EXTERNAL; #11 Welcome MOTD; #12 Version/Created placeholders; #13 DEFAULT_SERVER_CONFIG; #14 AWS connect ignores config; #15 AWS Lambda disconnect; #16 CF channel-register no-op |
353
- | Minor / Dead scaffolding | 7 | #17 dead lookup Effects; #18 CF batching reserved; #19 stale DO doc-comments; #20 case-mapping mismatch; #21 unused recordId; #22 stale CLI comment; #23 stale release doc |
354
-
355
- **Bottom line:** Implemented command reducers are solid. The real gaps are (1) two whole
356
- feature ports (`MessageStore`, `AccountStore`) shipped with no adapter wiring, (2) the CF
357
- runtime's four stubbed methods that break WHO/WHOIS/LIST/remote-disconnect, (3) AWS never
358
- broadcasts QUIT on disconnect, and (4) `OPER` is the largest scaffolded-but-absent command.