fix(auth): quiet interactive signup output - #57
Conversation
Raw envelopes (user object, session token, landing) now print only in JSON mode where they are the scripting contract; a terminal gets a clean 'Signed in as <email>'. promptEnter switches from p.text (which renders a dim 'undefined' on empty submit) to a Continue/Cancel confirm. The next-steps box is suppressed under the installer, which owns that journey. The existing-verified-account path now persists a default workspace like the fresh path, so the installer's key mint no longer dies on re-authenticated accounts. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Verified this against the PR head (7109dd8) by running it, not just reading the diff — repro'd all four claimed fixes live:
- Text mode no longer leaks token/user object/
undefined— confirmedemitResult()(src/commands/auth/signup.ts:201-206) gates all 7 formerformatOutputcall sites behindconfig.output === 'json'. Ran a live repro against the existing-verified-account (re-auth) path withoutput: 'text': no token, no raw user object, noundefinedin output. - "Signed in as
<email>." confirmed printed (signup.ts:225,:311). - Next-steps box suppressed under installer —
underInstaller()(signup.ts:208-213) checksPOLYLANE_ONBOARDING_RUN; confirmed live: box appears without the env var, disappears with it set, while "Signed in as ..." still prints either way. - Workspace persistence fix for re-authenticated accounts — confirmed via
git show 36c6b0f:src/commands/auth/signup.tsthat the pre-PR existing-verified-account branch never calledpersistDefaultWorkspace; the PR head adds it (signup.ts:301). Confirmed live:config.jsonnow getsworkspace_idwritten on that branch, which it didn't before.persistDefaultWorkspaceis wrapped in try/catch (non-fatal) and its innerselectWorkspaceshort-circuits under non-interactive mode, so no regression risk to scripted/agent invocations. - CI green (3/3), and I independently reproduced clean
npm ci/ codegen / typecheck / lint / full test suite (283/283, 0 fail) locally against this head. - No leftover debug prints found (
console.log/console.errorgrep acrosssrc/is empty); the verbose HTTP logger already redactsAuthorization/x-api-keyand never logs response bodies, unaffected by this change.
One real gap I'd like addressed before merge: none of this PR's own behavioral claims are covered by its test diff. The only test change is an assertion-string update (test/signup.test.ts:145). Specifically missing:
- A
output: 'text'test asserting the token/user object/undefineddo NOT appear in output for the existing-verified-account path (the exact regression this PR fixes). - A test for
"Signed in as <email>."appearing. - A test for
underInstaller()/POLYLANE_ONBOARDING_RUNsuppressing the Next-steps box. - A test asserting
persistDefaultWorkspace/config.json.workspace_idis now written on the existing-verified-account re-auth branch — the current persistence test (test/signup.test.ts:226-254) only covers the--code(first-time) path, which already worked before this PR.
Given the whole point of this PR is fixing a silent session-token leak, I'd rather see it locked down with tests than rely on manual re-verification next time something touches this file. Happy to re-review once those land — the fix itself is correct and I found no functional regressions.
Non-blocking follow-up (pre-existing, not introduced by this PR): JSON-mode/scripted output is still polluted by clack's intro/note/outro writing directly to stdout regardless of config.output (confirmed in node_modules/@clack/prompts, and confirmed this predates this PR via the base commit). Worth a separate follow-up given the PR's own framing of JSON as "the data contract for scripts."
Generated by Claude Code
Covers the review's four asks: no token/user-object/undefined in text mode, the JSON envelope still emitted for scripts, workspace_id persisted on re-auth, and the next-steps box suppressed under the installer. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Added the requested test coverage — new
292/292 passing, typecheck + lint clean. Agreed on the clack |
There was a problem hiding this comment.
LGTM: round-2 adds real test coverage for all four round-1 asks, and everything is green.
Verified against head ded76ab90764ecb82e5ee8f869f1879b7ec3a08f (fetched fresh via git fetch origin pull/57/head, confirmed git rev-parse HEAD matches the PR API's head SHA).
Diff since the round-1 fix (7109dd8): purely additive — +76/-0 in test/signup.test.ts only. No production code changed this round, so the previously-verified fixes in src/commands/auth/signup.ts and src/utils/prompt.ts are untouched.
New test suite (auth signup existing-account re-auth, test/signup.test.ts:210-282) — checked each assertion is real, not a smoke test:
- Text mode: asserts
!output.includes('tok_signup'),!output.includes('emailVerified'),!output.includes('undefined'), andoutput.includes('Signed in as dev@acme.com.')— exercises the exactuser.emailVerifiedbranch inemailSignup(signup.ts:299-312). - JSON mode: asserts the envelope (
tok_signup+emailVerified) IS present, confirmingemitResultonly gates in text mode, not silently dropping data everywhere. persistDefaultWorkspace: assertsconfig.json'sworkspace_idactually gets written on the re-auth branch specifically (signup.ts:308, the newawait persistDefaultWorkspace(config)call) — this is the exact line that fixes the installer'scredential_mintfailure from round 1.- Next-steps suppression: asserts
'Onboarding (in order)'present standalone and absent withPOLYLANE_ONBOARDING_RUNset, with the outro message still shown either way, and the env var is cleaned up inbeforeEach/finallyso it can't leak into other suites.
Grepped all callers of the changed helpers (emitResult, underInstaller, persistDefaultWorkspace, promptEnter, finishEmailSignIn) — emitResult/underInstaller are private to signup.ts with no other call sites to break; persistDefaultWorkspace's other call site (the --code verification path, signup.ts:222) is already covered by the pre-existing auth signup --code describe block. promptEnter's p.confirm({ active, inactive }) shape matches @clack/prompts' actual ConfirmOptions type (checked node_modules/@clack/prompts/dist/index.d.ts) and returns Promise<boolean | symbol>, consistent with the result === false check.
Local checks (fresh run, not trusting CI or the PR body's stated numbers):
npm ci— clean, 0 vulnerabilitiesnpm run codegen— succeeded (277 paths, 168 types, 350 operations)npm run typecheck— clean, no errorsnpm run lint— clean, no errors (src/ + codegen/)npm run test— 292 tests, 292 pass, 0 fail, 0 cancelled (matches the author's comment claim exactly; the PR description's stale "288/288" is from before this round's test-only commit)
CI: all 3 check runs green (Test & typecheck on Node 20.x/22.x/24.x), which also cover the npm run build + dist smoke-test leg that I didn't need to run locally since this diff doesn't touch build.ts/codegen//skill/SKILL.md/packaging.
No regressions found. The pre-existing clack intro/note/outro-in-JSON-mode noise remains a known, separate follow-up (author acknowledged it in their comment) and is not part of this PR's scope.
Generated by Claude Code
There was a problem hiding this comment.
Auto-approved: Claude reviewed this PR and posted an LGTM verdict (see its review). A repo admin enabled this via the auto-approve workflow.
Generated by Claude Code
|
Updated to build on #58: the next-steps suppression now reads |
|
Correction to my earlier comment: this PR merged before the refactor landed, so the |
From live install-flow testing (screenshots in the onboarding thread): interactive email sign-in dumped the raw API envelope — full user object, the session token in plaintext, and the landing table — plus a stray dim
undefinedunder the terms gate, and the CLI's own Next-steps box mid-install.--output json), where they are the data contract for scripts — the token still reaches pipes. A terminal now getsSigned in as <email>.promptEnteruses a Continue/Cancel confirm instead ofp.text: clack's text prompt renders a dimundefinedas its final value on an empty submit (verified against @clack/prompts in a PTY;defaultValuefixes the return value but not the render). Enter still continues; Ctrl-C or Cancel still aborts.installer setsPOLYLANE_HINTS=0` (the hints capability from feat(config): hints — a first-class switch for next-step guidance #58)) — the installer owns the post-sign-in journey.credential_mintfor a re-authenticated account (noconfig.jsonat all). It now runs the samepersistDefaultWorkspaceas the fresh-verification path.288/288 tests, typecheck and lint clean.
🤖 Generated with Claude Code