chore: v2.8.5 — Trash opens on one folder per user, server setup installs S3

- Files → Trash: ONE sidebar entry. An admin's opens on a folder per user's
  Trash (My Trash first, item counts from GET /api/homes/trash, an unreadable
  one showing its error); a folder opens that user's Trash (path bar
  Trash › user, Up back to the folders). An admin may restore/purge in
  another user's Trash (audited); purging asks first. The merged "All users"
  list is gone from the UI.
- A home's Trash is its user's whole recycle bin (home store + host store,
  items tagged `store`).
- `agenthub server setup` installs one Linux user per account on Linux by
  default (`--no-system` opts out); install-system messages drop `sudo`.
- Settings → Git: the author email suggests <username>@<AGENTHUB_EMAIL_DOMAIN>.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-15 16:02:11 +07:00
parent 09efb089cf
commit 758609775f
27 changed files with 839 additions and 107 deletions
+18 -4
View File
@@ -842,6 +842,11 @@ export interface FsTrashItem {
path: string;
isDir: boolean;
deletedAt: string;
/** A home's recycle bin only: which of the user's trash folders holds it. */
store?: "home" | "host";
/** The merged view only (`allTrash`): the home it belongs to, and its user. */
home?: string;
owner?: string;
}
/** How a taken name is settled: ask (409 EEXISTS with `names`), skip, keep both, replace. */
export type FsConflict = "fail" | "skip" | "keep" | "replace";
@@ -2638,15 +2643,22 @@ export const api = {
body: JSON.stringify({ paths }),
}),
trash: (t: FsPlace) => request<{ items: FsTrashItem[]; keepDays?: number }>(fsUrl(t, "/trash")),
restore: (t: FsPlace, id: string) =>
/** Every Trash the caller may open, merged (an admin: every user's). */
allTrash: () =>
request<{
items: FsTrashItem[];
errors?: { home: string; owner: string; message: string }[];
keepDays?: number;
}>("/homes/trash"),
restore: (t: FsPlace, id: string, store?: FsTrashItem["store"]) =>
request<{ path: string; laneId: number | null }>(fsUrl(t, "/trash/restore"), {
method: "POST",
body: JSON.stringify({ id }),
body: JSON.stringify(store ? { id, store } : { id }),
}),
purge: (t: FsPlace, id: string | "all") =>
purge: (t: FsPlace, id: string | "all", store?: FsTrashItem["store"]) =>
request<{ purged: number }>(fsUrl(t, "/trash/purge"), {
method: "POST",
body: JSON.stringify({ id }),
body: JSON.stringify(store ? { id, store } : { id }),
}),
/** A zip of `paths` (files and folders), for a plain link/anchor download. */
zipUrl: (t: FsPlace, paths: string[]) => {
@@ -4262,6 +4274,8 @@ export interface GitIdentity {
sshUsers?: { host: string; user: string }[];
/** The account's commit author (`git config --global`); null fields = unset. */
author: { name: string | null; email: string | null };
/** The suggested email while none is set: `<username>@smartgift.vn`. */
defaultEmail?: string | null;
https: {
protocol: "http" | "https";
host: string;