Skip to content

feat: update sails-rs to 1.0.0 - #32

Merged
vobradovich merged 62 commits into
masterfrom
feat/awesome-sails-beta
Jun 17, 2026
Merged

vobradovich merged 62 commits into
masterfrom
feat/awesome-sails-beta

Conversation

@m62624

@m62624 m62624 commented Apr 14, 2026 •

Copy link
Copy Markdown
Contributor

No description provided.

@m62624 m62624 changed the title chore(deps): update sails-rs to =1.0.0-beta.3 chore(deps): update sails-rs to =1.0.0-beta.4 Apr 27, 2026
@m62624
m62624 force-pushed the feat/awesome-sails-beta branch from 3231829 to 99b4fd3 Compare April 27, 2026 12:26
@vobradovich

Copy link
Copy Markdown
Contributor

Code Review: feat/awesome-sails-beta vs master

Branch: feat/awesome-sails-beta
Base: master (7f47b1a)
Head: 99b4fd3
Date: 2026-04-27

What Was Reviewed

~45 commits covering:

  • Allocation-free sorted array RBAC storage (const generics, SmallVec)
  • Binary search and swap_remove for linear storage
  • Benchmarking infrastructure with CI integration
  • Capacity tests and CapacityExceeded typed error
  • TypeInfo updates for sails-rs beta.4 compatibility
  • RBAC role update

Strengths

  • Clean separation between AccessControlStorage (pure data) and AccessControl (service wrapper).
  • CapacityExceeded as a typed, encodable error instead of a panic is a meaningful correctness improvement.
  • Benchmark scope reduction (10 000 → 100 members) is appropriately calibrated to new capacity constraints.
  • assert_str_panic removed in favour of typed Error comparison — strictly better.
  • No unsafe code introduced in the access-control crate.

Critical Issues

1. require_role logic broken for role_id == default_admin_role()

File: crates/awesome-sails/access-control/src/lib.rs (lines 428–451)

When role_id == default_admin_role(), the role_id != admin guard skips has_role entirely. A valid default-admin member calling require_role(default_admin_role(), actor) will get AccessDenied if the fast-path fails. The previous implementation used has_role(DEFAULT_ADMIN_ROLE) || has_role(role_id) — the new fast-path dropped this fallback.

Fix: Replace the fast-path with a proper has_role(admin, account_id) call, remove the role_id != admin guard, and add an explicit test for require_role(default_admin_role(), actor_in_admin_role).

2. roles_capacity_exceeded test doesn't verify the last valid role was accepted

File: tests/access-control-test/app/tests/gtest.rs (line 708)

Loop iterates 1..ROLES_LIMIT, but never asserts that the 32 custom-role grants succeeded. The test only checks that the ROLES_LIMIT + 1th role fails — the ROLES_LIMITth slot is never verified as successfully accepted.


Important Issues

3. data_idx: u16 silently overflows if N > 65535

File: crates/awesome-sails/access-control/src/lib.rs (lines 95, 294)

self.role_data.len() as u16 wraps silently for N > 65535. The capacity check prevents this in practice only if N ≤ 65535. No compile-time assertion exists.

Fix:

const _: () = assert!(N <= u16::MAX as usize, "N must fit in u16");

4. RS parameter undocumented for role_data SmallVec

File: crates/awesome-sails/access-control/src/lib.rs (line 89)

role_data uses RS inline slots (same as descriptors). This works since both grow in lockstep, but is not documented. A reader expects a separate parameter or an explanatory comment.

5. set_role_admin consumes role capacity without granting members

File: crates/awesome-sails/access-control/src/lib.rs (line 715)

set_role_admin_unchecked calls ensure_role_mut(role_id), allocating a new slot even for non-existent roles. With explicit capacity limits this side-effect is now observable — worth documenting or guarding.

6. Stale DEFAULT_ADMIN_ROLE references in doc comments

DEFAULT_ADMIN_ROLE is no longer a public symbol (replaced by default_admin_role()), but doc comments throughout lib.rs and vft-admin still reference the old name. Update to default_admin_role().

7. grant_initial_admin silently swallows CapacityExceeded when N == 0

File: crates/awesome-sails/access-control/src/lib.rs (line 279)

