Skip to content

Add flow-centric browser SSO - #3779

Merged
rajithacharith merged 1 commit into
thunder-id:mainfrom
madurangasiriwardena:feature/session-poc-2-rebased
Jul 10, 2026
Merged

Add flow-centric browser SSO#3779
rajithacharith merged 1 commit into
thunder-id:mainfrom
madurangasiriwardena:feature/session-poc-2-rebased

Conversation

@madurangasiriwardena

@madurangasiriwardena madurangasiriwardena commented Jul 6, 2026

Copy link
Copy Markdown
Member

Purpose

Introduces flow-centric browser SSO — the ability to reuse an existing browser login session across applications that share the same authentication flow, so a returning user can skip re-authenticating.

SSO is expressed as a property of the authentication flow graph rather than a separate subsystem: the flow author places SSO nodes to decide what an existing session lets a user skip. A session belongs to exactly one flow (keyed by flow_id) and is referenced by an opaque per-flow handle cookie; two apps SSO with each other iff they are configured with the same flow.

This is a first-phase (POC-level) implementation. A few data-handling decisions are deliberately interim, pending a follow-up flow-context data-classification effort (called out under Approach → Deferred).

Design discussion (architecture, storage model, DB operations): #3673

Approach

Flow graph — two node types, used as one or more checkpoint pairs

  • SSO-Check (SSOCheckExecutor, utility node) — resolves whether a live, compatible session already holds a given checkpoint and routes skip vs. authenticate (via onSuccess/onFailure).
  • Session (SessionExecutor, authentication node) — the join where the SSO and fresh-auth branches converge. On the fresh path it saves the checkpoint's context and mints a handle; on the SSO path it loads the saved context so downstream nodes continue authenticated.
  • A flow may contain multiple SSO-Check/Session checkpoint pairs (e.g. password as one checkpoint, step-up/MFA as another). Each SSO-Check binds to its Session node via a checkpointRef node property; the checkpoint id is that join node's id. All checkpoints of one login share a single session per flow execution, established idempotently on flow_execution_id, so each stage can be skipped independently on reuse. Create-vs-append is decided from the database (by handle or flow execution id), not in-memory ordering, so it holds under multi-request / divergent-branch flows.
image

Storage (runtime DB)

  • SSO_SESSION — lean row read on every resolve/touch (one row per establishing flow execution; unique on flow_execution_id).
  • SSO_SESSION_CONTEXT — one encrypted row per checkpoint ((session_id, checkpoint_id)), loaded only on the SSO restore path.
  • SSO_SESSION_PARTICIPANT — apps that used the session (basis for future session-wide logout/revocation).

Session lifecycle — governed by configurable idle (sliding) and absolute deadlines; the resolver rejects a session past either.

Engine-agnostic integration — the reusable flow engine (pkg/thunderidengine) stays SSO-unaware. SSO inputs ride on the request context.Context; the minted handle is returned on the engine's generic AdditionalData channel and the product transport layer turns it into the per-flow cookie. No SSO-specific field is added to the engine contract.

Deferred to a follow-up (flow-context data classification)

  • The resolved AuthUser is currently snapshotted as-is (materialized attributes), and RuntimeData is persisted in full apart from a deny-list of transient SSO control keys and request-scoped keys (requested_permissions, required_*_attributes, required_locales, clientId, authorizationRequestId, applicationId). A later phase will introduce a proper durability classification and attribute minimization/re-resolution. Tracked in SSO_TODO.md.
  • Session end/logout fan-out and an SSO cleanup job are defined as seams but not wired yet.

Related Issues

Related PRs

Checklist

  • Followed the contribution guidelines.
  • Manual test round performed and verified.
  • Documentation provided. (Add links if there are any)
    • Ran Vale and fixed all errors and warnings
  • Tests provided. (Add links if there are any)
    • Unit Tests
    • Integration Tests
  • Breaking changes. (Fill if applicable)
    • Breaking changes section filled.
    • breaking change label added.

Security checks

  • Followed secure coding standards in WSO2 Secure Coding Guidelines
  • Confirmed that this PR doesn't commit any keys, passwords, tokens, usernames, or other secrets.

Summary by CodeRabbit

  • New Features

    • Added SSO session support, allowing authentication flows to reuse active sessions across steps and flows.
    • Added session cookies with configurable idle and absolute expiration times.
    • Added checkpoint-based session save and restore behavior.
    • Added support for OAuth max_age and authentication assurance checks, including step-up authentication when requirements are unmet.
    • Added a “Basic with SSO” authentication flow template.
  • UI Improvements

    • Flow execution nodes now support custom descriptions and outcome labels in the console.

@coderabbitai

coderabbitai Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Adds persistent SSO sessions with checkpoint save/load behavior, per-flow cookie transport, assurance validation for acr_values and max_age, server configuration and database storage, SSO flow definitions, and console display metadata.

Changes

SSO session backend

Layer / File(s) Summary
Session storage and configuration
backend/internal/flow/session/*, backend/dbscripts/operationdb/*
Adds session, checkpoint-context, and participant persistence with timeout configuration, expiry handling, optimistic updates, and database schemas.
SSO executors and assurance
backend/internal/flow/executor/*, backend/internal/flow/common/*
Adds SSO-check and session executors, checkpoint runtime state, session snapshotting, rehydration, and assurance checks for requested authentication class and max_age.
Flow transport and startup wiring
backend/internal/flow/flowexec/*, backend/cmd/server/servicemanager.go
Propagates inbound and outbound SSO handles through flow execution, writes per-flow cookies, initializes session configuration, and injects the session service.
OAuth and flow definitions
backend/internal/oauth/*, backend/internal/flow/graphbuilder/*, frontend/apps/console/src/features/flows/data/*
Carries OAuth max_age into runtime data and adds SSO authentication flow definitions and graph-build coverage.
Console executor metadata
frontend/apps/console/src/features/flows/components/resources/steps/execution/*, frontend/apps/console/src/features/login-flow/data/executors.json
Renders executor descriptions and custom outcome labels and defines SSO/session executor display metadata.

Estimated code review effort: 5 (Critical) | ~120 minutes

Possibly related PRs

Suggested reviewers: ThaminduDilshan, rajithacharith, thiva-k, darshanasbg, brionmario

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 70.49% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title is concise and accurately summarizes the main change: adding flow-centric browser SSO.
Description check ✅ Passed The description covers Purpose, Approach, related links, checklist, and security checks, so it largely matches the template.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@madurangasiriwardena madurangasiriwardena changed the title [WIP] Add flow-centric browser SSO Add flow-centric browser SSO Jul 6, 2026

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 6

🧹 Nitpick comments (8)
frontend/apps/console/src/features/flows/components/resources/steps/execution/Execution.tsx (1)

52-60: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add direct test coverage for the new display.description/display.outcomes mapping in Execution.tsx.

The downstream consumers (ExecutionMinimal, ExecutionFactory) are tested, but the mapping itself in Execution.tsx (i.e., data.displayresource.display) has no direct test, so a typo or dropped field here wouldn't be caught.

As per path instructions, **/*.{go,md,mdx,tsx,ts,js,jsx,yaml,yml}: "Write tests for new features and bug fixes, targeting 80%+ coverage."

Also applies to: 78-80

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@frontend/apps/console/src/features/flows/components/resources/steps/execution/Execution.tsx`
around lines 52 - 60, Add direct test coverage for the `Execution.tsx` mapping
from `data.display` to `resource.display`, specifically the new
`display.description` and `display.outcomes` fields. Update or add tests around
the `displayFromData` handling in `Execution` so they assert the mapped
`resource.display` includes these properties before it reaches
`ExecutionMinimal`/`ExecutionFactory`, catching typos or dropped fields in this
component itself.

Source: Path instructions

backend/cmd/server/bootstrap/flows/authentication/auth_flow_sso.json (1)

1-127: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

🔴 Documentation Required
This PR introduces user-facing changes that are not covered by documentation updates under docs/.
Please update the relevant documentation before merging.

Missing documentation:

  • SSO authentication flow: new default-sso-flow bootstrap flow with SSOCheckExecutor/SessionExecutor join-point nodes — document in docs/content/guides/.
  • Session configuration: new session.idle_timeout_seconds / session.absolute_timeout_seconds deployment settings — document in docs/content/ config reference.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/cmd/server/bootstrap/flows/authentication/auth_flow_sso.json` around
lines 1 - 127, The new default-sso-flow bootstrap flow and session timeout
settings are user-facing and need corresponding docs updates. Add a guide under
docs/content/guides/ that explains the default-sso-flow behavior, including the
SSOCheckExecutor and SessionExecutor join points, and update the config
reference under docs/content/ to document session.idle_timeout_seconds and
session.absolute_timeout_seconds. Use the flow handle default-sso-flow and the
session settings names to locate the relevant documentation sections.

Source: Path instructions

frontend/apps/console/src/features/flows/utils/flowToCanvasTransformer.ts (1)

292-304: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Apply the same conditional-spread fix to CALL nodes.

The CALL node branch still unconditionally sets onFailure: apiNode.onFailure, which can be undefined, unlike the TASK_EXECUTION branch just above that now conditionally spreads it. If downstream rendering keys off presence of onFailure, CALL nodes without a failure branch may still show a dangling handle.

