Finding
A prior CodeRabbit review of Draft #235 identified a P1 that remained present through exact 4ef7ad130e4d0aa314ea59de3dafaea79cc0630c: read_validity_study(...) used isinstance(read_port, ValidityStudyReadPort) as its dependency gate, but a runtime-checkable protocol is a structural shape check, not reliable proof that resolving read_validity_study yields a safely callable capability.
A caller can expose a descriptor/property or other non-callable static member under that name. Depending on Python protocol-check implementation, structural checking can itself touch dynamic attributes or accept the static member; the application can then proceed into principal/policy validation and purpose-bound authorization before eventually failing when the repository capability is resolved/called. That violates the boundary's declared fail-fast dependency contract.
The repair must not replace this with eager getattr(...)/callable(...), which would execute a caller-controlled descriptor before authorization.
Test-first repair lineage
9794ff543c9190cdd6fa00dc37016db8391709a9: causal regression. _DescriptorReadPort.read_validity_study is a property whose getter raises if executed. The request uses a deliberately denying policy so the invalid dependency must raise TypeError before authorization can produce a denial; descriptor behavior must never run.
ccb5c0c58dc74c1d7eee59431e6337c207fcac35: minimal production successor. The owner boundary uses inspect.getattr_static(read_port, "read_validity_study", None) and rejects a missing/non-callable static capability before principal reconstruction, policy detachment, Keyverse evaluation, or persistence. Valid ordinary instance-method ports expose the class function statically and remain callable after authorization.
- Compare
4ef7ad1... → ccb5c0c... is two ordinary ahead-only commits touching only the focused regression and registry.py (+ import + static capability gate). No force-push/history rewrite, SQL/schema/role, Keyverse adapter, principal contract, requested fields, or owner-port signature was changed.
#239 remains preserved: canonical principal reconstruction/revalidation still occurs before PurposeBoundAccessRequest and Keyverse evaluation once the dependency capability has first been proven inertly callable.
Acceptance state
Current #235 exact head is ccb5c0c58dc74c1d7eee59431e6337c207fcac35 on protected develop@eb9757f8649aaad026a9865508d9aad50c1a7a4f, Draft and mechanically mergeable. Exact-head Foundation 33954469089 / Repository quality 101275139627 was queued before checkout at the latest gate read; Security 33954468968, SAST 33954468946, and CodeQL PR 33954468879 were non-terminal. Hosted GREEN/100% coverage/PostgreSQL/security completion is not claimed.
CodeRabbit reviewed exact ccb5c0c... against protected develop@eb9757f... and reported no blocking issue in the requested #240 scope. It verified the static inspect.getattr_static(...) capability read and callability gate; this is independent static evidence, not a formal qualifying approval or hosted GREEN. GitHub's formal review collection is still empty.
Keep this issue open until exact-head hosted/security/review evidence and normal protected integration are complete.
Finding
A prior CodeRabbit review of Draft #235 identified a P1 that remained present through exact
4ef7ad130e4d0aa314ea59de3dafaea79cc0630c:read_validity_study(...)usedisinstance(read_port, ValidityStudyReadPort)as its dependency gate, but a runtime-checkable protocol is a structural shape check, not reliable proof that resolvingread_validity_studyyields a safely callable capability.A caller can expose a descriptor/property or other non-callable static member under that name. Depending on Python protocol-check implementation, structural checking can itself touch dynamic attributes or accept the static member; the application can then proceed into principal/policy validation and purpose-bound authorization before eventually failing when the repository capability is resolved/called. That violates the boundary's declared fail-fast dependency contract.
The repair must not replace this with eager
getattr(...)/callable(...), which would execute a caller-controlled descriptor before authorization.Test-first repair lineage
9794ff543c9190cdd6fa00dc37016db8391709a9: causal regression._DescriptorReadPort.read_validity_studyis a property whose getter raises if executed. The request uses a deliberately denying policy so the invalid dependency must raiseTypeErrorbefore authorization can produce a denial; descriptor behavior must never run.ccb5c0c58dc74c1d7eee59431e6337c207fcac35: minimal production successor. The owner boundary usesinspect.getattr_static(read_port, "read_validity_study", None)and rejects a missing/non-callable static capability before principal reconstruction, policy detachment, Keyverse evaluation, or persistence. Valid ordinary instance-method ports expose the class function statically and remain callable after authorization.4ef7ad1...→ccb5c0c...is two ordinary ahead-only commits touching only the focused regression andregistry.py(+ import + static capability gate). No force-push/history rewrite, SQL/schema/role, Keyverse adapter, principal contract, requested fields, or owner-port signature was changed.#239 remains preserved: canonical principal reconstruction/revalidation still occurs before
PurposeBoundAccessRequestand Keyverse evaluation once the dependency capability has first been proven inertly callable.Acceptance state
Current #235 exact head is
ccb5c0c58dc74c1d7eee59431e6337c207fcac35on protecteddevelop@eb9757f8649aaad026a9865508d9aad50c1a7a4f, Draft and mechanically mergeable. Exact-head Foundation33954469089/ Repository quality101275139627was queued before checkout at the latest gate read; Security33954468968, SAST33954468946, and CodeQL PR33954468879were non-terminal. Hosted GREEN/100% coverage/PostgreSQL/security completion is not claimed.CodeRabbit reviewed exact
ccb5c0c...against protecteddevelop@eb9757f...and reported no blocking issue in the requested #240 scope. It verified the staticinspect.getattr_static(...)capability read and callability gate; this is independent static evidence, not a formal qualifying approval or hosted GREEN. GitHub's formal review collection is still empty.Keep this issue open until exact-head hosted/security/review evidence and normal protected integration are complete.