// Recorded read-only-scope consent for the Figma connector (Epic #750, Issue #760).
//
// There is NO OAuth grant flow: the operator mints a least-privilege, READ-ONLY Personal Access
// Token out of band. Before the FIRST scoped fetch for a connected scope, the operator must
// explicitly acknowledge that the configured PAT is read-only and least-privilege; this module
// records that acknowledgement as durable evidence. The expected scopes are DISPLAY-ONLY — the
// connector cannot grant or widen anything; it only shows what a least-privilege read-only token
// covers so the operator can confirm before the first fetch.
//
// The consent record carries NO token, NO PII, and NO board id / link / content — only the opaque
// `scopeRef`, the acknowledged read-only flag, an optional operator label, and a timestamp. It is
// persisted through the SAME reused Evidence contained-store seam as the connector audit.
import { createNodeContainedJsonArtifactStore, } from "@oscharko-dev/keiko-evidence";
import { FigmaConnectorError } from "./figmaConnectorErrors.js";
export const FIGMA_CONSENT_SCHEMA_VERSION = 1;
const FIGMA_CONSENT_SUFFIX = ".figma-consent.json";
/**
 * Display-only list of the least-privilege, read-only Figma scopes the connector relies on. Shown to
 * the operator before the first fetch so they can confirm the PAT they minted is read-only. The
 * connector reads files and renders images; it never writes. Figma PAT scopes are coarse, so this is
 * the human-readable expectation, not an enforced grant.
 */
export const EXPECTED_FIGMA_SCOPES = ["files:read", "file_dev_resources:read"];
const parseConsent = (value) => {
    if (typeof value !== "object" || value === null)
        return undefined;
    const record = value;
    if (record.figmaConsentSchemaVersion !== FIGMA_CONSENT_SCHEMA_VERSION)
        return undefined;
    if (typeof record.scopeRef !== "string" || record.readOnlyAcknowledged !== true)
        return undefined;
    return value;
};
const storeFor = (evidenceDir) => createNodeContainedJsonArtifactStore(evidenceDir, FIGMA_CONSENT_SUFFIX, { parse: parseConsent });
export const loadReadOnlyConsent = (scopeRef, evidenceDir) => storeFor(evidenceDir).load(scopeRef);
export const hasReadOnlyConsent = (scopeRef, evidenceDir) => loadReadOnlyConsent(scopeRef, evidenceDir) !== undefined;
/**
 * Record the operator's explicit acknowledgement of the read-only, least-privilege scope. Idempotent
 * by overwrite (re-acknowledging refreshes the timestamp). Returns the stored consent record.
 */
export const recordReadOnlyConsent = (input) => {
    const consent = {
        figmaConsentSchemaVersion: FIGMA_CONSENT_SCHEMA_VERSION,
        scopeRef: input.scopeRef,
        readOnlyAcknowledged: true,
        acknowledgedScopes: EXPECTED_FIGMA_SCOPES,
        acknowledgedBy: input.acknowledgedBy,
        acknowledgedAt: input.now,
    };
    storeFor(input.evidenceDir).record(input.scopeRef, consent);
    return consent;
};
/**
 * Gate the first fetch on recorded consent. Throws a coded, safe error when the operator has not yet
 * acknowledged the read-only scope for this connected scope. The connector calls this BEFORE token
 * materialisation so an unconsented scope never reaches Figma.
 */
export const assertReadOnlyConsent = (scopeRef, evidenceDir) => {
    if (!hasReadOnlyConsent(scopeRef, evidenceDir)) {
        throw new FigmaConnectorError("FIGMA_CONSENT_REQUIRED");
    }
};
