docs/SECURITY.md covers the layers of protection, what is stored, third parties, limits and open items to investigate. SESSION.md moves to docs/ and is rewritten as the handoff for removing ticket subjects next. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
7.1 KiB
Session summary: 2026-10-15 (v2.1.0)
A Claude Code session that added per-user settings, closed a sign-in gap, and wrote the security document. Background is in CLAUDE.md, docs/ROADMAP.md, docs/NOTES.md and docs/SECURITY.md.
Where things stand
- v2.0.0 (per-user Zoho sign-in, Docker) is running in production.
- Branch
v2.1.0is pushed with four commits on top of v2.0.0, and taggedv2.1.0-prod-hotfix(2f137af). The tag starts the Gitea image build. The build and the production deploy haven't been confirmed. - Since that tag, these changes are not committed:
SECURITY.mdandSESSION.mdmoved intodocs/, the open items section indocs/SECURITY.md, and the doc links inCLAUDE.mdand the README.
Before deploying v2.1.0 on the VPS
- Add
ALLOWED_EMAIL_DOMAINS=mainecc.edu(plus any campus domains staff use) to the production.env. The server won't start without it. - Add the
sdp-data:/app/datavolume to the compose file (on the service, plus the top-levelvolumes:), as in the repo'sdocker-compose.yml. Without it, saved settings are lost each time the container restarts. docker compose pull && docker compose up -d, then check:- an MCCS account signs in and gets the setup prompt
- a personal Zoho account is sent back with "not allowed"
What this session did
Per-user settings (commits 9479b12, 53c519e, 817fa47)
-
⚙ Settings button, and a setup prompt on someone's first visit (Save, or Use the defaults).
-
Settings per user:
- sites, groups and technicians, entered as tags with name suggestions; typing any name still works
- how often the status table recounts (2 to 60 minutes) and how long the feed lasts (1 to 24 hours)
- weather location, from the campus list in
src/places.js - hidden panels (stat tiles, weather, feed) and hidden status columns
The ding plays even with the feed hidden. Statuses and sound aren't per user.
-
Storage: on the server in
DATA_DIR/settings.json, keyed by the lowercased Zoho email, so settings follow people between browsers. Only values that differ from.envare stored. This replaced the plannedlocalStoragedesign, and the container now needs a volume (/app/datain Docker). -
Name suggestions (
/api/names,src/names.js): one region-wide query of recent tickets (30 days, up to 500 tickets, names only). It's refreshed at most hourly, shared by all users, and kept inDATA_DIR/names.json. No new Zoho scope was needed. A typed name that differs from SDP's only in case is saved with SDP's spelling. -
Server side:
- The server reads each user's settings itself; the page doesn't send them with each call.
PUTandDELETE /api/settingsvalidate everything (LIMITSinsrc/settings.js).- Weather is cached per zip.
- The closed feed's hard-coded 12-hour cut-off was removed, since the feed length is now a setting.
Sign-in limited to email domains (commit 2f137af)
- The gap: any Zoho account can approve our client. An outside account got a session, and
/api/sessiongave it the.envsite, group and technician names. Production v2.0.0 still has this gap until v2.1.0 is deployed. - The fix:
ALLOWED_EMAIL_DOMAINSis required.- The callback refuses other domains and revokes their Zoho token.
requireSessionchecks the domain again on every call, so older cookies stop working.- Matching is exact, so lookalike domains are refused.
/api/namesnow makes the caller's own token read one row from SDP before it returns the shared names.
Documents
docs/SECURITY.md, written for MCCS IT leadership and reviewers. It covers each layer of protection, what is stored, third parties, the limits, 12 open items to investigate, and how everything was tested.- The README,
env.example,NOTES.md(decisions) andROADMAP.mdwere updated as each piece landed.
Verified
- Server, end to end over a unix socket with axios stubbed:
- defaults and the first-visit state
- name suggestions: the region-wide query, the cache, and the access check before the cache is served
- validation of every field, non-JSON bodies, and malformed JSON
- saving: only values that differ from the defaults are stored, and names take SDP's spelling
- the closed and workload queries use the saved region and feed length
- weather per zip
- reset, and saved settings surviving a restart
- the domain check: outside, lookalike and missing emails, a second allowed domain, an outsider's pre-existing cookie, and startup without the setting
- Page, in jsdom with stubbed fetch:
- the setup prompt, and suggestions leaving out names already chosen
- tag adding and removal, Enter, Backspace, and a typed but un-added name counting on save
- a server error shown inside the dialog, and the save body
- after a save: the feed restarting, the recount, the weather reloading, and hidden panels and columns
- reset, and the full-width layout
- Not verified:
- anything against real SDP or Zoho
- how the dialog looks; there's no Chrome or Edge on the dev Mac for a screenshot
- the Gitea build of the hotfix tag
Next steps
-
Remove ticket subjects (first thing tomorrow). Ticket subjects can name students or describe their situation, which is a FERPA risk. They reach the page in two places:
- Closed feed:
fetchClosedTicketsinsrc/tickets.jsrequestssubjectand returns it. The page shows it inrenderTicketinsrc/public/index.html. - Unassigned list:
fetchUnassignedrequestssubjectand returns it. The page shows it inrenderUnassignedList, the hidden debug list.
Drop
subjectfromfields_requiredand from the returned objects, so it never leaves SDP, and update both render functions. The server never writes subjects to disk; they only pass through memory and the page. Afterwards, updatedocs/SECURITY.md(the page section, and open item 1) anddocs/NOTES.md. - Closed feed:
-
Technician check at sign-in (the ROADMAP item). Ask SDP whether the signed-in user is a technician. That probably needs a users or technicians read scope; confirm the exact scope name and endpoint in Zoho's docs. A new scope means everyone signs in again. It would also allow real pick lists for technicians.
-
Commit the document moves and the open items.
-
Deploy v2.1.0, following the checklist above. Then try it live: the quality of the name suggestions, the setup prompt, and the volume surviving a
pullandup -d. -
Work through the open items in
docs/SECURITY.md, starting with MCCS IT approval for the hosting and the non-technician test. -
Carried over from earlier sessions:
- check that the token renews after an hour
- README screenshots
- links to Zoho's documentation for the web sign-in flow
- the status table scrolling sideways (see
NOTES.md) - fill in campus satellites and confirm the zip codes in
src/places.js
To pick up
Start a Claude Code session in this repo and say something like:
Read docs/SESSION.md and docs/SECURITY.md. First, remove ticket subjects from everything the server requests and the page shows (FERPA). Then we'll add the SDP technician check at sign-in.