Skip to content

Releases: WhitenWhiten/topophany

Topophany v0.8.1

Choose a tag to compare

@github-actions github-actions released this 15 Oct 05:52

[0.8.1] - 2026-10-14

Changed

  • The README and the homepage show the preview where 0.8.0 put it, at
    home in Seattle, Osaka or Chengdu by language. Their stills, the
    homepage's recording and the words beside them still showed the
    network the preview had in Changsha, and the recording's two vantage
    points were observers the preview no longer has, so made again it
    would have shown nothing measured from either. They are captured
    again, and the tour now fails to record, in the tests too, when it
    views an observer the preview lacks. The homepage's vantage panel is
    drawn where each language's preview puts its home, the transit host
    and New York, with its map fitted to them and its arcs and labels laid
    out so that none overlap.
  • Topophany has a new mark, the globe of the README's banner in little:
    a dot-matrix Earth lit from the upper left, with an arc of light from
    Shanghai to a place it brings to light across the Pacific. It is the
    homepage's favicon, the mark beside its name and its Apple touch icon,
    and scripts/icon.py (make icon) draws it from the land mask.

Fixed

  • TLS and HTTPS checks, and https-connect hops, no longer report a
    healthy service as tls: timeout on a path that drops large
    ClientHellos. Built with Go 1.26, a probe offered Go's default key
    exchanges, led by the hybrid post-quantum X25519MLKEM768, whose key
    share alone is over a kilobyte; where a path never delivered that
    ClientHello, TCP connected and the handshake went unanswered until the
    check timed out, while curl and OpenSSL reached the same server. Probes
    now offer only X25519, P-256, P-384 and P-521, as those clients do.
    Workers still offer the hybrid exchange to their collectors.
  • A worker with several collectors no longer probes on while it drops
    every sample. Once each collector's share of the outbox was full, as
    when all of them were down long enough, a new sample was kept for none
    but reported as a degraded delivery, which a worker takes to mean
    another collector still has it; it logged the loss and went on. With
    room at no collector a worker now stops with the outbox's capacity
    error, as one with a single collector always did, and keeps what it
    queued.
  • An incident ledger that could not be written is written at the next
    judgement, two seconds on, whether or not anything changed by then. A
    failed write was tried again only once something else changed, yet the
    collector logged "incident ledger written again" at the next judgement
    that changed nothing, and a crash before the next change lost the
    incidents that write held. The log now follows a write that succeeded.
  • A collector starting on a new data directory makes it durably. The
    directory, those made above it and its new journal were never synced
    into their parents, so on a POSIX filesystem a power loss could leave
    the samples it had acknowledged, each written and synced, with no name
    to find them by. Each is now synced into its parent as it is made,
    before the collector opens, and so is any directory made to write a
    file into, such as a credentials file's.
  • A worker starting on a new outbox makes it durably. Its directories
    were never synced into their parents, and each record was synced into
    pending but pending into nothing, so a power loss could lose the
    samples a worker had queued before any collector took them. The
    outbox's directories are now synced as they are made, before the
    worker opens it.

Security

  • A worker can no longer crowd other observers' alerts out of a webhook
    they share. A webhook's queue held its 64 alerts whoever they were
    from, so while it was down or slow a worker could fill it with
    incidents of its own observer, which it can make at will, and every
    alert from another observer was dropped until it drained. A full queue
    now gives an alert from an observer with fewer waiting the place of the
    newest from the observer with the most, so each keeps its share; a
    drop is logged with the observer it was from.
  • A collector's TLS private key is read as its other credentials are.
    topo serve handed --tls-key to the TLS server to open as it was,
    so a key other users could read, a link or anything but a file was
    served from; now the key must be a regular file, not a link, of mode
    0600 or stricter on POSIX, or the collector does not start, and it
    says why. Copy a key out of a certificate tool's directory of links,
    such as Let's Encrypt's live/, rather than pointing at it.
  • The editor no longer writes a terminal control or bidi rune from a
    topology to the terminal. A field's text was shown without them, but
    its cursor, in color, redrew the rune under it as it was, so moving
    through a field of a crafted topology could send its controls one at a
    time. Any such rune now shows as a space, wherever a single rune is
    drawn, and the cursor stands where the text before it is shown rather
    than a column further per control.
  • A worker can no longer fill its observer's share of a collector for
    good by changing its boot. Each boot whose receipts expired left a
    floor that was kept forever and counted against the observer's share,
    and a worker picks its boot IDs, so one that sent each sample under a
    new boot made its observer's samples refused with 429 from then on,
    through a token rotation and a restart. An observer's floors now take
    at most an eighth of its share; past that, those whose receipts were
    taken longest ago go. The IDs they bound were received more than
    --retention and an hour ago, too long ago for their samples to be
    accepted again, and a boot still delivering keeps its floor.
  • A topology's values reach no terminal raw. Errors that refused an
    endpoint, link or path ID, a path's node or dependency, a check's kind
    or a repeated header name wrote the value as it was, so a crafted
    topology could clear, retitle or reorder the terminal of whoever
    validated, served or edited it. Those values are now quoted with their
    controls escaped, and everything topo writes to stderr, its errors and
    logs, leaves out terminal controls and bidi runes but for newlines and
    tabs.

