Sonador ACL MS1: Test Coverage Tracking

This issue is the canonical tracking location for all functional test work related to the Sonador ACL security model. Implementation status, coverage gaps, and priorities are maintained here. Child issues cover specific areas in depth.

Child issues:

  • oak-tree/medical-imaging/sonador#64 — Test matrix and full coverage assessment (closed July 2026 — all deliverables traced to implementing MRs in the close-out verification)
  • #73 (closed)acl permission functional tests (complete July 2026 — 11/11 implemented and passing live; see the ACL Policy Management section below)

Implementing merge requests (ACL close-out, June–July 2026):

June 2026 wave:

  • oak-tree/medical-imaging/sonador!88 — Sonador-side ACL enforcement fixes (worklist regression, comment permissions, modify/remove ancestor traversal)
  • orthanc-sonador!53 (merged) — Orthanc cloud-plugin policy-builder fixes (companion to oak-tree/medical-imaging/sonador!88)
  • sonador-ftests!8 (merged) — the functional test matrix inventoried below
  • oak-tree/medical-imaging/sonador-client!71 — IO-client test hardening the suite depends on

July 2026 wave (acl permission + worklist authorization):

  • oak-tree/medical-imaging/sonador!91 — acl permission enforcement: resource_perm() acl branch, DICOMweb ACL-management route backfill, descend-only scope (merged 2026-07-09)
  • orthanc-sonador!56 (merged)acl_traverse ancestor-traversal signal in the local policy builder; companion to oak-tree/medical-imaging/sonador!91 (merged 2026-07-09)
  • orthanc-authorization!2 (merged)acl action token in the route parser; companion to oak-tree/medical-imaging/sonador!91 (all three deploy together)
  • sonador-ftests!13 (merged)acl permission functional tests, 11 cases in tests/tests_sonadoracl_manage.py (merged 2026-07-09)
  • oak-tree/medical-imaging/sonador-client!74 — shared assertRejected/assertDenied helpers (dependency of sonador-ftests!13 (merged))
  • oak-tree/medical-imaging/sonador!90 / orthanc-sonador!55 (merged) — worklist authorization no longer requires local Modify; test updates in sonador-ftests!12 (merged) and oak-tree/medical-imaging/sonador-client!73 (merged 2026-07-08)

Documentation

The documentation/diagram checklist that previously lived here has been moved to its own tracking issue: #76 ("Systems & Workflow Documentation — SaMD diagram coverage"). That issue carries the full SaMD documentation assessment and current-coverage analysis. The original checklist is preserved as a comment on this issue for traceability. This issue now scopes functional-test coverage only.


Test Suite: Implemented

Tests live in oak-tree/medical-imaging/sonador-ftests. The tests/ directory holds tests added as part of this milestone; sonador/ftests/ holds the pre-existing suite that ships with the IO client library.

Server-Level Permissions

Test Permission Module
testacl_server_upload_data upload: allow → deny cycle tests/tests_sonadoracl_global.py
testacl_server_query_data query: allow → deny cycle tests/tests_sonadoracl_global.py

Global Resource Permissions (server-scoped policy)

Test Resource Permission Module
testacl_sonador_series_access_permission Series view tests/tests_sonadoracl_global.py
testacl_sonador_study_access_permission Study view tests/tests_sonadoracl_global.py
testacl_sonador_patient_access_permission Patient view tests/tests_sonadoracl_global.py
testacl_global_series_modify_permission Series modify tests/tests_sonadoracl_modify_remove.py
testacl_global_study_modify_permission Study modify tests/tests_sonadoracl_modify_remove.py
testacl_global_patient_modify_permission Patient modify tests/tests_sonadoracl_modify_remove.py
testacl_global_series_remove_permission Series remove tests/tests_sonadoracl_modify_remove.py
testacl_global_study_remove_permission Study remove tests/tests_sonadoracl_modify_remove.py
testacl_global_patient_remove_permission Patient remove tests/tests_sonadoracl_modify_remove.py
testacl_series_query_allow_deny Series query tests/tests_sonadoracl_query.py
testacl_study_query_allow_deny Study query (child series) tests/tests_sonadoracl_query.py
testacl_patient_query_allow_deny Patient query (all children) tests/tests_sonadoracl_query.py

Local Resource Permissions (Orthanc resource-level ACL)

