- partial-install visibility: error path now carries the modules
installed before the failure, instead of silently dropping the list
- introspect log line: shows source-installed/target-installed/delta
counts so the bell row narrates the comparison
- Authenticate calls: 15s timeout context (matches addon_lifecycle
pattern; hung Odoo no longer pins the parent op)
- source readiness probe: 30s waitForOdooReady before introspect so
source-down fails fast with clear message instead of cryptic auth
Promote no longer ships only code. After commit + sync it now:
- waits for target Odoo readiness
- queries source + target for installed-set across the recipe
- pre-checkpoint on target (best-effort)
- ButtonImmediate(install) on target for the delta
Op stays running until install hooks complete; complete means
prods Modules tab matches stages installed-set, not just mount layer.
Odoo 19 image runs Python 3.12 (Bookworm), which enforces PEP 668.
pip install --user is blocked without --break-system-packages, so
every addon with even one external_dependencies.python entry failed
on Odoo 19. Build container is single-shot, so the lock does not
apply — the flag is the correct override here.
- Wizard: default Odoo to latest matrix entry; PG snaps to recommended
on every Odoo change (was sticky-compatible, leaving PG 16 when
switching to Odoo 19 even though 17 is recommended)
- export.go: pgClientImageFor(shape.PostgresVersion) — pg_dump tracks
source instances actual PG version (17/18/whatever ships next)
- ProjectsView: super-admin All-tenants mode now fans out across tenants
(was falling back to platform tenant → empty Projects page)
- waitForJobTerminal: pod log tail spliced into job-failed errors
(export, import, backup, restore — visibility into REAL cause)
- runSpawnEnv: register env BEFORE seed (was after) so a failed seed
leaves a registered-but-empty env instead of a ghost instance
Backend SSE handler already accepts ?tenantId= as an additive filter
on top of canSeeOp (Phase G stays load-bearing); frontend now passes
the global tenant filter chip's value through both NotificationBell
and ActivityTab. Watcher clears + restarts the stream when the
super-admin switches tenant context. Dismissed Set is user-level
and survives the switch.