@hypercerts-org/lexicon 0.10.0 → 0.11.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.
- package/CHANGELOG.md +205 -0
- package/README.md +371 -388
- package/SCHEMAS.md +533 -75
- package/dist/exports.d.ts +900 -10
- package/dist/exports.d.ts.map +1 -1
- package/dist/generated/exports.d.ts +900 -10
- package/dist/generated/exports.d.ts.map +1 -1
- package/dist/generated/lexicons.d.ts +2683 -1093
- package/dist/generated/lexicons.d.ts.map +1 -1
- package/dist/generated/types/app/bsky/richtext/facet.d.ts +44 -7
- package/dist/generated/types/app/bsky/richtext/facet.d.ts.map +1 -1
- package/dist/generated/types/app/certified/badge/award.d.ts +2 -3
- package/dist/generated/types/app/certified/badge/award.d.ts.map +1 -1
- package/dist/generated/types/app/certified/badge/definition.d.ts +3 -3
- package/dist/generated/types/app/certified/badge/definition.d.ts.map +1 -1
- package/dist/generated/types/app/certified/badge/response.d.ts +2 -2
- package/dist/generated/types/app/certified/badge/response.d.ts.map +1 -1
- package/dist/generated/types/app/certified/link/evm.d.ts +45 -0
- package/dist/generated/types/app/certified/link/evm.d.ts.map +1 -0
- package/dist/generated/types/org/hypercerts/claim/activity.d.ts +6 -3
- package/dist/generated/types/org/hypercerts/claim/activity.d.ts.map +1 -1
- package/dist/generated/types/org/hypercerts/collection.d.ts +11 -5
- package/dist/generated/types/org/hypercerts/collection.d.ts.map +1 -1
- package/dist/generated/types/org/hypercerts/context/attachment.d.ts +5 -3
- package/dist/generated/types/org/hypercerts/context/attachment.d.ts.map +1 -1
- package/dist/generated/types/org/hypercerts/context/evaluation.d.ts +6 -6
- package/dist/generated/types/org/hypercerts/context/evaluation.d.ts.map +1 -1
- package/dist/generated/types/org/hypercerts/defs.d.ts +11 -0
- package/dist/generated/types/org/hypercerts/defs.d.ts.map +1 -1
- package/dist/generated/types/org/hypercerts/funding/receipt.d.ts +17 -5
- package/dist/generated/types/org/hypercerts/funding/receipt.d.ts.map +1 -1
- package/dist/generated/types/pub/leaflet/blocks/blockquote.d.ts +13 -0
- package/dist/generated/types/pub/leaflet/blocks/blockquote.d.ts.map +1 -0
- package/dist/generated/types/pub/leaflet/blocks/bskyPost.d.ts +13 -0
- package/dist/generated/types/pub/leaflet/blocks/bskyPost.d.ts.map +1 -0
- package/dist/generated/types/pub/leaflet/blocks/button.d.ts +12 -0
- package/dist/generated/types/pub/leaflet/blocks/button.d.ts.map +1 -0
- package/dist/generated/types/pub/leaflet/blocks/code.d.ts +13 -0
- package/dist/generated/types/pub/leaflet/blocks/code.d.ts.map +1 -0
- package/dist/generated/types/pub/leaflet/blocks/header.d.ts +14 -0
- package/dist/generated/types/pub/leaflet/blocks/header.d.ts.map +1 -0
- package/dist/generated/types/pub/leaflet/blocks/horizontalRule.d.ts +10 -0
- package/dist/generated/types/pub/leaflet/blocks/horizontalRule.d.ts.map +1 -0
- package/dist/generated/types/pub/leaflet/blocks/iframe.d.ts +12 -0
- package/dist/generated/types/pub/leaflet/blocks/iframe.d.ts.map +1 -0
- package/dist/generated/types/pub/leaflet/blocks/image.d.ts +21 -0
- package/dist/generated/types/pub/leaflet/blocks/image.d.ts.map +1 -0
- package/dist/generated/types/pub/leaflet/blocks/math.d.ts +11 -0
- package/dist/generated/types/pub/leaflet/blocks/math.d.ts.map +1 -0
- package/dist/generated/types/pub/leaflet/blocks/orderedList.d.ts +31 -0
- package/dist/generated/types/pub/leaflet/blocks/orderedList.d.ts.map +1 -0
- package/dist/generated/types/pub/leaflet/blocks/page.d.ts +11 -0
- package/dist/generated/types/pub/leaflet/blocks/page.d.ts.map +1 -0
- package/dist/generated/types/pub/leaflet/blocks/poll.d.ts +12 -0
- package/dist/generated/types/pub/leaflet/blocks/poll.d.ts.map +1 -0
- package/dist/generated/types/pub/leaflet/blocks/text.d.ts +14 -0
- package/dist/generated/types/pub/leaflet/blocks/text.d.ts.map +1 -0
- package/dist/generated/types/pub/leaflet/blocks/unorderedList.d.ts +29 -0
- package/dist/generated/types/pub/leaflet/blocks/unorderedList.d.ts.map +1 -0
- package/dist/generated/types/pub/leaflet/blocks/website.d.ts +14 -0
- package/dist/generated/types/pub/leaflet/blocks/website.d.ts.map +1 -0
- package/dist/generated/types/pub/leaflet/pages/linearDocument.d.ts +54 -1
- package/dist/generated/types/pub/leaflet/pages/linearDocument.d.ts.map +1 -1
- package/dist/generated/types/pub/leaflet/richtext/facet.d.ts +97 -0
- package/dist/generated/types/pub/leaflet/richtext/facet.d.ts.map +1 -0
- package/dist/index.cjs +4486 -1807
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +4407 -1804
- package/dist/index.mjs.map +1 -1
- package/dist/lexicons.cjs +927 -35
- package/dist/lexicons.cjs.map +1 -1
- package/dist/lexicons.d.ts +2683 -1093
- package/dist/lexicons.d.ts.map +1 -1
- package/dist/lexicons.mjs +927 -35
- package/dist/lexicons.mjs.map +1 -1
- package/dist/tests/validate-external-lexicons.test.d.ts +2 -0
- package/dist/tests/validate-external-lexicons.test.d.ts.map +1 -0
- package/dist/tests/validate-funding-receipt.test.d.ts +2 -0
- package/dist/tests/validate-funding-receipt.test.d.ts.map +1 -0
- package/dist/tests/validate-link-evm.test.d.ts +2 -0
- package/dist/tests/validate-link-evm.test.d.ts.map +1 -0
- package/dist/tests/validate-rights.test.d.ts +2 -0
- package/dist/tests/validate-rights.test.d.ts.map +1 -0
- package/dist/types/app/bsky/richtext/facet.d.ts +44 -7
- package/dist/types/app/bsky/richtext/facet.d.ts.map +1 -1
- package/dist/types/app/certified/badge/award.d.ts +2 -3
- package/dist/types/app/certified/badge/award.d.ts.map +1 -1
- package/dist/types/app/certified/badge/definition.d.ts +3 -3
- package/dist/types/app/certified/badge/definition.d.ts.map +1 -1
- package/dist/types/app/certified/badge/response.d.ts +2 -2
- package/dist/types/app/certified/badge/response.d.ts.map +1 -1
- package/dist/types/app/certified/link/evm.d.ts +45 -0
- package/dist/types/app/certified/link/evm.d.ts.map +1 -0
- package/dist/types/org/hypercerts/claim/activity.d.ts +6 -3
- package/dist/types/org/hypercerts/claim/activity.d.ts.map +1 -1
- package/dist/types/org/hypercerts/collection.d.ts +11 -5
- package/dist/types/org/hypercerts/collection.d.ts.map +1 -1
- package/dist/types/org/hypercerts/context/attachment.d.ts +5 -3
- package/dist/types/org/hypercerts/context/attachment.d.ts.map +1 -1
- package/dist/types/org/hypercerts/context/evaluation.d.ts +6 -6
- package/dist/types/org/hypercerts/context/evaluation.d.ts.map +1 -1
- package/dist/types/org/hypercerts/defs.d.ts +11 -0
- package/dist/types/org/hypercerts/defs.d.ts.map +1 -1
- package/dist/types/org/hypercerts/funding/receipt.d.ts +17 -5
- package/dist/types/org/hypercerts/funding/receipt.d.ts.map +1 -1
- package/dist/types/pub/leaflet/blocks/blockquote.d.ts +13 -0
- package/dist/types/pub/leaflet/blocks/blockquote.d.ts.map +1 -0
- package/dist/types/pub/leaflet/blocks/bskyPost.d.ts +13 -0
- package/dist/types/pub/leaflet/blocks/bskyPost.d.ts.map +1 -0
- package/dist/types/pub/leaflet/blocks/button.d.ts +12 -0
- package/dist/types/pub/leaflet/blocks/button.d.ts.map +1 -0
- package/dist/types/pub/leaflet/blocks/code.d.ts +13 -0
- package/dist/types/pub/leaflet/blocks/code.d.ts.map +1 -0
- package/dist/types/pub/leaflet/blocks/header.d.ts +14 -0
- package/dist/types/pub/leaflet/blocks/header.d.ts.map +1 -0
- package/dist/types/pub/leaflet/blocks/horizontalRule.d.ts +10 -0
- package/dist/types/pub/leaflet/blocks/horizontalRule.d.ts.map +1 -0
- package/dist/types/pub/leaflet/blocks/iframe.d.ts +12 -0
- package/dist/types/pub/leaflet/blocks/iframe.d.ts.map +1 -0
- package/dist/types/pub/leaflet/blocks/image.d.ts +21 -0
- package/dist/types/pub/leaflet/blocks/image.d.ts.map +1 -0
- package/dist/types/pub/leaflet/blocks/math.d.ts +11 -0
- package/dist/types/pub/leaflet/blocks/math.d.ts.map +1 -0
- package/dist/types/pub/leaflet/blocks/orderedList.d.ts +31 -0
- package/dist/types/pub/leaflet/blocks/orderedList.d.ts.map +1 -0
- package/dist/types/pub/leaflet/blocks/page.d.ts +11 -0
- package/dist/types/pub/leaflet/blocks/page.d.ts.map +1 -0
- package/dist/types/pub/leaflet/blocks/poll.d.ts +12 -0
- package/dist/types/pub/leaflet/blocks/poll.d.ts.map +1 -0
- package/dist/types/pub/leaflet/blocks/text.d.ts +14 -0
- package/dist/types/pub/leaflet/blocks/text.d.ts.map +1 -0
- package/dist/types/pub/leaflet/blocks/unorderedList.d.ts +29 -0
- package/dist/types/pub/leaflet/blocks/unorderedList.d.ts.map +1 -0
- package/dist/types/pub/leaflet/blocks/website.d.ts +14 -0
- package/dist/types/pub/leaflet/blocks/website.d.ts.map +1 -0
- package/dist/types/pub/leaflet/pages/linearDocument.d.ts +54 -1
- package/dist/types/pub/leaflet/pages/linearDocument.d.ts.map +1 -1
- package/dist/types/pub/leaflet/richtext/facet.d.ts +97 -0
- package/dist/types/pub/leaflet/richtext/facet.d.ts.map +1 -0
- package/lexicons/app/bsky/richtext/facet.json +51 -0
- package/lexicons/app/certified/badge/award.json +2 -2
- package/lexicons/app/certified/badge/definition.json +10 -2
- package/lexicons/app/certified/badge/response.json +2 -2
- package/lexicons/app/certified/link/evm.json +88 -0
- package/lexicons/org/hypercerts/claim/activity.json +8 -4
- package/lexicons/org/hypercerts/collection.json +19 -5
- package/lexicons/org/hypercerts/context/attachment.json +16 -5
- package/lexicons/org/hypercerts/context/evaluation.json +9 -6
- package/lexicons/org/hypercerts/defs.json +21 -0
- package/lexicons/org/hypercerts/funding/receipt.json +30 -10
- package/lexicons/pub/leaflet/blocks/blockquote.json +22 -0
- package/lexicons/pub/leaflet/blocks/bskyPost.json +19 -0
- package/lexicons/pub/leaflet/blocks/button.json +19 -0
- package/lexicons/pub/leaflet/blocks/code.json +21 -0
- package/lexicons/pub/leaflet/blocks/header.json +27 -0
- package/lexicons/pub/leaflet/blocks/horizontalRule.json +11 -0
- package/lexicons/pub/leaflet/blocks/iframe.json +21 -0
- package/lexicons/pub/leaflet/blocks/image.json +37 -0
- package/lexicons/pub/leaflet/blocks/math.json +15 -0
- package/lexicons/pub/leaflet/blocks/orderedList.json +54 -0
- package/lexicons/pub/leaflet/blocks/page.json +15 -0
- package/lexicons/pub/leaflet/blocks/poll.json +16 -0
- package/lexicons/pub/leaflet/blocks/text.json +26 -0
- package/lexicons/pub/leaflet/blocks/unorderedList.json +50 -0
- package/lexicons/pub/leaflet/blocks/website.json +27 -0
- package/lexicons/pub/leaflet/pages/linearDocument.json +98 -0
- package/lexicons/pub/leaflet/richtext/facet.json +149 -0
- package/package.json +3 -4
package/README.md
CHANGED
|
@@ -1,39 +1,180 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
Hypercerts protocol
|
|
5
|
-
|
|
1
|
+
# @hypercerts-org/lexicon
|
|
2
|
+
|
|
3
|
+
ATProto lexicon definitions and TypeScript types for the
|
|
4
|
+
[Hypercerts](https://hypercerts.org) protocol — a system for tracking,
|
|
5
|
+
evaluating, and funding impact work on the
|
|
6
|
+
[AT Protocol](https://atproto.com) network.
|
|
7
|
+
|
|
8
|
+
## Lexicon Map
|
|
9
|
+
|
|
10
|
+
```text
|
|
11
|
+
CLAIMS ─ the core impact record and its parts
|
|
12
|
+
──────────────────────────────────────────────────────────────────────
|
|
13
|
+
activity ──────────┬──► collection ◄──┐ (recursive nesting)
|
|
14
|
+
(the hypercert) │ │ │
|
|
15
|
+
│ ▼ │
|
|
16
|
+
├──► contribution (role, timeframe)
|
|
17
|
+
├──► contributorInformation (identity, avatar)
|
|
18
|
+
├──► rights (licensing terms)
|
|
19
|
+
└──► workScope
|
|
20
|
+
├── cel (CEL expression)
|
|
21
|
+
└── tag (reusable scope atom)
|
|
22
|
+
|
|
23
|
+
CONTEXT ─ evidence, data, and social verification
|
|
24
|
+
──────────────────────────────────────────────────────────────────────
|
|
25
|
+
attachment ─────────────► activity / evaluation / ...
|
|
26
|
+
measurement ────────────► activity / ...
|
|
27
|
+
evaluation ─────────────► activity / attachment
|
|
28
|
+
└──────► measurement
|
|
29
|
+
acknowledgement ────────► activity / collection (bidirectional link)
|
|
30
|
+
|
|
31
|
+
FUNDING ─ payment records
|
|
32
|
+
──────────────────────────────────────────────────────────────────────
|
|
33
|
+
receipt ────────────────► activity (from funder → to recipient)
|
|
34
|
+
|
|
35
|
+
HYPERBOARDS ─ visual display layer (hyperboards.org)
|
|
36
|
+
──────────────────────────────────────────────────────────────────────
|
|
37
|
+
board ──────────────────► activity / collection
|
|
38
|
+
└── contributorConfig ► contributorInformation
|
|
39
|
+
displayProfile (per-user visual defaults)
|
|
40
|
+
|
|
41
|
+
CERTIFIED ─ shared lexicons (certified.app)
|
|
42
|
+
──────────────────────────────────────────────────────────────────────
|
|
43
|
+
location (geo coordinates, GeoJSON, H3, …)
|
|
44
|
+
actor/profile (user profile)
|
|
45
|
+
actor/organization (org metadata)
|
|
46
|
+
badge/definition ──► badge/award ──► badge/response
|
|
47
|
+
```
|
|
6
48
|
|
|
7
|
-
|
|
49
|
+
Every arrow (`►`) is a `strongRef` or union reference stored on the
|
|
50
|
+
AT Protocol network. Full field-level documentation is in
|
|
51
|
+
[SCHEMAS.md](SCHEMAS.md).
|
|
8
52
|
|
|
9
|
-
|
|
53
|
+
## Consuming These Lexicons
|
|
10
54
|
|
|
11
|
-
|
|
12
|
-
|
|
55
|
+
If you are building a downstream application on top of these lexicons,
|
|
56
|
+
we strongly recommend **NOT** reading from `main` or other development
|
|
57
|
+
branches of the repository, but instead via the following published
|
|
58
|
+
releases:
|
|
13
59
|
|
|
14
|
-
-
|
|
15
|
-
|
|
60
|
+
- **For TypeScript / JavaScript code** — use [the npm package
|
|
61
|
+
`@hypercerts-org/lexicon`](https://www.npmjs.com/package/@hypercerts-org/lexicon),
|
|
62
|
+
which includes generated types, validation helpers, and schema
|
|
63
|
+
constants.
|
|
64
|
+
- **For other languages** — use the [tagged
|
|
65
|
+
releases](https://github.com/hypercerts-org/hypercerts-lexicon/releases)
|
|
66
|
+
published in this GitHub repository.
|
|
16
67
|
|
|
17
|
-
|
|
18
|
-
|
|
68
|
+
Both npm releases and git tags follow [SemVer](https://semver.org/).
|
|
69
|
+
For npm, you can depend on a version range to receive compatible
|
|
70
|
+
updates automatically. For GitHub releases/tags, pin a specific tag
|
|
71
|
+
or upgrade manually to a newer compatible SemVer release.
|
|
19
72
|
|
|
20
|
-
|
|
73
|
+
The raw lexicons published on ATProto can also be used, but they are
|
|
74
|
+
(unavoidably) missing useful context such as full documentation
|
|
75
|
+
(including changelogs), TypeScript type definitions, SemVer
|
|
76
|
+
guarantees, git history, and other tooling provided by the packaged
|
|
77
|
+
releases.
|
|
21
78
|
|
|
22
|
-
|
|
23
|
-
following icons:
|
|
79
|
+
### AI Agent Skill
|
|
24
80
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
81
|
+
If you use AI coding assistants (e.g. Claude Code, OpenCode), you can
|
|
82
|
+
install a skill that teaches your agent how to build with these
|
|
83
|
+
lexicons:
|
|
28
84
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
<summary>View ERD with field details</summary>
|
|
85
|
+
```bash
|
|
86
|
+
npx skills add hypercerts-org/hypercerts-lexicon
|
|
87
|
+
```
|
|
33
88
|
|
|
34
|
-
|
|
89
|
+
This installs the
|
|
90
|
+
[`building-with-hypercerts-lexicons`](.agents/skills/building-with-hypercerts-lexicons/SKILL.md)
|
|
91
|
+
skill, which provides your agent with guidance on package entry points,
|
|
92
|
+
TypeScript types, validation, all lexicon schemas, code examples, and
|
|
93
|
+
AT Protocol conventions.
|
|
94
|
+
|
|
95
|
+
## Maintenance and publishing releases
|
|
96
|
+
|
|
97
|
+
Clearly stability and predictability for users and developers are
|
|
98
|
+
essential.
|
|
99
|
+
|
|
100
|
+
Unfortunately AT Protocol doesn't support any kind of native
|
|
101
|
+
versioning or migrations which could support lexicon schema changes.
|
|
102
|
+
Instead, the AT Protocol community recommends minimising changes to
|
|
103
|
+
lexicons in general, and to avoid breaking changes wherever possible:
|
|
104
|
+
|
|
105
|
+
- https://atproto.com/guides/lexicon-style-guide
|
|
106
|
+
- https://www.pfrazee.com/blog/lexicon-guidance
|
|
107
|
+
|
|
108
|
+
This project intends to follow that guidance as much as possible
|
|
109
|
+
whilst retaining a pragmatic approach. In practice that means:
|
|
110
|
+
|
|
111
|
+
- Changes to other tooling within this repository which _do not touch
|
|
112
|
+
lexicons_ may be made at any time as long as they follow
|
|
113
|
+
[SemVer](https://semver.org/) to avoid negative impact on
|
|
114
|
+
developers.
|
|
115
|
+
|
|
116
|
+
- Non-breaking changes to lexicons, such as adding an optional
|
|
117
|
+
property or updating a `description`, may be made sparingly. While
|
|
118
|
+
these changes are backwards-compatible at the protocol level, they
|
|
119
|
+
may still require consuming applications and indexers to update
|
|
120
|
+
their schemas for consistent UX.
|
|
121
|
+
|
|
122
|
+
- Breaking changes to lexicons will only be made in exceptional
|
|
123
|
+
circumstances. Specifically, a breaking change will only proceed
|
|
124
|
+
**if and only if**:
|
|
125
|
+
- the broader community — not just the Hypercerts core team —
|
|
126
|
+
agrees that the benefits clearly outweigh the cost of the
|
|
127
|
+
breakage, **and**
|
|
128
|
+
- full consideration is given to all affected parties across the
|
|
129
|
+
community and wider ecosystem, not only those involved in the
|
|
130
|
+
decision, **and**
|
|
131
|
+
- no viable alternative exists, such as releasing a new `.v2`
|
|
132
|
+
version of the lexicon or introducing a `v2` field.
|
|
133
|
+
|
|
134
|
+
To date, breaking changes have only occurred during the early
|
|
135
|
+
stages of launching Hypercerts on AT Protocol, before external
|
|
136
|
+
consumers were building against the lexicons. We intend to keep
|
|
137
|
+
it that way.
|
|
138
|
+
|
|
139
|
+
It is also worth noting that members of the ATProto community have
|
|
140
|
+
been working on tooling to make these problems easier to deal with in
|
|
141
|
+
future, e.g. see https://panproto.dev/
|
|
142
|
+
|
|
143
|
+
## Use of branches
|
|
144
|
+
|
|
145
|
+
`main` is the only evergreen branch and the default branch on GitHub.
|
|
146
|
+
We aim to minimise deviations between `main` and versions published on
|
|
147
|
+
npm and ATProto. However the publishing processes involve several
|
|
148
|
+
moving parts (including third-party systems), and it is technically
|
|
149
|
+
impossible to update all three at the same time. So **please do not
|
|
150
|
+
assume they will always be perfectly in sync**.
|
|
151
|
+
|
|
152
|
+
See [docs/PUBLISHING.md](docs/PUBLISHING.md) for the full release workflow.
|
|
153
|
+
|
|
154
|
+
> If you see a `develop` branch, it is a stale leftover from a
|
|
155
|
+
> previous workflow and is no longer used; do not open pull requests
|
|
156
|
+
> against it.
|
|
157
|
+
|
|
158
|
+
## Contributing / development
|
|
159
|
+
|
|
160
|
+
Please see [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
161
|
+
|
|
162
|
+
### Project Structure
|
|
163
|
+
|
|
164
|
+
```text
|
|
165
|
+
lexicons/ Source of truth (committed)
|
|
166
|
+
org/hypercerts/ Hypercerts protocol lexicons
|
|
167
|
+
org/hyperboards/ Hyperboards visual layer lexicons
|
|
168
|
+
app/certified/ Shared/certified lexicons
|
|
169
|
+
com/atproto/ ATProto external references
|
|
170
|
+
|
|
171
|
+
generated/ Auto-generated TypeScript (gitignored)
|
|
172
|
+
dist/ Built bundles (gitignored)
|
|
173
|
+
scripts/ Build and codegen scripts
|
|
174
|
+
```
|
|
35
175
|
|
|
36
|
-
|
|
176
|
+
> **Never edit `generated/` or `dist/` directly** — they are
|
|
177
|
+
> regenerated from lexicon JSON files.
|
|
37
178
|
|
|
38
179
|
## Installation
|
|
39
180
|
|
|
@@ -41,9 +182,7 @@ following icons:
|
|
|
41
182
|
npm install @hypercerts-org/lexicon
|
|
42
183
|
```
|
|
43
184
|
|
|
44
|
-
##
|
|
45
|
-
|
|
46
|
-
### Basic Import
|
|
185
|
+
## Quick Start
|
|
47
186
|
|
|
48
187
|
```typescript
|
|
49
188
|
import {
|
|
@@ -51,8 +190,6 @@ import {
|
|
|
51
190
|
ACTIVITY_NSID,
|
|
52
191
|
validate,
|
|
53
192
|
} from "@hypercerts-org/lexicon";
|
|
54
|
-
|
|
55
|
-
// Use with AT Protocol Agent
|
|
56
193
|
import { Agent } from "@atproto/api";
|
|
57
194
|
|
|
58
195
|
const agent = new Agent({ service: "https://bsky.social" });
|
|
@@ -60,222 +197,152 @@ const agent = new Agent({ service: "https://bsky.social" });
|
|
|
60
197
|
// Register lexicons with the agent
|
|
61
198
|
agent.api.lex.add(...HYPERCERTS_SCHEMAS);
|
|
62
199
|
|
|
63
|
-
//
|
|
64
|
-
const
|
|
200
|
+
// Build a record
|
|
201
|
+
const record = {
|
|
65
202
|
$type: ACTIVITY_NSID,
|
|
66
|
-
title: "
|
|
67
|
-
shortDescription: "
|
|
68
|
-
// workScope can be a CEL expression (structured, machine-evaluable):
|
|
69
|
-
workScope: {
|
|
70
|
-
$type: "org.hypercerts.workscope.cel",
|
|
71
|
-
expression:
|
|
72
|
-
"scope.hasAll(['mangrove_restoration', 'environmental_education']) && location.country == 'KE'",
|
|
73
|
-
usedTags: [
|
|
74
|
-
{
|
|
75
|
-
uri: "at://did:plc:alice/org.hypercerts.workscope.tag/3k2abc",
|
|
76
|
-
cid: "...",
|
|
77
|
-
},
|
|
78
|
-
{
|
|
79
|
-
uri: "at://did:plc:alice/org.hypercerts.workscope.tag/7x9def",
|
|
80
|
-
cid: "...",
|
|
81
|
-
},
|
|
82
|
-
],
|
|
83
|
-
version: "v1",
|
|
84
|
-
createdAt: new Date().toISOString(),
|
|
85
|
-
},
|
|
86
|
-
// OR a strongRef to a single work scope tag:
|
|
87
|
-
// workScope: { uri: "at://did:plc:alice/org.hypercerts.workscope.tag/abc123", cid: "..." },
|
|
88
|
-
// OR a simple string: workScope: { $type: "org.hypercerts.claim.activity#workScopeString", scope: "Environmental conservation" },
|
|
89
|
-
startDate: "2023-01-01T00:00:00Z",
|
|
90
|
-
endDate: "2023-12-31T23:59:59Z",
|
|
203
|
+
title: "Reforestation in Amazon Basin 2024",
|
|
204
|
+
shortDescription: "Planted 5,000 native trees across 12 hectares",
|
|
91
205
|
createdAt: new Date().toISOString(),
|
|
92
206
|
};
|
|
93
207
|
|
|
94
|
-
// Validate before
|
|
95
|
-
const
|
|
96
|
-
if (!
|
|
97
|
-
console.error("Validation failed:", validation.errors);
|
|
98
|
-
}
|
|
208
|
+
// Validate before writing
|
|
209
|
+
const result = validate(ACTIVITY_NSID, record);
|
|
210
|
+
if (!result.valid) throw new Error(JSON.stringify(result.errors));
|
|
99
211
|
|
|
212
|
+
// Write to the network
|
|
100
213
|
await agent.api.com.atproto.repo.createRecord({
|
|
101
214
|
repo: agent.session?.did,
|
|
102
215
|
collection: ACTIVITY_NSID,
|
|
103
|
-
record
|
|
216
|
+
record,
|
|
104
217
|
});
|
|
105
218
|
```
|
|
106
219
|
|
|
107
|
-
|
|
220
|
+
## Lexicon Reference
|
|
108
221
|
|
|
109
|
-
|
|
110
|
-
using geographic coordinates or other location formats. They can be referenced
|
|
111
|
-
by activities, collections, attachments, measurements, and evaluations.
|
|
222
|
+
### Claims (`org.hypercerts.claim.*`)
|
|
112
223
|
|
|
113
|
-
|
|
114
|
-
|
|
224
|
+
| Lexicon | NSID | Description |
|
|
225
|
+
| --------------------------- | --------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
|
|
226
|
+
| **Activity** | `org.hypercerts.claim.activity` | The main hypercert record — describes impact work with title, description, contributors, work scope, timeframe, locations, and rights. |
|
|
227
|
+
| **Contribution** | `org.hypercerts.claim.contribution` | Details about a specific contribution: role, description, and timeframe. |
|
|
228
|
+
| **Contributor Information** | `org.hypercerts.claim.contributorInformation` | Identity record for a contributor: identifier (DID or URI), display name, and avatar. |
|
|
229
|
+
| **Rights** | `org.hypercerts.claim.rights` | Licensing and rights terms (e.g. "CC BY-SA 4.0") attached to an activity. |
|
|
115
230
|
|
|
116
|
-
|
|
117
|
-
$type: LOCATION_NSID,
|
|
118
|
-
lpVersion: "1.0", // Location Protocol version
|
|
119
|
-
srs: "http://www.opengis.net/def/crs/OGC/1.3/CRS84", // Spatial Reference System
|
|
120
|
-
locationType: "coordinate-decimal", // or "geojson-point", "geojson", "h3", "geohash", "wkt", "address", etc.
|
|
121
|
-
location: {
|
|
122
|
-
uri: "https://example.com/location-data.geojson",
|
|
123
|
-
},
|
|
124
|
-
// Optional fields
|
|
125
|
-
name: "Project Site A",
|
|
126
|
-
description: "Primary research facility in the Amazon rainforest",
|
|
127
|
-
createdAt: new Date().toISOString(),
|
|
128
|
-
};
|
|
129
|
-
```
|
|
231
|
+
### Collections (`org.hypercerts.*`)
|
|
130
232
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
- `location` (required): Location data as URI, blob, or string
|
|
135
|
-
- `name` (optional): Human-readable name for the location
|
|
136
|
-
- `description` (optional): Additional context about the location
|
|
137
|
-
- `createdAt` (required): Timestamp when the record was created
|
|
233
|
+
| Lexicon | NSID | Description |
|
|
234
|
+
| -------------- | --------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
235
|
+
| **Collection** | `org.hypercerts.collection` | A named, weighted group of activities and/or other collections. Supports recursive nesting. Used for projects, portfolios, favourites, funding rounds, etc. |
|
|
138
236
|
|
|
139
|
-
|
|
237
|
+
### Context (`org.hypercerts.context.*`)
|
|
140
238
|
|
|
141
|
-
|
|
239
|
+
| Lexicon | NSID | Description |
|
|
240
|
+
| ------------------- | ---------------------------------------- | --------------------------------------------------------------------------------------- |
|
|
241
|
+
| **Attachment** | `org.hypercerts.context.attachment` | Documents, reports, evidence, or other files linked to a record. |
|
|
242
|
+
| **Measurement** | `org.hypercerts.context.measurement` | Quantitative data point (metric + unit + value) linked to one or more records. |
|
|
243
|
+
| **Evaluation** | `org.hypercerts.context.evaluation` | An assessment of a record with evaluators, summary, score, and supporting measurements. |
|
|
244
|
+
| **Acknowledgement** | `org.hypercerts.context.acknowledgement` | Bidirectional link: confirms or rejects inclusion of a record in another context. |
|
|
142
245
|
|
|
143
|
-
|
|
144
|
-
2. **Small blob**: Embedded location data (up to 10MB)
|
|
145
|
-
3. **Location string**: Inline string wrapped in an object, containing coordinates or GeoJSON
|
|
246
|
+
### Work Scope (`org.hypercerts.workscope.*`)
|
|
146
247
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
lpVersion: "1.0",
|
|
152
|
-
srs: "http://www.opengis.net/def/crs/OGC/1.3/CRS84",
|
|
153
|
-
locationType: "geojson-point",
|
|
154
|
-
location: {
|
|
155
|
-
blob: {
|
|
156
|
-
$type: "blob",
|
|
157
|
-
ref: {
|
|
158
|
-
$link: "bafyrei...", // CID of the uploaded blob
|
|
159
|
-
},
|
|
160
|
-
mimeType: "application/geo+json",
|
|
161
|
-
size: 123,
|
|
162
|
-
},
|
|
163
|
-
},
|
|
164
|
-
name: "Amazon Research Station",
|
|
165
|
-
createdAt: new Date().toISOString(),
|
|
166
|
-
};
|
|
248
|
+
| Lexicon | NSID | Description |
|
|
249
|
+
| ------------------ | ------------------------------ | --------------------------------------------------------------------------------------------------------------------------------- |
|
|
250
|
+
| **Tag** | `org.hypercerts.workscope.tag` | Reusable scope atom (topic, domain, method, …) with taxonomy support, aliases, and linked ontologies. |
|
|
251
|
+
| **CEL Expression** | `org.hypercerts.workscope.cel` | Structured work scope using [CEL](https://github.com/google/cel-spec) expressions over tags. Embedded inline in activity records. |
|
|
167
252
|
|
|
168
|
-
|
|
169
|
-
const locationWithCoordinates = {
|
|
170
|
-
$type: LOCATION_NSID,
|
|
171
|
-
lpVersion: "1.0",
|
|
172
|
-
srs: "http://www.opengis.net/def/crs/OGC/1.3/CRS84",
|
|
173
|
-
locationType: "coordinate-decimal",
|
|
174
|
-
location: {
|
|
175
|
-
string: "-3.4653, -62.2159", // lat, lon
|
|
176
|
-
},
|
|
177
|
-
name: "Amazon Research Site",
|
|
178
|
-
description: "Field station coordinates",
|
|
179
|
-
createdAt: new Date().toISOString(),
|
|
180
|
-
};
|
|
253
|
+
### Funding (`org.hypercerts.funding.*`)
|
|
181
254
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
locationType: "geojson-point",
|
|
188
|
-
location: {
|
|
189
|
-
string: '{"type":"Point","coordinates":[-62.2159,-3.4653]}',
|
|
190
|
-
},
|
|
191
|
-
name: "Research Station Alpha",
|
|
192
|
-
createdAt: new Date().toISOString(),
|
|
193
|
-
};
|
|
194
|
-
```
|
|
255
|
+
| Lexicon | NSID | Description |
|
|
256
|
+
| ----------- | -------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
257
|
+
| **Receipt** | `org.hypercerts.funding.receipt` | Records a payment to a recipient, with amount, currency, payment rail, and optional transaction ID. The sender (`from`) is optional to support anonymous funders. |
|
|
258
|
+
|
|
259
|
+
### Hyperboards (`org.hyperboards.*`)
|
|
195
260
|
|
|
196
|
-
|
|
261
|
+
| Lexicon | NSID | Description |
|
|
262
|
+
| ------------------- | -------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
|
|
263
|
+
| **Board** | `org.hyperboards.board` | Visual presentation layer wrapping an activity or collection with background, colors, aspect ratio, and per-contributor styling. |
|
|
264
|
+
| **Display Profile** | `org.hyperboards.displayProfile` | Per-user visual defaults (avatar, hover image, video, click-through URL) reusable across boards. Singleton record (`literal:self`). |
|
|
197
265
|
|
|
198
|
-
|
|
266
|
+
### Certified (`app.certified.*`)
|
|
267
|
+
|
|
268
|
+
| Lexicon | NSID | Description |
|
|
269
|
+
| -------------------- | ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
|
|
270
|
+
| **Location** | `app.certified.location` | Geographic reference using the [Location Protocol](https://spec.decentralizedgeo.org) (coordinates, GeoJSON, H3, WKT, etc.). |
|
|
271
|
+
| **Profile** | `app.certified.actor.profile` | User account profile with display name, bio, avatar, and banner. |
|
|
272
|
+
| **Organization** | `app.certified.actor.organization` | Organization metadata: legal structure, URLs, location, founding date. |
|
|
273
|
+
| **Badge Definition** | `app.certified.badge.definition` | Defines a badge type with title, icon, and optional issuer allowlist. |
|
|
274
|
+
| **Badge Award** | `app.certified.badge.award` | Awards a badge to a user, project, or activity. |
|
|
275
|
+
| **Badge Response** | `app.certified.badge.response` | Recipient accepts or rejects a badge award. |
|
|
276
|
+
| **EVM Link** | `app.certified.link.evm` | Verifiable ATProto DID ↔ EVM wallet link via EIP-712 signature. Extensible for future proof methods (e.g. ERC-1271, ERC-6492). |
|
|
277
|
+
|
|
278
|
+
> **Full property tables** → [SCHEMAS.md](SCHEMAS.md)
|
|
279
|
+
|
|
280
|
+
## Entity Relationship Diagram
|
|
281
|
+
|
|
282
|
+

|
|
283
|
+
|
|
284
|
+
<details>
|
|
285
|
+
<summary>View ERD with field details</summary>
|
|
286
|
+
|
|
287
|
+

|
|
288
|
+
|
|
289
|
+
</details>
|
|
290
|
+
|
|
291
|
+
## Usage
|
|
292
|
+
|
|
293
|
+
### Accessing NSIDs
|
|
294
|
+
|
|
295
|
+
Individual constants (recommended):
|
|
199
296
|
|
|
200
297
|
```typescript
|
|
201
298
|
import { ACTIVITY_NSID, COLLECTION_NSID } from "@hypercerts-org/lexicon";
|
|
202
|
-
|
|
203
|
-
// Clean and explicit
|
|
204
|
-
const record = {
|
|
205
|
-
$type: ACTIVITY_NSID,
|
|
206
|
-
// ...
|
|
207
|
-
};
|
|
208
299
|
```
|
|
209
300
|
|
|
210
|
-
|
|
301
|
+
Semantic object:
|
|
211
302
|
|
|
212
303
|
```typescript
|
|
213
304
|
import { HYPERCERTS_NSIDS } from "@hypercerts-org/lexicon";
|
|
214
305
|
|
|
215
|
-
|
|
216
|
-
const activityId = HYPERCERTS_NSIDS.ACTIVITY;
|
|
217
|
-
const collectionId = HYPERCERTS_NSIDS.COLLECTION;
|
|
218
|
-
const rightsId = HYPERCERTS_NSIDS.RIGHTS;
|
|
306
|
+
const id = HYPERCERTS_NSIDS.ACTIVITY;
|
|
219
307
|
```
|
|
220
308
|
|
|
221
|
-
|
|
309
|
+
Type-based mapping:
|
|
222
310
|
|
|
223
311
|
```typescript
|
|
224
312
|
import { HYPERCERTS_NSIDS_BY_TYPE } from "@hypercerts-org/lexicon";
|
|
225
313
|
|
|
226
|
-
|
|
227
|
-
const activityId = HYPERCERTS_NSIDS_BY_TYPE.OrgHypercertsClaimActivity;
|
|
228
|
-
const collectionId = HYPERCERTS_NSIDS_BY_TYPE.OrgHypercertsCollection;
|
|
314
|
+
const id = HYPERCERTS_NSIDS_BY_TYPE.OrgHypercertsClaimActivity;
|
|
229
315
|
```
|
|
230
316
|
|
|
231
|
-
|
|
317
|
+
Lightweight bundle (no TypeScript types, smaller bundle):
|
|
232
318
|
|
|
233
319
|
```typescript
|
|
234
320
|
import { schemas, validate, ids } from "@hypercerts-org/lexicon/lexicons";
|
|
235
|
-
|
|
236
|
-
// Lighter bundle, type-based namespace access
|
|
237
|
-
const result = validate(ids.OrgHypercertsClaimActivity, record);
|
|
238
321
|
```
|
|
239
322
|
|
|
240
|
-
**Note**: Individual constants (e.g., `ACTIVITY_NSID`) are the recommended approach for most use cases as they provide the best developer experience with clear, concise naming.
|
|
241
|
-
|
|
242
323
|
### TypeScript Types
|
|
243
324
|
|
|
244
|
-
All lexicon types are exported as namespaces:
|
|
245
|
-
|
|
246
325
|
```typescript
|
|
247
326
|
import { OrgHypercertsClaimActivity } from "@hypercerts-org/lexicon";
|
|
248
327
|
|
|
249
|
-
// Use the Main type
|
|
250
328
|
const activity: OrgHypercertsClaimActivity.Main = {
|
|
251
329
|
$type: "org.hypercerts.claim.activity",
|
|
252
330
|
title: "My Impact Work",
|
|
253
|
-
|
|
331
|
+
shortDescription: "...",
|
|
332
|
+
createdAt: new Date().toISOString(),
|
|
254
333
|
};
|
|
255
334
|
```
|
|
256
335
|
|
|
257
|
-
###
|
|
258
|
-
|
|
259
|
-
Each lexicon is available in two forms as individual constants:
|
|
336
|
+
### Lexicon Documents
|
|
260
337
|
|
|
261
338
|
```typescript
|
|
262
339
|
import {
|
|
263
|
-
//
|
|
264
|
-
|
|
265
|
-
RIGHTS_LEXICON_JSON,
|
|
266
|
-
|
|
267
|
-
// Typed LexiconDoc - from lexicons.get() at module initialization
|
|
268
|
-
ACTIVITY_LEXICON_DOC,
|
|
269
|
-
RIGHTS_LEXICON_DOC,
|
|
340
|
+
ACTIVITY_LEXICON_JSON, // raw JSON (untyped)
|
|
341
|
+
ACTIVITY_LEXICON_DOC, // LexiconDoc (typed)
|
|
270
342
|
} from "@hypercerts-org/lexicon";
|
|
271
343
|
```
|
|
272
344
|
|
|
273
|
-
|
|
274
|
-
| ------- | -------------------- | ------------------------- | ------------------------------ |
|
|
275
|
-
| `_JSON` | Untyped JSON | Direct JSON import | Raw schema data |
|
|
276
|
-
| `_DOC` | `LexiconDoc` (typed) | `lexicons.get()` instance | Type-safe lexicon manipulation |
|
|
277
|
-
|
|
278
|
-
Or access all lexicons via semantic mapping objects:
|
|
345
|
+
Or via semantic mapping objects:
|
|
279
346
|
|
|
280
347
|
```typescript
|
|
281
348
|
import {
|
|
@@ -283,159 +350,111 @@ import {
|
|
|
283
350
|
HYPERCERTS_LEXICON_DOC,
|
|
284
351
|
} from "@hypercerts-org/lexicon";
|
|
285
352
|
|
|
286
|
-
|
|
287
|
-
const activityJSON = HYPERCERTS_LEXICON_JSON.ACTIVITY;
|
|
288
|
-
const activityDoc = HYPERCERTS_LEXICON_DOC.ACTIVITY;
|
|
289
|
-
const rightsJSON = HYPERCERTS_LEXICON_JSON.RIGHTS;
|
|
290
|
-
const rightsDoc = HYPERCERTS_LEXICON_DOC.RIGHTS;
|
|
353
|
+
const doc = HYPERCERTS_LEXICON_DOC.ACTIVITY;
|
|
291
354
|
```
|
|
292
355
|
|
|
293
|
-
## Schema Documentation
|
|
294
|
-
|
|
295
|
-
For complete schema documentation with all lexicon definitions and
|
|
296
|
-
property tables, see [SCHEMAS.md](SCHEMAS.md).
|
|
297
|
-
|
|
298
356
|
## Examples
|
|
299
357
|
|
|
300
|
-
###
|
|
301
|
-
|
|
302
|
-
Collections (`org.hypercerts.collection`) are named sets of references to
|
|
303
|
-
other records, for any purpose the creator chooses. They live at the
|
|
304
|
-
top-level namespace (not under `claim`) because they can contain more than
|
|
305
|
-
just claims.
|
|
306
|
-
|
|
307
|
-
#### Use Cases
|
|
308
|
-
|
|
309
|
-
- Defining which activity claims belong to a project
|
|
310
|
-
- Collections of projects
|
|
311
|
-
- Favourites lists
|
|
312
|
-
- Items associated with a particular funding round or funder
|
|
313
|
-
- Portfolios of work by a contributor or organization
|
|
314
|
-
- Thematic groupings (by work scope/topic)
|
|
315
|
-
- Curated showcases for display (e.g. a hyperboard)
|
|
316
|
-
- Milestone groupings (activities in a sprint/cycle)
|
|
317
|
-
- Geographic groupings (projects or locations in a region)
|
|
318
|
-
- Collections for reporting (e.g. all claims in a grant report)
|
|
319
|
-
|
|
320
|
-
**Note**: Hyperboards are a separate concern — they are visualisations
|
|
321
|
-
built on top of collections, not collections themselves.
|
|
322
|
-
|
|
323
|
-
#### Creating a Collection with Nested Items
|
|
358
|
+
### Creating Activities with Work Scope
|
|
324
359
|
|
|
325
360
|
```typescript
|
|
326
|
-
import {
|
|
361
|
+
import { ACTIVITY_NSID } from "@hypercerts-org/lexicon";
|
|
327
362
|
|
|
328
|
-
const
|
|
329
|
-
$type:
|
|
330
|
-
title: "
|
|
331
|
-
shortDescription:
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
},
|
|
349
|
-
],
|
|
363
|
+
const activity = {
|
|
364
|
+
$type: ACTIVITY_NSID,
|
|
365
|
+
title: "Mangrove Restoration in Mombasa",
|
|
366
|
+
shortDescription: "Restored 3 hectares of mangrove forest",
|
|
367
|
+
// Structured work scope via CEL expression:
|
|
368
|
+
workScope: {
|
|
369
|
+
$type: "org.hypercerts.workscope.cel",
|
|
370
|
+
expression:
|
|
371
|
+
"scope.hasAll(['mangrove_restoration']) && location.country == 'KE'",
|
|
372
|
+
usedTags: [
|
|
373
|
+
{
|
|
374
|
+
uri: "at://did:plc:alice/org.hypercerts.workscope.tag/3k2abc",
|
|
375
|
+
cid: "...",
|
|
376
|
+
},
|
|
377
|
+
],
|
|
378
|
+
version: "v1",
|
|
379
|
+
createdAt: new Date().toISOString(),
|
|
380
|
+
},
|
|
381
|
+
startDate: "2024-01-01T00:00:00Z",
|
|
382
|
+
endDate: "2024-12-31T23:59:59Z",
|
|
350
383
|
createdAt: new Date().toISOString(),
|
|
351
384
|
};
|
|
352
385
|
```
|
|
353
386
|
|
|
354
|
-
### Creating
|
|
355
|
-
|
|
356
|
-
Projects are collections with a `type` field set to "project" and can
|
|
357
|
-
include rich-text descriptions:
|
|
387
|
+
### Creating Collections (Projects, Portfolios, etc.)
|
|
358
388
|
|
|
359
389
|
```typescript
|
|
360
|
-
|
|
361
|
-
|
|
390
|
+
import { COLLECTION_NSID } from "@hypercerts-org/lexicon";
|
|
391
|
+
|
|
392
|
+
const project = {
|
|
393
|
+
$type: COLLECTION_NSID,
|
|
362
394
|
type: "project",
|
|
363
395
|
title: "Carbon Offset Initiative",
|
|
364
|
-
shortDescription: "
|
|
365
|
-
description: {
|
|
366
|
-
uri: "at://did:plc:alice/pub.leaflet.pages.linearDocument/abc123",
|
|
367
|
-
cid: "...",
|
|
368
|
-
},
|
|
396
|
+
shortDescription: "Activities focused on carbon reduction and reforestation",
|
|
369
397
|
items: [
|
|
370
398
|
{
|
|
371
|
-
|
|
372
|
-
|
|
399
|
+
itemIdentifier: {
|
|
400
|
+
uri: "at://did:plc:alice/org.hypercerts.claim.activity/3k2abc",
|
|
401
|
+
cid: "...",
|
|
402
|
+
},
|
|
373
403
|
},
|
|
374
404
|
{
|
|
375
|
-
|
|
376
|
-
|
|
405
|
+
itemIdentifier: {
|
|
406
|
+
uri: "at://did:plc:bob/org.hypercerts.claim.activity/7x9def",
|
|
407
|
+
cid: "...",
|
|
408
|
+
},
|
|
409
|
+
},
|
|
410
|
+
// Collections can contain other collections (recursive nesting):
|
|
411
|
+
{
|
|
412
|
+
itemIdentifier: {
|
|
413
|
+
uri: "at://did:plc:carol/org.hypercerts.collection/4m5ghi",
|
|
414
|
+
cid: "...",
|
|
415
|
+
},
|
|
377
416
|
},
|
|
378
417
|
],
|
|
379
418
|
createdAt: new Date().toISOString(),
|
|
380
419
|
};
|
|
381
420
|
```
|
|
382
421
|
|
|
383
|
-
|
|
384
|
-
"favorites", or any other collection type. The `description` field
|
|
385
|
-
supports rich-text via Leaflet linear documents.
|
|
386
|
-
|
|
387
|
-
### Adding Visual Representation to Collections
|
|
388
|
-
|
|
389
|
-
Collections can include `avatar` and `banner` fields for visual representation:
|
|
422
|
+
### Creating Location Records
|
|
390
423
|
|
|
391
424
|
```typescript
|
|
392
|
-
import {
|
|
425
|
+
import { LOCATION_NSID } from "@hypercerts-org/lexicon";
|
|
393
426
|
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
},
|
|
403
|
-
items: [
|
|
404
|
-
// ... collection items
|
|
405
|
-
],
|
|
427
|
+
// Decimal coordinates
|
|
428
|
+
const location = {
|
|
429
|
+
$type: LOCATION_NSID,
|
|
430
|
+
lpVersion: "1.0",
|
|
431
|
+
srs: "http://www.opengis.net/def/crs/OGC/1.3/CRS84",
|
|
432
|
+
locationType: "coordinate-decimal",
|
|
433
|
+
location: { string: "-3.4653, -62.2159" },
|
|
434
|
+
name: "Amazon Research Station",
|
|
406
435
|
createdAt: new Date().toISOString(),
|
|
407
436
|
};
|
|
408
|
-
```
|
|
409
437
|
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
438
|
+
// GeoJSON
|
|
439
|
+
const geoLocation = {
|
|
440
|
+
$type: LOCATION_NSID,
|
|
441
|
+
lpVersion: "1.0",
|
|
442
|
+
srs: "http://www.opengis.net/def/crs/OGC/1.3/CRS84",
|
|
443
|
+
locationType: "geojson-point",
|
|
444
|
+
location: { string: '{"type":"Point","coordinates":[-62.2159,-3.4653]}' },
|
|
445
|
+
name: "Research Station Alpha",
|
|
446
|
+
createdAt: new Date().toISOString(),
|
|
447
|
+
};
|
|
448
|
+
```
|
|
413
449
|
|
|
414
450
|
### Acknowledging Inclusion
|
|
415
451
|
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
one user includes another user's record (e.g. adding an activity to a
|
|
419
|
-
collection), the owner of the included record can create an
|
|
420
|
-
acknowledgement to confirm or reject the inclusion. This forms a
|
|
421
|
-
two-way link that an AppView can verify.
|
|
422
|
-
|
|
423
|
-
Each acknowledgement uses `com.atproto.repo.strongRef` fields to
|
|
424
|
-
reference both the **subject** (the record being included) and the
|
|
425
|
-
**context** (the record it's being included in).
|
|
426
|
-
|
|
427
|
-
See [SCHEMAS.md](SCHEMAS.md) for the full property reference.
|
|
428
|
-
|
|
429
|
-
#### Use Case: Activity Included in a Collection
|
|
430
|
-
|
|
431
|
-
A project organizer (Alice) creates a collection and adds Bob's
|
|
432
|
-
activity to it via a `strongRef` in the collection's `items[]` array.
|
|
433
|
-
Bob then creates an acknowledgement in his own repo to confirm:
|
|
452
|
+
When one user includes another's record (e.g. adding an activity to a
|
|
453
|
+
collection), the owner can confirm or reject with an acknowledgement:
|
|
434
454
|
|
|
435
455
|
```typescript
|
|
436
456
|
import { ACKNOWLEDGEMENT_NSID } from "@hypercerts-org/lexicon";
|
|
437
457
|
|
|
438
|
-
// Bob acknowledges that his activity is included in Alice's collection
|
|
439
458
|
const ack = {
|
|
440
459
|
$type: ACKNOWLEDGEMENT_NSID,
|
|
441
460
|
subject: {
|
|
@@ -446,96 +465,26 @@ const ack = {
|
|
|
446
465
|
uri: "at://did:plc:alice/org.hypercerts.collection/7x9def",
|
|
447
466
|
cid: "bafy...",
|
|
448
467
|
},
|
|
449
|
-
acknowledged: true,
|
|
450
|
-
createdAt: new Date().toISOString(),
|
|
451
|
-
};
|
|
452
|
-
```
|
|
453
|
-
|
|
454
|
-
#### Use Case: Contributor Included in an Activity
|
|
455
|
-
|
|
456
|
-
Alice creates an activity that lists Bob as a contributor. Bob creates
|
|
457
|
-
an acknowledgement in his own repo to confirm his participation:
|
|
458
|
-
|
|
459
|
-
```typescript
|
|
460
|
-
const ack = {
|
|
461
|
-
$type: ACKNOWLEDGEMENT_NSID,
|
|
462
|
-
subject: {
|
|
463
|
-
// Bob's contributor information record
|
|
464
|
-
uri: "at://did:plc:bob/org.hypercerts.claim.contributorInformation/abc123",
|
|
465
|
-
cid: "bafy...",
|
|
466
|
-
},
|
|
467
|
-
context: {
|
|
468
|
-
// Alice's activity that lists Bob as contributor
|
|
469
|
-
uri: "at://did:plc:alice/org.hypercerts.claim.activity/3k2abc",
|
|
470
|
-
cid: "bafy...",
|
|
471
|
-
},
|
|
472
|
-
acknowledged: true,
|
|
473
|
-
comment: "Confirming my contribution to this reforestation project",
|
|
474
|
-
createdAt: new Date().toISOString(),
|
|
475
|
-
};
|
|
476
|
-
```
|
|
477
|
-
|
|
478
|
-
Setting `acknowledged: false` explicitly rejects inclusion, which an
|
|
479
|
-
AppView can use to flag disputed associations.
|
|
480
|
-
|
|
481
|
-
### Adding Locations to Activities
|
|
482
|
-
|
|
483
|
-
The `locations` field in activity records is an array of strong references
|
|
484
|
-
(`com.atproto.repo.strongRef`) pointing to `app.certified.location` records.
|
|
485
|
-
Each strong reference contains two required fields:
|
|
486
|
-
|
|
487
|
-
- `uri`: The ATProto URI of the location record (e.g., `at://did:plc:alice/app.certified.location/abc123`)
|
|
488
|
-
- `cid`: The content identifier (CID) of the location record, ensuring referential integrity
|
|
489
|
-
|
|
490
|
-
**Validation and Expectations**:
|
|
491
|
-
|
|
492
|
-
- All location records referenced in the `locations` array must conform to the
|
|
493
|
-
`app.certified.location` lexicon schema
|
|
494
|
-
- The `uri` field must be a valid ATProto URI pointing to an existing location record
|
|
495
|
-
- The `cid` field must match the current CID of the referenced location record
|
|
496
|
-
- The `locations` field is optional; activities can be created without location data
|
|
497
|
-
|
|
498
|
-
### Adding Location to Collections
|
|
499
|
-
|
|
500
|
-
Collections can include an optional `location` field to specify where the collection's activities were performed:
|
|
501
|
-
|
|
502
|
-
```typescript
|
|
503
|
-
const collectionRecord = {
|
|
504
|
-
$type: "org.hypercerts.collection",
|
|
505
|
-
title: "Climate Action Projects",
|
|
506
|
-
shortDescription: "A collection of climate-related activities",
|
|
507
|
-
location: {
|
|
508
|
-
uri: "at://did:plc:alice/app.certified.location/xyz789",
|
|
509
|
-
cid: "...",
|
|
510
|
-
},
|
|
511
|
-
items: [
|
|
512
|
-
// ... collection items
|
|
513
|
-
],
|
|
468
|
+
acknowledged: true, // false to reject
|
|
514
469
|
createdAt: new Date().toISOString(),
|
|
515
470
|
};
|
|
516
471
|
```
|
|
517
472
|
|
|
518
|
-
The `location` field is a strong reference to an `app.certified.location` record containing the same `uri` and `cid` fields as described above for activities.
|
|
519
|
-
|
|
520
473
|
### Creating Attachments
|
|
521
474
|
|
|
522
|
-
Attachments provide commentary, context, evidence, or documentary material
|
|
523
|
-
related to hypercert records. They can be linked to activities, evaluations,
|
|
524
|
-
measurements, or even other attachments:
|
|
525
|
-
|
|
526
475
|
```typescript
|
|
527
476
|
import { ATTACHMENT_NSID } from "@hypercerts-org/lexicon";
|
|
528
477
|
|
|
529
|
-
const
|
|
478
|
+
const attachment = {
|
|
530
479
|
$type: ATTACHMENT_NSID,
|
|
531
480
|
title: "Field Survey Report",
|
|
481
|
+
contentType: "report",
|
|
532
482
|
subjects: [
|
|
533
483
|
{
|
|
534
484
|
uri: "at://did:plc:alice/org.hypercerts.claim.activity/abc123",
|
|
535
485
|
cid: "...",
|
|
536
486
|
},
|
|
537
487
|
],
|
|
538
|
-
contentType: "report",
|
|
539
488
|
content: [
|
|
540
489
|
{ uri: "https://example.com/reports/survey-2024.pdf" },
|
|
541
490
|
{ uri: "ipfs://Qm..." },
|
|
@@ -545,27 +494,61 @@ const attachmentRecord = {
|
|
|
545
494
|
};
|
|
546
495
|
```
|
|
547
496
|
|
|
548
|
-
|
|
497
|
+
## Development
|
|
498
|
+
|
|
499
|
+
### Commands
|
|
549
500
|
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
501
|
+
```bash
|
|
502
|
+
npm run gen-api # Regenerate TypeScript types from lexicons
|
|
503
|
+
npm run build # Build distributable bundles (ESM, CJS, types)
|
|
504
|
+
npm run check # Validate + typecheck + build (run before committing)
|
|
505
|
+
npm run lint # Check formatting (Prettier + ESLint)
|
|
506
|
+
npm run format # Auto-fix formatting
|
|
507
|
+
npm run gen-schemas-md # Regenerate SCHEMAS.md
|
|
508
|
+
npm run test # Run tests
|
|
509
|
+
```
|
|
557
510
|
|
|
558
|
-
|
|
511
|
+
### Linking ATProto Identity to EVM Wallets
|
|
512
|
+
|
|
513
|
+
The `app.certified.link.evm` record enables verifiable linking between
|
|
514
|
+
an ATProto DID and an EVM wallet address. The link is proven via a
|
|
515
|
+
cryptographic signature, allowing any verifier to confirm that the
|
|
516
|
+
wallet owner authorized the binding. Currently supports EOA wallets
|
|
517
|
+
via EIP-712 typed data signatures; the `proof` field is an open union
|
|
518
|
+
to allow future signature methods (e.g. ERC-1271, ERC-6492).
|
|
559
519
|
|
|
560
520
|
```typescript
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
521
|
+
import { LINK_EVM_NSID } from "@hypercerts-org/lexicon";
|
|
522
|
+
|
|
523
|
+
const evmLinkRecord = {
|
|
524
|
+
$type: LINK_EVM_NSID,
|
|
525
|
+
address: "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
|
|
526
|
+
proof: {
|
|
527
|
+
$type: "app.certified.link.evm#eip712Proof",
|
|
528
|
+
signature: "0xabc123...", // truncated for readability; real signatures are 130-132 hex chars
|
|
529
|
+
message: {
|
|
530
|
+
$type: "app.certified.link.evm#eip712Message",
|
|
531
|
+
did: "did:plc:alice",
|
|
532
|
+
evmAddress: "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
|
|
533
|
+
chainId: "1",
|
|
534
|
+
timestamp: "1709500000",
|
|
535
|
+
nonce: "0",
|
|
536
|
+
},
|
|
568
537
|
},
|
|
569
538
|
createdAt: new Date().toISOString(),
|
|
570
539
|
};
|
|
571
540
|
```
|
|
541
|
+
|
|
542
|
+
**Key fields:**
|
|
543
|
+
|
|
544
|
+
- `address` (required): 0x-prefixed EVM wallet address (EIP-55
|
|
545
|
+
checksummed, 42 chars)
|
|
546
|
+
- `proof` (required): Open union containing the cryptographic proof of
|
|
547
|
+
wallet ownership. Each variant bundles its signature with the
|
|
548
|
+
corresponding message format. Currently the only variant is
|
|
549
|
+
`#eip712Proof` for EOA wallets.
|
|
550
|
+
- `createdAt` (required): Timestamp when the record was created
|
|
551
|
+
|
|
552
|
+
## License
|
|
553
|
+
|
|
554
|
+
MIT
|