Skip to content

feat(cli): store access tokens securely in OS keyring#746

Open
toiroakr wants to merge 12 commits intomainfrom
feat/secure-token-storage
Open

feat(cli): store access tokens securely in OS keyring#746
toiroakr wants to merge 12 commits intomainfrom
feat/secure-token-storage

Conversation

@toiroakr
Copy link
Contributor

@toiroakr toiroakr commented Mar 12, 2026

Summary

  • Add opt-in secure token storage via OS keyring (macOS Keychain, Windows Credential Manager, Linux Secret Service) using @napi-rs/keyring
  • Keyring is disabled by default — set TAILOR_USE_KEYRING=1 to enable, keeping V1 config format for backward compatibility with older SDK versions
  • Introduce V2 config schema with min_sdk_version (semver validated via z.templateLiteral), latest_version, and latest_min_sdk_version fields for future version migration announcements
  • readPlatformConfig() and loadWorkspaceId() are now async — enables SDK version comparison for latest_min_sdk_version warning
  • writePlatformConfig converts V2→V1 for disk by default; V2 only written when TAILOR_USE_KEYRING is set
  • await token revocation in logout with tokenTypeHint for machine user support
  • Clear error messages for unsupported config versions with LATEST_CONFIG_VERSION constant

Design decisions

  • V1 compatibility by default: Users with multiple projects on different SDK versions won't be broken. Keyring is opt-in via TAILOR_USE_KEYRING env var until a safe migration path is established.
  • min_sdk_version in V2 config: Written to disk so older SDKs encountering a newer config can tell the user exactly which version to update to.
  • latest_version / latest_min_sdk_version: Optional fields for pre-announcing future config version migrations. When present and the current SDK is older than latest_min_sdk_version, a warning is shown.
  • Async readPlatformConfig: Required to read SDK version from package.json for the latest_min_sdk_version comparison. All callers were already in async contexts.

🤖 Generated with Claude Code

ref: #674 (comment)

@toiroakr toiroakr requested a review from remiposo as a code owner March 12, 2026 14:50
@changeset-bot
Copy link

changeset-bot bot commented Mar 12, 2026

🦋 Changeset detected

Latest commit: 963d850

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 2 packages
Name Type
@tailor-platform/sdk Minor
@tailor-platform/create-sdk Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

devin-ai-integration[bot]

This comment was marked as resolved.

@toiroakr toiroakr force-pushed the feat/secure-token-storage branch from 0dad18a to b047bed Compare March 12, 2026 15:03
@toiroakr toiroakr changed the base branch from main to feat/platform-token March 12, 2026 15:03
@pkg-pr-new
Copy link

pkg-pr-new bot commented Mar 12, 2026

Open in StackBlitz

npm i https://pkg.pr.new/@tailor-platform/create-sdk@746

commit: 963d850

@github-actions

This comment has been minimized.

Copy link
Contributor

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

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

Devin Review found 1 new potential issue.

View 8 additional findings in Devin Review.

Open in Devin Review

@toiroakr toiroakr force-pushed the feat/platform-token branch 4 times, most recently from 7437b49 to 51b0d46 Compare March 17, 2026 12:28
- Add @napi-rs/keyring for OS keyring integration (macOS Keychain,
  Windows Credential Manager, Linux Secret Service)
- Introduce V2 config schema with discriminated union (keyring | file)
- V1→V2 migration keeps tokens in file; keyring upgrade on next login/refresh
- Both regular and machine user login store tokens via keyring when available
- Add resolveTokens/saveUserTokens/deleteUserTokens async helpers
- Fall back to file-based storage with warning when keyring unavailable

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@toiroakr toiroakr force-pushed the feat/secure-token-storage branch from b047bed to b9113a0 Compare March 18, 2026 02:06
@toiroakr toiroakr marked this pull request as draft March 18, 2026 06:45
…ecure-token-storage

# Conflicts:
#	packages/sdk/src/cli/commands/login.ts
#	packages/sdk/src/cli/commands/logout.ts
…ecure-token-storage

# Conflicts:
#	packages/sdk/src/cli/commands/logout.ts
Keep V1 config format on disk to avoid breaking older SDK versions.
Keyring storage can be opted into via TAILOR_USE_KEYRING env var.
readPlatformConfig no longer writes back V2 format to disk.
Base automatically changed from feat/platform-token to main March 19, 2026 00:43
Enable SDK version check for latest_min_sdk_version warning.
Add latest_version and latest_min_sdk_version optional fields
to V2 config schema for future version migration announcements.
@github-actions

