Skip to content

refactor!: DDD に組み替え - #16

Merged
yuu61 merged 7 commits into
mainfrom
refactor/ddd-layers
Oct 1, 2026
Merged

yuu61 merged 7 commits into
mainfrom
refactor/ddd-layers

Conversation

@yuu61

@yuu61 yuu61 commented Oct 1, 2026

Copy link
Copy Markdown
Owner

概要

監視の中身を DDD の層(domain ← application ← infrastructure / presentation)に組み替え、旧パッケージ(internal/config・monitor・ping・tui)を削除する。層の依存方向は depguard で検査し、組み立ては cmd/deadman だけが行う。

組み替えの途中で見つかった不具合の修正も含む。多くは main にもともとある不具合で、たとえば次のものがある。

  • nexthop がゲートウェイの古い MAC を使い続ける
  • 端末の切断による SIGHUP で終了せず、監視プロセスが残る
  • 中継コマンドの出力待ちで表全体の更新が止まる
  • ssh が StrictHostKeyChecking=no で接続する

コミット

コミット 中身
build: 検査とリリース生成の手順を整理し、リントを厳格化する Makefile、.golangci.yml(depguard の層の規則を含む)
refactor: プローブの検証規則と監視状態をドメイン層に定義する internal/domain
refactor: 監視とリロードの状態管理をアプリケーション層に集約する internal/application
refactor: 設定の読み込みとログ出力をインフラ層のアダプタとして実装する configfile・logfile・hostinfo
refactor: 検証済みの計画を実行するプローブアダプタを実装する prober、gosnmp の追加
refactor!: TUI と起動処理を新しい監視レイヤーに切り替える presentation・cmd、旧パッケージの削除、README・docs
docs: エージェント向けの作業規約と不変条件を整理する CLAUDE.md を AGENTS.md に置き換え

各コミットで go build・go vet・go test が通る。

破壊的変更

詳細と書き換え方は docs/configuration.md と docs/logging.md の「旧版からの移行」にある。

  • 設定の構文
    • via=・tcp= を廃止し、probe= で方式を指定する。
    • 未知・未使用・重複・空の属性は構築エラーになる。
    • ssh は os= が必須。
  • 構築エラーになる行
    • 空白や制御文字を含む宛先名
    • RouterOS・SNMP の relay に使えない文字を含む行
    • ゾーンの誤用
    • Linux 以外の probe=nexthop
  • ログ
    • ファイル名を target-<識別子>.log に変え、targets.tsv に対応表を追記する。
    • 旧版から移ると、すべての行が新しいファイルに書き始める。
  • 統計
    • 中継や監視元の失敗(t / s / ?)は SNT・FAIL・LOSS に入れない。
  • ssh の中継
    • BatchMode=yes と StrictHostKeyChecking=accept-new で接続する。
    • パスワード認証の中継と、ホスト鍵が変わった中継は s になる。

確認

  • make check(go.mod・整形・lint・vet・-race テスト。lint と vet は linux/386・linux/arm・darwin/arm64・windows/amd64 でも実行)
  • 各コミットでの go build・go vet -tags manual・go test
  • 実際の設定ファイルでの起動・再読み込み・-l のログ名の確認

マージ後に直すもの

fuzz(FuzzCompiledPlansBuild)が見つけ、まだ直していない Compile の検査漏れが 2 件ある。どちらも main には Compile が無いので、退行ではない。

  • ssh・netns・vrf の argv に入る NUL
  • RouterOS の relay の IPv6 ゾーンの文字

https://claude.ai/code/session_01LtF9N9verD44nxHwAbKonM

yuu61 added 7 commits October 1, 2026 15:15
make check で go.mod・整形・リント・vet・テストを検証する。vet と
golangci-lint は開発機に加えて他の OS と 32bit(CROSS_PLATFORMS)でも回し、
manual タグのテストも対象にする。

リリースのアーカイブ生成を make package に集約し、GNU/BSD の日時変換、
UTC での時刻固定、チェックサム生成と失敗時の終了をそろえる。

リンターの無効化は、golangci-lint が非推奨にした旧版と、理由を書いた例外
だけにする。errcheck の check-blank・wrapcheck・forbidigo などを有効にし、
範囲は設定と path 付きの除外で絞る。depguard で層の依存方向
(domain ← application ← infrastructure / presentation)を検査する。

