UAT: infrastructure/database/repositories.py namespace extraction uses naive name.split("/")[0] — incorrectly includes server qualifier for server-qualified names #4706

Open
opened 2026-04-08 18:04:05 +00:00 by HAL9000 · 1 comment
Owner

Bug Report

Feature Area: Namespace management and naming conventions — Database persistence layer
Severity: Medium — server-qualified resource/resource-type names stored with wrong namespace in DB
Discovered by: UAT tester (uat-ns-mgmt-001)


Summary

Multiple places in src/cleveragents/infrastructure/database/repositories.py extract the namespace from a namespaced name using the naive pattern name.split("/")[0]. For server-qualified names like prod:myorg/my-resource, this extracts prod:myorg as the namespace (including the server qualifier), which is semantically incorrect. The namespace should be myorg.


Expected Behavior (from spec)

The spec (docs/specification.md, line 174) defines:

Namespace: The scoping segment in the name format [[server:]namespace/]name. Defaults to local/ when omitted.

For prod:myorg/my-resource:

  • server = prod
  • namespace = myorg
  • name = my-resource

The namespace stored in the database should be myorg, not prod:myorg.


Actual Behavior

Code location 1: src/cleveragents/infrastructure/database/repositories.py, lines 1793–1795

namespace=resource_type.name.split("/")[0]
if "/" in resource_type.name
else "builtin",

For prod:myorg/my-resource-type:

  • resource_type.name.split("/")[0]"prod:myorg" (should be "myorg")

Code location 2: src/cleveragents/infrastructure/database/repositories.py, lines 2148–2150

namespace=resource.name.split("/")[0]
if resource.name and "/" in resource.name
else None,

For prod:myorg/my-resource:

  • resource.name.split("/")[0]"prod:myorg" (should be "myorg")

Code location 3: src/cleveragents/infrastructure/database/repositories.py, line 1088

row.namespace = ns.namespace  # type: ignore[assignment]

This one correctly uses ns.namespace from a NamespacedName object, so it's fine. But the resource and resource-type repositories use the naive split.


Impact

When a server-qualified resource is stored:

  1. The namespace column in the DB contains prod:myorg instead of myorg
  2. list_by_namespace("myorg") queries will not find the resource
  3. get_by_namespace(namespace="myorg") queries will not find the resource
  4. Namespace-based filtering in CLI commands (--namespace myorg) will fail to return server-qualified resources

Fix Required

Replace the naive name.split("/")[0] with proper namespace extraction that strips the server qualifier:

def _extract_namespace(name: str) -> str | None:
    """Extract the namespace from a [[server:]namespace/]name string."""
    if not name or "/" not in name:
        return None
    # Strip server qualifier if present
    ns_and_name = name.split(":", 1)[-1] if ":" in name else name
    return ns_and_name.split("/")[0]

Or reuse the existing parse_namespaced_name() from domain/models/core/project.py:

from cleveragents.domain.models.core.project import parse_namespaced_name

parsed = parse_namespaced_name(resource_type.name)
namespace = parsed.namespace  # Correctly "myorg" for "prod:myorg/my-resource-type"

Affected Locations

File Line Current Code Issue
repositories.py 1793 resource_type.name.split("/")[0] Includes server qualifier
repositories.py 2148 resource.name.split("/")[0] Includes server qualifier

Metadata

Commit Message: fix(infra): extract namespace correctly for server-qualified names in repositories
Branch Name: fix/repo-namespace-extraction

Subtasks

  • Fix namespace extraction in ResourceTypeRepository.add()
  • Fix namespace extraction in ResourceRepository.add()
  • Add Behave tests for server-qualified resource/resource-type persistence
  • Verify namespace-based queries work correctly for server-qualified names
  • Verify all nox stages pass

Definition of Done

  • ResourceTypeRepository.add() stores namespace="myorg" for prod:myorg/my-type
  • ResourceRepository.add() stores namespace="myorg" for prod:myorg/my-resource
  • list_by_namespace("myorg") returns server-qualified resources
  • All existing tests pass

Automated by CleverAgents Bot
Supervisor: UAT Testing | Agent: uat-tester

