* feat(docs): mirror every docs/ page in all 65 locales Extends the documentation mirrors from the 22-page core set (#13940) to every Markdown page under docs/: 152 sources x 65 locales = 9,880 mirrors (6,208 new), language bars rewritten for the full locale list, state adopted so the blocking drift gate now covers all 152 pages. run-translation.mjs: an oversized block made only of table rows or list items (PROVIDER_REFERENCE.md 244-row table, FREE_TIERS.md 71-item list) is cut at item boundaries and rejoined without a blank line — the single 16-40 KB request outlived the backend socket for verbose scripts. 48 older mirrors whose tables had lost rows were retranslated with --force. * docs(i18n): refresh mirrors for the sources the base changed since the branch cut Section-level retranslation of the 29 docs (and README.md) whose source or mirrors moved on release/v3.8.51 during the run, then state adoption; the drift gate is green again on the merged tree.
120 KiB
Radar Free-Model Catalog (ខ្មែរ)
🌐 Languages: 🇺🇸 English · 🇪🇹 am · 🇸🇦 ar · 🇦🇿 az · 🇧🇬 bg · 🇧🇩 bn · 🇨🇿 cs · 🇩🇰 da · 🇩🇪 de · 🇬🇷 el · 🇪🇸 es · 🇪🇪 et · 🇮🇷 fa · 🇫🇮 fi · 🇫🇷 fr · 🇮🇪 ga · 🇮🇳 gu · 🇳🇬 ha · 🇮🇱 he · 🇮🇳 hi · 🇭🇷 hr · 🇭🇺 hu · 🇦🇲 hy · 🇮🇩 id · 🇳🇬 ig · 🇮🇹 it · 🇯🇵 ja · 🇬🇪 ka · 🇮🇳 kn · 🇰🇷 ko · 🇱🇹 lt · 🇱🇻 lv · 🇮🇳 ml · 🇮🇳 mr · 🇲🇾 ms · 🇲🇹 mt · 🇲🇲 my · 🇳🇵 ne · 🇳🇱 nl · 🇳🇴 no · 🇮🇳 or · 🇮🇳 pa · 🇵🇭 phi · 🇵🇱 pl · 🇵🇹 pt · 🇧🇷 pt-BR · 🇷🇴 ro · 🇷🇺 ru · 🇱🇰 si · 🇸🇰 sk · 🇸🇮 sl · 🇷🇸 sr · 🇸🇪 sv · 🇰🇪 sw · 🇮🇳 ta · 🇮🇳 te · 🇹🇭 th · 🇹🇷 tr · 🇺🇦 uk-UA · 🇵🇰 ur · 🇺🇿 uz · 🇻🇳 vi · 🇳🇬 yo · 🇨🇳 zh-CN · 🇹🇼 zh-TW
ប្រភពយោងចម្បង:
src/lib/radar/,src/lib/db/radar.ts,src/app/api/radar/បានធ្វើបច្ចុប្បន្នភាពចុងក្រោយ: 2026-09-01 — v3.8.51 ដែនកំណត់ភស្តុតាងនៃសេវាបង្ហោះ: ច្បាប់ផ្នែកម៉ាស៊ីនមេដែលបានពិពណ៌នានៅទីនេះ ត្រូវបានផ្ទៀងផ្ទាត់នៅ 2026-09-01 ជាមួយនឹងម៉ាស៊ីនមេ Radar ឯកជនដោយចេតនា នៅកំណែសម្រួលជាក់លាក់main@dce70f004364912f3f144cdb69f4cbcde16093ed។ ការអនុវត្តនោះមិនត្រូវបានចែកចាយក្នុង ឃ្លាំង OSS នេះទេ; ភាពអាចប្រើបាននៃសេវាបង្ហោះនៅតែជាស្ថានភាពប្រតិបត្តិការដាច់ដោយឡែក។
Radar គឺជា កម្មវិធីបន្ថែមជាជម្រើស ដែលដាក់កាតាឡុកម៉ូដែលឥតគិតថ្លៃ ដែលបានចុះហត្ថលេខា និងរៀបចំបច្ចុប្បន្នភាពថ្មីៗ
ពីលើទិន្នន័យគោលនៃកំណែចេញផ្សាយ (FREE_MODEL_BUDGETS ក្នុង
open-sse/config/freeModelCatalog.data.ts)។ វាមានឡើងដោយសារបរិបទនៃកម្រិតឥតគិតថ្លៃប្រែប្រួល
លឿនជាងវដ្តនៃការចេញផ្សាយ — អ្នកផ្តល់សេវាអាចបន្ថែម កាត់បន្ថយ ឬបញ្ឈប់កូតាឥតគិតថ្លៃនៅចន្លោះ
ការចេញផ្សាយនីមួយៗ ហើយកាតាឡុកគោលអាចធ្វើបច្ចុប្បន្នភាពបានតែនៅពេលកំណែថ្មីត្រូវបានចេញផ្សាយប៉ុណ្ណោះ។
អ្វីដែលឥតគិតថ្លៃនៅថ្ងៃនេះ នឹងមិនឈប់ឥតគិតថ្លៃដោយសារតែ feed ពីចម្ងាយឡើយ។ Radar មិនដែល ដាក់ធាតុគោលណាមួយក្រោយរបាំងបង់ប្រាក់ទេ; វាគ្រាន់តែធ្វើបច្ចុប្បន្នភាពវាលដែនកំណត់/ស្ថានភាពនៅពេលអាន ហើយអាច បន្ថែមជាស្រទាប់នូវម៉ូដែលឥតគិតថ្លៃដែលទើបរកឃើញថ្មីនៅចន្លោះការចេញផ្សាយ។ ប្រតិបត្តិករនៅតែអាចលាក់ ម៉ូដែលមួយក្នុងមូលដ្ឋាន ហើយអាចស្ដារវាឡើងវិញពីផ្ទាំងគ្រប់គ្រងដដែល។ កាតាឡុកគោលខ្លួនវា មិនត្រូវបានកែប្រែនៅលើថាសឡើយ — សូមមើល ច្បាប់បញ្ចូល overlay នៅពេលអាន ខាងក្រោម។
ស្ថានភាពនៃការផ្ដល់ជូនក្នុង v3.8.51
ស្ថានភាពខាងក្រោមបែងចែកអ្វីដែលកំណែ OSS នេះអនុវត្ត ពីខ្សែការងារ Radar នៅពេលក្រោយ។ វាជាស្ថានភាពកម្រិតកូដ មិនមែនជាការសន្យាថាការដាក់ឱ្យដំណើរការលើសេវាបង្ហោះជាក់លាក់ណាមួយ ឬសមាហរណកម្មខាងក្រៅណាមួយ កំពុងអាចប្រើបាននាពេលបច្ចុប្បន្ននោះទេ។
| ផ្នែក | ស្ថានភាពក្នុងកំណែចេញផ្សាយនេះ |
|---|---|
| កម្មវិធីអតិថិជនកាតាឡុកដែលបានចុះហត្ថលេខា | បានអនុវត្តនៅពីក្រោយ RADAR_ENABLED ដោយមានការចូលរួមតាមជម្រើសដាច់ដោយឡែក ការផ្ទៀងផ្ទាត់ Ed25519 ការកំណត់/ឃ្លាំងសម្ងាត់ក្នុងមូលដ្ឋានដែលបានអ៊ិនគ្រីប ការកំណត់ជំនួសសម្រាប់ការបង្ហាញ/បើកប្រើដែលរក្សាទុកជាអចិន្ត្រៃយ៍ tombstone ដែលអាចត្រឡប់វិញបាន កម្មវិធីកំណត់ពេល និងផ្ទាំងគ្រប់គ្រង។ |
| ការធ្វើឱ្យសកម្មសម្រាប់អ្នករួមចំណែក | ផ្ទាំងគ្រប់គ្រងភ្ជាប់ទៅលំហូរទាមទារសិទ្ធិ GitHub ដែលបង្ហោះនៅលើម៉ាស៊ីនមេ ហើយទទួលយកសោ omr_… ដែលមានស្រាប់។ សិទ្ធិមានលក្ខណៈសម្បត្តិរបស់អ្នករួមចំណែកត្រូវបានកំណត់ដោយសេវាឯកជន; កម្មវិធីអតិថិជន OSS មិនមាន token GitHub ឬតក្កវិជ្ជាចេញសោទេ។ |
| ការធ្វើឱ្យសកម្មដោយសោអ្នកគាំទ្រ | បានអនុវត្ត។ សោដើមត្រូវបានផ្ទៀងផ្ទាត់ អ៊ិនគ្រីបនៅពេលរក្សាទុក បិទបាំងនៅពេលអាន និងផ្ញើតែដោយការធ្វើសមកាលកម្មផ្នែកម៉ាស៊ីនមេប៉ុណ្ណោះ។ ការផ្លាស់ប្តូរ ឬសម្អាតសោ នឹងធ្វើឱ្យឃ្លាំងសម្ងាត់ feed ទាំងបួនដែលពាក់ព័ន្ធនឹងសិទ្ធិប្រើប្រាស់អស់សុពលភាព។ |
| តំណណែនាំបន្ត | បានអនុវត្តជាទម្រង់ feed ដែលបានចុះហត្ថលេខាដាច់ដោយឡែក និងធ្វើបច្ចុប្បន្នភាពរៀងរាល់ម៉ោង។ តំណថេរអាចប្រើបានភ្លាមៗសម្រាប់កម្រិតសហគមន៍; យុទ្ធនាការដែលមានកំណត់នៅតែជាទិន្នន័យផ្ទាល់តាមកម្រិត។ |
| ការផ្ដល់ជូនសម្រាប់អ្នកគាំទ្រ | បានអនុវត្តជាទម្រង់ feed ដាច់ដោយឡែក ដែលមានការចុះហត្ថលេខា ប្រើបានតែនៅពេលផ្ទាល់ និងទំព័រផ្ទាំងគ្រប់គ្រង។ កម្មវិធីអតិថិជនផ្ទៀងផ្ទាត់ schema អត្ថប្រយោជន៍បិទជាថ្មី រក្សាឃ្លាំងសម្ងាត់ល្អចុងក្រោយ ត្រងធាតុផុតកំណត់ និងដាក់ស្លាកការផ្ដល់ជូនរបស់ដៃគូយ៉ាងច្បាស់។ |
| ព័ត៌មានស៊ីជម្រៅ និងការទទួលស្គាល់អ្នកគាំទ្រ | បានអនុវត្តជាទម្រង់ feed ផ្ទាល់តែប៉ុណ្ណោះ ដែលបានចុះហត្ថលេខាយ៉ាងតឹងរ៉ឹង ជាមួយ ELO ដែលគ្រប់គ្រងដោយ Radar ភាពថ្មីទាន់សម័យ/និន្នាការរបស់កាតាឡុកផ្អែកលើអង្គហេតុ ផ្លាកសញ្ញាអ្នកគាំទ្រក្នុងមូលដ្ឋានដែលបានផ្ទៀងផ្ទាត់ ទំព័រផ្ទាំងគ្រប់គ្រង និងពាក្យបញ្ជាស្ថានភាព/សមកាលកម្ម CLI សម្រាប់តែក្នុងមូលដ្ឋាន។ |
| ការទូទាត់ និងអ៊ីមែលប្រតិបត្តិការ | មិនត្រូវបានអនុវត្តក្នុងកម្មវិធីអតិថិជន OSS ទេ។ ការទិញ ការបរិច្ចាគ ការត្រួតពិនិត្យបង្កាន់ដៃ ការស្ដារឡើងវិញ និងការផ្ញើសំបុត្រ ជាកម្មសិទ្ធិរបស់សេវាឯកជន; ភាពអាចប្រើបាននៃសេវាបង្ហោះនៅតែអាស្រ័យលើការដាក់ឱ្យដំណើរការដែលមានការត្រួតពិនិត្យ និងការកំណត់រចនាសម្ព័ន្ធរបស់អ្នកផ្តល់សេវា។ |
| ខ្សែការងារភ្នាក់ងារស្រាវជ្រាវ | មិនមែនជាផ្នែកនៃកំណែកម្មវិធីអតិថិជននេះទេ។ ខ្លឹមសារ feed ដែលបានរៀបចំជ្រើសរើសនៅតែជាទិន្នន័យផ្នែកម៉ាស៊ីនមេ; មិនមានភ្នាក់ងារស្រាវជ្រាវស្វយ័តណាមួយដំណើរការក្នុងការដំឡើង OmniRoute ទេ។ |
កម្មវិធីអានសេចក្តីប្រកាសសាធារណៈ
កម្មវិធីអានសេចក្តីប្រកាសទូទៅដាច់ដោយឡែកពី feature flag របស់ Radar។ ទំព័រដើមនៃ dashboard និង
កម្មវិធីមើល Changelog ទាញយក news.json សាធារណៈរបស់ repository តាមរយៈ GET ធម្មតាទៅកាន់
NEWS_JSON_URL (src/shared/utils/releaseNotes.ts)។ ពួកវាមិនផ្ញើការកំណត់ Radar, prompt, ការកំណត់
provider, កំណត់ត្រាប្រើប្រាស់ ឬស្ថានភាពបិទសេចក្តីជូនដំណឹងនៅក្នុងមូលដ្ឋានណាមួយឡើយ។
news.json ប្រើ schema v2 បិទដែលអនុវត្តដោយ parseNewsPayload()៖
schemaVersion: 2និងសំណុំitems[]ដែលមានដែនកំណត់;- តម្លៃ
idរបស់សេចក្តីប្រកាសដែលមានស្ថិរភាព និងមិនស្ទួន; - field
activeនិងpublishedAtជាទម្រង់ ISO ដែលបានកំណត់យ៉ាងច្បាស់; - ខ្លឹមសារជាភាសាអង់គ្លេសដែលតម្រូវឱ្យមាន ជាមួយខ្លឹមសារបកប្រែតាមមូលដ្ឋានស្រេចចិត្ត;
- តំណ HTTPS ដែលមិនត្រូវការព័ត៌មានសម្ងាត់ និង icon ដែលស្ថិតក្នុងបញ្ជីអនុញ្ញាត ជាជម្រើស;
- ការជ្រើសរើសធាតុសកម្មថ្មីបំផុតមុន, ការត្រឡប់ទៅប្រើភាសាអង់គ្លេសនៅពេលគ្មាន locale ដែលត្រូវគ្នា និងការបិទតាម
idនីមួយៗនៅក្នុងមូលដ្ឋាន។
parser ទទួលយកជាបណ្តោះអាសន្ននូវទម្រង់ឯកវចនៈពីមុន { active, title, message, ... } ដើម្បីឱ្យ
fork ចាស់ៗអាចធ្វើ migration ដោយមិនធ្វើឱ្យទិដ្ឋភាព Changelog ខូច។ feed មិនត្រឹមត្រូវនឹងមិនធ្វើសកម្មភាពអ្វីឡើយ។ ធាតុចាប់ផ្តើម Radar
ត្រូវបានចេញផ្សាយជាមួយ active: false; ការប្តូរវាទៅជា true គឺជាសកម្មភាពចេញផ្សាយដាច់ដោយឡែក
ក្រោយ merge និងក្រោយ deploy ហើយមិនផ្លាស់ប្តូរ RADAR_ENABLED ឬការយល់ព្រមដាច់ដោយឡែកសម្រាប់ feed-sync ឡើយ។
Flag៖ RADAR_ENABLED (បិទតាមលំនាំដើម)
Radar ត្រូវបានគ្រប់គ្រងពីដើមដល់ចប់ដោយ feature flag RADAR_ENABLED
(src/shared/constants/featureFlagDefinitions.ts, ប្រភេទ policies,
defaultValue: "false")។
នៅពេល flag ត្រូវបានបិទ ផ្ទៃប្រើប្រាស់នេះមិនមានទេ៖
- endpoint
/api/radar/*ទាំងអស់ រួមទាំងការអាន និងសរសេរស្ថានភាព model ក្នុងមូលដ្ឋាន នឹងត្រឡប់404មុនពេលប៉ះពាល់ module Radar ណាមួយ។ - អេក្រង់ dashboard (
/dashboard/radar,/dashboard/radar/setup,/dashboard/radar/combos,/dashboard/radar/offers,/dashboard/radar/intel) បង្ហាញnotFound()។ getRadarCatalog()(src/lib/radar/index.ts) ត្រឡប់ baseline ដដែលដោយគ្មានការកែប្រែ — ចំនួនធាតុដូចគ្នា, តម្លៃដូចគ្នា, ហើយធាតុនីមួយៗត្រូវបានដាក់ tagorigin: "baseline"— និងមិន អាន feed cache ឡើយ។- គ្មាន network call របស់ Radar ណាមួយត្រូវបានធ្វើឡើយ; sync module នីមួយៗត្រឡប់
{ status: "disabled" }មុនពេលប៉ះពាល់fetch។
នេះគឺជា gate ប្រភេទ strict superset៖ ការបើក flag គ្រាន់តែដោះសោ អេក្រង់ ប៉ុណ្ណោះ មិនមានអ្វីលើសពីនេះទេ។ វាមិន upload ទិន្នន័យ, មិនចាប់ផ្តើម background sync និងមិនផ្លាស់ប្តូរ routing ឬការជ្រើសរើស model ទេ — សូមមើលការយល់ព្រមដាច់ដោយឡែកខាងក្រោម។
ការ sync ទិន្នន័យគឺជាការយល់ព្រមដាច់ដោយឡែក — ការសន្យាអំពីភាពឯកជន
ការបើក RADAR_ENABLED គ្រាន់តែដោះសោ UI ប៉ុណ្ណោះ។ ការ sync feed តម្រូវឱ្យមានការយល់ព្រមទីពីរ
ដែលឯករាជ្យ និងរក្សាទុកក្នុង radar_settings.opt_in (src/lib/db/radar.ts,
migration 136_radar_cache_settings.sql)។ syncRadar() ពិនិត្យ flag និង ការយល់ព្រម
មុនពេលធ្វើ network call ណាមួយ៖
Flag បិទ → { status: "disabled" } — គ្មាន network call
Opt-in false → { status: "opt_out" } — គ្មាន network call
នៅពេលទាំងពីរត្រូវបានបើក ផ្លូវ sync គឺ៖
GET <feed base URL>/v1/catalog/latestជាមួយx-omniroute-radar-schema: 2និង headerAuthorization: Bearer <supporter key>ជាជម្រើស (សូមមើលខាងក្រោម)។ Server នឹងប្រើ artifact ផ្លាស់ប្តូរ v1 ដែលបានចុះហត្ថលេខាដាច់ដោយឡែកតាមលំនាំដើម នៅពេលគ្មាន schema header ដូច្នេះ client ចាស់ៗដែលបានដំឡើងរួចនៅតែបន្តទទួលបាន update។- នេះគឺជាលំហូរកម្មវិធីសម្រាប់ download តែប៉ុណ្ណោះ ប៉ុន្តែវានៅតែជាសំណើ HTTPS។ ហេដ្ឋារចនាសម្ព័ន្ធ ដែលបាន host ទទួល metadata នៃការតភ្ជាប់ធម្មតា ដូចជា IP ប្រភព។ នៅពេល supporter key ត្រូវបានកំណត់ ការ sync ក៏ផ្ញើ key នោះនៅក្នុង Bearer header ផងដែរ ដើម្បីឱ្យ service អាចកំណត់ entitlement។ នៅ revision ជាក់លាក់របស់ private-server ដែលបានកំណត់ក្នុងព្រំដែនភស្តុតាងខាងលើ ការកត់ត្រាគណនីសំណើ feed ប្រើ hash របស់ key, ការប្រើប្រាស់សរុប និង HMAC កាត់ខ្លីនៃ IP ដែលប្តូររៀងរាល់ថ្ងៃ សម្រាប់ការត្រួតពិនិត្យការបំពានដោយដៃ; table ទាំងនោះមិនរក្សាទុក key ឬ IP ក្នុងទម្រង់ដើមឡើយ។ Access log របស់ហេដ្ឋារចនាសម្ព័ន្ធ និង delivery outbox ដែលបាន encrypt គឺជាព្រំដែនប្រតិបត្តិការដាច់ដោយឡែក។
- OmniRoute មិនដែលផ្ញើ prompt, response, conversation, ព័ត៌មានសម្ងាត់របស់ provider, ចរាចរណ៍ model, uptime, latency ឬការកំណត់ provider ក្នុងមូលដ្ឋានទៅកាន់ service Radar ឡើយ។
- response ត្រូវបានផ្ទៀងផ្ទាត់, ធ្វើ validation និង cache ក្នុងមូលដ្ឋាន (សូមមើល
គំរូសុវត្ថិភាព)។ Radar មានផ្លូវ network ខាង server ចំនួនបួនគត់៖
syncRadar()សម្រាប់ catalog,syncRadarReferrals()សម្រាប់ referral និងsyncRadarOffers()/syncRadarIntel()សម្រាប់ offer និង Intel ដែលមានសម្រាប់តែ supporter។
supporter key គឺជា Bearer token ជាជម្រើស (radar_settings.supporter_key)
ដែលអនុញ្ញាតឱ្យ feed service សម្រេចថាត្រូវផ្តល់ tier មួយណា (សូមមើល
Tier)។ វា៖
- ត្រូវបានរក្សាទុកដោយ encrypt នៅពេលស្ថិតនៅក្នុង storage ជាមួយ helper AES-256-GCM
encrypt()/decrypt()ដូចគ្នា (src/lib/db/encryption.ts) ដែលប្រើសម្រាប់ព័ត៌មានសម្ងាត់របស់ provider។ - ត្រូវបានកំណត់តាមរយៈ
POST /api/radar/settings({ supporterKey: "omr_" + 40 hex chars }) និង មិនត្រូវបានបញ្ជូនត្រឡប់មកវិញឡើយ — response ត្រឡប់ទម្រង់ដែលបានបិទបាំង (omr_****abcd)។ - ការផ្លាស់ប្តូរ ឬលុបវានឹងធ្វើឱ្យ cache របស់ catalog, referral, offer និង Intel អសុពលភាពដោយអាតូមិក។ ការ sync/read បន្ទាប់នឹងកំណត់ entitlement ថ្មីនៅខាង server; ការរក្សាទុក key មិនធ្វើ network request ដោយខ្លួនឯង ឬប្រើប្រាស់ activation key ដែលប្រើបានតែម្តងឡើយ។
- ត្រូវបានផ្ញើទៅ feed service ជា Bearer token នៅពេល sync GET — គ្មានព័ត៌មានផ្សេងទៀតអំពី key ចាកចេញពី client ឡើយ។
ច្បាប់សិទ្ធិចូលប្រើ និងសុវត្ថិភាពដែលបង្ហាញមុនពេលយល់ព្រមចូលរួម
ផ្ទាំងគ្រប់គ្រងដែលមិនទាន់ដំណើរការ បង្ហាញច្បាប់ទាំងនេះពី
src/app/(dashboard)/dashboard/radar/RadarAccessExplainer.tsx មុនពេល អនុវត្តសកម្មភាពបើកដំណើរការណាមួយ។
កម្រិតសិទ្ធិចូលប្រើផ្លូវការគឺ៖
| កម្រិត | លក្ខខណ្ឌមានសិទ្ធិ | សិទ្ធិចូលប្រើ | ច្បាប់អំពីការផ្តល់ឡើងវិញ/ផុតកំណត់ |
|---|---|---|---|
| សហគមន៍ | អ្នកណាក៏បាន; មិនត្រូវការសោ | កាតាឡុកពេញលេញដែលពន្យារពេលប្រហែល 30 ថ្ងៃ | អាចប្រើបានជានិច្ច; គ្មានការចេញសិទ្ធិ |
| ដាក់ផ្កាយ + តាមដាន | GitHub OAuth ផ្ទៀងផ្ទាត់ទាំងការដាក់ផ្កាយលើឃ្លាំង និងការតាមដានម្ចាស់ | អានកាតាឡុកបច្ចុប្បន្នមួយដង បន្ទាប់មកត្រឡប់ទៅកម្រិតសហគមន៍ | ផ្តល់មួយដងក្នុងការចូលនីមួយៗ; មិនផ្តល់ឡើងវិញឡើយ |
| អ្នករួមចំណែក Top 10 | ចំណាត់ថ្នាក់ 1–10 ក្នុងតារាងចំណាត់ថ្នាក់ប្រចាំសប្តាហ៍ពេញលេញចុងក្រោយ | ចូលប្រើទិន្នន័យបច្ចុប្បន្នរយៈពេល 365 ថ្ងៃ | ទាមទារតាមតម្រូវការ; ការចាកចេញពីចំណាត់ថ្នាក់មិនកាត់បន្ថយរយៈពេលដែលបានផ្តល់ឡើយ |
| អ្នករួមចំណែក Top 100 | ចំណាត់ថ្នាក់ 11–100 ក្នុងតារាងចំណាត់ថ្នាក់នោះ | ចូលប្រើទិន្នន័យបច្ចុប្បន្នរយៈពេល 90 ថ្ងៃ | ច្បាប់ទាមទារតាមតម្រូវការ/អាចអនុវត្តម្តងហើយម្តងទៀតដោយទទួលលទ្ធផលដដែល |
| ការទិញរបស់អ្នកគាំទ្រ | ការទិញម្តងសម្រាប់រយៈពេល 6 ខែ 1 ឆ្នាំ ឬពេញមួយជីវិត | កាតាឡុកបច្ចុប្បន្ន ការផ្តល់ជូនបច្ចុប្បន្នដែលបានចុះហត្ថលេខា និង Intel | គ្មានការបន្តដោយស្វ័យប្រវត្តិ |
| ការបរិច្ចាគ/ការផ្តល់ដោយដៃ | ការបរិច្ចាគដែលម្ចាស់បានពិនិត្យ ឬការផ្តល់ដោយម្ចាស់សម្រាប់ចំនួនថ្ងៃជាក់លាក់/ពេញមួយជីវិត | សិទ្ធិប្រើប្រាស់បច្ចុប្បន្នដូចគ្នាសម្រាប់រយៈពេលដែលបានផ្តល់ | ការផ្តល់ដែលត្រូវបានធ្វើសវនកម្ម និងអាចអនុវត្តម្តងហើយម្តងទៀតដោយទទួលលទ្ធផលដដែល |
PR ដែលបានបញ្ចូលចូលគ្នា commit និងបន្ទាត់ដែលបានផ្លាស់ប្តូរ គឺជា ទិន្នន័យសម្រាប់ចំណាត់ថ្នាក់តែប៉ុណ្ណោះ។ ការចូលគណនីដែលស្ថិតនៅក្រៅ Top 100 មិនទទួលបានសិទ្ធិជាអ្នករួមចំណែកទេ ទោះបីមានចំនួន PR ប៉ុន្មានក៏ដោយ។ ការទិញមានកាលកំណត់ ការបរិច្ចាគ រយៈពេលសម្រាប់អ្នករួមចំណែក និង ការផ្តល់ដោយដៃ ត្រូវបានបូកបន្ថែមពីកាលបរិច្ឆេទផុតកំណត់បច្ចុប្បន្ន; សិទ្ធិពេញមួយជីវិតមានអាទិភាពខ្ពស់បំផុត។ ការផ្លាស់ប្តូរចំណាត់ថ្នាក់មិនដែល ដកហូត ឬកាត់បន្ថយរយៈពេលដែលបានផ្តល់រួចជាស្ថាពរទេ។
អាជ្ញាបណ្ណដែលបានបង្ហោះគឺសម្រាប់បុគ្គលម្នាក់ ហើយច្បាប់ដែលបង្ហាញដល់អ្នកប្រើគឺ អាចមានការដំឡើងដែលសកម្មបានតែមួយក្នុងពេលតែមួយ។ កំណែ នេះ មិន អះអាងថាមានការចាក់សោផ្នែករឹងទេ៖ ការធ្វើសមកាលកម្ម OSS មិនបង្កើតស្នាមសម្គាល់ផ្នែករឹង ឬរក្សា កិច្ចជួលឧបករណ៍តាមគ្រីបតូក្រាហ្វីឡើយ។ នៅឯកំណែ private-server ដែលបានផ្ទៀងផ្ទាត់ខាងលើ ការអនុវត្តការគ្រប់គ្រង រួមមានការផ្ទៀងផ្ទាត់សិទ្ធិប្រើប្រាស់ បូកនឹងសញ្ញាសម្រាប់ការពិនិត្យដោយដៃ នៅពេលឃើញសោបច្ចុប្បន្នដដែលពីអាសយដ្ឋាន IP ផ្សេងគ្នាទីបួន ក្នុងរយៈពេល 24 ម៉ោង។ សញ្ញានោះមិនដែលរារាំង ឬដកហូតសោដោយស្វ័យប្រវត្តិទេ។ ការស្ដារឡើងវិញ នឹងដកហូត និងជំនួសសោដែលបានបាត់ ខណៈរក្សាកាលបរិច្ឆេទផុតកំណត់ដែលមានស្រាប់; វាមិនចាប់ផ្តើមរយៈពេល ដែលបានទិញ ឬបានផ្តល់ឡើងវិញទេ។
ការផ្តល់ជូនបច្ចុប្បន្នត្រូវបានរៀបចំដោយដៃ ហើយអាចផ្លាស់ប្តូរ ឬផុតកំណត់។ អេក្រង់យល់ព្រមចូលរួមក៏បញ្ជាក់យ៉ាងច្បាស់អំពី ព្រំដែនឯកជនភាពផងដែរ៖ metadata របស់កាតាឡុក/ការណែនាំដែលបានចុះហត្ថលេខាត្រូវបានទាញយក; សោដែលមានសុពលភាពនឹងដោះសោបន្ថែម នូវការផ្តល់ជូនដែលបានចុះហត្ថលេខា និង Intel; សោ Bearer និង metadata នៃការតភ្ជាប់ធម្មតានឹងទៅដល់សេវាដែលបានបង្ហោះ; prompt ចម្លើយ ការសន្ទនា ព័ត៌មានសម្ងាត់របស់អ្នកផ្តល់សេវា ចរាចរណ៍ម៉ូដែល ពេលវេលាដំណើរការ latency និងការកំណត់រចនាសម្ព័ន្ធ អ្នកផ្តល់សេវាមូលដ្ឋាន មិនត្រូវបានបញ្ជូនទៅទេ។
ការទទួលបានកូនសោអ្នកគាំទ្រ
អេក្រង់ធ្វើឱ្យសកម្ម (/dashboard/radar) ភ្ជាប់ទៅកាន់លំហូរពីរសម្រាប់ ការទទួលបាន
កូនសោអ្នកគាំទ្រ។ OSS repo ខ្លួនវាមិនដែលចេញកូនសោ មិនដែលដំណើរការកូដទូទាត់ប្រាក់ និង
មិនដែលបញ្ជាក់តម្លៃ ទេ — ការកំណត់តម្លៃត្រូវបានសម្រេច និងបង្ហាញទាំងស្រុងនៅលើ
ទំព័រគោលដៅ មិនមែនក្នុង repo នេះទេ (សេចក្តីសម្រេចនៃលក្ខណៈបច្ចេកទេស D14)។
- "ខ្ញុំជាអ្នករួមចំណែក" — បើក
RADAR_CONTRIBUTOR_CLAIM_URL(លំនាំដើមhttps://radar.omniroute.online/auth/github) ដែលជាលំហូរទាមទារតាម GitHub OAuth បង្ហោះនៅលើ ម៉ាស៊ីនមេ Radar ឯកជន។ វាពិនិត្យចំណាត់ថ្នាក់ប្រចាំសប្តាហ៍ដែលបានបញ្ចប់ចុងក្រោយ៖ ចំណាត់ថ្នាក់កំពូល 10 ទទួលបាន 365 ថ្ងៃ ហើយចំណាត់ថ្នាក់ 11–100 ទទួលបាន 90 ថ្ងៃ។ នៅក្រៅកំពូល 100 ចំនួន PR មិនផ្តល់សិទ្ធិចូលប្រើឡើយ; ផ្ទុយទៅវិញ លំហូរនេះ ពិនិត្យកម្រិតប្រើបានតែម្តងដាច់ដោយឡែកដែលតម្រូវឱ្យដាក់ផ្កាយ + តាមដាន។ - "គាំទ្រគម្រោង" — បើក
RADAR_SUPPORTER_PLANS_URL(លំនាំដើមhttps://radar.omniroute.online/planos) ដែលជាទំព័របង្ហោះសម្រាប់ជម្រើសបង់ប្រាក់តែម្តងរយៈពេល 6 ខែ, 1 ឆ្នាំ និង មួយជីវិត។ ទំព័រ OSS នៅតែមិនបង្ហាញតម្លៃជាប្រាក់ណាមួយ។
URL ទាំងពីរត្រូវបានដោះស្រាយនៅផ្នែកម៉ាស៊ីនមេ (src/lib/radar/links.ts ដោយប្រើលំនាំ
ជំនួសតម្លៃតាម env ដូចគ្នានឹង RADAR_FEED_URL) ហើយបញ្ជូនបន្តទៅ dashboard តាមរយៈ
ការឆ្លើយតប GET /api/radar/settings ដែលមានស្រាប់ (contributorClaimUrl, supporterPlansUrl) —
សមាសភាគ client មិនដែលអាន process.env ដោយខ្លួនឯងទេ។
| អថេរ | គោលបំណង |
|---|---|
RADAR_CONTRIBUTOR_CLAIM_URL |
ជំនួស URL សម្រាប់ទាមទារជាអ្នករួមចំណែក (លំនាំដើម https://radar.omniroute.online/auth/github)។ |
RADAR_SUPPORTER_PLANS_URL |
ជំនួស URL សម្រាប់គម្រោងអ្នកគាំទ្រ (លំនាំដើម https://radar.omniroute.online/planos)។ |
ការសង្គ្រោះកូនសោអ្នកគាំទ្រដែលបានបាត់
ចំណុចចូលសង្គ្រោះរបស់សេវាដែលបានបង្ហោះគឺ https://radar.omniroute.online/recover; វាក៏ត្រូវបាន
ភ្ជាប់ពីទំព័រគម្រោងផងដែរ។ ការសង្គ្រោះនៅតែស្ថិតនៅក្រៅ client OSS ទាំងស្រុង ពីព្រោះការដំឡើងក្នុងមូលដ្ឋាន
មិនដែលទទួលអ៊ីមែលរបស់អ្នកទិញ/អ្នករួមចំណែក ហើយមិនអាចបង្កើតកូនសោដើមឡើងវិញពី
ការកំណត់ដែលបានអ៊ិនគ្រីបរបស់វាទេ។
- ដាក់ស្នើអ៊ីមែលដែលភ្ជាប់ជាមួយកូនសោ។ សេវានេះត្រឡប់ទំព័រទទួលយកដូចគ្នា មិនថាមាន អាជ្ញាបណ្ណដែលអាចសង្គ្រោះបានឬអត់ ដូច្នេះសំណុំបែបបទមិនបង្ហាញរាយគណនីទេ។
- ប្រសិនបើមានសិទ្ធិ worker ផ្ញើនឹងផ្ញើតំណប្រើបានតែម្តងដែលមានអាយុកាលខ្លី។ ការបើកវានឹងផ្លាស់ទី
token ភ្លាមៗទៅ cookie
HttpOnly/Secureដែលបានអ៊ិនគ្រីបបណ្តោះអាសន្ន ហើយប្តូរទិសទៅ URL/recoverស្អាត; ទំព័រនោះមិនមាន token, អ៊ីមែល, កូនសោចាស់ ឬកូនសោជំនួសឡើយ។ - បញ្ជាក់ការដកហូត។ សេវាឯកជនដកហូតកូនសោមុន បង្កើតកូនសោជំនួសដែលមាន គម្រោង/កាលផុតកំណត់ដូចគ្នា ហើយដាក់វាចូលជួររង់ចាំសម្រាប់ផ្ញើតាមអ៊ីមែលក្នុងប្រតិបត្តិការតែមួយ។ កូនសោជំនួសមិនដែល ត្រូវបានត្រឡប់ទៅ browser ទេ។
- បិទភ្ជាប់កូនសោជំនួសទៅក្នុង
/dashboard/radar។ ឥឡូវនេះកូនសោចាស់ត្រូវតែធ្លាក់ចុះទៅជាcommunity; កូនសោជំនួសត្រូវតែបង្កើតការធ្វើសមកាលកម្មliveដែលបានផ្ទៀងផ្ទាត់។ ការបើកតំណសង្គ្រោះដដែលម្តងទៀតត្រូវតែបរាជ័យជាមួយ ការឆ្លើយតបទូទៅថាមិនត្រឹមត្រូវ/ផុតកំណត់។
route សង្គ្រោះដែលបានបង្ហោះ និង mail worker អាចមាននៅក្នុងកូដ ប៉ុន្តែនៅតែមិនអាចប្រើបានក្នុង ការដាក់ឱ្យដំណើរការជាក់លាក់ណាមួយ។ កុំចាត់ទុកលំហូរនេះថារួចរាល់សម្រាប់ production រហូតដល់ម៉ាស៊ីនមេត្រូវបានដាក់ឱ្យដំណើរការ អ្នកផ្តល់សេវាផ្ញើ ត្រូវបានកំណត់រចនាសម្ព័ន្ធជាមួយអ្នកទទួលដែលបានគ្រប់គ្រង ហើយតំណប្រើបានតែម្តងពេញលេញត្រូវបានសាកល្បង។
នៅពេលអ្នកចូលមើលមានកូនសោ (omr_ + តួអក្សរ hex 40 តួ) អេក្រង់ធ្វើឱ្យសកម្ម
(src/app/(dashboard)/dashboard/radar/page.tsx) មានប្រអប់បញ្ចូលសម្រាប់បិទភ្ជាប់កូនសោជាផ្លូវចម្បង៖
ការបិទភ្ជាប់កូនសោ និងដាក់ស្នើនឹងផ្ញើ POST /api/radar/settings
({ optIn: true, supporterKey }) ក្នុងការហៅតែមួយ — ការបិទភ្ជាប់កូនសោទាំងកំណត់វា និងជ្រើសយល់ព្រមចូលរួម
ដែលដោះសោអេក្រង់។ ទម្រង់ (omr_ + តួអក្សរ hex 40 តួ) ត្រូវបានពិនិត្យជាមុននៅផ្នែក client
ដោយប្រើ helper isValidSupporterKeyFormat() រួម (src/lib/radar/supporterKey.ts)
ដើម្បីជួយសម្រួល UX; ទោះយ៉ាងណាក៏ដោយ schema Zod របស់ម៉ាស៊ីនមេជាការពិនិត្យដែលមានអំណាចសម្រេចចុងក្រោយ។ នៅពេល
កូនសោត្រូវបានកំណត់ អេក្រង់ធ្វើឱ្យសកម្មបង្ហាញទម្រង់ដែលបានបិទបាំង (supporterKeyMasked ពី
GET /api/radar/settings) ជំនួសឱ្យប្រអប់បញ្ចូលទទេ ដោយមានប៊ូតុង "ប្តូរកូនសោ" សម្រាប់
បិទភ្ជាប់កូនសោថ្មី — កូនសោដើមមិនត្រូវបានបង្ហាញឡើងវិញឡើយ។ ប៊ូតុងទាមទារ/គម្រោងទាំងពីរខាងលើ
នៅតែជាវិធីសម្រាប់ ទទួលបាន កូនសោជាលើកដំបូង; ប្រអប់បញ្ចូលនេះជាកន្លែងដែលប្រតិបត្តិករ
ដែលមានកូនសោរួចហើយធ្វើឱ្យវាសកម្ម។
ការធ្វើឱ្យសកម្មពីដើមដល់ចប់ និងការដំឡើងតាមការណែនាំ
សេវា feed ឯកជន និង client OSS នេះមានព្រំដែនតូចចង្អៀតដោយចេតនា៖ សេវា ចេញ និងផ្ទៀងផ្ទាត់កូនសោអ្នកគាំទ្រ ខណៈការដំឡើង OmniRoute ក្នុងមូលដ្ឋានអ៊ិនគ្រីបកូនសោ ធ្វើសមកាលកម្ម artifact ដែលបានចុះហត្ថលេខានៅផ្នែកម៉ាស៊ីនមេ និងណែនាំការដំឡើង provider។ លំដាប់ផ្ទៀងផ្ទាត់ដែលមានជំនួយគឺ៖
- ទទួលយកកូនសោដែលទើបចេញថ្មី ឬបានស្ដារឡើងវិញពីដំណើរការទាមទារសិទ្ធិរបស់អ្នកចូលរួម, plans/checkout, ដំណើរការស្ដារ ឬប្រតិបត្តិករម៉ាស៊ីនមេឯកជនដែលមានការអនុញ្ញាត។ កុំបិទភ្ជាប់កូនសោដើមទៅក្នុងកំណត់ហេតុ, រូបថតអេក្រង់, មតិយោបល់លើបញ្ហា ឬអាគុយម៉ង់បន្ទាត់ពាក្យបញ្ជា។
- បើកទង់មុខងារ
RADAR_ENABLEDលើការដំឡើង OmniRoute ក្នុងមូលដ្ឋាន។ វានឹងបង្ហាញ UI ប៉ុន្តែនៅតែមិនធ្វើសកម្មភាពបណ្ដាញ រហូតដល់ការយល់ព្រមដាច់ដោយឡែកត្រូវបានរក្សាទុក។ - បើក
/dashboard/radar, បិទភ្ជាប់កូនសោ ហើយធ្វើឱ្យសកម្ម។ កម្មវិធីរុករកផ្ញើសំណើក្នុងមូលដ្ឋានមួយPOST /api/radar/settingsជាមួយ{ optIn: true, supporterKey }; កូនសោត្រូវបានអ៊ិនគ្រីបក្នុងមូលដ្ឋាន ហើយ ការឆ្លើយតបមានតែomr_****<last4>ប៉ុណ្ណោះ។ - អនុញ្ញាតឱ្យអេក្រង់ធ្វើឱ្យសកម្មដំណើរការសមកាលកម្មកាតាឡុករបស់វា ឬជ្រើសរើស ធ្វើសមកាលកម្មឥឡូវនេះ។ បញ្ជាក់ថាទំព័រ
រាយការណ៍
live, កំណែមតិព័ត៌មាន និងពេលវេលាទាញយក។ សម្រាប់ការវិនិច្ឆ័យក្នុងមូលដ្ឋានដែលបានផ្ទៀងផ្ទាត់អត្តសញ្ញាណ,GET /api/radar/statusរាយការណ៍អំពីការយល់ព្រម/វត្តមានកូនសោ និងស្ថានភាពឃ្លាំងសម្ងាត់ទាំងបួន ដោយមិនបញ្ជូនត្រឡប់ កូនសោឡើយ។POST /api/radar/sync-allអាចធ្វើឱ្យកាតាឡុក, ការណែនាំបន្ត, ការផ្តល់ជូន និង Intel ស្រស់ឡើងវិញយ៉ាងជាក់លាក់។ - បើក
/dashboard/radar/setup?provider=<provider>។ ចូលទៅកាន់ URL ព័ត៌មានសម្ងាត់ដែលគ្រប់គ្រងដោយអ្នកផ្តល់សេវា, ជ្រើសរើស បន្ថែមកូនសោ API, រក្សាទុកតាមរយៈទម្រង់ពិតប្រាកដរបស់អ្នកផ្តល់សេវា, ត្រឡប់ទៅការណែនាំ ហើយដំណើរការ សាកល្បងការតភ្ជាប់។ ការណែនាំប្រើផ្លូវធម្មតា/api/providersនិង/api/providers/<connection-id>/test; វាមិនបង្កើតព័ត៌មានសម្ងាត់ Radar ដាច់ដោយឡែកទេ។ - បើក
/dashboard/radar/combosបន្ទាប់ពីការតភ្ជាប់អ្នកផ្តល់សេវាដែលត្រូវគ្នាយ៉ាងហោចណាស់ពីរបានដំណើរការ។ ពិនិត្យមើលក្រុមដែលបានណែនាំ ហើយបង្កើត combo តាមរយៈ combo API ដែលមានស្រាប់។ ការផ្តល់ជូន និង Intel នៅតែជាឃ្លាំងសម្ងាត់ដែលបានចុះហត្ថលេខា និងប្រើសម្រាប់តែliveដាច់ដោយឡែក ហើយអាចត្រូវបានពិនិត្យនៅលើទំព័រ Radar ផ្ទាល់ខ្លួនរបស់ពួកវា។ - ផ្ទុក
/dashboard/radarនិងទំព័ររៀបចំឡើងវិញ។ ការយល់ព្រម, ស្ថានភាពកូនសោដែលបានបិទបាំង, ឃ្លាំងសម្ងាត់ដែលបានផ្ទៀងផ្ទាត់, ការតភ្ជាប់ អ្នកផ្តល់សេវាដែលបានរក្សាទុក និងសកម្មភាពសាកល្បង ត្រូវតែបន្តមានបន្ទាប់ពីការផ្ទុកឡើងវិញ។ ចាប់យកភស្តុតាងតែបន្ទាប់ពី កូនសោដើម និងព័ត៌មានសម្ងាត់របស់អ្នកផ្តល់សេវាលែងអាចមើលឃើញ។
ការរក្សាទុកកូនសោមួយ មិនមែនជាភស្តុតាងនៃសិទ្ធិប្រើប្រាស់ live ដោយខ្លួនវាទេ។ ភស្តុតាងគឺជាការរួមបញ្ចូលគ្នានៃលទ្ធផល
GET /v1/license/check របស់សេវាឯកជន, ថ្នាក់ live ដែលកាតាឡុក OSS ផ្តល់ជូន, ឃ្លាំងសម្ងាត់ដែលបានចុះហត្ថលេខា
និងផ្ទៀងផ្ទាត់ និងលំហូរការតភ្ជាប់/សាកល្បងអ្នកផ្តល់សេវាពិតប្រាកដ។ កូនសោដែលមិនត្រឹមត្រូវ, ផុតកំណត់ ឬត្រូវបានដកហូត នឹងបន្ថយ
កាតាឡុកទៅជា community ដោយសុវត្ថិភាព; វាមិនត្រូវបានរាយការណ៍ថាជាការផ្ទៀងផ្ទាត់កូនសោ live ដោយជោគជ័យទេ។
តំណផ្ទាំងគ្រប់គ្រងឯកជន
RADAR_ADMIN_URL អាចបន្ថែម Radar Admin ↗ ភ្លាមៗបន្ទាប់ពីធាតុ Radar សម្រាប់អ្នកប្រើប្រាស់
ក្នុងផ្នែក Costs នៃរបារចំហៀង។ វាមិនមានតម្លៃលំនាំដើមដោយចេតនា៖ នៅពេលអថេរ
មិនត្រូវបានកំណត់ ឬមិនត្រឹមត្រូវ របារចំហៀងឋិតិវន្ត, ផ្ទាំងពាក្យបញ្ជា និងអេក្រង់កំណត់របារចំហៀងតាមបំណង នឹងមិនមាន
ធាតុអ្នកគ្រប់គ្រង និង URL ឯកជនឡើយ។
តម្លៃនេះត្រូវបានដោះស្រាយនៅផ្នែកម៉ាស៊ីនមេ និងបញ្ជូនបន្តតាមរយៈការឆ្លើយតប
GET /api/settings ដែលបានផ្ទៀងផ្ទាត់តាមការគ្រប់គ្រង ទៅតែសម័យ dashboard ដែលបានផ្ទៀងផ្ទាត់អត្តសញ្ញាណ ឬទៅម្ចាស់
loopback ដែលទុកចិត្តបាន ក្នុងអំឡុងពេលចាប់ផ្ដើមក្នុងមូលដ្ឋានដោយមិនចាំបាច់ចូលប្រើ។ ការផ្ទៀងផ្ទាត់តាម CLI, សេវាផ្ទៃក្នុង និងកូនសោ API
ដែលមាន manage-scope មិនទទួលបានតម្លៃនេះទេ។ កម្មវិធីរុករកផ្ទៀងផ្ទាត់ការឆ្លើយតបម្ដងទៀត មុនពេលបង្កើត
តំណខាងក្រៅ ដែលបើកជាមួយ noopener noreferrer។
ប្រើ URL ផ្លូវរូង HTTPS/tailnet ដែលគ្មានព័ត៌មានសម្ងាត់។ HTTP ធម្មតាត្រូវបានទទួលយកសម្រាប់តែការបញ្ជូនបន្ត SSH
តាម loopback ដូចជា http://127.0.0.1:9351; គ្រោងការណ៍ផ្សេងទៀត, ព័ត៌មានសម្ងាត់ដែលបានបង្កប់, URL ខូចទ្រង់ទ្រាយ និង
គោលដៅ HTTP ពីចម្ងាយ នឹងបិទបរាជ័យដោយសុវត្ថិភាព ហើយទុកឱ្យការរុករកមិនដំណើរការ។
គំរូសុវត្ថិភាព
ហត្ថលេខា Ed25519 លើបៃពិតប្រាកដ
ទិន្នន័យផ្ទុករបស់ feed ត្រូវបានចុះហត្ថលេខាដោយ Ed25519។ verifyFeedBytes()
(src/lib/radar/verify.ts) ផ្ទៀងផ្ទាត់ហត្ថលេខាលើ បៃឆ្លើយតបពិតប្រាកដ
ដែលបានទទួលតាមបណ្ដាញ — ទិន្នន័យផ្ទុកមិនត្រូវបានធ្វើសៀរៀលឡើងវិញមុនពេលផ្ទៀងផ្ទាត់ឡើយ ដូច្នេះ
ការអ៊ិនកូដឡើងវិញតាមបៃដូចគ្នាទាំងស្រុង មិនអាចធ្វើឱ្យការត្រួតពិនិត្យហត្ថលេខាអសុពលភាព ឬរំលងវាដោយស្ងាត់ៗបានទេ។
ការផ្ទៀងផ្ទាត់បរាជ័យ (invalid_signature) នឹងបញ្ឈប់ការធ្វើសមកាលកម្ម មុនពេលទិន្នន័យផ្ទុកត្រូវបាន
ញែក ឬរក្សាទុកក្នុងឃ្លាំងសម្ងាត់។
កូនសោសាធារណៈដែលបានខ្ទាស់ + ការប្ដូរកូនសោ
កូនសោសាធារណៈសម្រាប់ផ្ទៀងផ្ទាត់ត្រូវបានខ្ទាស់នៅក្នុង src/lib/radar/pinnedKeys.ts
(PINNED_FEED_PUBLIC_KEYS) ជាអារេ ដើម្បីឱ្យកូនសោថ្មីអាចត្រូវបានបន្ថែមនៅខាងមុខ មុនពេល
ប្ដូរកូនសោ ខណៈដែល feed ចាស់ៗក្នុងឃ្លាំងសម្ងាត់ ដែលបានចុះហត្ថលេខាដោយកូនសោមុន នៅតែមានសុពលភាពរហូតដល់
ត្រូវបានធ្វើសមកាលកម្មឡើងវិញ។
ការកំណត់ជំនួសតាម env ដែលសមស្របសម្រាប់ fork
អថេរ env ចំនួនពីរអនុញ្ញាតឱ្យ fork និងអ្នកបង្ហោះដោយខ្លួនឯង បញ្ជូន client ទៅកាន់ feed ផ្ទាល់ខ្លួន ជំនួសឱ្យ សេវា OmniRoute លំនាំដើម — សូមមើល របៀបបង្ហោះ feed ដោយខ្លួនឯង ខាងក្រោម៖
| អថេរ | គោលបំណង |
|---|---|
RADAR_FEED_URL |
កំណត់ជំនួស URL មូលដ្ឋានរបស់ feed (លំនាំដើម https://radar.omniroute.online)។ |
RADAR_FEED_PUBKEY |
កំណត់ជំនួសកូនសោសាធារណៈដែលបានខ្ទាស់ (base64-DER SPKI ឬ PEM) ដោយជំនួសអារេដែលភ្ជាប់មកស្រាប់ដោយកូនសោតែមួយនេះ។ |
កម្រិតអប្បបរមានៃកំណែ
syncRadar() បដិសេធ feed ដែលបានទាញយក ប្រសិនបើ version របស់វាមិនថ្មីជាងយ៉ាងដាច់ខាត បើធៀបនឹង
កំណែដែលបច្ចុប្បន្នស្ថិតក្នុងឃ្លាំងសម្ងាត់ (compareVersions(), ការប្រៀបធៀប YYYY.MM.DD.n ដែលបំបែកដោយសញ្ញាចុច) —
{ status: "stale" }។ វារារាំង endpoint របស់ feed ដែលត្រូវបានគ្រប់គ្រងដោយអ្នកវាយប្រហារ ឬកំណត់រចនាសម្ព័ន្ធមិនត្រឹមត្រូវ មិនឱ្យ
បន្ទាប client ត្រឡប់ទៅទិន្នន័យផ្ទុកចាស់ជាង ដែលបានចុះហត្ថលេខាខុសគ្នា។
កាលបរិច្ឆេទពីរ និងមូលហេតុដែលរក្សាទុកទាំងពីរ
feed ក្នុងឃ្លាំងសម្ងាត់មានកាលបរិច្ឆេទពីរផ្សេងគ្នា ហើយការភាន់ច្រឡំរវាងវាទាំងពីរគឺជាមូលហេតុសំខាន់នៃ ការរក្សាទុកទាំងពីរ៖
| វាល | ប្រភព | បញ្ជាក់អំពី |
|---|---|---|
generatedAt |
ខ្លឹមសារ feed ដែលបានចុះហត្ថលេខា | ទិន្នន័យ មានអាយុកាលប៉ុនណា |
fetchedAt |
នាឡិការបស់ការដំឡើងនេះ | ពេលដែលការដំឡើងនេះបាន ទាញយក វា |
feed ដែលទើបត្រូវបានទាញយកកាលពីប៉ុន្មាននាទីមុន អាចមានតួលេខចាស់រាប់សប្ដាហ៍ ដូច្នេះ fetchedAt តែឯងមិនអាច
ប្រាប់ប្រតិបត្តិករថាតើ overlay ថ្មីជាង baseline ដែលវាដាក់ពីលើឬអត់ទេ។ ទាំងពីរត្រូវបាន
រក្សាទុកអចិន្ត្រៃយ៍ក្នុង radar_feed_cache ត្រឡប់ដោយ getRadarCatalog().meta និងរាយការណ៍
ដោយឡែកពីគ្នាតាម GET /api/radar/status។ ជួរដេកដែលបានរក្សាទុកក្នុងឃ្លាំងសម្ងាត់ មុនពេលមានជួរឈរ generated_at
(migration 163) នឹងត្រូវបានអានត្រឡប់ជា null — អ្វីដែលមិនដឹង នៅតែមិនដឹង ជំនួសឱ្យ
ខ្ចីពេលវេលាទាញយកមកប្រើ។ radar_referrals_cache បានរក្សាទុក generated_at ផ្ទាល់ខ្លួនរបស់វា ចាប់តាំងពី
migration 142។
កម្រិតអប្បបរមានៃកំណែខាងលើប្រៀបធៀប version មិនមែនកាលបរិច្ឆេទណាមួយទេ។
នៅសល់ចន្លោះខ្វះខាតពីរ ដែលទាំងពីរគឺជាចេតនា៖ dashboard នៅតែបង្ហាញតែ Last fetched ដូច្នេះការអាន
កាលបរិច្ឆេទ build នៅទីនោះ ត្រូវការស្លាកថ្មីមួយ (និងធាតុ locale ចំនួន 41 របស់វា)។ ចំណែកឃ្លាំងសម្ងាត់ offers និង intel
មិនរក្សាទុកកាលបរិច្ឆេទ build ទាល់តែសោះ ទោះបី schema របស់ feed ពួកវាមានវាក៏ដោយ — ដូច្នេះ GET /api/radar/status មិនបញ្ចូលវាលនេះសម្រាប់ទាំងពីរនោះ ជំនួសឱ្យការរាយការណ៍ null
ដែលអាចត្រូវបានយល់ថា "មិនដឹង"។
ការផ្ទៀងផ្ទាត់ schema
បៃដែលបានទាញយកត្រូវបានញែក និងផ្ទៀងផ្ទាត់ជាមួយ RadarFeedSchema
(src/lib/radar/feedSchema.ts, ជា schema របស់ Zod) បន្ទាប់ពី ការផ្ទៀងផ្ទាត់ហត្ថលេខា។ ករណី
schema មិនត្រូវគ្នា នឹងត្រឡប់ { status: "invalid_schema" } ហើយឃ្លាំងសម្ងាត់នៅតែ
មិនត្រូវបានប៉ះពាល់។ ទិន្នន័យផ្ទុកក្នុងឃ្លាំងសម្ងាត់ត្រូវបានផ្ទៀងផ្ទាត់ឡើងវិញជាវិធានការការពារ រាល់ពេលអាន
(getRadarCatalog()) — ជួរដេកក្នុងឃ្លាំងសម្ងាត់ដែលខូច ឬត្រូវបានកែដោយដៃ នឹងត្រឡប់ទៅប្រើ
baseline ជំនួសឱ្យការបញ្ជូនវាទៅប្រើ។
កម្រិតទំហំឆ្លើយតប (10 MB)
syncRadar() អនុវត្ត កម្រិតរឹង 10 MB លើខ្លឹមសារឆ្លើយតបរបស់ feed — feed ដែលបានចុះហត្ថលេខា
គឺជាឯកសារ JSON ទំហំត្រឹមកម្រិត KB ដូច្នេះទំហំលើសពីនេះបង្ហាញថា RADAR_FEED_URL ត្រូវបានកំណត់រចនាសម្ព័ន្ធខុស ឬ
មានចេតនាអាក្រក់ (ឬប្រភពខាងលើកំពុងផ្ដល់ទិន្នន័យមិនត្រឹមត្រូវ) មិនមែនជា catalog ស្របច្បាប់ទេ។
ការអនុវត្តកម្រិតនេះមានពីរស្រទាប់៖
- ការត្រួតពិនិត្យបឋមលើ
Content-Lengthរំលងការអានខ្លឹមសារទាំងស្រុង នៅពេល header ប្រកាសតម្លៃលើសកម្រិតរួចហើយ។ - ការត្រួតពិនិត្យផលបូកកំពុងដំណើរការ ខណៈអានខ្លឹមសារ នឹងអនុវត្តកម្រិត ទោះបីជា
Content-Lengthអវត្តមាន ឬបញ្ជាក់ទំហំតិចជាងទំហំពិតក៏ដោយ — header មិនដែលត្រូវបាន ទុកចិត្តដោយឯកឯងឡើយ។ ការតភ្ជាប់ chunk ដែលបានប្រមូលផ្ដុំ រក្សាទុកបៃពិតប្រាកដដែលត្រូវការ សម្រាប់ការត្រួតពិនិត្យហត្ថលេខា Ed25519 នៅពេលក្រោយ។
ការលើសកម្រិតនឹងត្រឡប់ { status: "too_large" } ហើយទុកឃ្លាំងសម្ងាត់ឱ្យនៅដដែល
ដោយអនុវត្តតាមលំនាំមិនបំផ្លាញដូចគ្នានឹងរាល់ការបរាជ័យនៃការធ្វើសមកាលកម្មផ្សេងទៀត
(invalid_signature, invalid_schema, stale)។
កម្រិត៖ community និង live
ស្គីមារបស់ feed មានវាល tier: "community" | "live" ដែលត្រូវបានកំណត់ នៅផ្នែកម៉ាស៊ីនបម្រើ
ដោយសេវា feed ផ្អែកលើសំណើ (វត្តមាន និងសុពលភាពនៃ supporter key)
— client មិនដែលកំណត់កម្រិតរបស់ខ្លួនឯងទេ។
community— កាតាឡុកឥតគិតថ្លៃដែលយឺតជាងទិន្នន័យថ្មីបំផុតប្រហែល 30 ថ្ងៃ។ នេះជាអ្វីដែលសំណើគ្មានការផ្ទៀងផ្ទាត់អត្តសញ្ញាណ ឬប្រើ key មិនត្រឹមត្រូវ នឹងទទួលបាន។live— កាតាឡុកថ្មីបំផុត ដែលផ្តល់ជូនសំណើដែលមាន supporter key ត្រឹមត្រូវ។
supporter key ដែលមិនត្រឹមត្រូវ ឬផុតកំណត់ នឹងត្រូវបន្ថយទៅជា community — វាមិនដែលជា
កំហុសទេ។ ផ្លូវ sync គ្រាន់តែបែងចែករវាងការបរាជ័យផ្នែកហត្ថលេខា/ស្គីមា/កំណែ (ទាំងអស់
អាចស្ដារឡើងវិញបាន និងមិនធ្វើឱ្យស្ថានភាព cache មានបញ្ហាធ្ងន់ធ្ងរ) និងលទ្ធផលជោគជ័យ { status: "updated", version, tier }។ មិនមានផ្លូវកំហុសជាក់លាក់តាមកម្រិតណាមួយដែល client ត្រូវ
ដោះស្រាយឡើយ។
កម្រិតដែលត្រូវបានផ្តល់ជូនមកពី response header មិនមែនពី signed body ទេ
វាល tier របស់ body នៃ signed feed តែងតែជា "live" — សេវា feed បញ្ជូន
artifact ដែលបានចុះហត្ថលេខាចំនួនពីរក្នុងមួយកំណែ៖ live រួមបញ្ចូល campaign បច្ចុប្បន្ន ខណៈដែល community
លុបវាចេញ។ artifact នីមួយៗត្រូវបានចុះហត្ថលេខាលើ bytes ពិតប្រាកដរបស់វាផ្ទាល់។ body នៅតែមិន
ត្រូវបានប្រើជាការសម្រេចសិទ្ធិទទួលបានទេ; កម្រិតដែលត្រូវបានជ្រើសរើសពិតប្រាកដសម្រាប់សំណើមួយ ត្រូវបានបញ្ជូន
ក្នុង x-omniroute-feed-tier response header ដែលកំណត់នៅផ្នែកម៉ាស៊ីនបម្រើពី Authorization key
របស់សំណើ។
syncRadar() (src/lib/radar/sync.ts::parseServedTierHeader()) គឺជាកន្លែងតែមួយគត់
ដែលកំណត់កម្រិតដែល client គួរជឿទុកចិត្ត៖
- ញែក
x-omniroute-feed-tierដោយប្រើRadarTierSchema(Zod) — header ដែលអវត្តមាន ឬ តម្លៃដែលមិនមែនជា"community"ឬ"live"ដូចគ្នាបេះបិទ ត្រូវបានចាត់ទុកថា មិន មានវត្តមាន (មិនត្រូវបានជឿទុកចិត្ត ហើយរក្សាទុកក្នុង cache/UI តាមតម្លៃដើមរបស់វាឡើយ; វាក៏គ្របដណ្ដប់លើ feed server ចាស់ៗដែលមានមុន header នេះផងដែរ)។ - ប្រើវាល
tierរបស់ signed body (តែងតែជា"live") ជាតម្លៃបម្រុង តែនៅពេលជំហានទី 1 មិនផ្តល់លទ្ធផលអ្វីទេ។ - កម្រិតដែលបានកំណត់ គឺជាតម្លៃដែលត្រូវបានរក្សាទុកក្នុង cache និងត្រឡប់ជា
{ status: "updated", version, tier }— នេះជាតម្លៃដែល dashboard បង្ហាញ មិនមែនវាល body ដើម ទេ។
ច្បាប់ merge overlay នៅពេលអាន
applyFeed() (src/lib/radar/applyFeed.ts) merge feed ដែលបានរក្សាទុកក្នុង cache ពីលើ
baseline ឋិតិវន្តនៅ ពេលអាន នៅខាងក្នុង getRadarCatalog()។ អារេ baseline
(FREE_MODEL_BUDGETS) មិនដែលត្រូវបានកែប្រែទេ — MergedEntry[] ថ្មីមួយត្រូវបានគណនារាល់ពេល
ហៅ។
ច្បាប់ទាំងបួន តាមលំដាប់អាទិភាព៖
- Feed មិនដែលសរសេរជាន់លើ local override ទេ។ តាមវាលនីមួយៗ៖ ប្រសិនបើ operator បាន
កែតម្រូវវាលមួយលើ entry មួយ (
localOverridesmap ដែលកំណត់ key ដោយprovider:modelId) នោះ តម្លៃរបស់ feed សម្រាប់វាលជាក់លាក់នោះនឹងត្រូវរំលង — តម្លៃរបស់ operator មានអាទិភាព។ enabled: falseបិទ entry ដោយមានប្រភពកំណើត។ feed entry ដែលបិទ entry មួយ នឹងកំណត់enabled: falseនិងdisabledBy: "radar"លើលទ្ធផលដែលបាន merge ដើម្បីឱ្យ UI អាចពន្យល់ថា ហេតុអ្វី entry មួយបានប្តូរពីអាចប្រើបានទៅជាត្រូវបានបិទ។- entry ដែលអ្នកប្រើបានបន្ថែម ហើយមិនមានក្នុង feed នឹងនៅដដែលដោយគ្មានការប៉ះពាល់។ entry ដែល មានតែនៅក្នុង baseline (ឬត្រូវបានបន្ថែមក្នុងមូលដ្ឋាន) និងមិនមាន feed entry ដែលត្រូវគ្នា នឹងឆ្លងកាត់ដោយមិនផ្លាស់ប្តូរ។
- entry ដែលមាន tombstone មិនដែលត្រូវបានបង្កើតឡើងវិញទេ។ ប្រសិនបើ operator បានលុប
entry មួយយ៉ាងច្បាស់ (
tombstonesset) ការដែល feed បន្ថែមprovider:modelIdនោះឡើងវិញក្នុងកំណែ ក្រោយ មិនអាចនាំវាត្រឡប់មកវិញបានទេ។
វាលដែលអាចកែសម្រួលបាន និង tombstone ត្រូវបានរក្សាទុកក្នុង
radar_local_model_state (migration 153_radar_local_model_state.sql)។ DB
adapter សាធារណៈ (src/lib/db/radar.ts) បម្លែង row ទាំងនោះទៅជា localOverrides map និង
tombstones set ដែលប្រើដោយ applyFeed(); getRadarCatalog() ក្នុង production ផ្ទុកស្ថានភាពនោះ
បន្ទាប់ពីការត្រួតពិនិត្យ flag, cache និងស្គីមាបានឆ្លងកាត់។ មានតែ displayName និង enabled ប៉ុណ្ណោះដែល
operator អាចកែសម្រួលបាន។ អត្តសញ្ញាណ provider/model, ប្រភពកំណើតរបស់ feed, quota, សមត្ថភាព, ToS
និងទិន្នន័យរៀបចំ មិនអាចត្រូវបានសរសេរតាមរយៈផ្ទៃនេះទេ។
Dashboard ផ្តល់សកម្មភាព local ចំនួនបួន៖
- កែសម្រួល ផ្លាស់ប្តូរឈ្មោះបង្ហាញ និងស្ថានភាពបើកប្រើក្នុងមូលដ្ឋាន។
- កំណត់ការផ្លាស់ប្តូរក្នុងមូលដ្ឋានឡើងវិញ សម្អាតវាលដែលអាចកែសម្រួលបានទាំងពីរ ដោយមិនផ្លាស់ប្តូរ tombstone។
- លាក់ បង្កើត tombstone ដូច្នេះការអាប់ដេត feed នាពេលក្រោយមិនអាចបង្កើត row ឡើងវិញបានទេ។
- ស្ដារឡើងវិញ លុប tombstone ចេញ; override ដែលបានរក្សាទុកដោយឡែកណាមួយនៅតែមានប្រសិទ្ធភាព។
enabled: false របស់ feed នៅតែជាករណីលើកលែងផ្នែកសុវត្ថិភាព៖ វាមានអាទិភាពលើ
enabled: true ក្នុងមូលដ្ឋានដែលហួសសម័យ ធ្វើឱ្យ entry ដែលបាន merge នៅតែបិទ និងកត់ត្រា
disabledBy: "radar"។
ការបោះពុម្ពផ្សាយកាតាឡុកប្រើ schemaVersion: 2។ contextWindow និងវាលនីមួយៗនៃ tools, vision និង
thinking ជា number | null / boolean | null ដោយឯករាជ្យ៖ null មានន័យថាមិនដឹង ខណៈដែល
false មានន័យថា ប្រភព provider ផ្លូវការដែលបានបញ្ជាក់ដោយ D16 និយាយយ៉ាងច្បាស់ថាសមត្ថភាពនោះមិនមាន។
flag នៃ registry/model-spec ខាងក្នុងរបស់ OmniRoute មិនដែលត្រូវបានលើកជាការពិតរបស់ feed ដោយផ្ទាល់ទេ។ Client
នៅតែទទួលយក snapshot v1; ដោយសារ builder ចាស់ប្រើ false ជា placeholder សម្រាប់អវត្តមាន false របស់ v1
ត្រូវបាន normalize ជាមិនដឹង ខណៈដែល true របស់ v1 នៅតែជាការពិត។ កំណែស្គីមាដែលមិនស្គាល់ នឹងបរាជ័យបែបបិទសុវត្ថិភាព ហើយ
cache ត្រឹមត្រូវចុងក្រោយនៅតែអាចប្រើបាន។ model v2 នីមួយៗដែលមាន context/capability មិនមែន null ត្រូវតែមាន
metadataEvidenceUrls[] ជា HTTPS ដែលមិនត្រូវការព័ត៌មានសម្ងាត់; បើមិនដូច្នោះទេ ការផ្ទៀងផ្ទាត់ស្គីមានឹងបរាជ័យ ហើយ cache
មិនត្រូវបានជំនួសទេ។ តារាងកាតាឡុកបង្ហាញស្ថានភាពទាំងបីជា ✓, ✕ និង ?។
Combo ដែលមានការណែនាំ និងការចូលប្រើ MCP
តម្លៃ familyId ដែលបានបញ្ជាក់ នៅតែមានបន្ទាប់ពី read-time overlay និងជំរុញ module សុទ្ធ
buildRadarComboSuggestions() (src/lib/radar/comboSuggestions.ts)។ family មួយត្រូវបានណែនាំ
តែនៅពេល provider ខុសៗគ្នាយ៉ាងតិចពីរមាន connection សកម្ម និងផ្តល់ model
ID ដែលបានរៀបចំជាក់លាក់ដូចគ្នា។ model ដែលត្រូវបានបិទ, provider អសកម្ម, model ID ដែលបាត់, family ដែលមានតែមួយ និង
ការផ្គូផ្គង alias/prefix ដែលមិនច្បាស់លាស់ សុទ្ធតែបរាជ័យបែបបិទសុវត្ថិភាព។ សំណើប្រើយុទ្ធសាស្ត្រ priority ដែលមានស្រាប់ ដោយតម្រៀប
ថវិកាប្រចាំខែដដែលៗធំបំផុតមុនគេ; UI បង្កើតវាតាមរយៈ POST /api/combos ប៉ុណ្ណោះ។
UI ដែលមានការណែនាំស្ថិតនៅ /dashboard/radar/combos។ វាអានតែ endpoint មូលដ្ឋាន
GET /api/radar/catalog និង GET /api/combos/builder/options ប៉ុណ្ណោះ។ វាមិនដែលដំណើរការការធ្វើសមកាលកម្ម Radar,
អានព័ត៌មានសម្ងាត់របស់អ្នកផ្តល់សេវា ឬសរសេរដោយផ្ទាល់ទៅមូលដ្ឋានទិន្នន័យ combo ឡើយ។
កម្មវិធីភ្ញៀវ MCP អាចអានទិន្នន័យតំណាងមូលដ្ឋានដូចគ្នាជាមួយ omniroute_radar_catalog (read:radar)។ តម្រង
provider, familyId, និង enabledOnly ដែលជាជម្រើស ត្រូវបានវាយតម្លៃបន្ទាប់ពីការអានមូលដ្ឋាន
GET /api/radar/catalog មួយលើក។ លទ្ធផលដែលបានបិទជិតរបស់វារួមមាន metadata នៃកាតាឡុក ព្រមទាំងអ្នកផ្តល់សេវា/ម៉ូដែល,
ឈ្មោះបង្ហាញ, familyId, កូតា, សមត្ថភាព, ស្ថានភាពបានបើក, ប្រភពដើម និង disabledBy; URL សម្រាប់ការដំឡើង,
ជំហាន, ការតភ្ជាប់, អាសយដ្ឋានអ៊ីមែល, កូនសោ និងទិន្នន័យយោងបន្ត មិនត្រូវបានត្រឡប់មកវិញឡើយ។ ឧបករណ៍នេះ
អាចតែអានប៉ុណ្ណោះ ហើយមិនដែលហៅ /api/radar/sync ឡើយ។
សញ្ញាសម្គាល់ប្រភពដើម
ធាតុនីមួយៗដែលបានបញ្ចូលចូលគ្នាមានវាល origin ដែល UI បង្ហាញជាផ្លាកសញ្ញា៖
"baseline"— មិនត្រូវបានកែប្រែពីកាតាឡុកចេញផ្សាយថេរ។"radar"— វាលមួយ ឬច្រើនត្រូវបានធ្វើឱ្យថ្មីដោយ feed។"local"— ប្រតិបត្តិករមានការកំណត់ជំនួសមូលដ្ឋានយ៉ាងហោចណាស់មួយលើធាតុនេះ (ការ កំណត់ជំនួសមូលដ្ឋានតែងតែមានអាទិភាពលើ feed តាមច្បាប់ទី 1 ដោយមិនគិតពីអ្វីដែល feed បញ្ជាក់ឡើយ)។
ផ្ទៃមូលដ្ឋាន — មិនដែលជា feed proxy ឡើយ
ក្រុម route របស់ Radar មូលដ្ឋានខាងក្រោមគាំទ្រ UI ដែលស្ថិតនៅក្រោម src/app/api/radar/៖
| Route | Method | គោលបំណង |
|---|---|---|
/api/radar/catalog |
GET | ត្រឡប់ catalog ដែលបានបញ្ចូលគ្នា (getRadarCatalog()) ពី cache មូលដ្ឋាន។ |
/api/radar/sync |
POST | ដំណើរការ syncRadar() នៅផ្នែក server ហើយត្រឡប់ស្ថានភាពលទ្ធផល។ |
/api/radar/settings |
GET | ត្រឡប់ { optIn, hasSupporterKey, supporterKeyMasked } — មិនត្រឡប់ key ដើមឡើយ។ |
/api/radar/settings |
POST | កំណត់ការយល់ព្រមចូលរួម និង/ឬ supporter key (ដែលបានអ៊ិនគ្រីប)។ |
/api/radar/referrals |
GET | ត្រឡប់ { fixed, campaigns, tier } ពី cache មូលដ្ឋាន — សូមមើល តំណណែនាំ ខាងក្រោម។ |
/api/radar/offers |
GET | ត្រឡប់ offer សកម្មពី live cache មូលដ្ឋានដែលបានផ្ទៀងផ្ទាត់ ហើយមិនត្រឡប់ supporter key ឡើយ។ |
/api/radar/offers/sync |
POST | ដំណើរការ pipeline syncRadarOffers() ដែលប្រើតែ live key នៅផ្នែក server។ |
/api/radar/intel |
GET | ត្រឡប់ Intel ផ្ទាល់ក្នុងមូលដ្ឋានដែលបានផ្ទៀងផ្ទាត់ រួមជាមួយ boolean សម្គាល់ supporter ហើយមិនត្រឡប់អត្តសញ្ញាណ ឬ key ឡើយ។ |
/api/radar/intel/sync |
POST | ដំណើរការ pipeline syncRadarIntel() ដែលប្រើតែ live key នៅផ្នែក server។ |
/api/radar/status |
GET | ត្រឡប់ស្ថានភាព settings/cache មូលដ្ឋានដែលបានតែអាន សម្រាប់ catalog, referrals, offers និង Intel ដោយគ្មាន secret។ |
/api/radar/sync-all |
POST | ដំណើរការ module ធ្វើសមកាលកម្មទាំងបួននៅផ្នែក server ហើយត្រឡប់ស្ថានភាពដាច់ដោយឡែកសម្រាប់ feed នីមួយៗ។ |
/api/radar/local-model-state |
GET | រាយ override និង tombstone ដែលបានរក្សាទុក សម្រាប់ឧបករណ៍បញ្ជាកែសម្រួល/ស្ដារឡើងវិញ។ |
/api/radar/local-model-state |
PATCH | កំណត់ ឬលុប field override displayName/enabled ដែលបានធ្វើសុពលកម្ម។ |
/api/radar/local-model-state |
PUT | បង្កើត ឬលុប tombstone ដោយប្រើ { provider, modelId, tombstoned }។ |
/api/radar/local-model-state |
DELETE | លុប field override ដែលអាចកែសម្រួលបាន ខណៈពេលរក្សាទុក tombstone ដែលមានស្រាប់។ |
ច្បាប់តឹងរ៉ឹង៖ route ទាំងនេះមិនដែលធ្វើជា proxy សម្រាប់សេវា feed ឡើយ។ browser ទាក់ទងតែ
ជាមួយ server OmniRoute មូលដ្ឋានប៉ុណ្ណោះ។ module ទាំងបួនដែលទាក់ទងសេវា Radar គឺ
src/lib/radar/sync.ts (catalog), src/lib/radar/referralsSync.ts (referrals), និង
src/lib/radar/offersSync.ts (offers) ព្រមទាំង src/lib/radar/intelSync.ts (Intel)។ ទាំងអស់នេះដំណើរការ
នៅផ្នែក server មិនដែលនៅផ្នែក client ឡើយ។ វាធានាថា
URL របស់ feed និង supporter key ណាមួយ មិនលេចចេញក្នុង network traffic ដែលអាចមើលឃើញពី client ទាំងស្រុង។
endpoint ទាំងអស់របស់ Radar ត្រឡប់ 404 នៅពេល RADAR_ENABLED បិទ (សូមមើល
Flag ខាងលើ) ហើយបញ្ជូន response កំហុសតាមរយៈ
buildErrorBody()/sanitizeErrorMessage() អនុលោមតាមច្បាប់សម្អាតកំហុសសម្រាប់ repo ទាំងមូល
(docs/security/ERROR_SANITIZATION.md)។
ការផ្ទៀងផ្ទាត់អត្តសញ្ញាណ
endpoint ទាំងអស់របស់ Radar ទាមទារការផ្ទៀងផ្ទាត់អត្តសញ្ញាណតាមរយៈ isAuthenticated()
(src/shared/utils/apiAuth.ts) — cookie នៃ session របស់ dashboard ឬ API key ដែលមាន scope សម្រាប់ការគ្រប់គ្រង
ដែលជាច្រកការពារដូចគ្នានឹងច្រកការពារ /api/settings/* ផ្សេងទៀត។ ការពិនិត្យ 404
ពេល flag បិទ តែងតែដំណើរការ មុន ការពិនិត្យការផ្ទៀងផ្ទាត់អត្តសញ្ញាណ ដូច្នេះ installation ដែលបានបិទ RADAR_ENABLED
នៅតែដូចគ្នាទាំងស្រុងនៅកម្រិត byte (គ្មាន prompt ផ្ទៀងផ្ទាត់អត្តសញ្ញាណ ដើម្បីគ្រាន់តែដឹងថាផ្ទៃនេះមិនមានទេ)។
នៅពេល flag បើក សំណើដែលមិនបានផ្ទៀងផ្ទាត់អត្តសញ្ញាណនឹងទទួល 401 មុនការអាន ឬសរសេរ DB ណាមួយ។
GET /api/radar/settings មិនត្រឡប់ supporter key ដើមឡើយ មិនថាស្ថានភាពផ្ទៀងផ្ទាត់អត្តសញ្ញាណបែបណាក៏ដោយ —
វាត្រឡប់តែទម្រង់ដែលបានបិទបាំង និង boolean hasSupporterKey ប៉ុណ្ណោះ។
ការផ្តល់ជូនសម្រាប់អ្នកគាំទ្រ
ការផ្តល់ជូនប្រើ artifact ដែលបានចុះហត្ថលេខាផ្ទាល់ខ្លួនរបស់វា គឺ GET /v1/offers/latest ហើយមិនដែលប្រើ cache របស់ catalog ឬ referrals រួមគ្នាឡើយ។ endpoint របស់ server តម្រូវឱ្យមាន supporter Bearer key ដែលមានសុពលភាព និងកំពុងដំណើរការ; មិនមានការប្រើ community ជំនួសទេ។ ដូច្នេះ syncRadarOffers() នឹងឈប់មុនពេលភ្ជាប់ទៅបណ្ដាញ នៅពេល feature flag ត្រូវបានបិទ operator មិនបានយល់ព្រមចូលរួម ឬគ្មាន supporter key ត្រូវបានកំណត់រចនាសម្ព័ន្ធ។
បន្ទាប់ពី GET បានជោគជ័យ client នឹងផ្ទៀងផ្ទាត់ហត្ថលេខា Ed25519 លើ bytes នៃ response ដើមទាំងស្រុង ផ្ទៀងផ្ទាត់ RadarOffersFeedSchema តម្រូវឱ្យទាំង body ដែលបានចុះហត្ថលេខា និង header x-omniroute-feed-tier បញ្ជាក់ថា live អនុវត្តលក្ខខណ្ឌ version ដែលមានចំណុចបំបែក និងថ្មីជាងយ៉ាងដាច់ខាត ហើយបន្ទាប់មកទើបជំនួស radar_offers_cache ជា atomically (migration 144_radar_offers_cache.sql)។ កម្រិត 10 MB រួមបញ្ចូល header និង stream ដូចគ្នាដែលប្រើដោយ feeds ផ្សេងទៀតក៏ត្រូវបានអនុវត្តផងដែរ។ ការបរាជ័យផ្នែកហត្ថលេខា schema tier replay ទំហំ HTTP និងបណ្ដាញ សុទ្ធតែរក្សាទុក cache ដែលបានផ្ទៀងផ្ទាត់ចុងក្រោយ។
ទម្រង់ការផ្តល់ជូនបិទគាំទ្រប្រភេទអត្ថប្រយោជន៍ដែលអាចប្រៀបធៀបបានចំនួនបី៖ ភាគរយគិតជា basis points ឥណទានគិតជាឯកតារូបិយប័ណ្ណរង ឬចំនួនថ្ងៃសាកល្បង។ ការផ្តល់ជូនរបស់ partner ត្រូវតែរួមបញ្ចូល baseline សាធារណៈប្រភេទដូចគ្នា ហើយអត្ថប្រយោជន៍របស់វាត្រូវតែធំជាងយ៉ាងដាច់ខាត; ការផ្តល់ជូនផ្លូវការមិនមាន baseline របស់ partner ទេ។ URLs ត្រូវតែជា HTTPS ដែលគ្មាន credential។ getRadarOffers() ផ្ទៀងផ្ទាត់ payload ដែលបានរក្សាទុកក្នុង cache ឡើងវិញជាលក្ខណៈការពារ និងច្រោះធាតុដែលផុតកំណត់រាល់ពេលអានក្នុងមូលដ្ឋាន; /dashboard/radar/offers ច្រោះការផុតកំណត់ម្តងទៀតមុនពេល render ប្រើអត្ថបទភាសាព័រទុយហ្គាល់នៅពេលមាន ជាមួយភាសាអង់គ្លេសជាជម្រើសបម្រុង និងដាក់ស្លាកការផ្តល់ជូនរបស់ partner ឱ្យច្បាស់លាស់។
browser ហៅតែ routes ក្នុងមូលដ្ឋានប៉ុណ្ណោះ៖ វាអាន snapshot នៃ settings ដែលបានលាក់សម្ងាត់ ស្នើឱ្យ POST /api/radar/offers/sync ធ្វើ refresh នៅផ្នែក server ហើយបន្ទាប់មកអាន GET /api/radar/offers។ បើគ្មាន key វានឹងបង្ហាញតំណ contributor/support ដែលមានស្រាប់ ជំនួសឱ្យការព្យាយាមផ្ញើ feed request។ តំណការផ្តល់ជូនខាងក្រៅបើកនៅក្នុង tab ថ្មីដោយប្រើ noopener noreferrer។ មិនមាន MCP tool ឈ្មោះ radar_offers ត្រូវបានបញ្ចេញក្នុង release នេះទេ។
Radar Intel ផ្លាកសញ្ញាអ្នកគាំទ្រ និង CLI
Intel គឺជា artifact ដែលបានចុះហត្ថលេខានៅ GET /v1/intel/latest។ RadarIntelFeedSchema បិទទទួលយកតែចំណាត់ថ្នាក់ ELO ដែលគ្រប់គ្រងដោយ Radar និងបានទាញយកដោយ curator ឯកជនពីការប្រៀបធៀបដែលបានបញ្ជាក់ ព្រមទាំងភាពខុសគ្នាជាក់ស្តែងនៃអាយុ/ចំនួន catalog ដែលបានទាញយកពី snapshots របស់ catalog ដែលបានចុះហត្ថលេខា។ វិធីសាស្ត្រត្រូវបានកំណត់ថេរនៅ initial rating 1000 និង K=32។ ចំណាត់ថ្នាក់ទទេមានសុពលភាព នៅពេលមិនទាន់មានការប្រៀបធៀបណាមួយត្រូវបានបញ្ជាក់; client មិនដែលបង្កើតចំណាត់ថ្នាក់ដោយសំយោគឡើយ។
syncRadarIntel() អនុវត្ត Bearer នៅផ្នែក server, timeout 30 វិនាទី, កម្រិត streamed 10 MiB, ការផ្ទៀងផ្ទាត់ Ed25519 លើ bytes ដើមទាំងស្រុង, schema តឹងរ៉ឹង, លក្ខខណ្ឌ live សម្រាប់ body/header, កម្រិតអប្បបរមារបស់ version និងការរក្សា cache ល្អចុងក្រោយ ដូចគ្នានឹងការផ្តល់ជូន។ បន្ទាប់ពី snapshot ដែលបានផ្ទៀងផ្ទាត់ និងកំពុងដំណើរការ ត្រូវបានរក្សាទុក client នឹងទាញយក radar:<sha256(supporter key)> រក្សាទុកតែអត្តសញ្ញាណ one-way នោះ ហើយបញ្ចេញ recognition event ឯកទេស radar_supporter។ ផ្លាកសញ្ញា radar-supporter របស់វាគឺ idempotent និងផ្តល់ XP សូន្យ; វាមិនដែលធ្វើបច្ចុប្បន្នភាព leaderboards ឬប្រើ token_share ឡើងវិញទេ។ /dashboard/radar/intel render ផ្លាកសញ្ញាតែពី metadata នៃ cache ក្នុងមូលដ្ឋានដែលបានផ្ទៀងផ្ទាត់ប៉ុណ្ណោះ។
CLI ផ្តល់ omniroute radar status និង omniroute radar sync។ ទាំងពីរទាក់ទងតែជាមួយ OmniRoute API ក្នុងមូលដ្ឋានប៉ុណ្ណោះ។ status អនុវត្ត GET /api/radar/status ដែលបានតែអាន; sync ផ្ញើ POST /api/radar/sync-all មួយដង និងបោះពុម្ពលទ្ធផលសម្រាប់ feed នីមួយៗ។ command ទាំងពីរមិនអាន មិនទទួល និងមិនបោះពុម្ព supporter key ហើយក៏មិនទាក់ទងសេវា Radar ដោយផ្ទាល់ដែរ។
តំណណែនាំ (ក្រេឌីតឥតគិតថ្លៃ)
តំណណែនាំត្រូវបានផ្តល់ពី feed ឯករាជ្យ និងទាន់សម័យជានិច្ច —
GET /v1/referrals/latest — ដាច់ដោយឡែកពី catalog feed។ នេះត្រូវបានធ្វើឡើងដោយចេតនា៖
catalog feed នៅលើ community tier គឺជា snapshot ដែលអាចចាស់រហូតដល់ 30 ថ្ងៃ ដូច្នេះ
តំណណែនាំដែលបានស្រង់ចេញពីវា ក៏ធ្លាប់យឺតជាងបញ្ជីតំណពិតប្រាកដរបស់ server ក្នុងរយៈពេលដូចគ្នា
(តំណណែនាំដែលទើបតែបន្ថែមថ្មី នឹងមិនទៅដល់អ្នកប្រើឥតគិតថ្លៃ/community រហូតដល់មួយខែ)។
referrals feed លុបបំបាត់ការពន្យារពេលនោះ ដោយធ្វើសមកាលកម្មតាមកាលវិភាគផ្ទាល់ខ្លួនដែលខ្លីជាងច្រើន។
// តួ response របស់ GET /v1/referrals/latest (ចុះហត្ថលេខាដោយ Ed25519 ប្រើ pinned key ដូចគ្នានឹង
// catalog feed):
{
feed: "omniroute-radar-referrals",
schemaVersion: 1,
generatedAt: string, // ISO — កំណត់បានជាក់លាក់៖ max(updatedAt) ក្នុងចំណោមតំណ
// ណែនាំទាំងអស់ ដូច្នេះ request ដូចគ្នាពីរ បង្កើត signed bytes/signature
// ដូចគ្នាបេះបិទ
referrals: {
fixed: RadarReferral[], // មានក្នុងគ្រប់ tier ទាំងអស់ រួមទាំង no-auth/community
campaigns: RadarReferral[], // ត្រូវបានបំពេញតែសម្រាប់ live (supporter) Bearer key ដែលមានសុពលភាព
// ប៉ុណ្ណោះ; request ដែល no-auth/expired-key ទទួលបាន []
},
}
// RadarReferral = { provider, url, kind: "fixo" | "campanha", validUntil,
// requiredAction, isDefault }
មិនដូច catalog feed ទេ តួនេះមិនមាន field tier ទាល់តែសោះ — server សម្រេចថា
ត្រូវរួមបញ្ចូលអ្វីខ្លះសម្រាប់ request នីមួយៗ ដោយផ្អែកលើ key Authorization ដូច្នេះ
response header x-omniroute-feed-tier គឺជាប្រភពតែមួយគត់សម្រាប់ tier ដែលបានផ្តល់
(referralsSync.ts::syncRadarReferrals); header ដែលអវត្តមាន ឬមិនត្រូវបានស្គាល់ នឹងបន្ថយទៅជា
"community" ដែលជាការសន្មត់មានសិទ្ធិតិចបំផុត។ RadarReferralsFeedSchema
(src/lib/radar/referralsFeedSchema.ts) ផ្ទៀងផ្ទាត់តួទាំងមូល ដោយប្រើឡើងវិញនូវ
RadarReferralSchema សម្រាប់ referral នីមួយៗ ដែលបាន export ពី feedSchema.ts ដើម្បីឱ្យ feed
ទាំងពីរផ្ទៀងផ្ទាត់ referral នីមួយៗតាមរបៀបដូចគ្នា។ រាល់ RadarReferral.url ត្រូវតែជា https:// —
url ដែលជា http:// នឹងមិនឆ្លងកាត់ការផ្ទៀងផ្ទាត់ schema ទេ។
field referrals ចាស់ដែលបានបង្កប់ក្នុង catalog លើ RadarFeedSchema (feedSchema.ts) ត្រូវបាន
រក្សាទុកសម្រាប់ភាពត្រូវគ្នាជាមួយកំណែចាស់នៃ catalog feed ដែលបាន cache រួច ប៉ុន្តែ
getRadarReferrals() លែងអានវាទៀតហើយ — សូមមើល Accessor ខាងក្រោម។
ការធ្វើសមកាលកម្ម
syncRadarReferrals() (src/lib/radar/referralsSync.ts) គឺជា module តែមួយគត់ដែល
ចូលប្រើ network សម្រាប់ referral ដោយឆ្លុះបញ្ចាំង contract របស់ syncRadar() យ៉ាងដូចគ្នាបេះបិទ៖
flag បិទ → disabled; opt-in ជា false → opt_out; ទាញយក
${RADAR_FEED_URL}/v1/referrals/latest (ប្រើ fork overrides RADAR_FEED_URL/
RADAR_FEED_PUBKEY ដូចគ្នានឹង catalog), ផ្ទៀងផ្ទាត់ហត្ថលេខា Ed25519 លើ response bytes
ដើមជាក់លាក់ (verifyFeedBytes), ផ្ទៀងផ្ទាត់ជាមួយ RadarReferralsFeedSchema និង cache ទៅក្នុង
តារាង radar_referrals_cache (migration 142_radar_referrals_cache.sql) — ជាតារាងដែលដាច់ដោយឡែក
ទាំងស្រុងពី radar_feed_cache របស់ catalog។ កម្រិត response 10 MB និងកម្រិតអប្បបរមា
generatedAt បដិសេធ feed ចូលដែលចាស់ជាង feed ក្នុង cache ដើម្បីការពារការចាក់ឡើងវិញនូវ
artifact ដែលបានចុះហត្ថលេខាចាស់ជាង។ timestamp ស្មើគ្នាត្រូវបានទទួលយក៖ server ផ្តល់ដោយចេតនា
នូវ generatedAt ដែលកំណត់បានជាក់លាក់ដូចគ្នា សម្រាប់វ៉ារ្យ៉ង់ referral community និង live
ដូច្នេះ signed payload និង tier ដែលបានផ្តល់អាចផ្លាស់ប្តូរបន្ទាប់ពីការផ្លាស់ប្តូរ supporter key
ដោយមិនចាំបាច់ឱ្យសំណុំតំណមូលដ្ឋានផ្លាស់ប្តូរ។ វាមិន throw ទេ — វាតែងតែត្រឡប់ status object;
error មិនដែលមាន stack trace ក្នុង reason ទេ។
trigger ពីររក្សា referrals cache ឱ្យទាន់សម័យ ដោយទាំងពីរឯករាជ្យពីកាលវិភាគ 24h ផ្ទាល់របស់ catalog៖
- ធ្វើសមកាលកម្មនៅពេលអាន —
GET /api/radar/referralsខ្លួនវាហៅsyncRadarReferrals()ភ្លាមៗ នៅពេល cache បាត់ ឬចាស់ជាងREFERRALS_STALE_MS(1h,shouldSyncReferralsOnRead()) មុនពេលផ្តល់ response។ នេះជាអ្វីដែលធ្វើឱ្យតំណ fixed «ទាន់សម័យជានិច្ច» សម្រាប់ការផ្ទុក dashboard បន្ទាប់ភ្លាមៗ ដោយមិនចាំបាច់រង់ចាំ background timer ណាមួយ។ - ការធ្វើសមកាលកម្មបន្ទាប់បន្សំរបស់ scheduler —
radarSchedulerTick()(scheduler.ts) វាយតម្លៃដោយឯករាជ្យលើភាពចាស់របស់ referrals នៅរាល់ hourly tick ដូចគ្នាដែលប្រើសម្រាប់ catalog ហើយហៅsyncRadarReferrals()នៅពេលដល់កំណត់។ វាដំណើរការដោយមិនគិតថា catalog ខ្លួនវា ដល់កំណត់នៅ tick នោះឬអត់ ហើយមិនប៉ះពាល់ដល់ទម្រង់របស់RadarTickResultឡើយ (គ្រាន់តែជា side effect ដែលធ្វើឡើងតាមលទ្ធភាព ហើយត្រូវបានរំលងពេលមាន error)។
កម្មវិធីចូលប្រើ
src/lib/radar/index.ts export កម្មវិធីចូលប្រើសម្រាប់អានតែប៉ុណ្ណោះចំនួនពីរ ដែលទាំងពីរមិនដែល
throw ទេ (ជា defensive contract ដូចគ្នានឹង getRadarCatalog() — flag បិទ គ្មាន cache ឬ
cached payload ខូច សុទ្ធតែត្រូវបានបម្លែងទៅជាទម្រង់ទទេជំនួសឱ្យ error)៖
getRadarReferrals()→{ fixed: RadarReferral[], campaigns: RadarReferral[] }, អានពីradar_referrals_cache(តាមរយៈgetRadarReferralsCache()) និងផ្ទៀងផ្ទាត់ តាមរយៈRadarReferralsFeedSchema— មិនមែន catalog cache ទេ។getDefaultReferralFor(provider)→ referral ក្នុងfixedដែលមានisDefault: trueសម្រាប់ provider នោះ ឬnull។ វាពិនិត្យតែfixedប៉ុណ្ណោះ — campaign មិនដែលត្រូវបានប្រើជា តំណ "default" របស់ provider ទេ។
ច្បាប់ជាក់ស្តែងសម្រាប់ «referral មួយណាជា default សម្រាប់ provider» ស្ថិតនៅក្នុង
findDefaultReferral() (src/lib/radar/referrals.ts) ដែលជា pure function តូចមួយ និង គ្មាន
DB import — វាមានសុវត្ថិភាពក្នុងការនាំចូលទៅក្នុង component "use client"។ getRadarReferrals/
getDefaultReferralFor (ក្នុង index.ts) នាំចូល @/lib/db/radar ហើយដូច្នេះត្រូវនៅតែជា
server-only; providers dashboard នាំចូល referrals.ts ដោយផ្ទាល់ ជំនួសឱ្យ
index.ts (សូមមើលខាងក្រោម) ដើម្បីជៀសវាងការ bundle better-sqlite3 ទៅក្នុង browser។
GET /api/radar/referrals
អនុវត្តតាមលំដាប់ gate ដូចគ្នាទាំងស្រុងនឹង Radar route ផ្សេងៗទាំងអស់៖ បិទ RADAR_ENABLED →
404 (ត្រួតពិនិត្យមុនគេ ដើម្បីរក្សាភាពដូចគ្នាកម្រិត byte); មិនបានផ្ទៀងផ្ទាត់អត្តសញ្ញាណ → 401; បើមិនដូច្នោះទេ
វានឹងបង្កឱ្យមាន sync-on-read (សូមមើលខាងលើ) នៅពេលទិន្នន័យចាស់ ហើយបន្ទាប់មកត្រឡប់ 200 ជាមួយ
{ fixed, campaigns, tier } — tier មកដោយផ្ទាល់ពី cache row (ដែលអាចទើបតែបាន refresh)
និងមានគោលបំណងផ្តល់ព័ត៌មានតែប៉ុណ្ណោះ (ប្រើដើម្បីបង្ហាញសារណែនាំ upsell បែបទន់ភ្លន់របស់ UI ខាងក្រោម)។ វាមិនដែល
proxy feed server ដោយផ្ទាល់ទេ — source របស់ route នេះមិនមានការហៅ fetch( ឡើយ;
បណ្ដាញត្រូវបានប្រើតែនៅខាងក្នុង syncRadarReferrals() ប៉ុណ្ណោះ ដោយអនុវត្តតាមគោលការណ៍
ប្រើតែ local cache ដូចគ្នានឹង /api/radar/catalog។
UI ផ្ទាំងគ្រប់គ្រង — ផ្ទាំង "ក្រេឌីតឥតគិតថ្លៃ" នៅលើ /dashboard/radar
ប្រើទំព័រ Radar ដែលមានស្រាប់ (src/app/(dashboard)/dashboard/radar/page.tsx) ឡើងវិញជា
ផ្ទាំងទីពីរ ជំនួសឱ្យបង្កើត route ថ្មី — កាត់បន្ថយវិសាលភាព routing/i18n សម្រាប់មុខងារដែលជា
បំរែបំរួលនៃទិន្នន័យដែលទំព័រនេះប្រមូលយករួចហើយ។ បន្ទាប់ពីជ្រើសរើសចូលប្រើ របារផ្ទាំងនឹងផ្តល់
កាតាឡុក (តារាងដែលមានស្រាប់) និង ក្រេឌីតឥតគិតថ្លៃ៖
- តំណថេរត្រូវបានដាក់ជាក្រុមតាម provider ដោយតំណនីមួយៗបង្ហាញ
requiredAction(នៅពេលមាន) និងប៊ូតុងtarget="_blank" rel="noopener noreferrer"ដែលនាំទៅកាន់ referral URL។ - Campaign បង្ហាញព័ត៌មានដូចគ្នា ព្រមទាំង
validUntilនៅពេលមាន។ - នៅពេល
campaignsទទេ ហើយ tier ដែលបានផ្តល់គឺcommunityUI នឹងបង្ហាញ សារណែនាំ upsell ខ្លីមួយ ("campaign ដែលមានពេលកំណត់គឺជាអត្ថប្រយោជន៍បន្ថែមសម្រាប់អ្នកគាំទ្រ") — វា មិនដែល លាក់ ឬរារាំងបញ្ជីតំណថេរឡើយ ដែលនៅតែបង្ហាញពេញលេញសម្រាប់គ្រប់ tier។ សារ upsell នេះគ្រាន់តែជាសារណែនាំបែបទន់ភ្លន់ប៉ុណ្ណោះ មិនមែនជាការរារាំងទេ។
តំណ Referral នៅលើឈ្មោះ provider (ផ្ទាំងគ្រប់គ្រង providers)
ProviderPageHeader (src/app/(dashboard)/dashboard/providers/[id]/components/)
បានភ្ជាប់ឈ្មោះ provider ទៅកាន់ providerInfo.website រួចហើយនៅពេលមាន ហើយមាន
គំរូមុនមួយសម្រាប់តំណដែលរកចំណូល៖ កំណត់សម្គាល់ partner-link របស់ Kimi (Moonshot AI)
(i18n key providers.kimiPartnerLinkNote)។ D28 ប្រើឡើងវិញនូវគំរូកំណត់សម្គាល់សាមញ្ញដដែល
សម្រាប់ Radar default referrals ជំនួសឱ្យការបង្កើត key ថ្មី។
ការភ្ជាប់រលុង តាមការរចនា៖
resolveProviderHeaderLink()(src/app/(dashboard)/dashboard/providers/providerPageUtils.ts) គឺជាមុខងារ pure —(staticWebsite, referralUrl) => { website, isReferralLink }— ដោយមិនមាន dependency លើ@/lib/radarឬ@/lib/db/*ទេ។providerPageUtils.tsទាំងមូលនៅតែមិនមាន import ទាំងនោះ (ផ្ទៀងផ្ទាត់ដោយtests/unit/provider-header-referral-link.test.ts)។ProviderDetailPageClient.tsx(component"use client") គឺជាកន្លែងតែមួយគត់ដែលត្រូវបានអនុញ្ញាត ឱ្យប្រមូលទិន្នន័យ Radar — តាមរយៈfetch("/api/radar/referrals")ដែលជាគំរូ local-route ដូចគ្នា នឹងអ្វីដែលទំព័រផ្ទាំងគ្រប់គ្រង Radar ផ្ទាល់ប្រើ — ហើយវាគណនា default referral នៅផ្នែក client ដោយប្រើfindDefaultReferral()ពីsrc/lib/radar/referrals.tsដែលមិនពឹងផ្អែកលើ DB។- នៅពេលបិទ
RADAR_ENABLEDការហៅ fetch នឹងទទួល404,referralUrlនៅតែជាnullហើយresolveProviderHeaderLink()ត្រឡប់ catalogwebsiteថេរដោយមិនកែប្រែ — ទំព័រ provider មានភាពដូចគ្នាកម្រិត byte នឹងមុនពេលមុខងារនេះមាន។ លទ្ធផលដូចគ្នានេះក៏កើតឡើងនៅពេល មិនទាន់មាន cache ឬគ្មាន default referral សម្រាប់ provider ជាក់លាក់នោះ។ - នៅពេលមាន default referral អនុវត្ត
ProviderPageHeaderនឹងទទួលisReferralLinkនិងបង្ហាញកំណត់សម្គាល់/tooltip សាមញ្ញដូចគ្នានឹង partner link របស់ Kimi (ដោយប្រើ keyproviders.kimiPartnerLinkNoteឡើងវិញ) — មិនដែលបង្កើតការបង្ហាញរូបភាពថ្មីដាច់ដោយឡែកទេ។
របៀបបង្ហោះ feed ដោយខ្លួនឯង
fork ឬអ្នកបង្ហោះដោយខ្លួនឯងដែលចង់គ្រប់គ្រង catalog ទាំងស្រុង អាចដំណើរការសេវា feed ផ្ទាល់ខ្លួនបាន ដោយមិនចាំបាច់កែប្រែ client code៖
- ផ្តល់ endpoint
GET /v1/catalog/latestដែលត្រឡប់ JSON body ស្របតាមRadarFeedSchema(src/lib/radar/feedSchema.ts) — នៅកម្រិតកំពូលមានfeed: "omniroute-radar",schemaVersion: 2,version,tier,providers,models,quirksនិងtotals។ ត្រូវគោរពx-omniroute-radar-schema: 2; server ដែលឆបគ្នាក្នុងអំឡុងពេលផ្លាស់ប្តូរ គួរតែកំណត់ requests ដែលមិនមានវា ឱ្យប្រើ artifact v1 ដែលបានចុះហត្ថលេខាដាច់ដោយឡែកតាមលំនាំដើម។ - ចុះហត្ថលេខាលើ bytes ជាក់លាក់នៃ response ដោយប្រើគូ key Ed25519 ហើយត្រឡប់ហត្ថលេខា base64
នៅក្នុង response header
x-omniroute-feed-signature។ - កំណត់
RADAR_FEED_URLទៅ base URL ថ្មី និងRADAR_FEED_PUBKEYទៅ public key ដែលត្រូវគ្នា (base64-DER SPKI ឬ PEM) — សូមមើល ឯកសារយោង env var។ - បើក
RADAR_ENABLEDនិងជ្រើសរើសចូលរួមតាមរយៈPOST /api/radar/settings({ optIn: true })។
មិនត្រូវការការកែប្រែ code ផ្សេងទៀតទេ — verifyFeedBytes() នឹងទទួលយក override
ដោយស្វ័យប្រវត្តិ (getFeedPublicKeys() នៅក្នុង src/lib/radar/pinnedKeys.ts) ហើយការប្រៀបធៀប version,
ការផ្ទៀងផ្ទាត់ schema និងច្បាប់ merge នឹងត្រូវបានអនុវត្តដូចគ្នាចំពោះ feed ដែលបង្ហោះដោយខ្លួនឯង។
Referral links (សូមមើល Referral links (ក្រេឌីតឥតគិតថ្លៃ)
ខាងលើ) គឺជា artifact ស្រេចចិត្ត និងដាច់ដោយឡែក៖ fork ដែលផ្តល់តែ /v1/catalog/latest
នៅតែដំណើរការបានពេញលេញ — syncRadarReferrals() នឹងបន្ថយទៅជា { status: "error" } នៅពេលទទួលបាន 404
ពី /v1/referrals/latest ហើយ cache នឹងនៅតែទទេ ដូច្នេះ
GET /api/radar/referrals នឹងបន្តត្រឡប់ { fixed: [], campaigns: [], tier: null }
ជំនួសឱ្យការធ្វើឱ្យផ្នែកផ្សេងទៀតនៃទំព័របរាជ័យ។ ដើម្បីផ្តល់ referral links ផងដែរ សូមផ្តល់
GET /v1/referrals/latest ដែលស្របតាម RadarReferralsFeedSchema
(src/lib/radar/referralsFeedSchema.ts) ហើយចុះហត្ថលេខាវាដោយប្រើគូ key Ed25519 ដូចគ្នានឹង
catalog feed។
Supporter offers គឺជា artifact ស្រេចចិត្តមួយផ្សេងទៀត។ ដើម្បីផ្តល់វា សូមដាក់ឱ្យដំណើរការ
GET /v1/offers/latest ជាមួយ RadarOffersFeedSchema បែបបិទ
(src/lib/radar/offersFeedSchema.ts) តម្រូវឱ្យមានសិទ្ធិប្រើប្រាស់ដែលកំពុងមានសុពលភាព ត្រឡប់
x-omniroute-feed-tier: live ហើយចុះហត្ថលេខាលើ bytes ជាក់លាក់ដោយប្រើ key ដូចគ្នា។ fork ដែលមិនរួមបញ្ចូល
endpoint នេះ នឹងរក្សាឥរិយាបថរបស់ catalog/referrals មិនឱ្យផ្លាស់ប្តូរ; ការធ្វើឱ្យ offer ថ្មីឡើងវិញនឹងបរាជ័យដោយមិនបំផ្លាញទិន្នន័យ
ហើយ cache របស់ offer ក្នុងមូលដ្ឋានដែលបានផ្ទៀងផ្ទាត់ចុងក្រោយនឹងនៅតែអាចប្រើបាន។
Intel ក៏ជាជម្រើសតាមរបៀបដូចគ្នាដែរ។ អ្នកបង្ហោះដោយខ្លួនឯងអាចផ្តល់ GET /v1/intel/latest ដោយប្រើ
RadarIntelFeedSchema (src/lib/radar/intelFeedSchema.ts) តម្រូវឱ្យមានសិទ្ធិប្រើប្រាស់ដែលកំពុងមានសុពលភាព ត្រឡប់
x-omniroute-feed-tier: live ហើយចុះហត្ថលេខាលើ bytes ជាក់លាក់ដោយប្រើ key Ed25519 រួម។ ការមិនរួមបញ្ចូល
endpoint នេះ នឹងទុកឱ្យ catalog, referrals និង offers មិនផ្លាស់ប្តូរ; ការធ្វើឱ្យ Intel ថ្មីឡើងវិញនឹងរក្សាទុក snapshot
ក្នុងមូលដ្ឋានដែលបានផ្ទៀងផ្ទាត់ចុងក្រោយណាមួយ។
ឯកសារពាក់ព័ន្ធ
docs/security/ERROR_SANITIZATION.md— លំនាំ error-response ដែល routes/api/radar/*អនុវត្តតាម។docs/reference/ENVIRONMENT.md— ឯកសារយោងRADAR_FEED_URL/RADAR_FEED_PUBKEY។