Skip to content

feat: Nexus が pin する package/health 契約を Edge 側から書き出す - #426

Merged
01rabbit merged 1 commit into
mainfrom
claude/zealous-edison-k5vt5j
Sep 21, 2026
Merged

01rabbit merged 1 commit into
mainfrom
claude/zealous-edison-k5vt5j

Conversation

@01rabbit

Copy link
Copy Markdown
Owner

Azazel-Edge#424 の続き。消費側は Azazel-Nexus#44。

成果物・test・integration PR を両側で分けるという指示に従い、これは Edge 側だけの PR です。Nexus 側は本 PR が commit する契約ファイルを verbatim で取り込み、別 PR で消費します。

なぜ必要か

Nexus は本 package を検証しますが、packager を import しません。2 リポジトリは別々にビルド・テストします。consumer が producer のソースを自身の CI で必要とするなら、それは契約の検証ではなく実装の共有です。

何を出すか

packaging/nexus-core/contract/ に 3 つの JSON を生成し commit します。

file 固定するもの
pin.json package 名 / version / architecture / 2 つの contract 文字列 / artifact・manifest のファイル名 / signed: false / consumer の義務
manifest-schema.json manifest の全 field(sorted dotted path)
health-schema.json health report の全 field、posture check 名、healthy/unhealthy の語、4 条件

digest も timestamp も含みません。 これが再ビルドをまたいで byte 同一でいられる理由です。binary を再コンパイルするたびに変わる契約は、再承認が頻繁すぎて誰も差分を読まなくなります。この 3 ファイルの差分は常に「契約が変わった」を意味します。

導出であって再記述ではない

  • manifest schema は manifest_document から導出します。build() からこの関数を抽出しましたが、生成される manifest は 1 byte も変わりません(抽出前後の出力を diff して確認済み)
  • health schema は binary を実行して導出します。手書きの schema は同じものの 2 つ目の記述であり、両者が食い違った最初の瞬間に壊れるのは「検証したつもりの consumer」の側です

health schema は 2 回の実行から導出します。observe-only 既定と、enforcement を有効にしたもの。unhealthy 分枝は主張ではなく観測します。再生成は次の場合に拒否します。

  • enforcement 有効が unhealthy + 非 0 終了を出さない
  • 2 つの report の shape が異なる
  • ビルド済み binary が tree の version と食い違う

検証

tests/test_nexus_contract_export.py が一時ディレクトリへ再生成し、commit 済みファイルとの byte 同一性を検査します。manifest に field を足して契約に反映し忘れることができません。

mutation 7 件を実施。生存 1 件 — contract_documents から _binary_reports を外しても誰も気づかない(pin は tree の version を書き、health schema は別 binary から導出される。内部的に一貫した、2 つのビルドを同時に記述する契約ができる)。実際のテスト不足だったため、別ビルドの binary を拒否する試験を追加して閉じ、再変異で捕捉を確認しました。

  • python -m pytest tests -q → 925 passed / 4 skipped(基準 896)
  • cargo test → 30 passed

範囲外(触れていない)

installer/、security/、systemd/、実機 HIL、実ネットワーク強制、外部機器変更、公開 release、署名鍵・タグ操作。契約は signed: false を明示し、consumer に「digest 一致は偶発的改変に対する完全性であって真正性ではない」と課します。

🤖 Generated with Claude Code

https://claude.ai/code/session_01SsboPSj6GyJju6mTXwHHjq


Generated by Claude Code

Azazel-Nexus#44 は本 package を検証するが、packager を import しない。
2リポジトリは別々にビルド・テストするため、consumer が producer の
ソースを自身の CI で必要とするなら、それは契約の検証ではなく実装の共有になる。

- packaging/nexus-core/contract/ に pin.json / manifest-schema.json /
  health-schema.json を生成・commit する。digest も timestamp も含まないため
  再ビルドしても byte 同一で、差分は常に契約の変更を意味する
- manifest schema は manifest_document から導出する(再記述しない)。
  build() から manifest_document を抽出したが、生成される manifest は不変
- health schema は binary を 2 回実行して導出する。observe-only 既定と
  enforcement 有効の両方。unhealthy 分枝は主張ではなく観測する
- 再生成は、enforcement が unhealthy + 非 0 終了を出さない場合、2 つの
  report の shape が異なる場合、ビルド済み binary が tree の version と
  食い違う場合に拒否する
- tests/test_nexus_contract_export.py が一時ディレクトリへ再生成して
  commit 済みファイルとの byte 同一性を検査する。manifest に field を
  足して契約に反映し忘れることができない

mutation 7 件で検証。生存 1 件(contract_documents から _binary_reports を
外しても誰も気づかない)は実際のテスト不足だったため、別ビルドの binary を
拒否する試験を追加して閉じた。

tests 896 -> 925 passed / 4 skipped、cargo test 30 passed。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SsboPSj6GyJju6mTXwHHjq
@01rabbit
01rabbit marked this pull request as ready for review September 21, 2026 01:34
@01rabbit
01rabbit merged commit 2a3e42d into main Sep 21, 2026
5 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