if let Ok(role) = self.ensure_role_mut(default_admin_role()) {
    let _ = role.add_member(deployer);
}

If N == 0, the deployer never gets the admin role and the program silently misbehaves. Add a debug_assert or document N >= 1 as a precondition.


Suggestions

8. Enforce index-0 invariant in require_role with a debug_assert

The assumption "default admin role is always at index 0 in a sorted array" is correct but load-bearing. Add:

debug_assert_eq!(storage.descriptors[0].role_id, admin);

9. Benchmark baseline reduction eliminates high-scale regression detection

The bench_data.json went from 5000/10000-member baselines to 100. Regressions that only appear at higher scales are no longer tracked. Document this trade-off in benchmarks/README.md.

10. stress_test_max_members doesn't guard against role-slot exhaustion during setup

The test doesn't assert that the MINTER_ROLE grant succeeded before iterating members. If ROLES_LIMIT were 1, it would fail with CapacityExceeded on the role grant rather than a member add.

11. vft-admin RS == N and MS == M is intentional but unexplained

File: crates/awesome-sails/vft-admin/src/lib.rs (lines 45–48)

With ROLES_LIMIT = 4 and MEMBERS_LIMIT = 17, the SmallVec always holds everything on the stack. Valid intent — but a comment explaining why RS == N and MS == M are correct would help readers.

12. README code example has a formatting/indentation error

File: crates/awesome-sails/access-control/README.md (line 56)

