Frontend (BFF)¶
Frontend нь Backend-for-Frontend загвартай Next.js 15 (App Router) апп.
Браузер зөвхөн ижил-origin /api/* route handler руу залгадаг; тэдгээр нь
сервер талаас Go API руу проксиолно.
Яагаад BFF вэ?¶
sequenceDiagram
participant B as Браузер
participant N as Next.js route handler
participant A as Go API
B->>N: fetch('/api/gov/applications', {headers: x-dgov-csrf})
Note over N: httpOnly cookie-оос токен уншина<br/>origin шалгана
N->>A: GET /api/v1/gov/applications<br/>Authorization: Bearer …
A-->>N: {data: …}
N-->>B: {data: …} (токен ХЭЗЭЭ Ч буцахгүй)
Үр дүн: access / refresh токен нь httpOnly cookie-д амьдарна, клиентийн
JavaScript түүнийг унших боломжгүй. XSS гарсан ч токен шууд алдагдахгүй.
Давхар CSRF хамгаалалт¶
Мутаци хийдэг бүх браузерийн дуудлага lib/client.ts-ийн sendJSON /
postJSON-оор явна. Тэдгээр нь x-dgov-csrf толгойг нэмнэ; BFF талын
lib/bff.ts доторх checkOrigin нь дараах хоёуланг шаардана:
- Custom header — cross-site form илгээлт үүнийг тавьж чадахгүй.
- Origin / Referer шалгалт — өөрийн origin-той таарах ёстой.
Шинэ мутаци route бичихдээ
Шинэ POST/PUT/DELETE BFF route үүсгэвэл эхний мөрөнд checkOrigin
дуудна. Мартвал CSRF нээлттэй үлдэнэ.
Токен ба сессийн урсгал¶
| Файл | Үүрэг |
|---|---|
lib/cookies.ts |
httpOnly cookie бичих / унших |
lib/session.ts |
Session төлөв, хугацаа |
lib/api.ts |
Server талын fetch + tryRefresh |
lib/signout.ts |
Logout — backend + cookie цэвэрлэх |
RSC дотор refresh бүү дууд
Refresh нь токеныг эргүүлдэг (rotation). React Server Component-ийн
контекстээс дуудвал шинэ токеныг cookie-д бичих боломжгүй тул хуучин нь
хүчингүй болж, хэрэглэгч гацна. Тиймээс tryRefresh нь эхлээд cookie
бичигдэх боломжтой эсэхийг шалгадаг (lib/api.ts).
Өгөгдөл татах¶
Компонент доторх өгөгдөл TanStack Query-ээр явна:
const { data } = useQuery({
queryKey: ['gov', 'applications'],
queryFn: () => getJSON('/api/gov/applications'),
});
// мутацийн дараа:
queryClient.invalidateQueries({ queryKey: ['gov', 'applications'] });
Provider нь components/Providers.tsx-д. Хамаарал багатай байлгах бодлого тул
UI сан ашигладаггүй — lucide-react (icon), qrcode.react (eID QR) л байна.
Олон хэл (i18n)¶
UI мөрүүд lib/i18n.ts дотор төвлөрсөн, дөрвөн хэл: mn · en · zh ·
ru. Компонентод useT()-ээр хэрэглэнэ.
lib/i18n.test.ts нь түлхүүрийн бүрэн байдлыг шалгана — түлхүүр аль нэг
хэлэнд дутвал тест унана. prefersLatinName() нь кирилл бус хэл дээр латин
нэрийг илүүд үздэг (орос нь кирилл тул монгол бичлэгээ хадгална).
AI-ийн хариултын хэл
Чатын хүсэлт бүрд UI-ийн хэл lang талбараар илгээгддэг ба тэр нь эцсийн
шийдэгч — хэрэглэгч өөр хэлээр бичсэн ч хариулт UI-ийн хэлээр ирнэ.
Дэлгэрэнгүйг AI туслах-аас үз.
Харагдац (theming)¶
Сайтын харагдацыг админ тохируулна (accent өнгө, фонт, нягтрал, гэрэл/харанхуй), хэрэглэгч тус бүр өөрийн override хийж чадна:
| Гадаргуу | API |
|---|---|
| Нийтийн default | GET /api/site/appearance |
| Админ өөрчлөх | PUT /api/admin/site/appearance (settings.manage) |
| Нэрлэсэн theme | /api/admin/themes/* — CRUD + идэвхжүүлэх |
Брэндийн өнгийг кодод hardcode хийхгүй — Admin → Theme editor-оос тохируулна.
BFF route-ийн бүтэц¶
src/app/api/ дор 150 гаруй route handler бий. Backend модуль бүрт тохирсон
бүлэг:
api/auth/* eID нэвтрэлт, SSO, superadmin onboarding
api/me/* профайл, eID PKI самбар, гарын үсэг
api/gov/* төрийн үйлчилгээ + албан хаагчийн дараалал
api/registry/* үйлчилгээний регистр
api/relay/* хүсэлт дамжуулах
api/gateway/* API gateway
api/applications/* OAuth client бүртгэл
api/ai/* чат · STT · TTS · орчуулга
api/public/ai/* нэвтрэлтгүй чат (stream)
api/integrations/* Google Drive/Meet · Dropbox
api/gspace/* SFTP хадгалалт
api/provider/* OIDC login / consent / logout
api/audit, api/security, api/site, api/themes, api/superadmin …
Backend-ийн алдааг клиент рүү proxyResult / toClientResponse-оор дамжуулна —
токен эсвэл дотоод мессеж хэзээ ч задрахгүй.
Тест¶
| Тест | Юуг батална |
|---|---|
i18n.test.ts |
Толь бичиг + landing текстийн дөрвөн хэлний бүрэн байдал |
bff.test.ts |
checkOrigin, прокси хариултын хэлбэр |
securityHeaders.test.ts |
CSP болон бусад толгойн утга |
chatStream.test.ts |
SSE чатын урсгалын задаргаа |
navigation.test.ts |
Эрхээс хамаарсан цэсний бүтэц |