Use Case Coverage
A compact matrix for the important Accessly APIs, followed by small data-driven scenario packs. These are validation examples, not standalone demo apps.
Use Case Matrix
Grouped by API area and checked against the Accessly V1 public exports.
| Category | Use case | API used | Example permission/flag | Expected result | Status | Notes |
|---|---|---|---|---|---|---|
| Types | AccessModel | AccessModel | { user, permissions, flags, navigation, isLoading } | Shared normalized model for providers, hooks, adapters, navigation, and debug tools. | Stable | Scenario packs show normalized AccessModel objects. |
| Types | AccessDecision | AccessDecision | { allowed, reason, missing, matched, checkedFrom } | Detailed result for allowed, denied, loading, unknown, and invalid checks. | Stable | Scenario checks list expected decision fields. |
| Types | NavigationItem | NavigationItem | { label, href, permission, children } | Typed navigation can be filtered by permission. | Stable | Covered by flat and nested navigation rows. |
| Types | RolePermissions | RolePermissions | { admin: ['users.*'] } | Provider and engine can expand role permissions during checks. | Stable | Covered as provider and engine configuration. |
| Types | PermissionCheckInput | PermissionCheckInput | { permission } | { any } | { all } | { flag } | One typed input shape powers engine, hooks, and components. | Stable | All four variants are covered below. |
| Types | PermissionProviderProps | PermissionProviderProps | access, source, adapter, loading, registry | Documents the provider boundary and optional normalization path. | Stable | Loading, adapter, role, and unknown-permission rows cover important props. |
| Types | AccessAdapter | AccessAdapter | { normalize: (source) => AccessModel } | Custom adapters expose a normalize function. | Stable | Covered by createAdapter and backend normalization. |
| Engine | Direct permission allowed | checkPermission / Can / usePermission | users.create | Allowed when the model contains users.create. | Stable | Covers direct checkedFrom metadata. |
| Engine | Missing permission denied | checkPermission / Cannot | billing.manage | Denied with missing_permission. | Stable | Used for hidden or disabled UI. |
| Engine | Wildcard allowed | matchPermission / checkPermission | users.* -> users.create | Allowed with checkedFrom wildcard. | Stable | Admin and GitHub scenarios cover single-level wildcard checks. |
| Engine | Nested wildcard allowed | matchPermission / checkPermission | users.profile.* -> users.profile.edit | Allowed when wildcard and target have the same segment depth. | Stable | Admin scenario covers this real matching rule. |
| Engine | any[] allowed | checkPermission / Can | { any: ['media.upload', 'media.manage'] } | Allowed when at least one permission matches. | Stable | CMS scenario validates this. |
| Engine | any[] denied | checkPermission | { any: ['media.delete', 'media.admin'] } | Denied when no requested permission matches. | Stable | CMS scenario includes the denied branch. |
| Engine | all[] allowed | checkPermission / Can | { all: ['posts.update', 'posts.publish'] } | Allowed only when every permission matches. | Stable | CMS scenario validates this. |
| Engine | all[] denied | checkPermission | { all: ['posts.publish', 'posts.delete'] } | Denied with missing_permission when any requirement is missing. | Stable | CMS scenario includes the denied branch. |
| Engine | Feature flag allowed | checkPermission / Can | features.auditLog | Allowed with checkedFrom flag. | Stable | Admin, SaaS, and HR scenarios include enabled flags. |
| Engine | Feature flag denied | checkPermission / Can | features.newCheckout | Denied with missing_flag. | Stable | E-commerce scenario covers disabled flag behavior. |
| Engine | Unknown permission strategy | checkPermission | unknownPermission='throw' | Returns unknown_permission for unregistered denied checks. | Stable | Covered in the matrix as validation behavior. |
| Provider | Provider boundary | PermissionProvider | <PermissionProvider access={access}> | Makes the current AccessModel available to components and hooks. | Stable | Scenario snippets wrap UI with PermissionProvider. |
| Provider | Loading state | PermissionProvider / Can / ProtectedRoute | loading={true} | Returns not_ready and renders loading or fallback UI. | Stable | Covered for component and route gating. |
| React components | Can with children | Can | <Can permission='orders.fulfill'> | Renders children when the check is allowed. | Stable | Admin, CMS, HR, and E-commerce snippets use children. |
| React components | Can with fallback | Can | fallback={<button disabled />} | Renders fallback when denied or not ready. | Stable | E-commerce snippet covers disabled fallback UI. |
| React components | Can render prop with decision | Can | {(decision) => <Denied reason={decision.reason} />} | Receives the full AccessDecision for custom UI. | Stable | Documented in the matrix as the render-prop path. |
| React components | Cannot basic | Cannot | <Cannot permission='salary.view'> | Renders children when the check is denied. | Stable | HR and CMS scenarios cover denied UI. |
| React components | Cannot with flag | Cannot | <Cannot permission={{ flag: 'features.compensation' }}> | Renders children when a feature flag is missing. | Stable | HR scenario covers a denied flag check. |
| React components | ProtectedRoute fallback | ProtectedRoute | fallback={<Denied />} | Renders route fallback when denied. | Stable | SaaS and GitHub scenarios cover route checks. |
| React components | ProtectedRoute loading | ProtectedRoute | loading={<Spinner />} | Renders loading UI while the provider is not ready. | Stable | Covered with provider loading behavior. |
| Hooks | usePermission boolean | usePermission | usePermission('exports.enterprise') | Returns a boolean for custom controls. | Stable | SaaS scenario covers disabled button logic. |
| Hooks | useAccessDecision detailed result | useAccessDecision | useAccessDecision('repo.settings.manage') | Returns allowed, reason, missing, matched, and checkedFrom. | Stable | Used for denied explanations and debugging. |
| Hooks | useAccessModel reading current model | useAccessModel | const model = useAccessModel() | Reads the current normalized AccessModel from context. | Stable | Covered as a model inspection use case. |
| Navigation | filterNavigation flat nav | filterNavigation | [{ label: 'Billing', permission: 'billing.manage' }] | Returns only accessible top-level navigation items. | Stable | Sidebar filtering is explicitly covered. |
| Navigation | filterNavigation nested nav | filterNavigation | { children: [{ permission: 'settings.read' }] } | Filters children and skips parents with no visible children. | Stable | Covers nested NavigationItem behavior. |
| Navigation | useFilteredNavigation context nav | useFilteredNavigation | useFilteredNavigation(items, model) | Memoizes filtered navigation for React components. | Stable | Covered as the hook wrapper around filterNavigation. |
| Adapters | createAdapter custom backend | createAdapter / AccessAdapter | createAdapter((source) => ({ permissions: source.perms })) | Normalizes custom backend data to AccessModel. | Stable | Backend normalization row links to this utility. |
| Adapters | createActionsAdapter mapping actions | createActionsAdapter | { posts: ['read', 'publish'] } | Maps grouped actions to posts.read and posts.publish permissions. | Stable | Built-in adapter coverage. |
| Adapters | directPermissionsAdapter | directPermissionsAdapter | { permissions, roles, flags } | Maps flat backend fields directly. | Stable | Built-in adapter coverage. |
| Adapters | featureFlagsAdapter | featureFlagsAdapter | { features: { auditLog: true } } | Maps enabled features to flags. | Stable | Built-in adapter coverage. |
| Adapters | nestedModulesAdapter | nestedModulesAdapter | { posts: { publish: true } } | Maps nested booleans to permissions. | Stable | Built-in adapter coverage. |
| Adapters | pagesOnlyAdapter | pagesOnlyAdapter | { pages: ['admin'] } | Maps pages to pages.admin permissions. | Stable | Built-in adapter coverage. |
| Debug | formatDecision | formatDecision | formatDecision(decision) | Formats an AccessDecision for readable debugging output. | Stable | Supports denied explanation workflows. |
| Debug | inspectAccess | inspectAccess | inspectAccess(model) | Summarizes the current model, roles, permissions, flags, and loading state. | Stable | Pairs with useAccessModel and backend normalization debugging. |
| UI scenarios | Fallback UI | Can / Cannot / ProtectedRoute | fallback={<Denied />} | Shows alternate UI when denied or not ready. | Stable | E-commerce scenario uses disabled fallback. |
| UI scenarios | Denied explanation | useAccessDecision / formatDecision | payments.refund | Shows reason and missing permission details. | Stable | Scenario checks include expected denial reasons. |
| UI scenarios | Backend normalization | createAdapter and built-in adapters | backend roles, permissions, flags | Produces one AccessModel shape for React APIs. | Stable | Scenario access models are normalized outputs. |
| UI scenarios | Sidebar filtering | filterNavigation / useFilteredNavigation | settings.manage | Hides nav items the user cannot access. | Stable | Preview cards include visible and hidden nav states. |
| UI scenarios | Field-level hiding | Can / Cannot | salary.view | Hides restricted fields while keeping layout explicit. | Stable | HR scenario covers salary hiding. |
| UI scenarios | Disabled action button | usePermission / Can fallback | payments.refund | Disables an action while preserving denied context. | Stable | SaaS and E-commerce scenarios cover this. |
Missing Coverage
0 missingNo missing or partial coverage found in the current Accessly V1 public API audit. Rows marked Stable are represented by the matrix, scenario packs, or docs-page references.
Lightweight Scenario Packs
6 scenariosAdmin Dashboard
A system admin can manage users, view audit logs, and see admin-only navigation.
Checks
| Use | API | Input | Expected |
|---|---|---|---|
| Create user button | Can | users.create | allow / allowed |
| Audit page flag | useAccessDecision | features.auditLog | allow / allowed |
| Edit user profile | matchPermission | users.profile.edit | allow / allowed |
| Billing settings | Cannot | billing.manage | deny / missing_permission |
Small UI preview
Matched by users.*
Feature flag enabled
No billing.manage permission
Access model
{
"user": {
"id": "u_admin",
"roles": [
"admin"
]
},
"permissions": [
"users.*",
"users.profile.*",
"audit.view",
"settings.read"
],
"flags": [
"features.auditLog"
]
}const access = {
permissions: ["users.*", "users.profile.*", "audit.view", "settings.read"],
flags: ["features.auditLog"],
};
<PermissionProvider access={access}>
<Can permission="users.create">
<CreateUserButton />
</Can>
</PermissionProvider>SaaS Dashboard
A workspace owner sees reports and plan controls while beta features stay gated.
Checks
| Use | API | Input | Expected |
|---|---|---|---|
| Reports route | ProtectedRoute | reports.view | allow / allowed |
| Insights beta | Can | features.usageInsights | allow / allowed |
| Enterprise export | usePermission | exports.enterprise | deny / missing_permission |
Small UI preview
Direct permission
Flag enabled
Upsell or explain denial
Access model
{
"user": {
"id": "u_owner",
"roles": [
"owner"
]
},
"permissions": [
"reports.view",
"billing.manage",
"team.invite"
],
"flags": [
"features.usageInsights"
]
}const canExport = usePermission("exports.enterprise");
<button disabled={!canExport}>
Export report
</button>CMS
Editors can publish content, but destructive administration remains hidden.
Checks
| Use | API | Input | Expected |
|---|---|---|---|
| Publish action | Can | all: posts.update, posts.publish | allow / allowed |
| Media tools | Can | any: media.upload, media.manage | allow / allowed |
| Admin media tools | checkPermission | any: media.delete, media.admin | deny / missing_permission |
| Publish and delete | checkPermission | all: posts.publish, posts.delete | deny / missing_permission |
| Delete site | Cannot | site.delete | deny / missing_permission |
Small UI preview
all[] requirements pass
any[] has a match
Destructive action denied
Access model
{
"user": {
"id": "u_editor",
"roles": [
"editor"
]
},
"permissions": [
"posts.read",
"posts.update",
"posts.publish",
"media.upload"
],
"flags": [
"features.richEditor"
]
}<Can permission={{ all: ["posts.update", "posts.publish"] }}>
<PublishButton />
</Can>GitHub Repository
Repository collaborators can manage issues while protected settings stay owner-only.
Checks
| Use | API | Input | Expected |
|---|---|---|---|
| Close issue | Can | issues.close | allow / allowed |
| Review pull request | useAccessDecision | pulls.review | allow / allowed |
| Repository settings | ProtectedRoute | repo.settings.manage | deny / missing_permission |
Small UI preview
Wildcard permission
Direct permission
Owner-only permission missing
Access model
{
"user": {
"id": "u_maintainer",
"roles": [
"maintainer"
]
},
"permissions": [
"repo.read",
"issues.*",
"pulls.review"
],
"flags": [
"features.codeowners"
]
}const decision = useAccessDecision("repo.settings.manage");
return decision.allowed ? <Settings /> : <Denied reason={decision.reason} />;HR System
Managers can approve leave and hide salary fields without full HR administration.
Checks
| Use | API | Input | Expected |
|---|---|---|---|
| Approve leave | Can | leave.approve | allow / allowed |
| Salary field | Cannot | salary.view | deny / missing_permission |
| Self-service flag | Can | features.selfService | allow / allowed |
| Compensation beta | Cannot | features.compensation | deny / missing_flag |
Small UI preview
Manager permission
Field-level hiding
Self-service enabled
Access model
{
"user": {
"id": "u_manager",
"roles": [
"manager"
]
},
"permissions": [
"employees.read",
"leave.approve",
"profile.update"
],
"flags": [
"features.selfService"
]
}<Cannot permission="salary.view"> <span className="sr-only">Salary hidden</span> </Cannot>
E-commerce
Store staff can process orders and use inventory tools while refunds require extra access.
Checks
| Use | API | Input | Expected |
|---|---|---|---|
| Fulfill order | Can | orders.fulfill | allow / allowed |
| Refund order | useAccessDecision | payments.refund | deny / missing_permission |
| New checkout flag | Can | features.newCheckout | deny / missing_flag |
Small UI preview
Direct permission
Denied explanation shown
Feature flag disabled
Access model
{
"user": {
"id": "u_staff",
"roles": [
"store_staff"
]
},
"permissions": [
"orders.read",
"orders.fulfill",
"inventory.update"
],
"flags": []
}<Can
permission="payments.refund"
fallback={<button disabled>Refund unavailable</button>}
>
<RefundButton />
</Can>