G
YouTube TikTok Games
Skip to content

feat(login): add --id to sign in with Tempo ID - #318

Open
jxom wants to merge 4 commits into
mainfrom
jxom/login-id-flag
Open

jxom wants to merge 4 commits into
mainfrom
jxom/login-id-flag

Conversation

@jxom

@jxom jxom commented Nov 11, 2026

Copy link
Copy Markdown
Member

Problem

tempo wallet login always approves with a passkey in the wallet app. There is no way to sign in with Tempo ID from the CLI on mainnet or testnet.

Change

tempo wallet login --id adds tempo_id=true to the approval link the CLI prints and opens. The wallet app's approval page then offers Tempo ID's sign-in instead of a passkey. The wallet_connect request itself is unchanged, on whichever network --network selects.

  • --id is a new login option (src/schemas/login.ts), passed to startLogin, which rewrites verification_uri and verification_uri_complete in the registration before it is saved. So --no-wait, login status and the printed Continue at: line all show the same link.
  • docs/commands.md regenerated; changelog entry in .changelog/login-tempo-id.md.

The name is tempo_id, not id, because on the wallet's /remote approval pages id is the JSON-RPC request id and the page redirects it away.

Needs the wallet app to accept Tempo ID approvals of CLI logins on mainnet and testnet: https://github.com/tempoxyz/wallet/pull/2718. Until that ships, the page ignores tempo_id and approves with a passkey as before.

Validation

  • New test/login.test.ts cases on mainnet and testnet: the pending login's verification_url, the printed line and the saved registration carry tempo_id=true, the registered request names the right chain, and login status finishes the login.
  • pnpm typecheck, pnpm test:types and vp check pass.
  • Full vitest run: 343 failures here, the same count as on unchanged main (sessions and sqlite tests, no sqlite3 on this machine). One of them is login status > returns an approved login when its pending login cannot be cleared, which also fails on main here.
  • Against production: tempo wallet login --id --no-wait --no-browser --network testnet printed https://wallet.tempo.xyz/remote/rpc/wallet_connect?user_code=…&tempo_id=true, and that page renders (200) without dropping the parameter.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 11, 2026 •

Copy link
Copy Markdown
Codex Review Summary: ✅ Completed

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-11T21:54:39.642687Z 08877bf New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@tempoxyz-bot

tempoxyz-bot commented Nov 11, 2026 •

Copy link
Copy Markdown

👁️ Cyclops Security Review

✅ Reviewed 08877bf (latest) · Coverage: partial · ⚠️ 2 open findings · report
⚠️ Not checked: The external wallet approval-page implementation is outside the assigned repository and was not supplied as pinned source. The CLI's tempo_id parameter alone does not establish the page's authentication behavior or network support.
ℹ️ Not verifiable from the source alone (needs running code or deployed state): Windows caret escaping is covered only by generated-string assertions. Actual Node-to-cmd.exe-to-start parsing and the final browser URL were not observed; this surface is not ruled out. To verify it:

# Severity Finding Introduced Status
1 🟡 Medium Windows browser open of login --id link drops tempo_id at unescaped '&' a13be2e ✅ Fixed in 9f43a6f
2 🟢 Low Changelog and withTempoId JSDoc claim login status prints the approval link 57c0ead ✅ Fixed in 08877bf
3 ⚪ Informational login --id is silently ignored when a usable login is cached 57c0ead 🟠 Open
4 🟡 Medium refresh cannot request Tempo ID sign-in after login --id 57c0ead 🟠 Open

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Nothing blocking. The comments below are optional suggestions. There is no need to push a fix for them before merging.

Additional findings (outside the current diff — GitHub can't attach inline comments there):

  • 🟡 src/commands/login.ts — Users or agents who start a login with --id get retry commands without it, so a retry after an expiry or denial opens the passkey page. finishLogin builds login with continuationCommand(["wallet", "login"], network), and the E_LOGIN_EXPIRED, E_LOGIN_DENIED and logout-cancelled errors return that command. The pending login does not record that --id was chosen. Fix: save the choice in PendingLogin (or read tempo_id back from the saved verification_uri) and add --id to every wallet login retry command finishLogin builds, while bare logins keep the command they get today.

    Why this was flagged

    An agent runs tempo wallet login --id --no-wait. startLogin (src/commands/login.ts:168-170) adds tempo_id=true only to the URLs in the saved registration and stores no flag. The user lets the code expire, and login status reaches finishLogin. The retry command at src/commands/login.ts:196 is tempo wallet login --network <net> with no --id. It is returned as the next command for E_LOGIN_EXPIRED (line 238-243), E_LOGIN_DENIED (line 232-237) and the logout-cancelled E_USAGE (line 215-220). An agent that runs the returned command, as the _next contract invites, starts a passkey login, so the Tempo ID choice is silently lost. The base branch has no --id, so this only appears once the PR adds the option. No safeguard carries the choice forward: loginStatusHandler only gets network and the poll options, and PendingLogin has no field for it.

    Verification: nit. Trigger: a login started with --id ends denied, expired or cancelled by logout, and the user or agent runs the returned next command. Nothing breaks on the base branch, but the new flag's choice is dropped on retry. parsePendingLogin at src/commands/login.ts:171-181 saves no flag, and line 196 builds continuationCommand(["wallet", "login"], network) without --id.

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code review found no issues

No high-confidence issues detected in this change.

Comment thread src/commands/login.ts Resolved

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code review found no issues

No high-confidence issues detected in this change.

Comment thread .changelog/login-tempo-id.md Resolved

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code review found no issues

No high-confidence issues detected in this change.

Comment thread src/commands/login.ts
Comment on lines 99 to 100
const cached = await cachedLoginOutput(state, network);
if (cached) return cached;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Informational: login --id is silently ignored when a usable login is cached

loginHandler returns the cached whoami output before it reads options.id. With an unexpired access key on the target network, tempo wallet login --id exits 0 without registering a device code, printing a Tempo ID link, or telling the user the flag was dropped. First reported at 57c0ead; recheck at this head: still present.

Valid? React with 👍 / 👎.

Comment thread src/commands/login.ts
Comment on lines +168 to +170
if (options.id)
for (const key of ["verification_uri", "verification_uri_complete"])
if (key in registration) registration[key] = withTempoId(registration[key]);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Medium (exposure and trigger unconfirmed): refresh cannot request Tempo ID sign-in after login --id

tempo wallet login --id adds tempo_id=true only by rewriting the saved registration inside startLogin. tempo wallet refresh sends the same wallet_connect request but prints and opens the wallet's link unmodified and rejects --id, so a wallet logged in with Tempo ID gets a passkey approval link when it renews its access key.

Full finding

tempo wallet login --id adds tempo_id=true only by rewriting the saved registration inside startLogin. tempo wallet refresh sends the same wallet_connect request but prints and opens the wallet's link unmodified and rejects --id, so a wallet logged in with Tempo ID gets a passkey approval link when it renews its access key.

First reported at 57c0ead; recheck at this head: still present.

Valid? React with 👍 / 👎.

This branch has not been deployed

No deployments
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