Skip to content

fix(support): проверить parent CF и live round-trip для #76 - #459

Merged
zeegin merged 4 commits into
IngvarConsulting:mainfrom
korolevpavel:fix/issue-76-live-round-trip
Aug 12, 2026
Merged

fix(support): проверить parent CF и live round-trip для #76#459
zeegin merged 4 commits into
IngvarConsulting:mainfrom
korolevpavel:fix/issue-76-live-round-trip

Conversation

@korolevpavel

@korolevpavel korolevpavel commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Что меняется

Refs #76.

PR снимает только blocker воспроизведения на живой ИБ, описанный Игорем в комментарии #5255993808, и добавляет fail-closed защиту реального support-профиля CPM:

  • unica.support.edit перед изменением ParentConfigurations.bin проверяет exact parent .cf для каждой записи поставщика: post-image capability-операции переводит все vendor-rule slots в locked, где платформа требует matching Ext/ParentConfigurations/<Vendor>.cf;
  • missing, non-regular, linked или нечитаемый vendor payload одинаково блокирует preview и apply до записи файлов, persisted cache state и событий; support_guard не может обойти этот prerequisite;
  • apply повторяет preflight внутри транзакции и связывает exact preimages vendor .cf, membership каталога и ParentConfigurations.bin; при ошибке .bin остаётся byte-for-byte неизменным;
  • добавлен opt-in developer verifier: он копирует файловую ИБ, Designer-исходники и явно переданный parent CF в приватный workspace, запускает проверенную приватную копию packaged Unica и формирует санитизированный JSON evidence;
  • marker-free fullRebuild синхронизирует support state с одноразовой ИБ, после чего random metadata/BSL markers загружаются обычным build без fullRebuild; exact source preimages восстанавливаются до explicit full dump;
  • acceptance отдельно проверяет non-mutating fail-closed partial guard и возврат непредсказуемых markers только из ИБ через private staging publication.

Последующий комментарий #5258600630 корректно возвращает #76 в открытую работу. Этот PR использует Refs #76, не закрывает issue и не считает оставшуюся работу not planned.

Независимое ревью

После отдельного findings-first ревью исправлены найденные регрессии и закреплены RED→GREEN тестами:

  • preflight теперь рассматривает все vendor entries итогового post-image, включая уже locked и multi-vendor случаи;
  • preview/apply parity покрывает missing и unreadable parent CF;
  • восстановление source preimages отказывает при symlink/reparse ancestor и повторно проверяет границу перед replace;
  • packaged manifest криптографически связан с реально запущенной приватной копией Unica;
  • child environment построен по allowlist, secrets не наследуются и не сериализуются, а TMPDIR/TMP/TEMP, cache и IBCMD --data находятся внутри evidence;
  • terminal errors, integrity/cleanup failures и redaction дают непротиворечивый отчёт и не повреждают typed schema.

Итог независимого re-review: блокирующих, major и minor findings не осталось.

Архитектурный слой

  • Публичные имя, аргументы и typed payload unica.support.edit не изменены.
  • Успешная мутация сохраняет существующий ConfigXmlChanged; отказ не публикует cache events.
  • Verifier остаётся dev-only утилитой в scripts/dev/ и не входит в MCP surface или runtime package.
  • Новая ADR/design record не требуется: публичный контракт, формат XML, владение cache/state и границы слоёв не меняются.
  • Соблюдены REQ-SAFETY-PREVIEW-BY-DEFAULT, REQ-SAFETY-NO-PARTIAL-WRITE, INV-SOURCE-BOUND-PREIMAGES и INV-SOURCE-WRITE-CONTAINMENT.
  • Пройден change checklist в относящейся к PR части.

Live evidence

Повторный прогон выполнен уже после независимого ревью и hardening environment на одноразовых копиях CPM_3_3_3_Demo и CPM_3_3_3_xml/src:

  • host: macOS arm64 / POSIX (aarch64-apple-darwin); Windows live round-trip этим evidence не подтверждён;
  • платформа 8.3.27.2214, builder IBCMD, приватные --data и temp roots;
  • packaged Unica 0.12.0, SHA-256 cc80809e0e2b7da874b9f948f8eebbe1f911f5f1baae059f48d8d64a2fd49528, совпадает с generated manifest;
  • exact parent payload УправлениеХолдингом 3.3.3.27, SHA-256 159770a19708e186d49172f96632d7a84d20ec77daa13eba359e6ab0850bbddb;
  • 16 steps, support-sync full build и ordinary mutation build: pass;
  • applied partial dump: заблокирован, source hash до/после одинаков;
  • metadata и BSL markers отсутствовали после восстановления preimages и вернулись из ИБ после full dump; оба post-dump hash совпали с post-mutation hash;
  • исходные ИБ, source tree, parent CF, Unica binary и package manifest не изменились (privateCopiesOnly: true);
  • report: status=pass, exitCode=0; temporary evidence удалён (cleanupSucceeded: true).

Проверка

