Skip to content

PRD-05: Per-origin permissions, registry & anti-phishing #48

Open

Description

@hellno

Part of #44 (ADR 0001). Phase 2. The policy + trust layer that makes the Deckard-native bridge (PRD-04) safe: scope each connected origin (accounts × chains × methods), ship a curated registry + anti-phishing blocklist, treat origin as attacker-controllable. Pairs with PRD-04; depends on PRD-02.

Why

Once a dapp can connect (PRD-04), the wallet must answer "what may this origin do?" not "what may any caller do?". Standards (research §37): EIP-2255 (wallet_requestPermissions/getPermissions, {invoker, parentCapability, caveats}) and CAIP-25 scoping (accounts × chains × methods). Origin is self-asserted and spoofable (research §13, 29) → scope + attestation-as-hint + shipped blocklist, and the human always approves on decoded effects, never a claimed name.

Goals

  • Per-origin permission model: a connected origin gets a scoped, persisted, revocable session (accounts/chains/methods/caps/expiry), enforced by the daemon, distinct from the global Policy.
  • Curated dapp registry (the allowlist-first posture for generic connectivity): known-good origins + metadata + ERC-7730 descriptor refs. Offline-first and signed if updatable out-of-band.
  • Anti-phishing blocklist (known-malicious domains; eth-phishing-detect style), shipped + updatable.
  • wallet_addEthereumChain/switch guards (research §36).

Non-goals

Transport (PRD-04); signing decode (PRD-02); building/curating ERC-7730 upstream (we reference/consume). Open access as default — default is curated-allowlist; unknown origins only via an explicit friction-ful "unverified origin" confirm (never silent).

Design

Per-origin policy (deckard-contract + deckard-signerd): OriginGrant { origin, accounts, chains, methods, caps?, expiry }. The global Policy stays the outer fence — a grant can only ever be narrower (a grant never widens global caps/allowlist). Daemon evaluates both; stricter wins. Pure evaluate_origin(&proposal, &OriginGrant, &Policy) next to the existing decision fns (parity charter). Grants created at connect-time (human approves the requested scope, EIP-2255/CAIP-25 style), revocable from settings governance (next to "Pause all agents").

Origin attestation (hint only, research §29): origin string from the untrusted connector is shown unverified unless corroborated by a registry match or first-party attestation (PRD-04). No third-party relay attestation (WalletConnect/Verify shelved with WC). Decoded effects remain ground truth; never gate solely on a green check.

Registry + blocklist (offline-first, signed): in-repo signed JSON of curated origins → metadata + descriptor refs; ships with the build; out-of-band updates require a maintainer signature (tampered/unsigned → refused loudly, mirror policy_store.rs). Blocklist match = hard, loud block (red) even if the user tries to proceed — the one place we override user intent (a known drainer domain). Registry references which ERC-7730 descriptors apply so PRD-02's card renders human-readable intent; uncovered → PRD-02 blind-sign fallback.

Acceptance tests

origin_grant_cannot_widen_global; out_of_scope_method_denied; blocklist_hard_blocks; unsigned_registry_refused (falls back to safe built-in = nothing auto-trusted); unverified_origin_requires_friction; addchain_uses_user_chainid; evaluate_origin mock/daemon parity.

DoD

Shared DoD (#44) plus: revoke-origin + list-connected-origins are ⌘K commands + in settings governance; registry/blocklist trust model in SECURITY.md; "origin-untrusted, effects-are-ground-truth" in THREAT-MODEL.md; UI matches DESIGN.md (no green-check-as-safety).

Sources: research §13, 29, 36–37; EIP-2255, EIP-3085/3326; CAIP-25; eth-phishing-detect; existing policy.rs, policy_store.rs.

Activity

  1. hellno commented on Jun 19, 2026

    @hellno
    OwnerAuthor

    ⛓ Blocked by #46 — per-origin permissions depend on PRD-02 clear-signing (#46).

  2. hellno commented on Jun 24, 2026

    @hellno
    OwnerAuthor

    Per ADR-0005 (#135): per-origin grants reuse the Rules vocabulary (cap / allowlist / expiry / mode) but remain a software-enforced mechanism (the daemon refuses to sign out of scope), distinct from #33's chain-enforced session keys. Composition is monotonic narrowing — a grant only restricts the global Rules, never widens. Do not collapse the two into one mechanism.

  3. added 3 commits that reference this issue on Jul 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions