Skip to content

kyvvu-api changelog

All notable changes to the Kyvvu API are documented in this file.

Versions before 0.8.0 were alpha releases with frequent breaking changes to schemas, endpoints, and database models. The changelog starts from the first beta release.


[1.0.0] - 2026-10-28

  • 1.0: API 1.0 is the platform half of the 1.0 release. It still serves kyvvu-engine 0.13.0 and newer (MIN_ENGINE_VERSION unchanged), so 0.x agents keep working; the Python client 1.0 requires it.

  • Added: POST /logs/batch verifies a client-computed hash chain. A step may carry hash (the v1 entry hash, 64 lowercase hex); a batch that does carries it on every step with its seq, contiguous, and must continue the stored chain: the first seq is the stored tail + 1 and each hash equals the server's recomputation, checked under the task lock in the storing transaction. Otherwise the batch is refused whole with 422 and detail.code seq_mismatch (index, seq, expected_seq) or hash_mismatch (index, seq, expected_hash), and nothing is stored. An identical retry under the same Idempotency-Key is still answered from its receipt first, and a stored action_id is still a 409. A batch without hash is numbered and hashed by the server exactly as before; mixing the two in one batch, or hash without seq, is a 422. The server's hash computation now calls kyvvu_engine.chain_entry_hash; the algorithm, chain_version: "v1", the stored rows and the pre-0054 step fallback in validation are unchanged. No migration.

[0.22.0] - 2026-10-17

  • Changed: the bundled library's eu-ai-act-minimal.yaml is 1.1.0, byte-identical to the SDK baseline and kyvvu-manifests-public: the content-marking policy requires a gate between a model output and its delivery instead of before every model call.

  • Removed: HMAC signing of policy fetch responses. The API returns validated policy models; Ed25519 signing is planned.

  • Breaking: The log ordinal is seq: the logs.seq column and its uq_agent_task_seq constraint (the migration that introduced seq, run under the maintenance cutover), the log and chain-validation responses, the audit XML <seq> element, and the hash input key. A batch step that carries step is refused (422) naming seq.

  • Breaking: The behaviour field is kind and its enum is ActionKind; the retired field and enum names are rejected. Policy kind parameters are target_kinds, trigger_kinds, forbidden_kind, forbidden_kinds, required_kind, taint_kind, and forbidden_predecessor_kinds; old parameter names are rejected. A step policy's field needs a complete path such as input.recipient or properties.message.recipient (that is, input.<name> or properties.<name>); bare data field names are rejected.

[0.21.0] - 2026-10-01

Added

  • Restore an unassigned baseline manifest. POST /api/v1/assignments with the bundled manifest path and no repo_id restores it, tagged Baseline and pinned to the bundled file's SHA-256; the dashboard's Manifests page and the agent page offer the same. Re-registering never re-applies an unassigned baseline. Restoring one already assigned, or whose policy names overlap another assigned manifest, returns 409.
  • GET /api/v1/policies/rules lists each rule's requires.

Changed

  • POST/PUT /api/v1/policies return 422 for an unknown rule_type or params that do not match the rule, and the manifest validator refuses unknown rule types and duplicate policy names. The platform no longer stores a policy that every agent would refuse to load.
  • Policy risk_classification assignment and evaluation agree: "this class or above".
  • Library manifests (claude-code-safety, data-exfiltration-guard, healthcare-nen7510-hipaa) follow the engine's changes: field_matches_regex patterns are anchored with ^ for re.search, and domain_allowlist is scoped to step.resource.

[0.16.0] - 2026-08-27

Breaking. Restores the task.* step-type namespace across the API, and closes the ingest surfaces that let unknown step types through.

Breaking changes

  • The four task-boundary StepType values return to task.*: step.task_start → task.start, step.task_end → task.end, step.task_error → task.error, step.task_idle → task.idle. Migration 0019_restore_task_namespace rewrites logs.step_type accordingly. The eight step.* behavioral values are untouched.
  • step_type is now validated against the enum on the way in. The batch ingest (POST /logs/batch), the hosted evaluation payload (POST /engine/evaluate), and the engine incident payload all typed it as a bare str, so an unknown value was accepted and stored — and a task whose end marker was misspelled read as running forever. These now return 422. The step_type query filter on GET /logs is likewise typed.