Test Resource ACL Scope Permission Module
testacl_local_series_view_data_tenancy Series user view: limited user uploads (upload-only); upload alone ≠ view; grant series user ACL → allow → revoke → deny tests/tests_sonadoracl_local_view.py
testacl_local_patient_view_user_grant Patient user view: patient grant propagates to child series → revoke → deny tests/tests_sonadoracl_local_view.py
testacl_local_patient_view_group_grant Patient group view: patient group grant propagates to child series → revoke → deny tests/tests_sonadoracl_local_view.py
testacl_local_series_modify_user_acl Series user modify tests/tests_sonadoracl_modify_remove.py
testacl_local_series_modify_group_acl Series group modify tests/tests_sonadoracl_modify_remove.py
testacl_local_series_remove_user_acl Series user remove tests/tests_sonadoracl_modify_remove.py
testacl_local_series_remove_group_acl Series group remove tests/tests_sonadoracl_modify_remove.py
testacl_local_study_comment_view_deny_edit Study group comment_view ✓, comment_edit ✗ tests/tests_sonadoracl_local_comments.py
testacl_local_study_comment_edit_authorized Study group comment_edit override via local grant tests/tests_sonadoracl_local_comments.py
testacl_local_study_comment_view_denied Study group comment_view blocked by local policy tests/tests_sonadoracl_local_comments.py
test_user_acl_management Series → Study user view + DICOMweb cross-check sonador/ftests/tests_sonadorauth_acl.py
test_group_acl_management Series → Study group view + DICOMweb cross-check sonador/ftests/tests_sonadorauth_acl.py

ACL Policy Management (acl permission) — added July 2026

Full specification in #73 (closed); implemented in tests/tests_sonadoracl_manage.py (SonadorAclPermissionTests) via sonador-ftests!13 (merged), passing 11/11 live against dev01. Enforcement landed across oak-tree/medical-imaging/sonador!91, orthanc-sonador!56 (merged), and orthanc-authorization!2 (merged) (deploy together). Pinned design decision: acl does not imply view; scope semantics are descend-only.

Test Scope Coverage Module
testacl_global_wildcard Global * Creator can create local policies at patient/study/series; policies authorize the beneficiary tests/tests_sonadoracl_manage.py
testacl_global_scoped_patient Global patient={uid} Grant reaches the patient and all descendant studies/series tests/tests_sonadoracl_manage.py
testacl_global_scoped_study Global study={uid} Grant reaches the study + child series; denied on a sibling study tests/tests_sonadoracl_manage.py
testacl_global_scoped_series Global series={uid} Grant reaches only the series; denied on parent study and sibling series tests/tests_sonadoracl_manage.py
testacl_local_scoped_patient Local patient ACL ACL=True grant cascades to child study/series policy creation tests/tests_sonadoracl_manage.py
testacl_local_scoped_study Local study ACL ACL=True grant cascades to child series policy creation tests/tests_sonadoracl_manage.py
testacl_local_scoped_series Local series ACL Grant reaches only the series; denied on parent study tests/tests_sonadoracl_manage.py
testacl_negative_query_not_acl_dicomweb Negative query=True, acl=False → 403 via the DICOMweb ACL-management route tests/tests_sonadoracl_manage.py
testacl_negative_modify_not_acl_internal Negative modify=True, acl=False → 403 via the internal route (the pre-fix vulnerability, confirmed live) tests/tests_sonadoracl_manage.py
testacl_negative_revocation Negative Global and local revocation variants → 403 on further policy creation tests/tests_sonadoracl_manage.py
testacl_negative_acl_without_view_separation Negative acl=True, view=False can create/enumerate policies but is denied view-mediated retrieval tests/tests_sonadoracl_manage.py

Role Matrix

Canonical role definitions live in cli/roles.py (ADMIN, REVIEWER, TECHNICIAN, REFERRING). One test per role × resource-type combination is in tests/tests_sonadoracl_roles.py (12 methods: 4 roles × 3 resource types). See oak-tree/medical-imaging/sonador#64 for the full matrix.

Role Series Study Patient Permissions asserted per test
Admin view, comment_view, comment_edit, modify (all granted)
Reviewer view ✓, comment_view ✓, comment_edit ✓, modify ✗
Technician view ✓, comment_view ✗, comment_edit ✗, modify ✗
Referring view ✓, comment_view ✓, comment_edit ✗, modify ✗

Worklist / MS2 Integration

Test Description Module
testacl_worklist_reassignment_access_denied User reassigned off a study loses access; new assignee gains access (View-only grants — local Modify no longer required per oak-tree/medical-imaging/sonador!90 / orthanc-sonador!55 (merged); test updated in sonador-ftests!12 (merged)) tests/tests_sonadoracl_worklist_security.py
test_history_acl_parity Worklist item + history readable with local View; state/procedure writes succeed without local Modify (updated in sonador-ftests!12 (merged)) tests/tests_ext_worklist_procedures.py

Test Suite: Remaining Gaps

