Commit db7dabc
authored
feat(extensions): add OperationValidator.precheck pre-body-parse hook (#1548)
Add an optional ``precheck`` method to ``OperationValidatorExtension`` that
extensions can override to gate a request *before* its body is read off the
wire. Wire it as a FastAPI ``Depends`` ahead of the body parameter on the
billable POST routes (retain, recall, reflect, file retain, mental-model
create, mental-model refresh) so a rejecting precheck short-circuits the
request without ever materialising the JSON payload in memory.
The post-body-parse ``validate_retain`` / ``validate_recall`` /
``validate_reflect`` hooks are unchanged and remain the source of truth for
precise per-call cost and quota arithmetic. ``precheck`` is intentionally a
cheap, side-effect-free check — its sole purpose is to let an extension
short-circuit work that would otherwise allocate the request body
unnecessarily (e.g. a quota-exhausted caller submitting many large bodies).
Why before body parse:
FastAPI resolves dependencies before deserialising the route's body
parameter. A validator that runs only after parse — i.e. inside the route
handler's body — sees the already-materialised request, which is the wrong
layer for "this caller should not be allowed to spend resources on this
request at all" decisions. Wiring as ``Depends`` puts the gate at the right
layer with a one-line change per route.
Verified:
- FastAPI 0.125.0 resolves ``Depends`` raising ``HTTPException`` before
Pydantic deserialises the body, regardless of declaration order. A
reproducer using a ``model_validator(mode='before')`` recorder confirms
zero body-parse calls on the rejection path.
- The new ``PrecheckContext`` carries only operation name + bank_id +
request_context (already-resolved tenant). No body access — by design.
- Default ``precheck`` returns ``ValidationResult.accept()``; existing
validators are unaffected.
Tests: +7 unit tests covering the default no-op, the FastAPI Depends
wiring, accept/reject paths, status-code/reason propagation, and explicit
"body never parsed on rejection" assertions for retain / recall / reflect
plus a "GET routes are unaffected" guard. All passing.1 parent b83bb87 commit db7dabc
4 files changed
Lines changed: 393 additions & 3 deletions
File tree
- hindsight-api-slim
- hindsight_api
- api
- extensions
- tests
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2892 | 2892 | | |
2893 | 2893 | | |
2894 | 2894 | | |
| 2895 | + | |
| 2896 | + | |
| 2897 | + | |
| 2898 | + | |
| 2899 | + | |
| 2900 | + | |
| 2901 | + | |
| 2902 | + | |
| 2903 | + | |
| 2904 | + | |
| 2905 | + | |
| 2906 | + | |
| 2907 | + | |
| 2908 | + | |
| 2909 | + | |
| 2910 | + | |
| 2911 | + | |
| 2912 | + | |
| 2913 | + | |
| 2914 | + | |
| 2915 | + | |
| 2916 | + | |
| 2917 | + | |
| 2918 | + | |
| 2919 | + | |
| 2920 | + | |
| 2921 | + | |
| 2922 | + | |
| 2923 | + | |
| 2924 | + | |
| 2925 | + | |
| 2926 | + | |
| 2927 | + | |
| 2928 | + | |
| 2929 | + | |
| 2930 | + | |
| 2931 | + | |
| 2932 | + | |
| 2933 | + | |
| 2934 | + | |
| 2935 | + | |
| 2936 | + | |
| 2937 | + | |
| 2938 | + | |
| 2939 | + | |
| 2940 | + | |
| 2941 | + | |
| 2942 | + | |
| 2943 | + | |
| 2944 | + | |
| 2945 | + | |
2895 | 2946 | | |
2896 | 2947 | | |
2897 | 2948 | | |
| |||
3149 | 3200 | | |
3150 | 3201 | | |
3151 | 3202 | | |
3152 | | - | |
| 3203 | + | |
| 3204 | + | |
| 3205 | + | |
| 3206 | + | |
3153 | 3207 | | |
3154 | 3208 | | |
3155 | 3209 | | |
| |||
3337 | 3391 | | |
3338 | 3392 | | |
3339 | 3393 | | |
3340 | | - | |
| 3394 | + | |
| 3395 | + | |
| 3396 | + | |
| 3397 | + | |
3341 | 3398 | | |
3342 | 3399 | | |
3343 | 3400 | | |
| |||
3835 | 3892 | | |
3836 | 3893 | | |
3837 | 3894 | | |
| 3895 | + | |
3838 | 3896 | | |
3839 | 3897 | | |
3840 | 3898 | | |
| |||
3883 | 3941 | | |
3884 | 3942 | | |
3885 | 3943 | | |
| 3944 | + | |
3886 | 3945 | | |
3887 | 3946 | | |
3888 | 3947 | | |
| |||
5729 | 5788 | | |
5730 | 5789 | | |
5731 | 5790 | | |
5732 | | - | |
| 5791 | + | |
| 5792 | + | |
| 5793 | + | |
| 5794 | + | |
5733 | 5795 | | |
5734 | 5796 | | |
5735 | 5797 | | |
| |||
5899 | 5961 | | |
5900 | 5962 | | |
5901 | 5963 | | |
| 5964 | + | |
5902 | 5965 | | |
5903 | 5966 | | |
5904 | 5967 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
40 | 40 | | |
41 | 41 | | |
42 | 42 | | |
| 43 | + | |
43 | 44 | | |
44 | 45 | | |
45 | 46 | | |
| |||
72 | 73 | | |
73 | 74 | | |
74 | 75 | | |
| 76 | + | |
75 | 77 | | |
76 | 78 | | |
77 | 79 | | |
| |||
Lines changed: 63 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
82 | 82 | | |
83 | 83 | | |
84 | 84 | | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
85 | 112 | | |
86 | 113 | | |
87 | 114 | | |
| |||
407 | 434 | | |
408 | 435 | | |
409 | 436 | | |
| 437 | + | |
| 438 | + | |
| 439 | + | |
| 440 | + | |
| 441 | + | |
| 442 | + | |
| 443 | + | |
| 444 | + | |
| 445 | + | |
| 446 | + | |
| 447 | + | |
| 448 | + | |
| 449 | + | |
| 450 | + | |
| 451 | + | |
| 452 | + | |
| 453 | + | |
| 454 | + | |
| 455 | + | |
| 456 | + | |
| 457 | + | |
| 458 | + | |
| 459 | + | |
| 460 | + | |
| 461 | + | |
| 462 | + | |
| 463 | + | |
| 464 | + | |
| 465 | + | |
| 466 | + | |
| 467 | + | |
| 468 | + | |
| 469 | + | |
| 470 | + | |
| 471 | + | |
| 472 | + | |
410 | 473 | | |
411 | 474 | | |
412 | 475 | | |
| |||
0 commit comments