Skip to content

feat: add read-only OAuth mode for safe autonomous tool use#205

Merged
scottlovegrove merged 3 commits intomainfrom
feat/read-only-oauth-mode
Mar 31, 2026
Merged

feat: add read-only OAuth mode for safe autonomous tool use#205
scottlovegrove merged 3 commits intomainfrom
feat/read-only-oauth-mode

Conversation

@scottlovegrove
Copy link
Copy Markdown
Collaborator

@scottlovegrove scottlovegrove commented Mar 31, 2026

Summary

  • Adds td auth login --read-only flag that authenticates with OAuth scope data:read, blocking all mutating API calls at the proxy layer
  • Stores auth metadata (mode, scope) in config file alongside the secure token storage introduced in feat: store auth tokens in OS credential storage #120
  • Creates a permissions module with a default-deny allowlist of ~33 safe API methods — unknown/new methods are blocked by default
  • Displays auth mode in td auth status (both human-readable and --json output)

Supersedes #110, reimplemented against current main to accommodate the secure store refactor (#120) and command directory split (#195).

Changes

Area Files
Auth metadata src/lib/auth.tsAuthMode, AuthMetadata, SaveApiTokenOptions types; getAuthMetadata(); metadata persistence in save/clear
OAuth scopes src/lib/oauth.tsreadOnly option on buildAuthorizationUrl
Permissions src/lib/permissions.ts (new) — KNOWN_SAFE_API_METHODS, ensureWriteAllowed(), isMutatingApiMethod(), isMutatingSyncPayload()
API proxy src/lib/api/core.ts — permission checks before mutating calls
Upload guard src/lib/api/uploads.ts — direct ensureWriteAllowed() (bypasses proxy)
Commands src/commands/auth/{index,login,token,status}.ts--read-only flag, metadata passing, mode display
Tests New: permissions.test.ts, oauth.test.ts; updated: auth.test.ts, lib-auth.test.ts
Docs README.md, src/lib/skills/content.ts, skills/todoist-cli/SKILL.md

Test plan

  • npm run type-check passes
  • All 1147 tests pass
  • npm run lint:check — 0 warnings, 0 errors
  • npm run format:check — all clean
  • Manual: td auth login --read-only → verify OAuth flow uses data:read scope
  • Manual: attempt mutating command in read-only mode → verify blocked with clear error
  • Manual: td auth status → verify mode displayed
  • Manual: td auth login (without --read-only) → verify switches back to read-write

🤖 Generated with Claude Code

Add support for authenticating with a read-only OAuth token (scope
`data:read`) via `td auth login --read-only`. When in read-only mode,
all mutating API calls are blocked at the proxy layer before they
reach the Todoist API.

- Add `--read-only` flag to `td auth login` with `data:read` scope
- Store auth metadata (mode, scope) in config file alongside secure
  token storage from #120
- Create permissions module with default-deny allowlist of safe API
  methods — unknown/new methods are blocked by default
- Integrate permission checks into the API proxy and direct fetch
  calls (uploads)
- Display auth mode in `td auth status` (human + JSON output)
- Update README, skill content, and tests

Supersedes #110.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@scottlovegrove scottlovegrove self-assigned this Mar 31, 2026
@doistbot doistbot requested a review from pawelgrimm March 31, 2026 14:49
@scottlovegrove scottlovegrove added the 👀 Show PR PR must be reviewed before or after merging label Mar 31, 2026
Add step 3 to the add-command developer skill documenting that new
read-only SDK methods must be added to KNOWN_SAFE_API_METHODS in
src/lib/permissions.ts. The default-deny approach means unmapped
methods are automatically blocked in read-only mode.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Member

@doistbot doistbot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR introduces a read-only OAuth mode to safely restrict autonomous tool use by blocking mutating API calls through a proxy and an allowlist. The implementation is well-structured and thoughtfully integrates with the recent secure store refactor to provide robust safeguards. There are a couple of minor adjustments to consider, specifically exempting standard object prototype methods from being incorrectly flagged as mutating by the proxy, and using the explicit AuthMode type instead of a generic string to improve type safety.

Share FeedbackReview Logs

…e type

- Exempt standard Object.prototype methods (toString, valueOf, etc.)
  from being incorrectly treated as mutating API methods in the proxy
- Use explicit AuthMode type instead of string in formatAuthMode

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@scottlovegrove scottlovegrove merged commit 446756b into main Mar 31, 2026
4 checks passed
@scottlovegrove scottlovegrove deleted the feat/read-only-oauth-mode branch March 31, 2026 15:05
doist-release-bot bot added a commit that referenced this pull request Mar 31, 2026
## [1.34.0](v1.33.0...v1.34.0) (2026-03-31)

### Features

* add read-only OAuth mode for safe autonomous tool use ([#205](#205)) ([446756b](446756b))
@doist-release-bot
Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 1.34.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Copy link
Copy Markdown

@pawelgrimm pawelgrimm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

released 👀 Show PR PR must be reviewed before or after merging

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants