kcp-harness 0.1.0 → 0.4.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/README.md +267 -0
- package/dist/audit-reader.d.ts +68 -0
- package/dist/audit-reader.js +150 -0
- package/dist/audit.d.ts +5 -0
- package/dist/audit.js +2 -1
- package/dist/budget-ledger.js +8 -0
- package/dist/classifier.d.ts +1 -1
- package/dist/classifier.js +33 -7
- package/dist/cli.js +65 -1
- package/dist/config.d.ts +4 -0
- package/dist/config.js +2 -0
- package/dist/dashboard/server.d.ts +30 -0
- package/dist/dashboard/server.js +145 -0
- package/dist/dashboard/tail.d.ts +18 -0
- package/dist/dashboard/tail.js +77 -0
- package/dist/dashboard/ui.d.ts +1 -0
- package/dist/dashboard/ui.js +193 -0
- package/dist/export.d.ts +28 -0
- package/dist/export.js +226 -0
- package/dist/governor.d.ts +3 -1
- package/dist/governor.js +18 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +3 -0
- package/package.json +2 -1
package/dist/export.js
ADDED
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
// Compliance evidence export — SOC 2 Type II and ISO 27001 Annex A.
|
|
2
|
+
//
|
|
3
|
+
// Reads the audit JSONL log and produces structured evidence bundles
|
|
4
|
+
// suitable for compliance auditors. The mapping is deterministic: audit
|
|
5
|
+
// events map to specific control IDs based on their type and outcome.
|
|
6
|
+
//
|
|
7
|
+
// Output: a directory of JSON evidence files + Markdown summary reports.
|
|
8
|
+
import { mkdirSync, writeFileSync } from "node:fs";
|
|
9
|
+
import { join } from "node:path";
|
|
10
|
+
import { AuditReader } from "./audit-reader.js";
|
|
11
|
+
/** Export compliance evidence from the audit log. */
|
|
12
|
+
export async function exportEvidence(options) {
|
|
13
|
+
const reader = new AuditReader(options.auditPath);
|
|
14
|
+
const filter = options.dateRange
|
|
15
|
+
? { from: options.dateRange.from, to: options.dateRange.to }
|
|
16
|
+
: undefined;
|
|
17
|
+
const events = await reader.readAll(filter);
|
|
18
|
+
const summary = await reader.summarize(filter);
|
|
19
|
+
const sessionIndex = await reader.sessionIndex();
|
|
20
|
+
const files = [];
|
|
21
|
+
// Create output directories
|
|
22
|
+
mkdirSync(options.outputDir, { recursive: true });
|
|
23
|
+
// Write manifest
|
|
24
|
+
const manifest = {
|
|
25
|
+
generator: "kcp-harness",
|
|
26
|
+
generatedAt: new Date().toISOString(),
|
|
27
|
+
organization: options.organization,
|
|
28
|
+
format: options.format,
|
|
29
|
+
dateRange: options.dateRange ?? summary.dateRange,
|
|
30
|
+
statistics: summary,
|
|
31
|
+
};
|
|
32
|
+
writeJSON(options.outputDir, "manifest.json", manifest);
|
|
33
|
+
files.push("manifest.json");
|
|
34
|
+
// Write raw data
|
|
35
|
+
mkdirSync(join(options.outputDir, "raw"), { recursive: true });
|
|
36
|
+
writeJSON(options.outputDir, "raw/sessions.json", sessionIndex);
|
|
37
|
+
writeJSON(options.outputDir, "raw/statistics.json", summary);
|
|
38
|
+
files.push("raw/sessions.json", "raw/statistics.json");
|
|
39
|
+
// Generate framework-specific evidence
|
|
40
|
+
if (options.format === "soc2" || options.format === "both") {
|
|
41
|
+
const soc2Files = exportSOC2(options.outputDir, events, summary, options.organization);
|
|
42
|
+
files.push(...soc2Files);
|
|
43
|
+
}
|
|
44
|
+
if (options.format === "iso27001" || options.format === "both") {
|
|
45
|
+
const isoFiles = exportISO27001(options.outputDir, events, summary, options.organization);
|
|
46
|
+
files.push(...isoFiles);
|
|
47
|
+
}
|
|
48
|
+
return { outputDir: options.outputDir, files, summary };
|
|
49
|
+
}
|
|
50
|
+
// -- SOC 2 Type II (Trust Services Criteria) ----------------------------------
|
|
51
|
+
function exportSOC2(outputDir, events, summary, org) {
|
|
52
|
+
const dir = join(outputDir, "soc2");
|
|
53
|
+
mkdirSync(dir, { recursive: true });
|
|
54
|
+
const files = [];
|
|
55
|
+
// CC6.1 — Logical and physical access controls
|
|
56
|
+
const cc61 = buildControlEvidence("CC6.1", "Logical and Physical Access Controls", "The entity implements logical access security software, infrastructure, and architectures over protected information assets to protect them from security events.", events, (e) => e.type === "tool_call" && e.classification?.governed === true, (e) => `${e.outcome}: ${e.governance?.reason ?? e.toolCall?.name ?? "unknown"}`);
|
|
57
|
+
writeJSON(dir, "CC6.1-logical-access.json", cc61);
|
|
58
|
+
files.push("soc2/CC6.1-logical-access.json");
|
|
59
|
+
// CC6.3 — Authorized access
|
|
60
|
+
const cc63 = buildControlEvidence("CC6.3", "Authorized Access", "The entity authorizes, modifies, or removes access to data, software, functions, and other protected information assets based on roles, responsibilities, or the system design and changes.", events, (e) => e.type === "tool_call" && e.governance?.mode === "plan-first", (e) => `pre-authorized via plan "${e.governance?.approvedPlan?.task ?? "unknown"}"`);
|
|
61
|
+
writeJSON(dir, "CC6.3-authorized-access.json", cc63);
|
|
62
|
+
files.push("soc2/CC6.3-authorized-access.json");
|
|
63
|
+
// CC6.6 — System boundaries
|
|
64
|
+
const cc66 = buildControlEvidence("CC6.6", "System Boundaries", "The entity implements logical access security measures to protect against threats from sources outside its system boundaries.", events, (e) => e.type === "tool_call", (e) => e.classification?.governed
|
|
65
|
+
? `governed: ${e.classification.reason}`
|
|
66
|
+
: `pass-through: ${e.classification?.reason ?? "unclassified"}`);
|
|
67
|
+
writeJSON(dir, "CC6.6-system-boundaries.json", cc66);
|
|
68
|
+
files.push("soc2/CC6.6-system-boundaries.json");
|
|
69
|
+
// CC7.2 — Monitoring
|
|
70
|
+
const cc72 = buildControlEvidence("CC7.2", "Monitoring Activities", "The entity monitors system components and the operation of those components for anomalies that are indicative of malicious acts, natural disasters, and errors affecting the entity's ability to meet its objectives.", events, (_e) => true, (e) => `[${e.type}] ${e.outcome}: ${shortDetail(e)}`);
|
|
71
|
+
writeJSON(dir, "CC7.2-monitoring.json", cc72);
|
|
72
|
+
files.push("soc2/CC7.2-monitoring.json");
|
|
73
|
+
// CC8.1 — Change management
|
|
74
|
+
const cc81 = buildControlEvidence("CC8.1", "Change Management", "The entity authorizes, designs, develops or acquires, configures, documents, tests, approves, and implements changes to infrastructure, data, software, and procedures to meet its objectives.", events, (e) => e.type === "temporal_drift" || e.type === "plan_invalidated", (e) => e.drift
|
|
75
|
+
? `drift detected in ${e.drift.manifest}: ${e.drift.summary}`
|
|
76
|
+
: `${e.type}: ${e.outcome}`);
|
|
77
|
+
writeJSON(dir, "CC8.1-change-management.json", cc81);
|
|
78
|
+
files.push("soc2/CC8.1-change-management.json");
|
|
79
|
+
// Summary report
|
|
80
|
+
const report = generateSOC2Report(summary, cc61, cc63, cc66, cc72, cc81, org);
|
|
81
|
+
writeFile(dir, "summary.md", report);
|
|
82
|
+
files.push("soc2/summary.md");
|
|
83
|
+
return files;
|
|
84
|
+
}
|
|
85
|
+
// -- ISO 27001 Annex A --------------------------------------------------------
|
|
86
|
+
function exportISO27001(outputDir, events, summary, org) {
|
|
87
|
+
const dir = join(outputDir, "iso27001");
|
|
88
|
+
mkdirSync(dir, { recursive: true });
|
|
89
|
+
const files = [];
|
|
90
|
+
// A.8.3 — Information access restriction
|
|
91
|
+
const a83 = buildControlEvidence("A.8.3", "Information Access Restriction", "Access to information and other associated assets shall be restricted in accordance with the established topic-specific policy on access control.", events, (e) => e.type === "tool_call" && e.classification?.governed === true, (e) => `${e.outcome}: ${e.governance?.reason ?? e.toolCall?.name ?? "unknown"}`);
|
|
92
|
+
writeJSON(dir, "A.8.3-access-restriction.json", a83);
|
|
93
|
+
files.push("iso27001/A.8.3-access-restriction.json");
|
|
94
|
+
// A.8.4 — Access to source code
|
|
95
|
+
const a84 = buildControlEvidence("A.8.4", "Access to Source Code", "Read and write access to source code, development tools and software libraries shall be appropriately managed.", events, (e) => e.type === "tool_call" && e.classification?.governed === true
|
|
96
|
+
&& (e.toolCall?.name === "Read" || e.toolCall?.name === "Glob" || e.toolCall?.name === "Grep"), (e) => `${e.toolCall?.name} ${e.classification?.target ?? ""}: ${e.outcome}`);
|
|
97
|
+
writeJSON(dir, "A.8.4-source-code-access.json", a84);
|
|
98
|
+
files.push("iso27001/A.8.4-source-code-access.json");
|
|
99
|
+
// A.8.15 — Logging
|
|
100
|
+
const a815 = buildControlEvidence("A.8.15", "Logging", "Logs that record activities, exceptions, faults and other relevant events shall be produced, stored, protected and analysed.", events, (e) => e.type === "session_start" || e.type === "session_end", (e) => `session ${e.sessionId}: ${e.type}`);
|
|
101
|
+
writeJSON(dir, "A.8.15-logging.json", a815);
|
|
102
|
+
files.push("iso27001/A.8.15-logging.json");
|
|
103
|
+
// A.8.16 — Monitoring activities
|
|
104
|
+
const a816 = buildControlEvidence("A.8.16", "Monitoring Activities", "Networks, systems and applications shall be monitored for anomalous behaviour and appropriate actions taken to evaluate potential information security incidents.", events, (e) => e.type === "temporal_drift" || e.type === "budget_exceeded" || e.outcome === "blocked", (e) => `[${e.type}] ${e.outcome}: ${shortDetail(e)}`);
|
|
105
|
+
writeJSON(dir, "A.8.16-monitoring.json", a816);
|
|
106
|
+
files.push("iso27001/A.8.16-monitoring.json");
|
|
107
|
+
// A.5.23 — Information security for use of cloud services
|
|
108
|
+
const a523 = buildControlEvidence("A.5.23", "Information Security for Use of Cloud Services", "Processes for acquisition, use, management and exit from cloud services shall be established in accordance with the organization's information security requirements.", events, (e) => e.type === "tool_call" && e.signature !== undefined, (e) => `signature ${e.signature?.status ?? "unknown"}: ${e.signature?.detail ?? e.toolCall?.name ?? ""}`);
|
|
109
|
+
writeJSON(dir, "A.5.23-cloud-services.json", a523);
|
|
110
|
+
files.push("iso27001/A.5.23-cloud-services.json");
|
|
111
|
+
// Summary report
|
|
112
|
+
const report = generateISO27001Report(summary, a83, a84, a815, a816, a523, org);
|
|
113
|
+
writeFile(dir, "summary.md", report);
|
|
114
|
+
files.push("iso27001/summary.md");
|
|
115
|
+
return files;
|
|
116
|
+
}
|
|
117
|
+
// -- Helpers ------------------------------------------------------------------
|
|
118
|
+
function buildControlEvidence(controlId, controlName, description, events, predicate, detailFn) {
|
|
119
|
+
const matching = events.filter(predicate);
|
|
120
|
+
return {
|
|
121
|
+
controlId,
|
|
122
|
+
controlName,
|
|
123
|
+
description,
|
|
124
|
+
evidenceCount: matching.length,
|
|
125
|
+
events: matching.map((e) => ({
|
|
126
|
+
timestamp: e.timestamp,
|
|
127
|
+
sessionId: e.sessionId,
|
|
128
|
+
type: e.type,
|
|
129
|
+
outcome: e.outcome,
|
|
130
|
+
detail: detailFn(e),
|
|
131
|
+
})),
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
function shortDetail(e) {
|
|
135
|
+
if (e.drift)
|
|
136
|
+
return `drift in ${e.drift.manifest}`;
|
|
137
|
+
if (e.budget)
|
|
138
|
+
return `budget ${e.budget.totals?.USDC ?? 0}/${e.budget.ceiling?.amount ?? "∞"}`;
|
|
139
|
+
if (e.governance)
|
|
140
|
+
return e.governance.reason;
|
|
141
|
+
if (e.toolCall)
|
|
142
|
+
return `${e.toolCall.name}`;
|
|
143
|
+
return e.type;
|
|
144
|
+
}
|
|
145
|
+
function generateSOC2Report(summary, ...controls) {
|
|
146
|
+
const org = controls.pop();
|
|
147
|
+
const ctrls = controls;
|
|
148
|
+
const lines = [
|
|
149
|
+
`# SOC 2 Type II — Evidence Summary`,
|
|
150
|
+
org ? `\n**Organization**: ${org}` : "",
|
|
151
|
+
`\n**Generated**: ${new Date().toISOString()}`,
|
|
152
|
+
`**Period**: ${summary.dateRange.first || "N/A"} — ${summary.dateRange.last || "N/A"}`,
|
|
153
|
+
``,
|
|
154
|
+
`## Overview`,
|
|
155
|
+
``,
|
|
156
|
+
`| Metric | Value |`,
|
|
157
|
+
`|--------|-------|`,
|
|
158
|
+
`| Sessions | ${summary.sessions} |`,
|
|
159
|
+
`| Total events | ${summary.events} |`,
|
|
160
|
+
`| Governed access attempts | ${summary.governed} |`,
|
|
161
|
+
`| Blocked | ${summary.blocked} |`,
|
|
162
|
+
`| Budget exceeded | ${summary.budgetExceeded} |`,
|
|
163
|
+
`| Temporal drifts | ${summary.drifts} |`,
|
|
164
|
+
`| Signature-blocked | ${summary.signatureBlocked} |`,
|
|
165
|
+
``,
|
|
166
|
+
`## Controls`,
|
|
167
|
+
``,
|
|
168
|
+
`| Control | Name | Evidence Count |`,
|
|
169
|
+
`|---------|------|---------------|`,
|
|
170
|
+
...ctrls.map((c) => `| ${c.controlId} | ${c.controlName} | ${c.evidenceCount} |`),
|
|
171
|
+
``,
|
|
172
|
+
...ctrls.map((c) => [
|
|
173
|
+
`### ${c.controlId} — ${c.controlName}`,
|
|
174
|
+
``,
|
|
175
|
+
`> ${c.description}`,
|
|
176
|
+
``,
|
|
177
|
+
`Evidence items: **${c.evidenceCount}**`,
|
|
178
|
+
``,
|
|
179
|
+
].join("\n")),
|
|
180
|
+
];
|
|
181
|
+
return lines.filter(Boolean).join("\n") + "\n";
|
|
182
|
+
}
|
|
183
|
+
function generateISO27001Report(summary, ...controls) {
|
|
184
|
+
const org = controls.pop();
|
|
185
|
+
const ctrls = controls;
|
|
186
|
+
const lines = [
|
|
187
|
+
`# ISO 27001 Annex A — Evidence Summary`,
|
|
188
|
+
org ? `\n**Organization**: ${org}` : "",
|
|
189
|
+
`\n**Generated**: ${new Date().toISOString()}`,
|
|
190
|
+
`**Period**: ${summary.dateRange.first || "N/A"} — ${summary.dateRange.last || "N/A"}`,
|
|
191
|
+
``,
|
|
192
|
+
`## Overview`,
|
|
193
|
+
``,
|
|
194
|
+
`| Metric | Value |`,
|
|
195
|
+
`|--------|-------|`,
|
|
196
|
+
`| Sessions | ${summary.sessions} |`,
|
|
197
|
+
`| Total events | ${summary.events} |`,
|
|
198
|
+
`| Governed access attempts | ${summary.governed} |`,
|
|
199
|
+
`| Blocked | ${summary.blocked} |`,
|
|
200
|
+
`| Budget exceeded | ${summary.budgetExceeded} |`,
|
|
201
|
+
`| Temporal drifts | ${summary.drifts} |`,
|
|
202
|
+
`| Signature-blocked | ${summary.signatureBlocked} |`,
|
|
203
|
+
``,
|
|
204
|
+
`## Controls`,
|
|
205
|
+
``,
|
|
206
|
+
`| Control | Name | Evidence Count |`,
|
|
207
|
+
`|---------|------|---------------|`,
|
|
208
|
+
...ctrls.map((c) => `| ${c.controlId} | ${c.controlName} | ${c.evidenceCount} |`),
|
|
209
|
+
``,
|
|
210
|
+
...ctrls.map((c) => [
|
|
211
|
+
`### ${c.controlId} — ${c.controlName}`,
|
|
212
|
+
``,
|
|
213
|
+
`> ${c.description}`,
|
|
214
|
+
``,
|
|
215
|
+
`Evidence items: **${c.evidenceCount}**`,
|
|
216
|
+
``,
|
|
217
|
+
].join("\n")),
|
|
218
|
+
];
|
|
219
|
+
return lines.filter(Boolean).join("\n") + "\n";
|
|
220
|
+
}
|
|
221
|
+
function writeJSON(dir, filename, data) {
|
|
222
|
+
writeFileSync(join(dir, filename), JSON.stringify(data, null, 2) + "\n", "utf-8");
|
|
223
|
+
}
|
|
224
|
+
function writeFile(dir, filename, content) {
|
|
225
|
+
writeFileSync(join(dir, filename), content, "utf-8");
|
|
226
|
+
}
|
package/dist/governor.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type AgentPlan, type DecisionTrace } from "kcp-agent";
|
|
1
|
+
import { type AgentPlan, type DecisionTrace, type SignatureResult } from "kcp-agent";
|
|
2
2
|
import type { GovernancePolicy } from "./config.js";
|
|
3
3
|
import type { Classification } from "./classifier.js";
|
|
4
4
|
import type { SessionState, ApprovedPlan } from "./session.js";
|
|
@@ -19,6 +19,8 @@ export interface GovernanceDecision {
|
|
|
19
19
|
approvedPlan?: ApprovedPlan;
|
|
20
20
|
/** Budget spend result (for auto-plan mode with costs). */
|
|
21
21
|
budgetSpend?: SpendResult;
|
|
22
|
+
/** Manifest signature verification result (when signature checking is active). */
|
|
23
|
+
signature?: SignatureResult;
|
|
22
24
|
}
|
|
23
25
|
/**
|
|
24
26
|
* Govern a classified tool call — decide whether to approve or block.
|
package/dist/governor.js
CHANGED
|
@@ -100,6 +100,18 @@ async function autoGovern(target, domain, session, policy) {
|
|
|
100
100
|
approved: false,
|
|
101
101
|
mode: "blocked",
|
|
102
102
|
reason: `manifest error: ${tree.error}`,
|
|
103
|
+
signature: tree.signature,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
// Signature enforcement: if required, block on non-verified signatures
|
|
107
|
+
if (policy.signature_required && tree.signature?.status !== "verified") {
|
|
108
|
+
const status = tree.signature?.status ?? "unsigned";
|
|
109
|
+
const detail = tree.signature?.detail ?? "no signing block in manifest";
|
|
110
|
+
return {
|
|
111
|
+
approved: false,
|
|
112
|
+
mode: "blocked",
|
|
113
|
+
reason: `manifest signature ${status}: ${detail}`,
|
|
114
|
+
signature: tree.signature,
|
|
103
115
|
};
|
|
104
116
|
}
|
|
105
117
|
// Extract the flat plan list
|
|
@@ -131,6 +143,7 @@ async function autoGovern(target, domain, session, policy) {
|
|
|
131
143
|
mode: "auto-plan",
|
|
132
144
|
plan: rootPlan,
|
|
133
145
|
budgetSpend,
|
|
146
|
+
signature: tree.signature,
|
|
134
147
|
reason: `auto-plan blocked: budget ceiling exceeded — ${budgetSpend.reason}`,
|
|
135
148
|
};
|
|
136
149
|
}
|
|
@@ -142,6 +155,7 @@ async function autoGovern(target, domain, session, policy) {
|
|
|
142
155
|
mode: "auto-plan",
|
|
143
156
|
plan: rootPlan,
|
|
144
157
|
budgetSpend,
|
|
158
|
+
signature: tree.signature,
|
|
145
159
|
reason: `auto-plan approved: unit "${matchingUnit.id}" (score ${matchingUnit.score}) covers ${target}`,
|
|
146
160
|
};
|
|
147
161
|
}
|
|
@@ -152,6 +166,7 @@ async function autoGovern(target, domain, session, policy) {
|
|
|
152
166
|
approved: false,
|
|
153
167
|
mode: "auto-plan",
|
|
154
168
|
plan: rootPlan,
|
|
169
|
+
signature: tree.signature,
|
|
155
170
|
reason: `auto-plan blocked: unit "${ineligibleUnit.id}" covers ${target} but is not load-eligible (${ineligibleUnit.reasons.filter(r => r.startsWith("unaffordable") || r.startsWith("needs")).join("; ") || "gate restriction"})`,
|
|
156
171
|
};
|
|
157
172
|
}
|
|
@@ -164,6 +179,7 @@ async function autoGovern(target, domain, session, policy) {
|
|
|
164
179
|
approved: false,
|
|
165
180
|
mode: "auto-plan",
|
|
166
181
|
plan: rootPlan,
|
|
182
|
+
signature: tree.signature,
|
|
167
183
|
reason: `auto-plan blocked: ${skipReason}`,
|
|
168
184
|
};
|
|
169
185
|
}
|
|
@@ -188,6 +204,8 @@ function buildFollowOptions(policy, session) {
|
|
|
188
204
|
planOptions,
|
|
189
205
|
maxDepth: 0, // auto-plan doesn't follow federation by default
|
|
190
206
|
fetchGuard: {}, // default guards (no private hosts, https only)
|
|
207
|
+
requireSignature: policy.signature_required ?? false,
|
|
208
|
+
trustedKey: policy.trusted_keys?.[0], // FollowOptions takes a single key
|
|
191
209
|
};
|
|
192
210
|
}
|
|
193
211
|
function normalizePath(p) {
|
package/dist/index.d.ts
CHANGED
|
@@ -10,3 +10,6 @@ export { BudgetLedger, type BudgetCeiling, type LedgerEntry, type LedgerSource,
|
|
|
10
10
|
export { TemporalWatch, type WatchedPlan, type DriftResult, type WatchResult, } from "./temporal-watch.js";
|
|
11
11
|
export { generate, generateAll, listAgents, harnessServerEntry, governedPathsBlock, manifestRef, } from "./integrations/generate.js";
|
|
12
12
|
export { AGENTS, type AgentTarget, type IntegrationOutput, type IntegrationFile, type IntegrationOptions, type AgentInfo, } from "./integrations/types.js";
|
|
13
|
+
export { AuditReader, type AuditFilter, type AuditSummary, type SessionEntry, type SessionIndex, } from "./audit-reader.js";
|
|
14
|
+
export { exportEvidence, type ExportOptions, type ExportResult, } from "./export.js";
|
|
15
|
+
export { DashboardServer, type DashboardOptions, } from "./dashboard/server.js";
|
package/dist/index.js
CHANGED
|
@@ -19,3 +19,6 @@ export { BudgetLedger, } from "./budget-ledger.js";
|
|
|
19
19
|
export { TemporalWatch, } from "./temporal-watch.js";
|
|
20
20
|
export { generate, generateAll, listAgents, harnessServerEntry, governedPathsBlock, manifestRef, } from "./integrations/generate.js";
|
|
21
21
|
export { AGENTS, } from "./integrations/types.js";
|
|
22
|
+
export { AuditReader, } from "./audit-reader.js";
|
|
23
|
+
export { exportEvidence, } from "./export.js";
|
|
24
|
+
export { DashboardServer, } from "./dashboard/server.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kcp-harness",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "KCP Compliance Harness — MCP proxy that enforces deterministic knowledge governance for any agent",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
},
|
|
12
12
|
"files": [
|
|
13
13
|
"dist",
|
|
14
|
+
"README.md",
|
|
14
15
|
"LICENSE"
|
|
15
16
|
],
|
|
16
17
|
"scripts": {
|