13 Ekim 2026 Salı

SSRF - Server-Side Request Forgery

Giriş
Dışarıya bakan bir REST noktamız var. Bu nokta şöyle olsum
@RestController
@RequestMapping("/preview")
class PreviewController {

    private final RestClient restClient;

    PreviewController(RestClient.Builder builder) {
        this.restClient = builder.build();
    }

    @GetMapping
    String preview(@RequestParam URI url) {
        return restClient.get()
                .uri(url)
                .retrieve()
                .body(String.class);
    }
}
Eğer saldırgan URL olarak içsel/dahili bir adres verirse, butün güvenlik önlemlerini aşabilir. 

Spring Boot 4.1.1 bunu önlemek için org.springframework.boot.http.client.InetAddressFilter; sınıfını sağlıyor. Böylece restClient başka bir adrese bağlanamaz.

CRDTs - Conflict-Free Replicated Data Types

Giriş
Conflict-free replicated data types( CRDTs) are a family of data structures for sets, maps, ordered lists, counters, etc that can be concurrently edited by multiple users. It uses two-way merges.
İlgili bir yazı burada
Örnek
Şöyle olsun
import java.util.Objects;

public record ReplicaId(String value) {
    public ReplicaId {
        if (value == null || value.isBlank()) {
            throw new IllegalArgumentException("Replica ID must not be blank");
        }
    }
}
Şöyle olsun
public sealed interface CounterCommand
        permits CounterCommand.Increment, CounterCommand.Decrement {
    ReplicaId replica();
    record Increment(ReplicaId replica) implements CounterCommand {
        public Increment {
            java.util.Objects.requireNonNull(replica);
        }
    }
    record Decrement(ReplicaId replica) implements CounterCommand {
        public Decrement {
            java.util.Objects.requireNonNull(replica);
        }
    }
}
Gerçekleştirim şöyle.
Instead of storing one mutable total, it stores two maps:
- positive: the cumulative increments made by each replica.
- negative: the cumulative decrements made by each replica.
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

public record PnCounter(
        Map<ReplicaId, Long> positive,
        Map<ReplicaId, Long> negative) {

    public PnCounter {
        positive = immutableNonNegative(positive);
        negative = immutableNonNegative(negative);
    }

    public static PnCounter empty() {
        return new PnCounter(Map.of(), Map.of());
    }

    public PnCounter apply(CounterCommand command) {
        Objects.requireNonNull(command);

        return switch (command) {
            case CounterCommand.Increment inc ->
                    new PnCounter(bump(positive, inc.replica()), negative);
            case CounterCommand.Decrement dec ->
                    new PnCounter(positive, bump(negative, dec.replica()));
        };
    }

    public PnCounter merge(PnCounter other) {
        Objects.requireNonNull(other);
        return new PnCounter(
                joinByMaximum(positive, other.positive),
                joinByMaximum(negative, other.negative));
    }

    public long value() {
        return Math.subtractExact(sum(positive), sum(negative));
    }

    private static Map<ReplicaId, Long> bump(
            Map<ReplicaId, Long> current,
            ReplicaId replica) {

        var next = new HashMap<>(current);
        next.merge(replica, 1L, Math::addExact);
        return Map.copyOf(next);
    }

    private static Map<ReplicaId, Long> joinByMaximum(
            Map<ReplicaId, Long> left,
            Map<ReplicaId, Long> right) {

        var merged = new HashMap<>(left);
        right.forEach((replica, count) ->
                merged.merge(replica, count, Math::max));
        return Map.copyOf(merged);
    }

    private static long sum(Map<ReplicaId, Long> components) {
        return components.values().stream()
                .mapToLong(Long::longValue)
                .reduce(0L, Math::addExact);
    }

    private static Map<ReplicaId, Long> immutableNonNegative(
            Map<ReplicaId, Long> source) {

        Objects.requireNonNull(source);
        Map<ReplicaId, Long> copy = Map.copyOf(source);
        copy.forEach((replica, count) -> {
            Objects.requireNonNull(replica);
            if (count < 0) {
                throw new IllegalArgumentException("Components must be non-negative");
            }
        });
        return copy;
    }
}


9 Ekim 2026 Cuma

Metamorphic Testing

Giriş
Konuyu ilk defa burada gördüm.
Traditional testing assumes you know the expected output.

assertEquals(4, calculator.add(2, 2));

But how do you test an LLM that generates open-ended answers when there is no single correct output?

This is called the oracle problem: determining whether a program's output is correct when the expected answer is difficult or impossible to establish.

Metamorphic testing addresses this by checking relationships between multiple executions instead of checking each output against a known answer.
Örnek
How metamorphic testing works