Claude-Session: https://claude.ai/code/session_01LtF9N9verD44nxHwAbKonM
方式・宛先・送信元・既定値を閉じた型で表し、静的な検証と既定値の補完を
probe.Compile に集める。空白や制御文字を含むホスト名、RouterOS・SNMP の
中継先に使えない文字、ゾーンの誤用など、I/O なしで判定できる誤りは構築
エラーにし、構築後に毎ラウンド失敗する行を作らない。

確定した監視経路(方式・宛先・その方式で意味を持つ条件)から行の同一性を
決める。表示名・資格情報・既定値を書いたかどうかでは変わらず、TLS の検証
条件は含める。資格情報がどの綴りでも同一性を変えないことを fuzz で確かめる。

統計と履歴は、観測できた結果だけを数える。中継や監視元の失敗は死活不明と
して統計に加えない。行 ID の採番と、リロードでの引き継ぎを定義する。

Claude-Session: https://claude.ai/code/session_01LtF9N9verD44nxHwAbKonM
設定・プローブ・ホストの能力・ログをポート越しに扱う。統計と履歴を変える
のは Session の Update と ResetStatistics だけにし、プローブとリロードは
Task で走らせて結果をイベントで返す。表示には切り離したスナップショットと
差分(Transition)を渡す。

リロードは新しい世代を作り、古い世代のタイマー・結果・遅れたリロード完了を
捨てる。アダプタの資源は、世代の終了か未適用のリロードの破棄で一度だけ
解放する。終了時は実行中のプローブとタイマーを取り消し、タスクを待つ。

sync は行ごとに順に、async は 1 秒周期で並行に送る。ログの取りこぼしと
書き込みの失敗を数えて知らせる。起動時の警告(ICMP の権限、rp_filter、
nexthop の注意、snmp の非推奨)と構築エラーの行を、閉じた型の診断で表す。

Claude-Session: https://claude.ai/code/session_01LtF9N9verD44nxHwAbKonM
configfile は設定の綴りを型付きの設定に変え、Compile の構築エラーと構文の
問題(閉じていない引用符、属性でない語)を分けて報告する。

logfile は、行の同一性から作る target-<識別子>.log に結果を 1 行ずつ追記し、
どのファイルがどの行のものかを targets.tsv に残す。

- os.OpenRoot で指定したディレクトリの中に操作を限り、ディレクトリの
  差し替えや再作成を検出して開き直す。
- 書き込みは専用のゴルーチンと深い待ち行列で Update から切り離し、
  取りこぼした件数と書き込みの失敗を返す。書き込んだファイルの Close の
  エラーも返す。
- 途中で切れた行を修復し、複数の書き手の追記をロックで排他にする。

hostinfo は監視元のホスト名と、期限付きで解決したアドレスを返す。

Claude-Session: https://claude.ai/code/session_01LtF9N9verD44nxHwAbKonM
各方式(direct・nexthop・tcp・quic・ssh・netns・vrf・routeros・snmp)を
domain の Plan から構築し、結果を probe.Result のコードで返す。対象の無応答
だけを損失にし、中継の失敗(t / s)と監視元の失敗(?)は死活不明にする。
取り消しと、OS ごとに送れる方式を扱う。

- ICMP: direct と nexthop の RAW ソケットの受信にフィルタを付け、自分の
  エコーへの応答だけを読む。
- nexthop(Linux): ゲートウェイの MAC を netlink の近隣表から引き、
  REACHABLE でなければカーネルに再検証させる。ARP/NDP に応答しない
  ゲートウェイは損失に数える。インタフェースの再作成から復旧する。
- 外部コマンド(ssh・netns・vrf・hping3): 出力パイプを握ったまま残る
  子プロセスで監視が止まらないよう待ち時間に上限を置き、終了時に子プロセスを
  終わらせる。ssh は BatchMode=yes と StrictHostKeyChecking=accept-new で
  動かし、引数を中継先のシェル向けに引用する。中継先の ping には OS ごとの
  応答待ちとフラグを使う。
- routeros: API に届かない・拒否された・ping の結果以外を返したときは中継の
  失敗にし、アイドル接続に上限時間を置く。
- snmp: gosnmp で RFC 4560 の行の作成・結果の取得・削除を行う。テスト名を
  監視元と行の ID から決め、消し損ねた行を次のプローブが消せるようにする。

syscall とサードパーティのエラーに操作名を付けて包む。Compile が通した
Plan からアダプタを構築できることを fuzz で確かめる。

