@fedify/fedify 0.11.0-dev.243 → 0.11.0-dev.245

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.
package/CHANGES.md CHANGED
@@ -25,6 +25,10 @@ To be released.
25
25
  - Added `Context.getFeaturedUri()` method.
26
26
  - Added `{ type: "featured"; handle: string }` case to `ParseUriResult`
27
27
  type.
28
+ - Added `Federation.setFeaturedTagsDispatcher()` method.
29
+ - Added `Context.getFeaturedTagsUri()` method.
30
+ - Added `{ type: "featuredTags"; handle: string }` case to
31
+ `ParseUriResult` type.
28
32
 
29
33
  - Frequently used JSON-LD contexts are now preloaded. [[#74]]
30
34
 
@@ -49,15 +53,64 @@ To be released.
49
53
  - `Collection.current`
50
54
  - `Collection.first`
51
55
  - `Collection.last`
52
- - `Collection.items`
53
56
  - `CollectionPage.partOf`
54
57
  - `CollectionPage.next`
55
58
  - `CollectionPage.prev`
56
59
 
60
+ - Added `featured` property to `Actor` types in Activity Vocabulary API.
61
+ [[#78]]
62
+
63
+ - Added `Application.getFeatured()` method.
64
+ - Added `Application.featuredId` property.
65
+ - `new Application()` constructor now accepts `featured` option.
66
+ - `Application.clone()` method now accepts `featured` option.
67
+ - Added `Group.getFeatured()` method.
68
+ - Added `Group.featuredId` property.
69
+ - `new Group()` constructor now accepts `featured` option.
70
+ - `Group.clone()` method now accepts `featured` option.
71
+ - Added `Organization.getFeatured()` method.
72
+ - Added `Organization.featuredId` property.
73
+ - `new Organization()` constructor now accepts `featured` option.
74
+ - `Organization.clone()` method now accepts `featured` option.
75
+ - Added `Person.getFeatured()` method.
76
+ - Added `Person.featuredId` property.
77
+ - `new Person()` constructor now accepts `featured` option.
78
+ - `Person.clone()` method now accepts `featured` option.
79
+ - Added `Service.getFeatured()` method.
80
+ - Added `Service.featuredId` property.
81
+ - `new Service()` constructor now accepts `featured` option.
82
+ - `Service.clone()` method now accepts `featured` option.
83
+
84
+ - Added `featuredTags` property to `Actor` types in Activity Vocabulary API.
85
+ [[#78]]
86
+
87
+ - Added `Application.getFeaturedTags()` method.
88
+ - Added `Application.featuredTagsId` property.
89
+ - `new Application()` constructor now accepts `featuredTags` option.
90
+ - `Application.clone()` method now accepts `featuredTags` option.
91
+ - Added `Group.getFeaturedTags()` method.
92
+ - Added `Group.featuredTagsId` property.
93
+ - `new Group()` constructor now accepts `featuredTags` option.
94
+ - `Group.clone()` method now accepts `featuredTags` option.
95
+ - Added `Organization.getFeaturedTags()` method.
96
+ - Added `Organization.featuredTagsId` property.
97
+ - `new Organization()` constructor now accepts `featuredTags` option.
98
+ - `Organization.clone()` method now accepts `featuredTags` option.
99
+ - Added `Person.getFeaturedTags()` method.
100
+ - Added `Person.featuredTagsId` property.
101
+ - `new Person()` constructor now accepts `featuredTags` option.
102
+ - `Person.clone()` method now accepts `featuredTags` option.
103
+ - Added `Service.getFeaturedTags()` method.
104
+ - Added `Service.featuredTagsId` property.
105
+ - `new Service()` constructor now accepts `featuredTags` option.
106
+ - `Service.clone()` method now accepts `featuredTags` option.
107
+
57
108
  - Added `target` property to `Activity` class in Activity Vocabulary API.
58
109
 
59
110
  - Added `Activity.getTarget()` method.
60
111
  - Added `Activity.getTargets()` method.
112
+ - Added `Activity.targetId` property.
113
+ - Added `Activity.targetIds` property.
61
114
  - `new Activity()` constructor now accepts `target` option.
62
115
  - `new Activity()` constructor now accepts `targets` option.
63
116
  - `Activity.clone()` method now accepts `target` option.
@@ -67,6 +120,8 @@ To be released.
67
120
 
68
121
  - Added `Activity.getResult()` method.
69
122
  - Added `Activity.getResults()` method.
123
+ - Added `Activity.resultId` property.
124
+ - Added `Activity.resultIds` property.
70
125
  - `new Activity()` constructor now accepts `result` option.
71
126
  - `new Activity()` constructor now accepts `results` option.
72
127
  - `Activity.clone()` method now accepts `result` option.
@@ -76,6 +131,8 @@ To be released.
76
131
 
77
132
  - Added `Activity.getOrigin()` method.
78
133
  - Added `Activity.getOrigins()` method.
134
+ - Added `Activity.originId` property.
135
+ - Added `Activity.originIds` property.
79
136
  - `new Activity()` constructor now accepts `origin` option.
80
137
  - `new Activity()` constructor now accepts `origins` option.
81
138
  - `Activity.clone()` method now accepts `origin` option.
@@ -85,6 +142,8 @@ To be released.
85
142
 
86
143
  - Added `Activity.getInstrument()` method.
87
144
  - Added `Activity.getInstruments()` method.
145
+ - Added `Activity.instrumentId` property.
146
+ - Added `Activity.instrumentIds` property.
88
147
  - `new Activity()` constructor now accepts `instrument` option.
89
148
  - `new Activity()` constructor now accepts `instruments` option.
90
149
  - `Activity.clone()` method now accepts `instrument` option.
@@ -103,6 +162,10 @@ To be released.
103
162
  - Renamed `InboxListenerSetter` interface to `InboxListenerSetters`.
104
163
  - Added `InboxListenerSetters.setSharedKeyDispatcher()` method.
105
164
 
165
+ - Followed up the [change in `eddsa-jcs-2022` specification][eddsa-jcs-2022]
166
+ for Object Integrity Proofs. [[FEP-8b32], [#54]]
167
+
168
+ [eddsa-jcs-2022]: https://codeberg.org/fediverse/fep/pulls/338
106
169
  [#71]: https://github.com/dahlia/fedify/issues/71
107
170
  [#74]: https://github.com/dahlia/fedify/issues/74
108
171
  [#76]: https://github.com/dahlia/fedify/pull/76
@@ -4,7 +4,7 @@ import { accepts } from "../deps/jsr.io/@std/http/0.224.5/negotiation.js";
4
4
  import { verifyRequest } from "../sig/http.js";
5
5
  import { doesActorOwnKey } from "../sig/owner.js";
6
6
  import { verifyObject } from "../sig/proof.js";
7
- import { Activity, Object, OrderedCollection, OrderedCollectionPage, } from "../vocab/vocab.js";
7
+ import { Activity, Link, Object, OrderedCollection, OrderedCollectionPage, } from "../vocab/vocab.js";
8
8
  export function acceptsJsonLd(request) {
9
9
  const types = accepts(request);
10
10
  if (types == null)
@@ -146,7 +146,7 @@ function filterCollectionItems(items, collectionName, filterPredicate) {
146
146
  let logged = false;
147
147
  for (const item of items) {
148
148
  let mappedItem;
149
- if (item instanceof Object || item instanceof URL) {
149
+ if (item instanceof Object || item instanceof Link || item instanceof URL) {
150
150
  mappedItem = item;
151
151
  }
152
152
  else if (item.id == null)
@@ -49,6 +49,7 @@ export class Federation {
49
49
  #followersCallbacks;
50
50
  #likedCallbacks;
51
51
  #featuredCallbacks;
52
+ #featuredTagsCallbacks;
52
53
  #inboxListeners;
53
54
  #inboxErrorHandler;
54
55
  #sharedInboxKeyDispatcher;
@@ -348,6 +349,20 @@ export class Federation {
348
349
  "URI. Set the property with Context.getFeaturedUri(handle).");
349
350
  }
350
351
  }
352
+ if (this.#featuredTagsCallbacks != null &&
353
+ this.#featuredTagsCallbacks.dispatcher != null) {
354
+ if (actor?.featuredTagsId == null) {
355
+ logger.warn("You configured a featured tags collection dispatcher, but the " +
356
+ "actor does not have a featuredTags property. Set the property " +
357
+ "with Context.getFeaturedTagsUri(handle).");
358
+ }
359
+ else if (actor.featuredTagsId.href != context.getFeaturedTagsUri(handle).href) {
360
+ logger.warn("You configured a featured tags collection dispatcher, but the " +
361
+ "actor's featuredTags property does not match the featured tags " +
362
+ "collection URI. Set the property with " +
363
+ "Context.getFeaturedTagsUri(handle).");
364
+ }
365
+ }
351
366
  if (this.#router.has("inbox")) {
352
367
  if (actor.inboxId == null) {
353
368
  logger.warn("You configured inbox listeners, but the actor does not " +
@@ -716,6 +731,51 @@ export class Federation {
716
731
  };
717
732
  return setters;
718
733
  }
734
+ /**
735
+ * Registers a featured tags collection dispatcher.
736
+ * @param path The URI path pattern for the featured tags collection.
737
+ * The syntax is based on URI Template
738
+ * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). The path
739
+ * must have one variable: `{handle}`.
740
+ * @param dispatcher A featured tags collection callback to register.
741
+ * @returns An object with methods to set other featured tags collection
742
+ * callbacks.
743
+ * @throws {@link RouterError} Thrown if the path pattern is invalid.
744
+ * @since 0.11.0
745
+ */
746
+ setFeaturedTagsDispatcher(path, dispatcher) {
747
+ if (this.#router.has("featuredTags")) {
748
+ throw new RouterError("Featured tags collection dispatcher already set.");
749
+ }
750
+ const variables = this.#router.add(path, "featuredTags");
751
+ if (variables.size !== 1 || !variables.has("handle")) {
752
+ throw new RouterError("Path for featured tags collection dispatcher must have one " +
753
+ "variable: {handle}");
754
+ }
755
+ const callbacks = {
756
+ dispatcher,
757
+ };
758
+ this.#featuredTagsCallbacks = callbacks;
759
+ const setters = {
760
+ setCounter(counter) {
761
+ callbacks.counter = counter;
762
+ return setters;
763
+ },
764
+ setFirstCursor(cursor) {
765
+ callbacks.firstCursor = cursor;
766
+ return setters;
767
+ },
768
+ setLastCursor(cursor) {
769
+ callbacks.lastCursor = cursor;
770
+ return setters;
771
+ },
772
+ authorize(predicate) {
773
+ callbacks.authorizePredicate = predicate;
774
+ return setters;
775
+ },
776
+ };
777
+ return setters;
778
+ }
719
779
  /**
720
780
  * Assigns the URL path for the inbox and starts setting inbox listeners.
721
781
  *
@@ -1062,6 +1122,16 @@ export class Federation {
1062
1122
  onNotFound,
1063
1123
  onNotAcceptable,
1064
1124
  });
1125
+ case "featuredTags":
1126
+ return await handleCollection(request, {
1127
+ name: "featured tags",
1128
+ handle: route.values.handle,
1129
+ context,
1130
+ collectionCallbacks: this.#featuredTagsCallbacks,
1131
+ onUnauthorized,
1132
+ onNotFound,
1133
+ onNotAcceptable,
1134
+ });
1065
1135
  default: {
1066
1136
  const response = onNotFound(request);
1067
1137
  return response instanceof Promise ? await response : response;
@@ -1174,6 +1244,13 @@ class ContextImpl {
1174
1244
  }
1175
1245
  return new URL(path, this.#url);
1176
1246
  }
1247
+ getFeaturedTagsUri(handle) {
1248
+ const path = this.#router.build("featuredTags", { handle });
1249
+ if (path == null) {
1250
+ throw new RouterError("No featured tags collection path registered.");
1251
+ }
1252
+ return new URL(path, this.#url);
1253
+ }
1177
1254
  parseUri(uri) {
1178
1255
  if (uri.origin !== this.#url.origin)
1179
1256
  return null;
@@ -1213,6 +1290,9 @@ class ContextImpl {
1213
1290
  else if (route.name === "featured") {
1214
1291
  return { type: "featured", handle: route.values.handle };
1215
1292
  }
1293
+ else if (route.name === "featuredTags") {
1294
+ return { type: "featuredTags", handle: route.values.handle };
1295
+ }
1216
1296
  return null;
1217
1297
  }
1218
1298
  getHandleFromActorUri(actorUri) {
package/esm/sig/proof.js CHANGED
@@ -1,10 +1,10 @@
1
1
  import * as dntShim from "../_dnt.shims.js";
2
+ import { Activity, Multikey } from "../vocab/mod.js";
3
+ import { getLogger } from "@logtape/logtape";
2
4
  // @ts-ignore: json-canon is not typed
3
5
  import serialize from "json-canon";
4
6
  import { DataIntegrityProof } from "../vocab/vocab.js";
5
7
  import { fetchKey, validateCryptoKey } from "./key.js";
6
- import { Activity, Multikey } from "../vocab/mod.js";
7
- import { getLogger } from "@logtape/logtape";
8
8
  const logger = getLogger(["fedify", "sig", "proof"]);
9
9
  /**
10
10
  * Creates a proof for the given object.
@@ -32,13 +32,8 @@ export async function createProof(object, privateKey, keyId, { contextLoader, co
32
32
  const msgDigest = await dntShim.crypto.subtle.digest("SHA-256", msgBytes);
33
33
  created ??= dntShim.Temporal.Now.instant();
34
34
  const proofConfig = {
35
- // The below commented out line is needed according to section 3.3.1 of
36
- // the Data Integrity EdDSA Cryptosuites v1.0 spec, the FEP-8b32 spec does
37
- // not reflect this step; however, the FEP-8b32 spec will be updated to
38
- // be consistent with the Data Integrity EdDSA Cryptosuites v1.0 spec
39
- // some time soon. Before that happens, the below line is commented out.
40
- // See also: https://socialhub.activitypub.rocks/t/fep-8b32-object-integrity-proofs/2725/91?u=hongminhee
41
- // "@context": (compactMsg as any)["@context"],
35
+ // deno-lint-ignore no-explicit-any
36
+ "@context": compactMsg["@context"],
42
37
  type: "DataIntegrityProof",
43
38
  cryptosuite: "eddsa-jcs-2022",
44
39
  verificationMethod: keyId.href,
@@ -98,13 +93,8 @@ export async function verifyProof(jsonLd, proof, options = {}) {
98
93
  return null;
99
94
  const publicKeyPromise = fetchKey(proof.verificationMethodId, Multikey, options);
100
95
  const proofConfig = {
101
- // The below commented out line is needed according to section 3.3.1 of
102
- // the Data Integrity EdDSA Cryptosuites v1.0 spec, the FEP-8b32 spec does
103
- // not reflect this step; however, the FEP-8b32 spec will be updated to
104
- // be consistent with the Data Integrity EdDSA Cryptosuites v1.0 spec
105
- // some time soon. Before that happens, the below line is commented out.
106
- // See also: https://socialhub.activitypub.rocks/t/fep-8b32-object-integrity-proofs/2725/91?u=hongminhee
107
- // "@context": (jsonLd as any)["@context"],
96
+ // deno-lint-ignore no-explicit-any
97
+ "@context": jsonLd["@context"],
108
98
  type: "DataIntegrityProof",
109
99
  cryptosuite: proof.cryptosuite,
110
100
  verificationMethod: proof.verificationMethodId.href,
@@ -15,6 +15,9 @@ defaultContext:
15
15
  featured:
16
16
  "@id": "toot:featured"
17
17
  "@type": "@id"
18
+ featuredTags:
19
+ "@id": "toot:featuredTags"
20
+ "@type": "@id"
18
21
  discoverable: "toot:discoverable"
19
22
  suspended: "toot:suspended"
20
23
  memorial: "toot:memorial"
@@ -157,6 +160,17 @@ properties:
157
160
  range:
158
161
  - "https://www.w3.org/ns/activitystreams#Collection"
159
162
 
163
+ - singularName: featuredTags
164
+ functional: true
165
+ uri: "http://joinmastodon.org/ns#featuredTags"
166
+ description: |
167
+ What is known in Mastodon as "featured hashtags", hashtags that are featured
168
+ at people's profiles, is implemented using an extra property `featuredTags`
169
+ on the actor object that points to a {@link Collection} of {@link Hashtag}
170
+ objects specifically.
171
+ range:
172
+ - "https://www.w3.org/ns/activitystreams#Collection"
173
+
160
174
  - pluralName: streams
161
175
  singularName: stream
162
176
  singularAccessor: false
@@ -9,7 +9,13 @@ description: |
9
9
 
10
10
  Refer to the Activity Streams 2.0 Core specification for a complete
11
11
  description of the Collection type.
12
- defaultContext: "https://www.w3.org/ns/activitystreams"
12
+ defaultContext:
13
+ - "https://www.w3.org/ns/activitystreams"
14
+ - "https://w3id.org/security/data-integrity/v1"
15
+ - toot: "http://joinmastodon.org/ns#"
16
+ sensitive: "as:sensitive"
17
+ Emoji: "toot:Emoji"
18
+ Hashtag: "as:Hashtag"
13
19
 
14
20
  properties:
15
21
  - singularName: totalItems
@@ -57,3 +63,4 @@ properties:
57
63
  or unordered.
58
64
  range:
59
65
  - "https://www.w3.org/ns/activitystreams#Object"
66
+ - "https://www.w3.org/ns/activitystreams#Link"
@@ -7,7 +7,13 @@ description: |
7
7
  Used to represent distinct subsets of items from a `Collection`.
8
8
  Refer to the Activity Streams 2.0 Core for a complete description of
9
9
  the `CollectionPage` object.
10
- defaultContext: "https://www.w3.org/ns/activitystreams"
10
+ defaultContext:
11
+ - "https://www.w3.org/ns/activitystreams"
12
+ - "https://w3id.org/security/data-integrity/v1"
13
+ - toot: "http://joinmastodon.org/ns#"
14
+ sensitive: "as:sensitive"
15
+ Emoji: "toot:Emoji"
16
+ Hashtag: "as:Hashtag"
11
17
 
12
18
  properties:
13
19
  - singularName: partOf
@@ -15,6 +15,9 @@ defaultContext:
15
15
  featured:
16
16
  "@id": "toot:featured"
17
17
  "@type": "@id"
18
+ featuredTags:
19
+ "@id": "toot:featuredTags"
20
+ "@type": "@id"
18
21
  discoverable: "toot:discoverable"
19
22
  suspended: "toot:suspended"
20
23
  memorial: "toot:memorial"
@@ -157,6 +160,17 @@ properties:
157
160
  range:
158
161
  - "https://www.w3.org/ns/activitystreams#Collection"
159
162
 
163
+ - singularName: featuredTags
164
+ functional: true
165
+ uri: "http://joinmastodon.org/ns#featuredTags"
166
+ description: |
167
+ What is known in Mastodon as "featured hashtags", hashtags that are featured
168
+ at people's profiles, is implemented using an extra property `featuredTags`
169
+ on the actor object that points to a {@link Collection} of {@link Hashtag}
170
+ objects specifically.
171
+ range:
172
+ - "https://www.w3.org/ns/activitystreams#Collection"
173
+
160
174
  - pluralName: streams
161
175
  singularName: stream
162
176
  singularAccessor: false
@@ -6,7 +6,13 @@ entity: true
6
6
  description: |
7
7
  A subtype of {@link Collection} in which members of the logical collection
8
8
  are assumed to always be strictly ordered.
9
- defaultContext: "https://www.w3.org/ns/activitystreams"
9
+ defaultContext:
10
+ - "https://www.w3.org/ns/activitystreams"
11
+ - "https://w3id.org/security/data-integrity/v1"
12
+ - toot: "http://joinmastodon.org/ns#"
13
+ sensitive: "as:sensitive"
14
+ Emoji: "toot:Emoji"
15
+ Hashtag: "as:Hashtag"
10
16
 
11
17
  properties:
12
18
  - pluralName: items
@@ -18,3 +24,4 @@ properties:
18
24
  or unordered.
19
25
  range:
20
26
  - "https://www.w3.org/ns/activitystreams#Object"
27
+ - "https://www.w3.org/ns/activitystreams#Link"
@@ -7,7 +7,13 @@ description: |
7
7
  Used to represent ordered subsets of items from an `OrderedCollection`.
8
8
  Refer to the Activity Streams 2.0 Core for a complete description of
9
9
  the `OrderedCollectionPage` object.
10
- defaultContext: "https://www.w3.org/ns/activitystreams"
10
+ defaultContext:
11
+ - "https://www.w3.org/ns/activitystreams"
12
+ - "https://w3id.org/security/data-integrity/v1"
13
+ - toot: "http://joinmastodon.org/ns#"
14
+ sensitive: "as:sensitive"
15
+ Emoji: "toot:Emoji"
16
+ Hashtag: "as:Hashtag"
11
17
 
12
18
  properties:
13
19
  - singularName: startIndex
@@ -15,6 +15,9 @@ defaultContext:
15
15
  featured:
16
16
  "@id": "toot:featured"
17
17
  "@type": "@id"
18
+ featuredTags:
19
+ "@id": "toot:featuredTags"
20
+ "@type": "@id"
18
21
  discoverable: "toot:discoverable"
19
22
  suspended: "toot:suspended"
20
23
  memorial: "toot:memorial"
@@ -157,6 +160,17 @@ properties:
157
160
  range:
158
161
  - "https://www.w3.org/ns/activitystreams#Collection"
159
162
 
163
+ - singularName: featuredTags
164
+ functional: true
165
+ uri: "http://joinmastodon.org/ns#featuredTags"
166
+ description: |
167
+ What is known in Mastodon as "featured hashtags", hashtags that are featured
168
+ at people's profiles, is implemented using an extra property `featuredTags`
169
+ on the actor object that points to a {@link Collection} of {@link Hashtag}
170
+ objects specifically.
171
+ range:
172
+ - "https://www.w3.org/ns/activitystreams#Collection"
173
+
160
174
  - pluralName: streams
161
175
  singularName: stream
162
176
  singularAccessor: false
@@ -15,6 +15,9 @@ defaultContext:
15
15
  featured:
16
16
  "@id": "toot:featured"
17
17
  "@type": "@id"
18
+ featuredTags:
19
+ "@id": "toot:featuredTags"
20
+ "@type": "@id"
18
21
  discoverable: "toot:discoverable"
19
22
  suspended: "toot:suspended"
20
23
  memorial: "toot:memorial"
@@ -157,6 +160,17 @@ properties:
157
160
  range:
158
161
  - "https://www.w3.org/ns/activitystreams#Collection"
159
162
 
163
+ - singularName: featuredTags
164
+ functional: true
165
+ uri: "http://joinmastodon.org/ns#featuredTags"
166
+ description: |
167
+ What is known in Mastodon as "featured hashtags", hashtags that are featured
168
+ at people's profiles, is implemented using an extra property `featuredTags`
169
+ on the actor object that points to a {@link Collection} of {@link Hashtag}
170
+ objects specifically.
171
+ range:
172
+ - "https://www.w3.org/ns/activitystreams#Collection"
173
+
160
174
  - pluralName: streams
161
175
  singularName: stream
162
176
  singularAccessor: false
@@ -15,6 +15,9 @@ defaultContext:
15
15
  featured:
16
16
  "@id": "toot:featured"
17
17
  "@type": "@id"
18
+ featuredTags:
19
+ "@id": "toot:featuredTags"
20
+ "@type": "@id"
18
21
  discoverable: "toot:discoverable"
19
22
  suspended: "toot:suspended"
20
23
  memorial: "toot:memorial"
@@ -157,6 +160,17 @@ properties:
157
160
  range:
158
161
  - "https://www.w3.org/ns/activitystreams#Collection"
159
162
 
163
+ - singularName: featuredTags
164
+ functional: true
165
+ uri: "http://joinmastodon.org/ns#featuredTags"
166
+ description: |
167
+ What is known in Mastodon as "featured hashtags", hashtags that are featured
168
+ at people's profiles, is implemented using an extra property `featuredTags`
169
+ on the actor object that points to a {@link Collection} of {@link Hashtag}
170
+ objects specifically.
171
+ range:
172
+ - "https://www.w3.org/ns/activitystreams#Collection"
173
+
160
174
  - pluralName: streams
161
175
  singularName: stream
162
176
  singularAccessor: false