@bananapus/permission-ids-v6 0.0.17 → 0.0.19

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/ADMINISTRATION.md CHANGED
@@ -1,147 +1,62 @@
1
1
  # Administration
2
2
 
3
- Admin privileges and their scope in nana-permission-ids-v6.
4
-
5
3
  ## At A Glance
6
4
 
7
5
  | Item | Details |
8
- |------|---------|
9
- | Scope | Reference library for the permission IDs consumed across the Juicebox V6 ecosystem. No contract in this repo has mutable runtime state. |
10
- | Operators | Maintainers who change the constant list in source and downstream repos that consume those constants. |
11
- | Highest-risk actions | Renumbering or repurposing a permission ID that downstream contracts already depend on. |
12
- | Recovery posture | Runtime admin recovery does not apply here. If the constants are wrong, downstream code and docs have to be updated and redeployed against the corrected source. |
13
-
14
- ## Routine Operations
15
-
16
- - Treat `JBPermissionIds.sol` as a coordination artifact across repos, not a place for casual edits.
17
- - When adding a new permission, update the source library and the dependent repo docs together so operator guidance does not drift from code.
18
- - Re-check downstream permission assumptions after any change because multiple repos gate admin behavior through this single numbering scheme.
6
+ | --- | --- |
7
+ | Scope | Shared permission ID namespace for the wider ecosystem |
8
+ | Control posture | Source-level coordination only |
9
+ | Highest-risk actions | Reordering or reusing IDs already assumed by deployed contracts |
10
+ | Recovery posture | Requires downstream code changes and redeployments where relevant |
11
+
12
+ ## Purpose
13
+
14
+ `nana-permission-ids-v6` has no runtime admin surface. Its control significance is at the source level: it defines the shared permission namespace used by the rest of the ecosystem.
15
+
16
+ ## Control Model
17
+
18
+ - No owner
19
+ - No runtime governance
20
+ - No mutable onchain state
21
+ - Source-level coordination only
22
+
23
+ ## Roles
19
24
 
20
- ## One-Way Or High-Risk Actions
25
+ | Role | How Assigned | Scope | Notes |
26
+ | --- | --- | --- | --- |
27
+ | Maintainer | Source-code author | Ecosystem-wide | Can add or reorder constants only by editing code and updating dependent deployments |
21
28
 
22
- - Changing an existing numeric assignment can silently invalidate permission checks in dependent repos.
23
- - The library itself has no admin keys, but stale docs around it can mislead operators about real powers elsewhere in the ecosystem.
29
+ ## Privileged Surfaces
24
30
 
25
- ## Recovery Notes
31
+ There are no privileged runtime functions. The only meaningful changes are source changes to `JBPermissionIds.sol`.
26
32
 
27
- - If the permission map drifts from deployed contracts, the fix is coordinated source and documentation updates in the dependent repos, plus redeployment where the old numeric assumptions are already live.
28
- - There is no on-chain migration knob in this repo because it only ships compile-time constants.
33
+ ## Immutable And One-Way
29
34
 
30
- ## Overview
35
+ - Once deployed contracts depend on a given ID mapping, that mapping is effectively immutable for those deployments.
36
+ - Reusing or reordering IDs is a cross-repo breaking change.
31
37
 
32
- This repo defines permission ID constants. It contains no admin functions itself -- it is a reference library for the permission system used across the Juicebox V6 ecosystem. The constants in `JBPermissionIds` are consumed by contracts in nana-core-v6, nana-721-hook-v6, nana-buyback-hook-v6, nana-router-terminal-v6, and nana-suckers-v6 to gate privileged operations.
38
+ ## Operational Notes
33
39
 
34
- There are no ownable contracts, no upgrade mechanisms, and no mutable state. The library compiles to inline constants.
40
+ - Add new permission IDs append-only.
41
+ - Update downstream docs and call sites in the same change set.
42
+ - Treat permission ID changes as protocol changes, not refactors.
35
43
 
36
- ## Permission IDs
44
+ ## Machine Notes
37
45
 
38
- All 40 defined permission IDs and what they control:
46
+ - Do not infer semantic compatibility from matching names if numeric IDs changed.
47
+ - Treat `src/JBPermissionIds.sol` as append-only unless a breaking ecosystem-wide migration is intentional.
48
+ - If docs and code disagree on a permission number, trust the code and update the docs before further review.
39
49
 
