CRITICAL FIX: Server would CRASH ON STARTUP (multiple import errors)
REMOVED (2 scripts):
1. scripts/framework-watchdog.js
- Monitored .claude/session-state.json (OUR Claude Code setup)
- Monitored .claude/token-checkpoints.json (OUR file structure)
- Implementers won't have our .claude/ directory
2. scripts/init-db.js
- Created website collections: blog_posts, media_inquiries, case_submissions
- Created website collections: resources, moderation_queue, users, citations
- Created website collections: translations, koha_donations
- Next steps referenced deleted scripts (npm run seed:admin)
REWRITTEN (2 files):
src/models/index.js (29 lines → 27 lines)
- REMOVED imports: Document, BlogPost, MediaInquiry, CaseSubmission, Resource
- REMOVED imports: ModerationQueue, User (all deleted in Phase 2)
- KEPT imports: AuditLog, DeliberationSession, GovernanceLog, GovernanceRule
- KEPT imports: Precedent, Project, SessionState, VariableValue, VerificationLog
- Result: Only framework models exported
src/server.js (284 lines → 163 lines, 43% reduction)
- REMOVED: Imports to deleted middleware (csrf-protection, response-sanitization)
- REMOVED: Stripe webhook handling (/api/koha/webhook)
- REMOVED: Static file caching (for deleted public/ directory)
- REMOVED: Static file serving (public/ deleted in Phase 6)
- REMOVED: CSRF token endpoint
- REMOVED: Website homepage with "auth, documents, blog, admin" references
- REMOVED: Instruction sync (scripts/sync-instructions-to-db.js reference)
- REMOVED: Hardcoded log path (${process.env.HOME}/var/log/tractatus/...)
- REMOVED: Website-specific security middleware
- KEPT: Security headers, rate limiting, CORS, body parsers
- KEPT: API routes, governance services, MongoDB connections
- RESULT: Clean framework-only server
RESULT: Repository can now start without crashes, all imports resolve
🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
245 lines
8.7 KiB
JavaScript
Executable file
245 lines
8.7 KiB
JavaScript
Executable file
#!/usr/bin/env node
|
|
/**
|
|
* Seed Projects Script
|
|
* Creates sample projects and their variable values for development/testing
|
|
*
|
|
* Usage: npm run seed:projects
|
|
*/
|
|
|
|
require('dotenv').config();
|
|
|
|
const { connect: connectDb, close: closeDb } = require('../src/utils/db.util');
|
|
const { connect: connectMongoose, close: closeMongoose } = require('../src/utils/mongoose.util');
|
|
const Project = require('../src/models/Project.model');
|
|
const VariableValue = require('../src/models/VariableValue.model');
|
|
const logger = require('../src/utils/logger.util');
|
|
|
|
/**
|
|
* Sample projects with their variable values
|
|
*/
|
|
const sampleProjects = [
|
|
{
|
|
id: 'tractatus',
|
|
name: 'Tractatus AI Safety Framework',
|
|
description: 'The Tractatus website - multi-project governance system with AI safety framework',
|
|
techStack: {
|
|
framework: 'Express.js',
|
|
database: 'MongoDB',
|
|
frontend: 'Vanilla JavaScript',
|
|
css: 'Tailwind CSS'
|
|
},
|
|
repositoryUrl: 'https://github.com/example/tractatus',
|
|
metadata: {
|
|
environment: 'production',
|
|
domain: 'tractatus.org'
|
|
},
|
|
active: true,
|
|
variables: [
|
|
{ name: 'DB_NAME', value: 'tractatus_prod', description: 'Production database name', category: 'database' },
|
|
{ name: 'DB_PORT', value: '27017', description: 'MongoDB port', category: 'database' },
|
|
{ name: 'APP_PORT', value: '9000', description: 'Application HTTP port', category: 'config' },
|
|
{ name: 'API_BASE_URL', value: 'https://tractatus.org/api', description: 'Base URL for API', category: 'url' },
|
|
{ name: 'SESSION_SECRET', value: 'PROD_SECRET_KEY', description: 'Session encryption key', category: 'security' },
|
|
{ name: 'LOG_LEVEL', value: 'info', description: 'Logging verbosity', category: 'config' },
|
|
{ name: 'MAX_UPLOAD_SIZE', value: '10485760', description: 'Max file upload size (10MB)', category: 'config' }
|
|
]
|
|
},
|
|
{
|
|
id: 'family-history',
|
|
name: 'Family History Archive',
|
|
description: 'Digital family archive with document management and OCR capabilities',
|
|
techStack: {
|
|
framework: 'Express.js',
|
|
database: 'MongoDB',
|
|
frontend: 'React',
|
|
css: 'Tailwind CSS',
|
|
storage: 'S3-compatible'
|
|
},
|
|
repositoryUrl: 'https://github.com/example/family-history',
|
|
metadata: {
|
|
environment: 'development',
|
|
features: ['OCR', 'Document Management', 'Search']
|
|
},
|
|
active: true,
|
|
variables: [
|
|
{ name: 'DB_NAME', value: 'family_history_dev', description: 'Development database name', category: 'database' },
|
|
{ name: 'DB_PORT', value: '27017', description: 'MongoDB port', category: 'database' },
|
|
{ name: 'APP_PORT', value: '3000', description: 'Application HTTP port', category: 'config' },
|
|
{ name: 'API_BASE_URL', value: 'http://localhost:3000/api', description: 'Base URL for API', category: 'url' },
|
|
{ name: 'STORAGE_BUCKET', value: 'family-history-documents', description: 'S3 bucket name', category: 'path' },
|
|
{ name: 'OCR_ENABLED', value: 'true', description: 'Enable OCR processing', category: 'feature_flag', dataType: 'boolean' },
|
|
{ name: 'MAX_UPLOAD_SIZE', value: '52428800', description: 'Max file upload size (50MB)', category: 'config' },
|
|
{ name: 'LOG_LEVEL', value: 'debug', description: 'Logging verbosity', category: 'config' }
|
|
]
|
|
},
|
|
{
|
|
id: 'sydigital',
|
|
name: 'SyDigital Platform',
|
|
description: 'Digital transformation platform for enterprise solutions',
|
|
techStack: {
|
|
framework: 'Next.js',
|
|
database: 'PostgreSQL',
|
|
frontend: 'React',
|
|
css: 'Styled Components',
|
|
cache: 'Redis'
|
|
},
|
|
repositoryUrl: 'https://github.com/example/sydigital',
|
|
metadata: {
|
|
environment: 'staging',
|
|
tier: 'enterprise'
|
|
},
|
|
active: true,
|
|
variables: [
|
|
{ name: 'DB_NAME', value: 'sydigital_staging', description: 'Staging database name', category: 'database' },
|
|
{ name: 'DB_PORT', value: '5432', description: 'PostgreSQL port', category: 'database', dataType: 'number' },
|
|
{ name: 'APP_PORT', value: '3001', description: 'Application HTTP port', category: 'config' },
|
|
{ name: 'API_BASE_URL', value: 'https://staging.sydigital.com/api', description: 'Base URL for API', category: 'url' },
|
|
{ name: 'REDIS_URL', value: 'redis://localhost:6379', description: 'Redis connection URL', category: 'url' },
|
|
{ name: 'CACHE_TTL', value: '3600', description: 'Cache TTL in seconds', category: 'config', dataType: 'number' },
|
|
{ name: 'API_RATE_LIMIT', value: '1000', description: 'API requests per hour', category: 'config', dataType: 'number' },
|
|
{ name: 'LOG_LEVEL', value: 'warn', description: 'Logging verbosity', category: 'config' }
|
|
]
|
|
},
|
|
{
|
|
id: 'example-project',
|
|
name: 'Example Project',
|
|
description: 'Template project for testing and demonstration purposes',
|
|
techStack: {
|
|
framework: 'Express.js',
|
|
database: 'MongoDB',
|
|
frontend: 'Vanilla JavaScript'
|
|
},
|
|
repositoryUrl: null,
|
|
metadata: {
|
|
environment: 'development',
|
|
purpose: 'testing'
|
|
},
|
|
active: false, // Inactive to demonstrate filtering
|
|
variables: [
|
|
{ name: 'DB_NAME', value: 'example_db', description: 'Example database', category: 'database' },
|
|
{ name: 'DB_PORT', value: '27017', description: 'MongoDB port', category: 'database' },
|
|
{ name: 'APP_PORT', value: '8080', description: 'Application port', category: 'config' }
|
|
]
|
|
}
|
|
];
|
|
|
|
async function seedProjects() {
|
|
try {
|
|
console.log('\n=== Tractatus Projects & Variables Seed ===\n');
|
|
|
|
// Connect to database (both native and Mongoose)
|
|
await connectDb();
|
|
await connectMongoose();
|
|
|
|
// Get existing projects count
|
|
const existingCount = await Project.countDocuments();
|
|
|
|
if (existingCount > 0) {
|
|
console.log(`⚠️ Found ${existingCount} existing project(s) in database.`);
|
|
console.log('This will DELETE ALL existing projects and variables!');
|
|
console.log('Continue? (yes/no): ');
|
|
|
|
// Read from stdin
|
|
const readline = require('readline');
|
|
const rl = readline.createInterface({
|
|
input: process.stdin,
|
|
output: process.stdout
|
|
});
|
|
|
|
const answer = await new Promise(resolve => {
|
|
rl.question('', resolve);
|
|
});
|
|
rl.close();
|
|
|
|
if (answer.toLowerCase() !== 'yes') {
|
|
console.log('Cancelled. No changes made.');
|
|
await cleanup();
|
|
return;
|
|
}
|
|
|
|
// Delete all existing projects and variables
|
|
await Project.deleteMany({});
|
|
await VariableValue.deleteMany({});
|
|
console.log('✅ Deleted all existing projects and variables.\n');
|
|
}
|
|
|
|
// Create projects and variables
|
|
let createdCount = 0;
|
|
let variableCount = 0;
|
|
|
|
for (const projectData of sampleProjects) {
|
|
const { variables, ...projectInfo } = projectData;
|
|
|
|
// Create project
|
|
const project = new Project({
|
|
...projectInfo,
|
|
createdBy: 'seed-script',
|
|
updatedBy: 'seed-script'
|
|
});
|
|
|
|
await project.save();
|
|
createdCount++;
|
|
|
|
console.log(`✅ Created project: ${project.name} (${project.id})`);
|
|
|
|
// Create variables for this project
|
|
if (variables && variables.length > 0) {
|
|
for (const varData of variables) {
|
|
const variable = new VariableValue({
|
|
projectId: project.id,
|
|
variableName: varData.name,
|
|
value: varData.value,
|
|
description: varData.description || '',
|
|
category: varData.category || 'other',
|
|
dataType: varData.dataType || 'string',
|
|
active: true,
|
|
createdBy: 'seed-script',
|
|
updatedBy: 'seed-script'
|
|
});
|
|
|
|
await variable.save();
|
|
variableCount++;
|
|
}
|
|
|
|
console.log(` └─ Created ${variables.length} variable(s)`);
|
|
}
|
|
}
|
|
|
|
console.log('\n=== Seed Complete ===');
|
|
console.log(`✅ Created ${createdCount} projects`);
|
|
console.log(`✅ Created ${variableCount} variables`);
|
|
console.log('\nYou can now:');
|
|
console.log(' - View projects: GET /api/admin/projects');
|
|
console.log(' - View variables: GET /api/admin/projects/:projectId/variables');
|
|
console.log(' - Test substitution: GET /api/admin/rules?projectId=tractatus');
|
|
console.log('');
|
|
|
|
logger.info(`Projects seeded: ${createdCount} projects, ${variableCount} variables`);
|
|
|
|
} catch (error) {
|
|
console.error('\n❌ Error seeding projects:', error.message);
|
|
logger.error('Projects seed error:', error);
|
|
process.exit(1);
|
|
} finally {
|
|
await cleanup();
|
|
}
|
|
}
|
|
|
|
async function cleanup() {
|
|
await closeDb();
|
|
await closeMongoose();
|
|
}
|
|
|
|
// Handle Ctrl+C
|
|
process.on('SIGINT', async () => {
|
|
console.log('\n\n👋 Cancelled by user');
|
|
await cleanup();
|
|
process.exit(0);
|
|
});
|
|
|
|
// Run if called directly
|
|
if (require.main === module) {
|
|
seedProjects();
|
|
}
|
|
|
|
module.exports = seedProjects;
|