fix: GET /v1/user_info 500 on missing broker_credentials table (issue #9)

trex-core reported GET /v1/user_info returning 500 for valid service/daemon
tokens (whoami → daemon_id), degrading the daemon and holding new trades. The
reported hypothesis (service-token None deref) was a misdiagnosis. Root cause:

  app/api/v1_user_info.py: credentials = repo.list_broker_credentials(...)
  psycopg.errors.UndefinedTable: relation "broker_credentials" does not exist

The broker_credentials table was missing and the handler only caught
AttributeError, so the DB error propagated to a bare 500.

Two fixes:
1. Handler now degrades gracefully when broker-credential lookup fails — returns
   empty brokers and still serves daemon_id/user_id/permission, which do not
   depend on broker credentials. This is what trex-core's whoami needs.
2. ensure_schema() now also CREATE TABLE broker_credentials (same shape as
   migration 20260502_0014). ensure_schema-bootstrapped DBs were missing it,
   since previously only the alembic path created it.

Added tests/test_v1.py regression: broker-credential lookup raising a DB error
must yield HTTP 200 with daemon_id, not 500. Verified against the real DB
(was 500 → now 200 + daemon_id). Full suite 377 passed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-06 10:17:30 +09:00
co-authored by Claude Opus 4.8
parent b774e40678
commit 6b812b6035
3 changed files with 51 additions and 0 deletions
+13
View File
@@ -406,6 +406,19 @@ class PostgresPortfolioRepository:
ON daemons (owner_user_id)
"""
)
cur.execute(
"""
CREATE TABLE IF NOT EXISTS broker_credentials (
user_id TEXT NOT NULL,
broker TEXT NOT NULL,
account_ref TEXT NOT NULL,
encrypted_payload TEXT NOT NULL,
credential_version INTEGER NOT NULL DEFAULT 1,
last_rotated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
PRIMARY KEY (user_id, broker)
)
"""
)
cur.execute("SELECT EXISTS (SELECT 1 FROM pg_extension WHERE extname = 'timescaledb')")
if cur.fetchone()[0]:
cur.execute(