Repository navigation
v0.45.1
filex v0.45.1
Self-hosted file manager — Go single binary + multi-framework frontend.
Download a binary below, or pull a Docker image:
docker pull ghcr.io/brf-tech/filex:slim-v0.45.1
docker pull ghcr.io/brf-tech/filex:full-v0.45.1What changed
0.45.0 as it was meant to ship. v0.45.0 was tagged but never published:
one of its unit tests read a file only the maintainers' private repository has,
the release workflow's test gate failed on it in the public tree, and nothing —
no images, binaries, npm packages or desktop apps — went out. Everything
0.45.0 carried is below, in this release, together with the fix and a new
release gate that runs the web tests in the public tree before anything is
tagged.
Security
- A token confined to one folder could reach files outside it through the
app doors and the selection archive. Aroot:-scoped API token (the kind
a host application hands an embed, confined to the tenant's folder) could
run an app on any file of the storage — its result written next to that
file — and put files from outside its folder into a selection archive
(POST /api/files/archive/download). The path confinement rewrote the body
keys it knew and passed apathsarray through untouched, and those doors
checked the person's permissions but not the token's root. Both layers now
refuse: the confinement coverspaths, and every app door (run, view
events, the chosen output folder) and the archive check each path against
the token's root. Found while building #71.
Added
-
Drag a file out of the web admin onto the desktop (#71). The admin app
signs its requests with a bearer token, which the browser's drag-out
download cannot carry, so it offered no drag-out. The explorer now asks the
server for a one-file link while the pointer rests on a row or a ⌘K result
(POST /api/files/archive/downloadwith"mode":"file"→/z/<ticket>, on
the existing archive tickets): it lasts a minute at most and works once, and
at the drop it is checked again as its owner — account, token, tenant host,
tenant storage and at least viewer on the file. Every drag-out download is in
the audit log (file.download_link,file.download_link_refused); the link
itself never is. Folders are refused (409 IS_FOLDER). A cookie session
keeps its plain download URL. -
Desktop: Mount as a drive. One button in Settings attaches a filex
server as a drive of the operating system over WebDAV, and one detaches it —
the one-click counterpart of the connection guide, whose commands now come
from the same code. The account's own API token is the WebDAV credential and
reaches the OS on stdin, never on a command line. On Windows it uses
WNetAddConnection2, starts the WebClient service if it is stopped, and says
up front what WebClient needs (HTTPS for a password). The macOS and Linux
paths are there but not yet verified on those systems (#36). -
⌘K search results you can act on. A result in the palette's
Everywhere group has a Download button (a folder arrives as one zip) and
drags out like a row of the file list — through the desktop app's own drag,
or as the browser's single-file download where the session is a cookie. A
drag let go on the palette itself no longer starts an upload (#47). -
Desktop: ⌘K searches every account on the rail. Results are grouped
under one badge per account, the one you are looking at first. Each account
is searched, downloaded and dragged with its own sign-in, and opening another
account's result switches the rail to it. Embedders get the same through the
newaccountSearchconfig hook
(docs/INTEGRATION.md) (#47). -
pnpm release X.Y.Zcuts a release in order, and a red gate stops it.
The release process in docs/CONTRIBUTING.md is one
command now: preflight, the README/screenshot/docs audit, the doc gates, the
version stamp, the whole pre-tag chain (both images, three database engines,
TZ=UTC, Cypress, Playwright), the public export and its guards, then the
signed tags, the push, the workflow's output and the deploy. No option skips
a gate. The tool never signs, pushes or deploys: at those steps it prints the
commands, and on--resumeit checks what was done — each tag's signature
and target, what both remotes hold, and what the servers, the update feed,
the desktop feeds (bytes against their sha512) and docs.filex.sh serve.
--dry-runruns every gate and writes nothing (#48).
Fixed
- The Storage line says how full the drives are, not how much you uploaded
(#54, Berk Başarır). The line at the foot of the explorer's navigation
(web and desktop) and the storage chip in the admin top bar printed the
person's own upload counter under a label about the drive: on an S3 drive
holding 245.3 GB it read 523.5 MB, because files a sync discovered belong to
nobody. With a quota the line still shows the person's usage against it;
without one it shows the size of the drives the panel lists, the figure
Home's cards print, and "at least …" where a drive is not fully counted.
Refresh reads it again, and a failed poll keeps the last figure. - The release checks the public tree the way the release workflow does.
pnpm releasebuilt and tested the web code only in the private tree; it
now runs the Frontend job (packages, admin build, web and package unit
tests) in the exported tree as well, and--resumegets past its own
export after a red export gate instead of stopping until the checkout is
cleared by hand. - Desktop app: the sidebar entries are left-aligned again (#53). Home,
Trash, each storage and How to connect sat centred in their rows on macOS
and Windows. The explorer renders into the page that hosts it, and the
desktop app's own rule for its dialog buttons (justify-content: center)
reached the sidebar's buttons, which left that property unsaid. They say it
now, so a host page with a global button rule no longer moves them. - WebDAV: a file saved through a mapped Windows drive keeps its content.
Windows' WebDAV client sends a PROPPATCH with the Win32 times after every
save, and answering it committed an empty upload over the file — so every
file saved through a mapped drive landed on the server empty, with no error
anywhere. A write-open that is not an upload now only describes the file. - A big local storage is catalogued about three times faster (#70). A
folder's catalogue rows were written one statement at a time and every new
file indexed for search on its own, a disk-bound write each. They now go in
one database transaction per folder (SQLite, PostgreSQL and MySQL), the
folder's deletions included, and into the search index in one batch after it
commits. On a 100,020-file tree the lazy catalogue's background fill went
from 34 to 95 files/s and a full scan from 46 to 162 files/s; the lazy
catalogue's deletion-safety rules are unchanged. Content extraction, queued
per file as before, now trails behind the catalogue
(docs/LAZY-CATALOGUE.md). - WebDAV storages no longer cut transfers at 60 seconds (#73). The driver
bounded every request, body included, to one minute, so any upload or
download longer than that failed however well it was moving. Now only
silence is bounded: connecting, the answer and each next piece of a transfer
each waitattempt_timeout_s(30 s); copies, moves and deletes wait up to 10
minutes. A dead server is reported as unavailable within seconds, failures
that can pass are retried withintotal_timeout_s, and an upload is never
sent twice. The driver speaks HTTP/1.1. - An FTP server that stops answering no longer freezes its storage (#73).
Only the connect was bounded: the liveness check held the storage's single
connection forever, so every other operation on it waited too, and so did a
server that never greeted and a transfer that stopped. Every wait now ends
afterattempt_timeout_s(15 s), a fresh connection is tried within the
budget, a request whose client leaves stops waiting, and moving transfers
are never cut. FTPS data connections are encrypted by the driver itself.
WebDAV and FTP storages have the same three time settings as S3 on the
storage form. - S3: a store that is down is reported within seconds, not a minute and a
half (#44). A drop into an S3 folder while the object storage was down
answered503 storage_unavailableafter 85 s; a refused port took 26 s, a
host off the network ~145 s, and a store that accepted the connection but
never answered did not return at all. Every wait that is not a moving
transfer is now bounded per attempt — connecting (DNS included), the TLS
handshake, the answer after the request, an answer that stops arriving, an
upload the store stops taking — and retries are held to a time budget: with
the defaults a dead store is reported within 15 s as
s3 endpoint … is unavailable: <reason> (N attempts in Xs). A transfer that
keeps moving is never cut; copies, renames and multipart completion wait up
to 10 minutes. A certificate that does not verify is no longer retried, and
uploads over 2 MB (Expect: 100-continue) have an answer limit too. New
storage settingsattempt_timeout_s(10),max_attempts(6) and
total_timeout_s(15) appear in the storage form; see
docs/STORAGE.md. - Ops → Updates no longer promises what the install cannot do (#72). On
an install a package manager owns (Homebrew, winget, Snap, a distribution
package) or a container, a saved policy ofpatchorminormade the badge
read "Policy: install patches" although filex never replaces such a binary.
The server works out the effective behaviour in one place, shared with the
upgrade decision, and the status carriesbehaviorandpolicy_limit: the
badge reads Announces only, and the line under it says the saved policy
has no effect on this install, with the package manager and its command.
Checking switched off reads Checking off;minoron 0.x reads
Installs patches. The saved policy is kept as set. - The release badges on Ops → Updates have their colours again. Security,
schema change and the size of the step all rendered grey: they passed a
property the badge component does not have. - App screens wear the theme everywhere (#57). On a branded, dark
instance the wizard's current-step number and the people picker's avatar
were white on the theme's primary (2.3:1 on a pale one); they now use the
palette's--fe-text-on-primary, like filex's own buttons, and a signing
box's number takes its ink from the signer's colour. An app's page and a
public page (share, file request, signing link) now turn with light and dark
while they are open, instead of keeping the mode they were opened in.
docs/APP-PLUGINS-API.md lists the theme tokens
each surface node reads and what stays fixed on purpose (the PDF page,
signer colours, the signature pad's paper), and a test fails when a surface
node carries a fixed colour, corner or font. - Apps: a modal screen opened on several files keeps all of them. An
action that applies to a selection and opens a view saw every file on its
first screen, but from the first form edit (or the submit) on it was
answered about the first file only, and the job it queued ran on that one
file (#64). The explorer now sends the whole selection with every view
event; the server re-checks each path for the person asking, re-checks
applieson every file at submit, and takes at most 500 paths, asrun
does. - Desktop: a copy prepared for one account's drag-out is not handed to
another account's. Two accounts with a storage of the same name (the same
server, or the same drive name) shared the prepared copy of a path, so a drag
from the second could carry the first account's file. The copies are keyed
by account as well now (#47). - Linux: the desktop app opens on a minimal install. Electron loads the
ALSA sound library at start, and the.deband.rpmdid not depend on it:
on a system without it the app did not open. They now require
libasound2 | libasound2t64(Debian, Ubuntu) and(alsa-lib or libasound2)
(Fedora, openSUSE). - Linux: the desktop app warns when the Snap Store copy is installed too.
The snap keeps its own accounts and its own sync history, so a folder paired
in both copies was synced by two apps that did not know about each other —
duplicate uploads, conflict copies, a delete reaching the wrong side. A
.deb,.rpm, AppImage or AUR copy now says so in Settings, with the
commands to keep one. filex self-updateleaves a distribution package alone. A filex in
/usr/bin(or/usr/sbin,/bin,/sbin) was put there by a package
manager, and is now treated like a Homebrew, winget or Snap install: no
self-replacement, upgrade with the package manager. A hand install in
/usr/local/bin, where docs/CLI.md puts it, is unchanged.
Verify: sha256sum -c checksums.txt
- Documentation — https://docs.filex.sh
- Report a bug — https://github.com/BRF-Tech/filex/issues
- Full changelog — https://github.com/BRF-Tech/filex/blob/main/CHANGELOG.md
- Every release — https://github.com/BRF-Tech/filex/releases