Skip to content

Releases: hypercerts-org/hypercerts-lexicon

v0.11.2

09 Apr 15:15
7016442

Choose a tag to compare

Patch Changes

  • #205 4af4e8b Thanks @s-adamantine! - Sync vendored pub.leaflet.blocks.image lexicon with upstream, adding the optional fullBleed boolean property

v0.11.1

08 Apr 16:57
5a37ede

Choose a tag to compare

Patch Changes

  • #196 e66a459 Thanks @aspiers! - Fix incorrect NSID reference in org.hyperboards.board subject field description (org.hypercerts.claim.collectionorg.hypercerts.collection).

    Documentation fixes in README.md and SCHEMAS.md:

    • Correct validate() call signature examples (parameter order and result shape)
    • Fix relationship diagram arrow directions and missing entries (link/evm, CERTIFIED section)
    • Fix contributor field name (avatarimage)
    • Fix context target descriptions (generalized to any record since subjects use generic strongRef)
    • Add missing $type discriminators to union member examples

v0.11.0

07 Apr 22:28
f7bacd7

Choose a tag to compare

The v0.11.0 release introduces EVM identity linking, stronger type safety across badge and funding schemas, vendored Leaflet lexicons for runtime validation, and a set of schema refinements based on real-world usage from the first month of v0.10.0 adoption. All changes listed below are merged to main and will ship together as a single coordinated release.

npm install @hypercerts-org/lexicon@0.11.0

New lexicons

EVM identity linking

app.certified.link.evm

A new record type for creating verifiable links between ATProto identities and EVM wallet addresses. Each record contains a cryptographic proof — currently EIP-712 typed data signatures for EOA wallets — that binds a DID to an Ethereum address onchain.

The proof field is an open union, so future signature methods (ERC-1271, ERC-6492) can be added without breaking existing records.

{
  "address": "0xAb5801a7D398351b8bE11C439e05C5B3259aeC9B",
  "proof": {
    "$type": "app.certified.link.evm#eip712Proof",
    "signature": "0x...",
    "message": {
      "did": "did:plc:abc123",
      "evmAddress": "0xAb5801a7D398351b8bE11C439e05C5B3259aeC9B",
      "chainId": "1",
      "timestamp": "1711929600",
      "nonce": "0",
    },
  },
  "createdAt": "2026-04-03T00:00:00.000Z",
}

Vendored Leaflet and richtext lexicons

pub.leaflet.* · pub.leaflet.richtext.facet

The package now ships the full set of Leaflet block and richtext facet lexicon JSON files (17 files). Previously, these external schemas were shimmed at the TypeScript type level via @atcute packages, which caused LexiconDefNotFoundError at runtime when validating records with description or facet fields. Vendoring them fixes runtime validation and removes the @atcute/leaflet and @atcute/bluesky dependencies.

This is a packaging change, not a schema change. No record structures are affected.


Breaking changes

This release includes three breaking schema changes. All were identified early enough in adoption that the team decided the long-term gains outweigh the migration cost.

Evaluation scores are now strings

org.hypercerts.context.evaluation

The min, max, and value fields on evaluation scores changed from integer to string. ATProto has no native decimal type, and integer-only scores made use cases like "3.7 out of 5" impossible.

  // Before
- { "min": 0, "max": 10, "value": 7 }
+ // After
+ { "min": "0", "max": "10", "value": "7.5" }

Who needs to update:

Consumer Action
Indexers Change column type from INTEGER to TEXT. Backfill existing records. Update any numeric sorting or filtering logic.
AppViews Parse scores as strings. Use parseFloat() for numeric display where appropriate.
Frontend Handle both numeric strings ("3.7") and potentially non-numeric strings ("A+") in display components.

Badge references are now strong refs

app.certified.badge.award · app.certified.badge.response

Badge awards and responses now reference their parent records via com.atproto.repo.strongRef instead of plain lexicon refs. Strong references include both a URI and a content hash (CID), pinning the reference to a specific version of the badge definition. This prevents the meaning of an award from drifting if the underlying badge definition is later modified.

  // Before
- "badge": "at://did:plc:abc/app.certified.badge.definition/123"

  // After
+ "badge": {
+   "uri": "at://did:plc:abc/app.certified.badge.definition/123",
+   "cid": "bafyrei..."
+ }

Who needs to update:

Consumer Action
Indexers Update parsing to expect { uri, cid } objects instead of plain URI strings for badge and badgeAward fields.
AppViews Update resolution logic. Dereference using both uri and cid for content verification.
SDK consumers Regenerate types. Any code constructing badge awards or responses must supply the full strong ref.

Funding receipt fields normalized

org.hypercerts.funding.receipt

The from, to, and for fields have been reworked for consistency and stronger type safety.

