Skip to content

feat(kiloclaw) onboarding calendar connect step#3083

Open
St0rmz1 wants to merge 7 commits intomainfrom
feat/claw-calendar-connect-step
Open

feat(kiloclaw) onboarding calendar connect step#3083
St0rmz1 wants to merge 7 commits intomainfrom
feat/claw-calendar-connect-step

Conversation

@St0rmz1
Copy link
Copy Markdown
Contributor

@St0rmz1 St0rmz1 commented May 6, 2026

Summary

Add a Connect a calendar step to the KiloClaw onboarding wizard. New users see this between identity capture and channel selection. The step wraps the existing Google Calendar OAuth flow at /api/integrations/google/connect (read access only, no writes), with a Skip for now option that is always available.

To make the OAuth round trip land users back in the wizard rather than stranding them on Settings, this PR adds returnTo support to the Google OAuth state, connect, and callback routes. The signed state token validates returnTo against a strict relative path regex, blocks URI fragments, blocks path traversal segments (. / ..), and caps length at 2048 characters. The callback honors returnTo on both success and error paths.

The Connect button gates on the kiloclaw instance row existing in the DB (a fast write that completes shortly after provisioning kicks off, distinct from the slower Fly machine readiness). While the row is missing, the button reads "Setting up your instance…" and is disabled. Skip for now stays enabled throughout, so the user is never blocked.

After the OAuth round trip, the wizard hydrates local bot identity state from the persisted instance row so the user resumes at the calendar step instead of restarting from identity. A watchdog effect cleans the URL and surfaces a soft warning if hydration cannot complete within 5 seconds.

PostHog tracking covers the full funnel:

  • claw_setup_calendar_viewed (fires on render, matching the identity step pattern)
  • claw_setup_calendar_connect_clicked
  • claw_setup_calendar_oauth_completed
  • claw_setup_calendar_oauth_failed (reason allowlisted; unknown codes bucketed as unknown)
  • claw_setup_calendar_resumed (outcome: connected / error / unknown)
  • claw_setup_calendar_completed (with skipped and connected flags)

Verification

  • Provisioned a fresh kiloclaw instance through /claw/new. Identity step works as before. Calendar step renders with correct copy and the Recommended pill.
  • Clicked Connect Google Calendar within the first second of the calendar step rendering, before the kiloclaw row was visible. Button was disabled with "Setting up your instance…" copy. Once the row appeared, the button swapped to the active link.
  • Completed the Google OAuth consent flow with calendar readonly scope. Returned to /claw/new?step=calendar&success=google_connected. Wizard restored bot identity, set the step to calendar, showed a "Calendar connected" toast, and stripped the query params from the URL.
  • Cancelled the Google OAuth consent flow. Returned to /claw/new?step=calendar&error=access_denied. Wizard showed an error toast, fired claw_setup_calendar_oauth_failed with reason 'access_denied', and cleaned the URL.
  • Clicked Skip for now without connecting. Wizard advanced to channels.
  • Confirmed the existing Settings page Google connect flow still redirects to /claw/settings (returnTo unset, fallback path).
  • Confirmed crafted returnTo values are rejected before being baked into the signed state: //evil.example.com, https://evil.example.com/foo, /claw/new#frag, /claw/../admin all fall through to the no-returnTo fallback.

Visual Changes

Before After

Reviewer Notes

  • The Connect button gates on flowState.instanceStatus !== null (the DB row written by the provision API), not on Fly machine readiness. The OAuth state itself just needs to know which instance to associate the connection with; the gateway being up is only required later when calendar data is actually read.
  • instanceReady is a required (non optional) prop on CalendarConnectStepView so any future caller that forgets to pass it fails typecheck. Same defense in depth pattern used for assistantEmoji previously.
  • The watchdog effect runs alongside the resume effect with a 5 second deadline. If botIdentity hydration cannot complete from flowState.instanceStatus, the watchdog cleans the URL and shows a soft warning rather than leaving stale ?step=calendar params lingering on the identity step.
  • buildGoogleRedirectPath in the callback route requires a pre-encoded key=value fragment; appendQueryParam takes raw key plus value and encodes both. JSDoc on each function states the contract; the parameter name is preEncodedQueryFragment for emphasis.
  • A separate race surfaced during testing where freshly provisioned instances default to always ask permissions even though the wizard sends never ask. Root cause is the controller boot reading env vars before the live config patch lands. Not in scope for this PR; tracked for a follow up.

@St0rmz1 St0rmz1 changed the title Feat/claw calendar connect step feat(kiloclaw) onboarding calendar connect step May 6, 2026
Comment thread apps/web/src/app/(app)/claw/components/ClawOnboardingFlow.state.ts
Comment thread apps/web/src/app/(app)/claw/components/ClawOnboardingFlow.tsx
@kilo-code-bot
Copy link
Copy Markdown
Contributor

kilo-code-bot Bot commented May 6, 2026

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Files Reviewed (3 files)
  • apps/web/src/app/(app)/claw/components/CalendarConnectStep.tsx
  • apps/web/src/app/(app)/claw/components/ClawOnboardingFakeWalkthrough.tsx
  • apps/web/src/app/(app)/claw/components/ClawOnboardingFlow.tsx
Resolved Findings
  • apps/web/src/app/(app)/claw/components/ClawOnboardingFakeWalkthrough.tsx now includes the calendar fake step label.
  • apps/web/src/app/(app)/claw/components/CalendarConnectStep.tsx disables calendar OAuth until an instance exists.

Reviewed by gpt-5.5-20260423 · 367,152 tokens

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.

1 participant