Skip to content

Releases: HeliosDatabase/HeliosDB-Proxy

v1.7.0

Choose a tag to compare

@github-actions github-actions released this 11 Sep 06:21

Full Changelog: v1.6.1...v1.7.0

v1.6.1

Choose a tag to compare

@github-actions github-actions released this 09 Sep 20:22

What's Changed

  • 1.5.0 verification: Criterion re-baseline + regress nano-case fix by @danimoya in #43

Full Changelog: v1.6.0...v1.6.1

v1.6.0

Choose a tag to compare

@github-actions github-actions released this 04 Sep 14:01

What's Changed

  • ci: bump Node-20-deprecated actions to Node-24 majors by @danimoya in #39
  • ci: split always-red Integration job (integrate-pg required + integrate-nano non-blocking) by @danimoya in #38

Full Changelog: v1.5.0...v1.6.0

v1.5.0

Choose a tag to compare

@github-actions github-actions released this 11 Jul 20:34

Minor release — interface coverage ([limits]/[anomaly]/[plugins].kv_* config), plugin-KV admin endpoints, PG-wire protocol benchmarks, and security hardening (stored-XSS fix in the admin dashboard). Feature-additive with one default-behavior change (plugin kv_set is now bounded — see Changed).

Added

  • [limits] config section — eleven operational safety bounds (ten
    formerly-named consts plus the previously-inline 30s backend read timeout)
    that were hardcoded in src/server.rs are now tunable via proxy.toml. Each
    default reproduces the prior constant exactly, resolved once at startup, so a
    config without a [limits] block is byte-for-byte unchanged. Keys (default):
    max_cancel_keys (100000), startup_timeout_secs (30),
    backend_write_timeout_secs (30), backend_read_timeout_secs (30),
    client_write_timeout_secs (60), reprepare_timeout_secs (15),
    max_prepared_statements (8192), max_prepared_bytes (67108864 / 64 MiB),
    max_pending_bytes (67108864 / 64 MiB),
    max_total_idle_backend_conns (8192, pool-modes), and
    pool_reap_interval_secs (30). validate() rejects a 0 for any of these
    (a safety bound, not "unbounded") with a key-named error, and caps every
    *_secs timeout at one year (31536000) — a value above that would overflow
    the connect-time Instant + Duration deadline and panic the per-connection
    task, so it is refused up front.
  • [anomaly] config section — the in-process anomaly detector previously
    ran on a hardcoded AnomalyConfig::default() plus a MAX_SEEN_FINGERPRINTS
    module const with no way to tune it. Its eight tunables are now exposed via
    proxy.toml, defaults reproducing the prior behavior exactly: rate_window_secs
    (60), spike_z_threshold (3.0), auth_window_secs (60), auth_critical_count
    (10), auth_warning_count (5), event_buffer_size (1024), emit_novel_queries
    (true), and max_seen_fingerprints (100000). validate() rejects degenerate
    values (windows/buffer/fingerprint-cap > 0, spike_z_threshold finite and
    > 0, auth_critical_count >= 1, auth_warning_count <= auth_critical_count).
    The detector is built once at startup, so changing [anomaly] requires a
    restart (a SIGHUP reload does not rebuild it).
  • /admin/kv/<plugin>/<key> admin endpoints — the per-plugin KV store
    (KvBackend, read by plugins through their kv_get/kv_set host imports)
    can now be read, written, listed, and deleted from outside the WASM sandbox,
    so operators can push a plugin's runtime config (budgets, region maps, mask
    rules, allowlists) without a restart. GET /admin/kv/<plugin>/<key> returns
    {"plugin","key","value"} (404 if absent), GET /admin/kv/<plugin>/
    (trailing slash) lists the namespace as {"plugin","keys":[...]},
    PUT sets a value (UTF-8 body via from_utf8_lossy), and DELETE removes one
    (idempotent 200). A trailing-slash list accepts an optional ?prefix= filter;
    any query string is stripped before the plugin/key split, so ?… never leaks
    into a stored key, and an empty <plugin> segment (/admin/kv//<key>) is
    rejected 400. All four sit behind the normal admin bearer gate; the build
    returns 501 without --features wasm-plugins and 503 when no plugin
    manager is attached. Four [plugins] caps bound writes and are tunable
    (0 = unlimited): kv_max_value_bytes (default 65536, now bounds a single
    key OR value), kv_max_keys_per_plugin (default 1024), kv_max_plugins
    (default 256, bounds how many <plugin> namespaces can exist so a token-holder
    cannot exhaust memory by writing to unboundedly-many namespace names), and
    kv_max_total_bytes (default 67108864 / 64 MiB) — a total-footprint backstop
    that sums each entry's key + value bytes plus each live namespace's name bytes
    and keeps the whole store within a survivable ceiling regardless of the
    per-axis product (which could otherwise retain tens of GiB). A PUT
    past a cap returns 413 (and the in-WASM kv_set returns -1); an oversized
    body is rejected before it is copied. Overwriting an existing key never trips
    the key-count cap, writing to an existing namespace never trips the namespace
    cap, and deleting a namespace's last key frees its slot (the reclaimed bytes
    are subtracted from the total-footprint counter too).
    Keys must not contain ?: a query string is stripped before the plugin/key
    split (so ?prefix= can filter a listing), which means a plugin-created key
    containing ? is listable but not addressable via GET/DELETE over the admin
    surface.
  • benches/protocol.rs — a Criterion benchmark covering the PG-wire
    per-query hot path that every client frame and backend response flows
    through, previously uncovered by the pool/routing benches (so a regression
    there was invisible to quality gate 3). Three groups —
    protocol/decode_message, protocol/encode_message, and
    protocol/query_text — each run over three payload sizes (a trivial
    SELECT 1, a ~60-char WHERE query, and a deterministically-built ~1 KiB
    IN (...) statement) with Throughput::Bytes so a regression surfaces as
    both a per-call delta and a bytes/sec change. Feature-free: it exercises only
    the always-public protocol API, so it compiles under every feature set.

