feat(push): gate relay delivery on operator consent (#2984)

This commit is contained in:
Hampus
2026-09-27 20:33:10 +02:00
committed by GitHub
parent 336b8b7dcd
commit 01f53a168d
22 changed files with 1012 additions and 26 deletions
@@ -0,0 +1,89 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import {
DEFAULT_PUSH_SERVICE_DELIVERY_CONFIG,
type PushServiceDeliveryConfig,
PushServiceDeliveryConfigSchema,
PushServiceDeliveryConfigUpdateRequest,
pushServiceDeliveryEnrols,
} from '@fluxer/schema/src/domains/admin/PushServiceDeliverySchemas';
import {describe, expect, test} from 'vitest';
const ADMIN_USER_ID = '1500000000000000001';
const TARGETED_USER_ID = '1500000000000000002';
function createConfig(overrides: Partial<PushServiceDeliveryConfig> = {}): PushServiceDeliveryConfig {
return {
...DEFAULT_PUSH_SERVICE_DELIVERY_CONFIG,
included_user_ids: [],
excluded_user_ids: [],
...overrides,
};
}
describe('push service delivery relay consent', () => {
test('a stored configuration that predates relay consent reads back as not accepted', () => {
expect(
PushServiceDeliveryConfigSchema.parse({
enabled: true,
config_version: 4,
rollout_basis_points: 10000,
rollout_salt: 'push-service-delivery-v1',
included_user_ids: [],
excluded_user_ids: [],
}),
).toMatchObject({
relay_consent_accepted: false,
relay_consent_accepted_at: null,
relay_consent_accepted_by: null,
});
});
test('the defaults export carries the unaccepted consent', () => {
expect(DEFAULT_PUSH_SERVICE_DELIVERY_CONFIG.relay_consent_accepted).toBe(false);
expect(DEFAULT_PUSH_SERVICE_DELIVERY_CONFIG.relay_consent_accepted_at).toBeNull();
expect(DEFAULT_PUSH_SERVICE_DELIVERY_CONFIG.relay_consent_accepted_by).toBeNull();
});
test('an accepted consent round-trips through the stored schema', () => {
const accepted = {
...DEFAULT_PUSH_SERVICE_DELIVERY_CONFIG,
relay_consent_accepted: true,
relay_consent_accepted_at: '2026-09-27T10:11:12.000Z',
relay_consent_accepted_by: ADMIN_USER_ID,
};
expect(PushServiceDeliveryConfigSchema.parse(accepted)).toEqual(accepted);
});
test('the update request takes the consent flag on its own', () => {
expect(PushServiceDeliveryConfigUpdateRequest.parse({relay_consent_accepted: true})).toEqual({
relay_consent_accepted: true,
});
});
test('the update request refuses a client-supplied acceptance stamp', () => {
expect(
PushServiceDeliveryConfigUpdateRequest.parse({
relay_consent_accepted: true,
relay_consent_accepted_at: '2020-01-01T00:00:00.000Z',
relay_consent_accepted_by: ADMIN_USER_ID,
}),
).toEqual({relay_consent_accepted: true});
});
test.each([
{relay_consent_accepted_at: 'yesterday'},
{relay_consent_accepted_at: '2026-09-27'},
{relay_consent_accepted_by: 'not-an-id'},
{relay_consent_accepted: 'yes'},
])('rejects a malformed stored consent: %j', (value) => {
expect(PushServiceDeliveryConfigSchema.safeParse(value).success).toBe(false);
});
test('consent alone enrols nobody and refusing it excludes nobody', () => {
const withConsent = createConfig({enabled: false, relay_consent_accepted: true});
const withoutConsent = createConfig({enabled: true, rollout_basis_points: 10000});
expect(pushServiceDeliveryEnrols(withConsent, TARGETED_USER_ID)).toBe(false);
expect(pushServiceDeliveryEnrols(withoutConsent, TARGETED_USER_ID)).toBe(true);
});
});
@@ -21,6 +21,9 @@ const pushServiceDeliveryConfigFields = {
rollout_salt: z.string().trim().min(1).max(64).regex(PUSH_SERVICE_DELIVERY_SALT_PATTERN),
included_user_ids: PushServiceDeliveryTargetedUserIdsSchema,
excluded_user_ids: PushServiceDeliveryTargetedUserIdsSchema,
relay_consent_accepted: z.boolean(),
relay_consent_accepted_at: z.iso.datetime().nullable(),
relay_consent_accepted_by: PushServiceDeliveryTargetIdSchema.nullable(),
};
export const PushServiceDeliveryConfigSchema = z.object({
@@ -30,6 +33,9 @@ export const PushServiceDeliveryConfigSchema = z.object({
rollout_salt: pushServiceDeliveryConfigFields.rollout_salt.default(DEFAULT_PUSH_SERVICE_DELIVERY_SALT),
included_user_ids: pushServiceDeliveryConfigFields.included_user_ids.default([]),
excluded_user_ids: pushServiceDeliveryConfigFields.excluded_user_ids.default([]),
relay_consent_accepted: pushServiceDeliveryConfigFields.relay_consent_accepted.default(false),
relay_consent_accepted_at: pushServiceDeliveryConfigFields.relay_consent_accepted_at.default(null),
relay_consent_accepted_by: pushServiceDeliveryConfigFields.relay_consent_accepted_by.default(null),
});
export type PushServiceDeliveryConfig = z.infer<typeof PushServiceDeliveryConfigSchema>;
@@ -40,7 +46,7 @@ export const DEFAULT_PUSH_SERVICE_DELIVERY_CONFIG: PushServiceDeliveryConfig = P
export const PushServiceDeliveryConfigUpdateRequest = z
.object(pushServiceDeliveryConfigFields)
.omit({config_version: true})
.omit({config_version: true, relay_consent_accepted_at: true, relay_consent_accepted_by: true})
.partial();
export type PushServiceDeliveryConfigUpdateRequest = z.infer<typeof PushServiceDeliveryConfigUpdateRequest>;