@tempoxyz/id 0.0.0-pr-232.sha-a0eb0e8 → 0.0.0-pr-232.sha-e4f25eb

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.
@@ -606,5 +606,5 @@ Most of the features of Better Auth will not work correctly.`);let l=t.secrets??
606
606
  `)[0].slice(0,F8):``}catch{return``}finally{t!==void 0&&clearTimeout(t)}}async function R8(e,t){let n;try{let r=Promise.resolve(e.fetcher.fetch(`http://localhost${q6}`,{method:`POST`,headers:{"content-type":`application/json`,...e.token!==void 0&&{"x-void-dev-trigger":e.token}},body:X6(t)})).then(e=>({kind:`response`,res:e}),e=>({kind:`error`,cause:e})),i=await Promise.race([r,new Promise(e=>{n=setTimeout(()=>e({kind:`timeout`}),P8)})]);if(i.kind===`timeout`)return{ok:!1,reason:`no response within ${P8}ms`};if(i.kind===`error`){let e=i.cause;return{ok:!1,reason:e instanceof Error?e.message:String(e)}}let{res:a}=i;if(!a.ok){let e=await L8(a);return{ok:!1,reason:`dev server responded ${a.status}${e?`: ${e}`:``}`}}return a.headers.get(`x-void-email-inbox`)===`captured`?{ok:!0}:{ok:!1,reason:`response did not come from the dev inbox`}}catch(e){return{ok:!1,reason:e instanceof Error?e.message:String(e)}}finally{n!==void 0&&clearTimeout(n)}}function z8(e,t){return{ok:!0,ids:x8(e).map(e=>({recipient:e,messageId:t}))}}async function B8(e){if(e.idempotencyKey!==void 0&&(typeof e.idempotencyKey!=`string`||!/^[\x21-\x7e]{1,128}$/.test(e.idempotencyKey)))return C8(`MIME_ERROR`,`email: idempotencyKey must contain 1–128 printable non-space ASCII characters.`);let t=S8(e);if(t.from===void 0)return C8(`INVALID_FROM`,`email: 'from' is required. Set it explicitly or deploy via Void so the platform-injected __VOID_PROJECT_SLUG and __VOID_EMAIL_DOMAIN can default it to <slug>+noreply@<domain>.`);let n=t,r,i,a;try{r=await l6(n),{raw:i,messageId:a}=K6(r)}catch(e){return e instanceof Q3?C8(e.code,e.message,e):C8(`MIME_ERROR`,e instanceof Error?e.message:String(e),e)}let o=o8();if(!e.sendInDev&&t8()){let e=n8(r,i,a);return e8(e),z8(r,e.id)}let s=e.sendInDev?void 0:N8(o);if(s){let e=n8(r,i,a),t=await R8(s,e);if(t.ok)return z8(r,e.id);let n=`email: the void dev inbox at ${q6} is unreachable (${t.reason}), so nothing was captured and nothing was sent.`;return console.warn(`[void/email] ${n}`),C8(`UPSTREAM_ERROR`,n)}let c=x8(r),l=_8(o);if(l)return e.idempotencyKey===void 0?b8(l,r.from.email,c,i,a):C8(`MIME_ERROR`,`email: idempotencyKey requires a Void platform; the native Cloudflare binding cannot deduplicate sends.`);let u=o,d=u?.__VOID_PROXY,f=u?.__PROJECT_ID,p=u?.__VOID_PROXY_TOKEN;if(!d||!f||!p)return C8(`BINDING_MISSING`,"email: neither SEND_EMAIL nor __VOID_PROXY is available, so nothing was sent. Deploy via Void to bind the platform proxy, or set `email.from` in void.config.ts so `void deploy --platform cloudflare` provisions the SEND_EMAIL binding. Under `void dev` messages are captured by the local inbox at /__void/inbox instead — reaching this error there means that path was bypassed by the deprecated `sendInDev: true` (it never delivers) or unavailable (the worker has no assets binding to reach the dev server through).");let m={projectId:f,aiToken:p,from:r.from.email,recipients:c,mimeBase64:N3(i),requestId:w6(`req`),...e.idempotencyKey===void 0?{}:{idempotencyKey:e.idempotencyKey}},h=JSON.stringify(m),g=new AbortController,_=Date.now()+h8,v=e=>i8(_-Date.now(),e,()=>(g.abort(),Error(`email platform send timed out`))),y;try{y=await v(()=>d.fetch(`https://email-proxy/email/send`,{method:`POST`,headers:{"content-type":`application/json`},body:h,signal:g.signal}))}catch(e){return C8(`OUTCOME_UNKNOWN`,`email: send outcome is unknown: ${e instanceof Error?e.message:String(e)}. Check email logs or repeat the same idempotency key; do not create a new send.`,e)}return M8(y,c,a,v)}var V8=[`example.com`,`example.net`,`example.org`];function H8(e){let{domain:t,email:n}=e;return!t||!V8.some(e=>e===t)?!1:n.toLowerCase().endsWith(`@${t}`)}var U8=class extends Error{name=`Auth.UndeliverableError`},W8=Zz(async(e,t)=>{e.set(`auth`,G8(e)),await t()});function G8(e){return M3(Xz({accountStep:t=>e.var.accountChosen?Promise.resolve(!1):Z(e,O2(e,{clientId:t.clientId,cookie:t.headers.get(`cookie`),sessionId:t.sessionId,userId:t.userId}),`AccountStep.due`),baseURL:U.URL,cache:e.var.cache,db:b2,google:K8(),metadataFetch:bF(e.env.CLIENT_METADATA),pendingKey:t=>Z(e,u4($,t),`PendingKey.take`),secret:U.SECRET,sendCode:t=>q8(e,t),waitUntil:t=>e.executionCtx.waitUntil(t)}))}function K8(){let{GOOGLE_CLIENT_ID:e,GOOGLE_CLIENT_SECRET:t}=U;if(e&&t)return{clientId:e,clientSecret:t}}async function q8(e,t){let n=IF({code:t.code}),r=e.env.TEST_INBOX;if(r&&H8({domain:U.TEST_EMAIL_DOMAIN,email:t.email})){await Z(e,r.capture({subject:n.subject,text:n.text,to:[{email:t.email}]}),`inbox.capture`);return}let i=await Z(e,B8({attachments:[n.logo],html:n.html,subject:n.subject,text:n.text,to:t.email}),`email.send`);if(i.ok)return;let a=`error`in i?i.error.code:void 0;throw a===`QUOTA_EXCEEDED`?new iI:a===`UNVERIFIED_DESTINATION`?new U8(`The email service does not deliver to the address.`):Error(`Sending the sign-in code failed: ${a??`delivery`}.`)}(function(e){e.errors=[iI]})(q8||={});async function J8(e,t){let{clientId:n,userId:r}=t;if(!M4(e))try{let[t,i]=await Z(e,Promise.all([$.select({realmId:SP.realmId}).from(SP).where(Y(SP.userId,r)).limit(1),$.select({id:CP.id}).from(CP).where(sM(Y(CP.userId,r),_M(CP.address))).limit(1)]),`db.account.held`);if(t.length>0||i.length>0||!(await Z(e,e.env.ACCOUNT_LIMIT.limit({key:r}),`ratelimit.limit`)).success)return;let a=await Z(e,DH(e,{clientId:n??void 0,db:$,own:new URL(U.URL).origin}),`Realm.forRequest`),o=await Z(e,jH($,{origin:U.URL,realms:a}),`Realm.withDefaults`);await Z(e,z1(e,{db:$,env:U,realms:o,userId:r}),`TempoAccount.create`)}catch(t){KF(e,{error:t,fields:{clientId:n??void 0},message:`The sign-in created no first account, since its creation failed.`})}}var Y8=`tempo-id-passkey-link`,X8=`host`;async function Z8(e,t){let n=hB(e,Y8,X8);if(!n)return;let r=await Z(e,Hz(n,{host:new URL(e.req.url).host,secret:U.SECRET}),`Passkey.unseal`);if(!r)return;let[i,a]=await Z(e,Promise.all([r.nonce,t.nonce].map(e=>crypto.subtle.digest(`SHA-256`,new TextEncoder().encode(e)))),`crypto.digest`);return crypto.subtle.timingSafeEqual(i,a)?r:void 0}async function Q8(e,t){let n=Me(crypto.getRandomValues(new Uint8Array(32)),{pad:!1,url:!0});return _B(e,Y8,await Z(e,Pz({address:t.credential.address,createdAt:t.credential.createdAt,expiresAt:Math.floor(Date.now()/1e3)+300,host:new URL(e.req.url).host,id:t.id,nonce:n,publicKey:t.credential.publicKey,rpId:t.rpId},{secret:U.SECRET}),`Passkey.seal`),{httpOnly:!0,maxAge:300,path:`/`,prefix:X8,sameSite:`Lax`,secure:!0}),n}async function $8(e){let t=await crypto.subtle.digest(`SHA-256`,new TextEncoder().encode(e.nonce));return Xt(new Uint8Array(t))}async function e5(e){if(!e.expected)return!1;let t=await $8({nonce:e.nonce});return t.length===e.expected.length&&crypto.subtle.timingSafeEqual(Lt(t).buffer,Lt(e.expected).buffer)}function t5(e){vB(e,Y8,{path:`/`,prefix:X8,secure:!0})}var n5=/^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/,r5;(function(e){let t;(function(e){e.json=z({email:R().trim().toLowerCase().pipe(On({abort:!0}).max(254,{abort:!0,error:`Invalid email address`}).refine(e=>{let[t=``,n=``]=e.split(`@`);return t.length<=64&&n.split(`.`).every(e=>n5.test(e))},`Invalid email address`)).meta({description:`The user's email address.`,examples:[`ada@example.com`]})}),e.response=z({sent:bn(!0).meta({description:`The request is accepted. The value is the same for every address.`})})})(t||=e.code||={});let n;(function(e){e.json=z({assertion:yz.assertion.optional().meta({description:"The assertion of the email step's passkey, over a challenge from `POST /v1/auth/passkey/options` with `link`. Required with `link`, since only the person who holds the passkey can link it."}),code:R().trim().regex(/^\d{6}$/).meta({description:`The six-digit emailed code.`,examples:[`123456`]}),email:t.json.shape.email,link:R().max(64).optional().meta({description:"The email step's `link`, which links the wallet.tempo passkey that asked for it to this user, with that passkey's `assertion`. An expired link refuses the sign-in with `passkey_link_expired`, and the code stays valid.",examples:[`dGhlIG5vbmNlIHRoYXQgdGhlIHN0ZXAgY2Fycmllcw`]}),oauth_query:R().max(8192).optional().meta({description:`The sign-in page's query string when an app's authorization request sent the browser there, which the sign-in continues. Better Auth signs it. At most 8,192 characters.`,examples:[`client_id=client_01JZ8Q6W3N1R5B4V7C2X9K0M3T&response_type=code&exp=1760000000&sig=Gx3kB0`]})}).refine(e=>!e.link||e.assertion,{message:"Required with `link`.",path:[`assertion`]});let n=e.user=z({email:On().meta({description:`The user's email address.`,examples:[`ada@example.com`]}),id:R().meta({description:"The user's ID, which is the `sub` of every token Tempo ID issues for the user.",examples:[`user_01JZ8Q6W3N1R5B4V7C2X9K0M3T`]})}).meta({description:`The signed-in user.`,id:`User`});e.response=z({authorization:CR.response.optional().meta({description:"The app's headless authorization, for a one-tap sign-in on the app's page whose options carried `authorize`. Absent for any other sign-in."}),redirect:En().nullable().meta({description:"Where the browser continues: the app's `redirect_uri` with an authorization code, or `null` for a sign-in that no app waits on.",examples:[`https://app.example.com/callback?code=SplxlOBeZQQYbYS6WxSbIA`]}),user:n}),e.signedIn=gn([z({url:R()}),z({user:z({email:R(),id:R()})})])})(n||=e.verify||={});let r;(function(e){e.json=z({authorize:CR.request.optional().meta({description:"The app's headless authorization request, as `POST /v1/authorize` takes it, from a first-party app's page. The challenge is then the digest of its key, so the passkey's one assertion signs the user in and signs the key, and `POST /v1/auth/passkey/verify` returns the authorization. Requires `client_id`, the same as its own."}),client_id:R().min(1).max(64).optional().meta({description:"The client ID of the first-party app whose page runs the ceremony. It selects the app's realms, and the request's `Origin` must be the origin of one of the app's redirect URIs. Required from an app's page.",examples:[`client_01JZ8Q6W3N1R5B4V7C2X9K0M3T`]}),credentialId:gn([yz.credentialId,jn(yz.credentialId).max(16)]).optional().meta({description:"The credential ID, or up to 16 IDs, that the browser offers as `allowCredentials`, base64url. Defaults to every discoverable passkey of the relying party, as an empty list does.",examples:[`KEbWNCc7NgaYnUyrNeFGX9_3Y-8`]}),link:n.json.shape.link.meta({description:"The email step's `link`. The options then name only that step's passkey, at its relying party, in place of `credentialId`. The emailed-code sign-in sends the passkey's assertion with the `link`.",examples:[`dGhlIG5vbmNlIHRoYXQgdGhlIHN0ZXAgY2Fycmllcw`]}),mediation:xn([`conditional`,`optional`,`required`,`silent`]).optional().meta({description:"Returned in the options for `navigator.credentials.get()`, such as `conditional` for passkey autofill.",examples:[`conditional`]}),oauth_query:n.json.shape.oauth_query,user_code:R().max(32).optional().meta({description:"The user code of the device grant that the sign-in returns to. While the code is pending and bound to no user, it selects the realms of the app that requested it. Any other code selects the `default` realm. Ignored with `oauth_query` or `client_id`.",examples:[`WDJB-MJHT`]})}).refine(e=>!e.authorize||e.authorize.client_id===e.client_id,{message:"Requires the same `client_id`.",path:[`authorize`]}),e.sent=z({authorize:Nn({key_authorization:Nn({}).optional()})}),e.response=z({options:z({mediation:r.json.shape.mediation,publicKey:z({allowCredentials:jn(z({id:R().meta({description:`A credential ID, base64url.`,examples:[`KEbWNCc7NgaYnUyrNeFGX9_3Y-8`]}),type:bn(`public-key`).meta({description:`The credential type.`})}).meta({description:`A passkey the browser offers.`})).optional().meta({description:"The passkeys the browser offers, from `credentialId`. Absent, it offers every discoverable passkey of the relying party."}),challenge:_n([`0x`,R()]).meta({description:`The single-use challenge, as hex. It expires after 5 minutes.`,examples:[`0xf6310589abb21116acc6e123967ed0a125b5041c43f8e157237093e07eaa354c`]}),rpId:R().meta({description:`The relying party ID of the passkeys.`,examples:[`tempo.xyz`]}),userVerification:bn(`required`).meta({description:`Every passkey sign-in requires user verification.`})}).meta({description:"The `PublicKeyCredentialRequestOptions`, serialized with the challenge as hex."})}).meta({description:"The options for `navigator.credentials.get()`."})})})(r||=e.passkeyOptions||={});let i;(function(e){e.json=z({assertion:yz.assertion,oauth_query:n.json.shape.oauth_query}),e.response=gn([n.response.meta({description:`The signed-in user.`}),z({step:z({link:R().meta({description:"Send as `link` with the emailed-code sign-in, which links the passkey to that user.",examples:[`dGhlIG5vbmNlIHRoYXQgdGhlIHN0ZXAgY2Fycmllcw`]}),signed:bn(!1).meta({description:`Whether the assertion already signed a key authorization. This route signs none.`}),type:bn(`email`).meta({description:`Sign in with an emailed code, which links the passkey to that user.`})}).meta({description:`The email step, for a wallet.tempo passkey whose account has no email.`})}).meta({description:`A passkey sign-in that continues when the user verifies an email address.`})])})(i||=e.passkeyVerify||={});let a;(function(e){e.response=z({signed_out:bn(!0).meta({description:`The session is over, or there was none.`})})})(a||=e.logout||={});let o;(function(e){e.response=z({user:n.user.extend({name:R().nullable().meta({description:"The user's name, or `null` for a user who signed up without one.",examples:[`Ada Lovelace`]})}).nullable().meta({description:"The signed-in user, or `null` without a session.",id:`SessionUser`})})})(o||=e.session||={});let s;(function(e){e.query=z({oauth_query:n.json.shape.oauth_query,return_to:R().max(2048).optional().meta({description:`The page that sign-in returns to, from the sign-in page's query. Only a path on the device page passes, and any other value reads as absent.`,examples:[`/device?code=WDJB-MJHT`]})}),e.response=z({google:Dn().meta({description:`Whether Tempo ID offers Google sign-in, which the deployment configures.`,examples:[!0]}),passkeys:Dn().meta({description:"Whether Tempo ID offers passkey sign-in: one of the realms of the app that `oauth_query` or the device code of `return_to` names, or the `default` realm without one, holds passkeys that sign in at Tempo ID's origin.",examples:[!0]}),app:R().nullable().meta({description:"The display name of the app of the signed authorization request in `oauth_query`, or its client ID without one, or `null` for a forged or expired query, or an unknown app.",examples:[`Tempo Cash`]}),request:z({app:R().meta({description:`The app's display name, or its client ID without one.`,examples:[`Tempo Cash`]}),key:YL.description}).nullable().meta({description:"The app and the key of the signed authorization request in `oauth_query`, which the sign-in grants, or `null` for a forged or expired query, an unknown app, a request without a key, a key with a `challenge`, or a third-party app, whose key the approval page shows instead."}),return_to:R().nullable().meta({description:"The page that sign-in returns to, a path on the device page, or `null` for the account.",examples:[`/device?code=WDJB-MJHT`]}),user_code:R().nullable().meta({description:"The user code of the device page that sign-in returns to, or `null` without one.",examples:[`WDJBMJHT`]}),verified:Dn().meta({description:"Whether `app` is a registered app, whose name the page marks as verified. `false` for a third-party app, which names itself in its metadata document, and without an app.",examples:[!0]})})})(s||=e.methods||={})})(r5||={});var i5=new Fy().post(`/v1/auth/code`,sV({description:`Emails a sign-in code. The response is the same for every address, so it reveals no account.`,responses:gV({errors:[...dB,...q8.errors,..._V.errors,...EV.errors,nI,sI],success:{description:`The response for every address: the email service accepted the code, or does not deliver to the address.`,schema:r5.code.response}}),tags:[`Authenticate`]}),_V(`json`,r5.code.json),async e=>{let{email:t}=e.req.valid(`json`),n=await Z(e,EV(e,{limits:[{binding:`SIGN_IN_IP_LIMIT`,key:jV(e)},{binding:`SIGN_IN_CODE_LIMIT`,key:kV({email:t})}]}),`RateLimit.check`);if(n)return n;if(!await Z(e,DV($,{email:t}),`RateLimit.countCode`))return OV(e,{policy:wV}),NV(e,{policy:wV,retryAfter:wV.window});let r=await Z(e,e.var.auth.api.createVerificationOTP({body:{email:t,type:`sign-in`}}),`auth.createVerificationOTP`),i=await Z(e,q8(e,{code:r,email:t.toLowerCase()}),`Auth.sendCode`).catch(e=>e);return i&&(KF(e,{error:i,message:`The email service refused a sign-in code.`}),!(i instanceof U8))?X(e,i instanceof iI?i:new sI):e.json({sent:!0},200)}).post(`/v1/auth/code/verify`,sV({description:"Signs in with an emailed code, and sets the session cookie. For a user with no Tempo Account in the realm of the sign-in, the first realm of the app that `oauth_query` names or the `default` realm, it creates one when the realm creates accounts. A failed creation leaves the sign-in signed in, and the next sign-in or `POST /v1/account` creates the account.",responses:gV({errors:[...dB,...F4.errors,..._V.errors,...D4.errors,...EV.errors,Gz,Kz,cz,dz],success:{description:`The signed-in user.`,schema:r5.verify.response}}),tags:[`Authenticate`]}),_V(`json`,r5.verify.json),async e=>{let{assertion:t,code:n,email:r,link:i,oauth_query:a}=e.req.valid(`json`),o=F4(e,{oauth_query:a});if(o)return X(e,o);let s=await Z(e,EV(e,{limits:[{binding:`SIGN_IN_IP_LIMIT`,key:jV(e)}]}),`RateLimit.check`);if(s)return s;let c=i?await Z(e,Z8(e,{nonce:i}),`PasskeyLink.claim`):void 0;if(i&&!c)return X(e,new cz);let l=c&&t?await Z(e,Fz($,{clientDataJSON:t.metadata.clientDataJSON}),`Passkey.take`):void 0;if(c){let n=l&&i?await Z(e,e5({expected:l.link,nonce:i}),`PasskeyLink.matches`):!1;if(!t||!l||!n||l.clientId!==a5({oauth_query:a})||l.origin!==M4(e)||l.rpId!==c.rpId||t.id!==c.id||!Uz(t,{challenge:l.challenge,origin:l.origin??new URL(U.URL).origin,publicKey:c.publicKey,rpId:c.rpId})||!await Z(e,O4(e,{assertion:t,challenge:l}),`Headless.spend`))return X(e,new dz)}let u=await Z(e,e.var.auth.api.signInEmailOTP({asResponse:!1,body:{email:r,otp:n,...a?{oauth_query:a}:{}},headers:new Headers(e.req.raw.headers),request:e.req.raw,returnHeaders:!0}),`auth.signInEmailOTP`).catch(e=>{if(di(e)&&e.body?.error===`invalid_signature`)return new Gz;if(di(e))return new Kz;throw e});if(u instanceof eI)return X(e,u);for(let t of u.headers.getSetCookie())e.header(`set-cookie`,t,{append:!0});e.header(`cache-control`,`private, no-store`);let d=r5.verify.signedIn.parse(u.response),f=await(async()=>{if(`user`in d)return{email:d.user.email,id:d.user.id};let t=await Z(e,(await Z(e,e.var.auth.$context,`auth.context`)).internalAdapter.findUserByEmail(r),`db.user.findByEmail`);if(!t)throw Error(`The signed-in user is missing.`);return{email:t.user.email,id:t.user.id}})();if(c&&await Z(e,Cz($,{credential:c,id:c.id,rpId:c.rpId,userId:f.id}),`Passkey.link`)===f.id&&t5(e),await Z(e,J8(e,{clientId:a5({oauth_query:a}),userId:f.id}),`FirstAccount.create`),l?.authorize!==void 0&&t){e.header(C4,`true`);let n=await Z(e,D4(e,{assertion:t,challenge:l,setCookie:u.headers.getSetCookie()}),`Headless.oneTap`);return n instanceof Response?n:n instanceof eI?X(e,n):e.json({authorization:n,redirect:null,user:f},200)}let p=`user`in d?null:await Z(e,_4(e,{redirect:d.url,setCookie:u.headers.getSetCookie()}),`SignInConsent.afterSignIn`);return e.json({redirect:p,user:f},200)}).post(`/v1/auth/passkey/options`,sV({description:"Issues a single-use challenge, and returns request options for the passkeys of the relying party that the sign-in reaches. Without `oauth_query` or `client_id`, that is the relying party of the `default` realm. With either, it is the first of the app's realms that holds passkeys. From a first-party app's page, with `client_id`, the relying party must cover the page's origin and Tempo ID's, and only that page's assertion spends the challenge. With `link`, the options name only the email step's passkey.",responses:gV({errors:[...dB,...F4.errors,..._V.errors,...wR.errors,...xz.errors,...EV.errors,cz,lz],success:{description:`The request options.`,schema:r5.passkeyOptions.response}}),tags:[`Authenticate`]}),_V(`json`,r5.passkeyOptions.json),async e=>{let{authorize:t,client_id:n,credentialId:r,link:i,mediation:a,oauth_query:o,user_code:s}=e.req.valid(`json`),c=F4(e,{oauth_query:o});if(c)return X(e,c);let l=jV(e),u=await Z(e,EV(e,{limits:[{binding:`SIGN_IN_IP_LIMIT`,key:l?`passkey-options:${l}`:void 0}]}),`RateLimit.check`);if(u)return u;let d=i?await Z(e,Z8(e,{nonce:i}),`PasskeyLink.claim`):void 0;if(i&&!d)return X(e,new cz);let f=M4(e),p=n?await Z(e,SF($,{clientId:n,enabled:!0}).catch(e=>{if(!(e instanceof hF))throw e}),`Apps.get`):void 0;if(f||n){let t=xz({app:p,clientId:n,origin:e.req.header(`origin`)});if(t)return X(e,t)}let m=a5({oauth_query:o}),h=s?qR(s):void 0,g=!m&&!n&&h?await Z(e,BR($,{userCode:h}),`Device.client`):void 0,_=m??n??g,v=_?await Z(e,SH(e,()=>EH($,{clientId:_}),[`realm.forApp`,_]),`Realm.forApp`):[await Z(e,SH(e,()=>kH($,{id:wH}),[`realm.get`,wH]),`Realm.get`)],y=kz(await Z(e,jH($,{origin:U.URL,realms:v}),`Realm.withDefaults`),{origin:U.URL,page:f}),b=d&&(y?.realmId!=="default"||y.rpId!==d.rpId);if(!y||b)return X(e,new lz({clientId:(m??n)||void 0,origin:f}));let x=i?await Z(e,$8({nonce:i}),`PasskeyLink.digest`):void 0,S=t&&(f?wR(t,{app:p,origin:e.req.header(`origin`)}):new xR({error_description:"Invalid `Origin`: none. A one-tap sign-in with `authorize` runs only on the app's page.",field:`Origin`}));if(S)return X(e,S);let C=await Z(e,bz($,{authorize:await(async()=>{if(!t)return;let n=r5.passkeyOptions.sent.parse(await e.req.json()),r=t.key_authorization;return r?{...n.authorize,key_authorization:{...n.authorize.key_authorization,expiry:r.expiry}}:n.authorize})(),clientId:m,link:x,oneTap:await(async()=>{if(f){let e=t?.key_authorization;if(!e)return;let n=e.witness??Xt(crypto.getRandomValues(new Uint8Array(32)));return{digest:lR({key:e,witness:n}),witness:n}}if(o&&!i)return await Z(e,v4(e,{oauthQuery:o}),`SignInConsent.oneTap`)})(),origin:f,...y}),`Passkey.challenge`);if(!C)return X(e,new dz);let w=d?[d.id]:r===void 0?[]:[r].flat(),E=r5.passkeyOptions.response.shape.options.parse({...CS({challenge:C,...w.length>0?{credentialId:w}:{},rpId:y.rpId,userVerification:`required`}).options,...a?{mediation:a}:{}});return e.header(`cache-control`,`private, no-store`),e.json({options:E},200)}).post(`/v1/auth/passkey/verify`,sV({description:"Signs in with a passkey assertion over a challenge from the options, sent from the page that requested them, and sets the session cookie. For a user with no Tempo Account in the realm of the sign-in, the first realm of the app that `oauth_query` names or the `default` realm, it creates one when the realm creates accounts. A failed creation leaves the sign-in signed in, and the next sign-in or `POST /v1/account` creates the account.",responses:gV({errors:[...dB,...F4.errors,..._V.errors,...uI.errors,...D4.errors,...EV.errors,Gz,dz],success:{description:`The signed-in user, with the authorization of a one-tap sign-in on an app's page, or the email step for a wallet.tempo passkey without an email.`,schema:r5.passkeyVerify.response}}),tags:[`Authenticate`]}),_V(`json`,r5.passkeyVerify.json),async e=>{let{assertion:t,oauth_query:n}=e.req.valid(`json`),r=F4(e,{oauth_query:n});if(r)return X(e,r);let i=await Z(e,EV(e,{limits:[{binding:`SIGN_IN_IP_LIMIT`,key:jV(e)}]}),`RateLimit.check`);if(i)return i;let a=await Z(e,Fz($,{clientDataJSON:t.metadata.clientDataJSON}),`Passkey.take`);if(!a||a.link!==void 0||a.clientId!==a5({oauth_query:n})||a.origin!==M4(e))return X(e,new dz);let{id:o}=t,s=await Z(e,Sz($,{id:o,rpId:a.rpId}),`Passkey.get`),c=await(async()=>{if(!s&&e.env.WALLET&&a.realmId==="default")try{return await Z(e,K1(e.env.WALLET,{id:o}),`Wallet.credential`)}catch(t){return KF(e,{error:t,message:`The wallet service failed a passkey lookup.`}),t instanceof Error&&uI(t)||new sI}})();if(c instanceof eI)return X(e,c);let l=s?.publicKey??c?.publicKey;if(!l||!Uz(t,{challenge:a.challenge,origin:a.origin??new URL(U.URL).origin,publicKey:l,rpId:a.rpId})||!await Z(e,O4(e,{assertion:t,challenge:a}),`Headless.spend`))return X(e,new dz);if(c&&!c.email){let t=await Z(e,Q8(e,{credential:c,id:o,rpId:a.rpId}),`PasskeyLink.defer`);return e.header(`cache-control`,`private, no-store`),e.json({step:{link:t,signed:!1,type:`email`}},200)}let u=await(async()=>{if(s)return s.userId;let t=await Z(e,o5(e,{email:c.email}),`authenticate.emailUser`);return Z(e,Cz($,{credential:c,id:o,rpId:a.rpId,userId:t}),`Passkey.link`)})();if(!u)return X(e,new dz);let d=await Z(e,e.var.auth.api.signInPasskey({asResponse:!1,body:{userId:u,...n?{oauth_query:n}:{}},headers:new Headers(e.req.raw.headers),request:e.req.raw,returnHeaders:!0}),`auth.signInPasskey`).catch(e=>{if(di(e)&&e.body?.error===`invalid_signature`)return new Gz;throw e});if(d instanceof eI)return X(e,d);for(let t of d.headers.getSetCookie())e.header(`set-cookie`,t,{append:!0});e.header(`cache-control`,`private, no-store`);let f=r5.verify.signedIn.parse(d.response);if(await Z(e,J8(e,{clientId:a5({oauth_query:n}),userId:u}),`FirstAccount.create`),`user`in f){let n={email:f.user.email,id:f.user.id};if(a.authorize===void 0)return e.json({redirect:null,user:n},200);e.header(C4,`true`);let r=await Z(e,D4(e,{assertion:t,challenge:a,setCookie:d.headers.getSetCookie()}),`Headless.oneTap`);return r instanceof Response?r:r instanceof eI?X(e,r):e.json({authorization:r,redirect:null,user:n},200)}let[p]=await Z(e,$.select({email:gP.email,id:gP.id}).from(gP).where(Y(gP.id,u)),`db.user.get`);if(!p)throw Error(`The signed-in user is missing.`);let m=await Z(e,_4(e,{oneTap:a.witness?{assertion:t,witness:a.witness}:void 0,redirect:f.url,setCookie:d.headers.getSetCookie()}),`SignInConsent.afterSignIn`);return e.json({redirect:m,user:p},200)}).post(`/v1/auth/logout`,sV({description:`Signs out: ends the session, revokes the refresh tokens that apps received through it, and clears its cookie.`,responses:gV({errors:[...dB,nI],success:{description:`The session is over.`,schema:r5.logout.response}}),tags:[`Authenticate`]}),async e=>{let t=e.req.raw.headers,n=await Z(e,e.var.auth.api.getSession({headers:t}),`auth.getSession`);n&&await Z(e,$.update(uP).set({revoked:new Date}).where(sM(Y(uP.sessionId,n.session.id),gM(uP.revoked))),`db.oauthRefreshToken.revoke`);let r=await Z(e,e.var.auth.api.signOut({headers:t,returnHeaders:!0}),`auth.signOut`);for(let t of r.headers.getSetCookie())e.header(`set-cookie`,t,{append:!0});return e.header(`set-cookie`,T2(),{append:!0}),e.header(`cache-control`,`private, no-store`),e.json({signed_out:!0},200)}).get(`/v1/auth/session`,sV({description:"Reads the signed-in user, or `null` without a session.",responses:gV({success:{description:`The session.`,schema:r5.session.response}}),tags:[`Authenticate`]}),async e=>{let t=await Z(e,I4(e),`Session.get`);return e.header(`cache-control`,`private, no-store`),t?e.json({user:{email:t.user.email,id:t.user.id,name:t.user.name||null}},200):e.json({user:null},200)}).get(`/v1/auth/methods`,sV({description:"Reads the sign-in methods that the sign-in page offers, the key that a signed authorization request in `oauth_query` grants, and the page that sign-in returns to. A device code in `return_to` names the app that requested it, while the code is pending and bound to no user. The read binds nothing, and counts against the IP address's sign-in limit. Without `oauth_query`, a client ID reads the `default` realm, as the other sign-in routes do.",responses:gV({errors:[..._V.errors],success:{description:`The sign-in methods.`,schema:r5.methods.response}}),tags:[`Authenticate`]}),_V(`query`,r5.methods.query),async e=>{let t=e.req.valid(`query`),n=YR(t.return_to,{origin:U.URL}),r=(()=>{if(!t.oauth_query)return;let e=new URLSearchParams(t.oauth_query);return e.delete(`error`),e.has(`sig`)?e:void 0})(),i=n?qR(new URL(n,U.URL).searchParams.get(`code`)??``):void 0,a=await(async()=>{if(r)return r.get(`client_id`)??void 0;if(!i)return;let t=jV(e);if(t&&(await Z(e,e.env.SIGN_IN_IP_LIMIT.limit({key:`device-lookup:${t}`}),`ratelimit.limit`)).success)return await Z(e,BR($,{userCode:i}),`Device.client`)})(),o=a?await Z(e,SH(e,()=>EH($,{clientId:a}),[`realm.forApp`,a]),`Realm.forApp`):[await Z(e,SH(e,()=>kH($,{id:wH}),[`realm.get`,wH]),`Realm.get`)],s=await Z(e,jH($,{origin:U.URL,realms:o}),`Realm.withDefaults`),c=r?await Z(e,s5(e,{query:r}),`authenticate.granted`):null;return e.json({app:c?.app??null,google:!!K8(),passkeys:!!kz(s,{origin:U.URL}),request:c?.key?{app:c.app,key:c.key}:null,return_to:n??null,user_code:i||null,verified:c?.verified??!1},200)});function a5(e){return e.oauth_query?new URLSearchParams(e.oauth_query).get(`client_id`):null}async function o5(e,t){let n=t.email.trim().toLowerCase(),r=await Z(e,e.var.auth.$context,`auth.context`),i=await Z(e,r.internalAdapter.findUserByEmail(n),`db.user.findByEmail`);if(i)return i.user.id;try{return(await Z(e,r.internalAdapter.createUser({email:n,emailVerified:!0,name:``},{method:`passkey`}),`db.user.create`)).id}catch(t){let i=await Z(e,r.internalAdapter.findUserByEmail(n),`db.user.findByEmail`);if(i)return i.user.id;throw t}}async function s5(e,t){let{query:n}=t,r=await Z(e,e.var.auth.$context,`auth.context`),i=await Z(e,ta(n.toString(),r.secret),`auth.verifyOAuthQueryParams`),a=n.get(`client_id`);if(!i||!a)return null;let o=await Z(e,SF($,{clientId:a}).catch(e=>{if(!(e instanceof hF))throw e}),`Apps.get`);if(!o)return null;let s=DF(a),c=n.has(`challenge`)||s?void 0:ER(n);return{app:o.name??a,key:c&&!(c instanceof eI)?cR(c):null,verified:!s}}var c5;(function(e){let t;(function(e){e.json=CR.request,e.response=CR.response})(t||=e.authorize||={});let n;(function(e){e.json=z({account:R1.tempoAccount.shape.address.meta({description:`The address of the account that the user selects, one of the user's accounts in the app's realms.`,examples:[`0x8C3b5d0e2A4f6B1c9D7e3F5a0B2c4D6e8F1a3B5c`]}),oauth_query:R().min(1).max(8192).meta({description:`The account step's query string, which Better Auth signs when it sends the browser there. At most 8,192 characters.`,examples:[`client_id=Qk3vT9xZbLmN2pRw8YcHjF6sDaE4uGtK&response_type=code&exp=1760000000&sig=Gx3kB0`]}),passkey:z({assertion:yz.assertion}).optional().meta({description:`The passkey's assertion over the options of the passkey step, which the selection of a passkey-owned account returns. The repeated selection signs the key with it.`})}),e.response=gn([z({redirect:R().meta({description:"Where the browser continues: the approval page's path on Tempo ID, or the app's `redirect_uri` with an authorization code and `state`.",examples:[`https://app.example.com/callback?code=Vb7mQ2xLkP9sTzR4&state=af0ifjsldkj`]})}).meta({description:`A selection that continues the authorization.`}),yz.step]),e.result=z({url:R().min(1)})})(n||=e.account||={});let r;(function(e){e.json=z({accept:Dn().meta({description:"Whether the user approves the request. `false` denies it, and the app receives `access_denied`.",examples:[!0]}),account:R1.tempoAccount.shape.address.optional().meta({description:`The Tempo Account that the approval page showed for the request's key authorization, one of the user's accounts in the app's realms. Ignored when the key names its account, and absent for a request without a key.`,examples:[`0x8C3b5d0e2A4f6B1c9D7e3F5a0B2c4D6e8F1a3B5c`]}),oauth_query:R().min(1).max(8192).meta({description:`The approval page's query string, which Better Auth signs when it sends the browser there. At most 8,192 characters.`,examples:[`client_id=Qk3vT9xZbLmN2pRw8YcHjF6sDaE4uGtK&response_type=code&exp=1760000000&sig=Gx3kB0`]}),passkey:z({assertion:yz.assertion}).optional().meta({description:`The passkey's assertion over the options of the passkey step, which a passkey-owned account's approval returns. The repeated approval signs the key with it.`}),session_id:R().min(1).max(256).meta({description:`The ID of the session that the approval page showed. The decision applies only while that session is the signed-in one.`,examples:[`8nVq3kZ0bT5wXy2mLp7sR4dA`]})});let t=e.step=yz.step;e.response=gn([z({redirect:En().meta({description:"The app's `redirect_uri`, with an authorization code and `state`, or with `error=access_denied` when the user denied the request.",examples:[`https://app.example.com/callback?code=Vb7mQ2xLkP9sTzR4&state=af0ifjsldkj`]})}).meta({description:`A decision that returns to the app.`}),t])})(r||=e.consent||={});let i;(function(e){e.query=z({oauth_query:R().min(1).max(8192).meta({description:`The approval page's query string, which Better Auth signs when it sends the browser there. At most 8,192 characters.`,examples:[`client_id=Qk3vT9xZbLmN2pRw8YcHjF6sDaE4uGtK&response_type=code&exp=1760000000&sig=Gx3kB0`]})}),e.response=gn([z({redirect:En().meta({description:"The app's `redirect_uri`, with the refusal of the request's key as `error` and `error_description`, `state`, and `iss`.",examples:[`https://app.example.com/callback?error=invalid_request&state=af0ifjsldkj`]})}).meta({description:`A key that Tempo ID refuses, which returns the browser to the app.`}),z({request:z({account:z({address:R1.tempoAccount.shape.address.meta({description:`The account address.`,examples:[`0x8C3b5d0e2A4f6B1c9D7e3F5a0B2c4D6e8F1a3B5c`]}),owner:R1.tempoAccount.shape.config.shape.owners.unwrap().element.shape.type}).optional().meta({description:`The Tempo Account that the approval applies to: the account that the key names, else the app's selected account, else the user's oldest. Present only when the user holds more than one account in the app's realms.`}),app:R().meta({description:`The app's display name, or the host of its redirect URI without one.`,examples:[`Tempo Cash`]}),destination:R().meta({description:`The host of the app's redirect URI, or its scheme for a native app. For a third-party app, the host that serves its metadata document.`,examples:[`cash.tempo.xyz`]}),email:On().meta({description:`The signed-in user's email address.`,examples:[`ada@example.com`]}),key:YL.description.extend({challenge:R().optional().meta({description:`The message that the key's witness binds, such as a sign-in challenge from the app. Absent when the request carries none.`,examples:[`Sign in to app.example.com
607
607
  Nonce: 7f3a9c2e5b1d4f60`]}),refusal:q2.refusal.optional()}).optional().meta({description:`What the key that the request carries may do, and the account that approval signs for. Absent for a request without a key.`}),session:R().meta({description:"The ID of the signed-in session, which `POST /v1/authorize/consent` names.",examples:[`8nVq3kZ0bT5wXy2mLp7sR4dA`]}),verified:Dn().meta({description:`Whether the app is a registered app, whose name the page marks as verified. A third-party app names itself in its metadata document.`,examples:[!0]})}).nullable().meta({description:"The request that the approval page shows, or `null` for a forged or expired query, or a request without a known app."})}).meta({description:`The request that the approval page shows.`})])})(i||=e.request||={});let a;(function(e){e.query=i.query,e.response=z({request:z({accounts:jn(z({address:R1.tempoAccount.shape.address.meta({description:`The account address.`,examples:[`0x8C3b5d0e2A4f6B1c9D7e3F5a0B2c4D6e8F1a3B5c`]}),balance:iB.balance.nullable().meta({description:"The account's holdings of USD tokens on the chain of the request's key, or of Tempo mainnet without one. `null` when the read fails or takes longer than 3 seconds."}),owner:R1.tempoAccount.shape.config.shape.owners.unwrap().element.shape.type,realm:R().nullable().meta({description:"The name of the account's realm, or `null` for the `default` realm.",examples:[`Tempo Cash`]})})).readonly().meta({description:`The user's accounts in the app's realms, oldest first.`}),app:R().meta({description:`The app's display name.`,examples:[`Tempo Cash`]})}).nullable().meta({description:"The account step, or `null` for a forged or expired query, or a request without a known app."})})})(a||=e.accounts||={})})(c5||={});var l5=new Fy().post(`/v1/authorize`,sV({description:"Authorizes the app for the signed-in user without a redirect. Only a first-party app's page on the redirect URI's origin calls it. A native app authorizes through `/oauth2/authorize` instead. With `code_challenge`, the app's backend receives a code. Without one, a public app receives tokens. A key authorization is signed by the account's owner, and must fit the headless ceiling. The account becomes the app's account for its later requests.",responses:gV({errors:[...wR.errors,...A2.errors,...dB,..._V.errors,...EV.errors,Jz,nI,HL,I1],success:{description:`The authorization.`,schema:c5.authorize.response}}),security:[{sessionCookie:[]}],tags:[`Authorization`]}),_V(`json`,c5.authorize.json),async e=>{let t=e.req.valid(`json`),n=t.client_id,r=await Z(e,SF($,{clientId:n}).catch(e=>{if(!(e instanceof hF))throw e}),`Apps.get`),i=wR(t,{app:r,origin:e.req.header(`origin`)});if(i)return X(e,i);let a=await Z(e,I4(e),`Session.get`);if(!a)return X(e,new Jz);let o=await Z(e,E4(e,{headers:new Headers(e.req.raw.headers),request:t,secret:!!r.secret,session:a}),`Headless.authorize`);return o instanceof Response?o:o instanceof eI?X(e,o):e.json(o,200)}).post(`/v1/authorize/account`,sV({description:"Selects the account that the app of `oauth_query` uses, then continues its authorization, and returns the next redirect. The selection holds for the app's later authorizations in the same session, and `GET /v1/account` lists it first. When the sign-in page showed the request's key and a passkey owns the selected account, the selection returns the passkey step, and the repeated selection with `passkey` signs the key without the approval page.",responses:gV({errors:[...dB,...F4.errors,..._V.errors,...w2.errors,...EV.errors,Gz,Jz,I1],success:{description:`The next redirect, or the passkey step.`,schema:c5.account.response}}),security:[{sessionCookie:[]}],tags:[`Authorization`]}),_V(`json`,c5.account.json),async e=>{let{account:t,oauth_query:n,passkey:r}=e.req.valid(`json`),i=F4(e,{oauth_query:n});if(i)return X(e,i);let a=await Z(e,I4(e),`Session.get`);if(!a)return X(e,new Jz);let o=await Z(e,EV(e,{limits:[{binding:`ACCOUNT_LIMIT`,key:a.user.id}]}),`RateLimit.check`);if(o)return o;let s=await Z(e,e.var.auth.$context,`auth.context`),c=await Z(e,ta(n,s.secret),`auth.verifyOAuthQueryParams`),l=new URLSearchParams(n),u=l.get(`client_id`);if(!c||!u)return X(e,new Gz);if(m4(l),!k2(await Z(e,w2(e,{clientId:u,userId:a.user.id}),`AccountStep.accounts`),t))return X(e,new I1({account:t}));e.set(`accountChosen`,!0);let d=M2({account:t.toLowerCase(),clientId:u,cookie:e.req.header(`cookie`),sessionId:a.session.id}),f=new Headers(e.req.raw.headers);f.set(`cookie`,d.header);let p=await Z(e,e.var.auth.api.oauth2Continue({asResponse:!1,body:{oauth_query:n,postLogin:!0},headers:f,request:new Request(e.req.url,{headers:f,method:`POST`})}),`auth.oauth2Continue`).catch(e=>{if(di(e)&&e.body?.error===`invalid_signature`)return new Gz;throw e});if(p instanceof eI)return X(e,p);let m=await Z(e,g4(e,{account:t,assertion:r?.assertion,headers:f,redirect:c5.account.result.parse(p).url,session:a}),`SignInConsent.afterAccountStep`);return e.header(`set-cookie`,d.setCookie,{append:!0}),e.header(`cache-control`,`private, no-store`),`options`in m?e.json(yz.step.parse({step:{options:m.options,type:`passkey`}}),200):e.json({redirect:m.redirect},200)}).post(`/v1/authorize/consent`,sV({description:"Records the signed-in user's decision on the app's authorization request that `oauth_query` carries, and returns the app's redirect. The decision applies only while `session_id` names the signed-in session. An approval stores the consent, so the app's next request with the same scopes skips the approval page. An approval of a request with a key authorization signs the key as the account's owner, and the first redemption of the code returns it from `/oauth2/token`. For a passkey-owned account, the approval first returns the passkey step, and the repeated approval with `passkey` signs the key. A user who holds no account in the app's realms, and whose key names none, first receives a Privy-owned account, as `POST /v1/account` creates it.",responses:gV({errors:[...TR.errors,...dB,...F4.errors,...X2.errors,...Z2.errors,..._V.errors,...EV.errors,SR,Gz,qz,Jz,yR],success:{description:`The app's redirect, or the passkey step.`,schema:c5.consent.response}}),security:[{sessionCookie:[]}],tags:[`Authorization`]}),_V(`json`,c5.consent.json),async e=>{let{accept:t,account:n,oauth_query:r,passkey:i,session_id:a}=e.req.valid(`json`),o=F4(e,{oauth_query:r});if(o)return X(e,o);let s=await Z(e,I4(e),`Session.get`);if(!s)return X(e,new Jz);if(s.session.id!==a)return X(e,new qz);let c=await Z(e,e.var.auth.$context,`auth.context`);if(!await Z(e,ta(r,c.secret),`auth.verifyOAuthQueryParams`))return X(e,new Gz);let l=new URLSearchParams(r);m4(l);let u=t&&(l.has(`key_authorization`)||l.has(`challenge`))?await Z(e,EV(e,{limits:[{binding:`AUTHORIZE_LIMIT`,key:s.user.id}]}),`RateLimit.check`):void 0;if(u)return u;if(t){let t=await Z(e,f4(e,{account:n,assertion:i?.assertion,headers:new Headers(e.req.raw.headers),oauthQuery:r,session:s}),`Consent.approve`);return t instanceof eI?X(e,t):(e.header(`cache-control`,`private, no-store`),`options`in t?e.json(c5.consent.step.parse({step:{options:t.options,type:`passkey`}}),200):e.json({redirect:t.redirect},200))}let d=await Z(e,e.var.auth.api.oauth2Consent({asResponse:!1,body:{accept:t,oauth_query:r},headers:new Headers(e.req.raw.headers),request:e.req.raw}),`auth.oauth2Consent`).catch(e=>{if(di(e)&&e.body?.error===`invalid_signature`)return new Gz;throw e});return d instanceof eI?X(e,d):(e.header(`cache-control`,`private, no-store`),e.json({redirect:c5.account.result.parse(d).url},200))}).get(`/v1/authorize/request`,sV({description:"Reads the app's authorization request that `oauth_query` carries, as the approval page shows it: the app, where the browser returns, the account that the approval applies to when the user holds several, and any key, with the account that approval signs for and why approval cannot sign it, if it cannot. The account read counts against the user's `ACCOUNT_LIMIT`, as `GET /v1/account` does. A user who holds no account shows no account, and approval creates the first one. Creates no account. Returns the app's redirect with the refusal for a key that Tempo ID refuses.",responses:gV({errors:[..._V.errors,Jz,nI],success:{description:`The request, or the app's redirect with a refusal.`,schema:c5.request.response}}),security:[{sessionCookie:[]}],tags:[`Authorization`]}),_V(`query`,c5.request.query),async e=>{if(e.req.header(`sec-fetch-site`)===`cross-site`)return X(e,new nI);let t=await Z(e,I4(e),`Session.get`);if(!t)return X(e,new Jz);e.header(`cache-control`,`private, no-store`);let{oauth_query:n}=e.req.valid(`query`),r=new URLSearchParams(n),i=await Z(e,e.var.auth.$context,`auth.context`);if(!await Z(e,ta(n,i.secret),`auth.verifyOAuthQueryParams`))return e.json({request:null},200);let a=r.get(`client_id`),o=r.get(`redirect_uri`),s=URL.parse(o??``);if(!a||!o||!s)return e.json({request:null},200);let c=await Z(e,SF($,{clientId:a}).catch(e=>{if(!(e instanceof hF))throw e}),`Apps.get`);if(!c||!c.redirectUris.includes(o))return e.json({request:null},200);let l=t=>{let n=new URL(o);n.searchParams.append(`error`,t.response.error),n.searchParams.append(`error_description`,t.response.error_description);let i=r.get(`state`);return i&&n.searchParams.append(`state`,i),n.searchParams.append(`iss`,U.URL),e.json({redirect:n.href},200)},u=ER(r);if(u instanceof eI)return l(u);let d=u&&TR({app:c,clientId:a,codeChallenge:r.get(`code_challenge`),key:u,query:r});if(d)return l(d);let f=DF(a)?new URL(a).host:[`http:`,`https:`].includes(s.protocol)?s.host:s.protocol.slice(0,-1),p=await Z(e,Y2(e,{account:u?.account,clientId:a,sessionId:t.session.id,userId:t.user.id}),`KeySigner.preview`),m=(()=>{if(p.accounts.length<2)return;let e=k2(p.accounts,p.account),t=e?.config.owners[0];if(e&&t)return{address:e.address,owner:t.type}})(),h=(()=>{if(!u)return;let e=r.get(`challenge`);return{...cR(u),...p.account?{account:p.account}:{},...e?{challenge:e}:{},...p.refusal?{refusal:p.refusal}:{}}})();return e.json({request:{...m?{account:m}:{},app:c.name??f,destination:f,email:t.user.email,...h?{key:h}:{},session:t.session.id,verified:!DF(a)}},200)}).get(`/v1/authorize/accounts`,sV({description:"Reads the account step of the app's authorization request that `oauth_query` carries: the app, and the user's accounts in its realms, oldest first, each with its balance on the chain of the request's key, or of Tempo mainnet without one. The read counts against the user's `ACCOUNT_LIMIT`, as `GET /v1/account` does.",responses:gV({errors:[...w2.errors,..._V.errors,...EV.errors,Jz,nI],success:{description:`The account step.`,schema:c5.accounts.response}}),security:[{sessionCookie:[]}],tags:[`Authorization`]}),_V(`query`,c5.accounts.query),async e=>{if(e.req.header(`sec-fetch-site`)===`cross-site`)return X(e,new nI);let t=await Z(e,I4(e),`Session.get`);if(!t)return X(e,new Jz);e.header(`cache-control`,`private, no-store`);let{oauth_query:n}=e.req.valid(`query`),r=new URLSearchParams(n),i=await Z(e,e.var.auth.$context,`auth.context`),a=await Z(e,ta(n,i.secret),`auth.verifyOAuthQueryParams`),o=r.get(`client_id`);if(!a||!o)return e.json({request:null},200);let s=await Z(e,SH(e,()=>SF($,{clientId:o}).catch(e=>{if(!(e instanceof hF))throw e}),[`apps.get`,o]),`Apps.get`);if(!s)return e.json({request:null},200);let c=await Z(e,EV(e,{limits:[{binding:`ACCOUNT_LIMIT`,key:t.user.id}]}),`RateLimit.check`);if(c)return c;let l=await Z(e,w2(e,{clientId:o,userId:t.user.id}),`AccountStep.accounts`),u=ER(r),d=u&&!(u instanceof eI)?Number(u.chainId):$L,f=l.flatMap(e=>{let t=e.config.owners[0];return t?[{address:e.address,owner:t.type,realm:e.realm.id==="default"?null:e.realm.name}]:[]}),p=await Z(e,sB(e,{accounts:f,chainId:d,rpcUrl:U.TEMPO_RPC_URL}),`Balance.list`);return e.json({request:{accounts:f.map((e,t)=>({...e,balance:p[t]??null})),app:s.name??`The app`}},200)});async function u5(e,t){let n=await Z(e,KR($,{deviceCode:t.deviceCode}),`Device.id`);if(!n)throw Error(`The device code has no row.`);let r=e.req.raw.cf,i=[r?.city,r?.country].filter(Boolean).join(`, `);await Z(e,VR($,{challenge:t.challenge??null,device:t.device,expiresAt:new Date(Date.now()+t.expiresIn*1e3),id:n,ip:e.req.header(`cf-connecting-ip`)??null,key:t.key??null,location:i||null}),`Device.create`)}async function d5(e,t){let n=qR(t.code),r=n?await Z(e,UR($,{userCode:n}),`Device.get`):void 0;if(!n||!r)return new IR;let i=await(async()=>{if(r.status!==`pending`||r.userId)return r;try{await Z(e,e.var.auth.api.deviceVerify({headers:e.req.raw.headers,query:{user_code:n}}),`auth.deviceVerify`)}catch(e){if(di(e))return;throw e}return await Z(e,UR($,{userCode:n}),`Device.get`)})();if(!i||i.userId&&i.userId!==t.userId)return new IR;let a=await Z(e,SF($,{clientId:r.clientId}).catch(e=>{if(!(e instanceof hF))throw e}),`Apps.get`);return{clientId:r.clientId,request:{...a?.name?{app:{name:a.name}}:{},...r.challenge?{challenge:r.challenge}:{},created_at:Math.floor(r.createdAt.getTime()/1e3),...r.device?{device:r.device}:{},...r.ip?{ip:r.ip}:{},...r.key?{key_authorization:cR(r.key)}:{},...r.location?{location:r.location}:{},status:i.status,user_code:i.userCode}}}(function(e){e.errors=[IR]})(d5||={});async function f5(e,t){let{request:n,session:r}=t,i=n.key,a=await Z(e,SF($,{clientId:n.clientId,enabled:!0}).catch(e=>{if(!(e instanceof hF))throw e}),`Apps.get`);if(!a?.device||a.secret||!a.firstParty)return new SR({description:`Approval refused: \`client_id\` ${n.clientId} names no enabled public first-party device app. Deny the request, and start the sign-in again.`});let o=iR(i)??aR({app:a,clientId:n.clientId,key:i});if(o)return o;let s=await Z(e,X2(e,{account:i.account??t.account,clientId:n.clientId,cookie:e.req.header(`cookie`),create:!0,passkey:!0,sessionId:r.session.id,userId:r.user.id}),`KeySigner.resolve`);if(s instanceof HL){let e=s.response.meta?.account;return new HL({account:e,description:`Passkey required: the passkey of Tempo Account ${e} signs only at its own relying party, which the device page is not part of. Name another account, or deny the request.`})}if(s instanceof eI)return s;if(t.assertion&&s.owner.signer)return new dz;if(!t.assertion&&!s.owner.signer)return{options:await Z(e,J2(e,{account:s.account,clientId:n.clientId,key:i,owner:s.owner,userId:r.user.id}),`KeySigner.challenge`)};let c=await Z(e,Z2(e,{account:s.account,assertion:t.assertion,clientId:n.clientId,key:i,owner:s.owner,userId:r.user.id}),`KeySigner.sign`);return c instanceof eI?c:{account:s.account,keyAuthorization:c}}(function(e){e.errors=[...iR.errors,SR,...aR.errors,...X2.errors,...Z2.errors,HL,dz]})(f5||={});var p5;(function(e){let t;(function(e){e.json=Pn({challenge:CR.challenge.refine(e=>e===void 0||/^(?:[\t\n]|[^\p{Cc}\p{Cf}])*$/u.test(e),{message:`Remove control and format characters, such as bidi overrides`}),client_id:R().min(1).max(255).optional().meta({description:"The client ID of the device app that the CLI signs in to, whose realms the sign-in and the device page use. Defaults to `tempo-cli`.",examples:[`tempo-cli`]}),device:R().trim().min(1).max(64).regex(/^[^\p{Cc}\p{Cf}]*$/u,{message:`Remove control and format characters, such as bidi overrides`}).meta({description:`The name that the device page shows, such as the machine's hostname. It holds no control or format characters.`,examples:[`ada-macbook`]}),key_authorization:YL.request}).refine(e=>!e.challenge||e.key_authorization,{message:"A challenge requires `key_authorization`, whose witness binds it",path:[`challenge`]}),e.response=z({device_code:R().meta({description:"The secret code that the CLI polls `/v1/device/token` with (RFC 8628 §3.2). The CLI keeps it private.",examples:[`GmRhmhcxhwAzkoEqiMEg_DnyEysNkuNhszIySk9eS`]}),expires_in:Sn().meta({description:`Seconds until the device code and user code expire.`,examples:[600]}),interval:Sn().meta({description:`Seconds between polls.`,examples:[5]}),user_code:R().meta({description:`The code that the user enters on the device page: eight consonants in two groups of four.`,examples:[`WDJB-MJHT`]}),verification_uri:En().meta({description:`The page where the user enters the user code.`,examples:[`https://id.tempo.xyz/device`]}),verification_uri_complete:En().meta({description:`The device page with the user code filled in, for a link or QR code.`,examples:[`https://id.tempo.xyz/device?code=WDJB-MJHT`]})})})(t||=e.authorize||={});let n;(function(e){e.json=z({client_id:t.json.shape.client_id.meta({description:"The client ID that `/v1/device/authorize` named. Defaults to `tempo-cli`.",examples:[`tempo-cli`]}),device_code:R().min(1).max(128).meta({description:"The device code that `/v1/device/authorize` returned.",examples:[`GmRhmhcxhwAzkoEqiMEg_DnyEysNkuNhszIySk9eS`]})}),e.response=CR.tokens.extend({account:YL.account.optional(),key_authorization:YL.rpc.optional().meta({description:`The signed key authorization, in the node's RPC format, when the CLI requested a key. Only the first redemption returns it.`})}).meta({description:`The tokens, with the signed key authorization when the CLI requested a key.`,id:`DeviceTokens`}),e.issued=z({access_token:R(),expires_in:Sn(),id_token:R().optional(),refresh_token:R().optional(),token_type:R()})})(n||=e.token||={});let r;(function(e){e.param=z({code:R().meta({description:`The user code.`,examples:[`WDJB-MJHT`]})}),e.response=z({request:z({app:z({name:R().meta({description:`The app's display name.`,examples:[`Tempo CLI`]})}).optional().meta({description:`The app that requested the code. Absent when the app has no display name.`}),challenge:R().optional().meta({description:`The message whose EIP-191 hash is the key's witness, which approval signs. Absent when the CLI sent none.`,examples:[`Sign in to app.example.com
608
608
  Nonce: 7f3a9c2e5b1d4f60`]}),created_at:Sn().meta({description:`When the CLI requested the code, in Unix seconds.`,examples:[1792075800]}),device:R().optional().meta({description:"The name that the CLI reported, such as its hostname. Absent for a code from `POST /device/code`.",examples:[`ada-macbook`]}),ip:R().optional().meta({description:`The CLI's IP address. Absent when it is unknown.`,examples:[`203.0.113.7`]}),key_authorization:YL.description.extend({account:YL.description.shape.account.meta({description:`The Tempo Account that approval signs for: the one the request names, else the one the user selected for the app, else the oldest. Absent when the request names none and the accounts cannot be read, or the user holds none.`,examples:[`0x9a073914db0d149375ac2b7fbb72c68c0780fb5f`]}),refusal:q2.refusal.optional()}).optional().meta({description:`What the key that the CLI requested may do. Absent when the CLI requested no key.`}),location:R().optional().meta({description:`The CLI's city and country, from its IP address. Absent when they are unknown.`,examples:[`Berlin, DE`]}),status:xn([`approved`,`denied`,`pending`]).meta({description:"Whether the user approved or denied the code. `pending` until the user decides.",examples:[`pending`]}),user_code:R().meta({description:`The user code.`,examples:[`WDJB-MJHT`]})}).meta({description:`The request that the CLI made with the code.`})})})(r||=e.requests||={});let i;(function(e){e.json=z({account:R1.tempoAccount.shape.address.optional().meta({description:`The Tempo Account that the device page showed for the request's key authorization, one of the user's accounts in the app's realms. Ignored when the key names its account, and absent for a request without a key.`,examples:[`0x8C3b5d0e2A4f6B1c9D7e3F5a0B2c4D6e8F1a3B5c`]}),code:R().max(32).meta({description:`The user code.`,examples:[`WDJB-MJHT`]}),passkey:z({assertion:yz.assertion}).optional().meta({description:`The passkey's assertion over the options of the passkey step, which a passkey-owned account's approval returns. The repeated approval signs the key with it.`})});let t=e.step=yz.step;e.response=gn([z({status:bn(`approved`).meta({description:`The user approved the code. The CLI receives its tokens, and any signed key, on its next poll.`})}).meta({description:`A stored approval.`}),t])})(i||=e.approve||={});let a;(function(e){e.json=z({code:i.json.shape.code}),e.response=z({status:bn(`denied`).meta({description:"The user denied the code. The next poll returns `access_denied`."})})})(a||=e.deny||={})})(p5||={});async function m5(e,t){if(M4(e))return new nI;let n=await Z(e,I4(e),`Session.get`);if(!n)return new Jz;let r=await Z(e,EV(e,{limits:[{binding:`AUTHORIZE_LIMIT`,key:n.user.id}]}),`RateLimit.check`);if(r)return r;let i=qR(t.code),a=i?await Z(e,UR($,{userCode:i}),`Device.get`):void 0;if(!i||!a||a.userId&&a.userId!==n.user.id)return new IR;if(a.status!==`pending`)return new jR;let o=e.req.raw.headers,s=await(async()=>{if(a.userId)return a;try{await Z(e,e.var.auth.api.deviceVerify({headers:o,query:{user_code:i}}),`auth.deviceVerify`)}catch(e){if(!di(e))throw e}return await Z(e,UR($,{userCode:i}),`Device.get`)})();if(!s||s.userId!==n.user.id)return new IR;if(s.status!==`pending`)return new jR;let c=await(async()=>{if(t.decision!==`approve`||!s.key)return;let r=await Z(e,f5(e,{account:t.account,assertion:t.assertion,request:s,session:n}),`DeviceRequest.sign`);if(r instanceof eI)return r;if(r.options)return{options:r.options};let i={account:r.account,keyAuthorization:r.keyAuthorization};return await Z(e,WR($,{id:s.id,key:i,userId:n.user.id}),`Device.hold`)?{key:i}:await l()})();if(c instanceof eI)return c;if(c&&`options`in c)return{options:c.options};try{await Z(e,t.decision===`approve`?e.var.auth.api.deviceApprove({body:{userCode:i},headers:o}):e.var.auth.api.deviceDeny({body:{userCode:i},headers:o}),t.decision===`approve`?`auth.deviceApprove`:`auth.deviceDeny`);return}catch(t){if(c&&await Z(e,GR($,{id:s.id,key:c.key}),`Device.release`),!di(t))throw t;return await l()}async function l(){return await Z(e,UR($,{userCode:i}),`Device.get`)?new jR:new IR}}(function(e){e.errors=[...f5.errors,Jz,jR,IR,nI]})(m5||={});async function h5(e,t){let n=await Z(e,e.var.auth.handler(new Request(new URL(`/oauth2/token`,U.URL),{body:new URLSearchParams({client_id:t.clientId,device_code:t.deviceCode,grant_type:gF,resource:U.URL}),headers:{"content-type":`application/x-www-form-urlencoded`},method:`POST`})),`auth.handler`),r=await Z(e,n.json(),`response.json`);if(n.ok)return p5.token.issued.parse(r);let i=z({error:R()}).safeParse(r).data?.error;if(i===`authorization_pending`)return new MR;if(i===`slow_down`)return new PR;if(i===`access_denied`)return new FR;if(i===`expired_token`||i===`invalid_grant`)return new NR;throw Error(`The token endpoint refused a device code with ${i??n.status}.`)}(function(e){e.errors=[MR,NR,PR,FR]})(h5||={});var g5=new Fy().post(`/v1/device/authorize`,sV({description:"Starts the device grant (RFC 8628) for a CLI, as the device app that `client_id` names, or `tempo-cli`. The user approves the user code on the device page, and the CLI polls `/v1/device/token`. A request with `key_authorization` asks for a key, which the device page shows and approval signs. The key follows the rules of the redirect's approval page, without the headless ceiling, and a `challenge` requires the app's `tempo-id:sign` scope.",responses:gV({errors:[...dB,...iR.errors,...aR.errors,..._V.errors,...EV.errors,SR,nI],success:{description:`The device code.`,schema:p5.authorize.response}}),tags:[`Device grant`]}),_V(`json`,p5.authorize.json),async e=>{let t=await Z(e,EV(e,{limits:[{binding:`DEVICE_LIMIT`,key:jV(e)}]}),`RateLimit.check`);if(t)return t;let{challenge:n,client_id:r=LR,device:i,key_authorization:a}=e.req.valid(`json`),o=await Z(e,SF($,{clientId:r,enabled:!0}).catch(e=>{if(!(e instanceof hF))throw e}),`Apps.get`);if(!o?.device||o.secret||!o.firstParty)return X(e,new SR({description:`Device grant refused: \`client_id\` ${r} names no enabled public first-party device app. Send the client ID of a registered device app, or leave out \`client_id\`.`}));if(a){let t=rR(a,{challenge:n}),i=iR(t)??aR({app:o,clientId:r,key:t});if(i)return X(e,i)}let s=await Z(e,e.var.auth.api.deviceCode({body:{client_id:r,resource:U.URL,scope:RR}}),`auth.deviceCode`);await Z(e,u5(e,{challenge:n,device:i,deviceCode:s.device_code,expiresIn:s.expires_in,key:a}),`DeviceRequest.create`);let c=HR(s.user_code),l=new URL(JR,U.URL);return e.header(`cache-control`,`no-store`),e.json({device_code:s.device_code,expires_in:s.expires_in,interval:s.interval,user_code:c,verification_uri:l.href,verification_uri_complete:`${l.href}?${new URLSearchParams({code:c})}`},200)}).post(`/v1/device/token`,sV({description:`Polls for the device grant's tokens (RFC 8628 §3.4). The tokens of an approved code, and the key authorization that approval signed, are returned once.`,responses:gV({errors:[...dB,..._V.errors,...EV.errors,...h5.errors,nI],success:{description:`The tokens.`,schema:p5.token.response}}),tags:[`Device grant`]}),_V(`json`,p5.token.json),async e=>{let t=await Z(e,EV(e,{limits:[{binding:`TOKEN_LIMIT`,key:jV(e)}]}),`RateLimit.check`);if(t)return t;let n=e.req.valid(`json`).device_code,r=await Z(e,KR($,{deviceCode:n}),`Device.id`),i=await Z(e,h5(e,{clientId:e.req.valid(`json`).client_id??`tempo-cli`,deviceCode:n}),`device.poll`);if(e.header(`cache-control`,`no-store`),i instanceof eI)return X(e,i);let a=r?await Z(e,XR($,{id:r}),`Device.take`).catch(t=>{UF(e,{error:t,message:`The device token poll failed to take the held key.`})}):void 0,{access_token:o,expires_in:s,id_token:c,refresh_token:l,token_type:u}=i;return e.json({access_token:o,...a?{account:a.account,key_authorization:a.keyAuthorization}:{},expires_in:s,...c?{id_token:c}:{},...l?{refresh_token:l}:{},token_type:u},200)}).get(`/v1/device/requests/:code`,sV({description:"Reads a device code's request for the device page, by its user code. The first signed-in user to read a pending code binds it, so no other user decides it. A pending request's key carries the account that approval signs for, and why approval cannot sign it, if it cannot. That lookup counts against the user's `ACCOUNT_LIMIT`, as `GET /v1/account` does. Creates no account.",responses:gV({errors:[..._V.errors,...d5.errors,...EV.errors,Jz,nI],success:{description:`What the CLI requested.`,schema:p5.requests.response}}),security:[{sessionCookie:[]}],tags:[`Device grant`]}),_V(`param`,p5.requests.param),async e=>{if(e.req.header(`sec-fetch-site`)===`cross-site`)return X(e,new nI);let t=await Z(e,I4(e),`Session.get`);if(!t)return X(e,new Jz);let n=await Z(e,EV(e,{limits:[{binding:`AUTHORIZE_LIMIT`,key:`${t.user.id}:device`}]}),`RateLimit.check`);if(n)return n;let r=await Z(e,d5(e,{code:e.req.valid(`param`).code,userId:t.user.id}),`DeviceRequest.read`);if(e.header(`cache-control`,`private, no-store`),r instanceof eI)return X(e,r);let{clientId:i,request:a}=r,{key_authorization:o,...s}=a;if(!o||a.status!==`pending`)return e.json({request:a},200);let c=await Z(e,Y2(e,{account:o.account,clientId:i,sessionId:t.session.id,userId:t.user.id}),`KeySigner.preview`);return e.json({request:{...s,key_authorization:{...o,...c.account?{account:c.account}:{},...c.refusal?{refusal:c.refusal}:{}}}},200)}).post(`/v1/device/approve`,sV({description:"Approves a device code for the signed-in user. Only Tempo ID's device page may call it. The CLI receives its tokens on its next poll. An approval of a request with a key authorization signs the key as the account's owner, and the poll returns it beside the tokens. For a passkey-owned account, the approval first returns the passkey step, and the repeated approval with `passkey` signs the key. A user who holds no account in the app's realms, and whose key names none, first receives a Privy-owned account, as `POST /v1/account` creates it.",responses:gV({errors:[...dB,..._V.errors,...EV.errors,...m5.errors],success:{description:`The code is approved, or the passkey step.`,schema:p5.approve.response}}),security:[{sessionCookie:[]}],tags:[`Device grant`]}),_V(`json`,p5.approve.json),async e=>{let{account:t,code:n,passkey:r}=e.req.valid(`json`),i=await Z(e,m5(e,{account:t,assertion:r?.assertion,code:n,decision:`approve`}),`device.decide`);return i instanceof Response?i:i instanceof eI?X(e,i):i?(e.header(`cache-control`,`private, no-store`),e.json(p5.approve.step.parse({step:{options:i.options,type:`passkey`}}),200)):e.json({status:`approved`},200)}).post(`/v1/device/deny`,sV({description:"Denies a device code for the signed-in user. Only Tempo ID's device page may call it. The CLI's next poll returns `access_denied`.",responses:gV({errors:[...dB,..._V.errors,...EV.errors,...m5.errors],success:{description:`The code is denied.`,schema:p5.deny.response}}),security:[{sessionCookie:[]}],tags:[`Device grant`]}),_V(`json`,p5.deny.json),async e=>{let t=await Z(e,m5(e,{code:e.req.valid(`json`).code,decision:`deny`}),`device.decide`);return t instanceof Response?t:t instanceof eI?X(e,t):e.json({status:`denied`},200)}),_5;(function(e){let t;(function(e){e.response=z({ok:bn(!0).meta({description:"Always `true`."}),version:z({id:R().meta({description:"The version's ID, as `wrangler deploy` prints it.",examples:[`a5f3c2e1-7b4d-4e8a-9c6f-2d1b0e3a4c5f`]}),tag:R().meta({description:`The version's tag, or empty when it has none.`,examples:[`v1.4.0`]})}).meta({description:`The deployed Worker version that served the request.`})})})(t||=e.health||={})})(_5||={});var v5=new Fy().get(`/health`,sV({description:`Responds while the Worker is up, with the version that served the request.`,responses:gV({success:{description:`The Worker is up.`,schema:_5.health.response}}),tags:[`Health`]}),e=>{let{id:t,tag:n}=e.env.CF_VERSION_METADATA;return e.header(`cache-control`,`no-store`),e.json({ok:!0,version:{id:t,tag:n}},200)}),y5,b5=Zz(async(e,t)=>{e.set(`cache`,e.env.CACHE??(y5??=xH({ttl:(U.CONFIG_CACHE_TTL??30)*1e3}))),await t()}),x5=60,S5;(function(e){e.continuation=z({client_id:R().optional(),expiresAt:Sn(),id_token_hint:R(),post_logout_redirect_uri:R().optional(),state:R().optional()})})(S5||={});var C5=class extends tI(`invalid_id_token_hint`){name=`Logout.HintInvalidError`;constructor(){super({error_description:`Invalid id_token_hint: it is not an ID token that this issuer signed for the app. Send the ID token that the app received at sign-in.`,field:`id_token_hint`})}},w5=class extends tI(`logout_not_permitted`){name=`Logout.NotPermittedError`;constructor(e){super({error_description:`Logout not permitted: the app ${e.clientId} may not end the session. Register the app for logout, then retry.`,meta:{client_id:e.clientId}})}},T5=class extends tI(`post_logout_redirect_not_permitted`){name=`Logout.RedirectNotPermittedError`;constructor(e){super({error_description:`Invalid post_logout_redirect_uri: ${e.uri} is not registered for the app. Use one of its post-logout redirect URIs, or leave it out.`,field:`post_logout_redirect_uri`,meta:{post_logout_redirect_uri:e.uri}})}};async function E5(e,t){let n=await j5(t);if(n instanceof C5)return n;let[r]=await e.select({disabled:rP.disabled,enableEndSession:rP.enableEndSession,postLogoutRedirectUris:rP.postLogoutRedirectUris}).from(rP).where(Y(rP.clientId,n.clientId));if(!r||r.disabled||!r.enableEndSession)return new w5({clientId:n.clientId});let i=(()=>{let e=t.postLogoutRedirectUri;if(e===void 0)return;if(!(r.postLogoutRedirectUris??[]).includes(e))return new T5({uri:e});let n=new URL(e);return t.state!==void 0&&n.searchParams.set(`state`,t.state),n.href})();return i instanceof T5?i:{redirect:i,sessionId:n.sessionId}}(function(e){e.errors=[C5,w5,T5]})(E5||={});async function D5(e,t){let[n]=await e.select({id:mP.id}).from(mP).where(Y(mP.id,t.sessionId));if(n)throw Error(`The session still exists after sign-out.`)}async function O5(e,t){return await Xr({data:JSON.stringify(S5.continuation.parse({...e,expiresAt:Math.floor(Date.now()/1e3)+x5})),key:await M5(t.secret)})}async function k5(e,t){let n=await In({data:e,key:await M5(t.secret)}).then(e=>S5.continuation.safeParse(JSON.parse(e))).catch(()=>void 0);if(n?.success&&!(n.data.expiresAt<=Date.now()/1e3))return n.data}async function A5(e,t){await e.update(uP).set({revoked:new Date}).where(sM(Y(uP.sessionId,t.sessionId),gM(uP.revoked)))}async function j5(e){let{clientId:t,issuer:n,jwks:r}=e,i=await(async()=>{try{let t=await $r(e.hint,hi(r),{algorithms:[`RS256`]});return JSON.parse(new TextDecoder().decode(t.payload))}catch{return}})();if(!i||typeof i!=`object`)return new C5;let a=i,o=typeof a.aud==`string`?[a.aud]:Array.isArray(a.aud)?a.aud.filter(e=>typeof e==`string`):[],s=t??(o.length===1?o[0]:void 0);return a.iss!==n||!s||!o.includes(s)||typeof a.sid!=`string`||!a.sid||typeof a.sub!=`string`||!a.sub?new C5:{clientId:s,sessionId:a.sid,userId:a.sub}}async function M5(e){let t=new TextEncoder,n=await crypto.subtle.importKey(`raw`,t.encode(e),`HKDF`,!1,[`deriveBits`]),r=await crypto.subtle.deriveBits({hash:`SHA-256`,info:t.encode(`tempo-id:logout-continuation:v1`),name:`HKDF`,salt:new Uint8Array},n,256);return Xt(new Uint8Array(r))}var N5;(function(e){let t;(function(e){e.response=Nn({authorization_endpoint:En().meta({description:`The authorization endpoint.`,examples:[`https://id.tempo.xyz/oauth2/authorize`]}),issuer:En().meta({description:"The issuer's identifier, every token's `iss`.",examples:[`https://id.tempo.xyz`]}),jwks_uri:En().meta({description:`The issuer's signing keys.`,examples:[`https://id.tempo.xyz/oauth2/jwks`]}),token_endpoint:En().meta({description:`The token endpoint.`,examples:[`https://id.tempo.xyz/oauth2/token`]})}).meta({description:`The issuer's metadata (RFC 8414 §2, OpenID Connect Discovery §3), with the members that RFC 8414 defines.`,id:`AuthorizationServerMetadata`})})(t||=e.openidConfiguration||={});let n;(function(e){e.response=t.response})(n||=e.oauthAuthorizationServer||={});let r;(function(e){e.query=z({challenge:R().optional().meta({description:"A message, such as a sign-in challenge from the app's backend, whose EIP-191 hash becomes the key authorization's `witness` (TIP-1053). Requires `key_authorization`, and the app's `tempo-id:sign` scope.",examples:[`Sign in to app.example.com
609
- Nonce: 7f3a9c2e5b1d4f60`]}),client_id:R().meta({description:`The app's client ID.`,examples:[`tempo-cli`]}),code_challenge:R().meta({description:`The PKCE challenge: the base64url SHA-256 hash of the code verifier (RFC 7636 §4.2).`,examples:[`E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM`]}),code_challenge_method:bn(`S256`).meta({description:`The PKCE challenge method.`}),key_authorization:R().optional().meta({description:"A key authorization for the app's own key, as base64url JSON in the shape of `KeyAuthorizationRequest`. The request always shows the approval page, which signs the key, and `/oauth2/token` returns it beside the tokens. A key that breaks a rule returns to the redirect URI with the refusal.",examples:[`eyJhZGRyZXNzIjoiMHg4MWMwZjIyYmQxNzNjMTE1ZDE4ZWVlYTBmNmEzOGU5MzVlY2Y1MmZiIn0`]}),prompt:xn([`consent`,`login`,`none`,`select_account`]).optional().meta({description:`Whether the user signs in or consents again (OIDC Core §3.1.2.1). Absent to reuse the session and stored consent.`,examples:[`consent`]}),redirect_uri:En().meta({description:`One of the app's registered redirect URIs.`,examples:[`https://app.example/callback`]}),resource:En().optional().meta({description:`The API the access token is for (RFC 8707). Absent for Tempo ID's own origin.`,examples:[`https://id.tempo.xyz`]}),response_type:bn(`code`).meta({description:`The authorization code flow.`}),scope:R().meta({description:`Space-separated OAuth scopes.`,examples:[`openid profile email`]}),state:R().optional().meta({description:`An opaque value that the redirect returns to the app unchanged.`,examples:[`af0ifjsldkj`]})}),e.response=z({redirect:Dn().meta({description:"Whether the app sends the browser to `url`.",examples:[!0]}),url:R().meta({description:`Where the browser goes next: the sign-in page, the consent page, or the redirect URI with a code.`,examples:[`https://app.example/callback?code=SplxlOBeZQQYbYS6WxSbIA`]})}).meta({description:`The next step of the authorization, for a request that a script sends.`})})(r||=e.authorize||={});let i;(function(e){e.error=z({error:R().meta({description:"The RFC 6749 error code, such as `invalid_grant` or `invalid_client`.",examples:[`invalid_grant`]}),error_description:R().optional().meta({description:`The issuer's description of the error. Absent when the issuer sends none.`,examples:[`invalid code`]}),error_uri:En().optional().meta({description:`A page about the error. Absent when the issuer sends none.`,examples:[`https://example.com/docs/errors#invalid_grant`]}),request_id:R().optional().meta({description:"The request ID, which Tempo ID adds and `X-Request-Id` also carries.",examples:[`5b3e1f2a-8c4d-4e6f-9a0b-7c2d1e3f4a5b`]})}).meta({description:`The issuer's OAuth error response (RFC 6749 §5.2), passed through.`,id:`OAuthErrorResponse`}),e.form=z({client_id:R().optional().meta({description:"The app's client ID. Absent when the app authenticates with HTTP Basic `Authorization`.",examples:[`tempo-cli`]}),client_secret:R().optional().meta({description:`A confidential app's secret.`,examples:[`3bTm9qXc2Lr7WvN5kYp8Hs4Df6Ga1Je0`]}),code:R().optional().meta({description:"The authorization code to redeem, for the `authorization_code` grant.",examples:[`SplxlOBeZQQYbYS6WxSbIA`]}),code_verifier:R().optional().meta({description:"The PKCE verifier whose S256 hash is the authorization request's `code_challenge` (RFC 7636 §4.5).",examples:[`dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk`]}),device_code:R().optional().meta({description:`The device code, for the device code grant (RFC 8628 §3.4).`,examples:[`GmRhmhcxhwAzkoEqiMEg_DnyEysNkuNhszIySk9eS`]}),grant_type:xn([`authorization_code`,`client_credentials`,`refresh_token`,`urn:ietf:params:oauth:grant-type:device_code`]).meta({description:`The OAuth grant that the request redeems.`,examples:[`authorization_code`]}),redirect_uri:R().optional().meta({description:"The redirect URI of the authorization request, for the `authorization_code` grant.",examples:[`https://app.example/callback`]}),refresh_token:R().optional().meta({description:"The refresh token to redeem, for the `refresh_token` grant.",examples:[`yAjhKk7QnRZ3vD9pLm2Xc8Ws5Tf1Ub4N`]}),resource:En().optional().meta({description:`The API the access token is for (RFC 8707). Absent for Tempo ID's own origin.`,examples:[`https://id.tempo.xyz`]}),scope:R().optional().meta({description:`Space-separated OAuth scopes to request. Absent to keep the scopes of the grant.`,examples:[`openid profile email`]})}),e.response=Nn({access_token:R().meta({description:`The access token, an RS256 JWT for the requested resource.`,examples:[`eyJhbGciOiJSUzI1NiIsInR5cCI6ImF0K2p3dCJ9.e30.c2lnbmF0dXJl`]}),account:YL.account.optional().meta({description:"The Tempo Account that the key acts for. Present beside `key_authorization`.",examples:[`0x9a073914db0d149375ac2b7fbb72c68c0780fb5f`]}),expires_in:Sn().meta({description:`How long the access token lasts, in seconds.`,examples:[300]}),id_token:R().optional().meta({description:"The ID token, an RS256 JWT. Absent without the `openid` scope.",examples:[`eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.e30.c2lnbmF0dXJl`]}),key_authorization:YL.rpc.optional().meta({description:"The key authorization that the approval page signed, for the first redemption of a code whose request carried `key_authorization`. Absent for every other code, a refresh, and a key that expired."}),refresh_token:R().optional().meta({description:"The refresh token. Absent without the `offline_access` scope.",examples:[`yAjhKk7QnRZ3vD9pLm2Xc8Ws5Tf1Ub4N`]}),scope:R().optional().meta({description:`Space-separated OAuth scopes of the tokens.`,examples:[`openid profile email`]}),token_type:R().meta({description:`The type of the access token (RFC 6749 §7.1).`,examples:[`Bearer`]})}).meta({description:`The issuer's token response (RFC 6749 §5.1).`,id:`TokenResponse`})})(i||=e.token||={});let a;(function(e){e.form=z({client_id:R().optional().meta({description:"The app's client ID. The app holds the device grant. Absent when the app authenticates with HTTP Basic `Authorization`.",examples:[`tempo-cli`]}),client_secret:R().optional().meta({description:`A confidential app's secret.`,examples:[`3bTm9qXc2Lr7WvN5kYp8Hs4Df6Ga1Je0`]}),resource:En().optional().meta({description:`The API the access token is for (RFC 8707). Absent for Tempo ID's own origin.`,examples:[`https://id.tempo.xyz`]}),scope:R().optional().meta({description:`Space-separated OAuth scopes.`,examples:[`openid email offline_access`]})}),e.response=z({device_code:R().meta({description:"The secret code that the device polls `/oauth2/token` with (RFC 8628 §3.2). The device keeps it private.",examples:[`GmRhmhcxhwAzkoEqiMEg_DnyEysNkuNhszIySk9eS`]}),expires_in:Sn().meta({description:`Seconds until the device code and user code expire.`,examples:[600]}),interval:Sn().meta({description:`Seconds between polls.`,examples:[5]}),user_code:R().meta({description:`The code that the user enters on the verification page: eight consonants.`,examples:[`WDJBMJHT`]}),verification_uri:En().meta({description:`The page where the user enters the user code.`,examples:[`https://id.tempo.xyz/device`]}),verification_uri_complete:En().meta({description:`The verification page with the user code filled in, for a link or QR code.`,examples:[`https://id.tempo.xyz/device?user_code=WDJBMJHT`]})}).meta({description:`The issuer's device authorization response (RFC 8628 §3.2).`}),e.issued=z({device_code:R(),expires_in:Sn()})})(a||=e.deviceCode||={});let o;(function(e){e.form=z({client_id:i.form.shape.client_id,client_secret:i.form.shape.client_secret,token:R().meta({description:`The token to introspect.`,examples:[`yAjhKk7QnRZ3vD9pLm2Xc8Ws5Tf1Ub4N`]}),token_type_hint:xn([`access_token`,`refresh_token`]).optional().meta({description:"The type of `token`, which helps the issuer find it (RFC 7662 §2.1).",examples:[`refresh_token`]})}),e.response=Nn({active:Dn().meta({description:`Whether the token is active. An inactive token has no other members.`,examples:[!0]}),client_id:R().optional().meta({description:`The client ID of the app that the token belongs to.`,examples:[`tempo-cli`]}),exp:Sn().optional().meta({description:`When the token expires, in Unix seconds.`,examples:[1792076100]}),iat:Sn().optional().meta({description:`When the issuer issued the token, in Unix seconds.`,examples:[1792075800]}),iss:R().optional().meta({description:`The issuer's identifier.`,examples:[`https://id.tempo.xyz`]}),scope:R().optional().meta({description:`Space-separated OAuth scopes of the token.`,examples:[`openid profile email`]}),sub:R().optional().meta({description:`The user ID of the token's subject.`,examples:[`user_01JZ8Q6W3N1R5B4V7C2X9K0M3T`]})}).meta({description:`The issuer's introspection response (RFC 7662 §2.2).`,id:`IntrospectionResponse`})})(o||=e.introspect||={});let s;(function(e){e.form=z({client_id:i.form.shape.client_id,client_secret:i.form.shape.client_secret,token:R().meta({description:`The access or refresh token to revoke.`,examples:[`yAjhKk7QnRZ3vD9pLm2Xc8Ws5Tf1Ub4N`]}),token_type_hint:o.form.shape.token_type_hint})})(s||=e.revoke||={});let c;(function(e){e.response=Nn({email:R().optional().meta({description:"The user's email address. Absent without the `email` scope.",examples:[`ada@example.com`]}),email_verified:Dn().optional().meta({description:"Whether the issuer verified the email address. Absent without the `email` scope.",examples:[!0]}),sub:R().meta({description:`The user ID.`,examples:[`user_01JZ8Q6W3N1R5B4V7C2X9K0M3T`]})}).meta({description:`The issuer's UserInfo response (OIDC Core §5.3.2).`,id:`UserInfoResponse`})})(c||=e.userinfo||={});let l;(function(e){e.form=(e.query=z({client_id:R().optional().meta({description:"The app's client ID. Absent when `id_token_hint` names the app.",examples:[`tempo-cli`]}),continuation:R().optional().meta({description:`The sealed parameters of a form POST that carried no session cookie, which its 303 sends here. Absent otherwise.`,examples:[`a3f1c2…`]}),id_token_hint:R().optional().meta({description:"An ID token that Tempo ID issued to the app, which names the session to end. It may be expired. Required without `continuation`.",examples:[`eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.e30.c2lnbmF0dXJl`]}),post_logout_redirect_uri:En().optional().meta({description:`Where the browser goes after sign-out: one of the app's registered post-logout redirect URIs.`,examples:[`https://app.example/signed-out`]}),state:r.query.shape.state})).omit({continuation:!0}).extend({id_token_hint:R().meta({description:`An ID token that Tempo ID issued to the app, which names the session to end. It may be expired.`,examples:[`eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.e30.c2lnbmF0dXJl`]})}),e.response=z({signed_out:bn(!0).meta({description:`The browser holds no session that the hint names, since it ended or never held one.`})})})(l||=e.endSession||={});let u;(function(e){e.response=z({keys:jn(Nn({alg:R().optional().meta({description:`The algorithm that the key signs with.`,examples:[`RS256`]}),kid:R().optional().meta({description:"The key ID, which matches the `kid` header of a token that the key signs.",examples:[`Qq0BN2lPx8VzTRsaGgMjc5HbEFKY4Wty`]}),kty:R().meta({description:`The key family (RFC 7518 §6.1).`,examples:[`RSA`]})})).meta({description:`The issuer's public signing keys, with the members of each key that RFC 7517 defines.`})}).meta({description:`The issuer's JSON Web Key Set (RFC 7517 §5).`,id:`JsonWebKeySet`})})(u||=e.jwks||={})})(N5||={});var P5={...mV([]),400:{content:{"application/json":{schema:rV(N5.token.error)}},description:`The issuer's refusal, passed through.`},401:{content:{"application/json":{schema:rV(N5.token.error)}},description:`The issuer's refusal of the client or token, passed through.`}},F5={responses:{200:{content:{"application/json":{schema:rV(N5.introspect.response)}},description:`The issuer's introspection response.`},...P5,...mV([...dB,...EV.errors])},security:[{},{clientBasic:[]}],tags:[`OAuth`]},I5={description:`Signs the browser out (OpenID Connect RP-Initiated Logout) when it holds the session that the app's ID token names: revokes the refresh tokens that apps received through that session, ends it, and clears its cookie and the account step's selections. Any other session stays signed in. Redirects the browser to the app's post-logout redirect URI.`,responses:{302:{description:"Redirects the browser to the app's post-logout redirect URI, with `state`."},...gV({errors:[..._V.errors,...E5.errors],success:{description:"The browser is signed out of the session that the hint names, for a request without `post_logout_redirect_uri`.",schema:N5.endSession.response}})},tags:[`OAuth`]},L5=[`/.well-known/oauth-authorization-server`,`/.well-known/openid-configuration`,`/oauth2/authorize`,`/oauth2/introspect`,`/oauth2/jwks`,`/oauth2/revoke`,`/oauth2/token`,`/oauth2/userinfo`],R5=new Set([`/device/code`,`/oauth2/authorize`,`/oauth2/introspect`,`/oauth2/revoke`,`/oauth2/token`]),z5=new Fy().get(`/.well-known/openid-configuration`,sV({description:`Reads the issuer's OpenID Connect discovery document.`,responses:gV({success:{description:`The discovery document.`,schema:N5.openidConfiguration.response}}),tags:[`OAuth`]}),e=>H5(e)).get(`/.well-known/oauth-authorization-server`,sV({description:`Reads the issuer's authorization server metadata.`,responses:gV({success:{description:`The metadata.`,schema:N5.oauthAuthorizationServer.response}}),tags:[`OAuth`]}),e=>H5(e)).get(`/oauth2/authorize`,sV({description:`Starts an authorization. A signed-out browser goes to the sign-in page, and a signed-in one to the consent page or to the redirect URI with a code.`,responses:{200:{content:{"application/json":{schema:rV(N5.authorize.response)}},description:`The next step, for a request that a script sends.`},302:{description:"Redirects the browser to the sign-in page, the consent page, or the redirect URI. A refused `key_authorization` returns to the redirect URI with `error` and `error_description`. An unknown or disabled app, or an unregistered redirect URI, redirects to the error page."},...P5,...mV(EV.errors)},tags:[`OAuth`]}),hV(`query`,N5.authorize.query),e=>H5(e)).post(`/oauth2/token`,sV({description:`Redeems an authorization code, a refresh token, a device code, or client credentials for tokens.`,responses:{200:{content:{"application/json":{schema:rV(N5.token.response)}},description:`The tokens.`},...P5,...mV([...dB,...EV.errors])},security:[{},{clientBasic:[]}],tags:[`OAuth`]}),hV(`form`,N5.token.form),async e=>{let t=await Z(e,EV(e,{limits:[{binding:`TOKEN_LIMIT`,key:jV(e)}]}),`RateLimit.check`);if(t)return t;let n=new URLSearchParams(await Z(e,e.req.text(),`request.text`)),r=B5({authorization:e.req.header(`authorization`),form:n}),i=r?await Z(e,yF($,r),`Apps.authenticate`):!1;return await Z(e,EV(e,{limits:[{binding:`TOKEN_APP_LIMIT`,key:i?r?.clientId:void 0}]}),`RateLimit.check`)||H5(e)}).post(`/device/code`,sV({description:"Starts the device grant (RFC 8628 §3.1) for an app that holds it. The user approves the user code on the verification page, and the device redeems the device code at `/oauth2/token`. The device code binds to the user who approves it.",responses:{200:{content:{"application/json":{schema:rV(N5.deviceCode.response)}},description:`The device code.`},...P5,...mV([...dB,...EV.errors])},security:[{},{clientBasic:[]}],tags:[`OAuth`]}),hV(`form`,N5.deviceCode.form),async e=>{let t=jV(e),n=await Z(e,EV(e,{limits:[{binding:`DEVICE_LIMIT`,key:t===void 0?void 0:`${t}:form`}]}),`RateLimit.check`);if(n)return n;let r=await Z(e,H5(e),`oauth2.forward`);if(!r.ok)return r;let i=N5.deviceCode.issued.parse(await Z(e,r.clone().json(),`response.json`));return await Z(e,u5(e,{device:null,deviceCode:i.device_code,expiresIn:i.expires_in}),`DeviceRequest.create`),r}).post(`/oauth2/introspect`,sV({description:"Introspects a token (RFC 7662). The app authenticates with its client credentials, in the body or as HTTP Basic `Authorization`.",...F5}),hV(`form`,N5.introspect.form),e=>H5(e)).post(`/oauth2/introspection`,sV({deprecated:!0,description:"Introspects a token, as `POST /oauth2/introspect` does. Clients of the older package call this path.",...F5}),hV(`form`,N5.introspect.form),async e=>{let t=new URL(e.req.url);t.pathname=`/oauth2/introspect`;let n=new Request(t,e.req.raw);return await Z(e,U5(e,{body:await Z(e,n.clone().text(),`request.text`),request:n}),`oauth2.limitDiscovery`)||Z(e,e.var.auth.handler(n),`auth.handler`)}).post(`/oauth2/revoke`,sV({description:"Revokes an access or refresh token (RFC 7009). The app authenticates with its client credentials, in the body or as HTTP Basic `Authorization`.",responses:{200:{content:{"application/json":{schema:{description:`Empty: the token is revoked, or was already invalid (RFC 7009 §2.2).`}}},description:`The token is revoked.`},...P5,...mV([...dB,...EV.errors])},security:[{},{clientBasic:[]}],tags:[`OAuth`]}),hV(`form`,N5.revoke.form),e=>H5(e)).get(`/oauth2/userinfo`,sV({description:`Reads the token subject's claims (OIDC Core §5.3).`,responses:{200:{content:{"application/json":{schema:rV(N5.userinfo.response)}},description:`The issuer's UserInfo response.`},...P5},security:[{accessToken:[]}],tags:[`OAuth`]}),e=>H5(e)).get(`/oauth2/end-session`,sV(I5),_V(`query`,N5.endSession.query),async e=>V5(e,e.req.valid(`query`))).post(`/oauth2/end-session`,sV({...I5,responses:{...I5.responses,...mV(dB),303:{description:"Continues a form POST without the session cookie as `GET /oauth2/end-session` with the sealed parameters in `continuation`, which the browser sends with the cookie."}}}),_V(`form`,N5.endSession.form),async e=>V5(e,e.req.valid(`form`))).get(`/oauth2/jwks`,sV({description:`Reads the issuer's signing keys. A verifier may cache the response for 60 seconds, since a new key signs 5 minutes after its rotation.`,responses:gV({success:{description:`The JSON Web Key Set.`,schema:N5.jwks.response}}),tags:[`OAuth`]}),async e=>{let t=await Z(e,H5(e),`oauth2.forward`);return t.ok&&t.headers.set(`cache-control`,`public, max-age=60`),t}).on([`GET`,`POST`],[...L5],e=>H5(e));function B5(e){let{authorization:t,form:n}=e;if(t&&/^Basic +/i.test(t))try{return Tr(t)}catch{return}let[r,...i]=n.getAll(`client_id`).filter(e=>e.length>0),[a,...o]=n.getAll(`client_secret`).filter(e=>e.length>0);if(r&&a&&!i.length&&!o.length)return{clientId:r,clientSecret:a}}async function V5(e,t){let n=t.continuation===void 0?t:await Z(e,k5(t.continuation,{secret:U.SECRET}),`Logout.unseal`);if(!n)return X(e,new yR({issues:[{message:`Expired or invalid continuation. Send the logout request again`,path:[`continuation`]}]}));let r=n.id_token_hint;if(!r)return X(e,new yR({issues:[{message:`Required`,path:[`id_token_hint`]}]}));let i=await Z(e,pF($,{hint:r}),`SigningKey.hintKeys`),a=await Z(e,E5($,{clientId:n.client_id,hint:r,issuer:U.URL,jwks:i,postLogoutRedirectUri:n.post_logout_redirect_uri,state:n.state}),`Logout.check`);if(a instanceof eI)return X(e,a);let o=e.req.raw.headers,s=(await Z(e,e.var.auth.api.getSession({headers:o}),`auth.getSession`))?.session.id===a.sessionId;if(!s&&e.req.method===`POST`){let t=await Z(e,O5({client_id:n.client_id,id_token_hint:r,post_logout_redirect_uri:n.post_logout_redirect_uri,state:n.state},{secret:U.SECRET}),`Logout.seal`),i=new URL(`/oauth2/end-session`,U.URL);return i.searchParams.set(`continuation`,t),e.header(`cache-control`,`no-store`),e.redirect(i.href,303)}if(s){await Z(e,A5($,{sessionId:a.sessionId}),`Logout.revoke`);let t=await Z(e,e.var.auth.api.signOut({headers:o,returnHeaders:!0}),`auth.signOut`);await Z(e,D5($,{sessionId:a.sessionId}),`Logout.assertEnded`);for(let n of t.headers.getSetCookie())e.header(`set-cookie`,n,{append:!0});e.header(`set-cookie`,T2(),{append:!0})}return e.header(`cache-control`,`no-store`),a.redirect?e.redirect(a.redirect,302):e.json({signed_out:!0},200)}async function H5(e){let t=await Z(e,q5(e),`oauth2.withResource`),n=t.method===`POST`?await Z(e,t.clone().text(),`request.text`):void 0,r=n!==void 0&&t.headers.get(`content-type`)?.toLowerCase().includes(`application/x-www-form-urlencoded`)?new URLSearchParams(n):new URL(t.url).searchParams;return await Z(e,U5(e,{body:n,request:t}),`oauth2.limitDiscovery`)||(e.req.path===`/oauth2/authorize`&&r.getAll(`client_id`).length>1?X(e,new yR({issues:[{message:`Repeated parameter. Send it once`,path:[`client_id`]}]})):e.req.path===`/oauth2/authorize`&&await Z(e,K5(e,{query:r}),`oauth2.refuseKey`)||Z(e,e.var.auth.handler(t),`auth.handler`))}async function U5(e,t){let{body:n,request:r}=t,i=new URL(r.url);if(!R5.has(i.pathname))return;let a=[...i.searchParams.getAll(`client_id`),...W5(n),G5(r)].filter(e=>e!==void 0);if(a.some(DF)&&(await Z(e,OF($,{clientIds:a}),`Apps.stale`)).length!==0)return Z(e,EV(e,{limits:[{binding:`APP_DISCOVERY_LIMIT`,key:jV(e)}]}),`RateLimit.check`)}function W5(e){if(!e)return[];let t=new URLSearchParams(e),n=(()=>{try{let t=JSON.parse(e);if(typeof t!=`object`||!t)return[];let n=t.client_id;return typeof n==`string`?[n]:[]}catch{return[]}})(),r=t.getAll(`client_assertion`).flatMap(e=>{try{let[,t]=e.split(`.`),n=JSON.parse(new TextDecoder().decode(ve(t??``)));if(typeof n!=`object`||!n)return[];let{iss:r,sub:i}=n;return[r,i].filter(e=>typeof e==`string`)}catch{return[]}});return[...t.getAll(`client_id`),...n,...r]}function G5(e){let t=e.headers.get(`authorization`);if(t&&/^Basic +/i.test(t))try{return Tr(t).clientId}catch{return}}async function K5(e,t){let{query:n}=t;if(!n.has(`key_authorization`)&&!n.has(`challenge`))return;let r=n.get(`client_id`),i=n.get(`redirect_uri`);if(!r||!i||DF(r)&&!(await Z(e,e.var.auth.api.resolveOAuthClient({body:{client_id:r}}).catch(e=>{if(di(e))return{resolved:!1};throw e}),`auth.resolveOAuthClient`)).resolved)return;let a=await Z(e,SF($,{clientId:r}).catch(e=>{if(!(e instanceof hF))throw e}),`Apps.get`);if(!a||!a.redirectUris.includes(i))return;let o=ER(n),s=o instanceof eI?o:o&&TR({app:a,clientId:r,codeChallenge:n.get(`code_challenge`),key:o,query:n});if(!s)return;let c=new URL(i);c.searchParams.append(`error`,s.response.error),c.searchParams.append(`error_description`,s.response.error_description);let l=n.get(`state`);return l&&c.searchParams.append(`state`,l),c.searchParams.append(`iss`,U.URL),e.header(`cache-control`,`no-store`),e.redirect(c.href,302)}async function q5(e){let t=e.req.raw;if(e.req.path===`/oauth2/authorize`&&e.req.method===`GET`){let e=new URL(t.url);return e.searchParams.has(`resource`)||e.searchParams.set(`resource`,U.URL),e.search=DR(e.searchParams).toString(),new Request(e,t)}if(e.req.path===`/oauth2/authorize`&&e.req.method===`POST`&&e.req.header(`content-type`)?.split(`;`)[0]?.toLowerCase().includes(`application/x-www-form-urlencoded`)){let n=new URLSearchParams(await Z(e,e.req.text(),`request.text`));n.has(`resource`)||n.set(`resource`,U.URL);let r=new Headers(t.headers);return r.delete(`content-length`),r.set(`content-type`,`application/x-www-form-urlencoded`),new Request(t.url,{body:DR(n),headers:r,method:`POST`})}if(e.req.path===`/oauth2/token`&&e.req.method===`POST`){let n=new URLSearchParams(await Z(e,e.req.text(),`request.text`));n.has(`resource`)||n.set(`resource`,U.URL);let r=new Headers(t.headers);return r.delete(`content-length`),new Request(t.url,{body:n,headers:r,method:`POST`})}if(e.req.path===`/device/code`&&e.req.method===`POST`){let n=new URLSearchParams(await Z(e,e.req.text(),`request.text`));n.has(`resource`)||n.set(`resource`,U.URL),n.delete(`user_id`);let r=new Headers(t.headers);return r.delete(`content-length`),r.set(`content-type`,`application/x-www-form-urlencoded`),new Request(t.url,{body:n,headers:r,method:`POST`})}return t}var J5=class extends tI(`return_to_not_permitted`){name=`Provider.ReturnToNotPermittedError`;constructor(e){super({error_description:`Invalid return_to: ${e.origin} is not an origin of the app's redirect URIs. Return to a page on one of them, and pass the app's client_id.`,field:`return_to`,meta:{origin:e.origin}})}},Y5=class extends tI(`unknown_provider`){name=`Provider.UnknownError`;constructor(e){super({error_description:`Unknown provider: ${e.provider} is not offered. Request GET /v1/auth/providers for the providers offered.`,field:`provider`,meta:{provider:e.provider}})}},X5={google:`Google`};function Z5(e){return e.google?[{id:`google`,name:X5.google}]:[]}async function Q5(e,t){let{clientId:n,own:r}=t,i=new URL(t.returnTo,r);if(i.protocol!==`https:`&&i.protocol!==`http:`)return new J5({origin:i.origin});if(i.origin===r)return i.href;let[a]=n?await e.select({redirectUris:rP.redirectUris}).from(rP).where(sM(Y(rP.clientId,n),gM(rP.clientDiscoveryId))):[];return(a?.redirectUris??[]).flatMap(e=>{let t=URL.parse(e);return t&&(t.protocol===`https:`||t.protocol===`http:`)?[t.origin]:[]}).includes(i.origin)?i.href:new J5({origin:i.origin})}(function(e){e.errors=[J5]})(Q5||={});var $5=`tempo-id-grant`,e7=`tempo-id-sign-in-app`,t7=600,n7;(function(e){let t;(function(e){e.response=z({providers:jn(z({id:xn([`google`]).meta({description:"The provider's ID, which `GET /v1/auth/oauth/{provider}` takes.",examples:[`google`]}),name:R().meta({description:"The name to show, such as `Google`.",examples:[`Google`]})}).meta({description:`One provider Tempo ID offers.`})).readonly().meta({description:`The providers Tempo ID offers, in the order a page shows them. Empty when the deployment configures none.`})})})(t||=e.providers||={});let n;(function(e){e.param=z({provider:R().min(1).max(64).meta({description:"The ID of the provider, from `GET /v1/auth/providers`.",examples:[`google`]})}),e.query=z({client_id:R().min(1).max(255).optional().meta({description:"The app's client ID. A `return_to` on an origin of the app's redirect URIs requires it.",examples:[`client_01JZ8Q6W3N1R5B4V7C2X9K0M3T`]}),oauth_query:R().min(1).max(8192).optional().meta({description:`The signed authorization request in the sign-in page's query. The callback continues it, and redirects to the app.`,examples:[`client_id=tempo-cli&response_type=code&exp=1767225600&sig=4mLx2Wq9cH8t`]}),return_to:R().min(1).max(8448).refine(e=>URL.canParse(e,`https://id.invalid`),{message:`Set an absolute URL, or a path on Tempo ID`}).optional().meta({description:"The page that the browser returns to, signed in, on Tempo ID's origin or an origin of the app's redirect URIs. Defaults to the account page. A failed sign-in returns there with `error=access_denied`.",examples:[`https://app.example.com/welcome`]})})})(n||=e.signIn||={});let r;(function(e){e.param=n.param,e.query=n.query.pick({client_id:!0,return_to:!0})})(r||=e.failed||={});let i;(function(e){e.param=n.param,e.query=z({code:R().optional().meta({description:`The provider's authorization code.`,examples:[`4/0AVMBsJh7c2X9K0M3T`]}),error:R().optional().meta({description:`The provider's error code, for a refused sign-in.`,examples:[`access_denied`]}),state:R().optional().meta({description:`The state that the redirect to the provider sent.`,examples:[`Qm7rXcJ2bWv9Tk4LsN8pHd3F`]})})})(i||=e.callback||={})})(n7||={});var r7=new Fy().get(`/v1/auth/providers`,sV({description:`Lists the OAuth providers Tempo ID offers, for an app that shows its own sign-in buttons.`,responses:gV({success:{description:`The providers.`,schema:n7.providers.response}}),tags:[`Authenticate`]}),e=>e.json({providers:Z5({google:K8()})},200)).get(`/v1/auth/oauth/:provider`,sV({description:"Redirects the browser to the provider. The provider returns it to `/callback/{provider}`, which sets the session cookie, then continues `oauth_query` or redirects to `return_to`. The callback grants the key of `oauth_query` only when Tempo ID's own sign-in page sent the browser here.",responses:{302:{description:`Redirects the browser to the provider.`},...mV([..._V.errors,...Q5.errors,...EV.errors,Gz,Y5])},tags:[`Authenticate`]}),_V(`param`,n7.signIn.param),_V(`query`,n7.signIn.query),async e=>{let t=e.req.valid(`query`),n=Z5({google:K8()}).find(t=>t.id===e.req.valid(`param`).provider);if(!n)return X(e,new Y5({provider:e.req.valid(`param`).provider}));let r=jV(e),i=await Z(e,EV(e,{limits:[{binding:`SIGN_IN_IP_LIMIT`,key:r?`provider:${r}`:void 0}]}),`RateLimit.check`);if(i)return i;let a=await Z(e,Q5($,{clientId:t.client_id,own:new URL(U.URL).origin,returnTo:t.return_to??`/`}),`Provider.returnTo`);if(a instanceof eI)return X(e,a);let o=new URL(`/v1/auth/oauth/${n.id}/failed`,U.URL);o.searchParams.set(`return_to`,t.return_to??`/`),t.client_id&&o.searchParams.set(`client_id`,t.client_id);let s=await Z(e,e.var.auth.api.signInSocial({body:{callbackURL:a,disableRedirect:!0,errorCallbackURL:o.href,provider:n.id,...t.oauth_query?{oauth_query:t.oauth_query}:{}},headers:new Headers(e.req.raw.headers),returnHeaders:!0}),`auth.signInSocial`).catch(e=>{if(di(e)&&e.body?.error===`invalid_signature`)return new Gz;throw e});if(s instanceof eI)return X(e,s);for(let t of s.headers.getSetCookie())e.header(`set-cookie`,t,{append:!0});t.oauth_query&&e.req.header(`sec-fetch-site`)===`same-origin`?_B(e,$5,a4(new URLSearchParams(t.oauth_query)),{httpOnly:!0,maxAge:t7,path:`/`,prefix:`host`,sameSite:`Lax`,secure:!0}):vB(e,$5,{path:`/`,prefix:`host`,secure:!0});let c=t.oauth_query?new URLSearchParams(t.oauth_query).get(`client_id`):null;return c?_B(e,e7,c,{httpOnly:!0,maxAge:t7,path:`/`,prefix:`host`,sameSite:`Lax`,secure:!0}):vB(e,e7,{path:`/`,prefix:`host`,secure:!0}),e.header(`cache-control`,`private, no-store`),e.redirect(s.response.url??`/`,302)}).get(`/v1/auth/oauth/:provider/failed`,sV({description:"Redirects the browser from a failed provider sign-in to `return_to`, with `error=access_denied`. The code is the same for every cause, so it reveals neither the cause nor whether an account exists.",responses:{302:{description:"Redirects the browser to `return_to`."},...mV([..._V.errors,...Q5.errors])},tags:[`Authenticate`]}),_V(`param`,n7.failed.param),_V(`query`,n7.failed.query),async e=>{let t=e.req.valid(`query`),n=await Z(e,Q5($,{clientId:t.client_id,own:new URL(U.URL).origin,returnTo:t.return_to??`/login`}),`Provider.returnTo`);if(n instanceof eI)return X(e,n);let r=new URL(n);return r.searchParams.set(`error`,`access_denied`),e.redirect(r.href,302)}).get(`/callback/:provider`,sV({description:"Receives the provider's redirect, sets the session cookie, and redirects the browser to `return_to`, or continues the app's authorization. For a user with no Tempo Account in the realm of the sign-in, it creates one, as `POST /v1/auth/code/verify` does. A failure redirects to the failed route, or to the error page with `error=invalid_callback_request` if the browser holds no state for the callback.",responses:{302:{description:"Redirects the browser to `return_to`, to the app's redirect URI, to the failed route, or to the error page."},...mV([])},tags:[`Authenticate`]}),hV(`param`,n7.callback.param),hV(`query`,n7.callback.query),async e=>{let t=await Z(e,e.var.auth.handler(e.req.raw),`auth.handler`),n=t.headers.get(`location`);if(t.status!==302||!n)return t;let r=new URL(`/error`,U.URL),i=URL.parse(n,U.URL);if(i?.origin===r.origin&&i.pathname===r.pathname){r.searchParams.set(`error`,`invalid_callback_request`);let e=new Headers(t.headers);return e.set(`location`,r.href),new Response(null,{headers:e,status:302})}let a=t.headers.getSetCookie().map(e=>e.split(`;`,1)[0]).join(`; `),o=a?await Z(e,e.var.auth.api.getSession({headers:new Headers({cookie:a})}),`auth.getSession`).catch(t=>(KF(e,{error:t,message:`The provider sign-in created no first account, since its session failed to load.`}),null)):null;o&&await Z(e,J8(e,{clientId:hB(e,e7,`host`)??null,userId:o.user.id}),`FirstAccount.create`);let s=hB(e,$5,`host`),c=URL.parse(n,U.URL),l=s&&c&&a4(c.searchParams)===s?await Z(e,_4(e,{redirect:n,setCookie:t.headers.getSetCookie()}),`SignInConsent.afterSignIn`):n;if(!s&&l===n)return t;let u=new Headers(t.headers);return u.set(`location`,l),s&&u.append(`set-cookie`,te(`__Host-${$5}`,``,{httpOnly:!0,maxAge:0,path:`/`,sameSite:`Lax`,secure:!0})),new Response(null,{headers:u,status:302})}),i7=new Fy().route(`/`,v5).route(`/`,R4).route(`/`,i5).route(`/`,l5).route(`/`,g5).route(`/`,z5).route(`/`,r7),a7=new Fy().use(Qz).use(B2()).use(b5).use(Ky({referrerPolicy:`same-origin`})).use(eb()).use(`/.well-known/oauth-authorization-server`,P4).use(`/.well-known/openid-configuration`,P4).use(`/oauth2/introspect`,P4).use(`/oauth2/introspection`,P4).use(`/oauth2/jwks`,P4).use(`/oauth2/revoke`,P4).use(`/oauth2/token`,P4).use(`/oauth2/userinfo`,P4).use(`/v1/*`,N4).use(Ry([`/device/code`,`/oauth2/*`],Uy())).use(`/device/code`,pB).use(`/oauth2/*`,pB).use(`/v1/*`,pB).use(W8).route(`/`,i7).get(`/openapi.json`,sV({description:`Returns this OpenAPI document.`,responses:{200:{content:{"application/json":{schema:{type:`object`}}},description:`The OpenAPI 3.1 document.`},...mV([])},tags:[`Reference`]}),async e=>e.json(await Z(e,dV(a7),`OpenApi.document`),200)).get(`/docs`,sV({description:`Renders this OpenAPI document as an API reference.`,responses:{200:{content:{"text/html":{schema:{type:`string`}}},description:`The API reference page.`},...mV([])},tags:[`Reference`]}),e=>(e.header(`content-security-policy`,pV),e.html(fV))).all(`/:version{v\\d+}/*`,e=>X(e,new oI)).notFound(async e=>o7(e.req.path)?X(e,new oI):Z(e,e.env.pages(e),`page.render`)).onError(dI);function o7(e){if(s7.has(e))return!1;let t=e.split(`/`)[1]??``;return c7.has(t)||/^v\d+$/.test(t)}var s7=new Set([`/device`]),c7=new Set(a7.routes.flatMap(e=>{let t=e.path.split(`/`)[1]??``;return t&&t!==`*`&&!t.startsWith(`:`)?[t]:[]})),l7=new WeakSet;function u7(e){if(e instanceof Response)return e;let t;return t=e==null?new Response(null,{status:204}):typeof e==`string`?new Response(e,{headers:{"Content-Type":`text/html; charset=utf-8`}}):Response.json(e),l7.add(t),t}function d7(e){return Array.from(e,e=>({message:e.message,path:e.path?.map(e=>typeof e==`object`?e.key:e).join(`.`)}))}async function f7(e,t){let n=await e[`~standard`].validate(t);return n.issues?{ok:!1,issues:n.issues}:{ok:!0,value:n.value}}async function p7(e,t){let n={},r=[];if(e.params){let i=t.req.param(),a=await f7(e.params,i);a.ok?n.params=a.value:r.push({slot:`params`,issues:d7(a.issues)})}if(e.query){let i=new URL(t.req.url),a={};for(let[e,t]of i.searchParams)a[e]=t;let o=await f7(e.query,a);o.ok?n.query=o.value:r.push({slot:`query`,issues:d7(o.issues)})}if(e.body){let i;try{i=await t.req.json()}catch{return{ok:!1,response:Response.json({error:`Invalid JSON body`},{status:400})}}let a=await f7(e.body,i);a.ok?n.body=a.value:r.push({slot:`body`,issues:d7(a.issues)})}return r.length>0?{ok:!1,response:Response.json({error:`Validation failed`,issues:r},{status:400})}:{ok:!0,input:n}}function m7(...e){if(e.length===1)return e[0];let t=e.slice(0,-1),n=e[e.length-1];return(async e=>{let r=0,i=async()=>{if(r<t.length){let n=t[r++],a=await n(e,i);a instanceof Response&&(e.res=a)}else e.res=u7(await n(e))};return await i(),e.res})}(function(e){function t(e){return t=>(async n=>{let r=await p7(e,n);return r.ok?u7(await t(n,r.input)):r.response})}e.withValidator=t})(m7||={}),new TextEncoder,new TextDecoder(`utf-8`,{fatal:!0});function h7(e){return e}var g7=864e5,_7=h7(async e=>{let t=new Date;try{await b2.delete(vP).where(fM(vP.expiresAt,t)),await b2.delete($N).where(fM($N.expiresAt,t)),await b2.delete(xP).where(fM(xP.expiresAt,t)),await b2.delete(wP).where(fM(wP.expiresAt,t)),await b2.delete(rP).where(sM(_M(rP.clientDiscoveryId),fM(rP.updatedAt,new Date(t.getTime()-g7)),q`not exists (select 1 from ${cP} where ${cP.clientId} = ${rP.clientId})`,q`not exists (select 1 from ${bP} where ${bP.clientId} = ${rP.clientId})`))}catch(t){throw UF({error:t,fields:{cron:e.cron},message:`The cleanup cron failed.`}),t}}),v7=[`ratelimit`,`ratelimit-policy`,`retry-after`],y7=[`cf-connecting-ip`,`cf-ray`,`cf-worker`,`user-agent`],b7=yv(Oh),x7={fetch:(e,t,n)=>a7.fetch(e,{...t,pages:e=>S7(e,{env:t,ctx:n})},n),scheduled:(...e)=>Rv(e[1],()=>_7(...e))};async function S7(e,t){let{ctx:n,env:r}=t,i=T7(e.req.header(`cookie`)),a=new URL(e.req.url).origin,o,s,c=!1,l=async(t,o)=>{let l=new Request(t,o),u=new URL(l.url);if(u.origin!==a||!u.pathname.startsWith(`/v1/`))throw Error(`A page called a path outside the JSON API.`);i.size>0&&l.headers.set(`cookie`,E7(i));for(let t of y7){let n=e.req.header(t);n&&l.headers.set(t,n)}let d=await Z(e,Promise.resolve(a7.fetch(l,{...r,pages:()=>w7()},n)),`api`,`${l.method} ${new URL(l.url).pathname}`);for(let t of d.headers.getSetCookie())C7(i,{setCookie:t}),c?KF(e,{message:`A page set a cookie after its headers were sent.`}):e.header(`set-cookie`,t,{append:!0});return d.status===429&&(s??=d),d},u=await b7(e.req.raw,{context:{fetch:async(t,n)=>{o&&await Z(e,o.catch(()=>void 0),`api.wait`);let r=l(t,n);return o??=r,r},origin:a}});if(c=!0,e.header(`cache-control`,`private, no-store`),s&&u.status===200){for(let t of v7){let n=s.headers.get(t);n&&e.header(t,n)}return e.newResponse(u.body,{headers:u.headers,status:429})}return e.newResponse(u.body,u)}function C7(e,t){let[n,...r]=t.setCookie.split(`;`),i=n.indexOf(`=`),a=n.slice(0,i).trim(),o=n.slice(i+1).trim();r.some(e=>/^max-age=0$/i.test(e.trim()))||!o?e.delete(a):e.set(a,o)}function w7(){return Promise.resolve(new Response(null,{status:404}))}function T7(e){let t=new Map;for(let n of e?.split(`;`)??[]){let e=n.indexOf(`=`);e>0&&t.set(n.slice(0,e).trim(),n.slice(e+1).trim())}return t}function E7(e){return[...e].map(([e,t])=>`${e}=${t}`).join(`; `)}function D7(){let e=null;return async(t,n)=>{if(e)return e;let r=globalThis.__VITE_MANIFEST__;if(typeof r==`object`&&r)return e=r,e;let i=n?.ASSETS;if(!i||typeof i.fetch!=`function`)return null;let a=await i.fetch(new Request(new URL(`/.vite/manifest.json`,t.url).toString()));return a.ok?(e=await a.json(),e):null}}var O7={".avif":`image/avif`,".css":`text/css; charset=utf-8`,".gif":`image/gif`,".html":`text/html; charset=utf-8`,".ico":`image/x-icon`,".jpeg":`image/jpeg`,".jpg":`image/jpeg`,".js":`text/javascript; charset=utf-8`,".json":`application/json; charset=utf-8`,".mjs":`text/javascript; charset=utf-8`,".png":`image/png`,".svg":`image/svg+xml`,".txt":`text/plain; charset=utf-8`,".wasm":`application/wasm`,".webp":`image/webp`,".woff":`font/woff`,".woff2":`font/woff2`};function k7(e,t,n=`assets`,r=!1){if(![`GET`,`HEAD`].includes(e.method)||![200,206,304].includes(t.status))return t;let i=new URL(e.url).pathname,a=i.slice(i.lastIndexOf(`/`)+1),o=a.slice(a.lastIndexOf(`.`)).toLowerCase(),s=new Headers(t.headers);!s.has(`Content-Type`)&&O7[o]&&s.set(`Content-Type`,O7[o]);let c=s.get(`Cache-Control`),l=(c??``).toLowerCase().split(`,`).map(e=>e.trim()).sort().join(`,`)===`max-age=0,must-revalidate,public`,u=r&&i.startsWith(`/`+n.replace(/^\/+|\/+$/g,``)+`/`)&&o!==`.html`&&!(s.get(`Content-Type`)??``).toLowerCase().includes(`text/html`);return!s.has(`Set-Cookie`)&&u&&(!c||l)?s.set(`Cache-Control`,`public, max-age=31536000, immutable`):c||s.set(`Cache-Control`,`no-store`),new Response(t.body,{status:t.status,statusText:t.statusText,headers:s})}function A7(e,t=D7()){let n;return async(r,i,a)=>{let o=new URL(r.url).pathname;return![`GET`,`HEAD`].includes(r.method)||![200,206,304].includes(a.status)||!o.startsWith(`/`+(e??`assets`).replace(/^\/+|\/+$/g,``)+`/`)?k7(r,a,e):(n||=t(r,i).then(e=>new Set(Object.values(e??{}).flatMap(e=>Array.isArray(e?.immutableFiles)?e.immutableFiles:[])),()=>new Set),k7(r,a,e,(await n).has(o.slice(1))))}}function j7(e={}){let t=A7(e.assetsDir);return async(n,r,i)=>{if(i.status!==404||!r.ASSETS||n.method!==`GET`&&n.method!==`HEAD`)return i;let a=await r.ASSETS.fetch(new Request(n.url,{method:n.method,headers:n.headers}));if(a.status!==404)return t(n,r,a);let o=n.headers.get(`accept`)??``;if(e.serveSpaFallback&&o.includes(`text/html`)){let e=new URL(`/index.html`,n.url),t=await r.ASSETS.fetch(new Request(e,{method:n.method}));if(t.status===200){let e=new Response(t.body,{status:200,headers:t.headers});return e.headers.set(`Cache-Control`,`no-store`),e.headers.set(`Content-Type`,`text/html; charset=utf-8`),e}}else if(!e.serveSpaFallback&&e.notFound===`404-page`&&o.includes(`text/html`)&&(a.headers.get(`content-type`)??``).includes(`text/html`)){let e=new Response(a.body,a);return e.headers.set(`Cache-Control`,`no-store`),e}return i}}var M7={...x7,fetch(e,t,n){return Rv(t,async()=>N7(e,t,await x7.fetch(e,t,n)))}},N7=j7({assetsDir:`assets`,serveSpaFallback:!1,notFound:`none`}),P7=M7??{};export{P7 as default};
609
+ Nonce: 7f3a9c2e5b1d4f60`]}),client_id:R().meta({description:`The app's client ID.`,examples:[`tempo-cli`]}),code_challenge:R().meta({description:`The PKCE challenge: the base64url SHA-256 hash of the code verifier (RFC 7636 §4.2).`,examples:[`E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM`]}),code_challenge_method:bn(`S256`).meta({description:`The PKCE challenge method.`}),key_authorization:R().optional().meta({description:"A key authorization for the app's own key, as base64url JSON in the shape of `KeyAuthorizationRequest`. The request always shows the approval page, which signs the key, and `/oauth2/token` returns it beside the tokens. A key that breaks a rule returns to the redirect URI with the refusal.",examples:[`eyJhZGRyZXNzIjoiMHg4MWMwZjIyYmQxNzNjMTE1ZDE4ZWVlYTBmNmEzOGU5MzVlY2Y1MmZiIn0`]}),prompt:xn([`consent`,`login`,`none`,`select_account`]).optional().meta({description:`Whether the user signs in or consents again (OIDC Core §3.1.2.1). Absent to reuse the session and stored consent.`,examples:[`consent`]}),redirect_uri:En().meta({description:`One of the app's registered redirect URIs.`,examples:[`https://app.example/callback`]}),resource:En().optional().meta({description:`The API the access token is for (RFC 8707). Absent for Tempo ID's own origin.`,examples:[`https://id.tempo.xyz`]}),response_type:bn(`code`).meta({description:`The authorization code flow.`}),scope:R().meta({description:`Space-separated OAuth scopes.`,examples:[`openid profile email`]}),state:R().optional().meta({description:`An opaque value that the redirect returns to the app unchanged.`,examples:[`af0ifjsldkj`]})}),e.response=z({redirect:Dn().meta({description:"Whether the app sends the browser to `url`.",examples:[!0]}),url:R().meta({description:`Where the browser goes next: the sign-in page, the consent page, or the redirect URI with a code.`,examples:[`https://app.example/callback?code=SplxlOBeZQQYbYS6WxSbIA`]})}).meta({description:`The next step of the authorization, for a request that a script sends.`})})(r||=e.authorize||={});let i;(function(e){e.error=z({error:R().meta({description:"The RFC 6749 error code, such as `invalid_grant` or `invalid_client`.",examples:[`invalid_grant`]}),error_description:R().optional().meta({description:`The issuer's description of the error. Absent when the issuer sends none.`,examples:[`invalid code`]}),error_uri:En().optional().meta({description:`A page about the error. Absent when the issuer sends none.`,examples:[`https://example.com/docs/errors#invalid_grant`]}),request_id:R().optional().meta({description:"The request ID, which Tempo ID adds and `X-Request-Id` also carries.",examples:[`5b3e1f2a-8c4d-4e6f-9a0b-7c2d1e3f4a5b`]})}).meta({description:`The issuer's OAuth error response (RFC 6749 §5.2), passed through.`,id:`OAuthErrorResponse`}),e.form=z({client_id:R().optional().meta({description:"The app's client ID. Absent when the app authenticates with HTTP Basic `Authorization`.",examples:[`tempo-cli`]}),client_secret:R().optional().meta({description:`A confidential app's secret.`,examples:[`3bTm9qXc2Lr7WvN5kYp8Hs4Df6Ga1Je0`]}),code:R().optional().meta({description:"The authorization code to redeem, for the `authorization_code` grant.",examples:[`SplxlOBeZQQYbYS6WxSbIA`]}),code_verifier:R().optional().meta({description:"The PKCE verifier whose S256 hash is the authorization request's `code_challenge` (RFC 7636 §4.5).",examples:[`dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk`]}),device_code:R().optional().meta({description:`The device code, for the device code grant (RFC 8628 §3.4).`,examples:[`GmRhmhcxhwAzkoEqiMEg_DnyEysNkuNhszIySk9eS`]}),grant_type:xn([`authorization_code`,`client_credentials`,`refresh_token`,`urn:ietf:params:oauth:grant-type:device_code`]).meta({description:`The OAuth grant that the request redeems.`,examples:[`authorization_code`]}),redirect_uri:R().optional().meta({description:"The redirect URI of the authorization request, for the `authorization_code` grant.",examples:[`https://app.example/callback`]}),refresh_token:R().optional().meta({description:"The refresh token to redeem, for the `refresh_token` grant.",examples:[`yAjhKk7QnRZ3vD9pLm2Xc8Ws5Tf1Ub4N`]}),resource:En().optional().meta({description:`The API the access token is for (RFC 8707). Absent for Tempo ID's own origin.`,examples:[`https://id.tempo.xyz`]}),scope:R().optional().meta({description:`Space-separated OAuth scopes to request. Absent to keep the scopes of the grant.`,examples:[`openid profile email`]})}),e.response=Nn({access_token:R().meta({description:`The access token, an RS256 JWT for the requested resource.`,examples:[`eyJhbGciOiJSUzI1NiIsInR5cCI6ImF0K2p3dCJ9.e30.c2lnbmF0dXJl`]}),account:YL.account.optional().meta({description:"The Tempo Account that the key acts for. Present beside `key_authorization`.",examples:[`0x9a073914db0d149375ac2b7fbb72c68c0780fb5f`]}),expires_in:Sn().meta({description:`How long the access token lasts, in seconds.`,examples:[300]}),id_token:R().optional().meta({description:"The ID token, an RS256 JWT. Absent without the `openid` scope.",examples:[`eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.e30.c2lnbmF0dXJl`]}),key_authorization:YL.rpc.optional().meta({description:"The key authorization that the approval page signed, for the first redemption of a code whose request carried `key_authorization`. Absent for every other code, a refresh, and a key that expired."}),refresh_token:R().optional().meta({description:"The refresh token. Absent without the `offline_access` scope.",examples:[`yAjhKk7QnRZ3vD9pLm2Xc8Ws5Tf1Ub4N`]}),scope:R().optional().meta({description:`Space-separated OAuth scopes of the tokens.`,examples:[`openid profile email`]}),token_type:R().meta({description:`The type of the access token (RFC 6749 §7.1).`,examples:[`Bearer`]})}).meta({description:`The issuer's token response (RFC 6749 §5.1).`,id:`TokenResponse`})})(i||=e.token||={});let a;(function(e){e.form=z({client_id:R().optional().meta({description:"The app's client ID. The app holds the device grant. Absent when the app authenticates with HTTP Basic `Authorization`.",examples:[`tempo-cli`]}),client_secret:R().optional().meta({description:`A confidential app's secret.`,examples:[`3bTm9qXc2Lr7WvN5kYp8Hs4Df6Ga1Je0`]}),resource:En().optional().meta({description:`The API the access token is for (RFC 8707). Absent for Tempo ID's own origin.`,examples:[`https://id.tempo.xyz`]}),scope:R().optional().meta({description:`Space-separated OAuth scopes.`,examples:[`openid email offline_access`]})}),e.response=z({device_code:R().meta({description:"The secret code that the device polls `/oauth2/token` with (RFC 8628 §3.2). The device keeps it private.",examples:[`GmRhmhcxhwAzkoEqiMEg_DnyEysNkuNhszIySk9eS`]}),expires_in:Sn().meta({description:`Seconds until the device code and user code expire.`,examples:[600]}),interval:Sn().meta({description:`Seconds between polls.`,examples:[5]}),user_code:R().meta({description:`The code that the user enters on the verification page: eight consonants.`,examples:[`WDJBMJHT`]}),verification_uri:En().meta({description:`The page where the user enters the user code.`,examples:[`https://id.tempo.xyz/device`]}),verification_uri_complete:En().meta({description:`The verification page with the user code filled in, for a link or QR code.`,examples:[`https://id.tempo.xyz/device?user_code=WDJBMJHT`]})}).meta({description:`The issuer's device authorization response (RFC 8628 §3.2).`}),e.issued=z({device_code:R(),expires_in:Sn()})})(a||=e.deviceCode||={});let o;(function(e){e.form=z({client_id:i.form.shape.client_id,client_secret:i.form.shape.client_secret,token:R().meta({description:`The token to introspect.`,examples:[`yAjhKk7QnRZ3vD9pLm2Xc8Ws5Tf1Ub4N`]}),token_type_hint:xn([`access_token`,`refresh_token`]).optional().meta({description:"The type of `token`, which helps the issuer find it (RFC 7662 §2.1).",examples:[`refresh_token`]})}),e.response=Nn({active:Dn().meta({description:`Whether the token is active. An inactive token has no other members.`,examples:[!0]}),client_id:R().optional().meta({description:`The client ID of the app that the token belongs to.`,examples:[`tempo-cli`]}),exp:Sn().optional().meta({description:`When the token expires, in Unix seconds.`,examples:[1792076100]}),iat:Sn().optional().meta({description:`When the issuer issued the token, in Unix seconds.`,examples:[1792075800]}),iss:R().optional().meta({description:`The issuer's identifier.`,examples:[`https://id.tempo.xyz`]}),scope:R().optional().meta({description:`Space-separated OAuth scopes of the token.`,examples:[`openid profile email`]}),sub:R().optional().meta({description:`The user ID of the token's subject.`,examples:[`user_01JZ8Q6W3N1R5B4V7C2X9K0M3T`]})}).meta({description:`The issuer's introspection response (RFC 7662 §2.2).`,id:`IntrospectionResponse`})})(o||=e.introspect||={});let s;(function(e){e.form=z({client_id:i.form.shape.client_id,client_secret:i.form.shape.client_secret,token:R().meta({description:`The access or refresh token to revoke.`,examples:[`yAjhKk7QnRZ3vD9pLm2Xc8Ws5Tf1Ub4N`]}),token_type_hint:o.form.shape.token_type_hint})})(s||=e.revoke||={});let c;(function(e){e.response=Nn({email:R().optional().meta({description:"The user's email address. Absent without the `email` scope.",examples:[`ada@example.com`]}),email_verified:Dn().optional().meta({description:"Whether the issuer verified the email address. Absent without the `email` scope.",examples:[!0]}),sub:R().meta({description:`The user ID.`,examples:[`user_01JZ8Q6W3N1R5B4V7C2X9K0M3T`]})}).meta({description:`The issuer's UserInfo response (OIDC Core §5.3.2).`,id:`UserInfoResponse`})})(c||=e.userinfo||={});let l;(function(e){e.form=(e.query=z({client_id:R().optional().meta({description:"The app's client ID. Absent when `id_token_hint` names the app.",examples:[`tempo-cli`]}),continuation:R().optional().meta({description:`The sealed parameters of a form POST that carried no session cookie, which its 303 sends here. Absent otherwise.`,examples:[`a3f1c2…`]}),id_token_hint:R().optional().meta({description:"An ID token that Tempo ID issued to the app, which names the session to end. It may be expired. Required without `continuation`.",examples:[`eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.e30.c2lnbmF0dXJl`]}),post_logout_redirect_uri:En().optional().meta({description:`Where the browser goes after sign-out: one of the app's registered post-logout redirect URIs.`,examples:[`https://app.example/signed-out`]}),state:r.query.shape.state})).omit({continuation:!0}).extend({id_token_hint:R().meta({description:`An ID token that Tempo ID issued to the app, which names the session to end. It may be expired.`,examples:[`eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.e30.c2lnbmF0dXJl`]})}),e.response=z({signed_out:bn(!0).meta({description:`The browser holds no session that the hint names, since it ended or never held one.`})})})(l||=e.endSession||={});let u;(function(e){e.response=z({keys:jn(Nn({alg:R().optional().meta({description:`The algorithm that the key signs with.`,examples:[`RS256`]}),kid:R().optional().meta({description:"The key ID, which matches the `kid` header of a token that the key signs.",examples:[`Qq0BN2lPx8VzTRsaGgMjc5HbEFKY4Wty`]}),kty:R().meta({description:`The key family (RFC 7518 §6.1).`,examples:[`RSA`]})})).meta({description:`The issuer's public signing keys, with the members of each key that RFC 7517 defines.`})}).meta({description:`The issuer's JSON Web Key Set (RFC 7517 §5).`,id:`JsonWebKeySet`})})(u||=e.jwks||={})})(N5||={});var P5={...mV([]),400:{content:{"application/json":{schema:rV(N5.token.error)}},description:`The issuer's refusal, passed through.`},401:{content:{"application/json":{schema:rV(N5.token.error)}},description:`The issuer's refusal of the client or token, passed through.`}},F5={responses:{200:{content:{"application/json":{schema:rV(N5.introspect.response)}},description:`The issuer's introspection response.`},...P5,...mV([...dB,...EV.errors])},security:[{},{clientBasic:[]}],tags:[`OAuth`]},I5={description:`Signs the browser out (OpenID Connect RP-Initiated Logout) when it holds the session that the app's ID token names: revokes the refresh tokens that apps received through that session, ends it, and clears its cookie and the account step's selections. Any other session stays signed in. Redirects the browser to the app's post-logout redirect URI.`,responses:{302:{description:"Redirects the browser to the app's post-logout redirect URI, with `state`."},...gV({errors:[..._V.errors,...E5.errors],success:{description:"The browser is signed out of the session that the hint names, for a request without `post_logout_redirect_uri`.",schema:N5.endSession.response}})},tags:[`OAuth`]},L5=[`/.well-known/oauth-authorization-server`,`/.well-known/openid-configuration`,`/oauth2/authorize`,`/oauth2/introspect`,`/oauth2/jwks`,`/oauth2/revoke`,`/oauth2/token`,`/oauth2/userinfo`],R5=new Set([`/device/code`,`/oauth2/authorize`,`/oauth2/introspect`,`/oauth2/revoke`,`/oauth2/token`]),z5=new Fy().get(`/.well-known/openid-configuration`,sV({description:`Reads the issuer's OpenID Connect discovery document.`,responses:gV({success:{description:`The discovery document.`,schema:N5.openidConfiguration.response}}),tags:[`OAuth`]}),e=>H5(e)).get(`/.well-known/oauth-authorization-server`,sV({description:`Reads the issuer's authorization server metadata.`,responses:gV({success:{description:`The metadata.`,schema:N5.oauthAuthorizationServer.response}}),tags:[`OAuth`]}),e=>H5(e)).get(`/oauth2/authorize`,sV({description:`Starts an authorization. A signed-out browser goes to the sign-in page, and a signed-in one to the consent page or to the redirect URI with a code.`,responses:{200:{content:{"application/json":{schema:rV(N5.authorize.response)}},description:`The next step, for a request that a script sends.`},302:{description:"Redirects the browser to the sign-in page, the consent page, or the redirect URI. A refused `key_authorization` returns to the redirect URI with `error` and `error_description`. An unknown or disabled app, or an unregistered redirect URI, redirects to the error page."},...P5,...mV(EV.errors)},tags:[`OAuth`]}),hV(`query`,N5.authorize.query),e=>H5(e)).post(`/oauth2/token`,sV({description:`Redeems an authorization code, a refresh token, a device code, or client credentials for tokens.`,responses:{200:{content:{"application/json":{schema:rV(N5.token.response)}},description:`The tokens.`},...P5,...mV([...dB,...EV.errors])},security:[{},{clientBasic:[]}],tags:[`OAuth`]}),hV(`form`,N5.token.form),async e=>{let t=await Z(e,EV(e,{limits:[{binding:`TOKEN_LIMIT`,key:jV(e)}]}),`RateLimit.check`);if(t)return t;let n=new URLSearchParams(await Z(e,e.req.text(),`request.text`)),r=B5({authorization:e.req.header(`authorization`),form:n}),i=r?await Z(e,yF($,r),`Apps.authenticate`):!1;return await Z(e,EV(e,{limits:[{binding:`TOKEN_APP_LIMIT`,key:i?r?.clientId:void 0}]}),`RateLimit.check`)||H5(e)}).post(`/device/code`,sV({description:"Starts the device grant (RFC 8628 §3.1) for an app that holds it. The user approves the user code on the verification page, and the device redeems the device code at `/oauth2/token`. The device code binds to the user who approves it.",responses:{200:{content:{"application/json":{schema:rV(N5.deviceCode.response)}},description:`The device code.`},...P5,...mV([...dB,...EV.errors])},security:[{},{clientBasic:[]}],tags:[`OAuth`]}),hV(`form`,N5.deviceCode.form),async e=>{let t=jV(e),n=await Z(e,EV(e,{limits:[{binding:`DEVICE_LIMIT`,key:t===void 0?void 0:`${t}:form`}]}),`RateLimit.check`);if(n)return n;let r=await Z(e,H5(e),`oauth2.forward`);if(!r.ok)return r;let i=N5.deviceCode.issued.parse(await Z(e,r.clone().json(),`response.json`));return await Z(e,u5(e,{device:null,deviceCode:i.device_code,expiresIn:i.expires_in}),`DeviceRequest.create`),r}).post(`/oauth2/introspect`,sV({description:"Introspects a token (RFC 7662). The app authenticates with its client credentials, in the body or as HTTP Basic `Authorization`.",...F5}),hV(`form`,N5.introspect.form),e=>H5(e)).post(`/oauth2/introspection`,sV({deprecated:!0,description:"Introspects a token, as `POST /oauth2/introspect` does. Clients of the older package call this path.",...F5}),hV(`form`,N5.introspect.form),async e=>{let t=new URL(e.req.url);t.pathname=`/oauth2/introspect`;let n=new Request(t,e.req.raw);return await Z(e,U5(e,{body:await Z(e,n.clone().text(),`request.text`),request:n}),`oauth2.limitDiscovery`)||Z(e,e.var.auth.handler(n),`auth.handler`)}).post(`/oauth2/revoke`,sV({description:"Revokes an access or refresh token (RFC 7009). The app authenticates with its client credentials, in the body or as HTTP Basic `Authorization`.",responses:{200:{content:{"application/json":{schema:{description:`Empty: the token is revoked, or was already invalid (RFC 7009 §2.2).`}}},description:`The token is revoked.`},...P5,...mV([...dB,...EV.errors])},security:[{},{clientBasic:[]}],tags:[`OAuth`]}),hV(`form`,N5.revoke.form),e=>H5(e)).get(`/oauth2/userinfo`,sV({description:`Reads the token subject's claims (OIDC Core §5.3).`,responses:{200:{content:{"application/json":{schema:rV(N5.userinfo.response)}},description:`The issuer's UserInfo response.`},...P5},security:[{accessToken:[]}],tags:[`OAuth`]}),e=>H5(e)).get(`/oauth2/end-session`,sV(I5),_V(`query`,N5.endSession.query),async e=>V5(e,e.req.valid(`query`))).post(`/oauth2/end-session`,sV({...I5,responses:{...I5.responses,...mV(dB),303:{description:"Continues a form POST without the session cookie as `GET /oauth2/end-session` with the sealed parameters in `continuation`, which the browser sends with the cookie."}}}),_V(`form`,N5.endSession.form),async e=>V5(e,e.req.valid(`form`))).get(`/oauth2/jwks`,sV({description:`Reads the issuer's signing keys. A verifier may cache the response for 60 seconds, since a new key signs 5 minutes after its rotation.`,responses:gV({success:{description:`The JSON Web Key Set.`,schema:N5.jwks.response}}),tags:[`OAuth`]}),async e=>{let t=await Z(e,H5(e),`oauth2.forward`);if(!t.ok)return t;let n=N5.jwks.response.safeParse(await Z(e,t.clone().json(),`response.json`));return n.success&&n.data.keys.length>0&&t.headers.set(`cache-control`,`public, max-age=60`),t}).on([`GET`,`POST`],[...L5],e=>H5(e));function B5(e){let{authorization:t,form:n}=e;if(t&&/^Basic +/i.test(t))try{return Tr(t)}catch{return}let[r,...i]=n.getAll(`client_id`).filter(e=>e.length>0),[a,...o]=n.getAll(`client_secret`).filter(e=>e.length>0);if(r&&a&&!i.length&&!o.length)return{clientId:r,clientSecret:a}}async function V5(e,t){let n=t.continuation===void 0?t:await Z(e,k5(t.continuation,{secret:U.SECRET}),`Logout.unseal`);if(!n)return X(e,new yR({issues:[{message:`Expired or invalid continuation. Send the logout request again`,path:[`continuation`]}]}));let r=n.id_token_hint;if(!r)return X(e,new yR({issues:[{message:`Required`,path:[`id_token_hint`]}]}));let i=await Z(e,pF($,{hint:r}),`SigningKey.hintKeys`),a=await Z(e,E5($,{clientId:n.client_id,hint:r,issuer:U.URL,jwks:i,postLogoutRedirectUri:n.post_logout_redirect_uri,state:n.state}),`Logout.check`);if(a instanceof eI)return X(e,a);let o=e.req.raw.headers,s=(await Z(e,e.var.auth.api.getSession({headers:o}),`auth.getSession`))?.session.id===a.sessionId;if(!s&&e.req.method===`POST`){let t=await Z(e,O5({client_id:n.client_id,id_token_hint:r,post_logout_redirect_uri:n.post_logout_redirect_uri,state:n.state},{secret:U.SECRET}),`Logout.seal`),i=new URL(`/oauth2/end-session`,U.URL);return i.searchParams.set(`continuation`,t),e.header(`cache-control`,`no-store`),e.redirect(i.href,303)}if(s){await Z(e,A5($,{sessionId:a.sessionId}),`Logout.revoke`);let t=await Z(e,e.var.auth.api.signOut({headers:o,returnHeaders:!0}),`auth.signOut`);await Z(e,D5($,{sessionId:a.sessionId}),`Logout.assertEnded`);for(let n of t.headers.getSetCookie())e.header(`set-cookie`,n,{append:!0});e.header(`set-cookie`,T2(),{append:!0})}return e.header(`cache-control`,`no-store`),a.redirect?e.redirect(a.redirect,302):e.json({signed_out:!0},200)}async function H5(e){let t=await Z(e,q5(e),`oauth2.withResource`),n=t.method===`POST`?await Z(e,t.clone().text(),`request.text`):void 0,r=n!==void 0&&t.headers.get(`content-type`)?.toLowerCase().includes(`application/x-www-form-urlencoded`)?new URLSearchParams(n):new URL(t.url).searchParams;return await Z(e,U5(e,{body:n,request:t}),`oauth2.limitDiscovery`)||(e.req.path===`/oauth2/authorize`&&r.getAll(`client_id`).length>1?X(e,new yR({issues:[{message:`Repeated parameter. Send it once`,path:[`client_id`]}]})):e.req.path===`/oauth2/authorize`&&await Z(e,K5(e,{query:r}),`oauth2.refuseKey`)||Z(e,e.var.auth.handler(t),`auth.handler`))}async function U5(e,t){let{body:n,request:r}=t,i=new URL(r.url);if(!R5.has(i.pathname))return;let a=[...i.searchParams.getAll(`client_id`),...W5(n),G5(r)].filter(e=>e!==void 0);if(a.some(DF)&&(await Z(e,OF($,{clientIds:a}),`Apps.stale`)).length!==0)return Z(e,EV(e,{limits:[{binding:`APP_DISCOVERY_LIMIT`,key:jV(e)}]}),`RateLimit.check`)}function W5(e){if(!e)return[];let t=new URLSearchParams(e),n=(()=>{try{let t=JSON.parse(e);if(typeof t!=`object`||!t)return[];let n=t.client_id;return typeof n==`string`?[n]:[]}catch{return[]}})(),r=t.getAll(`client_assertion`).flatMap(e=>{try{let[,t]=e.split(`.`),n=JSON.parse(new TextDecoder().decode(ve(t??``)));if(typeof n!=`object`||!n)return[];let{iss:r,sub:i}=n;return[r,i].filter(e=>typeof e==`string`)}catch{return[]}});return[...t.getAll(`client_id`),...n,...r]}function G5(e){let t=e.headers.get(`authorization`);if(t&&/^Basic +/i.test(t))try{return Tr(t).clientId}catch{return}}async function K5(e,t){let{query:n}=t;if(!n.has(`key_authorization`)&&!n.has(`challenge`))return;let r=n.get(`client_id`),i=n.get(`redirect_uri`);if(!r||!i||DF(r)&&!(await Z(e,e.var.auth.api.resolveOAuthClient({body:{client_id:r}}).catch(e=>{if(di(e))return{resolved:!1};throw e}),`auth.resolveOAuthClient`)).resolved)return;let a=await Z(e,SF($,{clientId:r}).catch(e=>{if(!(e instanceof hF))throw e}),`Apps.get`);if(!a||!a.redirectUris.includes(i))return;let o=ER(n),s=o instanceof eI?o:o&&TR({app:a,clientId:r,codeChallenge:n.get(`code_challenge`),key:o,query:n});if(!s)return;let c=new URL(i);c.searchParams.append(`error`,s.response.error),c.searchParams.append(`error_description`,s.response.error_description);let l=n.get(`state`);return l&&c.searchParams.append(`state`,l),c.searchParams.append(`iss`,U.URL),e.header(`cache-control`,`no-store`),e.redirect(c.href,302)}async function q5(e){let t=e.req.raw;if(e.req.path===`/oauth2/authorize`&&e.req.method===`GET`){let e=new URL(t.url);return e.searchParams.has(`resource`)||e.searchParams.set(`resource`,U.URL),e.search=DR(e.searchParams).toString(),new Request(e,t)}if(e.req.path===`/oauth2/authorize`&&e.req.method===`POST`&&e.req.header(`content-type`)?.split(`;`)[0]?.toLowerCase().includes(`application/x-www-form-urlencoded`)){let n=new URLSearchParams(await Z(e,e.req.text(),`request.text`));n.has(`resource`)||n.set(`resource`,U.URL);let r=new Headers(t.headers);return r.delete(`content-length`),r.set(`content-type`,`application/x-www-form-urlencoded`),new Request(t.url,{body:DR(n),headers:r,method:`POST`})}if(e.req.path===`/oauth2/token`&&e.req.method===`POST`){let n=new URLSearchParams(await Z(e,e.req.text(),`request.text`));n.has(`resource`)||n.set(`resource`,U.URL);let r=new Headers(t.headers);return r.delete(`content-length`),new Request(t.url,{body:n,headers:r,method:`POST`})}if(e.req.path===`/device/code`&&e.req.method===`POST`){let n=new URLSearchParams(await Z(e,e.req.text(),`request.text`));n.has(`resource`)||n.set(`resource`,U.URL),n.delete(`user_id`);let r=new Headers(t.headers);return r.delete(`content-length`),r.set(`content-type`,`application/x-www-form-urlencoded`),new Request(t.url,{body:n,headers:r,method:`POST`})}return t}var J5=class extends tI(`return_to_not_permitted`){name=`Provider.ReturnToNotPermittedError`;constructor(e){super({error_description:`Invalid return_to: ${e.origin} is not an origin of the app's redirect URIs. Return to a page on one of them, and pass the app's client_id.`,field:`return_to`,meta:{origin:e.origin}})}},Y5=class extends tI(`unknown_provider`){name=`Provider.UnknownError`;constructor(e){super({error_description:`Unknown provider: ${e.provider} is not offered. Request GET /v1/auth/providers for the providers offered.`,field:`provider`,meta:{provider:e.provider}})}},X5={google:`Google`};function Z5(e){return e.google?[{id:`google`,name:X5.google}]:[]}async function Q5(e,t){let{clientId:n,own:r}=t,i=new URL(t.returnTo,r);if(i.protocol!==`https:`&&i.protocol!==`http:`)return new J5({origin:i.origin});if(i.origin===r)return i.href;let[a]=n?await e.select({redirectUris:rP.redirectUris}).from(rP).where(sM(Y(rP.clientId,n),gM(rP.clientDiscoveryId))):[];return(a?.redirectUris??[]).flatMap(e=>{let t=URL.parse(e);return t&&(t.protocol===`https:`||t.protocol===`http:`)?[t.origin]:[]}).includes(i.origin)?i.href:new J5({origin:i.origin})}(function(e){e.errors=[J5]})(Q5||={});var $5=`tempo-id-grant`,e7=`tempo-id-sign-in-app`,t7=600,n7;(function(e){let t;(function(e){e.response=z({providers:jn(z({id:xn([`google`]).meta({description:"The provider's ID, which `GET /v1/auth/oauth/{provider}` takes.",examples:[`google`]}),name:R().meta({description:"The name to show, such as `Google`.",examples:[`Google`]})}).meta({description:`One provider Tempo ID offers.`})).readonly().meta({description:`The providers Tempo ID offers, in the order a page shows them. Empty when the deployment configures none.`})})})(t||=e.providers||={});let n;(function(e){e.param=z({provider:R().min(1).max(64).meta({description:"The ID of the provider, from `GET /v1/auth/providers`.",examples:[`google`]})}),e.query=z({client_id:R().min(1).max(255).optional().meta({description:"The app's client ID. A `return_to` on an origin of the app's redirect URIs requires it.",examples:[`client_01JZ8Q6W3N1R5B4V7C2X9K0M3T`]}),oauth_query:R().min(1).max(8192).optional().meta({description:`The signed authorization request in the sign-in page's query. The callback continues it, and redirects to the app.`,examples:[`client_id=tempo-cli&response_type=code&exp=1767225600&sig=4mLx2Wq9cH8t`]}),return_to:R().min(1).max(8448).refine(e=>URL.canParse(e,`https://id.invalid`),{message:`Set an absolute URL, or a path on Tempo ID`}).optional().meta({description:"The page that the browser returns to, signed in, on Tempo ID's origin or an origin of the app's redirect URIs. Defaults to the account page. A failed sign-in returns there with `error=access_denied`.",examples:[`https://app.example.com/welcome`]})})})(n||=e.signIn||={});let r;(function(e){e.param=n.param,e.query=n.query.pick({client_id:!0,return_to:!0})})(r||=e.failed||={});let i;(function(e){e.param=n.param,e.query=z({code:R().optional().meta({description:`The provider's authorization code.`,examples:[`4/0AVMBsJh7c2X9K0M3T`]}),error:R().optional().meta({description:`The provider's error code, for a refused sign-in.`,examples:[`access_denied`]}),state:R().optional().meta({description:`The state that the redirect to the provider sent.`,examples:[`Qm7rXcJ2bWv9Tk4LsN8pHd3F`]})})})(i||=e.callback||={})})(n7||={});var r7=new Fy().get(`/v1/auth/providers`,sV({description:`Lists the OAuth providers Tempo ID offers, for an app that shows its own sign-in buttons.`,responses:gV({success:{description:`The providers.`,schema:n7.providers.response}}),tags:[`Authenticate`]}),e=>e.json({providers:Z5({google:K8()})},200)).get(`/v1/auth/oauth/:provider`,sV({description:"Redirects the browser to the provider. The provider returns it to `/callback/{provider}`, which sets the session cookie, then continues `oauth_query` or redirects to `return_to`. The callback grants the key of `oauth_query` only when Tempo ID's own sign-in page sent the browser here.",responses:{302:{description:`Redirects the browser to the provider.`},...mV([..._V.errors,...Q5.errors,...EV.errors,Gz,Y5])},tags:[`Authenticate`]}),_V(`param`,n7.signIn.param),_V(`query`,n7.signIn.query),async e=>{let t=e.req.valid(`query`),n=Z5({google:K8()}).find(t=>t.id===e.req.valid(`param`).provider);if(!n)return X(e,new Y5({provider:e.req.valid(`param`).provider}));let r=jV(e),i=await Z(e,EV(e,{limits:[{binding:`SIGN_IN_IP_LIMIT`,key:r?`provider:${r}`:void 0}]}),`RateLimit.check`);if(i)return i;let a=await Z(e,Q5($,{clientId:t.client_id,own:new URL(U.URL).origin,returnTo:t.return_to??`/`}),`Provider.returnTo`);if(a instanceof eI)return X(e,a);let o=new URL(`/v1/auth/oauth/${n.id}/failed`,U.URL);o.searchParams.set(`return_to`,t.return_to??`/`),t.client_id&&o.searchParams.set(`client_id`,t.client_id);let s=await Z(e,e.var.auth.api.signInSocial({body:{callbackURL:a,disableRedirect:!0,errorCallbackURL:o.href,provider:n.id,...t.oauth_query?{oauth_query:t.oauth_query}:{}},headers:new Headers(e.req.raw.headers),returnHeaders:!0}),`auth.signInSocial`).catch(e=>{if(di(e)&&e.body?.error===`invalid_signature`)return new Gz;throw e});if(s instanceof eI)return X(e,s);for(let t of s.headers.getSetCookie())e.header(`set-cookie`,t,{append:!0});t.oauth_query&&e.req.header(`sec-fetch-site`)===`same-origin`?_B(e,$5,a4(new URLSearchParams(t.oauth_query)),{httpOnly:!0,maxAge:t7,path:`/`,prefix:`host`,sameSite:`Lax`,secure:!0}):vB(e,$5,{path:`/`,prefix:`host`,secure:!0});let c=t.oauth_query?new URLSearchParams(t.oauth_query).get(`client_id`):null;return c?_B(e,e7,c,{httpOnly:!0,maxAge:t7,path:`/`,prefix:`host`,sameSite:`Lax`,secure:!0}):vB(e,e7,{path:`/`,prefix:`host`,secure:!0}),e.header(`cache-control`,`private, no-store`),e.redirect(s.response.url??`/`,302)}).get(`/v1/auth/oauth/:provider/failed`,sV({description:"Redirects the browser from a failed provider sign-in to `return_to`, with `error=access_denied`. The code is the same for every cause, so it reveals neither the cause nor whether an account exists.",responses:{302:{description:"Redirects the browser to `return_to`."},...mV([..._V.errors,...Q5.errors])},tags:[`Authenticate`]}),_V(`param`,n7.failed.param),_V(`query`,n7.failed.query),async e=>{let t=e.req.valid(`query`),n=await Z(e,Q5($,{clientId:t.client_id,own:new URL(U.URL).origin,returnTo:t.return_to??`/login`}),`Provider.returnTo`);if(n instanceof eI)return X(e,n);let r=new URL(n);return r.searchParams.set(`error`,`access_denied`),e.redirect(r.href,302)}).get(`/callback/:provider`,sV({description:"Receives the provider's redirect, sets the session cookie, and redirects the browser to `return_to`, or continues the app's authorization. For a user with no Tempo Account in the realm of the sign-in, it creates one, as `POST /v1/auth/code/verify` does. A failure redirects to the failed route, or to the error page with `error=invalid_callback_request` if the browser holds no state for the callback.",responses:{302:{description:"Redirects the browser to `return_to`, to the app's redirect URI, to the failed route, or to the error page."},...mV([])},tags:[`Authenticate`]}),hV(`param`,n7.callback.param),hV(`query`,n7.callback.query),async e=>{let t=await Z(e,e.var.auth.handler(e.req.raw),`auth.handler`),n=t.headers.get(`location`);if(t.status!==302||!n)return t;let r=new URL(`/error`,U.URL),i=URL.parse(n,U.URL);if(i?.origin===r.origin&&i.pathname===r.pathname){r.searchParams.set(`error`,`invalid_callback_request`);let e=new Headers(t.headers);return e.set(`location`,r.href),new Response(null,{headers:e,status:302})}let a=t.headers.getSetCookie().map(e=>e.split(`;`,1)[0]).join(`; `),o=a?await Z(e,e.var.auth.api.getSession({headers:new Headers({cookie:a})}),`auth.getSession`).catch(t=>(KF(e,{error:t,message:`The provider sign-in created no first account, since its session failed to load.`}),null)):null;o&&await Z(e,J8(e,{clientId:hB(e,e7,`host`)??null,userId:o.user.id}),`FirstAccount.create`);let s=hB(e,$5,`host`),c=URL.parse(n,U.URL),l=s&&c&&a4(c.searchParams)===s?await Z(e,_4(e,{redirect:n,setCookie:t.headers.getSetCookie()}),`SignInConsent.afterSignIn`):n;if(!s&&l===n)return t;let u=new Headers(t.headers);return u.set(`location`,l),s&&u.append(`set-cookie`,te(`__Host-${$5}`,``,{httpOnly:!0,maxAge:0,path:`/`,sameSite:`Lax`,secure:!0})),new Response(null,{headers:u,status:302})}),i7=new Fy().route(`/`,v5).route(`/`,R4).route(`/`,i5).route(`/`,l5).route(`/`,g5).route(`/`,z5).route(`/`,r7),a7=new Fy().use(Qz).use(B2()).use(b5).use(Ky({referrerPolicy:`same-origin`})).use(eb()).use(`/.well-known/oauth-authorization-server`,P4).use(`/.well-known/openid-configuration`,P4).use(`/oauth2/introspect`,P4).use(`/oauth2/introspection`,P4).use(`/oauth2/jwks`,P4).use(`/oauth2/revoke`,P4).use(`/oauth2/token`,P4).use(`/oauth2/userinfo`,P4).use(`/v1/*`,N4).use(Ry([`/device/code`,`/oauth2/*`],Uy())).use(`/device/code`,pB).use(`/oauth2/*`,pB).use(`/v1/*`,pB).use(W8).route(`/`,i7).get(`/openapi.json`,sV({description:`Returns this OpenAPI document.`,responses:{200:{content:{"application/json":{schema:{type:`object`}}},description:`The OpenAPI 3.1 document.`},...mV([])},tags:[`Reference`]}),async e=>e.json(await Z(e,dV(a7),`OpenApi.document`),200)).get(`/docs`,sV({description:`Renders this OpenAPI document as an API reference.`,responses:{200:{content:{"text/html":{schema:{type:`string`}}},description:`The API reference page.`},...mV([])},tags:[`Reference`]}),e=>(e.header(`content-security-policy`,pV),e.html(fV))).all(`/:version{v\\d+}/*`,e=>X(e,new oI)).notFound(async e=>o7(e.req.path)?X(e,new oI):Z(e,e.env.pages(e),`page.render`)).onError(dI);function o7(e){if(s7.has(e))return!1;let t=e.split(`/`)[1]??``;return c7.has(t)||/^v\d+$/.test(t)}var s7=new Set([`/device`]),c7=new Set(a7.routes.flatMap(e=>{let t=e.path.split(`/`)[1]??``;return t&&t!==`*`&&!t.startsWith(`:`)?[t]:[]})),l7=new WeakSet;function u7(e){if(e instanceof Response)return e;let t;return t=e==null?new Response(null,{status:204}):typeof e==`string`?new Response(e,{headers:{"Content-Type":`text/html; charset=utf-8`}}):Response.json(e),l7.add(t),t}function d7(e){return Array.from(e,e=>({message:e.message,path:e.path?.map(e=>typeof e==`object`?e.key:e).join(`.`)}))}async function f7(e,t){let n=await e[`~standard`].validate(t);return n.issues?{ok:!1,issues:n.issues}:{ok:!0,value:n.value}}async function p7(e,t){let n={},r=[];if(e.params){let i=t.req.param(),a=await f7(e.params,i);a.ok?n.params=a.value:r.push({slot:`params`,issues:d7(a.issues)})}if(e.query){let i=new URL(t.req.url),a={};for(let[e,t]of i.searchParams)a[e]=t;let o=await f7(e.query,a);o.ok?n.query=o.value:r.push({slot:`query`,issues:d7(o.issues)})}if(e.body){let i;try{i=await t.req.json()}catch{return{ok:!1,response:Response.json({error:`Invalid JSON body`},{status:400})}}let a=await f7(e.body,i);a.ok?n.body=a.value:r.push({slot:`body`,issues:d7(a.issues)})}return r.length>0?{ok:!1,response:Response.json({error:`Validation failed`,issues:r},{status:400})}:{ok:!0,input:n}}function m7(...e){if(e.length===1)return e[0];let t=e.slice(0,-1),n=e[e.length-1];return(async e=>{let r=0,i=async()=>{if(r<t.length){let n=t[r++],a=await n(e,i);a instanceof Response&&(e.res=a)}else e.res=u7(await n(e))};return await i(),e.res})}(function(e){function t(e){return t=>(async n=>{let r=await p7(e,n);return r.ok?u7(await t(n,r.input)):r.response})}e.withValidator=t})(m7||={}),new TextEncoder,new TextDecoder(`utf-8`,{fatal:!0});function h7(e){return e}var g7=864e5,_7=h7(async e=>{let t=new Date;try{await b2.delete(vP).where(fM(vP.expiresAt,t)),await b2.delete($N).where(fM($N.expiresAt,t)),await b2.delete(xP).where(fM(xP.expiresAt,t)),await b2.delete(wP).where(fM(wP.expiresAt,t)),await b2.delete(rP).where(sM(_M(rP.clientDiscoveryId),fM(rP.updatedAt,new Date(t.getTime()-g7)),q`not exists (select 1 from ${cP} where ${cP.clientId} = ${rP.clientId})`,q`not exists (select 1 from ${bP} where ${bP.clientId} = ${rP.clientId})`))}catch(t){throw UF({error:t,fields:{cron:e.cron},message:`The cleanup cron failed.`}),t}}),v7=[`ratelimit`,`ratelimit-policy`,`retry-after`],y7=[`cf-connecting-ip`,`cf-ray`,`cf-worker`,`user-agent`],b7=yv(Oh),x7={fetch:(e,t,n)=>a7.fetch(e,{...t,pages:e=>S7(e,{env:t,ctx:n})},n),scheduled:(...e)=>Rv(e[1],()=>_7(...e))};async function S7(e,t){let{ctx:n,env:r}=t,i=T7(e.req.header(`cookie`)),a=new URL(e.req.url).origin,o,s,c=!1,l=async(t,o)=>{let l=new Request(t,o),u=new URL(l.url);if(u.origin!==a||!u.pathname.startsWith(`/v1/`))throw Error(`A page called a path outside the JSON API.`);i.size>0&&l.headers.set(`cookie`,E7(i));for(let t of y7){let n=e.req.header(t);n&&l.headers.set(t,n)}let d=await Z(e,Promise.resolve(a7.fetch(l,{...r,pages:()=>w7()},n)),`api`,`${l.method} ${new URL(l.url).pathname}`);for(let t of d.headers.getSetCookie())C7(i,{setCookie:t}),c?KF(e,{message:`A page set a cookie after its headers were sent.`}):e.header(`set-cookie`,t,{append:!0});return d.status===429&&(s??=d),d},u=await b7(e.req.raw,{context:{fetch:async(t,n)=>{o&&await Z(e,o.catch(()=>void 0),`api.wait`);let r=l(t,n);return o??=r,r},origin:a}});if(c=!0,e.header(`cache-control`,`private, no-store`),s&&u.status===200){for(let t of v7){let n=s.headers.get(t);n&&e.header(t,n)}return e.newResponse(u.body,{headers:u.headers,status:429})}return e.newResponse(u.body,u)}function C7(e,t){let[n,...r]=t.setCookie.split(`;`),i=n.indexOf(`=`),a=n.slice(0,i).trim(),o=n.slice(i+1).trim();r.some(e=>/^max-age=0$/i.test(e.trim()))||!o?e.delete(a):e.set(a,o)}function w7(){return Promise.resolve(new Response(null,{status:404}))}function T7(e){let t=new Map;for(let n of e?.split(`;`)??[]){let e=n.indexOf(`=`);e>0&&t.set(n.slice(0,e).trim(),n.slice(e+1).trim())}return t}function E7(e){return[...e].map(([e,t])=>`${e}=${t}`).join(`; `)}function D7(){let e=null;return async(t,n)=>{if(e)return e;let r=globalThis.__VITE_MANIFEST__;if(typeof r==`object`&&r)return e=r,e;let i=n?.ASSETS;if(!i||typeof i.fetch!=`function`)return null;let a=await i.fetch(new Request(new URL(`/.vite/manifest.json`,t.url).toString()));return a.ok?(e=await a.json(),e):null}}var O7={".avif":`image/avif`,".css":`text/css; charset=utf-8`,".gif":`image/gif`,".html":`text/html; charset=utf-8`,".ico":`image/x-icon`,".jpeg":`image/jpeg`,".jpg":`image/jpeg`,".js":`text/javascript; charset=utf-8`,".json":`application/json; charset=utf-8`,".mjs":`text/javascript; charset=utf-8`,".png":`image/png`,".svg":`image/svg+xml`,".txt":`text/plain; charset=utf-8`,".wasm":`application/wasm`,".webp":`image/webp`,".woff":`font/woff`,".woff2":`font/woff2`};function k7(e,t,n=`assets`,r=!1){if(![`GET`,`HEAD`].includes(e.method)||![200,206,304].includes(t.status))return t;let i=new URL(e.url).pathname,a=i.slice(i.lastIndexOf(`/`)+1),o=a.slice(a.lastIndexOf(`.`)).toLowerCase(),s=new Headers(t.headers);!s.has(`Content-Type`)&&O7[o]&&s.set(`Content-Type`,O7[o]);let c=s.get(`Cache-Control`),l=(c??``).toLowerCase().split(`,`).map(e=>e.trim()).sort().join(`,`)===`max-age=0,must-revalidate,public`,u=r&&i.startsWith(`/`+n.replace(/^\/+|\/+$/g,``)+`/`)&&o!==`.html`&&!(s.get(`Content-Type`)??``).toLowerCase().includes(`text/html`);return!s.has(`Set-Cookie`)&&u&&(!c||l)?s.set(`Cache-Control`,`public, max-age=31536000, immutable`):c||s.set(`Cache-Control`,`no-store`),new Response(t.body,{status:t.status,statusText:t.statusText,headers:s})}function A7(e,t=D7()){let n;return async(r,i,a)=>{let o=new URL(r.url).pathname;return![`GET`,`HEAD`].includes(r.method)||![200,206,304].includes(a.status)||!o.startsWith(`/`+(e??`assets`).replace(/^\/+|\/+$/g,``)+`/`)?k7(r,a,e):(n||=t(r,i).then(e=>new Set(Object.values(e??{}).flatMap(e=>Array.isArray(e?.immutableFiles)?e.immutableFiles:[])),()=>new Set),k7(r,a,e,(await n).has(o.slice(1))))}}function j7(e={}){let t=A7(e.assetsDir);return async(n,r,i)=>{if(i.status!==404||!r.ASSETS||n.method!==`GET`&&n.method!==`HEAD`)return i;let a=await r.ASSETS.fetch(new Request(n.url,{method:n.method,headers:n.headers}));if(a.status!==404)return t(n,r,a);let o=n.headers.get(`accept`)??``;if(e.serveSpaFallback&&o.includes(`text/html`)){let e=new URL(`/index.html`,n.url),t=await r.ASSETS.fetch(new Request(e,{method:n.method}));if(t.status===200){let e=new Response(t.body,{status:200,headers:t.headers});return e.headers.set(`Cache-Control`,`no-store`),e.headers.set(`Content-Type`,`text/html; charset=utf-8`),e}}else if(!e.serveSpaFallback&&e.notFound===`404-page`&&o.includes(`text/html`)&&(a.headers.get(`content-type`)??``).includes(`text/html`)){let e=new Response(a.body,a);return e.headers.set(`Cache-Control`,`no-store`),e}return i}}var M7={...x7,fetch(e,t,n){return Rv(t,async()=>N7(e,t,await x7.fetch(e,t,n)))}},N7=j7({assetsDir:`assets`,serveSpaFallback:!1,notFound:`none`}),P7=M7??{};export{P7 as default};
610
610
  //# sourceMappingURL=index.js.map