fix(#213): resilient json2 introspection fallback behind a WAF#216
Conversation
The Odoo 19 ``json2`` connector maps positional method args to parameter names by first fetching the model schema over a separate ``GET /doc-bearer/<model>.json``. Some WAF configs (Cloudflare) challenge that GET path even when the RPC POST is allowed, so positional-arg calls fail before reaching Odoo while keyword calls go straight through (#213). - docs/guides/configuration.md: document the introspection gotcha and the keyword-argument workaround under the existing Cloudflare/WAF caveat. - odoo_lib.get_odoo_version: pass domain/fields as keywords. Version detection runs on every connection, so keeping it kwargs-only avoids the blocked GET on json2s behind a WAF. Note: the import/export hot path still makes positional RPC calls; a complete fix (resilient introspection fallback or full kwargs conversion) needs a live json2s test environment and is left as follow-up.
There was a problem hiding this comment.
Code Review
This pull request updates the get_odoo_version function in src/fluvo/lib/odoo_lib.py to use keyword arguments instead of positional arguments when calling search_read. This change prevents potential WAF/Cloudflare challenge issues associated with the GET /doc-bearer/ request used for positional argument introspection in the json2 connector. Additionally, the documentation in docs/guides/configuration.md has been updated to explain this behavior and recommend keyword arguments. There are no review comments, and I have no feedback to provide.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
The Odoo 19 json2 connector maps positional method args to parameter names by first fetching the model schema over GET /doc-bearer/<model>.json. A WAF (Cloudflare) commonly challenges that GET even when the RPC POST is allowed, so every positional call failed before reaching Odoo (#213). Make it transparent: wrap json2's JsonModel._introspect so that when the /doc-bearer/ GET fails, it falls back to the built-in Odoo 19 ORM signatures and positional calls to the standard methods (search, search_read, read, write, create, fields_get, ...) keep working with no code change. A positional call to a custom method with no built-in signature raises a clear, actionable error instead of a bare KeyError. json2/json2s exist only on Odoo 19+, so the Odoo 19 signatures (verified against a live server, matching odoo/addons/api_doc's /doc-bearer/ output exactly) are the only ones the fallback needs. - rpc_transport: fallback signature table + @api.model method set, resilient _introspect wrapper wired into install() (idempotent, sentinel-guarded). The new helpers use concise one-line docstrings so they add no pydoclint-baseline churn. - tests: cover fallback population, positional model- and record-method arg mapping, and the unknown-method guidance error. - docs: update the Cloudflare/WAF caveat to describe the automatic fallback. Also update two pydoclint baseline yield-type renderings ('batch', 'odoo_endpoint') that drifted with the resolved toolchain (Any -> list[Any], (str, object) -> dict[str, object]), which was failing the pydoclint pre-commit hook on every PR.
7695877 to
6d808e7
Compare
What
Fixes #213: a Cloudflare-fronted Odoo behind
json2sbreaks positional-argument RPC because the json2 connector introspects each model viaGET /doc-bearer/<model>.json, which the WAF challenges (HTTP 403 "Just a moment…") even though the RPCPOSTis allowed.Fix — transparent fallback
rpc_transportalready swaps json2's module-levelhttpxfor a pooled shim. This wraps json2'sJsonModel._introspectso that when the/doc-bearer/GET fails, it falls back to the built-in Odoo 19 ORM signatures, and positional calls to the standard methods (search,search_read,read,write,create,fields_get,unlink, …) keep working with no code change. A one-line warning is logged the first time. A positional call to a custom method with no built-in signature raises a clear, actionable error (use keyword args) instead of a bareKeyError.json2/json2sexist only on Odoo 19+, so the Odoo 19 signatures are the only ones needed. They were verified against a live Odoo 19 server and mirror exactly whatodoo/addons/api_doc's/doc-bearer/endpoint produces (ordered param names,selfstripped, var-keyword included,@api.modelset).Also
odoo_lib.get_odoo_version→ keyword args (runs on every connection).uv.lock, so the pydoclint pre-commit hook was rewriting it and failing on every PR. Regenerated so pre-commit is green.Tests
New
tests/test_rpc_transport.pycases: fallback population when the GET is blocked, positional model-method and record-method arg mapping, and the unknown-method guidance error. Full unit suite: 1435 passed. mypy + full pre-commit clean.Closes #213.