Skip to content

Commit 1cf70bf

Browse files
committed
Merge branch 'feat/account-management' into main
2 parents 34e0e08 + 3038566 commit 1cf70bf

File tree

107 files changed

+62978
-403
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

107 files changed

+62978
-403
lines changed

CONVEX_PLAN.md

Lines changed: 245 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,245 @@
1+
# Convex Integration Plan — Browser-AI Account & Payment System
2+
3+
## Context
4+
5+
The extension currently has no backend — all settings, API keys, and profiles live in `chrome.storage.local`. We want to add user accounts so we can accept payments. Users choose one of two paths on install:
6+
7+
1. **BYOK (Bring Your Own Key)** — free, works exactly as today
8+
2. **Paid Plan** — user pays a subscription, AI calls are proxied through Convex HTTP Actions using server-managed API keys
9+
10+
## Architecture Overview
11+
12+
```
13+
┌─────────────────────────────────────────────────┐
14+
│ Chrome Extension (packages/extension/) │
15+
│ │
16+
│ Sidepanel UI ──→ Convex Auth (login/signup) │
17+
│ ──→ chrome.storage.local (BYOK) │
18+
│ ──→ Convex DB (account, sub) │
19+
│ │
20+
│ Background ──→ BYOK: direct AI provider calls │
21+
│ ──→ Paid: Convex HTTP Action proxy │
22+
└──────────────────────┬──────────────────────────┘
23+
24+
┌──────────────────────▼──────────────────────────┐
25+
│ Convex Backend (packages/backend/convex/) │
26+
│ │
27+
│ Auth: Email/Password + Google + GitHub OAuth │
28+
│ DB: users, subscriptions, usage │
29+
│ HTTP Actions: /ai-proxy (streams AI responses) │
30+
│ HTTP Actions: /stripe-webhook │
31+
│ Actions: createCheckoutSession, manageSubscription│
32+
└─────────────────────────────────────────────────┘
33+
```
34+
35+
## Decisions Made
36+
37+
- **AI Proxy:** Convex HTTP Actions (all-in-one, no extra infra)
38+
- **Auth:** Email/Password + Google OAuth + GitHub OAuth via `@convex-dev/auth`
39+
- **Location:** `packages/backend/` (new monorepo package)
40+
- **Payment:** Stripe Checkout + webhook handling
41+
42+
---
43+
44+
## Phase 1: Convex Backend Setup
45+
46+
### 1.1 Create `packages/backend/`
47+
48+
```
49+
packages/backend/
50+
├── package.json
51+
├── convex/
52+
│ ├── schema.ts # DB schema
53+
│ ├── auth.ts # Auth config (providers)
54+
│ ├── http.ts # HTTP router (auth routes, stripe webhook, AI proxy)
55+
│ ├── users.ts # User queries/mutations
56+
│ ├── subscriptions.ts # Subscription queries/mutations
57+
│ ├── payments.ts # Stripe checkout action
58+
│ └── aiProxy.ts # AI proxy HTTP action
59+
└── .env.local # CONVEX_URL (gitignored)
60+
```
61+
62+
### 1.2 Schema (`convex/schema.ts`)
63+
64+
```typescript
65+
import { defineSchema, defineTable } from "convex/server";
66+
import { v } from "convex/values";
67+
import { authTables } from "@convex-dev/auth/server";
68+
69+
export default defineSchema({
70+
...authTables,
71+
72+
// authTables already creates `users` with name, email, etc.
73+
74+
subscriptions: defineTable({
75+
userId: v.id("users"),
76+
plan: v.union(v.literal("free"), v.literal("pro")),
77+
stripeCustomerId: v.optional(v.string()),
78+
stripeSubscriptionId: v.optional(v.string()),
79+
status: v.union(
80+
v.literal("active"),
81+
v.literal("canceled"),
82+
v.literal("past_due"),
83+
v.literal("inactive")
84+
),
85+
currentPeriodEnd: v.optional(v.number()),
86+
})
87+
.index("by_userId", ["userId"])
88+
.index("by_stripeCustomerId", ["stripeCustomerId"])
89+
.index("by_stripeSubscriptionId", ["stripeSubscriptionId"]),
90+
91+
usage: defineTable({
92+
userId: v.id("users"),
93+
month: v.string(), // "2026-02"
94+
requestCount: v.number(),
95+
tokensUsed: v.number(),
96+
})
97+
.index("by_userId_month", ["userId", "month"]),
98+
});
99+
```
100+
101+
### 1.3 Auth Config (`convex/auth.ts`)
102+
103+
- Providers: `Password`, `GitHub`, `Google`
104+
- Environment variables: `JWT_PRIVATE_KEY`, `JWKS`, `SITE_URL`, `AUTH_GITHUB_ID`, `AUTH_GITHUB_SECRET`, `AUTH_GOOGLE_ID`, `AUTH_GOOGLE_SECRET`
105+
106+
### 1.4 AI Proxy HTTP Action (`convex/aiProxy.ts` + route in `http.ts`)
107+
108+
- Receives POST requests from the extension with: model, messages, settings
109+
- Validates the user's auth token (from Authorization header)
110+
- Checks subscription is active
111+
- Increments usage counters
112+
- Forwards the request to the AI provider (OpenAI/Anthropic) with server-side API keys
113+
- Streams the response back to the extension
114+
- Environment variables: `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`
115+
116+
### 1.5 Stripe Integration
117+
118+
- `payments.ts`: `createCheckoutSession` action — creates Stripe Checkout session, returns URL
119+
- `http.ts`: `/stripe-webhook` route — handles `checkout.session.completed`, `customer.subscription.updated`, `customer.subscription.deleted`
120+
- Environment variables: `STRIPE_SECRET_KEY`, `STRIPE_WEBHOOK_SECRET`, `STRIPE_PRO_PRICE_ID`
121+
122+
---
123+
124+
## Phase 2: Extension Client Integration
125+
126+
### 2.1 New Files
127+
128+
```
129+
packages/extension/
130+
├── convex/
131+
│ └── client.ts # ConvexClient setup, auth helpers, chromeTokenStorage
132+
├── sidepanel/ui/
133+
│ └── account/
134+
│ ├── panel-account.ts # Account UI mixin (login/signup/manage)
135+
│ └── account-styles.css # Account panel styles
136+
```
137+
138+
### 2.2 Convex Client (`packages/extension/convex/client.ts`)
139+
140+
- Creates `ConvexClient` from `"convex/browser"` with deployment URL (build-time constant)
141+
- Custom `chromeTokenStorage` using `chrome.storage.local` for auth tokens
142+
- Exports: `convexClient`, `signIn()`, `signOut()`, `getAuthState()`, `getSubscription()`
143+
- Uses `anyApi` from `"convex/server"` since backend is in separate package
144+
145+
### 2.3 Account UI (`panel-account.ts`)
146+
147+
New mixin on `SidePanelUI` following existing pattern:
148+
- **Onboarding screen** (shown on first install): "Use your own API keys" vs "Get a subscription"
149+
- **Login/signup form**: email/password fields, Google/GitHub OAuth buttons
150+
- **Account section** in settings: shows plan, usage, manage subscription button
151+
- Attaches to existing settings panel as a new collapsible section
152+
153+
### 2.4 Background Service Changes (`background/service.ts`)
154+
155+
Modify the AI call path:
156+
- On startup, initialize Convex client (if user has account)
157+
- Before each AI call, check: does user have own API key set? → use it directly (BYOK)
158+
- No API key + active subscription? → route through Convex HTTP Action proxy
159+
- No API key + no subscription? → show "add API key or subscribe" message
160+
161+
### 2.5 Build Changes (`scripts/build.mjs`)
162+
163+
- Add `CONVEX_URL` as esbuild `define` constant (from env or hardcoded for prod)
164+
- Ensure `convex/browser` module is bundled correctly for extension
165+
- No changes to entry points needed — new code imports into existing entries
166+
167+
### 2.6 Manifest Changes
168+
169+
- Add Convex deployment domain to `host_permissions`: `https://*.convex.cloud/*`, `https://*.convex.site/*`
170+
171+
---
172+
173+
## Phase 3: Payment Flow
174+
175+
### User Journey (Paid Path)
176+
177+
1. User clicks "Get a subscription" on onboarding (or "Upgrade" in settings)
178+
2. Extension calls `convexClient.action(anyApi.payments.createCheckoutSession, {})`
179+
3. Action returns Stripe Checkout URL
180+
4. Extension opens URL in new tab (`chrome.tabs.create`)
181+
5. User completes payment on Stripe
182+
6. Stripe webhook fires → Convex creates/updates subscription record
183+
7. Extension polls or subscribes to subscription status → unlocks paid features
184+
8. AI calls now routed through Convex proxy
185+
186+
### User Journey (BYOK Path)
187+
188+
1. User clicks "Use your own keys" on onboarding
189+
2. Extension shows existing settings panel (provider, API key, model)
190+
3. Works exactly as today — no Convex account required
191+
4. Optional: user can later create account for cloud sync / backup
192+
193+
---
194+
195+
## Files to Create
196+
197+
| File | Purpose |
198+
|------|---------|
199+
| `packages/backend/package.json` | Backend package config |
200+
| `packages/backend/convex/schema.ts` | Database schema |
201+
| `packages/backend/convex/auth.ts` | Auth providers config |
202+
| `packages/backend/convex/http.ts` | HTTP router (auth, webhook, proxy) |
203+
| `packages/backend/convex/users.ts` | User queries/mutations |
204+
| `packages/backend/convex/subscriptions.ts` | Subscription CRUD |
205+
| `packages/backend/convex/payments.ts` | Stripe checkout action |
206+
| `packages/backend/convex/aiProxy.ts` | AI proxy HTTP action |
207+
| `packages/extension/convex/client.ts` | Extension Convex client |
208+
| `packages/extension/sidepanel/ui/account/panel-account.ts` | Account UI mixin |
209+
| `packages/extension/sidepanel/styles/account.css` | Account styles |
210+
211+
## Files to Modify
212+
213+
| File | Change |
214+
|------|--------|
215+
| `packages/extension/manifest.json` | Add Convex domains to host_permissions |
216+
| `packages/extension/background/service.ts` | Add subscription check + proxy routing |
217+
| `packages/extension/sidepanel/ui/core/panel-core.ts` | Initialize account UI, add account section |
218+
| `packages/extension/sidepanel/ui/settings/panel-settings.ts` | Add account section to settings |
219+
| `packages/extension/sidepanel/templates/main.html` | Add account UI containers |
220+
| `packages/extension/sidepanel/panel.ts` | Import account mixin |
221+
| `scripts/build.mjs` | Add CONVEX_URL define |
222+
| `package.json` (root) | Add backend workspace, convex deps |
223+
224+
---
225+
226+
## Verification
227+
228+
1. **Backend:** `cd packages/backend && npx convex dev` — schema deploys, functions sync
229+
2. **Auth:** Sign up with email, verify login works, test Google/GitHub OAuth
230+
3. **BYOK flow:** Existing behavior unchanged — enter API key, chat works
231+
4. **Paid flow:** Create checkout → pay with Stripe test card → subscription activates → AI calls proxy through Convex
232+
5. **Proxy:** Send a message as paid user → response streams back via Convex HTTP action
233+
6. **Cancellation:** Cancel in Stripe → webhook fires → subscription deactivated → proxy stops working
234+
7. **Build:** `npm run build` from root succeeds, extension loads in Chrome
235+
236+
---
237+
238+
## Implementation Order
239+
240+
1. Backend setup (schema, auth, basic functions) — can test independently via Convex dashboard
241+
2. Extension client + account UI (login/signup flow)
242+
3. Stripe integration (checkout, webhook, subscription management)
243+
4. AI proxy HTTP action (the most complex piece)
244+
5. Background service routing (BYOK vs proxy decision logic)
245+
6. Polish (onboarding flow, error handling, loading states)

