@keelcodes/policy 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +137 -0
- package/dist/bounded.d.ts +192 -0
- package/dist/bounded.d.ts.map +1 -0
- package/dist/bounded.js +341 -0
- package/dist/bounded.js.map +1 -0
- package/dist/commitment.d.ts +68 -0
- package/dist/commitment.d.ts.map +1 -0
- package/dist/commitment.js +80 -0
- package/dist/commitment.js.map +1 -0
- package/dist/erc20.d.ts +31 -0
- package/dist/erc20.d.ts.map +1 -0
- package/dist/erc20.js +36 -0
- package/dist/erc20.js.map +1 -0
- package/dist/errors.d.ts +13 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +22 -0
- package/dist/errors.js.map +1 -0
- package/dist/evaluate.d.ts +32 -0
- package/dist/evaluate.d.ts.map +1 -0
- package/dist/evaluate.js +125 -0
- package/dist/evaluate.js.map +1 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +23 -0
- package/dist/index.js.map +1 -0
- package/dist/normalize.d.ts +10 -0
- package/dist/normalize.d.ts.map +1 -0
- package/dist/normalize.js +92 -0
- package/dist/normalize.js.map +1 -0
- package/dist/session.d.ts +98 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +128 -0
- package/dist/session.js.map +1 -0
- package/dist/types.d.ts +108 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +21 -0
- package/dist/types.js.map +1 -0
- package/package.json +52 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
Apache License
|
|
2
|
+
Version 2.0, January 2004
|
|
3
|
+
http://www.apache.org/licenses/
|
|
4
|
+
|
|
5
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
6
|
+
|
|
7
|
+
1. Definitions.
|
|
8
|
+
|
|
9
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
10
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
11
|
+
|
|
12
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
13
|
+
the copyright owner that is granting the License.
|
|
14
|
+
|
|
15
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
16
|
+
other entities that control, are controlled by, or are under common
|
|
17
|
+
control with that entity. For the purposes of this definition,
|
|
18
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
19
|
+
direction or management of such entity, whether by contract or
|
|
20
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
21
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
22
|
+
|
|
23
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
24
|
+
exercising permissions granted by this License.
|
|
25
|
+
|
|
26
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
27
|
+
including but not limited to software source code, documentation
|
|
28
|
+
source, and configuration files.
|
|
29
|
+
|
|
30
|
+
"Object" form shall mean any form resulting from mechanical
|
|
31
|
+
transformation or translation of a Source form, including but
|
|
32
|
+
not limited to compiled object code, generated documentation,
|
|
33
|
+
and conversions to other media types.
|
|
34
|
+
|
|
35
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
36
|
+
Object form, made available under the License, as indicated by a
|
|
37
|
+
copyright notice that is included in or attached to the work
|
|
38
|
+
(an example is provided in the Appendix below).
|
|
39
|
+
|
|
40
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
41
|
+
form, that is based on (or derived from) the Work and for which the
|
|
42
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
43
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
44
|
+
of this License, Derivative Works shall not include works that remain
|
|
45
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
46
|
+
the Work and Derivative Works thereof.
|
|
47
|
+
|
|
48
|
+
"Contribution" shall mean any work of authorship, including
|
|
49
|
+
the original version of the Work and any modifications or additions
|
|
50
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
51
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
52
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
53
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
54
|
+
means any form of electronic, verbal, or written communication sent
|
|
55
|
+
to the Licensor or its representatives, including but not limited to
|
|
56
|
+
communication on electronic mailing lists, source code control systems,
|
|
57
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
58
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
59
|
+
excluding communication that is conspicuously marked or otherwise
|
|
60
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
61
|
+
|
|
62
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
63
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
64
|
+
subsequently incorporated within the Work.
|
|
65
|
+
|
|
66
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
67
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
68
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
69
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
70
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
71
|
+
Work and such Derivative Works in Source or Object form.
|
|
72
|
+
|
|
73
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
74
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
75
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
76
|
+
(except as stated in this section) patent license to make, have made,
|
|
77
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
78
|
+
where such license applies only to those patent claims licensable
|
|
79
|
+
by such Contributor that are necessarily infringed by their
|
|
80
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
81
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
82
|
+
institute patent litigation against any entity (including a
|
|
83
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
84
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
85
|
+
or contributory patent infringement, then any patent licenses
|
|
86
|
+
granted to You under this License for that Work shall terminate
|
|
87
|
+
as of the date such litigation is filed.
|
|
88
|
+
|
|
89
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
90
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
91
|
+
modifications, and in Source or Object form, provided that You
|
|
92
|
+
meet the following conditions:
|
|
93
|
+
|
|
94
|
+
(a) You must give any other recipients of the Work or
|
|
95
|
+
Derivative Works a copy of this License; and
|
|
96
|
+
|
|
97
|
+
(b) You must cause any modified files to carry prominent notices
|
|
98
|
+
stating that You changed the files; and
|
|
99
|
+
|
|
100
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
101
|
+
that You distribute, all copyright, patent, trademark, and
|
|
102
|
+
attribution notices from the Source form of the Work,
|
|
103
|
+
excluding those notices that do not pertain to any part of
|
|
104
|
+
the Derivative Works; and
|
|
105
|
+
|
|
106
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
107
|
+
distribution, then any Derivative Works that You distribute must
|
|
108
|
+
include a readable copy of the attribution notices contained
|
|
109
|
+
within such NOTICE file, excluding those notices that do not
|
|
110
|
+
pertain to any part of the Derivative Works, in at least one
|
|
111
|
+
of the following places: within a NOTICE text file distributed
|
|
112
|
+
as part of the Derivative Works; within the Source form or
|
|
113
|
+
documentation, if provided along with the Derivative Works; or,
|
|
114
|
+
within a display generated by the Derivative Works, if and
|
|
115
|
+
wherever such third-party notices normally appear. The contents
|
|
116
|
+
of the NOTICE file are for informational purposes only and
|
|
117
|
+
do not modify the License. You may add Your own attribution
|
|
118
|
+
notices within Derivative Works that You distribute, alongside
|
|
119
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
120
|
+
that such additional attribution notices cannot be construed
|
|
121
|
+
as modifying the License.
|
|
122
|
+
|
|
123
|
+
You may add Your own copyright statement to Your modifications and
|
|
124
|
+
may provide additional or different license terms and conditions
|
|
125
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
126
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
127
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
128
|
+
the conditions stated in this License.
|
|
129
|
+
|
|
130
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
131
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
132
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
133
|
+
this License, without any additional terms or conditions.
|
|
134
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
135
|
+
the terms of any separate license agreement you may have executed
|
|
136
|
+
with Licensor regarding such Contributions.
|
|
137
|
+
|
|
138
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
139
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
140
|
+
except as required for reasonable and customary use in describing the
|
|
141
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
142
|
+
|
|
143
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
144
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
145
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
146
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
147
|
+
implied, including, without limitation, any warranties or conditions
|
|
148
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
149
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
150
|
+
appropriateness of using or redistributing the Work and assume any
|
|
151
|
+
risks associated with Your exercise of permissions under this License.
|
|
152
|
+
|
|
153
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
154
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
155
|
+
unless required by applicable law (such as deliberate and grossly
|
|
156
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
157
|
+
liable to You for damages, including any direct, indirect, special,
|
|
158
|
+
incidental, or consequential damages of any character arising as a
|
|
159
|
+
result of this License or out of the use or inability to use the
|
|
160
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
161
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
162
|
+
other commercial damages or losses), even if such Contributor
|
|
163
|
+
has been advised of the possibility of such damages.
|
|
164
|
+
|
|
165
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
166
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
167
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
168
|
+
or other liability obligations and/or rights consistent with this
|
|
169
|
+
License. However, in accepting such obligations, You may act only
|
|
170
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
171
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
172
|
+
defend, and hold each Contributor harmless for any liability
|
|
173
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
174
|
+
of your accepting any such warranty or additional liability.
|
|
175
|
+
|
|
176
|
+
END OF TERMS AND CONDITIONS
|
|
177
|
+
|
|
178
|
+
APPENDIX: How to apply the Apache License to your work.
|
|
179
|
+
|
|
180
|
+
To apply the Apache License to your work, attach the following
|
|
181
|
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
182
|
+
replaced with your own identifying information. (Don't include
|
|
183
|
+
the brackets!) The text should be enclosed in the appropriate
|
|
184
|
+
comment syntax for the file format. We also recommend that a
|
|
185
|
+
file or class name and description of purpose be included on the
|
|
186
|
+
same "printed page" as the copyright notice for easier
|
|
187
|
+
identification within third-party archives.
|
|
188
|
+
|
|
189
|
+
Copyright 2026 Keel contributors
|
|
190
|
+
|
|
191
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
192
|
+
you may not use this file except in compliance with the License.
|
|
193
|
+
You may obtain a copy of the License at
|
|
194
|
+
|
|
195
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
196
|
+
|
|
197
|
+
Unless required by applicable law or agreed to in writing, software
|
|
198
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
199
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
200
|
+
See the License for the specific language governing permissions and
|
|
201
|
+
limitations under the License.
|
package/README.md
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# @keelcodes/policy
|
|
2
|
+
|
|
3
|
+
Account-agnostic authorization policy for agent accounts.
|
|
4
|
+
|
|
5
|
+
A policy declares **what an agent may do** with an account: which target
|
|
6
|
+
contracts it may call, which methods on them, and the value / frequency
|
|
7
|
+
ceilings. The model contains no account-specific encoding, so the same `Policy`
|
|
8
|
+
works across Kernel, Nexus and Safe7579.
|
|
9
|
+
|
|
10
|
+
This package is the **off-chain core**: the DSL, a canonical commitment hash, a
|
|
11
|
+
pre-check / simulation layer, and multi-session lifecycle management. The
|
|
12
|
+
on-chain carrier for enforcement is a **Keel ERC-7579 hook module**
|
|
13
|
+
(account-agnostic: a hook sees the execution of any 7579 account without parsing
|
|
14
|
+
account-specific call data). The hook recomputes the same commitment, so the two
|
|
15
|
+
layers cannot disagree about what a policy means.
|
|
16
|
+
|
|
17
|
+
## Policy DSL
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
import { normalizePolicy, policyCommitment } from '@keelcodes/policy';
|
|
21
|
+
|
|
22
|
+
const policy = normalizePolicy({
|
|
23
|
+
validAfter: 0n, // unix seconds; 0 = immediately
|
|
24
|
+
validUntil: 1_800_000_000n, // 0 = never
|
|
25
|
+
rules: [{
|
|
26
|
+
target: USDC, selectors: ['0xa9059cbb'],
|
|
27
|
+
maxPerTx: 10n ** 6n, maxDaily: 10n ** 7n, maxCalls: 50, // native value / count
|
|
28
|
+
tokenLimits: [{ token: USDC, maxPerTx: 10n ** 6n, maxDaily: 10n ** 7n }], // ERC-20 amount
|
|
29
|
+
}],
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
policyCommitment(policy); // keccak256(abi.encode(version, validAfter, validUntil, rules))
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Each rule scopes to one `target` with optional `selectors` (empty = any method)
|
|
36
|
+
and ceilings: `maxPerTx` (native value per call), `maxDaily` (native value per
|
|
37
|
+
day), `maxCalls` (call count). `0` / omitted means unlimited.
|
|
38
|
+
|
|
39
|
+
`normalizePolicy` fills every optional with its zero default and lower-cases
|
|
40
|
+
addresses, so `{ maxPerTx: 0n }` and `{}` produce the **same** commitment. A
|
|
41
|
+
malformed policy throws `PolicyError` at definition time.
|
|
42
|
+
|
|
43
|
+
## ERC-20 token limits
|
|
44
|
+
|
|
45
|
+
`tokenLimits` adds per-token amount ceilings (`maxPerTx` / `maxDaily`) on top
|
|
46
|
+
of the native-value caps. The token must equal the rule's `target` — a cap can
|
|
47
|
+
only be enforced on calls made **directly** to the token, so a limit for any
|
|
48
|
+
other address is rejected as dead config.
|
|
49
|
+
|
|
50
|
+
Amounts are read from the standard `transfer` / `approve` / `transferFrom` call
|
|
51
|
+
data (the amount is the final `uint256` word). While a limit is configured:
|
|
52
|
+
|
|
53
|
+
- `transfer` / `approve` are capped by the token ceilings;
|
|
54
|
+
- `transferFrom` is **refused** (`token-transfer-from-blocked`) — bounding a
|
|
55
|
+
pull from an arbitrary address is ambiguous, so the conservative choice is to
|
|
56
|
+
reject it;
|
|
57
|
+
- a malformed standard call is refused (`token-amount-unparsable`);
|
|
58
|
+
- any other selector is left to the rule's `selectors` whitelist.
|
|
59
|
+
|
|
60
|
+
Token caps apply to the immediate call target only; a token moved *inside* a
|
|
61
|
+
router call is not covered by this rule (use a rule on the token itself).
|
|
62
|
+
|
|
63
|
+
## Pre-check & simulation
|
|
64
|
+
|
|
65
|
+
`evaluateCall` applies validity, rule matching (first match in declared order)
|
|
66
|
+
and the ceilings. `simulateCalls` dry-runs a batch, accumulating usage so a
|
|
67
|
+
batch that only breaches a cap together is caught, and returns the first denial
|
|
68
|
+
with a machine-readable reason — before a bundler round-trip that would end in
|
|
69
|
+
a validation failure.
|
|
70
|
+
|
|
71
|
+
```ts
|
|
72
|
+
import { evaluateCall, simulateCalls, toCall } from '@keelcodes/policy';
|
|
73
|
+
|
|
74
|
+
const call = toCall({ target: USDC, value: 0n, data: transferCalldata });
|
|
75
|
+
evaluateCall(policy, { now: 1_700_000_000n, usage: [] }, call);
|
|
76
|
+
// → { allowed: true, ruleIndex: 0 }
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
`PolicyState.usage` is aligned to `policy.rules` by index; callers reset
|
|
80
|
+
`dailySpent` / `tokenSpent` when the day window rolls over.
|
|
81
|
+
|
|
82
|
+
## Hook install payload
|
|
83
|
+
|
|
84
|
+
The on-chain hook installs one session at a time. `encodeInstallData(sessionId,
|
|
85
|
+
policy)` builds the exact payload it decodes — `abi.encode(bytes32 sessionId,
|
|
86
|
+
bytes policyData)` with `policyData = encodePolicy(policy)`. The session's
|
|
87
|
+
on-chain commitment is therefore `keccak256(policyData) === policyCommitment(policy)`,
|
|
88
|
+
so an installed session can be verified against what was signed.
|
|
89
|
+
|
|
90
|
+
```ts
|
|
91
|
+
import { encodeInstallData } from '@keelcodes/policy';
|
|
92
|
+
|
|
93
|
+
encodeInstallData(session.id, session.policy); // → onInstall bytes
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Multi-session lifecycle
|
|
97
|
+
|
|
98
|
+
An account may hold **many concurrent sessions** — one policy grant each — which
|
|
99
|
+
fixes the old "one account, one session" limitation. A session is an immutable
|
|
100
|
+
record carrying the policy, its commitment and lifecycle metadata, and it holds
|
|
101
|
+
**no key material**: it references a policy, not a private key, so key custody
|
|
102
|
+
stays with the caller (KMS or the client).
|
|
103
|
+
|
|
104
|
+
```ts
|
|
105
|
+
import { InMemorySessionStore, issueSession, revokeSession, rotateSession } from '@keelcodes/policy';
|
|
106
|
+
|
|
107
|
+
const store = new InMemorySessionStore();
|
|
108
|
+
const session = await issueSession(store, { account, policy, now });
|
|
109
|
+
await revokeSession(store, session.id, now);
|
|
110
|
+
const { previous, next } = await rotateSession(store, session.id, { policy, now });
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
`sessionStatus(session, now)` derives `pending` / `active` / `expired` /
|
|
114
|
+
`revoked` from the record, and `listSessions(store, account, now)` returns an
|
|
115
|
+
account's sessions with their status. Revocation is append-only (the record is
|
|
116
|
+
kept with `revokedAt`, so it stays auditable), and a rotation cross-links the
|
|
117
|
+
predecessor and successor (`rotatedFrom` / `rotatedTo`) — the off-chain half of
|
|
118
|
+
the migration "uninstall old module + install new" (docs/KEEL_PLAN.md §7.5).
|
|
119
|
+
Persistence goes through the async `SessionStore` port, so a database-backed
|
|
120
|
+
store drops in; `InMemorySessionStore` is the minimal reference (no tenancy —
|
|
121
|
+
one Keel stack per product, see §6.3).
|
|
122
|
+
|
|
123
|
+
## Scope
|
|
124
|
+
|
|
125
|
+
- ✅ Declarative DSL + normalisation + validation
|
|
126
|
+
- ✅ Canonical commitment hash (ABI encoding shared with the on-chain carrier)
|
|
127
|
+
- ✅ Off-chain pre-check + batch simulation
|
|
128
|
+
- ✅ ERC-20 token limits (`maxPerTx` / `maxDaily` per token)
|
|
129
|
+
- ✅ ERC-7579 hook module (`KeelPolicyHook`, Solidity) enforcing the same rules on-chain, many sessions per account (see `contracts/`)
|
|
130
|
+
- ✅ Multi-session lifecycle (issue / revoke / rotate) + pluggable `SessionStore`
|
|
131
|
+
|
|
132
|
+
Pre-alpha. The public API is not stable yet.
|
|
133
|
+
|
|
134
|
+
## Out of scope
|
|
135
|
+
|
|
136
|
+
- Account implementations (see `@keelcodes/adapters`)
|
|
137
|
+
- Billing and multi-tenancy
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import type { Address, Hex } from './types.js';
|
|
2
|
+
/** Schema version mixed into `capabilityRoot`, so a future profile change can never collide with an older one. */
|
|
3
|
+
export declare const CAPABILITY_VERSION = 1;
|
|
4
|
+
/**
|
|
5
|
+
* Lifecycle status of an envelope, matching the standard's `Status` enum
|
|
6
|
+
* (including `None`, the "unknown id" result of `getStatus`).
|
|
7
|
+
*/
|
|
8
|
+
export declare enum EnvelopeStatus {
|
|
9
|
+
None = 0,
|
|
10
|
+
Active = 1,
|
|
11
|
+
Completed = 2,
|
|
12
|
+
Contested = 3,
|
|
13
|
+
Revoked = 4,
|
|
14
|
+
Expired = 5
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* A committed label a consumer can require a minimum of (e.g. a target
|
|
18
|
+
* contract that only accepts envelopes of tier >= 2). The standard treats
|
|
19
|
+
* `capabilityRoot` as opaque; Keel fixes four ordered tiers so the label is
|
|
20
|
+
* meaningful across the policy layer, the substrate and the manifest layer.
|
|
21
|
+
*/
|
|
22
|
+
export type TrustTier = 0 | 1 | 2 | 3;
|
|
23
|
+
/** An M-of-N approval set; `threshold` of `approvers` must sign before a release gate opens. */
|
|
24
|
+
export interface ApprovalInput {
|
|
25
|
+
/** Number of approvals required; `0` means no approval gate. */
|
|
26
|
+
threshold?: number;
|
|
27
|
+
/** Distinct approver addresses. */
|
|
28
|
+
approvers?: readonly Address[];
|
|
29
|
+
}
|
|
30
|
+
/** The bounded authority an envelope commits to, as authored. */
|
|
31
|
+
export interface CapabilityInput {
|
|
32
|
+
/** Asset the budget is denominated in; the zero address means native value. */
|
|
33
|
+
asset: Address;
|
|
34
|
+
/** Budget ceiling for the whole envelope; `0` means no spend authority. */
|
|
35
|
+
cap?: bigint;
|
|
36
|
+
/** Ordered trust label consumers may require a minimum of; defaults to 0. */
|
|
37
|
+
trustTier?: TrustTier;
|
|
38
|
+
/** Unix seconds before which no draw may be released; `0` means immediately. */
|
|
39
|
+
notBefore?: bigint;
|
|
40
|
+
/** M-of-N gate that must be satisfied before any draw is released. */
|
|
41
|
+
approvals?: ApprovalInput;
|
|
42
|
+
/** Whether the envelope may delegate an attenuated child. */
|
|
43
|
+
delegate?: boolean;
|
|
44
|
+
}
|
|
45
|
+
/** A fully-populated, hash-stable capability. */
|
|
46
|
+
export interface Capability {
|
|
47
|
+
readonly version: number;
|
|
48
|
+
readonly asset: Address;
|
|
49
|
+
readonly cap: bigint;
|
|
50
|
+
readonly trustTier: TrustTier;
|
|
51
|
+
readonly notBefore: bigint;
|
|
52
|
+
readonly approvals: {
|
|
53
|
+
readonly threshold: number;
|
|
54
|
+
readonly approvers: readonly Address[];
|
|
55
|
+
};
|
|
56
|
+
readonly delegate: boolean;
|
|
57
|
+
}
|
|
58
|
+
/** Running aggregate state committed by `cursorRoot`. */
|
|
59
|
+
export interface Cursor {
|
|
60
|
+
/** Total amount drawn against the capability so far. */
|
|
61
|
+
readonly spent: bigint;
|
|
62
|
+
/** Number of draws, used for idempotency and telemetry. */
|
|
63
|
+
readonly draws: number;
|
|
64
|
+
/** Unix seconds of the most recent advance; `0` until the first draw. */
|
|
65
|
+
readonly lastAdvance: bigint;
|
|
66
|
+
}
|
|
67
|
+
/** An on-chain envelope, as read from a registry. */
|
|
68
|
+
export interface Envelope {
|
|
69
|
+
readonly id: Hex;
|
|
70
|
+
readonly principal: Address;
|
|
71
|
+
readonly capabilityRoot: Hex;
|
|
72
|
+
readonly cursorRoot: Hex;
|
|
73
|
+
readonly createdAt: bigint;
|
|
74
|
+
readonly expiresAt: bigint;
|
|
75
|
+
readonly status: EnvelopeStatus;
|
|
76
|
+
}
|
|
77
|
+
/** Cross-chain/same-chain reference to an envelope; the pair (registry, id) suffices on one chain. */
|
|
78
|
+
export interface EnvelopeRef {
|
|
79
|
+
readonly chainId: bigint;
|
|
80
|
+
readonly registry: Address;
|
|
81
|
+
readonly id: Hex;
|
|
82
|
+
}
|
|
83
|
+
/** Why a draw was refused. */
|
|
84
|
+
export type DrawDenyReason = 'envelope-not-active' | 'not-yet-released' | 'cap-exceeded' | 'approval-required' | 'trust-tier-too-low';
|
|
85
|
+
/** The context a draw is evaluated in. */
|
|
86
|
+
export interface DrawContext {
|
|
87
|
+
/** Current unix time in seconds. */
|
|
88
|
+
readonly now: bigint;
|
|
89
|
+
/** Effective status of the envelope at `now`. */
|
|
90
|
+
readonly status: EnvelopeStatus;
|
|
91
|
+
/** Collected approvals (distinct approver addresses). */
|
|
92
|
+
readonly approvals?: readonly Address[];
|
|
93
|
+
/** Minimum trust tier the caller requires; defaults to 0. */
|
|
94
|
+
readonly minTier?: TrustTier;
|
|
95
|
+
}
|
|
96
|
+
/** Result of a draw evaluation; `reason` is set only when `allowed` is false. */
|
|
97
|
+
export interface DrawDecision {
|
|
98
|
+
readonly allowed: boolean;
|
|
99
|
+
readonly reason?: DrawDenyReason;
|
|
100
|
+
}
|
|
101
|
+
declare const ZERO_ADDRESS: Address;
|
|
102
|
+
/**
|
|
103
|
+
* Validates an authored capability and returns its normalised form. Addresses
|
|
104
|
+
* are lower-cased and every optional field is filled with its default, so
|
|
105
|
+
* semantically identical capabilities always commit to the same root.
|
|
106
|
+
*/
|
|
107
|
+
export declare function normalizeCapability(input: CapabilityInput): Capability;
|
|
108
|
+
/** Canonical ABI encoding of a normalised capability. */
|
|
109
|
+
export declare function encodeCapability(capability: Capability): Hex;
|
|
110
|
+
/** `capabilityRoot = keccak256(encodeCapability(capability))`. */
|
|
111
|
+
export declare function capabilityCommitment(capability: Capability): Hex;
|
|
112
|
+
/** Canonical ABI encoding of a cursor. */
|
|
113
|
+
export declare function encodeCursor(cursor: Cursor): Hex;
|
|
114
|
+
/** `cursorRoot = keccak256(encodeCursor(cursor))`. */
|
|
115
|
+
export declare function cursorCommitment(cursor: Cursor): Hex;
|
|
116
|
+
/** The cursor of an envelope that has never been drawn against. */
|
|
117
|
+
export declare const ZERO_CURSOR: Cursor;
|
|
118
|
+
/**
|
|
119
|
+
* Deterministic envelope id, per the standard's recommended derivation
|
|
120
|
+
* `keccak256(abi.encode(registry, principal, capabilityRoot, salt))`. A
|
|
121
|
+
* registry may precompute it before registering so a reference can be embedded
|
|
122
|
+
* upstream.
|
|
123
|
+
*/
|
|
124
|
+
export declare function envelopeId(params: {
|
|
125
|
+
registry: Address;
|
|
126
|
+
principal: Address;
|
|
127
|
+
capabilityRoot: Hex;
|
|
128
|
+
salt: Hex;
|
|
129
|
+
}): Hex;
|
|
130
|
+
/** Remaining headroom under a capability's cap. Never negative. */
|
|
131
|
+
export declare function remaining(capability: Capability, cursor: Cursor): bigint;
|
|
132
|
+
/**
|
|
133
|
+
* The budget invariant, `spent + amount <= cap`. Exposed separately so a
|
|
134
|
+
* caller can check a prospective draw without constructing a full context.
|
|
135
|
+
*/
|
|
136
|
+
export declare function withinCap(capability: Capability, cursor: Cursor, amount: bigint): boolean;
|
|
137
|
+
/** Whether the collected approvals satisfy the capability's M-of-N gate. */
|
|
138
|
+
export declare function approvalsSatisfied(capability: Capability, approvals: readonly Address[]): boolean;
|
|
139
|
+
/**
|
|
140
|
+
* Evaluates a prospective draw. Mirrors the on-chain substrate's gates in the
|
|
141
|
+
* same order — status, release time, trust tier, approvals, then the budget
|
|
142
|
+
* invariant — so an off-chain denial is never more permissive than the chain.
|
|
143
|
+
*/
|
|
144
|
+
export declare function canDraw(capability: Capability, cursor: Cursor, amount: bigint, context: DrawContext): DrawDecision;
|
|
145
|
+
/**
|
|
146
|
+
* Advances the cursor by one accepted draw. The caller must have obtained an
|
|
147
|
+
* allowed {@link canDraw} first; this function does not re-check the cap.
|
|
148
|
+
*/
|
|
149
|
+
export declare function advanceCursor(cursor: Cursor, amount: bigint, now: bigint): Cursor;
|
|
150
|
+
/** Derived status: an envelope past its expiry reads as `Expired` while it is not terminal. */
|
|
151
|
+
export declare function effectiveStatus(envelope: Envelope, now: bigint): EnvelopeStatus;
|
|
152
|
+
/** Throws unless `allocations` sum to at most `rootCap` (conservation). */
|
|
153
|
+
export declare function assertConservation(rootCap: bigint, allocations: readonly bigint[]): void;
|
|
154
|
+
/**
|
|
155
|
+
* Derives an attenuated child capability from a parent.
|
|
156
|
+
*
|
|
157
|
+
* Narrowing only: the child's cap and trust tier may not exceed the parent's,
|
|
158
|
+
* its release time may not be earlier, its approval gate may not be weaker
|
|
159
|
+
* (threshold no lower, approvers a subset of the parent's) and its asset must
|
|
160
|
+
* match. A parent that is not allowed to delegate (or is itself attenuated) may
|
|
161
|
+
* not spawn a child at all. The child is always barred from delegating further,
|
|
162
|
+
* which is what makes attenuation non-transitive widening impossible.
|
|
163
|
+
*/
|
|
164
|
+
export declare function attenuate(parent: Capability, child: CapabilityInput, options?: {
|
|
165
|
+
parentAttenuated?: boolean;
|
|
166
|
+
}): Capability;
|
|
167
|
+
/** Whether `to` is a legal successor of `from`. */
|
|
168
|
+
export declare function canSetStatus(from: EnvelopeStatus, to: EnvelopeStatus): boolean;
|
|
169
|
+
/** Applies a status transition, throwing {@link EnvelopeError} when it is illegal. */
|
|
170
|
+
export declare function applyStatus(envelope: Envelope, to: EnvelopeStatus): Envelope;
|
|
171
|
+
/** Whether a status is terminal (no successor). */
|
|
172
|
+
export declare function isTerminal(status: EnvelopeStatus): boolean;
|
|
173
|
+
/**
|
|
174
|
+
* The contest window a challenge opens. Any party the substrate permits may
|
|
175
|
+
* contest an Active envelope; once contested, resolution must land within the
|
|
176
|
+
* window or any caller may resolve to the documented default (`Active`), which
|
|
177
|
+
* stops an accused party from running out the clock to foreclose a verdict.
|
|
178
|
+
*/
|
|
179
|
+
export interface ContestWindow {
|
|
180
|
+
/** Unix seconds the contest was opened. */
|
|
181
|
+
readonly contestedAt: bigint;
|
|
182
|
+
/** Unix seconds after which a default resolution is permitted. */
|
|
183
|
+
readonly resolutionDeadline: bigint;
|
|
184
|
+
}
|
|
185
|
+
/** Opens a contest window of `windowSeconds` from `now`. */
|
|
186
|
+
export declare function openContest(now: bigint, windowSeconds: bigint): ContestWindow;
|
|
187
|
+
/** Whether the window has elapsed at `now`, letting any caller resolve to the default. */
|
|
188
|
+
export declare function contestExpired(window: ContestWindow, now: bigint): boolean;
|
|
189
|
+
/** The documented default resolution: a still-open contest lapses back to Active. */
|
|
190
|
+
export declare function defaultResolution(): EnvelopeStatus;
|
|
191
|
+
export { ZERO_ADDRESS as ZERO_ASSET };
|
|
192
|
+
//# sourceMappingURL=bounded.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bounded.d.ts","sourceRoot":"","sources":["../src/bounded.ts"],"names":[],"mappings":"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"}
|