@takosjp/yurucommu-core 3.4.3 → 3.4.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. package/migrations/0023_delivery_resolution_outbox.sql +33 -0
  2. package/migrations/0024_delivery_fanout_outbox.sql +35 -0
  3. package/migrations/0025_delivery_endpoint_terminal_retention.sql +6 -0
  4. package/migrations/0026_remote_actor_fetch_failures.sql +29 -0
  5. package/migrations/0027_remote_actor_tombstones.sql +12 -0
  6. package/migrations/0028_remote_actor_delivery_fence.sql +30 -0
  7. package/migrations/0029_delivery_endpoint_recipients.sql +47 -0
  8. package/package.json +2 -1
  9. package/packages/api/package.json +1 -1
  10. package/packages/api/src/lib/api/communities.ts +2 -0
  11. package/packages/api/src/lib/api/fetch.ts +69 -13
  12. package/packages/api/src/lib/api/normalize.ts +32 -10
  13. package/packages/api/src/lib/api/notifications.ts +4 -1
  14. package/packages/api/src/lib/rtc-client.ts +127 -29
  15. package/src/backend/federation-helpers.ts +1 -0
  16. package/src/backend/index.ts +16 -3
  17. package/src/backend/lib/account-migration.ts +340 -0
  18. package/src/backend/lib/activity-delete-cascade.ts +193 -0
  19. package/src/backend/lib/activitypub-actor-cache.ts +615 -48
  20. package/src/backend/lib/activitypub-actor-identity-sql.ts +179 -0
  21. package/src/backend/lib/activitypub-actor-identity.ts +39 -0
  22. package/src/backend/lib/activitypub-validators.ts +62 -4
  23. package/src/backend/lib/ap-ids.ts +36 -6
  24. package/src/backend/lib/ap-verify.ts +7 -17
  25. package/src/backend/lib/blocklist-purge.ts +676 -42
  26. package/src/backend/lib/blocklist.ts +278 -39
  27. package/src/backend/lib/community-visibility.ts +47 -33
  28. package/src/backend/lib/delivery/fanout-outbox.ts +336 -0
  29. package/src/backend/lib/delivery/planner.ts +16 -12
  30. package/src/backend/lib/delivery/queue-batching.ts +389 -145
  31. package/src/backend/lib/delivery/queue-delivery.ts +47 -25
  32. package/src/backend/lib/delivery/queue.ts +479 -73
  33. package/src/backend/lib/delivery/resolution-outbox.ts +456 -0
  34. package/src/backend/lib/delivery/types.ts +31 -7
  35. package/src/backend/lib/feed-exclude.ts +40 -28
  36. package/src/backend/lib/follow-edge-mutations.ts +217 -0
  37. package/src/backend/lib/notification-eligibility.ts +15 -9
  38. package/src/backend/lib/notification-push.ts +2 -2
  39. package/src/backend/lib/oidc-id-token.ts +66 -0
  40. package/src/backend/lib/personal-actor-moderation.ts +239 -0
  41. package/src/backend/lib/post-visibility.ts +79 -16
  42. package/src/backend/lib/remote-activity-id.ts +61 -0
  43. package/src/backend/lib/unread-counts.ts +3 -0
  44. package/src/backend/retention.ts +38 -1
  45. package/src/backend/routes/account-teardown.ts +422 -156
  46. package/src/backend/routes/activitypub/handlers/actor-inbox-handlers.ts +104 -105
  47. package/src/backend/routes/activitypub/handlers/inbound-community-scope.ts +121 -0
  48. package/src/backend/routes/activitypub/handlers/inbound-object-identity.ts +54 -0
  49. package/src/backend/routes/activitypub/handlers/inbound-reply-target.ts +34 -0
  50. package/src/backend/routes/activitypub/handlers/inbound-story-projection.ts +438 -0
  51. package/src/backend/routes/activitypub/handlers/inbox-content-handlers.ts +1121 -806
  52. package/src/backend/routes/activitypub/handlers/inbox-follow-handlers.ts +118 -153
  53. package/src/backend/routes/activitypub/handlers/inbox-interaction-handlers.ts +185 -168
  54. package/src/backend/routes/activitypub/handlers/inbox-shared-helpers.ts +220 -32
  55. package/src/backend/routes/activitypub/inbound-activity-identity.ts +16 -0
  56. package/src/backend/routes/activitypub/inbound-activity-reference.ts +116 -0
  57. package/src/backend/routes/activitypub/inbound-addressing.ts +87 -0
  58. package/src/backend/routes/activitypub/inbox-addressing.ts +22 -19
  59. package/src/backend/routes/activitypub/inbox-types.ts +14 -2
  60. package/src/backend/routes/activitypub/inbox.ts +81 -105
  61. package/src/backend/routes/activitypub/outbox.ts +0 -0
  62. package/src/backend/routes/activitypub.ts +6 -5
  63. package/src/backend/routes/actors-helpers.ts +34 -8
  64. package/src/backend/routes/actors.ts +328 -164
  65. package/src/backend/routes/auth-helpers.ts +57 -9
  66. package/src/backend/routes/auth.ts +10 -2
  67. package/src/backend/routes/communities/membership-invites.ts +4 -1
  68. package/src/backend/routes/communities/membership-members.ts +201 -73
  69. package/src/backend/routes/communities/membership-requests.ts +141 -76
  70. package/src/backend/routes/communities/membership-shared.ts +228 -21
  71. package/src/backend/routes/communities/messages.ts +9 -2
  72. package/src/backend/routes/communities/routes.ts +48 -13
  73. package/src/backend/routes/dm/contacts.ts +29 -41
  74. package/src/backend/routes/dm/conversations-helpers.ts +9 -1
  75. package/src/backend/routes/dm/messages.ts +36 -42
  76. package/src/backend/routes/dm/read-archive.ts +4 -2
  77. package/src/backend/routes/dm/requests.ts +62 -54
  78. package/src/backend/routes/follow-helpers.ts +200 -60
  79. package/src/backend/routes/follow.ts +146 -140
  80. package/src/backend/routes/media.ts +20 -94
  81. package/src/backend/routes/moderation.ts +72 -4
  82. package/src/backend/routes/notes.ts +3 -4
  83. package/src/backend/routes/notifications.ts +209 -108
  84. package/src/backend/routes/posts/delete-cascade.ts +253 -89
  85. package/src/backend/routes/posts/federation.ts +373 -0
  86. package/src/backend/routes/posts/interactions.ts +160 -184
  87. package/src/backend/routes/posts/like-mutation.ts +240 -0
  88. package/src/backend/routes/posts/post-helpers.ts +112 -162
  89. package/src/backend/routes/posts/queries.ts +150 -54
  90. package/src/backend/routes/posts/routes.ts +169 -329
  91. package/src/backend/routes/posts/transformers.ts +61 -6
  92. package/src/backend/routes/recommendations.ts +37 -44
  93. package/src/backend/routes/rtc/index.ts +26 -6
  94. package/src/backend/routes/search.ts +39 -55
  95. package/src/backend/routes/stories/interactions.ts +22 -6
  96. package/src/backend/routes/stories/query-helpers.ts +28 -41
  97. package/src/backend/routes/stories/routes.ts +125 -108
  98. package/src/backend/routes/takos-tools/dm.ts +17 -17
  99. package/src/backend/routes/takos-tools/posts.ts +189 -106
  100. package/src/backend/routes/takos-tools/search.ts +13 -4
  101. package/src/backend/routes/takos-tools/timeline.ts +35 -27
  102. package/src/backend/routes/takos-tools-response.ts +6 -2
  103. package/src/backend/routes/timeline.ts +5 -5
  104. package/src/backend/runtime/call-signaling-do.ts +35 -4
  105. package/src/backend/runtime/one-time-ticket.ts +116 -0
  106. package/src/backend/runtime/realtime-stream-do.ts +5 -61
  107. package/src/backend/runtime/signaling-hub.ts +36 -3
  108. package/src/backend/server.ts +95 -80
  109. package/src/db/d1-write.ts +67 -43
  110. package/src/db/schema/federation.ts +42 -1
  111. package/src/db/schema/messaging.ts +110 -2
  112. package/src/db/schema.ts +1 -1
