ai-docs: add DDD vocabulary for agent-assisted development#4009
ai-docs: add DDD vocabulary for agent-assisted development#4009greeshma1196 wants to merge 1 commit into
Conversation
- add communication style in agents.md Signed-off-by: greeshma1196 <greeshma.mathew@gmail.com>
| ### Predicate | ||
| Matching conditions determining if a route applies to a request: | ||
|
|
||
| - **Path Predicate**: Exact path with wildcards (`Path("/api/*resource")`) |
There was a problem hiding this comment.
- I think
wildcardsis true but missleading, because there are 2 different and likely not intuitive what they do.
See this "freeform wildcard" case:
% ./bin/skipper -inline-routes='r: Path("/foo/*bar") -> latency("3ms") -> status(201) -> <shunt>' -address :9002
..
[APP]INFO[0000] route settings, reset, route: r: Path("/foo/*bar") -> latency("3ms") -> status(201) -> <shunt>
...
::1 - - [15/May/2026:17:34:50 +0200] "GET /foo/bar/qux/baz HTTP/1.1" 201 0 "-" "curl/7.49.0" 3 localhost:9002 - -
::1 - - [15/May/2026:17:35:36 +0200] "GET /foo/foo/qux/baz HTTP/1.1" 201 0 "-" "curl/7.49.0" 3 localhost:9002 - -
So we do not need to match *bar, but *bar is a named "freeform wildcard" to use the name in variables for template filters later.
- Path() can also have named parameters called "simple wildcards". For example
Path( /customers/:id)
| - **Shunt Backend**: Handled internally without forwarding (`<shunt>`) | ||
| - **Loopback Backend**: Re-enters routing with modified request (`<loopback>`) | ||
| - **Dynamic Backend**: Target determined by filters at runtime (`<dynamic>`) | ||
| - **LB Backend**: Multiple endpoints with load balancing (`<roundRobin, "host1", "host2">`) |
|
|
||
| - **Path Predicate**: Exact path with wildcards (`Path("/api/*resource")`) | ||
| - **PathSubtree Predicate**: Path and all sub-paths (`PathSubtree("/admin")`) | ||
| - **PathRegexp Predicate**: Regex path matching (`PathRegexp(/\/api\/v[0-9]+\//)`) |
There was a problem hiding this comment.
It's more readable to use PathRegexp("/api/v[0-9]+/")
| ### Route Matching | ||
| Finding the appropriate route for an incoming request: | ||
|
|
||
| 1. **Path Tree Lookup**: Fast radix tree lookup |
There was a problem hiding this comment.
We should tell about that only Path() and PathSubtree() are part of this lookup
| - **Host Predicate**: Host header matching (`Host(/\.example\.com$/)`) | ||
| - **Method Predicate**: HTTP method (`Method("POST")`) | ||
| - **Header Predicate**: HTTP header matching (`Header("Accept", "application/json")`) | ||
| - **Custom Predicates**: User-defined logic (e.g., `Traffic(0.1)`, `Weight(100)`) |
| - **OTel Baggage Predicate**: Matches on OpenTelemetry baggage members | ||
| - **Key-only matching**: Matches if baggage member key exists, regardless of value (`OTelBaggage("key")`) | ||
| - **Key-value matching**: Matches if baggage member key exists AND value equals specified value (`OTelBaggage("key", "value")`) | ||
| - **Baggage Member**: Key-value pair with optional properties, stored in request context and propagated across service boundaries |
There was a problem hiding this comment.
Why do we list only a few predicates, but have 4 lines of OTelBaggagePredicate?
There was a problem hiding this comment.
I now remember why there is so much information on OTelBaggagePredicate. I worked on a PR where I was updating the predicate, so it updated this doc to reflect those changes.
| ### Filter | ||
| Processing units modifying requests/responses in a pipeline: | ||
|
|
||
| - **Filter Spec**: Factory for creating filter instances (`Spec` interface) |
There was a problem hiding this comment.
Does it make sense to change Spec to filters.Spec
| Processing units modifying requests/responses in a pipeline: | ||
|
|
||
| - **Filter Spec**: Factory for creating filter instances (`Spec` interface) | ||
| - **Filter Instance**: Route-specific filter with arguments (`Filter` interface) |
There was a problem hiding this comment.
Does it make sense to change Filter to filters.Filter
|
|
||
| - **Filter Spec**: Factory for creating filter instances (`Spec` interface) | ||
| - **Filter Instance**: Route-specific filter with arguments (`Filter` interface) | ||
| - **Filter Context**: Request-scoped state shared among filters (`FilterContext`) |
There was a problem hiding this comment.
Does it make sense to change FilterContext to filters.FilterContext
|
|
||
| ### Route Matching | ||
| Finding the appropriate route for an incoming request: | ||
|
|
There was a problem hiding this comment.
step 0 could be PriorityRoute, but I guess we should rather forget this. :)
| Finding the appropriate route for an incoming request: | ||
|
|
||
| 1. **Path Tree Lookup**: Fast radix tree lookup | ||
| 2. **Predicate Evaluation**: Testing non-path conditions |
| 1. **Path Tree Lookup**: Fast radix tree lookup | ||
| 2. **Predicate Evaluation**: Testing non-path conditions | ||
| 3. **Weight Resolution**: Handling multiple matches via weight | ||
| 4. **Route Selection**: First fully matching route |
There was a problem hiding this comment.
This is wrong:
- Only fully matching routes are considered.
- IF we have multiple routes matching then we use the one with the "highest" weight.
- If there is no match we do backtracking and use a less specific path route that math and check again all routes there until we match a route.
|
|
||
| 1. **Route Matching**: Finding applicable route | ||
| 2. **Filter Chain Execution**: Request-phase filters in order | ||
| 3. **Backend Forwarding**: Sending request to target |
There was a problem hiding this comment.
Backend Forwarding -> Proxy Call to Backend
Forwarding is terminology in the lower layer network and we have a forwarding backend with a different kind of idea than what we specify here.
| 1. **Route Matching**: Finding applicable route | ||
| 2. **Filter Chain Execution**: Request-phase filters in order | ||
| 3. **Backend Forwarding**: Sending request to target | ||
| 4. **Response Filter Chain**: Response-phase filters in reverse |
There was a problem hiding this comment.
Response-phase filters in reverse -> Execute Response() on filters in reverse order
| Complete request handling flow: | ||
|
|
||
| 1. **Route Matching**: Finding applicable route | ||
| 2. **Filter Chain Execution**: Request-phase filters in order |
There was a problem hiding this comment.
Request-phase filters in order -> Execute Request() on filters
| 2. **Filter Chain Execution**: Request-phase filters in order | ||
| 3. **Backend Forwarding**: Sending request to target | ||
| 4. **Response Filter Chain**: Response-phase filters in reverse | ||
| 5. **Response Delivery**: Streaming to client |
There was a problem hiding this comment.
Streaming to client -> Streaming Response headers and body to client
| Distribution across multiple backend endpoints: | ||
|
|
||
| - **Algorithm Selection**: roundRobin, random, consistentHash, powerOfRandomNChoices | ||
| - **Endpoint Health Tracking**: Monitoring availability |
There was a problem hiding this comment.
I am not sure what is meant by this.
I guess PHC -> Passive Health Checking
| - **Endpoint Health Tracking**: Monitoring availability | ||
| - **Fade-in**: Gradually ramping traffic to new endpoints | ||
|
|
||
| ## Key Abstractions |
There was a problem hiding this comment.
I think we should add types and packages to all of this below.
For example DataClient:
### routing.DataClient Interface
Abstraction for route definition sources:
- `LoadAll() ([]*eskip.Route, error)`: Load all routes
- `LoadUpdate() ([]*eskip.Route, []string, error)`: Incremental route updates returns all known routes, a list of route IDs scheduled for delete and an error.
| - `Response()`: Access HTTP response | ||
| - `StateBag()`: Share state between filters | ||
| - `PathParam()`: Extract path parameters | ||
| - `Serve()`: Short-circuit with custom response |
There was a problem hiding this comment.
These 5 are the most relevant or why it's only 5?
| ## Domain Patterns | ||
|
|
||
| ### Circuit Breaker | ||
| Fault tolerance for backend protection: |
There was a problem hiding this comment.
CBs are used on the client and likely should not be mentioned here (it should be considered as an egress feature).
|
|
||
| - **Client Rate Limiting**: Per-client request rate control | ||
| - **Service Rate Limiting**: Backend protection limits | ||
| - **Cluster Rate Limiting**: Distributed limiting across instances |
There was a problem hiding this comment.
we have 4 of these kind, maybe makes sense to list ?
| - **Client Rate Limiting**: Per-client request rate control | ||
| - **Service Rate Limiting**: Backend protection limits | ||
| - **Cluster Rate Limiting**: Distributed limiting across instances | ||
| - **Rate Limit Lookupper**: Client identification strategies (IP, header, static) |
| - **Cluster Rate Limiting**: Distributed limiting across instances | ||
| - **Rate Limit Lookupper**: Client identification strategies (IP, header, static) | ||
|
|
||
| ### Admission Control |
There was a problem hiding this comment.
Admission Control is one of "Load Shedders", right now we have only one, but there is a Draft PR to add a second one and likely we will add more here, too.
|
|
||
| - **Passive Mode**: Measures success rate without rejecting requests | ||
| - **Active Mode**: Rejects requests when measured success rate drops below threshold | ||
| - **Admission Signal Header**: HTTP header (`Admission-Control: true`) added to rejected requests |
There was a problem hiding this comment.
This is used in order to signal to other shedders that they should not count these as errors such that we do not have distributed effects to take down more and more parts of a distributed system.
| - **Request Phase**: Process before backend call | ||
| - **Response Phase**: Process in reverse order after backend | ||
| - **Filter Breaking**: Early termination with custom response | ||
| - **State Sharing**: Communication via StateBag |
There was a problem hiding this comment.
Communication -> Communication across filters
| - **Ingress Resources**: Standard Kubernetes ingress objects | ||
| - **RouteGroup Resources**: Custom Skipper CRD | ||
| - **Service Discovery**: Automatic endpoint discovery | ||
| - **Admission Control**: Webhook-based validation |
There was a problem hiding this comment.
Admission Control -> Admission Webhook
Where do we mention "Admission Control "? We should not
| - **RouteGroup Resources**: Custom Skipper CRD | ||
| - **Service Discovery**: Automatic endpoint discovery | ||
| - **Admission Control**: Webhook-based validation | ||
| - **East-West Routing**: Internal service-to-service routing within Kubernetes, bypassing the public ingress path; routes are cloned with a `Host` regexp matching the east-west domain (e.g., `svc.cluster.local`) |
There was a problem hiding this comment.
svc.cluster.local -> skipper.cluster.local is our default
| - **Admission Control**: Webhook-based validation | ||
| - **East-West Routing**: Internal service-to-service routing within Kubernetes, bypassing the public ingress path; routes are cloned with a `Host` regexp matching the east-west domain (e.g., `svc.cluster.local`) | ||
| - **East-West Domain**: Internal domain suffix used to identify and match east-west traffic | ||
| - **Endpoint Conditions**: Lifecycle states on EndpointSlice entries — `Ready` (healthy, accepting connections), `Serving` (may be terminating but still handling requests), `Terminating` (being shut down; excluded from selection) |
| Static file-based route definitions: | ||
|
|
||
| - **Eskip Files**: Routes in eskip DSL | ||
| - **Route String**: Simple command line definitions |
There was a problem hiding this comment.
not sure why this is within ### File DataClient
| - **Route String**: Simple command line definitions | ||
|
|
||
| ### routesrv | ||
| Proxy service that reduces kube-apiserver load by acting as a route cache between DataClient and Skipper instances: |
There was a problem hiding this comment.
a bit more than a proxy service and it's actually not proxying and requests
I would rather say it's:
Skipper and Kubernetes specific control plane service to reduce work of the ingress data plane creating routes and offload the kube-apiserver.
| ## Filter Categories | ||
|
|
||
| ### Header Manipulation | ||
| - `setRequestHeader`, `setResponseHeader`: Add/modify headers |
There was a problem hiding this comment.
set does not add nor modify, because it sets the request header
There are:
modRequestHeader to "modify"
appendRequestHeader to "add"/"append"
| ### Path Manipulation | ||
| - `modPath`: Regex-based path modification | ||
| - `setPath`: Replace entire path | ||
| - `setQuery`: Modify query parameters |
| - `basicAuth`: HTTP Basic authentication | ||
| - `oauthTokeninfoAnyScope`: OAuth token validation | ||
| - `webhook`: External authorization service | ||
| - `jwt`: JWT token validation |
| - `jwt`: JWT token validation | ||
|
|
||
| ### Traffic Management | ||
| - `tee`: Shadow/duplicate traffic to secondary backend |
There was a problem hiding this comment.
Shadow/duplicate traffic to secondary backend -> Shadow traffic (aka mirror traffic or duplicate traffic) to secondary backend
There was a problem hiding this comment.
Maybe we should have the terminology Shadow traffic explained elsewhere.
| - `static`: Serve static files | ||
| - `redirect`: HTTP redirects | ||
|
|
||
| ### Observability |
There was a problem hiding this comment.
the content of this part feels a bit random
| Random selection from available endpoints | ||
|
|
||
| ### ConsistentHash | ||
| Hash-based selection using client IP for sticky sessions |
There was a problem hiding this comment.
| Hash-based selection using client IP for sticky sessions | ||
|
|
||
| ### PowerOfRandomNChoices | ||
| Selects N random endpoints, chooses one with least active requests |
| - **Zone Threshold** (`minEndpointsByZone = 3`): Minimum number of zone-local endpoints required to serve a zone-filtered route | ||
| - **Threshold-Based Fallback**: When a zone has fewer than `minEndpointsByZone` endpoints, `getRouteForZone` returns the original unfiltered route with all endpoints | ||
| - **Zone-Specific Route Endpoint** (`/routes/{zone}`): The routesrv HTTP endpoint that serves pre-filtered zone-aware routes for a requested zone | ||
| - **routesrv Mode vs Direct Mode**: In routesrv mode the DataClient returns all endpoints with zone metadata unfiltered (so routesrv can do per-zone serving); in direct mode the DataClient filters by zone at ingestion time |
There was a problem hiding this comment.
Direct Mode is new terminology? Maybe DataClient mode?
There was a problem hiding this comment.
Yeah, its dataclient mode. This is probably because of the way I used the vocab.
| Hooks that transform routes before and after the routing tree is built: | ||
|
|
||
| - **PreProcessor interface** (`routing.PreProcessor`): Transforms `[]*eskip.Route` before the routing tree is built | ||
| - **PostProcessor interface** (`routing.PostProcessor`): Transforms `[]*routing.Route` after the routing tree is built |
There was a problem hiding this comment.
I would say you or the tool miss understood the code.
Did you read receiveRouteMatcher in routing/datasource.go?
| - **PostProcessor interface** (`routing.PostProcessor`): Transforms `[]*routing.Route` after the routing tree is built | ||
| - **Editor** (`eskip.Editor`): A preprocessor that regex-replaces predicates in route definitions (e.g., migrate `Source` → `ClientIP`) | ||
| - **Clone** (`eskip.Clone`): A preprocessor that duplicates routes with predicate substitutions for migration paths | ||
| - **DefaultFilters** (`eskip.DefaultFilters`): A preprocessor that appends a common filter set to all matching routes |
There was a problem hiding this comment.
There is an Append and a Prepend here
| ### Endpoint Registry | ||
| Central management of backend endpoint health: | ||
|
|
||
| - **Health Checking**: Active and passive monitoring |
There was a problem hiding this comment.
we do only passive health checking
| Central management of backend endpoint health: | ||
|
|
||
| - **Health Checking**: Active and passive monitoring | ||
| - **Endpoint States**: Healthy, unhealthy, dead |
There was a problem hiding this comment.
I think the states are hallucinated
| - **Route Metrics**: Per-route counts, latencies, error rates | ||
| - **Filter Metrics**: Individual filter performance | ||
| - **Backend Metrics**: Upstream response times and success rates | ||
| - **Custom Metrics**: User-defined measurements |
There was a problem hiding this comment.
Host based metrics are missing and not sure if Custom Metrics are "User-defined" and how a user defines them (What kind of user we are talking about?)
| - **Backend Metrics**: Upstream response times and success rates | ||
| - **Custom Metrics**: User-defined measurements | ||
|
|
||
| ### Swarm Clustering |
There was a problem hiding this comment.
this you can drop, I will delete it soon.
Adds ai-docs/ddd-vocab.md, a domain-driven design vocabulary for Skipper, to keep agent-assisted development aligned with the project's domain language