Skip to content

Access control tests#244

Merged
mts1715 merged 24 commits intomainfrom
taras/177-access-control-test
Mar 25, 2026
Merged

Access control tests#244
mts1715 merged 24 commits intomainfrom
taras/177-access-control-test

Conversation

@mts1715
Copy link
Contributor

@mts1715 mts1715 commented Mar 6, 2026

Closes: #177

Summary

Implements the full Actor Capability Matrix test suite for FlowALPv0.Pool entitlements, as defined in docs/security-permission-matrix.md

Description

cap_test.cdc

The previous file only validated pool creation. This PR replaces it with a structured security test suite covering every row in the permission matrix across all 6 entitlements — one test per matrix operation, organised in sections matching the matrix columns.

Negative test strategy

Cadence entitlements for Pool capabilities (EParticipant, EPosition, ERebalance, EGovernance, EImplementation) are enforced by the cadence type checker.
EPositionAdmin is the only entitlement in this file where negative (access-denied) tests are meaningful at runtime by borrowAuthorizedPosition, so testEPositionAdmin_BorrowUnauthorizedPosition_Fails exists.

Transaction reorganisation

Old pool-management/ and pool-governance/ stubs removed. Replaced by entitlement-scoped folders matching the matrix columns:
egovernance, eimplementation, eparticipant, eposition, epositionadmin, erebalance, setup (grant_e*_cap.cdc helpers), helpers (liquidation)

docs/security-permission-matrix.md

  • Added Test Coverage table mapping each test file to the matrix rows it covers.
  • Added Audit Notes section documenting union/conjunction semantics (EPosition | ERebalance for rebalance ops; FungibleToken.Withdraw + EPositionAdmin conjunction for borrowAuthorizedPosition).
  • Clarified which rows are covered by paid_auto_balance_test.cdc (rebalancer-local entitlements) and withdraw_stability_funds_test.cdc (withdrawStabilityFund).

Known issue documented (not fixed here)

publish_beta_cap.cdc grants EParticipant + EPosition to beta users. EPosition is not needed for normal user actions and allows any beta user to withdraw from or freeze any other user's position. The over-grant is explicitly tested in the eParticipantPositionUser section. Fix: grant EParticipant only — tracked separately.

vishalchangrani and others added 8 commits February 19, 2026 11:56
Maps all FlowALPv0 entitlements to operations by resource, with plain-language descriptions. Intended for audit/security review.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Mark EPosition as protocol-internal only, not for end users
- Add ownership-check warnings on all pool-level EPosition operations
- Document the beta capability over-grant issue (EPosition -> EParticipant fix needed)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace resource-grouped columns with actor columns (User, User w/ EPosition,
Rebalancer, Position Owner, Governance, Protocol Internal). The beta over-grant
is now directly visible as a dedicated column showing what current beta users
can do vs. what they should be able to do.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@mts1715 mts1715 self-assigned this Mar 6, 2026
@mts1715 mts1715 requested a review from a team as a code owner March 6, 2026 15:15
Copy link
Member

@Kay-Zee Kay-Zee left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there are a few test cases that I would love to have additional verification that the intended action did actually happen, and it was not just that the transaction was successful, but possibly didn't take the intended action, things like balance checks, new value checks, etc. For certain actions where this is harder to do, we can leave for later but the easy ones, that i mentioned i think might make sense to just do here.

Also, would love for the eGovernance tests to have their "negative" case checked, just because those are especially sensitive. It's a little bit "frivolous" as in we're just checking cadence is behaving as expected, but i think it should be pretty easy/straightforward, and gives some added confidence.

import "FlowALPv0"
import "FlowALPModels"

/// TEST TRANSACTION - DO NOT USE IN PRODUCTION
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are all really test transactions only? seems like they technically would still work in prod, no? assuming the account has the right entitlement?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it can, I've added this mark about "test transaction" because it should be rechecked before using in prod.
Removed at transactions that could be used in prod: 9bfe703