@@ -9,6 +9,7 @@ import type { Database } from "../../../db/index.ts";
9
9
  import { and, eq, lt, notInArray, or, sql } from "drizzle-orm";
10
10
  import {
11
11
  activities,
12
+ affectedRowCount,
12
13
  actorCache,
13
14
  actors,
14
15
  communities,
@@ -92,15 +93,18 @@ type TimedFetchResult = {
92
93
  latencyMs: number;
93
94
  };
94
95
 
96
+ type DeliveryFetch = typeof fetchWithTimeout;
97
+
95
98
  async function timedFetch(
96
99
  url: string,
97
100
  init: RequestInit & { timeout: number },
101
+ deliveryFetch: DeliveryFetch,
98
102
  ): Promise<TimedFetchResult> {
99
103
  const startedAt = Date.now();
100
104
  let response: Response | null = null;
101
105
  let error: unknown = null;
102
106
  try {
103
- response = await fetchWithTimeout(url, init);
107
+ response = await deliveryFetch(url, init);
104
108
  } catch (e) {
105
109
  error = e;
106
110
  }
@@ -150,7 +154,10 @@ async function resolveSigningActor(
150
154
  return { apId: actorRow.apId, privateKeyPem: actorRow.privateKeyPem };
151
155
  }
152
156
 
153
- // Check communities table
157
+ // Check communities table. Retired Groups deliberately keep this key until
158
+ // their Delete + older Group-authored activity projections drain; scheduled
159
+ // tombstone retention then scrubs it to an empty string while preserving the
160
+ // deleted community row as a permanent read-gate fact.
154
161
  const communityRow = await db
155
162
  .select({
156
163
  apId: communities.apId,
@@ -226,6 +233,7 @@ async function maybeShadowProbeInbox(
226
233
  sender: { apId: string; privateKeyPem: string };
227
234
  body: string;
228
235
  },
236
+ deliveryFetch: DeliveryFetch,
229
237
  ): Promise<void> {
230
238
  const allowedHosts = parseCommaSeparated(env.DELIVERY_SHADOW_PROBE_HOSTS);
231
239
  if (allowedHosts.length === 0) return;
@@ -257,16 +265,20 @@ async function maybeShadowProbeInbox(
257
265
  params.body,
258
266
  );
259
267
 
260
- const { response, error, latencyMs } = await timedFetch(inbox, {
261
- method: "POST",
262
- headers: {
263
- ...headers,
264
- "Content-Type": "application/activity+json",
265
- "X-Yurucommu-Shadow-Probe": "1",
268
+ const { response, error, latencyMs } = await timedFetch(
269
+ inbox,
270
+ {
271
+ method: "POST",
272
+ headers: {
273
+ ...headers,
274
+ "Content-Type": "application/activity+json",
275
+ "X-Yurucommu-Shadow-Probe": "1",
276
+ },
277
+ body: params.body,
278
+ timeout: DELIVERY_HTTP_TIMEOUT_MS,
266
279
  },
267
- body: params.body,
268
- timeout: DELIVERY_HTTP_TIMEOUT_MS,
269
- });
280
+ deliveryFetch,
281
+ );
270
282
 
271
283
  emitMetric("delivery_shadow_probe_inbox_latency_ms", latencyMs, {
272
284
  endpoint_host: params.endpointHost,
@@ -288,6 +300,7 @@ export async function processDeliverEndpoint(
288
300
  msg: DeliveryDeliverEndpointMessageV1,
289
301
  message: IQueueMessage<DeliveryQueueMessageV1>,
290
302
  bulkhead: Bulkhead,
303
+ deliveryFetch: DeliveryFetch = fetchWithTimeout,
291
304
  ): Promise<void> {
292
305
  if (!requireQueue(env, "deliver_endpoint", message)) return;
293
306
 
@@ -414,7 +427,7 @@ export async function processDeliverEndpoint(
414
427
  ),
415
428
  ),
416
429
  );
417
- if (((claim as { meta?: { changes?: number } }).meta?.changes ?? 0) === 0) {
430
+ if (affectedRowCount(claim) === 0) {
418
431
  message.ack();
419
432
  return;
420
433
  }
@@ -448,12 +461,16 @@ export async function processDeliverEndpoint(
448
461
  body,
449
462
  );
450
463
 
451
- const { response, error, latencyMs } = await timedFetch(endpoint, {
452
- method: "POST",
453
- headers: { ...headers, "Content-Type": "application/activity+json" },
454
- body,
455
- timeout: DELIVERY_HTTP_TIMEOUT_MS,
456
- });
464
+ const { response, error, latencyMs } = await timedFetch(
465
+ endpoint,
466
+ {
467
+ method: "POST",
468
+ headers: { ...headers, "Content-Type": "application/activity+json" },
469
+ body,
470
+ timeout: DELIVERY_HTTP_TIMEOUT_MS,
471
+ },
472
+ deliveryFetch,
473
+ );
457
474
 
458
475
  emitMetric("delivery_latency_ms", latencyMs, {
459
476
  endpoint_host: host,
@@ -501,13 +518,18 @@ export async function processDeliverEndpoint(
501
518
  // Shadow probe (staging-only)
502
519
  if (job.attempts === 0) {
503
520
  try {
504
- await maybeShadowProbeInbox(db, env, {
505
- activityId: job.activityApId,
506
- sharedInboxEndpoint: endpoint,
507
- endpointHost: host,
508
- sender,
509
- body,
510
- });
521
+ await maybeShadowProbeInbox(
522
+ db,
523
+ env,
524
+ {
525
+ activityId: job.activityApId,
526
+ sharedInboxEndpoint: endpoint,
527
+ endpointHost: host,
528
+ sender,
529
+ body,
530
+ },
531
+ deliveryFetch,
532
+ );
511
533
  } catch (e) {
512
534
  log.warn("Shadow probe failed", {
513
535
  event: "delivery.shadow_probe.failed",