Skip to content

v0.3.0

Choose a tag to compare

@github-actions github-actions released this 28 Aug 23:07
· 79 commits to master since this release
f58de4a

Changed

  • No byte cap by default. MaxBytes defaults to 0 (unlimited) and
    nq --max-bytes is omitted unless the link is metered; MaxDuration
    (12 s per direction) is the budget, so cost is at most link rate × 12 s and
    a confident result is reachable at any speed. Previously a 250 MiB cap
    truncated every run above ~250 Mbps with low confidence (#3). Slow links
    are unaffected. Set MaxBytes on metered links for the old behaviour.
  • Latency percentiles are honest about sample size: p95_ns is present only
    from 20 samples, and p80_ns (from 5), p90_ns (from 10) and p99_ns
    (from 100) are added. Previously p95_ns of the five idle probes was
    always the maximum (#4). The CLI prints the highest percentile available.
  • A load phase that fails before completing an interval no longer discards
    the whole result: Run returns the partial Result (that direction
    flagged flow_error, earlier phases intact) together with the error. Only
    discovery failures return no result.
  • Signed URLs: sig accepted in raw or padded, URL-safe or standard base64.
  • nqserver refuses to serve anonymously with a real certificate unless
    --allow-anonymous; --self-signed implies it.
  • Internal: the per-interval measurement logic now lives in a pure,
    clock-free internal/engine package driven by observations, so it can be
    tested against recorded and simulated links. No behaviour or JSON change;
    public latency types are aliases of the engine's.

Added

  • schema_version (1) as the first field of Result, bumped only when a
    field is renamed, removed, retyped, or changes meaning (#2).
  • Regression guards: leak check across mixed runs, wire-contract test,
    repeated-run isolation, JSON schema golden and v0.2.1 document fixture,
    fuzz targets for the four parsers (with a CI job), and a per-scenario cost
    ledger for the algorithm matrix.
  • End-to-end tests for real-world failure modes (upload rejected mid-stream,
    stalled body, redirects, dead hosts, upload cancellation/HTTP/1.1), IPv6
    loopback, full ramp to 16 flows, JSON round-trip, CLI edge flags, and the
    signed-URL encoding/canonicalisation edge cases.
  • nqserver --signing-key: the test endpoints accept HMAC-SHA256-signed,
    expiring URLs (exp, optional sub, sig) minted by a backend, so
    clients hold no credential; sub keys the per-client budget. nqserver sign mints keys and URLs; server.SignURL for Go issuers (#1, plan B).
  • nqserver bearer-token authentication (--auth-token / NQSERVER_AUTH_TOKEN)
    on every endpoint, and load limits that gate requests without shaping
    traffic: per-client byte budget (--client-bytes/--client-window, default 8 GiB
    per 10 min, unlimited under --self-signed; 429 + Retry-After),
    --upload-size, --max-connections (#1).
  • Options.Header applied to every request; nq --auth-token /
    NQ_AUTH_TOKEN.
  • Internal: internal/linksim, a fluid link model, and an algorithm
    scenario matrix with honesty/budget/convergence/accuracy oracles and a
    knownFailing ledger of what the current algorithm cannot yet do.

Fixed

  • Every load phase leaked one HTTP/2 connection and its read/write
    goroutines when a stream was still winding down at teardown (present since
    v0.1.0); the config fetch also left a keep-alive connection in the caller's
    transport pool. All library-dialled connections are now tracked and closed
    when Run returns (INV-4).
  • nq --max-bytes rejected 0 but accepted sub-byte values that rounded to 0
    and silently meant the default.