refactor(crypto): make system-wrapped DEKs the authoritative key path

DataCrypto and AuthManager now read keys through UserKeyManager: DEKs are
always unwrappable server-side, so the in-memory unlock session, DEK-in-JWT
wrapping, session-expiry data locks and ALLOW_APIKEY_DATA_UNLOCK are gone.
utils/user-crypto.ts is deleted; boot migration now cleans legacy wraps.
A one-release shim adopts DEKs from legacy dataKeyWrap tokens so active
password users migrate without re-login. Password login migrates legacy
password-wrapped DEKs via migratePasswordUserAtLogin.
This commit is contained in:
LukeGus
2026-07-16 00:19:12 -05:00
parent 16506de9da
commit ee7768dd86
14 changed files with 234 additions and 1114 deletions
+3 -6
View File
@@ -4,7 +4,7 @@ import { WebSocket } from "ws";
import { OPKSSHBinaryManager } from "../utils/opkssh-binary-manager.js";
import { sshLogger } from "../utils/logger.js";
import { createCurrentOpksshTokenRepository } from "../database/repositories/factory.js";
import { UserCrypto } from "../utils/user-crypto.js";
import { DataCrypto } from "../utils/data-crypto.js";
import { FieldCrypto } from "../utils/field-crypto.js";
import { promises as fs } from "fs";
import path from "path";
@@ -647,12 +647,10 @@ function handleOPKSSHOutput(requestId: string, output: string): void {
async function storeOPKSSHToken(session: OPKSSHAuthSession): Promise<void> {
try {
const userCrypto = UserCrypto.getInstance();
const expiresAt = new Date();
expiresAt.setHours(expiresAt.getHours() + 24);
const userDataKey = userCrypto.getUserDataKey(session.userId);
const userDataKey = DataCrypto.getUserDataKey(session.userId);
if (!userDataKey) {
throw new Error("User data key not found");
}
@@ -729,8 +727,7 @@ export async function getOPKSSHToken(
return null;
}
const userCrypto = UserCrypto.getInstance();
const userDataKey = userCrypto.getUserDataKey(userId);
const userDataKey = DataCrypto.getUserDataKey(userId);
if (!userDataKey) {
throw new Error("User data key not found");
}