@gramota/issuer
Issuer for SD-JWT-VC, with single + batch issuance for one-time-use credential pools.
Install: pnpm add @gramota/issuer
Source: github.com/gramota-org/gramota/tree/main/packages/issuer
Classes
Issuer
Defined in: @gramota/issuer/dist/issuer.d.ts:33
The issuer role per IETF SD-JWT-VC §3.
Wraps issueSdJwt (the low-level primitive in @gramota/sd-jwt) with:
- stateful config (signer, issuer id, optional kid/typ/hashAlg),
- holder-binding (cnf.jwk),
- sensible expiry handling (
expiresInorexpiresAt), - validation: every claim listed in
selectivelyDisclosablemust appear insubject, - Signer Strategy for signing — accepts raw JWKs (shorthand) or production-grade Signers (HSM, KMS, custom backends).
Two API shapes resolve to the same code path:
issuer.credentials.issue(...)— Stripe-style namespacing, symmetric withholder.credentials.*and forward-compatible with future operations (revoke, suspend, list).issuer.issue(...)— flat shorthand for the common case.
Constructors
Constructor
new Issuer(config: IssuerConfig): Issuer;
Defined in: @gramota/issuer/dist/issuer.d.ts:45
Parameters
config
Returns
Properties
credentials
readonly credentials: IssuerCredentialsApi;
Defined in: @gramota/issuer/dist/issuer.d.ts:44
Credential operations. issuer.credentials.{issue,issueBatch}(...).
Mirrors holder.credentials.* for stylistic symmetry across the SDK.
Accessors
publicKey
Get Signature
get publicKey(): JsonWebKey;
Defined in: @gramota/issuer/dist/issuer.d.ts:67
The issuer's public JWK — useful to publish at /.well-known/jwks.json.
Returns
JsonWebKey
issuerId
Get Signature
get issuerId(): string;
Defined in: @gramota/issuer/dist/issuer.d.ts:69
The issuer's identifier — useful for downstream URLs.
Returns
string
Methods
issue()
issue(options: IssueOptions): Promise<IssueResult>;
Defined in: @gramota/issuer/dist/issuer.d.ts:50
Issue a single SD-JWT-VC credential bound to a holder.
Equivalent to issuer.credentials.issue(options). Both shapes are
stable; pick whichever reads better at the call site.
Parameters
options
Returns
Promise<IssueResult>
issueBatch()
issueBatch(options: BatchIssueOptions): Promise<readonly IssueResult[]>;
Defined in: @gramota/issuer/dist/issuer.d.ts:63
Issue N credentials in a batch — OID4VCI Draft 14/15 batch flow.
Equivalent to issuer.credentials.issueBatch(options). Each entry in
options.credentials produces one independent credential bound to
that entry's holderKey, with fresh disclosure salts (so two
credentials over the same claims are unlinkable on the wire) and a
distinct credentialId. Shared options (subject, vct, expiry, …)
apply to every credential.
The EU reference wallet uses this to mint pools of one-time-use credentials so each presentation reveals a fresh token rather than a long-lived one.
Parameters
options
Returns
Promise<readonly IssueResult[]>
IssuerError
Defined in: @gramota/issuer/dist/types.d.ts:127
Extends
GramotaError
Constructors
Constructor
new IssuerError(
code: IssuerErrorCode,
message: string,
options?: {
cause?: unknown;
}): IssuerError;
Defined in: @gramota/issuer/dist/types.d.ts:129
Parameters
code
message
string
options?
cause?
unknown
Returns
Overrides
GramotaError.constructor
Properties
cause?
readonly optional cause?: unknown;
Defined in: .pnpm/@gramota+core@0.2.1/node_modules/@gramota/core/dist/error.d.ts:44
Optional original error that caused this one. Always set when the
Gramota package is wrapping a thrown exception from a dependency
(Web Crypto, JOSE, fetch). Survives JSON.stringify(err) only via
the cause property — Node 16.9+ logs it natively.
Inherited from
GramotaError.cause
code
readonly code: IssuerErrorCode;
Defined in: @gramota/issuer/dist/types.d.ts:128
Stable string that identifies the failure mode. Subclasses narrow the type; at runtime it's always a string. Use for branching, logs, and metrics labels — never serialize GramotaError.message for that purpose, message strings drift across versions.
Overrides
GramotaError.code
name
name: string;
Defined in: .pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es5.d.ts:1076
Inherited from
GramotaError.name
message
message: string;
Defined in: .pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es5.d.ts:1077
Inherited from
GramotaError.message
stack?
optional stack?: string;
Defined in: .pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es5.d.ts:1078
Inherited from
GramotaError.stack
Interfaces
IssuerCredentialsApi
Defined in: @gramota/issuer/dist/issuer.d.ts:5
Stripe-style sub-API for credential operations.
issuer.credentials.X(...).
Methods
issue()
issue(options: IssueOptions): Promise<IssueResult>;
Defined in: @gramota/issuer/dist/issuer.d.ts:7
Issue a single SD-JWT-VC credential bound to a holder.
Parameters
options
Returns
Promise<IssueResult>
issueBatch()
issueBatch(options: BatchIssueOptions): Promise<readonly IssueResult[]>;
Defined in: @gramota/issuer/dist/issuer.d.ts:13
Issue N credentials in a batch, one per holder-key entry — the
OID4VCI Draft 14/15 batch flow. The EU reference wallet asks for
numberOfCredentials = 10 so it can use a fresh credential per
presentation (one-time use, unlinkable). Each entry gets its own
cnf.jwk, fresh disclosure salts, and a distinct credentialId.
Parameters
options
Returns
Promise<readonly IssueResult[]>
IssueOptions
Defined in: @gramota/issuer/dist/types.d.ts:37
Properties
subject
subject: Readonly<Record<string, unknown>>;
Defined in: @gramota/issuer/dist/types.d.ts:41
All claims that will go into the credential. Top-level keys become
either selectively-disclosable disclosures or directly-visible payload
claims, controlled by selectivelyDisclosable.
selectivelyDisclosable?
optional selectivelyDisclosable?: readonly string[];
Defined in: @gramota/issuer/dist/types.d.ts:44
Names of subject keys to make selectively disclosable. Names that
don't appear in subject cause an error. Default: empty (no SD).
holderKey
holderKey: JsonWebKey;
Defined in: @gramota/issuer/dist/types.d.ts:47
Holder's PUBLIC JWK — bound into cnf.jwk. Required by SD-JWT-VC for
holder-binding (the security model collapses without it).
vct
vct: string;
Defined in: @gramota/issuer/dist/types.d.ts:51
SD-JWT-VC credential type identifier — required by the spec. Customers
who really know what they're doing can pass an empty string to skip,
but the default behaviour rejects missing vct.
expiresIn?
optional expiresIn?: number;
Defined in: @gramota/issuer/dist/types.d.ts:54
Seconds-until-expiry, relative to issuedAt. Mutually exclusive with
expiresAt.
expiresAt?
optional expiresAt?: number;
Defined in: @gramota/issuer/dist/types.d.ts:56
Absolute expiry as Unix seconds. Mutually exclusive with expiresIn.
notBefore?
optional notBefore?: number;
Defined in: @gramota/issuer/dist/types.d.ts:58
Optional nbf (not-before) claim.
issuedAt?
optional issuedAt?: number;
Defined in: @gramota/issuer/dist/types.d.ts:60
Override iat — defaults to floor(Date.now()/1000) at call time.
status?
optional status?: Readonly<Record<string, unknown>>;
Defined in: @gramota/issuer/dist/types.d.ts:62
Optional status claim for revocation tracking (Token Status List).
credentialId?
optional credentialId?: string;
Defined in: @gramota/issuer/dist/types.d.ts:64
Override the generated credential ID (default: random UUID v4).
IssueResult
Defined in: @gramota/issuer/dist/types.d.ts:67
Result of issuer.issue().
Properties
token
token: string;
Defined in: @gramota/issuer/dist/types.d.ts:69
The compact-serialised SD-JWT-VC token to send to the holder.
credentialId
credentialId: string;
Defined in: @gramota/issuer/dist/types.d.ts:71
Issuer-side identifier for tracking.
disclosures
disclosures: readonly SdJwtDisclosure[];
Defined in: @gramota/issuer/dist/types.d.ts:73
Disclosure objects — useful for the issuer's own records / audit logs.
expiresAt
expiresAt: number;
Defined in: @gramota/issuer/dist/types.d.ts:75
Computed expiry (if expiresIn or expiresAt was set).
BatchIssueEntry
Defined in: @gramota/issuer/dist/types.d.ts:82
Per-credential binding for issueBatch. Everything that varies across
credentials in the batch goes here; everything shared (subject, vct,
expiry, …) sits at the top level of BatchIssueOptions.
Properties
holderKey
holderKey: JsonWebKey;
Defined in: @gramota/issuer/dist/types.d.ts:85
Holder's PUBLIC JWK — bound into this credential's cnf.jwk. Each
entry must have a distinct holder key for one-time-use unlinkability.
credentialId?
optional credentialId?: string;
Defined in: @gramota/issuer/dist/types.d.ts:87
Override the generated credential ID (default: random UUID v4 per entry).
status?
optional status?: Readonly<Record<string, unknown>>;
Defined in: @gramota/issuer/dist/types.d.ts:91
Per-credential status claim — typical use is to allocate a distinct
Token Status List index for each one-time credential so they can be
revoked independently.
BatchIssueOptions
Defined in: @gramota/issuer/dist/types.d.ts:102
Options for issuer.issueBatch() (OID4VCI Draft 14/15 batch issuance).
Shared across the batch: subject, vct, expiry, notBefore, issuedAt, selectivelyDisclosable.
Per-credential: credentials[i] (holderKey, optional credentialId,
optional status).
Properties
subject
subject: Readonly<Record<string, unknown>>;
Defined in: @gramota/issuer/dist/types.d.ts:105
Claims shared by every credential in the batch. Same semantics as IssueOptions.subject.
vct
vct: string;
Defined in: @gramota/issuer/dist/types.d.ts:107
SD-JWT-VC type identifier — shared across the batch.
selectivelyDisclosable?
optional selectivelyDisclosable?: readonly string[];
Defined in: @gramota/issuer/dist/types.d.ts:112
Names of subject keys to make selectively disclosable. Validated
once against subject; applies to every credential. Each credential
gets fresh random salts (so two credentials over the same data are
unlinkable on the wire).
expiresIn?
optional expiresIn?: number;
Defined in: @gramota/issuer/dist/types.d.ts:114
Shared expiresIn. Mutually exclusive with expiresAt.
expiresAt?
optional expiresAt?: number;
Defined in: @gramota/issuer/dist/types.d.ts:116
Shared absolute expiresAt. Mutually exclusive with expiresIn.
notBefore?
optional notBefore?: number;
Defined in: @gramota/issuer/dist/types.d.ts:118
Shared nbf.
issuedAt?
optional issuedAt?: number;
Defined in: @gramota/issuer/dist/types.d.ts:121
Shared iat. Defaults to floor(Date.now()/1000) evaluated once
for the whole batch (so every credential reports the same iat).
credentials
credentials: readonly BatchIssueEntry[];
Defined in: @gramota/issuer/dist/types.d.ts:123
One entry per credential to issue. Length ≥ 1.
Type Aliases
IssuerConfig
type IssuerConfig = IssuerSignerInput & {
issuerId: string;
hashAlg?: HashAlg;
kid?: string;
typ?: string;
};
Defined in: @gramota/issuer/dist/types.d.ts:27
Configuration for an Issuer instance — set once, used per issue().
Type Declaration
issuerId
issuerId: string;
Issuer identifier (a stable URL). Becomes the iss claim.
hashAlg?
optional hashAlg?: HashAlg;
Hash algorithm for selective-disclosure digests. Default sha-256.
kid?
optional kid?: string;
JOSE kid header to set on every issued credential. Optional.
typ?
optional typ?: string;
JOSE typ header. Default vc+sd-jwt (per SD-JWT-VC spec).
IssuerErrorCode
type IssuerErrorCode =
| "issuer.subject_invalid"
| "issuer.holder_key_required"
| "issuer.vct_required"
| "issuer.expiry_conflict"
| "issuer.expiry_invalid"
| "issuer.disclosable_missing"
| "issuer.reserved_claim_in_subject"
| "issuer.batch_empty";
Defined in: @gramota/issuer/dist/types.d.ts:126
Stable codes for IssuerError.