diff --git a/README.md b/README.md
index 4e69b92..65b484d 100644
--- a/README.md
+++ b/README.md
@@ -252,6 +252,8 @@ curl -H "Authorization: Bearer change-me-in-production" \
Административный API внешней очереди возвращает безопасный provenance: время первого и последнего обнаружения, время проверки, отсутствующие поля и только разрешённые скалярные поля исходной записи. Неизвестные ключи и вложенные служебные структуры в ответ не попадают.
+В карточке внешнего наблюдения provenance доступен в отдельном раскрываемом блоке: временная линия, отсутствующие и исходные разрешённые поля видны до сопоставления и публикации.
+
## Эксплуатация production
- первый запуск, обновление и preflight: [deploy/README.md](deploy/README.md);
diff --git a/apps/web/src/pages/admin/external-sources.astro b/apps/web/src/pages/admin/external-sources.astro
index 9df05aa..5c9ca86 100644
--- a/apps/web/src/pages/admin/external-sources.astro
+++ b/apps/web/src/pages/admin/external-sources.astro
@@ -64,6 +64,19 @@ const apiUrl = import.meta.env.PUBLIC_API_URL || "http://localhost:8000";
if (pageNumber) pageNumber.textContent = `Страница ${offset / 50 + 1}`;
if (!pending.length) { list.innerHTML = '
Показаны только разрешённые поля, сохранённые парсером. Перед публикацией сверьте их с первоисточником.
`;
+ summary.append(details);
+ });
}
async function changePage(delta: number) {
const oldOffset = offset;
diff --git a/apps/web/src/styles/global.css b/apps/web/src/styles/global.css
index 82c8f65..5058db1 100644
--- a/apps/web/src/styles/global.css
+++ b/apps/web/src/styles/global.css
@@ -16,6 +16,7 @@
.admin-session-bar{display:flex;align-items:center;justify-content:space-between;gap:16px;margin:0 0 18px;padding:12px 14px;border:1px solid var(--line);border-radius:10px;background:var(--surface);color:var(--muted);font-size:13px}.admin-session-bar[hidden]{display:none}.admin-session-bar button{min-height:38px}
.admin-queue-filters{display:grid;grid-template-columns:1.3fr repeat(3,1fr) auto;gap:10px;align-items:end;margin:0 0 18px;padding:16px;border-radius:12px;background:var(--deep)}.admin-queue-filters[hidden]{display:none}.admin-queue-filters label{color:#b8c5c2;font-size:11px;text-transform:uppercase;letter-spacing:.08em}.admin-queue-filters input,.admin-queue-filters select{display:block;width:100%;height:42px;margin-top:6px;padding:0 10px;border:1px solid #ffffff29;border-radius:8px;background:#ffffff0c;color:#fff}.admin-queue-filters option{color:var(--ink)}.admin-queue-filters button{height:42px}
.admin-shortcuts{margin:14px 0;color:var(--text-muted);font-size:12px}.admin-shortcuts kbd{padding:2px 6px;border:1px solid var(--line);border-bottom-width:2px;border-radius:5px;background:var(--surface);font:700 11px Inter,sans-serif}.moderation-card:focus-within{outline:2px solid var(--focus);outline-offset:3px}
+.moderation-provenance{margin-top:18px;border-top:1px solid var(--border-soft);padding-top:14px}.moderation-provenance summary{cursor:pointer;color:var(--deep);font-weight:700}.moderation-provenance dl{margin-top:14px}.moderation-provenance p{margin:12px 0 0;color:var(--text-muted);font-size:12px;line-height:1.5}
@media(max-width:900px){.admin-queue-filters{grid-template-columns:1fr 1fr}}@media(max-width:520px){.admin-queue-filters{grid-template-columns:1fr}}
.admin-dashboard{width:min(1120px,calc(100% - 64px));margin:0 auto 100px}.admin-dashboard>.privacy{margin:10px 4px 25px}.admin-kpis{display:grid;grid-template-columns:repeat(4,1fr);gap:14px}.admin-kpis>a,.admin-kpis>article,.admin-dashboard-grid>section{padding:22px;border:1px solid var(--line);border-radius:14px;background:var(--surface)}.admin-kpis>a{color:inherit;text-decoration:none}.admin-kpis span,.admin-kpis small{display:block;color:var(--text-muted)}.admin-kpis strong{display:block;margin:10px 0;font:400 42px Georgia,serif;color:var(--deep)}.admin-kpis>a:hover{border-color:var(--focus);transform:translateY(-2px)}.admin-dashboard-grid{display:grid;grid-template-columns:1fr 1fr;gap:18px;margin-top:18px}.admin-dashboard-grid h2{margin:0 0 16px;font:400 25px Georgia,serif}.admin-dashboard-grid ul{list-style:none;margin:0 0 16px;padding:0}.admin-dashboard-grid li{display:flex;justify-content:space-between;gap:14px;padding:10px 0;border-bottom:1px solid var(--border-soft);font-size:13px}.admin-dashboard-grid li span{display:flex;align-items:center;gap:8px}.admin-dashboard-grid time{color:var(--text-muted)}
@media(max-width:900px){.admin-kpis{grid-template-columns:1fr 1fr}}@media(max-width:720px){.admin-dashboard{width:calc(100% - 28px)}.admin-kpis,.admin-dashboard-grid{grid-template-columns:1fr}}
diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md
index e74458e..2bf1dc5 100644
--- a/docs/ROADMAP.md
+++ b/docs/ROADMAP.md
@@ -65,7 +65,7 @@
- [x] **M01 · Усиление административного входа.** Сохранён двойной барьер Caddy Basic Auth + API Bearer; внешние ссылки ограничены `http/https`, UI завершает сессию после 15 минут бездействия, предоставляет явный выход и возвращает вход после `401`. Неуспешная API-авторизация ограничена постоянным счётчиком по HMAC-идентификатору клиента с учётом доверенного proxy; успешный вход очищает ошибки клиента. Bearer-токен не сохраняется в URL, cookie или browser storage.
- [x] **M02 · Единый dashboard.** `/admin` показывает счётчики pending-уловов и staging-наблюдений, число активных источников, их безопасные публичные статусы, последние импорты и быстрые переходы в очереди. Dashboard использует тот же memory-only токен и 15-минутную сессию, не выводит секреты, внутренние URL и полные тексты исключений.
- [x] **M03 · Эффективность очередей.** Очередь внешних наблюдений получила серверные фильтры по источнику и полноте, безопасный поиск по рыбе/водоёму и сортировку по свежести или риску; проблемный порядок поднимает неполные и несопоставленные записи, а параметры работают до пагинации. Обе очереди блокируют всю карточку на время решения, сохраняют введённую причину при ошибке, явно подтверждают успех и переводят фокус к следующей записи. Безопасные горячие клавиши работают только внутри карточки с фокусом и отключены в полях ввода; отклонение и удаление намеренно оставлены только на кнопках.
-- [ ] **M04 · Полный provenance и история решений — в работе.** Admin API отдаёт время первого/последнего обнаружения и проверки, явный список missing fields и allowlist безопасных скалярных полей исходной записи; неизвестные ключи, вложенные структуры и служебные данные не раскрываются. Далее: показать provenance перед публикацией, затем добавить read-only журнал решений и обезличенный экспорт.
+- [ ] **M04 · Полный provenance и история решений — в работе.** Admin API отдаёт время первого/последнего обнаружения и проверки, явный список missing fields и allowlist безопасных скалярных полей исходной записи; неизвестные ключи, вложенные структуры и служебные данные не раскрываются. Карточка показывает эти сведения в раскрываемом блоке перед публикацией и напоминает сверить их с первоисточником. Далее: read-only журнал решений и обезличенный экспорт.
- [ ] **M05 · Защита от параллельных решений.** Ввести version/updated-at precondition для optimistic locking и возвращать понятный `409`, если запись уже изменена другим модератором.
- [ ] **M06 · Персональные роли — после пилота.** Если модераторов станет больше одного, заменить общий токен индивидуальными аккаунтами, короткими сессиями, отзывом доступа и ролями; писать идентификатор оператора в аудит. Для одного владельца альфы не добавлять отдельный auth-сервис заранее.