Skip to content

feat(ibkr): Client Portal API v1 read-path wire layer + paper gateway harness#127

Merged
NotAProfDev merged 14 commits into
mainfrom
feat/ibkr-cpapi-readpath-wire
Jul 10, 2026
Merged

feat(ibkr): Client Portal API v1 read-path wire layer + paper gateway harness#127
NotAProfDev merged 14 commits into
mainfrom
feat/ibkr-cpapi-readpath-wire

Conversation

@NotAProfDev

@NotAProfDev NotAProfDev commented Jul 10, 2026

Copy link
Copy Markdown
Owner

Summary

First slice of the IBKR venue adapter: a transport-agnostic Client Portal API v1 (CPAPI) read-path wire layer plus a hand-rolled paper gateway harness. Venue-side half of the ADR-0003 anti-corruption boundary; no OATH-domain translation yet (deferred until InstrumentId/Order land).

Closes #126.

What's here (12 commits)

  • New oath-adapter-ibkr crate: a cpapi module with read-path DTOs (AuthStatus, TickleResponse, IServerAccounts, PortfolioAccount, Position, SecdefSearchEntry, SecdefInfo), an Endpoint/Method descriptor, a CpapiError envelope, and a decode<T> entry point. Depends only on serde/serde_json/thiserror.
  • Faithful-mirror modeling (spec §7.4): numbers-sent-as-strings stay String; ids/counts are i64; money/quantity are serde_json::Number (no premature f64); and the deliberate conid split — String on secdef/search, i64 on positions/secdef/info — modeled as each endpoint actually sends it.
  • Hand-rolled Client Portal Gateway container (docker/cpapi/) + a just ibkr-capture recipe.
  • A gated #[ignore] live integration test (stays out of CI even under --all-features).
  • README crate row + dependency-graph node + CHANGELOG [Unreleased] entry.

Not in this PR (deferred)

  • Real paper-account fixtures. The committed crates/adapter/ibkr/tests/fixtures/cpapi/*.json are representative (documented shapes). Real sanitized captures via the gateway harness are a pre-merge follow-up — see docker/cpapi/README.md.
  • Order/write path, WebSocket streaming, OATH-domain translation, and the webapi (beta OAuth 2.0) / tws (socket) sibling surfaces.

Verification

just ci is green — fmt, fmt-toml, typos, lint (-D warnings), check, test (239 tests, live test ignored), deny, doc, machete, gitleaks, actionlint, shellcheck.

Process

Built test-first from the spec → plan. Each task passed a spec + quality review; the whole branch passed a final review with fixes applied (notably secdef_info now carries its required conid/secType query params per spec §3.1).

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Added a new IBKR Client Portal API v1 venue adapter covering auth status, keepalive/tickle, accounts, portfolios, paginated positions, and secdef search/info.
    • Introduced transport-agnostic wire models plus a shared JSON decode entry point for CP API responses.
  • Documentation
    • Updated README and changelog to reflect IBKR adapter availability and detailed CP API fixture capture setup.
  • Tests
    • Added fixture-based decoding tests, endpoint path rendering tests, and an optional ignored live gateway test.
  • Chores
    • Expanded shell script linting and added IBKR terminology to spelling checks.

- secdef_info(conid, sec_type) now carries required query params
- Endpoint doc clarifies method+path/query only, bodies deferred
- tests/endpoint.rs asserts all seven endpoint constructors
- fix sso_expires unit doc (milliseconds, not seconds)
- harden live.rs curl (-fksS) + document IBKR_GATEWAY override
- Dockerfile: drop unused curl, document unpinned-download tradeoff
- soften "lossless" wording in cpapi/mod.rs to faithful-subset framing
- docker-compose.yml: restart: "no" for the auth-session harness
- capture.sh: note it must run from the repo root
@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: ca05a748-560d-413c-8357-e0c905b05a47

📥 Commits

Reviewing files that changed from the base of the PR and between bc25336 and 57abdfb.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock, !**/*.lock
📒 Files selected for processing (5)
  • CHANGELOG.md
  • crates/adapter/ibkr/tests/live.rs
  • docker/cpapi/Dockerfile
  • docker/cpapi/capture.sh
  • docs/superpowers/plans/2026-07-10-ibkr-cpapi-readpath-wire.md
✅ Files skipped from review due to trivial changes (2)
  • CHANGELOG.md
  • docs/superpowers/plans/2026-07-10-ibkr-cpapi-readpath-wire.md
