Update session notes for the v2.1.0 production deploy
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
d5a1080185
commit
48c206fd53
@ -40,7 +40,7 @@ Docs: <https://www.manageengine.com/products/service-desk/sdpod-v3-api/getting-s
|
|||||||
- **2026-10-15:** **Weather locations are a fixed list** (`src/places.js`), not free zip codes, so a browser can't make the server look up arbitrary places and the per-zip cache stays small. The `.env` zip is added to the list if it's missing.
|
- **2026-10-15:** **Weather locations are a fixed list** (`src/places.js`), not free zip codes, so a browser can't make the server look up arbitrary places and the per-zip cache stays small. The `.env` zip is added to the list if it's missing.
|
||||||
- **2026-10-15:** **Status rules stay in `.env`** (`STATUS_NAMES`, `UNASSIGNED_EXCLUDED_STATUSES`). They're the help desk's definition of open and closed, not a personal preference. Hiding a status column is per user, but hidden columns still count toward Total open.
|
- **2026-10-15:** **Status rules stay in `.env`** (`STATUS_NAMES`, `UNASSIGNED_EXCLUDED_STATUSES`). They're the help desk's definition of open and closed, not a personal preference. Hiding a status column is per user, but hidden columns still count toward Total open.
|
||||||
- **2026-10-15:** **Sound stays per browser** (`localStorage`), not in the saved settings, so a muted desk browser doesn't mute the wallboard signed in as the same person.
|
- **2026-10-15:** **Sound stays per browser** (`localStorage`), not in the saved settings, so a muted desk browser doesn't mute the wallboard signed in as the same person.
|
||||||
- **2026-10-15:** **Sign-in is limited by email domain (`ALLOWED_EMAIL_DOMAINS`).** Any Zoho account can approve our client, and before this, an outside account got a session and `/api/session` handed it the `.env` site, group and technician names (ticket queries failed with their token). Prod v2.0.0 has this gap. The callback now refuses other domains and revokes their token, `requireSession` re-checks every call so older cookies die too, and the server won't start without the setting. Students don't have Zoho accounts, so the domain is enough for now. Next step: check the user is an SDP technician at sign-in, which probably needs a users/technicians read scope.
|
- **2026-10-15:** **Sign-in is limited by email domain (`ALLOWED_EMAIL_DOMAINS`).** Any Zoho account can approve our client, and before this, an outside account got a session and `/api/session` handed it the `.env` site, group and technician names (ticket queries failed with their token). Prod v2.0.0 had this gap until v2.1.0 was deployed on 2026-10-16. The callback now refuses other domains and revokes their token, `requireSession` re-checks every call so older cookies die too, and the server won't start without the setting. Students don't have Zoho accounts, so the domain is enough for now. Next step: check the user is an SDP technician at sign-in, which probably needs a users/technicians read scope.
|
||||||
- **2026-10-16:** **No ticket subjects, anywhere (FERPA).** Subjects can name students or describe their situation. The closed feed and the unassigned query no longer put `subject` in `fields_required`, and the objects the server returns are built field by field, so a subject SDP sends anyway (if it ever ignores `fields_required`) is dropped before it leaves the server. Feed cards show the ticket number, technician and closing time. Don't add `subject`, `description` or any other free-text field to a query or response without a new review; to identify a ticket, use its number and open it in SDP.
|
- **2026-10-16:** **No ticket subjects, anywhere (FERPA).** Subjects can name students or describe their situation. The closed feed and the unassigned query no longer put `subject` in `fields_required`, and the objects the server returns are built field by field, so a subject SDP sends anyway (if it ever ignores `fields_required`) is dropped before it leaves the server. Feed cards show the ticket number, technician and closing time. Don't add `subject`, `description` or any other free-text field to a query or response without a new review; to identify a ticket, use its number and open it in SDP.
|
||||||
- **2026-10-15:** **`/api/names` makes the caller prove SDP access first** (a one-row requests query with their token) before returning the shared cache, so the names never go to a token SDP refuses.
|
- **2026-10-15:** **`/api/names` makes the caller prove SDP access first** (a one-row requests query with their token) before returning the shared cache, so the names never go to a token SDP refuses.
|
||||||
- **2026-10-15:** **No published ports in compose.** Docker's port publishing bypasses ufw, which would skip NPM's IP access list. The container joins NPM's network instead.
|
- **2026-10-15:** **No published ports in compose.** Docker's port publishing bypasses ufw, which would skip NPM's IP access list. The container joins NPM's network instead.
|
||||||
|
|||||||
102
docs/SESSION.md
102
docs/SESSION.md
@ -1,91 +1,45 @@
|
|||||||
# Session summary: 2026-10-15 (v2.1.0)
|
# Session summary: 2026-10-16 (v2.1.0, hotfix 2)
|
||||||
|
|
||||||
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`.
|
A short Claude Code session that removed ticket subjects from the dashboard (FERPA) and tagged the fix for production. Skylar then deployed v2.1.0 with the fix. Background is in `CLAUDE.md`, `docs/ROADMAP.md`, `docs/NOTES.md` and `docs/SECURITY.md`. The previous session (2026-10-15) added per-user settings, the email domain check and the security document; its details are in the git history and `NOTES.md`.
|
||||||
|
|
||||||
## Where things stand
|
## Where things stand
|
||||||
|
|
||||||
- v2.0.0 (per-user Zoho sign-in, Docker) is running in production.
|
- Branch `v2.1.0` is pushed and clean. Its latest commit is `d5a1080`, "Remove ticket subjects from SDP queries and the page".
|
||||||
- Branch `v2.1.0` is pushed with four commits on top of v2.0.0, and tagged **`v2.1.0-prod-hotfix`** (`2f137af`). The tag starts the Gitea image build. **The build and the production deploy haven't been confirmed.**
|
- That commit is tagged **`v2.1.0-prod-hotfix2`** (annotated) and pushed.
|
||||||
- Since that tag, these changes are **not committed**: `SECURITY.md` and `SESSION.md` moved into `docs/`, the open items section in `docs/SECURITY.md`, and the doc links in `CLAUDE.md` and the README.
|
- **Production runs v2.1.0 with hotfix 2**, deployed by Skylar on 2026-10-16 and working. The production `.env` has `ALLOWED_EMAIL_DOMAINS`, and the compose file has the `sdp-data:/app/data` volume. The sign-in gap from v2.0.0 is closed in production.
|
||||||
|
- The earlier tags are `v2.0.0-prod`, `v2.1.0-prod` and `v2.1.0-prod-hotfix` (`2f137af`, the email domain check).
|
||||||
### Before deploying v2.1.0 on the VPS
|
|
||||||
|
|
||||||
1. Add `ALLOWED_EMAIL_DOMAINS=mainecc.edu` (plus any campus domains staff use) to the production `.env`. **The server won't start without it.**
|
|
||||||
2. Add the `sdp-data:/app/data` volume to the compose file (on the service, plus the top-level `volumes:`), as in the repo's `docker-compose.yml`. Without it, saved settings are lost each time the container restarts.
|
|
||||||
3. `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
|
## What this session did
|
||||||
|
|
||||||
### Per-user settings (commits `9479b12`, `53c519e`, `817fa47`)
|
### Ticket subjects removed (commit `d5a1080`)
|
||||||
|
|
||||||
- **⚙ Settings** button, and a setup prompt on someone's first visit (Save, or Use the defaults).
|
- **Why:** subjects can name students or describe their situation, which is a FERPA risk.
|
||||||
- Settings per user:
|
- **Server (`src/tickets.js`):** the closed feed and unassigned queries no longer put `subject` in `fields_required`, and neither returned object includes it. The returned objects are built field by field, so a subject SDP sends anyway is dropped before it leaves the server.
|
||||||
- sites, groups and technicians, entered as tags with name suggestions; typing any name still works
|
- **Page (`src/public/index.html`):** feed cards now lead with the ticket number (monospace, class `ticket-id`), with the technician and closing time below. The hidden unassigned debug table lost its Subject column. The unused `.subject` and `.subject-cell` CSS is gone.
|
||||||
- how often the status table recounts (2 to 60 minutes) and how long the feed lasts (1 to 24 hours)
|
- **Docs:**
|
||||||
- weather location, from the campus list in `src/places.js`
|
- `docs/SECURITY.md`: section 5 lists what the page receives and has a "No ticket subjects" point. Open item 1 is updated: hosting approval is still needed, but now covers staff and operational data only. "How this was checked" has a line for this test.
|
||||||
- hidden panels (stat tiles, weather, feed) and hidden status columns
|
- `docs/NOTES.md`: a decision not to add `subject`, `description` or other free-text fields to any query or response without a new review.
|
||||||
|
- `README.md`: the debug list description.
|
||||||
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 `.env` are stored. This replaced the planned `localStorage` design, and the container now needs a volume (`/app/data` in 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 in `DATA_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.
|
|
||||||
- `PUT` and `DELETE /api/settings` validate everything (`LIMITS` in `src/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/session` gave it the `.env` site, group and technician names. **Production v2.0.0 still has this gap until v2.1.0 is deployed.**
|
|
||||||
- **The fix:** `ALLOWED_EMAIL_DOMAINS` is required.
|
|
||||||
- The callback refuses other domains and revokes their Zoho token.
|
|
||||||
- `requireSession` checks the domain again on every call, so older cookies stop working.
|
|
||||||
- Matching is exact, so lookalike domains are refused.
|
|
||||||
- `/api/names` now 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) and `ROADMAP.md` were updated as each piece landed.
|
|
||||||
|
|
||||||
### Verified
|
### Verified
|
||||||
|
|
||||||
- **Server, end to end** over a unix socket with axios stubbed:
|
- **Server, with axios stubbed** so SDP returned a subject on every ticket: neither query asked for `subject`, and nothing in the feed, unassigned or state output contained it.
|
||||||
- defaults and the first-visit state
|
- **Page:** the real `renderTicket` and `renderUnassignedList`, run in Node. Both rendered without subjects, and escaping still works.
|
||||||
- name suggestions: the region-wide query, the cache, and the access check before the cache is served
|
- **Skylar's own test** before tagging, then the production deploy, which is working.
|
||||||
- validation of every field, non-JSON bodies, and malformed JSON
|
- **Not verified by Claude:** a screenshot of the new card.
|
||||||
- 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
|
### Gitea push failures (not fixed)
|
||||||
- weather per zip
|
|
||||||
- reset, and saved settings surviving a restart
|
The first push of the session failed with `remote: Verify` and `Authentication failed`, and the retry worked. This happens now and then. The likely cause: Git Credential Manager 2.6.1 (the `generic` provider for git.vfsh.dev) signs in with Gitea's OAuth app. It stores an access token that expires after an hour (Gitea's default) and sends it without checking. Gitea refuses it, GCM throws it away, and the next push gets a fresh token. Skylar plans to switch the remote to SSH. Until then, retry a failed push once.
|
||||||
- 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
|
## Next steps
|
||||||
|
|
||||||
1. **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:
|
1. **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 SDP Cloud API docs. A new scope means everyone signs in again. It would also allow real pick lists for technicians. Nothing has been researched yet.
|
||||||
- **Closed feed:** `fetchClosedTickets` in `src/tickets.js` requests `subject` and returns it. The page shows it in `renderTicket` in `src/public/index.html`.
|
2. **Switch the Gitea remote to SSH** (Skylar).
|
||||||
- **Unassigned list:** `fetchUnassigned` requests `subject` and returns it. The page shows it in `renderUnassignedList`, the hidden debug list.
|
3. **Work through the open items in `docs/SECURITY.md`**, starting with MCCS IT approval for the hosting and the non-technician test.
|
||||||
|
4. **Carried over from earlier sessions:**
|
||||||
Drop `subject` from `fields_required` and 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, update `docs/SECURITY.md` (the page section, and open item 1) and `docs/NOTES.md`.
|
|
||||||
2. **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.
|
|
||||||
3. **Commit** the document moves and the open items.
|
|
||||||
4. **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 `pull` and `up -d`.
|
|
||||||
5. **Work through the open items in `docs/SECURITY.md`**, starting with MCCS IT approval for the hosting and the non-technician test.
|
|
||||||
6. **Carried over from earlier sessions:**
|
|
||||||
- check that the token renews after an hour
|
- check that the token renews after an hour
|
||||||
- README screenshots
|
- README screenshots, now showing the cards without subjects
|
||||||
- links to Zoho's documentation for the web sign-in flow
|
- links to Zoho's documentation for the web sign-in flow
|
||||||
- the status table scrolling sideways (see `NOTES.md`)
|
- the status table scrolling sideways (see `NOTES.md`)
|
||||||
- fill in campus satellites and confirm the zip codes in `src/places.js`
|
- fill in campus satellites and confirm the zip codes in `src/places.js`
|
||||||
@ -94,4 +48,4 @@ A Claude Code session that added per-user settings, closed a sign-in gap, and wr
|
|||||||
|
|
||||||
Start a Claude Code session in this repo and say something like:
|
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.
|
> Read docs/SESSION.md. Let's add the SDP technician check at sign-in: first find the right Zoho scope and endpoint.
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user