OpportunitiesEntities
Docs
    Ring Platform

    Decentralized Self-building Future

    Sign In
    Entities
    Opportunities
    Store
    Docs
    Platform Concepts
    RING EconomySonoratek LLCGlobal ImpactAI Meets Web3
    Get Started
    Quick StartCalculatorRoadmap
    Privacy|Contact
    v1.104.17|Sonoratek LLC

    Documentation

    Concepts, value, and typical clone scenarios — less code.

    Welcome to Ring
    Quick Reference
    Getting Started
    Prerequisites
    Installation
    First Success Validation
    Next Steps
    Features
    Multi-Vendor Store
    Inventory & Stock
    Vendor Management
    Commissions & Settlements
    SubscriptionConductor
    PaymentConductor
    Ring Oracle
    Payments Overview
    Public Pools & DAO Jars
    WayForPay Payment Integration
    Wallet & Credit System
    WalletConductor
    Affiliate & Referral Enablement
    Referral Codes (Refcodes)
    NFT Exhibition Marketplace
    Solana NFT Gates
    Token Staking System
    Owner Project Lab
    Entities
    Opportunities
    Real-Time Messaging
    Ring Tasks
    WebRTC Calls & STUNner TURN
    Peer Games
    News Module
    Member Blogs
    Public Profile Pages
    Profile Account Widgets
    Ring File Cabinet
    Username Reservation System
    Scientific Editor
    Notifications
    Push Notifications with FCM (Ring-Powered)
    Email AI-CRM
    Ring Mailer & RingdomX Mail
    Tunnel Protocol
    VideoConductor
    MediaConductor
    Generative Gallery
    Authentication
    Security & Compliance
    Admin console
    Admin Wiki
    Manage via Telegram
    Locale System
    Mobile Experience
    Performance Optimization Patterns
    Examples
    Quick Start
    Basic Setup
    White Label
    Custom Branding
    Web3 Integration
    Real World
    Advanced Features
    Customization
    Quick Start — Your First Ring Clone
    Customization Guide
    Vertical Presets (SSOT)
    Ringization playbook
    Branding
    Themes
    Features
    Localization
    Token Economics Setup
    Payment Gateway Integration
    Reference Ring deployments
    Project configuration
    Public environment variables
    Order Lab secrets
    WalletConnect Project ID (Reown Cloud)
    Supported services
    NODUS wiki (project knowledge)
    Configuration playbook
    Web3
    Token launch jurisdictions
    Wallet
    Wallet Security Tips
    Integrations
    Ethereum wallets (Wagmi v3)
    RingFileBase (object storage API)
    Ring CDN (RingFileBase edge)
    Deployment
    Self-hosted deployment
    Vercel Deployment
    Docker
    Environment Configuration
    Monitoring & Analytics
    Performance Optimization
    Backup & Recovery
    Architecture
    Data Model
    Security
    Real Time
    Discovery Mutation Sync
    PaymentConductor architecture
    WalletConductor architecture
    Backend Services
    Firebase Integration
    Development
    Ring MCP Server

    Quick entry (CTOs · auditors · agents)

    Welcome — mission & audiences
    Quick Reference
    Getting started
    Architecture & Auth.js
    Backend modes & databases (DB_BACKEND_MODE)
    Self-hosted
    Ring MCP Tools
    Ring MCP Server
    Token economics
    Token launch jurisdictions
    Deploy (Docker · k8s)
    Security & compliance reads
    ringdom.org — LegioX homebase
    Source — MIT license (GitHub)

    Documentation

    Concepts, value, and typical clone scenarios — less code.

    Welcome to Ring
    Quick Reference
    Getting Started
    Prerequisites
    Installation
    First Success Validation
    Next Steps
    Features
    Multi-Vendor Store
    Inventory & Stock
    Vendor Management
    Commissions & Settlements
    SubscriptionConductor
    PaymentConductor
    Ring Oracle
    Payments Overview
    Public Pools & DAO Jars
    WayForPay Payment Integration
    Wallet & Credit System
    WalletConductor
    Affiliate & Referral Enablement
    Referral Codes (Refcodes)
    NFT Exhibition Marketplace
    Solana NFT Gates
    Token Staking System
    Owner Project Lab
    Entities
    Opportunities
    Real-Time Messaging
    Ring Tasks
    WebRTC Calls & STUNner TURN
    Peer Games
    News Module
    Member Blogs
    Public Profile Pages
    Profile Account Widgets
    Ring File Cabinet
    Username Reservation System
    Scientific Editor
    Notifications
    Push Notifications with FCM (Ring-Powered)
    Email AI-CRM
    Ring Mailer & RingdomX Mail
    Tunnel Protocol
    VideoConductor
    MediaConductor
    Generative Gallery
    Authentication
    Security & Compliance
    Admin console
    Admin Wiki
    Manage via Telegram
    Locale System
    Mobile Experience
    Performance Optimization Patterns
    Examples
    Quick Start
    Basic Setup
    White Label
    Custom Branding
    Web3 Integration
    Real World
    Advanced Features
    Customization
    Quick Start — Your First Ring Clone
    Customization Guide
    Vertical Presets (SSOT)
    Ringization playbook
    Branding
    Themes
    Features
    Localization
    Token Economics Setup
    Payment Gateway Integration
    Reference Ring deployments
    Project configuration
    Public environment variables
    Order Lab secrets
    WalletConnect Project ID (Reown Cloud)
    Supported services
    NODUS wiki (project knowledge)
    Configuration playbook
    Web3
    Token launch jurisdictions
    Wallet
    Wallet Security Tips
    Integrations
    Ethereum wallets (Wagmi v3)
    RingFileBase (object storage API)
    Ring CDN (RingFileBase edge)
    Deployment
    Self-hosted deployment
    Vercel Deployment
    Docker
    Environment Configuration
    Monitoring & Analytics
    Performance Optimization
    Backup & Recovery
    Architecture
    Data Model
    Security
    Real Time
    Discovery Mutation Sync
    PaymentConductor architecture
    WalletConductor architecture
    Backend Services
    Firebase Integration
    Development
    Ring MCP Server

    Quick entry (CTOs · auditors · agents)

    Welcome — mission & audiences
    Quick Reference
    Getting started
    Architecture & Auth.js
    Backend modes & databases (DB_BACKEND_MODE)
    Self-hosted
    Ring MCP Tools
    Ring MCP Server
    Token economics
    Token launch jurisdictions
    Deploy (Docker · k8s)
    Security & compliance reads
    ringdom.org — LegioX homebase
    Source — MIT license (GitHub)

    Documentation

    Concepts, value, and typical clone scenarios — less code.

    Welcome to Ring
    Quick Reference
    Getting Started
    Prerequisites
    Installation
    First Success Validation
    Next Steps
    Features
    Multi-Vendor Store
    Inventory & Stock
    Vendor Management
    Commissions & Settlements
    SubscriptionConductor
    PaymentConductor
    Ring Oracle
    Payments Overview
    Public Pools & DAO Jars
    WayForPay Payment Integration
    Wallet & Credit System
    WalletConductor
    Affiliate & Referral Enablement
    Referral Codes (Refcodes)
    NFT Exhibition Marketplace
    Solana NFT Gates
    Token Staking System
    Owner Project Lab
    Entities
    Opportunities
    Real-Time Messaging
    Ring Tasks
    WebRTC Calls & STUNner TURN
    Peer Games
    News Module
    Member Blogs
    Public Profile Pages
    Profile Account Widgets
    Ring File Cabinet
    Username Reservation System
    Scientific Editor
    Notifications
    Push Notifications with FCM (Ring-Powered)
    Email AI-CRM
    Ring Mailer & RingdomX Mail
    Tunnel Protocol
    VideoConductor
    MediaConductor
    Generative Gallery
    Authentication
    Security & Compliance
    Admin console
    Admin Wiki
    Manage via Telegram
    Locale System
    Mobile Experience
    Performance Optimization Patterns
    Examples
    Quick Start
    Basic Setup
    White Label
    Custom Branding
    Web3 Integration
    Real World
    Advanced Features
    Customization
    Quick Start — Your First Ring Clone
    Customization Guide
    Vertical Presets (SSOT)
    Ringization playbook
    Branding
    Themes
    Features
    Localization
    Token Economics Setup
    Payment Gateway Integration
    Reference Ring deployments
    Project configuration
    Public environment variables
    Order Lab secrets
    WalletConnect Project ID (Reown Cloud)
    Supported services
    NODUS wiki (project knowledge)
    Configuration playbook
    Web3
    Token launch jurisdictions
    Wallet
    Wallet Security Tips
    Integrations
    Ethereum wallets (Wagmi v3)
    RingFileBase (object storage API)
    Ring CDN (RingFileBase edge)
    Deployment
    Self-hosted deployment
    Vercel Deployment
    Docker
    Environment Configuration
    Monitoring & Analytics
    Performance Optimization
    Backup & Recovery
    Architecture
    Data Model
    Security
    Real Time
    Discovery Mutation Sync
    PaymentConductor architecture
    WalletConductor architecture
    Backend Services
    Firebase Integration
    Development
    Ring MCP Server

    Quick entry (CTOs · auditors · agents)

    Welcome — mission & audiences
    Quick Reference
    Getting started
    Architecture & Auth.js
    Backend modes & databases (DB_BACKEND_MODE)
    Self-hosted
    Ring MCP Tools
    Ring MCP Server
    Token economics
    Token launch jurisdictions
    Deploy (Docker · k8s)
    Security & compliance reads
    ringdom.org — LegioX homebase
    Source — MIT license (GitHub)
    Ring Logo

    Loading documentation...

    Preparing Ring content

    Ring Logo

    Loading documentation...

    Preparing Ring content

    Ring Logo

    Loading documentation...

    Preparing Ring content

    Ring File Cabinet

    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.

    Access gates (verified)

    SurfaceWhoBehavior
    /file-cabinetAuth; 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/sharedsubscriber+Full drag desktop of trustee shares. Subscriber-only users also see upgrade CTA membersUpgrade → membership with returnTo=/profile/shared.
    /profile/galleryAuth; member+Curate image/video → private | unlisted | public (MemberUpgradeGate for non-members).
    /{username}/imgPublicLightbox for visibility=public items.
    /{username}/playerPublicMood 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.

    Member-gated own manager · shared for all subscribers

    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.

    Why this matters for your clone

    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.”

    Who gets what (operator view)

    File Cabinet access gates

    Own file manager (member+)

    Members open /file-cabinet — upload, folders, trustees via ContactPicker, expandable tree + options rail. Non-members hit the membership upgrade gate.

    Shared for all subscribers

    Every subscriber+ uses /profile/shared for trustee shares (view/download desktop). An in-rail upgrade CTA points to membership for an own manager.

    Architecture

    Role gates in code (verified)

    SurfaceGate
    app/.../file-cabinet/page.tsxauth → hasMemberPrivileges else MemberUpgradeGate (returnTo = ROUTES.FILE_CABINET)
    app/.../profile/shared/page.tsxauth → hasRoleAtLeast(..., subscriber) else unauthorized
    app/.../profile/gallery/page.tsxauth → hasMemberPrivileges else MemberUpgradeGate
    app/.../profile/cabinet/page.tsxRedirect → ROUTES.FILE_CABINET

    Related documentation

    Related documentation

    RingFileBase (object storage API)

    Depends-on: cabinet uploads go through file() / RingBaseAdapter and getCabinetStorageConfig.

    Ring CDN (RingFileBase edge)

    Depends-on: public gallery items use stable CDN /files/{uuid} (+ _v_* derivatives).

    Public Profile Pages

    Next-step: public /img, /player, and /games surfaces hang off /{username}.

    Peer Games

    See-also: public /games availability is a sibling profile surface (not File Cabinet ACL).

    Ring File Cabinet

    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.

    Access gates (verified)

    SurfaceWhoBehavior
    /file-cabinetAuth; 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/sharedsubscriber+Full drag desktop of trustee shares. Subscriber-only users also see upgrade CTA membersUpgrade → membership with returnTo=/profile/shared.
    /profile/galleryAuth; member+Curate image/video → private | unlisted | public (MemberUpgradeGate for non-members).
    /{username}/imgPublicLightbox for visibility=public items.
    /{username}/playerPublicMood 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.

    Member-gated own manager · shared for all subscribers

    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.

    Why this matters for your clone

    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.”

    Who gets what (operator view)

    File Cabinet access gates

    Own file manager (member+)

    Members open /file-cabinet — upload, folders, trustees via ContactPicker, expandable tree + options rail. Non-members hit the membership upgrade gate.

    Shared for all subscribers

    Every subscriber+ uses /profile/shared for trustee shares (view/download desktop). An in-rail upgrade CTA points to membership for an own manager.

    Architecture

    Role gates in code (verified)

    SurfaceGate
    app/.../file-cabinet/page.tsxauth → hasMemberPrivileges else MemberUpgradeGate (returnTo = ROUTES.FILE_CABINET)
    app/.../profile/shared/page.tsxauth → hasRoleAtLeast(..., subscriber) else unauthorized
    app/.../profile/gallery/page.tsxauth → hasMemberPrivileges else MemberUpgradeGate
    app/.../profile/cabinet/page.tsxRedirect → ROUTES.FILE_CABINET

    Related documentation

    Related documentation

    RingFileBase (object storage API)

    Depends-on: cabinet uploads go through file() / RingBaseAdapter and getCabinetStorageConfig.

    Ring CDN (RingFileBase edge)

    Depends-on: public gallery items use stable CDN /files/{uuid} (+ _v_* derivatives).

    Public Profile Pages

    Next-step: public /img, /player, and /games surfaces hang off /{username}.

    Peer Games

    See-also: public /games availability is a sibling profile surface (not File Cabinet ACL).

    Ring File Cabinet

    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.

    Access gates (verified)

    SurfaceWhoBehavior
    /file-cabinetAuth; 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/sharedsubscriber+Full drag desktop of trustee shares. Subscriber-only users also see upgrade CTA membersUpgrade → membership with returnTo=/profile/shared.
    /profile/galleryAuth; member+Curate image/video → private | unlisted | public (MemberUpgradeGate for non-members).
    /{username}/imgPublicLightbox for visibility=public items.
    /{username}/playerPublicMood 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.

    Member-gated own manager · shared for all subscribers

    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.

    Why this matters for your clone

    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.”

    Who gets what (operator view)

    File Cabinet access gates

    Own file manager (member+)

    Members open /file-cabinet — upload, folders, trustees via ContactPicker, expandable tree + options rail. Non-members hit the membership upgrade gate.

    Shared for all subscribers

    Every subscriber+ uses /profile/shared for trustee shares (view/download desktop). An in-rail upgrade CTA points to membership for an own manager.

    Architecture

    Role gates in code (verified)

    SurfaceGate
    app/.../file-cabinet/page.tsxauth → hasMemberPrivileges else MemberUpgradeGate (returnTo = ROUTES.FILE_CABINET)
    app/.../profile/shared/page.tsxauth → hasRoleAtLeast(..., subscriber) else unauthorized
    app/.../profile/gallery/page.tsxauth → hasMemberPrivileges else MemberUpgradeGate
    app/.../profile/cabinet/page.tsxRedirect → ROUTES.FILE_CABINET

    Related documentation

    Related documentation

    RingFileBase (object storage API)

    Depends-on: cabinet uploads go through file() / RingBaseAdapter and getCabinetStorageConfig.

    Ring CDN (RingFileBase edge)

    Depends-on: public gallery items use stable CDN /files/{uuid} (+ _v_* derivatives).

    Public Profile Pages

    Next-step: public /img, /player, and /games surfaces hang off /{username}.

    Peer Games

    See-also: public /games availability is a sibling profile surface (not File Cabinet ACL).

    Public gallery

    Curate at /profile/gallery (member+); public items appear on /{username}/img via CDN URLs.

    Storage plane

    Objects live in RingFileBase / MinIO; gallery images can request derivativesProfile: gallery.

    Generative Gallery from cabinet

    Detail-panel Image/Video chat opens the generative fs-modal (scope: cabinet); saves siblings under the source parent.

    Typical scenarios

    1. Vendor media kit — Member uploads PDFs and product photos on /file-cabinet; shares a folder with a trustee (view/download only, immediate grant).
    2. Store Agent Research alt folder — Product Research writes research-{runId}.md and citation-backed images under store/[storename]/[product-slug]/alt (depth ≤3). Vendors open those images in the detail panel → Image chat / Video chat to enhance or enlive, then save a sibling next to the source.
    3. Subscriber collaborator — A subscriber without membership still opens /profile/shared, arranges trusted files on their desktop, and downloads — without owning a personal cabinet.
    4. Public portfolio strip — Owner marks selected images public → visitors open /{username}/img.
    5. Confidential vs shared — Empty trustee list = confidential; Share FsModal shows a live Trustees row (or “confidential”) and Make confidential to revoke all trustees.

    Operator checklist

    • Confirm migration 042_file_cabinet.sql applied (tables file_cabinet_*) and the app image includes File Cabinet UI.
    • Env: NEXT_PUBLIC_STORAGE_PROVIDER=ring_filebase (or equivalent), RINGBASE_API_URL, RINGBASE_PUBLIC_URL, RINGBASE_API_TOKEN — see RingFileBase.
    • Smoke as member: upload on /file-cabinet → Share trustees → second user (subscriber+) sees the item on /profile/shared.
    • Smoke as subscriber (non-member): /file-cabinet shows upgrade gate; /profile/shared still works for shared files; rail shows “Members get their own file manager”.
    • Smoke gallery: add image → set public → open /{username}/img.
    • Do not expect HMAC/TTL signed URLs — public delivery is stable CDN /files/{fileId} today.
    Actions (listOwnCabinetAction, upload, own desktop)
    requireMember()
    Actions (listSharedCabinetAction, shared desktop)requireSubscriber(); scope: 'own' still requires member

    UX shell (verified)

    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.

    PieceRole
    Center paneBreadcrumbs + New folder / Upload (right) + icon workspace (no bordered desktop card)
    Right railTitle → 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 iconsVisible name SSOT in icons[].meta.filename (rename overwrites; no history); image icons use sync_thumb via download ?variant=
    Empty folderDelete control only when the folder has no children
    TrusteesOptions row + Share FsModal (live Trustees / confidential, inline ContactPicker, Make confidential when clearing trustees)
    LoadingFixed-height skeletons for trustees row, info meta, and image preview (no layout jump)
    Shared upgradeSubscriber-only + scope === 'shared' → t('membersUpgrade') CTA → /membership?returnTo=/profile/shared
    Image / Video chatDetail panel (file-cabinet-detail-panel.tsx) on image files → GenerativeMediaEditorFsModal (scope="cabinet")
    Sibling savesaveGeneratedMediaToDesktopAction under source parentId as {base}-enhanced-{ts}.{ext} or {base}-enlive-{ts}.{ext}

    Product research alt path (store Agent Knowledge)

    When vendors run Research on a product, features/store/lib/product-cabinet-media.ts ensures three nested dirs under the vendor owner’s cabinet (conceptual files/ root + MAX_FOLDER_DEPTH = 3):

    store/[storename]/[product-slug]/alt

    Artifacts: research-{runId}.md plus downloaded research-{runId}-N.{ext} images (SSRF-checked HTTP(S) fetch → RingBase → createFileNode). Storefront gallery enablement stays on the product form (Use in gallery) — see Multi-Vendor Store. Pipeline: cabinet.genmedia.sibling_save in scripts/PIPELINES.md.

    Module map

    PathRole
    features/file-cabinet/service.tsserver-only CRUD, ACL (incl. ancestor walk for inherited trustees), desktop, gallery
    features/file-cabinet/acl.tsowner | trustee (legacy editor → trustee)
    features/file-cabinet/constants.tsFILE_CABINET_DESKTOP_CHANNEL, FILE_CABINET_DOWNLOAD_PATH, MAX_FOLDER_DEPTH = 3
    features/file-cabinet/desktop-filename.tsVisible filename helpers
    features/file-cabinet/media-urls.tsSame-origin download URL helpers (?variant=)
    features/file-cabinet/components/*Desktop, tree, options, detail (Image/Video chat), share/rename FsModals, skeletons, gallery, public img
    app/_actions/file-cabinet.tsServer Actions + role gates + saveGeneratedMediaToDesktopAction
    features/store/lib/product-cabinet-media.tsStore research → store/…/alt writer (SSRF-safe)
    app/api/file-cabinet/download/route.tsACL check → byte stream (inline=1, optional variant= for thumbs/webp)
    lib/storage/storage-config.tsgetCabinetStorageConfig() — 25MB + MIME allowlist
    components/file-tree/tree-helpers.tsShared tree helpers (Admin Wiki adapters)
    data/migrations/042_file_cabinet.sqlSchema (+ mirrored in data/schema.sql)

    ACL model

    RoleCapabilities
    ownerFull CRUD, set trustees via ContactPicker (setCabinetTrusteesAction)
    trusteeView / 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.

    Schema (JSONB collections)

    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.

    createDoc id options

    Pass document id as createDoc(collection, data, { id }). Putting id only inside data lets PostgreSQLAdapter generateId() diverge from data.id.

    Storage upload (verified)

    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.

    Desktop tunnel

    saveDesktop publishes to the member’s personal tunnel:

    Client listens via useTunnelChannel in file-cabinet-desktop.tsx.

    Wire-up steps

    1. 1

      Apply migration

      Ensure 042_file_cabinet.sql (and schema.sql parity) on the clone DB. Fresh installs pick up tables from data/schema.sql.

    2. 2

      Confirm storage env

      Reference RingFileBase: NEXT_PUBLIC_STORAGE_PROVIDER=ring_filebase, RINGBASE_API_URL, RINGBASE_PUBLIC_URL, RINGBASE_API_TOKEN.

    3. 3

      Call through Server Actions

      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.

    4. 4

      Public img page

      app/[locale]/[username]/img/page.tsx loads listPublicGalleryByOwner(ownerId) and renders PublicProfileImgGallery. Only visibility=public items appear.

    Routes (constants)

    ConstantPath
    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.

    SubscriptionConductor

    Same-workflow: member gate for /file-cabinet vs subscriber+ shared desktop.

    Tunnel Protocol

    Deep-dive: desktop icon sync uses publishToUserTunnel on channel file-cabinet:desktop-icons.

    Admin Wiki

    See-also: shared FileTree helpers and JSONB id+data collection pattern.

    Multi-Vendor Store

    Same-workflow: Agent Knowledge Research writes markdown + images into store/product/alt.

    Generative Gallery

    Depends-on: cabinet Image/Video chat reuses GenerativeMediaEditorFsModal with scope cabinet.

    Public gallery

    Curate at /profile/gallery (member+); public items appear on /{username}/img via CDN URLs.

    Storage plane

    Objects live in RingFileBase / MinIO; gallery images can request derivativesProfile: gallery.

    Generative Gallery from cabinet

    Detail-panel Image/Video chat opens the generative fs-modal (scope: cabinet); saves siblings under the source parent.

    Typical scenarios

    1. Vendor media kit — Member uploads PDFs and product photos on /file-cabinet; shares a folder with a trustee (view/download only, immediate grant).
    2. Store Agent Research alt folder — Product Research writes research-{runId}.md and citation-backed images under store/[storename]/[product-slug]/alt (depth ≤3). Vendors open those images in the detail panel → Image chat / Video chat to enhance or enlive, then save a sibling next to the source.
    3. Subscriber collaborator — A subscriber without membership still opens /profile/shared, arranges trusted files on their desktop, and downloads — without owning a personal cabinet.
    4. Public portfolio strip — Owner marks selected images public → visitors open /{username}/img.
    5. Confidential vs shared — Empty trustee list = confidential; Share FsModal shows a live Trustees row (or “confidential”) and Make confidential to revoke all trustees.

    Operator checklist

    • Confirm migration 042_file_cabinet.sql applied (tables file_cabinet_*) and the app image includes File Cabinet UI.
    • Env: NEXT_PUBLIC_STORAGE_PROVIDER=ring_filebase (or equivalent), RINGBASE_API_URL, RINGBASE_PUBLIC_URL, RINGBASE_API_TOKEN — see RingFileBase.
    • Smoke as member: upload on /file-cabinet → Share trustees → second user (subscriber+) sees the item on /profile/shared.
    • Smoke as subscriber (non-member): /file-cabinet shows upgrade gate; /profile/shared still works for shared files; rail shows “Members get their own file manager”.
    • Smoke gallery: add image → set public → open /{username}/img.
    • Do not expect HMAC/TTL signed URLs — public delivery is stable CDN /files/{fileId} today.
    Actions (listOwnCabinetAction, upload, own desktop)
    requireMember()
    Actions (listSharedCabinetAction, shared desktop)requireSubscriber(); scope: 'own' still requires member

    UX shell (verified)

    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.

    PieceRole
    Center paneBreadcrumbs + New folder / Upload (right) + icon workspace (no bordered desktop card)
    Right railTitle → 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 iconsVisible name SSOT in icons[].meta.filename (rename overwrites; no history); image icons use sync_thumb via download ?variant=
    Empty folderDelete control only when the folder has no children
    TrusteesOptions row + Share FsModal (live Trustees / confidential, inline ContactPicker, Make confidential when clearing trustees)
    LoadingFixed-height skeletons for trustees row, info meta, and image preview (no layout jump)
    Shared upgradeSubscriber-only + scope === 'shared' → t('membersUpgrade') CTA → /membership?returnTo=/profile/shared
    Image / Video chatDetail panel (file-cabinet-detail-panel.tsx) on image files → GenerativeMediaEditorFsModal (scope="cabinet")
    Sibling savesaveGeneratedMediaToDesktopAction under source parentId as {base}-enhanced-{ts}.{ext} or {base}-enlive-{ts}.{ext}

    Product research alt path (store Agent Knowledge)

    When vendors run Research on a product, features/store/lib/product-cabinet-media.ts ensures three nested dirs under the vendor owner’s cabinet (conceptual files/ root + MAX_FOLDER_DEPTH = 3):

    store/[storename]/[product-slug]/alt

    Artifacts: research-{runId}.md plus downloaded research-{runId}-N.{ext} images (SSRF-checked HTTP(S) fetch → RingBase → createFileNode). Storefront gallery enablement stays on the product form (Use in gallery) — see Multi-Vendor Store. Pipeline: cabinet.genmedia.sibling_save in scripts/PIPELINES.md.

    Module map

    PathRole
    features/file-cabinet/service.tsserver-only CRUD, ACL (incl. ancestor walk for inherited trustees), desktop, gallery
    features/file-cabinet/acl.tsowner | trustee (legacy editor → trustee)
    features/file-cabinet/constants.tsFILE_CABINET_DESKTOP_CHANNEL, FILE_CABINET_DOWNLOAD_PATH, MAX_FOLDER_DEPTH = 3
    features/file-cabinet/desktop-filename.tsVisible filename helpers
    features/file-cabinet/media-urls.tsSame-origin download URL helpers (?variant=)
    features/file-cabinet/components/*Desktop, tree, options, detail (Image/Video chat), share/rename FsModals, skeletons, gallery, public img
    app/_actions/file-cabinet.tsServer Actions + role gates + saveGeneratedMediaToDesktopAction
    features/store/lib/product-cabinet-media.tsStore research → store/…/alt writer (SSRF-safe)
    app/api/file-cabinet/download/route.tsACL check → byte stream (inline=1, optional variant= for thumbs/webp)
    lib/storage/storage-config.tsgetCabinetStorageConfig() — 25MB + MIME allowlist
    components/file-tree/tree-helpers.tsShared tree helpers (Admin Wiki adapters)
    data/migrations/042_file_cabinet.sqlSchema (+ mirrored in data/schema.sql)

    ACL model

    RoleCapabilities
    ownerFull CRUD, set trustees via ContactPicker (setCabinetTrusteesAction)
    trusteeView / 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.

    Schema (JSONB collections)

    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.

    createDoc id options

    Pass document id as createDoc(collection, data, { id }). Putting id only inside data lets PostgreSQLAdapter generateId() diverge from data.id.

    Storage upload (verified)

    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.

    Desktop tunnel

    saveDesktop publishes to the member’s personal tunnel:

    Client listens via useTunnelChannel in file-cabinet-desktop.tsx.

    Wire-up steps

    1. 1

      Apply migration

      Ensure 042_file_cabinet.sql (and schema.sql parity) on the clone DB. Fresh installs pick up tables from data/schema.sql.

    2. 2

      Confirm storage env

      Reference RingFileBase: NEXT_PUBLIC_STORAGE_PROVIDER=ring_filebase, RINGBASE_API_URL, RINGBASE_PUBLIC_URL, RINGBASE_API_TOKEN.

    3. 3

      Call through Server Actions

      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.

    4. 4

      Public img page

      app/[locale]/[username]/img/page.tsx loads listPublicGalleryByOwner(ownerId) and renders PublicProfileImgGallery. Only visibility=public items appear.

    Routes (constants)

    ConstantPath
    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.

    SubscriptionConductor

    Same-workflow: member gate for /file-cabinet vs subscriber+ shared desktop.

    Tunnel Protocol

    Deep-dive: desktop icon sync uses publishToUserTunnel on channel file-cabinet:desktop-icons.

    Admin Wiki

    See-also: shared FileTree helpers and JSONB id+data collection pattern.

    Multi-Vendor Store

    Same-workflow: Agent Knowledge Research writes markdown + images into store/product/alt.

    Generative Gallery

    Depends-on: cabinet Image/Video chat reuses GenerativeMediaEditorFsModal with scope cabinet.

    Public gallery

    Curate at /profile/gallery (member+); public items appear on /{username}/img via CDN URLs.

    Storage plane

    Objects live in RingFileBase / MinIO; gallery images can request derivativesProfile: gallery.

    Generative Gallery from cabinet

    Detail-panel Image/Video chat opens the generative fs-modal (scope: cabinet); saves siblings under the source parent.

    Typical scenarios

    1. Vendor media kit — Member uploads PDFs and product photos on /file-cabinet; shares a folder with a trustee (view/download only, immediate grant).
    2. Store Agent Research alt folder — Product Research writes research-{runId}.md and citation-backed images under store/[storename]/[product-slug]/alt (depth ≤3). Vendors open those images in the detail panel → Image chat / Video chat to enhance or enlive, then save a sibling next to the source.
    3. Subscriber collaborator — A subscriber without membership still opens /profile/shared, arranges trusted files on their desktop, and downloads — without owning a personal cabinet.
    4. Public portfolio strip — Owner marks selected images public → visitors open /{username}/img.
    5. Confidential vs shared — Empty trustee list = confidential; Share FsModal shows a live Trustees row (or “confidential”) and Make confidential to revoke all trustees.

    Operator checklist

    • Confirm migration 042_file_cabinet.sql applied (tables file_cabinet_*) and the app image includes File Cabinet UI.
    • Env: NEXT_PUBLIC_STORAGE_PROVIDER=ring_filebase (or equivalent), RINGBASE_API_URL, RINGBASE_PUBLIC_URL, RINGBASE_API_TOKEN — see RingFileBase.
    • Smoke as member: upload on /file-cabinet → Share trustees → second user (subscriber+) sees the item on /profile/shared.
    • Smoke as subscriber (non-member): /file-cabinet shows upgrade gate; /profile/shared still works for shared files; rail shows “Members get their own file manager”.
    • Smoke gallery: add image → set public → open /{username}/img.
    • Do not expect HMAC/TTL signed URLs — public delivery is stable CDN /files/{fileId} today.
    Actions (listOwnCabinetAction, upload, own desktop)
    requireMember()
    Actions (listSharedCabinetAction, shared desktop)requireSubscriber(); scope: 'own' still requires member

    UX shell (verified)

    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.

    PieceRole
    Center paneBreadcrumbs + New folder / Upload (right) + icon workspace (no bordered desktop card)
    Right railTitle → 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 iconsVisible name SSOT in icons[].meta.filename (rename overwrites; no history); image icons use sync_thumb via download ?variant=
    Empty folderDelete control only when the folder has no children
    TrusteesOptions row + Share FsModal (live Trustees / confidential, inline ContactPicker, Make confidential when clearing trustees)
    LoadingFixed-height skeletons for trustees row, info meta, and image preview (no layout jump)
    Shared upgradeSubscriber-only + scope === 'shared' → t('membersUpgrade') CTA → /membership?returnTo=/profile/shared
    Image / Video chatDetail panel (file-cabinet-detail-panel.tsx) on image files → GenerativeMediaEditorFsModal (scope="cabinet")
    Sibling savesaveGeneratedMediaToDesktopAction under source parentId as {base}-enhanced-{ts}.{ext} or {base}-enlive-{ts}.{ext}

    Product research alt path (store Agent Knowledge)

    When vendors run Research on a product, features/store/lib/product-cabinet-media.ts ensures three nested dirs under the vendor owner’s cabinet (conceptual files/ root + MAX_FOLDER_DEPTH = 3):

    store/[storename]/[product-slug]/alt

    Artifacts: research-{runId}.md plus downloaded research-{runId}-N.{ext} images (SSRF-checked HTTP(S) fetch → RingBase → createFileNode). Storefront gallery enablement stays on the product form (Use in gallery) — see Multi-Vendor Store. Pipeline: cabinet.genmedia.sibling_save in scripts/PIPELINES.md.

    Module map

    PathRole
    features/file-cabinet/service.tsserver-only CRUD, ACL (incl. ancestor walk for inherited trustees), desktop, gallery
    features/file-cabinet/acl.tsowner | trustee (legacy editor → trustee)
    features/file-cabinet/constants.tsFILE_CABINET_DESKTOP_CHANNEL, FILE_CABINET_DOWNLOAD_PATH, MAX_FOLDER_DEPTH = 3
    features/file-cabinet/desktop-filename.tsVisible filename helpers
    features/file-cabinet/media-urls.tsSame-origin download URL helpers (?variant=)
    features/file-cabinet/components/*Desktop, tree, options, detail (Image/Video chat), share/rename FsModals, skeletons, gallery, public img
    app/_actions/file-cabinet.tsServer Actions + role gates + saveGeneratedMediaToDesktopAction
    features/store/lib/product-cabinet-media.tsStore research → store/…/alt writer (SSRF-safe)
    app/api/file-cabinet/download/route.tsACL check → byte stream (inline=1, optional variant= for thumbs/webp)
    lib/storage/storage-config.tsgetCabinetStorageConfig() — 25MB + MIME allowlist
    components/file-tree/tree-helpers.tsShared tree helpers (Admin Wiki adapters)
    data/migrations/042_file_cabinet.sqlSchema (+ mirrored in data/schema.sql)

    ACL model

    RoleCapabilities
    ownerFull CRUD, set trustees via ContactPicker (setCabinetTrusteesAction)
    trusteeView / 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.

    Schema (JSONB collections)

    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.

    createDoc id options

    Pass document id as createDoc(collection, data, { id }). Putting id only inside data lets PostgreSQLAdapter generateId() diverge from data.id.

    Storage upload (verified)

    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.

    Desktop tunnel

    saveDesktop publishes to the member’s personal tunnel:

    Client listens via useTunnelChannel in file-cabinet-desktop.tsx.

    Wire-up steps

    1. 1

      Apply migration

      Ensure 042_file_cabinet.sql (and schema.sql parity) on the clone DB. Fresh installs pick up tables from data/schema.sql.

    2. 2

      Confirm storage env

      Reference RingFileBase: NEXT_PUBLIC_STORAGE_PROVIDER=ring_filebase, RINGBASE_API_URL, RINGBASE_PUBLIC_URL, RINGBASE_API_TOKEN.

    3. 3

      Call through Server Actions

      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.

    4. 4

      Public img page

      app/[locale]/[username]/img/page.tsx loads listPublicGalleryByOwner(ownerId) and renders PublicProfileImgGallery. Only visibility=public items appear.

    Routes (constants)

    ConstantPath
    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.

    SubscriptionConductor

    Same-workflow: member gate for /file-cabinet vs subscriber+ shared desktop.

    Tunnel Protocol

    Deep-dive: desktop icon sync uses publishToUserTunnel on channel file-cabinet:desktop-icons.

    Admin Wiki

    See-also: shared FileTree helpers and JSONB id+data collection pattern.

    Multi-Vendor Store

    Same-workflow: Agent Knowledge Research writes markdown + images into store/product/alt.

    Generative Gallery

    Depends-on: cabinet Image/Video chat reuses GenerativeMediaEditorFsModal with scope cabinet.

    1. Docs
    2. /Features
    3. /Ring File Cabinet

    Updated Aug 3, 20268 min listen

    1. Docs
    2. /Features
    3. /Ring File Cabinet

    Updated Aug 3, 20268 min listen

    1. Docs
    2. /Features
    3. /Ring File Cabinet

    Updated Aug 3, 20268 min listen