Repository navigation
feat(extension): Connect OpenRouter, store screenshots over a real page, privacy policy v2 - #25
Merged
Merged
Conversation
The database, its -wal and -shm files, the model list cache and a new data folder were created with the process umask, and the systemd unit set no UMask, so on a shared computer other accounts could read the word list (SCR-450). The API token and backups were already private. Now every file the server keeps in the data folder is readable only by its own account. The BEAM can't give a mode when it creates a file, so files are created empty, made 0600, and only then filled: the database before SQLite first opens it (SQLite gives the -wal, -shm and -journal files the database's mode; a test checks this), each backup and the copy from the old name before VACUUM INTO, and the token and model cache through a private temporary file. A data folder the server makes is 0700. For existing installs, every start checks the folder before the database opens: Kotiko's own files that others can open are made 0600 again (with one warning naming them), and the folder 0700 when it holds nothing but Kotiko's files. A folder with other files in it, or a link, may be shared on purpose, so it is left as it is with a warning that gives the chmod to run. Nothing here stops the start. run.sh now sets umask 077 and the unit from install-service.sh UMask=0077, so files are private from the moment they exist. Docs: the configuration reference, security requirements and assurance case (the umask gap leaves the residual risks), the site's server page, the changelog and slice 29. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Ayla Croft <dev@scriptkittyos.com>
…ttings kotiko.org/connect/ is live over HTTPS, so the one-click OpenRouter sign-in that slice 11 built can be shown. There was no flag: the button simply wasn't in the pages yet. The welcome tab's first choice is now "Connect OpenRouter (free)", with "Paste a key instead" as the first link, as slice 22's sketch has it. Settings, Word lookups shows "Connect OpenRouter" when OpenRouter is chosen and no key is saved (or while replacing it). Both pages say they are waiting while OpenRouter's tab is open, and update on their own when the key arrives from the return page. Pasting a key still works. Tests cover the visible buttons, waiting, the key arriving, a failed exchange and a sign-in that can't start; the e2e test now starts from the real buttons on both pages and checks the sign-in address, the return page under the live page's CSP and the exchange body. The docs site's OpenRouter and Get started pages describe the button instead of "coming". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Ayla Croft <dev@scriptkittyos.com>
The popup screenshot opened popup.html as its own tab, so "This page" said Kotiko can't run on browser pages (SCR-758). The script now opens the article first and answers the popup's active-tab question with that real tab, served at www.example.com by a browser route so the page line names a website; it stops if the popup still describes a browser page. The dashboard shot waits for the background pronunciation of the word the popup adds, instead of showing "0 of 1", and the welcome shot shows OpenRouter connected, as most learners will see it. Adds the five 1280x800 English screenshots in brand/store/screenshots/en. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Ayla Croft <dev@scriptkittyos.com>
With "Connect OpenRouter" now visible, the policy must say what it does: OpenRouter sends the browser to https://kotiko.org/connect/ with a one-time code in the address, which Kotiko trades for the learner's key. The page sets no cookies and loads nothing else; the code works once, expires in ten minutes and is useless without a secret that stays in the browser; like any site, kotiko.org's hosts (GitHub Pages, Cloudflare) see the visit and that address. Version 2, with a changelog line, and the bundled copy in the extension synced. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Ayla Croft <dev@scriptkittyos.com>
…/connect-openrouter-and-screenshots # Conflicts: # CHANGELOG.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
1. "Connect OpenRouter (free)" is visible now that https://kotiko.org/connect/ is live (slice 11).
oauth.start/oauth.code,lib/pkce.js,content/connect.js) was built and tested; the buttons had just never been put on the pages.callback_url, the S256 challenge,key_label, andPOST /api/v1/auth/keyswith{code, code_verifier, code_challenge_method}./connect/page serves whatconnect.jsexpects.test/e2e/connect.spec.mjsclicks the real buttons on both pages and checks the sign-in address, the waiting text, the exchange body (stubbed), the key saved, an expired code refused, and the same path on another site ignored.https://kotiko.org/connect/as the callback and the returned code yields a working key.2. Store screenshots (SCR-758). The popup shot now opens over a real article tab,
www.example.comserved by a browser route (it never reaches the internet), so it no longer says "can't run on browser pages".3. Privacy policy → Version 2. A "Connecting OpenRouter" section:
The extension's bundled copy is synced, and the site page regenerates from the same source.
Checked
npm run lint: 0 errors.npm run coverage: 1947 pass, 94.03 % lines, 84.47 % branches.npm run perf: all ok.npx playwright test: 100 passed, 4 skipped.check-old-name,check-base-neutral,sync-privacy --check, contrast (76/76) andreuse lintpass. Sitenpm testandnpm run checkpass.Also noticed: the live
/connect/sends no CSP or frame headers (only the<meta>CSP). That's the Cloudflare hardening step in SCR-757.🤖 Generated with Claude Code