UAT: agents resource remove and agents resource add --update bypass ResourceRegistryService — CLI directly manipulates infrastructure DB models #2383

Open
opened 2026-04-03 17:27:41 +00:00 by freemo · 1 comment
Owner

Metadata

  • Branch: fix/resource-cli-bypass-service-layer
  • Commit Message: fix(cli): route resource remove and update through ResourceRegistryService
  • Milestone: v3.7.0
  • Parent Epic: #398

What Was Tested

The agents resource remove CLI command and the agents resource add --update flag in src/cleveragents/cli/commands/resource.py.

Expected Behavior (from spec)

Per ADR-007 (Repository Pattern) and ADR-003 (Dependency Injection), all data operations must go through the service layer. The ResourceRegistryService is the designated application service for resource management. CLI commands should call service methods, not directly access infrastructure models.

Actual Behavior (Bug)

agents resource remove (lines ~680-730 in resource.py):

# CLI directly imports and uses infrastructure DB models:
from cleveragents.infrastructure.database.models import (
    ResourceEdgeModel,
    ResourceModel,
)
session = service._session()  # Accesses private method
session.query(ResourceEdgeModel).filter(...).count()
session.query(ResourceModel).filter_by(...).delete(...)

agents resource add --update (lines ~490-520 in resource.py):

# Same pattern - directly imports and manipulates DB models:
from cleveragents.infrastructure.database.models import (
    ResourceEdgeModel,
    ResourceModel,
)
session = service._session()  # Accesses private method
session.query(ResourceEdgeModel).filter(...).delete(...)
session.query(ResourceModel).filter_by(...).delete(...)

ResourceRegistryService has NO remove_resource() method — the service class (ResourceRegistryService in src/cleveragents/application/services/resource_registry_service.py) provides register_resource, list_resources, show_resource but has no remove_resource() method at all.

Impact

  1. No domain events emitted when a resource is removed — event-driven subscribers won't be notified
  2. Architectural violation — CLI bypasses the service layer, violating ADR-007 and ADR-003
  3. Private method access — CLI calls service._session() which is a private method
  4. No proper error handling through the service layer
  5. Inconsistencyregister_resource goes through the service, but remove_resource bypasses it entirely

Code Locations

  • src/cleveragents/cli/commands/resource.pyresource_remove() function (~line 680) and resource_add() with --update flag (~line 490)
  • src/cleveragents/application/services/resource_registry_service.py — missing remove_resource() method
  • src/cleveragents/application/services/_resource_registry_ops.pyResourceInstanceMixin class missing remove_resource()

Steps to Reproduce

  1. Add a resource: agents resource add git-checkout local/my-repo --path /tmp/repo
  2. Remove it: agents resource remove local/my-repo --yes
  3. Observe that the CLI directly manipulates DB models instead of calling a service method

Subtasks

  • Write a failing Behave scenario reproducing the bug (TDD — failing test first)
  • Add remove_resource(name_or_id: str) -> None method to ResourceInstanceMixin in _resource_registry_ops.py
  • Add update_resource() / re_register_resource() method to ResourceInstanceMixin for the --update flag
  • Update resource_remove() CLI command to call service.remove_resource() instead of directly querying DB models
  • Update resource_add() CLI command --update path to call the new service method instead of directly querying DB models
  • Remove all direct infrastructure model imports (ResourceEdgeModel, ResourceModel) from resource.py CLI module
  • Remove all service._session() private method accesses from resource.py
  • Ensure domain events are emitted by the service on resource removal
  • Update/add type annotations on all new service methods (must pass nox -e typecheck)
  • Update Behave unit test scenarios to cover remove_resource() and update_resource() service methods
  • Verify all nox stages pass

Definition of Done

  • ResourceRegistryService exposes a public remove_resource() method that handles all deletion logic
  • ResourceRegistryService exposes a public update_resource() (or equivalent) method for the --update flag
  • resource.py CLI module contains no direct imports of ResourceEdgeModel or ResourceModel
  • resource.py CLI module contains no calls to service._session() or any other private service method
  • Domain events are emitted when a resource is removed via the service layer
  • All new service methods are fully type-annotated and pass Pyright (nox -e typecheck)
  • Behave scenarios cover the remove_resource() and update_resource() service methods
  • All nox stages pass
  • Coverage >= 97%

Automated by CleverAgents Bot
Supervisor: UAT Testing | Agent: ca-new-issue-creator

