Name: [IMP] viin_brain,viin_web_editor: UI hardening v1 (token + polish + Odoo-native + v2 seams)

State: Failed finished in 19m

PR State: merged

PR Author: David Tran

PR Author Email:

PR: #27

Committer: David Tran

Committer Email: davidtran.hp@gmail.com

Commit: 6d7ec7c9a357c0fba5cdfb57bda3408fb540a787

Description:

                                            [IMP] viin_brain: P7 H4 fix + WI-4 universal injector wire (round 3 sprint 3)

P7 H4 — content_html sanitize_attributes=False
- Brain embed blocks use data-snapshot-id, data-snapshot-kind,
  data-block-anchor, data-is-stale, data-mode attributes that are NOT
  in Odoo's safe_attrs whitelist (odoo/tools/mail.py:44-55).
- With default sanitize_attributes=True, html_sanitize() with
  safe_attrs_only=True strips all data-snapshot-* on every WRITE,
  breaking embed chrome render after save→reload.
- Fix: explicit sanitize_attributes=False preserves data-* while
  sanitize_tags=True (implicit) still blocks script/iframe/object
  tags so XSS posture intact.
- Verified via JSON-RPC ORM write of 950-byte embed HTML →
  read back returns 906 bytes with data-snapshot-kind +
  o_brain_snapshot_chrome--snapshot class preserved.

WI-4 (ADR-001) Universal Brain sidebar injection — restored
- Original __manifest__.py:270-271 declares "WI-4 (ADR-001) — universal
  hook injection for mail.thread descendants" but stage 1 (function
  definition) shipped without stage 2 (caller wiring) per git
  archaeology of commit 26f2190.
- Per ETHOS §4.1.1 boil-the-lake: the function intent was clear, only
  the wiring was missing; restore (wire) rather than delete.
- Rewrote brain_form_sidebar_universal.js to patch FormCompiler
  .prototype.compile() (not FormController) and mutate source arch
  this.templates[key] BEFORE super.compile(). Detection: presence of
  <div class="oe_chatter"> proxies for mail.thread descendant (= has
  brain_page_count via mail_thread.py inheritance). Guards against
  double-inject (existing .o_brain_form_sidebar_hook from bridge XML)
  + WeakSet on processed templates.
- Verified on 2 models with NO bridge XML:
  * project.project (Office Design ID=1) — BRAIN rail sidebar auto-renders
  * crm.team (Sales ID=1) — BRAIN rail sidebar auto-renders
- Existing 5 bridges (res.partner, crm.lead, hr.employee, project.task,
  sale.order) continue to work unchanged — hookAlreadyPresent guard
  prevents double injection.

NOTE — separate page_editor render race exists: bodyRef.el.innerHTML
stays empty despite state.page.content_html containing 906 bytes after
ORM write. JSON-RPC verifies content delivery; OWL render does not
materialize. Investigation deferred — not introduced by this commit;
unrelated to H4 sanitization fix.

NOTE — universal injector stat button (Brain Pages count) appears on
forms with <div name="button_box"> but the inserted <field name=
"brain_page_count" widget="statinfo"> child does not visually render in
project.project capture. Sidebar (primary deliverable) works on both
test models. Stat button compilation pipeline interaction worth
follow-up; sidebar functionality unblocked.

AC-1 hex grep PASS, brain_v3_ci_check.py --strict 8 PASS / 1 pre-existing
WARN (rule2 contenteditable baseline = 14 unchanged).

Refs PR #27.
                                            

Branch: 17.0

Instance ID: 0

Age:

Up-time: