feat(pairing): add PairingStore interface for persistence injection

This commit is contained in:
William Valentin
2026-02-09 21:42:17 -08:00
parent c3ca3f3776
commit 1e1a68924e
3 changed files with 79 additions and 7 deletions
+25 -5
View File
@@ -14,7 +14,7 @@ interface PendingCode {
label?: string;
}
interface ApprovedSender {
export interface ApprovedSender {
channel: string;
senderId: string;
approvedAt: number;
@@ -22,6 +22,12 @@ interface ApprovedSender {
codeUsed: string;
}
export interface PairingStore {
loadApproved(): ApprovedSender[];
saveApproved(sender: ApprovedSender): void;
removeApproved(channel: string, senderId: string): void;
}
/**
* Manages DM pairing codes for authenticating unknown senders.
*
@@ -35,9 +41,17 @@ export class PairingManager {
private config: PairingConfig;
private pendingCodes: Map<string, PendingCode> = new Map();
private approvedSenders: Map<string, ApprovedSender> = new Map();
private store?: PairingStore;
constructor(config: PairingConfig) {
constructor(config: PairingConfig, store?: PairingStore) {
this.config = config;
this.store = store;
if (store) {
for (const sender of store.loadApproved()) {
const key = `${sender.channel}:${sender.senderId}`;
this.approvedSenders.set(key, sender);
}
}
}
/** Generate a new pairing code. Returns the code string. */
@@ -77,12 +91,14 @@ export class PairingManager {
// Code is valid — approve the sender
const key = `${channel}:${senderId}`;
this.approvedSenders.set(key, {
const approved: ApprovedSender = {
channel,
senderId,
approvedAt: Date.now(),
codeUsed: normalizedCode,
});
};
this.approvedSenders.set(key, approved);
this.store?.saveApproved(approved);
// Remove the used code
this.pendingCodes.delete(normalizedCode);
@@ -98,7 +114,11 @@ export class PairingManager {
/** Revoke approval for a sender. Returns true if the sender was found and removed. */
revokeApproval(channel: string, senderId: string): boolean {
const key = `${channel}:${senderId}`;
return this.approvedSenders.delete(key);
const deleted = this.approvedSenders.delete(key);
if (deleted) {
this.store?.removeApproved(channel, senderId);
}
return deleted;
}
/** List all currently approved senders. */