Skip to content

fix(cognito): do not return optional blocks in CreateUserPoolClient when they are not set#1615

Merged
hectorvent merged 3 commits into
floci-io:mainfrom
b6k-dev:fix/cognito-user-pool-client-optional-blocks
Jul 2, 2026
Merged

fix(cognito): do not return optional blocks in CreateUserPoolClient when they are not set#1615
hectorvent merged 3 commits into
floci-io:mainfrom
b6k-dev:fix/cognito-user-pool-client-optional-blocks

Conversation

@b6k-dev

@b6k-dev b6k-dev commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

Summary

Closes #1505

Changes summary:

  • Omit optional blocks when serialzing CreateUserPoolClient
  • Add unit tests
  • Add compatibility tests for: Java SDK, terraform and opentofu

Type of change

  • Bug fix (fix:)
  • New feature (feat:)
  • Breaking change (feat!: or fix!:)
  • Docs / chore

AWS Compatibility

Incorrect behavior: CreateUserPoolClient returned "AnalyticsConfiguration": {} , "TokenValidityUnits": {} , and "RefreshTokenRotation": {} in the response body when those fields were not configured.

Fixed behavior: Optional block fields are now omitted from the CreateUserPoolClient response when not set.

Checklist

  • ./mvnw test passes locally
  • New or updated integration test added
  • Commit messages follow Conventional Commits

@hectorvent hectorvent added bug Something isn't working cognito Amazon Cognito labels Jun 28, 2026
@greptile-apps

greptile-apps Bot commented Jun 30, 2026

Copy link
Copy Markdown

Greptile Summary

This PR fixes a serialization bug in Floci's Cognito emulator where CreateUserPoolClient (and by extension DescribeUserPoolClient / UpdateUserPoolClient) was returning empty JSON objects ({}) for AnalyticsConfiguration, TokenValidityUnits, and RefreshTokenRotation when those optional blocks were not configured, breaking Terraform/OpenTofu provider parsing.

  • Core fix in CognitoJsonHandler.clientToNode: replaces the value != null ? value : new HashMap<>() pattern with Optional.ofNullable(...).ifPresent(...), so absent fields are simply omitted from the JSON response.
  • Unit tests added at both the service level (CognitoServiceTest) and JSON-serialization level (CognitoJsonHandlerTest), plus a Java SDK compatibility test and Terraform/OpenTofu end-to-end tests to prevent regression.

Confidence Score: 5/5

Safe to merge — the change is a narrow, well-tested serialization fix with no impact on request parsing or business logic.

The fix is confined to three lines in the shared clientToNode serialization method. It has no effect on how requests are parsed or how the service stores state — only on which fields are emitted in the response. Coverage is thorough: service-layer null assertions, JSON-serialization assertions, a Java SDK end-to-end test, and Terraform/OpenTofu apply tests. No regressions are introduced for callers that do set these optional fields, since Optional.ifPresent still emits them when non-null.

No files require special attention.

Important Files Changed

Filename Overview
src/main/java/io/github/hectorvent/floci/services/cognito/CognitoJsonHandler.java Core fix: replaces empty-map fallback with Optional.ifPresent for AnalyticsConfiguration, TokenValidityUnits, and RefreshTokenRotation in clientToNode; applies correctly to all three client operations (Create/Describe/Update) since they share this method.
src/test/java/io/github/hectorvent/floci/services/cognito/CognitoJsonHandlerTest.java New test createUserPoolClientDoesNotReturnOptionalBlockKeysWhenNotSet verifies that absent fields are omitted from the serialized JSON response; covers the serialization layer accurately.
src/test/java/io/github/hectorvent/floci/services/cognito/CognitoServiceTest.java New test createUserPoolClientWithNoOptionalBlocksLeavesThemNull confirms the service model layer returns null for the three optional fields when not provided; logically sound.
compatibility-tests/sdk-test-java/src/test/java/com/floci/test/CognitoFeaturesTest.java SDK compatibility test verifies AWS Java SDK correctly deserializes a response with absent optional blocks as null; cleanup correctly deletes the new client before the pool.
compatibility-tests/compat-terraform/main.tf Adds aws_cognito_user_pool_client resource referencing the pre-existing pool, enabling the end-to-end Terraform apply test.
compatibility-tests/compat-terraform/test/terraform.bats Bats test verifies the pool client was successfully created (non-empty, non-None ClientId), including the non-empty guard requested in prior review feedback.
compatibility-tests/compat-opentofu/main.tf Adds both the Cognito user pool and its client resource to the OpenTofu configuration; names match what the bats test queries for.
compatibility-tests/compat-opentofu/test/opentofu.bats Mirrors the Terraform bats test; verifies client existence after apply with non-empty and non-None guards.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant Client as AWS SDK / Terraform
    participant Handler as CognitoJsonHandler
    participant Service as CognitoService
    participant Model as UserPoolClient (model)

    Client->>Handler: CreateUserPoolClient (no optional blocks)
    Handler->>Service: createUserPoolClient(poolId, name, ...)
    Service->>Model: "new UserPoolClient (analyticsConfiguration=null, tokenValidityUnits=null, refreshTokenRotation=null)"
    Service-->>Handler: UserPoolClient
    Handler->>Handler: clientToNode(client)
    Note over Handler: Optional.ofNullable(null).ifPresent(...) fields are OMITTED (not emitted as {})
    Handler-->>Client: "{UserPoolClient: {ClientId: ...}} (no AnalyticsConfiguration, TokenValidityUnits, RefreshTokenRotation keys)"
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant Client as AWS SDK / Terraform
    participant Handler as CognitoJsonHandler
    participant Service as CognitoService
    participant Model as UserPoolClient (model)

    Client->>Handler: CreateUserPoolClient (no optional blocks)
    Handler->>Service: createUserPoolClient(poolId, name, ...)
    Service->>Model: "new UserPoolClient (analyticsConfiguration=null, tokenValidityUnits=null, refreshTokenRotation=null)"
    Service-->>Handler: UserPoolClient
    Handler->>Handler: clientToNode(client)
    Note over Handler: Optional.ofNullable(null).ifPresent(...) fields are OMITTED (not emitted as {})
    Handler-->>Client: "{UserPoolClient: {ClientId: ...}} (no AnalyticsConfiguration, TokenValidityUnits, RefreshTokenRotation keys)"
Loading

Reviews (2): Last reviewed commit: "fix(cognito): improve bats assertions" | Re-trigger Greptile

Comment thread compatibility-tests/compat-opentofu/test/opentofu.bats
Comment thread compatibility-tests/compat-terraform/test/terraform.bats
@b6k-dev

b6k-dev commented Jun 30, 2026

Copy link
Copy Markdown
Contributor Author

https://github.com/floci-io/floci/actions/runs/28461093249/job/84350196672?pr=1615 - seems like a Docker build cache issue not related to my changes

@hectorvent hectorvent left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks @b6k-dev,
Solid fix

@hectorvent
hectorvent merged commit 6c5f533 into floci-io:main Jul 2, 2026
27 of 29 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working cognito Amazon Cognito

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] CreateUserPoolClient returns empty {} for unset optional blocks, breaking Terraform applies

2 participants