tinyrelayfile
tinyrelay/docs/extensions/tinyclient-read-adapter.md/

docs/extensions/tinyclient-read-adapter.md raw
1# Tinyclient read adapter
2
3| Field | Value |
4| --- | --- |
5| Identifier | `tinyclient-read-adapter` |
6| Status | Experimental |
7| Contract revision | 1, tied to this repository revision; no version negotiation |
8| Owner | `tinyclient` defines the presentation contract; the tinyrelay backend owns data and authorization. |
9| Transport | HTTP GET, JSON success bodies, plain-text error bodies. |
10| Endpoint | `/api/tinyclient`, under the selected tenant prefix when present. |
11
12This project extension supports a separately running frontend. It is not a Nostr NIP, a general relay query protocol or a replacement for signed mutation APIs. Run compatible frontend and backend revisions together. No event kinds, tags or signing formats are introduced.
13
14## Authentication and scope
15
16The backend resolves the caller using its normal actor resolver. A public-key query parameter or header is not authentication. The standalone frontend forwards the browser session cookie when loading the presentation snapshot. For method and typed reads, an empty requested actor means anonymous access: the frontend omits the cookie even if the browser is signed in. A nonempty requested actor must match the actor authenticated in that request's snapshot; a mismatch fails before contacting the backend. Every backend query and typed read still resolves authentication and applies its own access checks.
17
18Keep the frontend's public origin and tenant path the same as the backend's configured public URL. The private backend address may differ. Existing NIP-98 proofs remain bound to their original URL, method and payload; the frontend proxies signed requests without translating or replaying them as adapter reads. Signed HTML requests use the integrated renderer.
19
20Responses carry `Cache-Control: private, no-store`. The frontend must not cache private snapshots for use after an authorization or backend failure. It refuses an unexpected public Host and does not follow redirects when fetching read-adapter responses.
21
22## Request forms
23
24All forms use GET. If `op` is nonempty it selects a typed read before `method` is considered.
25
26### Presentation snapshot
27
28With no `op` or `method`, the response is a JSON object with:
29
30- `policy`: Presentation policy, using the public `Policy` structure.
31- `url`, `slug`, `identity`: Relay presentation identity.
32- `actor`: Public key resolved by the backend, or an empty string for an anonymous caller.
33- `version`, `revision`: Backend build metadata.
34- `rooms`, `activity`: Whether the backend provides the corresponding optional typed interfaces.
35- `share_presence`: The authenticated caller's presence preference.
36- `views`: Optional custom-view presentation definitions.
37- `read_error`: Optional private-access failure used to render a restricted page.
38
39Nonowners receive a reduced policy without owner-only operational settings. A caller barred from private relay reads receives a masked presentation snapshot with `read_error`, rather than private relay identity or configuration. The snapshot does not grant permission to perform later reads.
40
41The authoritative field definitions are [`remoteSnapshot`](../../tinyclient/remote.go), [`Policy`](../../tinyclient/contracts.go) and their referenced public types. Readers should tolerate additional object fields. Changes to existing field meanings require a contract revision and compatibility review.
42
43### Method reads
44
45Supply `method=<name>` and optional `params=<JSON-array>`. Method names must appear in the read-only allowlist in [`remoteReadMethods`](../../tinyclient/remote.go). The adapter passes the decoded parameters and authenticated actor to `Backend.Query` and returns its JSON result directly, without a JSON-RPC envelope.
46
47Methods cover presentation reads such as repository browsing, wiki, rooms, social content, approvals and management lists. The allowlist does not override method authorization. Mutations are never dispatched through this contract. Method parameter and result semantics remain those of the corresponding backend read operation; this revision is coupled to the repository's backend contracts rather than a standalone third-party API.
48
49### Typed reads
50
51| `op` | Parameters | Backend contract |
52| --- | --- | --- |
53| `rooms` | `cursor`, `limit` | `RoomsReader.ListRooms` |
54| `room` | `room`, `cursor`, `limit` | `RoomsReader.ReadRoom` |
55| `thread` | `room`, `root`, `cursor`, `limit` | `RoomsReader.ReadThread` |
56| `activity` | `room`, `root` | `ChatActivityReader.ReadChatActivity` |
57
58Results use the typed interfaces in [`read_contracts.go`](../../tinyclient/read_contracts.go) and [`chat-activity.go`](../../tinyclient/chat-activity.go). The backend owns room access, cursor validation and limit bounds. The current adapter converts an absent or unparseable limit to zero; callers should send a valid decimal limit rather than rely on that fallback.
59
60## Errors
61
62| Status | Meaning |
63| --- | --- |
64| 200 | A successful JSON read, including a deliberately masked private snapshot. |
65| 400 | A method outside the allowlist or malformed JSON method parameters. |
66| 401 | The actor resolver rejected authentication. |
67| 403 | Private access or a backend operation was refused; also used for an unsupported typed `op`. |
68| 405 | Non-GET method; response includes `Allow: GET`. |
69| 501 | Requested typed interface is unavailable. |
70
71Do not parse plain-text errors as stable machine identifiers. These statuses describe the current binding, not a universal error model for the project. The standalone frontend returns 502 if it cannot load a valid snapshot, rather than rendering stale private data.
72
73## Discovery and compatibility
74
75The endpoint is configured as part of a compatible tinyrelay deployment; it is not advertised as a NIP capability. `rooms` and `activity` describe optional read interfaces, not full protocol compliance. Clients that do not use the adapter continue using the integrated website and existing relay interfaces.
76
77The adapter does not migrate sessions across origins, accept another tenant path, own a database or hold a relay signing key. Each standalone frontend process serves one tenant. A root-mounted frontend returns 404 for reserved `/r/<name>` paths before rendering or forwarding any request, including signed requests and WebSocket upgrades. A prefixed frontend accepts only its configured tenant path. Unknown method names fail closed; adding a method requires an authorization review and tests before it enters the allowlist.
78
79## Verification
80
81The contract is exercised by [`remote_auth_test.go`](../../tinyclient/remote_auth_test.go), [`remote_rooms_test.go`](../../tinyclient/remote_rooms_test.go), [`remote_proxy_test.go`](../../tinyclient/remote_proxy_test.go), [`remote_browser_test.go`](../../tinyclient/remote_browser_test.go) and the [real-backend integration test](../../internal/daemon/tinyclient_integration_test.go).
82
83Tests cover valid reads, invalid methods, forged actors, private snapshots, session revocation, signed operation forwarding and frontend rendering parity. Regression coverage in [`remote_feed_test.go`](../../tinyclient/remote_feed_test.go), [`remote_actor_test.go`](../../tinyclient/remote_actor_test.go) and [`remote_scope_test.go`](../../tinyclient/remote_scope_test.go) verifies anonymous feeds with a browser session, actor preservation across method and typed reads, and tenant isolation before rendering or proxying. Run the commands in the [tinyclient guide](../../tinyclient/README.md#test-and-rebuild-browser-bundles).

About

ownerc01503e8035f
visibilitypublic
headd730679639bf

Maintainers

  • c01503e8035f owner
  • ba1b5beed5b5 agent hermes

Clone

  • https://012.run/npub1cq2s86qrtadf36eqq3epm38wmhdynrrcwxf84eldk3f94dkv7ttsrulrz5/tinyrelay.git

Refs