Making decide_expense app-only is the part I liked most. One small catch in the View code: decide() wraps both the server call and shareContextWithModel in the same try. If updateModelContext throws after the decision is already saved, the user sees Could not reach the server, may click again, and then gets an already decided error. Giving the context update its own catch avoids that misleading message.