cargo fmt --all -- --check
cargo clippy --workspace --all-targets --all-features -- -D warnings
cargo test -p unica-coder --lib -- --test-threads=1
cargo test -p unica-coder support_ -- --test-threads=1
UV_CACHE_DIR=/private/tmp/unica-issue76-uv-cache \
  uv run --offline --with lxml==6.1.1 --with PyYAML==6.0.3 \
  python -m unittest discover -s tests/dev
python3 -B -m unittest tests.dev.test_verify_issue_76_roundtrip
python3 scripts/ci/check-architecture-sync.py --base upstream/main
python3 scripts/ci/check-rust-platform-boundary.py
python3 -B -m unittest tests.ci.test_architecture_registry tests.ci.test_design_documents
git diff --check

Результат: Rust lib 2748 passed, 2 ignored; support-related 57 passed; tests/dev222 passed; issue-specific — 38 passed; architecture/design — 49 passed; clippy, format, package verification и guardrails — pass.

Что PR намеренно не решает

Это не Closes #76.

Поставляемая Unica всё ещё закрепляет v8-runner 0.5.1 на 7ce1b062843d86644fe55741dbe0ee79f7ca767d. Upstream issue alkoleft/v8-runner-rust#30 закрыта, но реализационный PR #39 остаётся открытым и конфликтующим. В закреплённом runner по-прежнему нет:

  • exact requested / processed / skipped / conflicted receipts и post-hashes;
  • приватного per-IB hash/CDFI state;
  • divergence-safe shadow/staging merge для applied partial/incremental dump.

Поэтому applied partial/incremental dump остаётся fail-closed, а #76 — открытой активной работой с blocker зависимого runner. Этот PR подтверждает безопасный full round-trip на живой ИБ и делает его воспроизводимым.

Summary by CodeRabbit

  • Bug Fixes

    • Support capability changes now validate required vendor configuration payloads before preview or apply.
    • Invalid, missing, unreadable, or unsafe payloads are blocked without modifying configurations or cached state.
    • Validation results are consistent across dry-run and apply modes.
  • Verification

    • Added comprehensive round-trip checks for support transitions, rebuilds, dumps, restoration, integrity, cleanup, and error handling.
    • Added safeguards for protected paths, symlinks, credentials, and partial dumps.

@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 4efc31fa-337d-40ab-b4b6-1c16c45f4667

📥 Commits

Reviewing files that changed from the base of the PR and between fb918ef and d829156.

📒 Files selected for processing (2)
  • scripts/dev/verify-issue-76-roundtrip.py
  • tests/dev/test_verify_issue_76_roundtrip.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • tests/dev/test_verify_issue_76_roundtrip.py
  • scripts/dev/verify-issue-76-roundtrip.py

📝 Walkthrough

Walkthrough

The PR adds vendor .cf payload preflight checks for support capability edits. It also adds an isolated issue #76 round-trip verifier with MCP execution, workspace integrity checks, redacted reports, and comprehensive tests.

Changes

Support capability preflight

Layer / File(s) Summary
Vendor payload validation and transactional reuse
crates/unica-coder/src/infrastructure/native_operations/support.rs
Capability edits validate vendor records and .cf payloads before mutation. Validated payload preimages are reused during transactional writes.
Guard integration and application coverage
crates/unica-coder/src/infrastructure/support_guard.rs, crates/unica-coder/src/application/mod.rs
The support guard blocks failed capability preflights without changing files or cache state. Tests cover valid, missing, unreadable, and case-insensitive payloads.

Issue #76 round-trip verifier

Layer / File(s) Summary
Verifier inputs and isolated workspace
scripts/dev/verify-issue-76-roundtrip.py
The verifier validates inputs, creates private workspace copies, isolates IBCMD execution, and records integrity data.
Round-trip execution and MCP session
scripts/dev/verify-issue-76-roundtrip.py
The verifier runs support edits, mutations, builds, dumps, preimage restoration, and marker checks through an isolated MCP session.
Reporting, provenance, and CLI orchestration
scripts/dev/verify-issue-76-roundtrip.py
The verifier writes sanitized reports, checks packaged-tool provenance, handles failures and cleanup, and exposes a CLI entry point.
Round-trip verifier test coverage
tests/dev/test_verify_issue_76_roundtrip.py
Tests cover isolation, integrity, redaction, support transitions, mutation sequencing, partial-dump guards, provenance, cleanup, and CLI validation.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant ExecuteGate
  participant McpSession
  participant PrivateWorkspace
  participant ReportWriter
  ExecuteGate->>PrivateWorkspace: Create isolated inputs and runtime data
  ExecuteGate->>McpSession: Run support, mutation, build, and dump steps
  McpSession-->>ExecuteGate: Return tool results and integrity evidence
  ExecuteGate->>PrivateWorkspace: Restore source preimages and verify markers
  ExecuteGate->>ReportWriter: Persist sanitized verification report
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 2 | ❌ 3

