1. How permissions work
Two independent gates. To do something to a vessel's data a user needs both:
- A permission (this document): what they may do, e.g.
modules.maintenance.complete. Permissions are ticked on a role (Portal → Roles) and a user holds one or more roles. - Access to the vessel (Portal → Vessel Access, or a Fleet Group): where they may do it. A user with no vessel grant and no fleet group sees no vessel at all. Access is all-or-nothing per vessel - there are no per-vessel view/edit levels; an explicit
deniedentry blocks a vessel. Only the superadmin can grant vessel access.
Format. modules.<module>.<action>, e.g. modules.assets.edit. Standalone permissions have their own key (debug_terminal).
Rules the system applies
- Superadmin. The reserved
superadminrole bypasses every permission and every vessel check. No other role name ever gains access by its name (a role called "admin" is governed purely by its ticks). - Wildcards.
*grants everything (including modules added later);modules.<module>.*grants every action of one module. The "Full Access" preset uses*. - Any-of. Many routes accept several permissions and let the user in if they hold any one of them. They are shown as "any of" below.
- View comes first. In the Roles screen, ticking any action of a module also ticks its
view(you cannot act on what you cannot see). The exception iscrew: rest-own. - Permission ≠ page visibility. The sidebar and buttons are hidden using the same keys, but the API enforces them independently - hiding a button is never the only protection.
- Own-account actions need no permission: login/logout, your profile, change password, your own avatar, "my permissions", and the vessel list (limited to your vessels). See section 7.
- Summaries are scoped. Dashboard totals, counts and KPIs add up only the vessels the user may see.
Where the document says API routes, they are the backend endpoints that accept the permission; UI lists the frontend files that check it.
2. Role presets
One-click starting points in Create/Edit Role. They are starting points, not locked templates - tick/untick freely after applying one.
👑 Full Access
Everything, including modules added in future updates.
Grants * (everything, including future modules).
👀 Read Only
Can open every page but change nothing.
| Module | Actions |
|---|---|
Fleet Dashboard (dashboard) |
view |
Vessel KPIs (vessels) |
view |
Voyages (voyages) |
view |
Standard Work (standard-work) |
view |
Crew (crew) |
view |
Codes (codes) |
view |
Inventory (all) (inventory) |
view |
Assets (assets) |
view |
Movable Assets (movable-assets) |
view |
Warehouse & Catalogs (catalogs) |
view |
Spare Parts (spare-parts) |
view |
Stock (stock) |
view |
Alarm System (alarm-system) |
view |
Certificates (certificates) |
view |
Compliance (compliance) |
view |
Medic (medic) |
view |
Medical Items (medic-items) |
view |
Procurement (procurement) |
view |
Purchase Orders (po) |
view |
Suppliers (suppliers) |
view |
Budget (budget) |
view |
Cost Centers (cost-centers) |
view |
Maintenance (maintenance) |
view |
Cargo Operations (cargo) |
view |
Running Hours (running-hours) |
view |
Postponed Work Orders (postponed) |
view |
History (history) |
view |
Alerts (alerts) |
view |
Class Surveys (class-surveys) |
view |
Voyage Reports (voyage-reports) |
view |
Documents (documents) |
view |
Reports (reports) |
view |
Analytics (analytics) |
view |
User Dashboard (user-dashboard) |
view |
Messages (messages) |
view |
Users (users) |
view |
Roles (roles) |
view |
Vessel Access (vessel-access) |
view |
Fleet Groups (fleet-groups) |
view |
Notifications (notifications) |
view |
AIVA Assistant (aiva) |
view |
QHSE (qhse) |
view |
Admin Settings (settings) |
view |
Audit Log (audit-log) |
view |
Developer Console (dev_console) |
view |
🧭 Master / Captain
Full operational authority on the vessel. No user or system admin.
| Module | Actions |
|---|---|
AIVA Assistant (aiva) |
view |
Fleet Dashboard (dashboard) |
view |
Vessel KPIs (vessels) |
view, edit, set-position |
Voyages (voyages) |
view, create, edit, delete |
Maintenance (maintenance) |
view, create, edit, complete |
Postponed Work Orders (postponed) |
view, approve |
Running Hours (running-hours) |
view, edit |
History (history) |
view, export |
Alerts (alerts) |
view, acknowledge |
Crew (crew) |
view, edit, rest-edit, rest-approve |
Movable Assets (movable-assets) |
view, create, edit, pack, send, receive, finish, cancel |
Certificates (certificates) |
view, create, edit |
Compliance (compliance) |
view, edit |
QHSE (qhse) |
view, create, edit, delete |
Voyage Reports (voyage-reports) |
view, create, edit, export |
Documents (documents) |
view, upload, edit |
Messages (messages) |
view, send |
Medic (medic) |
view, edit |
Reports (reports) |
view, export |
🔧 Chief Engineer
Technical operations: maintenance, assets, spares, running hours.
| Module | Actions |
|---|---|
AIVA Assistant (aiva) |
view |
Fleet Dashboard (dashboard) |
view |
Vessel KPIs (vessels) |
view |
Maintenance (maintenance) |
view, create, edit, complete |
Running Hours (running-hours) |
view, edit |
Postponed Work Orders (postponed) |
view, approve |
History (history) |
view, export |
Alerts (alerts) |
view, acknowledge |
Assets (assets) |
view, create, edit, move |
Spare Parts (spare-parts) |
view, create, edit, adjust |
Stock (stock) |
view, adjust |
Warehouse & Catalogs (catalogs) |
view |
Alarm System (alarm-system) |
view, edit, acknowledge |
Standard Work (standard-work) |
view, create, edit |
Documents (documents) |
view, upload, edit |
Reports (reports) |
view, export |
Messages (messages) |
view, send |
⚓ Crew
Day-to-day work: see and complete jobs, look up spares, send messages.
| Module | Actions |
|---|---|
AIVA Assistant (aiva) |
view |
User Dashboard (user-dashboard) |
view |
Fleet Dashboard (dashboard) |
view |
Crew (crew) |
rest-own |
Maintenance (maintenance) |
view, complete |
Running Hours (running-hours) |
view, edit |
History (history) |
view |
Assets (assets) |
view |
Movable Assets (movable-assets) |
view |
Spare Parts (spare-parts) |
view |
Stock (stock) |
view |
Documents (documents) |
view |
Messages (messages) |
view, send |
Medic (medic) |
view |
QHSE (qhse) |
view |
Alerts (alerts) |
view, acknowledge |
🏢 Superintendent
Shore-side oversight across the fleet. No user or role administration.
| Module | Actions |
|---|---|
AIVA Assistant (aiva) |
view |
Fleet Dashboard (dashboard) |
view |
Vessel KPIs (vessels) |
view, create, edit, set-position |
Voyages (voyages) |
view, create, edit, delete |
Standard Work (standard-work) |
view, create, edit, delete |
Maintenance (maintenance) |
view, create, edit, complete |
Postponed Work Orders (postponed) |
view, approve |
Running Hours (running-hours) |
view, edit |
History (history) |
view, export |
Alerts (alerts) |
view, acknowledge |
Assets (assets) |
view, create, edit, move, import |
Spare Parts (spare-parts) |
view, create, edit, adjust |
Certificates (certificates) |
view, create, edit |
Compliance (compliance) |
view, edit |
Class Surveys (class-surveys) |
view, create, edit, delete |
Voyage Reports (voyage-reports) |
view, create, edit, export |
Documents (documents) |
view, upload, edit |
Reports (reports) |
view, export |
Analytics (analytics) |
view |
QHSE (qhse) |
view, create, edit, delete |
Crew (crew) |
view, create, edit, rest-edit, rest-approve |
Movable Assets (movable-assets) |
view, create, edit, approve, revoke, pack, send, receive, finish, cancel, manage |
Messages (messages) |
view, send |
Audit Log (audit-log) |
view, export |
🛒 Procurement Officer
Requisitions, purchase orders, suppliers and budget.
| Module | Actions |
|---|---|
AIVA Assistant (aiva) |
view |
Fleet Dashboard (dashboard) |
view |
Procurement (procurement) |
view, create, edit, delete |
Purchase Orders (po) |
view, create, edit, approve |
Suppliers (suppliers) |
view, create, edit, delete |
Budget (budget) |
view, edit |
Cost Centers (cost-centers) |
view, create, edit, delete |
Spare Parts (spare-parts) |
view |
Stock (stock) |
view |
Warehouse & Catalogs (catalogs) |
view, create, edit, import |
Documents (documents) |
view, upload, edit |
Reports (reports) |
view, export |
Messages (messages) |
view, send |
🦺 QHSE Officer
Safety, incidents, certificates, surveys and compliance.
| Module | Actions |
|---|---|
AIVA Assistant (aiva) |
view |
Fleet Dashboard (dashboard) |
view |
QHSE (qhse) |
view, create, edit, delete |
Certificates (certificates) |
view, create, edit |
Compliance (compliance) |
view, edit |
Class Surveys (class-surveys) |
view, create, edit, delete |
Documents (documents) |
view, upload, edit |
Alerts (alerts) |
view, acknowledge |
History (history) |
view, export |
Reports (reports) |
view, export |
Crew (crew) |
view |
Medic (medic) |
view, edit |
Audit Log (audit-log) |
view, export |
Messages (messages) |
view, send |
3. Which permission do I need to...?
Looked up from the real routes. "Any of" = holding one of them is enough. Every action also needs access to the vessel concerned (section 1).
| To... | Route | Permission needed |
|---|---|---|
| See the list of vessels / pick a vessel | GET /vessels |
signed in (no permission) |
| Open a vessel page | GET /vessels/:id |
signed in (no permission) |
| Edit vessel particulars | PATCH /vessels/:id |
modules.vessels.edit |
| Change a vessel's status | PATCH /vessels/:id/status |
modules.vessels.edit |
| Set a vessel position by hand | PATCH /vessels/:id/position |
modules.vessels.set-position |
| Delete a vessel | DELETE /vessels/:id |
modules.vessels.delete |
| Browse the asset (equipment) register | GET /assets/components |
any of modules.assets.view or modules.inventory.view |
| Create an asset | POST /assets/components |
modules.assets.create |
| Edit / rename an asset | PATCH /assets/components/:id |
modules.assets.edit |
| Move an asset in the SFI tree | POST /assets/components/:id/move |
modules.assets.move |
| Scrap an asset | POST /assets/components/:id/scrap |
modules.assets.edit |
| Delete an asset | DELETE /assets/components/:id |
modules.assets.delete |
| Link a spare part to an asset | POST /assets/components/:id/spare-parts |
modules.assets.edit |
| Raise a work order from an asset | POST /assets/components/:id/work-orders |
modules.assets.edit |
| Get the next work-order number | POST /maintenance/work-orders/generate-number |
any of modules.maintenance.create or modules.maintenance.edit or modules.assets.edit |
| List work orders | GET /maintenance/work-orders |
modules.maintenance.view |
| Start a work order | PATCH /maintenance/work-orders/:id/start |
modules.maintenance.edit |
| Release a work order someone else started | PATCH /maintenance/work-orders/:id/release |
modules.maintenance.edit |
| Sign out (complete) a work order | POST /maintenance/work-orders/:id/sign-out |
modules.maintenance.complete |
| Correct a completed work order | PATCH /maintenance/work-orders/:id/correct |
modules.maintenance.correct |
| Reopen a cancelled work order (completed ones: superadmin only) | PATCH /maintenance/work-orders/:id/reopen |
modules.maintenance.edit |
| Delete a work order | DELETE /maintenance/work-orders/:id |
modules.maintenance.delete |
| View PM schedules | GET /pm/schedules |
modules.maintenance.view |
| Create a PM schedule | POST /pm/schedules |
modules.maintenance.create |
| Edit a PM schedule | PATCH /pm/schedules/:id |
modules.maintenance.edit |
| Delete a PM schedule | DELETE /pm/schedules/:id |
modules.maintenance.delete |
| Record a running-hours reading | POST /running-hours |
modules.running-hours.edit |
| Create a spare part | POST /assets/spares |
modules.spare-parts.create |
| Edit a spare part | PATCH /assets/spares/:id |
modules.spare-parts.edit |
| Create a purchase order | POST /po |
modules.po.create |
| Edit a purchase order | PUT /po/:id |
modules.po.edit |
| Create a requisition | POST /procurement/requisitions |
modules.procurement.create |
| Upload a document | POST /documents/upload |
modules.documents.upload |
| Grant permissions on a document | POST /documents/:id/permissions |
modules.documents.edit |
| Add a crew certificate | POST /certificates/crew |
modules.certificates.create |
| Create a QHSE incident | POST /qhse/incidents |
modules.qhse.create |
| Send a message | POST /channels/:channelId/messages |
modules.messages.send |
| Create a user | POST /users |
modules.users.create |
| Create / edit a role | POST /roles |
modules.roles.create |
| Read the audit log | GET /audit/logs |
modules.audit-log.view |
| Open the AI assistant | GET /ai/status |
modules.aiva.view |
| Read Admin Settings (company profile, diagnostics) | GET /settings/company-profile |
modules.settings.view |
| Send a test email | POST /settings/email/test |
modules.settings.edit |
| Use the Developer Console (read-only) | GET /dev-console/schema |
modules.dev_console.view |
4. Module reference
Per module: what it covers, then every action with what it allows, how it is enforced, the API routes that accept it and the UI that checks it. Enforcement: API = backend routes; UI = frontend checks; service rule = enforced in service code (see section 5); not enforced = declared in the Roles screen but nothing checks it yet (ticking it has no effect).
🚢 Fleet
Fleet Dashboard (dashboard)
The Fleet Dashboard (home page): fleet map, KPIs, live alerts panel. Also unlocks the weather/maritime map data used on maps.
| Action | Permission | What it allows | Enforcement |
|---|---|---|---|
| View | modules.dashboard.view |
Open the Fleet Dashboard pages and read their data. | API + UI - 6 routes |
modules.dashboard.view - 6 API route(s), 2 UI file(s)
API routes
GET /maritime-poi- Maritime service businesses (OSM) within a bounding box — Fleet Map POI layer (any of: view, view, view)GET /weather/bounds- Get weather data for a map bounding box (3x3 grid) (any of: view, view, view)GET /weather/forecast/point- Get point forecast for a location (any of: view, view, view)POST /weather/grid- Get weather data for specific coordinate points (any of: view, view, view)GET /weather/status- Get weather service status (any of: view, view, view)GET /weather/webcams- Get webcams near a location (any of: view, view, view)
UI components/dashboard/fleet-dashboard.tsx, components/layout/sidebar.tsx
Vessel KPIs (vessels)
Vessel master data and the vessel pages: particulars, photo, status, manual position, AIS/track lookups (MarineTraffic, Barentswatch, Datalastic, Fiskeridir, Skipsregisteret) and the sync status of each vessel.
| Action | Permission | What it allows | Enforcement |
|---|---|---|---|
| View | modules.vessels.view |
Open the Vessel KPIs pages and read their data. | API + UI - 31 routes |
| Create | modules.vessels.create |
Create new Vessel KPIs records. | API + UI - 1 routes |
| Edit | modules.vessels.edit |
Edit vessel particulars, change vessel status, upload/delete the vessel photo, fetch track data. | API + UI - 58 routes |
| Delete | modules.vessels.delete |
Delete Vessel KPIs records. | API - 1 routes |
| Set Position | modules.vessels.set-position |
Manually set a vessel's position. Intended only for the window before the vessel's first AIS ping. | API + UI - 1 routes |
modules.vessels.view - 31 API route(s), 4 UI file(s)
API routes
GET /fleet-groups(any of: view, view)GET /fleet-groups/:id(any of: view, view)GET /fleet-groups/:id/members(any of: view, view)GET /fleet-groups/:id/users(any of: view, view)GET /maritime-poi- Maritime service businesses (OSM) within a bounding box — Fleet Map POI layer (any of: view, view, view)GET /positions/vessel/:vesselId- Get position history for a vesselGET /positions/vessel/:vesselId/latest- Get latest position for a vesselGET /positions/vessel/:vesselId/track- Get vessel track (position trail)GET /sync/bootstrap- Get full data snapshot for vessel initializationGET /sync/deltaGET /sync/metadataGET /sync/status- Get sync status for a vesselGET /telemetry/vessel/:vesselId/history- Get telemetry historyGET /telemetry/vessel/:vesselId/latest- Get latest telemetry for a vesselGET /tracking/barentswatch/search- Search vessels by name via BarentsWatch (any authenticated user) — for auto-filling MMSI/IMO when adding a vesselGET /tracking/barentswatch/vessel/:vesselId- Get BarentsWatch sync status + latest position for one vessel (any authenticated user)GET /tracking/datalastic/ship-specs/:vesselId- Get saved ship specifications for a vessel from databaseGET /tracking/fiskeridir/search- Search the Norwegian fishing vessel register (any authenticated user)GET /tracking/skipsregisteret/search- Search the Norwegian Ship Register (NOR/NIS) — any authenticated userGET /tracking/status- Get AISstream tracking statusGET /vessel-drawings- List a vessel’s Work Visualizer drawing sheets (ordered)GET /vessels/:id/marinetraffic-latest- Get latest MarineTraffic position for vesselGET /vessels/:id/marinetraffic-positions- Get MarineTraffic positions for vesselGET /vessels/:id/operational-summary- Get live operational counts for the map floating cardGET /vessels/:id/photo/exists- Check if vessel has photoGET /vessels/imo/:imo- Get vessel by IMO numberGET /weather/bounds- Get weather data for a map bounding box (3x3 grid) (any of: view, view, view)GET /weather/forecast/point- Get point forecast for a location (any of: view, view, view)POST /weather/grid- Get weather data for specific coordinate points (any of: view, view, view)GET /weather/status- Get weather service status (any of: view, view, view)GET /weather/webcams- Get webcams near a location (any of: view, view, view)
UI app/m/fleet/page.tsx, components/dashboard/widget-registry.tsx, components/layout/sidebar.tsx, lib/mobile/modules.ts
modules.vessels.create - 1 API route(s), 1 UI file(s)
API routes
POST /vessels- Create a new vessel (requires modules.vessels.create)
UI components/layout/topbar.tsx
modules.vessels.edit - 58 API route(s), 1 UI file(s)
API routes
POST /sync/resolve-conflict- Manually resolve a sync conflictPOST /telemetry- Store telemetry dataGET /tracking/aisstream/config- Get AISstream API configuration (Admin only)PATCH /tracking/aisstream/config- Update AISstream API configuration (Admin only)GET /tracking/aisstream/vessel-intervals- Get per-vessel AIS tracking intervals (Admin only)PATCH /tracking/aisstream/vessel-intervals- Bulk-update per-vessel AIS tracking intervals (Admin only)GET /tracking/barentswatch/config- Get BarentsWatch AIS configuration (Admin only)PATCH /tracking/barentswatch/config- Update BarentsWatch AIS configuration (Admin only)POST /tracking/barentswatch/historic/:vesselId- Fetch and import up to 14 days of historic AIS track for one vessel (Admin only)GET /tracking/barentswatch/lookup/:mmsi- Look up a single MMSI directly against the current combined feed (Admin only, debug)GET /tracking/barentswatch/queue- Get vessel sync queue with status (Admin only)GET /tracking/barentswatch/stats- Get BarentsWatch sync statistics (Admin only)POST /tracking/barentswatch/sync- Manually sync all vessel positions from BarentsWatch (Admin only)POST /tracking/barentswatch/sync/:vesselId- Force sync a specific vessel from BarentsWatch (Admin only)POST /tracking/barentswatch/test- Test the configured BarentsWatch credentials by requesting a token (Admin only)PATCH /tracking/barentswatch/vessel/:vesselId/sync-enabled- Toggle sync enabled for a vessel (Admin only)GET /tracking/cascade/status- Get cascade sync status (Datalastic → Marinesia → AISstream)POST /tracking/cascade/sync-all- Cascade sync all vessels (Datalastic → Marinesia → AISstream)POST /tracking/cascade/sync/:vesselId- Cascade sync a specific vessel (Datalastic → Marinesia → AISstream)GET /tracking/datalastic/config- Get Datalastic API configuration (Admin only)PATCH /tracking/datalastic/config- Update Datalastic API configuration (Admin only)GET /tracking/datalastic/queue- Get vessel sync queue for Datalastic (Admin only)POST /tracking/datalastic/ship-specs/:vesselId/fetch- Fetch ship specs from Datalastic API and save to vessel (Admin only)GET /tracking/datalastic/stats- Get Datalastic sync statistics (Admin only)POST /tracking/datalastic/sync/:vesselId- Force sync a specific vessel from Datalastic (Admin only)GET /tracking/datalastic/vessel/:identifier- Get vessel position from Datalastic by MMSI or IMOPATCH /tracking/datalastic/vessel/:vesselId/sync-enabled- Toggle Datalastic sync enabled for a vessel (Admin only)POST /tracking/fiskeridir/apply-specs/:vesselId- Apply admin-confirmed specs from a previewSpecs() result to a vessel (Admin only)GET /tracking/fiskeridir/config- Get Fiskeridirektoratet Fartøyregister configuration (Admin only)PATCH /tracking/fiskeridir/config- Enable/disable Fiskeridirektoratet Fartøyregister (Admin only)POST /tracking/fiskeridir/preview-specs/:vesselId- Look up a vessel in Fartøyregisteret and return what would be applied, WITHOUT saving anything (Admin only)GET /tracking/marinesia/config- Get Marinesia API configuration (Admin only)PATCH /tracking/marinesia/config- Update Marinesia API configuration (Admin only)POST /tracking/marinesia/enrich/:vesselId- Enrich vessel profile data from Marinesia (Admin only)GET /tracking/marinesia/location/latest/:mmsi- Get latest vessel position from Marinesia by MMSI (Admin only)GET /tracking/marinesia/profile/:mmsi- Get vessel profile from Marinesia by MMSI (Admin only)GET /tracking/marinesia/queue- Get vessel sync queue with status (Admin only)GET /tracking/marinesia/stats- Get Marinesia sync statistics (Admin only)POST /tracking/marinesia/sync- Manually sync all vessel positions from Marinesia (Admin only)POST /tracking/marinesia/sync/:vesselId- Force sync a specific vessel from Marinesia (Admin only)PATCH /tracking/marinesia/vessel/:vesselId/sync-enabled- Toggle sync enabled for a vessel (Admin only)POST /tracking/pause- Pause AISstream ingestion (Admin only)POST /tracking/persist-interval- Set AISstream persist interval (ms); 0 to persist every message (Admin only)POST /tracking/resume- Resume AISstream ingestion (Admin only)POST /tracking/simulate- Simulate vessel movement for demo purposes (Admin only)POST /tracking/skipsregisteret/apply-specs/:vesselId- Apply admin-confirmed specs from a previewSpecs() result to a vessel (Admin only)GET /tracking/skipsregisteret/config- Get Skipsregisteret configuration (Admin only)PATCH /tracking/skipsregisteret/config- Enable/disable Skipsregisteret (Admin only)POST /tracking/skipsregisteret/preview-specs/:vesselId- Look up a vessel in Skipsregisteret and return what would be applied, WITHOUT saving anything (Admin only)POST /tracking/update-all- Manually trigger tracking update for all vessels (Admin only)POST /tracking/vessel/:id- Track a specific vessel by ID (Admin only)POST /tracking/vesselfinder/update-all- Manually trigger VesselFinder update for all vessels (Admin only)POST /tracking/vesselfinder/update/:vesselId- Manually update vessel from VesselFinder API (Admin only)PATCH /vessels/:id- Update vessel (requires modules.vessels.edit)POST /vessels/:id/fetch-track-data- Fetch MarineTraffic track data for vesselDELETE /vessels/:id/photo- Delete vessel photoPOST /vessels/:id/photo- Upload vessel photoPATCH /vessels/:id/status- Update vessel status
UI app/vessels/[id]/page-client.tsx
modules.vessels.delete - 1 API route(s), 0 UI file(s)
API routes
DELETE /vessels/:id- Delete vessel (requires modules.vessels.delete)
modules.vessels.set-position - 1 API route(s), 1 UI file(s)
API routes
PATCH /vessels/:id/position- Manually set vessel position (requires modules.vessels.set-position)
UI components/dashboard/vessel-list.tsx
Voyages (voyages)
Voyage planning and execution: voyages, legs, port calls, fuel logs, ports registry and fuel profiles.
| Action | Permission | What it allows | Enforcement |
|---|---|---|---|
| View | modules.voyages.view |
Open the Voyages pages and read their data. | API + UI - 20 routes |
| Create | modules.voyages.create |
Create new Voyages records. | API + UI - 2 routes |
| Edit | modules.voyages.edit |
Change existing Voyages records. | API + UI - 9 routes |
| Delete | modules.voyages.delete |
Delete Voyages records. | API + UI - 2 routes |
modules.voyages.view - 20 API route(s), 1 UI file(s)
API routes
GET /maritime-poi- Maritime service businesses (OSM) within a bounding box — Fleet Map POI layer (any of: view, view, view)GET /voyages- List voyagesGET /voyages/:id- Get a voyage with its legs and port callsGET /voyages/:id/cargo- List cargo attached to this voyagePOST /voyages/:id/estimate- Recompute the fuel + cost estimate and return the full breakdownGET /voyages/:id/report.pdf- Download the voyage report as a branded PDFGET /voyages/:id/report.xlsx- Download the voyage as an Excel workbookPOST /voyages/calculate- Calculate route alternatives + distance/fuel for a planned leg-setGET /voyages/fuel-profile/:vesselId- Get (or auto-seed) a vessel fuel profileGET /voyages/ports- Search ports by name, alias, LOCODE or country (max 500 per page)GET /voyages/ports/:id- One port, including World Port Index detailsGET /voyages/ports/map- All ports with a position as compact tuples [id, name, locode, lat, lon, wpiSize] for the mapsGET /voyages/ports/nearest- Nearest ports to a position, with distance in NMGET /voyages/ports/registry/status- Port registry version and coverageGET /voyages/ports/search- Search ports for the route builder (name, alias, LOCODE; best match first, max 20)GET /weather/bounds- Get weather data for a map bounding box (3x3 grid) (any of: view, view, view)GET /weather/forecast/point- Get point forecast for a location (any of: view, view, view)POST /weather/grid- Get weather data for specific coordinate points (any of: view, view, view)GET /weather/status- Get weather service status (any of: view, view, view)GET /weather/webcams- Get webcams near a location (any of: view, view, view)
UI components/layout/sidebar.tsx
modules.voyages.create - 2 API route(s), 1 UI file(s)
API routes
POST /voyages- Create a voyagePOST /voyages/ports- Create a port
UI app/voyages/page.tsx
modules.voyages.edit - 9 API route(s), 1 UI file(s)
API routes
PATCH /voyages/:id- Update a voyagePOST /voyages/:id/actual-fuel- Record actual bunkered fuel (feeds the learning correction factor)POST /voyages/:id/cargo- Attach a cargo shipment (maps its ports onto voyage legs; warns if off-route)DELETE /voyages/:id/cargo/:shipmentId- Detach a cargo shipment from this voyagePUT /voyages/:id/legs- Replace the voyage leg-set (canonical route)PUT /voyages/:id/port-calls- Replace the voyage port-call setPATCH /voyages/:id/status- Advance a voyage through its lifecyclePUT /voyages/fuel-profile/:vesselId- Update a vessel fuel profile (marks it manual/trusted)PATCH /voyages/ports/:id- Update a port
UI app/voyages/page.tsx
modules.voyages.delete - 2 API route(s), 1 UI file(s)
API routes
DELETE /voyages/:id- Soft-delete a voyageDELETE /voyages/ports/:id- Delete a port
UI app/voyages/page.tsx
Standard Work (standard-work)
The Standard Work library (job templates that Planned Maintenance schedules are built from).
| Action | Permission | What it allows | Enforcement |
|---|---|---|---|
| View | modules.standard-work.view |
Open the Standard Work pages and read their data. | API + UI - 4 routes |
| Create | modules.standard-work.create |
Create new Standard Work records. | API + UI - 2 routes |
| Edit | modules.standard-work.edit |
Change existing Standard Work records. | API + UI - 4 routes |
| Delete | modules.standard-work.delete |
Delete Standard Work records. | API + UI - 1 routes |
modules.standard-work.view - 4 API route(s), 1 UI file(s)
API routes
GET /standards- List imported Standard JobsGET /standards/:id- Get a Standard Job by IDGET /standards/filter-options- Get unique filter options for standard jobsGET /uploads/list/:entityId- List files by entity ID (any of: view, view)
UI components/layout/sidebar.tsx
modules.standard-work.create - 2 API route(s), 1 UI file(s)
API routes
POST /standards- Create a new Standard JobPOST /standards/import- Import Standard Jobs from Excel (.xlsx)
UI app/standard-work/page.tsx
modules.standard-work.edit - 4 API route(s), 1 UI file(s)
API routes
PUT /standards/:id- Update a Standard JobPOST /standards/:id/unvalidate- Set validated = false for a Standard JobPOST /standards/:id/validate- Set validated = true for a Standard JobPOST /uploads/upload- Upload a file to local storage (any of: upload, edit)
UI app/standard-work/page.tsx
modules.standard-work.delete - 1 API route(s), 1 UI file(s)
API routes
DELETE /standards/:id- Delete a Standard Job
UI app/standard-work/page.tsx
Crew (crew)
Crew roster, vessel assignments, crew certificates/training/medical records, analytics (competency matrix, expiry dashboard, availability) and Hours of Rest.
| Action | Permission | What it allows | Enforcement |
|---|---|---|---|
| View | modules.crew.view |
Open the Crew pages and read their data. | API + UI - 20 routes |
| Create | modules.crew.create |
Create new Crew records. | API - 3 routes |
| Edit | modules.crew.edit |
Change existing Crew records. | API + UI - 12 routes |
| Delete | modules.crew.delete |
Delete Crew records. | API - 1 routes |
| Hours of rest: own record | modules.crew.rest-own |
Hours of rest: work with your OWN record only. Stands on its own - does not require Crew: view. | API + UI - 3 routes |
| Hours of rest: fill in anyone's | modules.crew.rest-edit |
Hours of rest: fill in anyone's record. | API + UI - 1 routes |
| Hours of rest: approve | modules.crew.rest-approve |
Hours of rest: approve (sign off) records. | API + UI - 1 routes |
modules.crew.view - 20 API route(s), 3 UI file(s)
API routes
GET /crew/analytics/availability- Crew availability overviewGET /crew/analytics/competency-matrix- Crew competency matrix (crew x certificates)GET /crew/analytics/expiry-dashboard- Upcoming expirations across certs/training/medical/passport/seaman bookGET /crew/assignments- Get crew assignments for a vesselGET /crew/departments- Get crew count by departmentGET /crew/history/:crewMemberId- Get assignment history for a crew memberGET /crew/integrity- Crew data integrity reportGET /crew/members- List crew membersGET /crew/members/:id- Get a crew memberGET /crew/members/:id/medical- List medical records for a crew memberGET /crew/members/:id/responsibilities- List responsibilities for a crew memberGET /crew/members/:id/training- List training records for a crew memberGET /crew/members/by-user/:userId- Resolve a userGET /crew/members/unlinked- Crew members with no linked userGET /crew/on-board- Get active crew currently on board a vesselGET /crew/responsibilities- Find responsibilities by scopeGET /crew/rest/member/:id- One crew member month of work/rest days, checked against the regulation (any of: view, rest-own)GET /crew/rest/regulation/:vesselId- The hours-of-rest limits that apply on a vesselGET /crew/rest/vessel/:vesselId- Month overview for everyone serving on a vesselGET /crew/users/unlinked- Users with no linked crew profile
UI app/crew/rest-hours/page.tsx, components/auth/auth-debug.tsx, components/layout/sidebar.tsx
modules.crew.create - 3 API route(s), 0 UI file(s)
API routes
POST /crew/embark- Create a new crew assignment (embark)POST /crew/members- Create a crew member (optionally linked to a user)POST /crew/seed-demo- Seed demo crew members across vessels (idempotent)
modules.crew.edit - 12 API route(s), 1 UI file(s)
API routes
PATCH /crew/disembark/:id- Complete a crew assignment (disembark)PATCH /crew/members/:id- Update a crew memberPOST /crew/members/:id/link-user- Link a crew member 1:1 to a userPOST /crew/members/:id/medical- Add a medical record (snapshots latest onto member)POST /crew/members/:id/photo- Set crew member profile photo pathPOST /crew/members/:id/responsibilities- Add a maintenance responsibilityPOST /crew/members/:id/training- Add a training recordPOST /crew/members/:id/unlink-user- Unlink the user from a crew memberDELETE /crew/responsibilities/:rid- Delete a responsibilityPUT /crew/rest/regulation/:vesselId- Set the hours-of-rest limits for a vesselDELETE /crew/training/:tid- Delete a training recordPATCH /crew/training/:tid- Update a training record
UI app/crew/rest-hours/page.tsx
modules.crew.delete - 1 API route(s), 0 UI file(s)
API routes
DELETE /crew/members/:id- Deactivate (soft-delete) a crew member
modules.crew.rest-own - 3 API route(s), 1 UI file(s)
API routes
GET /crew/rest/member/:id- One crew member month of work/rest days, checked against the regulation (any of: view, rest-own)PUT /crew/rest/member/:id/day/:date- Record one day of work and rest (any of: rest-edit, rest-own)GET /crew/rest/mine- The crew record linked to your login (for the own-record right)
UI app/crew/rest-hours/page.tsx
modules.crew.rest-edit - 1 API route(s), 1 UI file(s)
API routes
PUT /crew/rest/member/:id/day/:date- Record one day of work and rest (any of: rest-edit, rest-own)
UI app/crew/rest-hours/page.tsx
modules.crew.rest-approve - 1 API route(s), 1 UI file(s)
API routes
POST /crew/rest/member/:id/approval- Approve (lock) or reopen the recorded days in a date range (never your own)
UI app/crew/rest-hours/page.tsx
Codes (codes)
Company code lists used in drop-downs (departments, makers, categories, component types, ...).
| Action | Permission | What it allows | Enforcement |
|---|---|---|---|
| View | modules.codes.view |
Open the Codes pages and read their data. | API + UI - 4 routes |
| Create | modules.codes.create |
Create new Codes records. | API + UI - 4 routes |
| Edit | modules.codes.edit |
Change existing Codes records. | API + UI - 2 routes |
| Delete | modules.codes.delete |
Delete Codes records. | API + UI - 3 routes |
modules.codes.view - 4 API route(s), 1 UI file(s)
API routes
GET /codes- List code values; filter by type with ?type=keyGET /codes/export.csv- Export all code values as CSVGET /codes/export.xlsx- Export all code types and values as Excel (.xlsx)GET /codes/types- List all code types
UI components/layout/sidebar.tsx
modules.codes.create - 4 API route(s), 2 UI file(s)
API routes
POST /codes- Create a code valuePOST /codes/import- Import codes from CSV or XLSX (multipart file upload or raw text/csv body)POST /codes/seed-defaults- Restore default code types and values (idempotent)POST /codes/sync-from-spares- Import makers, suppliers, maker types from spare_parts (distinct values)
UI app/codes/page.tsx, components/form/code-combobox.tsx
modules.codes.edit - 2 API route(s), 1 UI file(s)
API routes
PATCH /codes/:id- Update a code valuePATCH /codes/types/:id- Update a code type
UI app/codes/page.tsx
modules.codes.delete - 3 API route(s), 1 UI file(s)
API routes
DELETE /codes/:id- Delete a code valueDELETE /codes/types/:id- Delete a company-created code typePOST /codes/types/:key/reset-values- Clear a code type\
UI app/codes/page.tsx
📦 Inventory
Inventory (all) (inventory)
Umbrella grant for the Inventory folder: many inventory screens and lookups accept inventory.view as an alternative to their own module permission (e.g. Assets or Spare Parts). inventory.edit is declared but not enforced anywhere.
| Action | Permission | What it allows | Enforcement |
|---|---|---|---|
| View | modules.inventory.view |
Open the Inventory (all) pages and read their data. | API + UI - 71 routes |
| Edit | modules.inventory.edit |
Declared but not enforced anywhere. | not enforced - 0 routes |
modules.inventory.view - 71 API route(s), 6 UI file(s)
API routes
GET /assets- Get all asset items (paginated) (any of: view, view)GET /assets/:id- Get asset item by ID (any of: view, view)GET /assets/:id/documents- List documents for an asset (any of: view, view)GET /assets/:id/documents/:docId/download- Get a pre-signed download URL for a document (or direct URL for external docs) (any of: view, view)GET /assets/:id/history- Get maintenance history for an asset (any of: view, view)GET /assets/:id/spare-parts- List spare parts linked to an asset (any of: view, view)GET /assets/:id/work-orders- List work orders for an asset (any of: view, view)GET /assets/change-logs/recent- Fleet-wide recent asset changes (dashboard Recent Activity feed) (any of: view, view)GET /assets/components- List all components (any of: view, view)GET /assets/components/:id(any of: view, view)GET /assets/components/:id/can-delete- Check if asset can be deleted (any of: view, view)GET /assets/components/:id/certificates- Get certificates for an asset (any of: view, view)GET /assets/components/:id/change-logs- Get change log for an asset (any of: view, view)GET /assets/components/:id/documents(any of: view, view)GET /assets/components/:id/documents/:docId/download(any of: view, view)GET /assets/components/:id/history(any of: view, view)GET /assets/components/:id/job-history- Get all work order history for an asset (any of: view, view)GET /assets/components/:id/spare-parts(any of: view, view)GET /assets/components/:id/work-orders(any of: view, view)GET /assets/components/:id/work-orders/:woId/spares- List spare parts linked to a work order (any of: view, view)GET /assets/components/history- Get all maintenance history with optional filtering (any of: view, view)GET /assets/components/scrapped/all- Get all scrapped assets across all vessels (any of: view, view)GET /assets/components/search- Search components (autocomplete) (any of: view, view)GET /assets/components/search- Search components by name or SFI code (autocomplete) (any of: view, view)GET /assets/components/vessel/:vesselId(any of: view, view)GET /assets/components/vessel/:vesselId/scrapped- Get all scrapped assets for a vessel (any of: view, view)GET /assets/components/vessel/:vesselId/sfi/:sfiGroup(any of: view, view)GET /assets/components/vessel/:vesselId/stats(any of: view, view)GET /assets/components/vessel/:vesselId/total-value- Get total asset value for a vessel (direct SQL query) (any of: view, view)GET /assets/spares- List all spare parts (any of: view, view)GET /assets/spares/:id(any of: view, view)GET /assets/spares/:id/asset-links- Get all assets/components this spare part is linked to (any of: view, view)GET /assets/spares/:id/transactions- Get stock transaction history for a spare part (any of: view, view)GET /assets/spares/:id/work-order-usage- Get work order usage history for this spare part (any of: view, view)GET /assets/spares/locations- List spare locations. Provide parentId to lazy-load children, else returns all in tree order. (any of: view, view)GET /assets/spares/low-stock- Get count of items below minimum stock level (any of: view, view)GET /assets/spares/reorder-report- Get spare parts that are below minimum quantity (reorder report) (any of: view, view)GET /assets/spares/stock- List all spare parts for a specific vessel (direct or via asset link) (any of: view, view)GET /assets/spares/transactions/all- Get all stock transactions, optionally filtered by vessel (any of: view, view)GET /assets/spares/unlinked- List spare parts not linked to any asset (any of: view, view)GET /assets/vessel/:vesselId- Get assets by vessel ID (any of: view, view)GET /assets/vessel/:vesselId/sfi/:sfiGroup- Get assets by vessel and SFI group (any of: view, view)GET /assets/vessel/:vesselId/stats- Get asset statistics for a vessel (any of: view, view)GET /catalog-folders- List all catalog folders with item counts (any of: view, view)GET /catalogs- List/search catalog items with filters and pagination (any of: view, view)GET /catalogs/stats- Get total catalog items and last import metadata (any of: view, view)GET /inventory/alarm-systems- List alarm systems with filters and pagination (any of: view, view)GET /inventory/certificates- List certificates with filters and pagination (any of: view, view)GET /medic/activity-log- Get activity log for medical inventory (any of: view, view)GET /medic/analytics/expiring- Get expiring items (any of: view, view)GET /medic/analytics/summary- Get medical inventory summary/KPIs (any of: view, view)GET /medic/categories- Get all medical categories (any of: view, view)GET /medic/compliance/:vesselId- Get full MLC compliance dashboard for vessel (3-leg score) (any of: view, view)GET /medic/export/items.csv- Export items catalog to CSV (any of: view, view)GET /medic/export/stock.csv- Export stock to CSV (any of: view, view)GET /medic/inspections- Get inspections (any of: view, view)GET /medic/inspections/:id- Get inspection details (any of: view, view)GET /medic/items- Get medical items catalog (any of: view, view)GET /medic/items/:id- Get medical item details (any of: view, view)GET /medic/kits- Get all medical kits (any of: view, view)GET /medic/kits/:id- Get medical kit details with items (any of: view, view)GET /medic/kits/:id/compliance/:vesselId- Get kit compliance for vessel (any of: view, view)GET /medic/missing/:vesselId- Get missing items for vessel (all kits or specific kit) (any of: view, view)GET /medic/stock- Get medical stock for vessel (any of: view, view)GET /medic/stock/:id- Get stock item details (any of: view, view)GET /medic/usage- Get usage logs (any of: view, view)GET /medic/usage/export.csv- Export usage logs to CSV (any of: view, view)GET /medic/vessel-kits/:vesselId- Get kit assignments for a vessel (any of: view, view)GET /vendor-catalogs- List vendor catalogs with optional supplier/search filter (any of: view, view)GET /vendor-catalogs/:id/items- List items in a vendor catalog with optional search/filter (any of: view, view)GET /vendor-catalogs/stats- Vendor catalog stats: total catalogs, items, breakdown by format (any of: view, view)
UI app/assets/page.tsx, app/assets/scrapped/page.tsx, app/spare-parts/page.tsx, app/stock/page.tsx, app/vessel-spares/page.tsx, components/layout/sidebar.tsx
Assets (assets)
The equipment register (SFI tree), asset detail pages (specification, criticality, FMEA, risk, tracking, documents, certificates), work orders and spare links raised from an asset, and maintenance history of an asset.
| Action | Permission | What it allows | Enforcement |
|---|---|---|---|
| View | modules.assets.view |
Open the Assets pages and read their data. | API + UI - 45 routes |
| Create | modules.assets.create |
Create new Assets records. | API - 2 routes |
| Edit | modules.assets.edit |
Edit an asset and everything attached to it: fields, criticality/FMEA/risk, documents, spare links, history entries, and raising work orders from the asset. Also required to scrap/restore an asset and to create a work-order number. | API + UI - 33 routes |
| Delete | modules.assets.delete |
Delete an asset that has no job history (assets with history can only be scrapped). | API - 2 routes |
| Move / Reorganize Codes | modules.assets.move |
Move an asset elsewhere in the SFI tree / reassign its code (the dedicated Move endpoint). | API + UI - 1 routes |
| Import | modules.assets.import |
Bulk-import assets from a spreadsheet. | API - 1 routes |
modules.assets.view - 45 API route(s), 6 UI file(s)
API routes
GET /assets- Get all asset items (paginated) (any of: view, view)GET /assets/:id- Get asset item by ID (any of: view, view)GET /assets/:id/documents- List documents for an asset (any of: view, view)GET /assets/:id/documents/:docId/download- Get a pre-signed download URL for a document (or direct URL for external docs) (any of: view, view)GET /assets/:id/history- Get maintenance history for an asset (any of: view, view)GET /assets/:id/spare-parts- List spare parts linked to an asset (any of: view, view)GET /assets/:id/work-orders- List work orders for an asset (any of: view, view)GET /assets/change-logs/recent- Fleet-wide recent asset changes (dashboard Recent Activity feed) (any of: view, view)GET /assets/components- List all components (any of: view, view)GET /assets/components/:id(any of: view, view)GET /assets/components/:id/can-delete- Check if asset can be deleted (any of: view, view)GET /assets/components/:id/certificates- Get certificates for an asset (any of: view, view)GET /assets/components/:id/change-logs- Get change log for an asset (any of: view, view)GET /assets/components/:id/documents(any of: view, view)GET /assets/components/:id/documents/:docId/download(any of: view, view)GET /assets/components/:id/history(any of: view, view)GET /assets/components/:id/job-history- Get all work order history for an asset (any of: view, view)GET /assets/components/:id/spare-parts(any of: view, view)GET /assets/components/:id/work-orders(any of: view, view)GET /assets/components/:id/work-orders/:woId/spares- List spare parts linked to a work order (any of: view, view)GET /assets/components/history- Get all maintenance history with optional filtering (any of: view, view)GET /assets/components/scrapped/all- Get all scrapped assets across all vessels (any of: view, view)GET /assets/components/search- Search components (autocomplete) (any of: view, view)GET /assets/components/search- Search components by name or SFI code (autocomplete) (any of: view, view)GET /assets/components/vessel/:vesselId(any of: view, view)GET /assets/components/vessel/:vesselId/scrapped- Get all scrapped assets for a vessel (any of: view, view)GET /assets/components/vessel/:vesselId/sfi/:sfiGroup(any of: view, view)GET /assets/components/vessel/:vesselId/stats(any of: view, view)GET /assets/components/vessel/:vesselId/total-value- Get total asset value for a vessel (direct SQL query) (any of: view, view)GET /assets/history/all- List maintenance history across all assets (filters & paging) (any of: view, view)GET /assets/history/analytics/cost-trends- Get maintenance cost trends over time (monthly aggregation) (any of: view, view)GET /assets/history/analytics/equipment-breakdown- Get maintenance breakdown by equipment type (any of: view, view)GET /assets/history/analytics/summary- Get maintenance summary statistics (any of: view, view)GET /assets/history/analytics/top-issues- Get top problem equipment by maintenance frequency (any of: view, view)GET /assets/history/export.csv- Export maintenance history as CSV (server-side, supports filters) (any of: view, view)GET /assets/history/export.xlsx- Export maintenance history as XLSX (server-side, supports filters) (any of: view, view)GET /assets/vessel/:vesselId- Get assets by vessel ID (any of: view, view)GET /assets/vessel/:vesselId/sfi/:sfiGroup- Get assets by vessel and SFI group (any of: view, view)GET /assets/vessel/:vesselId/stats- Get asset statistics for a vessel (any of: view, view)GET /movable/components/:assetId/movable- One component (any of: view, view)GET /reports/asset-data.pdf- Asset Data Report (dossier) for selected assets (any of: view, view)GET /reports/class-compliance.pdf- Class Compliance (PMS) report (any of: view, view)GET /reports/compliance.pdf- PM Compliance report (any of: view, view, view)GET /reports/maintenance-history.pdf- Maintenance History report (completed work) (any of: view, view, view)GET /reports/maintenance-schedule.pdf- Maintenance Schedule report (upcoming PM) (any of: view, view, view)
UI app/assets/page.tsx, app/assets/scrapped/page.tsx, app/m/assets/[id]/page.tsx, app/m/assets/page.tsx, components/layout/sidebar.tsx, lib/mobile/modules.ts
modules.assets.create - 2 API route(s), 0 UI file(s)
API routes
POST /assets- Create new asset itemPOST /assets/components
modules.assets.edit - 33 API route(s), 6 UI file(s)
API routes
PATCH /assets/:id- Update asset itemPOST /assets/:id/documents- Add document to an assetDELETE /assets/:id/documents/:docId- Delete a document from an assetPATCH /assets/:id/documents/:docId- Update a document (name or url)POST /assets/:id/documents/upload-url- Get a pre-signed upload URL for MinIO (S3)POST /assets/:id/history- Add maintenance history record to an assetPOST /assets/:id/spare-parts- Link a spare part to an asset (or create and link)DELETE /assets/:id/spare-parts/:partId- Unlink a spare part from an assetPATCH /assets/:id/spare-parts/:partId/stock- Adjust spare part stock or supplierPOST /assets/:id/work-orders- Create work order for an assetDELETE /assets/:id/work-orders/:woId- Delete a work orderPATCH /assets/:id/work-orders/:woId- Update work order (status, dates, costs, assignee)PATCH /assets/components/:idPOST /assets/components/:id/change-logs- Add a change log entry for an assetPOST /assets/components/:id/documentsDELETE /assets/components/:id/documents/:docIdPATCH /assets/components/:id/documents/:docIdPOST /assets/components/:id/historyPOST /assets/components/:id/scrap- Scrap an asset/componentPOST /assets/components/:id/spare-partsDELETE /assets/components/:id/spare-parts/:partIdPATCH /assets/components/:id/spare-parts/:partId/stockPOST /assets/components/:id/unscrap- Un-scrap an asset/componentPOST /assets/components/:id/work-ordersDELETE /assets/components/:id/work-orders/:woIdPATCH /assets/components/:id/work-orders/:woIdPOST /assets/components/:id/work-orders/:woId/spares- Link spare parts to a work orderDELETE /assets/components/:id/work-orders/:woId/spares/:spareId- Unlink spare part from work orderPATCH /assets/components/:id/work-orders/:woId/spares/:spareId- Update spare part quantity on work orderPOST /assets/components/:id/work-orders/:woId/spares/consume- Consume (deduct from stock) all spare parts linked to a work orderPOST /assets/components/upload-image- Upload asset imagePOST /maintenance/work-orders/generate-number- Generate next WO number from sequence (any of: create, edit, edit)POST /reports/service- Create a new service report for an asset (any of: edit, edit)
UI app/assets/[id]/fmea/page-client.tsx, app/assets/[id]/job-history/page-client.tsx, app/assets/[id]/risk-evaluation/page-client.tsx, app/assets/[id]/specification/page-client.tsx, app/assets/[id]/tracking/page-client.tsx, components/assets/sfi-grid.tsx
modules.assets.delete - 2 API route(s), 0 UI file(s)
API routes
DELETE /assets/:id- Delete asset itemDELETE /assets/components/:id
modules.assets.move - 1 API route(s), 1 UI file(s)
API routes
POST /assets/components/:id/move- Move/reorganize an SFI node + its subtree under a new parent (requires modules.assets.move). Use dryRun=true for a preview.
UI components/assets/sfi-grid.tsx
modules.assets.import - 1 API route(s), 0 UI file(s)
API routes
POST /assets/components/bulk- Bulk create SFI components (requires modules.assets.import)
Movable Assets (movable-assets)
Movable assets (tools/equipment transferred between vessels with pro-forma invoices), their categories, locations, in-transit tracking and due jobs.
| Action | Permission | What it allows | Enforcement |
|---|---|---|---|
| View | modules.movable-assets.view |
Open the Movable Assets pages and read their data. | API + UI - 13 routes |
| Create | modules.movable-assets.create |
Create new Movable Assets records. | API + UI - 4 routes |
| Edit | modules.movable-assets.edit |
Change existing Movable Assets records. | API + UI - 8 routes |
| Approve | modules.movable-assets.approve |
Approve a pro-forma invoice (it gets its number and the shipping list locks). | API + UI - 1 routes |
| Revoke approval | modules.movable-assets.revoke |
Revoke the approval of an invoice, until the package is sent. The steps after approval then have to be done again. | API + UI - 1 routes |
| Set to packed | modules.movable-assets.pack |
Set an approved invoice to packed (the people packing tell the office it is ready). | API + UI - 1 routes |
| Send | modules.movable-assets.send |
Send the package: the assets go in transit, onboard can no longer change them, and their jobs can be paused. | API + UI - 1 routes |
| Set as received | modules.movable-assets.receive |
Register what the receiving vessel has received, partly if need be. Received assets move to the receiving vessel. | API + UI - 1 routes |
| Finish and set active | modules.movable-assets.finish |
Finish the invoice: the received assets become active onboard and their jobs come back on the due list. | API + UI - 1 routes |
| Cancel | modules.movable-assets.cancel |
Cancel an invoice that has not been sent. The assets are active onboard again. | API + UI - 1 routes |
| Manage | modules.movable-assets.manage |
Administer movable-asset categories and which vessels carry them. | API + UI - 8 routes |
modules.movable-assets.view - 13 API route(s), 2 UI file(s)
API routes
GET /movable/categories- Movable categories with the vessels designated to receive eachGET /movable/components- Movable components across the fleetGET /movable/components/:assetId/movable- One component (any of: view, view)GET /movable/due-in-transit- Open jobs of assets that are travelling, and which are pausedGET /movable/holding-bay- A vesselGET /movable/in-transit- Assets on their wayGET /movable/invoices- Pro-forma invoicesGET /movable/invoices/:id- One invoice with its shipping list, packages, history and what may be done nextGET /movable/invoices/:id/files- Documents attached to the transferGET /movable/invoices/:id/warnings- Open jobs, permits and running-hours links worth knowing before the transferGET /movable/locations- Movable stock locations across the fleetGET /movable/locations/:locationId/items- The items inside a movable stock locationGET /movable/movements- Transfer history of movable assets
UI components/assets/asset-movable-card.tsx, components/layout/sidebar.tsx
modules.movable-assets.create - 4 API route(s), 1 UI file(s)
API routes
DELETE /movable/invoice-lines/:lineId- Take an asset off the shipping listPOST /movable/invoices- Start a pro-forma invoicePOST /movable/invoices/:id/components- Add a movable component to the shipping listPOST /movable/invoices/:id/locations- Add a movable stock location to the shipping list
UI app/movable-assets/page.tsx
modules.movable-assets.edit - 8 API route(s), 1 UI file(s)
API routes
DELETE /movable/files/:fileId- Remove an attached documentPATCH /movable/invoices/:id- Change the invoice detailsPOST /movable/invoices/:id/files- Attach a document to the transferPOST /movable/invoices/:id/jobs/disable- Pause the scheduled jobs of the assets on the invoicePOST /movable/invoices/:id/jobs/enable- Switch the paused jobs on again with the chosen due-date rulePOST /movable/invoices/:id/packages- Add a packageDELETE /movable/packages/:packageId- Remove a packagePATCH /movable/packages/:packageId- Change a package
UI app/movable-assets/page.tsx
modules.movable-assets.approve - 1 API route(s), 1 UI file(s)
API routes
POST /movable/invoices/:id/approve- Approve: number the invoice, lock the shipping list, check the receiver can take the categories
UI app/movable-assets/page.tsx
modules.movable-assets.revoke - 1 API route(s), 1 UI file(s)
API routes
POST /movable/invoices/:id/revoke- Revoke the approval (until the package is sent)
UI app/movable-assets/page.tsx
modules.movable-assets.pack - 1 API route(s), 1 UI file(s)
API routes
POST /movable/invoices/:id/pack- Set the invoice to packed
UI app/movable-assets/page.tsx
modules.movable-assets.send - 1 API route(s), 1 UI file(s)
API routes
POST /movable/invoices/:id/send- Send the package: the assets are in transit; their jobs can be paused
UI app/movable-assets/page.tsx
modules.movable-assets.receive - 1 API route(s), 1 UI file(s)
API routes
POST /movable/invoices/:id/receive- Register what the receiving vessel has received (partly if need be)
UI app/movable-assets/page.tsx
modules.movable-assets.finish - 1 API route(s), 1 UI file(s)
API routes
POST /movable/invoices/:id/finish- Finish: the assets are active onboard and their jobs come back
UI app/movable-assets/page.tsx
modules.movable-assets.cancel - 1 API route(s), 1 UI file(s)
API routes
POST /movable/invoices/:id/cancel- Cancel an invoice that has not been sent
UI app/movable-assets/page.tsx
modules.movable-assets.manage - 8 API route(s), 2 UI file(s)
API routes
POST /movable/categories- Add a movable categoryDELETE /movable/categories/:id- Delete a category nothing usesPATCH /movable/categories/:id- Change a movable categoryPUT /movable/categories/:id/vessels- Set which vessels may receive this categoryDELETE /movable/components/:assetId- Make a component fixed againPOST /movable/components/mark- Make a component (and its sub components) movableDELETE /movable/locations/:locationId- Make a stock location fixed againPOST /movable/locations/mark- Make a stock location movable
UI app/movable-assets/page.tsx, components/assets/asset-movable-card.tsx
Warehouse & Catalogs (catalogs)
Warehouse catalogs and vendor catalogs (folders, items, imports).
| Action | Permission | What it allows | Enforcement |
|---|---|---|---|
| View | modules.catalogs.view |
Open the Warehouse & Catalogs pages and read their data. | API + UI - 6 routes |
| Create | modules.catalogs.create |
Create new Warehouse & Catalogs records. | API - 3 routes |
| Edit | modules.catalogs.edit |
Change existing Warehouse & Catalogs records. | API - 2 routes |
| Delete | modules.catalogs.delete |
Delete Warehouse & Catalogs records. | API - 4 routes |
| Import | modules.catalogs.import |
Import Warehouse & Catalogs data. | API - 5 routes |
modules.catalogs.view - 6 API route(s), 1 UI file(s)
API routes
GET /catalog-folders- List all catalog folders with item counts (any of: view, view)GET /catalogs- List/search catalog items with filters and pagination (any of: view, view)GET /catalogs/stats- Get total catalog items and last import metadata (any of: view, view)GET /vendor-catalogs- List vendor catalogs with optional supplier/search filter (any of: view, view)GET /vendor-catalogs/:id/items- List items in a vendor catalog with optional search/filter (any of: view, view)GET /vendor-catalogs/stats- Vendor catalog stats: total catalogs, items, breakdown by format (any of: view, view)
UI components/layout/sidebar.tsx
modules.catalogs.create - 3 API route(s), 0 UI file(s)
API routes
POST /catalog-folders- Create new catalog folderPOST /catalogs- Create a single catalog itemPOST /vendor-catalogs- Create a new vendor catalog header (without items)
modules.catalogs.edit - 2 API route(s), 0 UI file(s)
API routes
PATCH /catalog-folders/:id- Update catalog folderPATCH /catalogs/:id- Update catalog item fields (name, unit, makerPartNo, stockQty)
modules.catalogs.delete - 4 API route(s), 0 UI file(s)
API routes
DELETE /catalog-folders/:id- Delete catalog folderDELETE /catalogs- Delete multiple catalog items by IDsDELETE /vendor-catalogs/:id- Delete a vendor catalog and all its items (cascade)DELETE /vendor-catalogs/items/:itemId- Delete a single vendor catalog item
modules.catalogs.import - 5 API route(s), 0 UI file(s)
API routes
POST /catalogs/bulk-import- Bulk import catalog items from parsed Excel dataPOST /catalogs/import- Bulk import catalog items (IMPA/ISSA). Accepts CSV/XLSX-parsed array.POST /catalogs/import/xlsx- Import catalog items from Excel (.xlsx) with headers: Item Code, Item Name, Catalog Type, Maker’s Part No, Unit, In Stock, SupplierIdPOST /vendor-catalogs/:id/items/import-json- Bulk import items from parsed JSON array (for programmatic use)POST /vendor-catalogs/:id/items/import-xlsx- Import items into a vendor catalog from Excel (.xlsx). Auto-detects IMPA / ISSA / Generic format.
Spare Parts (spare-parts)
Spare parts inventory: parts, stock locations, stock levels, imports, spare numbering.
| Action | Permission | What it allows | Enforcement |
|---|---|---|---|
| View | modules.spare-parts.view |
Open the Spare Parts pages and read their data. | API + UI - 11 routes |
| Create | modules.spare-parts.create |
Create new Spare Parts records. | API + UI - 4 routes |
| Edit | modules.spare-parts.edit |
Change existing Spare Parts records. | API + UI - 14 routes |
| Delete | modules.spare-parts.delete |
Delete Spare Parts records. | API - 2 routes |
| Adjust Stock | modules.spare-parts.adjust |
Adjust stock quantities of a spare part. | API + UI - 1 routes |
modules.spare-parts.view - 11 API route(s), 7 UI file(s)
API routes
GET /assets/spares- List all spare parts (any of: view, view)GET /assets/spares/:id(any of: view, view)GET /assets/spares/:id/asset-links- Get all assets/components this spare part is linked to (any of: view, view)GET /assets/spares/:id/transactions- Get stock transaction history for a spare part (any of: view, view)GET /assets/spares/:id/work-order-usage- Get work order usage history for this spare part (any of: view, view)GET /assets/spares/locations- List spare locations. Provide parentId to lazy-load children, else returns all in tree order. (any of: view, view)GET /assets/spares/low-stock- Get count of items below minimum stock level (any of: view, view)GET /assets/spares/reorder-report- Get spare parts that are below minimum quantity (reorder report) (any of: view, view)GET /assets/spares/stock- List all spare parts for a specific vessel (direct or via asset link) (any of: view, view)GET /assets/spares/transactions/all- Get all stock transactions, optionally filtered by vessel (any of: view, view)GET /assets/spares/unlinked- List spare parts not linked to any asset (any of: view, view)
UI app/m/stock/[id]/page.tsx, app/m/stock/page.tsx, app/spare-parts/page.tsx, app/vessel-spares/page.tsx, components/dashboard/widget-registry.tsx, components/layout/sidebar.tsx, lib/mobile/modules.ts
modules.spare-parts.create - 4 API route(s), 1 UI file(s)
API routes
POST /assets/sparesPOST /assets/spares/import- Import spare parts (dry-run or commit)POST /settings/spare-sequence/generate- Generate next Spare Part number for a vessel (any of: create, edit)POST /settings/spare-sequence/register- Register a manually entered spare part number to prevent reuse (any of: create, edit)
UI app/stock/page.tsx
modules.spare-parts.edit - 14 API route(s), 5 UI file(s)
API routes
PATCH /assets/spares/:idPATCH /assets/spares/:id/block- Block or unblock a spare partPATCH /assets/spares/:id/critical- Mark or unmark a spare part as criticalPOST /assets/spares/locations- Create a location folder (root or subfolder). Provide name and optional parentId + map placementDELETE /assets/spares/locations/:id- Delete a location. cascade=true also removes sub-locations, moves spare parts to No Location and clears component links.PATCH /assets/spares/locations/:id- Rename a location folder and update descendant paths and assigned partsPATCH /assets/spares/locations/:id/mapping- Save the Work Visualizer pin (normalized map_x/map_y + deck view) for a location. Pass null to clear a pin.PATCH /assets/spares/move-location- Move multiple spare parts to a location (by id, path, or clear to No Location)POST /settings/spare-sequence/generate- Generate next Spare Part number for a vessel (any of: create, edit)POST /settings/spare-sequence/register- Register a manually entered spare part number to prevent reuse (any of: create, edit)POST /vessel-drawings- Upload a drawing sheet. Send a renderable image asDELETE /vessel-drawings/:id- Delete a drawing sheet (its pins are unlinked, not deleted)PATCH /vessel-drawings/:id- Rename a drawing sheetPATCH /vessel-drawings/reorder- Reorder a vessel’s drawing sheets
UI app/spare-parts/page.tsx, app/stock/page.tsx, components/locations/LocationSelect.tsx, components/spares/spare-detail-card.tsx, components/visualizer/LocationManager.tsx
modules.spare-parts.delete - 2 API route(s), 0 UI file(s)
API routes
DELETE /assets/spares/:idPOST /assets/spares/cleanup-unassigned- Delete all spare parts with no vessel assignment (vesselId IS NULL) — superadmin + password
modules.spare-parts.adjust - 1 API route(s), 1 UI file(s)
API routes
POST /assets/spares/:id/adjust- Adjust stock quantity (receive, consume, adjust, scrap, return)
UI app/m/stock/[id]/page.tsx
Stock (stock)
The Stock page (a stock view over spares). Enforced in the UI only.
| Action | Permission | What it allows | Enforcement |
|---|---|---|---|
| View | modules.stock.view |
Open the Stock pages and read their data. | UI only - 0 routes |
| Adjust Stock | modules.stock.adjust |
Declared; stock changes are enforced through Spare Parts: adjust. | not enforced - 0 routes |
modules.stock.view - 0 API route(s), 2 UI file(s)
UI app/stock/page.tsx, components/layout/sidebar.tsx
Alarm System (alarm-system)
Alarm equipment tracking (fire, safety, engine alarms).
| Action | Permission | What it allows | Enforcement |
|---|---|---|---|
| View | modules.alarm-system.view |
Open the Alarm System pages and read their data. | API + UI - 1 routes |
| Edit | modules.alarm-system.edit |
Change existing Alarm System records. | API + UI - 3 routes |
| Acknowledge | modules.alarm-system.acknowledge |
Acknowledge an alarm. Declared but not currently enforced. | not enforced - 0 routes |
modules.alarm-system.view - 1 API route(s), 1 UI file(s)
API routes
GET /inventory/alarm-systems- List alarm systems with filters and pagination (any of: view, view)
UI components/layout/sidebar.tsx
modules.alarm-system.edit - 3 API route(s), 1 UI file(s)
API routes
POST /inventory/alarm-systems- Create an alarm (Admin only)DELETE /inventory/alarm-systems/:id- Delete an alarm (Admin only)PATCH /inventory/alarm-systems/:id- Update an alarm (Admin only)
UI app/alarm-system/page.tsx
Certificates (certificates)
Crew and vessel certificates, certificate types and the reminder automation.
| Action | Permission | What it allows | Enforcement |
|---|---|---|---|
| View | modules.certificates.view |
Open the Certificates pages and read their data. | API + UI - 26 routes |
| Create | modules.certificates.create |
Create new Certificates records. | API + UI - 5 routes |
| Edit | modules.certificates.edit |
Change existing Certificates records. | API - 6 routes |
| Delete | modules.certificates.delete |
Delete Certificates records. | API - 4 routes |
modules.certificates.view - 26 API route(s), 4 UI file(s)
API routes
GET /certificates/crew- Get all crew certificatesGET /certificates/crew/:id- Get crew certificate by IDGET /certificates/crew/crew-member/:crewMemberId- Get all certificates for a crew memberGET /certificates/crew/crew-member/:crewMemberId/compliance- Get crew member compliance statusGET /certificates/crew/expired- Get expired crew certificatesGET /certificates/crew/expiring- Get expiring crew certificatesGET /certificates/crew/statistics- Get crew certificates statisticsGET /certificates/reminders/summary- Get certificate reminder automation summaryGET /certificates/reports/crew/:crewMemberId/pdf- Download crew certificates PDF reportGET /certificates/reports/fleet/pdf- Download fleet certificates snapshot PDF reportGET /certificates/reports/vessel/:vesselId/pdf- Download vessel certificates PDF reportGET /certificates/types- Get all certificate typesGET /certificates/types/:id- Get certificate type by IDGET /certificates/types/code/:code- Get certificate type by codeGET /certificates/types/crew- Get all crew certificate typesGET /certificates/types/statistics- Get certificate types statisticsGET /certificates/types/vessel- Get all vessel certificate typesGET /certificates/vessel- Get all vessel certificatesGET /certificates/vessel/:id- Get vessel certificate by IDGET /certificates/vessel/by-vessel/:vesselId- Get all certificates for a vesselGET /certificates/vessel/by-vessel/:vesselId/compliance- Get vessel compliance statusGET /certificates/vessel/class-society/:classSociety- Get certificates by class societyGET /certificates/vessel/expired- Get expired vessel certificatesGET /certificates/vessel/expiring- Get expiring vessel certificatesGET /certificates/vessel/statistics- Get vessel certificates statisticsGET /inventory/certificates- List certificates with filters and pagination (any of: view, view)
UI app/m/certificates/page.tsx, components/dashboard/widget-registry.tsx, components/layout/sidebar.tsx, lib/mobile/modules.ts
modules.certificates.create - 5 API route(s), 2 UI file(s)
API routes
POST /assets/components/:id/certificates- Create a certificate for an assetPOST /certificates/crew- Create a new crew certificatePOST /certificates/types- Create a new certificate type (requires modules.certificates.create)POST /certificates/vessel- Create a new vessel certificatePOST /inventory/certificates- Create a certificate (Admin only)
UI app/assets/[id]/certificates/page-client.tsx, app/certificates/page.tsx
modules.certificates.edit - 6 API route(s), 0 UI file(s)
API routes
PUT /assets/components/:id/certificates/:certId- Update an asset certificatePUT /certificates/crew/:id- Update a crew certificatePUT /certificates/vessel/:id- Update a vessel certificatePATCH /inventory/certificates/:id- Update a certificate (Admin only)POST /inventory/certificates/:id/attachments- Attach a file to the certificate (Admin only)POST /inventory/certificates/:id/renew- Renew a certificate (Admin only)
modules.certificates.delete - 4 API route(s), 0 UI file(s)
API routes
DELETE /assets/components/:id/certificates/:certId- Delete an asset certificateDELETE /certificates/crew/:id- Delete a crew certificateDELETE /certificates/vessel/:id- Delete a vessel certificateDELETE /inventory/certificates/:id- Delete a certificate (Admin only)
Compliance (compliance)
Compliance status per vessel: the "Can sail?" status, blocking issues, expiring items, compliance snapshots.
| Action | Permission | What it allows | Enforcement |
|---|---|---|---|
| View | modules.compliance.view |
Open the Compliance pages and read their data. | API + UI - 6 routes |
| Edit | modules.compliance.edit |
Change existing Compliance records. | API - 2 routes |
modules.compliance.view - 6 API route(s), 1 UI file(s)
API routes
GET /compliance/blocking-issues- Get all vessels with blocking compliance issuesGET /compliance/can-sail- Check if vessel can sailGET /compliance/expiring- Get items expiring within specified daysGET /compliance/status- Get all compliance checks for a vesselGET /compliance/summary- Get vessel compliance summaryGET /reports/compliance.pdf- PM Compliance report (any of: view, view, view)
UI components/layout/sidebar.tsx
modules.compliance.edit - 2 API route(s), 0 UI file(s)
API routes
POST /compliance/evaluate-all- Trigger compliance evaluation for all vesselsPOST /compliance/evaluate/:vesselId- Trigger compliance evaluation for a specific vessel
Medic (medic)
Medical inventory: kits, stock, inspections, usage logs, analytics and per-vessel kit assignment.
| Action | Permission | What it allows | Enforcement |
|---|---|---|---|
| View | modules.medic.view |
Open the Medic pages and read their data. | API + UI - 20 routes |
| Create | modules.medic.create |
Create new Medic records. | API - 3 routes |
| Edit | modules.medic.edit |
Change existing Medic records. | API + UI - 32 routes |
| Delete | modules.medic.delete |
Delete Medic records. | API + UI - 2 routes |
modules.medic.view - 20 API route(s), 2 UI file(s)
API routes
GET /medic/activity-log- Get activity log for medical inventory (any of: view, view)GET /medic/analytics/expiring- Get expiring items (any of: view, view)GET /medic/analytics/summary- Get medical inventory summary/KPIs (any of: view, view)GET /medic/categories- Get all medical categories (any of: view, view)GET /medic/compliance/:vesselId- Get full MLC compliance dashboard for vessel (3-leg score) (any of: view, view)GET /medic/export/items.csv- Export items catalog to CSV (any of: view, view)GET /medic/export/stock.csv- Export stock to CSV (any of: view, view)GET /medic/inspections- Get inspections (any of: view, view)GET /medic/inspections/:id- Get inspection details (any of: view, view)GET /medic/items- Get medical items catalog (any of: view, view)GET /medic/items/:id- Get medical item details (any of: view, view)GET /medic/kits- Get all medical kits (any of: view, view)GET /medic/kits/:id- Get medical kit details with items (any of: view, view)GET /medic/kits/:id/compliance/:vesselId- Get kit compliance for vessel (any of: view, view)GET /medic/missing/:vesselId- Get missing items for vessel (all kits or specific kit) (any of: view, view)GET /medic/stock- Get medical stock for vessel (any of: view, view)GET /medic/stock/:id- Get stock item details (any of: view, view)GET /medic/usage- Get usage logs (any of: view, view)GET /medic/usage/export.csv- Export usage logs to CSV (any of: view, view)GET /medic/vessel-kits/:vesselId- Get kit assignments for a vessel (any of: view, view)
UI components/layout/sidebar.tsx, lib/mobile/modules.ts
modules.medic.create - 3 API route(s), 0 UI file(s)
API routes
POST /medic/categories- Create medical categoryPOST /medic/stock- Add stock itemPOST /medic/stock/logged- Add stock item with activity logging
modules.medic.edit - 32 API route(s), 1 UI file(s)
API routes
DELETE /medic/admin/wipe-all- FULL RESET: delete every medical record across all vessels, including the global catalog (items, categories, kits).DELETE /medic/admin/wipe-vessel/:vesselId- Delete ALL medical data for one vessel (stock, usage logs, inspections, kit assignments). Keeps the shared catalog.PUT /medic/categories/:id- Update medical categoryPOST /medic/import/items- Import items from JSON arrayPOST /medic/import/stock- Import stock from JSON arrayPOST /medic/inspections- Create inspectionPOST /medic/inspections/:id/sign-off- Sign off inspectionPOST /medic/kits- Create medical kitDELETE /medic/kits/:id- Delete medical kit — stock items are preserved, kit_id is cleared on linked stockPUT /medic/kits/:id- Update medical kitPOST /medic/kits/:id/items- Add item to kitDELETE /medic/kits/items/:kitItemId- Remove item from kitPOST /medic/seed/all- Seed all medical data (categories, items, kits) and stock for a vesselPOST /medic/seed/categories- Seed default medical categoriesPOST /medic/seed/categories- Seed default medical categoriesPOST /medic/seed/items- Seed sample medical items catalogPOST /medic/seed/kits- Seed default medical kitsPOST /medic/seed/kits- Seed default medical kitsPOST /medic/seed/stock- Seed demo medical stock for a vesselPUT /medic/stock/:id- Update stock itemPOST /medic/stock/:id/adjust- Adjust stock quantityPOST /medic/stock/:id/adjust/logged- Adjust stock quantity with activity loggingPOST /medic/stock/:id/assign-kit- Assign stock to a medical kitPOST /medic/stock/:id/consume- Consume stock (use for treatment) with activity loggingPUT /medic/stock/:id/logged- Update stock item with activity loggingPOST /medic/stock/:id/remove-kit- Remove stock from its medical kitPOST /medic/stock/:id/restock- Add quantity as a dated batch (merges into a matching-expiry batch or creates a new one)POST /medic/usage- Log medical supply usagePUT /medic/vessel-kits/:id- Update vessel kit assignment (interval, auto-schedule)POST /medic/vessel-kits/:vesselId/auto-populate- Auto-populate vessel kits from vessel MLC category (A/B/C)POST /medic/vessel-kits/:vesselId/kits- Assign a kit to a vesselDELETE /medic/vessel-kits/:vesselId/kits/:kitId- Remove a kit assignment from a vessel
UI app/medic/page.tsx
modules.medic.delete - 2 API route(s), 1 UI file(s)
API routes
DELETE /medic/categories/:id- Delete medical categoryDELETE /medic/stock/:id- Remove stock item
UI app/medic/page.tsx
Medical Items (medic-items)
The medical item master list. Enforced in the UI only.
| Action | Permission | What it allows | Enforcement |
|---|---|---|---|
| View | modules.medic-items.view |
Open the Medical Items pages and read their data. | UI only - 0 routes |
| Create | modules.medic-items.create |
Create new Medical Items records. | API + UI - 1 routes |
| Edit | modules.medic-items.edit |
Change existing Medical Items records. | API + UI - 1 routes |
| Delete | modules.medic-items.delete |
Delete Medical Items records. | API + UI - 1 routes |
modules.medic-items.view - 0 API route(s), 1 UI file(s)
UI app/medic/page.tsx
modules.medic-items.create - 1 API route(s), 1 UI file(s)
API routes
POST /medic/items- Create medical item
UI app/medic/page.tsx
modules.medic-items.edit - 1 API route(s), 1 UI file(s)
API routes
PUT /medic/items/:id- Update medical item
UI app/medic/page.tsx
modules.medic-items.delete - 1 API route(s), 1 UI file(s)
API routes
DELETE /medic/items/:id- Delete medical item
UI app/medic/page.tsx
🛒 Buy
Procurement (procurement)
Procurement documents: requisitions, RFQs, quotations and supplier comparison.
| Action | Permission | What it allows | Enforcement |
|---|---|---|---|
| View | modules.procurement.view |
Open the Procurement pages and read their data. | API + UI - 14 routes |
| Create | modules.procurement.create |
Create new Procurement records. | API - 3 routes |
| Edit | modules.procurement.edit |
Change existing Procurement records. | API - 12 routes |
| Delete | modules.procurement.delete |
Delete Procurement records. | API - 3 routes |
modules.procurement.view - 14 API route(s), 1 UI file(s)
API routes
GET /po(any of: view, view)GET /po/:id(any of: view, view)GET /po/create(any of: view, view)GET /po/vessel/:vesselId/stats(any of: view, view)GET /procurement/quotationsGET /procurement/quotations/:idGET /procurement/requisitionsGET /procurement/requisitions/:idGET /procurement/requisitions/:id/historyGET /procurement/rfqsGET /procurement/rfqs/:idGET /procurement/suppliers- List suppliers with filters and pagination (any of: view, view)GET /procurement/suppliers/template- Download supplier import template (.xlsx) (any of: view, view)GET /procurement/suppliers/with-locations- Suppliers with geocoded coordinates (Fleet Map supplier layer) (any of: view, view)
UI components/layout/sidebar.tsx
modules.procurement.create - 3 API route(s), 0 UI file(s)
API routes
POST /procurement/quotationsPOST /procurement/requisitionsPOST /procurement/rfqs
modules.procurement.edit - 12 API route(s), 0 UI file(s)
API routes
PUT /procurement/quotations/:idPOST /procurement/quotations/:id/awardPOST /procurement/quotations/:id/evaluatePOST /procurement/quotations/:id/rejectPOST /procurement/quotations/:id/shortlistPUT /procurement/requisitions/:idPOST /procurement/requisitions/:id/approvePOST /procurement/requisitions/:id/submitPUT /procurement/rfqs/:idPOST /procurement/rfqs/:id/cancelPOST /procurement/rfqs/:id/closePOST /procurement/rfqs/:id/issue
modules.procurement.delete - 3 API route(s), 0 UI file(s)
API routes
DELETE /procurement/quotations/:idDELETE /procurement/requisitions/:idDELETE /procurement/rfqs/:id
Purchase Orders (po)
Purchase orders: creation, items, split orders, supplier quotes/inquiries, approval workflow and budget control.
| Action | Permission | What it allows | Enforcement |
|---|---|---|---|
| View | modules.po.view |
Open the Purchase Orders pages and read their data. | API + UI - 4 routes |
| Create | modules.po.create |
Create new Purchase Orders records. | API - 1 routes |
| Edit | modules.po.edit |
Change existing Purchase Orders records. | API + UI - 30 routes |
| Approve | modules.po.approve |
Approve purchase orders at approval level 1. | API - 1 routes |
| Approve: level 2 | modules.po.approve-2 |
Approve purchase orders that need approval level 2 (higher value). | service rule (Enforced in the PO approval service (approval level).) - 0 routes |
| Approve: level 3 | modules.po.approve-3 |
Approve purchase orders that need approval level 3 (highest value). | service rule (Enforced in the PO approval service (approval level).) - 0 routes |
| Approve over budget | modules.po.approve-overspend |
Approve an order that takes a budget category past its tolerated overspend. | service rule (Enforced in the PO approval service (budget control).) - 0 routes |
| Delete | modules.po.delete |
Delete Purchase Orders records. | API - 1 routes |
modules.po.view - 4 API route(s), 1 UI file(s)
API routes
GET /po(any of: view, view)GET /po/:id(any of: view, view)GET /po/create(any of: view, view)GET /po/vessel/:vesselId/stats(any of: view, view)
UI components/dashboard/widget-registry.tsx
modules.po.create - 1 API route(s), 0 UI file(s)
API routes
POST /po
modules.po.edit - 30 API route(s), 2 UI file(s)
API routes
PUT /po-depth/:id/budget-category- Set which budget category the order is charged toPOST /po-depth/:id/confirm- Record the supplierPOST /po-depth/:id/hold- Put the order on holdPOST /po-depth/:id/inquiries- Ask more suppliers to quotePOST /po-depth/:id/paid- Mark the order as paid: it moves from committed to used budgetPOST /po-depth/:id/release- Release the order from holdPOST /po-depth/:id/revert- Move the order back a step, with a reasonPOST /po-depth/:id/select- Choose the supplier: its prices are copied onto the order linesPOST /po-depth/:id/snooze- Silence the late-delivery reminder until a datePOST /po-depth/:id/split- Split the order between suppliers: one order each, this one is closed as splitDELETE /po-depth/inquiries/:inquiryId- Remove a supplier from the inquiry listPUT /po-depth/inquiries/:inquiryId/quote- Record a supplierPOST /po-depth/inquiries/:inquiryId/send- Mark an inquiry as sent to the supplierPUT /po/:idPOST /po/:id/cancelPOST /po/:id/completePOST /po/:id/delivered/3rdpartyPOST /po/:id/delivered/vesselPOST /po/:id/delivered/warehousePOST /po/:id/in-transitPOST /po/:id/itemsDELETE /po/:id/items/:itemIdPUT /po/:id/items/:itemIdPOST /po/:id/items/:itemId/receivePOST /po/:id/orderPOST /po/:id/quote-receivedPOST /po/:id/receivePOST /po/:id/send-orderPOST /po/:id/send-rfqPOST /po/:id/submit
UI app/procurement/orders/[id]/page-client.tsx, components/procurement/po-depth-panels.tsx
modules.po.approve - 1 API route(s), 0 UI file(s)
API routes
POST /po/:id/approve
modules.po.delete - 1 API route(s), 0 UI file(s)
API routes
DELETE /po/:id
Suppliers (suppliers)
The supplier registry.
| Action | Permission | What it allows | Enforcement |
|---|---|---|---|
| View | modules.suppliers.view |
Open the Suppliers pages and read their data. | API + UI - 3 routes |
| Create | modules.suppliers.create |
Create new Suppliers records. | API - 2 routes |
| Edit | modules.suppliers.edit |
Change existing Suppliers records. | API + UI - 4 routes |
| Delete | modules.suppliers.delete |
Delete Suppliers records. | API - 1 routes |
modules.suppliers.view - 3 API route(s), 1 UI file(s)
API routes
GET /procurement/suppliers- List suppliers with filters and pagination (any of: view, view)GET /procurement/suppliers/template- Download supplier import template (.xlsx) (any of: view, view)GET /procurement/suppliers/with-locations- Suppliers with geocoded coordinates (Fleet Map supplier layer) (any of: view, view)
UI components/layout/sidebar.tsx
modules.suppliers.create - 2 API route(s), 0 UI file(s)
API routes
POST /procurement/suppliers- Create a supplier (Admin only)POST /procurement/suppliers/import- Import suppliers from Excel (.xlsx) (Admin only)
modules.suppliers.edit - 4 API route(s), 1 UI file(s)
API routes
PATCH /procurement/suppliers/:id- Update a supplier (Admin only)POST /procurement/suppliers/:id/attachments- Attach a file to the supplier (Admin only)POST /procurement/suppliers/:id/evaluate- Evaluate a supplier (Admin only): update status/rating/datePOST /procurement/suppliers/geocode-all- Geocode all suppliers without coordinates via Nominatim (Admin only, ~1s per supplier)
UI app/procurement/suppliers/page.tsx
modules.suppliers.delete - 1 API route(s), 0 UI file(s)
API routes
DELETE /procurement/suppliers/:id- Delete a supplier (Admin only)
Budget (budget)
Budgets and budget-vs-actual reporting.
| Action | Permission | What it allows | Enforcement |
|---|---|---|---|
| View | modules.budget.view |
Open the Budget pages and read their data. | API + UI - 9 routes |
| Edit | modules.budget.edit |
Change existing Budget records. | API - 2 routes |
modules.budget.view - 9 API route(s), 1 UI file(s)
API routes
GET /financial/budget/summary- Get budget summary by department (cost centers) (any of: view, view)GET /financial/budget/targets- Get budget targets for a vessel and year (any of: view, view)GET /financial/budget/vs-actual- Budget vs actual PO spend for a vessel and year (any of: view, view)GET /financial/cost-centers- Get all cost centers (any of: view, view)GET /financial/cost-centers/:code- Get cost center by code (any of: view, view)GET /financial/expense-categories- Get all expense categories (any of: view, view)GET /financial/expense-categories/:code- Get expense category by code (any of: view, view)GET /po-depth/budget/categories- The vessel (any of: .VIEW, view)GET /po-depth/budget/overview- Budget, paid (used), committed and available per category for a vessel and year (any of: .VIEW, view)
UI components/layout/sidebar.tsx
modules.budget.edit - 2 API route(s), 0 UI file(s)
API routes
POST /financial/budget/targets- Upsert a budget targetDELETE /financial/budget/targets/:id- Delete a budget target
Cost Centers (cost-centers)
Cost centers and expense categories (categorisation only - there is no accounting).
| Action | Permission | What it allows | Enforcement |
|---|---|---|---|
| View | modules.cost-centers.view |
Open the Cost Centers pages and read their data. | API + UI - 7 routes |
| Create | modules.cost-centers.create |
Create new Cost Centers records. | API - 2 routes |
| Edit | modules.cost-centers.edit |
Change existing Cost Centers records. | API - 2 routes |
| Delete | modules.cost-centers.delete |
Declared; not currently enforced. | not enforced - 0 routes |
modules.cost-centers.view - 7 API route(s), 1 UI file(s)
API routes
GET /financial/budget/summary- Get budget summary by department (cost centers) (any of: view, view)GET /financial/budget/targets- Get budget targets for a vessel and year (any of: view, view)GET /financial/budget/vs-actual- Budget vs actual PO spend for a vessel and year (any of: view, view)GET /financial/cost-centers- Get all cost centers (any of: view, view)GET /financial/cost-centers/:code- Get cost center by code (any of: view, view)GET /financial/expense-categories- Get all expense categories (any of: view, view)GET /financial/expense-categories/:code- Get expense category by code (any of: view, view)
UI components/layout/sidebar.tsx
modules.cost-centers.create - 2 API route(s), 0 UI file(s)
API routes
POST /financial/cost-centers- Create a cost centerPOST /financial/expense-categories- Create an expense category
modules.cost-centers.edit - 2 API route(s), 0 UI file(s)
API routes
PATCH /financial/cost-centers/:id- Update a cost centerPATCH /financial/expense-categories/:id- Update an expense category
⚙️ Operations
Maintenance (maintenance)
Work orders (create, start, sign out, correct, reopen), the overdue checker, completed history, work-order spares, and the Planned Maintenance (PM) schedules and triggers.
| Action | Permission | What it allows | Enforcement |
|---|---|---|---|
| View | modules.maintenance.view |
Open the Maintenance pages and read their data. | API + UI - 39 routes |
| Create | modules.maintenance.create |
Create work orders (also available through Assets: edit). | API - 3 routes |
| Edit | modules.maintenance.edit |
Edit work orders and PM schedules, start/release a job, link spares, trigger the overdue check, regenerate PM jobs. | API + UI - 51 routes |
| Complete | modules.maintenance.complete |
Sign out (complete) a work order. Ownership lock: if someone started the job, only that person can sign it out - everyone else must Release it first. An overdue job also needs an overdue reason. | API + UI - 2 routes |
| Correct completed work | modules.maintenance.correct |
Correct fields of an already-completed (signed) work order. | API + UI - 1 routes |
| Lock docking specifications | modules.maintenance.lock |
Lock docking specifications. | API + UI - 2 routes |
| Delete | modules.maintenance.delete |
Delete (soft-delete) a work order - it must be cancelled first - and delete PM schedules. | API + UI - 4 routes |
modules.maintenance.view - 39 API route(s), 10 UI file(s)
API routes
GET /docking/attachments/:entityId- Files attached to a project, or to an item or groupGET /docking/inquiries/:inquiryId/export- Download the Excel price inquiry sheet for one yardGET /docking/inquiries/:inquiryId/quotes- The quote entry grid for one yardGET /docking/projects- Docking / yard-stay projects for a vessel, with progress and cost roll-upGET /docking/projects/:id- One project with its items (PMS state and roll-ups folded in), summary and audit trailGET /docking/projects/:id/candidates- Open PMS jobs due by the end of the stay that can be pulled into the projectGET /docking/projects/:id/comparison- Quote comparison: one row per price detail, one column per yard, cheapest and dearest markedGET /docking/projects/:id/costs- Costs for the whole project, or for one item/group and everything under itGET /docking/projects/:id/events- Events logged in the project, or on one item/group and everything under itGET /docking/projects/:id/inquiries- Yards asked to quote, with what each one quoted in totalGET /docking/projects/:id/inquiry-preflight- Items that have no price detail yet (they would be left out of the inquiry)GET /docking/projects/:id/linkable-orders- Purchase orders on this vessel that can be linked to the projectGET /docking/projects/:id/orders- Purchase orders linked to the project, or to one item/group and everything under itGET /docking/projects/:id/overview- Flat overview of all working items with orders, events and the checks to run on themGET /docking/projects/:id/price-details- Price details for the whole project, or for one item/group and everything under itGET /docking/projects/:id/report.pdf- The specification / job sheets as a PDF to send to the yards (part = spec, jobs or all)GET /docking/projects/:id/shortlist/export- Download the job short list (open jobs and active events) as ExcelGET /docking/projects/:id/timeline- Schedule bars for the items, coloured by where each standsGET /docking/templates- Predefined docking jobs for a vessel (optionally for one piece of equipment)GET /maintenance/completed-this-month- Get count of completed jobs this month (from maintenance history)GET /maintenance/fleet-efficiency- Get fleet maintenance efficiency (% of active work orders that are not overdue)GET /maintenance/my-work-orders- Open work orders assigned to the current userGET /maintenance/overdue- Get all overdue work ordersGET /maintenance/overdue/count-by-vessel- Get overdue work order count grouped by vesselGET /maintenance/pm-schedules/:pmScheduleId/history- Get completed work order history for a PM schedule (any of: view, view)GET /maintenance/rules- Company-wide maintenance rules the sign-out form must follow (mandatory fields, ...)GET /maintenance/vessels/:vesselId/work-orders- List work orders by vesselGET /maintenance/work-orders- List all work orders (optionally filtered)GET /maintenance/work-orders/:id- Get a single work order by IDGET /maintenance/work-orders/:id/history- Get history/audit trail for a specific work order (any of: view, view)GET /maintenance/work-orders/:id/spares- List spare parts linked to a work orderGET /maintenance/work-orders/check-wo-number- Check if a WO number is uniqueGET /pm/schedules- List PM schedulesGET /pm/triggers/counter/:counterId- List triggers driven by a given counterGET /pm/triggers/schedule/:pmScheduleId- List the triggers of a maintenance planGET /pm/triggers/schedule/:pmScheduleId/evaluate- Evaluate a plan against its counters and calendarGET /postponed/folders(any of: view, view)GET /postponed/work-orders(any of: view, view)GET /reports/maintenance-schedule.pdf- Maintenance Schedule report (upcoming PM) (any of: view, view, view)
UI app/m/assets/[id]/page.tsx, app/m/page.tsx, app/m/work-orders/[id]/page.tsx, app/m/work-orders/page.tsx, app/operations/postponed-work-orders/page.tsx, components/auth/auth-debug.tsx, components/dashboard/widget-registry.tsx, components/layout/sidebar.tsx, lib/hooks/use-notification-inbox.ts, lib/mobile/modules.ts
modules.maintenance.create - 3 API route(s), 0 UI file(s)
API routes
POST /maintenance/work-orders/generate-number- Generate next WO number from sequence (any of: create, edit, edit)POST /pm/schedules- Create PM schedulePOST /pm/triggers- Add a trigger to a maintenance plan
modules.maintenance.edit - 51 API route(s), 3 UI file(s)
API routes
POST /docking/attachments/:entityId- Attach a file to a project, or to an item or groupDELETE /docking/attachments/file/:fileId- Remove an attached fileDELETE /docking/costs/:id- Remove a costDELETE /docking/events/:eventId- Remove an eventPATCH /docking/events/:eventId- Close or reopen an eventDELETE /docking/inquiries/:inquiryId- Remove a yard from the inquiryPATCH /docking/inquiries/:inquiryId- Update an inquiry: status, currency and exchange rate, days, start date, remarksPUT /docking/inquiries/:inquiryId/quotes- Save quoted prices typed into the gridPOST /docking/inquiries/:inquiryId/select- Choose this yard; optionally update prices from the quotation and book them as costsDELETE /docking/items/:itemId- Remove an itemPATCH /docking/items/:itemId- Edit an item: status, progress, dates, costs, contractor and the specification (unless locked)POST /docking/items/:itemId/events- Log an event (an unforeseen issue or a note) on an itemPOST /docking/items/:itemId/price-details- Add a price detail to an item or groupDELETE /docking/order-links/:linkId- Remove an order linkDELETE /docking/price-details/:id- Remove a price detailPATCH /docking/price-details/:id- Change a price detailPOST /docking/projects- Create a docking projectDELETE /docking/projects/:id- Delete a project that has not started, or a cancelled onePATCH /docking/projects/:id- Edit project detailsPOST /docking/projects/:id/copy- Start a new project (or a template) as a copy of this onePOST /docking/projects/:id/costs- Book a cost on the project or one of its itemsPOST /docking/projects/:id/inquiries- Add yards (suppliers, or a name) to the price inquiryPOST /docking/projects/:id/inquiries/import- Import a returned price inquiry sheet; dryRun=true only previewsPOST /docking/projects/:id/items- Add a group, spec or job itemPOST /docking/projects/:id/jobs- Pull PMS work orders into the project as job items (optionally grouped by SFI main group)POST /docking/projects/:id/orders- Link a purchase order to the project or one of its itemsPOST /docking/projects/:id/price-details/missing-totals- Give every item without a price detail aPOST /docking/projects/:id/shortlist/import- Import a returned short list; dryRun=true only previewsPOST /docking/projects/:id/status- Request inquiries, start, complete, cancel or reopen a projectPOST /docking/projects/:id/templates- Bring predefined jobs into a project (grouped by SFI, under a new group, or under an existing one)POST /docking/templates- Create a predefined docking jobDELETE /docking/templates/:id- Delete a predefined docking jobPATCH /docking/templates/:id- Change a predefined docking jobPOST /maintenance/overdue/check-now- Manually trigger overdue work order check (for testing)PATCH /maintenance/work-orders/:id- Update a work order fieldsPATCH /maintenance/work-orders/:id/release- Release an in-progress work order back to Open so another crew member can take it overPATCH /maintenance/work-orders/:id/reopen- Reopen a cancelled work order, or (superadmin only) a completed one — back to open statusPOST /maintenance/work-orders/:id/revoke- Revoke a completed work order (un-complete it). Superadmin only, within 30 days of completion.POST /maintenance/work-orders/:id/spares- Link spare parts to a work orderDELETE /maintenance/work-orders/:id/spares/:spareId- Unlink spare part from work orderPATCH /maintenance/work-orders/:id/spares/:spareId- Update spare part quantity on work orderPATCH /maintenance/work-orders/:id/start- Start a work order (claims ownership for the current user)POST /maintenance/work-orders/generate-number- Generate next WO number from sequence (any of: create, edit, edit)PATCH /pm/schedules/:id- Update PM schedulePOST /pm/schedules/:id/copy-to-multiple-vessels- Copy PM schedule to multiple vessels at oncePOST /pm/schedules/:id/copy-to-vessel- Copy PM schedule to another vesselPOST /pm/schedules/:id/instantiate- Instantiate work order from schedule and advance next duePOST /pm/schedules/:id/regenerate- Manually regenerate next work order for a PM schedule (uses today as completion date)POST /pm/schedules/sync- Sync PM schedules - generate work orders for schedules without active WOPATCH /pm/triggers/:id- Update a triggerPOST /reports/service- Create a new service report for an asset (any of: edit, edit)
UI app/docking/page.tsx, app/m/work-orders/[id]/page.tsx, components/assets/asset-detail-dialog.tsx
modules.maintenance.complete - 2 API route(s), 2 UI file(s)
API routes
PATCH /maintenance/work-orders/:id/complete- Complete a work orderPOST /maintenance/work-orders/:id/sign-out- Sign out a work order with all completion details
UI app/m/work-orders/[id]/page.tsx, app/m/work-orders/[id]/signout/page.tsx
modules.maintenance.correct - 1 API route(s), 1 UI file(s)
API routes
PATCH /maintenance/work-orders/:id/correct- Correct the sign-out of a completed work order (within 30 days, with a reason; audited)
UI components/maintenance/work-order-detail-floating-card.tsx
modules.maintenance.lock - 2 API route(s), 1 UI file(s)
API routes
POST /docking/items/:itemId/lock- Lock or unlock one item specificationPOST /docking/projects/:id/lock- Lock or unlock the whole specification (items added afterwards are variation orders)
UI app/docking/page.tsx
modules.maintenance.delete - 4 API route(s), 1 UI file(s)
API routes
DELETE /maintenance/work-orders/:id- Delete a work order (requires modules.maintenance.delete). Completed work orders cannot be deleted to preserve history.DELETE /maintenance/work-orders/wipe-all- DELETE ALL work orders for ALL vessels — superadmin + password confirmation (DANGEROUS!). Also removes each WO\DELETE /pm/schedules/:id- Delete PM schedule (and related work orders)DELETE /pm/triggers/:id- Remove a trigger
UI components/assets/asset-detail-dialog.tsx
Cargo Operations (cargo)
Cargo operations: shipments, manifests, locations, loading/discharge, reconciliation, documents.
| Action | Permission | What it allows | Enforcement |
|---|---|---|---|
| View | modules.cargo.view |
Open the Cargo Operations pages and read their data. | API + UI - 10 routes |
| Create | modules.cargo.create |
Create new Cargo Operations records. | API - 3 routes |
| Edit | modules.cargo.edit |
Change existing Cargo Operations records. | API - 8 routes |
| Delete | modules.cargo.delete |
Delete Cargo Operations records. | API - 3 routes |
modules.cargo.view - 10 API route(s), 1 UI file(s)
API routes
GET /cargo/locations- List cargo stowage locations with utilisationGET /cargo/manifests- List cargo manifests (voyages)GET /cargo/manifests/:id- Get a manifest with its consignment rowsGET /cargo/manifests/:id/manifest.pdf- Download the manifest as a PDFGET /cargo/manifests/onboard- Manifests currently carrying cargo (onboard)GET /cargo/onboard- What cargo is currently onboard (with per-location breakdown)GET /cargo/reconciliation- Planned-vs-actual cargo reconciliationGET /cargo/shipments- List cargo shipmentsGET /cargo/shipments/:id- Get a cargo shipmentGET /cargo/shipments/:id/operations- List load/discharge operations for a shipment
UI components/layout/sidebar.tsx
modules.cargo.create - 3 API route(s), 0 UI file(s)
API routes
POST /cargo/locations- Create a cargo stowage locationPOST /cargo/manifests- Create a cargo manifestPOST /cargo/shipments- Create a cargo shipment
modules.cargo.edit - 8 API route(s), 0 UI file(s)
API routes
PATCH /cargo/locations/:id- Update a cargo stowage locationPATCH /cargo/manifests/:id- Update a cargo manifestPOST /cargo/manifests/:id/discharge- Record discharge (date, port, signature) → completedPOST /cargo/manifests/:id/load- Record loading (date, port, signature) → onboardPATCH /cargo/manifests/:id/status- Advance a manifest through its lifecyclePATCH /cargo/shipments/:id- Update a cargo shipmentPOST /cargo/shipments/:id/operations- Record a load or discharge operationPATCH /cargo/shipments/:id/status- Advance a cargo shipment through its lifecycle
modules.cargo.delete - 3 API route(s), 0 UI file(s)
API routes
DELETE /cargo/locations/:id- Delete a cargo stowage locationDELETE /cargo/manifests/:id- Soft-delete a manifest and its rowsDELETE /cargo/shipments/:id- Soft-delete a cargo shipment
Running Hours (running-hours)
Running-hours counters and readings (the basis of hours-based PM) and AIS/telemetry estimates.
| Action | Permission | What it allows | Enforcement |
|---|---|---|---|
| View | modules.running-hours.view |
Open the Running Hours pages and read their data. | API + UI - 11 routes |
| Edit | modules.running-hours.edit |
Change existing Running Hours records. | API + UI - 6 routes |
modules.running-hours.view - 11 API route(s), 5 UI file(s)
API routes
GET /running-hours- Get all running countersGET /running-hours/:id- Get a specific counter by IDGET /running-hours/:id/ais-estimate- Recompute and return the AIS estimate for one counterGET /running-hours/:id/readings- Get reading history for a counterGET /running-hours/ais/estimates- AIS-derived running-hour estimatesGET /running-hours/ais/stale- Counters whose official reading has gone staleGET /running-hours/alerts- Get counters approaching warning/critical thresholdsGET /running-hours/asset/:assetId- Get all counters for a specific assetGET /running-hours/overview- Counters with vessel, usage rate, next due and trendGET /running-hours/summary- Get counter summary statisticsGET /running-hours/telemetry-sources- Get available telemetry sources for automatic counters
UI app/m/assets/[id]/page.tsx, app/m/running-hours/[id]/page.tsx, app/m/running-hours/page.tsx, components/layout/sidebar.tsx, lib/mobile/modules.ts
modules.running-hours.edit - 6 API route(s), 1 UI file(s)
API routes
POST /running-hours- Create a new running counterDELETE /running-hours/:id- Deactivate a counter (soft delete)PUT /running-hours/:id- Update a counterPOST /running-hours/readings- Record a new counter reading (manual update)POST /running-hours/readings/bulk- Record multiple readings at oncePOST /running-hours/sync/telemetry- Sync all automatic counters with telemetry for a vessel
UI app/m/running-hours/[id]/page.tsx
Postponed Work Orders (postponed)
Postponed work orders: folders of postponed jobs, resuming/moving them, and the rules on who may postpone what.
| Action | Permission | What it allows | Enforcement |
|---|---|---|---|
| View | modules.postponed.view |
Open the Postponed Work Orders pages and read their data. | API + UI - 2 routes |
| Approve | modules.postponed.approve |
Approve/decide postponed work orders and folders. | API - 6 routes |
| Postpone class jobs | modules.postponed.postpone-class |
Postpone jobs flagged as Class jobs (a user without it cannot). | service rule (Enforced in the postponement policy.) - 0 routes |
| Postpone critical jobs | modules.postponed.postpone-critical |
Postpone jobs flagged as Critical (also requires the company rule to allow critical postponements: Settings > Maintenance rules). | service rule (Enforced in the postponement policy.) - 0 routes |
| Postpone beyond the limit | modules.postponed.postpone-unlimited |
Not bound by the postponement limit (otherwise a job can only be pushed a set percentage of its interval past its due date). | service rule (Enforced in the postponement policy.) - 0 routes |
modules.postponed.view - 2 API route(s), 1 UI file(s)
API routes
GET /postponed/folders(any of: view, view)GET /postponed/work-orders(any of: view, view)
UI components/layout/sidebar.tsx
modules.postponed.approve - 6 API route(s), 0 UI file(s)
API routes
POST /postponed/foldersDELETE /postponed/folders/:idPATCH /postponed/folders/:idPOST /postponed/work-ordersPATCH /postponed/work-orders/:id/movePATCH /postponed/work-orders/:id/resume
History (history)
The Maintenance History pages (completed jobs per asset/vessel).
| Action | Permission | What it allows | Enforcement |
|---|---|---|---|
| View | modules.history.view |
Open the History pages and read their data. | API + UI - 10 routes |
| Export | modules.history.export |
Declared; not currently enforced. | not enforced - 0 routes |
modules.history.view - 10 API route(s), 2 UI file(s)
API routes
GET /assets/history/all- List maintenance history across all assets (filters & paging) (any of: view, view)GET /assets/history/analytics/cost-trends- Get maintenance cost trends over time (monthly aggregation) (any of: view, view)GET /assets/history/analytics/equipment-breakdown- Get maintenance breakdown by equipment type (any of: view, view)GET /assets/history/analytics/summary- Get maintenance summary statistics (any of: view, view)GET /assets/history/analytics/top-issues- Get top problem equipment by maintenance frequency (any of: view, view)GET /assets/history/export.csv- Export maintenance history as CSV (server-side, supports filters) (any of: view, view)GET /assets/history/export.xlsx- Export maintenance history as XLSX (server-side, supports filters) (any of: view, view)GET /maintenance/pm-schedules/:pmScheduleId/history- Get completed work order history for a PM schedule (any of: view, view)GET /maintenance/work-orders/:id/history- Get history/audit trail for a specific work order (any of: view, view)GET /reports/maintenance-history.pdf- Maintenance History report (completed work) (any of: view, view, view)
UI app/history/page.tsx, components/layout/sidebar.tsx
Alerts (alerts)
The alert feed (live alerts panel and the /alerts page): view, create system alerts, acknowledge/close.
| Action | Permission | What it allows | Enforcement |
|---|---|---|---|
| View | modules.alerts.view |
Open the Alerts pages and read their data. | API + UI - 3 routes |
| Edit | modules.alerts.edit |
Create system alerts through the API (used by system generators). | API - 1 routes |
| Acknowledge | modules.alerts.acknowledge |
Acknowledge and close alerts. | API + UI - 2 routes |
| Manage | modules.alerts.manage |
Alerts page export and management buttons. Enforced in the UI only. | UI only - 0 routes |
modules.alerts.view - 3 API route(s), 2 UI file(s)
API routes
GET /alerts- List alerts across the fleet (dashboard Live Alerts panel + full /alerts page)GET /alerts/count- Count alerts across the fleet (for the Live Alerts badge + /alerts stats)GET /alerts/vessel/:vesselId- List alerts by vessel
UI app/alerts/page.tsx, components/layout/sidebar.tsx
modules.alerts.edit - 1 API route(s), 0 UI file(s)
API routes
POST /alerts- Create a new alert
modules.alerts.acknowledge - 2 API route(s), 1 UI file(s)
API routes
PATCH /alerts/:id/ack- Acknowledge an alertPATCH /alerts/:id/close- Close an alert
UI app/alerts/page.tsx
modules.alerts.manage - 0 API route(s), 1 UI file(s)
UI app/alerts/page.tsx
📊 ReportsHub
Class Surveys (class-surveys)
Class surveys: surveys, findings, requirements/conditions of class, attachments, reports and KPIs.
| Action | Permission | What it allows | Enforcement |
|---|---|---|---|
| View | modules.class-surveys.view |
Open the Class Surveys pages and read their data. | API + UI - 20 routes |
| Create | modules.class-surveys.create |
Create new Class Surveys records. | API - 1 routes |
| Edit | modules.class-surveys.edit |
Change existing Class Surveys records. | API - 15 routes |
| Delete | modules.class-surveys.delete |
Delete Class Surveys records. | API - 1 routes |
modules.class-surveys.view - 20 API route(s), 1 UI file(s)
API routes
GET /class-surveysGET /class-surveys-v2/actions/:idGET /class-surveys-v2/actions/survey/:surveyIdGET /class-surveys-v2/auditGET /class-surveys-v2/recommendations/:idGET /class-surveys-v2/recommendations/survey/:surveyIdGET /class-surveys/:idGET /class-surveys/:id/full-reportGET /class-surveys/attachments/:idGET /class-surveys/attachments/survey/:surveyIdGET /class-surveys/findings/:idGET /class-surveys/findings/survey/:surveyIdGET /class-surveys/integrityGET /class-surveys/reports/due-soonGET /class-surveys/reports/fleet-matrixGET /class-surveys/reports/kpisGET /class-surveys/reports/overdueGET /class-surveys/requirements/:idGET /class-surveys/requirements/survey/:surveyIdGET /class-surveys/vessel/:vesselId/stats
UI components/layout/sidebar.tsx
modules.class-surveys.create - 1 API route(s), 0 UI file(s)
API routes
POST /class-surveys
modules.class-surveys.edit - 15 API route(s), 0 UI file(s)
API routes
POST /class-surveys-v2/actionsDELETE /class-surveys-v2/actions/:idPUT /class-surveys-v2/actions/:idPOST /class-surveys-v2/recommendationsDELETE /class-surveys-v2/recommendations/:idPUT /class-surveys-v2/recommendations/:idPUT /class-surveys/:idPOST /class-surveys/attachmentsDELETE /class-surveys/attachments/:idPOST /class-surveys/findingsDELETE /class-surveys/findings/:idPUT /class-surveys/findings/:idPOST /class-surveys/requirementsDELETE /class-surveys/requirements/:idPUT /class-surveys/requirements/:id
modules.class-surveys.delete - 1 API route(s), 0 UI file(s)
API routes
DELETE /class-surveys/:id
Voyage Reports (voyage-reports)
Voyage Reports pages. Enforced in the UI only.
| Action | Permission | What it allows | Enforcement |
|---|---|---|---|
| View | modules.voyage-reports.view |
Open the Voyage Reports pages and read their data. | not enforced - 0 routes |
| Create | modules.voyage-reports.create |
Enforced in the UI only (no API routes). | not enforced - 0 routes |
| Edit | modules.voyage-reports.edit |
Change existing Voyage Reports records. | not enforced - 0 routes |
| Export | modules.voyage-reports.export |
Export Voyage Reports data. | not enforced - 0 routes |
Documents (documents)
The document library: documents, versions, tags, per-document permissions, approval workflow and audit trail.
| Action | Permission | What it allows | Enforcement |
|---|---|---|---|
| View | modules.documents.view |
Open the Documents pages and read their data. | API + UI - 10 routes |
| Upload | modules.documents.upload |
Upload documents and new versions; edit a document's own fields. | API + UI - 6 routes |
| Edit | modules.documents.edit |
Manage a document: tags, per-document permissions, approval requests, mark-expired. | API - 6 routes |
| Delete | modules.documents.delete |
Delete a document. | API - 2 routes |
modules.documents.view - 10 API route(s), 1 UI file(s)
API routes
GET /documentsGET /documents/:idGET /documents/:id/auditGET /documents/:id/versionsPOST /documents/approvals/:approvalId/respondGET /documents/expiringGET /documents/statisticsGET /uploads/:id- Get file metadata by IDGET /uploads/list/:entityId- List files by entity ID (any of: view, view)GET /uploads/stats/storage- Get storage statistics
UI components/layout/sidebar.tsx
modules.documents.upload - 6 API route(s), 3 UI file(s)
API routes
POST /documentsPUT /documents/:idPOST /documents/:id/upload-versionPOST /documents/:id/versionsPOST /documents/uploadPOST /uploads/upload- Upload a file to local storage (any of: upload, edit)
UI app/m/qhse/page.tsx, components/qhse/incident-form.tsx, lib/api/uploads.ts
modules.documents.edit - 6 API route(s), 0 UI file(s)
API routes
POST /documents/:id/approvePOST /documents/:id/permissionsDELETE /documents/:id/permissions/:permissionIdDELETE /documents/:id/tagsPOST /documents/:id/tagsPOST /documents/mark-expired
modules.documents.delete - 2 API route(s), 0 UI file(s)
API routes
DELETE /documents/:idDELETE /uploads/:id- Delete a file
Reports (reports)
The Reports pages and the server-side generated PDFs/Excel exports.
| Action | Permission | What it allows | Enforcement |
|---|---|---|---|
| View | modules.reports.view |
Open the Reports pages and read their data. | API + UI - 16 routes |
| Export | modules.reports.export |
Declared; not currently enforced on its own. | not enforced - 0 routes |
modules.reports.view - 16 API route(s), 3 UI file(s)
API routes
GET /analytics/kpis/daily(any of: view, view)GET /analytics/risk-scores(any of: view, view)GET /reports/asset-data.pdf- Asset Data Report (dossier) for selected assets (any of: view, view)GET /reports/class-compliance.pdf- Class Compliance (PMS) report (any of: view, view)GET /reports/compliance.pdf- PM Compliance report (any of: view, view, view)GET /reports/exports/assets- Export assets/equipment to ExcelGET /reports/exports/crew- Export crew assignments to ExcelGET /reports/exports/maintenance-history- Export maintenance history to ExcelGET /reports/exports/overdue-work-orders- Export overdue work orders to ExcelGET /reports/exports/spare-parts- Export spare parts to ExcelGET /reports/exports/work-orders- Export work orders to ExcelGET /reports/maintenance-history.pdf- Maintenance History report (completed work) (any of: view, view, view)GET /reports/maintenance-schedule.pdf- Maintenance Schedule report (upcoming PM) (any of: view, view, view)GET /reports/service/:id- Get a specific service reportGET /reports/service/:id/pdf- Generate PDF for a service reportGET /reports/service/asset/:assetId- Get all service reports for an asset
UI app/reports/page.tsx, components/assets/asset-detail-dialog.tsx, components/layout/sidebar.tsx
Analytics (analytics)
The Analytics pages (KPI trends, risk scores).
| Action | Permission | What it allows | Enforcement |
|---|---|---|---|
| View | modules.analytics.view |
Open the Analytics pages and read their data. | API + UI - 2 routes |
modules.analytics.view - 2 API route(s), 1 UI file(s)
API routes
GET /analytics/kpis/daily(any of: view, view)GET /analytics/risk-scores(any of: view, view)
UI components/layout/sidebar.tsx
👥 Portal
User Dashboard (user-dashboard)
Each user's personal dashboard (widget grid) and its saved layout.
| Action | Permission | What it allows | Enforcement |
|---|---|---|---|
| View | modules.user-dashboard.view |
Open the User Dashboard pages and read their data. | API + UI - 3 routes |
modules.user-dashboard.view - 3 API route(s), 1 UI file(s)
API routes
DELETE /user-dashboard/layout- Reset the current userGET /user-dashboard/layout- Get the current userPUT /user-dashboard/layout- Save the current user
UI components/layout/sidebar.tsx
Messages (messages)
Messaging: channels, direct messages, read receipts.
| Action | Permission | What it allows | Enforcement |
|---|---|---|---|
| View | modules.messages.view |
Open the Messages pages and read their data. | API + UI - 11 routes |
| Send | modules.messages.send |
Send messages and create channels. | API - 10 routes |
| Delete | modules.messages.delete |
Delete messages. | API - 2 routes |
modules.messages.view - 11 API route(s), 2 UI file(s)
API routes
GET /channelsGET /channels/:channelId/messagesGET /channels/:idPOST /channels/:id/readGET /channels/:id/unread-countGET /channels/unread-countsGET /messages/:idPOST /messages/:id/readGET /messages/:id/statusPOST /messages/read-multipleGET /messages/search
UI components/layout/sidebar.tsx, lib/hooks/use-notification-inbox.ts
modules.messages.send - 10 API route(s), 0 UI file(s)
API routes
POST /channelsPOST /channels/:channelId/messagesPUT /channels/:idPOST /channels/:id/membersDELETE /channels/:id/members/:userIdPUT /channels/:id/members/:userId/rolePUT /messages/:idPOST /messages/:id/pinPOST /messages/:id/reactionsDELETE /messages/:id/reactions/:emoji
modules.messages.delete - 2 API route(s), 0 UI file(s)
API routes
DELETE /channels/:idDELETE /messages/:id
Users (users)
User accounts: list, create, edit, activate/deactivate, assign roles, reset/set passwords, avatars.
| Action | Permission | What it allows | Enforcement |
|---|---|---|---|
| View | modules.users.view |
Open the Users pages and read their data. | API + UI - 1 routes |
| Create | modules.users.create |
Create new Users records. | API + UI - 1 routes |
| Edit | modules.users.edit |
Change existing Users records. | API - 4 routes |
| Delete | modules.users.delete |
Delete Users records. | API - 1 routes |
modules.users.view - 1 API route(s), 3 UI file(s)
API routes
GET /users
UI app/users/page.tsx, components/auth/auth-debug.tsx, components/layout/sidebar.tsx
modules.users.create - 1 API route(s), 1 UI file(s)
API routes
POST /users
UI app/users/page.tsx
modules.users.edit - 4 API route(s), 0 UI file(s)
API routes
PATCH /users/:idDELETE /users/:id/avatarPOST /users/:id/avatarPATCH /users/:id/roles
modules.users.delete - 1 API route(s), 0 UI file(s)
API routes
DELETE /users/:id
Roles (roles)
Roles and their permission lists.
| Action | Permission | What it allows | Enforcement |
|---|---|---|---|
| View | modules.roles.view |
Open the Roles pages and read their data. | API + UI - 2 routes |
| Create | modules.roles.create |
Create new Roles records. | API - 1 routes |
| Edit | modules.roles.edit |
Change existing Roles records. | API - 2 routes |
| Delete | modules.roles.delete |
Delete Roles records. | API - 1 routes |
modules.roles.view - 2 API route(s), 3 UI file(s)
API routes
GET /rolesGET /roles/:id
UI components/auth/access-denied.tsx, components/auth/auth-debug.tsx, components/layout/sidebar.tsx
modules.roles.create - 1 API route(s), 0 UI file(s)
API routes
POST /roles
modules.roles.edit - 2 API route(s), 0 UI file(s)
API routes
PUT /roles/:idPOST /roles/update-user-counts
modules.roles.delete - 1 API route(s), 0 UI file(s)
API routes
DELETE /roles/:id
Vessel Access (vessel-access)
Viewing your own vessel grants. NOTE: granting/changing/revoking vessel access is superadmin-only (see "Superadmin-only").
| Action | Permission | What it allows | Enforcement |
|---|---|---|---|
| View | modules.vessel-access.view |
Open the Vessel Access pages and read their data. | API + UI - 6 routes |
| Manage | modules.vessel-access.manage |
Declared but not enforced: granting vessel access is superadmin-only. | not enforced - 0 routes |
modules.vessel-access.view - 6 API route(s), 1 UI file(s)
API routes
GET /vessel-access/audit- Get vessel access audit logs (SuperAdmin only)GET /vessel-access/can-access/:vesselId- Check if I can access a specific vesselGET /vessel-access/grants- Get all vessel access grants (SuperAdmin only)GET /vessel-access/grants/:id- Get vessel access grant by ID (SuperAdmin only)GET /vessel-access/my-grants- Get my vessel access grantsGET /vessel-access/my-vessels- Get vessel IDs I can access
UI components/layout/sidebar.tsx
Fleet Groups (fleet-groups)
Fleet groups (named sets of vessels) and their members.
| Action | Permission | What it allows | Enforcement |
|---|---|---|---|
| View | modules.fleet-groups.view |
Open the Fleet Groups pages and read their data. | API + UI - 4 routes |
| Create | modules.fleet-groups.create |
Create new Fleet Groups records. | API + UI - 1 routes |
| Edit | modules.fleet-groups.edit |
Change existing Fleet Groups records. | API + UI - 4 routes |
| Delete | modules.fleet-groups.delete |
Delete Fleet Groups records. | API + UI - 1 routes |
modules.fleet-groups.view - 4 API route(s), 2 UI file(s)
API routes
GET /fleet-groups(any of: view, view)GET /fleet-groups/:id(any of: view, view)GET /fleet-groups/:id/members(any of: view, view)GET /fleet-groups/:id/users(any of: view, view)
UI app/portal/vessel-access/page.tsx, components/layout/sidebar.tsx
modules.fleet-groups.create - 1 API route(s), 1 UI file(s)
API routes
POST /fleet-groups
UI app/portal/vessel-access/page.tsx
modules.fleet-groups.edit - 4 API route(s), 1 UI file(s)
API routes
DELETE /fleet-groups/:groupId/members/:memberIdPATCH /fleet-groups/:groupId/members/:memberIdPATCH /fleet-groups/:idPOST /fleet-groups/:id/members
UI app/portal/vessel-access/page.tsx
modules.fleet-groups.delete - 1 API route(s), 1 UI file(s)
API routes
DELETE /fleet-groups/:id
UI app/portal/vessel-access/page.tsx
Notifications (notifications)
The notification feed and delivery preferences.
| Action | Permission | What it allows | Enforcement |
|---|---|---|---|
| View | modules.notifications.view |
Open the Notifications pages and read their data. | API + UI - 5 routes |
| Manage | modules.notifications.manage |
Declared but not currently enforced. | not enforced - 0 routes |
modules.notifications.view - 5 API route(s), 2 UI file(s)
API routes
GET /notifications- Get notifications for the authenticated userPATCH /notifications/:id/acknowledge- Mark one of the caller\PATCH /notifications/:id/read- Mark one of the caller\POST /notifications/mark-all-read- Mark all of the caller\GET /notifications/unread-count- Get unread notifications count for the authenticated user
UI components/layout/sidebar.tsx, lib/hooks/use-notification-inbox.ts
AIVA Assistant (aiva)
AIVA, the AI assistant: open and use the chat, list providers/models. Its API keys and provider configuration stay superadmin-only.
| Action | Permission | What it allows | Enforcement |
|---|---|---|---|
| View | modules.aiva.view |
Open the AIVA Assistant pages and read their data. | API + UI - 9 routes |
modules.aiva.view - 9 API route(s), 2 UI file(s)
API routes
POST /ai/chat- Send a message to AI assistant (non-streaming)GET /ai/conversations- Get user conversation historyDELETE /ai/conversations/:id- Delete a conversationGET /ai/conversations/:id- Get a specific conversationGET /ai/providers- List all available AI providers with modelsGET /ai/providers/:id/models- Get models for a providerGET /ai/status- Get AI assistant status (enabled/disabled)GET /ai/user-preference- Get current user AI preferencePUT /ai/user-preference- Update current user AI preference
UI app/aiva/page.tsx, components/ai/ai-chat-widget.tsx
🛡️ QHSE
QHSE (qhse)
QHSE: incidents, inspections and findings, corrective actions, documents, risk assessments, NCRs.
| Action | Permission | What it allows | Enforcement |
|---|---|---|---|
| View | modules.qhse.view |
Open the QHSE pages and read their data. | API + UI - 36 routes |
| Create | modules.qhse.create |
Create new QHSE records. | API + UI - 8 routes |
| Edit | modules.qhse.edit |
Change existing QHSE records. | API - 17 routes |
| Delete | modules.qhse.delete |
Delete QHSE records. | API - 6 routes |
modules.qhse.view - 36 API route(s), 3 UI file(s)
API routes
GET /qhse-utils/integrity- Check QHSE data integrityGET /qhse/corrective-actions- Get all corrective actions for current vesselGET /qhse/corrective-actions/:id- Get a single corrective action by IDGET /qhse/corrective-actions/delta- Get corrective actions modified since timestampGET /qhse/corrective-actions/related/:type/:id- Get corrective actions for a related entityGET /qhse/corrective-actions/stats- Get corrective action statisticsGET /qhse/documents- Get all documents (vessel-specific + company-wide)GET /qhse/documents/:id- Get a single document by IDGET /qhse/documents/company-wide- Get only company-wide documentsGET /qhse/documents/delta- Get documents modified since timestampGET /qhse/documents/expiring-soon- Get documents expiring in next 30 daysGET /qhse/documents/stats- Get document statisticsGET /qhse/failure-reports- List failure reports for a vesselGET /qhse/failure-reports/:id- One failure report with its historyGET /qhse/failure-reports/stats- Open count, mean time to repair and out-of-production hours (optionally for one equipment)GET /qhse/incidents- Get all incidents for current vesselGET /qhse/incidents/:id- Get a single incident by IDGET /qhse/incidents/delta- Get incidents modified since timestamp (for offline sync)GET /qhse/incidents/stats- Get incident statistics for dashboardGET /qhse/inspection-findings/:id- Get a single finding by IDGET /qhse/inspection-findings/by-inspection/:inspectionId- Get all findings for an inspectionGET /qhse/inspection-findings/by-vessel- Get all findings for a vesselGET /qhse/inspection-findings/inspection/:inspectionId/pdf- Generate PDF report for inspection findingsGET /qhse/inspection-findings/stats/inspection/:inspectionId- Get statistics for an inspectionGET /qhse/inspection-findings/stats/vessel- Get statistics for a vesselGET /qhse/inspections- Get all inspections for current vesselGET /qhse/inspections/:id- Get a single inspection by IDGET /qhse/inspections/delta- Get inspections modified since timestampGET /qhse/inspections/stats- Get inspection statisticsGET /qhse/ncr- List non-conformance reports for a vesselGET /qhse/ncr/:id- One NCR with its historyGET /qhse/ncr/stats- Open / overdue counts and a breakdown by status and typeGET /qhse/risk-assessments- Get all risk assessments for current vesselGET /qhse/risk-assessments/:id- Get a single risk assessment by IDGET /qhse/risk-assessments/delta- Get risk assessments modified since timestampGET /qhse/risk-assessments/stats- Get risk assessment statistics
UI app/m/qhse/page.tsx, components/layout/sidebar.tsx, lib/mobile/modules.ts
modules.qhse.create - 8 API route(s), 1 UI file(s)
API routes
POST /qhse/corrective-actions- Create a new corrective actionPOST /qhse/documents- Create a new QHSE documentPOST /qhse/failure-reports- Start a failure report (as a draft)POST /qhse/incidents- Create a new incident reportPOST /qhse/inspection-findings- Create a new inspection findingPOST /qhse/inspections- Create a new inspection/checklistPOST /qhse/ncr- Raise a supplier or manual NCR (the others are created from maintenance data)POST /qhse/risk-assessments- Create a new risk assessment
UI app/m/qhse/page.tsx
modules.qhse.edit - 17 API route(s), 0 UI file(s)
API routes
PUT /qhse/corrective-actions/:id- Update a corrective actionPOST /qhse/corrective-actions/bulk- Bulk upsert corrective actionsPUT /qhse/documents/:id- Update a documentPOST /qhse/documents/bulk- Bulk upsert documents (server wins for policy docs)PATCH /qhse/failure-reports/:id- Edit a failure report that is not closedPOST /qhse/failure-reports/:id/status- Move a failure report along its lifecyclePUT /qhse/incidents/:id- Update an incidentPOST /qhse/incidents/bulk- Bulk upsert incidents (for offline sync)PATCH /qhse/inspection-findings/:id- Update a findingPUT /qhse/inspections/:id- Update an inspectionPOST /qhse/inspections/:id/signoff- Sign off an inspectionPOST /qhse/inspections/bulk- Bulk upsert inspectionsPATCH /qhse/ncr/:id- Edit the text of an open NCRPOST /qhse/ncr/:id/status- Move an NCR along its lifecycle (report / handle / close / escalate)POST /qhse/ncr/scan- Run the automatic NCR scan now (it also runs every hour)PUT /qhse/risk-assessments/:id- Update a risk assessmentPOST /qhse/risk-assessments/bulk- Bulk upsert risk assessments
modules.qhse.delete - 6 API route(s), 0 UI file(s)
API routes
DELETE /qhse/corrective-actions/:id- Delete a corrective actionDELETE /qhse/documents/:id- Delete a documentDELETE /qhse/incidents/:id- Delete an incidentDELETE /qhse/inspection-findings/:id- Delete a findingDELETE /qhse/inspections/:id- Delete an inspectionDELETE /qhse/risk-assessments/:id- Delete a risk assessment
⚡ Admin
Admin Settings (settings)
Admin Settings: company profile, email/SMTP, sequences (WO/PO/spare), maintenance & procurement rules, API configuration, diagnostics, database/replication/tracking admin pages.
| Action | Permission | What it allows | Enforcement |
|---|---|---|---|
| View | modules.settings.view |
Open the Admin Settings pages and read system diagnostics (health details, licence details, replication/queue status, company profile). | API + UI - 26 routes |
| Edit | modules.settings.edit |
Change settings and operate admin tools: SMTP/email test and sending, sequences, API/tracking/replication/updates configuration, grid views, demo data, database admin, error logs. | API + UI - 51 routes |
modules.settings.view - 26 API route(s), 2 UI file(s)
API routes
GET /db/connection-status- Get current database connection statusGET /health/detailsGET /license/details- Full license details (customer, expiry, last verification)GET /queue/metricsGET /replication/authority- Get all authority rules (bidirectional ownership model)GET /replication/authority/:entityType- Get authority matrix for an entity typeGET /replication/health/vessels/:vesselId- Get replication health for a vesselGET /settings/company-profile- Get the company profile used on document headers (manifests, reports)GET /settings/grid-views- List grid views for a scope. If ownerUserId provided, returns user views and shared viewsGET /settings/layout-edit- Get whether layout edit mode is enabled globallyGET /settings/maintenance-rules- Get the company-wide maintenance rules (mandatory sign-out fields, ...)GET /settings/page-layout- Get saved page layout for a scope (e.g., /codes)GET /settings/page-layouts- List all saved page layoutsGET /settings/po-sequence- Get Purchase Order number sequence settings (optionally per-vessel)GET /settings/procurement-rules- Get the company-wide procurement rules (approval separation, overspend control, ...)GET /settings/spare-sequence- Get Spare Part number sequence settings (optionally per-vessel)GET /settings/spare-sequence/all-vessels- Get all per-vessel Spare Part sequencesGET /settings/spare-sequence/check-available/:spareNumber- Check if a spare part number is available (not already used)GET /settings/spare-sequence/check/:vesselId- Check if a vessel has Spare Part sequence configuredGET /settings/spare-sequence/usage-history- Get usage history of spare part numbersGET /settings/spare-sequence/vessels-status- Get all vessels with their Spare Part sequence configuration statusGET /settings/voyage-sequence- Get the voyage (cargo manifest) numbering sequenceGET /settings/wo-sequence- Get Work Order number sequence settings (optionally per-vessel)GET /settings/wo-sequence/all-vessels- Get all per-vessel WO sequencesGET /settings/wo-sequence/check/:vesselId- Check if a vessel has WO sequence configuredGET /settings/wo-sequence/vessels-status- Get all vessels with their WO sequence configuration status
UI app/admin/settings/page.tsx, components/layout/sidebar.tsx
modules.settings.edit - 51 API route(s), 4 UI file(s)
API routes
POST /api/sync/pushGET /db/asset-value-checkPOST /email/alerts/sendGET /email/alerts/settingsPUT /email/alerts/settingsGET /email/alerts/settings/:alertTypePOST /email/alerts/settings/:alertType/toggleGET /email/alerts/statisticsGET /email/alerts/templatesPOST /email/alerts/templatesDELETE /email/alerts/templates/:idGET /email/alerts/templates/:idPUT /email/alerts/templates/:idPOST /email/alerts/templates/:id/clonePOST /email/alerts/test/:alertTypePOST /email/cache/clearGET /email/configsPOST /email/configsDELETE /email/configs/:idGET /email/configs/:idPUT /email/configs/:idGET /email/configs/default/getPOST /email/sendPOST /email/testGET /settings/api-config- Get API configuration (MyShipTracking, etc.). Keys are never returned - see the *Set flags.PATCH /settings/company-profile- Update the company profile (Admin only)PATCH /settings/company-theme- Save company custom theme (Admin only)POST /settings/compliance/evaluate-all- Run compliance evaluation for all vesselsGET /settings/email- Get email settings (SMTP host/user/recipients). Password is never returned - see smtpPassSet.PATCH /settings/email- Update email settings. Omit/blank/masked smtpPass leaves it unchanged; null clears it.POST /settings/email/test- Send test email to verify SMTP configurationPATCH /settings/grid-views- Upsert a grid view (columns with widths/visibility). Use isShared to allow others to use it.POST /settings/grid-views/delete- Delete a grid view by name/scope/owner (only owner or admin should do this – add auth if needed)PATCH /settings/maintenance-rules- Update the company-wide maintenance rules (any subset)PATCH /settings/po-sequence- Update Purchase Order number sequence settings (global or per-vessel via body.vesselId)PATCH /settings/procurement-rules- Update the company-wide procurement rules (any subset)POST /settings/seed/ports- Seed demo world ports (pass ?dryRun=true to preview without writing)PATCH /settings/spare-sequence- Update Spare Part number sequence settings (global or per-vessel via body.vesselId)POST /settings/spare-sequence/init-defaults- Initialize default Spare Part sequences for all vessels that do not have one configuredPOST /settings/spare-sequence/reset- Reset Spare Part sequence to specified value (global or per-vessel)POST /settings/spare-sequence/reset-all- Reset ALL Spare Part sequences to 1PATCH /settings/voyage-sequence- Update the voyage numbering sequencePATCH /settings/wo-sequence- Update Work Order number sequence settings (global or per-vessel via body.vesselId)POST /settings/wo-sequence/create-default/:vesselId- Create default WO sequence for a vessel (WO-0001 format)POST /settings/wo-sequence/reset- Reset WO sequence to specified value (global or per-vessel)POST /settings/wo-sequence/reset-all- Reset all WO sequences (global + all vessels) to 1POST /telemetry/simulate/:vesselId- Start telemetry simulation for a vesselPOST /telemetry/simulate/:vesselId/stop- Stop telemetry simulation for a vesselPOST /tracking/refresh- Refresh AISstream subscription (MMSI list)POST /voyages/ports/registry/apply-bundled- Install the port registry bundled with this release (adds/updates, keeps user edits)POST /voyages/ports/registry/update-online- Download the latest UN/LOCODE + World Port Index and apply them (needs internet)
UI app/admin/settings/page.tsx, app/settings/page.tsx, components/settings/maintenance-rules-panel.tsx, components/settings/procurement-rules-panel.tsx
Audit Log (audit-log)
The unified Audit Log (who changed what, with before/after).
| Action | Permission | What it allows | Enforcement |
|---|---|---|---|
| View | modules.audit-log.view |
Open the Audit Log pages and read their data. | API + UI - 4 routes |
| Export | modules.audit-log.export |
Export the audit log. Declared; the export is gated in the UI only. | not enforced - 0 routes |
modules.audit-log.view - 4 API route(s), 1 UI file(s)
API routes
GET /audit/entity-history- Get audit history for a specific entityGET /audit/entity-types- Get distinct entity types from audit logGET /audit/logs- Get audit logs with filteringGET /audit/summary- Get audit summary statistics
UI components/layout/sidebar.tsx
Developer Console (dev_console)
The read-only database console (queries, schema, health). A SELECT can read any table, so treat as a trusted grant. Write/maintenance functions in the console are superadmin-only.
| Action | Permission | What it allows | Enforcement |
|---|---|---|---|
| View | modules.dev_console.view |
Open the Developer Console pages and read their data. | API + UI - 4 routes |
modules.dev_console.view - 4 API route(s), 1 UI file(s)
API routes
GET /dev-console/health- Database health: size, biggest tables, dead tuples, active queries, caches, WAL slotsPOST /dev-console/query- Run a read-only SQL query (SELECT/WITH/EXPLAIN/SHOW). Enforced READ ONLY + timeout + row cap.GET /dev-console/schema- List all tables with row estimates and sizesGET /dev-console/schema/:table- Describe one table: columns, indexes, foreign keys
UI app/admin/settings/page.tsx
Debug Terminal (debug_terminal)
Access live system logs. Standalone permission (not tied to a module's view/edit).
GET /logs/buffer
Enforcement: API; UI: -
5. Rules enforced in code
These are behaviours attached to a permission that you cannot see from the route list.
Work orders (Maintenance)
- Ownership lock: starting a job records who started it. Only that person can sign it out (maintenance.complete); another user must Release it first, then start it themselves. Jobs that were never started are not locked.
- Sign-out identity: the "signed by" name always comes from the logged-in user, never from the request.
- Overdue: signing out an overdue job requires an overdue reason, which is written to the work-order history.
- Completed is locked: a completed work order cannot be moved back by a status update. Correcting it needs maintenance.correct; reopening or revoking a completed job is superadmin only (reopening a cancelled job needs maintenance.edit).
- Status changes: a work order can only follow the allowed state machine (draft → open → in progress → completed; cancelled/postponed branches). "Completed" is only reachable through sign-out.
- Permit to work: a job flagged "permit required" cannot be started until its permit number is entered on the work order.
- Deleting: a work order must be cancelled before it can be deleted; deletion is a soft delete.
Assets - Delete vs scrap: an asset with any work order or maintenance history cannot be deleted - it can only be scrapped (needs a reason, at least 5 characters). Scrapping and restoring are written to the asset change log. A scrapped asset cannot receive new work orders. An asset that still has sub-components cannot be deleted. - Running hours cannot be lowered or set negative unless the change is explicitly confirmed (a replaced hour-meter); every change is logged. - SFI codes are unique per vessel; the parent is derived from the code only when the code itself changes.
Purchase orders
- Each order needs an approval level decided by its value against the approval thresholds (level 1, 2 or 3). A user can approve up to the level they hold: po.approve = level 1, po.approve-2 = level 2, po.approve-3 = level 3 (holding a higher level covers the lower ones). The superadmin approves at any level.
- po.approve-overspend is additionally required to approve an order that takes a budget category beyond the tolerated overspend (Settings > Procurement rules).
- Segregation of duties and "had inquiries" rules apply per the procurement rules in Settings.
Postponed work orders
- Postponing a Class job needs postponed.postpone-class; a Critical job needs postponed.postpone-critical and the company rule must allow postponing critical jobs (Settings > Maintenance rules).
- A limited right can only push a job a set percentage of its interval past its due date; postponed.postpone-unlimited is not bound by that limit. The superadmin is never restricted.
Crew - Hours of rest
- crew.rest-own lets a crew member work with their own hours of rest without being able to see the rest of the crew; rest-edit fills in anyone's; rest-approve signs records off.
Documents - A document belongs to a vessel through what it is attached to (the vessel, a piece of equipment, a work order, a crew member). Users see company-wide documents plus those of their vessels. Approving a document can only be done by the approver named on the request.
Vessel access and fleet groups
- A grant (or fleet-group membership) means access to the vessel; denied blocks it, overriding a fleet group. Grants can expire.
- Record ids in a request (path, body, even nested or in the query string of a write) are traced to the vessel that owns the record, so another vessel's record is refused even when the request never names a vessel. A record that belongs to two vessels (a transfer, a crew member's current/planned vessel) is allowed if either is accessible.
Replication / relay endpoints between vessel and office instances are authenticated with a shared node secret, not with user permissions.
6. Superadmin-only
These routes check for the reserved superadmin role - no ticked permission grants them. They are the highest-risk functions and deliberately cannot be delegated.
168 routes in 21 areas:
/ai - 8 route(s)
DELETE /ai/api-key- Clear AI API key (superadmin only)GET /ai/provider-configs- Get all provider configs (admin)POST /ai/provider-configs- Create provider config (admin)DELETE /ai/provider-configs/:provider- Delete provider config (superadmin)PUT /ai/provider-configs/:provider- Update provider config (admin)GET /ai/settings- Get AI settings (admin only)PUT /ai/settings- Update AI settings (admin only)POST /ai/test-connection- Test AI API connection
/auth - 4 route(s)
DELETE /auth/sessionsGET /auth/sessionsGET /auth/sessions/:idDELETE /auth/sessions/older-than/:days
/db - 26 route(s)
POST /db/apply- Apply new database connection (hot reload - superadmin only)GET /db/check-schema- Check if vessels table has all required columns (superadmin only)GET /db/check-vessels- Check vessel count in current database (superadmin only)POST /db/clone- Clone database (PostgreSQL, superadmin only)POST /db/clone-database- [REMOVED] Never copied data on Postgres — use /db/clone (superadmin only)GET /db/config- Get current DB config (superadmin only)POST /db/configure- Configure database connection (superadmin only)POST /db/create-postgres-database- [REMOVED] Use migrations + manual CREATE DATABASE instead (superadmin only)POST /db/create-tables- Create missing tables (superadmin only)POST /db/execute-sql- Execute raw SQL (superadmin only — DANGEROUS, disabled in production)POST /db/get-schema-info- Get schema information from current database (superadmin only)GET /db/info- Get database server information (superadmin only)POST /db/list-databases- List all databases on current server (superadmin only)GET /db/list-databases-and-connection- List all databases and current connection (superadmin only)GET /db/list-databases-public- List all databases on current server (superadmin only)POST /db/run-migration- [REMOVED] UsePOST /db/save-connection- Save database connection after deployment (superadmin only)DELETE /db/saved-connection/:nameGET /db/saved-connectionsPOST /db/seed-minimalPOST /db/seed-superadmin- [REMOVED] Was SQL Server-only T-SQL, never worked against Postgres (superadmin only)POST /db/sync-schema- [REMOVED] Use TypeORM migrations instead (superadmin only)GET /db/system-folderPOST /db/system-folderPOST /db/test- Test database connection (superadmin only)POST /db/use-connection
/demo-data - 1 route(s)
GET /demo-data/status- Demo dataset status and row counts (superadmin only)
/dev-console - 2 route(s)
POST /dev-console/execute- Execute arbitrary write/DDL SQL (superadmin only — DANGEROUS)POST /dev-console/maintenance- Run a curated maintenance action (superadmin only)
/diagnostics - 3 route(s)
GET /diagnostics/license- Get real license status (admin only)GET /diagnostics/redis- Get Redis connection and statistics (admin only)GET /diagnostics/storage- Get file storage statistics (admin only)
/license - 1 route(s)
POST /license/activate- Activate a license key (superadmin only)
/logs - 7 route(s)
GET /logs- Get logs for a specific dateDELETE /logs/clear- Clear all log files (superadmin only)DELETE /logs/file/:date- Delete a specific log file by date (superadmin only)GET /logs/files- Get list of available log filesDELETE /logs/old/:days- Delete log files older than X days (superadmin only)GET /logs/recent- Get recent logs from todayGET /logs/stats- Get log statistics
/public - 6 route(s)
GET /public/rolesPOST /public/rolesDELETE /public/roles/:idGET /public/roles/:idPUT /public/roles/:idPOST /public/roles/update-user-counts
/qhse-utils - 2 route(s)
POST /qhse-utils/clear- Clear all QHSE data for a vessel — superadmin + password confirmation (hard delete)POST /qhse-utils/seed- Seed sample QHSE data for a vessel (dev/admin only)
/queue - 4 route(s)
GET /queue/email/jobsGET /queue/email/statusPOST /queue/email/testGET /queue/status
/replication - 32 route(s)
GET /replication/changes- Get recent change log entriesPOST /replication/changes/distribute- Distribute pending changes to vessel queuesPOST /replication/distribute- Manually trigger distributionGET /replication/export/:vesselId- Export a vessel for offline installation (SuperAdmin only)GET /replication/export/preview/:vesselId- Get export preview for a vessel (SuperAdmin only)GET /replication/health- Get replication health summaryGET /replication/health/nodes- Get health metrics for all nodesGET /replication/health/nodes/:nodeId- Get health metrics for a specific nodePOST /replication/import- Import a vessel export file (SuperAdmin only)POST /replication/import/validate- Validate an import file without applying (SuperAdmin only)POST /replication/inbound/process- Process pending inbound queue itemsGET /replication/nodes- Get all registered vessel nodesPOST /replication/nodes/:nodeId/activate- Process vessel activation acknowledgmentPUT /replication/nodes/:nodeId/enable-sync- Enable sync for a vessel (any status except decommissioned)POST /replication/nodes/:nodeId/package- Create incremental package for a vesselGET /replication/nodes/:nodeId/packages- Get pending packages for a vesselPOST /replication/nodes/:nodeId/provision- Generate provisioning package for a vesselGET /replication/nodes/:nodeId/provision/download- Download provisioning package as JSON filePUT /replication/nodes/:nodeId/suspend- Suspend sync for a vesselPOST /replication/nodes/register- Register a vessel for replicationGET /replication/outbound- Get outbound queue items per vesselPUT /replication/packages/:packageId/sent- Mark a package as sentGET /replication/packages/stats- Get package statisticsPOST /replication/pairing/apply- Apply officeGET /replication/pairing/status- This installGET /replication/queue- Get all change log itemsPUT /replication/relay/mode- ChoosePOST /replication/relay/register- Manually (re)trigger relay registration nowGET /replication/relay/status- Get this install\GET /replication/settings- Get replication settingsPUT /replication/settings/interval- Set distribution interval in secondsGET /replication/status- Get overall replication status
/seeds - 22 route(s)
POST /seeds/alerts- Seed sample alerts - to specific vessel or distributed across allPOST /seeds/backfill-due-date- Backfill dueDate from scheduledDate where missingPOST /seeds/certificate-types- Seed real-world maritime certificate types (STCW, SOLAS, MARPOL, ISM Code)POST /seeds/cleanup-orphans- Delete dangling Core PMS records for a vessel (spares preserved) — superadmin + passwordPOST /seeds/cleanup-spare-locations-orphans- Delete spare_locations with vessel_id not in vessels (orphan folders) — superadmin + passwordPOST /seeds/codes-defaults- Ensure codes schema and seed default types/values (idempotent)POST /seeds/demo-certificates- Seed demo vessel certificates for a vessel (uses existing certificate types)POST /seeds/demo-certificates/clear- Remove all vessel certificates for a vessel + dependent records — superadmin + passwordPOST /seeds/drop-legacy-workorders- Drop legacy work_orders table if it existsPOST /seeds/ensure-all-fks-indexes- Clean orphans and add DB-level FKs + indexes (idempotent, PostgreSQL)POST /seeds/ensure-asset-wo-schema- Ensure asset_work_orders table has all required columns (idempotent)POST /seeds/ensure-catalogs- Ensure catalogs table (catalog_items), indexes, and FK to suppliers (idempotent, PostgreSQL)POST /seeds/ensure-spare-locations-fks- Clean invalid parentId in spare_locations and add DB-level FKs (idempotent)POST /seeds/ensure-superadmin- Ensure SuperAdmin user exists (idempotent, superadmin only). First-boot bootstrap happens automatically at startup.POST /seeds/fix-catalog-imports-timestamp- Fix catalog_imports.importedAt default value for PostgreSQLPOST /seeds/import-workorders- Import work orders into asset_work_orders with valid assetId/vesselId mappingPOST /seeds/migrate-legacy-workorders- Migrate legacy work_orders into asset_work_orders and drop legacy tablePOST /seeds/random-workorders- Seed random work orders - to specific vessel or distributed across allGET /seeds/random-workorders/stream- Seed random work orders with SSE progress streaming (admin / superadmin only)POST /seeds/stock-prices- Add random prices to all stock items that have no pricePOST /seeds/workorders- Seed sample work orders for all active vesselsPOST /seeds/world-ports- Seed 150+ major world ports with UN/LOCODE, coordinates, timezone, and characteristics
/server - 3 route(s)
GET /server/active-users- Currently connected users (superadmin)POST /server/backup- Trigger database backup (superadmin)GET /server/sync-status- Cloud sync health status (superadmin)
/settings - 6 route(s)
PATCH /settings/api-config- Update API configuration (SuperAdmin only). Omit/blank/masked keys leave them unchanged; null clears.PATCH /settings/base-currency- Set the system base currency (SuperAdmin only)POST /settings/layout-edit- Set layout edit mode globally (true/false)POST /settings/page-layout- Save page layout for a scopePOST /settings/seed/compliance-audit-voyages- Seed demo data for compliance, audit logs, and voyagesPOST /settings/system/mark-initialized- Mark system as initialized (superadmin only)
/support - 11 route(s)
GET /support/admin/announcements- Get all announcements (admin only)POST /support/admin/announcements- Create announcement (admin only)DELETE /support/admin/announcements/:id- Delete announcement (admin only)GET /support/admin/announcements/:id- Get announcement by ID (admin only)PUT /support/admin/announcements/:id- Update announcement (admin only)GET /support/admin/changelog- Get all changelog entries (admin only)POST /support/admin/changelog- Create changelog entry (admin only)DELETE /support/admin/changelog/:id- Delete changelog entry (admin only)GET /support/admin/changelog/:id- Get changelog entry by ID (admin only)PUT /support/admin/changelog/:id- Update changelog entry (admin only)POST /support/admin/changelog/seed- Seed changelog from hardcoded entries (admin only)
/sync-admin - 14 route(s)
GET /sync-admin/alerts- Get sync alerts (failed imports, exports, silent vessels)PUT /sync-admin/alerts/:id/acknowledge- Acknowledge an alertPUT /sync-admin/alerts/:id/resolve- Resolve an alertGET /sync-admin/config- Get sync configuration (folders, encryption, schedule)PUT /sync-admin/config- Update sync configuration (superadmin only)GET /sync-admin/conflicts- List recent conflict resolutions for auditPOST /sync-admin/import/force- Force vessel-side import scan nowGET /sync-admin/overview- Aggregated sync stats for dashboardGET /sync-admin/vessels- List all vessels with sync status (registered and unregistered)POST /sync-admin/vessels/:nodeId/force-send- Force send all pending packages to a vessel nowGET /sync-admin/vessels/:nodeId/secret- Reveal node decrypt key (superadmin only, for debugging)PUT /sync-admin/vessels/:nodeId/sync-enabled- Enable or disable sync for a vesselPUT /sync-admin/vessels/:nodeId/transport- Update vessel transport config (email, API URL)POST /sync-admin/vessels/:vesselId/activate- Register and activate sync for a vessel (one-click setup)
/system - 6 route(s)
GET /system/error-logsGET /system/performancePOST /system/update/check- Force an immediate release check (bypasses 6h cache)GET /system/update/history- Update attempt history (newest first)GET /system/update/status- Current version vs latest available releasePOST /system/update/trigger- Trigger an update via the Update Agent (superadmin only)
/users - 2 route(s)
PATCH /users/:id/passwordPOST /users/:id/reset-password
/vessel-access - 3 route(s)
POST /vessel-access/grant- Grant vessel access to a user (SuperAdmin only)DELETE /vessel-access/grants/:id- Revoke vessel access (SuperAdmin only)PATCH /vessel-access/grants/:id- Update vessel access grant (SuperAdmin only)
/weather - 5 route(s)
DELETE /weather/cleanup- Clean up old cache entries (older than 24 hours)GET /weather/config- Get weather API configuration (Admin only)PATCH /weather/local/config- Update local weather API configuration (Admin only)PATCH /weather/windy/config- Update Windy API configuration (Admin only)POST /weather/windy/test- Test Windy API connection (Admin only)
Notably superadmin-only: granting, changing and revoking vessel access, license activation, AI provider keys/configuration, demo-data wipes, replication/provisioning, update agent, reopening/revoking completed work orders, and the console's write/maintenance functions.
7. Open and public routes
Routes with no permission. Nothing else in the system is reachable without one. A build test (route-protection.spec.ts) fails if a new route is added without a permission unless it is approved in that list.
Signed-in users only (no permission) - self-service by necessity
POST /auth/change-password- own accountPOST /auth/logout- own accountGET /auth/me- own accountGET /auth/profile- own accountPOST /auth/track-activity- own accountGET /config- logged-in topbarPOST /myshiptracking/bulk/refreshGET /myshiptracking/cache/statusGET /myshiptracking/vessel/:vesselId/historyGET /myshiptracking/vessel/:vesselId/latestPOST /myshiptracking/vessel/:vesselId/refreshGET /roles/my-permissions- your own permissionsDELETE /users/me/avatar- own accountPOST /users/me/avatar- own accountGET /vessels- limited to your granted vesselsGET /vessels/:id- limited to your granted vessels
Public (no login)
POST /auth/loginPOST /auth/refreshPOST /auth/registerPOST /auth/request-resetPOST /auth/request-verifyPOST /auth/resetPOST /auth/verify-emailGET /healthPOST /license/setup-activateGET /license/statusGET /monitoring/healthGET /monitoring/statsPOST /replication/vessel/ackPOST /replication/vessel/activate-ackPOST /replication/vessel/importPOST /replication/vessel/pushGET /server/infoGET /server/qrGET /settings/base-currencyGET /settings/company-themeGET /settings/system/initializedGET /support/announcementsGET /support/changelogGET /support/versionGET /sync/healthPOST /system/update/agent-callbackGET /system/update/versionGET /uploads/file/:path(*)GET /vessels/:id/photo
Public routes are login/registration/reset flows, health and version probes, pre-login branding, replication endpoints that check a node secret, the lock-screen licence activation (only works while locked, rate-limited), the update-agent callback (shared secret), and file/photo URLs used by <img>/<iframe> (accepted trade-off - the URLs are guessable and permanent; signed URLs are recommended).
8. Known gaps
Permissions that exist in the Roles screen but are not (fully) enforced. Ticking them currently has little or no effect:
| Permission | Status | Note |
|---|---|---|
modules.inventory.edit |
not enforced | Declared but not enforced anywhere. |
modules.stock.view |
UI only | Open the Stock pages and read their data. |
modules.stock.adjust |
not enforced | Declared; stock changes are enforced through Spare Parts: adjust. |
modules.alarm-system.acknowledge |
not enforced | Acknowledge an alarm. Declared but not currently enforced. |
modules.medic-items.view |
UI only | Open the Medical Items pages and read their data. |
modules.cost-centers.delete |
not enforced | Declared; not currently enforced. |
modules.history.export |
not enforced | Declared; not currently enforced. |
modules.alerts.manage |
UI only | Alerts page export and management buttons. Enforced in the UI only. |
modules.voyage-reports.view |
not enforced | Open the Voyage Reports pages and read their data. |
modules.voyage-reports.create |
not enforced | Enforced in the UI only (no API routes). |
modules.voyage-reports.edit |
not enforced | Change existing Voyage Reports records. |
modules.voyage-reports.export |
not enforced | Export Voyage Reports data. |
modules.reports.export |
not enforced | Declared; not currently enforced on its own. |
modules.vessel-access.manage |
not enforced | Declared but not enforced: granting vessel access is superadmin-only. |
modules.notifications.manage |
not enforced | Declared but not currently enforced. |
modules.audit-log.export |
not enforced | Export the audit log. Declared; the export is gated in the UI only. |
Also: documents of type port call or trip have no vessel link and are treated as company-wide; company-wide reference tables (suppliers, code lists, templates) are not vessel-scoped by design; the docs for each permission are regenerated from the code, so a gap closed later disappears from this table when regenerated.