Агуулгыг алгасах

PetroNet System — petronet.mn

Монгол Улсын газрын тосны бүтээгдэхүүний импорт, хадгалалт, түгээлт, борлуулалтыг нэг өгөгдлийн урсгалд нэгтгэж, бодит цагт хянах систем. Захиалагч нь Ашигт малтмал, газрын тосны газар (АМГТГ); систем нь одоогийн mpetro-г орлоно — системийн шаардлага.

PetroNet System бол нэг програм биш, экосистем: оролцогч тус бүр — жолооч, ШТС, аж ахуйн нэгж, зохицуулагч — өөрийн платформтой бөгөөд тэдгээр нь доор нь нэг өгөгдөл, нэг танилт, нэг аудитын мөрийг хуваалцана. Дөрвүүлээ өөр ажилтай хүнийг нэг дэлгэцэнд шахах нь дөрвүүлээ таагүй байх зам.

Ямар асуудлыг шийдэж байгаа вэ

200 гаруй аж ахуйн нэгж, 110 гаруй агуулах, 1500 гаруй ШТС ажиллаж байгаа хэрнээ өгөгдөл нь хоорондоо холбогдоогүй хоёр системд, долоо хоногт нэг хоёр удаа гараар орж байна. Улсын хэмжээнд ямар түлш, хаана, хэдэн литр байгааг бодит цагт харах ганц эх сурвалж байхгүй — тиймээс нөөц таамгаар удирдагдаж, хямралын үед тэгш–сондгой дугаар шиг бүдүүлэг хэрэгсэл л үлддэг.

PetroNet дөрвөн зүйлийг нэг системд нэгтгэнэ:

Юу Хаана
1 Гинжин мөрдлөг — импортын гэрээ → гааль → чанар → терминал → тээвэр → ШТС-ын сав → хошуу → хэрэглэгч /supply
2 ШТС-ын POS — аль ч үйлдвэрлэгчийн түгээгүүр, ATG-д холбогдох драйверын давхарга, офлайнд ажиллана /stations
3 Ваучер — бодитоор ирсэн түлшнээс л эрх үүсгэж, ойр байршил ба хэрэгцээгээр хуваарилна /vouchers
4 Төрийн хяналт — нөөц, үнэ, чанар, татвар, зөрүүг өөрчлөх боломжгүй аудитын мөр дээр /oversight

Гол архитектурын шийдэл: ваучер = нөөцлөгдсөн литр. Ваучер нь ШТС-ын савд бодитоор орсон, ATG хэмжилтээр баталгаажсан түлшнээс л үүснэ. Ингэснээр амлалт нөөцөөсөө давахгүй, мөн хангалтаа мэдээлээгүй ШТС-д ваучер үүсэхгүй тул дуулгавартай байдал нь шалгагчаар биш дизайнаараа албадагдана.

Дэлгэрэнгүй: хөгжүүлэлтийн төлөвлөгөө · дэлхийн жишиг · системийн шаардлага.

Экосистемийн бүрэлдэхүүн

Платформ Хэнд Юу
Иргэний платформ Жолооч, иргэн Ойрын ШТС, түлшний төрөл, нөөцийн түвшин, өдрийн эрх ба ваучер. eID-ээр танина
ААН портал Аж ахуйн нэгж Агуулах, ШТС-ын объектын бүртгэл, савны үлдэгдэл, үеийн тайлан ирүүлэх ба засварлах
Зохицуулагчийн Command Center АМГТГ, хяналтын байгууллага Улсын өдрийн нэгтгэл, хоногийн нөөц, хамрах хүрээний цоорхой, тулгалтын зөрүү, дохиолол
ШТС-ын POS ба ирмэгийн агент ШТС Хошуу, сав, ээлж, төлбөр, баримт. Локал сантай — интернэт тасарсан ч борлуулалт зогсохгүй
Дата агуулах ба аналитик Шинжээч, удирдлага Өдөр бүрийн таталт, цэвэрлэгээ, бизнесийн загвар, BI ба прогноз
Консол ба ажиглалт Оператор Байгууллага, эрх, аудит — тусдаа нэвтрэлт. Хэмжүүр, дохиолол, нөөцлөлт

