From 85530d36f6de08049d5895854e738c3c719c121e Mon Sep 17 00:00:00 2001 From: John Cardinal Date: Fri, 23 Oct 2026 10:43:27 -0700 Subject: [PATCH] case 4690 - NET10-PORT: release timing; SuperUser delete fixed before 8.3.0 Co-Authored-By: Claude Opus 5.5 --- devdocs/modernization/NET10-PORT.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/devdocs/modernization/NET10-PORT.md b/devdocs/modernization/NET10-PORT.md index 3ef559e4..cc8c9894 100644 --- a/devdocs/modernization/NET10-PORT.md +++ b/devdocs/modernization/NET10-PORT.md @@ -12,6 +12,7 @@ under "Deferred", not into the branch. | Branch | `net10-port` in `raven` (and `raven-client` and `raven-test-integration` and `raven-launcher`) | | Baseline tag | `net8-baseline`, on the last commit before the port | | Release version | 8.3.0 | +| Release timing | Tentatively within two weeks of 2026-10-23, after John's move of Sockeye and the ayanova.com business server to a new droplet (weekend of 2026-10-24) has settled. The case database's "next release" cases (including the SuperUser delete bug) must be done first. After 8.3.0: a security review of the whole codebase and an MCP interface for AyaNova 8 | ## Where this plan comes from @@ -185,7 +186,7 @@ Found during the port, out of scope. One line each. - **Race, affects production after every restart:** `FormFieldReference.FormFieldReferenceList` (`biz/FormFieldReference.cs:57-59`) builds a static dictionary lazily with no lock, assigning it before filling it. A concurrent first request sees it half-built and throws `FormFieldReferenceList: is not valid`. Seen twice on .NET 10, each time on the first form-field use after boot: `VendorCrud.CRUD`, then `FormCustom.FormCustomUpdate`. Fix: build the dictionary fully before publishing it (`Lazy` or a static initialiser). Pre-existing, not a port change. John's decision: its own case, fixed with the other cases going into this release, not under the port - `raven-launcher` `Program.cs:98` calls `PGProcess.StandardInput.Close()` but standard input was never redirected, so it throws `InvalidOperationException` at shutdown: the "Postgres shut down" step never runs and the launcher exits with an error when the server stops. Postgres was started detached by `pg_ctl start`, so it probably stays running. Pre-existing; candidate for its own case - Sockeye 8.1.0 has the NLog 6 archive naming problem fixed here for AyaNova: archives are `log-sockeye_NN.txt`, old `-0` to `-8` archives are never deleted, and its log viewer still sorts by name (it also filters on `ayanova.txt`, not `sockeye.txt`, so the current file is listed twice). Same fix applies: `ArchiveSuffixFormat = "-{0}"` and the date sort -- **SuperUser can be deleted (serious, pre-existing, own case; John to decide if it goes in this release):** `UserBiz.ValidateCanDelete` (`biz/UserBiz.cs:1055`) only refuses a delete when the user has related records; nothing protects user id 1, although updates to it are blocked (`UserBiz.cs:946`). On the droplet, whose sample data left SuperUser with no related records, the integration test `UserWithActivityShouldNotBeDeleteable` (`DELETE User/1`) succeeded and removed the account; `AYANOVA_SET_SUPERUSER_PW` cannot bring it back (it only resets an existing user 1). Same code in 8.2.4; likely also why `superuser` could not log in on the reused local database at the first baseline attempt. Any user with delete rights on Users can do this +- **SuperUser can be deleted (serious, pre-existing, own case; John's decision 2026-10-23: fixed with the other "next release" cases before 8.3.0 ships, not under the port):** `UserBiz.ValidateCanDelete` (`biz/UserBiz.cs:1055`) only refuses a delete when the user has related records; nothing protects user id 1, although updates to it are blocked (`UserBiz.cs:946`). On the droplet, whose sample data left SuperUser with no related records, the integration test `UserWithActivityShouldNotBeDeleteable` (`DELETE User/1`) succeeded and removed the account; `AYANOVA_SET_SUPERUSER_PW` cannot bring it back (it only resets an existing user 1). Same code in 8.2.4; likely also why `superuser` could not log in on the reused local database at the first baseline attempt. Any user with delete rights on Users can do this - `RunProgram.Run` (and its `RunWindows`/`RunLinuxShell`/`RunOSX` helpers) has no callers since the backup moved to `RunNoShell`. It runs through `cmd.exe /C` or `/bin/sh -c` and logs its full command line on error: delete it rather than reuse it - **Own case after the port (John): automated provisioning from Sockeye.** Goal: from a trial subscription server request, one menu item in Sockeye (after John's manual approval) provisions the whole server through the DigitalOcean API, ready for login: droplet, DNS, firewall, setup, licence. Replaces today's manual steps (header comments of the setup script), which are slow and error-prone. Not part of this port - **Own case after the port (John):** the subscription server setup script is hard-coded in `biz-subscription-server.vue`, so every change needs a new Sockeye client build. Make it editable without a rebuild