Includes:
- compositor.app, compositor.session, compositor.session.app, compositor.audit.log models
- /web/compositor/{token,apps,launch,audit} HTTP controllers with JWT (HS256)
- CompositorService OWL service (reusable via useService('compositor'))
- CompositorCanvas OWL component (reusable canvas wrapper)
- Security: compositor_group_user, compositor_group_manager groups + ir.access.csv rules
- 5 demo apps pre-loaded (gnome-calculator, xterm, gtk4-demo, glxgears, featherpad)
- Audit log capturing JWT issuance + app launch events
- Stub mode: launching apps returns a stub SurfaceHandle when proxy isn't connected
- Tested against Odoo 20 + PostgreSQL 17
Author: 1bspace.com
Parent company: 1B Global
License: Proprietary (1B Space internal use)
113 lines
6.1 KiB
XML
113 lines
6.1 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
|
<odoo>
|
|
<data>
|
|
<!-- ─── App List View ─────────────────────────────────────────── -->
|
|
<record id="view_compositor_app_list" model="ir.ui.view">
|
|
<field name="name">compositor.app.list</field>
|
|
<field name="model">compositor.app</field>
|
|
<field name="arch" type="xml">
|
|
<list string="Compositor Apps">
|
|
<field name="app_id"/>
|
|
<field name="name"/>
|
|
<field name="executable"/>
|
|
<field name="memory_limit_mb" string="Mem (MB)"/>
|
|
<field name="cpu_quota_percent" string="CPU (%)"/>
|
|
<field name="sandbox_network" string="Net"/>
|
|
<field name="sandbox_gpu" string="GPU"/>
|
|
<field name="running_session_count" string="Running"/>
|
|
<field name="active" widget="boolean_toggle"/>
|
|
</list>
|
|
</field>
|
|
</record>
|
|
|
|
<!-- ─── App Form View ─────────────────────────────────────────── -->
|
|
<record id="view_compositor_app_form" model="ir.ui.view">
|
|
<field name="name">compositor.app.form</field>
|
|
<field name="model">compositor.app</field>
|
|
<field name="arch" type="xml">
|
|
<form string="Compositor App">
|
|
<header>
|
|
<button name="action_test_executable" string="Test Executable" type="object" class="btn-secondary"/>
|
|
<button name="action_view_running_sessions" string="View Running Sessions" type="object" class="btn-primary"/>
|
|
</header>
|
|
<sheet>
|
|
<field name="icon" widget="image" class="oe_avatar"/>
|
|
<div class="oe_title">
|
|
<label for="name"/>
|
|
<h1><field name="name" placeholder="e.g. GNOME Calculator"/></h1>
|
|
<h3><field name="app_id" placeholder="e.g. gnome-calculator"/></h3>
|
|
</div>
|
|
<group>
|
|
<group string="Executable">
|
|
<field name="executable" placeholder="/usr/bin/gnome-calculator"/>
|
|
<field name="args" placeholder="--new-window"/>
|
|
<field name="env_vars" placeholder="GDK_SCALE=1"/>
|
|
</group>
|
|
<group string="Resource Limits (per instance)">
|
|
<field name="memory_limit_mb"/>
|
|
<field name="cpu_quota_percent"/>
|
|
<field name="tasks_max"/>
|
|
</group>
|
|
</group>
|
|
<group>
|
|
<group string="Sandbox">
|
|
<field name="sandbox_network"/>
|
|
<field name="sandbox_gpu"/>
|
|
</group>
|
|
<group string="Display">
|
|
<field name="color" widget="color"/>
|
|
<field name="active" widget="boolean_toggle"/>
|
|
<field name="company_id" groups="base.group_multi_company"/>
|
|
</group>
|
|
</group>
|
|
<notebook>
|
|
<page string="Allowed Groups" name="allowed_groups">
|
|
<field name="allowed_group_ids" widget="many2many_tags"/>
|
|
</page>
|
|
<page string="Description" name="description">
|
|
<field name="description" widget="html"/>
|
|
</page>
|
|
</notebook>
|
|
</sheet>
|
|
</form>
|
|
</field>
|
|
</record>
|
|
|
|
<!-- ─── App Search View ───────────────────────────────────────── -->
|
|
<record id="view_compositor_app_search" model="ir.ui.view">
|
|
<field name="name">compositor.app.search</field>
|
|
<field name="model">compositor.app</field>
|
|
<field name="arch" type="xml">
|
|
<search string="Compositor Apps">
|
|
<field name="name"/>
|
|
<field name="app_id"/>
|
|
<field name="executable"/>
|
|
<filter name="active" string="Active" domain="[('active', '=', True)]"/>
|
|
<filter name="with_network" string="Has Network Access" domain="[('sandbox_network', '=', True)]"/>
|
|
<filter name="with_gpu" string="Has GPU Access" domain="[('sandbox_gpu', '=', True)]"/>
|
|
<separator/>
|
|
<filter name="group_app_id" string="App ID" context="{'group_by': 'app_id'}"/>
|
|
</search>
|
|
</field>
|
|
</record>
|
|
|
|
<!-- ─── Action ────────────────────────────────────────────────── -->
|
|
<record id="action_compositor_app" model="ir.actions.act_window">
|
|
<field name="name">Apps</field>
|
|
<field name="res_model">compositor.app</field>
|
|
<field name="view_mode">list,form</field>
|
|
<field name="search_view_id" ref="view_compositor_app_search"/>
|
|
<field name="help" type="html">
|
|
<p class="o_view_nocontent_smiling_face">
|
|
Create a new compositor app
|
|
</p>
|
|
<p>
|
|
Each app is a Linux application that can be launched and
|
|
displayed inside the Odoo web client via the 1B Space
|
|
Compositor.
|
|
</p>
|
|
</field>
|
|
</record>
|
|
</data>
|
|
</odoo>
|