authorgravatar for julius0216@outlook.comJulius Marminge <julius0216@outlook.com> 2026-09-18 11:13:18-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-09-18 11:13:18-07:00
log80c1f771b39674ada4d3724610f08fba855fdd49
tree58385b284a758e69a84ee325905468178f7cabd3
parent4c61e3d7ecc4d9957c243677d35dd3313a37c067
signature Signed by PGP key B5690EEEBB952194

fix(relay): accept delegated thread IDs in activity routes (#12484)


6 files changed, 1628 insertions(+), 11 deletions(-)

infra/relay/migrations/postgres/20260918175607_long_thread_ids/migration.sql created+2
...@@ -0,0 +1,2 @@
1ALTER TABLE "relay_agent_activity_rows" ALTER COLUMN "thread_id" SET DATA TYPE varchar(512) USING "thread_id"::varchar(512);--> statement-breakpoint
2ALTER TABLE "relay_delivery_attempts" ALTER COLUMN "thread_id" SET DATA TYPE varchar(512) USING "thread_id"::varchar(512);
\ No newline at end of file
infra/relay/migrations/postgres/20260918175607_long_thread_ids/snapshot.json created+1516
...@@ -0,0 +1,1516 @@
1{
2 "version": "8",
3 "dialect": "postgres",
4 "id": "4b6d0d21-8d78-4499-9dde-b42bcf633d05",
5 "prevIds": ["1109ed23-036c-4c39-a459-52422a7ffd99"],
6 "ddl": [
7 {
8 "isRlsEnabled": false,
9 "name": "relay_agent_activity_rows",
10 "entityType": "tables",
11 "schema": "public"
12 },
13 {
14 "isRlsEnabled": false,
15 "name": "relay_delivery_attempts",
16 "entityType": "tables",
17 "schema": "public"
18 },
19 {
20 "isRlsEnabled": false,
21 "name": "relay_dpop_proofs",
22 "entityType": "tables",
23 "schema": "public"
24 },
25 {
26 "isRlsEnabled": false,
27 "name": "relay_environment_credentials",
28 "entityType": "tables",
29 "schema": "public"
30 },
31 {
32 "isRlsEnabled": false,
33 "name": "relay_environment_links",
34 "entityType": "tables",
35 "schema": "public"
36 },
37 {
38 "isRlsEnabled": false,
39 "name": "relay_live_activities",
40 "entityType": "tables",
41 "schema": "public"
42 },
43 {
44 "isRlsEnabled": false,
45 "name": "relay_managed_endpoint_allocations",
46 "entityType": "tables",
47 "schema": "public"
48 },
49 {
50 "isRlsEnabled": false,
51 "name": "relay_managed_tunnel_limits",
52 "entityType": "tables",
53 "schema": "public"
54 },
55 {
56 "isRlsEnabled": false,
57 "name": "relay_mobile_devices",
58 "entityType": "tables",
59 "schema": "public"
60 },
61 {
62 "type": "varchar(191)",
63 "typeSchema": null,
64 "notNull": true,
65 "dimensions": 0,
66 "default": null,
67 "generated": null,
68 "identity": null,
69 "name": "environment_id",
70 "entityType": "columns",
71 "schema": "public",
72 "table": "relay_agent_activity_rows"
73 },
74 {
75 "type": "text",
76 "typeSchema": null,
77 "notNull": true,
78 "dimensions": 0,
79 "default": null,
80 "generated": null,
81 "identity": null,
82 "name": "environment_public_key",
83 "entityType": "columns",
84 "schema": "public",
85 "table": "relay_agent_activity_rows"
86 },
87 {
88 "type": "varchar(512)",
89 "typeSchema": null,
90 "notNull": true,
91 "dimensions": 0,
92 "default": null,
93 "generated": null,
94 "identity": null,
95 "name": "thread_id",
96 "entityType": "columns",
97 "schema": "public",
98 "table": "relay_agent_activity_rows"
99 },
100 {
101 "type": "jsonb",
102 "typeSchema": null,
103 "notNull": true,
104 "dimensions": 0,
105 "default": null,
106 "generated": null,
107 "identity": null,
108 "name": "state_json",
109 "entityType": "columns",
110 "schema": "public",
111 "table": "relay_agent_activity_rows"
112 },
113 {
114 "type": "varchar(64)",
115 "typeSchema": null,
116 "notNull": true,
117 "dimensions": 0,
118 "default": null,
119 "generated": null,
120 "identity": null,
121 "name": "updated_at",
122 "entityType": "columns",
123 "schema": "public",
124 "table": "relay_agent_activity_rows"
125 },
126 {
127 "type": "varchar(64)",
128 "typeSchema": null,
129 "notNull": true,
130 "dimensions": 0,
131 "default": null,
132 "generated": null,
133 "identity": null,
134 "name": "created_at",
135 "entityType": "columns",
136 "schema": "public",
137 "table": "relay_agent_activity_rows"
138 },
139 {
140 "type": "varchar(36)",
141 "typeSchema": null,
142 "notNull": true,
143 "dimensions": 0,
144 "default": null,
145 "generated": null,
146 "identity": null,
147 "name": "id",
148 "entityType": "columns",
149 "schema": "public",
150 "table": "relay_delivery_attempts"
151 },
152 {
153 "type": "varchar(64)",
154 "typeSchema": null,
155 "notNull": true,
156 "dimensions": 0,
157 "default": null,
158 "generated": null,
159 "identity": null,
160 "name": "created_at",
161 "entityType": "columns",
162 "schema": "public",
163 "table": "relay_delivery_attempts"
164 },
165 {
166 "type": "varchar(255)",
167 "typeSchema": null,
168 "notNull": false,
169 "dimensions": 0,
170 "default": null,
171 "generated": null,
172 "identity": null,
173 "name": "user_id",
174 "entityType": "columns",
175 "schema": "public",
176 "table": "relay_delivery_attempts"
177 },
178 {
179 "type": "varchar(191)",
180 "typeSchema": null,
181 "notNull": false,
182 "dimensions": 0,
183 "default": null,
184 "generated": null,
185 "identity": null,
186 "name": "environment_id",
187 "entityType": "columns",
188 "schema": "public",
189 "table": "relay_delivery_attempts"
190 },
191 {
192 "type": "varchar(512)",
193 "typeSchema": null,
194 "notNull": false,
195 "dimensions": 0,
196 "default": null,
197 "generated": null,
198 "identity": null,
199 "name": "thread_id",
200 "entityType": "columns",
201 "schema": "public",
202 "table": "relay_delivery_attempts"
203 },
204 {
205 "type": "varchar(255)",
206 "typeSchema": null,
207 "notNull": false,
208 "dimensions": 0,
209 "default": null,
210 "generated": null,
211 "identity": null,
212 "name": "device_id",
213 "entityType": "columns",
214 "schema": "public",
215 "table": "relay_delivery_attempts"
216 },
217 {
218 "type": "varchar(64)",
219 "typeSchema": null,
220 "notNull": true,
221 "dimensions": 0,
222 "default": null,
223 "generated": null,
224 "identity": null,
225 "name": "kind",
226 "entityType": "columns",
227 "schema": "public",
228 "table": "relay_delivery_attempts"
229 },
230 {
231 "type": "varchar(64)",
232 "typeSchema": null,
233 "notNull": false,
234 "dimensions": 0,
235 "default": null,
236 "generated": null,
237 "identity": null,
238 "name": "source_job_id",
239 "entityType": "columns",
240 "schema": "public",
241 "table": "relay_delivery_attempts"
242 },
243 {
244 "type": "varchar(16)",
245 "typeSchema": null,
246 "notNull": false,
247 "dimensions": 0,
248 "default": null,
249 "generated": null,
250 "identity": null,
251 "name": "token_suffix",
252 "entityType": "columns",
253 "schema": "public",
254 "table": "relay_delivery_attempts"
255 },
256 {
257 "type": "integer",
258 "typeSchema": null,
259 "notNull": false,
260 "dimensions": 0,
261 "default": null,
262 "generated": null,
263 "identity": null,
264 "name": "apns_status",
265 "entityType": "columns",
266 "schema": "public",
267 "table": "relay_delivery_attempts"
268 },
269 {
270 "type": "text",
271 "typeSchema": null,
272 "notNull": false,
273 "dimensions": 0,
274 "default": null,
275 "generated": null,
276 "identity": null,
277 "name": "apns_reason",
278 "entityType": "columns",
279 "schema": "public",
280 "table": "relay_delivery_attempts"
281 },
282 {
283 "type": "varchar(128)",
284 "typeSchema": null,
285 "notNull": false,
286 "dimensions": 0,
287 "default": null,
288 "generated": null,
289 "identity": null,
290 "name": "apns_id",
291 "entityType": "columns",
292 "schema": "public",
293 "table": "relay_delivery_attempts"
294 },
295 {
296 "type": "text",
297 "typeSchema": null,
298 "notNull": false,
299 "dimensions": 0,
300 "default": null,
301 "generated": null,
302 "identity": null,
303 "name": "transport_error",
304 "entityType": "columns",
305 "schema": "public",
306 "table": "relay_delivery_attempts"
307 },
308 {
309 "type": "varchar(128)",
310 "typeSchema": null,
311 "notNull": true,
312 "dimensions": 0,
313 "default": null,
314 "generated": null,
315 "identity": null,
316 "name": "thumbprint",
317 "entityType": "columns",
318 "schema": "public",
319 "table": "relay_dpop_proofs"
320 },
321 {
322 "type": "varchar(255)",
323 "typeSchema": null,
324 "notNull": true,
325 "dimensions": 0,
326 "default": null,
327 "generated": null,
328 "identity": null,
329 "name": "jti",
330 "entityType": "columns",
331 "schema": "public",
332 "table": "relay_dpop_proofs"
333 },
334 {
335 "type": "integer",
336 "typeSchema": null,
337 "notNull": true,
338 "dimensions": 0,
339 "default": null,
340 "generated": null,
341 "identity": null,
342 "name": "iat",
343 "entityType": "columns",
344 "schema": "public",
345 "table": "relay_dpop_proofs"
346 },
347 {
348 "type": "varchar(64)",
349 "typeSchema": null,
350 "notNull": true,
351 "dimensions": 0,
352 "default": null,
353 "generated": null,
354 "identity": null,
355 "name": "expires_at",
356 "entityType": "columns",
357 "schema": "public",
358 "table": "relay_dpop_proofs"
359 },
360 {
361 "type": "varchar(64)",
362 "typeSchema": null,
363 "notNull": true,
364 "dimensions": 0,
365 "default": null,
366 "generated": null,
367 "identity": null,
368 "name": "created_at",
369 "entityType": "columns",
370 "schema": "public",
371 "table": "relay_dpop_proofs"
372 },
373 {
374 "type": "varchar(64)",
375 "typeSchema": null,
376 "notNull": true,
377 "dimensions": 0,
378 "default": null,
379 "generated": null,
380 "identity": null,
381 "name": "credential_id",
382 "entityType": "columns",
383 "schema": "public",
384 "table": "relay_environment_credentials"
385 },
386 {
387 "type": "varchar(191)",
388 "typeSchema": null,
389 "notNull": true,
390 "dimensions": 0,
391 "default": null,
392 "generated": null,
393 "identity": null,
394 "name": "environment_id",
395 "entityType": "columns",
396 "schema": "public",
397 "table": "relay_environment_credentials"
398 },
399 {
400 "type": "text",
401 "typeSchema": null,
402 "notNull": true,
403 "dimensions": 0,
404 "default": null,
405 "generated": null,
406 "identity": null,
407 "name": "environment_public_key",
408 "entityType": "columns",
409 "schema": "public",
410 "table": "relay_environment_credentials"
411 },
412 {
413 "type": "varchar(191)",
414 "typeSchema": null,
415 "notNull": true,
416 "dimensions": 0,
417 "default": null,
418 "generated": null,
419 "identity": null,
420 "name": "credential_hash",
421 "entityType": "columns",
422 "schema": "public",
423 "table": "relay_environment_credentials"
424 },
425 {
426 "type": "varchar(64)",
427 "typeSchema": null,
428 "notNull": false,
429 "dimensions": 0,
430 "default": null,
431 "generated": null,
432 "identity": null,
433 "name": "revoked_at",
434 "entityType": "columns",
435 "schema": "public",
436 "table": "relay_environment_credentials"
437 },
438 {
439 "type": "varchar(64)",
440 "typeSchema": null,
441 "notNull": true,
442 "dimensions": 0,
443 "default": null,
444 "generated": null,
445 "identity": null,
446 "name": "created_at",
447 "entityType": "columns",
448 "schema": "public",
449 "table": "relay_environment_credentials"
450 },
451 {
452 "type": "varchar(64)",
453 "typeSchema": null,
454 "notNull": true,
455 "dimensions": 0,
456 "default": null,
457 "generated": null,
458 "identity": null,
459 "name": "updated_at",
460 "entityType": "columns",
461 "schema": "public",
462 "table": "relay_environment_credentials"
463 },
464 {
465 "type": "varchar(191)",
466 "typeSchema": null,
467 "notNull": true,
468 "dimensions": 0,
469 "default": null,
470 "generated": null,
471 "identity": null,
472 "name": "user_id",
473 "entityType": "columns",
474 "schema": "public",
475 "table": "relay_environment_links"
476 },
477 {
478 "type": "varchar(191)",
479 "typeSchema": null,
480 "notNull": true,
481 "dimensions": 0,
482 "default": null,
483 "generated": null,
484 "identity": null,
485 "name": "environment_id",
486 "entityType": "columns",
487 "schema": "public",
488 "table": "relay_environment_links"
489 },
490 {
491 "type": "text",
492 "typeSchema": null,
493 "notNull": true,
494 "dimensions": 0,
495 "default": "'T3 Environment'",
496 "generated": null,
497 "identity": null,
498 "name": "environment_label",
499 "entityType": "columns",
500 "schema": "public",
501 "table": "relay_environment_links"
502 },
503 {
504 "type": "text",
505 "typeSchema": null,
506 "notNull": true,
507 "dimensions": 0,
508 "default": null,
509 "generated": null,
510 "identity": null,
511 "name": "environment_public_key",
512 "entityType": "columns",
513 "schema": "public",
514 "table": "relay_environment_links"
515 },
516 {
517 "type": "text",
518 "typeSchema": null,
519 "notNull": true,
520 "dimensions": 0,
521 "default": null,
522 "generated": null,
523 "identity": null,
524 "name": "endpoint_http_base_url",
525 "entityType": "columns",
526 "schema": "public",
527 "table": "relay_environment_links"
528 },
529 {
530 "type": "text",
531 "typeSchema": null,
532 "notNull": true,
533 "dimensions": 0,
534 "default": null,
535 "generated": null,
536 "identity": null,
537 "name": "endpoint_ws_base_url",
538 "entityType": "columns",
539 "schema": "public",
540 "table": "relay_environment_links"
541 },
542 {
543 "type": "varchar(32)",
544 "typeSchema": null,
545 "notNull": true,
546 "dimensions": 0,
547 "default": null,
548 "generated": null,
549 "identity": null,
550 "name": "endpoint_provider_kind",
551 "entityType": "columns",
552 "schema": "public",
553 "table": "relay_environment_links"
554 },
555 {
556 "type": "boolean",
557 "typeSchema": null,
558 "notNull": true,
559 "dimensions": 0,
560 "default": "true",
561 "generated": null,
562 "identity": null,
563 "name": "notifications_enabled",
564 "entityType": "columns",
565 "schema": "public",
566 "table": "relay_environment_links"
567 },
568 {
569 "type": "boolean",
570 "typeSchema": null,
571 "notNull": true,
572 "dimensions": 0,
573 "default": "true",
574 "generated": null,
575 "identity": null,
576 "name": "live_activities_enabled",
577 "entityType": "columns",
578 "schema": "public",
579 "table": "relay_environment_links"
580 },
581 {
582 "type": "boolean",
583 "typeSchema": null,
584 "notNull": true,
585 "dimensions": 0,
586 "default": "false",
587 "generated": null,
588 "identity": null,
589 "name": "managed_tunnels_enabled",
590 "entityType": "columns",
591 "schema": "public",
592 "table": "relay_environment_links"
593 },
594 {
595 "type": "varchar(191)",
596 "typeSchema": null,
597 "notNull": false,
598 "dimensions": 0,
599 "default": null,
600 "generated": null,
601 "identity": null,
602 "name": "created_by_device_id",
603 "entityType": "columns",
604 "schema": "public",
605 "table": "relay_environment_links"
606 },
607 {
608 "type": "varchar(64)",
609 "typeSchema": null,
610 "notNull": false,
611 "dimensions": 0,
612 "default": null,
613 "generated": null,
614 "identity": null,
615 "name": "revoked_at",
616 "entityType": "columns",
617 "schema": "public",
618 "table": "relay_environment_links"
619 },
620 {
621 "type": "varchar(64)",
622 "typeSchema": null,
623 "notNull": true,
624 "dimensions": 0,
625 "default": null,
626 "generated": null,
627 "identity": null,
628 "name": "created_at",
629 "entityType": "columns",
630 "schema": "public",
631 "table": "relay_environment_links"
632 },
633 {
634 "type": "varchar(64)",
635 "typeSchema": null,
636 "notNull": true,
637 "dimensions": 0,
638 "default": null,
639 "generated": null,
640 "identity": null,
641 "name": "updated_at",
642 "entityType": "columns",
643 "schema": "public",
644 "table": "relay_environment_links"
645 },
646 {
647 "type": "varchar(255)",
648 "typeSchema": null,
649 "notNull": true,
650 "dimensions": 0,
651 "default": null,
652 "generated": null,
653 "identity": null,
654 "name": "user_id",
655 "entityType": "columns",
656 "schema": "public",
657 "table": "relay_live_activities"
658 },
659 {
660 "type": "varchar(255)",
661 "typeSchema": null,
662 "notNull": true,
663 "dimensions": 0,
664 "default": null,
665 "generated": null,
666 "identity": null,
667 "name": "device_id",
668 "entityType": "columns",
669 "schema": "public",
670 "table": "relay_live_activities"
671 },
672 {
673 "type": "text",
674 "typeSchema": null,
675 "notNull": false,
676 "dimensions": 0,
677 "default": null,
678 "generated": null,
679 "identity": null,
680 "name": "activity_push_token",
681 "entityType": "columns",
682 "schema": "public",
683 "table": "relay_live_activities"
684 },
685 {
686 "type": "varchar(64)",
687 "typeSchema": null,
688 "notNull": false,
689 "dimensions": 0,
690 "default": null,
691 "generated": null,
692 "identity": null,
693 "name": "remote_start_queued_at",
694 "entityType": "columns",
695 "schema": "public",
696 "table": "relay_live_activities"
697 },
698 {
699 "type": "varchar(64)",
700 "typeSchema": null,
701 "notNull": false,
702 "dimensions": 0,
703 "default": null,
704 "generated": null,
705 "identity": null,
706 "name": "remote_started_at",
707 "entityType": "columns",
708 "schema": "public",
709 "table": "relay_live_activities"
710 },
711 {
712 "type": "varchar(64)",
713 "typeSchema": null,
714 "notNull": false,
715 "dimensions": 0,
716 "default": null,
717 "generated": null,
718 "identity": null,
719 "name": "ended_at",
720 "entityType": "columns",
721 "schema": "public",
722 "table": "relay_live_activities"
723 },
724 {
725 "type": "jsonb",
726 "typeSchema": null,
727 "notNull": false,
728 "dimensions": 0,
729 "default": null,
730 "generated": null,
731 "identity": null,
732 "name": "last_aggregate_json",
733 "entityType": "columns",
734 "schema": "public",
735 "table": "relay_live_activities"
736 },
737 {
738 "type": "varchar(64)",
739 "typeSchema": null,
740 "notNull": false,
741 "dimensions": 0,
742 "default": null,
743 "generated": null,
744 "identity": null,
745 "name": "last_live_activity_delivery_at",
746 "entityType": "columns",
747 "schema": "public",
748 "table": "relay_live_activities"
749 },
750 {
751 "type": "varchar(64)",
752 "typeSchema": null,
753 "notNull": true,
754 "dimensions": 0,
755 "default": null,
756 "generated": null,
757 "identity": null,
758 "name": "created_at",
759 "entityType": "columns",
760 "schema": "public",
761 "table": "relay_live_activities"
762 },
763 {
764 "type": "varchar(64)",
765 "typeSchema": null,
766 "notNull": true,
767 "dimensions": 0,
768 "default": null,
769 "generated": null,
770 "identity": null,
771 "name": "updated_at",
772 "entityType": "columns",
773 "schema": "public",
774 "table": "relay_live_activities"
775 },
776 {
777 "type": "varchar(191)",
778 "typeSchema": null,
779 "notNull": true,
780 "dimensions": 0,
781 "default": null,
782 "generated": null,
783 "identity": null,
784 "name": "user_id",
785 "entityType": "columns",
786 "schema": "public",
787 "table": "relay_managed_endpoint_allocations"
788 },
789 {
790 "type": "varchar(191)",
791 "typeSchema": null,
792 "notNull": true,
793 "dimensions": 0,
794 "default": null,
795 "generated": null,
796 "identity": null,
797 "name": "environment_id",
798 "entityType": "columns",
799 "schema": "public",
800 "table": "relay_managed_endpoint_allocations"
801 },
802 {
803 "type": "text",
804 "typeSchema": null,
805 "notNull": true,
806 "dimensions": 0,
807 "default": null,
808 "generated": null,
809 "identity": null,
810 "name": "hostname",
811 "entityType": "columns",
812 "schema": "public",
813 "table": "relay_managed_endpoint_allocations"
814 },
815 {
816 "type": "varchar(191)",
817 "typeSchema": null,
818 "notNull": false,
819 "dimensions": 0,
820 "default": null,
821 "generated": null,
822 "identity": null,
823 "name": "tunnel_id",
824 "entityType": "columns",
825 "schema": "public",
826 "table": "relay_managed_endpoint_allocations"
827 },
828 {
829 "type": "text",
830 "typeSchema": null,
831 "notNull": true,
832 "dimensions": 0,
833 "default": null,
834 "generated": null,
835 "identity": null,
836 "name": "tunnel_name",
837 "entityType": "columns",
838 "schema": "public",
839 "table": "relay_managed_endpoint_allocations"
840 },
841 {
842 "type": "varchar(191)",
843 "typeSchema": null,
844 "notNull": false,
845 "dimensions": 0,
846 "default": null,
847 "generated": null,
848 "identity": null,
849 "name": "dns_record_id",
850 "entityType": "columns",
851 "schema": "public",
852 "table": "relay_managed_endpoint_allocations"
853 },
854 {
855 "type": "varchar(64)",
856 "typeSchema": null,
857 "notNull": false,
858 "dimensions": 0,
859 "default": null,
860 "generated": null,
861 "identity": null,
862 "name": "ready_at",
863 "entityType": "columns",
864 "schema": "public",
865 "table": "relay_managed_endpoint_allocations"
866 },
867 {
868 "type": "varchar(64)",
869 "typeSchema": null,
870 "notNull": true,
871 "dimensions": 0,
872 "default": null,
873 "generated": null,
874 "identity": null,
875 "name": "created_at",
876 "entityType": "columns",
877 "schema": "public",
878 "table": "relay_managed_endpoint_allocations"
879 },
880 {
881 "type": "varchar(64)",
882 "typeSchema": null,
883 "notNull": true,
884 "dimensions": 0,
885 "default": null,
886 "generated": null,
887 "identity": null,
888 "name": "updated_at",
889 "entityType": "columns",
890 "schema": "public",
891 "table": "relay_managed_endpoint_allocations"
892 },
893 {
894 "type": "varchar(191)",
895 "typeSchema": null,
896 "notNull": true,
897 "dimensions": 0,
898 "default": null,
899 "generated": null,
900 "identity": null,
901 "name": "user_id",
902 "entityType": "columns",
903 "schema": "public",
904 "table": "relay_managed_tunnel_limits"
905 },
906 {
907 "type": "integer",
908 "typeSchema": null,
909 "notNull": true,
910 "dimensions": 0,
911 "default": null,
912 "generated": null,
913 "identity": null,
914 "name": "max_tunnels",
915 "entityType": "columns",
916 "schema": "public",
917 "table": "relay_managed_tunnel_limits"
918 },
919 {
920 "type": "varchar(64)",
921 "typeSchema": null,
922 "notNull": true,
923 "dimensions": 0,
924 "default": null,
925 "generated": null,
926 "identity": null,
927 "name": "created_at",
928 "entityType": "columns",
929 "schema": "public",
930 "table": "relay_managed_tunnel_limits"
931 },
932 {
933 "type": "varchar(64)",
934 "typeSchema": null,
935 "notNull": true,
936 "dimensions": 0,
937 "default": null,
938 "generated": null,
939 "identity": null,
940 "name": "updated_at",
941 "entityType": "columns",
942 "schema": "public",
943 "table": "relay_managed_tunnel_limits"
944 },
945 {
946 "type": "varchar(255)",
947 "typeSchema": null,
948 "notNull": true,
949 "dimensions": 0,
950 "default": null,
951 "generated": null,
952 "identity": null,
953 "name": "user_id",
954 "entityType": "columns",
955 "schema": "public",
956 "table": "relay_mobile_devices"
957 },
958 {
959 "type": "varchar(255)",
960 "typeSchema": null,
961 "notNull": true,
962 "dimensions": 0,
963 "default": null,
964 "generated": null,
965 "identity": null,
966 "name": "device_id",
967 "entityType": "columns",
968 "schema": "public",
969 "table": "relay_mobile_devices"
970 },
971 {
972 "type": "text",
973 "typeSchema": null,
974 "notNull": true,
975 "dimensions": 0,
976 "default": "'iOS device'",
977 "generated": null,
978 "identity": null,
979 "name": "label",
980 "entityType": "columns",
981 "schema": "public",
982 "table": "relay_mobile_devices"
983 },
984 {
985 "type": "varchar(16)",
986 "typeSchema": null,
987 "notNull": true,
988 "dimensions": 0,
989 "default": null,
990 "generated": null,
991 "identity": null,
992 "name": "platform",
993 "entityType": "columns",
994 "schema": "public",
995 "table": "relay_mobile_devices"
996 },
997 {
998 "type": "integer",
999 "typeSchema": null,
1000 "notNull": false,
1001 "dimensions": 0,
1002 "default": null,
1003 "generated": null,
1004 "identity": null,
1005 "name": "ios_major_version",
1006 "entityType": "columns",
1007 "schema": "public",
1008 "table": "relay_mobile_devices"
1009 },
1010 {
1011 "type": "integer",
1012 "typeSchema": null,
1013 "notNull": false,
1014 "dimensions": 0,
1015 "default": null,
1016 "generated": null,
1017 "identity": null,
1018 "name": "android_api_level",
1019 "entityType": "columns",
1020 "schema": "public",
1021 "table": "relay_mobile_devices"
1022 },
1023 {
1024 "type": "varchar(64)",
1025 "typeSchema": null,
1026 "notNull": false,
1027 "dimensions": 0,
1028 "default": null,
1029 "generated": null,
1030 "identity": null,
1031 "name": "app_version",
1032 "entityType": "columns",
1033 "schema": "public",
1034 "table": "relay_mobile_devices"
1035 },
1036 {
1037 "type": "varchar(255)",
1038 "typeSchema": null,
1039 "notNull": false,
1040 "dimensions": 0,
1041 "default": null,
1042 "generated": null,
1043 "identity": null,
1044 "name": "bundle_id",
1045 "entityType": "columns",
1046 "schema": "public",
1047 "table": "relay_mobile_devices"
1048 },
1049 {
1050 "type": "varchar(16)",
1051 "typeSchema": null,
1052 "notNull": false,
1053 "dimensions": 0,
1054 "default": null,
1055 "generated": null,
1056 "identity": null,
1057 "name": "aps_environment",
1058 "entityType": "columns",
1059 "schema": "public",
1060 "table": "relay_mobile_devices"
1061 },
1062 {
1063 "type": "text",
1064 "typeSchema": null,
1065 "notNull": false,
1066 "dimensions": 0,
1067 "default": null,
1068 "generated": null,
1069 "identity": null,
1070 "name": "push_token",
1071 "entityType": "columns",
1072 "schema": "public",
1073 "table": "relay_mobile_devices"
1074 },
1075 {
1076 "type": "text",
1077 "typeSchema": null,
1078 "notNull": false,
1079 "dimensions": 0,
1080 "default": null,
1081 "generated": null,
1082 "identity": null,
1083 "name": "push_to_start_token",
1084 "entityType": "columns",
1085 "schema": "public",
1086 "table": "relay_mobile_devices"
1087 },
1088 {
1089 "type": "jsonb",
1090 "typeSchema": null,
1091 "notNull": true,
1092 "dimensions": 0,
1093 "default": null,
1094 "generated": null,
1095 "identity": null,
1096 "name": "preferences_json",
1097 "entityType": "columns",
1098 "schema": "public",
1099 "table": "relay_mobile_devices"
1100 },
1101 {
1102 "type": "varchar(64)",
1103 "typeSchema": null,
1104 "notNull": true,
1105 "dimensions": 0,
1106 "default": null,
1107 "generated": null,
1108 "identity": null,
1109 "name": "created_at",
1110 "entityType": "columns",
1111 "schema": "public",
1112 "table": "relay_mobile_devices"
1113 },
1114 {
1115 "type": "varchar(64)",
1116 "typeSchema": null,
1117 "notNull": true,
1118 "dimensions": 0,
1119 "default": null,
1120 "generated": null,
1121 "identity": null,
1122 "name": "updated_at",
1123 "entityType": "columns",
1124 "schema": "public",
1125 "table": "relay_mobile_devices"
1126 },
1127 {
1128 "nameExplicit": true,
1129 "columns": [
1130 {
1131 "value": "updated_at",
1132 "isExpression": false,
1133 "asc": true,
1134 "nullsFirst": false,
1135 "opclass": null
1136 }
1137 ],
1138 "isUnique": false,
1139 "where": null,
1140 "with": "",
1141 "method": "btree",
1142 "concurrently": false,
1143 "name": "idx_relay_agent_activity_rows_updated",
1144 "entityType": "indexes",
1145 "schema": "public",
1146 "table": "relay_agent_activity_rows"
1147 },
1148 {
1149 "nameExplicit": true,
1150 "columns": [
1151 {
1152 "value": "environment_id",
1153 "isExpression": false,
1154 "asc": true,
1155 "nullsFirst": false,
1156 "opclass": null
1157 },
1158 {
1159 "value": "thread_id",
1160 "isExpression": false,
1161 "asc": true,
1162 "nullsFirst": false,
1163 "opclass": null
1164 },
1165 {
1166 "value": "created_at",
1167 "isExpression": false,
1168 "asc": true,
1169 "nullsFirst": false,
1170 "opclass": null
1171 }
1172 ],
1173 "isUnique": false,
1174 "where": null,
1175 "with": "",
1176 "method": "btree",
1177 "concurrently": false,
1178 "name": "idx_relay_delivery_attempts_environment",
1179 "entityType": "indexes",
1180 "schema": "public",
1181 "table": "relay_delivery_attempts"
1182 },
1183 {
1184 "nameExplicit": true,
1185 "columns": [
1186 {
1187 "value": "source_job_id",
1188 "isExpression": false,
1189 "asc": true,
1190 "nullsFirst": false,
1191 "opclass": null
1192 }
1193 ],
1194 "isUnique": true,
1195 "where": null,
1196 "with": "",
1197 "method": "btree",
1198 "concurrently": false,
1199 "name": "idx_relay_delivery_attempts_source_job",
1200 "entityType": "indexes",
1201 "schema": "public",
1202 "table": "relay_delivery_attempts"
1203 },
1204 {
1205 "nameExplicit": true,
1206 "columns": [
1207 {
1208 "value": "expires_at",
1209 "isExpression": false,
1210 "asc": true,
1211 "nullsFirst": false,
1212 "opclass": null
1213 }
1214 ],
1215 "isUnique": false,
1216 "where": null,
1217 "with": "",
1218 "method": "btree",
1219 "concurrently": false,
1220 "name": "idx_relay_dpop_proofs_expires_at",
1221 "entityType": "indexes",
1222 "schema": "public",
1223 "table": "relay_dpop_proofs"
1224 },
1225 {
1226 "nameExplicit": true,
1227 "columns": [
1228 {
1229 "value": "credential_hash",
1230 "isExpression": false,
1231 "asc": true,
1232 "nullsFirst": false,
1233 "opclass": null
1234 }
1235 ],
1236 "isUnique": true,
1237 "where": null,
1238 "with": "",
1239 "method": "btree",
1240 "concurrently": false,
1241 "name": "idx_relay_environment_credentials_hash",
1242 "entityType": "indexes",
1243 "schema": "public",
1244 "table": "relay_environment_credentials"
1245 },
1246 {
1247 "nameExplicit": true,
1248 "columns": [
1249 {
1250 "value": "environment_id",
1251 "isExpression": false,
1252 "asc": true,
1253 "nullsFirst": false,
1254 "opclass": null
1255 },
1256 {
1257 "value": "revoked_at",
1258 "isExpression": false,
1259 "asc": true,
1260 "nullsFirst": false,
1261 "opclass": null
1262 }
1263 ],
1264 "isUnique": false,
1265 "where": null,
1266 "with": "",
1267 "method": "btree",
1268 "concurrently": false,
1269 "name": "idx_relay_environment_credentials_environment",
1270 "entityType": "indexes",
1271 "schema": "public",
1272 "table": "relay_environment_credentials"
1273 },
1274 {
1275 "nameExplicit": true,
1276 "columns": [
1277 {
1278 "value": "environment_id",
1279 "isExpression": false,
1280 "asc": true,
1281 "nullsFirst": false,
1282 "opclass": null
1283 },
1284 {
1285 "value": "environment_public_key",
1286 "isExpression": false,
1287 "asc": true,
1288 "nullsFirst": false,
1289 "opclass": null
1290 },
1291 {
1292 "value": "revoked_at",
1293 "isExpression": false,
1294 "asc": true,
1295 "nullsFirst": false,
1296 "opclass": null
1297 }
1298 ],
1299 "isUnique": false,
1300 "where": null,
1301 "with": "",
1302 "method": "btree",
1303 "concurrently": false,
1304 "name": "idx_relay_environment_credentials_environment_key",
1305 "entityType": "indexes",
1306 "schema": "public",
1307 "table": "relay_environment_credentials"
1308 },
1309 {
1310 "nameExplicit": true,
1311 "columns": [
1312 {
1313 "value": "environment_id",
1314 "isExpression": false,
1315 "asc": true,
1316 "nullsFirst": false,
1317 "opclass": null
1318 },
1319 {
1320 "value": "revoked_at",
1321 "isExpression": false,
1322 "asc": true,
1323 "nullsFirst": false,
1324 "opclass": null
1325 }
1326 ],
1327 "isUnique": false,
1328 "where": null,
1329 "with": "",
1330 "method": "btree",
1331 "concurrently": false,
1332 "name": "idx_relay_environment_links_environment",
1333 "entityType": "indexes",
1334 "schema": "public",
1335 "table": "relay_environment_links"
1336 },
1337 {
1338 "nameExplicit": true,
1339 "columns": [
1340 {
1341 "value": "activity_push_token",
1342 "isExpression": false,
1343 "asc": true,
1344 "nullsFirst": false,
1345 "opclass": null
1346 }
1347 ],
1348 "isUnique": true,
1349 "where": null,
1350 "with": "",
1351 "method": "btree",
1352 "concurrently": false,
1353 "name": "idx_relay_live_activities_activity_push_token",
1354 "entityType": "indexes",
1355 "schema": "public",
1356 "table": "relay_live_activities"
1357 },
1358 {
1359 "nameExplicit": true,
1360 "columns": [
1361 {
1362 "value": "hostname",
1363 "isExpression": false,
1364 "asc": true,
1365 "nullsFirst": false,
1366 "opclass": null
1367 }
1368 ],
1369 "isUnique": true,
1370 "where": null,
1371 "with": "",
1372 "method": "btree",
1373 "concurrently": false,
1374 "name": "idx_relay_managed_endpoint_allocations_hostname",
1375 "entityType": "indexes",
1376 "schema": "public",
1377 "table": "relay_managed_endpoint_allocations"
1378 },
1379 {
1380 "nameExplicit": true,
1381 "columns": [
1382 {
1383 "value": "tunnel_name",
1384 "isExpression": false,
1385 "asc": true,
1386 "nullsFirst": false,
1387 "opclass": null
1388 }
1389 ],
1390 "isUnique": true,
1391 "where": null,
1392 "with": "",
1393 "method": "btree",
1394 "concurrently": false,
1395 "name": "idx_relay_managed_endpoint_allocations_tunnel_name",
1396 "entityType": "indexes",
1397 "schema": "public",
1398 "table": "relay_managed_endpoint_allocations"
1399 },
1400 {
1401 "nameExplicit": true,
1402 "columns": [
1403 {
1404 "value": "push_token",
1405 "isExpression": false,
1406 "asc": true,
1407 "nullsFirst": false,
1408 "opclass": null
1409 }
1410 ],
1411 "isUnique": true,
1412 "where": null,
1413 "with": "",
1414 "method": "btree",
1415 "concurrently": false,
1416 "name": "idx_relay_mobile_devices_push_token",
1417 "entityType": "indexes",
1418 "schema": "public",
1419 "table": "relay_mobile_devices"
1420 },
1421 {
1422 "nameExplicit": true,
1423 "columns": [
1424 {
1425 "value": "push_to_start_token",
1426 "isExpression": false,
1427 "asc": true,
1428 "nullsFirst": false,
1429 "opclass": null
1430 }
1431 ],
1432 "isUnique": true,
1433 "where": null,
1434 "with": "",
1435 "method": "btree",
1436 "concurrently": false,
1437 "name": "idx_relay_mobile_devices_push_to_start_token",
1438 "entityType": "indexes",
1439 "schema": "public",
1440 "table": "relay_mobile_devices"
1441 },
1442 {
1443 "columns": ["environment_id", "environment_public_key", "thread_id"],
1444 "nameExplicit": false,
1445 "name": "relay_agent_activity_rows_pkey",
1446 "entityType": "pks",
1447 "schema": "public",
1448 "table": "relay_agent_activity_rows"
1449 },
1450 {
1451 "columns": ["thumbprint", "jti"],
1452 "nameExplicit": false,
1453 "name": "relay_dpop_proofs_pkey",
1454 "entityType": "pks",
1455 "schema": "public",
1456 "table": "relay_dpop_proofs"
1457 },
1458 {
1459 "columns": ["user_id", "environment_id"],
1460 "nameExplicit": false,
1461 "name": "relay_environment_links_pkey",
1462 "entityType": "pks",
1463 "schema": "public",
1464 "table": "relay_environment_links"
1465 },
1466 {
1467 "columns": ["user_id", "device_id"],
1468 "nameExplicit": false,
1469 "name": "relay_live_activities_pkey",
1470 "entityType": "pks",
1471 "schema": "public",
1472 "table": "relay_live_activities"
1473 },
1474 {
1475 "columns": ["user_id", "environment_id"],
1476 "nameExplicit": false,
1477 "name": "relay_managed_endpoint_allocations_pkey",
1478 "entityType": "pks",
1479 "schema": "public",
1480 "table": "relay_managed_endpoint_allocations"
1481 },
1482 {
1483 "columns": ["user_id", "device_id"],
1484 "nameExplicit": false,
1485 "name": "relay_mobile_devices_pkey",
1486 "entityType": "pks",
1487 "schema": "public",
1488 "table": "relay_mobile_devices"
1489 },
1490 {
1491 "columns": ["id"],
1492 "nameExplicit": false,
1493 "name": "relay_delivery_attempts_pkey",
1494 "schema": "public",
1495 "table": "relay_delivery_attempts",
1496 "entityType": "pks"
1497 },
1498 {
1499 "columns": ["credential_id"],
1500 "nameExplicit": false,
1501 "name": "relay_environment_credentials_pkey",
1502 "schema": "public",
1503 "table": "relay_environment_credentials",
1504 "entityType": "pks"
1505 },
1506 {
1507 "columns": ["user_id"],
1508 "nameExplicit": false,
1509 "name": "relay_managed_tunnel_limits_pkey",
1510 "schema": "public",
1511 "table": "relay_managed_tunnel_limits",
1512 "entityType": "pks"
1513 }
1514 ],
1515 "renames": []
1516}
infra/relay/src/http/Api.test.ts+100-9
...@@ -1,4 +1,15 @@...@@ -1,4 +1,15 @@
1import * as HttpServer from "effect/unstable/http/HttpServer";
2import {
3 RelayClientAuth,
4 RelayClientPrincipal,
5 type RelayClientDeviceRecord,
6} from "@t3tools/contracts/relay";
7import * as EnvironmentLinker from "../environments/EnvironmentLinker.ts";
8import * as RelayTokens from "../auth/RelayTokens.ts";
9import * as Devices from "../agentActivity/Devices.ts";
1import { createClerkClient, verifyToken } from "@clerk/backend";10import { createClerkClient, verifyToken } from "@clerk/backend";
11import * as NodeHttpPlatform from "@effect/platform-node/NodeHttpPlatform";
12import * as NodeServices from "@effect/platform-node/NodeServices";
2import { describe, expect, it } from "@effect/vitest";13import { describe, expect, it } from "@effect/vitest";
3import { vi } from "vite-plus/test";14import { vi } from "vite-plus/test";
4import * as Context from "effect/Context";15import * as Context from "effect/Context";
...@@ -12,22 +23,21 @@ import * as Predicate from "effect/Predicate";...@@ -12,22 +23,21 @@ import * as Predicate from "effect/Predicate";
12import * as Redacted from "effect/Redacted";23import * as Redacted from "effect/Redacted";
13import * as TestClock from "effect/testing/TestClock";24import * as TestClock from "effect/testing/TestClock";
14import * as Tracer from "effect/Tracer";25import * as Tracer from "effect/Tracer";
26import * as Etag from "effect/unstable/http/Etag";
15import * as HttpRouter from "effect/unstable/http/HttpRouter";27import * as HttpRouter from "effect/unstable/http/HttpRouter";
16import * as HttpServerRequest from "effect/unstable/http/HttpServerRequest";28import * as HttpServerRequest from "effect/unstable/http/HttpServerRequest";
17import * as HttpServerResponse from "effect/unstable/http/HttpServerResponse";29import * as HttpServerResponse from "effect/unstable/http/HttpServerResponse";
18import * as HttpServer from "effect/unstable/http/HttpServer";
19import * as HttpApiBuilder from "effect/unstable/httpapi/HttpApiBuilder";
20import * as HttpApi from "effect/unstable/httpapi/HttpApi";30import * as HttpApi from "effect/unstable/httpapi/HttpApi";
31import * as HttpApiBuilder from "effect/unstable/httpapi/HttpApiBuilder";
21import { EnvironmentId } from "@t3tools/contracts";32import { EnvironmentId } from "@t3tools/contracts";
22import {33import {
23 RelayApi,
24 RelayClientAuth,
25 RelayClientPrincipal,
26 RelayEnvironmentAuth,34 RelayEnvironmentAuth,
27 type RelayClientDeviceRecord,35 RelayEnvironmentPrincipal,
36 RelayApi,
28} from "@t3tools/contracts/relay";37} from "@t3tools/contracts/relay";
2938
30import {39import {
40 RELAY_HTTP_ROUTER_CONFIG,
31 RELAY_REQUEST_DEADLINE_MS,41 RELAY_REQUEST_DEADLINE_MS,
32 clientApi,42 clientApi,
33 relayCors,43 relayCors,
...@@ -36,6 +46,7 @@ import {...@@ -36,6 +46,7 @@ import {
36 relayNotFoundRoute,46 relayNotFoundRoute,
37 relayDpopFailureReason,47 relayDpopFailureReason,
38 revokeEnvironmentLinkRecord,48 revokeEnvironmentLinkRecord,
49 serverApi,
39 traceRelayHttpRequestWith,50 traceRelayHttpRequestWith,
40 unlinkEnvironmentRecord,51 unlinkEnvironmentRecord,
41 verifyRelayClientBearerToken,52 verifyRelayClientBearerToken,
...@@ -46,9 +57,8 @@ import * as RelayDb from "../db.ts";...@@ -46,9 +57,8 @@ import * as RelayDb from "../db.ts";
46import * as EnvironmentCredentials from "../environments/EnvironmentCredentials.ts";57import * as EnvironmentCredentials from "../environments/EnvironmentCredentials.ts";
47import * as EnvironmentLinks from "../environments/EnvironmentLinks.ts";58import * as EnvironmentLinks from "../environments/EnvironmentLinks.ts";
48import * as ManagedEndpointProvider from "../environments/ManagedEndpointProvider.ts";59import * as ManagedEndpointProvider from "../environments/ManagedEndpointProvider.ts";
49import * as EnvironmentLinker from "../environments/EnvironmentLinker.ts";60import * as AgentActivityPublisher from "../agentActivity/AgentActivityPublisher.ts";
50import * as RelayTokens from "../auth/RelayTokens.ts";61import * as EnvironmentPublishSignatures from "../environments/EnvironmentPublishSignatures.ts";
51import * as Devices from "../agentActivity/Devices.ts";
5262
53vi.mock("@clerk/backend", () => ({63vi.mock("@clerk/backend", () => ({
54 createClerkClient: vi.fn(),64 createClerkClient: vi.fn(),
...@@ -606,6 +616,87 @@ describe("relay request tracing", () => {...@@ -606,6 +616,87 @@ describe("relay request tracing", () => {
606});616});
607617
608describe("relay routing fallback", () => {618describe("relay routing fallback", () => {
619 it.effect("publishes activity for escaped delegated thread IDs longer than 100 characters", () =>
620 Effect.gen(function* () {
621 const environmentId = "environment-1";
622 const environmentPublicKey = "environment-public-key";
623 const published: Array<
624 Parameters<AgentActivityPublisher.AgentActivityPublisher["Service"]["publish"]>[0]
625 > = [];
626 const verified: Array<
627 Parameters<
628 EnvironmentPublishSignatures.EnvironmentPublishSignatures["Service"]["verify"]
629 >[0]
630 > = [];
631 const publisher = Layer.succeed(AgentActivityPublisher.AgentActivityPublisher, {
632 publish: (input) =>
633 Effect.sync(() => {
634 published.push(input);
635 return { ok: true as const, deliveries: [] };
636 }),
637 replayForLiveActivityRegistration: () => Effect.succeed(null),
638 });
639 const signatures = Layer.succeed(EnvironmentPublishSignatures.EnvironmentPublishSignatures, {
640 verify: (input) =>
641 Effect.sync(() => {
642 verified.push(input);
643 }),
644 });
645 const auth = Layer.succeed(RelayEnvironmentAuth, {
646 environmentBearer: (effect) =>
647 effect.pipe(
648 Effect.provideService(RelayEnvironmentPrincipal, {
649 environmentId,
650 environmentPublicKey,
651 }),
652 ),
653 });
654 const routes = HttpApiBuilder.layer(
655 HttpApi.make("RelayApi").add(RelayApi.groups.server),
656 ).pipe(
657 Layer.provide(serverApi.pipe(Layer.provide([publisher, signatures]))),
658 Layer.provide(auth),
659 Layer.provide([NodeServices.layer, NodeHttpPlatform.layer, Etag.layerWeak]),
660 );
661 const httpEffect = yield* HttpRouter.toHttpEffect(
662 Layer.mergeAll(routes, relayNotFoundRoute, relayCors),
663 ).pipe(Effect.provideService(HttpRouter.RouterConfig, RELAY_HTTP_ROUTER_CONFIG));
664 const threadIds = [
665 "b7c8c522-d244-43dc-875f-7224fce79912",
666 "t".repeat(512),
667 "thread:delegated-task:command%3Amcp%3Ab7c8c522-d244-43dc-875f-7224fce79912%3Adelegate-task%3Agreet-subagent-20260813",
668 ];
669 for (const threadId of threadIds) {
670 const request = HttpServerRequest.fromWeb(
671 new Request(
672 `https://relay.test/v1/environments/${environmentId}/threads/${encodeURIComponent(threadId)}/agent-activity`,
673 {
674 method: "POST",
675 headers: {
676 authorization: "Bearer environment-credential",
677 "content-type": "application/json",
678 },
679 body: '{"state":null,"proof":"signed-proof"}',
680 },
681 ),
682 );
683 const response = yield* httpEffect.pipe(
684 Effect.provideService(HttpServerRequest.HttpServerRequest, request),
685 );
686 expect(response.status).toBe(200);
687 }
688 expect(published).toEqual(
689 threadIds.map((threadId) => ({
690 environmentId,
691 environmentPublicKey,
692 threadId,
693 state: null,
694 })),
695 );
696 expect(verified.map((input) => input.threadId)).toEqual(threadIds);
697 }).pipe(Effect.scoped),
698 );
699
609 it.effect("redirects the relay root to the API docs", () =>700 it.effect("redirects the relay root to the API docs", () =>
610 Effect.gen(function* () {701 Effect.gen(function* () {
611 const request = HttpServerRequest.fromWeb(new Request("https://relay.test/"));702 const request = HttpServerRequest.fromWeb(new Request("https://relay.test/"));
infra/relay/src/http/Api.ts+6
...@@ -71,6 +71,12 @@ import * as MobileRegistrations from "../agentActivity/MobileRegistrations.ts";...@@ -71,6 +71,12 @@ import * as MobileRegistrations from "../agentActivity/MobileRegistrations.ts";
71import { withSpanAttributes } from "../observability.ts";71import { withSpanAttributes } from "../observability.ts";
72import * as RelayDb from "../db.ts";72import * as RelayDb from "../db.ts";
7373
74// Delegated thread IDs carry escaped command provenance and exceed the router's
75// default 100-character path parameter limit. Match the environment server.
76export const RELAY_HTTP_ROUTER_CONFIG = {
77 maxParamLength: 512,
78} as const;
79
74const relayCorsAllowedMethods = ["GET", "POST", "DELETE", "OPTIONS"] as const;80const relayCorsAllowedMethods = ["GET", "POST", "DELETE", "OPTIONS"] as const;
75const relayCorsAllowedHeaders = [81const relayCorsAllowedHeaders = [
76 "authorization",82 "authorization",
infra/relay/src/persistence/schema.ts+2-2
...@@ -138,7 +138,7 @@ export const relayAgentActivityRows = pgTable(...@@ -138,7 +138,7 @@ export const relayAgentActivityRows = pgTable(
138 {138 {
139 environmentId: varchar("environment_id", { length: 191 }).notNull(),139 environmentId: varchar("environment_id", { length: 191 }).notNull(),
140 environmentPublicKey: text("environment_public_key").notNull(),140 environmentPublicKey: text("environment_public_key").notNull(),
141 threadId: varchar("thread_id", { length: 191 }).notNull(),141 threadId: varchar("thread_id", { length: 512 }).notNull(),
142 stateJson: jsonb("state_json").notNull().$type<RelayAgentActivityState>(),142 stateJson: jsonb("state_json").notNull().$type<RelayAgentActivityState>(),
143 updatedAt: varchar("updated_at", { length: 64 }).notNull(),143 updatedAt: varchar("updated_at", { length: 64 }).notNull(),
144 createdAt: varchar("created_at", { length: 64 }).notNull(),144 createdAt: varchar("created_at", { length: 64 }).notNull(),
...@@ -156,7 +156,7 @@ export const relayDeliveryAttempts = pgTable(...@@ -156,7 +156,7 @@ export const relayDeliveryAttempts = pgTable(
156 createdAt: varchar("created_at", { length: 64 }).notNull(),156 createdAt: varchar("created_at", { length: 64 }).notNull(),
157 userId: varchar("user_id", { length: 255 }),157 userId: varchar("user_id", { length: 255 }),
158 environmentId: varchar("environment_id", { length: 191 }),158 environmentId: varchar("environment_id", { length: 191 }),
159 threadId: varchar("thread_id", { length: 191 }),159 threadId: varchar("thread_id", { length: 512 }),
160 deviceId: varchar("device_id", { length: 255 }),160 deviceId: varchar("device_id", { length: 255 }),
161 kind: varchar("kind", { length: 64 }).notNull(),161 kind: varchar("kind", { length: 64 }).notNull(),
162 sourceJobId: varchar("source_job_id", { length: 64 }),162 sourceJobId: varchar("source_job_id", { length: 64 }),
infra/relay/src/worker.ts+2
...@@ -23,6 +23,7 @@ import {...@@ -23,6 +23,7 @@ import {
23 healthApi,23 healthApi,
24 metadataApi,24 metadataApi,
25 mobileApi,25 mobileApi,
26 RELAY_HTTP_ROUTER_CONFIG,
26 relayClientAuthLayer,27 relayClientAuthLayer,
27 relayDpopClientAuthLayer,28 relayDpopClientAuthLayer,
28 relayCors,29 relayCors,
...@@ -345,6 +346,7 @@ export const ApiLive = Api.make(...@@ -345,6 +346,7 @@ export const ApiLive = Api.make(
345 relayNotFoundRoute,346 relayNotFoundRoute,
346 ).pipe(347 ).pipe(
347 HttpRouter.toHttpEffect,348 HttpRouter.toHttpEffect,
349 Effect.provideService(HttpRouter.RouterConfig, RELAY_HTTP_ROUTER_CONFIG),
348 withoutCapturedParentSpan,350 withoutCapturedParentSpan,
349 Effect.flatMap((httpEffect) => traceRelayHttpRequestWith(httpEffect, relayTraceLayer)),351 Effect.flatMap((httpEffect) => traceRelayHttpRequestWith(httpEffect, relayTraceLayer)),
350 );352 );