mirror of
https://github.com/PR0M3TH3AN/SeedPass.git
synced 2026-10-30 01:12:17 +00:00
Collapse the duplicated high-risk expiry rule; close agent mutation gaps
Mutation testing carried agent.ts to zero survivors (37 mutants, all killed or non-compiling). Four gaps, in descending order of how much they mattered: The high-risk session's expiry was decided in two places -- the sweep in expire() and a second comparison inside highRiskTag(). Breaking EITHER left the whole suite green, because each covered for the other. Worse, the copy in highRiskTag() was unreachable: handle() sweeps before it dispatches, so no request could ever arrive with an expired session still in the map. It read like a check and enforced nothing. highRiskTag() now sweeps instead of re-testing expiresAt, so the rule has one home and a test can hold it to account. The remaining three were missing assertions, not missing checks: - `put`'s `!fingerprint || !mnemonic` guard could become `&&` unnoticed. Both fields are re-validated downstream, so nothing is permitted that was not before -- but a blank mnemonic then reports "fingerprint does not match the supplied seed", sending whoever reads it after the wrong field. Tests now pin the message. - Same shape on high-risk-unlock's fingerprint format guard: disabling it entirely still refused, via "profile not unlocked" -- a lie about a string that could never be a profile. It is also the guard between a caller-supplied string and the audit-log path join, so it should be the one that answers. - highRiskStatus's client-side `expires_at === null` decode was never asserted; inverted, it reports 0 for a locked profile and null for a live one. That number is how a caller knows what is left of the second factor. Also hoists FROZEN/TAG/daemonAt to module scope so the new tests share the injectable clock. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01Vtx94nXDmNgXEeThUZP4QN
This commit is contained in:
1 parent
17b94d3e26
commit
62e577a6e1
2 files changed
+162
-26
No files matched your search
@@ -541,13 +541,15 @@ export class AgentDaemon {
|
||||
* partition, so recording it would put it on disk by another route.
|
||||
*/
|
||||
private highRiskTag(fingerprint: string): string {
|
||||
const session = this.highRisk.get(fingerprint);
|
||||
if (!session) return "";
|
||||
if (session.expiresAt <= this.now()) {
|
||||
this.highRisk.delete(fingerprint);
|
||||
return "";
|
||||
}
|
||||
return session.tag;
|
||||
// Sweep rather than re-test `expiresAt` here. This used to carry its own
|
||||
// copy of the expiry comparison, which was wrong twice over: it was a
|
||||
// second place the rule could drift from expire(), and -- because
|
||||
// handle() sweeps before it dispatches -- it was a copy no request could
|
||||
// ever reach. Mutation testing found it: breaking EITHER comparison left
|
||||
// the whole suite green, because each one covered for the other. One
|
||||
// decision point means a test can actually hold it to account.
|
||||
this.expire();
|
||||
return this.highRisk.get(fingerprint)?.tag ?? "";
|
||||
}
|
||||
|
||||
private async handle(msg: Record<string, unknown>): Promise<Record<string, unknown>> {
|
||||
|
||||
Reference in new issue
Block a user