This comment has been minimized.

devin-ai-integration[bot]

This comment was marked as resolved.

…er refs

Replace lexicographic string comparison with proper semver numeric
comparison for latest_min_sdk_version check. Clear current_user in
toV1ForDisk when the referenced user is keyring-only and would be dropped.
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@toiroakr toiroakr force-pushed the feat/secure-token-storage branch from 6856d63 to 963d850 Compare March 23, 2026 05:20
@github-actions
Copy link

Code Metrics Report (packages/sdk)

main (08b4d38) #746 (31dee51) +/-
Coverage 55.8% 55.9% +0.0%
Code to Test Ratio 1:0.4 1:0.4 -0.1
Details
  |                    | main (08b4d38) | #746 (31dee51) |  +/-  |
  |--------------------|----------------|----------------|-------|
+ | Coverage           |          55.8% |          55.9% | +0.0% |
  |   Files            |            324 |            325 |    +1 |
  |   Lines            |          10320 |          10405 |   +85 |
+ |   Covered          |           5764 |           5820 |   +56 |
- | Code to Test Ratio |          1:0.4 |          1:0.4 |  -0.1 |
  |   Code             |          61615 |          61996 |  +381 |
+ |   Test             |          24673 |          24817 |  +144 |

Code coverage of files in pull request scope (20.8% → 22.5%)

Details
Files Coverage +/- Status
example/e2e/globalSetup.ts 25.0% 0.0% modified
packages/sdk/src/cli/commands/apply/apply.ts 90.5% 0.0% modified
packages/sdk/src/cli/commands/executor/get.ts 11.1% 0.0% modified
packages/sdk/src/cli/commands/executor/jobs.ts 0.6% 0.0% modified
packages/sdk/src/cli/commands/executor/list.ts 5.5% 0.0% modified
packages/sdk/src/cli/commands/executor/trigger.ts 12.6% 0.0% modified
packages/sdk/src/cli/commands/executor/webhook.ts 9.5% 0.0% modified
packages/sdk/src/cli/commands/function/logs.ts 2.5% 0.0% modified
packages/sdk/src/cli/commands/function/test-run.ts 1.3% 0.0% modified
packages/sdk/src/cli/commands/login.ts 8.0% 0.0% modified
packages/sdk/src/cli/commands/logout.ts 5.8% -1.9% modified
packages/sdk/src/cli/commands/machineuser/list.ts 6.2% 0.0% modified
packages/sdk/src/cli/commands/machineuser/token.ts 5.5% 0.0% modified
packages/sdk/src/cli/commands/oauth2client/get.ts 6.2% 0.0% modified
packages/sdk/src/cli/commands/oauth2client/list.ts 7.1% 0.0% modified
packages/sdk/src/cli/commands/open.ts 14.2% 0.0% modified
packages/sdk/src/cli/commands/profile/create.ts 5.5% 0.0% modified
packages/sdk/src/cli/commands/profile/delete.ts 14.2% 0.0% modified
packages/sdk/src/cli/commands/profile/list.ts 12.5% 0.0% modified
packages/sdk/src/cli/commands/profile/update.ts 3.8% 0.0% modified
packages/sdk/src/cli/commands/remove.ts 2.0% 0.0% modified
packages/sdk/src/cli/commands/secret/create.ts 5.2% 0.0% modified
packages/sdk/src/cli/commands/secret/delete.ts 5.5% 0.0% modified
packages/sdk/src/cli/commands/secret/list.ts 6.6% 0.0% modified
packages/sdk/src/cli/commands/secret/update.ts 6.2% 0.0% modified
packages/sdk/src/cli/commands/secret/vault/create.ts 10.0% 0.0% modified
packages/sdk/src/cli/commands/secret/vault/delete.ts 5.5% 0.0% modified
packages/sdk/src/cli/commands/secret/vault/list.ts 9.0% 0.0% modified
packages/sdk/src/cli/commands/show.ts 9.0% 0.0% modified
packages/sdk/src/cli/commands/staticwebsite/deploy.ts 3.9% 0.0% modified
packages/sdk/src/cli/commands/staticwebsite/get.ts 7.1% 0.0% modified
packages/sdk/src/cli/commands/staticwebsite/list.ts 6.2% 0.0% modified
packages/sdk/src/cli/commands/tailordb/erd/utils.ts 0.0% 0.0% modified
packages/sdk/src/cli/commands/tailordb/migrate/set.ts 1.8% 0.0% modified
packages/sdk/src/cli/commands/tailordb/migrate/status.ts 2.2% 0.0% modified
packages/sdk/src/cli/commands/tailordb/truncate.ts 69.8% 0.0% modified
packages/sdk/src/cli/commands/user/current.ts 14.2% 0.0% modified
packages/sdk/src/cli/commands/user/list.ts 7.6% 0.0% modified
packages/sdk/src/cli/commands/user/pat/create.ts 9.0% 0.0% modified
packages/sdk/src/cli/commands/user/pat/delete.ts 12.5% 0.0% modified
packages/sdk/src/cli/commands/user/pat/list.ts 4.3% 0.0% modified
packages/sdk/src/cli/commands/user/pat/update.ts 8.3% 0.0% modified
packages/sdk/src/cli/commands/user/switch.ts 14.2% 0.0% modified
packages/sdk/src/cli/commands/workflow/executions.ts 0.9% 0.0% modified
packages/sdk/src/cli/commands/workflow/get.ts 5.8% 0.0% modified
packages/sdk/src/cli/commands/workflow/list.ts 7.6% 0.0% modified
packages/sdk/src/cli/commands/workflow/resume.ts 4.1% 0.0% modified
packages/sdk/src/cli/commands/workflow/start.ts 20.0% 0.0% modified
packages/sdk/src/cli/commands/workspace/app/health.ts 13.3% 0.0% modified
packages/sdk/src/cli/commands/workspace/app/list.ts 6.4% 0.0% modified
packages/sdk/src/cli/commands/workspace/create.ts 7.3% 0.0% modified
packages/sdk/src/cli/commands/workspace/delete.ts 6.6% 0.0% modified
packages/sdk/src/cli/commands/workspace/get.ts 11.7% 0.0% modified
packages/sdk/src/cli/commands/workspace/user/invite.ts 15.3% 0.0% modified
packages/sdk/src/cli/commands/workspace/user/list.ts 6.8% 0.0% modified
packages/sdk/src/cli/commands/workspace/user/remove.ts 11.1% 0.0% modified
packages/sdk/src/cli/commands/workspace/user/update.ts 15.3% 0.0% modified
packages/sdk/src/cli/query/index.ts 47.0% 0.0% modified
packages/sdk/src/cli/shared/context.ts 58.3% -0.9% modified
packages/sdk/src/cli/shared/token-store.ts 90.0% +90.0% added

