6b7f0263e4
Replaces the hardcoded message limit with a model-driven paywall and removes registration before the first question: - Onboarding: the app opens directly into the chat. Dynamic conversation starters are served by GET /suggestions (services/api/suggestions.json), updatable with a deploy — no app release needed. Guests chat via POST /guest/chat, identified by an app-generated device id; sign-in moves to the paywall, where a purchase must attach to an account. - Free experience: the model runs in discovery mode — follow-up questions, pattern identification, visible understanding — building an analysis without delivering the full solution. - Intelligent paywall: the model returns structured output (reply + analysis_ready). Only when the problem is described, the information is sufficient and an action plan is ready does it write a calm transition and pause the conversation. Manufactured urgency, emotional pressure, fake readiness and mid-answer stops are explicitly forbidden. - Premium: on unlock the app resends the transcript and the backend immediately delivers the full analysis, strategies and exercises, then the dialogue continues without restriction. - The old FREE_MESSAGE_LIMIT becomes MESSAGE_CAP (default 200/30 days), kept purely as an abuse backstop — it is not the paywall. - WelcomeScreen removed; the app is now two views (Chat, Paywall). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0118DaxZR36RpnY524vRqx3z
143 lines
5.7 KiB
Markdown
143 lines
5.7 KiB
Markdown
# NeuroSemantics AI
|
|
|
|
A minimalist mobile app for iOS and Android. The product is one thing only:
|
|
an intelligent conversation partner with a specialized knowledge base in
|
|
neurosemantics and NLP. No course portal, no CRM, no community.
|
|
|
|
Design language: calm, simple, clear. Off-white background, near-black text,
|
|
one dark blue-green accent. No animations, no gradients.
|
|
|
|
## System overview
|
|
|
|
```
|
|
apps/mobile Expo / React Native app (two views: Chat, Paywall)
|
|
services/api One Lambda backend (chat, usage, subscription verification)
|
|
infra AWS CDK stack (the entire cloud environment)
|
|
db/migrations SQL schema (two tables: users, usage)
|
|
```
|
|
|
|
A new developer should understand the whole system in under an hour. Every
|
|
piece exists for a reason; if a feature does not make the core product better,
|
|
it is not built.
|
|
|
|
### Request flow
|
|
|
|
1. The user lands directly in the chat — no registration before the first
|
|
question. Guests are identified by an app-generated device id
|
|
(`POST /guest/chat`); dynamic conversation starters come from
|
|
`GET /suggestions` (both public routes). The suggestions live in
|
|
`services/api/suggestions.json` and can be updated with a deploy — no
|
|
app release needed.
|
|
2. Requests go through **API Gateway** to the single **Lambda**; signed-in
|
|
users use `POST /chat` with a **Cognito** JWT (Apple / Google / email via
|
|
the hosted UI).
|
|
3. The Lambda calls the **OpenAI Responses API** with the Markdown knowledge
|
|
base (`services/api/knowledge/`) as system instructions. The model
|
|
returns structured output: a reply plus an `analysis_ready` flag.
|
|
4. Sign-in happens at the paywall, since a purchase must attach to an
|
|
account. Usage counters live in **PostgreSQL** (Aurora Serverless v2).
|
|
|
|
### The intelligent paywall
|
|
|
|
The paywall is not a hardcoded message count. Free conversations run in
|
|
_discovery mode_: the model asks relevant follow-up questions, names
|
|
patterns, shows understanding, and builds toward an analysis — without
|
|
delivering the full solution. When the problem is described, the information
|
|
is sufficient, and a concrete action plan is ready, the model signals
|
|
`analysis_ready`, writes a calm transition ("…I have a concrete strategy I
|
|
would recommend. Continue with Premium to see the analysis and the
|
|
recommended steps."), and the conversation pauses.
|
|
|
|
The instructions explicitly forbid manufactured urgency, emotional pressure,
|
|
fake readiness, and stopping mid-answer — Premium should feel like the
|
|
natural continuation of an already valuable dialogue.
|
|
|
|
On unlock, the app resends the transcript; premium mode then delivers the
|
|
full analysis, recommended strategies and concrete exercises immediately,
|
|
and the dialogue continues without restriction.
|
|
|
|
A generous `MESSAGE_CAP` (default 200 per 30 days) exists purely as an
|
|
abuse backstop for the free tier — it is not the paywall.
|
|
|
|
Conversations are never stored server-side; the client holds them in memory
|
|
and sends the running transcript with each request. The database stores the
|
|
absolute minimum: `users` (id, email, provider, subscription_status,
|
|
created_at) and `usage` (messages_used, last_reset). No profiling, no
|
|
training on user data. Error logging is anonymized (no message content).
|
|
|
|
### Payments
|
|
|
|
Subscription logic is shared (`services/api/src/subscription/`); the payment
|
|
provider differs per platform behind one `PaymentProvider` interface:
|
|
|
|
- **iOS** — In-App Purchase; the backend verifies the app receipt with Apple.
|
|
- **Android** — Google Play Billing; the backend verifies the purchase token
|
|
with the Play Developer API.
|
|
- **Web (future)** — a Stripe adapter slots into the same interface.
|
|
|
|
Plans: Monthly and Yearly. Nothing else.
|
|
|
|
## Getting started
|
|
|
|
```sh
|
|
npm install # installs all workspaces
|
|
npm run lint
|
|
npm run typecheck
|
|
npm test
|
|
```
|
|
|
|
### Mobile app
|
|
|
|
```sh
|
|
cd apps/mobile
|
|
npm start # Expo dev server
|
|
```
|
|
|
|
Fill in `extra` in `app.json` (API URL, Cognito domain and client id) from
|
|
the CDK stack outputs. In-app purchases require a development build
|
|
(`expo run:ios` / `expo run:android`), not Expo Go.
|
|
|
|
### Backend + infrastructure
|
|
|
|
```sh
|
|
cd infra
|
|
npx cdk deploy
|
|
```
|
|
|
|
After the first deploy:
|
|
|
|
1. Put values into the `neurosemantics/app` secret in Secrets Manager:
|
|
`OPENAI_API_KEY`, `APPLE_SHARED_SECRET`, `GOOGLE_SERVICE_ACCOUNT_JSON`.
|
|
2. Run `db/migrations/001_init.sql` against the cluster (credentials are in
|
|
the RDS-managed secret).
|
|
3. Optional: enable Apple/Google sign-in by passing CDK context
|
|
(`googleClientId`, `googleClientSecret`, `appleTeamId`, `appleKeyId`,
|
|
`applePrivateKeySecretName`). Email sign-in works out of the box.
|
|
|
|
### CI/CD
|
|
|
|
GitHub Actions: `ci.yml` lints, type-checks and tests every PR;
|
|
`deploy.yml` deploys the CDK stack on every push to `main` (set the
|
|
`AWS_DEPLOY_ROLE_ARN` secret for OIDC). Store builds ship via EAS
|
|
(`eas build`) when you choose to release.
|
|
|
|
## Security
|
|
|
|
- All traffic over HTTPS. Account routes require a Cognito JWT; the two
|
|
public routes (`/suggestions`, `/guest/chat`) carry no account data and
|
|
are bounded by the free-tier message cap.
|
|
- Secrets live in AWS Secrets Manager only — no API keys in the client.
|
|
- The Lambda runs in private subnets; the database is not publicly reachable.
|
|
|
|
## Product philosophy
|
|
|
|
Every free user should leave the app feeling that the system understood
|
|
their situation, that a concrete analysis is ready, and that the next step
|
|
is available in Premium — never that they were held back by an artificial
|
|
interruption.
|
|
|
|
Every new feature must justify itself. The allowed AWS surface is
|
|
API Gateway, Lambda, Cognito, S3, Secrets Manager and CloudWatch — and V1
|
|
does not even need S3. No Redis, no Kubernetes, no Kafka, no Elasticsearch,
|
|
no queues, no microservices. One backend. Maximal simplicity.
|