Commit Graph

68 Commits

Author SHA1 Message Date
443d382394 case 4712 - customer contacts' pick lists limited to their own records
Step 4 of 4712 (security review F15). Pick lists checked only the Select role,
which customer contacts have for most types, and took the columns from the
request, so a contact could list every customer with phones and emails. For
contacts now: the customer list holds only their own customer (head office
contacts: their head office's customers); the unit list only their own
customer's units (head office contacts: the chosen customer, which must be
theirs; none until one is chosen); unit models as before; any other list 403.
pick-list/single names only those records. New CustomerPickList variant for a
single customer. Staff unchanged.

Checked: the contact's customer list went from 72 customers to its own one;
units only its own; vendors and users 403.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 14:14:43 -07:00
692fececc7 case 4716 - unit pick-list customer variant parsed as a number
UnitPickList.GetVariantCriteria put the value of a "customerid:<value>"
variant from the request into the query unparsed, reachable by any login
(security review F43, found during case 4712). The value is now parsed as a
long; anything else means no restriction, as 0 already did. The client's
format ("customerid: 5") still works.

Checked: new test fails on the old code, passes now; pick-list tests 10/10.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 14:08:01 -07:00
d75c3eecea case 4712 - customer contacts work only with their own service requests and units
Step 3 of 4712 (security review F14). The Customer role has change rights on
service requests and nothing checked whose they were. For customer contacts:
another customer's request is not found (read, update, delete); creating or
moving a request to a customer the contact does not own is refused (403); a
contact's request is always requested by that contact. unit/customerunit adds
units only to the contact's own customer (or one of its head office's).

Checked: another customer's request 404 (was 200), create for another customer
403, own request created and deleted.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 14:02:19 -07:00
bd4494abac case 4712 - customer contacts reach only their own customer's work orders
Step 2 of 4712 (security review F13). The customer work-order rights checked
only tag-based feature switches, never which customer a work order belongs to.
New UserBiz.CustomerContactOwnsCustomerAsync (own customer, or for a head
office contact a customer of its head office), used by:
- workorder/customer/{id}: another customer's work order is not found (404);
- customer work order report (-100): exactly one work order, which must be the
  contact's (the renderer used every id it was given);
- work order attachment list and download for contacts; other attachment types
  are refused to contacts (the customer screens show them only on work orders).

Checked: other customer's work order 404 (was 200); report on another's or on
two work orders not found; own customer report still accepted (202).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 13:52:31 -07:00
2b1adaa496 case 4712 - customer contacts limited to the routes the customer screens use
Customer contacts had the Customer role's Select and read rights on most record
types and could call any route whose staff role check they passed, including
several with no role check (security review F13 to F17). Step 1 of 4712: the
token middleware now answers 403 (same body as other 403s) to Customer and
HeadOffice users for any route not in CustomerContactRoutes, the routes the
customer screens use (read from raven-client). Anonymous routes are always
allowed. New routes stay closed to contacts unless added on purpose.
Ownership of the records these routes return follows in the next steps.

Checked: full integration suite 103 passed, 5 skipped, the same 2 known
failures as the baseline.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 13:44:02 -07:00
7b40caec8b case 4681 - done in sockeye: F40 fixed; repeatable fetch and fingerprint noted as a later case
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 12:55:10 -07:00
445f9b0d0a case 4717 - KPI interval accepted only as a known date unit
Six KPIs put the request's interval criterion into the query as
DATE_TRUNC('<interval>', ...) unchecked, reachable by staff down to
TechRestricted (security review F26). New KPIFetcher.DateTruncUnitOrNull
accepts only PostgreSQL's date_trunc unit names (any case); the seven KPIs that
read interval refuse anything else with "Invalid 'interval' criteria", the same
form as their existing missing-criteria errors. The client only sends day or
month. (WorkOrderByStatusList reads interval without using it; checked too.)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 12:36:52 -07:00
b1944b7ca3 case 4716 - pick-list search text passed as SQL parameters
PickListSqlBuilder put the search text and the tag search text into the SQL
inside quotes with no escaping, reachable by any login (security review F18);
an apostrophe in a search also made the query fail. The builder now writes
@plq / @pltag and PickListFetcher adds them as Npgsql parameters (same %text%
match; wildcards typed by the user still apply).

