Files - kubed-io/selenium-flow GitHub Wiki

Files

A workspace gets files three ways: the site downloads one, you make one with screenshot or print, or you keep_file one. A browser opened with open_session(record=true) adds a fourth: its video. They never merge into one list โ€” workspace://files is Files' own listing, and it names three folders beside it, workspace://files/screenshots, workspace://files/recordings and workspace://files/downloads, each with its own listing.

Section Belongs to Survives the browser Cleared
Downloads the browser โ€” the Grid's own store no wholesale, by an operator
Screenshots the workspace, from the moment it is taken yes wholesale, by an operator โ€” or kept out one at a time with keep_file
Recordings the workspace, filed shortly after the browser ends yes wholesale, by an operator โ€” or kept out one at a time with keep_file
Files the workspace, put there on purpose yes one at a time, by an operator

A screenshot or a print is kept from the start โ€” those bytes are this server's, so they are written straight into the workspace's own storage rather than handed to the browser as a download, which Chrome refuses on plain-http pages and on pages with no origin. A print lands directly in Files; a screenshot lands in Screenshots until it is kept or cleared.

Why a download is different

The Grid's file API is list, read-one, delete-all. There is no write and no per-file delete, and every rule about Downloads falls out of that:

  • keep_file copies a download into Files, because the original cannot be moved or removed โ€” it stays on the Grid until the browser ends or an operator clears Downloads.
  • Only Files ever offers a per-file delete, because only Files is a store this server actually owns.
  • Clearing Downloads is therefore safe: anything you kept is somewhere else by definition, which is the whole reason the admin UI can offer that button โ€” see Administration.

keep_file(uri)

Takes the uri an entry already carries โ€” from workspace://files, workspace://files/screenshots or workspace://files/downloads โ€” and:

  • a screenshot's uri: moves it into Files;
  • a download's uri: copies it into Files, leaving the original on the Grid;
  • a Files uri: answers with that file, unchanged.

A name already in Files is never overwritten: the incoming file lands beside it as name (1), name (2), and so on โ€” except keeping a download under a name already in Files, which replaces it, the way a second report.pdf replaces the first one you kept from the same site. screenshots and downloads are themselves reserved names inside Files: a file that would arrive under either one lands as screenshots (1) or downloads (1) instead, because those two path segments already mean the folders.

keep_file is not idempotent โ€” a second call moves or copies again โ€” and there is no tool to undo it. Removing a file, or clearing a whole section, is an operator action in the admin UI; no agent tool clears or deletes anything.

upload_file(file=uri)

Attaches any file this workspace has โ€” a screenshot, a download, or a file already in Files โ€” to a page's file input, addressed the same way you keep one: by its uri. The bytes never pass through you. A kept file can also be attached in a later session โ€” a browser opened after this one ended โ€” which is the main reason to keep one rather than just letting a screenshot sit in Screenshots.

Every address

Read it as URI
a resource workspace://files โ€” Files' own listing, plus a count for each folder
a resource workspace://files/{name} โ€” one file in Files, as bytes
a resource workspace://files/screenshots โ€” the listing
a resource workspace://files/screenshots/{name} โ€” one screenshot, as bytes
a resource workspace://files/downloads โ€” the listing
a resource workspace://files/downloads/{name} โ€” one download, as bytes, while the browser is open

The same three listings and the two item folders are mirrored as JSON over HTTP: GET /files, GET /files/screenshots, GET /files/downloads, and PUT /files/screenshots/{name}/kept or PUT /files/downloads/{name}/kept to keep one. Every call names its workspace: an X-Workspace header, or ?workspace=<name>.

Links

Every entry carries a signed URL that opens in a browser for a while, so a screenshot can be shown to someone rather than described. The signature covers that one path and an expiry; rotating the server's token revokes every link at once. Set PUBLIC_BASE_URL for absolute links โ€” see Deployment.

The three sections are signed over three different routes, because they are keyed by different things: /files/{session_id}/{name} for a download, keyed by the Grid's browser id; /screenshots/{workspace}/{name} and /kept/{workspace}/{name} for Screenshots and Files, keyed by the workspace name that outlives any browser. workspace://files and the admin UI hand these out already signed โ€” nothing needs to construct one.

Screenshots, Recordings and Files need somewhere to live. Set DATA_DIR, the same directory that turns on Flows โ€” each workspace's folders are under DATA_DIR/workspaces/<name>/; without it print is refused and a screenshot comes back with file_error. Downloads need SE_NODE_ENABLE_MANAGED_DOWNLOADS=true on the Grid node instead โ€” see Deployment. Nothing reaps Screenshots, Recordings or Files on its own: they stay until kept, cleared or deleted by an operator.

Recordings

A recording is filed into the workspace's Recordings once the Grid's recorder has finished it โ€” shortly after the browser ends or is reaped. Reading one, by its workspace://files/recordings/<name> uri or after keep_file has moved it into Files, answers its entry, never the video: its signed url plays it, from /recordings/{workspace}/{name}. Recording needs RECORDING_ENABLED=true and the Grid's videos delivered into RECORDING_DIR โ€” see Deployment.


Actions ยท Flows ยท Administration

โš ๏ธ **GitHub.com Fallback** โš ๏ธ