Implement Phase 1.2: Database with encryption at rest and core infrastructure

Co-authored-by: southseact-3d <217551146+southseact-3d@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2026-02-09 19:33:00 +00:00
parent 95a2d1b98d
commit 650d849ad2
17 changed files with 2716 additions and 0 deletions

114
chat/scripts/init-database.js Executable file
View File

@@ -0,0 +1,114 @@
#!/usr/bin/env node
/**
* Database initialization script for container startup
* Automatically sets up database on first run or when database doesn't exist
*/
const fs = require('fs');
const path = require('path');
const crypto = require('crypto');
const DATA_ROOT = process.env.CHAT_DATA_ROOT || '/home/web/data/.data';
const DATABASE_PATH = process.env.DATABASE_PATH || path.join(DATA_ROOT, 'shopify_ai.db');
const USE_JSON_DATABASE = process.env.USE_JSON_DATABASE === '1' || process.env.USE_JSON_DATABASE === 'true';
async function initializeDatabase() {
// Skip if using JSON mode
if (USE_JSON_DATABASE) {
console.log('📁 Using JSON database mode (backward compatibility)');
return;
}
console.log('🔍 Checking database status...');
// Ensure data directory exists
const dataDir = path.dirname(DATABASE_PATH);
if (!fs.existsSync(dataDir)) {
console.log('📁 Creating data directory:', dataDir);
fs.mkdirSync(dataDir, { recursive: true });
}
// Check if database exists
const dbExists = fs.existsSync(DATABASE_PATH);
if (dbExists) {
console.log('✅ Database already exists:', DATABASE_PATH);
// Verify encryption key is set
if (!process.env.DATABASE_ENCRYPTION_KEY) {
console.error('❌ DATABASE_ENCRYPTION_KEY not set!');
console.error(' Database exists but encryption key is missing.');
console.error(' Set DATABASE_ENCRYPTION_KEY to the key used when creating the database.');
process.exit(1);
}
return;
}
console.log('🔧 Database not found, setting up new database...');
// Generate encryption key if not provided
if (!process.env.DATABASE_ENCRYPTION_KEY) {
const generatedKey = crypto.randomBytes(32).toString('hex');
process.env.DATABASE_ENCRYPTION_KEY = generatedKey;
console.log('⚠️ Generated new encryption key (save this!)');
console.log('⚠️ DATABASE_ENCRYPTION_KEY=' + generatedKey);
console.log('⚠️ Add this to your environment configuration to persist it!');
// Save to a file for persistence
const keyFile = path.join(dataDir, '.encryption_key');
fs.writeFileSync(keyFile, generatedKey, { mode: 0o600 });
console.log('⚠️ Saved to:', keyFile);
}
// Generate JWT secret if not provided
if (!process.env.JWT_SECRET && !process.env.SESSION_SECRET) {
const jwtSecret = crypto.randomBytes(32).toString('hex');
process.env.JWT_SECRET = jwtSecret;
console.log('⚠️ Generated new JWT secret (save this!)');
console.log('⚠️ JWT_SECRET=' + jwtSecret);
// Save to a file for persistence
const jwtFile = path.join(dataDir, '.jwt_secret');
fs.writeFileSync(jwtFile, jwtSecret, { mode: 0o600 });
console.log('⚠️ Saved to:', jwtFile);
}
// Run setup script
try {
const setupScript = require('./setup-database.js');
console.log('✅ Database setup complete');
} catch (error) {
console.error('❌ Failed to setup database:', error.message);
throw error;
}
// Check if there are JSON files to migrate
const usersFile = path.join(DATA_ROOT, 'users.json');
const sessionsFile = path.join(DATA_ROOT, 'user-sessions.json');
const hasJsonData = fs.existsSync(usersFile) || fs.existsSync(sessionsFile);
if (hasJsonData) {
console.log('📦 Found existing JSON data files');
console.log(' To migrate data, run: node scripts/migrate-to-database.js');
console.log(' Or set USE_JSON_DATABASE=1 to continue using JSON files');
}
}
// Auto-initialize if called directly
if (require.main === module) {
initializeDatabase()
.then(() => {
console.log('✅ Database initialization complete');
process.exit(0);
})
.catch(error => {
console.error('❌ Database initialization failed:', error);
process.exit(1);
});
}
module.exports = { initializeDatabase };