a new section above Administration. it embeds THE PLATFORM'S OWN file browser rather
than drawing a file list — upload, delete, rename, move, thumbnails, the context
menu and every task hanging off it already exist and are maintained in one place. a
plugin's own would be a second to keep in step, arriving without any of that.
`basePath` IS A JAIL, not a starting folder: `useFileBrowserApp` resets currentPath
whenever it leaves, so pointing it at `<root>/media/originals` means the breadcrumb
stops there and `derived/` is not reachable by navigating. that is what was asked
for — people work in originals, derived is made for them.
IT IS A GUARDRAIL AND NOT A PERMISSION BOUNDARY, and the panel says so in its own
docstring because the difference will matter to whoever reads this next. the
file-browser API is unchanged and still addresses the whole home: anyone with file
access reaches derived/ through the Files screen. this prevents an accident, not a
determined person. confining it properly means scoping that API per user, which is a
platform change and a much larger one.
the panel also says, once, that derived/ exists and is made from these — otherwise
somebody who knows about it would think it had been lost.
`rootRelative` is new on the settings API because only the SERVER knows what home
is. the file browser addresses everything relative to a root, and a browser deriving
that prefix from the absolute path would be guessing. null when the root sits
outside home — a legitimate setting the browser cannot address, which the panel
explains rather than rendering an empty folder.
NOTHING HERE IS FOFOS-SPECIFIC, which matters now that this plugin is the template
for other site admins: the root is a setting, media/originals is the layout this
plugin creates, and both are read from the API. another site's plugin changes the
label.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Root location is two states now. reading, it is a path and one Edit. editing, it
is a field and the things you can do to it.
the actions moved to the block's BOTTOM row, off the value's line. an absolute
path is long, and it was being truncated to make room for buttons that are not
needed most of the time — the thing somebody opened this to read was the thing
squeezed. shown, it wraps with `break-all` rather than truncating, because a path
is read from both ends: the machine at the front, the folder at the back, and
hiding either is worse than two lines.
Edit is a mode and not an always-live field. this is looked at far more often than
it is changed, and a live input invites a stray keystroke into a path everything
else will depend on. Cancel restores what is stored, so leaving the mode cannot
leave half a path on screen looking like the setting.
"back to the default" is gone, as asked — and `clearRootPath` and its DELETE route
with it, since that button was the only caller. an unreferenced endpoint is the
same rot as an unreferenced component, and this one was a second, quieter Save
that wrote a value nobody chose.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
defaults to `<owner home>/fofos`, and stores the FULL path — never the tilde. a
tilde means "whoever is asking", and the people asking will not all be the same
person: this plugin is grantable, and the site is in one place regardless of who
is looking at it. stored as `~/fofos` it would give every user a different answer
to a question that has one.
THE DEFAULT IS COMPUTED, NOT WRITTEN. no row means the default is worked out on
every read, so it follows the machine. writing it in at install freezes whichever
home existed on install day, and a restore onto a different machine then points at
a directory that is not there while looking deliberately chosen. a saved path is a
decision and is stored exactly as given; only its absence is derived. the form
says which of the two it is showing, because "not set" reading identically to "set
to the default" is how somebody comes to believe they configured something they
did not.
THE PICKER USES THE PLATFORM'S FILE API — /file-browser/ls and /mkdir — not routes
of this plugin's own. they already refuse to leave home, and they already tell a
missing directory from a forbidden one, which is a distinction that cost somebody
an afternoon and would have been re-guessed here. shipping a second listing and
mkdir would be a second filesystem surface to audit for the sake of one form.
that API is an execution capability and never grantable, so for anybody but the
owner it 403s — said in a sentence rather than shown as an empty tree, because an
empty listing is data and must never be how a refusal looks. it also browses the
owner's home and nothing above it; a path outside home is still reachable by
typing, since the picker fills the field and the FIELD is what saves. one value on
screen, one Save, and picking a folder commits nothing by itself.
"Use this folder" takes the one that is OPEN rather than one highlighted in the
list. that makes looking inside and choosing one gesture, and it is the only way
to choose a folder with nothing in it — which a freshly made one always is.
a SECOND table, not a column on fofos_admin_connection, whose url and token are
both notNull: a root path could not be saved there without also having an HTTP
connection, and that connection is being replaced rather than extended. when it
goes, its table is a clean drop instead of surgery on columns that outlived it.
the rule against tables in this plugin is unbent — what it forbids is the CLIENT'S
work, and this row holds a path somebody can retype.
needs `bun db:push`.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>