Add vault secret manager backend with AES-256-GCM encryption
Secrets are encrypted at rest in the database. The derived encryption key is held in memory only — on reboot, an authorized user must enter the master password to unlock. Admins can also manually lock the vault. - vault_config, vault_category, vault_category_permission, vault_entry tables - AES-256-GCM encryption with PBKDF2-derived key + per-entry IV - Master password initialize/unlock/lock/change lifecycle - Category CRUD with role/user permission model (view/edit/admin) - Entry CRUD with reveal endpoint (POST to avoid caching) - Secret values never returned in list/detail responses - vault.view/edit/admin RBAC permissions seeded - 19 API integration tests covering full lifecycle
This commit is contained in:
46
packages/backend/src/db/migrations/0025_vault.sql
Normal file
46
packages/backend/src/db/migrations/0025_vault.sql
Normal file
@@ -0,0 +1,46 @@
|
||||
-- Vault secret manager tables
|
||||
|
||||
CREATE TABLE vault_config (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
master_key_salt TEXT NOT NULL,
|
||||
master_key_hash TEXT NOT NULL,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE TABLE vault_category (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
name VARCHAR(255) NOT NULL,
|
||||
description TEXT,
|
||||
created_by UUID REFERENCES "user"(id),
|
||||
is_public BOOLEAN NOT NULL DEFAULT false,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE TABLE vault_category_permission (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
category_id UUID NOT NULL REFERENCES vault_category(id) ON DELETE CASCADE,
|
||||
role_id UUID REFERENCES role(id),
|
||||
user_id UUID REFERENCES "user"(id),
|
||||
access_level storage_folder_access NOT NULL DEFAULT 'view',
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE TABLE vault_entry (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
category_id UUID NOT NULL REFERENCES vault_category(id) ON DELETE CASCADE,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
username VARCHAR(255),
|
||||
url VARCHAR(1000),
|
||||
notes TEXT,
|
||||
encrypted_value TEXT,
|
||||
iv TEXT,
|
||||
created_by UUID REFERENCES "user"(id),
|
||||
updated_by UUID REFERENCES "user"(id),
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE INDEX idx_vault_category_permission_category ON vault_category_permission(category_id);
|
||||
CREATE INDEX idx_vault_entry_category ON vault_entry(category_id);
|
||||
@@ -176,6 +176,13 @@
|
||||
"when": 1774840000000,
|
||||
"tag": "0024_add_traverse_access_level",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 25,
|
||||
"version": "7",
|
||||
"when": 1774850000000,
|
||||
"tag": "0025_vault",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user