The pub fn access_control( line is missing leading indentation inside the impl Program block, making the example non-compiling as shown.


Summary

# Severity Area Issue
1 Critical require_role logic Admin bypass path broken for role_id == default_admin_role()
2 Critical Capacity test roles_capacity_exceeded doesn't verify the last valid role was accepted
3 Important data_idx overflow No compile-time assertion that N <= u16::MAX
4 Important RS parameter role_data SmallVec uses RS but undocumented
5 Important set_role_admin Creates empty role slots, consuming capacity silently
6 Important Stale docs DEFAULT_ADMIN_ROLE in doc comments throughout
7 Important grant_initial_admin Silent CapacityExceeded failure when N == 0
8 Suggestion require_role Add debug_assert for index-0 assumption
9 Suggestion Benchmarks Baseline reduction eliminates high-scale regression detection
10 Suggestion Capacity tests stress_test_max_members doesn't guard against role-slot exhaustion
11 Suggestion vft-admin sizing RS == N and MS == M is intentional but unexplained
12 Suggestion README Indentation error in code example

@vobradovich vobradovich changed the title chore(deps): update sails-rs to =1.0.0-beta.4 feat: update sails-rs to 1.0.0 May 22, 2026
@github-actions github-actions Bot added the feat label May 22, 2026
@vobradovich vobradovich self-assigned this May 22, 2026
@github-actions

Copy link
Copy Markdown
Contributor
🔬 Click to see benchmark results vs master

🔬 Benchmark Comparison

Metric Current Baseline Change % Status
access_control.grant_role.0 950_403_467 990_713_476 -40_310_009 -4.07% 👍
access_control.grant_role.100 1_015_694_788 852_534_024 +163_160_764 19.14% ❌
access_control.grant_role.25 984_009_704 - - - ✨
access_control.grant_role.50 994_648_346 - - - ✨
access_control.has_role.0 965_248_793 837_548_725 +127_700_068 15.25% ❌
access_control.has_role.100 812_412_203 850_763_647 -38_351_444 -4.51% 👍
access_control.has_role.25 811_950_519 - - - ✨
access_control.has_role.50 812_181_361 - - - ✨
access_control.has_role_multi.1 965_248_793 837_548_725 +127_700_068 15.25% ❌
access_control.has_role_multi.16 851_426_257 - - - ✨
access_control.has_role_multi.32 851_657_692 - - - ✨
access_control.has_role_multi.8 851_406_759 - - - ✨
access_control.revoke_role.0 974_464_581 844_228_279 +130_236_302 15.43% ❌
access_control.revoke_role.100 1_017_811_082 857_192_808 +160_618_274 18.74% ❌
access_control.revoke_role.25 986_081_598 - - - ✨
access_control.revoke_role.50 996_735_040 - - - ✨

Legend

  • 🚀 Significant improvement (>5% reduction)
  • 👍 Minor improvement (<1% reduction)
  • ✅ No significant change
  • ⚠️ Minor regression (>1% increase)
  • ❌ Significant regression (>5% increase)
  • ✨ New metric (not present in baseline)
  • 🗑️ Removed metric (not present in current)

🤖 This comment was automatically generated. Baseline: branch master.

@github-actions

Copy link
Copy Markdown
Contributor
🔬 Click to see benchmark results vs master

🔬 Benchmark Comparison

Metric Current Baseline Change % Status
access_control.grant_role.0 948_553_136 990_713_476 -42_160_340 -4.26% 👍
access_control.grant_role.100 1_013_844_457 852_534_024 +161_310_433 18.92% ❌
access_control.grant_role.25 982_159_373 - - - ✨
access_control.grant_role.50 992_798_015 - - - ✨
access_control.has_role.0 963_398_462 837_548_725 +125_849_737 15.03% ❌
access_control.has_role.100 810_561_872 850_763_647 -40_201_775 -4.73% 👍
access_control.has_role.25 810_100_188 - - - ✨
access_control.has_role.50 810_331_030 - - - ✨
access_control.has_role_multi.1 963_398_462 837_548_725 +125_849_737 15.03% ❌
access_control.has_role_multi.16 849_575_926 - - - ✨
access_control.has_role_multi.32 849_807_361 - - - ✨
access_control.has_role_multi.8 849_556_428 - - - ✨
access_control.revoke_role.0 972_614_250 844_228_279 +128_385_971 15.21% ❌
access_control.revoke_role.100 1_015_960_751 857_192_808 +158_767_943 18.52% ❌
access_control.revoke_role.25 984_231_267 - - - ✨
access_control.revoke_role.50 994_884_709 - - - ✨

Legend

  • 🚀 Significant improvement (>5% reduction)
  • 👍 Minor improvement (<1% reduction)
  • ✅ No significant change
  • ⚠️ Minor regression (>1% increase)
  • ❌ Significant regression (>5% increase)
  • ✨ New metric (not present in baseline)
  • 🗑️ Removed metric (not present in current)

🤖 This comment was automatically generated. Baseline: branch master.

1 similar comment
@github-actions

Copy link
Copy Markdown
Contributor
🔬 Click to see benchmark results vs master

🔬 Benchmark Comparison

Metric Current Baseline Change % Status
access_control.grant_role.0 948_553_136 990_713_476 -42_160_340 -4.26% 👍
access_control.grant_role.100 1_013_844_457 852_534_024 +161_310_433 18.92% ❌
access_control.grant_role.25 982_159_373 - - - ✨
access_control.grant_role.50 992_798_015 - - - ✨
access_control.has_role.0 963_398_462 837_548_725 +125_849_737 15.03% ❌
access_control.has_role.100 810_561_872 850_763_647 -40_201_775 -4.73% 👍
access_control.has_role.25 810_100_188 - - - ✨
access_control.has_role.50 810_331_030 - - - ✨
access_control.has_role_multi.1 963_398_462 837_548_725 +125_849_737 15.03% ❌
access_control.has_role_multi.16 849_575_926 - - - ✨
access_control.has_role_multi.32 849_807_361 - - - ✨
access_control.has_role_multi.8 849_556_428 - - - ✨
access_control.revoke_role.0 972_614_250 844_228_279 +128_385_971 15.21% ❌
access_control.revoke_role.100 1_015_960_751 857_192_808 +158_767_943 18.52% ❌
access_control.revoke_role.25 984_231_267 - - - ✨
access_control.revoke_role.50 994_884_709 - - - ✨

Legend

  • 🚀 Significant improvement (>5% reduction)
  • 👍 Minor improvement (<1% reduction)
  • ✅ No significant change
  • ⚠️ Minor regression (>1% increase)
  • ❌ Significant regression (>5% increase)
  • ✨ New metric (not present in baseline)
  • 🗑️ Removed metric (not present in current)

🤖 This comment was automatically generated. Baseline: branch master.

@vobradovich
vobradovich merged commit b139af2 into master Jun 17, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants