/**
 * JWT License Issuer -- Server-side license creation for @connexum/ai-governance.
 *
 * Creates RS256-signed JWT license tokens with proper claims for each tier.
 * Used by the license server, NOT shipped to end users.
 *
 * @connexum/ai-governance
 */
import * as crypto from 'crypto';
import { TIER_LIMITS } from './jwt-validator.js';
/* ------------------------------------------------------------------ */
/*  JwtIssuer                                                          */
/* ------------------------------------------------------------------ */
export class JwtIssuer {
    config;
    constructor(config) {
        this.config = {
            defaultDurationDays: 365,
            defaultGracePeriodDays: 7,
            ...config,
        };
    }
    /**
     * Issue a new license JWT.
     */
    issue(request) {
        const now = Math.floor(Date.now() / 1000);
        const durationDays = request.durationDays ?? this.config.defaultDurationDays;
        const exp = now + (durationDays * 86400);
        const tierLimits = TIER_LIMITS[request.tier];
        const features = [...tierLimits.features];
        if (request.additionalFeatures) {
            for (const f of request.additionalFeatures) {
                if (!features.includes(f))
                    features.push(f);
            }
        }
        const claims = {
            tier: request.tier,
            org: request.org,
            maxAgents: request.maxAgents ?? tierLimits.maxAgents,
            maxPacks: request.maxPacks ?? tierLimits.maxPacks,
            features,
            iss: 'my-cc.io',
            aud: '@connexum/ai-governance',
            sub: request.org,
            iat: now,
            exp,
            jti: `lic_${crypto.randomBytes(16).toString('hex')}`,
            kid: this.config.kid,
            offlineGracePeriodDays: request.offlineGracePeriodDays ?? this.config.defaultGracePeriodDays,
        };
        const token = this.sign(claims);
        return {
            token,
            claims,
            expiresAt: new Date(exp * 1000).toISOString(),
        };
    }
    /**
     * Sign claims into a JWT.
     */
    sign(claims) {
        const header = {
            alg: 'RS256',
            typ: 'JWT',
            kid: this.config.kid,
        };
        const headerB64 = base64UrlEncode(JSON.stringify(header));
        const payloadB64 = base64UrlEncode(JSON.stringify(claims));
        const signatureInput = `${headerB64}.${payloadB64}`;
        const signer = crypto.createSign('RSA-SHA256');
        signer.update(signatureInput);
        const signature = signer.sign(this.config.privateKey);
        return `${signatureInput}.${bufferToBase64Url(signature)}`;
    }
    /**
     * Generate an RSA-2048 key pair for license signing.
     * Returns { publicKey, privateKey } in PEM format.
     */
    static generateKeyPair() {
        const { publicKey, privateKey } = crypto.generateKeyPairSync('rsa', {
            modulusLength: 2048,
            publicKeyEncoding: { type: 'spki', format: 'pem' },
            privateKeyEncoding: { type: 'pkcs8', format: 'pem' },
        });
        return { publicKey, privateKey };
    }
}
/* ------------------------------------------------------------------ */
/*  Base64URL helpers                                                  */
/* ------------------------------------------------------------------ */
function base64UrlEncode(str) {
    return Buffer.from(str)
        .toString('base64')
        .replace(/\+/g, '-')
        .replace(/\//g, '_')
        .replace(/=+$/, '');
}
function bufferToBase64Url(buf) {
    return buf
        .toString('base64')
        .replace(/\+/g, '-')
        .replace(/\//g, '_')
        .replace(/=+$/, '');
}
//# sourceMappingURL=jwt-issuer.js.map