tractatus/src/utils/activity-classifier.util.js
TheFlow ae12888eb4 feat(bi): add business intelligence backend infrastructure
Implements core BI analytics capabilities for governance ROI measurement:

- Activity classifier utility for automatic event categorization
  * Detects activity type (client communication, infrastructure, etc.)
  * Calculates risk level, stakeholder impact, data sensitivity
  * Computes business impact scores (0-100)

- Enhanced audit controller with BI analytics endpoints
  * Cost avoidance calculator with user-configurable factors
  * Framework maturity scoring (0-100 scale)
  * Team performance comparison (AI vs human)
  * Activity type breakdown and ROI projections

- New API routes for cost configuration (GET/POST /api/admin/cost-config)

- Hook validator enhancement
  * Automatic activity classification on governance decisions
  * MongoDB audit logging with BI context fields
  * Business impact scoring for blocked actions

Status: Research prototype v1.0
Note: Cost factors are illustrative placeholders requiring validation

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-27 10:07:33 +13:00

236 lines
7.5 KiB
JavaScript

/*
* Copyright 2025 John G Stroh
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Activity Classifier
* Provides business intelligence context for governance decisions
* Enables ROI analysis and use-case tracking
*/
// Activity type definitions
const ACTIVITY_TYPES = {
HUMAN_INITIATED: 'Human-Initiated Command',
AUTONOMOUS_PROCESSING: 'Autonomous Processing',
CODE_GENERATION: 'Code Generation',
DOCUMENTATION: 'Documentation',
CLIENT_COMMUNICATION: 'Client Communication',
DEPLOYMENT: 'Deployment',
COMPLIANCE_REVIEW: 'Compliance Review',
DATA_MANAGEMENT: 'Data Management'
};
// Risk context levels
const RISK_LEVELS = {
MINIMAL: 'minimal', // No external impact
LOW: 'low', // Internal team only
MEDIUM: 'medium', // Organization-wide
HIGH: 'high', // Client/public facing
CRITICAL: 'critical' // Legal/financial/regulatory
};
// Stakeholder impact
const STAKEHOLDER_IMPACT = {
INDIVIDUAL: 'individual', // Single developer
TEAM: 'team', // Development team
ORGANIZATION: 'organization', // Entire organization
CLIENT: 'client', // External clients
PUBLIC: 'public' // Public audience
};
// Data sensitivity levels
const DATA_SENSITIVITY = {
PUBLIC: 'public',
INTERNAL: 'internal',
CONFIDENTIAL: 'confidential',
RESTRICTED: 'restricted'
};
/**
* Classify activity based on action and metadata
*/
function classifyActivity(action, metadata = {}) {
const filePath = metadata.filePath || metadata.file || '';
const description = metadata.description || metadata.reason || '';
const service = metadata.service || '';
let activityType = ACTIVITY_TYPES.AUTONOMOUS_PROCESSING;
let riskLevel = RISK_LEVELS.LOW;
let stakeholderImpact = STAKEHOLDER_IMPACT.INDIVIDUAL;
let dataSensitivity = DATA_SENSITIVITY.INTERNAL;
// Detect activity type
if (action === 'file_edit_hook' || action === 'file_write_hook') {
// Check file path patterns
if (filePath.includes('public/') && !filePath.includes('admin/')) {
activityType = ACTIVITY_TYPES.CLIENT_COMMUNICATION;
stakeholderImpact = STAKEHOLDER_IMPACT.PUBLIC;
riskLevel = RISK_LEVELS.HIGH;
dataSensitivity = DATA_SENSITIVITY.PUBLIC;
} else if (filePath.includes('docs/')) {
activityType = ACTIVITY_TYPES.DOCUMENTATION;
stakeholderImpact = STAKEHOLDER_IMPACT.ORGANIZATION;
riskLevel = RISK_LEVELS.MEDIUM;
} else if (filePath.includes('.js') || filePath.includes('.css') || filePath.includes('.html')) {
activityType = ACTIVITY_TYPES.CODE_GENERATION;
stakeholderImpact = STAKEHOLDER_IMPACT.TEAM;
riskLevel = RISK_LEVELS.LOW;
} else if (filePath.includes('deploy') || filePath.includes('production')) {
activityType = ACTIVITY_TYPES.DEPLOYMENT;
stakeholderImpact = STAKEHOLDER_IMPACT.ORGANIZATION;
riskLevel = RISK_LEVELS.HIGH;
}
} else if (service === 'BoundaryEnforcer') {
activityType = ACTIVITY_TYPES.COMPLIANCE_REVIEW;
riskLevel = RISK_LEVELS.MEDIUM;
} else if (service === 'ContextPressureMonitor' || service === 'MetacognitiveVerifier') {
activityType = ACTIVITY_TYPES.AUTONOMOUS_PROCESSING;
}
// Detect client-facing content
if (filePath.includes('/components/footer') ||
filePath.includes('/components/navbar') ||
filePath.includes('contact') ||
filePath.includes('email')) {
activityType = ACTIVITY_TYPES.CLIENT_COMMUNICATION;
stakeholderImpact = STAKEHOLDER_IMPACT.CLIENT;
riskLevel = RISK_LEVELS.HIGH;
}
// Detect credentials and sensitive data
if (description.toLowerCase().includes('credential') ||
description.toLowerCase().includes('password') ||
description.toLowerCase().includes('api key') ||
description.toLowerCase().includes('secret')) {
dataSensitivity = DATA_SENSITIVITY.RESTRICTED;
riskLevel = RISK_LEVELS.CRITICAL;
}
// Detect copyright/legal
if (description.toLowerCase().includes('copyright') ||
description.toLowerCase().includes('license') ||
filePath.includes('LICENSE')) {
riskLevel = RISK_LEVELS.CRITICAL;
stakeholderImpact = STAKEHOLDER_IMPACT.PUBLIC;
}
return {
activityType,
riskLevel,
stakeholderImpact,
dataSensitivity,
reversibility: calculateReversibility(activityType, stakeholderImpact)
};
}
/**
* Calculate reversibility of action
*/
function calculateReversibility(activityType, stakeholderImpact) {
// Public-facing and client communication is harder to reverse
if (stakeholderImpact === STAKEHOLDER_IMPACT.PUBLIC ||
stakeholderImpact === STAKEHOLDER_IMPACT.CLIENT) {
return 'difficult';
}
// Deployment is harder to reverse
if (activityType === ACTIVITY_TYPES.DEPLOYMENT) {
return 'moderate';
}
// Code and documentation are easily reversible
if (activityType === ACTIVITY_TYPES.CODE_GENERATION ||
activityType === ACTIVITY_TYPES.DOCUMENTATION) {
return 'easy';
}
return 'moderate';
}
/**
* Get human-readable activity description
*/
function getActivityDescription(classification) {
const { activityType, stakeholderImpact, riskLevel } = classification;
const descriptions = {
[ACTIVITY_TYPES.CODE_GENERATION]: 'Internal development work',
[ACTIVITY_TYPES.CLIENT_COMMUNICATION]: 'Client-facing content',
[ACTIVITY_TYPES.DOCUMENTATION]: 'Documentation updates',
[ACTIVITY_TYPES.DEPLOYMENT]: 'Production deployment',
[ACTIVITY_TYPES.COMPLIANCE_REVIEW]: 'Compliance validation',
[ACTIVITY_TYPES.AUTONOMOUS_PROCESSING]: 'Background processing',
[ACTIVITY_TYPES.DATA_MANAGEMENT]: 'Data operations'
};
return descriptions[activityType] || 'Unknown activity';
}
/**
* Calculate business impact score (0-100)
*/
function calculateBusinessImpact(classification, wasBlocked) {
let score = 0;
// Risk level contribution (0-40)
const riskScores = {
[RISK_LEVELS.MINIMAL]: 5,
[RISK_LEVELS.LOW]: 10,
[RISK_LEVELS.MEDIUM]: 20,
[RISK_LEVELS.HIGH]: 30,
[RISK_LEVELS.CRITICAL]: 40
};
score += riskScores[classification.riskLevel] || 10;
// Stakeholder impact contribution (0-30)
const stakeholderScores = {
[STAKEHOLDER_IMPACT.INDIVIDUAL]: 5,
[STAKEHOLDER_IMPACT.TEAM]: 10,
[STAKEHOLDER_IMPACT.ORGANIZATION]: 20,
[STAKEHOLDER_IMPACT.CLIENT]: 25,
[STAKEHOLDER_IMPACT.PUBLIC]: 30
};
score += stakeholderScores[classification.stakeholderImpact] || 10;
// Data sensitivity contribution (0-20)
const sensitivityScores = {
[DATA_SENSITIVITY.PUBLIC]: 5,
[DATA_SENSITIVITY.INTERNAL]: 10,
[DATA_SENSITIVITY.CONFIDENTIAL]: 15,
[DATA_SENSITIVITY.RESTRICTED]: 20
};
score += sensitivityScores[classification.dataSensitivity] || 5;
// Reversibility contribution (0-10)
const reversibilityScores = {
'easy': 2,
'moderate': 5,
'difficult': 10
};
score += reversibilityScores[classification.reversibility] || 5;
// If blocked, this represents value saved
return wasBlocked ? score : 0;
}
module.exports = {
ACTIVITY_TYPES,
RISK_LEVELS,
STAKEHOLDER_IMPACT,
DATA_SENSITIVITY,
classifyActivity,
getActivityDescription,
calculateBusinessImpact
};