Every released version, what changed in it, and the date it went out. This page is generated from the module’s own changelog, which is the same file shipped inside technovision_ai_core and rendered on its Odoo Apps Store listing.
Seven screenshots on the Apps Store listing, taken from the module running against a real database for two different people — including the audit list showing Sara reading invoices through Invoicing and Omar reading stock through Inventory, neither ever offered the other's tool.
Changed
The Record Count column is labelled Records. At any sensible column width the old label rendered as Record C..., which is worse than the shorter word.
Notes
The first cut of the listing screenshot showed an answer quoting figures lifted from another module's demo script, printed directly above the tool result that contradicted them. On a listing whose entire claim is that answers are grounded in what was actually read, that would have been the worst possible image to publish. Every figure in the published screenshot was read out of the database by the tool it is attributed to.
18.0.1.0.0
Notes
First release.
Added
Permission-scoped reads. Every tool call runs as env[model].with_user(the person asking), so enforcement is Odoo's own model access and record rules rather than anything written here. There is no privileged query path in the module and none can be added from configuration.
Exposure (ai.exposure) — the outer, company-wide boundary saying which models the assistant may read at all, and which of their fields. Empty on install, so a fresh installation can answer nothing and sends no data anywhere.
A never-send field floor. Passwords, tokens, keys, credentials, signatures, session data, attachments and images are excluded whatever an administrator selects. Applied after the configuration, not as a default for it.
Filter validation. An operator allow-list (inselect, which takes raw SQL, is not on it), no dotted field paths, no filtering or sorting on a field the asker cannot read, and a hard row ceiling above whatever an exposure permits.
A complete audit trail (ai.tool.call) — model, operation, record ids, count, duration, refusals, and the entitling group when Access X-Ray is installed to resolve it. Immutable, and grouped or pivoted by person or model.
Providers behind an interface — Anthropic and OpenAI included, endpoint overridable for Azure OpenAI or a self-hosted deployment, plus a simulated provider that runs the whole loop and sends nothing anywhere.
Cost controls — per-model row limits, a tool-round budget, aggregates that read no individual record, and token usage recorded per conversation.
Two groups: a user asks and reads their own conversations; a manager configures exposure and reads everyone's.
Optional retention purge for the audit trail, off by default.
Security
The API key is never a field on any model. It lives in Odoo's encrypted ir.config_parameter store, is written only by a system administrator through a transient wizard, and is never displayed again. Asserted by test_no_field_on_any_model_holds_the_key.
The assistant is read-only by construction: no write, create, unlink or method call exists in the tool layer.
A conversation is answered with its owner's rights, not those of whoever is reading it, so a manager's follow-up on someone else's conversation cannot widen what it saw.
Notes for the curious
Two defects were found and fixed while building this, both worth recording because both would have been invisible in a demo:
The exposure lookup ran with the asking user's rights, so anyone who could not read ir.model.fields — which is most people — got no tools at all. A recordset union takes the environment of its left operand, and the elevation was being dropped there.
A recorded failure was being undone by the exception that reported it. An exception propagating out of a call rolls the transaction back, so a conversation that wrote state = failed and then raised reached the user as an error message with nothing left in the database to look at. Failures are now part of the conversation rather than raised over the top of it.