// C++17. Paired transport-free scaffold, not an authentication implementation. // VerifiedTransaction is produced ONLY after full verification under a lock. // Its destructor rolls back unless commitOnce succeeds. See examples/README.md. #include #include #include #include #include namespace bringpass { enum class Op { REGISTER, USE, REVOKE, RETRACT }; struct Envelope { std::vector fields; std::string signature; }; struct Result { Envelope receipt; bool fresh; }; struct Tx { virtual ~Tx() = default; virtual Op operation() const = 0; virtual std::optional cached() const = 0; virtual void registerNewKey() = 0; virtual void requireCurrentEntitlement() = 0; virtual void revokeTarget() = 0; virtual void retractRelationship() = 0; virtual Envelope signResult() = 0; virtual void commitOnce(const Envelope&) = 0; }; struct Ports { virtual ~Ports() = default; virtual Envelope challenge(Op,const std::string&,const std::string&,const std::string&) = 0; virtual void verifyProviderAndApprove(const Envelope&) = 0; virtual Envelope signProof(const Envelope&) = 0; virtual void verifyResultAndApply(const Envelope&) = 0; virtual std::unique_ptr beginVerified(const Envelope&,const std::string&) = 0; virtual Envelope recoverRevoke(const std::string&,const std::string&,const std::string&) = 0; }; struct TokenSide { Ports& ports; Envelope respond(const Envelope& q) { ports.verifyProviderAndApprove(q); return ports.signProof(q); } void accept(const Envelope& r) { ports.verifyResultAndApply(r); } }; struct ProviderSide { Ports& ports; Envelope start(Op op,const std::string& rid,const std::string& target,const std::string& context) { return ports.challenge(op,rid,target,context); } Result finish(const Envelope& proof,const std::string& trustedContext) { auto tx = ports.beginVerified(proof,trustedContext); if (!tx) throw std::runtime_error("Verified transaction required"); if (auto old = tx->cached()) return {*old,false}; switch (tx->operation()) { case Op::REGISTER: tx->registerNewKey(); break; case Op::USE: tx->requireCurrentEntitlement(); break; case Op::REVOKE: tx->revokeTarget(); break; case Op::RETRACT: tx->retractRelationship(); break; default: throw std::runtime_error("Unsupported operation"); } auto result = tx->signResult(); tx->commitOnce(result); return {result,true}; } Envelope lost(const std::string& rid,const std::string& target,const std::string& context) { return ports.recoverRevoke(rid,target,context); } }; std::string legacyValue(const std::string& value,bool approved,bool selected) { if (!approved || !selected || value.empty()) throw std::runtime_error("Local approval/selection required"); return value; // Only the agreed renderer/driver payload. } }