Skip to content

Commit b70da5e

Browse files
authored
Merge branch 'tinyhumansai:main' into feat/e2e-cross-platform
2 parents 8d75cb4 + c10f087 commit b70da5e

144 files changed

Lines changed: 13624 additions & 1654 deletions

File tree

Some content is hidden

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

.claude/memory.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,14 @@ Quick reference for anyone starting with Claude on this project. Updated by the
5454
- **`DEV_FORCE_ONBOARDING` was a no-op** — The old ternary had identical branches; fixed to actually force-show when the flag is set.
5555
- **`isOnboardedRedux` must be in useEffect deps** — When reading a selector value inside a useEffect, add it to the dependency array or the effect won't re-run when Redux state changes.
5656

57+
## CoreStateProvider & Auth Bootstrap
58+
59+
- **Auth session tokens are NOT in Redux persist** — They live entirely in the Rust sidecar, fetched via `fetchCoreAppSnapshot()` RPC. `PersistGate` only gates non-auth state (AI config, threads, channel connections). `CoreStateProvider` bootstrap is the critical auth path.
60+
- **`CoreStateProvider` premature `isBootstrapping: false` causes blank Settings** — If the initial RPC call fails (sidecar still starting), the old error handler set `isBootstrapping: false` immediately, causing `ProtectedRoute` to redirect to `/` before the 3s poll could recover. Fix (issue #413): keep `isBootstrapping: true` on initial failure, let the poll retry, give up after 5 attempts (~15s).
61+
- **`CoreStateProvider` is consumed by ~25 components** — Changes to its state shape or bootstrap behavior affect routes, socket, onboarding, nav, settings, and hooks. Treat it as a high-blast-radius file.
62+
- **Settings is a full route, not a modal**`/settings/*` uses nested `<Routes>` in `Settings.tsx`. The `.claude/rules/15-settings-modal-system.md` doc describing a portal/modal approach is outdated. A catch-all `<Route path="*">` redirects unmatched sub-paths to `/settings`.
63+
- **`PersistGate loading={null}` causes flash** — Changed to `loading={<RouteLoadingScreen />}` (issue #413). `RouteLoadingScreen` accepts an optional `label` prop (defaults to "Initializing OpenHuman...") and can be rendered with no props.
64+
5765
## Build Blockers: macOS Tahoe + whisper-rs
5866

5967
- **`whisper-rs` breaks `cargo build` on macOS Tahoe (Apple Silicon)** — Added in main via `whisper-rs = "0.16"` (voice feature #178). Apple clang 21+ refuses `-mcpu=native` when `--target=arm64-apple-macosx` is also set. This is NOT fixable by updating CLT.
@@ -71,6 +79,15 @@ Quick reference for anyone starting with Claude on this project. Updated by the
7179
- **Agent message bubbles** need `bg-stone-200/80` (not `bg-stone-100`) on `#F5F5F5` background — `bg-stone-100` is nearly invisible.
7280
- **~55 files touched** — purely CSS class changes, zero logic/handler/state changes.
7381

82+
## Upsell / Billing (Phase 1 — Issue #403)
83+
84+
- **Upsell components** live in `app/src/components/upsell/``UpsellBanner`, `UsageLimitModal`, `GlobalUpsellBanner`, `upsellDismissState`. Shared hook: `app/src/hooks/useUsageState.ts`.
85+
- **Usage data sources**`creditsApi.getTeamUsage()` returns `TeamUsage` (rolling 10h spend/cap + weekly budget/remaining). `billingApi.getCurrentPlan()` returns `CurrentPlanData` (plan tier, caps, subscription status). Both go through `callCoreCommand` (core RPC). No Redux slice — all local hook state.
86+
- **Module-level cache in `useUsageState`**`_cache` variable with 60s TTL prevents duplicate API calls when multiple components mount simultaneously. New pattern; do not remove.
87+
- **Banner dismiss state uses localStorage** (prefix `openhuman:upsell:`), not Redux — consistent with CLAUDE.md exception for ephemeral UI state.
88+
- **Phased rollout** — Phase 1 = banners + limit modal + hook. Phase 2 = onboarding upsell + analytics. Phase 3 = remote config + A/B testing.
89+
- **"5-hour" label stragglers in Conversations.tsx**`LimitPill` label and its hover tooltip still say "5h" / "5-hour". Commit 8c52236's "10-hour" terminology refactor missed those two spots.
90+
7491
## Environment
7592

7693
- **Core sidecar port**`7788` (default). Check with `lsof -i :7788`.

.env.example

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ OPENHUMAN_CORE_RPC_URL=http://127.0.0.1:7788/rpc
3434
OPENHUMAN_CORE_RUN_MODE=child
3535
# [optional] Override path to openhuman core binary (leave blank for auto-detection)
3636
OPENHUMAN_CORE_BIN=
37+
# [optional] Explicit .env path for `openhuman serve` / `openhuman run` (loaded before the server starts).
38+
# Must be set in the parent environment (exported in your shell or service manager). It is read before
39+
# any dotenv file is loaded, so defining OPENHUMAN_DOTENV_PATH inside a .env file cannot select that file.
40+
# OPENHUMAN_DOTENV_PATH=
3741

3842
# ---------------------------------------------------------------------------
3943
# Config overrides (override config.toml values at runtime)

.github/workflows/build-windows.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ jobs:
6363
VITE_BACKEND_URL: ${{ vars.BASE_URL }}
6464
VITE_SENTRY_DSN: ${{ vars.VITE_SENTRY_DSN }}
6565
VITE_DEBUG: ${{ vars.VITE_DEBUG }}
66+
VITE_MINIMUM_SUPPORTED_APP_VERSION: ${{ vars.VITE_MINIMUM_SUPPORTED_APP_VERSION }}
67+
VITE_LATEST_APP_DOWNLOAD_URL: ${{ vars.VITE_LATEST_APP_DOWNLOAD_URL }}
6668

6769
- name: Resolve core manifest and binary names
6870
id: core-paths
@@ -129,6 +131,8 @@ jobs:
129131
id: tauri-build
130132
env:
131133
BASE_URL: ${{ vars.BASE_URL }}
134+
VITE_MINIMUM_SUPPORTED_APP_VERSION: ${{ vars.VITE_MINIMUM_SUPPORTED_APP_VERSION }}
135+
VITE_LATEST_APP_DOWNLOAD_URL: ${{ vars.VITE_LATEST_APP_DOWNLOAD_URL }}
132136
with:
133137
projectPath: app
134138
args: -c ${{ steps.config-overrides.outputs.json }} --target x86_64-pc-windows-msvc

.github/workflows/release.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,9 @@ jobs:
309309
VITE_BACKEND_URL: ${{ vars.BASE_URL }}
310310
VITE_SENTRY_DSN: ${{ vars.VITE_SENTRY_DSN }}
311311
VITE_DEBUG: ${{ vars.VITE_DEBUG }}
312+
# OAuth guardrails (#365): block openhuman://oauth/success on outdated desktop builds.
313+
VITE_MINIMUM_SUPPORTED_APP_VERSION: ${{ vars.VITE_MINIMUM_SUPPORTED_APP_VERSION }}
314+
VITE_LATEST_APP_DOWNLOAD_URL: ${{ vars.VITE_LATEST_APP_DOWNLOAD_URL }}
312315

313316
- name: Resolve core manifest and binary names
314317
id: core-paths
@@ -390,6 +393,9 @@ jobs:
390393
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD || secrets.UPDATER_PRIVATE_KEY_PASSWORD }}
391394
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY || secrets.UPDATER_PRIVATE_KEY }}
392395
WITH_UPDATER: "true"
396+
# Must match standalone "Build frontend" so tauri-action's beforeBuildCommand embeds the gate.
397+
VITE_MINIMUM_SUPPORTED_APP_VERSION: ${{ vars.VITE_MINIMUM_SUPPORTED_APP_VERSION }}
398+
VITE_LATEST_APP_DOWNLOAD_URL: ${{ vars.VITE_LATEST_APP_DOWNLOAD_URL }}
393399
with:
394400
projectPath: app
395401
args: -c ${{ steps.config-overrides.outputs.json }} ${{ matrix.settings.args }}

