diigo-cache: the public page only reads
/public/<username> reads through the cache's viewer() facet (PageViewer: stored pages, knownTotal, fill progress — the reader alone), so it can't fetch from diigo or write storage. Behavior change, agreed beforehand: an unfetched page no longer fills itself on a miss; it says "not fetched yet" (JSON: stored: false), and the owner fills via the webkey page. The HIT/MISS line becomes "stored <when>". Strangers can no longer make the cache spend the owner's diigo session; the README's deployment concern shrinks to /api. Tests: viewing an unfetched page makes no webapp call; the page appears once stored; fill progress shows after one fill step. Generated-by: Claude Opus 5.5
This commit is contained in:
1 parent
a17d287e1d
commit
d7190abaf8
5 files changed
+54
-33
No files matched your search
+12
-10
@@ -26,7 +26,11 @@ goal 2 preamble).
|
||||
Public page n is diigo page n, filtered (may show fewer than
|
||||
`PAGE_SIZE`, 100: diigo's cap).
|
||||
`/public/<username>` resolves through the `idFromName("index")`
|
||||
registry.
|
||||
registry, and reads through `viewer()`, a read-only facet: it shows
|
||||
stored pages and fill progress, and can't fetch from diigo or write.
|
||||
- **Storage**: SQL lives in `src/cache-read.sql` (selects only) and
|
||||
`src/cache-write.sql`; `src/store.ts` turns them into a reader and a
|
||||
writer facet, so the cache logic holds no SQL text.
|
||||
- **Pages**: home's dump form (cache id + page number, POST) shows raw
|
||||
dump rows; `/public/<username>?page=n` shows an HTML list with a page
|
||||
form (JSON for `Accept: application/json`). Both say `cache: HIT` or
|
||||
@@ -72,20 +76,18 @@ show only a fingerprint (a prefix of the id's one-way hash).
|
||||
Stored state is meant to be durable: see the breaking-change rule in
|
||||
[capsite AGENTS.md](../AGENTS.md).
|
||||
|
||||
## Deployment concern: public pages spend your diigo session
|
||||
## Deployment concern: rate-limit `/api`
|
||||
|
||||
Anyone who can reach `/public/<username>` can make the cache fetch from
|
||||
diigo through *your* cookie session: each request may spend up to
|
||||
`FETCH_BUDGET` (40) diigo fetches on uncached pages (goal 1d), paced at
|
||||
`MS_PER_CALL`. Cached pages cost nothing. Before exposing a deployment:
|
||||
Public pages only read storage, so strangers can't make the cache spend
|
||||
your diigo session. `/api` is keyed (a cache id is needed), but Cap'n
|
||||
Web pipelining makes calls cheap to send. Before exposing a deployment:
|
||||
|
||||
- rate-limit the public routes and `/api` (Cap'n Web pipelining makes
|
||||
calls cheap to send) — on Cloudflare, the
|
||||
- rate-limit `/api` (and `/public/*`, which reads storage) — on
|
||||
Cloudflare, the
|
||||
[Workers rate-limit binding](https://developers.cloudflare.com/workers/runtime-apis/bindings/rate-limit/)
|
||||
(keyed by client and/or username); on other workerd hosts, a rate
|
||||
limit in the proxy in front;
|
||||
- run the fill job (goal 1e) so most pages are cached before strangers
|
||||
arrive.
|
||||
- run the fill job (goal 1e): public pages show only what's stored.
|
||||
|
||||
## RPC use (from another worker, same account)
|
||||
|
||||
|
||||
Reference in new issue
Block a user