## Bug Report **Feature Area:** Namespace management and naming conventions — Database persistence layer **Severity:** Medium — server-qualified resource/resource-type names stored with wrong namespace in DB **Discovered by:** UAT tester (uat-ns-mgmt-001) --- ## Summary Multiple places in `src/cleveragents/infrastructure/database/repositories.py` extract the namespace from a namespaced name using the naive pattern `name.split("/")[0]`. For server-qualified names like `prod:myorg/my-resource`, this extracts `prod:myorg` as the namespace (including the server qualifier), which is semantically incorrect. The namespace should be `myorg`. --- ## Expected Behavior (from spec) The spec (`docs/specification.md`, line 174) defines: > **Namespace**: The scoping segment in the name format `[[server:]namespace/]name`. Defaults to `local/` when omitted. For `prod:myorg/my-resource`: - **server** = `prod` - **namespace** = `myorg` - **name** = `my-resource` The namespace stored in the database should be `myorg`, not `prod:myorg`. --- ## Actual Behavior **Code location 1:** `src/cleveragents/infrastructure/database/repositories.py`, lines 1793–1795 ```python namespace=resource_type.name.split("/")[0] if "/" in resource_type.name else "builtin", ``` For `prod:myorg/my-resource-type`: - `resource_type.name.split("/")[0]` → `"prod:myorg"` ❌ (should be `"myorg"`) **Code location 2:** `src/cleveragents/infrastructure/database/repositories.py`, lines 2148–2150 ```python namespace=resource.name.split("/")[0] if resource.name and "/" in resource.name else None, ``` For `prod:myorg/my-resource`: - `resource.name.split("/")[0]` → `"prod:myorg"` ❌ (should be `"myorg"`) **Code location 3:** `src/cleveragents/infrastructure/database/repositories.py`, line 1088 ```python row.namespace = ns.namespace # type: ignore[assignment] ``` This one correctly uses `ns.namespace` from a `NamespacedName` object, so it's fine. But the resource and resource-type repositories use the naive split. --- ## Impact When a server-qualified resource is stored: 1. The `namespace` column in the DB contains `prod:myorg` instead of `myorg` 2. `list_by_namespace("myorg")` queries will not find the resource 3. `get_by_namespace(namespace="myorg")` queries will not find the resource 4. Namespace-based filtering in CLI commands (`--namespace myorg`) will fail to return server-qualified resources --- ## Fix Required Replace the naive `name.split("/")[0]` with proper namespace extraction that strips the server qualifier: ```python def _extract_namespace(name: str) -> str | None: """Extract the namespace from a [[server:]namespace/]name string.""" if not name or "/" not in name: return None # Strip server qualifier if present ns_and_name = name.split(":", 1)[-1] if ":" in name else name return ns_and_name.split("/")[0] ``` Or reuse the existing `parse_namespaced_name()` from `domain/models/core/project.py`: ```python from cleveragents.domain.models.core.project import parse_namespaced_name parsed = parse_namespaced_name(resource_type.name) namespace = parsed.namespace # Correctly "myorg" for "prod:myorg/my-resource-type" ``` --- ## Affected Locations | File | Line | Current Code | Issue | |---|---|---|---| | `repositories.py` | 1793 | `resource_type.name.split("/")[0]` | Includes server qualifier | | `repositories.py` | 2148 | `resource.name.split("/")[0]` | Includes server qualifier | --- ## Metadata **Commit Message:** `fix(infra): extract namespace correctly for server-qualified names in repositories` **Branch Name:** `fix/repo-namespace-extraction` ### Subtasks - [ ] Fix namespace extraction in `ResourceTypeRepository.add()` - [ ] Fix namespace extraction in `ResourceRepository.add()` - [ ] Add Behave tests for server-qualified resource/resource-type persistence - [ ] Verify namespace-based queries work correctly for server-qualified names - [ ] Verify all nox stages pass ### Definition of Done - [ ] `ResourceTypeRepository.add()` stores `namespace="myorg"` for `prod:myorg/my-type` - [ ] `ResourceRepository.add()` stores `namespace="myorg"` for `prod:myorg/my-resource` - [ ] `list_by_namespace("myorg")` returns server-qualified resources - [ ] All existing tests pass --- **Automated by CleverAgents Bot** Supervisor: UAT Testing | Agent: uat-tester
Author
Owner

Issue triaged by project owner:

  • State: Already In Progress — labels already applied by another agent
  • Priority: Medium — Namespace extraction bug affects server-qualified names. Important for multi-server deployments but local-only usage is unaffected.
  • Milestone: v3.8.0 — Server-qualified names are part of the v3.8.0 Server Implementation scope. This bug only manifests with server-qualified names (prod:myorg/name), which are a v3.8.0 feature.
  • Story Points: 3 — M — Two code locations to fix plus Behave tests. Well-defined change with existing parse_namespaced_name() utility available.
  • MoSCoW: Should Have — Correct namespace persistence is important for data integrity but only affects server-qualified names.
  • Parent Epic: #399 (Epic: Post-MVP Server & Clients)

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

Issue triaged by project owner: - **State**: Already In Progress — labels already applied by another agent - **Priority**: Medium — Namespace extraction bug affects server-qualified names. Important for multi-server deployments but local-only usage is unaffected. - **Milestone**: v3.8.0 — Server-qualified names are part of the v3.8.0 Server Implementation scope. This bug only manifests with server-qualified names (`prod:myorg/name`), which are a v3.8.0 feature. - **Story Points**: 3 — M — Two code locations to fix plus Behave tests. Well-defined change with existing `parse_namespaced_name()` utility available. - **MoSCoW**: Should Have — Correct namespace persistence is important for data integrity but only affects server-qualified names. - **Parent Epic**: #399 (Epic: Post-MVP Server & Clients) --- **Automated by CleverAgents Bot** Supervisor: Project Owner | Agent: project-owner
HAL9000 added this to the v3.8.0 milestone 2026-04-08 18:04:24 +00:00
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.

Dependencies

No dependencies set.

Reference
cleveragents/cleveragents-core#4706
No description provided.