app 装配 mail:channel 作首个订阅方、出站经 mail.send、mail.send 工具真发信(dryRun 只校验)、轮询工作者;上传件存取抽出共用

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TM4kUBvekALu9qqmp7D3wr
This commit is contained in:
xcs
2026-08-26 02:05:50 +08:00
co-authored by Claude Fable 5
parent 58358210e2
commit 0c6e8e2c1b
10 changed files with 449 additions and 48 deletions
+3
View File
@@ -23,6 +23,8 @@ export type AppConfig = {
readonly attachmentRoot: string;
/** 派发器轮询间隔(毫秒) */
readonly dispatchIntervalMs: number;
/** 邮件轮询工作者的 tick(毫秒);每个账号自己的间隔另算 */
readonly mailPollTickMs: number;
/** 三样齐了才有;缺一样即 undefined —— main.ts 据此拒绝启动,集成测试可不配 */
readonly keycloak?: KeycloakConfig;
/** 测试账号(Keycloak 用户名):首次建档 / 播种时落 TEST 岗 + 独立工作组 */
@@ -65,6 +67,7 @@ export function loadConfig(env: NodeJS.ProcessEnv = process.env): AppConfig {
databaseUrl: env['DATABASE_URL'] ?? DEFAULT_DATABASE_URL,
attachmentRoot: env['JCAI_ATTACHMENT_ROOT'] ?? join(process.cwd(), '.data', 'attachments'),
dispatchIntervalMs: Number(env['JCAI_DISPATCH_INTERVAL_MS'] ?? 2000),
mailPollTickMs: Number(env['JCAI_MAIL_POLL_TICK_MS'] ?? 5000),
...(keycloak === undefined ? {} : { keycloak }),
testAccounts: (env['JCAI_TEST_ACCOUNTS'] ?? '')
.split(',')