runFlow executes a prepared flow in the background and records the result. The optional display prompt runs concurrently: a decline (or other failure) aborts the flow, while an undeliverable prompt degrades to the manual fallback without tearing the flow down, so the user can still authorize out of
(ctx context.Context, cancel context.CancelFunc, plan *flowPlan)
| 194 | // the flow, while an undeliverable prompt degrades to the manual fallback without |
| 195 | // tearing the flow down, so the user can still authorize out of band. |
| 196 | func (m *Manager) runFlow(ctx context.Context, cancel context.CancelFunc, plan *flowPlan) { |
| 197 | defer cancel() |
| 198 | |
| 199 | if plan.display != nil { |
| 200 | go func() { |
| 201 | err := plan.display(ctx) |
| 202 | switch { |
| 203 | case err == nil: |
| 204 | // Prompt shown; the flow completes when the token arrives. |
| 205 | case ctx.Err() != nil: |
| 206 | // The flow is already ending (timed out or cancelled elsewhere), |
| 207 | // so there is nothing to fall back to. Checking this before the |
| 208 | // fallback also prevents misreading a context-cancelled prompt as |
| 209 | // a transport failure. |
| 210 | case errors.Is(err, ErrPromptUnavailable) && plan.fallback != nil: |
| 211 | // The client advertised the capability but could not deliver the |
| 212 | // prompt. Surface the manual instructions instead of failing, and |
| 213 | // keep the background flow alive so the user can still authorize. |
| 214 | m.logger.Debug("authorization prompt undeliverable; falling back to manual instructions", "reason", err) |
| 215 | m.fallBackToUserAction(plan.fallback) |
| 216 | default: |
| 217 | // A user decline (ErrPromptDeclined) or any other prompt failure |
| 218 | // ends the flow. |
| 219 | m.logger.Debug("authorization prompt closed", "reason", err) |
| 220 | cancel() |
| 221 | } |
| 222 | }() |
| 223 | } |
| 224 | |
| 225 | tok, err := plan.run(ctx) |
| 226 | m.complete(tok, err) |
| 227 | } |
| 228 | |
| 229 | // fallBackToUserAction promotes a running secure flow to the manual user-action |
| 230 | // channel after its prompt could not be delivered. The background flow keeps |
no test coverage detected