🚧 Files skipped from review as they are similar to previous changes (2)
  • crates/adapter/ibkr/tests/live.rs
  • docker/cpapi/Dockerfile

📝 Walkthrough

Walkthrough

Adds the oath-adapter-ibkr crate with CPAPI v1 read-path DTOs, endpoint descriptors, JSON decoding, fixture tests, a Docker gateway harness, fixture capture tooling, and an ignored live integration test.

Changes

IBKR CPAPI adapter

Layer / File(s) Summary
Workspace and adapter contract
Cargo.toml, crates/adapter/ibkr/**, README.md, CHANGELOG.md, docs/superpowers/**, _typos.toml
Registers the new workspace crate, exposes the cpapi module, documents its wire-layer scope, and records the design and implementation plan.
Endpoint descriptors and JSON decoding
crates/adapter/ibkr/src/cpapi/endpoint.rs, crates/adapter/ibkr/src/cpapi/error.rs, crates/adapter/ibkr/tests/endpoint.rs, crates/adapter/ibkr/tests/error.rs
Defines CPAPI methods and paths, error envelopes, generic JSON decoding, and tests for parameterized endpoint paths and decode outcomes.
Auth, portfolio, and security-definition DTOs
crates/adapter/ibkr/src/cpapi/{auth,portfolio,secdef}.rs, crates/adapter/ibkr/tests/{auth,portfolio,secdef}.rs, crates/adapter/ibkr/tests/fixtures/cpapi/*
Adds serde models for session, account, position, and security-definition responses with representative JSON fixtures and deserialization assertions.
Gateway capture and live validation
docker/cpapi/*, Justfile, crates/adapter/ibkr/tests/live.rs
Adds the Client Portal Gateway Docker setup, capture script and recipe, fixture sanitization instructions, shell lint coverage, and an ignored live auth-status test.

Estimated code review effort: 3 (Moderate) | ~30 minutes

Possibly related PRs

  • NotAProfDev/oath#40: Modifies the same workspace member and dependency declaration surface in Cargo.toml.

Suggested labels: enhancement

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title follows Conventional Commits and accurately summarizes the new IBKR CPAPI wire layer and gateway harness.
Linked Issues check ✅ Passed The PR covers the read-path DTOs, endpoint/error/decode APIs, Docker capture harness, and ignored live test, while deferring translated or write-path work.
Out of Scope Changes check ✅ Passed No clearly unrelated code changes are evident; the docs, tests, fixtures, and harness all support the IBKR CPAPI wire-layer scope.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/ibkr-cpapi-readpath-wire

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.

@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 (2)
docker/cpapi/capture.sh (1)

14-18: 🔒 Security & Privacy | 🔵 Trivial | 💤 Low value

-k (insecure TLS) is intentional but worth documenting inline.

The IBKR Client Portal Gateway ships with a self-signed certificate, so -k is necessary for local dev. The static analysis flags this as CWE-295, which is correct in general but not actionable here. Consider adding a brief inline comment noting why -k is used (self-signed gateway cert) so future readers don't "fix" it by removing the flag. If the gateway ever supports a custom CA, switching to --cacert would be preferable.

🤖 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 `@docker/cpapi/capture.sh` around lines 14 - 18, Document the intentional
insecure TLS behavior in the fetch function: add a brief inline comment next to
curl’s -k flag explaining that the local IBKR Client Portal Gateway uses a
self-signed certificate, while retaining -k for now and noting that a custom CA
should use --cacert if supported later.

Source: Linters/SAST tools

docs/superpowers/plans/2026-07-10-ibkr-cpapi-readpath-wire.md (1)

283-288: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Plan's secdef_info() signature is stale vs. the implementation.

The plan shows secdef_info() with no parameters, but the actual implementation in endpoint.rs takes conid: i64, sec_type: &str and renders them as query params. The PR objectives confirm this was a deliberate final adjustment ("required secdef_info query parameters"). Consider updating the plan's Task 2 Step 3 code block and the test in Step 1 to match the shipped implementation.

🤖 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 `@docs/superpowers/plans/2026-07-10-ibkr-cpapi-readpath-wire.md` around lines
283 - 288, Update the plan’s Task 2 Step 3 `secdef_info` example and the Step 1
test to match the implemented `secdef_info(conid: i64, sec_type: &str)`
signature, including both required query parameters and their expected rendered
values.
🤖 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 `@crates/adapter/ibkr/tests/live.rs`:
- Around line 20-23: Add a curl timeout to the Command invocation in the live
test by including the --max-time argument with a suitable limit such as 30
seconds in the arguments passed to curl, ensuring the request fails instead of
hanging indefinitely.

In `@docker/cpapi/Dockerfile`:
- Around line 1-19: Add a dedicated unprivileged user and group in the
Dockerfile, change ownership of /opt/clientportal and the gateway files to that
account, then add a USER instruction before CMD so bin/run.sh runs without root
privileges while retaining port 5000.

---

Nitpick comments:
In `@docker/cpapi/capture.sh`:
- Around line 14-18: Document the intentional insecure TLS behavior in the fetch
function: add a brief inline comment next to curl’s -k flag explaining that the
local IBKR Client Portal Gateway uses a self-signed certificate, while retaining
-k for now and noting that a custom CA should use --cacert if supported later.

In `@docs/superpowers/plans/2026-07-10-ibkr-cpapi-readpath-wire.md`:
- Around line 283-288: Update the plan’s Task 2 Step 3 `secdef_info` example and
the Step 1 test to match the implemented `secdef_info(conid: i64, sec_type:
&str)` signature, including both required query parameters and their expected
rendered values.
🪄 Autofix (Beta)

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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: db0f1ca2-2365-4258-93e8-9afc92d925e3

📥 Commits

Reviewing files that changed from the base of the PR and between 35d5a04 and bc25336.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock, !**/*.lock
📒 Files selected for processing (32)
  • CHANGELOG.md
  • Cargo.toml
  • Justfile
  • README.md
  • _typos.toml
  • crates/adapter/ibkr/Cargo.toml
  • crates/adapter/ibkr/src/cpapi/auth.rs
  • crates/adapter/ibkr/src/cpapi/endpoint.rs
  • crates/adapter/ibkr/src/cpapi/error.rs
  • crates/adapter/ibkr/src/cpapi/mod.rs
  • crates/adapter/ibkr/src/cpapi/portfolio.rs
  • crates/adapter/ibkr/src/cpapi/secdef.rs
  • crates/adapter/ibkr/src/lib.rs
  • crates/adapter/ibkr/tests/auth.rs
  • crates/adapter/ibkr/tests/endpoint.rs
  • crates/adapter/ibkr/tests/error.rs
  • crates/adapter/ibkr/tests/fixtures/cpapi/auth_status.json
  • crates/adapter/ibkr/tests/fixtures/cpapi/iserver_accounts.json
  • crates/adapter/ibkr/tests/fixtures/cpapi/portfolio_accounts.json
  • crates/adapter/ibkr/tests/fixtures/cpapi/positions.json
  • crates/adapter/ibkr/tests/fixtures/cpapi/secdef_info.json
  • crates/adapter/ibkr/tests/fixtures/cpapi/secdef_search.json
  • crates/adapter/ibkr/tests/fixtures/cpapi/tickle.json
  • crates/adapter/ibkr/tests/live.rs
  • crates/adapter/ibkr/tests/portfolio.rs
  • crates/adapter/ibkr/tests/secdef.rs
  • docker/cpapi/Dockerfile
  • docker/cpapi/README.md
  • docker/cpapi/capture.sh
  • docker/cpapi/docker-compose.yml
  • docs/superpowers/plans/2026-07-10-ibkr-cpapi-readpath-wire.md
  • docs/superpowers/specs/2026-07-10-ibkr-cpapi-readpath-wire-design.md

Comment thread crates/adapter/ibkr/tests/live.rs
Comment thread docker/cpapi/Dockerfile
NotAProfDev and others added 2 commits July 10, 2026 14:08
Address CodeRabbit's four findings on PR #127:

- tests/live.rs, docker/cpapi/capture.sh: add `curl --max-time 30` so a
  stalled/partially-reachable gateway fails fast instead of hanging.
- docker/cpapi/Dockerfile: run the Java gateway as a non-root `ibkr` user
  (Trivy DS-0002). Validated by build+run — starts clean as uid 999, no
  permission errors.
- docker/cpapi/capture.sh, tests/live.rs: document why `-k` (the gateway's
  self-signed cert) so it isn't "fixed" away.
- docs/superpowers/plans/…: sync the stale `secdef_info()` example with the
  shipped `secdef_info(conid, sec_type)` signature.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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.

feat(ibkr): Client Portal API v1 read-path wire layer + paper gateway harness

1 participant