Test Results 118 / 118 Tests PassingEvery compliance-critical path covered. RLS isolation verified at the PostgreSQL layer — not mocked. Results updated on every pull request via GitHub Actions CI.
Test Suites 10 suites · 118 assertions @kakunin/sdk — TypeScript SDK
sdk/kakunin-sdk/tests/sdk.test.ts
Public SDK unit tests. Mocks fetch globally. Covers client construction, model hash utility, all resource wrappers, retry logic, error mapping, and HMAC webhook verification.
Constructor throws if apiKey missing kkn_test_ prefix detected as sandbox mode kkn_live_ prefix is not sandbox computeModelHash → sha256: prefixed 64-char hex computeModelHash is deterministic for same input computeModelHash differs for different inputs agents.create returns agent on 201 agents.create throws KakuninError on 422 agents.certify returns certificate on 201 agents.certify throws on 409 (already certified) agents.getRisk returns risk profile events.ingest returns scored event result events.ingest flags high-risk events (revocation_check_queued: true) certificates.revoke returns revocation result verify.cert returns verified agent info — no Authorization header sent Error mapping: KakuninAuthError thrown on 401 Retry: 500 then 200 → succeeds on second attempt Retry exhausted: throws KakuninError after max retries webhooks.constructEvent verifies valid HMAC-SHA256 signature webhooks.constructEvent throws on invalid signature webhooks.constructEvent throws on stale timestamp (> tolerance) @kakunin/mcp — MCP Server Tools
mcp/kakunin-mcp/tests/mcp.test.ts
MCP tool handler unit tests. Tests all three tools directly without MCP transport. KakuninMcpClient mocked to isolate handler logic.
verify_agent_scope: allows permitted action by exact scope match verify_agent_scope: denies action not in permitted_actions verify_agent_scope: denies when no active certificate verify_agent_scope: denies when certificate is revoked verify_agent_scope: denies when transaction amount exceeds financial scope verify_agent_scope: allows when transaction amount is within limit verify_agent_scope: denies when venue not in permitted_venues verify_agent_scope: allows when venue is in permitted_venues verify_agent_scope: returns permitted_actions list in result check_risk_score: returns low risk profile with stable trend check_risk_score: returns high risk recommendation with revocation warning check_risk_score: returns medium increasing recommendation check_risk_score: handles null drift (< 30 days of data) audit_log_append: returns tx_id and risk score on success audit_log_append: passes session_id through to ingestEvent audit_log_append: flags revocation_check_queued on high-risk event Risk Scoring Engine
__tests__/unit/risk-engine.test.ts
Deterministic expected score for every action type. Band boundary assertions. Auto-revocation threshold checks.
api_call → score 0.05, band low authentication_attempt → score 0.15, band low data_access → score 0.20, band low authentication_failure → score 0.55, band medium data_mutation → score 0.35, band medium transaction_initiated → score 0.30, band medium transaction_anomaly → score 0.85, band high unauthorized_access_attempt → score 0.95, band high Unknown action type → fallback 0.10, band low Band boundary: 0.85 is high (not medium) Band boundary: 0.30 is medium (not low) Auto-revocation: transaction_anomaly ≥ 0.85 Auto-revocation: unauthorized_access_attempt ≥ 0.85 Certificate Issuance
__tests__/api/certify.test.ts
Full certificate issuance flow: agent lookup → KMS signing → DB write → audit log.
Issues certificate and writes audit_log on success Returns 409 when agent already has active certificate Returns 404 when agent not found Returns 422 when agent is retired Returns 503 when AWS KMS credentials not configured Returns 500 on DB insert failure Certificate Verification
__tests__/api/verify.test.ts
Public edge-cached verification endpoint. Cache-Control headers, expiry logic, revocation status.
Returns valid cert with agent info and Cache-Control: s-maxage=300 Returns 404 for unknown serial number Returns 400 for serial shorter than 8 characters (no DB call) Revoked cert returns valid: false with s-maxage=60 Active cert with past expires_at returns status: expired Certificate Revocation
__tests__/api/revoke.test.ts
Manual revocation: cert update, agent suspension, audit trail, CRL refresh via QStash.
Revokes cert and returns status: revoked with timestamp Writes certificate.revoked entry to audit_log Dispatches certificate.revoked webhook event Enqueues CRL regeneration via QStash after revocation Returns 409 when certificate already revoked Returns 422 when certificate is expired Returns 404 when certificate not found or wrong tenant Returns 400 when revocation reason is empty Returns 400 when request body missing reason field Returns 500 on database update failure Behavior Event Ingestion
__tests__/api/events.test.ts
Core event pipeline: Zod validation → quota check → risk scoring → DB write → async side effects.
Ingests low-risk event — returns risk_score, risk_band, event_id Writes behavior.{action_type} to audit_log on success High-risk event queues revocation check via QStash High-risk event dispatches risk.alert webhook Financial: amount > max_single_trade_usd auto-elevates to unauthorized_access_attempt Financial: disallowed venue auto-elevates to unauthorized_access_attempt Returns 429 when monthly event quota exceeded (with Retry-After header) Returns 404 on cross-tenant agent injection attempt Returns 422 when agent is retired Returns 400 on invalid action_type (Zod enum) Returns 400 on non-UUID agentId Returns 500 on database insert failure QStash failure is non-blocking — response still 200 GET: returns events with pagination metadata GET: returns 400 for invalid band parameter GET: returns 400 for invalid action_type parameter GET: clamps limit to maximum 100 Agent Registration
__tests__/api/agents.test.ts
Agent creation and listing. Plan quota enforcement, financial scope metadata, Stripe sync.
Creates agent and returns 201 with agent data Writes agent.created to audit_log on success Fires Stripe subscription quantity sync (fire-and-forget) Stores financial_scope in agent metadata when provided Returns 422 when agent quota exceeded for current plan Returns 400 when name is missing Returns 400 when model_hash is missing Returns 400 when financial_scope is missing required fields Returns 500 on database insert failure GET: returns agents list with total count GET: clamps limit to maximum 100 GET: applies status filter when provided GET: ignores invalid status parameter GET: returns 500 on database error Kill Switch (Halt)
__tests__/api/halt.test.ts
Cryptographic kill switch: signed halt receipt, cert revocation, agent suspension. KMS failure is non-fatal.
Halts agent and returns signed halt receipt Writes agent.halted to audit_log Dispatches agent.halted webhook KMS signing failure is non-fatal — signed_by_ca: false Proceeds without active certificate (agent suspended only) Returns 404 when agent not found Returns 409 when agent is already retired Returns 400 for invalid reason enum value Returns 400 when request body has invalid reason Cross-Tenant RLS Isolation
__tests__/security/rls-isolation.test.ts
Live Supabase test DB. Tenant A cannot read Tenant B data at the PostgreSQL layer — no application-level filter can fake this.
agents table: Tenant A cannot read Tenant B agents certificates table: Tenant A cannot read Tenant B certificates behavior_events table: Tenant A cannot read Tenant B events compliance_reports table: Tenant A cannot read Tenant B reports audit_log table: Tenant A cannot read Tenant B audit entries api_keys table: Tenant A cannot read Tenant B API key hashes audit_log immutability: UPDATE blocked by DB rule (append-only)
What Is Tested vs. Mocked Component Approach Reason Risk scoring logic Real code, no mock Pure function — tests the actual algorithm Certificate issuance Real code, KMS mocked KMS calls require live AWS credentials Supabase DB operations Mocked Avoids test DB dependency; tests business logic in isolation QStash job queue Mocked Fire-and-forget — tested for invocation, not delivery Webhook dispatch Mocked External HTTP — tested for invocation and correct payload AWS KMS signing Mocked Requires live AWS credentials with KMS permissions Stripe billing sync Mocked External API — tested for invocation RLS policies Live test DB Must run against real Postgres RLS engine — cannot mock @kakunin/sdk HTTP client Mocked fetch Tests retry logic, error mapping, and HMAC signing without a live API @kakunin/mcp tool handlers Real code, client mocked Tool handlers tested directly; KakuninMcpClient mocked to isolate logic
Run the Tests Commands All tests (no live DB required) npm run test
Full suite including RLS isolation node --env-file=.env.rls.test node_modules/.bin/vitest run
RLS isolation only node --env-file=.env.rls.test node_modules/.bin/vitest run __tests__/security/rls-isolation.test.ts
Seed RLS test DB (dedicated test project only) npx tsx scripts/setup-rls-test-db.ts
@kakunin/sdk — 21 unit tests cd sdk/kakunin-sdk && npm test
@kakunin/mcp — 16 unit tests cd mcp/kakunin-mcp && npm test
RLS on live Supabase test project