Skip to content

Commit 4a2dafa

Browse files
satyam-mishra-pceaspiers
authored andcommitted
feat: add cryptographic signature support to all lexicons
Add optional cryptographic signature support to all record lexicons, enabling platform attestation and verification that records were created through trusted services. Inspired by: - ATProtocol Attestation Specification by Nick Gerakines - The platformAttestation pattern from app.bumicerts.link.evm New lexicons: - app.certified.signature.inline: Inline signature with JOSE algorithm IDs - app.certified.signature.list: Container with signatures array (open union) - app.certified.signature.proof: Remote attestation proof record All 20 record lexicons now include an optional signatureData property: - org.hypercerts.claim.* (activity, contribution, contributorInformation, rights) - org.hypercerts.collection - org.hypercerts.context.* (acknowledgement, attachment, evaluation, measurement) - org.hypercerts.funding.receipt - org.hypercerts.workscope.tag - org.hyperboards.* (board, displayProfile) - app.certified.badge.* (award, definition, response) - app.certified.actor.* (profile, organization) - app.certified.location - app.certified.link.evm Design decisions: - Uses ref to app.certified.signature.list for DRY structure - JOSE algorithm identifiers (ES256K, ES256, Ed25519) per ATProto convention - Supports both inline signatures and remote attestations via strongRef
1 parent fb07dd9 commit 4a2dafa

29 files changed

Lines changed: 505 additions & 68 deletions