Field Before (v0.10.0) After
from Required, DID ref Optional, union of #text | app.certified.defs#did | com.atproto.repo.strongRef
to Plain string Union of #text | app.certified.defs#did | com.atproto.repo.strongRef
for AT-URI string com.atproto.repo.strongRef (pins to a specific record version)

The from and to fields were asymmetric — from required an AT Protocol identity while to accepted any string. Now both are three-way unions that accept a free-text string (#text — for display names, wallet addresses, or other identifiers), a DID, or a strong reference. This treats senders and recipients uniformly while preserving the ability to reference non-ATProto participants. from is also optional, properly supporting anonymous funding. for is now a strong ref, ensuring the receipt always points to the exact version of the activity it funded.

  // Before
- "from": { "$type": "app.certified.defs#did", "did": "did:plc:sender" },
- "to": "did:plc:recipient",
- "for": "at://did:plc:abc/org.hypercerts.claim.activity/123"

  // After — with a DID
+ "from": { "$type": "app.certified.defs#did", "did": "did:plc:sender" },
+ "to": { "$type": "app.certified.defs#did", "did": "did:plc:recipient" },

  // After — with a free-text identifier
+ "to": { "$type": "org.hypercerts.funding.receipt#text", "value": "0xAb58...eC9B" },

  // After — for field
+ "for": {
+   "uri": "at://did:plc:abc/org.hypercerts.claim.activity/123",
+   "cid": "bafyrei..."
+ }

Who needs to update:

Consumer Action
Indexers Update parsing for from, to (now unions with $type discriminator — handle all three variants), and for (now { uri, cid }). Allow NULL for from.
AppViews Update resolution logic for all three fields. for requires dereferencing via both URI and CID. Handle #text variants for display.
SDK consumers Regenerate types. Code constructing receipts must supply union-typed to and strong ref for.
Frontend Update forms to construct proper union objects for sender/recipient. Handle #text for non-ATProto participants. Handle missing from for anonymous display.

Schema changes

A note on "optional" fields: Even new optional fields require attention from indexers and AppViews. If an indexer doesn't store a new field, that data is silently lost for every downstream consumer. The changes below are non-breaking in the strict sense — existing records remain valid — but ignoring them means incomplete data.

Known values

Several free-text string fields now declare knownValues — a set of canonical values that establish interoperability conventions across the ecosystem. Custom values are still permitted. Think of these as Schelling points, not constraints.

Lexicon Field Known values
org.hypercerts.collection type favorites · project · portfolio · program
org.hypercerts.context.attachment contentType report · audit · evidence · testimonial · methodology
app.certified.badge.definition badgeType endorsement · verification · participation · certification · affiliation · recognition

Action: Indexers should index these values for filtering and categorization. AppViews and frontends can use them for dropdowns, search facets, and display grouping. No schema migration required — the underlying field type is still a string.

Badge icon is now optional

app.certified.badge.definition

The icon field moved from required to optional. Not all badges have a visual representation — endorsements, participation records, and text-based certifications can now omit the icon entirely.

Action: Indexers should allow NULL in the icon column. Frontend developers must add a fallback or placeholder when rendering badges without an icon — apps that assume icon is always present will crash or render broken UI.

Contributors array is uncapped

org.hypercerts.claim.activity

Removed the maxLength: 1000 constraint on the contributors array. ATProto records have a natural 1 MB size limit (~2,000–...

Read more

v0.10.0

03 Mar 20:20
82ee279

Choose a tag to compare

Minor Changes

  • #76 3044e22 Thanks @s-adamantine! - Add org.hypercerts.acknowledgement lexicon for bidirectional inclusion links between records across PDS repos

  • #141 06fb6b5 Thanks @holkexyz! - Add CEL expression support for structured work scopes (org.hypercerts.workscope.cel, org.hypercerts.workscope.tag)

  • #106 b03a1f7 Thanks @copilot-swe-agent! - Add avatar and banner fields to collection lexicon for visual representation

  • #113 c3f9ca2 Thanks @holkexyz! - Refactor collection items structure to support optional weights and remove activityWeight from activity schema

    Breaking Changes:

    • Activity lexicon (org.hypercerts.claim.activity):
      • Removed org.hypercerts.claim.activity#activityWeight def
      • Activity records no longer include activity weight information
    • Collection lexicon (org.hypercerts.claim.collection):
      • Changed org.hypercerts.claim.collection#items from array of strongRefs to array of item objects
      • Added org.hypercerts.claim.collection#item def with:
        • itemIdentifier (required): strongRef to an item (activity or collection)
        • itemWeight (optional): positive numeric value stored as string
      • Supports recursive collection nesting (items can reference activities or other collections)

    Migration:

    Collection items: Convert from array of strongRefs to array of item objects:

    // Before
    "items": [strongRef1, strongRef2]
    
    // After
    "items": [
      { "itemIdentifier": strongRef1, "itemWeight": "1.5" },
      { "itemIdentifier": strongRef2 }
    ]

    Activity weights: Migrate existing org.hypercerts.claim.activity#activityWeight data to collection org.hypercerts.claim.collection#item.itemWeight:

    // Old (removed from activity)
    { "activity": { "uri": "...", "cid": "..." }, "weight": "1.5" }
    
    // New (in collection items)
    { "itemIdentifier": { "uri": "...", "cid": "..." }, "itemWeight": "1.5" }

    Update collections that reference activities to include weights in org.hypercerts.claim.collection#item.itemWeight. Weights can be dropped if not needed.

  • #149 9f124eb Thanks @daviddao! - Add org.hyperboards.board and org.hyperboards.displayProfile lexicons for hyperboard visual presentation records.

  • #123 c623d32 Thanks @aspiers! - Add location property to collections. Collections can now reference a location record directly via strongRef. This replaces the sidecar pattern which was impractical since location records cannot be reused across multiple collections.

  • #140 20eb414 Thanks @holkexyz! - Add app.certified.actor.organization sidecar record for organization actor profiles with fields for organization type, labeled URLs, location (strongRef), and founded date

  • #133 6752cad Thanks @Kzoeps! - Add profile lexicon for Hypercert account profiles with support for display name, description, pronouns, website, avatar, banner.

  • #78 c55d8a7 Thanks @bitbeckers! - Remove org.hypercerts.claim.project lexicon and replace with org.hypercerts.claim.collection.project sidecar. Projects are now represented as collections with an optional project sidecar (same TID) that provides rich-text descriptions, avatars, and cover photos. Avatar and coverPhoto fields moved from base collection to project sidecar. Collections without the project sidecar are simple groupings; collections with it are "projects" with rich documentation.

  • #91 0c6da09 Thanks @holkexyz! - Add rich text facet support to activity claim descriptions

    Add shortDescriptionFacets and descriptionFacets fields to the activity lexicon to support rich text annotations (mentions, URLs, hashtags, etc.) in activity claim descriptions.

  • #144 fb90134 Thanks @holkexyz! - Make items optional in collection schema to allow creating empty collections

  • #151 4d5f42f Thanks @holkexyz! - Add optional url field to app.certified.badge.award for linking to an external page associated with the badge

  • #122 3e3da41 Thanks @aspiers! - Drop HELPER_ prefix from workScopeTag constants. HELPER_WORK_SCOPE_TAG_NSID, HELPER_WORK_SCOPE_TAG_LEXICON_JSON, and HELPER_WORK_SCOPE_TAG_LEXICON_DOC are now WORK_SCOPE_TAG_NSID, WORK_SCOPE_TAG_LEXICON_JSON, and WORK_SCOPE_TAG_LEXICON_DOC.

  • #136 062fbde Thanks @copilot-swe-agent! - Expand locationType knownValues to include geojson, h3, geohash, wkt, address, and scaledCoordinates from the Location Protocol spec

  • #131 7f42fad Thanks @aspiers! - Add inline string format to app.certified.location schema with documentation and examples

  • #121 5c33b79 Thanks @aspiers! - Fix camelCase export names to use underscores. Generated constants like CONTRIBUTIONDETAILS_LEXICON_* are now CONTRIBUTION_DETAILS_LEXICON_* for consistency.

    Affected exports:

    • CONTRIBUTION_DETAILS_NSID, CONTRIBUTION_DETAILS_LEXICON_JSON, CONTRIBUTION_DETAILS_LEXICON_DOC (was CONTRIBUTIONDETAILS_*)
    • CONTRIBUTOR_INFORMATION_NSID, CONTRIBUTOR_INFORMATION_LEXICON_JSON, CONTRIBUTOR_INFORMATION_LEXICON_DOC (was CONTRIBUTORINFORMATION_*)
    • STRONG_REF_NSID, STRONG_REF_LEXICON_JSON, STRONG_REF_LEXICON_DOC (was STRONGREF_*)
    • HELPER_WORK_SCOPE_TAG_NSID, HELPER_WORK_SCOPE_TAG_LEXICON_JSON, HELPER_WORK_SCOPE_TAG_LEXICON_DOC (was HELPER_WORKSCOPETAG_*)
  • #132 da481e0 Thanks @aspiers! - Convert app.certified.defs#did to object type

    The did definition in app.certified.defs has been converted from a primitive
    string type to an object type to comply with the ATProto specification
    requirement that all union variants must be object or record types.

    This change was necessary because app.certified.badge.award uses this
    definition in a union for the subject property.

    Breaking changes:

    • app.certified.defs#did: Now an object with did string property (maxLength 256)
    • Code using this type must now access the .did property instead of using the value directly
  • #132 e134b26 Thanks @aspiers! - Convert union string definitions to object types in activity lexicon

    The contributorIdentity, contributorRole, an...

Read more