Commit Graph
7 Commits
Author SHA1 Message Date
nvrl 781301a77b feat(sharing,public-link): update public links, name bookmarks, walk shared trees
- update_public_link sets the role, custom password and expiry of a node's
  public link and keeps its URL (TS updateSharedLink). Create and update
  share the sealing of the share key and SRP verifier.
- list_bookmarks decrypts the bookmarked item's name with the share key the
  stored password unlocks, and returns the custom password in the new
  Bookmark::custom_password. The URL fragment is now only the generated
  password.
- ProtonDrivePublicLinkClient::enumerate_subtree walks a shared folder
  breadth first, several folders of a level at a time.
- Add CHANGELOG.md, update the README feature table for this and the
  previous unreleased commits, and record the TS ports in UPSTREAM_SYNC.
2026-10-25 21:27:05 +01:00
nvrl 1477fe85d5 fix(drive): give each share root its own parent key in batch enumeration
enumerate_nodes and enumerate_nodes_light cached parent keys per batch by
the link's parent id. Every parentless link in a volume landed on None, so
when several share roots were enumerated together, the first root's share
key was used for the rest and they were dropped with "missing key".

Name a parent key by where it comes from: Parent(folder) for a link with a
parent, Root(link) for a parentless one. The batch cache and the
parent-key single-flight now both use that identity. The single-flight
previously keyed a root and its children on the same link id, although a
root resolves to its share key and its children to its node key, so two
concurrent cold loads could hand one of them the wrong key.

Fixes #2
2026-10-01 18:06:58 +02:00
nvrl e378db6ec8 implemented enumeration for drive 2026-08-10 14:10:43 +02:00
nvrl 4fe7f02ebb version 0.4.0 2026-08-03 00:18:39 +02:00
nvrl 9dd535b374 improved performance, concurrent upload, version 0.2.0 2026-07-24 20:29:15 +02:00
nvrl 24a99e6b9a public link consume, revision history, path helpers
Public links (public_link.rs, ported from the TS SDK — the C# SDK has no
equivalent): ProtonDrivePublicLinkClient lets a visitor with no Proton
account open someone else's share link. `info` reads pre-auth metadata,
`open` runs the SRP handshake against drive/urls/{token}/info + /auth and
unlocks the share key (bcrypt SharePasswordSalt -> key password -> the
SKESK'd SharePassphrase -> ShareKey). The read surface then reuses the
ordinary link/children/revision endpoints. Signature verification is
deliberately absent: an anonymous visitor cannot read core/v4/keys/all,
matching the TS SDK. Supporting primitives: http::get_unauthenticated and
crypto::decrypt_armored_with_password.

Revision history: enumerate_revisions / get_revision / restore_revision /
delete_revision, plus open_revision_at / download_revision{,_to} to read a
specific revision. Drafts are filtered on the wire value, since
RevisionState::from_raw maps 0 to Active. Three server behaviors found
live and worked around: ?NoBlockUrls=true still emits Blocks with null
BareURL, so get_revision deserializes into a DTO without that field; the
restore POST needs an empty object body, not null; and restore is async
(HTTP 202, non-1000 envelope) so the new active revision is not live on
return.

Path and hierarchy helpers: get_node_hierarchy, get_node_path,
get_node_by_path, create_folder_path. Names are encrypted and there is no
name-query endpoint, so lookup walks and decrypts one directory level per
segment.

Fix a silent-corruption path in block-size resolution. RevisionReader
accumulates block sizes to derive where each block starts in the
plaintext, so a vector that overstates any block but the last shifts every
block after it and the reader splices at the wrong offsets — full-length
reads of the wrong bytes, no error raised. resolve_block_sizes previously
guessed all-full blocks when both Common.BlockSizes and Common.Size were
unusable. It now errors for multi-block files and only assumes a full
block when there is exactly one (which cannot be misaligned). Regression
test in revision.rs::padded_block_sizes_shift_later_blocks.

Recover from stale upload drafts. An upload interrupted after the draft
node was created but before it was sealed leaves an unsealed draft, and
every later attempt at that name returns 422 AlreadyExists forever. Draft
creation now deletes the conflicting node and retries when the conflict is
an unsealed draft; by default only our own client's, with
upload_file_replacing_draft_from opting into any client's to recover
across a daemon restart (which rotates our client uid). A committed file
of that name is never touched.

Live tests for the public-link round trip, custom-password links, revision
history, and the path helpers.
2026-07-19 13:17:30 +02:00
nvrl 64f977edb3 feature (devices+sharing) + upgraded rand and aeds 2026-07-15 19:34:40 +02:00