Pure rename ahead of the dump worker's evolution into a bookmark cache
(goal 1c), so history follows the files. The diigo-login helper script
is dropped: the cookie now enters through webapp's mint form, never a
local script.
capsite-notes: What-we-built gains the webapp/diigo-dump layers (links
to READMEs and the goal tree, not repeats); root Goal restated as
'confine the diigo secret to a small auditable piece behind an
attenuated interface' per discussion, with the dead API-key path noted
and details delegated to the tree; credentials section de-staled
(placeholder values, unconditional 401 finding, cookie-path direction);
private-bookmarks note no longer recommends the dead HTTP Basic path.
diigo-bookmarks/README: title corrected sandboxed->native with the
conversion note and a disclaimer that its Develop/Publish sections are
inherited scaffold text (larger rework deferred).
Generated-by: opencode (GLM)
The hard rules move from the goal tree into a proper AGENTS.md at the
capsite root (discoverable by agents without reading the tree; the
workspace AGENTS.md's commit-trailer policy stays where it is, linked).
Checklist keeps a one-line pointer, so a continuation prompt still
surfaces them. Error hygiene (no header/param values in messages)
groups with secrets discipline there rather than as its own rule.
Generated-by: opencode (GLM)
diigo-dump/README was stale three ways: described the pre-DO connect
flow (askpass + DIIGO_COOKIE, both retired), referenced deleted files
(src/webapp.ts), and named the old entrypoint. Rewritten against
current code (DiigoBridge, DO storage state surface, state-aware
/_connect); run/connect/deploy instructions now live only in the
capsite checklist, linked (intra-repo docs link rather than repeat).
webapp/README Run section: port note corrected (two-config run makes
diigo-dump the primary) and pointed at the checklist as the source.
Generated-by: opencode (GLM)
Two prose referrals (preamble + root goal) and the Pointer bullet now
use [the capsite notes](capsite-notes.md) — descriptive, frontloaded,
context-free per the hypertext-links skill; no raw filename visible in
any anchor text. Also wrapped the bib-sync issue URL in the root goal.
Generated-by: opencode (GLM)
Pointers section now uses [descriptive text](url) links with
frontloaded, context-free anchor text (intra-repo relative paths for
local docs; mm-diigo repo link for the provenance collection).
New opencode skill hypertext-links encodes the Prism
docs/research/STYLE.md link rules for reuse here.
Generated-by: opencode (GLM)
ses_eec320fe4ffehaMAn44U1nTKJU verified both real keys, all documented
auth schemes, and two endpoints -> 401 unconditionally, with historical
proof the same creds worked in 2024-2025 (13.5k bookmarks downloaded).
Goal 2 is now 'plugin rides the webapp cookie path', with the cookie-
rotation cost explicit (2-iii); the earlier DECISION POINT framing
('try a real key') contradicted that record and is removed.
Generated-by: opencode (GLM)
Explicit tree semantics in the header: a goal is checked only when all
its children are (leaves: when verified). Architecture sketch moved out
(its content already lives in capsite-notes.md + per-worker READMEs;
duplicates would drift) — the tree's items carry just enough provenance
to stay self-contained. Adds 1b-i/1b-ii mint-loop subgoals and the 2-iii
decision point (API key vs cookie path for the plugin) surfaced this
session; hard rules + run instructions retained.
Generated-by: opencode (GLM)
Now carries the architecture sketch (webapp factory / diigo-dump
consumer / madmode site), the ladder state including what's verified
vs not (DO round trip still to exercise end-to-end), the run/how-to
commands, the hard rules learned this session (assistant never runs
dev servers; secrets discipline; error hygiene; wrangler types),
and pointers into the notes and provenance repos.
Generated-by: opencode (GLM)
webapp/ (new, site-agnostic, independently deployable):
- WebApp: fluent client (pathjoin/query/withHeaders/cookies/get/post)
as RpcTarget; flower-style unions cite NuxiNL/flower v0.11 (Jan 2019);
url/headers private (RpcTarget property reads are RPC); Error messages
carry no header/param values; query-stripped URLs only
- WebAppDo: per-instance authority in DO storage (survives eviction);
one-shot configure(), refuses different-url re-configure
- WebAppFactory: newWebApp(init) -> {id, app}, at(id); ids are bearer
capabilities and are not logged
- HTTP surface: GET / mint form (secret header keys render blank),
POST / mint (form or JSON), POST /at/<id> drive-by-capability
- types via wrangler types (worker-configuration.d.ts, gitignored)
diigo-dump/: now a webapp consumer. The diigo knowledge is only the
mint call: url=interact_api/, UA + x-requested-with, cookie, 500ms gate.
- src/webapp.ts, src/diigo-web.ts deleted (webapp's are canonical);
diigo.ts slimmed to dumpBookmarks + PagedGet
- /_connect is state-aware: connect form pre-mint; health check
(count=1 probe) + re-mint path post-mint; home-page link relabeled
- mint success page: narrow field + copy button (attribute-quoting
fixed; id in x-diigo-web-id header for scripts)
- scripts/diigo-login: askpass flow, marked OBSOLETE (page flow is
the primary); speaks the form protocol; writes only DIIGO_WEB_ID —
the cookie lives in DO storage, never on disk
- package.json: dev = wrangler dev -c wrangler.jsonc -c ../webapp/...
(verified: Ready on :8787, GET / 200, /_connect 200);
wrangler ^4.148.0 devDependency after node_modules was cleaned
TODO(webapp) in webapp/README.md: proxy-page vs primary-worker mint
form; reconsider as the UI grows.
Generated-by: opencode (GLM)
Restore the fluent client from mm-diigo's WebApp.js as RpcTarget classes
(src/webapp.ts): WebApp with pathjoin/query/withHeaders/cookies/get/post,
flower-style unions (NuxiNL/flower v0.11, Jan 2019 — merge only if no
shared key contradicts), pathjoin containment guard; RateLimitedWebApp
shares one gate across all derived handles, enforced at get/post only.
src/diigo.ts ports makeDiigoAPI and the dumpBookmarks generator.
RPC surface: DiigoService (WorkerEntrypoint) with open() handing a
rate-limited stub whose cookie is attached server-side only, and
dumpNdjson. Promise pipelining makes a whole chain a single round trip.
Divergences from the original for the RPC setting:
- url is a private field: a public property on an RpcTarget is readable
by stub holders, and query strings can carry credentials
- Error messages carry no header/param values; URLs have query stripped
(structured details via @endo/errors deferred until node_modules)
- fetch default is fetch.bind(globalThis): a detached fetch throws
'Illegal invocation' in workerd (found live, fixed, verified 200)
- dumpPage/open log failures via console.error for observability
README documents config, RPC use, and each divergence.
Generated-by: opencode (GLM)
fixup: scrub failed API-key ping from checklist
diigo-ping never authenticated (Diigo 401); the working path is the
session-cookie dump worker. Renumber steps, note the scrub with the
reason, and drop the ping how-to.
Generated-by: opencode (GLM)
Documents the cookie-path worker: endpoint and headers mirrored from
the mm-diigo original, DIIGO_COOKIE secret setup (local .dev.vars vs
wrangler secret put), the inert-GET / POST-only-submit behavior, and
the manual test result (200, total 1674, 2026-10-06) with pointers to
the checklist and capsite notes.
Generated-by: opencode (GLM)
Port of mm-diigo/projects/diigo-bak/diigo-dump.mjs as a Cloudflare Worker:
one page-number field + button, GET interact_api/load_user_items
(sort=updated, count=24) with DIIGO_COOKIE as a Worker secret.
GET / is inert; dumps happen only on POST submit.
Manual integration testing (local wrangler dev, port 8788, 2026-10-06)
shows it works: status 200, total 1674 bookmarks, page-1 items returned.
The browser-session-cookie path authenticates; the static API-key path
(diigo-ping worker, EmDash plugin) is still rejected by Diigo (401).
Also: project checklist (capsite-checklist.md) with step results, and a
.gitignore for local artifacts (.dev.vars, node_modules, wrangler state).
Generated-by: opencode (GLM)