/// Uses the cap stored at FlowALPv0.PoolCapStoragePath.
///
/// NOTE: All logic is in prepare because @Position resources cannot be stored as
/// transaction fields, and execute has no storage access. The prepare-only pattern
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

execute has no storage access

https://cadence-lang.org/docs/language/transactions#execute-phase

I don't believe that statement is true, si ti? the example on the doc is literally signer.storage.load

Also, why can't @Position resources cannot be stored as transaction fields?

Copy link
Contributor Author

@mts1715 mts1715 Mar 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this was my fault and misunderstanding.
fix ff18746


execute {
// Pool.rebalancePosition — requires EPosition | ERebalance; ERebalance alone is sufficient
self.pool.rebalancePosition(pid: pid, force: force)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

very similar to the tx above, except goes through the capability, wonder if there's any way to better differentiate the two tx, maybe in naming? anyway, just minor nit.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fix:
9bfe703

[setupPid, 1.0],
eParticipantPositionUser
)
Test.expect(result, Test.beSucceeded())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could we maybe also do an expect of the balance to make sure the withdraw actually withdrew some amount of tokens, and not just that the withdraw tx succeeded (but didn't withdraw somehow)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fix 63cfe76

[setupPid, 1.0],
eParticipantPositionUser
)
Test.expect(result, Test.beSucceeded())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same comment as above, would love to also verify balance

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fix 63cfe76


let result = _executeTransaction(
"../tests/transactions/flow-alp/erebalance/rebalance_pool.cdc",
[setupPid, true],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is showcasing that the rebalance user can rebalance the protocol accounts position.

That's what we're trying to show with this test? I thought the rebalance user would only rebalance their own position.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[ePositionAdminPid, TARGET_HEALTH],
ePositionAdminUser
)
Test.expect(result, Test.beSucceeded())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could we verify the new target health?

Copy link
Contributor Author

@mts1715 mts1715 Mar 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fix 63cfe76

mts1715 added 7 commits March 16, 2026 16:20
fix phases in transactions: execute block executes the main logic of the transaction.
…sed in prod;

fix pool_rebalance transactions naming
…rol-test

# Conflicts:
#	FlowActions
#	cadence/tests/transactions/flow-alp/pool-management/04_create_position.cdc
@mts1715 mts1715 requested a review from Kay-Zee March 17, 2026 11:06
@UlyanaAndrukhiv UlyanaAndrukhiv requested a review from a team March 17, 2026 15:55
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We already have ./cadence/transactions/flow-alp/pool-governance/collect_insurance.cdc.
I don't see an issue with having separate copies for the test transactions; in fact, it might be the correct approach, as transactions outside the test folder should adhere to stricter rules.
Just wanted to confirm this was a deliberate choice.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cadence/transactions/flow-alp/pool-governance/collect_insurance.cdc: directly borrows the Pool from storage (for the pool admin)
cadence/tests/transactions/flow-alp/egovernance/collect_insurance.cdc: borrows a Capability from PoolCapStoragePath (for eGovernanceUser who only has a delegated capability, not direct storage access)

Switching cap_test.cdc to use the pool-governance version would break testEGovernance_CollectInsurance since eGovernanceUser doesn't have the pool in their storage.

@mts1715 mts1715 requested review from a team and holyfuchs March 23, 2026 17:34
Copy link
Member

@Kay-Zee Kay-Zee left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, had some idea for some "negative" tests, i.e. show actions being blocked without the right entitlements, but that's probably a bit unnecessary

[ePositionAdminPid],
ePositionAdminUser
)
Test.expect(result, Test.beSucceeded())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

at least for the EGovernance cap, i wonder if we can showcase all of these functions failing if you don't have the cap? I think these ones, since they're especially sensitive, would be good to show the counter case of them not working without the cap.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fix 361eea0

@mts1715 mts1715 merged commit b9d0051 into main Mar 25, 2026
1 check passed
@mts1715 mts1715 deleted the taras/177-access-control-test branch March 25, 2026 17:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Access Control - Unauthorized access, privilege escalation, entitlement enforcement

4 participants