Early Access Admin Management
The Early Access Admin system provides comprehensive management of early access requests for the ContainerPub platform. This feature allows administrators to control who gains access to the platform during preview/beta phases.
Overview
The early access system consists of:
- Request Management: Review, approve, or reject early access requests
- Capacity Control: Set limits on the number of approved users
- Feature Flag Toggle: Enable/disable early access registration globally
- Audit Logging: Track all administrative actions on requests
- Temporary Passwords: Generate and send temporary passwords for approved users
Architecture
Database Tables
early_access_requests
- Stores all early access requests from potential users
- Tracks status: pending, approved, rejected, converted, expired
- Contains user information: email, name, company, use case
- Links to created user accounts via user_uuid
early_access_audit_logs
- Records all administrative actions on requests
- Tracks who performed actions and when
- Stores metadata for each action (notes, reasons, etc.)
feature_flags
- Global feature flag: preview_registration_enabled
- Controls whether new early access requests are accepted
- Stores capacity limit in value.target_users
Components
Backend Service: admin_backend_api/lib/services/early_access_admin_service.dart
- Business logic for request management
- Capacity enforcement
- Email masking for privacy
- Audit log creation
Feature Flags Service: admin_backend_api/lib/services/feature_flags_service.dart
- List, read, and update feature flags
- Feature overview with registration statistics
Form Schema Service: admin_backend_api/lib/services/early_access_form_schema_admin_service.dart
- CRUD operations for registration form schemas
- Schema upsert (create or update)
- Form data validation against schemas
HTTP Handlers: admin_backend_api/lib/handlers/
- early_access_request_handler.dart — REST API endpoints for request management
- early_access_features_handler.dart — Feature flag endpoints
- early_access_form_schema_handler.dart — Form schema management endpoints
- Request validation and error handling with Sentry integration
Frontend: frontend/admin_portal/lib/features/early_access/
- Flutter UI with Forui components
- Request listing with filters
- Detail view with action buttons
- Settings management
Feature Flag System
Flag: preview_registration_enabled
This feature flag controls early access registration globally.
Structure:
{
"name": "preview_registration_enabled",
"enabled": true,
"value": {
"target_users": 100
}
}
Behavior:
- enabled: true - Early access registration is open (subject to capacity)
- enabled: false - Early access registration is closed (no new requests accepted)
- value.target_users - Maximum number of approved/converted users allowed
Flag Management API
Feature flags have their own management endpoints:
List all flags:
GET /api/admin/early-access-featuresGet a specific flag:
GET /api/admin/early-access-features/<name>
Update a flag:
PUT /api/admin/early-access-features/<uuid>
{
"enabled": false,
"value": { "target_users": 200 }
}
Get feature overview with stats:
GET /api/admin/early-access-features/<featureUuid>/overview
Form Schema Management
The early access system supports configurable registration forms via the form schema management API.
Schema Operations
List schemas:
GET /api/admin/early-access-form-schemasGet schema by UUID:
GET /api/admin/early-access-form-schemas/<schemaUuid>
Get schemas by feature:
GET /api/admin/early-access-form-schemas/by-feature/<featureUuid>
Create or update schema (upsert):
POST /api/admin/early-access-form-schemas{
"feature_uuid": "feature-uuid",
"schema": {
"fields": [
{
"name": "company",
"type": "text",
"required": true,
"label": "Company Name"
},
{
"name": "use_case",
"type": "textarea",
"required": true,
"label": "How will you use ContainerPub?"
}
]
}
}
Delete schema:
DELETE /api/admin/early-access-form-schemas/<schemaUuid>
Validate form data against schema:
POST /api/admin/early-access-form-schemas/validate
{
"schema_uuid": "schema-uuid",
"data": {
"company": "Acme Corp",
"use_case": "Building cloud functions"
}
}
Capacity Management
The system enforces capacity limits:
- Check on Approval: Before approving a request, the system checks if capacity has been reached
- Count Approved/Converted: Only users with status approved or converted count toward capacity
- Prevent Over-Approval: If capacity is reached, approval requests fail with an error
Capacity Calculation:
final capacity = featureFlag.value['target_users'];
final approvedCount = COUNT(*) WHERE status IN ('approved', 'converted');
final availableSlots = capacity - approvedCount;
final acceptingRequests = approvedCount < capacity;
API Endpoints
List Requests
GET /api/admin/early-access/requests
Query parameters:
- page (int, default: 1) - Page number
- page_size (int, default: 20, max: 100) - Items per page
- status (string, optional) - Filter by status: pending, approved, rejected, converted, expired
- search (string, optional) - Search in email, first_name, last_name
Response:
{
"items": [
{
"uuid": "req-uuid",
"email": "jo***@example.com",
"first_name": "John",
"last_name": "Doe",
"company": "Acme Corp",
"use_case": "Building cloud functions",
"status": "pending",
"created_at": "2024-01-15T10:30:00Z"
}
],
"page": 1,
"page_size": 20
}
Get Request Details
GET /api/admin/early-access/requests/:requestUuid
Response includes full details with less masking for admin use.
Approve Request
POST /api/admin/early-access/requests/:requestUuid/approve
Request body:
{
"notes": "Approved for beta testing",
"temporary_password": "optional-custom-password"
}
Capacity Check: Fails if capacity limit reached.
Response:
{
"success": true,
"message": "Request approved successfully",
"item": { /* updated request */ }
}
Reject Request
POST /api/admin/early-access/requests/:requestUuid/reject
Request body:
{
"reason": "Does not meet criteria",
"notes": "Optional additional notes"
}
Response:
{
"success": true,
"message": "Request rejected successfully",
"item": { /* updated request */ }
}
Send Temporary Password
POST /api/admin/early-access/requests/:requestUuid/send-temporary-password
Generates a new temporary password for an approved request.
Response:
{
"success": true,
"temporary_password": "ABC123xyz!@#",
"email": "jo***@example.com"
}
Get Audit Logs
GET /api/admin/early-access/requests/:requestUuid/audit-logs
Returns all audit logs for a specific request.
Response:
{
"items": [
{
"uuid": "log-uuid",
"action": "approved",
"actor_uuid": "admin-uuid",
"actor_email": "ad***@admin.com",
"metadata": {
"notes": "Approved for beta testing"
},
"created_at": "2024-01-15T11:00:00Z"
}
]
}
Get Settings
GET /api/admin/early-access/settings
Returns current early access settings and statistics.
Response:
{
"settings": {
"capacity": 100,
"approved_count": 45,
"pending_count": 12,
"available_slots": 55,
"accepting_requests": true,
"feature_flag_enabled": true
}
}
Update Capacity
PUT /api/admin/early-access/settings/capacity
Request body:
{
"capacity": 200
}
Updates the target_users value in the feature flag.
Response:
{
"success": true,
"capacity": 200,
"updated_at": "2024-01-15T12:00:00Z"
}
Toggle Feature Flag
PUT /api/admin/early-access/settings/toggle
Request body:
{
"enabled": false
}
Enables or disables early access registration globally.
Response:
{
"success": true,
"enabled": false,
"updated_at": "2024-01-15T12:00:00Z"
}
Request Lifecycle
┌─────────┐
│ pending │ ─┐
└─────────┘ │
│ approve
├──────────> ┌──────────┐
│ │ approved │
│ └──────────┘
│ │
│ │ user creates account
│ v
│ ┌───────────┐
│ │ converted │
│ └───────────┘
│
│ reject
└──────────> ┌──────────┐
│ rejected │
└──────────┘
Status Descriptions:
- pending - Awaiting admin review
- approved - Approved by admin, temporary password sent
- converted - User successfully created account
- rejected - Rejected by admin with reason
- expired - Approval expired (not yet implemented)
Audit Actions
All administrative actions are logged:
- approved - Request approved
- rejected - Request rejected
- resent_password - Temporary password regenerated
- capacity_changed - Capacity limit updated
- flag_toggled - Feature flag enabled/disabled
Security & Privacy
Email Masking
All email addresses are masked in responses:
- john.doe@example.com → jo***@example.com
- Shows first 2 characters (or 1 if short) + *** + domain
Minimal User Info
Only essential fields are exposed:
- No internal IDs exposed (only UUIDs)
- No sensitive metadata in list views
- Full details only in detail endpoints
Role-Based Access
- viewer: Can view requests and settings (read-only)
- full_admin: Can approve, reject, update capacity, toggle flag
Frontend Implementation
Page Structure
EarlyAccessPage (early_access_page.dart)
- Main page with request list
- Search and filter controls
- Settings card showing capacity and stats
- Pagination controls
EarlyAccessRequestDetailPage (separate route)
- Full request details
- Action buttons (approve/reject)
- Audit log timeline
- Temporary password management
State Management
Uses Riverpod providers:
- earlyAccessListProvider - Fetches paginated requests
- earlyAccessSettingsProvider - Fetches settings/stats
- earlyAccessManagementProvider - Handles actions (approve/reject/update)
- Filter providers for search and status
UI Components
Built with Forui:
- FCard - Request cards and settings card
- FButton - Action buttons
- FSelect - Status filter dropdown
- FTextField - Search input
- FCircularProgress - Loading indicators
Usage Examples
Approve a Request
curl -X POST http://localhost:8081/api/admin/early-access/requests/req-uuid/approve \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"notes": "Approved for beta testing",
"temporary_password": "Welcome123!"
}'
Update Capacity
curl -X PUT http://localhost:8081/api/admin/early-access/settings/capacity \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"capacity": 200}'
Disable Early Access Registration
curl -X PUT http://localhost:8081/api/admin/early-access/settings/toggle \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"enabled": false}'
Search Requests
curl "http://localhost:8081/api/admin/early-access/requests?search=john&status=pending" \
-H "Authorization: Bearer $TOKEN"
Best Practices
Capacity Planning
- Set Realistic Limits: Start with a conservative capacity
- Monitor Closely: Watch approved_count vs capacity
- Adjust as Needed: Increase capacity based on system performance
- Communicate: Inform users when capacity is reached
Request Review
- Review Promptly: Don't leave requests pending too long
- Provide Reasons: Always include rejection reasons
- Add Notes: Document why requests were approved/rejected
- Track Patterns: Use audit logs to identify trends
Feature Flag Management
- Coordinate Releases: Disable flag during maintenance
- Test Thoroughly: Verify flag behavior before enabling
- Monitor Impact: Watch for issues after toggling
- Document Changes: Log why flag was toggled
Troubleshooting
Capacity Limit Reached
Symptom: Approval requests fail with "Capacity limit reached"
Solution:
- Check current capacity: GET /api/admin/early-access/settings
- Increase capacity: PUT /api/admin/early-access/settings/capacity
- Or reject pending requests to free slots
Feature Flag Not Working
Symptom: Registration still accepts/rejects requests despite flag state
Solution:
- Verify flag state: GET /api/admin/feature-flags/preview_registration_enabled
- Check backend logs for errors
- Ensure database connection is healthy
Audit Logs Missing
Symptom: No audit logs appear for actions
Solution:
- Check database table: SELECT * FROM early_access_audit_logs
- Verify admin principal is correctly extracted from token
- Check error logs for audit log insertion failures
Future Enhancements
- Email Notifications: Automatic emails on approval/rejection
- Expiration: Auto-expire approved requests after N days
- Bulk Actions: Approve/reject multiple requests at once
- Analytics: Dashboard with request trends and conversion rates
- Waitlist: Queue system when capacity is reached
- OTP Confirmation: Require OTP for sensitive admin actions
Next Steps
- Read Admin Backend Overview for server architecture
- Read Admin API Reference for complete admin endpoints
- Read Keycloak Authentication for admin auth system
- Read User Management for users, orgs, and tiers