#pragma once // Access to the `pairings` table: the WebSocket transport's revocable per-install tokens // (docs/05 §4). The plaintext token is returned by create() exactly once and never // stored — only its SHA-256 (CLAUDE.md §4). #include #include #include #include #include "store/sqlite.hpp" namespace velox::daemon::store { struct Pairing { std::string pairing_id; std::string origin; std::string label; std::string created_at; std::optional last_seen_at; std::optional revoked_at; }; class Pairings { public: explicit Pairings(Db& db) : db_(db) {} struct Created { std::string pairing_id; std::string token; // plaintext — send once, to the client, then forget }; // Mint a token for `origin`, store its hash + `label`, timestamp `now_iso`. DbResult create(std::string_view origin, std::string_view label, std::string_view now_iso); // The active (non-revoked) pairing whose token hashes to this value, if any. DbResult> find_active_by_token(std::string_view plaintext_token); // Bump last_seen_at. Called on every authenticated connect. DbResult touch(std::string_view pairing_id, std::string_view now_iso); // Mark revoked. Returns false if there was no such active pairing. DbResult revoke(std::string_view pairing_id, std::string_view now_iso); DbResult> list_active(); private: Db& db_; }; } // namespace velox::daemon::store