/**
 * WS5.2 R4a — durable store of cross-machine-DELIVERED account-follow-me mandates.
 *
 * THE ONE-DASHBOARD PROBLEM (operator feedback, load-bearing): the operator has ONE dashboard.
 * An account-follow-me enrollment is acted on by the TARGET machine, but a mandate is issued
 * (PIN-gated) on the operator's machine. A mandate issued on the laptop has LAPTOP authorship
 * (a symmetric HMAC over the laptop's per-machine authToken, §3.1a) and will NOT pass the target's
 * `MandateStore.verifyAuthorship` — by design. So the operator dashboard issues the mandate and
 * DELIVERS it (the R4a-signed `PortableMandate`) to the target over the mesh, where it is verified
 * via the asymmetric issuance signature against the target's REGISTERED operator-machine key.
 *
 * This store is where a target persists a delivered+verified mandate. It retains the FULL
 * `PortableMandate` (the mandate AND its asymmetric issuance signature), keyed by mandate id, so
 * the enroll-start route can RE-VERIFY at point-of-use (defense-in-depth — never trust a stored
 * flag blindly; the §3.1a HMAC proof is local-only and cannot ground a delivered mandate, so the
 * R4a signature is the standing proof of authority). It also records the authenticated operator
 * machine that delivered it (the mesh-authenticated `env.sender`) so the re-verify at use time
 * binds to the SAME trust anchor.
 *
 * Trust boundary (same root as MandateStore): integrity of the on-disk file against a LOCAL-write
 * attacker is the baseline (T12, out of scope). The R4a signature stops a forged/edited delivered
 * mandate from a hostile peer — local-file tamper of server-managed state is the baseline boundary.
 *
 * Pure file-state, no DB (file-based-state design decision). Mirrors MandateStore's read/write
 * shape. WS5.2 one-dashboard cross-machine mandate delivery.
 */
import fs from 'node:fs';
import path from 'node:path';
export class DeliveredMandateStore {
    d;
    constructor(deps) {
        this.d = deps;
    }
    nowIso() {
        return new Date(this.d.now ? this.d.now() : Date.now()).toISOString();
    }
    readAll() {
        try {
            const raw = JSON.parse(fs.readFileSync(this.d.filePath, 'utf8'));
            return Array.isArray(raw) ? raw : [];
        }
        catch {
            // @silent-fallback-ok — file may not exist yet; an empty store is DENY-BY-DEFAULT (the safe state).
            return [];
        }
    }
    writeAll(records) {
        fs.mkdirSync(path.dirname(this.d.filePath), { recursive: true });
        fs.writeFileSync(this.d.filePath, JSON.stringify(records, null, 2));
    }
    /**
     * Persist a delivered+verified mandate (called by the mesh handler ONLY after `acceptDeliveredMandate`
     * verified the R4a signature). `deliveredBy` is the mesh-AUTHENTICATED sender, NOT a payload name.
     * Idempotent by mandate id (a redelivery overwrites with the latest provenance).
     */
    put(portable, deliveredBy, operatorPublicKeyPem) {
        const id = portable.mandate.id;
        const record = {
            id, portable, deliveredBy, operatorPublicKeyPem, deliveredAt: this.nowIso(),
        };
        const all = this.readAll().filter((r) => r.id !== id);
        all.push(record);
        this.writeAll(all);
        return record;
    }
    get(id) {
        return this.readAll().find((r) => r.id === id);
    }
    list() {
        return this.readAll();
    }
    /** Remove a delivered mandate (e.g. on revocation). Idempotent. */
    remove(id) {
        const all = this.readAll();
        const next = all.filter((r) => r.id !== id);
        if (next.length !== all.length)
            this.writeAll(next);
    }
}
//# sourceMappingURL=DeliveredMandateStore.js.map