Claude-Session: https://claude.ai/code/session_01LtF9N9verD44nxHwAbKonM
TUI は Session の差分とスナップショットから描画し、表示設定・結果バー・
診断・レイアウトを責務ごとに分ける。cmd/deadman が各ポートに実装をつなぎ、
従来の config・monitor・ping・tui パッケージを削除する。palette は
presentation に、termfont は infrastructure に移す。

- 構築エラーの行は RESULT 欄に X と理由を出し、監視・履歴・ログに加えない。
  画面上部では件数の 1 行にまとめ、警告は監視行を押し出さない高さに抑える。
- 監視元の失敗で観測できなかったプローブを RESULT バーに ? で表示する。
- ログの取りこぼしと書き込みの失敗を画面上部に出し、書き込みの失敗は
  終了コードにも反映する。
- 端末の切断による SIGHUP では再読み込みせずに終了する。SIGHUP が届かない
  場合に備えて 1 秒ごとにも端末を確かめ、監視プロセスを残さない。

README と docs を目的別(設定・画面・動作環境・ログ)に作り直し、設定例を
新しい構文に合わせる。

BREAKING CHANGE: 旧 via・tcp 属性と、relay・nexthop による方式の暗黙の
選択を廃止し、probe= で方式を指定する。未知・未使用・重複・空の属性や
不正な値は構築エラーになる。ssh は os= が必須で、ssh・netns・vrf の宛先が
ホスト名なら resolve_family か送信元アドレスが要る。表示ディレクティブは
書式が正しい最後の行を採用し、使えない値は既定値に戻す。書き換えの対応表は
docs/configuration.md にある。

BREAKING CHANGE: 次の行は構築エラーになる。空白や制御文字を含む宛先名と
ssh の relay、英数字・-・_・. 以外を含む RouterOS・SNMP の relay のホスト名、
ホストの無い relay=:PORT、角括弧で囲まないゾーン付きの relay=ADDR%ZONE:PORT、
nexthop の宛先のゾーン、ゾーン付き IPv4-mapped の送信元、Linux 以外の
probe=nexthop。SNMP の relay はホスト名か IP アドレスに限り、UDP 161 に送る。

BREAKING CHANGE: ログのファイル名を、表示名でなく行の同一性から作る
target-<識別子>.log にし、どのファイルがどの行のものかを targets.tsv に
追記する。旧版から移ると、すべての行が新しいファイルに書き始める。表示名と
資格情報の変更では同じファイルのまま、監視経路の条件(QUIC・RouterOS の
verify を含む)を変えると新しいファイルになる。ディレクトリ内のファイルを
すべてログとみなすスクリプトは target-*.log に絞る必要がある。

BREAKING CHANGE: 統計は対象を観測できたプローブだけを数える。中継や監視元の
失敗(t / s / ?)は SNT・FAIL・LOSS に入れず、AVG は応答したプローブの平均に
なる。RouterOS の中継の失敗は X でなく t / s になり、ARP/NDP に応答しない
ゲートウェイへの nexthop は損失になる。

BREAKING CHANGE: ssh の中継は BatchMode=yes と StrictHostKeyChecking=accept-new
で接続する。パスワード認証、ssh-agent に載せていないパスフレーズ付きの鍵、
登録済みのホスト鍵が変わった中継は s になる。FreeBSD の中継先は IPv6 に
ping -6 を使うため 13 以降が要る。

Claude-Session: https://claude.ai/code/session_01LtF9N9verD44nxHwAbKonM
CLAUDE.md を AGENTS.md に置き換え、コードやリンターからは見えない約束だけを
書く。層の依存方向、監視状態の持ち主、世代と資源の解放、失敗を値で返すこと、
Compile での確定、行の同一性、閉じた型を不変条件として明記する。

作業規約として、コミット前の make check、リントの指摘を抑止せず構造で直す
こと、エラーを捨てないこと、OS 別の対のファイルを両方直すこと、利用者との
契約を変えるときの文書化と BREAKING CHANGE、日本語の Conventional Commits を
定める。

Claude-Session: https://claude.ai/code/session_01LtF9N9verD44nxHwAbKonM
@yuu61
yuu61 merged commit 5537471 into main Oct 1, 2026
2 of 3 checks passed
@yuu61
yuu61 deleted the refactor/ddd-layers branch October 1, 2026 06:21
@yuu61 yuu61 changed the title refactor!: 監視を DDD の層に組み替え、レビューで見つかった不具合を直す refactor!: DDD に組み替え Oct 1, 2026
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.

1 participant