refactor(lint): fix code style and unused variables across src/
- Fixed unused function parameters by prefixing with underscore - Removed unused imports and variables - Applied eslint --fix for automatic style fixes - Property shorthand - String template literals - Prefer const over let where appropriate - Spacing and formatting Reduces lint errors from 108+ to 78 (61 unused vars, 17 other issues) Related to CI lint failures in previous commit 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
fc236ffc00
commit
40601f7d27
41 changed files with 97 additions and 100 deletions
|
|
@ -102,7 +102,7 @@ async function getAuditAnalytics(req, res) {
|
||||||
const { days = 7 } = req.query;
|
const { days = 7 } = req.query;
|
||||||
|
|
||||||
// Get audit logs
|
// Get audit logs
|
||||||
const auditLogsResponse = await getAuditLogs(req, { json: (data) => data });
|
const auditLogsResponse = await getAuditLogs(req, { json: data => data });
|
||||||
const decisions = auditLogsResponse.decisions;
|
const decisions = auditLogsResponse.decisions;
|
||||||
|
|
||||||
// Calculate analytics
|
// Calculate analytics
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ async function getInbox(req, res) {
|
||||||
skip: parseInt(skip)
|
skip: parseInt(skip)
|
||||||
};
|
};
|
||||||
|
|
||||||
let items = [];
|
const items = [];
|
||||||
|
|
||||||
// Fetch contacts
|
// Fetch contacts
|
||||||
if (!type || type === 'all' || type === 'contact') {
|
if (!type || type === 'all' || type === 'contact') {
|
||||||
|
|
@ -137,7 +137,7 @@ async function getStats(req, res) {
|
||||||
* Helper: Get media inquiry statistics
|
* Helper: Get media inquiry statistics
|
||||||
*/
|
*/
|
||||||
async function getMediaStats() {
|
async function getMediaStats() {
|
||||||
const [total, newCount, triagedCount, respondedCount, closedCount] = await Promise.all([
|
const [_total, newCount, triagedCount, respondedCount, closedCount] = await Promise.all([
|
||||||
MediaInquiry.countByStatus('new'),
|
MediaInquiry.countByStatus('new'),
|
||||||
MediaInquiry.countByStatus('new'),
|
MediaInquiry.countByStatus('new'),
|
||||||
MediaInquiry.countByStatus('triaged'),
|
MediaInquiry.countByStatus('triaged'),
|
||||||
|
|
|
||||||
|
|
@ -237,7 +237,7 @@ exports.verifySession = async (req, res) => {
|
||||||
amount: session.amount_total / 100,
|
amount: session.amount_total / 100,
|
||||||
currency: session.currency,
|
currency: session.currency,
|
||||||
frequency: session.metadata.frequency,
|
frequency: session.metadata.frequency,
|
||||||
isSuccessful: isSuccessful
|
isSuccessful
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -269,7 +269,7 @@ exports.createPortalSession = async (req, res) => {
|
||||||
// Find customer by email
|
// Find customer by email
|
||||||
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
|
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
|
||||||
const customers = await stripe.customers.list({
|
const customers = await stripe.customers.list({
|
||||||
email: email,
|
email,
|
||||||
limit: 1
|
limit: 1
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -285,7 +285,7 @@ exports.createPortalSession = async (req, res) => {
|
||||||
// Create portal session
|
// Create portal session
|
||||||
const session = await stripe.billingPortal.sessions.create({
|
const session = await stripe.billingPortal.sessions.create({
|
||||||
customer: customer.id,
|
customer: customer.id,
|
||||||
return_url: `${process.env.FRONTEND_URL || 'https://agenticgovernance.digital'}/koha.html`,
|
return_url: `${process.env.FRONTEND_URL || 'https://agenticgovernance.digital'}/koha.html`
|
||||||
});
|
});
|
||||||
|
|
||||||
logger.info(`[KOHA] Customer portal session created for ${email}`);
|
logger.info(`[KOHA] Customer portal session created for ${email}`);
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ async function getAllProjects(req, res) {
|
||||||
try {
|
try {
|
||||||
const { active, database, limit } = req.query;
|
const { active, database, limit } = req.query;
|
||||||
|
|
||||||
let query = {};
|
const query = {};
|
||||||
|
|
||||||
// Filter by active status if specified
|
// Filter by active status if specified
|
||||||
if (active !== undefined) {
|
if (active !== undefined) {
|
||||||
|
|
@ -45,7 +45,7 @@ async function getAllProjects(req, res) {
|
||||||
|
|
||||||
// Get variable counts for each project
|
// Get variable counts for each project
|
||||||
const projectsWithCounts = await Promise.all(
|
const projectsWithCounts = await Promise.all(
|
||||||
projects.map(async (project) => {
|
projects.map(async project => {
|
||||||
const variableCount = await VariableValue.countDocuments({
|
const variableCount = await VariableValue.countDocuments({
|
||||||
projectId: project.id,
|
projectId: project.id,
|
||||||
active: true
|
active: true
|
||||||
|
|
|
||||||
|
|
@ -91,7 +91,7 @@ async function getSubmissions(req, res) {
|
||||||
|
|
||||||
// Manually fetch blog post titles for submissions that have blogPostId
|
// Manually fetch blog post titles for submissions that have blogPostId
|
||||||
const submissionsWithBlogData = await Promise.all(
|
const submissionsWithBlogData = await Promise.all(
|
||||||
submissions.map(async (submission) => {
|
submissions.map(async submission => {
|
||||||
const submissionObj = submission.toObject();
|
const submissionObj = submission.toObject();
|
||||||
|
|
||||||
if (submissionObj.blogPostId) {
|
if (submissionObj.blogPostId) {
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ const logger = require('../utils/logger.util');
|
||||||
/**
|
/**
|
||||||
* 404 Not Found handler
|
* 404 Not Found handler
|
||||||
*/
|
*/
|
||||||
function notFound(req, res, next) {
|
function notFound(req, res, _next) {
|
||||||
res.status(404).json({
|
res.status(404).json({
|
||||||
error: 'Not Found',
|
error: 'Not Found',
|
||||||
message: `Route ${req.method} ${req.originalUrl} not found`
|
message: `Route ${req.method} ${req.originalUrl} not found`
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@
|
||||||
* Production: Generic error messages only
|
* Production: Generic error messages only
|
||||||
* Development: More detailed errors for debugging
|
* Development: More detailed errors for debugging
|
||||||
*/
|
*/
|
||||||
function sanitizeErrorResponse(err, req, res, next) {
|
function sanitizeErrorResponse(err, req, res, _next) {
|
||||||
const isProduction = process.env.NODE_ENV === 'production';
|
const isProduction = process.env.NODE_ENV === 'production';
|
||||||
|
|
||||||
// Log full error details internally (always)
|
// Log full error details internally (always)
|
||||||
|
|
@ -46,7 +46,7 @@ function sanitizeErrorResponse(err, req, res, next) {
|
||||||
if (isProduction) {
|
if (isProduction) {
|
||||||
return res.status(statusCode).json({
|
return res.status(statusCode).json({
|
||||||
error: genericErrors[statusCode] || 'Error',
|
error: genericErrors[statusCode] || 'Error',
|
||||||
message: err.message || 'An error occurred',
|
message: err.message || 'An error occurred'
|
||||||
// NEVER include in production: stack, file paths, internal details
|
// NEVER include in production: stack, file paths, internal details
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ function securityHeadersMiddleware(req, res, next) {
|
||||||
"frame-ancestors 'none'",
|
"frame-ancestors 'none'",
|
||||||
"base-uri 'self'",
|
"base-uri 'self'",
|
||||||
"form-action 'self'",
|
"form-action 'self'",
|
||||||
"upgrade-insecure-requests"
|
'upgrade-insecure-requests'
|
||||||
].join('; ')
|
].join('; ')
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,7 @@ function validateRequired(fields) {
|
||||||
return res.status(400).json({
|
return res.status(400).json({
|
||||||
error: 'Validation failed',
|
error: 'Validation failed',
|
||||||
message: 'Required fields missing',
|
message: 'Required fields missing',
|
||||||
missing: missing
|
missing
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -83,12 +83,12 @@ function validateRequired(fields) {
|
||||||
* Sanitize string inputs
|
* Sanitize string inputs
|
||||||
*/
|
*/
|
||||||
function sanitizeInputs(req, res, next) {
|
function sanitizeInputs(req, res, next) {
|
||||||
const sanitizeString = (str) => {
|
const sanitizeString = str => {
|
||||||
if (typeof str !== 'string') return str;
|
if (typeof str !== 'string') return str;
|
||||||
return validator.escape(str.trim());
|
return validator.escape(str.trim());
|
||||||
};
|
};
|
||||||
|
|
||||||
const sanitizeObject = (obj) => {
|
const sanitizeObject = obj => {
|
||||||
const sanitized = {};
|
const sanitized = {};
|
||||||
|
|
||||||
for (const [key, value] of Object.entries(obj)) {
|
for (const [key, value] of Object.entries(obj)) {
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ class Donation {
|
||||||
donor: {
|
donor: {
|
||||||
name: data.donor?.name || 'Anonymous',
|
name: data.donor?.name || 'Anonymous',
|
||||||
email: data.donor?.email, // Required for receipt, kept private
|
email: data.donor?.email, // Required for receipt, kept private
|
||||||
country: data.donor?.country,
|
country: data.donor?.country
|
||||||
// Do NOT store full address unless required for tax purposes
|
// Do NOT store full address unless required for tax purposes
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -230,7 +230,7 @@ class Donation {
|
||||||
monthly_supporters: monthlySupporters,
|
monthly_supporters: monthlySupporters,
|
||||||
one_time_donations: oneTimeDonations,
|
one_time_donations: oneTimeDonations,
|
||||||
monthly_recurring_revenue: monthlyRevenue,
|
monthly_recurring_revenue: monthlyRevenue,
|
||||||
allocation: allocation,
|
allocation,
|
||||||
recent_donors: publicDonors,
|
recent_donors: publicDonors,
|
||||||
last_updated: new Date()
|
last_updated: new Date()
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -141,7 +141,7 @@ class ModerationQueue {
|
||||||
{ _id: new ObjectId(id) },
|
{ _id: new ObjectId(id) },
|
||||||
{
|
{
|
||||||
$set: {
|
$set: {
|
||||||
status: status,
|
status,
|
||||||
reviewed_at: new Date(),
|
reviewed_at: new Date(),
|
||||||
'review_decision.action': decision.action,
|
'review_decision.action': decision.action,
|
||||||
'review_decision.notes': decision.notes,
|
'review_decision.notes': decision.notes,
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ const projectSchema = new mongoose.Schema({
|
||||||
lowercase: true,
|
lowercase: true,
|
||||||
trim: true,
|
trim: true,
|
||||||
validate: {
|
validate: {
|
||||||
validator: function(v) {
|
validator(v) {
|
||||||
// Slug format: lowercase letters, numbers, hyphens
|
// Slug format: lowercase letters, numbers, hyphens
|
||||||
return /^[a-z0-9-]+$/.test(v);
|
return /^[a-z0-9-]+$/.test(v);
|
||||||
},
|
},
|
||||||
|
|
@ -92,7 +92,7 @@ const projectSchema = new mongoose.Schema({
|
||||||
type: String,
|
type: String,
|
||||||
default: '',
|
default: '',
|
||||||
validate: {
|
validate: {
|
||||||
validator: function(v) {
|
validator(v) {
|
||||||
if (!v) return true; // Empty is valid
|
if (!v) return true; // Empty is valid
|
||||||
// Basic URL validation
|
// Basic URL validation
|
||||||
try {
|
try {
|
||||||
|
|
|
||||||
|
|
@ -114,7 +114,7 @@ class ResponseTemplate {
|
||||||
throw new Error('Template not found');
|
throw new Error('Template not found');
|
||||||
}
|
}
|
||||||
|
|
||||||
let rendered = {
|
const rendered = {
|
||||||
subject: template.subject,
|
subject: template.subject,
|
||||||
content: template.content
|
content: template.content
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -92,7 +92,7 @@ class SLATracking {
|
||||||
first_response_at: new Date(),
|
first_response_at: new Date(),
|
||||||
response_time: responseTime,
|
response_time: responseTime,
|
||||||
status: 'responded',
|
status: 'responded',
|
||||||
breach: breach,
|
breach,
|
||||||
updated_at: new Date()
|
updated_at: new Date()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -190,8 +190,8 @@ scheduledTaskSchema.statics.getDueSoon = function(daysAhead = 7) {
|
||||||
status: 'pending',
|
status: 'pending',
|
||||||
showInSessionInit: true
|
showInSessionInit: true
|
||||||
})
|
})
|
||||||
.sort({ priority: -1, dueDate: 1 })
|
.sort({ priority: -1, dueDate: 1 })
|
||||||
.limit(10);
|
.limit(10);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Static: Get overdue tasks
|
// Static: Get overdue tasks
|
||||||
|
|
@ -200,7 +200,7 @@ scheduledTaskSchema.statics.getOverdue = function() {
|
||||||
dueDate: { $lt: new Date() },
|
dueDate: { $lt: new Date() },
|
||||||
status: 'pending'
|
status: 'pending'
|
||||||
})
|
})
|
||||||
.sort({ priority: -1, dueDate: 1 });
|
.sort({ priority: -1, dueDate: 1 });
|
||||||
};
|
};
|
||||||
|
|
||||||
// Static: Get tasks by category
|
// Static: Get tasks by category
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ const variableValueSchema = new mongoose.Schema({
|
||||||
uppercase: true,
|
uppercase: true,
|
||||||
trim: true,
|
trim: true,
|
||||||
validate: {
|
validate: {
|
||||||
validator: function(v) {
|
validator(v) {
|
||||||
// Variable names must be UPPER_SNAKE_CASE
|
// Variable names must be UPPER_SNAKE_CASE
|
||||||
return /^[A-Z][A-Z0-9_]*$/.test(v);
|
return /^[A-Z][A-Z0-9_]*$/.test(v);
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -374,7 +374,7 @@ router.get('/stats', async (req, res) => {
|
||||||
byCategory: {},
|
byCategory: {},
|
||||||
byPriority: {},
|
byPriority: {},
|
||||||
dueSoon: await ScheduledTask.countDocuments({
|
dueSoon: await ScheduledTask.countDocuments({
|
||||||
dueDate: { $lte: new Date(Date.now() + 7*24*60*60*1000) },
|
dueDate: { $lte: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000) },
|
||||||
status: 'pending'
|
status: 'pending'
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@ const { asyncHandler } = require('../middleware/error.middleware');
|
||||||
// Import services
|
// Import services
|
||||||
const {
|
const {
|
||||||
classifier,
|
classifier,
|
||||||
validator,
|
|
||||||
enforcer,
|
enforcer,
|
||||||
monitor
|
monitor
|
||||||
} = require('../services');
|
} = require('../services');
|
||||||
|
|
@ -115,7 +114,7 @@ router.post('/boundary-check',
|
||||||
|
|
||||||
const action = {
|
const action = {
|
||||||
type: 'decision',
|
type: 'decision',
|
||||||
decision: decision,
|
decision,
|
||||||
description: description || '',
|
description: description || '',
|
||||||
timestamp: new Date()
|
timestamp: new Date()
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ router.get('/metrics', authenticateToken, requireAdmin, async (req, res) => {
|
||||||
|
|
||||||
res.json({
|
res.json({
|
||||||
success: true,
|
success: true,
|
||||||
metrics: metrics
|
metrics
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error fetching hooks metrics:', error);
|
console.error('Error fetching hooks metrics:', error);
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ const donationLimiter = rateLimit({
|
||||||
standardHeaders: true,
|
standardHeaders: true,
|
||||||
legacyHeaders: false,
|
legacyHeaders: false,
|
||||||
// Skip rate limiting for webhook endpoint (Stripe needs reliable access)
|
// Skip rate limiting for webhook endpoint (Stripe needs reliable access)
|
||||||
skip: (req) => req.path === '/webhook'
|
skip: req => req.path === '/webhook'
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@ router.get('/health', authenticateToken, requireAdmin, async (req, res) => {
|
||||||
|
|
||||||
if (fileError) {
|
if (fileError) {
|
||||||
status = 'error';
|
status = 'error';
|
||||||
message = 'Cannot read instruction file: ' + fileError;
|
message = `Cannot read instruction file: ${ fileError}`;
|
||||||
severity = 'error';
|
severity = 'error';
|
||||||
} else if (difference === 0) {
|
} else if (difference === 0) {
|
||||||
status = 'healthy';
|
status = 'healthy';
|
||||||
|
|
@ -69,15 +69,15 @@ router.get('/health', authenticateToken, requireAdmin, async (req, res) => {
|
||||||
severity = 'success';
|
severity = 'success';
|
||||||
} else if (difference <= 2) {
|
} else if (difference <= 2) {
|
||||||
status = 'warning';
|
status = 'warning';
|
||||||
message = 'Minor desync: ' + difference + ' instruction' + (difference !== 1 ? 's' : '') + ' differ';
|
message = `Minor desync: ${ difference } instruction${ difference !== 1 ? 's' : '' } differ`;
|
||||||
severity = 'warning';
|
severity = 'warning';
|
||||||
} else if (difference <= 5) {
|
} else if (difference <= 5) {
|
||||||
status = 'warning';
|
status = 'warning';
|
||||||
message = 'Moderate desync: ' + difference + ' instructions differ (' + diffPercent + '%)';
|
message = `Moderate desync: ${ difference } instructions differ (${ diffPercent }%)`;
|
||||||
severity = 'warning';
|
severity = 'warning';
|
||||||
} else {
|
} else {
|
||||||
status = 'critical';
|
status = 'critical';
|
||||||
message = 'Critical desync: ' + difference + ' instructions differ (' + diffPercent + '%)';
|
message = `Critical desync: ${ difference } instructions differ (${ diffPercent }%)`;
|
||||||
severity = 'error';
|
severity = 'error';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -86,11 +86,11 @@ router.get('/health', authenticateToken, requireAdmin, async (req, res) => {
|
||||||
|
|
||||||
const missingInDb = fileInstructions
|
const missingInDb = fileInstructions
|
||||||
.filter(i => !dbIds.has(i.id))
|
.filter(i => !dbIds.has(i.id))
|
||||||
.map(i => ({ id: i.id, text: i.text.substring(0, 60) + '...' }));
|
.map(i => ({ id: i.id, text: `${i.text.substring(0, 60) }...` }));
|
||||||
|
|
||||||
const orphanedInDb = dbRules
|
const orphanedInDb = dbRules
|
||||||
.filter(r => !fileIds.has(r.id))
|
.filter(r => !fileIds.has(r.id))
|
||||||
.map(r => ({ id: r.id, text: r.text.substring(0, 60) + '...' }));
|
.map(r => ({ id: r.id, text: `${r.text.substring(0, 60) }...` }));
|
||||||
|
|
||||||
res.json({
|
res.json({
|
||||||
success: true,
|
success: true,
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ app.use(securityHeadersMiddleware);
|
||||||
|
|
||||||
// Keep helmet for other security features (but CSP already set above)
|
// Keep helmet for other security features (but CSP already set above)
|
||||||
app.use(helmet({
|
app.use(helmet({
|
||||||
contentSecurityPolicy: false, // Disabled - using our custom CSP in securityHeadersMiddleware
|
contentSecurityPolicy: false // Disabled - using our custom CSP in securityHeadersMiddleware
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// CORS
|
// CORS
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,7 @@ class AnthropicMemoryClient {
|
||||||
const requestOptions = {
|
const requestOptions = {
|
||||||
model: this.model,
|
model: this.model,
|
||||||
max_tokens: options.max_tokens || 8096,
|
max_tokens: options.max_tokens || 8096,
|
||||||
messages: messages,
|
messages,
|
||||||
betas: this.betaHeaders,
|
betas: this.betaHeaders,
|
||||||
...options
|
...options
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -362,7 +362,7 @@ Respond with JSON:
|
||||||
return excerpt.substring(0, lastPeriod + 1);
|
return excerpt.substring(0, lastPeriod + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return excerpt.substring(0, maxLength).trim() + '...';
|
return `${excerpt.substring(0, maxLength).trim() }...`;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -527,8 +527,8 @@ Respond with JSON as specified in the system prompt.`;
|
||||||
stats_found: statsFound,
|
stats_found: statsFound,
|
||||||
sources_provided: content.sources?.length || 0,
|
sources_provided: content.sources?.length || 0,
|
||||||
recommendation: violations.length > 0 ? 'REJECT' :
|
recommendation: violations.length > 0 ? 'REJECT' :
|
||||||
warnings.length > 0 ? 'REVIEW_REQUIRED' :
|
warnings.length > 0 ? 'REVIEW_REQUIRED' :
|
||||||
'APPROVED'
|
'APPROVED'
|
||||||
};
|
};
|
||||||
|
|
||||||
// Audit validation decision
|
// Audit validation decision
|
||||||
|
|
|
||||||
|
|
@ -45,8 +45,8 @@ const TRACTATUS_BOUNDARIES = {
|
||||||
principle: 'Values cannot be automated, only verified',
|
principle: 'Values cannot be automated, only verified',
|
||||||
humanRequired: true,
|
humanRequired: true,
|
||||||
keywords: ['value', 'principle', 'ethic', 'moral', 'should', 'ought', 'right', 'wrong',
|
keywords: ['value', 'principle', 'ethic', 'moral', 'should', 'ought', 'right', 'wrong',
|
||||||
'privacy', 'policy', 'trade-off', 'tradeoff', 'prioritize', 'priority',
|
'privacy', 'policy', 'trade-off', 'tradeoff', 'prioritize', 'priority',
|
||||||
'belief', 'virtue', 'integrity', 'fairness', 'justice'],
|
'belief', 'virtue', 'integrity', 'fairness', 'justice'],
|
||||||
examples: [
|
examples: [
|
||||||
'Decide whether to prioritize privacy over convenience',
|
'Decide whether to prioritize privacy over convenience',
|
||||||
'Determine our core values',
|
'Determine our core values',
|
||||||
|
|
@ -58,7 +58,7 @@ const TRACTATUS_BOUNDARIES = {
|
||||||
principle: 'Innovation cannot be proceduralized, only facilitated',
|
principle: 'Innovation cannot be proceduralized, only facilitated',
|
||||||
humanRequired: true,
|
humanRequired: true,
|
||||||
keywords: ['innovate', 'create', 'invent', 'breakthrough', 'novel', 'creative',
|
keywords: ['innovate', 'create', 'invent', 'breakthrough', 'novel', 'creative',
|
||||||
'architectural', 'architecture', 'design', 'fundamental', 'revolutionary', 'transform'],
|
'architectural', 'architecture', 'design', 'fundamental', 'revolutionary', 'transform'],
|
||||||
examples: [
|
examples: [
|
||||||
'Create entirely new approach',
|
'Create entirely new approach',
|
||||||
'Invent solution to fundamental problem',
|
'Invent solution to fundamental problem',
|
||||||
|
|
@ -70,7 +70,7 @@ const TRACTATUS_BOUNDARIES = {
|
||||||
principle: 'Wisdom cannot be encoded, only supported',
|
principle: 'Wisdom cannot be encoded, only supported',
|
||||||
humanRequired: true,
|
humanRequired: true,
|
||||||
keywords: ['wisdom', 'judgment', 'discernment', 'prudence', 'insight',
|
keywords: ['wisdom', 'judgment', 'discernment', 'prudence', 'insight',
|
||||||
'strategic', 'direction', 'guidance', 'wise', 'counsel', 'experience'],
|
'strategic', 'direction', 'guidance', 'wise', 'counsel', 'experience'],
|
||||||
examples: [
|
examples: [
|
||||||
'Exercise judgment in unprecedented situation',
|
'Exercise judgment in unprecedented situation',
|
||||||
'Apply wisdom to complex tradeoff',
|
'Apply wisdom to complex tradeoff',
|
||||||
|
|
@ -82,7 +82,7 @@ const TRACTATUS_BOUNDARIES = {
|
||||||
principle: 'Purpose cannot be generated, only preserved',
|
principle: 'Purpose cannot be generated, only preserved',
|
||||||
humanRequired: true,
|
humanRequired: true,
|
||||||
keywords: ['purpose', 'mission', 'why', 'meaning', 'goal', 'objective',
|
keywords: ['purpose', 'mission', 'why', 'meaning', 'goal', 'objective',
|
||||||
'vision', 'intent', 'aim', 'reason for', 'raison', 'fundamental goal'],
|
'vision', 'intent', 'aim', 'reason for', 'raison', 'fundamental goal'],
|
||||||
examples: [
|
examples: [
|
||||||
'Define our organizational purpose',
|
'Define our organizational purpose',
|
||||||
'Determine why we exist',
|
'Determine why we exist',
|
||||||
|
|
@ -94,7 +94,7 @@ const TRACTATUS_BOUNDARIES = {
|
||||||
principle: 'Meaning cannot be computed, only recognized',
|
principle: 'Meaning cannot be computed, only recognized',
|
||||||
humanRequired: true,
|
humanRequired: true,
|
||||||
keywords: ['meaning', 'significance', 'importance', 'matter', 'meaningful',
|
keywords: ['meaning', 'significance', 'importance', 'matter', 'meaningful',
|
||||||
'significant', 'important', 'matters', 'valuable', 'worthwhile'],
|
'significant', 'important', 'matters', 'valuable', 'worthwhile'],
|
||||||
examples: [
|
examples: [
|
||||||
'Decide what is truly significant',
|
'Decide what is truly significant',
|
||||||
'Determine what matters most',
|
'Determine what matters most',
|
||||||
|
|
@ -106,7 +106,7 @@ const TRACTATUS_BOUNDARIES = {
|
||||||
principle: 'Agency cannot be simulated, only respected',
|
principle: 'Agency cannot be simulated, only respected',
|
||||||
humanRequired: true,
|
humanRequired: true,
|
||||||
keywords: ['agency', 'autonomy', 'choice', 'freedom', 'sovereignty', 'self-determination',
|
keywords: ['agency', 'autonomy', 'choice', 'freedom', 'sovereignty', 'self-determination',
|
||||||
'decide for', 'on behalf', 'override', 'substitute', 'replace human'],
|
'decide for', 'on behalf', 'override', 'substitute', 'replace human'],
|
||||||
examples: [
|
examples: [
|
||||||
'Make autonomous decision for humans',
|
'Make autonomous decision for humans',
|
||||||
'Override human choice',
|
'Override human choice',
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ class ClaudeAPIService {
|
||||||
const payload = {
|
const payload = {
|
||||||
model: options.model || this.model,
|
model: options.model || this.model,
|
||||||
max_tokens: options.max_tokens || this.maxTokens,
|
max_tokens: options.max_tokens || this.maxTokens,
|
||||||
messages: messages,
|
messages,
|
||||||
...(options.system && { system: options.system }),
|
...(options.system && { system: options.system }),
|
||||||
...(options.temperature && { temperature: options.temperature })
|
...(options.temperature && { temperature: options.temperature })
|
||||||
};
|
};
|
||||||
|
|
@ -84,10 +84,10 @@ class ClaudeAPIService {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const req = https.request(options, (res) => {
|
const req = https.request(options, res => {
|
||||||
let data = '';
|
let data = '';
|
||||||
|
|
||||||
res.on('data', (chunk) => {
|
res.on('data', chunk => {
|
||||||
data += chunk;
|
data += chunk;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -105,7 +105,7 @@ class ClaudeAPIService {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
req.on('error', (error) => {
|
req.on('error', error => {
|
||||||
reject(new Error(`Request error: ${error.message}`));
|
reject(new Error(`Request error: ${error.message}`));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,7 @@ class ClaudeMdAnalyzer {
|
||||||
return {
|
return {
|
||||||
totalLines: lines.length,
|
totalLines: lines.length,
|
||||||
sections,
|
sections,
|
||||||
content: content
|
content
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -112,7 +112,7 @@ Analyze semantic similarity and provide detailed JSON response.`;
|
||||||
isAdaptation: 0
|
isAdaptation: 0
|
||||||
};
|
};
|
||||||
|
|
||||||
let reasoning = [];
|
const reasoning = [];
|
||||||
|
|
||||||
// Get publication market data
|
// Get publication market data
|
||||||
const pub1 = context.targetPublication1
|
const pub1 = context.targetPublication1
|
||||||
|
|
@ -338,7 +338,7 @@ Analyze semantic similarity and provide detailed JSON response.`;
|
||||||
* @returns {Object} Title similarity result
|
* @returns {Object} Title similarity result
|
||||||
*/
|
*/
|
||||||
analyzeTitleSimilarity(title1, title2) {
|
analyzeTitleSimilarity(title1, title2) {
|
||||||
const normalize = (str) => str.toLowerCase().replace(/[^a-z0-9\s]/g, '').trim();
|
const normalize = str => str.toLowerCase().replace(/[^a-z0-9\s]/g, '').trim();
|
||||||
|
|
||||||
const t1 = normalize(title1);
|
const t1 = normalize(title1);
|
||||||
const t2 = normalize(title2);
|
const t2 = normalize(title2);
|
||||||
|
|
|
||||||
|
|
@ -258,7 +258,7 @@ class CrossReferenceValidator {
|
||||||
text: message.content,
|
text: message.content,
|
||||||
timestamp: message.timestamp || new Date(),
|
timestamp: message.timestamp || new Date(),
|
||||||
source: 'user',
|
source: 'user',
|
||||||
context: context
|
context
|
||||||
});
|
});
|
||||||
|
|
||||||
// Calculate relevance to this action
|
// Calculate relevance to this action
|
||||||
|
|
|
||||||
|
|
@ -68,8 +68,8 @@ const QUADRANTS = {
|
||||||
persistence: 'HIGH',
|
persistence: 'HIGH',
|
||||||
description: 'Technical infrastructure, architecture',
|
description: 'Technical infrastructure, architecture',
|
||||||
keywords: ['code', 'technical', 'architecture', 'infrastructure', 'database', 'api',
|
keywords: ['code', 'technical', 'architecture', 'infrastructure', 'database', 'api',
|
||||||
'fix', 'bug', 'error', 'authentication', 'security', 'system', 'implementation',
|
'fix', 'bug', 'error', 'authentication', 'security', 'system', 'implementation',
|
||||||
'function', 'method', 'class', 'module', 'component', 'service'],
|
'function', 'method', 'class', 'module', 'component', 'service'],
|
||||||
verificationLevel: 'TECHNICAL_REVIEW',
|
verificationLevel: 'TECHNICAL_REVIEW',
|
||||||
humanOversight: 'TECHNICAL_EXPERTISE',
|
humanOversight: 'TECHNICAL_EXPERTISE',
|
||||||
examples: ['MongoDB port is 27017', 'Use JWT for authentication']
|
examples: ['MongoDB port is 27017', 'Use JWT for authentication']
|
||||||
|
|
@ -80,8 +80,8 @@ const QUADRANTS = {
|
||||||
persistence: 'CONTEXT_DEPENDENT',
|
persistence: 'CONTEXT_DEPENDENT',
|
||||||
description: 'Innovation, exploration, experimentation',
|
description: 'Innovation, exploration, experimentation',
|
||||||
keywords: ['explore', 'experiment', 'innovate', 'brainstorm', 'creative', 'try',
|
keywords: ['explore', 'experiment', 'innovate', 'brainstorm', 'creative', 'try',
|
||||||
'alternative', 'alternatives', 'consider', 'possibility', 'investigate',
|
'alternative', 'alternatives', 'consider', 'possibility', 'investigate',
|
||||||
'research', 'discover', 'prototype', 'test', 'suggest', 'idea'],
|
'research', 'discover', 'prototype', 'test', 'suggest', 'idea'],
|
||||||
verificationLevel: 'OPTIONAL',
|
verificationLevel: 'OPTIONAL',
|
||||||
humanOversight: 'INSIGHT_GENERATION',
|
humanOversight: 'INSIGHT_GENERATION',
|
||||||
examples: ['Explore alternative approaches', 'Suggest creative solutions']
|
examples: ['Explore alternative approaches', 'Suggest creative solutions']
|
||||||
|
|
@ -676,11 +676,9 @@ class InstructionPersistenceClassifier {
|
||||||
// Handle negations: "never X without confirmation" means confirmation IS required
|
// Handle negations: "never X without confirmation" means confirmation IS required
|
||||||
if (/\b(?:never|don't|do not).*without\s+confirmation\b/i.test(text)) {
|
if (/\b(?:never|don't|do not).*without\s+confirmation\b/i.test(text)) {
|
||||||
params.confirmed = true; // Double negative = positive requirement
|
params.confirmed = true; // Double negative = positive requirement
|
||||||
}
|
} else if (/\b(?:with confirmation|require confirmation|must confirm|need confirmation)\b/i.test(text)) {
|
||||||
else if (/\b(?:with confirmation|require confirmation|must confirm|need confirmation)\b/i.test(text)) {
|
|
||||||
params.confirmed = true;
|
params.confirmed = true;
|
||||||
}
|
} else if (/\b(?:without confirmation|no confirmation|skip confirmation)\b/i.test(text)) {
|
||||||
else if (/\b(?:without confirmation|no confirmation|skip confirmation)\b/i.test(text)) {
|
|
||||||
params.confirmed = false;
|
params.confirmed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -417,7 +417,7 @@ class MetacognitiveVerifier {
|
||||||
|
|
||||||
// Check for uncertain or weak language
|
// Check for uncertain or weak language
|
||||||
const uncertainPatterns = /\b(maybe|perhaps|might|possibly|not sure|uncertain)\b/i;
|
const uncertainPatterns = /\b(maybe|perhaps|might|possibly|not sure|uncertain)\b/i;
|
||||||
const explanationText = (reasoning.explanation || '') + ' ' + (reasoning.steps || []).join(' ');
|
const explanationText = `${reasoning.explanation || '' } ${ (reasoning.steps || []).join(' ')}`;
|
||||||
if (uncertainPatterns.test(explanationText)) {
|
if (uncertainPatterns.test(explanationText)) {
|
||||||
score -= 0.2;
|
score -= 0.2;
|
||||||
issues.push('Reasoning contains uncertain language');
|
issues.push('Reasoning contains uncertain language');
|
||||||
|
|
@ -454,7 +454,7 @@ class MetacognitiveVerifier {
|
||||||
const missing = [];
|
const missing = [];
|
||||||
|
|
||||||
// Penalty for destructive operations without thorough planning
|
// Penalty for destructive operations without thorough planning
|
||||||
const actionText = (action.type || '') + ' ' + (action.description || '') + ' ' + (action.command || '');
|
const actionText = `${action.type || '' } ${ action.description || '' } ${ action.command || ''}`;
|
||||||
const isDestructive = /delete|remove|drop|truncate|destroy|force/i.test(actionText) ||
|
const isDestructive = /delete|remove|drop|truncate|destroy|force/i.test(actionText) ||
|
||||||
(action.parameters && (action.parameters.destructive || action.parameters.force || action.parameters.delete));
|
(action.parameters && (action.parameters.destructive || action.parameters.force || action.parameters.delete));
|
||||||
|
|
||||||
|
|
@ -545,7 +545,7 @@ class MetacognitiveVerifier {
|
||||||
/modify_schema|alter.*table|migrate.*database/i
|
/modify_schema|alter.*table|migrate.*database/i
|
||||||
];
|
];
|
||||||
|
|
||||||
const actionText = (action.type || '') + ' ' + (action.description || '') + ' ' + (action.command || '');
|
const actionText = `${action.type || '' } ${ action.description || '' } ${ action.command || ''}`;
|
||||||
const isDestructive = destructivePatterns.some(pattern => pattern.test(actionText));
|
const isDestructive = destructivePatterns.some(pattern => pattern.test(actionText));
|
||||||
|
|
||||||
// Check if parameters indicate destructive operation
|
// Check if parameters indicate destructive operation
|
||||||
|
|
@ -767,7 +767,7 @@ class MetacognitiveVerifier {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const text = (reasoning.explanation || '') + ' ' + (reasoning.steps || []).join(' ');
|
const text = `${reasoning.explanation || '' } ${ (reasoning.steps || []).join(' ')}`;
|
||||||
const lower = text.toLowerCase();
|
const lower = text.toLowerCase();
|
||||||
|
|
||||||
// Simple contradiction patterns
|
// Simple contradiction patterns
|
||||||
|
|
@ -805,7 +805,7 @@ class MetacognitiveVerifier {
|
||||||
|
|
||||||
_checkParameterConflicts(parameters, reasoning) {
|
_checkParameterConflicts(parameters, reasoning) {
|
||||||
// Check if parameter values in action conflict with reasoning
|
// Check if parameter values in action conflict with reasoning
|
||||||
const reasoningText = (reasoning.explanation || '') + ' ' + (reasoning.evidence || []).join(' ');
|
const reasoningText = `${reasoning.explanation || '' } ${ (reasoning.evidence || []).join(' ')}`;
|
||||||
|
|
||||||
for (const [key, value] of Object.entries(parameters)) {
|
for (const [key, value] of Object.entries(parameters)) {
|
||||||
const valueStr = String(value);
|
const valueStr = String(value);
|
||||||
|
|
@ -878,7 +878,7 @@ class MetacognitiveVerifier {
|
||||||
*/
|
*/
|
||||||
_getDecisionReason(decision, scores, criticalFailures) {
|
_getDecisionReason(decision, scores, criticalFailures) {
|
||||||
if (decision === 'BLOCK') {
|
if (decision === 'BLOCK') {
|
||||||
return 'Critical failures detected: ' + criticalFailures.map(cf => cf.dimension).join(', ');
|
return `Critical failures detected: ${ criticalFailures.map(cf => cf.dimension).join(', ')}`;
|
||||||
}
|
}
|
||||||
if (decision === 'REQUEST_CLARIFICATION') {
|
if (decision === 'REQUEST_CLARIFICATION') {
|
||||||
return 'Low confidence in alignment or completeness';
|
return 'Low confidence in alignment or completeness';
|
||||||
|
|
|
||||||
|
|
@ -302,9 +302,9 @@ class RuleOptimizer {
|
||||||
suggestions.push({
|
suggestions.push({
|
||||||
type: 'missing_imperative',
|
type: 'missing_imperative',
|
||||||
severity: 'high',
|
severity: 'high',
|
||||||
original: ruleText.substring(0, 20) + '...',
|
original: `${ruleText.substring(0, 20) }...`,
|
||||||
before: ruleText,
|
before: ruleText,
|
||||||
after: 'MUST ' + ruleText.charAt(0).toLowerCase() + ruleText.slice(1),
|
after: `MUST ${ ruleText.charAt(0).toLowerCase() }${ruleText.slice(1)}`,
|
||||||
reason: 'No strong imperative - added "MUST" at start for clarity'
|
reason: 'No strong imperative - added "MUST" at start for clarity'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,7 @@ class TranslationService {
|
||||||
`auth_key=${encodeURIComponent(this.apiKey)}&text=${encodeURIComponent('test')}&target_lang=FR`,
|
`auth_key=${encodeURIComponent(this.apiKey)}&text=${encodeURIComponent('test')}&target_lang=FR`,
|
||||||
{
|
{
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/x-www-form-urlencoded',
|
'Content-Type': 'application/x-www-form-urlencoded'
|
||||||
},
|
},
|
||||||
timeout: 5000
|
timeout: 5000
|
||||||
}
|
}
|
||||||
|
|
@ -169,7 +169,7 @@ class TranslationService {
|
||||||
// Make translation request
|
// Make translation request
|
||||||
const response = await axios.post(`${this.apiUrl}/translate`, params.toString(), {
|
const response = await axios.post(`${this.apiUrl}/translate`, params.toString(), {
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/x-www-form-urlencoded',
|
'Content-Type': 'application/x-www-form-urlencoded'
|
||||||
},
|
},
|
||||||
timeout: 30000 // 30 second timeout
|
timeout: 30000 // 30 second timeout
|
||||||
});
|
});
|
||||||
|
|
@ -247,7 +247,7 @@ class TranslationService {
|
||||||
|
|
||||||
const response = await axios.post(`${this.apiUrl}/translate`, params.toString(), {
|
const response = await axios.post(`${this.apiUrl}/translate`, params.toString(), {
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/x-www-form-urlencoded',
|
'Content-Type': 'application/x-www-form-urlencoded'
|
||||||
},
|
},
|
||||||
timeout: 60000 // 60 seconds for batch
|
timeout: 60000 // 60 seconds for batch
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -28,10 +28,10 @@ module.exports = {
|
||||||
verifier: MetacognitiveVerifier,
|
verifier: MetacognitiveVerifier,
|
||||||
|
|
||||||
// Convenience methods
|
// Convenience methods
|
||||||
classifyInstruction: (instruction) => InstructionPersistenceClassifier.classify(instruction),
|
classifyInstruction: instruction => InstructionPersistenceClassifier.classify(instruction),
|
||||||
validateAction: (action, context) => CrossReferenceValidator.validate(action, context),
|
validateAction: (action, context) => CrossReferenceValidator.validate(action, context),
|
||||||
enforceBoundaries: (action, context) => BoundaryEnforcer.enforce(action, context),
|
enforceBoundaries: (action, context) => BoundaryEnforcer.enforce(action, context),
|
||||||
analyzePressure: (context) => ContextPressureMonitor.analyzePressure(context),
|
analyzePressure: context => ContextPressureMonitor.analyzePressure(context),
|
||||||
verifyAction: (action, reasoning, context) => MetacognitiveVerifier.verify(action, reasoning, context),
|
verifyAction: (action, reasoning, context) => MetacognitiveVerifier.verify(action, reasoning, context),
|
||||||
|
|
||||||
// Framework status
|
// Framework status
|
||||||
|
|
|
||||||
|
|
@ -104,8 +104,8 @@ class KohaService {
|
||||||
success_url: `${process.env.FRONTEND_URL || 'https://agenticgovernance.digital'}/koha/success.html?session_id={CHECKOUT_SESSION_ID}`,
|
success_url: `${process.env.FRONTEND_URL || 'https://agenticgovernance.digital'}/koha/success.html?session_id={CHECKOUT_SESSION_ID}`,
|
||||||
cancel_url: `${process.env.FRONTEND_URL || 'https://agenticgovernance.digital'}/koha.html`,
|
cancel_url: `${process.env.FRONTEND_URL || 'https://agenticgovernance.digital'}/koha.html`,
|
||||||
metadata: {
|
metadata: {
|
||||||
frequency: frequency,
|
frequency,
|
||||||
tier: tier,
|
tier,
|
||||||
currency: donationCurrency,
|
currency: donationCurrency,
|
||||||
amount_nzd: String(amountNZD),
|
amount_nzd: String(amountNZD),
|
||||||
exchange_rate: String(exchangeRate),
|
exchange_rate: String(exchangeRate),
|
||||||
|
|
@ -133,7 +133,7 @@ class KohaService {
|
||||||
|
|
||||||
sessionParams.subscription_data = {
|
sessionParams.subscription_data = {
|
||||||
metadata: {
|
metadata: {
|
||||||
tier: tier,
|
tier,
|
||||||
public_acknowledgement: public_acknowledgement ? 'yes' : 'no'
|
public_acknowledgement: public_acknowledgement ? 'yes' : 'no'
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -167,12 +167,12 @@ class KohaService {
|
||||||
|
|
||||||
// Create pending donation record in database
|
// Create pending donation record in database
|
||||||
await Donation.create({
|
await Donation.create({
|
||||||
amount: amount,
|
amount,
|
||||||
currency: donationCurrency.toLowerCase(),
|
currency: donationCurrency.toLowerCase(),
|
||||||
amount_nzd: amountNZD,
|
amount_nzd: amountNZD,
|
||||||
exchange_rate_to_nzd: exchangeRate,
|
exchange_rate_to_nzd: exchangeRate,
|
||||||
frequency: frequency,
|
frequency,
|
||||||
tier: tier,
|
tier,
|
||||||
donor: {
|
donor: {
|
||||||
name: donor.name || 'Anonymous',
|
name: donor.name || 'Anonymous',
|
||||||
email: donor.email,
|
email: donor.email,
|
||||||
|
|
@ -193,7 +193,7 @@ class KohaService {
|
||||||
return {
|
return {
|
||||||
sessionId: session.id,
|
sessionId: session.id,
|
||||||
checkoutUrl: session.url,
|
checkoutUrl: session.url,
|
||||||
frequency: frequency,
|
frequency,
|
||||||
amount: amount / 100
|
amount: amount / 100
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -276,8 +276,8 @@ class KohaService {
|
||||||
currency: currency.toLowerCase(),
|
currency: currency.toLowerCase(),
|
||||||
amount_nzd: amountNZD,
|
amount_nzd: amountNZD,
|
||||||
exchange_rate_to_nzd: exchangeRate,
|
exchange_rate_to_nzd: exchangeRate,
|
||||||
frequency: frequency,
|
frequency,
|
||||||
tier: tier,
|
tier,
|
||||||
donor: {
|
donor: {
|
||||||
name: session.metadata.donor_name || 'Anonymous',
|
name: session.metadata.donor_name || 'Anonymous',
|
||||||
email: session.customer_email
|
email: session.customer_email
|
||||||
|
|
@ -371,7 +371,7 @@ class KohaService {
|
||||||
const exchangeRate = getExchangeRate(currency);
|
const exchangeRate = getExchangeRate(currency);
|
||||||
|
|
||||||
await Donation.create({
|
await Donation.create({
|
||||||
amount: amount,
|
amount,
|
||||||
currency: currency.toLowerCase(),
|
currency: currency.toLowerCase(),
|
||||||
amount_nzd: amountNZD,
|
amount_nzd: amountNZD,
|
||||||
exchange_rate_to_nzd: exchangeRate,
|
exchange_rate_to_nzd: exchangeRate,
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ class DatabaseConnection {
|
||||||
minPoolSize: 2,
|
minPoolSize: 2,
|
||||||
maxIdleTimeMS: 30000,
|
maxIdleTimeMS: 30000,
|
||||||
serverSelectionTimeoutMS: 5000,
|
serverSelectionTimeoutMS: 5000,
|
||||||
socketTimeoutMS: 45000,
|
socketTimeoutMS: 45000
|
||||||
});
|
});
|
||||||
|
|
||||||
await this.client.connect();
|
await this.client.connect();
|
||||||
|
|
@ -105,7 +105,7 @@ const dbConnection = new DatabaseConnection();
|
||||||
module.exports = {
|
module.exports = {
|
||||||
connect: () => dbConnection.connect(),
|
connect: () => dbConnection.connect(),
|
||||||
getDb: () => dbConnection.getDb(),
|
getDb: () => dbConnection.getDb(),
|
||||||
getCollection: (name) => dbConnection.getCollection(name),
|
getCollection: name => dbConnection.getCollection(name),
|
||||||
close: () => dbConnection.close(),
|
close: () => dbConnection.close(),
|
||||||
isConnected: () => dbConnection.isConnected()
|
isConnected: () => dbConnection.isConnected()
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -94,7 +94,7 @@ function extractExcerpt(content) {
|
||||||
if (!content) return '';
|
if (!content) return '';
|
||||||
|
|
||||||
// Remove markdown formatting
|
// Remove markdown formatting
|
||||||
let text = content
|
const text = content
|
||||||
.replace(/^#+\s+/gm, '') // Remove headings
|
.replace(/^#+\s+/gm, '') // Remove headings
|
||||||
.replace(/\*\*(.+?)\*\*/g, '$1') // Remove bold
|
.replace(/\*\*(.+?)\*\*/g, '$1') // Remove bold
|
||||||
.replace(/\*(.+?)\*/g, '$1') // Remove italic
|
.replace(/\*(.+?)\*/g, '$1') // Remove italic
|
||||||
|
|
@ -112,7 +112,7 @@ function extractExcerpt(content) {
|
||||||
|
|
||||||
// Truncate to 150 chars if needed
|
// Truncate to 150 chars if needed
|
||||||
if (excerpt.length > 150) {
|
if (excerpt.length > 150) {
|
||||||
excerpt = excerpt.substring(0, 147) + '...';
|
excerpt = `${excerpt.substring(0, 147) }...`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return excerpt;
|
return excerpt;
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ const logger = winston.createLogger({
|
||||||
new winston.transports.File({
|
new winston.transports.File({
|
||||||
filename: logFile,
|
filename: logFile,
|
||||||
maxsize: 5242880, // 5MB
|
maxsize: 5242880, // 5MB
|
||||||
maxFiles: 5,
|
maxFiles: 5
|
||||||
}),
|
}),
|
||||||
|
|
||||||
// Error file
|
// Error file
|
||||||
|
|
@ -45,7 +45,7 @@ const logger = winston.createLogger({
|
||||||
filename: path.join(path.dirname(logFile), 'error.log'),
|
filename: path.join(path.dirname(logFile), 'error.log'),
|
||||||
level: 'error',
|
level: 'error',
|
||||||
maxsize: 5242880,
|
maxsize: 5242880,
|
||||||
maxFiles: 5,
|
maxFiles: 5
|
||||||
})
|
})
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -25,8 +25,8 @@ renderer.heading = function(text, level, raw) {
|
||||||
|
|
||||||
// Configure marked
|
// Configure marked
|
||||||
marked.setOptions({
|
marked.setOptions({
|
||||||
renderer: renderer,
|
renderer,
|
||||||
highlight: function(code, lang) {
|
highlight(code, lang) {
|
||||||
if (lang && hljs.getLanguage(lang)) {
|
if (lang && hljs.getLanguage(lang)) {
|
||||||
try {
|
try {
|
||||||
return hljs.highlight(code, { language: lang }).value;
|
return hljs.highlight(code, { language: lang }).value;
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ class MongooseConnection {
|
||||||
maxIdleTimeMS: 30000,
|
maxIdleTimeMS: 30000,
|
||||||
serverSelectionTimeoutMS: 5000,
|
serverSelectionTimeoutMS: 5000,
|
||||||
socketTimeoutMS: 45000,
|
socketTimeoutMS: 45000,
|
||||||
family: 4, // Use IPv4, skip trying IPv6
|
family: 4 // Use IPv4, skip trying IPv6
|
||||||
};
|
};
|
||||||
|
|
||||||
for (let attempt = 1; attempt <= retries; attempt++) {
|
for (let attempt = 1; attempt <= retries; attempt++) {
|
||||||
|
|
@ -38,7 +38,7 @@ class MongooseConnection {
|
||||||
logger.info(`✅ Mongoose connected to MongoDB`);
|
logger.info(`✅ Mongoose connected to MongoDB`);
|
||||||
|
|
||||||
// Handle connection events
|
// Handle connection events
|
||||||
mongoose.connection.on('error', (err) => {
|
mongoose.connection.on('error', err => {
|
||||||
logger.error('Mongoose connection error:', err);
|
logger.error('Mongoose connection error:', err);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ async function logSecurityEvent(event) {
|
||||||
severity: event.severity || 'medium'
|
severity: event.severity || 'medium'
|
||||||
};
|
};
|
||||||
|
|
||||||
const logLine = JSON.stringify(logEntry) + '\n';
|
const logLine = `${JSON.stringify(logEntry) }\n`;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Ensure log directory exists
|
// Ensure log directory exists
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue