1
0
Fork 0
mirror of https://github.com/IRS-Public/direct-file.git synced 2025-06-28 15:27:41 +00:00

initial commit

This commit is contained in:
sps-irs 2025-05-29 13:12:11 -04:00
parent 2f3ebd6693
commit 9dd76a786e
3413 changed files with 794523 additions and 1 deletions

1
docs/README.md Normal file
View file

@ -0,0 +1 @@
This is a consolidated set of documentation written to-date during the history of Direct File since 2022.

View file

@ -0,0 +1,35 @@
# Encrypting taxpayer artifacts
Date: 08/21/2023
## Status
Approved
## Context
Our system stores taxpayer artifacts in object storage (AWS S3). These artifacts include files like PDFs of completed tax returns and XML bundles for submission to the Modernized e-File (MeF) system that contain sensitive taxpayer data in the form of personally identifiable information (PII) and federal tax information (FTI).
AWS S3 provides server-side encryption to protect the contents of objects on disk. However, anyone with access to the S3 bucket is able to view the plaintext contents of files. To mitigate the impact of a breach or leak—e.g., a misconfiguration resulting in public access to the S3 bucket or improper file handling by administrators—we want an approach that provides an additional layer of encryption to sensitive files prior to their storage.
## Decision
We will use [Amazon S3 Encryption Client](https://docs.aws.amazon.com/amazon-s3-encryption-client/latest/developerguide/what-is-s3-encryption-client.html) to encrypt taxpayer artifacts containing sensitive information before storing them in object storage. This aligns with [our decision to use S3 for all artifact storage](adr_taxpayer_artifact_storage.md).
We will configure the client to use a symmetric AES-GCM 256-bit wrapping key that is created and managed by AWS Key Management Service (KMS). The client library will use this wrapping key as part of an [envelope encryption scheme](https://docs.aws.amazon.com/amazon-s3-encryption-client/latest/developerguide/concepts.html#envelope-encryption) for encrypting each artifact with a unique data key. The wrapping key will be used only for artifact storage, allowing these encryption and decryption operations to be auditable independently from other KMS operations throughout the system.
## Consequences
- We use an open-source, actively maintained encryption library that limits the need for custom implementation of cryptographic details
- The envelope encryption approach used by the library is conceptually similar to our chosen approach for column-level encryption
- If needed, we can use this same library for [encrypting the content of messages sent to our queues](https://aws.amazon.com/blogs/developer/encrypting-message-payloads-using-the-amazon-sqs-extended-client-and-the-amazon-s3-encryption-client/)
- We already utilize many AWS services and libraries, and as such this decision does not expand the list of third-party providers we rely on. Conversely, this further couples our implementation to AWS; if we move to a new cloud provider we will need to identify a suitable replacement library.
- We can further minimize overhead by enabling automatic key rotation on the wrapping key in AWS KMS
- Developers must use this library exclusively when storing and retrieving taxpayer artifacts containing sensitive information
- Plaintext taxpayer artifacts will not be readily available for debugging and troubleshooting. We will need to plan additional features for this functionality and ensure they are implemented in ways that support operational needs without undermining our security and privacy posture.
- [Additional configuration](https://docs.aws.amazon.com/amazon-s3-encryption-client/latest/developerguide/features.html#multipart-upload) may be necessary if we store files greater than 100MB
## Resources
- [ADR for storing artifacts in S3](docs/adr/adr_taxpayer_artifact_storage.md)
- [Amazon S3 Encryption Client](https://docs.aws.amazon.com/amazon-s3-encryption-client/latest/developerguide/what-is-s3-encryption-client.html)

View file

@ -0,0 +1,60 @@
# AWS KMS Key Management
Date: 10/23/2023
## Status
Draft
## Context
[ADR: Encrypting Taxpayer Data](adr_encrypting-taxpayer-data.md) specifies our strategy for encrypting taxpayer data.
Using AWS KMS keys, our system encrypts sensitive taxpayer data. Since the keys and their access makes
it possible to encrypt and decrypt the system's production data, we want to specify the standard operating procedure for
brokering, configuration, access management, and rotation for these keys.
## Decision
### Key Creation and Configuration
The IRS team overseeing our application infrastructure will be responsible for setting up the KMS keys for each environment/region,
and managing access to those keys.
We use KMS Customer Managed Keys with usage of `ENCRYPT_DECRYPT` and the encryption algorithm of
`SYMMETRIC_DEFAULT` (which is a 256-bit AES-GCM algorithm).
Additionally, the keys are set up as multi-region to support the IRS environments' ACTIVE-ACTIVE application infrastructure.
Our application(s) using the KMS encryption keys are configured to specify the key ARN, in keeping with AWS's recommendations
for using [strict mode](https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/best-practices.html#strict-discovery-mode).
### Access Management
* The least amount of privilege is given to application users of the KMS keys, which are governed by a combination of key
policies and IAM policies managed by IRS administrators.
* Direct File has access to the encryption keys for the following actions:
* GenerateDataKey
* kms:Encrypt
* kms:Decrypt
* The IRS's AWS cloud administrators have full key access rights.
### Rotation
We have automatic key rotation in KMS with the default schedule for customer managed keys.
KMS wrapping key rotation will happen automatically without intervention or need to update our configuration, as the properties
of the key never change (only the cryptographic material/secrets).
(from https://docs.aws.amazon.com/kms/latest/developerguide/rotate-keys.html):
> When you enable automatic key rotation for a KMS key, AWS KMS generates new cryptographic material for the KMS key every year.
> AWS KMS saves all previous versions of the cryptographic material in perpetuity so you can decrypt any data encrypted with that KMS key.
> AWS KMS does not delete any rotated key material until you delete the KMS key. You can track the rotation of key material for your KMS keys in Amazon CloudWatch and AWS CloudTrail.
## Consequences
- We follow recommended practices so that we have confidence in the maintainability and validity of our key management strategies
- We limit access to our KMS encryption keys to only our application and IRS cloud administrators
- With automated key rotation, rotations are passive to our application, with no configuration updates needed.
- Importantly, if keys are compromised, automated key rotation will not mitigate the issue.
## Resources
- [ADR for encrypting taxpayer data](adr_encrypting-taxpayer-data.md)
- https://docs.aws.amazon.com/kms/latest/developerguide/rotate-keys.html

View file

@ -0,0 +1,178 @@
# Github Branching Strategy for FS25 Production Development
Status: Accepted
Date: 2024-11-21
Decision: Option 1 - Set `main` as "future features" branch for all TY25+ work and create a long-term `production` TY24 branch and merge from `production` into main
## Context and Problem Statement
[//]: # ([Describe the context and problem statement, e.g., in free form using two to three sentences. You may want to articulate the problem in form of a question.])
This ADR documents our short-term Github branching strategy for filing season 2025 (FS25), starting in January 2025.
We don't currently support multiple tax years simultaneously in Direct File and all active tax logic in the repo at any point in time is currently for a single tax year. In the pilot year, filing season 2024 (FS24), we only supported tax year 2023 (TY23) and in the second year starting in January 2025 (FS25), we plan to only support tax year 2024 (TY24). We also have an additional product goal of keeping Direct File open year-round, but only supporting one tax year at a time for now. Supporting multiple tax years concurrently in production is on the roadmap for TY26/FS27.
Our development goals in the second year of Direct File are to simultaneously support two modes of operating within our single Github repository:
1. Support the active tax logic in production for TY24, fix bugs and potentially add small tax scope items that should be deployed to taxpayers in production during FS25
1. Start development on future scope beyond this year - Factgraph and foundational improvements and future TY25 tax logic that should not be deployed to taxpayers in production until after FS25
## Decision Drivers
Some factors considered in the decision
- Ease of use for developers: how can we make it easy for developers to use the right branch by default? A majority of the team will focus on active production TY25 tax scope and a minority will be working on future scope
- Complexity for devops: understand the workload and changes required for devsecops with each strategy
- Error workflow: if a PR is merged to the wrong branch, how easy is the workflow for fixing the error?
- Minimize git history issues: consider alternatives to the cherry-picking approach we took last year in order to make production git history cleaner and more accurate. Avoid situations where cherry-picked commits do not include important prerequisite changes.
## Considered Options
### Option 1: Set `main` as "future features" branch for all TY25+ work and create a long-term `production` TY24 branch and merge from `production` into main
#### Branches
- `main`: The evergreen branch consisting of both future features and production TY24 code. This branch is *not* to be deployed to taxpayers in production during FS25
- `production`: The long-running branch consisting of only production TY24 code, to be deployed to taxpayers in production during FS25 on a weekly basis via release branches.
- Pre-commit hooks and branch protection rules will also need to be configured on this new branch enforcing code review, CI tests, scans and more
#### Releases and Deployment
- Cut releases from `production`
- Deploy from `production`
- Reserve the TEST environment for regular deployments from `main` for testing future features
- Continue to use the PRE-PROD environment for `production` branch testing
- Continue these two branches throughout the year
- When it is time to cutover to TY25 (December 2025 or January 2026), fork a new `production` branch from `main` and continue the same processes for the next tax year (or move to Option 3 or another long-term branching strategy)
#### Developer workflows
The first step is to identify whether the work is destined for the current `production` branch, or whether it is work that is only for future tax years.
##### For production TY24
1. Check out and pull `production` branch
- `git checkout production`
- `git pull`
1. Create/check out new branch for feature/fix work
- `git checkout -b branch-for-ticket`
1. Create a PR for changes into `production` branch
1. Squash and merge PR into `production` branch
1. Create a second PR from the `production` branch into `main` and resolve conflicts if needed. We are unable to automate this step at this time, but would like to merge into `main` on every PR in order to make the conflict resolution easier.
- Note: Regular merge (not "Squash and Merge") is recommended here
##### For future features
1. Check out `main` branch
1. Make PR against `main` branch
1. Merge into `main` branch
#### Error workflow
##### If a change intended for `production` is accidentally made on `main`
1. Revert PR from `main`
1. Make new PR against `production` and follow developer workflow for production TY24 above
##### If a change intended for `main` is accidentally made on `production`
1. Notify release manager in the event the change might be destined for deployment and coordinate as needed
1. Revert PR from `production`
1. Make new PR against `main` and follow developer workflow for production TY24 above
### Option 2: Set `main` as the production TY24 branch and create a long-term "future features" branch for all TY25+ work and merge it back into `main`
#### Branches
- `main`: The main production branch consisting of only production TY24 code, to be deployed to taxpayers in production during FS25 on a weekly basis via release branches
- `future`: The long-running branch consisting of only future features TY25+ code, *not* to be deployed to taxpayers in production during FS25
#### Releases and Deployment
- Cut releases from `main`
- Deploy from `main`
- Reserve a lower environment for regular dpeloyments from `future` for testing future features
- Continue these two branches throughout the year
- When it is time to cutover to TY25 (December 2025 or January 2026), fork a new `main` branch from `future` and continue the same processes for the next tax year
#### Developer workflows
The first step is to identify whether the work is destined for the current `production` branch, or whether it is work that is only for future tax years.
##### For production TY24
1. Check out `main` branch
1. Make PR against `main` branch
1. Merge into `main` branch
1. Create a second PR from the `main` branch into `future` and resolve conflicts if needed. We are unable to automate this step at this time, but would like to merge into `main` on every PR in order to make the conflict resolution easier.
- Note: Regular merge (not "Squash and Merge") is recommended here
##### For future features
1. Check out `future` branch
1. Make PR against `future` branch
1. Merge into `future` branch
#### Error workflow
##### If a change is accidentally merged into `future`
1. Revert PR from `future`
1. Make new PR against `main` and follow developer workflow for future features
##### If a future feature change is accidentally merged into `main`
1. Notify release manager in the event the change might be destined for deployment and coordinate as needed
1. Revert PR from `main`
1. Make new PR against `future` and follow developer workflow for future features
### Option 3: Continue with one `main` branch and use feature flags to control production functionality
Two technical prerequisites are required for this option that do not exist today:
1. Ability to have multiple tax years exist in the codebase simultaneously because the repository will not have a way of separating one tax year from another via branches. This functionality is currently planned for 2026, not 2025.
1. Robust feature flagging: Because there will only be one single `main` branch that is deployed to production, we need to have a feature flag system we are confident in to ensure that future features do not accidentally launch to taxpayers ahead of schedule when they are not fully complete.
#### Branches
- `main`: The evergreen branch consisting of both future features and production TY24 code. This branch is to be deployed to taxpayers in production during FS25 on a weekly basis via release branches
#### Releases and Deployment
- Cut releases from `main`
- Deploy from `main`
- When it is time to cutover to TY25 (December 2025 or January 2026), no actions are necessary because there is no reconciliation / update of branches needed, there is only one `main` branch
#### Developer workflows
##### For production TY24
1. Check out `main` branch
1. Make PR against `main` branch
1. Merge into `main` branch
##### For future features
1. Check out `main` branch
1. Make PR against `main` branch with a feature flag that controls whether taxpayers will have access to the feature in production (for future features, this should likely be set to OFF)
1. Merge into `main` branch
#### Error workflow
##### If a change is accidentally merged into `main`
1. Revert PR from `main`
1. Make new PR against `main` and follow developer workflow for production TY24 above
## Decision Outcome
Chosen option: Option 1: Set `main` as "future features" branch for all TY25+ work and create a long-term `production` TY24 branch and merge from `production` into main in order to minimize the risk of future featues merging into the `production` branch by mistake. This option will maintain stability in `production` for our taxpayers, but will result in slightly more friction in the TY24 developer workflow.
## Pros and Cons of the Options
### Option 1: Set `main` as "future features" branch for all TY25+ work and create a long-term `production` TY24 branch and merge from `production` into main
`+`
- Lower risk of future features slipping into production because `main` as "future features" branch is the default branch
`-`
- Changes to devops workflow for releases and deployment are required because we will now be deploying from `production`
- Higher risk of TY24 changes being made on `main` instead of `production` because `main` is still the default. Developers working on TY24 will need to consciously switch over to the `production` branch, but mistakes on the `main` branch will not lead to taxpayer impact since `main` is not being deployed to production
- Breaks the principle that `main` is always deployable
### Option 2: Set `main` as the production TY24 branch and create a long-term "future features" branch for all TY25+ work and merge it back into `main` at the end
`+`
- `main` continues to be the source of truth for production code and is deployable to production
- No change to devops workflow for releases and deployment, we continue to deploy from `main`
`-`
- Higher risk of future features accidentally slipping into `main` since it is still the default branch, which may lead to production issues with taxpayers
- End of season switchover is a little wonky as `future` becomes `main` and a new `future` is created
### Option 3: Continue with one `main` branch and use feature flags to control production functionality
`+`
- No change to developer workflow in either case of making production TY24 changes or future feature changes
- No change to devops workflow for releases and deployments
`-`
- Will require additional engineering lift to complete the technical prerequisites of supporting multiple tax years at once and building out the feature flag system, that is unclear we have time for before January 2025
## Background information
- Our team is currently using [Github flow](https://docs.github.com/en/get-started/using-github/github-flow)
- Some additional git workflows considered for inspiration were [Gitflow](https://www.atlassian.com/git/tutorials/comparing-workflows/gitflow-workflow) and [Gitlab flow](https://about.gitlab.com/topics/version-control/what-is-gitlab-flow/), neither of which perfectly met our needs in a simple way

View file

@ -0,0 +1,44 @@
# ADR: CSS Preprocessor
Written: 20Jun2023
## Background
CSS has some major problems. Namely, it:
1. lacks variable names and the ability to import variables from other libraries.
1. lacks nesting and other hierarchical structures that are common in components.
1. is global (cascading!), leading to naming conflicts, difficult dead code detection, and difficult maintainbility in large code bases.
1. is constantly updated, and can have different implementations and minor differences between different browsers
To avoid these issues, while adding additional features, most of the web development community uses one or more forms of CSS Preprocessor, preprocessing a superset of CSS into the CSS that will eventually reach the users' browsers.
### Required Features
1. Must be able to implement and rely on the US Web Design System (USWDS)
1. Specifically, we need to interact with and rely on https://github.com/trussworks/react-uswds and https://github.com/uswds/uswds. Both of these systems use SASS and export SASS variables.
1. Must be able to scope CSS, eliminating global classes
1. Must help, not hinder, building an accessible product.
1. Must build output that runs without issue on popular phones and computers
1. Must support mobile development and responsive design
### Evaluation Criteria
1. Interoperability with existing USWDS libraries
1. Reputation within the frontend web development community
1. Output to responsive, mobile-friendly, and accessible design.
## OSS Landscape
There are a few CSS popular preprocessors:
1. [SASS](https://sass-lang.com/), per their own marketing speak, defines themselves as "the most mature, stable, and powerful professional grade CSS extension language in the world." Sass has ~10m weekly downloads on NPM and is increasing in number of downloads.
1. [LESS](https://lesscss.org/) is the main competitor to SASS, and contains many of the same features. Less has ~4m weekly downloads on NPM and is flat in number of downloads.
1. [PostCSS](https://postcss.org/) converts modern css into something most browsers can understand, placing polyfills in place. PostCSS is not a separate languagea -- it's a compile step like babel for greater compatibility. Stylelint and other tools are built on PostCSS
1. [CSS Modules](https://github.com/css-modules/css-modules) provide local scoping for CSS. Styles are defined in a normal css/less/sass file, then are imported into the React components that use those classes.
1. [Tailwind](https://tailwindcss.com/) is noteable for being slightly different than other popular CSS frameworks, and is a css framework -- rather than a preprocessor -- that encourages stylistic, rather than semanetic, classnames directly in markup. It's gaining popularity rapidly (4.7m downloads/wk, up from 3m downloads/wk a year ago). However, it would be hard to integrate with USWDS.
1. [Stylelint](https://stylelint.io/) is a CSS linter used to prevent bugs and increase maintainability of CSS
## Decision
We should run the following CSS Preprocessors:
1. Our CSS Language should be SASS, given its popularity and interoperability with USWDS. Most critically, we can import variable names from USWDS.
1. We should additionally use SASS Modules to scope our CSS to their components, avoiding global cascades.
1. We should use stylelint with its recommended config. We should also use the [a11y](https://www.npmjs.com/package/@ronilaukkarinen/stylelint-a11y) plugin experimentally to see if it helps us with accesibility (though noting that it seems not well supported and we should be willing to drop it).
1. Following our SASS compilation step, we should run postcss to get down to a supported list of browsers that we support via [browserlist](https://github.com/browserslist/browserslist#readme)
Unsurprisingly, when developing for these criteria (and with a sigh of relief that USWDS uses SASS), this is the same CSS stack used by [Create React App](https://create-react-app.dev/docs/adding-a-css-modules-stylesheet).

View file

@ -0,0 +1,54 @@
# Email Allow List for Phase A of Pilot Rollout
Date: 12/28/2023
## Status
Complete
## Context
For the Phase A launch which will be invite-only internal, around 1/29 - early February, we need to restrict access to Direct File using an email allow list. We will be provided a CSV of emails that will need to be checked by Direct File before allowing users to start their tax return. Users will need to authenticate via SADI/ID.me and once they arrive at Direct File, we need to check their SADI email address against our allow list. If the email is not on the allow list, the user should see an error message. The Direct File team does not have access to change anything in PROD, so we will use the following process to coordinate with TKTK, the IRS team who manages the PROD environment.
### Requirements
- Handle ~100s of emails on an allow list
- Accounts on the email allow list get access to Direct File in Phase A
- Accounts not on the email allow list see an error message when they try to go to Direct File
- Email allow list needs to be able to be updated WITHOUT a Prod code deployment
### Background
The current plan for identifying Direct File pilot users for Phase A:
1. An email will be sent to IRS Employees asking for interest in participating in the Direct File pilot
1. IRS Employees will tell us which email to use for the allow list (most likely via email)
1. We recommend using personal email, but we cant be sure someone hasnt already used their IRS email to sign up for IRS Online Account, and dont want to ban them from using DF
1. Well collect those emails and turn them into a .csv for the allow list
1. Employees will be able to use Direct File on campus and during work hours, using IRS machines (some of these employees may not have home computers or modern cell phones)
## Decision
### Email Allow list
- There will be less than 1,000 emails on the email allow list
- The email allow list will be saved in the `artifact-storage` S3 bucket already used by DF backend for storing PDF files
- The format of the email allow list when loaded into S3 will be a CSV of HMAC hashed normalized email addresses and a DF seed in order to prevent plaintext emails to be read
- The DF seed will be used for both
1. Hashing the email addresses in the CSV file and
2. By the DF application to check whether a logged in user is in the email allow list
- Emails will be normalized by performing the following transformations in order:
1. Convert to lower case
1. Trim any leading or trailing spaces
- We will update the `users` DB to store a new column representing whether or not the user is allowed to access the application. We will also use this column to determine whether a user is allowed in phase C, separate ADR to follow
- The alternative to having a DB record for this was to call the SADI PII service every time which risks creating downstream impacts for SADI
### Direct File Implementation
- Set up an environment variable `enforce-email-allow-list` to control whether we will enforce the email allow list in each environment.
- DF Backend app checks environment variable for email allow list. If it is ON, continue:
- On a regular time interval, say every `15 minutes`, DF backend poll S3 for an updated email allow list file:
- If it exists, then load emails into memory
- If the file does not exist, deny all access
- The email allow list contains HMAC hashed email addresses, so DF backend will need to load the user's SADI email and hash it using `HMAC (seed + lowercase(email))` to compare it to values on the email allow list
- For every request to DF backend, check whether the user is allowed
- Check whether user already exists in the DB
- If yes: Check the access granted column to see if the user has been allowed
- If yes: allow access to DF as normal
- If no: backend should respond with a 403 error code with custom message, which the frontend will turn into a user-friendly message
- If no: Check the hashed SADI email against the allow list
- If yes: mark the access granted column as true for the user
- If no: mark the access granted column as false. If the user has been previously allowed, we do not change the access from true to false
- A code deployment is needed in order to turn off the email allow list and move to the next phase (controlled availability)

View file

@ -0,0 +1,98 @@
---
# Configuration for the Jekyll template "Just the Docs"
parent: Decisions
nav_order: 100
title: "Fact-dictionary Testing"
# These are optional elements. Feel free to remove any of them.
status: "Proposed"
date: "2023-07-21"
---
<!-- we need to disable MD025, because we use the different heading "ADR Template" in the homepage (see above) than it is foreseen in the template -->
<!-- markdownlint-disable-next-line MD025 -->
# Fact-dictionary testing
## Context and problem statement
The core logic for how we calculate taxes is expressed through the Fact Dictionary, a configuration of the Fact Graph akin to a database schema (including something akin to views, via our derived facts). Currently, however, we have no direct way to test these configurations; we can test the client and then get at values, but the dictionary is used in more than just the client, and tests for it don't naturally belong there.
## Desirable solution properties
We'd like the solution to this problem to
1. Create test artifacts that can be verified by non-programmer tax experts
2. Allow for quick feedback cycles for developers editing the fact dictionary
3. Alert developers to regressions or new bugs while editing the fact dictionary
4. Identify calculation differences between the frontend and backend
## Considered options
1. Testing via the client directly, by writing vitest tests
2. Testing via calls to the spring API
3. Testing via spreadsheets, using the client test runner as a harness
4. Tests via spreadsheets, using a new scala app that runs tests against the JVM and Node
## Decision Outcome
Chosen option: Test via spreadsheets that are parsed by the client, using the client test runner as a harness. The spreadsheets will test common and edge tax scenarios, to identify possible errors in the fact dictionary.
In some detail, we will
- Create a series of workbooks that have a sheet of "given facts" full of paths to writable facts and their values and a sheet of "expected facts" of derived facts and their expected values.
- Create a test harness (using the JS libraries we use for the client) to watch and execute tests against these spreadsheets, effectively setting everything in the given sheet on a factgraph and then asserting each path in the expected sheet equals its value
### Consequences:
1. Good: If we get the spreadsheet format to be readable enough, we should be able to have the spreadsheets reviewed by someone at the IRS to check for correctness
2. Good: The client APIs are pretty quick to work with, and the vitest runner is familiar and fun
3. Good: Most of the fact dictionary edits happen while building out client code, so the feedback happens where we want it, during the normal development workflow
4. Good: Assuming we get a format we like, it wouldn't be too outlandish to run the same tests against the JVM by rewriting the test harness --- creating the test cases is the really hard part
4. Less good: We're going to be abusing vitest
5. Less good: We won't identify differences between the backend and frontend
6. Neutral but I don't like it: coming up with examples is both subjective and difficult, since you have to do taxes correctly
### Discussion
During the discussion in despair, we decided that looking for differences in the frontend and backend was distinctly secondary and could come later.
Chris made two helpful suggestions:
- We can mine VITA Volunteer Assistors test ([pub 6744](https://www.irs.gov/pub/irs-pdf/f6744.pdf)) for scenarios to test. Sadly, there is no answer key included.
- We will likely want to be able to base scenarios on one another (which I called spreadsheet inheritance to make everyone sad), so that we can test variations
## Pros and Cons of other options
### Testing via the client directly, by writing vitest tests
#### Pros
- Really straightforward, since we just write some tests
- Gets us tests
#### Cons
- Not easily reviewable by non-programmers
- Checking the tests on the JVM requires rewriting all of them
### Testing via calls to the spring API
#### Pros
- Probably good tooling exists --- it's spring
- Checks the test cases against the JVM
#### Cons
- Requires new Java APIs just for this
- Requires running the backend just to run the tests, which isn't where most fact dictionary changes happen
### Tests via spreadsheets, using a new scala app that runs tests against the JVM and Node
#### Pros
- All the pros of the chosen approach, plus gives us Node and JVM testing
#### Cons
- Just literally harder --- we have a lot of what we need in the client already, we'd be spinning up another scala app just for this
- Outside of the usual workflow, since devs would need to run a separate scala build tool just for testing fact dictionary changes

View file

@ -0,0 +1,126 @@
# ADR: Fact Dictionary Modules (and how to test them)
DATE: 11/27/2023
## TL;DR
Creating modules for facts should let us move from an untestable amount of complexity and interactions between facts to well defined boundaries that developers can reason about and test.
## Background
### The hodgepodge of facts and completeness
At the moment we have 451 derived facts and 261 writable facts in the fact dictionary. Any derived fact can depend on any other fact (written or derived from any section of the app), and any fact can be in any state of completeness, which can bubble through derived facts, leading to unexpected outcomes. In particular, bugs or errors written in the "You and Your Family" section might not manifest themselves until the final amount screen. These bugs are common and creating a game of whack-a-mole, and we need to replace whack-a-mole with a stronger system that prevents moles in the first place.
Additionally, the fact dictionary is hard to reason about in its current form due to these sometimes-odd relationships. A developer modifying social security may need to reason about a fact from the filer section that may or may not be intended for usage outside of that section.
In a world where any node can depend on any other node, we have to test everything, everywhere, all of the time, instead of being able to separate our tests into logical chunks and the boundaries between those chunks.
The current state of our fact dictionary looks like ![Current fact graph state, looking complicated!](./supporting-files/adr-namespacing-11-26-23-dictionary.svg)
### Example bugs caused by untested interactions between sections
These are a few examples of where bugs in some sections have manifested in strange ways in the app, but
1. When Married Filing Separately, (MFS), we never collected `secondaryFiler/canBeClaimed` (because it should not matter), but this led to a person getting stuck at the deductions section since `/agi` would be incomplete. We should have made sure that `/filersCouldntBeDependents` was always complete by the end of the spouse section .
2. When filing as either married status, and the filers did not live apart for at least six months, our social security section would break because we did not know if the filers lived apart all year. .
3. Any incompleteness bug in the app will leave `/dueRefund` incomplete (based on the tax calculation being incomplete), and the user will break on the 'tax-amount-number' screen.
### Testing for completeness
We have [completeness tests](../direct-file/df-client/df-client-app/src/test/functionalFlowTests/checkFlowSetsFacts.ts) that can test that a section of the flow will leave certain facts as complete. However, it's unclear which facts we should test for completeness at which points because there are no well defined boundaries between sections. For instance, in example (1) above a test that `/filersCouldntBeDependents` was complete by the end of the spouse section would have prevented the bug, but nobody knew to write that test.
Beyond that, even if we get this right at some point, there's no guarantee it will remain correct, or that developers writing downstream tests will always respect a `/maybeCompleteFact` that gets a default value in derived fact `/alwaysCompleteFact`, there's no guarantee that a downstream fact will correctly use `/alwaysCompleteFact` instead of accidentally using the maybe complete version.
## Proposed solution -- setting healthy boundaries via modules
### Goals
- When working on a section of the app (e.g. a credit like the EITC, or an income type like an SSA-1099), a developer should only need to reason about the facts in that section, and other well-tested, known-to-be-complete facts from other sections.
- Facts that are relied on across sections should be a defined set with high test coverage, and each fact should have a point in the flow where they are known to be complete.
- We should be able to think separately about testing facts within a section, and facts that cross boundaries between sections similar to how we can think about testing implementations and API boundaries.
- Find a way or ways to reduce the risk of unintended consequences when adding, changing, or deleting facts by limiting the possible dependencies of a fact
### Proposal
1. (must) We introduce two new concepts to our facts:
1. A module defines a logical section of the fact dictionary, such as the EITC, the educator deduction, or social security income. It *may* align with a section of the flow, but that is not required, and the fact dictionary continues to not know about the existence of the flow. All facts should exist in a module. During a transitionary period, `ty2022` will be a module.
2. Facts default to being private to their own module. They can be exported from their module for two purposes -- they can be exported for `downstreamFacts` and for `mef`. Our build will fail if a fact in one module depends on a private fact from a different module.
2. We break `ty2023.xml` into multiple files -- one file per module. The module name will be equivalent to the filename -- e.g. `eitc.xml` will produce the module `eitc`. This helps developers understand the scope of their current changes, and is consistent with modularity patterns in programming languages. It additionally allows test files to align their naming with the section of the fact dictionary that they test, and should be helpful towards us tracking per-module test coverage.
3. We test module dependencies at build time, but we will strip away the module information for runtime -- fact dictionary paths are complicated, and December 2023 is not a good time to mess with them. The runtimes on the frontend and backend will continue to run with a full list of facts, like they currently do.
3. (should) We continue writing our fact dictionary tests in vitest tests since we have many existing tests in that framework that we can re-use, and we can easily run these tests. In the future, we may change these to a more language-angostic format such as a spreadsheet.
#### Example
```xml
spouse.xml
<Fact path="/writableLivedApartAllYear">
<Name>Writable lived apart from spouse the whole year</Name>
<Description>
Whether the taxpayer lived apart from their spouse for the whole year.
Use `/livedApartAllYear` for downstream calculations
</Description>
<Writable>
<Boolean />
</Writable>
</Fact>
<Fact path="/livedApartAllYear">
<Name>Lived apart from spouse the whole year</Name>
<Description>
Whether the taxpayer lived apart from their spouse for the whole year.
Takes into account that we only ask this question if the TP and SP
lived apart the last six months.
</Description>
<Export downstreamFacts="true" />
<Derived>
<All>
<Dependency path="/writableLivedApartAllYear" />
<Dependency path="/livedApartLastSixMonths" />
</All>
</Derived>
</Fact>
...
eitc.xml
<Fact path="/eligibleForEitc">
...
<Dependency module="spouse" path="/livedApartAllYear" />
...
</Fact>
```
And with that, our fact dictionary should go from the complicated "any node to any node" setup, to instead look more like this graph, where the exported facts are the edges between namespaces, and we can write tests to check internal to a namespace, or using the boundary between namespaces.
Instead of having to test something as complicated as the above fact graph, we'll instead have something that looks closer to ![Simplified state that collects facts into nodes!](./supporting-files/adr-namespacing-proposal.svg)
Whereas testing the above any node to any node setup seems impossible, this looks like discrete chunks we can think about.
### Build Time Checks
We should build the following tests into our pre-merge CI pipeline:
- (must) A derived fact in a namespace only depends on facts in its own namespace or facts exported from other namespaces. For now I propose this being static analysis, but in the future, the fact graph itself could know about namespaces and do runtime checking.
- (should) A fact that is exported from a namespace is tested to be complete by some point in the flow, before it starts getting used by other namespace (e.g. after you complete the spouse section `/filersCouldntBeDependents` should always be complete). We can use our existing completeness tests for this, but modify them to test "All exported facts from a namespace" rather than a manually created and maybe-out-of-sync list defined in a typescript file.
- (should) Exported facts should be tested for correctness within their own section, and then can be relied on to be correct outside of their section (e.g. we've tested the various combos of `/filersCouldntBeDependents` for each filing status and writable fact scenario. There's no need for the deductions section to check every combo of the tree of facts upstream of `/filersCouldntBeDependents`).
- (must) The MeF integration should only use variables that are exported from a module for MeF. We may not immediately use this functionality, as it requires additional work (MeF sometimes intentionally depends on incomplete varaibles)
### Future work
After this we can investigate any of the following:
1. Using the new, better-defined inputs into a section to inform test coverage of that section (e.g. better understanding that TIN/SSN validity could affect W2 completeness could have prevented as bug TKTK
2. Moving fact dictionary tests from typescript to a language agnostic format
3. Making the fact graph itself aware of namespaces and adding runtime checks.
4. Measuring test coverage of each derived fact (I don't know how to check that we've actually hit every statement in a switch, etc.)
6. Perf improvements to the NP-hard flow tests
But most of the above will be a lot easier if we understand the boundaries we can test instead of trying to test everything, everywhere, all of the time.
## Changelog
1. (12/4/23) Modified the term "namespace" to "module"
2. (12/4/23) Specified file name as module names
3. (12/4/23) Defaulted facts private to their module
4. (12/4/23) Specified how modules will be imported by Dependency blocks

View file

@ -0,0 +1,48 @@
# ADR: Frontend Architectural Constraints for the Spring 2023 Client
Date: 10 May 2023
## Background
In April of 2023, the direct file team decided to prototype a new frontend (different from the developed for usability
tests earlier in the year) that has the following goals:
1. The main source of state/truth is the FactGraph, as provided by the transpiled scala code
2. The screens for the application are driven by a static configuration that maps nodes in the Factgraph to fields on the screen
1. Screens can be conditionally displayed, and the condition is calculated on the basis of data in the Factgraph
2. Groups of screens, called collections, can be repeated - most commonly when a tax return has more than one W2 or Filer
3. All tax calculation is handled by the Factgraph
4. The structure remains a SPA, to take advantage of edge processing of end users when doing Factgraph calculations
5. We can support multiple languages, and translation screens can include user-entered data
6. The application will meet the requirements of WCAG 2.0 and relevant 508 Standards
## Architectural properties
### Major pieces
Work to produce a client with the above properties has been prototyped in df-client as a React app. This app contains some early-stage design decisions:
- a **flow** from a tsx (soon to be xml) file, defines the order of questions in the interview and fields to be displayed on each screen
- the **fact dictionary**, serialized as JSON by the backend, defines the shape of the Factgraph, how facts are calculated/derived, and what the constraints on given facts are
- **translation strings** using i18next/i18next-react are modified to perform string interpolation from the Factgraph, as well as predetermined tax information via user interface text.
The basic mechanics for the client's operation look as follows:
1. On startup, the client initializes a mostly-empty factgraph using the JSON-serialized fact dictionary. This is exported as a global singleton object and is **the** mechanism for conveying tax-data-related state across screens/parts of the application. State that is unrelated to the user's tax data is stored in session storage and will be discussed in later ADRs.
2. A `BaseScreen` component reads the **flow** configuration to configure screens. Each screen contains either text (called `InfoDisplay`) or some number of fields (generically called `Facts`) gathering information from the user from the Factgraph.
1. Each field is responsible for writing its own data into the Factgraph, once those data are valid. Additionally, fields read their initial data from the Factgraph, which allows users to go back to previous screens and edit.
2. The Screen saves the user's data when the taps "Save" and transmits the writable facts back to the server.
3. The URL's within the interview portion of the application are formatted using a nested hierarchy, where each screen's URL reflects the current position in the flow.
4. `Checklist` component reads the **flow** and builds itself based on the category/subcategory/screen/fact configurations therein. The checklist computes the user's progress through the application by looking up which facts are complete and thereby which screens have all of their facts complete. These calculations are made based on the state of the local factgraph.
### Constraints
As we've built out the application, we've assumed the following constraints --- while none of these are set in stone, they are set in code that would require relatively deep changes to undo:
1. Several components use the **flow** configuration independently, and we treat is as, effectively, a global constant. As such, the **flow** configuration itself should be static. It allows for conditionals, so the user's flow can respond to change, but all possible paths should be in the flow at startup.
1. Conditionals in the flow expect a simple boolean value from the Factgraph --- any complex logic for flow conditionals should be computed in the Factgraph and exposed as a boolean derived fact
2. The application's overall state is opaque to react, which makes having multiple independent parts of the application concurrently rendered and synchronized difficult. For example, if we wanted to keep the checklist visible as the user entered facts, and have the checklist change its state automatically as the user completed various facts, this would require some creative engineering. As it is currently, this is not an issue --- react is re-rendering whole screens as the user works through the application, and it pulls the facts it needs for a given screen from the Factgraph on render. From the user's perspective, the checklist _is_ always up-to-date, because every time a user looks at the checklist, it will re-render and pull the latest overall state from the factgraph to calculate itself. The same is true of each individual screen in the interview --- they all replace one another, which necessitates re-rendering, and therefore screens are always constantly from the factgraph. We only run into problems if we want multiple screens that currently are considered to be rendered alone to be rendered together on the same screen and react to one another.
3. While we can reference facts in translation strings (via interpolation), the template language in i18next is VERY simple. I don't have a good solution here, other than read the docs and expect we'll need to code some solutions around it.
## Status
Documentation

View file

@ -0,0 +1,154 @@
# ADR: Front-end client
Updated: 3Jan2023
## Background
> There are two general approaches to building web applications today:
> traditional web applications that perform most of the application logic on the server to produce multiple web pages (MPAs),
> and single-page applications (SPAs) that perform most of the user interface logic in a web browser,
> communicating with the web server primarily using web APIs (Application Programming Interfaces).
There's a 3rd option of having some lightweight javascript interation on just a few pages, but these fall into the MPAs.
An example is a mostly static sites with self-contained form pages that need client side validation of input before submitting.
This document assumes the 2024 scope ONLY.
### REQUIRED features
In no particular order: (todo: reorder based on priority
1. Produces static website that interacts via Secure API
1. Support for the top 98% of browsers at time of launch
1. 508 Accessiblity compilant / USWDS style library
1. Multi-langage support (English and Spanish) aka "i18n" (internationaliazation => i...*(18 chars)*...n)
1. Mobile friendly (format and load speed)
1. Secure/Trusted client libraries
1. Deals with PII and so privacy/security is important
1. Safe to use from shared computer (such as a public library)
1. Security best practices. e.g. CORS and CSP (Content Security Policy)
1. Support for multiple pages and complex links between them.
1. Agency familiarity with libraries
### NOT REQUIRED features
1. Offline/sync support
1. Not building a Full CMS (Content management system) like WordPress/Drupal
1. Not supporting older browsers or custom mobile browsers (feature-poor, less secure)
## Client code library
There are many choices for client-side code libraries to help reduce custom code.
Using one of these libraries increases security since they have been widely vetted and follow many best-pratices. It also reduces the cost of development/maintenance since the more popular a client library is, the more coding talent and tooling is available. The most popular libraries also allow for a common, shared knowledge for the correct way to solve a problem.
One issue with larger client-side code libraries is that they have deeper "supply chains" of software. This is where a top-level library uses features of some other library, which in turn, includes even more 3rd party libraries. This nested approach continues until there are 50k+ files needed to build even the most simple application. This dependency amplification tends to make common functions more shared, but can also greatly increase complexity when an update is needed in a deeply nested package libraries, especially when there are multiple revisions depenencies (higher level libraries explicietly require different versions of the same package).
Code scanners can find and automatically patch these nested packaged library updates (example: github's dependabot) to reduce constant workload overhead of updating. Fully automated unit tests are used to verify updating a dependency didn't break anything; therefore, creating rich unit tests becomes a crutial aspect of modern projects.
### Evaluation criteria
1. **Supports required features from above**
1. popularity
1. static build output (easier ATO, "serverless")
1. support for unit tests
There's an added wrinkle that many libraries (React, Angular, etc) have a "add-on" approach and use _other_ libraries to get features. NextJs and Gastby are examples for the React ecosystems.
### Combos
| Libary + AddOn | Pros | Cons |
----------------------|-----------------------------|-----------------------|
| React v18 + i18Next | Minimal complexity - full featured | None? |
| React + Gastby | Good at i18l. Great plugins | Uses GraphQL not REST. Larger output |
| React + NextJS | More like a CMS | Mostly SSR, recent static site support. Larger output |
| React + Progressive Web App | Great for mobile/offline | More complex deploy |
| Angular v13 | Popular | Not as efficent / popular as React |
| VueJS | Smaller than react. | Less popular |
| Svelte | Minimal size. Few plugins. | Not widely used. |
| JQuery | Minimal size. | Requires lots of custom code to do things |
| Vanilla JS | Minimal size. | Requires lots of custom code to do things |
## Tooling
1. Code quality scanners: for quality, security issues
1. Dependency scanners: for 3rd party libraries and their nested includes that alerts for outdated dependencies
1. Unit testing: automated tests to verify deep core functionality
1. Integration testing: aka end-to-end testing
### Microsoft's Github toolchain
Correct tooling is critical. Github offers a complete CI/CD ecosystem for automating: code quality scans, secrets scans, unit tests, library updates, deployment, 508 compliance scans. It's widely used recieving constant updates and improvements.
It also has a ticketing/tracking system for code bugs/improvements that integrates with code changes. It can be configured to only submit code once all automated checks have passed and another team member has review and approved changes.
Many of these features are free for open source projects.
If we do NOT use github's CI/CD toolchain, then we'll need to find other products to fill these needs and staff expertise for these alternate tools.
This tightly couples the project to github, but offers so many benefits for starting projects, that it's probably the correct path.
#### Non-public (Open Source) projects
Many quality/security scanning tools need access to the source to work. This is trivial for open source projects, but require more work for closed source. These may have licensing costs for non-open source projects or concerns about exposing sensitive code to 3rd parties.
The FE project will _**heavily**_ leverage existing open source projects: React, typescript, USWDS, etc.
#####Opinion
The Front End code should be open sourced.
Rational:
1. All FE "source" is "client-side script" (javascript). This means the transpiled source script is downloaded into the public browsers to run. It is **_not_** possible to "hide" this code since it runs in the end user's browser.
1. Tax payers funded the development of this source (aka the American Public); therefor, the result of that work should be public unless there's some reason for it not to be.
1. Open source can be more widely vetted for bugs/issues.
1. If designed accordingly, the Front End could be just a presentation layer that interacts with the user and that uses a verified server-side API to do proprietary work.
### Libraries
Libraries to support common functionality allows for quicker development AND avoiding common security mistakes. Popular open source libraries are widely vetted and patched frequently.
## Decision
The early Usability Study portion of the initial product cycle (meaning as we're creating the first iteration of the product) is a good time to try out different libraries and drive a decision.
[Updated: March 8th, 2023:]
For the first batch the technologies tried out:
1. `React v18 with Hooks`
1. `typescript` everywhere
1. `i18Next` for multilingual / localization
1. `Redux` for state machine needs
1. Trussworks's `react-uswds` for USWDS+React
1. `jest` for unit tests
1. `cypress` for functionality testing
## Rationale
**React v18**
A standard reactive UX library that's used widely by various Government agencies. It's well documented and easy to hire sofware developer talent with prior experience.
**typescript**
A modern standard that "levels up" javascript from a loosely typed scripting language to a strictly typed compiled (transpiled) language. Helps catch bugs at compile time versus runtime, enforces that types are correct, etc
**i18Next**
One possible multilanguage (translation/internationalization) library to make translation into Spanish
**Redux**
...
**react-uswds**
...
**jest**
...
**cypress**
...
## Rejected
## Assumptions
## Constraints
## Status
Pending
## Consequences
## Open Questions

92
docs/adr/adr-language.md Normal file
View file

@ -0,0 +1,92 @@
# ADR: Backend Programming Language
DATE: 12/14/2022
## Background
What general programming language should we use for the back end tools we create? This includes the tax engine, the APIs, any code generation tools, and anything else that we might need that isn't part of the client software. We generally think it is advisable to keep the number of languages low to facilitate developers working on multiple parts of the system, which will help keep the number of required contractors down. There are both technical and nontechnical reasons why a language might be chosen.
#### Technical Questions
1. **How well does the language natively support graph concepts?** In the prototype we used a graph to express tax logic as configuration, with the hope that one day we could build a system that allows nontechnical users to update that logic. We believe this was a sound concept and will be carrying it forward into the new system.
2. **How well would the language support building APIs?** Our plan is to use REST endpoints to retrieve and save data. We require a system that has strong support for these concepts and has been used at scale.
3. **How well does the language support code generation?** We believe that code generation will be a key component of the system. Our front end pages and some of their logic will be generated from our backend configuration, and as such we need a language that lends itself to this kind of activity. This could include access to compiler tools or a strong domain modeling ability in the language.
4. **Does the ecosystem of the language support SOAP/WSDL/SOA concepts?** The MeF API describes itself using WSDL and will expect communication through this enterprise architecture style communication pattern. Our language should have an ecosystem that supports this kind of communication/service. This means that we should be able to point to a WSDL and have calls and possibly domain objects generated with any included validation.
5. **How strong is the tooling, the ecosystem, and the available libraries for the language?** The more we can automate, and the more we can rely on third parties for common interactions, the better. Our language should have connectors to commonly available cloud tools. It should have an IDE that works well, has a built in test runner, and has realtime support for warning and errors. We should not have to gather applications and create our own build tools.
6. **How popular is the language and will it last?** Few things in programming are worse than building in a language that the community has abandoned. Languages, frameworks, and tools become popular and then disappear just as quickly. Some languages last for decades only to fall out of favor for newer tools. Our goal is to find a language that is popular enough that it won't disappear, i.e. it has buy-in from large companies and industry domains.
#### Non Technical Questions
1. **How likely are we to find contractors that know the language(s) well?** This is a tricky concept because it relies on two separate factors. The first is the pure number of contractors we imagine exist in a given language based on the popularity of the language and its use in government projects. The second is the relative quality of those contractors based on the ease of use of the language. Some languages are generally used by high skilled coders, and others are open to a wider audience where the skill level varies substantially.
2. **What is the IRS likely to accept?** What languages do they currently support? What sort of process have they built up around those languages and the tools that support those languages? This is really the ultimate question, as anything the IRS wouldn't accept is out by default!
## Decision
We have decided to take a hybrid Scala and Java approach.
## Rationale
The rationale can best be couched in the questions above. In short though, we believe that Scala best matches the domain and the problems at hand while Java has some of the tooling and auto generation features we would want for external communications. They work interchangeably, so this shouldn't present a problem.
#### Technical Questions
1. Scala, and other functional languages have strong support for graph concepts. When building graph systems in other languages, it is common to employ functional concepts when architecting and coding the system. Even basic concepts like immutability and a lack of nulls helps to cut down on the amount of code required to generate the system. Beyond that, because of its natural affinity for recursion, Scala can handle traversal idiomatically. OO languages end up with extra lines and can be less expressive for the concepts we will be using.
2. This is one of the areas where the hybrid approach with Java shines. For our API layer we will fall into a common Java Spring pattern, which allows us all of the great tooling and speed of development that that ecosystem offers. Both Scala and Java have been used at Scale (Scala comes from the word scalable).
3. Functional languages are known for the ease in which a developer can model a domain and perform actions based on those models. Code generation, ignoring the read in and write out steps, is a pure process in the sense that it is idempotent. Working with pure functions is what functional languages are good at. Combining the two, a powerful domain model and pure functions, is a recipe for simple, powerful code generation.
4. Again, this is where the Java hybrid approach comes in. Java was strong in the days of SOA, and in fact, many of the books about SOA used Java as the lingua franca. It has amazing tools to work with WSDL, to process SOAP messages, and to handle anything we aren't expecting that may come from the SOA world.
5. Our belief is that the tooling is strong around both Scala and Java. The intelliJ IDE works well and meets all of the criteria of a modern, full service IDE. There are also alternative choices, like VSCode, which also meets all of the needs of a developer on a large scale system. Twitter, and many financial institutions have been using Scala successfully for many years.
6.Scala has been around for 18 years, and is one of the most popular languages on the JVM. It is the domain language of choice in the financial space. It isn't going anywhere any time soon.
#### Non Technical Questions
1. Scala is a difficult language. Many functional concepts will require exploration for mid level and novice programmers. We believe that the kinds of contractors who will be available will be more senior and will be better able to contribute long term to the project. We also believe that this language difficulty will protect us from common, simple mistakes at the cost of a higher ramp up time and a smaller potential contractor pool.
2. Because Scala runs on the JVM it should be acceptable. All of the support systems are already in place within the IRS to update and manage Java systems. Except for the code, our systems will appear no different. They will use common Java libraries, common java tools, and require the same sorts of maintenance.
## Rejected Languages
Below is the set of languages we measured and rejected in order of how well suited we feel they are to the problem space
1. **C#**: This was a close contender with Scala. It checks all of the boxes, but we felt that Scala is better for graphs and is closer to the stack that the IRS is comfortable with.
2. **Kotlin**: This language is very popular in the JVM ecosystem. It fell behind C# because of our lack of familiarity and its relative newness. It had the same pitfalls as other OO languages.
3. **Java**: Java was strongly considered, as it is the main language of the IRS, but we felt that it lacked many features that would make developing this application quick and easy.
The rest (no particular order):
- **F#**: This language has many of the features of Scala, but it is on the dotnet framework. We don't know if the IRS currently manages any dotnet systems. It is also a little less common than Scala. If we were to pick between the two for a general large scale production application, Scala would be the winner.
- **Rust**: We are just too unfamiliar with Rust to choose it to build something like this. It is also very new which comes with a lot of painful changes later.
- **Go**: This is another language that might be great, but we don't know enough about it. The ramp up time would be more than we have.
- **Ruby**: We built the prototype for most of this work in Ruby. While it worked well, we don't want to have to go through open source package management nightmares in a production application.
- **Typescript/Node**: Same as Ruby. The dependency on abandoned projects with security holes is a problem. Those packages can also introduce versioning conflicts and a whole host of other problems that we would rather not deal with from a support angle.
- **Python**: Same as Ruby and Typescript!
## Assumptions
- We will represent tax logic in a graph
- Rest endpoints are the preferred way of handling client-server communications
- Code generation is a workable approach
- MeF uses SOA concepts like WSDL and SOAP
- Contractors will be of higher quality
- Contractors in some languages are better than others
- Functional languages are better for dealing with graphs
- Functional languages are good for code generation for the reasons stated above
- The IRS doesn't use dotnet
- The hybrid approach is simple and easy to do
- Ruby/Python/Node have package issues that make them less desirable for government work
## Constraints
- The language should be understood by the team.
- The language should have practical use in large scale systems.
- The language should have financial domain applications.
- The language should be common enough that contractors are available.
- The language should follow a known, common support model.
- The language/ecosystem should be known by the government.
- The language has support for our domain concepts
- The language has existed for a long enough period of time to have gained common adoption.
## Status
Pending
## Consequences
The first, and most obvious consequence of this decision is that we won't be using another programming language. This locks us into a specific set of tools and resources.

View file

@ -0,0 +1,59 @@
# New Users Allowed Feature Flag for Phase C of Pilot Rollout
Date: 1/17/2024
## Status
Complete
## Context
For the Phase C launch which will be controlled availability (and Phase D launch of limited availability), we want to limit **when** new users have access to Direct File and **how many** new users can access Direct File.
### Requirements
- Allow new users to access Direct File during short open windows or when the max number of new users has been reached during an open window
- Max number of new users will be in the hundreds or thousands
- The open windows will be brief, for example a 2-hour period that is defined the day before, and will be unnanounced
- Outside of the open windows, no new users will be allowed to use Direct File
- Outside of the open windows, users who were previously allowed will be able to use Direct File as normal
- Users and emails who were previously allowed during the Phase A email allow list launch should still be allowed during Phase C
- If users are ON the allowlist, they are always allowed regardless of max total users
- If users are NOT on the allowlist, their access will be granted if and only if the open enrollment window is open and max users haven't been reached
- When we approach Phase D, all of the above requirements apply, except the open windows will be slightly longer, such as 1 week
- Closing a window needs to happen within 20 minutes of the IRS decision to close. We will need to coordinate with TKTK to meet this SLA.
## Decision
### Use a config file in S3 as our feature flags
Use a JSON file in S3 for Direct File feature flags that does not require a deployment to update.
#### Config File
- The JSON file will only contain feature flag variables that apply everywhere in the DF application starting with the following 2 flags for phase C. No PII will be included.
- `new-user-allowed`: boolean representing whether we are in an open window and new user accounts are allowed
- `max-users`: int representing how many max allowed users there can be in Direct File currently. This is a failsafe to prevent mass signups before the open window can be closed. This would be calculated by checking the number of rows in `users` where allowed is `true` before opening a window and adding the max number of new accounts we would like to allow in the open window. This does not need to be exact, stopping the creation of new accounts roughly around `max-users` is good enough
### Direct File Implementation
- Set up new default config JSON files `feature-flags.json` to store our feature flags, and additional config files per environment
- DF Backend app polls for the config file every `1 minute` to pick up changes and load the file into memory
- For every request to DF backend, check whether the user is allowed:
- Check whether user already exists in the `users` DB
- If yes the user exists: Check the allowed column to see if the user has been allowed
- If true: allow access to DF as normal
- If false:
- If `new-user-allowed` is true and `max-users` > count of records in `users` where `allowed = true`: set allowed to true for this user
- Else, respond with a 403 error code and a custom meessage
- If no the user does not exist: Check feature flags and email allow list
- If `new-user-allowed` is true and `max-users` > count of records in `users` where `allowed = true`: set allowed to true for this user and allow the user access to Direct File
- Else if hashed SADI email matches an email in the email allow list: set allowed to true and allow the user access to Direct File
- Else, respond with a 403 error code and a custom message
- A code deployment is needed in order to update the feature flags
### Updating the feature flag file
1. DF Backend PM will file an ticket with the updated config file. In the ticket, request to upload the new file to `artifact-storage` S3 in the correct environment
1. A turnaround time of 5 minutes or less is expected
1. DF backend will pick up the changes in the next poll for the new file to S3
## Other Options Considered
1. Store config values as DB record and have a TKTK dba run a DB query in PROD
1. Use a secrets manager? Parameter store?
1. Usie a real feature flag service so that business users could change them in a UI long term solution
We decided to use a config file approach due to the ease of setting it up and familiarity with the design and update process given the Phase A decision

View file

@ -0,0 +1,249 @@
---
# Configuration for the Jekyll template "Just the Docs"
parent: Decisions
nav_order: 100
title: "Optional facts"
# These are optional elements. Feel free to remove any of them.
status: "Decided"
date: "2023-11-14"
---
<!-- we need to disable MD025, because we use the different heading "ADR Template" in the homepage (see above) than it is foreseen in the template -->
<!-- markdownlint-disable-next-line MD025 -->
# Optional Facts
## Context and problem statement
The fact graph does not have a way to represent optional facts and we need to set certain fields such as W2 boxes and middle initials to be optional.
We need this feature for MVP.
## Desirable solution properties
We'd like the solution to this problem to
1. Allow us to show in the frontend to users that fields are optional.
2. Allow the user to leave the field blank and hit `Save and continue`.
3. Allow the fact graph to properly calculate downstream calculations without this fact.
## Considered options
1. Create a mechanism to allow specific writable facts to be left incomplete
1. Create the idea of null or default values in the fact graph/fact dictionary
## Decision Outcome
Chosen option: **Create a mechanism to allow specific writable facts to be left incomplete**
We do this by creating a second derived fact that is always complete. The original fact is prefixed with `writable-`. The derived fact uses the incompleteness of the writable fact to provide a default value. See below for instructions.
Reasoning: This one doesn't complicate our fact system with the ideas of placeholders, default values, `hasValue`s, validity etc because it keeps writable values separate from the downstream value. So it might be easier to do and easier to understand.
However, we felt in a v2 future version, we might do the other option. For now, we have proceeded with this option.
### Consequences
1. Good: We can start marking fields as optional.
2. Good: We can test that optional fields aren't breaking the flow downstream.
3. Good: We can test that visual treatment for optional fields works for users.
4. Bad: The scala option where we add the concept of optional fields into the graph itself might be more comprehensive.
### How to make a fact optional
Engineers looking to make a fact optional can do the following.
1. Find the component in `flow.tsx`. Not all fact types are enabled for optionality!!
Only `GenericString` fields and `TextFormControl` based fields (Dollar, Ein, Pin etc.) are enabled for optionality.
```xml
<Dollar path='/formW2s/*/wages'/>
```
* Add `required='false'` and rename to `writableWages`.
We must rename the fact, because we have to ensure no derived facts get marked as optional.
```xml
<Dollar path='/formW2s/*/writableWages' required='false' />
```
2. Find out if there should be a default value for this fact, or if it can be left incomplete.
* Dollar values can often use 0 as a default.
* Strings or enums may not have a correct default, and we may want to leave these incomplete.
* An incomplete fact can break other parts of the flow so we should verify with backend before leaving it incomplete.
* Reach out on Slack to get guidance from backend team members.
**IF DEFAULT IS NEEDED:** Find the fact in `ty2022.xml` or other fact dictionary files, and create a derived version that is always complete.
It uses the incompleteness of the writable fact to provide a default value.
* Replace this:
```xml
<Fact path="/formW2s/*/wages">
<Name>Wages</Name>
<Description>
Box 1 of Form W-2, wages, tips, and other compensation.
</Description>
<Writable>
<Dollar />
</Writable>
<Placeholder>
<Dollar>0</Dollar>
</Placeholder>
</Fact>
* With this (be sure to remove `<Placeholder>` if there is one):
```xml
<Fact path="/formW2s/*/writableWages">
<Name>Wages</Name>
<Description>
Box 1 of Form W-2, wages, tips, and other compensation.
This is the writable optional fact. Can be left incomplete.
Please use the derived fact in downstream calculations.
</Description>
<Writable>
<Dollar />
</Writable>
</Fact>
<Fact path="/formW2s/*/wages">
<Name>Wages</Name>
<Description>
Box 1 of Form W-2, wages, tips, and other compensation.
</Description>
<Derived>
<Switch>
<Case>
<When>
<IsComplete>
<Dependency path="../writableWages" />
</IsComplete>
</When>
<Then>
<Dependency path="../writableWages" />
</Then>
</Case>
<Case>
<When>
<True />
</When>
<Then>
<Dollar>0</Dollar>
</Then>
</Case>
</Switch>
</Derived>
</Fact>
```
**IF DEFAULT IS NOT NEEDED:** Find the fact in `ty2022.xml` or other fact dictionary files, and create a derived version that may be incomplete.
* Replace this (don't remove the Placeholder):
```xml
<Fact path="/formW2s/*/wages">
<Name>Wages</Name>
<Description>
Box 1 of Form W-2, wages, tips, and other compensation.
</Description>
<Writable>
<Dollar />
</Writable>
<Placeholder>
<Dollar>0</Dollar>
</Placeholder>
</Fact>
```
with this:
```xml
<Fact path="/formW2s/*/writableWages">
<Name>Wages</Name>
<Description>
Box 1 of Form W-2, wages, tips, and other compensation.
</Description>
<Writable>
<Dollar />
</Writable>
<Placeholder>
<Dollar>0</Dollar>
</Placeholder>
</Fact>
</Fact>
<Fact path="/formW2s/*/wages">
<Name>Wages</Name>
<Description>
Box 1 of Form W-2, wages, tips, and other compensation.
</Description>
<Derived>
<Dependence path='../writableWages' />
</Derived>
</Fact>
```
3. Search the `flow.tsx` for other components using the writable fact and update the fact name.
4. Rebuild the fact dictionary code
* In `direct-file/df-client/fact-dictionary` run
```sh
npm run build
```
5. Edit `en.yaml` and the other locales to replace field labels for the writable fields
```yaml
/formW2s/*/writableWages:
name: Wages, tips, other compensation
```
6. Finally, run tests and fix any testcases that should have the writable field, or alternately the derived field.
## Pros and Cons
### Create a mechanism to allow specific writable facts to be left incomplete
We do this by creating a second derived fact that is always complete. The original fact is prefixed with `writable-`. The derived fact uses the incompleteness of the writable fact to provide a default value.
#### Pros
* Lower lift
* Doesn't complicate the fact system with placeholders and potentially avoids complex bugs in the fact system at this late stage.
* Easier to understand.
#### Cons
* It's likely more correct and complete for our fact system to understand optionality.
### Create the idea of null or default values in the fact graph/fact dictionary
In this method, we would change the scala and the factgraph to handle the concept of null or default values.
If something has a default value in the fact dictionary, we pick that up on the frontend (similar to how we do enumOptions) and then let a person skip the question, using the default value in its place.
#### Pros
* This might be more logically correct as we're not overloading the concept of `incomplete` with `optional+empty`
#### Cons
* Bigger lift than the other option.
* Requires scala rework which we have less engineering bandwidth for.
* Currently, every writable fact is either `incomplete + no value`, `incomplete + placeholder`, or `complete`. Making this change would add a fourth state of `incomplete + default value` and that might have multiple downstream consequences in our application.

View file

@ -0,0 +1,106 @@
---
# Configuration for the Jekyll template "Just the Docs"
parent: Decisions
nav_order: 100
title: "Pseudolocalization"
# These are optional elements. Feel free to remove any of them.
status: "Proposed"
date: "2023-07-21"
---
<!-- we need to disable MD025, because we use the different heading "ADR Template" in the homepage (see above) than it is foreseen in the template -->
<!-- markdownlint-disable-next-line MD025 -->
# Pseudolocalization
## Context and problem statement
Currently the frontend is using a spanish language translation file as an alternate translation. However, we do not have translations so all strings translate to TRANSLATEME. Also, we will likely always be behind in sourcing the translations.
Pseudolocalization generates a translation file that translates “Account Settings” to Àççôôûññţ Šéţţîñĝš !!!
It allows us to easily catch:
* where weve missed translating a string
* where weve missed internationalizing a component
* where a 30% longer string would break ui
* where a bidirectional language would break the layout (perhaps not needed right now)
Developers can test the flow and read the pseudolocalized strings as they navigate the UI. Basically errors become really easy to catch during normal development.
## Desirable solution properties
We'd like the solution to this problem to
1. Highlight issues for developers and design to catch early and often
2. Not add additional load to development and design
## Considered options
1. Don't change anything, use fixed string for all translations
2. Use a package to generate a new translated set of strings
3. Use a package to hook into react and translate strings dynamically
## Decision Outcome
Chosen option: Use a package to generate a new translated set of strings.
Update 20240417: Now that we have Spanish, we are removing the pseudolocalization
Reasoning: Using a set of translated strings is the best way to catch if we've forgotten to hook something up correctly. Given our unusual use of the dynamic screens, FactGraph and translations, there's a possibility of bugs as we source translations for strings, facts, enums, etc.
If we don't change anything, we will continue to introduce more technical debt that will need to be fixed at a later date.
Package chosen: https://www.npmjs.com/package/pseudo-localization
### Consequences
1. Good: Easy way to ensure we are keeping our codebase properly internationalized.
2. Good: Devs can test the whole flow quickly without switching languages to understand what each field means.
3. Good: We can automate updating the translation so it's even less load on the developers.
4. Bad: Maybe we run into an issue with the pseudotranslation that won't be an issue with a real translation?
4. Bad: Spanish will not be our second language in the UI switcher.
## Pros and Cons
### Don't change anything, use fixed string for all translations
#### Pros
* Straightforward, it's what we have already.
#### Cons
* We can't tell which fields are which and testing is harder.
* May hide (or cause) issues that exist (or don't) with actual translations - For e.g. if 'Single' is selected but later 'Married' is shown, there's no way to tell if both strings are translated to 'TRANSLATEME'.
* All strings are same length.
### Use a package to generate a new translated set of strings
Package chosen: https://www.npmjs.com/package/pseudo-localization
#### Pros
* Devs can test the whole flow quickly without switching languages to understand what each field means.
* We can automate updating the translation so it's even less load on the developers.
* Tests the UI with +30% string length.
* This package appears to be the most flexible and popular option on npm. It has an MIT license.
#### Cons
* Requires ticket and work to update the translation script
* Spanish will not be the second language (although once the language switcher supports more languages we can just have both)
* This package was last updated in 2019 - so although popular enough, prefer to use it just as tooling vs hooking it directly into our codebase.
### Use a package to hook into react and translate strings dynamically
#### Pros
* Can be hooked into frontend dynamically.
#### Cons
* Doesn't actually exercise our own flow and the aggregation and intrapolation of strings from flow.xml and translation JSON files.
* Could appear to "fix" strings that aren't actually properly internationalized.
## References
* More on pseudolocalization: <https://www.shopify.com/partners/blog/pseudo-localization>

View file

@ -0,0 +1,33 @@
[//]: # ([short title of solved problem and solution])
Status: [proposed | rejected | accepted | deprecated | … | superseded by ADR-0005]
Deciders: [list everyone involved in the decision]
Date: [YYYY-MM-DD when the decision was last updated]
## Context and Problem Statement
[//]: # ([Describe the context and problem statement, e.g., in free form using two to three sentences. You may want to articulate the problem in form of a question.])
A decision was made in [adr-screener-config](./adr-screener-config.md) to use Astro SSG (static site generator) for the screener application. It was initially used for an MVP, and later replaced with React/Vite. This adr is to document that change and supercede the previous adr.
## Decision Drivers
- the realization that the application needed to support more dynamic features such as react-uswds and i18n features.
## Considered Options
React/Vite
## Decision Outcome
Chosen option: "React/Vite", because it was consistent with the client app and the approach to i18n could be consistent across the screener and client apps.
### Positive Consequences
- More dynamic content is an option
- We can easily utilize react-uswds library.
- The i18n system is aligned in both the screener and the client app.
- Engineers don't need to learn multiple systems and can seemlessly develop between the two apps. Onboarding for new engineers is simplified.
### Negative Consequences
- It's more complex than a more static configuration would be

View file

@ -0,0 +1,121 @@
---
# Configuration for the Jekyll template "Just the Docs"
parent: Decisions
nav_order: 100
title: "Screener static site"
# These are optional elements. Feel free to remove any of them.
status: "Decided"
date: "2023-08-08"
---
<!-- we need to disable MD025, because we use the different heading "ADR Template" in the homepage (see above) than it is foreseen in the template -->
<!-- markdownlint-disable-next-line MD025 -->
# Screener static site
superceded by: [adr-screener-config-update](../adr-screener-config-update.md)
## Context and problem statement
The screener is a set of four to five pages that serve as the entry point to the direct file. They will contain a set of simple questions with radio buttons that advance the user to the login flow or "knock" them out if any answers indicate they do not qualify for direct file.
Since the frontend will not be saving the user's answers to these questions, we have an architectural choice on how to create these pages. These will be unprotected routes not behind our login so the SADI team recommends hosting static pages for this content.
Also, we need a way to make changes to content, order of questions, and add or remove pages.
## Desirable solution properties
We'd like the solution to this problem to:
1. Allow the team to edit the config to change the order of questions and add or remove pages entirely.
2. Allow the team to make changes to content of the screener.
3. Allow the team to deploy the app with high confidence that no regressions will occur.
4. Have the static site support i18n and possibly reuse keys from existing client translation files.
## Assumptions
- We can change content and the config after the code freeze (will most likely require policy changes)
- No answer to a question in the screener is derived from a previous one with the exception of the initial state dropdown
- Every question (except the first state selection dropdown) will be a set of radio buttons with either:
- "Yes" or "No"
- "Yes," "No," or "I don't know" (and more content specific answers for the third option)
- The static site generator (SSG) will live in the same repo, just within another folder.
## Considered options
1. Use an SSG (static site generator) to create static HTML pages
2. Create another React SPA with a custom JSON or TS config
3. Integrate existing into existing direct file React SPA
## Trying to answer feedback
### Why not just plain HTML and JS?
The library we're currently using in the DF client for i18n is i18next. It's certainly possible to use i18next in a Vanilla JS and HTML site, but I think it's worth trying to reuse our existing approach using the react-i18next library. SSG libraries also provide a better developer experience in updating this content.
### Ok. Why not another Vite/React SPA?
The site is limited and fairly static so creating a SPA doesn't seem to fit the use case. Content largely drives the screener so a static site with a multi-page architecture fits the use case better than a fully-fledged SPA where lots of app-logic would be necessary.
## Decision Outcome
**Chosen option**: Use an SSG to build the app.
**Reasoning**: Using an SSG library, we can safely deploy the screener pages outside of the main direct file app. This allows us to have the unprotected routes of the app separate from the protected ones. This allows us to integrate with SADI more easily and also support changes to content quickly.
Also, with an SSG library (instead of plain HTML and JS) we can use the features of i18next more easily like we are doing in the DF client.
If we choose to integrate the screener into the React SPA, this will make it more complicated to secure these routes.
**Library Chosen**: Astro. We can revisit this choice if it proves not to work for us, but it's focused on content, ships as little JS as possible, provides React support if we need it, and provides good i18n support with an i18next library.
Consequences
- Good: Astro supports React so we can reuse components from the client
- Good: Astro has i18next libraries specific and we may even be able to use react-i18next
- Good: Creating all the pages at build will result in separate pages/paths for each language (i.e. /en/some-page, /es/otra-pagina).
- Good: We can can make changes to the questions, content, and pages fairly easily.
- Good: We can use snapshot testing to have a high degree of certainty that the UI doesn't change unexpectedly.
- Good: Easier to integrate with SADI if these pages are separate.
- Good: Can use i18next with the library to keep our translation mechanism the same, perhaps use one source of translation files.
- Bad: Will require separate CI/CD build pipeline.
- Bad: Another place to maintain content and possibly a config.
- Bad: Another tool for frontend developers on the team to learn.
## Overview of SSGs
### Astro
- Focused on shipping less JS, focus on static HTML output
- High retention in [state of JS survey](https://2022.stateofjs.com/en-US/libraries/rendering-frameworks/)
- Support for multiple frameworks including React
- Support for TypeScript
- Good i18next integration
### Vite
- Already have this tool in the codebase
- Provides TS support, React, i18n
- More inline with an SPA in mind
- SSG support doesn't appear to come "out of the box," [but it is possible](https://ogzhanolguncu.com/blog/react-ssr-ssg-from-scratch).
### Gatsby
- Support for React
- Large plugin ecosystem
- Support for TypeScript
- Seems unnecessarily complex given our needs (GraphQL features)
### Next.js
- Support for React
- SSR tools on pages if necessary
- Support for TypeScript
- Seems unnecessarily complex given our needs (SSR)
### Eleventy
- Multiple template languages
- Supports vanilla JS
- Flexible configuration
- Very fast build time
- Good for sites with a lot of pages

View file

@ -0,0 +1,34 @@
# Direct File Development 2024
Date: 06/14/2024
## Status
## Context
In our current state, Direct File cannot support filing taxes for two different tax years. That is, we cannot
make changes that expand our tax scope or prepare us for TY 2024 without causing breaking changes to TY 2023 functionality.
As an example of this, we've added a new required question for schedule B that asks every taxpayer, "Do you have a foreign bank account?". Since that question is new and required, every person who submitted a tax return for 2023 now has an incomplete tax return against main.
We essentially have two options:
1. We can build a new system where we maintain multiple versions of the flow, fact dictionary, mef, and pdf that support multiple tax years and scopes at one time. This is a lot of work to do.
2. We can not worry about backcompatibility and block production users from accessing the flow/fact graph. We use generated PDFs to expose last year's answers to the user. We have to build a way to block users from accessing the flow in production, but don't need to maintain multiple versions of the app. There is still a consequence that users will never be able to re-open last year's tax return in the flow.
## Decision
- Next year, we will probably have to deal with multi-year support and multiple fact dictionaries/flows/etc. But this year, we're concentrating on expanding our tax scope to expand to more users. That is the priority, rather than providing a good read-experience for last year's 140k users.
- We are ok to make non-backwards compatible changes. We can make changes that will break an existing user's fact graph. We will never try to open last year's users returns in a fact graph on main.
- We're going to continue deploying 23.15 to prod through late June 2024, possibly into Q3 2024, until a point where:
- We have generated all existing users tax returns into PDFs
- We have a feature flagging method so that existing users in prod will be able to download their tax return as a PDF in prod
- Users in other test environments will be able to run with the new enhanced scope and we'll be building for next year.
There's additional product thought that needs to go through what the TY2024 app looks like for users who filed in TY2023 through Direct File.
## Consequences
- This means that we will need to apply security patches to 23.15 separately from main. We should probably also set it to build weekly/regularly.
- Main is going to move ahead for TY2024. The next version of Direct File will always be the best one.
- We have work to do to put in a feature flag for last year's filers' experience in production so that those users will be able to download last year's tax return as a PDF.

View file

@ -0,0 +1,48 @@
| ADR title | Custom USWDS configuration settings in 2024 Direct File Pilot |
|-----------|-----------------------------------------------------------------|
| status | Approved |
| date | 2023-08-23 |
# Custom CSS theming of USWDS within Truss React Components
## Context and problem statement
The USWDS design system is implemented in Direct File using [ReactUSWDS Component Library](https://trussworks.github.io/react-uswds/?path=/story/welcome--welcome), an open source library built and maintained by Truss.
Truss includes out-of-the-box CSS with each component, with some variation in color and component display options.
Using a component library helps engineers build Direct File quickly while maintining a high degree of quality and consistency in the UI.
It is possible to [customize configuration settings](https://designsystem.digital.gov/documentation/settings/#configuring-custom-uswds-settings) within USWDS design system. Developing a shared understanding of this system across Engineers, Designers and PM's and then organizing and designing within these parameters is a sizeable effort for the team. It is a body of work that would add additinoal risk to meeting our project deadline.
Examples of these challenges are:
- Anticipating knock-on effects of any particular customization has proven time-consuming. An example of this customization pertained to the header. The design switched the header color to dark, and when the default stock menu was applied, the menu button text was dark grey, which is a visibility/accessibility issue. CSS was added to make that menu button text light but then in responsive mode, these buttons get moved to the dropdown nav, which has a light background. So then that menu button text needs to be dark, etc. This type of reactive color fixing creates an inconsistency and is time consuming.
- Coordinating common practices of how we implement design overrides at the code level is time-consuming and situational
- Creating consistency across separate applications (i.e. the Screener and the Filing application itself) requires more overhead the further we deviate from a out-of-the-box implementation of USWDS
Therefore, we propose that USWDS settings customization is out of scope for the Pilot not because it is not possible, but because at this point, investing time into customization is a lower priority than completing the base functionality required for the successful launch of the Pilot.
On a system wide level, design tokens provided by `usds-core` can be overwritten in `_theme.css`. Some system-wide theme guidelines currently exist in this file. It's my recommendation that we continue to utilize this pattern for CSS settings which are confidently applied application wide.
## Decision Outcome
Custmizing the settings of USWDS within React Truss Compoents is not in scope for the 2024 Direct File Pilot.
### Consequences
Pros:
- Using out-of-the-box functionality enables designers and engineers to move quickly and meet our go/no go deadline for the Pilot
- This does not have to be a permanent decision: we can go back later and develop a strategy for customizing the application in CY2024 or beyond
- Taxpayers will experience a more consistent UX.
Cons:
- This limits the look and feel of Direct File Pilot for 2024.
- There is some in-progress work that will need to be abandoned and/or removed (tech debt).
## Next Steps
- Designer leads review the Source of Truth to confirm sketches that are being used for Design Audit are consistent with USWDS out-of-the-box configuration, and not accidentally introducing/proposing customization in new Developer tickets. (Suzanne, Jess, Jen)
- Designers working on Design Audit ensure new tickets written do not introduce customization to USWDS components.
- PM/Delivery lead for Design Audit and Components must audit tickets as they come through to ensure that they are not introducing new customization to USWDS components.
- All teams must be made aware to ensure future commits to Source of Truth mural accurately reflect this decision.

View file

@ -0,0 +1,78 @@
---
# Configuration for the Jekyll template "Just the Docs"
parent: Decisions
nav_order: 100
title: "Accessibility testing methods"
# These are optional elements. Feel free to remove any of them.
status: "Accepted"
date: "2023-07-11"
---
<!-- we need to disable MD025, because we use the different heading "ADR Template" in the homepage (see above) than it is foreseen in the template -->
<!-- markdownlint-disable-next-line MD025 -->
# Accessibility testing methods
## Context and Problem Statement
Section 508 describes ways we can support people with disabilities, and many accessiblity tech/tools (AT) exist that support various tasks. We on this project team can use those tools to inspect our work, and we can use other tools that can simulate how those tools might work with the code we push to this repository. This decision record sets how we achieve our accessibility target (set in the "Accessibility Target" DR) in an agile way.
## Considered Options
* Review accessibility factors in every PR, where applicable
* Review accessibility factors at least every other sprint (once per month)
* Review accessibility factors in the final stages of this project before release
* Supplement manual review with automated accessibility review using a tool like pa11y
## Decision Outcome
Chosen option: "Review accessibility factors in every PR, where applicable", because our goal is to prioritize accessibility, and this saves us time in the long run by not introducing any problems that could best be fixed at a PR level.
Per discussion internally and with TKT, team will be shifting towards (1) "Review accessibility factors at least every other sprint (once per month)"; and (2) "Supplement manual review with automated accessibility review using a tool like pa11y." This will ensure more automated coverage for a11y testing, and less designer time spent on manual review.
### Consequences
* Good, because it is maximizes accessibility compliance opportunities
* Good, because it *prevents* accessibility problems from showing up rather than waiting to fix them
* Good, because it sets a policy that no obvious accessibility problems should ever be merged
* Neutral, because it a critical feature could be held up by a relatively less critical but still significant accessibility problem (exceptions could fix this)
* Bad (ish), because it will add about 10 minutes to each PR to thoroughly check accessibility.
* Bad (ish) because some 508 violations (P0 and P1 bugs) may get merged into test or dev branches, but will never be promoted into production.
### Confirmation
The initial decision was confirmed by the IRS' 508 Program Office (IRAP) and by our Contracting Officer's Representative. Project technical staff will continuously confirm adherence to this decision using a PR template, which includes a checklist of items they need to do before it can be merged.
The updated decision to supplement manual testing using pa11y or similar automated testing tool.
## Pros and Cons of the Options
### Review accessibility factors in every PR, where applicable
* Good, because it is maximizes accessibility compliance opportunities
* Good, because it *prevents* accessibility problems from showing up rather than waiting to fix them
* Good, because it sets a policy that no obvious accessibility problems should ever be merged
* Neutral, because it a critical feature could be held up by a relatively less critical but still significant accessibility problem (exceptions could fix this)
* Bad (ish), because it will add about 10 minutes to each PR for the submitting engineer and for the (likely designer) accessibility reviewer to thoroughly check accessibility.
### Review accessibility factors at least every other sprint (once per month)
* Good, because it is a relatively frequent check for introduced bugs
* Neutral, because it sets a middle ground between maximizing accessibility compliance and building capacity
* Bad, because reviews may catch a lot of bugs and require prioritization work
### Review accessibility factors in the final stages of this project before release
* Good, because it maximizes our capacity for building *something*
* Bad, because it is the opposite of best practices
* Bad, because problems discovered at that point may be too many to fix for our deadline
### Supplement manual review with automated accessibility review using a tool like pa11y
* Good, because it maximizes coverage by automating executed test cases against our a11y targets
* Good, because it frees up design time spent on manual reviews
* Bad (ish), because it will require some dedicated set up time from devops
## More Information
* Our [PR template](../PULL_REQUEST_TEMPLATE.md) and [design review instructions](../design-review-process.md) are the operational components of this decision. These are based on [documents produced by Truss](https://github.com/trussworks/accessibility) in their past projects.
* In case a PR for some reason needs to be merged without an an accessibility review, an issue should be made and immediately queued up for work so that any potential issues can be caught as soon as possible.

View file

@ -0,0 +1,94 @@
---
# Configuration for the Jekyll template "Just the Docs"
parent: Decisions
nav_order: 100
title: "Accessibility targets"
# These are optional elements. Feel free to remove any of them.
status: "Accepted"
informed: "All project technical staff"
---
<!-- we need to disable MD025, because we use the different heading "ADR Template" in the homepage (see above) than it is foreseen in the template -->
<!-- markdownlint-disable-next-line MD025 -->
# Accessibility targets
## Context and Problem Statement
In supporting a critical task for all U.S. residents, Direct File should be accessible. This decision record sets a clear target for this phase of development to meet those accessibility needs, and we expect to exceed that target when feasible.
The U.S. describes its accessiblity requirements in [Section 508](https://www.section508.gov/) of the Rehabilitation Act. [WCAG](https://www.w3.org/WAI/standards-guidelines/wcag/) provides the same for the internet at large with three levels of compliance (A, AA, AAA), and it has increased in minor versions (2.0, 2.1, 2.2) over the last 15 years. 508 and WCAG have a [very large overlap](https://www.access-board.gov/ict/#E207.2), and all non-overlapping features unique to 508 are either irrelevant to this project (e.g. manual operation and hardware) or out of this repo's scope (e.g. support channels). See the note in "More Information" below for further information.
Given these equivalencies, all considered options are oriented toward WCAG and achieve 508 compliance.
## Considered Options
* WCAG 2.0 A and AA (base 508)
* WCAG 2.1 A and AA (508 superset)
* WCAG 2.1 AA (enhanced superset)
* WCAG 2.2 AA (forward-thinking)
## Decision Outcome
Chosen option: "WCAG 2.2 AA (forward-thinking)", because it ensures we meet our baseline and exceed our goal
### Consequences
* Good, because it establishes and exceeds 508 compliance
* Good, because it is easy to remember the level expected of all elements (i.e. "what needs level A vs AA?")
* Good, because it challenges us to maximize WCAG at level AAA
* Good, because it sets Direct File up with the latest a11y guidance for years to come
* Good, because it doesn't require any more work than WCAG 2.1 AA with our current design
* Neutral, because it may require slighly more work than the bare minimum in the future
* Neutral, some automated a11y tools don't yet support 2.2 (as of Oct 2023)
### Confirmation
This decision to exceed 508 requirements is confirmed by the IRS' 508 Program Office (IRAP) and by our Contracting Officer's Representative, Robin Coplen. IRAP will only ensure that the baseline is met (2.0 A and AA). Project technical staff will continuously confirm adherence to this decision's specific version and level using accesibility evaluation tools and manual evaluations when/where appropriate.
## Pros and Cons of the Options
### WCAG 2.0 A and AA (base 508)
* Good, because it establishes 508 compliance
* Good, because it is the easiest level to achieve
* Bad, because omits updates and new tech since its publication 15 years ago
* Bad, because it does not exceed 508 compliance, as called for in our mission
### WCAG 2.1 A and AA (508 superset)
* Good, because it establishes 508 compliance
* Good, because it is the easiest level to achieve for the latest published guidance
* Bad, because it does not exceed 508 compliance, as called for in our mission, for the latest technologies like mobile devices
### WCAG 2.1 AA (enhanced superset)
* Good, because it establishes and exceeds 508 compliance
* Good, because it is easy to remember the level expected of all elements (i.e. "what needs level A vs AA?")
* Good, because it challenges us to maximize WCAG at level AAA
* Neutral, because it may require slighly more work than the bare minimum
* Neutral, because it is an outdated version (see "more information" below)
### WCAG 2.2 AA (forward-thinking)
* Good, because it establishes and exceeds 508 compliance
* Good, because it is easy to remember the level expected of all elements (i.e. "what needs level A vs AA?")
* Good, because it challenges us to maximize WCAG at level AAA
* Good, because it sets Direct File up with the latest a11y guidance for years to come
* Good, because it doesn't require any more work than WCAG 2.1 AA with our current design
* Neutral, because it may require slighly more work than the bare minimum in the future
* Neutral, some automated a11y tools don't yet support 2.2 (as of Oct 2023)
## More Information
* For a complete description of Section 508, see https://www.access-board.gov/ict/
* WCAG 2.1 is a superset of WCAG 2.0, which will be the official 508 version until Access Board approves an update, which can take years.
* Most automated testing tools use version 2.1, so 2.0 compliance may appear as failing on tools and 2.2 may not be available. In 2.2's case, it is largely backwards-compatible to 2.1 AA assuming all other criteria are met; therefore, if tools don't reflect 2.2 we can treat their 2.1 AA conformance as equivalent.
* Most testing tools are focused on level (A, AA, AAA) of compliance, so setting level AA as our target would be more memorable, programmable, and communicable.
* How we achieve these targets, including tooling and processes, are described in a separate decision record.
* WCAG 3 is still in a working draft phase, but it provides some guidance that may be truly better but technically non-compliant with 2.2 due to backward incompatibility. For example, WCAG 3.0 uses a new [color contrast algorithm (APCA)](https://github.com/Myndex/SAPC-APCA/blob/master/documentation/WhyAPCA.md#why-the-new-contrast-method-apca/) that better matches reality. In our effort to exceed targets, we may want to use [this calculator](http://www.myndex.com/APCA/) to test contrast among other things to allow us to both exceed our targets and be forward-thinking.
* Things 508 covers that WCAG does not explicitly (TLDR: there are no issues):
* **Functional Performance Criteria**: at least one method must be provided allowing individuals with disabilities to interact with the product. Most of these are [explicitly covered by WCAG](https://www.section508.gov/content/mapping-wcag-to-fpc/), but two are not:
* Without Speech - where speech is used for input, control or operation, ICT will provide at least one mode of operation that does not require user speech. We will not have any speech-based features built into this project, so this is not an issue.
* With Limited Reach and Strength - where a manual mode of operation is provided, ICT will provide at least one mode of operation that is operable with limited reach and limited strength. We will not have any manual operation methods, so this is not an issue.
* **Hardware and software**: 508 applies to websites like this, as well as hardware and operating systems. We are not building these, so this is not an issue.
* **Alternative Means of Communication**: 508 ensures that people with disabilities can effectively communicate and interact with support personnel. Examples of alternative means of communication include relay services for individuals with hearing impairments or providing accessible contact options for individuals with disabilities.

View file

@ -0,0 +1,60 @@
# ADR: Configuration Storage
DATE: 12/08/2022
Where should the configuration live, how can we ensure that it is version controlled, and what does a change process look like? At a minimum the change process should include the time and date of the change, the user who changed it, and a note from the user indicating why they made the change. A more advanced system would have sign offs that are also recorded. These actual configuration, and the changes to the configuration should be stored in git, but this may not be the best tool for disseminating changes out to containers running our software. For that we will need an accessible system that meets or exceeds our SLO. The focus of this document is how to store the data in such a way that it is made available to every container effectively, including audit systems, editing systems, and the tax engine itself.
## Decision
We should store the configuration of the tax rules in S3/a document store. The basic pathing will look something like the following:
```
/{schema-version}/
/{schema-version}/config1.xml
/{schema-version}/config2.xml
/{schema-version}/justification/
/{schema-version}/justification/justification.xml
```
The justification is the who, what, when, where, and why of the change.
## Rationale
We need a highly available method of updating n containers in m availability zones. We haven't set any SLOs yet, but money is on them being pretty tight. We need something that can be updated easily, and that won't require any downtime to make an update. We will want to do a schema version validating as part of a system health check, but that should be part of a normal health check! It could be stored in the database with the tax information, if we do indeed go that route, but it seems like extra work to mash all of the config into a blob when there is no reason to do so. They are documents and should be in a document store.
## Rejected ideas
#### on local storage/in container storage
This is the easiest option, and what we used for the prototype, but it would be unwieldy at scale. The update process for the schema would require a bit of downtime as we knock the containers down and bring them back up with the new configuration. There are other ways around that, like supplying it through an endpoint, but that would require verification and be a whole mess.
#### shared disk storage
This isn't a bad option for how to deal with the tax rules schema changes, but there is a concern of people directly changing it. Even if it is somehow secured and safe through another piece of software, tracking who changed it, when, and why, it would still represent a single point of failure in the system. There are mitigations for this, but what it starts to look like is a document storage system, which is what this ADR suggests.
#### blob storage
Blob storage could work for this, but it might be a bit awkward. If the configuration breaks up into multiple files, we could mash them all into one and store them in the blob, but that isn't as clean as keeping the documents separate. This approach does have the benefit of keeping the signoff and the reasoning behind it together.
## Assumptions
#### Config is documents
This seems like a solid assumption, but it might not be! I am having a hard time imagining something else, but maybe there is something.
#### We need high availability
We believe that the tax system can't go down during tax season. This seems like a really safe bet. It can basically be spun down for months out of the year, but once the season starts, this has to be on all the time and working.
#### We will have multiple application instances
I feel like this is something we should plan for, but hey, maybe I am wrong! I think that it would make sense for us to run several instances of the tax engine behind a load balancer so that we can make sure that it can handle the scale.
#### Regular disk storage is unreliable/unworkable
This assumption comes from not trusting file system watchers, and being concerned about disks in general. It feels like a potential point of failure to hook a shared disk to a container (imagining both running in AWS). There could be issues with the disk, with the connection to it, maybe it gets tampered with (not sure how)... I just trust databases more than a disk (I know they are on disks). I like the automatic backup schedules, the order, and the ability to see and track what is going on. This may just be a prejudice that I am bringing to the table. I trust document stores more than just disk storage. All of the pathing above could be used on a regular disk.
## Constraints
- The medium should be protectable in some way, meaning not just anyone can write and read.
- The medium should be available to many systems.
- The medium can meet auditing requirements (reads and writes are tracked in some way).
## Status
Pending
## Consequences
TODO: fill this in when we start seeing consequences!

View file

@ -0,0 +1,33 @@
# ADR: Configuration Management
DATE: 07/05/2023
## Background
A Configuration Management Plan is required in order to maintain proper control over the software and infrastructure in use by DirectFile.
This plan will be used by developers, operators, and security engineers and assessors in order to verify that the software and services in use have been properly vetted and authorized before being used. The plan must lay out policies and procedures for configuration management that speak to the needs of the Configuration Management Plan (CMP) Data Item Description (DID).
## Decision
The CM plan policies will be broken down into component stages for ease of consumption by the day-to-day engineers on the DirectFile team.
1. Development. This file will define policies and procedures for integrating new configuration and updating configuration of application code, including adding new features and required CI/CD scans and Pull Request approvals. This should also include any details on software that must be installed on developer's laptops above and beyond the standard-issue IRS GFE.
1. Infrastructure: This file will define policies and procedures for our infrastructure-as-code (IaC) implementation. This should also include details on how the baseline of deployed services is maintained, verified, and audited.
1. Deployment: This file will define policies and procedures for deploying changes to various IEP environments. This should also include details on how the baseline of runtime configuration is maintained, verified, and audited.
These files will be referenced by link to the established CMP DID to ensure each section of the CMP is covered by our policies and procedures. They should also be referenced from the full project's README.
## Rationale
The referential approach serves two purposes:
1. Day-to-day usefulness. By storing the CM policies alongside the code and IaC implementations, we reduce the onboarding burden, and ensure all engineers know the policies they are required to follow in developing and deploying DirectFile.
1. Accurate compliance. By utilizing the CMP DID as designed, we ensure that we speak to all aspects of IRS CMP processes. Additionally, by utilizing links to version-controlled documents rather than copying and pasting we ensure that our compliance documentation is accurate and up-to-date at all times.
## Status
Proposed
## Consequences
Each file must include some boilerplate to ensure future updaters know that certain questions from the CMP DID are being answered by the CM policies.

View file

@ -0,0 +1,59 @@
# Database migration management
Written: August 17, 2023
## Background
Direct File database schema changes are presently handled by Hibernate's auto DDL and run automatically at application start. This is simple and easy for early development efforts and can handle many database migrations automatically. Modifying an `@Entity`-annotated class is all that is necessary to make most schema changes, even destructive ones (depending on configuration).
As Direct File matures and approaches testing and eventual production usage, we must be more careful about changes to the database schema and take steps to reduce the likelihood of unintended changes. One way to do this is to integrate a tool that supports evolutionary database design.
### Required features
* Allow separation of database changes and code changes
* Easily determine what changes will happen when migrations are applied
* Allow database changes to be applied separately from application start
* Easily determine the current migration revision of the database
* Allows migration to a specified revision which may not be the newest
### Evaluation criteria
* Integrates with Java tooling
* Integrates into code review process
* Allows separation of privileges for database users
* Ideally, already available in IRS artifact repository
## Options considered
While there are many tools available for managing migrations that could work for Direct File, there are two that rise to the top due to their extensive usage and ubiquity in Java-based applications. They are [Liquibase](https://www.liquibase.org/) and [Flyway](https://flywaydb.org/).
Each of these meets the requirements for use by Direct File.
### Liquibase
* All migrations in a single file
* There is a choice of file format (YAML, XML, etc) and individual migrations can be specified directly as SQL or in a database-agnostic format.
* Easy to view all migrations and determine the order they will execute
* Requires coordination between developers for concurrent development of migrations
* Database changelog can get large and unwieldy over time
* Already available in IRS artifact repo (both `liquibase-core` and `liquibase-maven-plugin`)
### Flyway
* Migrations split into multiple files
* Each migration is SQL
* Potentially easier to concurrently add migrations, but still requires coordination between developers for concurrent development of migrations
* Possibly more difficult to follow the flow of migrations
* Already available in IRS artifact repo (both `flyway-core` and `flyway-maven-plugin`)
## Recommendation
Liquibase
Direct File is relatively small and should remain that way for some time. As the system has begun to grow, additional purpose-specific small services have been added. Those may have their own associated data stores, keeping the complexity of any single database limited.
Liquibase's single-file migration changelog will make it simple to view existing migrations and the low complexity of our database will mean the changelog should not grow out of control.
## Decision
Direct File will use Liquibase.

View file

@ -0,0 +1,69 @@
---
# Configuration for the Jekyll template "Just the Docs"
parent: Decisions
nav_order: 100
title: "Design & a11y reviews"
# These are optional elements. Feel free to remove any of them.
status: "Proposed"
---
<!-- we need to disable MD025, because we use the different heading "ADR Template" in the homepage (see above) than it is foreseen in the template -->
<!-- markdownlint-disable-next-line MD025 -->
# Accessibility testing methods
## Context and Problem Statement
In order to work in an agile fashion and ensure code changes meet both design spec and our [accessibility target](adr_a11y-target.md), we should align on a consistent process to achieve this. As part of the [accessibility review](adr_a11y-methods.md) for each PR, the original developer will do a first pass of both design and a11y review. This DR covers how designers will be the second set of eyes on those user-facing changes.
## Considered Options
* Review each PR locally before merging
* Review all merged PRs for the current sprint in the deployment environment at the end of the sprint
* Review entire application in the deployment environment every other sprint
* Review entire application in the deployment environment when designers are available
## Decision Outcome
Chosen option: "Review all merged PRs for the current sprint in the deployment environment at the end of the sprint", because it is the best we can reasonably do given our comfort with the tools and time available.
### Consequences
* Good, because it maximizes coverage
* Good, because it does a decent job of preventing issues from sneaking by for more than a sprint
* Bad, because it requires extra time to create a new issue for each problem discovered
* Bad, because it requires extra time to filter Github PRs by date
### Confirmation
This decision is confirmed by all designers, as they will be doing this work.
## Pros and Cons of the Options
### Review each PR locally before merging
* Good, because it maximizes coverage of changes
* Good, because it prevents almost all issues from sneaking by
* Good, because feedback can go directly into the PR
* Bad, because it requires frequent intervention by designers who may not be comfortable with necessary tools
### Review all merged PRs for the `{current | previous}` sprint in the deployment environment at the `{end | beginning}` of the sprint
* Good, because it maximizes coverage of changes
* Good, because it does a decent job of preventing issues from sneaking by for more than a sprint
* Bad, because it requires extra time to create a new issue for each problem discovered
* Bad, because it requires extra time to filter Github PRs by date
### Review entire application in the deployment environment every other sprint
* Good, because it maximizes coverage of the final user experience (end to end)
* Neutral, because it does a decent job of preventing issues from sneaking by for more than two sprints, but can mean more work is needed to recover from it
* Bad, because it requires extra time and cognitive load to check what was merged and identifying in the environment what to review. It's more likely in two vs one sprint that multiple PRs covered a certain page/feature, so filtering PRs by date is less useful.
* Bad, because it requires extra time to create a new issue for each problem discovered
### Review entire application in the deployment environment when designers are available
* Neutral, because it could maximize coverage of the final user experience (end to end), but only as much as the designer has time for
* Bad, because lingering design/a11y debt can be harder to pay off the longer it lingers
* Bad, because it requires extra time and cognitive load to check what was merged and identifying in the environment what to review. It's higly likely that multiple PRs covered a certain page/feature, so filtering PRs by date is useless.
* Bad, because it requires extra time to create a new issue for each problem discovered
## More Information
* The design review checklist is located in the PR template for the first option and in a [separate document](../design-review-process.md) for all other options.

View file

@ -0,0 +1,34 @@
## Overview
There are two main scenarios that, as it currently stands, the combination of our incident response (IR) practices and customer support (CS) motion do not support:
a) A taxpayer hits submit but an XMl validation failure occurs and they cannot submit at all. CS is unavailable (for whatever reason) and they give up attempting to submit with Direct File.
b) A taxpayer submits successfully, but an internal error occurs in the Submit application that blocks our ability to send their return to MeF. CS is not involved because, presumbly, the taxpayer never reached out to CS in the first case as they didn't run into any errors when hitting submit.
Our inability to reach out to taxpayers proactively is primarily due to the fact that CS can only reach out to taxpayer who reach out to them first via eGAIN.
In the above scenarios, neither taxpayer knows 1) if the issue they ran into has/will be fixed; and 2) if so, that they should resubmit their return. As a result, they are effectively left in the dark and/or knocked out of the filing with Direct File, thereby forcing them to submit elsewhere.
While our scale to-date (as of 2/26) has shielded us from the pain of these scenarios, or alleviated them altogether, we don't have a clear way to address them at this moment. Further, there is a very high likelihood that these scenarios will occur over the coming weeks and will become especially painful if/when the submission volume scales dramatically faster than our CS capabilities.
## Proposals
While we cannot change our CS motion to support this, we can enable a better product experience through how we notify taxpayers via email when an error occurs in our system.
### Notify taxpayers when we cannot submit due to internal error
We should notify taxpayers via email that there was an error submitting their return at the time of submission, i.e. XML validation failure or XML validation success but Submit app failure. The technical infrastructure to send emails on XML validation failure is already in place, we just need to create the HTML template for the email and actually send an email when XML validation failure occurs. Similarly, the requirements to send an email due to a post-submission error when trying to submit to MeF can be found here, and just need to be actioned.
### Notify taxpayers when Direct File has deployed a fix that should allow them to resubmit their return
We should also notify taxpayers via email that they are able to submit their return when we have deployed a fix into production that addresses the error that blocked them from submitting in the first place.
### Proposed Technical Changes (Rough)
1. Add two new HTML Templates to capture the two notification scenarios above, e.g. SubmissionErrorTemplate and ErrorResolvedTemplate. The templates should be added to the backend app, such that the ConfirmationService can process it, as well as the actual HTML template in the email app that is sent via email and rendered to the taxpayer
2. When an XML validation failure occurs during submission create a `SubmissionEvent` with an `eventType` of `error_xml` and enqueue a message from the backend to the email app to notify the user (naming of the eventType is TBD, might make sense to add a new `message` column and keep the eventType as `error`)
3. Update the SQS message sent from submit -> backend (on the submission confirmation queue) to allow for an `error` status. If the ConfirmationService and SendService are properly configured as per #1 above, everything should flow seemlessly. Similar to #2, create a `SubmissionEvent` with an `eventType` of `error_mef` for each submission that failed to submit to MeF (naming of the eventType is TBD, might make sense to add a new `message` column and keep the eventType as `error`)
4. Add a function to the backend that, when called, ingests a CSV of `taxReturnIds`, transforms the list into a SubmissionStatusMessage and calls ConfirmationService.handleStatusChangeEvent
5. Once a deploy goes out that fixes the underlying issue, create a CSV with `taxReturnIds` of the affected taxpayers (both those who reached out to CS and those who did not) using Splunk queries
6. Send this CSV to IEP and ask 1) their System Admin to run the command specified in #4; or 2)have them upload it to S3 and do something similar to the email allow list such that the function specified in #4 polls S3 and sends emails based off this polling. This second approach would require more state management but would possibly cut out the need for IEP to run commands and maybe obviate the need for a p2 to make this happen.
7. Add monitoring in place to observe the emails being sent out accordingly
8. [Alternative] We move the 'submitted' email to send only after we receive submission confirmation, not after we pass XML validation

View file

@ -0,0 +1,27 @@
# Encrypting taxpayer data
Date: 07/31/2023
## Status
Approved
## Context
Our system stores fact graphs containing sensitive taxpayer data including personally identifiable information (PII) and federal tax information (FTI). To mitigate the impact of a breach or leak, we want an approach for encrypting this data at rest. This approach should satisfy both our team's desired security posture and relevant compliance controls.
To date, we have considered a client-side approach and a server-side approach.
## Decision
We will implement server-side envelope encryption for securing taxpayer fact graphs at rest. We will generate a per-user symmetric data encryption key and use that key to encrypt fact graphs before storage in the taxpayer data store. The data encryption key will be encrypted using a root key and the encrypted key will be stored next to the fact graph in the taxpayer data store. The root key will be managed by AWS's Key Management Service (KMS).
## Consequences
- The server-side approach reduces implementation complexity, allowing us to meet our desired security qualities and maintain timelines for pilot launch
- We will need to implement additional mitigations to avoid information disclosure of plaintext fact graph data (e.g., through logging)
- We aren't reinventing the wheel, and we can take advantage of industry-standard encryption functionality provided by AWS KMS
- Plaintext fact graphs will be visible to the public-facing API gateway and other supporting services that sit between the web frontend and the Direct File API. Plaintext fact graphs will also be accessible to an administrator with the necessary decrypt permissions within KMS
- If needed, fact graph data can be migrated server-side
- Future layers of protection (e.g., message-level encryption) can be added as our threat model matures
- We will need to identify a stand-in for KMS in local environments and put any KMS-specific code behind an abstraction layer

View file

@ -0,0 +1,80 @@
---
# Configuration for the Jekyll template "Just the Docs"
parent: Decisions
nav_order: 100
title: "Error message types"
# These are optional elements. Feel free to remove any of them.
status: "In review"
---
<!-- we need to disable MD025, because we use the different heading "ADR Template" in the homepage (see above) than it is foreseen in the template -->
<!-- markdownlint-disable-next-line MD025 -->
# Accessibility testing methods
## Context and Problem Statement
We use error messages across the application, many of which follow certain patterns. We also have a challenge of translating all content, including those messages, which increases for each unique string. This decision record seeks to resolve both issues.
YYY and XXX have proposed an initial set of [patterns](#patterns) below guide that could be used for either option 1 or 2 below. Either way, those exact patterns should be considered independent of this decision itself, just presented as a clear example of the outcome of this decision.
## Considered Options
1. Create a set of patterns for all fields to use exactly
2. Create a set of patterns to use as a guide for many unique strings
3. Use any string we want in each error messages
## Decision Outcome
Chosen option: "Create a set of patterns for all fields to use exactly", because it minimizes translation cost, maximizes engineering efficiency, and minimizes content review.
### Consequences
* Good, because it maximizes consistency in implementation
* Good, because only the source strings need content review and translation work
* Good, because all instances of the string can be updated in one code change
* Good, because it sets a consistent content UX
* Neutral, because some fields may still need custom strings
* Bad, because some strings will be ok but not great for some instances
## Pros and Cons of the Options
### Create a set of patterns to use as the sole source for all fields
* Good, because it maximizes consistency in implementation
* Good, because only the source strings need content review and translation work
* Good, because all instances of the string can be updated in one code change
* Good, because it sets a consistent content UX
* Neutral, because some fields may still need custom strings
### Create a set of patterns to use as a guide for field-specific strings
* Good, because it sets a clear expectation for implementation
* Neutral, because similar/same strings may be easily discovered and grouped for content review and translation work
* Bad, because every string needs its own translation work
* Bad, because every string needs engineering work to update it
### Use any string we want in each error message
* Good, because it maximizes flexibility for initial implementation
* Bad, because every string needs its own content review and translation work
* Bad, because every string needs engineering work to update it
* Bad, because it may be confusing if the same type of error has different formulations across fields
## Patterns
| Type | Formula | Examples |
| -------------- | --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Required | This is required | [Same] |
| Match/re-enter | This does not match | [Same, and the field label should indicate what it matches to] |
| Length maximum | Must have fewer than [x] [y] | Must have fewer than 8 numbers<br>Must have fewer than 8 numbers and letters |
| Length minimum | Must have at least [x] [y] | Must have at least 16 numbers |
| Length target | Must have exactly [x] [y] | Must have exactly 10 numbers |
| Length range | Must have between [x] and [y] [z] | Must have between 8 and 16 numbers |
| Amount maximum | Must be less than [x] | Must be less than 100 |
| Amount minimum | Must be at least [x] | Must be at least 10 |
| Amount range | Must be between [x] and [y] | Must be between 10 and 100 |
| Date maximum | Must be [x] or earlier | Must be December 31, 2023 or earlier;<br>Must be today or earlier;<br>Must be tomorrow or earlier;<br>Must be yesterday or earlier |
| Date minimum | Must be [x] or later | Must be January 1, 2023 or later;<br>Must be today or later;<br>Must be tomorrow or later;<br>Must be yesterday or later |
| Date range | Must be between [x] and [y] | Must be between January 1, 2023 and December 31, 2023;<br>Must be between January 1, 2023 and today;<br>Must be between today and tomorrow;<br>Must be between yesterday and tomorrow |
| Allow list | Must have only [x] | Must have only English letters;<br>Must have only numbers;<br>Must have only English letters and numbers;<br>Must have only numbers, parentheses, and apostrophes;<br>Must have only !@#$%^&\*() |
| Example | This should look like [x] | This should look like username@website.com;<br>This should look like 123-456-7890 |

View file

@ -0,0 +1,43 @@
Date: 12/23
### Introduction
The concept of a tax return has recently evolved with the introduction of the concept of a resubmission. Whereas in the one-shot submission case we could assume a linear progression of data, with resubmissions we are faced with non-linear and cyclical progressions of tax return throughout the various services, effectively repeating the submission process until we receive an accepted status.
### Objectives
- Define a database schema for the backend database that enables **painless, scalable and future-proofed** tracking of the entire submission lifecycle at the database level with **minimal future migrations and backfills**.
- Minimize the number of unnecessary changes (migrations, backfills)
- We don't fundamentally know what we will need from a data storage perspective at this moment in time, so we should approach it from the standpoint of 'better be safe than sorry' for the pilot. We might store more data than we need if everything goes well, but if things don't go well we will be happy that we have the data laying around.
### Why make more changes to the `backend` schema
Upon further requirement gathering and edge cases cropping up, it appears that the schema changes we initially agreed to previously isn't going to scale well in the long term. Specifically, I don't believe that, based on said the #3562 schema changes, we could reliably reconstruct the history of a taxpayers journey through DF if they have to resubmit their return given our current models or describe what events happened at what time in said journey. Reconstructing the history from the data/backend perspective is a business requirement in my mind (for a variety of reasons) and should be solved pre-launch. As a result, I think we need to evolve our data modeling of the `TaxReturn` object and its relations a bit more to capture the domain we are after.
To be clear, this is less driven by our need to enable analytic at the database level (that is covered elsewhere). Rather, it is around modeling submission, tax returns, and status changes in a way that uplevels our observability into a taxpayer's journey through DF from a backend perspective. Even though we will likely not have access to production read-replicas for the pilot, we should still have an observable system with clean architecture.
### Why not make the minimally viable set of changes now and wait until after the pilot to make more changes
1. _As soon as we start populating our production database, the cost of making changes in the future is orders of magnitude higher than making them now._ In other words, if we don't make changes now but realize we need to make changes in June 2024, we now have to worry about taxpayer data loss as a consequence of executing migrations and backfills incorrectly.
2. In prod-like environments, I presume that we should not, if not cannot, pull taxpayer data from S3 (XML) or decrypt encrypted data (factgraph) to answer questions about a taxpayer's journey through DF. This would violate compliance firewalls on many levels and I assume that we should not rely on these avenues.
3. Aside from wanting better observability as we roll out in Phase 1-2 to give us confidence, from an incident response standpoint we need a way to break the glass and run SQL queries against the prod db if we are in trouble, even if that means asking a DBA on EOPS/IEP to make the query for us. In the event/when that this happens, those queries should be performant, simple and easier for a larger audience to understand without deep technical knowledge of our system. As described below, cleaner data modeling with a limited number of mutable fields makes analysis much easier
4. Our analytics integration (with whatever acronym'd platform we are going with these days) will land TBD in Q1/Q2 2024, assuming it lands on time. This means that if we need to run baseline reporting before we can access the analytics platform, we will need to do it at the database level based on whatever schema we decide on.
5. We haven't actually made meaningful changes to the backend database that populate data into tables in a new way. This means that any future changes to the codebase or database are still, effectively, net new and wouldn't require us to refactor work we just implemented.
### Current Schema Design
Our original implementation of the backend schema model system only contained the `TaxReturn` model. See Original Schema image in description.
The most recent iteration proposed in #3562 used a combination of `TaxReturn` with a new 1:M relation to an event-tracking model `TaxReturnSubmission` as follows (the mental model of how this works is described here ("Epic: Resubmit Return After Rejection"). See 'Interim Schema originally agreement upon in resubmission epic scoping' image in description.
After some more research into resubmissions and discussions with various team members working on related work, I believe that the above combination of `TaxReturn` and `TaxReturnSubmission` is still insufficient in themselves to achieve what we want. While we could handle both of these concerns at the `TaxReturnSubmission` level, this would result in 1) a model that begins to drift away from its original purpose, namely to track status change events through DirectFile; 2) a model that needs to replicate a bunch of data each time we want to create a new event (such as facts and return headers) without any discernible value; and 3) a model that begins to combine mutability (session time tracking) with immutability (status logging). For instance, if a taxpayer spent 20 minutes on the original submission and 5 minutes correcting errors and resubmitting, we should be able to attribute 20 minutes to the original submission and 5 to the correction, rather than having a single 25 minute field that cannot be attributed to the original or correction session. We cannot do this right now.
### Schema Proposal
See Proposed Schema in description
We move to a schema definition that more neatly decouples mutable data and immutable data by:
1. Remove the `submit_time` column from the `TaxReturn`.
2. Rename `TaxReturnSubmission` to `Submission` but maintain the M:1 relationship to `TaxReturn`. The `Submission` table is meant as a map between a single tax return and all the submissions that comprise the journey from creation to completion (ideally acceptance). Each `Submission` for a given `TaxReturn` maps to a snapshot of various data, most importantly the facts and return headers, when the /submit endpoint is called.As a result, we should add a `facts` column to the table, similar to the data definition `TaxReturn`. The key difference for these two fields is that the data stored on the `Submission` table is immutable and represents our archival storage of the facts and returns headers at a single moment in time (submission). When a new submission ocurs, we create a new `Submission` record to track this data, and copy the related `TaxReturn's` `facts` onto the `Submission`.
3. Add a `SubmissionEvent` model that FKs to `Submission`. The sole purpose of the `SubmissionEvent` model is to track status changes in our system, thereby function as an append-only audit log of events (effectively a write ahead log that we can use to play back the history of a submission from the standpoint of our system). Any immutable data corresponding to a status change event should live on this model. The statuses will be broader than MeF statuses alone.

View file

@ -0,0 +1,124 @@
# ADR: Data Storage
DATE: 12/21/2022
## Background
Our system will utilize and produce several kinds of data in its normal operation, each of which need to be considered when discussing storage. The categories are as follows:
1. **User Information**: We plan to use one or more third party authentication providers to provide verification of a user's claimed or proved identity. Those users will have preferences and personal information that our system will need. Although some of that information may be stored by the authentication provider, we will ask for it ourselves to avoid IAL2 identity proofing burdens.
2. **Unfiled Tax Information**: The goal of our system is to produce or file a tax return. To get to the point of filing or producing a tax return, a user will be asked a series of questions that will drive our system's ability to fill in the form(S) provided by the IRS. The answers to these questions must be stored and updated.
3. **Filed Tax Information**: When the user is ready, our system must offer them a method by which they may file their tax return. This could be either through the MeF or by mailing it a PDF. Our system must maintain the artifacts it creates for the period required by the agency. They should also be stored with information that would allow us to replicate the system they were run on, meaning version numbers for all software and schemas involved.
4. **Tax Software Schema Information**: The system asks a series of questions and collects information from the user. The questions asked and the structure by which the data is understood must be stored and versioned. In the initial version of the product we used configuration for both the question flow and the facts that were answered by the questions. We imagine something similar will be necessary.
5. **Permissions**: A user may have access to multiple years of returns, as well as returns filed by someone else on their behalf. In the first year, it may be required for multiple people to use the same account to file jointly. After the first year however, we may want to allow multiple accounts to view the same return and sign independently. We can also imagine a scenario where someone helps another person file taxes, or maybe needs access to previous years for another person in order to help them file this year. The implication is a sort of permission system which is out of scope for this document.
These general categories constitute the basic data that our system will use and generate. The decisions on how to store these pieces of information and how we came to those decisions are the subject of this document.
## Decision
The decisions here are going to be put in technology neutral terms, referring to general categories of systems rather than by specific brand names. Each of the categories above are handled differently in our system.
1. **User Information**: We expect that a minimum of data will come to us from the authentication provider. We will need to ask the user for most of the necessary personal information and store it ourselves. We will use a relational database table to store the ID from the authentication provider, the type of authentication provider (i.e. the name of the service), an ID specific to our system, and the necessary personal information. User preferences will be stored in the relational database as either a blob or as a table.
2. **Unfiled Tax Information**: A blob in the system's relational database is our preferred approach to handling information on which the user is actively working.
3. **Filed Tax Information**: A document storage system outside of the system's relational database is how we feel that this data should be stored.
4. **Tax Software Schema Information**: This can be stored in either a document store or in the relational database. It is slightly preferred to keep the schema in the relational database as it will allow for metadata storage and easier querying.
5. **Permissions**: The permissions on tax returns will be stored in the relational database.
## Rationale
#### User Information
To receive personal information from authentication providers, we would have to burden users with IAL2 identity proofing requirements. In order to avoid this, we will ask users to provide the information, and store it ourselves.
By storing information about the user that the auth system also stores, we will make it difficult for the user to anticipate behaviors between the two systems. One can imagine the frustration scenario of updating your information in our system with the expectation that it will be updated in the auth provider (why would I need to update it twice?). The opposite direction is equally annoying. Why didn't you just pull my information from the auth provider rather than making me update it in your system as well?
We will need to mitigate these impacts with careful messaging and communications.
Our use of a database table to store the user information linkage into our system is partly out of necessity and party convenience. We would like a unified ID internal to our system that connects users to tax records. Also, we don't want to be reliant on any particular third party auth provider. Beyond these two concerns, we would also like to not lock the user into a specific email address. There are a few ways to meet these requirements, like, for example, linking the records by PII. We felt that using PII would not be in the best interest of the user. There are conditions under which a users most sensitive PII, like their social security number, may change, whereas the ID they were assigned in the third party auth system will not change. The third party ID approach will also make it far more difficult to identify a user by their user record.
The user preferences are not of substantial concern. They do not require encryption, and they do not represent any real load on the system. Most likely they will be a set of key value pairs that represent how a user would like to see the site.
**Key Ideas**
- We don't want to burden users with meeting IAL2 identity proofing requirements.
- We don't want to lock our users into an email.
- We don't want to lock ourselves into a third party auth vendor.
- We don't want to use PII which might change to identify records.
- We would like an internal ID to identify users and their records that are unique to our system.
#### Unfiled Tax Information
There are several complexities that storing the active tax data in a blob solves. The first is that it doesn't lock us into using either snapshots or deltas. In a document storage context it would be easier to wipe out the old document and write a new one each time the user updates. This could be countered with an event/command sourcing pattern, which would then require us to validate each message is received, processed and stored. The easiest way to allow for either update concept is to use a JSON blob. If we are given new key value pairs, we simply have to apply them to the blob. If we want to wipe out the whole blob and rewrite it, we easily can.
The next important value is atomicity. Anything we do in the database can be done in a transaction if necessary, allowing us to roll back if there are any problems. The same could not be said if the data is stored in a document storage system elsewhere. Imagine, for example, that we would like to store the last updated time on the document. We could perform that update in our database, and then attempt to write the document to the document storage system only to have it fail. We now have a belief in our database, that the record was updated at time X, that is false. This isn't good. This same action could create broken links in the system.
Storing the information outside of the database requires extra hops. If the information is linked but stored in another document storage system, we will still have to go to the database to read the link and find the document. This means that rather than doing one database read we will have to do one read on the relational database and one on the document store. From an efficiency standpoint, this is a bad idea.
The data we are planning to store is not so large as to cause a problem for any common RDBMS provider. There won't be any particular slowdown or read issues associated with reading the data out of the database.
The final point is around single points of failure in the system. We can architect around having the database be a single point of failure in our system: there are a lot of tools to avoid that being a problem (like replication/failovers for example). If our database system does go completely down, our system will go down as well. Introducing another system doesn't solve that problem, and it in fact compounds the problem. Now we are reliant on two systems not going down rather than one. The likelihood of either going down is fairly low, but we have doubled our chances of trouble if we move any "active" data out of our database.
**Key Ideas**
- No lock in with respect to snapshot vs deltas
- Relational database operations are atomic, and can be rolled back on failure
- Storing data in multiple systems is less efficient as we will have to jump multiple times to get the data.
- Our data is not too large for efficient database storage.
- We already have the database as a failure point, why add more?
#### Filed Tax Information
The information generated around filing are PDF(s) showing the tax form as we have filled it out, the information we sent to the MeF, a copy of the data used to generate the form, and some information about the version of the system and the schemas used to file. This is read-only information meant to be a record of what was submitted to the IRS (which may also be helpful if we ever have to audit our system).
The first, obvious point is that these are mostly documents. The PDFs in particular are definitely files that can and should be stored as files. We don't know upfront the total number of documents that may be required. We can imagine that we will smash all the pdfs potentially required into one large pdf, but even if we do that there could be other documents that are necessary to retain. The uncertainty around the number and the size of these documents makes a document storage system a logical choice.
The fact that they are read only also helps inform the decision. Having them in a separate system that doesn't have a write capacity in the normal functioning of the system, except on filing, makes them safer from potential bugs that could cause a write to the wrong file. One could imagine for instance, a user is actively working, files, and then goes back to change something because they want to see if it will be reflected in their taxes. It is unlikely, but a bug could be introduced that updates the field data in the database. The extra level of protection is not necessary, but is an added benefit.
**Key Ideas**
- The artifacts are documents and should be treated like documents.
- We don't know how many potential artifacts we are dealing with.
- These are read only, and having them separated helps to make that more clear and avoids potential bugs.
#### Tax Software Schema Information
Either solution is acceptable in this context. We have a slight preference to storing it in the database so that some meta information can be stored with the schema. In the future we may want to change logging, marking the who, what, when, where, and why. It would be nice if we could also have the deltas of the change stored in a field nearby the schema.
If there is ever a need to query the schemas, maybe to show the change over time of a specific fact, it would be easier if they were in the relational database.
**Key Ideas**
- Either system would work.
- There are some advantages to storing the information in the relational database
- Able to add meta info to relational database table easier
- If we ever want to perform a query on this information the relational data will make that easier
#### Permissions
The permissions are applied to both the filed tax information and the active tax information. Because the active tax information is stored in the relational database, it is logical to store the permissions there as well. It wouldn't make sense to store the permissions elsewhere. The system relied on the relational database for general operation. If the document storage system went offline, it would be possible to continue operation, either without filing or with a queued filing system in place. If the permissions were in another location we would lose this property.
**Key Ideas**
- Permissions apply to the data in the relational system and the document store
- The system should still be able to operate without the document store, which means that permissions should be in the relational database
- Why would we store it away from the user's active data?
### Rejected ideas
### Assumptions
- User preferences are not of significant concern in terms of data storage.
#### Third party user IDs are
### Constraints
- We need a storage system that meets any SLO we may have.
- The system has to be widely understood and available. It shouldn't be something that contractors won't know.
- The system can scale without a bunch of management.
## Status
Pending
## Consequences
- Our UI will have to communicate to users that data entry does not update their personal information in a third party auth system.

View file

@ -0,0 +1,161 @@
---
parent: Decisions
nav_order: 100
title: "Yaml Translations"
# These are optional elements. Feel free to remove any of them.
status: "Proposed"
date: "20230906"
---
<!-- we need to disable MD025, because we use the different heading "ADR Template" in the homepage (see above) than it is foreseen in the template -->
<!-- markdownlint-disable-next-line MD025 -->
# Yaml Translations
## Context and problem statement
The translation files have 3 use cases
* The frontend code dynamically populates screens with the content of the translations. The structure needs to work with react-18next.
* The content will need to be written by a content team, and possibly taxperts, in the future.
* The content will also be provided as a set of meaningful strings for the translation teams to translate. They will return translations which will then need to be reintegrated into the codebase.
As this will be consumed by non-engineers, the current strategy of allowing tags within strings is becoming unwieldy.
The translation team has expressed concern with the html style strings and we decided to find a less challenging and less error-prone format.
## Desirable solution properties
We'd like the format to
1. Be easily consumed by our frontend and generate correct html
2. Be easily editable by the backend team currently writing content
3. Be easily editable by the content team when we transition to them editing
4. Split into strings that preserve enough context for translation teams to translate
5. Do not contain too much complexity of tags within the strings (`<strong>` and `<i>` ok)
## Considered options
1. Don't change anything, use json with all tags in strings
2. Use json but represent html as a structured json object
3. Use markdown and convert to json
4. Use yaml and represent html as a structured object
## Decision Outcome
Chosen option: Use yaml and represent html as a json object
Reasoning: Yaml is designed to be easy to read and understood by humans, which will help our translation/content files be more editable and consumable for everyone. By introducing the structure, we can cleanup the proliferation of tags in our strings and make the translation process go more smoothly.
Yaml is a superset of json and can represent all our current json 1:1. It's also a format that can be ingested by react-i18next.
Consequences:
* We need to convert the json to yaml, and break up the html strings into structured yaml, which will be used to generate the content.
* Editors of en.json will have to write yaml.
* Translators will get simplified strings with minimal html.
## Pros and Cons
### Don't change anything, use json with all tags in strings
```
"/info/you-and-your-family/spouse/intro": {
"body": "<p>You'll need to know:</p><ol> <li><strong>If you're considered 'married'</strong><p>Many long-term partnerships resemble marriage, but for tax purposes, there are guidelines for what is and isn't considered married.</p></li> <li><strong>If you and your spouse want to file a return together</strong></li><p>People who are married can file a tax return together (jointly) or file separate returns.</li> </ol>"
},
```
#### Pros
* No work, it's what we have already.
* React-i18next supports json out of the box.
#### Cons
* This is getting harder to read and edit as we continue to insert more content into this file.
* Translators will struggle with the nested tags and likely make errors which will slow down translation updates.
* It's not possible to break down these strings easily into meaningful snippets to send the translators, that will convert back into json.
* Content team might also struggle with editing this format.
### Use json but represent html as a structured json object
```
"body": [
"You'll need to know:",
{
"ol": [
{
"li": [
"<strong>If you're considered 'married'</strong>",
"Many long-term partnerships resemble marriage, but for tax purposes, there are guidelines for what is and isn't considered married."
]
},
{
"li": [
"<strong>If you and your spouse want to file a return together</strong>",
"People who are married can file a tax return together (jointly) or file separate returns."
]
}
]
}
]
```
#### Pros
* React-18next supports json out of the box (however we do have to dynamically generate the DOM elements).
* It can be flexible and we can also limit what tags we accept as we dynamically generate the DOM elements.
* Can easily programmatically be broken up into meaningful snippets for translators.
* Limited tags in the strings themselves, so less error-prone.
#### Cons
* Content is hard to read and write because of heavy nesting.
* This is challenging as an engineer, will be very challenging for a non-dev to edit with errors.
### Use markdown and convert to json
#### Pros
* Translators showed enthusiasm for this option.
* Can easily programmatically be broken up into meaningful snippets for translators.
* Limited tags in the strings themselves, so less error-prone.
* Content is easier to write for non-devs.
* Looks readable too.
#### Cons
* Not supported by react-i18next out of the box.
* We will need an extra step to get the markdown into a format for ingestion by react-i18next.
* Markdown is less strict than html and it's possible the markdown->html generates a larger variety of generated html than we intend to support.
* We need to convert the whole en.json into markdown.
* Opportunity for errors still exists when writing markdown correctly.
### Use yaml and represent html as a structured object
```
body:
- "You'll need to know:"
- ol:
- li:
- "<strong>If you're considered 'married'</strong>"
- "Many long-term partnerships resemble marriage, but for tax purposes, there are
guidelines for what is and isn't considered married."
- li:
- "<strong>If you and your spouse want to file a return together</strong>"
- "People who are married can file a tax return together (jointly) or file separate
returns."
```
#### Pros
* It can be flexible and we can also limit what tags we accept as we dynamically generate the DOM elements.
* Can easily programmatically be broken up into meaningful snippets for translators.
* Limited tags in the strings themselves, so less error-prone.
* Much more readable and editable in it's raw format for both content teams and engineers.
#### Cons
* We need to convert the whole en.json into yaml
* React-18next doesn't support yaml out of the box (however yaml->json is a well defined conversion).
* Opportunity for errors when writing the structure and getting the format and indent correct.

View file

@ -0,0 +1,36 @@
# Data Import Redux
Date: 5 Nov 2024
## Context
To facilitate the correctness of the frontend data import system, we will use redux to coalesce data from APIs.
Data Import has many lifetimes that are independent of traditional timeframes from the app. Data fetches get kicked off, data returns later, data gets validated as ready for import all independently of user action.
Front end screen logic is much simpler to write as a function of state rather than having to manage separate lifetimes in multiple places such as context, component state etc.
## Decision
Data Import will use the Redux Library to make it easier for us to manage changing state related to incoming data from the backend.
We will write logic in redux to transform data as it comes in so that the frontend knows when to use it.
# Alternatives Considered
## React Context and Fact Graph
- Lack of chained actions - because we expect data from different sections (about you, IP PIN, w2) to come in at different times, we need to be able to chain /retry fetches and coalsce them into one structure. Redux makes this much easier than alternatives considered.
- Limits blast radius - with data coming in and out while people are on other screens, redux provides much better APIs to avoid rerenders on API calls that are not relevant to the current screen.
# Other Libraries
I looked briefly at Recoil, MobX, Zustand and Jotai but they all seemed geared at simpler apps. Some of Data Import's initial features (e.g. knowing if more than a second has elapsed during a request) are much easier to impliment in redux based on my prototyping. Secondly, Redux is so well used that nobody ever got fired for using redux :P
# Future Uses
Redux has a few key advantages over things we have in our codebase right now:
- Automatically manages the render cycle more efficiently (important as our react tree grows ever larger)
- Proven at scale with complex application state
- Well known in the industry with a good tooling eco system
That being said, there are no current goals to rewrite anything in Redux. Rewriting core components of our application would take a lot more prototyping and exploration than is being done as part of this process.

View file

@ -0,0 +1,154 @@
# Data Import System Structure
Date: 7/3/2024
## Acronyms
- DF: Direct File
- DI: Data Import
- ETL: Extract, Transform, Load
- IR: Information Return
- TIN: Taxpayer Identification Number
## Context
To facilitate the correctness of the return and speed of data entry, Direct File (DF) should present the user with information that the IRS has about them that would be relevant to their return. This could include information returns (1098s, 1099s, W2s, etc), biographical information, and anything else that would help the user accurately file their return. To gather this information the DF application set needs one or more applications making up a Data Import (DI) system that is responsible for gathering the information, either on demand or prefetched, and providing it out to other systems upon request.
This ADR is an argument for a specific application layout for the DI system. It doesn't specify the interface between the application, any app and the Backend App, nor does it specify which IRS systems should be included in DI or an order of precedence for those systems. Any system names used are for example purposes and shouldn't be taken as a directive. The DI system accesses information considered controlled by the IRS which is stored either in AWS or on prem servers.
## Decision
The DI system should be a single app that checks IRS systems on request for the first year. In the second year, when we have a larger population of users it might be useful to precache the imports for known users and store them for when the user returns. It is also doubtful that we could get an encrypted storage mechanism for such sensitive data approved in time for launch. This question of precaching should be revisited next year.
### Application Structure
#### Input
The input to the system should be a queue that accepts messages from the backend, provided on return creation. The message should contain the TIN of the user and any other information required by the IRS internal interfacing systems (modules to the DI system). This message should be given some mechanism to be correlated back to a tax return, like the ID of the return for example. It should also have the Tax Year as part of the message so that we only gather information relevant to this year. There will be a lot more than this year's data in some of these systems. We may also need that to support late returns in the future.
##### Simple Example Message (assuming use of message versions in DF)
```
{
Tin: 123456789
OtherInformation: kjsjdfjsdf // don't add that... this is a place holder because we don't know.
TaxYear: 2024
ReturnId: 2423bf16-abbf-4b4a-810a-d039cd27c3a0
}
```
#### Layout
We don't know the eventual number of systems we will have to integrate with, and the system should be set up with growth in mind. The base structure is a spoke-hub, with the hub being a spooler of information and the spokes being specific interfaces to internal IRS systems. When an input message comes in the hub provides all of its spokes with a query information unit that every spoke will need to perform its lookups, likely this will start as only a tin and tax year, but it may expand later.
##### Example QueryInformation
```
{
Tin: 123456789
TaxYear: 2024
}
```
Each spoke will be given an interface type and will be added to the available DI systems via configuration. On application start we will read in the configuration and only instantiate DI modules (the spokes) that are requested.
##### Example DataImportModuleInterface
```
public interface DataImportModule {
UserData Query(QueryInformation information);
}
```
For the first year, all of the calls in the modules should be subject to a timeout of 5 (configurable) seconds. This is because we don't know how long some of these calls will take (in cases where they don't have information and generally), and we don't want to stall the user waiting for data. We shouldn't cancel the call itself, but should rather send back what we have from the spooler, with the idea that we can send an update when we get it back. This implies that the timeout is in the spooler, and the spooler keeps a record of previous calls for some length of time before disposing of them. For the first pass most of the DI modules will perform rest calls to external systems. When they receive information back from their system they should ETL and categorize that information into some basic concepts, rather than leaking where the data came from (n.b. it might one day matter where the data came from, but we won't worry about it for this year). The below example is what the object may look like.
#### Example UserData
```
public class UserData {
UUID TaxReturnId { get; set; }
// this could be useful for negotiating conflicts if a precedence can be established.
// DataImport for the Hub, otherwise the name of the system the data came from (totally optional)
String SystemId { get; set; }
// 1 for DI modules, aggregated for the Spooler (hub). If this equals
// the number of configured systems we are done and should send.
int SystemDataCount {get; set; }
// biographical information includes name information, dependents, spouse data
// anything relating to a human
Biographical BiographicalInfo { get; set; }
// PreviousReturnData includes information about last year's return
// this information will be very valuable, but some things will not match
// this year. It is helpful to have these separated out.
PreviousReturnData PreviousReturn { get; set; }
// Information returns contains collections of the various types of IRs
// that we support. These are general categories like 1099 and W2, not like
// the types themselves. These supported types should be configurable.
InformationReturns InformationReturns { get; set; }
// All non-supported IRs should go in here.
// We should assume that if anything makes it into here that
// Direct File isn't the correct choice for the user and they should
// be informed of that fact. This could be things like K1s or advanced
// cases that we don't support.
// These could just be the names of the forms themselves (like we don't
// have to map the form itself)
OtherTypes OtherInformationReturns { get; set; }
}
```
The above example implies several things:
1) This makes a pretty reasonable interface to the Backend app. It contains all of the information required and is in a pretty usable form.
1) There are cases we don't support, and we have to reflect that. It will be nice for the user to be kicked out before they waste a bunch of time.
1) Each of these classes will need a method to merge information together or be collections. It makes the most sense to do a best guess merge for conflicting information. There are a few reasons for this, namely that we are offering information that needs to be validated by the user and displaying multiple sets of information to a user will be very difficult/confusing.
1) Last year's return is categorically different than IR information pertaining to this year
1) We will have to merge together multiple UserData to get to a single UserData that will be passed to the backend
With the DI modules generally covered (they have an interface, they make a rest call, they can be configured, they all send back a version of the same object), the focus now turns to the hub, which is just going to spool this data and reply back on a queue. When the spooler (the hub) receives a request it will kick off all the configured DI modules and start a timeout timer. It will store in memory the TaxReturnId associated with the UserData that will be used to store that user's data. As the calls come back (assuming they are done async here) they will have the TaxReturnId property that will allow them to be correlated with the correct UserData. A call will be made to the mainUserData.merge(UserData data) that will merge current and new UserDatas together (follow general rules of encapsulation). If the timeout timer goes off the spooler will enqueue a message on an SQS queue returning the current state of data to the backend, but it will not remove the key value pair from the in memory collection unless all of the systems have returned. If all of the systems have returned (described in the above example) then enqueue the message. The user data should either be put to a distributed cache and linked in the enqueued message, or just put in the enqueued message depending on how big these UserData objects become.
##### After timeout:
We may have valuable information come in after the configured timeout. We don't want to lose that data, and as such we shouldn't remove a user's data from memory until all systems have returned. We should enqueue a message each time we receive new UserData after the timeout. The UserData class should contain its own merge logic and should be made available to all projects (meaning it should be in our library). The backend can decide what to do with these updates.
#### Summary
DI Modules are interfaced pieces that talk to external systems. They store their information in UserData objects that can be merged together. DI Modules are configured to be running or not. The Spooler is the thing that receives messages and kicks off DI Modules. It also tracks all of its current TaxReturnIds and the data returned from the DI Modules. When the timeout timer goes off or all DI Modules return the Spooler will enqueue a completed message. If more data comes in after the timeout, more messages will be enqueued.
n.b. This pattern could be used in either a precaching or on demand system.
## Rationale
There are a few ways one could solve this problem. For example, each DI Module could be its own microservice. This would be more in line with a general microservice architecture. We would still require some spooling agent to take all their information and be responsible for merging it. The main reason we don't follow this pattern is that we get very little benefit for the trouble. We would have more waiting, more messaging overhead, and more potential for lost data without any commensurate gain. If the number of these systems grows beyond a certain level it may become valuable to reconsider this position (or if the complexity of the system grows beyond this basic concept). The simplest and fastest (at this scale) approach is to create one small application that handles all of these, and runs its own child jobs in the form of the DI modules. We will know if something fails, when and why, and be able to perform retries if necessary without having to do a bunch of messaging stuff to get it to work. This also simplifies deployment down to a single app. It uses way less (AWS) resources this way.
## Rejected Concepts
#### Microservice
In general, applications should do one thing and the boundary of an application should not be expanded beyond this purview. We have here a well defined application boundary: a system that acts as an interface between the backend api (or any listener) and internal IRS systems for the purposes of gathering relevant user data. We could further split this into a set of applications that gather information and an application that performs the spooling. When each DI system finishes it would raise an event, and the spooler app would gather the data from the distributed cache, merge it, and write it back. Philosophically this works, but it adds a lot of failure points for very little gain at our current scale and set up. In the future this may be a very useful thing to do. We could for example house these applications near their supporting app (like an TKTK DI service that sits near the TKTK service in the on prem world and fetches) which would increase our speed and could get us faster information about those systems if we can integrate deeper with them.
##### Failures in the Microservice system
The main failure point is the problem of messaging. All messaging across a network is subject to failures. The more messages we have to send the more chances for these failures to occur. We should get some benefit for the failure, like higher scale or ease of development and onboarding but with only 5 or so of these systems and with such a simple pattern we aren't going to gain anything. Our throughput will not likely come from our own applications but rather the applications we rely on.
We are also relying on our distributed cache to stay up throughout the operation. We can handle the timeout on the requesting (backend api) app, and we can continue to count how many returns we have. What would happen if our distributed cache failed though? How would we know what we lost, if we lost anything? No individual pod would (or could really without introducing a P2P communication mesh, rumor/whispers protocol, or something really out of pocket with the queues) be managing the job in the microservice system and so if there were failures they would be harder to track and propagate. We don't yet know all of the failure cases, so it will be good to have these operations tightly managed by the spooler in the first year.
#### Backend API does it
The backend API is already responsible for a lot. This is also an asynchronous process that may take a bit of time. The complexity of the backend API is already hard enough to track, we should avoid adding discrete systems to it if for no other reason than so we can continue to reason about it. It is 2 less potential failure points than the above suggestion, but it comes with a substantial reduction in backend api complexity, memory use, and the ability to eventually turn this into a precaching system if we desire (which would be awkward if we were standing up backend api apps for that).
#### Linear Flow/Non-Spoke-Hub System
This system has about 5 very similar operations that easily slot into a spoke-hub system. Why fight against the obvious pattern? If this was done linearly it might be supportable for the first year, but it would be messy. It would also be much slower as each operation would have to be done in sequence. That would give you an automatic precedence order, which is a nice feature. This system design would not allow for growth in the future, good code reuse, or general supportability
## Assumptions
- Messaging systems occasionally lose messages: this is true, and it is underpinning at least some of the claims above.
- Having the per tax return system checks centrally managed is desired: My belief here is that we don't know all of the error cases and it will be easier for us to see them in a single application and create tests that exercise these failure conditions. There is a world in which that isn't necessary, but I think it has some solid side effects.
- Standing up more pods is annoying and not worth it: we have already updated our CDRP and docs with a single service doing this. We probably could update them but I don't see the benefit yet. I would like to hear a solid reason why breaking this into multiple applications is worthwhile.
- Merging is a wise idea: there is a world in which we just want to dump everything we know rather than doing a best guess merge. My view is that inundating the backend (and maybe the client/user) with this information isn't a useful thing to do. We want the user to check this information anyways. We aren't making any promises about the correctness!
- The bottleneck we will face is the other systems and not our system: If the other system is the bottle neck then it doesn't make sense to stand up a bunch of end point hitting services that just return data from that service. If that isn't true, if we are the problem, then it makes sense to have as many services to hit that end point as we can make use of. It could be as many as (made up number ahead) 50:1 DI services to spoolers in that case. It is reasonable to assume that the other systems will be the problem in this flow because where would our bottleneck come from? We will stand as many of our services up as needed but the ratio of end point hitters to spoolers will always remain constant (1:1 per type of DI service and spooler).
## Constraints
- This is for our current scale and complexity. These trade-offs are different at higher scales.
- This is for an assumed <20 system integrations
## Status
Pending
## Consequences
- We may hit a point where, like let's say 25 services where this pattern becomes cumbersome. It doesn't make sense to have so many calls on one system. The number of integrated systems decreases the total available load per system by some percentage. At some level we will want to split out the DI modules into microservices, but we shouldn't do that until it makes sense.

47
docs/adr/devx-goals.md Normal file
View file

@ -0,0 +1,47 @@
# Top line DevX goals
*Note: these are topline goals -- they may be contradictory and specific situations may involve trading off against these separate goals*
1. Creating a working, running set up of all services should be one command, `docker compose build`.
1. Running each service locally should be one command, `./mvnw spring-boot:run -Dspring-boot.run.profiles=development`
1. Running tests on each service should be one command, `./mvnw test`
1. Basic IDE settings for intellij and VS Code are checked into the repository, and opening a service or the full `direct-file` repository in these IDEs should "just work". Tests should run in the IDE, local debuggers should work, and there should be no red squigglies or unresolved problems in the IDE.
1. Formatters and linters (e.g. spotless and spotbugs) should standardize formatting, prevent unused variables, enforce styling, and otherwise keep the codebase clean and consistent. CI should check this formatting and linting.
1. Code standards are kept via CI tests and robots, not human code reviews.
1. We should have a build time of 5 minutes or less for our CI checks.
1. Environment variables and scripts that require setup outside of our build scripts should be minimal. When environment variables or scripts are required, and are not set, a service should fail immediately and loudly with a helpful error message.
1. Making a simple change should be simple and take a short amount of time (e.g. updating a fact graph -> MeF mapping should be 1 line of change)
1. Similarly, writing a simple test should be simple, and modifying our tests (unit or snpashot) should eb clear and easy.
1. Error messages that indicate a problem in environment setup should be clear and simple.
1. Error and warn logs should always point to a real and solveable problem.
1. We should not have manual code changes that are derivative of other code (e.g. updating `aliases.ts` for aliased facts).
1. Any script that is a part of a common dev workflow should be checked + run in CI.
## First 3 goals
We're doing great on the first 3 DevX goals!
## Basic IDE settings
1. We should check in recommended VS Code settings + plugins for Java Development.
1. We should (?) have recommmended settings for Intellij checked in.
1. We should fix the bad imports on jaxb sources for the IRS MeF SDK.
1. We should finish setting up spotbugs across projects, and resolving our existing spotbugs errors.
1. We should standardize our linting + formatting tools, and make them run in CI to prevent unresolved problems.
## Environment variables
1. We should have a louder error + immediate failure for not having `LOCAL_WRAPPING_KEY` set when someone runs a
2. Submit and status apps should fail to start without the appropriate environment variables set, along with a message about what variables are required.
## Simple changes should be simple
(Alex lacks the most content here, and would love people to add more)
1. We should stop checking in generated code for the frontend fact dictionary, and move that to a build step when someone starts, builds, or tests the frontend, since backend devs should not need to run `npm run build` when they modify facts.
1. We should stop checking in generated MeF code for the backend Mef packing transform, and move that to a build step that runs prior to the backend's `./mvnw compile` command. That command should run consistently.
1. We should remove all checked in intermediate formats and only have checked in writable fact graphs, and checked in XML snapshots.
## Simple tests should be simple
We're doing a lot better here than we used to! Snapshot tests now run in CI and regenerate automagically, instead of being an ETE test.
## Error messages + logging
1. We should look through our existing logs and check for unnecessary warn/error messages that are noisy, and remove those noisy logs (e.g. the address facts that currently spam every packing).
## Removing duplicative manual code changes
1. We should fix `aliases.ts` to not require changes any time someone creates a `Filter` or `IndexOf` fact.

View file

@ -0,0 +1,35 @@
# Bandwidth Constraints
Our users are going to come from all over the country, with a variety of access to broadband internet. We want to make sure that we're supporting the vast majority of users. To specify that further, we're looking to device and bandwidth data, and deciding the following constraints:
## Bandwidth Constraints
Source for bandwidth data is the [FCC 2021 Bandwidth Progress Report](https://docs.fcc.gov/public/attachments/FCC-21-18A1.pdf), which reports bandwidth levels through 2019.
As of 2019, 99.9% of people in the US have access to either:
1. Mobile 4G LTE
with a Minimum Advertised Speed of 5/1 Mbps OR
2. Fixed Terrestrial 25/3 Mbps
including 99.7% of people in in rural areas and 97.9% of people on Tribal lands (fig 3c).
Given this, we can support 99.9% of our population by supporting users with **5Mbps down/ 1Mbps up**.
## Latency Constraints
The FCC does not include latency in its Bandwidth Progress Report (III.A.17), so we're left to other less official sources. However, we can set our bar at "what is the latency of 4G LTE, given that it's going to be the worst case latency for the 99.9% of people who have 4G LTE or Terrestrial 25/3 Mbps"?
In this case, latency refers to the time it takes for your phone to get a response from the cell tower at the other side of its radio link. It doesn't include time from that radio link to our cloud data center, or any processing we'd do there, or the response time. But this is the measure that would put 4G on the same page as a terrestrial link.
Average 4g latency is around and lower than 50ms<sup>[1](https://www.statista.com/statistics/818205/4g-and-3g-network-latency-in-the-united-states-2017-by-provider/),[2](https://www.lightreading.com/mobile/4g-lte/lte-a-latent-problem/d/d-id/690536)</sup> while maximum latencies I can find on the internet seem to be around 100ms (though this seems hard to find information on!)<sup>[3](https://www.researchgate.net/figure/Maximum-and-average-latency-in-4G-and-3G-networks-6_fig3_338598740)</sup>
Given this, we should set our **latency target at 100ms** to support the worst case of the 99.9% of people in the US whose worst connection choice is 4G LTE.
### Dev suggestion
To assume the case of our worst case users, you can create a [network throttling profile](https://developer.chrome.com/docs/devtools/settings/throttling/) in Chrome devtools. You can use the app with that profile enabled to see the loading screens and timing experience that we're expecting of our worst case users.
#### Appendix
In 2023, apparently you can take zoom calls from the side of the mountain. And in 2024, maybe TKTK will file his taxes from there, too.
<img width="695" alt="On a mountain" src="https://github-production-user-asset-6210df.s3.amazonaws.com/135663320/251536414-ce525b7c-e795-49cd-ab33-6950a54d5ec4.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAVCODYLSA53PQK4ZA%2F20250416%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20250416T225041Z&X-Amz-Expires=300&X-Amz-Signature=be26cddd37bb08083453688fa707babf3f8ea027eb3d66e0a672b4f4724e4e62&X-Amz-SignedHeaders=host">

View file

@ -0,0 +1,33 @@
Created At: 2, Aug, 2024
RFC: Introducing Javascript/Typescript to DF Backends
# Problem Statement
Currently, all of our backend code is written in Java [^1]. We have a couple use cases where this might not be ideal:
1) One off production remediation code during filing season
2) Logic that is shared between the frontend and the background
[^1] Two exceptions worth noting - (1) we have simulators for development which are in python and (2) our fact graph is written in scala and runs on the JVM.
# Background
## Languages and Toolchains
We want to minimize the number of languages and toolchains in direct file. This has the following benefits:
- Less engineering time spent on configuring linting/ci/testing infrastrcuture
- Easier for an individual engineer to ramp up on the end to end of a product scenario
- Eliminates the need for handoffs between language boundaries
## Shared Frontend <> Backend Logic
Today we have our factgraph logic shared between the frontend and backend. We achieve this by transpiling scala into javascript. Many projects eventually want to share logic between frontends and backends and javascript is the lowest overhead approach to do this. Although we're not sure how the factgraph will evolve over time, one possibility is running in serverside via a javascript lambda.
## One-off Remediations
In production during filing season, we often want to run code in a production environment to fix issues. We do this using lambdas triggered s3 file notifications in production. These can often be written faster in a dynamic language like javascript/python/ruby. Going into filing season 2025 we would like to have the capability to run these type of remediation lambdas on a dynamic language.
# Decisions
Enable lambdas running the most recently available node lts in direct-file, start experimenting with appropriate usage.

File diff suppressed because it is too large Load diff

After

Width:  |  Height:  |  Size: 584 KiB

View file

@ -0,0 +1,179 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 8.1.0 (20230707.0739)
-->
<!-- Pages: 1 -->
<svg width="1605pt" height="575pt"
viewBox="0.00 0.00 1604.75 575.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 571)">
<polygon fill="white" stroke="none" points="-4,4 -4,-571 1600.75,-571 1600.75,4 -4,4"/>
<!-- filers -->
<g id="node1" class="node">
<title>filers</title>
<ellipse fill="none" stroke="black" cx="534" cy="-549" rx="29.86" ry="18"/>
<text text-anchor="middle" x="534" y="-543.95" font-family="Times,serif" font-size="14.00">filers</text>
</g>
<!-- deductions -->
<g id="node2" class="node">
<title>deductions</title>
<ellipse fill="none" stroke="black" cx="359" cy="-195" rx="50.84" ry="18"/>
<text text-anchor="middle" x="359" y="-189.95" font-family="Times,serif" font-size="14.00">deductions</text>
</g>
<!-- filers&#45;&gt;deductions -->
<g id="edge1" class="edge">
<title>filers&#45;&gt;deductions</title>
<path fill="none" stroke="black" d="M504.15,-546.35C391.69,-539.73 0,-512.98 0,-461.5 0,-461.5 0,-461.5 0,-282.5 0,-222.04 194.9,-203.71 297.49,-198.26"/>
<polygon fill="black" stroke="black" points="297.51,-201.71 307.33,-197.71 297.16,-194.72 297.51,-201.71"/>
<text text-anchor="middle" x="144.75" y="-366.95" font-family="Times,serif" font-size="14.00">/dependentStatusBansFilerFromClaimingDependents</text>
</g>
<!-- filers&#45;&gt;deductions -->
<g id="edge2" class="edge">
<title>filers&#45;&gt;deductions</title>
<path fill="none" stroke="black" d="M503.76,-548.59C446.07,-547.98 326,-537.57 326,-461.5 326,-461.5 326,-461.5 326,-282.5 326,-261.34 334.73,-239.06 343.21,-222.41"/>
<polygon fill="black" stroke="black" points="346.71,-224.3 348.38,-213.84 340.55,-220.98 346.71,-224.3"/>
<text text-anchor="middle" x="464.38" y="-366.95" font-family="Times,serif" font-size="14.00">/secondaryFilerAdditionalStandardDeductionItems</text>
</g>
<!-- dependents -->
<g id="node3" class="node">
<title>dependents</title>
<ellipse fill="none" stroke="black" cx="968" cy="-460.5" rx="52.38" ry="18"/>
<text text-anchor="middle" x="968" y="-455.45" font-family="Times,serif" font-size="14.00">dependents</text>
</g>
<!-- filers&#45;&gt;dependents -->
<g id="edge3" class="edge">
<title>filers&#45;&gt;dependents</title>
<path fill="none" stroke="black" d="M563.8,-545.71C613.28,-541.54 715.34,-531.41 800,-513 842.1,-503.85 888.87,-489.12 922.35,-477.75"/>
<polygon fill="black" stroke="black" points="923.41,-480.75 931.73,-474.19 921.14,-474.13 923.41,-480.75"/>
<text text-anchor="middle" x="936.88" y="-499.7" font-family="Times,serif" font-size="14.00">/filersCouldntBeDependents</text>
</g>
<!-- filingStatus -->
<g id="node4" class="node">
<title>filingStatus</title>
<ellipse fill="none" stroke="black" cx="706" cy="-372" rx="53.4" ry="18"/>
<text text-anchor="middle" x="706" y="-366.95" font-family="Times,serif" font-size="14.00">filingStatus</text>
</g>
<!-- filers&#45;&gt;filingStatus -->
<g id="edge4" class="edge">
<title>filers&#45;&gt;filingStatus</title>
<path fill="none" stroke="black" d="M506.78,-541.28C454.45,-527.07 348.21,-491.26 386,-442.5 423.68,-393.89 459.97,-421.36 520,-408 562.91,-398.45 611.77,-389.32 648.65,-382.78"/>
<polygon fill="black" stroke="black" points="648.96,-386.11 658.2,-380.93 647.74,-379.21 648.96,-386.11"/>
<text text-anchor="middle" x="449" y="-455.45" font-family="Times,serif" font-size="14.00">/eligibleForJointReturn</text>
</g>
<!-- filers&#45;&gt;filingStatus -->
<g id="edge5" class="edge">
<title>filers&#45;&gt;filingStatus</title>
<path fill="none" stroke="black" d="M531.49,-530.76C529.17,-508.16 528.58,-468.35 548,-442.5 571.97,-410.58 613.78,-393.06 648.37,-383.6"/>
<polygon fill="black" stroke="black" points="649.03,-386.79 657.85,-380.91 647.29,-380 649.03,-386.79"/>
<text text-anchor="middle" x="609.5" y="-455.45" font-family="Times,serif" font-size="14.00">/isWidowedInTaxYear</text>
</g>
<!-- filers&#45;&gt;filingStatus -->
<g id="edge6" class="edge">
<title>filers&#45;&gt;filingStatus</title>
<path fill="none" stroke="black" d="M561.07,-541.05C591.9,-531.78 641.77,-512.45 671,-478.5 689.85,-456.61 698.62,-424.24 702.66,-401.14"/>
<polygon fill="black" stroke="black" points="706.26,-401.73 704.32,-391.32 699.34,-400.67 706.26,-401.73"/>
<text text-anchor="middle" x="719.5" y="-455.45" font-family="Times,serif" font-size="14.00">/isMarried</text>
</g>
<!-- filers&#45;&gt;filingStatus -->
<g id="edge7" class="edge">
<title>filers&#45;&gt;filingStatus</title>
<path fill="none" stroke="black" d="M563.99,-548.77C613,-548.18 709.09,-538.89 752,-478.5 761.27,-465.46 758.51,-457.12 752,-442.5 747.13,-431.58 739.26,-434 732,-424.5 726.35,-417.12 721.38,-408.32 717.34,-400.1"/>
<polygon fill="black" stroke="black" points="720.12,-398.76 712.74,-391.15 713.76,-401.7 720.12,-398.76"/>
<text text-anchor="middle" x="805.75" y="-455.45" font-family="Times,serif" font-size="14.00">/eligibleForSingle</text>
</g>
<!-- credits -->
<g id="node5" class="node">
<title>credits</title>
<ellipse fill="none" stroke="black" cx="1048" cy="-106.5" rx="35.49" ry="18"/>
<text text-anchor="middle" x="1048" y="-101.45" font-family="Times,serif" font-size="14.00">credits</text>
</g>
<!-- deductions&#45;&gt;credits -->
<g id="edge15" class="edge">
<title>deductions&#45;&gt;credits</title>
<path fill="none" stroke="black" d="M406.36,-188.05C533.11,-172.14 878.89,-128.73 1002.95,-113.16"/>
<polygon fill="black" stroke="black" points="1003.08,-116.54 1012.56,-111.82 1002.2,-109.6 1003.08,-116.54"/>
<text text-anchor="middle" x="775.12" y="-145.7" font-family="Times,serif" font-size="14.00">/agi</text>
</g>
<!-- dependents&#45;&gt;filingStatus -->
<g id="edge8" class="edge">
<title>dependents&#45;&gt;filingStatus</title>
<path fill="none" stroke="black" d="M925.36,-449.79C913.31,-447.23 900.17,-444.59 888,-442.5 827.8,-432.14 805.7,-453.13 751.75,-424.5 740.26,-418.4 730.28,-408.2 722.6,-398.47"/>
<polygon fill="black" stroke="black" points="724.96,-396.78 716.21,-390.81 719.33,-400.93 724.96,-396.78"/>
<text text-anchor="middle" x="848.12" y="-411.2" font-family="Times,serif" font-size="14.00">/dependents/*/hohQualifyingPerson</text>
</g>
<!-- dependents&#45;&gt;filingStatus -->
<g id="edge9" class="edge">
<title>dependents&#45;&gt;filingStatus</title>
<path fill="none" stroke="black" d="M965.19,-442.47C962.36,-430.93 956.79,-416.3 946,-408 919.2,-387.38 831.57,-378.85 769.98,-375.37"/>
<polygon fill="black" stroke="black" points="770.35,-371.83 760.18,-374.79 769.98,-378.82 770.35,-371.83"/>
<text text-anchor="middle" x="1053.62" y="-411.2" font-family="Times,serif" font-size="14.00">/dependents/*/qssQualifyingPerson</text>
</g>
<!-- dependents&#45;&gt;credits -->
<g id="edge12" class="edge">
<title>dependents&#45;&gt;credits</title>
<path fill="none" stroke="black" d="M1018.44,-455.36C1065.97,-450.53 1132.82,-441 1153,-424.5 1172.14,-408.86 1174,-397.72 1174,-373 1174,-373 1174,-373 1174,-194 1174,-171.9 1120.63,-141.92 1083.36,-123.69"/>
<polygon fill="black" stroke="black" points="1085.33,-120.27 1074.8,-119.1 1082.3,-126.58 1085.33,-120.27"/>
<text text-anchor="middle" x="1270.75" y="-278.45" font-family="Times,serif" font-size="14.00">/dependents/*/eitcQualifyingPerson</text>
</g>
<!-- dependents&#45;&gt;credits -->
<g id="edge13" class="edge">
<title>dependents&#45;&gt;credits</title>
<path fill="none" stroke="black" d="M1020.59,-459.97C1136.55,-459.6 1404,-450.36 1404,-373 1404,-373 1404,-373 1404,-194 1404,-123.18 1160.85,-144.79 1093,-124.5 1090.41,-123.73 1087.75,-122.87 1085.09,-121.98"/>
<polygon fill="black" stroke="black" points="1086.51,-118.41 1075.92,-118.38 1084.17,-125.01 1086.51,-118.41"/>
<text text-anchor="middle" x="1500.38" y="-278.45" font-family="Times,serif" font-size="14.00">/dependents/*/isClaimedDependent</text>
</g>
<!-- filingStatus&#45;&gt;credits -->
<g id="edge10" class="edge">
<title>filingStatus&#45;&gt;credits</title>
<path fill="none" stroke="black" d="M726.62,-355.11C785.38,-309.84 953.7,-180.16 1020.34,-128.81"/>
<polygon fill="black" stroke="black" points="1022.27,-130.97 1028.05,-122.1 1017.99,-125.43 1022.27,-130.97"/>
<text text-anchor="middle" x="917" y="-234.2" font-family="Times,serif" font-size="14.00">/filingStatus</text>
</g>
<!-- income -->
<g id="node6" class="node">
<title>income</title>
<ellipse fill="none" stroke="black" cx="496" cy="-283.5" rx="38.56" ry="18"/>
<text text-anchor="middle" x="496" y="-278.45" font-family="Times,serif" font-size="14.00">income</text>
</g>
<!-- filingStatus&#45;&gt;income -->
<g id="edge11" class="edge">
<title>filingStatus&#45;&gt;income</title>
<path fill="none" stroke="black" d="M673.19,-357.48C635.6,-342 574.08,-316.66 534.32,-300.28"/>
<polygon fill="black" stroke="black" points="535.79,-296.69 525.21,-296.12 533.13,-303.17 535.79,-296.69"/>
<text text-anchor="middle" x="670.75" y="-322.7" font-family="Times,serif" font-size="14.00">/isFilingStatusMFJ</text>
</g>
<!-- finalAmount -->
<g id="node7" class="node">
<title>finalAmount</title>
<ellipse fill="none" stroke="black" cx="1117" cy="-18" rx="58.52" ry="18"/>
<text text-anchor="middle" x="1117" y="-12.95" font-family="Times,serif" font-size="14.00">finalAmount</text>
</g>
<!-- credits&#45;&gt;finalAmount -->
<g id="edge16" class="edge">
<title>credits&#45;&gt;finalAmount</title>
<path fill="none" stroke="black" d="M1060.66,-89.63C1070.8,-76.91 1085.23,-58.82 1096.95,-44.14"/>
<polygon fill="black" stroke="black" points="1099.98,-46.95 1103.48,-36.95 1094.51,-42.58 1099.98,-46.95"/>
<text text-anchor="middle" x="1112.38" y="-57.2" font-family="Times,serif" font-size="14.00">/totalTax</text>
</g>
<!-- income&#45;&gt;deductions -->
<g id="edge14" class="edge">
<title>income&#45;&gt;deductions</title>
<path fill="none" stroke="black" d="M473.68,-268.41C451.63,-254.49 417.63,-233.02 392.36,-217.07"/>
<polygon fill="black" stroke="black" points="394.48,-213.63 384.15,-211.25 390.74,-219.55 394.48,-213.63"/>
<text text-anchor="middle" x="481" y="-234.2" font-family="Times,serif" font-size="14.00">/taxableIncome</text>
</g>
<!-- estimatedPayments -->
<g id="node8" class="node">
<title>estimatedPayments</title>
<ellipse fill="none" stroke="black" cx="1185" cy="-106.5" rx="83.08" ry="18"/>
<text text-anchor="middle" x="1185" y="-101.45" font-family="Times,serif" font-size="14.00">estimatedPayments</text>
</g>
<!-- estimatedPayments&#45;&gt;finalAmount -->
<g id="edge17" class="edge">
<title>estimatedPayments&#45;&gt;finalAmount</title>
<path fill="none" stroke="black" d="M1171.57,-88.41C1161.63,-75.77 1147.94,-58.36 1136.76,-44.13"/>
<polygon fill="black" stroke="black" points="1139.11,-42.46 1130.18,-36.76 1133.6,-46.78 1139.11,-42.46"/>
<text text-anchor="middle" x="1197.5" y="-57.2" font-family="Times,serif" font-size="14.00">/totalPayments</text>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 11 KiB

File diff suppressed because it is too large Load diff

After

Width:  |  Height:  |  Size: 126 KiB

View file

@ -0,0 +1,88 @@
# Tax Logic Testing Strategy
12/15/23
## Problem Statement
The goal of Tax Logic Testing is to test:
1. Do we show users the correct screens and collect the correct information from each user based on their previous answers? This document refers to this problem as _completeness_ for whether the user has completed the correct screens and input a complete set of data. (Flow + fact dictionary interactions)
1. Do we correctly compute filing status, dependency, deduction, and credit eligibility, as well as the final tax amount calculations? This document refers to this problem as _correctness_ for whether our derived facts have the appropriate calculations. (Fact dictionary interactions)
1. Are we resilient to review + edit conditions (telling a user to resume where they need to resume and using only valid data)? (Flow + fact dictionary interactions)
We want to make sure that we are testing each of these criteria, automatically, on every pull request. We have already built most test infrastructure that we need for this. For our next steps, as we move closer to the pilot, we need to define and increase our test coverage for each of these problems.
## Where this proposal falls into the overall test framework
These tests, and this document, cover a lot of tax logic, but these are three areas outside of our scope:
### Scenario tests
The testing team will perform "scenario testing," which is an integration test that applies scenarios and checks that the expected tax burden is correct. This test type is a black box test, where it only registers a `PASS` or `FAIL` (with expected and observed values). This test's goal is to run through as many scenarios as we can very quickly to identify regressions.
### Manual testing with subject matter experts
We're relying on the testing team to go through a greater level of scenario testing + manual testing and file bugs on us when they find issues. We should hopefully be able to identify where we were missing a test, write a failing test case, and then fix the issue. SMEs and tax policy experts doing manual testing is how we might plan to find issues in _our understanding_ of the tax code.
### Testing after a user submits their data
This testing goes from the user through to the fact graph. We are testing that we generate the correct derived facts. This testing does not include MeF integration -- the backend team is responsible for translating our fact graph representation into MeF XML (though we will gladly help with facts!)
## Methods
Based on the recent modularization of the fact dictionary, we've defined that ~140 of the ~800 facts are used in multiple sections of the app -- these facts, which we can call **culminating facts** are the ones that determine a tax test, eligibility, or computation, and they should be selected for additional test coverage. We base our test strategies around proving the completeness and the correctness of each culminating fact.
The vast majority of our bugs during development have happened from these culminating facts either having been incomplete (e.g. you went through the dependents section, but we still didn't know if that dependent qualified for Child Tax Credit), or incorrect (e.g. The taxpayer was born January 1, and we calculated their Standard Deduction wrong).
This graph shows the current state of 143 culminating facts connecting our 21 independent modules:
![Culminating Facts!](./supporting-files/culminating-facts.svg)
This is the graph that we must test. We have four generalized types of tests, each of which have their own purpose in our testing strategy. All tests run on pre-merge, prior to every commit and deploy of our codebase.
### 1. Testing for Completeness
Historically, this has caused our largest area of bugs, but we have recently made strides by being able to test that a section will always complete certain facts. For this, we use our `flowSetsFacts` tests. This tests a combination of both our flow and fact dictionary. Existing tests live in ../direct-file/df-client/df-client-app/src/test/completenessTests
These tests run via a simulator that follows all potential paths in the flow for each potentially consequential answer to a question. Given this, the tests are computationally expensive to run, but have a low margin for manual error compared to our other forms of testing. We additionally have more work to do until we can run this on the largest sections of the app (spouse and dependents)
#### Test Examples
* At the end of the spouse section, do we know whether the taxpayer (and a potential spouse) need to be treated as dependent taxpayers?
* At the end of a dependents collection item, do we know is a person qualifies as a dependent, or a qualifying person for each filing status + credit?
* At the end of the W2 section, do we know the employer wage income of a person, as well as whether they have combat pay?
#### Coverage
We need to begin measuring our coverage of each of the culminating facts. Every culminating fact should be known to be complete by the end of a section in the app.
### 2. Testing for Correctness
Each of our culminating facts should represent a concept in the tax code (e.g. a rule, or eligibility, or a computation), or an important fact on the way there. We write vitest facts that generate a fact graph, and test that our fact dictionary rules represent our understandings. Existing tests live in ../df-client/df-client-app/src/test/factDictionaryTests. This tests just the fact dictionary.
This requires a potentially high volume of tests to be written for each culminating fact, and also may require taking other culiminated facts as input. When a tax bug is reported, we should generally be able to write a fact dictionary test that would prevent the bug from occurring again.
#### Examples
* After a certain income amount, the student loan adjustment will begin to phase out.
* A taxpayer will receive an additional amount of standard deduction if they are over 65.
* A person is ineligible for Qualifying Surviving Spouse status is they were ineligible to file jointly the year of their spouse's death.
* A child without an ssn can qualify a taxpayer for EITC, but is not used in the computation.
#### Coverage
We need to measure how many of our culminating facts have unit test coverage.
### 3. Functional Flow Navigation
After each screen, we must use the current fact graph state to choose the screen the user will see next. The screens the user sees affects the data that is collected. To test that the user sees the right screen based on their answers, we have written functional flow tests. For each screen, we test a starting state, being on the screen, setting a fact, and testing what screen the app will move to next. Existing tests live in ../direct-file/df-client/df-client-app/src/test/functionalFlowTests.
Creating these tests can be prone to manual error since it requires a developer to reason about the potential next screens after any screen. Combined with our completeness tests above, this checks that the user has input the correct data. This test a combination of the fact dictionary and flow.
#### Examples
* A taxpayer who says they were a US Citizen all year will move to being asked about their state residency. If they were not a taxpayer all year, they will be asked if they were a taxpayer at the end of the year.
* A taxpayer who notes that they lived in a single, in-scope state will go on to next enter their TIN. A taxpayer who says they lived in multiple states will move to a knockout screen.
#### Coverage
We need to track what percentage of screens we have as a starting point in a functional flow test, and what percentage of screens we navigate to in a functional flow test.
### 4. Static Analysis
We use static analysis (mostly TypeScript type safety) to ensure that we are reading facts that exist and writing to facts that are well defined. Similarly, we use static analysis to ensure that derived facts are only using culminating facts from other sections, and never internal facts that haven't been meant for consumption.
We can build additional static analysis that may help us with our robustness to edits.
#### Test Examples (existing)
* The client reads `/isEligibleForEitc` -- that is a fact defined in the fact dictionary.
* We write a boolean value to `/livedWithTaxPayerAllYear` -- that is a boolean value in the fact dictionary
* EITC relies on a dependent having qualified as an EITC qualifying child in the dependents section. We check that "/isEitcQualifyingChild" is marked as exported from the dependents module.
* A fact is used by MeF. We check that that fact exists in the fact dictionary.
#### Coverage
Static analysis operates on the full codebase and does not have a coverage metric.

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,304 @@
# **Research Templates and Protocols**
## **Protocols and Strategies for Research Sessions**
### **Observers and Notetakers Protocols**
* As a general user research best practice, research participants shouldn't feel outnumbered by research staff. Having more people than just the moderator can affect the participant's behavior, rapport, and impact findings. This becomes more important when addressing sensitive topics.
* Taxes are a difficult, sensitive topic for most taxpayers, depending on the taxpayer's situation. The team prioritizes participant psychological comfort when including observers and notetakers in research sessions. We also prioritize including IRS Direct File team members in research sessions to increase empathy with taxpayers.
* For each research session, we recommend no more than 3 research staff members max (including the moderator) to ensure participant psychological safety while allowing exposure to users for DF team members.
* Reflect if the research study will include sensitive topics such as complex family situations (e.g., a hostile divorce resulting in disagreement in dependent custody that affects tax filing), low or no income, transiency, and more.
* Participants can decide if they want to allow observers and notetakers in their research session, or if they want to talk to the moderator only. This check can happen during recruitment screening and again as the research session starts. If the research topic is sensitive, consider whether notetakers and observers should be reduced in number or even just the moderator (with the aid of video recordings for post-session notetaking). Make sure this is made clear to participants during the recruitment process (screening survey and phone screening questions and recruitment comms).
* If recordings are possible and/or the moderator is confident to handle notetaking on their own, give participants the ability to choose whether they want to have observers/notetakers in the session during the recruitment process. Reiterate this option to them as the research session starts, in case they change their mind. This option will make participants the most comfortable and result in better rapport and findings, as it gives them the option to have a 1:1 with the moderator.
* If the topic is sensitive or Federal Tax Information is involved (like in end-to-end observation sessions), it may be better to not record. If in this case the moderator needs a notetaker, make sure the participant is aware of this in advance and that this is contemplated in the recruitment screener. A notetaker may also be required in studies when the moderator isn't sure recordings are going to work.
* To help make participants comfortable, ensure any notetakers and observers present are on-camera at the start and introduced by full name and organization. Being on camera is not required beyond this initial introduction.
* Consider making video recordings available to team members after the session if research staff attendance must be limited. Videos should only be made available to team members working directly on the topic of research study and only for the purpose of research analysis.
### **Guidelines for Observers and Notetakers**
* Please be on time and on camera when we start. The moderator will quickly introduce you by name and organization. Being introduced at the start helps make the participant more comfortable (talking with the IRS can be intimidating\!)
* Observation of research sessions may not be guaranteed. You may have to wait a few minutes in the web conferencing waiting room as the moderator checks with the participant if they will allow observers/notetakers. Talking about taxes is extremely personal and sensitive, this practice helps increase participant psychological safety. If you're not able to join a session, please ask the research lead for access to research session recordings and/or notes before the research study ends.
* If possible, please stick around for 15 minutes after the participant leaves the room so we can debrief the session.
* If you have any questions that you would like to ask during the session, please send them in a Slack group chat with the moderator and notetaker. The moderator will have the chat open during the session and will ask the question when there is a good opportunity to. Do not include ANY PII (personal identifying information) in this chat.
#### **Guidelines for Notetakers**
* Note what participants say and also what they don't say--things they complete successfully, things they misunderstand or do wrong, where they try to click if relevant.
* Try to capture what they said, close to verbatim — not your interpretation of what they meant. E.g., “Im not sure about this checkbox” does not equal “Doesnt understand checkbox”
* Protect participant's PII (personal identifying information): Do not capture any sensitive details or PII. It's ok to capture details like what state they live in but if they start to get really specific on some detail, its ok to only capture a generic version.
* “Im a waiter at the Copacabana on Miami Beach” \-- its ok to just write “waiter”.
* “I had a tricky tax situation because I had 29 dependents” \-- its ok to just say “I had a tricky tax situation because I had \[much higher than average\] dependents”
### **Research Moderation Protocols**
#### **We do dry-runs of the moderation guides before the real sessions**
Find a colleague who's not involved with the project to do a dry-run, even if they have to make up a situation. This will help ensure moderation feels natural and that the interview can be completed in time. Make time after the session to get their and a notetaker's feedback on the questions and the notetaking templates. Before each dry-run, make sure to warn the "participant" that the moderation guide is work-in-progress and some things can be messy, but their feedback is important to help shape the moderation guide.
#### **We do not provide tax advice to research participants**
Participants may have questions about their tax situation or seek clarification on some aspect of how taxes work. We should never give tax advice.
If we're observing someone actually filling out their taxes as part of user research, and notice they made an error, what we can say will depend.
* Typos: Not tax advice. That's just noticing an error. The numbers are what the numbers are. If you see something, say something.
* Inaccurate selection: Be cautious \-- we can't tell someone how to answer a question. But an "are you sure" or equivalent application of brakes would be fine. Possibly just reminding them there's a chat service if they have questions.
* Doing something that could result in a rejection like guessing their last year's AGI: Telling them that's not what the question asks and explaining what will happen if the number is wrong is a statement of fact, not tax advice.
When in doubt, don't say anything.
#### **We protect participant PII (personal identifying information)**
We follow these IRS mandated best practices for protecting participant PII.
* Participant screening data has to be in an encrypted file within the recruitment vendors secured network, limited to the project team working on the project NO cloud based tool when collecting screening data.
* Recruitment partners must remove participant names, contact info and other linkable PII before sharing participants to the IRS (they will only be identified by participant ID numbers).
* Any summary of aggregated and de-identified participant characteristics from the recruitment screener will use secure email with password protected attachments.
* Any documents that contain participant PII should be deleted upon study completion.
* All other anonymized documents with participant notes to be deleted within 1 year.
Additionally, it's Direct File best practice to:
* Make sure participants don't enter any of their own PII into the dev site during a session. We do this by using prototypes that can't be entered into, we share our screens so they can't enter any data, or we give them fake data to use during sessions.
* Make sure any notes we capture during a session don't include PII or other sensitive information. See guidelines for notetakers above.
#### **When the participant fails and gets frustrated during usability testing**
Sometimes participants can feel like they're failing something when they don't successfully complete a task. Even if the moderator gives advance warning of that happening in user research and framing it as a normal thing, there are a few things the moderator can say to calm participants down without guiding them towards a solution.
Make sure to frame and describe the activity before it starts so the participant knows you want from them
* “We're testing the website and not you, which means there's no right or wrong answers we're looking for \- we're interested in your general thoughts and feedback.”
* “As you're going through the prototype, please think aloud. You don't need to read from the screen, as that can take time, but I'd like you to say whatever comes into your mind. I'm interested in what's grabbing your attention on the screen, what questions you have, and your general thoughts as you review a page.”
* “If at any point you feel uncomfortable or confused, please let me know. We are testing the site and gathering feedback and testing not you or your tax knowledge. Were here to support and learn from you.”
* “If you have any questions as we go along, please feel free to ask me. I may not be able to answer them right away since were interested in how people would navigate this website without a helper around. But if you still have any questions when were done, Ill try to answer them then.”
* “And please feel free to be as honest as possible you will not hurt our feelings.”
* When a participant get frustrated, reassure them they're doing well. “If you stumble on this, then a lot of people will, so you just found something for us to fix.”
### **Research Session Debrief Protocols**
The research moderator may gather with the observers/notetakers and others who might be interested in joining a research session debrief. The following questions are recommended:
* How is everyone feeling? Does anyone need anything (moderator especially)?
* If this was a difficult session, process what made it difficult, what went well, what could've been better, what you can do moving forward, etc. Remember that sometimes sessions are difficult and there's not much you can do about it. Be kind to yourselves.
* Does the research moderation need any changes? (e.g., phrasing of questions to avoid leading, changing of content in screens)
* Is there any PII (personal identifying information) we need to delete? Anything sensitive the participant shared that we need to clean up from the notes? (must be done the within 24 hours of the research session)
* What were the participants' needs and goals?
* What were the pain points in the experience?
* What went well in the experience?
* What are ideas and areas of opportunity for this participant?
* Next steps?
## **Sharing Research Insights Templates and Best Practices**
| | As research sessions are ongoing | After research sessions have concluded |
| :---- | :---- | :---- |
| Actions | Share updates and in-progress, preliminary findings with your study team and stakeholders via Slack. You can also post in a team Slack channel for broader team visibility. | Hold an interactive synthesis workshop with designers and other members of your study team to collectively form initial findings and recommendations. If needed, hold a broader share-out of finalized insights and recommendations with the study team and additional stakeholders. |
| Goals | Keep the team abreast of tidbits and interesting facts during research Give team members who were not able to participate in sessions a chance to respond to notes and ask questions | Deliver actionable insights and recommendations to individuals who can effect change on the product Keep a record of research findings for future reference |
| Audience | Study team (designers, content, PMs, other relevant stakeholders) | Study team (designers, content, PMs, other relevant stakeholders) Broader team |
| Dos | Share quotes, things participants did | Surface key themes Identify potential additional research opportunities Highlight study limitations (e.g., biases, audiences missing, etc.) Add all recommendations to backlog for future |
| Don'ts | Turn these research nuggets into themes prematurely Allow these research nuggets to be interpreted as themes prematurely, before synthesis has been conducted | Frame qualitative research "representative"—no qualitative research can be representative of all taxpayers. However, we can aim for a diversity of experiences and backgrounds |
| Template | \[Title, research goals, context into study\] Sessions completed: x out of x One participant did/said \[something\] \[highlight pain points, positives, or questions the participant had, keep it brief\] "\[Quote, if there's a relevant one. We don't have transcripts but paraphrased notes can make up for it, as long as they are highlighted as paraphrased. Try to reduce paraphrasing to a minimum by reducing quotes to short sentences or even single words you know for sure were used by the participant. Make sure no PII is included in quotes\]" (paraphrased) \[2-5 bullets as needed. If no sessions today, highlight that, along with any prospect of future sessions:\] No sessions conducted today / X no-shows / Prepping for 3 interviews Thursday / Conducting synthesis today and tomorrow | Presentation Share-outs to audiences outside of the immediate study team may benefit from a presentation Sprint demo: At the end of every sprint, the research pod shares an update on our work in-progress as well as the top 3 insights from any studies completed during the sprint. Use the template above for sprint demo share-outs. Document all finalized insights and recommendations within the study's study brief page for documentation purposes. |
## **Moderation Guide Template: Usability Testing**
This is the template that the Direct File research team used to facilitate usability testing.
### **Intro**
\[allow participant in from the waiting room, keep observers/notetakers in the waiting room (you may allow a notetaker in at this point if the study plan required it). Ensure Slack and notifications are paused if preferred.\]
Good morning/afternoon. How are you today? Im \[moderator name\], a \[insert role\] from \[insert organization\].
\[if a notetaker is part of the plan\] I wanted to introduce you to \[name notetaker by their full name and what organization they are affiliated with and their role. Ask them to be camera on, wave, then turn camera off to make the participant comfortable\].
Im/we are part of a team that's building Direct File, a website for people to file taxes directly with the IRS.
Before we start, I want to let you know more about what you can expect during today's conversation:
**Time:** Itll take no longer than \[insert time\]. Ill be watching the time to make sure we dont go over.
**Session:**
- I'll start with a few questions to learn a bit more about your past experiences filing taxes. Then I'll have you try out a prototype of the website we've been working on. \[describe specific topics that will be covered, including any sensitive areas or lines of questioning.\]
- We're testing the website and not you, which means there's no right or wrong answers we're looking for \- we're interested in your general thoughts and feedback.
- Taxes are hard \[if covering other sensitive topics, name those as well, e.g. “talking about shared custody can be difficult and bring up a lot of feelings”\]. If some topics become difficult to talk about please let me know, I'm here to support you. You can let me know if you need to take a break or stop at any point. If there are any questions you dont want to answer just let me know and Ill move on.
- Unfortunately, we're not tax experts and we can't give you tax advice. I also don't have access to your tax information.
**Privacy:**
- We'll only use what we learn from you to help improve Direct File.
- Everything you say will be anonymous and be kept strictly private. We are taking notes — but those wont include your name or any other personal identifying information. If there's anything else you want us to remove, you can always let us know, even at the end of the session.
- To help protect your personal and tax information, personally identifying information like your full name and your email is not shared with the IRS or other government agencies. The recruitment agency deletes that information after the study is completed.
- Your participation today is entirely voluntary. You'll receive compensation as a token of our appreciation for your participation. You do not have to answer any questions that you do not wish to answer but please keep in mind, there are no wrong answers.
**Notetakers \[if they opted in for observers and notetakers\]:**
- You mentioned youd be ok with having a \[additional\] notetaker in our session today. Are you still ok with that, or would you prefer to have the session without them today? Either way is fine with us.
- \[if participant accepts to have notetakers, or an additional notetaker, let them in the Zoom from the waiting room\] Ok, I will let them in. I wanted to introduce you to \[name notetakers/observers by their full names, role, and what organization they are affiliated with. Ask them to be camera on, wave, then turn camera off to make the participant comfortable\]. Most of the conversation today will be between you and me and they will be off camera, but I wanted to make sure they had a chance to say hello.
- \[if participant declines to have notetakers, or an additional notetaker, quietly remove them from the waiting room\] Ok, no problem.
**If recording:**
I would like to record this session. The recording is for research purposes only and your name won't be associated with it. Recordings will be kept in a secure location and shared only with the people running the study for the purpose of improving Direct File. Are you ok with recording this session?
\[when using Zoom\] Before I start recording, Im going to change your name on Zoom so that the recording doesnt include any full names. \[change name and start recording\]
- Do you understand these guidelines?
- Are you ok to continue?
- Do you have any questions before we start?
### **Prototype Introduction \- Moderator controls the prototype**
Next were going to look at a prototype of the website. There are a few things Id like you to keep in mind:
* Ill describe a scenario and then give you a set of tasks to complete using the prototype.
* This is a prototype and not the real website. \[Invision: It closely matches the real site, but some things may not work as expected.\] You may see placeholder information that doesn't match your own situation exactly and that's ok.
* I'm going to share my screen and you can tell me what to do, what to click, where to scroll.
* There are questions that will ask you to input information. When we get to these points, you can tell me what you would input, and then we'll move on.
* As you're going through the prototype, please think aloud. I'd like you to say whatever comes into your mind. I'm interested in what's grabbing your attention on the screen, what questions you have, and your general thoughts as you review a page.
* If at any point you feel uncomfortable or confused, please let me know. We are testing the site and gathering feedback and testing not you or your tax knowledge. Were here to support and learn from you.
* If you have any questions as we go along, please feel free to ask me. I may not be able to answer them right away since were interested in how people would navigate this website without a helper around. But if you still have any questions when were done, Ill try to answer them then.
* And please feel free to be as honest as possible it wont hurt our feelings.
\[Pull up testing environment and share screen\]
### **Prototype Introduction \- Participant controls the prototype**
Next were going to look at a prototype of the website. There are a few things Id like you to keep in mind:
* Ill describe a scenario and then give you a set of tasks to complete using the prototype.
* This is a prototype and not the real website. It closely matches the real site, but some things may not work as expected. \[Invision: It closely matches the real site, but some things may not work as expected.\] You may see placeholder information that doesn't match your own situation exactly and that's ok.
I'm going to send you a link to the prototype in the chat and ask you to open the prototype and share your screen so I can follow along as you go. Does this sound okay to you? \[If participant is uncomfortable \- Alternatively, I can share my screen and you can tell me where to click and what to do. Switch to moderator controls prototype intro\].
* \[Send link to prototype in chat, confirm has it open\]
* Can you share your screen now? (Zoom) You can share your screen by clicking on the green "Share screen" button in the bottom bar. Then, select on the option that has the website open. Let me know if you need any help with this.
Before we continue, I have some more information for you.
* As you go through the site, there'll be places where you can type in information. Please do not enter ANY real information about yourself. I'll give you fake data to enter.
* As you're going through the prototype, please think aloud. I'd like you to say whatever comes into your mind. I'm interested in what's grabbing your attention on the screen, what questions you have, and your general thoughts as you review a page.
* If at any point you feel uncomfortable or confused, please let me know. We are testing the site and gathering feedback and testing not you or your tax knowledge. Were here to support and learn from you.
* If you have any questions as we go along, please feel free to ask me. I may not be able to answer them right away since were interested in how people would navigate this website without a helper around. But if you still have any questions when were done, Ill try to answer them then.
* And please feel free to be as honest as possible it wont hurt our feelings.
### **Global questions/instructions/observation points throughout the session**
* What are your takeaways from this screen?/Can you describe what's going on in this page?
* What would you do next?
* You click \[button label\] and this is what you see next.
* What do you think will happen next?
* What are your questions or concerns so far?
* How would you go about answering this question?
* What questions do you have about how to answer this?
* What might make this hard or confusing to answer?
* What kind of help would you be looking for to answer this question?
* How confident are you that you're answering this question accurately?
* Do you have any other questions not otherwise answered on the page?
* How do you feel about your understanding of \[insert term\]? How concerned or not concerned are you about your understanding?
When looking at help content:
* What are your thoughts on what you're reading?
* How helpful or not helpful is this information?
* Do you have any additional questions?
### **Wrap-Up Questions**
That's all the questions I have for you today.
* Before we end, do you have any questions for me?
* Any last thoughts or feedback we didn't get to discuss already?
\[Confirm incentive payment steps as needed\]. Thank you so much for taking the time to share your thoughts and feedback. I'll bring your input to our team to help improve Direct File.
## **Moderation Guide Template: End-to-End Observation Session**
### **Intro**
\[Allow participant in from the waiting room, keep observers/notetakers in the waiting room (you may allow a notetaker in at this point if the study plan required it). Ensure Slack and notifications are paused if preferred.\]
Good morning/afternoon. How are you today? Im \[moderator name\], a \[insert role\] from \[insert organization\].
\[if a notetaker is part of the plan\] I wanted to introduce you to \[name notetaker by their full name and what organization they are affiliated with and their role. Ask them to be camera on, wave, then turn camera off to make the participant comfortable\].
Im/we are part of a team that's building Direct File, a website for people to file taxes directly with the IRS.
Before we start, I want to let you know more about what you can expect during today's conversation:
**Time:** We have 3 hours together today. If we end before 3 hours you will still get paid and if you arent finished by the 3-hour mark, we will stop our session, and you will still be paid for your time.
**Session:**
* I'll start with a few questions to learn a bit more about your past experiences filing taxes.
* \[if using DF to file taxes\] Since you chose to file your taxes using Direct File, youll be using the Direct File website while we observe.
* \[if using real tax forms\] Do you have the documents the recruiter asked you to gather?
* We're testing the website and not you, which means there's no right or wrong answers we're looking for \- we're interested in your general thoughts and feedback.
* Taxes are hard \[if covering other sensitive topics, name those as well, e.g. “talking about shared custody can be difficult and bring up a lot of feelings”\]. If some topics become difficult to talk about please let me know, I'm here to support you. You can let me know if you need to take a break or stop at any point. If there are any questions you dont want to answer just let me know and Ill move on.
* Unfortunately, we're not tax experts and we can't give you tax advice. I also don't have access to your tax information.
**Privacy:**
* We'll only use what we learn from you to help improve Direct File.
* Everything you say will be anonymous and be kept strictly private. We are taking notes — but those wont include your name or any other personal identifying information. If there's anything else you want us to remove, you can always let us know, even at the end of the session.
* Your participation today is entirely voluntary. You'll receive compensation as a token of our appreciation for your participation.
* We may ask you to show us your tax documents on occasion to compare it with what's showing up on the screen. When we do that, we'd ask you to hide SSNs, DOB and other information you deem sensitive before you show it to us. Would you be ok with that? If you prefer not to show us this information that's fine.
**Notetakers \[if they opted in for observers and notetakers\]:**
* Note that observers are referred to as notetakers throughout the experience for the sake of simplicity
* You mentioned youd be ok with having a \[additional\] notetaker in our session today. Are you still ok with that, or would you prefer to have the session without them today? Either way is fine with us.
* \[if participant accepts to have notetakers, or an additional notetaker, let them in the Zoom from the waiting room\] Ok, I will let them in. I wanted to introduce you to \[name notetakers/observers by their full names, role, and what organization they are affiliated with. Ask them to be camera on, wave, then turn camera off to make the participant comfortable\]. Most of the conversation today will be between you and me and they will be off camera, but I wanted to make sure they had a chance to say hello.
* \[if participant declines to have notetakers, or an additional notetaker, quietly remove them from the waiting room\] Ok, no problem.
Do you understand these guidelines?
Are you ok to continue?
Do you have any questions before we start?
### **Intro to End-to-End Tax Filing Task**
Ok, now well dive into Direct File. Ill start by setting up a scenario for you lets imagine its the 2025 tax season and youre starting your 2024 federal taxes. Youve heard about a new website called Direct File where you can file your federal taxes directly with the IRS online. Youve decided youre now going to file your federal taxes using Direct File.
Please take out your personal tax documents and use those as a reference when you fill out your tax information with Direct File. Next, please pull up the directfile.irs.gov on your device to start filing your taxes.
* \[if remote session\] Once you have successfully logged in, I would like you to share your screen.
* In order to share your screen on Zoom please press the green share screen button at the bottom center of the Zoom page. It will give you several options to share, please just share the Direct File website page. You can also click on the zoom window to make it active and:
* Enter Alt+S on Windows or Command+Shift+S on Mac to start and stop sharing.
* Enter Alt+T on Windows or Command+Shift+T on Mac to pause and continue sharing.
* Do everything you would normally do.
* During your tax filing process we may remind you to make sure we can clearly see your screen.
These questions may be asked depending on whether the participant has hit a roadblock or pain point.
* Can you describe what's going on in this page?
* What would you do next?
* What are your questions or concerns?
* Do you understand the way the information is being presented?
* How confident do you feel about this choice?
When looking at help content:
* What are your thoughts on what you're reading?
* Does this answer the questions you had?
* Do you have any additional questions?
### **Session Wrap-Up**
Thanks. I just have a few follow-up questions before we finish.
* Is there anything you saw today that you have questions about?
* From a scale of 1 to 10—1 being terrible and 10 being the best—how would you score the experience of filing your return?
* What makes you give it that score?
* \[if \>1 or \<10\] Why not a 1/10?
* \[if not 10\] What would have made it a 10?
That's all the questions I have for you today.
* (Optional) Is there anything you said you'd want us to delete from our notes?
* Before we end, do you have any questions for me? Or something to share that we didn't talk about?
* The recruitment firm will be in touch about your incentive.
* Thank you so much for your help and for taking the time to share your thoughts and feedback. I will bring your input to our team to help make using the Direct File website a better experience.

View file

@ -0,0 +1,80 @@
# **Resources for Learning About Taxes**
### **IRS Resources:**
* Taxpayer roadmap tool [https://www.taxpayeradvocate.irs.gov/get-help/roadmap/](https://www.taxpayeradvocate.irs.gov/get-help/roadmap/)
* Order a free copy of the taxpayer roadmap tool: [https://apps.irs.gov/app/taxmat/form-search/](https://apps.irs.gov/app/taxmat/form-search/)
* Train to be a Volunteer Income Tax Assistance (VITA) support volunteer or just use their resources: [https://apps.irs.gov/app/vita/basic\_student.jsp?level=basic](https://apps.irs.gov/app/vita/basic_student.jsp?level=basic)
* VITA intake form (good example of asking direct, situational questions) [https://www.irs.gov/pub/irs-pdf/f13614c.pdf](https://www.irs.gov/pub/irs-pdf/f13614c.pdf)
* Publication 4491 \- VITA Training Guide (currently down on IRS website but archived here: [https://www.vitaresources.net/](https://www.vitaresources.net/))
* Publication 4012 \- VITA Volunteer Resource Guide (currently down on IRS website but archived here: [https://www.vitaresources.net/](https://www.vitaresources.net/))
* Publication 17: A "tax code manual" that explains tax laws, treasury regulations and court decisions. [https://www.irs.gov/forms-pubs/about-publication-17](https://www.irs.gov/forms-pubs/about-publication-17) and [https://www.irs.gov/publications/p17\#en\_US\_2024\_publink1000170356](https://www.irs.gov/publications/p17#en_US_2024_publink1000170356)
* [Forms, Instructions, and Publications Browser](https://www.irs.gov/forms-instructions-and-publications): Searchable table on [irs.gov](https://www.irs.gov/) that lets you search for relevant forms, instructions, and publications by product number (eg., `Form 8889`, `Publication 969`, etc.), title, keyword, or revision date.
* IRS Pub 4801 \- line item estimates (tax forms with data about how many people used each line) [https://www.irs.gov/pub/irs-pdf/p4801.pdf](https://www.irs.gov/pub/irs-pdf/p4801.pdf)
## **IRS Resources relevant to Direct File Tax Scope:**
**Form 8889,Form 8889, Health Savings Accounts (HSAs)**
* About Form 8889 \- [https://www.irs.gov/forms-pubs/about-form-8889](https://www.irs.gov/forms-pubs/about-form-8889)
* Publication 969: Health Savings Accounts and Other Tax-Favored Health Plans \- [https://www.irs.gov/pub/irs-pdf/p969.pdf](https://www.irs.gov/pub/irs-pdf/p969.pdf)
**Form 1099-R, Distributions From Pensions, Annuities, etc**
* About Form 1099-R, Distributions From Pensions, Annuities, Retirement or Profit-Sharing Plans, IRAs, Insurance Contracts, etc. \- [https://www.irs.gov/forms-pubs/about-form-1099-r](https://www.irs.gov/forms-pubs/about-form-1099-r)
* Form 1040 \- [https://www.irs.gov/pub/irs-pdf/f1040.pdf](https://www.irs.gov/pub/irs-pdf/f1040.pdf)
* Instructions for Forms 1099-R and 5498 [https://www.irs.gov/instructions/i1099r](https://www.irs.gov/instructions/i1099r)
* Publication 590-A, Contributions to Individual Retirement Arrangements (IRAs) \- [https://www.irs.gov/forms-pubs/about-publication-590-a](https://www.irs.gov/forms-pubs/about-publication-590-a)
* Publication 590-B, Distributions from Individual Retirement Arrangements (IRAs)[https://www.irs.gov/forms-pubs/about-publication-590-b](https://www.irs.gov/forms-pubs/about-publication-590-b)
* Publication 1220, Specifications for Filing Forms 1097, 1098, 1099, 3921, 3922, 5498, 8935, and W2-G Electronically \- [https://www.irs.gov/pub/irs-pdf/p1220.pdf](https://www.irs.gov/pub/irs-pdf/p1220.pdf)
**Alaska Permanent Fund**
* Alaska Permanent Fund Dividend: Tax Information \- [https://pfd.alaska.gov/payments/tax-information](https://pfd.alaska.gov/payments/tax-information)
* Schedule 1 (Form 1040), Additional Income and Adjustments to Income PDF (📝 Line 8g).AQ: Is a Permanent Fund Dividend or a Resource Rebate payment received by a resident of Alaska taxable? \- [https://www.irs.gov/faqs/interest-dividends-other-types-of-income/1099-div-dividend-income\#collapse-2](https://www.irs.gov/faqs/interest-dividends-other-types-of-income/1099-div-dividend-income#collapse-2)
* Schedule 1 (Form 1040), Additional Income and Adjustments to Income PDF (Line 8g) \- [https://www.irs.gov/pub/irs-pdf/f1040s1.pdf](https://www.irs.gov/pub/irs-pdf/f1040s1.pdf)
**Schedule R (Form 1040), Elderly and Disabled Credit**
* About Schedule R (Form 1040), Credit for the Elderly or the Disabled \- [https://www.irs.gov/forms-pubs/about-schedule-r-form-1040](https://www.irs.gov/forms-pubs/about-schedule-r-form-1040)
* Publication 524 for the Elderly or the Disabled (Note that this publication is soon going to be obsolete. The IRS is getting rid of it/combining it with the instructions for Schedule R.) \- [https://www.irs.gov/publications/p524](https://www.irs.gov/publications/p524)
* Publication 525, Taxable and Nontaxable Income \- [https://www.irs.gov/forms-pubs/about-publication-525](https://www.irs.gov/forms-pubs/about-publication-525)
* Publication 554, Tax Guide for Seniors \- [https://www.irs.gov/publications/p554](https://www.irs.gov/publications/p554)
**Schedule B (Form 1040), Interest and Ordinary Dividends**
* About Schedule B (Form 1040), Interest and Ordinary Dividends \- [https://www.irs.gov/forms-pubs/about-schedule-b-form-1040](https://www.irs.gov/forms-pubs/about-schedule-b-form-1040)
* About Publication 17, Your Federal Income Tax \- [https://www.irs.gov/forms-pubs/about-publication-17](https://www.irs.gov/forms-pubs/about-publication-17)
**Saver's Credit (Qualified Retirement Savings Contributions Credit)**
* About Form 8880 \- [https://www.irs.gov/forms-pubs/about-form-8880](https://www.irs.gov/forms-pubs/about-form-8880)
* Publication 590-A, Contributions to Individual Retirement Arrangements (IRAs) \- [https://www.irs.gov/forms-pubs/about-publication-590-a](https://www.irs.gov/forms-pubs/about-publication-590-a)
* Publication 590-B, Distributions from Individual Retirement Arrangements (IRAs) \- [https://www.irs.gov/forms-pubs/about-publication-590-b](https://www.irs.gov/forms-pubs/about-publication-590-b)
**Premium Tax Credit (PTC), Form 8962**
* About Form 8962 \- Premium Tax Credit \- [https://www.irs.gov/forms-pubs/about-form-8962](https://www.irs.gov/forms-pubs/about-form-8962)
* About Publication 974 \- Premium Tax Credit \- [https://www.irs.gov/forms-pubs/about-publication-974](https://www.irs.gov/forms-pubs/about-publication-974)
**Child and Dependent Care Expenses (CDCC), Form 2441**
* About Form 2441, Child and Dependent Care Expenses \- [https://www.irs.gov/forms-pubs/about-form-2441](https://www.irs.gov/forms-pubs/about-form-2441)
* About Publication 503, Child and Dependent Care Expenses \- [https://www.irs.gov/forms-pubs/about-publication-503](https://www.irs.gov/forms-pubs/about-publication-503)
*
### **Past IRS Research and Reports**
* 2021 Tax Filing and Take-Up \- [https://www.nber.org/papers/w28398](https://www.nber.org/papers/w28398)
* 2019 Outreach Experiments on Paper Filers and Nonfilers \- [https://www.irs.gov/pub/irs-prior/p1500--2021.pdf](https://www.irs.gov/pub/irs-prior/p1500--2021.pdf)
* IRS contracted report about on uptake of the Free File program \- [https://www.irs.gov/newsroom/irs-free-file-program-sees-early-increase-in-use-filings-up-nearly-10-percent](https://www.irs.gov/newsroom/irs-free-file-program-sees-early-increase-in-use-filings-up-nearly-10-percent) and [https://www.irs.gov/pub/irs-soi/06rpppchu.pdf](https://www.irs.gov/pub/irs-soi/06rpppchu.pdf)
* IRS Direct File Pilot Program Filing Season 2024 After Action Report [https://www.irs.gov/pub/irs-pdf/p5969.pdf](https://www.irs.gov/pub/irs-pdf/p5969.pdf)
### **IRS-Adjacent Research and Reports**
* Code for America \- about free direct file \- [https://codeforamerica.org/news/federal-tax-direct-file-prototype/](https://codeforamerica.org/news/federal-tax-direct-file-prototype/)
* Code for America \- Lessons from GetCTC on the design of the IRS tax return processing system \- [https://files.codeforamerica.org/2023/04/20122629/modernized-efile-and-client-experience-getctc-2022-learnings-report.pdf](https://files.codeforamerica.org/2023/04/20122629/modernized-efile-and-client-experience-getctc-2022-learnings-report.pdf)
* TAS plain language help / explainers \- [https://www.taxpayeradvocate.irs.gov/get-help/](https://www.taxpayeradvocate.irs.gov/get-help/)
* Ethnography of homeless and housing-insecure Canadians experiences filing taxes and accessing benefits, Canada Revenue Agency \- [https://www.canada.ca/en/revenue-agency/programs/about-canada-revenue-agency-cra/corporate-reports-information/ethnography-homeless-experiences.html](https://www.canada.ca/en/revenue-agency/programs/about-canada-revenue-agency-cra/corporate-reports-information/ethnography-homeless-experiences.html)

File diff suppressed because one or more lines are too long

Binary file not shown.

View file

@ -0,0 +1,28 @@
# Design and a11y review process
The below steps are specifically the design and accessibility testing part of the overall acceptance flow process. The code submitter should have done their due dilligence for any user interface changes so that a design/a11y reviewer can focus on finer details. Although there are several steps, if we do this regularly it will be a light lift and will avoid any design/a11y debt.
## Verify that any changes match the design intention
- [ ] Check that the design translated visually
- [ ] Check interaction behavior
- [ ] Check different states (empty, one, some, error)
- [ ] Check for landmarks, page heading structure, and links
- [ ] Try to break the intended flow
- [ ] Confirm this works at 5Mbps down and 1Mbps up. You might use [Firefox dev tools](https://firefox-source-docs.mozilla.org/devtools-user/network_monitor/throttling/index.html) or Chrome's [WebRTC Network Limiter](https://chrome.google.com/webstore/detail/webrtc-network-limiter/npeicpdbkakmehahjeeohfdhnlpdklia)
## Verify that any changes meet accessibility targets
- [ ] Check responsiveness in mobile, tablet, and desktop at 200% zoom
- [ ] Check keyboard navigability
* Test general usability, landmarks, page header structure, and links with a screen reader (different from what the original dev used in their checklist):
- [ ] [VoiceOver](https://dequeuniversity.com/screenreaders/voiceover-keyboard-shortcuts#vo-mac-basics) in Safari
- [ ] [JAWS](https://dequeuniversity.com/screenreaders/jaws-keyboard-shortcuts#jaws-the_basics) in Chrome
- [ ] [NVDA](https://dequeuniversity.com/screenreaders/nvda-keyboard-shortcuts#nvda-the_basics) in Chrome
* Use an a11y tool to check these changes conform to at least WCAG 2.1 AA
- [ ] [WAVE](https://wave.webaim.org/)
- [ ] [axe](https://www.deque.com/axe/devtools/)
- [ ] [ANDI](https://www.ssa.gov/accessibility/andi/help/install.html#install)
- [ ] Browser inspector ([firefox](https://firefox-source-docs.mozilla.org/devtools-user/accessibility_inspector/#accessing-the-accessibility-inspector) / [chrome](https://developer.chrome.com/docs/lighthouse/accessibility/))
- [ ] For storybook-only components, use its [accessibility addon](https://medium.com/storybookjs/instant-accessibility-qa-linting-in-storybook-4a474b0f5347#c703).

BIN
docs/design/flow1.zip Normal file

Binary file not shown.

BIN
docs/design/flow2.zip Normal file

Binary file not shown.

BIN
docs/engineering/.DS_Store vendored Normal file

Binary file not shown.

View file

@ -0,0 +1 @@
# Engineering docs

View file

@ -0,0 +1,333 @@
# Tax Logic
# Scenarios
### Validating scenarios
Here some images that explain what scenarios are and how we validate them.
<img width="736" alt="Screenshot 2025-05-21 at 2 42 04 PM" src="https://github.com/user-attachments/assets/71b5a337-a7e7-4243-9b10-7757055a58bb" />
<img width="680" alt="Screenshot 2025-05-21 at 2 42 12 PM" src="https://github.com/user-attachments/assets/88f187b5-728d-4df6-aff7-219a928acf56" />
<img width="727" alt="Screenshot 2025-05-21 at 2 42 26 PM" src="https://github.com/user-attachments/assets/bed7889e-c98f-4d65-b987-58e97c556a8d" />
<img width="912" alt="Screenshot 2025-05-21 at 2 42 45 PM" src="https://github.com/user-attachments/assets/c4a9aa68-2a06-4a0b-be7a-df81d8558254" />
# Translations
## Summary
We use a library called [i18next](https://www.i18next.com/) for internationalization (i18n).
It creates the ability to use references (keys) to point to translation values based on various natural languages. Currently we have translations for English (by default) and Spanish. The translations are found in en.yaml and es.yaml.
Any content provided by design needs to be added to the en.yaml. All content is submitted by design to General Counsel (GC). After it is approved by GC, we do the Spanish translations, which are added to the es.yaml (Note: we are working on tooling to simplify translations)
## Tips and Tricks for adding content
- en.yaml is a very long file. See if your IDE has bookmarks, and use them to mark your spot
- en.yaml is organized by content type (subsubsections, headings, info, dataviews, fields)
- When implementing several screens, input by content component type rather than screen content. For example, input all the headings of each of the screens since they will be next to each other in the yaml file. Then do all the InfoDisplay content, then Modal content, etc).
- You can interpolate any (non-nested) fact value into the content using double curly brackets (ex. \`{{/taxYear}})
- If your content string starts with interpolation (ex `{{/secondaryFiler/firstName}}`), you need to wrap the string in double quotes
- Use a proper apostrophe char ``instead of a single quote `'` when an apostrophe is needed. On a Mac, the shortcut is `Option + Shift + ]`(there is a test for this, and search and replace may be the most efficient way to do this when copying and pasting from design)
- To reference existing content within the yaml, use the syntax `$t(path./to-value)`([for reference](https://www.i18next.com/translation-function/nesting))
- `>-` basically means 'newline' in yaml
# Flamingo Fact Checker
[Link to plugin and instructions](Flamingo-Fact-Checker).
# FAQs
* [What is migrateScenarios?](#what-is-migratescenarios)
* [Is there some fact graph 101 I can read?](#is-there-some-fact-graph-101-i-can-read)
* [Can someone explain the distinction between categories, subcategories, and subsubcategories in the codebase and why i MUST have a subsubcategory according to my console?](#can-someone-explain-the-distinction-between-categories-subcategories-and-subsubcategories-in-the-codebase-and-why-i-must-have-a-subsubcategory-according-to-my-console)
* [What's a scenario?](#whats-a-scenario)
* [Why don't we call scenarios fact graphs or vice versa?](#why-dont-we-call-scenarios-fact-graphs-or-vice-versa)
* [What tests should I run if making screen changes or fact changes?](#what-tests-should-i-run-if-making-screen-changes-or-fact-changes)
* [What do flowSnapshots do and why do I have 100 errors?](#what-do-flowsnapshots-do-and-why-do-i-have-100-errors)
* [What are we doing when we SetFactAction?](#what-are-we-doing-when-we-setfactaction)
* [Does `npm run test` run all the frontend tests?](#does-npm-run-test-run-all-the-frontend-tests)
* [When do facts need to be sent "downstream" or sent to "mef"?](#when-do-facts-need-to-be-sent-downstream-or-sent-to-mef)
* [Adding new collection aliases are weird ?](#adding-new-collection-aliases-are-weird)
* [What's the deal with Placeholders?](#whats-the-deal-with-placeholders)
* [What is the difference between a fact in the dictionary with a value put in \<Placeholder\> tags like this, and a fact in the dictionary with just a value assigned but no Placeholder tag like this?](#what-is-the-difference-between-a-fact-in-the-dictionary-with-a-value-put-in-placeholder-tags-likethis-and-a-fact-in-the-dictionary-with-just-a-value-assigned-but-no-placeholder-tag-likethis)
* [What about \<ExportZero/\>?](#what-about-exportzero)
* [How does one deal with the requirement of export zero dollar values, **sometimes**, **conditionally**?](#how-does-one-deal-with-the-requirement-of-export-zero-dollar-valuessometimesconditionally)
* [How are data view created?](#how-are-data-view-created)
* [When can we use which fact types when writing facts?](#when-can-we-use-which-fact-types-when-writing-facts)
* [\[ERROR\] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.13.0:compile (default-compile) on project directfile-api: Fatal error compiling: error: release version 21 not supported](#error-failed-to-execute-goal-orgapachemavenpluginsmaven-compiler-plugin3130compile-default-compile-on-project-directfile-api-fatal-error-compiling-error-release-version-21-not-supported)
* [How to create a knockout?](#how-to-create-a-knockout)
* [What is the difference between `useDynamicFact` and `useFact`?](#what-is-the-difference-between-usedynamicfact-and-usefact)
* [Headings vs InfoDisplays?](#headings-vs-infodisplays)
* [When we have a screen where we calculated a bunch of stuff to show to the tp, but it isn't a writable field - these results don't show up in the dataview. it seems weird not to have them. How do we add a non-field piece of info to the dataview for that subsubcategory?](#when-we-have-a-screen-where-we-calculated-a-bunch-of-stuff-to-show-to-the-tp-but-it-isnt-a-writable-field---these-results-dont-show-up-in-the-dataview-it-seems-weird-not-to-have-them-how-do-we-add-a-non-field-piece-of-info-to-the-dataview-for-that-subsubcategory)
* [My test is failing with \`Invalid UUID string: undefined](#my-test-is-failing-with-invalid-uuid-string-undefined)
* [I got a CSP warning in the console. I need to update the CSP. Where do I do that?](#i-got-a-csp-warning-in-the-console-i-need-to-update-the-csp-where-do-i-do-that)
* [What is All-Screens and where can I find it?](#what-is-all-screens-and-where-can-i-find-it)
* [What's the difference between `DFAlert`, `Assertion` , `TaxReturnAlert` , `MefAlert`, `FactAssertion`, and `FactResultAssertion` ?](#whats-the-difference-betweendfalert-assertion--taxreturnalert-mefalert-factassertion-and-factresultassertion-)
* [I have to create some checkboxes and can use MultiEnum or Booleans as checkboxes. When should I use one over the other?](#i-have-to-create-some-checkboxes-and-can-use-multienum-or-booleans-as-checkboxes-when-should-i-use-one-over-the-other)
* [Why does this Fact error out with \`java.lang.UnsupportedOperationException: must use getVect to access...](#why-does-this-fact-error-out-with-javalangunsupportedoperationexception-must-use-getvect-to-access)
* [I need to set a limit for a fact based on the value of another fact. How do I do it?](#i-need-to-set-a-limit-for-a-fact-based-on-the-value-of-another-fact-how-do-i-do-it)
* [How do I format a recent factgraph module that I changed?](#how-do-i-format-a-recent-factgraph-module-that-i-changed)
* [How to capitalize an Enum using existing CompNodes?](#how-to-capitalize-an-enum-using-existing-compnodes)
### What is migrateScenarios?
Why? When a change in the codebase requires that all jsons contain new facts or updates to existing facts, this script can be used to update all of the files at once.
How? The script does not automatically detect anything or run automatically.
* The eng who made the change to the codebase should change this script to update the facts as needed.
* In most cases only the section between MIGRATION START and MIGRATION END will need to be updated.
* Then the eng runs this script and commits the updated jsons. `npm run migrate-scenarios`
Note that even though it is checked in, this script runs only once to update all the scenario jsons.
### Can someone explain the distinction between categories, subcategories, and subsubcategories in the codebase and why i MUST have a subsubcategory according to my console?
* Categories and subcategories appear in the checklist
* Each subcategory may have 1-2 items of data in the checklist
* Each subcategory has a dataview, which is a summary of the subcategory.
* In some cases the dataview might just be a screen within the subcategory (`<Screen actAsDataView={true} />`)
* But in most cases the dataview is a new page which shows all the subsubcategories.
* The subsubcategories in the dataview have multiple items of data and an edit button.
* The subsubcategory edit button takes you to those screens in the flow.
* Then you will be in review mode and on completion of the screens in that subsubcategory, get redirected back to the dataview.
* Every screen must be in a subsubcategory with the following exceptions
* If a screen is the only screen in a subcategory AND it is marked with `actAsDataview`
* If a screen is not editable, can be placed inside a subcategory. In this case, the screen will only be shown to a taxpayer on their first pass of the screens- it will not show up in review mode.
### What's a scenario?
As a client enters information in the Direct File (DF) application, the application accumulates these facts. These accumulated facts is sometimes called the "client factgraph json". This json file can represent almost any situation, and they essentially represent one user's tax situation or _scenario_.
So we store them and use them to test different user scenarios. We have a few hundred pre-defined scenarios. These scenarios lay the foundation for testing various parts of our app. As we add scope, we may add more scenarios.
### Why don't we call scenarios fact graphs or vice versa?
I guess we could, but to allow some distinction between any fact graph and this set of fact graphs that represent different user tax return situations, we introduced the concept of scenarios.
Scenarios are a subset of factgraphs as they are required to be complete - as in, the person got to the sign and submit screen and there were no submission blocking errors.
### What tests should I run if making screen changes or fact changes?
It kinda depends on what is changing in the screen. If the screen order changes then the `flowSnapshots` tests would capture this. When facts change there can be a whole cascade of tests that can test this change. Our recommendation is to follow this [mural](https://app.mural.co/t/usdigitalservice0135/m/usdigitalservice0135/1722960219541/36%5B%E2%80%A6%5D510295f8a2727fd347e319714a73c?sender=u609b185fbd158566f8103243) and walk through each step when making fact changes. There are 4 steps and each step has instructions on what tests to run.
### What do flowSnapshots do and why do I have 100 errors?
flowSnapshots are making sure the order of the screens are what we expect them to be for each scenario.
The way it works is that it runs through the scenario, as though the user is clicking through screens and stores the sequence of screens seen. Then that sequence is stored, so that we can test that it doesn't change accidentally.
If some new screen was added that will be shown to the users represented by lots of scenarios, that sequence will now change and not match what was stored. So when the flowSnapshot test ran it updated all snapshots and you may be seeing many errors.
If the change you see in the files is what was expected based on the change you made in your PR, you can simply check in the new sequence.
### What are we doing when we SetFactAction?
Sometimes we need to set a fact when the tax payer (TP) reaches a screen, regardless of their input. In other words, "when a TP reaches this screen, set this fact".
### Does `npm run test` run all the frontend tests?
Yes, `npm run test` runs all the frontend vite tests. There are two other tests that may be helpful:
* `npm run test:ci` - which runs all tests from the CI/CD pipeline (ie, when a PR is opened or committed to) except the completenessTests and functionalFlowTests.
* `npm run test:ci:2` - runs the completenessTests and functionalFlowTests
### When do facts need to be sent "downstream" or sent to "mef"?
Our fact dictionary is broken into modules. Each fact dictionary module is an XML fie. Here's a list of them as of the time of writing this answer:
![Screenshot 2024-08-21 at 4.02.16 PM.png](uploads/a6af72545ca2a2b0bb18da9eb1f30267/Screenshot_2024-08-21_at_4.02.16_PM.png){width="281" height="822"}
With `elderlyAndDisabled.xml` selected, opening this file, we see:
![Screenshot 2024-08-21 at 4.02.06 PM.png](uploads/d84c34f216cf1c5c4d9fdb53a6eae640/Screenshot_2024-08-21_at_4.02.06_PM.png){width="1063" height="822"}A few things we notice that the first line of this file designates this to be a fact dictionary. The first fact has the export statement of:
* Export mef="true" downstreamFacts="true"
Certain facts are needed by other modules, if/when a fact is needed by another module, you can specify `downstreamFacts="true"`. Another advantage is testing. Fact that we're exporting for reuse in other modules should probably have tests.
You do not need to set downstreamFacts in order to write the value in a PDF, that process is just another way of displaying the value and is not subject to dependency management.
A few things to keep in mind
1. Always run the `npm run watch-fact-dictionary` so that any changes to any fact dictionary module will automatically re-build the dictionary
2. To validate your fact dictionary changes, you can run `npm run verify-module-dependencies`. This will let you know if some facts are in error or if you are missing the `mef` or `downstreamFacts` attribute on any fact definition.
### Adding new collection aliases are weird
Indeed. In the filers.xml fact dictionary module, you will sometimes see facts with a \_`*` eg, `/filers/`\_`*/firstName`. This would be a _collection_. Each collection is made up of _collection items._ In this case, the filers collection is made up of two items, namely the primary and secondary UUIDs.
Lets say we wanted to operate on that collection, by e.g., filtering it. When we filter that collection, the resulting collection could be
1. \[primaryUUID, secondaryUUID\]
2. \[primaryUUID\]
3. \[secondaryUUID\]
4. \[\]
This filtered collection, doesn't have access to the other facts in the filers module. For example, `/filers/*/MiddleInitial` or `/filers/*/dateofBirth`. In order to access these other facts, we use aliases.
There are two files responsible for aliases, ie, aliases.ts and dependencyGraph.ts
### What's the deal with Placeholders?
Placeholders help set the value but don't make a fact complete.To answer your questions more directly, placeholders mean that a value of a fact will never be blank. Once a fact is written we generally don't provide ways to clear out written facts. The reason they don't work as a proper default is that we also end up checking if a fact is complete in a couple of different spots.
### What is the difference between a fact in the dictionary with a value put in \<Placeholder\> tags and a fact in the dictionary with just a value assigned but no Placeholder tag
So we have a concept of writable facts and derived facts where writable facts are those that the user can update and derived facts that are just "calculated" values. "Placeholders" I believe are only supported for writable facts as the intention is that the user should potentially override them with a written value. Derived facts can just be static values like in the example you gave. I would consider it to be more of a constant than a default value, but that's likely just a jargon/pedantic distinction. This is a default value in the sense that this value will not really change.
### What about \<ExportZero/\>?
By default, facts with value zero are not sent to PDF or XML generation. This tag overrides that behavior for a fact, so that the zero will be included in the outputs.
Note that it is possible to conditionally export zero values by using this tag on a fact that conditionally leaves its value unspecified (incomplete). PDF generation automatically ignores incomplete fact values, producing the effect of a "blank" output. XML mappings can use the Optional syntax to get a similar result.
### How does one deal with the requirement of export zero dollar values, **sometimes**, **conditionally**?
TBD
### How are data view created?
Some info [here](flow/dataviews.md)
### When can we use which fact types when writing facts?
When creating facts the first question to ask is, is the fact a writable fact or a derived fact. If the fact is writable. then generally speaking we will require it to use one of the factTypes, to calculate a new fact based on some other fact (called a Dependency).
### \[ERROR\] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.13.0:compile (default-compile) on project directfile-api: Fatal error compiling: error: release version 21 not supported
In the event that anyone else has ran into the issue of `./mvnw` ignoring `JAVA_HOME`, I discovered that at some point in my past, I created a `~/.mavenrc` file that overrode `JAVA_HOME` to a specific version number, but only when running maven. Deleting that file caused `./mvnw` to use the correct version.
### How to create a knockout?
In summary there are 3 steps:
1. Create the fact that will be responsible to knockout the TP
2. Add the Screen that will use the fact created in Step 1 and set `isKnockout={true}` on it.
3. Add the newly created fact from Step 1 to the `/flowIsKnockedOut` fact in flow.xml.
### Headings vs InfoDisplays?
Every screen has a `Heading` and yes they are sometimes long. Every screen can only have one `Heading`.
Usually the top most text on every screen is the `Heading`. I believe in some cases there is a section header above the header. `InfoDisplay`s handles a lot of flexible content as you can put "html" inside it. Most explanatory text would use `InfoDisplay` by default.
You can have more than one `InfoDisplay` in a screen but not more than one `Heading`.
### When we have a screen where we calculated a bunch of stuff to show to the tp, but it isn't a writable field - these results don't show up in the `dataview`. it seems weird not to have them. How do we add a non-field piece of info to the `dataview` for that `subsubcategory`?
What you may be be looking for is `displayOnlyOn` property. You can add this to any of the content declaration types we have like Dollar or String with the corresponding fact and set the `displayOnlyOn` to `data-view` . We have a handful of examples of this within the CreditSubsection.
### My test is failing with \`Invalid UUID string: undefined
You may need to add a a line here in the test file:
```jsx
const collectionIdMap = {
[`/flow/you-and-your-family/about-you`]: primaryFilerId,
[`/flow/you-and-your-family/spouse`]: primaryFilerId,
[`/flow/you-and-your-family/dependents`]: dependentId,
[`/flow/income/jobs`]: w2Id,
[`/flow/income/interest`]: interestReportId,
[`/flow/income/unemployment`]: formId,
[`/flow/income/retirement`]: retirementForm1099Id,
[`/flow/income/apf`]: apfForm1099Id,
[`/flow/income/social-security`]: reportId, };``
```
### What is All-Screens and where can I find it?
All screens is a page that displays every screen in the application and the conditionals for that page. The URL for local development is at http://localhost:3000/df/file/all-screens/index.html
### What's the difference between `DFAlert`, `Assertion` , `TaxReturnAlert` , `MefAlert`, `FactAssertion`, and `FactResultAssertion` ?
`<DFAlert>` has no special behavior and just renders content on a screen like normal
`<Assertion>` is used for alerts that should show up only in the SubCategory dataview screen
`<TaxReturnAlert>` is rendered in a specific screen and an aggregated alert summary on the checklist and dataview pages
* If `type='error'` and the alert's conditions are true, submission will be blocked until the filer makes the necessary updates to fix the error.
* If `type='warning'` does not block submission and just directs the user to review the data on the screen in which it is present
* If the type is set to anything else, the alert will not render under any conditions (this is likely something we should prevent, but may have been unintentional)
* We currently use these to prompt filers to remove any income items associated with a secondary filer if they change their status to anything other than Married Filing Jointly.
`<MefAlert>` are used when an alert is based on the response from MEF and not something we can determine in advance and the error is correctable.
* These will only ever render when a tax return is rejected. They are configured with an `mefErrorCode` that is returned from MEF and linked to the user's return separately from the fact graph and is a required condition for displaying the alert.
* These alerts also bubble up to the checklist and dataviews just as with `<TaxReturnAlert>` and have the same behaviors with the `type` attribute.
* Additional conditions on `<MefAlert>` nodes are used when we are able to determine whether the cause of the error has been resolved and can hide/remove the alert.
* As an example, the `IND-180-01` MEF error code is set if the user submits a return claiming that they have no IP Pin but the IRS has records saying that they do. This prompts a blocking `<MefAlert>` to be displayed that will only become inactive once the user answers that they do, in fact, have a PIN and enter it.
* If we have no way know for certain whether the user has corrected the problem, we should make sure the alert is set to warning, so the user can resubmit once they believe they have corrected the issue.
`<TaxReturnAlert>` and `<MefAlert>` are both aggregated from the screen config so that we can direct them all the way from the checklist, down to the specific screen(s) they belong to.
`<FactAssertion>`, `<FactResultAssertion>`, and the `outcomeI18nKey`/`resultI18nKey` keys are used to display alerts that only bubble up to the dataview and collection screens and are primarily used in the dependents and qualifying persons section.
Lastly, "Cues & Aggregators" area of this 2023 Mural board does a good job explaining [how the alerts work](https://app.mural.co/t/usdigitalservice0135/m/usdigitalservice0135/1679591477411/ca7cc4ebdd42dfd9a3ee5ea57153b0135df9971f?wid=0-1701705425590). Documentation from Jen in the [design wiki - TODO](), should mirror what's on that 2023 Mural.
### I have to create some checkboxes and can use MultiEnum or Booleans as checkboxes. When should I use one over the other?
Use MultiEnum if
* All your checkboxes need to packaged into a single fact as a Set/List and needs to sent to MeF
Use Boolean if
* You need access to those checkbox values later on in the flow
### Why does this Fact error out with \`java.lang.UnsupportedOperationException: must use getVect to access...
Can you see the problem with the code below?
```jsx
<Fact path="/cdccCareProviders/*/isHouseholdEmployeeNo">
<Name>Is Not a Household Employee</Name>
<Description>Whether care provider is not a household employee. Used for the f2441 PDF 'No'
checkbox</Description>
<Derived>
<Not>
<Dependency path="/cdccCareProviders/*/isHouseholdEmployee" />
</Not>
</Derived>
</Fact>
```
The problem lies in the following fact: `/cdccCareProviders/*/isHouseholdEmployee`. Is this fact, complete and true?
To fix this issue, this fact:
```jsx
<Dependency path="/cdccCareProviders/*/isHouseholdEmployee" />`
```
should be
```jsx
<Dependency path="../isHouseholdEmployee" />
```
The error is telling you, you need to use get vect because the original `/cdccCareProviders/*/isHouseholdEmployee` is an array since we don't have the context for the `*`.\
If we use the `../isHouseholdEmployee` we are referencing the same id in the main fact so we would only get a single value here instead of an array.
### I need to set a limit for a fact based on the value of another fact. How do I do it?
There's been some discussion on setting up dynamic fact limits for field level validation, but field level validation alone would not work because you could change the limiting fact so `TaxReturnAlert` is used instead. `<TaxReturnAlert>` has the advantage that if you go back and make edits that would change the validity of that fact, you'll be directed to the now-invalid fact. The downside is the user is not immediately notified of the error.
### How do I format a recent factgraph module that I changed?
Navigate to the project you are working on (backend, submit, etc) and run \`./mvnw spotless:apply\`
### How to capitalize an Enum using existing CompNodes?
```jsx
<ToUpper>
<AsString>
<Dependency module="filers" path="/filerResidenceAndIncomeState" />
</AsString>
</ToUpper>
```

View file

@ -0,0 +1,65 @@
# Bug Prioritization
The following is a draft of guidelines for prioritizing bugs and incident responses that arise during tax season. For the below, we expect releases to happen weekly.\
\
**Rank 0 (R0): Emergency Hotfix, needs to ship as soon as possible**
* You can't submit a tax return (as an individual or to a state) for \>1% of submissions
* Refund or amount due calculation is incorrect and we know taxpayers are being affected by the issue
* Security incident or PII is exposed
* Direct File is down or significantly degraded
* High traffic feature where functionality is broken or not available, and no workaround
\
**R1: Now, Showstopper fix for the next immediate release**
* High traffic functionality is broken - difficult or time consuming workaround
* Medium traffic functionality is broken for a smaller percentage of taxpayers (10 - 50%) with no workaround
* Submissions to states or MeF are blocked for \<1% of taxpayers
* Direct file performance is degraded (metric)
* Refund or amount due calculation would be incorrect but circumstances to trigger the issue are rare enough that production users are unlikely to be affected before scheduled release.
\
**R2: Next, fix for the scheduled release following the next immediate release**
* High value taxpayer experience improvements: Medium, high, to very high traffic feature has confusing functionality with a workaround
* Low traffic functionality is broken for a smaller percentage of taxpayers (10 - 50%)
\
**R3: Later this tax season**
* Usability feedback (via customer support or other sources): improves a medium traffic feature but there is a current workaround
* Low traffic functionality is broken for a smaller percentage of taxpayers (\<10%)
\
**R4: Consider for this tax season**
* Nice to have usability improvements, functionality not needed to perform daily work and is not time sensitive
\
**R5: backlog for future tax seasons**
* Unlikely to get to these: low impact improvements
## References
* Last year's guidelines
* P0: emergency, merits a hotfix\
P1: a **must**/show stopper for the next scheduled release\
P2: a **should** for the next scheduled release\
P3: a **must** for this tax season\
P4: a **should** for this tax season\
P5: backlog for future tax seasons
* Feedback from states
* ability to submit a return is impacted (critical)
* ability to accurately _calculate_ state taxes is impacted (high priority)
* smooth user experience for TP when doing their state taxes (lower priority)
* Tax Logic Priority Scale
* P0: Yesterday (needs to ship as soon as possible, probably an incident)
* P1: Now (needs to be in the next regular release)
* P2: Next (should be release after next)
* P3: Later
* P4: Before the end of filing season
* P5: After filing season
* CfA user pain score calculator: https://files.codeforamerica.org/2022/11/29092445/Client-Pain-Score-User-Pain-Score.pdf
* Note: we chose Rank (R0) vs. Priority (P0) because there is a separate IRWorks priority that uses a different "P" scale

View file

@ -0,0 +1,75 @@
# Flamingo Fact Checker
[Flamingo Fact Checker (zip file in utils directory)](../../utils/) is a chrome extension to assist devs with tracking facts as they move through the UI.
## Features
* Fact tracking - View fact values live on screen.
* Live facts - shows the facts associated with the fields on the page currently being viewed.
* Telescope - View fact documentation and live values of the dependencies inline. Requires environment variable `VITE_ENABLE_FLAMINGO_TELESCOPE` to be set to true.
* Import / Export of factgraph - click on the extension button in Chrome to robustly import or export a factgraph.
* Import / Export of fact names - click on the extension button in Chrome to track a group of facts.
<img width="523" alt="image-1" src="https://github.com/user-attachments/assets/a82a157c-8195-43eb-9139-998b9c142bd9" />
<img width="706" alt="image-2" src="https://github.com/user-attachments/assets/81ff2ab3-092b-491a-b8da-819e88b6ea64" />
## How to install
1. Get the latest release zip
2. Extract the zip, it should create a folder named flamingo
3. Go to `chrome://extensions/`
4. Enable developer mode
5. Click on "Load unpacked", navigate to the folder and click select
6. Go to directfile on [localhost](http://localhost) and it should load.
### How to update
1. Get the latest release zip
2. Extract the zip, it should create a folder named flamingo
3. Go to `chrome://extensions/`
4. Hit the reload the button on the extension
### How to enable telescope
The data for the fact definitions is rather large and I didn't want to force everyone to download it. So this feature is available only on local dev and requires that you set an environment variable in your local environment:
```
export VITE_ENABLE_FLAMINGO_TELESCOPE=true
```
or start npm with it
```
VITE_ENABLE_FLAMINGO_TELESCOPE=true npm run start
```
## Releases
### v1.4.0 [flamingo_v1.4.0.zip](https://github.com/DirectFile/flamingo-fact-checker/blob/main/uploads/457d2aa5547a204b35897000246cbe84/flamingo_v1.4.0.zip)
* Facts truncate if too long, hover to see full name
* Bugs with first install fixed (if rewind never seemed to work for you)
### v1.3.0 [flamingo_v1.3.0.zip](https://github.com/DirectFile/flamingo-fact-checker/blob/main/uploads/14b80c152c2d518673e7bce8bcb65ad7/flamingo_v1.3.0.zip)
* Telescope into a fact and see its dependencies and their values
* Incomplete and placeholder values now visible
* Load and copy out your factgraph easily
### v1.2.1 [flamingo_v1.2.1.zip](https://github.com/DirectFile/flamingo-fact-checker/blob/main/uploads/3107745f4a357647582746fb3a2e8a44/flamingo_v1.2.1.zip)
* Rewind your factgraph
* Hotlink to collection items
* Bugfixes
#### Known Issues
* Some collection items may have more than one hotlink and depending on factgraph, they may not all be visible pages.
### v1.1.0 [flamingo_v1.1.0.zip](https://github.com/DirectFile/flamingo-fact-checker/blob/main/uploads/3fd9deef0cc06c1b9394babc7a4b1091/flamingo_v1.1.0.zip)
* Persistent fact tracking
* Live monitor of current facts on page

View file

@ -0,0 +1,13 @@
const { pdf_options, footerTemplate } = require("./md-to-pdf.config.js");
module.exports = {
pdf_options: {
format: pdf_options.format,
headerTemplate: pdf_options.headerTemplate,
footerTemplate: footerTemplate.replace('[[FOOTER]]', 'OS:IT:AD:CS-PLN-DFSYS_CM_PLAN-V1.0-03052024')
},
// https://github.com/simonhaenisch/md-to-pdf/issues/247
launch_options: {
headless: "new"
}
};

View file

@ -0,0 +1,13 @@
const { pdf_options, footerTemplate } = require("./md-to-pdf.config.js");
module.exports = {
pdf_options: {
format: pdf_options.format,
headerTemplate: pdf_options.headerTemplate,
footerTemplate: footerTemplate.replace('[[FOOTER]]', 'OS:IT:AD:CS-SYS-DFSYS_COH-V0.9-01052024')
},
// https://github.com/simonhaenisch/md-to-pdf/issues/247
launch_options: {
headless: "new"
}
};

View file

@ -0,0 +1,30 @@
const headerTemplate = `
<style>
section {
margin: 0 auto;
font-family: system-ui;
font-size: 12px;
}
.footer div {
position: absolute;
width: 50%;
bottom: 30px;
}
</style>
<section><div>[[HEADER]]</div></section>
`
const footerTemplate = '<section class="footer"><div style="left: 30px;">[[FOOTER]]</div><div style="text-align: right; right: 30px;"><span class="pageNumber"></span></div></section>';
module.exports = {
headerTemplate: headerTemplate,
footerTemplate: footerTemplate,
pdf_options: {
format: 'letter',
headerTemplate: headerTemplate.replace('[[HEADER]]', ''),
footerTemplate: footerTemplate.replace('[[FOOTER]]', 'Draft/Pre-decisional')
},
// https://github.com/simonhaenisch/md-to-pdf/issues/247
launch_options: {
headless: "new"
}
};

View file

@ -0,0 +1,85 @@
// pipe in all the files
// create toc (and figures)
// create pdf
const writeFile = require("node:fs/promises").writeFile;
const md2Toc = async () => {
let options = {
bullets: true,
bullet: "* ",
toplevel: false,
ignorebeforetoc: true,
indent: true,
links: true,
maxdepth: 4
},
tocBody = '',
fileOutput = '';
let passedToc = !options.ignorebeforetoc;
for await (const line of streamByLines(process.stdin)) {
fileOutput += `${line}\n`;
if (/^#/.test(line)) {
let title = line.replace(/^#+\s+/, ""),
onToc = false;
if (/^Table of/.test(title)) {
passedToc = !options.ignorebeforetoc;
onToc = true;
} else {
onToc = false;
}
if (passedToc) {
let currentDepth = (line.match(/^#+/) || [null])[0].length;
if (!options.toplevel) currentDepth = currentDepth-1;
// if we're still under the max depth
if (currentDepth > 0 && currentDepth <= options.maxdepth) {
let indentSpacer = options.indent ? Array(currentDepth).join(" ") : "";
let header;
if (options.links) {
let href = title.replace(/ /g, "-").replace(nonTocCharactersRegex, "").toLowerCase(),
link = "[" + title + "](#" + href + ")\n";
header = options.bullets ? options.bullet + link : link;
} else {
header = options.bullets ? options.bullet + title + "\n" : title + '\n';
}
tocBody = tocBody + indentSpacer + header;
}
}
passedToc ||= onToc;
}
}
const today = new Date().toLocaleDateString('en-US', {month: 'long', day: 'numeric', year: 'numeric'});
fileOutput = fileOutput.replace('[[TOC]]', tocBody).replace('[[DATE]]', today);
return fileOutput;
}
const streamByLines = (stream) => {
stream.setEncoding('utf8');
return {
async *[Symbol.asyncIterator]() {
let buffer = '';
for await (const chunk of stream) {
buffer += chunk;
const lines = buffer.split(/\r?\n/);
buffer = lines.pop();
for (const line of lines) {
yield line;
}
}
if (buffer.length > 0) yield buffer;
},
};
}
md2Toc().then((result) => console.log(result));
const nonTocCharactersRegex = /(?! |-|[\u0041-\u005A\u0061-\u007A\u00AA\u00B5\u00BA\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0\u08A2-\u08AC\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097F\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C33\u0C35-\u0C39\u0C3D\u0C58\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D60\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191C\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2183\u2184\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005\u3006\u3031-\u3035\u303B\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA697\uA6A0-\uA6E5\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA793\uA7A0-\uA7AA\uA7F8-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA80-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC\u0E01-\u0E3A\u0E40-\u0E4F\u0E5A\u05B])[\W]/g;

Binary file not shown.

View file

@ -0,0 +1,77 @@
# Dataviews
Before we get into Dataviews - here are some captured describing where this page could use some additional work and if the content:
"we really need to fill it out and organize it in a way that benefits new engineers and also our designers so they know what is easy to do vs what is an unsupported pattern. It would also be good to understand any roadmap requests they have for the improvements of Dataviews, and fixing known problems (interactions with KOs and loops for instance)."
"We need to better document the behavior of our Dataviews and what they are capable of. This will allow us to speed up development, have better conversations with Design, and plan for how we want to make improvements for them going forward. We also need to gather the growing list of known issues with data views to understand if there are holistic changes we can make to the infrastructure to create better experiences."
---
# How to make content vary within a question
## Outside of Loops
You can use standard facts within dataview questions and answers.
You can have content vary for MFJ by adding `_spouse` to the end of the string name, and it will be automatically used.
Otherwise, DataViews are limited. You can't specify the same context indicators you can for screen titles/questions, so be wary if you find you are mapping multiple strings to a single variable; you'll need to keep the dataview question generic to handle all cases, and that isn't a great practice to show a different question than the one you asked on the screen.
EXAMPLE
## Within Loops
Within loops the same rules as above apply, but you can also use facts related to the current filer. But you must use their name, not a pronoun.
For instance, this works:
`This is the answer for `_`PrimaryFirstName`_
`This is the answer for `_`SecondaryFirstName`_
This does not:
`This is the answer for `_`you`_
`This is the answer for `_`SecondaryFirstName`_
EXAMPLE
# How to make content vary within an answer
You can use the `i18nKeySuffixContext` along with conditions to vary the content displayed for a fact on the screen, but beware that we have limited ability to use conditional context in data-views.
For the most part, you are tied to the answers that were posed in the original screen.
There are ways around that, but they require custom code.
EXAMPLE
# How to hide a question on the data view
Use the displayOnlyOn property set to 'edit'. (e.g.`displayOnlyOn='edit'`)
EXAMPLE:
```
<LimitingString
path='/formW2s/*/filer/lastName'
readOnly={true}
displayOnlyOn='edit'
hintKey='/info/income/w2/why-change-name'
condition='/formW2s/*/filer/isPrimaryFiler'
/>
```
# How to show text only on the data view
Use a Generic String with the displayOnlyOn property set to 'data-view'. (e.g.`displayOnlyOn='data-view'`)
The string should be inserted in the flow sub or subsub category where you want it to appear.
EXAMPLE:
```
<GenericString path='/hsaDistributions/*/filer/fullName' displayOnlyOn='data-view' batches={[`hsa-1`]} />
```

View file

@ -0,0 +1,31 @@
# Writing facts
- Modules don't have any actual meaning, they're just a tool for organizing code
- The fact dictionary files eventually all compile down to one big dictionary
## examples of using dependencies in a fact
This establishes the context for the fact, in this case we're looking inside the "filers" collection:
```
<Fact path="/filers/*/hsaContributionsTotal">
```
This is a fact that lives outside the "filers" collection, so we don't use a relative path. It's being imported from the "filingStatus" module:
```
<Dependency module="filingStatus" path="/isFilingStatusMFJ" />
```
This is a fact that lives inside the "filers" collection, but is written in a different file:
```
<Dependency module="filers" path="../isSecondaryFiler" />
```
This is a relative path because it exists inside the "filers" collection. It is written in the filers.xml file, but that doesn't matter because we're already working within the filers collection so we have access to everything in that collection regardless of which module/file it is in:
```
<Dependency path="../isSecondaryFiler" />
```
This is a path for a fact that is written in the same file where it is being called. It is not a relative path because it exists outside the "filers" collection, but it does not need a module because it is in the current file:
```
<Dependency path="/secondaryHsaContributionsTotal" />
```

View file

@ -0,0 +1,30 @@
# Testing in the Direct File Client App
The Direct File client app has many steps for completing a tax return, making manual testing and bug reproduction time-consuming. These tools help streamline the process.
## Dev-Only Control Panel
<img width="673" alt="Screenshot 2025-05-23 at 10 08 03 AM" src="https://github.com/user-attachments/assets/5e098552-bd0d-448c-bde1-6b41d279ac7e" />
Access the control panel at `/df/file/account/` for development settings and data management:
- **Change date** - Set browser date to test deadline-related functionality
- **Data Import Profile** - Modify seeded test data (like date of birth) that can't be changed in the normal tax flow during local development
- **Download Data** - Export fact graph as JSON for attaching to pull requests or bug reports
- **Upload Data** - Import fact graph to quickly navigate to specific application states when testing PRs or reproducing bugs
- **Preview Tax Return** - View backend tax return preview
- **Load Preach UUID** - Load specific Preach configurations
## All Screens
<img width="1279" alt="Screenshot 2025-05-23 at 10 09 05 AM" src="https://github.com/user-attachments/assets/7fd2966f-4627-48d9-b8ad-0b3f2c8bbab8" />
Navigate to `/df/file/all-screens/index.html` to view all application pages in one location.
This page displays every screen in the tax flow and post-submission pages. Use the menu to filter and manipulate the view. Generate a PDF by pressing "p" and using the [Just-One-Page-PDF Chrome extension](https://chromewebstore.google.com/detail/just-one-page-pdf-an-awes/fgbhbfdgdlojklkbhdoilkdlomoilbpl?hl=en&pli=1).
## Flamingo Fact Checker
![418692897-164c00a1-b5ff-4280-b201-3be144dbc2a6](https://github.com/user-attachments/assets/001daa15-19c0-4729-bb08-342d66db9283)
Use the [Flamingo Fact Checker](df-tools/Flamingo-Fact-Checker.md) to monitor specific fact values as you progress through the tax flow.

View file

@ -0,0 +1,771 @@
# ****PRODUCT OVERVIEW****
# **Product one-pagers for TY2024**
One page overviews created by the product design team for use by the customer support team. At the end of each sprint, product teams would document the 101 of any new taxpayer-facing features or updates so that Customer Support can start developing training and content.
## **Alaska Permanent Fund Dividend (Form 1099-MISC)**
Taxpayers from Alaska:
* Will now have the ability to add their Alaska Permanent Fund Dividend (Form 1099-MISC) in Direct File
* With 1099-MISC income that is not from the Alaska Permanent Fund will not be able to use Direct File
* Who received income from a state other than Alaska during 2024 they will not be able to use Direct File
* That have a child who needs to report their Alaska Permanent Fund Dividend (1099-MISC) cannot yet do that in Direct File. This is because reporting a child's unearned income requires either of the below forms, both of which are currently out of scope:
* Form 8814, Parent's Election to Report Child's Interest and Dividends **OR**
* Form 8615, Tax for Certain Children Who Have Unearned Income
* Taxpayers who do not live and earn income exclusively in Alaska cannot report a PFD or any other form of income on the 1099-MISC.
* The Alaska Permanent Fund Dividend can also be referred to as “PFD,” or “the dividend”
### **Navigation**
*How do you navigate to this screen in the Direct File experience?*
For now, taxpayers will only be able to add the Form 1099-MISC **only** if it is for an Alaska Permanent Fund Dividend.
In the **About You** section, the taxpayer will:
1. Indicate if they are an Alaskan resident
2. Confirm if they received an Alaska Permanent Fund Dividend
If both of the above are true, then the taxpayer will have an Alaska Permanent Fund Dividend sub-section listed in the checklists Income section.
### **Likely TP questions & answers**
*What questions might taxpayers be asking Customer Support here? And preliminary short answer?*
| Question | Answer |
| ----- | ----- |
| Why cant I report my childs Alaska Permanent Fund Dividend in Direct File? | This year, the PFD dividend amount of $1,702 (it changes annually) triggers the [kiddie tax](https://www.irs.gov/taxtopics/tc553). In practical terms this means the unearned income range for children to report their taxes for 2024 is $1300 to $13,000, and the PFD will be more than $1300. The kiddie tax requires either form 8814 or 8615, neither of which Direct File supports this year. \*\*\*see extra note under visual aids |
| How do I get my Alaska Permanent Fund Dividend (Form 1099-MISC) for tax purposes? | If the TP successfully [applied](https://mypfd.alaska.gov/closed) for and received the PFD, they can get their Form 1099-MISC income tax statement the through [myPFD](https://myinfo.pfd.dor.alaska.gov/). |
| Do I need to report my Alaska Permanent Fund Dividend if it's garnished? | Even if part or all of the dividend was garnished, the entire amount of the dividend must be reported as taxable income. |
| Is the entire payment taxable? | Yes, the entire payment in taxable. |
| How would I report if I used my PFD for a charitable donation or college savings plan? | Taxpayers would include whatever portion of the PFD they moved to a charitable donation or tax-deferred college savings plan as an itemized deduction. This is currently out of scope for Direct File, which only supports the standard deduction. |
| Is the 2024 Energy Relief Payment included in the dividend distribution? | Yes, the Dividend and Energy Relief are combined as one payment. |
| Is the energy relief payment portion of the PFD taxable?' | The 2024 Permanent Fund Dividend amount is $1,702. This amount includes the Alaska dividend distribution of $1,403.83 and a one-time energy relief payment of $298.17.The entire $1,702 is taxable for federal income tax purposes. |
## **Retirement income Form 1099-R**
Taxpayers will now have the ability to add some pension and annuity income (Form 1099-R) in Direct File starting in March **2025\.** This is the template [Form 1099-R](https://www.irs.gov/forms-pubs/about-form-1099-r) that the TP will be using to fill out DF.
**Before March 2025**
If a taxpayer indicates they have any 1099-R income, they will be told that they can't use Direct File yet, but that the feature will be available in March.
**After March 2025**
Taxpayers will be able to file returns with 1099-R income within the Supported Income Types listed below. Taxpayers who were previously told they were ineligible because of this income should be able to complete and file their return.
### **Supported Income Types**
*Briefly describe the new feature and how it impacts the taxpayers experience.*
* Form 1099-R is used to report a variety of income types, only some of which will be supported by Direct File this year
* Supported income types include 1099-R forms where the Box 7 **Distribution code** matches any one of the following options, unless any of the exclusions in "Unsupported income types" applies below:
* 2
* 7
* G
* H
* 2B / B2
* 7B / B7
* Unsupported income types
* BG / GB
* 4G / G4
* 4H / H4
* 1099-R income where box 2a **Taxable amount** is left blank
* 1099-R income where box 2b **Taxable amount not determined** is checked
* Lump sum distributions for taxpayers born before January 2, 1936 (would require the unsupported form 4972\)
* 1099-R income where box 3 **Capital Gain** has a nonzero value
* 1099-R income where box 6 **Net unrealized appreciation in employers securities** has a nonzero value
* 1099-R income where the **IRA / SEP / SIMPLE** box is checked
* 1099-R income where box 7 **Distribution Code** has a value other than those listed in the supported income types
* 1099-R income with a taxable amount in box 2a as part of a rollover (box 7, codes that include G or H)
* 1099-R income that the taxpayer rolled over after receiving the distribution. Note that direct rollovers are supported.
* 1099-R income that qualifies as a disaster recovery distribution
* Distributions to public safety officers to pay for premiums for accident, health, or long-term insurance.
* 1099-R income where box 8 **Other** has a value greater than $0
* 1099-R income where box 10 **Amount allocable to IRR within 5 years** has a value greater than $0.
* 1099-R income where box 12 **FACTA Filing requirement** is checked
* 1099-R income where box 13 **Date of payment** is not left blank.
* 1099-R income where the State listed in box 15 does not match the taxpayer's income and residence state, unless the 1099-R is for a nontaxable rollover with no state withholding:
* Allowed situations:
* Box 15 is blank
* Box 15 state matches the filer's income \+ residence state
* Box 15 state doesn't match the filer's income \+ residence state but the 1099-R box 7 distribution code includes `G` or `H`
* All other 1099-Rs with a value for box 15 are not in scope.
### **Navigation**
Taxpayers are asked to report retirement income / 1099-Rs in the Income section, after interest income. If taxpayers do not have any to report, they can proceed by choosing the **`I don't have any 1099-Rs to report` option.**
### **Rejection reasons**
The following new rejection reasons may be experienced by taxpayers who report 1099-R income:
| Rejection code | Meaning | Recommended action |
| ----- | ----- | ----- |
| F1099R-002-01 | Payer Address in form 1099-R is missing the State | Check 1099-Rs to ensure payer address is correct. If on review, all 1099-Rs have a State saved in the payer address, report a possible bug. |
| F1099R-003-01 | Payer Address in form 1099-R is missing the Zip Code | Check 1099-Rs to ensure payer address is correct. If on review, all 1099-Rs have a zip code saved in the payer address, report a possible bug. |
| F1099R-004-01 | Payer Address zip code is invalid for the state reported on the 1099-R | Check 1099-Rs to ensure payer address is correct. If on review, all 1099-Rs have the same zip code shown on the form 1099-R they received, they may need to request a corrected 1099-R from the payer. |
| F1099R-005 | Only applies when the **FATCA filing requirement** box is checked on a 1099-R. This should not happen given our TY 2024 scope. | If encountered, please report as a bug. |
| F1099R-499-02 | Payer EIN is invalid | Taxpayer should check the EIN on each 1099-R reported in Direct File and ensure the EIN matches the 1099-R they received from the payer. If, after review, it still appears correct, taxpayer may need to contact their payer to get a corrected 1099-R with the correct EIN. If the taxpayer is certain the EIN is correct, report as a possible bug. |
| F1099R-502-02 | Payer EIN is incorrect | Taxpayer should check the EIN on each 1099-R reported in Direct File and ensure the EIN matches the 1099-R they received from the payer. If, after review, it still appears correct, taxpayer may need to contact their payer to get a corrected 1099-R with the correct EIN. If the taxpayer is certain the EIN is correct, report as a possible bug. |
| F1099R-505-02 | Payer EIN is incorrect | Taxpayer should check the EIN on each 1099-R reported in Direct File and ensure the EIN matches the 1099-R they received from the payer. If, after review, it still appears correct, taxpayer may need to contact their payer to get a corrected 1099-R with the correct EIN. If the taxpayer is certain the EIN is correct, report as a possible bug. |
### **Likely taxpayer questions & answers**
*What questions might taxpayers be asking Customer Support here? And preliminary short answer?*
| | Question | Answer |
| ----- | ----- | ----- |
| 1 | **I have an IRA. Can I use Direct File?** | You won't be able to use Direct File if you took a distribution from an Individual Retirement Arrangement (IRA) or if you contributed to an IRA during the tax year. This includes any type of IRA (traditional, Roth, SEP/SIMPLE). You may be able to use Direct File if you rolled over a retirement plan into an IRA, as long as it wasn't a conversion from a pre-tax to post-tax retirement plan. (For example: if you had a pre-tax 401(k) and rolled it over into a pre-tax IRA, you may be able to use Direct File. But if you rolled it over into a Roth (post-tax) IRA, you won't be able to use Direct File this year.) |
| 2 | **My 1099-R doesn't include an "Account Number" box. What do I put in Direct File?** | If your 1099-R doesn't include a piece of information that Direct File asks for (like "Account Number"), then leave it blank in Direct File. If Direct File tells you that it's required to answer that question, then you'll need to contact your payer for a corrected form. |
| 3 | **My 1099-R shows a box that Direct File didn't ask me about. Where do I put that info?** | Sometimes payers will include extra information on your 1099-R that you don't need to report in Direct File. However, there are a few things to check for before continuing on in Direct File. First, make sure that your form says 1099-R at the top, not RRB-1099-R. Next, make sure that you've gone through all the 1099-R questions in Direct File (some 1099-Rs are printed in a different order than what you'll see in Direct File). If you've confirmed both of those things, then you don't need to input any extra information that was included on your 1099-R in Direct File, and you can proceed to the next step. |
| 4 | **Update the existing KA "State residency and work** location eligibility for Direct File (irs.gov)" | *Note: add 1099-R (and other new in-scope types of income) to last year's question. For 1099-R check if Box 15 shows a different state than where you worked and lived in 2024\. Unless your 1099-R was reporting a rollover, you may be ineligible to use Direct File this year.* |
| 5 | **My 1099-R shows an amount in Box 2a "taxable amount," but Box 2b "taxable amount not determined" is also checked. Is that an error?** | If you have an amount in Box 2a but also the "taxable amount not determined" box is checked in Box 2b, that may mean this distribution was from an Individual Retirement Arrangement (IRA). Direct File doesn't support IRAs right now, so you'll have to find another tool (\<LINK\>). If you know that your distribution isn't from an IRA, then your payer may have made an error on your 1099-R. You should reach out to them to confirm the situation and get a corrected 1099-R. |
| 6 | **What do I do if I received Form 5498?** | **If you received Form 5498 before you filed your taxes**: Receiving Form 5498, you have an IRA. Direct File doesn't support contributions to, distributions from, or recharacterizations of IRAs. If any of those situations apply to you, you'll need to use another tool to file your federal taxes \<\<LINK\>\>. **If you received Form 5498 after you filed your taxes and you need to update your return:** \[Use the same language that we have in other KAs for amending a return.\] |
| 8 | **How do I report income for someone who's not me or my spouse?** | *(Note: this answer will probably apply to all types of income, including W-2, 1099-R, 1099-INT, Alaska Permanent Fund, etc. The answer should be drafted & confirmed with Counsel to make sure we're being accurate for all income types that DF supports. Keywords: dependent, child, son, daughter, mom, dad, parent, disabled, disability).* |
| 9 | **If I contributed to a SEP or SIMPLE IRA, can I use Direct File?** | If your IRA contribution is reported on your W-2 in Box 12 (Code F or S), you can use Direct File. If you made any contributions to an IRA that aren't reported on your W-2, you'll need to file your federal return using another tool \<\<LINK\>\> |
## **Interest Income requiring Schedule B**
Tax payers with more than $1,500 of interest or dividend income are *required* to file a Schedule B. In the previous tax-year, these tax-payers were not supported in Direct File.
For TY 2024 we've added support for tax payers who are required to file a Schedule B, but only the most common situations.
### **Supported tax situations**
* Tax payers with more than $1,500 of interest reported on 1099-INT(s)
### **Unsupported tax situations**
* Any dividend income (**1099-DIV**)
* Amortizable bond, interest, and premiums (**1099-INT**) including: Specified Private Activity Bonds & Interest, Market Discounts, Tax-Exempt bonds
* Original issue discount treated as interest income (**1099-OID**)
* Foreign income, accounts, or trusts **FBAR**:
* Tax payers with ownership or transactions with foreign assets or accounts may be required to file additional forms with the IRS and other authorities. (Those forms are not supported in Direct File)
* Failure to file those forms could result in penalties.
* Seller financed mortgage interest (**1099-INT & 1098**):
* Tax payers who receive interest income from a seller financed mortgage are required to provide detailed information about the payer of that interest (including name, address, SSN, and use of property).
* Tax payers are also required to issue Form 1098 to payers of seller financed mortgage interest.
* There may be penalties associated to improper reporting of this tax situation
* Nominee interest (**1099-INT & 1096**)
* Tax payers acting as nominees (receiving interest on behalf of another) are required to issue forms to the owner of the interest as well as file additional forms to the IRS
* Excludable interest (**1099-INT**)
* Tax payers with excludable interest from Series EE or I bonds used for education must file additional forms to the IRS those forms are not supported in direct file)
* This is a very rare case
* Tax exempt interest (**1099-INT**)
### **Navigation**
*How do you navigate to this screen in the Direct File experience?*
(Step-by-step navigation is helpful, taxpayers ask for this often)
1. Start your return
2. Complete "You and your family"
3. Complete "Income sources"
4. Complete "Jobs"
5. Begin "Interest Income"
6. Add 1099-INT(s)
7. Done\!
### **Likely TP questions & answers**
*What questions might taxpayers be asking Customer Support here? And preliminary short answer?*
| Question | Answer |
| ----- | ----- |
| Does Direct File support interest income? | Yes, DF supports interest income of any amount. Interest income below $1500 does not require any additional forms Interest income above $1500 does require Schedule B to be filed |
| Am I required to file Schedule B? | Schedule B is *required* if *any* of the following apply: Over $1,500 in taxable interest or dividends Seller-financed mortgage interest Accrued bond interest Original issue discount adjustment (OID) Amortizable bond premiums Excluding savings bond interest Received nominee interest or dividends Have foreign accounts or trusts [https://www.irs.gov/forms-pubs/about-schedule-b-form-1040](https://www.irs.gov/forms-pubs/about-schedule-b-form-1040) |
| Does Direct File support my tax situation? | Direct File only supports the interest income earned by the tax payer themselves and reported on form 1099-INT. Direct File *does not* support the tax situations listed above |
| Can I still use Direct File if my situation is unsupported? | Unfortunately, no. But we can point you to many other ways to file your federal taxes. |
## **Premium Tax Credit (PTC)**
The Premium Tax Credit serves as a tax credit aimed to offset the cost of health coverage for individuals who qualify and buy health insurance through Healthcare.gov or a state Marketplace.
The user qualifies for the credit if:
* Their health insurance plan is purchased through Healthcare.gov or a state Marketplace.
* Their household income falls between 100% and 400% of the federal poverty level for your household size.
* They don't file as Married Filing Separately (with exceptions for victims of domestic abuse and spousal abandonment).
* They can't be claimed as a dependent by another person.
If you qualify, you can either take your tax credit as a monthly subsidy to help pay for your insurance costs or claim the entire credit when you file your tax return.
Once they make their decision, we will use the details from their 1095-A to determine your Premium Tax Credit and complete Form 8962 to submit with their tax return.
### **TL;DR: Whats New for TY 2024?**
* **New Eligibility Group:** Taxpayers with Form 1095-A will now be able to check eligibility for the Premium Tax Credit (PTC).
* **Expanded Form Support:** Taxpayers can file Form 8962 for claiming PTC and reconciling advance payments of the Premium Tax Credit (APTC).
* **Enhanced User Guidance:** Taxpayers with changes in circumstances (unreported to the Marketplace) can now get guidance for looking up the second-lowest-cost Silver plan (SLCSP) premiums.
### **In Scope for TY 2024**
For the 2024 tax season, Direct File will allow taxpayers to:
1. **Claim the Premium Tax Credit (PTC)** Taxpayers with 1095-A forms can use Direct File to determine eligibility for the PTC.
2. **Reconcile Advance Payments** Taxpayers can reconcile their advance payments of the Premium Tax Credit (APTC) and calculate any repayments required.
3. **File Form 8962** Direct File will guide taxpayers through filing Form 8962 to claim their PTC or reconcile APTC.
---
### **Out of Scope for TY 2024**
Some taxpayer scenarios are **not** supported by Direct File this year due to complexity:
#### **Taxpayer Type Scenarios**
* Self-Employed Taxpayers
* Nonresident Taxpayers (Form 1040-NR)
* Taxpayers with Dependents Who Have a Filing Requirement
#### **Form-Specific Scenarios**
* Multiple Forms 1095-A
* Policy Allocations Between Multiple Tax Families (Form 8962, Part IV)
* Alternative Calculation for Year of Marriage (Form 8962, Part V)
#### **Specific Coverage Types**
* Employer-Sponsored Plan Coverage (QSEHRAs and ICHRAs)
* Taxpayers with Ineligible Immigration Status
### **Error Handling & System Messages**
When a taxpayer encounters an unsupported scenario (e.g., multiple 1095-A forms or self-employment income), Direct File will display the following “knockout” message, rationale, and prompt the tax payer to exit the return.
### **Likely Frequently Asked Questions**
| Question | Answer |
| ----- | ----- |
| What is the Premium Tax Credit (PTC)? | The PTC is a refundable tax credit designed to help eligible individuals and families pay for health insurance premiums purchased through the Health Insurance Marketplace. |
| Who is eligible for the Premium Tax Credit? | Eligibility is based on your income level, household size, and whether you obtain insurance through the Marketplace. Generally, your income must be between 100% and 400% of the federal poverty level. |
| How do I claim the Premium Tax Credit on my tax return? | If you are eligible to claim the PTC, answer the prompted questions to complete Form 8962, Premium Tax Credit, and it will be included with your federal tax return (Form 1040). |
| What information do I need to complete Form 8962? | You need your Form 1095-A, Health Insurance Marketplace Statement, which provides details on your insurance coverage, premium amounts, and advance payments of the PTC. [Instructions on How to Find your 1095-A Online](https://www.healthcare.gov/downloads/how-to-find-form-1095-a-online.pdf) |
| What if I received advance payments of the Premium Tax Credit (APTC)? | If you received APTC during the year, you must reconcile the amount paid to you with the actual credit you qualify for by completing Form 8962\. |
| What happens if my APTC is more than my actual PTC? | If your APTC is higher than your PTC, you will need to pay back the excess amount. This will be reflected as an additional tax on your return. |
| What if my income changes during the year? | Any significant change in your income or family size may affect your PTC amount. Report changes to the Marketplace as soon as possible to adjust your APTC. |
| How do I calculate my modified adjusted gross income (MAGI) for PTC eligibility? | MAGI is your adjusted gross income (AGI) with certain deductions added back in. This includes non-taxable Social Security benefits, tax-exempt interest, and excluded foreign income. |
| Can I qualify for PTC if I am eligible for employer-sponsored insurance? | Generally, you are not eligible for PTC if you have access to affordable employer-sponsored insurance that meets the minimum standards. |
| Can I claim PTC if Im married but filing separately? | Generally, married individuals must file a joint return to claim PTC. There are some exceptions, such as for those who are victims of domestic abuse or spousal abandonment. |
| What if I did not receive Form 1095-A? | You should contact the Marketplace where you purchased your insurance to request a copy. Form 1095-A is crucial for completing your tax return. |
| Can I claim the PTC if I am a dependent on someone elses tax return? | No, dependents cannot claim the PTC. Only taxpayers who are not claimed as dependents and meet other eligibility criteria can claim the credit. |
| What if I owe back taxes? | Will my PTC be used to pay them? The PTC is refundable, meaning you can receive the credit even if you owe no tax or have unpaid back taxes. However, the IRS may apply it to other federal tax liabilities. |
| Is the PTC affected by my states Medicaid expansion status? | Yes. If your state has not expanded Medicaid and your income is below 100% of the federal poverty line, you may not be eligible for PTC. |
| Can I apply the PTC to cover other members of my household? | Yes, the PTC can cover health insurance premiums for members of your tax household, which includes dependents and other covered individuals listed on your tax return. |
| What if I only had Marketplace coverage for part of the year? | You will calculate your PTC based only on the months you had Marketplace coverage. This can result in a prorated credit. |
| What happens if I didnt file a tax return last year? | If you received APTC last year, you must have filed a return to reconcile your credit. Failure to file a tax return will make you ineligible for APTC in the following year. |
| How does my household size affect my PTC? | Your household size, which includes all individuals listed on your tax return, is used to determine your federal poverty level and eligibility for the PTC. |
| What if my APTC is zero on my form 1095-A? | If your APTC is listed as zero, you did not receive any advance payments, but you may still be eligible for the PTC based on your actual income as you answer the questions to complete Form 8962\. |
| Where do I find the second lowest cost Silver plan (SLCSP) amount? | The SLCSP premium is provided on your Form 1095-A in Part III. If the SLCSP information is missing or incorrect, use the Health Insurance Marketplace's tool to find the correct amount. |
## **About You Data Import**
About You and IP PIN data import will be live for all taxpayers at the start of the tax filing season.
Rather than asking taxpayers to enter their basic biographical information after providing it to ID.me, we will be importing that data and showing it to the taxpayer to confirm. They can edit some of the information if they wish.
The information we will prepopulate from ID.me is:
* Name
* Date of birth (New from last year: cannot edit)
* Mailing address
* Phone number
* Email address (Already prepopulated, cannot edit)
* SSN or ITIN (New from last year: cannot edit)
* IP Pin (from TP's online account)
For IP Pins:
* This is only for the primary filer, not the spouse or dependents
* If the TP does not have an IP PIN on file, we will not show them the page to input their IP pin
* If the TP does have an IP PIN on file, we will import it from their online account
* If we aren't able to connect to the IP PIN service to know if they have one or not, we will default to last year's flow (asking the TP if they have one and to input it if they do)
Biographical information comes from our "SADI" integration (which provides us what the taxpayer provided to ID.me) and the IP PIN comes from the IRS "IP PIN" service integration.
### **Likely TP questions & answers**
*What questions might taxpayers be asking Customer Support here? And preliminary short answer?*
| Question | Answer |
| ----- | ----- |
| Where did you get this information from? How does the IRS know this information? | You gave IRS information, like your Social Security number or ITIN and your mailing address, when you signed up to use Direct File or an IRS Online Account in ID.me. |
| How do I edit this information if it's wrong? | To edit your name or mailing address, select the "Edit" link to the right of "Your basic Information." To edit your mailing address or phone number, select the "Edit" link to the right of "Your contact information." You cannot edit your email address, date of birth, or your Social Security Number or ITIN. |
| Why can't I change my email address? | Your email address is pre-filled with the email address you used to register for an ID.me account. You cant change the email using this product. [Visit ID.mes Help Center to learn how to change your email address.](https://help.id.me/hc/en-us/articles/360011500573) |
| What can't I change my SSN or ITIN? | You gave the IRS your Social Security number or ITIN when you signed up for an ID.me account to use Direct File or your IRS Online Account. You can't change your SSN or ITIN in Direct File unless you change your SSN or ITIN in ID.me first. This helps prevent identity theft. |
| Why can't I change by date of birth? | We filled in your date of birth with the date of birth you used when you signed up for an ID.me account. If your date of birth is incorrect, visit ID.me's Help Center to learn how to change it. If you're trying to change the date of birth because you want someone else to be the primary filer, you won't be able to. If you're filing with a spouse and want them to be the primary filer, they'll need to sign up for Direct File and log in using their account. If you're filing a tax return for a child who's over 18 years old, they'll need to sign up for Direct File and log in using their account. If you're trying to file a tax return for a child who is under 18 years old, youll need to file using another tool. Provide link to find other ways to file their federal taxes. **Internal note:** If the TP makes a change in ID.me, it will not automatically flow into DF. We will need to reset on our end. Please reach out to the data import team if this rare case occurs. |
| How can I change my email address, DOB, or SSN or ITIN? | If you need to change your SSN or ITIN, contact ID.me, then try signing in to Direct File again. **Internal note:** If the TP makes a change in ID.me, it will not automatically flow into DF. We will need to reset on our end. Please reach out to the data import team if this rare case occurs. |
| What if I'm trying to file a tax return for someone else? | You can only file as a federal tax return as the primary filer since we used ID.me to verify your information. If you are filing with a spouse and would like them to be the primary filer, they will have to sign up for Direct File and file your federal tax return from their account. If you are trying to file a return for your child who is under 18 years old, youll need to file using another tool. If they are over 18 years old, they can sign up for Direct File and file a federal tax return from their account. |
| I had a legal name change but that change isn't reflected in my SSN/I didn't communicate with SSA to change my name in my SSN. What name should I use in this year's tax return? | [Name changes & Social Security number matching issues | Internal Revenue Service](https://www.irs.gov/faqs/irs-procedures/name-changes-social-security-number-matching-issues#:~:text=my%20name%20corrected%3F-,Answer%3A,use%20to%20file%20your%20return.) If your W-2 uses a different name then what is entered in the “About You” section. In the “About You” section, be sure to use the name that matches your Social Security or ITIN paperwork. If your W-2 lists a different name than what you listed in the “About You” section (for example, it uses your maiden name or a different middle initial), thats OK. You don't need to request a corrected W-2 in these cases. What do I use for my middle initial if I have multiple middle names? Enter your name exactly as it appears on your Social Security or ITIN paperwork. For example, if your Social Security card displays your middle name as an initial, use the middle initial thats listed on your Social Security card in Direct File. I recently changed my name. What do I enter in Direct File? Use the name that matches your most updated Social Security or ITIN paperwork. You'll know your name is updated when you receive the paperwork. For example, if you have a new name but haven't changed your name with the Social Security Administration yet, you'll need to use your former name on the tax return. |
| I changed my name via US naturalization. Has my name changed with the SSA as well? What name should I use in my tax return? | Use the name that matches your most updated Social Security or ITIN paperwork. You'll know your name is updated when you receive the paperwork. For example, if you have a new name but haven't changed your name with the Social Security Administration yet, you'll need to use your former name on the tax return." |
| I am getting a rejection for an incorrect signing pin, but I can't see that page \- how do I fix that reject? | **Internal note:** This occurs because you or your spouse input an IP PIN when you didn't have one. Go to the IP PIN page, remove your IP PIN, and resubmit. |
| What should I do if I get a rejection about my DOB (IND-524) or social security number or IP PIN (IND-180-01) that I can't resolve? | If your date of birth is incorrect, visit ID.me's Help Center to learn how to change it and then we can help you resubmit. **Internal note:** If the TP makes a change in ID.me, it will not automatically flow into DF. We will need to reset on our end. Please reach out to the data import team if this rare case occurs. If the TP has an imported IP PIN that is incorrect and leads to a rejection (which should be rare), please reach out to the data import team to resolve. |
## **W2 Data Import**
We plan to launch this feature at the start of the tax season to a limited percentage of taxpayers to start and will increase the percentage from there.
In order to help make it easier and more accurate for taxpayers to file their tax return, we will allow them to choose to import W-2 information the IRS has on file for them. For taxpayers selected for our pilot:
* Taxpayers will be able to opt in to this feature
* They will see a summary page with the W-2 information we have on file and they can select to import one or more of those W-2s or choose not to import those W-2s and manually enter their own as they do today.
* Once the taxpayer imports a W-2, they will be able to view the information on the W-2 or remove it from their tax return.
* We are not able to import Box 12, Box 14, and state tax information (Box 15-20) because that is not in our data source at the IRS from the SSA
For a select percentage of taxpayers, they will see the opportunity to import W-2 information at the start of the "jobs" screens.
### **How will CS know if the TP is using data imported vs. manual entry?**
CS can ask taxpayers if they selected any W-2s that were already available to import rather than typing it in manually. If more confirmation is needed, reach out to the data import team who can look up on our end whether they imported data. Suggested ways to ask:
* Was a W-2 available for you to select when you reached the section where you input your jobs and W-2 income information?
* Was there a box to check to bring in / import / select a W-2 with information already provided?
### **Likely TP questions & answers**
*What questions might taxpayers be asking Customer Support here? And preliminary short answer?*
| Question | Answer |
| ----- | ----- |
| Where did you get my W-2 information? | Your employer reports your Form W-2 information to the federal government every year. This information is what IRS has on file for you. |
| What if I think something is incorrect on my W-2? | If any of the information on your W-2 isn't correct, reach out to your employer and ask for an updated W-2. For now, please enter a new W-2 manually with the correct information. |
| How do I edit my W-2 information? | Taxpayers can edit their W-2 information after they import their W-2. After importing the W-2, there is a summary screen where taxpayers can choose to "edit" information. |
| What if one of my W-2s is missing? | Here are some reasons why a Form W-2 might be missing from the list: **Your employer submitted your W-2 information to the federal government, but the IRS didn't get it yet.** Most W-2s are submitted to the federal government by January 31\. **You made less than $600 with an employer in this tax year**, so your employer isn't required to file a W-2 for you. You're still required to report all of your income. **We can only import standard W-2s**. If you have a nonstandard W-2 (handwritten, altered, or typed on a typewriter), we can't import it for you. If you have a Form W-2c (a corrected W-2), review the W-2 we imported for you to make sure the information is up to date. **We only support importing your W-2s, not your spouse's.** You can manually add your spouse's W-2s later on. If your W-2 isn't in this list, you can manually add your W-2. |
| How do I remove an imported W-2 after I imported it? | You can remove a W-2 you imported by clicking the "Remove W-2" option at the top of the W-2 Review screen (after importing a W-2). |
| What if I havent received a W-2 Im expecting yet? | If you haven't received a W-2 you're expecting, contact your employer. If you still havent received the missing form(s) by the end of February, call the IRS at 1-800-829-1040 for help |
| Where is my spouses W-2(s)? How do I add them? | Direct File can only import W-2s for the primary filer. You have to manually enter in your spouse's W-2s by clicking "Add W-2". |
| (on Import page) What if I want to review my W-2 information before importing? | You will be able to review all the information we imported from your W-2(s) after importing. You can make any edits or remove your W-2 as needed. |
| When was this information imported? What if something has changed since then? | When you first started your tax return with Direct File, we imported the information the IRS had on file from the SSA and your employer at that time. If something has changed since then, please make the change yourself by "editing" your W-2. |
| What is my name or address does not match the name or address on my Direct File account? | **Incorrect last name** If the last name on the W-2 doesn't match the name on the federal tax return, your return could be delayed or rejected. Request a corrected W-2 from the employer before you file your return in Direct File. If you still havent received the corrected form(s) by the end of February, call the IRS at 1-800-829-1040 for help **Incorrect first name or middle initial** If the first or middle initial are incorrect on the W-2 (for example, it uses a nickname), you can continue filing your return with this W-2. You don't need to request a corrected W-2. |
##
## **1099-INT Data Import**
In order to help make it easier and more accurate for taxpayers to file their tax return, we will allow them to choose to import 1099-INT information the IRS has on file for them. For taxpayers selected for our pilot:
* Taxpayers will be able to opt in to this feature
* They will see a summary page with the information we have on file and they can select to import one or more of those forms or choose not to import those 1099-INTs and manually enter their own as they do today.
* Once the taxpayer imports a 1099-INT, they will be able to view the information on the form or remove it from their tax return.
* We are not able to import Box 12, Box 14, and state tax information (Box 15-20) because that is not in our data source at the IRS from the SSA
For a select percentage of taxpayers, they will see the opportunity to import 1099-INT information at the start of the "interest income" screens.
### **Likely TP questions & answers**
*What questions might taxpayers be asking Customer Support here? And preliminary short answer?*
| Question | Answer |
| ----- | ----- |
| Where did you get my 1099-INT information? | This information is what IRS has on file for you that is reported by your interest income payer. |
| What if I think something is incorrect on my 1099-INT? | If any of the information on your 1099-INT isn't correct, reach out to your payer and ask for an updated form. For now, please enter a new 1099-INT manually with the correct information. |
| What if one of my 1099-INTs is missing? | Here are some reasons why a Form 1099-INT might be missing from the list: **The IRS hasn't yet received your Form 1099-INT from your payer. We only support importing your forms, not your spouse's.** You can manually add your spouse's form later on. If your form isn't in this list, you can manually add your form. |
| Where is my spouses form(s)? How do I add them? | Direct File can only import 1099-INTs for the primary filer. You have to manually enter in your spouse's 1099-INTs by clicking "Add 1099-INT". |
| When was this information imported? What if something has changed since then? | When you first started your tax return with Direct File, we imported the information the IRS had on file at that time. If something has changed since then, please make the change yourself by "editing" your 1099-INT. |
## **1095-A Data Import**
In order to help make it easier and more accurate for taxpayers to file their tax return, and reduce rejections for TPs who don't realize they have marketplace insurance for the PTC, we will be warning TPs if we see that they have a 1095-A in their online account.
* If they have a 1095-A in their account, they'll see a new page telling them they have one and where to get it
* They will also see a warning on the page that asks if they have marketplace insurance
* If the TP definitely doesn't have a 1095-A, we will tell them we think they don't have one.
* Note, we are only checking for the primary filer, not the spouse or their dependents
For a select percentage of taxpayers, they will see these pages in the Premium Tax Credit section
### **Likely TP questions & answers**
*What questions might taxpayers be asking Customer Support here? And preliminary short answer?*
| Question | Answer |
| ----- | ----- |
| Where did you get my 1095-A information? | This information is what the IRS has on file for you in your online account. |
| What if I didnt have a qualified health plan but received a Form 1095-A? | If no one on your tax return had a qualified Marketplace health plan, but someone received a Form 1095-A, the form may have been sent by mistake. Before you file your taxes, youll need to [contact HealthCare.gov](https://www.healthcare.gov/tax-form-1095/) or your [state Marketplace](https://www.healthcare.gov/marketplace-in-your-state/) to correct this mistake by getting a voided Form 1095-A. If you file your federal tax return without first getting a voided 1095-A, the IRS may reject your tax return. |
| Did you check for my spouses or dependents' form(s)? | Direct File can only check for the primary filer's 1095-A form, not their spouse's or dependents. |
| Where do I find my 1095-A in my online account? | Sign in to your online account, scroll down to "Records and Status", click "Information Return Documents", and look for forms under the current tax year (2024). |
If they do have a 1095-A on file:
![product-1-page-1095A-image_1](https://github.com/user-attachments/assets/6abcf431-7387-4607-8ce7-7c605e3a4cc6)
![product-1-page-1095A-image_2](https://github.com/user-attachments/assets/5eb38e01-fb97-4835-9166-183bc41425d6)
If they do not have a 1095-A on file:
![product-1-page-1095A-image_3](https://github.com/user-attachments/assets/c4338d8d-fe9e-47fd-9db0-c50c2483f55c)
## **Health Savings Accounts (HSAs)**
### **Description**
Direct File only supports simple HSA situations.
Situations currently supported in DF:
* For contributions:
* You or your employer contributed to your HSA, and you had the same type of insurance coverage for all of 2024
* For distributions:
* You only used HSA distributions to pay for qualified medical expenses
* You received a Form 1099-SA, and the distribution code is 1
Several exceptions apply. See *Unsupported Cases*, below, for specifics.
### **Tax Forms**
* Taxpayers must file Form 8889 if they had HSA activity in 2024, and in some circumstances if they filed form 8889 in 2023, regardless of activity in 2024\.
* Each filer with HSA activity reports that activity on Form 8889\. (Filers married filing jointly may have 2 Forms 8889, one for each filer)
* If either filer is eligible for an HSA deduction, that gets reported on Schedule 1 (Form 1040), Part II, line 13\.
### **Key facts about HSAs**
Because HSAs are tax-advantaged, there are lots of rules around contributions and distributions. Some highlights…
#### **Contribution rules**
In order to make HSA contributions, you must meet the following requirements:
1. You are covered under a High-Deductible Health Plan (HDHP) on the first day of the month.
2. You have no other health coverage except certain allowed coverage. (Allowed coverage includes accident, disability, dental, and vision. See [Form 8889 instructions](https://www.irs.gov/instructions/i8889) for more.)
3. You aren't enrolled in Medicare.
4. You cant be claimed as a dependent on someone elses \<TY\> tax return.
There is an annual limit for how much a taxpayer can contribute to their HSA each year. The calculation depends on:
* The type of High-Deductible Health Plan (HDHP) coverage you have—For 2024, if you have self-only coverage, your maximum contribution is $4,150. If you have family coverage, your maximum contribution is $8,300.
* Which months you were considered eligible—You're considered having HDHP coverage for all of a month if you had coverage on the first day of the month.
* Your age—If you're age 55 or older at the end of \<TY\>, the contribution limit is increased by $1,000 for your HSA.
If you follow the contribution rules, your contributions aren't taxable income.
2 important concepts:
* Employer contributions vs other contributions
* Employer contributions—Most HSA contributions go through an employer. Either the contribution came from the employer, or it was a pre-tax deduction from your paycheck. These employer contributions are marked on Form W-2, box 12, code W, and are not included in taxable wages.
* Other contributions—In addition, taxpayers can also make contributions that aren't through an employer. For example, they deposited money directly into their HSA through a bank account or check. These amounts get deducted from income through the HSA deduction.
* In 2024 vs for 2024—Taxpayers are allowed to contribute to their HSAs (or remove excess contributions) up to the filing deadline. So if you make a contribution in January 2025, you can choose to assign it for 2024\. As a result, taxpayers file their federal tax return without necessarily having an income tax form that lists the correct amount of their HSA contributions. Therefore, there's more burden on the taxpayer to provide the correct amount.
#### **Distribution rules**
While you're only allowed to contribute to an HSA if you meet certain requirements, you can take a distribution of the funds in an HSA at any time to pay for qualified medical expenses.
* HSA distributions are tax exempt, if they are spent on qualified medical expenses.
* Any distributions not used for qualified medical expenses are taxable and subject to an additional 20% tax. The additional 20% tax doesn't apply to distributions made after the account beneficiary:
* Dies
* Becomes disabled
* Turns age 65
* Generally, qualified medical expenses for HSA purposes are medical expenses that weren't covered by an insurance plan. They include many types of medical expenses (outlined in more detail in Publication 502, Medical and Dental Expenses), as well as some general health expenses like nonprescription medication, tampons and pads, and personal protective equipment like masks and hand sanitizer.
HSA distributions are reported on Form 1099-SA.
### **Direct File Scope for TY 2024**
#### **Who needs to file**
Our HSA questions allow Direct File to support tax situations where filers need to include Form 8889 on their tax return. Form 8889 is needed when:
* A taxpayer, their employer, or someone on their behalf, made contributions for 2024 to their HSA.
* A taxpayer received HSA distributions in 2024\.
* A taxpayer's 2023 tax return received benefits from assuming the taxpayer would be eligible to make HSA contributions throughout 2024, and the taxpayer's eligibility changed.
#### **Noteworthy features**
* Direct File chooses the most advantageous division of HSA contribution limits for married filers based on their actual contributions.
* Generally, filers who are married and have a family HDHP plan split their HSA contribution limit evenly. Some exceptions apply based on filer age.
* Spouses can agree to split that contribution limit differently.
* Filers who use the Married Filing Jointly (MFJ) status where both spouses make HSA contributions may notice that Direct File does not evenly allocate their HSA contributions.
* Direct File will allocate contribution limits for MFJ filers who share a family plan to ensure that the taxpayers receive the maximum deduction on their HSA contributions. This often means that the contribution limits are assigned unevenly.
#### **Unsupported cases**
Direct File doesn't support:
* Changes in marital status or coverage that affect your contribution limit. This includes getting married, not being covered by a High-Deductible Health Plan all year, or switching between self-only and family plans.
* Situations where you owe additional tax.
* Taxpayers who made contributions to their HSA for 2024 but were *not eligible* to make contributions throughout *all* of 2024\.
* Taxpayers who could be claimed as dependents
* Taxpayers who had Medicare for any part of the year
* Taxpayers who had disqualifying coverage for any part of the year
* Contributions to an HSA in excess of the filer's 2024 contribution limit, even if they're withdrawn before \<Tax Day\>. Excess contributions could happen because the taxpayer:
* Contributed over the contribution limit
* Werent actually eligible to contribute
* Left excess contributions in their account from a previous year
* A taxpayer's 2023 tax return received benefits (Last month rule) from assuming the taxpayer would be eligible to make HSA contributions throughout 2024, and the taxpayer's eligibility changed
* Situations where you have additional income. This includes distributions that aren't for qualified medical expenses, even if they aren't subject to an additional 20% tax because the account beneficiary died, became disabled, or turned 65\.
* Taxpayers who received HSA contributions from their employer that are attributable to a different tax year than the year when the contribution was made. This includes:
* Taxpayers who received employer contributions in 2024 toward their 2023 contribution limit
* Taxpayers who received employer contributions in 2025 toward their 2024 contribution limit
* Qualified HSA funding distributions
* HSA distributions other than Normal Distributions \- any distribution on 1099-SA where box 3 is not **1**
* Archer or Medicare Advantage Medical Savings Accounts (MSAs). These accounts are reported on the same income tax form as HSAs but are different.
* Taxpayers who choose to file married filing separately and both taxpayers made contributions to their HSA
### **Rejection reasons**
The following new rejection reasons may be experienced by taxpayers who report HSA activity:
| Rejection code | Meaning | Recommended action |
| ----- | ----- | ----- |
| F8889-001-01 | Recipient SSN on Form 8889 does not match a filer's SSN. | If encountered, report as a bug. |
| F8889-002-01 | Two Forms 8889 were added to the return and both had the same filer SSN. | If encountered, report as a bug. |
| F8889-004-01 | HSA contribution limit reported on Form 8889 is too high. | If encountered, report as a bug. |
| F8889-005 | Form 8889, line 5 value was not calculated correctly. | If encountered, report as a bug. |
| F8889-006 | Form 8889, line 7 value was not calculated correctly. | If encountered, report as a bug. |
| F8889-007 | Form 8889, line 8 value was not calculated correctly. | If encountered, report as a bug. |
| F8889-008 | Form 8889, line 11 value was not calculated correctly. | If encountered, report as a bug. |
| F8889-009 | Form 8889, line 12 value was not calculated correctly. | If encountered, report as a bug. |
| F8889-010 | Form 8889, line 13 value was not calculated correctly. | If encountered, report as a bug. |
| F8889-011 | Form 8889, line 14c value was not calculated correctly. | If encountered, report as a bug. |
| F8889-012 | Form 8889, line 16 value was not calculated correctly. | If encountered, report as a bug. |
| F8889-013 | Indicates taxable HSA distributions, which should not be in scope for Direct File. | If encountered, report as a bug. |
| F8889-014 | Only in use in Form 8889 Part III, which should not be in scope for Direct File. | If encountered, report as a bug. |
##
##
##
##
## **State taxes**
### **Description**
For any state that has a state tax filing requirement, we will be directing filers to a state tax filing tool after they submit their federal taxes.
Some states allow filers to transfer their federal tax data to the state tax filing tool, while others don't (these filers will have to enter all their data again in the state tool). In states that have data transfer, TPs are sent back to Direct File to log in and transfer their data after they begin their state tax return in the state tax filing tool.
| States with data transfer | States without data transfer | States with no filing requirement |
| ----- | ----- | ----- |
| Arizona Idaho Illinois Maryland Massachusetts New Jersey New Mexico New York North Carolina Oregon Pennsylvania Wisconsin | California Connecticut Kansas Maine | Alaska Florida Nevada New Hampshire South Dakota Tennessee Texas Washington (has Working Families Tax credit that filers can apply for) Wyoming |
##
### **Navigation**
How do you navigate to this screen in the Direct File experience?
There are three areas of Direct File that are related to the state tax filing experience: the eligibility screener, the confirmation screen that is displayed after a filer submits their return, and the data transfer screen which is displayed after a filer starts their state tax return and is directed back to Direct File to transfer their data.
#### **Eligibility screener**
There is a section in the eligibility screener that lists criteria for being able to use DF for each state. This section includes conditions that might prevent filers from using the state filing tool. If filers will not be able to use the state tool, we discourage them from using DF. These criteria are accessible from the state accordion on the first step of the eligibility screener.
#### **Confirmation screen**
After a filer submits their return, they see a card on the confirmation screen directing them to file their state taxes (if applicable).
* For integrated states (with data transfer), this card takes filers to a screen that outlines the process for filing state taxes. They then see a button to go to the state filing tool.
* For non-integrated states (without data transfer), the card on the confirmation screen has a button that takes the filer straight to the state filing tool.
#### **Data transfer screen**
After a filer begins their state tax return, they will be directed back to DF to log in and approve a transfer of their federal tax return data to the state filing tool.
"Return Status: Accepted" Required: Some states (AZ, ID, MD, NC, NJ, NY, PA) require the federal tax return to be accepted before the filer can transfer their data. If filers arrive on the data transfer screen before their return is accepted, they are told they need to wait before they can transfer. There is a button on this screen to refresh the page and check their status again. They can only click this refresh button once every 30 seconds (to keep from overloading the system).
"Returned Status: Pending" Allowed: Other states (IL, MA, NM, OR, WI) will allow filers to transfer their data before their federal return is accepted. We warn these filers that they may want to wait for acceptance to make sure they dont have to make changes to their state return (in case of federal return rejection).
Once a filer clicks the “transfer data” button, they are taken back to the state filing tool to continue their state return.
### **Likely TP questions & answers**
What questions might taxpayers be asking Customer Support here? And preliminary short answer?
| Question | Answer |
| ----- | ----- |
| Do I have to file state taxes? | Depending on your situation, you may need to file a state tax return in addition to your federal tax return. Requirements for filing vary by state: Arizona: [https://azdor.gov/individuals/income-tax-filing-assistance/filing-individual-returns](https://azdor.gov/individuals/income-tax-filing-assistance/filing-individual-returns) California: [www.ftb.ca.gov/file/personal/do-you-need-to-file.html](http://www.ftb.ca.gov/file/personal/do-you-need-to-file.html) Connecticut: [https://portal.ct.gov/drs/individuals/resident-income-tax/tax-information\#WhoMustFile](https://portal.ct.gov/drs/individuals/resident-income-tax/tax-information#WhoMustFile) Idaho: [https://tax.idaho.gov/taxes/income-tax/individual-income/online-guide/](https://tax.idaho.gov/taxes/income-tax/individual-income/online-guide/) Illinois: [https://tax.illinois.gov/individuals/filingrequirements.html](https://tax.illinois.gov/individuals/filingrequirements.html) Kansas: [https://www.ksrevenue.gov/perstaxtypesii.html](https://www.ksrevenue.gov/perstaxtypesii.html) Maine: [http://www.maine.gov/revenue/faq/individual-income-tax](http://www.maine.gov/revenue/faq/individual-income-tax) Maryland: [https://www.marylandtaxes.gov/individual/income/filing/index.php](https://www.marylandtaxes.gov/individual/income/filing/index.php) Massachusetts: [https://www.mass.gov/info-details/e-file-and-pay-your-ma-personal-income-taxes](https://www.mass.gov/info-details/e-file-and-pay-your-ma-personal-income-taxes) New Jersey: [https://www.nj.gov/treasury/taxation/njit23.shtml](https://www.nj.gov/treasury/taxation/njit23.shtml) New Mexico: [https://www.tax.newmexico.gov/individuals/personal-income-tax-information-overview/](https://www.tax.newmexico.gov/individuals/personal-income-tax-information-overview/) New York: [https://www.tax.ny.gov/pit/file/do\_i\_need\_to\_file.htm](https://www.tax.ny.gov/pit/file/do_i_need_to_file.htm) North Carolina: [https://www.ncdor.gov/individual-income-filing-requirements](https://www.ncdor.gov/individual-income-filing-requirements) Oregon: [https://www.oregon.gov/DOR/programs/individuals/Pages/file-requirements.aspx](https://www.oregon.gov/DOR/programs/individuals/Pages/file-requirements.aspx) Pennsylvania: [https://www.revenue.pa.gov/formsandpublications/papersonalincometaxguide/pages/brief-overview-filing-requirements.aspx](https://www.pa.gov/en/agencies/revenue.html) Wisconsin: [https://www.revenue.wi.gov/Pages/FAQS/pcs-indreq.aspx](https://www.revenue.wi.gov/Pages/FAQS/pcs-indreq.aspx) |
| Can I file my state taxes in Direct File? | You can only use Direct File for your Federal tax return. Direct File partners with states that offer free state filing tools. Once you complete your federal tax return with Direct File, we'll tell you where to go to complete your state return. |
| How do I file state taxes? | Many states require a state tax return in addition to a federal tax return. If your state does, you will need to file it separately from your federal tax return. Direct File partners with states that offer free state filing tools. If you lived and worked in one of those states for all of 2024, we will direct you to your state's free filing tool after you complete your federal tax return. For complete information about your state's tax filing process and tools, please visit your state Department of Revenue (links below). Arizona: [https://azdor.gov/](https://azdor.gov/) California: [https://www.cdtfa.ca.gov/](https://www.cdtfa.ca.gov/) Connecticut: [https://portal.ct.gov/drs](https://portal.ct.gov/drs) Idaho: [https://tax.idaho.gov/](https://tax.idaho.gov/) Illinois: [https://tax.illinois.gov/](https://tax.illinois.gov/) Kansas: [https://www.ksrevenue.gov/](https://www.ksrevenue.gov/) Maine: [https://www.maine.gov/revenue/](https://www.maine.gov/revenue/) Maryland: [https://www.marylandtaxes.gov/](https://www.marylandtaxes.gov/) Massachusetts: [https://www.mass.gov/orgs/massachusetts-department-of-revenue](https://www.mass.gov/orgs/massachusetts-department-of-revenue) New Jersey: [https://www.nj.gov/treasury/taxation/](https://www.nj.gov/treasury/taxation/) New Mexico: [https://www.tax.newmexico.gov/](https://www.tax.newmexico.gov/) New York: [https://www.tax.ny.gov/](https://www.tax.ny.gov/) North Carolina: [https://www.ncdor.gov/](https://www.ncdor.gov/) Oregon: [https://www.oregon.gov/dor/pages/index.aspx](https://www.oregon.gov/dor/pages/index.aspx) Pennsylvania: [https://www.pa.gov/en/agencies/revenue.html](https://www.pa.gov/en/agencies/revenue.html) Washington: [https://dor.wa.gov/](https://dor.wa.gov/) Wisconsin: [https://www.revenue.wi.gov/Pages/Home.aspx](https://www.revenue.wi.gov/Pages/Home.aspx) |
| What if I lived in one state but worked in another? | You need to have lived in and earned income in the same state for the whole tax year to use Direct File. You can confirm this by checking Box 15 on your W-2. If you're filing with a spouse, they must have lived and earned income in that state as well. If you aren't eligible for Direct File this year, there are other ways to file your taxes: [https://www.irs.gov/filing/e-file-options](https://www.irs.gov/filing/e-file-options) |
| Will I have to start my state taxes from scratch? | It depends on what state you live in. In several states, you will be able to transfer data from your federal tax return to your state tax return. These states include: Arizona Idaho Illinois Maryland Massachusetts New Jersey New Mexico New York North Carolina Oregon Pennsylvania Wisconsin |
| I'm having trouble logging into the state tool. What do I do? | We aren't able to help with state tax filing tools. For issues with the state tool, you will need to contact that state's department of revenue for support. |
| I have a question about something in my state taxes | We aren't able to help with state tax filing tools. For issues with the state tool, you will need to contact that state's department of revenue for support. |
| What do I do if I can't use the state tool? | If you are unable to use the state tax filing tool that we directed you to, you may have to find another way to file your state taxes. Contact your state department of revenue (see links to DOR pages above) to find other methods. You may also be able to use one of our Free File partners, but if you have already submitted your federal tax return through Direct File, you'll need to check that the tool allows you to file state taxes by themselves. If you file a duplicate of your federal return, your return will be rejected. |
| Why can't I transfer data from my federal return? | In some states (AZ, ID, MD, NC, NJ, NY, PA), your federal tax return needs to be accepted before you can transfer your data to your state tax filing site. If your return has been accepted and you're still having trouble transferring your data, customer support team should route the issue through on call for engineering trouble shooting. It is helpful to try to confirm with the taxpayer whether the issue came about when they were on a page within IRS Direct File, or a page within the state tax filing tool. |
| The data that transferred into my state return isn't correct. What do I do? | We transferred the data that you entered into your federal tax return. If that data is incorrect, you'll need to file an amended federal tax return. Direct File doesnt support amending a tax return that was already accepted through a different submission process. Learn how to amend a previously accepted tax return \- [https://www.irs.gov/filing/file-an-amended-return](https://www.irs.gov/filing/file-an-amended-return) |
| I tried to file my state taxes in another tool and had to file a duplicate of my federal return, which was then rejected. What do I do? | You need to contact customer support for the other tool you used, and contact your state department of revenue regarding options for filing your state return. |
| I need to file my state return now (deadline is here), but my federal return hasn't been accepted yet. What do I do? | We encourage you to file as early as possible to meet the April 15 deadline. We don't have additional information about how your state will treat returns that come in after the deadline. When you've finished your federal return, Direct File will tell you where to go to file your state return (if your state requires it). For taxpayers in AZ, ID, MD, NC, NJ, NY, PA: if you are waiting to get an accepted return status from Direct File for your federal return before starting your state return, we encourage you to keep an eye out for an email or check into your Direct File dashboard. Direct File will send you an email within 2 business days letting you know when your federal tax return has been accepted or rejected. If you have questions specific to your state and their deadlines, you can reach out to them directly (see state DOR webpages listed for prior answers). |
| Can I file my state return before my Federal return has been accepted? | For taxpayers in AZ, ID, MD, NC, NJ, NY, PA: You won't be able to submit your state return until your federal return has been accepted by the IRS. So, you won't be able to download your federal tax return data and transfer it to the state tax filing tool until this occurs. You'll get an email letting you know your federal return was accepted or rejected. When it's accepted, you'll be able to complete transferring the data to the state tax filing tool provided by your state. Typically, it can take up to an hour for the IRS to accept or reject your federal tax return. However, in some cases, it may take up to 2 business days. If it's been longer than 2 business days, reach back out to our customer support chat. For taxpayers in MA, IL, NM, OR, WI: You can file your state return after you have submitted your federal return. You don't need to wait until the IRS has accepted your federal return. For taxpayers in WA: You can submit your Working Families Tax Credit application after you have submitted your federal return. You don't need to wait until the IRS has accepted your federal return. |
| I don't have to file federal taxes. How do I file my state taxes? | Direct File partners with states that offer free state filing tools. If you lived and worked in one of those states for all of 2024, we will direct you to your state's free filing tool after you complete your federal tax return. For complete information about your state's tax filing process and tools, please visit your state Department of Revenue (links below). Arizona: [https://azdor.gov/](https://azdor.gov/) California: [https://www.cdtfa.ca.gov/](https://www.cdtfa.ca.gov/) Connecticut: [https://portal.ct.gov/drs](https://portal.ct.gov/drs) Idaho: [https://tax.idaho.gov/](https://tax.idaho.gov/) Illinois: [https://tax.illinois.gov/](https://tax.illinois.gov/) Kansas: [https://www.ksrevenue.gov/](https://www.ksrevenue.gov/) Maine: [https://www.maine.gov/revenue/](https://www.maine.gov/revenue/) Maryland: [https://www.marylandtaxes.gov/](https://www.marylandtaxes.gov/) Massachusetts: [https://www.mass.gov/orgs/massachusetts-department-of-revenue](https://www.mass.gov/orgs/massachusetts-department-of-revenue) New Jersey: [https://www.nj.gov/treasury/taxation/](https://www.nj.gov/treasury/taxation/) New Mexico: [https://www.tax.newmexico.gov/](https://www.tax.newmexico.gov/) New York: [https://www.tax.ny.gov/](https://www.tax.ny.gov/) North Carolina: [https://www.ncdor.gov/](https://www.ncdor.gov/) Oregon: [https://www.oregon.gov/dor/pages/index.aspx](https://www.oregon.gov/dor/pages/index.aspx) Pennsylvania: [https://www.pa.gov/en/agencies/revenue.html](https://www.pa.gov/en/agencies/revenue.html) Washington: [https://dor.wa.gov/](https://dor.wa.gov/) Wisconsin: [https://www.revenue.wi.gov/Pages/Home.aspx](https://www.revenue.wi.gov/Pages/Home.aspx) |
## **Credit for Elderly or Disabled**
### **Description**
Credit for the Elderly or the Disabled is a new addition to Direct File's *Credits Section*. When any filer on the tax-return is determined to be eligible for this tax credit, the user will encounter the set of questions that allow a filer to further establish their eligibility.
This tax credit is available to taxpayers who are either elderly (65+) or permanently and totally disabled, and whose income falls within [income limits for this credit](https://www.irs.gov/instructions/i1040sr#en_US_2023_publink11357od0e142). (External link: https://www.irs.gov/instructions/i1040sr\#en\_US\_2023\_publink11357od0e142)
Credit for the Elderly or the Disabled is a *nonrefundable* tax credit. This means that it can reduce your taxes, but it won't reduce what you owe below $0. In other words, it can't give you a refund.
**Note:** This credit is not indexed for inflation. With its current income limits, only a very narrow set of filers will be eligible to claim this credit. Because most tax liability within these limits will get offset by the standard deduction.
### **Eligibility**
* Must be 65+ or permanently and totally disabled
* AGI must be within credit limits for filing status
* Nontaxable income must be within credit limits for filing status
* This is nontaxable Social Security or other nontaxable pensions, annuities, or disability income.
How the math breaks down: Due to current standard deductions, only filers with the following attributes will benefit from this credit.
* Filing status: Single
* Nontaxable income:
* If age 65+: Generally \<$400, depending on income.
* If age \<65: Generally \<$1,350, depending on income.
* AGI:
* If age 65+: $16,550 \< x \< $17,500
* If age \<65: $14,600 \< x \< $17,500
### **Requirements**
* Elderly eligibility: 65+ years old as of January 1, \<TY+1\>
* Disabled eligibility:
* Age: \< 65 years old
* Retired on permanent and total disability by the end of \<TY\>
* Haven't reached employer's mandatory retirement age by January 1, \<TY\>
* Taxable Disability Income (from accident or health plans paid for by an employer): \> $0
* Doctor's statement: Required, but not filed. Kept as reference.
### **Navigation**
How do you navigate to this screen in the Direct File experience?
If a taxpayer is eligible for the Credit for the Elderly or the Disabled, the screens will appear in the Credits section of the Checklist.
## **Saver's Credit (Form 8880\)**
### **Description**
Tax payers may receive a tax credit if they contribute to qualifying retirement accounts, such as a 401(k) account.
The maximum credit available to tax payers is $1,000 for single payers or $2,000 for married filing jointly.
### **Navigation**
*How do you navigate to this screen in the Direct File experience?*
(Step-by-step navigation is helpful, taxpayers ask for this often)
1. Start your return
2. Complete "You and your family"
3. Begin "Income sources"
4. Select a supported fund type for box 12 on your W2 (i.e. “D” for 401(k))
5. Complete “Income sources”
6. Complete “Contributions” section
7. Begin “Credits” section
### **Unsupported tax situations**
* Taxpayer received distributions from retirement plans or ABLE accounts between 2021 and 2023
* Taxpayer received distributions between January 1 and October 16, 2025
* Direct File doesnt yet support:
* Contributions to a retirement plan that aren't reported on the 2024 Form W-2, box 12
* Contributions to Individual Retirement Arrangement (IRAs) in 2024
* Contributions to an Achieving a Better Life Experience (ABLE) account made by the designated beneficiary
* Contributions to a Section 408(k)(6) salary reduction SEP: Code F on Form W-2, box 12
* Taxpayer made contributions to a traditional IRA or most Roth IRAs (see table below)
* Taxpayer made elective deferrals to a Federal Thrift Savings Plan (TSP)
### **Likely TP questions & answers**
| Question | Answer |
| ----- | ----- |
| Why are there two 457(b) fund types with different codes? | Code G CAN represent either governmental or non-governmental contributions. Taxpayers can qualify for the Saver's credit with governmental 457(b) contributions only. Non-governmental 457(b) contributions do not qualify the taxpayer for the Saver's Credit. There is a question to determine this in the Direct File app flow. Code EE represents Governmental Roth 457(b) contributions and these also qualify the taxpayer for the Saver's Credit. |
| What's the deal with Code F? | This code technically qualifies for the Saver's Credit, but is out of scope for this tax year. It is for the section 408(k)(6) salary reduction SEP. |
| Which fund types does DF support? | See chart below for complete list of supported contributions for TY 2024\. |
![SaversCredit-supported-contributions-TY2024](https://github.com/user-attachments/assets/e468ab75-e57a-4cf0-99f0-7b5e0f595877)
### **Visual aids**
Applicable tax fund types are pulled from this page in the W2 section:
![SaversCredit_Applicable-tax-fund-types-W2 ](https://github.com/user-attachments/assets/9dbb4481-d6f6-4325-a12b-a47dbcd0dd68)
## **Post-Deadline Filing**
### **Description**
For filing season 2025, Direct File plans to stay open for the entire filing season (last year it closed after the rejection grace period, April 20). This has implications for how we communicate both in the run-up to the filing deadline and after the filing deadline.
### **Likely TP questions & answers**
What questions might taxpayers be asking Customer Support here? And a preliminary short answer?
| Question | Answer |
| ----- | ----- |
| When will Direct File no longer be available? | Direct File will be available for filing until mid-October \[exact date TBD\]. |
| How can I apply for an extension? | If you need more time you may apply for an extension at [https://www.irs.gov/filing/get-an-extension-to-file-your-tax-return](https://www.irs.gov/filing/get-an-extension-to-file-your-tax-return). Remember, even if you have an extension to file your tax return, you still need to pay your taxes by the original due date to avoid interest and penalties for failing to pay on time. |
| What is the federal tax filing deadline? | The **federal tax filing deadline is April 15, 2025 at 11:59PM in your timezone**. Your deadline may be postponed if you were affected by a disaster situation. Learn more at [https://www.irs.gov/newsroom/tax-relief-in-disaster-situations](https://www.irs.gov/newsroom/tax-relief-in-disaster-situations) |
| I have an extension. Can I still use Direct File? | Yes, you can still use Direct File to file your federal tax return. Remember that even if you have an extension to file your tax return, you still need to pay your taxes by the original due date to avoid interest and penalties for failing to pay on time. if you owe a federal tax balance, you'll need to pay by the federal tax filing deadline (April 15\) using one of these payment options: [https://www.irs.gov/payments](https://www.irs.gov/payments) |
| What happens if I file after the deadline? | If you file after April 15 and have a federal tax balance, the IRS may charge a **failure to file** penalty. There is no failure to file penalty if you are due a refund or have no tax due. If you have a balance due, your payment is due by April 15\. If you don't pay by this date, the IRS may charge a **failure to pay** penalty. The IRS will send you a letter about any penalties and work with you to arrange payment. In the meantime, you should file and pay any balance due as soon as possible using one of these payment options: [https://www.irs.gov/payments](https://www.irs.gov/payments) Your deadline may be postponed if you were impacted by a disaster. See [https://www.irs.gov/newsroom/tax-relief-in-disaster-situations](https://www.irs.gov/newsroom/tax-relief-in-disaster-situations) for more information. |
| What if I submitted on time, but my return has been rejected? | If you filed your return by April 15, you have until April 20 to resubmit an on-time return. You can still submit your return after April 20, but you may be subject to interest and penalties for failing to file on time if you have a balance due. |
| When do I need to pay my balance? | Even if you have an extension, you need to pay any balance due by April 15, or you may be subject to a failure to pay penalty. You have several options for paying your taxes outside of Direct File, including by digital wallet, credit or debit card, check, cash, or IRS payment plans. IRS tax payment options: [https://www.irs.gov/payments](https://www.irs.gov/payments) |
| Can I still file my state taxes after the deadline? | Yes, if you live in a state that requires a state tax return, you can still file your return after the deadline, although you may be subject to penalties or interest. Once you have filed your federal return, you can sign into Direct File to be directed to your state's Direct File partners with states that offer free state filing tools. If you lived and worked in one of those states for all of 2024, we will direct you to your state's free filing tool after you complete your federal tax return. For complete information about your state's tax filing process and tools, please visit your state Department of Revenue (links below). Arizona: [https://azdor.gov/](https://azdor.gov/) California: [https://www.cdtfa.ca.gov/](https://www.cdtfa.ca.gov/) Connecticut: [https://portal.ct.gov/drs](https://portal.ct.gov/drs) Idaho: [https://tax.idaho.gov/](https://tax.idaho.gov/) Illinois: [https://tax.illinois.gov/](https://tax.illinois.gov/) Kansas: [https://www.ksrevenue.gov/](https://www.ksrevenue.gov/) Maine: [https://www.maine.gov/revenue/](https://www.maine.gov/revenue/) Maryland: [https://www.marylandtaxes.gov/](https://www.marylandtaxes.gov/) Massachusetts: [https://www.mass.gov/orgs/massachusetts-department-of-revenue](https://www.mass.gov/orgs/massachusetts-department-of-revenue) New Jersey: [https://www.nj.gov/treasury/taxation/](https://www.nj.gov/treasury/taxation/) New Mexico: [https://www.tax.newmexico.gov/](https://www.tax.newmexico.gov/) New York: [https://www.tax.ny.gov/](https://www.tax.ny.gov/) North Carolina: [https://www.ncdor.gov/](https://www.ncdor.gov/) Oregon: [https://www.oregon.gov/dor/pages/index.aspx](https://www.oregon.gov/dor/pages/index.aspx) Pennsylvania: [https://www.pa.gov/en/agencies/revenue.html](https://www.pa.gov/en/agencies/revenue.html) Washington: [https://dor.wa.gov/](https://dor.wa.gov/) Wisconsin: [https://www.revenue.wi.gov/Pages/Home.aspx](https://www.revenue.wi.gov/Pages/Home.aspx) |
| How do I pay penalties or interest? | The IRS will send you a letter about any penalties and work with you to arrange payment. You have several options for paying your taxes outside of Direct File, including by digital wallet, credit or debit card, check, cash, or IRS payment plans. IRS tax payment options: [https://www.irs.gov/payments](https://www.irs.gov/payments) |
# **Other product areas**
## **About you**
In "About you", Direct File asks questions about the primary taxpayer that the IRS needs to know to generate the tax return. For example:
* There are questions (like what state the taxpayer lives in) that help determine if the taxpayer's tax situation fits the scope of the pilot.
* There are questions (like age and blindness) that inform the taxpayer's standard deduction.
* There are questions (related to the taxpayer dependency test) that inform the taxpayer's eligibility to claim a dependent.
* There are questions (like age and citizenship) that inform the taxpayer's eligibility to take certain tax credits or filing statuses.
* There are also questions (like phone number and address) that are required for future IRS communication with the taxpayer.
Citizenship and Residency: we ask for the taxpayer's citizenship and residency status because the scope of the Direct File pilot is limited to U.S. citizens and U.S. residents (including nonresidents who are considered residents for tax purposes). If the taxpayer is not a U.S. citizen or resident for tax purposes, we will direct them to other filing options.
## **Spouse**
The "Spouse" section starts by asking questions about a taxpayer's marital situation. If they have a spouse, we use that information to start to discern what filing status they qualify for. In "Spouse", Direct File asks questions about the taxpayer's spouse that the IRS needs to know to generate the tax return. For example:
* There are questions (like what state the taxpayer's spouse lives in) that help determine if the taxpayer's tax situation fits the scope of the pilot.
* There are questions (like spouse's age and blindness) that inform the taxpayer's standard deduction.
* There are questions (related to claiming a spouse as a dependent or the spouse's death) that inform the filing status they can claim.
Out of scope:
* Registered domestic partnerships in community property states (Form 8958\)
## **Citizenship & Residency**
| | | Scope for the person filling out the form | And their spouse may be | Excluded |
| ----- | ----- | ----- | ----- | ----- |
| Scope | We ask for the taxpayer's citizenship and residency status because the scope of the Direct File pilot is limited to U.S. citizens and U.S. residents (including nonresidents who are considered residents for tax purposes). If the taxpayer is not a U.S. citizen or resident for tax purposes, we will direct them to other filing options. | **Citizen all year Resident for tax purposes all year** (includes national who was also a U.S. resident all year) **Citizen by end of year** (just citizen and U.S. resident statuses in the year) | **Citizen all year Resident for tax purposes all year Citizen or U.S. resident all year Nonresident or dual status** (so person filling out the form may file as considered-unmarried-HOH or MFS) | Filer who was **nonresident for any part of year** |
| Dependents | We need to know if the taxpayer is a U.S. citizen, U.S. resident for tax purposes, or U.S. national because this affects whether they can claim their (non-citizen, non-resident, non-national) adopted child as a dependent. If the taxpayer is a U.S. citizen or U.S. national and legally adopts a child who isn't a U.S. citizen, U.S. resident alien, or U.S. national, then that child can pass the dependent residency test if they lived with the taxpayer all year as a member of the household. This exception also applies if the child was lawfully placed with the taxpayer for legal adoption and the child lived with the taxpayer for the rest of the year after placement (even if it wasn't all year). This exception does NOT apply for U.S. residents, which is why we need to know precisely if the taxpayer is a U.S. citizen, U.S. resident, or U.S. national. | **Citizen all year Resident for tax purposes all year** (includes national who was also a U.S. resident all year) **Citizen by end of year** (just citizen and U.S. resident statuses in the year) US National | | Nonresident Dual status |
| EITC | We need to know if the taxpayer was a U.S. citizen, U.S. resident for tax purposes ALL YEAR because this affects their eligibility for EITC. To qualify for EITC, the taxpayer and their spouse (if filing jointly) must be U.S. citizens or resident aliens for the entire tax year. U.S. nationals (by virtue of that status alone) do not qualify to claim EITC. If the taxpayer or their spouse was a nonresident alien for any part of the tax year, they can only claim EITC if their filing status is married filing jointly and either the taxpayer or their spouse is a U.S. citizen with a valid SSN, or a resident alien who was in the U.S. for at least 6 months of the tax year and they have a valid SSN. | **Citizen all year Resident for tax purposes all year** (includes national who was also a U.S. resident all year) **Citizen by end of year** (just citizen and U.S. resident statuses in the year) | | Nonresident Dual status |
| CTC/ODC | Use of citizenship or residency is implicit: the taxpayer must claim QC as dependent. See dependent rules. | | | |
| HOH | We need to know if the taxpayer was a U.S. citizen. U.S. resident for tax purposes ALL YEAR because this affects whether they can be "considered unmarried" for HOH filing status. If the taxpayer was a U.S. citizen or resident for the whole tax year, and has a nonresident spouse, they may be able to file as HOH if the nonresident spouse chooses not to file a joint return, the taxpayer meets the other requirements for this filing status, and the spouse is not a qualifying person for head of household purposes. | **Citizen all year Resident for tax purposes all year** (includes national who was also a U.S. resident all year) **Citizen by end of year** (just citizen and U.S. resident statuses in the year) | **Nonresident or dual status** (so person filling out the form may file as considered-unmarried-HOH or MFS) | Nonresident Dual status |
| MFJ | We need to know if the taxpayer was a U.S. citizen, U.S. resident for tax purposes ALL YEAR because this affects whether they can file a joint return with their spouse. Generally, a married couple can't file a joint return if either one is a nonresident at any time during the tax year. However, if one spouse was a nonresident or dual-status who was married to a U.S. citizen or resident at the end of the year, the spouses can choose to file a joint return. If they do file a joint return, the taxpayer and spouse will both be treated as U.S. residents for the entire tax year. | **Citizen all year Resident for tax purposes all year** (includes national who was also a U.S. resident all year) **Citizen by end of year** (just citizen and U.S. resident statuses in the year) | **Citizen all year Resident for tax purposes all year** (includes national who was also a U.S. resident all year) **Citizen by end of year** (just Citizen and U.S. resident statuses in the year) | Nonresident Dual status |
| QSS | Can be current U.S. citizen, U.S. resident for tax purposes some part of year, or NR from certain countries, but eligibility is contingent upon their actual citizenship/residency status in the year spouse died. | **Citizen all year Resident for tax purposes all year** (includes national who was also a U.S. resident all year) **Citizen by end of year** (just citizen and U.S. resident statuses in the year) **Actual status in year of spouse's death**: we check this in a different section of the product. | We ask if the filer and that spouse **were eligible to file jointly in the year of death** (both spouses' citizenship/residency is part of answering this question) | Nonresident Dual status |
| Standard deduction | We need to know if the taxpayer was a U.S. citizen, U.S. resident for tax purposes ALL YEAR because this affects their eligibility to take the standard deduction. Generally, only taxpayers who are U.S. citizens or U.S. residents for the whole tax year are eligible for the standard deduction. There are 2 exceptions to this rule that are in scope for the pilot. Active IRS election: 1\. A nonresident who is married to a U.S. citizen or resident at the end of the tax year and makes a joint election with their spouse to be treated as a U.S. resident for the entire tax year is eligible to take the standard deduction. 2\. Someone who is a nonresident at the beginning of the tax year and becomes a U.S. citizen or resident by the end of the tax year is eligible for the standard deduction if they are married to a U.S. citizen or resident by the end of the tax year and they make a joint election with their spouse to be treated as a U.S. resident for the entire tax year. | **Citizen all year Resident for tax purposes all year** (includes national who was also a resident all year) **Citizen by end of year** (just Citizen and U.S. resident statuses in the year) | | Nonresident Dual status If filer's Spouse was NR/Dual, the filer would be filing separately: MFS or HOH |
##
##

1
docs/product/README.md Normal file
View file

@ -0,0 +1 @@
# Product docs

83
docs/rfc/2023_and_me.md Normal file
View file

@ -0,0 +1,83 @@
Engineering decisions to be made early in the Dec 2022 - Spring 2023 development push
===========================
Background:
As we prepare to build a tax filing service, engineering decisions need to be made on a vast array of topics ranging from the overall architecture to language choices to hosting platforms to deployment tools. Some of these choices can be easily changed as the team grows and requirements evolve, while others will have high switching costs and put us on a path that will be hard to deviate from. The goal of this document is to identify the areas that are in greatest need of thoughtful treatment early in the process, so that we can prioritize them accordingly. Also provided are some initial thoughts on likely directions, associated tradeoffs, and a brief list of the things we need to know in order to proceed with a given choice.
Insight on each topic area should take into consideration our expectations about what skill sets we'll likely have available, what tools we can get authorization to use, and any lessons that can be derived from the prototype that was built in spring/summer 2022.
Topics:
* Division of responsibilities between front end and back end
* Modularization of back end (API for front end interaction? separation of MeF integration?)
* Language choices
* Front end web frameworks
* Data storage product
* Definition of a user account
* Authentication levels and tools
* Rough expectations for document ingest features and resulting dependencies
* Rough expected scope of Taxpert interface support and resulting dependencies
* Rough expectations for integration with third party customer support tool / CRM
Division of responsibilities between front end and back end
===========================
Modularization of back end (API for front end interaction? separation of MeF integration?)
===========================
Language choices
===========================
Front end web frameworks
===========================
Data storage product
===========================
* what are we storing?
* how long do we need to store it?
* what are the security requirements?
Definition of a user account
===========================
For joint filers, we need to make a choice as to whether a user account represents an individual human or the joint filing couple. There are examples of services in which this determination can be made independently by each user (for example, I may choose to share an email account with my spouse), but in our case, identity is a crucial concept that needs to be well defined with respect to user accounts.
Considerations:
* Handling access and information history from year to year as people change filing statuses and become married/unmarried.
* Future data prepopulation features that may require identity proofing.
Authentication levels and tools
===========================
We believe that, at least up through and including filing season 2024 (TY2023), we will:
* Allow taxpayers to provide data
* Pass back information from the IRS indicating whether returns are accepted or rejected
We will NOT grant users access to any sensitive tax data that they have not explicitly provided to the application.
For this set of features, we contend that the application must support similar levels of authentication as existing non-government applications which access the MeF API. It is important for users to demonstrate that they have the access keys (e.g. username, password, MFA methods) that were defined in any previous sessions during which they provided data, but it is not necessary to prove that they are a particular human.
Therefore, IAL1 is appropriate, while IAL2 is not.
In future years when we provide mechanisms to ingest data from sources other than user input, authentication should be enhanced to accommodate the data access restrictions appropriate for those data sources. Examples may include:
* SSO or password authentication for financial institutions
* IAL2 identity proofing for access to personal tax data held by the IRS
Rough expectations for document ingest features and resulting dependencies
===========================
Assumption: Initial scope does not include any automated ingestion of documents like W-2s, so we do not expect to rely on OCR libraries or similar.
Rough expected scope of Taxpert interface support and resulting dependencies
===========================
Assumption: Tax rules and logic for combining fields needs to be editable by people who are not software engineers.
Rough expectations for integration with third party customer support tool / CRM
===========================

View file

@ -0,0 +1,28 @@
# Design and a11y review process
The below steps are specifically the design and accessibility testing part of the overall acceptance flow process. The code submitter should have done their due dilligence for any user interface changes so that a design/a11y reviewer can focus on finer details. Although there are several steps, if we do this regularly it will be a light lift and will avoid any design/a11y debt.
## Verify that any changes match the design intention
- [ ] Check that the design translated visually
- [ ] Check interaction behavior
- [ ] Check different states (empty, one, some, error)
- [ ] Check for landmarks, page heading structure, and links
- [ ] Try to break the intended flow
- [ ] Confirm this works at 5Mbps down and 1Mbps up. You might use [Firefox dev tools](https://firefox-source-docs.mozilla.org/devtools-user/network_monitor/throttling/index.html) or Chrome's [WebRTC Network Limiter](https://chrome.google.com/webstore/detail/webrtc-network-limiter/npeicpdbkakmehahjeeohfdhnlpdklia)
## Verify that any changes meet accessibility targets
- [ ] Check responsiveness in mobile, tablet, and desktop at 200% zoom
- [ ] Check keyboard navigability
* Test general usability, landmarks, page header structure, and links with a screen reader (different from what the original dev used in their checklist):
- [ ] [VoiceOver](https://dequeuniversity.com/screenreaders/voiceover-keyboard-shortcuts#vo-mac-basics) in Safari
- [ ] [JAWS](https://dequeuniversity.com/screenreaders/jaws-keyboard-shortcuts#jaws-the_basics) in Chrome
- [ ] [NVDA](https://dequeuniversity.com/screenreaders/nvda-keyboard-shortcuts#nvda-the_basics) in Chrome
* Use an a11y tool to check these changes conform to at least WCAG 2.1 AA
- [ ] [WAVE](https://wave.webaim.org/)
- [ ] [axe](https://www.deque.com/axe/devtools/)
- [ ] [ANDI](https://www.ssa.gov/accessibility/andi/help/install.html#install)
- [ ] Browser inspector ([firefox](https://firefox-source-docs.mozilla.org/devtools-user/accessibility_inspector/#accessing-the-accessibility-inspector) / [chrome](https://developer.chrome.com/docs/lighthouse/accessibility/))
- [ ] For storybook-only components, use its [accessibility addon](https://medium.com/storybookjs/instant-accessibility-qa-linting-in-storybook-4a474b0f5347#c703).

146
docs/rfc/eng-rfc-process.md Normal file
View file

@ -0,0 +1,146 @@
Created At: May 5, 2024
Updated At: May 14, 2024
Author: Samuel Swire
RFC: Evolving How We Align on Technical Decisions
# Problem Statement
Direct File has matured as an application over the past year (read: we went to production) and grew its headcount to a 70+ member product team. However, we have not invested a lot of resources into adapting our processes around technical decision making to our burgeoning scale. This has manifested itself in last-mile delivery delays for various initiatives, primarily due to the fact that the right stakeholders were not in the room at the appropriate moments or they did not know that a decision was being made until after the fact.
Similarly, as Direct File grows in product scope, our relationship with the larger IRS IT organization will both change and become increasingly important. Integrating our ways of working during the pilot to the processes of the IRS enterprise more broadly will require a different approach than what served us during the pilot.
# BLUF: Proposed Process Changes
1. Distinguish RFCs from ADRs and clarify when to leverage each one
2. Establish a dedicated meeting time, with defined decision-makers, for reviewing RFCs that did not achieve alignment during async review
3. Include IRS IT SMEs within the RFC process and identify the criteria under which they should be engaged for certain changes
# Definitions
Request For Comments (RFC): In the engineering context, a formal document that recommends a technical specification for a set of product requirements. This can include anything from a change solely at the application level to a system(s)-wide, architecture that engages with multiple external services. Typically contains a set of working definitions, articulation of key product requirements, proposed implementation and analysis of alternatives. If the RFC is approved, it becomes the touchpoint for technical implementation and should be revised according to if new requirements appear. Some RFC are designated indefinitely with Experimental or Draft status.
Architecture Decision Record (ADR): A “lightweight” document that captures the rationale of a Architectural Decision (AD), i.e. a justified design choice that addresses a functional or non-functional requirement that is architecturally significant. ADRs captures a single AD and its rationale; the collection of ADRs created and maintained in a project constitute its decision log. ADRs typically contains a title, status, context, decision, and consequences.
# Proposal
## Goal
The goal of this proposal is to find the right balance between:
1) Functioning in an product-centric, agile manner;
2) Not constraining ourselves with unnecessary overhead; and
3) Clearly understanding the when, who and how of engaging with our IRS IT counterparts at the appropriate times.
The remainder of this proposal deals with some ways we can balance these needs and achieve these goals.
## Deepen our understand and engagement with the IRS IT organization and get our IRS IT SMEs involved as early as possible
We should engage with, at a minimum, our embedded Cyber SME and Technical Advisor as initial reviewers for any major system change, rather than as stakeholders that must be looped in only when the "paperwork" stage is reached, i.e. post-decision. Our IRS SMEs are our colleagues and champions within the enterprise - the earlier they are aware of changes that might require their support, the better the process will be for getting the features to production.
IRS IT SMEs should be involved when a system-wide change is being proposed, in particular one that might involve an update to any part of our ATO and especially control implementation statements in our System Security Plan (SSP). These changes typically require updating the `application.boundary` or `application.context` compliance documentation at some stages.
### When should I loop in IRS IT SMEs?
Examples of "system-wide changes" includes, but are not limited to:
- Provisioning new cloud infrastructure, both compute and storage
- Requesting changes to how our network boundaries are configured
- Adding new API endpoints or modifying where a URI can be located (i.e. changing the structure of the endpoint)
- New vulnerability scan findings that cannot be remediated timely
- Changing any part of our authorization or authentication flow
- Storing or accessing SBU/PII/FTI in an environment that isn't the application database or cache (in particular SaaS tools)
- Deviation from IRS IRMs
- Data or container security
- Integrating with other parts of the IRS (enterprise services, on-prem, cloud, etc.)
- Establishing connections external to the IRS
- Requesting new tools (whether or not they are ESP or COE approved)
- Major version upgrades of software framework components
- Standing up new deployed services
## Leverage RFCs as the primary mechanism to propose technical specifications
We currently conflate the concept of an ADR with an RFC. ADRs are static artifacts that are post-decisional; an engineer should be able to read the entire decision log of ADRs and roughly understand why the system is configured as it is. RFCs, on the other hand, are live documents meant for discussion and iteration. They are better suited for soliciting input and collecting feedback on a proposed approach, which is the right first step for proposing a technical specification. The outcome of an RFC might be an ADR, if the scale of proposed change merits it.
In practice, this means that once engineers are given a sufficiently large or complex set of requirements, they articulate their proposed approach in an RFC, rather than a combination of Gitlab tickets, Slack threads, and markdown files committed to the codebase with the word "ADR" in the title. This forces the engineer to spend more time substantiating their reasoning for a certain implementation and weighing various alternatives, as well as investigating the various upstream and downstream dependencies of the proposal. It also requires the engineer to consolidate their thoughts into a single SOT document, reducing the cognitive overhead of all participants of tracking the outcome across multiple surfaces (Github, Gitlab, Slack, Teams, etc.).
Writing an RFC **does not** negate the need to prototype various solutions; rather, prototyping should be considered part of the RFC process as a way to demonstrate the feasability of a given approach and that alternatives were considered.
Importantly, designing larger features and broader architecture design has historically been limited to a small number of developers relative to the size of the engineering organization, limiting the ability for other engineers to contribute and grow as system designers. This is mostly due to reasons of velocity and speed necessary to get the pilot out the door. RFCs provide a mechanism through which to enable other engineers to own their features end-to-end, instead of relying on another engineer to propose the implementation which they then action.
## Add a synchronous, cross-org forum for discussing RFCs that are not resolved asynchronously
In addition to moving to a world where RFCs are the formal document that facilitate discussion, we should also move away from a model where major engineering decisions are both reviewed and approved by a single functional team in a predominately asynchronous, i.e. in Github PRs. Instead, we should move towards a model where a broader audience can weigh in on proposed changes and discuss outstanding questions in a synchronous manner.
Making RFC review into a blocking mechanism is not the goal. Synchronous time should be leveraged **only** when there are outstanding questions on a proposal that require live, cross-team discussion. While async review and approval is always the first and best option, practically speaking at a certain level of system change, live discussion is inevitable if not necessary. We should embrace that reality, not fight it and rely on back-channels and 100-comment Slack thread to facilitate alignment on major changes.
Tactically, this would involve adding a standing RFC-review meeting that is 1) team-agnostic and open to the entire Product organization; and 2) always includes our Cyber SME and Technical Advisor as participants to make sure that all dependencies are considered. **An agenda should be circulated to participants 36 hours in advance and the meeting can be canceled if there is no agenda.**
One key benefit here is that a cross-organization, discussion-based approach to RFCs reduces knowledge silos across the product organization and allows engineers to better 1) understand what is happening across different teams; and thus 2) flag cross-cutting concerns that might not have been addressed during the primary review phase (e.g. changes to authn/authz affects many different teams, but not every team might be involved as the primary reviewers).
### Why a standing meeting instead of as needed/ad-hoc?
While the flexibility of ad-hoc better mirrors our historical and current practices around engineering meetings, there are a few reasons why a standing meeting with the sole purpose of reviewing RFCs is beneficial, at least in the first instance:
1. The right people are always in the room: the blended team model create a world where no single individual has access to everyone's calendar. By maintaining a standing meeting, everyone must put re-occuring blocks on their respective calendars, greatly increasing the chance that if they are a stakeholder, they will be able to attend.
1. In this vein, we want to ensure that our key IRS IT counterparts - those with a known stake in facilitating the delivery of the technical output - have their concerns are addressed before proceeding to implementation. This reduces our overall delivery lead time by removing "unknown unknowns" and proactively identifying (and accounting for) process-based roadblocks much earlier in the delivery process.
2. Resolving opposing views: major engineering changes often have several viable paths, and it is rare to have all outstanding questions answered asynchronously. A standing meeting releases both the author and reviewer from "finding a time to hash it out live" in favor of using a dedicated mechanism like RFC review (with an agenda and time limit on topics) to facilitate to discussion. This reduces unnecessary friction within and across teams, and enables other members of the organization to manage the discussion.
3. Context sharing and maintaining visibility for other teams and leadership: As Direct File grows, it is unrealistic that the people who might have reviewed PRs during the pilot will have the time to do so in Year 2, 3, etc. This doesn't mean, however, that they want to be divorced from the technical discussions that are happening. A standing meeting provides a dedicated space for those members/leadership to keep a finger on the pulse of what is happening without reviewing a dozen RFCs a week.
4. It is easier to start with a standing meeting and move to ad-hoc later than vice versa. Especially as we build the organizational muscles around a process like RFC review, it is helpful to have the meeting in place instead of requiring individuals to advocate for ad-hoc meetings out of the gate. During filing season, for instance, I expect us to leverage ad-hoc meetings significantly more. Conversely, during May-September when a lot of planning and technical designs are choosen, we would benefit from a standing meeting to make sure we aren't crossing-wires and are moving in lockstep.
5.
# Appendix I: Step-by-Step examples of how this all works in practice
If implemented, the expected development lifecycle would look roughly as follows:
**note: Each team/group/pod maintains autonomy in terms of how they want to define and implement the various steps, as long as 1) async and sync RFC review is incorporated into their development; and 2) IRS IT SMEs are engaged at the appropriate moments. The below will not map perfectly onto any given team's cadence, and instead aims to approximate the most-process heavy approach from which team's can choose what they would like to incorporate.**
1. Product requirements for a feature set are specified in a ticket (by someone)
2. The Directly Responsible Engineer (DRE) provides an intial, rough estimate of the scope and sizing of the work, as well as the documentation required to drive alignment on an orginizationally acceptable approach:
1. If a system-wide change (see below for criteria) is involved, an RFC and ADR will be required before moving to any implementation. **IRS IT SMEs should be looped in early as key stakeholders and reviewers.**
2. If the feature set is not a system-wide change, the DRE has discretion about if an RFC would be a helpful tool to facilitate design and/or gain consensus within a team or across teams. Some feature sets are complex enough to benefit from an RFC; others are not. Once the RFC is drafted, reviewed and approved, the DRE can begin implementation.
3. If an RFC is not needed, the DRE can immediately begin implementation and put up a PR with a description of the work and link back to the ticket.
3. If an RFC is needed, the DRE drafts a written proposal as a means to solicits feedback on the proposed technical approach. The document should live in the `docs/rfc` directory and be committed to the codebase in a PR in a text format like Markdown with associated artifacts (diagrams, etc.) included as needed.
1. All initial discussion can happen asynchronously and ad-hoc.
2. If a system-wide change is being proposed, DevOps and our IRS IT colleagues (in partiular Cyber SME and Technical Advisor) should be looped in at this stage as reviewers.
3. If a system-wide change is not being proposed, the DRE and reviewers should use their discretion as to if IRS IT should be engaged or not during the RFC stage. **If they are not engaged, the assumption is that they will not need to be engaged during or after implementation.**
4. If all questions (including those from IRS IT colleagues) are sufficiently addressed in the written RFC, the RFC can be approved and the DRE can move to implementation.
5. If there are outstanding questions in the RFC that cannot be resolved asynchronously, the RFC is slotted for discussion during the standing "RFC Review" meeting and circulated for discussion to all RFC Review participants.
1. During the meeting, the DRE presents a summary of the proposed changes and the group discusses the main outstanding questions and aligns on a path forward.
2. The DRE updates the RFC as needed coming out of this meeting.
3. n.b. **this is the only synchronous portion of this process, everything else is asynchronous**
6. In the event that an ADR is needed, after the RFC stage is complete an ADR is drafted and committed to the codebase in the `docs/adr` repository. This should all occur asynchronously and should be merged in short order with minimal review cycles.
1. No alignment is needed on the ADR as it simply codifies the outcome of the RFC and RFC review.
7. Once the RFC and/or ADR stages are complete, the DRE can begin implementation. At the same time, they also coordinate with IRS IT and DevOps to understand if they need any additional documentation aside from the RFC and ADR is necessary to initiate or facilitate IRS IT or IEP processes.
# Appendix II: Deciding between RFC, ADR and normal PRs
This section provides a basic decision tree for deciding between the following processes (in order of number of parties that need to coordinate to make a change, from least to most):
- Ticket with a PR
- ADR
- RFC
- A combination of the above
In general, default to the process requiring the least coordination available if you can't decide.
1. Are any of the criteria of the 'When should I loop in IRS IT SMEs?' section above met? -> RFC + ADR + loop in IRS IT SMEs as early as possible. See the long list of examples in the aforementioned section.
2. Is the feature set cross-cutting and requires multiple teams/pods to weigh in? -> RFC (ADR optional) + should confirm with IRS IT SMEs if there are upstream dependencies/compliance considerations that require documentation updates. Examples include
1. User-permissions
2. SADI
3. Major changes to MeF Integration
4. Major changes to the submission flow
5. Microservice messaging (queues, pub/sub)
3. Is the feature set within the domain of a single pod but cross-cutting between teams? -> RFC helpful but not required (ADR optional as well)
1. Addition of or modification to core functionality of a given microservice
4. Is the feature set within the domain of a single pod and within the domain a single team? -> RFC optional, depends on if the DRE feels it would be helpful to have a document separate from PR description or adding detail to ticket
1. Changes to MeF/PDF/Fact Graph conversion
2. Major additions or modifications to the UX flow
3. Implementing new tax logic within the flow/fact graph
4. Implementing or modifying retry logic for certain backend processes (e.g. sending email)
5. Requesting infrastructure configuration changes for previously-provisioned resources, such as changing the redrive policy on SQS for certain queues
5. Does the feature set have pre-existing, well defined product and technical requirements? -> PR/ticket is sufficient, no need for RFC or ADR
1. Modifying pre-existing tax logic within the flow/fact graph
2. Adding new repositories,interfaces, classes, services, etc. that clean up parts of the codebase
3. General refactoring
4. Spring-ifying the backend services
5. Updating dependencies
6. Remediating security findings

View file

@ -0,0 +1,42 @@
# Code generation for a React frontend
Our system is build on a Fact Graph and a Flow. The Facts have no awareness of presentation concerns, while the Flow encapsulates ordering and grouping of questions, along with pointers to human language translations of user-facing questions.
### Tom's suggestions:
Facts will have some properties:
- A way of getting graph specified validation into the system
- A way of referring to other constraining facts (charitable deduction for marital status)
- A name or identifier for being found and focused later
This tends to indicate that there should be some version of the fact graph in memory on the client side.
Each page will also need to have some properties:
- A series of templates for different page styles and layouts -- how will people know which to use?
- Well defined results for front and back actions
- The ability to jump to an arbitrary page (maybe by fact alone)
- A post action that sends the current state to the server
- Analytics
Because of the well ordered nature of the flow, and the need to be able to identify where facts are, we should use something like an FSM flow for pages. The actions above represent transitions to other states.
Page Information Singleton:
There can only ever be one of these in the system. The page information singleton contains the generated configuration that the front end understands. This configuration contains things like the IDs and friendly names, a dictionary of <fact name, page> so that individual facts can be found.
Page Manager FSM:
Each page is some data about what to display and how. It has a view template that lays out the page, zero or more fact templates that are applied to that template, a defined forward action, a defined back action, and ID for the page, and a friendly name for the URL. As the user works their way through the flow, the page manager will pull the information about which page to display from the Page Information Singleton
The implication here is that an external system generates the React frontend system. We start with a template react frontend that has the css and some of the basic tools in it. This external system then generates all of the pages, the frontend configuration for the page information singleton, and there are probably a few other pieces. Most of the fuzz is around the review step and how that will look in an autogenerated system. What I don't think will look good is if we just link directly back to the page in the flow without some indication that you are in the review process. I would also want the forward and back to go back to the review section and not start you into the flow again.
Testing:
We should be able to, in an automated way, run through the entire frontend application and verify that all of the paths work, all of the validators work, all of the constraints work, and that the product produces correct results.
Questions:
Will a page ever need alternate layouts? I am imagining a review section in which we may want forward and backward to work completely differently, and for the site to maybe look a bit different.
Should the site be generated on some other backend or should it kind of generate itself? I can imagine, if the need for multiple templates happens, that it would be nice to have a system that can dynamically generate itself. I can see massive problems with it too (like testing completeness).

74
docs/rfc/rfc-template.md Normal file
View file

@ -0,0 +1,74 @@
# RFC: [Title Here]
- Created: [mm/dd/yyyy]
- Approver(s):
- PR: if applicable
- Gitlab Issue: if applicable
# Primary author(s)
[primary authors]: #primary-authors
who owns this document and should be contacted about it?
# Collaborators
[collaborators]: #collaborators
anyone who contributed but isnt a primary author.
# Problem Statement
[problem statement]: #problem-statement
Why are we doing this? What use cases does it support? What is the expected outcome?
# Prior Art
What existing solutions are close but not quite right? How will this project replace or integrate with the alternatives?
# Goals and Non-Goals
[goals and non-goals]: #goals-and-non-goals
What problems are you trying to solve? What problems are you not trying to solve?
# Key terms or internal names
Define terms and language which might be referenced in the background and Suggested Solution below
# Background & Motivation
[background and motivation]: #background--motivation
What is the current state of the world? Why is this change being proposed?
# Suggested Solution
[design]: #suggested-solution
What exactly are you doing? Include architecture and process diagrams.
This is typically the longest part of the RFC.
# Timeline
[timeline]: #timeline
What is the proposed timeline for the implementation?
# Dependencies
[dependencies]: #dependencies
What existing internal and external systems does this one depend on? How will it use them?
# Alternatives Considered
[alternatives]: #alternatives-considered
What other approaches did you consider?
# Operations and Devops
[operations]: #operations-and-devops
What operational work is needed to implement this idea? What kind of IRS SME's should be involved? What is the "lift" from an operational perspective?
What additional telemetry and monitoring would be required to implement this?
# Security/Privacy/Compliance
[security privacy compliance]: #security-privacy-compliance
What security/privacy/compliance aspects should be considered?
# Risks
[risks]: #risks
What known risks exist? What factors may complicate your project?
Include: security, complexity, compatibility, latency, service immaturity, lack of team expertise, etc.
# Revisions
[revisions]: #revisions
RFC Updates for major changes, including status changes.
- created
- updated
- revisions based on feedback
- final status

91
docs/rfc/sqs-listeners.md Normal file
View file

@ -0,0 +1,91 @@
# RFC: SQS listener configuration
- Created: 9/10/2024
- Status: created
# Problem Statement
[problem statement]: #problem-statement
Which approach will we use to improve the graceful shutdown of SQS listeners in
Direct File's microservices?
# Goals and Non-Goals
[goals and non-goals]: #goals-and-non-goals
- Primary goal: Eliminate SQS exceptions seen on routine application shutdown
during deployments
- Secondary goal: Reduce complexity of SQS listener configuration
# Background & Motivation
[background and motivation]: #background--motivation
Currently, the class that sets up the SQS Connection (named
`SqsConnectionSetupService` in most, if not all, cases) in each microservice
includes a `@PreDestroy` method to stop and close the JMS SQS connection factory
during application shutdown. Even with this method in place, as old containers
shut down during rolling application deployments, they generate consumer
prefetch and receive message exceptions.
The `SqsConnectionSetupService` classes also contain a significant amount of
boilerplate code and must be updated anytime a microservice needs to subscribe
to another SQS queue.
# Suggested Solution
[design]: #suggested-solution
Create a Spring Boot starter (e.g., `irs-spring-boot-starter-sqs-jms`) that uses
`org.springframework:spring-jms` to manage the SQS connection factory. Having
Spring JMS manage the lifecyle of the listener containers should improve the
graceful shutdown. At the very least, implementing this solution will allow us
to test this and confirm whether we see an improvement.
Encapsulating the configuration in a Spring Boot starter will simplify the setup
for Direct File Spring Boot microservices that subscribe to SQS queues.
Implementation steps:
- Add the starter and integrate with the backend in one PR to start
- Integrate other apps with the starter in separate PRs (email-service, status,
submit
# Timeline
[timeline]: #timeline
About 1 sprint to implement the Spring Boot starter and update the various
microservices to use it. Initial prototyping and testing has already been done.
# Dependencies
[dependencies]: #dependencies
This solution will add a new Java dependency: `org.springframework:spring-jms`.
# Alternatives Considered
[alternatives]: #alternatives-considered
- Spring Cloud AWS. Spring Cloud AWS could also simplify our SQS configuration
and likely have a similar benefit in terms of improving graceful shutdown.
If we were already using Spring Cloud AWS, I would lean towards using it for
SQS. However, Spring Cloud AWS does not yet support Spring Boot `3.3.x`. Given
that we already use JMS for the SQS listeners, introducing the Spring JMS
project should be a lower lift.
- Explore other modifications to `SqsConnectionSetupService`. Perhaps there is a
way to modify our existing SQS connection setup to improve the graceful
shutdown, but it is unclear what that implementation would look like, and at
this point, there is likely value in exploring whether there is an existing
framework/library that can solve this problem for us.
# Operations and Devops
[operations]: #operations-and-devops
No operational/devops work expected.
# Security/Privacy/Compliance
[security privacy compliance]: #security-privacy-compliance
No security/privacy/compliance impacts expected.
# Risks
[risks]: #risks
Adds a new dependency, which may require some time for the team to get familiar
with, but this risk should be minimized by the fact that the applications would
still be using JMS, rather than making more significant changes to how the
application manages SQS subscriptions/listening.
# Revisions
[revisions]: #revisions
RFC Updates for major changes, including status changes.
- created
- updated
- revisions based on feedback
- final status

View file

@ -0,0 +1,86 @@
Created At: July 19, 2024
Updated At: May 26, 2024
RFC: Status Service 2.0 (f/k/a One Status to Rule them All)
# Problem Statement
Today, the editability of a tax return within the Client is computed differently than the status banner that is shown to the taxpayer within the Client as well as the exportability of a tax return into a State filing tool. The discrepancy of editability vs. exportability/status representation has been a constant topic of conversation since last filing season and a major source of confusion from an engineering and operational perspective. Moreover, the current design adds a large amount of unnecessary overhead in REST calls and database queries to and within the Status service, which cannot be scaled to accommodate increased load. 50x more scale in FS25 would risk introducing performance related problems under load in production.
This RFC proposes a unification of these statuses into a single, pre-existing status that controls all operations related to post-submission processing from the standpoint of the Client, Backend and State-API.
# Background
## Application Considerations
The statefullness of the Status services derived from the 2023 need to demo a full POC of Direct File. The current design is built directly on the POC in a way that causes multiple datastores across microservices to store redundant data.
The exportability of a tax return for State-API purposes and the status representation logic in the Client is based on logic within the Status service (specifically the TaxReturnXMLController that interfaces with the AcknowledgementService). Both operations are sent through internal REST calls from State-API and Backend, respectively, to the Status service, which handles all the business and database logic.
However, the editability of a tax return is wholly controlled by the Backend service and Backend database, specifically in the TaxReturnService.isTaxReturnEditable() logic which under the hood makes a query against the TaxReturnSubmissionRepository which queries the TaxReturnSubmission and SubmissionEvent tables.
## Architectural Considerations
The Status service has a single pod running in each region. It doesn't have autoscaling enabled in any way, which means that the only way we can scale it is vertically. For reference, the Backend service can scale to 96 pods max (48 per region). The client makes this call every 60 seconds whenever a user has an active session and is on the dashboard (post-submission), until a non-pending status is returned. For a given 15 minute session, this means that the client could make 15 calls to poll the status, if the return is determined to be pending for that time period. This creates a situation where nearly all requests are unnecessary and just add overhead to the Backend and Status services.
# Why we should expect the Status service to become a bottleneck in FS25 and beyond
The current design is not positioned to scale well in FS25 and beyond. Today, exporting a return and fetching the status are the two most expensive API calls we have throughout our systems, typically lasting between 3-10 seconds (depending on system load). Under an order of magnitutde of increased load, we would expect to see further elevated latency for these operations, likely on the order of 10-20 seconds. This is because of increased resource consumption/contention in the Status service, particurlarly at the database level. In other words, the Status service will become a bottleneck that will have cascading effects onto the State-API, Backend and Client, and directly onto the taxpayer.
If we have a huge rush of traffic from both the client (via the Backend) and State-API (first day, last day of filing season), we will greatly increase the number of cross-service REST calls and database queries in a way that would hamper performance for other parts of the Status service, for instance polling MeF for acknowledgements (its primary purpose). It will also provide poor user experiences for filers trying to export their returns, as well as cause confusion if/when the editability of a return within the Client is different than the banner indicating the return's status.
# Proposal
There are a few ways to solve this bottleneck problem:
1. Deprecate the Status service's endpoint completely and instead rely on the Backend database as the source of truth for statuses as well as horizontal scaling capacity of the backend for throughput purposes.
2. Convert the Status service's endpoint to consume submissionIds instead of taxReturnIds and caching the results in Redis (with a short-ish TTL)
3. Remove the Backend as the proxy for requests to the Status service and make calls directly to the Status service
4. Decrease the rate at which the client polls the /status endpoint
Each solution has pros and cons, however I would advocate that we implement Solution 1. Solution 2 is a fallback, and both are discussed below.
## What does the system look like if we implement Solution 1?
* Fetching return status into the Client and exporting a return to the State filing tool are significantly more performant through a combination of caching, no internal REST calls, reduced number of database calls, and reliance on the Backend horizontal pod autoscaling.
* Tax return editability in the Client is managed by the Backend database
* Tax return exportability to State filing tools is managed by the Backend database and accessed via a Backend internal API
* Tax return editability and exportability are managed by the same domain object (SubmissionEvent) and are thus much easier to reason about.
* There are no internal API calls to the Status service
* The same guardrails for always preferring accepted submissions is in place, guarding us against duplicate submissions.
# Solution 1 Implementation Proposal
* [ ] \[STEP 1, START HERE\] Migrate the AcknowledgementService.getLatestSubmissionIdByTaxReturnIdPreferringAcceptedSubmission logic to the TaxReturnService and refactor the underlying query to rely on SubmissionEvents instead of Completed/Pending objects.
* [ ] This interface should be the single SOT for determining if a return is accepted or rejected, for frontend editability and state-api export purposes.
* [ ] It should probably be named something like `getLatestSubmissionEventByTaxReturnIdPreferringAcceptedSubmissions`
* [ ] Migrate the Status service's AcknowledgementController.get() interface into the Backend app and expose the internal endpoint to the State-API.
* [ ] The query logic at AcknowledgementController.java#L56 can be deprecated and instead leverage the new interface in the TaxReturnService described in step 1.
* [ ] Alternatively, implement this logic within the State API service itself for fetching XML from S3 depending on the outcome of the `/status` call?
* [ ] Migrate the Status service's TaxReturnXMLController into the Backend and expose the internal endpoint to the State-API.
* [ ] The getTaxReturnStatus in TaxReturnXmlController.java#L32) logic can be deprecated and instead leverage the new interface in the TaxReturnService described in step 1
* [ ] Migrate the SubmissionEvent table to either:
* [ ] Add a single rejection_codes column with a JSON type that can persist JSON that mirrors StatusResponseBody.rejectionCodes; or
* [ ] a 1:M join between SubmissionEvent and RejectionCodes (identical to Completed and Error today in the Status service e.g. AcknowledgementService.java#L441
* [ ] Modify the status-change SQS message payload to include Errors such that all information contained in a StatusResponseBody is included in the SQS message and can be persisted in the Backend database
* [ ] When consuming SQS message payloads, persist rejectionCodes appropriately into the SubmissionEvent or RejectionCodes table (as decided above). After the data is persisted to the database, cache the results as a submissionId:StatusResponseBody key-value pair in Redis.
* [ ] Modify the TaxReturnService.getStatus in TaxReturnService.java#L793 to:
* [ ] First, query for the latest submission ID of the tax return and use this ID as a key to check Redis to see if there is a corresponding StatusResponseBody value
* [ ] Cache hit: return the StatusResponseBody value to the client
* [ ] Cache miss: either due to TTL expiration or the return hasn't been received/acknowledged by MeF. Check the database using
`TaxReturnService.getLatestSubmissionEventByTaxReturnIdPreferringAcceptedSubmissions`
* [ ] If the status is accepted/rejected , construct a StatusResponseBody payload from combination of the SubmissionEvent status (+ RejectionCode if applicable) and return it to the client
* [ ] If status is anything else, the tax return hasn't been sent/received by MeF and the appropriate StatusResponseBody is `pending` .
* [ ] Deprecate all Controllers and internal APIs in the Status service. Goodbye!
# Solution 2 Implementation Proposal
* [ ] Add a new API to the AcknowledgementController in AcknowledgementController.java#L45 that accepts a single submission ID instead of a tax return ID. This API will be similar to the current `get()` method within the Controller, except that it will have a different query pattern that will look for the most recent submission of a tax return to just looking for the submission itself via the submission Id.
* [ ] Logic around handling cases where a submission is both accepted and rejected so remain in place (i.e. we should always return accepted if a duplicate condition exists)
* [ ] NOTE: An alternative here is to change the current Status service API to only accept submission IDs (which can be easily accommodated by the Backend as described below) and then expose an internal API in the backend `getMostRecentSubmission` that the State API service calls before calling the `status` endpoint to fetch the status of the latest submission and check if the return can be exported
* [ ] Convert the TaxReturnService.getStatus in TaxReturnService.java#L793 to query for the latest submission ID of the tax return. Before making calling the internal status endpoint, the backend first checks Redis to see if there is a key-value latest submission Id-AcknowledgementStatus pair exists.
* [ ] If a cache hit, return the AcknowledgementStatus response to the client without making a call to the Status service
* [ ] If a cache miss, make a HTTP request to the Status service `/status` endpoint to fetch the AcknowledgementStatus, cache the results and return the result to the client
* [ ] When an Acknowledgement is received within the Status service, update the Redis cache with the accepted/rejected status

View file

@ -0,0 +1,7 @@
# How to generate a tsc perf build
1. Make sure that the normal lint steps run first to generate all the factgraph related stuff
2. `cd` into the package whose tsc build you'd like to test (probably df-client-app/)
3. Run `npx tsc --generateTrace ~/my-tsc-trace-output-directory` replacing the output directory with whatever you'd like
4. Open chrome, in the address bar type `chrome://tracing/`
5. Click the load button to open up the trace generated in step 3. (Should be a json file called `trace.json`)

BIN
docs/testing/.DS_Store vendored Normal file

Binary file not shown.

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,130 @@
## Data Import Profiles
To test different scenarios of data we can get from the Data Import service, we have created **data import profiles**. "Marge" is the default **profile**.
## How do I test with these profiles?
**If you are a developer:**
1. Have the app running locally and go to the account page: http://localhost:3000/df/file/account/
2. Select Data Import Profile to show all the profiles.
3. Click on "Reset your account and use profile: [profile name]"
4. Click on "start a new return" from that same profile.
5. Go home and use DF: http://localhost:3000/df/file/home/
## Why do we have Simpsons characters for profiles?
Because they are fun.
## What do they do?
Here are some basic features of each profile as of Jan 16, 2025:
### Marge
Features:
- Complete About You data
- Has IP PIN
- Has 1 W2 from SPRINGFIELD ATOMIC POWER AND LIGHT
### Marge with only SADI success
Features:
- Complete About You data
- Error for IP PIN
- Error for W2s
### Bart, Lisa
Features:
- Complete About You data
- No IP PIN
- Has 1 W2 from Goods and Stuff
### Homer
Features:
- Complete About You data
- No IP PIN
- Has 1 W2 from SPRINGFIELD ATOMIC POWER AND LIGHT
### Lisa Knockout
Features:
- Complete About You data
- No IP PIN
- Has 1 W2 from Goods and Stuff with KO for Box 13 - Statutory Employee
### Grandma
Features:
- Complete About You data
- No IP PIN
- Has 1 W2 from Goods and Stuff
### Abe
Features:
- Complete About You data
- Mailing address and street address
- Street address has '.' and '&' in it
- Incomplete IP PIN
- Has 5 W2s
### December 27
- Complete About you data
- Has IP PIN
- Incomplete W2s
### Jon
- Complete About you data
- Made to test a really long name: "Johnjacobjingleheimer Kleinschmidtingtonheimer"
- Error for IP PIN and W2s
### Kent
- Complete About you data
- Made to test symbols in the name fields "_" and "$"
- No IP PIN
- Has 1 W2 from Channel 5
### Krusty
- Complete About you data
- No IP Pin
- Has 2 W2s that trigger all possible KOs from Data Import
### Milhouse
- Complete About you data with the email "thrillhouse@gmail.com" which is pretty cool, I mean objectively speaking
- No IP Pin
- Has 2 W2s from Goods and Stuff and Kwiki Mart
### Ned
- Complete About you data
- No IP Pin
- Has a W2 from Goods and Stuff with an employee address different from the filer's address in about you
- Has 1099 int
### Owen
- Complete about you data from Shmowen Shmoutts, made to test the null mailing address bug
- Has IP Pin
- Incomplete W2
### Sean
- Complete About you data
- No IP Pin
- Has 1 W2 from SPEEDWAY
### Sideshow Bob
- About you data but without email
- No IP Pin
- No W2s
### Rod
- KO 1099-INT
### Maude
- 6 1099-INTs
### Ned
- 1 1099-INT
## Fact Graph Shortcuts
Don't want to fill out all of Direct File just to test a data import feature? Here are some pre-made FactGraphs that get you to various sections:
### 1099-INT
- Rod profile FG:[rod_1099_ko.json](uploads/95c1bfab5d7de7db1e5ce66c8eabff52/rod_1099_ko.json)
- Maude profile FG:[maude_1099-ints.json](uploads/eae401f1c2836421f395f6edf086b329/maude_1099-ints.json)
- Ned profile FG:[ned_1099_ints.json](uploads/59cca7745f4029ce0e20ff34674a0fc4/ned_1099_ints.json)

View file

@ -0,0 +1,112 @@
# Fact Graph Library
## About these Fact Graphs
We made a limited number of starting assumptions for these filing status fact graphs. They are filled in so that TP1:
* Has an SSN
* Is a citizen
* Is an age within DF's range of support
* Lived and earned in a state that doesn't have its own state-specific questions in the flow (no AK, MD, NJ, or NY)
* Is NOT a dependent taxpayer (unless as specific filing status scenario calls for it, like a dependent QSS taxpayer)
<details>
<summary>The goal a Utility Fact Graph</summary>
**What we kept in mind when making these:**
- The goal of a Utility Fact Graph is to save **manual testers** time on tax return fill-in as they test many different scenarios.
- It's meant to be a no-frills foundation for further editing: it is not meant to capture the world of fact combinations that could result in a given filing status.
- Because Data Import functionality now locks down the SSN/ITIN and Date of Birth fields for TP1 in the UI, we chose to make all these fact graphs with an SSN and a set age: over or under 65. If a tester needs an ITIN or a different DOB for TP1, they will have to manually change that in the fact graph json or just fill in a fresh return in the UI.
**Utility fact graphs should:**
* be limited to answers and choices contained in Section 1, You and your family
* answer all questions that don't go to filing status determination in a vanilla way that doesn't lead to conditional questions or potential downstream effects
* only add a person to the Family and household section if a qualifying person is required for filing status eligibility
* avoid answering in ways that could impact things other than filing status (for example, even though a QSS qualifying person can be any age and a couple different relationship types, it could be confusing and potentially impact other tests if in the utility fact graph they were filled in as a 'foster child' instead of a biological child)
</details>
### How to use a fact graph in DF
1. Copy the text of the entire fact graph you want to load into DF
2. Start a new tax return in DF or use an existing return
3. Go to the Account menu in DF
4. Expand the accordion for "Upload data" that's in the orange box titled "Dev-only Control Panel"
5. Paste the whole fact graph into the box labeled "Paste factgraph"
6. Click "Upload fact graph from text"
7. Say OK in the dialog box that pops up asking if you want to overwrite the existing return
8. Go back to your tax return, your fact graph info should now be populated
## Single Filing Status
### Under 65
* [Single (1995, MA)](fact-graphs/single_1995_ma.json)
### Over 65
* [Single (1940, MA)](fact-graphs/single-1940-MA.json)
## Married Filing Jointly Filing Status
### Under 65
* [MFJ (1995, TN)](fact-graphs/mfj_1995_TN.json)
### Over 65
* [MFJ (1940, TN)](fact-graphs/mfj_1940_TN.json)
## Married Filing Separately Filing Status
### Under 65
* [MFS (by choice, 1995, TN)](fact-graphs/mfs_by_choice_1995_TN.json)
* [MFS (because spouse is NR, 1995, FL)](fact-graphs/mfs_w_nr_spouse_1995_FL.json)
### Over 65
* [MFS (by choice, 1940, TN)](fact-graphs/mfs_by_choice_1940_TN.json)
* [MFS (because spouse is NR, 1940, FL)](fact-graphs/mfs_w_nr_spouse_1940_FL.json)
## Head of Household Filing Status
### Under 65
* [HOH (TP unmarried, qp is their claimed dependent, 1995, TN)](fact-graphs/HOH_unmarried_claimed_dependent_1995_TN.json)
* [HOH (TP unmarried, qp is non-dependent, 1995, TN)](fact-graphs/HOH_unmarried_with_nondependent_hoh-qp_1995_TN.json)
* [HOH (TP considered unmarried for HOH, qp is their claimed dependent, 1995, TN)](fact-graphs/considered_unmarried_for_HOH_claimed_dep_qp_1995_TN.json)
* [HOH (TP considered unmarried for HOH, married to nonresident and lived together last 6 months, claimed dependent, 1995, TN)](fact-graphs/fact-graph-2024-12-10-hoh-considered-unmarried-nra.json)
* [HOH (TP considered unmarried for HOH, qp is non-dependent, 1995, TN)](fact-graphs/considered_unmarried_for_HOH_nondependent_hoh-qp_1995_TN.json)
### Over 65
* [HOH (TP unmarried, qp is their claimed dependent, 1940, TN)](fact-graphs/HOH_unmarried_claimed_dependent_1940_TN.json)
* [HOH (TP unmarried, qp is non-dependent, 1940, TN)](fact-graphs/HOH_unmarried_with_nondependent_hoh-qp_1940_TN.json)
* [HOH (TP considered unmarried for HOH, qp is their claimed dependent, 1940, TN)](fact-graphs/considered_unmarried_for_HOH_claimed_dep_qp_1940_TN.json)
* [HOH (TP considered unmarried for HOH, qp is non-dependent, 1940, TN)](fact-graphs/considered_unmarried_for_HOH_nondependent_hoh-qp_1940_TN.json)
## Qualifying Surviving Spouse Filing Status
### Under 65
* [QSS (QSS-qp is their claimed dependent, 1995, MA)](fact-graphs/QSS-1995-MA.json)
* [QSS (QSS-qp is a non-dependent, 1995, MA)](fact-graphs/QSS-nondepQP-1995-MA.json)
* Dependent Taxpayer QSS
* [QSS (TP is dependent taxpayer, QSS-qp doesn't meet dependent tests, 1995, MA)](fact-graphs/QSS-dependentTP-nondepQP-1995-MA.json)
* [QSS (TP is dependent taxpayer, QSS-qp meets dependent tests but TP can't claim them because TP is a dependent themselves, 1995, MA)](fact-graphs/QSS-dependentTP-QP-passes-dependent-tests-1995-MA.json)
### Over 65
* [QSS (QSS-qp is their claimed dependent, 1940, MA)](fact-graphs/QSS-1940-MA.json)
* [QSS (QSS-qp is a non-dependent, 1940, MA)](fact-graphs/QSS-nondepQP-1940-MA.json)
* Dependent Taxpayer QSS
* [QSS (TP is dependent taxpayer, QSS-qp doesn't meet dependent tests, 1940, MA)](fact-graphs/QSS-dependentTP-nondepQP-1940-MA.json)
* [QSS (TP is dependent taxpayer, QSS-qp meets dependent tests but TP can't claim them because TP is a dependent themselves, 1940, MA)](fact-graphs/QSS-dependentTP-QP-passes-dependent-tests-1940-MA.json)
## Tailored situations
* [Taxpayer with child who is their nondependent qualifying person for CDCC and EITC, but is not their nondependent qualifying person for HOH](fact-graphs/fact-graph-2024-12-11T19_29_51.720Z.json)
* [Taxpayer who potentially qualifies for CTC, ODC, CDCC, and EITC and is about to start the Credits section in DF](fact-graphs/fg-baseline-start-credits-ctc-odc-cdcc-eitc.json)

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show more