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>
236 lines
7.5 KiB
JavaScript
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
|
|
};
|