Capability-based role permissions across the 112 verbs Neom recognises. The matrix is the v0 default mapping — per-tenant overrides via permission_templates.definition land in a follow-up run. Server actions guard mutations with assertCapability today.
Filled circles = capability granted. Hollow = not granted. Grey = portal-forbidden (79 capabilities are stripped from portal users at the resolver).
| Capability | COO | Director | Finance Officer | Financial Controller | Workspace Manager | BIM Manager | Client Portal | Commercial Lead | Consultant Portal | Estimator | Owner Portal | Procurement Lead | Project Manager | Quality Manager | Site Supervisor | Subcontractor Portal | WHSE Manager |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Project + tenant | |||||||||||||||||
| project.create | |||||||||||||||||
| project.edit_settings | |||||||||||||||||
| project.archive | |||||||||||||||||
| Tenant | |||||||||||||||||
| tenant.switch | |||||||||||||||||
| RFI | |||||||||||||||||
| rfi.create | |||||||||||||||||
| rfi.respond | |||||||||||||||||
| rfi.close | |||||||||||||||||
| rfi.void | |||||||||||||||||
| rfi.administer | |||||||||||||||||
| rfi.assign | |||||||||||||||||
| Variation | |||||||||||||||||
| variation.read | |||||||||||||||||
| variation.create | |||||||||||||||||
| variation.update | |||||||||||||||||
| variation.transition | |||||||||||||||||
| variation.incorporate | |||||||||||||||||
| Claim | |||||||||||||||||
| claim.create | |||||||||||||||||
| claim.update | |||||||||||||||||
| claim.transition | |||||||||||||||||
| claim.settle_final | |||||||||||||||||
| claim.export_pdf | |||||||||||||||||
| HSEQ | |||||||||||||||||
| hseq.create | |||||||||||||||||
| hseq.transition | |||||||||||||||||
| hseq.void | |||||||||||||||||
| Daily log | |||||||||||||||||
| daily_log.create | |||||||||||||||||
| daily_log.edit_others | |||||||||||||||||
| daily_log.submit | |||||||||||||||||
| daily_log.lock | |||||||||||||||||
| daily_log.update | |||||||||||||||||
| Submittal | |||||||||||||||||
| submittal.create | |||||||||||||||||
| submittal.transition | |||||||||||||||||
| submittal.distribute | |||||||||||||||||
| submittal.administer | |||||||||||||||||
| Drawing | |||||||||||||||||
| drawing.upload | |||||||||||||||||
| drawing.markup | |||||||||||||||||
| drawing.markup.create | |||||||||||||||||
| drawing.markup.delete | |||||||||||||||||
| Procurement | |||||||||||||||||
| procurement.read | |||||||||||||||||
| procurement.create | |||||||||||||||||
| procurement.award | |||||||||||||||||
| Correspondence | |||||||||||||||||
| correspondence.send | |||||||||||||||||
| correspondence.create_formal | |||||||||||||||||
| Reports | |||||||||||||||||
| report.run | |||||||||||||||||
| report.export | |||||||||||||||||
| Assistant / Executive / EOM | |||||||||||||||||
| assistant.view | |||||||||||||||||
| assistant.action | |||||||||||||||||
| Executive | |||||||||||||||||
| executive.view | |||||||||||||||||
| EOM | |||||||||||||||||
| eom.view | |||||||||||||||||
| eom.action | |||||||||||||||||
| eom.endorse | |||||||||||||||||
| Commercial settings | |||||||||||||||||
| commercial.retention_config | |||||||||||||||||
| commercial.cashflow_recalc | |||||||||||||||||
| commercial.cashflow_reallocate | |||||||||||||||||
| Admin | |||||||||||||||||
| admin.users | |||||||||||||||||
| admin.roles | |||||||||||||||||
| admin.integrations | |||||||||||||||||
| admin.audit | |||||||||||||||||
| admin.audit_export | |||||||||||||||||
| admin.errors | |||||||||||||||||
| admin.diagnostics | |||||||||||||||||
| admin.permissions | |||||||||||||||||
| admin.companies.manage | |||||||||||||||||
| admin.webhooks.manage | |||||||||||||||||
| admin.reports.cancel | |||||||||||||||||
| admin.worker.force_tick | |||||||||||||||||
| admin.worker.dlq_manage | |||||||||||||||||
| admin.templates.manage | |||||||||||||||||
memberships table when available · in-code defaults otherwise. Edit-mode lands when permission_templates.definition.capabilities ships.Per-tenant overrides on top of the role defaults. Stored in permission_templates.definition (jsonb). Empty roles means "applies to every role in the tenant".
| Name | Scope | Applies to | Grants | Revokes |
|---|---|---|---|---|
IDC Staff — baseline Tenant-wide baseline. Edit grant/revoke to layer overrides on top of role defaults. | workspace | all roles | — | — |
Estimator — exec view IDC convention: Estimators see the executive dashboard but cannot bulk-export reports. | workspace | Estimator | executive.view | report.export |
Finance access bundle Grants finance.read_full to anyone holding Financial Controller or Finance Officer. Adjust the role list to widen / narrow finance visibility. | workspace | Financial Controller, Finance Officer | finance.read_full | — |
variation.create · variation.update · variation.incorporate — variation flowsclaim.transition · claim.settle_final — claim flowsrfi.create · rfi.respond · rfi.close · rfi.void — RFI flowshseq.transition · hseq.void — HSEQ flowssubmittal.transition · submittal.distribute — submittal flowsdaily_log.create — daily log entrycommercial.retention_config — per-project retention rule editsdrawing.markup — guards createMarkupAction + deleteMarkupAction on the drawing viewer15 capabilities across 8 action surfaces guarded today. Procurement + drawing upload (blob pipeline) queued for the next pass.
Portal users have a hard ceiling of 79 forbidden capabilities — including everything under assistant., executive., eom., admin., commercial. (config), and stricter workflow verbs (claim.transition, variation.incorporate, hseq.transition).
The forbidden set is enforced inside capabilitiesForRoles so a misconfigured portal role definition can't accidentally grant internal verbs.