Inspiration
When a veteran dies, the family often needs the service file for burial honors or VA benefits. Requests can stall on mistakes that are easy to avoid, such as a request from someone who is not eligible, or a request for a file damaged in the 1973 St. Louis fire that doesn't give the National Archives the details it needs to rebuild the file. The rules are public, but they are spread across several archives.gov pages and they change. A guide with stale rules does harm, so I focused on the upkeep after release.
What it does
The page asks four questions: who is asking, the branch, the separation date and, optionally, the name used in service. It then shows whether the file is open to the requester, what it costs, when the record becomes archival, whether the 1973 fire likely affected it, what to gather and where to send the request. It also writes a cover letter to print and sign. The page runs in the browser and stores nothing.
Two custom GitLab Duo flows are built to handle the work after the code is written:
- Issue-to-MR has two agents. A scope check declines anything an agent should not change on its own, and a builder writes the change and its tests, runs them, commits with a DCO sign-off and opens a merge request linked to the issue.
- Pipeline Medic starts after a pipeline finishes, when a person's account started that pipeline. On a failed merge request pipeline, its fixer is set to read the logs and push a fix, with a limit of two attempts. On a passed one, its gatekeeper is set to review the diff against the project rules, post the pipeline's carbon figures and merge if the merge request is labeled
auto-merge. After a production deploy, its reporter posts a "Live in production" note on the issue. When amainor scheduled pipeline fails, its incident agent opens an issue. It did this on October 14, when the scheduled smoke test failed. Issue-to-MR did not pick up that issue, so it was fixed outside the flows, in merge request !6.
A daily scheduled pipeline checks that the archives.gov pages still contain the exact wording the rules depend on. If the National Archives changes a fee or a date, that check fails, and Pipeline Medic is set to open an issue. On October 17, issue #7 was filed, asking the daily check to also watch the fire's loss figures (about 80% of Army files and 75% of Air Force files in the affected ranges). Issue-to-MR's first session on it failed with no output. After a comment restarted it, a second session opened merge request !7. Its pipeline passed. Pipeline Medic did not start on it, so after I gave the go-ahead, it was merged from the scroll-ash-lab account at 8:21 PM HST that day. After the deploy, Pipeline Medic posted a "Live in production" note on issue #7.
That is the Supervised level: the agents take an issue to a tested, signed-off merge request, and a person decides whether to merge it.
How I built it
- Static HTML, CSS and JavaScript with no framework. The decision logic is a set of pure functions in
src/rules.js, and every fact lives inconfig/facts.jsonwith its source page. - Eight of the nine GitLab DevSecOps stages: Plan and Create through the two flows, and Verify, Secure, Package, Configure, Monitor and Govern in the CI/CD pipeline. The pipeline has a Release job, but it has not run yet. The pipeline runs lint, unit tests, an accessibility audit, GitLab SAST and secret detection, a security gate that fails on High or Critical findings, policy checks (MIT license, DCO, issue link, fact freshness, no credentials), a review app for each merge request that changes code, GitLab Pages for production, smoke tests and a generic package.
- Two custom flows written in the flow registry v1 YAML format, plus
AGENTS.md, two project skills and custom review instructions that the agents load.
I used AI coding assistants to write and test most of the code.
Sustainability
Every pipeline ends with an sci job that reports Software Carbon Intensity using the Green Software Foundation formula, SCI = ((E × I) + M) per R, with R as one pipeline run. Energy comes from each job's measured duration and Cloud Carbon Footprint coefficients for a 2 vCPU, 8 GB runner. Grid intensity is Google's published 2024 figure for us-east1, 576 gCO2e per kWh. That is the default region for GitLab's hosted Linux runners. Embodied emissions use the Cloud Carbon Footprint server baseline. Most jobs run only when the files they check have changed, and the sci job reports how many grams a pipeline saved compared with running every job. A merge request pipeline can run 13 jobs. On the project's own merge requests, a documentation-only change ran 4 of them, and the sci job reported 0.087 gCO2e for 0.75 runner-minutes. A change to the code ran 12, all but the source-drift check, which runs only when the facts file changes, and reported 0.361 gCO2e for 3.13 runner-minutes. The documentation-only run used about a quarter of the carbon. The gatekeeper is set up to post the figure on the merge requests it approves, but it has not posted one yet. The site is about 20 KB with no third-party requests.
Challenges I ran into
Closing the loop between the two flows. Pipeline Medic does not start on pipelines that an agent account created, so neither merge request Issue-to-MR opened (!4 and !7) was merged by a flow. Both were merged from the scroll-ash-lab account. A scheduled sweep would get around this, but this project's account does not have permission to create a scheduled flow trigger. For safety, I made every hard check a pipeline job, so the gatekeeper can only merge a green pipeline, and I limited automatic merges to merge requests the builder labels auto-merge. The fixer is set to stop after two attempts and hand off with a needs-human label instead of looping. The gatekeeper has not merged anything yet.
Accomplishments that I'm proud of
The tests cover the cases that trip people up: a year-only date in the year a record becomes archival, the Air Force fire cut-off at "Hubbard, James E." and Army discharges inside and outside the fire's date range.
What I learned
The hardest part of a guide like this is noticing when the National Archives changes a page.
What's next
Add the remaining NARA request types, such as replacement medals and medical records, and send the site's production response times to GitLab Observability so they are tracked alongside the carbon figures.
Built With
- css
- gitlab
- gitlab-ci
- gitlab-duo
- gitlab-pages
- html
- javascript
- node.js
Log in or sign up for Devpost to join the conversation.