# আর্কিটেকচার

## সিস্টেমের সারসংক্ষেপ

```
iOS app / agent client          -> api.<domain>  -> API Gateway -> Lambda backend -> Postgres
Web app                         -> app.<domain>  -> CloudFront -> SPA
Browser and agent auth          -> auth.<domain> -> API Gateway -> Auth Lambda -> Cognito
Apex fallback                   -> <domain>      -> CloudFront redirect -> app.<domain>
```

## মূলনীতি

1. `app`, `api` ও `auth`-এর জন্য আলাদা পাবলিক ডোমেইন
2. Postgres হলো ডেটার মূল উৎস
3. iOS ক্লায়েন্ট অফলাইন-ফার্স্ট: লোকাল SQLite আর সঙ্গে সিঙ্ক
4. ওয়েব অ্যাপ, iOS অ্যাপ আর বাইরের এজেন্টের ইন্টারফেস একই ওয়ার্কস্পেস মডেল ব্যবহার করে
5. বাইরের এজেন্ট শুরু করে `GET https://api.nibomo.com/v1/` থেকে

## সমর্থিত ক্লায়েন্ট

- `app.nibomo.com`-এ ওয়েব অ্যাপ
- মূল রিপোজিটরিতে লোকাল SQLite স্টোরেজসহ iOS অ্যাপ
- Google Play-তে Android অ্যাপ
- ডিসকভারি, OTP দিয়ে প্রাথমিক অথেনটিকেশন আর `Authorization: ApiKey`-এর মাধ্যমে বাইরের এজেন্ট ক্লায়েন্ট

## ডেটা মডেল

- `workspaces`
- `workspace_members`
- `user_settings`
- `devices`
- `cards`
- `decks`
- `review_events`
- `applied_operations`
- `sync_state`

## ডেটা ফ্লো

### ওয়েব

1. ব্রাউজার `auth.<domain>`-এর মাধ্যমে সাইন ইন করে।
2. ওয়েব অ্যাপ `api.<domain>` থেকে ওয়ার্কস্পেসের ডেটা লোড করে।
3. AI চ্যাটের অনুরোধ `/chat/local-turn` দিয়ে যায়।
4. পুনরালোচনা জমা দিলে লেখার সময়েই শিডিউলারের অবস্থা আপডেট হয়।

### iOS

1. iOS অ্যাপ প্রথমে লোকালি SQLite-এ লেখে।
2. লোকাল পরিবর্তনগুলো একটি আউটবক্সে সারিতে রাখা হয়।
3. সিঙ্ক `/v1/workspaces/{workspaceId}/sync/push` দিয়ে পরিবর্তন আপলোড করে।
4. সিঙ্ক `/v1/workspaces/{workspaceId}/sync/pull` দিয়ে রিমোট আপডেট ডাউনলোড করে।
5. লোকাল ডেটাবেস পরিবর্তনগুলো প্রয়োগ করে আর সিঙ্ক কার্সর এগিয়ে নেয়।

### বাইরের এজেন্ট

1. এজেন্ট `GET /v1/` দিয়ে শুরু করে।
2. OTP দিয়ে প্রাথমিক অথেনটিকেশন চলে `auth.<domain>`-এ।
3. এজেন্ট একটি দীর্ঘমেয়াদি API কী পায়।
4. এজেন্ট `/v1/agent/me` লোড করে, ওয়ার্কস্পেসের তালিকা নেয়, দরকার হলে একটি বেছে নেয়, তারপর `/v1/agent/sql/query` ও `/v1/agent/sql/execute` ব্যবহার করে।

## শিডিউলিং

Nibomo পুনরালোচনার শিডিউলার হিসেবে FSRS ব্যবহার করে।

বাস্তবায়নের নোট:

- ব্যাকএন্ড আর iOS-এ FSRS-এর হুবহু মেলানো দুটি বাস্তবায়ন রাখা হয়
- ওয়েব অ্যাপ শিডিউলিংয়ের ডেটা কন্ট্র্যাক্ট হুবহু মেনে চলে, কিন্তু শিডিউলারের তৃতীয় কোনো কপি রাখে না
- ওয়ার্কস্পেস-স্তরের শিডিউলার সেটিংসে আছে কাঙ্ক্ষিত রিটেনশন, শেখার ধাপ, পুনরায় শেখার ধাপ, সর্বোচ্চ ব্যবধান আর ফাজ
- পুনরালোচনার আসল সময় আসে `reviewedAtClient` থেকে

বিস্তারিত কন্ট্র্যাক্টের জন্য [মূল রিপোজিটরিতে FSRS শিডিউলিং লজিক](https://github.com/kirill-markin/flashcards-open-source-app/blob/main/docs/fsrs-scheduling-logic.md) দেখুন।

## অথেনটিকেশন

- Cognito দিয়ে ইমেইল OTP
- হোস্ট করা ওয়েব অ্যাপের জন্য শেয়ার করা ডোমেইনের ব্রাউজার সেশন কুকি
- `auth.<domain>`-এ এজেন্টের OTP দিয়ে প্রাথমিক অথেনটিকেশন, যার ফল একটি দীর্ঘমেয়াদি ApiKey
- লোকাল ডেভেলপমেন্টের জন্য `AUTH_MODE=none`
- প্রোডাকশনের মতো অথেনটিকেশনের জন্য `AUTH_MODE=cognito`

## ডিপ্লয়মেন্টের কাঠামো

- `app.<domain>` -> CloudFront + S3
- `api.<domain>` -> API Gateway + Lambda ব্যাকএন্ড
- `auth.<domain>` -> API Gateway + Lambda অথেনটিকেশন সার্ভিস
- AWS RDS-এ Postgres

অ্যাপেক্স ডোমেইন আলাদা একটি মার্কেটিং সাইটে থাকতে পারে। প্রাথমিক সেটআপের সময় সেটি অব্যবহৃত থাকলে ইনফ্রাস্ট্রাকচার সাময়িকভাবে সেটিকে `app.<domain>`-এ রিডাইরেক্ট করতে পারে।

---
*[এই পেজের স্টাইল করা HTML সংস্করণ দেখুন](<https://nibomo.com/bn/docs/architecture/>)*

*AI এজেন্ট `GET https://api.nibomo.com/v1/` দিয়ে শুরু করে এই সার্ভিসে ব্যবহারকারীর অ্যাকাউন্ট তৈরি করতে পারে। সেটআপ হয়ে গেলে তারা `https://mcp.nibomo.com/mcp`-এ MCP দিয়েও যুক্ত হতে পারে।*

*টিপ: https://nibomo.com-এর যেকোনো URL-এর শেষে `.md` যোগ করলে সেই পেজের পরিষ্কার Markdown সংস্করণ পাবেন।*