Name: [ADD] P-OPS-2 approval governance + no-key AI test framework

State: Killed

PR State: merged

PR Author: David Tran

PR Author Email:

PR: #47

Committer: David Tran

Committer Email: davidtran.hp@gmail.com

Commit: 149412ee85500233c35d28bbb7d19a9f08eaa419

Description:

                                            [FIX] viin_ai_approval: P-OPS-2 review fixes (XSS/PII/multi-company/hasattr)

Post-review fixes for the P-OPS-2 approval governance + no-key test PR.

CRITICAL
- viin_ai_approval: stored XSS in _format_advisory_html - LLM content was
  interpolated into HTML then wrapped in Markup() at the end (no escaping).
  Rebuilt all 3 paths with Markup(template) %% arg so every LLM-sourced value
  (summary/recommendation/signal label+value, fallback raw) is auto-escaped.

HIGH
- viin_ai_approval: advisory cron processed requests cross-company; sudo()
  bypasses the company ir.rule. Run each request via with_company(company_id)
  so its own agent/provider/BYOK key resolves.
- viin_ai_approval: ir_cron_advisory.xml missing noupdate=1 - upgrades reset
  the cron and silently re-enable LLM calls. Added noupdate=1.
- viin_ai_approval_sale: payment_term_id.name (free-text PII) was sent to the
  LLM. Replaced with a PII-free payment_term_category derived from term lines.
- viin_ai_ops_brain: evidence page landed ai_review_status='n_a' instead of
  honouring vault.auto_approve_ai_content; and page/link create lacked sudo()
  (AccessError for non-Brain-editor users). Set status explicitly + sudo().

hasattr existence-probe cleanup (ref Viindoo/odoo-mcp-client#63)
- viin_ai_approval_sale: commercial_partner_id does not exist on sale.order -
  hasattr was always False, so credit-headroom always used the wrong partner.
  Fixed to partner_id.commercial_partner_id (real hidden bug).
- account credit fields are guaranteed in the closure -> direct access.
- margin/margin_percent (sale_margin soft dep, not in closure) -> use
  'f' in source._fields. Base generic probes -> 'f' in source._fields too.

MED/LOW
- Dedup _has_executable_code/_has_real_code into viin_ai_approval/hooks.py.
- _stub_provider patches the registry class (was import-path) like _stub_llm.
- account: date.today()->fields.Date.today(); fix invalid payment_state key in
  topic prompt. ops_brain: goal fallback model + inheriting view id/name.

Tests
- Added stored-XSS regression tests, real PII-absent assertions (account+sale),
  ai_review_status-follows-vault-policy test.
- Replaced duck-typed-fake sale signal tests with real-record ORM tests + two
  helpers (FIRST-deterministic skipTest when sale_margin/account absent).
                                            

Branch: 17.0

Instance ID: 0

Age:

Up-time: Not finished