"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.deriveGranteeId = deriveGranteeId;
exports.resolveGranteeId = resolveGranteeId;
/**
 * Grantee-identity binding (Phase 0 of expose-disclosure-grants).
 *
 * The AttestationVault circuit keys disclosure grants by a 32-byte `grantee`.
 * To gate reads on an on-chain grant, NIGHTGATE must turn the authenticated
 * principal (`req.user.id`) into that same 32 bytes. This module owns:
 *
 *   1. `deriveGranteeId(kind, input)` — the canonical derivation. THE SAME
 *      function (or its documented scheme) must be used by whoever issues the
 *      grant, or the write-side id and the read-side id won't match.
 *   2. `resolveGranteeId(req, db, opts)` — look up the principal's registered
 *      granteeId from the `GranteeIdentities` table (scope precedence mirrors
 *      the disclosure-role middleware: a scoped row wins over a global one).
 *
 * Binding kind is per-deployment (`cds.requires.nightgate.granteeBinding`,
 * default 'wallet'). The principal→grantee *policy* (proving DID/wallet
 * ownership before a row is written) is the consumer's to own — NIGHTGATE
 * provides the table, derivation, and resolver, not the proofing.
 */
const cds_1 = __importDefault(require("@sap/cds"));
const sha256_1 = require("@noble/hashes/sha256");
const utils_1 = require("@noble/hashes/utils");
const midnight_1 = require("#cds-models/midnight");
const { SELECT } = cds_1.default.ql;
const HEX64_RE = /^[0-9a-fA-F]{64}$/;
/**
 * Canonical derivation of a 64-hex grantee id from a binding input.
 *   - 'custom': `input` IS the 64-hex id (validated, lower-cased) — passthrough.
 *   - 'wallet': `input` is the coin public key hex; id = sha256(pubkey bytes).
 *   - 'did':    `input` is the DID string; id = sha256(utf8(did)).
 * sha256 is used (already a dependency) purely as a stable 32-byte digest; the
 * grantee id is an identifier, not a circuit witness.
 */
function deriveGranteeId(kind, input) {
    if (input == null || input === '') {
        throw new Error('grantee-identity: input is required');
    }
    if (kind === 'custom') {
        if (!HEX64_RE.test(input)) {
            throw new Error('grantee-identity: custom granteeId must be 64 hex chars (32 bytes)');
        }
        return input.toLowerCase();
    }
    if (kind === 'wallet') {
        if (!/^[0-9a-fA-F]+$/.test(input) || input.length % 2 !== 0) {
            throw new Error('grantee-identity: wallet coin public key must be hex');
        }
        return (0, utils_1.bytesToHex)((0, sha256_1.sha256)(hexToBytes(input)));
    }
    // 'did'
    return (0, utils_1.bytesToHex)((0, sha256_1.sha256)(new TextEncoder().encode(input)));
}
/**
 * Resolve the authenticated principal's granteeId, or null when the principal
 * is anonymous or has no matching binding. Scope precedence: a row whose scope
 * equals `opts.scope` wins over a globally-scoped row.
 */
async function resolveGranteeId(req, db, opts = {}) {
    const userId = req.user?.id;
    if (!userId)
        return null;
    const rows = (await db.run(SELECT.from(midnight_1.GranteeIdentities).where({ userId }))) || [];
    if (rows.length === 0)
        return null;
    const norm = (s) => (s == null || s === '' ? null : s);
    if (opts.scope === undefined) {
        const global = rows.find(r => norm(r.scope) === null);
        return global ? global.granteeId : null;
    }
    // Prefer an exactly-scoped row; fall back to a global one.
    const scoped = rows.find(r => norm(r.scope) === opts.scope);
    if (scoped)
        return scoped.granteeId;
    const global = rows.find(r => norm(r.scope) === null);
    return global ? global.granteeId : null;
}
// Local hex→bytes (avoids importing the handler's copy; same semantics).
function hexToBytes(hex) {
    const out = new Uint8Array(hex.length / 2);
    for (let i = 0; i < out.length; i++)
        out[i] = parseInt(hex.substr(i * 2, 2), 16);
    return out;
}
