mindforge-cc 3.0.0 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agent/CLAUDE.md +50 -545
- package/.claude/CLAUDE.md +50 -545
- package/.mindforge/audit/AUDIT-SCHEMA.md +20 -1
- package/.mindforge/engine/nexus-tracer.js +115 -0
- package/.mindforge/engine/persona-factory.md +45 -0
- package/.mindforge/engine/swarm-controller.md +59 -0
- package/.mindforge/engine/wave-executor.md +104 -54
- package/.mindforge/memory/pattern-library.jsonl +1 -2
- package/.mindforge/personas/swarm-templates.json +118 -0
- package/.planning/ROI.jsonl +2 -0
- package/CHANGELOG.md +133 -22
- package/MINDFORGE.md +75 -106
- package/README.md +71 -101
- package/RELEASENOTES.md +41 -24
- package/bin/autonomous/auto-runner.js +154 -4
- package/bin/autonomous/context-refactorer.js +64 -0
- package/bin/autonomous/steer.js +19 -1
- package/bin/autonomous/stuck-monitor.js +43 -0
- package/bin/engine/feedback-loop.js +71 -0
- package/bin/engine/handover-manager.js +69 -0
- package/bin/engine/nexus-tracer.js +215 -0
- package/bin/engine/sre-manager.js +63 -0
- package/bin/engine/temporal-hindsight.js +88 -0
- package/bin/governance/policies/default-policies.jsonl +33 -0
- package/bin/governance/policy-engine.js +106 -0
- package/bin/governance/rbac-manager.js +109 -0
- package/bin/governance/trust-verifier.js +81 -0
- package/bin/governance/ztai-archiver.js +104 -0
- package/bin/governance/ztai-manager.js +203 -0
- package/bin/memory/eis-client.js +95 -0
- package/bin/memory/federated-sync.js +127 -0
- package/bin/memory/ghost-pattern-detector.js +69 -0
- package/bin/memory/knowledge-graph.js +37 -0
- package/bin/memory/semantic-hub.js +104 -0
- package/bin/models/cloud-broker.js +83 -0
- package/bin/models/finops-hub.js +79 -0
- package/bin/models/model-broker.js +129 -0
- package/bin/skill-validator.js +41 -0
- package/docs/INTELLIGENCE-MESH.md +35 -0
- package/docs/PERSONAS.md +63 -0
- package/docs/{references → References}/audit-events.md +6 -0
- package/docs/architecture/NEXUS-DASHBOARD.md +35 -0
- package/docs/architecture/PAR-ZTS-SURVEY.md +43 -0
- package/docs/architecture/README.md +31 -64
- package/docs/architecture/V4-SWARM-MESH.md +77 -0
- package/docs/architecture/V5-ENTERPRISE.md +113 -0
- package/docs/feature-dashboard.md +6 -1
- package/docs/governance-guide.md +47 -23
- package/docs/security/SECURITY.md +20 -7
- package/docs/security/ZTAI-OVERVIEW.md +37 -0
- package/docs/user-guide.md +29 -3
- package/docs/usp-features.md +79 -5
- package/package.json +1 -1
- /package/docs/{context → Context}/Master-Context.md +0 -0
- /package/docs/{references → References}/checkpoints.md +0 -0
- /package/docs/{references → References}/commands.md +0 -0
- /package/docs/{references → References}/config-reference.md +0 -0
- /package/docs/{references → References}/continuation-format.md +0 -0
- /package/docs/{references → References}/decimal-phase-calculation.md +0 -0
- /package/docs/{references → References}/git-integration.md +0 -0
- /package/docs/{references → References}/git-planning-commit.md +0 -0
- /package/docs/{references → References}/model-profile-resolution.md +0 -0
- /package/docs/{references → References}/model-profiles.md +0 -0
- /package/docs/{references → References}/phase-argument-parsing.md +0 -0
- /package/docs/{references → References}/planning-config.md +0 -0
- /package/docs/{references → References}/questioning.md +0 -0
- /package/docs/{references → References}/sdk-api.md +0 -0
- /package/docs/{references → References}/skills-api.md +0 -0
- /package/docs/{references → References}/tdd.md +0 -0
- /package/docs/{references → References}/ui-brand.md +0 -0
- /package/docs/{references → References}/user-profiling.md +0 -0
- /package/docs/{references → References}/verification-patterns.md +0 -0
- /package/docs/{references → References}/workstream-flag.md +0 -0
- /package/docs/{templates → Templates}/Agents/CLAUDE-MD.md +0 -0
- /package/docs/{templates → Templates}/Agents/COPILOT-INSTRUCTIONS.md +0 -0
- /package/docs/{templates → Templates}/Agents/DEBUGGER-PROMPT.md +0 -0
- /package/docs/{templates → Templates}/Agents/PLANNER-PROMPT.md +0 -0
- /package/docs/{templates/codebase → Templates/Codebase}/architecture.md +0 -0
- /package/docs/{templates/codebase → Templates/Codebase}/concerns.md +0 -0
- /package/docs/{templates/codebase → Templates/Codebase}/conventions.md +0 -0
- /package/docs/{templates/codebase → Templates/Codebase}/integrations.md +0 -0
- /package/docs/{templates/codebase → Templates/Codebase}/stack.md +0 -0
- /package/docs/{templates/codebase → Templates/Codebase}/structure.md +0 -0
- /package/docs/{templates/codebase → Templates/Codebase}/testing.md +0 -0
- /package/docs/{templates → Templates}/Execution/CONTINUE-HERE.md +0 -0
- /package/docs/{templates → Templates}/Execution/DISCUSSION-LOG.md +0 -0
- /package/docs/{templates → Templates}/Execution/PHASE-PROMPT.md +0 -0
- /package/docs/{templates → Templates}/Execution/STATE.md +0 -0
- /package/docs/{templates → Templates}/Execution/SUMMARY-COMPLEX.md +0 -0
- /package/docs/{templates → Templates}/Execution/SUMMARY-MINIMAL.md +0 -0
- /package/docs/{templates → Templates}/Execution/SUMMARY-STANDARD.md +0 -0
- /package/docs/{templates → Templates}/Execution/SUMMARY.md +0 -0
- /package/docs/{templates → Templates}/Profile/DEV-PREFERENCES.md +0 -0
- /package/docs/{templates → Templates}/Profile/USER-PROFILE.md +0 -0
- /package/docs/{templates → Templates}/Profile/USER-SETUP.md +0 -0
- /package/docs/{templates → Templates}/Project/DISCOVERY.md +0 -0
- /package/docs/{templates → Templates}/Project/MILESTONE-ARCHIVE.md +0 -0
- /package/docs/{templates → Templates}/Project/MILESTONE.md +0 -0
- /package/docs/{templates → Templates}/Project/PROJECT.md +0 -0
- /package/docs/{templates → Templates}/Project/REQUIREMENTS.md +0 -0
- /package/docs/{templates → Templates}/Project/RETROSPECTIVE.md +0 -0
- /package/docs/{templates → Templates}/Project/ROADMAP.md +0 -0
- /package/docs/{templates → Templates}/Quality/DEBUG.md +0 -0
- /package/docs/{templates → Templates}/Quality/UAT.md +0 -0
- /package/docs/{templates → Templates}/Quality/UI-SPEC.md +0 -0
- /package/docs/{templates → Templates}/Quality/VALIDATION.md +0 -0
- /package/docs/{templates → Templates}/Quality/VERIFICATION-REPORT.md +0 -0
- /package/docs/{templates/research → Templates/Research}/ARCHITECTURE.md +0 -0
- /package/docs/{templates/research → Templates/Research}/FEATURES.md +0 -0
- /package/docs/{templates/research → Templates/Research}/PITFALLS.md +0 -0
- /package/docs/{templates/research → Templates/Research}/STACK.md +0 -0
- /package/docs/{templates/research → Templates/Research}/SUMMARY.md +0 -0
- /package/docs/{templates → Templates}/System/CONFIG.json +0 -0
- /package/docs/{templates → Templates}/System/CONTEXT.md +0 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MindForge — SREManager (Pillar VI: Sovereign Reason Enclaves)
|
|
3
|
+
* Manages confidential reasoning sessions in simulated Trusted Execution Environments (TEE).
|
|
4
|
+
*/
|
|
5
|
+
'use strict';
|
|
6
|
+
|
|
7
|
+
const crypto = require('crypto');
|
|
8
|
+
|
|
9
|
+
class SREManager {
|
|
10
|
+
constructor() {
|
|
11
|
+
this.activeEnclaves = new Map();
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Initializes a Sovereign Reason Enclave for a task.
|
|
16
|
+
* @param {Object} context - Task context (requires Tier 3 identity)
|
|
17
|
+
* @returns {string} - Enclave ID
|
|
18
|
+
*/
|
|
19
|
+
initializeEnclave(context) {
|
|
20
|
+
if (context.tier < 3) {
|
|
21
|
+
throw new Error(`[SRE-DENY] Tier ${context.tier} principal is not authorized for Sovereign Reason Enclaves.`);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const enclaveId = crypto.randomBytes(12).toString('hex');
|
|
25
|
+
this.activeEnclaves.set(enclaveId, {
|
|
26
|
+
startedAt: new Date().toISOString(),
|
|
27
|
+
principal: context.did,
|
|
28
|
+
hasIP: true,
|
|
29
|
+
isolationLevel: 'Hardware-Enclave (Simulated)'
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
console.log(`[SRE-INIT] Initialized Sovereign Reason Enclave: ${enclaveId} for ${context.did}`);
|
|
33
|
+
return enclaveId;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Sanitizes a thought chain for global audit logging.
|
|
38
|
+
* Ensures that sensitive IP or "zero-visibility" thoughts are isolated.
|
|
39
|
+
* @param {string} thoughtChain - The raw agentic thought chain.
|
|
40
|
+
* @returns {string} - Sanitized/Isolated thought chain.
|
|
41
|
+
*/
|
|
42
|
+
sanitizeThoughtChain(thoughtChain, enclaveId) {
|
|
43
|
+
if (!this.activeEnclaves.has(enclaveId)) return thoughtChain;
|
|
44
|
+
|
|
45
|
+
// Zero-Visibility Protocol: In SRE mode, the global audit log only receives a hash
|
|
46
|
+
// or a redacted summary. The full chain is kept in volatile enclave memory.
|
|
47
|
+
const digest = crypto.createHash('sha256').update(thoughtChain).digest('hex');
|
|
48
|
+
|
|
49
|
+
return `[SRE-ISOLATED] Confidential reasoning executed in enclave ${enclaveId}. Verification Digest: ${digest}. Original trace is isolated from persistence.`;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Finalizes and purges the enclave.
|
|
54
|
+
*/
|
|
55
|
+
terminateEnclave(enclaveId) {
|
|
56
|
+
if (this.activeEnclaves.has(enclaveId)) {
|
|
57
|
+
this.activeEnclaves.delete(enclaveId);
|
|
58
|
+
console.log(`[SRE-PURGE] Sovereign Reason Enclave ${enclaveId} has been securely purged.`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
module.exports = SREManager;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MindForge — TemporalHindsight (Pillar VI: Proactive Equilibrium)
|
|
3
|
+
* Performs automated RCA and generates repair plans for diverging waves.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const fs = require('fs');
|
|
7
|
+
const path = require('path');
|
|
8
|
+
|
|
9
|
+
class TemporalHindsight {
|
|
10
|
+
constructor(config = {}) {
|
|
11
|
+
this.projectRoot = config.projectRoot || process.cwd();
|
|
12
|
+
this.historyLimit = config.historyLimit || 10; // Analyze last 10 failed tasks
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Performs Root Cause Analysis (RCA) on a failed wave.
|
|
17
|
+
* @param {Object} waveReport - Current wave results (failed tasks, logs)
|
|
18
|
+
* @returns {Object} - Diagnosis and Repair Plan
|
|
19
|
+
*/
|
|
20
|
+
async analyze(waveReport) {
|
|
21
|
+
const { failedTasks, divergence, phase } = waveReport;
|
|
22
|
+
const diagnosis = this.diagnoseFailures(failedTasks);
|
|
23
|
+
|
|
24
|
+
return {
|
|
25
|
+
timestamp: new Date().toISOString(),
|
|
26
|
+
phase,
|
|
27
|
+
divergence,
|
|
28
|
+
diagnosis,
|
|
29
|
+
repairPlan: this.generateRepairPlan(diagnosis, phase),
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Diagnoses common failure patterns in agentic workloads.
|
|
35
|
+
*/
|
|
36
|
+
diagnoseFailures(tasks) {
|
|
37
|
+
const errorMessages = tasks.map(t => t.error || '').join(' ').toLowerCase();
|
|
38
|
+
|
|
39
|
+
if (errorMessages.includes('permission denied') || errorMessages.includes('eacces')) {
|
|
40
|
+
return { type: 'ENVIRONMENTAL', cause: 'File system permission issues detected in multiple tasks.', severity: 'CRITICAL' };
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (errorMessages.includes('timeout') || errorMessages.includes('deadline exceeded')) {
|
|
44
|
+
return { type: 'RESOURCE', cause: 'Wave execution timeout. Tasks are too large or the model response is slow.', severity: 'HIGH' };
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (errorMessages.includes('lint') || errorMessages.includes('syntax error')) {
|
|
48
|
+
return { type: 'LOGIC', cause: 'Cumulative coding errors. The existing plan is producing invalid syntax consistently.', severity: 'STRICT' };
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return { type: 'UNKNOWN', cause: 'Generic wave divergence. Multiple unrelated failures detected.', severity: 'MEDIUM' };
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Generates a "Self-Healing" Plan.md entry.
|
|
56
|
+
*/
|
|
57
|
+
generateRepairPlan(diagnosis, phase) {
|
|
58
|
+
const steps = [];
|
|
59
|
+
|
|
60
|
+
switch (diagnosis.type) {
|
|
61
|
+
case 'ENVIRONMENTAL':
|
|
62
|
+
steps.push('PAUSE execution immediately.');
|
|
63
|
+
steps.push('Run `chmod -R u+w .` (simulated) on the affected directories.');
|
|
64
|
+
steps.push('Re-verify task 0.1 before resuming the wave.');
|
|
65
|
+
break;
|
|
66
|
+
case 'RESOURCE':
|
|
67
|
+
steps.push('PAUSE execution and increase `taskTimeoutMs` by 50%.');
|
|
68
|
+
steps.push('Request `EXECUTOR_MODEL` upgrade to `claude-3-opus` for complex tasks.');
|
|
69
|
+
steps.push('Serialise the next wave (concurrency = 1) to reduce resource contention.');
|
|
70
|
+
break;
|
|
71
|
+
case 'LOGIC':
|
|
72
|
+
steps.push('STOP active wave.');
|
|
73
|
+
steps.push('Rewrite Sub-tasks in PLAN.md for Phase ' + phase + ' with stricter TDD requirements.');
|
|
74
|
+
steps.push('Inject `Quality-Auditor` persona into the review loop.');
|
|
75
|
+
break;
|
|
76
|
+
default:
|
|
77
|
+
steps.push('PAUSE and request human review for divergence RCA.');
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return {
|
|
81
|
+
title: `AUTONOMOUS REPAIR PLAN: PHASE ${phase}`,
|
|
82
|
+
steps,
|
|
83
|
+
autoApplyStatus: 'PENDING_SIGNATURE',
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
module.exports = TemporalHindsight;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "policy_enforce_tier_3_security",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"effect": "DENY",
|
|
5
|
+
"description": "Agents with Tier < 3 cannot modify security or governance files.",
|
|
6
|
+
"conditions": {
|
|
7
|
+
"resource": "*/security/*,*/governance/*",
|
|
8
|
+
"min_tier": 3
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
<!-- slide -->
|
|
12
|
+
{
|
|
13
|
+
"id": "policy_permit_developer_src",
|
|
14
|
+
"version": "1.0.0",
|
|
15
|
+
"effect": "PERMIT",
|
|
16
|
+
"description": "Developer agents can write to src and tests.",
|
|
17
|
+
"conditions": {
|
|
18
|
+
"action": "write_file",
|
|
19
|
+
"resource": "*/src/*,*/tests/*",
|
|
20
|
+
"min_tier": 2
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
<!-- slide -->
|
|
24
|
+
{
|
|
25
|
+
"id": "policy_permit_global_sync_lead",
|
|
26
|
+
"version": "1.0.0",
|
|
27
|
+
"effect": "PERMIT",
|
|
28
|
+
"description": "Lead Architects can push to the Federated Intelligence Mesh.",
|
|
29
|
+
"conditions": {
|
|
30
|
+
"action": "federated_sync_push",
|
|
31
|
+
"min_tier": 3
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MindForge v5 — Agentic Policy Orchestrator (APO) Engine
|
|
3
|
+
* Evaluates agent intents against organizational security policies.
|
|
4
|
+
*/
|
|
5
|
+
'use strict';
|
|
6
|
+
|
|
7
|
+
const fs = require('node:fs');
|
|
8
|
+
const path = require('node:path');
|
|
9
|
+
|
|
10
|
+
class PolicyEngine {
|
|
11
|
+
constructor(config = {}) {
|
|
12
|
+
this.policiesDir = config.policiesDir || path.join(__dirname, 'policies');
|
|
13
|
+
this.ensurePoliciesDir();
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
ensurePoliciesDir() {
|
|
17
|
+
if (!fs.existsSync(this.policiesDir)) {
|
|
18
|
+
fs.mkdirSync(this.policiesDir, { recursive: true });
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Evaluates an agent's intent against all active policies.
|
|
24
|
+
* @param {Object} intent - The intent to evaluate.
|
|
25
|
+
* @param {string} intent.did - Source agent DID.
|
|
26
|
+
* @param {string} intent.action - Action type (e.g. 'write_file', 'delete_file').
|
|
27
|
+
* @param {string} intent.resource - Target resource (e.g. file path).
|
|
28
|
+
* @param {number} intent.tier - Agent trust tier.
|
|
29
|
+
* @returns {Object} - { verdict: 'PERMIT' | 'DENY', reason: string, requestId: string }
|
|
30
|
+
*/
|
|
31
|
+
evaluate(intent) {
|
|
32
|
+
const requestId = `pol_${Date.now()}_${Math.random().toString(36).slice(2, 7)}`;
|
|
33
|
+
console.log(`[APO-EVAL] [${requestId}] Evaluating intent: ${intent.action} on ${intent.resource} by ${intent.did}`);
|
|
34
|
+
|
|
35
|
+
const policies = this.loadPolicies();
|
|
36
|
+
|
|
37
|
+
// Default Deny if no policies found
|
|
38
|
+
if (policies.length === 0) {
|
|
39
|
+
return { verdict: 'DENY', reason: 'No organizational policies defined (Default Deny)', requestId };
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// 1. Check for explicit DENY rules first
|
|
43
|
+
for (const policy of policies) {
|
|
44
|
+
if (policy.effect === 'DENY' && this.matches(policy, intent)) {
|
|
45
|
+
return { verdict: 'DENY', reason: `Violation: ${policy.description || policy.id}`, requestId };
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// 2. Check for explicit PERMIT rules
|
|
50
|
+
for (const policy of policies) {
|
|
51
|
+
if (policy.effect === 'PERMIT' && this.matches(policy, intent)) {
|
|
52
|
+
return { verdict: 'PERMIT', reason: `Authorized by ${policy.id}`, requestId };
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return { verdict: 'DENY', reason: 'No matching PERMIT policy found (Implicit Deny)', requestId };
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
loadPolicies() {
|
|
60
|
+
if (!fs.existsSync(this.policiesDir)) return [];
|
|
61
|
+
|
|
62
|
+
return fs.readdirSync(this.policiesDir)
|
|
63
|
+
.filter(f => f.endsWith('.json'))
|
|
64
|
+
.map(f => {
|
|
65
|
+
try {
|
|
66
|
+
const content = fs.readFileSync(path.join(this.policiesDir, f), 'utf8');
|
|
67
|
+
return JSON.parse(content);
|
|
68
|
+
} catch (err) {
|
|
69
|
+
console.error(`[APO-ERROR] Failed to parse policy ${f}:`, err.message);
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
})
|
|
73
|
+
.filter(Boolean);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Simple rule matcher (simulated OPA/Rego logic).
|
|
78
|
+
*/
|
|
79
|
+
matches(policy, intent) {
|
|
80
|
+
const { conditions } = policy;
|
|
81
|
+
if (!conditions) return true;
|
|
82
|
+
|
|
83
|
+
// Check DID match (supports wildcards)
|
|
84
|
+
if (conditions.did && !this.globMatch(conditions.did, intent.did)) return false;
|
|
85
|
+
|
|
86
|
+
// Check Action match
|
|
87
|
+
if (conditions.action && !this.globMatch(conditions.action, intent.action)) return false;
|
|
88
|
+
|
|
89
|
+
// Check Resource match
|
|
90
|
+
if (conditions.resource && !this.globMatch(conditions.resource, intent.resource)) return false;
|
|
91
|
+
|
|
92
|
+
// Check Tier match
|
|
93
|
+
if (conditions.min_tier && intent.tier < conditions.min_tier) return false;
|
|
94
|
+
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
globMatch(pattern, text) {
|
|
99
|
+
if (pattern === '*') return true;
|
|
100
|
+
if (pattern === text) return true;
|
|
101
|
+
const regex = new RegExp('^' + pattern.replace(/\*/g, '.*') + '$');
|
|
102
|
+
return regex.test(text);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
module.exports = PolicyEngine;
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MindForge v5 — Agentic RBAC Manager
|
|
3
|
+
* Maps Agent DIDs to specific project roles and granular permissions.
|
|
4
|
+
*/
|
|
5
|
+
'use strict';
|
|
6
|
+
|
|
7
|
+
const fs = require('node:fs');
|
|
8
|
+
const path = require('node:path');
|
|
9
|
+
const ztai = require('./ztai-manager');
|
|
10
|
+
|
|
11
|
+
class RBACManager {
|
|
12
|
+
constructor(config = {}) {
|
|
13
|
+
this.rolesPath = config.rolesPath || path.join(process.cwd(), '.planning/AGENT-ROLES.json');
|
|
14
|
+
this.defaultRoles = {
|
|
15
|
+
'did:mindforge:planner': ['lead-architect', 'resource-optimizer'],
|
|
16
|
+
'did:mindforge:executor': ['developer', 'test-automator'],
|
|
17
|
+
'did:mindforge:reviewer': ['security-auditor', 'compliance-checker'],
|
|
18
|
+
'did:mindforge:researcher': ['knowledge-detective'],
|
|
19
|
+
'did:mindforge:tool': ['system-operator']
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Gets the roles assigned to a specific agent DID.
|
|
25
|
+
* @param {string} did
|
|
26
|
+
*/
|
|
27
|
+
getRoles(did) {
|
|
28
|
+
const roles = this.loadRoles();
|
|
29
|
+
// Return explicit roles OR default roles based on persona-matched DIDs
|
|
30
|
+
const explicit = roles[did];
|
|
31
|
+
if (explicit) return explicit;
|
|
32
|
+
|
|
33
|
+
// Default mapping (regex for persona-based DIDs)
|
|
34
|
+
for (const [pattern, defaultRoles] of Object.entries(this.defaultRoles)) {
|
|
35
|
+
if (did.includes(pattern)) return defaultRoles;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return ['guest-agent'];
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* [HARDEN] Dynamically binds roles based on ZTAI trust tiers if no explicit role exists.
|
|
43
|
+
* Ensures high-trust agents automatically get architect-level visibility.
|
|
44
|
+
*/
|
|
45
|
+
async getRolesByTier(did) {
|
|
46
|
+
const manager = new ztai();
|
|
47
|
+
const identity = await manager.getIdentity();
|
|
48
|
+
const explicit = this.getRoles(did);
|
|
49
|
+
|
|
50
|
+
if (identity.tier >= 3) {
|
|
51
|
+
return [...new Set([...explicit, 'lead-architect'])];
|
|
52
|
+
}
|
|
53
|
+
if (identity.tier >= 2) {
|
|
54
|
+
return [...new Set([...explicit, 'developer'])];
|
|
55
|
+
}
|
|
56
|
+
return explicit;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
loadRoles() {
|
|
60
|
+
if (!fs.existsSync(this.rolesPath)) return {};
|
|
61
|
+
try {
|
|
62
|
+
return JSON.parse(fs.readFileSync(this.rolesPath, 'utf8'));
|
|
63
|
+
} catch {
|
|
64
|
+
return {};
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Assigns a role to an agent.
|
|
70
|
+
*/
|
|
71
|
+
assignRole(did, roles) {
|
|
72
|
+
const current = this.loadRoles();
|
|
73
|
+
current[did] = Array.isArray(roles) ? roles : [roles];
|
|
74
|
+
fs.writeFileSync(this.rolesPath, JSON.stringify(current, null, 2));
|
|
75
|
+
console.log(`[RBAC] Assigned roles [${roles}] to agent ${did}`);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Revokes all roles for an agent.
|
|
80
|
+
*/
|
|
81
|
+
revokeRoles(did) {
|
|
82
|
+
const current = this.loadRoles();
|
|
83
|
+
delete current[did];
|
|
84
|
+
fs.writeFileSync(this.rolesPath, JSON.stringify(current, null, 2));
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Checks if an agent has a specific permission based on their roles.
|
|
89
|
+
* @param {string} did
|
|
90
|
+
* @param {string} permission
|
|
91
|
+
*/
|
|
92
|
+
hasPermission(did, permission) {
|
|
93
|
+
const roles = this.getRoles(did);
|
|
94
|
+
const PERMISSION_MAP = {
|
|
95
|
+
'lead-architect': ['write_architecture', 'approve_adr', 'global_sync_push'],
|
|
96
|
+
'developer': ['write_src', 'read_src', 'execute_tests'],
|
|
97
|
+
'security-auditor': ['read_security', 'write_audit_log', 'block_execution'],
|
|
98
|
+
'system-operator': ['write_bin', 'modify_infrastructure'],
|
|
99
|
+
'guest-agent': ['read_src']
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
for (const role of roles) {
|
|
103
|
+
if (PERMISSION_MAP[role]?.includes(permission)) return true;
|
|
104
|
+
}
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
module.exports = RBACManager;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MindForge ZTAI Trust Verifier
|
|
3
|
+
* v4.2.0-alpha.ztai
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const fs = require('fs');
|
|
7
|
+
const ztai = require('./ztai-manager');
|
|
8
|
+
|
|
9
|
+
class TrustVerifier {
|
|
10
|
+
/**
|
|
11
|
+
* Verifies a single audit entry.
|
|
12
|
+
* @param {object} entry - The audit entry object
|
|
13
|
+
* @returns {object} - { valid: boolean, error: string|null, tier: number }
|
|
14
|
+
*/
|
|
15
|
+
verifyEntry(entry) {
|
|
16
|
+
if (!entry.did || !entry.signature) {
|
|
17
|
+
return { valid: false, error: 'Missing ZTAI identity (did/signature)', tier: 0 };
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
try {
|
|
21
|
+
// Reconstruct payroll for verification (signature is stripped)
|
|
22
|
+
const { signature, ...payloadObj } = entry;
|
|
23
|
+
const payload = JSON.stringify(payloadObj);
|
|
24
|
+
|
|
25
|
+
const isValid = ztai.verifySignature(entry.did, payload, signature);
|
|
26
|
+
const agent = ztai.getAgent(entry.did);
|
|
27
|
+
|
|
28
|
+
if (!isValid) {
|
|
29
|
+
return { valid: false, error: 'Cryptographic signature mismatch', tier: agent ? agent.tier : 0 };
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return { valid: true, error: null, tier: agent.tier };
|
|
33
|
+
} catch (err) {
|
|
34
|
+
return { valid: false, error: err.message, tier: 0 };
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Validates a Tier 3 action requirement.
|
|
40
|
+
* @param {string} did - Executing agent DID
|
|
41
|
+
*/
|
|
42
|
+
isAuthorizedForTier3(did) {
|
|
43
|
+
const agent = ztai.getAgent(did);
|
|
44
|
+
return agent && agent.tier >= 3;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Scans a file of JSONL audit entries for integrity.
|
|
49
|
+
* @param {string} filePath
|
|
50
|
+
*/
|
|
51
|
+
async verifyAuditLog(filePath) {
|
|
52
|
+
const content = fs.readFileSync(filePath, 'utf8');
|
|
53
|
+
const lines = content.split('\n').filter(l => l.trim());
|
|
54
|
+
const results = {
|
|
55
|
+
total: lines.length,
|
|
56
|
+
valid: 0,
|
|
57
|
+
invalid: 0,
|
|
58
|
+
errors: []
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
for (const [index, line] of lines.entries()) {
|
|
62
|
+
try {
|
|
63
|
+
const entry = JSON.parse(line);
|
|
64
|
+
const { valid, error } = this.verifyEntry(entry);
|
|
65
|
+
if (valid) {
|
|
66
|
+
results.valid++;
|
|
67
|
+
} else {
|
|
68
|
+
results.invalid++;
|
|
69
|
+
results.errors.push(`Line ${index + 1}: ${error}`);
|
|
70
|
+
}
|
|
71
|
+
} catch (err) {
|
|
72
|
+
results.invalid++;
|
|
73
|
+
results.errors.push(`Line ${index + 1}: Invalid JSON`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return results;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
module.exports = new TrustVerifier();
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MindForge ZTAI Audit Archiver
|
|
3
|
+
* v4.2.5 — Non-Repudiation Engine
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const crypto = require('node:crypto');
|
|
7
|
+
const fs = require('node:fs/promises');
|
|
8
|
+
const path = require('node:path');
|
|
9
|
+
const ztai = require('./ztai-manager');
|
|
10
|
+
|
|
11
|
+
class ZTAIArchiver {
|
|
12
|
+
constructor(auditPath = '.mindforge/audit/AUDIT.jsonl') {
|
|
13
|
+
this.auditPath = auditPath;
|
|
14
|
+
this.manifestDir = '.mindforge/audit/manifests';
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Generates an integrity manifest for a specific block of audit entries.
|
|
19
|
+
* @param {Array<Object>} entries - A block of entries to sign.
|
|
20
|
+
* @param {string} archiverDid - The DID of the archiver (e.g., Release Manager)
|
|
21
|
+
* @returns {Promise<Object>} - The signed manifest
|
|
22
|
+
*/
|
|
23
|
+
async generateManifest(entries, archiverDid) {
|
|
24
|
+
if (!entries || entries.length === 0) return null;
|
|
25
|
+
|
|
26
|
+
// 1. Calculate the Merkle-like root hash of the block
|
|
27
|
+
const blockHashes = entries.map(e =>
|
|
28
|
+
crypto.createHash('sha256').update(JSON.stringify(e)).digest('hex')
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
// Simple cumulative hash chain as a Merkle Root equivalent
|
|
32
|
+
let cumulativeHash = '';
|
|
33
|
+
for (const h of blockHashes) {
|
|
34
|
+
cumulativeHash = crypto.createHash('sha256').update(cumulativeHash + h).digest('hex');
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const manifestMetadata = {
|
|
38
|
+
blockStart: entries[0].timestamp,
|
|
39
|
+
blockEnd: entries[entries.length - 1].timestamp,
|
|
40
|
+
entryCount: entries.length,
|
|
41
|
+
merkleRoot: cumulativeHash,
|
|
42
|
+
archivedAt: new Date().toISOString(),
|
|
43
|
+
archiver: archiverDid,
|
|
44
|
+
version: 'v4.2.5'
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
// 2. Sign the manifest with the archiver's DID
|
|
48
|
+
const signature = await ztai.signData(archiverDid, JSON.stringify(manifestMetadata));
|
|
49
|
+
|
|
50
|
+
return {
|
|
51
|
+
...manifestMetadata,
|
|
52
|
+
signature
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Scans the current AUDIT.jsonl and generates manifests for un-archived blocks.
|
|
58
|
+
* For the simulation, we process the entire file and generate one manifest.
|
|
59
|
+
*/
|
|
60
|
+
async archiveAuditLog(archiverDid) {
|
|
61
|
+
try {
|
|
62
|
+
const data = await fs.readFile(this.auditPath, 'utf8');
|
|
63
|
+
const lines = data.split('\n').filter(l => l.trim() !== '');
|
|
64
|
+
const entries = lines.map(l => JSON.parse(l));
|
|
65
|
+
|
|
66
|
+
if (entries.length === 0) return null;
|
|
67
|
+
|
|
68
|
+
const manifest = await this.generateManifest(entries, archiverDid);
|
|
69
|
+
|
|
70
|
+
// Ensure manifest directory exists
|
|
71
|
+
await fs.mkdir(this.manifestDir, { recursive: true });
|
|
72
|
+
|
|
73
|
+
const manifestPath = path.join(this.manifestDir, `manifest_${Date.now()}.json`);
|
|
74
|
+
await fs.writeFile(manifestPath, JSON.stringify(manifest, null, 2));
|
|
75
|
+
|
|
76
|
+
console.log(`[ZTAI-ARCHIVER] Manifest generated and signed by ${archiverDid}: ${manifestPath}`);
|
|
77
|
+
return manifest;
|
|
78
|
+
} catch (err) {
|
|
79
|
+
console.error(`[ZTAI-ARCHIVER] Failed to archive audit log: ${err.message}`);
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Verifies the integrity of the audit log against a manifest.
|
|
86
|
+
*/
|
|
87
|
+
async verifyIntegrity(manifestPath) {
|
|
88
|
+
const manifest = JSON.parse(await fs.readFile(manifestPath, 'utf8'));
|
|
89
|
+
const { signature, ...manifestMetadata } = manifest;
|
|
90
|
+
|
|
91
|
+
// 1. Verify Archiver Signature
|
|
92
|
+
const isSignatureValid = ztai.verifySignature(manifest.archiver, JSON.stringify(manifestMetadata), signature);
|
|
93
|
+
if (!isSignatureValid) {
|
|
94
|
+
throw new Error(`CRITICAL: Manifest signature invalid for ${manifestPath}`);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// 2. Recalculate and Verify Merkle Root (Simulated)
|
|
98
|
+
// In a real environment, this would compare against the actual AUDIT.jsonl data slices.
|
|
99
|
+
console.log(`[ZTAI-ARCHIVER] Integrity Verified for block ending ${manifest.blockEnd}`);
|
|
100
|
+
return true;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
module.exports = ZTAIArchiver;
|