AI-Generated Code Requires a Different Code Review Process

Code review for AI-generated code is different. A pull request can look syntactically perfect, pass all local tests, and still be wrong in a way that is hard to notice.

Our review habits, built over years of reading code written by other people, are not prepared for this. We are used to looking for logic errors or style issues. What changes now is that AI can generate hundreds of lines of code that look correct at first glance, but were built on the wrong assumptions.

This changes where the bottleneck in software development sits. Writing code is no longer the slowest part. Verifying what was generated is.

When a developer can generate large volumes of code, the reviewer’s job shifts from fixing mistakes to validating intent. The cost of a superficial review changes as well. It stops being a small bug and can become an architectural flaw, a security risk, or a performance issue that only appears in production.

The costs of trusting AI-generated code

The immediate productivity gains from AI are clear. What comes after is not always. We are starting to see new types of problems in code that looks correct at first glance, but was built with a fragile or incorrect understanding of the system.

Ignoring failures in AI outputs

AI-generated code often looks complete. It generates functions with docstrings, adds basic error handling, and follows the general syntax of the codebase. At first glance everything looks right, but important details may be missing.

The code is usually written for a generic problem, not for our specific operational context. It may also lack the extra checks that a more experienced engineer would normally add based on experience. For example, it might not consider the case where a downstream service returns a malformed object or times out under load, because those failures are specific to our system, not to the training data. The generated code might even include a `try/catch` block for a network failure, but it will not validate the payload of a successful but corrupted response.

Another common issue is the introduction of obscure or non-standard libraries. An AI model may solve a problem using a niche package it saw in training data, adding a new maintenance burden and a new security surface without the developer noticing. The code works, but now the team is responsible for a dependency they never chose.

Why current code review processes fail

Our code review practices were built around one assumption: there is a human author whose reasoning can be questioned. We review code by looking at logic and maintainability, trusting that the author has a mental model of the system. AI-generated code breaks that assumption.

The illusion of correctness

The biggest challenge is that AI code looks correct. Often it is cleaner and more consistent in style than code written by a junior developer. That aesthetic can put reviewers into a false sense of security. We look for bugs that are obvious, but miss the ones that are strategic.

An AI can generate a perfectly functional data transformation script. The reviewer confirms that it works with the sample data. What goes unnoticed is that the script loads the entire dataset into memory, a solution that works with a test file of 100 records but will crash the server when it runs against the production database with 10 million records. The code is not technically buggy, but it is operationally unviable.

This gets worse when the code contains many repeated sections. An AI can produce a 200-line controller that appears to follow the team’s REST patterns. Somewhere inside that code there may be a direct database query bypassing the service layer and its validation logic.

A human reviewer, seeing familiar patterns, may move quickly through the code and miss the architectural violation. There is no authorial intent to question, only an output to validate. You cannot trace the machine’s “reasoning” because it does not exist.

Ignoring security and performance regressions

AI models are trained on public code, including examples with known vulnerabilities and inefficient patterns. Because of that, they can repeat those solutions without evaluating the impact they introduce.

A 2021 Stanford study showed that developers using AI assistants were more likely to write insecure code than those who did not use them.

AI may suggest a deprecated encryption algorithm because it appeared in older training data. It may generate code vulnerable to a regular expression denial of service attack (ReDoS) by suggesting a complex regex pattern copied from a public forum. These are not simple mistakes. They are inherited vulnerabilities that linters and basic tests often fail to detect.

Performance regressions are also common and difficult to identify. AI tends to solve the immediate problem without considering the performance impact on the system as a whole. It may generate a solution that processes items in a list using nested loops, resulting in O(n²) complexity. This passes a unit test with 10 items but nearly stops the application with 10,000.

A human developer, with context about the system’s scale, would probably avoid this. AI does not have that context.

The same happens with error handling. In one function, the AI may use exceptions based on training examples. In another, it may return null or error codes, creating inconsistent behavior and a more fragile system.

Adapting code review for the AI era

To deal with these new risks, we need to shift the focus of code review from code correction to code verification. The question becomes: “Does this code do the right thing, for the right reasons, within the constraints of our system?” Every block of AI-generated code should be treated as if it came from a new developer who has no idea how your project works.

Prioritize intent over syntax

The review process needs to start before you look at the code. The first questions from the reviewer to the person who created the change should be: “What prompt did you use exactly?” and “What problem were you trying to solve?” This reframes the review around what the code is supposed to do.

First, verify whether the generated code actually solves the intended problem. It is common for AI to solve a similar but subtly different problem. The solution may be correct for the prompt but wrong for the business requirement.

Next, check whether the AI implementation fits into the system’s architecture. If the task was to add a simple validation rule, did it correctly modify an existing service, or did it generate a new class and fragment the logic?

Finally, mentally trace the data flow. In any non-trivial function, follow the data from input to output. What happens if an input is null? If a string is empty or contains unusual characters? If a network call fails? This deliberate tracing forces deeper analysis than a simple read-through.

A checklist for reviewing AI-generated code

To make this systematic, teams should adopt a verification-focused checklist for any pull request that contains a large amount of generated code. This moves the review away from subjective judgment and into a structured process.

  • Does it understand our business domain? AI has no domain context and will fill gaps with generic assumptions. For example, did it assume a user has only one email address when our system allows several?
  • Are the tests actually good? If the AI generated the tests, do they only cover the happy path? AI-generated tests are a starting point, but they rarely cover edge cases or failure modes specific to your system. The expectation for test coverage in AI-generated code should be higher, not lower.
  • Is it secure? Treat the code as untrusted input. Did it introduce new dependencies, and were they evaluated? Does it handle user input safely? Does it use approved cryptographic libraries?
  • Is it efficient? What is the algorithmic complexity of the generated functions? Does it access data inside a loop? Is it memory efficient? The reviewer is now also responsible for the performance analysis the generator ignored.
  • Can a human maintain this? Is the code easy to understand? Did the AI choose an algorithm that is more complicated than necessary? Is the code documented to explain why it works this way, not only what it does? The person who used the prompt needs to be able to explain the output. If they cannot, do not merge it.
  • Does it follow the project’s standards? AI does not know your specific architectural standards, preferred libraries, or error-handling strategies. The reviewer needs to make sure those standards are respected, checking whether the generated code integrates well with the rest of the system instead of introducing inconsistent logic.

