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:
2026-03-24 14:34:03 +00:00
parent b3a38767e0
commit 5dc739b800
8 changed files with 3105 additions and 3 deletions

View File

@@ -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"