Redesign admin peering settings and catalogs
This commit is contained in:
1 parent
492477f86a
commit
da40d73f02
16 files changed
+1037
-85
No files matched your search
+49
-30
@@ -11,21 +11,30 @@ received chapters. No database server or second library writer is introduced.
|
||||
|
||||
## Roles and direction
|
||||
|
||||
The admin UI is **Settings → Peering**, and all users can open the **Peers** catalog
|
||||
page. Each server may have many peers. For every peer, its admin independently sets:
|
||||
The interface is administrator-only and split by task: **Settings → Admin → Peering**
|
||||
manages server identity, peers, grants and transfer limits; **Peer catalogs** manages
|
||||
per-peer title approvals and remote catalog browsing. Ordinary users cannot see either
|
||||
page or call their APIs. Each server may have many peers.
|
||||
|
||||
- **Serve approved manga**: expose only individually checked library titles to that
|
||||
peer. Off is the default and invalidates the current serving grant.
|
||||
- **Allow downloads**: queue and pull chapters from that peer. Off is the default;
|
||||
a verified pairing and imported grant still allow browsing its approved catalog.
|
||||
- **Let readers queue**: ordinary readers may request transfers; otherwise only an
|
||||
admin may queue. Browsing a permitted catalog does not disclose the local user to
|
||||
the remote server.
|
||||
- Upload streams, bytes/s and bytes/day, and receiving pages in flight and bytes/s.
|
||||
Defaults are two in-flight pages and 2 MiB/s in each direction per peer. The
|
||||
publisher's caps remain authoritative. A gateway-wide four-stream ceiling applies.
|
||||
- **Grant scopes**: Catalog permits catalog, covers and metadata. Download includes
|
||||
Catalog and permits chapter transfers. Each direction has its own grant.
|
||||
- **Serving state**: Active or Paused. Pausing preserves the grant/token; explicit
|
||||
Revoke invalidates it. Scope changes take effect without exchanging a new token.
|
||||
- **Approved titles**: the publisher chooses titles on Peer catalogs, not in the
|
||||
connection settings. Pairing or a grant alone does not share a title.
|
||||
- **Local receiving** is a separate switch. Browsing works with Catalog permission
|
||||
even when local receiving is off; downloads require an active Download grant and
|
||||
local receiving enabled.
|
||||
- Transfer limits cover upload streams, bytes/s and bytes/day, plus receiving pages
|
||||
in flight and bytes/s. Defaults are two in-flight pages and 2 MiB/s each direction
|
||||
per peer. Publisher caps remain authoritative; a gateway-wide four-stream ceiling
|
||||
applies.
|
||||
|
||||
Serving and receiving are separate directions. Pairing by itself exposes no title.
|
||||
The required local server display name is 1–25 ASCII letters/digits. It is a friendly
|
||||
label, not the cryptographic identity; changing it does not rotate the certificate.
|
||||
An invitation expires after 48 hours, the certificate currently lasts one year, and
|
||||
a grant lasts up to 90 days bounded by certificate validity. The UI labels these as
|
||||
separate lifetimes.
|
||||
|
||||
## Deployment
|
||||
|
||||
@@ -38,8 +47,9 @@ scraper queue, Docker socket, or writable library mount. It must never be scaled
|
||||
past one instance for the same usage-counter directory.
|
||||
|
||||
1. Build the image and start the normal stack as documented in
|
||||
[`compose-deployment.md`](compose-deployment.md). Generate the local certificate
|
||||
in **Settings → Peering**. Keep `/data/peering/identity.key` private and backed up.
|
||||
[`compose-deployment.md`](compose-deployment.md). Set the local server name and
|
||||
generate its certificate in **Settings → Admin → Peering**. Keep
|
||||
`/data/peering/identity.key` private and backed up.
|
||||
2. Start the optional service with `docker compose --profile peering up -d
|
||||
peer-gateway`. Verify `docker compose --profile peering ps` shows healthy and
|
||||
`https://127.0.0.1:8093/health` responds. `/health` is deliberately unauthenticated
|
||||
@@ -65,12 +75,12 @@ require administrator-supervised re-pairing; there is no automatic key rotation
|
||||
2. Both admins import the other's invitation and press **Test & verify pairing**.
|
||||
The HTTPS handshake presents client and server certificates, checks their exact
|
||||
pins and dates, and consumes the one-use invitation code. Both sides must probe.
|
||||
3. A publisher checks specific titles under that peer, enables **Serve**, issues a
|
||||
90-day random grant, and sends the token privately to the receiving admin. The
|
||||
receiving admin imports the grant and enables **Allow downloads**. Reverse
|
||||
direction needs its own share selection and grant. The server stores only a hash
|
||||
of a grant it issued; the receiver stores its imported token server-side.
|
||||
4. A local user browses the catalog, selects missing/newest/last-five or an exact
|
||||
3. A publisher approves titles for that peer on **Peer catalogs**, chooses Catalog
|
||||
or Download grant scopes, and sends the one-time token privately. The receiving
|
||||
admin imports it and independently enables local receiving for downloads. Reverse
|
||||
direction needs its own approvals and grant. The server stores only a hash of a
|
||||
grant it issued; the receiver stores its imported token server-side.
|
||||
4. An admin browses the permitted catalog, selects missing/newest/last-five or an exact
|
||||
chapter, and queues it through the normal scraper. The peer adapter downloads up
|
||||
to the configured pages in flight, validates size and SHA-256, resumes a partial
|
||||
page with HTTP Range, checkpoints between batches, and atomically publishes each
|
||||
@@ -82,15 +92,19 @@ the human reader. It can still observe requested titles, times and byte counts.
|
||||
|
||||
## Peer v1 HTTP interface
|
||||
|
||||
All content endpoints require TLS 1.3 client certificate pinning, a paired/serving
|
||||
peer, and a currently valid certificate-bound bearer grant. There is no insecure
|
||||
HTTP fallback and no path-based file browsing.
|
||||
Catalog, cover, manifest and blob endpoints require TLS 1.3 client certificate
|
||||
pinning, paired identity, an active grant with the matching scope, and no serving
|
||||
pause. There is no insecure HTTP fallback or path-based file browsing. `/access`
|
||||
requires the pinned client certificate and reports status without a bearer grant so
|
||||
an admin can distinguish pairing from permission.
|
||||
|
||||
| Request | Response |
|
||||
| --- | --- |
|
||||
| `GET /peer/v1/hello` with one-use invitation headers | Protocol version and server identity fingerprint; no catalog |
|
||||
| `GET /peer/v1/catalog?cursor=N` | Up to 50 approved opaque title IDs, title/year/status, next cursor |
|
||||
| `GET /peer/v1/manga/{id}?cursor=N` | Up to 100 complete chapter IDs and light metadata |
|
||||
| `GET /peer/v1/access` | Pairing state, certificate expiry and current grant status/scopes; no catalog |
|
||||
| `GET /peer/v1/catalog?cursor=N` | Up to 50 approved opaque title IDs, safe metadata and cover availability |
|
||||
| `GET /peer/v1/covers/{mangaId}` | Approved cover image only; bounded to 5 MiB and charged to peer byte quota |
|
||||
| `GET /peer/v1/manga/{id}?cursor=N` | Up to 100 complete chapter IDs and public metadata |
|
||||
| `GET /peer/v1/manga/{id}/chapters/{id}` | Ordered page IDs, MIME, byte size, SHA-256 and ETag |
|
||||
| `GET /peer/v1/blobs/{id}` | One image, optional `Range: bytes=N-` and `If-Match`; 206 on resume |
|
||||
|
||||
@@ -111,8 +125,13 @@ parallelism, not unbounded connections.
|
||||
|
||||
`npm run test:peer` creates disposable A/B identities, gateways and libraries and
|
||||
tests mTLS pairing, no-cert/bad-grant rejection, private catalog, per-title sharing,
|
||||
manifest hashes, a resumed range response, scraper publication, duplicate skip and
|
||||
revocation. `npm test` includes it. An isolated Compose acceptance is:
|
||||
catalog-only cover access, manifest hashes, a resumed range response, scraper
|
||||
publication, duplicate skip, pause and revocation. `npm run test:peer-ab` additionally
|
||||
builds two independent Compose projects from synthetic fixtures, exercises real
|
||||
two-way pairing, browsing, cover retrieval, permission updates and sequential queueing,
|
||||
checks the queue remains paused, and tears both stacks down. The UI suite checks the
|
||||
guided setup, approvals, and non-admin boundary. An isolated single-stack Compose
|
||||
acceptance is:
|
||||
|
||||
```powershell
|
||||
$env:APP_IMAGE = 'mangacircus:local' # replace with the image just built
|
||||
@@ -133,6 +152,6 @@ without affecting reading or existing local downloads. Do not delete the identit
|
||||
to recover from a network error; that would break every peer pin.
|
||||
|
||||
Current limits: no automatic certificate renewal, invitation cancellation UI,
|
||||
peer cover-image endpoint, multi-peer performance pilot, VM deployment, or public
|
||||
internet exposure review. The gateway has no automated hoster-interaction logic;
|
||||
multi-peer performance pilot, VM deployment, or public internet exposure review.
|
||||
The gateway has no automated hoster-interaction logic;
|
||||
source scraping remains subject to the existing source-safety policy.
|
||||
Reference in new issue
Block a user