feat(release): prepare 1.1.0 candidate
This commit is contained in:
parent
5a34f66981
commit
5205dcdfa9
736 changed files with 115667 additions and 12203 deletions
192
server/supabase/tests/mobile-runtime-integrity.integration.sql
Normal file
192
server/supabase/tests/mobile-runtime-integrity.integration.sql
Normal file
|
|
@ -0,0 +1,192 @@
|
|||
\set ON_ERROR_STOP on
|
||||
|
||||
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;
|
||||
$$;
|
||||
|
||||
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
|
||||
(
|
||||
'20000000-0000-4000-8000-000000000001', 'authenticated', 'authenticated',
|
||||
'runtime-one@example.invalid', crypt('fixture-password', gen_salt('bf')), now(),
|
||||
'{"provider":"email","providers":["email"]}'::jsonb, '{}'::jsonb, now(), now()
|
||||
),
|
||||
(
|
||||
'20000000-0000-4000-8000-000000000002', 'authenticated', 'authenticated',
|
||||
'runtime-two@example.invalid', crypt('fixture-password', gen_salt('bf')), now(),
|
||||
'{"provider":"email","providers":["email"]}'::jsonb, '{}'::jsonb, now(), now()
|
||||
);
|
||||
|
||||
UPDATE public.subscriptions
|
||||
SET tier = 'free', status = 'active', overage_credits = 0
|
||||
WHERE user_id IN (
|
||||
'20000000-0000-4000-8000-000000000001',
|
||||
'20000000-0000-4000-8000-000000000002'
|
||||
);
|
||||
|
||||
SELECT pg_temp.assert_true(
|
||||
NOT has_function_privilege(
|
||||
'authenticated',
|
||||
'public.grant_verified_ad_reward(uuid,text,text,text,text,integer)',
|
||||
'EXECUTE'
|
||||
),
|
||||
'authenticated users must not grant their own ad rewards'
|
||||
);
|
||||
SELECT pg_temp.assert_true(
|
||||
NOT has_table_privilege('authenticated', 'public.ad_reward_receipts', 'SELECT'),
|
||||
'authenticated users must not read verified ad callback receipts'
|
||||
);
|
||||
SELECT pg_temp.assert_true(
|
||||
has_function_privilege('authenticated', 'public.mobile_dashboard_stats()', 'EXECUTE'),
|
||||
'authenticated users must be able to read their dashboard aggregate'
|
||||
);
|
||||
SELECT pg_temp.assert_true(
|
||||
NOT has_function_privilege('anon', 'public.mobile_dashboard_stats()', 'EXECUTE'),
|
||||
'anonymous users must not execute dashboard aggregates'
|
||||
);
|
||||
|
||||
DO $$
|
||||
DECLARE
|
||||
first_claim jsonb;
|
||||
duplicate_claim jsonb;
|
||||
cooldown_claim jsonb;
|
||||
cooldown_replay jsonb;
|
||||
capped_claim jsonb;
|
||||
balance integer;
|
||||
BEGIN
|
||||
first_claim := public.grant_verified_ad_reward(
|
||||
'20000000-0000-4000-8000-000000000001',
|
||||
'admob:fixture', 'rewarded_video_quota', '5224354917',
|
||||
'runtime-reward-transaction-0001', 50
|
||||
);
|
||||
PERFORM pg_temp.assert_true((first_claim->>'granted')::boolean, 'first reward is granted');
|
||||
|
||||
duplicate_claim := public.grant_verified_ad_reward(
|
||||
'20000000-0000-4000-8000-000000000001',
|
||||
'admob:fixture', 'rewarded_video_quota', '5224354917',
|
||||
'runtime-reward-transaction-0001', 50
|
||||
);
|
||||
PERFORM pg_temp.assert_true(
|
||||
duplicate_claim->>'reason' = 'duplicate',
|
||||
'transaction replay is idempotent'
|
||||
);
|
||||
|
||||
cooldown_claim := public.grant_verified_ad_reward(
|
||||
'20000000-0000-4000-8000-000000000001',
|
||||
'admob:fixture', 'rewarded_video_quota', '5224354917',
|
||||
'runtime-reward-transaction-0002', 50
|
||||
);
|
||||
PERFORM pg_temp.assert_true(
|
||||
cooldown_claim->>'reason' = 'cooldown',
|
||||
'distinct immediate callback is rate limited'
|
||||
);
|
||||
|
||||
cooldown_replay := public.grant_verified_ad_reward(
|
||||
'20000000-0000-4000-8000-000000000001',
|
||||
'admob:fixture', 'rewarded_video_quota', '5224354917',
|
||||
'runtime-reward-transaction-0002', 50
|
||||
);
|
||||
PERFORM pg_temp.assert_true(
|
||||
cooldown_replay->>'reason' = 'duplicate',
|
||||
'a cooldown receipt remains consumed and can never become grantable'
|
||||
);
|
||||
PERFORM pg_temp.assert_true(
|
||||
(SELECT count(*) FROM public.ad_reward_claims
|
||||
WHERE transaction_id = 'runtime-reward-transaction-0002') = 0,
|
||||
'a replayed cooldown receipt never creates a grant claim'
|
||||
);
|
||||
|
||||
SELECT overage_credits INTO balance FROM public.subscriptions
|
||||
WHERE user_id = '20000000-0000-4000-8000-000000000001';
|
||||
PERFORM pg_temp.assert_true(balance = 50, 'only one callback changes the balance');
|
||||
|
||||
INSERT INTO public.ad_reward_claims (
|
||||
user_id, network, placement, ad_unit_id, transaction_id, reward_tokens, verified_at
|
||||
)
|
||||
SELECT
|
||||
'20000000-0000-4000-8000-000000000002',
|
||||
'admob:fixture', 'rewarded_video_quota', '5224354917',
|
||||
'runtime-cap-' || lpad(number::text, 3, '0'), 50,
|
||||
date_trunc('day', now()) + (number * interval '20 seconds')
|
||||
FROM generate_series(1, 20) AS number;
|
||||
|
||||
capped_claim := public.grant_verified_ad_reward(
|
||||
'20000000-0000-4000-8000-000000000002',
|
||||
'admob:fixture', 'rewarded_video_quota', '5224354917',
|
||||
'runtime-cap-overflow-transaction', 50
|
||||
);
|
||||
PERFORM pg_temp.assert_true(
|
||||
capped_claim->>'reason' = 'daily_cap',
|
||||
'daily reward cap is enforced before another credit grant'
|
||||
);
|
||||
END;
|
||||
$$;
|
||||
|
||||
INSERT INTO public.history (
|
||||
id, user_id, title, original_text, mode, status, duration, word_count,
|
||||
app_version, created_at, updated_at
|
||||
) VALUES
|
||||
(
|
||||
'21000000-0000-4000-8000-000000000001',
|
||||
'20000000-0000-4000-8000-000000000001',
|
||||
'Today', 'today transcript', 'dictation', 'completed', 60, 10,
|
||||
'1.0.0', now(), now()
|
||||
),
|
||||
(
|
||||
'21000000-0000-4000-8000-000000000002',
|
||||
'20000000-0000-4000-8000-000000000001',
|
||||
'Yesterday', 'yesterday transcript', 'file-transcription', 'completed', 120, 20,
|
||||
'1.0.0', now() - interval '1 day', now() - interval '1 day'
|
||||
),
|
||||
(
|
||||
'21000000-0000-4000-8000-000000000003',
|
||||
'20000000-0000-4000-8000-000000000001',
|
||||
'Older', 'older transcript', 'dictation', 'completed', 30, 5,
|
||||
'1.0.0', now() - interval '3 days', now() - interval '3 days'
|
||||
),
|
||||
(
|
||||
'21000000-0000-4000-8000-000000000004',
|
||||
'20000000-0000-4000-8000-000000000001',
|
||||
'Error', 'failed transcript', 'dictation', 'error', 999, 999,
|
||||
'1.0.0', now(), now()
|
||||
),
|
||||
(
|
||||
'21000000-0000-4000-8000-000000000005',
|
||||
'20000000-0000-4000-8000-000000000002',
|
||||
'Other user', 'private transcript', 'dictation', 'completed', 500, 500,
|
||||
'1.0.0', now(), now()
|
||||
);
|
||||
|
||||
SET LOCAL ROLE authenticated;
|
||||
SELECT set_config(
|
||||
'request.jwt.claims',
|
||||
'{"sub":"20000000-0000-4000-8000-000000000001","role":"authenticated"}',
|
||||
true
|
||||
);
|
||||
|
||||
DO $$
|
||||
DECLARE
|
||||
stats jsonb := public.mobile_dashboard_stats();
|
||||
BEGIN
|
||||
PERFORM pg_temp.assert_true((stats->>'total_sessions')::integer = 3, 'completed own sessions counted');
|
||||
PERFORM pg_temp.assert_true((stats->>'total_recording_seconds')::numeric = 210, 'duration is exact');
|
||||
PERFORM pg_temp.assert_true((stats->>'total_word_count')::integer = 35, 'word count is exact');
|
||||
PERFORM pg_temp.assert_true((stats->>'today_sessions')::integer = 1, 'UTC today count is exact');
|
||||
PERFORM pg_temp.assert_true((stats->>'streak_days')::integer = 2, 'consecutive streak stops at gap');
|
||||
PERFORM pg_temp.assert_true(jsonb_array_length(stats->'recent_history') = 3, 'recent history excludes errors and other users');
|
||||
END;
|
||||
$$;
|
||||
|
||||
RESET ROLE;
|
||||
ROLLBACK;
|
||||
Loading…
Add table
Add a link
Reference in a new issue