Summary
The SDK's @hypercerts-org/lexicon@0.10.0-beta.14 defines three sub-types in org.hypercerts.claim.activity as objects, but the canonical lexicon at hyperscan.dev/lexicon defines them as bare strings.
This causes a wire-format mismatch: records written with the SDK produce a different structure than what the canonical schema describes.
Discrepancies
1. contributorIdentity
|
SDK (activity.json) |
Canonical (hyperscan.dev) |
| Type |
object with required: ["identity"] |
string |
| Wire format |
{ "$type": "...#contributorIdentity", "identity": "did:plc:abc" } |
"did:plc:abc" |
2. contributorRole
|
SDK (activity.json) |
Canonical (hyperscan.dev) |
| Type |
object with required: ["role"] |
string |
| Wire format |
{ "$type": "...#contributorRole", "role": "engineer" } |
"engineer" |
3. workScopeString
|
SDK (activity.json) |
Canonical (hyperscan.dev) |
| Type |
object with required: ["scope"] |
string |
| Wire format |
{ "$type": "...#workScopeString", "scope": "reforestation" } |
"reforestation" |
Context
These sub-types are used inside union fields on the contributor and main record objects:
contributor.contributorIdentity: union of [#contributorIdentity, com.atproto.repo.strongRef]
contributor.contributionDetails: union of [#contributorRole, com.atproto.repo.strongRef]
workScope: union of [com.atproto.repo.strongRef, #workScopeString]
ATProto unions require $type discrimination, so wrapping strings in objects may be intentional for union compatibility. However, the canonical lexicon on Hyperscan explicitly declares these as type: "string", not objects.
Impact
- The Hyperindex at
api.hi.gainforest.app/graphql stores these fields as opaque JSON types, so both formats work in practice
- But any validator or consumer strictly following the canonical schema would reject SDK-produced records (or vice versa)
- Apps building against the canonical docs (e.g. via the agent-friendly lexicon reference) will produce records incompatible with the SDK's TypeScript types
Questions
- Which is the source of truth — the SDK's
activity.json or the Hyperscan canonical definition?
- If the object wrapper is intentional (for ATProto union discrimination), should the canonical docs be updated to match?
- If the bare string is correct, should the SDK's lexicon be updated and types regenerated?
Everything else matches ✅
All other org.hypercerts.* lexicons in the SDK are fully aligned with the canonical:
claim.collection — field names items/itemIdentifier/itemWeight/banner all correct
claim.attachment, claim.evaluation, claim.measurement, claim.rights — all match
claim.contributionDetails, claim.contributorInformation — all match
defs, funding.receipt, helper.workScopeTag — all match
Versions
Summary
The SDK's
@hypercerts-org/lexicon@0.10.0-beta.14defines three sub-types inorg.hypercerts.claim.activityas objects, but the canonical lexicon at hyperscan.dev/lexicon defines them as bare strings.This causes a wire-format mismatch: records written with the SDK produce a different structure than what the canonical schema describes.
Discrepancies
1.
contributorIdentityactivity.json)objectwithrequired: ["identity"]string{ "$type": "...#contributorIdentity", "identity": "did:plc:abc" }"did:plc:abc"2.
contributorRoleactivity.json)objectwithrequired: ["role"]string{ "$type": "...#contributorRole", "role": "engineer" }"engineer"3.
workScopeStringactivity.json)objectwithrequired: ["scope"]string{ "$type": "...#workScopeString", "scope": "reforestation" }"reforestation"Context
These sub-types are used inside union fields on the
contributorand main record objects:contributor.contributorIdentity: union of[#contributorIdentity, com.atproto.repo.strongRef]contributor.contributionDetails: union of[#contributorRole, com.atproto.repo.strongRef]workScope: union of[com.atproto.repo.strongRef, #workScopeString]ATProto unions require
$typediscrimination, so wrapping strings in objects may be intentional for union compatibility. However, the canonical lexicon on Hyperscan explicitly declares these astype: "string", not objects.Impact
api.hi.gainforest.app/graphqlstores these fields as opaqueJSONtypes, so both formats work in practiceQuestions
activity.jsonor the Hyperscan canonical definition?Everything else matches ✅
All other
org.hypercerts.*lexicons in the SDK are fully aligned with the canonical:claim.collection— field namesitems/itemIdentifier/itemWeight/bannerall correctclaim.attachment,claim.evaluation,claim.measurement,claim.rights— all matchclaim.contributionDetails,claim.contributorInformation— all matchdefs,funding.receipt,helper.workScopeTag— all matchVersions
@hypercerts-org/sdk-core@0.10.0-beta.8@hypercerts-org/lexicon@0.10.0-beta.14