Type SESSION_PROPOSE config with a validated SessionProposeConfig model (#18)#20
Type SESSION_PROPOSE config with a validated SessionProposeConfig model (#18)#20phillipclapham wants to merge 1 commit into
Conversation
…el (sunilp#18) Replace the config: dict[str, Any] hatch on LdpMessageBody with a typed SessionProposeConfig so Pydantic enforces the wire shape at the boundary. trust_domain is required; preferred_payload_modes drops unknown / malformed entries via a field validator, preserving the forward-compat tolerance the manual guards from sunilp#17 provided (now retired from the handler). The client builds the typed model. Composes with sunilp#19: a malformed config now raises at parse time and is mapped to a 400 by the route.
|
Warning Review limit reached
More reviews will be available in 1 hour. Learn how PR review limits work. Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file). ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (7)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
Closes #18. Rebased onto
mainnow that #17 has landed, so the diff is just the typed-config change.Replaces the
config: dict[str, Any]hatch onLdpMessageBodywith a typedSessionProposeConfig, so Pydantic enforces the wire shape at the boundary:preferred_payload_modeskeeps the forward-compat tolerance the manual guards from Mode 3 (SEMANTIC_GRAPH) negotiation via declared support + codec registration (#15) + lifecycle hooks (#14) #17 added — amode="before"validator drops non-list / unknown / non-string entries, so a peer on a newer mode set degrades to the shared known modes instead of failing the handshake. Those manual guards are retired from the handler.trust_domainis required and non-blank (validator rejects""/ whitespace, mirroringTrustDomain.name). Deliberate contract tightening: previously a SESSION_PROPOSE missingtrust_domain(or with no config) was treated as the"unknown"domain; now it's rejected at the boundary, and amodel_validatorrequires config for SESSION_PROPOSE so it holds end to end. The bundled client always sendstrust_domain, so it's unaffected. If you'd rather keep the lenient default,trust_domain: str = "unknown"is a one-line change.ttl_secs, when present, must be positive.One design question:
LdpMessageBodyis a flat model, so the typedconfigfield is validated on every message type, not just SESSION_PROPOSE — a future message carrying aconfigthat isn't a valid SessionProposeConfig would be rejected at the boundary rather than reaching the unknown-message path. That's consistent with how the model already validates every other typed field (negotiated_mode,contract, …), and no current message carries config elsewhere, so there's no blast radius today. If you'd wantconfigto stay a universal extension hatch, the clean options are a discriminated union or conditionally coercing config only whentype == "SESSION_PROPOSE"— your call on evolvability, happy to implement either.Heads-up for the Rust mirror: Python conveys SESSION_PROPOSE mode prefs as
config.preferred_payload_modes, but the Rust server reads a top-levelpayload_mode(src/server.rs), so Python↔Rust mode negotiation looks like it diverges today (predates this PR). Worth a cross-SDK JSON fixture when you align Rust — happy to file a separate issue.Tests cover: drops unknown modes, coerces strings, requires non-blank trust_domain, rejects non-positive ttl, requires config for SESSION_PROPOSE, validates through the envelope boundary, and the factory dict path enforces the same. Also fixed
examples/session_flow.json, which usedrequired_trust_domain(a client-config field name) in the wire config.