protect-mcp 0.1.1 → 0.2.1

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/index.d.ts CHANGED
@@ -1,5 +1,11 @@
1
1
  interface ProtectPolicy {
2
2
  tools: Record<string, ToolPolicy>;
3
+ /** Default trust tier for unidentified agents (default: "unknown") */
4
+ default_tier?: TrustTier;
5
+ /** Policy engine mode */
6
+ policy_engine?: PolicyEngineMode;
7
+ /** External PDP endpoint (when policy_engine is "external" or "hybrid") */
8
+ external?: ExternalPDPConfig;
3
9
  }
4
10
  interface ToolPolicy {
5
11
  /**
@@ -15,6 +21,71 @@ interface ToolPolicy {
15
21
  rate_limit?: string;
16
22
  /** Explicitly block this tool */
17
23
  block?: boolean;
24
+ /** Minimum trust tier required for this tool (v2) */
25
+ min_tier?: TrustTier;
26
+ /** Tier-specific rate limits (v2) */
27
+ rate_limits?: Partial<Record<TrustTier, {
28
+ max: number;
29
+ window: string;
30
+ }>>;
31
+ }
32
+ type TrustTier = 'unknown' | 'signed-known' | 'evidenced' | 'privileged';
33
+ type PolicyEngineMode = 'built-in' | 'external' | 'hybrid';
34
+ interface ExternalPDPConfig {
35
+ /** HTTP endpoint for the external policy decision point */
36
+ endpoint: string;
37
+ /** Response format: 'opa' | 'cerbos' | 'generic' */
38
+ format?: 'opa' | 'cerbos' | 'generic';
39
+ /** Timeout in milliseconds (default: 500) */
40
+ timeout_ms?: number;
41
+ /** Fallback decision when external PDP is unreachable */
42
+ fallback?: 'allow' | 'deny';
43
+ }
44
+ /**
45
+ * Decision context sent to external PDPs.
46
+ * Transport-agnostic: works with OPA, Cerbos, or custom engines.
47
+ */
48
+ interface DecisionContext {
49
+ v: 1;
50
+ actor: {
51
+ id?: string;
52
+ tier: TrustTier;
53
+ manifest_hash?: string;
54
+ };
55
+ action: {
56
+ tool: string;
57
+ operation?: string;
58
+ };
59
+ target: {
60
+ service: string;
61
+ resource_id?: string;
62
+ };
63
+ credential_ref?: string;
64
+ mode: 'shadow' | 'enforce';
65
+ request_metadata: Record<string, unknown>;
66
+ }
67
+ /** Response from an external PDP */
68
+ interface ExternalDecision {
69
+ allowed: boolean;
70
+ reason?: string;
71
+ /** Additional metadata from the PDP */
72
+ metadata?: Record<string, unknown>;
73
+ }
74
+ interface CredentialConfig {
75
+ /** How the credential is injected: header, query, body */
76
+ inject: 'header' | 'query' | 'env';
77
+ /** Header name, query param name, or env var name */
78
+ name: string;
79
+ /** Environment variable that holds the actual secret */
80
+ value_env: string;
81
+ }
82
+ interface SigningConfig {
83
+ /** Path to the Ed25519 private key file (JSON with privateKey, publicKey) */
84
+ key_path?: string;
85
+ /** Issuer identifier (e.g., "my-gateway.example.com") */
86
+ issuer?: string;
87
+ /** Whether signing is enabled (default: true when key_path is set) */
88
+ enabled?: boolean;
18
89
  }
