Transformation schema
The shape of a transformation rule. Same JSON for both phases, both protocols. Each rule carries one action — covering headers, body fields (JSON Pointer), Diameter AVPs, status-code rewrites, and 3GPP error normalization.
Top-level shape
A transformation rule pairs a condition (when it applies) with a single action and its config (what it does). To apply several changes, author several rules.
phase and priority
phase: request— fires in the request filter chain before forwarding. Sees and can rewrite the inbound request.phase: response— fires in the response stage before the answer reaches the consumer. Sees and can rewrite the producer's answer.priority— lower runs first. Rules with equal priority sort bynameascending for determinism across restarts and replicas. Priorities don't span phases. Apriority: 100rule sees the original request; apriority: 200rule in the same phase sees the request after the first rule applied, so design accordingly when rules touch the same field.enabled— a disabled rule is stored but never evaluated.
condition
The condition object embeds the same CommonConditions as a policy rule (path, method, NF types, S-NSSAIs, visited PLMNs, protocols, Diameter application/command/origin/dest, IMSI ranges) as a flat shape, plus three transform-specific matchers. A rule whose condition is empty applies to every message in its phase.
header_match— map of header name to regex pattern (matched on the value).body_field_match— map of JSON Pointer to regex pattern (matched on the field value).status_codes— array of integer status codes; response phase only.
Actions
The action field is one of the values below. Each takes a fixed subset of config keys. Header and body-field actions work for SBI; AVP actions work for Diameter; status_rewrite and error_normalize are response-phase, SBI-only.
header_set
Set a header, replacing any existing value with the same name.
header_add
Append a header value without removing existing values of the same name.
header_remove
header_rewrite
Regex match-and-substitute on the value of a header. No-op if the header is absent.
body_field_set
Set or add a body field at a JSON Pointer path. field_value may be any JSON value.
body_field_remove
body_field_mask
Mask the value at a JSON Pointer path. Set mask_value for a literal replacement, or use mask_type (full, partial, hash) with mask_char, keep_prefix, and keep_suffix to mask in place.
body_field_map
Replace the value at a JSON Pointer path by looking it up in value_map. If the current value isn't a key in the map, the field is left unchanged.
status_rewrite
Response phase only. Rewrites the HTTP status code from from_status to to_status when it matches.
error_normalize
Response phase only. For a 4xx/5xx response whose body is not already a 3GPP ProblemDetails document (no status field), synthesizes a application/problem+json body from error_title and error_cause. Both fields default (to the HTTP status text and SYSTEM_FAILURE) if omitted.
avp_set (Diameter)
Set an AVP, replacing any existing instance. AVP value type is resolved from the dictionary by code.
avp_add (Diameter)
Add an AVP without removing existing instances of the same code.
avp_remove (Diameter)
avp_rewrite (Diameter)
Regex match-and-substitute on the string value of an AVP. No-op if the AVP is absent.
avp_mask (Diameter)
Mask an AVP's value using the same mask_type, mask_char, keep_prefix, and keep_suffix knobs as body_field_mask.
Template variables
Header values (header_value on header_set and header_add) support ${var} substitution. Body and AVP values are written literally and do not template. Variables:
${request_id}— the proxy's per-request identifier.${supi}— extracted SUPI, if any.${gpsi}— extracted GPSI, if any.${dnn}— extracted DNN, if any.${source_nf_type}— consumer NF type, if resolved.${target_nf_type}— producer NF type, if resolved.
An unknown placeholder is left in the string verbatim. CR/LF characters are stripped from substituted values.
Failure semantics
The transformation filter mutates but never blocks. A rule never denies or fails a request:
- Invalid regex — dropped at rule load time, logged as a warning. The rule's regex-based step is skipped; it cannot fail at request time.
- Bad JSON Pointer or non-JSON body — the failing op is logged at warn level and skipped; the message proceeds unchanged. Other ops on the same message still run.
- Response phase — read/marshal errors are logged; the response is forwarded (the original body is restored). The transform filter never synthesizes a 5xx or 502.
The chain still counts the filter in edge_filter_decisions_total with filter="transformation" (allow when the rewrite succeeds, deny if it returns an error). Watch rewrite failures in the structured logs as well. See Metrics.
Where to go next
- Transformation engine — how rules are matched and ordered.
- Admin API → Transformations — CRUD. Manifest dry-run is
d3x-edgectl apply --dry-run. - Tutorial: your first transformation rule.