Skip to content

Releases: danReynolds/tailscale_dart

tailscale 0.3.1

Choose a tag to compare

@danReynolds danReynolds released this 08 May 21:29
  • Adds Tailscale.up(ephemeral: true) for disposable CI jobs, preview
    environments, and tests.
  • Adds example/shelf_adapter.dart, a tested adapter showing how to run Shelf
    handlers directly on http.bind without making Shelf a core dependency.
  • Updates the README, developer site, API status, and architecture notes to
    point Shelf users at the tested adapter example.

tailscale 0.3.0

Choose a tag to compare

@danReynolds danReynolds released this 06 May 15:36

0.3.0

This release is a major API and transport rebuild for public POSIX usage.
It keeps the embedded-tsnet lifecycle model, but replaces the old loopback
transport helpers with package-native APIs backed by private fd capabilities
and a shared POSIX reactor.

Platform contract:

  • pubspec.yaml declares Android, iOS, Linux, and macOS support. Windows is
    intentionally unsupported until a Windows-native data-plane backend or
    fallback carrier is designed.
  • Linux CI runs Headscale E2E against the epoll reactor path; macOS, iOS, and
    Android have been validated through the demo/smoke harness.

Breaking — public API shape:

  • Tailscale.http is now the HTTP namespace. Use Tailscale.http.client for a
    standard package:http client routed through the tailnet.
  • The old Tailscale.listen(localPort, {tailnetPort}) reverse-proxy helper was
    removed. Use Tailscale.http.bind(port: ...) for in-process HTTP handling, or
    Tailscale.serve.forward(...) when forwarding an existing loopback HTTP
    server.
  • Inventory APIs now use Tailscale's node terminology:
    Tailscale.nodes(), Tailscale.nodeByIp(ip), Tailscale.onNodeChanges,
    TailscaleNode, and TailscaleNodeIdentity.
  • Tailscale.up() now returns Future<TailscaleStatus> and resolves on the
    first stable state (running, needsLogin, or needsMachineAuth).
  • PingResult.direct is now PingResult.path (PingPath.direct, derp, or
    unknown). The .direct getter remains as a convenience for the positive
    case.
  • ClientVersion now mirrors upstream fields: latestVersion,
    urgentSecurityUpdate, and optional notifyText.

Core lifecycle and observation:

  • TailscaleClient is the testable app-facing interface implemented by
    Tailscale.instance.
  • onStateChange, onError, and onNodeChanges are pushed from Go; node
    updates are debounced and new onNodeChanges subscribers receive the current
    snapshot.
  • Structured TailscaleErrorCode and per-namespace operation exceptions now
    preserve known LocalAPI error categories (notFound, forbidden, conflict,
    preconditionFailed, featureDisabled, unknown).

fd-backed transport APIs:

  • http.client streams outbound request/response bodies over private fd-backed
    channels while Go owns tsnet.Server.HTTPClient() semantics.
  • http.bind({port}) returns TailscaleHttpServer with package-native
    request/response objects and fd-backed request/response bodies.
  • tcp.dial(...) and tcp.bind(...) provide package-native raw TCP streams and
    listeners via Go-owned tsnet.Server.Dial/Listen connections handed to Dart
    as private fd capabilities.
  • tls.bind(...) accepts TLS-terminated tailnet connections as plaintext
    TailscaleConnections; certificate acquisition and renewal remain in Go.
  • udp.bind(...) provides message-preserving datagrams with remote endpoint
    metadata and rejects payloads over 60 KiB.
  • The POSIX data plane uses a shared kqueue/epoll reactor instead of spawning
    reader/writer isolates per fd.

Tailscale feature namespaces:

  • whois(ip) and nodeByIp(ip) are implemented for identity-aware
    authorization flows.
  • tls.domains() exposes auto-provisioned Tailscale certificate SANs.
  • diag.ping, diag.metrics, diag.derpMap, and diag.checkUpdate are
    implemented.
  • prefs.get, single-field prefs setters, and prefs.updateMasked are
    implemented.
  • exitNode.current, suggest, use, useById, useAuto, clear, and
    onCurrentChange are implemented.
  • serve.forward/clear publishes an existing loopback HTTP service inside the
    tailnet using LocalAPI ServeConfig.
  • funnel.forward/clear publishes an existing loopback HTTP service through
    Tailscale Funnel using tsnet.ListenFunnel plus a package-owned reverse
    proxy. Forwarding targets are loopback-only.
  • taildrop and profiles remain declared roadmap namespaces and throw
    UnimplementedError in this release.

Validation:

  • Unit, FFI, fd, runtime, Go, and Headscale E2E suites cover the core feature
    spine.
  • Live Tailscale tests cover hosted-control-plane behavior Headscale cannot
    model: routing controls, TLS serving, Serve forwarding, Funnel forwarding,
    and Serve cleanup on down()/restart.

Release hardening:

  • HTTP fd response-head envelopes are capped at 256 KiB on both the Dart and
    Go sides.
  • fd transport write/close dispatch failures, listener/server close failures,
    unread HTTP request bodies, and UDP binding teardown paths now deterministically
    close local resources.
  • Serve/Funnel forwarding canonicalizes localhost to 127.0.0.1 before
    creating loopback proxy targets.
  • Smoke-matrix tooling redacts bearer credentials from logs and stores generated
    runner tokens with owner-only file permissions.