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:
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
@@ -20,23 +21,22 @@ func TestSendPackageHappyPath(t *testing.T) {
|
||||
if r.URL.Path != "/api/package/CH1/file" {
|
||||
t.Errorf("неожиданный путь %q", r.URL.Path)
|
||||
}
|
||||
// Проверим что тело — это {Type: "archive", File: base64}.
|
||||
var body struct {
|
||||
Type string `json:"Type"`
|
||||
File string `json:"File"`
|
||||
// ИШ ждёт multipart/form-data: поля Type (FILE|ARCHIVE) + File (binary).
|
||||
if err := r.ParseMultipartForm(10 << 20); err != nil {
|
||||
t.Fatalf("parse multipart: %v", err)
|
||||
}
|
||||
if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
|
||||
t.Fatalf("decode body: %v", err)
|
||||
if got := r.FormValue("Type"); got != "ARCHIVE" {
|
||||
t.Errorf("Type = %q, ожидалось ARCHIVE", got)
|
||||
}
|
||||
if body.Type != "archive" {
|
||||
t.Errorf("Type = %q, ожидалось archive", body.Type)
|
||||
f, _, err := r.FormFile("File")
|
||||
if err != nil {
|
||||
t.Fatalf("form file: %v", err)
|
||||
}
|
||||
if body.File == "" {
|
||||
defer f.Close()
|
||||
b, _ := io.ReadAll(f)
|
||||
if len(b) == 0 {
|
||||
t.Errorf("File пустой")
|
||||
}
|
||||
if _, err := base64.StdEncoding.DecodeString(body.File); err != nil {
|
||||
t.Errorf("File не base64: %v", err)
|
||||
}
|
||||
w.WriteHeader(http.StatusOK)
|
||||
_ = json.NewEncoder(w).Encode(map[string]any{"id": 123})
|
||||
}))
|
||||
|
||||
Reference in New Issue
Block a user