Files
computer-playbook/roles/web-app-mattermost/files/sql/select/ai/service.sql
kevinveenbirkenbachandClaude Opus 5 a372d5aa0f fix(mattermost): check the Agents service against the contract, not for identity
The convergence check compared the stored service element to the declared one with
jsonb equality, and the deploy failed on "The Agents plugin still stores a service or
bot that differs from the deployed gateway contract".

The sequence is write via SQL, cycle the plugin, read back. Cycling is exactly when
the plugin rewrites that structure, and it owns it. Any field it adds of its own makes
byte-identical equality impossible, permanently, while the contract itself holds.

Containment says what the task means. Its own name asks whether the stored config
still matches the gateway contract, not whether it is the same object: the deployed
keys must be present with the deployed values, and what the plugin keeps besides is
its business.

Only that one condition changes. The bot check, the legacy-bot check, the FROM clause
and the per-active-row semantics stay as they were -- a first attempt restructured the
whole query into CTEs, which would have aggregated across active rows instead of
evaluating each, and reported converged as soon as any one of them matched.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-31 16:03:53 +02:00

33 lines
1.5 KiB
SQL

SELECT CASE
WHEN EXISTS (SELECT 1
FROM jsonb_array_elements(
CASE WHEN jsonb_typeof(a.config::jsonb -> 'services') = 'array'
THEN a.config::jsonb -> 'services'
ELSE '[]'::jsonb END
) AS s
WHERE s ->> 'id' = d.service ->> 'id'
AND s @> d.service)
AND EXISTS (SELECT 1
FROM agents_useragents u
WHERE u.username = d.bot ->> 'name'
AND u.serviceid = d.bot ->> 'serviceID'
AND u.model = d.bot ->> 'model'
AND u.deleteat = 0
AND u.botuserid <> '')
AND NOT EXISTS (SELECT 1
FROM jsonb_array_elements(
CASE WHEN jsonb_typeof(a.config::jsonb -> 'bots') = 'array'
THEN a.config::jsonb -> 'bots'
ELSE '[]'::jsonb END
) AS legacy
JOIN agents_useragents u2
ON u2.username = legacy ->> 'name'
AND u2.deleteat = 0)
THEN 'converged'
ELSE 'stale'
END
FROM agents_confighistory a,
(SELECT %(service)s::jsonb AS service,
%(bot)s::jsonb AS bot) AS d
WHERE a.active = true;