@oxy.so/federation 2.13.0 → 2.14.0

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.
@@ -7,8 +7,8 @@
7
7
  * because those are identical across every Oxy app: they bridge a federated follow
8
8
  * edge into the Oxy graph (via the identity adapter), record the AP-side follow
9
9
  * row (via the store adapter), and send the Accept back (via the delivery
10
- * service). Every CONTENT verb (Create / Announce / Like / Delete / Update, and a
11
- * non-follow Undo) is handed to the app-registered
10
+ * service). Every CONTENT verb (Create / Announce / Like / Delete / Update /
11
+ * Add / Remove, and a non-follow Undo) is handed to the app-registered
12
12
  * {@link InboundDispatcherConfig.onContentActivity} callback, where the app's own
13
13
  * post/engagement handlers live. The consent gate + notification side effects are
14
14
  * injected so the engine holds no app knowledge.
@@ -299,12 +299,15 @@ function createInboundDispatcher(config) {
299
299
  case 'Reject':
300
300
  await handleReject(activity, verifiedActorUri);
301
301
  break;
302
- // Content verbs — the app owns these (posts, engagement, actor profile edits).
302
+ // Content verbs — the app owns these (posts, engagement, actor profile
303
+ // edits, and collection changes such as pinned posts).
303
304
  case 'Create':
304
305
  case 'Delete':
305
306
  case 'Like':
306
307
  case 'Announce':
307
308
  case 'Update':
309
+ case 'Add':
310
+ case 'Remove':
308
311
  await config.onContentActivity(activity, verifiedActorUri);
309
312
  break;
310
313
  case 'Move': {
@@ -54,7 +54,7 @@ Object.defineProperty(exports, "DeliveryAuthorizationDeniedError", { enumerable:
54
54
  * Inbound ActivityPub dispatch — the untrusted-activity validator + switch, the
55
55
  * follow-protocol handlers (Follow / Accept / Undo(Follow) / Reject) over the
56
56
  * identity + store adapters, and the `onContentActivity` seam every content verb
57
- * (Create / Announce / Like / Delete / Update, non-follow Undo) is handed to.
57
+ * (Create / Announce / Like / Delete / Update / Add / Remove, non-follow Undo) is handed to.
58
58
  */
59
59
  var inboundDispatch_1 = require("./inboundDispatch");
60
60
  Object.defineProperty(exports, "createInboundDispatcher", { enumerable: true, get: function () { return inboundDispatch_1.createInboundDispatcher; } });
@@ -6,8 +6,8 @@
6
6
  * because those are identical across every Oxy app: they bridge a federated follow
7
7
  * edge into the Oxy graph (via the identity adapter), record the AP-side follow
8
8
  * row (via the store adapter), and send the Accept back (via the delivery
9
- * service). Every CONTENT verb (Create / Announce / Like / Delete / Update, and a
10
- * non-follow Undo) is handed to the app-registered
9
+ * service). Every CONTENT verb (Create / Announce / Like / Delete / Update /
10
+ * Add / Remove, and a non-follow Undo) is handed to the app-registered
11
11
  * {@link InboundDispatcherConfig.onContentActivity} callback, where the app's own
12
12
  * post/engagement handlers live. The consent gate + notification side effects are
13
13
  * injected so the engine holds no app knowledge.
@@ -294,12 +294,15 @@ export function createInboundDispatcher(config) {
294
294
  case 'Reject':
295
295
  await handleReject(activity, verifiedActorUri);
296
296
  break;
297
- // Content verbs — the app owns these (posts, engagement, actor profile edits).
297
+ // Content verbs — the app owns these (posts, engagement, actor profile
298
+ // edits, and collection changes such as pinned posts).
298
299
  case 'Create':
299
300
  case 'Delete':
300
301
  case 'Like':
301
302
  case 'Announce':
302
303
  case 'Update':
304
+ case 'Add':
305
+ case 'Remove':
303
306
  await config.onContentActivity(activity, verifiedActorUri);
304
307
  break;
305
308
  case 'Move': {
@@ -44,7 +44,7 @@ export { createDeliveryService, DeliveryAuthorizationDeniedError, } from './deli
44
44
  * Inbound ActivityPub dispatch — the untrusted-activity validator + switch, the
45
45
  * follow-protocol handlers (Follow / Accept / Undo(Follow) / Reject) over the
46
46
  * identity + store adapters, and the `onContentActivity` seam every content verb
47
- * (Create / Announce / Like / Delete / Update, non-follow Undo) is handed to.
47
+ * (Create / Announce / Like / Delete / Update / Add / Remove, non-follow Undo) is handed to.
48
48
  */
49
49
  export { createInboundDispatcher, ActorResolutionPendingError, } from './inboundDispatch.js';
50
50
  /** The WebFinger + host-meta discovery router (domain-parameterized, consent-gated). */
@@ -6,8 +6,8 @@
6
6
  * because those are identical across every Oxy app: they bridge a federated follow
7
7
  * edge into the Oxy graph (via the identity adapter), record the AP-side follow
8
8
  * row (via the store adapter), and send the Accept back (via the delivery
9
- * service). Every CONTENT verb (Create / Announce / Like / Delete / Update, and a
10
- * non-follow Undo) is handed to the app-registered
9
+ * service). Every CONTENT verb (Create / Announce / Like / Delete / Update /
10
+ * Add / Remove, and a non-follow Undo) is handed to the app-registered
11
11
  * {@link InboundDispatcherConfig.onContentActivity} callback, where the app's own
12
12
  * post/engagement handlers live. The consent gate + notification side effects are
13
13
  * injected so the engine holds no app knowledge.
@@ -157,7 +157,9 @@ export interface InboundDispatcherConfig {
157
157
  onOutboundFollowAccepted?(actorUri: string): Promise<void>;
158
158
  /**
159
159
  * Handle a CONTENT activity the engine does not own — Create / Announce / Like /
160
- * Delete / Update, and a non-follow Undo. The app's post/engagement handlers.
160
+ * Delete / Update / Add / Remove, and a non-follow Undo. The app's
161
+ * post/engagement handlers; `Add`/`Remove` carry collection changes such as a
162
+ * Mastodon pin (the status added to or removed from the actor's `featured`).
161
163
  */
162
164
  onContentActivity(activity: Record<string, unknown>, verifiedActorUri: string): Promise<void>;
163
165
  /**
@@ -44,7 +44,7 @@ export { createDeliveryService, DeliveryAuthorizationDeniedError, type DeliveryA
44
44
  * Inbound ActivityPub dispatch — the untrusted-activity validator + switch, the
45
45
  * follow-protocol handlers (Follow / Accept / Undo(Follow) / Reject) over the
46
46
  * identity + store adapters, and the `onContentActivity` seam every content verb
47
- * (Create / Announce / Like / Delete / Update, non-follow Undo) is handed to.
47
+ * (Create / Announce / Like / Delete / Update / Add / Remove, non-follow Undo) is handed to.
48
48
  */
49
49
  export { createInboundDispatcher, ActorResolutionPendingError, type InboundMove, type InboundDispatcher, type InboundDispatcherConfig, type InboundDispatcherLogger, type InboundActivityValidation, type InboundLocalUser, type InboundIdentity, type InboundConsent, type InboundActorResolver, type InboundFollowStore, type InboundDelivery, } from './inboundDispatch';
50
50
  /** The WebFinger + host-meta discovery router (domain-parameterized, consent-gated). */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oxy.so/federation",
3
- "version": "2.13.0",
3
+ "version": "2.14.0",
4
4
  "description": "Oxy Federation — the app-agnostic ActivityPub identity + follow engine substrate: the network-connector contract, normalized cross-network DTOs, HTTP signatures, actor resolution, the outbound delivery transport + follow lifecycle, the inbound dispatcher, and the webfinger/actor/inbox Express routers. Domain-parameterized so every Oxy app backend federates under its own domain.",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -375,7 +375,7 @@ describe('Move → onMove', () => {
375
375
  });
376
376
 
377
377
  describe('content verbs → onContentActivity', () => {
378
- it.each(['Create', 'Announce', 'Like', 'Delete', 'Update'])(
378
+ it.each(['Create', 'Announce', 'Like', 'Delete', 'Update', 'Add', 'Remove'])(
379
379
  'routes %s to the app',
380
380
  async (type) => {
381
381
  const rig = makeRig();
@@ -404,7 +404,7 @@ describe('content verbs → onContentActivity', () => {
404
404
  describe('blocked-origin domain policy', () => {
405
405
  const BLOCKED_ACTOR = 'https://spam.example/users/mallory';
406
406
 
407
- it.each(['Create', 'Announce', 'Like', 'Delete', 'Update'])(
407
+ it.each(['Create', 'Announce', 'Like', 'Delete', 'Update', 'Add', 'Remove'])(
408
408
  'drops %s from a blocked origin without reaching the app',
409
409
  async (type) => {
410
410
  const rig = makeRig({ blockedHosts: ['spam.example'] });
@@ -6,8 +6,8 @@
6
6
  * because those are identical across every Oxy app: they bridge a federated follow
7
7
  * edge into the Oxy graph (via the identity adapter), record the AP-side follow
8
8
  * row (via the store adapter), and send the Accept back (via the delivery
9
- * service). Every CONTENT verb (Create / Announce / Like / Delete / Update, and a
10
- * non-follow Undo) is handed to the app-registered
9
+ * service). Every CONTENT verb (Create / Announce / Like / Delete / Update /
10
+ * Add / Remove, and a non-follow Undo) is handed to the app-registered
11
11
  * {@link InboundDispatcherConfig.onContentActivity} callback, where the app's own
12
12
  * post/engagement handlers live. The consent gate + notification side effects are
13
13
  * injected so the engine holds no app knowledge.
@@ -186,7 +186,9 @@ export interface InboundDispatcherConfig {
186
186
  onOutboundFollowAccepted?(actorUri: string): Promise<void>;
187
187
  /**
188
188
  * Handle a CONTENT activity the engine does not own — Create / Announce / Like /
189
- * Delete / Update, and a non-follow Undo. The app's post/engagement handlers.
189
+ * Delete / Update / Add / Remove, and a non-follow Undo. The app's
190
+ * post/engagement handlers; `Add`/`Remove` carry collection changes such as a
191
+ * Mastodon pin (the status added to or removed from the actor's `featured`).
190
192
  */
191
193
  onContentActivity(activity: Record<string, unknown>, verifiedActorUri: string): Promise<void>;
192
194
  /**
@@ -499,12 +501,15 @@ export function createInboundDispatcher(config: InboundDispatcherConfig): Inboun
499
501
  case 'Reject':
500
502
  await handleReject(activity, verifiedActorUri);
501
503
  break;
502
- // Content verbs — the app owns these (posts, engagement, actor profile edits).
504
+ // Content verbs — the app owns these (posts, engagement, actor profile
505
+ // edits, and collection changes such as pinned posts).
503
506
  case 'Create':
504
507
  case 'Delete':
505
508
  case 'Like':
506
509
  case 'Announce':
507
510
  case 'Update':
511
+ case 'Add':
512
+ case 'Remove':
508
513
  await config.onContentActivity(activity, verifiedActorUri);
509
514
  break;
510
515
  case 'Move': {
package/src/node/index.ts CHANGED
@@ -109,7 +109,7 @@ export {
109
109
  * Inbound ActivityPub dispatch — the untrusted-activity validator + switch, the
110
110
  * follow-protocol handlers (Follow / Accept / Undo(Follow) / Reject) over the
111
111
  * identity + store adapters, and the `onContentActivity` seam every content verb
112
- * (Create / Announce / Like / Delete / Update, non-follow Undo) is handed to.
112
+ * (Create / Announce / Like / Delete / Update / Add / Remove, non-follow Undo) is handed to.
113
113
  */
114
114
  export {
115
115
  createInboundDispatcher,