phase8-p1b-lockout-and-bootstrap-contention.test.mjs
78 lines 2.7 KB
Raw
sha256:b5f647cb9c409f563d4671fe3fc05ddea01fabfed9b41fc11cb923588e1c1baf mirror: GitHub Phase A durable MCP OAuth (#270) Human minor ⚠ breaking 10 days ago
1 /**
2 * Phase 8 P1b — stress tier: lockout + bootstrap contention (§9).
3 */
4
5 import { describe, test, before, after } from 'node:test';
6 import assert from 'node:assert/strict';
7 import fs from 'fs';
8 import {
9 makeTempDataDir,
10 enableOfflineLockedTestEnv,
11 bootstrapTestAdmin,
12 TEST_PASSPHRASE,
13 TEST_SECRET,
14 } from '../helpers/phase8-p1b-local-auth-harness.mjs';
15 import {
16 authenticateLocalUser,
17 resetGlobalLoginRateLimitForTests,
18 } from '../../hub/lib/local-auth.mjs';
19 import {
20 generateSetupToken,
21 consumeSetupToken,
22 resetBootstrapRateLimitForTests,
23 } from '../../hub/lib/local-auth-bootstrap.mjs';
24
25 describe('phase8-p1b lockout and bootstrap contention (stress)', () => {
26 /** @type {{ dataDir: string, cleanup: () => void }} */
27 let tmp;
28
29 before(async () => {
30 tmp = await makeTempDataDir();
31 enableOfflineLockedTestEnv(tmp.dataDir);
32 resetGlobalLoginRateLimitForTests();
33 resetBootstrapRateLimitForTests();
34 await bootstrapTestAdmin(tmp.dataDir);
35 });
36
37 after(() => {
38 tmp.cleanup();
39 delete process.env.KNOWTATION_OFFLINE_LOCKED_AUTH;
40 delete process.env.KNOWTATION_OFFLINE_LOCKED_AUTH_TEST_SHIPPED;
41 });
42
43 test('10k failed logins lock at 5; correct passphrase blocked until unlock window', async () => {
44 const opts = { sessionSecret: TEST_SECRET, offlineLockedActive: true };
45 let locked = false;
46 for (let i = 0; i < 10000; i++) {
47 resetGlobalLoginRateLimitForTests();
48 const r = await authenticateLocalUser(tmp.dataDir, 'admin', 'wrong-' + i, opts);
49 if (r.code === 'ACCOUNT_LOCKED') {
50 locked = true;
51 if (i >= 4) break;
52 }
53 }
54 assert.equal(locked, true);
55 resetGlobalLoginRateLimitForTests();
56 const afterLock = await authenticateLocalUser(tmp.dataDir, 'admin', TEST_PASSPHRASE, opts);
57 assert.equal(afterLock.ok, false);
58 assert.equal(afterLock.code, 'ACCOUNT_LOCKED');
59 });
60
61 test('concurrent bootstrap consume: exactly one succeeds', async () => {
62 const dir = (await makeTempDataDir()).dataDir;
63 enableOfflineLockedTestEnv(dir);
64 resetBootstrapRateLimitForTests();
65 process.env.KNOWTATION_OFFLINE_LOCKED_AUTH_TEST_NO_BOOTSTRAP_RL = '1';
66 const { token } = generateSetupToken(dir, 'admin', '15m');
67 const attempts = Array.from({ length: 50 }, () =>
68 consumeSetupToken(dir, token, 'admin', TEST_PASSPHRASE, { ip: '127.0.0.1' })
69 );
70 const results = await Promise.all(attempts);
71 const okCount = results.filter((r) => r.ok).length;
72 const consumedCount = results.filter((r) => r.code === 'BOOTSTRAP_TOKEN_CONSUMED').length;
73 assert.equal(okCount, 1);
74 assert.ok(consumedCount >= 1);
75 fs.rmSync(dir, { recursive: true, force: true });
76 delete process.env.KNOWTATION_OFFLINE_LOCKED_AUTH_TEST_NO_BOOTSTRAP_RL;
77 });
78 });
File History 1 commit
sha256:b5f647cb9c409f563d4671fe3fc05ddea01fabfed9b41fc11cb923588e1c1baf mirror: GitHub Phase A durable MCP OAuth (#270) Human minor 10 days ago