T0-E1 independent findings¶
| Finding | Original severity | Independent code review | Independent runtime proof | Evidence integrity | Verdict | Residual |
|---|---|---|---|---|---|---|
| T0F-001 | S0 | identity_admin_api.py and school_context_api.py still treat platform group membership as global authority; company_scope.py and teacher scope retain group/global-role fallbacks. |
Added platform_operator to disposable conflict actor, kept active role school_admin, and reset GT-T2 user 104 successfully; roles/password/target state restored. |
Conflict matrix never used this broad-role-only conflict. | NOT_FIXED | S0 inactive-role/group-union authority remains. |
| T0F-002 | S0 | Dataset mutation gate covers call_kw/call_button mutating methods and recognizes list/create responses through side-effect checks. |
Teacher /web/dataset/call_kw attachment create returned a 403 response object; DB row count for audit name remained 0. |
Focused evidence now records before/after counts; response envelope is awkward but denial is effective. | CLOSED_BY_INDEPENDENT_AUDIT | UI/RPC response-shape hygiene remains, not a mutation bypass. |
| T0F-003 | S0 | Full FE/BE application tree hashing is broader, but validator has no required-case validation, no served-BE query, no DB/module/entitlement binding, and no E1 runtime manifest. | run_e1_evidence_identity_validator.sh fails immediately because T0-E1-runtime-manifest.json is absent. Mutation unit covers only nine synthetic cases; removed/skipped evidence cases are not checked. |
Current E1 evidence is not bound to a certifying manifest. | NOT_FIXED | False-green risk remains for evidence/results and runtime mismatch. |
| T0F-004 | S0 | Tested leadership HR/finance routes now have feature flags; broad executive routes are capability-gated. | With flags false, principal/performance, executive/finance/summary, tuition, leave, and leadership probes returned feature-disabled/capability-denied. Direct hr.employee RPC returned no rows under the tested school-admin ACL. |
E1 “enable HR” probe used a 404 path and did not prove an approved entitlement opens only its package. | PARTIALLY_FIXED | Denial is improved, but mixed-install enable/alternate-RPC proof is incomplete. |
| T0F-005 | S0 | Bulk endpoint returns 410, but identity scope still has a group fallback that defeats active-role isolation. | The independent conflict test reset GT-T2 user 104 from a GT-T1 company-1 actor whose active role was school_admin but whose assigned platform group was inactive. | E1 XTENANT tested only a non-conflicting school admin. |
NOT_FIXED | Cross-tenant reset remains reachable through an alternate authority path. |
| T0F-006 | S0 | /api/v1/users now generates a secret and forces must-change, but school-unit admin creation accepts admin_password; student/parent generation endpoints return plaintext credentials; demo/provision scripts retain admin defaults. |
Source and route review are production-capable; canonical user-create response was not enough to cover these alternate paths. | Matrix did not cover generate-students, generate-parents, or school-unit admin creation. | NOT_FIXED | Alternate credential creation and plaintext-return paths remain. |
| T0F-007 | S0 | Must-change gate is restricted to paths beginning /api; dataset read paths are outside that gate. |
Disposable must-change teacher logged in; /api/dashboard/stats denied, but /web/dataset/call_kw res.users.search_read returned [{id:98,login:...}]. |
Matrix tested only dashboard API, not direct RPC read. | NOT_FIXED | Must-change actor retains normal product/RPC read authority without FE. |
| T0F-008 | S0 | Native reset form is blocked and ICP is false, but auth_signup invitation/signup remains enabled (invitation_scope=b2c) and native /web/signup?token=bad is reachable. User creation still uses email/context paths that can invoke Odoo signup token behavior. |
/web/reset_password 404; /web/signup without token 404; /web/signup?token=bad 200 and native signup handler remains in Odoo. |
E1 native case checked only reset GET and not signup/token lifecycle. | NOT_FIXED | A second native password-setting lifecycle remains possible with a valid signup token. |
| T0F-009 | S1 | Consume uses FOR UPDATE, but token issuance has no lock/conditional uniqueness; session-store absence returns 0; audit writer swallows persistence errors. |
Two concurrent confirm requests produced exactly one success; no test induced unavailable-store/audit failure. | 19-case matrix says “concurrent” but CONFIRM-05 is rapid sequential double confirm. |
PARTIALLY_FIXED | Consume race improved; issue/revoke/audit atomicity remains unproven/unsafe. |
| T0F-013 | S1 | Public allowlist now uses exact entries or explicit trailing-slash prefixes; workflow invokes denominator checker. | Route recomputation passed: 1,715/1,678/34/3, 0 blockers; child /api/SPMB/registers/list is protected while exact /api/SPMB/registers is public. |
Route unit 54 tests passed; CI YAML includes checker. | CLOSED_BY_INDEPENDENT_AUDIT | No remaining E1 finding in this control. |
| T0F-014 | S1 | Matrix expanded to 19 cases, but no authorized successful admin reset, wrong-user/purpose, native signup denial, audit persistence, or genuine concurrency evidence. | T0-E1-20260809T070201Z reports 19/19; independent concurrent test supplied one missing case. |
Matrix evidence is incomplete for the stated DEC-014 denominator. | NOT_FIXED | 19/19 is not sufficient closure evidence. |
| T0F-015 | S0 | Scola Core APIs add company domains, but native RPC remains able to read unrestricted Core partner records. | T1 school_admin read /web/dataset/call_kw res.partner id 138 and company 22 (GT2 Teacher Assigned) successfully; Scola student API denied/returned no T2 object. |
E1 tenant subset used empty/fabricated/no-record probes and did not test partner RPC. | NOT_FIXED | Core actor can still read another tenant through a supported framework path. |
T0F-010, T0F-011 and T0F-012 are intentionally not assessed and remain open for T0-E2.