serverless-ircd 0.8.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (179) hide show
  1. package/.github/workflows/ci.yml +4 -0
  2. package/.github/workflows/deploy-aws.yml +156 -32
  3. package/.github/workflows/deploy-cf-tcp.yml +11 -9
  4. package/.github/workflows/deploy-cf.yml +14 -14
  5. package/CHANGELOG.md +550 -0
  6. package/README.md +275 -222
  7. package/apps/aws-stack/README.md +3 -5
  8. package/apps/aws-stack/bin/aws.ts +82 -9
  9. package/apps/aws-stack/cdk.json +0 -3
  10. package/apps/aws-stack/package.json +3 -4
  11. package/apps/aws-stack/src/aws-stack.ts +177 -52
  12. package/apps/aws-stack/src/static-site.ts +323 -0
  13. package/apps/aws-stack/tests/smoke-helpers.test.ts +1 -1
  14. package/apps/aws-stack/tests/stack.test.ts +267 -92
  15. package/apps/aws-stack/tests/static-site.test.ts +491 -0
  16. package/apps/aws-stack/tests/synth-no-bundle.test.ts +0 -1
  17. package/apps/cf-tcp-container/package.json +2 -3
  18. package/apps/cf-tcp-container/src/container-server.ts +33 -10
  19. package/apps/cf-tcp-container/tests/config-loader.test.ts +43 -0
  20. package/apps/cf-tcp-container/tests/container-server.test.ts +249 -1
  21. package/apps/cf-tcp-container/tests/persistence.test.ts +9 -0
  22. package/apps/cf-tcp-container/tests/tls-e2e.test.ts +24 -5
  23. package/apps/cf-tcp-container/wrangler.toml +1 -10
  24. package/apps/cf-worker/package.json +3 -4
  25. package/apps/cf-worker/wrangler.toml +12 -71
  26. package/apps/local-cli/package.json +1 -1
  27. package/apps/local-cli/src/server.ts +115 -48
  28. package/apps/local-cli/tests/config-resolution.test.ts +65 -0
  29. package/apps/local-cli/tests/motd-file-non-error.test.ts +29 -0
  30. package/apps/local-cli/tests/rehash.test.ts +147 -0
  31. package/apps/local-cli/tests/server-helpers.test.ts +63 -0
  32. package/apps/local-cli/tests/tcp.test.ts +89 -0
  33. package/apps/local-cli/tests/ws-subprotocol.test.ts +92 -0
  34. package/apps/web/landing/favicon.ico +0 -0
  35. package/apps/web/landing/index.html +227 -3
  36. package/apps/web/package.json +3 -2
  37. package/apps/web/scripts/build.mjs +91 -6
  38. package/apps/web/src/build-env.ts +125 -4
  39. package/apps/web/src/config-schema.ts +20 -6
  40. package/apps/web/src/render-docs.ts +292 -0
  41. package/apps/web/static/{config.staging.json → config.prod-aws.json} +3 -2
  42. package/apps/web/tests/build-env.test.ts +210 -9
  43. package/apps/web/tests/build-smoke.test.ts +33 -4
  44. package/apps/web/tests/config-schema.test.ts +149 -25
  45. package/apps/web/tests/landing-content.test.ts +103 -0
  46. package/apps/web/tests/render-docs.test.ts +198 -0
  47. package/docs/AWS-Adapter-Architecture.md +3 -2
  48. package/docs/AWS-Deployment.md +670 -96
  49. package/docs/AWS-TCP-Deployment.md +20 -45
  50. package/docs/Cloudflare-Deployment-Guide.md +87 -113
  51. package/docs/Cloudflare-TCP-Deployment.md +25 -49
  52. package/docs/Release-Process.md +27 -23
  53. package/docs/Services.md +102 -23
  54. package/docs/WebClientGuide.md +35 -26
  55. package/package.json +7 -10
  56. package/packages/aws-adapter/package.json +1 -1
  57. package/packages/aws-adapter/src/aws-runtime.ts +15 -1
  58. package/packages/aws-adapter/src/cdk-table-defs.ts +6 -11
  59. package/packages/aws-adapter/src/config-loader.ts +19 -2
  60. package/packages/aws-adapter/src/dynamo-services-store.ts +7 -0
  61. package/packages/aws-adapter/src/handlers/connect.ts +26 -0
  62. package/packages/aws-adapter/src/handlers/default.ts +190 -123
  63. package/packages/aws-adapter/src/handlers/index.ts +67 -23
  64. package/packages/aws-adapter/src/handlers/nlb-stream.ts +13 -8
  65. package/packages/aws-adapter/src/index.ts +5 -7
  66. package/packages/aws-adapter/src/origin-allowlist.ts +94 -0
  67. package/packages/aws-adapter/src/serialize.ts +15 -0
  68. package/packages/aws-adapter/src/tables.ts +2 -12
  69. package/packages/aws-adapter/tests/aws-harness.ts +0 -1
  70. package/packages/aws-adapter/tests/aws-runtime.test.ts +23 -1
  71. package/packages/aws-adapter/tests/config-loader.test.ts +66 -0
  72. package/packages/aws-adapter/tests/connect.test.ts +124 -1
  73. package/packages/aws-adapter/tests/connection-counter.test.ts +17 -0
  74. package/packages/aws-adapter/tests/default-occ.test.ts +219 -0
  75. package/packages/aws-adapter/tests/dynamo-services-store-unit.test.ts +11 -0
  76. package/packages/aws-adapter/tests/global-setup.ts +28 -1
  77. package/packages/aws-adapter/tests/gone-exception.test.ts +21 -2
  78. package/packages/aws-adapter/tests/handlers.test.ts +117 -11
  79. package/packages/aws-adapter/tests/migrate-accounts-to-services.test.ts +164 -0
  80. package/packages/aws-adapter/tests/nlb-stream.test.ts +29 -1
  81. package/packages/aws-adapter/tests/origin-allowlist.test.ts +110 -0
  82. package/packages/aws-adapter/tests/ping-checker.test.ts +0 -1
  83. package/packages/aws-adapter/tests/stats.test.ts +0 -3
  84. package/packages/aws-adapter/tests/sweeper.test.ts +20 -1
  85. package/packages/aws-adapter/tests/tables.test.ts +1 -8
  86. package/packages/aws-adapter/tests/transactions.test.ts +0 -1
  87. package/packages/cf-adapter/package.json +1 -5
  88. package/packages/cf-adapter/src/cf-runtime.ts +59 -8
  89. package/packages/cf-adapter/src/channel-do.ts +13 -3
  90. package/packages/cf-adapter/src/connection-do.ts +284 -115
  91. package/packages/cf-adapter/src/d1-services-store.ts +63 -26
  92. package/packages/cf-adapter/src/env.ts +11 -10
  93. package/packages/cf-adapter/src/index.ts +0 -6
  94. package/packages/cf-adapter/tests/cf-runtime.test.ts +101 -1
  95. package/packages/cf-adapter/tests/channel-do.test.ts +118 -1
  96. package/packages/cf-adapter/tests/connection-do-coverage.test.ts +460 -0
  97. package/packages/cf-adapter/tests/connection-do-pure.test.ts +222 -51
  98. package/packages/cf-adapter/tests/connection-do-sasl-d1.test.ts +62 -38
  99. package/packages/cf-adapter/tests/d1-services-store.test.ts +53 -2
  100. package/packages/cf-adapter/tests/serialize.test.ts +25 -0
  101. package/packages/in-memory-runtime/package.json +1 -1
  102. package/packages/irc-core/package.json +1 -1
  103. package/packages/irc-core/src/account-migration.ts +140 -0
  104. package/packages/irc-core/src/commands/account-auth.ts +60 -35
  105. package/packages/irc-core/src/commands/chanserv.ts +288 -4
  106. package/packages/irc-core/src/commands/hostserv.ts +38 -3
  107. package/packages/irc-core/src/commands/index.ts +1 -0
  108. package/packages/irc-core/src/commands/join.ts +41 -35
  109. package/packages/irc-core/src/commands/memoserv.ts +1 -1
  110. package/packages/irc-core/src/commands/nickserv.ts +138 -15
  111. package/packages/irc-core/src/commands/registration.ts +28 -17
  112. package/packages/irc-core/src/commands/sasl.ts +22 -31
  113. package/packages/irc-core/src/commands/service-aliases.ts +52 -0
  114. package/packages/irc-core/src/commands/topic.ts +23 -10
  115. package/packages/irc-core/src/config.ts +35 -9
  116. package/packages/irc-core/src/credential-hashing.ts +11 -54
  117. package/packages/irc-core/src/index.ts +1 -0
  118. package/packages/irc-core/src/ports.ts +159 -179
  119. package/packages/irc-core/src/state/channel.ts +17 -0
  120. package/packages/irc-core/src/types.ts +38 -10
  121. package/packages/irc-core/tests/account-migration.test.ts +133 -0
  122. package/packages/irc-core/tests/commands/chanserv.test.ts +668 -1
  123. package/packages/irc-core/tests/commands/hostserv.test.ts +71 -0
  124. package/packages/irc-core/tests/commands/join.test.ts +179 -0
  125. package/packages/irc-core/tests/commands/markread.test.ts +54 -0
  126. package/packages/irc-core/tests/commands/memoserv.test.ts +19 -0
  127. package/packages/irc-core/tests/commands/nickserv.test.ts +422 -3
  128. package/packages/irc-core/tests/commands/oper.test.ts +15 -0
  129. package/packages/irc-core/tests/commands/registration.test.ts +336 -108
  130. package/packages/irc-core/tests/commands/sasl.test.ts +194 -169
  131. package/packages/irc-core/tests/commands/service-aliases.test.ts +52 -0
  132. package/packages/irc-core/tests/commands/unified-account.test.ts +102 -84
  133. package/packages/irc-core/tests/credential-hashing.test.ts +0 -78
  134. package/packages/irc-core/tests/message-store.test.ts +5 -0
  135. package/packages/irc-core/tests/persistent-services-store.test.ts +71 -12
  136. package/packages/irc-core/tests/ports.test.ts +71 -0
  137. package/packages/irc-core/tests/services-store.test.ts +204 -0
  138. package/packages/irc-core/vitest.config.ts +6 -1
  139. package/packages/irc-server/package.json +1 -1
  140. package/packages/irc-server/src/actor.ts +80 -44
  141. package/packages/irc-server/tests/actor.test.ts +384 -50
  142. package/packages/irc-test-support/package.json +1 -1
  143. package/packages/irc-test-support/src/in-memory-harness.ts +8 -5
  144. package/packages/irc-test-support/src/scenarios.ts +21 -6
  145. package/packages/irc-test-support/tests/in-memory-harness.test.ts +19 -0
  146. package/packages/irc-test-support/vitest.config.ts +6 -1
  147. package/pnpm-workspace.yaml +1 -0
  148. package/scripts/__tests__/deploy-web-aws.test.ts +491 -0
  149. package/scripts/deploy-web-aws.mjs +290 -0
  150. package/scripts/package.json +23 -0
  151. package/scripts/tsconfig.test.json +12 -0
  152. package/scripts/vitest.config.ts +19 -0
  153. package/tools/ci-hardening/package.json +1 -1
  154. package/tools/ci-hardening/src/index.ts +2 -0
  155. package/tools/ci-hardening/src/validate.ts +57 -0
  156. package/tools/ci-hardening/tests/deploy-aws-oidc.test.ts +96 -0
  157. package/tools/ci-hardening/tests/validate.test.ts +42 -0
  158. package/tools/load-test/package.json +1 -1
  159. package/tools/load-test/src/client.ts +13 -13
  160. package/tools/load-test/tests/client.test.ts +258 -2
  161. package/tools/load-test/tests/config.test.ts +39 -0
  162. package/tools/load-test/tests/harness.test.ts +21 -0
  163. package/tools/load-test/tests/metrics.test.ts +7 -0
  164. package/tools/migrate-accounts-to-services.ts +270 -0
  165. package/tools/package.json +2 -1
  166. package/tools/seed-aws-accounts.ts +35 -10
  167. package/tools/seed-cf-accounts.ts +42 -9
  168. package/tools/tcp-ws-forwarder/package.json +1 -1
  169. package/tools/tcp-ws-forwarder/tests/close-error.test.ts +40 -0
  170. package/tools/tcp-ws-forwarder/tests/defensive-branches.test.ts +78 -0
  171. package/tools/tcp-ws-forwarder/tests/forwarder.test.ts +51 -0
  172. package/tools/tcp-ws-forwarder/tests/logger.test.ts +31 -1
  173. package/packages/aws-adapter/src/account-store.ts +0 -121
  174. package/packages/aws-adapter/src/dynamo-account-store.ts +0 -95
  175. package/packages/aws-adapter/tests/account-store-dynamo.test.ts +0 -223
  176. package/packages/aws-adapter/tests/account-store.test.ts +0 -276
  177. package/packages/cf-adapter/src/d1-account-store.ts +0 -198
  178. package/packages/cf-adapter/tests/d1-account-store.test.ts +0 -274
  179. package/packages/irc-core/tests/account-store.test.ts +0 -131
