@attested-intelligence/aga-mcp-server 2.2.0 → 2.2.2
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 +80 -68
- package/dist/adapters/openclaw.d.ts +0 -1
- package/dist/adapters/openclaw.d.ts.map +1 -1
- package/dist/adapters/openclaw.js +0 -1
- package/dist/adapters/openclaw.js.map +1 -1
- package/dist/proxy/evaluator.d.ts +0 -1
- package/dist/proxy/evaluator.d.ts.map +1 -1
- package/dist/proxy/evaluator.js +0 -1
- package/dist/proxy/evaluator.js.map +1 -1
- package/dist/proxy/index.d.ts +0 -1
- package/dist/proxy/index.d.ts.map +1 -1
- package/dist/proxy/index.js +0 -1
- package/dist/proxy/index.js.map +1 -1
- package/dist/proxy/profiles.d.ts +0 -1
- package/dist/proxy/profiles.d.ts.map +1 -1
- package/dist/proxy/profiles.js +0 -1
- package/dist/proxy/profiles.js.map +1 -1
- package/dist/proxy/server.d.ts +0 -1
- package/dist/proxy/server.d.ts.map +1 -1
- package/dist/proxy/server.js +0 -1
- package/dist/proxy/server.js.map +1 -1
- package/dist/proxy/stdio-bridge.d.ts +0 -1
- package/dist/proxy/stdio-bridge.d.ts.map +1 -1
- package/dist/proxy/stdio-bridge.js +0 -1
- package/dist/proxy/stdio-bridge.js.map +1 -1
- package/dist/proxy/types.d.ts +0 -1
- package/dist/proxy/types.d.ts.map +1 -1
- package/dist/proxy/types.js +0 -1
- package/dist/proxy/types.js.map +1 -1
- package/dist/proxy/verify.d.ts +0 -1
- package/dist/proxy/verify.d.ts.map +1 -1
- package/dist/proxy/verify.js +0 -1
- package/dist/proxy/verify.js.map +1 -1
- package/package.json +93 -97
- package/SECURITY.md +0 -59
- package/independent-verifier/README.md +0 -31
- package/independent-verifier/package.json +0 -18
- package/independent-verifier/verify.ts +0 -211
- package/src/adapters/openclaw.ts +0 -125
- package/src/core/artifact.ts +0 -45
- package/src/core/attestation.ts +0 -33
- package/src/core/behavioral.ts +0 -132
- package/src/core/bundle.ts +0 -45
- package/src/core/chain.ts +0 -72
- package/src/core/checkpoint.ts +0 -22
- package/src/core/delegation.ts +0 -146
- package/src/core/disclosure.ts +0 -32
- package/src/core/identity.ts +0 -62
- package/src/core/index.ts +0 -14
- package/src/core/portal.ts +0 -117
- package/src/core/quarantine.ts +0 -16
- package/src/core/receipt.ts +0 -33
- package/src/core/subject.ts +0 -11
- package/src/core/types.ts +0 -285
- package/src/crypto/hash.ts +0 -33
- package/src/crypto/index.ts +0 -5
- package/src/crypto/merkle.ts +0 -43
- package/src/crypto/salt.ts +0 -18
- package/src/crypto/sign.ts +0 -42
- package/src/crypto/types.ts +0 -19
- package/src/index.ts +0 -12
- package/src/middleware/governance.ts +0 -95
- package/src/middleware/index.ts +0 -1
- package/src/proxy/evaluator.ts +0 -176
- package/src/proxy/index.ts +0 -259
- package/src/proxy/profiles.ts +0 -48
- package/src/proxy/server.ts +0 -499
- package/src/proxy/stdio-bridge.ts +0 -171
- package/src/proxy/types.ts +0 -40
- package/src/proxy/verify.ts +0 -202
- package/src/server.ts +0 -435
- package/src/storage/index.ts +0 -3
- package/src/storage/interface.ts +0 -21
- package/src/storage/memory.ts +0 -27
- package/src/storage/sqlite.ts +0 -45
- package/src/tools/README.md +0 -13
- package/src/utils/canonical.ts +0 -14
- package/src/utils/constants.ts +0 -3
- package/src/utils/timestamp.ts +0 -12
- package/src/utils/uuid.ts +0 -2
package/src/core/identity.ts
DELETED
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Identity and Key Lifecycle.
|
|
3
|
-
*
|
|
4
|
-
* Non-biometric cryptographic identity: agent identity derived from
|
|
5
|
-
* cryptographic key pair bound to append-only attestation history in
|
|
6
|
-
* continuity chain. Authority from valid signature history, not biometric traits.
|
|
7
|
-
*
|
|
8
|
-
* Functions:
|
|
9
|
-
* - keyFingerprint: re-exported from crypto/sign.ts for convenience
|
|
10
|
-
* - isKeyValid: check key TTL expiry
|
|
11
|
-
* - rotateKeyPair: generate new key pair for rotation
|
|
12
|
-
* - recordKeyRotation: append KEY_ROTATION event to chain
|
|
13
|
-
*/
|
|
14
|
-
import { generateKeyPair, keyFingerprint, pkToHex } from '../crypto/sign.js';
|
|
15
|
-
import { isExpired } from '../utils/timestamp.js';
|
|
16
|
-
import { appendEvent } from './chain.js';
|
|
17
|
-
import type { KeyPair } from '../crypto/types.js';
|
|
18
|
-
import type { ContinuityEvent, KeyRotationRecord } from './types.js';
|
|
19
|
-
|
|
20
|
-
// Re-export keyFingerprint for identity module consumers (NCCoE §2)
|
|
21
|
-
export { keyFingerprint } from '../crypto/sign.js';
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Check whether a key is still valid given its issuance time and TTL.
|
|
25
|
-
* NCCoE §2: non-biometric identity validity check.
|
|
26
|
-
*/
|
|
27
|
-
export function isKeyValid(issuedAt: string, ttlSeconds: number): boolean {
|
|
28
|
-
return !isExpired(issuedAt, ttlSeconds);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Generate a new key pair for rotation, returning both old and new for
|
|
33
|
-
* a transition period defined by policy. NCCoE §3: key rotation.
|
|
34
|
-
*/
|
|
35
|
-
export function rotateKeyPair(currentKeyPair: KeyPair): { oldKeyPair: KeyPair; newKeyPair: KeyPair } {
|
|
36
|
-
const newKeyPair = generateKeyPair();
|
|
37
|
-
return { oldKeyPair: currentKeyPair, newKeyPair };
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Record a key rotation event on the continuity chain.
|
|
42
|
-
* NCCoE §3: "Key rotation is handled by including both old and new public keys
|
|
43
|
-
* during a transition period defined by policy."
|
|
44
|
-
*/
|
|
45
|
-
export function recordKeyRotation(
|
|
46
|
-
prevEvent: ContinuityEvent,
|
|
47
|
-
keypairType: string,
|
|
48
|
-
oldPublicKeyHex: string,
|
|
49
|
-
newPublicKeyHex: string,
|
|
50
|
-
reason: string,
|
|
51
|
-
signingKeyPair: KeyPair,
|
|
52
|
-
): ContinuityEvent {
|
|
53
|
-
const payload: KeyRotationRecord = {
|
|
54
|
-
keypair_type: keypairType,
|
|
55
|
-
old_public_key: oldPublicKeyHex,
|
|
56
|
-
new_public_key: newPublicKeyHex,
|
|
57
|
-
reason,
|
|
58
|
-
rotation_timestamp: new Date().toISOString(),
|
|
59
|
-
chain_sequence: prevEvent.sequence_number + 1,
|
|
60
|
-
};
|
|
61
|
-
return appendEvent('KEY_ROTATION', payload, prevEvent, signingKeyPair);
|
|
62
|
-
}
|
package/src/core/index.ts
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
export * from './types.js';
|
|
2
|
-
export * from './subject.js';
|
|
3
|
-
export * from './attestation.js';
|
|
4
|
-
export * from './artifact.js';
|
|
5
|
-
export * from './receipt.js';
|
|
6
|
-
export * from './chain.js';
|
|
7
|
-
export * from './portal.js';
|
|
8
|
-
export * from './quarantine.js';
|
|
9
|
-
export * from './checkpoint.js';
|
|
10
|
-
export * from './bundle.js';
|
|
11
|
-
export * from './disclosure.js';
|
|
12
|
-
export * from './behavioral.js';
|
|
13
|
-
export * from './delegation.js';
|
|
14
|
-
export * from './identity.js';
|
package/src/core/portal.ts
DELETED
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Portal (Sentinel) - Runtime Enforcement Boundary. Ref 150, 270-280.
|
|
3
|
-
* V3: TTL + revocation checked every measurement. Fail-closed semantics.
|
|
4
|
-
* Aligned with NCCoE filing Sections 3-4 and NIST-2025-0035.
|
|
5
|
-
*/
|
|
6
|
-
import { sha256Bytes, sha256Str } from '../crypto/hash.js';
|
|
7
|
-
import { b64ToSig, hexToPk, verifyStr } from '../crypto/sign.js';
|
|
8
|
-
import { canonicalize } from '../utils/canonical.js';
|
|
9
|
-
import { isWithinPeriod, isExpired, utcNow } from '../utils/timestamp.js';
|
|
10
|
-
import type { PolicyArtifact, PortalState, EnforcementAction, SubjectMetadata } from './types.js';
|
|
11
|
-
import type { HashHex } from '../crypto/types.js';
|
|
12
|
-
|
|
13
|
-
export interface MeasurementResult {
|
|
14
|
-
match: boolean;
|
|
15
|
-
currentBytesHash: HashHex;
|
|
16
|
-
currentMetaHash: HashHex;
|
|
17
|
-
expectedBytesHash: HashHex;
|
|
18
|
-
expectedMetaHash: HashHex;
|
|
19
|
-
ttl_ok: boolean;
|
|
20
|
-
revoked: boolean;
|
|
21
|
-
degraded?: boolean;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/** Degradation event record for the continuity chain. */
|
|
25
|
-
export interface DegradationEvent {
|
|
26
|
-
reason: string;
|
|
27
|
-
timestamp: string;
|
|
28
|
-
artifact_reference: HashHex;
|
|
29
|
-
previous_state: string;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export class Portal {
|
|
33
|
-
state: PortalState = 'INITIALIZATION';
|
|
34
|
-
artifact: PolicyArtifact | null = null;
|
|
35
|
-
sequenceCounter = 0;
|
|
36
|
-
lastLeafHash: HashHex | null = null;
|
|
37
|
-
revocations: Set<string> = new Set();
|
|
38
|
-
degradationLog: DegradationEvent[] = [];
|
|
39
|
-
|
|
40
|
-
loadArtifact(artifact: PolicyArtifact, pinnedPkHex: string): { ok: boolean; error?: string } {
|
|
41
|
-
this.state = 'ARTIFACT_VERIFICATION';
|
|
42
|
-
const { signature, ...unsigned } = artifact;
|
|
43
|
-
if (!verifyStr(b64ToSig(signature), canonicalize(unsigned), hexToPk(pinnedPkHex))) {
|
|
44
|
-
this.state = 'TERMINATED'; return { ok: false, error: 'Signature verification failed' };
|
|
45
|
-
}
|
|
46
|
-
if (!isWithinPeriod(utcNow(), artifact.effective_timestamp, artifact.expiration_timestamp)) {
|
|
47
|
-
this.state = 'TERMINATED'; return { ok: false, error: 'Artifact outside effective period' };
|
|
48
|
-
}
|
|
49
|
-
if (this.revocations.has(artifact.sealed_hash)) {
|
|
50
|
-
this.state = 'TERMINATED'; return { ok: false, error: 'Artifact has been revoked' };
|
|
51
|
-
}
|
|
52
|
-
this.artifact = artifact;
|
|
53
|
-
this.state = 'ACTIVE_MONITORING';
|
|
54
|
-
return { ok: true };
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
measure(subjectBytes: Uint8Array, meta: SubjectMetadata): MeasurementResult {
|
|
58
|
-
if (!this.artifact) throw new Error('No artifact loaded');
|
|
59
|
-
if (this.state === 'TERMINATED') throw new Error('Portal is terminated');
|
|
60
|
-
// SAFE_STATE allows continued measurement for logging
|
|
61
|
-
const empty = { currentBytesHash: '', currentMetaHash: '',
|
|
62
|
-
expectedBytesHash: this.artifact.subject_identifier.bytes_hash,
|
|
63
|
-
expectedMetaHash: this.artifact.subject_identifier.metadata_hash };
|
|
64
|
-
|
|
65
|
-
// Graceful degradation: TTL expiry -> SAFE_STATE + DEGRADATION event + continued logging
|
|
66
|
-
const ttl_ok = !isExpired(this.artifact.issued_timestamp, this.artifact.enforcement_parameters.ttl_seconds);
|
|
67
|
-
if (!ttl_ok) {
|
|
68
|
-
const prevState = this.state;
|
|
69
|
-
this.state = 'SAFE_STATE';
|
|
70
|
-
this.degradationLog.push({
|
|
71
|
-
reason: 'TTL_EXPIRED',
|
|
72
|
-
timestamp: utcNow(),
|
|
73
|
-
artifact_reference: this.artifact.sealed_hash,
|
|
74
|
-
previous_state: prevState,
|
|
75
|
-
});
|
|
76
|
-
return { match: false, ttl_ok: false, revoked: false, degraded: true, ...empty };
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// Fail-closed: revocation check
|
|
80
|
-
if (this.revocations.has(this.artifact.sealed_hash)) {
|
|
81
|
-
this.state = 'TERMINATED'; return { match: false, ttl_ok: true, revoked: true, ...empty };
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
const currentBytesHash = sha256Bytes(subjectBytes);
|
|
85
|
-
const currentMetaHash = sha256Str(canonicalize(meta));
|
|
86
|
-
const match = currentBytesHash === this.artifact.subject_identifier.bytes_hash &&
|
|
87
|
-
currentMetaHash === this.artifact.subject_identifier.metadata_hash;
|
|
88
|
-
|
|
89
|
-
if (!match && this.state === 'ACTIVE_MONITORING') this.state = 'DRIFT_DETECTED';
|
|
90
|
-
return { match, currentBytesHash, currentMetaHash,
|
|
91
|
-
expectedBytesHash: this.artifact.subject_identifier.bytes_hash,
|
|
92
|
-
expectedMetaHash: this.artifact.subject_identifier.metadata_hash,
|
|
93
|
-
ttl_ok: true, revoked: false };
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
enforce(action: EnforcementAction): void {
|
|
97
|
-
if (this.state !== 'DRIFT_DETECTED') throw new Error(`Cannot enforce in state ${this.state}`);
|
|
98
|
-
switch (action) {
|
|
99
|
-
case 'TERMINATE': case 'SAFE_STATE': this.state = 'TERMINATED'; break;
|
|
100
|
-
case 'QUARANTINE': this.state = 'PHANTOM_QUARANTINE'; break;
|
|
101
|
-
case 'ALERT_ONLY': this.state = 'ACTIVE_MONITORING'; break;
|
|
102
|
-
default: break;
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
revoke(sealedHash: string): void {
|
|
107
|
-
this.revocations.add(sealedHash);
|
|
108
|
-
if (this.artifact?.sealed_hash === sealedHash) this.state = 'TERMINATED';
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
isRevoked(sealedHash: string): boolean { return this.revocations.has(sealedHash); }
|
|
112
|
-
|
|
113
|
-
reset(): void {
|
|
114
|
-
this.state = 'INITIALIZATION'; this.artifact = null;
|
|
115
|
-
this.sequenceCounter = 0; this.lastLeafHash = null;
|
|
116
|
-
}
|
|
117
|
-
}
|
package/src/core/quarantine.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { utcNow } from '../utils/timestamp.js';
|
|
2
|
-
import type { QuarantineState } from './types.js';
|
|
3
|
-
|
|
4
|
-
export function initQuarantine(): QuarantineState {
|
|
5
|
-
return { active: true, started_at: utcNow(), inputs_captured: 0, outputs_severed: true, forensic_buffer: [] };
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
export function captureInput(q: QuarantineState, inputType: string, data: unknown): void {
|
|
9
|
-
q.forensic_buffer.push({ timestamp: utcNow(), type: inputType, data });
|
|
10
|
-
q.inputs_captured++;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export function releaseQuarantine(q: QuarantineState): { duration_ms: number; total_captures: number } {
|
|
14
|
-
q.active = false;
|
|
15
|
-
return { duration_ms: q.started_at ? Date.now() - Date.parse(q.started_at) : 0, total_captures: q.inputs_captured };
|
|
16
|
-
}
|
package/src/core/receipt.ts
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
/** V3: measurement_type field. Receipts generated for EVERY measurement. */
|
|
2
|
-
import { signStr, sigToB64 } from '../crypto/sign.js';
|
|
3
|
-
import { canonicalize } from '../utils/canonical.js';
|
|
4
|
-
import { utcNow } from '../utils/timestamp.js';
|
|
5
|
-
import { uuid } from '../utils/uuid.js';
|
|
6
|
-
import type { KeyPair, HashHex } from '../crypto/types.js';
|
|
7
|
-
import type { SignedReceipt, SubjectIdentifier, EnforcementAction } from './types.js';
|
|
8
|
-
|
|
9
|
-
export interface ReceiptInput {
|
|
10
|
-
subjectId: SubjectIdentifier;
|
|
11
|
-
artifactRef: HashHex;
|
|
12
|
-
currentHash: string;
|
|
13
|
-
sealedHash: string;
|
|
14
|
-
driftDetected: boolean;
|
|
15
|
-
driftDescription: string | null;
|
|
16
|
-
action: EnforcementAction | null;
|
|
17
|
-
measurementType: string;
|
|
18
|
-
seq: number;
|
|
19
|
-
prevLeaf: HashHex | null;
|
|
20
|
-
portalKP: KeyPair;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export function generateReceipt(input: ReceiptInput): SignedReceipt {
|
|
24
|
-
const unsigned = {
|
|
25
|
-
receipt_id: uuid(), subject_identifier: input.subjectId,
|
|
26
|
-
artifact_reference: input.artifactRef, current_hash: input.currentHash,
|
|
27
|
-
sealed_hash: input.sealedHash, drift_detected: input.driftDetected,
|
|
28
|
-
drift_description: input.driftDescription, enforcement_action: input.action,
|
|
29
|
-
measurement_type: input.measurementType, timestamp: utcNow(),
|
|
30
|
-
sequence_number: input.seq, previous_leaf_hash: input.prevLeaf,
|
|
31
|
-
};
|
|
32
|
-
return { ...unsigned, portal_signature: sigToB64(signStr(canonicalize(unsigned), input.portalKP.secretKey)) };
|
|
33
|
-
}
|
package/src/core/subject.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { sha256Bytes, sha256Str } from '../crypto/hash.js';
|
|
2
|
-
import { canonicalize } from '../utils/canonical.js';
|
|
3
|
-
import type { SubjectIdentifier, SubjectMetadata } from './types.js';
|
|
4
|
-
|
|
5
|
-
export function computeSubjectId(bytes: Uint8Array, meta: SubjectMetadata): SubjectIdentifier {
|
|
6
|
-
return { bytes_hash: sha256Bytes(bytes), metadata_hash: sha256Str(canonicalize(meta)) };
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export function computeSubjectIdFromString(content: string, meta: SubjectMetadata): SubjectIdentifier {
|
|
10
|
-
return computeSubjectId(new TextEncoder().encode(content), meta);
|
|
11
|
-
}
|
package/src/core/types.ts
DELETED
|
@@ -1,285 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* V3: Aligned with NIST-2025-0035 and NCCoE AI Agent Identity filings.
|
|
3
|
-
*/
|
|
4
|
-
import type { HashHex, SignatureBase64, SaltHex, MerkleInclusionProof } from '../crypto/types.js';
|
|
5
|
-
|
|
6
|
-
// ── Subject (100, 102, 104, 106, 126) ──────────────────────────
|
|
7
|
-
|
|
8
|
-
export interface SubjectIdentifier { // Ref 126
|
|
9
|
-
bytes_hash: HashHex; // Ref 104
|
|
10
|
-
metadata_hash: HashHex; // Ref 106
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export interface SubjectMetadata {
|
|
14
|
-
filename?: string;
|
|
15
|
-
creation_timestamp?: string;
|
|
16
|
-
author?: string;
|
|
17
|
-
version?: string;
|
|
18
|
-
content_type?: string;
|
|
19
|
-
[key: string]: unknown;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
// ── Enforcement (130–136, 162–168) ──────────────────────────────
|
|
23
|
-
|
|
24
|
-
export type EnforcementAction =
|
|
25
|
-
| 'TERMINATE' // Ref 162: immediate kill
|
|
26
|
-
| 'QUARANTINE' // Ref 164: phantom execution
|
|
27
|
-
| 'NETWORK_ISOLATE' // Ref 166: sever network, continue local
|
|
28
|
-
| 'SAFE_STATE' // Ref 168: return-to-home / controlled shutdown
|
|
29
|
-
| 'KEY_REVOKE' // invalidate crypto keys
|
|
30
|
-
| 'TOKEN_INVALIDATE' // revoke access tokens
|
|
31
|
-
| 'ACTUATOR_DISCONNECT' // sever physical actuator connections
|
|
32
|
-
| 'ALERT_ONLY'; // log without enforcement (gradual deployment)
|
|
33
|
-
|
|
34
|
-
export type MeasurementType =
|
|
35
|
-
| 'EXECUTABLE_IMAGE' | 'LOADED_MODULES' | 'CONTAINER_IMAGE'
|
|
36
|
-
| 'CONFIG_MANIFEST' | 'SBOM' | 'TEE_QUOTE'
|
|
37
|
-
| 'MEMORY_REGIONS' | 'CONTROL_FLOW' | 'FILE_SYSTEM_STATE'
|
|
38
|
-
| 'NETWORK_CONFIG';
|
|
39
|
-
|
|
40
|
-
export interface EnforcementParams { // Ref 130
|
|
41
|
-
measurement_cadence_ms: number; // Ref 132
|
|
42
|
-
ttl_seconds: number; // Ref 134
|
|
43
|
-
enforcement_triggers: EnforcementAction[]; // Ref 136
|
|
44
|
-
re_attestation_required: boolean;
|
|
45
|
-
measurement_types: MeasurementType[];
|
|
46
|
-
behavioral_baseline?: BehavioralBaselineRef; // NCCoE §6: optional behavioral baseline reference
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/** Inline behavioral baseline reference for EnforcementParams (NCCoE §6, CAISI §1a) */
|
|
50
|
-
export interface BehavioralBaselineRef {
|
|
51
|
-
permitted_tools: string[];
|
|
52
|
-
forbidden_sequences: string[][];
|
|
53
|
-
rate_limits: Record<string, number>;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// ── Policy & Disclosure (112, 138–142) ──────────────────────────
|
|
57
|
-
|
|
58
|
-
export type Sensitivity = 'S1_LOW' | 'S2_MODERATE' | 'S3_HIGH' | 'S4_CRITICAL';
|
|
59
|
-
export type DisclosureMode = 'PROOF_ONLY' | 'REVEAL_MIN' | 'REVEAL_FULL';
|
|
60
|
-
|
|
61
|
-
export interface ClaimRecord { // Ref 140
|
|
62
|
-
claim_id: string;
|
|
63
|
-
sensitivity: Sensitivity;
|
|
64
|
-
substitutes: string[];
|
|
65
|
-
inference_risks: string[];
|
|
66
|
-
permitted_modes: DisclosureMode[];
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
export interface SubstitutionRule { // Ref 142
|
|
70
|
-
original_claim_id: string;
|
|
71
|
-
substitute_claim_id: string;
|
|
72
|
-
conditions: Record<string, unknown>;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
export interface DisclosurePolicy { // Ref 138
|
|
76
|
-
claims_taxonomy: ClaimRecord[];
|
|
77
|
-
substitution_rules: SubstitutionRule[];
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// ── Evidence Commitment (114) ───────────────────────────────────
|
|
81
|
-
|
|
82
|
-
export interface EvidenceCommitmentRecord {
|
|
83
|
-
commitment: HashHex;
|
|
84
|
-
salt: SaltHex;
|
|
85
|
-
label: string;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// ── Policy Artifact (120, 122, 124, 144) ────────────────────────
|
|
89
|
-
|
|
90
|
-
export interface PolicyArtifact { // Ref 122 (Weave Piece)
|
|
91
|
-
schema_version: string;
|
|
92
|
-
protocol_version: string;
|
|
93
|
-
subject_identifier: SubjectIdentifier;
|
|
94
|
-
policy_reference: HashHex; // Ref 128
|
|
95
|
-
policy_version: number;
|
|
96
|
-
sealed_hash: HashHex; // Ref 124
|
|
97
|
-
seal_salt: SaltHex; // stored for audit
|
|
98
|
-
issued_timestamp: string;
|
|
99
|
-
effective_timestamp: string;
|
|
100
|
-
expiration_timestamp: string | null;
|
|
101
|
-
issuer_identifier: string;
|
|
102
|
-
enforcement_parameters: EnforcementParams;
|
|
103
|
-
disclosure_policy: DisclosurePolicy;
|
|
104
|
-
evidence_commitments: EvidenceCommitmentRecord[];
|
|
105
|
-
signature: SignatureBase64; // Ref 144
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
// ── Receipts (170, 172) ─────────────────────────────────────────
|
|
109
|
-
// V3: Generated for EVERY measurement, not just drift. Per NIST filing:
|
|
110
|
-
// "each measurement generates a signed receipt - match or mismatch"
|
|
111
|
-
|
|
112
|
-
export interface SignedReceipt { // Ref 172
|
|
113
|
-
receipt_id: string;
|
|
114
|
-
subject_identifier: SubjectIdentifier;
|
|
115
|
-
artifact_reference: HashHex;
|
|
116
|
-
current_hash: string;
|
|
117
|
-
sealed_hash: string;
|
|
118
|
-
drift_detected: boolean;
|
|
119
|
-
drift_description: string | null;
|
|
120
|
-
enforcement_action: EnforcementAction | null;
|
|
121
|
-
measurement_type: string; // V3: which measurement was performed
|
|
122
|
-
timestamp: string;
|
|
123
|
-
sequence_number: number;
|
|
124
|
-
previous_leaf_hash: HashHex | null;
|
|
125
|
-
portal_signature: SignatureBase64;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
// ── Continuity Chain (180–196) ──────────────────────────────────
|
|
129
|
-
|
|
130
|
-
export type EventType =
|
|
131
|
-
| 'GENESIS'
|
|
132
|
-
| 'POLICY_ISSUANCE'
|
|
133
|
-
| 'INTERACTION_RECEIPT'
|
|
134
|
-
| 'REVOCATION' // V3: mid-session revocation
|
|
135
|
-
| 'ATTESTATION'
|
|
136
|
-
| 'ANCHOR_BATCH'
|
|
137
|
-
| 'DISCLOSURE'
|
|
138
|
-
| 'SUBSTITUTION'
|
|
139
|
-
| 'KEY_ROTATION' // V3: key lifecycle event
|
|
140
|
-
| 'BEHAVIORAL_DRIFT' // NCCoE §6: behavioral pattern deviation
|
|
141
|
-
| 'DELEGATION' // NCCoE §4: sub-agent delegation
|
|
142
|
-
| 'DEGRADATION' // CAISI §4a: graceful degradation event
|
|
143
|
-
| 'RE_ATTESTATION'; // TTL re-attestation
|
|
144
|
-
|
|
145
|
-
export interface GenesisPayload {
|
|
146
|
-
protocol_version: string;
|
|
147
|
-
taxonomy_version: string;
|
|
148
|
-
root_fingerprint: string;
|
|
149
|
-
specification_hash: HashHex;
|
|
150
|
-
marker: 'GENESIS';
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
export interface ContinuityEvent { // Ref 184
|
|
154
|
-
schema_version: string;
|
|
155
|
-
protocol_version: string;
|
|
156
|
-
event_type: EventType;
|
|
157
|
-
event_id: string;
|
|
158
|
-
sequence_number: number;
|
|
159
|
-
timestamp: string;
|
|
160
|
-
previous_leaf_hash: HashHex | null;
|
|
161
|
-
leaf_hash: HashHex; // Ref 186
|
|
162
|
-
payload: unknown; // Ref 192
|
|
163
|
-
payload_hash: HashHex; // Ref 194
|
|
164
|
-
event_signature: SignatureBase64; // Ref 196
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
export interface StructuralMetadata { // Ref 190
|
|
168
|
-
schema_version: string;
|
|
169
|
-
protocol_version: string;
|
|
170
|
-
event_type: EventType;
|
|
171
|
-
event_id: string;
|
|
172
|
-
sequence_number: number;
|
|
173
|
-
timestamp: string;
|
|
174
|
-
previous_leaf_hash: HashHex | null;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
// ── Checkpoints (200–214) ───────────────────────────────────────
|
|
178
|
-
|
|
179
|
-
export interface CheckpointReference {
|
|
180
|
-
merkle_root: HashHex;
|
|
181
|
-
batch_start_sequence: number;
|
|
182
|
-
batch_end_sequence: number;
|
|
183
|
-
anchor_network: string;
|
|
184
|
-
transaction_id: string;
|
|
185
|
-
timestamp: string;
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
export interface AnchorBatchPayload {
|
|
189
|
-
checkpoint_reference: CheckpointReference;
|
|
190
|
-
leaf_count: number;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
// ── Evidence Bundle (240–246) ───────────────────────────────────
|
|
194
|
-
|
|
195
|
-
export interface EvidenceBundle {
|
|
196
|
-
artifact: PolicyArtifact;
|
|
197
|
-
receipts: SignedReceipt[];
|
|
198
|
-
merkle_proofs: MerkleInclusionProof[];
|
|
199
|
-
checkpoint_reference: CheckpointReference;
|
|
200
|
-
public_key: string;
|
|
201
|
-
bundle_signature: SignatureBase64;
|
|
202
|
-
verification_tier?: VerificationTier; // CAISI §3b: Bronze/Silver/Gold tiering
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
// ── Disclosure (250–256) ────────────────────────────────────────
|
|
206
|
-
|
|
207
|
-
export interface DisclosureRequest {
|
|
208
|
-
requested_claim_id: string;
|
|
209
|
-
requester_id: string;
|
|
210
|
-
mode: DisclosureMode;
|
|
211
|
-
timestamp: string;
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
export interface SubstitutionReceipt {
|
|
215
|
-
receipt_id: string;
|
|
216
|
-
original_claim_id: string;
|
|
217
|
-
substitute_claim_id: string | null;
|
|
218
|
-
policy_version: number;
|
|
219
|
-
reason_code: string;
|
|
220
|
-
timestamp: string;
|
|
221
|
-
chain_sequence_ref: number;
|
|
222
|
-
signature: SignatureBase64;
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
// ── Portal State Machine (150, 270–280) ─────────────────────────
|
|
226
|
-
|
|
227
|
-
export type PortalState =
|
|
228
|
-
| 'INITIALIZATION' // Ref 270
|
|
229
|
-
| 'ARTIFACT_VERIFICATION' // Ref 272
|
|
230
|
-
| 'ACTIVE_MONITORING' // Ref 274
|
|
231
|
-
| 'DRIFT_DETECTED' // Ref 276
|
|
232
|
-
| 'PHANTOM_QUARANTINE' // Ref 278
|
|
233
|
-
| 'SAFE_STATE' // Graceful degradation (TTL expiry)
|
|
234
|
-
| 'TERMINATED'; // Ref 280
|
|
235
|
-
|
|
236
|
-
export type VerificationTier = 'BRONZE' | 'SILVER' | 'GOLD';
|
|
237
|
-
|
|
238
|
-
// ── Revocation (V3) ────────────────────────────────────────────
|
|
239
|
-
// Per NCCoE filing Phase 3b: "An administrator pushes a REVOCATION event
|
|
240
|
-
// to the continuity chain, invalidating the agent's active policy artifact."
|
|
241
|
-
|
|
242
|
-
export interface RevocationRecord {
|
|
243
|
-
artifact_sealed_hash: HashHex;
|
|
244
|
-
reason: string;
|
|
245
|
-
revoked_by: string; // issuer pk hex
|
|
246
|
-
timestamp: string;
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
// ── Quarantine (220–230) ────────────────────────────────────────
|
|
250
|
-
|
|
251
|
-
export interface QuarantineState {
|
|
252
|
-
active: boolean;
|
|
253
|
-
started_at: string | null;
|
|
254
|
-
inputs_captured: number;
|
|
255
|
-
outputs_severed: boolean;
|
|
256
|
-
forensic_buffer: Array<{ timestamp: string; type: string; data: unknown }>;
|
|
257
|
-
forensic_receipts?: string[]; // Receipt IDs from forensic capture
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
// ── Delegation (NCCoE §4) ──────────────────────────────────────
|
|
261
|
-
|
|
262
|
-
export interface DelegationRecord {
|
|
263
|
-
sub_agent_id: string;
|
|
264
|
-
parent_artifact_reference: HashHex;
|
|
265
|
-
child_artifact: PolicyArtifact;
|
|
266
|
-
permitted_tools: string[];
|
|
267
|
-
ttl_seconds: number;
|
|
268
|
-
delegation_timestamp: string;
|
|
269
|
-
chain_sequence: number;
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
// ── Key Lifecycle ──────────────────────────────────────────────
|
|
273
|
-
|
|
274
|
-
export interface KeyRotationRecord {
|
|
275
|
-
keypair_type: string; // e.g. 'issuer', 'portal', 'chain'
|
|
276
|
-
old_public_key: string;
|
|
277
|
-
new_public_key: string;
|
|
278
|
-
reason: string;
|
|
279
|
-
rotation_timestamp: string;
|
|
280
|
-
chain_sequence: number;
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
// ── Sensitivity Level Aliases ────────────────────────────────────
|
|
284
|
-
// Existing Sensitivity type uses S1_LOW etc. These aliases map to the short forms.
|
|
285
|
-
export type SensitivityLevel = 'S1' | 'S2' | 'S3' | 'S4';
|
package/src/crypto/hash.ts
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { sha256 } from '@noble/hashes/sha256';
|
|
2
|
-
import { blake2b } from '@noble/hashes/blake2b';
|
|
3
|
-
import { bytesToHex } from '@noble/hashes/utils';
|
|
4
|
-
import type { HashHex } from './types.js';
|
|
5
|
-
|
|
6
|
-
const enc = new TextEncoder();
|
|
7
|
-
|
|
8
|
-
export function sha256Bytes(data: Uint8Array): HashHex {
|
|
9
|
-
return bytesToHex(sha256(data));
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export function sha256Str(data: string): HashHex {
|
|
13
|
-
return sha256Bytes(enc.encode(data));
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export function blake2b256(data: Uint8Array): HashHex {
|
|
17
|
-
return bytesToHex(blake2b(data, { dkLen: 32 }));
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/** Concatenate inputs (NO delimiter) and SHA-256. No delimiters per protocol spec. */
|
|
21
|
-
export function sha256Cat(...parts: (Uint8Array | string)[]): HashHex {
|
|
22
|
-
const bufs = parts.map(p => typeof p === 'string' ? enc.encode(p) : p);
|
|
23
|
-
const total = bufs.reduce((n, b) => n + b.length, 0);
|
|
24
|
-
const combined = new Uint8Array(total);
|
|
25
|
-
let off = 0;
|
|
26
|
-
for (const b of bufs) { combined.set(b, off); off += b.length; }
|
|
27
|
-
return sha256Bytes(combined);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/** Concatenate hex strings as text (no decode) and hash. For sealed_hash computation. */
|
|
31
|
-
export function sha256HexCat(...hexes: string[]): HashHex {
|
|
32
|
-
return sha256Str(hexes.join(''));
|
|
33
|
-
}
|
package/src/crypto/index.ts
DELETED
package/src/crypto/merkle.ts
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import { sha256Str } from './hash.js';
|
|
2
|
-
import type { HashHex, MerkleInclusionProof } from './types.js';
|
|
3
|
-
|
|
4
|
-
function pair(l: HashHex, r: HashHex): HashHex { return sha256Str(l + r); }
|
|
5
|
-
|
|
6
|
-
export function buildMerkleTree(leaves: HashHex[]): { root: HashHex; layers: HashHex[][] } {
|
|
7
|
-
if (!leaves.length) throw new Error('Empty leaf set');
|
|
8
|
-
if (leaves.length === 1) return { root: leaves[0], layers: [leaves] };
|
|
9
|
-
const layers: HashHex[][] = [[...leaves]];
|
|
10
|
-
let cur = leaves;
|
|
11
|
-
while (cur.length > 1) {
|
|
12
|
-
const next: HashHex[] = [];
|
|
13
|
-
for (let i = 0; i < cur.length; i += 2) {
|
|
14
|
-
next.push(pair(cur[i], i + 1 < cur.length ? cur[i + 1] : cur[i]));
|
|
15
|
-
}
|
|
16
|
-
layers.push(next);
|
|
17
|
-
cur = next;
|
|
18
|
-
}
|
|
19
|
-
return { root: cur[0], layers };
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export function inclusionProof(leaves: HashHex[], idx: number): MerkleInclusionProof {
|
|
23
|
-
if (idx < 0 || idx >= leaves.length) throw new RangeError(`Index ${idx} out of [0,${leaves.length})`);
|
|
24
|
-
const { root, layers } = buildMerkleTree(leaves);
|
|
25
|
-
const siblings: MerkleInclusionProof['siblings'] = [];
|
|
26
|
-
let ci = idx;
|
|
27
|
-
for (let L = 0; L < layers.length - 1; L++) {
|
|
28
|
-
const layer = layers[L];
|
|
29
|
-
const isRight = ci % 2 === 1;
|
|
30
|
-
const si = isRight ? ci - 1 : (ci + 1 < layer.length ? ci + 1 : ci);
|
|
31
|
-
siblings.push({ hash: layer[si], position: isRight ? 'left' : 'right' });
|
|
32
|
-
ci = Math.floor(ci / 2);
|
|
33
|
-
}
|
|
34
|
-
return { leafHash: leaves[idx], leafIndex: idx, siblings, root };
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export function verifyProof(proof: MerkleInclusionProof): boolean {
|
|
38
|
-
let h = proof.leafHash;
|
|
39
|
-
for (const s of proof.siblings) {
|
|
40
|
-
h = s.position === 'left' ? pair(s.hash, h) : pair(h, s.hash);
|
|
41
|
-
}
|
|
42
|
-
return h === proof.root;
|
|
43
|
-
}
|
package/src/crypto/salt.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { randomBytes } from 'node:crypto';
|
|
2
|
-
import { bytesToHex } from '@noble/hashes/utils';
|
|
3
|
-
import { sha256Cat } from './hash.js';
|
|
4
|
-
import type { SaltHex, SaltedCommitment, HashHex } from './types.js';
|
|
5
|
-
|
|
6
|
-
const enc = new TextEncoder();
|
|
7
|
-
|
|
8
|
-
export function generateSalt(): SaltHex { return bytesToHex(randomBytes(16)); }
|
|
9
|
-
|
|
10
|
-
export function saltedCommitment(content: Uint8Array | string, salt?: SaltHex): SaltedCommitment {
|
|
11
|
-
const s = salt ?? generateSalt();
|
|
12
|
-
const c = typeof content === 'string' ? enc.encode(content) : content;
|
|
13
|
-
return { commitment: sha256Cat(c, s), salt: s };
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export function verifySaltedCommitment(content: Uint8Array | string, salt: SaltHex, expected: HashHex): boolean {
|
|
17
|
-
return saltedCommitment(content, salt).commitment === expected;
|
|
18
|
-
}
|