feat(security): wire /elevate to session config

This commit is contained in:
William Valentin
2026-02-15 16:59:18 -08:00
parent 735f14d0b1
commit b574d170d1
2 changed files with 247 additions and 10 deletions
+119
View File
@@ -8,6 +8,8 @@ import type { Attachment } from '../../channels/types.js';
import type { SessionManager } from '../../session/manager.js';
import type { ModelTier } from '../../models/router.js';
import type { CommandRegistry } from '../../commands/index.js';
import { auditLogger } from '../../audit/index.js';
import { randomUUID } from 'crypto';
export interface AgentHandlerDeps {
sessionBridge: SessionBridge;
@@ -129,6 +131,123 @@ export function createAgentHandlers(deps: AgentHandlerDeps) {
}
return 'Session reset.';
},
getElevation: () => {
if (!sessionId || !deps.sessionManager) {
return 'Elevated mode: off';
}
const untilRaw = deps.sessionManager.getSessionConfig('ws', sessionId, 'elevation.until_ms');
const reason = deps.sessionManager.getSessionConfig('ws', sessionId, 'elevation.reason') ?? '';
const id = deps.sessionManager.getSessionConfig('ws', sessionId, 'elevation.id') ?? '';
if (!untilRaw || !id) {
return 'Elevated mode: off';
}
const untilMs = Number.parseInt(untilRaw, 10);
if (!Number.isFinite(untilMs)) {
return 'Elevated mode: off';
}
const now = Date.now();
if (untilMs <= now) {
deps.sessionManager.deleteSessionConfig('ws', sessionId, 'elevation.until_ms');
deps.sessionManager.deleteSessionConfig('ws', sessionId, 'elevation.reason');
deps.sessionManager.deleteSessionConfig('ws', sessionId, 'elevation.id');
auditLogger?.securityElevationExpired({
session_id: `ws:${sessionId}`,
channel: 'ws',
sender: connectionId,
elevation_id: id,
until_ms: untilMs,
reason: reason || undefined,
});
return 'Elevated mode: off (expired)';
}
const remainingMs = untilMs - now;
const remainingSec = Math.ceil(remainingMs / 1000);
return `Elevated mode: on (${remainingSec}s remaining)${reason ? `${reason}` : ''}`;
},
setElevation: (input: string) => {
if (!sessionId || !deps.sessionManager) {
return 'Elevate command is not available in this session.';
}
const raw = input.trim();
const parts = raw.split(/\s+/);
const hasYes = parts.includes('--yes') || parts.includes('--confirm');
const filtered = parts.filter(p => p !== '--yes' && p !== '--confirm');
if (filtered.length === 0) {
return 'Usage: /elevate <duration> <reason...> --yes | /elevate off --yes';
}
if (filtered[0] === 'off') {
if (!hasYes) {
return 'Refusing to disable elevation without explicit confirmation. Use: /elevate off --yes';
}
const existingId = deps.sessionManager.getSessionConfig('ws', sessionId, 'elevation.id') ?? randomUUID();
const existingUntil = deps.sessionManager.getSessionConfig('ws', sessionId, 'elevation.until_ms');
const existingReason = deps.sessionManager.getSessionConfig('ws', sessionId, 'elevation.reason') ?? '';
deps.sessionManager.deleteSessionConfig('ws', sessionId, 'elevation.until_ms');
deps.sessionManager.deleteSessionConfig('ws', sessionId, 'elevation.reason');
deps.sessionManager.deleteSessionConfig('ws', sessionId, 'elevation.id');
auditLogger?.securityElevationDisabled({
session_id: `ws:${sessionId}`,
channel: 'ws',
sender: connectionId,
elevation_id: existingId,
until_ms: existingUntil ? Number.parseInt(existingUntil, 10) : undefined,
reason: existingReason || undefined,
});
return 'Elevated mode: off';
}
if (!hasYes) {
return 'Refusing to enable elevation without explicit confirmation. Use: /elevate <duration> <reason...> --yes';
}
const dur = filtered[0];
const reason = filtered.slice(1).join(' ').trim();
const ttlMs = (() => {
const m = dur.match(/^(\d+)([smhd])$/i);
if (!m) {
return null;
}
const n = Number.parseInt(m[1], 10);
if (!Number.isFinite(n) || n <= 0) {
return null;
}
const unit = m[2].toLowerCase();
if (unit === 's') {return n * 1000;}
if (unit === 'm') {return n * 60_000;}
if (unit === 'h') {return n * 3_600_000;}
if (unit === 'd') {return n * 86_400_000;}
return null;
})();
if (!ttlMs) {
return 'Invalid duration. Use one of: 30s, 10m, 1h, 1d';
}
const untilMs = Date.now() + ttlMs;
const id = randomUUID();
deps.sessionManager.setSessionConfig('ws', sessionId, 'elevation.until_ms', String(untilMs));
deps.sessionManager.setSessionConfig('ws', sessionId, 'elevation.id', id);
if (reason) {
deps.sessionManager.setSessionConfig('ws', sessionId, 'elevation.reason', reason);
} else {
deps.sessionManager.deleteSessionConfig('ws', sessionId, 'elevation.reason');
}
auditLogger?.securityElevationEnabled({
session_id: `ws:${sessionId}`,
channel: 'ws',
sender: connectionId,
elevation_id: id,
until_ms: untilMs,
ttl_ms: ttlMs,
reason: reason || undefined,
});
return `Elevated mode: on until ${new Date(untilMs).toISOString()}`;
},
},
});