PRIVACY.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Privacy Policy — Parchi
2+
3+
**Last updated:** 2026-02-15
4+
5+
## Summary
6+
7+
Parchi does **not** collect, store, or transmit any personal data.
8+
9+
## Data Handling
10+
11+
- **No analytics or telemetry.** Parchi does not include any tracking, analytics, or telemetry code.
12+
- **No remote servers.** All communication goes directly from your browser to the AI provider you configure (e.g. OpenAI, Anthropic, Google). Parchi never proxies requests through its own servers.
13+
- **API keys stay local.** Your API keys and settings are stored in your browser's local extension storage (`chrome.storage.local`) and are never sent anywhere except to the provider endpoint you configured.
14+
- **No data retention.** Conversation history exists only in your browser session memory and is not persisted or transmitted.
15+
- **No cookies or fingerprinting.** Parchi does not set cookies, use tracking pixels, or fingerprint your browser.
16+
17+
## Permissions
18+
19+
Parchi requests browser permissions (active tab, scripting, tabs, storage) solely to provide its browser automation features. These permissions are never used to collect or exfiltrate data.
20+
21+
## Third-Party Services
22+
23+
When you use Parchi, your prompts and page content are sent to whichever AI provider you have configured. Please review your provider's privacy policy for how they handle that data.
24+
25+
## Contact
26+
27+
If you have questions about this policy, open an issue at: https://github.com/AshwinSundar/browser-ai/issues

0 commit comments

Comments
 (0)