8000 fix(clipper): sign in, or use your API token, not only an import webhook's by adeelahmad · Pull Request #406 · adeelahmad/lense · GitHub
[go: up one dir, main page]

Skip to content {"props":{"docsUrl":"https://docs.github.com/get-started/accessibility/keyboard-shortcuts"}}

fix(clipper): sign in, or use your API token, not only an import webhook's - #406

Merged
adeelahmad merged 15 commits into
mainfrom
claude/project-thread-ylh3hl
Oct 17, 2026
Merged

adeelahmad merged 15 commits into
mainfrom
claude/project-thread-ylh3hl

Conversation

@adeelahmad
Copy link
Copy Markdown
Owner

Requested by Adeel · project thread

Description

Before: the web clipper took only an import webhook's token (lih_…). Pasting an API token (la_…) was refused with "Lens didn't recognise this token: make a new import webhook and paste its token", because POST /api/v1/hooks/import knew only hook tokens.

After: the clipper's options lead with Sign in. You enter the Lens address and press Enter, Lens asks you to allow the clipper (OAuth with PKCE, the same sign-in the side panel already had, now shared with it), and clips go into the namespace you pick. The popup offers every namespace you can add to. Use a token instead takes an API token with write access or a hook's token, told apart by prefix. When Lens refuses one, the clipper says why: unknown or revoked, read-only, a sign-in that ended, or a Lens too old to take API tokens.

How: POST /api/v1/hooks/import also takes the person's own token (an API token with write scope, an OAuth app's, or the web app's session), with ?namespace= naming one where they have the import permission. Without it, their only such namespace is used, and if there are several the 400 lists them. These pushes are audited as import.push by the person and aren't counted on any hook. A new GET /api/v1/hooks/import says where a token's pushes go (kind, namespace, namespaces, write), and the clipper's Check uses it. Against an older Lens (405) it falls back to the old empty-push check. A 401 now says which kind of token Lens didn't know. The address form /hooks/import/{token} still takes hook tokens only, so a person's token never ends up in a logged path.

Motivation and Context

Adeel's clipper rejected his API token. Agents and scripts acting as a person can now use the same push address with their own token.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change

Checklist:

  • The title is a Conventional Commit.
  • My code follows the code style of this project (ruff, mypy clean).
  • I added or updated tests: tests/api/test_import_hooks.py (API token, web session, OAuth app with and without write scope, namespace choice, read-only, path form refused, 401 wording per kind); extensions/browser/test/lens.test.js (namespace in the push, error wording, check via GET and the old-Lens fallback, popup choices).
  • Docs updated: docs/web-clipper.md (Setting it up), docs/api.md (Import webhooks), threat-model.md (new entry-point row), extension README.
  • CHANGELOG.md under Unreleased.

Done questions (AGENTS.md)

  • Goal: the clipper takes an API token, or signs in with one click; merge on green.
  • Agents: anything acting as a person pushes with their own token to POST /api/v1/hooks/import?namespace=; GET there says where. No MCP import tool exists yet (refine later).
  • Zero setup: OAuth sign-in is on by default (tokens.oauth_enabled); nothing new to install.
  • Fewest clicks: address then Enter (prefilled when the side panel is already signed in), Lens's consent page, done. No token copying.
  • Configurable: n/a, no new settings. The namespace pick is in the clipper's options and popup.
  • Light: n/a, no new dependencies.
  • Private and secure: tokens stay in the extension's local storage. Person tokens need write scope and the namespace's import permission and are header-only. Threat model row added.
  • Cost: n/a, no model calls.
  • User decides: existing hook destinations keep working unchanged (destinations from before are treated as hooks).
  • Upgrades: no stored-data change on the server. Old clipper settings read as hook destinations.
  • Honest: docs say what's built. Safari still pastes an API token (it can't show the consent page).
  • Tests, docs and generated files updated (make openapi tooling regenerated openapi.json and the client).
  • Open standards: OAuth 2.1 + PKCE; no new dependencies.
  • Reported in the thread. Refine later: one sign-in per browser (signing in to a second Lens replaces the first), no rename for destinations, an MCP tool for importing.

🤖 Generated with Claude Code

https://claude.ai/code/session_01NZxdXgdzoJfnSLju6B6Ygz


Generated by Claude Code

…ook's

The web clipper only took import webhook tokens (lih_...): pasting an API token (la_...) failed with "Lens didn't
recognise this token: make a new import webhook and paste its token".

- Lens: POST /api/v1/hooks/import also takes the person's own token (an API token with write access, an app's, or the
  web app's), with ?namespace= naming one they can import into (default: their only one). Audited as import.push, by
  the person. GET /api/v1/hooks/import says where a token's pushes go. 401s say which kind of token Lens didn't know;
  the address form still takes hook tokens only.
