Skip to content

Releases: openquanter/quanterdeck

Quanterdeck v1.0.0

Choose a tag to compare

@github-actions github-actions released this 01 Oct 10:34
d19f1bb

The first tagged release. Everything below is "since the repository
started" rather than since a previous release.

Whether this console is behind quanterdeck's newest release

  • The same card checks the console itself. Quanterdeck publishes
    GitHub releases too; with each framework check the deck also reads the
    newest release of OQ_DECK_SELF_REPO (openquanter/quanterdeck by
    default) and compares its tag with the version the deck was built as —
    by version, not commit, because a build from a git archive has no
    commit to read while the version is always compiled in. Equal is
    current, newer is ahead (built from a branch after the release), older
    is behind. A tag that is not X.Y.Z (with or without v, optionally
    with a pre-release) is "cannot tell", with the reason; no release yet
    is its own state. The overview card gains a "This console (quanterdeck
    release)" section, and the top-bar badge names which release is newer.
  • Kept apart from the framework check. One more GET per check (five
    at most), on the same schedule, switch and proxy. Each half keeps its
    own error and last success, so GitHub refusing one leaves the other's
    answer standing. GET /api/v1/upstream gains a console object; the
    existing fields, behind included, still describe the framework.

Whether what runs is behind the framework's newest release

  • The deck checks the framework's GitHub releases. Shortly after
    startup and then every OQ_DECK_UPSTREAM_CHECK_HOURS (6 by default),
    it reads the newest release of OQ_DECK_UPSTREAM_REPO, resolves its
    tag to a commit, and asks GitHub to compare that commit with two
    running revisions: the deck's own, embedded at build time from
    Cargo.lock, and the trader's, from the framework field of the
    current release's manifest through the host agent. The overview has an
    "Upstream release" card and the top bar a badge when something is
    behind. A trader restart — a new journal in OQ_DECK_JOURNALS_DIR,
    looked for every 5 minutes without touching the network — brings the
    next check forward, so a deploy shows within minutes rather than at
    the next scheduled check.
  • "Cannot tell" stays "cannot tell". A timeout, an exhausted rate
    limit or a reply that does not parse is an error with its reason and
    time, shown beside the last successful answer and that answer's age —
    never as "up to date". No release published yet is its own state, and
    a revision GitHub does not know (or no agent to ask) is that
    revision's "cannot tell", with the reason.
  • One outbound request, and a way to turn it off. Unauthenticated
    GETs to api.github.com carrying a User-Agent and the repository
    path, nothing else; OQ_DECK_UPSTREAM_CHECK_HOURS=0 makes none at all,
    and the capability says so. OQ_DECK_UPSTREAM_PROXY names a proxy for
    this check only. A manual check (POST /api/v1/upstream/refresh) is
    checked for Origin like any write but is not behind
    OQ_DECK_ALLOW_WRITES — it changes nothing on the host — and runs at
    most once a minute.

A large directory no longer stalls the console

  • File work runs off the async workers. Listing runs, sweeps and
    journals, a run's or a journal's detail, comparison, attribution and
    reconciliation all parse files — the journal listing replays every
    journal whole — and did it on the threads that answer every other
    request, the session checks included. They run on the blocking pool
    now.
  • A listing remembers what an unchanged file parsed to. Keyed by
    inode, length, modification and change time; a file modified in the
    last two seconds, or one that would not read, is read again every
    time. The listing says exactly what it said before — an unreadable
    file is still listed with its reason and still withholds the total —
    and a removed file is forgotten with the listing that missed it.

