Files
cleveragents-core/features/database_resources.feature
freemo c054675167
CI / benchmark-publish (pull_request) Has been skipped
CI / lint (pull_request) Successful in 15s
CI / quality (pull_request) Successful in 18s
CI / build (pull_request) Successful in 17s
CI / typecheck (pull_request) Successful in 38s
CI / security (pull_request) Successful in 40s
CI / integration_tests (pull_request) Successful in 4m5s
CI / unit_tests (pull_request) Successful in 4m56s
CI / coverage (pull_request) Successful in 5m13s
CI / docker (pull_request) Successful in 1m10s
CI / lint (push) Successful in 13s
CI / quality (push) Successful in 19s
CI / build (push) Successful in 17s
CI / security (push) Successful in 37s
CI / typecheck (push) Successful in 40s
CI / benchmark-regression (push) Has been skipped
CI / unit_tests (push) Successful in 2m59s
CI / integration_tests (push) Successful in 3m24s
CI / docker (push) Successful in 40s
CI / coverage (push) Successful in 5m14s
CI / benchmark-publish (push) Successful in 17m55s
CI / benchmark-regression (pull_request) Successful in 34m15s
feat(resource): add database resources
Implement database resource types (postgres, mysql, sqlite, duckdb)
with connection args, auth handling, and transaction-based sandbox
strategy using BEGIN/ROLLBACK/COMMIT wrappers.

Key changes:
- Add DatabaseResourceHandler with 4 database type definitions
- Implement TransactionSandbox for transaction_rollback strategy
- Wire TransactionSandbox into SandboxFactory
- Register database types in bootstrap_builtin_types
- Add connection validation with credential masking
- Add Behave BDD tests, Robot integration tests, ASV benchmarks

ISSUES CLOSED: #342
2026-03-10 19:29:27 +00:00

229 lines
10 KiB
Gherkin

