S3 has no rename, so files, folders and drives kept the name they were
made with. s3d copies objects in its own database (the copy points at
the same data on Sia), so a rename is a copy to the new name and a
delete of the old: quick, and it uses no extra storage. A drive rename
makes a new bucket, moves every file, rebuilds public access for the new
name (a policy names its bucket) and removes the old one. Names that
already exist are refused. Drives on Silent Mode encrypt with keys tied
to each name, so their client gets no rename until it can re-encrypt.
The drives page and Overview now show how much of the Sia account is
used and how much is free. s3d does not report it; the indexer's
GET /account does, signed with the app key s3d registered (read from its
database for this one request, BLAKE2b-256 + Ed25519 as indexd expects).
A person with several sia.storage accounts (or phrases) could not tell
which one a Pithos s3d used: s3d records only the indexer URL. Pithos now
reads the app key s3d stores after login and asks the indexer, with a
request signed the way indexd's app API expects, for the account's key,
storage used and last use. Those match what sia.storage shows for the app,
and the page explains that the login and the phrase together decide the
account. Earlier accounts set aside on this computer show their key too.
A server-sent file list could name paths outside the s3d folder (or the key
file in it), and a failed move back deleted every listed path. Transfers now
accept only s3d data paths, check all of them before writing, never
overwrite, and clean up only what they wrote.
A lost reply could lose or fork the drives: move-up and move-down now ask the
server who holds them before touching the local copy, and once the server is
told to release, the local copy is never removed (the release is retried).
The gateway no longer lets one account route another's access key id, refuses
. and .. in shared-key paths, strips presign parameters before re-signing,
counts upload size on disk, stops s3d before it can be restarted mid-move, and
claims sign-up proofs before checking them. The key file is never replaced
when unreadable, a local edit removes the older encrypted copy, listing pages
no longer repeat, and data hashes stream instead of loading whole files.
Hosted drives sit on a server that holds the Sia connection key, so private
files must be unreadable there. Names are encrypted per path segment with
AES-SIV (deterministic, so folders and prefix listing still work on the
server) and bodies with chunked AES-256-GCM bound to drive and path, with
sizes computable both ways so uploads stream and range reads stay cheap.
s3d only sends full ~40 MB blocks to Sia, so a handful of small files can
stay in the local buffer forever (seen: 63 objects, 6 MiB, nothing on Sia).
An opt-in setting now flushes once the pending set has not changed for N
minutes, judged from s3d's upload stats so uploads from any S3 client count.
Failed flushes back off up to an hour instead of hammering a broken indexer.
The SigV4 encoder kept '/' unescaped in object paths by swapping in a
"never matches" regex (/$^/) for query values, but that regex matches the
empty string, so every empty query value went out as "/": prefix= became
prefix=/ and ?policy became ?policy=/. The request then no longer matched
what was signed, and listing any bucket or reading its policy failed
against s3d. Bucket listing and creation carry no query, so they worked.
Verified end to end against s3d (list, folders, upload, download, public
policy, folder delete) and against the aws cli; two regression tests.
s3d is driven entirely by a CLI and a two-route admin API, which keeps
Sia storage out of reach for anyone who does not live in a terminal.
Pithos wraps it: install the pinned s3d release (checksum verified),
start/stop and logs, indexer login, users and access keys, a bucket and
object browser with share links and public-read policies, and the
upload pipeline stats.
One control server (core/) serves one UI (ui/), and three hosts run it:
a web console, an Electron desktop window and a Theseus add-on, so a
feature lands everywhere at once. The server binds loopback, rejects
foreign Host headers, and signs views in with a one-time secret that
becomes a SameSite=Strict cookie. s3d login reads the recovery phrase
with term.ReadPassword, so it is driven through a pty, with a console
window fallback where the pty module is not shipped.