serverless-ircd 0.1.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.
- package/.github/workflows/ci.yml +96 -2
- package/.github/workflows/deploy-aws.yml +129 -0
- package/.github/workflows/deploy-cf.yml +0 -2
- package/.gitmodules +3 -0
- package/CHANGELOG.md +436 -0
- package/README.md +127 -84
- package/apps/aws-stack/README.md +73 -0
- package/apps/aws-stack/bin/aws.ts +49 -0
- package/apps/aws-stack/cdk.json +10 -0
- package/apps/aws-stack/package.json +41 -0
- package/apps/aws-stack/scripts/smoke-helpers.d.mts +22 -0
- package/apps/aws-stack/scripts/smoke-helpers.mjs +89 -0
- package/apps/aws-stack/scripts/smoke.mjs +142 -0
- package/apps/aws-stack/src/aws-stack.ts +263 -0
- package/apps/aws-stack/src/tables.ts +10 -0
- package/apps/aws-stack/tests/localstack.test.ts +46 -0
- package/apps/aws-stack/tests/smoke-helpers.test.ts +98 -0
- package/apps/aws-stack/tests/stack.test.ts +464 -0
- package/apps/aws-stack/tsconfig.build.json +11 -0
- package/apps/aws-stack/tsconfig.test.json +8 -0
- package/apps/aws-stack/vitest.config.ts +20 -0
- package/apps/cf-worker/package.json +1 -1
- package/apps/cf-worker/scripts/smoke.mjs +0 -0
- package/apps/cf-worker/src/worker.ts +8 -2
- package/apps/cf-worker/tests/smoke.test.ts +1 -0
- package/apps/cf-worker/wrangler.test.toml +5 -1
- package/apps/cf-worker/wrangler.toml +66 -17
- package/apps/local-cli/package.json +1 -1
- package/apps/local-cli/src/config-loader.ts +57 -0
- package/apps/local-cli/src/main.ts +1 -1
- package/apps/local-cli/src/server.ts +267 -32
- package/apps/local-cli/tests/config-loader.test.ts +107 -0
- package/apps/local-cli/tests/e2e.test.ts +126 -0
- package/apps/local-cli/tests/security-e2e.test.ts +239 -0
- package/biome.json +3 -1
- package/docs/ADR-001-pure-reducers-and-effect-system.md +74 -0
- package/docs/ADR-002-location-of-authority.md +82 -0
- package/docs/ADR-003-durable-object-sharding.md +93 -0
- package/docs/ADR-004-dynamodb-schema.md +96 -0
- package/docs/ADR-005-wss-only-transport-v1.md +83 -0
- package/docs/ADR-006-sasl-mechanism-scope.md +86 -0
- package/docs/ADR-007-deterministic-ports.md +82 -0
- package/docs/ADR-008-monorepo-tooling.md +60 -0
- package/docs/AWS-Adapter-Architecture.md +496 -0
- package/docs/AWS-Deployment.md +1186 -0
- package/docs/Cloudflare-Deployment-Guide.md +660 -0
- package/docs/Home.md +11 -0
- package/docs/Observability.md +87 -0
- package/docs/PlanIRCv3Websocket.md +489 -0
- package/docs/PlanWebClient.md +451 -0
- package/docs/Release-Process.md +443 -0
- package/package.json +19 -14
- package/packages/aws-adapter/README.md +35 -0
- package/packages/aws-adapter/package.json +52 -0
- package/packages/aws-adapter/src/account-store.ts +121 -0
- package/packages/aws-adapter/src/aws-runtime.ts +871 -0
- package/packages/aws-adapter/src/cdk-table-defs.ts +73 -0
- package/packages/aws-adapter/src/config-loader.ts +126 -0
- package/packages/aws-adapter/src/dynamo-account-store.ts +156 -0
- package/packages/aws-adapter/src/dynamo.ts +61 -0
- package/packages/aws-adapter/src/handlers/connect.ts +44 -0
- package/packages/aws-adapter/src/handlers/default.ts +330 -0
- package/packages/aws-adapter/src/handlers/disconnect.ts +48 -0
- package/packages/aws-adapter/src/handlers/index.ts +293 -0
- package/packages/aws-adapter/src/handlers/ping-checker.ts +217 -0
- package/packages/aws-adapter/src/handlers/state.ts +13 -0
- package/packages/aws-adapter/src/handlers/sweeper.ts +84 -0
- package/packages/aws-adapter/src/index.ts +74 -0
- package/packages/aws-adapter/src/message-store.ts +34 -0
- package/packages/aws-adapter/src/serialize.ts +283 -0
- package/packages/aws-adapter/src/tables.ts +53 -0
- package/packages/aws-adapter/tests/account-store-dynamo.test.ts +171 -0
- package/packages/aws-adapter/tests/account-store.test.ts +280 -0
- package/packages/aws-adapter/tests/aws-harness.ts +408 -0
- package/packages/aws-adapter/tests/aws-integration.test.ts +17 -0
- package/packages/aws-adapter/tests/aws-runtime.test.ts +654 -0
- package/packages/aws-adapter/tests/config-loader.test.ts +213 -0
- package/packages/aws-adapter/tests/disconnect-fanout.test.ts +336 -0
- package/packages/aws-adapter/tests/dynamo.test.ts +57 -0
- package/packages/aws-adapter/tests/global-setup.ts +301 -0
- package/packages/aws-adapter/tests/gone-exception.test.ts +271 -0
- package/packages/aws-adapter/tests/handlers.test.ts +473 -0
- package/packages/aws-adapter/tests/message-store.test.ts +55 -0
- package/packages/aws-adapter/tests/ping-checker.test.ts +571 -0
- package/packages/aws-adapter/tests/serialize.test.ts +249 -0
- package/packages/aws-adapter/tests/smoke.test.ts +48 -0
- package/packages/aws-adapter/tests/sweeper.test.ts +420 -0
- package/packages/aws-adapter/tests/tables.test.ts +74 -0
- package/packages/aws-adapter/tests/transactions.test.ts +446 -0
- package/packages/aws-adapter/tsconfig.build.json +16 -0
- package/packages/aws-adapter/tsconfig.test.json +14 -0
- package/packages/aws-adapter/vitest.config.ts +23 -0
- package/packages/cf-adapter/package.json +2 -1
- package/packages/cf-adapter/src/cf-runtime.ts +42 -22
- package/packages/cf-adapter/src/channel-do.ts +40 -1
- package/packages/cf-adapter/src/channel-registry-do.ts +58 -0
- package/packages/cf-adapter/src/config-loader.ts +135 -0
- package/packages/cf-adapter/src/connection-do.ts +119 -0
- package/packages/cf-adapter/src/env.ts +27 -1
- package/packages/cf-adapter/src/index.ts +2 -1
- package/packages/cf-adapter/tests/cf-harness.ts +2 -2
- package/packages/cf-adapter/tests/cf-integration.test.ts +2 -2
- package/packages/cf-adapter/tests/cf-runtime.test.ts +91 -0
- package/packages/cf-adapter/tests/config-loader.test.ts +149 -0
- package/packages/cf-adapter/tests/connection-do.test.ts +82 -0
- package/packages/cf-adapter/tests/worker/main.ts +2 -1
- package/packages/cf-adapter/tests/worker/stubs/channel-stub.ts +7 -1
- package/packages/cf-adapter/wrangler.test.toml +10 -1
- package/packages/in-memory-runtime/package.json +1 -1
- package/packages/in-memory-runtime/src/in-memory-runtime.ts +107 -16
- package/packages/in-memory-runtime/src/index.ts +1 -1
- package/packages/in-memory-runtime/tests/in-memory-runtime.test.ts +134 -0
- package/packages/irc-core/package.json +13 -2
- package/packages/irc-core/src/admission.ts +216 -0
- package/packages/irc-core/src/caps/capabilities.ts +1 -0
- package/packages/irc-core/src/case-fold.ts +64 -0
- package/packages/irc-core/src/cloak.ts +81 -0
- package/packages/irc-core/src/commands/cap.ts +1 -2
- package/packages/irc-core/src/commands/chathistory.ts +305 -0
- package/packages/irc-core/src/commands/index.ts +9 -0
- package/packages/irc-core/src/commands/invite.ts +6 -9
- package/packages/irc-core/src/commands/isupport.ts +1 -1
- package/packages/irc-core/src/commands/join.ts +63 -10
- package/packages/irc-core/src/commands/kick.ts +4 -11
- package/packages/irc-core/src/commands/list.ts +5 -4
- package/packages/irc-core/src/commands/mode.ts +5 -9
- package/packages/irc-core/src/commands/motd-lines.ts +127 -0
- package/packages/irc-core/src/commands/motd.ts +6 -110
- package/packages/irc-core/src/commands/oper.ts +151 -0
- package/packages/irc-core/src/commands/privmsg.ts +24 -0
- package/packages/irc-core/src/commands/registration.ts +79 -21
- package/packages/irc-core/src/commands/sasl.ts +251 -0
- package/packages/irc-core/src/commands/tagmsg.ts +205 -0
- package/packages/irc-core/src/config.ts +270 -0
- package/packages/irc-core/src/flood-control.ts +175 -0
- package/packages/irc-core/src/index.ts +7 -0
- package/packages/irc-core/src/ports.ts +719 -0
- package/packages/irc-core/src/protocol/base64.ts +16 -0
- package/packages/irc-core/src/protocol/index.ts +2 -1
- package/packages/irc-core/src/protocol/numerics.ts +11 -0
- package/packages/irc-core/src/protocol/parser.ts +27 -2
- package/packages/irc-core/src/state/connection.ts +41 -0
- package/packages/irc-core/src/types.ts +88 -2
- package/packages/irc-core/stryker.commands.conf.json +41 -0
- package/packages/irc-core/stryker.protocol.conf.json +26 -0
- package/packages/irc-core/tests/account-store.test.ts +88 -0
- package/packages/irc-core/tests/admission.test.ts +229 -0
- package/packages/irc-core/tests/caps/capabilities.test.ts +22 -0
- package/packages/irc-core/tests/case-fold.test.ts +80 -0
- package/packages/irc-core/tests/cloak.test.ts +78 -0
- package/packages/irc-core/tests/commands/chathistory.test.ts +996 -0
- package/packages/irc-core/tests/commands/join.test.ts +246 -2
- package/packages/irc-core/tests/commands/kick.test.ts +15 -0
- package/packages/irc-core/tests/commands/oper.test.ts +257 -0
- package/packages/irc-core/tests/commands/privmsg.test.ts +146 -2
- package/packages/irc-core/tests/commands/registration.test.ts +380 -20
- package/packages/irc-core/tests/commands/sasl.test.ts +536 -0
- package/packages/irc-core/tests/commands/tagmsg.test.ts +688 -0
- package/packages/irc-core/tests/commands/who.test.ts +22 -4
- package/packages/irc-core/tests/commands/whois.test.ts +8 -1
- package/packages/irc-core/tests/config.test.ts +721 -0
- package/packages/irc-core/tests/flood-control.test.ts +394 -0
- package/packages/irc-core/tests/message-store.test.ts +530 -0
- package/packages/irc-core/tests/parser.test.ts +44 -1
- package/packages/irc-core/tests/ports.test.ts +263 -0
- package/packages/irc-server/package.json +1 -1
- package/packages/irc-server/src/actor.ts +186 -44
- package/packages/irc-server/src/dispatch.ts +89 -5
- package/packages/irc-server/src/index.ts +2 -0
- package/packages/irc-server/src/routing.ts +160 -0
- package/packages/irc-server/tests/actor.test.ts +690 -15
- package/packages/irc-server/tests/dispatch.test.ts +84 -0
- package/packages/irc-server/tests/routing.test.ts +204 -0
- package/packages/irc-test-support/README.md +32 -0
- package/packages/irc-test-support/package.json +37 -0
- package/packages/{cf-adapter/tests/integration → irc-test-support/src}/in-memory-harness.ts +6 -5
- package/packages/irc-test-support/src/index.ts +24 -0
- package/packages/{cf-adapter/tests/integration/harness.test.ts → irc-test-support/tests/in-memory-harness.test.ts} +1 -1
- package/packages/{cf-adapter/tests/integration/scenarios.test.ts → irc-test-support/tests/in-memory-scenarios.test.ts} +1 -2
- package/packages/irc-test-support/tests/smoke.test.ts +11 -0
- package/packages/irc-test-support/tsconfig.build.json +16 -0
- package/packages/irc-test-support/tsconfig.test.json +14 -0
- package/packages/irc-test-support/vitest.config.ts +20 -0
- package/pnpm-workspace.yaml +1 -0
- package/tools/ci-hardening/package.json +30 -0
- package/tools/ci-hardening/src/index.ts +6 -0
- package/tools/ci-hardening/src/validate.ts +103 -0
- package/tools/ci-hardening/tests/__no_thresholds__.txt +11 -0
- package/tools/ci-hardening/tests/__partial_thresholds__.txt +16 -0
- package/tools/ci-hardening/tests/__stryker_bad__.json +4 -0
- package/tools/ci-hardening/tests/validate.test.ts +177 -0
- package/tools/ci-hardening/tsconfig.build.json +12 -0
- package/tools/ci-hardening/tsconfig.test.json +10 -0
- package/tools/ci-hardening/vitest.config.ts +21 -0
- package/tools/seed-aws-accounts.ts +80 -0
- package/tools/tcp-ws-forwarder/package.json +1 -1
- package/tools/tcp-ws-forwarder/src/forwarder.ts +34 -23
- package/tools/tcp-ws-forwarder/src/logger.ts +155 -0
- package/tools/tcp-ws-forwarder/src/main.ts +33 -14
- package/tools/tcp-ws-forwarder/tests/forwarder.test.ts +86 -0
- package/tools/tcp-ws-forwarder/tests/logger.test.ts +136 -0
- package/packages/cf-adapter/tests/integration/index.ts +0 -17
- /package/packages/{cf-adapter/tests/integration → irc-test-support/src}/harness.ts +0 -0
- /package/packages/{cf-adapter/tests/integration → irc-test-support/src}/scenarios.ts +0 -0
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SASL account store construction + resolution for the AWS adapter.
|
|
3
|
+
*
|
|
4
|
+
* Centralises `AccountStore` creation so the actor-construction site
|
|
5
|
+
* (`handleDefault`) binds a single helper rather than constructing the
|
|
6
|
+
* store inline. Two sources of credentials are reconciled here:
|
|
7
|
+
*
|
|
8
|
+
* 1. The DynamoDB `Accounts` table (authoritative when populated) —
|
|
9
|
+
* loaded at cold start into a {@link DynamoAccountStore} by
|
|
10
|
+
* {@link resolveAccountStore}. Credentials are stored as scrypt
|
|
11
|
+
* hashes, never plaintext.
|
|
12
|
+
* 2. The parsed server config (`saslAccounts`, sourced from the
|
|
13
|
+
* `SASL_ACCOUNTS` env var) — the legacy/config fallback used only
|
|
14
|
+
* when the table is empty, preserving the config-seed behaviour for
|
|
15
|
+
* deployments that have not migrated to the table.
|
|
16
|
+
*
|
|
17
|
+
* The resolved store is scoped to the Lambda execution context: it
|
|
18
|
+
* persists across warm invocations (via the memoised `HandlerDeps`) but
|
|
19
|
+
* is rebuilt on cold start, picking up account changes made since the
|
|
20
|
+
* last cold start.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
import { PutCommand } from '@aws-sdk/lib-dynamodb';
|
|
24
|
+
import type { DynamoDBDocumentClient } from '@aws-sdk/lib-dynamodb';
|
|
25
|
+
import {
|
|
26
|
+
type AccountStore,
|
|
27
|
+
InMemoryAccountStore,
|
|
28
|
+
type ParsedServerConfig,
|
|
29
|
+
} from '@serverless-ircd/irc-core';
|
|
30
|
+
import {
|
|
31
|
+
type HashedAccountCredential,
|
|
32
|
+
DynamoAccountStore,
|
|
33
|
+
hashAccountCredential,
|
|
34
|
+
loadDynamoAccountStore,
|
|
35
|
+
} from './dynamo-account-store.js';
|
|
36
|
+
|
|
37
|
+
// Re-export so callers can import everything from one module.
|
|
38
|
+
export {
|
|
39
|
+
DynamoAccountStore,
|
|
40
|
+
type HashedAccountCredential,
|
|
41
|
+
hashAccountCredential,
|
|
42
|
+
loadDynamoAccountStore,
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Constructs the config-seeded in-memory account store (the legacy
|
|
47
|
+
* fallback). Returns `undefined` when no accounts are configured so the
|
|
48
|
+
* actor's `ctx.accounts` stays unset (preserving the no-store behaviour:
|
|
49
|
+
* `AUTHENTICATE PLAIN` → `904`).
|
|
50
|
+
*
|
|
51
|
+
* @param serverConfig Parsed config carrying the `saslAccounts` seed list.
|
|
52
|
+
*/
|
|
53
|
+
export function bindAccountStore(serverConfig?: ParsedServerConfig): AccountStore | undefined {
|
|
54
|
+
if (serverConfig === undefined || serverConfig.saslAccounts.length === 0) {
|
|
55
|
+
return undefined;
|
|
56
|
+
}
|
|
57
|
+
return new InMemoryAccountStore(serverConfig.saslAccounts);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Resolves the SASL account store for a deployment, applying the
|
|
62
|
+
* table-then-config precedence.
|
|
63
|
+
*
|
|
64
|
+
* 1. Scans the DynamoDB `Accounts` table (pre-loading every hashed
|
|
65
|
+
* credential into a {@link DynamoAccountStore}). When the table has
|
|
66
|
+
* one or more rows it is authoritative — the table wins and the
|
|
67
|
+
* config seed is ignored.
|
|
68
|
+
* 2. When the table is empty, falls back to {@link bindAccountStore}
|
|
69
|
+
* (the `SASL_ACCOUNTS` env-var seed) so existing deployments that
|
|
70
|
+
* have not migrated to the table keep working unchanged.
|
|
71
|
+
* 3. Returns `undefined` when neither source has accounts (the default)
|
|
72
|
+
* so `ctx.accounts` stays unset and `AUTHENTICATE PLAIN` → `904`.
|
|
73
|
+
*
|
|
74
|
+
* Scan failures (table not found, network error) are swallowed and
|
|
75
|
+
* treated as an empty table, falling through to the config seed.
|
|
76
|
+
*
|
|
77
|
+
* @param docClient DynamoDB client addressed at the deployment's tables.
|
|
78
|
+
* @param tableName Physical name of the `Accounts` table for this env.
|
|
79
|
+
* @param serverConfig Parsed config (the config-seed fallback source).
|
|
80
|
+
*/
|
|
81
|
+
export async function resolveAccountStore(
|
|
82
|
+
docClient: DynamoDBDocumentClient,
|
|
83
|
+
tableName: string,
|
|
84
|
+
serverConfig?: ParsedServerConfig,
|
|
85
|
+
): Promise<AccountStore | undefined> {
|
|
86
|
+
try {
|
|
87
|
+
const store = await loadDynamoAccountStore(docClient, tableName);
|
|
88
|
+
if (store !== undefined) return store;
|
|
89
|
+
} catch {
|
|
90
|
+
// Table might not exist or be unreachable; fall through to config seed.
|
|
91
|
+
}
|
|
92
|
+
return bindAccountStore(serverConfig);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Writes (or re-seeds) a SASL PLAIN account into the `Accounts` table.
|
|
97
|
+
*
|
|
98
|
+
* The password is hashed via {@link hashAccountCredential} (scrypt,
|
|
99
|
+
* random salt) and stored as a {@link HashedAccountCredential} row —
|
|
100
|
+
* plaintext is never written. A repeat call for the same `username`
|
|
101
|
+
* overwrites the prior row (the PK is `account`), so this is the
|
|
102
|
+
* canonical CRUD/seed entry point for oper and SASL account
|
|
103
|
+
* provisioning.
|
|
104
|
+
*
|
|
105
|
+
* @returns The stored {@link HashedAccountCredential} (for tooling/tests).
|
|
106
|
+
*/
|
|
107
|
+
export async function putAccountCredential(
|
|
108
|
+
docClient: DynamoDBDocumentClient,
|
|
109
|
+
tableName: string,
|
|
110
|
+
username: string,
|
|
111
|
+
password: string,
|
|
112
|
+
): Promise<HashedAccountCredential> {
|
|
113
|
+
const entry = hashAccountCredential(username, password);
|
|
114
|
+
await docClient.send(
|
|
115
|
+
new PutCommand({
|
|
116
|
+
TableName: tableName,
|
|
117
|
+
Item: entry,
|
|
118
|
+
}),
|
|
119
|
+
);
|
|
120
|
+
return entry;
|
|
121
|
+
}
|