The key concept is a metamorphic relation (MR): a property that should remain true when you transform an input and execute the system again.

1. Original input

A woman is sitting on a park bench with her dog.

Paraphrase without changing meaning

2. Transformed input

A woman sits outdoors with her pet nearby.

Run both inputs through the LLM

Same classification : Relation holds

Different classification : Potential fault

The important point is that you don't need to know the correct classification in advance. If two semantically equivalent inputs produce contradictory classifications, the model may be behaving inconsistently. 

8 Ekim 2026 Perşembe

TCP Bottleneck Bandwidth and Round-trip propagation time (BBR)

1. Flow control — protects the receiver
Flow control = don't overwhelm the receiver.

2. Congestion control — protects the network
Even if the receiver can accept 1 GB/s, the network path might only handle 100 MB/s.

3. BBR — a different approach to congestion control
BBR changes the question.

Instead of primarily asking:
"Did I lose packets?"

it measures:
- Bandwidth
- RTT (latency)

and estimates the network's BDP (Bandwidth × RTT).

Then it tries to keep approximately the right amount of data in flight to utilize the available bandwidth without unnecessarily filling network buffers.

CUBIC ve BBR

CUBIC:
send faster
   ↓
packet loss
   ↓
slow down
   ↓
increase again
   ↓
loss
   ↓
slow down
BBR:
measure bandwidth + RTT
          ↓
estimate capacity
          ↓
send near that rate
          ↓
continuously measure again

ETL (Extract Transform Load) Pipeline

1. ETL Pipeline ne zaman lazım olur ?
- Bir projeyi ilk defa ayağa kaldırırken mevcut veriyi alıp kendi veri modelimize çevirirken kullanırız.

- Çalışan bir başka sistemin değişen deltasını alıp kendi sistemimize ekleyerek, senkronizasyonu sağlamak amaçlı kullanabiliriz.

- Data warehouse sistemini çeşitli kaynakları kullanarak beslemek için kullanabiliriz.

2. ELED Extract–Load–Eligibility-Deliver Pipeline
Aslında delivery pipeline demek daha doğru. ELED benim kendi uydurmam. Açıklaması şöyle
An ELD (Extract–Load–Deliver) delivery pipeline with eligibility, acknowledgment, retry, and penalty processing.
Burada
  • Extract = obtain candidate work from the source.
    • Read pending transmission records from DB
    • Receive new transmission requests
    • Fetch configuration/parameters needed to decide eligibility
  • Load = bring that work into the dispatcher's working set.
    • Put records into the actor's queue/buffer
    • Restore pending/in-flight state
    • Build the in-memory transmission items
  • Eligibility = decide what can be transmitted now.
    • Is it enabled?
    • Is the penalty expired?
    • Is the destination available?
    • Is the item within its transmission window?
    • Has it already been sent/in-flight?
  • Deliver = actually perform reliable transmission.
    • Send
    • Wait for ACK
    • Retry
    • Apply penalty
    • Complete/remove the item


    6 Ekim 2026 Salı

    Invariant nedir

    Giriş
    Açıklaması şöyle
    An invariant is not documentation describing what usually happens. It is a condition that must remain true across every valid transition in the system.
    Örnek
    Available + reserved= total inventory 

    30 Eylül 2026 Çarşamba

    JSON Çeşitleri

    Giriş
    Açıklaması şöyle
    There's a whole ecosystem of JSON-adjacent formats that have emerged over the years, each extending or modifying the base specification to solve problems the original format wasn't designed for.
    JSONL  - JSON Lines
    Açıklaması şöyle. Streaming ve memory problemini çözer
    JSONL is multiple independent JSON objects, one per line. Each line is a complete, valid JSON record. A thousand records means a thousand lines, each standing alone.
    Örnek
    Şöyle yaparız
    // Regular JSON - one structure
    {
      "records": [
        {"id": 1, "name": "Alice", "status": "active"},
        {"id": 2, "name": "Bob", "status": "inactive"},
        {"id": 3, "name": "Carol", "status": "active"}
      ]
    }
    // JSONL - one record per line
    {"id": 1, "name": "Alice", "status": "active"}
    {"id": 2, "name": "Bob", "status": "inactive"}
    {"id": 3, "name": "Carol", "status": "active"}

    JSON5 ve JSONC - JSON with Comments
    Açıklaması şöyle
    Allows comments and trailing commas for more forgiving configuration files. JSONC (JSON with comments, used by VSCode) does something similar.
    BISON - Binary JSON
    Açıklaması şöyle
    Powers MongoDB's internals.
    EJSON (Extended JSON)
    Açıklaması şöyle
    Adds additional type support. 
    GeoJSON
    Açıklaması şöyle
    Structures geographic data.