Skip to content

Commit e42dfbd

Browse files
committed
Add FEP-0837 Agreement and Commitment vocabulary types fedify-dev#775
Assisted-by: Claude Code:claude-opus-4-8
1 parent 441e19b commit e42dfbd

5 files changed

Lines changed: 626 additions & 1 deletion

File tree

CHANGES.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,19 @@ To be released.
409409
identifiers (`_:b0`) against `options.baseUrl`; blank nodes are left
410410
as `null` in the resulting instance's `id` field. [[#792]]
411411

412+
- Added the second-stage vocabulary types for [FEP-0837], economic
413+
resource coordination in federated networks.
414+
[[#775] by Samuel Brinkmann]
415+
416+
- Added `Agreement` class, representing the agreement reached between
417+
parties responding to a `Proposal`, wrapped in an `Offer` and
418+
finalized as the `result` of an `Accept`.
419+
- Added `Commitment` class, representing a promised economic
420+
transaction that references an `Intent` via `satisfies` and carries
421+
the committed quantity via `resourceQuantity`.
422+
423+
[FEP-0837]: https://w3id.org/fep/0837
424+
[#775]: https://github.com/fedify-dev/fedify/issues/775
412425
[#790]: https://github.com/fedify-dev/fedify/issues/790
413426

414427
### @fedify/vocab-tools
@@ -704,7 +717,6 @@ Released on April 28, 2026.
704717
measure, with `unit` and `numericalValue` properties.
705718
706719
[FEP-044f]: https://w3id.org/fep/044f
707-
[FEP-0837]: https://w3id.org/fep/0837
708720
[#452]: https://github.com/fedify-dev/fedify/issues/452
709721
[#578]: https://github.com/fedify-dev/fedify/issues/578
710722
[#645]: https://github.com/fedify-dev/fedify/issues/645

packages/vocab/src/__snapshots__/vocab.test.ts.snap

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1794,6 +1794,165 @@ snapshot[`Deno.inspect(Multikey) [auto] 3`] = `
17941794
}'
17951795
`;
17961796

1797+
snapshot[`Deno.inspect(Agreement) [auto] 1`] = `
1798+
'Agreement {
1799+
id: URL "https://example.com/",
1800+
attachments: [ Object {}, Link {}, PropertyValue {} ],
1801+
attributions: [ Application {}, Group {}, Organization {}, Person {}, Service {} ],
1802+
audience: Object {},
1803+
contents: [ "hello", <en> "hello" ],
1804+
contexts: [ Object {}, Link {} ],
1805+
names: [ "hello", <en> "hello" ],
1806+
endTime: 2024-03-03T08:30:06.796196096Z,
1807+
generators: [ Object {}, Link {} ],
1808+
icon: Image {},
1809+
image: Image {},
1810+
replyTargets: [ Object {}, Link {} ],
1811+
locations: [ Object {}, Link {} ],
1812+
previews: [ Link {}, Object {} ],
1813+
published: 2024-03-03T08:30:06.796196096Z,
1814+
replies: Collection {},
1815+
shares: Collection {},
1816+
likes: Collection {},
1817+
emojiReactions: Collection {},
1818+
startTime: 2024-03-03T08:30:06.796196096Z,
1819+
summaries: [ "hello", <en> "hello" ],
1820+
tags: [ Object {}, Link {} ],
1821+
updated: 2024-03-03T08:30:06.796196096Z,
1822+
urls: [ URL "https://example.com/", Link {} ],
1823+
to: Object {},
1824+
bto: Object {},
1825+
cc: Object {},
1826+
bcc: Object {},
1827+
mediaType: "hello",
1828+
duration: PT1H,
1829+
sensitive: true,
1830+
source: Source {},
1831+
proof: DataIntegrityProof {},
1832+
interactionPolicy: InteractionPolicy {},
1833+
approvedBy: URL "https://example.com/",
1834+
likeAuthorization: LikeAuthorization {},
1835+
replyAuthorization: ReplyAuthorization {},
1836+
announceAuthorization: AnnounceAuthorization {},
1837+
stipulates: Commitment {},
1838+
stipulatesReciprocal: Commitment {}
1839+
}'
1840+
`;
1841+
1842+
snapshot[`Deno.inspect(Agreement) [auto] 2`] = `
1843+
'Agreement {
1844+
id: URL "https://example.com/",
1845+
attachments: [ URL "https://example.com/" ],
1846+
attribution: URL "https://example.com/",
1847+
audience: URL "https://example.com/",
1848+
contents: [ "hello", <en> "hello" ],
1849+
contexts: [ URL "https://example.com/" ],
1850+
names: [ "hello", <en> "hello" ],
1851+
endTime: 2024-03-03T08:30:06.796196096Z,
1852+
generators: [ URL "https://example.com/" ],
1853+
icon: URL "https://example.com/",
1854+
image: URL "https://example.com/",
1855+
replyTarget: URL "https://example.com/",
1856+
location: URL "https://example.com/",
1857+
preview: URL "https://example.com/",
1858+
published: 2024-03-03T08:30:06.796196096Z,
1859+
replies: URL "https://example.com/",
1860+
shares: URL "https://example.com/",
1861+
likes: URL "https://example.com/",
1862+
emojiReactions: URL "https://example.com/",
1863+
startTime: 2024-03-03T08:30:06.796196096Z,
1864+
summaries: [ "hello", <en> "hello" ],
1865+
tags: [ URL "https://example.com/" ],
1866+
updated: 2024-03-03T08:30:06.796196096Z,
1867+
urls: [ URL "https://example.com/", Link {} ],
1868+
to: URL "https://example.com/",
1869+
bto: URL "https://example.com/",
1870+
cc: URL "https://example.com/",
1871+
bcc: URL "https://example.com/",
1872+
mediaType: "hello",
1873+
duration: PT1H,
1874+
sensitive: true,
1875+
source: Source {},
1876+
proof: URL "https://example.com/",
1877+
interactionPolicy: InteractionPolicy {},
1878+
approvedBy: URL "https://example.com/",
1879+
likeAuthorization: URL "https://example.com/",
1880+
replyAuthorization: URL "https://example.com/",
1881+
announceAuthorization: URL "https://example.com/",
1882+
stipulates: Commitment {},
1883+
stipulatesReciprocal: Commitment {}
1884+
}'
1885+
`;
1886+
1887+
snapshot[`Deno.inspect(Agreement) [auto] 3`] = `
1888+
'Agreement {
1889+
id: URL "https://example.com/",
1890+
attachments: [ Object {}, Object {} ],
1891+
attributions: [ Application {}, Application {} ],
1892+
audiences: [ Object {}, Object {} ],
1893+
contents: [ "hello", "hello" ],
1894+
contexts: [ Object {}, Object {} ],
1895+
names: [ "hello", "hello" ],
1896+
endTime: 2024-03-03T08:30:06.796196096Z,
1897+
generators: [ Object {}, Object {} ],
1898+
icons: [ Image {}, Image {} ],
1899+
images: [ Image {}, Image {} ],
1900+
replyTargets: [ Object {}, Object {} ],
1901+
locations: [ Object {}, Object {} ],
1902+
previews: [ Link {}, Link {} ],
1903+
published: 2024-03-03T08:30:06.796196096Z,
1904+
replies: Collection {},
1905+
shares: Collection {},
1906+
likes: Collection {},
1907+
emojiReactions: Collection {},
1908+
startTime: 2024-03-03T08:30:06.796196096Z,
1909+
summaries: [ "hello", "hello" ],
1910+
tags: [ Object {}, Object {} ],
1911+
updated: 2024-03-03T08:30:06.796196096Z,
1912+
urls: [ URL "https://example.com/", URL "https://example.com/" ],
1913+
tos: [ Object {}, Object {} ],
1914+
btos: [ Object {}, Object {} ],
1915+
ccs: [ Object {}, Object {} ],
1916+
bccs: [ Object {}, Object {} ],
1917+
mediaType: "hello",
1918+
duration: PT1H,
1919+
sensitive: true,
1920+
source: Source {},
1921+
proofs: [ DataIntegrityProof {}, DataIntegrityProof {} ],
1922+
interactionPolicy: InteractionPolicy {},
1923+
approvedBy: URL "https://example.com/",
1924+
likeAuthorization: LikeAuthorization {},
1925+
replyAuthorization: ReplyAuthorization {},
1926+
announceAuthorization: AnnounceAuthorization {},
1927+
stipulates: Commitment {},
1928+
stipulatesReciprocal: Commitment {}
1929+
}'
1930+
`;
1931+
1932+
snapshot[`Deno.inspect(Commitment) [auto] 1`] = `
1933+
'Commitment {
1934+
id: URL "https://example.com/",
1935+
satisfies: URL "https://example.com/",
1936+
resourceQuantity: Measure {}
1937+
}'
1938+
`;
1939+
1940+
snapshot[`Deno.inspect(Commitment) [auto] 2`] = `
1941+
'Commitment {
1942+
id: URL "https://example.com/",
1943+
satisfies: URL "https://example.com/",
1944+
resourceQuantity: Measure {}
1945+
}'
1946+
`;
1947+
1948+
snapshot[`Deno.inspect(Commitment) [auto] 3`] = `
1949+
'Commitment {
1950+
id: URL "https://example.com/",
1951+
satisfies: URL "https://example.com/",
1952+
resourceQuantity: Measure {}
1953+
}'
1954+
`;
1955+
17971956
snapshot[`Deno.inspect(Intent) [auto] 1`] = `
17981957
'Intent {
17991958
id: URL "https://example.com/",

packages/vocab/src/agreement.yaml

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
$schema: ../../vocab-tools/schema.yaml
2+
name: Agreement
3+
compactName: Agreement
4+
uri: "https://w3id.org/valueflows/ont/vf#Agreement"
5+
extends: "https://www.w3.org/ns/activitystreams#Object"
6+
entity: true
7+
description: |
8+
The agreement reached between parties responding to a {@link Proposal}.
9+
10+
An interested party sends an `Agreement` wrapped in an {@link Offer}
11+
activity. The proposing party then either finalizes the agreement by
12+
sending an {@link Accept} activity with the finalized `Agreement` as
13+
its `result`, or sends a {@link Reject} activity.
14+
15+
Note: This type extends ActivityStreams `Object` for practical
16+
interoperability within ActivityPub federation, even though FEP-0837
17+
defines `Agreement` as a pure ValueFlows type. Extending `Object`
18+
provides useful inherited properties such as `id`, `attributedTo`,
19+
`url`, `to`, and `published` without needing to redefine them.
20+
# NOTE: The context includes mappings for Commitment and Measure properties
21+
# (satisfies, resourceQuantity, hasUnit, hasNumericalValue) because the
22+
# code generator does not automatically merge contexts from referenced
23+
# types. Agreement must declare all mappings needed for correct JSON-LD
24+
# serialization of its embedded Commitment and Measure objects.
25+
defaultContext:
26+
- "https://www.w3.org/ns/activitystreams"
27+
- "https://w3id.org/security/data-integrity/v1"
28+
- "https://gotosocial.org/ns"
29+
- vf: "https://w3id.org/valueflows/ont/vf#"
30+
om2: "http://www.ontology-of-units-of-measure.org/resource/om-2/"
31+
fedibird: "http://fedibird.com/ns#"
32+
sensitive: "as:sensitive"
33+
emojiReactions:
34+
"@id": "fedibird:emojiReactions"
35+
"@type": "@id"
36+
Agreement: "vf:Agreement"
37+
Commitment: "vf:Commitment"
38+
stipulates: "vf:stipulates"
39+
stipulatesReciprocal: "vf:stipulatesReciprocal"
40+
satisfies:
41+
"@id": "vf:satisfies"
42+
"@type": "@id"
43+
resourceQuantity: "vf:resourceQuantity"
44+
hasUnit: "om2:hasUnit"
45+
hasNumericalValue: "om2:hasNumericalValue"
46+
47+
properties:
48+
- singularName: stipulates
49+
functional: true
50+
compactName: stipulates
51+
uri: "https://w3id.org/valueflows/ont/vf#stipulates"
52+
description: |
53+
The primary {@link Commitment} associated with the agreement. This
54+
commitment satisfies the primary {@link Intent} of the corresponding
55+
{@link Proposal}.
56+
range:
57+
- "https://w3id.org/valueflows/ont/vf#Commitment"
58+
59+
- singularName: stipulatesReciprocal
60+
functional: true
61+
compactName: stipulatesReciprocal
62+
uri: "https://w3id.org/valueflows/ont/vf#stipulatesReciprocal"
63+
description: |
64+
The reciprocal {@link Commitment} associated with the agreement.
65+
Required if the corresponding {@link Proposal} has a reciprocal
66+
{@link Intent}.
67+
range:
68+
- "https://w3id.org/valueflows/ont/vf#Commitment"

packages/vocab/src/commitment.yaml

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
$schema: ../../vocab-tools/schema.yaml
2+
name: Commitment
3+
compactName: Commitment
4+
uri: "https://w3id.org/valueflows/ont/vf#Commitment"
5+
entity: false
6+
description: |
7+
A promised economic transaction, referenced by an {@link Agreement}.
8+
9+
A commitment satisfies an {@link Intent} of a {@link Proposal} and
10+
specifies the actual amount of the economic resource being committed.
11+
defaultContext:
12+
- "https://www.w3.org/ns/activitystreams"
13+
- vf: "https://w3id.org/valueflows/ont/vf#"
14+
om2: "http://www.ontology-of-units-of-measure.org/resource/om-2/"
15+
Commitment: "vf:Commitment"
16+
satisfies:
17+
"@id": "vf:satisfies"
18+
"@type": "@id"
19+
resourceQuantity: "vf:resourceQuantity"
20+
hasUnit: "om2:hasUnit"
21+
hasNumericalValue: "om2:hasNumericalValue"
22+
23+
properties:
24+
- singularName: satisfies
25+
functional: true
26+
compactName: satisfies
27+
uri: "https://w3id.org/valueflows/ont/vf#satisfies"
28+
description: |
29+
The {@link Intent} of a {@link Proposal} that this commitment
30+
satisfies. The value is typically a fragment identifier such as
31+
`#primary` or `#reciprocal`.
32+
range:
33+
- "http://www.w3.org/2001/XMLSchema#anyURI"
34+
35+
- singularName: resourceQuantity
36+
functional: true
37+
compactName: resourceQuantity
38+
uri: "https://w3id.org/valueflows/ont/vf#resourceQuantity"
39+
untyped: true
40+
description: |
41+
The amount and unit of the economic resource being committed. The
42+
unit must match the unit specified in the corresponding {@link Intent}
43+
of the proposal.
44+
range:
45+
- "http://www.ontology-of-units-of-measure.org/resource/om-2/Measure"

0 commit comments

Comments
 (0)