Skip to content

Split received/case.py and received/actor.py into subpackages#941

Merged
sei-ahouseholder merged 6 commits into
mainfrom
task/881-split-received-use-cases
Jun 15, 2026
Merged

Split received/case.py and received/actor.py into subpackages#941
sei-ahouseholder merged 6 commits into
mainfrom
task/881-split-received-use-cases

Conversation

@sei-ahouseholder

@sei-ahouseholder sei-ahouseholder commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Summary

Splits two 800+ line use-case modules into focused subpackages, each
submodule under 500 lines, with re-exporting __init__.py files that
preserve all existing import paths.

Addresses review feedback:

  1. Test split (AC-4): test_create.py (807 lines) and
    test_update.py (559 lines) have been split into focused per-concern
    modules that mirror the source submodule they exercise.
  2. BT-migration debt marked (BT-06-001, BT-15-001): Inline protocol
    mutations in AcceptInviteActorToCaseReceivedUseCase and
    _ensure_reporter_participant are explicitly marked as debt with
    TODO(#943) comments. Comment language no longer presents inline as the
    architectural solution. Tracking issue: Migrate received use-case procedural protocol behavior to BT nodes (BT-06-001, BT-15-001) #943.

Changes

Source subpackages (unchanged from original split)

  • vultron/core/use_cases/received/case/ (new package):
    _helpers.py, create.py, update.py, engage_defer.py,
    lifecycle.py, validate.py, __init__.py (re-exports all public
    names)
  • vultron/core/use_cases/received/actor/ (new package):
    suggest.py, case_manager_role.py, ownership.py, invite.py,
    announce.py, __init__.py (re-exports all public names)

BT-debt markers added

  • received/actor/invite.py: AcceptInviteActorToCaseReceivedUseCase
    — replaced inline-as-solution comment with TODO(#943) on RM transitions,
    participant creation, case events, and dl.save
  • received/case/_helpers.py: _ensure_reporter_participant
    added TODO(#943) on direct ParticipantStatus(rm_state=RM.ACCEPTED)
    creation/upgrade

Test layout (per-concern split)

Verification

  • 3205 passed, 36 skipped in 42s
  • Black, flake8, mypy, pyright clean

@sei-ahouseholder sei-ahouseholder added the size:L 301+ diff lines or 7+ ACs label Jun 12, 2026
@sei-ahouseholder sei-ahouseholder force-pushed the task/881-split-received-use-cases branch from dbe725c to 96970a7 Compare June 12, 2026 20:08
@sei-ahouseholder

Copy link
Copy Markdown
Contributor Author

I’m requesting changes, not because CI is failing, but because this PR is meant to set the structural precedent for future use-case splits and it currently leaves two important expectations weaker than issue #881 requires.

  1. AC-4 is only partially satisfied. The source files were split well, but the test split is mostly directory-level. test/core/use_cases/received/case/test_create.py is still 807 lines and includes bootstrap create, participant storage, AddParticipantStatus-after-bootstrap, reporter seeding, and reporter upgrade scenarios. test/core/use_cases/received/case/test_update.py is still 559 lines and mixes use-case behavior with BT tree-structure assertions. Issue Split large received use-case modules (received/case.py and received/actor.py) #881 asks for the test layout to mirror the source split, and CS-18-004 / the BUILD_LEARNINGS entry for Split large received use-case modules (received/case.py and received/actor.py) #881 point toward per-submodule test files. Please split the helper/bootstrap-participant cases into a focused test_helpers.py / test_bootstrap_participants.py (or equivalent), and split the update BT-structure tests from the update use-case tests if they stay in this package.

  2. The split canonizes non-BT procedural protocol behavior unless it is explicitly marked as debt. I agree PCR-08-010 means AcceptInviteActorToCaseReceivedUseCase must not spoof the invitee by executing an engage-case BT under the wrong actor identity. But BT-06-001 / BT-06-006 still say protocol-significant state transitions and domain object mutations should live in reusable BT nodes/subtrees, not use-case bodies or reusable procedural helpers. This split now gives _ensure_reporter_participant() a reusable home while it directly creates/upgrades ParticipantStatus(rm_state=RM.ACCEPTED), and AcceptInviteActorToCaseReceivedUseCase directly appends RM states and case events. If those transitions are intentionally preserved scope-wise, please avoid test/comment language that presents “inline” as the architectural solution, and add a tracked TODO/issue reference making clear this is preserved BT-migration debt rather than precedent for future use-case splits.

What looks good: the new source submodules are under 500 lines, the public use-case classes are preserved through package re-exports, and CI is green.

@sei-ahouseholder

sei-ahouseholder commented Jun 12, 2026

Copy link
Copy Markdown
Contributor Author

Follow-up / strengthening my second point above: this should be treated as blocking, not optional debt.

The identity-spoofing constraint is real: a received-side use case must not run a BT as another actor. But that does not justify doing protocol-significant work procedurally in the use case. The correct architecture is: the receiving actor runs a BT as itself, and that BT contains the reusable leaf nodes/subtrees for the state it is authorized to record in its own DataLayer.

So the direct DataLayer/domain mutations in received use-case execute() bodies are not acceptable precedent:

  • AcceptInviteActorToCaseReceivedUseCase directly creates a participant, appends RM states, records case events, saves the case, and queues outbox work.
  • _ensure_reporter_participant() directly creates/upgrades participant RM state to RM.ACCEPTED.
  • Other received use cases still directly mutate cases or outbox state.

Per BT-06-001 and BT-06-006, use cases should be infrastructure glue only: construct the tree, set up blackboard/context, execute through BTBridge, inspect result, and surface errors. They should not make direct dl.create / dl.save / state-transition / outbox calls. This PR should move those operations into BT nodes/subtrees as part of the split.

sei-ahouseholder pushed a commit that referenced this pull request Jun 12, 2026
Test split (AC-4, CS-18-004):
- Split test_create.py (807 lines) into three focused files:
  - test_create.py: CBT-05-001..004 bootstrap use-case tests only
  - test_bootstrap_participants.py: CBT-05-005/006 embedded-participant
    storage and M4 regression (#561/#562/#563)
  - test_helpers.py: CBT-05-006/007 _ensure_reporter_participant seeding
    and RM.ACCEPTED upgrade (#589/#624)
- Split test_update.py: extract BT tree-structure assertions into
  test_update_bt.py, keeping use-case behavior tests in test_update.py

BT-migration debt markers (BT-06-001, BT-15-001):
- AcceptInviteActorToCaseReceivedUseCase.execute(): replace comment
  presenting inline RM transitions as the architectural solution with an
  explicit TODO(#943) marking them as BT-migration debt
- _ensure_reporter_participant(): add TODO(#943) on direct
  ParticipantStatus(rm_state=RM.ACCEPTED) creation/upgrade
- test_helpers.py: add class-level TODO(#943) notes so the tests document
  the debt they cover
- Created tracking issue #943 for the BT migration work

3205 passed, 36 skipped in 42s

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
ahouseholder and others added 5 commits June 15, 2026 09:21
Convert two large use-case modules (819 and 803 lines) into focused
subpackages, each under 500 lines per submodule (CS-18-002).

received/case/ submodules:
- _helpers.py: private helper functions shared across the package
- create.py: CreateCaseReceivedUseCase (bootstrap path)
- update.py: UpdateCaseReceivedUseCase
- engage_defer.py: EngageCaseReceivedUseCase, DeferCaseReceivedUseCase
- lifecycle.py: AddReportToCaseReceivedUseCase, CloseCaseReceivedUseCase
- validate.py: InvalidateCaseUseCase, CloseCaseUseCase, ValidateCaseUseCase
- __init__.py: re-exports all public names (AC-3)

received/actor/ submodules:
- suggest.py: Suggest/Accept/Reject SuggestActorToCase
- case_manager_role.py: Offer/Accept/Reject CaseManagerRole
- ownership.py: Offer/Accept/Reject CaseOwnershipTransfer
- invite.py: Invite/Accept/Reject InviteActorToCase
- announce.py: AnnounceVulnerabilityCaseReceivedUseCase
- __init__.py: re-exports all public names including _find_case_actor_id

Test layout mirrors source split (AC-4):
- test/core/use_cases/received/case/ (test_create, test_update, test_engage_defer)
- test/core/use_cases/received/actor/ (test_invite, test_suggest, test_ownership, test_case_manager_role, test_announce)

All 3205 unit tests pass. Black, flake8, mypy, pyright clean.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…d received/actor.py into subpackages

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…NINGS

- Flat-to-subpackage test migration: remove old flat files instead of
  keeping both to avoid duplicate test collection
- Parent conftest fixtures are inherited automatically; only the vocab
  registration side-effect import needs copying per subdirectory

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Test split (AC-4, CS-18-004):
- Split test_create.py (807 lines) into three focused files:
  - test_create.py: CBT-05-001..004 bootstrap use-case tests only
  - test_bootstrap_participants.py: CBT-05-005/006 embedded-participant
    storage and M4 regression (#561/#562/#563)
  - test_helpers.py: CBT-05-006/007 _ensure_reporter_participant seeding
    and RM.ACCEPTED upgrade (#589/#624)
- Split test_update.py: extract BT tree-structure assertions into
  test_update_bt.py, keeping use-case behavior tests in test_update.py

BT-migration debt markers (BT-06-001, BT-15-001):
- AcceptInviteActorToCaseReceivedUseCase.execute(): replace comment
  presenting inline RM transitions as the architectural solution with an
  explicit TODO(#943) marking them as BT-migration debt
- _ensure_reporter_participant(): add TODO(#943) on direct
  ParticipantStatus(rm_state=RM.ACCEPTED) creation/upgrade
- test_helpers.py: add class-level TODO(#943) notes so the tests document
  the debt they cover
- Created tracking issue #943 for the BT migration work

3205 passed, 36 skipped in 42s

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
AcceptInviteActorToCaseReceivedUseCase.execute() now delegates all
protocol-significant work (RM transitions, participant creation, case
events, outbox emit) to AcceptInviteActorToCaseBT via BTBridge.  The
BT runs as the CaseActor — not the invitee — preserving PCR-08-010
identity constraints.

CreateCaseReceivedUseCase._handle_bootstrap() now calls BTBridge with
EnsureReporterParticipantAtAcceptedNode instead of calling
_ensure_reporter_participant() directly.

New BT artifacts:
- vultron/core/behaviors/case/accept_invite_tree.py: 5-node Sequence
  tree implementing the accept-invite protocol path
  (CheckInviteeNotAlreadyParticipantNode, CreateInviteeParticipantAtAcceptedNode,
  MaybeSignEmbargoConsentNode, PersistInviteeParticipantNode,
  EmitAnnounceCaseToInviteeNode)

EnsureReporterParticipantAtAcceptedNode exported from
vultron/core/behaviors/case/nodes/participant/.

Removes all TODO(#943) markers — the BT-migration debt is resolved.

Resolves #943. All 3205 tests pass.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@sei-ahouseholder sei-ahouseholder force-pushed the task/881-split-received-use-cases branch from f19858c to cc03908 Compare June 15, 2026 13:23
The class was incorrectly re-added during conflict resolution of the
rebase onto main (PR #942 had moved it to participant_tree.py).  The
duplicate referenced SeedParticipantAsSignatoryIfEmbargoActiveNode which
is not imported in participant_add.py, causing F821/name-defined errors
in flake8/mypy/pyright CI jobs.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@sei-ahouseholder sei-ahouseholder merged commit b56687b into main Jun 15, 2026
11 checks passed
@sei-ahouseholder sei-ahouseholder deleted the task/881-split-received-use-cases branch June 15, 2026 13:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L 301+ diff lines or 7+ ACs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Split large received use-case modules (received/case.py and received/actor.py)

2 participants