/**
 * Install Context — factory that wires LicensePackLoader + MonthlyVerifyScheduler
 * into a single consumer object the GovernanceRuntime can hold.
 *
 * This is the real customer-code-path consumer of the two previously-orphaned
 * modules (F-NEW-META-1 pattern — shipped in PR #1215 but never imported by
 * any production caller).
 *
 * Step 0 probe: grep -rn "LicensePackLoader\|MonthlyVerifyScheduler" src/ returned
 *   only source + index.ts + test — zero production consumers before this PR.
 * Step 0 evidence: F-NEW-META-1 pattern flagged by orchestrator audit at
 *   session-end 2026-05-21 — modules shipped but unwired.
 * Step 0 customer-path: customer instantiates GovernanceRuntime({...config, installJwt})
 *   → loader fetches packs + scheduler verifies monthly → onToolObserved triggers
 *   verify on first event of month.
 *
 * Design constraints (Architectural Invariant 2):
 *   - NEVER throw on install JWT parse failure — log + return undefined.
 *   - NEVER block runtime construction on loader/verify failures.
 *   - NEVER depend on @connexum/license-server package at runtime (wrong layer).
 *     pack_codes claim parsing is inlined narrowly here.
 *
 * @connexum/ai-governance  Task #32 wiring — install-context factory
 */
import { LicensePackLoader } from './license-pack-loader.js';
import { MonthlyVerifyScheduler } from './monthly-verify-scheduler.js';
/* ------------------------------------------------------------------ */
/*  JWT pack_codes claim parser (inlined — no license-server dep)      */
/* ------------------------------------------------------------------ */
/**
 * Minimally parse the base64url payload from a JWT string.
 * Returns the decoded JSON object, or null on any parse error.
 * Never throws.
 *
 * @internal
 */
export function parseJwtPayload(token) {
    if (!token || typeof token !== 'string')
        return null;
    const parts = token.split('.');
    if (parts.length !== 3)
        return null;
    // Base64url → base64 → decode
    const base64 = parts[1]
        .replace(/-/g, '+')
        .replace(/_/g, '/')
        .padEnd(Math.ceil(parts[1].length / 4) * 4, '=');
    try {
        const decoded = Buffer.from(base64, 'base64').toString('utf-8');
        const payload = JSON.parse(decoded);
        if (payload !== null && typeof payload === 'object' && !Array.isArray(payload)) {
            return payload;
        }
        return null;
    }
    catch {
        return null;
    }
}
/**
 * Extract and validate the `pack_codes` claim from a decoded JWT payload.
 *
 * Expected shape (PR-W-3+4 format from license-server):
 *   pack_codes: Array<{ packId: string; code: string; agentId: string }>
 *
 * Returns validated array or null when missing / malformed.
 * Never throws.
 *
 * @internal
 */
export function extractPackCodes(payload) {
    const raw = payload['pack_codes'];
    if (!Array.isArray(raw) || raw.length === 0)
        return null;
    const validated = [];
    for (const entry of raw) {
        if (entry !== null &&
            typeof entry === 'object' &&
            typeof entry['packId'] === 'string' &&
            typeof entry['code'] === 'string' &&
            typeof entry['agentId'] === 'string') {
            validated.push(entry);
        }
    }
    return validated.length > 0 ? validated : null;
}
/* ------------------------------------------------------------------ */
/*  Factory                                                             */
/* ------------------------------------------------------------------ */
/**
 * Parse the install JWT and wire LicensePackLoader + MonthlyVerifyScheduler.
 *
 * Returns the wired {@link InstallContext} when the JWT is valid, or `undefined`
 * when the JWT is missing, malformed, or lacks a valid `pack_codes` claim.
 *
 * Per Invariant 2 (advisory, never authoritative): this function never throws.
 * Errors are logged to stderr and the runtime continues without install context.
 *
 * @example
 * ```ts
 * const ctx = initInstallContext({
 *   installJwt: process.env.MY_CC_INSTALL_JWT!,
 *   agentJwt:   process.env.MY_CC_AGENT_JWT!,
 * });
 * if (ctx) {
 *   void ctx.loader.loadPacksFromJwt(ctx.packCodes); // fire-and-forget
 * }
 * ```
 */
export function initInstallContext(opts) {
    const { installJwt, agentJwt } = opts;
    const licenseServerBaseUrl = opts.licenseServerBaseUrl ?? 'https://license.my-cc.io';
    // --- Parse the install JWT payload (never throws) ---
    const payload = parseJwtPayload(installJwt);
    if (!payload) {
        process.stderr.write('[GovernanceRuntime] install JWT could not be parsed — ' +
            'no install context will be wired. Agents continue normally (Invariant 2).\n');
        return undefined;
    }
    // --- Extract pack_codes claim ---
    const packCodes = extractPackCodes(payload);
    if (!packCodes) {
        process.stderr.write('[GovernanceRuntime] install JWT has no valid pack_codes claim — ' +
            'no install context will be wired. Agents continue normally (Invariant 2).\n');
        return undefined;
    }
    // --- Extract orgId from `org` claim (fall back gracefully) ---
    const orgId = typeof payload['org'] === 'string' && payload['org'].length > 0
        ? payload['org']
        : typeof payload['sub'] === 'string' && payload['sub'].length > 0
            ? payload['sub']
            : 'unknown-org';
    // --- Wire scheduler first (it is the MonthlyVerifyCache for the loader) ---
    const scheduler = new MonthlyVerifyScheduler({
        licenseServerUrl: licenseServerBaseUrl,
        agentJwt,
    });
    // --- Wire loader with scheduler as its monthlyVerifyCache ---
    const loader = new LicensePackLoader({
        licenseServerUrl: licenseServerBaseUrl,
        orgId,
        monthlyVerifyCache: scheduler,
    });
    return { loader, scheduler, packCodes, orgId };
}
//# sourceMappingURL=install-context.js.map