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-engine0.13.0 and newer (MIN_ENGINE_VERSIONunchanged), so 0.x agents keep working; the Python client 1.0 requires it. -
Added:
POST /logs/batchverifies a client-computed hash chain. A step may carryhash(the v1 entry hash, 64 lowercase hex); a batch that does carries it on every step with itsseq, contiguous, and must continue the stored chain: the firstseqis 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 anddetail.codeseq_mismatch(index,seq,expected_seq) orhash_mismatch(index,seq,expected_hash), and nothing is stored. An identical retry under the sameIdempotency-Keyis still answered from its receipt first, and a storedaction_idis still a 409. A batch withouthashis numbered and hashed by the server exactly as before; mixing the two in one batch, orhashwithoutseq, is a 422. The server's hash computation now callskyvvu_engine.chain_entry_hash; the algorithm,chain_version: "v1", the stored rows and the pre-0054stepfallback in validation are unchanged. No migration.
[0.22.0] - 2026-10-17¶
-
Changed: the bundled library's
eu-ai-act-minimal.yamlis 1.1.0, byte-identical to the SDK baseline andkyvvu-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: thelogs.seqcolumn and itsuq_agent_task_seqconstraint (the migration that introducedseq, 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 carriesstepis refused (422) namingseq. -
Breaking: The behaviour field is
kindand its enum isActionKind; the retired field and enum names are rejected. Policy kind parameters aretarget_kinds,trigger_kinds,forbidden_kind,forbidden_kinds,required_kind,taint_kind, andforbidden_predecessor_kinds; old parameter names are rejected. A step policy'sfieldneeds a complete path such asinput.recipientorproperties.message.recipient(that is,input.<name>orproperties.<name>); bare data field names are rejected.
[0.21.0] - 2026-10-01¶
Added¶
- Restore an unassigned baseline manifest.
POST /api/v1/assignmentswith the bundled manifest path and norepo_idrestores 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/ruleslists each rule'srequires.
Changed¶
POST/PUT /api/v1/policiesreturn 422 for an unknownrule_typeor 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_classificationassignment 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_regexpatterns are anchored with^forre.search, anddomain_allowlistis scoped tostep.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
StepTypevalues return totask.*:step.task_start→task.start,step.task_end→task.end,step.task_error→task.error,step.task_idle→task.idle. Migration0019_restore_task_namespacerewriteslogs.step_typeaccordingly. The eightstep.*behavioral values are untouched. step_typeis 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 barestr, so an unknown value was accepted and stored — and a task whose end marker was misspelled read asrunningforever. These now return 422. Thestep_typequery filter onGET /logsis likewise typed.
Notes¶
LogDetail.step_type(the read model) staysstr | Noneon purpose. It is built straight fromlogs.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
0019does not restorelogs.granularity(dropped in0016and still derivable from the type prefix), does not touchpolicies.evaluate_at(write-only, andNULLin every production row), and does not rewriteincidents.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 initsimplified 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_namefield (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_keyandrisk_classificationmoved fromregister_agent()to the SDK constructor. The API endpoint contract is unchanged, but SDK callers must update. - Risk classification:
unacceptableis now rejected at registration (EU AI Act Article 5). - Incident listing: Filter parameters (
environment,status,severity) now useLiteraltypes. 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}/applyrequest body extended with optionalagent_id,risk_classification, andpolicy_namestargeting fields. Response includespolicies_skipped. - Incident enrichment: Response now includes
agent_identifierfield alongsideagent_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.sleepremoved). verify_passwordnow logs exceptions before returningFalse.- PostgreSQL-specific SQL (
func.left,func.concat) replaced with portablefunc.substrand+operator. - Event model default ID format aligned with event logger (
evt_prefix). - Pre-existing test
test_agent_key_requires_instance_422updated to match relaxed endpoint behaviour.
Improved¶
- Consolidated duplicate
get_user_agent_ids()intocore/queries.py. - Conditional imports in
policies/router.pymoved 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.