NIP-46 decrypted bridge

The nip46-decrypted-bridge-v0 contract defines what the companion does with an already-decrypted NIP-46 payload. The bridge is intentionally narrow: it does not implement relay sessions, does not do encryption, and does not derive keys.

What the bridge accepts

The companion accepts a decrypted NIP-46 payload as JSON. The bridge:

  1. Validates the payload against the NIP-46 contract: it is a sign_event request, get_public_key, or another supported method.
  2. Maps it to the equivalent v0 nSealr signing request — or, if the request shape isn’t supported, returns a deterministic non-signing decision with a typed reason.
  3. Returns the decision to the calling companion surface. Routing, relay sessions, and signer I/O stay outside this narrow bridge contract.
$ nsealr nip46 decide --message decrypted.json --permissions sign_event:1 --out decision.json
# decision.json contains a sign_event conversion or a deterministic refusal

or:

$ nsealr nip46 decide --message unsupported-method.json --permissions sign_event:1 --out decision.json
 deterministic non-signing decision: UNSUPPORTED_METHOD

What it does not do

Out of scopeWhy
Open a relay sessionHandled by the relay session layer (Nip46SessionManager), not this narrow bridge
Decrypt NIP-46 envelopesDone by the relay session layer with the ephemeral client transport key; this bridge takes already-decrypted input
Sign user events itselfThe companion never holds the user signing key (it only signs kind‑24133 transport events with the ephemeral client key)
Implement remote signer logicThat’s the signer’s job

Per-signer policy

The bridge produces standard v0 signing-request decisions for the calling companion surface. The signer then applies its policy (scoped-policy-automation-v0 on the USB/NIP-46 line, manual-only on QR vaults, external review acknowledgement on smartcards). The bridge does not enforce policy on its own.

Deterministic non-signing decisions

When the bridge cannot convert or allow a request, it returns one of a fixed enumeration. The caller can rely on these as typed values.

DecisionWhen
UNSUPPORTED_METHODThe NIP-46 method is not part of the v0 surface
BAD_PAYLOAD_SHAPEThe decrypted JSON doesn’t match the NIP-46 schema
IMPLEMENTATION_LIMITRequest exceeds shared v0 implementation limits
POLICY_DENY_BY_DEFAULTNo explicit allow rule covers this request
SIGNER_UNREACHABLENo active signer route can be reached now

A bridge that returns one of these has not signed and will not sign. The decision is final for the request id; the caller must build a fresh request to try again.

See also

Last updated 2026-06-22