@tinycloud/web-sdk 3.9.0-beta.4 → 3.9.0-beta.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,6 +2,12 @@ import { CredentialError, type IKVService } from "@tinycloud/sdk-core";
2
2
  import { type HeldEmailCredentialOptions, type VerifiedHeldEmailCredential } from "@tinycloud/sdk-core/held-credentials";
3
3
  /** A held record whose verified expiry is within this many milliseconds is not offered; the caller re-acquires. */
4
4
  export declare const HELD_REUSE_MARGIN_MS = 600000;
5
+ /**
6
+ * Fixed, non-secret marker (`details.state`) on a `VERIFIED_NOT_SAVED` error whose write or read-back was refused by a typed kv 401 or 403: the
7
+ * credential was issued and verified but the app session may not store it. The error keeps its code; nothing from the kv error (message, address,
8
+ * space, token) is attached.
9
+ */
10
+ export declare const HELD_STORE_PERMISSION_DENIED_STATE = "permission_denied";
5
11
  /** Issuer policy for the S3.1 verifier. The owner and the clock are supplied per call. */
6
12
  export type HeldIssuerPolicy = Omit<HeldEmailCredentialOptions, "owner" | "now">;
7
13
  /**
@@ -84,7 +90,9 @@ export interface FindHeldCredentialInput extends HeldIssuerPolicy {
84
90
  }
85
91
  /**
86
92
  * Owner-scoped read. Lists only `v1/held/<registryKey>/`, so `v1/records/` is never considered.
87
- * Returns the verified record with the latest expiry that still clears the reuse margin, or undefined.
93
+ * Returns the verified record with the latest expiry that still clears the reuse margin, or undefined. A failed list is "not found" (looser than
94
+ * `listHeldEmailCredentials`), EXCEPT a list or get the app may not make: that throws `PERMISSION_DENIED`, because "not found" there would send the
95
+ * caller to acquire a credential (a mailed code) that its session then cannot store.
88
96
  */
89
97
  export declare function findHeldCredential(input: FindHeldCredentialInput): Promise<HeldMatch | undefined>;
90
98
  export type ListHeldEmailCredentialsInput = Omit<FindHeldCredentialInput, "email"> & {
@@ -108,8 +116,8 @@ export type ListHeldEmailCredentialsInput = Omit<FindHeldCredentialInput, "email
108
116
  * malformed or fails verification is skipped silently, never reported and never thrown. A store failure is
109
117
  * not a bad record, so the screen can tell "none" from "unreachable": a `kv.get` or `kv.list` that throws
110
118
  * propagates, and one that resolves not-ok is an `OFFLINE` CredentialError (a key that is gone by the time it
111
- * is read, `KV_NOT_FOUND`, is skipped). A refused owner, or a listing that is truncated or beyond the page
112
- * limit, also throws. `findHeldCredential` is looser: it reads a failed `kv.list` as "not found".
119
+ * is read, `KV_NOT_FOUND`, is skipped). A call the app session may not make (a typed 401 or 403 from kv) is `PERMISSION_DENIED`, not `OFFLINE`. A refused owner, or a listing that is truncated or beyond the page
120
+ * limit, also throws. `findHeldCredential` is looser: it reads a failed `kv.list` as "not found" (but not a permission failure).
113
121
  * Every returned summary field comes from the re-verified credential, never from other stored fields.
114
122
  * `record` is the raw stored value; only the `verified` fields and the summary above are authoritative.
115
123
  */
