@openagentid/oas-attestation
v1.0.2
Published
W3C Verifiable Credentials and attestation types for OAS entities
Readme
@openagentid/oas-attestation
W3C Verifiable Credentials and attestation types for OAS entities.
This package provides credential construction, signing, and verification following the W3C Verifiable Credentials data model, extended with OAS-specific attestation types (security audits, behavior attestations, capability verifications, compliance attestations, expert endorsements, and community reviews).
Installation
npm i @openagentid/oas-attestationRequirements: Node.js >= 20, ESM-only.
Peer dependencies: @openagentid/oas-crypto.
Usage
Build and sign a credential
import {
CredentialBuilder,
AttestationType,
signCredential,
} from '@openagentid/oas-attestation';
import { OasKeyPair } from '@openagentid/oas-crypto';
const kp = await OasKeyPair.generate();
const unsigned = new CredentialBuilder()
.issuer('did:oas:l1fe:hmr:alice')
.issuanceDate('2026-01-01T00:00:00Z')
.attestationType(AttestationType.SecurityAudit)
.subject({
id: 'did:oas:l1fe:agent:bot',
auditor: 'SecureCo',
scope: 'full',
findings: 'no critical issues',
})
.build();
const signed = await signCredential(
unsigned,
kp,
'did:oas:l1fe:hmr:alice#key-1',
'2026-01-01T00:00:00Z',
);
console.log(signed.proof?.type); // 'Ed25519Signature2020'Verify a credential
import { verifyCredential } from '@openagentid/oas-attestation';
const valid = await verifyCredential(signed, issuerPublicKeyBytes);
console.log(valid); // trueVerify with temporal checks
import { verifyCredentialWithTime } from '@openagentid/oas-attestation';
// Also checks expiration and issuance date
const valid = await verifyCredentialWithTime(
signed,
issuerPublicKeyBytes,
new Date().toISOString(),
);Set an expiration date
const unsigned = new CredentialBuilder()
.issuer('did:oas:l1fe:hmr:alice')
.issuanceDate('2026-01-01T00:00:00Z')
.expirationDate('2027-01-01T00:00:00Z')
.subject({ id: 'did:oas:l1fe:agent:bot' })
.build();Custom attestation types
const unsigned = new CredentialBuilder()
.issuer('did:oas:l1fe:hmr:alice')
.issuanceDate('2026-01-01T00:00:00Z')
.attestationType('Custom:MyDomainSpecificAttestation')
.subject({ id: 'did:oas:l1fe:agent:bot', customField: 'value' })
.build();Check required fields for an attestation type
import { requiredFields, validateSubject, AttestationType } from '@openagentid/oas-attestation';
const fields = requiredFields(AttestationType.SecurityAudit);
console.log(fields); // ['auditor', 'scope', 'findings']
// Throws AttestationError if required fields are missing
validateSubject(AttestationType.SecurityAudit, {
auditor: 'SecureCo',
scope: 'full',
findings: 'none',
});API Reference
OasCredential (interface)
An OAS Verifiable Credential following the W3C VC data model.
interface OasCredential {
readonly '@context': ReadonlyArray<string>;
readonly type: ReadonlyArray<string>;
readonly issuer: string;
readonly issuanceDate: string;
readonly expirationDate?: string;
readonly credentialSubject: Readonly<Record<string, unknown>>;
readonly oasAttestationType?: AttestationTypeValue;
readonly proof?: CredentialProof;
}CredentialProof (interface)
interface CredentialProof {
readonly type: 'Ed25519Signature2020';
readonly created: string;
readonly verificationMethod: string;
readonly proofPurpose: 'assertionMethod';
readonly proofValue: string;
}CredentialBuilder (class)
Fluent builder for constructing OAS Verifiable Credentials.
class CredentialBuilder {
/** Sets the issuer DID. Required. */
issuer(did: string): this;
/** Sets the issuance date (ISO 8601). Required. */
issuanceDate(date: string): this;
/** Sets the optional expiration date (ISO 8601). */
expirationDate(date: string): this;
/** Sets the credential subject (claims about the entity). */
subject(claims: Record<string, unknown>): this;
/** Sets the OAS attestation type (standard or custom). */
attestationType(type: AttestationTypeValue): this;
/**
* Builds an unsigned credential.
* @returns A frozen OasCredential without a proof.
* @throws AttestationError if issuer or issuanceDate is missing.
*/
build(): OasCredential;
}AttestationType
Standard OAS attestation types.
const AttestationType = {
SecurityAudit: 'SecurityAudit',
BehaviorAttestation: 'BehaviorAttestation',
CapabilityVerification: 'CapabilityVerification',
ComplianceAttestation: 'ComplianceAttestation',
ExpertEndorsement: 'ExpertEndorsement',
CommunityReview: 'CommunityReview',
} as const;
type StandardAttestationType = (typeof AttestationType)[keyof typeof AttestationType];
/** Standard types or custom types prefixed with "Custom:". */
type AttestationTypeValue = StandardAttestationType | `Custom:${string}`;Required fields per attestation type:
| Type | Required fields |
|------|----------------|
| SecurityAudit | auditor, scope, findings |
| BehaviorAttestation | observedBehavior, period |
| CapabilityVerification | capability, verificationMethod |
| ComplianceAttestation | standard, status |
| ExpertEndorsement | domain, endorsement |
| CommunityReview | rating, review |
| Custom:* | (none -- custom types have no required fields) |
Functions
/**
* Signs an OAS Verifiable Credential with an Ed25519 keypair.
* Validates required fields for the attestation type before signing.
* @throws AttestationError on validation or signing failure.
*/
async function signCredential(
credential: OasCredential,
keypair: OasKeyPair,
verificationMethodId: string,
created: string,
): Promise<OasCredential>;
/**
* Verifies an OAS credential's proof signature.
* @throws AttestationError if the credential has no proof.
*/
async function verifyCredential(
credential: OasCredential,
issuerPublicKeyBytes: Uint8Array,
): Promise<boolean>;
/**
* Verifies a credential with temporal validation.
* Checks signature, expiration, and issuance date.
* @throws AttestationError if expired or not yet valid.
*/
async function verifyCredentialWithTime(
credential: OasCredential,
issuerPublicKeyBytes: Uint8Array,
now: string,
): Promise<boolean>;
/**
* Returns the required fields for a given attestation type.
* Returns an empty array for custom types.
*/
function requiredFields(type: AttestationTypeValue): ReadonlyArray<string>;
/**
* Validates that a credential subject contains all required fields.
* @throws AttestationError if required fields are missing.
*/
function validateSubject(
type: AttestationTypeValue,
subject: Record<string, unknown>,
): void;Constants
const VC_CONTEXT = 'https://www.w3.org/2018/credentials/v1';
const OAS_ATTESTATION_CONTEXT = 'https://openagent.id/ns/attestation/v1';Error classes
class AttestationError extends Error {
readonly code: AttestationErrorCode;
readonly details: Readonly<Record<string, unknown>>;
constructor(code: AttestationErrorCode, message: string, details?: Record<string, unknown>);
}
const AttestationErrorCode = {
InvalidIssuer: 'INVALID_ISSUER',
InvalidSubject: 'INVALID_SUBJECT',
UnknownAttestationType: 'UNKNOWN_ATTESTATION_TYPE',
MissingProof: 'MISSING_PROOF',
InvalidProofSignature: 'INVALID_PROOF_SIGNATURE',
ProofGenerationFailed: 'PROOF_GENERATION_FAILED',
Expired: 'EXPIRED',
NotYetValid: 'NOT_YET_VALID',
MissingField: 'MISSING_FIELD',
Json: 'JSON_ERROR',
Crypto: 'CRYPTO_ERROR',
} as const;
type AttestationErrorCode = (typeof AttestationErrorCode)[keyof typeof AttestationErrorCode];Dependencies
| Package | Purpose |
|---------|---------|
| @openagentid/oas-crypto | Ed25519 signing, JCS canonicalization, multibase encoding |
License
Copyright © 2026 L1fe Labs, Inc.
Licensed under either of Apache License 2.0 or MIT license, at your option.
