@haven_ai/signer 0.8.1-alpha.0 → 0.10.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +39 -4
- package/dist/cli.cjs +369 -28
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +370 -29
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +357 -16
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +51 -10
- package/dist/index.d.ts +51 -10
- package/dist/index.js +358 -17
- package/dist/index.js.map +1 -1
- package/package.json +6 -5
package/README.md
CHANGED
|
@@ -61,7 +61,7 @@ metadata found in the credential file, and the sign-only tool list. It refuses
|
|
|
61
61
|
to start until acknowledged with either `HAVEN_SIGNER_ACK=<hash>` or
|
|
62
62
|
`npx @haven_ai/signer@alpha --credentials /path/to/haven-agent.json --ack`.
|
|
63
63
|
|
|
64
|
-
It exposes
|
|
64
|
+
It exposes five stdio MCP tools, all sign-only:
|
|
65
65
|
|
|
66
66
|
| Tool | Does | Emits |
|
|
67
67
|
|---|---|---|
|
|
@@ -69,6 +69,7 @@ It exposes four stdio MCP tools, all sign-only:
|
|
|
69
69
|
| `haven_sign_x402` | One-shot x402: funding signature **and** the merchant header in a single local call (`haven_sign` + `haven_x402_sign_header`). `{ payment_id }` alone is the preferred call | `{ signature, x402_binding, payment_header, accepted }` |
|
|
70
70
|
| `haven_x402_sign_header` | Build + sign the EIP-3009 merchant payment header, only when the fresh merchant `payment_required` matches the recorded `x402_binding` | `{ payment_header, accepted }` |
|
|
71
71
|
| `haven_sign_sweep_delegate` | Sign a Haven-prepared gasless EIP-3009 sweep that recovers stranded funds from the delegate wallet back to your own account. Never broadcasts | `{ signature }` |
|
|
72
|
+
| `haven_sign_siwx` | Answer a merchant x402 Sign-In-With-X (SIWX) challenge (#3728): the signer composes the EIP-4361 message ITSELF from the grammar-validated `sign-in-with-x` challenge and the delegate address read from the key — never a caller-supplied message — signs it EIP-191, and returns the finished header. Refuses (`SIWX_REFUSED`) unless the challenge domain matches the `url` host (the FINAL URL after redirects — never follow a redirect with the header or a resulting session token attached), the resource uri origin matches, the URL is https, the nonce is well-formed, the expiry window is ≤ 5 minutes (plus a small clock-skew tolerance), and `supportedChains` offers the credential chain with `eip191`. Moves no funds and grants no spend authority | `{ sign_in_with_x_header }` — retry the merchant with the `SIGN-IN-WITH-X` header set to that value |
|
|
72
73
|
|
|
73
74
|
The `initialize` handshake advertises which binding versions this signer
|
|
74
75
|
understands, under `capabilities.experimental['haven/signer-compatibility']`
|
|
@@ -99,8 +100,11 @@ const { paymentHeader } = await signer.buildX402PaymentHeader(
|
|
|
99
100
|
)
|
|
100
101
|
```
|
|
101
102
|
|
|
102
|
-
The signer also exposes `signSweepAuthorization(input)` for the gasless sweep
|
|
103
|
-
|
|
103
|
+
The signer also exposes `signSweepAuthorization(input)` for the gasless sweep and
|
|
104
|
+
`signSiwxMessage(message)` for #3728's composed EIP-4361 sign-in — the message
|
|
105
|
+
always reaches it composed in-package from grammar-validated challenge fields,
|
|
106
|
+
with the address taken from the key.
|
|
107
|
+
All five are methods on the object `createEdgeSigner` returns, not standalone
|
|
104
108
|
exports. There is NO raw-hash primitive: `signPaymentHash(hash)` (raw ECDSA over
|
|
105
109
|
the retired AllowanceModule rail's hash) was removed in #3169, and
|
|
106
110
|
`signX402FundingHash` (the expected-context v1 bare-hash path) in #3272 — the
|
|
@@ -202,6 +206,26 @@ relays ("Connection closed" plus this process's exit message) names the same
|
|
|
202
206
|
command. The consent hash covers identity, tool names and the surface version —
|
|
203
207
|
not the block's prose — so neither change re-prompts an acknowledged install.
|
|
204
208
|
|
|
209
|
+
## Several Haven pairs on one machine (#3738)
|
|
210
|
+
|
|
211
|
+
One harness can carry several Haven pairs — `haven-research` +
|
|
212
|
+
`haven-signer-research`, `haven-ops` + `haven-signer-ops`, alongside a bare
|
|
213
|
+
`haven` + `haven-signer` (Codex: `haven` + `haven_signer`). A model must act as
|
|
214
|
+
one agent per task and keep hosted and signer calls inside that pair. Server
|
|
215
|
+
names are easy to cross, so the signer's `initialize` instructions state what
|
|
216
|
+
it is bound to:
|
|
217
|
+
|
|
218
|
+
```
|
|
219
|
+
This signer is bound to agent id <agent_id> and delegate address <0x…>.
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
The agent id comes from the credential file's `agent_id` (or `HAVEN_AGENT_ID`
|
|
223
|
+
alongside `HAVEN_DELEGATE_KEY`); when neither is set the line says "no recorded
|
|
224
|
+
agent id" and still gives the delegate address, which is then compared alone.
|
|
225
|
+
The model compares it with `haven_get_agent`'s `id` and `delegateAddress` from
|
|
226
|
+
the hosted server it called, and signs nothing on a mismatch. Neither value is secret (the consent screen prints both), and
|
|
227
|
+
the line is advisory: what the signer refuses to sign is unchanged.
|
|
228
|
+
|
|
205
229
|
## Orchestration
|
|
206
230
|
|
|
207
231
|
Direct payment:
|
|
@@ -289,6 +313,17 @@ what a payload means; they re-derive it.
|
|
|
289
313
|
- **A binding version it does not understand.** The refusal is machine-readable
|
|
290
314
|
— `code`, `supported_versions`, `received_version`, `fallback`, and (#3103)
|
|
291
315
|
`next_tool_omitted_reason` — and names updating the signer as the fix.
|
|
316
|
+
- **A sign-in challenge that does not describe the origin it is sent to (#3728).**
|
|
317
|
+
`haven_sign_siwx` composes the EIP-4361 message itself from the challenge's
|
|
318
|
+
grammar-validated fields and the delegate address from the key; a challenge
|
|
319
|
+
whose domain is not the host of the `url` being called, whose resource uri
|
|
320
|
+
origin differs, that is not https, that carries a malformed or missing nonce,
|
|
321
|
+
a `version` other than `"1"`, an expiry window beyond the spec's 5-minute max
|
|
322
|
+
age (plus a small clock-skew tolerance), or that does not offer the credential
|
|
323
|
+
chain with an `eip191` signature type is refused with no signature and no
|
|
324
|
+
audit entry. A caller-supplied message, hash or byte string is never signed —
|
|
325
|
+
a SIWX signature therefore cannot double as a payment authorization, a
|
|
326
|
+
UserOp signature or any other Haven signature.
|
|
292
327
|
- **A sweep that does not move funds out of this delegate's own key** — the
|
|
293
328
|
`from` check is unconditional. The **destination** check is not, and this is
|
|
294
329
|
the one asymmetry in this list: the signer compares the sweep's `to` against
|
|
@@ -318,7 +353,7 @@ refusal class — `fallback`, `retry_with_new_quote`, `http_status`,
|
|
|
318
353
|
`SIGN_CONTEXT_REFUSED` (other) row names the hosted status read
|
|
319
354
|
(`next_tool_server_role: hosted`, `next_tool_name: haven_get_payment_status`,
|
|
320
355
|
`next_arguments: { payment_id }` — resolve the role against your own server
|
|
321
|
-
names); every other row carries `next_tool_omitted_reason` with the exact
|
|
356
|
+
names, and with several Haven pairs against this signer's own pair); every other row carries `next_tool_omitted_reason` with the exact
|
|
322
357
|
remedy. `message` is unchanged.
|
|
323
358
|
|
|
324
359
|
**#3271: `haven_sign` (never `haven_sign_x402`) has one escape from this
|