Modules, add-ons, and authorization
Tenants license capabilities independently. Nanaade computes effective feature codes from the tenant's bundle and approved overrides, then applies membership permissions on top.
Product names and stable codes
Tenant administrators see plain-language product names, the corresponding dashboard label, route information, audience, dependencies, and the internal feature code. For example:
| Dashboard/product name | Stable feature code |
|---|---|
| View Jobs | job-board |
| Check Resume Match | job-board.resume-scoring |
| Manka Career Copilot | jobseeker-copilot |
| Job Opportunities in Copilot | jobseeker-copilot.job-discovery |
| Improve My Resume | jobseeker-copilot.resume-coaching |
| Interview Resources | interview-resources |
Human-readable names may improve over time; feature and launch codes are the integration contract. Store and compare the documented codes rather than copying dashboard labels into authorization logic.
Shared jobseeker dashboard
/dashboard is Nanaade's shared jobseeker workspace. It serves regular retail users with the user role and university-affiliated users with the student role.
Retail jobseekers continue to use Nanaade plan and credit rules. Tenant jobseekers use their organization's entitlements and usage limits. A successful tenant SSO session does not convert this route into a student-only dashboard.
/dashboard
├── Retail user → personal plan and retail credits
└── Tenant member → tenant modules, add-ons, and usage policy
The tenant-facing catalog uses the jobseeker audience for shared capabilities. University-specific functions, such as curriculum mapping, still require university membership and academic context.
Job board dependency example
The base job-board module grants job discovery, details, and saved jobs. Applications and AI operations are licensed separately:
job-board
├── job-board.resume-scoring
│ └── requires resume-builder
├── job-board.applications
│ ├── requires resume-builder
│ └── requires job-board.resume-scoring
├── job-board.upskill-recommendations
│ └── requires job-board.resume-scoring
└── job-board.mock-interview
└── external provider: Micro1
An unlicensed recommendations add-on does more than hide the “Other Recommendations” panel. Nanaade instructs the AI service not to generate course materials, removes them from the stored response, and avoids that additional provider work.
Licensed does not always mean ready
An entitlement answers whether a tenant may use a capability. A prerequisite answers whether this user has supplied enough data to use it well. Nanaade checks both on the server.
For example, licensing job-board.resume-scoring does not make an empty user profile analyzable. The first attempt returns RESUME_REQUIRED; Nanaade then offers the user an in-place PDF upload or its resume builder and retries the analysis after processing.
| User action | Required license | Required Nanaade data | Stable response when missing |
|---|---|---|---|
| Browse jobs and open details | job-board | Authenticated tenant member | — |
| Check resume match | job-board.resume-scoring | Parsed or built resume | RESUME_REQUIRED |
| Apply to a job | job-board.applications | Resume and completed match analysis | RESUME_REQUIRED or JOB_ANALYSIS_REQUIRED |
| View upskill recommendations | job-board.upskill-recommendations | Completed match analysis | JOB_ANALYSIS_REQUIRED |
| Use Copilot resume coaching | jobseeker-copilot.resume-coaching | Parsed or built resume | RESUME_REQUIRED |
| Optimize a resume section | resume-builder.ai-optimisation | Parsed or built resume | RESUME_REQUIRED |
| Generate student career roles | career-pathway | Field of study and current academic year | ACADEMIC_PROFILE_REQUIRED |
| Continue a career roadmap | career-pathway | Generated roles, skill ratings, and career profile | CAREER_PROFILE_REQUIRED |
| Run a job mock interview | job-board.mock-interview | Valid Nanaade job; skills come from the job and/or user profile | JOB_NOT_FOUND when the job is unavailable |
| Run a skills-based mock interview | Interview Resources mock-interview add-on | At least one selected skill in the request | INTERVIEW_SKILLS_REQUIRED |
These prerequisites are derived from Nanaade's own records. Do not place resumes, career profiles, or entitlement claims inside an SSO assertion. The tenant portal supplies identity and a launch code; Nanaade loads the user record, checks the server-side grant, and then checks the data needed by that controller.
Tenant SSO succeeds
→ Nanaade resolves the licensed launch
→ Controller loads the Nanaade user record
→ Required data is present: perform the operation
→ Required data is missing: return 422 + stable code + safe action
For just-in-time users, an initially sparse Nanaade record is expected. Design the first-use experience to collect only the information required by the selected module.
Jobseeker Copilot
jobseeker-copilot is the current module code. Older student-copilot grants are normalized for compatibility.
jobseeker-copilot.job-discoveryrequires Job Board.jobseeker-copilot.resume-coachingrequires Resume Builder.jobseeker-copilot.interview-preparationrequires Interview Resources.- Voice interviewing and action hooks remain independently controlled.
Interview Resources is also an independent module. Its preparation content, AI preparation, mock interviewing, and reports can be licensed separately.
Feature types
| Type | Example | Behavior |
|---|---|---|
| Shell | portal.notifications | Controls shared portal interface. |
| Module | resume-builder | Grants a primary product area. |
| Add-on | career-pathway.skill-gap-analysis | Grants an optional capability beneath its parent. |
Every add-on requires its parent module. Other dependencies can require all or any of several features. Disabled or preview-only catalog entries cannot be granted through normal administration.
Example university grant
[
"portal.dashboard",
"cohort-management",
"cohort-management.csv-import",
"institution-analytics",
"resume-builder",
"career-pathway",
"career-pathway.skill-gap-analysis",
"learning-resources"
]
Granting career-pathway.skill-gap-analysis without career-pathway is invalid. institution-analytics also depends on cohort data and therefore requires cohort-management.
Four enforcement layers
- Sidebar links and dashboard cards are omitted.
- Direct frontend route access renders a branded Feature Unavailable page.
- Buttons, tabs, and expensive operations check the specific add-on.
- Backend routes/services reject unauthorized operations.
Client-side hiding is a usability feature, never the security boundary. A user who manually constructs a URL or HTTP request must get the same decision from the backend.
API denial
HTTP/1.1 403 Forbidden
Content-Type: application/json
{
"success": false,
"code": "FEATURE_NOT_LICENSED",
"feature": "career-pathway.skill-gap-analysis"
}
Your external portal should not attempt to duplicate Nanaade's dependency graph. Treat Nanaade as authoritative and show only launch-level messaging such as “Career workspace available.” Nanaade renders the precise licensed navigation after entry.
Licensed navigation profiles
Tenant entitlements remain the authorization source of truth. Nanaade administrators may additionally hide a licensed navigation item or display an unlicensed item as a disabled upgrade prompt.
Licensed + visible → clickable navigation
Licensed + hidden → omitted from navigation; API remains licensed
Unlicensed + upgrade → disabled “Upgrade” item
Unlicensed + default → omitted
Navigation configuration never grants access. Direct routes and APIs continue to enforce the feature catalog even when an upgrade prompt is visible.
The shared jobseeker shell applies this policy consistently to desktop and mobile sidebars, specialized module sidebars, header links, notification controls, billing visibility, and floating Copilot tools. Nanaade waits for tenant configuration before mounting the shell, so unlicensed retail navigation is not briefly exposed while configuration loads.
Advanced Job Board filters are an action-level example. Without job-board.advanced-filters, Nanaade omits salary, experience, employment-type, and remote filters. Sending those query parameters manually still returns FEATURE_NOT_LICENSED from the backend.
Metered modules and limits
Features backed by Gemini, Micro1, voice AI, email, or calendar providers may have tenant and per-member limits. Licensed tenant calls bypass retail credits but create tenant-scoped usage records.
- Tenant limits reset at the beginning of each calendar month.
- Member limits may be hourly and/or daily.
- An 80% tenant threshold returns
X-Tenant-Usage-Warning. - A reached limit returns a stable
429error. - Unmetered reads and unrelated modules remain available when one meter is exhausted.
Changes during a session
Administrators can grant or revoke modules without deploying the tenant portal. Nanaade increments configVersion, invalidates cached tenant configuration, and applies the new result on subsequent protected requests. Design users' workflows so a mid-session revocation produces a clear unavailable response rather than losing entered data silently.