OXYGENHUB

Releases 1

oxy 0.5.0 v0.5.0 · ✔ signed by Andy McCall · andymccall ·

Trust and audit
  • A repository kept in a bucket finds signatures and seals without a LIST each (issue #116). Every lookup of an object's signatures, seals, receipts, approvals or certificate listed a prefix in the bucket, and most of these lookups found nothing. Writers now also add each such entry to a journal (pack-entries, updated by compare-and-swap), and oxy gc folds them all into one list. Once a store has been folded, a reader reads the lists and the journal when it opens it, and again after 30 seconds (as long as the pack listing is kept), and looks everything up from them. Another writer's entry is seen within 30 seconds, as its pack would be, even by a handle a server keeps open. The first oxy gc also copies the one-list keys of much older stores (sigs/, seals/, certs/, …) into the current layout and marks them folded, so readers stop requesting them; until now nearly every lookup made one of these requests and found nothing. On the test store, 40 lookups went from 85 requests (40 LISTs) to 7 (one journal read and no LIST). Older readers are unaffected, because every entry still has its own key. Entries written by oxy 0.4.6 or older after the fold are missed until the next oxy gc, so upgrade every client that writes to the bucket first, then run oxy gc once. A server's /health counts journal reads as read_journal. A repository's own directory works as before.

  • A server can refuse a push by what it adds (oxygenhub#268). oxy-server's Backend has a vet_push step, called with the push's changes before anything is stored or moved; OxygenHub uses it for push protection (secret scanning). The refusal reaches oxy push as the server's own text, several lines included, and a refusal that mentions a certificate or a timeout no longer picks up a misleading hint.

  • Fetch checks the hub's transparency log (oxygenhub#238). A hub that keeps a log sends its latest checkpoint with every refs answer, and each bookmark's attestation with its log entry and inclusion proof. The first fetch pins the hub's log key in <oxy home>/tlog/<hub> with the last checkpoint seen. A later checkpoint must be signed by that key and extend the last one: a smaller log, another root at the same size or a failed consistency proof fails the fetch, saying the hub showed two histories. An attestation not logged yet, or not proved, is only a note for now, printed by fetch and pull and in --json. A hub that comes back with a new log key (a new key, a reused address, a rename) is a loud note, and the new key is pinned. Older hubs and clients ignore the new fields.

  • oxy tlog verify audits a hub's whole log (oxygenhub#238). It accepts the hub's checkpoint by the same rules as fetch, downloads every entry and requires them to make the root the checkpoint signs, then lists this repository's entries, a key's (--key) or all of them (--all); --json too. It also shows which witnesses cosigned and when.

  • Trusted time from witnesses (oxygenhub#240). An entry's integrated time is the earliest time a trusted witness cosigned a checkpoint that holds it, by the witness's clock, so a hub can only make it later, never earlier. A fetch pins the hub's witnesses beside its log key (<oxy home>/tlog/<hub>.witnesses; a new or changed witness key is a note), counts a cosignature only when it verifies against a pinned key, and checks a delegate's delegation and a short-lived key's certificate at that time. Without one it checks them as before, at the hub's acceptance or the attestation's own time. A claimed time more than 10 minutes off the integrated time is noted, not refused, for now. The wire change is additive.

  • oxy witness serve: a witness anyone can run (oxygenhub#238). oxy witness serve --name HOST --log ORIGIN=FILE … serves the C2SP tlog-witness add-checkpoint call. It cosigns, with this oxy home's key and its own clock, each checkpoint that verifies with the log's key and extends the last one it cosigned, and refuses a fork. What it cosigned is kept per log in --state, so it survives a restart.

  • oxy show --stat (issue #119). Lists the files a change touched instead of its diff: each path with lines added and removed and its kind, renames as from → to, and a total. --json gives each file's counts.

  • oxy merge takes a remote's bookmark (issue #117). oxy merge oxygenhub/develop said "no bookmark": merge looked only at local bookmarks, so merging what a remote has meant switching to it, pulling and switching back. It now takes a remote's tracking bookmark as last fetched, as revsets do, and says where it looked when neither exists.

  • Commit a resolution by paths, and amend only some paths (issue #118). A conflict resolution can be committed by paths, leaving other work uncommitted on top of the resolved state, as long as the paths include every file it resolves, whole; otherwise the refusal names them. oxy amend PATH… folds only those paths into the head and leaves the rest uncommitted.

  • oxy doctor checks the trust policy (issue #127). A repository with no policy was "Everything looks right" while every fetch warned that nothing was verified. Doctor now has a trust line: no policy is a warning that says who sets one and how; a policy shows its serial, roots, rules and expiry, warns within 30 days of expiry and fails once it has expired.

  • The same file added on both sides is one file (issue #101). The same path added on two bookmarks with identical content (files, symlinks, or subrepos at the same pin) now merges with no conflict and nothing to resolve. Every peer and the hub show it the same way whatever order the changes came in, and it stays one file through later edits, moves, removals and partial commits. Different content or a different mode is still a name conflict, and directories are not unified. The stored and signed formats are unchanged.

  • A bookmark nobody can verify no longer breaks every fetch (oxygenhub#266, oxygenhub#271). A delegate or short-lived key that moved a bookmark without signing any of its changes left every client failing the whole fetch with "unknown key". A fetch now carries the identities and certificates of the keys that signed every bookmark's latest attestation and every tag's, so clients, older ones included, can verify the move. A client that still cannot verify a bookmark other than the current one leaves that bookmark as it was, warns naming it and why, and fetches the rest. The current bookmark (the one a pull takes or a clone checks out) still fails, as does a missing, unauthorised or rolled-back attestation. The signers are gathered once per operation, not on every fetch call: a repository in a bucket with 145 bookmarks had taken 14 s a fetch.

  • Readers never wait for a push or gc (oxygenhub#249). A repository can now be read safely while another process writes it. A handle reads the operation head once and keeps it, so one request never mixes two views. A read that misses reloads the pack list and tries once more. A repack retires the packs and loose objects it replaces instead of deleting them, and gc deletes them only an hour later; oxy gc says what it deleted or kept for readers. A forge no longer needs to hold readers back while it pushes or collects garbage.

  • A repository kept in a bucket lists its packs less often (issue #116). Every open listed the bucket's packs, and a forge opens the store once per request. The pack listing is now kept for 30 seconds and forgotten the moment this process writes or deletes a pack, so its own packs are never hidden; another writer's new pack is seen within 30 seconds. Opening a store no longer sends a request per pack, and a bucket store's stat is a HEAD of the key, not a listing. A server's /health counts pack listings, kept listings and other listings apart.

  • Text that looks like a conflict marker no longer blocks a resolution (issue #126). A file that showed oxy's own conflict markers, such as documentation or a test fixture, could never be committed as resolved ("markers remain"). A file now still has markers only when it holds a marker line oxy wrote for its conflicts. A real marker left behind is still caught.

  • A carried switch no longer says carried files were removed (issue #120). After a switch that carried the working copy's changes, oxy said new files were "removed from disk" although they were still there. Carried files are now left out of what was removed, and the switch names what it carried.

Assets