❌ Failed checks (3 warnings)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The PR adds verification, but it does not implement issue #76's dirty-target contract, build loading, dump conflict handling, or restart persistence. Implement the mutation-to-runtime dirty contract, hash tracking, build and partial-dump safeguards, result receipts, and persistent workspace state for issue #76.
Out of Scope Changes check ⚠️ Warning The support-edit parent CF preflight changes are unrelated to issue #76's workspace dirty-state and source-to-IB round-trip requirements. Move the parent CF preflight changes to a separate PR or link an issue that defines those support-edit requirements.
Docstring Coverage ⚠️ Warning Docstring coverage is 6.85% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies both main changes: parent CF validation and the live round-trip verifier for issue #76.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@korolevpavel
korolevpavel marked this pull request as ready for review August 11, 2026 23:38

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
tests/dev/test_verify_issue_76_roundtrip.py (1)

683-688: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Bind the integrity-probe failure to the probe, not to a call count.

flaky_digest fails on the third _stat_tree_digest call. The verifier calls _stat_tree_digest twice during setup and twice inside inspect_input_integrity. The test therefore depends on the exact number of setup calls. If a later change adds or removes one _stat_tree_digest call before the probe, the injected failure moves to a different call site. The test can then fail for an unrelated reason, or pass without exercising the probe path.

Trigger the failure from the probe path instead. One option is to fail on the path that the probe inspects after the session was created, or to set a flag when the session factory runs and fail only after that flag is set.

♻️ Proposed refactor to decouple the test from the call count
             original_digest = verifier._stat_tree_digest
-            calls = 0
+            session_started = False
 
             def flaky_digest(path):
-                nonlocal calls
-                calls += 1
-                if calls >= 3:
+                if session_started:
                     raise RuntimeError("synthetic integrity probe failure")
                 return original_digest(path)
 
             class StartFailingSession(ScriptedSession):
                 def start(self, _required_tools) -> None:
+                    nonlocal session_started
+                    session_started = True
                     raise verifier.SourceError("synthetic MCP start failure")
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/dev/test_verify_issue_76_roundtrip.py` around lines 683 - 688, Update
flaky_digest in the roundtrip test to trigger the synthetic failure based on the
integrity-probe context rather than the calls counter. Bind the failure to the
specific post-session probe path, or set a flag when the session factory runs
and fail only afterward, while preserving normal digest behavior before the
probe.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@scripts/dev/verify-issue-76-roundtrip.py`:
- Around line 2537-2540: Update the successful cleanup branch in the report
finalization flow to recompute containsProprietaryParentConfiguration after
temporary.cleanup() succeeds, matching the failure branch’s treatment. Set it
based on the post-cleanup filesystem state so the written report no longer
claims proprietary payload remains; preserve the existing retained and
cleanupSucceeded updates.

In `@tests/dev/test_verify_issue_76_roundtrip.py`:
- Around line 1004-1005: In the locked object-rule receipt test, remove the
duplicated unica.meta.edit assertion and add an assertion that
unica.runtime.execute is absent from client.calls, preserving the existing
checks that mutation tools are not reached.

---

Nitpick comments:
In `@tests/dev/test_verify_issue_76_roundtrip.py`:
- Around line 683-688: Update flaky_digest in the roundtrip test to trigger the
synthetic failure based on the integrity-probe context rather than the calls
counter. Bind the failure to the specific post-session probe path, or set a flag
when the session factory runs and fail only afterward, while preserving normal
digest behavior before the probe.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 5b1092ae-a27b-4c93-a71b-f11c981a4568

📥 Commits

Reviewing files that changed from the base of the PR and between f7dd99b and fb918ef.

📒 Files selected for processing (5)
  • crates/unica-coder/src/application/mod.rs
  • crates/unica-coder/src/infrastructure/native_operations/support.rs
  • crates/unica-coder/src/infrastructure/support_guard.rs
  • scripts/dev/verify-issue-76-roundtrip.py
  • tests/dev/test_verify_issue_76_roundtrip.py

Comment thread scripts/dev/verify-issue-76-roundtrip.py
Comment thread tests/dev/test_verify_issue_76_roundtrip.py Outdated
@korolevpavel

Copy link
Copy Markdown
Contributor Author

Проверка новых замечаний спустя 60 минут завершена. Три замечания CodeRabbit проверены и исправлены в d829156: устранён stale proprietary-payload receipt после успешного cleanup, fail-closed тест теперь доказывает отсутствие meta/code/runtime вызовов, а injection ошибки integrity probe привязан к фазе session start вместо числа digest-вызовов. RED для cleanup воспроизведён до исправления; после исправлений зелёные 38/38 issue-specific и 222/222 tests/dev, py_compile и diff-check. Новых комментариев Игоря/zeegin за контрольный интервал нет.

@zeegin zeegin added this to the v0.12 milestone Aug 12, 2026

@zeegin zeegin left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Проверил head d829156 против актуального main a3a3c5c: блокирующих замечаний к PR нет. Локально на merge-result прошли cargo fmt, строгий Clippy, полный Rust workspace и 222/222 tests/dev; публичный контракт и архитектурный sync не изменены, все review threads закрыты. Единственное падение полного Python CI воспроизводится на чистом текущем main в design-документах из #328 и этим PR не внесено.

@zeegin
zeegin merged commit 237fbec into IngvarConsulting:main Aug 12, 2026
17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants