Batch of red-team r3 fixes that were in the working tree before the 2026-09-28 design overhaul, committed as one unit with their tests. - desktop main: STT timeouts and sidecar, voice recording store, sync (credentials, audio, knowledge reindex, push gates), runtime provisioner, update policy, AltGr keybindings, voice-command policy, dictionary file codec/limits, meeting transcript condensing and a local recording ledger so interrupted-session recovery only closes meetings this device recorded (a phone's live meeting is left alone). - mobile: login CSRF via implicit token callbacks rejected, account deletion/retention, durable queue retention, knowledge realtime without unfiltered DELETE, meeting re-record failure paths, cloud STT client, preferences store/resync. - core: text chunking splits long unbroken transcripts to fit, template field policy, dictionary limits, meeting markdown inline handling. - server: payple webhook policy and cancellation order scope, meeting document generation quota, team RPC null-role guard, unified LLM quota in-flight accounting, knowledge chunk vector index, meeting re-record failure paths (migrations 20260929*). - ci: portable/runtime feed gates, update-policy schema, Forgejo file delete and alias planning. Four older tests are updated to the new contracts rather than the old behavior: token-pair auth callbacks are rejected, knowledge realtime no longer subscribes to DELETE, long transcript lines are split, and meeting recovery requires the local recording ledger for empty rows.
341 lines
17 KiB
PL/PgSQL
341 lines
17 KiB
PL/PgSQL
\set ON_ERROR_STOP on
|
|
|
|
-- Regression (red-team r3-10): meeting-document claims and llm-proxy
|
|
-- reservations used two separate quota ledgers. A claim held its unit only as
|
|
-- a 'processing' row in meeting_document_generation_requests (advisory lock
|
|
-- seed 0), while reserve_llm_quota counted only daily_usage (seed 20260928).
|
|
-- An llm-proxy request could therefore take the unit a running document
|
|
-- generation already held; the document was paid for and then rejected by
|
|
-- commit with generation_quota_exceeded.
|
|
--
|
|
-- Since 20260929020000_unify_llm_quota_inflight a claim takes a
|
|
-- reserve_llm_quota lease, so both paths share one ledger (daily_usage +
|
|
-- llm_quota_reservations) and one lock (daily_usage_lock_v1). This file covers
|
|
-- the cross-path interleavings (document <-> llm-proxy in both orders, a mixed
|
|
-- burst at the limit, late commit after lease reclaim, legacy claims);
|
|
-- meeting-document-generation-quota.integration.sql covers the single path.
|
|
--
|
|
-- Local only: psql against the local Supabase stack. Runs in a transaction and
|
|
-- rolls back.
|
|
|
|
BEGIN;
|
|
|
|
CREATE OR REPLACE FUNCTION pg_temp.assert_true(condition boolean, message text)
|
|
RETURNS void
|
|
LANGUAGE plpgsql
|
|
AS $$
|
|
BEGIN
|
|
IF condition IS NOT TRUE THEN
|
|
RAISE EXCEPTION 'assertion_failed: %', message;
|
|
END IF;
|
|
END;
|
|
$$;
|
|
|
|
-- Returns the claim payload, or {"error": SQLERRM} when the claim raises.
|
|
CREATE OR REPLACE FUNCTION pg_temp.try_claim(p_actor uuid, p_key uuid, p_meeting uuid, p_template uuid, p_model text)
|
|
RETURNS jsonb
|
|
LANGUAGE plpgsql
|
|
AS $$
|
|
BEGIN
|
|
RETURN public.claim_meeting_document_generation_v1(
|
|
p_actor, p_key, p_meeting, p_template, 'Lease fixture document', p_model
|
|
);
|
|
EXCEPTION WHEN OTHERS THEN
|
|
RETURN jsonb_build_object('error', SQLERRM);
|
|
END;
|
|
$$;
|
|
|
|
-- Returns the commit payload, or {"error": SQLERRM} when the commit raises.
|
|
CREATE OR REPLACE FUNCTION pg_temp.try_commit(p_actor uuid, p_key uuid)
|
|
RETURNS jsonb
|
|
LANGUAGE plpgsql
|
|
AS $$
|
|
BEGIN
|
|
RETURN public.commit_meeting_document_generation_v1(p_actor, p_key, 'Generated body', 10, 1, 1);
|
|
EXCEPTION WHEN OTHERS THEN
|
|
RETURN jsonb_build_object('error', SQLERRM);
|
|
END;
|
|
$$;
|
|
|
|
CREATE OR REPLACE FUNCTION pg_temp.usage_of(p_actor uuid, p_feature text)
|
|
RETURNS integer
|
|
LANGUAGE sql
|
|
AS $$
|
|
SELECT coalesce(sum(count), 0)::integer FROM public.daily_usage
|
|
WHERE user_id = p_actor AND feature = p_feature AND date = CURRENT_DATE;
|
|
$$;
|
|
|
|
INSERT INTO auth.users (
|
|
id, aud, role, email, encrypted_password, email_confirmed_at,
|
|
raw_app_meta_data, raw_user_meta_data, created_at, updated_at
|
|
) VALUES
|
|
(
|
|
'38000000-0000-4000-8000-000000000001', 'authenticated', 'authenticated',
|
|
'meeting-doc-lease-pro@example.invalid', crypt('fixture-password', gen_salt('bf')), now(),
|
|
'{"provider":"email","providers":["email"]}'::jsonb, '{}'::jsonb, now(), now()
|
|
),
|
|
(
|
|
'38000000-0000-4000-8000-000000000002', 'authenticated', 'authenticated',
|
|
'meeting-doc-lease-free@example.invalid', crypt('fixture-password', gen_salt('bf')), now(),
|
|
'{"provider":"email","providers":["email"]}'::jsonb, '{}'::jsonb, now(), now()
|
|
),
|
|
(
|
|
'38000000-0000-4000-8000-000000000003', 'authenticated', 'authenticated',
|
|
'meeting-doc-lease-unlimited@example.invalid', crypt('fixture-password', gen_salt('bf')), now(),
|
|
'{"provider":"email","providers":["email"]}'::jsonb, '{}'::jsonb, now(), now()
|
|
);
|
|
|
|
UPDATE public.subscriptions SET tier = 'pro', status = 'active', overage_credits = 0
|
|
WHERE user_id = '38000000-0000-4000-8000-000000000001';
|
|
UPDATE public.subscriptions SET tier = 'free', status = 'active', overage_credits = 0
|
|
WHERE user_id = '38000000-0000-4000-8000-000000000002';
|
|
UPDATE public.subscriptions SET tier = 'pro_plus', status = 'active', overage_credits = 0
|
|
WHERE user_id = '38000000-0000-4000-8000-000000000003';
|
|
|
|
INSERT INTO public.meetings (id, user_id, title, status, raw_transcript)
|
|
VALUES
|
|
('38100000-0000-4000-8000-000000000001', '38000000-0000-4000-8000-000000000001',
|
|
'Lease fixture meeting', 'completed', 'Speaker one talked about the roadmap.'),
|
|
('38100000-0000-4000-8000-000000000002', '38000000-0000-4000-8000-000000000002',
|
|
'Lease fixture meeting', 'completed', 'Speaker two talked about hiring.'),
|
|
('38100000-0000-4000-8000-000000000003', '38000000-0000-4000-8000-000000000003',
|
|
'Lease fixture meeting', 'completed', 'Speaker three talked about budgets.');
|
|
|
|
INSERT INTO public.user_templates (
|
|
id, user_id, template_kind, name, template_type, system_prompt, is_builtin
|
|
) VALUES
|
|
('38200000-0000-4000-8000-000000000001', '38000000-0000-4000-8000-000000000001',
|
|
'meeting_document', 'Lease fixture template', 'custom', 'Summarize the meeting.', false),
|
|
('38200000-0000-4000-8000-000000000002', '38000000-0000-4000-8000-000000000002',
|
|
'meeting_document', 'Lease fixture template', 'custom', 'Summarize the meeting.', false),
|
|
('38200000-0000-4000-8000-000000000003', '38000000-0000-4000-8000-000000000003',
|
|
'meeting_document', 'Lease fixture template', 'custom', 'Summarize the meeting.', false);
|
|
|
|
-- Pro user, one daily Opus unit left (49/50).
|
|
INSERT INTO public.daily_usage (user_id, date, feature, count)
|
|
VALUES ('38000000-0000-4000-8000-000000000001', CURRENT_DATE, 'llm_opus', 49);
|
|
|
|
-- 1. A running document holds the last unit against llm-proxy, and its commit
|
|
-- is not thrown away afterwards (the reported bug).
|
|
DO $$
|
|
DECLARE
|
|
actor constant uuid := '38000000-0000-4000-8000-000000000001';
|
|
meeting constant uuid := '38100000-0000-4000-8000-000000000001';
|
|
template constant uuid := '38200000-0000-4000-8000-000000000001';
|
|
opus constant text := 'claude-opus-4-6';
|
|
claim jsonb;
|
|
proxy jsonb;
|
|
committed jsonb;
|
|
request_row public.meeting_document_generation_requests;
|
|
BEGIN
|
|
claim := pg_temp.try_claim(actor, '38300000-0000-4000-8000-000000000001', meeting, template, opus);
|
|
PERFORM pg_temp.assert_true((claim->>'claimed')::boolean, 'last Opus unit can be claimed: ' || claim::text);
|
|
|
|
SELECT * INTO request_row FROM public.meeting_document_generation_requests
|
|
WHERE user_id = actor AND idempotency_key = '38300000-0000-4000-8000-000000000001';
|
|
PERFORM pg_temp.assert_true(request_row.llm_reservation_id IS NOT NULL,
|
|
'the claim records the LLM quota lease it holds');
|
|
PERFORM pg_temp.assert_true(pg_temp.usage_of(actor, 'llm_opus') = 50,
|
|
'the in-flight claim is visible in the shared ledger');
|
|
|
|
-- The bug: llm-proxy used to see 49/50 here and reserve a second paid call.
|
|
proxy := public.reserve_llm_quota(actor, gen_random_uuid(), 'llm_opus', 50, 'daily');
|
|
PERFORM pg_temp.assert_true(NOT (proxy->>'allowed')::boolean,
|
|
'llm-proxy cannot take the unit a running document holds: ' || proxy::text);
|
|
|
|
committed := pg_temp.try_commit(actor, '38300000-0000-4000-8000-000000000001');
|
|
PERFORM pg_temp.assert_true(committed->>'error' IS NULL AND committed->'document' IS NOT NULL,
|
|
'the paid document is committed, not rejected: ' || committed::text);
|
|
PERFORM pg_temp.assert_true(committed->>'consumedFrom' = 'base', 'commit reports the base allowance');
|
|
PERFORM pg_temp.assert_true(pg_temp.usage_of(actor, 'llm_opus') = 50,
|
|
'commit completes the lease without charging a second unit');
|
|
PERFORM pg_temp.assert_true(
|
|
(SELECT status FROM public.llm_quota_reservations WHERE id = request_row.llm_reservation_id) = 'completed',
|
|
'commit completes the lease');
|
|
|
|
-- Idempotent commit replay does not charge again.
|
|
committed := pg_temp.try_commit(actor, '38300000-0000-4000-8000-000000000001');
|
|
PERFORM pg_temp.assert_true((committed->>'idempotent')::boolean, 'commit replay is idempotent');
|
|
PERFORM pg_temp.assert_true(pg_temp.usage_of(actor, 'llm_opus') = 50, 'commit replay charges nothing');
|
|
END;
|
|
$$;
|
|
|
|
-- 2. The reverse order: an llm-proxy reservation holds the last unit, so the
|
|
-- document claim is rejected before any provider work.
|
|
UPDATE public.daily_usage SET count = 49
|
|
WHERE user_id = '38000000-0000-4000-8000-000000000001' AND date = CURRENT_DATE AND feature = 'llm_opus';
|
|
|
|
DO $$
|
|
DECLARE
|
|
actor constant uuid := '38000000-0000-4000-8000-000000000001';
|
|
meeting constant uuid := '38100000-0000-4000-8000-000000000001';
|
|
template constant uuid := '38200000-0000-4000-8000-000000000001';
|
|
proxy_id constant uuid := '38500000-0000-4000-8000-000000000001';
|
|
proxy jsonb;
|
|
claim jsonb;
|
|
BEGIN
|
|
proxy := public.reserve_llm_quota(actor, proxy_id, 'llm_opus', 50, 'daily');
|
|
PERFORM pg_temp.assert_true((proxy->>'allowed')::boolean, 'llm-proxy takes the last unit');
|
|
|
|
claim := pg_temp.try_claim(actor, '38300000-0000-4000-8000-000000000002', meeting, template, 'claude-opus-4-6');
|
|
PERFORM pg_temp.assert_true(claim->>'error' = 'generation_quota_exceeded',
|
|
'a document claim cannot take the unit llm-proxy holds: ' || claim::text);
|
|
PERFORM pg_temp.assert_true(NOT EXISTS (
|
|
SELECT 1 FROM public.meeting_document_generation_requests
|
|
WHERE user_id = actor AND idempotency_key = '38300000-0000-4000-8000-000000000002'
|
|
), 'a rejected claim leaves no request row');
|
|
|
|
-- Once llm-proxy releases its lease, the document can be claimed.
|
|
PERFORM public.finalize_llm_quota(proxy_id, false);
|
|
claim := pg_temp.try_claim(actor, '38300000-0000-4000-8000-000000000002', meeting, template, 'claude-opus-4-6');
|
|
PERFORM pg_temp.assert_true((claim->>'claimed')::boolean, 'released unit can be claimed: ' || claim::text);
|
|
|
|
-- Replaying the in-flight key neither reserves again nor errors.
|
|
claim := pg_temp.try_claim(actor, '38300000-0000-4000-8000-000000000002', meeting, template, 'claude-opus-4-6');
|
|
PERFORM pg_temp.assert_true(
|
|
claim->>'error' IS NULL AND NOT (claim->>'claimed')::boolean AND claim->>'status' = 'processing',
|
|
'replaying the in-flight key reports processing: ' || claim::text);
|
|
PERFORM pg_temp.assert_true(pg_temp.usage_of(actor, 'llm_opus') = 50, 'a replay holds no extra unit');
|
|
|
|
-- Failure releases the unit back to the shared ledger, once.
|
|
PERFORM public.fail_meeting_document_generation_v1(actor, '38300000-0000-4000-8000-000000000002', 'provider_timeout');
|
|
PERFORM public.fail_meeting_document_generation_v1(actor, '38300000-0000-4000-8000-000000000002', 'provider_timeout');
|
|
PERFORM pg_temp.assert_true(pg_temp.usage_of(actor, 'llm_opus') = 49,
|
|
'failing a claim releases exactly one unit');
|
|
proxy := public.reserve_llm_quota(actor, gen_random_uuid(), 'llm_opus', 50, 'daily');
|
|
PERFORM pg_temp.assert_true((proxy->>'allowed')::boolean, 'the released unit is usable by llm-proxy');
|
|
END;
|
|
$$;
|
|
|
|
-- 3. Interleaved burst: document claims and llm-proxy reservations together
|
|
-- never exceed the remaining allowance, and one overage credit is spent once.
|
|
UPDATE public.daily_usage SET count = 45
|
|
WHERE user_id = '38000000-0000-4000-8000-000000000001' AND date = CURRENT_DATE AND feature = 'llm_opus';
|
|
UPDATE public.llm_quota_reservations SET status = 'completed'
|
|
WHERE user_id = '38000000-0000-4000-8000-000000000001' AND status = 'reserved';
|
|
UPDATE public.subscriptions SET overage_credits = 1
|
|
WHERE user_id = '38000000-0000-4000-8000-000000000001';
|
|
|
|
DO $$
|
|
DECLARE
|
|
actor constant uuid := '38000000-0000-4000-8000-000000000001';
|
|
meeting constant uuid := '38100000-0000-4000-8000-000000000001';
|
|
template constant uuid := '38200000-0000-4000-8000-000000000001';
|
|
granted integer := 0;
|
|
outcome jsonb;
|
|
i integer;
|
|
BEGIN
|
|
FOR i IN 1..10 LOOP
|
|
IF i % 2 = 0 THEN
|
|
outcome := public.reserve_llm_quota(actor, gen_random_uuid(), 'llm_opus', 50, 'daily');
|
|
IF (outcome->>'allowed')::boolean THEN granted := granted + 1; END IF;
|
|
ELSE
|
|
outcome := pg_temp.try_claim(actor, gen_random_uuid(), meeting, template, 'claude-opus-4-6');
|
|
IF coalesce((outcome->>'claimed')::boolean, false) THEN granted := granted + 1; END IF;
|
|
END IF;
|
|
END LOOP;
|
|
PERFORM pg_temp.assert_true(granted = 6,
|
|
'5 base units + 1 overage credit admit exactly 6 paid calls, got ' || granted);
|
|
PERFORM pg_temp.assert_true(pg_temp.usage_of(actor, 'llm_opus') = 51, 'shared ledger records every admitted call');
|
|
PERFORM pg_temp.assert_true(
|
|
(SELECT overage_credits FROM public.subscriptions WHERE user_id = actor) = 0,
|
|
'the overage credit is spent once');
|
|
END;
|
|
$$;
|
|
|
|
-- 4. Lease handling: an expired claim lease stops holding its unit, and a late
|
|
-- commit re-checks the allowance instead of charging past it.
|
|
DO $$
|
|
DECLARE
|
|
actor constant uuid := '38000000-0000-4000-8000-000000000002';
|
|
meeting constant uuid := '38100000-0000-4000-8000-000000000002';
|
|
template constant uuid := '38200000-0000-4000-8000-000000000002';
|
|
haiku constant text := 'claude-haiku-4-5-20251001';
|
|
claim jsonb;
|
|
proxy jsonb;
|
|
committed jsonb;
|
|
late_id uuid;
|
|
BEGIN
|
|
INSERT INTO public.daily_usage (user_id, date, feature, count)
|
|
VALUES (actor, CURRENT_DATE - 3, 'llm_haiku', 249);
|
|
|
|
claim := pg_temp.try_claim(actor, '38300000-0000-4000-8000-000000000010', meeting, template, haiku);
|
|
PERFORM pg_temp.assert_true((claim->>'claimed')::boolean, 'last weekly Haiku unit can be claimed');
|
|
|
|
-- Crashed worker: its lease expires, and the next reservation reclaims it.
|
|
SELECT llm_reservation_id INTO late_id FROM public.meeting_document_generation_requests
|
|
WHERE user_id = actor AND idempotency_key = '38300000-0000-4000-8000-000000000010';
|
|
UPDATE public.llm_quota_reservations SET lease_expires_at = now() - interval '1 minute' WHERE id = late_id;
|
|
|
|
proxy := public.reserve_llm_quota(actor, gen_random_uuid(), 'llm_haiku', 250, 'weekly');
|
|
PERFORM pg_temp.assert_true((proxy->>'allowed')::boolean,
|
|
'an expired document lease no longer holds a unit: ' || proxy::text);
|
|
|
|
-- The late commit finds its lease released and the allowance spent: reject
|
|
-- rather than charge a unit that is no longer there.
|
|
committed := pg_temp.try_commit(actor, '38300000-0000-4000-8000-000000000010');
|
|
PERFORM pg_temp.assert_true(committed->>'error' = 'generation_quota_exceeded',
|
|
'a late commit past the allowance is rejected: ' || committed::text);
|
|
|
|
-- With an overage credit the late commit is charged again and succeeds.
|
|
UPDATE public.subscriptions SET overage_credits = 1 WHERE user_id = actor;
|
|
committed := pg_temp.try_commit(actor, '38300000-0000-4000-8000-000000000010');
|
|
PERFORM pg_temp.assert_true(committed->>'error' IS NULL AND committed->>'consumedFrom' = 'overage',
|
|
'a late commit re-charges through the shared ledger: ' || committed::text);
|
|
PERFORM pg_temp.assert_true(
|
|
(SELECT overage_credits FROM public.subscriptions WHERE user_id = actor) = 0,
|
|
'the late commit spent the overage credit');
|
|
PERFORM pg_temp.assert_true(
|
|
(SELECT sum(count) FROM public.daily_usage WHERE user_id = actor AND feature = 'llm_haiku') = 251,
|
|
'the late commit is recorded once');
|
|
END;
|
|
$$;
|
|
|
|
-- 5. Claims made before this migration (no lease) still commit through the
|
|
-- shared ledger, and fail without touching it.
|
|
DO $$
|
|
DECLARE
|
|
actor constant uuid := '38000000-0000-4000-8000-000000000003';
|
|
meeting constant uuid := '38100000-0000-4000-8000-000000000003';
|
|
template constant uuid := '38200000-0000-4000-8000-000000000003';
|
|
lease uuid;
|
|
claim jsonb;
|
|
committed jsonb;
|
|
BEGIN
|
|
claim := pg_temp.try_claim(actor, '38300000-0000-4000-8000-000000000020', meeting, template, 'claude-sonnet-4-6');
|
|
PERFORM pg_temp.assert_true((claim->>'claimed')::boolean, 'pro_plus Sonnet claim');
|
|
|
|
-- Turn it into a legacy claim: no lease, nothing recorded yet.
|
|
SELECT llm_reservation_id INTO lease FROM public.meeting_document_generation_requests
|
|
WHERE user_id = actor AND idempotency_key = '38300000-0000-4000-8000-000000000020';
|
|
UPDATE public.meeting_document_generation_requests SET llm_reservation_id = NULL
|
|
WHERE user_id = actor AND idempotency_key = '38300000-0000-4000-8000-000000000020';
|
|
PERFORM public.finalize_llm_quota(lease, false);
|
|
PERFORM pg_temp.assert_true(pg_temp.usage_of(actor, 'llm_sonnet') = 0, 'legacy claim holds nothing');
|
|
|
|
committed := pg_temp.try_commit(actor, '38300000-0000-4000-8000-000000000020');
|
|
PERFORM pg_temp.assert_true(committed->>'error' IS NULL AND committed->>'consumedFrom' = 'base',
|
|
'a legacy claim commits: ' || committed::text);
|
|
PERFORM pg_temp.assert_true(pg_temp.usage_of(actor, 'llm_sonnet') = 1, 'a legacy commit records one unit');
|
|
|
|
-- Legacy failure is a no-op on the ledger.
|
|
claim := pg_temp.try_claim(actor, '38300000-0000-4000-8000-000000000021', meeting, template, 'claude-sonnet-4-6');
|
|
SELECT llm_reservation_id INTO lease FROM public.meeting_document_generation_requests
|
|
WHERE user_id = actor AND idempotency_key = '38300000-0000-4000-8000-000000000021';
|
|
UPDATE public.meeting_document_generation_requests SET llm_reservation_id = NULL
|
|
WHERE user_id = actor AND idempotency_key = '38300000-0000-4000-8000-000000000021';
|
|
PERFORM public.finalize_llm_quota(lease, false);
|
|
PERFORM public.fail_meeting_document_generation_v1(actor, '38300000-0000-4000-8000-000000000021', 'provider_timeout');
|
|
PERFORM pg_temp.assert_true(pg_temp.usage_of(actor, 'llm_sonnet') = 1, 'a legacy failure changes nothing');
|
|
|
|
-- Unlimited allowances are never throttled and still release on failure.
|
|
claim := pg_temp.try_claim(actor, '38300000-0000-4000-8000-000000000022', meeting, template, 'claude-haiku-4-5-20251001');
|
|
PERFORM pg_temp.assert_true((claim->>'claimed')::boolean, 'unlimited Haiku claim');
|
|
claim := pg_temp.try_claim(actor, '38300000-0000-4000-8000-000000000023', meeting, template, 'claude-haiku-4-5-20251001');
|
|
PERFORM pg_temp.assert_true((claim->>'claimed')::boolean, 'unlimited allowances are not throttled');
|
|
PERFORM public.fail_meeting_document_generation_v1(actor, '38300000-0000-4000-8000-000000000023', 'provider_timeout');
|
|
PERFORM pg_temp.assert_true(pg_temp.usage_of(actor, 'llm_haiku') = 1, 'unlimited failure releases its unit');
|
|
END;
|
|
$$;
|
|
|
|
ROLLBACK;
|