diff --git a/TODO.md b/TODO.md index 3d5965d..0bc29b1 100644 --- a/TODO.md +++ b/TODO.md @@ -60,10 +60,10 @@ passive badge, which is the product's pitch. Two nudges, cheapest first: since it lands at the moment of install. Needs human-written copy and a decision between opening substandard.blog or a bundled page. -## After the store listing exists +## Recapture once substandard.blog is a publication -Deferred on purpose until the CWS listing is live and tested (publishing the -publication record is itself the public announcement): +The listing is live; these were deferred behind it and behind the publication +record, which is still unwritten (see below): - Recapture the popup screenshots once substandard.blog is itself a publication, so the store screenshots show our own record. Every capture of @@ -77,35 +77,13 @@ publication record is itself the public announcement): release flow — the upload endpoint is the only authoritative validator (it rejects things no local tool checks, like a manifest `key`). -## Write the screenshot gallery's copy - -The homepage gallery ships with `PLACEHOLDER` strings for its heading and its -four captions (`scripts/shots.mjs`, rendered by `web/src/pages/index.astro`). -It is the most prominent prose on the page after the hero, so it is a human's -call, not a generated one. The `alt` text beside each caption is a plain -description of the image and is written; it is there for accessibility, not -for the pitch, and does not need rewording with the captions. - -Which shots appear is the same decision: the list is four today -(signed-out publication, subscribed, unverified page, blocked-and-labeled) out -of the seven states in `docs/status-states.md`, two of which — the first and -the last — are also the store listing's screenshots. The layout centers a lone -last shot, so an odd count is fine. - -## Ship the feedback and preferences scopes with a metadata deploy - -The feedback form asks for `include:app.userinput.authBasic` and the labeler -list asks for `rpc:app.bsky.actor.getPreferences?aud=*`. Both live in -`oauth/client-metadata.json` — the file PDSes read from -`https://substandard.blog/client-metadata.json`. Two consequences at release -time: - -- Deploy the site (`scripts/deploy-site.sh`) before the extension release. A - build asking for a scope the hosted metadata does not list is refused at the - authorization request, which breaks sign-in itself, not just feedback. - `deploy-ext.sh` will not package until then: its preflight runs - `check-oauth-metadata.mjs --hosted`, which compares the hosted file to - `oauth/client-metadata.json` field by field, scope included. +## Sessions granted before the current scope list + +The hosted metadata already carries `include:app.userinput.authBasic` and +`rpc:app.bsky.actor.getPreferences?aud=*`, so the deploy-before-release +ordering this entry used to describe is done and `check-oauth-metadata.mjs +--hosted` passes. What is left is the other half: + - Sessions granted under the old list cannot post; the panel says so when the PDS refuses the write. Nothing prompts for re-consent on its own — decide whether that is worth a status pill once there are users with old sessions. @@ -172,35 +150,15 @@ Details that matter: - Constellation is a third-party dependency. If it is down, hide the count rather than falling back to pagination. -## Say in the privacy policy that we probe every origin - -The policy at `web/src/pages/privacy.astro` says the extension "makes requests -directly from your browser to that site". True, but it does not say the part a -reader would want: detection probes -`/.well-known/site.standard.publication` on **every** http(s) origin visited, -whether or not it turns out to be a publication. Consequences worth stating -plainly, because a reader who discovers them unaided will read the omission as -concealment: - -- Every site's operator can see the request in their logs, so it is a - fingerprint of substandard users. -- It reaches intranet hosts and `localhost` as well as the public web. Kept - deliberately — local dev of a publication depends on it. -- Nothing of the user's rides along: requests are `credentials: 'omit'`, and - the result is cached in `storage.session` (see `src/lib/http.ts` and - `src/lib/detection.ts`). - -Wording is a human's call — this is prominent user-facing prose. The facts -above are the input, not a draft. - ## Check the store listing's Privacy practices tab against reality The listing is live, and CWS enforces the data-use declarations on it. Confirm the dashboard says what the extension actually does: broad host permissions with a justification, "Website content" handling, and no collection (there is no backend). A mismatch between the declared practices and observable -behaviour is a takedown risk, not a paperwork one. Pairs with the privacy -policy item above. +behaviour is a takedown risk, not a paperwork one. The privacy policy itself +now describes the per-site check and the ecosystem lookups; this is the other +copy of those claims, and the two should not drift apart. ## Decide what to do about the 843 kB popup chunk