access_gate 0.0.3 copy "access_gate: ^0.0.3" to clipboard
access_gate: ^0.0.3 copied to clipboard

Hide Flutter widgets behind feature flags, roles, permissions, and attribute-based access policies.

access_gate #

Hide Flutter widgets behind feature flags, roles, permissions, and attribute-based access policies.

access_gate is intentionally provider-agnostic. Bring your own source of truth, such as Firebase Remote Config, LaunchDarkly, Supabase claims, local app state, or a backend policy response, then expose those facts through AccessContext.

Features #

  • Feature flag gates with enabled flags and exact feature values.
  • RBAC gates with required roles or any-of role checks.
  • Permission gates for fine-grained access checks.
  • ABAC gates with exact attributes and custom predicates.
  • Policy composition with all-of, any-of, and not rules.
  • Structured denial reasons for custom fallback UI.
  • AccessGuard for page-level access decisions.
  • JSON helpers for access contexts and serializable policies.
  • AccessScope and AccessController for inherited access state.
  • AccessHidden, a zero-size fallback for denied gates.

Getting started #

Add the package, then create an AccessController from your app's current feature flag and authorization state.

final accessController = AccessController(
  AccessContext(
    enabledFeatures: {'advanced_reports'},
    roles: {'admin'},
    permissions: {'reports.view'},
    attributes: {'plan': 'pro', 'region': 'us'},
  ),
);

Place AccessScope above the widgets that should use the shared access state.

AccessScope(
  controller: accessController,
  child: const MyApp(),
);

Basic usage #

Require one feature flag:

AccessGate.feature(
  feature: 'advanced_reports',
  child: const AdvancedReportsButton(),
);

Require a role:

AccessGate.role(
  role: 'admin',
  fallback: const Text('Admin access required'),
  child: const AdminPanel(),
);

Require a permission:

AccessGate.permission(
  permission: 'reports.view',
  child: const ReportList(),
);

Combine feature flags, roles, permissions, and ABAC attributes:

AccessGate.when(
  allFeatures: {'advanced_reports'},
  anyRoles: {'admin', 'analyst'},
  allPermissions: {'reports.view'},
  attributes: {'plan': 'pro'},
  child: const AdvancedReportsPage(),
);

Use a custom predicate when exact attribute matching is not enough:

AccessGate.when(
  predicate: (context) {
    return context.attribute('teamId') == selectedTeamId &&
        context.attribute('plan') == 'enterprise';
  },
  predicateReason: 'Requires access to this team.',
  child: const TeamSettings(),
);

Policy composition #

Compose policies when access can be granted through multiple paths, or when an allow rule needs an explicit exclusion.

final policy = AccessPolicy.allOf([
  AccessPolicy.anyOf([
    AccessPolicy.role('admin'),
    AccessPolicy(
      allPermissions: {'reports.view'},
      attributes: {'plan': 'pro'},
    ),
  ]),
  AccessPolicy.not(
    AccessPolicy.role('suspended'),
    reason: 'Suspended users cannot access reports.',
  ),
]);

AccessGate(
  policy: policy,
  child: const AdvancedReportsPage(),
);

Page guards #

Use AccessGuard when the whole page or route body should branch on an access decision.

AccessGuard(
  policy: AccessPolicy.permission('reports.view'),
  builder: (context, decision) {
    return const ReportsPage();
  },
  deniedBuilder: (context, decision) {
    return Text(decision.reasons.first);
  },
);

Typed keys #

The core API stores provider-facing strings, but apps can define typed keys with enums by implementing the category marker interfaces.

enum AppFeature implements AccessFeature {
  advancedReports('advanced_reports');

  const AppFeature(this.accessKey);

  @override
  final String accessKey;
}

enum AppRole implements AccessRole {
  admin('admin');

  const AppRole(this.accessKey);

  @override
  final String accessKey;
}

Use fromKeys and *Key constructors when you want compile-time key names in app code:

final context = AccessContext.fromKeys(
  enabledFeatures: {AppFeature.advancedReports},
  roles: {AppRole.admin},
);

AccessGate.featureKey(
  feature: AppFeature.advancedReports,
  child: const AdvancedReportsButton(),
);

If an enum's case name already matches the provider key, the AccessEnumKey extension exposes myEnumValue.accessKey as a convenience.

Denied access #

By default, denied gates render accessHidden, a zero-size widget that is safe inside layout widgets like Column, Row, and Stack. This is useful when a widget should simply disappear.

AccessGate.feature(
  feature: 'new_checkout',
  child: const CheckoutButton(),
);

Use fallback or fallbackBuilder when denied users should see something.

AccessGate.permission(
  permission: 'billing.manage',
  fallbackBuilder: (context, decision) {
    final reason = decision.denialReasons.first;
    return Text('${reason.key}: ${reason.message}');
  },
  child: const BillingSettings(),
);

decision.reasons remains available as a simple list of messages.

JSON helpers #

AccessContext can round-trip through JSON-compatible maps. Policies without custom predicates can also be serialized, including composed policies.

final context = AccessContext.fromJson(savedContextJson);
final policy = AccessPolicy.fromJson(savedPolicyJson);

final contextJson = context.toJson();
final policyJson = policy.toJson();

Custom predicate functions are runtime-only and cannot be serialized.

Agent-friendly usage #

Coding agents integrating this package into Flutter apps should read doc/using-access-gate.md.

The shared Agent Skills-compatible skill lives at skills/access-gate/. Codex can use it from that location. Claude Code users can copy that folder to ~/.claude/skills/access-gate/, or use the project wrapper at .claude/skills/access-gate/ when working from this repository.

Repository-maintenance guidance is available in AGENTS.md for Codex and CLAUDE.md for Claude Code.

Important security note #

access_gate controls client-side visibility. It is not a replacement for server-side authorization, database security rules, API checks, or audit controls. Use it to keep Flutter UI honest and ergonomic; enforce real access at your data and service boundaries too.

1
likes
0
points
58
downloads

Publisher

verified publisherwilliams.engineering

Weekly Downloads

Hide Flutter widgets behind feature flags, roles, permissions, and attribute-based access policies.

Repository (GitHub)
View/report issues

Topics

#authorization #feature-flags #rbac #abac

License

unknown (license)

Dependencies

flutter

More

Packages that depend on access_gate