Re-derive the audit structurally — 57 decorative

Fixkamo-internal
Ya
14 Agosti 2026, 22:34 UTC
Mwandishi
kamo
Ahadi ya
6d4a0d0

The count moved 58 -> 52 -> 47 -> 57 because every version hard-coded a list of gate-helper names and the codebase has more than anyone can recall. Six were missed across three passes — denyUnless, hasAnyRight, sessionHasRight, forbidden, findByMemberAndRight, checkRole — and each miss reported a working permission as dead. audit_v3.py names none of them. It uses the structural difference between code that USES a right and prose that DISCUSSES one: argument position (hasRight(request, RoleRightType.X), List.of(RoleRightType.X)) or receiver position (RoleRightType.X.name(), which is how OrganizationController gates branding). A javadoc paragraph mentioning {@code MANAGE_TIMECARDS} no longer reads as a check — that was the source of most phantom 'enforced' results. It validates against 13 rights confirmed by reading the code and exits non-zero rather than emit a list it disagrees with. The guard caught two defects while the analyzer was being written, and disproved one of my own earlier corrections: VIEW_DASHBOARD is decorative. The file-level pass had rescued it wrongly. Net vs the shipped list: +13 (six sales-agent rights, four marketing VIEW_*, VIEW_DASHBOARD, VIEW_TIME_OFF, VIEW_VOICEMAIL — all rescued by file-level matching but never passed to anything), -2 (VIEW_PAYROLL, MANAGE_PAYROLL, which genuinely are enforced). Analyzer and its output are committed so the number is reproducible instead of asserted, and the file says not to hand-edit — editing one entry by eye is how it drifted before.

Mabadiliko yote

Je, unaona nini kuhusu usafiri?

Kila moja ya hizi updates ardhi katika nafasi yako ya kazi moja kwa moja. Kuanza bure na kuangalia kukua wiki baada ya wiki.

Kuwa Huru MileleMtazamo wa bei