Repository navigation
Protected pages with shareable invite links - #36
Draft
avb-dev-docs wants to merge 2 commits into
Draft
avb-dev-docs wants to merge 2 commits into
avb-dev-docs wants to merge 2 commits into
Conversation
Port of the page-protection system (proven in keyboard-docs), extended with per-page invitation links: - `protected: true` frontmatter (editor lock toggle included) builds the page as a lock shell — title/description only; content is served solely by /api/reader/content after a server-side check of the reader cookie, an invite, or a team session. - Invite links: editors mint a signed hash from the new Invite… menu next to the lock toggle (or POST /api/admin/invite) and share the page URL with ?invite=<hash> appended. The HMAC covers the page slug and expiry (7/30/90 days or none), so a link opens exactly one page and can't be extended; redeeming it sets a per-page cookie so navigation and refreshes stay unlocked. Stateless — rotating ADMIN_SECRET revokes all links at once. - Site-wide READER_PIN unlock and always-on access for signed-in editors, as in the original design. - Protected content is excluded everywhere it could leak: search index bodies, llms.txt / llms-full.txt, the /llms.mdx markdown mirrors, and (new in this repo) the AI assistant's retrieval and the /mcp server's search/read/list tools. - Docs: new Access → "Protected pages" page; READER_PIN listed in configuration and wrangler.jsonc comments. Verified: types:check + lint clean; 34-check e2e matrix against pnpm dev (lock shell never carries content; anonymous 401; mint requires session; invite unlocks its page only — cross-page 401; tampered expiry/signature rejected; cookie redemption; PIN path; admin bypass; llms/search/MCP surfaces clean; public pages unaffected). Co-Authored-By: Claude <[email protected]> Claude-Session: https://claude.ai/code/session_01Ccsf25xk9FdqFbYJ3NWkoo
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
docsdotdev | 1ab6c18 | Commit Preview URL Branch Preview URL |
Aug 24 2026, 01:54 AM |
A practical contributor guide alongside the existing "Why docs.dev + Claude Code" pitch page: one-time setup (clone, pnpm install, claude), asking for pages in plain language, the /new-page and /draft-page skills, verifying with types:check + the dev preview, and the four review paths (direct push, PR, shared draft, branch review from the editor), with a conventions cheat sheet. Registered in the sidebar's Editing group after claude-code. Verified: pnpm types:check passes. Co-Authored-By: Claude <[email protected]> Claude-Session: https://claude.ai/code/session_01Ccsf25xk9FdqFbYJ3NWkoo
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 changed and why
You can now mark individual docs pages as protected and let people in selectively: pages opt in with
protected: true(an editor lock toggle writes it), build as a lock shell with no content in the static HTML, and unlock via a site-wide reading PIN or a shareable invite link — a little signed hash an editor mints from the new Invite… menu (7/30/90-day or non-expiring) that's appended to the page URL (?invite=inv1.<exp>.<sig>) and shared. The hash is HMAC-bound to that one page's slug + expiry, redeems into a per-page cookie so the page stays unlocked after the parameter is gone, and is stateless — rotatingADMIN_SECRETrevokes every link at once.Ports the protection system already proven in keyboard-docs, and additionally gates this repo's extra content surfaces: search-index bodies,
llms.txt/llms-full.txt, the/llms.mdxmarkdown mirrors, the AI assistant's retrieval, and the/mcpserver's search/read/list tools all exclude protected pages. New Access → "Protected pages" docs page explains the flow.Also adds a second docs page (separate commit): Editing → "Contributing with Claude Code" — the practical contributor workflow for local Claude Code (setup, asking for pages, the
/new-pageand/draft-pageskills, verification, and the four review paths), complementing the existing "Why docs.dev + Claude Code" page.Security considerations
This PR is an authorization feature; the gate is enforced server-side on the Worker:
/api/reader/content, which requires a valid reader cookie (HMAC ofADMIN_SECRET+READER_PIN), a valid invite for that slug, or a signed-in editor session. The prerendered page is a lock shell — content never ships in static HTML.invite-v1:<slug>:<exp>keyed byADMIN_SECRET, truncated to 128 bits; constant-time comparison; expiry covered by the signature so it can't be extended; version-prefixed (inv1.) and domain-separated from the reader-cookie HMAC. Minting requires an editor session. Trade-off: tokens are stateless, so there is no per-link revocation — expiry bounds a leaked link, and rotatingADMIN_SECRETrevokes everything.READER_PIN/ADMIN_SECRETunset, the respective unlock paths reject; nothing falls back to open.Verification
pnpm types:checkandpnpm lintclean; 34-check e2e matrix againstpnpm dev— lock shell never contains page content; anonymous content API → 401; minting requires an admin session; an invite unlocks exactly its own page (cross-page attempts → 401); tampered expiry/signature → 401; cookie redemption and PIN unlock work; admins bypass;llms.txt/llms-full.txt/llms.mdx/search/MCPread_page+search_docs+list_pagesall exclude the protected test pages; public pages unaffected.Rollback
Revert the merge commit. (Any invite links handed out stop working once reverted; nothing server-side to clean up.)
Review attestation