import { n as __decorateMetadata, t as __decorateParam } from "./decorateParam-BWxkAUSj.js";
import { t as __decorate } from "./decorate-CXWmflG_.js";
import { inject, injectable } from "@codemation/core";
import { createHash, createHmac, randomBytes, timingSafeEqual } from "node:crypto";

//#region src/pairing/PairingConfigToken.ts
const PairingConfigToken = Symbol.for("codemation.pairing.PairingConfig");

//#endregion
//#region src/pairing/HmacRequestSigner.ts
let HmacRequestSigner = class HmacRequestSigner$1 {
	constructor(config = null) {
		this.config = config;
	}
	sign(method, urlOrPath, body) {
		if (this.config === null) throw new Error("HmacRequestSigner.sign called without a registered PairingConfig — workspace is not in managed mode.");
		const ts = Math.floor(Date.now() / 1e3);
		const nonce = randomBytes(16).toString("base64");
		const parsed = new URL(urlOrPath, "http://placeholder");
		const path = (parsed.pathname + parsed.search).toLowerCase();
		const bodyHash = createHash("sha256").update(body, "utf8").digest("hex");
		const baseString = [
			method.toUpperCase(),
			path,
			ts,
			nonce,
			bodyHash
		].join("\n");
		const sig = createHmac("sha256", Buffer.from(this.config.pairingSecret, "base64")).update(baseString, "utf8").digest("base64");
		return { Authorization: `Codemation-Hmac v=1,workspaceId=${this.config.workspaceId},ts=${ts},nonce=${nonce},sig=${sig}` };
	}
};
HmacRequestSigner = __decorate([
	injectable(),
	__decorateParam(0, inject(PairingConfigToken, { isOptional: true })),
	__decorateMetadata("design:paramtypes", [Object])
], HmacRequestSigner);

//#endregion
//#region src/pairing/PairedFetch.ts
var _ref$2;
let PairedFetch = class PairedFetch$1 {
	constructor(signer) {
		this.signer = signer;
	}
	async get(url) {
		const headers = this.signer.sign("GET", url, "");
		return fetch(url, {
			method: "GET",
			headers: { ...headers }
		});
	}
	async post(url, body) {
		const bodyString = JSON.stringify(body);
		const headers = this.signer.sign("POST", url, bodyString);
		return fetch(url, {
			method: "POST",
			headers: {
				...headers,
				"Content-Type": "application/json"
			},
			body: bodyString
		});
	}
	async delete(url) {
		const headers = this.signer.sign("DELETE", url, "");
		return fetch(url, {
			method: "DELETE",
			headers: { ...headers }
		});
	}
};
PairedFetch = __decorate([
	injectable(),
	__decorateParam(0, inject(HmacRequestSigner)),
	__decorateMetadata("design:paramtypes", [typeof (_ref$2 = typeof HmacRequestSigner !== "undefined" && HmacRequestSigner) === "function" ? _ref$2 : Object])
], PairedFetch);

//#endregion
//#region src/pairing/PairingConfigFactory.ts
/**
* Reads pairing configuration from environment variables.
*
* Required env vars when pairing is enabled:
*   WORKSPACE_ID               — the workspace's database ID
*   WORKSPACE_PAIRING_SECRET   — base64-encoded 32-byte shared secret
*   CONTROL_PLANE_URL          — base URL of the control plane API
*
* Returns null if any required variable is absent (pairing disabled).
* See docs/pairing-protocol.md for full bootstrap instructions.
*/
var PairingConfigFactory = class {
	create(env) {
		const workspaceId = env["WORKSPACE_ID"];
		const pairingSecret = env["WORKSPACE_PAIRING_SECRET"];
		const controlPlaneUrl = env["CONTROL_PLANE_URL"];
		if (!workspaceId || !pairingSecret || !controlPlaneUrl) return null;
		const decoded = Buffer.from(pairingSecret, "base64");
		if (decoded.length !== 32) throw new Error(`WORKSPACE_PAIRING_SECRET must be a base64-encoded 32-byte value (got ${decoded.length} bytes). Generate a valid secret with: openssl rand -base64 32`);
		return {
			workspaceId,
			pairingSecret,
			controlPlaneUrl
		};
	}
};

//#endregion
//#region src/pairing/HmacNonceStoreToken.ts
const HmacNonceStoreToken = Symbol.for("codemation.pairing.HmacNonceStore");

