|
| 1 | +# Application logic |
| 2 | + |
| 3 | +!!! info "See also" |
| 4 | + |
| 5 | + More specific user flow diagrams: [Enrollment pathways](../enrollment-pathways/README.md) |
| 6 | + |
| 7 | +This page describes how Cal-ITP Benefits defines user flows through the following high-level _phases_: |
| 8 | + |
| 9 | +1. [Initial setup](#initial-setup) |
| 10 | +1. [Identity proofing](#identity-proofing) |
| 11 | +1. [Eligibility verification](#eligibility-verification) |
| 12 | +1. [Enrollment](#enrollment) |
| 13 | + |
| 14 | +```mermaid |
| 15 | +flowchart LR |
| 16 | + start((Start)) |
| 17 | + entry[Initial setup] |
| 18 | + identity[Identity proofing] |
| 19 | + eligibility[Eligibility verification] |
| 20 | + enrollment[Enrollment] |
| 21 | + complete((End)) |
| 22 | + style complete stroke-width:2px |
| 23 | +
|
| 24 | + start --> entry |
| 25 | + entry --> identity |
| 26 | + identity --> eligibility |
| 27 | + eligibility --> enrollment |
| 28 | + enrollment --> complete |
| 29 | +``` |
| 30 | + |
| 31 | +The structure of the source code in [`benefits/`](https://github.com/cal-itp/benefits/tree/dev/benefits) |
| 32 | +generally follows from these phases: |
| 33 | + |
| 34 | +- [`benefits/core/`](https://github.com/cal-itp/benefits/tree/dev/benefits/core) implements shared logic and models, and |
| 35 | + defines the user's entrypoint into the app |
| 36 | +- [`benefits/oauth/`](https://github.com/cal-itp/benefits/tree/dev/benefits/oauth) implements identity proofing |
| 37 | +- [`benefits/eligibility/`](https://github.com/cal-itp/benefits/tree/dev/benefits/eligibility) implements eligibility |
| 38 | + verification |
| 39 | +- [`benefits/enrollment/`](https://github.com/cal-itp/benefits/tree/dev/benefits/enrollment) implements enrollment |
| 40 | + |
| 41 | +Each of these directories contains a standalone Django app registered in the [settings](../configuration/README.md#django-settings). |
| 42 | + |
| 43 | +All of the common logic and [database models and migrations](./models-migrations.md) are defined in `benefits.core`, and this |
| 44 | +app is imported by the other apps. |
| 45 | + |
| 46 | +## Django request pipeline |
| 47 | + |
| 48 | +Each request to the Benefits app is ultimately a [Django request](https://docs.djangoproject.com/en/5.0/ref/request-response/) |
| 49 | +and goes through the [Django HTTP request pipeline](https://docs.djangoproject.com/en/5.0/topics/http/). |
| 50 | + |
| 51 | +Benefits uses middleware to pre- and post-process requests for (view) access control, session configuration, and analytics. |
| 52 | +Benefits also uses context processors to enrich the Django template context with data needed for rendering on the front-end. |
| 53 | + |
| 54 | +!!! example "Key supporting files" |
| 55 | + |
| 56 | + [`benefits/core/context_processors.py`][core-context-processors] |
| 57 | + |
| 58 | + [`benefits/core/middleware.py`][core-middleware] |
| 59 | + |
| 60 | +In general, the flow of a Django request looks like: |
| 61 | + |
| 62 | +```mermaid |
| 63 | +flowchart LR |
| 64 | + user((User)) |
| 65 | + style user stroke-width:2px |
| 66 | +
|
| 67 | + pre_middleware[Request middleware] |
| 68 | + view_middleware[View-specific middleware] |
| 69 | + context[Context processors] |
| 70 | + view[View function] |
| 71 | + post_middleware[Response middleware] |
| 72 | +
|
| 73 | + user -- Request --> pre_middleware |
| 74 | + pre_middleware -- Request --> view_middleware |
| 75 | + view_middleware -- Request --> context |
| 76 | + context -- Request --> view |
| 77 | + view -- Response --> post_middleware |
| 78 | + post_middleware -- Response --> user |
| 79 | +``` |
| 80 | + |
| 81 | +## Initial setup |
| 82 | + |
| 83 | +In this phase, the user makes the initial selections that will configure the rest of their journey. |
| 84 | + |
| 85 | +!!! example "Entrypoint" |
| 86 | + |
| 87 | + [`benefits/core/views.py`][core-views] |
| 88 | + |
| 89 | +!!! example "Key supporting files" |
| 90 | + |
| 91 | + [`benefits/core/models.py`][core-models] |
| 92 | + |
| 93 | + [`benefits/core/session.py`][core-session] |
| 94 | + |
| 95 | +```mermaid |
| 96 | +flowchart LR |
| 97 | + session[(session)] |
| 98 | + analytics[[analytics]] |
| 99 | +
|
| 100 | + start((Start)) |
| 101 | + pick_agency["`Agency picker |
| 102 | + modal`"] |
| 103 | + agency(("`Agency |
| 104 | + selected`")) |
| 105 | + eligibility(("`Eligibility type |
| 106 | + selected`")) |
| 107 | + next>"`_Next phase_`"] |
| 108 | + style next stroke-width:2px |
| 109 | +
|
| 110 | + start -- "1a. Lands on index" --> pick_agency |
| 111 | + start -- "1b. Lands on agency index" --> agency |
| 112 | + %% invisible links help with diagram layout |
| 113 | + start ~~~ session |
| 114 | + start ~~~ agency |
| 115 | +
|
| 116 | + pick_agency -- 2. Chooses agency --> agency |
| 117 | + agency -- 3. Chooses enrollment pathway --> eligibility |
| 118 | +
|
| 119 | + eligibility -- 4. continue --> next |
| 120 | +
|
| 121 | + agency -. update -.-o session |
| 122 | + eligibility -. update -.-o session |
| 123 | + eligibility -. selected eligibility verifier -.-o analytics |
| 124 | +``` |
| 125 | + |
| 126 | +Depending upon the choice of enrollment pathway, the _Next phase_ above may be: |
| 127 | + |
| 128 | +- [Identity proofing](#identity-proofing), for all flows that require user PII (such as for verifying age). |
| 129 | +- [Eligibility verification](#eligibility-verification), for Agency card flows that require a physical card from the transit |
| 130 | + agency. |
| 131 | + |
| 132 | +## Identity proofing |
| 133 | + |
| 134 | +In this phase, Cal-ITP Benefits takes the user through an [OpenID Connect (OIDC)](https://openid.net/developers/how-connect-works/) |
| 135 | +flow as a Client (the Relying Party or RP) of the CDT Identity Gateway (the Identity Provider or IDP), via Login.gov. |
| 136 | + |
| 137 | +The CDT Identity Gateway transforms PII from Login.gov into anonymized boolean claims that are later used in |
| 138 | +[eligibility verification](#eligibility-verification). |
| 139 | + |
| 140 | +!!! example "Entrypoint" |
| 141 | + |
| 142 | + [`benefits/oauth/views.py`][oauth-views] |
| 143 | + |
| 144 | +!!! example "Key supporting files" |
| 145 | + |
| 146 | + [`benefits/oauth/client.py`][oauth-client] |
| 147 | + |
| 148 | + [`benefits/oauth/redirects.py`][oauth-redirects] |
| 149 | + |
| 150 | +```mermaid |
| 151 | +flowchart LR |
| 152 | + session[(session)] |
| 153 | + analytics[[analytics]] |
| 154 | +
|
| 155 | + start((Initial setup)) |
| 156 | + style start stroke-dasharray: 5 5 |
| 157 | +
|
| 158 | + benefits[Benefits app] |
| 159 | + idg[["`CDT |
| 160 | + Identity Gateway`"]] |
| 161 | + logingov[[Login.gov]] |
| 162 | + claims((Claims received)) |
| 163 | +
|
| 164 | + next>"`_Eligibility |
| 165 | + verification_`"] |
| 166 | + style next stroke-width:2px |
| 167 | +
|
| 168 | + start -- 1. Clicks login button --> benefits |
| 169 | + %% invisible links help with diagram layout |
| 170 | + start ~~~ session |
| 171 | +
|
| 172 | + benefits -- 2. OIDC authorize_redirect --> idg |
| 173 | + benefits -. started sign in -.-o analytics |
| 174 | +
|
| 175 | + idg <-. "3. PII exchange" .-> logingov |
| 176 | + idg -- 4. OIDC token authorization --> claims |
| 177 | +
|
| 178 | + claims -- 5. continue --> next |
| 179 | + claims -. update .-o session |
| 180 | + claims -. finished sign in -.-o analytics |
| 181 | +``` |
| 182 | + |
| 183 | +## Eligibility verification |
| 184 | + |
| 185 | +In this phase, Cal-ITP Benefits verifies the user's claims using one of two methods: |
| 186 | + |
| 187 | +- Claims validation, using claims previously stored in the user's session during [Identity proofing](#identity-proofing) |
| 188 | +- Eligibility API verification, using non-PII claims provided by the user in an HTML form submission |
| 189 | + |
| 190 | +!!! example "Entrypoint" |
| 191 | + |
| 192 | + [`benefits/eligibility/views.py`][eligibility-views] |
| 193 | + |
| 194 | +!!! example "Key supporting files" |
| 195 | + |
| 196 | + [`benefits/eligibility/verify.py`][eligibility-verify] |
| 197 | + |
| 198 | +```mermaid |
| 199 | +flowchart LR |
| 200 | + session[(session)] |
| 201 | + analytics[[analytics]] |
| 202 | +
|
| 203 | + start(("`Previous |
| 204 | + phase`")) |
| 205 | + style start stroke-dasharray: 5 5 |
| 206 | +
|
| 207 | + claims[Session claims check] |
| 208 | + form[HTTP form POST] |
| 209 | + server[[Eligibility Verification server]] |
| 210 | + eligible{Eligible?} |
| 211 | +
|
| 212 | + next>"`_Enrollment_`"] |
| 213 | + style next stroke-width:2px |
| 214 | +
|
| 215 | + stop{{Stop}} |
| 216 | +
|
| 217 | + start -- Eligibility API verification --> form |
| 218 | + form -- Eligibility API call --> server |
| 219 | + form -. started eligibility -.-o analytics |
| 220 | + server --> eligible |
| 221 | +
|
| 222 | + start -- Claims validation --> claims |
| 223 | + session -.-o claims |
| 224 | + claims --> eligible |
| 225 | + claims -. started eligibility -.-o analytics |
| 226 | +
|
| 227 | + eligible -- Yes --> next |
| 228 | + eligible -- No --> stop |
| 229 | + eligible -. update .-o session |
| 230 | + eligible -. returned eligibility -.-o analytics |
| 231 | +``` |
| 232 | + |
| 233 | +## Enrollment |
| 234 | + |
| 235 | +In this final phase, the user registers their contactless payment card with a concession group configured within the |
| 236 | +payment processor (Littlepay). |
| 237 | + |
| 238 | +**_Cal-ITP Benefits never processes, transmits, nor stores the user's payment card details._** |
| 239 | + |
| 240 | +!!! example "Entrypoint" |
| 241 | + |
| 242 | + [`benefits/enrollment/views.py`][enrollment-views] |
| 243 | + |
| 244 | +!!! example "Supporting packages" |
| 245 | + |
| 246 | + [`cal-itp/littlepay`][littlepay] |
| 247 | + |
| 248 | +```mermaid |
| 249 | +sequenceDiagram |
| 250 | +autonumber |
| 251 | +%% Enrollment phase |
| 252 | + actor user as User |
| 253 | + participant benefits as Benefits app |
| 254 | + participant littlepay as Littlepay |
| 255 | + participant analytics as Analytics |
| 256 | +
|
| 257 | +user->>benefits: starts enrollment phase |
| 258 | + activate user |
| 259 | +benefits-->>user: display enrollment index |
| 260 | +user->>littlepay: GET tokenization lib (AJAX) |
| 261 | +littlepay-->>user: tokenization lib .js |
| 262 | +user->>benefits: GET card tokenization access token (AJAX) |
| 263 | + deactivate user |
| 264 | + activate benefits |
| 265 | +benefits->>littlepay: GET API access token |
| 266 | +littlepay-->>benefits: access token |
| 267 | +benefits->>littlepay: GET card tokenization access token |
| 268 | +littlepay-->>benefits: access token |
| 269 | +benefits-->>user: access token |
| 270 | + deactivate benefits |
| 271 | + activate user |
| 272 | +user->>user: click to initiate payment card collection |
| 273 | +user-->>user: display Littlepay overlay |
| 274 | +user-->>analytics: started payment connection |
| 275 | +user->>littlepay: provides debit or credit card details |
| 276 | +littlepay-->>user: card token |
| 277 | +user-->>analytics: closed payment connection |
| 278 | +user->>benefits: POST back card token |
| 279 | + deactivate user |
| 280 | + activate benefits |
| 281 | +benefits->>littlepay: GET API access token |
| 282 | +littlepay-->>benefits: access token |
| 283 | +benefits->>littlepay: GET funding source from card token |
| 284 | +littlepay-->>benefits: funding source |
| 285 | +benefits->>littlepay: enroll funding source in group |
| 286 | +benefits-->>analytics: returned enrollment |
| 287 | + deactivate benefits |
| 288 | +``` |
| 289 | + |
| 290 | +[core-context-processors]: https://github.com/cal-itp/benefits/blob/dev/benefits/core/context_processors.py |
| 291 | +[core-middleware]: https://github.com/cal-itp/benefits/blob/dev/benefits/core/middleware.py |
| 292 | +[core-models]: https://github.com/cal-itp/benefits/blob/dev/benefits/core/models.py |
| 293 | +[core-session]: https://github.com/cal-itp/benefits/blob/dev/benefits/core/session.py |
| 294 | +[core-views]: https://github.com/cal-itp/benefits/blob/dev/benefits/core/views.py |
| 295 | +[eligibility-verify]: https://github.com/cal-itp/benefits/blob/dev/benefits/eligibility/verify.py |
| 296 | +[eligibility-views]: https://github.com/cal-itp/benefits/blob/dev/benefits/eligibility/views.py |
| 297 | +[enrollment-views]: https://github.com/cal-itp/benefits/blob/dev/benefits/enrollment/views.py |
| 298 | +[littlepay]: https://github.com/cal-itp/littlepay |
| 299 | +[oauth-client]: https://github.com/cal-itp/benefits/blob/dev/benefits/oauth/client.py |
| 300 | +[oauth-redirects]: https://github.com/cal-itp/benefits/blob/dev/benefits/oauth/redirects.py |
| 301 | +[oauth-views]: https://github.com/cal-itp/benefits/blob/dev/benefits/oauth/views.py |
0 commit comments