40
- | ID | Constant | Used By | What It Controls |
41
- |----|----------|---------|-----------------|
42
- | 1 | `ROOT` | All contracts (via `JBPermissions`) | Grants every permission. See [ROOT Permission](#root-permission). |
43
- | 2 | `QUEUE_RULESETS` | nana-core (`JBController`) | `JBController.queueRulesetsOf` -- queue new rulesets for a project. |
44
- | 3 | `LAUNCH_RULESETS` | nana-core (`JBController`) | `JBController.launchRulesetsFor` -- launch a project's initial rulesets. Also requires `SET_TERMINALS` (ID 15). |
45
- | 4 | `CASH_OUT_TOKENS` | nana-core (`JBMultiTerminal`) | `JBMultiTerminal.cashOutTokensOf` -- redeem tokens for surplus. Checked against the **token holder**, not the project owner. |
46
- | 5 | `SEND_PAYOUTS` | nana-core (`JBMultiTerminal`) | `JBMultiTerminal.sendPayoutsOf` -- distribute payouts to splits. |
47
- | 6 | `MIGRATE_TERMINAL` | nana-core (`JBMultiTerminal`) | `JBMultiTerminal.migrateBalanceOf` -- migrate a project's balance to another terminal. |
48
- | 7 | `SET_PROJECT_URI` | nana-core (`JBController`) | `JBController.setUriOf` -- set project metadata URI. |
49
- | 8 | `DEPLOY_ERC20` | nana-core (`JBController`) | `JBController.deployERC20For` -- deploy a new ERC-20 token for a project. |
50
- | 9 | `SET_TOKEN` | nana-core (`JBController`) | `JBController.setTokenFor` -- set an existing ERC-20 token for a project. |
51
- | 10 | `MINT_TOKENS` | nana-core (`JBController`) | `JBController.mintTokensOf` -- mint new project tokens. Only effective when the current ruleset allows owner minting. |
52
- | 11 | `BURN_TOKENS` | nana-core (`JBController`) | `JBController.burnTokensOf` -- burn tokens. Checked against the **token holder**. |
53
- | 12 | `CLAIM_TOKENS` | nana-core (`JBController`) | `JBController.claimTokensFor` -- claim internal credits as ERC-20. Checked against the **token holder**. |
54
- | 13 | `TRANSFER_CREDITS` | nana-core (`JBController`) | `JBController.transferCreditsFrom` -- transfer internal credits. Checked against the **token holder**. |
55
- | 14 | `SET_CONTROLLER` | nana-core (`JBDirectory`) | `JBDirectory.setControllerOf` -- set a project's controller. |
56
- | 15 | `SET_TERMINALS` | nana-core (`JBDirectory`) | `JBDirectory.setTerminalsOf` -- set a project's terminals. **Warning:** can remove the primary terminal. |
57
- | 16 | `ADD_TERMINALS` | nana-core (`JBDirectory`) | `JBDirectory.setPrimaryTerminalOf` -- add a new terminal when `setPrimaryTerminalOf` implicitly adds it. |
58
- | 17 | `SET_PRIMARY_TERMINAL` | nana-core (`JBDirectory`) | `JBDirectory.setPrimaryTerminalOf` -- set the primary terminal for a token. |
59
- | 18 | `USE_ALLOWANCE` | nana-core (`JBMultiTerminal`) | `JBMultiTerminal.useAllowanceOf` -- spend surplus allowance to an arbitrary address. |
60
- | 19 | `SET_SPLIT_GROUPS` | nana-core (`JBController`) | `JBController.setSplitGroupsOf` -- configure payout and reserved token splits. |
61
- | 20 | `ADD_PRICE_FEED` | nana-core (`JBController`) | `JBController.addPriceFeedFor` (which internally calls `JBPrices.addPriceFeedFor`) -- add a price feed for a project. |
62
- | 21 | `ADD_ACCOUNTING_CONTEXTS` | nana-core (`JBMultiTerminal`) | `JBMultiTerminal.addAccountingContextsFor` -- add accepted tokens to a terminal. |
63
- | 22 | `SET_TOKEN_METADATA` | nana-core (`JBController`) | `JBController.setTokenMetadataOf` -- set a project token's name and symbol. |
64
- | 23 | `SIGN_FOR_ERC20` | nana-core (`JBERC20`) | Sign messages on behalf of a project's ERC-20 token via ERC-1271. Used for Etherscan contract verification and other off-chain signature validation. |
65
- | 24 | `ADJUST_721_TIERS` | nana-721-hook (`JB721TiersHook`) | `JB721TiersHook.adjustTiers` -- add or remove NFT tiers. |
66
- | 25 | `SET_721_METADATA` | nana-721-hook (`JB721TiersHook`) | `JB721TiersHook.setMetadata` -- set NFT metadata URIs. |
67
- | 26 | `MINT_721` | nana-721-hook (`JB721TiersHook`) | `JB721TiersHook.mintFor` -- manually mint NFTs to a beneficiary. |
68
- | 27 | `SET_721_DISCOUNT_PERCENT` | nana-721-hook (`JB721TiersHook`) | `JB721TiersHook.setDiscountPercentOf` -- set discount percent on NFT tiers. |
69
- | 28 | `SET_BUYBACK_TWAP` | nana-buyback-hook (`JBBuybackHook`) | `JBBuybackHook.setTwapWindowOf` -- configure the TWAP oracle window. |
70
- | 29 | `SET_BUYBACK_POOL` | nana-buyback-hook (`JBBuybackHook`) | `JBBuybackHook.setPoolFor` -- set the Uniswap pool for buybacks. |
71
- | 30 | `SET_BUYBACK_HOOK` | nana-buyback-hook (`JBBuybackHookRegistry`) | `JBBuybackHookRegistry.setHookFor` and `lockHookFor` -- configure and permanently lock the buyback hook. |
72
- | 31 | `SET_ROUTER_TERMINAL` | nana-router-terminal (`JBRouterTerminalRegistry`) | `JBRouterTerminalRegistry.setTerminalFor` and `lockTerminalFor` -- configure and permanently lock the router terminal. |
73
- | 32 | `MAP_SUCKER_TOKEN` | nana-suckers (`JBSucker`) | `JBSucker.mapToken` -- map an ERC-20 to its remote chain counterpart. Immutable once the outbox tree has entries. |
74
- | 33 | `DEPLOY_SUCKERS` | nana-suckers (`JBSuckerRegistry`) | `JBSuckerRegistry.deploySuckersFor` -- deploy sucker contracts for cross-chain bridging. |
75
- | 34 | `SUCKER_SAFETY` | nana-suckers (`JBSucker`) | `JBSucker.enableEmergencyHatchFor` -- enable the emergency hatch to recover stuck tokens. |
76
- | 35 | `SET_SUCKER_DEPRECATION` | nana-suckers (`JBSucker`) | `JBSucker.setDeprecation` -- set deprecation status (ENABLED, DEPRECATION_PENDING, SENDING_DISABLED, DEPRECATED). |
77
- | 36 | `HIDE_TOKENS` | revnet-core (`REVHiddenTokens`) | `REVHiddenTokens.hideTokensOf` -- hide (burn) tokens on behalf of a holder. Checked against the **token holder**. |
78
- | 37 | `OPEN_LOAN` | revnet-core (`REVLoans`) | `REVLoans.borrowFrom` -- open a loan on behalf of a token holder. Checked against the **token holder**. |
79
- | 38 | `REALLOCATE_LOAN` | revnet-core (`REVLoans`) | `REVLoans.reallocateCollateralFromLoan` -- reallocate loan collateral on behalf of a loan NFT owner. Checked against the **loan NFT owner**. |
80
- | 39 | `REPAY_LOAN` | revnet-core (`REVLoans`) | `REVLoans.repayLoan` -- repay a loan on behalf of a loan NFT owner. Checked against the **loan NFT owner**. |
81
- | 40 | `REVEAL_TOKENS` | revnet-core (`REVHiddenTokens`) | `REVHiddenTokens.revealTokensOf` -- reveal (re-mint) hidden tokens on behalf of a holder. Checked against the **token holder**. |
82
-
83
- IDs 0 and 41-255 are unused. ID 0 is reserved and cannot be set. IDs 41-255 are available for future ecosystem extensions.
84
-
85
- ## ROOT Permission
86
-
87
- `ROOT` (ID 1) is a superuser permission. When an operator has ROOT for a given project, `JBPermissions` treats every permission check as passing for that project. It is the only permission that grants blanket access.
88
-
89
- Restrictions enforced by `JBPermissions`:
90
-
91
- - **Cannot be granted for the wildcard project ID (0).** Attempting to set ROOT with `projectId = 0` reverts with `JBPermissions_CantSetRootPermissionForWildcardProject()`. This prevents a single operator from controlling all projects owned by an account.
92
- - **ROOT operators cannot grant ROOT to others.** A ROOT operator can call `setPermissionsFor` on behalf of the account, but the new permission set must not include ROOT and must not target the wildcard project ID.
93
- - **ROOT is scoped per project.** Having ROOT for project 5 does not grant any permissions for project 6.
94
-
95
- ## Wildcard Project ID
96
-
97
- When permissions are granted with `projectId = 0`, they apply to **every project** owned by the granting account. This is checked by `JBPermissions` as a fallback: if the operator does not have a specific permission for the target project, the contract checks whether the operator has that permission for `projectId = 0`.
98
-
99
- ROOT cannot be set for the wildcard project ID. All other permissions can.
100
-
101
- ## How Permissions Are Checked
102
-
103
- Permissions are stored in `JBPermissions` as a 256-bit packed integer per (operator, account, projectId) tuple:
104
-
105
- ```
106
- permissionsOf[operator][account][projectId] => uint256 (packed bits)
107
- ```
108
-
109
- Each bit position corresponds to a permission ID. When a contract checks whether an operator has a permission, it calls `JBPermissions.hasPermission(operator, account, projectId, permissionId, includeRoot, includeWildcardProjectId)`, which:
50
+ ## Recovery
110
51
 
111
- 1. Checks whether the operator has ROOT (bit 1) for the specific project -- if so, returns true.
112
- 2. If `includeWildcardProjectId`, checks whether the operator has ROOT (bit 1) for the wildcard project (`projectId = 0`) -- if so, returns true.
113
- 3. Checks whether the specific permission bit is set for the specific project -- if so, returns true.
114
- 4. If `includeWildcardProjectId`, checks whether the specific permission bit is set for the wildcard project (`projectId = 0`) -- if so, returns true.
52
+ - There is no runtime recovery surface.
53
+ - A bad ID assignment is fixed only by downstream code changes and redeployments where needed.
115
54
 
116
- Steps 1-2 are skipped if `includeRoot` is false. Steps 2 and 4 are skipped if `includeWildcardProjectId` is false.
55
+ ## Admin Boundaries
117
56
 
118
- Contracts that use this system inherit from `JBPermissioned`, which provides the `_requirePermissionFrom(account, projectId, permissionId)` modifier. This modifier passes if the caller is the account itself or has the required permission via `JBPermissions`.
57
+ - Nobody can patch deployed contracts to reinterpret old permission bits.
58
+ - This repo cannot grant, revoke, or inspect permissions by itself.
119
59
 
120
- ## High-Risk Permissions
60
+ ## Source Map
121
61
 
122
- Some permissions warrant extra caution when granting:
123
-
124
- - **`ROOT` (1):** Full access to all gated functions for a project.
125
- - **`SET_TERMINALS` (15):** Can remove the primary terminal, breaking payments and cashouts.
126
- - **`USE_ALLOWANCE` (18):** Can send surplus funds to any address.
127
- - **`SET_BUYBACK_HOOK` (30):** Can permanently lock the buyback hook configuration.
128
- - **`SET_ROUTER_TERMINAL` (31):** Can permanently lock the router terminal configuration.
129
- - **`MINT_TOKENS` (10):** Can inflate token supply (subject to ruleset allowing owner minting).
130
-
131
- ## Holder vs. Owner Permissions
132
-
133
- Most permissions are checked against the **project owner** (the account that owns the project NFT). Several permissions are instead checked against the **token holder** or **loan NFT owner**:
134
-
135
- | Permission | Checked Against |
136
- |-----------|----------------|
137
- | `CASH_OUT_TOKENS` (4) | Token holder |
138
- | `BURN_TOKENS` (11) | Token holder |
139
- | `CLAIM_TOKENS` (12) | Token holder |
140
- | `TRANSFER_CREDITS` (13) | Token holder |
141
- | `HIDE_TOKENS` (36) | Token holder |
142
- | `OPEN_LOAN` (37) | Token holder |
143
- | `REALLOCATE_LOAN` (38) | Loan NFT owner |
144
- | `REPAY_LOAN` (39) | Loan NFT owner |
145
- | `REVEAL_TOKENS` (40) | Token holder |
146
-
147
- This means a token holder can grant an operator permission to cash out, burn, claim, transfer, hide, reveal, or borrow against their own tokens -- independent of the project owner's permissions. Loan NFT owners can similarly grant operators permission to repay or reallocate their loans.
62
+ - `src/JBPermissionIds.sol`
package/ARCHITECTURE.md CHANGED
@@ -2,41 +2,52 @@
2
2
 
3
3
  ## Purpose
4
4
 
5
- `nana-permission-ids-v6` is the shared permission namespace for the ecosystem. It exists so every repo can agree on what permission bit means what.
5
+ `nana-permission-ids-v6` is the shared permission namespace for the V6 ecosystem. It makes sure every repo agrees on what each permission bit means when interacting with `JBPermissions`.
6
6
 
7
- ## Boundaries
7
+ ## System Overview
8
8
 
9
- - This repo intentionally contains almost no logic.
10
- - Its value is stability, not sophistication.
11
- - The constants here are coupled to checks spread across many sibling repos.
9
+ This repo intentionally contains almost no logic. Other repos import `JBPermissionIds` and compare permission bits against these constants.
12
10
 
13
- ## Main Components
11
+ ## Core Invariants
14
12
 
15
- | Component | Responsibility |
16
- | --- | --- |
17
- | `JBPermissionIds` | Defines the canonical `uint8` IDs used with `JBPermissions` |
13
+ - Existing IDs must stay stable once deployed contracts or integrations use them.
14
+ - New IDs should be appended intentionally, not reused or repurposed.
15
+ - Numeric stability matters more than naming convenience.
16
+ - `ROOT` must stay aligned with `JBPermissions` expectations in `nana-core-v6`.
18
17
 
19
- ## Runtime Model
18
+ ## Modules
20
19
 
21
- There is no runtime state. Other repos import this library and compare permission bits against these constants.
20
+ | Module | Responsibility | Notes |
21
+ | --- | --- | --- |
22
+ | `JBPermissionIds` | Defines canonical `uint8` permission IDs | Entire repo value |
22
23
 
23
- ## Critical Invariants
24
+ ## Trust Boundaries
24
25
 
25
- - Existing IDs must remain stable once consumed by deployed contracts and integrations.
26
- - New IDs should only be appended intentionally; repurposing an old ID is ecosystem-breaking.
27
- - `ROOT` stays special and must remain consistent with `JBPermissions` expectations.
26
+ - This repo has no runtime authority by itself.
27
+ - It is tightly coupled to `nana-core-v6` and every repo that performs permission checks.
28
28
 
29
- ## Where Complexity Lives
29
+ ## Critical Flows
30
30
 
31
- - The code is trivial; the coordination burden is not.
32
- - Mistakes here look like harmless renames until they land in downstream permission checks.
31
+ There is no runtime flow. Other repos import the library and use the constants in permission checks.
33
32
 
34
- ## Dependencies
33
+ ## Accounting Model
35
34
 
36
- - Semantically coupled to `nana-core-v6` and every repo that performs permission checks
35
+ No accounting lives here.
36
+
37
+ ## Security Model
38
+
39
+ - The code is trivial, but the coordination burden is not.
40
+ - A rename or reorder here can silently break permissions across the ecosystem.
41
+ - The real blast radius comes from deployed contracts that already use these values.
42
+ - There is very little meaningful local runtime test surface in this repo.
37
43
 
38
44
  ## Safe Change Guide
39
45
 
40
- - Treat every ID change as a cross-repo protocol change.
41
- - When adding a permission, update the docs and downstream repos in the same change set.
42
- - Do not add convenience aliases that obscure the one-to-one mapping between bit position and meaning.
46
+ - Treat any ID change as a cross-repo protocol change.
47
+ - When adding a permission, update downstream repos and docs in the same change set.
48
+ - Do not add aliases that hide the one-to-one mapping between bit position and meaning.
49
+
50
+ ## Source Map
51
+
52
+ - `src/JBPermissionIds.sol`
53
+ - `references/runtime.md`
@@ -1,35 +1,55 @@
1
1
  # Audit Instructions
2
2
 
3
- This repo is only permission ID constants, but the constants are security-critical because many repos key access control off them.
3
+ This repo is only permission ID constants, but those constants are security-critical because many repos key access control off them.
4
4
 
5
- ## Objective
5
+ ## Audit Objective
6
6
 
7
7
  Find issues that:
8
- - assign duplicate IDs to different semantic permissions
8
+
9
+ - assign duplicate IDs to different permissions
9
10
  - mismatch IDs that downstream repos assume are canonical
10
11
  - create ordering or collision hazards for future permission additions
11
12
 
12
13
  ## Scope
13
14
 
14
15
  In scope:
16
+
15
17
  - `src/JBPermissionIds.sol`
16
18
 
19
+ ## Start Here
20
+
21
+ 1. `src/JBPermissionIds.sol`
22
+ 2. downstream consumers in `nana-core-v6` and `revnet-core-v6`
23
+
24
+ ## Security Model
25
+
26
+ This repo defines canonical numeric IDs that other repos treat as part of their permission model.
27
+
28
+ - the file is small, but stale renumbering or collisions can silently widen or break access control elsewhere
29
+ - correctness depends on cross-repo alignment, not local logic alone
30
+
31
+ ## Integration Assumptions
32
+
33
+ | Dependency | Assumption | What breaks if wrong |
34
+ |------------|------------|----------------------|
35
+ | `nana-core-v6` | ERC-20 signature delegation still uses the documented ID | Signature authority checks mismatch |
36
+ | `revnet-core-v6` | Loan and hidden-token permissions still use the documented IDs | Delegated actions widen, fail, or misroute |
37
+
17
38
  ## Critical Invariants
18
39
 
19
40
  1. Each permission semantic has one stable numeric ID.
20
41
  2. No two distinct permissions share an ID.
21
42
  3. IDs match the expectations of all dependent repos in this workspace.
22
- 4. ID 23 (`SIGN_FOR_ERC20`) is consumed by `nana-core-v6` (`JBERC20`) — verify it matches the value used for ERC-1271 signature delegation.
23
- 5. IDs 36-40 (revnet-core delegation: `HIDE_TOKENS`, `OPEN_LOAN`, `REALLOCATE_LOAN`, `REPAY_LOAN`, `REVEAL_TOKENS`) are consumed by `revnet-core-v6` — verify they match the values used in `REVHiddenTokens` and `REVLoans`.
43
+ 4. ID `23` (`SIGN_FOR_ERC20`) matches the value used by `nana-core-v6` for ERC-1271 signature delegation.
44
+ 5. IDs `36-40` used by `revnet-core-v6` match the values used in `REVHiddenTokens` and `REVLoans`.
24
45
 
25
- ## Threat Model
46
+ ## Attack Surfaces
26
47
 
27
- Prioritize stale or inconsistent constants, especially where wildcard grants or deployer permissions depend on a specific numeric value.
48
+ - duplicate or reordered constants
49
+ - stale cross-repo assumptions
50
+ - permission additions that collide with previously assigned meanings
28
51
 
29
- ## Build And Verification
52
+ ## Verification
30
53
 
31
- Standard workflow:
32
54
  - `npm install`
33
55
  - `forge build`
34
-
35
- A meaningful finding here should show a real downstream permission check becoming broader, narrower, or mismatched because of the constant set.
package/README.md CHANGED
@@ -2,17 +2,22 @@
2
2
 
3
3
  `@bananapus/permission-ids-v6` is the shared constant library for Juicebox V6 operator permissions. It gives every repo in the ecosystem the same numeric meaning for the same permission name.
4
4
 
5
- Architecture: [ARCHITECTURE.md](./ARCHITECTURE.md)
5
+ Architecture: [ARCHITECTURE.md](./ARCHITECTURE.md)
6
+ User journeys: [USER_JOURNEYS.md](./USER_JOURNEYS.md)
7
+ Skills: [SKILLS.md](./SKILLS.md)
8
+ Risks: [RISKS.md](./RISKS.md)
9
+ Administration: [ADMINISTRATION.md](./ADMINISTRATION.md)
10
+ Audit instructions: [AUDIT_INSTRUCTIONS.md](./AUDIT_INSTRUCTIONS.md)
6
11
 
7
12
  ## Overview
8
13
 
9
- The library is intentionally simple: one Solidity file, no storage, no deployment, and no runtime logic. Its value comes from consistency.
14
+ This library is intentionally simple: one Solidity file, no storage, no deployment, and no runtime logic. Its value is consistency.
10
15
 
11
- `JBPermissions` stores operator permissions as packed bits. This package names the bit positions so integrations do not drift across repos.
16
+ `JBPermissions` stores operator permissions as packed bits. This package names those bit positions so integrations do not drift across repos.
12
17
 
13
18
  Use this repo as the single source of truth for permission numbers. Do not redefine permission IDs locally in downstream repos.
14
19
 
15
- If the question is "who can do this action?" you will still need `JBPermissions` in `nana-core-v6`. This repo only tells you what the numeric labels mean.
20
+ If the question is "who can do this action?" you still need `JBPermissions` in `nana-core-v6`. This repo only tells you what the numbers mean.
16
21
 
17
22
  ## Current Permission Ranges
18
23
 
@@ -21,16 +26,42 @@ If the question is "who can do this action?" you will still need `JBPermissions`
21
26
  | `1` | global `ROOT` permission |
22
27
  | `2-23` | core protocol permissions |
23
28
  | `24-27` | 721 hook permissions |
24
- | `28-30` | buyback hook permissions |
25
- | `31` | router terminal permission |
26
- | `32-35` | sucker and omnichain permissions |
27
- | `36-40` | revnet-core permissions (hidden tokens, loans) |
29
+ | `28-30` | buyback hook and registry permissions |
30
+ | `31` | router terminal registry permission |
31
+ | `32-35` | sucker and omnichain deployment permissions |
32
+ | `36-40` | revnet-core permissions |
28
33
 
29
34
  The exact constants live in `src/JBPermissionIds.sol`.
30
35
 
36
+ Two IDs deserve extra attention:
37
+
38
+ - `SET_BUYBACK_HOOK` covers both setting and permanently locking the configured buyback hook
39
+ - `SET_ROUTER_TERMINAL` covers both setting and permanently locking the configured router terminal
40
+
31
41
  ## Mental Model
32
42
 
33
- This repo is a coordination artifact, not a behavior repo. Its value is that every other package can import the same names and mean the same thing.
43
+ This repo is a naming registry, not a behavior repo. Its job is to make every other package use the same permission names for the same bit positions.
44
+
45
+ ## Read This File First
46
+
47
+ 1. `src/JBPermissionIds.sol`
48
+
49
+ ## Integration Traps
50
+
51
+ - changing an existing numeric constant is an ecosystem breaking change
52
+ - adding a new permission ID without coordinating downstream repos creates semantic drift even if code still compiles
53
+ - wildcard project permissions are still dangerous even when the numeric IDs are correct
54
+
55
+ ## Where Meaning Lives
56
+
57
+ - numeric permission labels: `JBPermissionIds.sol`
58
+ - runtime permission checks: `nana-core-v6/src/JBPermissions.sol`
59
+ - repo-specific uses of those IDs: the downstream repo that imports them
60
+
61
+ ## For AI Agents
62
+
63
+ - Treat this repo as a naming registry for permission bits, not as the runtime permission engine.
64
+ - If asked whether an action is allowed, inspect the downstream repo that checks the ID in addition to this file.
34
65
 
35
66
  ## Install
36
67
 
@@ -55,5 +86,6 @@ src/
55
86
  ## Risks And Notes
56
87
 
57
88
  - `ROOT` is intentionally powerful and should be granted sparingly
58
- - wildcard project scope is convenient but easy to misuse operationally
59
- - any change to this file has ecosystem-wide consequences because other repos assume the values are stable
89
+ - wildcard project scope is convenient but easy to misuse
90
+ - some IDs bundle configuration and irreversible locking authority, so their blast radius is larger than the short name suggests
91
+ - any change to this file has ecosystem-wide consequences because other repos assume the values stay stable
package/RISKS.md CHANGED
@@ -1,36 +1,50 @@
1
1
  # Permission IDs Risk Register
2
2
 
3
- Constants-only library defining permission ID values used throughout the Juicebox V6 ecosystem. The main failure mode is not local arithmetic; it is ecosystem-wide semantic drift if contracts disagree on what a permission ID means.
3
+ This file covers the coordination risks in `JBPermissionIds`. The contract surface is tiny, but drift here can corrupt access control across the V6 ecosystem.
4
4
 
5
- ## How to use this file
5
+ ## How To Use This File
6
6
 
7
- - Read `Priority risks` first; these are the ways a tiny library can create very large blast radius.
8
- - Use the design notes to understand why stability and coordination matter more here than contract complexity.
9
- - Treat any change in this repo as an ecosystem migration event, not a routine edit.
7
+ - Read `Priority risks` first. The main danger is cross-repo disagreement, not a local code bug.
8
+ - Treat every ID change as an ecosystem migration event.
9
+ - Use `Invariants to verify` to keep append-only discipline explicit.
10
10
 
11
- ## Priority risks
11
+ ## Priority Risks
12
12
 
13
13
  | Priority | Risk | Why it matters | Primary controls |
14
14
  |----------|------|----------------|------------------|
15
- | P0 | Semantic drift across repos | If two repos interpret the same `uint8` differently, access control breaks silently across the ecosystem. | Single source of truth, strict review, and synchronized downstream updates. |
16
- | P1 | Reordering or repurposing existing IDs | Changing established IDs can create backward-incompatible authority bugs without any contract-level revert. | Append-only discipline and explicit migration communication. |
17
- | P2 | Incomplete ecosystem adoption | A new permission ID is only safe if every dependent repo and deploy script understands it. | Cross-repo review and deployment coordination. |
15
+ | P0 | Semantic drift across repos | If two packages assign different meanings to the same ID, permission checks can silently authorize the wrong actions. | Single source of truth, append-only changes, and synchronized downstream updates. |
16
+ | P1 | Reusing or reordering existing IDs | Renumbering breaks deployed contracts and off-chain tooling without any on-chain migration safety. | Never repurpose an assigned ID. Append only. |
17
+ | P1 | Over-trusting high-impact IDs | Some IDs directly control funds, routing, locking, or loan state. Misgrants are dangerous. | Explicit operator review and narrow-scoped grants. |
18
18
 
19
19
  ## 1. Known Risks
20
20
 
21
- - **ROOT permission (ID 1).** ROOT grants all permissions across every contract. Any address granted ROOT can perform any permissioned operation on any project. Should never be granted to untrusted addresses.
22
- - **SET_BUYBACK_HOOK includes lock (ID 30).** Gates both `setHookFor` and `lockHookFor`. An operator with this permission can permanently lock the buyback hook configuration.
23
- - **SET_ROUTER_TERMINAL includes lock (ID 31).** Gates both `setTerminalFor` and `lockTerminalFor`. An operator can permanently lock the router terminal.
24
- - **ID collision risk.** Permission IDs are manually assigned sequential uint8 values. Adding new IDs requires coordination to avoid collision. Library is append-only.
25
- - **No runtime enforcement.** This library only defines constants. Enforcement happens in consuming contracts. A mismatch between the ID used here and the ID checked in a consumer would silently fail.
26
- - **High-impact permission IDs (fund-moving).** IDs that control fund flow should receive the most audit scrutiny: `ROOT` (1, grants everything), `CASH_OUT_TOKENS` (4, triggers withdrawals), `SEND_PAYOUTS` (5, triggers payout distribution), `MIGRATE_TERMINAL` (6, moves balances), `SET_TERMINALS` (15, redirects all fund flows), `USE_ALLOWANCE` (18, draws from surplus), `SET_SPLIT_GROUPS` (19, controls where payouts go). Of these, ROOT + SET_TERMINALS + MIGRATE_TERMINAL are the most dangerous — they can redirect all of a project's funds.
27
- - **SIGN_FOR_ERC20 (ID 23).** Grants permission to sign messages on behalf of a project's ERC-20 token via ERC-1271. Used for Etherscan contract verification and other off-chain signature validation. Should only be granted to trusted addresses since it controls the token's signing authority.
28
- - **Wildcard `projectId=0` semantics.** When a permission is granted with `projectId=0`, it applies to ALL projects. This is used by system contracts (e.g., `REVLoans` gets `USE_ALLOWANCE` with `projectId=0`). A bug in a contract holding wildcard permissions affects every project in the ecosystem, not just one. Only system-level contracts should hold wildcard permissions.
29
-
30
- ## 2. Design Notes
31
-
32
- - Permission 0 is reserved and cannot be set.
33
- - IDs are `uint8` (0-255), with 1-40 currently assigned.
34
- - IDs 36-40 are used by `revnet-core-v6` for operator delegation: `HIDE_TOKENS` (36), `OPEN_LOAN` (37), `REALLOCATE_LOAN` (38), `REPAY_LOAN` (39), `REVEAL_TOKENS` (40).
35
- - IDs 41-255 are available for ecosystem extensions. Third-party contracts can define their own permission IDs in this range, but must coordinate to avoid collisions. No on-chain registry exists for custom IDs — collision detection is purely social.
36
- - This library has zero dependencies -- it is the leaf of the dependency graph.
21
+ - **No runtime enforcement here.** This library only defines constants. Safety depends on every consuming repo checking the intended ID.
22
+ - **`ROOT` is broad authority.** `ROOT` (ID `1`) grants all permissions, including permissions added in the future.
23
+ - **Wildcard grants increase blast radius.** Any permission granted with `projectId = 0` applies to all projects owned by that account.
24
+ - **Hook and router lock powers are bundled.** `SET_BUYBACK_HOOK` (`30`) and `SET_ROUTER_TERMINAL` (`31`) both cover setting and locking.
25
+ - **Third-party extensions do not have an on-chain namespace.** IDs `41-255` are only socially coordinated, so external packages can collide without coordination.
26
+
27
+ ## 2. High-Impact IDs
28
+
29
+ - **Fund-moving IDs.** `CASH_OUT_TOKENS` (`4`), `SEND_PAYOUTS` (`5`), `MIGRATE_TERMINAL` (`6`), `SET_TERMINALS` (`15`), `USE_ALLOWANCE` (`18`), and `SET_SPLIT_GROUPS` (`19`) can redirect or release value.
30
+ - **Hook-routing IDs.** `SET_BUYBACK_POOL` (`28`), `SET_BUYBACK_HOOK` (`30`), and `SET_ROUTER_TERMINAL` (`31`) materially control execution routes and can lock those routes permanently.
31
+ - **Revnet loan IDs.** `OPEN_LOAN` (`37`), `REALLOCATE_LOAN` (`38`), and `REPAY_LOAN` (`39`) are operationally powerful because they move collateral and debt state.
32
+
33
+ ## 3. Integration Risks
34
+
35
+ - **Docs can lag deployed assumptions.** Off-chain tooling, UIs, and audits often rely on human-readable permission names.
36
+ - **Cross-package imports must stay canonical.** Downstream repos should import this library instead of redefining numeric literals locally.
37
+ - **Future IDs expand current `ROOT` power.** Any new permission automatically becomes available to existing `ROOT` operators.
38
+
39
+ ## 4. Invariants To Verify
40
+
41
+ - Assigned IDs are append-only and never repurposed.
42
+ - `0` stays unused as a permission ID.
43
+ - Every documented ID in this repo matches the numeric checks in downstream contracts.
44
+ - New IDs added after `40` do not collide with existing ecosystem assignments.
45
+
46
+ ## 5. Accepted Behaviors
47
+
48
+ ### 5.1 This repo is coordination infrastructure, not an enforcement layer
49
+
50
+ `JBPermissionIds` intentionally has no access control, storage, or runtime checks. The repo matters because every other package can import the same constants and mean the same thing.
package/SKILLS.md CHANGED
@@ -2,8 +2,8 @@
2
2
 
3
3
  ## Use This File For
4
4
 
5
- - Use this file when you need the canonical numeric meaning of a Juicebox V6 permission constant or when reviewing changes that would affect permission numbering across the ecosystem.
6
- - Start here, then open the constant file directly.
5
+ - Use this file when you need the canonical numeric meaning of a Juicebox V6 permission constant.
6
+ - Start here when reviewing changes that could affect permission numbering across the ecosystem.
7
7
 
8
8
  ## Read This Next
9
9
 
@@ -20,11 +20,11 @@
20
20
 
21
21
  ## Purpose
22
22
 
23
- Single source of truth for Juicebox V6 permission ID constants. This repo has no runtime behavior; its value is ecosystem-wide coordination.
23
+ This repo is the single source of truth for Juicebox V6 permission ID constants. It has no runtime behavior. Its value is ecosystem-wide coordination.
24
24
 
25
25
  ## Reference Files
26
26
 
27
- - Open [`references/runtime.md`](./references/runtime.md) when you need the stability expectations and why changes here are ecosystem-wide.
27
+ - Open [`references/runtime.md`](./references/runtime.md) when you need the stability expectations and why changes here affect the whole ecosystem.
28
28
 
29
29
  ## Working Rules
30
30
 
package/USER_JOURNEYS.md CHANGED
@@ -1,46 +1,103 @@
1
1
  # User Journeys
2
2
 
3
- ## Who This Repo Serves
3
+ ## Repo Purpose
4
4
 
5
- - protocol and product engineers mapping actions to the right operator permission
6
- - auditors checking whether a downstream repo reused or drifted from the shared permission vocabulary
7
- - maintainers adding new permission surfaces without colliding with existing meaning
5
+ This repo is the shared permission vocabulary for the V6 ecosystem. It does not store permissions or enforce them at runtime. It defines the constants that downstream repos should import so permissioned behavior stays clear and consistent.
6
+
7
+ ## Primary Actors
8
+
9
+ - engineers choosing which permission constant should guard a feature
10
+ - auditors checking whether a repo drifted from the shared vocabulary
11
+ - maintainers extending the permission map without numeric collisions
12
+
13
+ ## Key Surfaces
14
+
15
+ - `JBPermissionIds`: library of canonical permission constants used across V6 repos
16
+ - grouped constants for core, 721, router, buyback, sucker, revnet, and related actions
17
+ - reserved ranges documented in `README.md`, including `ROOT = 1`, ecosystem-managed IDs through `40`, and socially coordinated extension space above that
8
18
 
9
19
  ## Journey 1: Map A Product Action To The Right Permission
10
20
 
11
- **Starting state:** a repo needs to guard an action with `JBPermissions`.
21
+ **Actor:** downstream engineer.
12
22
 
13
- **Success:** the code imports the canonical constant instead of inventing a local numeric meaning.
23
+ **Intent:** protect an action with the canonical permission constant instead of inventing a local number.
14
24
 
15
- **Flow**
16
- 1. Find the action's domain in `JBPermissionIds`, such as core, 721 hook, buyback, router, or sucker permissions.
17
- 2. Import the shared constant into the downstream repo.
18
- 3. Check the relevant caller against that constant through `JBPermissions`.
25
+ **Preconditions**
26
+ - the action is governed by `JBPermissions`
27
+ - the engineer knows which repo or domain owns the action
28
+
29
+ **Main Flow**
30
+ 1. Find the action domain in `JBPermissionIds`, such as core, 721, router, buyback, or sucker permissions.
31
+ 2. Import the constant into the downstream repo.
32
+ 3. Use that constant in the runtime authorization check.
33
+ 4. Treat bundled high-impact IDs like `SET_BUYBACK_HOOK` and `SET_ROUTER_TERMINAL` as broader powers than their short names suggest because they also gate locking.
34
+
35
+ **Failure Modes**
36
+ - the repo hardcodes a number locally and drifts from the shared vocabulary
37
+ - a repo picks the wrong existing constant because the action sounds similar but is not actually equivalent
38
+ - a team grants `ROOT` or wildcard permissions without appreciating the blast radius
39
+ - docs and tests describe a permission by nickname instead of the imported constant
40
+
41
+ **Postconditions**
42
+ - the downstream action is guarded by the shared permission vocabulary instead of a local numeric convention
19
43
 
20
44
  ## Journey 2: Review An Existing Operator Setup
21
45
 
22
- **Starting state:** a project or audit needs to understand what a granted permission actually means.
46
+ **Actor:** auditor, operator, or integrator.
47
+
48
+ **Intent:** decode opaque permission bits into named actions.
23
49
 
24
- **Success:** the operator bitset can be read as named product actions instead of opaque integers.
50
+ **Preconditions**
51
+ - the operator bitset or granted permission IDs are already known
52
+ - the reviewer understands that this repo names permissions but does not prove how each repo uses them
25
53
 
26
- **Flow**
54
+ **Main Flow**
27
55
  1. Start with the permission bits granted on the project.
28
- 2. Map each bit back to the shared constant defined here.
29
- 3. Confirm that the downstream repo still uses that constant consistently at its authorization checks.
56
+ 2. Map each bit to its named constant here.
57
+ 3. Confirm the downstream repo still uses that constant consistently in authorization checks and docs.
58
+ 4. Check whether any granted IDs are really funds-moving, routing, locking, or loan-management powers rather than low-risk admin toggles.
59
+
60
+ **Failure Modes**
61
+ - downstream code reuses a permission ID for a different meaning
62
+ - reviewers decode the bit correctly but underestimate what the downstream repo lets that permission do
63
+ - reviewers rely on this repo alone and skip the guarded code
64
+
65
+ **Postconditions**
66
+ - the reviewer has a named permission map and knows which downstream repos still need inspection
30
67
 
31
68
  ## Journey 3: Add A New Ecosystem Surface Without Permission Drift
32
69
 
33
- **Starting state:** a new repo or feature needs a permission that does not fit any existing constant.
70
+ **Actor:** maintainer extending the permission vocabulary.
34
71
 
35
- **Success:** the new constant is added once, in the right numeric range, and downstream packages can reuse it without ambiguity.
72
+ **Intent:** add a new permission constant that the rest of the ecosystem can reuse.
36
73
 
37
- **Flow**
38
- 1. Pick the next unused ID in the relevant ecosystem range.
74
+ **Preconditions**
75
+ - no existing constant already matches the new action
76
+ - the maintainer understands the numeric ranges already in use
77
+
78
+ **Main Flow**
79
+ 1. Choose the next unused ID in the relevant range.
39
80
  2. Add the named constant in `JBPermissionIds.sol`.
40
- 3. Update downstream repos to import that constant instead of duplicating the number.
41
- 4. Re-audit any docs or tests that explain the meaning of that permission.
81
+ 3. Update downstream repos to import the constant instead of duplicating the number.
82
+ 4. Refresh docs and tests that explain the permission.
83
+ 5. If the new ID goes above the ecosystem-managed range, coordinate externally so third-party packages do not collide on the same number.
84
+
85
+ **Failure Modes**
86
+ - a new repo defines its own numeric constant first and creates drift
87
+ - a new constant is added in the wrong semantic range, making later review harder
88
+ - a new ID silently expands what existing `ROOT` operators can do without that blast radius being reviewed
89
+ - documentation updates lag behind the code change
90
+
91
+ **Postconditions**
92
+ - the new ecosystem surface has a reusable canonical permission ID with coordinated downstream adoption
93
+
94
+ ## Trust Boundaries
95
+
96
+ - this repo is trusted only as shared vocabulary
97
+ - actual storage and enforcement live elsewhere
98
+ - downstream repos can still misuse a constant even when they import the right one
42
99
 
43
100
  ## Hand-Offs
44
101
 
45
102
  - Use [nana-core-v6](../nana-core-v6/USER_JOURNEYS.md) for the runtime permission registry that stores and checks these IDs.
46
- - Use the relevant downstream repo when the question is about what a permissioned action actually does after authorization succeeds.
103
+ - Use the relevant downstream repo when the question is about what a permissioned action does after authorization succeeds.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bananapus/permission-ids-v6",
3
- "version": "0.0.17",
3
+ "version": "0.0.19",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -1,5 +1,7 @@
1
1
  # Permission IDs Runtime
2
2
 
3
+ Use this file when you need to confirm the canonical numeric labels, not when you need to understand enforcement behavior.
4
+
3
5
  ## Core Role
4
6
 
5
7
  - [`src/JBPermissionIds.sol`](../src/JBPermissionIds.sol) defines the canonical numeric labels used by the rest of the ecosystem.
@@ -13,3 +15,4 @@
13
15
 
14
16
  - If you edit a constant, audit every dependent repo that imports it.
15
17
  - If you need to know who can exercise a permission, follow the usage into the enforcing repo rather than stopping here.
18
+ - There are no repo-local tests here, so downstream compile and behavior audits matter more than this package in isolation.