@hypercerts-org/lexicon 0.10.0-beta.8 → 0.10.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.
Files changed (147) hide show
  1. package/CHANGELOG.md +714 -0
  2. package/README.md +278 -9
  3. package/SCHEMAS.md +440 -143
  4. package/dist/exports.d.ts +837 -304
  5. package/dist/exports.d.ts.map +1 -1
  6. package/dist/generated/exports.d.ts +837 -304
  7. package/dist/generated/exports.d.ts.map +1 -1
  8. package/dist/generated/lexicons.d.ts +1631 -625
  9. package/dist/generated/lexicons.d.ts.map +1 -1
  10. package/dist/generated/types/app/certified/actor/organization.d.ts +32 -0
  11. package/dist/generated/types/app/certified/actor/organization.d.ts.map +1 -0
  12. package/dist/generated/types/app/certified/actor/profile.d.ts +30 -0
  13. package/dist/generated/types/app/certified/actor/profile.d.ts.map +1 -0
  14. package/dist/generated/types/app/certified/badge/award.d.ts +2 -0
  15. package/dist/generated/types/app/certified/badge/award.d.ts.map +1 -1
  16. package/dist/generated/types/app/certified/badge/response.d.ts +1 -1
  17. package/dist/generated/types/app/certified/badge/response.d.ts.map +1 -1
  18. package/dist/generated/types/app/certified/defs.d.ts +11 -1
  19. package/dist/generated/types/app/certified/defs.d.ts.map +1 -1
  20. package/dist/generated/types/app/certified/location.d.ts +13 -5
  21. package/dist/generated/types/app/certified/location.d.ts.map +1 -1
  22. package/dist/generated/types/org/hyperboards/board.d.ts +75 -0
  23. package/dist/generated/types/org/hyperboards/board.d.ts.map +1 -0
  24. package/dist/generated/types/org/hyperboards/displayProfile.d.ts +31 -0
  25. package/dist/generated/types/org/hyperboards/displayProfile.d.ts.map +1 -0
  26. package/dist/generated/types/org/hypercerts/claim/activity.d.ts +30 -11
  27. package/dist/generated/types/org/hypercerts/claim/activity.d.ts.map +1 -1
  28. package/dist/generated/types/org/hypercerts/claim/{contributionDetails.d.ts → contribution.d.ts} +6 -6
  29. package/dist/generated/types/org/hypercerts/claim/contribution.d.ts.map +1 -0
  30. package/dist/generated/types/org/hypercerts/claim/contributorInformation.d.ts +2 -2
  31. package/dist/generated/types/org/hypercerts/claim/contributorInformation.d.ts.map +1 -1
  32. package/dist/generated/types/org/hypercerts/claim/rights.d.ts +3 -3
  33. package/dist/generated/types/org/hypercerts/claim/rights.d.ts.map +1 -1
  34. package/dist/generated/types/org/hypercerts/{claim/collection.d.ts → collection.d.ts} +11 -10
  35. package/dist/generated/types/org/hypercerts/collection.d.ts.map +1 -0
  36. package/dist/generated/types/org/hypercerts/context/acknowledgement.d.ts +25 -0
  37. package/dist/generated/types/org/hypercerts/context/acknowledgement.d.ts.map +1 -0
  38. package/dist/generated/types/org/hypercerts/context/attachment.d.ts +35 -0
  39. package/dist/generated/types/org/hypercerts/context/attachment.d.ts.map +1 -0
  40. package/dist/{types/org/hypercerts/claim → generated/types/org/hypercerts/context}/evaluation.d.ts +15 -15
  41. package/dist/generated/types/org/hypercerts/context/evaluation.d.ts.map +1 -0
  42. package/dist/generated/types/org/hypercerts/context/measurement.d.ts +43 -0
  43. package/dist/generated/types/org/hypercerts/context/measurement.d.ts.map +1 -0
  44. package/dist/generated/types/org/hypercerts/defs.d.ts +8 -44
  45. package/dist/generated/types/org/hypercerts/defs.d.ts.map +1 -1
  46. package/dist/generated/types/org/hypercerts/funding/receipt.d.ts +1 -1
  47. package/dist/generated/types/org/hypercerts/funding/receipt.d.ts.map +1 -1
  48. package/dist/generated/types/org/hypercerts/workscope/cel.d.ts +20 -0
  49. package/dist/generated/types/org/hypercerts/workscope/cel.d.ts.map +1 -0
  50. package/dist/generated/types/org/hypercerts/workscope/tag.d.ts +36 -0
  51. package/dist/generated/types/org/hypercerts/workscope/tag.d.ts.map +1 -0
  52. package/dist/index.cjs +2570 -1235
  53. package/dist/index.cjs.map +1 -1
  54. package/dist/index.mjs +2512 -1201
  55. package/dist/index.mjs.map +1 -1
  56. package/dist/lexicons.cjs +932 -397
  57. package/dist/lexicons.cjs.map +1 -1
  58. package/dist/lexicons.d.ts +1631 -625
  59. package/dist/lexicons.d.ts.map +1 -1
  60. package/dist/lexicons.mjs +932 -397
  61. package/dist/lexicons.mjs.map +1 -1
  62. package/dist/types/app/certified/actor/organization.d.ts +32 -0
  63. package/dist/types/app/certified/actor/organization.d.ts.map +1 -0
  64. package/dist/types/app/certified/actor/profile.d.ts +30 -0
  65. package/dist/types/app/certified/actor/profile.d.ts.map +1 -0
  66. package/dist/types/app/certified/badge/award.d.ts +2 -0
  67. package/dist/types/app/certified/badge/award.d.ts.map +1 -1
  68. package/dist/types/app/certified/badge/response.d.ts +1 -1
  69. package/dist/types/app/certified/badge/response.d.ts.map +1 -1
  70. package/dist/types/app/certified/defs.d.ts +11 -1
  71. package/dist/types/app/certified/defs.d.ts.map +1 -1
  72. package/dist/types/app/certified/location.d.ts +13 -5
  73. package/dist/types/app/certified/location.d.ts.map +1 -1
  74. package/dist/types/org/hyperboards/board.d.ts +75 -0
  75. package/dist/types/org/hyperboards/board.d.ts.map +1 -0
  76. package/dist/types/org/hyperboards/displayProfile.d.ts +31 -0
  77. package/dist/types/org/hyperboards/displayProfile.d.ts.map +1 -0
  78. package/dist/types/org/hypercerts/claim/activity.d.ts +30 -11
  79. package/dist/types/org/hypercerts/claim/activity.d.ts.map +1 -1
  80. package/dist/types/org/hypercerts/claim/{contributionDetails.d.ts → contribution.d.ts} +6 -6
  81. package/dist/types/org/hypercerts/claim/contribution.d.ts.map +1 -0
  82. package/dist/types/org/hypercerts/claim/contributorInformation.d.ts +2 -2
  83. package/dist/types/org/hypercerts/claim/contributorInformation.d.ts.map +1 -1
  84. package/dist/types/org/hypercerts/claim/rights.d.ts +3 -3
  85. package/dist/types/org/hypercerts/claim/rights.d.ts.map +1 -1
  86. package/dist/types/org/hypercerts/{claim/collection.d.ts → collection.d.ts} +11 -10
  87. package/dist/types/org/hypercerts/collection.d.ts.map +1 -0
  88. package/dist/types/org/hypercerts/context/acknowledgement.d.ts +25 -0
  89. package/dist/types/org/hypercerts/context/acknowledgement.d.ts.map +1 -0
  90. package/dist/types/org/hypercerts/context/attachment.d.ts +35 -0
  91. package/dist/types/org/hypercerts/context/attachment.d.ts.map +1 -0
  92. package/dist/{generated/types/org/hypercerts/claim → types/org/hypercerts/context}/evaluation.d.ts +15 -15
  93. package/dist/types/org/hypercerts/context/evaluation.d.ts.map +1 -0
  94. package/dist/types/org/hypercerts/context/measurement.d.ts +43 -0
  95. package/dist/types/org/hypercerts/context/measurement.d.ts.map +1 -0
  96. package/dist/types/org/hypercerts/defs.d.ts +8 -44
  97. package/dist/types/org/hypercerts/defs.d.ts.map +1 -1
  98. package/dist/types/org/hypercerts/funding/receipt.d.ts +1 -1
  99. package/dist/types/org/hypercerts/funding/receipt.d.ts.map +1 -1
  100. package/dist/types/org/hypercerts/workscope/cel.d.ts +20 -0
  101. package/dist/types/org/hypercerts/workscope/cel.d.ts.map +1 -0
  102. package/dist/types/org/hypercerts/workscope/tag.d.ts +36 -0
  103. package/dist/types/org/hypercerts/workscope/tag.d.ts.map +1 -0
  104. package/lexicons/app/certified/actor/organization.json +70 -0
  105. package/lexicons/app/certified/actor/profile.json +61 -0
  106. package/lexicons/app/certified/badge/award.json +8 -1
  107. package/lexicons/app/certified/badge/definition.json +8 -3
  108. package/lexicons/app/certified/badge/response.json +3 -2
  109. package/lexicons/app/certified/defs.json +11 -3
  110. package/lexicons/app/certified/location.json +29 -6
  111. package/lexicons/org/hyperboards/board.json +152 -0
  112. package/lexicons/org/hyperboards/displayProfile.json +64 -0
  113. package/lexicons/org/hypercerts/claim/activity.json +57 -39
  114. package/lexicons/org/hypercerts/claim/{contributionDetails.json → contribution.json} +4 -4
  115. package/lexicons/org/hypercerts/claim/contributorInformation.json +3 -2
  116. package/lexicons/org/hypercerts/claim/rights.json +5 -3
  117. package/lexicons/org/hypercerts/{claim/collection.json → collection.json} +15 -7
  118. package/lexicons/org/hypercerts/context/acknowledgement.json +42 -0
  119. package/lexicons/org/hypercerts/context/attachment.json +77 -0
  120. package/lexicons/org/hypercerts/{claim → context}/evaluation.json +22 -22
  121. package/lexicons/org/hypercerts/context/measurement.json +107 -0
  122. package/lexicons/org/hypercerts/defs.json +14 -89
  123. package/lexicons/org/hypercerts/funding/receipt.json +12 -6
  124. package/lexicons/org/hypercerts/workscope/cel.json +39 -0
  125. package/lexicons/org/hypercerts/workscope/tag.json +87 -0
  126. package/package.json +2 -2
  127. package/dist/generated/types/org/hypercerts/claim/collection.d.ts.map +0 -1
  128. package/dist/generated/types/org/hypercerts/claim/contributionDetails.d.ts.map +0 -1
  129. package/dist/generated/types/org/hypercerts/claim/evaluation.d.ts.map +0 -1
  130. package/dist/generated/types/org/hypercerts/claim/evidence.d.ts +0 -29
  131. package/dist/generated/types/org/hypercerts/claim/evidence.d.ts.map +0 -1
  132. package/dist/generated/types/org/hypercerts/claim/measurement.d.ts +0 -30
  133. package/dist/generated/types/org/hypercerts/claim/measurement.d.ts.map +0 -1
  134. package/dist/generated/types/org/hypercerts/helper/workScopeTag.d.ts +0 -31
  135. package/dist/generated/types/org/hypercerts/helper/workScopeTag.d.ts.map +0 -1
  136. package/dist/types/org/hypercerts/claim/collection.d.ts.map +0 -1
  137. package/dist/types/org/hypercerts/claim/contributionDetails.d.ts.map +0 -1
  138. package/dist/types/org/hypercerts/claim/evaluation.d.ts.map +0 -1
  139. package/dist/types/org/hypercerts/claim/evidence.d.ts +0 -29
  140. package/dist/types/org/hypercerts/claim/evidence.d.ts.map +0 -1
  141. package/dist/types/org/hypercerts/claim/measurement.d.ts +0 -30
  142. package/dist/types/org/hypercerts/claim/measurement.d.ts.map +0 -1
  143. package/dist/types/org/hypercerts/helper/workScopeTag.d.ts +0 -31
  144. package/dist/types/org/hypercerts/helper/workScopeTag.d.ts.map +0 -1
  145. package/lexicons/org/hypercerts/claim/evidence.json +0 -57
  146. package/lexicons/org/hypercerts/claim/measurement.json +0 -70
  147. package/lexicons/org/hypercerts/helper/workScopeTag.json +0 -65
