Compare commits

..

8 Commits

Author SHA1 Message Date
Owen Schwartz
4ca5acf158 Merge pull request #2660 from fosrl/dev
Also update lastPing for legacy
2026-03-16 17:13:10 -07:00
Owen
ea41fcc566 Also update lastPing for legacy 2026-03-16 17:12:37 -07:00
Owen Schwartz
5736c1d8ce Merge pull request #2659 from fosrl/dev
Small improvements
2026-03-16 16:37:26 -07:00
Owen
d142366dd9 Merge branch 'main' into dev 2026-03-16 16:32:28 -07:00
Owen
bab09dff95 Add better metadata to ssh 2026-03-16 15:33:21 -07:00
Owen
23d3345ab9 Reduce writes 2026-03-16 14:37:27 -07:00
Owen Schwartz
09a64815d4 Merge pull request #2657 from fosrl/hotfix-jit
Fix jit on by default
2026-03-15 22:02:12 -07:00
Owen
6d5f969798 Fix jit on by default 2026-03-15 22:01:39 -07:00
7 changed files with 36 additions and 7 deletions

View File

@@ -415,7 +415,7 @@ jobs:
- name: Install cosign
# cosign is used to sign and verify container images (key and keyless)
uses: sigstore/cosign-installer@ba7bc0a3fef59531c69a25acd34668d6d3fe6f22 # v4.1.0
uses: sigstore/cosign-installer@faadad0cce49287aee09b3a48701e75088a2c6ad # v4.0.0
- name: Dual-sign and verify (GHCR & Docker Hub)
# Sign each image by digest using keyless (OIDC) and key-based signing,

View File

@@ -23,7 +23,7 @@ jobs:
skopeo --version
- name: Install cosign
uses: sigstore/cosign-installer@ba7bc0a3fef59531c69a25acd34668d6d3fe6f22 # v4.1.0
uses: sigstore/cosign-installer@faadad0cce49287aee09b3a48701e75088a2c6ad # v4.0.0
- name: Input check
run: |

View File

@@ -515,6 +515,6 @@ authenticated.post(
verifyOrgAccess,
verifyLimits,
verifyUserHasAction(ActionsEnum.signSshKey),
logActionAudit(ActionsEnum.signSshKey),
// logActionAudit(ActionsEnum.signSshKey), // it is handled inside of the function below so we can include more metadata
ssh.signSshKey
);

View File

@@ -14,7 +14,9 @@
import { Request, Response, NextFunction } from "express";
import { z } from "zod";
import {
actionAuditLog,
db,
logsDb,
newts,
roles,
roundTripMessageTracker,
@@ -34,6 +36,7 @@ import { canUserAccessSiteResource } from "@server/auth/canUserAccessSiteResourc
import { signPublicKey, getOrgCAKeys } from "@server/lib/sshCA";
import config from "@server/lib/config";
import { sendToClient } from "#private/routers/ws";
import { ActionsEnum } from "@server/auth/actions";
const paramsSchema = z.strictObject({
orgId: z.string().nonempty()
@@ -446,6 +449,20 @@ export async function signSshKey(
sshHost = resource.destination;
}
await logsDb.insert(actionAuditLog).values({
timestamp: Math.floor(Date.now() / 1000),
orgId: orgId,
actorType: "user",
actor: req.user?.username ?? "",
actorId: req.user?.userId ?? "",
action: ActionsEnum.signSshKey,
metadata: JSON.stringify({
resourceId: resource.siteResourceId,
resource: resource.name,
siteId: resource.siteId,
})
});
return response<SignSshKeyResponse>(res, {
data: {
certificate: cert.certificate,

View File

@@ -197,6 +197,12 @@ const connectedClients: Map<string, AuthenticatedWebSocket[]> = new Map();
// Config version tracking map (local to this node, resets on server restart)
const clientConfigVersions: Map<string, number> = new Map();
// Tracks the last Unix timestamp (seconds) at which a ping was flushed to the
// DB for a given siteId. Resets on server restart which is fine the first
// ping after startup will always write, re-establishing the online state.
const lastPingDbWrite: Map<number, number> = new Map();
const PING_DB_WRITE_INTERVAL = 45; // seconds
// Recovery tracking
let isRedisRecoveryInProgress = false;
@@ -855,12 +861,16 @@ const setupConnection = async (
const newtClient = client as Newt;
ws.on("ping", async () => {
if (!newtClient.siteId) return;
const now = Math.floor(Date.now() / 1000);
const lastWrite = lastPingDbWrite.get(newtClient.siteId) ?? 0;
if (now - lastWrite < PING_DB_WRITE_INTERVAL) return;
lastPingDbWrite.set(newtClient.siteId, now);
try {
await db
.update(sites)
.set({
online: true,
lastPing: Math.floor(Date.now() / 1000)
lastPing: now
})
.where(eq(sites.siteId, newtClient.siteId));
} catch (error) {

View File

@@ -97,6 +97,7 @@ export async function flushSiteBandwidthToDb(): Promise<void> {
accumulator = new Map<string, AccumulatorEntry>();
const currentTime = new Date().toISOString();
const currentTimeEpochSeconds = Math.floor(new Date().getTime() / 1000);
// Sort by publicKey for consistent lock ordering across concurrent
// writers — deadlock-prevention strategy.
@@ -119,7 +120,8 @@ export async function flushSiteBandwidthToDb(): Promise<void> {
.set({
megabytesOut: sql`COALESCE(${sites.megabytesOut}, 0) + ${bytesIn}`,
megabytesIn: sql`COALESCE(${sites.megabytesIn}, 0) + ${bytesOut}`,
lastBandwidthUpdate: currentTime
lastBandwidthUpdate: currentTime,
lastPing: currentTimeEpochSeconds
})
.where(eq(sites.pubKey, publicKey))
.returning({
@@ -321,4 +323,4 @@ export const receiveBandwidth = async (
)
);
}
};
};

View File

@@ -227,7 +227,7 @@ export const handleOlmRegisterMessage: MessageHandler = async (context) => {
// Prepare an array to store site configurations
logger.debug(`Found ${sitesCount} sites for client ${client.clientId}`);
let jitMode = true;
let jitMode = false;
if (sitesCount > 250 && build == "saas") {
// THIS IS THE MAX ON THE BUSINESS TIER
// we have too many sites