Repository navigation
Receive the transaction policy engine from wdk-core - #2
Conversation
From tetherto/wdk main at 467b58b: src/policy/* to src/, types/src/policy/* to types/src/, tests/wdk-policy.test.js, docs/policy-exclusions-audit.md, and the repository scaffolding (LICENSE, .github, .npmrc, .npmignore, .editorconfig, .gitignore, tsconfig.json). The next commit packages it.
WdkPolicies attaches to a WDK instance through registerMiddleware, whose middlewares may return a replacement account from @tetherto/wdk 1.0.0-beta.21 on, and returns the engine's governed proxy for every account retrieved from an attached wallet. register, getExclusions and dispose take over registerPolicy, getPolicyExclusions and the policy half of dispose. The engine's own suite runs unchanged except for its import line, through tests/legacy-wdk.js, which rebuilds core's old API on core plus this package, including core's order of applying policies after every middleware; tests/wdk-policies.test.js covers the plugin API. zod is pinned to 4.4.3, the version core's lockfile had: two tests assert zod's error text, which 4.6 changed. README and AGENTS.md carry the sections core had, with a migration table.
- Pin @tetherto/wdk and @tetherto/wdk-wallet exactly in devDependencies; the peer range stays ^1.0.0-beta.21. - tests/legacy-wdk.js keeps its middlewares in a Map. - Rewrap the WdkPolicies documentation lines that ran past 120 columns, in the source and the declarations. - AGENTS.md: the declarations in types/ are hand-maintained, and protocols registered with account.registerProtocol are built with the governed proxy, so their internal account calls are evaluated. - README.md: name attach and dispose parameters blockchains, as the code does.
- One @throws per condition, descriptions without history notes, and parameter descriptions that say what each argument is for, in the source and the declarations. - Import Policy and RegisterPolicyOptions from the engine's index.js. - Plugin tests: a dummy account class, the condition mock at the top level and checked for its arguments, the denial message asserted, and two new cases: attaching several wallets at once, and dispose() with no arguments.
|
We maintain a WDK wallet module for RGB assets that runs in the browser ( Two things we ran into, in case they are useful: 1. A module's own read methods are denied once any policy applies. With only a cap on 2. Peer range vs. the already-tagged |
1.0.0-beta.21 was released with the engine still in core; it calls middlewares without the context argument, so the plugin cannot attach to it.
|
Thanks for trying it in the browser with an RGB module, that's very useful. 1. Reads on third-party modules. Keeping the exclusions an explicit list was deliberate. Deriving them from the read-only class was considered and set aside when the list was built (tetherto/wdk#82), because class placement turned out not to be reliable evidence:
That's why every default exclusion was classified on its documented behaviour (see 2. Peer range. Right, thanks for catching it. |
|
Thanks, both make sense. We'll export the RGB read-only method names from the module so apps can pass them straight to |
| this._attached.set(wdk, attached) | ||
|
|
||
| for (const blockchain of blockchains) { | ||
| this._wallets.add(blockchain) |
There was a problem hiding this comment.
A typo here isn't caught — register() validates against this same set, so attach(wdk, 'etherium') succeeds and the accounts come back ungoverned. Core checked against the wallets actually registered.
There was a problem hiding this comment.
This may require a new public method on core (e.g. wdk.hasWallet), which should be designed on its own rather than rushed in here, so let's leave it out of scope for this PR and we don't want to block on it. Tracking in #3.
It only polls getTransaction, which is already excluded, so a policy that allowed only sends denied waiting on its own transaction. Adds it to the default exclusions and the audit, and moves the pinned counts in the engine suite.
beta.22 has no middleware context or replacement; beta.23 is the first release with both.
requested changes were made; attach validation is tracked in #3
Description
The transaction policy engine moves here from
@tetherto/wdkand publishes as@tetherto/wdk-policies, an opt-in plugin. Core's side, and the hook the plugin relies on, is tetherto/wdk#127, released in@tetherto/wdk1.0.0-beta.23.The first two commits are the copy and the packaging, so a reviewer can see that the engine was copied unchanged. Review fixes follow as small commits.
1. Copy the engine from core, unchanged
Cut from tetherto/wdk
mainat467b58b, which was released unchanged as1.0.0-beta.21, after every open engine fix had been decided (tetherto/wdk#117, tetherto/wdk#119, tetherto/wdk#120 and tetherto/wdk#121 merged; tetherto/wdk#111 closed as a duplicate):src/policy/*→src/types/src/policy/*→types/src/tests/wdk-policy.test.js→tests/docs/policy-exclusions-audit.mdLICENSE,.github/(issue template, PR template, build and publish workflows),.npmrc,.npmignore,.editorconfig,.gitignore,tsconfig.json2. Package it as a plugin
src/wdk-policies.jsdefinesWdkPolicies:new WdkPolicies(options)takes the two settings core's constructor used to take:maxConditionTimeoutMsandpolicyExclusions.attach(wdk, ...blockchains)registers one middleware per wallet. The middleware returns the engine's governed proxy. Attaching the same wallet twice installs one middleware.register(policies, options)replaceswdk.registerPolicy. It throwsPolicyConfigurationErrorfor a policy bound to a wallet that was never attached.getExclusions()replaceswdk.getPolicyExclusions().dispose(blockchains?)replaces the policy half ofwdk.dispose.Exports and types:
index.jsexportsWdkPoliciesas the default, plus the names core exported:PolicyViolationError,PolicyConfigurationError,DEFAULT_POLICY_EXCLUSIONS,DENIAL_CODES, and the policy typedefs.bare.jsis a Bare entry, as core has.types/holds the hand-maintained declarations, withtypes/src/wdk-policies.d.tsadded.Tests:
tests/legacy-wdk.jsrebuilds core's oldregisterPolicyAPI on top of core plus the plugin, including core's order of applying policies after every middleware. The engine's suite then runs with only its import line changed. Porting the suite toWdkPoliciesdirectly can come later.tests/wdk-policies.test.jscovers the plugin's own API.package.json:@tetherto/wdk-policies, version1.0.0-beta.1;@tetherto/wdk^1.0.0-beta.23as a peer dependency, and pinned to1.0.0-beta.23as a dev dependency.1.0.0-beta.22and earlier must not satisfy the peer range: they call a middleware without the context argument, sogetAccount()would throw;zodpinned to4.4.3, the version core's lockfile has. Two engine tests assert zod's exact error text, and zod 4.6 changed it. Loosening the pin means updating those two expectations;bare-node-runtime^1.5.2, for the Bare entry, as core has;package-lock.json.README.mdandAGENTS.mdcarry the sections core had, rewritten for the plugin, with a migration table from@tetherto/wdk1.0.0-beta.21. The README says up front that the engine runs in the caller's own process and is a guardrail against mistakes, not a security boundary.Motivation and Context
The engine lived in
@tetherto/wdk, so every core install shipped it andzod. As a plugin it is opt-in.Attach order matters. A middleware registered after
attachreceives the governed account, which refuses new functions and accessors. The README says to attach after any middleware whose effects should be governed.Changelog note
@tetherto/wdk1.0.0-beta.21 shipped, except thatwaitForTransactionis now inDEFAULT_POLICY_EXCLUSIONS. It only pollsgetTransaction, which was already excluded, so a policy that allowed only sends denied waiting on its own transaction.@tetherto/wdk1.0.0-beta.23or later, where a middleware's return value replaces the account. A middleware that returns a value by accident now replaces the account too.Verification
@tetherto/wdk1.0.0-beta.23from npm: 167 tests pass, the engine's 157 and the plugin's 10.standardis clean.diffoftests/wdk-policy.test.jsagainst core at467b58b: the import line and the three pinned exclusion counts differ.src/andtypes/src/exceptwdk-policies.js,wdk-policies.d.tsandconstants.js(thewaitForTransactionentry) is byte-identical to core'ssrc/policy/andtypes/src/policy/at467b58b.Before the first publish
@tetherto/wdk-policiesexists already, as a0.0.0placeholder.id-token: write) and areleaseenvironment. This repository needs to be added as a trusted publisher for the package, and the environment created.Related Issue
Closes #1
Follow-up: #3,
attachdoes not check that a wallet is registered. It needs a new public method on core, so it is out of scope here.Type of change