Commit Graph

2 Commits

Author SHA1 Message Date
Fredrik Johansson
4a6a373f1e Restyle UI to match flit/wisp theming, add delete + token revoke/list
UI: ported flit/wisp's dark, JetBrains-Mono-accented theme wholesale
(same CSS vars, same card/button/input vocabulary) so stash reads as
part of the same family of tools instead of a bare unstyled list. List
view is now card-based with unread indicators; reader view got proper
article typography.

Delete: the list and reader views now have a delete button (with a
confirm prompt) wired to the existing DELETE /api/articles/:id via a
new POST /delete/:id UI route, since browser forms can't issue DELETE
directly. express.urlencoded() added to parse the form posts this and
the existing mark-read buttons need.

Token management: added listTokens/revokeToken to db.ts, plus
`npm run tokens` (lists label/created_at/last-4-chars only — never
re-prints a full secret) and `npm run revoke-token -- <label>`. This
was a real, previously-missing gap: there was no way to invalidate a
single compromised token short of wiping the entire database. Built
after a token got printed in plaintext during a debugging session and
there was no way to kill just that one credential.

Verified: full theme renders correctly (screenshotted list + reader
views), revoke-token correctly 401s the targeted token while leaving
others untouched (tested against a real leaked-then-revoked token),
list-tokens never displays a recoverable secret.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-13 19:00:36 +02:00
Fredrik Johansson
f2ebfe35d4 Initial build: stash server + browser extension
Server (Express + better-sqlite3 + FTS5, mirroring keep's stack):
/api/capture (upsert-on-url, per PROPOSAL.md's dedup decision),
/api/articles (list/search/mark-read/delete), plus a minimal
server-rendered reading list and reader view at / and /read/:id
(token passed as ?t= there since browser navigation can't set an
Authorization header). Bearer-token auth generated via `npm run
token` — no login flow, matching keep's one-time identity
registration pattern.

Extension (Manifest V3, sideloaded, no store distribution): toolbar
click or context menu "Send to stash" runs @mozilla/readability
(vendored into extension/lib/) against the current page, falling back
to raw rendered HTML when extraction comes back too thin. Options
page for one-time server URL + token entry.

Verified end-to-end with the real extension loaded in a live Chromium
instance (not just unit-tested extraction logic): capture against a
real page, dedup-on-recapture, mark-read, FTS5 search, 401 on missing
auth, and both server-rendered views all confirmed working.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-12 23:23:01 +02:00