Feature Owner: scorevi (Sean Patrick Caintic)
Module: Dashboards
Priority: P0
Sprint #12: Fully Implemented & Deployed
Date: 2026-06-29
EXECUTIVE SUMMARY
What is this feature?
Agency-level administration dashboard for managing team members, token limits, branding, and reviewing analytics. Protected by authenticateAgencyMember() in app/agency/layout.tsx. Agency layout renders AgencyLayoutClient.tsx with UnifiedSidebar(userRole="agency"). Owner vs member split: only agency owners (verified via agencies.owner_clerk_id — TEXT, Clerk string ID) can manage team, set token limits, and update branding. The ADMIN agency member role was deprecated June 2026 (migration 202606050001 removed ADMIN, added previous_platform_role VARCHAR(50)). Agency member roles: CHECK (IN ('CREATOR','REVIEWER')).
Why does it matter?
Agencies are the B2B unit. Agency admins need to manage their team, control token costs per member, and configure their own branding (logo, SMTP). Without this, every agency action requires a platform admin.
What's the MVP scope?
Fully deployed. Team management (invite, remove, edit roles). Token limit per member. Agency branding (SMTP, logo, themes). Member usage tracking. Owner/member split enforced server-side. AgencyStatusContext with 1-min in-memory cache.
1. USER PAIN POINT & SOLUTION
Current State (Without Feature)
Agencies have no self-service. They must email platform admins to add team members, set limits, or change branding.
Pain Point
Emotional: "I run a training agency but I can't even add my own team members."
Functional: No agency-level administration.
Business Impact: Support burden on platform admins; agencies feel limited.
Future State (With Feature)
Agency owner logs in → sees their agency dashboard → invites team members → sets per-member token limits → configures branding. Fully self-service.
Marketing Hook
"Your agency, your rules. Manage your team, control your costs, own your branding."
2. 4D FRAMEWORK MAPPING
Diagnose
Agency status endpoint (GET /api/agency/status) returns { isMember, isOwner, platformRole, effectiveRole, isViewingAsOther, agency?, membership? } for dashboard orchestration.
Design
Not directly applicable.
Develop
Token limit controls per member shape content production budgets.
Deliver
Reviewer analytics visible on agency dashboard.
3. USER FLOWS
Entry Point
Agency owner/member signs in → auto-routed to /agency. Layout guard authenticateAgencyMember() verifies membership.
Success Criteria
Owner manages team/tokens/branding. Member sees personal usage and team directory.
Main Flow (Happy Path)
Owner — Team Management:
Owner navigates to agency team page
Clicks "Invite Member" →
InviteModal.tsxopens8-rule invitation validation in
lib/agency/member-invitation.service.ts:No self-invite, cannot invite platform ADMINS, cannot invite AGENCY owners, cannot invite LEARNERs
Role compatibility check, single-agency constraint, active-only check, owner-only for admin-level invites
Invite sent via
POST /api/agency/team/invite/Member accepts → status becomes ACTIVE
Owner — Token Limits:
Owner navigates to agency admin
Sees per-member token usage (enriched via
GET /api/agency/admin/members)Adjusts member limit →
PATCH /api/agency/admin/members/[memberId]/token-limit
Owner — Branding:
PUT/GET /api/agency/branding,POST/DELETE /api/agency/branding/logo,POST /api/agency/branding/smtp-test— all owner-only
Member — Personal:
GET /api/agency/member/usage— personal token consumptionGET /api/agency/member/team— team directory
Edge Cases
No data: No members → "Invite your first team member" prompt.
API error: Invite fails → error toast with reason (e.g., user already in another agency).
Permission denied: Member accessing owner-only pages → redirected.
4. INFORMATION ARCHITECTURE
Primary Information (Always visible)
Dashboard: Members, token budget, top usage, review analytics.
Team: Member list with roles and statuses.
Status: Agency membership context via
AgencyStatusContext(1-min cache).
Secondary Information
Token usage per member.
Agency branding preview.
AgencyLegacyWarning.tsx— warning for AGENCY-role users without an agency.
Actions
Primary CTA (Owner): "Invite Member", "Save Limits", "Update Branding".
Secondary Actions: "Remove Member", "Edit Role", "Resend Invite" (POST /api/agency/team/invite/resend/).
5. WIREFRAMES
Excluded — UI is fully developed (AgencyLayoutClient.tsx + sub-pages, InviteModal.tsx, AgencyBanners.tsx, AgencyLegacyWarning.tsx).
6. WIREFLOWS
Excluded.
7. PROTOTYPE
Excluded — production deployed.
8. BACKEND SCHEMA
Database Tables
agencies: id UUID PK, owner_clerk_id TEXT NOT NULL -- Clerk string ID name, plan, monthly_token_budget, status agency_members: id UUID PK, agency_id FK→agencies user_clerk_id TEXT -- Clerk string ID role TEXT CHECK (role IN ('CREATOR','REVIEWER')) -- ADMIN deprecated Jun 2026 status TEXT CHECK (status IN ('PENDING','ACTIVE','REVOKED')) monthly_token_limit INTEGER previous_platform_role VARCHAR(50) -- For rollback tracking (migration 202606050001)
Invitation Validation (8-Rule Chain)
Located in lib/agency/member-invitation.service.ts:
No self-invite
Cannot invite platform ADMINS
Cannot invite AGENCY owners
Cannot invite LEARNERs
Role compatibility check
Single-agency constraint (user must not be in another agency)
Active-only (cannot invite suspended users)
Owner-only for admin-level invites
9. API ENDPOINTS
Status & Team
GET /api/agency/status (returns: isMember, isOwner, platformRole, effectiveRole, isViewingAsOther, agency?, membership?)GET /api/agency/team/list/ (agency admin — note: NOT team-directory)POST /api/agency/team/invite/ (agency admin)POST /api/agency/team/invite/resend/ (agency admin)PATCH /api/agency/team/members/[memberId]/ (edit role)DELETE /api/agency/team/members/[memberId]/ (remove member)POST /api/agency/team/claim/ (auto-claim pending invite)GET /api/agency/team/eligible-users/ (agency admin)GET /api/agency/team/lookup/ (agency admin)
Member Usage
GET /api/agency/member/usage (personal token consumption)GET /api/agency/member/team-directory (agency member)
Admin (Owner Only)
GET /api/agency/admin/members (enriched with token usage)PATCH /api/agency/admin/members/[memberId]/token-limit (owner only)
Branding (Owner Only)
GET /api/agency/branding (owner)PUT /api/agency/branding (owner)POST /api/agency/branding/logo (owner)DELETE /api/agency/branding/logo (owner)POST /api/agency/branding/smtp-test (owner)
Self-Service
POST /api/agency/create (self-service agency creation)GET /api/agency/list (PUBLIC)
10. DATA REQUIREMENTS
Frontend Needs
AgencyStatusContextprovides agency membership status with 1-min in-memory cache.Team member list with roles, statuses, and token usage.
Token limit sliders for per-member adjustments.
Caching Strategy
AgencyStatusContextcaches for 1 minute (in-memory).
11. PERFORMANCE CONSIDERATIONS
Database Optimization
Index on
agency_members.user_clerk_idfor lookup.Index on
agency_members.agency_idfor member lists.
Who can access this feature?
Agency owners: full access (verified via
agencies.owner_clerk_idTEXT field).Agency members (CREATOR/REVIEWER): limited access (personal usage, team directory).
Non-members: redirected.
authenticateAgencyMember() for layout guard. Owner verification for sensitive routes via owner_clerk_id comparison.
13. ERROR HANDLING
Error | How Handled |
|---|---|
Non-member accessing | Redirected to actual role dashboard |
Invite validation failure | Error toast with specific rule violated |
User already in another agency | Blocked (single-agency constraint) |
Owner-only access by member | Permission denied |
14. TESTING CHECKLIST
Happy Path
□ Owner invites member → member claims → active
□ Owner sets token limit → member sees cap
□ Member views personal usage dashboard
□ Owner uploads/removes logo
Edge Cases
□ Non-member accessing /agency → redirected
□ Inviting user already in another agency → blocked
□ Revoking invite → status becomes REVOKED
□ AgencyStatusContext cache invalidation after 1 min
15. OPEN QUESTIONS
The
AgencyLegacyWarningcomponent for AGENCY-role users without an agency is a stopgap — should we remove the AGENCY platform role entirely?ADMIN agency member role fully deprecated June 2026 — any remaining rows with ADMIN role should be migrated.
16. OUT OF SCOPE (v1.1+)
Multi-agency membership.
Agency sub-admins with limited permissions.
Agency billing/invoicing.
17. SUCCESS METRICS
Agency owners manage team without platform admin intervention.
Token limit enforcement prevents cost overruns.
18. DEPENDENCIES
This feature depends on:
[0.1] Secure Login + [6.1.1] RBAC.
[10.1] Gemini Configuration — token tracking feeds agency budgets.
[5.1] Super Admin View — admin can also manage agencies.
These features depend on this:
Agency-level reviewer analytics.
Token enforcement (3-tier: sitewide → agency → member).
19. TIMELINE & OWNERSHIP
Sprint #12: Already deployed.
Backend: scorevi
Frontend: scorevi
Estimated Completion: Complete.
Document Version
1.0 - Initial version - 2026-06-29 08:20 UTC
1.1 - Added Document Version section and update author to have full name - 2026-06-29 08:46 UTC