@vinkius-core/mcp-fusion 2.7.0 → 2.8.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/dist/cli/fusion.d.ts +101 -0
- package/dist/cli/fusion.d.ts.map +1 -0
- package/dist/cli/fusion.js +333 -0
- package/dist/cli/fusion.js.map +1 -0
- package/dist/index.d.ts +41 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -1
- package/dist/introspection/BehaviorDigest.d.ts +112 -0
- package/dist/introspection/BehaviorDigest.d.ts.map +1 -0
- package/dist/introspection/BehaviorDigest.js +146 -0
- package/dist/introspection/BehaviorDigest.js.map +1 -0
- package/dist/introspection/CapabilityLockfile.d.ts +259 -0
- package/dist/introspection/CapabilityLockfile.d.ts.map +1 -0
- package/dist/introspection/CapabilityLockfile.js +391 -0
- package/dist/introspection/CapabilityLockfile.js.map +1 -0
- package/dist/introspection/ContractAwareSelfHealing.d.ts +90 -0
- package/dist/introspection/ContractAwareSelfHealing.d.ts.map +1 -0
- package/dist/introspection/ContractAwareSelfHealing.js +132 -0
- package/dist/introspection/ContractAwareSelfHealing.js.map +1 -0
- package/dist/introspection/ContractDiff.d.ts +91 -0
- package/dist/introspection/ContractDiff.d.ts.map +1 -0
- package/dist/introspection/ContractDiff.js +466 -0
- package/dist/introspection/ContractDiff.js.map +1 -0
- package/dist/introspection/CryptoAttestation.d.ts +143 -0
- package/dist/introspection/CryptoAttestation.d.ts.map +1 -0
- package/dist/introspection/CryptoAttestation.js +194 -0
- package/dist/introspection/CryptoAttestation.js.map +1 -0
- package/dist/introspection/EntitlementScanner.d.ts +124 -0
- package/dist/introspection/EntitlementScanner.d.ts.map +1 -0
- package/dist/introspection/EntitlementScanner.js +244 -0
- package/dist/introspection/EntitlementScanner.js.map +1 -0
- package/dist/introspection/GovernanceObserver.d.ts +88 -0
- package/dist/introspection/GovernanceObserver.d.ts.map +1 -0
- package/dist/introspection/GovernanceObserver.js +132 -0
- package/dist/introspection/GovernanceObserver.js.map +1 -0
- package/dist/introspection/SemanticProbe.d.ts +207 -0
- package/dist/introspection/SemanticProbe.d.ts.map +1 -0
- package/dist/introspection/SemanticProbe.js +255 -0
- package/dist/introspection/SemanticProbe.js.map +1 -0
- package/dist/introspection/TokenEconomics.d.ts +210 -0
- package/dist/introspection/TokenEconomics.d.ts.map +1 -0
- package/dist/introspection/TokenEconomics.js +286 -0
- package/dist/introspection/TokenEconomics.js.map +1 -0
- package/dist/introspection/ToolContract.d.ts +159 -0
- package/dist/introspection/ToolContract.d.ts.map +1 -0
- package/dist/introspection/ToolContract.js +191 -0
- package/dist/introspection/ToolContract.js.map +1 -0
- package/dist/introspection/canonicalize.d.ts +20 -0
- package/dist/introspection/canonicalize.d.ts.map +1 -0
- package/dist/introspection/canonicalize.js +51 -0
- package/dist/introspection/canonicalize.js.map +1 -0
- package/dist/introspection/index.d.ts +20 -0
- package/dist/introspection/index.d.ts.map +1 -1
- package/dist/introspection/index.js +20 -0
- package/dist/introspection/index.js.map +1 -1
- package/dist/observability/DebugObserver.d.ts +26 -1
- package/dist/observability/DebugObserver.d.ts.map +1 -1
- package/dist/observability/DebugObserver.js +8 -1
- package/dist/observability/DebugObserver.js.map +1 -1
- package/dist/observability/index.d.ts +1 -1
- package/dist/observability/index.d.ts.map +1 -1
- package/dist/observability/index.js.map +1 -1
- package/dist/server/ServerAttachment.d.ts +41 -0
- package/dist/server/ServerAttachment.d.ts.map +1 -1
- package/dist/server/ServerAttachment.js +25 -1
- package/dist/server/ServerAttachment.js.map +1 -1
- package/package.json +8 -1
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import type { ServerDigest } from './BehaviorDigest.js';
|
|
2
|
+
/**
|
|
3
|
+
* Configuration for zero-trust attestation.
|
|
4
|
+
*
|
|
5
|
+
* Passed to `AttachOptions.zeroTrust` in ServerAttachment.
|
|
6
|
+
*/
|
|
7
|
+
export interface ZeroTrustConfig {
|
|
8
|
+
/**
|
|
9
|
+
* The signing strategy to use.
|
|
10
|
+
* - `'hmac'` — HMAC-SHA256 with a shared secret (built-in)
|
|
11
|
+
* - A custom `AttestationSigner` for external KMS integration
|
|
12
|
+
*/
|
|
13
|
+
readonly signer: 'hmac' | AttestationSigner;
|
|
14
|
+
/**
|
|
15
|
+
* For `'hmac'` mode: the shared secret.
|
|
16
|
+
* Read from environment in production (never hardcode).
|
|
17
|
+
*/
|
|
18
|
+
readonly secret?: string;
|
|
19
|
+
/**
|
|
20
|
+
* Expected server digest hash from a known-good build.
|
|
21
|
+
* When set, runtime verification will fail-fast if the
|
|
22
|
+
* re-computed digest doesn't match.
|
|
23
|
+
*/
|
|
24
|
+
readonly expectedDigest?: string;
|
|
25
|
+
/**
|
|
26
|
+
* Whether to fail-fast on attestation failure.
|
|
27
|
+
* Default: `true` in production, `false` in development.
|
|
28
|
+
*/
|
|
29
|
+
readonly failOnMismatch?: boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Whether to expose the attestation in MCP capabilities.
|
|
32
|
+
* Default: `true`.
|
|
33
|
+
*/
|
|
34
|
+
readonly exposeCapability?: boolean;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Pluggable signer interface for external KMS integration.
|
|
38
|
+
*
|
|
39
|
+
* Implementations should be stateless and async-safe.
|
|
40
|
+
* The `sign()` method receives the canonical digest string
|
|
41
|
+
* and returns a signature (hex-encoded or base64).
|
|
42
|
+
*/
|
|
43
|
+
export interface AttestationSigner {
|
|
44
|
+
/** Human-readable name (e.g., 'sigstore', 'aws-kms') */
|
|
45
|
+
readonly name: string;
|
|
46
|
+
/** Sign a digest string */
|
|
47
|
+
sign(digest: string): Promise<string>;
|
|
48
|
+
/** Verify a digest against a signature */
|
|
49
|
+
verify(digest: string, signature: string): Promise<boolean>;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Result of an attestation operation.
|
|
53
|
+
*/
|
|
54
|
+
export interface AttestationResult {
|
|
55
|
+
/** Whether the attestation was successful */
|
|
56
|
+
readonly valid: boolean;
|
|
57
|
+
/** The computed digest */
|
|
58
|
+
readonly computedDigest: string;
|
|
59
|
+
/** The expected digest (if configured) */
|
|
60
|
+
readonly expectedDigest: string | null;
|
|
61
|
+
/** The signature (if signing was performed) */
|
|
62
|
+
readonly signature: string | null;
|
|
63
|
+
/** Signer identity */
|
|
64
|
+
readonly signerName: string;
|
|
65
|
+
/** ISO-8601 timestamp of attestation */
|
|
66
|
+
readonly attestedAt: string;
|
|
67
|
+
/** Human-readable error message, if invalid */
|
|
68
|
+
readonly error: string | null;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Capability structure exposed via MCP `server.capabilities`.
|
|
72
|
+
*
|
|
73
|
+
* Clients can inspect this to verify the server's behavioral
|
|
74
|
+
* identity before trusting tool responses.
|
|
75
|
+
*/
|
|
76
|
+
export interface FusionTrustCapability {
|
|
77
|
+
/** Current server behavioral digest */
|
|
78
|
+
readonly serverDigest: string;
|
|
79
|
+
/** Attestation signature (if signed) */
|
|
80
|
+
readonly signature: string | null;
|
|
81
|
+
/** Signer identity */
|
|
82
|
+
readonly signerName: string;
|
|
83
|
+
/** ISO-8601 timestamp of last attestation */
|
|
84
|
+
readonly attestedAt: string;
|
|
85
|
+
/** Number of tools covered by the attestation */
|
|
86
|
+
readonly toolCount: number;
|
|
87
|
+
/** Whether the attestation passed verification */
|
|
88
|
+
readonly verified: boolean;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Create an HMAC-SHA256 signer from a shared secret.
|
|
92
|
+
*
|
|
93
|
+
* @param secret - The shared secret (should be ≥32 bytes)
|
|
94
|
+
* @returns An `AttestationSigner` using HMAC-SHA256
|
|
95
|
+
*/
|
|
96
|
+
export declare function createHmacSigner(secret: string): AttestationSigner;
|
|
97
|
+
/**
|
|
98
|
+
* Sign a server digest and produce an attestation result.
|
|
99
|
+
*
|
|
100
|
+
* @param serverDigest - The server's behavioral digest
|
|
101
|
+
* @param config - Zero-trust configuration
|
|
102
|
+
* @returns Attestation result with signature
|
|
103
|
+
*/
|
|
104
|
+
export declare function attestServerDigest(serverDigest: ServerDigest, config: ZeroTrustConfig): Promise<AttestationResult>;
|
|
105
|
+
/**
|
|
106
|
+
* Verify a previously signed attestation.
|
|
107
|
+
*
|
|
108
|
+
* @param serverDigest - The current server digest
|
|
109
|
+
* @param signature - The signature to verify
|
|
110
|
+
* @param config - Zero-trust configuration
|
|
111
|
+
* @returns Attestation result with verification status
|
|
112
|
+
*/
|
|
113
|
+
export declare function verifyAttestation(serverDigest: ServerDigest, signature: string, config: ZeroTrustConfig): Promise<AttestationResult>;
|
|
114
|
+
/**
|
|
115
|
+
* Runtime capability pinning — check that the current digest
|
|
116
|
+
* matches what was attested at build time.
|
|
117
|
+
*
|
|
118
|
+
* Designed to be called once at server startup in the `attach()` flow.
|
|
119
|
+
*
|
|
120
|
+
* @param currentDigest - Re-computed server digest
|
|
121
|
+
* @param config - Zero-trust configuration
|
|
122
|
+
* @returns Attestation result
|
|
123
|
+
* @throws If `failOnMismatch` is true and the digest doesn't match
|
|
124
|
+
*/
|
|
125
|
+
export declare function verifyCapabilityPin(currentDigest: ServerDigest, config: ZeroTrustConfig): Promise<AttestationResult>;
|
|
126
|
+
/**
|
|
127
|
+
* Build the `fusionTrust` capability object for MCP exposure.
|
|
128
|
+
*
|
|
129
|
+
* @param attestation - A completed attestation result
|
|
130
|
+
* @param toolCount - Number of tools in the registry
|
|
131
|
+
* @returns Capability structure for `server.capabilities`
|
|
132
|
+
*/
|
|
133
|
+
export declare function buildTrustCapability(attestation: AttestationResult, toolCount: number): FusionTrustCapability;
|
|
134
|
+
/**
|
|
135
|
+
* Error thrown when zero-trust attestation fails with failOnMismatch.
|
|
136
|
+
*
|
|
137
|
+
* Carries the full `AttestationResult` for programmatic inspection.
|
|
138
|
+
*/
|
|
139
|
+
export declare class AttestationError extends Error {
|
|
140
|
+
readonly attestation: AttestationResult;
|
|
141
|
+
constructor(message: string, attestation: AttestationResult);
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=CryptoAttestation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CryptoAttestation.d.ts","sourceRoot":"","sources":["../../src/introspection/CryptoAttestation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CryptoAttestation — Zero-Trust Runtime Verification
|
|
3
|
+
*
|
|
4
|
+
* **Evolution 1: Zero-Trust Runtime**
|
|
5
|
+
*
|
|
6
|
+
* Provides cryptographic attestation and capability pinning
|
|
7
|
+
* for MCP Fusion tool contracts. This module enables:
|
|
8
|
+
*
|
|
9
|
+
* 1. **Digital Signing**: Sign a `ToolContract` or `ServerDigest`
|
|
10
|
+
* using HMAC-SHA256 (built-in) or pluggable external signers
|
|
11
|
+
* (Sigstore, AWS KMS, Azure Key Vault).
|
|
12
|
+
*
|
|
13
|
+
* 2. **Runtime Verification**: At server startup, re-compute the
|
|
14
|
+
* behavioral digest and compare it against the expected
|
|
15
|
+
* (signed) digest. If they differ, fail fast with a clear
|
|
16
|
+
* attestation error.
|
|
17
|
+
*
|
|
18
|
+
* 3. **Capability Pinning**: Expose a `fusionTrust` capability
|
|
19
|
+
* in the MCP `server.capabilities` that clients can inspect
|
|
20
|
+
* to verify the server's behavioral identity.
|
|
21
|
+
*
|
|
22
|
+
* **Zero-overhead principle**: When attestation is not configured,
|
|
23
|
+
* no cryptographic operations execute — the attach flow is
|
|
24
|
+
* identical to the default path.
|
|
25
|
+
*
|
|
26
|
+
* @module
|
|
27
|
+
*/
|
|
28
|
+
import { createHmac, timingSafeEqual } from 'node:crypto';
|
|
29
|
+
// ============================================================================
|
|
30
|
+
// HMAC Signer (Built-in)
|
|
31
|
+
// ============================================================================
|
|
32
|
+
/**
|
|
33
|
+
* Create an HMAC-SHA256 signer from a shared secret.
|
|
34
|
+
*
|
|
35
|
+
* @param secret - The shared secret (should be ≥32 bytes)
|
|
36
|
+
* @returns An `AttestationSigner` using HMAC-SHA256
|
|
37
|
+
*/
|
|
38
|
+
export function createHmacSigner(secret) {
|
|
39
|
+
return {
|
|
40
|
+
name: 'hmac-sha256',
|
|
41
|
+
async sign(digest) {
|
|
42
|
+
return hmacSign(digest, secret);
|
|
43
|
+
},
|
|
44
|
+
async verify(digest, signature) {
|
|
45
|
+
const expected = hmacSign(digest, secret);
|
|
46
|
+
return timingSafeCompare(expected, signature);
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
// ============================================================================
|
|
51
|
+
// Attestation Operations
|
|
52
|
+
// ============================================================================
|
|
53
|
+
/**
|
|
54
|
+
* Sign a server digest and produce an attestation result.
|
|
55
|
+
*
|
|
56
|
+
* @param serverDigest - The server's behavioral digest
|
|
57
|
+
* @param config - Zero-trust configuration
|
|
58
|
+
* @returns Attestation result with signature
|
|
59
|
+
*/
|
|
60
|
+
export async function attestServerDigest(serverDigest, config) {
|
|
61
|
+
const signer = resolveSigner(config);
|
|
62
|
+
const signature = await signer.sign(serverDigest.digest);
|
|
63
|
+
const attestedAt = new Date().toISOString();
|
|
64
|
+
// Verify against expected digest if configured
|
|
65
|
+
if (config.expectedDigest) {
|
|
66
|
+
const matches = serverDigest.digest === config.expectedDigest;
|
|
67
|
+
return {
|
|
68
|
+
valid: matches,
|
|
69
|
+
computedDigest: serverDigest.digest,
|
|
70
|
+
expectedDigest: config.expectedDigest,
|
|
71
|
+
signature,
|
|
72
|
+
signerName: signer.name,
|
|
73
|
+
attestedAt,
|
|
74
|
+
error: matches ? null : `Attestation failed: computed digest ${serverDigest.digest} does not match expected ${config.expectedDigest}`,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
return {
|
|
78
|
+
valid: true,
|
|
79
|
+
computedDigest: serverDigest.digest,
|
|
80
|
+
expectedDigest: null,
|
|
81
|
+
signature,
|
|
82
|
+
signerName: signer.name,
|
|
83
|
+
attestedAt,
|
|
84
|
+
error: null,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Verify a previously signed attestation.
|
|
89
|
+
*
|
|
90
|
+
* @param serverDigest - The current server digest
|
|
91
|
+
* @param signature - The signature to verify
|
|
92
|
+
* @param config - Zero-trust configuration
|
|
93
|
+
* @returns Attestation result with verification status
|
|
94
|
+
*/
|
|
95
|
+
export async function verifyAttestation(serverDigest, signature, config) {
|
|
96
|
+
const signer = resolveSigner(config);
|
|
97
|
+
const verified = await signer.verify(serverDigest.digest, signature);
|
|
98
|
+
const attestedAt = new Date().toISOString();
|
|
99
|
+
return {
|
|
100
|
+
valid: verified,
|
|
101
|
+
computedDigest: serverDigest.digest,
|
|
102
|
+
expectedDigest: config.expectedDigest ?? null,
|
|
103
|
+
signature,
|
|
104
|
+
signerName: signer.name,
|
|
105
|
+
attestedAt,
|
|
106
|
+
error: verified ? null : `Signature verification failed for digest ${serverDigest.digest}`,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Runtime capability pinning — check that the current digest
|
|
111
|
+
* matches what was attested at build time.
|
|
112
|
+
*
|
|
113
|
+
* Designed to be called once at server startup in the `attach()` flow.
|
|
114
|
+
*
|
|
115
|
+
* @param currentDigest - Re-computed server digest
|
|
116
|
+
* @param config - Zero-trust configuration
|
|
117
|
+
* @returns Attestation result
|
|
118
|
+
* @throws If `failOnMismatch` is true and the digest doesn't match
|
|
119
|
+
*/
|
|
120
|
+
export async function verifyCapabilityPin(currentDigest, config) {
|
|
121
|
+
const result = await attestServerDigest(currentDigest, config);
|
|
122
|
+
if (!result.valid && (config.failOnMismatch ?? true)) {
|
|
123
|
+
throw new AttestationError(`[MCP Fusion] Zero-Trust attestation failed: ${result.error}`, result);
|
|
124
|
+
}
|
|
125
|
+
return result;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Build the `fusionTrust` capability object for MCP exposure.
|
|
129
|
+
*
|
|
130
|
+
* @param attestation - A completed attestation result
|
|
131
|
+
* @param toolCount - Number of tools in the registry
|
|
132
|
+
* @returns Capability structure for `server.capabilities`
|
|
133
|
+
*/
|
|
134
|
+
export function buildTrustCapability(attestation, toolCount) {
|
|
135
|
+
return {
|
|
136
|
+
serverDigest: attestation.computedDigest,
|
|
137
|
+
signature: attestation.signature,
|
|
138
|
+
signerName: attestation.signerName,
|
|
139
|
+
attestedAt: attestation.attestedAt,
|
|
140
|
+
toolCount,
|
|
141
|
+
verified: attestation.valid,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
// ============================================================================
|
|
145
|
+
// Attestation Error
|
|
146
|
+
// ============================================================================
|
|
147
|
+
/**
|
|
148
|
+
* Error thrown when zero-trust attestation fails with failOnMismatch.
|
|
149
|
+
*
|
|
150
|
+
* Carries the full `AttestationResult` for programmatic inspection.
|
|
151
|
+
*/
|
|
152
|
+
export class AttestationError extends Error {
|
|
153
|
+
attestation;
|
|
154
|
+
constructor(message, attestation) {
|
|
155
|
+
super(message);
|
|
156
|
+
this.name = 'AttestationError';
|
|
157
|
+
this.attestation = attestation;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
// ============================================================================
|
|
161
|
+
// Internals
|
|
162
|
+
// ============================================================================
|
|
163
|
+
/**
|
|
164
|
+
* Resolve the signer from config.
|
|
165
|
+
* @internal
|
|
166
|
+
*/
|
|
167
|
+
function resolveSigner(config) {
|
|
168
|
+
if (config.signer === 'hmac') {
|
|
169
|
+
if (!config.secret) {
|
|
170
|
+
throw new Error('[MCP Fusion] HMAC signer requires a secret. Set zeroTrust.secret or use a custom signer.');
|
|
171
|
+
}
|
|
172
|
+
return createHmacSigner(config.secret);
|
|
173
|
+
}
|
|
174
|
+
return config.signer;
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* HMAC-SHA256 sign.
|
|
178
|
+
* @internal
|
|
179
|
+
*/
|
|
180
|
+
function hmacSign(data, secret) {
|
|
181
|
+
return createHmac('sha256', secret).update(data, 'utf8').digest('hex');
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Timing-safe string comparison to prevent timing attacks.
|
|
185
|
+
* @internal
|
|
186
|
+
*/
|
|
187
|
+
function timingSafeCompare(a, b) {
|
|
188
|
+
if (a.length !== b.length)
|
|
189
|
+
return false;
|
|
190
|
+
const bufA = Buffer.from(a, 'utf8');
|
|
191
|
+
const bufB = Buffer.from(b, 'utf8');
|
|
192
|
+
return timingSafeEqual(bufA, bufB);
|
|
193
|
+
}
|
|
194
|
+
//# sourceMappingURL=CryptoAttestation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CryptoAttestation.js","sourceRoot":"","sources":["../../src/introspection/CryptoAttestation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* EntitlementScanner — AST-Based Blast Radius Analysis
|
|
3
|
+
*
|
|
4
|
+
* **Evolution 5: Blast Radius**
|
|
5
|
+
*
|
|
6
|
+
* Performs static analysis of handler source files to detect
|
|
7
|
+
* I/O capabilities (filesystem, network, subprocess, crypto)
|
|
8
|
+
* that expand the tool's blast radius beyond what its
|
|
9
|
+
* declarative contract suggests.
|
|
10
|
+
*
|
|
11
|
+
* **Key insight**: A tool declared as `readOnly: true` that
|
|
12
|
+
* imports `child_process` has a mismatch between its declared
|
|
13
|
+
* contract and its actual capabilities. This scanner detects
|
|
14
|
+
* such mismatches and reports them as entitlement violations.
|
|
15
|
+
*
|
|
16
|
+
* **Implementation approach**: Instead of a full TypeScript AST
|
|
17
|
+
* parser (which would require `typescript` as a dependency),
|
|
18
|
+
* this module uses regex-based pattern matching on source text.
|
|
19
|
+
* This is deliberately conservative — it may over-report but
|
|
20
|
+
* never under-report.
|
|
21
|
+
*
|
|
22
|
+
* **Contract integration**: The entitlement report is embedded
|
|
23
|
+
* in the `ToolContract.entitlements` field, making entitlement
|
|
24
|
+
* changes trackable via `ContractDiff`.
|
|
25
|
+
*
|
|
26
|
+
* Pure-function module: no state, no side effects.
|
|
27
|
+
*
|
|
28
|
+
* @module
|
|
29
|
+
*/
|
|
30
|
+
import type { HandlerEntitlements } from './ToolContract.js';
|
|
31
|
+
/**
|
|
32
|
+
* Complete entitlement report for a handler.
|
|
33
|
+
*/
|
|
34
|
+
export interface EntitlementReport {
|
|
35
|
+
/** Resolved entitlements */
|
|
36
|
+
readonly entitlements: HandlerEntitlements;
|
|
37
|
+
/** All detected entitlement matches */
|
|
38
|
+
readonly matches: readonly EntitlementMatch[];
|
|
39
|
+
/** Entitlement violations (declared vs detected mismatches) */
|
|
40
|
+
readonly violations: readonly EntitlementViolation[];
|
|
41
|
+
/** Whether the handler is considered safe */
|
|
42
|
+
readonly safe: boolean;
|
|
43
|
+
/** Human-readable summary */
|
|
44
|
+
readonly summary: string;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* A single entitlement match detected in source code.
|
|
48
|
+
*/
|
|
49
|
+
export interface EntitlementMatch {
|
|
50
|
+
/** Which entitlement category */
|
|
51
|
+
readonly category: EntitlementCategory;
|
|
52
|
+
/** The specific API/import detected */
|
|
53
|
+
readonly identifier: string;
|
|
54
|
+
/** Pattern that matched */
|
|
55
|
+
readonly pattern: string;
|
|
56
|
+
/** Source text (context around the match) */
|
|
57
|
+
readonly context: string;
|
|
58
|
+
/** Line number in the source (1-based) */
|
|
59
|
+
readonly line: number;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* An entitlement violation — mismatch between declaration and detection.
|
|
63
|
+
*/
|
|
64
|
+
export interface EntitlementViolation {
|
|
65
|
+
/** Which entitlement is violated */
|
|
66
|
+
readonly category: EntitlementCategory;
|
|
67
|
+
/** What was declared (e.g., readOnly: true) */
|
|
68
|
+
readonly declared: string;
|
|
69
|
+
/** What was detected */
|
|
70
|
+
readonly detected: string;
|
|
71
|
+
/** Severity */
|
|
72
|
+
readonly severity: 'warning' | 'error';
|
|
73
|
+
/** Human-readable description */
|
|
74
|
+
readonly description: string;
|
|
75
|
+
}
|
|
76
|
+
/** Entitlement categories */
|
|
77
|
+
export type EntitlementCategory = 'filesystem' | 'network' | 'subprocess' | 'crypto';
|
|
78
|
+
/**
|
|
79
|
+
* Declaration claims for validation against detected entitlements.
|
|
80
|
+
*/
|
|
81
|
+
export interface EntitlementClaims {
|
|
82
|
+
/** Whether the action is declared as readOnly */
|
|
83
|
+
readonly readOnly?: boolean;
|
|
84
|
+
/** Whether the action is declared as destructive */
|
|
85
|
+
readonly destructive?: boolean;
|
|
86
|
+
/** Explicitly allowed entitlements (bypasses violation detection) */
|
|
87
|
+
readonly allowed?: readonly EntitlementCategory[];
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Scan source text for entitlement patterns.
|
|
91
|
+
*
|
|
92
|
+
* @param source - The source code text to scan
|
|
93
|
+
* @param fileName - File name for reporting (optional)
|
|
94
|
+
* @returns All entitlement matches found
|
|
95
|
+
*/
|
|
96
|
+
export declare function scanSource(source: string, fileName?: string): readonly EntitlementMatch[];
|
|
97
|
+
/**
|
|
98
|
+
* Build `HandlerEntitlements` from detected matches.
|
|
99
|
+
*
|
|
100
|
+
* @param matches - Detected entitlement matches
|
|
101
|
+
* @returns Aggregated entitlements
|
|
102
|
+
*/
|
|
103
|
+
export declare function buildEntitlements(matches: readonly EntitlementMatch[]): HandlerEntitlements;
|
|
104
|
+
/**
|
|
105
|
+
* Validate detected entitlements against declared claims.
|
|
106
|
+
*
|
|
107
|
+
* Uses a rule table instead of imperative branching.
|
|
108
|
+
* Each rule encodes a policy check as pure data.
|
|
109
|
+
*
|
|
110
|
+
* @param matches - Detected matches
|
|
111
|
+
* @param claims - Declared claims from action metadata
|
|
112
|
+
* @returns Violations found
|
|
113
|
+
*/
|
|
114
|
+
export declare function validateClaims(matches: readonly EntitlementMatch[], claims: EntitlementClaims): readonly EntitlementViolation[];
|
|
115
|
+
/**
|
|
116
|
+
* Perform a complete entitlement scan and validation.
|
|
117
|
+
*
|
|
118
|
+
* @param source - Handler source code
|
|
119
|
+
* @param claims - Declared claims for validation
|
|
120
|
+
* @param fileName - Optional file name for reporting
|
|
121
|
+
* @returns Complete entitlement report
|
|
122
|
+
*/
|
|
123
|
+
export declare function scanAndValidate(source: string, claims?: EntitlementClaims, fileName?: string): EntitlementReport;
|
|
124
|
+
//# sourceMappingURL=EntitlementScanner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EntitlementScanner.d.ts","sourceRoot":"","sources":["../../src/introspection/EntitlementScanner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAM7D;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAC9B,4BAA4B;IAC5B,QAAQ,CAAC,YAAY,EAAE,mBAAmB,CAAC;IAC3C,uCAAuC;IACvC,QAAQ,CAAC,OAAO,EAAE,SAAS,gBAAgB,EAAE,CAAC;IAC9C,+DAA+D;IAC/D,QAAQ,CAAC,UAAU,EAAE,SAAS,oBAAoB,EAAE,CAAC;IACrD,6CAA6C;IAC7C,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,6BAA6B;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC7B,iCAAiC;IACjC,QAAQ,CAAC,QAAQ,EAAE,mBAAmB,CAAC;IACvC,uCAAuC;IACvC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,2BAA2B;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,6CAA6C;IAC7C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,0CAA0C;IAC1C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACjC,oCAAoC;IACpC,QAAQ,CAAC,QAAQ,EAAE,mBAAmB,CAAC;IACvC,+CAA+C;IAC/C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,wBAAwB;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,eAAe;IACf,QAAQ,CAAC,QAAQ,EAAE,SAAS,GAAG,OAAO,CAAC;IACvC,iCAAiC;IACjC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAChC;AAED,6BAA6B;AAC7B,MAAM,MAAM,mBAAmB,GAAG,YAAY,GAAG,SAAS,GAAG,YAAY,GAAG,QAAQ,CAAC;AAErF;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAC9B,iDAAiD;IACjD,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,oDAAoD;IACpD,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC;IAC/B,qEAAqE;IACrE,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,mBAAmB,EAAE,CAAC;CACrD;AAsED;;;;;;GAMG;AACH,wBAAgB,UAAU,CACtB,MAAM,EAAE,MAAM,EACd,QAAQ,CAAC,EAAE,MAAM,GAClB,SAAS,gBAAgB,EAAE,CAyB7B;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC7B,OAAO,EAAE,SAAS,gBAAgB,EAAE,GACrC,mBAAmB,CAWrB;AA4ED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAC1B,OAAO,EAAE,SAAS,gBAAgB,EAAE,EACpC,MAAM,EAAE,iBAAiB,GAC1B,SAAS,oBAAoB,EAAE,CAOjC;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC3B,MAAM,EAAE,MAAM,EACd,MAAM,GAAE,iBAAsB,EAC9B,QAAQ,CAAC,EAAE,MAAM,GAClB,iBAAiB,CAgBnB"}
|