Skip to content

K2GO-376 feat(cx-core): /v1/share gate (two-lifetime, token-scoped) - #694

Merged
luisguzman-adfa merged 4 commits into
mainfrom
feat/K2GO-376-share-gate
Oct 24, 2026
Merged

luisguzman-adfa merged 4 commits into
mainfrom
feat/K2GO-376-share-gate

Conversation

@luisguzman-adfa

Copy link
Copy Markdown
Collaborator

Adds the cx-core /v1/share gate: the shared contract (build-order step 1) for granular wireless
Share. Share is the network twin of export: same bundle, manifest and import path; only the
carrier changes. The receiver PULLS from the sender's live cx-core, so the transfer can close
itself (unlike Clone's mute standalone rsync daemon).

Endpoints:

  • POST /v1/share {items:[{app,localRef}]} -> {sessionId, token, manifestUrl}
  • GET /v1/share/{sessionId}/manifest (token-checked)
  • GET /v1/share/{sessionId}/fetch/{itemRef} (token-checked; 409 while staging)
  • POST /v1/share/{sessionId}/complete (receiver clean-success close)
  • DELETE /v1/share/{sessionId} (cancel, host or receiver)

Design:

  • Two lifetimes: the CONNECTION (per item) reuses the export op's idle TTL + in_use pin; the
    SESSION is durable (token + scoped item set + delivered state) until COMPLETE, CANCEL, or a
    long safety cap (6h), not the short connection idle. In-memory for v1 (disk-persist later).
  • Token is opaque, constant-time compared, carried in the X-Share-Token header (never the URL),
    bound to the session and scoped to the item set (itemRef is an opaque index).
  • A share session reuses the export long-op per item (lazily created child op): one transfer
    owner, single-flight per item, delivered only on a clean close.

Scope: cx-core only, loopback. No app, network, hotspot or pairing (those are step 2). Python
stdlib only. 183 cx-core tests (33 share); independent two-pass review, all findings fixed.

…g-op

Token-gated share session over a scoped item set (POST /v1/share, GET manifest,
GET fetch per item reusing the export op, DELETE). Closes on the first of five
closers; loopback only (network carrier + pairing are later app slices). Core 0.3.0.
…session lifetimes

The durable session no longer expires on the short connection idle; it closes on COMPLETE,
CANCEL, or a long safety cap (the per-item connection TTL stays the export op's). Move the
token to the X-Share-Token header so it never reaches access logs. Single-flight per item.
Count an item delivered only on a clean close (ExportStream.completed); add POST
/v1/share/{id}/complete; drop the implicit drop-based auto-close.
…nt drop

Move the response header writes inside the try whose finally runs on_close, so a client
disconnect during the headers still releases the export op pin and the share single-flight
slot. A stranded slot blocked the safety cap and leaked the durable session (content exposed
past the cap). Also note the manifest delivered flag is an advisory sender-side hint, not
receiver-persisted state.
@luisguzman-adfa
luisguzman-adfa merged commit 89815e0 into main Oct 24, 2026
3 checks passed
@luisguzman-adfa
luisguzman-adfa deleted the feat/K2GO-376-share-gate branch October 24, 2026 23:25
@luisguzman-adfa
luisguzman-adfa restored the feat/K2GO-376-share-gate branch October 25, 2026 13:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant