{"_id":"@cooperation/claim-atproto","_rev":"2-34c70e25a98fc17cb195112d5eae50a9","name":"@cooperation/claim-atproto","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"@cooperation/claim-atproto","version":"0.1.0","keywords":["atproto","bluesky","claims","verifiable-credentials","linkedclaims","did"],"author":"","license":"MIT","_id":"@cooperation/claim-atproto@0.1.0","maintainers":[{"name":"gvelez17","email":"gvelez17@gmail.com"},{"name":"omarsalah1","email":"omar.salah.bus@gmail.com"}],"dist":{"shasum":"f1c4dc190f73ba7c7d8bc7958fd575bb551e312a","tarball":"https://registry.npmjs.org/@cooperation/claim-atproto/-/claim-atproto-0.1.0.tgz","fileCount":9,"integrity":"sha512-O/612iWojuB201gcwhx8HBwYKTNlycNEyn3kKtv8WVECdTtENbV1LxZiGDivG5yYl8pzxwuCkymRq3+KHvOCUg==","signatures":[{"sig":"MEUCIF4O/rWZV+lnm+1zIOZHFZVIeBXMC6uv0fBDEkhl2EvwAiEAzSGlooqLUzKUz7R1Y20++OJtD2sdDLwmPPH6k8RKH6c=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":191846},"main":"./dist/index.js","types":"./dist/index.d.ts","module":"./dist/index.mjs","engines":{"node":">=18.0.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"}},"gitHead":"f20c475632d865756a26bd78fb0030479ac66d1f","scripts":{"dev":"tsup --watch","lint":"eslint src --ext .ts","test":"vitest","build":"tsup","format":"prettier --write 'src/**/*.ts'","test:ui":"vitest --ui","type-check":"tsc --noEmit","prepublishOnly":"npm run build"},"_npmUser":{"name":"gvelez17","email":"gvelez17@gmail.com"},"repository":{"url":"","type":"git"},"_npmVersion":"10.8.2","description":"TypeScript library for creating and publishing linked claims on ATProto","directories":{},"_nodeVersion":"20.20.0","dependencies":{"@atproto/api":"^0.13.0","multiformats":"^13.3.1","@atproto/lexicon":"^0.4.1"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","eslint":"^9.17.0","vitest":"^2.1.8","prettier":"^3.4.2","@vitest/ui":"^2.1.8","typescript":"^5.7.2","@types/node":"^22.10.5","@typescript-eslint/parser":"^8.19.1","@typescript-eslint/eslint-plugin":"^8.19.1"},"peerDependencies":{"@atproto/api":">=0.12.0"},"_npmOperationalInternal":{"tmp":"tmp/claim-atproto_0.1.0_1774346966214_0.5443761715973576","host":"s3://npm-registry-packages-npm-production"}}},"time":{"created":"2026-03-24T10:09:25.772Z","modified":"2026-06-15T23:09:36.651Z","0.1.0":"2026-03-24T10:09:26.403Z"},"license":"MIT","keywords":["atproto","bluesky","claims","verifiable-credentials","linkedclaims","did"],"repository":{"url":"","type":"git"},"description":"TypeScript library for creating and publishing linked claims on ATProto","maintainers":[{"email":"gvelez17@gmail.com","name":"gvelez17"},{"email":"dzagidulin@gmail.com","name":"codenamedmitri"},{"email":"omar.salah.bus@gmail.com","name":"omarsalah1"}],"readme":"# @cooperation/claim-atproto\n\n> TypeScript library for creating and publishing linked claims on ATProto (Bluesky)\n\nA composable, type-safe library for working with verifiable claims on the AT Protocol. Implements the [LinkedClaims](https://github.com/decentralized-identity/labs-linkedclaims) specification from the Decentralized Identity Foundation (DIF).\n\n## Features\n\n- ✅ **Fluent Builder API** - Chainable, type-safe claim construction\n- ✅ **ATProto Native** - Seamless integration with Bluesky/ATProto\n- ✅ **Claims-about-Claims** - Built-in support for endorsements, disputes, revocations\n- ✅ **Content Hashing** - Compute integrity hashes for evidence\n- ✅ **Schema Validation** - Automatic validation against the `com.linkedclaims.claim` lexicon\n- ✅ **Universal** - Works in Node.js and browser environments\n- ✅ **TypeScript** - Full type safety with excellent IDE support\n\n## Installation\n\n```bash\nnpm install @cooperation/claim-atproto\n```\n\n**Requirements:**\n- Node.js 18+ or modern browser\n- `@atproto/api` (peer dependency)\n\n## Quick Start\n\n```typescript\nimport { AtpAgent } from '@atproto/api'\nimport { ClaimClient, createClaim } from '@cooperation/claim-atproto'\n\n// Authenticate with Bluesky\nconst agent = new AtpAgent({ service: 'https://bsky.social' })\nawait agent.login({\n  identifier: 'alice.bsky.social',\n  password: 'app-password', // Use an app password, not your main password\n})\n\n// Create a claim client\nconst client = new ClaimClient({ agent })\n\n// Build and publish a claim\nconst claim = createClaim()\n  .subject('did:plc:alice')\n  .type('skill')\n  .object('React')\n  .statement('5 years of production experience')\n  .confidence(0.9)\n  .build()\n\nconst published = await client.publish(claim)\nconsole.log(`Published at: ${published.uri}`)\n```\n\n## Core Concepts\n\n### Claims\n\nA **claim** is an immutable, signed assertion about any URI-addressable subject:\n\n```typescript\nconst claim = createClaim()\n  .subject('did:plc:alice')           // Who/what the claim is about\n  .type('skill')                      // Category of claim\n  .object('TypeScript')               // Optional: specific object\n  .statement('Expert level')          // Human-readable explanation\n  .confidence(1.0)                    // Optional: confidence (0-1)\n  .build()\n```\n\n### Claims-about-Claims\n\nEndorsements, disputes, and other meta-claims reference another claim's AT-URI:\n\n```typescript\nimport { createEndorsement } from '@cooperation/claim-atproto'\n\n// Endorse another claim\nconst endorsement = createEndorsement(\n  'at://did:plc:alice/com.linkedclaims.claim/xyz123',\n  'I can confirm Alice has these skills',\n  { confidence: 1.0, howKnown: 'FIRST_HAND' }\n).build()\n\nawait client.publish(endorsement)\n```\n\n### Evidence & Provenance\n\nAdd structured evidence with content hashing:\n\n```typescript\nimport { createSource, computeDigestMultibase } from '@cooperation/claim-atproto'\n\nconst evidenceHash = await computeDigestMultibase('Evidence content...')\n\nconst claim = createClaim()\n  .subject('https://ngo.org/project')\n  .type('impact')\n  .statement('Delivered 500 water filters')\n  .withSource(\n    createSource()\n      .uri('https://evidence.org/report.pdf')\n      .digest(evidenceHash)\n      .howKnown('WEB_DOCUMENT')\n  )\n  .build()\n```\n\n## API Overview\n\n### Builders\n\n- **`createClaim()`** - Build a claim with fluent API\n- **`createSource()`** - Build evidence/provenance metadata\n- **`createProof()`** - Build external proof (for future external signing support)\n\n### Client\n\n- **`ClaimClient`** - Publish and manage claims on ATProto\n  - `.publish(claim)` - Publish to your repository\n  - `.publishTo(did, claim)` - Publish to another repository\n  - `.get(uri)` - Fetch a claim by AT-URI\n  - `.delete(uri)` - Delete a claim\n\n### Helpers\n\n- **`createEndorsement(uri, statement, options)`** - Create an endorsement\n- **`createDispute(uri, statement, options)`** - Create a dispute\n- **`createSuperseding(uri, statement)`** - Create an update/replacement\n- **`createRevocation(uri, reason)`** - Create a revocation\n- **`computeDigestMultibase(content)`** - Hash content for integrity\n- **`fetchAndHash(uri)`** - Fetch and hash remote content\n\n### Validation\n\n- **`validateClaim(claim)`** - Validate against lexicon (throws on error)\n- **`isValidClaim(claim)`** - Check validity (returns boolean)\n\n## Examples\n\n### Basic Skill Claim\n\n```typescript\nconst claim = createClaim()\n  .subject('did:plc:alice')\n  .type('skill')\n  .object('React')\n  .statement('3 years production experience')\n  .build()\n\nconst published = await client.publish(claim)\n```\n\n### Impact Claim with Evidence\n\n```typescript\nconst claim = createClaim()\n  .subject('https://example.org/ngo/project-123')\n  .type('impact')\n  .statement('Distributed 500 water filters in Kibera')\n  .withSource(\n    createSource()\n      .uri('ipfs://bafybei...')\n      .howKnown('FIRST_HAND')\n      .dateObserved(new Date('2024-12-15'))\n  )\n  .effectiveDate(new Date('2024-12-15'))\n  .build()\n\nawait client.publish(claim)\n```\n\n### Endorsement\n\n```typescript\nimport { createEndorsement } from '@cooperation/claim-atproto'\n\nconst endorsement = createEndorsement(\n  'at://did:plc:bob/com.linkedclaims.claim/abc123',\n  'I worked with Bob for 2 years and can confirm his skills',\n  { confidence: 1.0, howKnown: 'FIRST_HAND' }\n).build()\n\nawait client.publish(endorsement)\n```\n\n### Dispute\n\n```typescript\nimport { createDispute } from '@cooperation/claim-atproto'\n\nconst dispute = createDispute(\n  'at://did:plc:alice/com.linkedclaims.claim/xyz789',\n  'The actual count was 200, not 500',\n  {\n    evidence: 'https://evidence.org/actual-count.pdf',\n    howKnown: 'WEB_DOCUMENT'\n  }\n).build()\n\nawait client.publish(dispute)\n```\n\n### Rating\n\n```typescript\nconst rating = createClaim()\n  .subject('https://restaurant.example.com')\n  .type('rating')\n  .object('food-quality')\n  .stars(4)\n  .statement('Excellent pasta, slightly slow service')\n  .build()\n\nawait client.publish(rating)\n```\n\n## TypeScript Types\n\nFull TypeScript support with exported types:\n\n```typescript\nimport type {\n  Claim,\n  ClaimSource,\n  EmbeddedProof,\n  PublishedClaim,\n  HowKnown,\n  ClaimClientConfig,\n} from '@cooperation/claim-atproto'\n```\n\n## Claim Types\n\nThe `claimType` field is an open string. Common values include:\n\n- **`skill`** - Professional skills\n- **`credential`** - Certifications, degrees\n- **`impact`** - NGO/charity impact claims\n- **`endorsement`** - Endorsement of another claim\n- **`dispute`** - Dispute of another claim\n- **`rating`** - Star ratings (use `stars` field)\n- **`review`** - Reviews with text\n- **`membership`** - Organization membership\n- **`supersedes`** - Claim that replaces another\n- **`revocation`** - Claim revocation\n\nYou can use any string value that fits your use case.\n\n## Claim Signing\n\nAll claims published to ATProto are automatically signed by the repository's signing key. This happens transparently when you call `client.publish()`.\n\n**Who signed a claim?**\n- If published to user's own repo → signer is the user's DID\n- If published to server's repo → signer is the server's DID\n\nFor external signing (MetaMask, DIDs, etc.), see the `embeddedProof` field in the types. External signing support may be added in future versions.\n\n## Validation\n\nClaims are automatically validated against the `com.linkedclaims.claim` lexicon before publishing:\n\n```typescript\nimport { validateClaim, isValidClaim } from '@cooperation/claim-atproto'\n\n// Throws error if invalid\nvalidateClaim(claim)\n\n// Returns boolean\nif (isValidClaim(claim)) {\n  await client.publish(claim)\n}\n\n// Disable validation for testing\nconst client = new ClaimClient({ agent, validate: false })\n```\n\n## Browser Usage\n\nThe library works in browsers too:\n\n```html\n<script type=\"module\">\n  import { createClaim } from 'https://esm.sh/@cooperation/claim-atproto'\n\n  const claim = createClaim()\n    .subject('did:plc:alice')\n    .type('endorsement')\n    .build()\n</script>\n```\n\nOr with a bundler (Vite, Webpack, etc.):\n\n```typescript\nimport { ClaimClient, createClaim } from '@cooperation/claim-atproto'\n// ... use normally\n```\n\n## More Examples\n\nSee the [`examples/`](./examples/) directory for complete working examples:\n\n- **[basic-claim.ts](./examples/node/basic-claim.ts)** - Simple skill claim\n- **[endorsement.ts](./examples/node/endorsement.ts)** - Endorsing another claim\n- **[with-evidence.ts](./examples/node/with-evidence.ts)** - Claim with evidence and content hash\n\n## Development\n\n```bash\n# Install dependencies\nnpm install\n\n# Build\nnpm run build\n\n# Test\nnpm test\n\n# Type check\nnpm run type-check\n\n# Run examples\nnpx tsx examples/node/basic-claim.ts\n```\n\n## Lexicon: `com.linkedclaims.claim`\n\nThe lexicon definition is at `src/lexicons/com-linkedclaims-claim.json`. Key fields:\n\n- **`subject`** (required) — URI the claim is about. Any URI: HTTPS, DID, AT-URI, IPFS CID\n- **`claimType`** (required) — category: skill, credential, impact, endorsement, dispute, rating, etc.\n- **`claimUri`** — persistent identity of this claim. Other claims reference it as their subject\n- **`statement`** — human-readable explanation\n- **`source`** — where the claim info comes from (uri, howKnown, digestMultibase, dateObserved, author, curator)\n- **`evidence[]`** — supporting materials: photos, videos, documents (uri, digestMultibase, mediaType, description)\n- **`confidence`** — signer's confidence (0-1)\n- **`stars`** — star rating (1-5)\n- **`respondAt`** — URI for sending endorsements/disputes\n- **`embeddedProof`** — for claims signed externally (MetaMask, etc.) before publishing to ATProto\n\n### Namespace Ownership\n\n`com.linkedclaims.claim` maps to `linkedclaims.com`. DNS verification via TXT record on `_atproto.linkedclaims.com`.\n\n### Architecture\n\nATProto is one publication channel — not the canonical home. Claims are signed assertions that can exist in multiple systems. The LinkedTrust backend (`trust_claim_backend`) acts as an **AppView**: it subscribes to the ATProto firehose via Jetstream, indexes `com.linkedclaims.claim` records from ALL publishers, and provides query/aggregation APIs.\n\nWhen a claim is published to ATProto, its AT-URI (`at://did:plc:xyz/com.linkedclaims.claim/tid`) becomes its permanent decentralized address. Other claims can reference it by setting `subject` to that AT-URI — this is how endorsements, disputes, and other claims-about-claims work.\n\n## Embeddable Web Component\n\nA `<linked-claims-atproto>` web component is available for embedding ATProto claim feeds on any web page:\n\n```html\n<!-- Show claims about this page -->\n<linked-claims-atproto api=\"https://live.linkedtrust.us\"></linked-claims-atproto>\n\n<!-- Show claims about a specific URL -->\n<linked-claims-atproto subject=\"https://example.com\" api=\"https://live.linkedtrust.us\"></linked-claims-atproto>\n\n<!-- Browse a specific user's claims (no backend needed) -->\n<linked-claims-atproto repo=\"did:plc:xztctnvt5ycnsippd3orwqk7\" subject=\"*\"></linked-claims-atproto>\n```\n\nSource: `trust_claim/public/atproto-claims.js` (will move into this SDK as a built artifact).\n\n## Related Projects\n\n- **[claim-lexicon](https://github.com/Cooperation-org/claim-atproto)** - The `com.linkedclaims.claim` lexicon specification\n- **[@atproto/api](https://www.npmjs.com/package/@atproto/api)** - ATProto SDK\n- **[LinkedClaims](https://github.com/decentralized-identity/labs-linkedclaims)** - DIF specification\n\n## License\n\nMIT\n\n## Contributing\n\nContributions welcome! Please open an issue or PR.\n\n## Questions?\n\n- **Lexicon Issues:** Report at the [claim-lexicon repo](https://github.com/Cooperation-org/claim-atproto/issues)\n- **Library Issues:** Open an issue in this repo\n- **ATProto Questions:** See [ATProto docs](https://atproto.com)\n","readmeFilename":"README.md"}