@@ -1 +1 @@
1
- (()=>{"use strict";var e={d:(t,r)=>{for(var i in r)e.o(r,i)&&!e.o(t,i)&&Object.defineProperty(t,i,{enumerable:!0,get:r[i]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t),r:e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})}},t={};e.r(t),e.d(t,{EmailProofError:()=>U,OpenCredentialsHttpTransport:()=>h,acquireEmailProof:()=>$,acquireHeldCredential:()=>Ve,completeEmailProof:()=>M,createAccountHolderSigner:()=>Ee,createEd25519HolderSigner:()=>x,createMemoryEmailProofPendingStore:()=>V,findHeldCredential:()=>qe,interpretCredentialFlow:()=>c,listHeldEmailCredentials:()=>Le,requestEmailProofCode:()=>B,storeHeldCredential:()=>_e,verifyStoredEmailProof:()=>te});const r=require("@tinycloud/sdk-core"),i=require("@tinycloud/sdk-core/held-credentials");var n=Object.freeze({witnessOrigin:"https://witness.credentials.org",issuerDid:"did:web:issuer.credentials.org",issuerKid:"did:web:issuer.credentials.org#controller",issuerX:"eEJI4xEobto4HtQ7Pg9R1vBOwcpfGRTlXDG5QfqLnGQ",descriptorDigest:"1tg-qphmKBVtNwzVg9xyz-xxqt_xtMXAsQyXw46m8S0"}),s=Object.freeze({type:r.ACCOUNT_HOLDER_BINDING_DOMAIN,protocol:"tinycloud.credentials/acquisition/v1",profile:"tinycloud.email-held/v1",profileVersion:1,descriptorDigest:"dc3_DuvzipXwYkTfjKqTaK1c3VS0YSPnaBsYSQriC0w",issuer:n.issuerDid,issuerKid:n.issuerKid,audience:"tinycloud://credentials",openerOrigin:"https://localhost",completionOrigin:"https://localhost",completionContext:"sdk-acquisition",credentialLifetimeSeconds:31536e3}),o=6e5,a=()=>new r.CredentialError("REQUEST_SUBSTITUTED","Holder binding was substituted"),d=(e,t)=>new Promise((r,i)=>{const n=setTimeout(r,e);t?.addEventListener("abort",()=>{clearTimeout(n),i(new DOMException("Aborted","AbortError"))},{once:!0})});async function c(e){const t="account_is_subject"===e.descriptor.subjectRelationship;if(t&&!0!==e.allowAccountSubject)throw new r.CredentialError("UNSUPPORTED_PROFILE","The held credential profile requires an explicit opt-in");const i=new Map(e.descriptor.steps.map(e=>[e.type,e])),n=new Set;let c="";const l=async t=>{const i=(0,r.validateCredentialHolderBinding)(t);if(i.requestId!==e.requestId||i.descriptorDigest!==e.descriptorDigest||i.requirementDigest!==e.requirementDigest||i.holderDid!==e.holderDid||i.issuer!==e.descriptor.issuer.did||i.issuerKid!==e.descriptor.issuer.kid||i.profile!==e.descriptor.profile||i.openerOrigin!==e.openerOrigin||i.completionOrigin!==e.openerOrigin||"tinycloud://credentials"!==i.audience)throw new r.CredentialError("REQUEST_SUBSTITUTED","Holder binding was substituted");const n=e.descriptor.holderBinding.alg;if(i.type!==e.descriptor.holderBinding.domain||"EIP191"===n&&!e.transport.challengeNonce)throw new r.CredentialError("REQUEST_SUBSTITUTED","Holder binding was substituted");return"EIP191"===n&&await async function(e,t){const{descriptor:i}=t;if("EIP191"!==i.holderBinding.alg||e.type!==i.holderBinding.domain||e.requestId!==t.requestId||e.descriptorDigest!==t.descriptorDigest||e.requirementDigest!==t.requirementDigest||e.holderDid!==t.holderDid||e.issuer!==i.issuer.did||e.issuerKid!==i.issuer.kid||e.profile!==i.profile||e.openerOrigin!==t.openerOrigin||e.completionOrigin!==t.openerOrigin||e.audience!==s.audience||e.completionContext!==s.completionContext||e.type!==s.type||e.protocol!==s.protocol||e.profile!==s.profile||e.profileVersion!==s.profileVersion||e.descriptorDigest!==s.descriptorDigest||e.issuer!==s.issuer||e.issuerKid!==s.issuerKid||e.openerOrigin!==s.openerOrigin||e.completionOrigin!==s.completionOrigin||e.credentialLifetimeSeconds!==s.credentialLifetimeSeconds)throw a();if(void 0===t.challengeNonce||e.challengeNonce!==t.challengeNonce)throw a();if(e.normalizedClaimsDigest!==await(0,r.canonicalDigest)(t.requirement.claims))throw a();const n=Date.parse(e.expiresAt);if(void 0===t.serverExpiresAt||n!==Date.parse(t.serverExpiresAt)||Date.parse(e.issuedAt)!==n-o)throw a()}(i,{descriptor:e.descriptor,requirement:e.requirement,requestId:e.requestId,descriptorDigest:e.descriptorDigest,requirementDigest:e.requirementDigest,holderDid:e.holderDid,openerOrigin:e.openerOrigin,challengeNonce:e.transport.challengeNonce(e.requestId),serverExpiresAt:e.expiresAt}),i},u=async()=>{t&&void 0===e.transport.signedBinding?.(e.requestId)&&await l(await e.transport.holderBinding(e.requestId,e.verifier,e.signal))};for(;;){e.signal?.throwIfAborted();const t=await e.transport.state(e.requestId,e.verifier,e.signal);if(t.requestId!==e.requestId)throw new r.CredentialError("REQUEST_SUBSTITUTED","Credential request identity changed");if("expired"===t.state)throw new r.CredentialError("REQUEST_EXPIRED","Credential request expired",{state:t.state,correlationId:t.correlationId});if("canceled"===t.state)throw new r.CredentialError("CANCELED","Credential request was canceled",{state:t.state,correlationId:t.correlationId});if("issuer_unready"===t.state)throw new r.CredentialError("ISSUER_UNREADY","Credential issuer is not ready",{retryAfterMs:t.retryAfterMs,state:t.state,correlationId:t.correlationId});if("complete"===t.state)return void await u();if("ready_to_issue"===t.state||"issued"===t.state){await u(),"ready_to_issue"!==t.state||n.has("issue")?await(e.onWait?.()??d(t.retryAfterMs??50,e.signal)):(await e.transport.issue(e.requestId,e.verifier,e.signal),n.add("issue"));continue}const s=t.nextStep;if(!s){await(e.onWait?.()??d(t.retryAfterMs??50,e.signal));continue}const o=i.get(s.type);if(s.id!==s.type||!o||o.type!==s.type||o.version!==s.version)throw new r.CredentialError("REQUEST_SUBSTITUTED","Server selected an undeclared credential step");if(n.has(s.id)||t.transitionId===c)await(e.onWait?.()??d(t.retryAfterMs??50,e.signal));else{if(c=t.transitionId,"holder_signature"===s.type){e.onProgress?.({state:"signing",stepId:s.id,correlationId:t.correlationId});const i=await l(await e.transport.holderBinding(e.requestId,e.verifier,e.signal)),n=e.descriptor.holderBinding.alg;if("EIP191"===n!=("EIP191"===e.signing.holderKey?.alg))throw new r.CredentialError("REQUEST_SUBSTITUTED","Holder binding was substituted");const o=(0,r.holderBindingSigningBytes)(i);let a=await(e.signing.autoSign?.(i,o,e.signal));if(void 0===a){if(!e.signing.requestApproval)throw new r.CredentialError("SIGNATURE_REJECTED","OpenKey approval is required");try{a=await e.signing.requestApproval(i,o,e.signal)}catch(e){if(e instanceof r.CredentialError)throw e;throw new r.CredentialError("SIGNATURE_REJECTED","OpenKey approval was rejected",{cause:e})}}if(!(a instanceof Uint8Array)||0===a.length)throw new r.CredentialError("SIGNATURE_REJECTED","OpenKey signature is invalid");await e.transport.submitHolderSignature(e.requestId,e.verifier,"EIP191"===n?`0x${Array.from(a,e=>e.toString(16).padStart(2,"0")).join("")}`:(0,r.encodeBase64Url)(a),e.signal,e.signing.holderKey)}else{e.onProgress?.({state:"collect_input"===s.type?"collecting":"proving",stepId:s.id,correlationId:t.correlationId});const i=e.handlers?.[s.type],n=e.proofHandler;if(!i&&!n){await(e.onWait?.()??d(t.retryAfterMs??50,e.signal));continue}if(!0===s.constraints.challengeRequired&&await e.transport.beginStep(e.requestId,e.verifier,s.type,e.signal),i){const t=await i({descriptor:e.descriptor,requirement:e.requirement,stepId:s.id,constraints:s.constraints,signal:e.signal});await e.transport.submitStep(e.requestId,e.verifier,s.id,t,e.signal)}else{let t;for(let i=1;;i+=1){const o=await n({stepId:s.id,constraints:s.constraints,display:{title:e.descriptor.display.title,description:e.descriptor.display.description,consent:e.descriptor.display.consent,progressLabel:e.descriptor.accessibility.progressLabel,errorLiveRegion:e.descriptor.accessibility.errorLiveRegion},inputs:e.descriptor.inputs.map(({id:e,label:t,schema:r})=>({id:e,label:t,schema:r})),...void 0===t?{}:{feedback:t},signal:e.signal});try{await e.transport.submitStep(e.requestId,e.verifier,s.id,o,e.signal);break}catch(n){if(!(n instanceof r.CredentialError)||"PROOF_REJECTED"!==n.code)throw n;const o=e.descriptor.lifecycle.maxProofAttempts-i;if("mailbox_otp"!==s.type||o<=0)throw new r.CredentialError("VERIFICATION_FAILED","The proof was not accepted",{state:o<=0?"proof_attempts_exhausted":"proof_rejected",cause:n});t={kind:"rejected",attemptsRemaining:o}}}}}n.add(s.id)}}}function l(e,t){if("object"!=typeof e||null===e||Array.isArray(e))throw new r.CredentialError("VERIFICATION_FAILED",`${t} is invalid`);return e}function u(e,t){if("string"!=typeof e||!/^[A-Za-z0-9_-]{16,128}$/.test(e))throw new r.CredentialError("REQUEST_SUBSTITUTED",`${t} is invalid`);return e}function p(e,t){if("string"!=typeof e||!Number.isFinite(Date.parse(e)))throw new r.CredentialError("VERIFICATION_FAILED",`${t} is invalid`);return new Date(e).toISOString()}var f=new Set(["REQUEST_EXPIRED","ISSUER_UNREADY","UNSUPPORTED_PROFILE","UNSUPPORTED_VERSION","SIGNATURE_REJECTED"]),h=class{constructor(e,t=globalThis.fetch.bind(globalThis),i={}){if(this.descriptor=e,this.fetchFn=t,this.options=i,this.nonces=new Map,this.bindings=new Map,"account_is_subject"===e.subjectRelationship&&!0!==i.allowAccountSubject)throw new r.CredentialError("UNSUPPORTED_PROFILE","The held credential profile requires an explicit opt-in")}url(e,t){return new URL((0,r.credentialEndpointPath)(e,t),this.descriptor.issuer.origin).href}async request(e,t){let i;try{const r={method:t.method??"GET",credentials:"omit",cache:"no-store",redirect:"error",referrerPolicy:"no-referrer",signal:t.signal,headers:{accept:"application/json",...void 0===t.body?{}:{"content-type":"application/json"},...void 0===t.verifier?{}:{authorization:`Bearer ${t.verifier}`}},...void 0===t.body?{}:{body:JSON.stringify(t.body)}};i=await this.fetchFn(this.url(e,t.id),r)}catch(e){if(e instanceof DOMException&&"AbortError"===e.name)throw new r.CredentialError("CANCELED","Credential acquisition was canceled",{cause:e});throw new r.CredentialError("OFFLINE","OpenCredentials is unavailable",{cause:e})}if(!i.ok){let e;try{e=await i.json()}catch{e=void 0}const t=function(e,t,i){if("object"!=typeof e||null===e||Array.isArray(e))return;const n=e;if("code,correlationId,recoverable,state,type"!==Object.keys(n).sort().join(",")||"tinycloud.credentials/error/v1"!==n.type||"string"!=typeof n.code||"boolean"!=typeof n.recoverable||"string"!=typeof n.state||"string"!=typeof n.correlationId)return;if("PROOF_REJECTED"===n.code)return n.recoverable?new r.CredentialError("PROOF_REJECTED","The proof was not accepted",{state:n.state,correlationId:n.correlationId}):new r.CredentialError("VERIFICATION_FAILED","The proof attempt limit was reached",{state:"proof_attempts_exhausted",correlationId:n.correlationId});if("RATE_LIMITED"===n.code)return new r.CredentialError("ISSUER_UNREADY","Too many verification codes were requested",{state:"rate_limited",correlationId:n.correlationId,retryAfterMs:1e3*Number(t.headers.get("retry-after"))||void 0,recoverable:i?n.recoverable:void 0});if("CHALLENGE_EXPIRED"===n.code)return new r.CredentialError("REQUEST_EXPIRED","The credential challenge expired",{state:n.state,correlationId:n.correlationId,recoverable:i?n.recoverable:void 0});if("DESCRIPTOR_MISMATCH"===n.code&&(n.code="UNSUPPORTED_PROFILE"),!f.has(n.code))return;const s=n.code;return new r.CredentialError(s,`OpenCredentials rejected the request: ${s}`,{state:n.state,correlationId:n.correlationId,retryAfterMs:1e3*Number(t.headers.get("retry-after"))||void 0,recoverable:i?n.recoverable:void 0})}(e,i,!0===this.options.honorServerRecoverable);if(t)throw t;if(410===i.status)throw new r.CredentialError("REQUEST_EXPIRED","Credential request expired");if(409===i.status)throw new r.CredentialError("REQUEST_SUBSTITUTED","Credential request was replayed or substituted");if(503===i.status)throw new r.CredentialError("ISSUER_UNREADY","Credential issuer is not ready",{retryAfterMs:1e3*Number(i.headers.get("retry-after"))||void 0});throw new r.CredentialError("VERIFICATION_FAILED","OpenCredentials rejected the request")}if(204!==i.status)try{return await i.json()}catch(e){throw new r.CredentialError("VERIFICATION_FAILED","OpenCredentials response is invalid",{cause:e})}}async create(e){const t=l(await this.request("request",{method:"POST",body:{protocol:e.descriptor.protocol,profile:e.descriptor.profile,profileVersion:e.descriptor.profileVersion,descriptorDigest:e.descriptorDigest,requirementDigest:e.requirementDigest,holderDid:e.holderDid,inputs:e.inputs??e.requirement.claims,audience:s.audience,openerOrigin:e.openerOrigin,completionOrigin:e.openerOrigin,completionContext:s.completionContext,completionVerifierChallenge:e.completionVerifierChallenge},signal:e.signal}),"create response");if("tinycloud.credentials/acquisition-request/v1"!==t.type||t.protocol!==e.descriptor.protocol||"challenge"!==t.next||"challenge"!==t.endpoint)throw new r.CredentialError("VERIFICATION_FAILED","create response is invalid");const i=u(t.requestId,"requestId");return{requestId:i,locator:i,expiresAt:p(t.expiresAt,"expiresAt"),correlationId:i}}challengeNonce(e){return this.nonces.get(e)}signedBinding(e){return this.bindings.get(e)}proofStep(){return this.descriptor.steps.some(e=>"mailbox_otp"===e.type)?"mailbox_otp":"collect_input"}async state(e,t,i){const n=l(await this.request("state",{id:e,verifier:t,signal:i}),"state response");if("tinycloud.credentials/acquisition-state/v1"!==n.type||n.requestId!==e||n.profile!==this.descriptor.profile||1!==n.profileVersion)throw new r.CredentialError("REQUEST_SUBSTITUTED","Credential state response is substituted");const s={type:"OpenCredentialsAcquisitionState",version:1,requestId:e,transitionId:`${String(n.state)}:${String(n.resultPreviouslyRead??!1)}`,correlationId:e};if("challenge_required"===n.state){const e=this.proofStep();return{...s,state:"pending",nextStep:{id:e,type:e,version:1,constraints:{challengeRequired:!0}}}}if("account_is_subject"===this.descriptor.subjectRelationship&&("proof_required"===n.state||"holder_binding_required"===n.state||"holder_signature_required"===n.state||"ready_to_issue"===n.state||"issued"===n.state)){const t=n.challengeNonce,i=this.nonces.get(e);if("string"!=typeof t||""===t||void 0!==i&&i!==t)throw new r.CredentialError("REQUEST_SUBSTITUTED","Credential challenge nonce is missing or changed");this.nonces.set(e,u(t,"challengeNonce"))}if("proof_required"===n.state){const t=this.proofStep();return"account_is_subject"!==this.descriptor.subjectRelationship&&this.nonces.set(e,u(n.challengeNonce,"challengeNonce")),{...s,state:"pending",nextStep:{id:t,type:t,version:1,constraints:{}}}}if("holder_binding_required"===n.state||"holder_signature_required"===n.state)return{...s,state:"pending",nextStep:{id:"holder_signature",type:"holder_signature",version:1,constraints:{}}};if("ready_to_issue"===n.state)return{...s,state:"ready_to_issue"};if("issued"===n.state)return{...s,state:"complete"};throw new r.CredentialError("REQUEST_SUBSTITUTED","Credential state is unsupported")}async beginStep(e,t,i,n){const s=this.proofStep();if(i!==s)throw new r.CredentialError("REQUEST_SUBSTITUTED","Credential challenge step is substituted");const o=l(await this.request("challenge",{id:e,verifier:t,method:"POST",body:{step:s,stepVersion:1},signal:n}),"challenge response");if("tinycloud.credentials/challenge/v1"!==o.type||o.step!==s||1!==o.stepVersion)throw new r.CredentialError("REQUEST_SUBSTITUTED","Credential challenge is substituted");this.nonces.set(e,u(o.challengeNonce,"challengeNonce"))}async submitStep(e,t,i,n,s){const o=this.proofStep();if(i!==o)throw new r.CredentialError("REQUEST_SUBSTITUTED","Credential proof step is substituted");const a=this.nonces.get(e);if(!a)throw new r.CredentialError("REQUEST_SUBSTITUTED","Credential challenge is missing");await this.request("proof",{id:e,verifier:t,method:"POST",body:{step:o,stepVersion:1,challengeNonce:a,proof:n},signal:s})}async holderBinding(e,t,i){const n=l(await this.request("holder_binding",{id:e,verifier:t,signal:i}),"holder binding response");if("tinycloud.credentials/holder-binding-request/v1"!==n.type||n.signingDomain!==this.descriptor.holderBinding.domain||n.alg!==this.descriptor.holderBinding.alg||"string"!=typeof n.canonical)throw new r.CredentialError("REQUEST_SUBSTITUTED","Holder binding response is invalid");const s=(0,r.validateCredentialHolderBinding)(n.binding);if(s.type!==n.signingDomain)throw new r.CredentialError("REQUEST_SUBSTITUTED","Holder binding type does not match its signing domain");if((0,r.encodeBase64Url)((0,r.holderBindingCanonicalBytes)(s))!==n.canonical)throw new r.CredentialError("REQUEST_SUBSTITUTED","Holder binding canonical bytes were substituted");return this.bindings.set(e,s),s}async submitHolderSignature(e,t,i,n,s){const o=this.bindings.get(e);if(!o)throw new r.CredentialError("REQUEST_SUBSTITUTED","Holder binding was not retrieved");if("EIP191"===this.descriptor.holderBinding.alg&&!s)throw new r.CredentialError("REQUEST_SUBSTITUTED","An account holder must name its key and algorithm");const a=s?.alg??"EdDSA",d=s?.kid??`${o.holderDid}#${o.holderDid.replace("did:key:","")}`;await this.request("holder_signature",{id:e,verifier:t,method:"POST",body:{alg:a,kid:d,signature:i},signal:n})}async issue(e,t,r){await this.request("issue",{id:e,verifier:t,method:"POST",signal:r})}async result(e,t,i){const n=l(await this.request("result",{id:e,verifier:t,signal:i}),"result response");if("tinycloud.credentials/result/v1"!==n.type||n.protocol!==this.descriptor.protocol||n.profile!==this.descriptor.profile||1!==n.profileVersion||"vc+sd-jwt"!==n.format||n.descriptorDigest!==await(0,r.canonicalDigest)(this.descriptor)||n.issuer!==this.descriptor.issuer.did||n.issuerKid!==this.descriptor.issuer.kid||"string"!=typeof n.credential||await(0,r.sha256Base64Url)(n.credential)!==n.credentialDigest)throw new r.CredentialError("VERIFICATION_FAILED","Issued result metadata is invalid");const s=l(n.holderBinding,"result holder binding");if(n.subject!==s.did||s.signingDomain!==this.descriptor.holderBinding.domain)throw new r.CredentialError("HOLDER_MISMATCH","Issued holder binding is invalid");const o=l(n.claims,"result claims"),a={};for(const[e,t]of Object.entries(o)){if("string"!=typeof t)throw new r.CredentialError("VERIFICATION_FAILED","Issued claims are invalid");a[e]=t}const d=l(n.validity,"result validity"),c=function(e){const t=e.split("~",1)[0]?.split(".")[1];if(!t)throw new r.CredentialError("VERIFICATION_FAILED","Issued SD-JWT is invalid");try{return l(JSON.parse((new TextDecoder).decode((0,r.decodeBase64Url)(t))),"SD-JWT payload")}catch(e){if(e instanceof r.CredentialError)throw e;throw new r.CredentialError("VERIFICATION_FAILED","Issued SD-JWT is invalid",{cause:e})}}(n.credential);if("string"!=typeof c.jti)throw new r.CredentialError("VERIFICATION_FAILED","Credential id is invalid");const u=p(d.issuedAt,"issuedAt"),f=p(d.expiresAt,"expiresAt"),h=l(n.status,"result status");if("none"!==h.type||h.freshnessSeconds!==this.descriptor.status.freshnessSeconds)throw new r.CredentialError("VERIFICATION_FAILED","Credential status is invalid");return{type:"OpenCredentialsIssuedCredential",version:1,protocol:this.descriptor.protocol,profile:{id:this.descriptor.profile,version:1},credentialType:{id:this.descriptor.format.vct,version:1},schema:this.descriptor.format.vct,format:"vc+sd-jwt",issuerDid:n.issuer,issuerKid:n.issuerKid,subjectDid:n.subject,holderDid:n.subject,claims:a,claimsDigest:await(0,r.canonicalDigest)(a),descriptorDigest:n.descriptorDigest,credentialId:c.jti,issuedAt:u,notBefore:u,expiresAt:f,status:{method:"none",freshnessSeconds:h.freshnessSeconds},credential:n.credential}}async issuerMetadata(e){return await this.request("issuer_metadata",{signal:e})}async checkStatus(e,t){return"none"===e.method&&e.freshnessSeconds===this.descriptor.status.freshnessSeconds}},E={id:"opencredentials.email/v1",version:1},w=9e5,g=`${n.witnessOrigin}/.well-known/opencredentials`,I=[{kid:n.issuerKid,alg:"EdDSA",jwk:{kty:"OKP",crv:"Ed25519",x:n.issuerX},validFrom:"2020-01-01T00:00:00Z",validUntil:"2100-01-01T00:00:00Z"}],D="tinycloud.email-proof/v1",m={"tinycloud.email-proof/v1":{descriptorDigest:n.descriptorDigest,requiredStep:"mailbox_otp",enabled:!0},"tinycloud.email-held/v1":{descriptorDigest:s.descriptorDigest,requiredStep:"mailbox_otp",enabled:!1}},A=s.openerOrigin,y="tinycloud.email-held/v1",S="blockchainAccountId",v=31536e3,T=6e5,C=3e5,_=6e4,O="did:key:",R=/^did:key:z6Mk[^#]+$/,b=/^[^\s@]+@[^\s@]+\.[^\s@]+$/,N=Symbol.for("nodejs.util.inspect.custom"),q={ADDRESS_INVALID:!1,HOLDER_INVALID:!1,CODE_INVALID:!0,RATE_LIMITED:!0,ISSUER_UNAVAILABLE:!0,NETWORK:!0,PROFILE_UNAVAILABLE:!1,CODE_REJECTED:!0,CODE_ATTEMPTS_EXHAUSTED:!1,SIGNATURE_REJECTED:!0,CREDENTIAL_INVALID:!1,SESSION_EXPIRED:!1,SESSION_INVALID:!1,CLIENT_CLOCK_SKEW:!1,CANCELED:!1,FAILED:!1},L={ADDRESS_INVALID:"Email address is invalid.",HOLDER_INVALID:"Holder must be a did:key Ed25519 identifier.",CODE_INVALID:"Verification code must be 8 digits.",ISSUER_UNAVAILABLE:"Email verification is unavailable right now.",NETWORK:"Could not reach the email verification service.",PROFILE_UNAVAILABLE:"The witness does not offer the email verification profile.",CODE_REJECTED:"Verification code was not accepted.",CODE_ATTEMPTS_EXHAUSTED:"Too many wrong codes. Request a new code.",SIGNATURE_REJECTED:"Holder signature was rejected.",CREDENTIAL_INVALID:"Issued credential failed verification.",SESSION_EXPIRED:"Email verification request expired. Request a new code.",SESSION_INVALID:"Email verification request is no longer valid. Request a new code.",CLIENT_CLOCK_SKEW:"Your device clock is more than 5 minutes behind. Correct it and try again.",CANCELED:"Email verification was canceled.",FAILED:"Email verification failed."},U=class extends Error{constructor(e,t,r,i=q[t]){super("RATE_LIMITED"===t?function(e){const t="Too many codes were requested for this address.";if(void 0===e||!Number.isFinite(e)||e<=0)return`${t} Try again in about an hour.`;const r=Math.max(1,Math.ceil(e/6e4));return`${t} Try again in ${r} ${1===r?"minute":"minutes"}.`}(r):L[t]),this.name="EmailProofError",this.step=e,this.code=t,this.retryAfterMs=r,this.recoverable=i}};function x(e,t){const r=e.indexOf("#"),i=-1===r?e:e.slice(0,r);if(-1!==r&&e.slice(r+1)!==i.slice(O.length))throw new U("request","HOLDER_INVALID");if(!R.test(i))throw new U("request","HOLDER_INVALID");return{did:i,alg:"EdDSA",kid:X(i),sign:t}}function P(e){const t={type:e.type,version:e.version,profile:e.profile,address:e.address,requestId:e.requestId,holderDid:e.holderDid,descriptorDigest:e.descriptorDigest,requirementDigest:e.requirementDigest,openerOrigin:e.openerOrigin,createdAt:e.createdAt,expiresAt:e.expiresAt,...void 0===e.serverExpiresAt?{}:{serverExpiresAt:e.serverExpiresAt}},r={...t};return F(r,"verifier",e.verifier),F(r,"toJSON",()=>({...t})),F(r,N,()=>({...t,verifier:"[redacted]"})),Object.freeze(r)}function F(e,t,r){Object.defineProperty(e,t,{value:r,enumerable:!1,writable:!1,configurable:!1})}function k(e){return Math.min(Date.parse(e.expiresAt),Date.parse(e.createdAt)+w)}function V(){const e=new Map,t=t=>{for(const[r,i]of e)k(i)<=t.getTime()&&e.delete(r)};return{async findLive(r,i){let n;t(i);for(const t of e.values())t.address===r&&(!n||Date.parse(t.createdAt)>Date.parse(n.createdAt))&&(n=t);return n},async put(t){e.set(t.requestId,t)},async delete(t){e.delete(t)},get:async(r,i)=>(t(i),e.get(r))}}var H=class extends Error{},j=async()=>{throw new H("code requested")};async function B(e){const t=e.profile??D;W(t,"request",e.allowHeldProfile);const i=t===y;i&&G(e.holder,"request",t);const n=Q(e.address,t);i||G(e.holder,"request",t);const s=e.now??(()=>new Date),o=e.signal??AbortSignal.timeout(_),a=Y(n,t),d=await(0,r.credentialRequirementDigest)(a),l=await Z(t,a,{fetch:e.fetch,signal:o},"request",e.allowHeldProfile),u=await(0,r.canonicalDigest)(l),p=(0,r.encodeBase64Url)(crypto.getRandomValues(new Uint8Array(32))),f=new h(l,e.fetch,{honorServerRecoverable:!0,...i?{allowAccountSubject:!0}:{}}),E=s().getTime();let g;try{g=await f.create({descriptor:l,descriptorDigest:u,requirement:a,requirementDigest:d,holderDid:e.holder.did,openerOrigin:A,completionVerifierChallenge:await(0,r.sha256Base64Url)(p),signal:o})}catch(e){throw ie(e,"request",o)}const I=Date.parse(g.expiresAt);if(!Number.isFinite(I))throw new U("request","FAILED");const m=I-T;if(i&&m-s().getTime()>C)throw new U("request","CLIENT_CLOCK_SKEW");const S=P({type:"TinyCloudEmailProofPending",version:1,profile:t,address:n,requestId:g.requestId,verifier:p,holderDid:e.holder.did,descriptorDigest:u,requirementDigest:d,openerOrigin:A,createdAt:new Date(E).toISOString(),expiresAt:new Date(i?E+Math.min(I-m,w):Math.min(I,E+w)).toISOString(),...i?{serverExpiresAt:g.expiresAt}:{}});try{await c({descriptor:l,...i?{allowAccountSubject:!0}:{},requirement:a,requestId:g.requestId,verifier:p,holderDid:e.holder.did,descriptorDigest:u,requirementDigest:d,openerOrigin:A,...i?{expiresAt:g.expiresAt}:{},transport:f,signing:re(e.holder,i),handlers:{mailbox_otp:j},signal:o})}catch(e){if(e instanceof H)return S;throw ie(e,"request",o)}throw new U("request","FAILED")}async function M(e){return K(e,I)}async function K(e,t){const{pending:s}=e,o=e.now??(()=>new Date);if(!function(e){if("object"!=typeof e||null===e)return!1;const t=e;return"TinyCloudEmailProofPending"===t.type&&1===t.version&&t.openerOrigin===A&&[t.profile,t.address,t.requestId,t.verifier,t.holderDid,t.descriptorDigest,t.requirementDigest,t.openerOrigin,t.createdAt,t.expiresAt].every(e=>"string"==typeof e)&&Number.isFinite(Date.parse(t.createdAt))&&Number.isFinite(Date.parse(t.expiresAt))}(s))throw new U("session","SESSION_INVALID");W(s.profile,"session",e.allowHeldProfile);const a=s.profile===y;if(a&&!Number.isFinite(Date.parse(s.serverExpiresAt??"")))throw new U("session","SESSION_INVALID");if(k(s)<=o().getTime())throw new U("session","SESSION_EXPIRED");if(!/^\d{8}$/.test(e.code))throw new U("code","CODE_INVALID");if(G(e.holder,"code",s.profile),e.holder.did!==s.holderDid)throw new U("session","SESSION_INVALID");const d=e.signal??AbortSignal.timeout(_),l=Y(s.address,s.profile);if(await(0,r.credentialRequirementDigest)(l)!==s.requirementDigest)throw new U("session","SESSION_INVALID");const u=await Z(s.profile,l,{fetch:e.fetch,signal:d},"session",e.allowHeldProfile),p=await(0,r.canonicalDigest)(u);if(p!==s.descriptorDigest)throw new U("session","SESSION_INVALID");const f=new h(u,e.fetch,{honorServerRecoverable:!0,...a?{allowAccountSubject:!0}:{}});try{const t=await f.state(s.requestId,s.verifier,d);if(!0===t.nextStep?.constraints.challengeRequired)throw new U("session","SESSION_INVALID");await c({descriptor:u,...a?{allowAccountSubject:!0}:{},requirement:l,requestId:s.requestId,verifier:s.verifier,holderDid:s.holderDid,descriptorDigest:p,requirementDigest:s.requirementDigest,openerOrigin:s.openerOrigin,...a?{expiresAt:s.serverExpiresAt}:{},transport:f,signing:re(e.holder,a),handlers:{mailbox_otp:async()=>({otp:e.code})},signal:d})}catch(e){throw ie(e,"code",d)}try{const e=await f.result(s.requestId,s.verifier,d);if(a){const a=await async function(e){const{envelope:t,pending:s,descriptor:o}=e,a=e=>new r.CredentialError("VERIFICATION_FAILED",e),d=Date.parse(t.issuedAt),c=e.now().getTime();if(!Number.isFinite(d)||d-c>C)throw a("client clock is more than 5 minutes behind the issuer");const l=e.issuerKeys.find(e=>e.kid===n.issuerKid);if(!l)throw a("no pinned issuer key");const u=(0,i.parseIssuerSet)({format:"tinycloud.credentials-issuers/v1",version:1,issuers:[{issuerDid:n.issuerDid,kid:n.issuerKid,alg:"EdDSA",publicKey:l.jwk.x,vcts:[E.id],profiles:[y],notBefore:"2020-01-01T00:00:00Z",retiredAt:null,notAfter:null}]},{didMethods:{issuer:["web"]}}),p=(0,i.verifyHeldEmailCredential)(t.credential,{now:new Date(Math.max(c,d)),owner:s.holderDid,didMethods:{issuer:["web"]},acceptedIssuers:[{issuerDid:n.issuerDid,kid:n.issuerKid}],issuerSet:u}),f=e.transport.signedBinding(s.requestId),h=Object.keys(t.claims).sort().join(),w=e=>Math.floor(e/1e3);if(t.subjectDid!==s.holderDid||t.holderDid!==s.holderDid||"email,emailDomain"!==h||t.claims.email!==p.claims.email||t.claims.emailDomain!==p.claims.emailDomain||t.claims.email!==s.address||w(Date.parse(t.issuedAt))!==w(p.issuedAt.getTime())||w(Date.parse(t.expiresAt))!==w(p.expiresAt.getTime())||t.descriptorDigest!==e.descriptorDigest||t.profile.id!==y||1!==t.profile.version||t.issuerDid!==n.issuerDid||t.issuerKid!==n.issuerKid||"vc+sd-jwt"!==t.format||"none"!==t.status.method||t.status.freshnessSeconds!==o.status.freshnessSeconds)throw a("issued credential does not match the request");if(f?.type!==o.holderBinding.domain||!("credentialLifetimeSeconds"in f))throw a("signed binding is missing");if(p.credentialId!==f.jti||(p.expiresAt.getTime()-p.issuedAt.getTime())/1e3!==f.credentialLifetimeSeconds)throw a("credential does not match the binding the account signed");return p}({envelope:e,pending:s,descriptor:u,descriptorDigest:p,transport:f,issuerKeys:t,now:o});return{envelope:e,verified:a,credentialId:a.credentialId,issuedAt:a.issuedAt.toISOString(),expiresAt:a.expiresAt.toISOString(),descriptor:u}}const c=await(0,r.verifyIssuedCredential)({envelope:e,descriptor:u,descriptorDigest:p,requirement:l,holderDid:s.holderDid,issuerMetadata:ee(t),now:o(),checkStatus:(e,t)=>f.checkStatus(e,t),signal:d});return{envelope:e,verified:c,credentialId:c.credentialId,issuedAt:c.issuedAt,expiresAt:c.expiresAt,descriptor:u}}catch(e){throw ie(e,"credential",d)}}async function $(e){return async function(e,t){const r=e.profile??D;W(r,"request",e.allowHeldProfile);const i=Q(e.address,r),n=e.now??(()=>new Date),s=e.pendingStore,o=s?await s.findLive(i,n()):void 0;let a=o?.profile===r?o:void 0;if(a&&r===y&&!Number.isFinite(Date.parse(a.serverExpiresAt??"")))throw await(s?.delete(a.requestId).catch(()=>{})),new U("session","SESSION_INVALID");a||(a=await B({...e,address:i}),await(s?.put(a)));const d=P(a);if(!e.getCode)return{status:"code-requested",pending:d};const c=await e.getCode({pending:d});try{const r=await K({...e,pending:a,code:c},t),i=[];if(s)try{await s.delete(a.requestId)}catch{i.push("The pending request could not be deleted after success; it expires at its deadline.")}return{status:"issued",result:r,warnings:i}}catch(e){throw e instanceof U&&e.recoverable||await(s?.delete(a.requestId).catch(()=>{})),e}}(e,I)}function Q(e,t){if(t===y)return function(e){const t=()=>new U("request","ADDRESS_INVALID"),r=e.trim();if(/[^\x00-\x7f]/.test(r))throw t();const i=r.toLowerCase(),n=i.split("@");if(i.length<3||i.length>254||2!==n.length||/[^\x21-\x7e]/.test(i))throw t();const[s,o]=n;if(s.length>64||!J.test(s)||s.startsWith("+"))throw t();if(o.length>253||!o.includes(".")||!o.split(".").every(e=>e.length<=63&&z.test(e)))throw t();return i}(e);const r=e.trim();if(r.length>254||!b.test(r))throw new U("request","ADDRESS_INVALID");return r}var J=/^[a-z0-9!#$%&'*+\-/=?^_`{|}~]+(\.[a-z0-9!#$%&'*+\-/=?^_`{|}~]+)*$/,z=/^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/;function X(e){return`${e}#${e.slice(O.length)}`}function G(e,t,r){if(r===y)return function(e,t){const r=(0,i.parsePkhDid)(e.did),n=null!==r&&"1"===r.chainId?`did:pkh:eip155:1:${(0,i.toChecksumAddress)(r.address)}`:void 0;if(void 0===n||e.did!==n||"EIP191"!==e.alg||e.kid!==`${n}#${S}`)throw new U(t,"HOLDER_INVALID")}(e,t);if(!R.test(e.did)||"EdDSA"!==e.alg||e.kid!==X(e.did))throw new U(t,"HOLDER_INVALID")}function W(e,t,r){const i=Object.prototype.hasOwnProperty.call(m,e)?m[e]:void 0;if(!i||!i.enabled&&(!0!==r||e!==y))throw new U(t,"PROFILE_UNAVAILABLE");return i}function Y(e,t){return t===y?(0,r.validateCredentialRequirement)({type:"TinyCloudCredentialRequirement",version:1,profile:{id:t,version:1},credentialType:E,claims:{email:e},maxAgeSeconds:v}):(0,r.createEmailCredentialRequirement)({email:e,profile:{id:t,version:1},credentialType:E})}async function Z(e,t,i,s,o){const a=W(e,s,o);let d;try{d=await async function(e,t,i={}){let n;try{n=new URL(t)}catch{throw new r.CredentialError("UNSUPPORTED_PROFILE","Discovery URL is invalid")}if("https:"!==n.protocol||!["/.well-known/opencredentials","/v1/credential-types"].includes(n.pathname)||n.search||n.hash)throw new r.CredentialError("UNSUPPORTED_PROFILE","Discovery URL is not an allowed catalog endpoint");const s={credentials:"omit",cache:"no-store",redirect:"error",referrerPolicy:"no-referrer",signal:i.signal};let o;try{o=await(i.fetch??globalThis.fetch.bind(globalThis))(n,s)}catch(e){throw new r.CredentialError("OFFLINE","Credential discovery is unavailable",{cause:e})}if(!o.ok)throw new r.CredentialError(503===o.status?"ISSUER_UNREADY":"OFFLINE","Credential discovery is unavailable");const a=await o.json();if("tinycloud.credentials/catalog/v1"!==a.type||"tinycloud.credentials/acquisition/v1"!==a.protocol||1!==a.catalogVersion||!Array.isArray(a.profiles))throw new r.CredentialError("DESCRIPTOR_INVALID","Credential catalog is invalid");for(const t of a.profiles){if("object"!=typeof t||null===t||Array.isArray(t))continue;const i=t;if(!0===i.supported&&!0===i.enabled&&("ready"===i.readiness||"degraded"===i.readiness))try{const t=(0,r.validateCredentialFlowDescriptor)(i.descriptor);if((0,r.descriptorSatisfiesRequirement)(t,e)&&i.descriptorDigest===await(0,r.canonicalDigest)(t))return t}catch{}}throw new r.CredentialError("UNSUPPORTED_PROFILE","No available credential profile satisfies the requirement")}(t,g,{fetch:i.fetch,signal:i.signal})}catch(e){throw function(e,t,r){return t.aborted&&"TimeoutError"!==t.reason?.name?new U(r,"CANCELED"):ie(e,r,t)}(e,i.signal,s)}if(d.issuer.origin!==n.witnessOrigin||d.issuer.did!==n.issuerDid||!d.steps.some(e=>e.type===a.requiredStep))throw new U(s,"PROFILE_UNAVAILABLE");if(await(0,r.canonicalDigest)(d)!==a.descriptorDigest)throw new U(s,"PROFILE_UNAVAILABLE");return d}function ee(e){return{type:"OpenCredentialsIssuerMetadata",version:1,origin:n.witnessOrigin,issuerDid:n.issuerDid,keys:e,cache:{maxAgeSeconds:3600,etag:"pinned"}}}async function te(e){return async function(e,t){const{record:i,requirement:s,holderDid:o}=e,a=i.descriptor;if(i.descriptorDigest!==n.descriptorDigest||await(0,r.canonicalDigest)(a)!==n.descriptorDigest)throw new r.CredentialError("VERIFICATION_FAILED","stored descriptor does not match the pinned descriptor digest");const d={type:"OpenCredentialsIssuedCredential",version:1,protocol:a.protocol,profile:i.profile,credentialType:i.credentialType,schema:i.schema,format:"vc+sd-jwt",issuerDid:i.issuerDid,issuerKid:i.issuerKid,subjectDid:i.subjectDid,holderDid:i.holderDid,claims:i.claims,claimsDigest:i.claimsDigest,descriptorDigest:i.descriptorDigest,credentialId:i.credentialId,issuedAt:i.issuedAt,notBefore:i.notBefore,expiresAt:i.expiresAt,status:i.status,credential:i.credential},c=await(0,r.verifyIssuedCredential)({envelope:d,descriptor:a,descriptorDigest:n.descriptorDigest,requirement:s,holderDid:o,issuerMetadata:ee(t),now:e.now,checkStatus:async e=>"none"===e.method&&e.freshnessSeconds===a.status.freshnessSeconds,signal:e.signal});if(i.holderDid!==o||i.ownerDid!==o)throw new r.CredentialError("HOLDER_MISMATCH","stored record belongs to another holder");if(i.credentialDigest!==c.credentialDigest)throw new r.CredentialError("VERIFICATION_FAILED","stored credential digest does not match the verified credential");if(i.requirementDigest!==await(0,r.credentialRequirementDigest)(s))throw new r.CredentialError("VERIFICATION_FAILED","stored requirement digest does not match the requirement");if(i.recordId!==await(0,r.canonicalDigest)({credentialDigest:c.credentialDigest,holderDid:i.ownerDid}))throw new r.CredentialError("VERIFICATION_FAILED","stored record id does not match its credential");return c}(e,I)}function re(e,t){return{autoSign:async(r,i)=>{try{return await e.sign(i)}catch(e){const r=e instanceof DOMException&&("TimeoutError"===e.name||"AbortError"===e.name);if(!t||e instanceof U||r)throw e;throw new U("credential","SIGNATURE_REJECTED")}},holderKey:{alg:e.alg,kid:e.kid}}}function ie(e,t,i){if(e instanceof U)return e;if(e instanceof DOMException&&"TimeoutError"===e.name)return new U(t,"NETWORK");const n=(0,r.credentialError)(e),s=n.details;switch(n.code){case"ISSUER_UNREADY":return"rate_limited"===s.state?new U(t,"RATE_LIMITED",s.retryAfterMs,n.recoverable):new U(t,"ISSUER_UNAVAILABLE",void 0,n.recoverable);case"OFFLINE":return i?.aborted&&"TimeoutError"!==i.reason?.name?new U(t,"CANCELED"):new U(t,"NETWORK");case"UNSUPPORTED_PROFILE":case"UNSUPPORTED_VERSION":case"DESCRIPTOR_INVALID":return new U(t,"PROFILE_UNAVAILABLE");case"PROOF_REJECTED":return new U("code","CODE_REJECTED",void 0,!0);case"VERIFICATION_FAILED":return"proof_attempts_exhausted"===s.state?new U("code","CODE_ATTEMPTS_EXHAUSTED"):"credential"===t?new U("credential","CREDENTIAL_INVALID"):"code"===t?new U("code","CODE_REJECTED",void 0,!1):new U(t,"FAILED");case"HOLDER_MISMATCH":return new U("credential","CREDENTIAL_INVALID");case"REQUEST_EXPIRED":return new U("session","SESSION_EXPIRED");case"REQUEST_SUBSTITUTED":return new U("session","SESSION_INVALID");case"SIGNATURE_REJECTED":return new U("credential","SIGNATURE_REJECTED",void 0,n.recoverable);case"CANCELED":return new U(t,"CANCELED");default:return new U(t,"FAILED")}}const ne="blockchainAccountId",se="1",oe=0;function ae(){return new U("request","HOLDER_INVALID")}const de=["audience","challengeNonce","completionContext","completionOrigin","credentialLifetimeSeconds","descriptorDigest","expiresAt","holderDid","issuedAt","issuer","issuerKid","jti","normalizedClaimsDigest","openerOrigin","profile","profileVersion","protocol","requestId","requirementDigest","type"],ce=/^urn:uuid:[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/,le=/^[A-Za-z0-9_-]{32}$/,ue=/^[A-Za-z0-9_-]{43}$/,pe=/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$/,fe=6e5;function he(e){try{return new TextDecoder("utf-8",{fatal:!0,ignoreBOM:!0}).decode(e)}catch{throw ae()}}function Ee(e,t){const n=(0,i.parsePkhDid)(e);if(null===n||n.chainId!==se)throw ae();const o=(0,i.toChecksumAddress)(n.address),a=`did:pkh:eip155:${se}:${o}`;return{did:a,alg:"EIP191",kid:`${a}#${ne}`,sign:async e=>{const n=new Uint8Array(e);!function(e,t){const n=he(e);let o,a;try{o=JSON.parse(n),a=(0,r.jcsCanonicalize)(o)}catch{throw ae()}if(a!==n||"object"!=typeof o||null===o||Array.isArray(o))throw ae();const d=o;if(Object.keys(d).sort().join()!==de.join())throw ae();for(const e of de)if("profileVersion"!==e&&"credentialLifetimeSeconds"!==e&&("string"!=typeof d[e]||""===d[e]))throw ae();const c=e=>d[e];if(Object.keys(s).some(e=>d[e]!==s[e])||!(0,i.pkhPrincipalsEqual)(d.holderDid,t)||!ce.test(c("jti"))||!le.test(c("requestId"))||!le.test(c("challengeNonce"))||!ue.test(c("requirementDigest"))||!ue.test(c("normalizedClaimsDigest"))||!pe.test(c("issuedAt"))||!pe.test(c("expiresAt"))||Date.parse(c("expiresAt"))-Date.parse(c("issuedAt"))!==fe)throw ae()}(function(e){const t=(new TextEncoder).encode(i.ACCOUNT_BINDING_DOMAIN);if(e.length<=t.length+1||e[t.length]!==oe)throw ae();for(let r=0;r<t.length;r++)if(e[r]!==t[r])throw ae();return e.subarray(t.length+1)}(n),a);const d=he(n),c=await t(n),l=c[64];if(65!==c.length||27!==l&&28!==l)throw ae();if(!await(0,r.verifyEip191MessageSignature)(d,function(e){return`0x${Array.from(e,e=>e.toString(16).padStart(2,"0")).join("")}`}(c),o))throw ae();return c}}}const we=6e5;function ge(e,t){return e.getTime()-t.getTime()>we}const Ie=50,De="1",me="KV_NOT_FOUND";function Ae(e){const t=(0,i.parsePkhDid)(e);if(null===t)throw new r.CredentialError("ACTIVE_SESSION_REQUIRED","Held credentials require a did:pkh:eip155 account owner");if(t.chainId!==De)throw new r.CredentialError("ACTIVE_SESSION_REQUIRED","Held credentials require an Ethereum mainnet (chain 1) account owner");return`did:pkh:eip155:${De}:${(0,i.toChecksumAddress)(t.address)}`}function ye(e){return`v1/held/${(0,i.registryKey)(e)}/`}function Se(e,t){return`${ye(e)}${t}`}function ve(e){if("object"!=typeof e||null===e)return!1;const t=e;return"TinyCloudHeldCredential"===t.type&&1===t.version&&"string"==typeof t.ownerDid&&"string"==typeof t.recordId&&"string"==typeof t.credentialDigest&&"string"==typeof t.credential&&"string"==typeof t.storedAt}function Te(e,t,r){return{issuerSet:e.issuerSet,acceptedIssuers:e.acceptedIssuers,didMethods:e.didMethods,now:t,owner:r}}async function Ce(e){return{type:"TinyCloudHeldStorageReceipt",version:1,ownerDid:e.ownerDid,recordId:e.recordId,recordDigest:await(0,r.canonicalDigest)(e),storedAt:e.storedAt}}async function _e(e){const t=e.now??new Date,n=Ae(e.ownerDid);let s;try{s=(0,i.verifyHeldEmailCredential)(e.sdJwt,Te(e,t,n))}catch(e){throw function(e){if(!(e instanceof i.HeldCredentialError))return e;const t="nonce-account-mismatch"===e.code?"HOLDER_MISMATCH":"VERIFICATION_FAILED";return new r.CredentialError(t,e.message,{cause:e})}(e)}const o=e.sdJwt;if("string"!=typeof o)throw new r.CredentialError("VERIFICATION_FAILED","Held credential must be an SD-JWT string");if("string"!=typeof s.claims.email)throw new r.CredentialError("VERIFICATION_FAILED","Held credential must disclose an email claim");if(!ge(s.expiresAt,t))throw new r.CredentialError("VERIFICATION_FAILED","Held credential expires within the reuse margin");const a=await(0,r.canonicalDigest)(o),d=await(0,r.canonicalDigest)({credentialDigest:a,holderDid:n}),c={type:"TinyCloudHeldCredential",version:1,ownerDid:n,recordId:d,credentialDigest:a,credential:o,storedAt:t.toISOString()},l=await async function(e,t,n){const s=()=>new r.CredentialError("VERIFIED_NOT_SAVED","Held credential could not be confirmed in storage"),o=await e.batchPut([{key:t,value:n}]).catch(()=>{});if(!0!==o?.ok)throw s();const a=await e.get(t).catch(()=>{}),d=!0===a?.ok?a.data.data:void 0;if(!ve(d)||d.recordId!==n.recordId||d.credentialDigest!==n.credentialDigest||d.credential!==n.credential||!(0,i.pkhPrincipalsEqual)(d.ownerDid,n.ownerDid))throw s();return d}(e.kv,Se(n,d),c);return{record:l,receipt:await Ce(l),verified:s}}async function Oe(e,t,r,i,n){const s=await e.get(t);return Re(s.ok?s.data.data:void 0,t,r,i,n)}async function Re(e,t,n,s,o){if(!ve(e))return{kind:"invalid"};if(!(0,i.pkhPrincipalsEqual)(e.ownerDid,n))return{kind:"invalid"};const a=await(0,r.canonicalDigest)(e.credential),d=await(0,r.canonicalDigest)({credentialDigest:a,holderDid:n});if(e.credentialDigest!==a||e.recordId!==d||t!==Se(n,d))return{kind:"invalid"};let c;try{c=(0,i.verifyHeldEmailCredential)(e.credential,Te(s,o,n))}catch(e){if(!(e instanceof i.HeldCredentialError)||"bad-config"===e.code)throw e;return{kind:"expired"===e.code?"expired":"invalid"}}const l=c.claims.email;return"string"!=typeof l?{kind:"invalid"}:{kind:"verified",email:l,match:{record:e,verified:c,recordId:d,email:l,issuedAt:c.issuedAt,expiresAt:c.expiresAt,issuer:c.issuer}}}class be extends r.CredentialError{}async function Ne(e,t){const i=[];let n;for(let s=0;s<Ie;s+=1){const s=await e.list(void 0===n?{prefix:t}:{prefix:t,cursor:n});if(!s.ok)return;if(i.push(...s.data.keys),!s.data.truncated)return[...new Set(i)];const o=s.data.nextCursor;if(void 0===o||""===o)throw new r.CredentialError("VERIFICATION_FAILED","Held listing is truncated without a continuation cursor");n=o}throw new be("VERIFICATION_FAILED","Held listing exceeds the page limit")}async function qe(e){const t=e.now??new Date,r=Ae(e.ownerDid),i=await Ne(e.kv,ye(r));if(void 0===i)return;const n=e.email.replace(/[A-Z]+/g,e=>e.toLowerCase());let s;for(const o of i){const i=await Oe(e.kv,o,r,e,t);if("verified"!==i.kind||i.email!==n)continue;const a=i.match.verified.expiresAt.getTime();ge(i.match.verified.expiresAt,t)&&(void 0===s||a>s.verified.expiresAt.getTime())&&(s=i.match)}return s}async function Le(e){const t=e.now??new Date,n=Ae(e.ownerDid),s=await Ne(e.kv,ye(n));if(void 0===s)throw new r.CredentialError("OFFLINE","Held credentials could not be listed");const o=[];for(const a of s){const s=await e.kv.get(a);if(!s.ok){if("error"in s&&s.error.code===me)continue;throw new r.CredentialError("OFFLINE","A held credential could not be read")}let d;try{d=await Re(s.data.data,a,n,e,t)}catch(e){if(e instanceof i.HeldCredentialError&&"bad-config"===e.code)throw e;continue}"verified"===d.kind&&ge(d.match.verified.expiresAt,t)&&o.push(d.match)}return o.sort((e,t)=>{const r=t.issuedAt.getTime()-e.issuedAt.getTime();return 0!==r?r:e.recordId<t.recordId?-1:e.recordId>t.recordId?1:0})}const Ue="tinycloud.email-held/v1",xe="opencredentials.email/v1",Pe=3e5;class Fe extends Error{constructor(e,t){super(t),this.retryable=!1,this.name="HeldSourceError",this.code=e}}const ke="Saved held credentials list is too long to read; clear old ones";async function Ve(e){return async function(e,t){const{kv:s,address:o,holder:a,sessionDid:d,getCode:c,pendingStore:l,fetch:u,signal:p,now:f,allowHeldProfile:h,...E}=e,w=f??(()=>new Date),g=Ae(a.did);if(void 0!==d&&!(0,i.pkhPrincipalsEqual)(d,g))throw new r.CredentialError("HOLDER_MISMATCH","Held acquisition holder must be the session account");const I=!0===h;let D;try{D=await async function(e,t,n,s,o){const a=s.trim().replace(/[A-Z]+/g,e=>e.toLowerCase()),d=async()=>function(e){let t;for(const r of e)(void 0===t||r.expiresAt.getTime()>t.expiresAt.getTime())&&(t=r);return t}((await async function(e,t,n,s){try{return await Le({...t,kv:e,ownerDid:n,now:s})}catch(e){if(e instanceof r.CredentialError||e instanceof i.HeldCredentialError)throw e;throw new r.CredentialError("OFFLINE","Held credentials could not be read",{cause:e})}}(e,t,n,new Date(o().getTime()+Pe))).filter(e=>e.email===a));try{return await d()}catch(e){if(!(e instanceof be))throw e}try{return await async function(e){const t=e.now??new Date,r=Ae(e.ownerDid),i=await Ne(e.kv,ye(r));if(void 0===i)return[];const n=[],s=new Map;for(const o of i){const i=await Oe(e.kv,o,r,e,t);if("invalid"===i.kind)continue;if("expired"===i.kind){n.push(o);continue}const a={key:o,recordId:i.match.record.recordId,expiresAt:i.match.verified.expiresAt.getTime()},d=s.get(i.email);if(void 0===d){s.set(i.email,a);continue}const c=a.expiresAt>d.expiresAt||a.expiresAt===d.expiresAt&&a.recordId>d.recordId;s.set(i.email,c?a:d),n.push(c?d.key:a.key)}const o=[];for(const t of n)(await e.kv.delete(t)).ok&&o.push(t);return o}({...t,kv:e,ownerDid:n,now:o()}),await d()}catch(e){if(e instanceof be)throw new Fe("held-store-listing-limit",ke);throw e}}(s,E,g,o,w)}catch(e){if(I||!(e instanceof r.CredentialError&&"OFFLINE"===e.code))throw e}if(void 0!==D)return{credential:D.record.credential,holderDid:g,expiresAt:D.verified.expiresAt};I&&function(e,t){const s=()=>new r.CredentialError("VERIFICATION_FAILED","The issuer policy does not accept the held credential issuer"),{issuerDid:o,issuerKid:a}=n;if(!Array.isArray(e.acceptedIssuers)||!e.acceptedIssuers.some(e=>e.issuerDid===o&&(void 0===e.kid||e.kid===a)))throw s();if(!i.IssuerSet.is(e.issuerSet))throw s();const d=e.issuerSet.resolveIssuer(o,a),c=t.getTime();if(!d||!d.vcts.includes(xe)||!d.profiles.includes(Ue)||c<d.notBefore||null!==d.retiredAt&&c>=d.retiredAt||null!==d.notAfter&&c>=d.notAfter)throw s()}(E,w());const m=await t({address:o,holder:a,profile:Ue,getCode:c,pendingStore:He(l,g,w),fetch:u,signal:p,now:w,allowHeldProfile:h});if("issued"!==m.status)throw new r.CredentialError("PROOF_REJECTED","Held acquisition did not issue a credential");const A=m.result.envelope.credential,y=w().getTime(),S=function(e){try{const t=JSON.parse((new TextDecoder).decode((0,r.decodeBase64Url)(e.split("~")[0].split(".")[1]))),i="object"==typeof t&&null!==t&&"iat"in t?t.iat:void 0;if("number"==typeof i&&Number.isSafeInteger(i))return 1e3*i}catch{}throw new r.CredentialError("VERIFICATION_FAILED","Issued credential is not readable")}(A);if(S-y>Pe)throw new r.CredentialError("VERIFICATION_FAILED","client clock is more than 5 minutes behind the issuer");let v;try{v=await _e({...E,kv:s,ownerDid:g,sdJwt:A,now:new Date(Math.max(y,S))})}catch{throw new r.CredentialError("VERIFIED_NOT_SAVED","Verified held credential could not be stored")}return{credential:A,holderDid:g,expiresAt:v.verified.expiresAt}}(e,$)}function He(e,t,r){if(void 0===e)return;const n=e=>void 0!==e&&e.profile===Ue&&(0,i.pkhPrincipalsEqual)(e.holderDid,t);return{async findLive(t,r){const i=await e.findLive(t,r);return n(i)?i:void 0},put:t=>e.put(t),async delete(t){n(await e.get(t,r()))&&await e.delete(t)},async get(t,r){const i=await e.get(t,r);return n(i)?i:void 0}}}module.exports=t})();
1
+ (()=>{"use strict";var e={d:(t,r)=>{for(var i in r)e.o(r,i)&&!e.o(t,i)&&Object.defineProperty(t,i,{enumerable:!0,get:r[i]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t),r:e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})}},t={};e.r(t),e.d(t,{EmailProofError:()=>x,OpenCredentialsHttpTransport:()=>h,acquireEmailProof:()=>Q,acquireHeldCredential:()=>Qe,completeEmailProof:()=>K,createAccountHolderSigner:()=>Ie,createEd25519HolderSigner:()=>P,createMemoryEmailProofPendingStore:()=>H,findHeldCredential:()=>Ve,interpretCredentialFlow:()=>c,listHeldEmailCredentials:()=>He,requestEmailProofCode:()=>M,storeHeldCredential:()=>Ue,verifyStoredEmailProof:()=>re});const r=require("@tinycloud/sdk-core"),i=require("@tinycloud/sdk-core/held-credentials");var n=Object.freeze({witnessOrigin:"https://witness.credentials.org",issuerDid:"did:web:issuer.credentials.org",issuerKid:"did:web:issuer.credentials.org#controller",issuerX:"eEJI4xEobto4HtQ7Pg9R1vBOwcpfGRTlXDG5QfqLnGQ",descriptorDigest:"1tg-qphmKBVtNwzVg9xyz-xxqt_xtMXAsQyXw46m8S0"}),s=Object.freeze({type:r.ACCOUNT_HOLDER_BINDING_DOMAIN,protocol:"tinycloud.credentials/acquisition/v1",profile:"tinycloud.email-held/v1",profileVersion:1,descriptorDigest:"dc3_DuvzipXwYkTfjKqTaK1c3VS0YSPnaBsYSQriC0w",issuer:n.issuerDid,issuerKid:n.issuerKid,audience:"tinycloud://credentials",openerOrigin:"https://localhost",completionOrigin:"https://localhost",completionContext:"sdk-acquisition",credentialLifetimeSeconds:31536e3}),o=6e5,a=()=>new r.CredentialError("REQUEST_SUBSTITUTED","Holder binding was substituted"),d=(e,t)=>new Promise((r,i)=>{const n=setTimeout(r,e);t?.addEventListener("abort",()=>{clearTimeout(n),i(new DOMException("Aborted","AbortError"))},{once:!0})});async function c(e){const t="account_is_subject"===e.descriptor.subjectRelationship;if(t&&!0!==e.allowAccountSubject)throw new r.CredentialError("UNSUPPORTED_PROFILE","The held credential profile requires an explicit opt-in");const i=new Map(e.descriptor.steps.map(e=>[e.type,e])),n=new Set;let c="";const l=async t=>{const i=(0,r.validateCredentialHolderBinding)(t);if(i.requestId!==e.requestId||i.descriptorDigest!==e.descriptorDigest||i.requirementDigest!==e.requirementDigest||i.holderDid!==e.holderDid||i.issuer!==e.descriptor.issuer.did||i.issuerKid!==e.descriptor.issuer.kid||i.profile!==e.descriptor.profile||i.openerOrigin!==e.openerOrigin||i.completionOrigin!==e.openerOrigin||"tinycloud://credentials"!==i.audience)throw new r.CredentialError("REQUEST_SUBSTITUTED","Holder binding was substituted");const n=e.descriptor.holderBinding.alg;if(i.type!==e.descriptor.holderBinding.domain||"EIP191"===n&&!e.transport.challengeNonce)throw new r.CredentialError("REQUEST_SUBSTITUTED","Holder binding was substituted");return"EIP191"===n&&await async function(e,t){const{descriptor:i}=t;if("EIP191"!==i.holderBinding.alg||e.type!==i.holderBinding.domain||e.requestId!==t.requestId||e.descriptorDigest!==t.descriptorDigest||e.requirementDigest!==t.requirementDigest||e.holderDid!==t.holderDid||e.issuer!==i.issuer.did||e.issuerKid!==i.issuer.kid||e.profile!==i.profile||e.openerOrigin!==t.openerOrigin||e.completionOrigin!==t.openerOrigin||e.audience!==s.audience||e.completionContext!==s.completionContext||e.type!==s.type||e.protocol!==s.protocol||e.profile!==s.profile||e.profileVersion!==s.profileVersion||e.descriptorDigest!==s.descriptorDigest||e.issuer!==s.issuer||e.issuerKid!==s.issuerKid||e.openerOrigin!==s.openerOrigin||e.completionOrigin!==s.completionOrigin||e.credentialLifetimeSeconds!==s.credentialLifetimeSeconds)throw a();if(void 0===t.challengeNonce||e.challengeNonce!==t.challengeNonce)throw a();if(e.normalizedClaimsDigest!==await(0,r.canonicalDigest)(t.requirement.claims))throw a();const n=Date.parse(e.expiresAt);if(void 0===t.serverExpiresAt||n!==Date.parse(t.serverExpiresAt)||Date.parse(e.issuedAt)!==n-o)throw a()}(i,{descriptor:e.descriptor,requirement:e.requirement,requestId:e.requestId,descriptorDigest:e.descriptorDigest,requirementDigest:e.requirementDigest,holderDid:e.holderDid,openerOrigin:e.openerOrigin,challengeNonce:e.transport.challengeNonce(e.requestId),serverExpiresAt:e.expiresAt}),i},u=async()=>{t&&void 0===e.transport.signedBinding?.(e.requestId)&&await l(await e.transport.holderBinding(e.requestId,e.verifier,e.signal))};for(;;){e.signal?.throwIfAborted();const t=await e.transport.state(e.requestId,e.verifier,e.signal);if(t.requestId!==e.requestId)throw new r.CredentialError("REQUEST_SUBSTITUTED","Credential request identity changed");if("expired"===t.state)throw new r.CredentialError("REQUEST_EXPIRED","Credential request expired",{state:t.state,correlationId:t.correlationId});if("canceled"===t.state)throw new r.CredentialError("CANCELED","Credential request was canceled",{state:t.state,correlationId:t.correlationId});if("issuer_unready"===t.state)throw new r.CredentialError("ISSUER_UNREADY","Credential issuer is not ready",{retryAfterMs:t.retryAfterMs,state:t.state,correlationId:t.correlationId});if("complete"===t.state)return void await u();if("ready_to_issue"===t.state||"issued"===t.state){await u(),"ready_to_issue"!==t.state||n.has("issue")?await(e.onWait?.()??d(t.retryAfterMs??50,e.signal)):(await e.transport.issue(e.requestId,e.verifier,e.signal),n.add("issue"));continue}const s=t.nextStep;if(!s){await(e.onWait?.()??d(t.retryAfterMs??50,e.signal));continue}const o=i.get(s.type);if(s.id!==s.type||!o||o.type!==s.type||o.version!==s.version)throw new r.CredentialError("REQUEST_SUBSTITUTED","Server selected an undeclared credential step");if(n.has(s.id)||t.transitionId===c)await(e.onWait?.()??d(t.retryAfterMs??50,e.signal));else{if(c=t.transitionId,"holder_signature"===s.type){e.onProgress?.({state:"signing",stepId:s.id,correlationId:t.correlationId});const i=await l(await e.transport.holderBinding(e.requestId,e.verifier,e.signal)),n=e.descriptor.holderBinding.alg;if("EIP191"===n!=("EIP191"===e.signing.holderKey?.alg))throw new r.CredentialError("REQUEST_SUBSTITUTED","Holder binding was substituted");const o=(0,r.holderBindingSigningBytes)(i);let a=await(e.signing.autoSign?.(i,o,e.signal));if(void 0===a){if(!e.signing.requestApproval)throw new r.CredentialError("SIGNATURE_REJECTED","OpenKey approval is required");try{a=await e.signing.requestApproval(i,o,e.signal)}catch(e){if(e instanceof r.CredentialError)throw e;throw new r.CredentialError("SIGNATURE_REJECTED","OpenKey approval was rejected",{cause:e})}}if(!(a instanceof Uint8Array)||0===a.length)throw new r.CredentialError("SIGNATURE_REJECTED","OpenKey signature is invalid");await e.transport.submitHolderSignature(e.requestId,e.verifier,"EIP191"===n?`0x${Array.from(a,e=>e.toString(16).padStart(2,"0")).join("")}`:(0,r.encodeBase64Url)(a),e.signal,e.signing.holderKey)}else{e.onProgress?.({state:"collect_input"===s.type?"collecting":"proving",stepId:s.id,correlationId:t.correlationId});const i=e.handlers?.[s.type],n=e.proofHandler;if(!i&&!n){await(e.onWait?.()??d(t.retryAfterMs??50,e.signal));continue}if(!0===s.constraints.challengeRequired&&await e.transport.beginStep(e.requestId,e.verifier,s.type,e.signal),i){const t=await i({descriptor:e.descriptor,requirement:e.requirement,stepId:s.id,constraints:s.constraints,signal:e.signal});await e.transport.submitStep(e.requestId,e.verifier,s.id,t,e.signal)}else{let t;for(let i=1;;i+=1){const o=await n({stepId:s.id,constraints:s.constraints,display:{title:e.descriptor.display.title,description:e.descriptor.display.description,consent:e.descriptor.display.consent,progressLabel:e.descriptor.accessibility.progressLabel,errorLiveRegion:e.descriptor.accessibility.errorLiveRegion},inputs:e.descriptor.inputs.map(({id:e,label:t,schema:r})=>({id:e,label:t,schema:r})),...void 0===t?{}:{feedback:t},signal:e.signal});try{await e.transport.submitStep(e.requestId,e.verifier,s.id,o,e.signal);break}catch(n){if(!(n instanceof r.CredentialError)||"PROOF_REJECTED"!==n.code)throw n;const o=e.descriptor.lifecycle.maxProofAttempts-i;if("mailbox_otp"!==s.type||o<=0)throw new r.CredentialError("VERIFICATION_FAILED","The proof was not accepted",{state:o<=0?"proof_attempts_exhausted":"proof_rejected",cause:n});t={kind:"rejected",attemptsRemaining:o}}}}}n.add(s.id)}}}function l(e,t){if("object"!=typeof e||null===e||Array.isArray(e))throw new r.CredentialError("VERIFICATION_FAILED",`${t} is invalid`);return e}function u(e,t){if("string"!=typeof e||!/^[A-Za-z0-9_-]{16,128}$/.test(e))throw new r.CredentialError("REQUEST_SUBSTITUTED",`${t} is invalid`);return e}function p(e,t){if("string"!=typeof e||!Number.isFinite(Date.parse(e)))throw new r.CredentialError("VERIFICATION_FAILED",`${t} is invalid`);return new Date(e).toISOString()}var f=new Set(["REQUEST_EXPIRED","ISSUER_UNREADY","UNSUPPORTED_PROFILE","UNSUPPORTED_VERSION","SIGNATURE_REJECTED"]),h=class{constructor(e,t=globalThis.fetch.bind(globalThis),i={}){if(this.descriptor=e,this.fetchFn=t,this.options=i,this.nonces=new Map,this.bindings=new Map,"account_is_subject"===e.subjectRelationship&&!0!==i.allowAccountSubject)throw new r.CredentialError("UNSUPPORTED_PROFILE","The held credential profile requires an explicit opt-in")}url(e,t){return new URL((0,r.credentialEndpointPath)(e,t),this.descriptor.issuer.origin).href}async request(e,t){let i;try{const r={method:t.method??"GET",credentials:"omit",cache:"no-store",redirect:"error",referrerPolicy:"no-referrer",signal:t.signal,headers:{accept:"application/json",...void 0===t.body?{}:{"content-type":"application/json"},...void 0===t.verifier?{}:{authorization:`Bearer ${t.verifier}`}},...void 0===t.body?{}:{body:JSON.stringify(t.body)}};i=await this.fetchFn(this.url(e,t.id),r)}catch(e){if(e instanceof DOMException&&"AbortError"===e.name)throw new r.CredentialError("CANCELED","Credential acquisition was canceled",{cause:e});throw new r.CredentialError("OFFLINE","OpenCredentials is unavailable",{cause:e})}if(!i.ok){let e;try{e=await i.json()}catch{e=void 0}const t=function(e,t,i){if("object"!=typeof e||null===e||Array.isArray(e))return;const n=e;if("code,correlationId,recoverable,state,type"!==Object.keys(n).sort().join(",")||"tinycloud.credentials/error/v1"!==n.type||"string"!=typeof n.code||"boolean"!=typeof n.recoverable||"string"!=typeof n.state||"string"!=typeof n.correlationId)return;if("PROOF_REJECTED"===n.code)return n.recoverable?new r.CredentialError("PROOF_REJECTED","The proof was not accepted",{state:n.state,correlationId:n.correlationId}):new r.CredentialError("VERIFICATION_FAILED","The proof attempt limit was reached",{state:"proof_attempts_exhausted",correlationId:n.correlationId});if("RATE_LIMITED"===n.code)return new r.CredentialError("ISSUER_UNREADY","Too many verification codes were requested",{state:"rate_limited",correlationId:n.correlationId,retryAfterMs:1e3*Number(t.headers.get("retry-after"))||void 0,recoverable:i?n.recoverable:void 0});if("CHALLENGE_EXPIRED"===n.code)return new r.CredentialError("REQUEST_EXPIRED","The credential challenge expired",{state:n.state,correlationId:n.correlationId,recoverable:i?n.recoverable:void 0});if("DESCRIPTOR_MISMATCH"===n.code&&(n.code="UNSUPPORTED_PROFILE"),!f.has(n.code))return;const s=n.code;return new r.CredentialError(s,`OpenCredentials rejected the request: ${s}`,{state:n.state,correlationId:n.correlationId,retryAfterMs:1e3*Number(t.headers.get("retry-after"))||void 0,recoverable:i?n.recoverable:void 0})}(e,i,!0===this.options.honorServerRecoverable);if(t)throw t;if(410===i.status)throw new r.CredentialError("REQUEST_EXPIRED","Credential request expired");if(409===i.status)throw new r.CredentialError("REQUEST_SUBSTITUTED","Credential request was replayed or substituted");if(503===i.status)throw new r.CredentialError("ISSUER_UNREADY","Credential issuer is not ready",{retryAfterMs:1e3*Number(i.headers.get("retry-after"))||void 0});throw new r.CredentialError("VERIFICATION_FAILED","OpenCredentials rejected the request")}if(204!==i.status)try{return await i.json()}catch(e){throw new r.CredentialError("VERIFICATION_FAILED","OpenCredentials response is invalid",{cause:e})}}async create(e){const t=l(await this.request("request",{method:"POST",body:{protocol:e.descriptor.protocol,profile:e.descriptor.profile,profileVersion:e.descriptor.profileVersion,descriptorDigest:e.descriptorDigest,requirementDigest:e.requirementDigest,holderDid:e.holderDid,inputs:e.inputs??e.requirement.claims,audience:s.audience,openerOrigin:e.openerOrigin,completionOrigin:e.openerOrigin,completionContext:s.completionContext,completionVerifierChallenge:e.completionVerifierChallenge},signal:e.signal}),"create response");if("tinycloud.credentials/acquisition-request/v1"!==t.type||t.protocol!==e.descriptor.protocol||"challenge"!==t.next||"challenge"!==t.endpoint)throw new r.CredentialError("VERIFICATION_FAILED","create response is invalid");const i=u(t.requestId,"requestId");return{requestId:i,locator:i,expiresAt:p(t.expiresAt,"expiresAt"),correlationId:i}}challengeNonce(e){return this.nonces.get(e)}signedBinding(e){return this.bindings.get(e)}proofStep(){return this.descriptor.steps.some(e=>"mailbox_otp"===e.type)?"mailbox_otp":"collect_input"}async state(e,t,i){const n=l(await this.request("state",{id:e,verifier:t,signal:i}),"state response");if("tinycloud.credentials/acquisition-state/v1"!==n.type||n.requestId!==e||n.profile!==this.descriptor.profile||1!==n.profileVersion)throw new r.CredentialError("REQUEST_SUBSTITUTED","Credential state response is substituted");const s={type:"OpenCredentialsAcquisitionState",version:1,requestId:e,transitionId:`${String(n.state)}:${String(n.resultPreviouslyRead??!1)}`,correlationId:e};if("challenge_required"===n.state){const e=this.proofStep();return{...s,state:"pending",nextStep:{id:e,type:e,version:1,constraints:{challengeRequired:!0}}}}if("account_is_subject"===this.descriptor.subjectRelationship&&("proof_required"===n.state||"holder_binding_required"===n.state||"holder_signature_required"===n.state||"ready_to_issue"===n.state||"issued"===n.state)){const t=n.challengeNonce,i=this.nonces.get(e);if("string"!=typeof t||""===t||void 0!==i&&i!==t)throw new r.CredentialError("REQUEST_SUBSTITUTED","Credential challenge nonce is missing or changed");this.nonces.set(e,u(t,"challengeNonce"))}if("proof_required"===n.state){const t=this.proofStep();return"account_is_subject"!==this.descriptor.subjectRelationship&&this.nonces.set(e,u(n.challengeNonce,"challengeNonce")),{...s,state:"pending",nextStep:{id:t,type:t,version:1,constraints:{}}}}if("holder_binding_required"===n.state||"holder_signature_required"===n.state)return{...s,state:"pending",nextStep:{id:"holder_signature",type:"holder_signature",version:1,constraints:{}}};if("ready_to_issue"===n.state)return{...s,state:"ready_to_issue"};if("issued"===n.state)return{...s,state:"complete"};throw new r.CredentialError("REQUEST_SUBSTITUTED","Credential state is unsupported")}async beginStep(e,t,i,n){const s=this.proofStep();if(i!==s)throw new r.CredentialError("REQUEST_SUBSTITUTED","Credential challenge step is substituted");const o=l(await this.request("challenge",{id:e,verifier:t,method:"POST",body:{step:s,stepVersion:1},signal:n}),"challenge response");if("tinycloud.credentials/challenge/v1"!==o.type||o.step!==s||1!==o.stepVersion)throw new r.CredentialError("REQUEST_SUBSTITUTED","Credential challenge is substituted");this.nonces.set(e,u(o.challengeNonce,"challengeNonce"))}async submitStep(e,t,i,n,s){const o=this.proofStep();if(i!==o)throw new r.CredentialError("REQUEST_SUBSTITUTED","Credential proof step is substituted");const a=this.nonces.get(e);if(!a)throw new r.CredentialError("REQUEST_SUBSTITUTED","Credential challenge is missing");await this.request("proof",{id:e,verifier:t,method:"POST",body:{step:o,stepVersion:1,challengeNonce:a,proof:n},signal:s})}async holderBinding(e,t,i){const n=l(await this.request("holder_binding",{id:e,verifier:t,signal:i}),"holder binding response");if("tinycloud.credentials/holder-binding-request/v1"!==n.type||n.signingDomain!==this.descriptor.holderBinding.domain||n.alg!==this.descriptor.holderBinding.alg||"string"!=typeof n.canonical)throw new r.CredentialError("REQUEST_SUBSTITUTED","Holder binding response is invalid");const s=(0,r.validateCredentialHolderBinding)(n.binding);if(s.type!==n.signingDomain)throw new r.CredentialError("REQUEST_SUBSTITUTED","Holder binding type does not match its signing domain");if((0,r.encodeBase64Url)((0,r.holderBindingCanonicalBytes)(s))!==n.canonical)throw new r.CredentialError("REQUEST_SUBSTITUTED","Holder binding canonical bytes were substituted");return this.bindings.set(e,s),s}async submitHolderSignature(e,t,i,n,s){const o=this.bindings.get(e);if(!o)throw new r.CredentialError("REQUEST_SUBSTITUTED","Holder binding was not retrieved");if("EIP191"===this.descriptor.holderBinding.alg&&!s)throw new r.CredentialError("REQUEST_SUBSTITUTED","An account holder must name its key and algorithm");const a=s?.alg??"EdDSA",d=s?.kid??`${o.holderDid}#${o.holderDid.replace("did:key:","")}`;await this.request("holder_signature",{id:e,verifier:t,method:"POST",body:{alg:a,kid:d,signature:i},signal:n})}async issue(e,t,r){await this.request("issue",{id:e,verifier:t,method:"POST",signal:r})}async result(e,t,i){const n=l(await this.request("result",{id:e,verifier:t,signal:i}),"result response");if("tinycloud.credentials/result/v1"!==n.type||n.protocol!==this.descriptor.protocol||n.profile!==this.descriptor.profile||1!==n.profileVersion||"vc+sd-jwt"!==n.format||n.descriptorDigest!==await(0,r.canonicalDigest)(this.descriptor)||n.issuer!==this.descriptor.issuer.did||n.issuerKid!==this.descriptor.issuer.kid||"string"!=typeof n.credential||await(0,r.sha256Base64Url)(n.credential)!==n.credentialDigest)throw new r.CredentialError("VERIFICATION_FAILED","Issued result metadata is invalid");const s=l(n.holderBinding,"result holder binding");if(n.subject!==s.did||s.signingDomain!==this.descriptor.holderBinding.domain)throw new r.CredentialError("HOLDER_MISMATCH","Issued holder binding is invalid");const o=l(n.claims,"result claims"),a={};for(const[e,t]of Object.entries(o)){if("string"!=typeof t)throw new r.CredentialError("VERIFICATION_FAILED","Issued claims are invalid");a[e]=t}const d=l(n.validity,"result validity"),c=function(e){const t=e.split("~",1)[0]?.split(".")[1];if(!t)throw new r.CredentialError("VERIFICATION_FAILED","Issued SD-JWT is invalid");try{return l(JSON.parse((new TextDecoder).decode((0,r.decodeBase64Url)(t))),"SD-JWT payload")}catch(e){if(e instanceof r.CredentialError)throw e;throw new r.CredentialError("VERIFICATION_FAILED","Issued SD-JWT is invalid",{cause:e})}}(n.credential);if("string"!=typeof c.jti)throw new r.CredentialError("VERIFICATION_FAILED","Credential id is invalid");const u=p(d.issuedAt,"issuedAt"),f=p(d.expiresAt,"expiresAt"),h=l(n.status,"result status");if("none"!==h.type||h.freshnessSeconds!==this.descriptor.status.freshnessSeconds)throw new r.CredentialError("VERIFICATION_FAILED","Credential status is invalid");return{type:"OpenCredentialsIssuedCredential",version:1,protocol:this.descriptor.protocol,profile:{id:this.descriptor.profile,version:1},credentialType:{id:this.descriptor.format.vct,version:1},schema:this.descriptor.format.vct,format:"vc+sd-jwt",issuerDid:n.issuer,issuerKid:n.issuerKid,subjectDid:n.subject,holderDid:n.subject,claims:a,claimsDigest:await(0,r.canonicalDigest)(a),descriptorDigest:n.descriptorDigest,credentialId:c.jti,issuedAt:u,notBefore:u,expiresAt:f,status:{method:"none",freshnessSeconds:h.freshnessSeconds},credential:n.credential}}async issuerMetadata(e){return await this.request("issuer_metadata",{signal:e})}async checkStatus(e,t){return"none"===e.method&&e.freshnessSeconds===this.descriptor.status.freshnessSeconds}},E={id:"opencredentials.email/v1",version:1},w=9e5,g=`${n.witnessOrigin}/.well-known/opencredentials`,I=[{kid:n.issuerKid,alg:"EdDSA",jwk:{kty:"OKP",crv:"Ed25519",x:n.issuerX},validFrom:"2020-01-01T00:00:00Z",validUntil:"2100-01-01T00:00:00Z"}],D="tinycloud.email-proof/v1",m={"tinycloud.email-proof/v1":{descriptorDigest:n.descriptorDigest,requiredStep:"mailbox_otp",enabled:!0},"tinycloud.email-held/v1":{descriptorDigest:s.descriptorDigest,requiredStep:"mailbox_otp",enabled:!1}},A=s.openerOrigin,y="tinycloud.email-held/v1",S="blockchainAccountId",v=31536e3,T=6e5,C=3e5,_=6e4,O="did:key:",R=/^did:key:z6Mk[^#]+$/,b=/^[^\s@]+@[^\s@]+\.[^\s@]+$/,N=Symbol.for("nodejs.util.inspect.custom"),q={ADDRESS_INVALID:!1,HOLDER_INVALID:!1,CODE_INVALID:!0,RATE_LIMITED:!0,ISSUER_UNAVAILABLE:!0,NETWORK:!0,PROFILE_UNAVAILABLE:!1,CODE_REJECTED:!0,CODE_ATTEMPTS_EXHAUSTED:!1,SIGNATURE_REJECTED:!0,CREDENTIAL_INVALID:!1,SESSION_EXPIRED:!1,SESSION_INVALID:!1,CLIENT_CLOCK_SKEW:!1,CANCELED:!1,FAILED:!1},L={ADDRESS_INVALID:"Email address is invalid.",HOLDER_INVALID:"Holder must be a did:key Ed25519 identifier.",CODE_INVALID:"Verification code must be 8 digits.",ISSUER_UNAVAILABLE:"Email verification is unavailable right now.",NETWORK:"Could not reach the email verification service.",PROFILE_UNAVAILABLE:"The witness does not offer the email verification profile.",CODE_REJECTED:"Verification code was not accepted.",CODE_ATTEMPTS_EXHAUSTED:"Too many wrong codes. Request a new code.",SIGNATURE_REJECTED:"Holder signature was rejected.",CREDENTIAL_INVALID:"Issued credential failed verification.",SESSION_EXPIRED:"Email verification request expired. Request a new code.",SESSION_INVALID:"Email verification request is no longer valid. Request a new code.",CLIENT_CLOCK_SKEW:"Your device clock is more than 5 minutes behind. Correct it and try again.",CANCELED:"Email verification was canceled.",FAILED:"Email verification failed."},U="This SDK build doesn't enable the email verification profile.",x=class extends Error{constructor(e,t,r,i=q[t],n){super(n??("RATE_LIMITED"===t?function(e){const t="Too many codes were requested for this address.";if(void 0===e||!Number.isFinite(e)||e<=0)return`${t} Try again in about an hour.`;const r=Math.max(1,Math.ceil(e/6e4));return`${t} Try again in ${r} ${1===r?"minute":"minutes"}.`}(r):L[t])),this.name="EmailProofError",this.step=e,this.code=t,this.retryAfterMs=r,this.recoverable=i}};function P(e,t){const r=e.indexOf("#"),i=-1===r?e:e.slice(0,r);if(-1!==r&&e.slice(r+1)!==i.slice(O.length))throw new x("request","HOLDER_INVALID");if(!R.test(i))throw new x("request","HOLDER_INVALID");return{did:i,alg:"EdDSA",kid:G(i),sign:t}}function F(e){const t={type:e.type,version:e.version,profile:e.profile,address:e.address,requestId:e.requestId,holderDid:e.holderDid,descriptorDigest:e.descriptorDigest,requirementDigest:e.requirementDigest,openerOrigin:e.openerOrigin,createdAt:e.createdAt,expiresAt:e.expiresAt,...void 0===e.serverExpiresAt?{}:{serverExpiresAt:e.serverExpiresAt}},r={...t};return k(r,"verifier",e.verifier),k(r,"toJSON",()=>({...t})),k(r,N,()=>({...t,verifier:"[redacted]"})),Object.freeze(r)}function k(e,t,r){Object.defineProperty(e,t,{value:r,enumerable:!1,writable:!1,configurable:!1})}function V(e){return Math.min(Date.parse(e.expiresAt),Date.parse(e.createdAt)+w)}function H(){const e=new Map,t=t=>{for(const[r,i]of e)V(i)<=t.getTime()&&e.delete(r)};return{async findLive(r,i){let n;t(i);for(const t of e.values())t.address===r&&(!n||Date.parse(t.createdAt)>Date.parse(n.createdAt))&&(n=t);return n},async put(t){e.set(t.requestId,t)},async delete(t){e.delete(t)},get:async(r,i)=>(t(i),e.get(r))}}var j=class extends Error{},B=async()=>{throw new j("code requested")};async function M(e){const t=e.profile??D;Y(t,"request",e.allowHeldProfile);const i=t===y;i&&W(e.holder,"request",t);const n=J(e.address,t);i||W(e.holder,"request",t);const s=e.now??(()=>new Date),o=e.signal??AbortSignal.timeout(_),a=Z(n,t),d=await(0,r.credentialRequirementDigest)(a),l=await ee(t,a,{fetch:e.fetch,signal:o},"request",e.allowHeldProfile),u=await(0,r.canonicalDigest)(l),p=(0,r.encodeBase64Url)(crypto.getRandomValues(new Uint8Array(32))),f=new h(l,e.fetch,{honorServerRecoverable:!0,...i?{allowAccountSubject:!0}:{}}),E=s().getTime();let g;try{g=await f.create({descriptor:l,descriptorDigest:u,requirement:a,requirementDigest:d,holderDid:e.holder.did,openerOrigin:A,completionVerifierChallenge:await(0,r.sha256Base64Url)(p),signal:o})}catch(e){throw ne(e,"request",o)}const I=Date.parse(g.expiresAt);if(!Number.isFinite(I))throw new x("request","FAILED");const m=I-T;if(i&&m-s().getTime()>C)throw new x("request","CLIENT_CLOCK_SKEW");const S=F({type:"TinyCloudEmailProofPending",version:1,profile:t,address:n,requestId:g.requestId,verifier:p,holderDid:e.holder.did,descriptorDigest:u,requirementDigest:d,openerOrigin:A,createdAt:new Date(E).toISOString(),expiresAt:new Date(i?E+Math.min(I-m,w):Math.min(I,E+w)).toISOString(),...i?{serverExpiresAt:g.expiresAt}:{}});try{await c({descriptor:l,...i?{allowAccountSubject:!0}:{},requirement:a,requestId:g.requestId,verifier:p,holderDid:e.holder.did,descriptorDigest:u,requirementDigest:d,openerOrigin:A,...i?{expiresAt:g.expiresAt}:{},transport:f,signing:ie(e.holder,i),handlers:{mailbox_otp:B},signal:o})}catch(e){if(e instanceof j)return S;throw ne(e,"request",o)}throw new x("request","FAILED")}async function K(e){return $(e,I)}async function $(e,t){const{pending:s}=e,o=e.now??(()=>new Date);if(!function(e){if("object"!=typeof e||null===e)return!1;const t=e;return"TinyCloudEmailProofPending"===t.type&&1===t.version&&t.openerOrigin===A&&[t.profile,t.address,t.requestId,t.verifier,t.holderDid,t.descriptorDigest,t.requirementDigest,t.openerOrigin,t.createdAt,t.expiresAt].every(e=>"string"==typeof e)&&Number.isFinite(Date.parse(t.createdAt))&&Number.isFinite(Date.parse(t.expiresAt))}(s))throw new x("session","SESSION_INVALID");Y(s.profile,"session",e.allowHeldProfile);const a=s.profile===y;if(a&&!Number.isFinite(Date.parse(s.serverExpiresAt??"")))throw new x("session","SESSION_INVALID");if(V(s)<=o().getTime())throw new x("session","SESSION_EXPIRED");if(!/^\d{8}$/.test(e.code))throw new x("code","CODE_INVALID");if(W(e.holder,"code",s.profile),e.holder.did!==s.holderDid)throw new x("session","SESSION_INVALID");const d=e.signal??AbortSignal.timeout(_),l=Z(s.address,s.profile);if(await(0,r.credentialRequirementDigest)(l)!==s.requirementDigest)throw new x("session","SESSION_INVALID");const u=await ee(s.profile,l,{fetch:e.fetch,signal:d},"session",e.allowHeldProfile),p=await(0,r.canonicalDigest)(u);if(p!==s.descriptorDigest)throw new x("session","SESSION_INVALID");const f=new h(u,e.fetch,{honorServerRecoverable:!0,...a?{allowAccountSubject:!0}:{}});try{const t=await f.state(s.requestId,s.verifier,d);if(!0===t.nextStep?.constraints.challengeRequired)throw new x("session","SESSION_INVALID");await c({descriptor:u,...a?{allowAccountSubject:!0}:{},requirement:l,requestId:s.requestId,verifier:s.verifier,holderDid:s.holderDid,descriptorDigest:p,requirementDigest:s.requirementDigest,openerOrigin:s.openerOrigin,...a?{expiresAt:s.serverExpiresAt}:{},transport:f,signing:ie(e.holder,a),handlers:{mailbox_otp:async()=>({otp:e.code})},signal:d})}catch(e){throw ne(e,"code",d)}try{const e=await f.result(s.requestId,s.verifier,d);if(a){const a=await async function(e){const{envelope:t,pending:s,descriptor:o}=e,a=e=>new r.CredentialError("VERIFICATION_FAILED",e),d=Date.parse(t.issuedAt),c=e.now().getTime();if(!Number.isFinite(d)||d-c>C)throw a("client clock is more than 5 minutes behind the issuer");const l=e.issuerKeys.find(e=>e.kid===n.issuerKid);if(!l)throw a("no pinned issuer key");const u=(0,i.parseIssuerSet)({format:"tinycloud.credentials-issuers/v1",version:1,issuers:[{issuerDid:n.issuerDid,kid:n.issuerKid,alg:"EdDSA",publicKey:l.jwk.x,vcts:[E.id],profiles:[y],notBefore:"2020-01-01T00:00:00Z",retiredAt:null,notAfter:null}]},{didMethods:{issuer:["web"]}}),p=(0,i.verifyHeldEmailCredential)(t.credential,{now:new Date(Math.max(c,d)),owner:s.holderDid,didMethods:{issuer:["web"]},acceptedIssuers:[{issuerDid:n.issuerDid,kid:n.issuerKid}],issuerSet:u}),f=e.transport.signedBinding(s.requestId),h=Object.keys(t.claims).sort().join(),w=e=>Math.floor(e/1e3);if(t.subjectDid!==s.holderDid||t.holderDid!==s.holderDid||"email,emailDomain"!==h||t.claims.email!==p.claims.email||t.claims.emailDomain!==p.claims.emailDomain||t.claims.email!==s.address||w(Date.parse(t.issuedAt))!==w(p.issuedAt.getTime())||w(Date.parse(t.expiresAt))!==w(p.expiresAt.getTime())||t.descriptorDigest!==e.descriptorDigest||t.profile.id!==y||1!==t.profile.version||t.issuerDid!==n.issuerDid||t.issuerKid!==n.issuerKid||"vc+sd-jwt"!==t.format||"none"!==t.status.method||t.status.freshnessSeconds!==o.status.freshnessSeconds)throw a("issued credential does not match the request");if(f?.type!==o.holderBinding.domain||!("credentialLifetimeSeconds"in f))throw a("signed binding is missing");if(p.credentialId!==f.jti||(p.expiresAt.getTime()-p.issuedAt.getTime())/1e3!==f.credentialLifetimeSeconds)throw a("credential does not match the binding the account signed");return p}({envelope:e,pending:s,descriptor:u,descriptorDigest:p,transport:f,issuerKeys:t,now:o});return{envelope:e,verified:a,credentialId:a.credentialId,issuedAt:a.issuedAt.toISOString(),expiresAt:a.expiresAt.toISOString(),descriptor:u}}const c=await(0,r.verifyIssuedCredential)({envelope:e,descriptor:u,descriptorDigest:p,requirement:l,holderDid:s.holderDid,issuerMetadata:te(t),now:o(),checkStatus:(e,t)=>f.checkStatus(e,t),signal:d});return{envelope:e,verified:c,credentialId:c.credentialId,issuedAt:c.issuedAt,expiresAt:c.expiresAt,descriptor:u}}catch(e){throw ne(e,"credential",d)}}async function Q(e){return async function(e,t){const r=e.profile??D;Y(r,"request",e.allowHeldProfile);const i=J(e.address,r),n=e.now??(()=>new Date),s=e.pendingStore,o=s?await s.findLive(i,n()):void 0;let a=o?.profile===r?o:void 0;if(a&&r===y&&!Number.isFinite(Date.parse(a.serverExpiresAt??"")))throw await(s?.delete(a.requestId).catch(()=>{})),new x("session","SESSION_INVALID");a||(a=await M({...e,address:i}),await(s?.put(a)));const d=F(a);if(!e.getCode)return{status:"code-requested",pending:d};const c=await e.getCode({pending:d});try{const r=await $({...e,pending:a,code:c},t),i=[];if(s)try{await s.delete(a.requestId)}catch{i.push("The pending request could not be deleted after success; it expires at its deadline.")}return{status:"issued",result:r,warnings:i}}catch(e){throw e instanceof x&&e.recoverable||await(s?.delete(a.requestId).catch(()=>{})),e}}(e,I)}function J(e,t){if(t===y)return function(e){const t=()=>new x("request","ADDRESS_INVALID"),r=e.trim();if(/[^\x00-\x7f]/.test(r))throw t();const i=r.toLowerCase(),n=i.split("@");if(i.length<3||i.length>254||2!==n.length||/[^\x21-\x7e]/.test(i))throw t();const[s,o]=n;if(s.length>64||!z.test(s)||s.startsWith("+"))throw t();if(o.length>253||!o.includes(".")||!o.split(".").every(e=>e.length<=63&&X.test(e)))throw t();return i}(e);const r=e.trim();if(r.length>254||!b.test(r))throw new x("request","ADDRESS_INVALID");return r}var z=/^[a-z0-9!#$%&'*+\-/=?^_`{|}~]+(\.[a-z0-9!#$%&'*+\-/=?^_`{|}~]+)*$/,X=/^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/;function G(e){return`${e}#${e.slice(O.length)}`}function W(e,t,r){if(r===y)return function(e,t){const r=(0,i.parsePkhDid)(e.did),n=null!==r&&"1"===r.chainId?`did:pkh:eip155:1:${(0,i.toChecksumAddress)(r.address)}`:void 0;if(void 0===n||e.did!==n||"EIP191"!==e.alg||e.kid!==`${n}#${S}`)throw new x(t,"HOLDER_INVALID")}(e,t);if(!R.test(e.did)||"EdDSA"!==e.alg||e.kid!==G(e.did))throw new x(t,"HOLDER_INVALID")}function Y(e,t,r){const i=Object.prototype.hasOwnProperty.call(m,e)?m[e]:void 0;if(!i||!i.enabled&&(!0!==r||e!==y))throw new x(t,"PROFILE_UNAVAILABLE",void 0,void 0,U);return i}function Z(e,t){return t===y?(0,r.validateCredentialRequirement)({type:"TinyCloudCredentialRequirement",version:1,profile:{id:t,version:1},credentialType:E,claims:{email:e},maxAgeSeconds:v}):(0,r.createEmailCredentialRequirement)({email:e,profile:{id:t,version:1},credentialType:E})}async function ee(e,t,i,s,o){const a=Y(e,s,o);let d;try{d=await async function(e,t,i={}){let n;try{n=new URL(t)}catch{throw new r.CredentialError("UNSUPPORTED_PROFILE","Discovery URL is invalid")}if("https:"!==n.protocol||!["/.well-known/opencredentials","/v1/credential-types"].includes(n.pathname)||n.search||n.hash)throw new r.CredentialError("UNSUPPORTED_PROFILE","Discovery URL is not an allowed catalog endpoint");const s={credentials:"omit",cache:"no-store",redirect:"error",referrerPolicy:"no-referrer",signal:i.signal};let o;try{o=await(i.fetch??globalThis.fetch.bind(globalThis))(n,s)}catch(e){throw new r.CredentialError("OFFLINE","Credential discovery is unavailable",{cause:e})}if(!o.ok)throw new r.CredentialError(503===o.status?"ISSUER_UNREADY":"OFFLINE","Credential discovery is unavailable");const a=await o.json();if("tinycloud.credentials/catalog/v1"!==a.type||"tinycloud.credentials/acquisition/v1"!==a.protocol||1!==a.catalogVersion||!Array.isArray(a.profiles))throw new r.CredentialError("DESCRIPTOR_INVALID","Credential catalog is invalid");for(const t of a.profiles){if("object"!=typeof t||null===t||Array.isArray(t))continue;const i=t;if(!0===i.supported&&!0===i.enabled&&("ready"===i.readiness||"degraded"===i.readiness))try{const t=(0,r.validateCredentialFlowDescriptor)(i.descriptor);if((0,r.descriptorSatisfiesRequirement)(t,e)&&i.descriptorDigest===await(0,r.canonicalDigest)(t))return t}catch{}}throw new r.CredentialError("UNSUPPORTED_PROFILE","No available credential profile satisfies the requirement")}(t,g,{fetch:i.fetch,signal:i.signal})}catch(e){throw function(e,t,r){return t.aborted&&"TimeoutError"!==t.reason?.name?new x(r,"CANCELED"):ne(e,r,t)}(e,i.signal,s)}if(d.issuer.origin!==n.witnessOrigin||d.issuer.did!==n.issuerDid||!d.steps.some(e=>e.type===a.requiredStep))throw new x(s,"PROFILE_UNAVAILABLE");if(await(0,r.canonicalDigest)(d)!==a.descriptorDigest)throw new x(s,"PROFILE_UNAVAILABLE");return d}function te(e){return{type:"OpenCredentialsIssuerMetadata",version:1,origin:n.witnessOrigin,issuerDid:n.issuerDid,keys:e,cache:{maxAgeSeconds:3600,etag:"pinned"}}}async function re(e){return async function(e,t){const{record:i,requirement:s,holderDid:o}=e,a=i.descriptor;if(i.descriptorDigest!==n.descriptorDigest||await(0,r.canonicalDigest)(a)!==n.descriptorDigest)throw new r.CredentialError("VERIFICATION_FAILED","stored descriptor does not match the pinned descriptor digest");const d={type:"OpenCredentialsIssuedCredential",version:1,protocol:a.protocol,profile:i.profile,credentialType:i.credentialType,schema:i.schema,format:"vc+sd-jwt",issuerDid:i.issuerDid,issuerKid:i.issuerKid,subjectDid:i.subjectDid,holderDid:i.holderDid,claims:i.claims,claimsDigest:i.claimsDigest,descriptorDigest:i.descriptorDigest,credentialId:i.credentialId,issuedAt:i.issuedAt,notBefore:i.notBefore,expiresAt:i.expiresAt,status:i.status,credential:i.credential},c=await(0,r.verifyIssuedCredential)({envelope:d,descriptor:a,descriptorDigest:n.descriptorDigest,requirement:s,holderDid:o,issuerMetadata:te(t),now:e.now,checkStatus:async e=>"none"===e.method&&e.freshnessSeconds===a.status.freshnessSeconds,signal:e.signal});if(i.holderDid!==o||i.ownerDid!==o)throw new r.CredentialError("HOLDER_MISMATCH","stored record belongs to another holder");if(i.credentialDigest!==c.credentialDigest)throw new r.CredentialError("VERIFICATION_FAILED","stored credential digest does not match the verified credential");if(i.requirementDigest!==await(0,r.credentialRequirementDigest)(s))throw new r.CredentialError("VERIFICATION_FAILED","stored requirement digest does not match the requirement");if(i.recordId!==await(0,r.canonicalDigest)({credentialDigest:c.credentialDigest,holderDid:i.ownerDid}))throw new r.CredentialError("VERIFICATION_FAILED","stored record id does not match its credential");return c}(e,I)}function ie(e,t){return{autoSign:async(r,i)=>{try{return await e.sign(i)}catch(e){const r=e instanceof DOMException&&("TimeoutError"===e.name||"AbortError"===e.name);if(!t||e instanceof x||r)throw e;throw new x("credential","SIGNATURE_REJECTED")}},holderKey:{alg:e.alg,kid:e.kid}}}function ne(e,t,i){if(e instanceof x)return e;if(e instanceof DOMException&&"TimeoutError"===e.name)return new x(t,"NETWORK");const n=(0,r.credentialError)(e),s=n.details;switch(n.code){case"ISSUER_UNREADY":return"rate_limited"===s.state?new x(t,"RATE_LIMITED",s.retryAfterMs,n.recoverable):new x(t,"ISSUER_UNAVAILABLE",void 0,n.recoverable);case"OFFLINE":return i?.aborted&&"TimeoutError"!==i.reason?.name?new x(t,"CANCELED"):new x(t,"NETWORK");case"UNSUPPORTED_PROFILE":case"UNSUPPORTED_VERSION":case"DESCRIPTOR_INVALID":return new x(t,"PROFILE_UNAVAILABLE");case"PROOF_REJECTED":return new x("code","CODE_REJECTED",void 0,!0);case"VERIFICATION_FAILED":return"proof_attempts_exhausted"===s.state?new x("code","CODE_ATTEMPTS_EXHAUSTED"):"credential"===t?new x("credential","CREDENTIAL_INVALID"):"code"===t?new x("code","CODE_REJECTED",void 0,!1):new x(t,"FAILED");case"HOLDER_MISMATCH":return new x("credential","CREDENTIAL_INVALID");case"REQUEST_EXPIRED":return new x("session","SESSION_EXPIRED");case"REQUEST_SUBSTITUTED":return new x("session","SESSION_INVALID");case"SIGNATURE_REJECTED":return new x("credential","SIGNATURE_REJECTED",void 0,n.recoverable);case"CANCELED":return new x(t,"CANCELED");default:return new x(t,"FAILED")}}const se="blockchainAccountId",oe="1",ae=0,de="The wallet signer signs only the exact account binding for this request.";function ce(){return new x("request","HOLDER_INVALID",void 0,void 0,de)}function le(){return new x("request","HOLDER_INVALID")}const ue=["audience","challengeNonce","completionContext","completionOrigin","credentialLifetimeSeconds","descriptorDigest","expiresAt","holderDid","issuedAt","issuer","issuerKid","jti","normalizedClaimsDigest","openerOrigin","profile","profileVersion","protocol","requestId","requirementDigest","type"],pe=/^urn:uuid:[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/,fe=/^[A-Za-z0-9_-]{32}$/,he=/^[A-Za-z0-9_-]{43}$/,Ee=/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$/,we=6e5;function ge(e){try{return new TextDecoder("utf-8",{fatal:!0,ignoreBOM:!0}).decode(e)}catch{throw ce()}}function Ie(e,t){const n=(0,i.parsePkhDid)(e);if(null===n||n.chainId!==oe)throw le();const o=(0,i.toChecksumAddress)(n.address),a=`did:pkh:eip155:${oe}:${o}`;return{did:a,alg:"EIP191",kid:`${a}#${se}`,sign:async e=>{const n=new Uint8Array(e);!function(e,t){const n=ge(e);let o,a;try{o=JSON.parse(n),a=(0,r.jcsCanonicalize)(o)}catch{throw ce()}if(a!==n||"object"!=typeof o||null===o||Array.isArray(o))throw ce();const d=o;if(Object.keys(d).sort().join()!==ue.join())throw ce();for(const e of ue)if("profileVersion"!==e&&"credentialLifetimeSeconds"!==e&&("string"!=typeof d[e]||""===d[e]))throw ce();const c=e=>d[e];if(Object.keys(s).some(e=>d[e]!==s[e])||!(0,i.pkhPrincipalsEqual)(d.holderDid,t)||!pe.test(c("jti"))||!fe.test(c("requestId"))||!fe.test(c("challengeNonce"))||!he.test(c("requirementDigest"))||!he.test(c("normalizedClaimsDigest"))||!Ee.test(c("issuedAt"))||!Ee.test(c("expiresAt"))||Date.parse(c("expiresAt"))-Date.parse(c("issuedAt"))!==we)throw ce()}(function(e){const t=(new TextEncoder).encode(i.ACCOUNT_BINDING_DOMAIN);if(e.length<=t.length+1||e[t.length]!==ae)throw ce();for(let r=0;r<t.length;r++)if(e[r]!==t[r])throw ce();return e.subarray(t.length+1)}(n),a);const d=ge(n),c=await t(n),l=c[64];if(65!==c.length||27!==l&&28!==l)throw le();if(!await(0,r.verifyEip191MessageSignature)(d,function(e){return`0x${Array.from(e,e=>e.toString(16).padStart(2,"0")).join("")}`}(c),o))throw le();return c}}}const De=6e5;function me(e,t){return e.getTime()-t.getTime()>De}const Ae=50,ye="1",Se="KV_NOT_FOUND",ve="This app can't read held credentials: the session may lack kv get and list on v1/held/ (skipPrefix), or may need to sign in again.",Te="This app can't delete held credentials: the session may lack kv del on v1/held/ (skipPrefix), or may need to sign in again.",Ce="permission_denied";function _e(e){let t="object"==typeof e&&null!==e&&"error"in e?e.error:void 0,r=!1;for(let e=0;e<8&&"object"==typeof t&&null!==t;e+=1){const e=t,i=e.meta,n=[e.status,e.statusCode,"object"==typeof i&&null!==i?i.status:void 0].find(e=>"number"==typeof e&&Number.isInteger(e)&&e>=400&&e<=599);if(void 0!==n)return 401===n||403===n;"AUTH_UNAUTHORIZED"===e.code&&(r=!0),t=e.cause}return r}function Oe(e){const t=(0,i.parsePkhDid)(e);if(null===t)throw new r.CredentialError("ACTIVE_SESSION_REQUIRED","Held credentials require a did:pkh:eip155 account owner");if(t.chainId!==ye)throw new r.CredentialError("ACTIVE_SESSION_REQUIRED","Held credentials require an Ethereum mainnet (chain 1) account owner");return`did:pkh:eip155:${ye}:${(0,i.toChecksumAddress)(t.address)}`}function Re(e){return`v1/held/${(0,i.registryKey)(e)}/`}function be(e,t){return`${Re(e)}${t}`}function Ne(e){if("object"!=typeof e||null===e)return!1;const t=e;return"TinyCloudHeldCredential"===t.type&&1===t.version&&"string"==typeof t.ownerDid&&"string"==typeof t.recordId&&"string"==typeof t.credentialDigest&&"string"==typeof t.credential&&"string"==typeof t.storedAt}function qe(e,t,r){return{issuerSet:e.issuerSet,acceptedIssuers:e.acceptedIssuers,didMethods:e.didMethods,now:t,owner:r}}async function Le(e){return{type:"TinyCloudHeldStorageReceipt",version:1,ownerDid:e.ownerDid,recordId:e.recordId,recordDigest:await(0,r.canonicalDigest)(e),storedAt:e.storedAt}}async function Ue(e){const t=e.now??new Date,n=Oe(e.ownerDid);let s;try{s=(0,i.verifyHeldEmailCredential)(e.sdJwt,qe(e,t,n))}catch(e){throw function(e){if(!(e instanceof i.HeldCredentialError))return e;const t="nonce-account-mismatch"===e.code?"HOLDER_MISMATCH":"VERIFICATION_FAILED";return new r.CredentialError(t,e.message,{cause:e})}(e)}const o=e.sdJwt;if("string"!=typeof o)throw new r.CredentialError("VERIFICATION_FAILED","Held credential must be an SD-JWT string");if("string"!=typeof s.claims.email)throw new r.CredentialError("VERIFICATION_FAILED","Held credential must disclose an email claim");if(!me(s.expiresAt,t))throw new r.CredentialError("VERIFICATION_FAILED","Held credential expires within the reuse margin");const a=await(0,r.canonicalDigest)(o),d=await(0,r.canonicalDigest)({credentialDigest:a,holderDid:n}),c={type:"TinyCloudHeldCredential",version:1,ownerDid:n,recordId:d,credentialDigest:a,credential:o,storedAt:t.toISOString()},l=await async function(e,t,n){const s=(e=!1)=>new r.CredentialError("VERIFIED_NOT_SAVED","Held credential could not be confirmed in storage",e?{state:Ce}:{}),o=await e.batchPut([{key:t,value:n}]).catch(()=>{});if(!0!==o?.ok)throw s(void 0!==o&&_e(o));const a=await e.get(t).catch(()=>{});if(void 0!==a&&!a.ok&&_e(a))throw s(!0);const d=!0===a?.ok?a.data.data:void 0;if(!Ne(d)||d.recordId!==n.recordId||d.credentialDigest!==n.credentialDigest||d.credential!==n.credential||!(0,i.pkhPrincipalsEqual)(d.ownerDid,n.ownerDid))throw s();return d}(e.kv,be(n,d),c);return{record:l,receipt:await Le(l),verified:s}}async function xe(e,t,i,n,s){const o=await e.get(t);if(!o.ok&&_e(o))throw new r.CredentialError("PERMISSION_DENIED",ve);return Pe(o.ok?o.data.data:void 0,t,i,n,s)}async function Pe(e,t,n,s,o){if(!Ne(e))return{kind:"invalid"};if(!(0,i.pkhPrincipalsEqual)(e.ownerDid,n))return{kind:"invalid"};const a=await(0,r.canonicalDigest)(e.credential),d=await(0,r.canonicalDigest)({credentialDigest:a,holderDid:n});if(e.credentialDigest!==a||e.recordId!==d||t!==be(n,d))return{kind:"invalid"};let c;try{c=(0,i.verifyHeldEmailCredential)(e.credential,qe(s,o,n))}catch(e){if(!(e instanceof i.HeldCredentialError)||"bad-config"===e.code)throw e;return{kind:"expired"===e.code?"expired":"invalid"}}const l=c.claims.email;return"string"!=typeof l?{kind:"invalid"}:{kind:"verified",email:l,match:{record:e,verified:c,recordId:d,email:l,issuedAt:c.issuedAt,expiresAt:c.expiresAt,issuer:c.issuer}}}class Fe extends r.CredentialError{}async function ke(e,t){const i=[];let n;for(let s=0;s<Ae;s+=1){const s=await e.list(void 0===n?{prefix:t}:{prefix:t,cursor:n});if(!s.ok){if(_e(s))throw new r.CredentialError("PERMISSION_DENIED",ve);return}if(i.push(...s.data.keys),!s.data.truncated)return[...new Set(i)];const o=s.data.nextCursor;if(void 0===o||""===o)throw new r.CredentialError("VERIFICATION_FAILED","Held listing is truncated without a continuation cursor");n=o}throw new Fe("VERIFICATION_FAILED","Held listing exceeds the page limit")}async function Ve(e){const t=e.now??new Date,r=Oe(e.ownerDid),i=await ke(e.kv,Re(r));if(void 0===i)return;const n=e.email.replace(/[A-Z]+/g,e=>e.toLowerCase());let s;for(const o of i){const i=await xe(e.kv,o,r,e,t);if("verified"!==i.kind||i.email!==n)continue;const a=i.match.verified.expiresAt.getTime();me(i.match.verified.expiresAt,t)&&(void 0===s||a>s.verified.expiresAt.getTime())&&(s=i.match)}return s}async function He(e){const t=e.now??new Date,n=Oe(e.ownerDid),s=await ke(e.kv,Re(n));if(void 0===s)throw new r.CredentialError("OFFLINE","Held credentials could not be listed");const o=[];for(const a of s){const s=await e.kv.get(a);if(!s.ok){if("error"in s&&s.error.code===Se)continue;if(_e(s))throw new r.CredentialError("PERMISSION_DENIED",ve);throw new r.CredentialError("OFFLINE","A held credential could not be read")}let d;try{d=await Pe(s.data.data,a,n,e,t)}catch(e){if(e instanceof i.HeldCredentialError&&"bad-config"===e.code)throw e;continue}"verified"===d.kind&&me(d.match.verified.expiresAt,t)&&o.push(d.match)}return o.sort((e,t)=>{const r=t.issuedAt.getTime()-e.issuedAt.getTime();return 0!==r?r:e.recordId<t.recordId?-1:e.recordId>t.recordId?1:0})}const je="tinycloud.email-held/v1",Be="opencredentials.email/v1",Me=3e5;class Ke extends Error{constructor(e,t){super(t),this.retryable=!1,this.name="HeldSourceError",this.code=e}}const $e="Saved held credentials list is too long to read; clear old ones";async function Qe(e){return async function(e,t){const{kv:s,address:o,holder:a,sessionDid:d,getCode:c,pendingStore:l,fetch:u,signal:p,now:f,allowHeldProfile:h,...E}=e,w=f??(()=>new Date),g=Oe(a.did);if(void 0!==d&&!(0,i.pkhPrincipalsEqual)(d,g))throw new r.CredentialError("HOLDER_MISMATCH","Held acquisition holder must be the session account");const I=!0===h;let D;try{D=await async function(e,t,n,s,o){const a=s.trim().replace(/[A-Z]+/g,e=>e.toLowerCase()),d=async()=>function(e){let t;for(const r of e)(void 0===t||r.expiresAt.getTime()>t.expiresAt.getTime())&&(t=r);return t}((await async function(e,t,n,s){try{return await He({...t,kv:e,ownerDid:n,now:s})}catch(e){if(e instanceof r.CredentialError||e instanceof i.HeldCredentialError)throw e;throw new r.CredentialError("OFFLINE","Held credentials could not be read",{cause:e})}}(e,t,n,new Date(o().getTime()+Me))).filter(e=>e.email===a));try{return await d()}catch(e){if(!(e instanceof Fe))throw e}try{return await async function(e){const t=e.now??new Date,i=Oe(e.ownerDid),n=await ke(e.kv,Re(i));if(void 0===n)return[];const s=[],o=new Map;for(const r of n){const n=await xe(e.kv,r,i,e,t);if("invalid"===n.kind)continue;if("expired"===n.kind){s.push(r);continue}const a={key:r,recordId:n.match.record.recordId,expiresAt:n.match.verified.expiresAt.getTime()},d=o.get(n.email);if(void 0===d){o.set(n.email,a);continue}const c=a.expiresAt>d.expiresAt||a.expiresAt===d.expiresAt&&a.recordId>d.recordId;o.set(n.email,c?a:d),s.push(c?d.key:a.key)}const a=[];for(const t of s){const i=await e.kv.delete(t);if(!i.ok&&_e(i))throw new r.CredentialError("PERMISSION_DENIED",Te);i.ok&&a.push(t)}return a}({...t,kv:e,ownerDid:n,now:o()}),await d()}catch(e){if(e instanceof Fe)throw new Ke("held-store-listing-limit",$e);throw e}}(s,E,g,o,w)}catch(e){if(I||!(e instanceof r.CredentialError)||"OFFLINE"!==e.code&&"PERMISSION_DENIED"!==e.code)throw e}if(void 0!==D)return{credential:D.record.credential,holderDid:g,expiresAt:D.verified.expiresAt};I&&function(e,t){const s=()=>new r.CredentialError("VERIFICATION_FAILED","The issuer policy does not accept the held credential issuer"),{issuerDid:o,issuerKid:a}=n;if(!Array.isArray(e.acceptedIssuers)||!e.acceptedIssuers.some(e=>e.issuerDid===o&&(void 0===e.kid||e.kid===a)))throw s();if(!i.IssuerSet.is(e.issuerSet))throw s();const d=e.issuerSet.resolveIssuer(o,a),c=t.getTime();if(!d||!d.vcts.includes(Be)||!d.profiles.includes(je)||c<d.notBefore||null!==d.retiredAt&&c>=d.retiredAt||null!==d.notAfter&&c>=d.notAfter)throw s()}(E,w());const m=await t({address:o,holder:a,profile:je,getCode:c,pendingStore:Je(l,g,w),fetch:u,signal:p,now:w,allowHeldProfile:h});if("issued"!==m.status)throw new r.CredentialError("PROOF_REJECTED","Held acquisition did not issue a credential");const A=m.result.envelope.credential,y=w().getTime(),S=function(e){try{const t=JSON.parse((new TextDecoder).decode((0,r.decodeBase64Url)(e.split("~")[0].split(".")[1]))),i="object"==typeof t&&null!==t&&"iat"in t?t.iat:void 0;if("number"==typeof i&&Number.isSafeInteger(i))return 1e3*i}catch{}throw new r.CredentialError("VERIFICATION_FAILED","Issued credential is not readable")}(A);if(S-y>Me)throw new r.CredentialError("VERIFICATION_FAILED","client clock is more than 5 minutes behind the issuer");let v;try{v=await Ue({...E,kv:s,ownerDid:g,sdJwt:A,now:new Date(Math.max(y,S))})}catch(e){const t=e instanceof r.CredentialError&&e.details.state===Ce;throw new r.CredentialError("VERIFIED_NOT_SAVED","Verified held credential could not be stored",t?{state:Ce}:{})}return{credential:A,holderDid:g,expiresAt:v.verified.expiresAt}}(e,Q)}function Je(e,t,r){if(void 0===e)return;const n=e=>void 0!==e&&e.profile===je&&(0,i.pkhPrincipalsEqual)(e.holderDid,t);return{async findLive(t,r){const i=await e.findLive(t,r);return n(i)?i:void 0},put:t=>e.put(t),async delete(t){n(await e.get(t,r()))&&await e.delete(t)},async get(t,r){const i=await e.get(t,r);return n(i)?i:void 0}}}module.exports=t})();
@@ -1 +1 @@
1
- import{ACCOUNT_HOLDER_BINDING_DOMAIN as e,CredentialError as t,canonicalDigest as i,createEmailCredentialRequirement as r,credentialEndpointPath as s,credentialError as n,credentialRequirementDigest as o,decodeBase64Url as a,descriptorSatisfiesRequirement as d,encodeBase64Url as c,holderBindingCanonicalBytes as l,holderBindingSigningBytes as u,jcsCanonicalize as p,sha256Base64Url as f,validateCredentialFlowDescriptor as h,validateCredentialHolderBinding as w,validateCredentialRequirement as g,verifyEip191MessageSignature as I,verifyIssuedCredential as E}from"@tinycloud/sdk-core";import{ACCOUNT_BINDING_DOMAIN as D,HeldCredentialError as A,IssuerSet as m,parseIssuerSet as y,parsePkhDid as S,pkhPrincipalsEqual as T,registryKey as v,toChecksumAddress as _,verifyHeldEmailCredential as O}from"@tinycloud/sdk-core/held-credentials";var R=Object.freeze({witnessOrigin:"https://witness.credentials.org",issuerDid:"did:web:issuer.credentials.org",issuerKid:"did:web:issuer.credentials.org#controller",issuerX:"eEJI4xEobto4HtQ7Pg9R1vBOwcpfGRTlXDG5QfqLnGQ",descriptorDigest:"1tg-qphmKBVtNwzVg9xyz-xxqt_xtMXAsQyXw46m8S0"}),b=Object.freeze({type:e,protocol:"tinycloud.credentials/acquisition/v1",profile:"tinycloud.email-held/v1",profileVersion:1,descriptorDigest:"dc3_DuvzipXwYkTfjKqTaK1c3VS0YSPnaBsYSQriC0w",issuer:R.issuerDid,issuerKid:R.issuerKid,audience:"tinycloud://credentials",openerOrigin:"https://localhost",completionOrigin:"https://localhost",completionContext:"sdk-acquisition",credentialLifetimeSeconds:31536e3}),N=()=>new t("REQUEST_SUBSTITUTED","Holder binding was substituted"),C=(e,t)=>new Promise((i,r)=>{const s=setTimeout(i,e);t?.addEventListener("abort",()=>{clearTimeout(s),r(new DOMException("Aborted","AbortError"))},{once:!0})});async function L(e){const r="account_is_subject"===e.descriptor.subjectRelationship;if(r&&!0!==e.allowAccountSubject)throw new t("UNSUPPORTED_PROFILE","The held credential profile requires an explicit opt-in");const s=new Map(e.descriptor.steps.map(e=>[e.type,e])),n=new Set;let o="";const a=async r=>{const s=w(r);if(s.requestId!==e.requestId||s.descriptorDigest!==e.descriptorDigest||s.requirementDigest!==e.requirementDigest||s.holderDid!==e.holderDid||s.issuer!==e.descriptor.issuer.did||s.issuerKid!==e.descriptor.issuer.kid||s.profile!==e.descriptor.profile||s.openerOrigin!==e.openerOrigin||s.completionOrigin!==e.openerOrigin||"tinycloud://credentials"!==s.audience)throw new t("REQUEST_SUBSTITUTED","Holder binding was substituted");const n=e.descriptor.holderBinding.alg;if(s.type!==e.descriptor.holderBinding.domain||"EIP191"===n&&!e.transport.challengeNonce)throw new t("REQUEST_SUBSTITUTED","Holder binding was substituted");return"EIP191"===n&&await async function(e,t){const{descriptor:r}=t;if("EIP191"!==r.holderBinding.alg||e.type!==r.holderBinding.domain||e.requestId!==t.requestId||e.descriptorDigest!==t.descriptorDigest||e.requirementDigest!==t.requirementDigest||e.holderDid!==t.holderDid||e.issuer!==r.issuer.did||e.issuerKid!==r.issuer.kid||e.profile!==r.profile||e.openerOrigin!==t.openerOrigin||e.completionOrigin!==t.openerOrigin||e.audience!==b.audience||e.completionContext!==b.completionContext||e.type!==b.type||e.protocol!==b.protocol||e.profile!==b.profile||e.profileVersion!==b.profileVersion||e.descriptorDigest!==b.descriptorDigest||e.issuer!==b.issuer||e.issuerKid!==b.issuerKid||e.openerOrigin!==b.openerOrigin||e.completionOrigin!==b.completionOrigin||e.credentialLifetimeSeconds!==b.credentialLifetimeSeconds)throw N();if(void 0===t.challengeNonce||e.challengeNonce!==t.challengeNonce)throw N();if(e.normalizedClaimsDigest!==await i(t.requirement.claims))throw N();const s=Date.parse(e.expiresAt);if(void 0===t.serverExpiresAt||s!==Date.parse(t.serverExpiresAt)||Date.parse(e.issuedAt)!==s-6e5)throw N()}(s,{descriptor:e.descriptor,requirement:e.requirement,requestId:e.requestId,descriptorDigest:e.descriptorDigest,requirementDigest:e.requirementDigest,holderDid:e.holderDid,openerOrigin:e.openerOrigin,challengeNonce:e.transport.challengeNonce(e.requestId),serverExpiresAt:e.expiresAt}),s},d=async()=>{r&&void 0===e.transport.signedBinding?.(e.requestId)&&await a(await e.transport.holderBinding(e.requestId,e.verifier,e.signal))};for(;;){e.signal?.throwIfAborted();const i=await e.transport.state(e.requestId,e.verifier,e.signal);if(i.requestId!==e.requestId)throw new t("REQUEST_SUBSTITUTED","Credential request identity changed");if("expired"===i.state)throw new t("REQUEST_EXPIRED","Credential request expired",{state:i.state,correlationId:i.correlationId});if("canceled"===i.state)throw new t("CANCELED","Credential request was canceled",{state:i.state,correlationId:i.correlationId});if("issuer_unready"===i.state)throw new t("ISSUER_UNREADY","Credential issuer is not ready",{retryAfterMs:i.retryAfterMs,state:i.state,correlationId:i.correlationId});if("complete"===i.state)return void await d();if("ready_to_issue"===i.state||"issued"===i.state){await d(),"ready_to_issue"!==i.state||n.has("issue")?await(e.onWait?.()??C(i.retryAfterMs??50,e.signal)):(await e.transport.issue(e.requestId,e.verifier,e.signal),n.add("issue"));continue}const r=i.nextStep;if(!r){await(e.onWait?.()??C(i.retryAfterMs??50,e.signal));continue}const l=s.get(r.type);if(r.id!==r.type||!l||l.type!==r.type||l.version!==r.version)throw new t("REQUEST_SUBSTITUTED","Server selected an undeclared credential step");if(n.has(r.id)||i.transitionId===o)await(e.onWait?.()??C(i.retryAfterMs??50,e.signal));else{if(o=i.transitionId,"holder_signature"===r.type){e.onProgress?.({state:"signing",stepId:r.id,correlationId:i.correlationId});const s=await a(await e.transport.holderBinding(e.requestId,e.verifier,e.signal)),n=e.descriptor.holderBinding.alg;if("EIP191"===n!=("EIP191"===e.signing.holderKey?.alg))throw new t("REQUEST_SUBSTITUTED","Holder binding was substituted");const o=u(s);let d=await(e.signing.autoSign?.(s,o,e.signal));if(void 0===d){if(!e.signing.requestApproval)throw new t("SIGNATURE_REJECTED","OpenKey approval is required");try{d=await e.signing.requestApproval(s,o,e.signal)}catch(e){if(e instanceof t)throw e;throw new t("SIGNATURE_REJECTED","OpenKey approval was rejected",{cause:e})}}if(!(d instanceof Uint8Array)||0===d.length)throw new t("SIGNATURE_REJECTED","OpenKey signature is invalid");await e.transport.submitHolderSignature(e.requestId,e.verifier,"EIP191"===n?`0x${Array.from(d,e=>e.toString(16).padStart(2,"0")).join("")}`:c(d),e.signal,e.signing.holderKey)}else{e.onProgress?.({state:"collect_input"===r.type?"collecting":"proving",stepId:r.id,correlationId:i.correlationId});const s=e.handlers?.[r.type],n=e.proofHandler;if(!s&&!n){await(e.onWait?.()??C(i.retryAfterMs??50,e.signal));continue}if(!0===r.constraints.challengeRequired&&await e.transport.beginStep(e.requestId,e.verifier,r.type,e.signal),s){const t=await s({descriptor:e.descriptor,requirement:e.requirement,stepId:r.id,constraints:r.constraints,signal:e.signal});await e.transport.submitStep(e.requestId,e.verifier,r.id,t,e.signal)}else{let i;for(let s=1;;s+=1){const o=await n({stepId:r.id,constraints:r.constraints,display:{title:e.descriptor.display.title,description:e.descriptor.display.description,consent:e.descriptor.display.consent,progressLabel:e.descriptor.accessibility.progressLabel,errorLiveRegion:e.descriptor.accessibility.errorLiveRegion},inputs:e.descriptor.inputs.map(({id:e,label:t,schema:i})=>({id:e,label:t,schema:i})),...void 0===i?{}:{feedback:i},signal:e.signal});try{await e.transport.submitStep(e.requestId,e.verifier,r.id,o,e.signal);break}catch(n){if(!(n instanceof t)||"PROOF_REJECTED"!==n.code)throw n;const o=e.descriptor.lifecycle.maxProofAttempts-s;if("mailbox_otp"!==r.type||o<=0)throw new t("VERIFICATION_FAILED","The proof was not accepted",{state:o<=0?"proof_attempts_exhausted":"proof_rejected",cause:n});i={kind:"rejected",attemptsRemaining:o}}}}}n.add(r.id)}}}function q(e,i){if("object"!=typeof e||null===e||Array.isArray(e))throw new t("VERIFICATION_FAILED",`${i} is invalid`);return e}function U(e,i){if("string"!=typeof e||!/^[A-Za-z0-9_-]{16,128}$/.test(e))throw new t("REQUEST_SUBSTITUTED",`${i} is invalid`);return e}function x(e,i){if("string"!=typeof e||!Number.isFinite(Date.parse(e)))throw new t("VERIFICATION_FAILED",`${i} is invalid`);return new Date(e).toISOString()}var F=new Set(["REQUEST_EXPIRED","ISSUER_UNREADY","UNSUPPORTED_PROFILE","UNSUPPORTED_VERSION","SIGNATURE_REJECTED"]),V=class{constructor(e,i=globalThis.fetch.bind(globalThis),r={}){if(this.descriptor=e,this.fetchFn=i,this.options=r,this.nonces=new Map,this.bindings=new Map,"account_is_subject"===e.subjectRelationship&&!0!==r.allowAccountSubject)throw new t("UNSUPPORTED_PROFILE","The held credential profile requires an explicit opt-in")}url(e,t){return new URL(s(e,t),this.descriptor.issuer.origin).href}async request(e,i){let r;try{const t={method:i.method??"GET",credentials:"omit",cache:"no-store",redirect:"error",referrerPolicy:"no-referrer",signal:i.signal,headers:{accept:"application/json",...void 0===i.body?{}:{"content-type":"application/json"},...void 0===i.verifier?{}:{authorization:`Bearer ${i.verifier}`}},...void 0===i.body?{}:{body:JSON.stringify(i.body)}};r=await this.fetchFn(this.url(e,i.id),t)}catch(e){if(e instanceof DOMException&&"AbortError"===e.name)throw new t("CANCELED","Credential acquisition was canceled",{cause:e});throw new t("OFFLINE","OpenCredentials is unavailable",{cause:e})}if(!r.ok){let e;try{e=await r.json()}catch{e=void 0}const i=function(e,i,r){if("object"!=typeof e||null===e||Array.isArray(e))return;const s=e;if("code,correlationId,recoverable,state,type"!==Object.keys(s).sort().join(",")||"tinycloud.credentials/error/v1"!==s.type||"string"!=typeof s.code||"boolean"!=typeof s.recoverable||"string"!=typeof s.state||"string"!=typeof s.correlationId)return;if("PROOF_REJECTED"===s.code)return s.recoverable?new t("PROOF_REJECTED","The proof was not accepted",{state:s.state,correlationId:s.correlationId}):new t("VERIFICATION_FAILED","The proof attempt limit was reached",{state:"proof_attempts_exhausted",correlationId:s.correlationId});if("RATE_LIMITED"===s.code)return new t("ISSUER_UNREADY","Too many verification codes were requested",{state:"rate_limited",correlationId:s.correlationId,retryAfterMs:1e3*Number(i.headers.get("retry-after"))||void 0,recoverable:r?s.recoverable:void 0});if("CHALLENGE_EXPIRED"===s.code)return new t("REQUEST_EXPIRED","The credential challenge expired",{state:s.state,correlationId:s.correlationId,recoverable:r?s.recoverable:void 0});if("DESCRIPTOR_MISMATCH"===s.code&&(s.code="UNSUPPORTED_PROFILE"),!F.has(s.code))return;const n=s.code;return new t(n,`OpenCredentials rejected the request: ${n}`,{state:s.state,correlationId:s.correlationId,retryAfterMs:1e3*Number(i.headers.get("retry-after"))||void 0,recoverable:r?s.recoverable:void 0})}(e,r,!0===this.options.honorServerRecoverable);if(i)throw i;if(410===r.status)throw new t("REQUEST_EXPIRED","Credential request expired");if(409===r.status)throw new t("REQUEST_SUBSTITUTED","Credential request was replayed or substituted");if(503===r.status)throw new t("ISSUER_UNREADY","Credential issuer is not ready",{retryAfterMs:1e3*Number(r.headers.get("retry-after"))||void 0});throw new t("VERIFICATION_FAILED","OpenCredentials rejected the request")}if(204!==r.status)try{return await r.json()}catch(e){throw new t("VERIFICATION_FAILED","OpenCredentials response is invalid",{cause:e})}}async create(e){const i=q(await this.request("request",{method:"POST",body:{protocol:e.descriptor.protocol,profile:e.descriptor.profile,profileVersion:e.descriptor.profileVersion,descriptorDigest:e.descriptorDigest,requirementDigest:e.requirementDigest,holderDid:e.holderDid,inputs:e.inputs??e.requirement.claims,audience:b.audience,openerOrigin:e.openerOrigin,completionOrigin:e.openerOrigin,completionContext:b.completionContext,completionVerifierChallenge:e.completionVerifierChallenge},signal:e.signal}),"create response");if("tinycloud.credentials/acquisition-request/v1"!==i.type||i.protocol!==e.descriptor.protocol||"challenge"!==i.next||"challenge"!==i.endpoint)throw new t("VERIFICATION_FAILED","create response is invalid");const r=U(i.requestId,"requestId");return{requestId:r,locator:r,expiresAt:x(i.expiresAt,"expiresAt"),correlationId:r}}challengeNonce(e){return this.nonces.get(e)}signedBinding(e){return this.bindings.get(e)}proofStep(){return this.descriptor.steps.some(e=>"mailbox_otp"===e.type)?"mailbox_otp":"collect_input"}async state(e,i,r){const s=q(await this.request("state",{id:e,verifier:i,signal:r}),"state response");if("tinycloud.credentials/acquisition-state/v1"!==s.type||s.requestId!==e||s.profile!==this.descriptor.profile||1!==s.profileVersion)throw new t("REQUEST_SUBSTITUTED","Credential state response is substituted");const n={type:"OpenCredentialsAcquisitionState",version:1,requestId:e,transitionId:`${String(s.state)}:${String(s.resultPreviouslyRead??!1)}`,correlationId:e};if("challenge_required"===s.state){const e=this.proofStep();return{...n,state:"pending",nextStep:{id:e,type:e,version:1,constraints:{challengeRequired:!0}}}}if("account_is_subject"===this.descriptor.subjectRelationship&&("proof_required"===s.state||"holder_binding_required"===s.state||"holder_signature_required"===s.state||"ready_to_issue"===s.state||"issued"===s.state)){const i=s.challengeNonce,r=this.nonces.get(e);if("string"!=typeof i||""===i||void 0!==r&&r!==i)throw new t("REQUEST_SUBSTITUTED","Credential challenge nonce is missing or changed");this.nonces.set(e,U(i,"challengeNonce"))}if("proof_required"===s.state){const t=this.proofStep();return"account_is_subject"!==this.descriptor.subjectRelationship&&this.nonces.set(e,U(s.challengeNonce,"challengeNonce")),{...n,state:"pending",nextStep:{id:t,type:t,version:1,constraints:{}}}}if("holder_binding_required"===s.state||"holder_signature_required"===s.state)return{...n,state:"pending",nextStep:{id:"holder_signature",type:"holder_signature",version:1,constraints:{}}};if("ready_to_issue"===s.state)return{...n,state:"ready_to_issue"};if("issued"===s.state)return{...n,state:"complete"};throw new t("REQUEST_SUBSTITUTED","Credential state is unsupported")}async beginStep(e,i,r,s){const n=this.proofStep();if(r!==n)throw new t("REQUEST_SUBSTITUTED","Credential challenge step is substituted");const o=q(await this.request("challenge",{id:e,verifier:i,method:"POST",body:{step:n,stepVersion:1},signal:s}),"challenge response");if("tinycloud.credentials/challenge/v1"!==o.type||o.step!==n||1!==o.stepVersion)throw new t("REQUEST_SUBSTITUTED","Credential challenge is substituted");this.nonces.set(e,U(o.challengeNonce,"challengeNonce"))}async submitStep(e,i,r,s,n){const o=this.proofStep();if(r!==o)throw new t("REQUEST_SUBSTITUTED","Credential proof step is substituted");const a=this.nonces.get(e);if(!a)throw new t("REQUEST_SUBSTITUTED","Credential challenge is missing");await this.request("proof",{id:e,verifier:i,method:"POST",body:{step:o,stepVersion:1,challengeNonce:a,proof:s},signal:n})}async holderBinding(e,i,r){const s=q(await this.request("holder_binding",{id:e,verifier:i,signal:r}),"holder binding response");if("tinycloud.credentials/holder-binding-request/v1"!==s.type||s.signingDomain!==this.descriptor.holderBinding.domain||s.alg!==this.descriptor.holderBinding.alg||"string"!=typeof s.canonical)throw new t("REQUEST_SUBSTITUTED","Holder binding response is invalid");const n=w(s.binding);if(n.type!==s.signingDomain)throw new t("REQUEST_SUBSTITUTED","Holder binding type does not match its signing domain");if(c(l(n))!==s.canonical)throw new t("REQUEST_SUBSTITUTED","Holder binding canonical bytes were substituted");return this.bindings.set(e,n),n}async submitHolderSignature(e,i,r,s,n){const o=this.bindings.get(e);if(!o)throw new t("REQUEST_SUBSTITUTED","Holder binding was not retrieved");if("EIP191"===this.descriptor.holderBinding.alg&&!n)throw new t("REQUEST_SUBSTITUTED","An account holder must name its key and algorithm");const a=n?.alg??"EdDSA",d=n?.kid??`${o.holderDid}#${o.holderDid.replace("did:key:","")}`;await this.request("holder_signature",{id:e,verifier:i,method:"POST",body:{alg:a,kid:d,signature:r},signal:s})}async issue(e,t,i){await this.request("issue",{id:e,verifier:t,method:"POST",signal:i})}async result(e,r,s){const n=q(await this.request("result",{id:e,verifier:r,signal:s}),"result response");if("tinycloud.credentials/result/v1"!==n.type||n.protocol!==this.descriptor.protocol||n.profile!==this.descriptor.profile||1!==n.profileVersion||"vc+sd-jwt"!==n.format||n.descriptorDigest!==await i(this.descriptor)||n.issuer!==this.descriptor.issuer.did||n.issuerKid!==this.descriptor.issuer.kid||"string"!=typeof n.credential||await f(n.credential)!==n.credentialDigest)throw new t("VERIFICATION_FAILED","Issued result metadata is invalid");const o=q(n.holderBinding,"result holder binding");if(n.subject!==o.did||o.signingDomain!==this.descriptor.holderBinding.domain)throw new t("HOLDER_MISMATCH","Issued holder binding is invalid");const d=q(n.claims,"result claims"),c={};for(const[e,i]of Object.entries(d)){if("string"!=typeof i)throw new t("VERIFICATION_FAILED","Issued claims are invalid");c[e]=i}const l=q(n.validity,"result validity"),u=function(e){const i=e.split("~",1)[0]?.split(".")[1];if(!i)throw new t("VERIFICATION_FAILED","Issued SD-JWT is invalid");try{return q(JSON.parse((new TextDecoder).decode(a(i))),"SD-JWT payload")}catch(e){if(e instanceof t)throw e;throw new t("VERIFICATION_FAILED","Issued SD-JWT is invalid",{cause:e})}}(n.credential);if("string"!=typeof u.jti)throw new t("VERIFICATION_FAILED","Credential id is invalid");const p=x(l.issuedAt,"issuedAt"),h=x(l.expiresAt,"expiresAt"),w=q(n.status,"result status");if("none"!==w.type||w.freshnessSeconds!==this.descriptor.status.freshnessSeconds)throw new t("VERIFICATION_FAILED","Credential status is invalid");return{type:"OpenCredentialsIssuedCredential",version:1,protocol:this.descriptor.protocol,profile:{id:this.descriptor.profile,version:1},credentialType:{id:this.descriptor.format.vct,version:1},schema:this.descriptor.format.vct,format:"vc+sd-jwt",issuerDid:n.issuer,issuerKid:n.issuerKid,subjectDid:n.subject,holderDid:n.subject,claims:c,claimsDigest:await i(c),descriptorDigest:n.descriptorDigest,credentialId:u.jti,issuedAt:p,notBefore:p,expiresAt:h,status:{method:"none",freshnessSeconds:w.freshnessSeconds},credential:n.credential}}async issuerMetadata(e){return await this.request("issuer_metadata",{signal:e})}async checkStatus(e,t){return"none"===e.method&&e.freshnessSeconds===this.descriptor.status.freshnessSeconds}},P={id:"opencredentials.email/v1",version:1},k=9e5,j=`${R.witnessOrigin}/.well-known/opencredentials`,B=[{kid:R.issuerKid,alg:"EdDSA",jwk:{kty:"OKP",crv:"Ed25519",x:R.issuerX},validFrom:"2020-01-01T00:00:00Z",validUntil:"2100-01-01T00:00:00Z"}],H="tinycloud.email-proof/v1",M={"tinycloud.email-proof/v1":{descriptorDigest:R.descriptorDigest,requiredStep:"mailbox_otp",enabled:!0},"tinycloud.email-held/v1":{descriptorDigest:b.descriptorDigest,requiredStep:"mailbox_otp",enabled:!1}},K=b.openerOrigin,$="tinycloud.email-held/v1",Q=3e5,J=/^did:key:z6Mk[^#]+$/,z=/^[^\s@]+@[^\s@]+\.[^\s@]+$/,X=Symbol.for("nodejs.util.inspect.custom"),G={ADDRESS_INVALID:!1,HOLDER_INVALID:!1,CODE_INVALID:!0,RATE_LIMITED:!0,ISSUER_UNAVAILABLE:!0,NETWORK:!0,PROFILE_UNAVAILABLE:!1,CODE_REJECTED:!0,CODE_ATTEMPTS_EXHAUSTED:!1,SIGNATURE_REJECTED:!0,CREDENTIAL_INVALID:!1,SESSION_EXPIRED:!1,SESSION_INVALID:!1,CLIENT_CLOCK_SKEW:!1,CANCELED:!1,FAILED:!1},W={ADDRESS_INVALID:"Email address is invalid.",HOLDER_INVALID:"Holder must be a did:key Ed25519 identifier.",CODE_INVALID:"Verification code must be 8 digits.",ISSUER_UNAVAILABLE:"Email verification is unavailable right now.",NETWORK:"Could not reach the email verification service.",PROFILE_UNAVAILABLE:"The witness does not offer the email verification profile.",CODE_REJECTED:"Verification code was not accepted.",CODE_ATTEMPTS_EXHAUSTED:"Too many wrong codes. Request a new code.",SIGNATURE_REJECTED:"Holder signature was rejected.",CREDENTIAL_INVALID:"Issued credential failed verification.",SESSION_EXPIRED:"Email verification request expired. Request a new code.",SESSION_INVALID:"Email verification request is no longer valid. Request a new code.",CLIENT_CLOCK_SKEW:"Your device clock is more than 5 minutes behind. Correct it and try again.",CANCELED:"Email verification was canceled.",FAILED:"Email verification failed."},Y=class extends Error{constructor(e,t,i,r=G[t]){super("RATE_LIMITED"===t?function(e){const t="Too many codes were requested for this address.";if(void 0===e||!Number.isFinite(e)||e<=0)return`${t} Try again in about an hour.`;const i=Math.max(1,Math.ceil(e/6e4));return`${t} Try again in ${i} ${1===i?"minute":"minutes"}.`}(i):W[t]),this.name="EmailProofError",this.step=e,this.code=t,this.retryAfterMs=i,this.recoverable=r}};function Z(e,t){const i=e.indexOf("#"),r=-1===i?e:e.slice(0,i);if(-1!==i&&e.slice(i+1)!==r.slice(8))throw new Y("request","HOLDER_INVALID");if(!J.test(r))throw new Y("request","HOLDER_INVALID");return{did:r,alg:"EdDSA",kid:fe(r),sign:t}}function ee(e){const t={type:e.type,version:e.version,profile:e.profile,address:e.address,requestId:e.requestId,holderDid:e.holderDid,descriptorDigest:e.descriptorDigest,requirementDigest:e.requirementDigest,openerOrigin:e.openerOrigin,createdAt:e.createdAt,expiresAt:e.expiresAt,...void 0===e.serverExpiresAt?{}:{serverExpiresAt:e.serverExpiresAt}},i={...t};return te(i,"verifier",e.verifier),te(i,"toJSON",()=>({...t})),te(i,X,()=>({...t,verifier:"[redacted]"})),Object.freeze(i)}function te(e,t,i){Object.defineProperty(e,t,{value:i,enumerable:!1,writable:!1,configurable:!1})}function ie(e){return Math.min(Date.parse(e.expiresAt),Date.parse(e.createdAt)+k)}function re(){const e=new Map,t=t=>{for(const[i,r]of e)ie(r)<=t.getTime()&&e.delete(i)};return{async findLive(i,r){let s;t(r);for(const t of e.values())t.address===i&&(!s||Date.parse(t.createdAt)>Date.parse(s.createdAt))&&(s=t);return s},async put(t){e.set(t.requestId,t)},async delete(t){e.delete(t)},get:async(i,r)=>(t(r),e.get(i))}}var se=class extends Error{},ne=async()=>{throw new se("code requested")};async function oe(e){const t=e.profile??H;we(t,"request",e.allowHeldProfile);const r=t===$;r&&he(e.holder,"request",t);const s=le(e.address,t);r||he(e.holder,"request",t);const n=e.now??(()=>new Date),a=e.signal??AbortSignal.timeout(6e4),d=ge(s,t),l=await o(d),u=await Ie(t,d,{fetch:e.fetch,signal:a},"request",e.allowHeldProfile),p=await i(u),h=c(crypto.getRandomValues(new Uint8Array(32))),w=new V(u,e.fetch,{honorServerRecoverable:!0,...r?{allowAccountSubject:!0}:{}}),g=n().getTime();let I;try{I=await w.create({descriptor:u,descriptorDigest:p,requirement:d,requirementDigest:l,holderDid:e.holder.did,openerOrigin:K,completionVerifierChallenge:await f(h),signal:a})}catch(e){throw me(e,"request",a)}const E=Date.parse(I.expiresAt);if(!Number.isFinite(E))throw new Y("request","FAILED");const D=E-6e5;if(r&&D-n().getTime()>Q)throw new Y("request","CLIENT_CLOCK_SKEW");const A=ee({type:"TinyCloudEmailProofPending",version:1,profile:t,address:s,requestId:I.requestId,verifier:h,holderDid:e.holder.did,descriptorDigest:p,requirementDigest:l,openerOrigin:K,createdAt:new Date(g).toISOString(),expiresAt:new Date(r?g+Math.min(E-D,k):Math.min(E,g+k)).toISOString(),...r?{serverExpiresAt:I.expiresAt}:{}});try{await L({descriptor:u,...r?{allowAccountSubject:!0}:{},requirement:d,requestId:I.requestId,verifier:h,holderDid:e.holder.did,descriptorDigest:p,requirementDigest:l,openerOrigin:K,...r?{expiresAt:I.expiresAt}:{},transport:w,signing:Ae(e.holder,r),handlers:{mailbox_otp:ne},signal:a})}catch(e){if(e instanceof se)return A;throw me(e,"request",a)}throw new Y("request","FAILED")}async function ae(e){return de(e,B)}async function de(e,r){const{pending:s}=e,n=e.now??(()=>new Date);if(!function(e){if("object"!=typeof e||null===e)return!1;const t=e;return"TinyCloudEmailProofPending"===t.type&&1===t.version&&t.openerOrigin===K&&[t.profile,t.address,t.requestId,t.verifier,t.holderDid,t.descriptorDigest,t.requirementDigest,t.openerOrigin,t.createdAt,t.expiresAt].every(e=>"string"==typeof e)&&Number.isFinite(Date.parse(t.createdAt))&&Number.isFinite(Date.parse(t.expiresAt))}(s))throw new Y("session","SESSION_INVALID");we(s.profile,"session",e.allowHeldProfile);const a=s.profile===$;if(a&&!Number.isFinite(Date.parse(s.serverExpiresAt??"")))throw new Y("session","SESSION_INVALID");if(ie(s)<=n().getTime())throw new Y("session","SESSION_EXPIRED");if(!/^\d{8}$/.test(e.code))throw new Y("code","CODE_INVALID");if(he(e.holder,"code",s.profile),e.holder.did!==s.holderDid)throw new Y("session","SESSION_INVALID");const d=e.signal??AbortSignal.timeout(6e4),c=ge(s.address,s.profile);if(await o(c)!==s.requirementDigest)throw new Y("session","SESSION_INVALID");const l=await Ie(s.profile,c,{fetch:e.fetch,signal:d},"session",e.allowHeldProfile),u=await i(l);if(u!==s.descriptorDigest)throw new Y("session","SESSION_INVALID");const p=new V(l,e.fetch,{honorServerRecoverable:!0,...a?{allowAccountSubject:!0}:{}});try{const t=await p.state(s.requestId,s.verifier,d);if(!0===t.nextStep?.constraints.challengeRequired)throw new Y("session","SESSION_INVALID");await L({descriptor:l,...a?{allowAccountSubject:!0}:{},requirement:c,requestId:s.requestId,verifier:s.verifier,holderDid:s.holderDid,descriptorDigest:u,requirementDigest:s.requirementDigest,openerOrigin:s.openerOrigin,...a?{expiresAt:s.serverExpiresAt}:{},transport:p,signing:Ae(e.holder,a),handlers:{mailbox_otp:async()=>({otp:e.code})},signal:d})}catch(e){throw me(e,"code",d)}try{const e=await p.result(s.requestId,s.verifier,d);if(a){const i=await async function(e){const{envelope:i,pending:r,descriptor:s}=e,n=e=>new t("VERIFICATION_FAILED",e),o=Date.parse(i.issuedAt),a=e.now().getTime();if(!Number.isFinite(o)||o-a>Q)throw n("client clock is more than 5 minutes behind the issuer");const d=e.issuerKeys.find(e=>e.kid===R.issuerKid);if(!d)throw n("no pinned issuer key");const c=y({format:"tinycloud.credentials-issuers/v1",version:1,issuers:[{issuerDid:R.issuerDid,kid:R.issuerKid,alg:"EdDSA",publicKey:d.jwk.x,vcts:[P.id],profiles:[$],notBefore:"2020-01-01T00:00:00Z",retiredAt:null,notAfter:null}]},{didMethods:{issuer:["web"]}}),l=O(i.credential,{now:new Date(Math.max(a,o)),owner:r.holderDid,didMethods:{issuer:["web"]},acceptedIssuers:[{issuerDid:R.issuerDid,kid:R.issuerKid}],issuerSet:c}),u=e.transport.signedBinding(r.requestId),p=Object.keys(i.claims).sort().join(),f=e=>Math.floor(e/1e3);if(i.subjectDid!==r.holderDid||i.holderDid!==r.holderDid||"email,emailDomain"!==p||i.claims.email!==l.claims.email||i.claims.emailDomain!==l.claims.emailDomain||i.claims.email!==r.address||f(Date.parse(i.issuedAt))!==f(l.issuedAt.getTime())||f(Date.parse(i.expiresAt))!==f(l.expiresAt.getTime())||i.descriptorDigest!==e.descriptorDigest||i.profile.id!==$||1!==i.profile.version||i.issuerDid!==R.issuerDid||i.issuerKid!==R.issuerKid||"vc+sd-jwt"!==i.format||"none"!==i.status.method||i.status.freshnessSeconds!==s.status.freshnessSeconds)throw n("issued credential does not match the request");if(u?.type!==s.holderBinding.domain||!("credentialLifetimeSeconds"in u))throw n("signed binding is missing");if(l.credentialId!==u.jti||(l.expiresAt.getTime()-l.issuedAt.getTime())/1e3!==u.credentialLifetimeSeconds)throw n("credential does not match the binding the account signed");return l}({envelope:e,pending:s,descriptor:l,descriptorDigest:u,transport:p,issuerKeys:r,now:n});return{envelope:e,verified:i,credentialId:i.credentialId,issuedAt:i.issuedAt.toISOString(),expiresAt:i.expiresAt.toISOString(),descriptor:l}}const i=await E({envelope:e,descriptor:l,descriptorDigest:u,requirement:c,holderDid:s.holderDid,issuerMetadata:Ee(r),now:n(),checkStatus:(e,t)=>p.checkStatus(e,t),signal:d});return{envelope:e,verified:i,credentialId:i.credentialId,issuedAt:i.issuedAt,expiresAt:i.expiresAt,descriptor:l}}catch(e){throw me(e,"credential",d)}}async function ce(e){return async function(e,t){const i=e.profile??H;we(i,"request",e.allowHeldProfile);const r=le(e.address,i),s=e.now??(()=>new Date),n=e.pendingStore,o=n?await n.findLive(r,s()):void 0;let a=o?.profile===i?o:void 0;if(a&&i===$&&!Number.isFinite(Date.parse(a.serverExpiresAt??"")))throw await(n?.delete(a.requestId).catch(()=>{})),new Y("session","SESSION_INVALID");a||(a=await oe({...e,address:r}),await(n?.put(a)));const d=ee(a);if(!e.getCode)return{status:"code-requested",pending:d};const c=await e.getCode({pending:d});try{const i=await de({...e,pending:a,code:c},t),r=[];if(n)try{await n.delete(a.requestId)}catch{r.push("The pending request could not be deleted after success; it expires at its deadline.")}return{status:"issued",result:i,warnings:r}}catch(e){throw e instanceof Y&&e.recoverable||await(n?.delete(a.requestId).catch(()=>{})),e}}(e,B)}function le(e,t){if(t===$)return function(e){const t=()=>new Y("request","ADDRESS_INVALID"),i=e.trim();if(/[^\x00-\x7f]/.test(i))throw t();const r=i.toLowerCase(),s=r.split("@");if(r.length<3||r.length>254||2!==s.length||/[^\x21-\x7e]/.test(r))throw t();const[n,o]=s;if(n.length>64||!ue.test(n)||n.startsWith("+"))throw t();if(o.length>253||!o.includes(".")||!o.split(".").every(e=>e.length<=63&&pe.test(e)))throw t();return r}(e);const i=e.trim();if(i.length>254||!z.test(i))throw new Y("request","ADDRESS_INVALID");return i}var ue=/^[a-z0-9!#$%&'*+\-/=?^_`{|}~]+(\.[a-z0-9!#$%&'*+\-/=?^_`{|}~]+)*$/,pe=/^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/;function fe(e){return`${e}#${e.slice(8)}`}function he(e,t,i){if(i===$)return function(e,t){const i=S(e.did),r=null!==i&&"1"===i.chainId?`did:pkh:eip155:1:${_(i.address)}`:void 0;if(void 0===r||e.did!==r||"EIP191"!==e.alg||e.kid!==`${r}#blockchainAccountId`)throw new Y(t,"HOLDER_INVALID")}(e,t);if(!J.test(e.did)||"EdDSA"!==e.alg||e.kid!==fe(e.did))throw new Y(t,"HOLDER_INVALID")}function we(e,t,i){const r=Object.prototype.hasOwnProperty.call(M,e)?M[e]:void 0;if(!r||!r.enabled&&(!0!==i||e!==$))throw new Y(t,"PROFILE_UNAVAILABLE");return r}function ge(e,t){return t===$?g({type:"TinyCloudCredentialRequirement",version:1,profile:{id:t,version:1},credentialType:P,claims:{email:e},maxAgeSeconds:31536e3}):r({email:e,profile:{id:t,version:1},credentialType:P})}async function Ie(e,r,s,n,o){const a=we(e,n,o);let c;try{c=await async function(e,r,s={}){let n;try{n=new URL(r)}catch{throw new t("UNSUPPORTED_PROFILE","Discovery URL is invalid")}if("https:"!==n.protocol||!["/.well-known/opencredentials","/v1/credential-types"].includes(n.pathname)||n.search||n.hash)throw new t("UNSUPPORTED_PROFILE","Discovery URL is not an allowed catalog endpoint");const o={credentials:"omit",cache:"no-store",redirect:"error",referrerPolicy:"no-referrer",signal:s.signal};let a;try{a=await(s.fetch??globalThis.fetch.bind(globalThis))(n,o)}catch(e){throw new t("OFFLINE","Credential discovery is unavailable",{cause:e})}if(!a.ok)throw new t(503===a.status?"ISSUER_UNREADY":"OFFLINE","Credential discovery is unavailable");const c=await a.json();if("tinycloud.credentials/catalog/v1"!==c.type||"tinycloud.credentials/acquisition/v1"!==c.protocol||1!==c.catalogVersion||!Array.isArray(c.profiles))throw new t("DESCRIPTOR_INVALID","Credential catalog is invalid");for(const t of c.profiles){if("object"!=typeof t||null===t||Array.isArray(t))continue;const r=t;if(!0===r.supported&&!0===r.enabled&&("ready"===r.readiness||"degraded"===r.readiness))try{const t=h(r.descriptor);if(d(t,e)&&r.descriptorDigest===await i(t))return t}catch{}}throw new t("UNSUPPORTED_PROFILE","No available credential profile satisfies the requirement")}(r,j,{fetch:s.fetch,signal:s.signal})}catch(e){throw function(e,t,i){return t.aborted&&"TimeoutError"!==t.reason?.name?new Y(i,"CANCELED"):me(e,i,t)}(e,s.signal,n)}if(c.issuer.origin!==R.witnessOrigin||c.issuer.did!==R.issuerDid||!c.steps.some(e=>e.type===a.requiredStep))throw new Y(n,"PROFILE_UNAVAILABLE");if(await i(c)!==a.descriptorDigest)throw new Y(n,"PROFILE_UNAVAILABLE");return c}function Ee(e){return{type:"OpenCredentialsIssuerMetadata",version:1,origin:R.witnessOrigin,issuerDid:R.issuerDid,keys:e,cache:{maxAgeSeconds:3600,etag:"pinned"}}}async function De(e){return async function(e,r){const{record:s,requirement:n,holderDid:a}=e,d=s.descriptor;if(s.descriptorDigest!==R.descriptorDigest||await i(d)!==R.descriptorDigest)throw new t("VERIFICATION_FAILED","stored descriptor does not match the pinned descriptor digest");const c={type:"OpenCredentialsIssuedCredential",version:1,protocol:d.protocol,profile:s.profile,credentialType:s.credentialType,schema:s.schema,format:"vc+sd-jwt",issuerDid:s.issuerDid,issuerKid:s.issuerKid,subjectDid:s.subjectDid,holderDid:s.holderDid,claims:s.claims,claimsDigest:s.claimsDigest,descriptorDigest:s.descriptorDigest,credentialId:s.credentialId,issuedAt:s.issuedAt,notBefore:s.notBefore,expiresAt:s.expiresAt,status:s.status,credential:s.credential},l=await E({envelope:c,descriptor:d,descriptorDigest:R.descriptorDigest,requirement:n,holderDid:a,issuerMetadata:Ee(r),now:e.now,checkStatus:async e=>"none"===e.method&&e.freshnessSeconds===d.status.freshnessSeconds,signal:e.signal});if(s.holderDid!==a||s.ownerDid!==a)throw new t("HOLDER_MISMATCH","stored record belongs to another holder");if(s.credentialDigest!==l.credentialDigest)throw new t("VERIFICATION_FAILED","stored credential digest does not match the verified credential");if(s.requirementDigest!==await o(n))throw new t("VERIFICATION_FAILED","stored requirement digest does not match the requirement");if(s.recordId!==await i({credentialDigest:l.credentialDigest,holderDid:s.ownerDid}))throw new t("VERIFICATION_FAILED","stored record id does not match its credential");return l}(e,B)}function Ae(e,t){return{autoSign:async(i,r)=>{try{return await e.sign(r)}catch(e){const i=e instanceof DOMException&&("TimeoutError"===e.name||"AbortError"===e.name);if(!t||e instanceof Y||i)throw e;throw new Y("credential","SIGNATURE_REJECTED")}},holderKey:{alg:e.alg,kid:e.kid}}}function me(e,t,i){if(e instanceof Y)return e;if(e instanceof DOMException&&"TimeoutError"===e.name)return new Y(t,"NETWORK");const r=n(e),s=r.details;switch(r.code){case"ISSUER_UNREADY":return"rate_limited"===s.state?new Y(t,"RATE_LIMITED",s.retryAfterMs,r.recoverable):new Y(t,"ISSUER_UNAVAILABLE",void 0,r.recoverable);case"OFFLINE":return i?.aborted&&"TimeoutError"!==i.reason?.name?new Y(t,"CANCELED"):new Y(t,"NETWORK");case"UNSUPPORTED_PROFILE":case"UNSUPPORTED_VERSION":case"DESCRIPTOR_INVALID":return new Y(t,"PROFILE_UNAVAILABLE");case"PROOF_REJECTED":return new Y("code","CODE_REJECTED",void 0,!0);case"VERIFICATION_FAILED":return"proof_attempts_exhausted"===s.state?new Y("code","CODE_ATTEMPTS_EXHAUSTED"):"credential"===t?new Y("credential","CREDENTIAL_INVALID"):"code"===t?new Y("code","CODE_REJECTED",void 0,!1):new Y(t,"FAILED");case"HOLDER_MISMATCH":return new Y("credential","CREDENTIAL_INVALID");case"REQUEST_EXPIRED":return new Y("session","SESSION_EXPIRED");case"REQUEST_SUBSTITUTED":return new Y("session","SESSION_INVALID");case"SIGNATURE_REJECTED":return new Y("credential","SIGNATURE_REJECTED",void 0,r.recoverable);case"CANCELED":return new Y(t,"CANCELED");default:return new Y(t,"FAILED")}}function ye(){return new Y("request","HOLDER_INVALID")}const Se=["audience","challengeNonce","completionContext","completionOrigin","credentialLifetimeSeconds","descriptorDigest","expiresAt","holderDid","issuedAt","issuer","issuerKid","jti","normalizedClaimsDigest","openerOrigin","profile","profileVersion","protocol","requestId","requirementDigest","type"],Te=/^urn:uuid:[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/,ve=/^[A-Za-z0-9_-]{32}$/,_e=/^[A-Za-z0-9_-]{43}$/,Oe=/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$/;function Re(e){try{return new TextDecoder("utf-8",{fatal:!0,ignoreBOM:!0}).decode(e)}catch{throw ye()}}function be(e,t){const i=S(e);if(null===i||"1"!==i.chainId)throw ye();const r=_(i.address),s=`did:pkh:eip155:1:${r}`;return{did:s,alg:"EIP191",kid:`${s}#blockchainAccountId`,sign:async e=>{const i=new Uint8Array(e);!function(e,t){const i=Re(e);let r,s;try{r=JSON.parse(i),s=p(r)}catch{throw ye()}if(s!==i||"object"!=typeof r||null===r||Array.isArray(r))throw ye();const n=r;if(Object.keys(n).sort().join()!==Se.join())throw ye();for(const e of Se)if("profileVersion"!==e&&"credentialLifetimeSeconds"!==e&&("string"!=typeof n[e]||""===n[e]))throw ye();const o=e=>n[e];if(Object.keys(b).some(e=>n[e]!==b[e])||!T(n.holderDid,t)||!Te.test(o("jti"))||!ve.test(o("requestId"))||!ve.test(o("challengeNonce"))||!_e.test(o("requirementDigest"))||!_e.test(o("normalizedClaimsDigest"))||!Oe.test(o("issuedAt"))||!Oe.test(o("expiresAt"))||Date.parse(o("expiresAt"))-Date.parse(o("issuedAt"))!==6e5)throw ye()}(function(e){const t=(new TextEncoder).encode(D);if(e.length<=t.length+1||0!==e[t.length])throw ye();for(let i=0;i<t.length;i++)if(e[i]!==t[i])throw ye();return e.subarray(t.length+1)}(i),s);const n=Re(i),o=await t(i),a=o[64];if(65!==o.length||27!==a&&28!==a)throw ye();if(!await I(n,function(e){return`0x${Array.from(e,e=>e.toString(16).padStart(2,"0")).join("")}`}(o),r))throw ye();return o}}}function Ne(e,t){return e.getTime()-t.getTime()>6e5}function Ce(e){const i=S(e);if(null===i)throw new t("ACTIVE_SESSION_REQUIRED","Held credentials require a did:pkh:eip155 account owner");if("1"!==i.chainId)throw new t("ACTIVE_SESSION_REQUIRED","Held credentials require an Ethereum mainnet (chain 1) account owner");return`did:pkh:eip155:1:${_(i.address)}`}function Le(e){return`v1/held/${v(e)}/`}function qe(e,t){return`${Le(e)}${t}`}function Ue(e){if("object"!=typeof e||null===e)return!1;const t=e;return"TinyCloudHeldCredential"===t.type&&1===t.version&&"string"==typeof t.ownerDid&&"string"==typeof t.recordId&&"string"==typeof t.credentialDigest&&"string"==typeof t.credential&&"string"==typeof t.storedAt}function xe(e,t,i){return{issuerSet:e.issuerSet,acceptedIssuers:e.acceptedIssuers,didMethods:e.didMethods,now:t,owner:i}}async function Fe(e){return{type:"TinyCloudHeldStorageReceipt",version:1,ownerDid:e.ownerDid,recordId:e.recordId,recordDigest:await i(e),storedAt:e.storedAt}}async function Ve(e){const r=e.now??new Date,s=Ce(e.ownerDid);let n;try{n=O(e.sdJwt,xe(e,r,s))}catch(e){throw function(e){if(!(e instanceof A))return e;const i="nonce-account-mismatch"===e.code?"HOLDER_MISMATCH":"VERIFICATION_FAILED";return new t(i,e.message,{cause:e})}(e)}const o=e.sdJwt;if("string"!=typeof o)throw new t("VERIFICATION_FAILED","Held credential must be an SD-JWT string");if("string"!=typeof n.claims.email)throw new t("VERIFICATION_FAILED","Held credential must disclose an email claim");if(!Ne(n.expiresAt,r))throw new t("VERIFICATION_FAILED","Held credential expires within the reuse margin");const a=await i(o),d=await i({credentialDigest:a,holderDid:s}),c={type:"TinyCloudHeldCredential",version:1,ownerDid:s,recordId:d,credentialDigest:a,credential:o,storedAt:r.toISOString()},l=await async function(e,i,r){const s=()=>new t("VERIFIED_NOT_SAVED","Held credential could not be confirmed in storage"),n=await e.batchPut([{key:i,value:r}]).catch(()=>{});if(!0!==n?.ok)throw s();const o=await e.get(i).catch(()=>{}),a=!0===o?.ok?o.data.data:void 0;if(!Ue(a)||a.recordId!==r.recordId||a.credentialDigest!==r.credentialDigest||a.credential!==r.credential||!T(a.ownerDid,r.ownerDid))throw s();return a}(e.kv,qe(s,d),c);return{record:l,receipt:await Fe(l),verified:n}}async function Pe(e,t,i,r,s){const n=await e.get(t);return ke(n.ok?n.data.data:void 0,t,i,r,s)}async function ke(e,t,r,s,n){if(!Ue(e))return{kind:"invalid"};if(!T(e.ownerDid,r))return{kind:"invalid"};const o=await i(e.credential),a=await i({credentialDigest:o,holderDid:r});if(e.credentialDigest!==o||e.recordId!==a||t!==qe(r,a))return{kind:"invalid"};let d;try{d=O(e.credential,xe(s,n,r))}catch(e){if(!(e instanceof A)||"bad-config"===e.code)throw e;return{kind:"expired"===e.code?"expired":"invalid"}}const c=d.claims.email;return"string"!=typeof c?{kind:"invalid"}:{kind:"verified",email:c,match:{record:e,verified:d,recordId:a,email:c,issuedAt:d.issuedAt,expiresAt:d.expiresAt,issuer:d.issuer}}}class je extends t{}async function Be(e,i){const r=[];let s;for(let n=0;n<50;n+=1){const n=await e.list(void 0===s?{prefix:i}:{prefix:i,cursor:s});if(!n.ok)return;if(r.push(...n.data.keys),!n.data.truncated)return[...new Set(r)];const o=n.data.nextCursor;if(void 0===o||""===o)throw new t("VERIFICATION_FAILED","Held listing is truncated without a continuation cursor");s=o}throw new je("VERIFICATION_FAILED","Held listing exceeds the page limit")}async function He(e){const t=e.now??new Date,i=Ce(e.ownerDid),r=await Be(e.kv,Le(i));if(void 0===r)return;const s=e.email.replace(/[A-Z]+/g,e=>e.toLowerCase());let n;for(const o of r){const r=await Pe(e.kv,o,i,e,t);if("verified"!==r.kind||r.email!==s)continue;const a=r.match.verified.expiresAt.getTime();Ne(r.match.verified.expiresAt,t)&&(void 0===n||a>n.verified.expiresAt.getTime())&&(n=r.match)}return n}async function Me(e){const i=e.now??new Date,r=Ce(e.ownerDid),s=await Be(e.kv,Le(r));if(void 0===s)throw new t("OFFLINE","Held credentials could not be listed");const n=[];for(const o of s){const s=await e.kv.get(o);if(!s.ok){if("error"in s&&"KV_NOT_FOUND"===s.error.code)continue;throw new t("OFFLINE","A held credential could not be read")}let a;try{a=await ke(s.data.data,o,r,e,i)}catch(e){if(e instanceof A&&"bad-config"===e.code)throw e;continue}"verified"===a.kind&&Ne(a.match.verified.expiresAt,i)&&n.push(a.match)}return n.sort((e,t)=>{const i=t.issuedAt.getTime()-e.issuedAt.getTime();return 0!==i?i:e.recordId<t.recordId?-1:e.recordId>t.recordId?1:0})}const Ke="tinycloud.email-held/v1",$e=3e5;class Qe extends Error{constructor(e,t){super(t),this.retryable=!1,this.name="HeldSourceError",this.code=e}}async function Je(e){return async function(e,i){const{kv:r,address:s,holder:n,sessionDid:o,getCode:d,pendingStore:c,fetch:l,signal:u,now:p,allowHeldProfile:f,...h}=e,w=p??(()=>new Date),g=Ce(n.did);if(void 0!==o&&!T(o,g))throw new t("HOLDER_MISMATCH","Held acquisition holder must be the session account");const I=!0===f;let E;try{E=await async function(e,i,r,s,n){const o=s.trim().replace(/[A-Z]+/g,e=>e.toLowerCase()),a=async()=>function(e){let t;for(const i of e)(void 0===t||i.expiresAt.getTime()>t.expiresAt.getTime())&&(t=i);return t}((await async function(e,i,r,s){try{return await Me({...i,kv:e,ownerDid:r,now:s})}catch(e){if(e instanceof t||e instanceof A)throw e;throw new t("OFFLINE","Held credentials could not be read",{cause:e})}}(e,i,r,new Date(n().getTime()+$e))).filter(e=>e.email===o));try{return await a()}catch(e){if(!(e instanceof je))throw e}try{return await async function(e){const t=e.now??new Date,i=Ce(e.ownerDid),r=await Be(e.kv,Le(i));if(void 0===r)return[];const s=[],n=new Map;for(const o of r){const r=await Pe(e.kv,o,i,e,t);if("invalid"===r.kind)continue;if("expired"===r.kind){s.push(o);continue}const a={key:o,recordId:r.match.record.recordId,expiresAt:r.match.verified.expiresAt.getTime()},d=n.get(r.email);if(void 0===d){n.set(r.email,a);continue}const c=a.expiresAt>d.expiresAt||a.expiresAt===d.expiresAt&&a.recordId>d.recordId;n.set(r.email,c?a:d),s.push(c?d.key:a.key)}const o=[];for(const t of s)(await e.kv.delete(t)).ok&&o.push(t);return o}({...i,kv:e,ownerDid:r,now:n()}),await a()}catch(e){if(e instanceof je)throw new Qe("held-store-listing-limit","Saved held credentials list is too long to read; clear old ones");throw e}}(r,h,g,s,w)}catch(e){if(I||!(e instanceof t&&"OFFLINE"===e.code))throw e}if(void 0!==E)return{credential:E.record.credential,holderDid:g,expiresAt:E.verified.expiresAt};I&&function(e,i){const r=()=>new t("VERIFICATION_FAILED","The issuer policy does not accept the held credential issuer"),{issuerDid:s,issuerKid:n}=R;if(!Array.isArray(e.acceptedIssuers)||!e.acceptedIssuers.some(e=>e.issuerDid===s&&(void 0===e.kid||e.kid===n)))throw r();if(!m.is(e.issuerSet))throw r();const o=e.issuerSet.resolveIssuer(s,n),a=i.getTime();if(!o||!o.vcts.includes("opencredentials.email/v1")||!o.profiles.includes(Ke)||a<o.notBefore||null!==o.retiredAt&&a>=o.retiredAt||null!==o.notAfter&&a>=o.notAfter)throw r()}(h,w());const D=await i({address:s,holder:n,profile:Ke,getCode:d,pendingStore:ze(c,g,w),fetch:l,signal:u,now:w,allowHeldProfile:f});if("issued"!==D.status)throw new t("PROOF_REJECTED","Held acquisition did not issue a credential");const y=D.result.envelope.credential,S=w().getTime(),v=function(e){try{const t=JSON.parse((new TextDecoder).decode(a(e.split("~")[0].split(".")[1]))),i="object"==typeof t&&null!==t&&"iat"in t?t.iat:void 0;if("number"==typeof i&&Number.isSafeInteger(i))return 1e3*i}catch{}throw new t("VERIFICATION_FAILED","Issued credential is not readable")}(y);if(v-S>$e)throw new t("VERIFICATION_FAILED","client clock is more than 5 minutes behind the issuer");let _;try{_=await Ve({...h,kv:r,ownerDid:g,sdJwt:y,now:new Date(Math.max(S,v))})}catch{throw new t("VERIFIED_NOT_SAVED","Verified held credential could not be stored")}return{credential:y,holderDid:g,expiresAt:_.verified.expiresAt}}(e,ce)}function ze(e,t,i){if(void 0===e)return;const r=e=>void 0!==e&&e.profile===Ke&&T(e.holderDid,t);return{async findLive(t,i){const s=await e.findLive(t,i);return r(s)?s:void 0},put:t=>e.put(t),async delete(t){r(await e.get(t,i()))&&await e.delete(t)},async get(t,i){const s=await e.get(t,i);return r(s)?s:void 0}}}export{Y as EmailProofError,V as OpenCredentialsHttpTransport,ce as acquireEmailProof,Je as acquireHeldCredential,ae as completeEmailProof,be as createAccountHolderSigner,Z as createEd25519HolderSigner,re as createMemoryEmailProofPendingStore,He as findHeldCredential,L as interpretCredentialFlow,Me as listHeldEmailCredentials,oe as requestEmailProofCode,Ve as storeHeldCredential,De as verifyStoredEmailProof};
1
+ import{ACCOUNT_HOLDER_BINDING_DOMAIN as e,CredentialError as t,canonicalDigest as i,createEmailCredentialRequirement as r,credentialEndpointPath as s,credentialError as n,credentialRequirementDigest as o,decodeBase64Url as a,descriptorSatisfiesRequirement as d,encodeBase64Url as c,holderBindingCanonicalBytes as l,holderBindingSigningBytes as u,jcsCanonicalize as p,sha256Base64Url as f,validateCredentialFlowDescriptor as h,validateCredentialHolderBinding as w,validateCredentialRequirement as g,verifyEip191MessageSignature as I,verifyIssuedCredential as E}from"@tinycloud/sdk-core";import{ACCOUNT_BINDING_DOMAIN as D,HeldCredentialError as A,IssuerSet as m,parseIssuerSet as y,parsePkhDid as S,pkhPrincipalsEqual as v,registryKey as T,toChecksumAddress as _,verifyHeldEmailCredential as O}from"@tinycloud/sdk-core/held-credentials";var R=Object.freeze({witnessOrigin:"https://witness.credentials.org",issuerDid:"did:web:issuer.credentials.org",issuerKid:"did:web:issuer.credentials.org#controller",issuerX:"eEJI4xEobto4HtQ7Pg9R1vBOwcpfGRTlXDG5QfqLnGQ",descriptorDigest:"1tg-qphmKBVtNwzVg9xyz-xxqt_xtMXAsQyXw46m8S0"}),b=Object.freeze({type:e,protocol:"tinycloud.credentials/acquisition/v1",profile:"tinycloud.email-held/v1",profileVersion:1,descriptorDigest:"dc3_DuvzipXwYkTfjKqTaK1c3VS0YSPnaBsYSQriC0w",issuer:R.issuerDid,issuerKid:R.issuerKid,audience:"tinycloud://credentials",openerOrigin:"https://localhost",completionOrigin:"https://localhost",completionContext:"sdk-acquisition",credentialLifetimeSeconds:31536e3}),N=()=>new t("REQUEST_SUBSTITUTED","Holder binding was substituted"),C=(e,t)=>new Promise((i,r)=>{const s=setTimeout(i,e);t?.addEventListener("abort",()=>{clearTimeout(s),r(new DOMException("Aborted","AbortError"))},{once:!0})});async function L(e){const r="account_is_subject"===e.descriptor.subjectRelationship;if(r&&!0!==e.allowAccountSubject)throw new t("UNSUPPORTED_PROFILE","The held credential profile requires an explicit opt-in");const s=new Map(e.descriptor.steps.map(e=>[e.type,e])),n=new Set;let o="";const a=async r=>{const s=w(r);if(s.requestId!==e.requestId||s.descriptorDigest!==e.descriptorDigest||s.requirementDigest!==e.requirementDigest||s.holderDid!==e.holderDid||s.issuer!==e.descriptor.issuer.did||s.issuerKid!==e.descriptor.issuer.kid||s.profile!==e.descriptor.profile||s.openerOrigin!==e.openerOrigin||s.completionOrigin!==e.openerOrigin||"tinycloud://credentials"!==s.audience)throw new t("REQUEST_SUBSTITUTED","Holder binding was substituted");const n=e.descriptor.holderBinding.alg;if(s.type!==e.descriptor.holderBinding.domain||"EIP191"===n&&!e.transport.challengeNonce)throw new t("REQUEST_SUBSTITUTED","Holder binding was substituted");return"EIP191"===n&&await async function(e,t){const{descriptor:r}=t;if("EIP191"!==r.holderBinding.alg||e.type!==r.holderBinding.domain||e.requestId!==t.requestId||e.descriptorDigest!==t.descriptorDigest||e.requirementDigest!==t.requirementDigest||e.holderDid!==t.holderDid||e.issuer!==r.issuer.did||e.issuerKid!==r.issuer.kid||e.profile!==r.profile||e.openerOrigin!==t.openerOrigin||e.completionOrigin!==t.openerOrigin||e.audience!==b.audience||e.completionContext!==b.completionContext||e.type!==b.type||e.protocol!==b.protocol||e.profile!==b.profile||e.profileVersion!==b.profileVersion||e.descriptorDigest!==b.descriptorDigest||e.issuer!==b.issuer||e.issuerKid!==b.issuerKid||e.openerOrigin!==b.openerOrigin||e.completionOrigin!==b.completionOrigin||e.credentialLifetimeSeconds!==b.credentialLifetimeSeconds)throw N();if(void 0===t.challengeNonce||e.challengeNonce!==t.challengeNonce)throw N();if(e.normalizedClaimsDigest!==await i(t.requirement.claims))throw N();const s=Date.parse(e.expiresAt);if(void 0===t.serverExpiresAt||s!==Date.parse(t.serverExpiresAt)||Date.parse(e.issuedAt)!==s-6e5)throw N()}(s,{descriptor:e.descriptor,requirement:e.requirement,requestId:e.requestId,descriptorDigest:e.descriptorDigest,requirementDigest:e.requirementDigest,holderDid:e.holderDid,openerOrigin:e.openerOrigin,challengeNonce:e.transport.challengeNonce(e.requestId),serverExpiresAt:e.expiresAt}),s},d=async()=>{r&&void 0===e.transport.signedBinding?.(e.requestId)&&await a(await e.transport.holderBinding(e.requestId,e.verifier,e.signal))};for(;;){e.signal?.throwIfAborted();const i=await e.transport.state(e.requestId,e.verifier,e.signal);if(i.requestId!==e.requestId)throw new t("REQUEST_SUBSTITUTED","Credential request identity changed");if("expired"===i.state)throw new t("REQUEST_EXPIRED","Credential request expired",{state:i.state,correlationId:i.correlationId});if("canceled"===i.state)throw new t("CANCELED","Credential request was canceled",{state:i.state,correlationId:i.correlationId});if("issuer_unready"===i.state)throw new t("ISSUER_UNREADY","Credential issuer is not ready",{retryAfterMs:i.retryAfterMs,state:i.state,correlationId:i.correlationId});if("complete"===i.state)return void await d();if("ready_to_issue"===i.state||"issued"===i.state){await d(),"ready_to_issue"!==i.state||n.has("issue")?await(e.onWait?.()??C(i.retryAfterMs??50,e.signal)):(await e.transport.issue(e.requestId,e.verifier,e.signal),n.add("issue"));continue}const r=i.nextStep;if(!r){await(e.onWait?.()??C(i.retryAfterMs??50,e.signal));continue}const l=s.get(r.type);if(r.id!==r.type||!l||l.type!==r.type||l.version!==r.version)throw new t("REQUEST_SUBSTITUTED","Server selected an undeclared credential step");if(n.has(r.id)||i.transitionId===o)await(e.onWait?.()??C(i.retryAfterMs??50,e.signal));else{if(o=i.transitionId,"holder_signature"===r.type){e.onProgress?.({state:"signing",stepId:r.id,correlationId:i.correlationId});const s=await a(await e.transport.holderBinding(e.requestId,e.verifier,e.signal)),n=e.descriptor.holderBinding.alg;if("EIP191"===n!=("EIP191"===e.signing.holderKey?.alg))throw new t("REQUEST_SUBSTITUTED","Holder binding was substituted");const o=u(s);let d=await(e.signing.autoSign?.(s,o,e.signal));if(void 0===d){if(!e.signing.requestApproval)throw new t("SIGNATURE_REJECTED","OpenKey approval is required");try{d=await e.signing.requestApproval(s,o,e.signal)}catch(e){if(e instanceof t)throw e;throw new t("SIGNATURE_REJECTED","OpenKey approval was rejected",{cause:e})}}if(!(d instanceof Uint8Array)||0===d.length)throw new t("SIGNATURE_REJECTED","OpenKey signature is invalid");await e.transport.submitHolderSignature(e.requestId,e.verifier,"EIP191"===n?`0x${Array.from(d,e=>e.toString(16).padStart(2,"0")).join("")}`:c(d),e.signal,e.signing.holderKey)}else{e.onProgress?.({state:"collect_input"===r.type?"collecting":"proving",stepId:r.id,correlationId:i.correlationId});const s=e.handlers?.[r.type],n=e.proofHandler;if(!s&&!n){await(e.onWait?.()??C(i.retryAfterMs??50,e.signal));continue}if(!0===r.constraints.challengeRequired&&await e.transport.beginStep(e.requestId,e.verifier,r.type,e.signal),s){const t=await s({descriptor:e.descriptor,requirement:e.requirement,stepId:r.id,constraints:r.constraints,signal:e.signal});await e.transport.submitStep(e.requestId,e.verifier,r.id,t,e.signal)}else{let i;for(let s=1;;s+=1){const o=await n({stepId:r.id,constraints:r.constraints,display:{title:e.descriptor.display.title,description:e.descriptor.display.description,consent:e.descriptor.display.consent,progressLabel:e.descriptor.accessibility.progressLabel,errorLiveRegion:e.descriptor.accessibility.errorLiveRegion},inputs:e.descriptor.inputs.map(({id:e,label:t,schema:i})=>({id:e,label:t,schema:i})),...void 0===i?{}:{feedback:i},signal:e.signal});try{await e.transport.submitStep(e.requestId,e.verifier,r.id,o,e.signal);break}catch(n){if(!(n instanceof t)||"PROOF_REJECTED"!==n.code)throw n;const o=e.descriptor.lifecycle.maxProofAttempts-s;if("mailbox_otp"!==r.type||o<=0)throw new t("VERIFICATION_FAILED","The proof was not accepted",{state:o<=0?"proof_attempts_exhausted":"proof_rejected",cause:n});i={kind:"rejected",attemptsRemaining:o}}}}}n.add(r.id)}}}function q(e,i){if("object"!=typeof e||null===e||Array.isArray(e))throw new t("VERIFICATION_FAILED",`${i} is invalid`);return e}function U(e,i){if("string"!=typeof e||!/^[A-Za-z0-9_-]{16,128}$/.test(e))throw new t("REQUEST_SUBSTITUTED",`${i} is invalid`);return e}function x(e,i){if("string"!=typeof e||!Number.isFinite(Date.parse(e)))throw new t("VERIFICATION_FAILED",`${i} is invalid`);return new Date(e).toISOString()}var F=new Set(["REQUEST_EXPIRED","ISSUER_UNREADY","UNSUPPORTED_PROFILE","UNSUPPORTED_VERSION","SIGNATURE_REJECTED"]),P=class{constructor(e,i=globalThis.fetch.bind(globalThis),r={}){if(this.descriptor=e,this.fetchFn=i,this.options=r,this.nonces=new Map,this.bindings=new Map,"account_is_subject"===e.subjectRelationship&&!0!==r.allowAccountSubject)throw new t("UNSUPPORTED_PROFILE","The held credential profile requires an explicit opt-in")}url(e,t){return new URL(s(e,t),this.descriptor.issuer.origin).href}async request(e,i){let r;try{const t={method:i.method??"GET",credentials:"omit",cache:"no-store",redirect:"error",referrerPolicy:"no-referrer",signal:i.signal,headers:{accept:"application/json",...void 0===i.body?{}:{"content-type":"application/json"},...void 0===i.verifier?{}:{authorization:`Bearer ${i.verifier}`}},...void 0===i.body?{}:{body:JSON.stringify(i.body)}};r=await this.fetchFn(this.url(e,i.id),t)}catch(e){if(e instanceof DOMException&&"AbortError"===e.name)throw new t("CANCELED","Credential acquisition was canceled",{cause:e});throw new t("OFFLINE","OpenCredentials is unavailable",{cause:e})}if(!r.ok){let e;try{e=await r.json()}catch{e=void 0}const i=function(e,i,r){if("object"!=typeof e||null===e||Array.isArray(e))return;const s=e;if("code,correlationId,recoverable,state,type"!==Object.keys(s).sort().join(",")||"tinycloud.credentials/error/v1"!==s.type||"string"!=typeof s.code||"boolean"!=typeof s.recoverable||"string"!=typeof s.state||"string"!=typeof s.correlationId)return;if("PROOF_REJECTED"===s.code)return s.recoverable?new t("PROOF_REJECTED","The proof was not accepted",{state:s.state,correlationId:s.correlationId}):new t("VERIFICATION_FAILED","The proof attempt limit was reached",{state:"proof_attempts_exhausted",correlationId:s.correlationId});if("RATE_LIMITED"===s.code)return new t("ISSUER_UNREADY","Too many verification codes were requested",{state:"rate_limited",correlationId:s.correlationId,retryAfterMs:1e3*Number(i.headers.get("retry-after"))||void 0,recoverable:r?s.recoverable:void 0});if("CHALLENGE_EXPIRED"===s.code)return new t("REQUEST_EXPIRED","The credential challenge expired",{state:s.state,correlationId:s.correlationId,recoverable:r?s.recoverable:void 0});if("DESCRIPTOR_MISMATCH"===s.code&&(s.code="UNSUPPORTED_PROFILE"),!F.has(s.code))return;const n=s.code;return new t(n,`OpenCredentials rejected the request: ${n}`,{state:s.state,correlationId:s.correlationId,retryAfterMs:1e3*Number(i.headers.get("retry-after"))||void 0,recoverable:r?s.recoverable:void 0})}(e,r,!0===this.options.honorServerRecoverable);if(i)throw i;if(410===r.status)throw new t("REQUEST_EXPIRED","Credential request expired");if(409===r.status)throw new t("REQUEST_SUBSTITUTED","Credential request was replayed or substituted");if(503===r.status)throw new t("ISSUER_UNREADY","Credential issuer is not ready",{retryAfterMs:1e3*Number(r.headers.get("retry-after"))||void 0});throw new t("VERIFICATION_FAILED","OpenCredentials rejected the request")}if(204!==r.status)try{return await r.json()}catch(e){throw new t("VERIFICATION_FAILED","OpenCredentials response is invalid",{cause:e})}}async create(e){const i=q(await this.request("request",{method:"POST",body:{protocol:e.descriptor.protocol,profile:e.descriptor.profile,profileVersion:e.descriptor.profileVersion,descriptorDigest:e.descriptorDigest,requirementDigest:e.requirementDigest,holderDid:e.holderDid,inputs:e.inputs??e.requirement.claims,audience:b.audience,openerOrigin:e.openerOrigin,completionOrigin:e.openerOrigin,completionContext:b.completionContext,completionVerifierChallenge:e.completionVerifierChallenge},signal:e.signal}),"create response");if("tinycloud.credentials/acquisition-request/v1"!==i.type||i.protocol!==e.descriptor.protocol||"challenge"!==i.next||"challenge"!==i.endpoint)throw new t("VERIFICATION_FAILED","create response is invalid");const r=U(i.requestId,"requestId");return{requestId:r,locator:r,expiresAt:x(i.expiresAt,"expiresAt"),correlationId:r}}challengeNonce(e){return this.nonces.get(e)}signedBinding(e){return this.bindings.get(e)}proofStep(){return this.descriptor.steps.some(e=>"mailbox_otp"===e.type)?"mailbox_otp":"collect_input"}async state(e,i,r){const s=q(await this.request("state",{id:e,verifier:i,signal:r}),"state response");if("tinycloud.credentials/acquisition-state/v1"!==s.type||s.requestId!==e||s.profile!==this.descriptor.profile||1!==s.profileVersion)throw new t("REQUEST_SUBSTITUTED","Credential state response is substituted");const n={type:"OpenCredentialsAcquisitionState",version:1,requestId:e,transitionId:`${String(s.state)}:${String(s.resultPreviouslyRead??!1)}`,correlationId:e};if("challenge_required"===s.state){const e=this.proofStep();return{...n,state:"pending",nextStep:{id:e,type:e,version:1,constraints:{challengeRequired:!0}}}}if("account_is_subject"===this.descriptor.subjectRelationship&&("proof_required"===s.state||"holder_binding_required"===s.state||"holder_signature_required"===s.state||"ready_to_issue"===s.state||"issued"===s.state)){const i=s.challengeNonce,r=this.nonces.get(e);if("string"!=typeof i||""===i||void 0!==r&&r!==i)throw new t("REQUEST_SUBSTITUTED","Credential challenge nonce is missing or changed");this.nonces.set(e,U(i,"challengeNonce"))}if("proof_required"===s.state){const t=this.proofStep();return"account_is_subject"!==this.descriptor.subjectRelationship&&this.nonces.set(e,U(s.challengeNonce,"challengeNonce")),{...n,state:"pending",nextStep:{id:t,type:t,version:1,constraints:{}}}}if("holder_binding_required"===s.state||"holder_signature_required"===s.state)return{...n,state:"pending",nextStep:{id:"holder_signature",type:"holder_signature",version:1,constraints:{}}};if("ready_to_issue"===s.state)return{...n,state:"ready_to_issue"};if("issued"===s.state)return{...n,state:"complete"};throw new t("REQUEST_SUBSTITUTED","Credential state is unsupported")}async beginStep(e,i,r,s){const n=this.proofStep();if(r!==n)throw new t("REQUEST_SUBSTITUTED","Credential challenge step is substituted");const o=q(await this.request("challenge",{id:e,verifier:i,method:"POST",body:{step:n,stepVersion:1},signal:s}),"challenge response");if("tinycloud.credentials/challenge/v1"!==o.type||o.step!==n||1!==o.stepVersion)throw new t("REQUEST_SUBSTITUTED","Credential challenge is substituted");this.nonces.set(e,U(o.challengeNonce,"challengeNonce"))}async submitStep(e,i,r,s,n){const o=this.proofStep();if(r!==o)throw new t("REQUEST_SUBSTITUTED","Credential proof step is substituted");const a=this.nonces.get(e);if(!a)throw new t("REQUEST_SUBSTITUTED","Credential challenge is missing");await this.request("proof",{id:e,verifier:i,method:"POST",body:{step:o,stepVersion:1,challengeNonce:a,proof:s},signal:n})}async holderBinding(e,i,r){const s=q(await this.request("holder_binding",{id:e,verifier:i,signal:r}),"holder binding response");if("tinycloud.credentials/holder-binding-request/v1"!==s.type||s.signingDomain!==this.descriptor.holderBinding.domain||s.alg!==this.descriptor.holderBinding.alg||"string"!=typeof s.canonical)throw new t("REQUEST_SUBSTITUTED","Holder binding response is invalid");const n=w(s.binding);if(n.type!==s.signingDomain)throw new t("REQUEST_SUBSTITUTED","Holder binding type does not match its signing domain");if(c(l(n))!==s.canonical)throw new t("REQUEST_SUBSTITUTED","Holder binding canonical bytes were substituted");return this.bindings.set(e,n),n}async submitHolderSignature(e,i,r,s,n){const o=this.bindings.get(e);if(!o)throw new t("REQUEST_SUBSTITUTED","Holder binding was not retrieved");if("EIP191"===this.descriptor.holderBinding.alg&&!n)throw new t("REQUEST_SUBSTITUTED","An account holder must name its key and algorithm");const a=n?.alg??"EdDSA",d=n?.kid??`${o.holderDid}#${o.holderDid.replace("did:key:","")}`;await this.request("holder_signature",{id:e,verifier:i,method:"POST",body:{alg:a,kid:d,signature:r},signal:s})}async issue(e,t,i){await this.request("issue",{id:e,verifier:t,method:"POST",signal:i})}async result(e,r,s){const n=q(await this.request("result",{id:e,verifier:r,signal:s}),"result response");if("tinycloud.credentials/result/v1"!==n.type||n.protocol!==this.descriptor.protocol||n.profile!==this.descriptor.profile||1!==n.profileVersion||"vc+sd-jwt"!==n.format||n.descriptorDigest!==await i(this.descriptor)||n.issuer!==this.descriptor.issuer.did||n.issuerKid!==this.descriptor.issuer.kid||"string"!=typeof n.credential||await f(n.credential)!==n.credentialDigest)throw new t("VERIFICATION_FAILED","Issued result metadata is invalid");const o=q(n.holderBinding,"result holder binding");if(n.subject!==o.did||o.signingDomain!==this.descriptor.holderBinding.domain)throw new t("HOLDER_MISMATCH","Issued holder binding is invalid");const d=q(n.claims,"result claims"),c={};for(const[e,i]of Object.entries(d)){if("string"!=typeof i)throw new t("VERIFICATION_FAILED","Issued claims are invalid");c[e]=i}const l=q(n.validity,"result validity"),u=function(e){const i=e.split("~",1)[0]?.split(".")[1];if(!i)throw new t("VERIFICATION_FAILED","Issued SD-JWT is invalid");try{return q(JSON.parse((new TextDecoder).decode(a(i))),"SD-JWT payload")}catch(e){if(e instanceof t)throw e;throw new t("VERIFICATION_FAILED","Issued SD-JWT is invalid",{cause:e})}}(n.credential);if("string"!=typeof u.jti)throw new t("VERIFICATION_FAILED","Credential id is invalid");const p=x(l.issuedAt,"issuedAt"),h=x(l.expiresAt,"expiresAt"),w=q(n.status,"result status");if("none"!==w.type||w.freshnessSeconds!==this.descriptor.status.freshnessSeconds)throw new t("VERIFICATION_FAILED","Credential status is invalid");return{type:"OpenCredentialsIssuedCredential",version:1,protocol:this.descriptor.protocol,profile:{id:this.descriptor.profile,version:1},credentialType:{id:this.descriptor.format.vct,version:1},schema:this.descriptor.format.vct,format:"vc+sd-jwt",issuerDid:n.issuer,issuerKid:n.issuerKid,subjectDid:n.subject,holderDid:n.subject,claims:c,claimsDigest:await i(c),descriptorDigest:n.descriptorDigest,credentialId:u.jti,issuedAt:p,notBefore:p,expiresAt:h,status:{method:"none",freshnessSeconds:w.freshnessSeconds},credential:n.credential}}async issuerMetadata(e){return await this.request("issuer_metadata",{signal:e})}async checkStatus(e,t){return"none"===e.method&&e.freshnessSeconds===this.descriptor.status.freshnessSeconds}},k={id:"opencredentials.email/v1",version:1},V=9e5,j=`${R.witnessOrigin}/.well-known/opencredentials`,B=[{kid:R.issuerKid,alg:"EdDSA",jwk:{kty:"OKP",crv:"Ed25519",x:R.issuerX},validFrom:"2020-01-01T00:00:00Z",validUntil:"2100-01-01T00:00:00Z"}],H="tinycloud.email-proof/v1",M={"tinycloud.email-proof/v1":{descriptorDigest:R.descriptorDigest,requiredStep:"mailbox_otp",enabled:!0},"tinycloud.email-held/v1":{descriptorDigest:b.descriptorDigest,requiredStep:"mailbox_otp",enabled:!1}},K=b.openerOrigin,$="tinycloud.email-held/v1",Q=3e5,J=/^did:key:z6Mk[^#]+$/,z=/^[^\s@]+@[^\s@]+\.[^\s@]+$/,X=Symbol.for("nodejs.util.inspect.custom"),G={ADDRESS_INVALID:!1,HOLDER_INVALID:!1,CODE_INVALID:!0,RATE_LIMITED:!0,ISSUER_UNAVAILABLE:!0,NETWORK:!0,PROFILE_UNAVAILABLE:!1,CODE_REJECTED:!0,CODE_ATTEMPTS_EXHAUSTED:!1,SIGNATURE_REJECTED:!0,CREDENTIAL_INVALID:!1,SESSION_EXPIRED:!1,SESSION_INVALID:!1,CLIENT_CLOCK_SKEW:!1,CANCELED:!1,FAILED:!1},W={ADDRESS_INVALID:"Email address is invalid.",HOLDER_INVALID:"Holder must be a did:key Ed25519 identifier.",CODE_INVALID:"Verification code must be 8 digits.",ISSUER_UNAVAILABLE:"Email verification is unavailable right now.",NETWORK:"Could not reach the email verification service.",PROFILE_UNAVAILABLE:"The witness does not offer the email verification profile.",CODE_REJECTED:"Verification code was not accepted.",CODE_ATTEMPTS_EXHAUSTED:"Too many wrong codes. Request a new code.",SIGNATURE_REJECTED:"Holder signature was rejected.",CREDENTIAL_INVALID:"Issued credential failed verification.",SESSION_EXPIRED:"Email verification request expired. Request a new code.",SESSION_INVALID:"Email verification request is no longer valid. Request a new code.",CLIENT_CLOCK_SKEW:"Your device clock is more than 5 minutes behind. Correct it and try again.",CANCELED:"Email verification was canceled.",FAILED:"Email verification failed."},Y=class extends Error{constructor(e,t,i,r=G[t],s){super(s??("RATE_LIMITED"===t?function(e){const t="Too many codes were requested for this address.";if(void 0===e||!Number.isFinite(e)||e<=0)return`${t} Try again in about an hour.`;const i=Math.max(1,Math.ceil(e/6e4));return`${t} Try again in ${i} ${1===i?"minute":"minutes"}.`}(i):W[t])),this.name="EmailProofError",this.step=e,this.code=t,this.retryAfterMs=i,this.recoverable=r}};function Z(e,t){const i=e.indexOf("#"),r=-1===i?e:e.slice(0,i);if(-1!==i&&e.slice(i+1)!==r.slice(8))throw new Y("request","HOLDER_INVALID");if(!J.test(r))throw new Y("request","HOLDER_INVALID");return{did:r,alg:"EdDSA",kid:fe(r),sign:t}}function ee(e){const t={type:e.type,version:e.version,profile:e.profile,address:e.address,requestId:e.requestId,holderDid:e.holderDid,descriptorDigest:e.descriptorDigest,requirementDigest:e.requirementDigest,openerOrigin:e.openerOrigin,createdAt:e.createdAt,expiresAt:e.expiresAt,...void 0===e.serverExpiresAt?{}:{serverExpiresAt:e.serverExpiresAt}},i={...t};return te(i,"verifier",e.verifier),te(i,"toJSON",()=>({...t})),te(i,X,()=>({...t,verifier:"[redacted]"})),Object.freeze(i)}function te(e,t,i){Object.defineProperty(e,t,{value:i,enumerable:!1,writable:!1,configurable:!1})}function ie(e){return Math.min(Date.parse(e.expiresAt),Date.parse(e.createdAt)+V)}function re(){const e=new Map,t=t=>{for(const[i,r]of e)ie(r)<=t.getTime()&&e.delete(i)};return{async findLive(i,r){let s;t(r);for(const t of e.values())t.address===i&&(!s||Date.parse(t.createdAt)>Date.parse(s.createdAt))&&(s=t);return s},async put(t){e.set(t.requestId,t)},async delete(t){e.delete(t)},get:async(i,r)=>(t(r),e.get(i))}}var se=class extends Error{},ne=async()=>{throw new se("code requested")};async function oe(e){const t=e.profile??H;we(t,"request",e.allowHeldProfile);const r=t===$;r&&he(e.holder,"request",t);const s=le(e.address,t);r||he(e.holder,"request",t);const n=e.now??(()=>new Date),a=e.signal??AbortSignal.timeout(6e4),d=ge(s,t),l=await o(d),u=await Ie(t,d,{fetch:e.fetch,signal:a},"request",e.allowHeldProfile),p=await i(u),h=c(crypto.getRandomValues(new Uint8Array(32))),w=new P(u,e.fetch,{honorServerRecoverable:!0,...r?{allowAccountSubject:!0}:{}}),g=n().getTime();let I;try{I=await w.create({descriptor:u,descriptorDigest:p,requirement:d,requirementDigest:l,holderDid:e.holder.did,openerOrigin:K,completionVerifierChallenge:await f(h),signal:a})}catch(e){throw me(e,"request",a)}const E=Date.parse(I.expiresAt);if(!Number.isFinite(E))throw new Y("request","FAILED");const D=E-6e5;if(r&&D-n().getTime()>Q)throw new Y("request","CLIENT_CLOCK_SKEW");const A=ee({type:"TinyCloudEmailProofPending",version:1,profile:t,address:s,requestId:I.requestId,verifier:h,holderDid:e.holder.did,descriptorDigest:p,requirementDigest:l,openerOrigin:K,createdAt:new Date(g).toISOString(),expiresAt:new Date(r?g+Math.min(E-D,V):Math.min(E,g+V)).toISOString(),...r?{serverExpiresAt:I.expiresAt}:{}});try{await L({descriptor:u,...r?{allowAccountSubject:!0}:{},requirement:d,requestId:I.requestId,verifier:h,holderDid:e.holder.did,descriptorDigest:p,requirementDigest:l,openerOrigin:K,...r?{expiresAt:I.expiresAt}:{},transport:w,signing:Ae(e.holder,r),handlers:{mailbox_otp:ne},signal:a})}catch(e){if(e instanceof se)return A;throw me(e,"request",a)}throw new Y("request","FAILED")}async function ae(e){return de(e,B)}async function de(e,r){const{pending:s}=e,n=e.now??(()=>new Date);if(!function(e){if("object"!=typeof e||null===e)return!1;const t=e;return"TinyCloudEmailProofPending"===t.type&&1===t.version&&t.openerOrigin===K&&[t.profile,t.address,t.requestId,t.verifier,t.holderDid,t.descriptorDigest,t.requirementDigest,t.openerOrigin,t.createdAt,t.expiresAt].every(e=>"string"==typeof e)&&Number.isFinite(Date.parse(t.createdAt))&&Number.isFinite(Date.parse(t.expiresAt))}(s))throw new Y("session","SESSION_INVALID");we(s.profile,"session",e.allowHeldProfile);const a=s.profile===$;if(a&&!Number.isFinite(Date.parse(s.serverExpiresAt??"")))throw new Y("session","SESSION_INVALID");if(ie(s)<=n().getTime())throw new Y("session","SESSION_EXPIRED");if(!/^\d{8}$/.test(e.code))throw new Y("code","CODE_INVALID");if(he(e.holder,"code",s.profile),e.holder.did!==s.holderDid)throw new Y("session","SESSION_INVALID");const d=e.signal??AbortSignal.timeout(6e4),c=ge(s.address,s.profile);if(await o(c)!==s.requirementDigest)throw new Y("session","SESSION_INVALID");const l=await Ie(s.profile,c,{fetch:e.fetch,signal:d},"session",e.allowHeldProfile),u=await i(l);if(u!==s.descriptorDigest)throw new Y("session","SESSION_INVALID");const p=new P(l,e.fetch,{honorServerRecoverable:!0,...a?{allowAccountSubject:!0}:{}});try{const t=await p.state(s.requestId,s.verifier,d);if(!0===t.nextStep?.constraints.challengeRequired)throw new Y("session","SESSION_INVALID");await L({descriptor:l,...a?{allowAccountSubject:!0}:{},requirement:c,requestId:s.requestId,verifier:s.verifier,holderDid:s.holderDid,descriptorDigest:u,requirementDigest:s.requirementDigest,openerOrigin:s.openerOrigin,...a?{expiresAt:s.serverExpiresAt}:{},transport:p,signing:Ae(e.holder,a),handlers:{mailbox_otp:async()=>({otp:e.code})},signal:d})}catch(e){throw me(e,"code",d)}try{const e=await p.result(s.requestId,s.verifier,d);if(a){const i=await async function(e){const{envelope:i,pending:r,descriptor:s}=e,n=e=>new t("VERIFICATION_FAILED",e),o=Date.parse(i.issuedAt),a=e.now().getTime();if(!Number.isFinite(o)||o-a>Q)throw n("client clock is more than 5 minutes behind the issuer");const d=e.issuerKeys.find(e=>e.kid===R.issuerKid);if(!d)throw n("no pinned issuer key");const c=y({format:"tinycloud.credentials-issuers/v1",version:1,issuers:[{issuerDid:R.issuerDid,kid:R.issuerKid,alg:"EdDSA",publicKey:d.jwk.x,vcts:[k.id],profiles:[$],notBefore:"2020-01-01T00:00:00Z",retiredAt:null,notAfter:null}]},{didMethods:{issuer:["web"]}}),l=O(i.credential,{now:new Date(Math.max(a,o)),owner:r.holderDid,didMethods:{issuer:["web"]},acceptedIssuers:[{issuerDid:R.issuerDid,kid:R.issuerKid}],issuerSet:c}),u=e.transport.signedBinding(r.requestId),p=Object.keys(i.claims).sort().join(),f=e=>Math.floor(e/1e3);if(i.subjectDid!==r.holderDid||i.holderDid!==r.holderDid||"email,emailDomain"!==p||i.claims.email!==l.claims.email||i.claims.emailDomain!==l.claims.emailDomain||i.claims.email!==r.address||f(Date.parse(i.issuedAt))!==f(l.issuedAt.getTime())||f(Date.parse(i.expiresAt))!==f(l.expiresAt.getTime())||i.descriptorDigest!==e.descriptorDigest||i.profile.id!==$||1!==i.profile.version||i.issuerDid!==R.issuerDid||i.issuerKid!==R.issuerKid||"vc+sd-jwt"!==i.format||"none"!==i.status.method||i.status.freshnessSeconds!==s.status.freshnessSeconds)throw n("issued credential does not match the request");if(u?.type!==s.holderBinding.domain||!("credentialLifetimeSeconds"in u))throw n("signed binding is missing");if(l.credentialId!==u.jti||(l.expiresAt.getTime()-l.issuedAt.getTime())/1e3!==u.credentialLifetimeSeconds)throw n("credential does not match the binding the account signed");return l}({envelope:e,pending:s,descriptor:l,descriptorDigest:u,transport:p,issuerKeys:r,now:n});return{envelope:e,verified:i,credentialId:i.credentialId,issuedAt:i.issuedAt.toISOString(),expiresAt:i.expiresAt.toISOString(),descriptor:l}}const i=await E({envelope:e,descriptor:l,descriptorDigest:u,requirement:c,holderDid:s.holderDid,issuerMetadata:Ee(r),now:n(),checkStatus:(e,t)=>p.checkStatus(e,t),signal:d});return{envelope:e,verified:i,credentialId:i.credentialId,issuedAt:i.issuedAt,expiresAt:i.expiresAt,descriptor:l}}catch(e){throw me(e,"credential",d)}}async function ce(e){return async function(e,t){const i=e.profile??H;we(i,"request",e.allowHeldProfile);const r=le(e.address,i),s=e.now??(()=>new Date),n=e.pendingStore,o=n?await n.findLive(r,s()):void 0;let a=o?.profile===i?o:void 0;if(a&&i===$&&!Number.isFinite(Date.parse(a.serverExpiresAt??"")))throw await(n?.delete(a.requestId).catch(()=>{})),new Y("session","SESSION_INVALID");a||(a=await oe({...e,address:r}),await(n?.put(a)));const d=ee(a);if(!e.getCode)return{status:"code-requested",pending:d};const c=await e.getCode({pending:d});try{const i=await de({...e,pending:a,code:c},t),r=[];if(n)try{await n.delete(a.requestId)}catch{r.push("The pending request could not be deleted after success; it expires at its deadline.")}return{status:"issued",result:i,warnings:r}}catch(e){throw e instanceof Y&&e.recoverable||await(n?.delete(a.requestId).catch(()=>{})),e}}(e,B)}function le(e,t){if(t===$)return function(e){const t=()=>new Y("request","ADDRESS_INVALID"),i=e.trim();if(/[^\x00-\x7f]/.test(i))throw t();const r=i.toLowerCase(),s=r.split("@");if(r.length<3||r.length>254||2!==s.length||/[^\x21-\x7e]/.test(r))throw t();const[n,o]=s;if(n.length>64||!ue.test(n)||n.startsWith("+"))throw t();if(o.length>253||!o.includes(".")||!o.split(".").every(e=>e.length<=63&&pe.test(e)))throw t();return r}(e);const i=e.trim();if(i.length>254||!z.test(i))throw new Y("request","ADDRESS_INVALID");return i}var ue=/^[a-z0-9!#$%&'*+\-/=?^_`{|}~]+(\.[a-z0-9!#$%&'*+\-/=?^_`{|}~]+)*$/,pe=/^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/;function fe(e){return`${e}#${e.slice(8)}`}function he(e,t,i){if(i===$)return function(e,t){const i=S(e.did),r=null!==i&&"1"===i.chainId?`did:pkh:eip155:1:${_(i.address)}`:void 0;if(void 0===r||e.did!==r||"EIP191"!==e.alg||e.kid!==`${r}#blockchainAccountId`)throw new Y(t,"HOLDER_INVALID")}(e,t);if(!J.test(e.did)||"EdDSA"!==e.alg||e.kid!==fe(e.did))throw new Y(t,"HOLDER_INVALID")}function we(e,t,i){const r=Object.prototype.hasOwnProperty.call(M,e)?M[e]:void 0;if(!r||!r.enabled&&(!0!==i||e!==$))throw new Y(t,"PROFILE_UNAVAILABLE",void 0,void 0,"This SDK build doesn't enable the email verification profile.");return r}function ge(e,t){return t===$?g({type:"TinyCloudCredentialRequirement",version:1,profile:{id:t,version:1},credentialType:k,claims:{email:e},maxAgeSeconds:31536e3}):r({email:e,profile:{id:t,version:1},credentialType:k})}async function Ie(e,r,s,n,o){const a=we(e,n,o);let c;try{c=await async function(e,r,s={}){let n;try{n=new URL(r)}catch{throw new t("UNSUPPORTED_PROFILE","Discovery URL is invalid")}if("https:"!==n.protocol||!["/.well-known/opencredentials","/v1/credential-types"].includes(n.pathname)||n.search||n.hash)throw new t("UNSUPPORTED_PROFILE","Discovery URL is not an allowed catalog endpoint");const o={credentials:"omit",cache:"no-store",redirect:"error",referrerPolicy:"no-referrer",signal:s.signal};let a;try{a=await(s.fetch??globalThis.fetch.bind(globalThis))(n,o)}catch(e){throw new t("OFFLINE","Credential discovery is unavailable",{cause:e})}if(!a.ok)throw new t(503===a.status?"ISSUER_UNREADY":"OFFLINE","Credential discovery is unavailable");const c=await a.json();if("tinycloud.credentials/catalog/v1"!==c.type||"tinycloud.credentials/acquisition/v1"!==c.protocol||1!==c.catalogVersion||!Array.isArray(c.profiles))throw new t("DESCRIPTOR_INVALID","Credential catalog is invalid");for(const t of c.profiles){if("object"!=typeof t||null===t||Array.isArray(t))continue;const r=t;if(!0===r.supported&&!0===r.enabled&&("ready"===r.readiness||"degraded"===r.readiness))try{const t=h(r.descriptor);if(d(t,e)&&r.descriptorDigest===await i(t))return t}catch{}}throw new t("UNSUPPORTED_PROFILE","No available credential profile satisfies the requirement")}(r,j,{fetch:s.fetch,signal:s.signal})}catch(e){throw function(e,t,i){return t.aborted&&"TimeoutError"!==t.reason?.name?new Y(i,"CANCELED"):me(e,i,t)}(e,s.signal,n)}if(c.issuer.origin!==R.witnessOrigin||c.issuer.did!==R.issuerDid||!c.steps.some(e=>e.type===a.requiredStep))throw new Y(n,"PROFILE_UNAVAILABLE");if(await i(c)!==a.descriptorDigest)throw new Y(n,"PROFILE_UNAVAILABLE");return c}function Ee(e){return{type:"OpenCredentialsIssuerMetadata",version:1,origin:R.witnessOrigin,issuerDid:R.issuerDid,keys:e,cache:{maxAgeSeconds:3600,etag:"pinned"}}}async function De(e){return async function(e,r){const{record:s,requirement:n,holderDid:a}=e,d=s.descriptor;if(s.descriptorDigest!==R.descriptorDigest||await i(d)!==R.descriptorDigest)throw new t("VERIFICATION_FAILED","stored descriptor does not match the pinned descriptor digest");const c={type:"OpenCredentialsIssuedCredential",version:1,protocol:d.protocol,profile:s.profile,credentialType:s.credentialType,schema:s.schema,format:"vc+sd-jwt",issuerDid:s.issuerDid,issuerKid:s.issuerKid,subjectDid:s.subjectDid,holderDid:s.holderDid,claims:s.claims,claimsDigest:s.claimsDigest,descriptorDigest:s.descriptorDigest,credentialId:s.credentialId,issuedAt:s.issuedAt,notBefore:s.notBefore,expiresAt:s.expiresAt,status:s.status,credential:s.credential},l=await E({envelope:c,descriptor:d,descriptorDigest:R.descriptorDigest,requirement:n,holderDid:a,issuerMetadata:Ee(r),now:e.now,checkStatus:async e=>"none"===e.method&&e.freshnessSeconds===d.status.freshnessSeconds,signal:e.signal});if(s.holderDid!==a||s.ownerDid!==a)throw new t("HOLDER_MISMATCH","stored record belongs to another holder");if(s.credentialDigest!==l.credentialDigest)throw new t("VERIFICATION_FAILED","stored credential digest does not match the verified credential");if(s.requirementDigest!==await o(n))throw new t("VERIFICATION_FAILED","stored requirement digest does not match the requirement");if(s.recordId!==await i({credentialDigest:l.credentialDigest,holderDid:s.ownerDid}))throw new t("VERIFICATION_FAILED","stored record id does not match its credential");return l}(e,B)}function Ae(e,t){return{autoSign:async(i,r)=>{try{return await e.sign(r)}catch(e){const i=e instanceof DOMException&&("TimeoutError"===e.name||"AbortError"===e.name);if(!t||e instanceof Y||i)throw e;throw new Y("credential","SIGNATURE_REJECTED")}},holderKey:{alg:e.alg,kid:e.kid}}}function me(e,t,i){if(e instanceof Y)return e;if(e instanceof DOMException&&"TimeoutError"===e.name)return new Y(t,"NETWORK");const r=n(e),s=r.details;switch(r.code){case"ISSUER_UNREADY":return"rate_limited"===s.state?new Y(t,"RATE_LIMITED",s.retryAfterMs,r.recoverable):new Y(t,"ISSUER_UNAVAILABLE",void 0,r.recoverable);case"OFFLINE":return i?.aborted&&"TimeoutError"!==i.reason?.name?new Y(t,"CANCELED"):new Y(t,"NETWORK");case"UNSUPPORTED_PROFILE":case"UNSUPPORTED_VERSION":case"DESCRIPTOR_INVALID":return new Y(t,"PROFILE_UNAVAILABLE");case"PROOF_REJECTED":return new Y("code","CODE_REJECTED",void 0,!0);case"VERIFICATION_FAILED":return"proof_attempts_exhausted"===s.state?new Y("code","CODE_ATTEMPTS_EXHAUSTED"):"credential"===t?new Y("credential","CREDENTIAL_INVALID"):"code"===t?new Y("code","CODE_REJECTED",void 0,!1):new Y(t,"FAILED");case"HOLDER_MISMATCH":return new Y("credential","CREDENTIAL_INVALID");case"REQUEST_EXPIRED":return new Y("session","SESSION_EXPIRED");case"REQUEST_SUBSTITUTED":return new Y("session","SESSION_INVALID");case"SIGNATURE_REJECTED":return new Y("credential","SIGNATURE_REJECTED",void 0,r.recoverable);case"CANCELED":return new Y(t,"CANCELED");default:return new Y(t,"FAILED")}}function ye(){return new Y("request","HOLDER_INVALID",void 0,void 0,"The wallet signer signs only the exact account binding for this request.")}function Se(){return new Y("request","HOLDER_INVALID")}const ve=["audience","challengeNonce","completionContext","completionOrigin","credentialLifetimeSeconds","descriptorDigest","expiresAt","holderDid","issuedAt","issuer","issuerKid","jti","normalizedClaimsDigest","openerOrigin","profile","profileVersion","protocol","requestId","requirementDigest","type"],Te=/^urn:uuid:[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/,_e=/^[A-Za-z0-9_-]{32}$/,Oe=/^[A-Za-z0-9_-]{43}$/,Re=/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$/;function be(e){try{return new TextDecoder("utf-8",{fatal:!0,ignoreBOM:!0}).decode(e)}catch{throw ye()}}function Ne(e,t){const i=S(e);if(null===i||"1"!==i.chainId)throw Se();const r=_(i.address),s=`did:pkh:eip155:1:${r}`;return{did:s,alg:"EIP191",kid:`${s}#blockchainAccountId`,sign:async e=>{const i=new Uint8Array(e);!function(e,t){const i=be(e);let r,s;try{r=JSON.parse(i),s=p(r)}catch{throw ye()}if(s!==i||"object"!=typeof r||null===r||Array.isArray(r))throw ye();const n=r;if(Object.keys(n).sort().join()!==ve.join())throw ye();for(const e of ve)if("profileVersion"!==e&&"credentialLifetimeSeconds"!==e&&("string"!=typeof n[e]||""===n[e]))throw ye();const o=e=>n[e];if(Object.keys(b).some(e=>n[e]!==b[e])||!v(n.holderDid,t)||!Te.test(o("jti"))||!_e.test(o("requestId"))||!_e.test(o("challengeNonce"))||!Oe.test(o("requirementDigest"))||!Oe.test(o("normalizedClaimsDigest"))||!Re.test(o("issuedAt"))||!Re.test(o("expiresAt"))||Date.parse(o("expiresAt"))-Date.parse(o("issuedAt"))!==6e5)throw ye()}(function(e){const t=(new TextEncoder).encode(D);if(e.length<=t.length+1||0!==e[t.length])throw ye();for(let i=0;i<t.length;i++)if(e[i]!==t[i])throw ye();return e.subarray(t.length+1)}(i),s);const n=be(i),o=await t(i),a=o[64];if(65!==o.length||27!==a&&28!==a)throw Se();if(!await I(n,function(e){return`0x${Array.from(e,e=>e.toString(16).padStart(2,"0")).join("")}`}(o),r))throw Se();return o}}}function Ce(e,t){return e.getTime()-t.getTime()>6e5}const Le="This app can't read held credentials: the session may lack kv get and list on v1/held/ (skipPrefix), or may need to sign in again.",qe="permission_denied";function Ue(e){let t="object"==typeof e&&null!==e&&"error"in e?e.error:void 0,i=!1;for(let e=0;e<8&&"object"==typeof t&&null!==t;e+=1){const e=t,r=e.meta,s=[e.status,e.statusCode,"object"==typeof r&&null!==r?r.status:void 0].find(e=>"number"==typeof e&&Number.isInteger(e)&&e>=400&&e<=599);if(void 0!==s)return 401===s||403===s;"AUTH_UNAUTHORIZED"===e.code&&(i=!0),t=e.cause}return i}function xe(e){const i=S(e);if(null===i)throw new t("ACTIVE_SESSION_REQUIRED","Held credentials require a did:pkh:eip155 account owner");if("1"!==i.chainId)throw new t("ACTIVE_SESSION_REQUIRED","Held credentials require an Ethereum mainnet (chain 1) account owner");return`did:pkh:eip155:1:${_(i.address)}`}function Fe(e){return`v1/held/${T(e)}/`}function Pe(e,t){return`${Fe(e)}${t}`}function ke(e){if("object"!=typeof e||null===e)return!1;const t=e;return"TinyCloudHeldCredential"===t.type&&1===t.version&&"string"==typeof t.ownerDid&&"string"==typeof t.recordId&&"string"==typeof t.credentialDigest&&"string"==typeof t.credential&&"string"==typeof t.storedAt}function Ve(e,t,i){return{issuerSet:e.issuerSet,acceptedIssuers:e.acceptedIssuers,didMethods:e.didMethods,now:t,owner:i}}async function je(e){return{type:"TinyCloudHeldStorageReceipt",version:1,ownerDid:e.ownerDid,recordId:e.recordId,recordDigest:await i(e),storedAt:e.storedAt}}async function Be(e){const r=e.now??new Date,s=xe(e.ownerDid);let n;try{n=O(e.sdJwt,Ve(e,r,s))}catch(e){throw function(e){if(!(e instanceof A))return e;const i="nonce-account-mismatch"===e.code?"HOLDER_MISMATCH":"VERIFICATION_FAILED";return new t(i,e.message,{cause:e})}(e)}const o=e.sdJwt;if("string"!=typeof o)throw new t("VERIFICATION_FAILED","Held credential must be an SD-JWT string");if("string"!=typeof n.claims.email)throw new t("VERIFICATION_FAILED","Held credential must disclose an email claim");if(!Ce(n.expiresAt,r))throw new t("VERIFICATION_FAILED","Held credential expires within the reuse margin");const a=await i(o),d=await i({credentialDigest:a,holderDid:s}),c={type:"TinyCloudHeldCredential",version:1,ownerDid:s,recordId:d,credentialDigest:a,credential:o,storedAt:r.toISOString()},l=await async function(e,i,r){const s=(e=!1)=>new t("VERIFIED_NOT_SAVED","Held credential could not be confirmed in storage",e?{state:qe}:{}),n=await e.batchPut([{key:i,value:r}]).catch(()=>{});if(!0!==n?.ok)throw s(void 0!==n&&Ue(n));const o=await e.get(i).catch(()=>{});if(void 0!==o&&!o.ok&&Ue(o))throw s(!0);const a=!0===o?.ok?o.data.data:void 0;if(!ke(a)||a.recordId!==r.recordId||a.credentialDigest!==r.credentialDigest||a.credential!==r.credential||!v(a.ownerDid,r.ownerDid))throw s();return a}(e.kv,Pe(s,d),c);return{record:l,receipt:await je(l),verified:n}}async function He(e,i,r,s,n){const o=await e.get(i);if(!o.ok&&Ue(o))throw new t("PERMISSION_DENIED",Le);return Me(o.ok?o.data.data:void 0,i,r,s,n)}async function Me(e,t,r,s,n){if(!ke(e))return{kind:"invalid"};if(!v(e.ownerDid,r))return{kind:"invalid"};const o=await i(e.credential),a=await i({credentialDigest:o,holderDid:r});if(e.credentialDigest!==o||e.recordId!==a||t!==Pe(r,a))return{kind:"invalid"};let d;try{d=O(e.credential,Ve(s,n,r))}catch(e){if(!(e instanceof A)||"bad-config"===e.code)throw e;return{kind:"expired"===e.code?"expired":"invalid"}}const c=d.claims.email;return"string"!=typeof c?{kind:"invalid"}:{kind:"verified",email:c,match:{record:e,verified:d,recordId:a,email:c,issuedAt:d.issuedAt,expiresAt:d.expiresAt,issuer:d.issuer}}}class Ke extends t{}async function $e(e,i){const r=[];let s;for(let n=0;n<50;n+=1){const n=await e.list(void 0===s?{prefix:i}:{prefix:i,cursor:s});if(!n.ok){if(Ue(n))throw new t("PERMISSION_DENIED",Le);return}if(r.push(...n.data.keys),!n.data.truncated)return[...new Set(r)];const o=n.data.nextCursor;if(void 0===o||""===o)throw new t("VERIFICATION_FAILED","Held listing is truncated without a continuation cursor");s=o}throw new Ke("VERIFICATION_FAILED","Held listing exceeds the page limit")}async function Qe(e){const t=e.now??new Date,i=xe(e.ownerDid),r=await $e(e.kv,Fe(i));if(void 0===r)return;const s=e.email.replace(/[A-Z]+/g,e=>e.toLowerCase());let n;for(const o of r){const r=await He(e.kv,o,i,e,t);if("verified"!==r.kind||r.email!==s)continue;const a=r.match.verified.expiresAt.getTime();Ce(r.match.verified.expiresAt,t)&&(void 0===n||a>n.verified.expiresAt.getTime())&&(n=r.match)}return n}async function Je(e){const i=e.now??new Date,r=xe(e.ownerDid),s=await $e(e.kv,Fe(r));if(void 0===s)throw new t("OFFLINE","Held credentials could not be listed");const n=[];for(const o of s){const s=await e.kv.get(o);if(!s.ok){if("error"in s&&"KV_NOT_FOUND"===s.error.code)continue;if(Ue(s))throw new t("PERMISSION_DENIED",Le);throw new t("OFFLINE","A held credential could not be read")}let a;try{a=await Me(s.data.data,o,r,e,i)}catch(e){if(e instanceof A&&"bad-config"===e.code)throw e;continue}"verified"===a.kind&&Ce(a.match.verified.expiresAt,i)&&n.push(a.match)}return n.sort((e,t)=>{const i=t.issuedAt.getTime()-e.issuedAt.getTime();return 0!==i?i:e.recordId<t.recordId?-1:e.recordId>t.recordId?1:0})}const ze="tinycloud.email-held/v1",Xe=3e5;class Ge extends Error{constructor(e,t){super(t),this.retryable=!1,this.name="HeldSourceError",this.code=e}}async function We(e){return async function(e,i){const{kv:r,address:s,holder:n,sessionDid:o,getCode:d,pendingStore:c,fetch:l,signal:u,now:p,allowHeldProfile:f,...h}=e,w=p??(()=>new Date),g=xe(n.did);if(void 0!==o&&!v(o,g))throw new t("HOLDER_MISMATCH","Held acquisition holder must be the session account");const I=!0===f;let E;try{E=await async function(e,i,r,s,n){const o=s.trim().replace(/[A-Z]+/g,e=>e.toLowerCase()),a=async()=>function(e){let t;for(const i of e)(void 0===t||i.expiresAt.getTime()>t.expiresAt.getTime())&&(t=i);return t}((await async function(e,i,r,s){try{return await Je({...i,kv:e,ownerDid:r,now:s})}catch(e){if(e instanceof t||e instanceof A)throw e;throw new t("OFFLINE","Held credentials could not be read",{cause:e})}}(e,i,r,new Date(n().getTime()+Xe))).filter(e=>e.email===o));try{return await a()}catch(e){if(!(e instanceof Ke))throw e}try{return await async function(e){const i=e.now??new Date,r=xe(e.ownerDid),s=await $e(e.kv,Fe(r));if(void 0===s)return[];const n=[],o=new Map;for(const t of s){const s=await He(e.kv,t,r,e,i);if("invalid"===s.kind)continue;if("expired"===s.kind){n.push(t);continue}const a={key:t,recordId:s.match.record.recordId,expiresAt:s.match.verified.expiresAt.getTime()},d=o.get(s.email);if(void 0===d){o.set(s.email,a);continue}const c=a.expiresAt>d.expiresAt||a.expiresAt===d.expiresAt&&a.recordId>d.recordId;o.set(s.email,c?a:d),n.push(c?d.key:a.key)}const a=[];for(const i of n){const r=await e.kv.delete(i);if(!r.ok&&Ue(r))throw new t("PERMISSION_DENIED","This app can't delete held credentials: the session may lack kv del on v1/held/ (skipPrefix), or may need to sign in again.");r.ok&&a.push(i)}return a}({...i,kv:e,ownerDid:r,now:n()}),await a()}catch(e){if(e instanceof Ke)throw new Ge("held-store-listing-limit","Saved held credentials list is too long to read; clear old ones");throw e}}(r,h,g,s,w)}catch(e){if(I||!(e instanceof t)||"OFFLINE"!==e.code&&"PERMISSION_DENIED"!==e.code)throw e}if(void 0!==E)return{credential:E.record.credential,holderDid:g,expiresAt:E.verified.expiresAt};I&&function(e,i){const r=()=>new t("VERIFICATION_FAILED","The issuer policy does not accept the held credential issuer"),{issuerDid:s,issuerKid:n}=R;if(!Array.isArray(e.acceptedIssuers)||!e.acceptedIssuers.some(e=>e.issuerDid===s&&(void 0===e.kid||e.kid===n)))throw r();if(!m.is(e.issuerSet))throw r();const o=e.issuerSet.resolveIssuer(s,n),a=i.getTime();if(!o||!o.vcts.includes("opencredentials.email/v1")||!o.profiles.includes(ze)||a<o.notBefore||null!==o.retiredAt&&a>=o.retiredAt||null!==o.notAfter&&a>=o.notAfter)throw r()}(h,w());const D=await i({address:s,holder:n,profile:ze,getCode:d,pendingStore:Ye(c,g,w),fetch:l,signal:u,now:w,allowHeldProfile:f});if("issued"!==D.status)throw new t("PROOF_REJECTED","Held acquisition did not issue a credential");const y=D.result.envelope.credential,S=w().getTime(),T=function(e){try{const t=JSON.parse((new TextDecoder).decode(a(e.split("~")[0].split(".")[1]))),i="object"==typeof t&&null!==t&&"iat"in t?t.iat:void 0;if("number"==typeof i&&Number.isSafeInteger(i))return 1e3*i}catch{}throw new t("VERIFICATION_FAILED","Issued credential is not readable")}(y);if(T-S>Xe)throw new t("VERIFICATION_FAILED","client clock is more than 5 minutes behind the issuer");let _;try{_=await Be({...h,kv:r,ownerDid:g,sdJwt:y,now:new Date(Math.max(S,T))})}catch(e){const i=e instanceof t&&e.details.state===qe;throw new t("VERIFIED_NOT_SAVED","Verified held credential could not be stored",i?{state:qe}:{})}return{credential:y,holderDid:g,expiresAt:_.verified.expiresAt}}(e,ce)}function Ye(e,t,i){if(void 0===e)return;const r=e=>void 0!==e&&e.profile===ze&&v(e.holderDid,t);return{async findLive(t,i){const s=await e.findLive(t,i);return r(s)?s:void 0},put:t=>e.put(t),async delete(t){r(await e.get(t,i()))&&await e.delete(t)},async get(t,i){const s=await e.get(t,i);return r(s)?s:void 0}}}export{Y as EmailProofError,P as OpenCredentialsHttpTransport,ce as acquireEmailProof,We as acquireHeldCredential,ae as completeEmailProof,Ne as createAccountHolderSigner,Z as createEd25519HolderSigner,re as createMemoryEmailProofPendingStore,Qe as findHeldCredential,L as interpretCredentialFlow,Je as listHeldEmailCredentials,oe as requestEmailProofCode,Be as storeHeldCredential,De as verifyStoredEmailProof};