IBKR Phase 6 MVP deploy postmortem¶
作成日: 2026-04-13 対象ソース:
AEGIS/WORK_LOG/2026-04-12_ibkr_implementation_handover.md,AEGIS/WORK_LOG/2026-04-12_ibkr_scaffold_phases_1a_3_4_5.md,AEGIS/WORK_LOG/2026-04-12_ibkr_synology_pivot.md,AEGIS/WORK_LOG/2026-04-12_ibkr_phase3b_phase6_mvp.md
Source fidelity note¶
この postmortem は、2026-04-12 の ibkr_*.md ログだけを根拠に書いている。
R4 queue で指定された issue 名のうち、元ログに failing command / error string
まで残っていないものは、そのことを明記したうえで、ログに残っている
「採用した対処」と「再発防止の学び」だけを書く。
Executive summary¶
2026-04-12 の IBKR Phase 6 MVP は、当初の Mac local dry-run → Fargate 前提から、
既存 Saxo 運用と同じ Synology + GitHub Actions の deploy lane に切り替わった。
その後、Phase 3 Part B の smoke binary と、Phase 6 MVP の
lt-ibkr-quote-collector まで進み、MVP は underlying snapshot 収集に
スコープを絞って production 回収点を先に作った。
Phase 6.1 addendum¶
2026-04-13 の Phase 6.1 では、MVP の underlying collector を土台にして
lt-ibkr-spread-collector を追加し、ibkr_spread_quote_v2 JSONL を
Synology 上へ継続書き込みできる状態まで進めた。構成は 1 container 追加ではなく、
IBeam gateway / underlying quote collector / spread collector の 3-container
分離とし、認証寿命・scan cadence・障害切り分けを独立に扱う方針を採っている。
特に option chain 解決は、当初想定していた「month token を渡して
secdef/info 一発で全 chain を取る」単純経路では live IBeam で安定しなかった。
実運用で採用した sequence は以下:
POST /v1/api/iserver/secdef/searchで underlyingconidとmonthsを取得GET /v1/api/iserver/secdef/strikesで対象 month の strike ladder を取得- Rust
select_atm_put_spread相当で short/long strike を決定 GET /v1/api/iserver/secdef/info?strike=...&right=Pを short / long それぞれに発行- 各 leg
conidで snapshot / whatIf を取得し、net bid/ask/mid と margin preview を組み立てる
このため、Phase 6.1 の collector hardening では search -> strikes -> info
の live 実績 path を守りつつ、month-wide secdef/info は telemetry 用の
best-effort retry に留めている。今後 secdef/info 一括解決が安定するまでは、
option chain API sequence の実態は「search → strikes → info」が正である。
Production issues encountered¶
| Issue | Logs preserve | Resolution preserved in the logs | Lesson learned |
|---|---|---|---|
| IP allowlist | 元ログには allowlist 自体の失敗出力は残っていない。一方で、2026-04-12_ibkr_synology_pivot.md には、実運用標準が Mac/Fargate ではなく Tailscale + SSH key で Synology に入り、GitHub Actions から /volume1/aegis/repo を同期して deploy する方式だと明記されている。 |
deploy 経路を既存運用に寄せ、pt-docker/.env の必須変数検証、manual dispatch、verify job での auth_status / /iserver/accounts 確認までを workflow に固定した。 |
新規 broker lane を載せるときは、新しい実行面を増やす前に既存の deploy lane に合わせる方が切り分けが速い。 |
| btrfs ACL chmod | 2026-04-12 の ibkr_*.md には btrfs / ACL / chmod の失敗出力は残っていない。残っている事実は、secret は git 管理外の pt-docker/.env に置き、Synology 上で user が one-time bootstrap し、workflow 側は --env-file と fail-fast の env 検証で読む、という運用面の確定だけ。 |
permission 修復のような in-place 操作ではなく、pt-docker/.env の one-time bootstrap と workflow の fail-fast 検証に寄せた。共有 compose には手を入れず、IBKR gateway を別 compose / 別 workflow として切り出した。 |
ファイルシステム差異や権限の不確実性があるときは、mutable な現地修復より、secret bootstrap を最小化した immutable deploy に寄せる方が安全。 |
| reqwest HTTP/2 403 | 元ログに 403 の文言は残っていないが、2026-04-12_ibkr_phase3b_phase6_mvp.md には Mac の SSH tunnel 経由で TLS handshake が Connection reset by peer で失敗したこと、2026-04-12_ibkr_implementation_handover.md と scaffold log には IBeam が self-signed 証明書を出すので Rust reqwest client で .danger_accept_invalid_certs(true) が必要だと残っている。 |
adapter 側のバグと決めつけず、ssh nas "curl" で 3 endpoint の実レスポンス shape を直接観測し、Rust 側は self-signed 前提で TLS verify off を explicit に扱うようにした。live 実行は fragile な Mac tunnel ではなく production container 側へ寄せた。 |
self-signed gateway を跨ぐときは、先に transport/TLS を疑い、remote curl で shape を固定してから client 実装に戻る方が早い。 |
Debugging vs implementing¶
正確な工数比率は、2026-04-12 の ibkr_*.md には記録されていないため算出しない。
実装として明示的に残っている単位:
- Phase 1a / 3 / 4 / 5 scaffold
- Synology pivot に伴う compose / workflow / config / README 更新
lt-ibkr-smokebinary 追加lt-ibkr-quote-collectorMVP 追加
デバッグ / 切り分けとして明示的に残っている単位:
- Paper Trading Password reset の backend error と再試行待ち
- UI session と API session の排他性の誤解整理
- Mac / Fargate 前提から Synology + GHA への deploy lane 見直し
- SSH tunnel 経由の TLS handshake failure と
ssh nas "curl"による shape 確認
したがって、このセッションは「実装を進めながら、deploy lane と transport の 前提を何度も切り分け直した」性格が強く、体感の debug 量は小さくなかったと 言えるが、何時間対何時間かまではログから断定しない。
What worked¶
- Phase 6 full scope を一気に載せず、underlying snapshot の JSONL 収集へ MVP を絞ったことで、production 投入前の回収点を近づけられた。
- 既存 gateway compose を変更せず、
host.docker.internal:host-gatewayを 使って quote collector から loopback bind の gateway へ到達させたため、 稼働中 gateway の再作成を避けられた。 - smoke / collector とも、実 API shape を見てから regression test を追加する 流れにできている。
Follow-ups carried forward¶
- option chain / spread / whatIf は Phase 6.1 へ分離したまま。Phase 6 MVP は underlying quote collector に限定されている。
- Paper password reset backend error は、次セッション開始時に再確認が必要。
- IBKR shadow 観測の次段は、5 営業日 parity 観測と
analyze_saxo_ibkr_parity.pyによる集計。