Files
cleveragents-core/features/a2a_server_auth_namespace.feature
freemo b0ab61134d feat(server): implement authentication, authorization, and namespace service
Implement server-mode services for multi-tenant deployments:

- TokenAuthClient: SHA-256 hashed bearer-token authentication with
  configurable TTL, register/revoke/validate operations, and
  constant-time comparison for timing side-channel protection
- AuthorizationService: Namespace-scoped role-based access control
  with viewer/member/admin/owner hierarchy and grant/revoke/check_access
- NamespaceService: In-memory namespace registry with list/show/members
  endpoints backing _cleveragents/namespace/* A2A extension methods
- HealthService: Aggregated health-check probe registry returning
  composite healthy/unhealthy status with per-service details
- DiagnosticsService: Runtime diagnostics collector (Python version,
  platform, uptime, loaded modules, custom checks)
- Server DB tables: server_users, server_tokens (SHA-256 hashed),
  namespace_acls with Alembic migration s1_001
- Facade wiring: namespace/health/diagnostics handlers dispatch to
  real services when registered, fall back to stubs otherwise
- Behave BDD: 23 scenarios covering all services and facade wiring
- Robot integration: 11 test cases with helper script

ISSUES CLOSED: #927
2026-04-02 09:48:43 +00:00

160 lines
6.8 KiB
Gherkin

@phase2 @a2a @server
Feature: Server-mode authentication, authorization, and namespace service
As a server operator
I want token-based auth, namespace-scoped authorization, and namespace queries
So that multi-tenant server deployments are secure and queryable
# -----------------------------------------------------------------------
# TokenAuthClient authentication
# -----------------------------------------------------------------------
Scenario: TokenAuthClient authenticates a valid token
Given a TokenAuthClient with default TTL
And a registered bearer token "tok_server_test_01"
When I authenticate with token "tok_server_test_01"
Then authentication should succeed
Scenario: TokenAuthClient rejects an unknown token
Given a TokenAuthClient with default TTL
When I authenticate with token "tok_unknown_999"
Then authentication should fail
Scenario: TokenAuthClient rejects an expired token
Given a TokenAuthClient with TTL of 1 second
And a registered bearer token "tok_expiring"
And I wait for the token to expire
When I authenticate with token "tok_expiring"
Then authentication should fail
Scenario: TokenAuthClient validates a registered token
Given a TokenAuthClient with default TTL
And a registered bearer token "tok_validate_test"
When I validate token "tok_validate_test"
Then token validation should succeed
Scenario: TokenAuthClient revokes a token
Given a TokenAuthClient with default TTL
And a registered bearer token "tok_to_revoke"
When I revoke token "tok_to_revoke"
Then the revocation should succeed
And authenticating with revoked token "tok_to_revoke" should fail
Scenario: TokenAuthClient rejects empty token in authenticate
Given a TokenAuthClient with default TTL
When I authenticate with an empty token
Then a ValueError should be raised for empty token in server auth
Scenario: TokenAuthClient reports active token count
Given a TokenAuthClient with default TTL
And a registered bearer token "tok_count_1"
And a registered bearer token "tok_count_2"
Then active token count should be 2
# -----------------------------------------------------------------------
# AuthorizationService — namespace-scoped access
# -----------------------------------------------------------------------
Scenario: AuthorizationService grants and checks access
Given an AuthorizationService
And user "u-1" is granted "admin" role in namespace "default"
When I check "write" access for "u-1" in "default"
Then access check should pass
Scenario: AuthorizationService denies insufficient role
Given an AuthorizationService
And user "u-2" is granted "viewer" role in namespace "proj-a"
When I check "write" access for "u-2" in "proj-a"
Then an AuthorizationError should be raised
Scenario: AuthorizationService denies unknown user
Given an AuthorizationService
When I check "read" access for "u-unknown" in "default"
Then an AuthorizationError should be raised
Scenario: AuthorizationService revokes access
Given an AuthorizationService
And user "u-3" is granted "member" role in namespace "ns-x"
When I revoke access for "u-3" in "ns-x"
Then the revocation should report success
And checking "read" access for "u-3" in "ns-x" should raise AuthorizationError
Scenario: AuthorizationService lists user grants
Given an AuthorizationService
And user "u-4" is granted "viewer" role in namespace "ns-a"
And user "u-4" is granted "admin" role in namespace "ns-b"
When I list grants for "u-4"
Then the grants list should contain 2 entries
# -----------------------------------------------------------------------
# NamespaceService — list / show / members
# -----------------------------------------------------------------------
Scenario: NamespaceService lists registered namespaces
Given a NamespaceService with namespaces "default" and "staging"
When I list namespaces
Then the namespace list should contain 2 entries
Scenario: NamespaceService shows namespace details
Given a NamespaceService with namespace "production" owned by "u-owner"
When I show namespace "production"
Then the namespace details should include owner "u-owner"
Scenario: NamespaceService returns members of a namespace
Given a NamespaceService with namespace "team-ns" having 3 members
When I list members of namespace "team-ns"
Then the members list should contain 3 entries
Scenario: NamespaceService raises on unknown namespace show
Given a NamespaceService with namespace "only-one"
When I show namespace "nonexistent"
Then a ResourceNotFoundError should be raised
Scenario: NamespaceService raises on unknown namespace members
Given a NamespaceService with namespace "only-one"
When I list members of namespace "nonexistent"
Then a ResourceNotFoundError should be raised
# -----------------------------------------------------------------------
# HealthService — health check aggregation
# -----------------------------------------------------------------------
Scenario: HealthService returns healthy when no probes fail
Given a HealthService with a healthy probe
When I run the health check
Then the overall status should be "healthy"
Scenario: HealthService returns unhealthy when a probe fails
Given a HealthService with an unhealthy probe
When I run the health check
Then the overall status should be "unhealthy"
# -----------------------------------------------------------------------
# DiagnosticsService — runtime diagnostics
# -----------------------------------------------------------------------
Scenario: DiagnosticsService returns runtime info
Given a DiagnosticsService
When I run diagnostics
Then the diagnostics result should include python version
# -----------------------------------------------------------------------
# Facade wiring — namespace handlers use real services
# -----------------------------------------------------------------------
Scenario: Facade dispatches namespace list to NamespaceService
Given a facade wired with a NamespaceService containing "default"
When I dispatch "_cleveragents/namespace/list"
Then the response should contain 1 namespace
Scenario: Facade dispatches health check to HealthService
Given a facade wired with a HealthService
When I dispatch "_cleveragents/health/check"
Then the server facade response status should be "ok"
And the server response data status should be "healthy"
Scenario: Facade dispatches diagnostics run to DiagnosticsService
Given a facade wired with a DiagnosticsService
When I dispatch "_cleveragents/diagnostics/run"
Then the server facade response status should be "ok"
And the server response data should include python info