Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • docs/shaer-c2s-api.md

    r30871c1 rf889429  
    8080| `GET /ap/users/:slug/outbox` | OrderedCollection of the account's own `Create(Note)` |
    8181| `GET /ap/users/:slug/inbox` | OrderedCollection of recent inbound posts (accounts you follow) as `Create(Note)`. Owner only; `403` for anyone else. The unified home feed is outbox + inbox merged. |
     82
     83### Waiting for news on the inbox read
     84
     85The inbox read can hold the answer until there is something new, so a client does
     86not have to poll. It is the **same call and the same response** — no separate
     87endpoint and no separate "there is news" shape, because a second shape is a
     88second description of a post that can drift from the first.
     89
     90```
     91GET /ap/users/:slug/inbox?since=<cursor>&wait=25
     92```
     93
     94- `since` is the `shaer:cursor` from your previous answer. Treat it as opaque.
     95- `wait` is seconds, capped at 50 — well under what a proxy will hold.
     96- Send neither and the route behaves exactly as it always did.
     97
     98Two possible answers:
     99
     100| | |
     101|---|---|
     102| **`200`** | something changed. The full, current collection with a fresh `shaer:cursor`. |
     103| **`304`** | nothing changed within `wait`. **No body.** Keep the cursor you have and ask again. |
     104
     105`304` is not an error — it is the normal answer to a quiet minute, and it is why
     106this costs nothing while nothing happens. Sending the whole timeline back every
     107`wait` seconds just to say "still nothing" would be a poor trade for saving one
     108round trip.
     109
     110A server that has not run the feed-state migration yet cannot tell change from
     111stillness, and answers `200` with the collection every time rather than `304`
     112forever. Slower, never wrong.
     113
     114The cursor moves for **all four** sources this read merges: the timeline,
     115messages, replies on your own posts, and your own sent notes.
     116
     117Limits worth knowing as a client author:
     118
     119- four waiting connections per account. A fifth gets the current state
     120  immediately rather than an error, so a broken reconnect loop degrades to
     121  ordinary polling instead of locking the account out.
     122- hanging up ends the wait; there is no cost to abandoning a request.
     123- the bearer is checked *before* any waiting, so an unauthenticated caller can
     124  never hold a connection open.
     125
     126This works while your app is in the foreground, and only there. iOS freezes
     127network activity the moment an app is backgrounded, and a held-open connection
     128does not survive it.
     129
     130**There is no background channel to fall back on for a native app.** Klonkt's
     131web push uses VAPID, which a self-hosted instance can generate and send entirely
     132on its own — but only to a browser or an installed PWA. A native app receives
     133push through APNs (or FCM), signed with the *application's* key, which a
     134self-hosted Klonkt does not have and should not have: whoever holds it can push
     135to every user of that app. Closing that gap needs a relay run by the app's
     136publisher, and that is a decision about money and control, not a protocol
     137detail.
     138
     139So for a self-hosted setup this is not a stopgap until push arrives. For now it
     140is the freshness channel.
    82141| `GET /ap/users/:slug/followers` | see below |
    83142| `GET /ap/users/:slug/following` | see below |
Note: See TracChangeset for help on using the changeset viewer.