Feature: Database resource types and transaction sandbox
As a CleverAgents developer
I want database resource types with transaction-based sandboxing
So that I can manage database resources with isolation and rollback
# ---- Resource Type Definitions ----
Scenario: Postgres resource type is defined
Given the database type definitions are loaded
Then the "postgres" type definition should exist
And the "postgres" type should have sandbox strategy "transaction_rollback"
And the "postgres" type should have a "host" cli argument
And the "postgres" type should have a "port" cli argument
And the "postgres" type should have a "dbname" cli argument
And the "postgres" type should have a "user" cli argument
And the "postgres" type should have a "password" cli argument
And the "postgres" type should have a "connection-string" cli argument
Scenario: MySQL resource type is defined
Given the database type definitions are loaded
Then the "mysql" type definition should exist
And the "mysql" type should have sandbox strategy "transaction_rollback"
And the "mysql" type should have a "host" cli argument
And the "mysql" type should have a "port" cli argument
Scenario: SQLite resource type is defined
Given the database type definitions are loaded
Then the "sqlite" type definition should exist
And the "sqlite" type should have sandbox strategy "transaction_rollback"
And the "sqlite" type should have a "path" cli argument
Scenario: DuckDB resource type is defined
Given the database type definitions are loaded
Then the "duckdb" type definition should exist
And the "duckdb" type should have sandbox strategy "transaction_rollback"
And the "duckdb" type should have a "path" cli argument
# ---- Connection Argument Validation ----
Scenario: Resolve postgres connection args from properties
Given postgres connection properties with host "db.example.com" port 5432 dbname "mydb"
When I resolve connection args for "postgres"
Then the resolved args should have host "db.example.com"
And the resolved args should have port 5432
And the resolved args should have dbname "mydb"
Scenario: Resolve postgres connection args from connection string
Given postgres properties with connection string "postgresql://admin:secret@db:5432/app"
When I resolve connection args for "postgres"
Then the resolved args should have connection string "postgresql://admin:secret@db:5432/app"
Scenario: Resolve postgres credentials from env vars
Given postgres properties without explicit credentials
And the env var "CLEVERAGENTS_DB_USER" is set to "envuser"
And the env var "CLEVERAGENTS_DB_PASSWORD" is set to "envpass"
When I resolve connection args for "postgres"
Then the resolved args should have user "envuser"
And the resolved args should have password "envpass"
Scenario: Resolve sqlite connection args
Given sqlite properties with path "/tmp/test.db"
When I resolve connection args for "sqlite"
Then the resolved args should have path "/tmp/test.db"
Scenario: Resolve duckdb connection args with default memory
Given duckdb properties with no path
When I resolve connection args for "duckdb"
Then the resolved args should have path ":memory:"
# ---- Credential Masking in Error Messages ----
Scenario: Credential masking in postgres validation message
Given postgres connection properties with user "admin" and password "s3cret"
When I validate the "postgres" connection
Then the validation message should not contain "s3cret"
And the validation result should be successful
Scenario: Connection string credentials are masked
Given postgres properties with connection string "postgresql://admin:s3cret@db:5432/app"
When I validate the "postgres" connection
Then the validation message should not contain "s3cret"
# ---- Read-Only Enforcement ----
Scenario: Read-only transaction sandbox rejects writes
Given a temporary SQLite database with a test table
And a transaction sandbox in read-only mode
When I attempt to insert data via the sandbox
Then the sandbox should reject the write operation
# ---- Transaction Sandbox Create / Commit / Rollback ----
Scenario: Transaction sandbox lifecycle create and commit
Given a temporary SQLite database with a test table
And a transaction sandbox for the database
When I create the sandbox with plan "PLAN-TX-001"
And I insert a row via the sandbox
And I commit the sandbox
Then the row should be persisted in the database
Scenario: Transaction sandbox lifecycle create and rollback
Given a temporary SQLite database with a test table
And a transaction sandbox for the database
When I create the sandbox with plan "PLAN-TX-002"
And I insert a row via the sandbox
And I rollback the sandbox
Then the row should not be persisted in the database
Scenario: Transaction sandbox cleanup closes connection
Given a temporary SQLite database with a test table
And a transaction sandbox for the database
When I create the sandbox with plan "PLAN-TX-003"
And I cleanup the sandbox
Then the sandbox status should be "cleaned_up"
# ---- SQLite Resource Handler Roundtrip ----
Scenario: SQLite validate_connection success
Given a temporary SQLite database
When I validate the sqlite connection
Then the sqlite validation should succeed
Scenario: SQLite validate_connection with memory database
When I validate an in-memory sqlite connection
Then the sqlite validation should succeed
# ---- DatabaseResourceHandler Protocol ----
Scenario: DatabaseResourceHandler satisfies ResourceHandler protocol
Given a DatabaseResourceHandler instance
Then the handler should satisfy the ResourceHandler protocol
Scenario: DatabaseResourceHandler uses transaction_rollback strategy
Given a DatabaseResourceHandler instance
Then the handler default strategy should be "transaction_rollback"
# ---- SandboxFactory transaction_rollback routing ----
Scenario: SandboxFactory creates TransactionSandbox for transaction_rollback
Given the sandbox factory is available
When a sandbox is requested for resource "db-1" at ":memory:" using transaction_rollback
Then the created sandbox should be a TransactionSandbox
Scenario: SandboxFactory reports transaction_rollback as supported
Given the sandbox factory is available
Then the factory should report "transaction_rollback" as supported
# ---- TransactionSandbox edge cases ----
Scenario: TransactionSandbox rejects empty resource_id
When I create a TransactionSandbox with empty resource_id
Then the edge error should be a ValueError mentioning "resource_id"
Scenario: TransactionSandbox rejects empty original_path
When I create a TransactionSandbox with empty original_path
Then the edge error should be a ValueError mentioning "original_path"
Scenario: TransactionSandbox rejects empty plan_id
Given a temporary SQLite database with a test table
And a transaction sandbox for the database
When I try to create the sandbox with an empty plan_id
Then the edge error should be a ValueError mentioning "plan_id"
Scenario: TransactionSandbox get_path returns db path
Given a temporary SQLite database with a test table
And a transaction sandbox for the database
When I create the sandbox with plan "PLAN-PATH"
Then get_path should return the database path
Scenario: TransactionSandbox get_path rejects traversal
Given a temporary SQLite database with a test table
And a transaction sandbox for the database
When I create the sandbox with plan "PLAN-TRAV"
Then get_path with traversal should raise ValueError
Scenario: TransactionSandbox get_path in wrong state raises
Given a temporary SQLite database with a test table
And a transaction sandbox for the database
Then get_path before create should raise SandboxStateError
Scenario: TransactionSandbox commit in wrong state raises
Given a temporary SQLite database with a test table
And a transaction sandbox for the database
Then commit before create should raise SandboxStateError
Scenario: TransactionSandbox rollback in wrong state raises
Given a temporary SQLite database with a test table
And a transaction sandbox for the database
Then rollback before create should raise SandboxStateError
Scenario: TransactionSandbox cleanup is idempotent
Given a temporary SQLite database with a test table
And a transaction sandbox for the database
When I create the sandbox with plan "PLAN-IDEM"
And I cleanup the sandbox
And I cleanup the sandbox again
Then the sandbox status should be "cleaned_up"
Scenario: TransactionSandbox execute in wrong state raises
Given a temporary SQLite database with a test table
And a transaction sandbox for the database
Then execute before create should raise SandboxStateError
Scenario: TransactionSandbox cleanup with active transaction
Given a temporary SQLite database with a test table
And a transaction sandbox for the database
When I create the sandbox with plan "PLAN-ACT"
And I insert a row via the sandbox
And I cleanup the sandbox
Then the sandbox status should be "cleaned_up"
Scenario: DuckDB validate_connection stub
When I validate a duckdb connection with path ":memory:"
Then the duckdb validation should succeed with a stub message
Scenario: MySQL validate_connection stub
Given mysql connection properties with host "db.example.com" and port 3306
When I validate the "mysql" connection
Then the validation result should be successful
Scenario: Unknown database type validation
When I validate an unknown database type
Then the unknown validation should fail
Scenario: Resolve mysql connection args from connection string
Given mysql properties with connection string "mysql://user:pass@host:3306/db"
When I resolve connection args for "mysql"
Then the resolved args should have connection string "mysql://user:pass@host:3306/db"