Changelog: searching selection lists for text with an apostrophe now works.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 12:28:43 -07:00
e58ab2c100 case 4715 - download file names checked
report/download and export/download (any download key), the log-file routes and
backup download built a path from the file name in the URL with Path.Combine
and no check, so on Windows a name with a folder part or an absolute path could
reach files outside the folder (security review F21). New helper
FileUtil.FullPathInFolderOrNull accepts only a bare file name that resolves
directly inside the folder; TemporaryFileExists and BackupFileExists use it
(the download routes already call them first), and so do both log routes.
A refused name gets the same 404 as a missing file.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 12:20:25 -07:00
705a54f9d8 case 4718 - report and translation import need create rights
report/upload and translation/upload had no role check, so any login, customer
contacts included, could import a report template (whose JavaScript runs in the
server's browser at render time) or a translation (security review F19, F24).
Both now require the same right as creating one, checked before the upload is
read. The import screens are already limited to those roles.

Checked locally: customer contact and Service 403, BizAdmin 202.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 12:10:00 -07:00
a843bd3132 case 4711 - JWT signing key generated by the server; AYANOVA_JWT_SECRET removed
The LAN/IIS and Linux templates shipped a placeholder secret printed in the
manual, and installs that kept it signed logins with a public key; any setting
also invited short or reused values (security review F1). The setting is now
ignored (one warning at boot if still present): the server generates a key once
(48 random bytes) into jwt-signing.key in the data folder (beside the app if
there is none; owner-only on Linux) and reuses it, so sign-ins also survive a
restart where the server used to make a new key each boot (standalone, Linux
desktop). If the file cannot be used, a temporary key is used for that run.

Templates and dev launch configs drop the setting; manual updated (key page
rewritten, setting steps removed from install pages); changelog line.

Checked locally: token forged with the old placeholder 401; key file created
and reused after restart (old token 200); auth and 2FA tests pass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 12:01:08 -07:00
5bf1f2700a case 4710 - done in raven and sockeye: F5 and F41 fixed
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 11:36:50 -07:00
141bdeb89c case 4710 - 2FA step requires the temp token from the password step
The 2FA step matched the user by temp token alone, and the token was left
empty after a successful 2FA login (null right after turning 2FA on), so an
empty or missing token skipped the password step (security review F5).
Now: an empty or missing temp token is refused before the lookup; the token is
cleared to null after success; after 5 wrong codes the token is cleared, so the
password must be entered again (counted in memory per user).

Changelog: general security notice for self-hosted upgrades, and the one
behaviour change users can see. SECURITY-REVIEW.md: F5 fixed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 11:28:17 -07:00
27e187bac6 Release 8.3.0 cases: John's edits of 2026-10-24
4713 takes F28; 4698 folded into 4711; F2 moved into 4579 (now priority 00);
4665 moved to the release after.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 10:42:32 -07:00
229fe208a7 Release 8.3.0 cases: Sockeye case 4681 takes F40 and the Sockeye half of F39
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 10:17:04 -07:00
67205ccf41 Release 8.3.0 case list, and security findings mapped to cases
John's "next release" cases (exported 2026-10-24) listed in NET10-PORT.md;
SECURITY-REVIEW.md maps each finding to its case. F28 has no case yet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-24 10:09:59 -07:00
fc3342df48 Security review: F34 client library upgrades approved for 8.3.0
John's decision: DOMPurify to 2.5.x and Vuetify to the latest 2.x (2.6.16 as the
fallback if 2.7 does not build on Node 12.22.9), as an exception to the
front-end dependency rule, each proven by a full client build and Cypress.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 20:38:59 -07:00
2fca018add Security review: F5, F1 and F18 also fixed in 8.3.0; findings gate the release
John's decision: 8.3.0 is not released until every finding is fixed or
explicitly accepted. The review therefore runs before the release, not after.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 19:58:31 -07:00
ee6def1932 Security review: F13 to F17 (customer contact isolation) fixed in 8.3.0
John's decision: urgent, "next release" cases before 8.3.0; hosted and
self-hosted installations equally. Recorded in SECURITY-REVIEW.md and in the
NET10-PORT.md list of cases for this release.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 19:55:50 -07:00
67cc5eafad case 4690 - CLAUDE.md and NET10-PORT: port merged into main; release work continues on main
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 17:24:43 -07:00
4351ee9706 case 4690 - NET10-PORT: tick or reword older open items with current evidence
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 17:07:53 -07:00
181b1e446e case 4690 - NET10-PORT: Windows LAN installer tested; all five packages installed and started
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 17:02:50 -07:00
daf093d51c case 4690 - Windows network install: official PostgreSQL download link (installer and manual); examples for PostgreSQL 18
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 16:06:27 -07:00
4ae9d53e72 case 4690 - .NET SDK 10.0.402 on the workstation: standalone and launcher bundle runtime 10.0.13; update-before-release note in BUILD.md
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 15:43:55 -07:00
67e2a37149 case 4690 - manual: only one type of Windows installation per computer (installers share one AppId by design)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 14:54:53 -07:00
92b4428146 case 4690 - NET10-PORT: John's decisions on the standalone findings; installer AppId notes
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 14:52:38 -07:00
9fcc70cf1c case 4690 - NET10-PORT: fix a row reference in the log
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 14:45:04 -07:00
5e64ac3250 case 4690 - NET10-PORT: Windows standalone installer test results; VC++ runtime, launcher shutdown impact and bundled runtime version recorded
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 14:44:50 -07:00
63b2a34cc8 case 4690 - standalone installer: create the empty PostgreSQL folders Git does not keep (fresh installs failed to start the database)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 14:44:19 -07:00
d81a88b607 case 4690 - NET10-PORT: Linux packages from the release build tested on Ubuntu 24.04; desktop data-path finding deferred
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 12:20:45 -07:00
a223a2bc65 case 4690 - build-release.bat: copy all output to build-output.txt; UTF-8 for MkDocs when piped
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 11:37:29 -07:00
b74a97016e case 4690 - NET10-PORT: customer manual item done
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 11:17:44 -07:00
523bb8f10b case 4690 - BUILD.md: backup laptop catch-up checklist (.NET 10 SDK and tooling changes made on the workstation)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 11:14:33 -07:00
fba399670d case 4690 - dev docs: build VM deprecated, releases built on the workstation (backup laptop as fallback)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 10:52:17 -07:00
2dbac07bf4 case 4690 - build docs: .NET 10 SDK for the server, launcher and build VM
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 10:48:06 -07:00
b4cfc54aa2 case 4690 - Windows installers: stop creating unused Chrome folders in the program folder; uninstall removes them
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 10:47:22 -07:00
afb0791ea8 case 4690 - LAN installer: Hosting Bundle prompt and link to .NET 10
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 10:44:34 -07:00
85530d36f6 case 4690 - NET10-PORT: release timing; SuperUser delete fixed before 8.3.0
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 10:43:27 -07:00
ce8c4d18a1 case 4690 - NET10-PORT: section 4 results on Ubuntu 26.04
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 09:43:22 -07:00
4d8754f037 case 4690 - NET10-PORT: Ubuntu 26.04 fresh install with the updated setup script
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 09:32:00 -07:00
b0399d93cc case 4690 - NET10-PORT: setup script plan for 26.04; Sockeye automated provisioning noted as a future case
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 09:10:39 -07:00
d3df5a8606 case 4690 - NET10-PORT: Linux report date format confirmed unchanged from 8.2.4
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 08:13:33 -07:00
bf0555fb31 case 4690 - report browser: launch chrome-headless-shell; writable config/cache folders for the browser; Ubuntu 24.04 droplet results
Full Chrome 155 would not start under a Linux service user with no writable
home (chrome_crashpad_handler: --database is required). chrome-headless-shell
starts, and measured on a 1 GB droplet is 3-4x faster and smaller per render.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 08:12:21 -07:00
b76cf098b7 case 4690 - NET10-PORT: test project retargeted; InvariantGlobalization left off; subscription setup script added to the port
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 20:57:38 -07:00
9af1034a88 case 4690 - data-list date filters: >= and < from the start of the minute, != excludes the whole minute; null check first
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 20:38:23 -07:00
892ef59608 case 4690 - report browser download/launch failures: logged at Error, specific error returned to the client
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 20:31:29 -07:00
a34e012eee case 4690 - report browser downloads under the data path, not beside the app; manual updated
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 20:25:00 -07:00
e8e7a2ec40 case 4690 - erase database: check CREATEDB before dropping, so a failed create can't leave no database
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 20:15:13 -07:00
78f5863947 case 4690 - backup: run pg_dump without a shell, password in PGPASSWORD, failures detected by exit code
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 20:00:52 -07:00
86ac9a2b96 case 4690 - remaining packages to current releases (Bogus, jose-jwt, QRCoder); Newtonsoft.Json direct reference
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 19:47:31 -07:00