UAT: NamespacedName in plan.py does not reject reserved namespaces (system, internal, admin, root) — spec requires these to be blocked #4423

Open
opened 2026-04-08 12:30:30 +00:00 by HAL9000 · 0 comments
Owner

Metadata

  • Branch: fix/namespaced-name-reserved-namespace-check
  • Commit Message: fix(domain): add reserved namespace check to NamespacedName.validate_namespace() in plan.py
  • Milestone: Backlog
  • Parent Epic: #399

Bug Report

What was tested: NamespacedName validation in src/cleveragents/domain/models/core/plan.py against ADR-002 namespace system spec and the RESERVED_NAMESPACES set defined in project.py.

Expected behavior (from spec, ADR-002):
The spec defines reserved namespaces that must not be used for custom entity registration. The project.py module defines RESERVED_NAMESPACES = frozenset({"system", "internal", "admin", "root"}) and enforces this in parse_namespaced_name().

Actual behavior:
NamespacedName(namespace="system", name="my-action") succeeds without error. The validate_namespace() method in plan.py only checks that the namespace is alphanumeric with hyphens — it does NOT check against the RESERVED_NAMESPACES set.

Code location: src/cleveragents/domain/models/core/plan.py, lines 219-228:

@field_validator("namespace")
@classmethod
def validate_namespace(cls: type[NamespacedName], v: str) -> str:
    """Validate namespace format."""
    if not v:
        return "local"
    # Namespace should be lowercase alphanumeric with hyphens
    if not all(c.isalnum() or c == "-" for c in v):
        raise ValueError("Namespace must be alphanumeric with hyphens only")
    return v.lower()

Contrast with parse_namespaced_name() in project.py (lines 122-130):

if namespace in RESERVED_NAMESPACES:
    raise ValueError(
        f"Namespace '{namespace}' is reserved. "
        f"Reserved: {', '.join(sorted(RESERVED_NAMESPACES))}"
    )

Impact: Plans and actions can be created with reserved namespaces like system/my-plan or admin/my-action. This creates a security and consistency risk — reserved namespaces are intended for system use only.

Steps to reproduce (code-level):

from cleveragents.domain.models.core.plan import NamespacedName
# Should raise ValueError but doesn't:
nn = NamespacedName(namespace="system", name="my-action")
print(nn)  # Prints: system/my-action — should be rejected

nn2 = NamespacedName(namespace="admin", name="my-plan")
print(nn2)  # Prints: admin/my-plan — should be rejected

Fix: Add RESERVED_NAMESPACES check to NamespacedName.validate_namespace() in plan.py, mirroring the check in parse_namespaced_name() in project.py. The RESERVED_NAMESPACES constant should be shared between both modules (ideally moved to a shared constants module).

Related: This is part of a broader inconsistency between NamespacedName (plan.py) and ParsedName/parse_namespaced_name (project.py) — two separate implementations of the same namespace concept with different validation rules. See also #4419 (provider namespace check missing from NamespacedName).


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

## Metadata - **Branch**: `fix/namespaced-name-reserved-namespace-check` - **Commit Message**: `fix(domain): add reserved namespace check to NamespacedName.validate_namespace() in plan.py` - **Milestone**: Backlog - **Parent Epic**: #399 ## Bug Report **What was tested:** `NamespacedName` validation in `src/cleveragents/domain/models/core/plan.py` against ADR-002 namespace system spec and the `RESERVED_NAMESPACES` set defined in `project.py`. **Expected behavior (from spec, ADR-002):** The spec defines reserved namespaces that must not be used for custom entity registration. The `project.py` module defines `RESERVED_NAMESPACES = frozenset({"system", "internal", "admin", "root"})` and enforces this in `parse_namespaced_name()`. **Actual behavior:** `NamespacedName(namespace="system", name="my-action")` succeeds without error. The `validate_namespace()` method in `plan.py` only checks that the namespace is alphanumeric with hyphens — it does NOT check against the `RESERVED_NAMESPACES` set. **Code location:** `src/cleveragents/domain/models/core/plan.py`, lines 219-228: ```python @field_validator("namespace") @classmethod def validate_namespace(cls: type[NamespacedName], v: str) -> str: """Validate namespace format.""" if not v: return "local" # Namespace should be lowercase alphanumeric with hyphens if not all(c.isalnum() or c == "-" for c in v): raise ValueError("Namespace must be alphanumeric with hyphens only") return v.lower() ``` **Contrast with `parse_namespaced_name()` in `project.py`** (lines 122-130): ```python if namespace in RESERVED_NAMESPACES: raise ValueError( f"Namespace '{namespace}' is reserved. " f"Reserved: {', '.join(sorted(RESERVED_NAMESPACES))}" ) ``` **Impact:** Plans and actions can be created with reserved namespaces like `system/my-plan` or `admin/my-action`. This creates a security and consistency risk — reserved namespaces are intended for system use only. **Steps to reproduce (code-level):** ```python from cleveragents.domain.models.core.plan import NamespacedName # Should raise ValueError but doesn't: nn = NamespacedName(namespace="system", name="my-action") print(nn) # Prints: system/my-action — should be rejected nn2 = NamespacedName(namespace="admin", name="my-plan") print(nn2) # Prints: admin/my-plan — should be rejected ``` **Fix:** Add `RESERVED_NAMESPACES` check to `NamespacedName.validate_namespace()` in `plan.py`, mirroring the check in `parse_namespaced_name()` in `project.py`. The `RESERVED_NAMESPACES` constant should be shared between both modules (ideally moved to a shared constants module). **Related:** This is part of a broader inconsistency between `NamespacedName` (plan.py) and `ParsedName`/`parse_namespaced_name` (project.py) — two separate implementations of the same namespace concept with different validation rules. See also #4419 (provider namespace check missing from `NamespacedName`). --- **Automated by CleverAgents Bot** Supervisor: UAT Testing | Agent: uat-tester
HAL9000 added this to the v3.5.0 milestone 2026-04-08 17:42:48 +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#4423
No description provided.