Concepts, value, and typical clone scenarios — less code.
Concepts, value, and typical clone scenarios — less code.
Підготовка контенту платформи Ring
Підготовка контенту платформи Ring
Підготовка контенту платформи Ring
Use Founder / Developer tabs in the docs sidebar to filter this page. Uploads ride RingFileBase; public gallery bytes ride Ring CDN /files/{uuid}.
Ring File Cabinet is the personal file manager for Ring clones: nested folders (max depth 3), a three-column desktop workspace, owner / trustee ACL (trustee = view + download only), a shared-with-me desktop for every subscriber+, private gallery curation, and a public /{username}/img lightbox for items marked visibility=public.
| Surface | Who | Behavior |
|---|---|---|
/file-cabinet | Auth; member+ | Own manager — FileCabinetWrapper → FileCabinetDesktop. Non-members see MemberUpgradeGate (same pattern as add-entity). |
/profile/cabinet | — | Redirects to /file-cabinet (ROUTES.PROFILE_CABINET aliases FILE_CABINET). |
/profile/shared | subscriber+ | Full drag desktop of trustee shares. Subscriber-only users also see upgrade CTA membersUpgrade → membership with returnTo=/profile/shared. |
/profile/gallery | Auth; member+ | Curate image/video → private | unlisted | public (MemberUpgradeGate for non-members). |
/{username}/img | Public | Lightbox for visibility=public items. |
/{username}/player | Public | Mood player (renamed from /songs; no legacy redirect). Private manage stays /profile/songs. |
ACL grants are immediate (no invite-accept). Max upload 25MB via getCabinetStorageConfig(). Publications use a separate co-author model — not File Cabinet ACL.
Own File Cabinet (/file-cabinet) and gallery manage (/profile/gallery) require member privileges (hasMemberPrivileges + MemberUpgradeGate). All subscribers (and above) open /profile/shared for trustee shares — they do not get an own desktop or upload surface until they upgrade to member.
Members need a place for docs, scans, and media that is not chat attachment chaos and not the Admin Wiki vault. File Cabinet is personal storage with trusted viewers, a shared inbox for collaborators, and a public gallery face — useful for marketplaces, service rings, and any clone where trust includes “show my work.”
Members open /file-cabinet — upload, folders, trustees via ContactPicker, expandable tree + options rail. Non-members hit the membership upgrade gate.
Every subscriber+ uses /profile/shared for trustee shares (view/download desktop). An in-rail upgrade CTA points to membership for an own manager.
Depends-on: cabinet uploads go through file() / RingBaseAdapter and getCabinetStorageConfig.
Depends-on: public gallery items use stable CDN /files/{uuid} (+ _v_* derivatives).
Next-step: public /img, /player, and /games surfaces hang off /{username}.
See-also: public /games availability is a sibling profile surface (not File Cabinet ACL).
Use Founder / Developer tabs in the docs sidebar to filter this page. Uploads ride RingFileBase; public gallery bytes ride Ring CDN /files/{uuid}.
Ring File Cabinet is the personal file manager for Ring clones: nested folders (max depth 3), a three-column desktop workspace, owner / trustee ACL (trustee = view + download only), a shared-with-me desktop for every subscriber+, private gallery curation, and a public /{username}/img lightbox for items marked visibility=public.
| Surface | Who | Behavior |
|---|---|---|
/file-cabinet | Auth; member+ | Own manager — FileCabinetWrapper → FileCabinetDesktop. Non-members see MemberUpgradeGate (same pattern as add-entity). |
/profile/cabinet | — | Redirects to /file-cabinet (ROUTES.PROFILE_CABINET aliases FILE_CABINET). |
/profile/shared | subscriber+ | Full drag desktop of trustee shares. Subscriber-only users also see upgrade CTA membersUpgrade → membership with returnTo=/profile/shared. |
/profile/gallery | Auth; member+ | Curate image/video → private | unlisted | public (MemberUpgradeGate for non-members). |
/{username}/img | Public | Lightbox for visibility=public items. |
/{username}/player | Public | Mood player (renamed from /songs; no legacy redirect). Private manage stays /profile/songs. |
ACL grants are immediate (no invite-accept). Max upload 25MB via getCabinetStorageConfig(). Publications use a separate co-author model — not File Cabinet ACL.
Own File Cabinet (/file-cabinet) and gallery manage (/profile/gallery) require member privileges (hasMemberPrivileges + MemberUpgradeGate). All subscribers (and above) open /profile/shared for trustee shares — they do not get an own desktop or upload surface until they upgrade to member.
Members need a place for docs, scans, and media that is not chat attachment chaos and not the Admin Wiki vault. File Cabinet is personal storage with trusted viewers, a shared inbox for collaborators, and a public gallery face — useful for marketplaces, service rings, and any clone where trust includes “show my work.”
Members open /file-cabinet — upload, folders, trustees via ContactPicker, expandable tree + options rail. Non-members hit the membership upgrade gate.
Every subscriber+ uses /profile/shared for trustee shares (view/download desktop). An in-rail upgrade CTA points to membership for an own manager.
Depends-on: cabinet uploads go through file() / RingBaseAdapter and getCabinetStorageConfig.
Depends-on: public gallery items use stable CDN /files/{uuid} (+ _v_* derivatives).
Next-step: public /img, /player, and /games surfaces hang off /{username}.
See-also: public /games availability is a sibling profile surface (not File Cabinet ACL).
Use Founder / Developer tabs in the docs sidebar to filter this page. Uploads ride RingFileBase; public gallery bytes ride Ring CDN /files/{uuid}.
Ring File Cabinet is the personal file manager for Ring clones: nested folders (max depth 3), a three-column desktop workspace, owner / trustee ACL (trustee = view + download only), a shared-with-me desktop for every subscriber+, private gallery curation, and a public /{username}/img lightbox for items marked visibility=public.
| Surface | Who | Behavior |
|---|---|---|
/file-cabinet | Auth; member+ | Own manager — FileCabinetWrapper → FileCabinetDesktop. Non-members see MemberUpgradeGate (same pattern as add-entity). |
/profile/cabinet | — | Redirects to /file-cabinet (ROUTES.PROFILE_CABINET aliases FILE_CABINET). |
/profile/shared | subscriber+ | Full drag desktop of trustee shares. Subscriber-only users also see upgrade CTA membersUpgrade → membership with returnTo=/profile/shared. |
/profile/gallery | Auth; member+ | Curate image/video → private | unlisted | public (MemberUpgradeGate for non-members). |
/{username}/img | Public | Lightbox for visibility=public items. |
/{username}/player | Public | Mood player (renamed from /songs; no legacy redirect). Private manage stays /profile/songs. |
ACL grants are immediate (no invite-accept). Max upload 25MB via getCabinetStorageConfig(). Publications use a separate co-author model — not File Cabinet ACL.
Own File Cabinet (/file-cabinet) and gallery manage (/profile/gallery) require member privileges (hasMemberPrivileges + MemberUpgradeGate). All subscribers (and above) open /profile/shared for trustee shares — they do not get an own desktop or upload surface until they upgrade to member.
Members need a place for docs, scans, and media that is not chat attachment chaos and not the Admin Wiki vault. File Cabinet is personal storage with trusted viewers, a shared inbox for collaborators, and a public gallery face — useful for marketplaces, service rings, and any clone where trust includes “show my work.”
Members open /file-cabinet — upload, folders, trustees via ContactPicker, expandable tree + options rail. Non-members hit the membership upgrade gate.
Every subscriber+ uses /profile/shared for trustee shares (view/download desktop). An in-rail upgrade CTA points to membership for an own manager.
Depends-on: cabinet uploads go through file() / RingBaseAdapter and getCabinetStorageConfig.
Depends-on: public gallery items use stable CDN /files/{uuid} (+ _v_* derivatives).
Next-step: public /img, /player, and /games surfaces hang off /{username}.
See-also: public /games availability is a sibling profile surface (not File Cabinet ACL).
Curate at /profile/gallery (member+); public items appear on /{username}/img via CDN URLs.
/file-cabinet; shares a folder with a trustee (view/download only, immediate grant)./profile/shared, arranges trusted files on their desktop, and downloads — without owning a personal cabinet.public → visitors open /{username}/img.FsModal shows a live Trustees row (or “confidential”) and Make confidential to revoke all trustees.042_file_cabinet.sql applied (tables file_cabinet_*) and the app image includes File Cabinet UI.NEXT_PUBLIC_STORAGE_PROVIDER=ring_filebase (or equivalent), RINGBASE_API_URL, RINGBASE_PUBLIC_URL, RINGBASE_API_TOKEN — see RingFileBase./file-cabinet → Share trustees → second user (subscriber+) sees the item on /profile/shared./file-cabinet shows upgrade gate; /profile/shared still works for shared files; rail shows “Members get their own file manager”.public → open /{username}/img./files/{fileId} today.Actions (listOwnCabinetAction, upload, own desktop) |
requireMember() |
Actions (listSharedCabinetAction, shared desktop) | requireSubscriber(); scope: 'own' still requires member |
FileCabinetWrapper is a thin client boundary (components/wrappers/file-cabinet-wrapper.tsx) that renders FileCabinetDesktop. The three-column shell (RingRightRailLayout + Davinci center pane) lives inside the desktop component.
| Piece | Role |
|---|---|
| Center pane | Breadcrumbs + New folder / Upload (right) + icon workspace (no bordered desktop card) |
| Right rail | Title → expandable folders-only tree → options (DavinciGlassPanel, title = visible filename) → non-scrolling info panel |
| Tree | +/− expand; selected dir uses fully-rounded (rounded-[99px]) active surface; expand state in treeExpandedIds on the desktop document |
| Desktop icons | Visible name SSOT in icons[].meta.filename (rename overwrites; no history); image icons use sync_thumb via download ?variant= |
| Empty folder | Delete control only when the folder has no children |
| Trustees | Options row + Share FsModal (live Trustees / confidential, inline ContactPicker, Make confidential when clearing trustees) |
| Loading | Fixed-height skeletons for trustees row, info meta, and image preview (no layout jump) |
| Shared upgrade | Subscriber-only + scope === 'shared' → t('membersUpgrade') CTA → /membership?returnTo=/profile/shared |
| Path | Role |
|---|---|
features/file-cabinet/service.ts | server-only CRUD, ACL (incl. ancestor walk for inherited trustees), desktop, gallery |
features/file-cabinet/acl.ts | owner | trustee (legacy editor → trustee) |
features/file-cabinet/constants.ts | FILE_CABINET_DESKTOP_CHANNEL, FILE_CABINET_DOWNLOAD_PATH, MAX_FOLDER_DEPTH = 3 |
features/file-cabinet/desktop-filename.ts | Visible filename helpers |
features/file-cabinet/media-urls.ts | Same-origin download URL helpers (?variant=) |
features/file-cabinet/components/* | Desktop, tree, options, detail, share/rename FsModals, skeletons, gallery, public img |
app/_actions/file-cabinet.ts | Server Actions + role gates |
app/api/file-cabinet/download/route.ts | ACL check → byte stream (inline=1, optional variant= for thumbs/webp) |
lib/storage/storage-config.ts | getCabinetStorageConfig() — 25MB + MIME allowlist |
components/file-tree/tree-helpers.ts | Shared tree helpers (Admin Wiki adapters) |
data/migrations/042_file_cabinet.sql | Schema (+ mirrored in data/schema.sql) |
| Role | Capabilities |
|---|---|
owner | Full CRUD, set trustees via ContactPicker (setCabinetTrusteesAction) |
trustee | View / list / download; shared desktop layout; cannot mutate or upload |
Grants write to file_cabinet_acl immediately — no invite-accept flow. Listing ACL for the options rail walks ancestors so folder shares surface on nested files.
Tables (id + data JSONB): file_cabinet_nodes, file_cabinet_acl, file_cabinet_desktop, file_cabinet_gallery_items.
Desktop document stores icon positions and treeExpandedIds for the folders-only expand/collapse tree. Per-folder layout cache keeps drag positions when navigating nested folders.
Pass document id as createDoc(collection, data, { id }). Putting id only inside data lets PostgreSQLAdapter generateId() diverge from data.id.
Cabinet uploads use file().upload(...) with access: 'private', derivativesProfile: 'gallery' for images, and MIME/size checks from getCabinetStorageConfig() (images, PDF, Office, text/csv/md, zip, plus video/mp4 / video/webm).
Public gallery items store the CDN URL from upload (storageUrl). There are no HMAC/TTL signed URLs in the current RingBaseAdapter path — delivery is {RINGBASE_PUBLIC_URL}/files/{fileId} (+ _v_* derivatives). Private downloads use the ACL proxy (/api/file-cabinet/download) with Content-Disposition from node.name / desktop meta.filename. Direct CDN /files/{uuid} still lacks Content-Disposition — see backlog.
saveDesktop publishes to the member’s personal tunnel:
Client listens via useTunnelChannel in file-cabinet-desktop.tsx.
Ensure 042_file_cabinet.sql (and schema.sql parity) on the clone DB. Fresh installs pick up tables from data/schema.sql.
Reference RingFileBase: NEXT_PUBLIC_STORAGE_PROVIDER=ring_filebase, RINGBASE_API_URL, RINGBASE_PUBLIC_URL, RINGBASE_API_TOKEN.
Prefer app/_actions/file-cabinet.ts from client UI — do not bypass ACL helpers in service.ts. Own list/upload requires member; shared desktop requires subscriber+; getDesktop / saveDesktop for scope: 'own' still require member privileges.
app/[locale]/[username]/img/page.tsx loads listPublicGalleryByOwner(ownerId) and renders PublicProfileImgGallery. Only visibility=public items appear.
| Constant | Path |
|---|---|
ROUTES.FILE_CABINET | /file-cabinet (canonical own manager) |
ROUTES.PROFILE_CABINET | /file-cabinet (deprecated alias; /profile/cabinet redirects) |
ROUTES.PROFILE_SHARED | /profile/shared |
ROUTES.PROFILE_GALLERY | /profile/gallery |
ROUTES.PUBLIC_PROFILE_IMG(username) | /{username}/img |
ROUTES.PUBLIC_PROFILE_PLAYER(username) | /{username}/player |
Private mood-player manage remains /profile/songs (ROUTES.PROFILE_SONGS). Peer /games is a sibling public-profile surface — not File Cabinet storage.
Same-workflow: member gate for /file-cabinet vs subscriber+ shared desktop.
Curate at /profile/gallery (member+); public items appear on /{username}/img via CDN URLs.
/file-cabinet; shares a folder with a trustee (view/download only, immediate grant)./profile/shared, arranges trusted files on their desktop, and downloads — without owning a personal cabinet.public → visitors open /{username}/img.FsModal shows a live Trustees row (or “confidential”) and Make confidential to revoke all trustees.042_file_cabinet.sql applied (tables file_cabinet_*) and the app image includes File Cabinet UI.NEXT_PUBLIC_STORAGE_PROVIDER=ring_filebase (or equivalent), RINGBASE_API_URL, RINGBASE_PUBLIC_URL, RINGBASE_API_TOKEN — see RingFileBase./file-cabinet → Share trustees → second user (subscriber+) sees the item on /profile/shared./file-cabinet shows upgrade gate; /profile/shared still works for shared files; rail shows “Members get their own file manager”.public → open /{username}/img./files/{fileId} today.Actions (listOwnCabinetAction, upload, own desktop) |
requireMember() |
Actions (listSharedCabinetAction, shared desktop) | requireSubscriber(); scope: 'own' still requires member |
FileCabinetWrapper is a thin client boundary (components/wrappers/file-cabinet-wrapper.tsx) that renders FileCabinetDesktop. The three-column shell (RingRightRailLayout + Davinci center pane) lives inside the desktop component.
| Piece | Role |
|---|---|
| Center pane | Breadcrumbs + New folder / Upload (right) + icon workspace (no bordered desktop card) |
| Right rail | Title → expandable folders-only tree → options (DavinciGlassPanel, title = visible filename) → non-scrolling info panel |
| Tree | +/− expand; selected dir uses fully-rounded (rounded-[99px]) active surface; expand state in treeExpandedIds on the desktop document |
| Desktop icons | Visible name SSOT in icons[].meta.filename (rename overwrites; no history); image icons use sync_thumb via download ?variant= |
| Empty folder | Delete control only when the folder has no children |
| Trustees | Options row + Share FsModal (live Trustees / confidential, inline ContactPicker, Make confidential when clearing trustees) |
| Loading | Fixed-height skeletons for trustees row, info meta, and image preview (no layout jump) |
| Shared upgrade | Subscriber-only + scope === 'shared' → t('membersUpgrade') CTA → /membership?returnTo=/profile/shared |
| Path | Role |
|---|---|
features/file-cabinet/service.ts | server-only CRUD, ACL (incl. ancestor walk for inherited trustees), desktop, gallery |
features/file-cabinet/acl.ts | owner | trustee (legacy editor → trustee) |
features/file-cabinet/constants.ts | FILE_CABINET_DESKTOP_CHANNEL, FILE_CABINET_DOWNLOAD_PATH, MAX_FOLDER_DEPTH = 3 |
features/file-cabinet/desktop-filename.ts | Visible filename helpers |
features/file-cabinet/media-urls.ts | Same-origin download URL helpers (?variant=) |
features/file-cabinet/components/* | Desktop, tree, options, detail, share/rename FsModals, skeletons, gallery, public img |
app/_actions/file-cabinet.ts | Server Actions + role gates |
app/api/file-cabinet/download/route.ts | ACL check → byte stream (inline=1, optional variant= for thumbs/webp) |
lib/storage/storage-config.ts | getCabinetStorageConfig() — 25MB + MIME allowlist |
components/file-tree/tree-helpers.ts | Shared tree helpers (Admin Wiki adapters) |
data/migrations/042_file_cabinet.sql | Schema (+ mirrored in data/schema.sql) |
| Role | Capabilities |
|---|---|
owner | Full CRUD, set trustees via ContactPicker (setCabinetTrusteesAction) |
trustee | View / list / download; shared desktop layout; cannot mutate or upload |
Grants write to file_cabinet_acl immediately — no invite-accept flow. Listing ACL for the options rail walks ancestors so folder shares surface on nested files.
Tables (id + data JSONB): file_cabinet_nodes, file_cabinet_acl, file_cabinet_desktop, file_cabinet_gallery_items.
Desktop document stores icon positions and treeExpandedIds for the folders-only expand/collapse tree. Per-folder layout cache keeps drag positions when navigating nested folders.
Pass document id as createDoc(collection, data, { id }). Putting id only inside data lets PostgreSQLAdapter generateId() diverge from data.id.
Cabinet uploads use file().upload(...) with access: 'private', derivativesProfile: 'gallery' for images, and MIME/size checks from getCabinetStorageConfig() (images, PDF, Office, text/csv/md, zip, plus video/mp4 / video/webm).
Public gallery items store the CDN URL from upload (storageUrl). There are no HMAC/TTL signed URLs in the current RingBaseAdapter path — delivery is {RINGBASE_PUBLIC_URL}/files/{fileId} (+ _v_* derivatives). Private downloads use the ACL proxy (/api/file-cabinet/download) with Content-Disposition from node.name / desktop meta.filename. Direct CDN /files/{uuid} still lacks Content-Disposition — see backlog.
saveDesktop publishes to the member’s personal tunnel:
Client listens via useTunnelChannel in file-cabinet-desktop.tsx.
Ensure 042_file_cabinet.sql (and schema.sql parity) on the clone DB. Fresh installs pick up tables from data/schema.sql.
Reference RingFileBase: NEXT_PUBLIC_STORAGE_PROVIDER=ring_filebase, RINGBASE_API_URL, RINGBASE_PUBLIC_URL, RINGBASE_API_TOKEN.
Prefer app/_actions/file-cabinet.ts from client UI — do not bypass ACL helpers in service.ts. Own list/upload requires member; shared desktop requires subscriber+; getDesktop / saveDesktop for scope: 'own' still require member privileges.
app/[locale]/[username]/img/page.tsx loads listPublicGalleryByOwner(ownerId) and renders PublicProfileImgGallery. Only visibility=public items appear.
| Constant | Path |
|---|---|
ROUTES.FILE_CABINET | /file-cabinet (canonical own manager) |
ROUTES.PROFILE_CABINET | /file-cabinet (deprecated alias; /profile/cabinet redirects) |
ROUTES.PROFILE_SHARED | /profile/shared |
ROUTES.PROFILE_GALLERY | /profile/gallery |
ROUTES.PUBLIC_PROFILE_IMG(username) | /{username}/img |
ROUTES.PUBLIC_PROFILE_PLAYER(username) | /{username}/player |
Private mood-player manage remains /profile/songs (ROUTES.PROFILE_SONGS). Peer /games is a sibling public-profile surface — not File Cabinet storage.
Same-workflow: member gate for /file-cabinet vs subscriber+ shared desktop.
Curate at /profile/gallery (member+); public items appear on /{username}/img via CDN URLs.
/file-cabinet; shares a folder with a trustee (view/download only, immediate grant)./profile/shared, arranges trusted files on their desktop, and downloads — without owning a personal cabinet.public → visitors open /{username}/img.FsModal shows a live Trustees row (or “confidential”) and Make confidential to revoke all trustees.042_file_cabinet.sql applied (tables file_cabinet_*) and the app image includes File Cabinet UI.NEXT_PUBLIC_STORAGE_PROVIDER=ring_filebase (or equivalent), RINGBASE_API_URL, RINGBASE_PUBLIC_URL, RINGBASE_API_TOKEN — see RingFileBase./file-cabinet → Share trustees → second user (subscriber+) sees the item on /profile/shared./file-cabinet shows upgrade gate; /profile/shared still works for shared files; rail shows “Members get their own file manager”.public → open /{username}/img./files/{fileId} today.Actions (listOwnCabinetAction, upload, own desktop) |
requireMember() |
Actions (listSharedCabinetAction, shared desktop) | requireSubscriber(); scope: 'own' still requires member |
FileCabinetWrapper is a thin client boundary (components/wrappers/file-cabinet-wrapper.tsx) that renders FileCabinetDesktop. The three-column shell (RingRightRailLayout + Davinci center pane) lives inside the desktop component.
| Piece | Role |
|---|---|
| Center pane | Breadcrumbs + New folder / Upload (right) + icon workspace (no bordered desktop card) |
| Right rail | Title → expandable folders-only tree → options (DavinciGlassPanel, title = visible filename) → non-scrolling info panel |
| Tree | +/− expand; selected dir uses fully-rounded (rounded-[99px]) active surface; expand state in treeExpandedIds on the desktop document |
| Desktop icons | Visible name SSOT in icons[].meta.filename (rename overwrites; no history); image icons use sync_thumb via download ?variant= |
| Empty folder | Delete control only when the folder has no children |
| Trustees | Options row + Share FsModal (live Trustees / confidential, inline ContactPicker, Make confidential when clearing trustees) |
| Loading | Fixed-height skeletons for trustees row, info meta, and image preview (no layout jump) |
| Shared upgrade | Subscriber-only + scope === 'shared' → t('membersUpgrade') CTA → /membership?returnTo=/profile/shared |
| Path | Role |
|---|---|
features/file-cabinet/service.ts | server-only CRUD, ACL (incl. ancestor walk for inherited trustees), desktop, gallery |
features/file-cabinet/acl.ts | owner | trustee (legacy editor → trustee) |
features/file-cabinet/constants.ts | FILE_CABINET_DESKTOP_CHANNEL, FILE_CABINET_DOWNLOAD_PATH, MAX_FOLDER_DEPTH = 3 |
features/file-cabinet/desktop-filename.ts | Visible filename helpers |
features/file-cabinet/media-urls.ts | Same-origin download URL helpers (?variant=) |
features/file-cabinet/components/* | Desktop, tree, options, detail, share/rename FsModals, skeletons, gallery, public img |
app/_actions/file-cabinet.ts | Server Actions + role gates |
app/api/file-cabinet/download/route.ts | ACL check → byte stream (inline=1, optional variant= for thumbs/webp) |
lib/storage/storage-config.ts | getCabinetStorageConfig() — 25MB + MIME allowlist |
components/file-tree/tree-helpers.ts | Shared tree helpers (Admin Wiki adapters) |
data/migrations/042_file_cabinet.sql | Schema (+ mirrored in data/schema.sql) |
| Role | Capabilities |
|---|---|
owner | Full CRUD, set trustees via ContactPicker (setCabinetTrusteesAction) |
trustee | View / list / download; shared desktop layout; cannot mutate or upload |
Grants write to file_cabinet_acl immediately — no invite-accept flow. Listing ACL for the options rail walks ancestors so folder shares surface on nested files.
Tables (id + data JSONB): file_cabinet_nodes, file_cabinet_acl, file_cabinet_desktop, file_cabinet_gallery_items.
Desktop document stores icon positions and treeExpandedIds for the folders-only expand/collapse tree. Per-folder layout cache keeps drag positions when navigating nested folders.
Pass document id as createDoc(collection, data, { id }). Putting id only inside data lets PostgreSQLAdapter generateId() diverge from data.id.
Cabinet uploads use file().upload(...) with access: 'private', derivativesProfile: 'gallery' for images, and MIME/size checks from getCabinetStorageConfig() (images, PDF, Office, text/csv/md, zip, plus video/mp4 / video/webm).
Public gallery items store the CDN URL from upload (storageUrl). There are no HMAC/TTL signed URLs in the current RingBaseAdapter path — delivery is {RINGBASE_PUBLIC_URL}/files/{fileId} (+ _v_* derivatives). Private downloads use the ACL proxy (/api/file-cabinet/download) with Content-Disposition from node.name / desktop meta.filename. Direct CDN /files/{uuid} still lacks Content-Disposition — see backlog.
saveDesktop publishes to the member’s personal tunnel:
Client listens via useTunnelChannel in file-cabinet-desktop.tsx.
Ensure 042_file_cabinet.sql (and schema.sql parity) on the clone DB. Fresh installs pick up tables from data/schema.sql.
Reference RingFileBase: NEXT_PUBLIC_STORAGE_PROVIDER=ring_filebase, RINGBASE_API_URL, RINGBASE_PUBLIC_URL, RINGBASE_API_TOKEN.
Prefer app/_actions/file-cabinet.ts from client UI — do not bypass ACL helpers in service.ts. Own list/upload requires member; shared desktop requires subscriber+; getDesktop / saveDesktop for scope: 'own' still require member privileges.
app/[locale]/[username]/img/page.tsx loads listPublicGalleryByOwner(ownerId) and renders PublicProfileImgGallery. Only visibility=public items appear.
| Constant | Path |
|---|---|
ROUTES.FILE_CABINET | /file-cabinet (canonical own manager) |
ROUTES.PROFILE_CABINET | /file-cabinet (deprecated alias; /profile/cabinet redirects) |
ROUTES.PROFILE_SHARED | /profile/shared |
ROUTES.PROFILE_GALLERY | /profile/gallery |
ROUTES.PUBLIC_PROFILE_IMG(username) | /{username}/img |
ROUTES.PUBLIC_PROFILE_PLAYER(username) | /{username}/player |
Private mood-player manage remains /profile/songs (ROUTES.PROFILE_SONGS). Peer /games is a sibling public-profile surface — not File Cabinet storage.
Same-workflow: member gate for /file-cabinet vs subscriber+ shared desktop.