♻️ Suggested fix
   if (stepType === StepTypes.Call) {
     canvasNode.data = {
       flow: apiNode.flow ?? {ref: ''},
       action: {
         type: 'CALL',
         flow: apiNode.flow ?? {ref: ''},
         onSuccess: apiNode.onSuccess,
-        onFailure: apiNode.onFailure,
+        ...(apiNode.onFailure !== undefined ? {onFailure: apiNode.onFailure} : {}),
       },
     };
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/apps/console/src/features/flows/utils/flowToCanvasTransformer.ts`
around lines 292 - 304, The CALL node handling in flowToCanvasTransformer still
assigns onFailure unconditionally, so it can appear present even when missing.
Update the StepTypes.Call branch in flowToCanvasTransformer to match the
TASK_EXECUTION conditional-spread pattern: build the action object for CALL with
onSuccess always set, and only include onFailure when apiNode.onFailure is
defined. This should be done in the canvasNode.data assignment where
apiNode.flow, onSuccess, and onFailure are mapped.
backend/internal/flow/executor/error_constants.go (1)

1178-1197: 🗄️ Data Integrity & Integration | 🔵 Trivial

TODO left for wiring interaction_required to an OAuth2 redirect.

The error itself maps to a real OIDC error code — this specification also defines the following error codes... The Authorization Server requires End-User interaction of some form to proceed. This error MAY be returned when the prompt parameter value in the Authentication Request is none, but the Authentication Request cannot be completed without displaying a user interface for End-User interaction. The constant is defined but the actual redirect wiring is left as a TODO. Confirm this is tracked before this error path ships to users, otherwise ErrInteractionRequired will just surface as an opaque flow error rather than driving the expected OAuth2 authorize-error redirect.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/internal/flow/executor/error_constants.go` around lines 1178 - 1197,
The ErrInteractionRequired constant in error_constants.go is defined, but the
TODO for wiring it into an OAuth2 authorize-error redirect is still unresolved.
Make sure the interaction_required error path is tracked and implemented in the
flow executor so it triggers the expected redirect instead of surfacing as a
generic flow error; use ErrInteractionRequired and its existing error mapping as
the integration point.
backend/internal/flow/session/model.go (1)

63-67: 🔒 Security & Privacy | 🔵 Trivial

Handle rotation TODO — track before GA.

Until handle rotation lands, a leaked HandleID remains valid for the full session lifetime (idle/absolute deadlines only). Worth prioritizing before this ships broadly, or ensure it's tracked in SSO_TODO.md.

Want me to open a follow-up issue for handle rotation, or draft an implementation?

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/internal/flow/session/model.go` around lines 63 - 67, The session
handle rotation TODO in the HandleID field of session model.go needs to be
tracked before GA, since a leaked handle remains valid for the full session
lifetime. Add or update a tracked item in SSO_TODO.md for the handle rotation
work, or otherwise create a follow-up issue tied to the session model/session
cookie flow so it is explicitly tracked. Use the HandleID field comment and the
session handle rotation TODO as the anchor points when locating the code.
backend/internal/flow/executor/session_executor_test.go (1)

362-375: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Test doesn't assert the session row is actually established when context write fails.

The comment states "the session may be established, but no handle is emitted," but the test never asserts store.created is non-nil to confirm the session row was in fact persisted before the context failure. Worth adding that assertion to lock in the documented behavior.

TestSession_FreshSave_SessionContextErrorIsNonFatal verifies that a checkpoint-context write failure degrades SSO without failing auth: the session may be established, but no handle is emitted and the checkpoint is not recorded, so the session simply holds no reusable checkpoint.

✅ Suggested assertion addition
 	resp, err := exec.Execute(freshCtx())

 	require.NoError(t, err)
 	assert.Equal(t, providers.ExecComplete, resp.Status)
+	assert.NotNil(t, store.created, "the session row must still be established")
 	// The cookie is emitted only after the checkpoint context commits, so a context failure emits none.
 	assert.Empty(t, resp.AdditionalData[session.SessionHandleKey])
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/internal/flow/executor/session_executor_test.go` around lines 362 -
375, The test for session context write failure is missing an assertion that the
session row was still created before the checkpoint context failed. Update
TestSession_FreshSave_SessionContextErrorIsNonFatal to also verify store.created
is non-nil, alongside the existing checks on authCtx.created,
resp.AdditionalData, and resp.RuntimeData, so the behavior of session
establishment without emitted handle is locked in.
backend/internal/flow/session/state.go (1)

50-61: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value

Consider validating Idle <= Absolute.

NewTimeouts independently substitutes defaults for non-positive inputs but never checks that the resolved Idle doesn't exceed Absolute. If a caller supplies idleSeconds larger than absoluteSeconds (e.g., via misconfiguration), the idle deadline could sit beyond the absolute deadline, making the absolute cap the only effective one silently. Given SessionConfig validation lives in a different layer not included here, this may already be handled upstream.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/internal/flow/session/state.go` around lines 50 - 61, In NewTimeouts,
add a validation step after resolving the defaults and overrides to ensure the
final Idle timeout never exceeds the final Absolute timeout. Use the existing
DefaultTimeouts logic in session/state.go and adjust the returned Timeouts or
reject the invalid combination consistently with SessionConfig validation, so
misconfigured idleSeconds and absoluteSeconds cannot produce an invalid session
timeout pair.
backend/cmd/server/servicemanager.go (1)

355-361: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Reuse the already-captured flowConfig instead of re-resolving runtime config three times.

flowConfig := flowconfig.FromServerRuntime() is already captured above (line 327). Calling flowconfig.FromServerRuntime() again for DeploymentID on each store constructor is redundant.

♻️ Suggested cleanup
-			SessionStore: flowsession.NewStore(
-				dbprovider.GetDBProvider(), flowconfig.FromServerRuntime().DeploymentID),
-			SessionContextStore: flowsession.NewSessionContextStore(
-				dbprovider.GetDBProvider(), flowconfig.FromServerRuntime().DeploymentID,
-				flowsession.NewPassthroughEncryptor()),
-			SessionParticipantStore: flowsession.NewParticipantStore(
-				dbprovider.GetDBProvider(), flowconfig.FromServerRuntime().DeploymentID),
+			SessionStore: flowsession.NewStore(
+				dbprovider.GetDBProvider(), flowConfig.DeploymentID),
+			SessionContextStore: flowsession.NewSessionContextStore(
+				dbprovider.GetDBProvider(), flowConfig.DeploymentID,
+				flowsession.NewPassthroughEncryptor()),
+			SessionParticipantStore: flowsession.NewParticipantStore(
+				dbprovider.GetDBProvider(), flowConfig.DeploymentID),
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/cmd/server/servicemanager.go` around lines 355 - 361, Reuse the
existing flowConfig captured in servicemanager.go instead of calling
flowconfig.FromServerRuntime() again when constructing SessionStore,
SessionContextStore, and SessionParticipantStore. Update those constructors to
read DeploymentID from flowConfig so the already-resolved runtime config is used
consistently and the repeated lookups are removed.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@backend/internal/flow/flowexec/handler.go`:
- Around line 36-44: The SSO cookie in newFlowExecutionHandler is still created
with Secure hardcoded to false, so update the ssoCarrier initialization to read
the Secure setting from the server’s deployment/TLS config instead of using a
constant. Use the existing flowExecService-backed handler path and
session.NewCookieCarrier in handler.go, and wire it to the same
runtime.Config.Server security configuration pattern used elsewhere so the
cookie respects whether the deployment is running behind TLS.
- Around line 86-95: The SSO handle cookie in handler.go is using the package
default timeout instead of the configured session absolute timeout. Update the
flow in flowexec handler to pass the server-configured
Session.AbsoluteTimeoutSeconds through to h.ssoCarrier.Write instead of
session.DefaultAbsoluteTimeout, so the cookie lifetime matches the runtime
configuration. Use the existing flowStep.SSOHandleOut/SSOFlowID branch and the
session timeout wiring from servicemanager.go to locate the right value.

In `@backend/internal/flow/session/errors.go`:
- Around line 28-30: The error message for ErrSessionContextTooLarge in
errors.go contains a duplicated word (“session session”), so update the error
string to use a single “session” while keeping the same sentinel name and
surrounding comment unchanged.

In `@backend/internal/flow/session/SSO_CONTEXT_CLASSIFICATION.md`:
- Line 50: The markdown heading in SSO_CONTEXT_CLASSIFICATION.md is failing Vale
because it is not in Title Case. Update the top-level heading text under the
flow-context section to use proper Title Case, keeping the same meaning while
matching the style rules for headings.

In `@backend/internal/flow/session/SSO_TODO.md`:
- Line 50: The markdown headings in SSO_TODO.md are failing Vale Title Case
checks; update the affected heading text to proper Title Case while preserving
meaning. Fix the headings identified by the Session lifecycle section and the
related Revocation + logout and Attribute-storage architecture headings,
ensuring the heading strings themselves conform to the Vale title-case style
without changing surrounding content.
- Line 229: The Vale failure is caused by the informal abbreviation “repo” in
this documentation note; replace it with “repository” in the SSO_TODO content.
Update the surrounding sentence to keep the meaning intact while using the full
word, and scan nearby prose in the same section for any similar informal
abbreviations.

---

Nitpick comments:
In `@backend/cmd/server/bootstrap/flows/authentication/auth_flow_sso.json`:
- Around line 1-127: The new default-sso-flow bootstrap flow and session timeout
settings are user-facing and need corresponding docs updates. Add a guide under
docs/content/guides/ that explains the default-sso-flow behavior, including the
SSOCheckExecutor and SessionExecutor join points, and update the config
reference under docs/content/ to document session.idle_timeout_seconds and
session.absolute_timeout_seconds. Use the flow handle default-sso-flow and the
session settings names to locate the relevant documentation sections.

In `@backend/cmd/server/servicemanager.go`:
- Around line 355-361: Reuse the existing flowConfig captured in
servicemanager.go instead of calling flowconfig.FromServerRuntime() again when
constructing SessionStore, SessionContextStore, and SessionParticipantStore.
Update those constructors to read DeploymentID from flowConfig so the
already-resolved runtime config is used consistently and the repeated lookups
are removed.

In `@backend/internal/flow/executor/error_constants.go`:
- Around line 1178-1197: The ErrInteractionRequired constant in
error_constants.go is defined, but the TODO for wiring it into an OAuth2
authorize-error redirect is still unresolved. Make sure the interaction_required
error path is tracked and implemented in the flow executor so it triggers the
expected redirect instead of surfacing as a generic flow error; use
ErrInteractionRequired and its existing error mapping as the integration point.

In `@backend/internal/flow/executor/session_executor_test.go`:
- Around line 362-375: The test for session context write failure is missing an
assertion that the session row was still created before the checkpoint context
failed. Update TestSession_FreshSave_SessionContextErrorIsNonFatal to also
verify store.created is non-nil, alongside the existing checks on
authCtx.created, resp.AdditionalData, and resp.RuntimeData, so the behavior of
session establishment without emitted handle is locked in.

In `@backend/internal/flow/session/model.go`:
- Around line 63-67: The session handle rotation TODO in the HandleID field of
session model.go needs to be tracked before GA, since a leaked handle remains
valid for the full session lifetime. Add or update a tracked item in SSO_TODO.md
for the handle rotation work, or otherwise create a follow-up issue tied to the
session model/session cookie flow so it is explicitly tracked. Use the HandleID
field comment and the session handle rotation TODO as the anchor points when
locating the code.

In `@backend/internal/flow/session/state.go`:
- Around line 50-61: In NewTimeouts, add a validation step after resolving the
defaults and overrides to ensure the final Idle timeout never exceeds the final
Absolute timeout. Use the existing DefaultTimeouts logic in session/state.go and
adjust the returned Timeouts or reject the invalid combination consistently with
SessionConfig validation, so misconfigured idleSeconds and absoluteSeconds
cannot produce an invalid session timeout pair.

In
`@frontend/apps/console/src/features/flows/components/resources/steps/execution/Execution.tsx`:
- Around line 52-60: Add direct test coverage for the `Execution.tsx` mapping
from `data.display` to `resource.display`, specifically the new
`display.description` and `display.outcomes` fields. Update or add tests around
the `displayFromData` handling in `Execution` so they assert the mapped
`resource.display` includes these properties before it reaches
`ExecutionMinimal`/`ExecutionFactory`, catching typos or dropped fields in this
component itself.

In `@frontend/apps/console/src/features/flows/utils/flowToCanvasTransformer.ts`:
- Around line 292-304: The CALL node handling in flowToCanvasTransformer still
assigns onFailure unconditionally, so it can appear present even when missing.
Update the StepTypes.Call branch in flowToCanvasTransformer to match the
TASK_EXECUTION conditional-spread pattern: build the action object for CALL with
onSuccess always set, and only include onFailure when apiNode.onFailure is
defined. This should be done in the canvasNode.data assignment where
apiNode.flow, onSuccess, and onFailure are mapped.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 97240157-de4d-4b6e-9ed1-5e1547b9998e

📥 Commits

Reviewing files that changed from the base of the PR and between 59d399b and 82e62e1.

⛔ Files ignored due to path filters (1)
  • backend/tests/mocks/flow/flowexecmock/flowVersionLookup_mock.go is excluded by !**/*_mock.go
📒 Files selected for processing (58)
  • backend/cmd/server/bootstrap/flows/authentication/auth_flow_sso.json
  • backend/cmd/server/deployment.yaml
  • backend/cmd/server/servicemanager.go
  • backend/dbscripts/runtimedb/postgres.sql
  • backend/dbscripts/runtimedb/sqlite.sql
  • backend/internal/flow/common/constants.go
  • backend/internal/flow/executor/auth_assert_assurance_test.go
  • backend/internal/flow/executor/auth_assert_executor.go
  • backend/internal/flow/executor/constants.go
  • backend/internal/flow/executor/error_constants.go
  • backend/internal/flow/executor/register.go
  • backend/internal/flow/executor/session_executor.go
  • backend/internal/flow/executor/session_executor_test.go
  • backend/internal/flow/executor/sso_check_executor.go
  • backend/internal/flow/executor/sso_check_executor_test.go
  • backend/internal/flow/flowexec/engine.go
  • backend/internal/flow/flowexec/flowVersionLookup_mock_test.go
  • backend/internal/flow/flowexec/handler.go
  • backend/internal/flow/flowexec/model.go
  • backend/internal/flow/flowexec/service.go
  • backend/internal/flow/flowexec/service_sso_test.go
  • backend/internal/flow/mgt/graph_builder_sso_test.go
  • backend/internal/flow/session/SSO_CONTEXT_CLASSIFICATION.md
  • backend/internal/flow/session/SSO_TODO.md
  • backend/internal/flow/session/crypto.go
  • backend/internal/flow/session/errors.go
  • backend/internal/flow/session/inputs.go
  • backend/internal/flow/session/model.go
  • backend/internal/flow/session/participant.go
  • backend/internal/flow/session/participant_store.go
  • backend/internal/flow/session/participant_store_test.go
  • backend/internal/flow/session/queries.go
  • backend/internal/flow/session/resolver.go
  • backend/internal/flow/session/resolver_test.go
  • backend/internal/flow/session/session_context.go
  • backend/internal/flow/session/session_context_store.go
  • backend/internal/flow/session/session_context_store_test.go
  • backend/internal/flow/session/state.go
  • backend/internal/flow/session/state_test.go
  • backend/internal/flow/session/store.go
  • backend/internal/flow/session/store_test.go
  • backend/internal/flow/session/transient_test.go
  • backend/internal/flow/session/transport.go
  • backend/internal/flow/session/transport_test.go
  • backend/internal/oauth/oauth2/authz/service.go
  • backend/internal/oauth/oauth2/constants/constants.go
  • backend/internal/oauth/oauth2/model/parameter.go
  • backend/internal/system/config/config.go
  • backend/internal/system/config/config_test.go
  • backend/internal/system/i18n/core/defaults.go
  • frontend/apps/console/src/features/flows/components/resources/steps/execution/Execution.tsx
  • frontend/apps/console/src/features/flows/components/resources/steps/execution/ExecutionMinimal.tsx
  • frontend/apps/console/src/features/flows/components/resources/steps/execution/__tests__/ExecutionMinimal.test.tsx
  • frontend/apps/console/src/features/flows/components/resources/steps/execution/execution-factory/ExecutionFactory.tsx
  • frontend/apps/console/src/features/flows/components/resources/steps/execution/execution-factory/__tests__/ExecutionFactory.test.tsx
  • frontend/apps/console/src/features/flows/models/base.ts
  • frontend/apps/console/src/features/flows/utils/flowToCanvasTransformer.ts
  • frontend/apps/console/src/features/login-flow/data/executors.json

Comment thread backend/internal/flow/flowexec/handler.go Outdated
Comment thread backend/internal/flow/flowexec/handler.go
Comment thread backend/internal/flow/session/errors.go Outdated

---

## 1. Top-level flow-context fields

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.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Fix Vale Title Case CI failure on heading.

The Vale style check pipeline fails on this heading for not using Title Case.

✏️ Proposed fix
-## 1. Top-level flow-context fields
+## 1. Top-Level Flow-Context Fields
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
## 1. Top-level flow-context fields
## 1. Top-Level Flow-Context Fields
🧰 Tools
🪛 GitHub Actions: 🥒 Vale Lint (Changed Markdown Only) / 0_Vale style check.txt

[error] 50-50: WSO2-IAM.TitleCaseTitles: Use Title Case for headings.

🪛 GitHub Actions: 🥒 Vale Lint (Changed Markdown Only) / Vale style check

[error] 50-50: Vale rule [WSO2-IAM.TitleCaseTitles]: Use Title Case for headings.

🪛 GitHub Check: Vale style check

[failure] 50-50:
[vale] reported by reviewdog 🐶
[WSO2-IAM.TitleCaseTitles] Use Title Case for headings.

Raw Output:
{"message": "[WSO2-IAM.TitleCaseTitles] Use Title Case for headings.", "location": {"path": "backend/internal/flow/session/SSO_CONTEXT_CLASSIFICATION.md", "range": {"start": {"line": 50, "column": 4}}}, "severity": "ERROR"}

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/internal/flow/session/SSO_CONTEXT_CLASSIFICATION.md` at line 50, The
markdown heading in SSO_CONTEXT_CLASSIFICATION.md is failing Vale because it is
not in Title Case. Update the top-level heading text under the flow-context
section to use proper Title Case, keeping the same meaning while matching the
style rules for headings.

Source: Pipeline failures

the `__Host-` prefix as a separate managed flag rather than folding it into this free-form value.
— `transport.go` (`cookieNamePrefix` const, `CookieName`).

## Session lifecycle

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.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Fix Vale Title Case CI failures on headings.

The Vale style check pipeline reports Title Case violations on these headings ("## Session lifecycle", "### 6. Revocation + logout", "### 7b. Attribute-storage architecture (implemented) — reference by default, persist only what can't be re-resolved").

✏️ Proposed fixes
-## Session lifecycle
+## Session Lifecycle
-### 6. Revocation + logout
+### 6. Revocation + Logout
-### 7b. Attribute-storage architecture (implemented) — reference by default, persist only what can't be re-resolved
+### 7b. Attribute-Storage Architecture (Implemented) — Reference by Default, Persist Only What Can't Be Re-Resolved

Also applies to: 67-67, 124-124

🧰 Tools
🪛 GitHub Actions: 🥒 Vale Lint (Changed Markdown Only) / 0_Vale style check.txt

[error] 50-50: WSO2-IAM.TitleCaseTitles: Use Title Case for headings.

🪛 GitHub Actions: 🥒 Vale Lint (Changed Markdown Only) / Vale style check

[error] 50-50: Vale rule [WSO2-IAM.TitleCaseTitles]: Use Title Case for headings.

🪛 GitHub Check: Vale style check

[failure] 50-50:
[vale] reported by reviewdog 🐶
[WSO2-IAM.TitleCaseTitles] Use Title Case for headings.

Raw Output:
{"message": "[WSO2-IAM.TitleCaseTitles] Use Title Case for headings.", "location": {"path": "backend/internal/flow/session/SSO_TODO.md", "range": {"start": {"line": 50, "column": 4}}}, "severity": "ERROR"}

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/internal/flow/session/SSO_TODO.md` at line 50, The markdown headings
in SSO_TODO.md are failing Vale Title Case checks; update the affected heading
text to proper Title Case while preserving meaning. Fix the headings identified
by the Session lifecycle section and the related Revocation + logout and
Attribute-storage architecture headings, ensuring the heading strings themselves
conform to the Vale title-case style without changing surrounding content.

Source: Pipeline failures

completed assertion. **Transport to design:** have the gate forward a flow error to
`/oauth2/auth/callback` (extend it to accept an error code instead of an assertion) → map to
`error=interaction_required`. Likely needs coordinated changes in the **gate SDK** (separate
repo) as well as the backend. — `error_constants.go`, `authz/service.go`, `authz/handler.go`.

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.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Fix Vale informal-abbreviation CI failure.

The Vale style check pipeline flags "repo" as an informal abbreviation; use "repository".

✏️ Proposed fix
-  `error=interaction_required`. Likely needs coordinated changes in the **gate SDK** (separate
-  repo) as well as the backend. — `error_constants.go`, `authz/service.go`, `authz/handler.go`.
+  `error=interaction_required`. Likely needs coordinated changes in the **gate SDK** (separate
+  repository) as well as the backend. — `error_constants.go`, `authz/service.go`, `authz/handler.go`.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
repo) as well as the backend. — `error_constants.go`, `authz/service.go`, `authz/handler.go`.
repository) as well as the backend. — `error_constants.go`, `authz/service.go`, `authz/handler.go`.
🧰 Tools
🪛 GitHub Actions: 🥒 Vale Lint (Changed Markdown Only) / 0_Vale style check.txt

[error] 229-229: WSO2-IAM.NoInformalAbbreviations: Use 'repository' instead of 'repo'. Avoid informal abbreviations in documentation.


[warning] 229-229: Vale.Spelling: Did you really mean 'repo'?

🪛 GitHub Actions: 🥒 Vale Lint (Changed Markdown Only) / Vale style check

[error] 229-229: Vale rule [WSO2-IAM.NoInformalAbbreviations]: Use 'repository' instead of 'repo'. Avoid informal abbreviations in documentation.


[warning] 229-229: Vale rule [Vale.Spelling]: Did you really mean "repo"?

🪛 GitHub Check: Vale style check

[failure] 229-229:
[vale] reported by reviewdog 🐶
[WSO2-IAM.NoInformalAbbreviations] Use 'repository' instead of 'repo'. Avoid informal abbreviations in documentation.

Raw Output:
{"message": "[WSO2-IAM.NoInformalAbbreviations] Use 'repository' instead of 'repo'. Avoid informal abbreviations in documentation.", "location": {"path": "backend/internal/flow/session/SSO_TODO.md", "range": {"start": {"line": 229, "column": 3}}}, "severity": "ERROR"}

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/internal/flow/session/SSO_TODO.md` at line 229, The Vale failure is
caused by the informal abbreviation “repo” in this documentation note; replace
it with “repository” in the SSO_TODO content. Update the surrounding sentence to
keep the meaning intact while using the full word, and scan nearby prose in the
same section for any similar informal abbreviations.

Source: Pipeline failures

@coderabbitai coderabbitai Bot left a comment

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.

🧹 Nitpick comments (1)
backend/internal/flow/flowexec/handler_test.go (1)

49-49: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add tests for the new SSO cookie transport behavior.

These updates only pass (false, 0) to the new constructor. Please add focused coverage that verifies inbound cookies are available on the service context and that SSOHandleOut writes the expected per-flow cookie with a non-zero TTL/security setting. As per coding guidelines, "**/*.{go,md,mdx,tsx,ts,js,jsx,yaml,yml}: Write tests for new features and bug fixes, targeting 80%+ coverage."

Also applies to: 107-107, 124-124, 144-144, 172-172

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/internal/flow/flowexec/handler_test.go` at line 49, Add focused tests
around newFlowExecutionHandler and the flow execution handler paths to cover the
SSO cookie transport behavior. Verify that inbound cookies are propagated onto
the service context in the relevant handler/request flow, and add a test for
SSOHandleOut that confirms it writes the per-flow cookie with a non-zero TTL and
secure/httpOnly-style settings as expected. Use the existing handler_test.go
cases that construct the handler with newFlowExecutionHandler(mockSvc, false, 0)
as the entry points for these assertions.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@backend/internal/flow/flowexec/handler_test.go`:
- Line 49: Add focused tests around newFlowExecutionHandler and the flow
execution handler paths to cover the SSO cookie transport behavior. Verify that
inbound cookies are propagated onto the service context in the relevant
handler/request flow, and add a test for SSOHandleOut that confirms it writes
the per-flow cookie with a non-zero TTL and secure/httpOnly-style settings as
expected. Use the existing handler_test.go cases that construct the handler with
newFlowExecutionHandler(mockSvc, false, 0) as the entry points for these
assertions.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 2849fe06-f5e1-469d-b7e6-84775f803b79

📥 Commits

Reviewing files that changed from the base of the PR and between 82e62e1 and 5e68f6a.

⛔ Files ignored due to path filters (1)
  • backend/tests/mocks/flow/flowexecmock/flowVersionLookup_mock.go is excluded by !**/*_mock.go
📒 Files selected for processing (58)
  • backend/cmd/server/bootstrap/flows/authentication/auth_flow_sso.json
  • backend/cmd/server/deployment.yaml
  • backend/cmd/server/servicemanager.go
  • backend/dbscripts/runtimedb/postgres.sql
  • backend/dbscripts/runtimedb/sqlite.sql
  • backend/internal/flow/common/constants.go
  • backend/internal/flow/executor/auth_assert_assurance_test.go
  • backend/internal/flow/executor/auth_assert_executor.go
  • backend/internal/flow/executor/constants.go
  • backend/internal/flow/executor/error_constants.go
  • backend/internal/flow/executor/register.go
  • backend/internal/flow/executor/session_executor.go
  • backend/internal/flow/executor/session_executor_test.go
  • backend/internal/flow/executor/sso_check_executor.go
  • backend/internal/flow/executor/sso_check_executor_test.go
  • backend/internal/flow/flowexec/engine.go
  • backend/internal/flow/flowexec/flowVersionLookup_mock_test.go
  • backend/internal/flow/flowexec/handler.go
  • backend/internal/flow/flowexec/handler_test.go
  • backend/internal/flow/flowexec/init.go
  • backend/internal/flow/flowexec/model.go
  • backend/internal/flow/flowexec/service.go
  • backend/internal/flow/flowexec/service_sso_test.go
  • backend/internal/flow/mgt/graph_builder_sso_test.go
  • backend/internal/flow/session/crypto.go
  • backend/internal/flow/session/errors.go
  • backend/internal/flow/session/inputs.go
  • backend/internal/flow/session/model.go
  • backend/internal/flow/session/participant.go
  • backend/internal/flow/session/participant_store.go
  • backend/internal/flow/session/participant_store_test.go
  • backend/internal/flow/session/queries.go
  • backend/internal/flow/session/resolver.go
  • backend/internal/flow/session/resolver_test.go
  • backend/internal/flow/session/session_context.go
  • backend/internal/flow/session/session_context_store.go
  • backend/internal/flow/session/session_context_store_test.go
  • backend/internal/flow/session/state.go
  • backend/internal/flow/session/state_test.go
  • backend/internal/flow/session/store.go
  • backend/internal/flow/session/store_test.go
  • backend/internal/flow/session/transient_test.go
  • backend/internal/flow/session/transport.go
  • backend/internal/flow/session/transport_test.go
  • backend/internal/oauth/oauth2/authz/service.go
  • backend/internal/oauth/oauth2/constants/constants.go
  • backend/internal/oauth/oauth2/model/parameter.go
  • backend/internal/system/config/config.go
  • backend/internal/system/config/config_test.go
  • backend/internal/system/i18n/core/defaults.go
  • frontend/apps/console/src/features/flows/components/resources/steps/execution/Execution.tsx
  • frontend/apps/console/src/features/flows/components/resources/steps/execution/ExecutionMinimal.tsx
  • frontend/apps/console/src/features/flows/components/resources/steps/execution/__tests__/ExecutionMinimal.test.tsx
  • frontend/apps/console/src/features/flows/components/resources/steps/execution/execution-factory/ExecutionFactory.tsx
  • frontend/apps/console/src/features/flows/components/resources/steps/execution/execution-factory/__tests__/ExecutionFactory.test.tsx
  • frontend/apps/console/src/features/flows/models/base.ts
  • frontend/apps/console/src/features/flows/utils/flowToCanvasTransformer.ts
  • frontend/apps/console/src/features/login-flow/data/executors.json
✅ Files skipped from review due to trivial changes (4)
  • backend/internal/flow/session/participant.go
  • backend/internal/system/i18n/core/defaults.go
  • backend/internal/flow/flowexec/flowVersionLookup_mock_test.go
  • backend/internal/oauth/oauth2/constants/constants.go
🚧 Files skipped from review as they are similar to previous changes (51)
  • backend/internal/oauth/oauth2/model/parameter.go
  • backend/internal/flow/session/errors.go
  • backend/cmd/server/deployment.yaml
  • frontend/apps/console/src/features/flows/components/resources/steps/execution/execution-factory/ExecutionFactory.tsx
  • backend/internal/flow/session/crypto.go
  • backend/internal/flow/session/model.go
  • frontend/apps/console/src/features/flows/components/resources/steps/execution/ExecutionMinimal.tsx
  • backend/internal/system/config/config.go
  • frontend/apps/console/src/features/flows/models/base.ts
  • backend/internal/flow/session/transient_test.go
  • backend/internal/flow/session/state_test.go
  • backend/internal/flow/flowexec/model.go
  • backend/cmd/server/bootstrap/flows/authentication/auth_flow_sso.json
  • backend/internal/system/config/config_test.go
  • backend/internal/flow/mgt/graph_builder_sso_test.go
  • frontend/apps/console/src/features/flows/components/resources/steps/execution/execution-factory/tests/ExecutionFactory.test.tsx
  • backend/internal/flow/session/inputs.go
  • backend/internal/flow/session/resolver.go
  • backend/internal/flow/common/constants.go
  • backend/internal/flow/session/transport_test.go
  • frontend/apps/console/src/features/flows/utils/flowToCanvasTransformer.ts
  • backend/internal/oauth/oauth2/authz/service.go
  • backend/internal/flow/session/state.go
  • frontend/apps/console/src/features/flows/components/resources/steps/execution/Execution.tsx
  • backend/internal/flow/flowexec/service.go
  • backend/dbscripts/runtimedb/postgres.sql
  • frontend/apps/console/src/features/flows/components/resources/steps/execution/tests/ExecutionMinimal.test.tsx
  • backend/internal/flow/session/participant_store_test.go
  • backend/internal/flow/executor/constants.go
  • backend/internal/flow/session/transport.go
  • frontend/apps/console/src/features/login-flow/data/executors.json
  • backend/internal/flow/flowexec/service_sso_test.go
  • backend/dbscripts/runtimedb/sqlite.sql
  • backend/internal/flow/executor/session_executor.go
  • backend/internal/flow/session/session_context_store.go
  • backend/internal/flow/session/queries.go
  • backend/internal/flow/executor/auth_assert_executor.go
  • backend/internal/flow/executor/auth_assert_assurance_test.go
  • backend/cmd/server/servicemanager.go
  • backend/internal/flow/session/store.go
  • backend/internal/flow/executor/register.go
  • backend/internal/flow/session/participant_store.go
  • backend/internal/flow/session/session_context.go
  • backend/internal/flow/executor/sso_check_executor_test.go
  • backend/internal/flow/session/resolver_test.go
  • backend/internal/flow/executor/error_constants.go
  • backend/internal/flow/executor/sso_check_executor.go
  • backend/internal/flow/flowexec/engine.go
  • backend/internal/flow/executor/session_executor_test.go
  • backend/internal/flow/session/store_test.go
  • backend/internal/flow/session/session_context_store_test.go

@madurangasiriwardena
madurangasiriwardena force-pushed the feature/session-poc-2-rebased branch 3 times, most recently from 09d3eff to 7efc897 Compare July 7, 2026 05:17

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 2

🧹 Nitpick comments (2)
backend/internal/flow/executor/session_executor_test.go (2)

167-171: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Swallowed error in test helper.

authenticatedAuthUser() discards the UnmarshalJSON error. If the hardcoded JSON literal ever breaks, tests silently get a zero-value AuthUser instead of a clear failure at the source.

♻️ Proposed fix
-func authenticatedAuthUser() providers.AuthUser {
+func authenticatedAuthUser(t *testing.T) providers.AuthUser {
+	t.Helper()
 	var authUser providers.AuthUser
-	_ = authUser.UnmarshalJSON([]byte(`{"entityReferenceToken":"tok","attributeToken":"tok"}`))
+	require.NoError(t, authUser.UnmarshalJSON([]byte(`{"entityReferenceToken":"tok","attributeToken":"tok"}`)))
 	return authUser
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/internal/flow/executor/session_executor_test.go` around lines 167 -
171, The test helper authenticatedAuthUser() is swallowing the UnmarshalJSON
error and can return a zero-value AuthUser silently. Update
authenticatedAuthUser() to handle the error explicitly in the helper itself, so
any malformed hardcoded JSON causes a clear test failure instead of being
ignored.

199-207: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Test setup silently ignores errors and hardcodes a shared /tmp path.

config.InitializeServerRuntime and core.Initialize errors are discarded, and all tests share the hardcoded path /tmp/test-session-exec. A setup failure here would surface as a confusing nil-pointer panic deep in newSessionExecutor rather than a clear setup error, and the shared path risks collisions/permission issues across test runs.

♻️ Proposed fix
-	_ = config.InitializeServerRuntime("/tmp/test-session-exec", &config.Config{})
-	flowFactory, _ := core.Initialize(cache.Initialize(config.GetServerRuntime().Config.Cache, "test-deployment"))
+	require.NoError(t, config.InitializeServerRuntime(t.TempDir(), &config.Config{}))
+	flowFactory, err := core.Initialize(cache.Initialize(config.GetServerRuntime().Config.Cache, "test-deployment"))
+	require.NoError(t, err)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/internal/flow/executor/session_executor_test.go` around lines 199 -
207, In newTestSessionExecutorWithTx, stop discarding the errors from
config.InitializeServerRuntime and core.Initialize, and fail the test
immediately if either setup step returns an error. Also replace the hardcoded
shared /tmp/test-session-exec path with a unique per-test temp directory (for
example using the test’s temp helpers) so concurrent runs do not collide. Keep
the fix localized to newTestSessionExecutorWithTx and the initialization calls
it performs.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@backend/internal/flow/flowexec/service.go`:
- Around line 132-142: This change introduces user-facing SSO flow behavior,
session timeout configuration, and an SDK-visible cookie/handle contract, so add
or update the relevant docs before merging. Update the flow guide for the new
SSO checkpoint behavior around SSOCheckExecutor, SessionExecutor, and
checkpointRef, add config reference coverage for session.DefaultTimeouts and the
new idle/absolute session deadlines, and document the AdditionalData-based SSO
handle and per-flow cookie transport contract for SDK consumers.
- Around line 139-141: The SSO path in Execute currently calls
resolveActiveFlowVersion on every step, which repeatedly hits
flowProvider.GetFlow and the underlying store. Update the flow execution path in
service.go so the active flow version is resolved once per flow execution and
then reused across subsequent steps, using the existing Execute and
resolveActiveFlowVersion flow/engineCtx handling to cache the result on
engineCtx.SSOFlowVersion instead of recomputing it each time.

---

Nitpick comments:
In `@backend/internal/flow/executor/session_executor_test.go`:
- Around line 167-171: The test helper authenticatedAuthUser() is swallowing the
UnmarshalJSON error and can return a zero-value AuthUser silently. Update
authenticatedAuthUser() to handle the error explicitly in the helper itself, so
any malformed hardcoded JSON causes a clear test failure instead of being
ignored.
- Around line 199-207: In newTestSessionExecutorWithTx, stop discarding the
errors from config.InitializeServerRuntime and core.Initialize, and fail the
test immediately if either setup step returns an error. Also replace the
hardcoded shared /tmp/test-session-exec path with a unique per-test temp
directory (for example using the test’s temp helpers) so concurrent runs do not
collide. Keep the fix localized to newTestSessionExecutorWithTx and the
initialization calls it performs.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 4c8a91f2-2aab-455c-b905-c5a8f7f78d74

📥 Commits

Reviewing files that changed from the base of the PR and between 4a9b345 and 7efc897.

⛔ Files ignored due to path filters (1)
  • backend/tests/mocks/flow/flowexecmock/flowVersionLookup_mock.go is excluded by !**/*_mock.go
📒 Files selected for processing (59)
  • backend/cmd/server/bootstrap/flows/authentication/auth_flow_sso.json
  • backend/cmd/server/deployment.yaml
  • backend/cmd/server/servicemanager.go
  • backend/dbscripts/runtimedb/postgres.sql
  • backend/dbscripts/runtimedb/sqlite.sql
  • backend/internal/flow/common/constants.go
  • backend/internal/flow/executor/auth_assert_assurance_test.go
  • backend/internal/flow/executor/auth_assert_executor.go
  • backend/internal/flow/executor/constants.go
  • backend/internal/flow/executor/error_constants.go
  • backend/internal/flow/executor/register.go
  • backend/internal/flow/executor/session_executor.go
  • backend/internal/flow/executor/session_executor_test.go
  • backend/internal/flow/executor/sso_check_executor.go
  • backend/internal/flow/executor/sso_check_executor_test.go
  • backend/internal/flow/flowexec/engine.go
  • backend/internal/flow/flowexec/flowVersionLookup_mock_test.go
  • backend/internal/flow/flowexec/handler.go
  • backend/internal/flow/flowexec/handler_test.go
  • backend/internal/flow/flowexec/init.go
  • backend/internal/flow/flowexec/model.go
  • backend/internal/flow/flowexec/service.go
  • backend/internal/flow/flowexec/service_sso_test.go
  • backend/internal/flow/mgt/graph_builder_sso_test.go
  • backend/internal/flow/session/crypto.go
  • backend/internal/flow/session/errors.go
  • backend/internal/flow/session/inputs.go
  • backend/internal/flow/session/model.go
  • backend/internal/flow/session/participant.go
  • backend/internal/flow/session/participant_store.go
  • backend/internal/flow/session/participant_store_test.go
  • backend/internal/flow/session/queries.go
  • backend/internal/flow/session/resolver.go
  • backend/internal/flow/session/resolver_test.go
  • backend/internal/flow/session/session_context.go
  • backend/internal/flow/session/session_context_store.go
  • backend/internal/flow/session/session_context_store_test.go
  • backend/internal/flow/session/state.go
  • backend/internal/flow/session/state_test.go
  • backend/internal/flow/session/store.go
  • backend/internal/flow/session/store_test.go
  • backend/internal/flow/session/transient_test.go
  • backend/internal/flow/session/transport.go
  • backend/internal/flow/session/transport_test.go
  • backend/internal/oauth/oauth2/authz/service.go
  • backend/internal/oauth/oauth2/constants/constants.go
  • backend/internal/oauth/oauth2/model/parameter.go
  • backend/internal/system/config/config.go
  • backend/internal/system/config/config_test.go
  • backend/internal/system/i18n/core/defaults.go
  • frontend/apps/console/src/features/flows/components/resources/steps/execution/Execution.tsx
  • frontend/apps/console/src/features/flows/components/resources/steps/execution/ExecutionMinimal.tsx
  • frontend/apps/console/src/features/flows/components/resources/steps/execution/__tests__/Execution.test.tsx
  • frontend/apps/console/src/features/flows/components/resources/steps/execution/__tests__/ExecutionMinimal.test.tsx
  • frontend/apps/console/src/features/flows/components/resources/steps/execution/execution-factory/ExecutionFactory.tsx
  • frontend/apps/console/src/features/flows/components/resources/steps/execution/execution-factory/__tests__/ExecutionFactory.test.tsx
  • frontend/apps/console/src/features/flows/models/base.ts
  • frontend/apps/console/src/features/flows/utils/flowToCanvasTransformer.ts
  • frontend/apps/console/src/features/login-flow/data/executors.json
✅ Files skipped from review due to trivial changes (4)
  • backend/internal/flow/executor/constants.go
  • backend/internal/system/i18n/core/defaults.go
  • backend/internal/flow/flowexec/flowVersionLookup_mock_test.go
  • backend/internal/oauth/oauth2/constants/constants.go
🚧 Files skipped from review as they are similar to previous changes (50)
  • backend/internal/flow/session/errors.go
  • backend/internal/flow/session/participant.go
  • backend/cmd/server/deployment.yaml
  • frontend/apps/console/src/features/flows/utils/flowToCanvasTransformer.ts
  • frontend/apps/console/src/features/flows/components/resources/steps/execution/execution-factory/tests/ExecutionFactory.test.tsx
  • backend/internal/flow/session/crypto.go
  • frontend/apps/console/src/features/flows/models/base.ts
  • backend/internal/flow/session/inputs.go
  • backend/internal/oauth/oauth2/model/parameter.go
  • backend/internal/flow/mgt/graph_builder_sso_test.go
  • backend/internal/flow/session/transient_test.go
  • backend/internal/flow/flowexec/init.go
  • backend/internal/flow/session/state.go
  • backend/internal/flow/session/model.go
  • backend/internal/flow/session/state_test.go
  • backend/internal/flow/session/session_context.go
  • backend/internal/flow/executor/sso_check_executor.go
  • backend/cmd/server/bootstrap/flows/authentication/auth_flow_sso.json
  • backend/internal/system/config/config.go
  • backend/internal/flow/session/session_context_store.go
  • backend/internal/flow/executor/sso_check_executor_test.go
  • backend/internal/flow/executor/auth_assert_assurance_test.go
  • backend/internal/system/config/config_test.go
  • frontend/apps/console/src/features/flows/components/resources/steps/execution/Execution.tsx
  • frontend/apps/console/src/features/flows/components/resources/steps/execution/execution-factory/ExecutionFactory.tsx
  • backend/internal/flow/flowexec/handler.go
  • backend/internal/flow/executor/auth_assert_executor.go
  • frontend/apps/console/src/features/flows/components/resources/steps/execution/ExecutionMinimal.tsx
  • backend/internal/oauth/oauth2/authz/service.go
  • frontend/apps/console/src/features/login-flow/data/executors.json
  • backend/internal/flow/flowexec/handler_test.go
  • backend/internal/flow/session/transport_test.go
  • backend/internal/flow/session/transport.go
  • backend/internal/flow/executor/error_constants.go
  • backend/dbscripts/runtimedb/postgres.sql
  • backend/internal/flow/session/participant_store.go
  • backend/cmd/server/servicemanager.go
  • backend/internal/flow/common/constants.go
  • backend/internal/flow/executor/session_executor.go
  • backend/dbscripts/runtimedb/sqlite.sql
  • backend/internal/flow/session/store.go
  • backend/internal/flow/flowexec/model.go
  • frontend/apps/console/src/features/flows/components/resources/steps/execution/tests/ExecutionMinimal.test.tsx
  • backend/internal/flow/session/resolver.go
  • backend/internal/flow/executor/register.go
  • backend/internal/flow/flowexec/service_sso_test.go
  • backend/internal/flow/session/resolver_test.go
  • backend/internal/flow/flowexec/engine.go
  • frontend/apps/console/src/features/flows/components/resources/steps/execution/tests/Execution.test.tsx
  • backend/internal/flow/session/queries.go

Comment on lines +132 to +142
// Resolve the inbound SSO handle for this flow from the request-scoped transport inputs.
applyInboundSSO(engineCtx, ctx)
// Resolve the active flow version whenever the flow establishes or consults an SSO session.
// Both paths need it: the save path (fresh login, which carries no inbound handle) stamps the
// version onto the new session, and the check path compares against it. Gating this on an
// inbound handle would save sessions at version 0 and then fail the version check on the next
// login. Flows that use no SSO session skip the lookup.
if flowUsesSSOSession(engineCtx.Graph) {
engineCtx.SSOFlowVersion = s.resolveActiveFlowVersion(ctx, engineCtx, logger)
}

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.

📐 Maintainability & Code Quality | 🟠 Major

🔴 Documentation Required
This PR introduces user-facing changes that are not covered by documentation updates under docs/.
Please update the relevant documentation before merging.

Missing documentation:

  • Flow-centric browser SSO behavior: new SSOCheckExecutor/SessionExecutor flow nodes and checkpointRef binding change how authentication flows behave for end users; document in docs/content/guides/ (how to configure SSO checkpoints in a flow graph).
  • Session lifetime configuration: new configurable idle/absolute session deadlines (session.DefaultTimeouts()) are a new configuration surface; document in docs/content/ (config reference).
  • SDK-impacting change: the minted SSO handle is now surfaced via AdditionalData and converted into a per-flow cookie by the transport layer; document this new cookie/handle contract in docs/content/sdks/.

If documentation is already covered elsewhere in this PR (outside this reviewed file set), please disregard.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/internal/flow/flowexec/service.go` around lines 132 - 142, This
change introduces user-facing SSO flow behavior, session timeout configuration,
and an SDK-visible cookie/handle contract, so add or update the relevant docs
before merging. Update the flow guide for the new SSO checkpoint behavior around
SSOCheckExecutor, SessionExecutor, and checkpointRef, add config reference
coverage for session.DefaultTimeouts and the new idle/absolute session
deadlines, and document the AdditionalData-based SSO handle and per-flow cookie
transport contract for SDK consumers.

Source: Path instructions

Comment thread backend/internal/flow/flowexec/service.go
@madurangasiriwardena
madurangasiriwardena force-pushed the feature/session-poc-2-rebased branch 3 times, most recently from b5e6e76 to 0cd4b3e Compare July 7, 2026 13:50

@coderabbitai coderabbitai Bot left a comment

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.

🧹 Nitpick comments (2)
backend/internal/flow/executor/session_executor_test.go (2)

204-229: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Duplicated context-builder logic between freshCtx and ssoLoadCtx.

Both helpers construct near-identical providers.NodeContext values. Consider extracting a shared base builder that each customizes, to reduce upkeep when NodeContext fields change.

Also applies to: 465-477

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/internal/flow/executor/session_executor_test.go` around lines 204 -
229, The test helpers `freshCtx` and `ssoLoadCtx` are duplicating the same
`providers.NodeContext` setup, which makes future `NodeContext` changes harder
to maintain. Extract the common construction into a shared helper or base
builder and let `freshCtx` and `ssoLoadCtx` only override the fields they differ
on. Keep the shared logic aligned with the existing `providers.NodeContext`
fields like `Context`, `ExecutionID`, `RuntimeData`, `AuthUser`,
`ExecutionHistory`, and `Application`.

194-202: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Discarded setup error could mask confusing failures.

core.Initialize error is ignored; a setup failure here would surface as a downstream assertion failure (e.g., nil flowFactory panic) instead of a clear test-setup error.

🔧 Proposed fix
 	require.NoError(t, config.InitializeServerRuntime(t.TempDir(), &config.Config{}))
-	flowFactory, _ := core.Initialize(cache.Initialize(config.GetServerRuntime().Config.Cache, "test-deployment"))
+	flowFactory, err := core.Initialize(cache.Initialize(config.GetServerRuntime().Config.Cache, "test-deployment"))
+	require.NoError(t, err)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/internal/flow/executor/session_executor_test.go` around lines 194 -
202, The test helper newTestSessionExecutorWithTx is ignoring the error returned
by core.Initialize, which can hide setup failures and cause confusing downstream
panics. Update the helper to capture and assert the initialization error before
calling newSessionExecutor, using the existing require helper so failures in
core.Initialize are reported as a clear test-setup error rather than a nil
flowFactory issue.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@backend/internal/flow/executor/session_executor_test.go`:
- Around line 204-229: The test helpers `freshCtx` and `ssoLoadCtx` are
duplicating the same `providers.NodeContext` setup, which makes future
`NodeContext` changes harder to maintain. Extract the common construction into a
shared helper or base builder and let `freshCtx` and `ssoLoadCtx` only override
the fields they differ on. Keep the shared logic aligned with the existing
`providers.NodeContext` fields like `Context`, `ExecutionID`, `RuntimeData`,
`AuthUser`, `ExecutionHistory`, and `Application`.
- Around line 194-202: The test helper newTestSessionExecutorWithTx is ignoring
the error returned by core.Initialize, which can hide setup failures and cause
confusing downstream panics. Update the helper to capture and assert the
initialization error before calling newSessionExecutor, using the existing
require helper so failures in core.Initialize are reported as a clear test-setup
error rather than a nil flowFactory issue.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: cf5591df-ff9d-4167-8849-f4d92f66449d

📥 Commits

Reviewing files that changed from the base of the PR and between 7efc897 and 0cd4b3e.

⛔ Files ignored due to path filters (1)
  • backend/tests/mocks/flow/flowexecmock/flowVersionLookup_mock.go is excluded by !**/*_mock.go
📒 Files selected for processing (59)
  • backend/cmd/server/bootstrap/flows/authentication/auth_flow_sso.json
  • backend/cmd/server/deployment.yaml
  • backend/cmd/server/servicemanager.go
  • backend/dbscripts/runtimedb/postgres.sql
  • backend/dbscripts/runtimedb/sqlite.sql
  • backend/internal/flow/common/constants.go
  • backend/internal/flow/executor/auth_assert_assurance_test.go
  • backend/internal/flow/executor/auth_assert_executor.go
  • backend/internal/flow/executor/constants.go
  • backend/internal/flow/executor/error_constants.go
  • backend/internal/flow/executor/register.go
  • backend/internal/flow/executor/session_executor.go
  • backend/internal/flow/executor/session_executor_test.go
  • backend/internal/flow/executor/sso_check_executor.go
  • backend/internal/flow/executor/sso_check_executor_test.go
  • backend/internal/flow/flowexec/engine.go
  • backend/internal/flow/flowexec/flowVersionLookup_mock_test.go
  • backend/internal/flow/flowexec/handler.go
  • backend/internal/flow/flowexec/handler_test.go
  • backend/internal/flow/flowexec/init.go
  • backend/internal/flow/flowexec/model.go
  • backend/internal/flow/flowexec/service.go
  • backend/internal/flow/flowexec/service_sso_test.go
  • backend/internal/flow/mgt/graph_builder_sso_test.go
  • backend/internal/flow/session/crypto.go
  • backend/internal/flow/session/errors.go
  • backend/internal/flow/session/inputs.go
  • backend/internal/flow/session/model.go
  • backend/internal/flow/session/participant.go
  • backend/internal/flow/session/participant_store.go
  • backend/internal/flow/session/participant_store_test.go
  • backend/internal/flow/session/queries.go
  • backend/internal/flow/session/resolver.go
  • backend/internal/flow/session/resolver_test.go
  • backend/internal/flow/session/session_context.go
  • backend/internal/flow/session/session_context_store.go
  • backend/internal/flow/session/session_context_store_test.go
  • backend/internal/flow/session/state.go
  • backend/internal/flow/session/state_test.go
  • backend/internal/flow/session/store.go
  • backend/internal/flow/session/store_test.go
  • backend/internal/flow/session/transient_test.go
  • backend/internal/flow/session/transport.go
  • backend/internal/flow/session/transport_test.go
  • backend/internal/oauth/oauth2/authz/service.go
  • backend/internal/oauth/oauth2/constants/constants.go
  • backend/internal/oauth/oauth2/model/parameter.go
  • backend/internal/system/config/config.go
  • backend/internal/system/config/config_test.go
  • backend/internal/system/i18n/core/defaults.go
  • frontend/apps/console/src/features/flows/components/resources/steps/execution/Execution.tsx
  • frontend/apps/console/src/features/flows/components/resources/steps/execution/ExecutionMinimal.tsx
  • frontend/apps/console/src/features/flows/components/resources/steps/execution/__tests__/Execution.test.tsx
  • frontend/apps/console/src/features/flows/components/resources/steps/execution/__tests__/ExecutionMinimal.test.tsx
  • frontend/apps/console/src/features/flows/components/resources/steps/execution/execution-factory/ExecutionFactory.tsx
  • frontend/apps/console/src/features/flows/components/resources/steps/execution/execution-factory/__tests__/ExecutionFactory.test.tsx
  • frontend/apps/console/src/features/flows/models/base.ts
  • frontend/apps/console/src/features/flows/utils/flowToCanvasTransformer.ts
  • frontend/apps/console/src/features/login-flow/data/executors.json
✅ Files skipped from review due to trivial changes (5)
  • backend/internal/oauth/oauth2/model/parameter.go
  • backend/internal/system/i18n/core/defaults.go
  • frontend/apps/console/src/features/flows/models/base.ts
  • backend/internal/flow/flowexec/flowVersionLookup_mock_test.go
  • backend/internal/oauth/oauth2/constants/constants.go
🚧 Files skipped from review as they are similar to previous changes (53)
  • backend/internal/flow/session/state_test.go
  • backend/internal/flow/session/crypto.go
  • backend/internal/flow/session/participant.go
  • backend/internal/flow/session/errors.go
  • backend/internal/flow/session/resolver.go
  • backend/internal/flow/mgt/graph_builder_sso_test.go
  • backend/cmd/server/deployment.yaml
  • backend/internal/flow/session/inputs.go
  • backend/cmd/server/bootstrap/flows/authentication/auth_flow_sso.json
  • frontend/apps/console/src/features/flows/utils/flowToCanvasTransformer.ts
  • backend/internal/flow/executor/constants.go
  • frontend/apps/console/src/features/flows/components/resources/steps/execution/execution-factory/ExecutionFactory.tsx
  • frontend/apps/console/src/features/flows/components/resources/steps/execution/Execution.tsx
  • backend/internal/flow/flowexec/init.go
  • backend/internal/flow/session/state.go
  • backend/internal/flow/session/transient_test.go
  • backend/internal/system/config/config_test.go
  • backend/internal/flow/session/model.go
  • backend/internal/oauth/oauth2/authz/service.go
  • frontend/apps/console/src/features/flows/components/resources/steps/execution/execution-factory/tests/ExecutionFactory.test.tsx
  • frontend/apps/console/src/features/flows/components/resources/steps/execution/tests/ExecutionMinimal.test.tsx
  • backend/internal/flow/executor/auth_assert_assurance_test.go
  • backend/internal/flow/session/transport_test.go
  • backend/internal/flow/flowexec/model.go
  • backend/internal/flow/flowexec/handler.go
  • backend/internal/flow/executor/error_constants.go
  • backend/internal/system/config/config.go
  • frontend/apps/console/src/features/flows/components/resources/steps/execution/ExecutionMinimal.tsx
  • backend/internal/flow/executor/register.go
  • backend/internal/flow/session/queries.go
  • backend/dbscripts/runtimedb/postgres.sql
  • backend/cmd/server/servicemanager.go
  • backend/internal/flow/executor/sso_check_executor.go
  • backend/dbscripts/runtimedb/sqlite.sql
  • frontend/apps/console/src/features/login-flow/data/executors.json
  • backend/internal/flow/flowexec/engine.go
  • backend/internal/flow/executor/session_executor.go
  • backend/internal/flow/session/store.go
  • backend/internal/flow/session/resolver_test.go
  • backend/internal/flow/session/transport.go
  • backend/internal/flow/executor/sso_check_executor_test.go
  • backend/internal/flow/flowexec/handler_test.go
  • backend/internal/flow/executor/auth_assert_executor.go
  • backend/internal/flow/session/participant_store_test.go
  • backend/internal/flow/session/session_context.go
  • backend/internal/flow/common/constants.go
  • backend/internal/flow/flowexec/service.go
  • backend/internal/flow/session/session_context_store_test.go
  • backend/internal/flow/session/store_test.go
  • backend/internal/flow/session/participant_store.go
  • frontend/apps/console/src/features/flows/components/resources/steps/execution/tests/Execution.test.tsx
  • backend/internal/flow/session/session_context_store.go
  • backend/internal/flow/flowexec/service_sso_test.go

@madurangasiriwardena
madurangasiriwardena force-pushed the feature/session-poc-2-rebased branch 3 times, most recently from 3fd8e96 to 7a4c892 Compare July 8, 2026 08:10
@madurangasiriwardena

Copy link
Copy Markdown
Member Author

@coderabbitai resume

@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Reviews resumed.

@madurangasiriwardena
madurangasiriwardena force-pushed the feature/session-poc-2-rebased branch from 7a4c892 to 5398bca Compare July 8, 2026 08:39

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 1

🧹 Nitpick comments (1)
backend/internal/flow/session/transport.go (1)

96-104: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Minimize captured cookie data in Read.

Read stores every inbound cookie (including unrelated app cookies) into InboundHandle.Cookies, even though only tid_sso_-prefixed cookies are ever consumed via HandleFor. Filtering here reduces the blast radius of the "must never be persisted" invariant documented on InboundHandle.

♻️ Proposed fix
 func (c *cookieTransport) Read(r *http.Request) InboundHandle {
 	cookies := make(map[string]string)
 	for _, ck := range r.Cookies() {
-		cookies[ck.Name] = ck.Value
+		if strings.HasPrefix(ck.Name, cookieNamePrefix) {
+			cookies[ck.Name] = ck.Value
+		}
 	}
 	return InboundHandle{
 		Cookies: cookies,
 	}
 }

(requires adding "strings" to imports)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/internal/flow/session/transport.go` around lines 96 - 104, The
cookieTransport.Read method is capturing all inbound cookies into
InboundHandle.Cookies, but only tid_sso_-prefixed cookies are used later by
HandleFor. Update Read to filter r.Cookies() so it only stores cookies whose
names match the tid_sso_ prefix, and add the needed strings import for the
prefix check. Keep the change localized to cookieTransport.Read and preserve the
existing InboundHandle shape.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@backend/internal/oauth/oauth2/constants/constants.go`:
- Line 65: The new OAuth2 RequestParamMaxAge constant makes max_age a
user-facing authorization request parameter, so update the docs to cover it in
the OAuth2/OIDC API reference and authentication guide. In
docs/content/apis.mdx, document max_age semantics and how it interacts with
verified_claims.verification.time.max_age; in the relevant docs/content/guides/
authentication-flow guide, describe browser SSO behavior across applications,
including checkpoint-based session reuse, per-flow SSO cookies, and
idle/absolute session timeout configuration. Use the existing auth flow and
OAuth2 terminology from oauth2const.RequestParamMaxAge and the session-timeout
behavior described by the PR so the new behavior is discoverable.

---

Nitpick comments:
In `@backend/internal/flow/session/transport.go`:
- Around line 96-104: The cookieTransport.Read method is capturing all inbound
cookies into InboundHandle.Cookies, but only tid_sso_-prefixed cookies are used
later by HandleFor. Update Read to filter r.Cookies() so it only stores cookies
whose names match the tid_sso_ prefix, and add the needed strings import for the
prefix check. Keep the change localized to cookieTransport.Read and preserve the
existing InboundHandle shape.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: f5b928ec-2098-465a-b4a7-db9272629b35

📥 Commits

Reviewing files that changed from the base of the PR and between 7efc897 and 7a4c892.

⛔ Files ignored due to path filters (1)
  • backend/tests/mocks/flow/flowexecmock/flowVersionLookup_mock.go is excluded by !**/*_mock.go
📒 Files selected for processing (58)
  • backend/cmd/server/bootstrap/flows/authentication/auth_flow_sso.json
  • backend/cmd/server/deployment.yaml
  • backend/cmd/server/servicemanager.go
  • backend/dbscripts/runtimedb/postgres.sql
  • backend/dbscripts/runtimedb/sqlite.sql
  • backend/internal/flow/common/constants.go
  • backend/internal/flow/executor/auth_assert_assurance_test.go
  • backend/internal/flow/executor/auth_assert_executor.go
  • backend/internal/flow/executor/constants.go
  • backend/internal/flow/executor/error_constants.go
  • backend/internal/flow/executor/register.go
  • backend/internal/flow/executor/session_executor.go
  • backend/internal/flow/executor/session_executor_test.go
  • backend/internal/flow/executor/sso_check_executor.go
  • backend/internal/flow/executor/sso_check_executor_test.go
  • backend/internal/flow/flowexec/engine.go
  • backend/internal/flow/flowexec/flowVersionLookup_mock_test.go
  • backend/internal/flow/flowexec/handler.go
  • backend/internal/flow/flowexec/handler_test.go
  • backend/internal/flow/flowexec/init.go
  • backend/internal/flow/flowexec/model.go
  • backend/internal/flow/flowexec/service.go
  • backend/internal/flow/flowexec/service_sso_test.go
  • backend/internal/flow/mgt/graph_builder_sso_test.go
  • backend/internal/flow/session/errors.go
  • backend/internal/flow/session/inputs.go
  • backend/internal/flow/session/model.go
  • backend/internal/flow/session/participant.go
  • backend/internal/flow/session/participant_store.go
  • backend/internal/flow/session/participant_store_test.go
  • backend/internal/flow/session/queries.go
  • backend/internal/flow/session/resolver.go
  • backend/internal/flow/session/resolver_test.go
  • backend/internal/flow/session/session_context.go
  • backend/internal/flow/session/session_context_store.go
  • backend/internal/flow/session/session_context_store_test.go
  • backend/internal/flow/session/state.go
  • backend/internal/flow/session/state_test.go
  • backend/internal/flow/session/store.go
  • backend/internal/flow/session/store_test.go
  • backend/internal/flow/session/transient_test.go
  • backend/internal/flow/session/transport.go
  • backend/internal/flow/session/transport_test.go
  • backend/internal/oauth/oauth2/authz/service.go
  • backend/internal/oauth/oauth2/constants/constants.go
  • backend/internal/oauth/oauth2/model/parameter.go
  • backend/internal/system/config/config.go
  • backend/internal/system/config/config_test.go
  • backend/internal/system/i18n/core/defaults.go
  • frontend/apps/console/src/features/flows/components/resources/steps/execution/Execution.tsx
  • frontend/apps/console/src/features/flows/components/resources/steps/execution/ExecutionMinimal.tsx
  • frontend/apps/console/src/features/flows/components/resources/steps/execution/__tests__/Execution.test.tsx
  • frontend/apps/console/src/features/flows/components/resources/steps/execution/__tests__/ExecutionMinimal.test.tsx
  • frontend/apps/console/src/features/flows/components/resources/steps/execution/execution-factory/ExecutionFactory.tsx
  • frontend/apps/console/src/features/flows/components/resources/steps/execution/execution-factory/__tests__/ExecutionFactory.test.tsx
  • frontend/apps/console/src/features/flows/models/base.ts
  • frontend/apps/console/src/features/flows/utils/flowToCanvasTransformer.ts
  • frontend/apps/console/src/features/login-flow/data/executors.json
✅ Files skipped from review due to trivial changes (3)
  • backend/internal/flow/session/participant.go
  • backend/internal/system/i18n/core/defaults.go
  • backend/internal/flow/flowexec/flowVersionLookup_mock_test.go
🚧 Files skipped from review as they are similar to previous changes (51)
  • backend/internal/flow/session/resolver.go
  • backend/internal/flow/session/transient_test.go
  • backend/internal/flow/mgt/graph_builder_sso_test.go
  • frontend/apps/console/src/features/flows/components/resources/steps/execution/execution-factory/ExecutionFactory.tsx
  • frontend/apps/console/src/features/flows/models/base.ts
  • backend/internal/oauth/oauth2/model/parameter.go
  • backend/internal/oauth/oauth2/authz/service.go
  • backend/internal/flow/session/state_test.go
  • frontend/apps/console/src/features/flows/utils/flowToCanvasTransformer.ts
  • backend/internal/flow/session/inputs.go
  • backend/cmd/server/bootstrap/flows/authentication/auth_flow_sso.json
  • frontend/apps/console/src/features/login-flow/data/executors.json
  • backend/cmd/server/deployment.yaml
  • backend/internal/flow/session/errors.go
  • backend/internal/flow/executor/register.go
  • backend/internal/flow/session/session_context.go
  • frontend/apps/console/src/features/flows/components/resources/steps/execution/tests/ExecutionMinimal.test.tsx
  • frontend/apps/console/src/features/flows/components/resources/steps/execution/execution-factory/tests/ExecutionFactory.test.tsx
  • backend/internal/system/config/config_test.go
  • backend/internal/system/config/config.go
  • backend/dbscripts/runtimedb/sqlite.sql
  • frontend/apps/console/src/features/flows/components/resources/steps/execution/ExecutionMinimal.tsx
  • backend/internal/flow/session/queries.go
  • backend/internal/flow/session/model.go
  • backend/internal/flow/executor/auth_assert_executor.go
  • backend/internal/flow/session/resolver_test.go
  • backend/internal/flow/executor/auth_assert_assurance_test.go
  • backend/cmd/server/servicemanager.go
  • backend/internal/flow/flowexec/service.go
  • backend/internal/flow/session/state.go
  • backend/internal/flow/flowexec/model.go
  • backend/internal/flow/flowexec/handler_test.go
  • backend/internal/flow/flowexec/init.go
  • frontend/apps/console/src/features/flows/components/resources/steps/execution/tests/Execution.test.tsx
  • backend/internal/flow/executor/sso_check_executor.go
  • backend/internal/flow/flowexec/handler.go
  • backend/internal/flow/executor/constants.go
  • backend/internal/flow/executor/error_constants.go
  • backend/internal/flow/session/participant_store.go
  • backend/internal/flow/session/transport_test.go
  • frontend/apps/console/src/features/flows/components/resources/steps/execution/Execution.tsx
  • backend/internal/flow/common/constants.go
  • backend/dbscripts/runtimedb/postgres.sql
  • backend/internal/flow/executor/sso_check_executor_test.go
  • backend/internal/flow/flowexec/service_sso_test.go
  • backend/internal/flow/flowexec/engine.go
  • backend/internal/flow/session/store_test.go
  • backend/internal/flow/session/participant_store_test.go
  • backend/internal/flow/executor/session_executor_test.go
  • backend/internal/flow/executor/session_executor.go
  • backend/internal/flow/session/store.go

RequestParamPrompt string = "prompt"
RequestParamRequestURI string = "request_uri"
RequestParamAcrValues string = "acr_values"
RequestParamMaxAge string = "max_age"

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.

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

🔴 Documentation Required
This PR introduces user-facing changes that are not covered by documentation updates under docs/.
Please update the relevant documentation before merging.

Missing documentation:

  • New OAuth2 max_age authorization request parameter: document the parameter, its semantics, and interaction with verified_claims.verification.time.max_age in docs/content/apis.mdx (OAuth2/OIDC API reference).
  • Browser SSO across applications (checkpoint-based session reuse, per-flow SSO cookie, idle/absolute session timeouts): document the new authentication-flow behavior and any new deployment/session-timeout config in docs/content/guides/ (authentication flow guide).

The authorization service reads the max_age request query parameter via oauth2const.RequestParamMaxAge and stores it in maxAge for request processing/validation. confirms this is now a live, user-facing OAuth2 parameter.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/internal/oauth/oauth2/constants/constants.go` at line 65, The new
OAuth2 RequestParamMaxAge constant makes max_age a user-facing authorization
request parameter, so update the docs to cover it in the OAuth2/OIDC API
reference and authentication guide. In docs/content/apis.mdx, document max_age
semantics and how it interacts with verified_claims.verification.time.max_age;
in the relevant docs/content/guides/ authentication-flow guide, describe browser
SSO behavior across applications, including checkpoint-based session reuse,
per-flow SSO cookies, and idle/absolute session timeout configuration. Use the
existing auth flow and OAuth2 terminology from oauth2const.RequestParamMaxAge
and the session-timeout behavior described by the PR so the new behavior is
discoverable.

Source: Path instructions

@@ -0,0 +1,127 @@
{

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Shall we add this as a flow builder template rather than introducing a new bootstrap flow?

CREATE INDEX idx_flow_context_expiry_time ON "FLOW_CONTEXT" (EXPIRY_TIME);

-- Table to store SSO sessions, grouped by flow (FLOW_ID) and resolved by an opaque handle.
CREATE TABLE "SSO_SESSION" (

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is persistent runtime data right? Shouldn't this go into operations DB?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

If going with runtime DB, there's some other refactoring happening to move this into a key value pair based table. Other existing tables are refactored progressively, but since this is a new table, we can directly follow this pattern adding data to RUNTIME_STORE.

#3818

"name": "SSOCheckExecutor"
},
"properties": {
"checkpointRef": "session"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This checkpointRef is sort of a checkpoint key within the session entry right?. SSOCheckExecutor lookup for a checkpoint with a key constructed by appending this ref in the session record.

But is this something intuitive for a user to configure? Does this always need to have id of the SessionExecutor? If so same info is already available via the onSuccess edge. I'm thinking whether we can set this explicitly by looking at the onSuccess edge at the graph construction time.

Anyway this is fine for the initial cut.

Comment thread backend/cmd/server/deployment.yaml Outdated
jwt:
preferred_key_id: "default-key"

session:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Shall we move these to default.json and remove from deployment.yaml?

Comment thread backend/cmd/server/servicemanager.go Outdated
GithubSvc: githubAuthnService,
GoogleSvc: googleAuthnService,
OpenID4VPVerifierSvc: openid4vpSvc,
SessionStore: flowsession.NewStore(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Plugging store implementations is not something we follow currently. But something we thought of having in future.
But is this a requirement currently? If this is not used outside flow package, we can keep it flow internal.

There are use cases which uses flow execution and core, but nothing else. Need to see how they can unplug session implementation via the thunderidengine/ service manager.

cc: @senthalan

RuntimeKeySSOSessionSaved = "ssoSessionSaved"
// RuntimeKeyAuthTime holds the Unix timestamp (seconds) at which the subject authenticated
// for the current session, carried across the SSO path for downstream assurance checks.
RuntimeKeyAuthTime = "authTime"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
RuntimeKeyAuthTime = "authTime"
RuntimeKeyAuthTime = "ssoAuthTime"

What if we append sso prefix for this too?

@madurangasiriwardena
madurangasiriwardena force-pushed the feature/session-poc-2-rebased branch from e5891d6 to 9eef538 Compare July 10, 2026 09:19
madurangasiriwardena added a commit to madurangasiriwardena/thunder-id that referenced this pull request Jul 10, 2026
Introduce a session.Service that owns resolve/checkpoint orchestration and
transactions, hiding the individual stores behind unexported constructors.
Build it in session.Initialize and inject it into the executor tree so the
flowexec engine and service carry no SSO initialization logic.

Add an engine-only EngineData channel on the executor/node responses so the
session handle reaches the engine without leaking to the client.

Inject the SSO cookie Secure flag and session timeouts into flowexec through
flowconfig.Config instead of reading the server runtime inside the package,
and move the SSO session lifetime configuration into the server-config API as
a new "session" section.

Refs thunder-id#3779
@madurangasiriwardena
madurangasiriwardena force-pushed the feature/session-poc-2-rebased branch from 9eef538 to be06e32 Compare July 10, 2026 10:14
if engineCtx.Graph == nil {
return 0
}
def, svcErr := s.flowProvider.GetFlow(ctx, engineCtx.Graph.GetID())

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Here we'll be fetching the flow again right? Can't we pass this version from previous fetch/ add to ctx and reuse?

@@ -0,0 +1,127 @@
{

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Do we need to keep this here?

@@ -0,0 +1,100 @@
/*

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Shall we merge this to the same store.go file?

// (re-execution or a concurrent request) overwrites it rather than erroring on the primary key.
// The ON CONFLICT ... DO UPDATE form is valid in both PostgreSQL and SQLite.
queryCreateSessionContext = model.DBQuery{
ID: "SSO-SESS-AC-01",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Not a must change. But we should be able to update all queries to use the same prefix since we have a single store interface now

// EngineData carries executor output the flow engine consumes internally (for example, a
// transport signal such as a minted session handle). Unlike AdditionalData, it is never
// serialized to the client.
EngineData map[string]string `json:"-"`

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We already have a forwarded data concept, but that's used to communicate data from current node to the next. If possible let's reuse that for this requirement

@@ -0,0 +1,141 @@
/*

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Should be able to merge to the same store.go file

@madurangasiriwardena
madurangasiriwardena added this pull request to the merge queue Jul 10, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to a conflict with the base branch Jul 10, 2026
Introduce a session.Service that owns resolve/checkpoint orchestration and
transactions, hiding the individual stores behind unexported constructors.
Build it in session.Initialize and inject it into the executor tree so the
flowexec engine and service carry no SSO initialization logic.

Add an engine-only EngineData channel on the executor/node responses so the
session handle reaches the engine without leaking to the client.

Inject the SSO cookie Secure flag and session timeouts into flowexec through
flowconfig.Config instead of reading the server runtime inside the package,
and move the SSO session lifetime configuration into the server-config API as
a new "session" section.

Refs thunder-id#3779
@rajithacharith
rajithacharith enabled auto-merge July 10, 2026 12:23
@rajithacharith
rajithacharith added this pull request to the merge queue Jul 10, 2026
Merged via the queue into thunder-id:main with commit 8956d42 Jul 10, 2026
27 of 45 checks passed
madurangasiriwardena added a commit to madurangasiriwardena/thunder-id that referenced this pull request Jul 10, 2026
- Merge participant and session-context stores into store.go (single store impl)
- Unify SQL query-constant IDs under one SSO-SESS-NN prefix
- Build the graphbuilder SSO test flow inline; drop testdata/sso_flow.json
- Reuse the flow version captured at context load instead of re-fetching the
  flow in resolveActiveFlowVersion

Refs thunder-id#3779
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants