Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .agents/skills/add-vocab/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,11 @@ Embedded context entries are YAML mappings where:
- String value `"prefix:term"` or `"https://..."` defines a simple term alias
- Object value with `"@id"` and optionally `"@type": "@id"` defines a term
that should be treated as an IRI (linked resource)
- Object value may also carry `"@container": "@set"` or
`"@container": "@list"` to match a vocabulary whose context defines a
container. A context term's `@container` is separate from the
property-level `container: list` option, which controls how the compact
serializer writes list values.

### Ensuring complete compaction coverage

Expand Down
29 changes: 29 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,13 @@ To be released.
for maps that will be rejected. Policy-rejected maps now appear in
`onRequestFinished` verification reports with their policy failure and no
signature checks. [[#1177], [#1264]]
- Changed compound proof verification to accept `"@container": "@set"` term
definitions in actor contexts when deciding whether embedded portable keys
are covered by the actor's proof. A `@set` container only forces expanded
values into arrays, so it does not make key expansion ambiguous; `@list`
and other containers remain rejected. This keeps portable actors that
publish container terms such as Mastodon's `attributionDomains`
verifiable. [[#1234], [#1353]]
- Fixed log entries emitted during an individual outbound activity delivery
or inbound activity processing carrying the enclosing HTTP request's or
queue worker's `traceId`/`spanId` instead of the delivery or processing
Expand All @@ -75,12 +82,14 @@ To be released.
[#1030]: https://github.com/fedify-dev/fedify/issues/1030
[#1177]: https://github.com/fedify-dev/fedify/issues/1177
[#1205]: https://github.com/fedify-dev/fedify/pull/1205
[#1234]: https://github.com/fedify-dev/fedify/issues/1234
[#1264]: https://github.com/fedify-dev/fedify/pull/1264
[#1289]: https://github.com/fedify-dev/fedify/issues/1289
[#1290]: https://github.com/fedify-dev/fedify/issues/1290
[#1299]: https://github.com/fedify-dev/fedify/pull/1299
[#1318]: https://github.com/fedify-dev/fedify/issues/1318
[#1328]: https://github.com/fedify-dev/fedify/pull/1328
[#1353]: https://github.com/fedify-dev/fedify/pull/1353

### @fedify/cli

Expand Down Expand Up @@ -287,6 +296,17 @@ To be released.
entries may not be visited. Accessor and serialization traversal costs are
unchanged. [[#1243], [#1337]]

- Added the `attributionDomains` property to `Application`, `Group`,
`Organization`, `Person`, and `Service`, so applications can publish the
domains an actor claims for Mastodon's `fediverse:creator` link credits
without subclassing the actor types. Each value is a bare host name
without a scheme, port, path, or leading `*.`; Fedify treats the values as
opaque strings and does not normalize them. Actor serialization and
`Update` documents that embed an actor now compact the property as
`attributionDomains` instead of `toot:attributionDomains`, which is the key
Mastodon reads when it refreshes an account, and parsing accepts both
a single string value and an array of strings. [[#1234], [#1353]]

- Added vocabulary support for the [FEP-6757] draft, which marks
ActivityPub content with explicit copyright license URIs.
[[#1212], [#1241]]
Expand Down Expand Up @@ -327,6 +347,11 @@ To be released.

### @fedify/vocab-tools

- Added `@container` support to embedded `defaultContext` term definitions
in the vocabulary schema. Terms such as Mastodon's `attributionDomains`
can now use `"@container": "@set"` or `"@container": "@list"` to match
their published JSON-LD contexts, while existing term definitions keep
validating as before. [[#1234], [#1353]]
- Added non-functional `redundantProperties` support with ordered fallback
to the first non-empty value set, preserving lists and graphs without
merging synonyms. Added `redundantPropertiesWrite: canonical` to write
Expand All @@ -343,6 +368,10 @@ To be released.
`https://w3id.org/identity/v1`. Previously, such a property compacted to
a prefixed name like `dc:license` without the extra context.
[[#1212], [#1241]]
- Made the generated `xsd:string` decoder skip JSON-LD values whose `@value`
is not a string instead of placing them in string accessors. Malformed
remote values no longer leak numbers or booleans into properties such as
`attributionDomains`. [[#1234], [#1353]]

[#1210]: https://github.com/fedify-dev/fedify/issues/1210
[#1215]: https://github.com/fedify-dev/fedify/pull/1215
Expand Down
12 changes: 12 additions & 0 deletions changes.d/fedify/compound-proof-set-contexts.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
links:
'#1234': https://github.com/fedify-dev/fedify/issues/1234
'#1353': https://github.com/fedify-dev/fedify/pull/1353
---
- Changed compound proof verification to accept `"@container": "@set"` term
definitions in actor contexts when deciding whether embedded portable keys
are covered by the actor's proof. A `@set` container only forces expanded
values into arrays, so it does not make key expansion ambiguous; `@list`
and other containers remain rejected. This keeps portable actors that
publish container terms such as Mastodon's `attributionDomains`
verifiable. [[#1234], [#1353]]
10 changes: 10 additions & 0 deletions changes.d/vocab-tools/context-container-terms.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
links:
'#1234': https://github.com/fedify-dev/fedify/issues/1234
'#1353': https://github.com/fedify-dev/fedify/pull/1353
---
- Added `@container` support to embedded `defaultContext` term definitions
in the vocabulary schema. Terms such as Mastodon's `attributionDomains`
can now use `"@container": "@set"` or `"@container": "@list"` to match
their published JSON-LD contexts, while existing term definitions keep
validating as before. [[#1234], [#1353]]
9 changes: 9 additions & 0 deletions changes.d/vocab-tools/string-decoder-skip-unparsable.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
links:
'#1234': https://github.com/fedify-dev/fedify/issues/1234
'#1353': https://github.com/fedify-dev/fedify/pull/1353
---
- Made the generated `xsd:string` decoder skip JSON-LD values whose `@value`
is not a string instead of placing them in string accessors. Malformed
remote values no longer leak numbers or booleans into properties such as
`attributionDomains`. [[#1234], [#1353]]
15 changes: 15 additions & 0 deletions changes.d/vocab/toot-attribution-domains.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
links:
'#1234': https://github.com/fedify-dev/fedify/issues/1234
'#1353': https://github.com/fedify-dev/fedify/pull/1353
---
- Added the `attributionDomains` property to `Application`, `Group`,
`Organization`, `Person`, and `Service`, so applications can publish the
domains an actor claims for Mastodon's `fediverse:creator` link credits
without subclassing the actor types. Each value is a bare host name
without a scheme, port, path, or leading `*.`; Fedify treats the values as
opaque strings and does not normalize them. Actor serialization and
`Update` documents that embed an actor now compact the property as
`attributionDomains` instead of `toot:attributionDomains`, which is the key
Mastodon reads when it refreshes an account, and parsing accepts both
a single string value and an array of strings. [[#1234], [#1353]]
4 changes: 3 additions & 1 deletion claude-plugin/skills/actor/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ Walk through:
object or `FederationBuilder`, including the `{identifier}` path
parameter.
2. Returning a `Person`, `Service`, or other `Actor` vocabulary object
with the required fields (`id`, `inbox`, `publicKey`, etc.).
with the required fields (`id`, `inbox`, `publicKey`, etc.). Set
`attributionDomains` to bare host names when the actor should be
credited on Mastodon link previews; Fedify does not normalize them.
3. Chaining `.setKeyPairsDispatcher()` to supply RSA and Ed25519 keys.
4. Optionally configuring `mapActorAlias()` for handle-based or
fixed-path aliases.
Expand Down
8 changes: 8 additions & 0 deletions packages/fedify/src/federation/handler.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,10 @@ test("handleActor()", async () => {
"@type": "@id",
},
discoverable: "toot:discoverable",
attributionDomains: {
"@id": "toot:attributionDomains",
"@container": "@set",
},
indexable: "toot:indexable",
memorial: "toot:memorial",
suspended: "toot:suspended",
Expand Down Expand Up @@ -326,6 +330,10 @@ test("handleActor()", async () => {
"@type": "@id",
},
discoverable: "toot:discoverable",
attributionDomains: {
"@id": "toot:attributionDomains",
"@container": "@set",
},
indexable: "toot:indexable",
memorial: "toot:memorial",
suspended: "toot:suspended",
Expand Down
34 changes: 34 additions & 0 deletions packages/fedify/src/sig/compound-proof-verification.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -795,6 +795,28 @@ test("verifyCompoundPortableObjectProofs() exempts keys embedded in portable act
assert(result.status === "ok");
assert(result.verified);
assertEquals(result.portableObjects.map((o) => o.path), [""]);
// A parent context may carry a "@set" container term without making the
// keys ambiguous:
const actorWithSetTerm = await compatibleActor();
result = await verifyCompoundPortableObjectProofs(
await signCompatible({
...actorWithSetTerm,
"@context": [
...actorWithSetTerm["@context"] as unknown[],
{
tags: {
"@id": "https://example.com/tags",
"@container": "@set",
},
},
],
}),
limits,
options,
);
assert(result.status === "ok");
assert(result.verified);
assertEquals(result.portableObjects.map((o) => o.path), [""]);
// An ap: actor with gateway keys at compatible identifiers, as Fedify's
// own portable actors have:
result = await verifyCompoundPortableObjectProofs(
Expand Down Expand Up @@ -863,6 +885,18 @@ test("verifyCompoundPortableObjectProofs() exempts only keys of the parent itsel
{ kind: "@type" },
],
},
"a parent context with a list container": {
...actor,
"@context": [
...actor["@context"] as unknown[],
{
tags: {
"@id": "https://example.com/tags",
"@container": "@list",
},
},
],
},
"a key with a scoped context": {
...actor,
publicKey: {
Expand Down
10 changes: 9 additions & 1 deletion packages/fedify/src/sig/compound-proof.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1319,6 +1319,8 @@ function isKeyIdOf(id: string, portableId: string): boolean {
* Checks whether a `@context` value defines no keyword aliases and no scoped
* contexts: only references to contexts and term definitions that map terms
* to IRIs, optionally with an `@id` or `@vocab` type coercion or a datatype.
* A `@set` container is accepted because it only forces expanded values into
* arrays, which expansion does anyway; `@list` and other containers are not.
*/
function isSimpleContext(context: CompoundProofJsonValue | undefined): boolean {
if (typeof context === "string") return true;
Expand All @@ -1330,9 +1332,15 @@ function isSimpleContext(context: CompoundProofJsonValue | undefined): boolean {
if (term.startsWith("@")) return false;
if (typeof definition === "string") return !definition.startsWith("@");
if (!isCompoundProofJsonObject(definition)) return false;
const { "@id": id, "@type": type, ...rest } = definition;
const {
"@id": id,
"@type": type,
"@container": container,
...rest
} = definition;
return Object.keys(rest).length < 1 &&
typeof id === "string" && !id.startsWith("@") &&
(container === undefined || container === "@set") &&
(type === undefined || type === "@id" || type === "@vocab" ||
typeof type === "string" && !type.startsWith("@"));
});
Expand Down
Loading
Loading