This approach demands more from the reviewer. The reviewer’s role stops being just checking style or syntax. They need to understand whether the code actually makes sense within the system.

Otherwise, the codebase begins to accumulate subtle mistakes and problems that only appear later in production.

The speed of AI code generation is a major advantage, but it only works with strong code review processes.

Health: Module psd1

@{
RootModule = ‘SqlTechnicalSanity.psm1’
ModuleVersion = ‘3.0.0’
GUID = ‘14552ff8-6ab0-4fef-bd66-d6901c0b6a5e’
Author = ‘OpenAI’
CompanyName = ‘OpenAI’
Copyright = ‘(c) OpenAI. All rights reserved.’
Description = ‘Fail-soft, dbatools-first SQL Server technical sanity reporting with Outlook-safe HTML output.’
PowerShellVersion = ‘5.1’

FunctionsToExport = @(
    'Invoke-SqlTechnicalSanity',
    'Get-SqlTechnicalSanityCollector',
    'Get-SqlTechnicalSanityCheck',
    'ConvertTo-SqlTechnicalSanityHtml',
    'ConvertTo-SqlTechnicalSanityJson',
    'Export-SqlTechnicalSanityReport'
)

CmdletsToExport   = @()
VariablesToExport = @()
AliasesToExport   = @()

PrivateData = @{
    PSData = @{
        Tags = @('SQLServer','dbatools','HealthCheck','HTML','Outlook','FailSoft','Operations')
        ReleaseNotes = 'v3 scaffold with expanded collectors: replication, tempdb, error log, and share/path checks.'
    }
}

}

From RSA to ECC: The Impact of Quantum Computing on Modern Cryptography

The digital world as we know it rests on a mathematical foundation that has remained largely unchallenged for decades. Every secure connection you make, from online banking to encrypted messaging, relies on cryptographic algorithms that protect your data from prying eyes. But beneath this veneer of security, a storm is brewing. Quantum computers, once relegated to the realm of theoretical physics, are advancing at a pace that threatens to unravel the very fabric of our digital security infrastructure.

The Mathematics That Protect Us

To understand the quantum threat, we must first appreciate what makes our current encryption systems work. Modern cryptography relies on what mathematicians call “computational hardness assumptions” – problems that are theoretically possible to solve but practically impossible given current computing capabilities.

The RSA algorithm, named after its creators Rivest, Shamir, and Adleman, has been the workhorse of public-key cryptography since 1977. Its security rests on a deceptively simple premise: factoring large numbers is extraordinarily difficult. While multiplying two prime numbers together is trivial, reversing that operation to find the original primes becomes exponentially harder as the numbers grow larger. A 2048-bit RSA key would require classical computers thousands of years to factor using the most efficient algorithms known today.

Similarly, Elliptic Curve Cryptography (ECC) derives its security from the elliptic curve discrete logarithm problem. ECC offers equivalent security with smaller key sizes compared to RSA, making it particularly valuable for resource-constrained environments like mobile devices and Internet of Things (IoT) systems.

Symmetric encryption algorithms like the Advanced Encryption Standard (AES) face a different challenge. Rather than mathematical factorization, their security relies on the sheer size of their key space. AES-256, the gold standard for symmetric encryption, offers 2^256 possible keys – a number so vast that brute-force attacks are computationally infeasible.

Enter the Quantum Realm

In 1994, mathematician Peter Shor published a paper that would eventually send shockwaves through the cryptographic community. Shor’s algorithm, designed to run on a quantum computer, could factor large integers exponentially faster than any classical algorithm. What would take traditional supercomputers millennia could potentially be accomplished by a sufficiently powerful quantum machine in a matter of hours or days.

The implications were profound. Shor’s algorithm doesn’t merely offer a speedup – it fundamentally changes the computational complexity of factoring from exponential to polynomial time. This means that RSA and ECC, the cornerstones of modern public-key infrastructure, would become completely vulnerable once quantum computers reach sufficient scale.

But Shor’s algorithm is not the only quantum threat. In 1996, Lov Grover developed another quantum algorithm that poses risks to symmetric encryption. Grover’s algorithm provides a quadratic speedup for searching unsorted databases, which translates to effectively halving the key length of symmetric ciphers. AES-256 would offer only 128-bit equivalent security under quantum attack – still formidable, but no longer the impenetrable barrier it once seemed.

The Harvest Now, Decrypt Later Strategy

Here is where the timeline becomes deeply concerning. We do not need to wait for quantum computers to become widely available before the damage begins. Sophisticated adversaries are already executing what cybersecurity professionals call “Harvest Now, Decrypt Later” (HNDL) attacks.

The strategy is elegantly simple and terrifyingly effective. Threat actors intercept and store encrypted data today, knowing they cannot yet decrypt it. They simply wait, maintaining vast archives of captured communications, financial records, classified documents, and personal information. When quantum computers eventually mature, they will unlock these treasure troves of data, revealing secrets that their owners believed were permanently protected.

Major cybersecurity agencies worldwide have identified HNDL as a critical and immediate threat. The U.S. Department of Homeland Security, the UK’s National Cyber Security Centre , the European Union Agency for Cybersecurity, and the Australian Cyber Security Centre have all issued guidance based on the premise that adversaries are actively harvesting encrypted data with future decryption in mind. For data with long-term value – government secrets, intellectual property, medical records, financial information – the vulnerability exists not in some distant future when quantum computers arrive, but right now, in this moment, as adversaries systematically archive encrypted transmissions.

The Timeline: How Much Time Remains?

Predicting the arrival of “Q-Day” – the moment when quantum computers can break practical encryption – is fraught with uncertainty. The challenge involves not merely building quantum computers, but building quantum computers with enough error corrected qubits to run Shor’s algorithm at meaningful scales.

Current quantum processors from companies like IBM, Google, and IonQ operate with a few hundred physical qubits. Breaking RSA-2048 would likely require millions or even billions of error-corrected qubits – a staggering engineering challenge that involves not just scaling up qubit counts, but dramatically improving error rates and coherence times.

