/** * Registry credential vault RPC handlers. */ import * as vault from '../core/registry-vault.js' import * as validation from '../utils/validation.js' import { docker } from '../services/docker.js' import logger from '../utils/logger.js' export function registerVaultHandlers(session) { session.respond('listVaultCredentials', async () => { return { success: true, type: 'vaultCredentials', data: vault.listCredentials(), } }) session.respond('vaultStoreCredential', async (args) => { const username = validation.sanitizeString(args.username, 128) const password = args.password const serveraddress = validation.sanitizeString( args.serveraddress || 'https://index.docker.io/v1/', 512 ) if (!username || !password) throw new Error('username and password required') // Optional verify against engine if (args.verify !== false) { try { await new Promise((resolve, reject) => { docker.checkAuth({ username, password, serveraddress }, (err, res) => err ? reject(err) : resolve(res) ) }) } catch (err) { if (args.requireAuth) throw new Error(`Auth failed: ${err.message}`) logger.warn('vault store: checkAuth soft-fail', { error: err.message }) } } const stored = vault.storeCredential({ id: args.id, username, password, serveraddress, label: args.label || username, }) return { success: true, message: 'Credential stored encrypted at rest', data: stored } }) session.respond('vaultDeleteCredential', async (args) => { if (!args.id) throw new Error('credential id required') return vault.deleteCredential(args.id) }) session.respond('vaultUseCredential', async (args) => { if (!args.id) throw new Error('credential id required') const cred = vault.getCredential(args.id) if (!cred) throw new Error('Credential not found') session.state.set('registryAuth', { username: cred.username, password: cred.password, serveraddress: cred.serveraddress, }) return { success: true, message: `Using vault credential for ${cred.username}`, data: { username: cred.username, serveraddress: cred.serveraddress, }, } }) }