feat(broker): add Alpaca paper read-only adapter - #309
Merged
Conversation
Add a GET/read-only Alpaca Paper adapter foundation (no order placement, no execution, no live broker, no committed credentials): - app/services/alpaca_paper_readonly_adapter.py — AlpacaPaperReadOnlyAdapter. Injected-client / env-gated; safe degraded_demo fallback when read-only is not explicitly enabled or credentials are absent; lazy paper-only SDK import that degrades on any error; sanitizes positions to display-safe fields only. - app/schemas/alpaca_paper_readonly.py — AlpacaPaperPositionsPreview + AlpacaPaperReadOnlyPosition (extra="forbid"; safety flags always true, order_placement_enabled=false). - app/api/routes/alpaca_paper.py — new GET /api/alpaca-paper/positions-preview (no mutating routes added). - tests/app/test_alpaca_paper_readonly_adapter.py — 13 tests (degraded default, injected client sanitization, no forbidden-field leakage, raising/malformed degrade safely, unsafe/disabled config resolves no client, GET-only route). - docs/tasks/alpaca_paper_readonly_adapter_001.md. Read-only only. No POST/PUT/PATCH/DELETE, no place/submit/cancel/replace order, no live endpoint, no secrets. Legacy brokers/alpaca_adapter.py left untouched. Safety posture unchanged: autotrade=false, dry_run=true, read_only=true, live_orders_blocked=true, max risk <= 1%. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
Sorry @Melly-999, you have reached your weekly rate limit of 500000 diff characters.
Please try again later or upgrade to continue using Sourcery
Melly-999
temporarily deployed
to
feature/alpaca-paper-readonly-adapter-001 - alpha_data_scraper_ai PR #309
June 15, 2026 17:30 — with
Render
Destroyed
Melly-999
marked this pull request as ready for review
June 15, 2026 20:23
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Scope
Backend read-only adapter + GET route + tests + task doc. No frontend, scripts, workflows, package, Docker/Tauri, cloud config, or env files.
99ff2f11971f5de214d7547f2ea89e465cae573ebf9a01cbf889367dc462073f74d3d47bb5b8e1aaFiles changed
app/api/routes/alpaca_paper.py(1 new GET route)app/schemas/alpaca_paper_readonly.py(new)app/services/alpaca_paper_readonly_adapter.py(new)tests/app/test_alpaca_paper_readonly_adapter.py(new)docs/tasks/alpaca_paper_readonly_adapter_001.md(new)Implementation summary
AlpacaPaperReadOnlyAdapter— optional injected client +env_reader. Resolves a client only when explicitly enabled (ALPACA_PAPER_READONLY_ENABLED=true+ALPACA_ENV=paper+ credentials present) or when a client is injected; otherwise a safe degraded fallback. The default client factory lazy-imports the Alpaca SDK withpaper=True(paper endpoint only) and degrades on any error. Only the read-onlyget_all_positionsis referenced.GET /api/alpaca-paper/positions-preview— sanitized positions preview (no mutating routes added).ALPACA_ENV/ client error →mode=degraded_demo,connected=false,source=fallback, empty positions; never raises.symbol/qty/market_value/unrealized_pl/side; schemaextra="forbid"drops broker-internal fields; credentials never stored, logged, or returned.Read-only boundary
GET-only · no POST/PUT/PATCH/DELETE · no order placement/cancellation/replacement · no live broker endpoint (
paper=Trueonly) · no credential UI · no secrets · no frontend trading controls.Forbidden output fields confirmed absent:
account_id,broker_account_id,broker_order_id,execution_id,api_key,secret,token.Tests / validation summary
account_id/asset_id; raising client degrades; malformed positions skip/degrade; unsafeALPACA_ENV=liveand disabled config resolve no client; route GET 200 + safety flags; route no forbidden keys; POST/PUT/PATCH/DELETE → 405; OpenAPI GET-only). No real creds, no network.python scripts/validate_safety_config.py→ OVERALL: PASS.black --check,flake8,mypy(new files) → all clean.git diff --check→ clean.Static scan summary
No secrets / token-shaped strings / DB URLs / API keys / broker credentials / account IDs / emails / phones / Neon identifiers. No safety-flip values. No
place_order/submit_order/execute_order/cancel_order/replace_order/MarketOrderRequest/OrderSidein new code — matches exist only in the task doc's prohibition/denylist text. Legacybrokers/alpaca_adapter.pyleft untouched.Out of scope
Safety confirmation
🤖 Generated with Claude Code