Access rules
R-S-02 asks for RBAC and attaches a warning: LOOMS RBAC is additive-only with no Deny — do not inherit that limitation. These are the three properties that make this the fix rather than a rename.
- · Rules are data. They can be listed, diffed, reviewed and exported. Six hand-written predicates could not be.
- · Deny wins, at any priority. There is no ordering in which an allow overcomes an explicit deny.
- · Every rule names its basis. A rule that cannot say which requirement it implements does not get written.
Decided by allow-in-scope-read. R-S-03 — read within your own org-unit scope
| RULE | EFFECT | WHY | |
|---|---|---|---|
| ○ | 10 deny-readonly-writes | DENY | action view not in create/approve/certify |
| ○ | 11 deny-out-of-scope | DENY | OPS-COLL is in scope |
| ○ | 12 deny-audit-to-others | DENY | role exec not in viewer/dept_head/gm/metric_owner/data_owner/hr_bp/board |
| ○ | 13 deny-individual-export | DENY | action view not in export |
| ○ | 20 allow-feeds-operational | ALLOW | resource pack not in integrations/project |
| ○ | 21 allow-appraisal-cycle | ALLOW | resource pack not in appraisal |
| ○ | 22 allow-layer4-rollup | ALLOW | resource pack not in layer4 |
| ○ | 23 allow-simulator-l1 | ALLOW | resource pack not in simulator |
| ○ | 24 allow-campaign-owners | ALLOW | readOnly is true, rule needs false |
| ○ | 25 allow-audit-to-auditor | ALLOW | resource pack not in audit |
| ○ | 26 allow-export | ALLOW | action view not in export |
| ○ | 27 allow-individual-read | ALLOW | role exec not in hr_bp/auditor |
| ▶ | 40 allow-in-scope-read | ALLOW | OPS-COLL is in scope |
This is the trace Internal Audit asks for and no role matrix can produce: not what the answer was, but which rule produced it and on whose authority.
| PRI | RULE | EFFECT | SUBJECT | ACTION | RESOURCE | BASIS |
|---|---|---|---|---|---|---|
| 10 | deny-readonly-writes A board member and an Internal Auditor are read-only by design. This is the rule LOOMS cannot express. | DENY | anyone readOnly = true | create, approve, certify | any | A-26 — a read-only persona has no accountable role for a write |
| 11 | deny-out-of-scope Evaluated BEFORE resolution everywhere it is used, so an out-of-scope value never enters the RSC stream (R-S-17). | DENY | anyone | any | pack, division, metric, project, campaign + org-unit scope | R-S-03 / A-26 — row-level scope by org unit |
| 12 | deny-audit-to-others A deny, not an omission: the /settings/audit page still renders, filtered to the reader’s own rows. | DENY | viewer, dept_head, gm, metric_owner, data_owner, hr_bp, board | view | audit | R-S-04 / R-S-20 — the full log is Internal Audit’s; everyone else reads their OWN events |
| 13 | deny-individual-export Overrides allow-export, which would otherwise permit it. This is the deny R-S-02 warns LOOMS cannot express, doing real work rather than sitting in the table. | DENY | anyone | export | individual | R-S-14 / Q-19 — the workforce notice and DPIA extension are a hard prerequisite and are not issued |
| 20 | allow-feeds-operational Replaces canSeeIntegrations(). A Telesales agent has no reason to read another department’s key fingerprints. | ALLOW | exec, gm, dept_head, metric_owner, data_owner, auditor, hr_bp | view | integrations, project | R-S-13 / A-34 — an operational role in a data pipeline |
| 21 | allow-appraisal-cycle A line manager needs it because they are in it; a board member has no role in an appraisal cycle. | ALLOW | hr_bp, auditor, exec, dept_head, gm | view | appraisal | A-41 — the cycle is an HR instrument, not a scorecard |
| 22 | allow-layer4-rollup Gated on managing something. Getting this wrong once hid it from the CEO, who is the reader for “0 of 26 can be rated”. | ALLOW | exec, gm, dept_head, hr_bp, auditor, data_owner, metric_owner | view | layer4 | A-45 — a readiness report about the platform’s reach, not an individual scorecard |
| 23 | allow-simulator-l1 A department head’s version of “what should I focus on” is their pack. One screen for all three would be the one-size dashboard this programme replaces. | ALLOW | layer L1 | view, simulate | simulator | R-P-20 — the simulator reasons over the Layer-1 perspective weights |
| 24 | allow-campaign-owners Read is wider and scoped by unit; create is narrower, because a read-only persona has no goal to commit to. | ALLOW | exec, gm, dept_head, metric_owner readOnly = false | create | campaign | R-P-25 — a campaign names an accountable owner |
| 25 | allow-audit-to-auditor Both see the whole log — the CEO is the reader for a company-wide access review, and narrowing it by org unit would defeat that. Both reads are themselves events. | ALLOW | auditor, exec | view | audit | R-S-04 — the log is reusable as J-SOX and Internal Audit evidence |
| 26 | allow-export Everyone in scope may export; the control is that it is recorded, not that it is rare. | ALLOW | anyone | export | report, individual | R-S-08 — export is a permission: controlled, watermarked and logged |
| 27 | allow-individual-read Self and direct reports are handled by canReadIndividual, which is a row predicate rather than a surface rule. | ALLOW | hr_bp, auditor | view | individual | A-45 / R-S-15 — Layer-4 row scope runs on the reporting line, with a role exception for HR and Audit |
| 40 | allow-in-scope-read The broad read rule. It sits at the bottom because the denies above it must be evaluated first. | ALLOW | anyone | view, explain | pack, division, metric, campaign, board, report + org-unit scope | R-S-03 — read within your own org-unit scope |
Read-only in the prototype, like the registry. At fullstack these live in the database beside the RLS predicates (A-21) and a change to one is a change-controlled action with its own audit row.