diff --git a/capsite-checklist.md b/capsite-checklist.md index 13dd475..74a323e 100644 --- a/capsite-checklist.md +++ b/capsite-checklist.md @@ -1,52 +1,66 @@ -# capsite checklist +# capsite goal tree -Goal: an EmDash site (madmode) collecting diigo.com bookmarks, credentials -held by the host, never inside the plugin (see capsite-notes.md). +Nested checkboxes form a goal tree: each `- [ ]` is a goal; its indented +children are the subgoals/steps that must pass before it (an item is only +checked when **all** its children are checked — or, for leaf items, when +it has passed verification itself). Working notes live under each goal; +`capsite-notes.md` carries the background narrative. -## Architecture (as of 2026-10-07) +## the goal tree -- `webapp/` — site-agnostic DO factory worker (deploy-once). Each instance - is an attenuated credentialed handle to one HTTP surface; ids are bearer - capabilities (128-bit, inderivable; not logged). Fluent surface - (`pathjoin/query/withHeaders/cookies/get/post`), flower-style unions - (contra-value throws; after NuxiNL/flower v0.11), promise-pipelined - (whole chain = 1 round trip; only terminal get/post does I/O). -- `diigo-dump/` — the webapp consumer: mint call carries all diigo - knowledge (interact_api url, UA + x-requested-with headers, cookie, - 500ms gate). Drives dumps via `WEBAPP.at(id)` stub. -- `madmode/` — EmDash site; `diigo-bookmarks/` native plugin (API-key - path; currently 401 — see step 2); `diigo-ping/` obsolete probe worker - (kept as evidence). +- [ ] **EmDash site (madmode) collects diigo.com bookmarks; credentials + held by the host, never inside the plugin** (background: + capsite-notes.md; after step 2, expands to bib sync #195) -## State of the ladder + - [x] Credential discipline established: cookies/keys/secrets live in + Worker secrets or DO storage, never in source, config, or the + plugin. (`.dev.vars` gitignored: only `DIIGO_WEB_ID`; + cookie lives in the webapp DO's storage since the 1b split.) + - [x] **1. Cookie-path dump worker** (`diigo-dump/`): port of + mm-diigo's diigo-dump.mjs. GET inert, dump only on POST. + Verified 2026-10-06: 200, `total: 1674`. (Scrubbed: static + API-key ping worker 401'd — the cookie path was the one that + worked; see the API-key subgoal below for where that left us.) + - [x] **1b. webapp DO factory** (`webapp/`): credentialed authority + in a Durable Object; ids are bearer capabilities (not logged); + factory worker is site-agnostic; consumer holds only the id. + Dev wiring verified: `pnpm dev` boots both, home + /_connect + answer on :8787. + - [ ] 1b-i. Mint through the running dev server end-to-end: + POST /_mint (or /_connect page) with a fresh cookie → + id → dump page 1 through the DO → 200/items. + (Everything up to mint is verified; this closes the loop.) + - [ ] 1b-ii. Prod mint + handoff: deploy both, mint against + prod, `wrangler secret put DIIGO_WEB_ID`, dump a page. -- [x] **1. Cookie-path dump worker** (`diigo-dump/`): GET is inert; dump - only on POST. Manual test (2026-10-06): 200, `total: 1674`. - (Scrubbed: static API-key ping worker failed 401 — cookie path works.) -- [x] **1b. webapp DO factory split**: credentialed authority in a - Durable Object (storage persists init/config across restarts and - evictions); consumer talks via service binding + id. - Dev wiring verified: `pnpm dev` in diigo-dump → Ready on :8787, - home + /_connect pages answer. NOT yet verified: mint through the - running dev server (POST /_mint with a fresh cookie), then dump - page 1 through the DO — the end-to-end chain. -- [ ] **2. Real API key in madmode/.dev.vars**: fetch a key from - https://www.diigo.com/settings/api; confirm the EmDash plugin's - "Sync now" returns success (status 200, bookmarks stored). - Note: API-key path 401'd with the placeholder key; webapp's cookie - path is proven — if the key path stays broken, consider whether the - plugin should ride the webapp DO instead. -- [ ] **3. `/bookmarks` page renders real data** after a sync — titles/tags - visible at `http://localhost:4321/bookmarks`. -- [ ] **4. Cron sync works** locally without errors (`0 */6 * * *` task in - `_emdash_cron_tasks`). -- [ ] **5. Deploy order**: webapp first (`cd webapp && npx wrangler - deploy`), then diigo-dump; mint a prod instance (POST /_mint with - cookie; capture id from x-diigo-web-id header); - `wrangler secret put DIIGO_WEB_ID` in diigo-dump; then madmode - (`pnpm wrangler deploy`, secrets via `wrangler secret put`); - plugin "Sync now" against prod. -- [ ] **6. bib sync #195**: repeat the pattern for the next read-access need. + - [ ] **2. madmode collects real bookmarks** (the API-key path) + - [ ] 2-i. Real API key: fetch from + https://www.diigo.com/settings/api; put in + `madmode/.dev.vars` (placeholder now; 401s). + - [ ] 2-ii. Plugin "Sync now" succeeds: status 200, bookmarks + stored (admin at /_emdash/admin → Diigo Sync). + - [ ] 2-iii. DECISION POINT: if the API-key path stays 401, + consider riding the plugin on the webapp cookie path + instead (plugin already declares the host gate; the DO + would hold the cookie). Prefer the API key if it works — + a static key beats a session cookie for cron. + - [ ] **3. `/bookmarks` renders real data** after a sync — titles/tags at + http://localhost:4321/bookmarks. + - [ ] **4. Cron sync** works locally without errors (`0 */6 * * *` in + `_emdash_cron_tasks`). + - [ ] **5. Deployed end-to-end** (order matters; webapp first): + - [ ] 5-i. webapp: `cd webapp && npx wrangler deploy` + - [ ] 5-ii. diigo-dump: deploy + prod mint + `wrangler secret + put DIIGO_WEB_ID` (id from x-diigo-web-id header) + - [ ] 5-iii. madmode: `pnpm wrangler deploy`, secrets via + `wrangler secret put`; plugin "Sync now" against prod + - [ ] **6. bib sync #195**: repeat the pattern for the next + read-access need. +- [ ] **webapp graduates from prototype** (optional; only if it earns it) + - [ ] TODO(webapp): one canonical mint form — proxy-page (current) vs + running webapp as the primary worker so its own port serves the + form directly; revisit as the UI grows. + - [ ] @endo/errors for structured error details (needs node_modules). ## How to run (continuation prompts) @@ -74,6 +88,12 @@ Terminal flow (superseded by the page; needs a display): Then: enter a page number on the home page, dump → JSON items. GET / is inert (no accidental fetches; dumps happen only on POST submits). +madmode (EmDash site; separate worker, separate concerns): + + cd ~/oros-bots/capsite/madmode && pnpm dev # → :4321 + # admin at /_emdash/admin; dev-bypass auth helper: + # /_emdash/api/setup/dev-bypass?redirect=/_emdash/admin + ## Hard rules (learned 2026-10-06/07; keep them) - The ASSISTANT never runs wrangler/astro dev servers; the user does @@ -83,8 +103,7 @@ is inert (no accidental fetches; dumps happen only on POST submits). `wrangler secret put` deployed. Since the DO split, only DIIGO_WEB_ID is a diigo-dump secret at all. - Error messages must not contain header or param values (they cross RPC - as exceptions and land in logs); URLs appear query-stripped. TODO: - @endo/errors for structured details once node_modules exists. + as exceptions and land in logs); URLs appear query-stripped. - `wrangler types` after any wrangler.jsonc change (generated worker-configuration.d.ts is gitignored). @@ -94,6 +113,4 @@ is inert (no accidental fetches; dumps happen only on POST submits). - ../mm-diigo/projects/diigo-bak/ — provenance of the fluent client and dump generator (WebApp.js, diigo-dump.mjs, diigo-interact.mjs; commit 7dbb367, Oct 6 2026) -- webapp/README.md — HTTP + RPC surfaces; TODO there: proxy-page vs - primary-worker mint form -- diigo-dump/README.md — consumer wiring, run/deploy details \ No newline at end of file +- webapp/README.md, diigo-dump/README.md — per-worker details \ No newline at end of file