import { type RawRuleOf } from '@casl/ability';
import { type MemberAbility } from './types';
type MemberRule = RawRuleOf<MemberAbility>;
/**
 * Collapses rules that are identical except for the value of a single scalar
 * condition (e.g. `projectUuid`, `upstreamProjectUuid`) into one rule with that
 * key as `{ $in: [...] }`, and drops exact duplicates.
 *
 * Only sound when the rule set contains NO inverted (`cannot`) rules: with only
 * positive rules, `can()` means "does any rule match", so both `$in` merging and
 * exact dedup are order-independent and decision-preserving. With an inverted
 * rule present, CASL is last-relevant-rule-wins, and removing or merging a
 * positive rule can flip a decision (e.g. a duplicate `can` after a `cannot` is
 * what re-grants access). In that case we return the rules untouched. Every
 * built-in role, custom-scope, and service-account builder emits only positive
 * rules (guarded by a test), so the large-permission-graph case this targets is
 * fully collapsed.
 *
 * Masking ALL scalar-string condition values when grouping is safe because a
 * single ability is built for one org and one user, so `organizationUuid`,
 * `userUuid`, `createdByUserUuid` and `type` are constants across the rule set —
 * the only scalar that varies is the per-project id. If that ever stops holding
 * (two scalars varying independently within a group), `varyingKeys.length > 1`
 * falls back to dedup-only and never produces a wrong `$in` merge.
 *
 * Decision-equivalence: `{ key: { $in: [a, b] } }` matches exactly the union of
 * `{ key: a }` and `{ key: b }` when every other condition is identical.
 */
export declare const collapseAbilityRules: (rules: MemberRule[]) => MemberRule[];
export {};
//# sourceMappingURL=collapseAbilityRules.d.ts.map