Skip to content

fix(ibkr): reconcile CP API v1 read-path to the live paper gateway#129

Merged
NotAProfDev merged 1 commit into
mainfrom
feat/ibkr-cpapi-real-fixtures
Jul 10, 2026
Merged

fix(ibkr): reconcile CP API v1 read-path to the live paper gateway#129
NotAProfDev merged 1 commit into
mainfrom
feat/ibkr-cpapi-real-fixtures

Conversation

@NotAProfDev

@NotAProfDev NotAProfDev commented Jul 10, 2026

Copy link
Copy Markdown
Owner

Closes #128

Deferred Task 9 from #127: replace the representative CP API v1 fixtures with real, sanitized captures from a live paper Client Portal Gateway, and reconcile the code to the live wire.

Live-wire corrections (the real gateway disagreed with the representative fixtures)

  • tickle binds IBKR's misspelled collission key (an alias keeps the correct spelling should IBKR fix it); guard test added.
  • secdef/info binds ticker (not symbol) and returns a single object (not an array) for one conid.
  • Endpoint::secdef_info is now conid-only — a stock lookup with secType=STK is rejected 400 "month required".
  • capture.sh sends an empty-body POST /tickle (a bodyless POST returns 411) and drops secType from secdef/info.
  • secdef/search real AAPL returns 6 sections; positions keep money as serde_json::Number (real mktPrice preserved, holdings zeroed).

Sanitization

Account id, holder name, session token, userId, MAC, hardware id, balances, and account-status date scrubbed; the public market price is kept. gitleaks clean; collission allowlisted in _typos.toml.

just ci is green. Adversarially verified across three lenses (data-leak audit / wire fidelity / harness correctness).

Not in this PR: the widened gateway ips.allow that makes browser login work in a devcontainer was an ephemeral runtime patch. Baking it in + harness hardening (healthcheck, compose limits, container-IP capture — ideas from a reference oath-ibkr-v2 gateway) is a planned follow-up.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes

    • Improved IBKR authentication-status parsing for the API’s misspelled collision field.
    • Updated security-definition requests and responses to match observed gateway behavior.
    • Corrected handling of security-definition details, including ticker information and response formatting.
  • Tests

    • Expanded and refreshed IBKR paper-gateway fixtures to reflect real-world response payloads.
    • Added coverage for authentication and security-definition compatibility cases.
  • Documentation

    • Updated the unreleased changelog with details on the refreshed IBKR gateway fixtures and behavior.

Replace the representative cpapi fixtures with real, sanitized captures from a
live paper Client Portal Gateway, and reconcile the DTOs, endpoint descriptor,
and capture script to what the wire actually sends:

- tickle: bind IBKR's misspelled `collission` key (a correct-spelling alias is
  kept should IBKR ever fix it); add a guard test.
- secdef/info: bind `ticker` (not `symbol`), and decode a single object (not an
  array) for one conid.
- Endpoint::secdef_info is now conid-only — a stock lookup with `secType=STK`
  is rejected `400 "month required"`.
- capture.sh: `POST /tickle` sends an empty body (a bodyless POST returns 411);
  secdef/info drops `secType`.
- secdef/search: real AAPL returns 6 sections; positions keep money as
  `serde_json::Number` (real mktPrice preserved, holdings zeroed).

Fixtures sanitized: account id, holder name, session token, userId, MAC,
hardware id, balances, and account-status date scrubbed; the public market
price is kept. `collission` is allowlisted in _typos.toml.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@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: fc940566-5482-4210-a0ce-e1117490c5d1

📥 Commits

Reviewing files that changed from the base of the PR and between 1218850 and ba21ab3.

📒 Files selected for processing (17)
  • CHANGELOG.md
  • _typos.toml
  • crates/adapter/ibkr/src/cpapi/auth.rs
  • crates/adapter/ibkr/src/cpapi/endpoint.rs
  • crates/adapter/ibkr/src/cpapi/secdef.rs
  • crates/adapter/ibkr/tests/auth.rs
  • crates/adapter/ibkr/tests/endpoint.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/portfolio.rs
  • crates/adapter/ibkr/tests/secdef.rs
  • docker/cpapi/capture.sh

📝 Walkthrough

Walkthrough

IBKR CPAPI mappings and endpoint requests were reconciled with sanitized paper-gateway captures. Fixtures, capture commands, deserialization behavior, public endpoint signatures, and related tests were updated for the observed wire shapes.

Changes

IBKR CPAPI wire reconciliation

Layer / File(s) Summary
Update CPAPI wire contracts
crates/adapter/ibkr/src/cpapi/auth.rs, crates/adapter/ibkr/src/cpapi/secdef.rs, crates/adapter/ibkr/src/cpapi/endpoint.rs, _typos.toml
Tickle accepts the wire key collission, SecdefInfo exposes ticker, and secdef_info now builds a conid-only request.
Capture observed gateway payloads
docker/cpapi/capture.sh, crates/adapter/ibkr/tests/fixtures/cpapi/*, CHANGELOG.md
Capture commands and sanitized fixtures now reflect observed tickle, security-definition, authentication, account, position, and search payloads.
Validate reconciled behavior
crates/adapter/ibkr/tests/auth.rs, crates/adapter/ibkr/tests/endpoint.rs, crates/adapter/ibkr/tests/secdef.rs, crates/adapter/ibkr/tests/portfolio.rs
Tests verify wire-key decoding, endpoint paths, response shapes, ticker mapping, section counts, and updated market-price data.

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

Possibly related issues

🚥 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 reflects the IBKR CP API v1 read-path reconciliation.
Linked Issues check ✅ Passed The changes match the linked issue by replacing fixtures with live captures and reconciling DTOs, endpoints, and capture.sh.
Out of Scope Changes check ✅ Passed No unrelated scope was introduced; the changes stay within fixture, DTO, endpoint, test, and capture-script updates.
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-real-fixtures

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.

@NotAProfDev NotAProfDev merged commit d96b7b6 into main Jul 10, 2026
5 checks passed
@NotAProfDev NotAProfDev deleted the feat/ibkr-cpapi-real-fixtures branch July 10, 2026 18:55
NotAProfDev added a commit that referenced this pull request Jul 10, 2026
NotAProfDev added a commit that referenced this pull request Jul 10, 2026
* chore(ibkr): harden the CP gateway docker harness

Make the dev Client Portal Gateway self-sufficient so browser login works in a
devcontainer without a manual patch, adopting hardening ideas from a reference
gateway:

- Bake a dev `conf.yaml` into the image whose `ips.allow` covers loopback +
  RFC-1918 private ranges — the distribution's shipped allowlist
  (192.*/131.216.*/127.0.0.1) rejects a Docker-forwarded login (source
  172.*/10.*) with 403 "not allowed".
- Add a container HEALTHCHECK (curl /iserver/auth/status -> 200|401); install
  curl for it.
- Harden docker-compose: cap_drop ALL, no-new-privileges, mem/pids limits, and a
  bounded log size.
- `just ibkr-capture` resolves the gateway's container IP (new
  docker/cpapi/gateway-base-url.sh helper) because localhost:5000 is not routable
  from inside a devcontainer; capture.sh is untouched.

Verified: image builds, and a throwaway container serves 401 (source allowed,
not 403) with no manual ips.allow patch. Allowlist `vertx` (the keystore
filename) in _typos.toml.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* chore(ibkr): merge main (#129) into the gateway-harness branch

# Conflicts:
#	_typos.toml
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): real paper-account CP API v1 fixtures + DTO/endpoint reconciliation (plan Task 9)

1 participant