mirror of
https://github.com/storytold/figcraft.git
synced 2026-10-24 10:27:00 -06:00
M9: online files: the app remembers the files it put online
A file put on a server without the server's key stays its owner's after its tab closes or the app quits. The app records it with the preferences (server, id, name, owner token, the owner's links, what others join with; at most 200; validated when read back) and never shows the token: not in command results, ui.inspect, logs or debug output. - Home > Online lists your online files: open one as its owner (a new tab, or its tab comes to the front), start and stop sharing, copy the code or link, rename on the server, remove from the server (confirmed), forget here. One request per server when the section opens; offline and gone states. - collab.files, collab.openFile, collab.forgetFile; collab.manageFile takes its server and token from the record and gains share / unshare. - Server: Admin owned (a compatible addition within protocol version 2) says what became of the files a list of owner tokens owns. Older servers leave the list as recorded. - Tabs mark files in a live session (shared, or open only to you); toasts about a file that isn't in front name it; after a crash a recorded file reopens from its server as its owner. - Draft catalogs (de, fr, ja, ko, pt-BR, zh-Hans) translate the 71 strings and 5 command labels they lacked and the new ones; es and es-419 follow. - Docs: collab-protocol, server, mcp, control-protocol, parity pages, gaps, ROADMAP.
This commit is contained in:
+59
-6
@@ -64,9 +64,11 @@ people you trust.
|
||||
On a server [open to the public](#running-a-public-server) the address alone is enough
|
||||
(`wss://figcraft.example.com/`): the dialog asks the server first and shows that no key is needed,
|
||||
who runs it ("Hosted by …" and a link to its terms) and how long unopened files are kept. Publishing
|
||||
then also gives an **owner token**, shown once with the links in a **File published** window: copy
|
||||
it and keep it, it is the only way to revoke the links, rename the file or remove it later
|
||||
(`collab.manageFile` from [MCP](mcp.md#live-sessions)). The Share popover shows the server's line
|
||||
then also gives an **owner token**, shown once with the links in a **File published** window. The
|
||||
app keeps it with your preferences and lists the file under [Home ▸ Online](#your-online-files),
|
||||
where it can be opened, shared, renamed and removed later without the token in hand; copy it if
|
||||
you want to manage the file from another computer or a script (`collab.manageFile` from
|
||||
[MCP](mcp.md#live-sessions)). The Share popover shows the server's line
|
||||
and the date the server deletes the file unless someone opens it.
|
||||
|
||||
## Sharing with a join code
|
||||
@@ -86,7 +88,8 @@ working at once, whoever joined with them is disconnected ("Sharing was stopped
|
||||
copy they have), and the owner stays in the file, which stays on the server, open only to them.
|
||||
**Start sharing** again gives the same file new links and codes. **Share ▸ Advanced ▸ Remove from
|
||||
server…** (it asks first) takes the file off the server; closing the tab or quitting changes
|
||||
nothing on the server. To use **your** server for this, set its address
|
||||
nothing on the server, and the file is still yours afterwards: see
|
||||
[Your online files](#your-online-files). To use **your** server for this, set its address
|
||||
(`wss://figcraft.example.com/`) in Preferences on every machine that shares or joins; a server
|
||||
that needs its key is reached under **Advanced ▸ Publish to another server…**, or with
|
||||
`collab.share {server: "wss://…/?key=…"}`, and gets codes too.
|
||||
@@ -112,6 +115,54 @@ that needs its key is reached under **Advanced ▸ Publish to another server…*
|
||||
no migration, existing files get codes the next time they are shared, and no setting turns codes
|
||||
on or off. Behind the reverse proxy nothing changes (codes travel inside the WebSocket).
|
||||
|
||||
## Your online files
|
||||
|
||||
A file you put on a server without its key is yours, and stays where it is when its tab closes or
|
||||
the app quits. The app remembers each one **with your preferences on this computer** (never in the
|
||||
document): the server, the file's id and name, its owner token, your own links to it, when you put
|
||||
it there and last opened it, and the code and links others join with while it is shared. The home
|
||||
screen lists them under **Online**:
|
||||
|
||||
- **A row** shows the file's name, the server, **Shared** or **Not shared**, and when you last
|
||||
opened it. Clicking it opens the file as its owner, in step with the server, in a tab of its
|
||||
own (or brings its tab to the front when it is open already). In that tab **Stop sharing** and
|
||||
**Start sharing** work as in the session that first shared it.
|
||||
- **Its menu** (the button at the row's end): **Open**; **Stop sharing** / **Start sharing**
|
||||
(others lose their links and codes, or get new ones; the file itself stays); **Copy code** and
|
||||
**Copy link** while it is shared; **Rename on the server…**; **Remove from server…** (it asks
|
||||
first: the file is deleted there for everyone and can't be brought back); **Forget on this
|
||||
computer** (the row goes, **the file stays on the server** until it expires, and without its
|
||||
token this computer can't manage it again).
|
||||
- **Nothing is asked of a server until you open Online** (or act on a file). Then each server is
|
||||
asked once, in the background, what became of your files there. A file the server no longer has
|
||||
(removed, or expired unopened) reads **No longer on the server** and can be cleared from the
|
||||
list. A server that can't be reached says so above the list, with **Try again**; the rows still
|
||||
show what this computer remembers.
|
||||
- **Tabs** of files in a live session carry a small mark after the name: waves for a session
|
||||
others get into (a file you share or joined), a closed ring for a file of yours on a server that
|
||||
only you get into now. Messages about a file that isn't in front name it ("Ada joined
|
||||
Homepage").
|
||||
- **After a crash**, a file of yours that was open and in step with its server opens again from
|
||||
the server as its owner, rather than as an unsaved recovery copy.
|
||||
|
||||
The owner token is a password for that one file: it is kept only in the preferences file of your
|
||||
user account (`state.json` in FigCraft's settings folder), is never logged, and never appears in
|
||||
what commands return (`collab.files` says `hasOwnerToken: true`). Whoever can read that file can
|
||||
manage your online files; a list of at most 200 files is kept (the one opened longest ago makes
|
||||
room). The files are the ones published **from this computer**: another computer of yours doesn't
|
||||
know them unless you manage them there with the token. A file published with the server's key has
|
||||
no owner token and belongs to the server's operator: it isn't listed.
|
||||
|
||||
Scripts and agents use `collab.files {refresh?}`, `collab.openFile {file}`,
|
||||
`collab.forgetFile {file}` and `collab.manageFile {file, action}` ([MCP](mcp.md#live-sessions)).
|
||||
|
||||
- **Upgrade note.** Asking what became of the files needs a server of this version or newer. An
|
||||
older server still works for everything else: the list shows what the computer remembers, says
|
||||
that the server can't tell what became of the files, and opening, sharing, renaming and removing
|
||||
go on as before (they use requests the server already knows). To get the state of the files,
|
||||
upgrade the server binary and restart it: the data directory needs no migration and there is no
|
||||
setting to turn on.
|
||||
|
||||
## Joining
|
||||
|
||||
A [join code](#sharing-with-a-join-code) is the short way in. Share links look like the desktop
|
||||
@@ -350,7 +401,9 @@ keeps the key for everything else.
|
||||
runs it (`operator_contact`), its terms (`terms_url`) and how long unopened files are kept. A file
|
||||
published without the key gets its edit and view links and an **owner token** (128 random bits,
|
||||
shown once, kept only as its SHA-256): with it, whoever published the file lists, makes and
|
||||
revokes its links, renames it on the server or removes it (`collab.manageFile`), and nothing else.
|
||||
revokes its links, renames it on the server or removes it (`collab.manageFile`), asks whether
|
||||
it is still there (what the app's [Online list](#your-online-files) does, for all its files in
|
||||
one request), and nothing else.
|
||||
An app older than open hosting is told the server is open when it tries a key.
|
||||
- **Limits per address** (only when open): connections at once (`max_connections_per_ip`), new
|
||||
connections a minute (`connects_per_minute`), files published an hour (`publishes_per_hour`),
|
||||
@@ -402,7 +455,7 @@ What someone can do, by what they hold (the server is reached through TLS at the
|
||||
| Someone with a **join code** | Exactly what its link gives (a view code: the view link's row; an edit code: the edit link's), until the code or its link is gone | Get a code for any other link; learn anything from a wrong code but that it is wrong |
|
||||
| Someone with a file's **view link** | See that file and everyone's changes and presence in it; read its team library and usage; report it | Change it (the server refuses a viewer's edits); reach any other file; manage links |
|
||||
| Someone with a file's **edit link** | Change that file, within its size cap; publish its team library (on a public server only for files published with the key); report it | Reach any other file; grow it past `max_file_mb` or its publisher's share; list, make or revoke links; rename or remove it |
|
||||
| Whoever holds a file's **owner token** (published without the key) | List, make and revoke that file's links (disconnecting whoever joined with a revoked one, which is how the app stops sharing), ask for join codes for links whose token they hold, rename it on the server, remove it | Touch any other file, even with its id; list files; read reports; block; anything of the plugin directory |
|
||||
| Whoever holds a file's **owner token** (published without the key) | List, make and revoke that file's links (disconnecting whoever joined with a revoked one, which is how the app stops sharing), ask for join codes for links whose token they hold, rename it on the server, remove it; ask whether it is still there, its name, link ids and expiry (asking doesn't count as opening it) | Touch any other file, even with its id; tell a file that doesn't exist from one they don't own; list files; read reports; block; anything of the plugin directory |
|
||||
| The **operator** (server key, or the machine) | Everything above for every file, reports, blocks, the plugin directory; read every file on disk | Recover a lost link or owner token (only hashes are kept) |
|
||||
|
||||
Limits that hold against everyone: message sizes by what a connection is for, file sizes as they
|
||||
|
||||
Reference in New Issue
Block a user