Signing in once, on the machines you choose

  • A browser you enrol is not asked again. The login page offers to
    remember this device; that browser then carries a device credential
    instead of a password and a code. It is a second way in with one
    factor rather than two, which is why it is named, listed in Settings
    and revocable — and why withdrawing one is deliberately not behind
    OQ_DECK_ALLOW_WRITES. Only its SHA-256 is written, so a copy of the
    file is a list of what exists rather than a set of keys to use.
  • Sessions no longer expire at a fixed hour. OQ_DECK_SESSION_HOURS
    and OQ_DECK_SESSION_IDLE_MINUTES are settings, bounded and refused
    rather than clamped, and /runtime/settings reports the ones in force
    instead of the two numbers it used to hardcode.
  • Signing out ends the session, not the device. Taking a device away
    is a separate act with its own page; otherwise signing out on a shared
    machine would un-enrol it.
  • Sessions still live in memory, so a restart still ends them — and an
    enrolled browser does not notice, which is what the device credential
    is for.
  • A machine can be enrolled by proving an SSH key, for the case the
    box above does not cover: a laptop you have a key on and no password
    on. scripts/deck-enrol.sh asks the deck for a challenge, signs it,
    and prints a link; opening the link in the browser enrols it. The
    keys trusted are the ones an allowed_signers file lists
    (OQ_DECK_TRUSTED_KEYS), verified with the same ssh-keygen -Y verify the host agent trusts a release with — under its own
    namespace, so a release signature cannot be replayed here. Off unless
    that variable is set, and the console reports which it is.
  • deck-enrol.sh takes --cacert (or OQ_DECK_CA), because a deck
    behind a proxy with its own CA is one curl refuses to talk to, and the
    reference deployment is exactly that. --insecure exists too, and says
    in the script what it costs: the challenge this script signs is what
    authorises enrolling a browser, so a machine in the middle of that
    connection can collect the signature and enrol one of its own.

The console says what it knows

  • A fee the run has not measured is not a zero. The books charge a
    fee from a schedule, and a live run is built without one — so fees
    was zero for every live run and the console drew it beside realized
    and funding as though it were a measurement. The venue states the
    commission on each fill; a run books that now, checks the total
    against the venue's own trade records when it ends, and reports
    not measured until it has one. A measured zero and a figure that
    could not be measured are opposite facts, and the page no longer
    conflates them.
  • A venue reading older than the run is not a disagreement. The
    console compares the newest journal against a reading it rewrites
    about once a minute, so for that minute after a restart it was
    comparing two runs — every order they have apart counted in both
    directions. It says which run the reading is of, and that it catches
    up.
  • A refusal says which fact stopped it. undecodable,
    no adoption record, or the reading predates the run were one
    sentence; the sentence could not describe a case it did not know
    about, and the new one had no sentence at all.
  • The step-up code counts its failures — five wrong ones close it
    for fifteen minutes, the same numbers signing in uses. A six-digit
    code is a million guesses and what sits behind this one is stopping
    the trader.
  • Listing the strategies is a read. It called the code that sends
    an instance whose configuration moved back to draft, so opening a page
    moved a strategy. The step taken refuses instead, which is also where
    the gate has to see it.
  • The two codes are two entries, and the console says so. The host
    agent's step-up secret is the agent's — a compromised deck cannot mint
    one — so nothing here can show it, and nothing said where it comes
    from. The field that asks for it, first-run setup, and Settings all do
    now; enrolling only the console's is why a first deploy stops at the
    code.
  • The sign-in screens are in this round's style. They were not: a
    different product mark, a card shadow heavier than every other card's
    and not from the theme, and the language and theme switches — the two
    things this release is about — unreachable until after signing in.
  • This repository names no deployment of its own. A release's
    allow-list was a constant holding one operator's private binary, and
    the unit, channel and prefix defaults were that deployment's. They are
    configuration now, the mark and the copy are generic, and the
    defaults a deployment must set are in the README's table.

English, beside Chinese

  • The interface is in Chinese and English, switched from the top bar
    or Settings and remembered in the browser. Every piece of copy is
    written as tr("中文", "English") where it is used, and
    scripts/check-i18n.py (run in CI) fails on Chinese that has no
    English beside it.
  • The deck answers in the reader's language: refusals, capability
    reasons and attribution's missing inputs follow the request's
    Accept-Language.
  • So does the host agent. Every sentence it words is a pair
    (oq_deck_core::lang::Said) — a config file that changed under a
    write, a deploy whose health check failed, a promotion the gate
    refuses, a control port that stops answering. The agent does not know
    which language the console is being read in, so it sends both and the
    deck picks.
  • The promotion gate's refusal is a pair on the wire
    (decision.reason is {zh, en}). The console used to recover the
    English by matching the gate's Chinese with a regex table that had to
    be kept in step by hand; the table is gone.
  • Records keep both renderings, in sibling fields: reason and
    reason_en, result and result_en, problem, outcome, step,
    message. A record written before the console had two languages
    carries one renderin...
Read more