Permissions Matrix
This table is not edited by hand. It is regenerated on every build by
apps/docs/scripts/generate-permissions-matrix.ts, which walks
apps/api/src/**/*.controller.ts with ts-morph and extracts each method’s
HTTP verb, path, @Roles(...), and @Public() posture directly from the
source. If a controller method declares no access posture at all, the build
fails — see Drift control.
- Method / Path — the HTTP verb and the live route, with the API’s global
/v1prefix already applied (perapps/api/src/main.ts). Thehealthroute is intentionally exempt from the prefix. - Module — the directory under
apps/api/src/the controller lives in. - Required roles — the literal arguments to
@Roles(...). Empty for public routes. - Public? —
Yesif the method or its containing controller is marked@Public(), or if the class name matches*Public*Controller. - Used by — the
apps/*workspaces whose source contains a literal URL targeting the endpoint. Static scan only — call sites that build URLs through a helper function (buildUrl(resource, id)) are invisible, so a blank cell means either the endpoint is genuinely unused or its callers compose the URL dynamically. An endpoint marked role-restricted to one audience but showing the other app as a caller is a drift signal worth investigating. - Source — a deep link to the controller method on GitHub.
- Reference in a prompt — click the clipboard button to copy a single self-contained sentence identifying the endpoint (verb, path, source file:line, controller and handler, access posture, and known callers). Paste it at the top of a prompt to an AI coding agent so it has every field from the row without context-switching.
88 routes detected — generated at build time
from apps/api/src/**/*.controller.ts. This page cannot drift
from the live API.
| Method | Path | Module | Required roles | Public? | Used by | Source | Reference in a prompt |
|---|---|---|---|---|---|---|---|
GET | /v1/applications | applications | membercompany-admincompany-memberteros-ops | No | opspool | ApplicationsController.findAll | |
POST | /v1/applications | applications | memberteros-ops | No | opspool | ApplicationsController.create | |
GET | /v1/applications/:id | applications | membercompany-admincompany-memberteros-ops | No | ops | ApplicationsController.findOne | |
GET | /v1/applications/:id/job-posting | applications | membercompany-admincompany-memberteros-ops | No | pool | ApplicationsController.findJobPostingForApplication | |
POST | /v1/applications/:id/offer/accept | applications | company-admincompany-memberteros-ops | No | ops | ApplicationsController.acceptOffer | |
POST | /v1/applications/:id/stage-events | applications | company-admincompany-memberteros-ops | No | ops | ApplicationsController.createStageEvent | |
PATCH | /v1/applications/:id/withdraw | applications | memberteros-ops | No | pool | ApplicationsController.withdraw | |
GET | /v1/audit-logs | audit | teros-ops-admin | No | ops | AuditLogController.findAll | |
GET | /v1/audit-logs/actors | audit | teros-ops-admin | No | ops | AuditLogController.findActors | |
GET | /v1/candidate-profiles | candidate-profiles | teros-opsteros-ops-admin | No | ops | CandidateProfilesController.findAll | |
POST | /v1/candidate-profiles | candidate-profiles | member | No | opspool | CandidateProfilesController.createOwn | |
GET | /v1/candidate-profiles/admin/failed-resume-conversions | candidate-profiles | teros-ops-admin | No | ops | CandidateProfilesController.listFailedResumeConversionsForAdmin | |
GET | /v1/candidate-profiles/admin/legacy-file-migration | candidate-profiles | teros-ops-admin | No | ops | CandidateProfilesController.getLegacyFileMigrationStatus | |
POST | /v1/candidate-profiles/admin/legacy-file-migration/run-next-batch | candidate-profiles | teros-ops-admin | No | ops | CandidateProfilesController.runLegacyFileMigrationBatch | |
GET | /v1/candidate-profiles/by-sub/:workosUserSub | candidate-profiles | company-admincompany-memberteros-opsteros-ops-admin | No | ops | CandidateProfilesController.findBySub | |
PATCH | /v1/candidate-profiles/by-sub/:workosUserSub | candidate-profiles | teros-opsteros-ops-admin | No | ops | CandidateProfilesController.updateBySub | |
POST | /v1/candidate-profiles/by-sub/:workosUserSub/approve | candidate-profiles | teros-opsteros-ops-admin | No | ops | CandidateProfilesController.approveBySub | |
POST | /v1/candidate-profiles/by-sub/:workosUserSub/ignore | candidate-profiles | teros-opsteros-ops-admin | No | ops | CandidateProfilesController.ignoreBySub | |
DELETE | /v1/candidate-profiles/by-sub/:workosUserSub/invitation | candidate-profiles | teros-opsteros-ops-admin | No | ops | CandidateProfilesController.revokeInvitation | |
GET | /v1/candidate-profiles/by-sub/:workosUserSub/invitation | candidate-profiles | teros-opsteros-ops-admin | No | ops | CandidateProfilesController.findActiveInvitation | |
POST | /v1/candidate-profiles/by-sub/:workosUserSub/invitation | candidate-profiles | teros-opsteros-ops-admin | No | ops | CandidateProfilesController.createInvitation | |
GET | /v1/candidate-profiles/by-sub/:workosUserSub/notes | candidate-profiles | company-admincompany-memberteros-opsteros-ops-admin | No | ops | CandidateProfilesController.findNotesBySub | |
POST | /v1/candidate-profiles/by-sub/:workosUserSub/notes | candidate-profiles | teros-opsteros-ops-admin | No | ops | CandidateProfilesController.createNoteBySub | |
PATCH | /v1/candidate-profiles/by-sub/:workosUserSub/notes/:noteId | candidate-profiles | teros-opsteros-ops-admin | No | ops | CandidateProfilesController.updateNoteBySub | |
PATCH | /v1/candidate-profiles/by-sub/:workosUserSub/owner | candidate-profiles | teros-ops-admin | No | ops | CandidateProfilesController.reassignOwnerBySub | |
DELETE | /v1/candidate-profiles/by-sub/:workosUserSub/profile-picture | candidate-profiles | teros-opsteros-ops-admin | No | ops | CandidateProfilesController.deleteProfilePictureBySub | |
GET | /v1/candidate-profiles/by-sub/:workosUserSub/profile-picture | candidate-profiles | company-admincompany-memberteros-opsteros-ops-admin | No | ops | CandidateProfilesController.findProfilePictureBySub | |
POST | /v1/candidate-profiles/by-sub/:workosUserSub/profile-picture | candidate-profiles | teros-opsteros-ops-admin | No | ops | CandidateProfilesController.updateProfilePictureBySub | |
DELETE | /v1/candidate-profiles/by-sub/:workosUserSub/public-resume-link | candidate-profiles | teros-opsteros-ops-admin | No | ops | CandidateProfilesController.voidPublicResumeLink | |
GET | /v1/candidate-profiles/by-sub/:workosUserSub/public-resume-link | candidate-profiles | teros-opsteros-ops-admin | No | ops | CandidateProfilesController.findActivePublicResumeLink | |
POST | /v1/candidate-profiles/by-sub/:workosUserSub/public-resume-link | candidate-profiles | teros-opsteros-ops-admin | No | ops | CandidateProfilesController.createPublicResumeLink | |
POST | /v1/candidate-profiles/by-sub/:workosUserSub/recover | candidate-profiles | teros-opsteros-ops-admin | No | ops | CandidateProfilesController.recoverBySub | |
GET | /v1/candidate-profiles/by-sub/:workosUserSub/resume | candidate-profiles | company-admincompany-memberteros-opsteros-ops-admin | No | ops | CandidateProfilesController.findResumeBySub | |
POST | /v1/candidate-profiles/by-sub/:workosUserSub/resume | candidate-profiles | teros-opsteros-ops-admin | No | ops | CandidateProfilesController.updateResumeBySub | |
POST | /v1/candidate-profiles/by-sub/:workosUserSub/resume-conversion/retry | candidate-profiles | teros-ops-admin | No | ops | CandidateProfilesController.retryResumeConversionBySub | |
GET | /v1/candidate-profiles/by-sub/:workosUserSub/resume-markdown | candidate-profiles | teros-opsteros-ops-admin | No | ops | CandidateProfilesController.findResumeMarkdownBySub | |
PATCH | /v1/candidate-profiles/by-sub/:workosUserSub/resume-markdown | candidate-profiles | teros-opsteros-ops-admin | No | ops | CandidateProfilesController.updateResumeMarkdownBySub | |
GET | /v1/candidate-profiles/by-sub/:workosUserSub/resume-profile-suggestions | candidate-profiles | teros-opsteros-ops-admin | No | ops | CandidateProfilesController.findResumeProfileSuggestionsBySub | |
POST | /v1/candidate-profiles/by-sub/:workosUserSub/unapprove | candidate-profiles | teros-opsteros-ops-admin | No | ops | CandidateProfilesController.unapproveBySub | |
POST | /v1/candidate-profiles/manual | candidate-profiles | teros-opsteros-ops-admin | No | ops | CandidateProfilesController.createManual | |
GET | /v1/candidate-profiles/me | candidate-profiles | member | No | pool | CandidateProfilesController.findOwn | |
PATCH | /v1/candidate-profiles/me | candidate-profiles | member | No | pool | CandidateProfilesController.updateOwn | |
POST | /v1/candidate-profiles/me/onboarding | candidate-profiles | member | No | pool | CandidateProfilesController.saveOnboardingStep1 | |
POST | /v1/candidate-profiles/me/onboarding/complete | candidate-profiles | member | No | pool | CandidateProfilesController.completeOnboardingFinal | |
DELETE | /v1/candidate-profiles/me/profile-picture | candidate-profiles | member | No | pool | CandidateProfilesController.deleteOwnProfilePicture | |
GET | /v1/candidate-profiles/me/profile-picture | candidate-profiles | member | No | pool | CandidateProfilesController.findOwnProfilePicture | |
POST | /v1/candidate-profiles/me/profile-picture | candidate-profiles | member | No | pool | CandidateProfilesController.updateOwnProfilePicture | |
GET | /v1/candidate-profiles/me/resume | candidate-profiles | member | No | pool | CandidateProfilesController.findOwnResume | |
POST | /v1/candidate-profiles/me/resume | candidate-profiles | member | No | pool | CandidateProfilesController.updateOwnResume | |
GET | /v1/candidate-profiles/me/resume-markdown | candidate-profiles | member | No | pool | CandidateProfilesController.findOwnResumeMarkdown | |
GET | /v1/candidate-profiles/me/resume-profile-suggestions | candidate-profiles | member | No | pool | CandidateProfilesController.findOwnResumeProfileSuggestions | |
GET | /v1/candidate-profiles/me/status | candidate-profiles | member | No | pool | CandidateProfilesController.findOwnStatus | |
POST | /v1/candidate-profiles/resume-prefill | candidate-profiles | teros-opsteros-ops-admin | No | ops | CandidateProfilesController.prefillFromResume | |
GET | /v1/public/invitation/:token | candidate-profiles | anonymous | Yes | pool | PublicInvitationController.validateInvitation | |
POST | /v1/public/invitation/:token/redeem | candidate-profiles | anonymous | Yes | pool | PublicInvitationController.redeemInvitation | |
GET | /v1/public/resume/:token | candidate-profiles | anonymous | Yes | ops | PublicResumeController.getPublicResume | |
GET | /v1/public/resume/:token/profile-picture | candidate-profiles | anonymous | Yes | ops | PublicResumeController.getPublicResumeProfilePicture | |
GET | /health | health | anonymous | Yes | debug | HealthController.check | |
GET | /v1/job-posting-requests | job-posting-requests | teros-opscompany-admin | No | ops | JobPostingRequestsController.list | |
POST | /v1/job-posting-requests | job-posting-requests | teros-opscompany-admin | No | ops | JobPostingRequestsController.create | |
POST | /v1/job-posting-requests/:id/disable | job-posting-requests | teros-opscompany-admin | No | ops | JobPostingRequestsController.disable | |
GET | /v1/public/job-posting-requests/:token | job-posting-requests | anonymous | Yes | ops | PublicJobPostingRequestsController.get | |
PATCH | /v1/public/job-posting-requests/:token | job-posting-requests | anonymous | Yes | ops | PublicJobPostingRequestsController.update | |
POST | /v1/public/job-posting-requests/:token/draft | job-posting-requests | anonymous | Yes | ops | PublicJobPostingRequestsController.draft | |
POST | /v1/public/job-posting-requests/:token/submit | job-posting-requests | anonymous | Yes | ops | PublicJobPostingRequestsController.submit | |
GET | /v1/job-postings | job-postings | membercompany-admincompany-memberteros-ops | No | opspool | JobPostingsController.findAll | |
POST | /v1/job-postings | job-postings | company-adminteros-ops | No | ops | JobPostingsController.create | |
GET | /v1/job-postings/:id | job-postings | membercompany-admincompany-memberteros-ops | No | ops | JobPostingsController.findOne | |
PATCH | /v1/job-postings/:id | job-postings | company-adminteros-ops | No | ops | JobPostingsController.update | |
POST | /v1/job-postings/:id/close | job-postings | company-adminteros-ops | No | ops | JobPostingsController.close | |
DELETE | /v1/job-postings/:id/public-link | job-postings | company-adminteros-ops | No | ops | JobPostingsController.voidPublicLink | |
GET | /v1/job-postings/:id/public-link | job-postings | company-adminteros-ops | No | ops | JobPostingsController.findActivePublicLink | |
POST | /v1/job-postings/:id/public-link | job-postings | company-adminteros-ops | No | ops | JobPostingsController.createPublicLink | |
GET | /v1/public/job-postings/:token | job-postings | anonymous | Yes | ops | PublicJobPostingsController.getPublicJobPosting | |
GET | /v1/ops-dashboard/metrics | ops-dashboard | company-admincompany-memberteros-ops | No | ops | OpsDashboardController.metrics | |
GET | /v1/organizations | organizations | company-admincompany-memberteros-ops | No | ops | OrganizationsController.findAll | |
POST | /v1/organizations | organizations | teros-ops | No | ops | OrganizationsController.create | |
DELETE | /v1/organizations/:id | organizations | company-adminteros-ops | No | — | OrganizationsController.remove | |
GET | /v1/organizations/:id | organizations | company-admincompany-memberteros-ops | No | — | OrganizationsController.findOne | |
PATCH | /v1/organizations/:id | organizations | company-adminteros-ops | No | — | OrganizationsController.update | |
GET | /v1/organizations/:id/members | organizations | company-admincompany-memberteros-ops | No | ops | OrganizationsController.findMembers | |
POST | /v1/organizations/:id/sync | organizations | teros-ops | No | — | OrganizationsController.sync | |
POST | /v1/organizations/sync-all | organizations | teros-ops-admin | No | ops | OrganizationsController.bulkSync | |
GET | /v1/skills | skills | teros-ops-admin | No | ops | SkillsController.list | |
PATCH | /v1/skills/:id/parent | skills | teros-ops-admin | No | ops | SkillsController.setParent | |
POST | /v1/skills/approve | skills | teros-ops-admin | No | ops | SkillsController.approve | |
POST | /v1/skills/normalize | skills | teros-ops-admin | No | ops | SkillsController.normalize | |
POST | /v1/skills/reject | skills | teros-ops-admin | No | ops | SkillsController.reject |
How to read this in a PR
Section titled “How to read this in a PR”When a PR changes a controller decorator, this table changes on next build.
If a role moves from teros-ops-admin → teros-ops, the diff is visible in
the generated JSON (and therefore in the deployed site preview). Reviewers
should treat any unexplained roles change as a blocker until the author
articulates intent.