fix: address code review findings from 2026-08-17

- scope no-cache headers to non-static routes (restore immutable asset caching)
- reset cached rejected MongoDB promise so retries can succeed
- use last X-Forwarded-For entry in Content Editor rate limiter (anti-spoofing)
- remove weak Mongo defaults from compose files (fail loudly on missing env)
- move staging banner text to common.json content
- read APP_PORT from env file in deploy.sh healthcheck
- filter network noise from staging smoke console assertions

Closes MITHOME-48, MITHOME-49, MITHOME-50, MITHOME-51, MITHOME-52, MITHOME-53, MITHOME-54
This commit is contained in:
Do Siki
2026-08-18 12:21:32 +02:00
parent 93aaa10a36
commit bd7287aa58
14 changed files with 115 additions and 17 deletions
+2 -1
View File
@@ -6,6 +6,7 @@ import Header from "../components/Header";
import Footer from "../components/Footer";
import { ThemeProvider } from "../components/ThemeProvider";
import { siteConfig } from "../config/site";
import { common } from "../content";
const geistSans = Geist({
variable: "--font-geist-sans",
@@ -93,7 +94,7 @@ export default function RootLayout({
<ThemeProvider>
{isStaging && (
<div className="bg-amber-400 px-4 py-2 text-center text-xs font-extrabold tracking-[0.18em] text-amber-950 sm:text-sm">
STAGING / TESZTKÖRNYEZET A STAGING OLDALT LÁTOD
{common.staging.banner}
</div>
)}
<Header />
+3
View File
@@ -13,5 +13,8 @@
"required": "Ez a mező kötelező",
"invalidEmail": "Érvénytelen email cím formátum",
"minLength": "Legalább {min} karakter szükséges"
},
"staging": {
"banner": "⚠ STAGING / TESZTKÖRNYEZET — A STAGING OLDALT LÁTOD"
}
}
+1
View File
@@ -14,6 +14,7 @@ const schemas = {
buttons: object({ contact: string, learnMore: string, webmail: string, sendMessage: string }),
labels: object({ required: string, features: string }),
validation: object({ required: string, invalidEmail: string, minLength: string }),
staging: object({ banner: string }),
}),
home: object({
hero: object({ title: string, subtitle: string, description: string, trustBullets: array(string), cta: object({ primary: ctaLink, secondary: ctaLink }) }),
+3
View File
@@ -190,6 +190,9 @@ export interface CommonContent {
invalidEmail: string
minLength: string
}
staging: {
banner: string
}
}
export interface LegalPageContent {
+18
View File
@@ -139,5 +139,23 @@ describe('MongoDB Connection (Unit Tests)', () => {
// Should be the same client instance
expect(client1).toBe(client2)
})
it('should not cache a rejected connection promise and retry on next call', async () => {
// First attempt fails (e.g. transient DB outage at startup)
const failingClient = {
connect: jest.fn().mockRejectedValueOnce(new Error('transient failure')),
db: jest.fn(),
close: jest.fn()
}
MockedMongoClient.mockImplementation(() => failingClient)
const { getClientPromise } = await import('./mongodb')
await expect(getClientPromise()).rejects.toThrow('transient failure')
// Second call must retry instead of replaying the cached rejection
failingClient.connect.mockResolvedValueOnce(failingClient as any)
await expect(getClientPromise()).resolves.toBe(failingClient)
})
})
})
+13 -2
View File
@@ -24,13 +24,24 @@ export function getClientPromise(): Promise<MongoClient> {
// @ts-expect-error - Global variable for development hot reload
if (!global._mongoClientPromise) {
// @ts-expect-error - Global variable for development hot reload
global._mongoClientPromise = createClientPromise()
global._mongoClientPromise = createClientPromise().catch((error: Error) => {
// A rejected promise must not stay cached: a transient failure would
// otherwise break every subsequent request in this process.
// @ts-expect-error - Global variable for development hot reload
global._mongoClientPromise = undefined
throw error
})
}
// @ts-expect-error - Global variable for development hot reload
return global._mongoClientPromise
}
clientPromise ??= createClientPromise()
clientPromise ??= createClientPromise().catch((error: Error) => {
// See the development branch above: drop the cached rejection so the next
// call can retry the connection.
clientPromise = undefined
throw error
})
return clientPromise
}