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 managementearly_access_features_handler.dart— Feature flag endpointsearly_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-features
Get 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-schemas
Get 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
approvedorconvertedcount 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 numberpage_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 reviewapproved- Approved by admin, temporary password sentconverted- User successfully created accountrejected- Rejected by admin with reasonexpired- Approval expired (not yet implemented)
Audit Actions#
All administrative actions are logged:
approved- Request approvedrejected- Request rejectedresent_password- Temporary password regeneratedcapacity_changed- Capacity limit updatedflag_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 requestsearlyAccessSettingsProvider- Fetches settings/statsearlyAccessManagementProvider- Handles actions (approve/reject/update)- Filter providers for search and status
UI Components#
Built with Forui:
FCard- Request cards and settings cardFButton- Action buttonsFSelect- Status filter dropdownFTextField- Search inputFCircularProgress- 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