npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@observer-protocol/ows-op-verify

v0.1.0

Published

Observer Protocol delegation-credential verifier for the Open Wallet Standard policy engine. Pre-signing enforcement of signed agent mandates as an OWS custom-executable policy.

Readme

ows-op-policy

Observer Protocol delegation verification for Open Wallet Standard wallets.

Status: pre-release. Built and conformance-tested against fixtures; not yet published or validated against production Observer Protocol credentials.

A single-file policy executable for the OWS policy engine that gates every agent signing request on a signed, revocable, scope-limited mandate — an ObserverDelegationCredential issued under AIP v0.8. The agent holds an OWS API key; the principal holds the mandate; the wallet refuses to sign anything the mandate doesn't cover.

OWS evaluates policies before the wallet secret's decryption key is derived, so a deny here means key material is never touched. OWS provides the local key-custody and gating machinery; Observer Protocol provides the verifiable authorization provenance — who authorized this agent, for what scope, and whether that authority has been revoked.

agent calls ows sign (API key in the passphrase position)
  → OWS policy engine (AND of all policies on the key)
      → declarative rules: allowed_chains, expires_at   (mirror of mandate scope)
      → executable: ows-op-verify                       (this project)
           verifies   eddsa-jcs-2022 proof · issuer did:web + assertionMethod
                      schema allowlist · validity window · revocation status
           enforces   rails · amount ceilings · counterparty lists · time windows
                      velocity caps (deny-side) · authorization levels 1/2/3
  → deny  ⇒ POLICY_DENIED — the wallet's HKDF key is never derived
  → allow ⇒ decrypt → sign → zeroize

Quickstart

npm install && npm run build          # produces dist/ows-op-verify.cjs (zero runtime deps)
npm test                              # 43 conformance checks, pass AND fail sides

node installer/install.mjs --credential /path/to/delegation-credential.json
ows policy create --file op-delegation.json
ows key create --name "my-agent" --wallet <wallet> --policy op-delegation