Priority 1 — Blocking

  • acl permission: no test anywhere verifies... Closed out July 2026. All 11 test cases specified in #73 (closed) (4 global-scoped + 3 local-scoped + 4 negative/regression) implemented in tests/tests_sonadoracl_manage.py (sonador-ftests!13 (merged)) and passing live against dev01. Required a precursor enforcement fix — resource_perm() had no branch returning self.acl, so ACL-management requests fell through to view/modify/remove (a real, confirmed vulnerability: a modify=True, acl=False user could create ACL policies) — landed across oak-tree/medical-imaging/sonador!91, orthanc-sonador!56 (merged), and orthanc-authorization!2 (merged) (all three deploy together). See #73 (closed) for full detail. Full test-by-test trace is in the "ACL Policy Management" section above.

Priority 2 — Important

  • upload deny boundary: testacl_server_upload_data verifies the allow cycle and revocation flag, but no test creates a group with upload=False and asserts that upload_image() raises 403 for that group specifically.

  • Local modify and remove at study and patient scope: current local tests cover series scope only. Tests at study and patient scope use server-level scoped policies rather than Orthanc resource-level ACL (study.create_group_acl({...}) / patient.create_group_acl({...})).

  • DICOMweb cross-checks in new tests: only the pre-existing test_user_acl_management and test_group_acl_management verify that DICOMweb endpoints (WADO-RS/QIDO-RS) honor ACL decisions. The 32 tests added in June 2026 do not include DICOMweb assertions. (Partial progress July 2026: testacl_negative_query_not_acl_dicomweb exercises a DICOMweb deny for the acl route; a positive-grant DICOMweb acl case is still outstanding — noted as a known gap in sonador-ftests!13 (merged).)

Priority 3 — API Surface

  • query_study() and query_patient() direct calls: the three testacl_*_query_allow_deny tests call query_series() to verify inheritance from study/patient-level policies. The query_study() and query_patient() API methods are never called directly in any ACL test.

  • anonymize() operation: zero coverage across all test files. This is a destructive write operation with a separate Orthanc authorization path that must be confirmed to require modify permission.

  • filearchive() endpoint: ACL enforcement on the Orthanc archive download URL is untested. tests_download.py tests DICOMweb-based downloads, not the filearchive path.

Priority 4 — Future

  • fetch_attachments(), attachment_info(), attachment_data() — no coverage.
  • reconstruct(), fetch_meta() — no coverage.
  • Specialized DICOM resource types: query_sr(), query_seg(), query_m3d(), query_doc() — no ACL coverage.

Notes

  • Feb 15, 2024: Sonador was notified of scope changes due to updates to the Orthanc Advanced Authorization Plugin. Validation of resource access will be managed via the Orthanc–Sonador integration rather than a custom filter function.
  • Mar 24, 2024: Milestone updated with detailed test, documentation, and sub-task requirements.
  • Mar 28, 2024: Test cases elaborated for server permissions, global policies, and local policies. Agreed to focus on global policy tests for the Mar 29 review.
  • May 8, 2024: Cognito credential provider initial implementation was too slow. Added credentials cache issue (oak-tree/medical-imaging/sonador#68) and cryptographic offline validation issue (#67 (closed)).
  • May 31, 2024: Added tasks for user/group lookup via UID and integration into Orthanc.
  • Oct 24, 2024: Created follow-up Centinel milestone for overflow and additional development. acl permission functional tests created as #73 (closed).
  • Jun 2026: Full coverage assessment completed (oak-tree/medical-imaging/sonador#64). 32 new functional tests added to sonador-ftests/tests/ covering global and local view/modify/remove/query/comment permissions, the four-role matrix across all resource types, and the MS2 worklist reassignment security scenario. Remaining gaps documented in "Remaining Gaps" above. Implemented and verified by sonador-ftests!8 (merged) (with fixes in oak-tree/medical-imaging/sonador!88 / orthanc-sonador!53 (merged) and IO-client hardening in oak-tree/medical-imaging/sonador-client!71). Documentation/diagram checklist split out to #76.
  • Jul 2026: acl permission (Priority-1 gap) closed out — enforcement across oak-tree/medical-imaging/sonador!91 / orthanc-sonador!56 (merged) / orthanc-authorization!2 (merged), tests in sonador-ftests!13 (merged) (11/11 live). Worklist authorization decoupled from local Modify (oak-tree/medical-imaging/sonador!90 / orthanc-sonador!55 (merged), tests in sonador-ftests!12 (merged)). oak-tree/medical-imaging/sonador#64 closed with a full deliverable → MR trace. Remaining scope of this issue is Priority 2–4 only (non-blocking).

Project Tracking

OP#74

Edited by Sonador Claude