19
90
  interface RateLimit {
20
91
  count: number;
@@ -38,15 +109,17 @@ interface JsonRpcResponse {
38
109
  }
39
110
  interface DecisionLog {
40
111
  /** Schema version */
41
- v: 1;
112
+ v: 1 | 2;
42
113
  /** Tool name that was called */
43
114
  tool: string;
44
115
  /** Decision: allow or deny */
45
116
  decision: 'allow' | 'deny';
46
117
  /** Why this decision was made */
47
- reason_code: 'policy_allow' | 'policy_block' | 'rate_limit_exceeded' | 'observe_mode' | 'default_allow';
118
+ reason_code: 'policy_allow' | 'policy_block' | 'rate_limit_exceeded' | 'observe_mode' | 'default_allow' | 'tier_insufficient' | 'external_pdp_allow' | 'external_pdp_deny' | 'external_pdp_error';
48
119
  /** SHA-256 digest of the canonicalized policy file */
49
120
  policy_digest: string;
121
+ /** Which policy engine made the decision */
122
+ policy_engine?: PolicyEngineMode;
50
123
  /** Unique request identifier */
51
124
  request_id: string;
52
125
  /** Unix timestamp (ms) */
@@ -54,7 +127,11 @@ interface DecisionLog {
54
127
  /** Remaining rate limit budget (if rate limit is configured) */
55
128
  rate_limit_remaining?: number;
56
129
  /** Operating mode */
57
- mode: 'observe' | 'enforce';
130
+ mode: 'shadow' | 'enforce';
131
+ /** Trust tier of the agent at decision time (v2) */
132
+ tier?: TrustTier;
133
+ /** Credential label used (v2, never the actual secret) */
134
+ credential_ref?: string;
58
135
  }
59
136
  interface ProtectConfig {
60
137
  /** Command to spawn (first element of child process) */
@@ -67,11 +144,75 @@ interface ProtectConfig {
67
144
  policyDigest: string;
68
145
  /** ScopeBlind tenant slug (optional, for future API integration) */
69
146
  slug?: string;
70
- /** Whether to enforce policy (default: false = observe mode) */
147
+ /** Whether to enforce policy (default: false = shadow mode) */
71
148
  enforce?: boolean;
72
149
  /** Verbose debug logging to stderr */
73
150
  verbose?: boolean;
151
+ /** Signing configuration */
152
+ signing?: SigningConfig;
153
+ /** Credential vault: maps credential labels to injection config */
154
+ credentials?: Record<string, CredentialConfig>;
155
+ }
156
+
157
+ /**
158
+ * @scopeblind/protect-mcp — Trust Tier Admission Evaluator
159
+ *
160
+ * Evaluates an agent's presented credentials at connection start
161
+ * and assigns a trust tier. The tier is used for per-tool policy
162
+ * evaluation throughout the session.
163
+ *
164
+ * Tiers (ascending): unknown → signed-known → evidenced → privileged
165
+ *
166
+ * Sprint 2: Simple evaluation (has valid manifest = signed-known).
167
+ * Full evidence evaluation (evidenced tier) is stubbed.
168
+ */
169
+
170
+ /**
171
+ * Minimal manifest info needed for tier evaluation.
172
+ * This is not the full manifest — just the fields admission cares about.
173
+ */
174
+ interface ManifestPresentation {
175
+ /** Agent identifier (e.g., sb:agent:xxxx) */
176
+ agent_id: string;
177
+ /** SHA-256 hash of the canonical manifest */
178
+ manifest_hash: string;
179
+ /** Ed25519 public key (hex) */
180
+ public_key?: string;
181
+ /** Whether the manifest signature was verified */
182
+ signature_valid?: boolean;
183
+ /** Optional evidence summary for tier upgrade */
184
+ evidence_summary?: {
185
+ receipt_count: number;
186
+ epoch_span: number;
187
+ issuer_count: number;
188
+ };
74
189
  }
190
+ /**
191
+ * Result of tier admission evaluation.
192
+ */
193
+ interface AdmissionResult {
194
+ tier: TrustTier;
195
+ agent_id?: string;
196
+ manifest_hash?: string;
197
+ reason: string;
198
+ }
199
+ /**
200
+ * Explicit tier overrides from the operator's config.
201
+ * Maps agent IDs to explicitly assigned tiers.
202
+ */
203
+ type TierOverrides = Record<string, TrustTier>;
204
+ /**
205
+ * Evaluate an agent's trust tier based on their presented credentials.
206
+ *
207
+ * @param manifest - Manifest presentation from the agent (or null if none)
208
+ * @param overrides - Operator-configured tier overrides
209
+ * @returns AdmissionResult with assigned tier
210
+ */
211
+ declare function evaluateTier(manifest: ManifestPresentation | null, overrides?: TierOverrides): AdmissionResult;
212
+ /**
213
+ * Check if a trust tier meets the minimum required tier.
214
+ */
215
+ declare function meetsMinTier(actual: TrustTier, required: TrustTier): boolean;
75
216
 
76
217
  /**
77
218
  * ProtectGateway — stdio MITM proxy for MCP servers.
@@ -79,17 +220,31 @@ interface ProtectConfig {
79
220
  * Sits between an MCP client (stdin/stdout) and a wrapped MCP server (child process).
80
221
  * Intercepts `tools/call` requests for policy enforcement and decision logging.
81
222
  * Passes through all other JSON-RPC messages transparently.
223
+ *
224
+ * v2 features:
225
+ * - Shadow mode (default): observe + signed receipts, no blocking
226
+ * - Trust-tier gating: evaluate manifest at admission, assign tier
227
+ * - Credential vault: inject secrets, agent never sees raw keys
228
+ * - BYOPE: pluggable policy decision via external HTTP webhook
229
+ * - Signed receipts: every decision produces a signed artifact
82
230
  */
83
231
  declare class ProtectGateway {
84
232
  private child;
85
233
  private config;
86
234
  private rateLimitStore;
87
235
  private clientReader;
236
+ private currentTier;
237
+ private admissionResult;
88
238
  constructor(config: ProtectConfig);
89
239
  /**
90
240
  * Start the gateway: spawn child process and wire up message relay.
91
241
  */
92
242
  start(): Promise<void>;
243
+ /**
244
+ * Set the trust tier for this session.
245
+ * Called at admission (first interaction) or by explicit manifest presentation.
246
+ */
247
+ setManifest(manifest: ManifestPresentation | null): AdmissionResult;
93
248
  /**
94
249
  * Handle a message from the MCP client (stdin).
95
250
  * Intercept tools/call requests; pass through everything else.
@@ -104,8 +259,13 @@ declare class ProtectGateway {
104
259
  * Intercept a tools/call request. Returns a JSON-RPC error response if denied, null if allowed.
105
260
  */
106
261
  private interceptToolCall;
262
+ /**
263
+ * Get the applicable rate limit spec based on the agent's tier.
264
+ */
265
+ private getTierRateLimit;
107
266
  /**
108
267
  * Emit a structured decision log to stderr.
268
+ * If signing is enabled, also emits a signed artifact.
109
269
  */
110
270
  private emitDecisionLog;
111
271
  /**
@@ -131,14 +291,19 @@ declare class ProtectGateway {
131
291
  }
132
292
 
133
293
  /**
134
- * Load and validate a policy file. Returns the policy and its digest.
294
+ * Load and validate a policy file. Returns the policy, credentials, signing config, and digest.
135
295
  */
136
296
  declare function loadPolicy(path: string): {
137
297
  policy: ProtectPolicy;
138
298
  digest: string;
299
+ credentials?: Record<string, CredentialConfig>;
300
+ signing?: SigningConfig;
139
301
  };
140
302
  /**
141
303
  * Get the policy for a specific tool. Falls back to "*" wildcard, then default-allow.
304
+ *
305
+ * Backwards compatible: old policies with just { block, rate_limit, require }
306
+ * still work. New policies can add { min_tier, rate_limits }.
142
307
  */
143
308
  declare function getToolPolicy(toolName: string, policy: ProtectPolicy | null): ToolPolicy;
144
309
  /**
@@ -154,4 +319,514 @@ declare function checkRateLimit(key: string, limit: RateLimit, store: Map<string
154
319
  remaining: number;
155
320
  };
156
321
 
157
- export { type DecisionLog, type JsonRpcRequest, type JsonRpcResponse, type ProtectConfig, ProtectGateway, type ProtectPolicy, type RateLimit, type ToolPolicy, checkRateLimit, getToolPolicy, loadPolicy, parseRateLimit };
322
+ /**
323
+ * @scopeblind/protect-mcp — Credential Vault
324
+ *
325
+ * Config-driven credential injection for MCP tool calls.
326
+ * The agent NEVER sees the raw credential. protect-mcp holds
327
+ * the secret and injects it into the appropriate context.
328
+ *
329
+ * Credentials are referenced by label in the policy and receipts.
330
+ * The actual secret value is read from environment variables.
331
+ *
332
+ * Example config:
333
+ * {
334
+ * "credentials": {
335
+ * "stripe_api": {
336
+ * "inject": "header",
337
+ * "name": "Authorization",
338
+ * "value_env": "STRIPE_KEY"
339
+ * },
340
+ * "github_token": {
341
+ * "inject": "header",
342
+ * "name": "Authorization",
343
+ * "value_env": "GITHUB_TOKEN"
344
+ * }
345
+ * }
346
+ * }
347
+ */
348
+
349
+ /**
350
+ * Result of credential resolution.
351
+ */
352
+ interface CredentialResolution {
353
+ /** Whether the credential was found and resolved */
354
+ resolved: boolean;
355
+ /** The credential label (safe to log, never the actual value) */
356
+ label: string;
357
+ /** Error message if resolution failed */
358
+ error?: string;
359
+ /** The resolved value (NEVER log this) */
360
+ value?: string;
361
+ /** How the credential should be injected */
362
+ inject?: 'header' | 'query' | 'env';
363
+ /** Injection target name (header name, query param, env var) */
364
+ name?: string;
365
+ }
366
+ /**
367
+ * Resolve a credential from the vault.
368
+ * Reads the actual secret from the environment variable specified in config.
369
+ *
370
+ * @param label - Credential label (e.g., "stripe_api")
371
+ * @param credentials - Credential configuration map
372
+ * @returns CredentialResolution (value is only populated on success)
373
+ */
374
+ declare function resolveCredential(label: string, credentials: Record<string, CredentialConfig> | undefined): CredentialResolution;
375
+ /**
376
+ * Get the list of configured credential labels (safe to log).
377
+ *
378
+ * @param credentials - Credential configuration map
379
+ * @returns Array of credential labels
380
+ */
381
+ declare function listCredentialLabels(credentials: Record<string, CredentialConfig> | undefined): string[];
382
+ /**
383
+ * Validate credential configuration at startup.
384
+ * Checks that all referenced environment variables exist.
385
+ *
386
+ * @param credentials - Credential configuration map
387
+ * @returns Array of warnings for missing env vars
388
+ */
389
+ declare function validateCredentials(credentials: Record<string, CredentialConfig> | undefined): string[];
390
+
391
+ /**
392
+ * @scopeblind/protect-mcp — Signing Integration
393
+ *
394
+ * Produces signed v2 artifact receipts for tool call decisions.
395
+ * Uses @veritasacta/artifacts as a required dependency (Sprint 2+).
396
+ *
397
+ * If signing is configured, every decision produces a signed artifact.
398
+ * If signing fails, the receipt is emitted unsigned with signature: null
399
+ * and a warning — never crashes, never silently drops.
400
+ */
401
+
402
+ /**
403
+ * Initialize the signing subsystem.
404
+ * Loads the key file and dynamically imports @veritasacta/artifacts.
405
+ *
406
+ * @param config - Signing configuration
407
+ * @returns Array of warnings (empty = success)
408
+ */
409
+ declare function initSigning(config: SigningConfig | undefined): Promise<string[]>;
410
+ /**
411
+ * Sign a decision log entry as a v2 artifact.
412
+ *
413
+ * Returns the signed artifact JSON string, or null if signing is not configured.
414
+ * On signing failure, returns an unsigned artifact with a warning.
415
+ */
416
+ declare function signDecision(entry: DecisionLog): {
417
+ signed: string | null;
418
+ artifact_type: string;
419
+ warning?: string;
420
+ };
421
+ /**
422
+ * Get the signer's public key info for discovery/verification.
423
+ */
424
+ declare function getSignerInfo(): {
425
+ publicKey: string;
426
+ kid: string;
427
+ issuer: string;
428
+ } | null;
429
+ /**
430
+ * Check if signing is available.
431
+ */
432
+ declare function isSigningEnabled(): boolean;
433
+
434
+ /**
435
+ * @scopeblind/protect-mcp — External PDP Adapter
436
+ *
437
+ * BYOPE (Bring Your Own Policy Engine) — sends decision context
438
+ * to an external Policy Decision Point via HTTP webhook.
439
+ *
440
+ * Supports OPA, Cerbos, and generic JSON formats.
441
+ * ScopeBlind always signs the receipt regardless of who made the decision.
442
+ *
443
+ * Sprint 2: One HTTP webhook adapter. More adapters later.
444
+ */
445
+
446
+ /**
447
+ * Query an external PDP for a policy decision.
448
+ *
449
+ * @param context - The decision context (transport-agnostic)
450
+ * @param config - External PDP configuration
451
+ * @returns ExternalDecision with allow/deny and optional metadata
452
+ */
453
+ declare function queryExternalPDP(context: DecisionContext, config: ExternalPDPConfig): Promise<ExternalDecision>;
454
+ /**
455
+ * Build a DecisionContext from a tool call.
456
+ */
457
+ declare function buildDecisionContext(toolName: string, tier: TrustTier, opts: {
458
+ agentId?: string;
459
+ manifestHash?: string;
460
+ credentialRef?: string;
461
+ mode: 'shadow' | 'enforce';
462
+ slug?: string;
463
+ requestMetadata?: Record<string, unknown>;
464
+ }): DecisionContext;
465
+
466
+ /**
467
+ * @scopeblind/protect-mcp — Audit Bundle Export
468
+ *
469
+ * Creates self-contained audit bundles that can be verified offline.
470
+ * A bundle includes receipts, optional anchors, and the signing keys
471
+ * needed to verify everything — no network calls required.
472
+ *
473
+ * Format:
474
+ * {
475
+ * format: "scopeblind:audit-bundle",
476
+ * version: 1,
477
+ * exported_at: ISO-8601,
478
+ * tenant: string,
479
+ * time_range: { from, to },
480
+ * receipts: [...signed v2 artifacts...],
481
+ * anchors: [...optional audit anchors...],
482
+ * verification: {
483
+ * algorithm: "ed25519",
484
+ * signing_keys: [...JWK keys needed to verify all receipts...],
485
+ * instructions: "..."
486
+ * }
487
+ * }
488
+ */
489
+
490
+ interface AuditBundleOptions {
491
+ /** Tenant/service identifier */
492
+ tenant: string;
493
+ /** Time range for exported receipts */
494
+ timeRange?: {
495
+ from: string;
496
+ to: string;
497
+ };
498
+ /** Signed v2 artifacts (decision_receipts and/or gateway_restraints) */
499
+ receipts: Record<string, unknown>[];
500
+ /** Optional audit anchors */
501
+ anchors?: Record<string, unknown>[];
502
+ /** JWK signing keys used by the receipts */
503
+ signingKeys: Array<{
504
+ kty: string;
505
+ crv: string;
506
+ kid: string;
507
+ x: string;
508
+ use?: string;
509
+ }>;
510
+ }
511
+ interface AuditBundle {
512
+ format: 'scopeblind:audit-bundle';
513
+ version: 1;
514
+ exported_at: string;
515
+ tenant: string;
516
+ time_range: {
517
+ from: string;
518
+ to: string;
519
+ } | null;
520
+ receipts: Record<string, unknown>[];
521
+ anchors: Record<string, unknown>[];
522
+ verification: {
523
+ algorithm: 'ed25519';
524
+ signing_keys: Array<{
525
+ kty: string;
526
+ crv: string;
527
+ kid: string;
528
+ x: string;
529
+ use?: string;
530
+ }>;
531
+ instructions: string;
532
+ };
533
+ }
534
+ /**
535
+ * Create a self-contained audit bundle for offline verification.
536
+ *
537
+ * The bundle contains everything needed to verify all receipts:
538
+ * - The signed receipts themselves
539
+ * - The public keys used to sign them
540
+ * - Verification instructions
541
+ *
542
+ * No network access required to verify.
543
+ */
544
+ declare function createAuditBundle(opts: AuditBundleOptions): AuditBundle;
545
+ /**
546
+ * Collect decision log entries into signed receipts suitable for bundling.
547
+ * Filters for entries that have attached signed artifacts.
548
+ */
549
+ declare function collectSignedReceipts(logs: DecisionLog[]): Record<string, unknown>[];
550
+
551
+ /**
552
+ * Agent identity format: sb:agent:{first 32 hex chars of SHA-256(public key bytes)}
553
+ * Example: "sb:agent:a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6"
554
+ */
555
+ type AgentId = `sb:agent:${string}`;
556
+ /**
557
+ * Builder identity format: sb:builder:{hash}
558
+ */
559
+ type BuilderId = `sb:builder:${string}`;
560
+ /**
561
+ * Ed25519 public key in prefixed format: "ed25519:{base64url}"
562
+ */
563
+ type Ed25519PublicKey = `ed25519:${string}`;
564
+ /**
565
+ * SHA-256 hash in prefixed format: "sha256:{hex}"
566
+ */
567
+ type SHA256Hash = `sha256:${string}`;
568
+ /**
569
+ * Manifest lifecycle status.
570
+ * - active: Agent is operational. Operators should grant access per policy.
571
+ * - suspended: Temporarily disabled. Builder is investigating. Reversible.
572
+ * - revoked: Permanently disabled. Irreversible. New keypair needed.
573
+ */
574
+ type ManifestStatus = 'active' | 'suspended' | 'revoked';
575
+ /**
576
+ * ScopeBlind disclosure modes — governance decision, not implementation detail.
577
+ * - private: Minimum-disclosure. Unlinkable, single-use identity.
578
+ * - scoped: Pseudonymous. Deterministic per-service hash.
579
+ * - named: Full attribution. Explicit identifier.
580
+ */
581
+ type DisclosureMode = 'private' | 'scoped' | 'named';
582
+ /**
583
+ * The five evidence types in the Agent Economy taxonomy.
584
+ * Evidence and claims/interpretation are ALWAYS separate layers.
585
+ */
586
+ type EvidenceType = 'arena' | 'benchmark' | 'work' | 'restraint' | 'attestation';
587
+ interface AgentManifest {
588
+ /** Spec version. Always "0.1" for this version. */
589
+ manifest_version: '0.1';
590
+ /** Stable agent identity: sb:agent:{public_key_hash} */
591
+ id: AgentId;
592
+ /** Monotonically increasing version number. Starts at 1. */
593
+ version: number;
594
+ /**
595
+ * SHA-256 of the previous manifest version's canonical JSON.
596
+ * Null for the first version. Creates an append-only version chain.
597
+ */
598
+ previous_version: SHA256Hash | null;
599
+ /** ISO 8601 timestamp — when this manifest version was created. */
600
+ created_at: string;
601
+ /** ISO 8601 timestamp — when this manifest was last modified. */
602
+ updated_at: string;
603
+ /** ISO 8601 timestamp — when this manifest expires. Null means no expiry. */
604
+ expires_at: string | null;
605
+ /** Lifecycle status of this agent. */
606
+ status: ManifestStatus;
607
+ /** Human-readable reason when suspended or revoked. Null if active. */
608
+ status_reason: string | null;
609
+ /** ISO 8601 timestamp of last status change. Null if always active. */
610
+ status_changed_at: string | null;
611
+ identity: ManifestIdentity;
612
+ capabilities: ManifestCapabilities;
613
+ config: ManifestConfig;
614
+ evidence_summary: EvidenceSummary;
615
+ lease_compatibility: LeaseCompatibility;
616
+ signature: ManifestSignature;
617
+ }
618
+ interface ManifestIdentity {
619
+ /** Ed25519 public key: "ed25519:{base64url}" */
620
+ public_key: Ed25519PublicKey;
621
+ /** Key algorithm. Always "Ed25519" in v0.1. */
622
+ key_algorithm: 'Ed25519';
623
+ /** Builder information. All fields optional — builder can remain pseudonymous. */
624
+ builder: ManifestBuilder;
625
+ }
626
+ interface ManifestBuilder {
627
+ /** Builder's display name. Optional. */
628
+ name?: string;
629
+ /** Builder's contact information. Optional. */
630
+ contact?: string;
631
+ /** ScopeBlind builder identity. Optional. */
632
+ id?: BuilderId;
633
+ }
634
+ interface ManifestCapabilities {
635
+ /**
636
+ * SHA-256 hash of the model identifier string.
637
+ * Hides exact model while allowing change detection.
638
+ */
639
+ model_family_hash: SHA256Hash;
640
+ /** Declared tool usage categories (e.g., "file_read", "web_search"). */
641
+ tool_categories: string[];
642
+ /** Which ScopeBlind disclosure modes this agent supports. */
643
+ supported_disclosure_modes: DisclosureMode[];
644
+ /** Declared maximum context window size. Optional. */
645
+ max_context_tokens?: number;
646
+ /** ISO 639-1 language codes the agent supports. Optional. */
647
+ languages?: string[];
648
+ }
649
+ interface ManifestConfig {
650
+ /** SHA-256 of the system prompt text. Config hash, not config. */
651
+ system_prompt_hash: SHA256Hash;
652
+ /** SHA-256 of the canonical JSON of tool definitions. */
653
+ tool_definitions_hash: SHA256Hash;
654
+ /** SHA-256 of the canonical JSON of model parameters. */
655
+ parameters_hash: SHA256Hash;
656
+ /** Builder's internal version label. Optional. */
657
+ config_version?: string;
658
+ }
659
+ interface EvidenceSummaryEntry {
660
+ /** Total number of receipts of this type. */
661
+ count: number;
662
+ /** ISO 8601 timestamp of the most recent receipt. */
663
+ latest_at: string;
664
+ /** Identity of the primary issuer for this evidence type. */
665
+ issuer: string;
666
+ }
667
+ interface EvidenceSummary {
668
+ arena: EvidenceSummaryEntry;
669
+ benchmark: EvidenceSummaryEntry;
670
+ work: EvidenceSummaryEntry;
671
+ restraint: EvidenceSummaryEntry;
672
+ attestation: EvidenceSummaryEntry;
673
+ }
674
+ interface LeaseCompatibility {
675
+ /** Minimum protect-mcp policy version this agent supports. Optional. */
676
+ min_policy_version?: string;
677
+ /** Rate limit thresholds the agent is designed to work within. Optional. */
678
+ accepted_rate_limits?: {
679
+ default?: string;
680
+ max_burst?: string;
681
+ };
682
+ /** Tools the agent must have access to in order to function. Optional. */
683
+ required_tools?: string[];
684
+ /** Tools the agent can use but doesn't require. Optional. */
685
+ optional_tools?: string[];
686
+ }
687
+ interface ManifestSignature {
688
+ /** Signature algorithm. Always "Ed25519" in v0.1. */
689
+ algorithm: 'Ed25519';
690
+ /** Identity of the signer. Self-signed in v1 trust model. */
691
+ signer: AgentId | string;
692
+ /** Base64url-encoded signature over canonical JSON of all fields except signature. */
693
+ value: string;
694
+ }
695
+ /**
696
+ * Issuer type classifies who is signing the evidence receipt.
697
+ * - platform: Automated platform (arena, benchmark suite, task marketplace)
698
+ * - human: Individual human attestor
699
+ * - gateway: protect-mcp or similar gateway (generates restraint evidence)
700
+ * - evaluator: Evaluation framework or benchmarking system
701
+ */
702
+ type IssuerType = 'platform' | 'human' | 'gateway' | 'evaluator';
703
+ interface EvidenceIssuer {
704
+ /** Issuer identity string (domain, sb:user:..., etc.) */
705
+ id: string;
706
+ /** What kind of entity is issuing this evidence. */
707
+ type: IssuerType;
708
+ /** Issuer's Ed25519 public key for signature verification. */
709
+ public_key: Ed25519PublicKey;
710
+ }
711
+ interface EvidenceReceiptBase {
712
+ /** Spec version. Always "0.1" for this version. */
713
+ receipt_version: '0.1';
714
+ /** Unique receipt identifier: "ev:{type}:{hash}" */
715
+ receipt_id: string;
716
+ /** Which of the 5 evidence types this receipt represents. */
717
+ evidence_type: EvidenceType;
718
+ /** Which agent this evidence is about. */
719
+ agent_id: AgentId;
720
+ /** Who signed this evidence receipt. */
721
+ issuer: EvidenceIssuer;
722
+ /** ISO 8601 timestamp — when this receipt was issued. */
723
+ issued_at: string;
724
+ /** ISO 8601 timestamp — hard expiry. Null if using freshness_window. */
725
+ expires_at: string | null;
726
+ /** Freshness window in seconds. Consumer decides if fresh enough. */
727
+ freshness_window_seconds: number;
728
+ signature: {
729
+ algorithm: 'Ed25519';
730
+ signer: string;
731
+ value: string;
732
+ };
733
+ }
734
+ interface ArenaPayload {
735
+ battle_id: string;
736
+ /** SHA-256 hash of opponent agent ID (privacy: don't reveal opponent). */
737
+ opponent_hash: SHA256Hash;
738
+ outcome: 'win' | 'loss' | 'tie';
739
+ /** Optional category tag for the prompt. */
740
+ prompt_category?: string;
741
+ platform: string;
742
+ }
743
+ interface BenchmarkPayload {
744
+ suite_id: string;
745
+ suite_version: string;
746
+ scores: {
747
+ overall: number;
748
+ categories?: Record<string, number>;
749
+ };
750
+ run_id: string;
751
+ /** SHA-256 hash of benchmark configuration (reproducibility). */
752
+ run_config_hash?: SHA256Hash;
753
+ }
754
+ interface WorkPayload {
755
+ task_id: string;
756
+ task_category: string;
757
+ outcome: 'success' | 'partial' | 'failure';
758
+ /** Optional quantification of work done. */
759
+ item_count?: number;
760
+ error_count?: number;
761
+ /** Link to human reviewer's attestation receipt. */
762
+ reviewer_attestation_id?: string;
763
+ }
764
+ interface RestraintPayload {
765
+ policy_digest: string;
766
+ /** ISO 8601 — start of the observation window. */
767
+ window_start: string;
768
+ /** ISO 8601 — end of the observation window. */
769
+ window_end: string;
770
+ total_calls: number;
771
+ allow_count: number;
772
+ deny_count: number;
773
+ deny_reason_codes: string[];
774
+ mode: 'observe' | 'enforce';
775
+ }
776
+ interface AttestationPayload {
777
+ /** Narrow, specific statement about observed behavior. NOT a general endorsement. */
778
+ statement: string;
779
+ /** Scope of the attestation (e.g., "invoice_processing"). */
780
+ scope: string;
781
+ /** ISO 8601 — start of the observation period. */
782
+ observed_period_start: string;
783
+ /** ISO 8601 — end of the observation period. */
784
+ observed_period_end: string;
785
+ attestor_type: 'human' | 'organization';
786
+ }
787
+ interface ArenaReceipt extends EvidenceReceiptBase {
788
+ evidence_type: 'arena';
789
+ payload: ArenaPayload;
790
+ }
791
+ interface BenchmarkReceipt extends EvidenceReceiptBase {
792
+ evidence_type: 'benchmark';
793
+ payload: BenchmarkPayload;
794
+ }
795
+ interface WorkReceipt extends EvidenceReceiptBase {
796
+ evidence_type: 'work';
797
+ payload: WorkPayload;
798
+ }
799
+ interface RestraintReceipt extends EvidenceReceiptBase {
800
+ evidence_type: 'restraint';
801
+ payload: RestraintPayload;
802
+ }
803
+ interface AttestationReceipt extends EvidenceReceiptBase {
804
+ evidence_type: 'attestation';
805
+ payload: AttestationPayload;
806
+ }
807
+ /** Union type for all evidence receipt variants. */
808
+ type EvidenceReceipt = ArenaReceipt | BenchmarkReceipt | WorkReceipt | RestraintReceipt | AttestationReceipt;
809
+ /** Check if a string is a valid agent ID format. */
810
+ declare function isAgentId(s: string): s is AgentId;
811
+ /** Check if a string is a valid evidence type. */
812
+ declare function isEvidenceType(s: string): s is EvidenceType;
813
+ /** Check if a string is a valid manifest status. */
814
+ declare function isManifestStatus(s: string): s is ManifestStatus;
815
+ /** Check if a string is a valid disclosure mode. */
816
+ declare function isDisclosureMode(s: string): s is DisclosureMode;
817
+ /**
818
+ * Validate the structural integrity of a manifest (types and required fields).
819
+ * Does NOT verify the cryptographic signature — use verifyManifestSignature() for that.
820
+ *
821
+ * Returns an array of error strings. Empty array = valid.
822
+ */
823
+ declare function validateManifest(manifest: unknown): string[];
824
+ /**
825
+ * Validate the structural integrity of an evidence receipt.
826
+ * Does NOT verify the cryptographic signature.
827
+ *
828
+ * Returns an array of error strings. Empty array = valid.
829
+ */
830
+ declare function validateEvidenceReceipt(receipt: unknown): string[];
831
+
832
+ export { type AdmissionResult, type AgentId, type AgentManifest, type ArenaPayload, type ArenaReceipt, type AttestationPayload, type AttestationReceipt, type AuditBundle, type AuditBundleOptions, type BenchmarkPayload, type BenchmarkReceipt, type BuilderId, type CredentialConfig, type DecisionContext, type DecisionLog, type DisclosureMode, type Ed25519PublicKey, type EvidenceIssuer, type EvidenceReceipt, type EvidenceReceiptBase, type EvidenceSummary, type EvidenceSummaryEntry, type EvidenceType, type ExternalDecision, type ExternalPDPConfig, type IssuerType, type JsonRpcRequest, type JsonRpcResponse, type LeaseCompatibility, type ManifestBuilder, type ManifestCapabilities, type ManifestConfig, type ManifestIdentity, type ManifestPresentation, type ManifestSignature, type ManifestStatus, type PolicyEngineMode, type ProtectConfig, ProtectGateway, type ProtectPolicy, type RateLimit, type RestraintPayload, type RestraintReceipt, type SHA256Hash, type SigningConfig, type TierOverrides, type ToolPolicy, type TrustTier, type WorkPayload, type WorkReceipt, buildDecisionContext, checkRateLimit, collectSignedReceipts, createAuditBundle, evaluateTier, getSignerInfo, getToolPolicy, initSigning, isAgentId, isDisclosureMode, isEvidenceType, isManifestStatus, isSigningEnabled, listCredentialLabels, loadPolicy, meetsMinTier, parseRateLimit, queryExternalPDP, resolveCredential, signDecision, validateCredentials, validateEvidenceReceipt, validateManifest };