package/README.md CHANGED
@@ -65,10 +65,27 @@ const activityRecord = {
65
65
  $type: ACTIVITY_NSID,
66
66
  title: "My Impact Work",
67
67
  shortDescription: "Description here",
68
+ // workScope can be a CEL expression (structured, machine-evaluable):
68
69
  workScope: {
69
- uri: "at://did:plc:alice/org.hypercerts.claim.workscope/abc123",
70
- cid: "...",
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(),
71
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" },
72
89
  startDate: "2023-01-01T00:00:00Z",
73
90
  endDate: "2023-12-31T23:59:59Z",
74
91
  createdAt: new Date().toISOString(),
@@ -87,6 +104,95 @@ await agent.api.com.atproto.repo.createRecord({
87
104
  });
88
105
  ```
89
106
 
107
+ ### Creating Location Records
108
+
109
+ Location records (`app.certified.location`) specify where work was performed
110
+ using geographic coordinates or other location formats. They can be referenced
111
+ by activities, collections, attachments, measurements, and evaluations.
112
+
113
+ ```typescript
114
+ import { LOCATION_NSID } from "@hypercerts-org/lexicon";
115
+
116
+ const locationRecord = {
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
+ ```
130
+
131
+ - `lpVersion` (required): Version of the Location Protocol specification
132
+ - `srs` (required): Spatial Reference System URI defining the coordinate system
133
+ - `locationType` (required): Format identifier (e.g., "coordinate-decimal", "geojson-point", "geojson", "h3", "geohash", "wkt", "address", "scaledCoordinates"). See the [Location Protocol spec](https://spec.decentralizedgeo.org/specification/location-types/#location-type-registry) for the full registry.
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
138
+
139
+ **Location data formats:**
140
+
141
+ The `location` field accepts three formats:
142
+
143
+ 1. **URI reference**: `{ uri: "https://..." }` - Link to external location data
144
+ 2. **Small blob**: Embedded location data (up to 10MB)
145
+ 3. **Location string**: Inline string wrapped in an object, containing coordinates or GeoJSON
146
+
147
+ ```typescript
148
+ // Example with embedded blob
149
+ const locationWithBlob = {
150
+ $type: LOCATION_NSID,
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
+ };
167
+
168
+ // Example with inline string (coordinates)
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
+ };
181
+
182
+ // Example with inline GeoJSON string
183
+ const locationWithGeoJSON = {
184
+ $type: LOCATION_NSID,
185
+ lpVersion: "1.0",
186
+ srs: "http://www.opengis.net/def/crs/OGC/1.3/CRS84",
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
+ ```
195
+
90
196
  ### Accessing NSIDs (Lexicon IDs)
91
197
 
92
198
  **Recommended**: Use individual NSID constants for cleaner, more readable code:
@@ -119,7 +225,7 @@ import { HYPERCERTS_NSIDS_BY_TYPE } from "@hypercerts-org/lexicon";
119
225
 
120
226
  // Access via type namespace names
121
227
  const activityId = HYPERCERTS_NSIDS_BY_TYPE.OrgHypercertsClaimActivity;
122
- const collectionId = HYPERCERTS_NSIDS_BY_TYPE.OrgHypercertsClaimCollection;
228
+ const collectionId = HYPERCERTS_NSIDS_BY_TYPE.OrgHypercertsCollection;
123
229
  ```
124
230
 
125
231
  **Lightweight Bundle**: Import from `/lexicons` for runtime validation without TypeScript types (smaller bundle size):
@@ -191,13 +297,36 @@ property tables, see [SCHEMAS.md](SCHEMAS.md).
191
297
 
192
298
  ## Examples
193
299
 
194
- ### Creating a Collection with Nested Items
300
+ ### Collections
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
195
324
 
196
325
  ```typescript
197
326
  import { TID } from "@atproto/common";
198
327
 
199
328
  const collectionRecord = {
200
- $type: "org.hypercerts.claim.collection",
329
+ $type: "org.hypercerts.collection",
201
330
  title: "Climate Action Projects",
202
331
  shortDescription:
203
332
  "A collection of climate-related activities and sub-collections",
@@ -214,7 +343,7 @@ const collectionRecord = {
214
343
  },
215
344
  // Reference to another collection (recursive!)
216
345
  {
217
- uri: "at://did:plc:carol/org.hypercerts.claim.collection/4m5ghi",
346
+ uri: "at://did:plc:carol/org.hypercerts.collection/4m5ghi",
218
347
  cid: "...",
219
348
  },
220
349
  ],
@@ -229,7 +358,7 @@ include rich-text descriptions:
229
358
 
230
359
  ```typescript
231
360
  const projectRecord = {
232
- $type: "org.hypercerts.claim.collection",
361
+ $type: "org.hypercerts.collection",
233
362
  type: "project",
234
363
  title: "Carbon Offset Initiative",
235
364
  shortDescription: "A project focused on carbon reduction and reforestation",
@@ -282,6 +411,73 @@ const collectionRecord = {
282
411
  are optional and support either embedded image blobs or URI references to
283
412
  external images.
284
413
 
414
+ ### Acknowledging Inclusion
415
+
416
+ The `org.hypercerts.context.acknowledgement` record enables bidirectional
417
+ linking between records that live in different PDS repositories. When
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:
434
+
435
+ ```typescript
436
+ import { ACKNOWLEDGEMENT_NSID } from "@hypercerts-org/lexicon";
437
+
438
+ // Bob acknowledges that his activity is included in Alice's collection
439
+ const ack = {
440
+ $type: ACKNOWLEDGEMENT_NSID,
441
+ subject: {
442
+ uri: "at://did:plc:bob/org.hypercerts.claim.activity/3k2abc",
443
+ cid: "bafy...",
444
+ },
445
+ context: {
446
+ uri: "at://did:plc:alice/org.hypercerts.collection/7x9def",
447
+ cid: "bafy...",
448
+ },
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
+
285
481
  ### Adding Locations to Activities
286
482
 
287
483
  The `locations` field in activity records is an array of strong references
@@ -298,5 +494,78 @@ Each strong reference contains two required fields:
298
494
  - The `uri` field must be a valid ATProto URI pointing to an existing location record
299
495
  - The `cid` field must match the current CID of the referenced location record
300
496
  - The `locations` field is optional; activities can be created without location data
301
- - When using the sidecar pattern (same TID), ensure the location record is created
302
- or updated alongside the activity record for consistency
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
+ ],
514
+ createdAt: new Date().toISOString(),
515
+ };
516
+ ```
517
+
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
+ ### Creating Attachments
521
+
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
+ ```typescript
527
+ import { ATTACHMENT_NSID } from "@hypercerts-org/lexicon";
528
+
529
+ const attachmentRecord = {
530
+ $type: ATTACHMENT_NSID,
531
+ title: "Field Survey Report",
532
+ subjects: [
533
+ {
534
+ uri: "at://did:plc:alice/org.hypercerts.claim.activity/abc123",
535
+ cid: "...",
536
+ },
537
+ ],
538
+ contentType: "report",
539
+ content: [
540
+ { uri: "https://example.com/reports/survey-2024.pdf" },
541
+ { uri: "ipfs://Qm..." },
542
+ ],
543
+ shortDescription: "Quarterly field survey documenting project progress",
544
+ createdAt: new Date().toISOString(),
545
+ };
546
+ ```
547
+
548
+ **Key fields:**
549
+
550
+ - `title` (required): String title for the attachment
551
+ - `shortDescription`/`description`: Support rich text via facet annotations
552
+ - `subjects` (optional): Array of strong references to records this attachment relates to
553
+ - `contentType` (optional): Type descriptor (e.g., "report", "audit", "evidence", "testimonial")
554
+ - `content` (required): Array of URIs or blobs containing the attachment files
555
+ - `location` (optional): Strong reference to an `app.certified.location` record
556
+ - `createdAt` (required): Timestamp when the attachment was created
557
+
558
+ **Adding Location to Attachments:**
559
+
560
+ ```typescript
561
+ const attachmentWithLocation = {
562
+ $type: ATTACHMENT_NSID,
563
+ title: "Site Inspection Photos",
564
+ content: [{ uri: "https://..." }],
565
+ location: {
566
+ uri: "at://did:plc:alice/app.certified.location/loc123",
567
+ cid: "...",
568
+ },
569
+ createdAt: new Date().toISOString(),
570
+ };
571
+ ```