Skip to content

Preserve lambda Viper StringMap keys#857

Open
gontzess wants to merge 2 commits into
mainfrom
gontzess/fix-lambda-viper-stringmap-case
Open

Preserve lambda Viper StringMap keys#857
gontzess wants to merge 2 commits into
mainfrom
gontzess/fix-lambda-viper-stringmap-case

Conversation

@gontzess
Copy link
Copy Markdown
Contributor

Why

The typed-config fix preserves StringMap key case for generated connector configs, but lambda connectors that intentionally use *viper.Viper still receive the effective lambda config. Viper.Set recursively lowercases nested map[string]any keys, so dynamic StringMap fields can still lose case-sensitive keys.

What this changes

This makes the lambda effective config schema-aware for StringMapField values. Those payloads are stored as JSON strings before entering Viper, which keeps GetStringMap and GetStringMapString behavior while avoiding Viper's recursive map-key lowercasing. The PR also adds a regression test for the Viper path and keeps the existing typed-config test intact.

Depends on #856.

Validation

  • go test -tags baton_lambda_support ./pkg/cli
  • go test ./pkg/cli

out := make(map[string]struct{})
for _, schemaField := range connectorSchema.Fields {
if schemaField.Variant == field.StringMapVariant {
out[strings.ToLower(schemaField.FieldName)] = struct{}{}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we want to lower the field names here at all? WHat is consuming out that needs lowered names?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Example config value:

map[string]any{
	"user-custom-fields": map[string]any{
		"customString10":     "Custom String 10",
		"departmentNav/name": "Department",
	},
}

Non-Lambda CLI

Top-level field names are effectively Viper-managed and case-insensitive. The nested map keys are the customer’s payload and should stay as-is.

v.GetStringMapString("user-custom-fields")
// map[string]string{
//   "customString10":     "Custom String 10",
//   "departmentNav/name": "Department",
// }

Lambda, Typed Connector

This is the SuccessFactors-style path. With PR #856, the typed generated config decodes the raw lambda payload directly, bypassing Viper.Set for the connector struct.

cfg.UserCustomFields
// map[string]any{
//   "customString10":     "Custom String 10",
//   "departmentNav/name": "Department",
// }

PR #857 does not materially affect this path.

Lambda, Axiomatic / *viper.Viper

This is the future footgun path. Axiomatic receives *viper.Viper, so without PR #857 the nested keys would pass through Viper.Set as a map and become:

map[string]any{
	"customstring10":     "Custom String 10",
	"departmentnav/name": "Department",
}

With PR #857, only schema-declared StringMapField values are converted before Viper.Set:

"user-custom-fields" => `{"customString10":"Custom String 10","departmentNav/name":"Department"}`

Then Axiomatic reads it normally:

v.GetStringMapString("user-custom-fields")
// map[string]string{
//   "customString10":     "Custom String 10",
//   "departmentNav/name": "Department",
// }

we haven't used this field type yet for axiomatic but i think we want to set the precident as wanting case sensative - map keys are often external identifiers, not user-facing option names. They may be JSON paths, OData paths, SCIM attributes, API field names, headers, claim names, or vendor-specific IDs. Many of those are case-sensitive, or at least case-preserving.

Base automatically changed from gontzess/fix-stringmap-case-typed to main May 22, 2026 21:42
@gontzess gontzess requested a review from a team May 22, 2026 21:42
@gontzess gontzess force-pushed the gontzess/fix-lambda-viper-stringmap-case branch from 0e61804 to 066aa0b Compare May 22, 2026 21:44
@github-actions
Copy link
Copy Markdown
Contributor

General PR Review: Preserve lambda Viper StringMap keys

Blocking Issues: 0 | Suggestions: 0 | Threads Resolved: 0
Review mode: full
View review run

Review Summary

This PR makes effectiveLambdaConfig schema-aware so that StringMap field values are encoded as JSON strings before being passed to Viper.Set, avoiding Viper's recursive map-key lowercasing. The approach is sound: lambdaStringMapFields correctly collects StringMap fields from both top-level fields and field groups, and lambdaStringMapValueForViper cleanly handles the string passthrough and JSON encoding paths. The new test covers both GetStringMap and GetStringMapString retrieval, and the existing typed-config test is properly updated. No issues found.

Security Issues

None found.

Correctness Issues

None found.

Suggestions

None.

Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No blocking issues found.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants