diff --git a/ERD-with-fields.png b/ERD-with-fields.png index 31388c3..46bb842 100644 Binary files a/ERD-with-fields.png and b/ERD-with-fields.png differ diff --git a/ERD-with-fields.svg b/ERD-with-fields.svg index 8d34c36..385df85 100644 --- a/ERD-with-fields.svg +++ b/ERD-with-fields.svg @@ -1 +1 @@ -Hypercert ERDHypercert ERDcontributorDID or name/pseudonymactivitytitleshortDescriptiondescription?image?workScope?startDateendDatecontributions[]?location?rights?project?createdAtevidencesubject?contenttitleshortDescription?description?relationType?createdAtmeasurementsubject?measurers[]metricvaluemethodType?methodURI?evidenceURI[]?location?createdAtevaluationsubject?summaryevaluators[]content[]?measurements[]?scorelocation?createdAtcontributionrole?contributors[]description?startDate?endDate?createdAtlocationlpVersionsrslocationTypelocationname?description?createdAtrightsrightsNamerightsTyperightsDescriptionattachment?createdAtcollectiontitleshortDescription?avatar?coverPhoto?activities[]createdAtprojecttitleshortDescriptiondescription?avatar?coverPhoto?activities[]?location?createdAtfunderDID or name/pseudonymfundingReceipttofromfor?amountcurrencypaymentRail?paymentNetwork?transactionId?notes?occurredAt?createdAttoken(on-chain only)  tokenizesmade byfundshasfunds \ No newline at end of file +Hypercert ERDHypercert ERDcontributorDID or name/pseudonymactivitytitleshortDescriptiondescription?image?workScope?startDateendDatecontributions[]?location?rights?project?createdAtevidencesubject?contenttitleshortDescription?description?relationType?createdAtmeasurementsubject?measurers[]metricvaluemethodType?methodURI?evidenceURI[]?location?createdAtevaluationsubject?summaryevaluators[]content[]?measurements[]?scorelocation?createdAtcontributionrole?contributors[]description?startDate?endDate?createdAtlocationlpVersionsrslocationTypelocationname?description?createdAtbadgeDefinitionbadgeTypetitleicondescription?allowedIssuers[]?createdAtbadgeAwardbadgesubjectnote?createdAtbadgeResponsebadgeAwardresponseweight?createdAtrightsrightsNamerightsTyperightsDescriptionattachment?createdAtcollectiontitleshortDescription?avatar?coverPhoto?activities[]createdAtprojecttitleshortDescriptiondescription?avatar?coverPhoto?activities[]?location?createdAtfunderDID or name/pseudonymfundingReceipttofromfor?amountcurrencypaymentRail?paymentNetwork?transactionId?notes?occurredAt?createdAttoken(on-chain only)  tokenizesmade byfundshasfunds \ No newline at end of file diff --git a/ERD.png b/ERD.png index 852a4ce..3f0b7dc 100644 Binary files a/ERD.png and b/ERD.png differ diff --git a/ERD.puml b/ERD.puml index 3343995..20c8fce 100644 --- a/ERD.puml +++ b/ERD.puml @@ -137,6 +137,36 @@ dataclass location { !endif } +' Certified badges (data class + award + response) +dataclass badgeDefinition { + !if (SHOW_FIELDS == "true") + badgeType + title + icon + description? + allowedIssuers[]? + createdAt + !endif +} + +dataclass badgeAward { + !if (SHOW_FIELDS == "true") + badge + subject + note? + createdAt + !endif +} + +dataclass badgeResponse { + !if (SHOW_FIELDS == "true") + badgeAward + response + weight? + createdAt + !endif +} + ' org.hypercerts.claim.rights dataclass rights { !if (SHOW_FIELDS == "true") @@ -294,4 +324,11 @@ fundingReceipt::to --> contributor fundingReceipt::for --> activity : funds +badgeAward::badge --> badgeDefinition +badgeResponse::badgeAward --> badgeAward +badgeAward::subject --> contributor +badgeAward::subject --> activity +' This screws up the layout +'badgeAward::subject --[norank]-> project + @enduml diff --git a/ERD.svg b/ERD.svg index 03ec4cb..e86ba08 100644 --- a/ERD.svg +++ b/ERD.svg @@ -1 +1 @@ -Hypercert ERDHypercert ERDcontributoractivityevidencemeasurementevaluationcontributionlocationrightscollectionprojectfunderfundingReceipttoken tokenizesmade byfundshasfunds \ No newline at end of file +Hypercert ERDHypercert ERDcontributoractivityevidencemeasurementevaluationcontributionlocationbadgeDefinitionbadgeAwardbadgeResponserightscollectionprojectfunderfundingReceipttoken tokenizesmade byfundshasfunds \ No newline at end of file diff --git a/README.md b/README.md index 404a704..1aaf3b2 100644 --- a/README.md +++ b/README.md @@ -110,6 +110,53 @@ Certified lexicons are common/shared lexicons that can be used across multiple p | `description` | `string` | ❌ | Optional description for this location | | | `createdAt` | `string` | ✅ | Client-declared timestamp when this record was originally created | | +### Badges Lexicon + +**Lexicon IDs:** `app.certified.badge.definition`, `app.certified.badge.award`, `app.certified.badge.response` + +**Description:** Defines badge metadata, award records, and recipient responses for certified badges that can be used across protocols. + +#### Badge Definition + +**Lexicon ID:** `app.certified.badge.definition` + +**Key:** `tid` + +| Property | Type | Required | Description | +| ---------------- | -------- | -------- | ---------------------------------------------------------------------- | +| `badgeType` | `string` | ✅ | Category of the badge (e.g., endorsement, participation, affiliation). | +| `title` | `string` | ✅ | Human-readable title of the badge. | +| `icon` | `blob` | ✅ | Icon representing the badge (accepted `image/*` types, maxSize 1MB). | +| `description` | `string` | ❌ | Optional short statement describing the badge. | +| `allowedIssuers` | `array` | ❌ | Optional allowlist of DIDs allowed to issue this badge. | +| `createdAt` | `string` | ✅ | Client-declared timestamp when this record was originally created. | + +#### Badge Award + +**Lexicon ID:** `app.certified.badge.award` + +**Key:** `tid` + +| Property | Type | Required | Description | +| ----------- | -------- | -------- | ------------------------------------------------------------------------------------ | +| `badge` | `ref` | ✅ | Reference to the badge definition for this award (`app.certified.badge.definition`). | +| `subject` | `union` | ✅ | Entity the badge award is for (either a DID or a specific AT Protocol record). | +| `note` | `string` | ❌ | Optional explanation for the award. | +| `createdAt` | `string` | ✅ | Client-declared timestamp when this record was originally created. | + +#### Badge Response + +**Lexicon ID:** `app.certified.badge.response` + +**Key:** `tid` + +| Property | Type | Required | Description | +| ------------ | -------- | -------- | ---------------------------------------------------------------------- | +| `badgeAward` | `ref` | ✅ | Reference to the badge award (`app.certified.badge.award`). | +| `response` | `string` | ✅ | Enum: `accepted` or `rejected`. | +| `weight` | `string` | ❌ | Optional relative weight assigned by the recipient (stored as string). | +| `createdAt` | `string` | ✅ | Client-declared timestamp when this record was originally created. | + --- ## Hypercerts Lexicons diff --git a/lexicons/app/certified/badge/award.json b/lexicons/app/certified/badge/award.json new file mode 100644 index 0000000..f02fce1 --- /dev/null +++ b/lexicons/app/certified/badge/award.json @@ -0,0 +1,36 @@ +{ + "lexicon": 1, + "id": "app.certified.badge.award", + "defs": { + "main": { + "type": "record", + "description": "Records a badge award to a user, project, or activity claim.", + "key": "tid", + "record": { + "type": "object", + "required": ["badge", "subject", "createdAt"], + "properties": { + "badge": { + "type": "ref", + "ref": "app.certified.badge.definition", + "description": "Reference to the badge definition for this award." + }, + "subject": { + "type": "union", + "description": "Entity the badge award is for (either an account DID or any specific AT Protocol record), e.g. a user, a project, or a specific activity claim.", + "refs": ["app.certified.defs#did", "com.atproto.repo.strongRef"] + }, + "note": { + "type": "string", + "description": "Optional statement explaining the reason for this badge award." + }, + "createdAt": { + "type": "string", + "format": "datetime", + "description": "Client-declared timestamp when this record was originally created" + } + } + } + } + } +} diff --git a/lexicons/app/certified/badge/definition.json b/lexicons/app/certified/badge/definition.json new file mode 100644 index 0000000..7729158 --- /dev/null +++ b/lexicons/app/certified/badge/definition.json @@ -0,0 +1,53 @@ +{ + "lexicon": 1, + "id": "app.certified.badge.definition", + "defs": { + "main": { + "type": "record", + "description": "Defines a badge that can be awarded via badge award records to users, projects, or activity claims.", + "key": "tid", + "record": { + "type": "object", + "required": ["title", "badgeType", "icon", "createdAt"], + "properties": { + "badgeType": { + "type": "string", + "description": "Category of the badge (e.g. endorsement, participation, affiliation)." + }, + "title": { + "type": "string", + "description": "Human-readable title of the badge." + }, + "icon": { + "type": "blob", + "description": "Icon representing the badge, stored as a blob for compact visual display.", + "accept": [ + "image/png", + "image/jpeg", + "image/webp", + "image/svg+xml" + ], + "maxSize": 1048576 + }, + "description": { + "type": "string", + "description": "Optional short statement describing what the badge represents." + }, + "allowedIssuers": { + "type": "array", + "description": "Optional allowlist of DIDs allowed to issue this badge. If omitted, anyone may issue it.", + "items": { + "type": "ref", + "ref": "app.certified.defs#did" + } + }, + "createdAt": { + "type": "string", + "format": "datetime", + "description": "Client-declared timestamp when this record was originally created" + } + } + } + } + } +} diff --git a/lexicons/app/certified/badge/response.json b/lexicons/app/certified/badge/response.json new file mode 100644 index 0000000..eba4e58 --- /dev/null +++ b/lexicons/app/certified/badge/response.json @@ -0,0 +1,36 @@ +{ + "lexicon": 1, + "id": "app.certified.badge.response", + "defs": { + "main": { + "type": "record", + "description": "Recipient response to a badge award.", + "key": "tid", + "record": { + "type": "object", + "required": ["badgeAward", "response", "createdAt"], + "properties": { + "badgeAward": { + "type": "ref", + "ref": "app.certified.badge.award", + "description": "Reference to the badge award." + }, + "response": { + "type": "string", + "enum": ["accepted", "rejected"], + "description": "The recipient’s response for the badge (accepted or rejected)." + }, + "weight": { + "type": "string", + "description": "Optional relative weight for accepted badges, assigned by the recipient." + }, + "createdAt": { + "type": "string", + "format": "datetime", + "description": "Client-declared timestamp when this record was originally created" + } + } + } + } + } +} diff --git a/lexicons/app/certified/defs.json b/lexicons/app/certified/defs.json new file mode 100644 index 0000000..81d3959 --- /dev/null +++ b/lexicons/app/certified/defs.json @@ -0,0 +1,12 @@ +{ + "lexicon": 1, + "id": "app.certified.defs", + "description": "Common type definitions used across certified protocols.", + "defs": { + "did": { + "type": "string", + "format": "did", + "description": "A Decentralized Identifier (DID) string." + } + } +} diff --git a/lexicons/org/hypercerts/claim/evaluation.json b/lexicons/org/hypercerts/claim/evaluation.json index 5f0c9b4..a6efbc4 100644 --- a/lexicons/org/hypercerts/claim/evaluation.json +++ b/lexicons/org/hypercerts/claim/evaluation.json @@ -38,8 +38,8 @@ "type": "array", "description": "DIDs of the evaluators", "items": { - "type": "string", - "format": "did" + "type": "ref", + "ref": "app.certified.defs#did" }, "maxLength": 1000 }, diff --git a/lexicons/org/hypercerts/claim/measurement.json b/lexicons/org/hypercerts/claim/measurement.json index a28f581..029eecf 100644 --- a/lexicons/org/hypercerts/claim/measurement.json +++ b/lexicons/org/hypercerts/claim/measurement.json @@ -19,8 +19,8 @@ "type": "array", "description": "DIDs of the entity (or entities) that measured this data", "items": { - "type": "string", - "format": "did" + "type": "ref", + "ref": "app.certified.defs#did" }, "maxLength": 100 }, diff --git a/lexicons/org/hypercerts/funding/receipt.json b/lexicons/org/hypercerts/funding/receipt.json index 4943fd3..3efe87c 100644 --- a/lexicons/org/hypercerts/funding/receipt.json +++ b/lexicons/org/hypercerts/funding/receipt.json @@ -11,8 +11,8 @@ "required": ["from", "to", "amount", "currency", "createdAt"], "properties": { "from": { - "type": "string", - "format": "did", + "type": "ref", + "ref": "app.certified.defs#did", "description": "DID of the sender who transferred the funds. Leave empty if sender wants to stay anonymous." }, "to": {