Yet the timeline is shortening. Gartner has projected that RSA and ECC could become unsafe by 2029 and potentially broken by 2034. Other estimates suggest 2048-bit RSA could be vulnerable by the early 2030s. Conservative researchers suggest 15 to 20 years may still be needed, but breakthroughs in quantum error correction could dramatically accelerate these timelines.

The consensus among experts is clear: cryptographically relevant quantum computers will likely emerge within the next two decades, and possibly much sooner. Organizations that wait for definitive proof before acting may find themselves catastrophically exposed.

Post-Quantum Cryptography: The Race for Solutions

Recognizing the existential threat posed by quantum computing, the National Institute of Standards and Technology (NIST) launched an ambitious program in 2016 to standardize post-quantum cryptographic algorithms. After eight years of rigorous evaluation involving the global cryptographic community, NIST released its first set of standards in August 2024.

The standardized algorithms – CRYSTALS-Kyber (Key Encapsulation Mechanism (KEM) ) for key encapsulation, CRYSTALS Dilithium(Renamed as Module-Lattice-Based Digital Signature Algorithm (ML-DSA)) for digital signatures, and SPHINCS+ as a hash-based signature alternative – represent a new generation of cryptographic primitives designed to resist both classical and quantum attacks. These algorithms rely on mathematical problems that appear resistant to quantum speedups, including lattice-based cryptography, code-based cryptography, and hash-based signatures

Lattice-based cryptography, in particular, has emerged as a leading candidate for postquantum security. These schemes derive their hardness from problems like Learning With Errors (LWE) and its variants, which remain difficult even for quantum computers. The mathematical structures involved offer not only resistance to quantum attacks but also practical efficiency for real-world deployment.

However, the standardization process has not been without setbacks. During evaluation, two previous candidate algorithms were compromised – one broken in under an hour. These failures underscore the importance of rigorous testing and the challenges of developing cryptographic systems that must remain secure for decades against adversaries who may eventually possess quantum capabilities.

Quantum Key Distribution: A Complementary Approach

While post-quantum cryptography offers software-based solutions, Quantum Key Distribution (QKD) provides a fundamentally different approach to secure communication. QKD leverages the principles of quantum mechanics itself to establish secure keys between parties.

The security of QKD rests on physical principles rather than computational assumptions. Any attempt to eavesdrop on a quantum communication channel necessarily disturbs the quantum states being transmitted, revealing the presence of an attacker. This offers information-theoretic security – protection that does not depend on the computational limitations of adversaries.

However, QKD faces significant practical limitations. Current implementations require specialized hardware and are limited by distance constraints and transmission losses. While QKD offers compelling security properties for specific high-value applications, it is unlikely to replace cryptographic solutions for general-purpose communication in the near term.

What Organizations Must Do Now ?

The window for orderly transition is narrowing. Organizations that delay action risk finding themselves in a crisis situation, forced to implement rushed migrations under the threat of imminent quantum capabilities.

Conduct a Cryptographic Inventory

The first step is understanding your current exposure. Organizations must catalog all cryptographic implementations across their infrastructure, identifying where RSA, ECC, and other vulnerable algorithms are used. This inventory should encompass not only internally developed systems but also third-party software, cloud services, and vendor products.

Develop a Migration Roadmap

With inventory in hand, organizations should develop prioritized migration plans. High value assets and long-lived data deserve immediate attention. Systems that handle sensitive information with extended confidentiality requirements – government classified data, healthcare records, financial systems – should be prioritized for early migration.

Embrace Crypto Agility

Organizations should design their systems for cryptographic agility – the ability to swap algorithms without fundamental architectural changes. This principle, sometimes called “cryptographic agility,” ensures that future algorithm updates can be deployed quickly and efficiently. Avoid hard-coding specific algorithms or key sizes; instead, build abstraction layers that allow for seamless transitions.

Test Post-Quantum Solutions

Begin pilot implementations of NIST-standardized post-quantum algorithms in noncritical systems. This hands-on experience will reveal integration challenges, performance impacts, and interoperability issues before they become critical concerns. Many vendors are already releasing post-quantum capable products; early adopters can provide valuable feedback and shape the development of quantum-resistant solutions.

Address the HNDL Threat

For the most sensitive data, consider the Harvest Now, Decrypt Later threat model. Data with long confidentiality requirements should be protected with quantum-resistant algorithms immediately, even if broader infrastructure migration takes longer. Some organizations are implementing hybrid encryption schemes that combine classical and post-quantum algorithms, providing defense in depth against both current and future threats.

The Countdown Continues

We stand at an inflection point in the history of digital security. The mathematical foundations that have protected our communications for decades are facing an existential threat from an entirely new paradigm of computing. The quantum countdown is not a distant concern – it is a present reality that demands immediate action.

The good news is that solutions exist. The cryptographic community has risen to the challenge, developing post-quantum algorithms that can protect our digital infrastructure well into the quantum era. NIST’s standardization efforts have provided a roadmap for the transition ahead.

What remains is the hard work of implementation. Organizations must move beyond awareness to action, beginning the systematic process of inventorying their cryptographic dependencies, planning their migrations, and building the crypto-agile systems that will carry them through the quantum transition.

The adversaries are already harvesting. Every day of delay increases the risk that today’s encrypted communications will become tomorrow’s exposed secrets. The quantum countdown waits for no one. The time to act is now.

Agentic Software Development

Reflections After 3 Years of Use

I’ve been intensively using generative AI since ChatGPT was released in November 2022. Software development quickly became one of the areas where I use it most. Repeated cycles of enthusiasm and disappointment have led me to a more mature understanding of its strengths and limitations. Here are some reflections.

The New Baseline for Development

I’m convinced that in the current state of the art, specialized code generation agents are a fundamental tool for software developers. Those who don’t adopt them are creating a massive handicap compared to those of us who use them systematically.

Beware of Trivialization

I’m concerned about the trivialization happening when people without software engineering knowledge see how “with a simple prompt” they can build functional applications “without coding.” While this is possible, there are several caveats to keep in mind.

