# Design: Verb Header Propagation
**Author**: @worstell
<!-- Status of the document - draft, in-review, etc. - is conveyed via HackMD labels -->
## Description
Attach/propagate headers (metadata) through verb calls. Headers can be specified at verb, module, or realm level, with automatic propagation through the call chain based on the specification level. For HTTP ingress calls, selected headers are captured and automatically forwarded downstream; the same logic applies to verb-to-verb calls.
## Goals
- Support header propagation with the following levels of granularity:
1. Verb level—selected headers are captured through the inbound request and automatically forwarded downstream to any calls that occur within the annotated verb's call lifecycle. Only response-specified headers are returned in the verb's final response
2. Module level—selected headers are automatically propagated through all verb calls in the module; can be specified for propagation on requests and/or responses
3. Realm level—same as module-level, scoped to the entire realm
- Support context sharing (e.g., request IDs, security tokens, feature flags) throughout the system
### Non-Goals
- Security/auth/credential verification etc.
- Supporting middleware as a feature
## Design
Naming considerations:
```
//ftl:verbcontext
or
//ftl:verb
//ftl:context
```
```
//ftl:propagate
```
```
//ftl:propagate headers
```
```
//ftl:callcontext
```
```
//ftl:cascade
```
```
//ftl:forward
```
```
//ftl:forwarding
```
```
//ftl:carrier
```
Leaning "callcontext" or "forward", but interested in others' thoughts here.
### Header Specification Levels
1. **Verb Level Management (annotation)**
```go
//ftl:verb
//ftl:callcontext request-headers=["X-Request-ID", "X-Correlation-ID"] response-headers=["X-Request-ID"]
func ProcessOrder(ctx context.Context, req Request) (Response, error) {
// ...
}
```
2. **Module and Realm Level Management (FTL CLI)**
```bash
ftl callcontext <command>
Commands:
list List all headers
Flags:
--level=module Context level (${verb, module, realm}).
add
remove
# List all headers
ftl callcontext list headers
# List all realm-level headers
ftl callcontext list headers --level=realm
# List module-level headers for the echo module
ftl callcontext list headers echo
# List verb-level headers for the processOrder verb in the echo module
ftl callcontext list headers echo.processOrder
### Realm-level updates
# Add headers; defaults to realm level if not specified
ftl callcontext add --request-headers "X-Request-ID,X-Correlation-ID" --response-headers "X-Request-ID"
>>> No module or verb target was specified; update for the entire FTL realm? Y/n
# Remove headers; defaults to realm level if not specified
ftl callcontext remove --request-headers "X-Request-ID,X-Correlation-ID" --response-headers "X-Request-ID"
>>> No module or verb target was specified; update for the entire FTL realm? Y/n
### Module-level updates
ftl callcontext add ... echo
ftl callcontext remove ... echo
### Verb-level updates (can also be applied via manually annotating code).
# Running these commands edits the source code where the verb is declared
# to add or update the corresponding annotation.
ftl callcontext add ... echo.processOrder
ftl callcontext remove ... echo.processOrder
```
If no target is specified when executing any of the editing commands, the user will be prompted to confirm that they would like to perform the operation for the entire realm (default).
Verb level headers can be applied either by manually via annotation, or via `ftl callcontext add ... <module>.<verb>` which will add the annotation to the source code on the user's behalf.
Commands operating on the module or realm level will either update the `ftl.toml` (module) or `ftl-project.toml` (realm) correspondingly.
### Required changes
1. **Core**
- Add callcontext to the schema as verb metadata
- Determine which headers to propagate from the entrypoint based on schema/header configurations (may be implemented partially or completely by the runtimes, TBD)
4. **Runtime**
- Add callcontext annotations/APIs
- Use the “metadata” field in the FTL CallRequest/Response proto to pass information
- Copy headers via metadata across calls
- Filter select headers in the final verb response
5. **Ingress**
- Parse specified headers on inbound ingress calls and add them to the CallRequest metadata when invoking the verb internally