@codemem/mcp 0.33.0 → 0.34.0

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/dist/http.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"http.js","names":["Address6","MemoryStore","Buffer","isIPv62","#clients","#codes","#deleteExpiredCodes","#tokensByHash","#tokenHashKey","#deleteInactiveTokens","#grantsById","#grantIdsByRefreshHash","#refreshHashesByGrantId","#deleteInactiveGrants","#deleteGrantRefreshHashIndexEntries","#records","#deleteExpired","#clientsStore","#codeStore","#tokenStore","#refreshTokenStore","#publicMcpUrl","#resourceServerUrl","#oidc","#now"],"sources":["../../../node_modules/.pnpm/ip-address@10.1.1/node_modules/ip-address/dist/common.js","../../../node_modules/.pnpm/ip-address@10.1.1/node_modules/ip-address/dist/v4/constants.js","../../../node_modules/.pnpm/ip-address@10.1.1/node_modules/ip-address/dist/address-error.js","../../../node_modules/.pnpm/ip-address@10.1.1/node_modules/ip-address/dist/ipv4.js","../../../node_modules/.pnpm/ip-address@10.1.1/node_modules/ip-address/dist/v6/constants.js","../../../node_modules/.pnpm/ip-address@10.1.1/node_modules/ip-address/dist/v6/helpers.js","../../../node_modules/.pnpm/ip-address@10.1.1/node_modules/ip-address/dist/v6/regular-expressions.js","../../../node_modules/.pnpm/ip-address@10.1.1/node_modules/ip-address/dist/ipv6.js","../../../node_modules/.pnpm/ip-address@10.1.1/node_modules/ip-address/dist/ip-address.js","../../../node_modules/.pnpm/express-rate-limit@8.5.2_express@5.2.1/node_modules/express-rate-limit/dist/index.mjs","../src/audit.ts","../src/oauth.ts","../src/oidc.ts","../src/provider.ts","../src/http.ts"],"sourcesContent":["\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.isInSubnet = isInSubnet;\nexports.isCorrect = isCorrect;\nexports.numberToPaddedHex = numberToPaddedHex;\nexports.stringToPaddedHex = stringToPaddedHex;\nexports.testBit = testBit;\nfunction isInSubnet(address) {\n if (this.subnetMask < address.subnetMask) {\n return false;\n }\n if (this.mask(address.subnetMask) === address.mask()) {\n return true;\n }\n return false;\n}\nfunction isCorrect(defaultBits) {\n return function () {\n if (this.addressMinusSuffix !== this.correctForm()) {\n return false;\n }\n if (this.subnetMask === defaultBits && !this.parsedSubnet) {\n return true;\n }\n return this.parsedSubnet === String(this.subnetMask);\n };\n}\nfunction numberToPaddedHex(number) {\n return number.toString(16).padStart(2, '0');\n}\nfunction stringToPaddedHex(numberString) {\n return numberToPaddedHex(parseInt(numberString, 10));\n}\n/**\n * @param binaryValue Binary representation of a value (e.g. `10`)\n * @param position Byte position, where 0 is the least significant bit\n */\nfunction testBit(binaryValue, position) {\n const { length } = binaryValue;\n if (position > length) {\n return false;\n }\n const positionInString = length - position;\n return binaryValue.substring(positionInString, positionInString + 1) === '1';\n}\n//# sourceMappingURL=common.js.map","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.RE_SUBNET_STRING = exports.RE_ADDRESS = exports.GROUPS = exports.BITS = void 0;\nexports.BITS = 32;\nexports.GROUPS = 4;\nexports.RE_ADDRESS = /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/g;\nexports.RE_SUBNET_STRING = /\\/\\d{1,2}$/;\n//# sourceMappingURL=constants.js.map","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.AddressError = void 0;\nclass AddressError extends Error {\n constructor(message, parseMessage) {\n super(message);\n this.name = 'AddressError';\n this.parseMessage = parseMessage;\n }\n}\nexports.AddressError = AddressError;\n//# sourceMappingURL=address-error.js.map","\"use strict\";\n/* eslint-disable no-param-reassign */\nvar __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n var desc = Object.getOwnPropertyDescriptor(m, k);\n if (!desc || (\"get\" in desc ? !m.__esModule : desc.writable || desc.configurable)) {\n desc = { enumerable: true, get: function() { return m[k]; } };\n }\n Object.defineProperty(o, k2, desc);\n}) : (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n o[k2] = m[k];\n}));\nvar __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\n}) : function(o, v) {\n o[\"default\"] = v;\n});\nvar __importStar = (this && this.__importStar) || function (mod) {\n if (mod && mod.__esModule) return mod;\n var result = {};\n if (mod != null) for (var k in mod) if (k !== \"default\" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\n __setModuleDefault(result, mod);\n return result;\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.Address4 = void 0;\nconst common = __importStar(require(\"./common\"));\nconst constants = __importStar(require(\"./v4/constants\"));\nconst address_error_1 = require(\"./address-error\");\n/**\n * Represents an IPv4 address\n * @class Address4\n * @param {string} address - An IPv4 address string\n */\nclass Address4 {\n constructor(address) {\n this.groups = constants.GROUPS;\n this.parsedAddress = [];\n this.parsedSubnet = '';\n this.subnet = '/32';\n this.subnetMask = 32;\n this.v4 = true;\n /**\n * Returns true if the address is correct, false otherwise\n * @memberof Address4\n * @instance\n * @returns {Boolean}\n */\n this.isCorrect = common.isCorrect(constants.BITS);\n /**\n * Returns true if the given address is in the subnet of the current address\n * @memberof Address4\n * @instance\n * @returns {boolean}\n */\n this.isInSubnet = common.isInSubnet;\n this.address = address;\n const subnet = constants.RE_SUBNET_STRING.exec(address);\n if (subnet) {\n this.parsedSubnet = subnet[0].replace('/', '');\n this.subnetMask = parseInt(this.parsedSubnet, 10);\n this.subnet = `/${this.subnetMask}`;\n if (this.subnetMask < 0 || this.subnetMask > constants.BITS) {\n throw new address_error_1.AddressError('Invalid subnet mask.');\n }\n address = address.replace(constants.RE_SUBNET_STRING, '');\n }\n this.addressMinusSuffix = address;\n this.parsedAddress = this.parse(address);\n }\n static isValid(address) {\n try {\n // eslint-disable-next-line no-new\n new Address4(address);\n return true;\n }\n catch (e) {\n return false;\n }\n }\n /*\n * Parses a v4 address\n */\n parse(address) {\n const groups = address.split('.');\n if (!address.match(constants.RE_ADDRESS)) {\n throw new address_error_1.AddressError('Invalid IPv4 address.');\n }\n return groups;\n }\n /**\n * Returns the correct form of an address\n * @memberof Address4\n * @instance\n * @returns {String}\n */\n correctForm() {\n return this.parsedAddress.map((part) => parseInt(part, 10)).join('.');\n }\n /**\n * Converts a hex string to an IPv4 address object\n * @memberof Address4\n * @static\n * @param {string} hex - a hex string to convert\n * @returns {Address4}\n */\n static fromHex(hex) {\n const padded = hex.replace(/:/g, '').padStart(8, '0');\n const groups = [];\n let i;\n for (i = 0; i < 8; i += 2) {\n const h = padded.slice(i, i + 2);\n groups.push(parseInt(h, 16));\n }\n return new Address4(groups.join('.'));\n }\n /**\n * Converts an integer into a IPv4 address object\n * @memberof Address4\n * @static\n * @param {integer} integer - a number to convert\n * @returns {Address4}\n */\n static fromInteger(integer) {\n return Address4.fromHex(integer.toString(16));\n }\n /**\n * Return an address from in-addr.arpa form\n * @memberof Address4\n * @static\n * @param {string} arpaFormAddress - an 'in-addr.arpa' form ipv4 address\n * @returns {Adress4}\n * @example\n * var address = Address4.fromArpa(42.2.0.192.in-addr.arpa.)\n * address.correctForm(); // '192.0.2.42'\n */\n static fromArpa(arpaFormAddress) {\n // remove ending \".in-addr.arpa.\" or just \".\"\n const leader = arpaFormAddress.replace(/(\\.in-addr\\.arpa)?\\.$/, '');\n const address = leader.split('.').reverse().join('.');\n return new Address4(address);\n }\n /**\n * Converts an IPv4 address object to a hex string\n * @memberof Address4\n * @instance\n * @returns {String}\n */\n toHex() {\n return this.parsedAddress.map((part) => common.stringToPaddedHex(part)).join(':');\n }\n /**\n * Converts an IPv4 address object to an array of bytes\n * @memberof Address4\n * @instance\n * @returns {Array}\n */\n toArray() {\n return this.parsedAddress.map((part) => parseInt(part, 10));\n }\n /**\n * Converts an IPv4 address object to an IPv6 address group\n * @memberof Address4\n * @instance\n * @returns {String}\n */\n toGroup6() {\n const output = [];\n let i;\n for (i = 0; i < constants.GROUPS; i += 2) {\n output.push(`${common.stringToPaddedHex(this.parsedAddress[i])}${common.stringToPaddedHex(this.parsedAddress[i + 1])}`);\n }\n return output.join(':');\n }\n /**\n * Returns the address as a `bigint`\n * @memberof Address4\n * @instance\n * @returns {bigint}\n */\n bigInt() {\n return BigInt(`0x${this.parsedAddress.map((n) => common.stringToPaddedHex(n)).join('')}`);\n }\n /**\n * Helper function getting start address.\n * @memberof Address4\n * @instance\n * @returns {bigint}\n */\n _startAddress() {\n return BigInt(`0b${this.mask() + '0'.repeat(constants.BITS - this.subnetMask)}`);\n }\n /**\n * The first address in the range given by this address' subnet.\n * Often referred to as the Network Address.\n * @memberof Address4\n * @instance\n * @returns {Address4}\n */\n startAddress() {\n return Address4.fromBigInt(this._startAddress());\n }\n /**\n * The first host address in the range given by this address's subnet ie\n * the first address after the Network Address\n * @memberof Address4\n * @instance\n * @returns {Address4}\n */\n startAddressExclusive() {\n const adjust = BigInt('1');\n return Address4.fromBigInt(this._startAddress() + adjust);\n }\n /**\n * Helper function getting end address.\n * @memberof Address4\n * @instance\n * @returns {bigint}\n */\n _endAddress() {\n return BigInt(`0b${this.mask() + '1'.repeat(constants.BITS - this.subnetMask)}`);\n }\n /**\n * The last address in the range given by this address' subnet\n * Often referred to as the Broadcast\n * @memberof Address4\n * @instance\n * @returns {Address4}\n */\n endAddress() {\n return Address4.fromBigInt(this._endAddress());\n }\n /**\n * The last host address in the range given by this address's subnet ie\n * the last address prior to the Broadcast Address\n * @memberof Address4\n * @instance\n * @returns {Address4}\n */\n endAddressExclusive() {\n const adjust = BigInt('1');\n return Address4.fromBigInt(this._endAddress() - adjust);\n }\n /**\n * Converts a BigInt to a v4 address object\n * @memberof Address4\n * @static\n * @param {bigint} bigInt - a BigInt to convert\n * @returns {Address4}\n */\n static fromBigInt(bigInt) {\n return Address4.fromHex(bigInt.toString(16));\n }\n /**\n * Convert a byte array to an Address4 object\n * @memberof Address4\n * @static\n * @param {Array<number>} bytes - an array of 4 bytes (0-255)\n * @returns {Address4}\n */\n static fromByteArray(bytes) {\n if (bytes.length !== 4) {\n throw new address_error_1.AddressError('IPv4 addresses require exactly 4 bytes');\n }\n // Validate that all bytes are within valid range (0-255)\n for (let i = 0; i < bytes.length; i++) {\n if (!Number.isInteger(bytes[i]) || bytes[i] < 0 || bytes[i] > 255) {\n throw new address_error_1.AddressError('All bytes must be integers between 0 and 255');\n }\n }\n return this.fromUnsignedByteArray(bytes);\n }\n /**\n * Convert an unsigned byte array to an Address4 object\n * @memberof Address4\n * @static\n * @param {Array<number>} bytes - an array of 4 unsigned bytes (0-255)\n * @returns {Address4}\n */\n static fromUnsignedByteArray(bytes) {\n if (bytes.length !== 4) {\n throw new address_error_1.AddressError('IPv4 addresses require exactly 4 bytes');\n }\n const address = bytes.join('.');\n return new Address4(address);\n }\n /**\n * Returns the first n bits of the address, defaulting to the\n * subnet mask\n * @memberof Address4\n * @instance\n * @returns {String}\n */\n mask(mask) {\n if (mask === undefined) {\n mask = this.subnetMask;\n }\n return this.getBitsBase2(0, mask);\n }\n /**\n * Returns the bits in the given range as a base-2 string\n * @memberof Address4\n * @instance\n * @returns {string}\n */\n getBitsBase2(start, end) {\n return this.binaryZeroPad().slice(start, end);\n }\n /**\n * Return the reversed ip6.arpa form of the address\n * @memberof Address4\n * @param {Object} options\n * @param {boolean} options.omitSuffix - omit the \"in-addr.arpa\" suffix\n * @instance\n * @returns {String}\n */\n reverseForm(options) {\n if (!options) {\n options = {};\n }\n const reversed = this.correctForm().split('.').reverse().join('.');\n if (options.omitSuffix) {\n return reversed;\n }\n return `${reversed}.in-addr.arpa.`;\n }\n /**\n * Returns true if the given address is a multicast address\n * @memberof Address4\n * @instance\n * @returns {boolean}\n */\n isMulticast() {\n return this.isInSubnet(new Address4('224.0.0.0/4'));\n }\n /**\n * Returns a zero-padded base-2 string representation of the address\n * @memberof Address4\n * @instance\n * @returns {string}\n */\n binaryZeroPad() {\n return this.bigInt().toString(2).padStart(constants.BITS, '0');\n }\n /**\n * Groups an IPv4 address for inclusion at the end of an IPv6 address\n * @returns {String}\n */\n groupForV6() {\n const segments = this.parsedAddress;\n return this.address.replace(constants.RE_ADDRESS, `<span class=\"hover-group group-v4 group-6\">${segments\n .slice(0, 2)\n .join('.')}</span>.<span class=\"hover-group group-v4 group-7\">${segments\n .slice(2, 4)\n .join('.')}</span>`);\n }\n}\nexports.Address4 = Address4;\n//# sourceMappingURL=ipv4.js.map","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.RE_URL_WITH_PORT = exports.RE_URL = exports.RE_ZONE_STRING = exports.RE_SUBNET_STRING = exports.RE_BAD_ADDRESS = exports.RE_BAD_CHARACTERS = exports.TYPES = exports.SCOPES = exports.GROUPS = exports.BITS = void 0;\nexports.BITS = 128;\nexports.GROUPS = 8;\n/**\n * Represents IPv6 address scopes\n * @memberof Address6\n * @static\n */\nexports.SCOPES = {\n 0: 'Reserved',\n 1: 'Interface local',\n 2: 'Link local',\n 4: 'Admin local',\n 5: 'Site local',\n 8: 'Organization local',\n 14: 'Global',\n 15: 'Reserved',\n};\n/**\n * Represents IPv6 address types\n * @memberof Address6\n * @static\n */\nexports.TYPES = {\n 'ff01::1/128': 'Multicast (All nodes on this interface)',\n 'ff01::2/128': 'Multicast (All routers on this interface)',\n 'ff02::1/128': 'Multicast (All nodes on this link)',\n 'ff02::2/128': 'Multicast (All routers on this link)',\n 'ff05::2/128': 'Multicast (All routers in this site)',\n 'ff02::5/128': 'Multicast (OSPFv3 AllSPF routers)',\n 'ff02::6/128': 'Multicast (OSPFv3 AllDR routers)',\n 'ff02::9/128': 'Multicast (RIP routers)',\n 'ff02::a/128': 'Multicast (EIGRP routers)',\n 'ff02::d/128': 'Multicast (PIM routers)',\n 'ff02::16/128': 'Multicast (MLDv2 reports)',\n 'ff01::fb/128': 'Multicast (mDNSv6)',\n 'ff02::fb/128': 'Multicast (mDNSv6)',\n 'ff05::fb/128': 'Multicast (mDNSv6)',\n 'ff02::1:2/128': 'Multicast (All DHCP servers and relay agents on this link)',\n 'ff05::1:2/128': 'Multicast (All DHCP servers and relay agents in this site)',\n 'ff02::1:3/128': 'Multicast (All DHCP servers on this link)',\n 'ff05::1:3/128': 'Multicast (All DHCP servers in this site)',\n '::/128': 'Unspecified',\n '::1/128': 'Loopback',\n 'ff00::/8': 'Multicast',\n 'fe80::/10': 'Link-local unicast',\n};\n/**\n * A regular expression that matches bad characters in an IPv6 address\n * @memberof Address6\n * @static\n */\nexports.RE_BAD_CHARACTERS = /([^0-9a-f:/%])/gi;\n/**\n * A regular expression that matches an incorrect IPv6 address\n * @memberof Address6\n * @static\n */\nexports.RE_BAD_ADDRESS = /([0-9a-f]{5,}|:{3,}|[^:]:$|^:[^:]|\\/$)/gi;\n/**\n * A regular expression that matches an IPv6 subnet\n * @memberof Address6\n * @static\n */\nexports.RE_SUBNET_STRING = /\\/\\d{1,3}(?=%|$)/;\n/**\n * A regular expression that matches an IPv6 zone\n * @memberof Address6\n * @static\n */\nexports.RE_ZONE_STRING = /%.*$/;\nexports.RE_URL = /^\\[{0,1}([0-9a-f:]+)\\]{0,1}/;\nexports.RE_URL_WITH_PORT = /\\[([0-9a-f:]+)\\]:([0-9]{1,5})/;\n//# sourceMappingURL=constants.js.map","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.escapeHtml = escapeHtml;\nexports.spanAllZeroes = spanAllZeroes;\nexports.spanAll = spanAll;\nexports.spanLeadingZeroes = spanLeadingZeroes;\nexports.simpleGroup = simpleGroup;\nfunction escapeHtml(s) {\n return s\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#39;');\n}\n/**\n * @returns {String} the string with all zeroes contained in a <span>\n */\nfunction spanAllZeroes(s) {\n return escapeHtml(s).replace(/(0+)/g, '<span class=\"zero\">$1</span>');\n}\n/**\n * @returns {String} the string with each character contained in a <span>\n */\nfunction spanAll(s, offset = 0) {\n const letters = s.split('');\n return letters\n .map((n, i) => `<span class=\"digit value-${escapeHtml(n)} position-${i + offset}\">${spanAllZeroes(n)}</span>`)\n .join('');\n}\nfunction spanLeadingZeroesSimple(group) {\n return escapeHtml(group).replace(/^(0+)/, '<span class=\"zero\">$1</span>');\n}\n/**\n * @returns {String} the string with leading zeroes contained in a <span>\n */\nfunction spanLeadingZeroes(address) {\n const groups = address.split(':');\n return groups.map((g) => spanLeadingZeroesSimple(g)).join(':');\n}\n/**\n * Groups an address\n * @returns {String} a grouped address\n */\nfunction simpleGroup(addressString, offset = 0) {\n const groups = addressString.split(':');\n return groups.map((g, i) => {\n if (/group-v4/.test(g)) {\n return g;\n }\n return `<span class=\"hover-group group-${i + offset}\">${spanLeadingZeroesSimple(g)}</span>`;\n });\n}\n//# sourceMappingURL=helpers.js.map","\"use strict\";\nvar __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n var desc = Object.getOwnPropertyDescriptor(m, k);\n if (!desc || (\"get\" in desc ? !m.__esModule : desc.writable || desc.configurable)) {\n desc = { enumerable: true, get: function() { return m[k]; } };\n }\n Object.defineProperty(o, k2, desc);\n}) : (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n o[k2] = m[k];\n}));\nvar __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\n}) : function(o, v) {\n o[\"default\"] = v;\n});\nvar __importStar = (this && this.__importStar) || function (mod) {\n if (mod && mod.__esModule) return mod;\n var result = {};\n if (mod != null) for (var k in mod) if (k !== \"default\" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\n __setModuleDefault(result, mod);\n return result;\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.ADDRESS_BOUNDARY = void 0;\nexports.groupPossibilities = groupPossibilities;\nexports.padGroup = padGroup;\nexports.simpleRegularExpression = simpleRegularExpression;\nexports.possibleElisions = possibleElisions;\nconst v6 = __importStar(require(\"./constants\"));\nfunction groupPossibilities(possibilities) {\n return `(${possibilities.join('|')})`;\n}\nfunction padGroup(group) {\n if (group.length < 4) {\n return `0{0,${4 - group.length}}${group}`;\n }\n return group;\n}\nexports.ADDRESS_BOUNDARY = '[^A-Fa-f0-9:]';\nfunction simpleRegularExpression(groups) {\n const zeroIndexes = [];\n groups.forEach((group, i) => {\n const groupInteger = parseInt(group, 16);\n if (groupInteger === 0) {\n zeroIndexes.push(i);\n }\n });\n // You can technically elide a single 0, this creates the regular expressions\n // to match that eventuality\n const possibilities = zeroIndexes.map((zeroIndex) => groups\n .map((group, i) => {\n if (i === zeroIndex) {\n const elision = i === 0 || i === v6.GROUPS - 1 ? ':' : '';\n return groupPossibilities([padGroup(group), elision]);\n }\n return padGroup(group);\n })\n .join(':'));\n // The simplest case\n possibilities.push(groups.map(padGroup).join(':'));\n return groupPossibilities(possibilities);\n}\nfunction possibleElisions(elidedGroups, moreLeft, moreRight) {\n const left = moreLeft ? '' : ':';\n const right = moreRight ? '' : ':';\n const possibilities = [];\n // 1. elision of everything (::)\n if (!moreLeft && !moreRight) {\n possibilities.push('::');\n }\n // 2. complete elision of the middle\n if (moreLeft && moreRight) {\n possibilities.push('');\n }\n if ((moreRight && !moreLeft) || (!moreRight && moreLeft)) {\n // 3. complete elision of one side\n possibilities.push(':');\n }\n // 4. elision from the left side\n possibilities.push(`${left}(:0{1,4}){1,${elidedGroups - 1}}`);\n // 5. elision from the right side\n possibilities.push(`(0{1,4}:){1,${elidedGroups - 1}}${right}`);\n // 6. no elision\n possibilities.push(`(0{1,4}:){${elidedGroups - 1}}0{1,4}`);\n // 7. elision (including sloppy elision) from the middle\n for (let groups = 1; groups < elidedGroups - 1; groups++) {\n for (let position = 1; position < elidedGroups - groups; position++) {\n possibilities.push(`(0{1,4}:){${position}}:(0{1,4}:){${elidedGroups - position - groups - 1}}0{1,4}`);\n }\n }\n return groupPossibilities(possibilities);\n}\n//# sourceMappingURL=regular-expressions.js.map","\"use strict\";\n/* eslint-disable prefer-destructuring */\n/* eslint-disable no-param-reassign */\nvar __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n var desc = Object.getOwnPropertyDescriptor(m, k);\n if (!desc || (\"get\" in desc ? !m.__esModule : desc.writable || desc.configurable)) {\n desc = { enumerable: true, get: function() { return m[k]; } };\n }\n Object.defineProperty(o, k2, desc);\n}) : (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n o[k2] = m[k];\n}));\nvar __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\n}) : function(o, v) {\n o[\"default\"] = v;\n});\nvar __importStar = (this && this.__importStar) || function (mod) {\n if (mod && mod.__esModule) return mod;\n var result = {};\n if (mod != null) for (var k in mod) if (k !== \"default\" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\n __setModuleDefault(result, mod);\n return result;\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.Address6 = void 0;\nconst common = __importStar(require(\"./common\"));\nconst constants4 = __importStar(require(\"./v4/constants\"));\nconst constants6 = __importStar(require(\"./v6/constants\"));\nconst helpers = __importStar(require(\"./v6/helpers\"));\nconst ipv4_1 = require(\"./ipv4\");\nconst regular_expressions_1 = require(\"./v6/regular-expressions\");\nconst address_error_1 = require(\"./address-error\");\nconst common_1 = require(\"./common\");\nfunction assert(condition) {\n if (!condition) {\n throw new Error('Assertion failed.');\n }\n}\nfunction addCommas(number) {\n const r = /(\\d+)(\\d{3})/;\n while (r.test(number)) {\n number = number.replace(r, '$1,$2');\n }\n return number;\n}\nfunction spanLeadingZeroes4(n) {\n n = n.replace(/^(0{1,})([1-9]+)$/, '<span class=\"parse-error\">$1</span>$2');\n n = n.replace(/^(0{1,})(0)$/, '<span class=\"parse-error\">$1</span>$2');\n return n;\n}\n/*\n * A helper function to compact an array\n */\nfunction compact(address, slice) {\n const s1 = [];\n const s2 = [];\n let i;\n for (i = 0; i < address.length; i++) {\n if (i < slice[0]) {\n s1.push(address[i]);\n }\n else if (i > slice[1]) {\n s2.push(address[i]);\n }\n }\n return s1.concat(['compact']).concat(s2);\n}\nfunction paddedHex(octet) {\n return parseInt(octet, 16).toString(16).padStart(4, '0');\n}\nfunction unsignByte(b) {\n // eslint-disable-next-line no-bitwise\n return b & 0xff;\n}\n/**\n * Represents an IPv6 address\n * @class Address6\n * @param {string} address - An IPv6 address string\n * @param {number} [groups=8] - How many octets to parse\n * @example\n * var address = new Address6('2001::/32');\n */\nclass Address6 {\n constructor(address, optionalGroups) {\n this.addressMinusSuffix = '';\n this.parsedSubnet = '';\n this.subnet = '/128';\n this.subnetMask = 128;\n this.v4 = false;\n this.zone = '';\n // #region Attributes\n /**\n * Returns true if the given address is in the subnet of the current address\n * @memberof Address6\n * @instance\n * @returns {boolean}\n */\n this.isInSubnet = common.isInSubnet;\n /**\n * Returns true if the address is correct, false otherwise\n * @memberof Address6\n * @instance\n * @returns {boolean}\n */\n this.isCorrect = common.isCorrect(constants6.BITS);\n if (optionalGroups === undefined) {\n this.groups = constants6.GROUPS;\n }\n else {\n this.groups = optionalGroups;\n }\n this.address = address;\n const subnet = constants6.RE_SUBNET_STRING.exec(address);\n if (subnet) {\n this.parsedSubnet = subnet[0].replace('/', '');\n this.subnetMask = parseInt(this.parsedSubnet, 10);\n this.subnet = `/${this.subnetMask}`;\n if (Number.isNaN(this.subnetMask) ||\n this.subnetMask < 0 ||\n this.subnetMask > constants6.BITS) {\n throw new address_error_1.AddressError('Invalid subnet mask.');\n }\n address = address.replace(constants6.RE_SUBNET_STRING, '');\n }\n else if (/\\//.test(address)) {\n throw new address_error_1.AddressError('Invalid subnet mask.');\n }\n const zone = constants6.RE_ZONE_STRING.exec(address);\n if (zone) {\n this.zone = zone[0];\n address = address.replace(constants6.RE_ZONE_STRING, '');\n }\n this.addressMinusSuffix = address;\n this.parsedAddress = this.parse(this.addressMinusSuffix);\n }\n static isValid(address) {\n try {\n // eslint-disable-next-line no-new\n new Address6(address);\n return true;\n }\n catch (e) {\n return false;\n }\n }\n /**\n * Convert a BigInt to a v6 address object\n * @memberof Address6\n * @static\n * @param {bigint} bigInt - a BigInt to convert\n * @returns {Address6}\n * @example\n * var bigInt = BigInt('1000000000000');\n * var address = Address6.fromBigInt(bigInt);\n * address.correctForm(); // '::e8:d4a5:1000'\n */\n static fromBigInt(bigInt) {\n const hex = bigInt.toString(16).padStart(32, '0');\n const groups = [];\n let i;\n for (i = 0; i < constants6.GROUPS; i++) {\n groups.push(hex.slice(i * 4, (i + 1) * 4));\n }\n return new Address6(groups.join(':'));\n }\n /**\n * Convert a URL (with optional port number) to an address object\n * @memberof Address6\n * @static\n * @param {string} url - a URL with optional port number\n * @example\n * var addressAndPort = Address6.fromURL('http://[ffff::]:8080/foo/');\n * addressAndPort.address.correctForm(); // 'ffff::'\n * addressAndPort.port; // 8080\n */\n static fromURL(url) {\n let host;\n let port = null;\n let result;\n // If we have brackets parse them and find a port\n if (url.indexOf('[') !== -1 && url.indexOf(']:') !== -1) {\n result = constants6.RE_URL_WITH_PORT.exec(url);\n if (result === null) {\n return {\n error: 'failed to parse address with port',\n address: null,\n port: null,\n };\n }\n host = result[1];\n port = result[2];\n // If there's a URL extract the address\n }\n else if (url.indexOf('/') !== -1) {\n // Remove the protocol prefix\n url = url.replace(/^[a-z0-9]+:\\/\\//, '');\n // Parse the address\n result = constants6.RE_URL.exec(url);\n if (result === null) {\n return {\n error: 'failed to parse address from URL',\n address: null,\n port: null,\n };\n }\n host = result[1];\n // Otherwise just assign the URL to the host and let the library parse it\n }\n else {\n host = url;\n }\n // If there's a port convert it to an integer\n if (port) {\n port = parseInt(port, 10);\n // squelch out of range ports\n if (port < 0 || port > 65536) {\n port = null;\n }\n }\n else {\n // Standardize `undefined` to `null`\n port = null;\n }\n return {\n address: new Address6(host),\n port,\n };\n }\n /**\n * Create an IPv6-mapped address given an IPv4 address\n * @memberof Address6\n * @static\n * @param {string} address - An IPv4 address string\n * @returns {Address6}\n * @example\n * var address = Address6.fromAddress4('192.168.0.1');\n * address.correctForm(); // '::ffff:c0a8:1'\n * address.to4in6(); // '::ffff:192.168.0.1'\n */\n static fromAddress4(address) {\n const address4 = new ipv4_1.Address4(address);\n const mask6 = constants6.BITS - (constants4.BITS - address4.subnetMask);\n return new Address6(`::ffff:${address4.correctForm()}/${mask6}`);\n }\n /**\n * Return an address from ip6.arpa form\n * @memberof Address6\n * @static\n * @param {string} arpaFormAddress - an 'ip6.arpa' form address\n * @returns {Adress6}\n * @example\n * var address = Address6.fromArpa(e.f.f.f.3.c.2.6.f.f.f.e.6.6.8.e.1.0.6.7.9.4.e.c.0.0.0.0.1.0.0.2.ip6.arpa.)\n * address.correctForm(); // '2001:0:ce49:7601:e866:efff:62c3:fffe'\n */\n static fromArpa(arpaFormAddress) {\n // remove ending \".ip6.arpa.\" or just \".\"\n let address = arpaFormAddress.replace(/(\\.ip6\\.arpa)?\\.$/, '');\n const semicolonAmount = 7;\n // correct ip6.arpa form with ending removed will be 63 characters\n if (address.length !== 63) {\n throw new address_error_1.AddressError(\"Invalid 'ip6.arpa' form.\");\n }\n const parts = address.split('.').reverse();\n for (let i = semicolonAmount; i > 0; i--) {\n const insertIndex = i * 4;\n parts.splice(insertIndex, 0, ':');\n }\n address = parts.join('');\n return new Address6(address);\n }\n /**\n * Return the Microsoft UNC transcription of the address\n * @memberof Address6\n * @instance\n * @returns {String} the Microsoft UNC transcription of the address\n */\n microsoftTranscription() {\n return `${this.correctForm().replace(/:/g, '-')}.ipv6-literal.net`;\n }\n /**\n * Return the first n bits of the address, defaulting to the subnet mask\n * @memberof Address6\n * @instance\n * @param {number} [mask=subnet] - the number of bits to mask\n * @returns {String} the first n bits of the address as a string\n */\n mask(mask = this.subnetMask) {\n return this.getBitsBase2(0, mask);\n }\n /**\n * Return the number of possible subnets of a given size in the address\n * @memberof Address6\n * @instance\n * @param {number} [subnetSize=128] - the subnet size\n * @returns {String}\n */\n // TODO: probably useful to have a numeric version of this too\n possibleSubnets(subnetSize = 128) {\n const availableBits = constants6.BITS - this.subnetMask;\n const subnetBits = Math.abs(subnetSize - constants6.BITS);\n const subnetPowers = availableBits - subnetBits;\n if (subnetPowers < 0) {\n return '0';\n }\n return addCommas((BigInt('2') ** BigInt(subnetPowers)).toString(10));\n }\n /**\n * Helper function getting start address.\n * @memberof Address6\n * @instance\n * @returns {bigint}\n */\n _startAddress() {\n return BigInt(`0b${this.mask() + '0'.repeat(constants6.BITS - this.subnetMask)}`);\n }\n /**\n * The first address in the range given by this address' subnet\n * Often referred to as the Network Address.\n * @memberof Address6\n * @instance\n * @returns {Address6}\n */\n startAddress() {\n return Address6.fromBigInt(this._startAddress());\n }\n /**\n * The first host address in the range given by this address's subnet ie\n * the first address after the Network Address\n * @memberof Address6\n * @instance\n * @returns {Address6}\n */\n startAddressExclusive() {\n const adjust = BigInt('1');\n return Address6.fromBigInt(this._startAddress() + adjust);\n }\n /**\n * Helper function getting end address.\n * @memberof Address6\n * @instance\n * @returns {bigint}\n */\n _endAddress() {\n return BigInt(`0b${this.mask() + '1'.repeat(constants6.BITS - this.subnetMask)}`);\n }\n /**\n * The last address in the range given by this address' subnet\n * Often referred to as the Broadcast\n * @memberof Address6\n * @instance\n * @returns {Address6}\n */\n endAddress() {\n return Address6.fromBigInt(this._endAddress());\n }\n /**\n * The last host address in the range given by this address's subnet ie\n * the last address prior to the Broadcast Address\n * @memberof Address6\n * @instance\n * @returns {Address6}\n */\n endAddressExclusive() {\n const adjust = BigInt('1');\n return Address6.fromBigInt(this._endAddress() - adjust);\n }\n /**\n * Return the scope of the address\n * @memberof Address6\n * @instance\n * @returns {String}\n */\n getScope() {\n let scope = constants6.SCOPES[parseInt(this.getBits(12, 16).toString(10), 10)];\n if (this.getType() === 'Global unicast' && scope !== 'Link local') {\n scope = 'Global';\n }\n return scope || 'Unknown';\n }\n /**\n * Return the type of the address\n * @memberof Address6\n * @instance\n * @returns {String}\n */\n getType() {\n for (const subnet of Object.keys(constants6.TYPES)) {\n if (this.isInSubnet(new Address6(subnet))) {\n return constants6.TYPES[subnet];\n }\n }\n return 'Global unicast';\n }\n /**\n * Return the bits in the given range as a BigInt\n * @memberof Address6\n * @instance\n * @returns {bigint}\n */\n getBits(start, end) {\n return BigInt(`0b${this.getBitsBase2(start, end)}`);\n }\n /**\n * Return the bits in the given range as a base-2 string\n * @memberof Address6\n * @instance\n * @returns {String}\n */\n getBitsBase2(start, end) {\n return this.binaryZeroPad().slice(start, end);\n }\n /**\n * Return the bits in the given range as a base-16 string\n * @memberof Address6\n * @instance\n * @returns {String}\n */\n getBitsBase16(start, end) {\n const length = end - start;\n if (length % 4 !== 0) {\n throw new Error('Length of bits to retrieve must be divisible by four');\n }\n return this.getBits(start, end)\n .toString(16)\n .padStart(length / 4, '0');\n }\n /**\n * Return the bits that are set past the subnet mask length\n * @memberof Address6\n * @instance\n * @returns {String}\n */\n getBitsPastSubnet() {\n return this.getBitsBase2(this.subnetMask, constants6.BITS);\n }\n /**\n * Return the reversed ip6.arpa form of the address\n * @memberof Address6\n * @param {Object} options\n * @param {boolean} options.omitSuffix - omit the \"ip6.arpa\" suffix\n * @instance\n * @returns {String}\n */\n reverseForm(options) {\n if (!options) {\n options = {};\n }\n const characters = Math.floor(this.subnetMask / 4);\n const reversed = this.canonicalForm()\n .replace(/:/g, '')\n .split('')\n .slice(0, characters)\n .reverse()\n .join('.');\n if (characters > 0) {\n if (options.omitSuffix) {\n return reversed;\n }\n return `${reversed}.ip6.arpa.`;\n }\n if (options.omitSuffix) {\n return '';\n }\n return 'ip6.arpa.';\n }\n /**\n * Return the correct form of the address\n * @memberof Address6\n * @instance\n * @returns {String}\n */\n correctForm() {\n let i;\n let groups = [];\n let zeroCounter = 0;\n const zeroes = [];\n for (i = 0; i < this.parsedAddress.length; i++) {\n const value = parseInt(this.parsedAddress[i], 16);\n if (value === 0) {\n zeroCounter++;\n }\n if (value !== 0 && zeroCounter > 0) {\n if (zeroCounter > 1) {\n zeroes.push([i - zeroCounter, i - 1]);\n }\n zeroCounter = 0;\n }\n }\n // Do we end with a string of zeroes?\n if (zeroCounter > 1) {\n zeroes.push([this.parsedAddress.length - zeroCounter, this.parsedAddress.length - 1]);\n }\n const zeroLengths = zeroes.map((n) => n[1] - n[0] + 1);\n if (zeroes.length > 0) {\n const index = zeroLengths.indexOf(Math.max(...zeroLengths));\n groups = compact(this.parsedAddress, zeroes[index]);\n }\n else {\n groups = this.parsedAddress;\n }\n for (i = 0; i < groups.length; i++) {\n if (groups[i] !== 'compact') {\n groups[i] = parseInt(groups[i], 16).toString(16);\n }\n }\n let correct = groups.join(':');\n correct = correct.replace(/^compact$/, '::');\n correct = correct.replace(/(^compact)|(compact$)/, ':');\n correct = correct.replace(/compact/, '');\n return correct;\n }\n /**\n * Return a zero-padded base-2 string representation of the address\n * @memberof Address6\n * @instance\n * @returns {String}\n * @example\n * var address = new Address6('2001:4860:4001:803::1011');\n * address.binaryZeroPad();\n * // '0010000000000001010010000110000001000000000000010000100000000011\n * // 0000000000000000000000000000000000000000000000000001000000010001'\n */\n binaryZeroPad() {\n return this.bigInt().toString(2).padStart(constants6.BITS, '0');\n }\n // TODO: Improve the semantics of this helper function\n parse4in6(address) {\n const groups = address.split(':');\n const lastGroup = groups.slice(-1)[0];\n const address4 = lastGroup.match(constants4.RE_ADDRESS);\n if (address4) {\n this.parsedAddress4 = address4[0];\n this.address4 = new ipv4_1.Address4(this.parsedAddress4);\n for (let i = 0; i < this.address4.groups; i++) {\n if (/^0[0-9]+/.test(this.address4.parsedAddress[i])) {\n // The prefix groups haven't been through the bad-character check\n // yet, so escape them before including in the error HTML.\n const highlighted = this.address4.parsedAddress.map(spanLeadingZeroes4).join('.');\n const prefix = groups.slice(0, -1).map(helpers.escapeHtml).join(':');\n const separator = groups.length > 1 ? ':' : '';\n throw new address_error_1.AddressError(\"IPv4 addresses can't have leading zeroes.\", `${prefix}${separator}${highlighted}`);\n }\n }\n this.v4 = true;\n groups[groups.length - 1] = this.address4.toGroup6();\n address = groups.join(':');\n }\n return address;\n }\n // TODO: Make private?\n parse(address) {\n address = this.parse4in6(address);\n const badCharacters = address.match(constants6.RE_BAD_CHARACTERS);\n if (badCharacters) {\n throw new address_error_1.AddressError(`Bad character${badCharacters.length > 1 ? 's' : ''} detected in address: ${badCharacters.join('')}`, address.replace(constants6.RE_BAD_CHARACTERS, '<span class=\"parse-error\">$1</span>'));\n }\n const badAddress = address.match(constants6.RE_BAD_ADDRESS);\n if (badAddress) {\n throw new address_error_1.AddressError(`Address failed regex: ${badAddress.join('')}`, address.replace(constants6.RE_BAD_ADDRESS, '<span class=\"parse-error\">$1</span>'));\n }\n let groups = [];\n const halves = address.split('::');\n if (halves.length === 2) {\n let first = halves[0].split(':');\n let last = halves[1].split(':');\n if (first.length === 1 && first[0] === '') {\n first = [];\n }\n if (last.length === 1 && last[0] === '') {\n last = [];\n }\n const remaining = this.groups - (first.length + last.length);\n if (!remaining) {\n throw new address_error_1.AddressError('Error parsing groups');\n }\n this.elidedGroups = remaining;\n this.elisionBegin = first.length;\n this.elisionEnd = first.length + this.elidedGroups;\n groups = groups.concat(first);\n for (let i = 0; i < remaining; i++) {\n groups.push('0');\n }\n groups = groups.concat(last);\n }\n else if (halves.length === 1) {\n groups = address.split(':');\n this.elidedGroups = 0;\n }\n else {\n throw new address_error_1.AddressError('Too many :: groups found');\n }\n groups = groups.map((group) => parseInt(group, 16).toString(16));\n if (groups.length !== this.groups) {\n throw new address_error_1.AddressError('Incorrect number of groups found');\n }\n return groups;\n }\n /**\n * Return the canonical form of the address\n * @memberof Address6\n * @instance\n * @returns {String}\n */\n canonicalForm() {\n return this.parsedAddress.map(paddedHex).join(':');\n }\n /**\n * Return the decimal form of the address\n * @memberof Address6\n * @instance\n * @returns {String}\n */\n decimal() {\n return this.parsedAddress.map((n) => parseInt(n, 16).toString(10).padStart(5, '0')).join(':');\n }\n /**\n * Return the address as a BigInt\n * @memberof Address6\n * @instance\n * @returns {bigint}\n */\n bigInt() {\n return BigInt(`0x${this.parsedAddress.map(paddedHex).join('')}`);\n }\n /**\n * Return the last two groups of this address as an IPv4 address string\n * @memberof Address6\n * @instance\n * @returns {Address4}\n * @example\n * var address = new Address6('2001:4860:4001::1825:bf11');\n * address.to4().correctForm(); // '24.37.191.17'\n */\n to4() {\n const binary = this.binaryZeroPad().split('');\n return ipv4_1.Address4.fromHex(BigInt(`0b${binary.slice(96, 128).join('')}`).toString(16));\n }\n /**\n * Return the v4-in-v6 form of the address\n * @memberof Address6\n * @instance\n * @returns {String}\n */\n to4in6() {\n const address4 = this.to4();\n const address6 = new Address6(this.parsedAddress.slice(0, 6).join(':'), 6);\n const correct = address6.correctForm();\n let infix = '';\n if (!/:$/.test(correct)) {\n infix = ':';\n }\n return correct + infix + address4.address;\n }\n /**\n * Return an object containing the Teredo properties of the address\n * @memberof Address6\n * @instance\n * @returns {Object}\n */\n inspectTeredo() {\n /*\n - Bits 0 to 31 are set to the Teredo prefix (normally 2001:0000::/32).\n - Bits 32 to 63 embed the primary IPv4 address of the Teredo server that\n is used.\n - Bits 64 to 79 can be used to define some flags. Currently only the\n higher order bit is used; it is set to 1 if the Teredo client is\n located behind a cone NAT, 0 otherwise. For Microsoft's Windows Vista\n and Windows Server 2008 implementations, more bits are used. In those\n implementations, the format for these 16 bits is \"CRAAAAUG AAAAAAAA\",\n where \"C\" remains the \"Cone\" flag. The \"R\" bit is reserved for future\n use. The \"U\" bit is for the Universal/Local flag (set to 0). The \"G\" bit\n is Individual/Group flag (set to 0). The A bits are set to a 12-bit\n randomly generated number chosen by the Teredo client to introduce\n additional protection for the Teredo node against IPv6-based scanning\n attacks.\n - Bits 80 to 95 contains the obfuscated UDP port number. This is the\n port number that is mapped by the NAT to the Teredo client with all\n bits inverted.\n - Bits 96 to 127 contains the obfuscated IPv4 address. This is the\n public IPv4 address of the NAT with all bits inverted.\n */\n const prefix = this.getBitsBase16(0, 32);\n const bitsForUdpPort = this.getBits(80, 96);\n // eslint-disable-next-line no-bitwise\n const udpPort = (bitsForUdpPort ^ BigInt('0xffff')).toString();\n const server4 = ipv4_1.Address4.fromHex(this.getBitsBase16(32, 64));\n const bitsForClient4 = this.getBits(96, 128);\n // eslint-disable-next-line no-bitwise\n const client4 = ipv4_1.Address4.fromHex((bitsForClient4 ^ BigInt('0xffffffff')).toString(16));\n const flagsBase2 = this.getBitsBase2(64, 80);\n const coneNat = (0, common_1.testBit)(flagsBase2, 15);\n const reserved = (0, common_1.testBit)(flagsBase2, 14);\n const groupIndividual = (0, common_1.testBit)(flagsBase2, 8);\n const universalLocal = (0, common_1.testBit)(flagsBase2, 9);\n const nonce = BigInt(`0b${flagsBase2.slice(2, 6) + flagsBase2.slice(8, 16)}`).toString(10);\n return {\n prefix: `${prefix.slice(0, 4)}:${prefix.slice(4, 8)}`,\n server4: server4.address,\n client4: client4.address,\n flags: flagsBase2,\n coneNat,\n microsoft: {\n reserved,\n universalLocal,\n groupIndividual,\n nonce,\n },\n udpPort,\n };\n }\n /**\n * Return an object containing the 6to4 properties of the address\n * @memberof Address6\n * @instance\n * @returns {Object}\n */\n inspect6to4() {\n /*\n - Bits 0 to 15 are set to the 6to4 prefix (2002::/16).\n - Bits 16 to 48 embed the IPv4 address of the 6to4 gateway that is used.\n */\n const prefix = this.getBitsBase16(0, 16);\n const gateway = ipv4_1.Address4.fromHex(this.getBitsBase16(16, 48));\n return {\n prefix: prefix.slice(0, 4),\n gateway: gateway.address,\n };\n }\n /**\n * Return a v6 6to4 address from a v6 v4inv6 address\n * @memberof Address6\n * @instance\n * @returns {Address6}\n */\n to6to4() {\n if (!this.is4()) {\n return null;\n }\n const addr6to4 = [\n '2002',\n this.getBitsBase16(96, 112),\n this.getBitsBase16(112, 128),\n '',\n '/16',\n ].join(':');\n return new Address6(addr6to4);\n }\n /**\n * Return a byte array\n * @memberof Address6\n * @instance\n * @returns {Array}\n */\n toByteArray() {\n const valueWithoutPadding = this.bigInt().toString(16);\n const leadingPad = '0'.repeat(valueWithoutPadding.length % 2);\n const value = `${leadingPad}${valueWithoutPadding}`;\n const bytes = [];\n for (let i = 0, length = value.length; i < length; i += 2) {\n bytes.push(parseInt(value.substring(i, i + 2), 16));\n }\n return bytes;\n }\n /**\n * Return an unsigned byte array\n * @memberof Address6\n * @instance\n * @returns {Array}\n */\n toUnsignedByteArray() {\n return this.toByteArray().map(unsignByte);\n }\n /**\n * Convert a byte array to an Address6 object\n * @memberof Address6\n * @static\n * @returns {Address6}\n */\n static fromByteArray(bytes) {\n return this.fromUnsignedByteArray(bytes.map(unsignByte));\n }\n /**\n * Convert an unsigned byte array to an Address6 object\n * @memberof Address6\n * @static\n * @returns {Address6}\n */\n static fromUnsignedByteArray(bytes) {\n const BYTE_MAX = BigInt('256');\n let result = BigInt('0');\n let multiplier = BigInt('1');\n for (let i = bytes.length - 1; i >= 0; i--) {\n result += multiplier * BigInt(bytes[i].toString(10));\n multiplier *= BYTE_MAX;\n }\n return Address6.fromBigInt(result);\n }\n /**\n * Returns true if the address is in the canonical form, false otherwise\n * @memberof Address6\n * @instance\n * @returns {boolean}\n */\n isCanonical() {\n return this.addressMinusSuffix === this.canonicalForm();\n }\n /**\n * Returns true if the address is a link local address, false otherwise\n * @memberof Address6\n * @instance\n * @returns {boolean}\n */\n isLinkLocal() {\n // Zeroes are required, i.e. we can't check isInSubnet with 'fe80::/10'\n if (this.getBitsBase2(0, 64) ===\n '1111111010000000000000000000000000000000000000000000000000000000') {\n return true;\n }\n return false;\n }\n /**\n * Returns true if the address is a multicast address, false otherwise\n * @memberof Address6\n * @instance\n * @returns {boolean}\n */\n isMulticast() {\n return this.getType() === 'Multicast';\n }\n /**\n * Returns true if the address is a v4-in-v6 address, false otherwise\n * @memberof Address6\n * @instance\n * @returns {boolean}\n */\n is4() {\n return this.v4;\n }\n /**\n * Returns true if the address is a Teredo address, false otherwise\n * @memberof Address6\n * @instance\n * @returns {boolean}\n */\n isTeredo() {\n return this.isInSubnet(new Address6('2001::/32'));\n }\n /**\n * Returns true if the address is a 6to4 address, false otherwise\n * @memberof Address6\n * @instance\n * @returns {boolean}\n */\n is6to4() {\n return this.isInSubnet(new Address6('2002::/16'));\n }\n /**\n * Returns true if the address is a loopback address, false otherwise\n * @memberof Address6\n * @instance\n * @returns {boolean}\n */\n isLoopback() {\n return this.getType() === 'Loopback';\n }\n // #endregion\n // #region HTML\n /**\n * @returns {String} the address in link form with a default port of 80\n */\n href(optionalPort) {\n if (optionalPort === undefined) {\n optionalPort = '';\n }\n else {\n optionalPort = `:${optionalPort}`;\n }\n return `http://[${this.correctForm()}]${optionalPort}/`;\n }\n /**\n * @returns {String} a link suitable for conveying the address via a URL hash\n */\n link(options) {\n if (!options) {\n options = {};\n }\n if (options.className === undefined) {\n options.className = '';\n }\n if (options.prefix === undefined) {\n options.prefix = '/#address=';\n }\n if (options.v4 === undefined) {\n options.v4 = false;\n }\n let formFunction = this.correctForm;\n if (options.v4) {\n formFunction = this.to4in6;\n }\n const form = formFunction.call(this);\n const safeHref = helpers.escapeHtml(`${options.prefix}${form}`);\n const safeForm = helpers.escapeHtml(form);\n if (options.className) {\n const safeClass = helpers.escapeHtml(options.className);\n return `<a href=\"${safeHref}\" class=\"${safeClass}\">${safeForm}</a>`;\n }\n return `<a href=\"${safeHref}\">${safeForm}</a>`;\n }\n /**\n * Groups an address\n * @returns {String}\n */\n group() {\n if (this.elidedGroups === 0) {\n // The simple case\n return helpers.simpleGroup(this.addressMinusSuffix).join(':');\n }\n assert(typeof this.elidedGroups === 'number');\n assert(typeof this.elisionBegin === 'number');\n // The elided case\n const output = [];\n const [left, right] = this.addressMinusSuffix.split('::');\n if (left.length) {\n output.push(...helpers.simpleGroup(left));\n }\n else {\n output.push('');\n }\n const classes = ['hover-group'];\n for (let i = this.elisionBegin; i < this.elisionBegin + this.elidedGroups; i++) {\n classes.push(`group-${i}`);\n }\n output.push(`<span class=\"${classes.join(' ')}\"></span>`);\n if (right.length) {\n output.push(...helpers.simpleGroup(right, this.elisionEnd));\n }\n else {\n output.push('');\n }\n if (this.is4()) {\n assert(this.address4 instanceof ipv4_1.Address4);\n output.pop();\n output.push(this.address4.groupForV6());\n }\n return output.join(':');\n }\n // #endregion\n // #region Regular expressions\n /**\n * Generate a regular expression string that can be used to find or validate\n * all variations of this address\n * @memberof Address6\n * @instance\n * @param {boolean} substringSearch\n * @returns {string}\n */\n regularExpressionString(substringSearch = false) {\n let output = [];\n // TODO: revisit why this is necessary\n const address6 = new Address6(this.correctForm());\n if (address6.elidedGroups === 0) {\n // The simple case\n output.push((0, regular_expressions_1.simpleRegularExpression)(address6.parsedAddress));\n }\n else if (address6.elidedGroups === constants6.GROUPS) {\n // A completely elided address\n output.push((0, regular_expressions_1.possibleElisions)(constants6.GROUPS));\n }\n else {\n // A partially elided address\n const halves = address6.address.split('::');\n if (halves[0].length) {\n output.push((0, regular_expressions_1.simpleRegularExpression)(halves[0].split(':')));\n }\n assert(typeof address6.elidedGroups === 'number');\n output.push((0, regular_expressions_1.possibleElisions)(address6.elidedGroups, halves[0].length !== 0, halves[1].length !== 0));\n if (halves[1].length) {\n output.push((0, regular_expressions_1.simpleRegularExpression)(halves[1].split(':')));\n }\n output = [output.join(':')];\n }\n if (!substringSearch) {\n output = [\n '(?=^|',\n regular_expressions_1.ADDRESS_BOUNDARY,\n '|[^\\\\w\\\\:])(',\n ...output,\n ')(?=[^\\\\w\\\\:]|',\n regular_expressions_1.ADDRESS_BOUNDARY,\n '|$)',\n ];\n }\n return output.join('');\n }\n /**\n * Generate a regular expression that can be used to find or validate all\n * variations of this address.\n * @memberof Address6\n * @instance\n * @param {boolean} substringSearch\n * @returns {RegExp}\n */\n regularExpression(substringSearch = false) {\n return new RegExp(this.regularExpressionString(substringSearch), 'i');\n }\n}\nexports.Address6 = Address6;\n//# sourceMappingURL=ipv6.js.map","\"use strict\";\nvar __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n var desc = Object.getOwnPropertyDescriptor(m, k);\n if (!desc || (\"get\" in desc ? !m.__esModule : desc.writable || desc.configurable)) {\n desc = { enumerable: true, get: function() { return m[k]; } };\n }\n Object.defineProperty(o, k2, desc);\n}) : (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n o[k2] = m[k];\n}));\nvar __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\n}) : function(o, v) {\n o[\"default\"] = v;\n});\nvar __importStar = (this && this.__importStar) || function (mod) {\n if (mod && mod.__esModule) return mod;\n var result = {};\n if (mod != null) for (var k in mod) if (k !== \"default\" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\n __setModuleDefault(result, mod);\n return result;\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.v6 = exports.AddressError = exports.Address6 = exports.Address4 = void 0;\nvar ipv4_1 = require(\"./ipv4\");\nObject.defineProperty(exports, \"Address4\", { enumerable: true, get: function () { return ipv4_1.Address4; } });\nvar ipv6_1 = require(\"./ipv6\");\nObject.defineProperty(exports, \"Address6\", { enumerable: true, get: function () { return ipv6_1.Address6; } });\nvar address_error_1 = require(\"./address-error\");\nObject.defineProperty(exports, \"AddressError\", { enumerable: true, get: function () { return address_error_1.AddressError; } });\nconst helpers = __importStar(require(\"./v6/helpers\"));\nexports.v6 = { helpers };\n//# sourceMappingURL=ip-address.js.map","// source/ip-key-generator.ts\nimport { isIPv6 } from \"node:net\";\nimport { Address6 } from \"ip-address\";\nfunction ipKeyGenerator(ip, ipv6Subnet = 56) {\n if (isIPv6(ip)) {\n const address = new Address6(ip);\n if (address.is4()) return address.to4().correctForm();\n if (ipv6Subnet) {\n const subnet = new Address6(`${ip}/${ipv6Subnet}`);\n return subnet.networkForm();\n }\n }\n return ip;\n}\n\n// source/memory-store.ts\nvar MemoryStore = class {\n constructor(validations2) {\n this.validations = validations2;\n /**\n * These two maps store usage (requests) and reset time by key (for example, IP\n * addresses or API keys).\n *\n * They are split into two to avoid having to iterate through the entire set to\n * determine which ones need reset. Instead, `Client`s are moved from `previous`\n * to `current` as they hit the endpoint. Once `windowMs` has elapsed, all clients\n * left in `previous`, i.e., those that have not made any recent requests, are\n * known to be expired and can be deleted in bulk.\n */\n this.previous = /* @__PURE__ */ new Map();\n this.current = /* @__PURE__ */ new Map();\n /**\n * Confirmation that the keys incremented in once instance of MemoryStore\n * cannot affect other instances.\n */\n this.localKeys = true;\n }\n /**\n * Method that initializes the store.\n *\n * @param options {Options} - The options used to setup the middleware.\n */\n init(options) {\n this.windowMs = options.windowMs;\n this.validations?.windowMs(this.windowMs);\n if (this.interval) clearInterval(this.interval);\n this.interval = setInterval(() => {\n this.clearExpired();\n }, this.windowMs);\n this.interval.unref?.();\n }\n /**\n * Method to fetch a client's hit count and reset time.\n *\n * @param key {string} - The identifier for a client.\n *\n * @returns {ClientRateLimitInfo | undefined} - The number of hits and reset time for that client.\n *\n * @public\n */\n async get(key) {\n return this.current.get(key) ?? this.previous.get(key);\n }\n /**\n * Method to increment a client's hit counter.\n *\n * @param key {string} - The identifier for a client.\n *\n * @returns {ClientRateLimitInfo} - The number of hits and reset time for that client.\n *\n * @public\n */\n async increment(key) {\n const client = this.getClient(key);\n const now = Date.now();\n if (client.resetTime.getTime() <= now) {\n this.resetClient(client, now);\n }\n client.totalHits++;\n return client;\n }\n /**\n * Method to decrement a client's hit counter.\n *\n * @param key {string} - The identifier for a client.\n *\n * @public\n */\n async decrement(key) {\n const client = this.getClient(key);\n if (client.totalHits > 0) client.totalHits--;\n }\n /**\n * Method to reset a client's hit counter.\n *\n * @param key {string} - The identifier for a client.\n *\n * @public\n */\n async resetKey(key) {\n this.current.delete(key);\n this.previous.delete(key);\n }\n /**\n * Method to reset everyone's hit counter.\n *\n * @public\n */\n async resetAll() {\n this.current.clear();\n this.previous.clear();\n }\n /**\n * Method to stop the timer (if currently running) and prevent any memory\n * leaks.\n *\n * @public\n */\n shutdown() {\n clearInterval(this.interval);\n void this.resetAll();\n }\n /**\n * Recycles a client by setting its hit count to zero, and reset time to\n * `windowMs` milliseconds from now.\n *\n * NOT to be confused with `#resetKey()`, which removes a client from both the\n * `current` and `previous` maps.\n *\n * @param client {Client} - The client to recycle.\n * @param now {number} - The current time, to which the `windowMs` is added to get the `resetTime` for the client.\n *\n * @return {Client} - The modified client that was passed in, to allow for chaining.\n */\n resetClient(client, now = Date.now()) {\n client.totalHits = 0;\n client.resetTime.setTime(now + this.windowMs);\n return client;\n }\n /**\n * Retrieves or creates a client, given a key. Also ensures that the client being\n * returned is in the `current` map.\n *\n * @param key {string} - The key under which the client is (or is to be) stored.\n *\n * @returns {Client} - The requested client.\n */\n getClient(key) {\n if (this.current.has(key)) return this.current.get(key);\n let client;\n if (this.previous.has(key)) {\n client = this.previous.get(key);\n this.previous.delete(key);\n } else {\n client = { totalHits: 0, resetTime: /* @__PURE__ */ new Date() };\n this.resetClient(client);\n }\n this.current.set(key, client);\n return client;\n }\n /**\n * Move current clients to previous, create a new map for current.\n *\n * This function is called every `windowMs`.\n */\n clearExpired() {\n this.previous = this.current;\n this.current = /* @__PURE__ */ new Map();\n }\n};\n\n// source/rate-limit.ts\nimport { isIPv6 as isIPv62 } from \"node:net\";\n\n// source/console-logger.ts\nvar ConsoleLogger = {\n warn(...args) {\n console.warn(...args.reverse());\n },\n error(...args) {\n console.error(...args.reverse());\n }\n};\n\n// source/headers.ts\nimport { Buffer } from \"node:buffer\";\nimport { createHash } from \"node:crypto\";\nvar SUPPORTED_DRAFT_VERSIONS = [\n \"draft-6\",\n \"draft-7\",\n \"draft-8\"\n];\nvar getResetSeconds = (windowMs, resetTime) => {\n let resetSeconds;\n if (resetTime) {\n const deltaSeconds = Math.ceil((resetTime.getTime() - Date.now()) / 1e3);\n resetSeconds = Math.max(0, deltaSeconds);\n } else {\n resetSeconds = Math.ceil(windowMs / 1e3);\n }\n return resetSeconds;\n};\nvar getPartitionKey = (key) => {\n const hash = createHash(\"sha256\");\n hash.update(key);\n const partitionKey = hash.digest(\"hex\").slice(0, 12);\n return Buffer.from(partitionKey).toString(\"base64\");\n};\nvar setLegacyHeaders = (response, info) => {\n if (response.headersSent) return;\n response.setHeader(\"X-RateLimit-Limit\", info.limit.toString());\n response.setHeader(\"X-RateLimit-Remaining\", info.remaining.toString());\n if (info.resetTime instanceof Date) {\n response.setHeader(\"Date\", (/* @__PURE__ */ new Date()).toUTCString());\n response.setHeader(\n \"X-RateLimit-Reset\",\n Math.ceil(info.resetTime.getTime() / 1e3).toString()\n );\n }\n};\nvar setDraft6Headers = (response, info, windowMs) => {\n if (response.headersSent) return;\n const windowSeconds = Math.ceil(windowMs / 1e3);\n const resetSeconds = getResetSeconds(windowMs, info.resetTime);\n response.setHeader(\"RateLimit-Policy\", `${info.limit};w=${windowSeconds}`);\n response.setHeader(\"RateLimit-Limit\", info.limit.toString());\n response.setHeader(\"RateLimit-Remaining\", info.remaining.toString());\n if (typeof resetSeconds === \"number\")\n response.setHeader(\"RateLimit-Reset\", resetSeconds.toString());\n};\nvar setDraft7Headers = (response, info, windowMs) => {\n if (response.headersSent) return;\n const windowSeconds = Math.ceil(windowMs / 1e3);\n const resetSeconds = getResetSeconds(windowMs, info.resetTime);\n response.setHeader(\"RateLimit-Policy\", `${info.limit};w=${windowSeconds}`);\n response.setHeader(\n \"RateLimit\",\n `limit=${info.limit}, remaining=${info.remaining}, reset=${resetSeconds}`\n );\n};\nvar setDraft8Headers = (response, info, windowMs, name, key) => {\n if (response.headersSent) return;\n const windowSeconds = Math.ceil(windowMs / 1e3);\n const resetSeconds = getResetSeconds(windowMs, info.resetTime);\n const partitionKey = getPartitionKey(key);\n const header = `r=${info.remaining}; t=${resetSeconds}`;\n const policy = `q=${info.limit}; w=${windowSeconds}; pk=:${partitionKey}:`;\n response.append(\"RateLimit\", `\"${name}\"; ${header}`);\n response.append(\"RateLimit-Policy\", `\"${name}\"; ${policy}`);\n};\nvar setRetryAfterHeader = (response, info, windowMs) => {\n if (response.headersSent) return;\n const resetSeconds = getResetSeconds(windowMs, info.resetTime);\n response.setHeader(\"Retry-After\", resetSeconds.toString());\n};\n\n// source/utils.ts\nvar omitUndefinedProperties = (passedOptions) => {\n const omittedOptions = {};\n for (const k of Object.keys(passedOptions)) {\n const key = k;\n if (passedOptions[key] !== void 0) {\n omittedOptions[key] = passedOptions[key];\n }\n }\n return omittedOptions;\n};\n\n// source/validations.ts\nimport { isIP } from \"node:net\";\nvar ValidationError = class extends Error {\n /**\n * The code must be a string, in snake case and all capital, that starts with\n * the substring `ERR_ERL_`.\n *\n * The message must be a string, starting with an uppercase character,\n * describing the issue in detail.\n */\n constructor(code, message) {\n const url = `https://express-rate-limit.github.io/${code}/`;\n super(`${message} See ${url} for more information.`);\n this.name = this.constructor.name;\n this.code = code;\n this.help = url;\n }\n};\nvar ChangeWarning = class extends ValidationError {\n};\nvar usedStores = /* @__PURE__ */ new Set();\nvar singleCountKeys = /* @__PURE__ */ new WeakMap();\nvar validations = {\n enabled: {\n default: true\n },\n // Should be EnabledValidations type, but that's a circular reference\n disable() {\n for (const k of Object.keys(this.enabled)) this.enabled[k] = false;\n },\n /**\n * Checks whether the IP address is valid, and that it does not have a port\n * number in it.\n *\n * See https://github.com/express-rate-limit/express-rate-limit/wiki/Error-Codes#err_erl_invalid_ip_address.\n *\n * @param ip {string | undefined} - The IP address provided by Express as request.ip.\n *\n * @returns {void}\n */\n ip(ip) {\n if (ip === void 0) {\n throw new ValidationError(\n \"ERR_ERL_UNDEFINED_IP_ADDRESS\",\n `An undefined 'request.ip' was detected. This might indicate a misconfiguration or the connection being destroyed prematurely.`\n );\n }\n if (!isIP(ip)) {\n throw new ValidationError(\n \"ERR_ERL_INVALID_IP_ADDRESS\",\n `An invalid 'request.ip' (${ip}) was detected. Consider passing a custom 'keyGenerator' function to the rate limiter.`\n );\n }\n },\n /**\n * Makes sure the trust proxy setting is not set to `true`.\n *\n * See https://github.com/express-rate-limit/express-rate-limit/wiki/Error-Codes#err_erl_permissive_trust_proxy.\n *\n * @param request {Request} - The Express request object.\n *\n * @returns {void}\n */\n trustProxy(request) {\n if (request.app.get(\"trust proxy\") === true) {\n throw new ValidationError(\n \"ERR_ERL_PERMISSIVE_TRUST_PROXY\",\n `The Express 'trust proxy' setting is true, which allows anyone to trivially bypass IP-based rate limiting.`\n );\n }\n },\n /**\n * Makes sure the trust proxy setting is set in case the `X-Forwarded-For`\n * header is present.\n *\n * See https://github.com/express-rate-limit/express-rate-limit/wiki/Error-Codes#err_erl_unset_trust_proxy.\n *\n * @param request {Request} - The Express request object.\n *\n * @returns {void}\n */\n xForwardedForHeader(request) {\n if (request.headers[\"x-forwarded-for\"] && request.app.get(\"trust proxy\") === false) {\n throw new ValidationError(\n \"ERR_ERL_UNEXPECTED_X_FORWARDED_FOR\",\n `The 'X-Forwarded-For' header is set but the Express 'trust proxy' setting is false (default). This could indicate a misconfiguration which would prevent express-rate-limit from accurately identifying users.`\n );\n }\n },\n /**\n * Alert the user if the Forwarded header is set (standardized version of X-Forwarded-For - not supported by express as of version 5.1.0)\n *\n * @param request {Request} - The Express request object.\n *\n * @returns {void}\n */\n forwardedHeader(request) {\n if (request.headers.forwarded && request.ip === request.socket?.remoteAddress) {\n throw new ValidationError(\n \"ERR_ERL_FORWARDED_HEADER\",\n `The 'Forwarded' header (standardized X-Forwarded-For) is set but currently being ignored. Add a custom keyGenerator to use a value from this header.`\n );\n }\n },\n /**\n * Ensures totalHits value from store is a positive integer.\n *\n * @param hits {any} - The `totalHits` returned by the store.\n */\n positiveHits(hits) {\n if (typeof hits !== \"number\" || hits < 1 || hits !== Math.round(hits)) {\n throw new ValidationError(\n \"ERR_ERL_INVALID_HITS\",\n `The totalHits value returned from the store must be a positive integer, got ${hits}`\n );\n }\n },\n /**\n * Ensures a single store instance is not used with multiple express-rate-limit instances\n */\n unsharedStore(store) {\n if (usedStores.has(store)) {\n const maybeUniquePrefix = store?.localKeys ? \"\" : \" (with a unique prefix)\";\n throw new ValidationError(\n \"ERR_ERL_STORE_REUSE\",\n `A Store instance must not be shared across multiple rate limiters. Create a new instance of ${store.constructor.name}${maybeUniquePrefix} for each limiter instead.`\n );\n }\n usedStores.add(store);\n },\n /**\n * Ensures a given key is incremented only once per request.\n *\n * @param request {Request} - The Express request object.\n * @param store {Store} - The store class.\n * @param key {string} - The key used to store the client's hit count.\n *\n * @returns {void}\n */\n singleCount(request, store, key) {\n let storeKeys = singleCountKeys.get(request);\n if (!storeKeys) {\n storeKeys = /* @__PURE__ */ new Map();\n singleCountKeys.set(request, storeKeys);\n }\n const storeKey = store.localKeys ? store : store.constructor.name;\n let keys = storeKeys.get(storeKey);\n if (!keys) {\n keys = [];\n storeKeys.set(storeKey, keys);\n }\n const prefixedKey = `${store.prefix ?? \"\"}${key}`;\n if (keys.includes(prefixedKey)) {\n throw new ValidationError(\n \"ERR_ERL_DOUBLE_COUNT\",\n `The hit count for ${key} was incremented more than once for a single request.`\n );\n }\n keys.push(prefixedKey);\n },\n /**\n * Warns the user that the behaviour for `max: 0` / `limit: 0` is\n * changing in the next major release.\n *\n * @param limit {number} - The maximum number of hits per client.\n *\n * @returns {void}\n */\n limit(limit) {\n if (limit === 0) {\n throw new ChangeWarning(\n \"WRN_ERL_MAX_ZERO\",\n \"Setting limit or max to 0 disables rate limiting in express-rate-limit v6 and older, but will cause all requests to be blocked in v7\"\n );\n }\n },\n /**\n * Warns the user that the `draft_polli_ratelimit_headers` option is deprecated\n * and will be removed in the next major release.\n *\n * @param draft_polli_ratelimit_headers {any | undefined} - The now-deprecated setting that was used to enable standard headers.\n *\n * @returns {void}\n */\n draftPolliHeaders(draft_polli_ratelimit_headers) {\n if (draft_polli_ratelimit_headers) {\n throw new ChangeWarning(\n \"WRN_ERL_DEPRECATED_DRAFT_POLLI_HEADERS\",\n `The draft_polli_ratelimit_headers configuration option is deprecated and has been removed in express-rate-limit v7, please set standardHeaders: 'draft-6' instead.`\n );\n }\n },\n /**\n * Warns the user that the `onLimitReached` option is deprecated and\n * will be removed in the next major release.\n *\n * @param onLimitReached {any | undefined} - The maximum number of hits per client.\n *\n * @returns {void}\n */\n onLimitReached(onLimitReached) {\n if (onLimitReached) {\n throw new ChangeWarning(\n \"WRN_ERL_DEPRECATED_ON_LIMIT_REACHED\",\n \"The onLimitReached configuration option is deprecated and has been removed in express-rate-limit v7.\"\n );\n }\n },\n /**\n * Warns the user when an invalid/unsupported version of the draft spec is passed.\n *\n * @param version {any | undefined} - The version passed by the user.\n *\n * @returns {void}\n */\n headersDraftVersion(version) {\n if (typeof version !== \"string\" || // @ts-expect-error This is fine. If version is not in the array, it will just return false.\n !SUPPORTED_DRAFT_VERSIONS.includes(version)) {\n const versionString = SUPPORTED_DRAFT_VERSIONS.join(\", \");\n throw new ValidationError(\n \"ERR_ERL_HEADERS_UNSUPPORTED_DRAFT_VERSION\",\n `standardHeaders: only the following versions of the IETF draft specification are supported: ${versionString}.`\n );\n }\n },\n /**\n * Warns the user when the selected headers option requires a reset time but\n * the store does not provide one.\n *\n * @param resetTime {Date | undefined} - The timestamp when the client's hit count will be reset.\n *\n * @returns {void}\n */\n headersResetTime(resetTime) {\n if (!resetTime) {\n throw new ValidationError(\n \"ERR_ERL_HEADERS_NO_RESET\",\n `standardHeaders: 'draft-7' requires a 'resetTime', but the store did not provide one. The 'windowMs' value will be used instead, which may cause clients to wait longer than necessary.`\n );\n }\n },\n knownOptions(passedOptions) {\n if (!passedOptions) return;\n const optionsMap = {\n windowMs: true,\n limit: true,\n message: true,\n statusCode: true,\n legacyHeaders: true,\n standardHeaders: true,\n identifier: true,\n requestPropertyName: true,\n skipFailedRequests: true,\n skipSuccessfulRequests: true,\n keyGenerator: true,\n ipv6Subnet: true,\n handler: true,\n skip: true,\n requestWasSuccessful: true,\n store: true,\n validate: true,\n headers: true,\n max: true,\n passOnStoreError: true,\n logger: true\n };\n const validOptions = Object.keys(optionsMap).concat(\n \"draft_polli_ratelimit_headers\",\n // not a valid option anymore, but we have a more specific check for this one, so don't warn for it here\n // from express-slow-down - https://github.com/express-rate-limit/express-slow-down/blob/main/source/types.ts#L65\n \"delayAfter\",\n \"delayMs\",\n \"maxDelayMs\"\n );\n for (const key of Object.keys(passedOptions)) {\n if (!validOptions.includes(key)) {\n throw new ValidationError(\n \"ERR_ERL_UNKNOWN_OPTION\",\n `Unexpected configuration option: ${key}`\n // todo: suggest a valid option with a short levenstein distance?\n );\n }\n }\n },\n /**\n * Checks the options.validate setting to ensure that only recognized\n * validations are enabled or disabled.\n *\n * If any unrecognized values are found, an error is logged that\n * includes the list of supported validations.\n */\n validationsConfig() {\n const supportedValidations = Object.keys(this).filter(\n (k) => ![\"enabled\", \"disable\"].includes(k)\n );\n supportedValidations.push(\"default\");\n for (const key of Object.keys(this.enabled)) {\n if (!supportedValidations.includes(key)) {\n throw new ValidationError(\n \"ERR_ERL_UNKNOWN_VALIDATION\",\n `options.validate.${key} is not recognized. Supported validate options are: ${supportedValidations.join(\n \", \"\n )}.`\n );\n }\n }\n },\n /**\n * Checks to see if the instance was created inside of a request handler,\n * which would prevent it from working correctly, with the default memory\n * store (or any other store with localKeys.)\n */\n creationStack(store) {\n const { stack } = new Error(\n \"express-rate-limit validation check (set options.validate.creationStack=false to disable)\"\n );\n if (stack?.includes(\"Layer.handle [as handle_request]\") || // express v4\n stack?.includes(\"Layer.handleRequest\")) {\n if (!store.localKeys) {\n throw new ValidationError(\n \"ERR_ERL_CREATED_IN_REQUEST_HANDLER\",\n \"express-rate-limit instance should *usually* be created at app initialization, not when responding to a request.\"\n );\n }\n throw new ValidationError(\n \"ERR_ERL_CREATED_IN_REQUEST_HANDLER\",\n \"express-rate-limit instance should be created at app initialization, not when responding to a request.\"\n );\n }\n },\n ipv6Subnet(ipv6Subnet) {\n if (ipv6Subnet === false) {\n return;\n }\n if (!Number.isInteger(ipv6Subnet) || ipv6Subnet < 32 || ipv6Subnet > 64) {\n throw new ValidationError(\n \"ERR_ERL_IPV6_SUBNET\",\n `Unexpected ipv6Subnet value: ${ipv6Subnet}. Expected an integer between 32 and 64 (usually 48-64).`\n );\n }\n },\n ipv6SubnetOrKeyGenerator(options) {\n if (options.ipv6Subnet !== void 0 && options.keyGenerator) {\n throw new ValidationError(\n \"ERR_ERL_IPV6SUBNET_OR_KEYGENERATOR\",\n `Incompatible options: the 'ipv6Subnet' option is ignored when a custom 'keyGenerator' function is also set.`\n );\n }\n },\n keyGeneratorIpFallback(keyGenerator) {\n if (!keyGenerator) {\n return;\n }\n const src = keyGenerator.toString();\n if ((src.includes(\"req.ip\") || src.includes(\"request.ip\")) && !src.includes(\"ipKeyGenerator\")) {\n throw new ValidationError(\n \"ERR_ERL_KEY_GEN_IPV6\",\n \"Custom keyGenerator appears to use request IP without calling the ipKeyGenerator helper function for IPv6 addresses. This could allow IPv6 users to bypass limits.\"\n );\n }\n },\n /**\n * Checks to see if the window duration is greater than 2^32 - 1. This is only\n * called by the default MemoryStore, since it uses Node's setInterval method.\n *\n * See https://nodejs.org/api/timers.html#setintervalcallback-delay-args.\n */\n windowMs(windowMs) {\n const SET_TIMEOUT_MAX = 2 ** 31 - 1;\n if (typeof windowMs !== \"number\" || Number.isNaN(windowMs) || windowMs < 1 || windowMs > SET_TIMEOUT_MAX) {\n throw new ValidationError(\n \"ERR_ERL_WINDOW_MS\",\n `Invalid windowMs value: ${windowMs}${typeof windowMs !== \"number\" ? ` (${typeof windowMs})` : \"\"}, must be a number between 1 and ${SET_TIMEOUT_MAX} when using the default MemoryStore`\n );\n }\n }\n};\nfunction validateLogger(logger) {\n if (typeof logger !== \"object\" || typeof logger.error !== \"function\" || typeof logger.warn !== \"function\") {\n throw new TypeError(\n \"Provided logger does not implement the Logger interface\"\n );\n }\n}\nvar getValidations = (_enabled, logger) => {\n validateLogger(logger);\n let enabled;\n if (typeof _enabled === \"boolean\") {\n enabled = {\n default: _enabled\n };\n } else {\n enabled = {\n default: true,\n ..._enabled\n };\n }\n const wrappedValidations = { enabled };\n for (const [name, validation] of Object.entries(validations)) {\n if (typeof validation === \"function\")\n wrappedValidations[name] = (...args) => {\n if (!(enabled[name] ?? enabled.default)) {\n return;\n }\n try {\n ;\n validation.apply(\n wrappedValidations,\n args\n );\n } catch (error) {\n if (error instanceof ChangeWarning) logger.warn(error);\n else logger.error(error);\n }\n };\n }\n return wrappedValidations;\n};\n\n// source/rate-limit.ts\nvar isLegacyStore = (store) => (\n // Check that `incr` exists but `increment` does not - store authors might want\n // to keep both around for backwards compatibility.\n typeof store.incr === \"function\" && typeof store.increment !== \"function\"\n);\nvar promisifyStore = (passedStore) => {\n if (!isLegacyStore(passedStore)) {\n return passedStore;\n }\n const legacyStore = passedStore;\n class PromisifiedStore {\n async increment(key) {\n return new Promise((resolve, reject) => {\n legacyStore.incr(\n key,\n (error, totalHits, resetTime) => {\n if (error) reject(error);\n resolve({ totalHits, resetTime });\n }\n );\n });\n }\n async decrement(key) {\n return legacyStore.decrement(key);\n }\n async resetKey(key) {\n return legacyStore.resetKey(key);\n }\n /* istanbul ignore next */\n async resetAll() {\n if (typeof legacyStore.resetAll === \"function\")\n return legacyStore.resetAll();\n }\n }\n return new PromisifiedStore();\n};\nvar getOptionsFromConfig = (config) => {\n const { validations: validations2, ...directlyPassableEntries } = config;\n return {\n ...directlyPassableEntries,\n validate: validations2.enabled\n };\n};\nvar parseOptions = (passedOptions) => {\n const notUndefinedOptions = omitUndefinedProperties(passedOptions);\n const logger = passedOptions.logger ?? ConsoleLogger;\n const validations2 = getValidations(\n notUndefinedOptions?.validate ?? true,\n logger\n );\n validations2.validationsConfig();\n validations2.knownOptions(passedOptions);\n validations2.draftPolliHeaders(\n // @ts-expect-error see the note above.\n notUndefinedOptions.draft_polli_ratelimit_headers\n );\n validations2.onLimitReached(notUndefinedOptions.onLimitReached);\n if (notUndefinedOptions.ipv6Subnet !== void 0 && typeof notUndefinedOptions.ipv6Subnet !== \"function\") {\n validations2.ipv6Subnet(notUndefinedOptions.ipv6Subnet);\n }\n validations2.keyGeneratorIpFallback(notUndefinedOptions.keyGenerator);\n validations2.ipv6SubnetOrKeyGenerator(notUndefinedOptions);\n let standardHeaders = notUndefinedOptions.standardHeaders ?? false;\n if (standardHeaders === true) standardHeaders = \"draft-6\";\n const config = {\n windowMs: 60 * 1e3,\n limit: passedOptions.max ?? 5,\n // `max` is deprecated, but support it anyways.\n message: \"Too many requests, please try again later.\",\n statusCode: 429,\n legacyHeaders: passedOptions.headers ?? true,\n identifier(request, _response) {\n let duration = \"\";\n const property = config.requestPropertyName;\n const { limit } = request[property];\n const seconds = config.windowMs / 1e3;\n const minutes = config.windowMs / (1e3 * 60);\n const hours = config.windowMs / (1e3 * 60 * 60);\n const days = config.windowMs / (1e3 * 60 * 60 * 24);\n if (seconds < 60) duration = `${seconds}sec`;\n else if (minutes < 60) duration = `${minutes}min`;\n else if (hours < 24) duration = `${hours}hr${hours > 1 ? \"s\" : \"\"}`;\n else duration = `${days}day${days > 1 ? \"s\" : \"\"}`;\n return `${limit}-in-${duration}`;\n },\n requestPropertyName: \"rateLimit\",\n skipFailedRequests: false,\n skipSuccessfulRequests: false,\n requestWasSuccessful: (_request, response) => response.statusCode < 400,\n skip: (_request, _response) => false,\n async keyGenerator(request, response) {\n validations2.ip(request.ip);\n validations2.trustProxy(request);\n validations2.xForwardedForHeader(request);\n validations2.forwardedHeader(request);\n const ip = request.ip;\n let subnet = 56;\n if (isIPv62(ip)) {\n subnet = typeof config.ipv6Subnet === \"function\" ? await config.ipv6Subnet(request, response) : config.ipv6Subnet;\n if (typeof config.ipv6Subnet === \"function\")\n validations2.ipv6Subnet(subnet);\n }\n return ipKeyGenerator(ip, subnet);\n },\n ipv6Subnet: 56,\n async handler(request, response, _next, _optionsUsed) {\n response.status(config.statusCode);\n const message = typeof config.message === \"function\" ? await config.message(\n request,\n response\n ) : config.message;\n if (!response.writableEnded) response.send(message);\n },\n passOnStoreError: false,\n // Allow the default options to be overridden by the passed options.\n ...notUndefinedOptions,\n // `standardHeaders` is resolved into a draft version above, use that.\n standardHeaders,\n // Note that this field is declared after the user's options are spread in,\n // so that this field doesn't get overridden with an un-promisified store!\n store: promisifyStore(\n notUndefinedOptions.store ?? new MemoryStore(validations2)\n ),\n // Print an error to the console if a few known misconfigurations are detected.\n validations: validations2,\n logger\n };\n if (typeof config.store.increment !== \"function\" || typeof config.store.decrement !== \"function\" || typeof config.store.resetKey !== \"function\" || config.store.resetAll !== void 0 && typeof config.store.resetAll !== \"function\" || config.store.init !== void 0 && typeof config.store.init !== \"function\") {\n throw new TypeError(\n \"An invalid store was passed. Please ensure that the store is a class that implements the `Store` interface.\"\n );\n }\n return config;\n};\nvar handleAsyncErrors = (fn) => async (request, response, next) => {\n try {\n await Promise.resolve(fn(request, response, next)).catch(next);\n } catch (error) {\n next(error);\n }\n};\nvar rateLimit = (passedOptions) => {\n const config = parseOptions(passedOptions ?? {});\n const options = getOptionsFromConfig(config);\n config.validations.creationStack(config.store);\n config.validations.unsharedStore(config.store);\n if (typeof config.store.init === \"function\") {\n try {\n const storeInit = config.store.init(options);\n if (storeInit instanceof Promise) {\n storeInit.catch(\n (error) => config.logger.error(\n error,\n \"express-rate-limit: async error during store initialization.\"\n )\n );\n }\n } catch (error) {\n config.logger.error(\n error,\n \"express-rate-limit: error during store initialization.\"\n );\n }\n }\n const middleware = handleAsyncErrors(\n async (request, response, next) => {\n const closePromise = config.skipFailedRequests && new Promise((resolve) => response.once(\"close\", resolve));\n const finishPromise = (config.skipFailedRequests || config.skipSuccessfulRequests) && new Promise((resolve) => response.once(\"finish\", resolve));\n const errorPromise = config.skipFailedRequests && new Promise((resolve) => response.once(\"error\", resolve));\n const skip = await config.skip(request, response);\n if (skip) {\n next();\n return;\n }\n const augmentedRequest = request;\n const key = await config.keyGenerator(request, response);\n let totalHits = 0;\n let resetTime;\n try {\n const incrementResult = await config.store.increment(key);\n totalHits = incrementResult.totalHits;\n resetTime = incrementResult.resetTime;\n } catch (error) {\n if (config.passOnStoreError) {\n config.logger.error(\n error,\n \"express-rate-limit: error from store, allowing request without rate-limiting.\"\n );\n next();\n return;\n }\n throw error;\n }\n config.validations.positiveHits(totalHits);\n config.validations.singleCount(request, config.store, key);\n const retrieveLimit = typeof config.limit === \"function\" ? config.limit(request, response) : config.limit;\n const limit = await retrieveLimit;\n config.validations.limit(limit);\n const info = {\n limit,\n used: totalHits,\n remaining: Math.max(limit - totalHits, 0),\n resetTime,\n key\n };\n Object.defineProperty(info, \"current\", {\n configurable: false,\n enumerable: false,\n value: totalHits\n });\n augmentedRequest[config.requestPropertyName] = info;\n if (config.legacyHeaders && !response.headersSent) {\n setLegacyHeaders(response, info);\n }\n if (config.standardHeaders && !response.headersSent) {\n switch (config.standardHeaders) {\n case \"draft-6\": {\n setDraft6Headers(response, info, config.windowMs);\n break;\n }\n case \"draft-7\": {\n config.validations.headersResetTime(info.resetTime);\n setDraft7Headers(response, info, config.windowMs);\n break;\n }\n case \"draft-8\": {\n const retrieveName = typeof config.identifier === \"function\" ? config.identifier(request, response) : config.identifier;\n const name = await retrieveName;\n config.validations.headersResetTime(info.resetTime);\n setDraft8Headers(response, info, config.windowMs, name, key);\n break;\n }\n default: {\n config.validations.headersDraftVersion(config.standardHeaders);\n break;\n }\n }\n }\n if (config.skipFailedRequests || config.skipSuccessfulRequests) {\n let decremented = false;\n const decrementKey = async () => {\n if (!decremented) {\n await config.store.decrement(key);\n decremented = true;\n }\n };\n if (config.skipFailedRequests) {\n if (finishPromise) {\n void finishPromise.then(async () => {\n if (!await config.requestWasSuccessful(request, response))\n await decrementKey();\n });\n }\n if (closePromise) {\n void closePromise.then(async () => {\n if (!response.writableEnded) await decrementKey();\n });\n }\n if (errorPromise) {\n void errorPromise.then(async () => {\n await decrementKey();\n });\n }\n }\n if (config.skipSuccessfulRequests) {\n if (finishPromise) {\n void finishPromise.then(async () => {\n if (await config.requestWasSuccessful(request, response))\n await decrementKey();\n });\n }\n }\n }\n config.validations.disable();\n if (totalHits > limit) {\n if (config.legacyHeaders || config.standardHeaders) {\n setRetryAfterHeader(response, info, config.windowMs);\n }\n config.handler(request, response, next, options);\n return;\n }\n next();\n }\n );\n const getThrowFn = () => {\n throw new Error(\"The current store does not support the get/getKey method\");\n };\n middleware.resetKey = config.store.resetKey.bind(config.store);\n middleware.getKey = typeof config.store.get === \"function\" ? config.store.get.bind(config.store) : getThrowFn;\n return middleware;\n};\nvar rate_limit_default = rateLimit;\nexport {\n MemoryStore,\n rate_limit_default as default,\n ipKeyGenerator,\n rate_limit_default as rateLimit\n};\n","/**\n * @codemem/mcp — privacy-safe OAuth audit events.\n *\n * Phase 1 single-user remote MCP needs operator-visible security events\n * (registration, authorize, OIDC callback, token issuance, revocation, bearer\n * verification) without ever logging bearer tokens, authorization codes,\n * client secrets, OIDC ID tokens, or private memory contents.\n */\n\nexport type OAuthAuditKind =\n\t| \"registration\"\n\t| \"authorize\"\n\t| \"oidc_callback\"\n\t| \"token\"\n\t| \"refresh\"\n\t| \"rotation\"\n\t| \"revocation\"\n\t| \"bearer\";\n\nexport type OAuthAuditOutcome = \"success\" | \"denied\" | \"error\";\n\nexport type BearerDenyReason =\n\t| \"missing_authorization_header\"\n\t| \"malformed_authorization_header\"\n\t| \"unknown_token\"\n\t| \"expired_token\"\n\t| \"revoked_token\";\n\nexport interface OAuthAuditEventBase {\n\ttimestamp: string;\n\toutcome: OAuthAuditOutcome;\n\treason?: string;\n\tclientId?: string;\n\tremoteAddress?: string;\n}\n\nexport type OAuthAuditEvent = OAuthAuditEventBase & { kind: OAuthAuditKind };\n\nexport type OAuthAuditEmitter = (event: OAuthAuditEvent) => void;\n\n// Canonicalized denylist — keys are compared after lowercasing and stripping\n// non-alphanumeric separators, so `access_token`, `accessToken`, `ACCESS-TOKEN`\n// and `access token` all reduce to `accesstoken` and are blocked uniformly.\n// This codebase commonly uses camelCase identifiers, so a snake_case-only\n// denylist would miss real leak vectors.\nconst FORBIDDEN_KEY_TOKENS = new Set([\n\t\"token\",\n\t\"accesstoken\",\n\t\"refreshtoken\",\n\t\"idtoken\",\n\t\"code\",\n\t\"codeverifier\",\n\t\"codechallenge\",\n\t\"clientsecret\",\n\t\"authorization\",\n\t\"password\",\n\t\"secret\",\n]);\n\nfunction canonicalizeAuditKey(key: string): string {\n\treturn key.toLowerCase().replace(/[^a-z0-9]/g, \"\");\n}\n\n/**\n * Build an audit event with redaction safety. Throws if a forbidden field\n * leaks in; callers should never need to pass token/code material here.\n */\nexport function buildOAuthAuditEvent(\n\tkind: OAuthAuditKind,\n\tfields: Omit<OAuthAuditEventBase, \"timestamp\"> & { now?: number },\n): OAuthAuditEvent {\n\tfor (const key of Object.keys(fields)) {\n\t\tif (FORBIDDEN_KEY_TOKENS.has(canonicalizeAuditKey(key))) {\n\t\t\tthrow new Error(`OAuth audit event must not carry forbidden field: ${key}`);\n\t\t}\n\t}\n\tconst { now, ...rest } = fields;\n\treturn {\n\t\tkind,\n\t\ttimestamp: new Date(now ?? Date.now()).toISOString(),\n\t\t...rest,\n\t};\n}\n\n/**\n * Wrap an audit emitter so any synchronous throw or stream-write failure stays\n * contained. Audit logging is best-effort observability and must never break\n * the OAuth/MCP request flow it observes. Failures are reported once per\n * process to `console.error` so they remain visible without flooding output.\n */\nexport function wrapAuditEmitterBestEffort(emit: OAuthAuditEmitter): OAuthAuditEmitter {\n\tlet reportedFailure = false;\n\treturn (event) => {\n\t\ttry {\n\t\t\temit(event);\n\t\t} catch (err) {\n\t\t\tif (!reportedFailure) {\n\t\t\t\treportedFailure = true;\n\t\t\t\tconsole.error(\"codemem MCP OAuth audit emitter failed (further failures suppressed):\", err);\n\t\t\t}\n\t\t}\n\t};\n}\n\n/**\n * Default audit emitter writes one JSON object per line to stderr. This keeps\n * MCP HTTP stdout reserved for protocol traffic and is greppable by operators\n * via `journalctl` or a redirected log file.\n */\nexport function createDefaultOAuthAuditEmitter(\n\tstream: NodeJS.WriteStream = process.stderr,\n): OAuthAuditEmitter {\n\treturn (event) => {\n\t\tstream.write(`${JSON.stringify({ source: \"codemem-mcp-oauth-audit\", ...event })}\\n`);\n\t};\n}\n\n/**\n * No-op emitter, used when CODEMEM_MCP_AUDIT=0 or when callers explicitly\n * want to suppress audit output (for example, embedded tests).\n */\nexport function createSilentOAuthAuditEmitter(): OAuthAuditEmitter {\n\treturn () => {};\n}\n\n/**\n * Resolve an emitter from environment configuration. `CODEMEM_MCP_AUDIT=0`,\n * `false`, or `no` disables audit logging; anything else (including unset)\n * uses the default stderr emitter.\n */\nexport function resolveOAuthAuditEmitterFromEnv(\n\tvalue = process.env.CODEMEM_MCP_AUDIT,\n): OAuthAuditEmitter {\n\tconst normalized = value?.trim().toLowerCase();\n\tif (normalized === \"0\" || normalized === \"false\" || normalized === \"no\") {\n\t\treturn createSilentOAuthAuditEmitter();\n\t}\n\treturn createDefaultOAuthAuditEmitter();\n}\n","import { createHash, createHmac, randomBytes, randomUUID, timingSafeEqual } from \"node:crypto\";\nimport type { OAuthRegisteredClientsStore } from \"@modelcontextprotocol/sdk/server/auth/clients.js\";\nimport { InvalidClientMetadataError } from \"@modelcontextprotocol/sdk/server/auth/errors.js\";\nimport type { OAuthServerProvider } from \"@modelcontextprotocol/sdk/server/auth/provider.js\";\nimport { createOAuthMetadata } from \"@modelcontextprotocol/sdk/server/auth/router.js\";\nimport {\n\ttype OAuthClientInformationFull,\n\ttype OAuthClientMetadata,\n\tOAuthClientMetadataSchema,\n\ttype OAuthErrorResponse,\n\ttype OAuthMetadata,\n\ttype OAuthProtectedResourceMetadata,\n\tOAuthProtectedResourceMetadataSchema,\n\ttype OAuthTokens,\n\tOAuthTokensSchema,\n} from \"@modelcontextprotocol/sdk/shared/auth.js\";\n\nexport const MCP_OAUTH_PUBLIC_URL_ENV = \"CODEMEM_MCP_HTTP_PUBLIC_URL\";\nexport const MCP_OAUTH_RESOURCE_NAME = \"codemem MCP\";\nexport const MCP_OAUTH_SCOPES_SUPPORTED = [\"memory:read\", \"memory:write\"];\nexport const MCP_OAUTH_SERVICE_DOCUMENTATION_URL = \"https://github.com/kunickiaj/codemem#readme\";\n\nconst CLAUDE_HOSTED_CALLBACK = \"https://claude.ai/api/mcp/auth_callback\";\nconst LOCAL_CALLBACK_HOSTS = new Set([\"localhost\", \"127.0.0.1\", \"::1\"]);\nconst SUPPORTED_GRANT_TYPES = new Set([\"authorization_code\", \"refresh_token\"]);\nconst SUPPORTED_RESPONSE_TYPES = new Set([\"code\"]);\nconst AUTHORIZATION_CODE_TTL_MS = 5 * 60 * 1000;\nconst ACCESS_TOKEN_TTL_SECONDS = 60 * 60;\nconst REFRESH_TOKEN_TTL_SECONDS = 30 * 24 * 60 * 60;\nconst MAX_AUTHORIZATION_CODES = 100;\nconst MAX_ACCESS_TOKENS = 100;\nconst MAX_REFRESH_GRANTS = 100;\nconst ACCESS_TOKEN_BYTES = 32;\nconst ACCESS_TOKEN_BASE64URL_LENGTH = 43;\nconst ACCESS_TOKEN_BASE64URL = /^[A-Za-z0-9_-]{43}$/;\nconst PKCE_S256_CHALLENGE = /^[A-Za-z0-9_-]{43}$/;\nconst PKCE_VERIFIER = /^[A-Za-z0-9._~-]{43,128}$/;\n\nexport interface McpOAuthMetadataOptions {\n\tmcpUrl: string;\n\tclientsStore: OAuthRegisteredClientsStore;\n}\n\nexport interface RegisteredMcpOAuthClient {\n\tstatus: 201;\n\tbody: OAuthClientInformationFull;\n}\n\nexport interface McpOAuthRegistrationError {\n\tstatus: 400;\n\tbody: { error: \"invalid_client_metadata\"; error_description: string };\n}\n\nexport interface AuthorizationCodeRecord {\n\tclientId: string;\n\tredirectUri: string;\n\tcodeChallenge: string;\n\tscopes: string[];\n\tresource?: string;\n\texpiresAt: number;\n\tused: boolean;\n}\n\nexport interface OAuthAuthorizationCodeStore {\n\tissueCode(record: Omit<AuthorizationCodeRecord, \"used\">, now?: number): string | undefined;\n\tpeekCode(code: string): AuthorizationCodeRecord | undefined;\n\tconsumeCode(code: string): AuthorizationCodeRecord | undefined;\n}\n\nexport interface AccessTokenRecord {\n\tclientId: string;\n\tgrantId?: string;\n\tscopes: string[];\n\tresource?: string;\n\ttokenHash: string;\n\tissuedAt: number;\n\texpiresAt: number;\n\tlastUsedAt: number | null;\n\trevokedAt: number | null;\n}\n\nexport type AccessTokenVerificationResult =\n\t| { ok: true; record: AccessTokenRecord }\n\t| { ok: false; reason: \"unknown_token\" | \"expired_token\" | \"revoked_token\" };\n\nexport interface OAuthAccessTokenStore {\n\tissueToken(\n\t\tclientId: string,\n\t\tnow?: number,\n\t\tresource?: string,\n\t\tgrantId?: string,\n\t\tscopes?: string[],\n\t): { token: string; expiresIn: number } | undefined;\n\tverifyToken(token: string, now?: number): AccessTokenVerificationResult;\n\trevokeToken(token: string, now?: number): boolean;\n\trevokeTokensForGrant?(grantId: string, now?: number): number;\n}\n\nexport interface RefreshTokenGrantRecord {\n\tgrantId: string;\n\tclientId: string;\n\tscopes: string[];\n\tresource?: string;\n\tcurrentRefreshTokenHash: string;\n\tpreviousRefreshTokenHash: string | null;\n\tissuedAt: number;\n\texpiresAt: number;\n\trotatedAt: number | null;\n\trevokedAt: number | null;\n}\n\nexport type RefreshTokenRotationResult =\n\t| { ok: true; grant: RefreshTokenGrantRecord; refreshToken: string; expiresIn: number }\n\t| {\n\t\t\tok: false;\n\t\t\treason:\n\t\t\t\t| \"unknown_refresh_token\"\n\t\t\t\t| \"expired_refresh_token\"\n\t\t\t\t| \"revoked_refresh_token\"\n\t\t\t\t| \"client_mismatch\"\n\t\t\t\t| \"scope_mismatch\"\n\t\t\t\t| \"resource_mismatch\"\n\t\t\t\t| \"refresh_token_replay\";\n\t\t\tgrantId?: string;\n\t };\n\nexport interface OAuthRefreshTokenStore {\n\tissueGrant(\n\t\trecord: { clientId: string; scopes?: string[]; resource?: string },\n\t\tnow?: number,\n\t): { grant: RefreshTokenGrantRecord; refreshToken: string; expiresIn: number } | undefined;\n\trotateRefreshToken(\n\t\tclientId: string,\n\t\trefreshToken: string,\n\t\toptions?: { scopes?: string[]; resource?: string },\n\t\tnow?: number,\n\t): RefreshTokenRotationResult;\n\trevokeRefreshToken(token: string, now?: number): string | undefined;\n\trevokeGrant(grantId: string, now?: number): boolean;\n}\n\nexport interface McpOAuthRedirectResult {\n\tstatus: 302;\n\tlocation: string;\n}\n\nexport interface McpOAuthErrorResult {\n\tstatus: 400;\n\tbody: OAuthErrorResponse;\n}\n\nexport interface McpOAuthTokenResult {\n\tstatus: 200;\n\tbody: OAuthTokens;\n}\n\nexport interface PreparedMcpOAuthAuthorizationRequest {\n\tclientId: string;\n\tredirectUri: string;\n\tcodeChallenge: string;\n\tscopes: string[];\n\tresource: string | null;\n\tstate: string | null;\n}\n\nexport class InMemoryOAuthClientsStore implements OAuthRegisteredClientsStore {\n\treadonly #clients = new Map<string, OAuthClientInformationFull>();\n\n\tgetClient(clientId: string): OAuthClientInformationFull | undefined {\n\t\treturn this.#clients.get(clientId);\n\t}\n\n\tregisterClient(\n\t\tclient: Omit<OAuthClientInformationFull, \"client_id\" | \"client_id_issued_at\">,\n\t): OAuthClientInformationFull {\n\t\tconst redirectError = validateRedirectUris(client.redirect_uris);\n\t\tif (redirectError) throw new InvalidClientMetadataError(redirectError);\n\t\tif (client.client_secret || client.token_endpoint_auth_method !== \"none\") {\n\t\t\tthrow new InvalidClientMetadataError(\n\t\t\t\t\"Only public clients with token_endpoint_auth_method=none are supported\",\n\t\t\t);\n\t\t}\n\t\tif (client.grant_types && !isSupportedList(client.grant_types, SUPPORTED_GRANT_TYPES)) {\n\t\t\tthrow new InvalidClientMetadataError(\n\t\t\t\t\"Only authorization_code and refresh_token grant_types are supported\",\n\t\t\t);\n\t\t}\n\t\tif (\n\t\t\tclient.response_types &&\n\t\t\t!isSupportedList(client.response_types, SUPPORTED_RESPONSE_TYPES)\n\t\t) {\n\t\t\tthrow new InvalidClientMetadataError(\"Only code response_type is supported\");\n\t\t}\n\t\tif (this.#clients.size >= 100) {\n\t\t\tconst oldestClientId = this.#clients.keys().next().value;\n\t\t\tif (oldestClientId) this.#clients.delete(oldestClientId);\n\t\t}\n\t\tconst registered = {\n\t\t\t...client,\n\t\t\ttoken_endpoint_auth_method: \"none\" as const,\n\t\t\tgrant_types: client.grant_types ?? [\"authorization_code\", \"refresh_token\"],\n\t\t\tresponse_types: client.response_types ?? [\"code\"],\n\t\t\tclient_id: randomUUID(),\n\t\t\tclient_id_issued_at: Math.floor(Date.now() / 1000),\n\t\t};\n\t\tthis.#clients.set(registered.client_id, registered);\n\t\treturn registered;\n\t}\n}\n\nexport class InMemoryOAuthAuthorizationCodeStore implements OAuthAuthorizationCodeStore {\n\treadonly #codes = new Map<string, AuthorizationCodeRecord>();\n\n\tissueCode(record: Omit<AuthorizationCodeRecord, \"used\">, now = Date.now()): string | undefined {\n\t\tthis.#deleteExpiredCodes(now);\n\t\tif (this.#codes.size >= MAX_AUTHORIZATION_CODES) return undefined;\n\t\tconst code = randomUUID();\n\t\tthis.#codes.set(code, { ...record, used: false });\n\t\treturn code;\n\t}\n\n\tpeekCode(code: string): AuthorizationCodeRecord | undefined {\n\t\tconst record = this.#codes.get(code);\n\t\tif (!record || record.used) return undefined;\n\t\treturn record;\n\t}\n\n\tconsumeCode(code: string): AuthorizationCodeRecord | undefined {\n\t\tconst record = this.#codes.get(code);\n\t\tif (!record || record.used) return undefined;\n\t\trecord.used = true;\n\t\treturn record;\n\t}\n\n\t#deleteExpiredCodes(now: number): void {\n\t\tfor (const [code, record] of this.#codes) {\n\t\t\tif (record.expiresAt <= now) this.#codes.delete(code);\n\t\t}\n\t}\n}\n\nexport class InMemoryOAuthAccessTokenStore implements OAuthAccessTokenStore {\n\treadonly #tokensByHash = new Map<string, AccessTokenRecord>();\n\treadonly #tokenHashKey = randomBytes(32);\n\n\tissueToken(\n\t\tclientId: string,\n\t\tnow = Date.now(),\n\t\tresource?: string,\n\t\tgrantId?: string,\n\t\tscopes: string[] = [],\n\t): { token: string; expiresIn: number } | undefined {\n\t\tthis.#deleteInactiveTokens(now);\n\t\tif (this.#tokensByHash.size >= MAX_ACCESS_TOKENS) return undefined;\n\t\tconst tokenBytes = randomBytes(ACCESS_TOKEN_BYTES);\n\t\tconst tokenHash = signOAuthAccessTokenBytes(tokenBytes, this.#tokenHashKey);\n\t\tthis.#tokensByHash.set(tokenHash, {\n\t\t\tclientId,\n\t\t\tgrantId,\n\t\t\tscopes: [...scopes],\n\t\t\tresource,\n\t\t\ttokenHash,\n\t\t\tissuedAt: now,\n\t\t\texpiresAt: now + ACCESS_TOKEN_TTL_SECONDS * 1000,\n\t\t\tlastUsedAt: null,\n\t\t\trevokedAt: null,\n\t\t});\n\t\treturn {\n\t\t\ttoken: tokenBytes.toString(\"base64url\"),\n\t\t\texpiresIn: ACCESS_TOKEN_TTL_SECONDS,\n\t\t};\n\t}\n\n\tverifyToken(token: string, now = Date.now()): AccessTokenVerificationResult {\n\t\tconst tokenBytes = decodeOAuthAccessToken(token);\n\t\tif (!tokenBytes) return { ok: false, reason: \"unknown_token\" };\n\t\tconst tokenHash = signOAuthAccessTokenBytes(tokenBytes, this.#tokenHashKey);\n\t\tconst record = this.#tokensByHash.get(tokenHash);\n\t\tif (!record || !isSameTokenHash(record.tokenHash, tokenHash)) {\n\t\t\treturn { ok: false, reason: \"unknown_token\" };\n\t\t}\n\t\tif (record.revokedAt !== null) return { ok: false, reason: \"revoked_token\" };\n\t\tif (record.expiresAt <= now) return { ok: false, reason: \"expired_token\" };\n\t\trecord.lastUsedAt = now;\n\t\treturn { ok: true, record: { ...record } };\n\t}\n\n\trevokeToken(token: string, now = Date.now()): boolean {\n\t\tconst tokenBytes = decodeOAuthAccessToken(token);\n\t\tif (!tokenBytes) return false;\n\t\tconst tokenHash = signOAuthAccessTokenBytes(tokenBytes, this.#tokenHashKey);\n\t\tconst record = this.#tokensByHash.get(tokenHash);\n\t\tif (!record || !isSameTokenHash(record.tokenHash, tokenHash)) return false;\n\t\tif (record.revokedAt !== null) return true;\n\t\trecord.revokedAt = now;\n\t\treturn true;\n\t}\n\n\trevokeTokensForGrant(grantId: string, now = Date.now()): number {\n\t\tlet revoked = 0;\n\t\tfor (const record of this.#tokensByHash.values()) {\n\t\t\tif (record.grantId !== grantId || record.revokedAt !== null) continue;\n\t\t\trecord.revokedAt = now;\n\t\t\trevoked += 1;\n\t\t}\n\t\treturn revoked;\n\t}\n\n\t#deleteInactiveTokens(now: number): void {\n\t\tfor (const [tokenHash, record] of this.#tokensByHash) {\n\t\t\tif (record.expiresAt <= now || record.revokedAt !== null)\n\t\t\t\tthis.#tokensByHash.delete(tokenHash);\n\t\t}\n\t}\n}\n\nexport class InMemoryOAuthRefreshTokenStore implements OAuthRefreshTokenStore {\n\treadonly #grantsById = new Map<string, RefreshTokenGrantRecord>();\n\treadonly #grantIdsByRefreshHash = new Map<string, string>();\n\treadonly #refreshHashesByGrantId = new Map<string, Set<string>>();\n\treadonly #tokenHashKey = randomBytes(32);\n\n\tissueGrant(\n\t\trecord: { clientId: string; scopes?: string[]; resource?: string },\n\t\tnow = Date.now(),\n\t): { grant: RefreshTokenGrantRecord; refreshToken: string; expiresIn: number } | undefined {\n\t\tthis.#deleteInactiveGrants(now);\n\t\tif (this.#grantsById.size >= MAX_REFRESH_GRANTS) return undefined;\n\t\tconst refreshToken = randomToken();\n\t\tconst refreshTokenHash = hashSerializedOAuthToken(refreshToken, this.#tokenHashKey);\n\t\tif (!refreshTokenHash) return undefined;\n\t\tconst grant: RefreshTokenGrantRecord = {\n\t\t\tgrantId: randomUUID(),\n\t\t\tclientId: record.clientId,\n\t\t\tscopes: [...(record.scopes ?? [])],\n\t\t\tresource: record.resource,\n\t\t\tcurrentRefreshTokenHash: refreshTokenHash,\n\t\t\tpreviousRefreshTokenHash: null,\n\t\t\tissuedAt: now,\n\t\t\texpiresAt: now + REFRESH_TOKEN_TTL_SECONDS * 1000,\n\t\t\trotatedAt: null,\n\t\t\trevokedAt: null,\n\t\t};\n\t\tthis.#grantsById.set(grant.grantId, grant);\n\t\tthis.#grantIdsByRefreshHash.set(refreshTokenHash, grant.grantId);\n\t\tthis.#refreshHashesByGrantId.set(grant.grantId, new Set([refreshTokenHash]));\n\t\treturn {\n\t\t\tgrant: { ...grant, scopes: [...grant.scopes] },\n\t\t\trefreshToken,\n\t\t\texpiresIn: REFRESH_TOKEN_TTL_SECONDS,\n\t\t};\n\t}\n\n\trotateRefreshToken(\n\t\tclientId: string,\n\t\trefreshToken: string,\n\t\toptions: { scopes?: string[]; resource?: string } = {},\n\t\tnow = Date.now(),\n\t): RefreshTokenRotationResult {\n\t\tconst tokenHash = hashSerializedOAuthToken(refreshToken, this.#tokenHashKey);\n\t\tif (!tokenHash) return { ok: false, reason: \"unknown_refresh_token\" };\n\t\tconst grantId = this.#grantIdsByRefreshHash.get(tokenHash);\n\t\tif (!grantId) return { ok: false, reason: \"unknown_refresh_token\" };\n\t\tconst grant = this.#grantsById.get(grantId);\n\t\tif (!grant) return { ok: false, reason: \"unknown_refresh_token\" };\n\t\tif (grant.revokedAt !== null) return { ok: false, reason: \"revoked_refresh_token\", grantId };\n\t\tif (grant.expiresAt <= now) {\n\t\t\tthis.revokeGrant(grantId, now);\n\t\t\treturn { ok: false, reason: \"expired_refresh_token\", grantId };\n\t\t}\n\t\tif (grant.clientId !== clientId) return { ok: false, reason: \"client_mismatch\", grantId };\n\t\tif (!isScopeSubset(options.scopes ?? grant.scopes, grant.scopes)) {\n\t\t\treturn { ok: false, reason: \"scope_mismatch\", grantId };\n\t\t}\n\t\tif ((grant.resource ?? null) !== (options.resource ?? grant.resource ?? null)) {\n\t\t\treturn { ok: false, reason: \"resource_mismatch\", grantId };\n\t\t}\n\n\t\tconst matchesCurrent = isSameTokenHash(grant.currentRefreshTokenHash, tokenHash);\n\t\tconst matchesPrevious =\n\t\t\tgrant.previousRefreshTokenHash !== null &&\n\t\t\tisSameTokenHash(grant.previousRefreshTokenHash, tokenHash);\n\t\tif (!matchesCurrent && !matchesPrevious) {\n\t\t\tthis.revokeGrant(grantId, now);\n\t\t\treturn { ok: false, reason: \"refresh_token_replay\", grantId };\n\t\t}\n\n\t\tconst nextRefreshToken = randomToken();\n\t\tconst nextRefreshTokenHash = hashSerializedOAuthToken(nextRefreshToken, this.#tokenHashKey);\n\t\tif (!nextRefreshTokenHash) return { ok: false, reason: \"unknown_refresh_token\" };\n\t\tgrant.scopes = [...(options.scopes ?? grant.scopes)];\n\t\tgrant.previousRefreshTokenHash = matchesCurrent ? grant.currentRefreshTokenHash : null;\n\t\tgrant.currentRefreshTokenHash = nextRefreshTokenHash;\n\t\tgrant.rotatedAt = now;\n\t\tthis.#grantIdsByRefreshHash.set(nextRefreshTokenHash, grantId);\n\t\tthis.#refreshHashesByGrantId.get(grantId)?.add(nextRefreshTokenHash);\n\t\treturn {\n\t\t\tok: true,\n\t\t\tgrant: { ...grant, scopes: [...grant.scopes] },\n\t\t\trefreshToken: nextRefreshToken,\n\t\t\texpiresIn: Math.max(0, Math.floor((grant.expiresAt - now) / 1000)),\n\t\t};\n\t}\n\n\trevokeRefreshToken(token: string, now = Date.now()): string | undefined {\n\t\tconst tokenHash = hashSerializedOAuthToken(token, this.#tokenHashKey);\n\t\tif (!tokenHash) return undefined;\n\t\tconst grantId = this.#grantIdsByRefreshHash.get(tokenHash);\n\t\tif (!grantId) return undefined;\n\t\tthis.revokeGrant(grantId, now);\n\t\treturn grantId;\n\t}\n\n\trevokeGrant(grantId: string, now = Date.now()): boolean {\n\t\tconst grant = this.#grantsById.get(grantId);\n\t\tif (!grant) return false;\n\t\tif (grant.revokedAt !== null) return true;\n\t\tgrant.revokedAt = now;\n\t\tthis.#deleteGrantRefreshHashIndexEntries(grant);\n\t\treturn true;\n\t}\n\n\t#deleteInactiveGrants(now: number): void {\n\t\tfor (const [grantId, grant] of this.#grantsById) {\n\t\t\tif (grant.expiresAt > now && grant.revokedAt === null) continue;\n\t\t\tthis.#grantsById.delete(grantId);\n\t\t\tthis.#deleteGrantRefreshHashIndexEntries(grant);\n\t\t}\n\t}\n\n\t#deleteGrantRefreshHashIndexEntries(grant: RefreshTokenGrantRecord): void {\n\t\tconst refreshHashes = this.#refreshHashesByGrantId.get(grant.grantId);\n\t\tif (refreshHashes) {\n\t\t\tfor (const refreshHash of refreshHashes) this.#grantIdsByRefreshHash.delete(refreshHash);\n\t\t\tthis.#refreshHashesByGrantId.delete(grant.grantId);\n\t\t\treturn;\n\t\t}\n\t\tthis.#grantIdsByRefreshHash.delete(grant.currentRefreshTokenHash);\n\t\tif (grant.previousRefreshTokenHash)\n\t\t\tthis.#grantIdsByRefreshHash.delete(grant.previousRefreshTokenHash);\n\t}\n}\n\nexport function createInMemoryOAuthClientsStore(): OAuthRegisteredClientsStore {\n\treturn new InMemoryOAuthClientsStore();\n}\n\nexport function createInMemoryOAuthAuthorizationCodeStore(): OAuthAuthorizationCodeStore {\n\treturn new InMemoryOAuthAuthorizationCodeStore();\n}\n\nexport function createInMemoryOAuthAccessTokenStore(): OAuthAccessTokenStore {\n\treturn new InMemoryOAuthAccessTokenStore();\n}\n\nexport function createInMemoryOAuthRefreshTokenStore(): OAuthRefreshTokenStore {\n\treturn new InMemoryOAuthRefreshTokenStore();\n}\n\nexport function createMcpOAuthMetadata(options: McpOAuthMetadataOptions): OAuthMetadata {\n\tconst mcpUrl = normalizeMcpPublicUrl(options.mcpUrl);\n\tconst issuerUrl = getOriginUrl(mcpUrl);\n\tconst provider = createMetadataOnlyProvider(options.clientsStore);\n\treturn {\n\t\t...createOAuthMetadata({\n\t\t\tprovider,\n\t\t\tissuerUrl,\n\t\t\tbaseUrl: issuerUrl,\n\t\t}),\n\t\t// Phase 1 treats claude.ai and local callback clients as public clients.\n\t\t// Do not issue or advertise client secrets until we have a concrete need.\n\t\tgrant_types_supported: [\"authorization_code\", \"refresh_token\"],\n\t\ttoken_endpoint_auth_methods_supported: [\"none\"],\n\t\tscopes_supported: MCP_OAUTH_SCOPES_SUPPORTED,\n\t\tservice_documentation: MCP_OAUTH_SERVICE_DOCUMENTATION_URL,\n\t\trevocation_endpoint: new URL(\"/revoke\", issuerUrl).href,\n\t\trevocation_endpoint_auth_methods_supported: [\"none\"],\n\t\tclient_id_metadata_document_supported: false,\n\t};\n}\n\nexport function createMcpProtectedResourceMetadata(mcpUrl: string): OAuthProtectedResourceMetadata {\n\tconst normalizedMcpUrl = normalizeMcpPublicUrl(mcpUrl);\n\tconst metadata = {\n\t\tresource: normalizedMcpUrl.href,\n\t\tauthorization_servers: [getOriginUrl(normalizedMcpUrl).href],\n\t\tscopes_supported: MCP_OAUTH_SCOPES_SUPPORTED,\n\t\tbearer_methods_supported: [\"header\"],\n\t\tresource_name: MCP_OAUTH_RESOURCE_NAME,\n\t\tresource_documentation: MCP_OAUTH_SERVICE_DOCUMENTATION_URL,\n\t};\n\treturn OAuthProtectedResourceMetadataSchema.parse(metadata);\n}\n\nexport function registerMcpOAuthClient(\n\trequestBody: unknown,\n\tclientsStore: OAuthRegisteredClientsStore,\n): RegisteredMcpOAuthClient | McpOAuthRegistrationError {\n\tif (!clientsStore.registerClient) {\n\t\treturn invalidClientMetadata(\"Dynamic client registration is not enabled\");\n\t}\n\n\tconst parseResult = OAuthClientMetadataSchema.safeParse(requestBody);\n\tif (!parseResult.success) {\n\t\treturn invalidClientMetadata(parseResult.error.message);\n\t}\n\n\tconst clientMetadata = parseResult.data;\n\tconst redirectError = validateRedirectUris(clientMetadata.redirect_uris);\n\tif (redirectError) return invalidClientMetadata(redirectError);\n\n\tif (!isSupportedTokenEndpointAuthMethod(clientMetadata.token_endpoint_auth_method)) {\n\t\treturn invalidClientMetadata(\n\t\t\t\"Only public clients with token_endpoint_auth_method=none are supported\",\n\t\t);\n\t}\n\n\tif (\n\t\tclientMetadata.grant_types &&\n\t\t!isSupportedList(clientMetadata.grant_types, SUPPORTED_GRANT_TYPES)\n\t) {\n\t\treturn invalidClientMetadata(\n\t\t\t\"Only authorization_code and refresh_token grant_types are supported\",\n\t\t);\n\t}\n\n\tif (\n\t\tclientMetadata.response_types &&\n\t\t!isSupportedList(clientMetadata.response_types, SUPPORTED_RESPONSE_TYPES)\n\t) {\n\t\treturn invalidClientMetadata(\"Only code response_type is supported\");\n\t}\n\n\tconst registered = clientsStore.registerClient({\n\t\t...clientMetadata,\n\t\ttoken_endpoint_auth_method: \"none\",\n\t\tgrant_types: clientMetadata.grant_types ?? [\"authorization_code\", \"refresh_token\"],\n\t\tresponse_types: clientMetadata.response_types ?? [\"code\"],\n\t});\n\n\tif (registered instanceof Promise) {\n\t\tthrow new Error(\n\t\t\t\"Asynchronous OAuth client stores are not supported by this HTTP bootstrap yet\",\n\t\t);\n\t}\n\n\treturn { status: 201, body: registered };\n}\n\nexport function authorizeMcpOAuthClient(\n\tparams: URLSearchParams,\n\tclientsStore: OAuthRegisteredClientsStore,\n\tcodeStore: OAuthAuthorizationCodeStore,\n\tnow = Date.now(),\n): McpOAuthRedirectResult | McpOAuthErrorResult {\n\tconst prepared = prepareMcpOAuthAuthorizationRequest(params, clientsStore);\n\tif (\"status\" in prepared) return prepared;\n\n\tconst code = codeStore.issueCode(\n\t\t{\n\t\t\tclientId: prepared.clientId,\n\t\t\tredirectUri: prepared.redirectUri,\n\t\t\tcodeChallenge: prepared.codeChallenge,\n\t\t\tscopes: prepared.scopes,\n\t\t\t...(prepared.resource ? { resource: prepared.resource } : {}),\n\t\t\texpiresAt: now + AUTHORIZATION_CODE_TTL_MS,\n\t\t},\n\t\tnow,\n\t);\n\tif (!code)\n\t\treturn invalidOAuthRequest(\"temporarily_unavailable\", \"Too many active authorization codes\");\n\tconst redirect = new URL(prepared.redirectUri);\n\tredirect.searchParams.set(\"code\", code);\n\tif (prepared.state !== null) redirect.searchParams.set(\"state\", prepared.state);\n\treturn { status: 302, location: redirect.href };\n}\n\nexport function prepareMcpOAuthAuthorizationRequest(\n\tparams: URLSearchParams,\n\tclientsStore: OAuthRegisteredClientsStore,\n): PreparedMcpOAuthAuthorizationRequest | McpOAuthErrorResult {\n\tconst clientId = params.get(\"client_id\") ?? \"\";\n\tconst redirectUri = params.get(\"redirect_uri\") ?? \"\";\n\tconst responseType = params.get(\"response_type\") ?? \"\";\n\tconst codeChallenge = params.get(\"code_challenge\") ?? \"\";\n\tconst codeChallengeMethod = params.get(\"code_challenge_method\") ?? \"\";\n\tconst resource = params.get(\"resource\");\n\tconst scopes = parseScopeList(params.get(\"scope\"));\n\tconst state = params.get(\"state\");\n\n\tif (responseType !== \"code\") return invalidOAuthRequest(\"unsupported_response_type\");\n\tif (codeChallengeMethod !== \"S256\") {\n\t\treturn invalidOAuthRequest(\"invalid_request\", \"PKCE code_challenge_method=S256 is required\");\n\t}\n\tif (!PKCE_S256_CHALLENGE.test(codeChallenge)) {\n\t\treturn invalidOAuthRequest(\"invalid_request\", \"Valid PKCE S256 code_challenge is required\");\n\t}\n\n\tconst client = getRegisteredClient(clientsStore, clientId);\n\tif (!client) return invalidOAuthRequest(\"invalid_client\", \"Unknown OAuth client_id\");\n\tif (!client.redirect_uris.includes(redirectUri)) {\n\t\treturn invalidOAuthRequest(\"invalid_request\", \"redirect_uri is not registered for this client\");\n\t}\n\n\treturn { clientId, redirectUri, codeChallenge, scopes, resource, state };\n}\n\nexport function exchangeMcpOAuthAuthorizationCode(\n\tparams: URLSearchParams,\n\tclientsStore: OAuthRegisteredClientsStore,\n\tcodeStore: OAuthAuthorizationCodeStore,\n\ttokenStore: OAuthAccessTokenStore,\n\tnow = Date.now(),\n): McpOAuthTokenResult | McpOAuthErrorResult {\n\tif ((params.get(\"grant_type\") ?? \"\") !== \"authorization_code\") {\n\t\treturn invalidOAuthRequest(\"unsupported_grant_type\", \"Only authorization_code is supported\");\n\t}\n\n\tconst clientId = params.get(\"client_id\") ?? \"\";\n\tconst code = params.get(\"code\") ?? \"\";\n\tconst redirectUri = params.get(\"redirect_uri\") ?? \"\";\n\tconst codeVerifier = params.get(\"code_verifier\") ?? \"\";\n\tconst resource = params.get(\"resource\");\n\tconst client = getRegisteredClient(clientsStore, clientId);\n\tif (!client) return invalidOAuthRequest(\"invalid_client\", \"Unknown OAuth client_id\");\n\tif (!PKCE_VERIFIER.test(codeVerifier)) {\n\t\treturn invalidOAuthRequest(\"invalid_grant\", \"Invalid PKCE code_verifier\");\n\t}\n\n\t// Peek the authorization code without consuming it so a transient token-\n\t// store overflow (`temporarily_unavailable`) leaves the code reusable; only\n\t// permanent grant failures (expiry, client/redirect mismatch, PKCE) consume\n\t// the code. The code is finally consumed atomically with token issuance.\n\tconst record = codeStore.peekCode(code);\n\tif (!record) return invalidOAuthRequest(\"invalid_grant\", \"Invalid or already used code\");\n\tif (record.expiresAt <= now) {\n\t\tcodeStore.consumeCode(code);\n\t\treturn invalidOAuthRequest(\"invalid_grant\", \"Expired code\");\n\t}\n\tif (record.clientId !== clientId || record.redirectUri !== redirectUri) {\n\t\tcodeStore.consumeCode(code);\n\t\treturn invalidOAuthRequest(\"invalid_grant\", \"Code does not match client or redirect_uri\");\n\t}\n\tif (pkceS256(codeVerifier) !== record.codeChallenge) {\n\t\tcodeStore.consumeCode(code);\n\t\treturn invalidOAuthRequest(\"invalid_grant\", \"PKCE verification failed\");\n\t}\n\tif ((record.resource ?? null) !== (resource || null)) {\n\t\tcodeStore.consumeCode(code);\n\t\treturn invalidOAuthRequest(\"invalid_grant\", \"Code does not match resource\");\n\t}\n\n\tconst issued = tokenStore.issueToken(clientId, now, record.resource, undefined, record.scopes);\n\tif (!issued) {\n\t\t// Token-store overload is transient: leave the auth code unused so the\n\t\t// client can retry token exchange without restarting the OAuth flow.\n\t\treturn invalidOAuthRequest(\"temporarily_unavailable\", \"Too many active access tokens\");\n\t}\n\n\tconst consumed = codeStore.consumeCode(code);\n\tif (!consumed) {\n\t\ttokenStore.revokeToken(issued.token, now);\n\t\t// Lost a race with another request that consumed the code in the gap\n\t\t// between peek and consume. Treat as invalid_grant rather than issuing\n\t\t// a duplicate usable token, since the code is no longer single-use atomic.\n\t\treturn invalidOAuthRequest(\"invalid_grant\", \"Authorization code already used\");\n\t}\n\n\tconst tokens = OAuthTokensSchema.parse({\n\t\taccess_token: issued.token,\n\t\ttoken_type: \"Bearer\",\n\t\texpires_in: issued.expiresIn,\n\t});\n\treturn { status: 200, body: tokens };\n}\n\nexport function revokeMcpOAuthAccessToken(\n\tparams: URLSearchParams,\n\ttokenStore: OAuthAccessTokenStore,\n): { status: 200; body: Record<string, never> } {\n\tconst token = params.get(\"token\") ?? \"\";\n\ttokenStore.revokeToken(token);\n\treturn { status: 200, body: {} };\n}\n\nexport function normalizeMcpPublicUrl(value: string): URL {\n\tlet url: URL;\n\ttry {\n\t\turl = new URL(value);\n\t} catch {\n\t\tthrow new Error(\"Invalid MCP HTTP public URL; expected an HTTPS /mcp URL\");\n\t}\n\tif (url.protocol !== \"https:\" && !isLoopbackUrl(url)) {\n\t\tthrow new Error(\"Invalid MCP HTTP public URL; use HTTPS for non-loopback URLs\");\n\t}\n\tif (url.username || url.password || url.search || url.hash) {\n\t\tthrow new Error(\n\t\t\t\"Invalid MCP HTTP public URL; credentials, query strings, and fragments are not allowed\",\n\t\t);\n\t}\n\tif (url.pathname === \"/\") url.pathname = \"/mcp\";\n\tif (url.pathname !== \"/mcp\") {\n\t\tthrow new Error(\"Invalid MCP HTTP public URL; expected /mcp path\");\n\t}\n\treturn url;\n}\n\nfunction getOriginUrl(url: URL): URL {\n\treturn new URL(url.origin);\n}\n\nfunction validateRedirectUris(redirectUris: OAuthClientMetadata[\"redirect_uris\"]): string | null {\n\tfor (const redirectUri of redirectUris) {\n\t\tconst url = new URL(redirectUri);\n\t\tif (url.username || url.password || url.hash) return `Invalid redirect URI: ${redirectUri}`;\n\t\tif (url.href === CLAUDE_HOSTED_CALLBACK) continue;\n\t\tif (isLoopbackCallbackUrl(url)) continue;\n\t\treturn `Unsupported redirect URI: ${redirectUri}`;\n\t}\n\treturn null;\n}\n\nfunction isSupportedTokenEndpointAuthMethod(method: string | undefined): boolean {\n\treturn method === undefined || method === \"none\";\n}\n\nfunction isSupportedList(values: string[], supported: Set<string>): boolean {\n\treturn values.length > 0 && values.every((value) => supported.has(value));\n}\n\nfunction isLoopbackCallbackUrl(url: URL): boolean {\n\treturn (\n\t\turl.protocol === \"http:\" &&\n\t\tLOCAL_CALLBACK_HOSTS.has(normalizeHostname(url.hostname)) &&\n\t\turl.pathname === \"/callback\" &&\n\t\turl.search === \"\"\n\t);\n}\n\nfunction isLoopbackUrl(url: URL): boolean {\n\tconst hostname = normalizeHostname(url.hostname);\n\treturn url.protocol === \"http:\" && LOCAL_CALLBACK_HOSTS.has(hostname);\n}\n\nfunction normalizeHostname(hostname: string): string {\n\treturn hostname.replace(/^\\[(.*)]$/, \"$1\").toLowerCase();\n}\n\nfunction parseScopeList(scope: string | null | undefined): string[] {\n\treturn (\n\t\tscope\n\t\t\t?.split(/\\s+/)\n\t\t\t.map((item) => item.trim())\n\t\t\t.filter(Boolean) ?? []\n\t);\n}\n\nfunction invalidClientMetadata(description: string): McpOAuthRegistrationError {\n\treturn {\n\t\tstatus: 400,\n\t\tbody: { error: \"invalid_client_metadata\", error_description: description },\n\t};\n}\n\nfunction invalidOAuthRequest(error: string, description?: string): McpOAuthErrorResult {\n\treturn {\n\t\tstatus: 400,\n\t\tbody: description ? { error, error_description: description } : { error },\n\t};\n}\n\nfunction getRegisteredClient(\n\tclientsStore: OAuthRegisteredClientsStore,\n\tclientId: string,\n): OAuthClientInformationFull | undefined {\n\tconst client = clientsStore.getClient(clientId);\n\tif (client instanceof Promise) {\n\t\tthrow new Error(\n\t\t\t\"Asynchronous OAuth client stores are not supported by this HTTP bootstrap yet\",\n\t\t);\n\t}\n\treturn client;\n}\n\nfunction pkceS256(codeVerifier: string): string {\n\treturn createHash(\"sha256\").update(codeVerifier).digest(\"base64url\");\n}\n\n// Decode an externally-supplied access-token string into the fixed-length\n// random Buffer it represents. Rejects anything that is not a base64url-encoded\n// ACCESS_TOKEN_BYTES-length value, so invalid input never reaches the HMAC\n// signer. Returns null on any decode/length mismatch.\nfunction decodeOAuthAccessToken(serialized: string): Buffer | null {\n\tif (typeof serialized !== \"string\") return null;\n\tif (serialized.length !== ACCESS_TOKEN_BASE64URL_LENGTH) return null;\n\tif (!ACCESS_TOKEN_BASE64URL.test(serialized)) return null;\n\tconst bytes = Buffer.from(serialized, \"base64url\");\n\tif (bytes.length !== ACCESS_TOKEN_BYTES) return null;\n\treturn bytes;\n}\n\nfunction randomToken(): string {\n\treturn randomBytes(ACCESS_TOKEN_BYTES).toString(\"base64url\");\n}\n\nfunction hashSerializedOAuthToken(serialized: string, key: Buffer): string | null {\n\tconst tokenBytes = decodeOAuthAccessToken(serialized);\n\tif (!tokenBytes) return null;\n\treturn signOAuthToken(tokenBytes, key);\n}\n\n// Compute the HMAC-SHA256 signature of the binary access-token material using\n// the per-store random key. This is an integrity signature over a random\n// 256-bit value, not password hashing; tokens are validated by re-signing the\n// presented bytes and comparing the digest to the stored signature.\nfunction signOAuthAccessTokenBytes(material: Buffer, key: Buffer): string {\n\treturn signOAuthToken(material, key);\n}\n\nfunction signOAuthToken(material: Buffer | string, key: Buffer): string {\n\treturn createHmac(\"sha256\", key).update(material).digest(\"base64url\");\n}\n\nfunction isSameTokenHash(left: string, right: string): boolean {\n\tconst leftBuffer = Buffer.from(left);\n\tconst rightBuffer = Buffer.from(right);\n\treturn leftBuffer.length === rightBuffer.length && timingSafeEqual(leftBuffer, rightBuffer);\n}\n\nfunction isScopeSubset(requested: string[], granted: string[]): boolean {\n\tconst grantedScopes = new Set(granted);\n\treturn requested.every((scope) => grantedScopes.has(scope));\n}\n\nfunction createMetadataOnlyProvider(\n\tclientsStore: OAuthRegisteredClientsStore,\n): OAuthServerProvider {\n\treturn {\n\t\tclientsStore,\n\t\tasync authorize() {\n\t\t\tthrow new Error(\"OAuth authorize is not implemented yet\");\n\t\t},\n\t\tasync challengeForAuthorizationCode() {\n\t\t\tthrow new Error(\"OAuth token exchange is not implemented yet\");\n\t\t},\n\t\tasync exchangeAuthorizationCode() {\n\t\t\tthrow new Error(\"OAuth token exchange is not implemented yet\");\n\t\t},\n\t\tasync exchangeRefreshToken() {\n\t\t\tthrow new Error(\"OAuth refresh is not implemented yet\");\n\t\t},\n\t\tasync verifyAccessToken() {\n\t\t\tthrow new Error(\"OAuth bearer verification is not implemented yet\");\n\t\t},\n\t};\n}\n","import { createPublicKey, randomUUID, verify } from \"node:crypto\";\nimport type { OAuthRegisteredClientsStore } from \"@modelcontextprotocol/sdk/server/auth/clients.js\";\nimport {\n\ttype McpOAuthErrorResult,\n\ttype McpOAuthRedirectResult,\n\tprepareMcpOAuthAuthorizationRequest,\n} from \"./oauth.js\";\n\nexport const MCP_OIDC_ISSUER_URL_ENV = \"CODEMEM_MCP_OIDC_ISSUER_URL\";\nexport const MCP_OIDC_CLIENT_ID_ENV = \"CODEMEM_MCP_OIDC_CLIENT_ID\";\nexport const MCP_OIDC_CLIENT_SECRET_ENV = \"CODEMEM_MCP_OIDC_CLIENT_SECRET\";\nexport const MCP_OAUTH_ALLOWED_SUBJECT_ENV = \"CODEMEM_MCP_OAUTH_ALLOWED_SUBJECT\";\nexport const MCP_OAUTH_ALLOWED_EMAIL_ENV = \"CODEMEM_MCP_OAUTH_ALLOWED_EMAIL\";\n\nconst PENDING_AUTH_TTL_MS = 5 * 60 * 1000;\nconst MAX_PENDING_AUTH = 100;\nconst ID_TOKEN_CLOCK_SKEW_MS = 5 * 60 * 1000;\n\ntype JsonWebKey = Record<string, unknown>;\n\nexport interface OidcConfig {\n\tissuerUrl: string;\n\tclientId: string;\n\tclientSecret: string;\n\tallowedSubject?: string;\n\tallowedEmail?: string;\n}\n\nexport interface PendingOidcAuthorization {\n\toauthParams: string;\n\tnonce: string;\n\texpiresAt: number;\n}\n\nexport interface OidcPendingAuthorizationStore {\n\tissue(record: Omit<PendingOidcAuthorization, \"expiresAt\">, now?: number): string | undefined;\n\tconsume(state: string): PendingOidcAuthorization | undefined;\n}\n\ninterface OidcDiscoveryMetadata {\n\tissuer: string;\n\tauthorization_endpoint: string;\n\ttoken_endpoint: string;\n\tjwks_uri: string;\n}\n\ninterface OidcTokensResponse {\n\tid_token?: string;\n\terror?: string;\n\terror_description?: string;\n}\n\ninterface JwtHeader {\n\talg?: string;\n\tkid?: string;\n}\n\ninterface JwtClaims {\n\tiss?: string;\n\taud?: string | string[];\n\tazp?: string;\n\texp?: number;\n\tiat?: number;\n\tnonce?: string;\n\tsub?: string;\n\temail?: string;\n\temail_verified?: boolean;\n}\n\ninterface JsonWebKeySet {\n\tkeys?: JsonWebKey[];\n}\n\nexport class InMemoryOidcPendingAuthorizationStore implements OidcPendingAuthorizationStore {\n\treadonly #records = new Map<string, PendingOidcAuthorization>();\n\n\tissue(record: Omit<PendingOidcAuthorization, \"expiresAt\">, now = Date.now()): string | undefined {\n\t\tthis.#deleteExpired(now);\n\t\tif (this.#records.size >= MAX_PENDING_AUTH) return undefined;\n\t\tconst state = randomUUID();\n\t\tthis.#records.set(state, { ...record, expiresAt: now + PENDING_AUTH_TTL_MS });\n\t\treturn state;\n\t}\n\n\tconsume(state: string): PendingOidcAuthorization | undefined {\n\t\tconst record = this.#records.get(state);\n\t\tthis.#records.delete(state);\n\t\treturn record;\n\t}\n\n\t#deleteExpired(now: number): void {\n\t\tfor (const [state, record] of this.#records) {\n\t\t\tif (record.expiresAt <= now) this.#records.delete(state);\n\t\t}\n\t}\n}\n\nexport function createInMemoryOidcPendingAuthorizationStore(): OidcPendingAuthorizationStore {\n\treturn new InMemoryOidcPendingAuthorizationStore();\n}\n\nexport function resolveOidcConfig(env: NodeJS.ProcessEnv = process.env): OidcConfig | undefined {\n\tconst issuerUrl = env[MCP_OIDC_ISSUER_URL_ENV]?.trim();\n\tconst clientId = env[MCP_OIDC_CLIENT_ID_ENV]?.trim();\n\tconst clientSecret = env[MCP_OIDC_CLIENT_SECRET_ENV]?.trim();\n\tconst allowedSubject = env[MCP_OAUTH_ALLOWED_SUBJECT_ENV]?.trim();\n\tconst allowedEmail = env[MCP_OAUTH_ALLOWED_EMAIL_ENV]?.trim().toLowerCase();\n\tif (!issuerUrl && !clientId && !clientSecret && !allowedSubject && !allowedEmail)\n\t\treturn undefined;\n\tif (!issuerUrl || !clientId || !clientSecret) {\n\t\tthrow new Error(\"Incomplete MCP OIDC configuration\");\n\t}\n\tvalidateOidcUrl(issuerUrl, \"issuer\", { allowLoopbackHttp: true });\n\tif (!allowedSubject && !allowedEmail) {\n\t\tthrow new Error(\n\t\t\t\"MCP OIDC requires CODEMEM_MCP_OAUTH_ALLOWED_SUBJECT or CODEMEM_MCP_OAUTH_ALLOWED_EMAIL\",\n\t\t);\n\t}\n\treturn { issuerUrl, clientId, clientSecret, allowedSubject, allowedEmail };\n}\n\nexport async function beginOidcAuthorization(\n\tparams: URLSearchParams,\n\tclientsStore: OAuthRegisteredClientsStore,\n\tpendingStore: OidcPendingAuthorizationStore,\n\tconfig: OidcConfig | undefined,\n\tpublicMcpUrl: string,\n\tnow = Date.now(),\n): Promise<McpOAuthRedirectResult | McpOAuthErrorResult> {\n\tif (!config) return invalidOAuthRequest(\"temporarily_unavailable\", \"OIDC is not configured\");\n\tconst prepared = prepareMcpOAuthAuthorizationRequest(params, clientsStore);\n\tif (\"status\" in prepared) return prepared;\n\n\tconst discovery = await fetchOidcDiscovery(config.issuerUrl);\n\tconst nonce = randomUUID();\n\tconst upstreamState = pendingStore.issue({ oauthParams: params.toString(), nonce }, now);\n\tif (!upstreamState)\n\t\treturn invalidOAuthRequest(\"temporarily_unavailable\", \"Too many pending OIDC authorizations\");\n\n\tconst redirectUri = getCallbackUrl(publicMcpUrl);\n\tconst upstream = new URL(discovery.authorization_endpoint);\n\tupstream.searchParams.set(\"response_type\", \"code\");\n\tupstream.searchParams.set(\"client_id\", config.clientId);\n\tupstream.searchParams.set(\"redirect_uri\", redirectUri);\n\tupstream.searchParams.set(\"scope\", \"openid email\");\n\tupstream.searchParams.set(\"state\", upstreamState);\n\tupstream.searchParams.set(\"nonce\", nonce);\n\treturn { status: 302, location: upstream.href };\n}\n\nexport async function completeOidcAuthorization(\n\tcallbackParams: URLSearchParams,\n\tpendingStore: OidcPendingAuthorizationStore,\n\tconfig: OidcConfig,\n\tpublicMcpUrl: string,\n\tnow = Date.now(),\n): Promise<{ oauthParams: URLSearchParams } | McpOAuthErrorResult> {\n\ttry {\n\t\tconst code = callbackParams.get(\"code\") ?? \"\";\n\t\tconst state = callbackParams.get(\"state\") ?? \"\";\n\t\tif (!state) return invalidOAuthRequest(\"invalid_request\", \"Missing OIDC state\");\n\t\tconst pending = pendingStore.consume(state);\n\t\tif (!pending || pending.expiresAt <= now)\n\t\t\treturn invalidOAuthRequest(\"invalid_request\", \"Expired or unknown OIDC state\");\n\t\tif (!code) return invalidOAuthRequest(\"invalid_request\", \"Missing OIDC code\");\n\n\t\tconst discovery = await fetchOidcDiscovery(config.issuerUrl);\n\t\tconst tokens = await exchangeOidcCode(\n\t\t\tdiscovery.token_endpoint,\n\t\t\tconfig,\n\t\t\tgetCallbackUrl(publicMcpUrl),\n\t\t\tcode,\n\t\t);\n\t\tif (!tokens.id_token)\n\t\t\treturn invalidOAuthRequest(\"invalid_request\", \"OIDC token exchange failed\");\n\t\tconst claims = await validateIdToken(\n\t\t\ttokens.id_token,\n\t\t\tdiscovery,\n\t\t\tconfig.clientId,\n\t\t\tpending.nonce,\n\t\t\tnow,\n\t\t);\n\t\tif (!isAllowedIdentity(claims, config))\n\t\t\treturn invalidOAuthRequest(\"access_denied\", \"OIDC identity is not allowed\");\n\n\t\treturn { oauthParams: new URLSearchParams(pending.oauthParams) };\n\t} catch {\n\t\treturn invalidOAuthRequest(\"access_denied\", \"OIDC identity verification failed\");\n\t}\n}\n\nfunction getCallbackUrl(publicMcpUrl: string): string {\n\tconst url = new URL(publicMcpUrl);\n\treturn new URL(\"/oauth/callback\", url.origin).href;\n}\n\nasync function fetchOidcDiscovery(issuerUrl: string): Promise<OidcDiscoveryMetadata> {\n\tconst issuer = new URL(issuerUrl);\n\tif (issuer.search || issuer.hash)\n\t\tthrow new Error(\"OIDC issuer must not include query or fragment\");\n\tif (issuer.username || issuer.password)\n\t\tthrow new Error(\"OIDC issuer must not include credentials\");\n\tconst discoveryUrl = new URL(\n\t\t`${issuer.pathname.replace(/\\/$/, \"\")}/.well-known/openid-configuration`,\n\t\tissuer.origin,\n\t);\n\tconst response = await fetch(discoveryUrl);\n\tif (!response.ok) throw new Error(\"OIDC discovery request failed\");\n\tconst metadata = (await response.json()) as Partial<OidcDiscoveryMetadata>;\n\tif (metadata.issuer !== issuer.href && metadata.issuer !== issuer.href.replace(/\\/$/, \"\")) {\n\t\tthrow new Error(\"OIDC discovery issuer mismatch\");\n\t}\n\tif (!metadata.authorization_endpoint || !metadata.token_endpoint || !metadata.jwks_uri) {\n\t\tthrow new Error(\"OIDC discovery metadata is incomplete\");\n\t}\n\tconst allowLoopbackHttp = issuer.protocol === \"http:\" && isLoopbackHostname(issuer.hostname);\n\tvalidateOidcUrl(metadata.authorization_endpoint, \"authorization endpoint\", { allowLoopbackHttp });\n\tvalidateOidcUrl(metadata.token_endpoint, \"token endpoint\", { allowLoopbackHttp });\n\tvalidateOidcUrl(metadata.jwks_uri, \"JWKS URI\", { allowLoopbackHttp });\n\treturn metadata as OidcDiscoveryMetadata;\n}\n\nasync function exchangeOidcCode(\n\ttokenEndpoint: string,\n\tconfig: OidcConfig,\n\tredirectUri: string,\n\tcode: string,\n): Promise<OidcTokensResponse> {\n\tconst body = new URLSearchParams({\n\t\tgrant_type: \"authorization_code\",\n\t\tcode,\n\t\tredirect_uri: redirectUri,\n\t\tclient_id: config.clientId,\n\t\tclient_secret: config.clientSecret,\n\t});\n\tconst response = await fetch(tokenEndpoint, {\n\t\tmethod: \"POST\",\n\t\theaders: { \"content-type\": \"application/x-www-form-urlencoded\" },\n\t\tbody,\n\t});\n\tif (!response.ok) throw new Error(\"OIDC token request failed\");\n\treturn (await response.json()) as OidcTokensResponse;\n}\n\nasync function validateIdToken(\n\tidToken: string,\n\tdiscovery: OidcDiscoveryMetadata,\n\tclientId: string,\n\tnonce: string,\n\tnow: number,\n): Promise<JwtClaims> {\n\tconst [encodedHeader, encodedClaims, signature] = idToken.split(\".\");\n\tif (!encodedHeader || !encodedClaims || !signature) throw new Error(\"Invalid OIDC id_token\");\n\tconst header = parseJwtPart<JwtHeader>(encodedHeader);\n\tconst claims = parseJwtPart<JwtClaims>(encodedClaims);\n\tif (header.alg !== \"RS256\" || !header.kid) throw new Error(\"Unsupported OIDC id_token signature\");\n\tif (claims.iss !== discovery.issuer) throw new Error(\"OIDC id_token issuer mismatch\");\n\tif (!audienceIncludes(claims.aud, clientId)) throw new Error(\"OIDC id_token audience mismatch\");\n\tif (!isValidAuthorizedParty(claims.aud, claims.azp, clientId))\n\t\tthrow new Error(\"OIDC id_token authorized party mismatch\");\n\tif (typeof claims.exp !== \"number\" || !Number.isFinite(claims.exp) || claims.exp * 1000 <= now)\n\t\tthrow new Error(\"OIDC id_token is expired\");\n\tif (typeof claims.iat !== \"number\" || !Number.isFinite(claims.iat))\n\t\tthrow new Error(\"OIDC id_token issued-at time is missing\");\n\tif (claims.iat * 1000 > now + ID_TOKEN_CLOCK_SKEW_MS)\n\t\tthrow new Error(\"OIDC id_token issued-at time is in the future\");\n\tif (claims.nonce !== nonce) throw new Error(\"OIDC id_token nonce mismatch\");\n\tif (!claims.sub) throw new Error(\"OIDC id_token subject is missing\");\n\n\tconst jwksResponse = await fetch(discovery.jwks_uri);\n\tif (!jwksResponse.ok) throw new Error(\"OIDC JWKS request failed\");\n\tconst jwks = (await jwksResponse.json()) as JsonWebKeySet;\n\tconst jwk = jwks.keys?.find((key) => key.kid === header.kid && key.kty === \"RSA\");\n\tif (!jwk) throw new Error(\"OIDC signing key not found\");\n\tconst key = createPublicKey({ key: jwk, format: \"jwk\" });\n\tconst signed = `${encodedHeader}.${encodedClaims}`;\n\tconst ok = verify(\"RSA-SHA256\", Buffer.from(signed), key, Buffer.from(signature, \"base64url\"));\n\tif (!ok) throw new Error(\"OIDC id_token signature verification failed\");\n\treturn claims;\n}\n\nfunction parseJwtPart<T>(encoded: string): T {\n\treturn JSON.parse(Buffer.from(encoded, \"base64url\").toString(\"utf8\")) as T;\n}\n\nfunction audienceIncludes(audience: string | string[] | undefined, clientId: string): boolean {\n\treturn Array.isArray(audience) ? audience.includes(clientId) : audience === clientId;\n}\n\nfunction isValidAuthorizedParty(\n\taudience: string | string[] | undefined,\n\tauthorizedParty: string | undefined,\n\tclientId: string,\n): boolean {\n\tif (authorizedParty && authorizedParty !== clientId) return false;\n\treturn !Array.isArray(audience) || audience.length <= 1 || authorizedParty === clientId;\n}\n\nfunction isAllowedIdentity(claims: JwtClaims, config: OidcConfig): boolean {\n\tif (config.allowedSubject && claims.sub === config.allowedSubject) return true;\n\tif (!config.allowedEmail) return false;\n\treturn claims.email_verified === true && claims.email?.toLowerCase() === config.allowedEmail;\n}\n\nfunction validateOidcUrl(\n\tvalue: string,\n\tlabel: string,\n\toptions: { allowLoopbackHttp?: boolean } = {},\n): void {\n\tconst url = new URL(value);\n\tif (url.username || url.password) throw new Error(`OIDC ${label} must not include credentials`);\n\tif (url.protocol === \"https:\") return;\n\tif (options.allowLoopbackHttp && url.protocol === \"http:\" && isLoopbackHostname(url.hostname))\n\t\treturn;\n\tthrow new Error(`OIDC ${label} must use HTTPS`);\n}\n\nfunction isLoopbackHostname(hostname: string): boolean {\n\tconst normalized = hostname.replace(/^\\[(.*)]$/, \"$1\").toLowerCase();\n\treturn normalized === \"localhost\" || normalized === \"127.0.0.1\" || normalized === \"::1\";\n}\n\nfunction invalidOAuthRequest(error: string, description?: string): McpOAuthErrorResult {\n\treturn {\n\t\tstatus: 400,\n\t\tbody: description ? { error, error_description: description } : { error },\n\t};\n}\n","import type { OAuthRegisteredClientsStore } from \"@modelcontextprotocol/sdk/server/auth/clients.js\";\nimport {\n\tAccessDeniedError,\n\tInvalidClientError,\n\tInvalidGrantError,\n\tInvalidRequestError,\n\tInvalidTokenError,\n\tServerError,\n\tTemporarilyUnavailableError,\n\tUnsupportedResponseTypeError,\n} from \"@modelcontextprotocol/sdk/server/auth/errors.js\";\nimport type {\n\tAuthorizationParams,\n\tOAuthServerProvider,\n} from \"@modelcontextprotocol/sdk/server/auth/provider.js\";\nimport type { AuthInfo } from \"@modelcontextprotocol/sdk/server/auth/types.js\";\nimport {\n\ttype OAuthClientInformationFull,\n\ttype OAuthErrorResponse,\n\ttype OAuthTokenRevocationRequest,\n\ttype OAuthTokens,\n\tOAuthTokensSchema,\n} from \"@modelcontextprotocol/sdk/shared/auth.js\";\nimport type { Response } from \"express\";\nimport {\n\tcreateInMemoryOAuthRefreshTokenStore,\n\ttype OAuthAccessTokenStore,\n\ttype OAuthAuthorizationCodeStore,\n\ttype OAuthRefreshTokenStore,\n} from \"./oauth.js\";\nimport {\n\tbeginOidcAuthorization,\n\ttype OidcConfig,\n\ttype OidcPendingAuthorizationStore,\n} from \"./oidc.js\";\n\nexport interface MemoryOAuthServerProviderOptions {\n\tclientsStore: OAuthRegisteredClientsStore;\n\tcodeStore: OAuthAuthorizationCodeStore;\n\ttokenStore: OAuthAccessTokenStore;\n\trefreshTokenStore?: OAuthRefreshTokenStore;\n\tpublicMcpUrl: string;\n\toidc?: { config: OidcConfig; pendingStore: OidcPendingAuthorizationStore };\n\tnow?: () => number;\n}\n\n/**\n * MemoryOAuthServerProvider adapts codemem's existing in-memory stores to the\n * `@modelcontextprotocol/sdk` `OAuthServerProvider` contract so the SDK's\n * `mcpAuthRouter` and `requireBearerAuth` middleware can drive the OAuth\n * lifecycle. This class is the boundary between SDK-handled HTTP and\n * codemem-owned storage / upstream-OIDC bridging.\n *\n * Conventions encoded here:\n * - `authorize()` does NOT mint the MCP authorization code itself. It\n * persists pending state and redirects the user-agent to the upstream OIDC\n * provider. The MCP code is issued later by codemem's own /oauth/callback\n * route (wired in codemem-b20m.3) after the upstream identity is validated.\n * - PKCE is validated by the SDK token handler against the challenge returned\n * from `challengeForAuthorizationCode`. We do not re-verify here.\n * - `expiresAt` returned in `AuthInfo` is epoch SECONDS per the SDK's\n * `requireBearerAuth` expectations; the underlying store records ms.\n * - Refresh-token grants use dual-token rotation: the current token and one\n * previous token are accepted to tolerate client retry races, while older\n * replayed tokens revoke the whole grant.\n */\nexport class MemoryOAuthServerProvider implements OAuthServerProvider {\n\treadonly #clientsStore: OAuthRegisteredClientsStore;\n\treadonly #codeStore: OAuthAuthorizationCodeStore;\n\treadonly #tokenStore: OAuthAccessTokenStore;\n\treadonly #refreshTokenStore: OAuthRefreshTokenStore;\n\treadonly #publicMcpUrl: string;\n\treadonly #resourceServerUrl: string;\n\treadonly #oidc?: { config: OidcConfig; pendingStore: OidcPendingAuthorizationStore };\n\treadonly #now: () => number;\n\n\tconstructor(options: MemoryOAuthServerProviderOptions) {\n\t\tthis.#clientsStore = options.clientsStore;\n\t\tthis.#codeStore = options.codeStore;\n\t\tthis.#tokenStore = options.tokenStore;\n\t\tthis.#refreshTokenStore = options.refreshTokenStore ?? createInMemoryOAuthRefreshTokenStore();\n\t\tthis.#publicMcpUrl = options.publicMcpUrl;\n\t\tthis.#resourceServerUrl = new URL(options.publicMcpUrl).href;\n\t\tthis.#oidc = options.oidc;\n\t\tthis.#now = options.now ?? Date.now;\n\t}\n\n\tget clientsStore(): OAuthRegisteredClientsStore {\n\t\treturn this.#clientsStore;\n\t}\n\n\tasync authorize(\n\t\tclient: OAuthClientInformationFull,\n\t\tparams: AuthorizationParams,\n\t\tres: Response,\n\t): Promise<void> {\n\t\tif (!this.#oidc) {\n\t\t\tthrow new TemporarilyUnavailableError(\"OIDC is not configured\");\n\t\t}\n\t\tconst upstreamParams = buildUpstreamAuthorizationParams(client, params);\n\t\tconst result = await beginOidcAuthorization(\n\t\t\tupstreamParams,\n\t\t\tthis.#clientsStore,\n\t\t\tthis.#oidc.pendingStore,\n\t\t\tthis.#oidc.config,\n\t\t\tthis.#publicMcpUrl,\n\t\t\tthis.#now(),\n\t\t);\n\t\tif (result.status === 302) {\n\t\t\tres.redirect(302, result.location);\n\t\t\treturn;\n\t\t}\n\t\tthrow mapOAuthErrorBody(result.body);\n\t}\n\n\tasync challengeForAuthorizationCode(\n\t\t_client: OAuthClientInformationFull,\n\t\tauthorizationCode: string,\n\t): Promise<string> {\n\t\tconst record = this.#codeStore.peekCode(authorizationCode);\n\t\tif (!record) throw new InvalidGrantError(\"Invalid or already used code\");\n\t\tif (record.clientId !== _client.client_id) {\n\t\t\tthrow new InvalidGrantError(\"Code does not match client\");\n\t\t}\n\t\tif (record.expiresAt <= this.#now()) {\n\t\t\tthis.#codeStore.consumeCode(authorizationCode);\n\t\t\tthrow new InvalidGrantError(\"Expired code\");\n\t\t}\n\t\treturn record.codeChallenge;\n\t}\n\n\tasync exchangeAuthorizationCode(\n\t\tclient: OAuthClientInformationFull,\n\t\tauthorizationCode: string,\n\t\t_codeVerifier?: string,\n\t\tredirectUri?: string,\n\t\tresource?: URL,\n\t): Promise<OAuthTokens> {\n\t\tconst now = this.#now();\n\t\tconst record = this.#codeStore.peekCode(authorizationCode);\n\t\tif (!record) throw new InvalidGrantError(\"Invalid or already used code\");\n\t\tif (record.expiresAt <= now) {\n\t\t\tthis.#codeStore.consumeCode(authorizationCode);\n\t\t\tthrow new InvalidGrantError(\"Expired code\");\n\t\t}\n\t\tif (record.clientId !== client.client_id) {\n\t\t\tthis.#codeStore.consumeCode(authorizationCode);\n\t\t\tthrow new InvalidGrantError(\"Code does not match client\");\n\t\t}\n\t\t// RFC 6749 §4.1.3: if the authorization request included redirect_uri,\n\t\t// the token request MUST include the same value. codemem always binds a\n\t\t// redirect_uri at /authorize, so a missing value at /token is always a\n\t\t// grant mismatch, not an optional check.\n\t\tif (redirectUri === undefined || record.redirectUri !== redirectUri) {\n\t\t\tthis.#codeStore.consumeCode(authorizationCode);\n\t\t\tthrow new InvalidGrantError(\"Code does not match redirect_uri\");\n\t\t}\n\t\tif ((record.resource ?? null) !== (resource?.href ?? null)) {\n\t\t\tthis.#codeStore.consumeCode(authorizationCode);\n\t\t\tthrow new InvalidGrantError(\"Code does not match resource\");\n\t\t}\n\n\t\tconst scopes = normalizeClientScopes(record.scopes) ?? [];\n\t\tconst grant = this.#refreshTokenStore.issueGrant(\n\t\t\t{ clientId: client.client_id, scopes, resource: record.resource },\n\t\t\tnow,\n\t\t);\n\t\tif (!grant) {\n\t\t\tthrow new TemporarilyUnavailableError(\"Too many active refresh grants\");\n\t\t}\n\t\tconst issued = this.#tokenStore.issueToken(\n\t\t\tclient.client_id,\n\t\t\tnow,\n\t\t\trecord.resource,\n\t\t\tgrant.grant.grantId,\n\t\t\tscopes,\n\t\t);\n\t\tif (!issued) {\n\t\t\t// Token-store overload is transient: leave the auth code unused so the\n\t\t\t// client can retry token exchange without restarting the OAuth flow.\n\t\t\tthis.#refreshTokenStore.revokeGrant(grant.grant.grantId, now);\n\t\t\tthrow new TemporarilyUnavailableError(\"Too many active access tokens\");\n\t\t}\n\n\t\tconst consumed = this.#codeStore.consumeCode(authorizationCode);\n\t\tif (!consumed) {\n\t\t\tthis.#tokenStore.revokeToken(issued.token, now);\n\t\t\tthis.#refreshTokenStore.revokeGrant(grant.grant.grantId, now);\n\t\t\t// Lost a race with a concurrent exchange that consumed the code in\n\t\t\t// the gap between peek and consume. Reject rather than issuing a\n\t\t\t// duplicate usable token.\n\t\t\tthrow new InvalidGrantError(\"Authorization code already used\");\n\t\t}\n\n\t\treturn OAuthTokensSchema.parse({\n\t\t\taccess_token: issued.token,\n\t\t\ttoken_type: \"Bearer\",\n\t\t\texpires_in: issued.expiresIn,\n\t\t\trefresh_token: grant.refreshToken,\n\t\t});\n\t}\n\n\tasync exchangeRefreshToken(\n\t\tclient: OAuthClientInformationFull,\n\t\trefreshToken: string,\n\t\tscopes?: string[],\n\t\tresource?: URL,\n\t): Promise<OAuthTokens> {\n\t\tconst now = this.#now();\n\t\tconst rotation = this.#refreshTokenStore.rotateRefreshToken(\n\t\t\tclient.client_id,\n\t\t\trefreshToken,\n\t\t\t{ scopes: normalizeClientScopes(scopes), ...(resource ? { resource: resource.href } : {}) },\n\t\t\tnow,\n\t\t);\n\t\tif (!rotation.ok) {\n\t\t\tif (rotation.reason === \"refresh_token_replay\" && rotation.grantId) {\n\t\t\t\tthis.#tokenStore.revokeTokensForGrant?.(rotation.grantId, now);\n\t\t\t}\n\t\t\tthrow new InvalidGrantError(refreshTokenErrorDescription(rotation.reason));\n\t\t}\n\t\tconst issued = this.#tokenStore.issueToken(\n\t\t\tclient.client_id,\n\t\t\tnow,\n\t\t\trotation.grant.resource,\n\t\t\trotation.grant.grantId,\n\t\t\trotation.grant.scopes,\n\t\t);\n\t\tif (!issued) throw new TemporarilyUnavailableError(\"Too many active access tokens\");\n\t\treturn OAuthTokensSchema.parse({\n\t\t\taccess_token: issued.token,\n\t\t\ttoken_type: \"Bearer\",\n\t\t\texpires_in: issued.expiresIn,\n\t\t\trefresh_token: rotation.refreshToken,\n\t\t});\n\t}\n\n\tasync verifyAccessToken(token: string): Promise<AuthInfo> {\n\t\tconst result = this.#tokenStore.verifyToken(token, this.#now());\n\t\tif (!result.ok) {\n\t\t\tconst reason =\n\t\t\t\tresult.reason === \"expired_token\"\n\t\t\t\t\t? \"Token has expired\"\n\t\t\t\t\t: result.reason === \"revoked_token\"\n\t\t\t\t\t\t? \"Token has been revoked\"\n\t\t\t\t\t\t: \"Token is invalid\";\n\t\t\tthrow new InvalidTokenError(reason);\n\t\t}\n\t\tconst authInfo: AuthInfo = {\n\t\t\ttoken,\n\t\t\tclientId: result.record.clientId,\n\t\t\tscopes: result.record.scopes,\n\t\t\texpiresAt: Math.floor(result.record.expiresAt / 1000),\n\t\t};\n\t\tif (result.record.resource) {\n\t\t\tif (new URL(result.record.resource).href !== this.#resourceServerUrl) {\n\t\t\t\tthrow new InvalidTokenError(\"Token audience does not match this resource server\");\n\t\t\t}\n\t\t\tauthInfo.resource = new URL(result.record.resource);\n\t\t}\n\t\treturn authInfo;\n\t}\n\n\tasync revokeToken(\n\t\t_client: OAuthClientInformationFull,\n\t\trequest: OAuthTokenRevocationRequest,\n\t): Promise<void> {\n\t\tconst now = this.#now();\n\t\tthis.#tokenStore.revokeToken(request.token, now);\n\t\tconst grantId = this.#refreshTokenStore.revokeRefreshToken(request.token, now);\n\t\tif (grantId) this.#tokenStore.revokeTokensForGrant?.(grantId, now);\n\t}\n}\n\nfunction buildUpstreamAuthorizationParams(\n\tclient: OAuthClientInformationFull,\n\tparams: AuthorizationParams,\n): URLSearchParams {\n\tconst upstream = new URLSearchParams();\n\tupstream.set(\"client_id\", client.client_id);\n\tupstream.set(\"redirect_uri\", params.redirectUri);\n\tupstream.set(\"response_type\", \"code\");\n\tupstream.set(\"code_challenge\", params.codeChallenge);\n\tupstream.set(\"code_challenge_method\", \"S256\");\n\tif (params.state) upstream.set(\"state\", params.state);\n\tif (params.scopes?.length) upstream.set(\"scope\", params.scopes.join(\" \"));\n\tif (params.resource) upstream.set(\"resource\", params.resource.href);\n\treturn upstream;\n}\n\nfunction mapOAuthErrorBody(body: OAuthErrorResponse): Error {\n\tconst description = body.error_description ?? body.error;\n\tswitch (body.error) {\n\t\tcase \"temporarily_unavailable\":\n\t\t\treturn new TemporarilyUnavailableError(description);\n\t\tcase \"invalid_request\":\n\t\t\treturn new InvalidRequestError(description);\n\t\tcase \"invalid_client\":\n\t\t\treturn new InvalidClientError(description);\n\t\tcase \"access_denied\":\n\t\t\treturn new AccessDeniedError(description);\n\t\tcase \"unsupported_response_type\":\n\t\t\treturn new UnsupportedResponseTypeError(description);\n\t\tdefault:\n\t\t\treturn new ServerError(description);\n\t}\n}\n\nfunction refreshTokenErrorDescription(reason: string): string {\n\tswitch (reason) {\n\t\tcase \"expired_refresh_token\":\n\t\t\treturn \"Refresh token has expired\";\n\t\tcase \"revoked_refresh_token\":\n\t\t\treturn \"Refresh token has been revoked\";\n\t\tcase \"client_mismatch\":\n\t\t\treturn \"Refresh token does not match client\";\n\t\tcase \"scope_mismatch\":\n\t\t\treturn \"Refresh token scope cannot be expanded\";\n\t\tcase \"resource_mismatch\":\n\t\t\treturn \"Refresh token does not match resource\";\n\t\tcase \"refresh_token_replay\":\n\t\t\treturn \"Refresh token replay detected\";\n\t\tdefault:\n\t\t\treturn \"Invalid refresh token\";\n\t}\n}\n\nfunction normalizeClientScopes(scopes: string[] | undefined): string[] | undefined {\n\tconst normalized = scopes\n\t\t?.map((scope) => scope.trim())\n\t\t.filter(Boolean)\n\t\t.map((scope) => {\n\t\t\tif (scope === \"memory:read_access\") return \"memory:read\";\n\t\t\tif (scope === \"memory:write_access\") return \"memory:write\";\n\t\t\treturn scope;\n\t\t});\n\treturn normalized && normalized.length > 0 ? normalized : undefined;\n}\n","#!/usr/bin/env node\n\n/**\n * @codemem/mcp — MCP Streamable HTTP server bootstrap.\n *\n * Local-first HTTP transport for MCP clients. OAuth metadata and Dynamic Client\n * Registration are exposed for remote MCP setup; public MCP requests require\n * OAuth bearer tokens.\n */\n\nimport { createServer, type IncomingMessage, type Server } from \"node:http\";\nimport { isIP } from \"node:net\";\nimport { pathToFileURL } from \"node:url\";\nimport { MemoryStore, resolveDbPath } from \"@codemem/core\";\nimport { requireBearerAuth } from \"@modelcontextprotocol/sdk/server/auth/middleware/bearerAuth.js\";\nimport {\n\tgetOAuthProtectedResourceMetadataUrl,\n\tmcpAuthRouter,\n} from \"@modelcontextprotocol/sdk/server/auth/router.js\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StreamableHTTPServerTransport } from \"@modelcontextprotocol/sdk/server/streamableHttp.js\";\nimport express, { type NextFunction, type Request, type Response } from \"express\";\nimport { rateLimit } from \"express-rate-limit\";\nimport {\n\ttype BearerDenyReason,\n\tbuildOAuthAuditEvent,\n\ttype OAuthAuditEmitter,\n\tresolveOAuthAuditEmitterFromEnv,\n\twrapAuditEmitterBestEffort,\n} from \"./audit.js\";\nimport {\n\tcreateInMemoryOAuthAccessTokenStore,\n\tcreateInMemoryOAuthAuthorizationCodeStore,\n\tcreateInMemoryOAuthClientsStore,\n\tcreateMcpOAuthMetadata,\n\tcreateMcpProtectedResourceMetadata,\n\tMCP_OAUTH_PUBLIC_URL_ENV,\n\tMCP_OAUTH_RESOURCE_NAME,\n\tMCP_OAUTH_SCOPES_SUPPORTED,\n\tMCP_OAUTH_SERVICE_DOCUMENTATION_URL,\n\tnormalizeMcpPublicUrl,\n\ttype OAuthAccessTokenStore,\n} from \"./oauth.js\";\nimport {\n\tcompleteOidcAuthorization,\n\tcreateInMemoryOidcPendingAuthorizationStore,\n\tresolveOidcConfig,\n} from \"./oidc.js\";\nimport { MemoryOAuthServerProvider } from \"./provider.js\";\nimport { createCodememMcpServer } from \"./server.js\";\n\nexport const DEFAULT_MCP_HTTP_HOST = \"127.0.0.1\";\nexport const DEFAULT_MCP_HTTP_PORT = 38889;\nconst HTTP_DEFAULT_PORT = 80;\nconst TRUSTED_PUBLIC_BROWSER_ORIGINS = new Set([\"https://claude.ai\"]);\nconst CORS_ALLOW_HEADERS = \"authorization,content-type,mcp-session-id\";\nconst CORS_MAX_AGE_SECONDS = \"600\";\nconst MAX_GUARD_LOG_FIELD_LENGTH = 256;\nconst PUBLIC_MCP_RATE_LIMIT_WINDOW_MS = 15 * 60 * 1000;\nconst PUBLIC_MCP_RATE_LIMIT_REQUESTS = 600;\n\nconst VALID_HOSTNAME = /^[a-zA-Z0-9.-]+$/;\nconst LOOPBACK_HOSTS = new Set([\"127.0.0.1\", \"::1\", \"localhost\"]);\n\ninterface ActiveRequest {\n\tmcpServer: McpServer;\n}\n\nexport interface CodememMcpHttpOptions {\n\thost?: string;\n\tport?: number | string;\n\tdbPath?: string;\n\tallowUnsafePublic?: boolean;\n\tpublicUrl?: string;\n\toauthAccessTokenStore?: OAuthAccessTokenStore;\n\tauditEmitter?: OAuthAuditEmitter;\n}\n\nexport interface CodememMcpHttpServer {\n\tserver: Server;\n\tstore: MemoryStore;\n\turl: string;\n\tclose: () => Promise<void>;\n}\n\nexport function validateMcpHttpHost(host: string | undefined, allowUnsafePublic = false): string {\n\tconst value = host?.trim() || DEFAULT_MCP_HTTP_HOST;\n\tif (value.includes(\"://\") || value.includes(\"/\") || value.includes(\"\\\\\")) {\n\t\tthrow new Error(`Invalid MCP HTTP host: ${host}`);\n\t}\n\tif (!(isIP(value) || value === \"localhost\" || VALID_HOSTNAME.test(value))) {\n\t\tthrow new Error(`Invalid MCP HTTP host: ${host}`);\n\t}\n\tif (!allowUnsafePublic && !isLoopbackHost(value)) {\n\t\tthrow new Error(\n\t\t\t`Refusing unsafe MCP HTTP host ${value}; set CODEMEM_MCP_HTTP_UNSAFE_PUBLIC=1 to allow non-loopback binding`,\n\t\t);\n\t}\n\treturn value;\n}\n\nexport function isLoopbackHost(host: string): boolean {\n\treturn LOOPBACK_HOSTS.has(normalizeHost(host));\n}\n\nexport function isUnsafePublicBindAllowed(\n\tvalue = process.env.CODEMEM_MCP_HTTP_UNSAFE_PUBLIC,\n): boolean {\n\treturn value === \"1\" || value?.toLowerCase() === \"true\" || value?.toLowerCase() === \"yes\";\n}\n\nexport function isAllowedMcpHttpRequestHost(\n\theader: string | undefined,\n\texpectedPort: number,\n): boolean {\n\tconst parsed = parseHostHeader(header);\n\tif (!parsed) return false;\n\tif (!isLoopbackHost(parsed.host)) return false;\n\tif (parsed.port === null) {\n\t\t// No `:port` in the Host header means the client is using the protocol\n\t\t// default. This server is plain HTTP, so the implied port is 80. Only\n\t\t// accept the bare-host form when the bound port is also 80.\n\t\treturn expectedPort === HTTP_DEFAULT_PORT;\n\t}\n\treturn parsed.port === expectedPort;\n}\n\nexport function isAllowedMcpHttpRequestOrigin(\n\theader: string | undefined,\n\texpectedPort: number,\n): boolean {\n\tif (!header) return true;\n\ttry {\n\t\tconst url = new URL(header);\n\t\tconst port = url.port ? Number(url.port) : url.protocol === \"https:\" ? 443 : 80;\n\t\treturn (\n\t\t\t(url.protocol === \"http:\" || url.protocol === \"https:\") &&\n\t\t\turl.username === \"\" &&\n\t\t\turl.password === \"\" &&\n\t\t\turl.pathname === \"/\" &&\n\t\t\turl.search === \"\" &&\n\t\t\turl.hash === \"\" &&\n\t\t\tisLoopbackHost(url.hostname) &&\n\t\t\tport === expectedPort\n\t\t);\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nexport function isAllowedMcpHttpRequestRemoteAddress(address: string | undefined): boolean {\n\tif (!address) return false;\n\treturn isLoopbackHost(address.replace(/^::ffff:/, \"\"));\n}\n\nfunction normalizeHost(host: string): string {\n\treturn host.replace(/^\\[(.*)]$/, \"$1\").toLowerCase();\n}\n\nfunction parseHostHeader(header: string | undefined): { host: string; port: number | null } | null {\n\tif (!header) return null;\n\tif (header.startsWith(\"[\")) {\n\t\t// Bracketed IPv6: `[::1]` or `[::1]:8080`.\n\t\tconst withPort = /^\\[([^\\]]+)]:(\\d+)$/.exec(header);\n\t\tif (withPort?.[1] && withPort[2]) {\n\t\t\treturn { host: withPort[1], port: Number(withPort[2]) };\n\t\t}\n\t\tconst bareIpv6 = /^\\[([^\\]]+)]$/.exec(header);\n\t\tif (bareIpv6?.[1]) return { host: bareIpv6[1], port: null };\n\t\treturn null;\n\t}\n\tconst lastColon = header.lastIndexOf(\":\");\n\tif (lastColon < 0) {\n\t\t// RFC-compliant clients may omit `:port` on default-port requests. Treat\n\t\t// the implied port as \"use the protocol default\" and let the caller\n\t\t// reconcile against the actually bound port.\n\t\treturn { host: header, port: null };\n\t}\n\tconst host = header.slice(0, lastColon);\n\tconst port = Number(header.slice(lastColon + 1));\n\tif (!Number.isInteger(port)) return null;\n\treturn { host, port };\n}\n\nexport function parseMcpHttpPort(port: number | string | undefined): number {\n\tif (port === undefined || port === \"\") return DEFAULT_MCP_HTTP_PORT;\n\tconst value = typeof port === \"number\" ? port : Number(port);\n\tif (!Number.isInteger(value) || value < 0 || value > 65_535) {\n\t\tthrow new Error(`Invalid MCP HTTP port: ${port}`);\n\t}\n\treturn value;\n}\n\nexport async function startCodememMcpHttpServer(\n\toptions: CodememMcpHttpOptions = {},\n): Promise<CodememMcpHttpServer> {\n\tconst host = validateMcpHttpHost(\n\t\toptions.host ?? process.env.CODEMEM_MCP_HTTP_HOST,\n\t\toptions.allowUnsafePublic ?? isUnsafePublicBindAllowed(),\n\t);\n\tconst port = parseMcpHttpPort(options.port ?? process.env.CODEMEM_MCP_HTTP_PORT);\n\tconst configuredPublicUrl = options.publicUrl ?? process.env[MCP_OAUTH_PUBLIC_URL_ENV];\n\tconst configuredPublicMcpUrl = configuredPublicUrl\n\t\t? normalizeMcpPublicUrl(configuredPublicUrl)\n\t\t: undefined;\n\tconst store = new MemoryStore(options.dbPath ?? resolveDbPath());\n\tconst clientsStore = createInMemoryOAuthClientsStore();\n\tconst codeStore = createInMemoryOAuthAuthorizationCodeStore();\n\tconst tokenStore = options.oauthAccessTokenStore ?? createInMemoryOAuthAccessTokenStore();\n\tconst oidcConfig = resolveOidcConfig();\n\tconst oidcPendingStore = createInMemoryOidcPendingAuthorizationStore();\n\tconst shouldRequireMcpBearer = configuredPublicMcpUrl !== undefined || oidcConfig !== undefined;\n\tconst auditEmit = wrapAuditEmitterBestEffort(\n\t\toptions.auditEmitter ?? resolveOAuthAuditEmitterFromEnv(),\n\t);\n\tconst activeRequests = new Set<ActiveRequest>();\n\tlet closePromise: Promise<void> | null = null;\n\n\tconst app = express();\n\tapp.disable(\"x-powered-by\");\n\t// Tailscale Funnel and similar local ingress proxies forward from loopback and\n\t// add X-Forwarded-For. Trust only loopback proxy hops so SDK rate limiters can\n\t// key on the real client IP without making public clients spoofable.\n\tapp.set(\"trust proxy\", \"loopback\");\n\tconst server = createServer(app);\n\n\tawait new Promise<void>((resolve, reject) => {\n\t\tserver.once(\"error\", reject);\n\t\tserver.listen({ host, port }, () => {\n\t\t\tserver.off(\"error\", reject);\n\t\t\tresolve();\n\t\t});\n\t});\n\n\tconst publicMcpUrl = configuredPublicMcpUrl?.href ?? getServerUrl(server, host);\n\tconst publicMcpUrlObject = new URL(publicMcpUrl);\n\tconst issuerUrl = getSdkIssuerUrl(publicMcpUrlObject, getBoundPort(server));\n\tconst provider = new MemoryOAuthServerProvider({\n\t\tclientsStore,\n\t\tcodeStore,\n\t\ttokenStore,\n\t\tpublicMcpUrl,\n\t\t...(oidcConfig ? { oidc: { config: oidcConfig, pendingStore: oidcPendingStore } } : {}),\n\t});\n\tconst resourceMetadataUrl = getOAuthProtectedResourceMetadataUrl(publicMcpUrlObject);\n\n\tapp.use(\n\t\trateLimit({\n\t\t\twindowMs: PUBLIC_MCP_RATE_LIMIT_WINDOW_MS,\n\t\t\tlimit: PUBLIC_MCP_RATE_LIMIT_REQUESTS,\n\t\t\tstandardHeaders: \"draft-8\",\n\t\t\tlegacyHeaders: false,\n\t\t\t// Avoid express-rate-limit's default IPv6 subnet helper here: its current\n\t\t\t// transitive ip-address API throws on IPv6 loopback in our Node 24 test path.\n\t\t\t// This coarse limiter is defense-in-depth before the SDK OAuth limiters and\n\t\t\t// the Host/Origin guard; it must never break local IPv6 metadata requests.\n\t\t\tipv6Subnet: false,\n\t\t}),\n\t);\n\tapp.use((req, res, next) => {\n\t\tconst boundPort = getBoundPort(server);\n\t\tconst pathname = normalizeRoutePath(req.path);\n\t\tif (pathname === \"/mcp\") {\n\t\t\tif (isAllowedMcpHttpRequest(req, boundPort, configuredPublicMcpUrl)) {\n\t\t\t\tapplyPublicCorsHeaders(req, res, configuredPublicMcpUrl);\n\t\t\t\tif (req.method === \"OPTIONS\") {\n\t\t\t\t\tres.status(204).send(\"\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\treturn next();\n\t\t\t}\n\t\t\temitHttpGuardDeny(req, pathname, configuredPublicMcpUrl);\n\t\t\tres.status(403).type(\"text/plain\").send(\"Forbidden\");\n\t\t\treturn;\n\t\t}\n\t\tif (isOAuthOrMetadataPath(pathname)) {\n\t\t\tif (isAllowedOAuthHttpRequest(req, boundPort, configuredPublicMcpUrl)) {\n\t\t\t\tapplyPublicCorsHeaders(req, res, configuredPublicMcpUrl);\n\t\t\t\tif (req.method === \"OPTIONS\") {\n\t\t\t\t\tres.status(204).send(\"\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\treturn next();\n\t\t\t}\n\t\t\temitHttpGuardDeny(req, pathname, configuredPublicMcpUrl);\n\t\t\tres.status(403).type(\"text/plain\").send(\"Forbidden\");\n\t\t\treturn;\n\t\t}\n\t\tnext();\n\t});\n\n\tapp.use(auditOAuthRouteResponses(auditEmit));\n\n\tapp.get(\"/oauth/callback\", async (req, res) => {\n\t\tconst remoteAddress = req.socket.remoteAddress ?? undefined;\n\t\tif (!oidcConfig) {\n\t\t\tauditEmit(\n\t\t\t\tbuildOAuthAuditEvent(\"oidc_callback\", {\n\t\t\t\t\toutcome: \"denied\",\n\t\t\t\t\treason: \"oidc_not_configured\",\n\t\t\t\t\tremoteAddress,\n\t\t\t\t}),\n\t\t\t);\n\t\t\tres.status(400).json({\n\t\t\t\terror: \"temporarily_unavailable\",\n\t\t\t\terror_description: \"OIDC is not configured\",\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\tconst completed = await completeOidcAuthorization(\n\t\t\tnew URLSearchParams(req.query as Record<string, string>),\n\t\t\toidcPendingStore,\n\t\t\toidcConfig,\n\t\t\tpublicMcpUrl,\n\t\t);\n\t\tif (\"status\" in completed) {\n\t\t\tauditEmit(\n\t\t\t\tbuildOAuthAuditEvent(\"oidc_callback\", {\n\t\t\t\t\toutcome: \"denied\",\n\t\t\t\t\treason: completed.body.error,\n\t\t\t\t\tremoteAddress,\n\t\t\t\t}),\n\t\t\t);\n\t\t\tres.status(completed.status).json(completed.body);\n\t\t\treturn;\n\t\t}\n\t\tconst oauthClientId = completed.oauthParams.get(\"client_id\") ?? undefined;\n\t\tconst code = codeStore.issueCode({\n\t\t\tclientId: completed.oauthParams.get(\"client_id\") ?? \"\",\n\t\t\tredirectUri: completed.oauthParams.get(\"redirect_uri\") ?? \"\",\n\t\t\tcodeChallenge: completed.oauthParams.get(\"code_challenge\") ?? \"\",\n\t\t\tscopes: parseScopeList(completed.oauthParams.get(\"scope\")),\n\t\t\t...(completed.oauthParams.get(\"resource\")\n\t\t\t\t? { resource: completed.oauthParams.get(\"resource\") ?? undefined }\n\t\t\t\t: {}),\n\t\t\texpiresAt: Date.now() + 5 * 60 * 1000,\n\t\t});\n\t\tif (!code) {\n\t\t\tauditEmit(\n\t\t\t\tbuildOAuthAuditEvent(\"oidc_callback\", {\n\t\t\t\t\toutcome: \"denied\",\n\t\t\t\t\treason: \"temporarily_unavailable\",\n\t\t\t\t\tclientId: oauthClientId,\n\t\t\t\t\tremoteAddress,\n\t\t\t\t}),\n\t\t\t);\n\t\t\tres.status(400).json({\n\t\t\t\terror: \"temporarily_unavailable\",\n\t\t\t\terror_description: \"Too many active authorization codes\",\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\tconst redirect = new URL(completed.oauthParams.get(\"redirect_uri\") ?? \"\");\n\t\tredirect.searchParams.set(\"code\", code);\n\t\tconst state = completed.oauthParams.get(\"state\");\n\t\tif (state) redirect.searchParams.set(\"state\", state);\n\t\tauditEmit(\n\t\t\tbuildOAuthAuditEvent(\"oidc_callback\", {\n\t\t\t\toutcome: \"success\",\n\t\t\t\treason: \"code_issued\",\n\t\t\t\tclientId: oauthClientId,\n\t\t\t\tremoteAddress,\n\t\t\t}),\n\t\t);\n\t\tres.redirect(302, redirect.href);\n\t});\n\n\tapp.get(\"/.well-known/oauth-authorization-server\", (_req, res) => {\n\t\tres.status(200).json(createMcpOAuthMetadata({ mcpUrl: publicMcpUrl, clientsStore }));\n\t});\n\tapp.get(\"/.well-known/oauth-protected-resource/mcp\", (_req, res) => {\n\t\tres.status(200).json(createMcpProtectedResourceMetadata(publicMcpUrl));\n\t});\n\n\tapp.use(\n\t\tmcpAuthRouter({\n\t\t\tprovider,\n\t\t\tissuerUrl,\n\t\t\tbaseUrl: issuerUrl,\n\t\t\tresourceServerUrl: publicMcpUrlObject,\n\t\t\tresourceName: MCP_OAUTH_RESOURCE_NAME,\n\t\t\tscopesSupported: MCP_OAUTH_SCOPES_SUPPORTED,\n\t\t\tserviceDocumentationUrl: new URL(MCP_OAUTH_SERVICE_DOCUMENTATION_URL),\n\t\t\tclientRegistrationOptions: { clientSecretExpirySeconds: 0 },\n\t\t}),\n\t);\n\n\tconst bearerMiddleware = shouldRequireMcpBearer\n\t\t? requireBearerAuth({ verifier: provider, resourceMetadataUrl })\n\t\t: (_req: Request, _res: Response, next: NextFunction) => next();\n\tconst bearerAuditMiddleware = shouldRequireMcpBearer\n\t\t? auditBearerPreflight(auditEmit, tokenStore)\n\t\t: (_req: Request, _res: Response, next: NextFunction) => next();\n\tapp.post(\"/mcp\", bearerAuditMiddleware, bearerMiddleware, async (req, res) => {\n\t\tif (req.auth) {\n\t\t\tauditEmit(\n\t\t\t\tbuildOAuthAuditEvent(\"bearer\", {\n\t\t\t\t\toutcome: \"success\",\n\t\t\t\t\tclientId: req.auth.clientId,\n\t\t\t\t\tremoteAddress: req.socket.remoteAddress ?? undefined,\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t\tconst mcpServer = createCodememMcpServer(store);\n\t\tconst transport = new StreamableHTTPServerTransport({ sessionIdGenerator: undefined });\n\t\tconst activeRequest = { mcpServer };\n\t\tactiveRequests.add(activeRequest);\n\t\ttry {\n\t\t\tawait mcpServer.connect(transport);\n\t\t\tawait transport.handleRequest(req, res);\n\t\t} finally {\n\t\t\tactiveRequests.delete(activeRequest);\n\t\t\tawait mcpServer.close();\n\t\t}\n\t});\n\tapp.all(\"/mcp\", (_req, res) => {\n\t\tres.setHeader(\"Allow\", \"POST\");\n\t\tres.status(405).type(\"text/plain\").send(\"Method not allowed\");\n\t});\n\tapp.use((_req, res) => {\n\t\tres.status(404).type(\"text/plain\").send(\"Not found\");\n\t});\n\n\tconst close = () => {\n\t\tclosePromise ??= (async () => {\n\t\t\tawait Promise.allSettled([...activeRequests].map(({ mcpServer }) => mcpServer.close()));\n\t\t\tawait new Promise<void>((resolve, reject) => {\n\t\t\t\tserver.close((err) => {\n\t\t\t\t\tif (!err || (err as NodeJS.ErrnoException).code === \"ERR_SERVER_NOT_RUNNING\") {\n\t\t\t\t\t\tresolve();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\treject(err);\n\t\t\t\t});\n\t\t\t\tserver.closeAllConnections();\n\t\t\t});\n\t\t\tstore.close();\n\t\t})();\n\t\treturn closePromise;\n\t};\n\n\treturn {\n\t\tserver,\n\t\tstore,\n\t\turl: `http://${formatHostForUrl(host)}:${getBoundPort(server)}/mcp`,\n\t\tclose,\n\t};\n}\n\nfunction isAllowedMcpHttpRequest(\n\treq: IncomingMessage,\n\texpectedPort: number,\n\tpublicMcpUrl: URL | undefined,\n): boolean {\n\tif (isAllowedLocalMcpHttpRequest(req, expectedPort)) return true;\n\tif (!publicMcpUrl) return false;\n\treturn (\n\t\tisAllowedPublicRequestHost(req.headers.host, publicMcpUrl) &&\n\t\tisAllowedPublicOrigin(req.headers.origin, publicMcpUrl)\n\t);\n}\n\nfunction isAllowedLocalMcpHttpRequest(req: IncomingMessage, expectedPort: number): boolean {\n\treturn (\n\t\tisAllowedMcpHttpRequestRemoteAddress(req.socket.remoteAddress) &&\n\t\tisAllowedMcpHttpRequestHost(req.headers.host, expectedPort) &&\n\t\tisAllowedMcpHttpRequestOrigin(req.headers.origin, expectedPort)\n\t);\n}\n\nfunction isAllowedOAuthHttpRequest(\n\treq: IncomingMessage,\n\texpectedPort: number,\n\tpublicMcpUrl: URL | undefined,\n): boolean {\n\tif (isAllowedLocalMcpHttpRequest(req, expectedPort)) return true;\n\tif (!publicMcpUrl) return false;\n\treturn (\n\t\tisAllowedPublicRequestHost(req.headers.host, publicMcpUrl) &&\n\t\tisAllowedPublicOrigin(req.headers.origin, publicMcpUrl)\n\t);\n}\n\nfunction isAllowedPublicOrigin(header: string | undefined, publicMcpUrl: URL): boolean {\n\tif (!header) return true;\n\ttry {\n\t\tconst origin = new URL(header);\n\t\treturn (\n\t\t\torigin.origin === publicMcpUrl.origin || TRUSTED_PUBLIC_BROWSER_ORIGINS.has(origin.origin)\n\t\t);\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nfunction applyPublicCorsHeaders(\n\treq: IncomingMessage,\n\tres: Response,\n\tpublicMcpUrl: URL | undefined,\n): void {\n\tif (!publicMcpUrl) return;\n\tconst origin = getAllowedPublicCorsOrigin(req.headers.origin, publicMcpUrl);\n\tif (!origin) return;\n\tres.setHeader(\"Access-Control-Allow-Origin\", origin);\n\tres.setHeader(\"Access-Control-Allow-Methods\", \"GET,POST,OPTIONS\");\n\tres.setHeader(\n\t\t\"Access-Control-Allow-Headers\",\n\t\treq.headers[\"access-control-request-headers\"] ?? CORS_ALLOW_HEADERS,\n\t);\n\tres.setHeader(\"Access-Control-Max-Age\", CORS_MAX_AGE_SECONDS);\n\tres.setHeader(\"Vary\", \"Origin\");\n}\n\nfunction getAllowedPublicCorsOrigin(\n\theader: string | undefined,\n\tpublicMcpUrl: URL,\n): string | undefined {\n\tif (!header) return undefined;\n\ttry {\n\t\tconst origin = new URL(header).origin;\n\t\tif (origin === publicMcpUrl.origin || TRUSTED_PUBLIC_BROWSER_ORIGINS.has(origin)) {\n\t\t\treturn origin;\n\t\t}\n\t} catch {\n\t\treturn undefined;\n\t}\n\treturn undefined;\n}\n\nfunction emitHttpGuardDeny(\n\treq: IncomingMessage,\n\tpathname: string,\n\tpublicMcpUrl: URL | undefined,\n): void {\n\tconsole.warn(\n\t\tJSON.stringify({\n\t\t\tsource: \"codemem-mcp-http-guard\",\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t\toutcome: \"denied\",\n\t\t\treason: \"host_or_origin_mismatch\",\n\t\t\tmethod: req.method,\n\t\t\tpath: pathname,\n\t\t\thost: truncateGuardLogField(req.headers.host),\n\t\t\torigin: truncateGuardLogField(req.headers.origin),\n\t\t\texpectedOrigin: publicMcpUrl?.origin,\n\t\t\tremoteAddress: req.socket.remoteAddress ?? undefined,\n\t\t}),\n\t);\n}\n\nfunction truncateGuardLogField(value: string | undefined): string | undefined {\n\tif (!value || value.length <= MAX_GUARD_LOG_FIELD_LENGTH) return value;\n\treturn `${value.slice(0, MAX_GUARD_LOG_FIELD_LENGTH)}…`;\n}\n\nfunction isAllowedPublicRequestHost(header: string | undefined, publicMcpUrl: URL): boolean {\n\tconst parsed = parseHostHeader(header);\n\tif (!parsed) return false;\n\tconst expectedPort = publicMcpUrl.port\n\t\t? Number(publicMcpUrl.port)\n\t\t: publicMcpUrl.protocol === \"https:\"\n\t\t\t? 443\n\t\t\t: 80;\n\tconst impliedPort = publicMcpUrl.protocol === \"https:\" ? 443 : 80;\n\tconst actualPort = parsed.port ?? impliedPort;\n\treturn (\n\t\tnormalizeHost(parsed.host) === normalizeHost(publicMcpUrl.hostname) &&\n\t\tactualPort === expectedPort\n\t);\n}\n\nfunction getBoundPort(server: Server): number {\n\tconst address = server.address();\n\tif (!address || typeof address === \"string\") return DEFAULT_MCP_HTTP_PORT;\n\treturn address.port;\n}\n\nfunction formatHostForUrl(host: string): string {\n\treturn isIP(host) === 6 ? `[${host}]` : host;\n}\n\nfunction getServerUrl(server: Server, host: string): string {\n\treturn `http://${formatHostForUrl(host)}:${getBoundPort(server)}/mcp`;\n}\n\nfunction getSdkIssuerUrl(publicMcpUrl: URL, port: number): URL {\n\tif (publicMcpUrl.protocol === \"https:\") return new URL(publicMcpUrl.origin);\n\tif (isLoopbackHost(publicMcpUrl.hostname) && normalizeHost(publicMcpUrl.hostname) !== \"::1\") {\n\t\treturn new URL(publicMcpUrl.origin);\n\t}\n\treturn new URL(`http://localhost:${port}/`);\n}\n\nfunction isOAuthOrMetadataPath(pathname: string): boolean {\n\treturn (\n\t\tpathname === \"/register\" ||\n\t\tpathname === \"/authorize\" ||\n\t\tpathname === \"/token\" ||\n\t\tpathname === \"/revoke\" ||\n\t\tpathname === \"/oauth/callback\" ||\n\t\tpathname === \"/.well-known/oauth-authorization-server\" ||\n\t\tpathname === \"/.well-known/oauth-protected-resource/mcp\"\n\t);\n}\n\nfunction normalizeRoutePath(pathname: string): string {\n\treturn pathname.length > 1 ? pathname.replace(/\\/+$/, \"\") : pathname;\n}\n\nfunction auditOAuthRouteResponses(\n\tauditEmit: (event: ReturnType<typeof buildOAuthAuditEvent>) => void,\n) {\n\treturn (req: Request, res: Response, next: NextFunction) => {\n\t\tconst pathname = req.path;\n\t\tif (!isAuditedOAuthPath(pathname)) return next();\n\t\tlet responseBody: unknown;\n\t\tconst originalJson = res.json.bind(res);\n\t\tres.json = ((body: unknown) => {\n\t\t\tresponseBody = body;\n\t\t\treturn originalJson(body);\n\t\t}) as typeof res.json;\n\t\tres.on(\"finish\", () => {\n\t\t\tif (pathname === \"/oauth/callback\") return;\n\t\t\tconst kind = oauthAuditKindForRequest(pathname, req);\n\t\t\tif (!kind) return;\n\t\t\tconst error = getOAuthResponseError(res, responseBody);\n\t\t\tconst clientId = getRequestClientId(req, responseBody);\n\t\t\tauditEmit(\n\t\t\t\tbuildOAuthAuditEvent(kind, {\n\t\t\t\t\toutcome: error ? \"denied\" : \"success\",\n\t\t\t\t\t...(error ? { reason: error } : {}),\n\t\t\t\t\t...(clientId ? { clientId } : {}),\n\t\t\t\t\tremoteAddress: req.socket.remoteAddress ?? undefined,\n\t\t\t\t}),\n\t\t\t);\n\t\t});\n\t\tnext();\n\t};\n}\n\nfunction isAuditedOAuthPath(pathname: string): boolean {\n\treturn oauthAuditKindForPath(pathname) !== null;\n}\n\nfunction oauthAuditKindForRequest(\n\tpathname: string,\n\treq: Request,\n): \"registration\" | \"authorize\" | \"token\" | \"refresh\" | \"revocation\" | null {\n\tif (pathname === \"/token\" && req.body?.grant_type === \"refresh_token\") return \"refresh\";\n\treturn oauthAuditKindForPath(pathname);\n}\n\nfunction oauthAuditKindForPath(\n\tpathname: string,\n): \"registration\" | \"authorize\" | \"token\" | \"revocation\" | null {\n\tif (pathname === \"/register\") return \"registration\";\n\tif (pathname === \"/authorize\") return \"authorize\";\n\tif (pathname === \"/token\") return \"token\";\n\tif (pathname === \"/revoke\") return \"revocation\";\n\treturn null;\n}\n\nfunction getOAuthResponseError(res: Response, body: unknown): string | undefined {\n\tconst bodyError = getOAuthBodyError(body);\n\tif (bodyError) return bodyError;\n\tconst location = res.getHeader(\"location\");\n\tif (typeof location !== \"string\") return undefined;\n\ttry {\n\t\tconst redirect = new URL(location);\n\t\treturn redirect.searchParams.get(\"error\") ?? undefined;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nfunction getOAuthBodyError(body: unknown): string | undefined {\n\tif (\n\t\ttypeof body === \"object\" &&\n\t\tbody !== null &&\n\t\t\"error\" in body &&\n\t\ttypeof body.error === \"string\"\n\t) {\n\t\treturn body.error;\n\t}\n\treturn undefined;\n}\n\nfunction getRequestClientId(req: Request, body: unknown): string | undefined {\n\tif (\n\t\ttypeof body === \"object\" &&\n\t\tbody !== null &&\n\t\t\"client_id\" in body &&\n\t\ttypeof body.client_id === \"string\"\n\t) {\n\t\treturn body.client_id;\n\t}\n\tconst bodyClientId = typeof req.body?.client_id === \"string\" ? req.body.client_id : undefined;\n\tif (bodyClientId) return bodyClientId;\n\tconst queryClientId = typeof req.query.client_id === \"string\" ? req.query.client_id : undefined;\n\treturn queryClientId;\n}\n\nfunction auditBearerPreflight(\n\tauditEmit: (event: ReturnType<typeof buildOAuthAuditEvent>) => void,\n\ttokenStore: OAuthAccessTokenStore,\n) {\n\treturn (req: Request, _res: Response, next: NextFunction) => {\n\t\tconst reason = getBearerPreflightDenyReason(req.headers.authorization, tokenStore);\n\t\tif (reason) {\n\t\t\tauditEmit(\n\t\t\t\tbuildOAuthAuditEvent(\"bearer\", {\n\t\t\t\t\toutcome: \"denied\",\n\t\t\t\t\treason,\n\t\t\t\t\tremoteAddress: req.socket.remoteAddress ?? undefined,\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t\tnext();\n\t};\n}\n\nfunction getBearerPreflightDenyReason(\n\theader: string | undefined,\n\ttokenStore: OAuthAccessTokenStore,\n): BearerDenyReason | null {\n\tif (!header) return \"missing_authorization_header\";\n\tconst [scheme, token, extra] = header.trim().split(/\\s+/);\n\tif (!scheme || !token || extra || scheme.toLowerCase() !== \"bearer\") {\n\t\treturn \"malformed_authorization_header\";\n\t}\n\tconst verification = tokenStore.verifyToken(token);\n\tif (!verification.ok) return verification.reason;\n\treturn null;\n}\n\nfunction parseScopeList(scope: string | null | undefined): string[] {\n\treturn (\n\t\tscope\n\t\t\t?.split(/\\s+/)\n\t\t\t.map((item) => item.trim())\n\t\t\t.filter(Boolean) ?? []\n\t);\n}\n\nfunction isEntrypoint(): boolean {\n\tconst script = process.argv[1];\n\treturn script ? import.meta.url === pathToFileURL(script).href : false;\n}\n\nasync function main() {\n\tconst httpServer = await startCodememMcpHttpServer();\n\tconsole.error(`codemem MCP HTTP server listening at ${httpServer.url}`);\n\n\tconst shutdown = async () => {\n\t\ttry {\n\t\t\tawait httpServer.close();\n\t\t} catch {\n\t\t\t// Best effort — process is exiting.\n\t\t}\n\t\tprocess.exit(0);\n\t};\n\n\tprocess.on(\"SIGINT\", shutdown);\n\tprocess.on(\"SIGTERM\", shutdown);\n}\n\nif (isEntrypoint()) {\n\tmain().catch((err) => {\n\t\tconsole.error(\"codemem MCP HTTP server failed to start:\", err);\n\t\tprocess.exit(1);\n\t});\n}\n"],"x_google_ignoreList":[0,1,2,3,4,5,6,7,8,9],"mappings":"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"}
1
+ {"version":3,"file":"http.js","names":["Address6","MemoryStore","Buffer","isIPv62","#clients","#codes","#deleteExpiredCodes","#tokensByHash","#tokenHashKey","#deleteInactiveTokens","#grantsById","#grantIdsByRefreshHash","#refreshHashesByGrantId","#deleteInactiveGrants","#deleteGrantRefreshHashIndexEntries","#path","#load","#deleteInactive","#save","#records","#deleteExpired","#clientsStore","#codeStore","#tokenStore","#refreshTokenStore","#publicMcpUrl","#resourceServerUrl","#oidc","#now"],"sources":["../../../node_modules/.pnpm/ip-address@10.1.1/node_modules/ip-address/dist/common.js","../../../node_modules/.pnpm/ip-address@10.1.1/node_modules/ip-address/dist/v4/constants.js","../../../node_modules/.pnpm/ip-address@10.1.1/node_modules/ip-address/dist/address-error.js","../../../node_modules/.pnpm/ip-address@10.1.1/node_modules/ip-address/dist/ipv4.js","../../../node_modules/.pnpm/ip-address@10.1.1/node_modules/ip-address/dist/v6/constants.js","../../../node_modules/.pnpm/ip-address@10.1.1/node_modules/ip-address/dist/v6/helpers.js","../../../node_modules/.pnpm/ip-address@10.1.1/node_modules/ip-address/dist/v6/regular-expressions.js","../../../node_modules/.pnpm/ip-address@10.1.1/node_modules/ip-address/dist/ipv6.js","../../../node_modules/.pnpm/ip-address@10.1.1/node_modules/ip-address/dist/ip-address.js","../../../node_modules/.pnpm/express-rate-limit@8.5.2_express@5.2.1/node_modules/express-rate-limit/dist/index.mjs","../src/audit.ts","../src/oauth.ts","../src/oidc.ts","../src/provider.ts","../src/http.ts"],"sourcesContent":["\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.isInSubnet = isInSubnet;\nexports.isCorrect = isCorrect;\nexports.numberToPaddedHex = numberToPaddedHex;\nexports.stringToPaddedHex = stringToPaddedHex;\nexports.testBit = testBit;\nfunction isInSubnet(address) {\n if (this.subnetMask < address.subnetMask) {\n return false;\n }\n if (this.mask(address.subnetMask) === address.mask()) {\n return true;\n }\n return false;\n}\nfunction isCorrect(defaultBits) {\n return function () {\n if (this.addressMinusSuffix !== this.correctForm()) {\n return false;\n }\n if (this.subnetMask === defaultBits && !this.parsedSubnet) {\n return true;\n }\n return this.parsedSubnet === String(this.subnetMask);\n };\n}\nfunction numberToPaddedHex(number) {\n return number.toString(16).padStart(2, '0');\n}\nfunction stringToPaddedHex(numberString) {\n return numberToPaddedHex(parseInt(numberString, 10));\n}\n/**\n * @param binaryValue Binary representation of a value (e.g. `10`)\n * @param position Byte position, where 0 is the least significant bit\n */\nfunction testBit(binaryValue, position) {\n const { length } = binaryValue;\n if (position > length) {\n return false;\n }\n const positionInString = length - position;\n return binaryValue.substring(positionInString, positionInString + 1) === '1';\n}\n//# sourceMappingURL=common.js.map","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.RE_SUBNET_STRING = exports.RE_ADDRESS = exports.GROUPS = exports.BITS = void 0;\nexports.BITS = 32;\nexports.GROUPS = 4;\nexports.RE_ADDRESS = /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/g;\nexports.RE_SUBNET_STRING = /\\/\\d{1,2}$/;\n//# sourceMappingURL=constants.js.map","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.AddressError = void 0;\nclass AddressError extends Error {\n constructor(message, parseMessage) {\n super(message);\n this.name = 'AddressError';\n this.parseMessage = parseMessage;\n }\n}\nexports.AddressError = AddressError;\n//# sourceMappingURL=address-error.js.map","\"use strict\";\n/* eslint-disable no-param-reassign */\nvar __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n var desc = Object.getOwnPropertyDescriptor(m, k);\n if (!desc || (\"get\" in desc ? !m.__esModule : desc.writable || desc.configurable)) {\n desc = { enumerable: true, get: function() { return m[k]; } };\n }\n Object.defineProperty(o, k2, desc);\n}) : (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n o[k2] = m[k];\n}));\nvar __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\n}) : function(o, v) {\n o[\"default\"] = v;\n});\nvar __importStar = (this && this.__importStar) || function (mod) {\n if (mod && mod.__esModule) return mod;\n var result = {};\n if (mod != null) for (var k in mod) if (k !== \"default\" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\n __setModuleDefault(result, mod);\n return result;\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.Address4 = void 0;\nconst common = __importStar(require(\"./common\"));\nconst constants = __importStar(require(\"./v4/constants\"));\nconst address_error_1 = require(\"./address-error\");\n/**\n * Represents an IPv4 address\n * @class Address4\n * @param {string} address - An IPv4 address string\n */\nclass Address4 {\n constructor(address) {\n this.groups = constants.GROUPS;\n this.parsedAddress = [];\n this.parsedSubnet = '';\n this.subnet = '/32';\n this.subnetMask = 32;\n this.v4 = true;\n /**\n * Returns true if the address is correct, false otherwise\n * @memberof Address4\n * @instance\n * @returns {Boolean}\n */\n this.isCorrect = common.isCorrect(constants.BITS);\n /**\n * Returns true if the given address is in the subnet of the current address\n * @memberof Address4\n * @instance\n * @returns {boolean}\n */\n this.isInSubnet = common.isInSubnet;\n this.address = address;\n const subnet = constants.RE_SUBNET_STRING.exec(address);\n if (subnet) {\n this.parsedSubnet = subnet[0].replace('/', '');\n this.subnetMask = parseInt(this.parsedSubnet, 10);\n this.subnet = `/${this.subnetMask}`;\n if (this.subnetMask < 0 || this.subnetMask > constants.BITS) {\n throw new address_error_1.AddressError('Invalid subnet mask.');\n }\n address = address.replace(constants.RE_SUBNET_STRING, '');\n }\n this.addressMinusSuffix = address;\n this.parsedAddress = this.parse(address);\n }\n static isValid(address) {\n try {\n // eslint-disable-next-line no-new\n new Address4(address);\n return true;\n }\n catch (e) {\n return false;\n }\n }\n /*\n * Parses a v4 address\n */\n parse(address) {\n const groups = address.split('.');\n if (!address.match(constants.RE_ADDRESS)) {\n throw new address_error_1.AddressError('Invalid IPv4 address.');\n }\n return groups;\n }\n /**\n * Returns the correct form of an address\n * @memberof Address4\n * @instance\n * @returns {String}\n */\n correctForm() {\n return this.parsedAddress.map((part) => parseInt(part, 10)).join('.');\n }\n /**\n * Converts a hex string to an IPv4 address object\n * @memberof Address4\n * @static\n * @param {string} hex - a hex string to convert\n * @returns {Address4}\n */\n static fromHex(hex) {\n const padded = hex.replace(/:/g, '').padStart(8, '0');\n const groups = [];\n let i;\n for (i = 0; i < 8; i += 2) {\n const h = padded.slice(i, i + 2);\n groups.push(parseInt(h, 16));\n }\n return new Address4(groups.join('.'));\n }\n /**\n * Converts an integer into a IPv4 address object\n * @memberof Address4\n * @static\n * @param {integer} integer - a number to convert\n * @returns {Address4}\n */\n static fromInteger(integer) {\n return Address4.fromHex(integer.toString(16));\n }\n /**\n * Return an address from in-addr.arpa form\n * @memberof Address4\n * @static\n * @param {string} arpaFormAddress - an 'in-addr.arpa' form ipv4 address\n * @returns {Adress4}\n * @example\n * var address = Address4.fromArpa(42.2.0.192.in-addr.arpa.)\n * address.correctForm(); // '192.0.2.42'\n */\n static fromArpa(arpaFormAddress) {\n // remove ending \".in-addr.arpa.\" or just \".\"\n const leader = arpaFormAddress.replace(/(\\.in-addr\\.arpa)?\\.$/, '');\n const address = leader.split('.').reverse().join('.');\n return new Address4(address);\n }\n /**\n * Converts an IPv4 address object to a hex string\n * @memberof Address4\n * @instance\n * @returns {String}\n */\n toHex() {\n return this.parsedAddress.map((part) => common.stringToPaddedHex(part)).join(':');\n }\n /**\n * Converts an IPv4 address object to an array of bytes\n * @memberof Address4\n * @instance\n * @returns {Array}\n */\n toArray() {\n return this.parsedAddress.map((part) => parseInt(part, 10));\n }\n /**\n * Converts an IPv4 address object to an IPv6 address group\n * @memberof Address4\n * @instance\n * @returns {String}\n */\n toGroup6() {\n const output = [];\n let i;\n for (i = 0; i < constants.GROUPS; i += 2) {\n output.push(`${common.stringToPaddedHex(this.parsedAddress[i])}${common.stringToPaddedHex(this.parsedAddress[i + 1])}`);\n }\n return output.join(':');\n }\n /**\n * Returns the address as a `bigint`\n * @memberof Address4\n * @instance\n * @returns {bigint}\n */\n bigInt() {\n return BigInt(`0x${this.parsedAddress.map((n) => common.stringToPaddedHex(n)).join('')}`);\n }\n /**\n * Helper function getting start address.\n * @memberof Address4\n * @instance\n * @returns {bigint}\n */\n _startAddress() {\n return BigInt(`0b${this.mask() + '0'.repeat(constants.BITS - this.subnetMask)}`);\n }\n /**\n * The first address in the range given by this address' subnet.\n * Often referred to as the Network Address.\n * @memberof Address4\n * @instance\n * @returns {Address4}\n */\n startAddress() {\n return Address4.fromBigInt(this._startAddress());\n }\n /**\n * The first host address in the range given by this address's subnet ie\n * the first address after the Network Address\n * @memberof Address4\n * @instance\n * @returns {Address4}\n */\n startAddressExclusive() {\n const adjust = BigInt('1');\n return Address4.fromBigInt(this._startAddress() + adjust);\n }\n /**\n * Helper function getting end address.\n * @memberof Address4\n * @instance\n * @returns {bigint}\n */\n _endAddress() {\n return BigInt(`0b${this.mask() + '1'.repeat(constants.BITS - this.subnetMask)}`);\n }\n /**\n * The last address in the range given by this address' subnet\n * Often referred to as the Broadcast\n * @memberof Address4\n * @instance\n * @returns {Address4}\n */\n endAddress() {\n return Address4.fromBigInt(this._endAddress());\n }\n /**\n * The last host address in the range given by this address's subnet ie\n * the last address prior to the Broadcast Address\n * @memberof Address4\n * @instance\n * @returns {Address4}\n */\n endAddressExclusive() {\n const adjust = BigInt('1');\n return Address4.fromBigInt(this._endAddress() - adjust);\n }\n /**\n * Converts a BigInt to a v4 address object\n * @memberof Address4\n * @static\n * @param {bigint} bigInt - a BigInt to convert\n * @returns {Address4}\n */\n static fromBigInt(bigInt) {\n return Address4.fromHex(bigInt.toString(16));\n }\n /**\n * Convert a byte array to an Address4 object\n * @memberof Address4\n * @static\n * @param {Array<number>} bytes - an array of 4 bytes (0-255)\n * @returns {Address4}\n */\n static fromByteArray(bytes) {\n if (bytes.length !== 4) {\n throw new address_error_1.AddressError('IPv4 addresses require exactly 4 bytes');\n }\n // Validate that all bytes are within valid range (0-255)\n for (let i = 0; i < bytes.length; i++) {\n if (!Number.isInteger(bytes[i]) || bytes[i] < 0 || bytes[i] > 255) {\n throw new address_error_1.AddressError('All bytes must be integers between 0 and 255');\n }\n }\n return this.fromUnsignedByteArray(bytes);\n }\n /**\n * Convert an unsigned byte array to an Address4 object\n * @memberof Address4\n * @static\n * @param {Array<number>} bytes - an array of 4 unsigned bytes (0-255)\n * @returns {Address4}\n */\n static fromUnsignedByteArray(bytes) {\n if (bytes.length !== 4) {\n throw new address_error_1.AddressError('IPv4 addresses require exactly 4 bytes');\n }\n const address = bytes.join('.');\n return new Address4(address);\n }\n /**\n * Returns the first n bits of the address, defaulting to the\n * subnet mask\n * @memberof Address4\n * @instance\n * @returns {String}\n */\n mask(mask) {\n if (mask === undefined) {\n mask = this.subnetMask;\n }\n return this.getBitsBase2(0, mask);\n }\n /**\n * Returns the bits in the given range as a base-2 string\n * @memberof Address4\n * @instance\n * @returns {string}\n */\n getBitsBase2(start, end) {\n return this.binaryZeroPad().slice(start, end);\n }\n /**\n * Return the reversed ip6.arpa form of the address\n * @memberof Address4\n * @param {Object} options\n * @param {boolean} options.omitSuffix - omit the \"in-addr.arpa\" suffix\n * @instance\n * @returns {String}\n */\n reverseForm(options) {\n if (!options) {\n options = {};\n }\n const reversed = this.correctForm().split('.').reverse().join('.');\n if (options.omitSuffix) {\n return reversed;\n }\n return `${reversed}.in-addr.arpa.`;\n }\n /**\n * Returns true if the given address is a multicast address\n * @memberof Address4\n * @instance\n * @returns {boolean}\n */\n isMulticast() {\n return this.isInSubnet(new Address4('224.0.0.0/4'));\n }\n /**\n * Returns a zero-padded base-2 string representation of the address\n * @memberof Address4\n * @instance\n * @returns {string}\n */\n binaryZeroPad() {\n return this.bigInt().toString(2).padStart(constants.BITS, '0');\n }\n /**\n * Groups an IPv4 address for inclusion at the end of an IPv6 address\n * @returns {String}\n */\n groupForV6() {\n const segments = this.parsedAddress;\n return this.address.replace(constants.RE_ADDRESS, `<span class=\"hover-group group-v4 group-6\">${segments\n .slice(0, 2)\n .join('.')}</span>.<span class=\"hover-group group-v4 group-7\">${segments\n .slice(2, 4)\n .join('.')}</span>`);\n }\n}\nexports.Address4 = Address4;\n//# sourceMappingURL=ipv4.js.map","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.RE_URL_WITH_PORT = exports.RE_URL = exports.RE_ZONE_STRING = exports.RE_SUBNET_STRING = exports.RE_BAD_ADDRESS = exports.RE_BAD_CHARACTERS = exports.TYPES = exports.SCOPES = exports.GROUPS = exports.BITS = void 0;\nexports.BITS = 128;\nexports.GROUPS = 8;\n/**\n * Represents IPv6 address scopes\n * @memberof Address6\n * @static\n */\nexports.SCOPES = {\n 0: 'Reserved',\n 1: 'Interface local',\n 2: 'Link local',\n 4: 'Admin local',\n 5: 'Site local',\n 8: 'Organization local',\n 14: 'Global',\n 15: 'Reserved',\n};\n/**\n * Represents IPv6 address types\n * @memberof Address6\n * @static\n */\nexports.TYPES = {\n 'ff01::1/128': 'Multicast (All nodes on this interface)',\n 'ff01::2/128': 'Multicast (All routers on this interface)',\n 'ff02::1/128': 'Multicast (All nodes on this link)',\n 'ff02::2/128': 'Multicast (All routers on this link)',\n 'ff05::2/128': 'Multicast (All routers in this site)',\n 'ff02::5/128': 'Multicast (OSPFv3 AllSPF routers)',\n 'ff02::6/128': 'Multicast (OSPFv3 AllDR routers)',\n 'ff02::9/128': 'Multicast (RIP routers)',\n 'ff02::a/128': 'Multicast (EIGRP routers)',\n 'ff02::d/128': 'Multicast (PIM routers)',\n 'ff02::16/128': 'Multicast (MLDv2 reports)',\n 'ff01::fb/128': 'Multicast (mDNSv6)',\n 'ff02::fb/128': 'Multicast (mDNSv6)',\n 'ff05::fb/128': 'Multicast (mDNSv6)',\n 'ff02::1:2/128': 'Multicast (All DHCP servers and relay agents on this link)',\n 'ff05::1:2/128': 'Multicast (All DHCP servers and relay agents in this site)',\n 'ff02::1:3/128': 'Multicast (All DHCP servers on this link)',\n 'ff05::1:3/128': 'Multicast (All DHCP servers in this site)',\n '::/128': 'Unspecified',\n '::1/128': 'Loopback',\n 'ff00::/8': 'Multicast',\n 'fe80::/10': 'Link-local unicast',\n};\n/**\n * A regular expression that matches bad characters in an IPv6 address\n * @memberof Address6\n * @static\n */\nexports.RE_BAD_CHARACTERS = /([^0-9a-f:/%])/gi;\n/**\n * A regular expression that matches an incorrect IPv6 address\n * @memberof Address6\n * @static\n */\nexports.RE_BAD_ADDRESS = /([0-9a-f]{5,}|:{3,}|[^:]:$|^:[^:]|\\/$)/gi;\n/**\n * A regular expression that matches an IPv6 subnet\n * @memberof Address6\n * @static\n */\nexports.RE_SUBNET_STRING = /\\/\\d{1,3}(?=%|$)/;\n/**\n * A regular expression that matches an IPv6 zone\n * @memberof Address6\n * @static\n */\nexports.RE_ZONE_STRING = /%.*$/;\nexports.RE_URL = /^\\[{0,1}([0-9a-f:]+)\\]{0,1}/;\nexports.RE_URL_WITH_PORT = /\\[([0-9a-f:]+)\\]:([0-9]{1,5})/;\n//# sourceMappingURL=constants.js.map","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.escapeHtml = escapeHtml;\nexports.spanAllZeroes = spanAllZeroes;\nexports.spanAll = spanAll;\nexports.spanLeadingZeroes = spanLeadingZeroes;\nexports.simpleGroup = simpleGroup;\nfunction escapeHtml(s) {\n return s\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#39;');\n}\n/**\n * @returns {String} the string with all zeroes contained in a <span>\n */\nfunction spanAllZeroes(s) {\n return escapeHtml(s).replace(/(0+)/g, '<span class=\"zero\">$1</span>');\n}\n/**\n * @returns {String} the string with each character contained in a <span>\n */\nfunction spanAll(s, offset = 0) {\n const letters = s.split('');\n return letters\n .map((n, i) => `<span class=\"digit value-${escapeHtml(n)} position-${i + offset}\">${spanAllZeroes(n)}</span>`)\n .join('');\n}\nfunction spanLeadingZeroesSimple(group) {\n return escapeHtml(group).replace(/^(0+)/, '<span class=\"zero\">$1</span>');\n}\n/**\n * @returns {String} the string with leading zeroes contained in a <span>\n */\nfunction spanLeadingZeroes(address) {\n const groups = address.split(':');\n return groups.map((g) => spanLeadingZeroesSimple(g)).join(':');\n}\n/**\n * Groups an address\n * @returns {String} a grouped address\n */\nfunction simpleGroup(addressString, offset = 0) {\n const groups = addressString.split(':');\n return groups.map((g, i) => {\n if (/group-v4/.test(g)) {\n return g;\n }\n return `<span class=\"hover-group group-${i + offset}\">${spanLeadingZeroesSimple(g)}</span>`;\n });\n}\n//# sourceMappingURL=helpers.js.map","\"use strict\";\nvar __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n var desc = Object.getOwnPropertyDescriptor(m, k);\n if (!desc || (\"get\" in desc ? !m.__esModule : desc.writable || desc.configurable)) {\n desc = { enumerable: true, get: function() { return m[k]; } };\n }\n Object.defineProperty(o, k2, desc);\n}) : (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n o[k2] = m[k];\n}));\nvar __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\n}) : function(o, v) {\n o[\"default\"] = v;\n});\nvar __importStar = (this && this.__importStar) || function (mod) {\n if (mod && mod.__esModule) return mod;\n var result = {};\n if (mod != null) for (var k in mod) if (k !== \"default\" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\n __setModuleDefault(result, mod);\n return result;\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.ADDRESS_BOUNDARY = void 0;\nexports.groupPossibilities = groupPossibilities;\nexports.padGroup = padGroup;\nexports.simpleRegularExpression = simpleRegularExpression;\nexports.possibleElisions = possibleElisions;\nconst v6 = __importStar(require(\"./constants\"));\nfunction groupPossibilities(possibilities) {\n return `(${possibilities.join('|')})`;\n}\nfunction padGroup(group) {\n if (group.length < 4) {\n return `0{0,${4 - group.length}}${group}`;\n }\n return group;\n}\nexports.ADDRESS_BOUNDARY = '[^A-Fa-f0-9:]';\nfunction simpleRegularExpression(groups) {\n const zeroIndexes = [];\n groups.forEach((group, i) => {\n const groupInteger = parseInt(group, 16);\n if (groupInteger === 0) {\n zeroIndexes.push(i);\n }\n });\n // You can technically elide a single 0, this creates the regular expressions\n // to match that eventuality\n const possibilities = zeroIndexes.map((zeroIndex) => groups\n .map((group, i) => {\n if (i === zeroIndex) {\n const elision = i === 0 || i === v6.GROUPS - 1 ? ':' : '';\n return groupPossibilities([padGroup(group), elision]);\n }\n return padGroup(group);\n })\n .join(':'));\n // The simplest case\n possibilities.push(groups.map(padGroup).join(':'));\n return groupPossibilities(possibilities);\n}\nfunction possibleElisions(elidedGroups, moreLeft, moreRight) {\n const left = moreLeft ? '' : ':';\n const right = moreRight ? '' : ':';\n const possibilities = [];\n // 1. elision of everything (::)\n if (!moreLeft && !moreRight) {\n possibilities.push('::');\n }\n // 2. complete elision of the middle\n if (moreLeft && moreRight) {\n possibilities.push('');\n }\n if ((moreRight && !moreLeft) || (!moreRight && moreLeft)) {\n // 3. complete elision of one side\n possibilities.push(':');\n }\n // 4. elision from the left side\n possibilities.push(`${left}(:0{1,4}){1,${elidedGroups - 1}}`);\n // 5. elision from the right side\n possibilities.push(`(0{1,4}:){1,${elidedGroups - 1}}${right}`);\n // 6. no elision\n possibilities.push(`(0{1,4}:){${elidedGroups - 1}}0{1,4}`);\n // 7. elision (including sloppy elision) from the middle\n for (let groups = 1; groups < elidedGroups - 1; groups++) {\n for (let position = 1; position < elidedGroups - groups; position++) {\n possibilities.push(`(0{1,4}:){${position}}:(0{1,4}:){${elidedGroups - position - groups - 1}}0{1,4}`);\n }\n }\n return groupPossibilities(possibilities);\n}\n//# sourceMappingURL=regular-expressions.js.map","\"use strict\";\n/* eslint-disable prefer-destructuring */\n/* eslint-disable no-param-reassign */\nvar __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n var desc = Object.getOwnPropertyDescriptor(m, k);\n if (!desc || (\"get\" in desc ? !m.__esModule : desc.writable || desc.configurable)) {\n desc = { enumerable: true, get: function() { return m[k]; } };\n }\n Object.defineProperty(o, k2, desc);\n}) : (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n o[k2] = m[k];\n}));\nvar __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\n}) : function(o, v) {\n o[\"default\"] = v;\n});\nvar __importStar = (this && this.__importStar) || function (mod) {\n if (mod && mod.__esModule) return mod;\n var result = {};\n if (mod != null) for (var k in mod) if (k !== \"default\" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\n __setModuleDefault(result, mod);\n return result;\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.Address6 = void 0;\nconst common = __importStar(require(\"./common\"));\nconst constants4 = __importStar(require(\"./v4/constants\"));\nconst constants6 = __importStar(require(\"./v6/constants\"));\nconst helpers = __importStar(require(\"./v6/helpers\"));\nconst ipv4_1 = require(\"./ipv4\");\nconst regular_expressions_1 = require(\"./v6/regular-expressions\");\nconst address_error_1 = require(\"./address-error\");\nconst common_1 = require(\"./common\");\nfunction assert(condition) {\n if (!condition) {\n throw new Error('Assertion failed.');\n }\n}\nfunction addCommas(number) {\n const r = /(\\d+)(\\d{3})/;\n while (r.test(number)) {\n number = number.replace(r, '$1,$2');\n }\n return number;\n}\nfunction spanLeadingZeroes4(n) {\n n = n.replace(/^(0{1,})([1-9]+)$/, '<span class=\"parse-error\">$1</span>$2');\n n = n.replace(/^(0{1,})(0)$/, '<span class=\"parse-error\">$1</span>$2');\n return n;\n}\n/*\n * A helper function to compact an array\n */\nfunction compact(address, slice) {\n const s1 = [];\n const s2 = [];\n let i;\n for (i = 0; i < address.length; i++) {\n if (i < slice[0]) {\n s1.push(address[i]);\n }\n else if (i > slice[1]) {\n s2.push(address[i]);\n }\n }\n return s1.concat(['compact']).concat(s2);\n}\nfunction paddedHex(octet) {\n return parseInt(octet, 16).toString(16).padStart(4, '0');\n}\nfunction unsignByte(b) {\n // eslint-disable-next-line no-bitwise\n return b & 0xff;\n}\n/**\n * Represents an IPv6 address\n * @class Address6\n * @param {string} address - An IPv6 address string\n * @param {number} [groups=8] - How many octets to parse\n * @example\n * var address = new Address6('2001::/32');\n */\nclass Address6 {\n constructor(address, optionalGroups) {\n this.addressMinusSuffix = '';\n this.parsedSubnet = '';\n this.subnet = '/128';\n this.subnetMask = 128;\n this.v4 = false;\n this.zone = '';\n // #region Attributes\n /**\n * Returns true if the given address is in the subnet of the current address\n * @memberof Address6\n * @instance\n * @returns {boolean}\n */\n this.isInSubnet = common.isInSubnet;\n /**\n * Returns true if the address is correct, false otherwise\n * @memberof Address6\n * @instance\n * @returns {boolean}\n */\n this.isCorrect = common.isCorrect(constants6.BITS);\n if (optionalGroups === undefined) {\n this.groups = constants6.GROUPS;\n }\n else {\n this.groups = optionalGroups;\n }\n this.address = address;\n const subnet = constants6.RE_SUBNET_STRING.exec(address);\n if (subnet) {\n this.parsedSubnet = subnet[0].replace('/', '');\n this.subnetMask = parseInt(this.parsedSubnet, 10);\n this.subnet = `/${this.subnetMask}`;\n if (Number.isNaN(this.subnetMask) ||\n this.subnetMask < 0 ||\n this.subnetMask > constants6.BITS) {\n throw new address_error_1.AddressError('Invalid subnet mask.');\n }\n address = address.replace(constants6.RE_SUBNET_STRING, '');\n }\n else if (/\\//.test(address)) {\n throw new address_error_1.AddressError('Invalid subnet mask.');\n }\n const zone = constants6.RE_ZONE_STRING.exec(address);\n if (zone) {\n this.zone = zone[0];\n address = address.replace(constants6.RE_ZONE_STRING, '');\n }\n this.addressMinusSuffix = address;\n this.parsedAddress = this.parse(this.addressMinusSuffix);\n }\n static isValid(address) {\n try {\n // eslint-disable-next-line no-new\n new Address6(address);\n return true;\n }\n catch (e) {\n return false;\n }\n }\n /**\n * Convert a BigInt to a v6 address object\n * @memberof Address6\n * @static\n * @param {bigint} bigInt - a BigInt to convert\n * @returns {Address6}\n * @example\n * var bigInt = BigInt('1000000000000');\n * var address = Address6.fromBigInt(bigInt);\n * address.correctForm(); // '::e8:d4a5:1000'\n */\n static fromBigInt(bigInt) {\n const hex = bigInt.toString(16).padStart(32, '0');\n const groups = [];\n let i;\n for (i = 0; i < constants6.GROUPS; i++) {\n groups.push(hex.slice(i * 4, (i + 1) * 4));\n }\n return new Address6(groups.join(':'));\n }\n /**\n * Convert a URL (with optional port number) to an address object\n * @memberof Address6\n * @static\n * @param {string} url - a URL with optional port number\n * @example\n * var addressAndPort = Address6.fromURL('http://[ffff::]:8080/foo/');\n * addressAndPort.address.correctForm(); // 'ffff::'\n * addressAndPort.port; // 8080\n */\n static fromURL(url) {\n let host;\n let port = null;\n let result;\n // If we have brackets parse them and find a port\n if (url.indexOf('[') !== -1 && url.indexOf(']:') !== -1) {\n result = constants6.RE_URL_WITH_PORT.exec(url);\n if (result === null) {\n return {\n error: 'failed to parse address with port',\n address: null,\n port: null,\n };\n }\n host = result[1];\n port = result[2];\n // If there's a URL extract the address\n }\n else if (url.indexOf('/') !== -1) {\n // Remove the protocol prefix\n url = url.replace(/^[a-z0-9]+:\\/\\//, '');\n // Parse the address\n result = constants6.RE_URL.exec(url);\n if (result === null) {\n return {\n error: 'failed to parse address from URL',\n address: null,\n port: null,\n };\n }\n host = result[1];\n // Otherwise just assign the URL to the host and let the library parse it\n }\n else {\n host = url;\n }\n // If there's a port convert it to an integer\n if (port) {\n port = parseInt(port, 10);\n // squelch out of range ports\n if (port < 0 || port > 65536) {\n port = null;\n }\n }\n else {\n // Standardize `undefined` to `null`\n port = null;\n }\n return {\n address: new Address6(host),\n port,\n };\n }\n /**\n * Create an IPv6-mapped address given an IPv4 address\n * @memberof Address6\n * @static\n * @param {string} address - An IPv4 address string\n * @returns {Address6}\n * @example\n * var address = Address6.fromAddress4('192.168.0.1');\n * address.correctForm(); // '::ffff:c0a8:1'\n * address.to4in6(); // '::ffff:192.168.0.1'\n */\n static fromAddress4(address) {\n const address4 = new ipv4_1.Address4(address);\n const mask6 = constants6.BITS - (constants4.BITS - address4.subnetMask);\n return new Address6(`::ffff:${address4.correctForm()}/${mask6}`);\n }\n /**\n * Return an address from ip6.arpa form\n * @memberof Address6\n * @static\n * @param {string} arpaFormAddress - an 'ip6.arpa' form address\n * @returns {Adress6}\n * @example\n * var address = Address6.fromArpa(e.f.f.f.3.c.2.6.f.f.f.e.6.6.8.e.1.0.6.7.9.4.e.c.0.0.0.0.1.0.0.2.ip6.arpa.)\n * address.correctForm(); // '2001:0:ce49:7601:e866:efff:62c3:fffe'\n */\n static fromArpa(arpaFormAddress) {\n // remove ending \".ip6.arpa.\" or just \".\"\n let address = arpaFormAddress.replace(/(\\.ip6\\.arpa)?\\.$/, '');\n const semicolonAmount = 7;\n // correct ip6.arpa form with ending removed will be 63 characters\n if (address.length !== 63) {\n throw new address_error_1.AddressError(\"Invalid 'ip6.arpa' form.\");\n }\n const parts = address.split('.').reverse();\n for (let i = semicolonAmount; i > 0; i--) {\n const insertIndex = i * 4;\n parts.splice(insertIndex, 0, ':');\n }\n address = parts.join('');\n return new Address6(address);\n }\n /**\n * Return the Microsoft UNC transcription of the address\n * @memberof Address6\n * @instance\n * @returns {String} the Microsoft UNC transcription of the address\n */\n microsoftTranscription() {\n return `${this.correctForm().replace(/:/g, '-')}.ipv6-literal.net`;\n }\n /**\n * Return the first n bits of the address, defaulting to the subnet mask\n * @memberof Address6\n * @instance\n * @param {number} [mask=subnet] - the number of bits to mask\n * @returns {String} the first n bits of the address as a string\n */\n mask(mask = this.subnetMask) {\n return this.getBitsBase2(0, mask);\n }\n /**\n * Return the number of possible subnets of a given size in the address\n * @memberof Address6\n * @instance\n * @param {number} [subnetSize=128] - the subnet size\n * @returns {String}\n */\n // TODO: probably useful to have a numeric version of this too\n possibleSubnets(subnetSize = 128) {\n const availableBits = constants6.BITS - this.subnetMask;\n const subnetBits = Math.abs(subnetSize - constants6.BITS);\n const subnetPowers = availableBits - subnetBits;\n if (subnetPowers < 0) {\n return '0';\n }\n return addCommas((BigInt('2') ** BigInt(subnetPowers)).toString(10));\n }\n /**\n * Helper function getting start address.\n * @memberof Address6\n * @instance\n * @returns {bigint}\n */\n _startAddress() {\n return BigInt(`0b${this.mask() + '0'.repeat(constants6.BITS - this.subnetMask)}`);\n }\n /**\n * The first address in the range given by this address' subnet\n * Often referred to as the Network Address.\n * @memberof Address6\n * @instance\n * @returns {Address6}\n */\n startAddress() {\n return Address6.fromBigInt(this._startAddress());\n }\n /**\n * The first host address in the range given by this address's subnet ie\n * the first address after the Network Address\n * @memberof Address6\n * @instance\n * @returns {Address6}\n */\n startAddressExclusive() {\n const adjust = BigInt('1');\n return Address6.fromBigInt(this._startAddress() + adjust);\n }\n /**\n * Helper function getting end address.\n * @memberof Address6\n * @instance\n * @returns {bigint}\n */\n _endAddress() {\n return BigInt(`0b${this.mask() + '1'.repeat(constants6.BITS - this.subnetMask)}`);\n }\n /**\n * The last address in the range given by this address' subnet\n * Often referred to as the Broadcast\n * @memberof Address6\n * @instance\n * @returns {Address6}\n */\n endAddress() {\n return Address6.fromBigInt(this._endAddress());\n }\n /**\n * The last host address in the range given by this address's subnet ie\n * the last address prior to the Broadcast Address\n * @memberof Address6\n * @instance\n * @returns {Address6}\n */\n endAddressExclusive() {\n const adjust = BigInt('1');\n return Address6.fromBigInt(this._endAddress() - adjust);\n }\n /**\n * Return the scope of the address\n * @memberof Address6\n * @instance\n * @returns {String}\n */\n getScope() {\n let scope = constants6.SCOPES[parseInt(this.getBits(12, 16).toString(10), 10)];\n if (this.getType() === 'Global unicast' && scope !== 'Link local') {\n scope = 'Global';\n }\n return scope || 'Unknown';\n }\n /**\n * Return the type of the address\n * @memberof Address6\n * @instance\n * @returns {String}\n */\n getType() {\n for (const subnet of Object.keys(constants6.TYPES)) {\n if (this.isInSubnet(new Address6(subnet))) {\n return constants6.TYPES[subnet];\n }\n }\n return 'Global unicast';\n }\n /**\n * Return the bits in the given range as a BigInt\n * @memberof Address6\n * @instance\n * @returns {bigint}\n */\n getBits(start, end) {\n return BigInt(`0b${this.getBitsBase2(start, end)}`);\n }\n /**\n * Return the bits in the given range as a base-2 string\n * @memberof Address6\n * @instance\n * @returns {String}\n */\n getBitsBase2(start, end) {\n return this.binaryZeroPad().slice(start, end);\n }\n /**\n * Return the bits in the given range as a base-16 string\n * @memberof Address6\n * @instance\n * @returns {String}\n */\n getBitsBase16(start, end) {\n const length = end - start;\n if (length % 4 !== 0) {\n throw new Error('Length of bits to retrieve must be divisible by four');\n }\n return this.getBits(start, end)\n .toString(16)\n .padStart(length / 4, '0');\n }\n /**\n * Return the bits that are set past the subnet mask length\n * @memberof Address6\n * @instance\n * @returns {String}\n */\n getBitsPastSubnet() {\n return this.getBitsBase2(this.subnetMask, constants6.BITS);\n }\n /**\n * Return the reversed ip6.arpa form of the address\n * @memberof Address6\n * @param {Object} options\n * @param {boolean} options.omitSuffix - omit the \"ip6.arpa\" suffix\n * @instance\n * @returns {String}\n */\n reverseForm(options) {\n if (!options) {\n options = {};\n }\n const characters = Math.floor(this.subnetMask / 4);\n const reversed = this.canonicalForm()\n .replace(/:/g, '')\n .split('')\n .slice(0, characters)\n .reverse()\n .join('.');\n if (characters > 0) {\n if (options.omitSuffix) {\n return reversed;\n }\n return `${reversed}.ip6.arpa.`;\n }\n if (options.omitSuffix) {\n return '';\n }\n return 'ip6.arpa.';\n }\n /**\n * Return the correct form of the address\n * @memberof Address6\n * @instance\n * @returns {String}\n */\n correctForm() {\n let i;\n let groups = [];\n let zeroCounter = 0;\n const zeroes = [];\n for (i = 0; i < this.parsedAddress.length; i++) {\n const value = parseInt(this.parsedAddress[i], 16);\n if (value === 0) {\n zeroCounter++;\n }\n if (value !== 0 && zeroCounter > 0) {\n if (zeroCounter > 1) {\n zeroes.push([i - zeroCounter, i - 1]);\n }\n zeroCounter = 0;\n }\n }\n // Do we end with a string of zeroes?\n if (zeroCounter > 1) {\n zeroes.push([this.parsedAddress.length - zeroCounter, this.parsedAddress.length - 1]);\n }\n const zeroLengths = zeroes.map((n) => n[1] - n[0] + 1);\n if (zeroes.length > 0) {\n const index = zeroLengths.indexOf(Math.max(...zeroLengths));\n groups = compact(this.parsedAddress, zeroes[index]);\n }\n else {\n groups = this.parsedAddress;\n }\n for (i = 0; i < groups.length; i++) {\n if (groups[i] !== 'compact') {\n groups[i] = parseInt(groups[i], 16).toString(16);\n }\n }\n let correct = groups.join(':');\n correct = correct.replace(/^compact$/, '::');\n correct = correct.replace(/(^compact)|(compact$)/, ':');\n correct = correct.replace(/compact/, '');\n return correct;\n }\n /**\n * Return a zero-padded base-2 string representation of the address\n * @memberof Address6\n * @instance\n * @returns {String}\n * @example\n * var address = new Address6('2001:4860:4001:803::1011');\n * address.binaryZeroPad();\n * // '0010000000000001010010000110000001000000000000010000100000000011\n * // 0000000000000000000000000000000000000000000000000001000000010001'\n */\n binaryZeroPad() {\n return this.bigInt().toString(2).padStart(constants6.BITS, '0');\n }\n // TODO: Improve the semantics of this helper function\n parse4in6(address) {\n const groups = address.split(':');\n const lastGroup = groups.slice(-1)[0];\n const address4 = lastGroup.match(constants4.RE_ADDRESS);\n if (address4) {\n this.parsedAddress4 = address4[0];\n this.address4 = new ipv4_1.Address4(this.parsedAddress4);\n for (let i = 0; i < this.address4.groups; i++) {\n if (/^0[0-9]+/.test(this.address4.parsedAddress[i])) {\n // The prefix groups haven't been through the bad-character check\n // yet, so escape them before including in the error HTML.\n const highlighted = this.address4.parsedAddress.map(spanLeadingZeroes4).join('.');\n const prefix = groups.slice(0, -1).map(helpers.escapeHtml).join(':');\n const separator = groups.length > 1 ? ':' : '';\n throw new address_error_1.AddressError(\"IPv4 addresses can't have leading zeroes.\", `${prefix}${separator}${highlighted}`);\n }\n }\n this.v4 = true;\n groups[groups.length - 1] = this.address4.toGroup6();\n address = groups.join(':');\n }\n return address;\n }\n // TODO: Make private?\n parse(address) {\n address = this.parse4in6(address);\n const badCharacters = address.match(constants6.RE_BAD_CHARACTERS);\n if (badCharacters) {\n throw new address_error_1.AddressError(`Bad character${badCharacters.length > 1 ? 's' : ''} detected in address: ${badCharacters.join('')}`, address.replace(constants6.RE_BAD_CHARACTERS, '<span class=\"parse-error\">$1</span>'));\n }\n const badAddress = address.match(constants6.RE_BAD_ADDRESS);\n if (badAddress) {\n throw new address_error_1.AddressError(`Address failed regex: ${badAddress.join('')}`, address.replace(constants6.RE_BAD_ADDRESS, '<span class=\"parse-error\">$1</span>'));\n }\n let groups = [];\n const halves = address.split('::');\n if (halves.length === 2) {\n let first = halves[0].split(':');\n let last = halves[1].split(':');\n if (first.length === 1 && first[0] === '') {\n first = [];\n }\n if (last.length === 1 && last[0] === '') {\n last = [];\n }\n const remaining = this.groups - (first.length + last.length);\n if (!remaining) {\n throw new address_error_1.AddressError('Error parsing groups');\n }\n this.elidedGroups = remaining;\n this.elisionBegin = first.length;\n this.elisionEnd = first.length + this.elidedGroups;\n groups = groups.concat(first);\n for (let i = 0; i < remaining; i++) {\n groups.push('0');\n }\n groups = groups.concat(last);\n }\n else if (halves.length === 1) {\n groups = address.split(':');\n this.elidedGroups = 0;\n }\n else {\n throw new address_error_1.AddressError('Too many :: groups found');\n }\n groups = groups.map((group) => parseInt(group, 16).toString(16));\n if (groups.length !== this.groups) {\n throw new address_error_1.AddressError('Incorrect number of groups found');\n }\n return groups;\n }\n /**\n * Return the canonical form of the address\n * @memberof Address6\n * @instance\n * @returns {String}\n */\n canonicalForm() {\n return this.parsedAddress.map(paddedHex).join(':');\n }\n /**\n * Return the decimal form of the address\n * @memberof Address6\n * @instance\n * @returns {String}\n */\n decimal() {\n return this.parsedAddress.map((n) => parseInt(n, 16).toString(10).padStart(5, '0')).join(':');\n }\n /**\n * Return the address as a BigInt\n * @memberof Address6\n * @instance\n * @returns {bigint}\n */\n bigInt() {\n return BigInt(`0x${this.parsedAddress.map(paddedHex).join('')}`);\n }\n /**\n * Return the last two groups of this address as an IPv4 address string\n * @memberof Address6\n * @instance\n * @returns {Address4}\n * @example\n * var address = new Address6('2001:4860:4001::1825:bf11');\n * address.to4().correctForm(); // '24.37.191.17'\n */\n to4() {\n const binary = this.binaryZeroPad().split('');\n return ipv4_1.Address4.fromHex(BigInt(`0b${binary.slice(96, 128).join('')}`).toString(16));\n }\n /**\n * Return the v4-in-v6 form of the address\n * @memberof Address6\n * @instance\n * @returns {String}\n */\n to4in6() {\n const address4 = this.to4();\n const address6 = new Address6(this.parsedAddress.slice(0, 6).join(':'), 6);\n const correct = address6.correctForm();\n let infix = '';\n if (!/:$/.test(correct)) {\n infix = ':';\n }\n return correct + infix + address4.address;\n }\n /**\n * Return an object containing the Teredo properties of the address\n * @memberof Address6\n * @instance\n * @returns {Object}\n */\n inspectTeredo() {\n /*\n - Bits 0 to 31 are set to the Teredo prefix (normally 2001:0000::/32).\n - Bits 32 to 63 embed the primary IPv4 address of the Teredo server that\n is used.\n - Bits 64 to 79 can be used to define some flags. Currently only the\n higher order bit is used; it is set to 1 if the Teredo client is\n located behind a cone NAT, 0 otherwise. For Microsoft's Windows Vista\n and Windows Server 2008 implementations, more bits are used. In those\n implementations, the format for these 16 bits is \"CRAAAAUG AAAAAAAA\",\n where \"C\" remains the \"Cone\" flag. The \"R\" bit is reserved for future\n use. The \"U\" bit is for the Universal/Local flag (set to 0). The \"G\" bit\n is Individual/Group flag (set to 0). The A bits are set to a 12-bit\n randomly generated number chosen by the Teredo client to introduce\n additional protection for the Teredo node against IPv6-based scanning\n attacks.\n - Bits 80 to 95 contains the obfuscated UDP port number. This is the\n port number that is mapped by the NAT to the Teredo client with all\n bits inverted.\n - Bits 96 to 127 contains the obfuscated IPv4 address. This is the\n public IPv4 address of the NAT with all bits inverted.\n */\n const prefix = this.getBitsBase16(0, 32);\n const bitsForUdpPort = this.getBits(80, 96);\n // eslint-disable-next-line no-bitwise\n const udpPort = (bitsForUdpPort ^ BigInt('0xffff')).toString();\n const server4 = ipv4_1.Address4.fromHex(this.getBitsBase16(32, 64));\n const bitsForClient4 = this.getBits(96, 128);\n // eslint-disable-next-line no-bitwise\n const client4 = ipv4_1.Address4.fromHex((bitsForClient4 ^ BigInt('0xffffffff')).toString(16));\n const flagsBase2 = this.getBitsBase2(64, 80);\n const coneNat = (0, common_1.testBit)(flagsBase2, 15);\n const reserved = (0, common_1.testBit)(flagsBase2, 14);\n const groupIndividual = (0, common_1.testBit)(flagsBase2, 8);\n const universalLocal = (0, common_1.testBit)(flagsBase2, 9);\n const nonce = BigInt(`0b${flagsBase2.slice(2, 6) + flagsBase2.slice(8, 16)}`).toString(10);\n return {\n prefix: `${prefix.slice(0, 4)}:${prefix.slice(4, 8)}`,\n server4: server4.address,\n client4: client4.address,\n flags: flagsBase2,\n coneNat,\n microsoft: {\n reserved,\n universalLocal,\n groupIndividual,\n nonce,\n },\n udpPort,\n };\n }\n /**\n * Return an object containing the 6to4 properties of the address\n * @memberof Address6\n * @instance\n * @returns {Object}\n */\n inspect6to4() {\n /*\n - Bits 0 to 15 are set to the 6to4 prefix (2002::/16).\n - Bits 16 to 48 embed the IPv4 address of the 6to4 gateway that is used.\n */\n const prefix = this.getBitsBase16(0, 16);\n const gateway = ipv4_1.Address4.fromHex(this.getBitsBase16(16, 48));\n return {\n prefix: prefix.slice(0, 4),\n gateway: gateway.address,\n };\n }\n /**\n * Return a v6 6to4 address from a v6 v4inv6 address\n * @memberof Address6\n * @instance\n * @returns {Address6}\n */\n to6to4() {\n if (!this.is4()) {\n return null;\n }\n const addr6to4 = [\n '2002',\n this.getBitsBase16(96, 112),\n this.getBitsBase16(112, 128),\n '',\n '/16',\n ].join(':');\n return new Address6(addr6to4);\n }\n /**\n * Return a byte array\n * @memberof Address6\n * @instance\n * @returns {Array}\n */\n toByteArray() {\n const valueWithoutPadding = this.bigInt().toString(16);\n const leadingPad = '0'.repeat(valueWithoutPadding.length % 2);\n const value = `${leadingPad}${valueWithoutPadding}`;\n const bytes = [];\n for (let i = 0, length = value.length; i < length; i += 2) {\n bytes.push(parseInt(value.substring(i, i + 2), 16));\n }\n return bytes;\n }\n /**\n * Return an unsigned byte array\n * @memberof Address6\n * @instance\n * @returns {Array}\n */\n toUnsignedByteArray() {\n return this.toByteArray().map(unsignByte);\n }\n /**\n * Convert a byte array to an Address6 object\n * @memberof Address6\n * @static\n * @returns {Address6}\n */\n static fromByteArray(bytes) {\n return this.fromUnsignedByteArray(bytes.map(unsignByte));\n }\n /**\n * Convert an unsigned byte array to an Address6 object\n * @memberof Address6\n * @static\n * @returns {Address6}\n */\n static fromUnsignedByteArray(bytes) {\n const BYTE_MAX = BigInt('256');\n let result = BigInt('0');\n let multiplier = BigInt('1');\n for (let i = bytes.length - 1; i >= 0; i--) {\n result += multiplier * BigInt(bytes[i].toString(10));\n multiplier *= BYTE_MAX;\n }\n return Address6.fromBigInt(result);\n }\n /**\n * Returns true if the address is in the canonical form, false otherwise\n * @memberof Address6\n * @instance\n * @returns {boolean}\n */\n isCanonical() {\n return this.addressMinusSuffix === this.canonicalForm();\n }\n /**\n * Returns true if the address is a link local address, false otherwise\n * @memberof Address6\n * @instance\n * @returns {boolean}\n */\n isLinkLocal() {\n // Zeroes are required, i.e. we can't check isInSubnet with 'fe80::/10'\n if (this.getBitsBase2(0, 64) ===\n '1111111010000000000000000000000000000000000000000000000000000000') {\n return true;\n }\n return false;\n }\n /**\n * Returns true if the address is a multicast address, false otherwise\n * @memberof Address6\n * @instance\n * @returns {boolean}\n */\n isMulticast() {\n return this.getType() === 'Multicast';\n }\n /**\n * Returns true if the address is a v4-in-v6 address, false otherwise\n * @memberof Address6\n * @instance\n * @returns {boolean}\n */\n is4() {\n return this.v4;\n }\n /**\n * Returns true if the address is a Teredo address, false otherwise\n * @memberof Address6\n * @instance\n * @returns {boolean}\n */\n isTeredo() {\n return this.isInSubnet(new Address6('2001::/32'));\n }\n /**\n * Returns true if the address is a 6to4 address, false otherwise\n * @memberof Address6\n * @instance\n * @returns {boolean}\n */\n is6to4() {\n return this.isInSubnet(new Address6('2002::/16'));\n }\n /**\n * Returns true if the address is a loopback address, false otherwise\n * @memberof Address6\n * @instance\n * @returns {boolean}\n */\n isLoopback() {\n return this.getType() === 'Loopback';\n }\n // #endregion\n // #region HTML\n /**\n * @returns {String} the address in link form with a default port of 80\n */\n href(optionalPort) {\n if (optionalPort === undefined) {\n optionalPort = '';\n }\n else {\n optionalPort = `:${optionalPort}`;\n }\n return `http://[${this.correctForm()}]${optionalPort}/`;\n }\n /**\n * @returns {String} a link suitable for conveying the address via a URL hash\n */\n link(options) {\n if (!options) {\n options = {};\n }\n if (options.className === undefined) {\n options.className = '';\n }\n if (options.prefix === undefined) {\n options.prefix = '/#address=';\n }\n if (options.v4 === undefined) {\n options.v4 = false;\n }\n let formFunction = this.correctForm;\n if (options.v4) {\n formFunction = this.to4in6;\n }\n const form = formFunction.call(this);\n const safeHref = helpers.escapeHtml(`${options.prefix}${form}`);\n const safeForm = helpers.escapeHtml(form);\n if (options.className) {\n const safeClass = helpers.escapeHtml(options.className);\n return `<a href=\"${safeHref}\" class=\"${safeClass}\">${safeForm}</a>`;\n }\n return `<a href=\"${safeHref}\">${safeForm}</a>`;\n }\n /**\n * Groups an address\n * @returns {String}\n */\n group() {\n if (this.elidedGroups === 0) {\n // The simple case\n return helpers.simpleGroup(this.addressMinusSuffix).join(':');\n }\n assert(typeof this.elidedGroups === 'number');\n assert(typeof this.elisionBegin === 'number');\n // The elided case\n const output = [];\n const [left, right] = this.addressMinusSuffix.split('::');\n if (left.length) {\n output.push(...helpers.simpleGroup(left));\n }\n else {\n output.push('');\n }\n const classes = ['hover-group'];\n for (let i = this.elisionBegin; i < this.elisionBegin + this.elidedGroups; i++) {\n classes.push(`group-${i}`);\n }\n output.push(`<span class=\"${classes.join(' ')}\"></span>`);\n if (right.length) {\n output.push(...helpers.simpleGroup(right, this.elisionEnd));\n }\n else {\n output.push('');\n }\n if (this.is4()) {\n assert(this.address4 instanceof ipv4_1.Address4);\n output.pop();\n output.push(this.address4.groupForV6());\n }\n return output.join(':');\n }\n // #endregion\n // #region Regular expressions\n /**\n * Generate a regular expression string that can be used to find or validate\n * all variations of this address\n * @memberof Address6\n * @instance\n * @param {boolean} substringSearch\n * @returns {string}\n */\n regularExpressionString(substringSearch = false) {\n let output = [];\n // TODO: revisit why this is necessary\n const address6 = new Address6(this.correctForm());\n if (address6.elidedGroups === 0) {\n // The simple case\n output.push((0, regular_expressions_1.simpleRegularExpression)(address6.parsedAddress));\n }\n else if (address6.elidedGroups === constants6.GROUPS) {\n // A completely elided address\n output.push((0, regular_expressions_1.possibleElisions)(constants6.GROUPS));\n }\n else {\n // A partially elided address\n const halves = address6.address.split('::');\n if (halves[0].length) {\n output.push((0, regular_expressions_1.simpleRegularExpression)(halves[0].split(':')));\n }\n assert(typeof address6.elidedGroups === 'number');\n output.push((0, regular_expressions_1.possibleElisions)(address6.elidedGroups, halves[0].length !== 0, halves[1].length !== 0));\n if (halves[1].length) {\n output.push((0, regular_expressions_1.simpleRegularExpression)(halves[1].split(':')));\n }\n output = [output.join(':')];\n }\n if (!substringSearch) {\n output = [\n '(?=^|',\n regular_expressions_1.ADDRESS_BOUNDARY,\n '|[^\\\\w\\\\:])(',\n ...output,\n ')(?=[^\\\\w\\\\:]|',\n regular_expressions_1.ADDRESS_BOUNDARY,\n '|$)',\n ];\n }\n return output.join('');\n }\n /**\n * Generate a regular expression that can be used to find or validate all\n * variations of this address.\n * @memberof Address6\n * @instance\n * @param {boolean} substringSearch\n * @returns {RegExp}\n */\n regularExpression(substringSearch = false) {\n return new RegExp(this.regularExpressionString(substringSearch), 'i');\n }\n}\nexports.Address6 = Address6;\n//# sourceMappingURL=ipv6.js.map","\"use strict\";\nvar __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n var desc = Object.getOwnPropertyDescriptor(m, k);\n if (!desc || (\"get\" in desc ? !m.__esModule : desc.writable || desc.configurable)) {\n desc = { enumerable: true, get: function() { return m[k]; } };\n }\n Object.defineProperty(o, k2, desc);\n}) : (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n o[k2] = m[k];\n}));\nvar __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\n}) : function(o, v) {\n o[\"default\"] = v;\n});\nvar __importStar = (this && this.__importStar) || function (mod) {\n if (mod && mod.__esModule) return mod;\n var result = {};\n if (mod != null) for (var k in mod) if (k !== \"default\" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\n __setModuleDefault(result, mod);\n return result;\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.v6 = exports.AddressError = exports.Address6 = exports.Address4 = void 0;\nvar ipv4_1 = require(\"./ipv4\");\nObject.defineProperty(exports, \"Address4\", { enumerable: true, get: function () { return ipv4_1.Address4; } });\nvar ipv6_1 = require(\"./ipv6\");\nObject.defineProperty(exports, \"Address6\", { enumerable: true, get: function () { return ipv6_1.Address6; } });\nvar address_error_1 = require(\"./address-error\");\nObject.defineProperty(exports, \"AddressError\", { enumerable: true, get: function () { return address_error_1.AddressError; } });\nconst helpers = __importStar(require(\"./v6/helpers\"));\nexports.v6 = { helpers };\n//# sourceMappingURL=ip-address.js.map","// source/ip-key-generator.ts\nimport { isIPv6 } from \"node:net\";\nimport { Address6 } from \"ip-address\";\nfunction ipKeyGenerator(ip, ipv6Subnet = 56) {\n if (isIPv6(ip)) {\n const address = new Address6(ip);\n if (address.is4()) return address.to4().correctForm();\n if (ipv6Subnet) {\n const subnet = new Address6(`${ip}/${ipv6Subnet}`);\n return subnet.networkForm();\n }\n }\n return ip;\n}\n\n// source/memory-store.ts\nvar MemoryStore = class {\n constructor(validations2) {\n this.validations = validations2;\n /**\n * These two maps store usage (requests) and reset time by key (for example, IP\n * addresses or API keys).\n *\n * They are split into two to avoid having to iterate through the entire set to\n * determine which ones need reset. Instead, `Client`s are moved from `previous`\n * to `current` as they hit the endpoint. Once `windowMs` has elapsed, all clients\n * left in `previous`, i.e., those that have not made any recent requests, are\n * known to be expired and can be deleted in bulk.\n */\n this.previous = /* @__PURE__ */ new Map();\n this.current = /* @__PURE__ */ new Map();\n /**\n * Confirmation that the keys incremented in once instance of MemoryStore\n * cannot affect other instances.\n */\n this.localKeys = true;\n }\n /**\n * Method that initializes the store.\n *\n * @param options {Options} - The options used to setup the middleware.\n */\n init(options) {\n this.windowMs = options.windowMs;\n this.validations?.windowMs(this.windowMs);\n if (this.interval) clearInterval(this.interval);\n this.interval = setInterval(() => {\n this.clearExpired();\n }, this.windowMs);\n this.interval.unref?.();\n }\n /**\n * Method to fetch a client's hit count and reset time.\n *\n * @param key {string} - The identifier for a client.\n *\n * @returns {ClientRateLimitInfo | undefined} - The number of hits and reset time for that client.\n *\n * @public\n */\n async get(key) {\n return this.current.get(key) ?? this.previous.get(key);\n }\n /**\n * Method to increment a client's hit counter.\n *\n * @param key {string} - The identifier for a client.\n *\n * @returns {ClientRateLimitInfo} - The number of hits and reset time for that client.\n *\n * @public\n */\n async increment(key) {\n const client = this.getClient(key);\n const now = Date.now();\n if (client.resetTime.getTime() <= now) {\n this.resetClient(client, now);\n }\n client.totalHits++;\n return client;\n }\n /**\n * Method to decrement a client's hit counter.\n *\n * @param key {string} - The identifier for a client.\n *\n * @public\n */\n async decrement(key) {\n const client = this.getClient(key);\n if (client.totalHits > 0) client.totalHits--;\n }\n /**\n * Method to reset a client's hit counter.\n *\n * @param key {string} - The identifier for a client.\n *\n * @public\n */\n async resetKey(key) {\n this.current.delete(key);\n this.previous.delete(key);\n }\n /**\n * Method to reset everyone's hit counter.\n *\n * @public\n */\n async resetAll() {\n this.current.clear();\n this.previous.clear();\n }\n /**\n * Method to stop the timer (if currently running) and prevent any memory\n * leaks.\n *\n * @public\n */\n shutdown() {\n clearInterval(this.interval);\n void this.resetAll();\n }\n /**\n * Recycles a client by setting its hit count to zero, and reset time to\n * `windowMs` milliseconds from now.\n *\n * NOT to be confused with `#resetKey()`, which removes a client from both the\n * `current` and `previous` maps.\n *\n * @param client {Client} - The client to recycle.\n * @param now {number} - The current time, to which the `windowMs` is added to get the `resetTime` for the client.\n *\n * @return {Client} - The modified client that was passed in, to allow for chaining.\n */\n resetClient(client, now = Date.now()) {\n client.totalHits = 0;\n client.resetTime.setTime(now + this.windowMs);\n return client;\n }\n /**\n * Retrieves or creates a client, given a key. Also ensures that the client being\n * returned is in the `current` map.\n *\n * @param key {string} - The key under which the client is (or is to be) stored.\n *\n * @returns {Client} - The requested client.\n */\n getClient(key) {\n if (this.current.has(key)) return this.current.get(key);\n let client;\n if (this.previous.has(key)) {\n client = this.previous.get(key);\n this.previous.delete(key);\n } else {\n client = { totalHits: 0, resetTime: /* @__PURE__ */ new Date() };\n this.resetClient(client);\n }\n this.current.set(key, client);\n return client;\n }\n /**\n * Move current clients to previous, create a new map for current.\n *\n * This function is called every `windowMs`.\n */\n clearExpired() {\n this.previous = this.current;\n this.current = /* @__PURE__ */ new Map();\n }\n};\n\n// source/rate-limit.ts\nimport { isIPv6 as isIPv62 } from \"node:net\";\n\n// source/console-logger.ts\nvar ConsoleLogger = {\n warn(...args) {\n console.warn(...args.reverse());\n },\n error(...args) {\n console.error(...args.reverse());\n }\n};\n\n// source/headers.ts\nimport { Buffer } from \"node:buffer\";\nimport { createHash } from \"node:crypto\";\nvar SUPPORTED_DRAFT_VERSIONS = [\n \"draft-6\",\n \"draft-7\",\n \"draft-8\"\n];\nvar getResetSeconds = (windowMs, resetTime) => {\n let resetSeconds;\n if (resetTime) {\n const deltaSeconds = Math.ceil((resetTime.getTime() - Date.now()) / 1e3);\n resetSeconds = Math.max(0, deltaSeconds);\n } else {\n resetSeconds = Math.ceil(windowMs / 1e3);\n }\n return resetSeconds;\n};\nvar getPartitionKey = (key) => {\n const hash = createHash(\"sha256\");\n hash.update(key);\n const partitionKey = hash.digest(\"hex\").slice(0, 12);\n return Buffer.from(partitionKey).toString(\"base64\");\n};\nvar setLegacyHeaders = (response, info) => {\n if (response.headersSent) return;\n response.setHeader(\"X-RateLimit-Limit\", info.limit.toString());\n response.setHeader(\"X-RateLimit-Remaining\", info.remaining.toString());\n if (info.resetTime instanceof Date) {\n response.setHeader(\"Date\", (/* @__PURE__ */ new Date()).toUTCString());\n response.setHeader(\n \"X-RateLimit-Reset\",\n Math.ceil(info.resetTime.getTime() / 1e3).toString()\n );\n }\n};\nvar setDraft6Headers = (response, info, windowMs) => {\n if (response.headersSent) return;\n const windowSeconds = Math.ceil(windowMs / 1e3);\n const resetSeconds = getResetSeconds(windowMs, info.resetTime);\n response.setHeader(\"RateLimit-Policy\", `${info.limit};w=${windowSeconds}`);\n response.setHeader(\"RateLimit-Limit\", info.limit.toString());\n response.setHeader(\"RateLimit-Remaining\", info.remaining.toString());\n if (typeof resetSeconds === \"number\")\n response.setHeader(\"RateLimit-Reset\", resetSeconds.toString());\n};\nvar setDraft7Headers = (response, info, windowMs) => {\n if (response.headersSent) return;\n const windowSeconds = Math.ceil(windowMs / 1e3);\n const resetSeconds = getResetSeconds(windowMs, info.resetTime);\n response.setHeader(\"RateLimit-Policy\", `${info.limit};w=${windowSeconds}`);\n response.setHeader(\n \"RateLimit\",\n `limit=${info.limit}, remaining=${info.remaining}, reset=${resetSeconds}`\n );\n};\nvar setDraft8Headers = (response, info, windowMs, name, key) => {\n if (response.headersSent) return;\n const windowSeconds = Math.ceil(windowMs / 1e3);\n const resetSeconds = getResetSeconds(windowMs, info.resetTime);\n const partitionKey = getPartitionKey(key);\n const header = `r=${info.remaining}; t=${resetSeconds}`;\n const policy = `q=${info.limit}; w=${windowSeconds}; pk=:${partitionKey}:`;\n response.append(\"RateLimit\", `\"${name}\"; ${header}`);\n response.append(\"RateLimit-Policy\", `\"${name}\"; ${policy}`);\n};\nvar setRetryAfterHeader = (response, info, windowMs) => {\n if (response.headersSent) return;\n const resetSeconds = getResetSeconds(windowMs, info.resetTime);\n response.setHeader(\"Retry-After\", resetSeconds.toString());\n};\n\n// source/utils.ts\nvar omitUndefinedProperties = (passedOptions) => {\n const omittedOptions = {};\n for (const k of Object.keys(passedOptions)) {\n const key = k;\n if (passedOptions[key] !== void 0) {\n omittedOptions[key] = passedOptions[key];\n }\n }\n return omittedOptions;\n};\n\n// source/validations.ts\nimport { isIP } from \"node:net\";\nvar ValidationError = class extends Error {\n /**\n * The code must be a string, in snake case and all capital, that starts with\n * the substring `ERR_ERL_`.\n *\n * The message must be a string, starting with an uppercase character,\n * describing the issue in detail.\n */\n constructor(code, message) {\n const url = `https://express-rate-limit.github.io/${code}/`;\n super(`${message} See ${url} for more information.`);\n this.name = this.constructor.name;\n this.code = code;\n this.help = url;\n }\n};\nvar ChangeWarning = class extends ValidationError {\n};\nvar usedStores = /* @__PURE__ */ new Set();\nvar singleCountKeys = /* @__PURE__ */ new WeakMap();\nvar validations = {\n enabled: {\n default: true\n },\n // Should be EnabledValidations type, but that's a circular reference\n disable() {\n for (const k of Object.keys(this.enabled)) this.enabled[k] = false;\n },\n /**\n * Checks whether the IP address is valid, and that it does not have a port\n * number in it.\n *\n * See https://github.com/express-rate-limit/express-rate-limit/wiki/Error-Codes#err_erl_invalid_ip_address.\n *\n * @param ip {string | undefined} - The IP address provided by Express as request.ip.\n *\n * @returns {void}\n */\n ip(ip) {\n if (ip === void 0) {\n throw new ValidationError(\n \"ERR_ERL_UNDEFINED_IP_ADDRESS\",\n `An undefined 'request.ip' was detected. This might indicate a misconfiguration or the connection being destroyed prematurely.`\n );\n }\n if (!isIP(ip)) {\n throw new ValidationError(\n \"ERR_ERL_INVALID_IP_ADDRESS\",\n `An invalid 'request.ip' (${ip}) was detected. Consider passing a custom 'keyGenerator' function to the rate limiter.`\n );\n }\n },\n /**\n * Makes sure the trust proxy setting is not set to `true`.\n *\n * See https://github.com/express-rate-limit/express-rate-limit/wiki/Error-Codes#err_erl_permissive_trust_proxy.\n *\n * @param request {Request} - The Express request object.\n *\n * @returns {void}\n */\n trustProxy(request) {\n if (request.app.get(\"trust proxy\") === true) {\n throw new ValidationError(\n \"ERR_ERL_PERMISSIVE_TRUST_PROXY\",\n `The Express 'trust proxy' setting is true, which allows anyone to trivially bypass IP-based rate limiting.`\n );\n }\n },\n /**\n * Makes sure the trust proxy setting is set in case the `X-Forwarded-For`\n * header is present.\n *\n * See https://github.com/express-rate-limit/express-rate-limit/wiki/Error-Codes#err_erl_unset_trust_proxy.\n *\n * @param request {Request} - The Express request object.\n *\n * @returns {void}\n */\n xForwardedForHeader(request) {\n if (request.headers[\"x-forwarded-for\"] && request.app.get(\"trust proxy\") === false) {\n throw new ValidationError(\n \"ERR_ERL_UNEXPECTED_X_FORWARDED_FOR\",\n `The 'X-Forwarded-For' header is set but the Express 'trust proxy' setting is false (default). This could indicate a misconfiguration which would prevent express-rate-limit from accurately identifying users.`\n );\n }\n },\n /**\n * Alert the user if the Forwarded header is set (standardized version of X-Forwarded-For - not supported by express as of version 5.1.0)\n *\n * @param request {Request} - The Express request object.\n *\n * @returns {void}\n */\n forwardedHeader(request) {\n if (request.headers.forwarded && request.ip === request.socket?.remoteAddress) {\n throw new ValidationError(\n \"ERR_ERL_FORWARDED_HEADER\",\n `The 'Forwarded' header (standardized X-Forwarded-For) is set but currently being ignored. Add a custom keyGenerator to use a value from this header.`\n );\n }\n },\n /**\n * Ensures totalHits value from store is a positive integer.\n *\n * @param hits {any} - The `totalHits` returned by the store.\n */\n positiveHits(hits) {\n if (typeof hits !== \"number\" || hits < 1 || hits !== Math.round(hits)) {\n throw new ValidationError(\n \"ERR_ERL_INVALID_HITS\",\n `The totalHits value returned from the store must be a positive integer, got ${hits}`\n );\n }\n },\n /**\n * Ensures a single store instance is not used with multiple express-rate-limit instances\n */\n unsharedStore(store) {\n if (usedStores.has(store)) {\n const maybeUniquePrefix = store?.localKeys ? \"\" : \" (with a unique prefix)\";\n throw new ValidationError(\n \"ERR_ERL_STORE_REUSE\",\n `A Store instance must not be shared across multiple rate limiters. Create a new instance of ${store.constructor.name}${maybeUniquePrefix} for each limiter instead.`\n );\n }\n usedStores.add(store);\n },\n /**\n * Ensures a given key is incremented only once per request.\n *\n * @param request {Request} - The Express request object.\n * @param store {Store} - The store class.\n * @param key {string} - The key used to store the client's hit count.\n *\n * @returns {void}\n */\n singleCount(request, store, key) {\n let storeKeys = singleCountKeys.get(request);\n if (!storeKeys) {\n storeKeys = /* @__PURE__ */ new Map();\n singleCountKeys.set(request, storeKeys);\n }\n const storeKey = store.localKeys ? store : store.constructor.name;\n let keys = storeKeys.get(storeKey);\n if (!keys) {\n keys = [];\n storeKeys.set(storeKey, keys);\n }\n const prefixedKey = `${store.prefix ?? \"\"}${key}`;\n if (keys.includes(prefixedKey)) {\n throw new ValidationError(\n \"ERR_ERL_DOUBLE_COUNT\",\n `The hit count for ${key} was incremented more than once for a single request.`\n );\n }\n keys.push(prefixedKey);\n },\n /**\n * Warns the user that the behaviour for `max: 0` / `limit: 0` is\n * changing in the next major release.\n *\n * @param limit {number} - The maximum number of hits per client.\n *\n * @returns {void}\n */\n limit(limit) {\n if (limit === 0) {\n throw new ChangeWarning(\n \"WRN_ERL_MAX_ZERO\",\n \"Setting limit or max to 0 disables rate limiting in express-rate-limit v6 and older, but will cause all requests to be blocked in v7\"\n );\n }\n },\n /**\n * Warns the user that the `draft_polli_ratelimit_headers` option is deprecated\n * and will be removed in the next major release.\n *\n * @param draft_polli_ratelimit_headers {any | undefined} - The now-deprecated setting that was used to enable standard headers.\n *\n * @returns {void}\n */\n draftPolliHeaders(draft_polli_ratelimit_headers) {\n if (draft_polli_ratelimit_headers) {\n throw new ChangeWarning(\n \"WRN_ERL_DEPRECATED_DRAFT_POLLI_HEADERS\",\n `The draft_polli_ratelimit_headers configuration option is deprecated and has been removed in express-rate-limit v7, please set standardHeaders: 'draft-6' instead.`\n );\n }\n },\n /**\n * Warns the user that the `onLimitReached` option is deprecated and\n * will be removed in the next major release.\n *\n * @param onLimitReached {any | undefined} - The maximum number of hits per client.\n *\n * @returns {void}\n */\n onLimitReached(onLimitReached) {\n if (onLimitReached) {\n throw new ChangeWarning(\n \"WRN_ERL_DEPRECATED_ON_LIMIT_REACHED\",\n \"The onLimitReached configuration option is deprecated and has been removed in express-rate-limit v7.\"\n );\n }\n },\n /**\n * Warns the user when an invalid/unsupported version of the draft spec is passed.\n *\n * @param version {any | undefined} - The version passed by the user.\n *\n * @returns {void}\n */\n headersDraftVersion(version) {\n if (typeof version !== \"string\" || // @ts-expect-error This is fine. If version is not in the array, it will just return false.\n !SUPPORTED_DRAFT_VERSIONS.includes(version)) {\n const versionString = SUPPORTED_DRAFT_VERSIONS.join(\", \");\n throw new ValidationError(\n \"ERR_ERL_HEADERS_UNSUPPORTED_DRAFT_VERSION\",\n `standardHeaders: only the following versions of the IETF draft specification are supported: ${versionString}.`\n );\n }\n },\n /**\n * Warns the user when the selected headers option requires a reset time but\n * the store does not provide one.\n *\n * @param resetTime {Date | undefined} - The timestamp when the client's hit count will be reset.\n *\n * @returns {void}\n */\n headersResetTime(resetTime) {\n if (!resetTime) {\n throw new ValidationError(\n \"ERR_ERL_HEADERS_NO_RESET\",\n `standardHeaders: 'draft-7' requires a 'resetTime', but the store did not provide one. The 'windowMs' value will be used instead, which may cause clients to wait longer than necessary.`\n );\n }\n },\n knownOptions(passedOptions) {\n if (!passedOptions) return;\n const optionsMap = {\n windowMs: true,\n limit: true,\n message: true,\n statusCode: true,\n legacyHeaders: true,\n standardHeaders: true,\n identifier: true,\n requestPropertyName: true,\n skipFailedRequests: true,\n skipSuccessfulRequests: true,\n keyGenerator: true,\n ipv6Subnet: true,\n handler: true,\n skip: true,\n requestWasSuccessful: true,\n store: true,\n validate: true,\n headers: true,\n max: true,\n passOnStoreError: true,\n logger: true\n };\n const validOptions = Object.keys(optionsMap).concat(\n \"draft_polli_ratelimit_headers\",\n // not a valid option anymore, but we have a more specific check for this one, so don't warn for it here\n // from express-slow-down - https://github.com/express-rate-limit/express-slow-down/blob/main/source/types.ts#L65\n \"delayAfter\",\n \"delayMs\",\n \"maxDelayMs\"\n );\n for (const key of Object.keys(passedOptions)) {\n if (!validOptions.includes(key)) {\n throw new ValidationError(\n \"ERR_ERL_UNKNOWN_OPTION\",\n `Unexpected configuration option: ${key}`\n // todo: suggest a valid option with a short levenstein distance?\n );\n }\n }\n },\n /**\n * Checks the options.validate setting to ensure that only recognized\n * validations are enabled or disabled.\n *\n * If any unrecognized values are found, an error is logged that\n * includes the list of supported validations.\n */\n validationsConfig() {\n const supportedValidations = Object.keys(this).filter(\n (k) => ![\"enabled\", \"disable\"].includes(k)\n );\n supportedValidations.push(\"default\");\n for (const key of Object.keys(this.enabled)) {\n if (!supportedValidations.includes(key)) {\n throw new ValidationError(\n \"ERR_ERL_UNKNOWN_VALIDATION\",\n `options.validate.${key} is not recognized. Supported validate options are: ${supportedValidations.join(\n \", \"\n )}.`\n );\n }\n }\n },\n /**\n * Checks to see if the instance was created inside of a request handler,\n * which would prevent it from working correctly, with the default memory\n * store (or any other store with localKeys.)\n */\n creationStack(store) {\n const { stack } = new Error(\n \"express-rate-limit validation check (set options.validate.creationStack=false to disable)\"\n );\n if (stack?.includes(\"Layer.handle [as handle_request]\") || // express v4\n stack?.includes(\"Layer.handleRequest\")) {\n if (!store.localKeys) {\n throw new ValidationError(\n \"ERR_ERL_CREATED_IN_REQUEST_HANDLER\",\n \"express-rate-limit instance should *usually* be created at app initialization, not when responding to a request.\"\n );\n }\n throw new ValidationError(\n \"ERR_ERL_CREATED_IN_REQUEST_HANDLER\",\n \"express-rate-limit instance should be created at app initialization, not when responding to a request.\"\n );\n }\n },\n ipv6Subnet(ipv6Subnet) {\n if (ipv6Subnet === false) {\n return;\n }\n if (!Number.isInteger(ipv6Subnet) || ipv6Subnet < 32 || ipv6Subnet > 64) {\n throw new ValidationError(\n \"ERR_ERL_IPV6_SUBNET\",\n `Unexpected ipv6Subnet value: ${ipv6Subnet}. Expected an integer between 32 and 64 (usually 48-64).`\n );\n }\n },\n ipv6SubnetOrKeyGenerator(options) {\n if (options.ipv6Subnet !== void 0 && options.keyGenerator) {\n throw new ValidationError(\n \"ERR_ERL_IPV6SUBNET_OR_KEYGENERATOR\",\n `Incompatible options: the 'ipv6Subnet' option is ignored when a custom 'keyGenerator' function is also set.`\n );\n }\n },\n keyGeneratorIpFallback(keyGenerator) {\n if (!keyGenerator) {\n return;\n }\n const src = keyGenerator.toString();\n if ((src.includes(\"req.ip\") || src.includes(\"request.ip\")) && !src.includes(\"ipKeyGenerator\")) {\n throw new ValidationError(\n \"ERR_ERL_KEY_GEN_IPV6\",\n \"Custom keyGenerator appears to use request IP without calling the ipKeyGenerator helper function for IPv6 addresses. This could allow IPv6 users to bypass limits.\"\n );\n }\n },\n /**\n * Checks to see if the window duration is greater than 2^32 - 1. This is only\n * called by the default MemoryStore, since it uses Node's setInterval method.\n *\n * See https://nodejs.org/api/timers.html#setintervalcallback-delay-args.\n */\n windowMs(windowMs) {\n const SET_TIMEOUT_MAX = 2 ** 31 - 1;\n if (typeof windowMs !== \"number\" || Number.isNaN(windowMs) || windowMs < 1 || windowMs > SET_TIMEOUT_MAX) {\n throw new ValidationError(\n \"ERR_ERL_WINDOW_MS\",\n `Invalid windowMs value: ${windowMs}${typeof windowMs !== \"number\" ? ` (${typeof windowMs})` : \"\"}, must be a number between 1 and ${SET_TIMEOUT_MAX} when using the default MemoryStore`\n );\n }\n }\n};\nfunction validateLogger(logger) {\n if (typeof logger !== \"object\" || typeof logger.error !== \"function\" || typeof logger.warn !== \"function\") {\n throw new TypeError(\n \"Provided logger does not implement the Logger interface\"\n );\n }\n}\nvar getValidations = (_enabled, logger) => {\n validateLogger(logger);\n let enabled;\n if (typeof _enabled === \"boolean\") {\n enabled = {\n default: _enabled\n };\n } else {\n enabled = {\n default: true,\n ..._enabled\n };\n }\n const wrappedValidations = { enabled };\n for (const [name, validation] of Object.entries(validations)) {\n if (typeof validation === \"function\")\n wrappedValidations[name] = (...args) => {\n if (!(enabled[name] ?? enabled.default)) {\n return;\n }\n try {\n ;\n validation.apply(\n wrappedValidations,\n args\n );\n } catch (error) {\n if (error instanceof ChangeWarning) logger.warn(error);\n else logger.error(error);\n }\n };\n }\n return wrappedValidations;\n};\n\n// source/rate-limit.ts\nvar isLegacyStore = (store) => (\n // Check that `incr` exists but `increment` does not - store authors might want\n // to keep both around for backwards compatibility.\n typeof store.incr === \"function\" && typeof store.increment !== \"function\"\n);\nvar promisifyStore = (passedStore) => {\n if (!isLegacyStore(passedStore)) {\n return passedStore;\n }\n const legacyStore = passedStore;\n class PromisifiedStore {\n async increment(key) {\n return new Promise((resolve, reject) => {\n legacyStore.incr(\n key,\n (error, totalHits, resetTime) => {\n if (error) reject(error);\n resolve({ totalHits, resetTime });\n }\n );\n });\n }\n async decrement(key) {\n return legacyStore.decrement(key);\n }\n async resetKey(key) {\n return legacyStore.resetKey(key);\n }\n /* istanbul ignore next */\n async resetAll() {\n if (typeof legacyStore.resetAll === \"function\")\n return legacyStore.resetAll();\n }\n }\n return new PromisifiedStore();\n};\nvar getOptionsFromConfig = (config) => {\n const { validations: validations2, ...directlyPassableEntries } = config;\n return {\n ...directlyPassableEntries,\n validate: validations2.enabled\n };\n};\nvar parseOptions = (passedOptions) => {\n const notUndefinedOptions = omitUndefinedProperties(passedOptions);\n const logger = passedOptions.logger ?? ConsoleLogger;\n const validations2 = getValidations(\n notUndefinedOptions?.validate ?? true,\n logger\n );\n validations2.validationsConfig();\n validations2.knownOptions(passedOptions);\n validations2.draftPolliHeaders(\n // @ts-expect-error see the note above.\n notUndefinedOptions.draft_polli_ratelimit_headers\n );\n validations2.onLimitReached(notUndefinedOptions.onLimitReached);\n if (notUndefinedOptions.ipv6Subnet !== void 0 && typeof notUndefinedOptions.ipv6Subnet !== \"function\") {\n validations2.ipv6Subnet(notUndefinedOptions.ipv6Subnet);\n }\n validations2.keyGeneratorIpFallback(notUndefinedOptions.keyGenerator);\n validations2.ipv6SubnetOrKeyGenerator(notUndefinedOptions);\n let standardHeaders = notUndefinedOptions.standardHeaders ?? false;\n if (standardHeaders === true) standardHeaders = \"draft-6\";\n const config = {\n windowMs: 60 * 1e3,\n limit: passedOptions.max ?? 5,\n // `max` is deprecated, but support it anyways.\n message: \"Too many requests, please try again later.\",\n statusCode: 429,\n legacyHeaders: passedOptions.headers ?? true,\n identifier(request, _response) {\n let duration = \"\";\n const property = config.requestPropertyName;\n const { limit } = request[property];\n const seconds = config.windowMs / 1e3;\n const minutes = config.windowMs / (1e3 * 60);\n const hours = config.windowMs / (1e3 * 60 * 60);\n const days = config.windowMs / (1e3 * 60 * 60 * 24);\n if (seconds < 60) duration = `${seconds}sec`;\n else if (minutes < 60) duration = `${minutes}min`;\n else if (hours < 24) duration = `${hours}hr${hours > 1 ? \"s\" : \"\"}`;\n else duration = `${days}day${days > 1 ? \"s\" : \"\"}`;\n return `${limit}-in-${duration}`;\n },\n requestPropertyName: \"rateLimit\",\n skipFailedRequests: false,\n skipSuccessfulRequests: false,\n requestWasSuccessful: (_request, response) => response.statusCode < 400,\n skip: (_request, _response) => false,\n async keyGenerator(request, response) {\n validations2.ip(request.ip);\n validations2.trustProxy(request);\n validations2.xForwardedForHeader(request);\n validations2.forwardedHeader(request);\n const ip = request.ip;\n let subnet = 56;\n if (isIPv62(ip)) {\n subnet = typeof config.ipv6Subnet === \"function\" ? await config.ipv6Subnet(request, response) : config.ipv6Subnet;\n if (typeof config.ipv6Subnet === \"function\")\n validations2.ipv6Subnet(subnet);\n }\n return ipKeyGenerator(ip, subnet);\n },\n ipv6Subnet: 56,\n async handler(request, response, _next, _optionsUsed) {\n response.status(config.statusCode);\n const message = typeof config.message === \"function\" ? await config.message(\n request,\n response\n ) : config.message;\n if (!response.writableEnded) response.send(message);\n },\n passOnStoreError: false,\n // Allow the default options to be overridden by the passed options.\n ...notUndefinedOptions,\n // `standardHeaders` is resolved into a draft version above, use that.\n standardHeaders,\n // Note that this field is declared after the user's options are spread in,\n // so that this field doesn't get overridden with an un-promisified store!\n store: promisifyStore(\n notUndefinedOptions.store ?? new MemoryStore(validations2)\n ),\n // Print an error to the console if a few known misconfigurations are detected.\n validations: validations2,\n logger\n };\n if (typeof config.store.increment !== \"function\" || typeof config.store.decrement !== \"function\" || typeof config.store.resetKey !== \"function\" || config.store.resetAll !== void 0 && typeof config.store.resetAll !== \"function\" || config.store.init !== void 0 && typeof config.store.init !== \"function\") {\n throw new TypeError(\n \"An invalid store was passed. Please ensure that the store is a class that implements the `Store` interface.\"\n );\n }\n return config;\n};\nvar handleAsyncErrors = (fn) => async (request, response, next) => {\n try {\n await Promise.resolve(fn(request, response, next)).catch(next);\n } catch (error) {\n next(error);\n }\n};\nvar rateLimit = (passedOptions) => {\n const config = parseOptions(passedOptions ?? {});\n const options = getOptionsFromConfig(config);\n config.validations.creationStack(config.store);\n config.validations.unsharedStore(config.store);\n if (typeof config.store.init === \"function\") {\n try {\n const storeInit = config.store.init(options);\n if (storeInit instanceof Promise) {\n storeInit.catch(\n (error) => config.logger.error(\n error,\n \"express-rate-limit: async error during store initialization.\"\n )\n );\n }\n } catch (error) {\n config.logger.error(\n error,\n \"express-rate-limit: error during store initialization.\"\n );\n }\n }\n const middleware = handleAsyncErrors(\n async (request, response, next) => {\n const closePromise = config.skipFailedRequests && new Promise((resolve) => response.once(\"close\", resolve));\n const finishPromise = (config.skipFailedRequests || config.skipSuccessfulRequests) && new Promise((resolve) => response.once(\"finish\", resolve));\n const errorPromise = config.skipFailedRequests && new Promise((resolve) => response.once(\"error\", resolve));\n const skip = await config.skip(request, response);\n if (skip) {\n next();\n return;\n }\n const augmentedRequest = request;\n const key = await config.keyGenerator(request, response);\n let totalHits = 0;\n let resetTime;\n try {\n const incrementResult = await config.store.increment(key);\n totalHits = incrementResult.totalHits;\n resetTime = incrementResult.resetTime;\n } catch (error) {\n if (config.passOnStoreError) {\n config.logger.error(\n error,\n \"express-rate-limit: error from store, allowing request without rate-limiting.\"\n );\n next();\n return;\n }\n throw error;\n }\n config.validations.positiveHits(totalHits);\n config.validations.singleCount(request, config.store, key);\n const retrieveLimit = typeof config.limit === \"function\" ? config.limit(request, response) : config.limit;\n const limit = await retrieveLimit;\n config.validations.limit(limit);\n const info = {\n limit,\n used: totalHits,\n remaining: Math.max(limit - totalHits, 0),\n resetTime,\n key\n };\n Object.defineProperty(info, \"current\", {\n configurable: false,\n enumerable: false,\n value: totalHits\n });\n augmentedRequest[config.requestPropertyName] = info;\n if (config.legacyHeaders && !response.headersSent) {\n setLegacyHeaders(response, info);\n }\n if (config.standardHeaders && !response.headersSent) {\n switch (config.standardHeaders) {\n case \"draft-6\": {\n setDraft6Headers(response, info, config.windowMs);\n break;\n }\n case \"draft-7\": {\n config.validations.headersResetTime(info.resetTime);\n setDraft7Headers(response, info, config.windowMs);\n break;\n }\n case \"draft-8\": {\n const retrieveName = typeof config.identifier === \"function\" ? config.identifier(request, response) : config.identifier;\n const name = await retrieveName;\n config.validations.headersResetTime(info.resetTime);\n setDraft8Headers(response, info, config.windowMs, name, key);\n break;\n }\n default: {\n config.validations.headersDraftVersion(config.standardHeaders);\n break;\n }\n }\n }\n if (config.skipFailedRequests || config.skipSuccessfulRequests) {\n let decremented = false;\n const decrementKey = async () => {\n if (!decremented) {\n await config.store.decrement(key);\n decremented = true;\n }\n };\n if (config.skipFailedRequests) {\n if (finishPromise) {\n void finishPromise.then(async () => {\n if (!await config.requestWasSuccessful(request, response))\n await decrementKey();\n });\n }\n if (closePromise) {\n void closePromise.then(async () => {\n if (!response.writableEnded) await decrementKey();\n });\n }\n if (errorPromise) {\n void errorPromise.then(async () => {\n await decrementKey();\n });\n }\n }\n if (config.skipSuccessfulRequests) {\n if (finishPromise) {\n void finishPromise.then(async () => {\n if (await config.requestWasSuccessful(request, response))\n await decrementKey();\n });\n }\n }\n }\n config.validations.disable();\n if (totalHits > limit) {\n if (config.legacyHeaders || config.standardHeaders) {\n setRetryAfterHeader(response, info, config.windowMs);\n }\n config.handler(request, response, next, options);\n return;\n }\n next();\n }\n );\n const getThrowFn = () => {\n throw new Error(\"The current store does not support the get/getKey method\");\n };\n middleware.resetKey = config.store.resetKey.bind(config.store);\n middleware.getKey = typeof config.store.get === \"function\" ? config.store.get.bind(config.store) : getThrowFn;\n return middleware;\n};\nvar rate_limit_default = rateLimit;\nexport {\n MemoryStore,\n rate_limit_default as default,\n ipKeyGenerator,\n rate_limit_default as rateLimit\n};\n","/**\n * @codemem/mcp — privacy-safe OAuth audit events.\n *\n * Phase 1 single-user remote MCP needs operator-visible security events\n * (registration, authorize, OIDC callback, token issuance, revocation, bearer\n * verification) without ever logging bearer tokens, authorization codes,\n * client secrets, OIDC ID tokens, or private memory contents.\n */\n\nexport type OAuthAuditKind =\n\t| \"registration\"\n\t| \"authorize\"\n\t| \"oidc_callback\"\n\t| \"token\"\n\t| \"refresh\"\n\t| \"rotation\"\n\t| \"revocation\"\n\t| \"bearer\";\n\nexport type OAuthAuditOutcome = \"success\" | \"denied\" | \"error\";\n\nexport type BearerDenyReason =\n\t| \"missing_authorization_header\"\n\t| \"malformed_authorization_header\"\n\t| \"unknown_token\"\n\t| \"expired_token\"\n\t| \"revoked_token\";\n\nexport interface OAuthAuditEventBase {\n\ttimestamp: string;\n\toutcome: OAuthAuditOutcome;\n\treason?: string;\n\tclientId?: string;\n\tremoteAddress?: string;\n}\n\nexport type OAuthAuditEvent = OAuthAuditEventBase & { kind: OAuthAuditKind };\n\nexport type OAuthAuditEmitter = (event: OAuthAuditEvent) => void;\n\n// Canonicalized denylist — keys are compared after lowercasing and stripping\n// non-alphanumeric separators, so `access_token`, `accessToken`, `ACCESS-TOKEN`\n// and `access token` all reduce to `accesstoken` and are blocked uniformly.\n// This codebase commonly uses camelCase identifiers, so a snake_case-only\n// denylist would miss real leak vectors.\nconst FORBIDDEN_KEY_TOKENS = new Set([\n\t\"token\",\n\t\"accesstoken\",\n\t\"refreshtoken\",\n\t\"idtoken\",\n\t\"code\",\n\t\"codeverifier\",\n\t\"codechallenge\",\n\t\"clientsecret\",\n\t\"authorization\",\n\t\"password\",\n\t\"secret\",\n]);\n\nfunction canonicalizeAuditKey(key: string): string {\n\treturn key.toLowerCase().replace(/[^a-z0-9]/g, \"\");\n}\n\n/**\n * Build an audit event with redaction safety. Throws if a forbidden field\n * leaks in; callers should never need to pass token/code material here.\n */\nexport function buildOAuthAuditEvent(\n\tkind: OAuthAuditKind,\n\tfields: Omit<OAuthAuditEventBase, \"timestamp\"> & { now?: number },\n): OAuthAuditEvent {\n\tfor (const key of Object.keys(fields)) {\n\t\tif (FORBIDDEN_KEY_TOKENS.has(canonicalizeAuditKey(key))) {\n\t\t\tthrow new Error(`OAuth audit event must not carry forbidden field: ${key}`);\n\t\t}\n\t}\n\tconst { now, ...rest } = fields;\n\treturn {\n\t\tkind,\n\t\ttimestamp: new Date(now ?? Date.now()).toISOString(),\n\t\t...rest,\n\t};\n}\n\n/**\n * Wrap an audit emitter so any synchronous throw or stream-write failure stays\n * contained. Audit logging is best-effort observability and must never break\n * the OAuth/MCP request flow it observes. Failures are reported once per\n * process to `console.error` so they remain visible without flooding output.\n */\nexport function wrapAuditEmitterBestEffort(emit: OAuthAuditEmitter): OAuthAuditEmitter {\n\tlet reportedFailure = false;\n\treturn (event) => {\n\t\ttry {\n\t\t\temit(event);\n\t\t} catch (err) {\n\t\t\tif (!reportedFailure) {\n\t\t\t\treportedFailure = true;\n\t\t\t\tconsole.error(\"codemem MCP OAuth audit emitter failed (further failures suppressed):\", err);\n\t\t\t}\n\t\t}\n\t};\n}\n\n/**\n * Default audit emitter writes one JSON object per line to stderr. This keeps\n * MCP HTTP stdout reserved for protocol traffic and is greppable by operators\n * via `journalctl` or a redirected log file.\n */\nexport function createDefaultOAuthAuditEmitter(\n\tstream: NodeJS.WriteStream = process.stderr,\n): OAuthAuditEmitter {\n\treturn (event) => {\n\t\tstream.write(`${JSON.stringify({ source: \"codemem-mcp-oauth-audit\", ...event })}\\n`);\n\t};\n}\n\n/**\n * No-op emitter, used when CODEMEM_MCP_AUDIT=0 or when callers explicitly\n * want to suppress audit output (for example, embedded tests).\n */\nexport function createSilentOAuthAuditEmitter(): OAuthAuditEmitter {\n\treturn () => {};\n}\n\n/**\n * Resolve an emitter from environment configuration. `CODEMEM_MCP_AUDIT=0`,\n * `false`, or `no` disables audit logging; anything else (including unset)\n * uses the default stderr emitter.\n */\nexport function resolveOAuthAuditEmitterFromEnv(\n\tvalue = process.env.CODEMEM_MCP_AUDIT,\n): OAuthAuditEmitter {\n\tconst normalized = value?.trim().toLowerCase();\n\tif (normalized === \"0\" || normalized === \"false\" || normalized === \"no\") {\n\t\treturn createSilentOAuthAuditEmitter();\n\t}\n\treturn createDefaultOAuthAuditEmitter();\n}\n","import { createHash, createHmac, randomBytes, randomUUID, timingSafeEqual } from \"node:crypto\";\nimport { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from \"node:fs\";\nimport { chmod } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport type { OAuthRegisteredClientsStore } from \"@modelcontextprotocol/sdk/server/auth/clients.js\";\nimport { InvalidClientMetadataError } from \"@modelcontextprotocol/sdk/server/auth/errors.js\";\nimport type { OAuthServerProvider } from \"@modelcontextprotocol/sdk/server/auth/provider.js\";\nimport { createOAuthMetadata } from \"@modelcontextprotocol/sdk/server/auth/router.js\";\nimport {\n\ttype OAuthClientInformationFull,\n\ttype OAuthClientMetadata,\n\tOAuthClientMetadataSchema,\n\ttype OAuthErrorResponse,\n\ttype OAuthMetadata,\n\ttype OAuthProtectedResourceMetadata,\n\tOAuthProtectedResourceMetadataSchema,\n\ttype OAuthTokens,\n\tOAuthTokensSchema,\n} from \"@modelcontextprotocol/sdk/shared/auth.js\";\n\nexport const MCP_OAUTH_PUBLIC_URL_ENV = \"CODEMEM_MCP_HTTP_PUBLIC_URL\";\nexport const MCP_OAUTH_RESOURCE_NAME = \"codemem MCP\";\nexport const MCP_OAUTH_SCOPES_SUPPORTED = [\"memory:read\", \"memory:write\"];\nexport const MCP_OAUTH_SERVICE_DOCUMENTATION_URL = \"https://github.com/kunickiaj/codemem#readme\";\n\nconst CLAUDE_HOSTED_CALLBACK = \"https://claude.ai/api/mcp/auth_callback\";\nconst LOCAL_CALLBACK_HOSTS = new Set([\"localhost\", \"127.0.0.1\", \"::1\"]);\nconst SUPPORTED_GRANT_TYPES = new Set([\"authorization_code\", \"refresh_token\"]);\nconst SUPPORTED_RESPONSE_TYPES = new Set([\"code\"]);\nconst AUTHORIZATION_CODE_TTL_MS = 5 * 60 * 1000;\nconst ACCESS_TOKEN_TTL_SECONDS = 60 * 60;\nconst REFRESH_TOKEN_TTL_SECONDS = 30 * 24 * 60 * 60;\nconst MAX_AUTHORIZATION_CODES = 100;\nconst MAX_ACCESS_TOKENS = 100;\nconst MAX_REFRESH_GRANTS = 100;\nconst ACCESS_TOKEN_BYTES = 32;\nconst ACCESS_TOKEN_BASE64URL_LENGTH = 43;\nconst ACCESS_TOKEN_BASE64URL = /^[A-Za-z0-9_-]{43}$/;\nconst PKCE_S256_CHALLENGE = /^[A-Za-z0-9_-]{43}$/;\nconst PKCE_VERIFIER = /^[A-Za-z0-9._~-]{43,128}$/;\n\nexport interface McpOAuthMetadataOptions {\n\tmcpUrl: string;\n\tclientsStore: OAuthRegisteredClientsStore;\n}\n\nexport interface RegisteredMcpOAuthClient {\n\tstatus: 201;\n\tbody: OAuthClientInformationFull;\n}\n\nexport interface McpOAuthRegistrationError {\n\tstatus: 400;\n\tbody: { error: \"invalid_client_metadata\"; error_description: string };\n}\n\nexport interface AuthorizationCodeRecord {\n\tclientId: string;\n\tredirectUri: string;\n\tcodeChallenge: string;\n\tscopes: string[];\n\tresource?: string;\n\texpiresAt: number;\n\tused: boolean;\n}\n\nexport interface OAuthAuthorizationCodeStore {\n\tissueCode(record: Omit<AuthorizationCodeRecord, \"used\">, now?: number): string | undefined;\n\tpeekCode(code: string): AuthorizationCodeRecord | undefined;\n\tconsumeCode(code: string): AuthorizationCodeRecord | undefined;\n}\n\nexport interface AccessTokenRecord {\n\tclientId: string;\n\tgrantId?: string;\n\tscopes: string[];\n\tresource?: string;\n\ttokenHash: string;\n\tissuedAt: number;\n\texpiresAt: number;\n\tlastUsedAt: number | null;\n\trevokedAt: number | null;\n}\n\nexport type AccessTokenVerificationResult =\n\t| { ok: true; record: AccessTokenRecord }\n\t| { ok: false; reason: \"unknown_token\" | \"expired_token\" | \"revoked_token\" };\n\nexport interface OAuthAccessTokenStore {\n\tissueToken(\n\t\tclientId: string,\n\t\tnow?: number,\n\t\tresource?: string,\n\t\tgrantId?: string,\n\t\tscopes?: string[],\n\t): { token: string; expiresIn: number } | undefined;\n\tverifyToken(token: string, now?: number): AccessTokenVerificationResult;\n\trevokeToken(token: string, now?: number): boolean;\n\trevokeTokensForGrant?(grantId: string, now?: number): number;\n}\n\nexport interface RefreshTokenGrantRecord {\n\tgrantId: string;\n\tclientId: string;\n\tscopes: string[];\n\tresource?: string;\n\tcurrentRefreshTokenHash: string;\n\tpreviousRefreshTokenHash: string | null;\n\tissuedAt: number;\n\texpiresAt: number;\n\trotatedAt: number | null;\n\trevokedAt: number | null;\n}\n\nexport type RefreshTokenRotationResult =\n\t| { ok: true; grant: RefreshTokenGrantRecord; refreshToken: string; expiresIn: number }\n\t| {\n\t\t\tok: false;\n\t\t\treason:\n\t\t\t\t| \"unknown_refresh_token\"\n\t\t\t\t| \"expired_refresh_token\"\n\t\t\t\t| \"revoked_refresh_token\"\n\t\t\t\t| \"client_mismatch\"\n\t\t\t\t| \"scope_mismatch\"\n\t\t\t\t| \"resource_mismatch\"\n\t\t\t\t| \"refresh_token_replay\";\n\t\t\tgrantId?: string;\n\t };\n\nexport interface OAuthRefreshTokenStore {\n\tissueGrant(\n\t\trecord: { clientId: string; scopes?: string[]; resource?: string },\n\t\tnow?: number,\n\t): { grant: RefreshTokenGrantRecord; refreshToken: string; expiresIn: number } | undefined;\n\trotateRefreshToken(\n\t\tclientId: string,\n\t\trefreshToken: string,\n\t\toptions?: { scopes?: string[]; resource?: string },\n\t\tnow?: number,\n\t): RefreshTokenRotationResult;\n\trevokeRefreshToken(token: string, now?: number): string | undefined;\n\trevokeGrant(grantId: string, now?: number): boolean;\n}\n\nexport interface McpOAuthRedirectResult {\n\tstatus: 302;\n\tlocation: string;\n}\n\nexport interface McpOAuthErrorResult {\n\tstatus: 400;\n\tbody: OAuthErrorResponse;\n}\n\nexport interface McpOAuthTokenResult {\n\tstatus: 200;\n\tbody: OAuthTokens;\n}\n\nexport interface PreparedMcpOAuthAuthorizationRequest {\n\tclientId: string;\n\tredirectUri: string;\n\tcodeChallenge: string;\n\tscopes: string[];\n\tresource: string | null;\n\tstate: string | null;\n}\n\nexport class InMemoryOAuthClientsStore implements OAuthRegisteredClientsStore {\n\treadonly #clients = new Map<string, OAuthClientInformationFull>();\n\n\tgetClient(clientId: string): OAuthClientInformationFull | undefined {\n\t\treturn this.#clients.get(clientId);\n\t}\n\n\tregisterClient(\n\t\tclient: Omit<OAuthClientInformationFull, \"client_id\" | \"client_id_issued_at\">,\n\t): OAuthClientInformationFull {\n\t\tconst redirectError = validateRedirectUris(client.redirect_uris);\n\t\tif (redirectError) throw new InvalidClientMetadataError(redirectError);\n\t\tif (client.client_secret || client.token_endpoint_auth_method !== \"none\") {\n\t\t\tthrow new InvalidClientMetadataError(\n\t\t\t\t\"Only public clients with token_endpoint_auth_method=none are supported\",\n\t\t\t);\n\t\t}\n\t\tif (client.grant_types && !isSupportedList(client.grant_types, SUPPORTED_GRANT_TYPES)) {\n\t\t\tthrow new InvalidClientMetadataError(\n\t\t\t\t\"Only authorization_code and refresh_token grant_types are supported\",\n\t\t\t);\n\t\t}\n\t\tif (\n\t\t\tclient.response_types &&\n\t\t\t!isSupportedList(client.response_types, SUPPORTED_RESPONSE_TYPES)\n\t\t) {\n\t\t\tthrow new InvalidClientMetadataError(\"Only code response_type is supported\");\n\t\t}\n\t\tif (this.#clients.size >= 100) {\n\t\t\tconst oldestClientId = this.#clients.keys().next().value;\n\t\t\tif (oldestClientId) this.#clients.delete(oldestClientId);\n\t\t}\n\t\tconst registered = {\n\t\t\t...client,\n\t\t\ttoken_endpoint_auth_method: \"none\" as const,\n\t\t\tgrant_types: client.grant_types ?? [\"authorization_code\", \"refresh_token\"],\n\t\t\tresponse_types: client.response_types ?? [\"code\"],\n\t\t\tclient_id: randomUUID(),\n\t\t\tclient_id_issued_at: Math.floor(Date.now() / 1000),\n\t\t};\n\t\tthis.#clients.set(registered.client_id, registered);\n\t\treturn registered;\n\t}\n}\n\nexport class InMemoryOAuthAuthorizationCodeStore implements OAuthAuthorizationCodeStore {\n\treadonly #codes = new Map<string, AuthorizationCodeRecord>();\n\n\tissueCode(record: Omit<AuthorizationCodeRecord, \"used\">, now = Date.now()): string | undefined {\n\t\tthis.#deleteExpiredCodes(now);\n\t\tif (this.#codes.size >= MAX_AUTHORIZATION_CODES) return undefined;\n\t\tconst code = randomUUID();\n\t\tthis.#codes.set(code, { ...record, used: false });\n\t\treturn code;\n\t}\n\n\tpeekCode(code: string): AuthorizationCodeRecord | undefined {\n\t\tconst record = this.#codes.get(code);\n\t\tif (!record || record.used) return undefined;\n\t\treturn record;\n\t}\n\n\tconsumeCode(code: string): AuthorizationCodeRecord | undefined {\n\t\tconst record = this.#codes.get(code);\n\t\tif (!record || record.used) return undefined;\n\t\trecord.used = true;\n\t\treturn record;\n\t}\n\n\t#deleteExpiredCodes(now: number): void {\n\t\tfor (const [code, record] of this.#codes) {\n\t\t\tif (record.expiresAt <= now) this.#codes.delete(code);\n\t\t}\n\t}\n}\n\nexport class InMemoryOAuthAccessTokenStore implements OAuthAccessTokenStore {\n\treadonly #tokensByHash = new Map<string, AccessTokenRecord>();\n\treadonly #tokenHashKey = randomBytes(32);\n\n\tissueToken(\n\t\tclientId: string,\n\t\tnow = Date.now(),\n\t\tresource?: string,\n\t\tgrantId?: string,\n\t\tscopes: string[] = [],\n\t): { token: string; expiresIn: number } | undefined {\n\t\tthis.#deleteInactiveTokens(now);\n\t\tif (this.#tokensByHash.size >= MAX_ACCESS_TOKENS) return undefined;\n\t\tconst tokenBytes = randomBytes(ACCESS_TOKEN_BYTES);\n\t\tconst tokenHash = signOAuthAccessTokenBytes(tokenBytes, this.#tokenHashKey);\n\t\tthis.#tokensByHash.set(tokenHash, {\n\t\t\tclientId,\n\t\t\tgrantId,\n\t\t\tscopes: [...scopes],\n\t\t\tresource,\n\t\t\ttokenHash,\n\t\t\tissuedAt: now,\n\t\t\texpiresAt: now + ACCESS_TOKEN_TTL_SECONDS * 1000,\n\t\t\tlastUsedAt: null,\n\t\t\trevokedAt: null,\n\t\t});\n\t\treturn {\n\t\t\ttoken: tokenBytes.toString(\"base64url\"),\n\t\t\texpiresIn: ACCESS_TOKEN_TTL_SECONDS,\n\t\t};\n\t}\n\n\tverifyToken(token: string, now = Date.now()): AccessTokenVerificationResult {\n\t\tconst tokenBytes = decodeOAuthAccessToken(token);\n\t\tif (!tokenBytes) return { ok: false, reason: \"unknown_token\" };\n\t\tconst tokenHash = signOAuthAccessTokenBytes(tokenBytes, this.#tokenHashKey);\n\t\tconst record = this.#tokensByHash.get(tokenHash);\n\t\tif (!record || !isSameTokenHash(record.tokenHash, tokenHash)) {\n\t\t\treturn { ok: false, reason: \"unknown_token\" };\n\t\t}\n\t\tif (record.revokedAt !== null) return { ok: false, reason: \"revoked_token\" };\n\t\tif (record.expiresAt <= now) return { ok: false, reason: \"expired_token\" };\n\t\trecord.lastUsedAt = now;\n\t\treturn { ok: true, record: { ...record } };\n\t}\n\n\trevokeToken(token: string, now = Date.now()): boolean {\n\t\tconst tokenBytes = decodeOAuthAccessToken(token);\n\t\tif (!tokenBytes) return false;\n\t\tconst tokenHash = signOAuthAccessTokenBytes(tokenBytes, this.#tokenHashKey);\n\t\tconst record = this.#tokensByHash.get(tokenHash);\n\t\tif (!record || !isSameTokenHash(record.tokenHash, tokenHash)) return false;\n\t\tif (record.revokedAt !== null) return true;\n\t\trecord.revokedAt = now;\n\t\treturn true;\n\t}\n\n\trevokeTokensForGrant(grantId: string, now = Date.now()): number {\n\t\tlet revoked = 0;\n\t\tfor (const record of this.#tokensByHash.values()) {\n\t\t\tif (record.grantId !== grantId || record.revokedAt !== null) continue;\n\t\t\trecord.revokedAt = now;\n\t\t\trevoked += 1;\n\t\t}\n\t\treturn revoked;\n\t}\n\n\t#deleteInactiveTokens(now: number): void {\n\t\tfor (const [tokenHash, record] of this.#tokensByHash) {\n\t\t\tif (record.expiresAt <= now || record.revokedAt !== null)\n\t\t\t\tthis.#tokensByHash.delete(tokenHash);\n\t\t}\n\t}\n}\n\nexport class InMemoryOAuthRefreshTokenStore implements OAuthRefreshTokenStore {\n\treadonly #grantsById = new Map<string, RefreshTokenGrantRecord>();\n\treadonly #grantIdsByRefreshHash = new Map<string, string>();\n\treadonly #refreshHashesByGrantId = new Map<string, Set<string>>();\n\treadonly #tokenHashKey = randomBytes(32);\n\n\tissueGrant(\n\t\trecord: { clientId: string; scopes?: string[]; resource?: string },\n\t\tnow = Date.now(),\n\t): { grant: RefreshTokenGrantRecord; refreshToken: string; expiresIn: number } | undefined {\n\t\tthis.#deleteInactiveGrants(now);\n\t\tif (this.#grantsById.size >= MAX_REFRESH_GRANTS) return undefined;\n\t\tconst refreshToken = randomToken();\n\t\tconst refreshTokenHash = hashSerializedOAuthToken(refreshToken, this.#tokenHashKey);\n\t\tif (!refreshTokenHash) return undefined;\n\t\tconst grant: RefreshTokenGrantRecord = {\n\t\t\tgrantId: randomUUID(),\n\t\t\tclientId: record.clientId,\n\t\t\tscopes: [...(record.scopes ?? [])],\n\t\t\tresource: record.resource,\n\t\t\tcurrentRefreshTokenHash: refreshTokenHash,\n\t\t\tpreviousRefreshTokenHash: null,\n\t\t\tissuedAt: now,\n\t\t\texpiresAt: now + REFRESH_TOKEN_TTL_SECONDS * 1000,\n\t\t\trotatedAt: null,\n\t\t\trevokedAt: null,\n\t\t};\n\t\tthis.#grantsById.set(grant.grantId, grant);\n\t\tthis.#grantIdsByRefreshHash.set(refreshTokenHash, grant.grantId);\n\t\tthis.#refreshHashesByGrantId.set(grant.grantId, new Set([refreshTokenHash]));\n\t\treturn {\n\t\t\tgrant: { ...grant, scopes: [...grant.scopes] },\n\t\t\trefreshToken,\n\t\t\texpiresIn: REFRESH_TOKEN_TTL_SECONDS,\n\t\t};\n\t}\n\n\trotateRefreshToken(\n\t\tclientId: string,\n\t\trefreshToken: string,\n\t\toptions: { scopes?: string[]; resource?: string } = {},\n\t\tnow = Date.now(),\n\t): RefreshTokenRotationResult {\n\t\tconst tokenHash = hashSerializedOAuthToken(refreshToken, this.#tokenHashKey);\n\t\tif (!tokenHash) return { ok: false, reason: \"unknown_refresh_token\" };\n\t\tconst grantId = this.#grantIdsByRefreshHash.get(tokenHash);\n\t\tif (!grantId) return { ok: false, reason: \"unknown_refresh_token\" };\n\t\tconst grant = this.#grantsById.get(grantId);\n\t\tif (!grant) return { ok: false, reason: \"unknown_refresh_token\" };\n\t\tif (grant.revokedAt !== null) return { ok: false, reason: \"revoked_refresh_token\", grantId };\n\t\tif (grant.expiresAt <= now) {\n\t\t\tthis.revokeGrant(grantId, now);\n\t\t\treturn { ok: false, reason: \"expired_refresh_token\", grantId };\n\t\t}\n\t\tif (grant.clientId !== clientId) return { ok: false, reason: \"client_mismatch\", grantId };\n\t\tif (!isScopeSubset(options.scopes ?? grant.scopes, grant.scopes)) {\n\t\t\treturn { ok: false, reason: \"scope_mismatch\", grantId };\n\t\t}\n\t\tif ((grant.resource ?? null) !== (options.resource ?? grant.resource ?? null)) {\n\t\t\treturn { ok: false, reason: \"resource_mismatch\", grantId };\n\t\t}\n\n\t\tconst matchesCurrent = isSameTokenHash(grant.currentRefreshTokenHash, tokenHash);\n\t\tconst matchesPrevious =\n\t\t\tgrant.previousRefreshTokenHash !== null &&\n\t\t\tisSameTokenHash(grant.previousRefreshTokenHash, tokenHash);\n\t\tif (!matchesCurrent && !matchesPrevious) {\n\t\t\tthis.revokeGrant(grantId, now);\n\t\t\treturn { ok: false, reason: \"refresh_token_replay\", grantId };\n\t\t}\n\n\t\tconst nextRefreshToken = randomToken();\n\t\tconst nextRefreshTokenHash = hashSerializedOAuthToken(nextRefreshToken, this.#tokenHashKey);\n\t\tif (!nextRefreshTokenHash) return { ok: false, reason: \"unknown_refresh_token\" };\n\t\tgrant.scopes = [...(options.scopes ?? grant.scopes)];\n\t\tgrant.previousRefreshTokenHash = matchesCurrent ? grant.currentRefreshTokenHash : null;\n\t\tgrant.currentRefreshTokenHash = nextRefreshTokenHash;\n\t\tgrant.rotatedAt = now;\n\t\tthis.#grantIdsByRefreshHash.set(nextRefreshTokenHash, grantId);\n\t\tthis.#refreshHashesByGrantId.get(grantId)?.add(nextRefreshTokenHash);\n\t\treturn {\n\t\t\tok: true,\n\t\t\tgrant: { ...grant, scopes: [...grant.scopes] },\n\t\t\trefreshToken: nextRefreshToken,\n\t\t\texpiresIn: Math.max(0, Math.floor((grant.expiresAt - now) / 1000)),\n\t\t};\n\t}\n\n\trevokeRefreshToken(token: string, now = Date.now()): string | undefined {\n\t\tconst tokenHash = hashSerializedOAuthToken(token, this.#tokenHashKey);\n\t\tif (!tokenHash) return undefined;\n\t\tconst grantId = this.#grantIdsByRefreshHash.get(tokenHash);\n\t\tif (!grantId) return undefined;\n\t\tthis.revokeGrant(grantId, now);\n\t\treturn grantId;\n\t}\n\n\trevokeGrant(grantId: string, now = Date.now()): boolean {\n\t\tconst grant = this.#grantsById.get(grantId);\n\t\tif (!grant) return false;\n\t\tif (grant.revokedAt !== null) return true;\n\t\tgrant.revokedAt = now;\n\t\tthis.#deleteGrantRefreshHashIndexEntries(grant);\n\t\treturn true;\n\t}\n\n\t#deleteInactiveGrants(now: number): void {\n\t\tfor (const [grantId, grant] of this.#grantsById) {\n\t\t\tif (grant.expiresAt > now && grant.revokedAt === null) continue;\n\t\t\tthis.#grantsById.delete(grantId);\n\t\t\tthis.#deleteGrantRefreshHashIndexEntries(grant);\n\t\t}\n\t}\n\n\t#deleteGrantRefreshHashIndexEntries(grant: RefreshTokenGrantRecord): void {\n\t\tconst refreshHashes = this.#refreshHashesByGrantId.get(grant.grantId);\n\t\tif (refreshHashes) {\n\t\t\tfor (const refreshHash of refreshHashes) this.#grantIdsByRefreshHash.delete(refreshHash);\n\t\t\tthis.#refreshHashesByGrantId.delete(grant.grantId);\n\t\t\treturn;\n\t\t}\n\t\tthis.#grantIdsByRefreshHash.delete(grant.currentRefreshTokenHash);\n\t\tif (grant.previousRefreshTokenHash)\n\t\t\tthis.#grantIdsByRefreshHash.delete(grant.previousRefreshTokenHash);\n\t}\n}\n\ninterface OAuthStateFileData {\n\tversion: 1;\n\tclients: OAuthClientInformationFull[];\n\taccessTokens: AccessTokenRecord[];\n\trefreshGrants: RefreshTokenGrantRecord[];\n\trefreshHashesByGrantId: Record<string, string[]>;\n}\n\n/**\n * JSON-backed OAuth state for remote MCP clients.\n *\n * Claude keeps its dynamically-registered `client_id` and refresh token across\n * connector reconnects. If codemem only stores that state in memory, a package\n * upgrade or MCP process restart makes Claude's next refresh look like an\n * unknown client. This store persists client registrations, access tokens, and\n * refresh-token grants so routine restarts do not force users through OAuth\n * again.\n */\nexport class JsonFileOAuthStateStore\n\timplements\n\t\tOAuthRegisteredClientsStore,\n\t\tOAuthAuthorizationCodeStore,\n\t\tOAuthAccessTokenStore,\n\t\tOAuthRefreshTokenStore\n{\n\treadonly #path: string;\n\treadonly #codes = new Map<string, AuthorizationCodeRecord>();\n\t#clients = new Map<string, OAuthClientInformationFull>();\n\t#tokensByHash = new Map<string, AccessTokenRecord>();\n\t#grantsById = new Map<string, RefreshTokenGrantRecord>();\n\t#grantIdsByRefreshHash = new Map<string, string>();\n\t#refreshHashesByGrantId = new Map<string, Set<string>>();\n\n\tconstructor(path = getDefaultMcpOAuthStatePath()) {\n\t\tthis.#path = path;\n\t\tthis.#load();\n\t}\n\n\tgetClient(clientId: string): OAuthClientInformationFull | undefined {\n\t\treturn this.#clients.get(clientId);\n\t}\n\n\tregisterClient(\n\t\tclient: Omit<OAuthClientInformationFull, \"client_id\" | \"client_id_issued_at\">,\n\t): OAuthClientInformationFull {\n\t\tconst redirectError = validateRedirectUris(client.redirect_uris);\n\t\tif (redirectError) throw new InvalidClientMetadataError(redirectError);\n\t\tif (client.client_secret || client.token_endpoint_auth_method !== \"none\") {\n\t\t\tthrow new InvalidClientMetadataError(\n\t\t\t\t\"Only public clients with token_endpoint_auth_method=none are supported\",\n\t\t\t);\n\t\t}\n\t\tif (client.grant_types && !isSupportedList(client.grant_types, SUPPORTED_GRANT_TYPES)) {\n\t\t\tthrow new InvalidClientMetadataError(\n\t\t\t\t\"Only authorization_code and refresh_token grant_types are supported\",\n\t\t\t);\n\t\t}\n\t\tif (\n\t\t\tclient.response_types &&\n\t\t\t!isSupportedList(client.response_types, SUPPORTED_RESPONSE_TYPES)\n\t\t) {\n\t\t\tthrow new InvalidClientMetadataError(\"Only code response_type is supported\");\n\t\t}\n\t\tthis.#deleteInactive(Date.now());\n\t\tif (this.#clients.size >= 100) {\n\t\t\tconst oldestClientId = this.#clients.keys().next().value;\n\t\t\tif (oldestClientId) this.#clients.delete(oldestClientId);\n\t\t}\n\t\tconst registered = {\n\t\t\t...client,\n\t\t\ttoken_endpoint_auth_method: \"none\" as const,\n\t\t\tgrant_types: client.grant_types ?? [\"authorization_code\", \"refresh_token\"],\n\t\t\tresponse_types: client.response_types ?? [\"code\"],\n\t\t\tclient_id: randomUUID(),\n\t\t\tclient_id_issued_at: Math.floor(Date.now() / 1000),\n\t\t};\n\t\tthis.#clients.set(registered.client_id, registered);\n\t\tthis.#save();\n\t\treturn registered;\n\t}\n\n\tissueCode(record: Omit<AuthorizationCodeRecord, \"used\">, now = Date.now()): string | undefined {\n\t\tthis.#deleteExpiredCodes(now);\n\t\tif (this.#codes.size >= MAX_AUTHORIZATION_CODES) return undefined;\n\t\tconst code = randomUUID();\n\t\tthis.#codes.set(code, { ...record, used: false });\n\t\treturn code;\n\t}\n\n\tpeekCode(code: string): AuthorizationCodeRecord | undefined {\n\t\tconst record = this.#codes.get(code);\n\t\tif (!record || record.used) return undefined;\n\t\treturn record;\n\t}\n\n\tconsumeCode(code: string): AuthorizationCodeRecord | undefined {\n\t\tconst record = this.#codes.get(code);\n\t\tif (!record || record.used) return undefined;\n\t\trecord.used = true;\n\t\treturn record;\n\t}\n\n\tissueToken(\n\t\tclientId: string,\n\t\tnow = Date.now(),\n\t\tresource?: string,\n\t\tgrantId?: string,\n\t\tscopes: string[] = [],\n\t): { token: string; expiresIn: number } | undefined {\n\t\tthis.#deleteInactive(now);\n\t\tif (this.#tokensByHash.size >= MAX_ACCESS_TOKENS) return undefined;\n\t\tconst token = randomToken();\n\t\tconst tokenHash = hashOAuthTokenForStateFile(token);\n\t\tif (!tokenHash) return undefined;\n\t\tthis.#tokensByHash.set(tokenHash, {\n\t\t\tclientId,\n\t\t\tgrantId,\n\t\t\tscopes: [...scopes],\n\t\t\tresource,\n\t\t\ttokenHash,\n\t\t\tissuedAt: now,\n\t\t\texpiresAt: now + ACCESS_TOKEN_TTL_SECONDS * 1000,\n\t\t\tlastUsedAt: null,\n\t\t\trevokedAt: null,\n\t\t});\n\t\tthis.#save();\n\t\treturn { token, expiresIn: ACCESS_TOKEN_TTL_SECONDS };\n\t}\n\n\tverifyToken(token: string, now = Date.now()): AccessTokenVerificationResult {\n\t\tconst tokenHash = hashOAuthTokenForStateFile(token);\n\t\tif (!tokenHash) return { ok: false, reason: \"unknown_token\" };\n\t\tconst record = this.#tokensByHash.get(tokenHash);\n\t\tif (!record || !isSameTokenHash(record.tokenHash, tokenHash)) {\n\t\t\treturn { ok: false, reason: \"unknown_token\" };\n\t\t}\n\t\tif (record.revokedAt !== null) return { ok: false, reason: \"revoked_token\" };\n\t\tif (record.expiresAt <= now) return { ok: false, reason: \"expired_token\" };\n\t\trecord.lastUsedAt = now;\n\t\treturn { ok: true, record: { ...record, scopes: [...record.scopes] } };\n\t}\n\n\trevokeToken(token: string, now = Date.now()): boolean {\n\t\tconst tokenHash = hashOAuthTokenForStateFile(token);\n\t\tif (!tokenHash) return false;\n\t\tconst record = this.#tokensByHash.get(tokenHash);\n\t\tif (!record || !isSameTokenHash(record.tokenHash, tokenHash)) return false;\n\t\tif (record.revokedAt !== null) return true;\n\t\trecord.revokedAt = now;\n\t\tthis.#save();\n\t\treturn true;\n\t}\n\n\trevokeTokensForGrant(grantId: string, now = Date.now()): number {\n\t\tlet revoked = 0;\n\t\tfor (const record of this.#tokensByHash.values()) {\n\t\t\tif (record.grantId !== grantId || record.revokedAt !== null) continue;\n\t\t\trecord.revokedAt = now;\n\t\t\trevoked += 1;\n\t\t}\n\t\tif (revoked > 0) this.#save();\n\t\treturn revoked;\n\t}\n\n\tissueGrant(\n\t\trecord: { clientId: string; scopes?: string[]; resource?: string },\n\t\tnow = Date.now(),\n\t): { grant: RefreshTokenGrantRecord; refreshToken: string; expiresIn: number } | undefined {\n\t\tthis.#deleteInactive(now);\n\t\tif (this.#grantsById.size >= MAX_REFRESH_GRANTS) return undefined;\n\t\tconst refreshToken = randomToken();\n\t\tconst refreshTokenHash = hashOAuthTokenForStateFile(refreshToken);\n\t\tif (!refreshTokenHash) return undefined;\n\t\tconst grant: RefreshTokenGrantRecord = {\n\t\t\tgrantId: randomUUID(),\n\t\t\tclientId: record.clientId,\n\t\t\tscopes: [...(record.scopes ?? [])],\n\t\t\tresource: record.resource,\n\t\t\tcurrentRefreshTokenHash: refreshTokenHash,\n\t\t\tpreviousRefreshTokenHash: null,\n\t\t\tissuedAt: now,\n\t\t\texpiresAt: now + REFRESH_TOKEN_TTL_SECONDS * 1000,\n\t\t\trotatedAt: null,\n\t\t\trevokedAt: null,\n\t\t};\n\t\tthis.#grantsById.set(grant.grantId, grant);\n\t\tthis.#grantIdsByRefreshHash.set(refreshTokenHash, grant.grantId);\n\t\tthis.#refreshHashesByGrantId.set(grant.grantId, new Set([refreshTokenHash]));\n\t\tthis.#save();\n\t\treturn {\n\t\t\tgrant: { ...grant, scopes: [...grant.scopes] },\n\t\t\trefreshToken,\n\t\t\texpiresIn: REFRESH_TOKEN_TTL_SECONDS,\n\t\t};\n\t}\n\n\trotateRefreshToken(\n\t\tclientId: string,\n\t\trefreshToken: string,\n\t\toptions: { scopes?: string[]; resource?: string } = {},\n\t\tnow = Date.now(),\n\t): RefreshTokenRotationResult {\n\t\tconst tokenHash = hashOAuthTokenForStateFile(refreshToken);\n\t\tif (!tokenHash) return { ok: false, reason: \"unknown_refresh_token\" };\n\t\tconst grantId = this.#grantIdsByRefreshHash.get(tokenHash);\n\t\tif (!grantId) return { ok: false, reason: \"unknown_refresh_token\" };\n\t\tconst grant = this.#grantsById.get(grantId);\n\t\tif (!grant) return { ok: false, reason: \"unknown_refresh_token\" };\n\t\tif (grant.revokedAt !== null) return { ok: false, reason: \"revoked_refresh_token\", grantId };\n\t\tif (grant.expiresAt <= now) {\n\t\t\tthis.revokeGrant(grantId, now);\n\t\t\treturn { ok: false, reason: \"expired_refresh_token\", grantId };\n\t\t}\n\t\tif (grant.clientId !== clientId) return { ok: false, reason: \"client_mismatch\", grantId };\n\t\tif (!isScopeSubset(options.scopes ?? grant.scopes, grant.scopes)) {\n\t\t\treturn { ok: false, reason: \"scope_mismatch\", grantId };\n\t\t}\n\t\tif ((grant.resource ?? null) !== (options.resource ?? grant.resource ?? null)) {\n\t\t\treturn { ok: false, reason: \"resource_mismatch\", grantId };\n\t\t}\n\n\t\tconst matchesCurrent = isSameTokenHash(grant.currentRefreshTokenHash, tokenHash);\n\t\tconst matchesPrevious =\n\t\t\tgrant.previousRefreshTokenHash !== null &&\n\t\t\tisSameTokenHash(grant.previousRefreshTokenHash, tokenHash);\n\t\tif (!matchesCurrent && !matchesPrevious) {\n\t\t\tthis.revokeGrant(grantId, now);\n\t\t\treturn { ok: false, reason: \"refresh_token_replay\", grantId };\n\t\t}\n\n\t\tconst nextRefreshToken = randomToken();\n\t\tconst nextRefreshTokenHash = hashOAuthTokenForStateFile(nextRefreshToken);\n\t\tif (!nextRefreshTokenHash) return { ok: false, reason: \"unknown_refresh_token\" };\n\t\tgrant.scopes = [...(options.scopes ?? grant.scopes)];\n\t\tgrant.previousRefreshTokenHash = matchesCurrent ? grant.currentRefreshTokenHash : null;\n\t\tgrant.currentRefreshTokenHash = nextRefreshTokenHash;\n\t\tgrant.rotatedAt = now;\n\t\tthis.#grantIdsByRefreshHash.set(nextRefreshTokenHash, grantId);\n\t\tthis.#refreshHashesByGrantId.get(grantId)?.add(nextRefreshTokenHash);\n\t\tthis.#save();\n\t\treturn {\n\t\t\tok: true,\n\t\t\tgrant: { ...grant, scopes: [...grant.scopes] },\n\t\t\trefreshToken: nextRefreshToken,\n\t\t\texpiresIn: Math.max(0, Math.floor((grant.expiresAt - now) / 1000)),\n\t\t};\n\t}\n\n\trevokeRefreshToken(token: string, now = Date.now()): string | undefined {\n\t\tconst tokenHash = hashOAuthTokenForStateFile(token);\n\t\tif (!tokenHash) return undefined;\n\t\tconst grantId = this.#grantIdsByRefreshHash.get(tokenHash);\n\t\tif (!grantId) return undefined;\n\t\tthis.revokeGrant(grantId, now);\n\t\treturn grantId;\n\t}\n\n\trevokeGrant(grantId: string, now = Date.now()): boolean {\n\t\tconst grant = this.#grantsById.get(grantId);\n\t\tif (!grant) return false;\n\t\tif (grant.revokedAt !== null) return true;\n\t\tgrant.revokedAt = now;\n\t\tthis.#deleteGrantRefreshHashIndexEntries(grant);\n\t\tthis.#save();\n\t\treturn true;\n\t}\n\n\t#load(): void {\n\t\tif (!existsSync(this.#path)) return;\n\t\tlet parsed: OAuthStateFileData;\n\t\ttry {\n\t\t\tparsed = JSON.parse(readFileSync(this.#path, \"utf8\")) as OAuthStateFileData;\n\t\t} catch {\n\t\t\treturn;\n\t\t}\n\t\tif (parsed.version !== 1) return;\n\t\tthis.#clients = new Map(parsed.clients.map((client) => [client.client_id, client]));\n\t\tthis.#tokensByHash = new Map(parsed.accessTokens.map((record) => [record.tokenHash, record]));\n\t\tthis.#grantsById = new Map(parsed.refreshGrants.map((grant) => [grant.grantId, grant]));\n\t\tthis.#grantIdsByRefreshHash = new Map();\n\t\tthis.#refreshHashesByGrantId = new Map();\n\t\tfor (const grant of this.#grantsById.values()) {\n\t\t\tconst hashes = new Set(parsed.refreshHashesByGrantId[grant.grantId] ?? []);\n\t\t\thashes.add(grant.currentRefreshTokenHash);\n\t\t\tif (grant.previousRefreshTokenHash) hashes.add(grant.previousRefreshTokenHash);\n\t\t\tthis.#refreshHashesByGrantId.set(grant.grantId, hashes);\n\t\t\tfor (const hash of hashes) this.#grantIdsByRefreshHash.set(hash, grant.grantId);\n\t\t}\n\t\tthis.#deleteInactive(Date.now());\n\t}\n\n\t#save(): void {\n\t\tmkdirSync(dirname(this.#path), { recursive: true, mode: 0o700 });\n\t\tconst data: OAuthStateFileData = {\n\t\t\tversion: 1,\n\t\t\tclients: [...this.#clients.values()],\n\t\t\taccessTokens: [...this.#tokensByHash.values()],\n\t\t\trefreshGrants: [...this.#grantsById.values()],\n\t\t\trefreshHashesByGrantId: Object.fromEntries(\n\t\t\t\t[...this.#refreshHashesByGrantId.entries()].map(([grantId, hashes]) => [\n\t\t\t\t\tgrantId,\n\t\t\t\t\t[...hashes],\n\t\t\t\t]),\n\t\t\t),\n\t\t};\n\t\tconst tmpPath = `${this.#path}.${process.pid}.${Date.now()}.tmp`;\n\t\twriteFileSync(tmpPath, `${JSON.stringify(data, null, 2)}\\n`, { mode: 0o600 });\n\t\trenameSync(tmpPath, this.#path);\n\t\tvoid chmod(this.#path, 0o600).catch(() => undefined);\n\t}\n\n\t#deleteExpiredCodes(now: number): void {\n\t\tfor (const [code, record] of this.#codes) {\n\t\t\tif (record.expiresAt <= now) this.#codes.delete(code);\n\t\t}\n\t}\n\n\t#deleteInactive(now: number): void {\n\t\tlet changed = false;\n\t\tfor (const [tokenHash, record] of this.#tokensByHash) {\n\t\t\tif (record.expiresAt > now && record.revokedAt === null) continue;\n\t\t\tthis.#tokensByHash.delete(tokenHash);\n\t\t\tchanged = true;\n\t\t}\n\t\tfor (const [grantId, grant] of this.#grantsById) {\n\t\t\tif (grant.expiresAt > now && grant.revokedAt === null) continue;\n\t\t\tthis.#grantsById.delete(grantId);\n\t\t\tthis.#deleteGrantRefreshHashIndexEntries(grant);\n\t\t\tchanged = true;\n\t\t}\n\t\tif (changed) this.#save();\n\t}\n\n\t#deleteGrantRefreshHashIndexEntries(grant: RefreshTokenGrantRecord): void {\n\t\tconst refreshHashes = this.#refreshHashesByGrantId.get(grant.grantId);\n\t\tif (refreshHashes) {\n\t\t\tfor (const refreshHash of refreshHashes) this.#grantIdsByRefreshHash.delete(refreshHash);\n\t\t\tthis.#refreshHashesByGrantId.delete(grant.grantId);\n\t\t\treturn;\n\t\t}\n\t\tthis.#grantIdsByRefreshHash.delete(grant.currentRefreshTokenHash);\n\t\tif (grant.previousRefreshTokenHash)\n\t\t\tthis.#grantIdsByRefreshHash.delete(grant.previousRefreshTokenHash);\n\t}\n}\n\nexport function createInMemoryOAuthClientsStore(): OAuthRegisteredClientsStore {\n\treturn new InMemoryOAuthClientsStore();\n}\n\nexport function createInMemoryOAuthAuthorizationCodeStore(): OAuthAuthorizationCodeStore {\n\treturn new InMemoryOAuthAuthorizationCodeStore();\n}\n\nexport function createInMemoryOAuthAccessTokenStore(): OAuthAccessTokenStore {\n\treturn new InMemoryOAuthAccessTokenStore();\n}\n\nexport function createInMemoryOAuthRefreshTokenStore(): OAuthRefreshTokenStore {\n\treturn new InMemoryOAuthRefreshTokenStore();\n}\n\nexport function createJsonFileOAuthStateStore(path?: string): JsonFileOAuthStateStore {\n\treturn new JsonFileOAuthStateStore(path);\n}\n\nexport function getDefaultMcpOAuthStatePath(): string {\n\treturn join(process.env.HOME?.trim() || homedir(), \".codemem\", \"mcp-oauth-state.json\");\n}\n\nexport function createMcpOAuthMetadata(options: McpOAuthMetadataOptions): OAuthMetadata {\n\tconst mcpUrl = normalizeMcpPublicUrl(options.mcpUrl);\n\tconst issuerUrl = getOriginUrl(mcpUrl);\n\tconst provider = createMetadataOnlyProvider(options.clientsStore);\n\treturn {\n\t\t...createOAuthMetadata({\n\t\t\tprovider,\n\t\t\tissuerUrl,\n\t\t\tbaseUrl: issuerUrl,\n\t\t}),\n\t\t// Phase 1 treats claude.ai and local callback clients as public clients.\n\t\t// Do not issue or advertise client secrets until we have a concrete need.\n\t\tgrant_types_supported: [\"authorization_code\", \"refresh_token\"],\n\t\ttoken_endpoint_auth_methods_supported: [\"none\"],\n\t\tscopes_supported: MCP_OAUTH_SCOPES_SUPPORTED,\n\t\tservice_documentation: MCP_OAUTH_SERVICE_DOCUMENTATION_URL,\n\t\trevocation_endpoint: new URL(\"/revoke\", issuerUrl).href,\n\t\trevocation_endpoint_auth_methods_supported: [\"none\"],\n\t\tclient_id_metadata_document_supported: false,\n\t};\n}\n\nexport function createMcpProtectedResourceMetadata(mcpUrl: string): OAuthProtectedResourceMetadata {\n\tconst normalizedMcpUrl = normalizeMcpPublicUrl(mcpUrl);\n\tconst metadata = {\n\t\tresource: normalizedMcpUrl.href,\n\t\tauthorization_servers: [getOriginUrl(normalizedMcpUrl).href],\n\t\tscopes_supported: MCP_OAUTH_SCOPES_SUPPORTED,\n\t\tbearer_methods_supported: [\"header\"],\n\t\tresource_name: MCP_OAUTH_RESOURCE_NAME,\n\t\tresource_documentation: MCP_OAUTH_SERVICE_DOCUMENTATION_URL,\n\t};\n\treturn OAuthProtectedResourceMetadataSchema.parse(metadata);\n}\n\nexport function registerMcpOAuthClient(\n\trequestBody: unknown,\n\tclientsStore: OAuthRegisteredClientsStore,\n): RegisteredMcpOAuthClient | McpOAuthRegistrationError {\n\tif (!clientsStore.registerClient) {\n\t\treturn invalidClientMetadata(\"Dynamic client registration is not enabled\");\n\t}\n\n\tconst parseResult = OAuthClientMetadataSchema.safeParse(requestBody);\n\tif (!parseResult.success) {\n\t\treturn invalidClientMetadata(parseResult.error.message);\n\t}\n\n\tconst clientMetadata = parseResult.data;\n\tconst redirectError = validateRedirectUris(clientMetadata.redirect_uris);\n\tif (redirectError) return invalidClientMetadata(redirectError);\n\n\tif (!isSupportedTokenEndpointAuthMethod(clientMetadata.token_endpoint_auth_method)) {\n\t\treturn invalidClientMetadata(\n\t\t\t\"Only public clients with token_endpoint_auth_method=none are supported\",\n\t\t);\n\t}\n\n\tif (\n\t\tclientMetadata.grant_types &&\n\t\t!isSupportedList(clientMetadata.grant_types, SUPPORTED_GRANT_TYPES)\n\t) {\n\t\treturn invalidClientMetadata(\n\t\t\t\"Only authorization_code and refresh_token grant_types are supported\",\n\t\t);\n\t}\n\n\tif (\n\t\tclientMetadata.response_types &&\n\t\t!isSupportedList(clientMetadata.response_types, SUPPORTED_RESPONSE_TYPES)\n\t) {\n\t\treturn invalidClientMetadata(\"Only code response_type is supported\");\n\t}\n\n\tconst registered = clientsStore.registerClient({\n\t\t...clientMetadata,\n\t\ttoken_endpoint_auth_method: \"none\",\n\t\tgrant_types: clientMetadata.grant_types ?? [\"authorization_code\", \"refresh_token\"],\n\t\tresponse_types: clientMetadata.response_types ?? [\"code\"],\n\t});\n\n\tif (registered instanceof Promise) {\n\t\tthrow new Error(\n\t\t\t\"Asynchronous OAuth client stores are not supported by this HTTP bootstrap yet\",\n\t\t);\n\t}\n\n\treturn { status: 201, body: registered };\n}\n\nexport function authorizeMcpOAuthClient(\n\tparams: URLSearchParams,\n\tclientsStore: OAuthRegisteredClientsStore,\n\tcodeStore: OAuthAuthorizationCodeStore,\n\tnow = Date.now(),\n): McpOAuthRedirectResult | McpOAuthErrorResult {\n\tconst prepared = prepareMcpOAuthAuthorizationRequest(params, clientsStore);\n\tif (\"status\" in prepared) return prepared;\n\n\tconst code = codeStore.issueCode(\n\t\t{\n\t\t\tclientId: prepared.clientId,\n\t\t\tredirectUri: prepared.redirectUri,\n\t\t\tcodeChallenge: prepared.codeChallenge,\n\t\t\tscopes: prepared.scopes,\n\t\t\t...(prepared.resource ? { resource: prepared.resource } : {}),\n\t\t\texpiresAt: now + AUTHORIZATION_CODE_TTL_MS,\n\t\t},\n\t\tnow,\n\t);\n\tif (!code)\n\t\treturn invalidOAuthRequest(\"temporarily_unavailable\", \"Too many active authorization codes\");\n\tconst redirect = new URL(prepared.redirectUri);\n\tredirect.searchParams.set(\"code\", code);\n\tif (prepared.state !== null) redirect.searchParams.set(\"state\", prepared.state);\n\treturn { status: 302, location: redirect.href };\n}\n\nexport function prepareMcpOAuthAuthorizationRequest(\n\tparams: URLSearchParams,\n\tclientsStore: OAuthRegisteredClientsStore,\n): PreparedMcpOAuthAuthorizationRequest | McpOAuthErrorResult {\n\tconst clientId = params.get(\"client_id\") ?? \"\";\n\tconst redirectUri = params.get(\"redirect_uri\") ?? \"\";\n\tconst responseType = params.get(\"response_type\") ?? \"\";\n\tconst codeChallenge = params.get(\"code_challenge\") ?? \"\";\n\tconst codeChallengeMethod = params.get(\"code_challenge_method\") ?? \"\";\n\tconst resource = params.get(\"resource\");\n\tconst scopes = parseScopeList(params.get(\"scope\"));\n\tconst state = params.get(\"state\");\n\n\tif (responseType !== \"code\") return invalidOAuthRequest(\"unsupported_response_type\");\n\tif (codeChallengeMethod !== \"S256\") {\n\t\treturn invalidOAuthRequest(\"invalid_request\", \"PKCE code_challenge_method=S256 is required\");\n\t}\n\tif (!PKCE_S256_CHALLENGE.test(codeChallenge)) {\n\t\treturn invalidOAuthRequest(\"invalid_request\", \"Valid PKCE S256 code_challenge is required\");\n\t}\n\n\tconst client = getRegisteredClient(clientsStore, clientId);\n\tif (!client) return invalidOAuthRequest(\"invalid_client\", \"Unknown OAuth client_id\");\n\tif (!client.redirect_uris.includes(redirectUri)) {\n\t\treturn invalidOAuthRequest(\"invalid_request\", \"redirect_uri is not registered for this client\");\n\t}\n\n\treturn { clientId, redirectUri, codeChallenge, scopes, resource, state };\n}\n\nexport function exchangeMcpOAuthAuthorizationCode(\n\tparams: URLSearchParams,\n\tclientsStore: OAuthRegisteredClientsStore,\n\tcodeStore: OAuthAuthorizationCodeStore,\n\ttokenStore: OAuthAccessTokenStore,\n\tnow = Date.now(),\n): McpOAuthTokenResult | McpOAuthErrorResult {\n\tif ((params.get(\"grant_type\") ?? \"\") !== \"authorization_code\") {\n\t\treturn invalidOAuthRequest(\"unsupported_grant_type\", \"Only authorization_code is supported\");\n\t}\n\n\tconst clientId = params.get(\"client_id\") ?? \"\";\n\tconst code = params.get(\"code\") ?? \"\";\n\tconst redirectUri = params.get(\"redirect_uri\") ?? \"\";\n\tconst codeVerifier = params.get(\"code_verifier\") ?? \"\";\n\tconst resource = params.get(\"resource\");\n\tconst client = getRegisteredClient(clientsStore, clientId);\n\tif (!client) return invalidOAuthRequest(\"invalid_client\", \"Unknown OAuth client_id\");\n\tif (!PKCE_VERIFIER.test(codeVerifier)) {\n\t\treturn invalidOAuthRequest(\"invalid_grant\", \"Invalid PKCE code_verifier\");\n\t}\n\n\t// Peek the authorization code without consuming it so a transient token-\n\t// store overflow (`temporarily_unavailable`) leaves the code reusable; only\n\t// permanent grant failures (expiry, client/redirect mismatch, PKCE) consume\n\t// the code. The code is finally consumed atomically with token issuance.\n\tconst record = codeStore.peekCode(code);\n\tif (!record) return invalidOAuthRequest(\"invalid_grant\", \"Invalid or already used code\");\n\tif (record.expiresAt <= now) {\n\t\tcodeStore.consumeCode(code);\n\t\treturn invalidOAuthRequest(\"invalid_grant\", \"Expired code\");\n\t}\n\tif (record.clientId !== clientId || record.redirectUri !== redirectUri) {\n\t\tcodeStore.consumeCode(code);\n\t\treturn invalidOAuthRequest(\"invalid_grant\", \"Code does not match client or redirect_uri\");\n\t}\n\tif (pkceS256(codeVerifier) !== record.codeChallenge) {\n\t\tcodeStore.consumeCode(code);\n\t\treturn invalidOAuthRequest(\"invalid_grant\", \"PKCE verification failed\");\n\t}\n\tif ((record.resource ?? null) !== (resource || null)) {\n\t\tcodeStore.consumeCode(code);\n\t\treturn invalidOAuthRequest(\"invalid_grant\", \"Code does not match resource\");\n\t}\n\n\tconst issued = tokenStore.issueToken(clientId, now, record.resource, undefined, record.scopes);\n\tif (!issued) {\n\t\t// Token-store overload is transient: leave the auth code unused so the\n\t\t// client can retry token exchange without restarting the OAuth flow.\n\t\treturn invalidOAuthRequest(\"temporarily_unavailable\", \"Too many active access tokens\");\n\t}\n\n\tconst consumed = codeStore.consumeCode(code);\n\tif (!consumed) {\n\t\ttokenStore.revokeToken(issued.token, now);\n\t\t// Lost a race with another request that consumed the code in the gap\n\t\t// between peek and consume. Treat as invalid_grant rather than issuing\n\t\t// a duplicate usable token, since the code is no longer single-use atomic.\n\t\treturn invalidOAuthRequest(\"invalid_grant\", \"Authorization code already used\");\n\t}\n\n\tconst tokens = OAuthTokensSchema.parse({\n\t\taccess_token: issued.token,\n\t\ttoken_type: \"Bearer\",\n\t\texpires_in: issued.expiresIn,\n\t});\n\treturn { status: 200, body: tokens };\n}\n\nexport function revokeMcpOAuthAccessToken(\n\tparams: URLSearchParams,\n\ttokenStore: OAuthAccessTokenStore,\n): { status: 200; body: Record<string, never> } {\n\tconst token = params.get(\"token\") ?? \"\";\n\ttokenStore.revokeToken(token);\n\treturn { status: 200, body: {} };\n}\n\nexport function normalizeMcpPublicUrl(value: string): URL {\n\tlet url: URL;\n\ttry {\n\t\turl = new URL(value);\n\t} catch {\n\t\tthrow new Error(\"Invalid MCP HTTP public URL; expected an HTTPS /mcp URL\");\n\t}\n\tif (url.protocol !== \"https:\" && !isLoopbackUrl(url)) {\n\t\tthrow new Error(\"Invalid MCP HTTP public URL; use HTTPS for non-loopback URLs\");\n\t}\n\tif (url.username || url.password || url.search || url.hash) {\n\t\tthrow new Error(\n\t\t\t\"Invalid MCP HTTP public URL; credentials, query strings, and fragments are not allowed\",\n\t\t);\n\t}\n\tif (url.pathname === \"/\") url.pathname = \"/mcp\";\n\tif (url.pathname !== \"/mcp\") {\n\t\tthrow new Error(\"Invalid MCP HTTP public URL; expected /mcp path\");\n\t}\n\treturn url;\n}\n\nfunction getOriginUrl(url: URL): URL {\n\treturn new URL(url.origin);\n}\n\nfunction validateRedirectUris(redirectUris: OAuthClientMetadata[\"redirect_uris\"]): string | null {\n\tfor (const redirectUri of redirectUris) {\n\t\tconst url = new URL(redirectUri);\n\t\tif (url.username || url.password || url.hash) return `Invalid redirect URI: ${redirectUri}`;\n\t\tif (url.href === CLAUDE_HOSTED_CALLBACK) continue;\n\t\tif (isLoopbackCallbackUrl(url)) continue;\n\t\treturn `Unsupported redirect URI: ${redirectUri}`;\n\t}\n\treturn null;\n}\n\nfunction isSupportedTokenEndpointAuthMethod(method: string | undefined): boolean {\n\treturn method === undefined || method === \"none\";\n}\n\nfunction isSupportedList(values: string[], supported: Set<string>): boolean {\n\treturn values.length > 0 && values.every((value) => supported.has(value));\n}\n\nfunction isLoopbackCallbackUrl(url: URL): boolean {\n\treturn (\n\t\turl.protocol === \"http:\" &&\n\t\tLOCAL_CALLBACK_HOSTS.has(normalizeHostname(url.hostname)) &&\n\t\turl.pathname === \"/callback\" &&\n\t\turl.search === \"\"\n\t);\n}\n\nfunction isLoopbackUrl(url: URL): boolean {\n\tconst hostname = normalizeHostname(url.hostname);\n\treturn url.protocol === \"http:\" && LOCAL_CALLBACK_HOSTS.has(hostname);\n}\n\nfunction normalizeHostname(hostname: string): string {\n\treturn hostname.replace(/^\\[(.*)]$/, \"$1\").toLowerCase();\n}\n\nfunction parseScopeList(scope: string | null | undefined): string[] {\n\treturn (\n\t\tscope\n\t\t\t?.split(/\\s+/)\n\t\t\t.map((item) => item.trim())\n\t\t\t.filter(Boolean) ?? []\n\t);\n}\n\nfunction invalidClientMetadata(description: string): McpOAuthRegistrationError {\n\treturn {\n\t\tstatus: 400,\n\t\tbody: { error: \"invalid_client_metadata\", error_description: description },\n\t};\n}\n\nfunction invalidOAuthRequest(error: string, description?: string): McpOAuthErrorResult {\n\treturn {\n\t\tstatus: 400,\n\t\tbody: description ? { error, error_description: description } : { error },\n\t};\n}\n\nfunction getRegisteredClient(\n\tclientsStore: OAuthRegisteredClientsStore,\n\tclientId: string,\n): OAuthClientInformationFull | undefined {\n\tconst client = clientsStore.getClient(clientId);\n\tif (client instanceof Promise) {\n\t\tthrow new Error(\n\t\t\t\"Asynchronous OAuth client stores are not supported by this HTTP bootstrap yet\",\n\t\t);\n\t}\n\treturn client;\n}\n\nfunction pkceS256(codeVerifier: string): string {\n\treturn createHash(\"sha256\").update(codeVerifier).digest(\"base64url\");\n}\n\n// Decode an externally-supplied access-token string into the fixed-length\n// random Buffer it represents. Rejects anything that is not a base64url-encoded\n// ACCESS_TOKEN_BYTES-length value, so invalid input never reaches the HMAC\n// signer. Returns null on any decode/length mismatch.\nfunction decodeOAuthAccessToken(serialized: string): Buffer | null {\n\tif (typeof serialized !== \"string\") return null;\n\tif (serialized.length !== ACCESS_TOKEN_BASE64URL_LENGTH) return null;\n\tif (!ACCESS_TOKEN_BASE64URL.test(serialized)) return null;\n\tconst bytes = Buffer.from(serialized, \"base64url\");\n\tif (bytes.length !== ACCESS_TOKEN_BYTES) return null;\n\treturn bytes;\n}\n\nfunction randomToken(): string {\n\treturn randomBytes(ACCESS_TOKEN_BYTES).toString(\"base64url\");\n}\n\nfunction hashSerializedOAuthToken(serialized: string, key: Buffer): string | null {\n\tconst tokenBytes = decodeOAuthAccessToken(serialized);\n\tif (!tokenBytes) return null;\n\treturn signOAuthToken(tokenBytes, key);\n}\n\nfunction hashOAuthTokenForStateFile(serialized: string): string | null {\n\tconst tokenBytes = decodeOAuthAccessToken(serialized);\n\tif (!tokenBytes) return null;\n\treturn createHash(\"sha256\").update(tokenBytes).digest(\"base64url\");\n}\n\n// Compute the HMAC-SHA256 signature of the binary access-token material using\n// the per-store random key. This is an integrity signature over a random\n// 256-bit value, not password hashing; tokens are validated by re-signing the\n// presented bytes and comparing the digest to the stored signature.\nfunction signOAuthAccessTokenBytes(material: Buffer, key: Buffer): string {\n\treturn signOAuthToken(material, key);\n}\n\nfunction signOAuthToken(material: Buffer | string, key: Buffer): string {\n\treturn createHmac(\"sha256\", key).update(material).digest(\"base64url\");\n}\n\nfunction isSameTokenHash(left: string, right: string): boolean {\n\tconst leftBuffer = Buffer.from(left);\n\tconst rightBuffer = Buffer.from(right);\n\treturn leftBuffer.length === rightBuffer.length && timingSafeEqual(leftBuffer, rightBuffer);\n}\n\nfunction isScopeSubset(requested: string[], granted: string[]): boolean {\n\tconst grantedScopes = new Set(granted);\n\treturn requested.every((scope) => grantedScopes.has(scope));\n}\n\nfunction createMetadataOnlyProvider(\n\tclientsStore: OAuthRegisteredClientsStore,\n): OAuthServerProvider {\n\treturn {\n\t\tclientsStore,\n\t\tasync authorize() {\n\t\t\tthrow new Error(\"OAuth authorize is not implemented yet\");\n\t\t},\n\t\tasync challengeForAuthorizationCode() {\n\t\t\tthrow new Error(\"OAuth token exchange is not implemented yet\");\n\t\t},\n\t\tasync exchangeAuthorizationCode() {\n\t\t\tthrow new Error(\"OAuth token exchange is not implemented yet\");\n\t\t},\n\t\tasync exchangeRefreshToken() {\n\t\t\tthrow new Error(\"OAuth refresh is not implemented yet\");\n\t\t},\n\t\tasync verifyAccessToken() {\n\t\t\tthrow new Error(\"OAuth bearer verification is not implemented yet\");\n\t\t},\n\t};\n}\n","import { createPublicKey, randomUUID, verify } from \"node:crypto\";\nimport type { OAuthRegisteredClientsStore } from \"@modelcontextprotocol/sdk/server/auth/clients.js\";\nimport {\n\ttype McpOAuthErrorResult,\n\ttype McpOAuthRedirectResult,\n\tprepareMcpOAuthAuthorizationRequest,\n} from \"./oauth.js\";\n\nexport const MCP_OIDC_ISSUER_URL_ENV = \"CODEMEM_MCP_OIDC_ISSUER_URL\";\nexport const MCP_OIDC_CLIENT_ID_ENV = \"CODEMEM_MCP_OIDC_CLIENT_ID\";\nexport const MCP_OIDC_CLIENT_SECRET_ENV = \"CODEMEM_MCP_OIDC_CLIENT_SECRET\";\nexport const MCP_OAUTH_ALLOWED_SUBJECT_ENV = \"CODEMEM_MCP_OAUTH_ALLOWED_SUBJECT\";\nexport const MCP_OAUTH_ALLOWED_EMAIL_ENV = \"CODEMEM_MCP_OAUTH_ALLOWED_EMAIL\";\n\nconst PENDING_AUTH_TTL_MS = 5 * 60 * 1000;\nconst MAX_PENDING_AUTH = 100;\nconst ID_TOKEN_CLOCK_SKEW_MS = 5 * 60 * 1000;\n\ntype JsonWebKey = Record<string, unknown>;\n\nexport interface OidcConfig {\n\tissuerUrl: string;\n\tclientId: string;\n\tclientSecret: string;\n\tallowedSubject?: string;\n\tallowedEmail?: string;\n}\n\nexport interface PendingOidcAuthorization {\n\toauthParams: string;\n\tnonce: string;\n\texpiresAt: number;\n}\n\nexport interface OidcPendingAuthorizationStore {\n\tissue(record: Omit<PendingOidcAuthorization, \"expiresAt\">, now?: number): string | undefined;\n\tconsume(state: string): PendingOidcAuthorization | undefined;\n}\n\ninterface OidcDiscoveryMetadata {\n\tissuer: string;\n\tauthorization_endpoint: string;\n\ttoken_endpoint: string;\n\tjwks_uri: string;\n}\n\ninterface OidcTokensResponse {\n\tid_token?: string;\n\terror?: string;\n\terror_description?: string;\n}\n\ninterface JwtHeader {\n\talg?: string;\n\tkid?: string;\n}\n\ninterface JwtClaims {\n\tiss?: string;\n\taud?: string | string[];\n\tazp?: string;\n\texp?: number;\n\tiat?: number;\n\tnonce?: string;\n\tsub?: string;\n\temail?: string;\n\temail_verified?: boolean;\n}\n\ninterface JsonWebKeySet {\n\tkeys?: JsonWebKey[];\n}\n\nexport class InMemoryOidcPendingAuthorizationStore implements OidcPendingAuthorizationStore {\n\treadonly #records = new Map<string, PendingOidcAuthorization>();\n\n\tissue(record: Omit<PendingOidcAuthorization, \"expiresAt\">, now = Date.now()): string | undefined {\n\t\tthis.#deleteExpired(now);\n\t\tif (this.#records.size >= MAX_PENDING_AUTH) return undefined;\n\t\tconst state = randomUUID();\n\t\tthis.#records.set(state, { ...record, expiresAt: now + PENDING_AUTH_TTL_MS });\n\t\treturn state;\n\t}\n\n\tconsume(state: string): PendingOidcAuthorization | undefined {\n\t\tconst record = this.#records.get(state);\n\t\tthis.#records.delete(state);\n\t\treturn record;\n\t}\n\n\t#deleteExpired(now: number): void {\n\t\tfor (const [state, record] of this.#records) {\n\t\t\tif (record.expiresAt <= now) this.#records.delete(state);\n\t\t}\n\t}\n}\n\nexport function createInMemoryOidcPendingAuthorizationStore(): OidcPendingAuthorizationStore {\n\treturn new InMemoryOidcPendingAuthorizationStore();\n}\n\nexport function resolveOidcConfig(env: NodeJS.ProcessEnv = process.env): OidcConfig | undefined {\n\tconst issuerUrl = env[MCP_OIDC_ISSUER_URL_ENV]?.trim();\n\tconst clientId = env[MCP_OIDC_CLIENT_ID_ENV]?.trim();\n\tconst clientSecret = env[MCP_OIDC_CLIENT_SECRET_ENV]?.trim();\n\tconst allowedSubject = env[MCP_OAUTH_ALLOWED_SUBJECT_ENV]?.trim();\n\tconst allowedEmail = env[MCP_OAUTH_ALLOWED_EMAIL_ENV]?.trim().toLowerCase();\n\tif (!issuerUrl && !clientId && !clientSecret && !allowedSubject && !allowedEmail)\n\t\treturn undefined;\n\tif (!issuerUrl || !clientId || !clientSecret) {\n\t\tthrow new Error(\"Incomplete MCP OIDC configuration\");\n\t}\n\tvalidateOidcUrl(issuerUrl, \"issuer\", { allowLoopbackHttp: true });\n\tif (!allowedSubject && !allowedEmail) {\n\t\tthrow new Error(\n\t\t\t\"MCP OIDC requires CODEMEM_MCP_OAUTH_ALLOWED_SUBJECT or CODEMEM_MCP_OAUTH_ALLOWED_EMAIL\",\n\t\t);\n\t}\n\treturn { issuerUrl, clientId, clientSecret, allowedSubject, allowedEmail };\n}\n\nexport async function beginOidcAuthorization(\n\tparams: URLSearchParams,\n\tclientsStore: OAuthRegisteredClientsStore,\n\tpendingStore: OidcPendingAuthorizationStore,\n\tconfig: OidcConfig | undefined,\n\tpublicMcpUrl: string,\n\tnow = Date.now(),\n): Promise<McpOAuthRedirectResult | McpOAuthErrorResult> {\n\tif (!config) return invalidOAuthRequest(\"temporarily_unavailable\", \"OIDC is not configured\");\n\tconst prepared = prepareMcpOAuthAuthorizationRequest(params, clientsStore);\n\tif (\"status\" in prepared) return prepared;\n\n\tconst discovery = await fetchOidcDiscovery(config.issuerUrl);\n\tconst nonce = randomUUID();\n\tconst upstreamState = pendingStore.issue({ oauthParams: params.toString(), nonce }, now);\n\tif (!upstreamState)\n\t\treturn invalidOAuthRequest(\"temporarily_unavailable\", \"Too many pending OIDC authorizations\");\n\n\tconst redirectUri = getCallbackUrl(publicMcpUrl);\n\tconst upstream = new URL(discovery.authorization_endpoint);\n\tupstream.searchParams.set(\"response_type\", \"code\");\n\tupstream.searchParams.set(\"client_id\", config.clientId);\n\tupstream.searchParams.set(\"redirect_uri\", redirectUri);\n\tupstream.searchParams.set(\"scope\", \"openid email\");\n\tupstream.searchParams.set(\"state\", upstreamState);\n\tupstream.searchParams.set(\"nonce\", nonce);\n\treturn { status: 302, location: upstream.href };\n}\n\nexport async function completeOidcAuthorization(\n\tcallbackParams: URLSearchParams,\n\tpendingStore: OidcPendingAuthorizationStore,\n\tconfig: OidcConfig,\n\tpublicMcpUrl: string,\n\tnow = Date.now(),\n): Promise<{ oauthParams: URLSearchParams } | McpOAuthErrorResult> {\n\ttry {\n\t\tconst code = callbackParams.get(\"code\") ?? \"\";\n\t\tconst state = callbackParams.get(\"state\") ?? \"\";\n\t\tif (!state) return invalidOAuthRequest(\"invalid_request\", \"Missing OIDC state\");\n\t\tconst pending = pendingStore.consume(state);\n\t\tif (!pending || pending.expiresAt <= now)\n\t\t\treturn invalidOAuthRequest(\"invalid_request\", \"Expired or unknown OIDC state\");\n\t\tif (!code) return invalidOAuthRequest(\"invalid_request\", \"Missing OIDC code\");\n\n\t\tconst discovery = await fetchOidcDiscovery(config.issuerUrl);\n\t\tconst tokens = await exchangeOidcCode(\n\t\t\tdiscovery.token_endpoint,\n\t\t\tconfig,\n\t\t\tgetCallbackUrl(publicMcpUrl),\n\t\t\tcode,\n\t\t);\n\t\tif (!tokens.id_token)\n\t\t\treturn invalidOAuthRequest(\"invalid_request\", \"OIDC token exchange failed\");\n\t\tconst claims = await validateIdToken(\n\t\t\ttokens.id_token,\n\t\t\tdiscovery,\n\t\t\tconfig.clientId,\n\t\t\tpending.nonce,\n\t\t\tnow,\n\t\t);\n\t\tif (!isAllowedIdentity(claims, config))\n\t\t\treturn invalidOAuthRequest(\"access_denied\", \"OIDC identity is not allowed\");\n\n\t\treturn { oauthParams: new URLSearchParams(pending.oauthParams) };\n\t} catch {\n\t\treturn invalidOAuthRequest(\"access_denied\", \"OIDC identity verification failed\");\n\t}\n}\n\nfunction getCallbackUrl(publicMcpUrl: string): string {\n\tconst url = new URL(publicMcpUrl);\n\treturn new URL(\"/oauth/callback\", url.origin).href;\n}\n\nasync function fetchOidcDiscovery(issuerUrl: string): Promise<OidcDiscoveryMetadata> {\n\tconst issuer = new URL(issuerUrl);\n\tif (issuer.search || issuer.hash)\n\t\tthrow new Error(\"OIDC issuer must not include query or fragment\");\n\tif (issuer.username || issuer.password)\n\t\tthrow new Error(\"OIDC issuer must not include credentials\");\n\tconst discoveryUrl = new URL(\n\t\t`${issuer.pathname.replace(/\\/$/, \"\")}/.well-known/openid-configuration`,\n\t\tissuer.origin,\n\t);\n\tconst response = await fetch(discoveryUrl);\n\tif (!response.ok) throw new Error(\"OIDC discovery request failed\");\n\tconst metadata = (await response.json()) as Partial<OidcDiscoveryMetadata>;\n\tif (metadata.issuer !== issuer.href && metadata.issuer !== issuer.href.replace(/\\/$/, \"\")) {\n\t\tthrow new Error(\"OIDC discovery issuer mismatch\");\n\t}\n\tif (!metadata.authorization_endpoint || !metadata.token_endpoint || !metadata.jwks_uri) {\n\t\tthrow new Error(\"OIDC discovery metadata is incomplete\");\n\t}\n\tconst allowLoopbackHttp = issuer.protocol === \"http:\" && isLoopbackHostname(issuer.hostname);\n\tvalidateOidcUrl(metadata.authorization_endpoint, \"authorization endpoint\", { allowLoopbackHttp });\n\tvalidateOidcUrl(metadata.token_endpoint, \"token endpoint\", { allowLoopbackHttp });\n\tvalidateOidcUrl(metadata.jwks_uri, \"JWKS URI\", { allowLoopbackHttp });\n\treturn metadata as OidcDiscoveryMetadata;\n}\n\nasync function exchangeOidcCode(\n\ttokenEndpoint: string,\n\tconfig: OidcConfig,\n\tredirectUri: string,\n\tcode: string,\n): Promise<OidcTokensResponse> {\n\tconst body = new URLSearchParams({\n\t\tgrant_type: \"authorization_code\",\n\t\tcode,\n\t\tredirect_uri: redirectUri,\n\t\tclient_id: config.clientId,\n\t\tclient_secret: config.clientSecret,\n\t});\n\tconst response = await fetch(tokenEndpoint, {\n\t\tmethod: \"POST\",\n\t\theaders: { \"content-type\": \"application/x-www-form-urlencoded\" },\n\t\tbody,\n\t});\n\tif (!response.ok) throw new Error(\"OIDC token request failed\");\n\treturn (await response.json()) as OidcTokensResponse;\n}\n\nasync function validateIdToken(\n\tidToken: string,\n\tdiscovery: OidcDiscoveryMetadata,\n\tclientId: string,\n\tnonce: string,\n\tnow: number,\n): Promise<JwtClaims> {\n\tconst [encodedHeader, encodedClaims, signature] = idToken.split(\".\");\n\tif (!encodedHeader || !encodedClaims || !signature) throw new Error(\"Invalid OIDC id_token\");\n\tconst header = parseJwtPart<JwtHeader>(encodedHeader);\n\tconst claims = parseJwtPart<JwtClaims>(encodedClaims);\n\tif (header.alg !== \"RS256\" || !header.kid) throw new Error(\"Unsupported OIDC id_token signature\");\n\tif (claims.iss !== discovery.issuer) throw new Error(\"OIDC id_token issuer mismatch\");\n\tif (!audienceIncludes(claims.aud, clientId)) throw new Error(\"OIDC id_token audience mismatch\");\n\tif (!isValidAuthorizedParty(claims.aud, claims.azp, clientId))\n\t\tthrow new Error(\"OIDC id_token authorized party mismatch\");\n\tif (typeof claims.exp !== \"number\" || !Number.isFinite(claims.exp) || claims.exp * 1000 <= now)\n\t\tthrow new Error(\"OIDC id_token is expired\");\n\tif (typeof claims.iat !== \"number\" || !Number.isFinite(claims.iat))\n\t\tthrow new Error(\"OIDC id_token issued-at time is missing\");\n\tif (claims.iat * 1000 > now + ID_TOKEN_CLOCK_SKEW_MS)\n\t\tthrow new Error(\"OIDC id_token issued-at time is in the future\");\n\tif (claims.nonce !== nonce) throw new Error(\"OIDC id_token nonce mismatch\");\n\tif (!claims.sub) throw new Error(\"OIDC id_token subject is missing\");\n\n\tconst jwksResponse = await fetch(discovery.jwks_uri);\n\tif (!jwksResponse.ok) throw new Error(\"OIDC JWKS request failed\");\n\tconst jwks = (await jwksResponse.json()) as JsonWebKeySet;\n\tconst jwk = jwks.keys?.find((key) => key.kid === header.kid && key.kty === \"RSA\");\n\tif (!jwk) throw new Error(\"OIDC signing key not found\");\n\tconst key = createPublicKey({ key: jwk, format: \"jwk\" });\n\tconst signed = `${encodedHeader}.${encodedClaims}`;\n\tconst ok = verify(\"RSA-SHA256\", Buffer.from(signed), key, Buffer.from(signature, \"base64url\"));\n\tif (!ok) throw new Error(\"OIDC id_token signature verification failed\");\n\treturn claims;\n}\n\nfunction parseJwtPart<T>(encoded: string): T {\n\treturn JSON.parse(Buffer.from(encoded, \"base64url\").toString(\"utf8\")) as T;\n}\n\nfunction audienceIncludes(audience: string | string[] | undefined, clientId: string): boolean {\n\treturn Array.isArray(audience) ? audience.includes(clientId) : audience === clientId;\n}\n\nfunction isValidAuthorizedParty(\n\taudience: string | string[] | undefined,\n\tauthorizedParty: string | undefined,\n\tclientId: string,\n): boolean {\n\tif (authorizedParty && authorizedParty !== clientId) return false;\n\treturn !Array.isArray(audience) || audience.length <= 1 || authorizedParty === clientId;\n}\n\nfunction isAllowedIdentity(claims: JwtClaims, config: OidcConfig): boolean {\n\tif (config.allowedSubject && claims.sub === config.allowedSubject) return true;\n\tif (!config.allowedEmail) return false;\n\treturn claims.email_verified === true && claims.email?.toLowerCase() === config.allowedEmail;\n}\n\nfunction validateOidcUrl(\n\tvalue: string,\n\tlabel: string,\n\toptions: { allowLoopbackHttp?: boolean } = {},\n): void {\n\tconst url = new URL(value);\n\tif (url.username || url.password) throw new Error(`OIDC ${label} must not include credentials`);\n\tif (url.protocol === \"https:\") return;\n\tif (options.allowLoopbackHttp && url.protocol === \"http:\" && isLoopbackHostname(url.hostname))\n\t\treturn;\n\tthrow new Error(`OIDC ${label} must use HTTPS`);\n}\n\nfunction isLoopbackHostname(hostname: string): boolean {\n\tconst normalized = hostname.replace(/^\\[(.*)]$/, \"$1\").toLowerCase();\n\treturn normalized === \"localhost\" || normalized === \"127.0.0.1\" || normalized === \"::1\";\n}\n\nfunction invalidOAuthRequest(error: string, description?: string): McpOAuthErrorResult {\n\treturn {\n\t\tstatus: 400,\n\t\tbody: description ? { error, error_description: description } : { error },\n\t};\n}\n","import type { OAuthRegisteredClientsStore } from \"@modelcontextprotocol/sdk/server/auth/clients.js\";\nimport {\n\tAccessDeniedError,\n\tInvalidClientError,\n\tInvalidGrantError,\n\tInvalidRequestError,\n\tInvalidTokenError,\n\tServerError,\n\tTemporarilyUnavailableError,\n\tUnsupportedResponseTypeError,\n} from \"@modelcontextprotocol/sdk/server/auth/errors.js\";\nimport type {\n\tAuthorizationParams,\n\tOAuthServerProvider,\n} from \"@modelcontextprotocol/sdk/server/auth/provider.js\";\nimport type { AuthInfo } from \"@modelcontextprotocol/sdk/server/auth/types.js\";\nimport {\n\ttype OAuthClientInformationFull,\n\ttype OAuthErrorResponse,\n\ttype OAuthTokenRevocationRequest,\n\ttype OAuthTokens,\n\tOAuthTokensSchema,\n} from \"@modelcontextprotocol/sdk/shared/auth.js\";\nimport type { Response } from \"express\";\nimport {\n\tcreateInMemoryOAuthRefreshTokenStore,\n\ttype OAuthAccessTokenStore,\n\ttype OAuthAuthorizationCodeStore,\n\ttype OAuthRefreshTokenStore,\n} from \"./oauth.js\";\nimport {\n\tbeginOidcAuthorization,\n\ttype OidcConfig,\n\ttype OidcPendingAuthorizationStore,\n} from \"./oidc.js\";\n\nexport interface MemoryOAuthServerProviderOptions {\n\tclientsStore: OAuthRegisteredClientsStore;\n\tcodeStore: OAuthAuthorizationCodeStore;\n\ttokenStore: OAuthAccessTokenStore;\n\trefreshTokenStore?: OAuthRefreshTokenStore;\n\tpublicMcpUrl: string;\n\toidc?: { config: OidcConfig; pendingStore: OidcPendingAuthorizationStore };\n\tnow?: () => number;\n}\n\n/**\n * MemoryOAuthServerProvider adapts codemem's existing in-memory stores to the\n * `@modelcontextprotocol/sdk` `OAuthServerProvider` contract so the SDK's\n * `mcpAuthRouter` and `requireBearerAuth` middleware can drive the OAuth\n * lifecycle. This class is the boundary between SDK-handled HTTP and\n * codemem-owned storage / upstream-OIDC bridging.\n *\n * Conventions encoded here:\n * - `authorize()` does NOT mint the MCP authorization code itself. It\n * persists pending state and redirects the user-agent to the upstream OIDC\n * provider. The MCP code is issued later by codemem's own /oauth/callback\n * route (wired in codemem-b20m.3) after the upstream identity is validated.\n * - PKCE is validated by the SDK token handler against the challenge returned\n * from `challengeForAuthorizationCode`. We do not re-verify here.\n * - `expiresAt` returned in `AuthInfo` is epoch SECONDS per the SDK's\n * `requireBearerAuth` expectations; the underlying store records ms.\n * - Refresh-token grants use dual-token rotation: the current token and one\n * previous token are accepted to tolerate client retry races, while older\n * replayed tokens revoke the whole grant.\n */\nexport class MemoryOAuthServerProvider implements OAuthServerProvider {\n\treadonly #clientsStore: OAuthRegisteredClientsStore;\n\treadonly #codeStore: OAuthAuthorizationCodeStore;\n\treadonly #tokenStore: OAuthAccessTokenStore;\n\treadonly #refreshTokenStore: OAuthRefreshTokenStore;\n\treadonly #publicMcpUrl: string;\n\treadonly #resourceServerUrl: string;\n\treadonly #oidc?: { config: OidcConfig; pendingStore: OidcPendingAuthorizationStore };\n\treadonly #now: () => number;\n\n\tconstructor(options: MemoryOAuthServerProviderOptions) {\n\t\tthis.#clientsStore = options.clientsStore;\n\t\tthis.#codeStore = options.codeStore;\n\t\tthis.#tokenStore = options.tokenStore;\n\t\tthis.#refreshTokenStore = options.refreshTokenStore ?? createInMemoryOAuthRefreshTokenStore();\n\t\tthis.#publicMcpUrl = options.publicMcpUrl;\n\t\tthis.#resourceServerUrl = new URL(options.publicMcpUrl).href;\n\t\tthis.#oidc = options.oidc;\n\t\tthis.#now = options.now ?? Date.now;\n\t}\n\n\tget clientsStore(): OAuthRegisteredClientsStore {\n\t\treturn this.#clientsStore;\n\t}\n\n\tasync authorize(\n\t\tclient: OAuthClientInformationFull,\n\t\tparams: AuthorizationParams,\n\t\tres: Response,\n\t): Promise<void> {\n\t\tif (!this.#oidc) {\n\t\t\tthrow new TemporarilyUnavailableError(\"OIDC is not configured\");\n\t\t}\n\t\tconst upstreamParams = buildUpstreamAuthorizationParams(client, params);\n\t\tconst result = await beginOidcAuthorization(\n\t\t\tupstreamParams,\n\t\t\tthis.#clientsStore,\n\t\t\tthis.#oidc.pendingStore,\n\t\t\tthis.#oidc.config,\n\t\t\tthis.#publicMcpUrl,\n\t\t\tthis.#now(),\n\t\t);\n\t\tif (result.status === 302) {\n\t\t\tres.redirect(302, result.location);\n\t\t\treturn;\n\t\t}\n\t\tthrow mapOAuthErrorBody(result.body);\n\t}\n\n\tasync challengeForAuthorizationCode(\n\t\t_client: OAuthClientInformationFull,\n\t\tauthorizationCode: string,\n\t): Promise<string> {\n\t\tconst record = this.#codeStore.peekCode(authorizationCode);\n\t\tif (!record) throw new InvalidGrantError(\"Invalid or already used code\");\n\t\tif (record.clientId !== _client.client_id) {\n\t\t\tthrow new InvalidGrantError(\"Code does not match client\");\n\t\t}\n\t\tif (record.expiresAt <= this.#now()) {\n\t\t\tthis.#codeStore.consumeCode(authorizationCode);\n\t\t\tthrow new InvalidGrantError(\"Expired code\");\n\t\t}\n\t\treturn record.codeChallenge;\n\t}\n\n\tasync exchangeAuthorizationCode(\n\t\tclient: OAuthClientInformationFull,\n\t\tauthorizationCode: string,\n\t\t_codeVerifier?: string,\n\t\tredirectUri?: string,\n\t\tresource?: URL,\n\t): Promise<OAuthTokens> {\n\t\tconst now = this.#now();\n\t\tconst record = this.#codeStore.peekCode(authorizationCode);\n\t\tif (!record) throw new InvalidGrantError(\"Invalid or already used code\");\n\t\tif (record.expiresAt <= now) {\n\t\t\tthis.#codeStore.consumeCode(authorizationCode);\n\t\t\tthrow new InvalidGrantError(\"Expired code\");\n\t\t}\n\t\tif (record.clientId !== client.client_id) {\n\t\t\tthis.#codeStore.consumeCode(authorizationCode);\n\t\t\tthrow new InvalidGrantError(\"Code does not match client\");\n\t\t}\n\t\t// RFC 6749 §4.1.3: if the authorization request included redirect_uri,\n\t\t// the token request MUST include the same value. codemem always binds a\n\t\t// redirect_uri at /authorize, so a missing value at /token is always a\n\t\t// grant mismatch, not an optional check.\n\t\tif (redirectUri === undefined || record.redirectUri !== redirectUri) {\n\t\t\tthis.#codeStore.consumeCode(authorizationCode);\n\t\t\tthrow new InvalidGrantError(\"Code does not match redirect_uri\");\n\t\t}\n\t\tif ((record.resource ?? null) !== (resource?.href ?? null)) {\n\t\t\tthis.#codeStore.consumeCode(authorizationCode);\n\t\t\tthrow new InvalidGrantError(\"Code does not match resource\");\n\t\t}\n\n\t\tconst scopes = normalizeClientScopes(record.scopes) ?? [];\n\t\tconst grant = this.#refreshTokenStore.issueGrant(\n\t\t\t{ clientId: client.client_id, scopes, resource: record.resource },\n\t\t\tnow,\n\t\t);\n\t\tif (!grant) {\n\t\t\tthrow new TemporarilyUnavailableError(\"Too many active refresh grants\");\n\t\t}\n\t\tconst issued = this.#tokenStore.issueToken(\n\t\t\tclient.client_id,\n\t\t\tnow,\n\t\t\trecord.resource,\n\t\t\tgrant.grant.grantId,\n\t\t\tscopes,\n\t\t);\n\t\tif (!issued) {\n\t\t\t// Token-store overload is transient: leave the auth code unused so the\n\t\t\t// client can retry token exchange without restarting the OAuth flow.\n\t\t\tthis.#refreshTokenStore.revokeGrant(grant.grant.grantId, now);\n\t\t\tthrow new TemporarilyUnavailableError(\"Too many active access tokens\");\n\t\t}\n\n\t\tconst consumed = this.#codeStore.consumeCode(authorizationCode);\n\t\tif (!consumed) {\n\t\t\tthis.#tokenStore.revokeToken(issued.token, now);\n\t\t\tthis.#refreshTokenStore.revokeGrant(grant.grant.grantId, now);\n\t\t\t// Lost a race with a concurrent exchange that consumed the code in\n\t\t\t// the gap between peek and consume. Reject rather than issuing a\n\t\t\t// duplicate usable token.\n\t\t\tthrow new InvalidGrantError(\"Authorization code already used\");\n\t\t}\n\n\t\treturn OAuthTokensSchema.parse({\n\t\t\taccess_token: issued.token,\n\t\t\ttoken_type: \"Bearer\",\n\t\t\texpires_in: issued.expiresIn,\n\t\t\trefresh_token: grant.refreshToken,\n\t\t});\n\t}\n\n\tasync exchangeRefreshToken(\n\t\tclient: OAuthClientInformationFull,\n\t\trefreshToken: string,\n\t\tscopes?: string[],\n\t\tresource?: URL,\n\t): Promise<OAuthTokens> {\n\t\tconst now = this.#now();\n\t\tconst rotation = this.#refreshTokenStore.rotateRefreshToken(\n\t\t\tclient.client_id,\n\t\t\trefreshToken,\n\t\t\t{ scopes: normalizeClientScopes(scopes), ...(resource ? { resource: resource.href } : {}) },\n\t\t\tnow,\n\t\t);\n\t\tif (!rotation.ok) {\n\t\t\tif (rotation.reason === \"refresh_token_replay\" && rotation.grantId) {\n\t\t\t\tthis.#tokenStore.revokeTokensForGrant?.(rotation.grantId, now);\n\t\t\t}\n\t\t\tthrow new InvalidGrantError(refreshTokenErrorDescription(rotation.reason));\n\t\t}\n\t\tconst issued = this.#tokenStore.issueToken(\n\t\t\tclient.client_id,\n\t\t\tnow,\n\t\t\trotation.grant.resource,\n\t\t\trotation.grant.grantId,\n\t\t\trotation.grant.scopes,\n\t\t);\n\t\tif (!issued) throw new TemporarilyUnavailableError(\"Too many active access tokens\");\n\t\treturn OAuthTokensSchema.parse({\n\t\t\taccess_token: issued.token,\n\t\t\ttoken_type: \"Bearer\",\n\t\t\texpires_in: issued.expiresIn,\n\t\t\trefresh_token: rotation.refreshToken,\n\t\t});\n\t}\n\n\tasync verifyAccessToken(token: string): Promise<AuthInfo> {\n\t\tconst result = this.#tokenStore.verifyToken(token, this.#now());\n\t\tif (!result.ok) {\n\t\t\tconst reason =\n\t\t\t\tresult.reason === \"expired_token\"\n\t\t\t\t\t? \"Token has expired\"\n\t\t\t\t\t: result.reason === \"revoked_token\"\n\t\t\t\t\t\t? \"Token has been revoked\"\n\t\t\t\t\t\t: \"Token is invalid\";\n\t\t\tthrow new InvalidTokenError(reason);\n\t\t}\n\t\tconst authInfo: AuthInfo = {\n\t\t\ttoken,\n\t\t\tclientId: result.record.clientId,\n\t\t\tscopes: result.record.scopes,\n\t\t\texpiresAt: Math.floor(result.record.expiresAt / 1000),\n\t\t};\n\t\tif (result.record.resource) {\n\t\t\tif (new URL(result.record.resource).href !== this.#resourceServerUrl) {\n\t\t\t\tthrow new InvalidTokenError(\"Token audience does not match this resource server\");\n\t\t\t}\n\t\t\tauthInfo.resource = new URL(result.record.resource);\n\t\t}\n\t\treturn authInfo;\n\t}\n\n\tasync revokeToken(\n\t\t_client: OAuthClientInformationFull,\n\t\trequest: OAuthTokenRevocationRequest,\n\t): Promise<void> {\n\t\tconst now = this.#now();\n\t\tthis.#tokenStore.revokeToken(request.token, now);\n\t\tconst grantId = this.#refreshTokenStore.revokeRefreshToken(request.token, now);\n\t\tif (grantId) this.#tokenStore.revokeTokensForGrant?.(grantId, now);\n\t}\n}\n\nfunction buildUpstreamAuthorizationParams(\n\tclient: OAuthClientInformationFull,\n\tparams: AuthorizationParams,\n): URLSearchParams {\n\tconst upstream = new URLSearchParams();\n\tupstream.set(\"client_id\", client.client_id);\n\tupstream.set(\"redirect_uri\", params.redirectUri);\n\tupstream.set(\"response_type\", \"code\");\n\tupstream.set(\"code_challenge\", params.codeChallenge);\n\tupstream.set(\"code_challenge_method\", \"S256\");\n\tif (params.state) upstream.set(\"state\", params.state);\n\tif (params.scopes?.length) upstream.set(\"scope\", params.scopes.join(\" \"));\n\tif (params.resource) upstream.set(\"resource\", params.resource.href);\n\treturn upstream;\n}\n\nfunction mapOAuthErrorBody(body: OAuthErrorResponse): Error {\n\tconst description = body.error_description ?? body.error;\n\tswitch (body.error) {\n\t\tcase \"temporarily_unavailable\":\n\t\t\treturn new TemporarilyUnavailableError(description);\n\t\tcase \"invalid_request\":\n\t\t\treturn new InvalidRequestError(description);\n\t\tcase \"invalid_client\":\n\t\t\treturn new InvalidClientError(description);\n\t\tcase \"access_denied\":\n\t\t\treturn new AccessDeniedError(description);\n\t\tcase \"unsupported_response_type\":\n\t\t\treturn new UnsupportedResponseTypeError(description);\n\t\tdefault:\n\t\t\treturn new ServerError(description);\n\t}\n}\n\nfunction refreshTokenErrorDescription(reason: string): string {\n\tswitch (reason) {\n\t\tcase \"expired_refresh_token\":\n\t\t\treturn \"Refresh token has expired\";\n\t\tcase \"revoked_refresh_token\":\n\t\t\treturn \"Refresh token has been revoked\";\n\t\tcase \"client_mismatch\":\n\t\t\treturn \"Refresh token does not match client\";\n\t\tcase \"scope_mismatch\":\n\t\t\treturn \"Refresh token scope cannot be expanded\";\n\t\tcase \"resource_mismatch\":\n\t\t\treturn \"Refresh token does not match resource\";\n\t\tcase \"refresh_token_replay\":\n\t\t\treturn \"Refresh token replay detected\";\n\t\tdefault:\n\t\t\treturn \"Invalid refresh token\";\n\t}\n}\n\nfunction normalizeClientScopes(scopes: string[] | undefined): string[] | undefined {\n\tconst normalized = scopes\n\t\t?.map((scope) => scope.trim())\n\t\t.filter(Boolean)\n\t\t.map((scope) => {\n\t\t\tif (scope === \"memory:read_access\") return \"memory:read\";\n\t\t\tif (scope === \"memory:write_access\") return \"memory:write\";\n\t\t\treturn scope;\n\t\t});\n\treturn normalized && normalized.length > 0 ? normalized : undefined;\n}\n","#!/usr/bin/env node\n\n/**\n * @codemem/mcp — MCP Streamable HTTP server bootstrap.\n *\n * Local-first HTTP transport for MCP clients. OAuth metadata and Dynamic Client\n * Registration are exposed for remote MCP setup; public MCP requests require\n * OAuth bearer tokens.\n */\n\nimport { createServer, type IncomingMessage, type Server } from \"node:http\";\nimport { isIP } from \"node:net\";\nimport { pathToFileURL } from \"node:url\";\nimport { MemoryStore, resolveDbPath } from \"@codemem/core\";\nimport { requireBearerAuth } from \"@modelcontextprotocol/sdk/server/auth/middleware/bearerAuth.js\";\nimport {\n\tgetOAuthProtectedResourceMetadataUrl,\n\tmcpAuthRouter,\n} from \"@modelcontextprotocol/sdk/server/auth/router.js\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StreamableHTTPServerTransport } from \"@modelcontextprotocol/sdk/server/streamableHttp.js\";\nimport express, { type NextFunction, type Request, type Response } from \"express\";\nimport { rateLimit } from \"express-rate-limit\";\nimport {\n\ttype BearerDenyReason,\n\tbuildOAuthAuditEvent,\n\ttype OAuthAuditEmitter,\n\tresolveOAuthAuditEmitterFromEnv,\n\twrapAuditEmitterBestEffort,\n} from \"./audit.js\";\nimport {\n\tcreateInMemoryOAuthAccessTokenStore,\n\tcreateInMemoryOAuthAuthorizationCodeStore,\n\tcreateInMemoryOAuthClientsStore,\n\tcreateJsonFileOAuthStateStore,\n\tcreateMcpOAuthMetadata,\n\tcreateMcpProtectedResourceMetadata,\n\tMCP_OAUTH_PUBLIC_URL_ENV,\n\tMCP_OAUTH_RESOURCE_NAME,\n\tMCP_OAUTH_SCOPES_SUPPORTED,\n\tMCP_OAUTH_SERVICE_DOCUMENTATION_URL,\n\tnormalizeMcpPublicUrl,\n\ttype OAuthAccessTokenStore,\n} from \"./oauth.js\";\nimport {\n\tcompleteOidcAuthorization,\n\tcreateInMemoryOidcPendingAuthorizationStore,\n\tresolveOidcConfig,\n} from \"./oidc.js\";\nimport { MemoryOAuthServerProvider } from \"./provider.js\";\nimport { createCodememMcpServer } from \"./server.js\";\n\nexport const DEFAULT_MCP_HTTP_HOST = \"127.0.0.1\";\nexport const DEFAULT_MCP_HTTP_PORT = 38889;\nconst HTTP_DEFAULT_PORT = 80;\nconst TRUSTED_PUBLIC_BROWSER_ORIGINS = new Set([\"https://claude.ai\"]);\nconst CORS_ALLOW_HEADERS = \"authorization,content-type,mcp-session-id\";\nconst CORS_MAX_AGE_SECONDS = \"600\";\nconst MAX_GUARD_LOG_FIELD_LENGTH = 256;\nconst PUBLIC_MCP_RATE_LIMIT_WINDOW_MS = 15 * 60 * 1000;\nconst PUBLIC_MCP_RATE_LIMIT_REQUESTS = 600;\n\nconst VALID_HOSTNAME = /^[a-zA-Z0-9.-]+$/;\nconst LOOPBACK_HOSTS = new Set([\"127.0.0.1\", \"::1\", \"localhost\"]);\n\ninterface ActiveRequest {\n\tmcpServer: McpServer;\n}\n\nexport interface CodememMcpHttpOptions {\n\thost?: string;\n\tport?: number | string;\n\tdbPath?: string;\n\tallowUnsafePublic?: boolean;\n\tpublicUrl?: string;\n\toauthAccessTokenStore?: OAuthAccessTokenStore;\n\toauthStatePath?: string;\n\tauditEmitter?: OAuthAuditEmitter;\n}\n\nexport interface CodememMcpHttpServer {\n\tserver: Server;\n\tstore: MemoryStore;\n\turl: string;\n\tclose: () => Promise<void>;\n}\n\nexport function validateMcpHttpHost(host: string | undefined, allowUnsafePublic = false): string {\n\tconst value = host?.trim() || DEFAULT_MCP_HTTP_HOST;\n\tif (value.includes(\"://\") || value.includes(\"/\") || value.includes(\"\\\\\")) {\n\t\tthrow new Error(`Invalid MCP HTTP host: ${host}`);\n\t}\n\tif (!(isIP(value) || value === \"localhost\" || VALID_HOSTNAME.test(value))) {\n\t\tthrow new Error(`Invalid MCP HTTP host: ${host}`);\n\t}\n\tif (!allowUnsafePublic && !isLoopbackHost(value)) {\n\t\tthrow new Error(\n\t\t\t`Refusing unsafe MCP HTTP host ${value}; set CODEMEM_MCP_HTTP_UNSAFE_PUBLIC=1 to allow non-loopback binding`,\n\t\t);\n\t}\n\treturn value;\n}\n\nexport function isLoopbackHost(host: string): boolean {\n\treturn LOOPBACK_HOSTS.has(normalizeHost(host));\n}\n\nexport function isUnsafePublicBindAllowed(\n\tvalue = process.env.CODEMEM_MCP_HTTP_UNSAFE_PUBLIC,\n): boolean {\n\treturn value === \"1\" || value?.toLowerCase() === \"true\" || value?.toLowerCase() === \"yes\";\n}\n\nexport function isAllowedMcpHttpRequestHost(\n\theader: string | undefined,\n\texpectedPort: number,\n): boolean {\n\tconst parsed = parseHostHeader(header);\n\tif (!parsed) return false;\n\tif (!isLoopbackHost(parsed.host)) return false;\n\tif (parsed.port === null) {\n\t\t// No `:port` in the Host header means the client is using the protocol\n\t\t// default. This server is plain HTTP, so the implied port is 80. Only\n\t\t// accept the bare-host form when the bound port is also 80.\n\t\treturn expectedPort === HTTP_DEFAULT_PORT;\n\t}\n\treturn parsed.port === expectedPort;\n}\n\nexport function isAllowedMcpHttpRequestOrigin(\n\theader: string | undefined,\n\texpectedPort: number,\n): boolean {\n\tif (!header) return true;\n\ttry {\n\t\tconst url = new URL(header);\n\t\tconst port = url.port ? Number(url.port) : url.protocol === \"https:\" ? 443 : 80;\n\t\treturn (\n\t\t\t(url.protocol === \"http:\" || url.protocol === \"https:\") &&\n\t\t\turl.username === \"\" &&\n\t\t\turl.password === \"\" &&\n\t\t\turl.pathname === \"/\" &&\n\t\t\turl.search === \"\" &&\n\t\t\turl.hash === \"\" &&\n\t\t\tisLoopbackHost(url.hostname) &&\n\t\t\tport === expectedPort\n\t\t);\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nexport function isAllowedMcpHttpRequestRemoteAddress(address: string | undefined): boolean {\n\tif (!address) return false;\n\treturn isLoopbackHost(address.replace(/^::ffff:/, \"\"));\n}\n\nfunction normalizeHost(host: string): string {\n\treturn host.replace(/^\\[(.*)]$/, \"$1\").toLowerCase();\n}\n\nfunction parseHostHeader(header: string | undefined): { host: string; port: number | null } | null {\n\tif (!header) return null;\n\tif (header.startsWith(\"[\")) {\n\t\t// Bracketed IPv6: `[::1]` or `[::1]:8080`.\n\t\tconst withPort = /^\\[([^\\]]+)]:(\\d+)$/.exec(header);\n\t\tif (withPort?.[1] && withPort[2]) {\n\t\t\treturn { host: withPort[1], port: Number(withPort[2]) };\n\t\t}\n\t\tconst bareIpv6 = /^\\[([^\\]]+)]$/.exec(header);\n\t\tif (bareIpv6?.[1]) return { host: bareIpv6[1], port: null };\n\t\treturn null;\n\t}\n\tconst lastColon = header.lastIndexOf(\":\");\n\tif (lastColon < 0) {\n\t\t// RFC-compliant clients may omit `:port` on default-port requests. Treat\n\t\t// the implied port as \"use the protocol default\" and let the caller\n\t\t// reconcile against the actually bound port.\n\t\treturn { host: header, port: null };\n\t}\n\tconst host = header.slice(0, lastColon);\n\tconst port = Number(header.slice(lastColon + 1));\n\tif (!Number.isInteger(port)) return null;\n\treturn { host, port };\n}\n\nexport function parseMcpHttpPort(port: number | string | undefined): number {\n\tif (port === undefined || port === \"\") return DEFAULT_MCP_HTTP_PORT;\n\tconst value = typeof port === \"number\" ? port : Number(port);\n\tif (!Number.isInteger(value) || value < 0 || value > 65_535) {\n\t\tthrow new Error(`Invalid MCP HTTP port: ${port}`);\n\t}\n\treturn value;\n}\n\nexport async function startCodememMcpHttpServer(\n\toptions: CodememMcpHttpOptions = {},\n): Promise<CodememMcpHttpServer> {\n\tconst host = validateMcpHttpHost(\n\t\toptions.host ?? process.env.CODEMEM_MCP_HTTP_HOST,\n\t\toptions.allowUnsafePublic ?? isUnsafePublicBindAllowed(),\n\t);\n\tconst port = parseMcpHttpPort(options.port ?? process.env.CODEMEM_MCP_HTTP_PORT);\n\tconst configuredPublicUrl = options.publicUrl ?? process.env[MCP_OAUTH_PUBLIC_URL_ENV];\n\tconst configuredPublicMcpUrl = configuredPublicUrl\n\t\t? normalizeMcpPublicUrl(configuredPublicUrl)\n\t\t: undefined;\n\tconst store = new MemoryStore(options.dbPath ?? resolveDbPath());\n\tconst oauthStateStore = options.oauthAccessTokenStore\n\t\t? undefined\n\t\t: createJsonFileOAuthStateStore(options.oauthStatePath);\n\tconst clientsStore = oauthStateStore ?? createInMemoryOAuthClientsStore();\n\tconst codeStore = oauthStateStore ?? createInMemoryOAuthAuthorizationCodeStore();\n\tconst tokenStore =\n\t\toptions.oauthAccessTokenStore ?? oauthStateStore ?? createInMemoryOAuthAccessTokenStore();\n\tconst oidcConfig = resolveOidcConfig();\n\tconst oidcPendingStore = createInMemoryOidcPendingAuthorizationStore();\n\tconst shouldRequireMcpBearer = configuredPublicMcpUrl !== undefined || oidcConfig !== undefined;\n\tconst auditEmit = wrapAuditEmitterBestEffort(\n\t\toptions.auditEmitter ?? resolveOAuthAuditEmitterFromEnv(),\n\t);\n\tconst activeRequests = new Set<ActiveRequest>();\n\tlet closePromise: Promise<void> | null = null;\n\n\tconst app = express();\n\tapp.disable(\"x-powered-by\");\n\t// Tailscale Funnel and similar local ingress proxies forward from loopback and\n\t// add X-Forwarded-For. Trust only loopback proxy hops so SDK rate limiters can\n\t// key on the real client IP without making public clients spoofable.\n\tapp.set(\"trust proxy\", \"loopback\");\n\tconst server = createServer(app);\n\n\tawait new Promise<void>((resolve, reject) => {\n\t\tserver.once(\"error\", reject);\n\t\tserver.listen({ host, port }, () => {\n\t\t\tserver.off(\"error\", reject);\n\t\t\tresolve();\n\t\t});\n\t});\n\n\tconst publicMcpUrl = configuredPublicMcpUrl?.href ?? getServerUrl(server, host);\n\tconst publicMcpUrlObject = new URL(publicMcpUrl);\n\tconst issuerUrl = getSdkIssuerUrl(publicMcpUrlObject, getBoundPort(server));\n\tconst provider = new MemoryOAuthServerProvider({\n\t\tclientsStore,\n\t\tcodeStore,\n\t\ttokenStore,\n\t\tpublicMcpUrl,\n\t\t...(oauthStateStore ? { refreshTokenStore: oauthStateStore } : {}),\n\t\t...(oidcConfig ? { oidc: { config: oidcConfig, pendingStore: oidcPendingStore } } : {}),\n\t});\n\tconst resourceMetadataUrl = getOAuthProtectedResourceMetadataUrl(publicMcpUrlObject);\n\n\tapp.use(\n\t\trateLimit({\n\t\t\twindowMs: PUBLIC_MCP_RATE_LIMIT_WINDOW_MS,\n\t\t\tlimit: PUBLIC_MCP_RATE_LIMIT_REQUESTS,\n\t\t\tstandardHeaders: \"draft-8\",\n\t\t\tlegacyHeaders: false,\n\t\t\t// Avoid express-rate-limit's default IPv6 subnet helper here: its current\n\t\t\t// transitive ip-address API throws on IPv6 loopback in our Node 24 test path.\n\t\t\t// This coarse limiter is defense-in-depth before the SDK OAuth limiters and\n\t\t\t// the Host/Origin guard; it must never break local IPv6 metadata requests.\n\t\t\tipv6Subnet: false,\n\t\t}),\n\t);\n\tapp.use((req, res, next) => {\n\t\tconst boundPort = getBoundPort(server);\n\t\tconst pathname = normalizeRoutePath(req.path);\n\t\tif (pathname === \"/mcp\") {\n\t\t\tif (isAllowedMcpHttpRequest(req, boundPort, configuredPublicMcpUrl)) {\n\t\t\t\tapplyPublicCorsHeaders(req, res, configuredPublicMcpUrl);\n\t\t\t\tif (req.method === \"OPTIONS\") {\n\t\t\t\t\tres.status(204).send(\"\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\treturn next();\n\t\t\t}\n\t\t\temitHttpGuardDeny(req, pathname, configuredPublicMcpUrl);\n\t\t\tres.status(403).type(\"text/plain\").send(\"Forbidden\");\n\t\t\treturn;\n\t\t}\n\t\tif (isOAuthOrMetadataPath(pathname)) {\n\t\t\tif (isAllowedOAuthHttpRequest(req, boundPort, configuredPublicMcpUrl)) {\n\t\t\t\tapplyPublicCorsHeaders(req, res, configuredPublicMcpUrl);\n\t\t\t\tif (req.method === \"OPTIONS\") {\n\t\t\t\t\tres.status(204).send(\"\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\treturn next();\n\t\t\t}\n\t\t\temitHttpGuardDeny(req, pathname, configuredPublicMcpUrl);\n\t\t\tres.status(403).type(\"text/plain\").send(\"Forbidden\");\n\t\t\treturn;\n\t\t}\n\t\tnext();\n\t});\n\n\tapp.use(auditOAuthRouteResponses(auditEmit));\n\n\tapp.get(\"/oauth/callback\", async (req, res) => {\n\t\tconst remoteAddress = req.socket.remoteAddress ?? undefined;\n\t\tif (!oidcConfig) {\n\t\t\tauditEmit(\n\t\t\t\tbuildOAuthAuditEvent(\"oidc_callback\", {\n\t\t\t\t\toutcome: \"denied\",\n\t\t\t\t\treason: \"oidc_not_configured\",\n\t\t\t\t\tremoteAddress,\n\t\t\t\t}),\n\t\t\t);\n\t\t\tres.status(400).json({\n\t\t\t\terror: \"temporarily_unavailable\",\n\t\t\t\terror_description: \"OIDC is not configured\",\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\tconst completed = await completeOidcAuthorization(\n\t\t\tnew URLSearchParams(req.query as Record<string, string>),\n\t\t\toidcPendingStore,\n\t\t\toidcConfig,\n\t\t\tpublicMcpUrl,\n\t\t);\n\t\tif (\"status\" in completed) {\n\t\t\tauditEmit(\n\t\t\t\tbuildOAuthAuditEvent(\"oidc_callback\", {\n\t\t\t\t\toutcome: \"denied\",\n\t\t\t\t\treason: completed.body.error,\n\t\t\t\t\tremoteAddress,\n\t\t\t\t}),\n\t\t\t);\n\t\t\tres.status(completed.status).json(completed.body);\n\t\t\treturn;\n\t\t}\n\t\tconst oauthClientId = completed.oauthParams.get(\"client_id\") ?? undefined;\n\t\tconst code = codeStore.issueCode({\n\t\t\tclientId: completed.oauthParams.get(\"client_id\") ?? \"\",\n\t\t\tredirectUri: completed.oauthParams.get(\"redirect_uri\") ?? \"\",\n\t\t\tcodeChallenge: completed.oauthParams.get(\"code_challenge\") ?? \"\",\n\t\t\tscopes: parseScopeList(completed.oauthParams.get(\"scope\")),\n\t\t\t...(completed.oauthParams.get(\"resource\")\n\t\t\t\t? { resource: completed.oauthParams.get(\"resource\") ?? undefined }\n\t\t\t\t: {}),\n\t\t\texpiresAt: Date.now() + 5 * 60 * 1000,\n\t\t});\n\t\tif (!code) {\n\t\t\tauditEmit(\n\t\t\t\tbuildOAuthAuditEvent(\"oidc_callback\", {\n\t\t\t\t\toutcome: \"denied\",\n\t\t\t\t\treason: \"temporarily_unavailable\",\n\t\t\t\t\tclientId: oauthClientId,\n\t\t\t\t\tremoteAddress,\n\t\t\t\t}),\n\t\t\t);\n\t\t\tres.status(400).json({\n\t\t\t\terror: \"temporarily_unavailable\",\n\t\t\t\terror_description: \"Too many active authorization codes\",\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\tconst redirect = new URL(completed.oauthParams.get(\"redirect_uri\") ?? \"\");\n\t\tredirect.searchParams.set(\"code\", code);\n\t\tconst state = completed.oauthParams.get(\"state\");\n\t\tif (state) redirect.searchParams.set(\"state\", state);\n\t\tauditEmit(\n\t\t\tbuildOAuthAuditEvent(\"oidc_callback\", {\n\t\t\t\toutcome: \"success\",\n\t\t\t\treason: \"code_issued\",\n\t\t\t\tclientId: oauthClientId,\n\t\t\t\tremoteAddress,\n\t\t\t}),\n\t\t);\n\t\tres.redirect(302, redirect.href);\n\t});\n\n\tapp.get(\"/.well-known/oauth-authorization-server\", (_req, res) => {\n\t\tres.status(200).json(createMcpOAuthMetadata({ mcpUrl: publicMcpUrl, clientsStore }));\n\t});\n\tapp.get(\"/.well-known/oauth-protected-resource/mcp\", (_req, res) => {\n\t\tres.status(200).json(createMcpProtectedResourceMetadata(publicMcpUrl));\n\t});\n\n\tapp.use(\n\t\tmcpAuthRouter({\n\t\t\tprovider,\n\t\t\tissuerUrl,\n\t\t\tbaseUrl: issuerUrl,\n\t\t\tresourceServerUrl: publicMcpUrlObject,\n\t\t\tresourceName: MCP_OAUTH_RESOURCE_NAME,\n\t\t\tscopesSupported: MCP_OAUTH_SCOPES_SUPPORTED,\n\t\t\tserviceDocumentationUrl: new URL(MCP_OAUTH_SERVICE_DOCUMENTATION_URL),\n\t\t\tclientRegistrationOptions: { clientSecretExpirySeconds: 0 },\n\t\t}),\n\t);\n\n\tconst bearerMiddleware = shouldRequireMcpBearer\n\t\t? requireBearerAuth({ verifier: provider, resourceMetadataUrl })\n\t\t: (_req: Request, _res: Response, next: NextFunction) => next();\n\tconst bearerAuditMiddleware = shouldRequireMcpBearer\n\t\t? auditBearerPreflight(auditEmit, tokenStore)\n\t\t: (_req: Request, _res: Response, next: NextFunction) => next();\n\tapp.post(\"/mcp\", bearerAuditMiddleware, bearerMiddleware, async (req, res) => {\n\t\tif (req.auth) {\n\t\t\tauditEmit(\n\t\t\t\tbuildOAuthAuditEvent(\"bearer\", {\n\t\t\t\t\toutcome: \"success\",\n\t\t\t\t\tclientId: req.auth.clientId,\n\t\t\t\t\tremoteAddress: req.socket.remoteAddress ?? undefined,\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t\tconst mcpServer = createCodememMcpServer(store);\n\t\tconst transport = new StreamableHTTPServerTransport({ sessionIdGenerator: undefined });\n\t\tconst activeRequest = { mcpServer };\n\t\tactiveRequests.add(activeRequest);\n\t\ttry {\n\t\t\tawait mcpServer.connect(transport);\n\t\t\tawait transport.handleRequest(req, res);\n\t\t} finally {\n\t\t\tactiveRequests.delete(activeRequest);\n\t\t\tawait mcpServer.close();\n\t\t}\n\t});\n\tapp.all(\"/mcp\", (_req, res) => {\n\t\tres.setHeader(\"Allow\", \"POST\");\n\t\tres.status(405).type(\"text/plain\").send(\"Method not allowed\");\n\t});\n\tapp.use((_req, res) => {\n\t\tres.status(404).type(\"text/plain\").send(\"Not found\");\n\t});\n\n\tconst close = () => {\n\t\tclosePromise ??= (async () => {\n\t\t\tawait Promise.allSettled([...activeRequests].map(({ mcpServer }) => mcpServer.close()));\n\t\t\tawait new Promise<void>((resolve, reject) => {\n\t\t\t\tserver.close((err) => {\n\t\t\t\t\tif (!err || (err as NodeJS.ErrnoException).code === \"ERR_SERVER_NOT_RUNNING\") {\n\t\t\t\t\t\tresolve();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\treject(err);\n\t\t\t\t});\n\t\t\t\tserver.closeAllConnections();\n\t\t\t});\n\t\t\tstore.close();\n\t\t})();\n\t\treturn closePromise;\n\t};\n\n\treturn {\n\t\tserver,\n\t\tstore,\n\t\turl: `http://${formatHostForUrl(host)}:${getBoundPort(server)}/mcp`,\n\t\tclose,\n\t};\n}\n\nfunction isAllowedMcpHttpRequest(\n\treq: IncomingMessage,\n\texpectedPort: number,\n\tpublicMcpUrl: URL | undefined,\n): boolean {\n\tif (isAllowedLocalMcpHttpRequest(req, expectedPort)) return true;\n\tif (!publicMcpUrl) return false;\n\treturn (\n\t\tisAllowedPublicRequestHost(req.headers.host, publicMcpUrl) &&\n\t\tisAllowedPublicOrigin(req.headers.origin, publicMcpUrl)\n\t);\n}\n\nfunction isAllowedLocalMcpHttpRequest(req: IncomingMessage, expectedPort: number): boolean {\n\treturn (\n\t\tisAllowedMcpHttpRequestRemoteAddress(req.socket.remoteAddress) &&\n\t\tisAllowedMcpHttpRequestHost(req.headers.host, expectedPort) &&\n\t\tisAllowedMcpHttpRequestOrigin(req.headers.origin, expectedPort)\n\t);\n}\n\nfunction isAllowedOAuthHttpRequest(\n\treq: IncomingMessage,\n\texpectedPort: number,\n\tpublicMcpUrl: URL | undefined,\n): boolean {\n\tif (isAllowedLocalMcpHttpRequest(req, expectedPort)) return true;\n\tif (!publicMcpUrl) return false;\n\treturn (\n\t\tisAllowedPublicRequestHost(req.headers.host, publicMcpUrl) &&\n\t\tisAllowedPublicOrigin(req.headers.origin, publicMcpUrl)\n\t);\n}\n\nfunction isAllowedPublicOrigin(header: string | undefined, publicMcpUrl: URL): boolean {\n\tif (!header) return true;\n\ttry {\n\t\tconst origin = new URL(header);\n\t\treturn (\n\t\t\torigin.origin === publicMcpUrl.origin || TRUSTED_PUBLIC_BROWSER_ORIGINS.has(origin.origin)\n\t\t);\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nfunction applyPublicCorsHeaders(\n\treq: IncomingMessage,\n\tres: Response,\n\tpublicMcpUrl: URL | undefined,\n): void {\n\tif (!publicMcpUrl) return;\n\tconst origin = getAllowedPublicCorsOrigin(req.headers.origin, publicMcpUrl);\n\tif (!origin) return;\n\tres.setHeader(\"Access-Control-Allow-Origin\", origin);\n\tres.setHeader(\"Access-Control-Allow-Methods\", \"GET,POST,OPTIONS\");\n\tres.setHeader(\n\t\t\"Access-Control-Allow-Headers\",\n\t\treq.headers[\"access-control-request-headers\"] ?? CORS_ALLOW_HEADERS,\n\t);\n\tres.setHeader(\"Access-Control-Max-Age\", CORS_MAX_AGE_SECONDS);\n\tres.setHeader(\"Vary\", \"Origin\");\n}\n\nfunction getAllowedPublicCorsOrigin(\n\theader: string | undefined,\n\tpublicMcpUrl: URL,\n): string | undefined {\n\tif (!header) return undefined;\n\ttry {\n\t\tconst origin = new URL(header).origin;\n\t\tif (origin === publicMcpUrl.origin || TRUSTED_PUBLIC_BROWSER_ORIGINS.has(origin)) {\n\t\t\treturn origin;\n\t\t}\n\t} catch {\n\t\treturn undefined;\n\t}\n\treturn undefined;\n}\n\nfunction emitHttpGuardDeny(\n\treq: IncomingMessage,\n\tpathname: string,\n\tpublicMcpUrl: URL | undefined,\n): void {\n\tconsole.warn(\n\t\tJSON.stringify({\n\t\t\tsource: \"codemem-mcp-http-guard\",\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t\toutcome: \"denied\",\n\t\t\treason: \"host_or_origin_mismatch\",\n\t\t\tmethod: req.method,\n\t\t\tpath: pathname,\n\t\t\thost: truncateGuardLogField(req.headers.host),\n\t\t\torigin: truncateGuardLogField(req.headers.origin),\n\t\t\texpectedOrigin: publicMcpUrl?.origin,\n\t\t\tremoteAddress: req.socket.remoteAddress ?? undefined,\n\t\t}),\n\t);\n}\n\nfunction truncateGuardLogField(value: string | undefined): string | undefined {\n\tif (!value || value.length <= MAX_GUARD_LOG_FIELD_LENGTH) return value;\n\treturn `${value.slice(0, MAX_GUARD_LOG_FIELD_LENGTH)}…`;\n}\n\nfunction isAllowedPublicRequestHost(header: string | undefined, publicMcpUrl: URL): boolean {\n\tconst parsed = parseHostHeader(header);\n\tif (!parsed) return false;\n\tconst expectedPort = publicMcpUrl.port\n\t\t? Number(publicMcpUrl.port)\n\t\t: publicMcpUrl.protocol === \"https:\"\n\t\t\t? 443\n\t\t\t: 80;\n\tconst impliedPort = publicMcpUrl.protocol === \"https:\" ? 443 : 80;\n\tconst actualPort = parsed.port ?? impliedPort;\n\treturn (\n\t\tnormalizeHost(parsed.host) === normalizeHost(publicMcpUrl.hostname) &&\n\t\tactualPort === expectedPort\n\t);\n}\n\nfunction getBoundPort(server: Server): number {\n\tconst address = server.address();\n\tif (!address || typeof address === \"string\") return DEFAULT_MCP_HTTP_PORT;\n\treturn address.port;\n}\n\nfunction formatHostForUrl(host: string): string {\n\treturn isIP(host) === 6 ? `[${host}]` : host;\n}\n\nfunction getServerUrl(server: Server, host: string): string {\n\treturn `http://${formatHostForUrl(host)}:${getBoundPort(server)}/mcp`;\n}\n\nfunction getSdkIssuerUrl(publicMcpUrl: URL, port: number): URL {\n\tif (publicMcpUrl.protocol === \"https:\") return new URL(publicMcpUrl.origin);\n\tif (isLoopbackHost(publicMcpUrl.hostname) && normalizeHost(publicMcpUrl.hostname) !== \"::1\") {\n\t\treturn new URL(publicMcpUrl.origin);\n\t}\n\treturn new URL(`http://localhost:${port}/`);\n}\n\nfunction isOAuthOrMetadataPath(pathname: string): boolean {\n\treturn (\n\t\tpathname === \"/register\" ||\n\t\tpathname === \"/authorize\" ||\n\t\tpathname === \"/token\" ||\n\t\tpathname === \"/revoke\" ||\n\t\tpathname === \"/oauth/callback\" ||\n\t\tpathname === \"/.well-known/oauth-authorization-server\" ||\n\t\tpathname === \"/.well-known/oauth-protected-resource/mcp\"\n\t);\n}\n\nfunction normalizeRoutePath(pathname: string): string {\n\treturn pathname.length > 1 ? pathname.replace(/\\/+$/, \"\") : pathname;\n}\n\nfunction auditOAuthRouteResponses(\n\tauditEmit: (event: ReturnType<typeof buildOAuthAuditEvent>) => void,\n) {\n\treturn (req: Request, res: Response, next: NextFunction) => {\n\t\tconst pathname = req.path;\n\t\tif (!isAuditedOAuthPath(pathname)) return next();\n\t\tlet responseBody: unknown;\n\t\tconst originalJson = res.json.bind(res);\n\t\tres.json = ((body: unknown) => {\n\t\t\tresponseBody = body;\n\t\t\treturn originalJson(body);\n\t\t}) as typeof res.json;\n\t\tres.on(\"finish\", () => {\n\t\t\tif (pathname === \"/oauth/callback\") return;\n\t\t\tconst kind = oauthAuditKindForRequest(pathname, req);\n\t\t\tif (!kind) return;\n\t\t\tconst error = getOAuthResponseError(res, responseBody);\n\t\t\tconst clientId = getRequestClientId(req, responseBody);\n\t\t\tauditEmit(\n\t\t\t\tbuildOAuthAuditEvent(kind, {\n\t\t\t\t\toutcome: error ? \"denied\" : \"success\",\n\t\t\t\t\t...(error ? { reason: error } : {}),\n\t\t\t\t\t...(clientId ? { clientId } : {}),\n\t\t\t\t\tremoteAddress: req.socket.remoteAddress ?? undefined,\n\t\t\t\t}),\n\t\t\t);\n\t\t});\n\t\tnext();\n\t};\n}\n\nfunction isAuditedOAuthPath(pathname: string): boolean {\n\treturn oauthAuditKindForPath(pathname) !== null;\n}\n\nfunction oauthAuditKindForRequest(\n\tpathname: string,\n\treq: Request,\n): \"registration\" | \"authorize\" | \"token\" | \"refresh\" | \"revocation\" | null {\n\tif (pathname === \"/token\" && req.body?.grant_type === \"refresh_token\") return \"refresh\";\n\treturn oauthAuditKindForPath(pathname);\n}\n\nfunction oauthAuditKindForPath(\n\tpathname: string,\n): \"registration\" | \"authorize\" | \"token\" | \"revocation\" | null {\n\tif (pathname === \"/register\") return \"registration\";\n\tif (pathname === \"/authorize\") return \"authorize\";\n\tif (pathname === \"/token\") return \"token\";\n\tif (pathname === \"/revoke\") return \"revocation\";\n\treturn null;\n}\n\nfunction getOAuthResponseError(res: Response, body: unknown): string | undefined {\n\tconst bodyError = getOAuthBodyError(body);\n\tif (bodyError) return bodyError;\n\tconst location = res.getHeader(\"location\");\n\tif (typeof location !== \"string\") return undefined;\n\ttry {\n\t\tconst redirect = new URL(location);\n\t\treturn redirect.searchParams.get(\"error\") ?? undefined;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nfunction getOAuthBodyError(body: unknown): string | undefined {\n\tif (\n\t\ttypeof body === \"object\" &&\n\t\tbody !== null &&\n\t\t\"error\" in body &&\n\t\ttypeof body.error === \"string\"\n\t) {\n\t\treturn body.error;\n\t}\n\treturn undefined;\n}\n\nfunction getRequestClientId(req: Request, body: unknown): string | undefined {\n\tif (\n\t\ttypeof body === \"object\" &&\n\t\tbody !== null &&\n\t\t\"client_id\" in body &&\n\t\ttypeof body.client_id === \"string\"\n\t) {\n\t\treturn body.client_id;\n\t}\n\tconst bodyClientId = typeof req.body?.client_id === \"string\" ? req.body.client_id : undefined;\n\tif (bodyClientId) return bodyClientId;\n\tconst queryClientId = typeof req.query.client_id === \"string\" ? req.query.client_id : undefined;\n\treturn queryClientId;\n}\n\nfunction auditBearerPreflight(\n\tauditEmit: (event: ReturnType<typeof buildOAuthAuditEvent>) => void,\n\ttokenStore: OAuthAccessTokenStore,\n) {\n\treturn (req: Request, _res: Response, next: NextFunction) => {\n\t\tconst reason = getBearerPreflightDenyReason(req.headers.authorization, tokenStore);\n\t\tif (reason) {\n\t\t\tauditEmit(\n\t\t\t\tbuildOAuthAuditEvent(\"bearer\", {\n\t\t\t\t\toutcome: \"denied\",\n\t\t\t\t\treason,\n\t\t\t\t\tremoteAddress: req.socket.remoteAddress ?? undefined,\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t\tnext();\n\t};\n}\n\nfunction getBearerPreflightDenyReason(\n\theader: string | undefined,\n\ttokenStore: OAuthAccessTokenStore,\n): BearerDenyReason | null {\n\tif (!header) return \"missing_authorization_header\";\n\tconst [scheme, token, extra] = header.trim().split(/\\s+/);\n\tif (!scheme || !token || extra || scheme.toLowerCase() !== \"bearer\") {\n\t\treturn \"malformed_authorization_header\";\n\t}\n\tconst verification = tokenStore.verifyToken(token);\n\tif (!verification.ok) return verification.reason;\n\treturn null;\n}\n\nfunction parseScopeList(scope: string | null | undefined): string[] {\n\treturn (\n\t\tscope\n\t\t\t?.split(/\\s+/)\n\t\t\t.map((item) => item.trim())\n\t\t\t.filter(Boolean) ?? []\n\t);\n}\n\nfunction isEntrypoint(): boolean {\n\tconst script = process.argv[1];\n\treturn script ? import.meta.url === pathToFileURL(script).href : false;\n}\n\nasync function main() {\n\tconst httpServer = await startCodememMcpHttpServer();\n\tconsole.error(`codemem MCP HTTP server listening at ${httpServer.url}`);\n\n\tconst shutdown = async () => {\n\t\ttry {\n\t\t\tawait httpServer.close();\n\t\t} catch {\n\t\t\t// Best effort — process is exiting.\n\t\t}\n\t\tprocess.exit(0);\n\t};\n\n\tprocess.on(\"SIGINT\", shutdown);\n\tprocess.on(\"SIGTERM\", shutdown);\n}\n\nif (isEntrypoint()) {\n\tmain().catch((err) => {\n\t\tconsole.error(\"codemem MCP HTTP server failed to start:\", err);\n\t\tprocess.exit(1);\n\t});\n}\n"],"x_google_ignoreList":[0,1,2,3,4,5,6,7,8,9],"mappings":"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"}