RocketDaoNodeTrusted - DAO takeover during deployment/bootstrapping
The initial deployer of the `RocketStorage` contract is set as the Guardian/Bootstrapping role. This guardian can bootstrap the TrustedNode and Protocol DAO, add members, upgrade components, change settings.\\nRight after deploying the DAO contract the member count is zero. The Guardian can now begin calling any of the bootstrapping functions to add members, change settings, upgrade components, interact with the treasury, etc. The bootstrapping configuration by the Guardian is unlikely to all happen within one transaction which might allow other parties to interact with the system while it is being set up.\\n`RocketDaoNodeTrusted` also implements a recovery mode that allows any registered node to invite themselves directly into the DAO without requiring approval from the Guardian or potential other DAO members as long as the total member count is below `daoMemberMinCount` (3). The Guardian itself is not counted as a DAO member as it is a supervisory role.\\n```\\n/\\*\\*\\*\\* Recovery \\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*/\\n   \\n// In an explicable black swan scenario where the DAO loses more than the min membership required (3), this method can be used by a regular node operator to join the DAO\\n// Must have their ID, email, current RPL bond amount available and must be called by their current registered node account\\nfunction memberJoinRequired(string memory \\_id, string memory \\_email) override public onlyLowMemberMode onlyRegisteredNode(msg.sender) onlyLatestContract("rocketDAONodeTrusted", address(this)) {\\n    // Ok good to go, lets add them\\n    (bool successPropose, bytes memory responsePropose) = getContractAddress('rocketDAONodeTrustedProposals').call(abi.encodeWithSignature("proposalInvite(string,string,address)", \\_id, \\_email, msg.sender));\\n    // Was there an error?\\n    require(successPropose, getRevertMsg(responsePropose));\\n    // Get the to automatically join as a member (by a regular proposal, they would have to manually accept, but this is no ordinary situation)\\n    (bool successJoin, bytes memory responseJoin) = getContractAddress("rocketDAONodeTrustedActions").call(abi.encodeWithSignature("actionJoinRequired(address)", msg.sender));\\n    // Was there an error?\\n    require(successJoin, getRevertMsg(responseJoin));\\n}\\n```\\n\\nThis opens up a window during the bootstrapping phase where any Ethereum Address might be able to register as a node (RocketNodeManager.registerNode) if node registration is enabled (default=true) rushing into `RocketDAONodeTrusted.memberJoinRequired` adding themselves (up to 3 nodes) as trusted nodes to the DAO. The new DAO members can now take over the DAO by issuing proposals, waiting 2 blocks to vote/execute them (upgrade, change settings while Guardian is changing settings, etc.). The Guardian role can kick the new DAO members, however, they can invite themselves back into the DAO.\\n```\\nsetSettingBool("node.registration.enabled", true);     \\n```\\n
Disable the DAO recovery mode during bootstrapping. Disable node registration by default and require the guardian to enable it. Ensure that `bootstrapDisable` (in both DAO contracts) performs sanity checks as to whether the DAO bootstrapping finished and permissions can effectively be revoked without putting the DAO at risk or in an irrecoverable state (enough members bootstrapped, vital configurations like registration and other settings are configured, …).
```\\n/\\*\\*\\*\\* Recovery \\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*/\\n   \\n// In an explicable black swan scenario where the DAO loses more than the min membership required (3), this method can be used by a regular node operator to join the DAO\\n// Must have their ID, email, current RPL bond amount available and must be called by their current registered node account\\nfunction memberJoinRequired(string memory \\_id, string memory \\_email) override public onlyLowMemberMode onlyRegisteredNode(msg.sender) onlyLatestContract("rocketDAONodeTrusted", address(this)) {\\n    // Ok good to go, lets add them\\n    (bool successPropose, bytes memory responsePropose) = getContractAddress('rocketDAONodeTrustedProposals').call(abi.encodeWithSignature("proposalInvite(string,string,address)", \\_id, \\_email, msg.sender));\\n    // Was there an error?\\n    require(successPropose, getRevertMsg(responsePropose));\\n    // Get the to automatically join as a member (by a regular proposal, they would have to manually accept, but this is no ordinary situation)\\n    (bool successJoin, bytes memory responseJoin) = getContractAddress("rocketDAONodeTrustedActions").call(abi.encodeWithSignature("actionJoinRequired(address)", msg.sender));\\n    // Was there an error?\\n    require(successJoin, getRevertMsg(responseJoin));\\n}\\n```\\n