Перейти к содержанию

Архитектур

Кодоос уншиж бичсэн. Нэр, бүтэц 2026-08-30-нд, тоонууд 2026-09-13-нд backend/ дотроос шалгагдсан — энэ баримт нь зорилго биш, одоогийн байдал. Тоо бүр golden файл эсвэл тестээс гардаг; эх сурвалж нь «Хэмжсэн хэмжээс» хэсэгт.

Баримтын төв · Модуль бичих · Танилт · Ажиллагаа


Нэг бинарь, гурван урсгал

cmd/api нэг процесс ачаалж, дотор нь хоорондоо import хийдэггүй гурван хүсэлтийн урсгал ажиллана.

Ажлын урсгал Операторын урсгал Хүний урсгал
Хэнд Байгууллага доторх хүн Суулгацыг удирдах оператор Хүн өөрөө, аль ч байгууллагаас гадуур
Origin nexus.gerege.net admin.nexus.gerege.net nexus.gerege.net
API угтвар /api/v1/* /api/platform/v1/* /api/v1/me/*
Cookie session_token cp_session session_token
Бүртгэл registry.users + workspace.memberships operator.operator_accounts registry.users
DB role gerege_nexus_tenant gerege_nexus_operator gerege_nexus_tenant
Go багц internal/workspace/* internal/operator/* internal/person

Замын бүрэн жагсаалт pkg/host/testdata/routes.txt — 182 өөр замын 75 нь /api/platform/v1/* (операторынх); тоолох арга доор.

Операторын бүртгэл нь хэрэглэгчийн бүртгэл биш. Нэг хүн хоёуланд нь нэвтэрч болох ч тусдаа identity, cookie, эрх, audit ашиглана. Оператор байгууллагын нүдээр харах шаардлагатай бол шалтгаан бүхий, хугацаа хязгаартай impersonation урсгалыг ашиглана — тэр нь бүртгэгддэг.

Хүний урсгал нь ажлын урсгалтай нэг cookie, нэг DB role хуваалцдаг. Ялгаа нь хамрах хүрээ: /api/v1/me/* нь нэг хүний зүйлсийг бүх байгууллагаар нь хариулна — түүнд ирсэн зүйлс, түүний гишүүн болох хүсэлтүүд, лавлах. Тиймээс энэ нь workspace-ийн дэд багц биш, тусдаа багц: workspace-ийн query бүр байгууллага дотор ажиллаж байгаа хүнд зориулж бичигдсэн бөгөөд тэдгээрийг энд import хийх нь тэр query-үүдийг ямар ч байгууллагад харьяалагдахгүй хүсэлтээс дуудагдах боломжтой болгоно. Session-ээс хэрэгтэй зүйл нь ганц асуулт — «энэ token хэн бэ» — асуулт нь import биш, port.

Гурван урсгал хоорондоо import хийхгүйг internal/planes_test.go компиляцын граф дээр шалгана: workspace ↮ operator, person ↮ workspace, person ↮ operator. Энэ бол баримтын амлалт биш, тестийн батламж.

ажлын origin ─┐                            ┌─ internal/workspace/*  → workspace schema
              │                            │
              ├─ pkg/host/server.go ───────┼─ internal/person       → registry + workspace
              │     дундын middleware      │
операторын ───┘                            └─ internal/operator/*   → operator + registry
                          │
                    internal/kernel/*
                          │
                      PostgreSQL

backend/pkg/host нь composition root — гурваас илүүг нэрлэх эрхтэй цорын ганц газар. run.go нь бүх зүйлийг дараалалтайгаар босгоно: лог, trace, метрик, алдааны бүртгэл, өгөгдлийн сангийн pool, tenant binding, audit sink, Redis, сервер, суурь өгөгдөл, ардын ажил. server.go нь гурван route table-ыг нэг router дээр mount хийнэ.

Дундын middleware гинж, дарааллаараа:

RequestID → Tracing → RequestLogger → Recovery → LoadShedder → Metrics
          → SecurityHeaders → CORS → CSRF

Гурван schema

Schema Хүснэгт Юу эзэмшдэг
workspace 33 Байгууллагын ажил: гишүүнчлэл, эрх, апп суулгалт, баримт, тайлан, SSO
registry 23 Суулгацын бүртгэл: байгууллага, хүн, тэдгээрийн таних тэмдэг
operator 8 Операторын бүртгэл, audit, зөвшөөрөл

Хуваалт нь гоо зүйн биш: db/migrations-ийн guardrail тест нь schema бүрийн хүснэгтийн тоог тоолж, бичсэн тоотой тулгадаг (schema_split_test.go). Хүснэгт нэмэх нь тэр тоог шинэчлэхийг шаардана — өөрөөр хэлбэл хилийг санамсаргүй давах боломжгүй.

Өгөгдлийн тусгаарлалт — хоёр давхарга

Query бүр WHERE tenant_id = $1 авч явдаг ба тэр нь үндсэн хяналт хэвээр. Доор нь хоёр дахь давхарга байна: internal/kernel/dbguard.

pgxpool нь query бүрд холболт гаргаж өгдөг ба BeforeAcquire нь хүсэлтийн контексттэйгээ ажилладаг. Тэр нь аль холболт ашиглагдах гэж байгааг ба хэн ашиглах гэж байгааг хоёуланг нь мэддэг цорын ганц цэг тул уяа тэнд хийгдэнэ:

контекстэд байгууллага   → SET ROLE gerege_nexus_tenant, app.current_tenant = <id>
контекстэд хүн           → SET ROLE gerege_nexus_tenant, байгууллагагүй
аль нь ч биш             → SET ROLE NONE (нэвтрэх role, бодлогод захирагдахгүй)

Гурав дахь тохиолдол нь цоорхой биш — платформын зам юм: нэвтрэлт, session тайлах, OAuth callback, шүүрдэлт зэрэг байгууллагагүй ажил тэрүүгээр явна.

Үр дүн нь: ирээдүйд, өөр хүний бичсэн модульд WHERE мартагдвал тэр нь өөр байгууллагын мөрийг буцаахгүй, юу ч буцаахгүй.

app.current_user нь мөн бүх уясан холболт дээр тавигдана. Ихэнх бодлого түүнийг уншдаггүй — тэдгээр байгууллагаар тусгаарладаг. Уншдаг нь хүнд харьяалагддаг хүснэгтүүд: тэнд тусгаарлах зүйл нь хүн өөрөө тул түлхүүр нь ч хүн байх ёстой. Заримдаа байдаг уяа нь бодлого бичигчийн бодох ёстой нэмэлт тохиолдол болдог учир үргэлж тавигддаг.

Цөм — internal/kernel

Аль ч урсгалыг import хийдэггүй багцууд (бүрэн жагсаалт: ls backend/internal/kernel): appid, async, cache, config, credentials, dbguard, eidflow, flags, httpx, memo, pgerr, resilience, security, settings, telemetry, usage ба гадаад системийн клиентүүд (appcatalog, eidrp, eidsign, gemini, geregecore, mailrail). Шууд import-ыг internal/planes_test.go, дамжсан хамаарлыг CI-ийн lint ажил шалгана.

Хамаарлын чиглэл нэг талдаа: урсгалууд цөмийг уншина, цөм урсгалыг мэдэхгүй.

Load shedder-ийн тааз нь нэг зэрэг 1000 хүсэлт. Түүнээс хойш ирсэн хүсэлт 503 авна — дараалал уртсаж бүх хүн хүлээхээс, зарим нь шууд хариу авах нь дээр.

Аппын уяа

backend/internal/apps нь distribution модулийн угсрах цэг. Экосистемийн стратегийн шалгуур нь «нэг ч бизнес аппгүйгээр ачаалж, апп бүрийг каталогоос авдаг платформ» — 2026-08-25-наас 09-21 хүртэл catalog/apps.json нь [] байв, 2026-10-25-наас дахин []. Хооронд нь (#66) ганц цөмд багтсан апп байсан — API гарц (io.gerege.nexus.api_gateway); 2026-10-25-нд хасагдаж, хүснэгтүүд нь 00160-аар устсан. Бусад апп (documents, urtuu, reports, egov, sso_clients г.м.) client-gerege-nexus ба appstore-gerege-nexus руу явсан; тэдгээрийн дэлгэц (frontend/app/module/*) цөмийн frontend образд зориуд үлдсэн — frontend-гүй distribution-ууд тэр образыг хуваалцдаг.

Апп бүр pkg/nexus-ээр өөрийгөө бүртгүүлж, каталогоор ирнэ. Дэлгэрэнгүйг Модуль бичих.

Хэмжсэн хэмжээс

2026-09-25-нд, доорх командаар (repo root-оос) тоологдсон. Тоо хөдөлсөн бол баримтыг бус командыг итгэ — хамгийн чухал хоёр нь (зам, schema) golden файл ба тестээр CI-д аль хэдийн шалгагддаг.

Утга Эх сурвалж
Go эх код (тестгүй) 61,674 мөр git ls-files 'backend/*.go' \| grep -v _test.go \| xargs cat \| wc -l
Go тест 40,437 мөр, 259 файл — эх кодын 66% git ls-files 'backend/*_test.go'
Frontend (TS/TSX, тест орно) 55,144 мөр, 369 файл git ls-files 'frontend/*.ts' 'frontend/*.tsx'
HTTP зам 192 өөр зам (184 платформ, 8 [app]), 76 нь /api/platform sed 's/^\[app\] //' backend/pkg/host/testdata/routes.txt \| awk '{print $2}' \| sort -u
Migration 128 файл, сүүлийнх 00129 (00113 зориуд алгассан) ls backend/db/migrations/*.sql; numbering_test.go
Schema-ийн хүснэгт 33 / 24 / 8 backend/db/migrations/schema_split_test.go
Каталог дахь апп 0 (2026-10-25-наас) catalog/apps.json

routes.txt нь МЕТОД зам хэлбэрийн 213 мөр; цөмийн аппын (registerAppModuleRoutes) 12 мөр нь [app] угтвартай. Mount/Handle-оор холбогдсон зам нэг ANY мөр болж бичигддэг (7 мөр). Нэг зам хэд хэдэн методтой байж болох тул мөрийн тоо замын тоо биш — GET/POST/PUT/DELETE мөр 206, /api/platform дээр 86. Тиймээс замыг [app] угтварыг хасаад өөр замаар (2-р багана) тоолно. Файлыг go test ./pkg/host -run TestTheRouteTable -update шинэчилнэ.

Тест нь хамгаалалт болж ажилладаг нь чухал: маршрутын golden file (pkg/host/testdata/routes.txt), schema-ийн хилийн тоолол, RLS бодлогын хэлбэр, гурван урсгалын import граф. Эдгээр нь онолын зөвийг биш, буруу зүйл чимээгүй нэвтрэхийг хардаг.

Гадагш хандах зам

Систем Юунд
Gerege ID Иргэний танилт, гарын үсэг
ДАН Төрийн танилт
ХУР (XYP) Лавлагаа
Gerege eSign (HSM) Байгууллагын гарын үсэг
Gemini AI туслах
Hosted email verify Хаяг баталгаажуулалт

Дуудлага бүр нэг histogram-аар хэмжигдэнэ — external_request_duration_seconds{system,operation,status}. Аль тал нь удааширсныг маргах шаардлагагүй байхын тулд.

Системийн нэр нь хаалттай олонлог (internal/kernel/telemetry/external.go). Танихгүй нэр other болж нугалагдана: тогтмолгүй нэр нь хэзээ ч арилахгүй time series үүсгэдэг.

Native бүрхүүл

macOS, iOS/iPadOS, Windows, Android — дөрвүүлээ нэг web shell ачаалж, нэг bridge гэрээгээр ярина (SHELL_CONTRACT.md). Дөрвөн удаа бичсэн апп биш, дөрвөн удаа савласан нэг апп.

Ажиглалт

Хэмжүүр бүр OpenTelemetry-ийн SDK-аар дамжиж, Prometheus exporter-ээр /metrics дээр гарна. HTTP-ийнх нь semantic convention-ыг дагана (http_server_request_duration_seconds); хүсэлтийн тоо нь тэр гистограммын _count цуврал.

Trace асаалттай үед гистограммын сэмпл бүр trace_id авч явна, тиймээс латенси графикийн удаан цэг нь тэр хүсэлтийн trace руу нээгддэг холбоос болно. Дэлгэрэнгүйг Ажиллагаа.