SDK Configure Bundle Size

main (08b4d38) #746 (31dee51) +/-
configure-index-size 10.74KB 10.74KB 0KB
dependency-chunks-size 34KB 34KB 0KB
total-bundle-size 44.74KB 44.74KB 0KB

Runtime Performance

main (08b4d38) #746 (31dee51) +/-
Generate Median 2,632ms 2,607ms -25ms
Generate Max 2,653ms 2,648ms -5ms
Apply Build Median 2,648ms 2,639ms -9ms
Apply Build Max 2,674ms 2,752ms 78ms

Type Performance (instantiations)

main (08b4d38) #746 (31dee51) +/-
tailordb-basic 43,028 43,028 0
tailordb-optional 3,927 3,927 0
tailordb-relation 4,071 4,071 0
tailordb-validate 2,925 2,925 0
tailordb-hooks 5,790 5,790 0
tailordb-object 11,571 11,571 0
tailordb-enum 2,793 2,793 0
resolver-basic 9,239 9,239 0
resolver-nested 25,626 25,626 0
resolver-array 17,862 17,862 0
executor-schedule 4,244 4,244 0
executor-webhook 883 883 0
executor-record 4,847 4,847 0
executor-resolver 4,273 4,273 0
executor-operation-function 877 877 0
executor-operation-gql 879 879 0
executor-operation-webhook 898 898 0
executor-operation-workflow 2,290 2,290 0

Reported by octocov

Copy link
Contributor

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

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

Devin Review found 1 new potential issue.

View 17 additional findings in Devin Review.

Open in Devin Review

@toiroakr toiroakr marked this pull request as ready for review March 23, 2026 07:08
@tailor-platform tailor-platform deleted a comment from claude bot Mar 23, 2026
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