Many platforms that let you generate applications with a prompt lock you into their environment (vendor lock-in) and produce applications with security, scalability, and maintainability issues unsuitable for production. On top of that, people without software experience lack the ability to write complete specifications, so the AI fills in the gaps with assumptions that aren’t made explicit and often don’t align with expectations. These applications can be useful as prototypes or for private use, but risky for broader deployment.

The Senior Developer’s Superpower

On the flip side, software development agents can be a superpower in the hands of a senior developer. AI cannot produce production-grade software without proper guidance, but it can dramatically accelerate productivity.

This isn’t about “vibe” coding, but about spec-driven development. That means producing detailed technical documentation that guides development agents to generate the required code.

What does it include? Functional specifications with measurable acceptance criteria, architectural patterns, code quality standards, testing, security, observability, among others.

The developer’s role doesn’t disappear; it evolves from writing code to designing the structural elements that enable quality software. As Faisal Haque puts it, this is the evolution from coder to builder.

I’ve been dedicating myself to exploring and experimenting with how to produce high-quality software using agents, and I’m preparing a series of posts to share the learnings I’ve gathered along the way.

In the next posts, I’ll dig into the specifics: how models actually behave, what spec-driven development looks like in practice, and the techniques that make the difference. What’s been your experience so far?

Porting Test Drive II from SNES to PC, Part 24: Tightening the SNES selector domains and the B1F9 handoff window

Porting Test Drive II from SNES to PC, Part 24: Tightening the SNES selector domains and the B1F9 handoff window

The previous checkpoint created the first DOS-driven SNES front-end contract set.

That was useful, but still soft in two places:

  • the selector domains were only loosely named
  • the bank-1 handoff candidate near L009568/L0095AD was structurally plausible, but still blurry around the real gameplay callback chain

This checkpoint tightened both without pretending they are solved.

The four-state selector is now more concrete

The strongest static gain came from decoding the small table at 01:8000/01:8008.

That table is the source for $1C7E/$1C80, which means it drives the row base and row count used by the shared front-end descriptor builder.

It now decodes cleanly as:

  • bases: [0, 5, 11, 18]
  • counts: [5, 6, 7, 8]

So $1C7C is not just “some four-state knob.”

It is a verified four-group descriptor selector.

That still does not prove the human label is “track” or “scenery,” but it does eliminate a weaker reading where $1C7C was just another UI-only toggle with no real content boundary behind it.

It selects whole descriptor groups.

The three-choice preview domain also got sharper

The $0202 -> $1C78 preview path now has more than one kind of evidence behind it.

The code already showed:

  • a three-choice animated preview loop in L00BBCB
  • commit of the final choice into $1C78

Now the helper tables make that path look like a real content domain instead of a single visual trick.

The three preview bundle indices resolve to distinct helper triples:

  • index 9 -> L00A9A0 00:B0AB, L00A9CB 0E:8000, L00A9F2 02:FC11
  • index 10 -> 00:B6B2, 0E:91FE, 02:FBF3
  • index 11 -> 00:BCBA, 0E:A428, 0D:C98F

And an adjacent unlabeled front-end UI helper consumes:

  • $0202 + 0x0008

through the same 1E80 text/UI buffer used elsewhere in the menu flow.

That still does not give a final name-bearing proof that this is the car selector.

But combined with the verified CUSTOMIZE CAR surface, it makes $0202/$1C78 a much stronger car-facing candidate than it was before.

One good failure also landed

I tried to push the current helper-scene builder through those preview bundle indices.

That did not work cleanly.

The L00A9CB bulk path for helper indices 9..11 currently fails with a 26FB length mismatch:

  • decoded bytes: 11348
  • expected bytes: 16640

That is not a wasted attempt.

It says the three-choice preview is not just another instance of the already-solved simple helper scene path.

So the correct next move is a dedicated preview extractor, not more blind reuse of the simpler builder.

The handoff window got narrower, not fully solved

The other useful result came from forced probes on the two bank-1 sibling callbacks:

  • 01:9568
  • 01:95AD

Both forced lanes still do exactly one real thing we care about:

  • they reach 01:B1F9 once
  • that happens at frame 1201

And the stack return words still separate the two siblings cleanly:

  • 01:9568 returns through 0x9575
  • 01:95AD returns through 0x95B7

The state split also survives:

  • 01:9568 enters with state_0f77 = 1
  • 01:95AD enters with state_0f77 = 0

But the same narrow trace window still does not show:

  • writes to $096C-$0971
  • an exec hit at 02:9016

That matters because the broader static corridor does already stage:

  • main callback 02:9016
  • NMI callback 02:8F3C

So the missing proof is no longer “does this branch really enter the handoff code?”

It does.

The missing proof is now specifically:

when does callback promotion happen relative to that bank-1 branch boundary?

That is a better unknown than the old one.

What changed in practice

This checkpoint did not solve the front end.

It did make the next probes much less vague:

  • $1C7C is now a verified four-group descriptor selector, not just a guess
  • $0202/$1C78 is now backed by explicit preview bundle triples
  • the preview extractor needs its own path
  • L009568/L0095AD -> L00B1F9 is real, but the immediate 02:9016 promotion is still outside the narrow forced trace window

That is enough to move the next turn away from generic menu speculation and toward two concrete jobs:

  • extend the preview extractor for helper indices 9..11
  • widen the forced trace around callback promotion instead of repeating the same short B1F9 window

DSGVO auf deiner KMU-Webseite: Was wirklich Pflicht ist – und was nicht

DSGVO Checkliste für KMU-Webseiten

Abmahnungen wegen DSGVO-Verstößen sind in Deutschland kein seltenes Schicksal mehr – sie treffen auch kleine Unternehmen, die einfach nur eine ordentliche Webseite betreiben wollen. Das Gemeine daran: Die meisten Fehler entstehen nicht aus Gleichgültigkeit, sondern weil niemand einem erklärt hat, wo die echten Stolpersteine liegen.

DSGVO Checkliste für KMU-Webseiten

Das Missverständnis mit der DSGVO

Viele Entwickler – und erst recht ihre Kunden – denken, DSGVO bedeutet: irgendein Cookie-Banner draufklatschen und fertig. Die Realität ist etwas nuancierter, aber auch nicht so kompliziert, wie sie oft dargestellt wird.