- Clipper: Sign in in the options (OAuth with PKCE, the side panel's own sign-in, shared with it), or paste an API
  token or a hook token, told apart by their prefix. The popup offers each namespace the person can add to.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NZxdXgdzoJfnSLju6B6Ygz
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NZxdXgdzoJfnSLju6B6Ygz
@adeelahmad adeelahmad self-assigned this Oct 15, 2026
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NZxdXgdzoJfnSLju6B6Ygz
…-ylh3hl

# Conflicts:
#	CHANGELOG.md
#	threat-model.yaml
Copy link
Copy Markdown
Owner Author

Clicks and keystrokes per feature failed on da43c4c: the computer-run graph-merge journey hit locator.waitFor: Timeout 20000ms exceeded. Every other journey passed on both devices. This PR doesn't touch the web app or the graph. It's the known slow-runner race where an entity reaches the graph only after the imports' jobs finish, and it also fails on main. #397 (merged) fixed it in ci/clicks/journeys.mjs by waiting for those jobs before the journey. I merged main into this branch in a841470 to bring that wait in.


Generated by Claude Code

claude added 10 commits October 15, 2026 12:27
…-ylh3hl

# Conflicts:
#	CHANGELOG.md
#	nextjs-frontend/openapi.json
#	threat-model.yaml
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NZxdXgdzoJfnSLju6B6Ygz
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NZxdXgdzoJfnSLju6B6Ygz
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NZxdXgdzoJfnSLju6B6Ygz
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NZxdXgdzoJfnSLju6B6Ygz
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NZxdXgdzoJfnSLju6B6Ygz
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NZxdXgdzoJfnSLju6B6Ygz
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NZxdXgdzoJfnSLju6B6Ygz
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NZxdXgdzoJfnSLju6B6Ygz
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NZxdXgdzoJfnSLju6B6Ygz
@adeelahmad
adeelahmad merged commit d6c55fa into main Oct 17, 2026
16 checks passed
@adeelahmad
adeelahmad deleted the claude/project-thread-ylh3hl branch October 17, 2026 05:02
adeelahmad pushed a commit that referenced this pull request Oct 18, 2026
…ay and clipper sign-in as built

Since the last README refresh, #474, #484, #510, #511, #497, #495, #406, #516, #517
and #491 merged. The README's built list now says a conversation exports as Markdown,
PDF or JSON and its answers, questions and code copy; a Tools chip picks an answer's
tools, limit and namespaces; sandbox runs open under the answer with downloads, and
Settings starts the gateway; deep research plans, runs and returns a cited report;
ready-made MCP servers (the browser, GitHub) and the optional containers start from
the web app; and the web clipper signs in or takes an API token. Each has its checks
in docs/requirements.md. In progress drops the merged PRs and lists the open feature
PRs; the Planned proof item keeps only the Raspberry Pi timing (#481 and #482 are
closed); the docs index links requirements and checks, and published feeds.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HDx7PPUauyjMn1LZs8JAsS
adeelahmad pushed a commit that referenced this pull request Oct 18, 2026
…ay and clipper sign-in as built

Since the last README refresh, #474, #484, #510, #511, #497, #495, #406, #516, #517,
#491, #400 and #506 merged. The README's built list now says the assistant answers
questions about Lens itself; a conversation exports as Markdown, PDF or JSON and its
answers, questions and code copy; a Tools chip picks an answer's tools, limit and
namespaces; sandbox runs open under the answer with downloads, and Settings starts the
gateway; deep research plans, runs and returns a cited report; ready-made MCP servers,
the MCP servers page and the optional containers start from the web app; and the web
clipper signs in or takes an API token. Each has its checks in docs/requirements.md.
In progress lists only open PRs; the Nebula mesh (#546, merged, partly built) moves to
Planned with what's next; the Planned proof item keeps only the Raspberry Pi timing;
the docs index links requirements and checks, and published feeds.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HDx7PPUauyjMn1LZs8JAsS
adeelahmad added a commit that referenced this pull request Oct 18, 2026
…ay and clipper sign-in as built (#536)

Since the last README refresh, #474, #484, #510, #511, #497, #495, #406, #516, #517,
#491, #400 and #506 merged. The README's built list now says the assistant answers
questions about Lens itself; a conversation exports as Markdown, PDF or JSON and its
answers, questions and code copy; a Tools chip picks an answer's tools, limit and
namespaces; sandbox runs open under the answer with downloads, and Settings starts the
gateway; deep research plans, runs and returns a cited report; ready-made MCP servers,
the MCP servers page and the optional containers start from the web app; and the web
clipper signs in or takes an API token. Each has its checks in docs/requirements.md.
In progress lists only open PRs; the Nebula mesh (#546, merged, partly built) moves to
Planned with what's next; the Planned proof item keeps only the Raspberry Pi timing;
the docs index links requirements and checks, and published feeds.


Claude-Session: https://claude.ai/code/session_01HDx7PPUauyjMn1LZs8JAsS

Co-authored-by: Adeel Ahmad <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

0