Skip to content

SDK lexicon diverges from canonical: 3 activity sub-types are objects but should be strings #140

@daviddao

Description

@daviddao

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

  1. Which is the source of truth — the SDK's activity.json or the Hyperscan canonical definition?
  2. If the object wrapper is intentional (for ATProto union discrimination), should the canonical docs be updated to match?
  3. 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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions