feat: живой цикл M2M с НРД + мастер установки ключа на флешку
Инфраструктура M2M (живой обмен с НРД через ИШ): - обработка M2MTransferResponse: ERROR(M2Mxx) → заявка Отклонена, сохранение ответа; INFO → ждём Decision; идемпотентность поллера - fallback-корреляция ответов с нулевым GUID (M2M14/M2M17) по FIFO - сырой XML ответа НРД в карточке заявки (для пересылки в ТП) - тестовый пакет роботу приведён к эталону m2m_robot_samples (CostInfo=Yes, 4 бумаги, IsolationStatus, DocumentSeries=сценарий); override паспорта - редирект из теста сразу в карточку заявки Мастер установки ключа Валидаты на флешку (admin/setup/keywizard): - пошаговый: загрузка .7z+пароль → выбор флешки → запись → справочник сертификатов (CRL) → перезапуск+проверка ИШ → готово - привилегированный воркер (bj-keymedia) в host-namespace через файл-обмен, bj-server остаётся в песочнице - сохранение структуры профиля архива (spr<N>), перечисление съёмных USB Прочее: - пакет-доказательство для ТП НРД + форма регистрации участника M2M - эталонные образцы робота (DOC/m2m_robot_samples) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+44
-13
@@ -19,19 +19,29 @@ var templatesFS embed.FS
|
||||
// конкретный content-шаблон). Так html/template не путается с несколькими
|
||||
// {{define "content"}} в разных файлах.
|
||||
type admin struct {
|
||||
home, claims, claim, status, setup *template.Template
|
||||
help, helpDatabase, helpLK, helpCryptoPro, helpSystems, helpRobot, helpArchitecture *template.Template
|
||||
wizard, news *template.Template
|
||||
home, claims, claim, status, setup *template.Template
|
||||
help, helpDatabase, helpLK, helpCrypto, helpSystems, helpRobot, helpArchitecture *template.Template
|
||||
wizard, news, keyWizard *template.Template
|
||||
}
|
||||
|
||||
// templateFuncs — функции, доступные внутри шаблонов. Главная задача —
|
||||
// русификация статусов и других технических обозначений (см. требование
|
||||
// «всё UI на русском, кроме программных терминов»).
|
||||
var templateFuncs = template.FuncMap{
|
||||
"ru": russianText,
|
||||
"ruState": russianState,
|
||||
"ruOutcome": russianOutcome,
|
||||
"now": time.Now,
|
||||
"ru": russianText,
|
||||
"ruState": russianState,
|
||||
"ruOutcome": russianOutcome,
|
||||
"now": time.Now,
|
||||
"add": func(a, b int) int { return a + b },
|
||||
"fallbackTpl": fallback,
|
||||
"anyKeymedia": func(ds []flashDrive) bool {
|
||||
for _, d := range ds {
|
||||
if d.IsKeymedia {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
},
|
||||
}
|
||||
|
||||
// russianState переводит технический FSM-state в человекочитаемый
|
||||
@@ -115,9 +125,9 @@ func newAdmin() (*admin, error) {
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("parse admin_help_lk: %w", err)
|
||||
}
|
||||
helpCP, err := parse("admin_help_cryptopro.html")
|
||||
helpCrypto, err := parse("admin_help_crypto.html")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("parse admin_help_cryptopro: %w", err)
|
||||
return nil, fmt.Errorf("parse admin_help_crypto: %w", err)
|
||||
}
|
||||
helpSys, err := parse("admin_help_systems.html")
|
||||
if err != nil {
|
||||
@@ -139,11 +149,15 @@ func newAdmin() (*admin, error) {
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("parse admin_help_architecture: %w", err)
|
||||
}
|
||||
keyWizard, err := parse("admin_keywizard.html")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("parse admin_keywizard: %w", err)
|
||||
}
|
||||
return &admin{
|
||||
home: home, claims: claims, claim: claim, status: status, setup: setup,
|
||||
help: help, helpDatabase: helpDB, helpLK: helpLK, helpCryptoPro: helpCP, helpSystems: helpSys,
|
||||
help: help, helpDatabase: helpDB, helpLK: helpLK, helpCrypto: helpCrypto, helpSystems: helpSys,
|
||||
helpRobot: helpRobot, helpArchitecture: helpArch,
|
||||
wizard: wizard, news: news,
|
||||
wizard: wizard, news: news, keyWizard: keyWizard,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -173,6 +187,11 @@ type homeData struct {
|
||||
}
|
||||
Recent []ClaimView
|
||||
News []NewsItem // top-3 активных или свежих новостей
|
||||
|
||||
// Сводка готовности системы для hero-блока дашборда.
|
||||
AllReady bool
|
||||
NotReadyCount int
|
||||
TotalCount int
|
||||
}
|
||||
|
||||
// claimsData — данные журнала.
|
||||
@@ -222,8 +241,8 @@ func RegisterAdmin(mux *http.ServeMux, svc *Service, rc *RuntimeConfig, getOpts
|
||||
render(w, a.helpDatabase, nowPage("База данных", "help"))
|
||||
case p == "help/lk-api":
|
||||
render(w, a.helpLK, nowPage("API ЛК", "help"))
|
||||
case p == "help/cryptopro":
|
||||
render(w, a.helpCryptoPro, nowPage("КриптоПро", "help"))
|
||||
case p == "help/crypto":
|
||||
render(w, a.helpCrypto, nowPage("Криптография", "help"))
|
||||
case p == "help/systems":
|
||||
render(w, a.helpSystems, nowPage("Внешние системы", "help"))
|
||||
case p == "help/robot":
|
||||
@@ -254,6 +273,18 @@ func (a *admin) renderHome(w http.ResponseWriter, r *http.Request, svc *Service,
|
||||
Recent: recent.Items,
|
||||
News: topNews(rc.Snapshot().News.Items, 3),
|
||||
}
|
||||
// Готовность системы считаем ТОЛЬКО по обязательным компонентам.
|
||||
// Опциональные (напр. callback в ЛК) не влияют на «готовность».
|
||||
for _, c := range status.Checks {
|
||||
if c.Optional {
|
||||
continue
|
||||
}
|
||||
data.TotalCount++
|
||||
if !c.OK {
|
||||
data.NotReadyCount++
|
||||
}
|
||||
}
|
||||
data.AllReady = data.TotalCount > 0 && data.NotReadyCount == 0
|
||||
full, err := svc.ListClaims(ctx, m2mcore.Filter{Limit: 200})
|
||||
if err == nil {
|
||||
for _, c := range full.Items {
|
||||
|
||||
Reference in New Issue
Block a user