Эдгээрийн доор нэг Go бинарь, нэг өгөгдлийн сан, нэг танилт байна: экосистем нь олон сервер гэсэн үг биш, олон ажлын орон зай гэсэн үг. Гадагшаа нь ГЕГ, ХУР, e-Barimt, eID болон ATG/IoT төхөөрөмжүүдтэй холбогдоно.

Энэ репо юу вэ

Gerege Nexus-ийн хувийн цөм (gerege-systems/nexus-gerege-private) дээрх distribution. Цөм нь энэ репод core/ — хувийн цөмийн snapshot (core/SNAPSHOT), go.mod-ийн replace-ээр холбогдоно. Энэ бүтээгдэхүүний шатахууны бизнес логик modules/petro/-д, түүнд таарсан газрын зураг, операторын дэлгэц ба нийтийн мэдээллийн UI нь core/frontend-д залгаас хэлбэрээр.

core/-ийг гараар эсвэл rsync-ээр шинэчлэхгүй: deploy/sync-core.sh upstream diff-ийг git apply --3way-ээр тавьдаг тул залгаас хэвээр үлдэнэ, зөрчилдвөл зогсоно. Цөм шинэчлэгдэхэд core-sync.yml үүнийг автоматаар ажиллуулна.

2026-09-14 хүртэл PetroNet public open-gerege-nexus цөм дээр ажиллаж байсан — тэр түүх gerege-systems/petronet-gerege-nexus-old-д.

Модулиуд

io.gerege.nexus.petro (modules/petro/) нь бүх байгууллагад default сууна — main.go-гийн DefaultApps. ШТС ба агуулахын бүртгэл, түлшний төрөл ба нөөц, хил–бааз–цистерн–ШТС-ын гинжин мөрдлөг, 15 °C-ийн залруулга, тайлангийн үе ба хяналтын workflow, иргэний өдрийн эрх ба ваучер, зохицуулагчийн нэгтгэлийг нэг module migration history-тэй авч явна (modules/petro/migrations/). Каталог, manifest, chronicle нь catalog/-д байна.

Юу бэлэн болсон, юу дараагийн ээлжинд байгааг plan/PLAN.md §0 бүртгэсэн — тэр нь төлөвлөгөө биш, кодод байгаа зүйлийн жагсаалт.

Юу нь ялгаатай вэ

Нэвтрэлт Бие даасан — өөрийн нууц үг, өөрийн OIDC issuer. SSO_CLIENT_ISSUER хоосон
Домэйн petronet.mn, www.petronet.mn
Портууд 5441 / 8099 / 3028, зөвхөн loopback — цөмийн анхдагч биш
Сервер Тусдаа хост, ганцаараа

Портууд нь түүхэн сонголт: энэ хост дээр урьд нь хөрш систем зэрэгцэн ажиллаж 3008/8082/5434-ийг эзэлж байсан. Тэр систем 2026-09-03-нд алга болж портууд чөлөөтэй болсон ч энэ стек өөрийнхөө дээр үлдэнэ — ажиллаж буй суулгацын портыг солих нь compose, vhost, гэрчилгээ бүхнийг хөндөөд хариуд нь юу ч өгөхгүй.

Үүнээс мөрдөгдөх дүрэм хэвээр: nginx/petronet.mn.conf нь цөмийн snippets/nexus-oauth.conf-ыг include хийхгүй — тэр snippet 127.0.0.1:8082 гэж хатуу бичсэн бөгөөд энэ стекийн backend 8099 дээр байна.

Байрлуулалт

Сервер дээр /opt/petronet-v2/ — src/ энэ репогийн git checkout, .env (chmod 600), brand/. Хост дээр гараар git pull хийхгүй — прод руу ганц зам:

commit → PR → main → CI (ci.yml) ✓ → Deploy (deploy.yml)
  → self-hosted runner: deploy/ci-deploy.sh <sha>   # git reset --hard <sha>
  → ./deploy.sh                                     # build, migrate, verify, rollback

