fix(channels): normalize direct dm guard numeric overrides

This commit is contained in:
Peter Steinberger
2026-05-29 01:28:40 -04:00
parent fa1d5f6584
commit 6bf2fdf739
2 changed files with 60 additions and 7 deletions
+36 -7
View File
@@ -1,3 +1,5 @@
import { resolveIntegerOption } from "../shared/number-coercion.js";
export type DirectDmPreCryptoGuardPolicy = {
allowedKinds: readonly number[];
maxFutureSkewSec: number;
@@ -21,16 +23,43 @@ export type DirectDmPreCryptoGuardPolicyOverrides = Partial<
export function createDirectDmPreCryptoGuardPolicy(
overrides: DirectDmPreCryptoGuardPolicyOverrides = {},
): DirectDmPreCryptoGuardPolicy {
const defaultMaxFutureSkewSec = 120;
const defaultMaxCiphertextBytes = 16 * 1024;
const defaultMaxPlaintextBytes = 8 * 1024;
const defaultWindowMs = 60_000;
const defaultMaxPerSenderPerWindow = 20;
const defaultMaxGlobalPerWindow = 200;
const defaultMaxTrackedSenderKeys = 4096;
return {
allowedKinds: overrides.allowedKinds ?? [4],
maxFutureSkewSec: overrides.maxFutureSkewSec ?? 120,
maxCiphertextBytes: overrides.maxCiphertextBytes ?? 16 * 1024,
maxPlaintextBytes: overrides.maxPlaintextBytes ?? 8 * 1024,
maxFutureSkewSec: resolveIntegerOption(overrides.maxFutureSkewSec, defaultMaxFutureSkewSec, {
min: 0,
}),
maxCiphertextBytes: resolveIntegerOption(
overrides.maxCiphertextBytes,
defaultMaxCiphertextBytes,
{ min: 1 },
),
maxPlaintextBytes: resolveIntegerOption(overrides.maxPlaintextBytes, defaultMaxPlaintextBytes, {
min: 1,
}),
rateLimit: {
windowMs: overrides.rateLimit?.windowMs ?? 60_000,
maxPerSenderPerWindow: overrides.rateLimit?.maxPerSenderPerWindow ?? 20,
maxGlobalPerWindow: overrides.rateLimit?.maxGlobalPerWindow ?? 200,
maxTrackedSenderKeys: overrides.rateLimit?.maxTrackedSenderKeys ?? 4096,
windowMs: resolveIntegerOption(overrides.rateLimit?.windowMs, defaultWindowMs, { min: 1 }),
maxPerSenderPerWindow: resolveIntegerOption(
overrides.rateLimit?.maxPerSenderPerWindow,
defaultMaxPerSenderPerWindow,
{ min: 1 },
),
maxGlobalPerWindow: resolveIntegerOption(
overrides.rateLimit?.maxGlobalPerWindow,
defaultMaxGlobalPerWindow,
{ min: 1 },
),
maxTrackedSenderKeys: resolveIntegerOption(
overrides.rateLimit?.maxTrackedSenderKeys,
defaultMaxTrackedSenderKeys,
{ min: 1 },
),
},
};
}
+24
View File
@@ -186,6 +186,30 @@ describe("plugin-sdk/direct-dm", () => {
expect(policy.rateLimit.maxGlobalPerWindow).toBe(200);
});
it("defaults non-finite shared pre-crypto guard numeric overrides", () => {
const policy = createDirectDmPreCryptoGuardPolicy({
maxFutureSkewSec: Number.NaN,
maxCiphertextBytes: Number.POSITIVE_INFINITY,
maxPlaintextBytes: Number.NEGATIVE_INFINITY,
rateLimit: {
windowMs: Number.NaN,
maxPerSenderPerWindow: Number.POSITIVE_INFINITY,
maxGlobalPerWindow: Number.NEGATIVE_INFINITY,
maxTrackedSenderKeys: Number.NaN,
},
});
expect(policy.maxFutureSkewSec).toBe(120);
expect(policy.maxCiphertextBytes).toBe(16 * 1024);
expect(policy.maxPlaintextBytes).toBe(8 * 1024);
expect(policy.rateLimit).toEqual({
windowMs: 60_000,
maxPerSenderPerWindow: 20,
maxGlobalPerWindow: 200,
maxTrackedSenderKeys: 4096,
});
});
it("dispatches direct DMs through the standard route/session/reply pipeline", async () => {
const { recordInboundSession, dispatchReplyWithBufferedBlockDispatcher, runtime } =
createDirectDmRuntime();