Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/nasty-ways-change.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@agentcommercekit/vc": minor
---

Replaced StatusList2021 with BitstringStatusList for VC revocation
4 changes: 2 additions & 2 deletions docs/demos/example-identity.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ The API supports issuing, verifying, and revoking two primary credential types:
- **`ControllerCredential`**: proves ownership of DIDs (part of ACK-ID).
- **`PaymentReceiptCredential`**: provides proof of payment meeting a Payment Request (part of ACK-Pay).

The issuer implements credential revocation using [StatusList2021](https://www.w3.org/community/reports/credentials/CG-FINAL-vc-status-list-2021-20230102/), a privacy-preserving and efficient revocation list method.
The issuer implements credential revocation using [Bitstring Status List](https://www.w3.org/TR/vc-bitstring-status-list/), a privacy-preserving and efficient revocation list method.

## Installation and Setup

Expand Down Expand Up @@ -158,7 +158,7 @@ curl --request DELETE \

#### `GET /status/:listId`

Retrieve StatusList2021 credential for revocation checks.
Retrieve Bitstring Status List credential for revocation checks.

**Sample cURL:**

Expand Down
4 changes: 2 additions & 2 deletions examples/issuer/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ The API allows for the issuance, verification, and revocation of the following c
- `ControllerCredential`: ACK-ID credentials that prove DID ownership hierarchies.
- `PaymentReceiptCredential`: ACK-Pay credentials that provide proof of payment that satisfies a given Payment Request.

This issuer supports credential revocation using [StatusList2021](https://www.w3.org/community/reports/credentials/CG-FINAL-vc-status-list-2021-20230102/), which is a privacy-preserving, space-efficient mechanism for maintaining a credential revocation list.
This issuer supports credential revocation using [Bitstring Status List](https://www.w3.org/TR/vc-bitstring-status-list/), which is a privacy-preserving, space-efficient mechanism for maintaining a credential revocation list.

## Getting Started

Expand Down Expand Up @@ -269,7 +269,7 @@ curl --request DELETE \

#### GET /status/:listId

Retrieve a StatusList2021 credential for checking revocation status
Retrieve a Bitstring Status List credential for checking revocation status

**Response Body**

Expand Down
13 changes: 9 additions & 4 deletions examples/issuer/src/routes/status.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ import { database } from "@/middleware/database"
import { didResolver } from "@/middleware/did-resolver"
import { issuer } from "@/middleware/issuer"
import type { ApiResponse } from "@repo/api-utils/api-response"
import type { StatusList2021Credential, Verifiable } from "agentcommercekit"
import type {
BitstringStatusListCredential,
Verifiable
} from "agentcommercekit"
import type { Env } from "hono"

const app = new Hono<Env>()
Expand All @@ -21,16 +24,18 @@ app.use("*", didResolver())
/**
* GET /status/:listId
*
* @description Retrieves a StatusList2021 credential for checking revocation status
* @description Retrieves a BitstringStatusListCredential for checking revocation status
*
* URL Parameters:
* - listId: string - ID of the status list to retrieve
*
* @returns Signed StatusList2021 credential with compressed bit string
* @returns Signed BitstringStatusListCredential with compressed bit string
*/
app.get(
"/:listId",
async (c): Promise<ApiResponse<Verifiable<StatusList2021Credential>>> => {
async (
c
): Promise<ApiResponse<Verifiable<BitstringStatusListCredential>>> => {
const listId = c.req.param("listId")
const db = c.get("db")
const issuer = c.get("issuer")
Expand Down
4 changes: 2 additions & 2 deletions examples/verifier/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ This example showcases a **Credential Verifier** for [ACK-ID](https://www.agentc
- `ControllerCredential`: ACK-ID credentials that prove DID ownership hierarchies.
- `PaymentReceiptCredential`: ACK-Pay credentials that provide proof of payment that satisfies a given Payment Request.

This verifier uses [StatusList2021](https://www.w3.org/community/reports/credentials/CG-FINAL-vc-status-list-2021-20230102/), to check if a credential is revoked.# Installation
This verifier uses [Bitstring Status List](https://www.w3.org/TR/vc-bitstring-status-list/), to check if a credential is revoked.

## Getting Started

Expand Down Expand Up @@ -98,7 +98,7 @@ curl --request POST \
},
"credentialStatus": {
"id": "http://localhost:3456/status/0#0",
"type": "StatusList2021Entry",
"type": "BitstringStatusListEntry",
"statusPurpose": "revocation",
"statusListIndex": "0",
"statusListCredential": "http://localhost:3456/status/0"
Expand Down
14 changes: 7 additions & 7 deletions packages/vc/src/revocation/is-status-list-credential.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import * as v from "valibot"
import { isCredential } from "../is-credential"
import { statusList2021ClaimSchema } from "../schemas/valibot"
import type { StatusList2021Credential } from "./types"
import { bitstringStatusListClaimSchema } from "../schemas/valibot"
import type { BitstringStatusListCredential } from "./types"
import type { CredentialSubject } from "../types"

function isStatusList2021Claim(
function isStatusListClaim(
credentialSubject: CredentialSubject
): credentialSubject is v.InferOutput<typeof statusList2021ClaimSchema> {
return v.is(statusList2021ClaimSchema, credentialSubject)
): credentialSubject is v.InferOutput<typeof bitstringStatusListClaimSchema> {
return v.is(bitstringStatusListClaimSchema, credentialSubject)
}

/**
Expand All @@ -18,9 +18,9 @@ function isStatusList2021Claim(
*/
export function isStatusListCredential(
credential: unknown
): credential is StatusList2021Credential {
): credential is BitstringStatusListCredential {
if (!isCredential(credential)) {
return false
}
return isStatusList2021Claim(credential.credentialSubject)
return isStatusListClaim(credential.credentialSubject)
}
2 changes: 1 addition & 1 deletion packages/vc/src/revocation/make-revocable.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ describe("makeRevocable", () => {

expect(revocableCredential.credentialStatus).toEqual({
id: mockStatusListId,
type: "StatusList2021Entry",
type: "BitstringStatusListEntry",
statusPurpose: "revocation",
statusListIndex: mockStatusListIndex.toString(),
statusListCredential: mockStatusListUrl
Expand Down
2 changes: 1 addition & 1 deletion packages/vc/src/revocation/make-revocable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export function makeRevocable<T extends W3CCredential>(
...credential,
credentialStatus: {
id,
type: "StatusList2021Entry",
type: "BitstringStatusListEntry",
statusPurpose: "revocation",
statusListIndex: statusListIndex.toString(),
statusListCredential: statusListUrl
Expand Down
4 changes: 2 additions & 2 deletions packages/vc/src/revocation/status-list-credential.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ describe("createStatusListCredential", () => {

const credential = createStatusListCredential(params)

expect(credential.type).toContain("StatusList2021Credential")
expect(credential.type).toContain("BitstringStatusListCredential")
expect(credential.issuer).toEqual({ id: issuer })
expect(credential.credentialSubject).toBeDefined()
expect(credential.credentialSubject.type).toBe("StatusList2021")
expect(credential.credentialSubject.type).toBe("BitstringStatusList")
expect(credential.credentialSubject.statusPurpose).toBe("revocation")
expect(credential.credentialSubject.encodedList).toBe(params.encodedList)
})
Expand Down
10 changes: 5 additions & 5 deletions packages/vc/src/revocation/status-list-credential.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { createCredential } from "../create-credential"
import type { StatusList2021Credential } from "./types"
import type { BitstringStatusListCredential } from "./types"

type CreateStatusListCredentialParams = {
/**
Expand All @@ -20,20 +20,20 @@ type CreateStatusListCredentialParams = {
* Generates a status list credential.
*
* @param params - The {@link CreateStatusListCredentialParams} to use
* @returns A {@link StatusList2021Credential}
* @returns A {@link BitstringStatusListCredential}
*/
export function createStatusListCredential({
url,
encodedList,
issuer
}: CreateStatusListCredentialParams): StatusList2021Credential {
}: CreateStatusListCredentialParams): BitstringStatusListCredential {
return createCredential({
id: url,
type: "StatusList2021Credential",
type: "BitstringStatusListCredential",
issuer,
subject: `${url}#list`,
attestation: {
type: "StatusList2021",
type: "BitstringStatusList",
statusPurpose: "revocation",
encodedList
}
Expand Down
12 changes: 6 additions & 6 deletions packages/vc/src/revocation/types.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
import type { statusList2021ClaimSchema } from "../schemas/valibot"
import type { bitstringStatusListClaimSchema } from "../schemas/valibot"
import type { W3CCredential } from "../types"
import type * as v from "valibot"

type StatusList2021Entry = {
type BitstringStatusListEntry = {
id: string
type: "StatusList2021Entry"
type: "BitstringStatusListEntry"
statusPurpose: string
statusListIndex: string
statusListCredential: string
}

export type StatusList2021Credential = W3CCredential & {
credentialSubject: v.InferOutput<typeof statusList2021ClaimSchema>
export type BitstringStatusListCredential = W3CCredential & {
credentialSubject: v.InferOutput<typeof bitstringStatusListClaimSchema>
}

export type Revocable<T extends W3CCredential> = T & {
credentialStatus: StatusList2021Entry
credentialStatus: BitstringStatusListEntry
}
4 changes: 2 additions & 2 deletions packages/vc/src/schemas/valibot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ export const jwtProofSchema = v.object({
jwt: v.string()
})

export const statusList2021ClaimSchema = v.object({
export const bitstringStatusListClaimSchema = v.object({
id: v.string(),
type: v.literal("StatusList2021"),
type: v.literal("BitstringStatusList"),
statusPurpose: v.string(),
encodedList: v.string()
})
4 changes: 2 additions & 2 deletions packages/vc/src/schemas/zod/v3.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ export const jwtProofSchema = z.object({
jwt: z.string()
})

export const statusList2021ClaimSchema = z.object({
export const bitstringStatusListClaimSchema = z.object({
id: z.string(),
type: z.literal("StatusList2021"),
type: z.literal("BitstringStatusList"),
statusPurpose: z.string(),
encodedList: z.string()
})
4 changes: 2 additions & 2 deletions packages/vc/src/schemas/zod/v4.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ export const jwtProofSchema = z.object({
jwt: z.string()
})

export const statusList2021ClaimSchema = z.object({
export const bitstringStatusListClaimSchema = z.object({
id: z.string(),
type: z.literal("StatusList2021"),
type: z.literal("BitstringStatusList"),
statusPurpose: z.string(),
encodedList: z.string()
})
7 changes: 5 additions & 2 deletions packages/vc/src/verification/is-revoked.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { BitBuffer } from "bit-buffers"
import { isStatusListCredential } from "../revocation/is-status-list-credential"
import type { Revocable, StatusList2021Credential } from "../revocation/types"
import type {
BitstringStatusListCredential,
Revocable
} from "../revocation/types"
import type { W3CCredential } from "../types"

/**
Expand All @@ -21,7 +24,7 @@ export function isRevocable<T extends W3CCredential>(

async function fetchStatusList(
credential: Revocable<W3CCredential>
): Promise<StatusList2021Credential | undefined> {
): Promise<BitstringStatusListCredential | undefined> {
const statusListUrl = credential.credentialStatus.statusListCredential

try {
Expand Down
Loading