Resource Scanner
Automatic resource discovery that scans @Protectable methods and MVC endpoints at application startup, registering them as ManagedResource entities for policy assignment.
Overview
Contexa provides two complementary resource scanners that detect different types of protectable resources in the application:
- MethodResourceScanner —Discovers non-controller methods annotated with
@Protectable - MvcResourceScanner —Discovers Spring MVC controller endpoints via
RequestMappingHandlerMapping
Both scanners implement the ResourceScanner interface and produce ManagedResource entities with an initial status of NEEDS_DEFINITION.
End-to-End Pipeline
Resource scanning is the first stage of a four-step resource management pipeline: Scan —Define —Policy —Dynamic Authorization. At application startup, ResourceScanner implementations discover all @RequestMapping endpoints and @Protectable methods, storing them as ManagedResource entities in the database. The AI engine then generates human-readable friendly names for discovered resources in batch.
The scanners synchronize discovered resources into ManagedResourceRepository. In the current OSS operator flow, review, permission definition, and policy creation are centered in the integrated Policy Center resources/create experience. The legacy /admin/workbench/resources controller path still exists in server code and continues to expose the underlying define, exclude, restore, and management endpoints.
ResourceScanner Interface
public interface ResourceScanner {
List<ManagedResource> scan();
}
MethodResourceScanner
Scans all Spring beans in the io.contexa.contexaiam package for public methods annotated with @Protectable. Controller classes are explicitly excluded since they are handled by MvcResourceScanner.
Scan Logic
- Iterate all bean definitions in the
ApplicationContext - Resolve the target class (unwrapping AOP proxies via
AopUtils.getTargetClass()) - Skip classes outside the
io.contexa.contexaiampackage - Skip classes annotated with
@Controlleror@RestController - For each public method with
@Protectable, create aManagedResource
Resource Identifier Format
Method resources use a fully qualified method signature as the identifier:
io.contexa.contexaiam.service.AccountService.updateAccount(Long,AccountDto)
ManagedResource Fields (METHOD type)
| Field | Value Source |
|---|---|
resourceIdentifier | Fully qualified method signature with parameter types |
resourceType | METHOD |
serviceOwner | Simple class name of the declaring class |
parameterTypes | JSON array of fully qualified parameter type names |
returnType | Fully qualified return type name |
sourceCodeLocation | Derived from class name: io/contexa/.../ClassName.java |
status | NEEDS_DEFINITION |
MvcResourceScanner
Scans Spring MVC @Controller and @RestController classes for URL-mapped endpoints using RequestMappingHandlerMapping.
Scan Logic
- Retrieve the
requestMappingHandlerMappingbean - Iterate all registered handler methods
- Skip classes outside the
io.contexa.contexaiampackage - Skip classes not annotated with
@Controlleror@RestController - Extract URL patterns from
PathPatternsRequestCondition - Extract HTTP method (defaulting to
ANY) - Generate API docs URL using
IamAdminProperties.restDocsPath
ManagedResource Fields (URL type)
| Field | Value Source |
|---|---|
resourceIdentifier | URL pattern string (e.g., /admin/users/{id}) |
resourceType | URL |
httpMethod | GET, POST, PUT, DELETE, PATCH, or ANY |
friendlyName | Handler method name |
description | URL: [HTTP_METHOD] /path/pattern |
serviceOwner | Simple class name of the controller |
apiDocsUrl | {restDocsPath}#{controller}_{method} |
status | NEEDS_DEFINITION |
ManagedResource Entity
@Entity
@Table(name = "MANAGED_RESOURCE")
public class ManagedResource {
private Long id;
private String resourceIdentifier; // URL pattern or method signature
private ResourceType resourceType; // URL or METHOD
private HttpMethod httpMethod; // GET, POST, PUT, DELETE, PATCH, ANY
private String friendlyName;
private String description;
private String serviceOwner;
private String parameterTypes; // JSON array (METHOD only)
private String returnType; // Fully qualified type (METHOD only)
private String apiDocsUrl; // Link to API documentation
private String sourceCodeLocation; // Source file path (METHOD only)
private String availableContextVariables;
private Status status; // NEEDS_DEFINITION, PERMISSION_CREATED,
// POLICY_CONNECTED, EXCLUDED
private Permission permission; // OneToOne mapping
private LocalDateTime createdAt;
private LocalDateTime updatedAt;
public enum ResourceType { URL, METHOD }
public enum HttpMethod { GET, POST, PUT, DELETE, PATCH, ANY }
public enum Status {
NEEDS_DEFINITION,
PERMISSION_CREATED,
POLICY_CONNECTED,
EXCLUDED
}
}
Resource Lifecycle
| Status | Description |
|---|---|
NEEDS_DEFINITION | Discovered by scanner; no permission assigned yet |
PERMISSION_CREATED | A Permission entity has been linked to this resource |
POLICY_CONNECTED | A policy references this resource through its targets |
EXCLUDED | Explicitly excluded from authorization (e.g., public endpoints) |
ManagedResource Lifecycle
Status Transitions
| Status | Description | Transition Trigger |
|---|---|---|
NEEDS_DEFINITION | Resource discovered by scanner, not yet configured | Initial scan |
PERMISSION_CREATED | defineResourceAsPermission() called, Permission entity created | Admin action in the Policy Center resources flow or legacy workbench route |
POLICY_CONNECTED | Policy created and linked to this resource | Policy Center / legacy policy screens |
EXCLUDED | Resource excluded from authorization management | Exclude flow updates the managed resource status |
ManagedResource Entity Fields
| Field | Type | Description |
|---|---|---|
resourceIdentifier | String | Unique ID (URL pattern + method, or qualified method signature) |
resourceType | ResourceType | URL or METHOD |
friendlyName | String | AI-suggested human-readable name, or a fallback name when AI suggestions are unavailable |
status | ManagedResource.Status | NEEDS_DEFINITION, PERMISSION_CREATED, POLICY_CONNECTED, EXCLUDED |
Resource Workbench
The legacy /admin/workbench/resources route is still implemented in server code. In the current OSS UI bundle, day-to-day review and policy authoring are centered in Policy Center, which uses the same managed-resource registry and related admin endpoints.
Discovering Resources
- View all scanned resources with status-based filtering
- Refresh scan results on demand
- Search and filter by resource type, status, or name
Defining Resources as Permissions
Click "Define as Permission" on a NEEDS_DEFINITION resource to:
- Create a corresponding
Permissionentity - Update the resource status to
PERMISSION_CREATED - Make the resource available for policy creation
Two Paths from Workbench
After defining a resource as a permission, two policy creation options are available:
| Path | Action | Use Case |
|---|---|---|
| Quick Grant | Policy Center quick-create flow with selected roles, permissions, or stored SpEL shortcuts | Simple role-to-permission assignment |
| Advanced Policy | Policy Center manual / AI-assisted create flow with resource context | Complex conditions, AI expressions, multi-rule policies |
End-to-End Workflow
Step 1: Scan
Automatic at application startup via WorkbenchInitializer. MvcResourceScanner scans all @Controller and @RestController classes. MethodResourceScanner scans all @Protectable methods. Friendly names and descriptions are then filled from AI suggestions when available, with fallback values used if AI suggestions are unavailable.
Step 2: Review & Define
Review NEEDS_DEFINITION resources through the current Policy Center integrated resources area or the legacy workbench-backed endpoints. Define relevant resources as permissions, and exclude resources that do not need authorization (static assets, public endpoints).
Step 3: Create Policy
From the current Policy Center resources flow, or the legacy /admin/policy-builder/from-resource route, continue into policy authoring with the selected resource context. Compatible condition templates are filtered for the chosen resource, and the same managed-resource lifecycle stays in sync as the policy is created.
Step 4: Dynamic Authorization
When the policy is saved, reloadAuthorizationSystem() triggers CustomDynamicAuthorizationManager.reload(). The policy takes effect immediately. With .anyRequest().access(customDynamicAuthorizationManager) in your security configuration, no static authorization rules are needed.
Resource Workbench: Operations Guide
The managed-resource lifecycle is still backed by the legacy /admin/workbench/resources controller, but the current OSS UI centers operators in Policy Center. This section describes the shared operational workflows behind both surfaces.
Filtering Resources
The current resource review flow provides multiple filtering options to find resources quickly, whether operators use the integrated Policy Center surface or the legacy workbench-backed endpoints:
| Filter | Options | Use Case |
|---|---|---|
| By Status | NEEDS_DEFINITION, PERMISSION_CREATED, POLICY_CONNECTED, EXCLUDED | Find resources at a specific lifecycle stage |
| By Service Owner | Controller or service class name | Filter resources belonging to a specific module |
| By Keyword | Free text search | Search by resource identifier, friendly name, or description |
| By Resource Type | URL or METHOD | Filter by endpoint type vs. method-level resource |
Defining a Resource
When you define a resource, the following happens in sequence:
- Click "Define as Permission" on a
NEEDS_DEFINITIONresource - Enter a friendly name for the permission (or accept the AI-suggested name)
- A
Permissionentity is automatically created and linked to the resource - The resource status changes to
PERMISSION_CREATED - The resource is now ready for policy assignment
Policy Setup from Workbench
After defining a resource, a modal appears offering two policy creation paths:
Quick Grant (Wizard)
Use the Policy Center quick-create flow to open a simplified grant path with the selected resource context.
- Pre-selects the resource permission
- Choose target roles and confirm
- Creates a simple ALLOW policy
Advanced (Manual / builder-compatible flow)
Use the Policy Center manual create flow to open the full policy authoring experience with the selected resource context. The legacy builder controller path still exists in server code, but the current OSS template bundle centers this flow in Policy Center.
- Target is pre-filled (from-resource mode)
- Full condition template selection
- Supports complex rules and AI conditions
Excluding and Restoring Resources
Resources that do not require authorization (public endpoints, static assets, health checks) can be excluded:
- Excluding: Click "Exclude" on a
NEEDS_DEFINITIONresource. The status changes toEXCLUDED, and the resource is removed from authorization management. - Restoring: Excluded resources can be restored by clicking "Restore". The status reverts to
NEEDS_DEFINITION, and the resource re-enters the management lifecycle.
When to exclude: Public API endpoints, static asset paths, health check endpoints (/actuator/health), documentation paths.
When to restore: Previously public endpoints that now require authorization, or resources excluded by mistake.
Status Transition Diagram
AI Auto-Naming
When resources are discovered by the scanner, their technical identifiers (URL patterns or method signatures) are not user-friendly. The AI auto-naming system generates human-readable names and descriptions automatically.
How It Works
ResourceRegistryServiceImpl calls the AI ResourceNaming service after scanning is complete. The AI analyzes each technical identifier and generates:
- Friendly name: A concise, business-oriented name (e.g., "Update User Profile" for
PUT /api/users/{id}) - Description: A longer explanation of what the resource does
Batch Processing
To optimize AI API usage, auto-naming processes resources in batches of 10 items per batch. This approach:
- Reduces the number of AI API calls
- Provides contextual awareness across related resources in the same batch
- Handles failures gracefully by retrying individual batches
Name Generation Strategy
| Technical Identifier | AI-Generated Friendly Name |
|---|---|
GET /api/users | List All Users |
PUT /api/users/{id} | Update User Profile |
DELETE /admin/roles/{id} | Delete Role |
AccountService.updateAccount(Long,AccountDto) | Update Account Details |