Release govoplan-files v0.1.26: speed archive workflows and unify file tools
Module Package Release / publish-packages (push) Successful in 12s

This commit is contained in:
2026-09-08 01:32:41 +02:00
parent 2baa8f2657
commit ff84812f7f
35 changed files with 4331 additions and 275 deletions
+116 -4
View File
@@ -14,6 +14,19 @@ a document collaboration engine, or a records-management system.
## Choose a reading path
The Files workspace keeps **Reload → Create folder → Upload** at the top right;
Upload is the primary everyday action. Reload re-reads the current folder with
its active pattern/property filters and retains usable loaded content on failure.
For connector spaces it only browses the current remote folder: it never imports
or synchronizes content. **Connections and imports** groups explicit import,
synchronization, and linked-space management. Opening this chooser makes no
remote changes. Select content to use the local **Download**, applicable
**Unpack archive**, or **Manage selection** actions. The latter groups move,
copy, rename, sharing, and access explanations, with deletion in a separate
section and its existing confirmation. All permissions, connector restrictions,
conflict checks, retention rules, keyboard shortcuts, and context menus remain
in force; unavailable actions explain their blockers.
| If you need to... | Start with... |
| --- | --- |
| Upload, find, organize, download, or import a file | [User tasks](#user-tasks) |
@@ -144,6 +157,15 @@ updates currently belong to connector sync.
### Preview and unpack archives
The dialog uses the shared blurred loading overlay, without an envelope
animation. Its status distinguishes transfer, inspection, extraction/storage,
and transaction finalization. Selected file counts and byte totals are known
from the preview; running extraction displays actual server counters. Unknown
progress is indeterminate, and all bytes processed does not mean the transaction
has committed. Closing, changing the destination, and editing the selection are
disabled while work runs. Errors release the overlay and keep the selection
available for review; no automatic import retry is performed.
The UI previews ZIP, TAR, TAR.GZ, TAR.BZ2, and TAR.XZ before writing managed
files. Users may select individual files or complete folders. The request is
spooled to a bounded temporary file rather than buffered wholly in memory. The
@@ -161,10 +183,43 @@ defaults are:
rejected;
- actual bytes read are counted, not only archive header declarations.
The browser retains the selected archive and password until confirmation.
Confirmation reuploads the archive, verifies the token and digest, repeats all
safety checks, and commits only the selected files. No preview archive or
password is retained server-side.
The UI requests private temporary staging and uploads the archive once. Password
verification, renewed preview requests and confirmation reuse that same copy;
the password remains request-only and is never stored with it. Confirmation
rechecks the actor/destination-bound preview token, digest and safety limits and
commits only selected files. Repreviewing does not extend the initial staged
copy's lifetime. Cancelling or replacing the archive requests its release;
successful confirmation removes it. An expired or missing copy requires a fresh
upload; when requesting another preview, the UI can safely repeat that preview
with the original selected file. It never retries confirmation automatically.
API clients that do not opt into `retain_upload`
retain the original request-only preview/confirmation upload contract.
For an archive that is **already uploaded**, select exactly one managed archive
and choose **Unpack archive** in the action bar or context menu. Select an
accessible destination space and folder, then choose **Preview archive**. The
same entry selection, folder selection, password verification and confirmation
dialog applies. Bytes stay on the server; no browser download/re-upload is
needed. This path resolves verified source bytes within the configured archive
size limit before passing them into the ordinary bounded extraction pipeline.
Managed extraction requires `files:file:read`, `files:file:download` and
`files:file:upload`, current source ownership/share access, and destination-owner
access. Both stages enforce source tenant, deletion/version checks, integrity,
quarantine, envelope decryption availability and effective source/destination
connector restrictions. The token additionally binds the exact managed file and
version. A changed version, revoked share, expired token or changed destination
requires a fresh preview. No existing destination file is overwritten, including
the source archive; choose another destination if a member collides. Failed
extraction rolls back newly created managed assets through the existing upload
transaction/recovery path. The source file, bytes and version are not modified.
New members use ordinary archive-upload destination defaults: neither ZIP
password protection nor a source storage encryption envelope is automatically
copied to extracted files. The resulting provenance records source file/version
lineage without passwords. Keep the busy dialog open until the synchronous
operation completes; this is not a resumable background job. Remote entries in
connector spaces must first be synchronized into managed storage.
### Organize files and folders
@@ -565,6 +620,9 @@ before it can return a usable client or session.
| `FILE_ARCHIVE_MAX_EXPANDED_BYTES` | 2 GiB | Maximum expanded archive bytes |
| `FILE_ARCHIVE_MAX_EXPANSION_RATIO` | 100 | Maximum expanded-to-compressed ratio |
| `FILE_ARCHIVE_PREVIEW_TTL_SECONDS` | 1,800 | Lifetime of the sealed archive preview token |
| `FILE_ARCHIVE_WORK_ROOT` | private OS-temporary directory | Shared transient archive/progress workspace; distinct from durable blob storage |
| `FILE_ARCHIVE_STAGED_MAX_BYTES` | 2 GiB | Total staged archive bytes admitted per work root |
| `FILE_ARCHIVE_STAGED_PER_ACTOR` | 4 | Maximum staged archives per tenant/user; oldest inactive stages may be evicted |
| `MASTER_KEY_B64` | development fallback only | Encrypts database-managed connector secrets |
The local backend is the operational baseline. It resolves every storage key
@@ -586,6 +644,59 @@ durable shared mount only for same-host replicas. Independent hosts require the
`shared` profile with external S3, PostgreSQL, Redis, a stable installation id,
and one immutable module composition.
### Archive staging, progress and performance
Archive preview staging is optional in the API and requested by the UI. It is
not durable managed storage or a background job queue. The default work root
is below the OS temporary directory, isolated by the service uid and a hash of
the configured local storage root. `FILE_ARCHIVE_WORK_ROOT` selects an explicit
root. The internal directory must have mode `0700`; archive, lease and progress
files use `0600`. Passwords are never retained. Progress records contain only
status and file/byte counters, not member names or content.
All same-host API workers must see the same work directory, including across
container mounts. For multiple hosts, provide shared POSIX storage with working
`flock` locks, or route an archive's preview, confirmation and progress requests
to the same host. Shared S3 blob storage alone does not share this transient
workspace. Include upload limits, temporary disk capacity and sufficiently long
proxy/request timeouts in deployment checks; confirmation remains synchronous.
The defaults permit 2 GiB of staged data per work root and four stages per
tenant/user. A new stage can evict the actor's oldest inactive copy; active
imports are never evicted to admit another one. Staging expires after the
configured preview TTL (1,800 seconds by default), measured from initial
staging and not renewed by password repreview. Cancel/replacement requests and
successful import remove copies; expiry cleanup is opportunistic during later
archive work, so an abandoned file is not guaranteed to disappear at its exact
idle deadline. Active POSIX leases protect copies in use beyond TTL until the
operation releases them; a crashed worker releases its OS lock. Do not delete
active work directories as a cleanup shortcut.
For classic ZIPCrypto archives, an optional maintained system `libarchive`
library accelerates decoding through its public read API. It applies only to
stored/Deflate ZIP entries with ASCII or UTF-8-flagged names; AES, unsupported
formats/encodings and a missing library use the existing Python reader chosen
before decoding. Native corruption/password errors never trigger a fallback.
Install/update the library through the deployment's supported package process
and restart workers after installation. Both paths retain complete header and
path validation, selection and actual output limits; the native path also
independently checks size and CRC and never extracts to filesystem paths.
Verified members are read and stored one at a time, avoiding a whole expanded
archive in memory. Storage-client reuse is confined to one archive operation;
authorization, tenant isolation and policy are not cached. Batched response
metadata avoids repeated lookups, while every member still follows the durable
recovery ledger, fencing, integrity and post-commit verification path. The
optional decoder's speedup does not imply an equal end-to-end or S3 speedup.
Use `tests/benchmark_archive_storage.py` for isolated synthetic SQLite/local
storage and decoder measurements; it is not a production PostgreSQL/S3 benchmark.
Transfer, inspection, extraction/storage and finalization remain separate
phases. File and byte counters report actual work; an unknown amount remains
indeterminate. Reading all bytes is not transaction success: the UI waits for
confirmation and commit settlement. Failed or unavailable progress reporting
does not automatically retry an import or prove it failed.
### Connector egress
Connector access to private networks is a deployment-wide decision:
@@ -834,6 +945,7 @@ All routes below are under `/api/v1/files`.
| --- | --- |
| Spaces and content | `GET /spaces`, `GET /`, `GET /folders`, `GET /delta` |
| Upload and folders | `POST /upload`, `POST /upload-zip` (compatibility), `POST /archive-preview`, `POST /archive-confirm`, `POST /folders`, `POST /folders/delete` |
| Existing managed archive extraction | `POST /{file_id}/archive-preview`, `POST /{file_id}/archive-confirm` (JSON source version, destination, request-only password, preview token and selected paths; read/download/upload permissions) |
| File access | `GET /{file_id}`, `GET /{file_id}/download`, `DELETE /{file_id}`, `POST /bulk-delete` |
| Organization | `POST /bulk-rename`, `POST /transfer`, `POST /archive.zip`, `POST /resolve-patterns` |
| Sharing | `POST /{file_id}/shares`, `POST /bulk-shares` |
+6 -2
View File
@@ -9,7 +9,7 @@ and consequences described here.
| Surface | Primary task | Archetype | Consequence | Pattern evidence |
| --- | --- | --- | --- | --- |
| `/files` space and folder panes | Browse managed and connected content without losing location | Directory/explorer | Low for navigation; medium for exposing filenames and provenance | Full-height two-pane workspace, bounded panes, stable selection and contextual Help Center link |
| `/files` toolbar and property filters | Find and act on the current selection | Explorer actions and local filtering | Medium for upload, move, copy, share and synchronization; high for delete | Actions remain beside the affected list, disabled controls explain permission/state/selection blockers, destructive work uses `ConfirmDialog` |
| `/files` workspace header and selection toolbar | Find content and act at the appropriate scope | Persistent workspace actions plus local selection tools | Medium for upload, move, copy, share and synchronization; high for delete | Reload → Create folder → primary Upload stay above both panes; Connections and imports groups secondary workspace tools; Download, eligible Unpack archive and Manage selection stay list-local; deletion is separated and uses `ConfirmDialog` |
| Upload/archive, transfer, rename and connector-import dialogs | Supply and review one bounded change | Adaptive create/edit or guided import | Medium to high because files, paths and external bytes change | Shared `Dialog`, `FileDropZone`, validation, conflict review, unsaved inputs and explicit confirmation |
| File share dialog | Inspect and change access | Review/decision | High because another actor gains access | Shared dialog, access explanation, stable row actions and destructive confirmation |
| System/tenant/group/user connector surfaces | Compare connections, credentials and effective policy | Administration/configuration | High because endpoints, secrets and inherited policy control external access | Shared `ConnectionTree`, adaptive forms, `ActionBlockerHint`, policy provenance and contextual admin help |
@@ -22,6 +22,11 @@ and consequences described here.
- Loading, errors, success, empty results, access explanations and confirmation
use Core components. Files does not reproduce the application shell.
- Explicit Reload bypasses the client read cache for the current folder and all
active filter pages, never imports/synchronizes content, and keeps usable data
on failure. Late responses cannot replace a changed tenant, account or folder.
- Selection and connection tools use domain-labelled shared dialogs and form
sections; opening a tool chooser does not itself perform a remote operation.
- A connector that comes from deployment settings remains visible but read-only;
its action explains that bootstrap configuration and a restart are required.
- Missing permission, target, selection, endpoint, or compatible provider is an
@@ -52,4 +57,3 @@ The focused structural test guards these contracts, optional-module boundaries,
confirmation, contextual help, advanced-only JSON and responsive rules. Core's
TypeScript build, structural localization audit, module-permutation suite and
full-product bundle check provide the integration gates.