## Metadata - **Branch**: `fix/resource-cli-bypass-service-layer` - **Commit Message**: `fix(cli): route resource remove and update through ResourceRegistryService` - **Milestone**: v3.7.0 - **Parent Epic**: #398 ## What Was Tested The `agents resource remove` CLI command and the `agents resource add --update` flag in `src/cleveragents/cli/commands/resource.py`. ## Expected Behavior (from spec) Per ADR-007 (Repository Pattern) and ADR-003 (Dependency Injection), all data operations must go through the service layer. The `ResourceRegistryService` is the designated application service for resource management. CLI commands should call service methods, not directly access infrastructure models. ## Actual Behavior (Bug) **`agents resource remove`** (lines ~680-730 in `resource.py`): ```python # CLI directly imports and uses infrastructure DB models: from cleveragents.infrastructure.database.models import ( ResourceEdgeModel, ResourceModel, ) session = service._session() # Accesses private method session.query(ResourceEdgeModel).filter(...).count() session.query(ResourceModel).filter_by(...).delete(...) ``` **`agents resource add --update`** (lines ~490-520 in `resource.py`): ```python # Same pattern - directly imports and manipulates DB models: from cleveragents.infrastructure.database.models import ( ResourceEdgeModel, ResourceModel, ) session = service._session() # Accesses private method session.query(ResourceEdgeModel).filter(...).delete(...) session.query(ResourceModel).filter_by(...).delete(...) ``` **`ResourceRegistryService` has NO `remove_resource()` method** — the service class (`ResourceRegistryService` in `src/cleveragents/application/services/resource_registry_service.py`) provides `register_resource`, `list_resources`, `show_resource` but has no `remove_resource()` method at all. ## Impact 1. **No domain events emitted** when a resource is removed — event-driven subscribers won't be notified 2. **Architectural violation** — CLI bypasses the service layer, violating ADR-007 and ADR-003 3. **Private method access** — CLI calls `service._session()` which is a private method 4. **No proper error handling** through the service layer 5. **Inconsistency** — `register_resource` goes through the service, but `remove_resource` bypasses it entirely ## Code Locations - `src/cleveragents/cli/commands/resource.py` — `resource_remove()` function (~line 680) and `resource_add()` with `--update` flag (~line 490) - `src/cleveragents/application/services/resource_registry_service.py` — missing `remove_resource()` method - `src/cleveragents/application/services/_resource_registry_ops.py` — `ResourceInstanceMixin` class missing `remove_resource()` ## Steps to Reproduce 1. Add a resource: `agents resource add git-checkout local/my-repo --path /tmp/repo` 2. Remove it: `agents resource remove local/my-repo --yes` 3. Observe that the CLI directly manipulates DB models instead of calling a service method ## Subtasks - [ ] Write a failing Behave scenario reproducing the bug (TDD — failing test first) - [ ] Add `remove_resource(name_or_id: str) -> None` method to `ResourceInstanceMixin` in `_resource_registry_ops.py` - [ ] Add `update_resource()` / `re_register_resource()` method to `ResourceInstanceMixin` for the `--update` flag - [ ] Update `resource_remove()` CLI command to call `service.remove_resource()` instead of directly querying DB models - [ ] Update `resource_add()` CLI command `--update` path to call the new service method instead of directly querying DB models - [ ] Remove all direct infrastructure model imports (`ResourceEdgeModel`, `ResourceModel`) from `resource.py` CLI module - [ ] Remove all `service._session()` private method accesses from `resource.py` - [ ] Ensure domain events are emitted by the service on resource removal - [ ] Update/add type annotations on all new service methods (must pass `nox -e typecheck`) - [ ] Update Behave unit test scenarios to cover `remove_resource()` and `update_resource()` service methods - [ ] Verify all nox stages pass ## Definition of Done - [ ] `ResourceRegistryService` exposes a public `remove_resource()` method that handles all deletion logic - [ ] `ResourceRegistryService` exposes a public `update_resource()` (or equivalent) method for the `--update` flag - [ ] `resource.py` CLI module contains no direct imports of `ResourceEdgeModel` or `ResourceModel` - [ ] `resource.py` CLI module contains no calls to `service._session()` or any other private service method - [ ] Domain events are emitted when a resource is removed via the service layer - [ ] All new service methods are fully type-annotated and pass Pyright (`nox -e typecheck`) - [ ] Behave scenarios cover the `remove_resource()` and `update_resource()` service methods - [ ] All nox stages pass - [ ] Coverage >= 97% --- **Automated by CleverAgents Bot** Supervisor: UAT Testing | Agent: ca-new-issue-creator
freemo added this to the v3.7.0 milestone 2026-04-03 17:27:55 +00:00
Author
Owner

Issue triaged by project owner:

  • State: Verified
  • Priority: High — CLI commands bypassing the service layer violates the Repository Pattern (ADR-007) and Dependency Injection (ADR-003). This creates a maintenance and correctness risk as business logic in the service layer is skipped.
  • Milestone: v3.7.0 (as specified in issue metadata)
  • MoSCoW: Should Have — While the commands work functionally, bypassing the service layer means validation, events, and business rules are skipped. This is an architectural correctness issue that should be fixed.
  • Parent Epic: #398 (Post-MVP Resources)

Well-described with clear ADR references. Valid and actionable.


Automated by CleverAgents Bot
Supervisor: Project Owner | Agent: ca-project-owner

Issue triaged by project owner: - **State**: Verified - **Priority**: High — CLI commands bypassing the service layer violates the Repository Pattern (ADR-007) and Dependency Injection (ADR-003). This creates a maintenance and correctness risk as business logic in the service layer is skipped. - **Milestone**: v3.7.0 (as specified in issue metadata) - **MoSCoW**: Should Have — While the commands work functionally, bypassing the service layer means validation, events, and business rules are skipped. This is an architectural correctness issue that should be fixed. - **Parent Epic**: #398 (Post-MVP Resources) Well-described with clear ADR references. Valid and actionable. --- **Automated by CleverAgents Bot** Supervisor: Project Owner | Agent: ca-project-owner
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Blocks
#398 Epic: Post-MVP Resources
cleveragents/cleveragents-core
Reference
cleveragents/cleveragents-core#2383
No description provided.