docs(security): publish public threat model - #74
Conversation
📝 WalkthroughWalkthroughChangesThreat Model Documentation
Estimated code review effort: 2 (Simple) | ~10 minutes Poem
Caution Pre-merge checks failedPlease resolve all errors before merging. Addressing warnings is optional.
❌ Failed checks (1 error)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
|
@coderabbitai review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/threat-model.md`:
- Line 63: Update the MCP client to local ingress row in the threat-model matrix
to state that secret-backed bearer authentication is mandatory for every
explicitly enabled non-loopback binding, replacing the current “optional”
wording while preserving the other listed controls.
In `@tests/threat-model-docs-contract.test.ts`:
- Around line 68-79: Update the threat list in the contract test’s iteration to
include “**Credential-runtime or container handoff exposure**” and “**Misleading
upstream identity or response data**”. Keep the existing assertions unchanged so
every documented threat row in threatModel is required by the test.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 3b65f6d4-3980-4d16-8ecf-60b36b79833b
📒 Files selected for processing (6)
README.mdSECURITY.mddocs/architecture.mddocs/security.mddocs/threat-model.mdtests/threat-model-docs-contract.test.ts
Summary
Security impact
Validation
RUN v3.2.7 /private/tmp/miftah-issue37-threat-model
✓ tests/threat-model-docs-contract.test.ts (2 tests) 3ms
Test Files 1 passed (1)
Tests 2 passed (2)
Start at 19:20:29
Duration 162ms (transform 19ms, setup 0ms, collect 16ms, tests 3ms, environment 0ms, prepare 31ms) failed on the prior optional-auth wording, then passed after the correction.
RUN v3.2.7 /private/tmp/miftah-issue37-threat-model
✓ tests/mcp-wrapper.test.ts (88 tests) 41623ms
✓ Miftah MCP wrapper > scopes annotation trust to each named base upstream 386ms
✓ Miftah MCP wrapper > verifies requested named upstreams alone and all configured upstreams in sorted order 477ms
✓ Miftah MCP wrapper > invalidates passive identity status when a verified upstream profile restarts 426ms
✓ Miftah MCP wrapper > exposes management and upstream capabilities while routing calls by active profile 504ms
✓ Miftah MCP wrapper > routes a standard resource read through a canonical provider URI matcher 491ms
✓ Miftah MCP wrapper > uses the collector snapshot for matching redacted preview and audit evidence 547ms
✓ Miftah MCP wrapper > routes a client-visible multi-upstream GitHub tool through its static matcher binding 1049ms
✓ Miftah MCP wrapper > records bounded canonical matcher evidence for an ambiguous proxied operation without forwarding it 606ms
✓ Miftah MCP wrapper > uses the same canonical matcher evidence for preview and successful proxied operation audits 802ms
✓ Miftah MCP wrapper > does not treat a static matcher as the explicit rule required for destructive operations 652ms
✓ Miftah MCP wrapper > advertises and emits tool list changes after a profile switch 328ms
✓ Miftah MCP wrapper > propagates a cancelled tool call to the selected stdio upstream and records one terminal audit outcome 769ms
✓ Miftah MCP wrapper > propagates cancellation through initial tool discovery 763ms
✓ Miftah MCP wrapper > propagates cancellation through management tool discovery 817ms
✓ Miftah MCP wrapper > keeps shared tool discovery alive when one downstream caller cancels 818ms
✓ Miftah MCP wrapper > starts fresh tool discovery when a prior sole caller has cancelled 791ms
✓ Miftah MCP wrapper > fans shared tool discovery progress out to every downstream caller 446ms
✓ Miftah MCP wrapper > propagates cancellation through resource discovery 754ms
✓ Miftah MCP wrapper > aggregates concurrent upstream tool-discovery progress on one downstream token 493ms
✓ Miftah MCP wrapper > namespaces aggregated resource templates and routes instantiated reads to their origin upstream 351ms
✓ Miftah MCP wrapper > reports a stable unavailable error when no aggregated upstream implements resource templates 363ms
✓ Miftah MCP wrapper > proxies resource subscriptions to the selected upstream and namespaces update notifications 454ms
✓ Miftah MCP wrapper > forwards only updates for the subscribed resource 333ms
✓ Miftah MCP wrapper > does not forward an update from a subscription that fails before activation 331ms
✓ Miftah MCP wrapper > cleans up an upstream subscription that finishes after downstream cancellation 491ms
✓ Miftah MCP wrapper > releases a subscription after its unsubscribe request is cancelled 447ms
✓ Miftah MCP wrapper > bounds a pending subscription before switching profiles at capacity 604ms
✓ Miftah MCP wrapper > serializes cancelled subscription cleanup before a retry 1395ms
✓ Miftah MCP wrapper > fans one upstream resource update out to every matching static and template subscription 561ms
✓ Miftah MCP wrapper > re-establishes a resource subscription after its upstream restarts 369ms
✓ Miftah MCP wrapper > clears a direct resource subscription when its upstream lifecycle ends 423ms
✓ Miftah MCP wrapper > serializes overlapping resource subscription transitions before releasing idle capacity 398ms
✓ Miftah MCP wrapper > joins an in-flight unsubscribe before profile cleanup 484ms
✓ Miftah MCP wrapper > does not retain a subscription invalidated during its upstream handshake 462ms
✓ Miftah MCP wrapper > does not establish a captured-profile subscription after a profile switch 336ms
✓ Miftah MCP wrapper > keeps a resource subscription alive beyond the upstream idle timeout 348ms
✓ Miftah MCP wrapper > drops an old-profile resource subscription before a delayed update can be forwarded 512ms
✓ Miftah MCP wrapper > clears a routed third-profile subscription when the active profile changes 628ms
✓ Miftah MCP wrapper > bounds resource subscription cleanup while switching profiles 1733ms
✓ Miftah MCP wrapper > releases subscription-capability probes before serving the active profile at capacity 397ms
✓ Miftah MCP wrapper > forwards upstream tools, resources, and prompts list-change notifications 393ms
✓ Miftah MCP wrapper > forwards a tool list change from a session first used for discovery 486ms
✓ Miftah MCP wrapper > refreshes the initial tool snapshot after a concurrent upstream list change 383ms
✓ Miftah MCP wrapper > does not reject a cold tool call when an idle upstream emits a list change 318ms
✓ Miftah MCP wrapper > clears a deferred tool invalidation when its list request is cancelled 461ms
✓ Miftah MCP wrapper > refreshes the advertised tool schema after a profile switch 494ms
✓ Miftah MCP wrapper > retries tool discovery when the active profile changes during listing 587ms
✓ Miftah MCP wrapper > rejects routing to a profile with a different advertised tool schema 517ms
✓ Miftah MCP wrapper > fails strict discovery when configured profiles expose different tool schemas 417ms
✓ Miftah MCP wrapper > invalidates strict discovery when a non-active profile becomes unavailable 527ms
✓ Miftah MCP wrapper > resolves unregistered miftah-prefixed names through the tool registry 346ms
✓ Miftah MCP wrapper > shares controlled discovery between a list request and a cold call 365ms
✓ Miftah MCP wrapper > invalidates a profile tool snapshot after an explicit restart 433ms
✓ Miftah MCP wrapper > linearizes a cold tool call before a concurrent profile switch 523ms
✓ Miftah MCP wrapper > blocks denied resource reads before forwarding them upstream 351ms
✓ Miftah MCP wrapper > collects runtime roots once and routes repeated proxied calls from the cached context 612ms
✓ Miftah MCP wrapper > routes proxied calls with empty roots when the initialized notification is dropped 457ms
✓ Miftah MCP wrapper > keeps a relative runtime config distinct from a later project marker 603ms
✓ Miftah MCP wrapper > keeps fallback routing usable without roots and preserves direct-server empty context 728ms
✓ Miftah MCP wrapper > falls back after a failed runtime roots request without retrying per operation 462ms
✓ Miftah MCP wrapper > refreshes advertised roots once and ignores unadvertised roots changes 1773ms
✓ Miftah MCP wrapper > refreshes again when roots change during an in-flight roots request 604ms
✓ Miftah MCP wrapper > uses exactly one routing context snapshot per proxied operation 659ms
✓ Miftah MCP wrapper > returns unknown context profile errors without forwarding the proxied call 474ms
✓ Miftah MCP wrapper > restores a workspace-scoped active profile and exposes safe selection metadata 647ms
✓ tests/package-contract.test.ts (16 tests) 18525ms
✓ packed artifact contract > keeps the test worker responsive while an npm subprocess is running 561ms
✓ packed artifact contract > includes captured output when an npm command exits unsuccessfully 328ms
✓ packed artifact contract > contains required runtime, documentation, and example files from a real dry run 388ms
✓ packed artifact contract > runs the checked package command against the real npm pack output 627ms
✓ packed artifact contract > loads the installed entry point and runs the installed binary from a real tarball 10309ms
✓ tests/multi-upstream.test.ts (28 tests) 11966ms
✓ multi-upstream wrapper > keeps healthy aggregate capabilities available when a bundled upstream cannot start 390ms
✓ multi-upstream wrapper > reports redacted capability discovery failures as degraded upstream health 376ms
✓ multi-upstream wrapper > fails strict tool discovery with a complete unavailable-upstream diagnostic 358ms
✓ multi-upstream wrapper > fails strict resource discovery with a complete unavailable-upstream diagnostic 312ms
✓ multi-upstream wrapper > fails strict prompt discovery with a complete unavailable-upstream diagnostic 347ms
✓ multi-upstream wrapper > aggregates namespaced resources and routes each read to its originating upstream 405ms
✓ multi-upstream wrapper > removes stale routes when a bundled upstream fails resource discovery 367ms
✓ multi-upstream wrapper > removes stale routes when a bundled upstream fails prompt discovery 463ms
✓ multi-upstream wrapper > notifies clients when partial resource and prompt discovery recovers 626ms
✓ multi-upstream wrapper > rejects ambiguous namespaced resource and prompt collisions atomically 408ms
✓ multi-upstream wrapper > preserves independent upstream pagination through opaque aggregate cursors 399ms
✓ multi-upstream wrapper > notifies clients to re-list aggregated resources and prompts after a profile change 896ms
✓ multi-upstream wrapper > redacts configured and URI-embedded credentials before publishing a namespaced resource URI 353ms
✓ multi-upstream wrapper > uses controlled discovery to route cold namespaced reads and prompt gets exactly 359ms
✓ multi-upstream wrapper > routes a namespaced tool call before tools are listed 366ms
✓ multi-upstream wrapper > restarts every upstream in a profile bundle and invalidates its tool snapshot 718ms
✓ multi-upstream wrapper > recovers healthy tool discovery after a partial multi-upstream restart failure 841ms
✓ multi-upstream wrapper > refreshes the tool registry after an upstream crashes and later recovers 1375ms
✓ multi-upstream wrapper > waits for every bundled restart to settle before returning a restart failure 705ms
✓ multi-upstream wrapper > lists namespaced upstream tools through the deterministic registry 364ms
✓ multi-upstream wrapper > namespaces and routes tools from multiple upstream servers 377ms
✓ tests/upstream-manager.test.ts (26 tests) 7721ms
✓ upstream process manager > shuts down an idle profile and starts a fresh process on its next use 331ms
✓ upstream process manager > keeps a replacement session healthy and reserved while an idle predecessor is still closing 1571ms
✓ upstream process manager > does not idle-shutdown a profile while an upstream request is in flight 336ms
✓ upstream process manager > does not restart a crashed process unless automatic recovery is configured 423ms
✓ upstream process manager > automatically recovers a crashed profile after a bounded backoff 336ms
✓ upstream process manager > stops automatic recovery when the configured restart budget is exhausted 806ms
✓ upstream process manager > records a failed restart teardown before starting a replacement session 333ms
✓ upstream process manager > cancels pending automatic recovery when the manager shuts down 427ms
✓ tests/operation-pipeline.test.ts (20 tests) 7389ms
✓ operation pipeline > verifies named upstream writes against their exact override or inherited identity 410ms
✓ operation pipeline > rejects ambiguous resource and prompt routes before forwarding them upstream 396ms
✓ operation pipeline > does not forward destructive calls when project context profile hints conflict 371ms
✓ operation pipeline > routes resource reads and prompt retrieval to the selected profile 391ms
✓ operation pipeline > keeps in-flight resource and prompt operations bound to their captured profile 604ms
✓ operation pipeline > completes in-flight aggregate reads and prompts after a profile switch 817ms
✓ operation pipeline > retries cold aggregate route discovery against the captured profile after a switch 1073ms
✓ operation pipeline > redacts credential-bearing unknown resource URIs in diagnostics 467ms
✓ tests/approval-fallback.test.ts (23 tests) 4413ms
✓ approval fallback > audits a native approval that expires while its form is open 305ms
✓ tests/audit-outcomes.test.ts (15 tests) 5119ms
✓ audit outcomes > records one terminal operation event for list, management, and unknown-tool requests 537ms
✓ audit outcomes > records wrapper and lazy upstream lifecycle outcomes 753ms
✓ audit outcomes > redacts secret-bearing discovery metadata before it reaches MCP clients 448ms
✓ audit outcomes > redacts discovery failures from client errors, health, and audit output 420ms
✓ audit outcomes > keeps MCP results available and exposes audit health when fail-open writes fail 338ms
✓ audit outcomes > records upstream crash and automatic recovery outcomes 469ms
✓ audit outcomes > records a static profile lock as wrapper startup metadata 338ms
✓ tests/identity-manager.test.ts (23 tests) 4588ms
✓ identity verifier > forwards cancellation through identity probe discovery 705ms
✓ identity verifier > keeps a shared identity probe alive when one request cancels 632ms
✓ tests/doctor.test.ts (22 tests) 4594ms
✓ doctor readiness runner > accepts a relative executable resolved from its configured working directory 1129ms
✓ doctor readiness runner > reports profile tool schema differences as warnings or strict errors 499ms
✓ tests/remote-transport.test.ts (11 tests) 4088ms
✓ remote upstream transports > forces local cleanup when a Streamable HTTP session DELETE hangs 3812ms
✓ tests/http-server.test.ts (15 tests) 4405ms
✓ Miftah Streamable HTTP server > bounds oversized JSON requests before they can reserve a session 366ms
✓ Miftah Streamable HTTP server > keeps profile selection isolated across concurrent HTTP client sessions 1011ms
✓ Miftah Streamable HTTP server > reconnects an interrupted SSE stream to the existing session without creating another runtime 353ms
✓ Miftah Streamable HTTP server > expires idle sessions and releases their retained upstream transport 1042ms
✓ Miftah Streamable HTTP server > keeps capacity reserved until a deleted session runtime has finished closing 568ms
✓ Miftah Streamable HTTP server > reserves capacity during concurrent initialization and releases it after DELETE 596ms
✓ tests/audit-integrity.test.ts (20 tests) 2866ms
✓ audit journal integrity > compacts integrity metadata when retention removes every rotated archive 971ms
✓ tests/secret-providers.test.ts (89 tests | 11 skipped) 2613ms
✓ external secret providers > resolves default keychain and 1Password commands from absolute PATH entries 876ms
✓ tests/audit-log-reader.test.ts (35 tests) 2078ms
✓ logs command integration > follows a managed rotation that completes before its next poll 557ms
✓ tests/profile-lease-pipeline.test.ts (6 tests) 1574ms
✓ profile leases in the operation pipeline > requires an explicit unexpired selection before forwarding a lease-protected risk 310ms
✓ profile leases in the operation pipeline > does not let a routed profile borrow the active profile's lease 486ms
✓ tests/audit.test.ts (24 tests) 1936ms
✓ audit logger > serializes concurrent logger instances through the journal lock at a rotation boundary 1582ms
✓ tests/plugin-api.test.ts (13 tests) 1220ms
✓ tests/plugin-routing-server.test.ts (1 test) 790ms
✓ plugin routing server integration > uses configured routing plugins for real proxied MCP tool calls 789ms
✓ tests/profile-lock-mcp.test.ts (3 tests) 978ms
✓ MCP profile locks > exposes opt-in connection-bound lock controls and safe profile state 387ms
✓ MCP profile locks > keeps lock controls discoverable but rejects calls while the opt-in is disabled 353ms
✓ tests/profile-runtime-isolation.test.ts (23 tests) 1056ms
✓ profile runtime isolation > atomically rematerializes mapped files on restart and never deletes source files or runtime state 305ms
✓ tests/routing-context.test.ts (21 tests) 960ms
✓ tests/executable-resolver.test.ts (4 tests) 1280ms
✓ secret executable resolution > resolves explicit relative paths and case-insensitive quoted PATH entries 543ms
✓ tests/config-preflight.test.ts (4 tests) 579ms
✓ tests/profile-transition-audit-barrier.test.ts (1 test) 484ms
✓ profile transition audit barrier > does not expose a new profile lease to concurrent calls before its required audit transition commits 483ms
✓ tests/public-api.test.ts (4 tests) 293ms
✓ tests/secrets.test.ts (20 tests) 131ms
✓ tests/plugin-routing-pipeline.test.ts (1 test) 116ms
✓ tests/config-migration.test.ts (21 tests) 153ms
✓ tests/audit-verify.test.ts (2 tests) 107ms
✓ tests/fake-upstream-fixture.test.ts (1 test) 109ms
✓ tests/audit-export.test.ts (6 tests) 96ms
✓ tests/profile-state.test.ts (10 tests) 75ms
✓ tests/negative-paths.test.ts (5 tests) 65ms
✓ tests/init-command.test.ts (10 tests) 23ms
✓ tests/managed-audit-follow.test.ts (1 test) 22ms
✓ tests/config-runtime-parity.test.ts (62 tests) 18ms
✓ tests/config.test.ts (56 tests) 14ms
✓ tests/runtime-config-resolution.test.ts (4 tests) 16ms
✓ tests/config-schema-contract.test.ts (8 tests) 13ms
✓ tests/config-diagnostics.test.ts (29 tests) 14ms
✓ tests/approval-store.test.ts (11 tests) 13ms
✓ tests/audit-journal-path-safety.test.ts (1 test) 13ms
✓ tests/preset-catalog.test.ts (31 tests) 9ms
✓ tests/config-public-contract.test.ts (4 tests) 10ms
✓ tests/identity-docs-contract.test.ts (2 tests) 8ms
✓ tests/doctor-report.test.ts (10 tests) 8ms
✓ tests/resource-prompt-registry.test.ts (13 tests) 9ms
✓ tests/routing-policy.test.ts (24 tests) 8ms
✓ tests/windows-config-acl.test.ts (6 tests) 9ms
✓ tests/windows-config-migration-acl-failure.test.ts (1 test) 9ms
✓ tests/release-config.test.ts (18 tests) 8ms
✓ tests/tool-registry.test.ts (1 test) 8ms
✓ tests/config-loader.test.ts (4 tests) 9ms
✓ tests/logs-writer.test.ts (4 tests) 5ms
✓ tests/preset-docs-contract.test.ts (1 test) 6ms
✓ tests/secret-provider-availability.test.ts (8 tests | 2 skipped) 6ms
✓ tests/client-snippets.test.ts (30 tests) 4ms
✓ tests/provider-routing-matchers.test.ts (14 tests) 5ms
✓ tests/release-version.test.ts (4 tests) 4ms
✓ tests/profile-manager.test.ts (10 tests) 4ms
✓ tests/cli-parse.test.ts (10 tests) 4ms
✓ tests/threat-model-docs-contract.test.ts (2 tests) 3ms
✓ tests/progress-preserving-transport.test.ts (7 tests) 3ms
✓ tests/tooling-config.test.ts (4 tests) 3ms
✓ tests/presets.test.ts (4 tests) 2ms
✓ tests/secret-provider-docs-contract.test.ts (3 tests) 2ms
✓ tests/profile-state-docs-contract.test.ts (1 test) 3ms
✓ tests/risk-classification-docs-contract.test.ts (1 test) 2ms
✓ tests/approval-docs-contract.test.ts (1 test) 2ms
✓ tests/cli-exit-codes.test.ts (3 tests) 2ms
✓ tests/provider-routing-matchers-docs-contract.test.ts (1 test) 2ms
✓ tests/profile-runtime-isolation-docs-contract.test.ts (2 tests) 8ms
✓ tests/windows-secret-command-contract.test.ts (2 tests) 5ms
✓ tests/profile-leases-docs-contract.test.ts (1 test) 3ms
✓ tests/routing-context-docs-contract.test.ts (1 test) 6ms
↓ tests/windows-config-migration-acl.test.ts (9 tests | 9 skipped)
Test Files 75 passed | 1 skipped (76)
Tests 998 passed | 22 skipped (1020)
Start at 19:20:30
Duration 149.20s (transform 988ms, setup 0ms, collect 4.19s, tests 134.31s, environment 6ms, prepare 2.29s) — passed.
RUN v3.2.7 /private/tmp/miftah-issue37-threat-model
✓ tests/http-server.test.ts (15 tests) 3728ms
✓ Miftah Streamable HTTP server > keeps profile selection isolated across concurrent HTTP client sessions 588ms
✓ Miftah Streamable HTTP server > expires idle sessions and releases their retained upstream transport 1040ms
✓ Miftah Streamable HTTP server > keeps capacity reserved until a deleted session runtime has finished closing 556ms
✓ Miftah Streamable HTTP server > reserves capacity during concurrent initialization and releases it after DELETE 491ms
✓ tests/secret-providers.test.ts (89 tests | 11 skipped) 3874ms
✓ external secret providers > resolves default keychain and 1Password commands from absolute PATH entries 1786ms
✓ tests/executable-resolver.test.ts (4 tests) 885ms
✓ tests/routing-context.test.ts (21 tests) 923ms
✓ tests/config-migration.test.ts (21 tests) 126ms
✓ tests/secrets.test.ts (20 tests) 135ms
✓ tests/config-runtime-parity.test.ts (62 tests) 21ms
✓ tests/config.test.ts (56 tests) 16ms
✓ tests/config-diagnostics.test.ts (29 tests) 12ms
✓ tests/config-schema-contract.test.ts (8 tests) 14ms
✓ tests/config-public-contract.test.ts (4 tests) 10ms
✓ tests/windows-config-acl.test.ts (6 tests) 9ms
✓ tests/windows-config-migration-acl-failure.test.ts (1 test) 7ms
✓ tests/config-loader.test.ts (4 tests) 9ms
✓ tests/routing-policy.test.ts (24 tests) 8ms
✓ tests/secret-provider-availability.test.ts (8 tests | 2 skipped) 6ms
✓ tests/provider-routing-matchers.test.ts (14 tests) 5ms
✓ tests/profile-manager.test.ts (10 tests) 5ms
✓ tests/tooling-config.test.ts (4 tests) 3ms
✓ tests/presets.test.ts (4 tests) 3ms
✓ tests/provider-routing-matchers-docs-contract.test.ts (1 test) 3ms
↓ tests/windows-config-migration-acl.test.ts (9 tests | 9 skipped)
Test Files 21 passed | 1 skipped (22)
Tests 392 passed | 22 skipped (414)
Start at 19:23:00
Duration 14.76s (transform 480ms, setup 0ms, collect 1.02s, tests 9.80s, environment 2ms, prepare 714ms) — 392 passed, 22 expected platform skips.
RUN v3.2.7 /private/tmp/miftah-issue37-threat-model
Coverage enabled with v8
✓ tests/mcp-wrapper.test.ts (88 tests) 38238ms
✓ Miftah MCP wrapper > uses explicitly trusted tool annotations and records risk provenance 315ms
✓ Miftah MCP wrapper > scopes annotation trust to each named base upstream 393ms
✓ Miftah MCP wrapper > verifies requested named upstreams alone and all configured upstreams in sorted order 521ms
✓ Miftah MCP wrapper > invalidates passive identity status when a verified upstream profile restarts 455ms
✓ Miftah MCP wrapper > exposes management and upstream capabilities while routing calls by active profile 503ms
✓ Miftah MCP wrapper > routes a standard resource read through a canonical provider URI matcher 486ms
✓ Miftah MCP wrapper > uses the collector snapshot for matching redacted preview and audit evidence 515ms
✓ Miftah MCP wrapper > routes a client-visible multi-upstream GitHub tool through its static matcher binding 757ms
✓ Miftah MCP wrapper > records bounded canonical matcher evidence for an ambiguous proxied operation without forwarding it 623ms
✓ Miftah MCP wrapper > uses the same canonical matcher evidence for preview and successful proxied operation audits 766ms
✓ Miftah MCP wrapper > does not treat a static matcher as the explicit rule required for destructive operations 685ms
✓ Miftah MCP wrapper > propagates a cancelled tool call to the selected stdio upstream and records one terminal audit outcome 742ms
✓ Miftah MCP wrapper > propagates cancellation through initial tool discovery 748ms
✓ Miftah MCP wrapper > propagates cancellation through management tool discovery 748ms
✓ Miftah MCP wrapper > keeps shared tool discovery alive when one downstream caller cancels 827ms
✓ Miftah MCP wrapper > starts fresh tool discovery when a prior sole caller has cancelled 785ms
✓ Miftah MCP wrapper > fans shared tool discovery progress out to every downstream caller 474ms
✓ Miftah MCP wrapper > propagates cancellation through resource discovery 757ms
✓ Miftah MCP wrapper > aggregates concurrent upstream tool-discovery progress on one downstream token 473ms
✓ Miftah MCP wrapper > namespaces aggregated resource templates and routes instantiated reads to their origin upstream 370ms
✓ Miftah MCP wrapper > reports a stable unavailable error when no aggregated upstream implements resource templates 416ms
✓ Miftah MCP wrapper > proxies resource subscriptions to the selected upstream and namespaces update notifications 419ms
✓ Miftah MCP wrapper > forwards only updates for the subscribed resource 319ms
✓ Miftah MCP wrapper > does not forward an update from a subscription that fails before activation 323ms
✓ Miftah MCP wrapper > cleans up an upstream subscription that finishes after downstream cancellation 468ms
✓ Miftah MCP wrapper > releases a subscription after its unsubscribe request is cancelled 452ms
✓ Miftah MCP wrapper > bounds a pending subscription before switching profiles at capacity 802ms
✓ Miftah MCP wrapper > serializes cancelled subscription cleanup before a retry 1395ms
✓ Miftah MCP wrapper > fans one upstream resource update out to every matching static and template subscription 570ms
✓ Miftah MCP wrapper > re-establishes a resource subscription after its upstream restarts 359ms
✓ Miftah MCP wrapper > clears a direct resource subscription when its upstream lifecycle ends 373ms
✓ Miftah MCP wrapper > serializes overlapping resource subscription transitions before releasing idle capacity 398ms
✓ Miftah MCP wrapper > joins an in-flight unsubscribe before profile cleanup 458ms
✓ Miftah MCP wrapper > does not retain a subscription invalidated during its upstream handshake 517ms
✓ Miftah MCP wrapper > does not establish a captured-profile subscription after a profile switch 368ms
✓ Miftah MCP wrapper > keeps a resource subscription alive beyond the upstream idle timeout 348ms
✓ Miftah MCP wrapper > drops an old-profile resource subscription before a delayed update can be forwarded 519ms
✓ Miftah MCP wrapper > clears a routed third-profile subscription when the active profile changes 664ms
✓ Miftah MCP wrapper > bounds resource subscription cleanup while switching profiles 547ms
✓ Miftah MCP wrapper > releases subscription-capability probes before serving the active profile at capacity 360ms
✓ Miftah MCP wrapper > forwards upstream tools, resources, and prompts list-change notifications 307ms
✓ Miftah MCP wrapper > forwards a tool list change from a session first used for discovery 321ms
✓ Miftah MCP wrapper > does not reject a cold tool call when an idle upstream emits a list change 499ms
✓ Miftah MCP wrapper > clears a deferred tool invalidation when its list request is cancelled 507ms
✓ Miftah MCP wrapper > refreshes the advertised tool schema after a profile switch 517ms
✓ Miftah MCP wrapper > retries tool discovery when the active profile changes during listing 629ms
✓ Miftah MCP wrapper > rejects routing to a profile with a different advertised tool schema 555ms
✓ Miftah MCP wrapper > fails strict discovery when configured profiles expose different tool schemas 387ms
✓ Miftah MCP wrapper > invalidates strict discovery when a non-active profile becomes unavailable 479ms
✓ Miftah MCP wrapper > shares controlled discovery between a list request and a cold call 335ms
✓ Miftah MCP wrapper > invalidates a profile tool snapshot after an explicit restart 419ms
✓ Miftah MCP wrapper > linearizes a cold tool call before a concurrent profile switch 498ms
✓ Miftah MCP wrapper > collects runtime roots once and routes repeated proxied calls from the cached context 562ms
✓ Miftah MCP wrapper > routes proxied calls with empty roots when the initialized notification is dropped 406ms
✓ Miftah MCP wrapper > keeps a relative runtime config distinct from a later project marker 545ms
✓ Miftah MCP wrapper > keeps fallback routing usable without roots and preserves direct-server empty context 661ms
✓ Miftah MCP wrapper > falls back after a failed runtime roots request without retrying per operation 410ms
✓ Miftah MCP wrapper > refreshes advertised roots once and ignores unadvertised roots changes 1192ms
✓ Miftah MCP wrapper > refreshes again when roots change during an in-flight roots request 459ms
✓ Miftah MCP wrapper > uses exactly one routing context snapshot per proxied operation 541ms
✓ Miftah MCP wrapper > returns unknown context profile errors without forwarding the proxied call 389ms
✓ Miftah MCP wrapper > restores a workspace-scoped active profile and exposes safe selection metadata 526ms
✓ tests/package-contract.test.ts (16 tests) 19164ms
✓ packed artifact contract > keeps the test worker responsive while an npm subprocess is running 550ms
✓ packed artifact contract > includes captured output when an npm command exits unsuccessfully 325ms
✓ packed artifact contract > contains required runtime, documentation, and example files from a real dry run 391ms
✓ packed artifact contract > runs the checked package command against the real npm pack output 610ms
✓ packed artifact contract > loads the installed entry point and runs the installed binary from a real tarball 11370ms
✓ tests/multi-upstream.test.ts (28 tests) 11490ms
✓ multi-upstream wrapper > keeps healthy aggregate capabilities available when a bundled upstream cannot start 438ms
✓ multi-upstream wrapper > reports redacted capability discovery failures as degraded upstream health 423ms
✓ multi-upstream wrapper > fails strict tool discovery with a complete unavailable-upstream diagnostic 302ms
✓ multi-upstream wrapper > aggregates namespaced resources and routes each read to its originating upstream 360ms
✓ multi-upstream wrapper > removes stale routes when a bundled upstream fails resource discovery 377ms
✓ multi-upstream wrapper > removes stale routes when a bundled upstream fails prompt discovery 540ms
✓ multi-upstream wrapper > notifies clients when partial resource and prompt discovery recovers 590ms
✓ multi-upstream wrapper > rejects ambiguous namespaced resource and prompt collisions atomically 342ms
✓ multi-upstream wrapper > preserves independent upstream pagination through opaque aggregate cursors 363ms
✓ multi-upstream wrapper > notifies clients to re-list aggregated resources and prompts after a profile change 837ms
✓ multi-upstream wrapper > redacts configured and URI-embedded credentials before publishing a namespaced resource URI 377ms
✓ multi-upstream wrapper > uses controlled discovery to route cold namespaced reads and prompt gets exactly 407ms
✓ multi-upstream wrapper > routes a namespaced tool call before tools are listed 357ms
✓ multi-upstream wrapper > restarts every upstream in a profile bundle and invalidates its tool snapshot 642ms
✓ multi-upstream wrapper > recovers healthy tool discovery after a partial multi-upstream restart failure 840ms
✓ multi-upstream wrapper > refreshes the tool registry after an upstream crashes and later recovers 1154ms
✓ multi-upstream wrapper > waits for every bundled restart to settle before returning a restart failure 709ms
✓ multi-upstream wrapper > lists namespaced upstream tools through the deterministic registry 356ms
✓ multi-upstream wrapper > namespaces and routes tools from multiple upstream servers 381ms
✓ tests/upstream-manager.test.ts (26 tests) 7539ms
✓ upstream process manager > shuts down an idle profile and starts a fresh process on its next use 323ms
✓ upstream process manager > keeps a replacement session healthy and reserved while an idle predecessor is still closing 1578ms
✓ upstream process manager > does not restart a crashed process unless automatic recovery is configured 428ms
✓ upstream process manager > automatically recovers a crashed profile after a bounded backoff 328ms
✓ upstream process manager > stops automatic recovery when the configured restart budget is exhausted 794ms
✓ upstream process manager > records a failed restart teardown before starting a replacement session 330ms
✓ upstream process manager > cancels pending automatic recovery when the manager shuts down 431ms
✓ tests/operation-pipeline.test.ts (20 tests) 7838ms
✓ operation pipeline > verifies named upstream writes against their exact override or inherited identity 409ms
✓ operation pipeline > rejects ambiguous resource and prompt routes before forwarding them upstream 529ms
✓ operation pipeline > does not forward destructive calls when project context profile hints conflict 380ms
✓ operation pipeline > routes resource reads and prompt retrieval to the selected profile 369ms
✓ operation pipeline > keeps in-flight resource and prompt operations bound to their captured profile 575ms
✓ operation pipeline > completes in-flight aggregate reads and prompts after a profile switch 810ms
✓ operation pipeline > retries cold aggregate route discovery against the captured profile after a switch 1312ms
✓ operation pipeline > checks aggregate resource and prompt policy before discovering upstream routes 340ms
✓ operation pipeline > redacts credential-bearing resource URIs before writing audit metadata 306ms
✓ operation pipeline > redacts credential-bearing unknown resource URIs in diagnostics 375ms
✓ operation pipeline > redacts sensitive URI components from direct resource and prompt metadata 303ms
✓ tests/audit-outcomes.test.ts (15 tests) 4320ms
✓ audit outcomes > records one terminal operation event for list, management, and unknown-tool requests 541ms
✓ audit outcomes > keeps MCP results available and exposes audit health when fail-open writes fail 444ms
✓ audit outcomes > records upstream crash and automatic recovery outcomes 516ms
✓ tests/doctor.test.ts (22 tests) 4201ms
✓ doctor readiness runner > accepts a relative executable resolved from its configured working directory 805ms
✓ doctor readiness runner > reports profile tool schema differences as warnings or strict errors 479ms
✓ tests/identity-manager.test.ts (23 tests) 4299ms
✓ identity verifier > forwards cancellation through identity probe discovery 683ms
✓ identity verifier > keeps a shared identity probe alive when one request cancels 628ms
✓ tests/approval-fallback.test.ts (23 tests) 4678ms
✓ tests/remote-transport.test.ts (11 tests) 4124ms
✓ remote upstream transports > forces local cleanup when a Streamable HTTP session DELETE hangs 3821ms
✓ tests/secret-providers.test.ts (89 tests | 11 skipped) 2559ms
✓ external secret providers > resolves default keychain and 1Password commands from absolute PATH entries 754ms
✓ tests/http-server.test.ts (15 tests) 3738ms
✓ Miftah Streamable HTTP server > bounds oversized JSON requests before they can reserve a session 311ms
✓ Miftah Streamable HTTP server > keeps profile selection isolated across concurrent HTTP client sessions 505ms
✓ Miftah Streamable HTTP server > reconnects an interrupted SSE stream to the existing session without creating another runtime 333ms
✓ Miftah Streamable HTTP server > expires idle sessions and releases their retained upstream transport 1033ms
✓ Miftah Streamable HTTP server > keeps capacity reserved until a deleted session runtime has finished closing 538ms
✓ Miftah Streamable HTTP server > reserves capacity during concurrent initialization and releases it after DELETE 519ms
✓ tests/audit-integrity.test.ts (20 tests) 3012ms
✓ audit journal integrity > compacts integrity metadata when retention removes every rotated archive 1065ms
✓ tests/audit-log-reader.test.ts (35 tests) 2198ms
✓ logs command integration > follows a managed rotation that completes before its next poll 562ms
✓ tests/audit.test.ts (24 tests) 1834ms
✓ audit logger > serializes concurrent logger instances through the journal lock at a rotation boundary 1502ms
✓ tests/profile-lease-pipeline.test.ts (6 tests) 1534ms
✓ profile leases in the operation pipeline > does not let a routed profile borrow the active profile's lease 474ms
✓ tests/plugin-api.test.ts (13 tests) 1221ms
✓ tests/profile-runtime-isolation.test.ts (23 tests) 961ms
✓ tests/profile-lock-mcp.test.ts (3 tests) 989ms
✓ MCP profile locks > exposes opt-in connection-bound lock controls and safe profile state 381ms
✓ MCP profile locks > keeps lock controls discoverable but rejects calls while the opt-in is disabled 369ms
✓ tests/routing-context.test.ts (21 tests) 962ms
✓ tests/executable-resolver.test.ts (4 tests) 870ms
✓ tests/plugin-routing-server.test.ts (1 test) 705ms
✓ plugin routing server integration > uses configured routing plugins for real proxied MCP tool calls 705ms
✓ tests/config-preflight.test.ts (4 tests) 554ms
✓ tests/profile-transition-audit-barrier.test.ts (1 test) 519ms
✓ profile transition audit barrier > does not expose a new profile lease to concurrent calls before its required audit transition commits 518ms
✓ tests/public-api.test.ts (4 tests) 255ms
✓ tests/secrets.test.ts (20 tests) 135ms
✓ tests/config-migration.test.ts (21 tests) 141ms
✓ tests/plugin-routing-pipeline.test.ts (1 test) 115ms
✓ tests/fake-upstream-fixture.test.ts (1 test) 108ms
✓ tests/audit-verify.test.ts (2 tests) 105ms
✓ tests/audit-export.test.ts (6 tests) 106ms
✓ tests/profile-state.test.ts (10 tests) 77ms
✓ tests/negative-paths.test.ts (5 tests) 69ms
✓ tests/init-command.test.ts (10 tests) 22ms
✓ tests/managed-audit-follow.test.ts (1 test) 23ms
✓ tests/config-runtime-parity.test.ts (62 tests) 19ms
✓ tests/runtime-config-resolution.test.ts (4 tests) 15ms
✓ tests/config.test.ts (56 tests) 18ms
✓ tests/config-schema-contract.test.ts (8 tests) 16ms
✓ tests/approval-store.test.ts (11 tests) 15ms
✓ tests/audit-journal-path-safety.test.ts (1 test) 16ms
✓ tests/config-diagnostics.test.ts (29 tests) 12ms
✓ tests/config-public-contract.test.ts (4 tests) 12ms
✓ tests/preset-catalog.test.ts (31 tests) 13ms
✓ tests/windows-config-acl.test.ts (6 tests) 10ms
✓ tests/config-loader.test.ts (4 tests) 8ms
✓ tests/resource-prompt-registry.test.ts (13 tests) 8ms
✓ tests/release-config.test.ts (18 tests) 8ms
✓ tests/profile-runtime-isolation-docs-contract.test.ts (2 tests) 4ms
✓ tests/identity-docs-contract.test.ts (2 tests) 7ms
✓ tests/routing-policy.test.ts (24 tests) 7ms
✓ tests/doctor-report.test.ts (10 tests) 11ms
✓ tests/tool-registry.test.ts (1 test) 9ms
✓ tests/windows-config-migration-acl-failure.test.ts (1 test) 8ms
✓ tests/secret-provider-availability.test.ts (8 tests | 2 skipped) 7ms
✓ tests/preset-docs-contract.test.ts (1 test) 6ms
✓ tests/routing-context-docs-contract.test.ts (1 test) 2ms
✓ tests/profile-manager.test.ts (10 tests) 5ms
✓ tests/logs-writer.test.ts (4 tests) 6ms
✓ tests/provider-routing-matchers.test.ts (14 tests) 5ms
✓ tests/windows-secret-command-contract.test.ts (2 tests) 2ms
✓ tests/client-snippets.test.ts (30 tests) 5ms
✓ tests/release-version.test.ts (4 tests) 5ms
✓ tests/cli-parse.test.ts (10 tests) 4ms
✓ tests/profile-state-docs-contract.test.ts (1 test) 3ms
✓ tests/provider-routing-matchers-docs-contract.test.ts (1 test) 3ms
✓ tests/presets.test.ts (4 tests) 3ms
✓ tests/tooling-config.test.ts (4 tests) 4ms
✓ tests/threat-model-docs-contract.test.ts (2 tests) 4ms
✓ tests/progress-preserving-transport.test.ts (7 tests) 4ms
✓ tests/profile-leases-docs-contract.test.ts (1 test) 6ms
✓ tests/secret-provider-docs-contract.test.ts (3 tests) 3ms
✓ tests/risk-classification-docs-contract.test.ts (1 test) 2ms
✓ tests/approval-docs-contract.test.ts (1 test) 2ms
✓ tests/cli-exit-codes.test.ts (3 tests) 2ms
↓ tests/windows-config-migration-acl.test.ts (9 tests | 9 skipped)
Test Files 75 passed | 1 skipped (76)
Tests 998 passed | 22 skipped (1020)
Start at 19:23:15
Duration 146.13s (transform 1.02s, setup 0ms, collect 4.24s, tests 129.00s, environment 8ms, prepare 2.91s)
% Coverage report from v8
-------------------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
-------------------|---------|----------|---------|---------|-------------------
All files | 95.46 | 92.04 | 98.27 | 95.46 |
config | 95.76 | 93.33 | 100 | 95.76 |
diagnostics.ts | 96.77 | 93.93 | 100 | 96.77 | 18-19
env-expand.ts | 100 | 100 | 100 | 100 |
...son-schema.ts | 98.96 | 93.75 | 100 | 98.96 | 9-10
load-config.ts | 94.4 | 86.27 | 100 | 94.4 | 98-104
...ate-config.ts | 98.09 | 96 | 100 | 98.09 | 107-108
path-resolve.ts | 100 | 75 | 100 | 100 | 5
presets.ts | 96.73 | 94.56 | 100 | 96.73 | ...51-252,262-263
schema.ts | 94.99 | 94.48 | 100 | 94.99 | ...-819,1117-1125
types.ts | 0 | 0 | 0 | 0 |
...ate-config.ts | 90.38 | 86.66 | 100 | 90.38 | 22,59-60,62-63
versions.ts | 100 | 100 | 100 | 100 |
mcp/server | 97.9 | 93.64 | 98.92 | 97.9 |
...n-pipeline.ts | 100 | 96.9 | 100 | 100 | 105,217,273
...t-registry.ts | 97.45 | 92.1 | 98.14 | 97.45 | ...78,693,762-763
tool-registry.ts | 97.47 | 94.49 | 100 | 97.47 | 194-198
secrets | 94.56 | 90.49 | 96.33 | 94.56 |
...-providers.ts | 100 | 90 | 100 | 100 | 56,77,84
...e-resolver.ts | 100 | 89.79 | 100 | 100 | 21,25,60-61
...-providers.ts | 95.12 | 92 | 94.73 | 95.12 | ...83-284,294-295
...-reference.ts | 97.89 | 95.91 | 100 | 97.89 | 99-100
redact.ts | 96.13 | 94.73 | 100 | 96.13 | ...63-264,276-280
...ess-runner.ts | 86.97 | 81.69 | 94.11 | 86.97 | ...67,180-182,239
...ailability.ts | 94.93 | 81.57 | 100 | 94.93 | 85-86,100-101
...t-provider.ts | 0 | 0 | 0 | 0 |
...t-resolver.ts | 93.98 | 91.89 | 85.71 | 93.98 | ...08,214,224-226
upstream | 92.98 | 90.06 | 98.52 | 92.98 |
remote-error.ts | 91.66 | 80 | 100 | 91.66 | 41-42,50-51
...ss-manager.ts | 93.06 | 90.7 | 98.38 | 93.06 | ...22-823,884-885
-------------------|---------|----------|---------|---------|-------------------,
CLI Building entry: {"cli/main":"src/cli/main.ts","index":"src/index.ts","plugin-api":"src/plugins/plugin-api.ts","plugin-host":"src/plugin-host.mjs"}
CLI Using tsconfig: tsconfig.json
CLI tsup v8.5.1
CLI Using tsup config: /private/tmp/miftah-issue37-threat-model/tsup.config.ts
CLI Target: es2022
CLI Cleaning output folder
ESM Build start
ESM dist/index.js 440.00 B
ESM dist/chunk-FY43IYAP.js 170.00 B
ESM dist/plugin-api.js 165.00 B
ESM dist/plugin-host.js 4.85 KB
ESM dist/cli/main.js 136.40 KB
ESM dist/chunk-R67JK7EH.js 552.47 KB
ESM dist/index.js.map 71.00 B
ESM dist/chunk-FY43IYAP.js.map 2.61 KB
ESM dist/plugin-host.js.map 8.60 KB
ESM dist/plugin-api.js.map 71.00 B
ESM dist/cli/main.js.map 252.91 KB
ESM dist/chunk-R67JK7EH.js.map 1.03 MB
ESM ⚡️ Build success in 38ms
DTS Build start
DTS ⚡️ Build success in 4515ms
DTS dist/cli/main.d.ts 73.00 B
DTS dist/index.d.ts 17.86 KB
DTS dist/plugin-host.d.ts 4.83 KB
DTS dist/plugin-api.d.ts 2.72 KB,
{
"type": "object",
"properties": {
"version": {
"type": "string",
"enum": [
"1",
"2"
]
},
"name": {
"type": "string",
"minLength": 1
},
"description": {
"type": "string"
},
"defaultProfile": {
"type": "string",
"minLength": 1
},
"upstream": {
"type": "object",
"properties": {
"transport": {
"type": "string",
"enum": [
"stdio",
"http",
"sse",
"streamable-http"
]
},
"command": {
"type": "string",
"minLength": 1
},
"args": {
"type": "array",
"items": {
"type": "string"
}
},
"env": {
"type": "object",
"additionalProperties": {
"type": "string"
}
},
"cwd": {
"type": "string"
},
"url": {
"type": "string",
"format": "uri"
},
"headers": {
"type": "object",
"additionalProperties": {
"type": "string"
}
},
"trustToolAnnotations": {
"type": "boolean"
}
},
"required": [
"transport"
],
"additionalProperties": false
},
"upstreams": {
"type": "object",
"additionalProperties": {
"$ref": "#/properties/upstream"
}
},
"profiles": {
"type": "object",
"additionalProperties": {
"type": "object",
"properties": {
"description": {
"type": "string"
},
"tags": {
"type": "array",
"items": {
"type": "string"
}
},
"env": {
"type": "object",
"additionalProperties": {
"type": "string"
}
},
"args": {
"type": "array",
"items": {
"type": "string"
}
},
"cwd": {
"type": "string"
},
"headers": {
"type": "object",
"additionalProperties": {
"type": "string"
}
},
"policy": {
"type": "string"
},
"identity": {
"type": "object",
"properties": {
"expected": {
"type": "object",
"properties": {
"provider": {
"type": "string",
"minLength": 1,
"maxLength": 256
},
"login": {
"$ref": "#/properties/profiles/additionalProperties/properties/identity/properties/expected/properties/provider"
},
"organization": {
"$ref": "#/properties/profiles/additionalProperties/properties/identity/properties/expected/properties/provider"
},
"host": {
"$ref": "#/properties/profiles/additionalProperties/properties/identity/properties/expected/properties/provider"
}
},
"additionalProperties": false
},
"probe": {
"type": "object",
"properties": {
"tool": {
"type": "string",
"minLength": 1,
"maxLength": 256
},
"resultFormat": {
"type": "string",
"enum": [
"text",
"json"
]
},
"provider": {
"$ref": "#/properties/profiles/additionalProperties/properties/identity/properties/expected/properties/provider"
}
},
"required": [
"tool",
"resultFormat"
],
"additionalProperties": false
},
"maxAgeMs": {
"type": "integer",
"exclusiveMinimum": true,
"minimum": 0,
"maximum": 86400000
},
"requiredForRisk": {
"type": "array",
"items": {
"type": "string",
"enum": [
"write",
"destructive"
]
},
"minItems": 1
}
},
"required": [
"expected",
"probe",
"maxAgeMs"
],
"additionalProperties": false
},
"lease": {
"type": "object",
"properties": {
"ttlMs": {
"type": "integer",
"minimum": 1000,
"maximum": 3600000
},
"requiredForRisk": {
"type": "array",
"items": {
"type": "string",
"enum": [
"write",
"destructive"
]
},
"minItems": 1,
"maxItems": 2,
"uniqueItems": true
}
},
"required": [
"ttlMs",
"requiredForRisk"
],
"additionalProperties": false
},
"isolation": {
"type": "object",
"properties": {
"files": {
"type": "array",
"items": {
"type": "object",
"properties": {
"source": {
"type": "string",
"minLength": 1,
"maxLength": 512,
"pattern": "^(?![A-Za-z]:)(?![\\/])(?!.(?:^|[\\/])(?:\.{1,2})(?:[\\/]|$))[^\\\\/\\u0000]+(?:[\\/][^\\\\/\\u0000]+)$"
},
"destination": {
"$ref": "#/properties/profiles/additionalProperties/properties/isolation/properties/files/items/properties/source"
},
"environment": {
"type": "string",
"pattern": "^[A-Za-z_][A-Za-z0-9_]{0,127}$"
}
},
"required": [
"source",
"destination"
],
"additionalProperties": false
},
"maxItems": 32,
"uniqueItems": true
},
"containerVolumes": {
"type": "array",
"items": {
"type": "object",
"properties": {
"source": {
"type": "string",
"minLength": 1,
"maxLength": 512,
"pattern": "^(?![A-Za-z]:)(?![\\/])(?!.(?:^|[\\/])(?:\.{1,2})(?:[\\/]|$))[^\\\\/,\\u0000]+(?:[\\/][^\\\\/,\\u0000]+)$"
},
"destination": {
"type": "string",
"minLength": 1,
"maxLength": 512,
"pattern": "^\/(?!.(?:^|\/)(?:\.{1,2})(?:\/|$))[^\\\\/,\\u0000]+(?:\/[^\\\\/,\\u0000]+)$"
},
"readOnly": {
"type": "boolean"
},
"environment": {
"$ref": "#/properties/profiles/additionalProperties/properties/isolation/properties/files/items/properties/environment"
}
},
"required": [
"source",
"destination"
],
"additionalProperties": false
},
"maxItems": 32,
"uniqueItems": true
}
},
"additionalProperties": false
},
"routing": {
"type": "object",
"properties": {
"match": {
"type": "object",
"properties": {
"github": {
"type": "object",
"properties": {
"repositories": {
"type": "array",
"items": {
"type": "string",
"pattern": "^[a-z0-9][a-z0-9_.-]{0,99}\/[a-z0-9][a-z0-9_.-]{0,99}$"
},
"minItems": 1,
"maxItems": 32,
"uniqueItems": true
},
"organizations": {
"type": "array",
"items": {
"type": "string",
"pattern": "^a-z0-9$"
},
"minItems": 1,
"maxItems": 32,
"uniqueItems": true
}
},
"additionalProperties": false,
"minProperties": 1
},
"sentry": {
"type": "object",
"properties": {
"organizations": {
"type": "array",
"items": {
"type": "string",
"pattern": "^[a-z0-9][a-z0-9_-]{0,127}$"
},
"minItems": 1,
"maxItems": 32,
"uniqueItems": true
},
"projects": {
"type": "array",
"items": {
"type": "string",
"pattern": "^[a-z0-9][a-z0-9_-]{0,127}\/[a-z0-9][a-z0-9_-]{0,127}$"
},
"minItems": 1,
"maxItems": 32,
"uniqueItems": true
},
"environments": {
"type": "array",
"items": {
"type": "string",
"pattern": "^[A-Za-z0-9][A-Za-z0-9.-]{0,127}$"
},
"minItems": 1,
"maxItems": 32,
"uniqueItems": true
}
},
"additionalProperties": false,
"minProperties": 1
},
"jira": {
"type": "object",
"properties": {
"sites": {
"type": "array",
"items": {
"type": "string",
"maxLength": 256,
"pattern": "^https:\/\/(?!.:443$)(?:a-z0-9?)(?:\.(?:a-z0-9?))(?::(?:[1-9][0-9]{0,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5]))?$"
},
"minItems": 1,
"maxItems": 32,
"uniqueItems": true
},
"projects": {
"type": "array",
"items": {
"type": "string",
"pattern": "^[A-Z][A-Z0-9]{0,9}$"
},
"minItems": 1,
"maxItems": 32,
"uniqueItems": true
}
},
"additionalProperties": false,
"minProperties": 1
},
"linear": {
"type": "object",
"properties": {
"workspaces": {
"type": "array",
"items": {
"type": "string",
"pattern": "^[a-z0-9][a-z0-9-]{0,127}$"
},
"minItems": 1,
"maxItems": 32,
"uniqueItems": true
},
"teams": {
"type": "array",
"items": {
"$ref": "#/properties/profiles/additionalProperties/properties/routing/properties/match/properties/linear/properties/workspaces/items"
},
"minItems": 1,
"maxItems": 32,
"uniqueItems": true
}
},
"additionalProperties": false,
"minProperties": 1
},
"posthog": {
"type": "object",
"properties": {
"hosts": {
"type": "array",
"items": {
"$ref": "#/properties/profiles/additionalProperties/properties/routing/properties/match/properties/jira/properties/sites/items",
"pattern": "^https:\/\/(?!.:443$)(?:a-z0-9?)(?:\.(?:a-z0-9?))(?::(?:[1-9][0-9]{0,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5]))?$"
},
"minItems": 1,
"maxItems": 32,
"uniqueItems": true
},
"projects": {
"type": "array",
"items": {
"type": "string",
"pattern": "^[1-9][0-9]{0,17}$"
},
"minItems": 1,
"maxItems": 32,
"uniqueItems": true
}
},
"additionalProperties": false,
"minProperties": 1
}
},
"additionalProperties": false,
"minProperties": 1
}
},
"required": [
"match"
],
"additionalProperties": false
},
"upstreams": {
"type": "object",
"additionalProperties": {
"type": "object",
"properties": {
"args": {
"type": "array",
"items": {
"type": "string"
}
},
"env": {
"type": "object",
"additionalProperties": {
"type": "string"
}
},
"cwd": {
"type": "string"
},
"headers": {
"type": "object",
"additionalProperties": {
"type": "string"
}
},
"identity": {
"$ref": "#/properties/profiles/additionalProperties/properties/identity"
},
"isolation": {
"$ref": "#/properties/profiles/additionalProperties/properties/isolation"
}
},
"additionalProperties": false
}
}
},
"additionalProperties": false
}
},
"routing": {
"type": "object",
"properties": {
"mode": {
"type": "string",
"const": "hybrid"
},
"fallback": {
"type": "string",
"enum": [
"default",
"activeProfile",
"ask",
"block"
]
},
"rules": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"when": {
"type": "object",
"additionalProperties": {}
},
"profile": {
"type": "string",
"minLength": 1
}
},
"required": [
"when",
"profile"
],
"additionalProperties": false
}
}
},
"additionalProperties": false
},
"policies": {
"type": "object",
"additionalProperties": {
"type": "object",
"properties": {
"allow": {
"type": "array",
"items": {
"type": "string",
"enum": [
"read",
"write",
"destructive"
]
}
},
"allowRisk": {
"type": "array",
"items": {
"type": "string",
"enum": [
"read",
"write",
"destructive"
]
}
},
"deny": {
"type": "array",
"items": {
"type": "string"
}
},
"denyRisk": {
"type": "array",
"items": {
"type": "string",
"enum": [
"read",
"write",
"destructive"
]
}
},
"requireConfirmation": {
"type": "array",
"items": {
"type": "string"
}
}
},
"additionalProperties": false
}
},
"security": {
"type": "object",
"properties": {
"allowPlaintextSecrets": {
"type": "boolean"
},
"redactSecrets": {
"type": "boolean",
"const": true
},
"allowProfileSwitchingFromMcp": {
"type": "boolean"
},
"requireProfileSwitchConfirmation": {
"type": "boolean"
},
"allowProfileLockingFromMcp": {
"type": "boolean"
},
"requireExplicitProfileForDestructive": {
"type": "boolean"
},
"requireExplicitSelectionForDestructive": {
"type": "boolean"
},
"lockToProfile": {
"type": [
"string",
"null"
]
}
},
"additionalProperties": false
},
"process": {
"type": "object",
"properties": {
"startupTimeoutMs": {
"type": "integer",
"exclusiveMinimum": true,
"minimum": 0
},
"shutdownTimeoutMs": {
"type": "integer",
"exclusiveMinimum": true,
"minimum": 0
},
"idleTimeoutMs": {
"type": "integer",
"exclusiveMinimum": true,
"minimum": 0
},
"restartOnCrash": {
"type": "boolean"
},
"maxRestarts": {
"type": "integer",
"minimum": 0
},
"maxConcurrentProfiles": {
"type": "integer",
"exclusiveMinimum": true,
"minimum": 0
}
},
"additionalProperties": false
},
"audit": {
"type": "object",
"properties": {
"enabled": {
"type": "boolean"
},
"path": {
"type": "string",
"minLength": 1
},
"format": {
"type": "string",
"const": "jsonl"
},
"includeArguments": {
"type": "boolean"
},
"redact": {
"type": "boolean",
"const": true
},
"failureMode": {
"type": "string",
"enum": [
"fail-open",
"fail-closed"
]
},
"rotation": {
"type": "object",
"properties": {
"maxBytes": {
"type": "integer",
"exclusiveMinimum": true,
"minimum": 0,
"maximum": 2147483647
},
"maxAgeMs": {
"type": "integer",
"exclusiveMinimum": true,
"minimum": 0,
"maximum": 31536000000
},
"retainFiles": {
"type": "integer",
"minimum": 0,
"maximum": 2000
}
},
"required": [
"retainFiles"
],
"additionalProperties": false,
"anyOf": [
{
"required": [
"maxBytes"
]
},
{
"required": [
"maxAgeMs"
]
}
]
},
"integrity": {
"type": "object",
"properties": {
"algorithm": {
"type": "string",
"const": "sha256-chain"
}
},
"required": [
"algorithm"
],
"additionalProperties": false
}
},
"additionalProperties": false
},
"tooling": {
"type": "object",
"properties": {
"collisionStrategy": {
"type": "string",
"enum": [
"prefix-upstream",
"fail"
]
},
"toolDiscoveryMode": {
"type": "string",
"enum": [
"permissive",
"strict"
]
},
"toolRiskOverrides": {
"type": "object",
"additionalProperties": {
"type": "string",
"enum": [
"read",
"write",
"destructive"
]
}
},
"unknownToolRisk": {
"type": "string",
"enum": [
"write",
"destructive"
]
}
},
"additionalProperties": false
},
"secrets": {
"type": "object",
"properties": {
"envFiles": {
"type": "array",
"items": {
"type": "string"
}
},
"allowPlaintextSecrets": {
"type": "boolean"
},
"providerTimeoutMs": {
"type": "integer",
"minimum": 100,
"maximum": 120000
}
},
"additionalProperties": false
},
"plugins": {
"type": "object",
"properties": {
"allowlist": {
"type": "array",
"items": {
"anyOf": [
{
"type": "object",
"properties": {
"id": {
"type": "string",
"pattern": "^[a-z][a-z0-9-]{0,63}$"
},
"kind": {
"type": "string",
"const": "secret-provider"
},
"path": {
"type": "string",
"pattern": "^\.\/(?:[A-Za-z0-9][A-Za-z0-9.-]\/)[A-Za-z0-9][A-Za-z0-9.-]*\.mjs$"
}
},
"required": [
"id",
"kind",
"path"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"id": {
"$ref": "#/properties/plugins/properties/allowlist/items/anyOf/0/properties/id"
},
"kind": {
"type": "string",
"const": "routing-matcher"
},
"path": {
"$ref": "#/properties/plugins/properties/allowlist/items/anyOf/0/properties/path"
},
"bindings": {
"type": "object",
"additionalProperties": {
"type": "string",
"minLength": 1,
"maxLength": 256
},
"propertyNames": {
"pattern": "^[a-z0-9][a-z0-9._-]{0,127}$"
}
}
},
"required": [
"id",
"kind",
"path",
"bindings"
],
"additionalProperties": false
}
]
},
"minItems": 1,
"maxItems": 32
},
"timeoutMs": {
"type": "integer",
"minimum": 100,
"maximum": 60000
}
},
"required": [
"allowlist"
],
"additionalProperties": false
},
"state": {
"type": "object",
"properties": {
"persistActiveProfile": {
"type": "boolean"
},
"scope": {
"type": "string",
"enum": [
"process",
"session",
"workspace",
"global"
]
}
},
"additionalProperties": false
},
"server": {
"type": "object",
"properties": {
"http": {
"type": "object",
"properties": {
"host": {
"type": "string",
"minLength": 1,
"maxLength": 253
},
"port": {
"type": "integer",
"minimum": 0,
"maximum": 65535
},
"allowNonLoopback": {
"type": "boolean",
"const": true
},
"authToken": {
"type": "string",
"minLength": 1,
"maxLength": 4096
},
"allowedHosts": {
"type": "array",
"items": {
"$ref": "#/properties/server/properties/http/properties/host"
},
"minItems": 1,
"maxItems": 64
},
"allowedOrigins": {
"type": "array",
"items": {
"type": "string",
"minLength": 1,
"maxLength": 2048
},
"maxItems": 64
},
"maxSessions": {
"type": "integer",
"minimum": 1,
"maximum": 256
},
"sessionIdleTimeoutMs": {
"type": "integer",
"minimum": 1000,
"maximum": 86400000
},
"maxRequestBytes": {
"type": "integer",
"minimum": 1024,
"maximum": 10485760
}
},
"additionalProperties": false
}
},
"additionalProperties": false
}
},
"required": [
"version",
"name",
"defaultProfile",
"profiles"
],
"additionalProperties": false,
"$schema": "https://json-schema.org/draft/2019-09/schema#",
"allOf": [
{
"oneOf": [
{
"required": [
"upstream"
]
},
{
"required": [
"upstreams"
]
}
]
},
{
"if": {
"required": [
"state"
],
"properties": {
"state": {
"required": [
"persistActiveProfile"
],
"properties": {
"persistActiveProfile": {
"const": true
}
}
}
}
},
"then": {
"properties": {
"state": {
"required": [
"scope"
],
"properties": {
"scope": {
"enum": [
"workspace",
"global"
]
}
}
}
}
}
},
{
"if": {
"required": [
"state"
],
"properties": {
"state": {
"required": [
"scope"
],
"properties": {
"scope": {
"enum": [
"workspace",
"global"
]
}
}
}
}
},
"then": {
"properties": {
"state": {
"required": [
"persistActiveProfile"
],
"properties": {
"persistActiveProfile": {
"const": true
}
}
}
}
}
},
{
"if": {
"required": [
"audit"
],
"properties": {
"audit": {
"anyOf": [
{
"required": [
"rotation"
]
},
{
"required": [
"integrity"
]
}
]
}
}
},
"then": {
"properties": {
"audit": {
"required": [
"path"
],
"properties": {
"enabled": {
"not": {
"const": false
}
}
}
}
}
}
},
{
"if": {
"required": [
"version"
],
"properties": {
"version": {
"const": "2"
}
}
},
"then": {
"allOf": [
{
"not": {
"required": [
"security"
],
"properties": {
"security": {
"required": [
"allowPlaintextSecrets"
]
}
}
}
},
{
"not": {
"required": [
"security"
],
"properties": {
"security": {
"required": [
"redactSecrets"
]
}
}
}
},
{
"not": {
"required": [
"audit"
],
"properties": {
"audit": {
"required": [
"redact"
]
}
}
}
},
{
"not": {
"required": [
"upstream"
],
"properties": {
"upstream": {
"required": [
"transport"
],
"properties": {
"transport": {
"const": "http"
}
}
}
}
}
},
{
"properties": {
"upstreams": {
"additionalProperties": {
"not": {
"required": [
"transport"
],
"properties": {
"transport": {
"const": "http"
}
}
}
}
}
}
}
]
}
}
],
"title": "Miftah configuration"
},
Package contract verified (41 files)., and
RUN v3.2.7 /private/tmp/miftah-issue37-threat-model
✓ tests/package-contract.test.ts (16 tests) 18728ms
✓ packed artifact contract > keeps the test worker responsive while an npm subprocess is running 513ms
✓ packed artifact contract > includes captured output when an npm command exits unsuccessfully 327ms
✓ packed artifact contract > contains required runtime, documentation, and example files from a real dry run 393ms
✓ packed artifact contract > runs the checked package command against the real npm pack output 610ms
✓ packed artifact contract > loads the installed entry point and runs the installed binary from a real tarball 10885ms
Test Files 1 passed (1)
Tests 16 passed (16)
Start at 19:25:55
Duration 18.91s (transform 50ms, setup 0ms, collect 49ms, tests 18.73s, environment 0ms, prepare 29ms) — passed.
Issue status
This delivers the documentation portion of #37. The independent external review remains uncommissioned and is explicitly recorded as a release-blocking follow-up; this PR does not claim external assurance or close the issue.