//#endregion
//#region src/pairing/IncomingHmacVerifier.ts
let IncomingHmacVerifier = class IncomingHmacVerifier$1 {
	nonceTtlSeconds = 600;
	constructor(config = null, nonceStore) {
		this.config = config;
		this.nonceStore = nonceStore;
	}
	async verify(method, url, body, authHeader) {
		if (this.config === null) throw new Error("IncomingHmacVerifier.verify called without a registered PairingConfig — workspace is not in managed mode.");
		if (!this.config.pairingSecret || this.config.pairingSecret.trim().length === 0) throw new Error("IncomingHmacVerifier: pairingSecret is not configured — cannot verify HMAC requests.");
		if (!authHeader?.startsWith("Codemation-Hmac ")) return { failure: "missing" };
		const parts = this.parseHeader(authHeader);
		if (!parts) return { failure: "missing" };
		if (parts.v !== "1") return { failure: "version" };
		const nowSec = Math.floor(Date.now() / 1e3);
		if (Math.abs(nowSec - parts.ts) > 300) return { failure: "expired" };
		if (parts.workspaceId !== this.config.workspaceId) return { failure: "workspace" };
		const parsed = new URL(url, "http://placeholder");
		const path = (parsed.pathname + parsed.search).toLowerCase();
		const bodyHash = createHash("sha256").update(body, "utf8").digest("hex");
		const baseString = [
			method.toUpperCase(),
			path,
			parts.ts,
			parts.nonce,
			bodyHash
		].join("\n");
		const expected = createHmac("sha256", Buffer.from(this.config.pairingSecret, "base64")).update(baseString, "utf8").digest("base64");
		const expectedBuf = Buffer.from(expected);
		const actualBuf = Buffer.from(parts.sig);
		if (expectedBuf.length !== actualBuf.length || !timingSafeEqual(expectedBuf, actualBuf)) return { failure: "signature" };
		const nonceKey = `${parts.workspaceId}:${parts.nonce}`;
		const nonceExpiresAt = /* @__PURE__ */ new Date((nowSec + this.nonceTtlSeconds) * 1e3);
		if (!await this.nonceStore.recordIfNew(nonceKey, nonceExpiresAt)) return { failure: "replay" };
		return { workspaceId: parts.workspaceId };
	}
	parseHeader(header) {
		const payload = header.slice(16);
		const fields = {};
		for (const part of payload.split(",")) {
			const eq = part.indexOf("=");
			if (eq === -1) return null;
			fields[part.slice(0, eq).trim()] = part.slice(eq + 1).trim();
		}
		const { v, workspaceId, ts, nonce, sig } = fields;
		if (!v || !workspaceId || !ts || !nonce || !sig) return null;
		return {
			v,
			workspaceId,
			ts: Number(ts),
			nonce,
			sig
		};
	}
};
IncomingHmacVerifier = __decorate([
	injectable(),
	__decorateParam(0, inject(PairingConfigToken, { isOptional: true })),
	__decorateParam(1, inject(HmacNonceStoreToken)),
	__decorateMetadata("design:paramtypes", [Object, Object])
], IncomingHmacVerifier);

//#endregion
//#region src/pairing/InternalHmacAuthMiddleware.ts
var _ref$1;
let InternalHmacAuthMiddleware = class InternalHmacAuthMiddleware$1 {
	constructor(verifier) {
		this.verifier = verifier;
	}
	handle() {
		return async (c, next) => {
			const body = c.req.method === "GET" || c.req.method === "HEAD" ? "" : await c.req.text();
			if ("failure" in await this.verifier.verify(c.req.method, c.req.url, body, c.req.header("authorization") ?? null)) return c.json({ error: "Unauthorized" }, 401);
			c.set("body", body);
			await next();
		};
	}
};
InternalHmacAuthMiddleware = __decorate([
	injectable(),
	__decorateParam(0, inject(IncomingHmacVerifier)),
	__decorateMetadata("design:paramtypes", [typeof (_ref$1 = typeof IncomingHmacVerifier !== "undefined" && IncomingHmacVerifier) === "function" ? _ref$1 : Object])
], InternalHmacAuthMiddleware);

//#endregion
//#region src/pairing/InternalPingRegistrar.ts
var _ref;
let InternalPingRegistrar = class InternalPingRegistrar$1 {
	constructor(hmacMiddleware, pairingConfig) {
		this.hmacMiddleware = hmacMiddleware;
		this.pairingConfig = pairingConfig;
	}
	register(app) {
		const { workspaceId } = this.pairingConfig;
		app.get("/internal/ping", this.hmacMiddleware.handle(), (c) => {
			return c.json({
				pong: true,
				workspaceId
			});
		});
	}
};
InternalPingRegistrar = __decorate([
	injectable(),
	__decorateParam(0, inject(InternalHmacAuthMiddleware)),
	__decorateParam(1, inject(PairingConfigToken)),
	__decorateMetadata("design:paramtypes", [typeof (_ref = typeof InternalHmacAuthMiddleware !== "undefined" && InternalHmacAuthMiddleware) === "function" ? _ref : Object, Object])
], InternalPingRegistrar);

//#endregion
export { PairingConfigFactory as a, PairingConfigToken as c, HmacNonceStoreToken as i, InternalHmacAuthMiddleware as n, PairedFetch as o, IncomingHmacVerifier as r, HmacRequestSigner as s, InternalPingRegistrar as t };
//# sourceMappingURL=InternalPingRegistrar-BavAAnvk.js.map