The installer copies the executable to ~/.ows/plugins/policies/, derives the declarative mirror rules (allowed_chains from the mandate's rails, expires_at from validUntil), writes every behavioral knob into the policy config explicitly, and self-tests the executable before telling you the exact ows commands to finish with. A reference policy file is in policy/op-delegation.template.json.

What gets verified (credential plane)

Proof-suite note (deliberate, not an oversight): this verifier implements the eddsa-jcs-2022 surface as deployed by the Observer Protocol issuance pipeline — the production signing reality. The AIP v0.6–v0.8 draft texts still cite the older Ed25519Signature2026 suite name; aligning the draft language is tracked separately in the AIP repository and is intentionally not part of this project. Where draft text and deployed surface disagree, this verifier follows the deployed surface.

| Check | Behavior | |---|---| | Proof suite | DataIntegrityProof / eddsa-jcs-2022 (W3C VC Data Integrity). Legacy Ed25519Signature20xx suites are rejected | | Issuer | Pinned in config; resolved via did:web; the signing key must be listed in assertionMethod — a key merely present on the DID document is refused | | Schema | credentialSchema.id must be on the configured allowlist (default: delegation/v2.1.json only) | | Validity | validFrom ≤ now ≤ validUntil | | Revocation | W3C Bitstring Status List. Refresh-first: the list is re-fetched on every evaluation; on fetch failure a cached copy younger than revocation.maxStalenessHours (default 24, always written explicitly by the installer) is honored; anything older denies until connectivity returns. The status list credential's own signature is verified against the same pinned issuer |

What gets enforced (transaction plane)

Binding mandate fields deny; advisory fields (per AIP v0.8: cumulative_budget, allowed_counterparty_types, actionScope.geographic_restriction) are surfaced in the decision log but never ground a deny. A binding constraint the verifier cannot establish from the signing context is a deny — wrongful acceptance is treated as categorically worse than wrongful rejection.

  • actionScope.allowed_rails, per_transaction_ceiling (same-currency only — no FX conversion, ever), allowed_transaction_categories (against the category declared in config for this key)
  • Authorization levels: one-time (exact amount/counterparty/rail/deadline), recurring (per-transaction max, validity, counterparty; period ceilings enforced deny-side via the per-key daily counter), policy (per-rail caps)
  • tradingMandate: maxNotionalPerOrder + unit, counterparty allowList/blockList (raw addresses, or DIDs via config.counterpartyAddressMap), temporal.allowedTimeWindows (IANA timezones), velocity caps (deny-side, see Limitations), geographic (allowedJurisdictionsOnly fails closed; blockedJurisdictions fails open per AIP v0.8 §2.3 — both surfaced in the log)

Per-rail support matrix

The released OWS engine (v1.3.2) hands executables transaction.raw_hex only — the full serialized transaction (the parsed to/value/data fields in main-branch docs are newer than the latest release; discovered live-fire, not from docs, for both EVM and Solana). This verifier decodes the payload itself, zero runtime dependencies, and does not silently skip what it can't read:

| Rail | Credential plane¹ | Native amount | Token amount (USDC/USDT) | Counterparty | Net effect | |---|---|---|---|---|---| | EVM (eip155:*) | ✅ | ✅ ETH/POL value | ✅ ERC-20 + EIP-3009 transfer* decoded at the token's own decimals | ✅ recipient (to, or the token-transfer to) | Full enforcement | | Solana (solana:*) | ✅ | ✅ SOL (System transfer) | ✅ SPL TransferChecked (mint-identified, 6-dec) | ✅ wallet (SOL) / token account (SPL)³ | Full enforcement (legacy + v0), within the fail-closed boundaries below | | Bitcoin, Tron, TON, Cosmos, Sui, XRPL, … | ✅ | ✗ payload unparsed | ✗ | ✗ | Verified-identity only: binding amount/counterparty mandates deny; identity/temporal/revocation-scoped mandates work |

¹ proof, issuer, schema, validity, revocation, time windows, rail allowlists — chain-independent.

EVM payloads: EIP-1559 / EIP-2930 / legacy RLP, with a chainId cross-check against the signing context. Native value, plus ERC-20 transfer/transferFrom and EIP-3009 transferWithAuthorization / receiveWithAuthorization (the x402 USDC path) decoded at the token's registered decimals. Calldata to an unknown contract still denies under a binding amount constraint unless allowContractCalls: true (native-value-only measurement, said loudly).

Solana payloads — what is enforced: legacy and v0 (versioned) messages; System-program SOL transfers; SPL Token TransferChecked for USDC/USDT (mint identified from the instruction, amount at 6 decimals, on-chain decimals cross-checked against the registry). Same-currency invariant (no FX), identical to EVM.

Solana payloads — fail-closed boundaries (deny any binding amount/counterparty constraint; stated plainly, not stretched):

  • Address Lookup Tables (v0 ALUT): accounts loaded from on-chain tables are not in the static message. No on-chain reads in v1 → deny when a constraint would depend on an ALUT-loaded account.
  • Plain SPL Transfer (non-checked): the mint is not in the instruction, so the asset cannot be proven offline → deny under a token ceiling. Use TransferChecked for enforceable token payments. (The asset is never guessed.)
  • Opaque / unhandled instructions (unknown program, or unhandled System/Token instruction that could move value) alongside a transfer → deny: every instruction must satisfy the mandate. Benign ComputeBudget and Memo instructions do not defeat enforcement.
  • Multiple value transfers in one transaction → deny (attribution unsupported in v1).
  • Network binding: a Solana message carries a recentBlockhash, not the genesis hash, so mainnet-vs-devnet cannot be re-derived from the static payload (unlike EVM's embedded chainId). The cluster is taken from the PolicyContext chain_id via the rail map; this is trusted input, documented here rather than faked. (Open question flagged for design review.)

³ SPL transfers move between token accounts, not wallets. The verifier matches the destination token account address against the mandate's counterparty list; matching by wallet/DID requires that token account to be listed (in the allowlist or counterpartyAddressMap). Deriving a token account's owner offline (associated-token-account derivation) is a planned extension; until then owner-based SPL counterparty matching fails closed.

Contributing a rail: implement payload parsing for the chain (amount + recipient), add the CAIP-2 → rail mapping with its family to DEFAULT_RAILS, and add pass/fail fixtures for every rule the parser enables. PRs are welcome — the conformance runner (test/run.mjs) is the gate.

Configuration

Everything arrives through the OWS policy file's config object (injected by the engine as policy_config). No quiet defaults: the installer writes every behavioral value out loud; the table is the contract.

| Key | Required | Meaning | |---|---|---| | credentialPath | ✅ | Delegation credential JSON. Re-read on every call — rotation/re-issue takes effect immediately | | issuerDid | ✅ | Pinned trusted issuer. Credentials from any other issuer deny | | schemaAllowlist | ✅ | Accepted credentialSchema.id URLs (frozen-URL schema policy; default v2.1 only) | | agentDid | — | Pin credentialSubject.id; mismatch denies | | revocation.maxStalenessHours | written explicitly (24) | Cache window for status lists when refresh fails. Older ⇒ deny | | revocation.onUnreachable | written explicitly | cache-then-deny (the only implemented behavior, on purpose) | | revocation.fetchTimeoutMs | written explicitly (1500) | Per-fetch budget inside OWS's hard 5s executable timeout | | didCache.maxStalenessHours | written explicitly (24) | Same refresh-first policy for issuer DID documents | | rails | defaults built in | CAIP-2 → {rail, currency, decimals, family} map; extend/override per deployment | | evmTokens | defaults built in | lowercased ERC-20 contract → {symbol, decimals} (USDC/USDT preloaded); identifies token transfers | | solanaMints | defaults built in | base58 SPL mint → {symbol, decimals} (USDC/USDT preloaded) | | allowContractCalls | default false | Permit unknown EVM contract calldata under binding amount constraints, measured by native value only (read the footnote first) | | transactionCategory | — | Category this key's transactions are declared as, matched against allowed_transaction_categories | | counterpartyAddressMap | — | DID → addresses, for mandates that pin counterparties by DID (use token-account addresses for SPL) | | cacheDir / auditLog | written explicitly | Cache location; JSONL decision log | | offline.didDocumentPath / offline.statusListPath | — | Air-gapped/test overrides; bypass network entirely |

Decision log

Every evaluation appends one JSON line — timestamp, verdict, reason, advisory notes, chain, wallet/key ids, credential id + SHA-256, transaction hash — to auditLog (0600). The log is unsigned in this release; emission of signed PolicyEvaluationCredentials with a published per-instance key is a planned extension (see docs/SCOPE.md).

Limitations (read these — they are load-bearing)

  • Counterparty DIDs need a mapping. The wallet sees addresses, not DIDs. A mandate pinning a counterparty DID with no counterpartyAddressMap entry denies (the binding cannot be established).
  • requireIssuerClassIn denies. Verifying a counterparty's attested issuer class needs an attestation source this executable doesn't have yet.
  • SPL counterparty matching is against the token account, not the wallet owner. Offline associated-token-account derivation is a planned extension; until then, list token-account addresses in the allowlist or fail closed.
  • Solana v0 ALUT and plain SPL Transfer fail closed under binding amount/counterparty constraints (no on-chain reads; mint not in a plain Transfer). See the support matrix for the full boundary list.
  • Velocity/period ceilings are deny-side only. The only state OWS provides is a per-API-key, per-calendar-day, native-value counter — a lower bound on any rolling window. An overshoot it can see is a real overshoot (deny); full allow-side accounting needs a stateful evaluator.
  • One-time credentials aren't consumed. Single-use semantics can't be tracked at this layer; revoke the credential after settlement.
  • Order-plane constraints are not enforced here. allowedVenues, allowedInstruments, dailyDrawdownCap require order context and belong to an order-aware evaluator; they are surfaced as NOT-ENFORCED notes.
  • Schema note: the frozen v2.1 schema's proof block predates the eddsa-jcs-2022 migration; the credential body is validated against v2.1 structure while the proof is verified per W3C VC Data Integrity. Tracked as a spec-alignment item in the AIP repository.

Development

npm run typecheck   # strict TS
npm run build       # esbuild → dist/ows-op-verify.cjs (single file, node:* only)
npm test            # fixtures regenerated fresh (keys generated on the fly), 43 checks
npm run livefire    # end-to-end against a real local OWS install (see harness/)

MIT. Spec surface: observer-protocol/op-policy-engine · observer-protocol/aip.