Notes

  • LogDetail.step_type (the read model) stays str | None on purpose. It is built straight from logs.step_type, and ingest accepted arbitrary strings before this release, so validating on read would turn one leftover row into a 500 for the whole log page. The vocabulary is enforced on the way in.
  • Migration 0019 does not restore logs.granularity (dropped in 0016 and still derivable from the type prefix), does not touch policies.evaluate_at (write-only, and NULL in every production row), and does not rewrite incidents.details (an immutable record of what the engine reported at the time).

[0.10.0] - 2026-05-14

Added

  • Repos module: GitHub repository connections with encrypted token storage
  • Assignments module: manifest-to-agent assignment with policy materialization
  • GET /agents/{agent_id}/last-fetch: policy retrieval timestamp
  • Manifest YAML validation (structure, severity, scope, risk_classification)
  • Validate endpoints accept JWT via verify_either_auth

Changed

  • Dashboard restyled: sidebar navigation (6 tabs), Settings page with sub-tabs
  • kyvvu init simplified to pure scaffolding (no auth, no policy application)
  • Policy unique constraint now includes agent_id (allows per-agent duplicates from manifests)
  • Events API returns user_name field (resolved from User relationship)

Removed

  • Policy template system: /policy-templates/* endpoints, TemplateLoader, template YAML files
  • Base.metadata.create_all() from app lifespan (Alembic-only schema management)
  • Templates and Policies tabs from dashboard
  • Default seeded policies (replaced by manifest assignment)

[0.8.0] - 2026-04-28

First beta release. The API surface is now stable — breaking changes will be versioned and documented going forward.

Breaking changes from alpha (< 0.8.0)

  • Agent registration: agent_key and risk_classification moved from register_agent() to the SDK constructor. The API endpoint contract is unchanged, but SDK callers must update.
  • Risk classification: unacceptable is now rejected at registration (EU AI Act Article 5).
  • Incident listing: Filter parameters (environment, status, severity) now use Literal types. Invalid values return 422 instead of 400.
  • Pagination defaults: All list endpoints standardised to skip=0, limit=50 (was 100 in some endpoints). Max remains 1000.
  • Policy templates: POST /policy-templates/{id}/apply request body extended with optional agent_id, risk_classification, and policy_names targeting fields. Response includes policies_skipped.
  • Incident enrichment: Response now includes agent_identifier field alongside agent_id.

Added

  • Login rate limiting (5 attempts / 15 min per IP, HTTP 429).
  • Unverified org members blocked from API key creation (HTTP 403).
  • DB connectivity check on startup (fail-fast).
  • CORS wildcard warning when KV_ENVIRONMENT=production.
  • Cross-org policy isolation in incident creation.
  • Soft-deleted policy filter on engine incident path.
  • Bulk N+1 fix for incident enrichment.
  • Cache invalidation before commit on API key deletion/toggle.
  • Owner ID validation for orgless API keys.
  • Policy template targeting: apply to specific agent, override risk classification, select policies by name.
  • 14 new hardening tests (rate limiting, cross-org, batch retry, API key verification).

Fixed

  • Background batch retry no longer blocks worker thread (time.sleep removed).
  • verify_password now logs exceptions before returning False.
  • PostgreSQL-specific SQL (func.left, func.concat) replaced with portable func.substr and + operator.
  • Event model default ID format aligned with event logger (evt_ prefix).
  • Pre-existing test test_agent_key_requires_instance_422 updated to match relaxed endpoint behaviour.

Improved

  • Consolidated duplicate get_user_agent_ids() into core/queries.py.
  • Conditional imports in policies/router.py moved to module level.
  • Column aliasing (meta / metadata) documented in models.
  • Docstrings expanded for background batch write and incident enrichment.
  • Fragility comment added to event substring access check.