Skip to content

v0.5.0

Latest

Choose a tag to compare

@github-actions github-actions released this 26 Jul 18:38

Korvun v0.5.0

The fifth release adds Korvun's third channel: a generic Webhook. Any system that
speaks JSON over HTTP becomes a mouth into Korvun — no provider account, no SDK.
No breaking changes: every existing config runs exactly as before, and go.mod is
untouched (stdlib only).

Highlights

Generic Webhook channel (ADR-0038)

The Stage-2 webhook adapter is now a first-class core channel: declare type: "webhook" in your config and Korvun opens an authenticated HTTP endpoint that turns
inbound JSON into a message, routes it through a brain, and POSTs the reply back to a
URL you choose. What it brings:

  • Mandatory, fail-closed Bearer auth. Every request must carry Authorization: Bearer <secret>, compared in constant time (SHA-256 + subtle.ConstantTimeCompare
    — the same mechanism as the admin gate, ADR-0028 §1). An empty/unresolved secret
    rejects every request; the body is never read on a 401, and the secret never
    appears in a log or error.
  • Conversation identity. A configurable conversation_id field groups messages
    into one conversation for brain memory; when a payload omits it, Korvun falls back
    to the sender id
    , and the reply echoes the conversation id back to your
    outbound URL.
  • Honest saturation. A momentarily full inbound buffer answers 503 (retry
    later)
    and counts the drop — it never blocks the HTTP goroutine on a slow
    brain.
  • Loopback by default, warned when exposed. The endpoint binds 127.0.0.1:8090;
    binding a non-loopback address emits a loud boot warning that the Bearer secret
    would cross the network in cleartext without a TLS-terminating reverse proxy in
    front (Korvun terminates no TLS itself).
  • Two env-only secrets. token_env (inbound, required) and an optional
    outbound_token_env (outbound Bearer to your receiver) — both are env-var names,
    never values (ADR-0010). A named outbound secret that does not resolve at boot is
    a loud, named error, never a silent unauthenticated outbound.
  • Edge validation. POST only (else 405), application/json (else 415), ≤ 1 MiB
    body (else 413), well-formed JSON with a sender and content (else 400).

Validated end to end on real hardware (2026-07-26, Intel iMac, macOS 13): a real
curl message into the webhook was routed through a local llama3.2:1b brain and the
reply — carrying the same conversation_id — arrived at a one-line test receiver in
~11s cold / ~1s warm; the unauthenticated request was correctly rejected with 401, and
the process shut down cleanly on SIGINT.

New guide — zero to round-trip

A new docs/WEBHOOK-SETUP.md walks the whole path: generate the
secret (openssl rand -hex 32), curl a message in, watch the brain's replies with a
one-line python3 test receiver, read what each rejection means (401/415/413/400,
and 503 = retry), and expose it safely behind a minimal reverse-proxy/TLS snippet. The
full schema lives in the new webhook section of
docs/CONFIGURATION.md, and configs/korvun.example.json ships
a webhook channel example.

Korvun Desktop carries it too

Korvun Desktop 0.5.0 embeds the webhook channel in the core from day one — it is
declarable by JSON config exactly like the headless binary. The visual form for it
arrives later with the Builder-canvas; today it is config-driven.

Compatibility

No breaking changes. The schema addition is strictly additive: existing
telegram/discord configs parse, validate, and behave byte-for-byte as before. Zero
new dependencies
— the channel is pure standard library (net/http, crypto/sha256,
crypto/subtle), so go.mod is unchanged.

Minor

  • V1 criteria updated on the roadmap; the Webhook piece marked complete
    (docs/ROAD-TO-BETA.md).
  • Docs: WEBHOOK-SETUP.md, the webhook block in CONFIGURATION.md, the example
    config, and the setup/config cross-links.

Artifacts

Two families in one release, exactly as v0.4.0. <ver> is the version without the
leading v (e.g. 0.5.0).

Family Artifact Target
Headless korvun_<ver>_{linux,darwin}_{amd64,arm64}.tar.gz, korvun_<ver>_windows_{amd64,arm64}.zip server / CLI, six OS·arch
Headless checksums.txt + .sig + .pem, per-archive *.sbom.json signed manifest + SBOMs
Desktop korvun-desktop_<ver>_darwin_universal.dmg macOS universal app
Desktop korvun-desktop_<ver>_windows_amd64-installer.exe Windows NSIS installer
Desktop korvun-desktop_<ver>_linux_amd64.tar.gz Linux binary + .desktop
Desktop checksums-desktop.txt + .sig + .pem signed desktop manifest

Draft-until-complete: the release is born a draft and is published only once
both families and their signatures are present, so a broken desktop build can never
expose a half-populated public release (ADR-0035 §8; SP7 §1e).

Verifying this release

Both families are signed keyless with cosign
(Sigstore), each with its own manifest. Verify the manifest signature you need, then
check your download against it.

Headless:

cosign verify-blob checksums.txt \
  --signature checksums.txt.sig \
  --certificate checksums.txt.pem \
  --certificate-identity-regexp 'https://github.com/Sebastian197/korvun/.*' \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com

Desktop:

cosign verify-blob checksums-desktop.txt \
  --signature checksums-desktop.txt.sig \
  --certificate checksums-desktop.txt.pem \
  --certificate-identity-regexp 'https://github.com/Sebastian197/korvun/.*' \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com

Full install and verification walkthrough: docs/packaging/INSTALL.md.
For the webhook channel specifically: docs/WEBHOOK-SETUP.md.