From c34195aeb0444b48915128dab3328904641e1de4 Mon Sep 17 00:00:00 2001 From: Jayesh Betala Date: Tue, 2 Jun 2026 12:24:55 +0530 Subject: [PATCH] fix(one-way-doors): treat 'rotate ... password' as a one-way door The credential-rotation keyword pattern in the one-way-door safety net omitted 'password' from its noun alternation, while the sibling 'revoke' and 'reset' patterns both include it. As a result classifyQuestion / isOneWayDoor classified 'rotate the database password' as a reversible two-way door, so a credential-rotation question could be suppressed by a permissive tuning preference instead of always asking. Add 'password' to the rotate alternation for parity with revoke/reset, and add a regression test in the one-way-doors classifier block. Fixes #1839 Co-Authored-By: Claude Opus 4.8 (1M context) --- scripts/one-way-doors.ts | 2 +- test/plan-tune.test.ts | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/scripts/one-way-doors.ts b/scripts/one-way-doors.ts index 1f566fabb..6735c386d 100644 --- a/scripts/one-way-doors.ts +++ b/scripts/one-way-doors.ts @@ -65,7 +65,7 @@ const DESTRUCTIVE_PATTERNS: RegExp[] = [ // Credentials / auth — allow filler words ("the", "my") between verb and noun /\brevoke\s+[\w\s]*\b(api key|token|credential|access key|password)\b/i, /\breset\s+[\w\s]*\b(api key|token|password|credential)\b/i, - /\brotate\s+[\w\s]*\b(api key|token|secret|credential|access key)\b/i, + /\brotate\s+[\w\s]*\b(api key|token|secret|credential|access key|password)\b/i, // Scope / architecture forks (reversible with effort — still deserve confirmation) /\barchitectur(e|al)\s+(change|fork|shift|decision)\b/i, diff --git a/test/plan-tune.test.ts b/test/plan-tune.test.ts index 40a1465b6..6ddd6f5d5 100644 --- a/test/plan-tune.test.ts +++ b/test/plan-tune.test.ts @@ -426,6 +426,19 @@ describe('one-way-doors classifier', () => { } }); + test('rotate password is one-way (parity with revoke/reset)', () => { + const cases = [ + 'Rotate the database password?', + 'rotate password for the service account', + ]; + for (const summary of cases) { + const result = classifyQuestion({ summary }); + expect(result.oneWay).toBe(true); + expect(result.reason).toBe('keyword'); + expect(result.matched).toBeDefined(); + } + }); + test('skill-category fallback fires for cso:approval and land-and-deploy:approval', () => { expect(isOneWayDoor({ skill: 'cso', category: 'approval' })).toBe(true); expect(isOneWayDoor({ skill: 'land-and-deploy', category: 'approval' })).toBe(true);