Skip to content

OrderbookDeltaPayload.ts still typed as str — v2.5 #270 WS AwareDatetime sweep missed it #331

Closed

Description

@TexasCoding

Problem

v2.5 #270 widened user_orders and communications WS payload timestamps to pydantic.AwareDatetime, explicitly to close "the gap left by v2.4's #234 REST sweep — naive RFC3339 strings now raise ValidationError on WS too." OrderbookDeltaPayload.ts was missed: the docstring in the same file still calls it an RFC3339 timestamp string, but the field is still typed str | None. A malformed or naive timestamp on the highest-volume WS channel sails through with no validation, while the same shape on user_orders / communications raises — exactly the inconsistency #270 set out to remove.

ts_ms (the spec-preferred Unix-ms field) is unaffected, but ts is the documented backward-compat surface and is still emitted by older delta frames per spec, so leaving it str silently reopens the gap.

Evidence

  • kalshi/ws/models/orderbook_delta.py:90-112:
class OrderbookDeltaPayload(BaseModel):
    """Payload for orderbook_delta messages.

    Wire format per AsyncAPI spec and confirmed on demo: ``price_dollars`` is
    a dollar-decimal string (e.g. ``"0.0200"``), ``delta_fp`` is a fixed-point
    count string (e.g. ``"10.00"``, may be negative), ``ts`` is an RFC3339
    timestamp string (e.g. ``"2026-04-19T18:43:37.662364Z"``).
    """
    ...
    ts: str | None = None
    # v0.14+ backfill (#162). ts_ms (Unix ms) supersedes ts (RFC3339).
    ts_ms: int | None = None

Suggested fix

Change ts: str | None = None to ts: AwareDatetime | None = None. Pydantic's AwareDatetime accepts RFC3339 strings and rejects naive timestamps with the same semantics already in force on user_orders. Add a regression test in tests/ws/test_models.py mirroring the user_orders aware-datetime test for orderbook_delta.

Source

Round-3 independent audit (reviewer: models_contracts).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingwsWebSocket-related

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions