deleteOrg.childTest.ts read its leftover counts with db.get(sql...), a better-sqlite3 driver method. The pg config type-checks the same file with the pg driver's types, where .get() does not exist, so build-postgres failed on PR #3895's head (TS2339 at deleteOrg.childTest.ts:108) and main has carried the break since the merge landed 40 seconds before the job reported red. Read the counts through the query builder instead - the same .select({ count: count() }) shape deleteOrg.ts itself uses, which compiles under both configs - keeping the observations JSON the parent test parses unchanged.
Signed-off-by: Manas Choksi <12302040701105@mbit.edu.in>
Signed-off-by: choksi2212 <choksi2212@users.noreply.github.com>
deleteOrgById fetched the org's sites with .limit(1), so the per-site
cleanup loop ran for at most one site: the WireGuard deletePeer call,
the Newt terminate collection, and cleanupSiteAssociations were all
skipped for every other site in the org.
Drop the limit so every site is loaded, and mirror deleteSite.ts in the
loop: run cleanupSiteAssociations for newt sites so clients of other
orgs do not keep stale associations for the deleted sites.
Covered by a standalone regression test that seeds two wireguard and
two newt sites plus a stale association-cache row, runs deleteOrgById
against a stubbed exit node, and asserts all four sites were cleaned.
On the previous code the test fails with exactly the reported symptom:
one peer removal instead of two.
Fixes#3863
A leading '-' only matters when the value is not a plain number, so
-12 and -1.5 stay numeric while payloads like -2+3+cmd|'/c calc'!A0
still get the apostrophe prefix.
generateCSV escaped quotes only when a value happened to contain a comma and never neutralised formula prefixes, so every CSV log export could emit attacker controlled cells that execute when an admin opens the file. actor is a virtual API key name validated as nothing more than a non-empty string, and path, host, originalRequestURL, metadata and the AI session bodies come straight from the client request.
Each value now goes through a single encoder that collapses CR, LF and CRLF to a literal \n so a record can never be split across rows, prefixes a leading apostrophe when the first character would make a spreadsheet evaluate the cell as a formula, and quotes whenever the field contains a comma or a quote instead of only when it contains a comma. Headers use the same encoder so a column name cannot desynchronise the rows from the header row.
The five CSV export endpoints also declare charset=utf-8, matching the content type already used by the log streaming destination.
Fixes#3864