@observer-protocol/wdk-op-policy
v0.4.1
Published
Observer Protocol delegation-credential enforcement for the Tether WDK transaction policy engine (PR #55). Ships an ALLOW+DENY policy pair as one unit — the DENY companion is mandatory and fails closed — so a WDK account verifies a signed agent mandate at
Downloads
783
Maintainers
Readme
@observer-protocol/wdk-op-policy
Provenance. This repository is the source of the currently published version of
@observer-protocol/wdk-op-policy, republished as a single snapshot each time the package is published. It makes no promise to track anything between releases: the tree either is the published version's source, or the package has not been published since it was written. Development history lives in a private build repository and is deliberately not published here.Current:
0.4.1. Do not take that on trust. The package ships built output, not this source tree, so a directory diff against the tarball will not match. Check it like this:npm pack @observer-protocol/[email protected] && tar xzf observer-protocol-wdk-op-policy-0.4.1.tgz npm ci && npm run build diff -r package/dist dist
gitHeaddoes not resolve here for0.2.0through0.4.0. Those were published from the private build repo, so thegitHeadrecorded in each of those tarballs names a commit that exists there and not here, whilerepository.urlnames this repository. Of the versions published before0.4.1, only0.1.0resolves against this history. Thenpm packdiff above is the check that works for them.Two related notes.
0.2.0through0.4.0also each carry 13 stale.d.tsfiles underdist/core/describing a vendored core removed on 2026-06-25: the build did not cleandist/, so output from before that removal was republished. Nothing imports them, and0.4.1does not carry them. And the publish guard now refuses to run where the push upstream is not the repositoryrepository.urlnames, which is the check that would have prevented thegitHeadgap in the first place.
The Tether-WDK instance of OP Crossrail — one signed mandate, one rolling cross-rail budget, one shared spend ledger, enforced on every rail an agent pays on. This engine enforces it inside the WDK transaction policy engine.
Co-location contract (read before relying on the cross-rail budget): the cross-rail ledger is a local append-only file with no cross-process locking. Every adapter sharing a budget MUST be handed the SAME path IN THE SAME PROCESS. Different paths give each rail its own budget (the budget multiplies); a shared path across processes races and under-counts. Neither of these fails closed — verify co-location in your deployment. A missing path fails closed (that rail denies).
Enforce a signed Observer Protocol delegation credential on a Tether WDK account — at the signer boundary, fail-closed — via the WDK transaction policy engine (tetherto/wdk #55).
The third Observer Protocol enforcement engine. Same credential, same mandate vocabulary, same vendored core as the OWS verifier and the mppx account — here as a pair of WDK policy rules. The API always registers an ALLOW + DENY pair together: the DENY companion is the mandatory fail-closed backbone (DENY-wins + fail-closed-on-throw), so it holds regardless of what else the consumer registered.
Install
npm install @observer-protocol/wdk-op-policy @tetherto/wdkRequires @tetherto/wdk >= 1.0.0-beta.11 — the first published release carrying the
transaction policy engine (PR #55). Verified against 1.0.0-beta.11 (see
docs/CONFORMANCE.md).
Use
import { registerObserverPolicy } from '@observer-protocol/wdk-op-policy';
registerObserverPolicy(wdk, {
policy: {
credentialPath: '~/.op/agent-delegation.json', // the signed ObserverDelegationCredential
issuerDid: 'did:web:observerprotocol.org',
schemaAllowlist: [
'https://observerprotocol.org/schemas/delegation/v2.1.json',
'https://observerprotocol.org/schemas/delegation/v2.4.json',
],
agentDid: 'did:web:observerprotocol.org:agents:my-agent',
revocation: { maxStalenessHours: 24, onUnreachable: 'cache-then-deny', fetchTimeoutMs: 1500 },
auditLog: '~/.op/decisions.jsonl',
// evmTokens / rails as needed; defaults cover mainnet USDC/USDT
},
wallets: { ethereum: 'eip155:1' }, // wallet label -> CAIP-2 (MUST resolve to a rail)
}, { wallet: 'ethereum' });
// Every write op on the governed account now verifies the mandate before signing.
// Out-of-mandate / unverifiable -> PolicyViolationError; the key never signs.registerObserverPolicy emits two rules — an ALLOW (in-mandate) and a DENY
(violation/uncertainty). Do not hand-author a lone ALLOW, and never pair OP with a
broad permissive wildcard ALLOW on the same operations without the DENY — that reopens a
fail-open hole (proven; see SUPPORT-MATRIX).
What it enforces
Gates sendTransaction, signTransaction, transfer, approve, signTypedData against
per-rail ceiling, counterparty, temporal window, and cross-tx velocity. Exact decode per
operation, the fail-closed construction, rail resolution, and limitations are in
docs/SUPPORT-MATRIX.md; scope/non-goals in
docs/SCOPE.md.
Security model
- Fail-closed: uncertainty (DID/status outage, thrown verification, timeout) blocks — the DENY condition never resolves uncertainty to a silent allow.
- Default-deny aware: OP relies on the engine's default-deny on governed accounts, and the DENY backbone holds even alongside a permissive baseline.
- Enforcement locus: the signer boundary, from the actual operation params — portable across OWS, mppx, and WDK. The binding layer is contested; the enforcement locus is not.
- Validated against the published engine (
@tetherto/[email protected]), 26 conformance cases.
Develop
npm test # typecheck + build + fixtures + 26 conformance cases (real engine)
npm run check:core-sync # vendored core must match ows-op-verify byte-for-byteMIT.
