I think there’s a middle ground where the blackholed canister can be assigned sole control over itself, and if it detects that it is no longer functioning correctly it can un-blackhole itself by assigning control to a DAO (though that should be a never scenario that just gives peace of mind that the plausible worst case scenario is temporary custody assigned to a DAO). That significantly limits incentives for governance capture over that DAO while, imo, meeting the bar for ‘non-custodial’.
That’s the path Jupiter Faucet is taking for the core value moving canisters.
I think it should be secure enough via the II shared email. II is verifying the ownership, so I think you should be able to fully rely on that. (given that you require the user to sign-in via II where he granted your app access to the shared email before he is able to claim the gift)
just a sidenote here → the developer didn’t use II here for authentication and implemented his own dedicated solution for email verification.
that sounds great, assuming it would always work. I am not sure if that can always be guaranteed though how would a canister automatically detect that it is no longer functioning correctly?
If the canister depends on an external API (e.g. a system canister such as NNS governance or the ICP ledger/index canisters) the canister can catch arbitrary errors attempting to use that API. Depending on the canister, it could either increment an error counter or log the timestamp of the last successful call. If the counter exceeds a certain theshold (consecutive failures in a row) or a specified period of time has gone by without a successful call, the canister can assign control of itself to a pre-specified recovery principal (a ‘lifeline’ canister in Jupiter Faucet terms, and the lifeline is intended as a DAO-controlled canister).
Basically the canister should catch any unexpected errors and use that information to decide if it needs to unblackhole itself.
The only reason this wouldn’t work is if an error isn’t caught (but it’s fairly easy to write/verify code that has a catch all). If the call to the management canister somehow fails to reassign control, that would be due to a breaking change to the management canister API which should never be allowed to happend, and if it did the NNS would revert that change (it would be crazy not to).