Der Kern ist eigentlich simpel: Wer personenbezogene Daten verarbeitet, braucht dafür eine Rechtsgrundlage und muss transparent darüber informieren. Und personenbezogene Daten entstehen schneller als man denkt – IP-Adressen, Cookie-IDs, Formulareinträge. Selbst ein schlichter Server-Log zählt dazu.

Die drei relevantesten Rechtsgrundlagen im Web-Kontext: Einwilligung (für Tracking und Marketing), Vertragserfüllung (für Kontaktanfragen) und berechtigtes Interesse (für technisch notwendige Dinge wie Sicherheitslogs). Wer das einmal verstanden hat, kann die meisten Entscheidungen selbst treffen.

Impressum: Unterschätzter Klassiker

Das Impressum ist die häufigste Abmahnfalle – und das, obwohl die Anforderungen eigentlich klar definiert sind. Vollständiger Name mit korrekter Rechtsform, ladungsfähige Anschrift (kein Postfach!), funktionierende E-Mail-Adresse und Telefonnummer, Handelsregisternummer falls vorhanden.

Zwei Fehler sieht man besonders oft: Die Rechtsform stimmt nicht exakt (“GmbH” statt “GmbH & Co. KG”), oder die Daten sind schlicht veraltet. Außerdem gilt die 2-Klick-Regel – das Impressum muss von jeder Unterseite aus mit maximal zwei Klicks erreichbar sein. Ein Footer-Link reicht dafür völlig.

Wichtig für Entwickler, die Webseiten für Kunden bauen: Impressum und Datenschutzerklärung sind zwei separate Dokumente mit unterschiedlichen Zwecken. Eine Vermischung ist nicht zulässig. Wer das von Anfang an sauber trennt – so wie es blackforest-webcraft.de als Standard für alle Kundenprojekte beschreibt – spart sich später Ärger.

Datenschutzerklärung: Kein “Set and Forget”

Digitales Notizbuch mit Checkliste und Kalender für DSGVO-Updates

Die Datenschutzerklärung ist das Dokument, das am häufigsten veraltet – und das am häufigsten unterschätzt wird. Jedes eingebundene Tool muss dort auftauchen: Name, Anbieter, Zweck, Rechtsgrundlage, Speicherdauer, eventuelle Drittlandübermittlung.

Bei Google Analytics 4 bedeutet das konkret: IP-Anonymisierung erwähnen (in GA4 standardmäßig aktiv), Auftragsverarbeitungsvertrag mit Google abschließen (in den GA4-Einstellungen, einmal klicken), Datenaufbewahrung auf zwei Monate reduzieren, Google-Signale deaktivieren.

Ein halbjährlicher Review-Termin im Kalender ist kein Overkill, sondern Minimum. Neues Plugin eingebunden? Datenschutzerklärung aktualisieren. Hoster gewechselt? Datenschutzerklärung aktualisieren. Das klingt mühsam, ist aber mit einem internen Änderungslog gut handhabbar.

Cookie-Banner: Wo die meisten Fehler passieren

Technisch notwendige Cookies brauchen keine Einwilligung. Alles andere – Tracking, Marketing, Social Media – schon, und zwar bevor die Cookies gesetzt werden.

Ein rechtssicherer Banner hat einen gleichwertigen “Ablehnen”-Button. Nicht versteckt in den Einstellungen, nicht als kleiner grauer Link unter dem großen grünen “Akzeptieren”-Knopf. Gleichwertig. Außerdem dürfen Tracking-Skripte nicht laden, bevor der Nutzer eine Wahl getroffen hat – das lässt sich im Inkognito-Modus mit den Browser-DevTools schnell überprüfen.

Seit März 2024 ist der Google Consent Mode V2 Pflicht, wenn Google Ads im Spiel ist. Ohne korrekte CMP-Integration verliert man Conversion-Daten von ablehnenden Nutzern komplett.

Kontaktformulare und Hosting: Die technischen Basics

Kontaktformular mit Sicherheitssymbolen und deutschem Server-Rack

Datensparsamkeit beim Kontaktformular: Name und E-Mail reichen in den meisten Fällen. SSL ist Pflicht – ohne HTTPS ist jedes Formular ein Verstoß. Beim Spam-Schutz lieber auf Honeypot-Felder setzen als auf Google reCAPTCHA, das seinerseits Einwilligung benötigt.

Beim Hosting gilt: Deutschland oder EU ist unkompliziert. Außerhalb der EU wird es aufwendiger – Standardvertragsklauseln, Drittlandtransfer in der Datenschutzerklärung erwähnen, Datenschutz-Folgenabschätzung. Und der E-Mail-Provider ist ebenfalls Auftragsverarbeiter – auch das wird oft vergessen.

Was bleibt?

DSGVO-Konformität ist kein einmaliges Projekt, sondern ein laufender Prozess. Aber der Aufwand hält sich in Grenzen, wenn man die Grundlagen einmal sauber aufgesetzt hat: vollständiges Impressum, gepflegte Datenschutzerklärung, ehrlicher Cookie-Banner, verschlüsselte Formulare, sauberes Hosting.

Na ja, und regelmäßig draufschauen. Das ist eigentlich alles.

Wie handhabt ihr das in euren Projekten – erklärt ihr euren Kunden die DSGVO-Anforderungen aktiv, oder setzt ihr einfach um und hofft, dass niemand fragt?

Remote Work Didn’t Fix Toxic Culture—It Just Made It Async

TL;DR: Your team’s dysfunction didn’t disappear when everyone went remote. It just moved into Slack, and now it’s worse because you can’t read the room.

I spent 3 years watching this play out. Pre-pandemic, your manager’s bad mood was obvious—you’d catch it in a hallway conversation. Now? That same manager writes passive-aggressive comments in PRs at 11 PM and you’re supposed to interpret tone through a screen.

The real problem: We mistook silence for health.

Remote work did expose one thing clearly—bad code, bad decisions, bad people all leave a digital paper trail. But instead of fixing the culture, teams just learned to code-switch better. The senior engineer who bullied juniors in meetings? Now they bully them in GitHub comments. The meeting-obsessed manager? Just scheduled 8 async updates instead.

