@muhaven/mcp 0.2.3 → 0.2.5
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/CHANGELOG.md +77 -0
- package/dist/broker.cjs +2 -2
- package/dist/broker.js +2 -2
- package/dist/index.cjs +28 -4
- package/dist/index.d.cts +11 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +28 -4
- package/manifest.json +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,83 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.2.5] — 2026-05-23
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- **`PLACEHOLDER_SIGNATURE` size 86 bytes → 66 bytes** to match the
|
|
15
|
+
real Kernel v3.1 PermissionValidator signature shape that
|
|
16
|
+
`buildKernelSessionKeySignature` produces:
|
|
17
|
+
|
|
18
|
+
byte 0 — 0xff (PermissionValidator "use root permission" sentinel)
|
|
19
|
+
bytes 1..65 — 65-byte ECDSA
|
|
20
|
+
= 66 bytes total
|
|
21
|
+
|
|
22
|
+
Pre-0.2.5 the placeholder was 86 bytes — the OLD enable-mode shape
|
|
23
|
+
(1 byte prefix + 20 bytes validator + 65 bytes ECDSA). The paymaster
|
|
24
|
+
simulated the validator with the wrong-length signature, the
|
|
25
|
+
validator reverted with `AA23 reverted`, and
|
|
26
|
+
`zd_sponsorUserOperation` returned rpc_error → MCP mapped to
|
|
27
|
+
`paymaster_rejected`. This is the load-bearing piece that 0.2.4 did
|
|
28
|
+
NOT close.
|
|
29
|
+
|
|
30
|
+
### Added
|
|
31
|
+
|
|
32
|
+
- **`pathDFallbackDetail` in the `muhaven.position.buy` echo.** Every
|
|
33
|
+
Path D fallback (`bundler_setup_failed`, `paymaster_rejected`,
|
|
34
|
+
`encrypt_shares_server_error`, etc.) now carries the underlying
|
|
35
|
+
error message in addition to the structured reason code. Pre-0.2.5
|
|
36
|
+
the message was dropped → every new gate required curl repro to
|
|
37
|
+
find the actual error class (cost ~2 publish cycles during the
|
|
38
|
+
2026-05-23 smoke). Future fallback iterations are self-diagnosing.
|
|
39
|
+
Untrusted-network input (bundler RPC error messages) is sanitized
|
|
40
|
+
server-side before crossing into the echo (existing
|
|
41
|
+
`sanitizeRpcMessageForLlmContext` boundary).
|
|
42
|
+
|
|
43
|
+
### Changed
|
|
44
|
+
|
|
45
|
+
- **`DEFAULT_REQUEST_TIMEOUT_MS` 15s → 75s.** The cold-start FHE
|
|
46
|
+
encrypt at `/api/v1/agent/path-d/encrypt-shares` costs ~25s on
|
|
47
|
+
first call after fhe-worker container boot (CoFHE verifier-
|
|
48
|
+
signature handshake). The 15s default cut the MCP-side fetch
|
|
49
|
+
before the backend's reply arrived → spurious
|
|
50
|
+
`encrypt_shares_server_error`. Operators on warm setups can
|
|
51
|
+
tighten via `MUHAVEN_REQUEST_TIMEOUT_MS`. Subsequent encrypts
|
|
52
|
+
after warm-up are sub-second; the 75s ceiling is defensive
|
|
53
|
+
headroom, not steady-state latency.
|
|
54
|
+
|
|
55
|
+
## [0.2.4] — 2026-05-23
|
|
56
|
+
|
|
57
|
+
### Fixed
|
|
58
|
+
|
|
59
|
+
- **Paymaster RPC method + param shape**:
|
|
60
|
+
`pm_sponsorUserOperation` → `zd_sponsorUserOperation`. ZeroDev v3
|
|
61
|
+
endpoints route paymaster RPCs through Alchemy infrastructure, which
|
|
62
|
+
exposes only ERC-7677 (`pm_getPaymasterStubData` / `pm_getPaymasterData`)
|
|
63
|
+
and ZeroDev-prefixed (`zd_sponsorUserOperation`) — the legacy
|
|
64
|
+
`pm_sponsorUserOperation` returns `"Unsupported method"` from
|
|
65
|
+
Alchemy. The MCP server's `attemptPathD` failed at
|
|
66
|
+
`pathDFallbackReason: paymaster_rejected` on every Path D autonomous
|
|
67
|
+
buy. Fix: switch method name + change request shape from positional
|
|
68
|
+
`[userOp, entryPoint]` to wrapped
|
|
69
|
+
`[{chainId, userOp, entryPointAddress, shouldOverrideFee, shouldConsume}]`.
|
|
70
|
+
Matches `@zerodev/sdk@5.5.10`'s `paymaster/sponsorUserOperation.js`
|
|
71
|
+
byte-for-byte. Verified 2026-05-23 via direct curl reproduction
|
|
72
|
+
against the prod bundler URL (bare → "Unsupported method"; correct
|
|
73
|
+
shape → simulation result with AA23 from synthetic UserOp, proving
|
|
74
|
+
the method works).
|
|
75
|
+
|
|
76
|
+
`sponsorUserOp` now requires `expectedChainId` in `BundlerClientOptions`
|
|
77
|
+
(throws `BundlerClientError(config)` when missing) — the chainId is
|
|
78
|
+
part of the request envelope. Defaults conservative placeholder gas
|
|
79
|
+
limits on the userOp when the caller omits them (ZeroDev's Zod
|
|
80
|
+
validator requires the gas fields in the request even though
|
|
81
|
+
simulation recomputes them).
|
|
82
|
+
|
|
83
|
+
Added 3 regression tests pinning the new method name, the wrapped
|
|
84
|
+
envelope, the gas-default behaviour + a `config`-error case when
|
|
85
|
+
expectedChainId is missing.
|
|
86
|
+
|
|
10
87
|
## [0.2.3] — 2026-05-23
|
|
11
88
|
|
|
12
89
|
### Fixed
|
package/dist/broker.cjs
CHANGED
|
@@ -10,7 +10,7 @@ var crypto = require('crypto');
|
|
|
10
10
|
|
|
11
11
|
var DEFAULT_BACKEND_URL = "https://api.muhaven.app";
|
|
12
12
|
var DEFAULT_DASHBOARD_URL = "https://muhaven.app";
|
|
13
|
-
var DEFAULT_REQUEST_TIMEOUT_MS =
|
|
13
|
+
var DEFAULT_REQUEST_TIMEOUT_MS = 75e3;
|
|
14
14
|
var DEFAULT_BROKER_TIMEOUT_MS = 5e3;
|
|
15
15
|
var DEFAULT_BROKER_MAX_BYTES = 64 * 1024;
|
|
16
16
|
var DEFAULT_JWT_CACHE_TTL_SEC = 30;
|
|
@@ -2783,7 +2783,7 @@ function printUsage() {
|
|
|
2783
2783
|
}
|
|
2784
2784
|
function getBrokerPackageVersion() {
|
|
2785
2785
|
{
|
|
2786
|
-
return "0.2.
|
|
2786
|
+
return "0.2.5";
|
|
2787
2787
|
}
|
|
2788
2788
|
}
|
|
2789
2789
|
function printVersion() {
|
package/dist/broker.js
CHANGED
|
@@ -12,7 +12,7 @@ var getDirname = () => path.dirname(getFilename());
|
|
|
12
12
|
var __dirname$1 = /* @__PURE__ */ getDirname();
|
|
13
13
|
var DEFAULT_BACKEND_URL = "https://api.muhaven.app";
|
|
14
14
|
var DEFAULT_DASHBOARD_URL = "https://muhaven.app";
|
|
15
|
-
var DEFAULT_REQUEST_TIMEOUT_MS =
|
|
15
|
+
var DEFAULT_REQUEST_TIMEOUT_MS = 75e3;
|
|
16
16
|
var DEFAULT_BROKER_TIMEOUT_MS = 5e3;
|
|
17
17
|
var DEFAULT_BROKER_MAX_BYTES = 64 * 1024;
|
|
18
18
|
var DEFAULT_JWT_CACHE_TTL_SEC = 30;
|
|
@@ -2785,7 +2785,7 @@ function printUsage() {
|
|
|
2785
2785
|
}
|
|
2786
2786
|
function getBrokerPackageVersion() {
|
|
2787
2787
|
{
|
|
2788
|
-
return "0.2.
|
|
2788
|
+
return "0.2.5";
|
|
2789
2789
|
}
|
|
2790
2790
|
}
|
|
2791
2791
|
function printVersion() {
|
package/dist/index.cjs
CHANGED
|
@@ -22,7 +22,7 @@ var getImportMetaUrl = () => typeof document === "undefined" ? new URL(`file:${_
|
|
|
22
22
|
var importMetaUrl = /* @__PURE__ */ getImportMetaUrl();
|
|
23
23
|
var DEFAULT_BACKEND_URL = "https://api.muhaven.app";
|
|
24
24
|
var DEFAULT_DASHBOARD_URL = "https://muhaven.app";
|
|
25
|
-
var DEFAULT_REQUEST_TIMEOUT_MS =
|
|
25
|
+
var DEFAULT_REQUEST_TIMEOUT_MS = 75e3;
|
|
26
26
|
var DEFAULT_BROKER_TIMEOUT_MS = 5e3;
|
|
27
27
|
var DEFAULT_BROKER_MAX_BYTES = 64 * 1024;
|
|
28
28
|
var DEFAULT_JWT_CACHE_TTL_SEC = 30;
|
|
@@ -1071,7 +1071,28 @@ var BundlerClient = class {
|
|
|
1071
1071
|
* `estimateUserOpGas` round-trip on the happy path).
|
|
1072
1072
|
*/
|
|
1073
1073
|
async sponsorUserOp(userOp, entryPoint) {
|
|
1074
|
-
|
|
1074
|
+
if (this.options.expectedChainId === void 0) {
|
|
1075
|
+
throw new BundlerClientError(
|
|
1076
|
+
"config",
|
|
1077
|
+
"sponsorUserOp requires expectedChainId in BundlerClientOptions \u2014 ZeroDev paymaster needs it in the request envelope"
|
|
1078
|
+
);
|
|
1079
|
+
}
|
|
1080
|
+
const userOpWithGas = {
|
|
1081
|
+
...userOp,
|
|
1082
|
+
callGasLimit: userOp.callGasLimit ?? "0x100000",
|
|
1083
|
+
// 1_048_576
|
|
1084
|
+
verificationGasLimit: userOp.verificationGasLimit ?? "0x100000",
|
|
1085
|
+
preVerificationGas: userOp.preVerificationGas ?? "0x100000"
|
|
1086
|
+
};
|
|
1087
|
+
const result = await this.rpc("zd_sponsorUserOperation", [
|
|
1088
|
+
{
|
|
1089
|
+
chainId: this.options.expectedChainId,
|
|
1090
|
+
userOp: userOpWithGas,
|
|
1091
|
+
entryPointAddress: entryPoint,
|
|
1092
|
+
shouldOverrideFee: false,
|
|
1093
|
+
shouldConsume: true
|
|
1094
|
+
}
|
|
1095
|
+
]);
|
|
1075
1096
|
return parseSponsoredFields(result);
|
|
1076
1097
|
}
|
|
1077
1098
|
/**
|
|
@@ -1902,7 +1923,7 @@ var SUBSCRIPTION_PURCHASE_SELECTOR = viem.toFunctionSelector(
|
|
|
1902
1923
|
var SUBSCRIPTION_PURCHASE_ABI = viem.parseAbi([
|
|
1903
1924
|
"function purchase(address token, (uint256 ctHash, uint8 securityZone, uint8 utype, bytes signature) encShares, uint128 maxSharesHint, address ephemeralEOA)"
|
|
1904
1925
|
]);
|
|
1905
|
-
var PLACEHOLDER_SIGNATURE = "
|
|
1926
|
+
var PLACEHOLDER_SIGNATURE = "0xff" + "fe".repeat(65);
|
|
1906
1927
|
function ok(data) {
|
|
1907
1928
|
return { ok: true, data };
|
|
1908
1929
|
}
|
|
@@ -2646,6 +2667,7 @@ async function positionBuy(input, deps) {
|
|
|
2646
2667
|
const navDisplay = formatUsd6AsDecimal(navUsd6);
|
|
2647
2668
|
const sharesStr = shares.toString();
|
|
2648
2669
|
let pathDFallbackReason;
|
|
2670
|
+
let pathDFallbackDetail;
|
|
2649
2671
|
let pathDSubmittedUserOpHash;
|
|
2650
2672
|
const pathD = await attemptPathD(
|
|
2651
2673
|
{ shares, tokenAddress: token.address, tokenSymbol: token.symbol },
|
|
@@ -2656,6 +2678,7 @@ async function positionBuy(input, deps) {
|
|
|
2656
2678
|
}
|
|
2657
2679
|
if (pathD.kind === "fallback") {
|
|
2658
2680
|
pathDFallbackReason = pathD.reason;
|
|
2681
|
+
pathDFallbackDetail = pathD.message;
|
|
2659
2682
|
if (pathD.submittedUserOpHash) {
|
|
2660
2683
|
pathDSubmittedUserOpHash = pathD.submittedUserOpHash;
|
|
2661
2684
|
}
|
|
@@ -2681,6 +2704,7 @@ ${dashboardUrl}`,
|
|
|
2681
2704
|
effectiveNotionalUsd6: effectiveNotionalUsd6.toString(),
|
|
2682
2705
|
navUsd6: navUsd6.toString(),
|
|
2683
2706
|
...pathDFallbackReason ? { pathDFallbackReason } : {},
|
|
2707
|
+
...pathDFallbackDetail ? { pathDFallbackDetail } : {},
|
|
2684
2708
|
...pathDSubmittedUserOpHash ? { pathDSubmittedUserOpHash } : {}
|
|
2685
2709
|
}
|
|
2686
2710
|
});
|
|
@@ -3032,7 +3056,7 @@ var SERVER_NAME = "@muhaven/mcp";
|
|
|
3032
3056
|
var SERVER_VERSION = resolveServerVersion();
|
|
3033
3057
|
function resolveServerVersion() {
|
|
3034
3058
|
{
|
|
3035
|
-
return "0.2.
|
|
3059
|
+
return "0.2.5";
|
|
3036
3060
|
}
|
|
3037
3061
|
}
|
|
3038
3062
|
function toJsonInputSchema(schema) {
|
package/dist/index.d.cts
CHANGED
|
@@ -708,6 +708,17 @@ interface PartialUserOpForSponsorship {
|
|
|
708
708
|
readonly maxPriorityFeePerGas: `0x${string}`;
|
|
709
709
|
/** Worst-case placeholder so paymaster simulates realistic gas. */
|
|
710
710
|
readonly signature: `0x${string}`;
|
|
711
|
+
/**
|
|
712
|
+
* Optional pre-estimated gas fields. ZeroDev's `zd_sponsorUserOperation`
|
|
713
|
+
* does its own simulation + recomputes these in the response, so
|
|
714
|
+
* passing placeholders is OK — but the upstream Zod validator
|
|
715
|
+
* REQUIRES the fields to be present. `sponsorUserOp` defaults them
|
|
716
|
+
* to safe placeholders when omitted (the response carries the real
|
|
717
|
+
* values for the caller to use).
|
|
718
|
+
*/
|
|
719
|
+
readonly callGasLimit?: `0x${string}`;
|
|
720
|
+
readonly verificationGasLimit?: `0x${string}`;
|
|
721
|
+
readonly preVerificationGas?: `0x${string}`;
|
|
711
722
|
}
|
|
712
723
|
interface SponsoredUserOpFields {
|
|
713
724
|
readonly paymaster: `0x${string}`;
|
package/dist/index.d.ts
CHANGED
|
@@ -708,6 +708,17 @@ interface PartialUserOpForSponsorship {
|
|
|
708
708
|
readonly maxPriorityFeePerGas: `0x${string}`;
|
|
709
709
|
/** Worst-case placeholder so paymaster simulates realistic gas. */
|
|
710
710
|
readonly signature: `0x${string}`;
|
|
711
|
+
/**
|
|
712
|
+
* Optional pre-estimated gas fields. ZeroDev's `zd_sponsorUserOperation`
|
|
713
|
+
* does its own simulation + recomputes these in the response, so
|
|
714
|
+
* passing placeholders is OK — but the upstream Zod validator
|
|
715
|
+
* REQUIRES the fields to be present. `sponsorUserOp` defaults them
|
|
716
|
+
* to safe placeholders when omitted (the response carries the real
|
|
717
|
+
* values for the caller to use).
|
|
718
|
+
*/
|
|
719
|
+
readonly callGasLimit?: `0x${string}`;
|
|
720
|
+
readonly verificationGasLimit?: `0x${string}`;
|
|
721
|
+
readonly preVerificationGas?: `0x${string}`;
|
|
711
722
|
}
|
|
712
723
|
interface SponsoredUserOpFields {
|
|
713
724
|
readonly paymaster: `0x${string}`;
|
package/dist/index.js
CHANGED
|
@@ -18,7 +18,7 @@ import { privateKeyToAccount } from 'viem/accounts';
|
|
|
18
18
|
// src/server.ts
|
|
19
19
|
var DEFAULT_BACKEND_URL = "https://api.muhaven.app";
|
|
20
20
|
var DEFAULT_DASHBOARD_URL = "https://muhaven.app";
|
|
21
|
-
var DEFAULT_REQUEST_TIMEOUT_MS =
|
|
21
|
+
var DEFAULT_REQUEST_TIMEOUT_MS = 75e3;
|
|
22
22
|
var DEFAULT_BROKER_TIMEOUT_MS = 5e3;
|
|
23
23
|
var DEFAULT_BROKER_MAX_BYTES = 64 * 1024;
|
|
24
24
|
var DEFAULT_JWT_CACHE_TTL_SEC = 30;
|
|
@@ -1067,7 +1067,28 @@ var BundlerClient = class {
|
|
|
1067
1067
|
* `estimateUserOpGas` round-trip on the happy path).
|
|
1068
1068
|
*/
|
|
1069
1069
|
async sponsorUserOp(userOp, entryPoint) {
|
|
1070
|
-
|
|
1070
|
+
if (this.options.expectedChainId === void 0) {
|
|
1071
|
+
throw new BundlerClientError(
|
|
1072
|
+
"config",
|
|
1073
|
+
"sponsorUserOp requires expectedChainId in BundlerClientOptions \u2014 ZeroDev paymaster needs it in the request envelope"
|
|
1074
|
+
);
|
|
1075
|
+
}
|
|
1076
|
+
const userOpWithGas = {
|
|
1077
|
+
...userOp,
|
|
1078
|
+
callGasLimit: userOp.callGasLimit ?? "0x100000",
|
|
1079
|
+
// 1_048_576
|
|
1080
|
+
verificationGasLimit: userOp.verificationGasLimit ?? "0x100000",
|
|
1081
|
+
preVerificationGas: userOp.preVerificationGas ?? "0x100000"
|
|
1082
|
+
};
|
|
1083
|
+
const result = await this.rpc("zd_sponsorUserOperation", [
|
|
1084
|
+
{
|
|
1085
|
+
chainId: this.options.expectedChainId,
|
|
1086
|
+
userOp: userOpWithGas,
|
|
1087
|
+
entryPointAddress: entryPoint,
|
|
1088
|
+
shouldOverrideFee: false,
|
|
1089
|
+
shouldConsume: true
|
|
1090
|
+
}
|
|
1091
|
+
]);
|
|
1071
1092
|
return parseSponsoredFields(result);
|
|
1072
1093
|
}
|
|
1073
1094
|
/**
|
|
@@ -1898,7 +1919,7 @@ var SUBSCRIPTION_PURCHASE_SELECTOR = toFunctionSelector(
|
|
|
1898
1919
|
var SUBSCRIPTION_PURCHASE_ABI = parseAbi([
|
|
1899
1920
|
"function purchase(address token, (uint256 ctHash, uint8 securityZone, uint8 utype, bytes signature) encShares, uint128 maxSharesHint, address ephemeralEOA)"
|
|
1900
1921
|
]);
|
|
1901
|
-
var PLACEHOLDER_SIGNATURE = "
|
|
1922
|
+
var PLACEHOLDER_SIGNATURE = "0xff" + "fe".repeat(65);
|
|
1902
1923
|
function ok(data) {
|
|
1903
1924
|
return { ok: true, data };
|
|
1904
1925
|
}
|
|
@@ -2642,6 +2663,7 @@ async function positionBuy(input, deps) {
|
|
|
2642
2663
|
const navDisplay = formatUsd6AsDecimal(navUsd6);
|
|
2643
2664
|
const sharesStr = shares.toString();
|
|
2644
2665
|
let pathDFallbackReason;
|
|
2666
|
+
let pathDFallbackDetail;
|
|
2645
2667
|
let pathDSubmittedUserOpHash;
|
|
2646
2668
|
const pathD = await attemptPathD(
|
|
2647
2669
|
{ shares, tokenAddress: token.address, tokenSymbol: token.symbol },
|
|
@@ -2652,6 +2674,7 @@ async function positionBuy(input, deps) {
|
|
|
2652
2674
|
}
|
|
2653
2675
|
if (pathD.kind === "fallback") {
|
|
2654
2676
|
pathDFallbackReason = pathD.reason;
|
|
2677
|
+
pathDFallbackDetail = pathD.message;
|
|
2655
2678
|
if (pathD.submittedUserOpHash) {
|
|
2656
2679
|
pathDSubmittedUserOpHash = pathD.submittedUserOpHash;
|
|
2657
2680
|
}
|
|
@@ -2677,6 +2700,7 @@ ${dashboardUrl}`,
|
|
|
2677
2700
|
effectiveNotionalUsd6: effectiveNotionalUsd6.toString(),
|
|
2678
2701
|
navUsd6: navUsd6.toString(),
|
|
2679
2702
|
...pathDFallbackReason ? { pathDFallbackReason } : {},
|
|
2703
|
+
...pathDFallbackDetail ? { pathDFallbackDetail } : {},
|
|
2680
2704
|
...pathDSubmittedUserOpHash ? { pathDSubmittedUserOpHash } : {}
|
|
2681
2705
|
}
|
|
2682
2706
|
});
|
|
@@ -3028,7 +3052,7 @@ var SERVER_NAME = "@muhaven/mcp";
|
|
|
3028
3052
|
var SERVER_VERSION = resolveServerVersion();
|
|
3029
3053
|
function resolveServerVersion() {
|
|
3030
3054
|
{
|
|
3031
|
-
return "0.2.
|
|
3055
|
+
return "0.2.5";
|
|
3032
3056
|
}
|
|
3033
3057
|
}
|
|
3034
3058
|
function toJsonInputSchema(schema) {
|
package/manifest.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"manifest_version": "0.2",
|
|
4
4
|
"name": "muhaven-mcp",
|
|
5
5
|
"display_name": "MuHaven (RWA portfolio)",
|
|
6
|
-
"version": "0.2.
|
|
6
|
+
"version": "0.2.5",
|
|
7
7
|
"description": "Confidential RWA portfolio management on Fhenix CoFHE. Read your encrypted balances, propose yield claims and policy changes — all signing happens in a sibling broker daemon, the LLM never sees your private key.",
|
|
8
8
|
"long_description": "MuHaven MCP exposes 24 tools across read.* / position.* / policy.* / issuer.* / governance.* groups for managing real-world asset (RWA) tokens with FHE-encrypted balances. Authentication uses a one-time device-code ceremony (run `muhaven-broker login`); subsequent tool calls fetch the JWT from the broker over a Unix socket. Position / governance tools deep-link to the dashboard for passkey signing — they NEVER auto-submit to a bundler. The companion `muhaven-broker` daemon must be running before tools can be invoked. See README for setup.",
|
|
9
9
|
"author": {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@muhaven/mcp",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.5",
|
|
4
4
|
"description": "MuHaven MCP server — read/position/policy toolsets bridging Claude Desktop / Cursor / Claude Code to the MuHaven backend, with a sibling muhaven-broker daemon holding the session-key private half over a local IPC socket",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|