From fb9ec4fa14313cda630e234b5cd9ecc736805574 Mon Sep 17 00:00:00 2001 From: holkexyz Date: Tue, 24 Feb 2026 10:06:15 +0100 Subject: [PATCH 1/4] feat: add org.hypercerts.claim.post lexicon Add a post record type for updates, reports, and comments on hypercerts records. Modeled after app.bsky.feed.post with hypercerts-specific extensions (multi-reply, attachments). Also adds type shims for app.bsky.embed.* and com.atproto.label.defs external lexicon references. Co-Authored-By: Claude Opus 4.6 --- .changeset/add-post-lexicon.md | 5 ++ SCHEMAS.md | 30 ++++++++++ lexicons/org/hypercerts/claim/post.json | 80 +++++++++++++++++++++++++ scripts/create-shims.sh | 56 +++++++++++++++++ 4 files changed, 171 insertions(+) create mode 100644 .changeset/add-post-lexicon.md create mode 100644 lexicons/org/hypercerts/claim/post.json diff --git a/.changeset/add-post-lexicon.md b/.changeset/add-post-lexicon.md new file mode 100644 index 00000000..da2e5814 --- /dev/null +++ b/.changeset/add-post-lexicon.md @@ -0,0 +1,5 @@ +--- +"@hypercerts-org/lexicon": minor +--- + +Add org.hypercerts.claim.post lexicon for updates, reports, and comments on hypercerts records diff --git a/SCHEMAS.md b/SCHEMAS.md index b433ccf1..8534734e 100644 --- a/SCHEMAS.md +++ b/SCHEMAS.md @@ -95,6 +95,36 @@ Hypercerts-specific lexicons for tracking impact work and claims. --- +### `org.hypercerts.claim.post` + +**Description:** Record containing a hypercerts post, e.g. an update, a report, a comment. + +**Key:** `tid` + +#### Properties + +| Property | Type | Required | Description | Comments | +| ------------- | ---------- | -------- | ----------------------------------------------------------------------------------------------------------------------- | ------------------------------------ | +| `text` | `string` | ✅ | The primary post content. May be an empty string, if there are embeds. | maxLength: 50000, maxGraphemes: 5000 | +| `facets` | `ref[]` | ❌ | Annotations of text (mentions, URLs, hashtags, etc) | | +| `replies` | `ref[]` | ❌ | The subjects that this post is in reply to. Each entry identifies a thread root and the direct parent being replied to. | maxLength: 10 | +| `embed` | `union` | ❌ | | | +| `labels` | `union` | ❌ | Self-label values for this post. Effectively content warnings. | | +| `tags` | `string[]` | ❌ | Additional hashtags, in addition to any included in post text and facets. | maxLength: 8 | +| `attachments` | `union[]` | ❌ | The files, documents, or external references attached to this post. | maxLength: 100 | +| `createdAt` | `string` | ✅ | Client-declared timestamp when this post was originally created. | | + +#### Defs + +##### `org.hypercerts.claim.post#replyRef` + +| Property | Type | Required | Description | +| -------- | ----- | -------- | ----------- | +| `root` | `ref` | ✅ | | +| `parent` | `ref` | ✅ | | + +--- + ### `org.hypercerts.claim.rights` **Description:** Describes the rights that a contributor and/or an owner has, such as whether the hypercert can be sold, transferred, and under what conditions. diff --git a/lexicons/org/hypercerts/claim/post.json b/lexicons/org/hypercerts/claim/post.json new file mode 100644 index 00000000..b4e05635 --- /dev/null +++ b/lexicons/org/hypercerts/claim/post.json @@ -0,0 +1,80 @@ +{ + "lexicon": 1, + "id": "org.hypercerts.claim.post", + "defs": { + "main": { + "type": "record", + "description": "Record containing a hypercerts post, e.g. an update, a report, a comment.", + "key": "tid", + "record": { + "type": "object", + "required": ["text", "createdAt"], + "properties": { + "text": { + "type": "string", + "maxLength": 50000, + "maxGraphemes": 5000, + "description": "The primary post content. May be an empty string, if there are embeds." + }, + "facets": { + "type": "array", + "description": "Annotations of text (mentions, URLs, hashtags, etc)", + "items": { "type": "ref", "ref": "app.bsky.richtext.facet" } + }, + "replies": { + "type": "array", + "description": "The subjects that this post is in reply to. Each entry identifies a thread root and the direct parent being replied to.", + "items": { "type": "ref", "ref": "#replyRef" }, + "maxLength": 10 + }, + "embed": { + "type": "union", + "refs": [ + "app.bsky.embed.images", + "app.bsky.embed.video", + "app.bsky.embed.external", + "app.bsky.embed.record", + "app.bsky.embed.recordWithMedia" + ] + }, + "labels": { + "type": "union", + "description": "Self-label values for this post. Effectively content warnings.", + "refs": ["com.atproto.label.defs#selfLabels"] + }, + "tags": { + "type": "array", + "description": "Additional hashtags, in addition to any included in post text and facets.", + "maxLength": 8, + "items": { "type": "string", "maxLength": 640, "maxGraphemes": 64 } + }, + "attachments": { + "type": "array", + "description": "The files, documents, or external references attached to this post.", + "items": { + "type": "union", + "refs": [ + "org.hypercerts.defs#uri", + "org.hypercerts.defs#smallBlob" + ] + }, + "maxLength": 100 + }, + "createdAt": { + "type": "string", + "format": "datetime", + "description": "Client-declared timestamp when this post was originally created." + } + } + } + }, + "replyRef": { + "type": "object", + "required": ["root", "parent"], + "properties": { + "root": { "type": "ref", "ref": "com.atproto.repo.strongRef" }, + "parent": { "type": "ref", "ref": "com.atproto.repo.strongRef" } + } + } + } +} diff --git a/scripts/create-shims.sh b/scripts/create-shims.sh index 265666d7..412b6880 100755 --- a/scripts/create-shims.sh +++ b/scripts/create-shims.sh @@ -23,4 +23,60 @@ export type Mention = AppBskyRichtextFacet.Mention; export type Tag = AppBskyRichtextFacet.Tag; EOF +# app.bsky.embed.* - Bluesky embed types +mkdir -p ./generated/types/app/bsky/embed +cat >./generated/types/app/bsky/embed/images.ts <<'EOF' +// Type shim for app.bsky.embed.images lexicon +import type { AppBskyEmbedImages } from '@atcute/bluesky'; +export type Main = AppBskyEmbedImages.Main; +export type Image = AppBskyEmbedImages.Image; +export type View = AppBskyEmbedImages.View; +export type ViewImage = AppBskyEmbedImages.ViewImage; +EOF + +cat >./generated/types/app/bsky/embed/video.ts <<'EOF' +// Type shim for app.bsky.embed.video lexicon +import type { AppBskyEmbedVideo } from '@atcute/bluesky'; +export type Main = AppBskyEmbedVideo.Main; +export type Caption = AppBskyEmbedVideo.Caption; +export type View = AppBskyEmbedVideo.View; +EOF + +cat >./generated/types/app/bsky/embed/external.ts <<'EOF' +// Type shim for app.bsky.embed.external lexicon +import type { AppBskyEmbedExternal } from '@atcute/bluesky'; +export type Main = AppBskyEmbedExternal.Main; +export type External = AppBskyEmbedExternal.External; +export type View = AppBskyEmbedExternal.View; +export type ViewExternal = AppBskyEmbedExternal.ViewExternal; +EOF + +cat >./generated/types/app/bsky/embed/record.ts <<'EOF' +// Type shim for app.bsky.embed.record lexicon +import type { AppBskyEmbedRecord } from '@atcute/bluesky'; +export type Main = AppBskyEmbedRecord.Main; +export type View = AppBskyEmbedRecord.View; +export type ViewBlocked = AppBskyEmbedRecord.ViewBlocked; +export type ViewDetached = AppBskyEmbedRecord.ViewDetached; +export type ViewNotFound = AppBskyEmbedRecord.ViewNotFound; +export type ViewRecord = AppBskyEmbedRecord.ViewRecord; +EOF + +cat >./generated/types/app/bsky/embed/recordWithMedia.ts <<'EOF' +// Type shim for app.bsky.embed.recordWithMedia lexicon +import type { AppBskyEmbedRecordWithMedia } from '@atcute/bluesky'; +export type Main = AppBskyEmbedRecordWithMedia.Main; +export type View = AppBskyEmbedRecordWithMedia.View; +EOF + +# com.atproto.label.defs - ATProto label types +mkdir -p ./generated/types/com/atproto/label +cat >./generated/types/com/atproto/label/defs.ts <<'EOF' +// Type shim for com.atproto.label.defs lexicon +import type { ComAtprotoLabelDefs } from '@atcute/atproto'; +export type SelfLabels = ComAtprotoLabelDefs.SelfLabels; +export type SelfLabel = ComAtprotoLabelDefs.SelfLabel; +export type Label = ComAtprotoLabelDefs.Label; +EOF + echo "Created type shims for external lexicons" From 921051afff87f5a636f8dc71671d219d1abfa111 Mon Sep 17 00:00:00 2001 From: holkexyz Date: Tue, 24 Feb 2026 10:25:15 +0100 Subject: [PATCH 2/4] address CodeRabbit review feedback - Add descriptions to embed, replyRef, root, and parent fields - Fix "etc)" to "etc.)" in facets description - Add namespace re-exports to embed/label type shims for consistency - Add post entity and relationships to ERD.puml - Regenerate SCHEMAS.md Co-Authored-By: Claude Opus 4.6 --- ERD.puml | 16 ++++++++++++++++ SCHEMAS.md | 12 ++++++------ lexicons/org/hypercerts/claim/post.json | 16 +++++++++++++--- scripts/create-shims.sh | 6 ++++++ 4 files changed, 41 insertions(+), 9 deletions(-) diff --git a/ERD.puml b/ERD.puml index 753bb797..dcb94a39 100644 --- a/ERD.puml +++ b/ERD.puml @@ -242,6 +242,19 @@ dataclass collection { !endif } +' org.hypercerts.claim.post +dataclass post { + !if (SHOW_FIELDS == "true") + text + replies[]? + embed? + labels? + tags[]? + attachments[]? + createdAt + !endif +} + ' org.hypercerts.context.acknowledgement dataclass acknowledgement { !if (SHOW_FIELDS == "true") @@ -384,6 +397,9 @@ fundingReceipt::to --> contributorEntity fundingReceipt::for --> activity : funds +post::replies --> activity : "replies to" +post::replies --> collection : "replies to" + badgeAward::badge --> badgeDefinition badgeResponse::badgeAward --> badgeAward badgeAward::subject --> contributorInformation diff --git a/SCHEMAS.md b/SCHEMAS.md index 8534734e..605996fc 100644 --- a/SCHEMAS.md +++ b/SCHEMAS.md @@ -106,9 +106,9 @@ Hypercerts-specific lexicons for tracking impact work and claims. | Property | Type | Required | Description | Comments | | ------------- | ---------- | -------- | ----------------------------------------------------------------------------------------------------------------------- | ------------------------------------ | | `text` | `string` | ✅ | The primary post content. May be an empty string, if there are embeds. | maxLength: 50000, maxGraphemes: 5000 | -| `facets` | `ref[]` | ❌ | Annotations of text (mentions, URLs, hashtags, etc) | | +| `facets` | `ref[]` | ❌ | Annotations of text (mentions, URLs, hashtags, etc.) | | | `replies` | `ref[]` | ❌ | The subjects that this post is in reply to. Each entry identifies a thread root and the direct parent being replied to. | maxLength: 10 | -| `embed` | `union` | ❌ | | | +| `embed` | `union` | ❌ | The primary featured media for this post (images, video, external link, or quoted record). | | | `labels` | `union` | ❌ | Self-label values for this post. Effectively content warnings. | | | `tags` | `string[]` | ❌ | Additional hashtags, in addition to any included in post text and facets. | maxLength: 8 | | `attachments` | `union[]` | ❌ | The files, documents, or external references attached to this post. | maxLength: 100 | @@ -118,10 +118,10 @@ Hypercerts-specific lexicons for tracking impact work and claims. ##### `org.hypercerts.claim.post#replyRef` -| Property | Type | Required | Description | -| -------- | ----- | -------- | ----------- | -| `root` | `ref` | ✅ | | -| `parent` | `ref` | ✅ | | +| Property | Type | Required | Description | +| -------- | ----- | -------- | ------------------------------------------------------------------------------------------ | +| `root` | `ref` | ✅ | The root record of the thread being replied to. | +| `parent` | `ref` | ✅ | The direct parent record being replied to (may be the same as root for top-level replies). | --- diff --git a/lexicons/org/hypercerts/claim/post.json b/lexicons/org/hypercerts/claim/post.json index b4e05635..16d0435e 100644 --- a/lexicons/org/hypercerts/claim/post.json +++ b/lexicons/org/hypercerts/claim/post.json @@ -18,7 +18,7 @@ }, "facets": { "type": "array", - "description": "Annotations of text (mentions, URLs, hashtags, etc)", + "description": "Annotations of text (mentions, URLs, hashtags, etc.)", "items": { "type": "ref", "ref": "app.bsky.richtext.facet" } }, "replies": { @@ -29,6 +29,7 @@ }, "embed": { "type": "union", + "description": "The primary featured media for this post (images, video, external link, or quoted record).", "refs": [ "app.bsky.embed.images", "app.bsky.embed.video", @@ -70,10 +71,19 @@ }, "replyRef": { "type": "object", + "description": "Identifies the thread root and direct parent that this post is replying to.", "required": ["root", "parent"], "properties": { - "root": { "type": "ref", "ref": "com.atproto.repo.strongRef" }, - "parent": { "type": "ref", "ref": "com.atproto.repo.strongRef" } + "root": { + "type": "ref", + "ref": "com.atproto.repo.strongRef", + "description": "The root record of the thread being replied to." + }, + "parent": { + "type": "ref", + "ref": "com.atproto.repo.strongRef", + "description": "The direct parent record being replied to (may be the same as root for top-level replies)." + } } } } diff --git a/scripts/create-shims.sh b/scripts/create-shims.sh index 412b6880..a2acb620 100755 --- a/scripts/create-shims.sh +++ b/scripts/create-shims.sh @@ -28,6 +28,7 @@ mkdir -p ./generated/types/app/bsky/embed cat >./generated/types/app/bsky/embed/images.ts <<'EOF' // Type shim for app.bsky.embed.images lexicon import type { AppBskyEmbedImages } from '@atcute/bluesky'; +export type { AppBskyEmbedImages }; export type Main = AppBskyEmbedImages.Main; export type Image = AppBskyEmbedImages.Image; export type View = AppBskyEmbedImages.View; @@ -37,6 +38,7 @@ EOF cat >./generated/types/app/bsky/embed/video.ts <<'EOF' // Type shim for app.bsky.embed.video lexicon import type { AppBskyEmbedVideo } from '@atcute/bluesky'; +export type { AppBskyEmbedVideo }; export type Main = AppBskyEmbedVideo.Main; export type Caption = AppBskyEmbedVideo.Caption; export type View = AppBskyEmbedVideo.View; @@ -45,6 +47,7 @@ EOF cat >./generated/types/app/bsky/embed/external.ts <<'EOF' // Type shim for app.bsky.embed.external lexicon import type { AppBskyEmbedExternal } from '@atcute/bluesky'; +export type { AppBskyEmbedExternal }; export type Main = AppBskyEmbedExternal.Main; export type External = AppBskyEmbedExternal.External; export type View = AppBskyEmbedExternal.View; @@ -54,6 +57,7 @@ EOF cat >./generated/types/app/bsky/embed/record.ts <<'EOF' // Type shim for app.bsky.embed.record lexicon import type { AppBskyEmbedRecord } from '@atcute/bluesky'; +export type { AppBskyEmbedRecord }; export type Main = AppBskyEmbedRecord.Main; export type View = AppBskyEmbedRecord.View; export type ViewBlocked = AppBskyEmbedRecord.ViewBlocked; @@ -65,6 +69,7 @@ EOF cat >./generated/types/app/bsky/embed/recordWithMedia.ts <<'EOF' // Type shim for app.bsky.embed.recordWithMedia lexicon import type { AppBskyEmbedRecordWithMedia } from '@atcute/bluesky'; +export type { AppBskyEmbedRecordWithMedia }; export type Main = AppBskyEmbedRecordWithMedia.Main; export type View = AppBskyEmbedRecordWithMedia.View; EOF @@ -74,6 +79,7 @@ mkdir -p ./generated/types/com/atproto/label cat >./generated/types/com/atproto/label/defs.ts <<'EOF' // Type shim for com.atproto.label.defs lexicon import type { ComAtprotoLabelDefs } from '@atcute/atproto'; +export type { ComAtprotoLabelDefs }; export type SelfLabels = ComAtprotoLabelDefs.SelfLabels; export type SelfLabel = ComAtprotoLabelDefs.SelfLabel; export type Label = ComAtprotoLabelDefs.Label; From 29133a89d376630e0764ed4a0ccc37e24f0377c1 Mon Sep 17 00:00:00 2001 From: holkexyz Date: Wed, 25 Feb 2026 10:03:34 +0100 Subject: [PATCH 3/4] fix: make text optional on post record Co-Authored-By: Claude Opus 4.6 --- lexicons/org/hypercerts/claim/post.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lexicons/org/hypercerts/claim/post.json b/lexicons/org/hypercerts/claim/post.json index 16d0435e..b8dc654e 100644 --- a/lexicons/org/hypercerts/claim/post.json +++ b/lexicons/org/hypercerts/claim/post.json @@ -8,7 +8,7 @@ "key": "tid", "record": { "type": "object", - "required": ["text", "createdAt"], + "required": ["createdAt"], "properties": { "text": { "type": "string", From 08e3b3c8173dfe78e8ff9901ef332e90385d8e74 Mon Sep 17 00:00:00 2001 From: holkexyz Date: Wed, 25 Feb 2026 10:13:12 +0100 Subject: [PATCH 4/4] fix: show array types as type[] and handle object-type mains in SCHEMAS.md Co-Authored-By: Claude Opus 4.6 --- SCHEMAS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SCHEMAS.md b/SCHEMAS.md index 605996fc..4313f481 100644 --- a/SCHEMAS.md +++ b/SCHEMAS.md @@ -105,7 +105,7 @@ Hypercerts-specific lexicons for tracking impact work and claims. | Property | Type | Required | Description | Comments | | ------------- | ---------- | -------- | ----------------------------------------------------------------------------------------------------------------------- | ------------------------------------ | -| `text` | `string` | ✅ | The primary post content. May be an empty string, if there are embeds. | maxLength: 50000, maxGraphemes: 5000 | +| `text` | `string` | ❌ | The primary post content. May be an empty string, if there are embeds. | maxLength: 50000, maxGraphemes: 5000 | | `facets` | `ref[]` | ❌ | Annotations of text (mentions, URLs, hashtags, etc.) | | | `replies` | `ref[]` | ❌ | The subjects that this post is in reply to. Each entry identifies a thread root and the direct parent being replied to. | maxLength: 10 | | `embed` | `union` | ❌ | The primary featured media for this post (images, video, external link, or quoted record). | |