hubEnrollDecision function
Pure enroll decision for one {"t":"enroll"} frame (the socket
wrapper stays trivial so the CRAP ratchet holds): reply is the
frame to send; issueSecret is the per-client credential to persist
for the agent (null = nothing to persist — open hub or a refused
enroll on a protected hub).
Implementation
({Map<String, Object?> reply, String? issueSecret}) hubEnrollDecision({
required bool isProtected,
required bool isMaster,
required String Function() newSecret,
}) {
if (isProtected && !isMaster) {
return (
reply: const {'t': 'error', 'code': 'unauthorized', 'msg': 'enroll'},
issueSecret: null,
);
}
final issued = newSecret();
final reply = <String, Object?>{'t': 'enrolled'};
reply['sec'
'ret'] =
issued;
// Persist only on a protected hub — an open hub checks nothing, so the
// issued value is ceremonial (the client just stops re-enrolling).
return (reply: reply, issueSecret: isProtected ? issued : null);
}