Source commit: b8b1f14

Full Changelog: v0.8.0...v0.8.1

Topophany v0.8.0

Choose a tag to compare

@github-actions github-actions released this 15 Oct 04:06

[0.8.0] - 2026-10-14

Everything since 0.3.0. No release was published between them.

Added

  • On the geo map, p hides every site plate and draws the arcs dashed,
    leaving the markers and the lines. p again brings the plates back.
    The key does nothing on the virtual geo or the network graph.
  • Long-term history. Collectors roll every sample they accept up into
    per-check rollups that outlive the raw journal: each sample's outcome
    stands until the next sample or until it goes stale, and the time it
    stood is summed as up, degraded, down or inconclusive (the monitor could
    not tell), with the samples by outcome and a histogram of what the
    passing ones took. Time no current sample stood for is unmeasured,
    never up or down, so availability reads as "95.7% up over 96%
    measured". Rollups are kept five minutes wide for two days, hourly for
    32 days and daily after that, written with each checkpoint and rebuilt
    from the journal, so a crash counts no sample twice. topo serve --rollup-bytes caps them (32 MiB by default); at the cap a collector
    sheds the rollups of contracts it no longer counts, then the oldest
    days of the observer whose rollups take the most room, and never stops
    ingesting for them.
  • Snapshots carry each check's availability over the last 24 hours, 7
    days and 30 days. A check's evidence shows them, such as Last 24h: 99.2% up over 96% measured · down 11m, and the Checks tab its last
    day's share up as UP 24H.
  • GET /v1/rollups?check=ID&step=1h&span=7d lays a check's rollups out
    in slots of five minutes, an hour or a day, and topo history CHECK --step 1h [--span 7d] prints them, slot by slot with a total, or as
    JSON. The preview keeps synthetic rollups as a collector watching all
    along would, so scenarios show in them too.
  • A check's evidence opens with its recent samples, read from the
    collector's history: a strip of one slot per sample colored by outcome,
    with a grey dot for each interval in which none was taken, a bar for
    what each passing sample took, and their median and 95th-percentile
    times with the median DNS, connect, TLS and first-byte times.
    topo show checks ID prints the same strip, and its JSON carries it
    slot by slot as samples.
  • Collectors keep an incident ledger, incidents.json in their data
    directory, judged every two seconds from the evidence of all observers
    whether anyone is looking: an incident opens when it is confirmed,
    recovers while its failed checks pass again short of their recovery
    threshold (a failure then is a relapse, not a new incident), and closes
    as recovered, unconfirmed, paused or changed. Each change is logged.
    Snapshots carry the open records and those closed in the last day as
    ledger; the Incidents tab and topo show incidents list them after
    the open incidents, one row per occurrence, and an incident's evidence
    says when it opened, how often it happened before and how long it
    lasted. A recovering incident still needs attention.
  • A collector logs what its store holds when it starts: each observer's
    receipts and bytes against its share, and where its receipts settle at
    the last hour's rate, since a receipt lasts the ingestion window and an
    hour. It warns once when an observer is set to fill its share, and
    when, so its sampling or --retention can change before its samples
    are refused.
  • Webhook alerts. topo serve --alerts alerts.json posts incidents that
    open and close, and observers that fall silent or report again, as
    JSON or in the formats of ntfy, Slack and Discord, filtered by event
    and observer. The file names secrets, so it is private to the
    collector like auth.json and reloads with it on SIGHUP. Each
    webhook has a bounded queue delivered in order, at least once, with
    retries for failures, 408, 429 and 5xx until an alert has waited a
    day. What waits is kept in the data directory as alert-queue.json,
    so a collector that stops or reloads loses none of it, and each
    webhook's sent and dropped alerts are counted there and logged at
    start; logs name webhooks by ID, never by URL.
  • Everything the TUI shows can be read from the command line. topo status
    prints the Overview (verdict, check and tab counts, what needs attention,
    services and observers) and says it in its exit status: 0 all clear,
    2 something needs attention, 3 nothing current is known, 4 no collector
    answered. topo show TAB [ID] prints any tab, or the evidence behind
    one entry as the evidence panel has it, a server with its card;
    topo show map lists the map's nodes and edges with what each may
    claim. topo history CHECK reads a check's recent samples. Each takes
    --json, --observer and the connection flags of topo.
  • Collectors and workers reload on SIGHUP (systemctl reload with the
    shipped units): a collector rereads its topology and auth.json, a
    worker its topology. A file that fails validation, names another
    project or drops the process's own observer is refused and logged, and
    the running topology kept; a reload logs which checks measure something
    new and so start afresh. Windows has no SIGHUP; restart there.
  • Snapshots say, for each observer, whether its executor measures what the
    collector counts. After a collector reload, an observer whose worker
    still runs the old topology reads outdated, needs attention and is
    counted on the Observers tab until that worker reloads too. Workers
    report this in their heartbeats.
  • Snapshots carry each endpoint's state from the checks that target it,
    and the Topology tab's endpoints show the same evidence lines as other
    entities: the state's reason and the checks behind it.
  • topo preview [--scenario N] status (or show, history) reads the
    synthetic evidence, and topo preview scenarios lists the scenarios, so
    scripts and agents can be rehearsed on a simulated outage.
  • The preview speaks English, Japanese and Chinese. Names, notes and
    scenarios come from one catalog per language in
    internal/preview/locales, through references such as @node.win; a
    language is supported when its catalog is there. Each language also has
    its own placed topology, so the home is Seattle, Osaka or Chengdu
    rather than one private network shown in translation. The node IDs,
    the scenarios and the evidence stay the same, and a test holds every
    language to that. topo preview --lang picks one, and by default the
    first of LC_ALL, LC_MESSAGES and LANG that is set decides,
    falling back to English. --print-topology writes the topology in
    that language, and topo preview scenarios --json gives each scenario
    an id that is the same in every language.
  • The homepage is in English at /, Japanese at /ja/ and Chinese at
    /zh/, each linking the others, with a language menu and a hint that
    offers a visitor arriving from elsewhere the page in their browser's
    language. The pages are written by scripts/build_site.py from one
    template per page in site/src and one catalog per language, and each
    language replays a TUI recording of its own preview. It says what
    Topophany is, and can be found as that: a sitemap naming every
    language's page, robots.txt, and schema.org data for the site and
    the software. Headings are lit dot by dot, the docs sit beside the
    install, and the semantics are drawn as the TUI draws them. The page
    is a line or two where it was the manual, and what was there for
    effect is gone.
  • The README is translated into Japanese (README.ja.md) and Chinese
    (README.zh.md); a test keeps their commands, links and sections those
    of the original, and each shows the TUI in its own language.
  • make captures captures the TUI stills in docs/assets from the
    preview, painted by the homepage's terminal renderer: the README's in
    every language, the guide's in English. They now show the current TUI.
  • f shows the map alone, on the Overview or Topology (from another tab,
    the Topology's), and f or Esc brings the panels back. The selection
    still moves with the arrow keys and is named with its state along the
    map's foot. With the room, the virtual geo says what runs on each node,
    services with a problem first and in their color, on a line under it
    when its cards have the height, and geo plates name them after each
    node.

Changed

  • The geo map labels a site with a plate, its place over a row for each
    node, set down where it covers the least land and the fewest arcs:
    beside its marker when there is room, otherwise joined to it by a thin
    leader, so a crowded region spreads its labels into the sea around it
    rather than stacking them over each other. A short map shows fewer rows
    and counts the rest, then folds a plate to one line. Labels stay put
    while the selection moves.
  • Fitting every site, the geo map folds a stretch of longitude wider than
    60° with no site in it, such as the Pacific between China and
    California, to a narrow seam marked with how many degrees it holds, so
    the coasts on either side get the width instead of an empty ocean. The
    focus and world views are never folded. Its natural height is the
    latitudes its sites span with room for their labels, rather than the
    whole world, and on the Overview it keeps the rest when nothing needs
    attention.
  • Labels take the room there is rather than a fixed width: virtual geo
    cards widen to their full names where the gaps can spare it, a network
    chip cut short by its column runs on into free cells to its right, a
    service on the Overview with no cell beside it runs on to the edge, and
    a server card's row keeps what it names whole before what it says on
    the right.
  • Server cards name the server once, its state in the pill, and take an
    amber or red header when something on them is affected or down. Their
    sections open with a quiet label and a hairline rather than a bright
    heading, and the frame is the card's edge, ...
Read more

Topophany v0.3.0

Choose a tag to compare

@github-actions github-actions released this 14 Oct 07:46

Added

  • About links to the homepage, topophany.com, and to the source on GitHub,
    written as OSC 8 hyperlinks where the terminal takes them
    (TOPO_HYPERLINKS=0 or 1 decides outright). On short screens the
    blank rows between its paragraphs close up so the links stay.
  • Where there is room, About lists the keys of the mode the UI is in
    (viewer, preview or editor) as keycaps, so ? doubles as help.
  • Tabs count what in them needs a look (failing services, paths and
    checks, open incidents, silent observers), red when anything is down and
    amber otherwise; on narrow terminals the tab's number takes the color.
  • The terminal window is named after the verdict, such as
    ✖ 2 incidents · homelab · Topophany (✎ topology.json ● in the
    editor), and its own title is put back on exit.

Changed

  • The TUI writes only the cells that changed since the last frame, not
    every line with a change, so animation on the maps sends a few hundred
    bytes a step instead of tens of kilobytes.
  • While connecting or loading a view, the header, the status row, the
    Overview's verdict and the empty map show a turning spinner rather than
    a still ◌, so a slow collector reads as busy, not stuck.
  • Menus, forms and confirmations cast a soft shadow onto the dimmed view.
  • The Overview's big number is lit from above, a shade of its color for
    each of its five pixel rows, as the About wordmark is.
  • On small terminals such as 80x24 the Overview keeps the verdict's big
    number, puts the observers beside it, and when nothing needs attention
    gives the room under a short all-clear to the service matrix.
  • The glints on the Overview's map run as smoothly as on the Topology
    tab, and About's globe, once its introduction has played, turns at ten
    frames a second rather than fourteen.
  • Times in the evidence read alike: an incident's start, a check's last
    sample and when the collector received it are local time to the second
    (2026-10-13 10:58:07 PDT), and an incident's start says how long ago
    it was, rather than mixing in RFC 3339.

Fixed

  • PTY acceptance reconstructs the terminal screen before checking state, so
    incremental redraws correctly verify collector failover. CI fuzz suites use
    an execution budget instead of a short wall-clock deadline.
  • Large topology diagrams have bounded layout work and an explicit fallback;
    ordinary dense diagrams retain their routing and ordering quality.
  • Notices fade out, and the evidence footer identifies Enter as the back action.
  • On narrow terminals the header's project and view no longer run into
    the live indicator: they end in an ellipsis before it. Before the first
    snapshot the header no longer says it was updated "never".

Security

  • Enforce per-source collector connection quotas and absolute connection lifetimes;
    close unauthenticated HTTP/1 connections while preserving authenticated reuse.
  • Give viewers a public topology revision that excludes private execution settings,
    including revisions embedded in snapshots and observation history. Workers keep
    the private execution revision contract.

Source commit: d440d53

Full Changelog: v0.2.0...v0.3.0

Topophany v0.2.0

Choose a tag to compare

@github-actions github-actions released this 14 Oct 05:46

Added

  • A virtual geo map, now the default when any node has a location: places
    become cards in columns from west to east and north to south, keeping
    the world's order but not its distances, so crowded sites stay legible.
    Each node has its own row, links are wires between rows (and brackets
    inside a card for links within one place), and unplaced nodes such as
    edges and the internet float as pills beside what they connect to. m
    cycles virtual geo, geo and network; cards fold on short maps, and links
    that find no room are counted in the legend.
  • A Servers tab (3): a card for each server with its state, kind,
    provider and place, the services it runs and the edges in front of them,
    its addresses by network, what it hosts, who observes from it, its links,
    and its notes as a memo. Edge and platform cards list what runs there,
    what they stand in front of and where they answered from. Later tabs move
    up one: Services is 4 and About is 9.
  • Edges and platforms: nodes of kind edge (Cloudflare, Vercel) and
    platform (Supabase) with a provider, services with a runtime
    (workers, pages, functions, …), and endpoints that name the edges in
    front of them in via. Evidence is attributed along via: an edge's
    answer, even a 521, proves the edge; the origin counts only a passing
    response not served from the edge's cache.
  • HTTP probes record which edge answered, from where and whether from its
    cache (edge_provider, edge_pop, edge_region, edge_cache).
  • The preview topology puts Cloudflare in front of the main site, with a
    Worker, a Pages site and a Vercel app on Supabase, and gains two
    scenarios: the origin down behind Cloudflare, and the edge unreachable
    from the mainland.

Changed

  • The About globe reads as a sphere instead of a flat disc: a shaded ocean
    and land lit from the upper left, falling off across a soft terminator and
    toward the limb, with a graticule that curves with the surface. Truecolor
    terminals shade under the dots; 256-colour terminals keep a dotted ocean.
    The README banner is redrawn from the same art.
  • The homelab example models its CDN as an edge in front of the DMIT
    origin.

Fixed

  • Avoid a data race when reading outbox delivery retry state.
  • A service reached over several failing paths no longer repeats "access
    path unavailable" once per path in its reason.

Security

  • Bound Exit-IP and Mihomo JSON structure before decoding; escape bidirectional controls in CLI JSON without changing parsed values.
  • Reserve outbox capacity per destination, history capacity per observer, and snapshot computation per viewer; bound connections and pre-authentication work.
  • Retain durable observation-ID bindings until administrative archival and scope persisted heartbeats to their project and configuration revision.
  • Bind source verification to the tested commit and file manifest; resolve release tags back to the built commit immediately before publication.
  • Add regression tests for all eleven scan-bundle findings, including restart recovery, invalid acknowledgements, and moved release tags.

Source commit: 52d0e16

Full Changelog: v0.1.0...v0.2.0

Topophany v0.1.0

Choose a tag to compare

@github-actions github-actions released this 14 Oct 02:33

Topophany's first usable release: a single topo binary for evidence-based network monitoring, collection, and scoped observation workers.

Highlights

  • Terminal dashboard, geographic and network maps, service tables, offline previews, and a local topology editor.
  • HTTP/TLS, DNS, TCP, UDP, and ICMP probes, CONNECT/SOCKS5 proxy chains, and local proxy/tunnel adapters.
  • Evidence and freshness tracking, dependency-based state derivation, journal recovery, deduplication, and a durable worker outbox.
  • Bounded API resources and JSON decoding, hardened storage and configuration boundaries, and immutable release builds.

Downloads

Choose the archive for your operating system and CPU, extract it, and run topo --help. Linux and macOS archives contain topo; Windows archives contain topo.exe.

Platform Architectures
Linux amd64, arm64
macOS amd64, arm64
Windows amd64, arm64

Verify downloaded archives against SHA256SUMS.txt. On Linux, run sha256sum --ignore-missing --check SHA256SUMS.txt; on macOS, compare shasum -a 256 <archive> with the matching checksum. On Windows, use Get-FileHash <archive> -Algorithm SHA256.

See the README for setup and the changelog for release details.

Validation

The merged application passed the complete local acceptance suite: race detection, repeated tests, nine bounded fuzz targets, five cross-compilation targets, and loopback process acceptance. Statement coverage was 85.9%. Cross-compilation verifies builds; native Windows/macOS and production network acceptance were not performed.