The Pattern

Think of it like this:

Old culture toxicity:
visibility = high
confrontation = forced
resolution = sometimes happens

Remote culture toxicity:
visibility = hidden in timestamps
confrontation = deniable
resolution = “that’s just how they communicate”

The dysfunction didn’t change. The accountability did.

What I Learned

Culture is a system, not a setting. Flipping “remote” doesn’t rewrite how people treat each other—it just changes the medium. I’ve seen amazing remote teams and soul-crushing ones. The difference? Teams that actually addressed why people were unhappy, not just where they worked.

The teams that thrived remotely did something radical: they explicitly named their values, called out bad behavior in public channels, and held leadership accountable the same way they held junior devs accountable in code review.

It took work. It wasn’t comfortable. But it worked.

What I’m Curious About

Have you seen this in your org? Did remote work unmask problems or just rearrange them? And more importantly—did your team actually address the culture, or just accept a quieter version of the same dysfunction?

Drop a comment. I’m betting you’ve got a story.

Google Search Console Has a Full API. Why Is Nobody Using It from Their IDE?

Google Search Console Has a Full API. Why Is Nobody Using It from Their IDE?

I published a blog post, waited three days for Google to index it, then realized I could have just… asked it to. Literally. There’s an API endpoint that lets you ping Google and say “hey, this URL exists now, please come look at it.” I’d been sitting there refreshing the Google Search Console dashboard like it was a deployment pipeline, waiting for a green checkmark that I could have triggered myself.

That was the moment I realized my entire SEO workflow was broken. Not technically broken — just comically manual for something that has a perfectly good API behind it.

The SEO Waiting Game

Here’s what the publish-and-pray cycle actually looks like. You write a post. You deploy it. You go to Google Search Console, paste the URL into the inspection tool, and click “Request Indexing.” Then you wait. Maybe a few hours, maybe a few days. You check back. It’s still not indexed. You resubmit. You wait some more.

Now multiply that by every page on your site. Got a new blog with 30 posts? That’s 30 manual submissions. Changed your URL structure during a migration? Enjoy manually requesting re-indexing for every single page while praying the old ones get removed from the index before someone clicks a dead link.

And that’s just the indexing side. The analytics side is worse. Google Search Console’s dashboard loads like it’s running on a 2014 server. You click “Performance,” wait five seconds for the chart to render, filter by page, wait again, filter by query, wait again. Want to compare two date ranges? That’s another round of waiting. Want to export the data? CSV download, open in a spreadsheet, pivot table. For data that Google already has in a structured API response.

The tools exist. The API has been there for years. Nobody wraps it in a way that developers actually want to use.

gsc-mcp

gsc-mcp is an MCP server that puts the entire Google Search Console API surface into your AI agent’s hands. 13 tools across 5 categories: site management, sitemaps, search analytics, URL inspection, and the Indexing API. It covers everything the dashboard does, minus the loading spinners.

Setup takes about two minutes. You need a Google Cloud project with the Search Console API enabled and OAuth credentials. Drop this into your MCP config:

{
  "mcpServers": {
    "gsc": {
      "command": "npx",
      "args": ["-y", "@mikusnuz/gsc-mcp"],
      "env": {
        "GSC_CLIENT_ID": "your-client-id",
        "GSC_CLIENT_SECRET": "your-client-secret",
        "GSC_REFRESH_TOKEN": "your-refresh-token"
      }
    }
  }
}

Standard OAuth2 flow. You create credentials in the Google Cloud Console, run through the consent screen once, grab your refresh token, and you’re done. Nothing exotic.

What You Can Actually Do With This

The first thing I did was ask a question that would have taken me four clicks and two loading screens in the dashboard:

Me: What are my top 10 queries by clicks for the last 7 days?

Agent: Here are your top queries for the past week:
  1. "mcp server tutorial" - 342 clicks, 12,400 impressions, 2.8% CTR, pos 4.2
  2. "model context protocol" - 289 clicks, 8,900 impressions, 3.2% CTR, pos 3.8
  3. "npm publish automation" - 156 clicks, 5,200 impressions, 3.0% CTR, pos 6.1
  ...

Instant. No dashboard. No waiting for charts to render. And because it’s a conversation, I can immediately follow up: “Which of those dropped in position compared to last month?” or “Show me which pages rank for ‘mcp server tutorial’.” Try doing that kind of drill-down in the GSC dashboard without losing your mind.

URL inspection is another one that used to eat my time. Instead of pasting URLs one at a time into the inspection bar:

Me: Is /blog/deploy-mcp-server indexed? Is it mobile-friendly?

Agent: URL inspection for /blog/deploy-mcp-server:
  - Indexing: Indexed, last crawled March 21
  - Mobile usability: No issues detected
  - Rich results: FAQ schema detected and valid
  - Crawl: Successful, 200 response, 1.2s load time

Indexing status, crawl info, rich results validation, mobile usability — all in one response. In the dashboard, that’s four different sections you’d have to click through.

The Batch Indexing Play

Here’s where it gets genuinely useful for anyone running a blog, a docs site, or any content-heavy project. The Indexing API supports batch operations — up to 100 URLs in a single request.

Think about what that means for your deploy workflow. You push a new version of your docs site with 15 updated pages. Instead of manually submitting each one, you just tell your agent:

Me: I just deployed updated docs. Submit these URLs for indexing:
    /docs/getting-started, /docs/api-reference, /docs/authentication,
    /docs/webhooks, /docs/migration-guide, /docs/changelog

Agent: Batch indexing request submitted for 6 URLs.
  All 6 URLs notified successfully.
  Google will prioritize crawling these URLs.

You could even hook this into your CI/CD pipeline. Deploy triggers a build, build generates a sitemap diff, agent submits the changed URLs to the Indexing API. Your pages show up in search results hours after deploy instead of days. For a blog that publishes daily, that’s the difference between traffic hitting on day one versus day four.

Sitemap management works the same way. Submit a new sitemap, check the status of existing ones, see which URLs Google has picked up from your sitemap versus which ones it’s ignoring. All conversational. All instant.

The Honest Limitations