Changed

  • Plugin kv_set is now bounded (was unbounded in 1.4.0). The per-plugin KV
    store went from an infallible unbounded write to a capped one. The in-WASM
    kv_set import keeps its i32 ABI — 0 on success, -1 when the write is
    refused (a cap breach now joins the internal-error case in returning -1);
    the internal store set() method that backs it changed from returning () to
    returning a bool (false = refused). The new [plugins] caps default to
    kv_max_value_bytes 65536,
    kv_max_keys_per_plugin 1024, kv_max_plugins 256, and kv_max_total_bytes
    67108864 (64 MiB). Upgrade impact: a plugin deployed under 1.4.0 that
    stored values larger than 64 KiB, or more than 1024 keys in its namespace,
    will silently start receiving -1 from kv_set after upgrade — writes past a
    cap fail instead of succeeding. Setting any kv_* cap to 0 disables that
    cap and restores the unbounded 1.4.0 behavior for that axis (set all four to
    0 for byte-for-byte 1.4.0 semantics).
  • CI now lints test code (cargo clippy --tests) — both clippy invocations
    in .github/workflows/ci.yml gained --tests, so #[cfg(test)] modules and
    the tests/ integration crate are held to the same -D warnings bar as the
    library. Pre-existing clippy::field_reassign_with_default warnings in test
    code (converted let mut x = T::default(); x.field = …; sequences into
    struct-literal T { field: …, ..Default::default() } initializers, behavior
    unchanged) were cleared so the gate starts green.
  • Rewrote docs/transaction-replay.md and docs/topology-providers.md against
    the current code.
    Both documents were conceptually dated. The TR deep dive is now
    grounded in src/transaction_journal.rs, src/failover_replay.rs,
    src/failover_controller.rs, src/switchover_buffer.rs, src/replay/mod.rs, and the
    tr_enabled / tr_mode / write_timeout_secs keys — correcting invented keys
    (tr_max_journal_bytes, switchover_drain_timeout_secs never existed), the
    write_timeout_secs default (30, not 15), the default tr_mode (session), the
    text-format (not binary) replay parameter path, and the fact that session-state/cursor
    migration exists only as unwired library modules (src/cursor_restore.rs,
    src/session_migrate.rs) not reachable from the replay path, while
    FailoverController/PrimaryTracker are library components rather than
    daemon-wired. The topology doc now separates the daemon's
    static-role-plus-health primary tracking (surfaced at /topology) from the
    TopologyProvider library abstraction, and notes the PostgreSQL provider is constructed
    programmatically (not from [[nodes]]). Each doc carries a "last verified against"
    commit line.