.changeset/fuzzy-pandas-smile.md

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
---
2+
"@hypercerts-org/lexicon": minor
3+
---
4+
5+
Add cryptographic signature support to all lexicons
6+
7+
Adds optional cryptographic signature support to all record lexicons, enabling platform attestation and verification that records were created through trusted services. This is inspired by the [ATProtocol Attestation Specification](https://ngerakines.leaflet.pub/3m3idxul5hc2r) by Nick Gerakines.
8+
9+
**New lexicons:**
10+
11+
- `app.certified.signature.inline` - Inline cryptographic signature object with JOSE algorithm identifiers (ES256, ES256K, Ed25519)
12+
- `app.certified.signature.list` - Container object with `signatures` array supporting both inline signatures and remote attestation references
13+
- `app.certified.signature.proof` - Remote attestation proof record containing the CID of attested content
14+
15+
**Changes to existing lexicons:**
16+
17+
All 20 record lexicons now include an optional `signatureData` property that references `app.certified.signature.list`:
18+
19+
- `org.hypercerts.claim.activity`
20+
- `org.hypercerts.claim.contribution`
21+
- `org.hypercerts.claim.contributorInformation`
22+
- `org.hypercerts.claim.rights`
23+
- `org.hypercerts.collection`
24+
- `org.hypercerts.context.acknowledgement`
25+
- `org.hypercerts.context.attachment`
26+
- `org.hypercerts.context.evaluation`
27+
- `org.hypercerts.context.measurement`
28+
- `org.hypercerts.funding.receipt`
29+
- `org.hypercerts.workscope.tag`
30+
- `org.hyperboards.board`
31+
- `org.hyperboards.displayProfile`
32+
- `app.certified.badge.award`
33+
- `app.certified.badge.definition`
34+
- `app.certified.badge.response`
35+
- `app.certified.actor.profile`
36+
- `app.certified.actor.organization`
37+
- `app.certified.location`
38+
- `app.certified.link.evm`
39+
40+
**Design notes:**
41+
42+
This is a non-breaking extension - signatures are optional on all records. Two signature patterns are supported:
43+
44+
1. **Inline signatures** - Embedded directly in the record via `app.certified.signature.inline`
45+
2. **Remote attestations** - References to proof records in other repositories via `com.atproto.repo.strongRef`
46+
47+
Signature algorithm identifiers use [JOSE format](https://www.iana.org/assignments/jose/jose.xhtml) per ATProto convention:
48+
49+
- `ES256K` - secp256k1 (Ethereum/Bitcoin curve, ATProto default)
50+
- `ES256` - P-256 (NIST curve, WebCrypto compatible)
51+
- `Ed25519` - EdDSA

ERD.puml

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,40 @@ dataclass rights {
229229
!endif
230230
}
231231

232+
' app.certified.signature.inline
233+
dataclass signatureInline {
234+
!if (SHOW_FIELDS == "true")
235+
signatureType?
236+
signature
237+
key
238+
!endif
239+
}
240+
241+
' app.certified.signature.list
242+
dataclass signatureList {
243+
!if (SHOW_FIELDS == "true")
244+
signatures[]?
245+
!endif
246+
}
247+
248+
' app.certified.signature.proof
249+
dataclass signatureProof {
250+
!if (SHOW_FIELDS == "true")
251+
cid
252+
note?
253+
createdAt?
254+
!endif
255+
}
256+
257+
' app.certified.link.evm
258+
dataclass linkEvm {
259+
!if (SHOW_FIELDS == "true")
260+
address
261+
proof
262+
createdAt
263+
!endif
264+
}
265+
232266
' org.hypercerts.collection
233267
dataclass collection {
234268
!if (SHOW_FIELDS == "true")
@@ -391,4 +425,27 @@ badgeAward::subject --> activity
391425
' This screws up the layout
392426
'badgeAward::subject --[norank]-> collection
393427

428+
' Signature relationships
429+
signatureList::signatures --> signatureInline
430+
signatureList::signatures --> signatureProof : "strongRef"
431+
432+
' signatureData relationships (all record lexicons reference signatureList)
433+
activity ..> signatureList : signatureData
434+
collection ..> signatureList : signatureData
435+
attachment ..> signatureList : signatureData
436+
measurement ..> signatureList : signatureData
437+
evaluation ..> signatureList : signatureData
438+
acknowledgement ..> signatureList : signatureData
439+
contribution ..> signatureList : signatureData
440+
contributorInformation ..> signatureList : signatureData
441+
rights ..> signatureList : signatureData
442+
fundingReceipt ..> signatureList : signatureData
443+
workScopeTag ..> signatureList : signatureData
444+
location ..> signatureList : signatureData
445+
badgeDefinition ..> signatureList : signatureData
446+
badgeAward ..> signatureList : signatureData
447+
badgeResponse ..> signatureList : signatureData
448+
organization ..> signatureList : signatureData
449+
linkEvm ..> signatureList : signatureData
450+
394451
@enduml

README.md

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ CERTIFIED ─ shared lexicons (certified.app)
4444
actor/profile (user profile)
4545
actor/organization (org metadata)
4646
badge/definition ──► badge/award ──► badge/response
47+
signature/inline (embedded cryptographic signature)
48+
signature/list (container for signatures array)
49+
signature/proof (remote attestation proof record)
4750
```
4851

4952
Every arrow (``) is a `strongRef` or union reference stored on the
@@ -275,6 +278,16 @@ await agent.api.com.atproto.repo.createRecord({
275278
| **Badge Response** | `app.certified.badge.response` | Recipient accepts or rejects a badge award. |
276279
| **EVM Link** | `app.certified.link.evm` | Verifiable ATProto DID ↔ EVM wallet link via EIP-712 signature. Extensible for future proof methods (e.g. ERC-1271, ERC-6492). |
277280

281+
### Signatures (`app.certified.signature.*`)
282+
283+
| Lexicon | NSID | Description |
284+
| -------------------- | -------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
285+
| **Inline Signature** | `app.certified.signature.inline` | An inline cryptographic signature for attesting to record content. Uses JOSE algorithm identifiers (ES256, ES256K, Ed25519). |
286+
| **Signature List** | `app.certified.signature.list` | Container object with a `signatures` array. Referenced by all record lexicons via `signatureData` property. |
287+
| **Proof** | `app.certified.signature.proof` | Remote attestation proof record containing the CID of attested content. Lives in the attestor's repository and can be referenced via strongRef. |
288+
289+
All record lexicons include an optional `signatureData` property that references `app.certified.signature.list`, enabling cryptographic attestations. See [Cryptographic Signatures](#cryptographic-signatures) for usage details.
290+
278291
> **Full property tables**[SCHEMAS.md](SCHEMAS.md)
279292
280293
## Entity Relationship Diagram
@@ -494,6 +507,73 @@ const attachment = {
494507
};
495508
```
496509

510+
### Cryptographic Signatures
511+
512+
All record lexicons support optional cryptographic signatures via the `signatureData` property. This enables platform attestation and verification that records were created through trusted services.
513+
514+
Signatures support two patterns:
515+
516+
1. **Inline signatures**: Embedded directly in the record
517+
2. **Remote attestations**: References to proof records in other repositories (via `strongRef`)
518+
519+
```typescript
520+
import { ACTIVITY_NSID } from "@hypercerts-org/lexicon";
521+
522+
// Activity with inline signature
523+
const signedActivity = {
524+
$type: ACTIVITY_NSID,
525+
title: "Verified Reforestation Project",
526+
shortDescription: "Planted 1,000 trees in partnership with local community",
527+
createdAt: new Date().toISOString(),
528+
signatureData: {
529+
signatures: [
530+
// Inline signature (embedded)
531+
{
532+
$type: "app.certified.signature.inline",
533+
signatureType: "ES256K", // JOSE algorithm: secp256k1
534+
signature: new Uint8Array([
535+
/* signature bytes */
536+
]),
537+
key: "did:plc:platform123#signing", // DID verification method
538+
},
539+
// Remote attestation (reference to proof in another repo)
540+
{
541+
$type: "com.atproto.repo.strongRef",
542+
uri: "at://did:plc:verifier/app.certified.signature.proof/abc123",
543+
cid: "bafy...",
544+
},
545+
],
546+
},
547+
};
548+
```
549+
550+
#### Signature Algorithm Identifiers
551+
552+
The `signatureType` property uses [JOSE algorithm identifiers](https://www.iana.org/assignments/jose/jose.xhtml):
553+
554+
| Value | Curve | Description |
555+
| --------- | --------- | --------------------------------------- |
556+
| `ES256` | P-256 | NIST curve, WebCrypto compatible |
557+
| `ES256K` | secp256k1 | Ethereum/Bitcoin curve, ATProto default |
558+
| `Ed25519` | Ed25519 | EdDSA, increasingly popular |
559+
560+
#### Remote Attestation Proofs
561+
562+
For remote attestations, create a proof record in the attestor's repository:
563+
564+
```typescript
565+
import { SIGNATURE_PROOF_NSID } from "@hypercerts-org/lexicon";
566+
567+
const proof = {
568+
$type: SIGNATURE_PROOF_NSID,
569+
cid: "bafy...", // CID of the attested content
570+
note: "Verified by platform quality assurance process",
571+
createdAt: new Date().toISOString(),
572+
};
573+
```
574+
575+
For the full specification, see Nick Gerakines' [ATProtocol Attestation Specification](https://ngerakines.leaflet.pub/3m3idxul5hc2r).
576+
497577
## Development
498578

499579
### Commands

0 commit comments

Comments
 (0)