import { describe, expect, it } from "@effect/vitest";import { EnvironmentId, ThreadId } from "@t3tools/contracts";import type { RelayAgentActivityAggregateState } from "@t3tools/contracts/relay";import * as Redacted from "effect/Redacted"; import { makeApnsDeliveryJobPayload, signApnsDeliveryJob, verifySignedApnsDeliveryJob,} from "./apnsDeliveryJobs.ts"; const secret = Redacted.make("queue-signing-secret");const aggregate: RelayAgentActivityAggregateState = { title: "T3 Code", subtitle: "Agent work in progress", activeCount: 1, updatedAt: "2026-05-25T00:00:00.000Z", activities: [ { environmentId: EnvironmentId.make("env"), threadId: ThreadId.make("thread"), projectTitle: "Project", threadTitle: "Thread", modelTitle: "gpt-5.4", phase: "running", status: "Working", updatedAt: "2026-05-25T00:00:00.000Z", deepLink: "/threads/env/thread", }, ],}; const notification = { title: "Thread", body: "Input: Project", environmentId: "env", threadId: "thread", deepLink: "/threads/env/thread",}; describe("apnsDeliveryJobs", () => { it("rejects tampered signed queue jobs", () => { const payload = makeApnsDeliveryJobPayload({ kind: "live_activity_end", userId: "user-1", deviceId: "device-1", token: "token-1", aggregate: null, createdAt: "2026-05-25T00:00:00.000Z", expiresAt: "2026-05-25T00:05:00.000Z", jobId: "job-1", }); const signed = signApnsDeliveryJob({ secret, payload }); const tampered = { ...signed, payload: { ...signed.payload, target: { ...signed.payload.target, token: "attacker-token", }, }, }; const result = verifySignedApnsDeliveryJob({ secret, job: tampered, nowMs: 0, }); expect(result).toMatchObject({ _tag: "ApnsDeliveryJobSignatureInvalid", jobId: "job-1", kind: "live_activity_end", userId: "user-1", deviceId: "device-1", message: "Invalid signature for APNs delivery job job-1.", }); }); it("rejects Live Activity start jobs without aggregate state", () => { const payload = makeApnsDeliveryJobPayload({ kind: "live_activity_start", userId: "user-1", deviceId: "device-1", token: "token-1", aggregate: null, createdAt: "2026-05-25T00:00:00.000Z", expiresAt: "2026-05-25T00:05:00.000Z", jobId: "job-start-invalid", }); const signed = signApnsDeliveryJob({ secret, payload }); const result = verifySignedApnsDeliveryJob({ secret, job: signed, nowMs: 0, }); expect(result).toMatchObject({ _tag: "ApnsDeliveryJobLiveActivityAggregateMissing", jobId: "job-start-invalid", kind: "live_activity_start", userId: "user-1", deviceId: "device-1", message: "APNs live activity start job job-start-invalid requires an aggregate.", }); }); it("rejects push notification jobs carrying aggregate state", () => { const payload = makeApnsDeliveryJobPayload({ kind: "push_notification", userId: "user-1", deviceId: "device-1", token: "token-1", aggregate, notification, createdAt: "2026-05-25T00:00:00.000Z", expiresAt: "2026-05-25T00:05:00.000Z", jobId: "job-push-invalid", }); const signed = signApnsDeliveryJob({ secret, payload }); const result = verifySignedApnsDeliveryJob({ secret, job: signed, nowMs: 0, }); expect(result).toMatchObject({ _tag: "ApnsDeliveryJobPushNotificationAggregateUnexpected", jobId: "job-push-invalid", userId: "user-1", deviceId: "device-1", message: "APNs push notification job job-push-invalid must not carry aggregate state.", }); }); it("accepts minimal kind-specific signed queue jobs", () => { const pushPayload = makeApnsDeliveryJobPayload({ kind: "push_notification", userId: "user-1", deviceId: "device-1", token: "token-1", aggregate: null, notification, createdAt: "2026-05-25T00:00:00.000Z", expiresAt: "2026-05-25T00:05:00.000Z", jobId: "job-push-valid", }); const liveActivityPayload = makeApnsDeliveryJobPayload({ kind: "live_activity_update", userId: "user-1", deviceId: "device-1", token: "token-1", aggregate, createdAt: "2026-05-25T00:00:00.000Z", expiresAt: "2026-05-25T00:05:00.000Z", jobId: "job-live-valid", }); expect( verifySignedApnsDeliveryJob({ secret, job: signApnsDeliveryJob({ secret, payload: pushPayload }), nowMs: 0, }), ).toEqual(pushPayload); expect( verifySignedApnsDeliveryJob({ secret, job: signApnsDeliveryJob({ secret, payload: liveActivityPayload }), nowMs: 0, }), ).toEqual(liveActivityPayload); }); it("rejects jobs with invalid or overlong time windows", () => { const basePayload = makeApnsDeliveryJobPayload({ kind: "live_activity_end", userId: "user-1", deviceId: "device-1", token: "token-1", aggregate: null, createdAt: "2026-05-25T00:00:00.000Z", expiresAt: "2026-05-25T00:10:00.000Z", jobId: "job-window", }); const invalidCreatedAt = { ...basePayload, createdAt: "not-a-date", }; const invertedWindow = { ...basePayload, expiresAt: "2026-05-24T23:59:59.000Z", }; const overlongWindow = { ...basePayload, expiresAt: "2026-05-25T00:10:01.000Z", }; expect( verifySignedApnsDeliveryJob({ secret, job: signApnsDeliveryJob({ secret, payload: invalidCreatedAt }), nowMs: 0, }), ).toMatchObject({ _tag: "ApnsDeliveryJobCreatedAtInvalid", jobId: "job-window", kind: "live_activity_end", userId: "user-1", deviceId: "device-1", createdAt: "not-a-date", message: "APNs delivery job job-window has invalid creation time not-a-date.", }); expect( verifySignedApnsDeliveryJob({ secret, job: signApnsDeliveryJob({ secret, payload: invertedWindow }), nowMs: 0, }), ).toMatchObject({ _tag: "ApnsDeliveryJobTimeWindowInvalid", jobId: "job-window", kind: "live_activity_end", userId: "user-1", deviceId: "device-1", createdAt: "2026-05-25T00:00:00.000Z", expiresAt: "2026-05-24T23:59:59.000Z", message: "APNs delivery job job-window has invalid time window 2026-05-25T00:00:00.000Z to 2026-05-24T23:59:59.000Z.", }); expect( verifySignedApnsDeliveryJob({ secret, job: signApnsDeliveryJob({ secret, payload: overlongWindow }), nowMs: 0, }), ).toMatchObject({ _tag: "ApnsDeliveryJobTimeWindowTooLong", jobId: "job-window", kind: "live_activity_end", userId: "user-1", deviceId: "device-1", createdAt: "2026-05-25T00:00:00.000Z", expiresAt: "2026-05-25T00:10:01.000Z", message: "APNs delivery job job-window time window 2026-05-25T00:00:00.000Z to 2026-05-25T00:10:01.000Z is too long.", }); });});
import { describe, expect, it } from "@effect/vitest";
import { EnvironmentId, ThreadId } from "@t3tools/contracts";
import type { RelayAgentActivityAggregateState } from "@t3tools/contracts/relay";
import * as Redacted from "effect/Redacted";
import {
makeApnsDeliveryJobPayload,
signApnsDeliveryJob,
verifySignedApnsDeliveryJob,
} from "./apnsDeliveryJobs.ts";
const secret = Redacted.make("queue-signing-secret");
const aggregate: RelayAgentActivityAggregateState = {
title: "T3 Code",
subtitle: "Agent work in progress",
activeCount: 1,
updatedAt: "2026-05-25T00:00:00.000Z",
activities: [
{
environmentId: EnvironmentId.make("env"),
threadId: ThreadId.make("thread"),
projectTitle: "Project",
threadTitle: "Thread",
modelTitle: "gpt-5.4",
phase: "running",
status: "Working",
updatedAt: "2026-05-25T00:00:00.000Z",
deepLink: "/threads/env/thread",
},
],
};
const notification = {
title: "Thread",
body: "Input: Project",
environmentId: "env",
threadId: "thread",
deepLink: "/threads/env/thread",
};
describe("apnsDeliveryJobs", () => {
it("rejects tampered signed queue jobs", () => {
const payload = makeApnsDeliveryJobPayload({
kind: "live_activity_end",
userId: "user-1",
deviceId: "device-1",
token: "token-1",
aggregate: null,
createdAt: "2026-05-25T00:00:00.000Z",
expiresAt: "2026-05-25T00:05:00.000Z",
jobId: "job-1",
});
const signed = signApnsDeliveryJob({ secret, payload });
const tampered = {
...signed,
payload: {
...signed.payload,
target: {
...signed.payload.target,
token: "attacker-token",
},
},
};
const result = verifySignedApnsDeliveryJob({
secret,
job: tampered,
nowMs: 0,
});
expect(result).toMatchObject({
_tag: "ApnsDeliveryJobSignatureInvalid",
jobId: "job-1",
kind: "live_activity_end",
userId: "user-1",
deviceId: "device-1",
message: "Invalid signature for APNs delivery job job-1.",
});
});
it("rejects Live Activity start jobs without aggregate state", () => {
const payload = makeApnsDeliveryJobPayload({
kind: "live_activity_start",
userId: "user-1",
deviceId: "device-1",
token: "token-1",
aggregate: null,
createdAt: "2026-05-25T00:00:00.000Z",
expiresAt: "2026-05-25T00:05:00.000Z",
jobId: "job-start-invalid",
});
const signed = signApnsDeliveryJob({ secret, payload });
const result = verifySignedApnsDeliveryJob({
secret,
job: signed,
nowMs: 0,
});
expect(result).toMatchObject({
_tag: "ApnsDeliveryJobLiveActivityAggregateMissing",
jobId: "job-start-invalid",
kind: "live_activity_start",
userId: "user-1",
deviceId: "device-1",
message: "APNs live activity start job job-start-invalid requires an aggregate.",
});
});
it("rejects push notification jobs carrying aggregate state", () => {
const payload = makeApnsDeliveryJobPayload({
kind: "push_notification",
userId: "user-1",
deviceId: "device-1",
token: "token-1",
aggregate,
notification,
createdAt: "2026-05-25T00:00:00.000Z",
expiresAt: "2026-05-25T00:05:00.000Z",
jobId: "job-push-invalid",
});
const signed = signApnsDeliveryJob({ secret, payload });
const result = verifySignedApnsDeliveryJob({
secret,
job: signed,
nowMs: 0,
});
expect(result).toMatchObject({
_tag: "ApnsDeliveryJobPushNotificationAggregateUnexpected",
jobId: "job-push-invalid",
userId: "user-1",
deviceId: "device-1",
message: "APNs push notification job job-push-invalid must not carry aggregate state.",
});
});
it("accepts minimal kind-specific signed queue jobs", () => {
const pushPayload = makeApnsDeliveryJobPayload({
kind: "push_notification",
userId: "user-1",
deviceId: "device-1",
token: "token-1",
aggregate: null,
notification,
createdAt: "2026-05-25T00:00:00.000Z",
expiresAt: "2026-05-25T00:05:00.000Z",
jobId: "job-push-valid",
});
const liveActivityPayload = makeApnsDeliveryJobPayload({
kind: "live_activity_update",
userId: "user-1",
deviceId: "device-1",
token: "token-1",
aggregate,
createdAt: "2026-05-25T00:00:00.000Z",
expiresAt: "2026-05-25T00:05:00.000Z",
jobId: "job-live-valid",
});
expect(
verifySignedApnsDeliveryJob({
secret,
job: signApnsDeliveryJob({ secret, payload: pushPayload }),
nowMs: 0,
}),
).toEqual(pushPayload);
expect(
verifySignedApnsDeliveryJob({
secret,
job: signApnsDeliveryJob({ secret, payload: liveActivityPayload }),
nowMs: 0,
}),
).toEqual(liveActivityPayload);
});
it("rejects jobs with invalid or overlong time windows", () => {
const basePayload = makeApnsDeliveryJobPayload({
kind: "live_activity_end",
userId: "user-1",
deviceId: "device-1",
token: "token-1",
aggregate: null,
createdAt: "2026-05-25T00:00:00.000Z",
expiresAt: "2026-05-25T00:10:00.000Z",
jobId: "job-window",
});
const invalidCreatedAt = {
...basePayload,
createdAt: "not-a-date",
};
const invertedWindow = {
...basePayload,
expiresAt: "2026-05-24T23:59:59.000Z",
};
const overlongWindow = {
...basePayload,
expiresAt: "2026-05-25T00:10:01.000Z",
};
expect(
verifySignedApnsDeliveryJob({
secret,
job: signApnsDeliveryJob({ secret, payload: invalidCreatedAt }),
nowMs: 0,
}),
).toMatchObject({
_tag: "ApnsDeliveryJobCreatedAtInvalid",
jobId: "job-window",
kind: "live_activity_end",
userId: "user-1",
deviceId: "device-1",
createdAt: "not-a-date",
message: "APNs delivery job job-window has invalid creation time not-a-date.",
});
expect(
verifySignedApnsDeliveryJob({
secret,
job: signApnsDeliveryJob({ secret, payload: invertedWindow }),
nowMs: 0,
}),
).toMatchObject({
_tag: "ApnsDeliveryJobTimeWindowInvalid",
jobId: "job-window",
kind: "live_activity_end",
userId: "user-1",
deviceId: "device-1",
createdAt: "2026-05-25T00:00:00.000Z",
expiresAt: "2026-05-24T23:59:59.000Z",
message:
"APNs delivery job job-window has invalid time window 2026-05-25T00:00:00.000Z to 2026-05-24T23:59:59.000Z.",
});
expect(
verifySignedApnsDeliveryJob({
secret,
job: signApnsDeliveryJob({ secret, payload: overlongWindow }),
nowMs: 0,
}),
).toMatchObject({
_tag: "ApnsDeliveryJobTimeWindowTooLong",
jobId: "job-window",
kind: "live_activity_end",
userId: "user-1",
deviceId: "device-1",
createdAt: "2026-05-25T00:00:00.000Z",
expiresAt: "2026-05-25T00:10:01.000Z",
message:
"APNs delivery job job-window time window 2026-05-25T00:00:00.000Z to 2026-05-25T00:10:01.000Z is too long.",
});
});
});