Skip to content

resource/pingone_davinci_flow: form node theme reference (theme.value / themeId.value) not resolved as embedded reference #128

Description

@samir-gandhi

Community Note

  • Please vote on this issue by adding a 👍 reaction to the original issue to help the community and maintainers prioritize this request
  • Please do not leave "+1" or other comments that do not add relevant new information or questions, they generate extra noise for issue followers and do not help prioritize the request
  • If you are interested in working on this issue or have submitted a pull request, please leave a comment

Description

resource/pingone_davinci_flow node data on pingOneFormsConnector showForm nodes can reference a DaVinci UI template/theme. The DaVinci UI exposes three distinct configurations for this ("theme" options in the node's editor), and the raw JSON shape differs across all three — this is not a single field with a UUID-or-placeholder value, it's a mode selector plus a conditionally-present second field:

  1. Direct theme UUIDproperties.theme.value is a real UUID referencing a specific UI template.
  2. Unset / defaultproperties.theme key is absent entirely.
  3. Indirect via themeIdproperties.theme.value is the literal string "useThemeId" (a mode discriminator, not a UUID), and the actual reference lives in a sibling property, properties.themeId.value, wrapped in the same rich-text/Slate JSON structure used elsewhere in this schema (e.g. mfaPolicyId, userId): "[{\"children\":[{\"text\":\"<uuid-or-variable>\"}]}]".

None of these three are resolved today — the exporter emits them as inert raw strings inside the properties JSON blob, the same treatment as any other opaque form config value. This mirrors a case we already handle correctly for a single-field UUID: properties.form.value (also a UUID, referencing a DaVinci form) is resolved via an EmbeddedReferenceRule with the reference_with_fallback strategy (internal/platform/pingone/resource_flow.go). Case 1 above fits that existing mechanism directly. Cases 2 and 3 do not — case 2 needs no rule to fire at all (already correct/inert), and case 3 requires resolving the reference from a different JSON key (themeId.value) than the one holding the mode flag (theme.value), plus unwrapping the rich-text wrapper before the UUID (or variable) is reachable. No existing code in this repo unwraps that rich-text shape yet (confirmed: mfaPolicyId/userId, which use the identical wrapper, are also just passed through unresolved today) — case 3 may need new handling beyond a simple EmbeddedReferenceRule registration, or an extension to walkJSONPath/the rule mechanism to support unwrapping before UUID extraction.

Emitting a bare UUID string means re-applying the exported HCL against a different environment (or after the referenced theme/template changes ID) silently breaks, with no depends_on edge and no way to override it without editing the JSON blob by hand.

Note: there is currently no pingone_davinci_ui_template/theme resource exported by this tool, so — same as form.value before pingone_davinci_form existed — a resolved reference would start as a variable fallback (UUID exposed as an overridable Terraform variable) rather than a full resource reference, and would automatically upgrade to a reference once a UI template resource is added.

Evidence

Confirmed directly against a real flow export containing all three cases side by side (three pingOneFormsConnector showForm nodes):

{
  "capabilityName": "showForm",
  "properties": {
    "form": { "value": "860b5cd5-45cc-466d-abbd-64298bb90bed" },
    "theme": { "value": "e6fd37f9-11dd-40f3-90f6-eaeb971ee3db" }
  }
}
{
  "capabilityName": "showForm",
  "properties": {
    "form": { "value": "ba30f833-e6a5-4fda-9ff1-2576ece5108c" }
  }
}
{
  "capabilityName": "showForm",
  "properties": {
    "form": { "value": "e439ac2a-8712-4ed0-9619-edd8526d286e" },
    "theme": { "value": "useThemeId" },
    "themeId": { "value": "[\n  {\n    \"children\": [\n      {\n        \"text\": \"abc123\"\n      }\n    ]\n  }\n]" }
  }
}

(An earlier export also showed a fourth string, "activeTheme", in theme.value on a node with no themeId — possibly an older/different sentinel than "useThemeId", or a naming change between DaVinci versions; worth confirming which sentinel(s) are current.)

form.value is a real UUID in all three nodes and is unaffected by which theme mode is set — the form.value reference rule applies identically regardless.

Separately, the same export surfaced a form-connector capability difference worth noting for scoping: the legacy pingOneFormsConnector capability is customForm; the current one is showForm. customForm's property set is a strict subset (dynamicText, form, formData, nodeTitle — no theme/themeId, no outcomes, no authenticationMethodSource, etc.), confirmed absent from a customForm node in the same export. Theme configuration appears to be showForm-specific. The fix shouldn't need capability-aware branching — rules only fire when the relevant JSON key exists — but flagging in case a theme concept appears on customForm in the future with a different shape.

Ping CLI and Plugin Version

Current main (post-#127, DaVinci flow outcomes fix).

Affected Command(s)

  • pingcli tfr export (or standalone equivalent) for pingone_davinci_flow

Expected Behavior

  • When properties.theme.value holds a direct UUID (case 1), it is resolved the same way properties.form.value is: replaced with a Terraform variable reference (fallback) or a resource reference (once a UI template/theme resource exists), with a corresponding graph edge / depends_on where applicable.
  • When properties.theme is absent (case 2), no change is needed — nothing to resolve.
  • When properties.theme.value is the "useThemeId" mode flag (case 3), the UUID (or variable-slot placeholder) inside properties.themeId.value's rich-text wrapper is extracted and resolved the same way, without disturbing the theme mode flag itself.

Actual Behavior

In all three cases, whatever raw string(s) are present are left embedded in the properties JSON blob verbatim — no variable, no reference, no dependency tracking. Re-applying the exported HCL in a different environment (where a referenced UUID doesn't exist) or after a theme is regenerated will silently point at the wrong (or a nonexistent) theme, for either theme.value (case 1) or the UUID nested in themeId.value (case 3).

Steps to Reproduce

  1. Export a DaVinci flow containing pingOneFormsConnector showForm nodes covering the three theme configurations above (a specific theme selected directly, no theme set, and a theme selected via the "use theme ID" option).
  2. Inspect the generated HCL — the properties attribute (rendered via jsonencode_raw) contains the raw theme/themeId values with no variable or reference substitution.
  3. Compare against the same nodes' form.value, which is substituted with a variable/reference.

Important Factoids

  • No pingone_davinci_ui_template (or theme) resource is exported by this tool yet — a resolved reference would land as a variable fallback initially, same bootstrapping path form.value took before pingone_davinci_form existed.
  • The existing EmbeddedReferenceRule mechanism (internal/core/embedded_references.go) may need extending, not just a new registration — it currently only supports extracting a UUID from a single JSONKeyPath (via walkJSONPath, which expects a plain string value at the end of the path). Case 3 needs (a) checking a different key's value (theme.value == "useThemeId") as a precondition before acting on themeId, and (b) unwrapping the rich-text [{"children":[{"text":"..."}]}] structure to reach the actual UUID before/after resolution — walkJSONPath returns "" today if the final value isn't a plain string. Case 1 (theme.value as a direct UUID) fits the existing mechanism as-is.
  • Related: resource/pingone_branding_theme: add export support #35, resource/pingone_branding_theme_default: add export support #36 (branding theme resource export support) — unclear yet whether DaVinci UI templates/themes are the same underlying resource as PingOne branding themes, or a distinct DaVinci-specific concept; worth checking before deciding the eventual target resource type for a non-fallback reference.
  • The rich-text wrapper format is shared with at least mfaPolicyId and userId elsewhere in showForm's properties — also currently unresolved/opaque. If a generic rich-text-unwrap helper is built for themeId, it's likely reusable for those too (separate issue/scope, noting here for context).

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    davinciPingOne DaVinci categoryenhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions