0008: MIDOT sign-in
Michigan TREDIS users sign in to MIDOT and manage their passwords
- ID: PRD-0008
- Status: Accepted
- Decision maker: Trevor Gerhardt
- Scope: MIDOT, Services, and Email
- Product owner: Trevor Gerhardt
- Design owner: Trevor Gerhardt
- Engineering owner: Conveyal
- Last reviewed: 2026-10-15
- Related issues or projects: Not applicable. This work follows a direct planning request.
- Related designs: The legacy TREDIS sign-in screen. It has Username, Password, a LOGIN button, and "Forgot password?" and "Reset password?" links.
- Related ADRs: ADR 0015, ADR 0014, ADR 0011
- Related user documentation: MIDOT guide
Summary
MIDOT users sign in with their existing TREDIS username and password. The sign-in screen keeps the features of the legacy TREDIS screen and uses Michigan Digital Guidelines components. Users can request a password reset link by email, or change a known password. All MIDOT pages and APIs require a session.
User problem and evidence
Today, Vercel deployment protection is the only access control for MIDOT.
It does not identify the person who uses the tool, and Michigan users cannot use it.
Michigan users already have TREDIS accounts in tredis_global_dynamic and sign in at the legacy TREDIS site.
The TREDIS introduction describes that sign-in.
The legacy data has no password reset table. The legacy stp_getLoginInfo procedure returned decrypted passwords to the application.
MIDOT must not copy that behavior.
Goals and success measures
| Goal | Measure | Target or review method |
|---|---|---|
| Only eligible Michigan users use MIDOT | Browser tests for each account state | Ineligible accounts cannot sign in or get a link |
| No page or API is available without a session | Browser and HTTP tests without a session | Every protected path refuses or redirects |
| Users can recover access without support | Browser test of the full reset flow | Email, link, new password, and sign-in all succeed |
| Passwords stay inside the server and MySQL | Code review and service projection tests | No password or ciphertext in a result or log |
| Legacy reports see MIDOT sessions | Service test of the session log row | One MIDOT row for each sign-in |
Non-goals
- Sign-in through
@concourse/auth, or a mapping between Concourse and TREDIS identities. - Creation, deletion, or administration of TREDIS users.
- Rate limits, account lockout, or failed-attempt counts.
- Terms acceptance and the forced password change on the first sign-in.
- Session revocation before the session expires.
- A change-password link for signed-in users.
- Access decisions from contracts, licenses, or Michigan product flags other than
isMichiganUser. - Sign-in with the TREDIS administrator password.
Users and use cases
Use case: Sign in to MIDOT
- Actor: A Michigan TREDIS user.
- Need: Sign in with the existing TREDIS username and password.
- Goal: Use the MIDOT tools.
Use case: Recover a forgotten password
- Actor: A Michigan TREDIS user who does not know the password.
- Need: Receive a reset link at the account email address.
- Goal: Set a new password without help from support.
Use case: Change a known password
- Actor: A Michigan TREDIS user who knows the current password.
- Need: Replace the password.
- Goal: Keep the account secure.
Requirements
An eligible user has isMichiganUser set to YES, has no past UserExpirationDate, and does not have OnMaintenance set.
Sign-in, reset email, and password changes apply the same eligibility rule.
PRD-0008-US-01: Sign in
- Story status: Current
- Replaces: N/A
- Replaced by: N/A
- User need: As a Michigan TREDIS user, I want to sign in with my TREDIS username and password, so that I can use MIDOT.
- Requirement:
/loginaccepts a username and password. An eligible user with a correct password receives a session for 8 hours from sign-in. - Done when:
- An eligible user with a correct password goes to the requested same-origin path, or to
/. - An unknown user, a wrong password, and an ineligible user all see the same error message.
- A redirect to another origin goes to
/instead. - A signed-in user who opens
/logingoes to/. - The session ends 8 hours after sign-in, and the user must sign in again.
- Unavailable storage shows a safe "not available" message and creates no session.
- An eligible user with a correct password goes to the requested same-origin path, or to
PRD-0008-US-02: Protected pages and APIs
- Story status: Current
- Replaces: N/A
- Replaced by: N/A
- User need: As a MIDOT operator, I want every page and API to require a session, so that only signed-in Michigan users can see data.
- Requirement: All pages and APIs except sign-in, forgot password, and reset password require a valid session.
- Done when:
- A protected API request without a valid session returns HTTP 401 and no data.
- A protected page without a session goes to
/login?redirect=<path>. - The header shows the user's real name, or the username when the real name is empty.
PRD-0008-US-03: Sign out
- Story status: Current
- Replaces: N/A
- Replaced by: N/A
- User need: As a signed-in user, I want to sign out, so that the next person on the computer cannot use my session.
- Requirement: The header has a "Sign out" button. Sign-out ends the session and goes to
/login. - Done when:
- After sign-out, protected pages and APIs require a new sign-in.
- Sign-out records the end time in the session log row of that session.
PRD-0008-US-04: Request a reset link
- Story status: Current
- Replaces: N/A
- Replaced by: N/A
- User need: As a user who forgot my password, I want a reset link by email, so that I can set a new password.
- Requirement:
/forgot-passwordaccepts a username. MIDOT emails a reset link that expires after 30 minutes to an eligible user with an email address. - Done when:
- Every request shows the same confirmation, whether or not MIDOT sent an email.
- An unknown user, an ineligible user, and a user with no email address receive no email.
- The email contains a plain link to
/reset-password, the 30-minute expiry, and a note to ignore the email if the user did not ask for it.
PRD-0008-US-05: Set a new password with a reset link
- Story status: Current
- Replaces: N/A
- Replaced by: N/A
- User need: As a user with a reset link, I want to set a new password, so that I can sign in again.
- Requirement: A valid reset link opens a form for a new password. A successful change goes to
/loginwith a success message. - Done when:
- An expired link, a changed link, or a used link shows an error and a way to request a new link.
- After a password change, all earlier links for that user stop working.
- The user must sign in with the new password. MIDOT does not start a session after the change.
- The new password follows the password rules.
PRD-0008-US-06: Change a known password
- Story status: Current
- Replaces: N/A
- Replaced by: N/A
- User need: As a user who knows my password, I want to change it from the sign-in screen, so that I can replace it without email.
- Requirement:
/reset-passwordwithout a link accepts a username, the current password, and a new password. - Done when:
- An eligible user with the correct current password can set a new password that follows the password rules.
- A wrong current password, an unknown user, and an ineligible user all see the same error message.
- A successful change goes to
/loginwith a success message, and outstanding reset links stop working.
PRD-0008-US-07: Password rules
- Story status: Current
- Replaces: N/A
- Replaced by: N/A
- User need: As a user, I want clear password rules, so that I can choose a valid password the first time.
- Requirement: A new password has 12 to 47 UTF-8 bytes. It is different from the username and the current password. There are no character-class rules.
- Done when:
- Each broken rule shows a specific message at the new password field.
- The rule checks run on the server. Browser checks only give earlier feedback.
PRD-0008-US-08: Legacy session log
- Story status: Current
- Replaces: N/A
- Replaced by: N/A
- User need: As a TREDIS administrator, I want MIDOT sign-ins in the legacy session log, so that legacy reports include MIDOT use.
- Requirement: Each sign-in adds one
tbluserlogrow withProductset toMIDOT. - Done when:
- The row has the user and client identifiers, the username, the role, the start time, and a new login access key.
- The row has the client IP address when it fits the column, and the browser name cut to the column width.
- The row has the deployed version and no password.
- Legacy TREDIS sign-in data for the user does not change.
Implementation
ADR 0015 records the design. The MIDOT guide describes the routes, settings, and local use. Services owns the sign-in workflows and the TREDIS Global Dynamic sign-in service. RSDB owns their legacy reads and writes. Contracts owns the HTTP bodies and the password rules. MIDOT owns the cookie, reset tokens, routes, and pages. The reset email sender is not decided, so production reset email is not configured. Vercel deployment protection stays on until launch.
Experience and content
Entry points and main flow. A visit to any protected page without a session goes to /login.
After sign-in, the user returns to the requested page. The header shows the user's name and a "Sign out" button.
Screens. Each screen uses the standard MIDOT page with the Michigan header and footer. Each screen uses Michigan Digital Guidelines components, not the teal and gold legacy style.
| Screen | Content |
|---|---|
Sign in, /login | Username and Password inputs, a "Sign in" button, and "Forgot password?" and "Reset password?" links |
Forgot password, /forgot-password | Username input, a "Send reset link" button, and a link back to sign-in |
| Reset password with a link | New password and Confirm new password inputs, and a "Change password" button |
Reset password, /reset-password | Username, Current password, New password, and Confirm new password inputs, and a "Change password" button |
Loading, success, and error states. Submit buttons show a loading state and cannot be pressed twice. Errors and confirmations use an alert above the form.
| State | Message |
|---|---|
| Sign-in failure | The username or password is not correct. |
| Change failure | The username or current password is not correct. |
| Reset link requested | If this account can receive email, we sent a reset link. The link expires in 30 minutes. |
| Reset link not valid | This reset link is not valid or has expired. Request a new link. |
| Password changed | Your password is changed. Sign in with the new password. |
| Storage or email unavailable | Sign-in is not available now. Try again later. |
User-visible terms. Use "Sign in" and "Sign out". The /login path keeps the legacy name.
Keep the legacy link labels "Forgot password?" and "Reset password?".
Accessibility. Every input has a visible label. Field errors connect to their input.
The alert gets focus after a failed submit. Inputs use the username, current-password, and new-password autocomplete values.
The browser suite scans each screen and state for WCAG 2.1 Level A and AA violations.
Constraints and dependencies
- ADR 0015 owns the session, reset link, and code ownership design.
- The TREDIS Global Dynamic service verifies passwords inside MySQL and needs
RACKSPACE_TREDIS_LEGACY_ENCRYPTION_KEY. - The legacy encrypted password column limits a password to 47 UTF-8 bytes.
- The legacy user tables use latin1. A username or password with other characters cannot match.
@concourse/emailsends only toRESEND_TEST_RECIPIENTtoday. MIDOT production email needs a deliberate change to that rule.- Open dependency: the reset email sender address and its verified Resend domain are not decided.
- There is no rate limit. Password guessing and reset email volume have no limit except Vercel platform protection.
- Vercel deployment protection stays on until launch. A separate change removes it.
User documentation
- Audience: Michigan TREDIS users of MIDOT.
- Tasks to explain: Sign in, sign out, request a reset link, and change a known password.
- Agreed terms: Sign in, sign out, reset link, and the legacy link labels.
- Examples or screenshots needed: The sign-in screen and the reset email.
- Published documentation: Not applicable until delivery.
Revision history
No revisions.