@@ -0,0 +1,133 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import {
3
+ type LegacyAccountRow,
4
+ buildMigrationSql,
5
+ buildServicesPutItem,
6
+ parseSaslAccountsForMigration,
7
+ } from '../src/account-migration';
8
+
9
+ describe('parseSaslAccountsForMigration', () => {
10
+ it('returns an empty array for undefined', () => {
11
+ expect(parseSaslAccountsForMigration(undefined)).toEqual([]);
12
+ });
13
+
14
+ it('returns an empty array for an empty string', () => {
15
+ expect(parseSaslAccountsForMigration('')).toEqual([]);
16
+ });
17
+
18
+ it('parses a single username:password entry', () => {
19
+ expect(parseSaslAccountsForMigration('alice:s3cret')).toEqual([
20
+ { username: 'alice', password: 's3cret' },
21
+ ]);
22
+ });
23
+
24
+ it('skips blank lines and malformed entries', () => {
25
+ expect(
26
+ parseSaslAccountsForMigration('alice:s3cret\n\nnocolon\n:emptyuser\nemptypass:\n \n'),
27
+ ).toEqual([{ username: 'alice', password: 's3cret' }]);
28
+ });
29
+ });
30
+
31
+ describe('buildMigrationSql', () => {
32
+ const legacyRow = (account: string, salt = 'salt', hash = 'hash'): LegacyAccountRow => ({
33
+ account,
34
+ algorithm: 'scrypt',
35
+ salt,
36
+ hash,
37
+ });
38
+
39
+ it('creates a nickserv_accounts row with cert_subjects "[]" for a legacy account', () => {
40
+ const stmts = buildMigrationSql([legacyRow('alice')], undefined);
41
+ expect(stmts[0]).toContain('CREATE TABLE IF NOT EXISTS nickserv_accounts');
42
+ expect(stmts[1]).toContain('INSERT OR IGNORE');
43
+ expect(stmts[1]).toContain("'alice'");
44
+ expect(stmts[1]).toContain("'[]'");
45
+ });
46
+
47
+ it('uses INSERT OR IGNORE (never REPLACE)', () => {
48
+ const stmts = buildMigrationSql([legacyRow('alice')], undefined);
49
+ expect(stmts[1]).toContain('INSERT OR IGNORE');
50
+ expect(stmts[1]).not.toContain('INSERT OR REPLACE');
51
+ });
52
+
53
+ it('is idempotent (same input → same output)', () => {
54
+ const stmts1 = buildMigrationSql([legacyRow('alice')], undefined);
55
+ const stmts2 = buildMigrationSql([legacyRow('alice')], undefined);
56
+ expect(stmts1).toEqual(stmts2);
57
+ });
58
+
59
+ it('carries SASL_ACCOUNTS env-seed entries not in the legacy table', () => {
60
+ const stmts = buildMigrationSql([legacyRow('alice')], 'bob:bobspw\nalice:alicespw');
61
+ expect(stmts).toHaveLength(3);
62
+ expect(stmts[1]).toContain("'alice'");
63
+ expect(stmts[1]).toContain("'salt'");
64
+ expect(stmts[2]).toContain("'bob'");
65
+ expect(stmts[2]).not.toContain("'bobspw'");
66
+ });
67
+
68
+ it('does not re-hash legacy rows', () => {
69
+ const stmts = buildMigrationSql([legacyRow('alice', 'mysalt', 'myhash')], undefined);
70
+ expect(stmts[1]).toContain("'mysalt'");
71
+ expect(stmts[1]).toContain("'myhash'");
72
+ });
73
+
74
+ it('produces only CREATE TABLE when both inputs are empty', () => {
75
+ const stmts = buildMigrationSql([], undefined);
76
+ expect(stmts).toHaveLength(1);
77
+ });
78
+
79
+ it('escapes single quotes in usernames', () => {
80
+ const stmts = buildMigrationSql([legacyRow("O'Brien")], undefined);
81
+ expect(stmts[1]).toContain("'O''Brien'");
82
+ });
83
+ });
84
+
85
+ describe('buildServicesPutItem', () => {
86
+ it('targets the NICK:<fold> partition', () => {
87
+ const input = buildServicesPutItem(
88
+ { account: 'alice', algorithm: 'scrypt', salt: 's', hash: 'h' },
89
+ 'StagingServices',
90
+ );
91
+ expect(input.TableName).toBe('StagingServices');
92
+ expect(input.Item.pk).toBe('NICK:alice');
93
+ expect(input.Item.sk).toBe('#');
94
+ expect(input.Item.type).toBe('nick');
95
+ });
96
+
97
+ it('preserves the legacy scrypt credential fields', () => {
98
+ const input = buildServicesPutItem(
99
+ { account: 'alice', algorithm: 'scrypt', salt: 'mysalt', hash: 'myhash' },
100
+ 'Services',
101
+ );
102
+ expect(input.Item.algorithm).toBe('scrypt');
103
+ expect(input.Item.salt).toBe('mysalt');
104
+ expect(input.Item.hash).toBe('myhash');
105
+ });
106
+
107
+ it('defaults certSubjects to an empty array', () => {
108
+ const input = buildServicesPutItem(
109
+ { account: 'alice', algorithm: 'scrypt', salt: 's', hash: 'h' },
110
+ 'Services',
111
+ );
112
+ expect(input.Item.certSubjects).toEqual([]);
113
+ });
114
+
115
+ it('folds the nick case-insensitively', () => {
116
+ const input = buildServicesPutItem(
117
+ { account: 'Alice', algorithm: 'scrypt', salt: 's', hash: 'h' },
118
+ 'Services',
119
+ );
120
+ expect(input.Item.pk).toBe('NICK:alice');
121
+ expect(input.Item.nick).toBe('Alice');
122
+ });
123
+
124
+ it('stamps default email / enforce / createdAt', () => {
125
+ const input = buildServicesPutItem(
126
+ { account: 'alice', algorithm: 'scrypt', salt: 's', hash: 'h' },
127
+ 'Services',
128
+ );
129
+ expect(input.Item.email).toBe('');
130
+ expect(input.Item.enforce).toBe('none');
131
+ expect(input.Item.createdAt).toBe(0);
132
+ });
133
+ });