Crewing Roles and Permissions
Authoritative build spec: the same matrix appears in Crewing Implementation Spec § 6, alongside the codebase wiring. This page is the detailed rationale, aligned with that spec.
Crewing extends the existing lib/permissions.ts map (see
Roles and Permissions) with crewing permissions. Every
crewing Server Action calls requirePermission(role, permission) first; the
relevant state machine adds the status+role gate on top.
1. Role mapping
| Crewing actor | PPMS role | Notes |
|---|---|---|
| PM / APM / Site In-charge (the only on-site logins) | SITE_STAFF (new, proposed) |
apply-only leave (on behalf of crew), attendance, PPE issue, doc upload, view-only contract (except salary) & bank; requests relief cover (does not raise requisitions) |
| MPO | MANNING (existing — "crew-management staff") |
recruitment + verifies site data (docs/PPE/NoK), except bank/EPF (Accounts) and leave (Manager); no leave and no attendance access |
| Accounts | ACCOUNTS |
verifies bank + EPF; consumes wage report |
| Manager | MANAGER |
approves salary structures, candidate selection, interview waivers, leave, appraisals, wage reports; reviews attendance |
| Superuser | SUPERUSER |
combined authority across crewing actions |
| Auditor | AUDITOR |
read-only across crewing |
| Admin | ADMIN |
manages ranks & doc requirements |
| Candidate | none | public careers form only |
Proposed enum change: add
SITE_STAFFtoRole. If review prefers reuse,TECHNICALcould host site staff, but its PO semantics ("deck/engine crew") differ from PM/APM managerial duties — hence the new role.
Only PM, Assistant PM and Site In-charge get a login (a single
SITE_STAFFrole). No other on-vessel rank — Dredger in-charge, dredge/engine operators, deck hands, support staff, down to Mess Boy — has a portal account; they are crew members / data subjects whose leave, attendance, PPE and documents are entered for them by site staff. The on-vessel rank tree in Data Model § Rank is an org chart, not a list of users.
2. Permission → role matrix
✓ = granted. (SITE = SITE_STAFF, MAN = MANNING/MPO, ACC = ACCOUNTS,
MGR = MANAGER, SU = SUPERUSER, AUD = AUDITOR, ADM = ADMIN.)
| Permission | SITE | MAN | ACC | MGR | SU | AUD | ADM |
|---|---|---|---|---|---|---|---|
raise_requisition ⁵ |
✓ | ✓ | ✓ | ||||
request_relief_cover ⁵ |
✓ | ✓ | |||||
convert_relief_to_requisition |
✓ | ✓ | ✓ | ||||
cancel_requisition |
✓ | ✓ | ✓ | ||||
view_requisitions |
✓ | ✓ | ✓ | ✓ | ✓ | ||
manage_candidates (shortlist/vetting) |
✓ | ✓ | ✓ | ||||
record_reference_check |
✓ | ✓ | ✓ | ||||
record_interview_result |
✓ | ✓ | ✓ | ||||
request_interview_waiver ⁶ |
✓ | ✓ | |||||
approve_interview_waiver ⁶ |
✓ | ✓ | |||||
approve_salary_structure |
✓ | ✓ | |||||
select_candidate (final approval) |
✓ | ✓ | |||||
onboard_crew |
✓ | ✓ | ✓ | ||||
sign_off_crew |
✓ | ✓ | ✓ | ✓ | |||
view_crew_records |
✓¹ | ✓ | ✓² | ✓ | ✓ | ✓ | ✓ |
upload_crew_records (docs/NoK/emergency/EPF) |
✓ | ✓ | ✓ | ✓ | |||
issue_ppe |
✓ | ✓ | ✓ | ✓ | |||
apply_leave |
✓ | ✓ | ✓ | ||||
decide_leave ⁷ |
✓ | ✓ | |||||
record_attendance |
✓ | ✓ | |||||
view_attendance ³ |
✓ | ✓ | ✓ | ✓ | |||
verify_site_records (docs/PPE/NoK) |
✓ | ✓ | ✓ | ||||
verify_bank_epf |
✓ | ✓ | |||||
raise_appraisal |
✓ | ✓ | ✓ | ||||
verify_appraisal |
✓ | ✓ | ✓ | ||||
approve_appraisal |
✓ | ✓ | |||||
generate_wage_report ⁴ |
✓ | ✓ | |||||
approve_wage_report |
✓ | ✓ | |||||
view_wage_report |
✓ | ✓ | ✓ | ✓ | ✓ | ||
manage_ranks |
✓ | ✓ |
¹ Site staff get crew records for their own site only, with contract
view-only-except-salary and bank view-only.
² Accounts see bank/EPF and the wage report, not the full HR record.
³ Attendance is deliberately not visible to the MPO (or Accounts). Site staff
record it; the Manager reviews it (it feeds the wage report).
⁴ The wage report reads attendance, so it is generated by the Manager (or the
month-end job) — not the MPO, who has no attendance access.
⁵ Site staff do not raise requisitions. They flag a gap with
request_relief_cover; the office (MPO/Manager) reviews it and converts it into a
requisition.
⁶ Everyone is interviewed. For a returning ex-hand the MPO may
request_interview_waiver; only a Manager can approve_interview_waiver
(never automatic).
⁷ Leave is decided by the Manager, not the MPO. Site staff apply on behalf of
crew; the MPO has no role in leave.
3. Field-level restrictions (PII)
Enforced in Server Components/Actions on top of the permission map:
| Field | Visible to | Hidden from |
|---|---|---|
| Salary (contract letter, salary structure) | MPO, Manager, Accounts, Superuser, Auditor | Site staff |
| Full bank account number | Accounts (verify), Manager, Superuser | Site staff (view-only masked), MPO |
| Aadhaar / PAN number | MPO (verify), Accounts (EPF), Superuser | Site staff (masked) |
| Candidate rejection remarks | MPO, Manager, Superuser, Auditor | Candidate |
4. Business rules layered on top
- A candidate cannot be onboarded until the salary structure is Manager-approved and a contract letter is attached.
- Bank and EPF records can only be set
VERIFIEDby Accounts (UAN/Aadhaar EPFO check); everything else site staff enter is verified by MPO. - Attendance has no verification gate (operational record). It is recorded by site staff and visible only to site staff and the Manager — the MPO cannot see attendance; the Manager reviews it (it feeds the wage report).
- Leave is applied by the Site in-charge on behalf of crew (crew are not portal
users); the Manager decides (approves/rejects) leave — the MPO has no leave
role. An approved leave that clashes — overlaps another for the same rank
below its required strength — auto-raises a
LEAVE-reason requisition (system-raised, same backfill path as sign-off). - Site staff do not raise requisitions. A foreseen gap is flagged with
request_relief_cover; the office converts the relief request into a requisition. - Everyone is interviewed; an ex-hand interview is waived only with Manager
approval (
request_interview_waiverby MPO →approve_interview_waiverby Manager). - An appraisal must be
MPO_VERIFIEDbefore a Manager can approve it. - A wage report must be
MANAGER_APPROVEDbefore it isSENT_TO_ACCOUNTS. - Only one ACTIVE assignment per crew member; sign-off is required before a new one.
- Site staff actions are scoped to the site/vessel they are assigned to.
5. Implementation pattern
// app/(portal)/crewing/candidates/actions.ts
'use server'
export async function onboardCandidate(input: OnboardInput) {
const session = await auth()
requirePermission(session.user.role, 'onboard_crew') // role gate
const app = await db.application.findUniqueOrThrow(...)
assertCanTransition(app.stage, 'onboard') // pipeline gate
// ...create assignment + side-effects in a transaction,
// write a CrewAction, dispatch notifications
}
Same shape as every PO Server Action: permission → state-machine guard → transactional write → audit row → notify.
Pelagia Portal (PPMS)
Overview
Build & Run
System
Product
- Feature Catalogue
- Pages and Navigation
- Workflows
- Purchase Orders
- Vendors and GST Lookup
- Inventory and Catalogue
- Inventory on Approval
- Notifications
- File Storage
- Design System
Planned
Quality
Ops
Engineering
Pelagia Portal (PPMS) — internal purchase-order management. Self-hosted on pms1, live at pms.pelagiamarine.com. This wiki tracks the shipped product; authoritative sources are the repo code, App/CLAUDE.md, Docs/, and CHANGELOG.md.