Fixed

  • /healthz, /livez, /readyz admin routes — these three
    Kubernetes-style probe paths were already token-exempt in the admin auth gate
    but had no handler, so they fell through to the catch-all and returned 404.
    They now route to the same handlers as their slash-form twins (/healthz
    /health, /livez/health/live, /readyz/health/ready), returning
    byte-for-byte identical responses. Because they are token-exempt, orchestrators
    can use /livez and /readyz for unauthenticated liveness/readiness probes
    even when admin_token is set (the slash-form /health/live and
    /health/ready remain token-gated, unchanged).
  • Embedded admin dashboard usable with admin_token set — v1.4.0 made
    token-gating the recommended posture, but the embedded web UI
    (src/admin_ui.html, served at / and /ui) sent no Authorization
    header on any of its fetch() calls, so with a token set every panel
    401ed — the secure configuration broke the dashboard. The UI now wraps
    window.fetch once to inject Authorization: Bearer <token> (from the tab's
    sessionStorage, key helios_admin_token) into every request; on a 401
    it prompts once per page load for the token and reloads. A token button
    in the header bar clears the saved token so a wrong one can be re-entered.
    The static shell (GET /, /ui) is now token-exempt so the page can load
    and prompt — it carries no privileged data, and every API call it makes is
    still individually gated. Without a token, behavior is unchanged (no prompt).

Security

  • Stored XSS in the embedded admin dashboard (present in 1.4.0 — prioritize
    this upgrade).
    The admin web UI (src/admin_ui.html, served at / and
    /ui) interpolated backend- and attacker-derived strings into innerHTML
    with only a partial <-escape. A crafted SQL query whose text flowed into an
    anomaly `f...
Read more

v1.4.0

Choose a tag to compare

@github-actions github-actions released this 09 Jul 01:30

What's Changed

  • perf(hotpath): eliminate per-query allocations + protocol crash guards (G1/M1) by @danimoya in #26
  • fix(pool): COPY-hang, poisoned-park, and pool-key identity leakage (G2/M2) by @danimoya in #27
  • fix(stability): admin DoS caps, health-interval guard, pre-auth timeout (G4/M4) by @danimoya in #28
  • fix(auth): event-driven auth relay — slow-client deadlock + ErrorResponse blindness (G3/M3) by @danimoya in #29
  • fix(mem): bound the ha-tr journal and reclaim per-session L1 caches (G5/M5) by @danimoya in #30
  • perf(pool): conditional reset — skip DISCARD ALL for provably-clean connections (G2c) by @danimoya in #31
  • fix(relay): idle backend watch — LISTEN/NOTIFY delivery + kill the 200ms Flush stall (G3b) by @danimoya in #32
  • fix(stability): session RAII guard + DashMap sessions, health-loop supervision (G4b) by @danimoya in #33
  • fix(security): HTTP/MCP/GraphQL gateway request hardening (G-A1) by @danimoya in #34
  • fix(security): refuse anonymous non-loopback admin; cap admin connections (G-A2) by @danimoya in #35
  • feat(edge-proxy): two-region result cache with SSE invalidation push by @danimoya in #36
  • docs(readme): edge-proxy demo GIF + asciinema link by @danimoya in #37

Full Changelog: v1.3.1...v1.4.0

v1.3.1

Choose a tag to compare

@github-actions github-actions released this 28 Jun 15:23

What's Changed

  • Platform-tier wiring + reliability hardening: all 17 feature flags real (0.7.0 → 1.3.0) by @danimoya in #24
  • fix(admin): query-analytics feature compiles standalone (parse_limit_query gating) by @danimoya in #25

Full Changelog: v1.3.0...v1.3.1

v1.3.0

Choose a tag to compare

@github-actions github-actions released this 27 Jun 23:59

Full Changelog: v0.6.1...v1.3.0

v0.6.1

Choose a tag to compare

@github-actions github-actions released this 15 Jun 14:55

Full Changelog: v0.6.0...v0.6.1

Full Changelog: v0.6.0...v0.6.1

v0.6.0

Choose a tag to compare

@github-actions github-actions released this 15 Jun 09:20

Full Changelog: v0.5.1...v0.6.0

v0.5.1

Choose a tag to compare

@github-actions github-actions released this 14 Jun 23:52

Full Changelog: v0.5.0...v0.5.1