I should be clear: the Indexing API doesn’t guarantee instant indexing. It tells Google “this URL changed, please re-crawl it soon.” Google still decides when and whether to actually index it. But in my experience, it cuts the wait from days to hours for most pages. That’s a meaningful difference.

The Search Analytics data also has the same lag as the dashboard — usually 2-3 days behind real-time. That’s a Google limitation, not a tool limitation. You’re not getting fresher data through the API than you would through the web UI.

And if your site has thousands of pages, the 100-URL batch limit on the Indexing API means you’ll need multiple requests for large-scale reindexing jobs. Not a dealbreaker, but worth knowing.

SEO Shouldn’t Require Staring at Dashboards

I’ve been saying this about every developer tool category for the past year, but it especially applies to SEO: if there’s an API, there’s no reason you should be clicking through a web interface to do routine work. Google Search Console has had a comprehensive API for years. The dashboard just happened to be the default way people interacted with it, because nobody built a better interface.

MCP changes that equation. Your AI agent becomes the interface. You describe what you want in plain language, and it figures out which API calls to make. No memorizing query parameters for the Search Analytics API. No manually constructing URL inspection requests. No batch-submitting sitemaps through a web form.

I check my search performance every morning now. Not because I became more disciplined about SEO — I just ask while I’m already in my terminal. “How did yesterday’s post perform?” takes three seconds. That question used to take two minutes of clicking and loading. The small friction was enough to make me skip it most days. Now I never skip it.

The best SEO workflow is the one you actually do consistently. And you’re a lot more consistent when the tool lives where you already work.

Alan West is a full-stack developer based in San Francisco who ships too many side projects and complains about developer tools on the internet. Find him on GitHub or don’t — he’ll be in his terminal either way.

Your Dashboard Is Not Reality — It’s a Conversation with an Economy That Never Stops Moving

Your Dashboard Is Not Reality — It’s a Conversation with an Economy That Never Stops Moving

I used to think that a well built dashboard was a mirror. Clean data, precise calculations, a thoughtful layout and the business would see the truth.

That was before I started working through supply chain disruptions, before inflation started rewriting assumptions weekly, before I realized that a dashboard published on Monday can be economically obsolete by Wednesday.

Business analytics, when it’s honest, doesn’t reflect a static reality. It tracks a live organism: the economy. And if you’re building reports without accounting for that, you’re not giving stakeholders clarity — you’re giving them a false sense of stillness.

What We Actually Need to Know

In solutions development, we spend a lot of time on data modeling, performance and governance. Those matter. But there’s another layer that rarely shows up in job descriptions: economic awareness.

When I build a dashboard today, I need to understand not just the company’s internal logic, but the external context that makes that logic hold or break.

  • What’s happening with interest rates and how does that affect our discounting strategy?

  • Which input costs are volatile right now and are we reflecting that in our margin calculations?

  • If a key supplier is affected by a geopolitical event, does our “inventory turnover” measure still mean what it meant last quarter?

Without that awareness, a dashboard can become dangerously precise about the wrong thing.

How Building Dashboards Affects the Mind

There’s a cognitive shift that happens when you spend years in BI. At first, you chase accuracy: the numbers must match the source. Then you chase clarity: the story must be obvious.

But after a while, something else creeps in. You start to feel the tension between what the data shows and what the business needs to do right now.

When you’re building a report in real‑time economic conditions — say, during a period of sudden currency devaluation or a raw material shortage — you realize that every KPI carries a hidden timestamp. A “current” sales figure is actually last month’s reality. A forecast model built on 2 years of historical data might be useless if the last 6 months have been structurally different.

That tension changes how you design. You stop building static dashboards. You start building alert systems, scenario toggles and contextual notes embedded directly into the report. Because the goal isn’t just to inform — it’s to prevent someone from making a decision based on a world that no longer exists.

Your Dashboard Is Not Reality — It’s a Conversation with an Economy That Never Stops Moving

A Real Time Example: The Cost of “Normal”

Let me give you a concrete case.

A few months ago, I was working on a procurement dashboard for a manufacturing company. The original request was straightforward: show purchase order volumes, lead times and supplier performance. We built a clean Power BI report with trend lines, all using historical data.

Then a major shipping route was disrupted. Lead times that had averaged 30 days for 3 years suddenly jumped to 60 days. Our dashboard, which was refreshing weekly, was still showing “stable” trend lines because the data hadn’t fully caught up.

The procurement director called me: “Why does this report still look fine?”

That was the moment we rebuilt the logic. We stopped using static historical averages as benchmarks. Instead, we integrated external freight index data, built a flag that triggered whenever lead time deviation exceeded a threshold and added a simple toggle: “View vs. pre disruption baseline” or “View vs. last 4 weeks.”

We also started publishing a short “economic context” text box alongside the report — a line or 2 explaining what was happening in the market and how it might affect the numbers.

That small change transformed the dashboard from a historical log into a tool for real time decision making. It also changed how I think about every report I build now. I no longer ask, “Is this number accurate?” I ask, “Is this number relevant to the decision being made today?”

What This Means for How We Work

If you’re in business analytics — especially in solutions development — you’re not just a technical role. You’re the bridge between data and economic reality.

That means:

  • We need to stay curious about the world outside the database. Inflation, supply chains, labor markets — they’re not abstract news; they’re variables in our models.

  • We need to design for instability. Hard coded thresholds and static benchmarks will fail. Build flexibility into your semantic layer and give users ways to compare across different time contexts.

  • We need to acknowledge uncertainty in our deliverables. A clean number without a confidence interval or a footnote about external conditions is a silent risk.

The Shift in My Own Mind

Looking back, the biggest change in my own approach wasn’t learning a new tool. It was accepting that a dashboard is never finished. Because the economy doesn’t finish changing.

Every time I publish a report now, I know that the context will shift. My job isn’t to deliver a final answer. It’s to give the business a framework that can evolve with reality.

And honestly, that’s what makes this work meaningful. We’re not just moving numbers around. We’re helping people make decisions in a world that refuses to stand still.

Thank you for your time. If you found value here, feel free to share it with a fellow analyst.

The Most Dangerous Response Code Isn’t 500. It’s 200.

