Guide

What `recent_uploads.status` means

The pending → claimed → expired / oversize state machine on every upload link. Sourced from R2 events, not the client.

5/18/2026 · connect0 · 3 min

Every file connecting into the core moves through a small state machine — this is how you (and the agent) know it actually landed.

Every upload.create_link and upload.write call writes a row to upload_link. That row has a derived status field, surfaced through info's recent_uploads and the dashboard's project pages. The state machine is small but worth understanding because it's how you (and the agent) answer "did the upload work?"

The four states

StatusMeaning
pendingLink issued, R2 hasn't reported a PUT yet. Either the user hasn't uploaded, or the upload landed within the last few seconds and the event hasn't propagated through the queue.
claimedR2 fired an event saying bytes landed at the target key. This is the only signal that flips the row to claimed — a hostile client can't fake it.
expiredThe link's expires_at passed and no claim ever arrived. The audit row stays around for forensics; the URL itself stopped working.
oversizeR2 reported more bytes than the link's content_length declared. The bytes are in R2 (we don't reject after-the-fact), but the row is flagged for an operator to investigate.

Why claim is R2-driven, not client-driven

The browser-helper page sees a successful PUT and could just call back to the server saying "done." We don't trust that signal — a buggy or malicious client can lie. Instead, R2 publishes an event-notification to a Cloudflare Queue, an internal Worker reads it, and that Worker POSTs to apps/api with an HMAC-signed payload. The audit ledger reflects what Cloudflare actually saw.

Side effect: there's a delay between "PUT succeeded" and "row flips to claimed." Typically a few seconds; occasionally longer when Cloudflare's event pipeline is heavy. The UI shows "uploaded — confirming with R2" during that window.

How the agent should use it

After an upload-link issuance, the right "did it work?" loop is:

  1. info with {account_slug, project_slug} set.
  2. Find the link in current_project.recent_uploads (the most recent matching target_path).
  3. If status === "claimed", proceed.
  4. If status === "pending" and the link issuance was < ~30s ago, wait + retry.
  5. If status === "pending" and > 60s ago, the upload probably didn't happen. Ask the user.
  6. If status === "oversize", the file is on disk but it's bigger than declared — usually a clue that the agent passed content_length wrong.

On the dashboard

/a/<account>/projects/<project>/upload has a "Recent uploads" card with the same data plus colour-coded badges. oversize is destructive-tinted because it's the one status that wants human eyes.

Reading the bytes_received column

When status === "claimed", bytes_received is what R2 reported. Compare to content_length (what the agent declared) to spot drift. They should match exactly for the upload.create_link path with content_length set; differ for the no-content-length variant or for upload.write (where the agent computes the bytes itself).

Next steps

Where this fits

This is the Connect everything pillar of connect0 — the core that connects everything your company runs on. The status ledger is how the core proves a file really connected in — sourced from R2, not the client. Start building → · All guides →