feat: integration test suite — 416 tests, 61% coverage
Add OpenBao and Kratos to docker-compose dev stack with bootstrap seeding. Full integration tests hitting real services: - Vault SDK: KV read/write/delete, re-auth on bad token, new_with_token constructor for dev mode - Kratos SDK: list/get/create/disable/enable users, session listing - Token store: PAT lifecycle with OpenBao backing, expiry handling - Identity tools: full tool dispatch through Kratos admin API - Gitea SDK: resolve_username, ensure_token (PAT auto-provisioning), list/get repos, issues, comments, branches, file content - Devtools: tool dispatch for all gitea_* tools against live Gitea - Archive indexer: batch flush, periodic flush task, edit/redact/reaction updates against OpenSearch - Memory store: set/query/get_recent with user scoping in OpenSearch - Room history: context retrieval by timestamp and event_id, access control enforcement - Search archive: keyword search with room/sender filters, room scoping - Code search: language filter, repo filter, branch scoping - Breadcrumbs: symbol retrieval, empty index handling, token budget - Bridge: full event lifecycle mapping, request ID filtering - Evaluator: DM/mention/silence short-circuits, LLM evaluation path, reply-to-human suppression - Agent registry: list/get_id, prompt reuse, prompt-change recreation - Conversations: token tracking, multi-turn context recall, room isolation Bug fixes caught by tests: - AgentRegistry in-memory cache skipped hash comparison on prompt change - KratosClient::set_state sent bare PUT without traits (400 error) - find_code_session returns None on NULL conversation_id
This commit is contained in:
@@ -40,10 +40,71 @@ if [ -z "$ACCESS_TOKEN" ]; then
|
||||
DEVICE_ID=$(echo "$RESPONSE" | python3 -c "import sys,json; print(json.load(sys.stdin)['device_id'])")
|
||||
fi
|
||||
|
||||
# ── OpenBao: seed KV secrets engine ──────────────────────────────────────
|
||||
|
||||
OPENBAO="http://localhost:8200"
|
||||
VAULT_TOKEN="dev-root-token"
|
||||
|
||||
echo ""
|
||||
echo "Waiting for OpenBao..."
|
||||
until curl -sf "$OPENBAO/v1/sys/health" >/dev/null 2>&1; do
|
||||
sleep 1
|
||||
done
|
||||
echo "OpenBao is ready."
|
||||
|
||||
# Write a test secret for integration tests
|
||||
echo "Seeding OpenBao KV..."
|
||||
curl -sf -X POST "$OPENBAO/v1/secret/data/sol-test" \
|
||||
-H "X-Vault-Token: $VAULT_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"data":{"key":"test-secret-value","note":"seeded by bootstrap.sh"}}' \
|
||||
> /dev/null 2>&1 && echo " ✓ secret/sol-test" || echo " – sol-test (already exists or failed)"
|
||||
|
||||
# Write a test token path
|
||||
curl -sf -X POST "$OPENBAO/v1/secret/data/sol-tokens/testuser/gitea" \
|
||||
-H "X-Vault-Token: $VAULT_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"data":{"token":"test-gitea-pat-12345","token_type":"pat","refresh_token":"","expires_at":""}}' \
|
||||
> /dev/null 2>&1 && echo " ✓ secret/sol-tokens/testuser/gitea" || echo " – token (already exists or failed)"
|
||||
|
||||
# ── Kratos: seed test identities ────────────────────────────────────────
|
||||
|
||||
KRATOS_ADMIN="http://localhost:4434"
|
||||
|
||||
echo ""
|
||||
echo "Waiting for Kratos..."
|
||||
until curl -sf "$KRATOS_ADMIN/admin/health/ready" >/dev/null 2>&1; do
|
||||
sleep 1
|
||||
done
|
||||
echo "Kratos is ready."
|
||||
|
||||
echo "Seeding Kratos identities..."
|
||||
curl -sf -X POST "$KRATOS_ADMIN/admin/identities" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"schema_id":"default","traits":{"email":"sienna@sunbeam.local","name":{"first":"Sienna","last":"V"}}}' \
|
||||
> /dev/null 2>&1 && echo " ✓ sienna@sunbeam.local" || echo " – sienna (already exists or failed)"
|
||||
|
||||
curl -sf -X POST "$KRATOS_ADMIN/admin/identities" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"schema_id":"default","traits":{"email":"lonni@sunbeam.local","name":{"first":"Lonni","last":"B"}}}' \
|
||||
> /dev/null 2>&1 && echo " ✓ lonni@sunbeam.local" || echo " – lonni (already exists or failed)"
|
||||
|
||||
curl -sf -X POST "$KRATOS_ADMIN/admin/identities" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"schema_id":"default","traits":{"email":"amber@sunbeam.local","name":{"first":"Amber","last":"K"}}}' \
|
||||
> /dev/null 2>&1 && echo " ✓ amber@sunbeam.local" || echo " – amber (already exists or failed)"
|
||||
|
||||
# ── Summary ─────────────────────────────────────────────────────────────
|
||||
|
||||
echo ""
|
||||
echo "Add these to your .env or export them:"
|
||||
echo ""
|
||||
echo "export SOL_MATRIX_ACCESS_TOKEN=\"$ACCESS_TOKEN\""
|
||||
echo "export SOL_MATRIX_DEVICE_ID=\"$DEVICE_ID\""
|
||||
echo ""
|
||||
echo "Services:"
|
||||
echo " Tuwunel: $HOMESERVER"
|
||||
echo " OpenBao: $OPENBAO (token: $VAULT_TOKEN)"
|
||||
echo " Kratos: $KRATOS_ADMIN"
|
||||
echo ""
|
||||
echo "Then restart Sol: docker compose -f docker-compose.dev.yaml restart sol"
|
||||
|
||||
33
dev/identity.schema.json
Normal file
33
dev/identity.schema.json
Normal file
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"$id": "https://schemas.sunbeam.pt/identity.default.schema.json",
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "Default Identity Schema",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"traits": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"email": {
|
||||
"type": "string",
|
||||
"format": "email",
|
||||
"title": "Email",
|
||||
"ory.sh/kratos": {
|
||||
"credentials": {
|
||||
"password": { "identifier": true }
|
||||
},
|
||||
"recovery": { "via": "email" }
|
||||
}
|
||||
},
|
||||
"name": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"first": { "type": "string", "title": "First Name" },
|
||||
"last": { "type": "string", "title": "Last Name" }
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": ["email"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
}
|
||||
37
dev/kratos.yml
Normal file
37
dev/kratos.yml
Normal file
@@ -0,0 +1,37 @@
|
||||
version: v1.3.1
|
||||
|
||||
dsn: sqlite:///var/lib/sqlite/kratos.db?_fk=true&mode=rwc
|
||||
|
||||
serve:
|
||||
public:
|
||||
base_url: http://localhost:4433/
|
||||
cors:
|
||||
enabled: true
|
||||
admin:
|
||||
base_url: http://localhost:4434/
|
||||
|
||||
selfservice:
|
||||
default_browser_return_url: http://localhost:4433/
|
||||
flows:
|
||||
registration:
|
||||
enabled: true
|
||||
ui_url: http://localhost:4433/registration
|
||||
login:
|
||||
ui_url: http://localhost:4433/login
|
||||
recovery:
|
||||
enabled: true
|
||||
ui_url: http://localhost:4433/recovery
|
||||
|
||||
identity:
|
||||
default_schema_id: default
|
||||
schemas:
|
||||
- id: default
|
||||
url: file:///etc/kratos/identity.schema.json
|
||||
|
||||
log:
|
||||
level: warning
|
||||
format: text
|
||||
|
||||
courier:
|
||||
smtp:
|
||||
connection_uri: smtp://localhost:1025/?disable_starttls=true
|
||||
Reference in New Issue
Block a user