Cargo.lock

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ prost = { version = "0.14", default-features = false }
6060
postgres = { version = "0.19", features = ["with-chrono-0_4"] }
6161
chrono-tz = "0.10"
6262
dialoguer = { version = "0.12", features = ["fuzzy-select"] }
63+
dotenvy = "0.15"
6364
console = "0.16"
6465
glob = "0.3"
6566
regex = "1.10"

Referral-doc.md

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
# Referral System
2+
3+
## Overview
4+
5+
Referral rewards are paid to the referrer based on real successful payments from referred users.
6+
7+
- Reward rate: `20%` of payment (`2000` basis points)
8+
- Referred user reward: none
9+
- Behavior flag: `RECURRING_REFERRAL_REWARD`
10+
- `true`: reward every successful eligible payment
11+
- `false`: reward only once per referral
12+
13+
## Main Rules
14+
15+
- Each user has one unique referral code.
16+
- A user can apply a code only before their first confirmed payment.
17+
- Self-referral is blocked (user id + identity fields).
18+
- Rewarding is idempotent:
19+
- same payment cannot reward twice
20+
- non-recurring mode allows only one reward for that referral
21+
22+
## Data Model
23+
24+
### `ReferralCode` (`referralcodes`)
25+
26+
- `userId` (unique)
27+
- `referralCode` (unique)
28+
29+
### `Referral` (`referrals`)
30+
31+
- `referrerId`
32+
- `referredUserId` (unique)
33+
- `referralCode`
34+
- `status`: `pending | converted`
35+
- `sourceIp`, `deviceFingerprint`, `convertedAt`
36+
37+
### `ReferralTransaction` (`referraltransactions`)
38+
39+
- `referralId`, `referrerId`, `referredUserId`
40+
- `sourcePaymentId`, `sourcePaymentGateway`, `sourcePaymentObjectId`
41+
- `paymentAmountUsd`, `rewardAmountUsd`, `rewardRate` (Decimal128)
42+
- `creditTransactionId`
43+
- `idempotencyKey` (unique)
44+
45+
## Migration
46+
47+
Migration file: `src/migrations/1744200000000-referral-system.ts`
48+
49+
What it does:
50+
51+
- creates indexes for referral collections
52+
- backfills missing referral codes for existing users
53+
- backfills `Referral` records from legacy `user.referral.invitedBy`
54+
- supports `users` and `tgusers` collections
55+
56+
### Run migration (non-interactive)
57+
58+
```bash
59+
npx ts-migrate-mongoose up -f src/migrate.ts -a true
60+
```
61+
62+
### Check migration status
63+
64+
```bash
65+
npm run migrate:list
66+
```
67+
68+
### Roll back referral migration (if needed)
69+
70+
```bash
71+
npm run migrate:down
72+
```
73+
74+
## Core Services
75+
76+
- `src/services/referral/referralCodeService.ts`
77+
- ensures and fetches user referral codes
78+
- `src/services/referral/referralService.ts`
79+
- apply code, enforce eligibility, return referral stats
80+
- `src/services/referral/referralRewardService.ts`
81+
- compute reward in cents, award credits, upsert audit transaction, mark referral converted
82+
83+
## API
84+
85+
- `GET /referral/stats`
86+
- returns code, referral link, totals, and referral rows
87+
- `POST /referral/apply`
88+
- request: `{ "code": "ABCD1234", "deviceFingerprint": "optional" }`
89+
- supports `x-device-fingerprint` header
90+
91+
## Payment Integration
92+
93+
Reward processing is triggered on successful payment flows in:
94+
95+
- `src/controllers/payment/coinbase/webhook.ts`
96+
- `src/controllers/payment/stripe/handleWebhook.ts`
97+
98+
## Config
99+
100+
`RECURRING_REFERRAL_REWARD` is read via `nconf`. Truthy values: `true`, `1`, `yes`.
101+
102+
## Tests
103+
104+
Key test: `src/services/referral/__tests__/referralRewardService.test.ts`
105+
106+
- non-recurring behavior
107+
- recurring behavior
108+
- payment idempotency

app/.env.example

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,8 @@ VITE_DEV_FORCE_ONBOARDING=false
2828
# [optional] Client-side timeout for skill callTool/triggerSync (seconds; default 120, max 3600).
2929
# Should match OPENHUMAN_TOOL_TIMEOUT_SECS on the core when set.
3030
# VITE_TOOL_TIMEOUT_SECS=
31+
32+
# [optional] Minimum desktop app semver to complete OAuth deep links (openhuman://oauth/success). Leave unset in dev.
33+
# VITE_MINIMUM_SUPPORTED_APP_VERSION=0.51.0
34+
# [optional] Download page when OAuth is blocked due to an outdated build (default: GitHub releases/latest).
35+
# VITE_LATEST_APP_DOWNLOAD_URL=https://github.com/tinyhumansai/openhuman/releases/latest

app/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "openhuman-app",
3-
"version": "0.51.17",
3+
"version": "0.51.19",
44
"type": "module",
55
"scripts": {
66
"dev": "vite",
91.1 KB
Loading

0 commit comments

Comments
 (0)