Дэлгэрэнгүй: CLAUDE.md, docs/DEPLOYMENT.md.

deploy.sh нь backend болон web хоёр образыг энэ repository-оос хамт барина. Ингэснээр Fuel module-ийн API, газрын зураг, операторын дэлгэц нэг revision-оор гарна; тусдаа WEB_IMAGE эсвэл registry login шаардлагагүй.

Найман нэр

Нэр Юу Ард нь
petronet.mn Платформ — frontend ба /api/v1/* Next.js + Go
admin.petronet.mn Операторын консол — /api/platform/v1/* Мөн тэр хоёр
developer.petronet.mn Хөгжүүлэгчийн портал — OAuth клиент, scope, түлхүүр (цөмийн /dev) Мөн тэр хоёр, DEVELOPER_HOST
monitoring.petronet.mn Grafana Prometheus + хоёр exporter
dwh.petronet.mn Дата агуулахын зураглал Статик, өөрийн контейнер
docs.petronet.mn PetroNet System-ийн ажиллагааны баримт Статик, өөрийн контейнер
plan.petronet.mn Төслийн баримт — шаардлага, төлөвлөгөө, жишиг Статик, өөрийн контейнер
backups.petronet.mn Нөөцлөлтийн тайлбар Статик; сан нь өөр хостод

Хаягууд нь кодод биш, .env-ийн SERVICE_URL_*-д: нүүр хуудас тохируулсныг нь л карт болгож зурна.

Дөрвөн статик хуудас өөрийн контейнерээс үйлчилнэ — агуулга нь репод, зам нь compose-д, тиймээс шинэчлэх нь ердийн deploy (дээрх зам). Хостын файлын систем рүү гараар хуулах алхам байхгүй.

Эдгээрээс гадна төхөөрөмжийн дөрвөн шугам байна — desktop. / mobile. / kiosk. / pos.petronet.mn. Тэдгээр нь өөр үйлчилгээ БИШ: яг ижил frontend ба API, зөвхөн өөр origin дээр, native клиент бүрийн webview доторх дуудлага same-origin байхын тулд. Дөрвүүлэн хараахан асаагүй — Байрлуулалт § Төхөөрөмжийн шугамууд.

Native клиентүүд

native-apps/ дотор дөрвөн клиент, хоёр шугам: macOS ба Windows нь PetroNetDesktop (desktop.petronet.mn), iOS/iPadOS ба Android нь PetroNetMobile (mobile.petronet.mn). Аппын нэр нь платформыг биш ТӨХӨӨРӨМЖИЙН ШУГАМЫГ нэрлэдэг: хүн ширээн дээрх Mac, Windows хоёртой ижил байдлаар харьцдаг тул тэд нэг апп.

Гурван зарчим: клиентэд secret байхгүй (бүх дуудлага өөрийн web backend-ийн нийтийн /api/… route-уудаар — хөтөчтэй яг ижил зам); identity нь session биш snapshot (Keychain / Android Keystore); харагдах нэр нь PetroNet. Өнгө нь frontend/app/petronet.css-ээс — хөтөч дээрх PetroNet ба гар дээрх PetroNet нэг бүтээгдэхүүн шиг уншигдана.

Эх нь Gerege Nexus-ийн native-apps/; энд ирэхдээ нэр, bundle ID, шугамын хаяг, палитр солигдсон ч бүтэц, гэрээ, урсгал нь ЭХ ХЭВЭЭР — цөмийн засварыг буулгах нь механик ажил хэвээр байхын тулд. Дэлгэрэнгүй: native-apps/README.md.

Операторын консол

admin.petronet.mn — тенантын лавлах биш, платформын өөрийн консол: тусдаа нэвтрэлт, тусдаа cookie, тусдаа audit, тусдаа DB role. Хаягийн нэршил нь цөмийн docs/CONTROL_PLANE.md §3.1-ийн admin.<домэйн>.

Эхний операторыг доорх шидтэн үүсгэнэ (нууц үг + authenticator). Хоёр дахийг консол өөрөө үүсгэнэ.

Шидтэн өнгөрсөн бол — түүний токен байгууллага үүсмэгц үхдэг — эхний оператор нь shell-ээс:

ssh <host> -t \
  'docker exec -it petronet2_backend /app/operator-bootstrap \
     -email та@жишээ.mn -name "Таны нэр"'

Нууц үгийг хоёр удаа асууж (≥12), TOTP-ийн түлхүүр ба otpauth:// хаягийг нэг удаа үзүүлнэ. Authenticator-т нэмээд кодоор баталгаажуулна. Нууц үгийг flag эсвэл env-д бүү дамжуул: shell-ийн түүх, процессын жагсаалтад үлдэнэ.

Хаягийн хязгаарлалт одоогоор тавиагүй. nginx/admin.petronet.mn.conf дотор шалтгаан ба сэргээх хоёр мөрийг бичсэн — операторуудын хаяг тодрох өдөр тэрийг асаана. Одоогоор консолыг хамгаалж байгаа зүйл нь хаягийн хаалга (CONTROL_PLANE_HOST), нууц үг, ба authenticator-ийн код гурав.

Ажиглалт

monitoring.petronet.mn — Grafana, стекийн өөрийн Prometheus дээр. Хоёр самбар цөмөөс хуулагдсан (API-гийн тойм, дэд бүтэц); Loki рүү заасан панелиудыг хассан — энд лог цуглуулагч байхгүй, байхгүй эх сурвалж заасан панель нь «datasource not found» гэж хариулна.

Гурван зорилт: энэ бүтээгдэхүүний API, хостын node_exporter, ба PetroNet System-ийн сангийн postgres_exporter. Хөрш дээр node_exporter аль хэдийн ажилладаг ч түүний порт 127.0.0.1 дээр уягдсан тул контейнерээс хүрэх зам байхгүй — өөрийнхөө нэгийг ажиллуулна.

Баримт бичиг

docs/ — платформын бүх баримт, PetroNet System-ийн нэр, хаягаар брэндлэгдсэн, дээр нь docs/DEPLOYMENT.md: зөвхөн энэ хостын тухай баримт. Хуулсан шалтгаан нь захиалагч тал бүхнийг нэг газраас уншиж чадах ёстой явдал — платформынхаа баримтыг өөр репо руу заасан холбоосоор орлуулах нь баримт биш, шилжүүлэг. Гарал үүслийг нь docs/README.md-ийн эхний хэсэг тайлбарлана.

plan/ — төслийн баримт: захиалагчийн системийн шаардлага, хөгжүүлэлтийн төлөвлөгөө, дэлхийн жишиг, ба дотоод хэрэглээний бүрэн төлөвлөгөө (plan/petronet-plan.md — нийтлэгддэггүй).

Хоёулаа MkDocs-оор угсардаг, нэг угсрагчаар, өөр өөр хаяг руу:

sh docs/mkdocs/build.sh        # docs.petronet.mn → docs/mkdocs/build/site
sh docs/mkdocs/build.sh plan   # plan.petronet.mn → docs/mkdocs/build-plan/site

Тэдгээр нь хоёр өөр уншигчийнх: docs нь ажиллаж буй системийг долоон хэлээр тайлбарладаг, plan нь юу барихаар тохирсныг монголоор. Гаралт нь артефакт (.gitignore). Хостод Python суулгахгүй — MkDocs контейнерээр ажиллана. Баримт өөрчлөгдвөл дахин угсраад docker compose restart docs plan.

Нууцууд

Нууцын сан (Infisical) дээрх petronet-gerege-nexus төслийн prod орчин нь PetroNet System-ийн нууцуудын эх сурвалж: сангийн нууц үг, built-in клиентийн нууц, eID-ийн relying-party хос, Gerege Core-ийн токен, Grafana-гийн админ, ба нөөцлөлтийн age нийтийн түлхүүр.

Хостын .env нь тэдгээрийн хуулбар. Эх сурвалж нь тэнд байгаа нь чухал: хост дахин суухад юуг бөглөх ёстойг санах хүн хэрэггүй, мөн нэг нууцыг солих нь нэг л газарт хийгддэг ажил болно.

age-ийн хувийн түлхүүр энд ч, хостод ч байхгүй — тэр нь open-gerege-nexus төсөлд, операторт. Хостод зөвхөн нийтийн түлхүүр байгаа нь санаатай: эвдэрсэн платформ өөрийн илгээсэн нөөцлөлтөө уншиж чадахгүй.

Нөөцлөлт

deploy/scripts/backup.sh — өдөр бүр 03:15-д cron-оор. pg_dump авч, 14 хоногоос хуучныг цэвэрлэж, үр дүнг platform_backups-д бичнэ (консол тэр мөрийг уншина). Хэмжигдээгүй нөөцлөлт нь нөөцлөлтгүйтэй бараг адил тул бүтэлгүйтэл ч бүртгэгдэнэ.

Дискэн дээрх хуулбар нь тэр дискийг алдвал хамт алга болно. Өөр байршил руу шифрлэн илгээх алхам нь скриптэд бэлэн — BACKUP_AGE_RECIPIENT (age-ийн нийтийн түлхүүр; хувийнх нь операторт байна) ба BACKUP_S3_* дөрөв тавигдмагц ажиллана. Тавиагүй бол алхам чимээгүй алгасагдаж, petronet_backup_offsite_ok 0 гэж хэмжигдэнэ.

Хэмжүүр

Стек өөрийн Prometheus-той (deploy/monitoring/prometheus.yml), ганц зорилт — энэ бүтээгдэхүүний API. Консолын «Платформын эрүүл мэнд» дэлгэц түүнээс уншина (PROMETHEUS_URL).

Хөрш дээр бүтэн мониторингийн стек ажилладаг ч түүнийг хуваалцаагүй: консолын асуулгууд job-оор шүүдэггүй тул хоёр бүтээгдэхүүний хүсэлт нийлж, хөршийн тоо PetroNet System-ийн нэрээр харагдах байв. Disk, санах ой, Postgres-ийн хэмжигдэхүүн одоогоор алга — тэдгээрийн exporter хөршийнх. Консол унасан асуулгыг орхидог тул дэлгэц худал тоо биш, дутуу хэсэгтэй харагдана.

ssh -L 9093:127.0.0.1:9093 <host>   # Prometheus-ыг өөрөө харах

Эхний байгууллага, эхний админ

Цөмийн эхний ачааллын шидтэн (/setup). Байгууллагагүй үед л зэвсэглэдэг: токен нь ачаалах үед санах ойд үүсч, лог руу нэг удаа бичигдэж, байгууллага үүсмэгц устдаг.

docker logs petronet2_backend 2>&1 | grep -i "setup token"

Дараа нь https://petronet.mn/setup дээр тэр токеноор орж байгууллага, админаа үүсгэнэ. Сүүлийн алхам нь операторын консолын эхний бүртгэл — алгасаж болно. Байгууллага үүссэний дараа энэ зам 404 болно.

Өөрийн модуль нэмэх

modules/<нэр>/ үүсгээд main.go-гийн Options.Modules callback дотор Fuel module-ийн хажууд бүртгэнэ. Түвшин 2-ын бүтэцтэй тул дараагийн module нэмэхэд platform core-ийг fork хийх шаардлагагүй.

Өөрийн хүснэгттэй бол modules/<нэр>/migrations/00001_<нэр>.sql гэж бичээд конструктораасаа бүртгэнэ:

//go:embed migrations/*.sql
var migrations embed.FS

func New(p nexus.Platform) *Module {
    m := &Module{...}
    nexus.Register(m)
    nexus.Migrations(m.ID(), schema()) // fs.Sub(migrations, "migrations")
    return m
}

Каталог: catalog/apps.json, catalog/manifests/<slug>.json, ба хувилбарын түүхээ catalog/chronicle/<slug>.json-д. Образ нь энэ репогийн каталогийг цөмийнхтэй нийлүүлдэг — бинарь дотор байгаа аппыг каталог нэрлээгүй бол систем асахаас татгалзана.

Дэлгэрэнгүй заавар: MODULE_AUTHORING_GUIDE.md.