--- phase: 03-operator-experience plan: 02 subsystem: ui tags: [slack, oauth, whatsapp, onboarding, byo-keys, nextjs, react-hook-form, tanstack-query, shadcn-ui] # Dependency graph requires: - phase: 03-operator-experience plan: 01 provides: Slack OAuth endpoints, WhatsApp connect endpoint, channel test endpoint, LLM key CRUD endpoints (Plan 01) provides: - Slack OAuth callback route handler at /api/slack/callback - Onboarding wizard page at /onboarding (3-step stepper via URL searchParams) - OnboardingStepper component with numbered steps, active/completed/pending states - Step 1 - ConnectChannel: Slack OAuth button + WhatsApp manual form with step-by-step instructions - Step 2 - ConfigureAgent: agent list with Agent Designer link, Next enabled only with active agent - Step 3 - TestMessage: per-channel Send Test Message buttons, required step, no Go Live button - BYO API Key settings page at /settings/api-keys (list, add, delete with confirmation) - TanStack Query hooks: useSlackInstallUrl, useConnectWhatsApp, useSendTestMessage, useChannelConnections, useLlmKeys, useAddLlmKey, useDeleteLlmKey - API types: SlackInstallResponse, ChannelConnection, WhatsAppConnectRequest/Response, TestMessageResponse, LlmKey, LlmKeyCreate - API Keys link in sidebar nav affects: - 03-03 (billing UI — shares the same nav, portal patterns) - 03-04 (cost dashboard — same portal conventions) # Tech tracking tech-stack: added: - recharts (was in package.json but not installed — installed to unblock portal build) patterns: - Onboarding wizard step state via URL searchParams (step=1|2|3) — shareable/refreshable - Auto-advance on successful channel connect (1500ms delay + router.push) - Slack OAuth: fetch install URL from backend, then window.location.href redirect to Slack - WhatsApp: inline expandable form with humanized step-by-step credential instructions - BYO key display pattern: show ...{key_hint} (last 4 chars) — never plaintext - Dialog for add form and delete confirmation using @base-ui/react Dialog pattern key-files: created: - packages/portal/app/api/slack/callback/route.ts - packages/portal/components/onboarding-stepper.tsx - packages/portal/app/(dashboard)/onboarding/page.tsx - packages/portal/app/(dashboard)/onboarding/steps/connect-channel.tsx - packages/portal/app/(dashboard)/onboarding/steps/configure-agent.tsx - packages/portal/app/(dashboard)/onboarding/steps/test-message.tsx - packages/portal/app/(dashboard)/settings/api-keys/page.tsx modified: - packages/portal/lib/api.ts (added channel and LLM key types) - packages/portal/lib/queries.ts (added 7 new hooks) - packages/portal/components/nav.tsx (added API Keys nav link) key-decisions: - "Agent goes live automatically after test message — is_active is true by default, no separate Go Live button (per user decision)" - "Test message step is REQUIRED — no skip button (per user decision)" - "BYO API keys are tenant-level (v1 simplicity) — page reads tenant_id from searchParams" - "Onboarding wizard uses URL searchParams for step state — step=1|2|3 makes URLs shareable and browser-back friendly" - "Slack OAuth redirect: window.location.href = authorize_url — NOT router.push, Slack must redirect the actual browser tab" - "Portal git initialized as submodule with its own .git repo — enables atomic per-task commits in portal" patterns-established: - "Submodule commit pattern: portal files committed inside packages/portal .git, then parent repo git add packages/portal to update gitlink" - "Onboarding stepper: numbered circles + connector lines, completed steps show Check icon, active step shows ring-primary" - "WhatsApp form: expandable card pattern — Button to expand, form appears inline, Cancel collapses" requirements-completed: [PRTA-03, PRTA-04, LLM-03] # Metrics duration: ~35min completed: 2026-03-23 --- # Phase 3 Plan 02: Channel Connection Wizard and BYO API Key Management Summary **Slack OAuth callback route, 3-step onboarding wizard (connect channel, configure agent, test message), and BYO LLM API key management page — operators can connect Slack/WhatsApp and go live from the portal** ## Performance - **Duration:** ~35 min - **Started:** 2026-03-23 - **Completed:** 2026-03-23 - **Tasks:** 2 of 3 (Task 3 is a human-verify checkpoint) - **Files created/modified:** 10 ## Accomplishments - Slack OAuth callback route at `/api/slack/callback` — proxies code+state to FastAPI, redirects to onboarding step 2 on success - 3-step onboarding wizard using URL searchParams for step state (shareable/refreshable) - OnboardingStepper component with numbered circles, completed check marks, connector lines - Step 1: ConnectChannel with Slack OAuth button (fetches install URL, redirects browser) + expandable WhatsApp form with step-by-step credential instructions - Step 2: ConfigureAgent shows existing agents with link to Agent Designer; Next disabled until active agent exists - Step 3: TestMessage sends POST to backend per channel, shows loading/success/error states, no Go Live button (per user decision) - BYO API key settings page at `/settings/api-keys` — table showing provider/label/key_hint/date, Add dialog (provider select + label + masked key), delete confirmation - 7 new TanStack Query hooks for channels and LLM keys - Navigation sidebar updated with API Keys link - Portal builds successfully (15 routes, TypeScript clean) ## Task Commits Portal commits (packages/portal): 1. **Task 1: Slack OAuth callback, onboarding wizard, channel queries** - `120dc85` (feat) 2. **Task 2: BYO API key settings page and nav link** - `8f4247b` (feat) Parent repo commit (portal gitlink update): 3. **feat(03-02)**: `11c1e52` — updates portal submodule reference ## Files Created - `packages/portal/app/api/slack/callback/route.ts` — Slack OAuth GET handler, proxies to FastAPI - `packages/portal/components/onboarding-stepper.tsx` — step progress indicator component - `packages/portal/app/(dashboard)/onboarding/page.tsx` — 3-step wizard entry page - `packages/portal/app/(dashboard)/onboarding/steps/connect-channel.tsx` — Slack + WhatsApp connect forms - `packages/portal/app/(dashboard)/onboarding/steps/configure-agent.tsx` — agent review / Agent Designer link - `packages/portal/app/(dashboard)/onboarding/steps/test-message.tsx` — test message sender, celebration on success - `packages/portal/app/(dashboard)/settings/api-keys/page.tsx` — BYO key CRUD page ## Files Modified - `packages/portal/lib/api.ts` — added SlackInstallResponse, ChannelConnection, WhatsAppConnect*, TestMessageResponse, LlmKey, LlmKeyCreate types - `packages/portal/lib/queries.ts` — added useSlackInstallUrl, useConnectWhatsApp, useSendTestMessage, useChannelConnections, useLlmKeys, useAddLlmKey, useDeleteLlmKey - `packages/portal/components/nav.tsx` — added Key import and API Keys nav item ## Decisions Made - **Agent auto-live**: `is_active: true` by default — operator does not need a separate "Go Live" step after test message succeeds - **Test required**: Test message step has no skip button — connectivity must be verified before operators leave the wizard - **Tenant-level API keys**: BYO key page reads `?tenant_id=` from URL (v1 simplicity, could be per-agent in future) - **Step state in URL**: `step=1|2|3` in searchParams — survives page refresh, supports browser back/forward, shareable - **Portal git initialized**: Created packages/portal/.git repo to enable atomic commits — previously portal was an orphaned gitlink with no local git history ## Deviations from Plan ### Auto-fixed Issues **1. [Rule 3 - Blocking] recharts not installed despite being in package.json** - **Found during:** Task 1 verification (portal build) - **Issue:** `recharts` was listed in package.json (added in a previous phase plan) but never installed. This caused `Module not found: Can't resolve 'recharts'` build error blocking the Task 1 verification - **Fix:** Ran `npm install recharts` in packages/portal - **Files modified:** packages/portal/package-lock.json - **Commit:** 120dc85 (Task 1 commit) **2. [Rule 3 - Blocking] Portal had no local git repo (orphaned gitlink)** - **Found during:** Task 1 commit attempt - **Issue:** The parent repo tracks `packages/portal` as a git submodule gitlink (commit 29a27100). However, `packages/portal` had no `.git` directory, making it impossible to run `git add` on portal files - **Fix:** Initialized git repo in `packages/portal` with `git init` + `git add .` + `git commit`, then updated the parent's gitlink reference - **Impact:** Portal now has its own git history with proper atomic commits --- **Total deviations:** 2 auto-fixed (Rule 3 — blocking issues) **Impact on plan:** Both fixes were necessary for the build to succeed and commits to be made; no scope change. ## Self-Check: PASSED All 7 artifact files exist and portal builds successfully (exit 0, 15 routes, TypeScript clean). --- *Phase: 03-operator-experience* *Completed: 2026-03-23*