A 500 error is loud. Your monitoring fires. Your on-call gets paged. Someone fixes it within the hour.

A 200 that serves broken content is silent. Your monitoring dashboard stays green. Your users see a blank page, a broken checkout, a form that submits to nothing. And nobody on your team knows until a customer complains — or churns.

Modern web stacks fail in ways a simple status code cannot describe. Here are six common patterns where 200 OK actively hides broken websites.

1. The Phantom Deploy: Missing Bundle Hashes

Modern frontend frameworks produce hashed filenames: main.a4f2c.js, styles.b7e91.css. On every deploy, these hashes change. The HTML document references the new filenames. The old files get cleaned up.

Here’s the failure mode:

You deploy at 2pm. The build produces vendor.c8d13.js and app.7fb2e.css. Your CDN edge nodes in Frankfurt still serve the HTML from the previous build — which references vendor.9a1b0.js and app.3de4f.css. Those files are gone. The document loads fine. Every asset 404s. Users in Europe see a blank screen for 45 minutes until the CDN cache expires.

This is especially common on:

  • Netlify with atomic deploys but CDN propagation delays
  • Vercel with ISR pages serving stale HTML
  • Any CDN where HTML cache TTLs are longer than deploy frequency

The fix is cache invalidation discipline — but the point is that your uptime monitor never sees the problem. It fetches the document, gets 200, and moves on. It never checks whether main.a4f2c.js actually exists.

2. The Silent MIME Rejection

Browsers enforce strict MIME type checking for scripts and stylesheets. If your server responds with Content-Type: text/html for a JavaScript file, the browser silently blocks execution. No visible error. Your SPA just doesn’t boot.

How does a JS file end up served as HTML?

  • A CDN or reverse proxy intercepts the request and returns an error page (HTML) instead of the actual file
  • A misconfigured Nginx try_files directive falls through to index.html for any path — including .js files
  • Cloudflare’s custom error pages replace a 404 with a branded HTML error page, served as text/html

The server logs show 200. The CDN metrics show successful delivery. The browser silently ignores the script. Your monitoring sees 200 and reports everything healthy. The only way to catch this is to verify the Content-Type header against the expected MIME type for each critical asset.

3. The Redirect Ouroboros

A redirect loop is usually obvious — the browser shows ERR_TOO_MANY_REDIRECTS. But most monitoring tools follow a limited number of redirects and report the final status, some don’t follow redirects at all, and the loop might only trigger for specific user agents, cookie states, or geographic regions.

Common causes:

  • A Shopify app redirects /products to /collections, while a theme redirect sends /collections back to /products
  • Mixed HTTP/HTTPS configurations where each protocol redirects to the other
  • CDN-level redirect rules conflicting with origin-level rules

Your monitoring sees the first 301 and considers that a valid response. Meanwhile, real browsers with real cookies hit an infinite loop.

4. The Ghost Server

After a DNS migration, CDN swap, or infrastructure change, your domain might resolve to the wrong server. The wrong server still responds — it’s just not your server anymore.

Scenarios:

  • You migrate from AWS to Vercel but a DNS record still points a subdomain to the old EC2 instance. The instance serves stale content from 6 months ago. 200 OK.
  • A CDN failover activates and sends traffic to a backup origin that was never updated. It serves the version from the last time someone deployed to it. 200 OK.
  • A load balancer health check passes because the server responds, but it’s responding with a default page, not your application.

The response is valid HTTP. The status is 200. The content is just… wrong. It’s from a different version, a different environment, or a different application entirely.

Catching this requires tracking the resolved IP and server identity over time — and comparing the content fingerprint against a known baseline. Not just “did it respond” but “did it respond with the right content from the right server.”

5. The API Gateway Mask

API gateways, reverse proxies, and edge functions sit in front of your application. When the app behind them crashes, the gateway often catches the error and returns its own response — with a 200 status code.

Your landing page URL returns {"error":"unauthorized","statusCode":401} as a 200 OK with Content-Type: application/json. Or your edge function crashes and the platform serves a generic fallback page. Valid HTML. 200 OK. Not your application.

Common with AWS API Gateway fronting Lambda, Cloudflare Workers with fallback behavior, and Vercel edge middleware that wraps errors. If your monitoring doesn’t verify that the response content type matches what you’d expect for that URL, these failures pass undetected.

6. The Third-Party Collapse

Your site loads. Your HTML is correct. Your own assets are fine. But a critical external dependency is down — and your page breaks without your server knowing.

This matters most when the dependency is load-bearing: Stripe’s JS SDK failing means your checkout form renders as an empty div. An auth provider’s script timing out means users can’t log in. A CDN-hosted app bundle 404ing means your SPA doesn’t boot. A bot-protection script blocking form submission means your lead capture is dead.

Your server returns 200. Your monitoring checks your domain. The broken resource is on someone else’s domain. That gap is where this failure hides.

The Common Thread

All six patterns share one characteristic: the HTTP status code says everything is fine while the user experience is broken.

Status codes tell you whether a request succeeded at the protocol level, not whether the page is actually usable. A 200 means “the server processed your request and returned a response.” It doesn’t mean the response contains what the user needs.

A lot of monitoring still relies on a false assumption: that a successful HTTP response is a good proxy for a working site. For simple, server-rendered pages with no external dependencies, that was close enough. For modern web applications with hashed assets, CDN layers, API gateways, SPAs, and third-party dependencies, it’s a dangerous gap.

What Would Actually Catch These

The common thread across all six patterns is that the status code is the wrong layer to monitor. Catching these failures means shifting from “did the server respond?” to “does the response actually constitute a working page?”

That means treating the HTML document as a manifest, not a destination — following up on the assets it references, verifying their types, and confirming they load. It means following redirect chains to completion rather than trusting the first hop. It means tracking what your site returns over time so you notice when the content silently changes. And it means checking from more than one location, because CDN failures don’t happen everywhere at once.

This is the problem we built Sitewatch to solve. But regardless of what tool you use, the principle matters: stop trusting 200 OK as proof that your site works.

Have you been burned by a silent failure that hid behind 200 OK? I’d be curious to hear what the failure pattern was — these stories are how the industry gets better at catching them.