@collective-intelligence/external-apps-server-sdk 0.0.0-stage → 0.1.1
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.
- package/README.md +1075 -2
- package/dist/admin.d.ts +7556 -0
- package/dist/admin.js +6 -0
- package/dist/auth/better-auth.d.ts +71 -0
- package/dist/auth/better-auth.js +1 -0
- package/dist/auth/federated.d.ts +135 -0
- package/dist/auth/federated.js +8 -0
- package/dist/auth.d.ts +162 -0
- package/dist/auth.js +1 -0
- package/dist/express.d.ts +644 -0
- package/dist/express.js +1 -0
- package/dist/gateway/contracts.d.ts +663 -0
- package/dist/gateway/contracts.js +0 -0
- package/dist/gateway.d.ts +762 -0
- package/dist/gateway.js +8 -0
- package/dist/index.d.ts +597 -0
- package/dist/index.js +9 -0
- package/dist/knowledge-sources/payload.d.ts +420 -0
- package/dist/knowledge-sources/payload.js +1 -0
- package/dist/knowledge-sources/strapi.d.ts +389 -0
- package/dist/knowledge-sources/strapi.js +1 -0
- package/dist/persistence/drizzle-effect.d.ts +38 -0
- package/dist/persistence/drizzle-effect.js +1 -0
- package/dist/persistence/drizzle.d.ts +1514 -0
- package/dist/persistence/drizzle.js +18 -0
- package/dist/resources.d.ts +423 -0
- package/dist/resources.js +15 -0
- package/dist/runtime/effect.d.ts +954 -0
- package/dist/runtime/effect.js +15 -0
- package/dist/runtime/express.d.ts +644 -0
- package/dist/runtime/express.js +1 -0
- package/dist/runtime/nestjs.d.ts +802 -0
- package/dist/runtime/nestjs.js +8 -0
- package/dist/runtime/next.d.ts +874 -0
- package/dist/runtime/next.js +8 -0
- package/dist/runtime/web.d.ts +776 -0
- package/dist/runtime/web.js +8 -0
- package/dist/tools/ai-sdk.d.ts +170 -0
- package/dist/tools/ai-sdk.js +8 -0
- package/package.json +242 -4
package/dist/auth.d.ts
ADDED
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
// Generated by dts-bundle-generator v9.5.1
|
|
2
|
+
|
|
3
|
+
export type PrincipalKind = "detached_user" | "service_principal";
|
|
4
|
+
export type DelegatedSubjectPolicy = "allowed" | "forbidden" | "required";
|
|
5
|
+
export type AuthorizationRequirement = Readonly<{
|
|
6
|
+
delegatedSubject?: DelegatedSubjectPolicy;
|
|
7
|
+
organization: "required";
|
|
8
|
+
principalKinds: readonly PrincipalKind[];
|
|
9
|
+
scopes: readonly string[];
|
|
10
|
+
}>;
|
|
11
|
+
export type ExternalAuditSubject = Readonly<{
|
|
12
|
+
issuer: string;
|
|
13
|
+
mappedCiUserId?: string;
|
|
14
|
+
subject: string;
|
|
15
|
+
}>;
|
|
16
|
+
export type GatewayCallerIdentity = Readonly<{
|
|
17
|
+
audience: readonly string[];
|
|
18
|
+
binding: string;
|
|
19
|
+
expiresAt: number;
|
|
20
|
+
installationId: string;
|
|
21
|
+
issuer: string;
|
|
22
|
+
organizationId: string;
|
|
23
|
+
principalKind: PrincipalKind;
|
|
24
|
+
requestId: string;
|
|
25
|
+
scopes: readonly string[];
|
|
26
|
+
subject: string;
|
|
27
|
+
}>;
|
|
28
|
+
export type GatewayInvocationContext = Readonly<{
|
|
29
|
+
caller: GatewayCallerIdentity;
|
|
30
|
+
correlationId: string;
|
|
31
|
+
externalAuditSubject?: ExternalAuditSubject;
|
|
32
|
+
organizationId: string;
|
|
33
|
+
}>;
|
|
34
|
+
export interface GatewayReplayStore {
|
|
35
|
+
/** Atomically consumes an identifier until its token expiration. */
|
|
36
|
+
readonly consume: (requestId: string, expiresAt: number) => Promise<boolean>;
|
|
37
|
+
}
|
|
38
|
+
export type GatewayCallerVerificationRequest = Readonly<{
|
|
39
|
+
binding: string;
|
|
40
|
+
organizationId: string;
|
|
41
|
+
token: string;
|
|
42
|
+
}>;
|
|
43
|
+
export type GatewayCallerVerifier = (request: GatewayCallerVerificationRequest) => Promise<GatewayCallerIdentity>;
|
|
44
|
+
export type GatewayTrustedIssuer = Readonly<{
|
|
45
|
+
issuer: string;
|
|
46
|
+
tenantUrl: string;
|
|
47
|
+
}>;
|
|
48
|
+
/** The application checks its current gateway connection/grant authority on every call. */
|
|
49
|
+
export type GatewayConnectionAuthority = (input: Readonly<{
|
|
50
|
+
binding: string;
|
|
51
|
+
connectionId: string;
|
|
52
|
+
issuer: string;
|
|
53
|
+
organizationId: string;
|
|
54
|
+
scopes: readonly string[];
|
|
55
|
+
token: string;
|
|
56
|
+
}>) => Promise<boolean>;
|
|
57
|
+
export type GatewayVerifierOptions = Readonly<{
|
|
58
|
+
audience: string;
|
|
59
|
+
clockToleranceSeconds?: number;
|
|
60
|
+
fetch?: typeof globalThis.fetch;
|
|
61
|
+
jwksCacheTtlMs?: number;
|
|
62
|
+
replayStore: GatewayReplayStore;
|
|
63
|
+
}>;
|
|
64
|
+
export type GatewayCallerVerifierConfig = GatewayVerifierOptions & Readonly<{
|
|
65
|
+
trustedIssuers: readonly GatewayTrustedIssuer[];
|
|
66
|
+
authorizeConnection: GatewayConnectionAuthority;
|
|
67
|
+
}>;
|
|
68
|
+
export type GatewayConnectionGrant = Readonly<{
|
|
69
|
+
issuer: string;
|
|
70
|
+
organizationId: string;
|
|
71
|
+
connectionId: string;
|
|
72
|
+
}>;
|
|
73
|
+
/** App-owned durable storage. put must atomically upsert the exact tuple; remove revokes it. */
|
|
74
|
+
export interface GatewayConnectionGrantStore {
|
|
75
|
+
readonly has: (grant: GatewayConnectionGrant) => Promise<boolean>;
|
|
76
|
+
readonly put: (grant: GatewayConnectionGrant) => Promise<void>;
|
|
77
|
+
readonly remove: (grant: GatewayConnectionGrant) => Promise<void>;
|
|
78
|
+
}
|
|
79
|
+
export type GatewayConnectionAuthenticationConfig = Omit<GatewayCallerVerifierConfig, "authorizeConnection"> & Readonly<{
|
|
80
|
+
grants: GatewayConnectionGrantStore;
|
|
81
|
+
setupCredentials: () => Promise<readonly string[]>;
|
|
82
|
+
validationTimeoutMs?: number;
|
|
83
|
+
}>;
|
|
84
|
+
export type GatewayPackageEnrollmentGrant = GatewayConnectionGrant & Readonly<{
|
|
85
|
+
packageInstallationId: string;
|
|
86
|
+
packageFqn: string;
|
|
87
|
+
gatewayFqn: string;
|
|
88
|
+
audience: string;
|
|
89
|
+
manifestHash: string;
|
|
90
|
+
}>;
|
|
91
|
+
/** Commit nonce consumption and the complete grant together, or neither. False means replay. */
|
|
92
|
+
export interface GatewayPackageEnrollmentStore {
|
|
93
|
+
readonly enroll: (input: Readonly<{
|
|
94
|
+
grant: GatewayPackageEnrollmentGrant;
|
|
95
|
+
requestId: string;
|
|
96
|
+
expiresAt: number;
|
|
97
|
+
}>) => Promise<boolean>;
|
|
98
|
+
}
|
|
99
|
+
export type GatewayPackageEnrollmentInput = Readonly<{
|
|
100
|
+
callerToken: string;
|
|
101
|
+
manifestHash: string;
|
|
102
|
+
}>;
|
|
103
|
+
export type GatewayPackageEnrollmentConfig = Readonly<{
|
|
104
|
+
audience: string;
|
|
105
|
+
trustedIssuers: readonly GatewayTrustedIssuer[];
|
|
106
|
+
allowedPackages: readonly Readonly<{
|
|
107
|
+
organizationId: string;
|
|
108
|
+
packageFqn: string;
|
|
109
|
+
gatewayFqn: string;
|
|
110
|
+
}>[];
|
|
111
|
+
store: GatewayPackageEnrollmentStore;
|
|
112
|
+
fetch?: typeof globalThis.fetch;
|
|
113
|
+
validationTimeoutMs?: number;
|
|
114
|
+
}>;
|
|
115
|
+
/** Application login identities are separate from gateway machine callers. */
|
|
116
|
+
export type ApplicationUserIdentity = Readonly<{
|
|
117
|
+
kind: "local_user";
|
|
118
|
+
id: string;
|
|
119
|
+
email: string;
|
|
120
|
+
name: string | null;
|
|
121
|
+
} | {
|
|
122
|
+
kind: "ci_user";
|
|
123
|
+
id: string;
|
|
124
|
+
email: string | null;
|
|
125
|
+
name: string | null;
|
|
126
|
+
issuer: string;
|
|
127
|
+
organizationId: string;
|
|
128
|
+
}>;
|
|
129
|
+
/** Constructed only after user/app/organization authorization at server ingress.
|
|
130
|
+
* Canonical identities survive proxy hops and scope mutation receipts; credentials
|
|
131
|
+
* and request/correlation IDs are deliberately not part of that logical identity.
|
|
132
|
+
*/
|
|
133
|
+
export type EntityInvocationContext = Readonly<{
|
|
134
|
+
applicationId: string;
|
|
135
|
+
issuer: string;
|
|
136
|
+
organizationId: string;
|
|
137
|
+
resourceId: string;
|
|
138
|
+
roles: readonly string[];
|
|
139
|
+
scopes: readonly string[];
|
|
140
|
+
teamIds: readonly string[];
|
|
141
|
+
user: ApplicationUserIdentity;
|
|
142
|
+
}>;
|
|
143
|
+
export declare const createGatewayConnectionAuthentication: (config: GatewayConnectionAuthenticationConfig) => {
|
|
144
|
+
enrollConnection: ({ credential, callerToken }: Readonly<{
|
|
145
|
+
credential: string;
|
|
146
|
+
callerToken: string;
|
|
147
|
+
}>) => Promise<void>;
|
|
148
|
+
verifyCaller: GatewayCallerVerifier;
|
|
149
|
+
verifySetupCredential: (credential: string) => Promise<boolean>;
|
|
150
|
+
};
|
|
151
|
+
export declare const authorizeGatewayInvocation: (input: Readonly<{
|
|
152
|
+
caller: GatewayCallerIdentity;
|
|
153
|
+
correlationId: string;
|
|
154
|
+
externalAuditSubject?: ExternalAuditSubject;
|
|
155
|
+
requirement: AuthorizationRequirement;
|
|
156
|
+
}>) => GatewayInvocationContext;
|
|
157
|
+
export declare const createGatewayCallerVerifier: (config: GatewayCallerVerifierConfig) => GatewayCallerVerifier, createGatewaySetupVerifier: (credentials: () => Promise<readonly string[]>) => ((credential: string) => Promise<boolean>), createInMemoryReplayStore: (maximumEntries?: number) => GatewayReplayStore;
|
|
158
|
+
export declare const createGatewayPackageEnrollment: (config: GatewayPackageEnrollmentConfig) => {
|
|
159
|
+
enrollPackageConnection: ({ callerToken, manifestHash }: GatewayPackageEnrollmentInput) => Promise<void>;
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
export {};
|
package/dist/auth.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var __defProp=Object.defineProperty;var __returnValue=(v)=>v;function __exportSetter(name,newValue){this[name]=__returnValue.bind(null,newValue)}var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:true,configurable:true,set:__exportSetter.bind(all,name)})};var exports_authorization={};__export(exports_authorization,{authorizeGatewayInvocation:()=>authorizeGatewayInvocation});var exports_caller_verifier={};__export(exports_caller_verifier,{createTrustedGatewayTokenVerifier:()=>createTrustedGatewayTokenVerifier,createInMemoryReplayStore:()=>createInMemoryReplayStore,createGatewaySetupVerifier:()=>createGatewaySetupVerifier,createGatewayCallerVerifier:()=>createGatewayCallerVerifier,GatewayCallerAuthError:()=>GatewayCallerAuthError});var encoder=new TextEncoder;var decoder=new TextDecoder;var strictDecoder=new TextDecoder("utf-8",{fatal:true});var MAX_INT32=2**32;function concat(...buffers){const size=buffers.reduce((acc,{length})=>acc+length,0);const buf=new Uint8Array(size);let i=0;for(const buffer of buffers){buf.set(buffer,i);i+=buffer.length}return buf}function encode(string){const bytes=new Uint8Array(string.length);for(let i=0;i<string.length;i++){const code=string.charCodeAt(i);if(code>127){throw new TypeError("non-ASCII string encountered in encode()")}bytes[i]=code}return bytes}var unusable=(name,prop="algorithm.name")=>new TypeError(`CryptoKey does not support this operation, its ${prop} must be ${name}`);function checkUsage(key,usage){if(usage&&!key.usages.includes(usage)){throw new TypeError(`CryptoKey does not support this operation, its usages must include ${usage}.`)}}function checkModulusLength(alg,key){const{modulusLength}=key.algorithm;if(typeof modulusLength!=="number"||modulusLength<2048){throw new TypeError(`${alg} requires key modulusLength to be 2048 bits or larger`)}}function checkCryptoKey(key,expected,usage){const algorithm=key.algorithm;if(algorithm.name!==expected.name){throw unusable(expected.name)}if(expected.hash&&algorithm.hash?.name!==expected.hash){throw unusable(expected.hash,"algorithm.hash")}if(expected.namedCurve&&algorithm.namedCurve!==expected.namedCurve){throw unusable(expected.namedCurve,"algorithm.namedCurve")}if(expected.length!==undefined&&algorithm.length!==expected.length){throw unusable(expected.length,"algorithm.length")}checkUsage(key,usage)}function message(msg,actual,...types){if(types.length>2){const last=types.pop();msg+=`one of type ${types.join(", ")}, or ${last}.`}else if(types.length===2){msg+=`one of type ${types[0]} or ${types[1]}.`}else{msg+=`of type ${types[0]}.`}if(actual==null){msg+=` Received ${actual}`}else if(typeof actual==="function"&&actual.name){msg+=` Received function ${actual.name}`}else if(typeof actual==="object"&&actual!=null){if(actual.constructor?.name){msg+=` Received an instance of ${actual.constructor.name}`}}return msg}var withAlg=(alg,actual,...types)=>message(`Key for the ${alg} algorithm must be `,actual,...types);var exports_errors={};__export(exports_errors,{JWTInvalid:()=>JWTInvalid,JWTExpired:()=>JWTExpired,JWTClaimValidationFailed:()=>JWTClaimValidationFailed,JWSSignatureVerificationFailed:()=>JWSSignatureVerificationFailed,JWSInvalid:()=>JWSInvalid,JWKSTimeout:()=>JWKSTimeout,JWKSNoMatchingKey:()=>JWKSNoMatchingKey,JWKSMultipleMatchingKeys:()=>JWKSMultipleMatchingKeys,JWKSInvalid:()=>JWKSInvalid,JWKInvalid:()=>JWKInvalid,JWEInvalid:()=>JWEInvalid,JWEDecryptionFailed:()=>JWEDecryptionFailed,JOSENotSupported:()=>JOSENotSupported,JOSEError:()=>JOSEError,JOSEAlgNotAllowed:()=>JOSEAlgNotAllowed});class JOSEError extends Error{static code="ERR_JOSE_GENERIC";code="ERR_JOSE_GENERIC";constructor(message2,options){super(message2,options);this.name=this.constructor.name;Error.captureStackTrace?.(this,this.constructor)}}class JWTClaimValidationFailed extends JOSEError{static code="ERR_JWT_CLAIM_VALIDATION_FAILED";code="ERR_JWT_CLAIM_VALIDATION_FAILED";claim;reason;payload;constructor(message2,payload,claim="unspecified",reason="unspecified"){super(message2,{cause:{claim,reason,payload}});this.claim=claim;this.reason=reason;this.payload=payload}}class JWTExpired extends JOSEError{static code="ERR_JWT_EXPIRED";code="ERR_JWT_EXPIRED";claim;reason;payload;constructor(message2,payload,claim="unspecified",reason="unspecified"){super(message2,{cause:{claim,reason,payload}});this.claim=claim;this.reason=reason;this.payload=payload}}class JOSEAlgNotAllowed extends JOSEError{static code="ERR_JOSE_ALG_NOT_ALLOWED";code="ERR_JOSE_ALG_NOT_ALLOWED"}class JOSENotSupported extends JOSEError{static code="ERR_JOSE_NOT_SUPPORTED";code="ERR_JOSE_NOT_SUPPORTED"}class JWEDecryptionFailed extends JOSEError{static code="ERR_JWE_DECRYPTION_FAILED";code="ERR_JWE_DECRYPTION_FAILED";constructor(message2="decryption operation failed",options){super(message2,options)}}class JWEInvalid extends JOSEError{static code="ERR_JWE_INVALID";code="ERR_JWE_INVALID"}class JWSInvalid extends JOSEError{static code="ERR_JWS_INVALID";code="ERR_JWS_INVALID"}class JWTInvalid extends JOSEError{static code="ERR_JWT_INVALID";code="ERR_JWT_INVALID"}class JWKInvalid extends JOSEError{static code="ERR_JWK_INVALID";code="ERR_JWK_INVALID"}class JWKSInvalid extends JOSEError{static code="ERR_JWKS_INVALID";code="ERR_JWKS_INVALID"}class JWKSNoMatchingKey extends JOSEError{static code="ERR_JWKS_NO_MATCHING_KEY";code="ERR_JWKS_NO_MATCHING_KEY";constructor(message2="no applicable key found in the JSON Web Key Set",options){super(message2,options)}}class JWKSMultipleMatchingKeys extends JOSEError{[Symbol.asyncIterator]=async function*(){};static code="ERR_JWKS_MULTIPLE_MATCHING_KEYS";code="ERR_JWKS_MULTIPLE_MATCHING_KEYS";constructor(message2="multiple matching keys found in the JSON Web Key Set",options){super(message2,options)}}class JWKSTimeout extends JOSEError{static code="ERR_JWKS_TIMEOUT";code="ERR_JWKS_TIMEOUT";constructor(message2="request timed out",options){super(message2,options)}}class JWSSignatureVerificationFailed extends JOSEError{static code="ERR_JWS_SIGNATURE_VERIFICATION_FAILED";code="ERR_JWS_SIGNATURE_VERIFICATION_FAILED";constructor(message2="signature verification failed",options){super(message2,options)}}var isCryptoKey=(key)=>{if(key?.[Symbol.toStringTag]==="CryptoKey")return true;try{return key instanceof CryptoKey}catch{return false}};var isKeyObject=(key)=>key?.[Symbol.toStringTag]==="KeyObject";var isKeyLike=(key)=>isCryptoKey(key)||isKeyObject(key);function decodeBase64(encoded){if(Uint8Array.fromBase64){return Uint8Array.fromBase64(encoded)}const binary=atob(encoded);const bytes=new Uint8Array(binary.length);for(let i=0;i<binary.length;i++){bytes[i]=binary.charCodeAt(i)}return bytes}var invalid="The input to be decoded is not correctly encoded.";function decode(input){if(Uint8Array.fromBase64){try{return Uint8Array.fromBase64(typeof input==="string"?input:decoder.decode(input),{alphabet:"base64url"})}catch(cause){throw new TypeError(invalid,{cause})}}let encoded=input;if(encoded instanceof Uint8Array){encoded=decoder.decode(encoded)}if(encoded.includes("+")||encoded.includes("/")){throw new TypeError(invalid)}encoded=encoded.replace(/-/g,"+").replace(/_/g,"/");try{return decodeBase64(encoded)}catch{throw new TypeError(invalid)}}function isObject(input){if(typeof input!=="object"||input===null||Object.prototype.toString.call(input)!=="[object Object]"){return false}const prototype=Object.getPrototypeOf(input);if(prototype===null){return true}let proto=prototype;while(Object.getPrototypeOf(proto)!==null){proto=Object.getPrototypeOf(proto)}return prototype===proto}function isDisjoint(...headers){const parameters=new Set;for(const header of headers){if(!header)continue;for(const parameter of Object.keys(header)){if(parameters.has(parameter)){return false}parameters.add(parameter)}}return true}var isJWK=(key)=>isObject(key)&&typeof key.kty==="string";var isPrivateJWK=(key)=>key.kty!=="oct"&&(key.kty==="AKP"&&typeof key.priv==="string"||typeof key.d==="string");var isPublicJWK=(key)=>key.kty!=="oct"&&key.d===undefined&&key.priv===undefined;var isSecretJWK=(key)=>key.kty==="oct"&&typeof key.k==="string";var unprotected=Symbol();function decodeBase64url(value,label,ErrorClass){try{return decode(value)}catch{throw new ErrorClass(`Failed to base64url decode the ${label}`)}}function encodeBase64url(value,label,ErrorClass){try{return encode(value)}catch{throw new ErrorClass(`The ${label} is not a valid base64url string`)}}function parseJoseHeader(b64,ErrorClass,message2){let parsed;try{parsed=JSON.parse(strictDecoder.decode(decode(b64)))}catch{throw new ErrorClass(message2)}if(!isObject(parsed)){throw new ErrorClass(message2)}return parsed}async function jwkToKey(entry,jwk){if(jwk.kty==="RSA"&&"oth"in jwk&&jwk.oth!==undefined){throw new JOSENotSupported('RSA JWK "oth" (Other Primes Info) Parameter value is not supported')}if(!entry.kty.includes(jwk.kty)){throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value')}const algorithm=entry.resolve?.({kty:jwk.kty,crv:jwk.crv})??entry.subtle;const isPrivate=!!(jwk.d||jwk.priv);const keyData={...jwk};if(keyData.kty!=="AKP"){delete keyData.alg}delete keyData.use;return crypto.subtle.importKey("jwk",keyData,algorithm,jwk.ext??!isPrivate,jwk.key_ops??entry.usages[isPrivate?1:0])}var tag=(key)=>key[Symbol.toStringTag];var jwkMatchesOp=(entry,key,usage)=>{const{alg}=entry;if(key.use!==undefined){const expected=usage==="sign"||usage==="verify"?"sig":"enc";if(key.use!==expected){throw new TypeError(`Invalid key for this operation, its "use" must be "${expected}" when present`)}}if(key.alg!==undefined&&key.alg!==alg){throw new TypeError(`Invalid key for this operation, its "alg" must be "${alg}" when present`)}if(Array.isArray(key.key_ops)){const expectedKeyOp=usage==="encrypt"||usage==="decrypt"?entry.ops?.[usage==="encrypt"?0:1]:usage;if(expectedKeyOp&&!key.key_ops.includes(expectedKeyOp)){throw new TypeError(`Invalid key for this operation, its "key_ops" must include "${expectedKeyOp}" when present`)}}};function checkKeyType(entry,key,usage){const{alg,secret}=entry;const privateKey=usage==="decrypt"||usage==="sign";if(secret&&key instanceof Uint8Array)return[BYTES,key];if(isJWK(key)){if(secret?!isSecretJWK(key):!(privateKey?isPrivateJWK(key):isPublicJWK(key))){throw new TypeError(secret?`JSON Web Key for symmetric algorithms must have JWK "kty" (Key Type) equal to "oct" and the JWK "k" (Key Value) present`:`JSON Web Key for this operation must be a ${privateKey?"private":"public"} JWK`)}jwkMatchesOp(entry,key,usage);return[JWK,key]}if(!isKeyLike(key)){throw new TypeError(secret?withAlg(alg,key,"CryptoKey","KeyObject","JSON Web Key","Uint8Array"):withAlg(alg,key,"CryptoKey","KeyObject","JSON Web Key"))}if(secret){if(key.type!=="secret"){throw new TypeError(`${tag(key)} instances for symmetric algorithms must be of type "secret"`)}}else{if(key.type==="secret"){throw new TypeError(`${tag(key)} instances for asymmetric algorithms must not be of type "secret"`)}const expectedType=privateKey?"private":"public";if((key.type==="public"||key.type==="private")&&key.type!==expectedType){const operation=usage==="sign"?"signing":usage==="verify"?"verifying":`${usage.slice(0,-1)}tion`;throw new TypeError(`${tag(key)} instances for asymmetric algorithm ${operation} must be of type "${expectedType}"`)}}return isCryptoKey(key)?[CRYPTO,key]:[KEYOBJECT,key]}var BYTES=0;var CRYPTO=1;var KEYOBJECT=2;var JWK=3;var cache;var nist={__proto__:null,prime256v1:"P-256",secp384r1:"P-384",secp521r1:"P-521"};function cached(key,alg,value){cache||=new WeakMap;const entry=cache.get(key);if(value){if(entry){entry[alg]=value}else{cache.set(key,{__proto__:null,[alg]:value})}}return value??entry?.[alg]}var handleJWK=async(key,jwk,entry)=>cached(key,entry.alg)??cached(key,entry.alg,await jwkToKey(entry,{...jwk,alg:entry.alg}));var handleKeyObject=(keyObject,entry)=>{const hit=cached(keyObject,entry.alg);if(hit)return hit;const isPublic=keyObject.type==="public";const usages=entry.usages[isPublic?0:1];const{asymmetricKeyType}=keyObject;const crv=nist[keyObject.asymmetricKeyDetails?.namedCurve];const params=entry.resolve?.({crv,asymmetricKeyType})??entry.subtle;return cached(keyObject,entry.alg,keyObject.toCryptoKey(params,isPublic,usages))};async function prepareKey(entry,key,usage){const tagged=checkKeyType(entry,key,usage);switch(tagged[0]){case BYTES:case CRYPTO:return tagged[1];case JWK:{const key2=tagged[1];if(key2.k){return decode(key2.k)}if(!Object.isFrozen(key2)){const{key_ops}=key2;if(Array.isArray(key_ops))Object.freeze(key_ops);Object.freeze(key2)}return handleJWK(key2,key2,entry)}case KEYOBJECT:{const keyObject=tagged[1];if(keyObject.type==="secret"){return keyObject.export()}if("toCryptoKey"in keyObject&&typeof keyObject.toCryptoKey==="function"){return handleKeyObject(keyObject,entry)}return handleJWK(keyObject,keyObject.export({format:"jwk"}),entry)}}}function table(entries){const out={__proto__:null};for(const alg in entries){out[alg]={...entries[alg],alg}}return out}var JWS_RECOGNIZED={__proto__:null,b64:true};function validateAlgorithms(option,algorithms){if(algorithms!==undefined&&(!Array.isArray(algorithms)||algorithms.some((s)=>typeof s!=="string"))){throw new TypeError(`"${option}" option must be an array of strings`)}if(!algorithms){return}return new Set(algorithms)}function validateCrit(Err,recognizedDefault,recognizedOption,protectedHeader,joseHeader){if(joseHeader.crit!==undefined&&protectedHeader?.crit===undefined){throw new Err('"crit" (Critical) Header Parameter MUST be integrity protected')}if(!protectedHeader||protectedHeader.crit===undefined){return[]}if(!Array.isArray(protectedHeader.crit)||protectedHeader.crit.length===0||protectedHeader.crit.some((input)=>typeof input!=="string"||input.length===0)){throw new Err('"crit" (Critical) Header Parameter MUST be an array of non-empty strings when present')}const recognized=recognizedOption===undefined?recognizedDefault:{__proto__:null,...recognizedOption,...recognizedDefault};for(const parameter of protectedHeader.crit){if(!(parameter in recognized)){throw new JOSENotSupported(`Extension Header Parameter "${parameter}" is not recognized`)}if(!Object.hasOwn(joseHeader,parameter)||joseHeader[parameter]===undefined){throw new Err(`Extension Header Parameter "${parameter}" is missing`)}if(recognized[parameter]&&(!Object.hasOwn(protectedHeader,parameter)||protectedHeader[parameter]===undefined)){throw new Err(`Extension Header Parameter "${parameter}" MUST be integrity protected`)}}return protectedHeader.crit}async function getSigKey(entry,key,usage){if(key instanceof Uint8Array){return crypto.subtle.importKey("raw",key,entry.subtle,false,[usage])}checkCryptoKey(key,entry.subtle,usage);if(entry.minRsaBits)checkModulusLength(entry.alg,key);return key}async function verify(entry,key,signature,data){const cryptoKey=await getSigKey(entry,key,"verify");try{return await crypto.subtle.verify(entry.signing,cryptoKey,signature,data)}catch{return false}}var sig=[["verify"],["sign"]];function hmac(bits){const subtle={name:"HMAC",hash:`SHA-${bits}`};return{kty:["oct"],secret:true,subtle,signing:subtle,usages:sig}}function rsa(bits,saltLength){const name=saltLength?"RSA-PSS":"RSASSA-PKCS1-v1_5";const subtle={name,hash:`SHA-${bits}`};return{kty:["RSA"],subtle,signing:saltLength?{...subtle,saltLength}:subtle,usages:sig,minRsaBits:2048}}function ecdsa(crv,bits){return{kty:["EC"],crv,subtle:{name:"ECDSA",namedCurve:crv},signing:{name:"ECDSA",hash:`SHA-${bits}`},usages:sig}}function eddsa(){const subtle={name:"Ed25519"};return{kty:["OKP"],crv:"Ed25519",subtle,signing:subtle,usages:sig}}function mldsa(bits){const name=`ML-DSA-${bits}`;const subtle={name};return{kty:["AKP"],subtle,signing:subtle,usages:sig}}var JWS=table({HS256:hmac(256),HS384:hmac(384),HS512:hmac(512),RS256:rsa(256),RS384:rsa(384),RS512:rsa(512),PS256:rsa(256,32),PS384:rsa(384,48),PS512:rsa(512,64),ES256:ecdsa("P-256",256),ES384:ecdsa("P-384",384),ES512:ecdsa("P-521",512),EdDSA:eddsa(),Ed25519:eddsa(),"ML-DSA-44":mldsa(44),"ML-DSA-65":mldsa(65),"ML-DSA-87":mldsa(87)});function jwsAlgorithm(alg){const entry=typeof alg==="string"?JWS[alg]:undefined;if(!entry){throw new JOSENotSupported(`alg ${alg} is not supported either by JOSE or your javascript runtime`)}return entry}function prepareVerify(options){return[options&&validateAlgorithms("algorithms",options.algorithms),options?.crit]}async function verifySignature(jws,shared,key){const{protected:encodedProtected,header,payload:inputPayload}=jws;let parsedProt={};if(encodedProtected){parsedProt=parseJoseHeader(encodedProtected,JWSInvalid,"JWS Protected Header is invalid")}let joseHeader;if(header!==undefined){if(!isDisjoint(parsedProt,header)){throw new JWSInvalid("JWS Protected and JWS Unprotected Header Parameter names must be disjoint")}joseHeader={...parsedProt,...header}}else{joseHeader=parsedProt}const extensions=validateCrit(JWSInvalid,JWS_RECOGNIZED,shared[1],parsedProt,joseHeader);let b64=true;if(extensions.includes("b64")){b64=parsedProt.b64;if(typeof b64!=="boolean"){throw new JWSInvalid('The "b64" (base64url-encode payload) Header Parameter must be a boolean')}}const{alg}=joseHeader;if(typeof alg!=="string"||!alg){throw new JWSInvalid('JWS "alg" (Algorithm) Header Parameter missing or invalid')}if(shared[0]&&!shared[0].has(alg)){throw new JOSEAlgNotAllowed('"alg" (Algorithm) Header Parameter value not allowed')}if(b64){if(typeof inputPayload!=="string"){throw new JWSInvalid("JWS Payload must be a string")}}else if(typeof inputPayload!=="string"&&!(inputPayload instanceof Uint8Array)){throw new JWSInvalid("JWS Payload must be a string or an Uint8Array instance")}let resolvedKey=false;if(typeof key==="function"){key=await key(parsedProt,jws);resolvedKey=true}const entry=jwsAlgorithm(alg);const data=concat(encodedProtected!==undefined?encode(encodedProtected):new Uint8Array,encode("."),typeof inputPayload==="string"?b64?shared[2]??=encodeBase64url(inputPayload,"payload",JWSInvalid):encoder.encode(inputPayload):inputPayload);const signature=decodeBase64url(jws.signature,"signature",JWSInvalid);const k=await prepareKey(entry,key,"verify");const verified=await verify(entry,k,signature,data);if(!verified){throw new JWSSignatureVerificationFailed}let payload;if(b64){payload=decodeBase64url(inputPayload,"payload",JWSInvalid)}else if(typeof inputPayload==="string"){payload=encoder.encode(inputPayload)}else{payload=inputPayload}return[payload,parsedProt,b64,k,resolvedKey]}async function verifyCompact(jws,shared,key){if(jws instanceof Uint8Array){jws=decoder.decode(jws)}if(typeof jws!=="string"){throw new JWSInvalid("Compact JWS must be a string or Uint8Array")}const{0:protectedHeader,1:payload,2:signature,length}=jws.split(".");if(length!==3){throw new JWSInvalid("Invalid Compact JWS")}return verifySignature({payload,protected:protectedHeader,signature},shared,key)}var epoch=(date)=>Math.floor(date.getTime()/1000);var multipliers={s:1,m:60,h:3600,d:86400,w:604800,y:31557600};var REGEX=/^(\+|\-)? ?(\d+|\d+\.\d+) ?(seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)(?: (ago|from now))?$/i;var checkFailed="check_failed";function secs(str){const matched=REGEX.exec(str);if(!matched||matched[4]&&matched[1]){throw new TypeError("Invalid time period format")}const value=parseFloat(matched[2]);const numericDate=Math.round(value*multipliers[matched[3][0].toLowerCase()]);if(matched[1]==="-"||matched[4]==="ago"){return-numericDate}return numericDate}function validateInput(label,input){if(!Number.isFinite(input)){throw new TypeError(`Invalid ${label} input`)}return input}function numericDate(value,label){if(typeof value==="number")return validateInput(label,value);if(value instanceof Date)return validateInput(label,epoch(value));return epoch(new Date)+secs(value)}var normalizeTyp=(value)=>{if(value.includes("/")){return value.toLowerCase()}return`application/${value.toLowerCase()}`};var checkAudiencePresence=(audPayload,audOption)=>{if(typeof audPayload==="string"){return audOption.includes(audPayload)}if(Array.isArray(audPayload)){return audOption.some((aud)=>audPayload.includes(aud))}return false};function validateNumericDate(payload,claim,required=false){const value=payload[claim];if(value===undefined&&!required)return;if(typeof value!=="number"){throw new JWTClaimValidationFailed(`"${claim}" claim must be a number`,payload,claim,"invalid")}return value}function unexpectedClaim(payload,claim){throw new JWTClaimValidationFailed(`unexpected "${claim}" claim value`,payload,claim,checkFailed)}function validateClaimsSet(protectedHeader,encodedPayload,options={}){let payload;try{payload=JSON.parse(strictDecoder.decode(encodedPayload))}catch{}if(!isObject(payload)){throw new JWTInvalid("JWT Claims Set must be a top-level JSON object")}const{typ}=options;if(typ&&(typeof protectedHeader.typ!=="string"||normalizeTyp(protectedHeader.typ)!==normalizeTyp(typ))){throw new JWTClaimValidationFailed('unexpected "typ" JWT header value',payload,"typ",checkFailed)}const{requiredClaims=[],issuer,subject,audience,maxTokenAge}=options;const presenceCheck=[...requiredClaims];if(maxTokenAge!==undefined)presenceCheck.push("iat");if(audience!==undefined)presenceCheck.push("aud");if(subject!==undefined)presenceCheck.push("sub");if(issuer!==undefined)presenceCheck.push("iss");for(const claim of new Set(presenceCheck.reverse())){if(!Object.hasOwn(payload,claim)){throw new JWTClaimValidationFailed(`missing required "${claim}" claim`,payload,claim,"missing")}}if(issuer!==undefined&&!(Array.isArray(issuer)?issuer:[issuer]).includes(payload.iss)){unexpectedClaim(payload,"iss")}if(subject!==undefined&&payload.sub!==subject){unexpectedClaim(payload,"sub")}if(audience!==undefined&&!checkAudiencePresence(payload.aud,typeof audience==="string"?[audience]:audience)){unexpectedClaim(payload,"aud")}const{clockTolerance}=options;let tolerance=0;if(typeof clockTolerance==="string"){tolerance=secs(clockTolerance)}else if(clockTolerance!==undefined){if(typeof clockTolerance!=="number"){throw new TypeError("Invalid clockTolerance option type")}tolerance=clockTolerance}validateInput("clockTolerance option",tolerance);const{currentDate}=options;const now=validateInput("currentDate option",epoch(currentDate||new Date));const iat=validateNumericDate(payload,"iat",maxTokenAge!==undefined);const nbf=validateNumericDate(payload,"nbf");if(nbf!==undefined){if(nbf>now+tolerance){throw new JWTClaimValidationFailed('"nbf" claim timestamp check failed',payload,"nbf",checkFailed)}}const exp=validateNumericDate(payload,"exp");if(exp!==undefined){if(exp<=now-tolerance){throw new JWTExpired('"exp" claim timestamp check failed',payload,"exp",checkFailed)}}if(maxTokenAge!==undefined){const age=now-iat;const max=typeof maxTokenAge==="number"?maxTokenAge:secs(maxTokenAge);if(age-tolerance>max){throw new JWTExpired('"iat" claim timestamp check failed (too far in the past)',payload,"iat",checkFailed)}if(age<0-tolerance){throw new JWTClaimValidationFailed('"iat" claim timestamp check failed (it should be in the past)',payload,"iat",checkFailed)}}return payload}class JWTClaimsBuilder{#payload;constructor(payload){if(!isObject(payload)){throw new TypeError("JWT Claims Set MUST be an object")}this.#payload=structuredClone(payload)}data(){return encoder.encode(JSON.stringify(this.#payload))}get iss(){return this.#payload.iss}set iss(value){this.#payload.iss=value}get sub(){return this.#payload.sub}set sub(value){this.#payload.sub=value}get aud(){return this.#payload.aud}set aud(value){this.#payload.aud=value}set jti(value){this.#payload.jti=value}set nbf(value){this.#payload.nbf=numericDate(value,"setNotBefore")}set exp(value){this.#payload.exp=numericDate(value,"setExpirationTime")}set iat(value){if(value===undefined){this.#payload.iat=epoch(new Date)}else if(typeof value==="string"){this.#payload.iat=validateInput("setIssuedAt",epoch(new Date)+secs(value))}else{this.#payload.iat=numericDate(value,"setIssuedAt")}}}async function jwtVerify(jwt,key,options){const verified=await verifyCompact(jwt,prepareVerify(options),key);if(!verified[2]){throw new JWTInvalid("JWTs MUST NOT use unencoded payload")}const payload=validateClaimsSet(verified[1],verified[0],options);const result={payload,protectedHeader:verified[1]};if(typeof key==="function"){return{...result,key:verified[3]}}return result}function signatureAlgorithm(alg){const entry=typeof alg==="string"?JWS[alg]:undefined;if(!entry||entry.secret){throw new JOSENotSupported('Unsupported "alg" value for a JSON Web Key Set')}return entry}function isJWKSLike(jwks){if(!jwks||typeof jwks!=="object"){return false}const{keys}=jwks;return Array.isArray(keys)&&keys.every(isObject)}class LocalJWKSetImpl{#jwks;#cached=new WeakMap;constructor(jwks){if(!isJWKSLike(jwks)){throw new JWKSInvalid("JSON Web Key Set malformed")}this.#jwks=structuredClone(jwks)}jwks(){return this.#jwks}async getKey(protectedHeader,token){const{alg,kid}={...protectedHeader,...token?.header};const entry=signatureAlgorithm(alg);const candidates=this.#jwks.keys.filter((jwk2)=>entry.kty.includes(jwk2.kty)&&(typeof kid!=="string"||kid===jwk2.kid)&&(!(typeof jwk2.alg==="string"||jwk2.kty==="AKP")||alg===jwk2.alg)&&(typeof jwk2.use!=="string"||jwk2.use==="sig")&&(!Array.isArray(jwk2.key_ops)||jwk2.key_ops.includes("verify"))&&(!entry.crv||jwk2.crv===entry.crv));const{0:jwk,length}=candidates;if(length===0){throw new JWKSNoMatchingKey}if(length!==1){const error=new JWKSMultipleMatchingKeys;const _cached=this.#cached;error[Symbol.asyncIterator]=async function*(){for(const jwk2 of candidates){try{yield await importWithAlgCache(_cached,jwk2,entry)}catch{}}};throw error}return importWithAlgCache(this.#cached,jwk,entry)}}async function importWithAlgCache(cache2,jwk,entry){const cached2=cache2.get(jwk)||cache2.set(jwk,{__proto__:null}).get(jwk);if(cached2[entry.alg]===undefined){const key=await jwkToKey(entry,{...jwk,alg:entry.alg,ext:true});if(key.type!=="public"){throw new JWKSInvalid("JSON Web Key Set members must be public keys")}cached2[entry.alg]=key}return cached2[entry.alg]}function createLocalJWKSet(jwks){const set=new LocalJWKSetImpl(jwks);const localJWKSet=async(protectedHeader,token)=>set.getKey(protectedHeader,token);Object.defineProperty(localJWKSet,"jwks",{value:()=>structuredClone(set.jwks())});return localJWKSet}function decodeJwt(jwt){if(typeof jwt!=="string")throw new JWTInvalid("JWTs must use Compact JWS serialization, JWT must be a string");const{1:payload,length}=jwt.split(".");if(length===5)throw new JWTInvalid("Only JWTs using Compact JWS serialization can be decoded");if(length!==3)throw new JWTInvalid("Invalid JWT");if(!payload)throw new JWTInvalid("JWTs must contain a payload");let decoded;try{decoded=decode(payload)}catch{throw new JWTInvalid("Failed to base64url decode the payload")}let result;try{result=JSON.parse(strictDecoder.decode(decoded))}catch{throw new JWTInvalid("Failed to parse the decoded payload as JSON")}if(!isObject(result))throw new JWTInvalid("Invalid JWT Claims Set");return result}var requireHttpsOrigin=(value,name)=>{let url;try{url=new URL(value)}catch{throw new TypeError(`${name} must contain only an HTTPS origin`)}if(url.protocol!=="https:"||url.origin!==value||url.pathname!=="/"||url.search!==""||url.hash!==""||url.username!==""||url.password!==""){throw new TypeError(`${name} must contain only an HTTPS origin`)}return url.origin};var createInMemoryReplayStore=(maximumEntries=1e4)=>{if(!Number.isSafeInteger(maximumEntries)||maximumEntries<1){throw new TypeError("maximumEntries must be a positive integer")}const consumed=new Map;return{consume:async(requestId,expiresAt)=>{await Promise.resolve();const now=Date.now();for(const[id,expiry]of consumed){if(expiry<=now){consumed.delete(id)}}if(consumed.has(requestId)){return false}if(consumed.size>=maximumEntries){return false}consumed.set(requestId,expiresAt);return true}}};var gatewayCallerAuthErrorBrand=Symbol.for("@collective-intelligence/external-apps-server-sdk/GatewayCallerAuthError");class GatewayCallerAuthError extends Error{code;[gatewayCallerAuthErrorBrand]=true;static[Symbol.hasInstance](value){return value instanceof Error&&gatewayCallerAuthErrorBrand in value&&value[gatewayCallerAuthErrorBrand]===true&&"code"in value&&(value.code==="authorization_denied"||value.code==="temporarily_unavailable"||value.code==="replay_detected"||value.code==="unauthenticated")}constructor(code,message2){super(message2);this.code=code;this.name="GatewayCallerAuthError"}}var object=(value)=>{if(typeof value!=="object"||value===null||Array.isArray(value)){return null}return Object.fromEntries(Object.entries(value))};var boundedJson=async(response)=>{if(!response.ok){throw new TypeError("CI authentication metadata unavailable")}const text=await response.text();if(new TextEncoder().encode(text).byteLength>1048576){throw new TypeError("CI authentication metadata is too large")}return JSON.parse(text)};var audiences=(value)=>{if(typeof value==="string"){return[value]}return Array.isArray(value)?value:[]};var principalKind=(value)=>{if(value!=="detached_user"&&value!=="service_principal"){throw new GatewayCallerAuthError("unauthenticated","Gateway caller principal kind is invalid")}return value};var requiredString=(payload,key)=>{const value=payload[key];if(typeof value!=="string"||value.length===0){throw new GatewayCallerAuthError("unauthenticated",`Gateway caller claim ${key} is required`)}return value};var createTrustedGatewayTokenVerifier=(config)=>{const fetch=config.fetch??globalThis.fetch;const tenant=new URL(requireHttpsOrigin(config.tenantUrl,"tenantUrl"));const cacheTtl=config.jwksCacheTtlMs??300000;if(!Number.isSafeInteger(cacheTtl)||cacheTtl<1000||cacheTtl>3600000){throw new TypeError("jwksCacheTtlMs must be an integer from 1_000 to 3_600_000")}let cached2;const keys=async(force=false)=>{if(!force&&cached2!==undefined&&cached2.expiresAt>Date.now()){return cached2.verifier}const discovery=object(await boundedJson(await fetch(new URL("/.well-known/oauth-authorization-server",tenant),{redirect:"manual",signal:AbortSignal.timeout(1e4)})));if(discovery===null||discovery.issuer!==config.issuer||typeof discovery.jwks_uri!=="string"){throw new TypeError("CI authentication discovery is invalid")}const jwksUrl=new URL(discovery.jwks_uri);if(jwksUrl.origin!==tenant.origin||jwksUrl.username!==""||jwksUrl.password!==""){throw new TypeError("CI JWKS must remain on the configured tenant")}const document=object(await boundedJson(await fetch(jwksUrl,{redirect:"manual",signal:AbortSignal.timeout(1e4)})));if(document===null||!Array.isArray(document.keys)){throw new TypeError("CI JWKS is invalid")}const verifier=createLocalJWKSet(document);cached2={expiresAt:Date.now()+cacheTtl,verifier};return verifier};return async(token)=>{const verify2=async(force=false)=>await jwtVerify(token,await keys(force),{algorithms:["ES256"],audience:config.audience,clockTolerance:config.clockToleranceSeconds??5,issuer:config.issuer});let payload;try{try{const verified=await verify2();const{payload:verifiedPayload}=verified;payload=verifiedPayload}catch(error){if(!(error instanceof exports_errors.JWKSNoMatchingKey)){throw error}const verified=await verify2(true);const{payload:verifiedPayload}=verified;payload=verifiedPayload}}catch{throw new GatewayCallerAuthError("unauthenticated","Gateway caller token is invalid")}if(typeof payload.exp!=="number"||payload.exp*1000<=Date.now()){throw new GatewayCallerAuthError("unauthenticated","Gateway caller expiry is required")}return payload}};var createTrustedIssuerVerifier=(config)=>{const verifyToken=createTrustedGatewayTokenVerifier(config);return async(request)=>{const payload=await verifyToken(request.token);if(payload.purpose!==undefined){throw new GatewayCallerAuthError("authorization_denied","Enrollment tokens cannot authorize invocation")}const identity={audience:audiences(payload.aud),binding:requiredString(payload,"binding"),expiresAt:(payload.exp??0)*1000,installationId:requiredString(payload,"installation_id"),issuer:requiredString(payload,"iss"),organizationId:requiredString(payload,"org_id"),principalKind:principalKind(requiredString(payload,"principal_kind")),requestId:requiredString(payload,"jti"),scopes:requiredString(payload,"scope").split(" ").filter(Boolean),subject:requiredString(payload,"sub")};if(identity.organizationId!==request.organizationId||identity.binding!==request.binding){throw new GatewayCallerAuthError("authorization_denied","Gateway caller is bound to another capability")}if(!await config.authorizeConnection({binding:identity.binding,connectionId:identity.installationId,issuer:identity.issuer,organizationId:identity.organizationId,scopes:identity.scopes,token:request.token})){throw new GatewayCallerAuthError("authorization_denied","Gateway connection or capability grant is not active")}if(!await config.replayStore.consume(`${identity.issuer}\x00${identity.requestId}`,identity.expiresAt)){throw new GatewayCallerAuthError("replay_detected","Gateway caller request was already consumed")}return identity}};var createGatewayCallerVerifier=(config)=>{if(config.trustedIssuers.length===0){throw new TypeError("At least one trusted CI issuer is required")}const verifiers=new Map;for(const trusted of config.trustedIssuers){if(verifiers.has(trusted.issuer)){throw new TypeError("Trusted CI issuers must be unique")}verifiers.set(trusted.issuer,createTrustedIssuerVerifier({...config,...trusted}))}return async(request)=>{let issuer;try{issuer=decodeJwt(request.token).iss}catch{}const verify2=issuer===undefined?undefined:verifiers.get(issuer);if(verify2===undefined){throw new GatewayCallerAuthError("unauthenticated","Gateway caller issuer is not trusted")}return await verify2(request)}};var createGatewaySetupVerifier=(credentials)=>async(credential)=>{if(credential.length===0){return false}const digest=await crypto.subtle.digest("SHA-256",new TextEncoder().encode(credential));const supplied=new Uint8Array(digest);let accepted=0;for(const expected of await credentials()){if(expected.length===0){continue}const candidate=new Uint8Array(await crypto.subtle.digest("SHA-256",new TextEncoder().encode(expected)));let difference=0;for(const[index,value]of supplied.entries()){difference|=value^(candidate[index]??0)}accepted|=Number(difference===0)}return accepted===1};var validExternalSubject=(subject)=>subject!==undefined&&subject.issuer.length>0&&subject.subject.length>0;var authorizeGatewayInvocation=(input)=>{if(!input.requirement.principalKinds.includes(input.caller.principalKind)){throw new GatewayCallerAuthError("authorization_denied","The principal kind is not authorized")}const scopes=new Set(input.caller.scopes);if(input.requirement.scopes.some((scope)=>!scopes.has(scope))){throw new GatewayCallerAuthError("authorization_denied","The caller does not have the required scopes")}const hasSubject=validExternalSubject(input.externalAuditSubject);if(input.requirement.delegatedSubject==="required"&&!hasSubject){throw new GatewayCallerAuthError("authorization_denied","An external audit subject is required")}if(input.requirement.delegatedSubject==="forbidden"&&input.externalAuditSubject!==undefined){throw new GatewayCallerAuthError("authorization_denied","An external audit subject is not allowed")}return hasSubject&&input.externalAuditSubject!==undefined?{caller:input.caller,correlationId:input.correlationId,externalAuditSubject:input.externalAuditSubject,organizationId:input.caller.organizationId}:{caller:input.caller,correlationId:input.correlationId,organizationId:input.caller.organizationId}};var exports_connection_authority={};__export(exports_connection_authority,{createGatewayConnectionAuthentication:()=>createGatewayConnectionAuthentication});var createGatewayConnectionAuthentication=(config)=>{const verifySetupCredential=createGatewaySetupVerifier(config.setupCredentials);const fetch=config.fetch??globalThis.fetch;const validate=async(input)=>{const trusted=config.trustedIssuers.find((candidate)=>candidate.issuer===input.issuer);if(trusted===undefined){return false}let response;try{response=await fetch(new URL("/gateway-caller/validate",trusted.tenantUrl),{cache:"no-store",headers:{accept:"application/json",authorization:`Bearer ${input.token}`},method:"POST",redirect:"manual",signal:AbortSignal.timeout(config.validationTimeoutMs??1e4)})}catch{throw new GatewayCallerAuthError("temporarily_unavailable","CI connection authority is unavailable")}if(response.status===401||response.status===403){return false}if(response.status!==200){throw new GatewayCallerAuthError("temporarily_unavailable","CI connection authority is unavailable")}try{const body=await response.json();if(typeof body==="object"&&body!==null&&"active"in body&&body.active===true){return true}throw new GatewayCallerAuthError("temporarily_unavailable","CI connection authority returned an invalid response")}catch{throw new GatewayCallerAuthError("temporarily_unavailable","CI connection authority returned an invalid response")}};const verifyCaller=createGatewayCallerVerifier({...config,authorizeConnection:async(input)=>{let enrolled;try{enrolled=await config.grants.has(input)}catch{throw new GatewayCallerAuthError("temporarily_unavailable","Gateway connection storage is unavailable")}if(!enrolled){return false}return await validate(input)}});const verifyEnrollment=createGatewayCallerVerifier({...config,authorizeConnection:async(input)=>input.binding==="connection:discover"&&input.scopes.length===1&&input.scopes[0]==="gateway:discover"&&await validate(input)});const enrollConnection=async({credential,callerToken})=>{if(!await verifySetupCredential(credential)){throw new GatewayCallerAuthError("unauthenticated","The setup credential is invalid")}let organizationId;try{organizationId=decodeJwt(callerToken).org_id}catch{}if(typeof organizationId!=="string"||organizationId.length===0){throw new GatewayCallerAuthError("unauthenticated","A signed discovery token is required")}const identity=await verifyEnrollment({binding:"connection:discover",organizationId,token:callerToken});try{await config.grants.put({connectionId:identity.installationId,issuer:identity.issuer,organizationId:identity.organizationId})}catch{throw new GatewayCallerAuthError("temporarily_unavailable","Gateway connection storage is unavailable")}};return{enrollConnection,verifyCaller,verifySetupCredential}};var exports_package_enrollment={};__export(exports_package_enrollment,{createGatewayPackageEnrollment:()=>createGatewayPackageEnrollment});var claim=(payload,name)=>{const value=payload[name];if(typeof value!=="string"||value.length===0||value.length>1024){throw new GatewayCallerAuthError("unauthenticated",`Enrollment claim ${name} is required`)}return value};var validateClaims=(payload,audience)=>{const now=Date.now()/1000;if(!Number.isSafeInteger(payload.iat)||!Number.isSafeInteger(payload.exp)||payload.iat===undefined||payload.exp===undefined||payload.iat>now||payload.exp<=now||payload.exp-payload.iat<1||payload.exp-payload.iat>300||payload.aud!==audience||payload.purpose!=="package_gateway_enrollment"||payload.binding!=="connection:enroll"||payload.scope!=="gateway:enroll"){throw new GatewayCallerAuthError("authorization_denied","Enrollment token must have exact purpose, audience, scope and bounded lifetime")}return payload.exp*1000};var createGatewayPackageEnrollment=(config)=>{if(config.trustedIssuers.length===0||config.allowedPackages.length===0){throw new TypeError("Enrollment requires configured trust and local package policy")}const timeout=config.validationTimeoutMs??1e4;if(!Number.isSafeInteger(timeout)||timeout<1||timeout>30000){throw new TypeError("validationTimeoutMs must be between 1 and 30_000")}const verifiers=new Map(config.trustedIssuers.map((trusted)=>[trusted.issuer,{trusted,verify:createTrustedGatewayTokenVerifier({...trusted,audience:config.audience,clockToleranceSeconds:0,fetch:config.fetch??globalThis.fetch})}]));if(verifiers.size!==config.trustedIssuers.length){throw new TypeError("Trusted CI issuers must be unique")}const fetch=config.fetch??globalThis.fetch;const enrollPackageConnection=async({callerToken,manifestHash})=>{let issuer;try{issuer=decodeJwt(callerToken).iss}catch{}const verifier=issuer===undefined?undefined:verifiers.get(issuer);if(verifier===undefined){throw new GatewayCallerAuthError("unauthenticated","Enrollment issuer is not trusted")}const payload=await verifier.verify(callerToken);const expiresAt=validateClaims(payload,config.audience);const grant={audience:config.audience,connectionId:claim(payload,"installation_id"),gatewayFqn:claim(payload,"gateway_fqn"),issuer:claim(payload,"iss"),manifestHash:claim(payload,"manifest_hash"),organizationId:claim(payload,"org_id"),packageFqn:claim(payload,"package_fqn"),packageInstallationId:claim(payload,"package_installation_id")};if(!config.allowedPackages.some((allowed)=>allowed.organizationId===grant.organizationId&&allowed.packageFqn===grant.packageFqn&&allowed.gatewayFqn===grant.gatewayFqn)||grant.manifestHash!==manifestHash){throw new GatewayCallerAuthError("authorization_denied","Enrollment package policy or runtime manifest does not match")}const requestId=`${grant.issuer}\x00${claim(payload,"jti")}`;let response;try{response=await fetch(new URL("/gateway-caller/validate",verifier.trusted.tenantUrl),{headers:{accept:"application/json",authorization:`Bearer ${callerToken}`},method:"POST",redirect:"manual",signal:AbortSignal.timeout(timeout)})}catch{throw new GatewayCallerAuthError("temporarily_unavailable","CI enrollment authority is unavailable")}if(response.status===401||response.status===403){throw new GatewayCallerAuthError("authorization_denied","CI enrollment authority is not active")}if(response.status!==200){throw new GatewayCallerAuthError("temporarily_unavailable","CI enrollment authority is unavailable")}try{const body=await response.json();if(typeof body!=="object"||body===null||!("active"in body)||body.active!==true){throw new Error("Invalid authority response")}}catch{throw new GatewayCallerAuthError("temporarily_unavailable","CI enrollment authority returned an invalid response")}if(expiresAt<=Date.now()){throw new GatewayCallerAuthError("unauthenticated","Enrollment token expired before commit")}try{if(!await config.store.enroll({expiresAt,grant,requestId})){throw new GatewayCallerAuthError("replay_detected","Enrollment token was already consumed")}}catch(error){if(error instanceof GatewayCallerAuthError){throw error}throw new GatewayCallerAuthError("temporarily_unavailable","Gateway enrollment storage is unavailable")}};return{enrollPackageConnection}};var{createGatewayConnectionAuthentication:createGatewayConnectionAuthentication2}=exports_connection_authority;var{authorizeGatewayInvocation:authorizeGatewayInvocation2}=exports_authorization;var{createGatewayCallerVerifier:createGatewayCallerVerifier2,createGatewaySetupVerifier:createGatewaySetupVerifier2,createInMemoryReplayStore:createInMemoryReplayStore2}=exports_caller_verifier;var{createGatewayPackageEnrollment:createGatewayPackageEnrollment2}=exports_package_enrollment;export{createInMemoryReplayStore2 as createInMemoryReplayStore,createGatewaySetupVerifier2 as createGatewaySetupVerifier,createGatewayPackageEnrollment2 as createGatewayPackageEnrollment,createGatewayConnectionAuthentication2 as createGatewayConnectionAuthentication,createGatewayCallerVerifier2 as createGatewayCallerVerifier,authorizeGatewayInvocation2 as authorizeGatewayInvocation};
|