From 572f4436a06f6b89595b9d2c349c8e0502ef3ab0 Mon Sep 17 00:00:00 2001 From: Sean Silvius Date: Sat, 11 Apr 2026 05:13:38 -0700 Subject: [PATCH] fix(imap): AuthAdapter JSDoc drift -- remove argon2 and D1 prescription The JSDoc above `AuthAdapter` said "App passwords are stored hashed (argon2) in D1 and verified here." That's wrong on two axes: 1. The IMAP server does not own credential storage or hashing. That was the original design but it was rewritten: AuthAdapter is an interface contract only, the consumer brings their own auth system. Prescribing argon2 contradicts the rewritten contract. 2. Core docs must be generic: "blob storage" not "R2", "database" not "D1". Referencing D1 by name inside the core protocol package violates the zero-vendor-dependency principle. Replaced with a proper JSDoc block that: - States the interface-only posture explicitly - Names the consumer's ownership (storage, hashing, generation, revocation) - Lists the security guarantees the IMAP server DOES enforce regardless of adapter implementation (generic failure response, rate limit, disconnect after max attempts) - Refers to the adapter lifecycle in neutral language This matches the authoritative `authentication.md` doc shipped in PR #76 and the interface-only posture in the `@rafters/mail-imap-server` quickstart.md fixed in PR #78. Verification: - pnpm --filter @rafters/mail-imap test: 313 passing - pnpm --filter @rafters/mail-imap typecheck: clean - pnpm --filter @rafters/mail-imap build: ESM + dts clean - pnpm lint: 0 warnings, 0 errors Co-Authored-By: Claude Opus 4.6 (1M context) --- packages/imap/src/commands/auth.ts | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/packages/imap/src/commands/auth.ts b/packages/imap/src/commands/auth.ts index af1a76c..c858989 100644 --- a/packages/imap/src/commands/auth.ts +++ b/packages/imap/src/commands/auth.ts @@ -32,8 +32,24 @@ export const SERVER_CAPABILITIES = [ /** * Adapter interface for credential verification. - * The IMAP server delegates auth to the consumer's implementation. - * App passwords are stored hashed (argon2) in D1 and verified here. + * + * The IMAP server delegates all authentication to the consumer. It does + * not own credential storage, hashing, generation, revocation, or any + * other part of the credential lifecycle. The consumer implements this + * interface against whatever auth system they use (their own database, + * a SaaS auth provider, a remote verification service, etc.). + * + * The IMAP server calls `verifyAppPassword` on every LOGIN. The adapter + * returns `true` for a valid credential and `false` for anything else -- + * wrong password, unknown user, revoked credential, rate-limited, and + * any other failure mode. The server treats all failures identically + * to prevent information leakage. + * + * Security guarantees enforced by the IMAP server regardless of adapter + * implementation: + * - Generic "LOGIN failed" response on any false return + * - Per-session rate limit (`MAX_LOGIN_ATTEMPTS`) + * - Disconnect after the attempt limit is hit */ export interface AuthAdapter { verifyAppPassword(email: string, appPassword: string): Promise;