Skip to content

Agents/sss integration review feedback#5083

Closed
psrsingh wants to merge 3 commits into
linuxfoundation:devfrom
psrsingh:agents/sss-integration-review-feedback
Closed

Agents/sss integration review feedback#5083
psrsingh wants to merge 3 commits into
linuxfoundation:devfrom
psrsingh:agents/sss-integration-review-feedback

Conversation

@psrsingh
Copy link
Copy Markdown
Contributor

@psrsingh psrsingh commented Jun 2, 2026

Summary

Add SSS (Sanctions Screening Service) enforcement to signing flows and address review feedback around sanction handling, rollout safety, and performance.

Changes

SSS compliance checks

  • Added SSS compliance checks to signing flows in cla-backend-go.

  • Preserve existing manual sanction behavior:

    • is_sanctioned remains an independent/manual block.
    • SSS can set is_sanctioned=true.
    • A clean SSS result never clears an existing sanction flag.
  • Added explicit handling for SSS timeout, auth, retryable, and not-found errors.

Configurable rollout

  • Added cla-sss-required-<stage> configuration support.
  • When Required=true, SSS availability errors fail closed.
  • When Required=false, SSS availability errors are logged and signing proceeds.
  • Definitive sanctioned results always block regardless of configuration.

Domain resolution

  • Resolve domains using:

    1. Organization Domains
    2. Organization Link as fallback
  • Normalize parsed domains and strip www. prefixes.

  • Removed unreachable code from resolveDomain().

Persistence

  • Added UpdateCompanySanctionStatus.
  • Avoid unnecessary DynamoDB writes when the value has not changed.

Performance

  • Added a small in-memory compliance cache (5 minute TTL) to avoid repeated org-service and SSS lookups for the same organization during a single execution window.

Notes

cla-backend-legacy does not currently have an SSS client integration. The live SSS checks added in this change are in cla-backend-go.

The legacy ECLA endpoints continue to enforce the persisted is_sanctioned flag. Adding live SSS checks directly to the legacy ECLA flow would require separate work in cla-backend-legacy.

Validation

  • gofmt completed
  • git diff --check passed
  • Added tests covering SSS-required behavior and caching

psrsingh added 2 commits May 30, 2026 15:07
Signed-off-by: psrsingh <psr.singh336@gmail.com>
Signed-off-by: psrsingh <psr.singh336@gmail.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jun 2, 2026

Review Change Stack

Walkthrough

The PR integrates an external Sanctions Screening Service (SSS) client into corporate and employee signature processing. Configuration is loaded from local and SSM sources with Auth0 credentials and timeout settings. A new company repository method persists sanction flags to DynamoDB. The sign service is extended with SSS client initialization, compliance caching with TTL, and domain-resolution logic for screening. Both signature flows are updated to call compliance checks before proceeding.

Changes

Sanctions Screening Integration

Layer / File(s) Summary
SSS Configuration Schema and Loading
cla-backend-go/config/config.go, cla-backend-go/config/local.go, cla-backend-go/config/ssm.go
Configuration structure for SSS is defined with Auth0 credentials, base URL, request timeout, and a required flag, then loaded and populated from local and SSM sources with appropriate defaults and optional overrides.
Company Sanction Persistence
cla-backend-go/company/repository.go
New UpdateCompanySanctionStatus method is added to the company repository interface and implemented to update the company's is_sanctioned flag and date_modified timestamp in DynamoDB, with optimization to skip writes when the flag value is unchanged.
Sign Service Foundation with SSS Support
cla-backend-go/v2/sign/service.go
The sign service struct is extended with SSS client, required flag, and mutex-protected compliance cache. The NewService constructor signature is updated to accept the SSS client and required flag parameters, and the compliance cache is initialized.
Compliance Screening Implementation
cla-backend-go/v2/sign/service.go
Core compliance checking logic is implemented via checkCompanyCompliance, which queries the SSS client, resolves organization domains, caches results with TTL, persists SSS-flagged sanctions to the repository, and classifies SSS errors to determine whether signing should be blocked. The RequestCorporateSignature flow is updated to use this compliance subsystem instead of a direct IsSanctioned check.
ECLA Signature Compliance Check
cla-backend-go/v2/sign/helpers.go
The hasUserSigned function in the ECLA flow is updated to enforce company compliance checking before processing employee signatures, including a nil-check for the company record and returning early if compliance checking fails or the company is flagged.
Server Startup SSS Client Initialization
cla-backend-go/cmd/server.go
At server startup, the SSS client is conditionally initialized based on the configured Auth0 and base URL settings, with timeout defaulting to 30 seconds. The client initialization failure is logged as a warning and disables screening by leaving the client as nil. The v2SignService constructor is updated to pass the initialized SSS client and required flag.
S3 Upload Service Parameter Update
cla-backend-go/cmd/s3_upload/main.go
The sign service constructor call in s3_upload/main.go is updated to pass configFile.SSS.Required as a parameter, matching the new NewService signature.
Sign Service Compliance Tests
cla-backend-go/v2/sign/service_sss_test.go
Comprehensive test suite covers domain resolution logic (preferring Domains over parsed Link hostname), error handling for required vs optional SSS modes (blocking on retryable errors when required, allowing auth errors when optional), and compliance cache behavior (key preference for CompanyExternalID and TTL expiration logic).

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • linuxfoundation/easycla#5058: Implements the reusable SSS client, models, and error types that this PR directly depends on for compliance checking in corporate signature processing.
🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 27.27% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Agents/sss integration review feedback' is vague and doesn't clearly convey the main change; it references an internal process (review feedback) rather than describing the substantive work being merged. Revise to a more descriptive title like 'Add SSS compliance enforcement to signing flows' that clearly indicates the primary change being implemented.
✅ Passed checks (3 passed)
Check name Status Explanation
Description check ✅ Passed The description is directly related to the changeset, providing clear details about SSS compliance checks, configurable rollout, domain resolution, persistence improvements, and performance caching.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 golangci-lint (2.12.2)

level=error msg="[linters_context] typechecking error: pattern ./...: directory prefix . does not contain main module or its selected dependencies"


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

Signed-off-by: psrsingh <psr.singh336@gmail.com>
@psrsingh psrsingh force-pushed the agents/sss-integration-review-feedback branch from 6347fe6 to 2ebd9e1 Compare June 2, 2026 08:40
@lukaszgryglicki
Copy link
Copy Markdown
Member

lukaszgryglicki commented Jun 2, 2026

Why a new PR? Instead of continuying on #5078 ?

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

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)
cla-backend-go/v2/sign/service.go (1)

3057-3057: SSS flag comparison is valid; minor redundancy in blocked computation

  • sss.StatusFlagged exists (exported as StatusFlagged = "flagged" in cla-backend-go/sss/types.go), so the line 3057 comparison is sound.
  • blocked := company.IsSanctioned || sanctioned is redundant if the function already returns when company.IsSanctioned is true; it’s defensive but can be simplified for clarity.
🤖 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 `@cla-backend-go/v2/sign/service.go` at line 3057, The comparison using
sss.StatusFlagged is correct but the subsequent blocked := company.IsSanctioned
|| sanctioned is redundant if the code already returns when company.IsSanctioned
is true; simplify by either removing the early return and keeping blocked as
company.IsSanctioned || result.Status == sss.StatusFlagged (referencing
result.Status and sss.StatusFlagged) or, if you keep the early return that exits
when company.IsSanctioned is true, change blocked to just sanctioned (the local
variable sanctioned computed from result.Status) and remove the redundant
company.IsSanctioned check.
🤖 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 `@cla-backend-go/company/repository.go`:
- Around line 1282-1338: UpdateCompanySanctionStatus currently calls
repo.dynamoDBClient.UpdateItem(input) without ctx; change it to the
context-aware API repo.dynamoDBClient.UpdateItemWithContext(ctx, input) so the
passed ctx (from the function parameter and f log fields) propagates to DynamoDB
calls and respects cancellations/deadlines; update the call site that assigns _,
err = repo.dynamoDBClient.UpdateItem(...) to use UpdateItemWithContext(ctx, ...)
and keep the same error handling and return path.

---

Nitpick comments:
In `@cla-backend-go/v2/sign/service.go`:
- Line 3057: The comparison using sss.StatusFlagged is correct but the
subsequent blocked := company.IsSanctioned || sanctioned is redundant if the
code already returns when company.IsSanctioned is true; simplify by either
removing the early return and keeping blocked as company.IsSanctioned ||
result.Status == sss.StatusFlagged (referencing result.Status and
sss.StatusFlagged) or, if you keep the early return that exits when
company.IsSanctioned is true, change blocked to just sanctioned (the local
variable sanctioned computed from result.Status) and remove the redundant
company.IsSanctioned check.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: bd6c02e9-ecd2-44d4-9f2e-8e94f22bc935

📥 Commits

Reviewing files that changed from the base of the PR and between 3b58bf9 and 2ebd9e1.

📒 Files selected for processing (9)
  • cla-backend-go/cmd/s3_upload/main.go
  • cla-backend-go/cmd/server.go
  • cla-backend-go/company/repository.go
  • cla-backend-go/config/config.go
  • cla-backend-go/config/local.go
  • cla-backend-go/config/ssm.go
  • cla-backend-go/v2/sign/helpers.go
  • cla-backend-go/v2/sign/service.go
  • cla-backend-go/v2/sign/service_sss_test.go

Comment on lines +1282 to +1338
func (repo repository) UpdateCompanySanctionStatus(ctx context.Context, companyID string, sanctioned bool) error {
f := logrus.Fields{
"functionName": "company.repository.UpdateCompanySanctionStatus",
utils.XREQUESTID: ctx.Value(utils.XREQUESTID),
"companyID": companyID,
"sanctioned": sanctioned,
}

// Fetch current company to check if value has changed
currentCompany, err := repo.GetCompany(ctx, companyID)
if err != nil {
log.WithFields(f).Warnf("unable to fetch current company record to check sanction status, error: %v", err)
return err
}
if currentCompany == nil {
return fmt.Errorf("company not found: %s", companyID)
}

// Avoid unnecessary writes - only update if value has changed
if currentCompany.IsSanctioned == sanctioned {
log.WithFields(f).Debugf("sanction status unchanged (current=%v, new=%v), skipping update", currentCompany.IsSanctioned, sanctioned)
return nil
}

log.WithFields(f).Debugf("updating sanction status from %v to %v", currentCompany.IsSanctioned, sanctioned)

_, now := utils.CurrentTime()

input := &dynamodb.UpdateItemInput{
ExpressionAttributeNames: map[string]*string{
"#S": aws.String("is_sanctioned"),
"#M": aws.String("date_modified"),
},
ExpressionAttributeValues: map[string]*dynamodb.AttributeValue{
":s": {
BOOL: aws.Bool(sanctioned),
},
":m": {
S: aws.String(now),
},
},
TableName: aws.String(repo.companyTableName),
Key: map[string]*dynamodb.AttributeValue{
"company_id": {
S: aws.String(companyID),
},
},
UpdateExpression: aws.String("SET #S = :s, #M = :m"),
}

_, err = repo.dynamoDBClient.UpdateItem(input)
if err != nil {
log.WithFields(f).Warnf("error updating company sanction status, error: %v", err)
return err
}

return nil
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

Does aws-sdk-go v1.36.27 dynamodb client provide an UpdateItemWithContext method?

💡 Result:

No. In aws-sdk-go v1, the DynamoDB client’s context-aware method for UpdateItem is named UpdateItemWithContext (not UpdateItemWithContextWithContext / etc.), and aws-sdk-go v1 does not provide any additional method beyond that naming in the dynamodbiface interface. The interface includes UpdateItemWithContext(aws.Context, *dynamodb.UpdateItemInput,...request.Option), alongside UpdateItem(*dynamodb.UpdateItemInput). [1] So, the answer to “Does aws-sdk-go v1.36.27 dynamodb client provide an UpdateItemWithContext method?” is: Yes—UpdateItemWithContext exists for the DynamoDB client in aws-sdk-go v1 (as specified by the official dynamodbiface for the v1 SDK). [1]

Citations:


Propagate request ctx to the DynamoDB UpdateItem call.

UpdateCompanySanctionStatus accepts ctx but the DynamoDB write uses UpdateItem(input) (no context), so cancellations/deadlines won’t reach DynamoDB. Use the context-aware method supported by aws-sdk-go v1 (UpdateItemWithContext).

♻️ Use context-aware UpdateItem
-	_, err = repo.dynamoDBClient.UpdateItem(input)
+	_, err = repo.dynamoDBClient.UpdateItemWithContext(ctx, input)
 	if err != nil {
 		log.WithFields(f).Warnf("error updating company sanction status, error: %v", err)
 		return err
 	}

The read-before-write skip optimization and the BOOL/string attribute mapping look correct and consistent with the table model.

📝 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
func (repo repository) UpdateCompanySanctionStatus(ctx context.Context, companyID string, sanctioned bool) error {
f := logrus.Fields{
"functionName": "company.repository.UpdateCompanySanctionStatus",
utils.XREQUESTID: ctx.Value(utils.XREQUESTID),
"companyID": companyID,
"sanctioned": sanctioned,
}
// Fetch current company to check if value has changed
currentCompany, err := repo.GetCompany(ctx, companyID)
if err != nil {
log.WithFields(f).Warnf("unable to fetch current company record to check sanction status, error: %v", err)
return err
}
if currentCompany == nil {
return fmt.Errorf("company not found: %s", companyID)
}
// Avoid unnecessary writes - only update if value has changed
if currentCompany.IsSanctioned == sanctioned {
log.WithFields(f).Debugf("sanction status unchanged (current=%v, new=%v), skipping update", currentCompany.IsSanctioned, sanctioned)
return nil
}
log.WithFields(f).Debugf("updating sanction status from %v to %v", currentCompany.IsSanctioned, sanctioned)
_, now := utils.CurrentTime()
input := &dynamodb.UpdateItemInput{
ExpressionAttributeNames: map[string]*string{
"#S": aws.String("is_sanctioned"),
"#M": aws.String("date_modified"),
},
ExpressionAttributeValues: map[string]*dynamodb.AttributeValue{
":s": {
BOOL: aws.Bool(sanctioned),
},
":m": {
S: aws.String(now),
},
},
TableName: aws.String(repo.companyTableName),
Key: map[string]*dynamodb.AttributeValue{
"company_id": {
S: aws.String(companyID),
},
},
UpdateExpression: aws.String("SET #S = :s, #M = :m"),
}
_, err = repo.dynamoDBClient.UpdateItem(input)
if err != nil {
log.WithFields(f).Warnf("error updating company sanction status, error: %v", err)
return err
}
return nil
func (repo repository) UpdateCompanySanctionStatus(ctx context.Context, companyID string, sanctioned bool) error {
f := logrus.Fields{
"functionName": "company.repository.UpdateCompanySanctionStatus",
utils.XREQUESTID: ctx.Value(utils.XREQUESTID),
"companyID": companyID,
"sanctioned": sanctioned,
}
// Fetch current company to check if value has changed
currentCompany, err := repo.GetCompany(ctx, companyID)
if err != nil {
log.WithFields(f).Warnf("unable to fetch current company record to check sanction status, error: %v", err)
return err
}
if currentCompany == nil {
return fmt.Errorf("company not found: %s", companyID)
}
// Avoid unnecessary writes - only update if value has changed
if currentCompany.IsSanctioned == sanctioned {
log.WithFields(f).Debugf("sanction status unchanged (current=%v, new=%v), skipping update", currentCompany.IsSanctioned, sanctioned)
return nil
}
log.WithFields(f).Debugf("updating sanction status from %v to %v", currentCompany.IsSanctioned, sanctioned)
_, now := utils.CurrentTime()
input := &dynamodb.UpdateItemInput{
ExpressionAttributeNames: map[string]*string{
"`#S`": aws.String("is_sanctioned"),
"`#M`": aws.String("date_modified"),
},
ExpressionAttributeValues: map[string]*dynamodb.AttributeValue{
":s": {
BOOL: aws.Bool(sanctioned),
},
":m": {
S: aws.String(now),
},
},
TableName: aws.String(repo.companyTableName),
Key: map[string]*dynamodb.AttributeValue{
"company_id": {
S: aws.String(companyID),
},
},
UpdateExpression: aws.String("SET `#S` = :s, `#M` = :m"),
}
_, err = repo.dynamoDBClient.UpdateItemWithContext(ctx, input)
if err != nil {
log.WithFields(f).Warnf("error updating company sanction status, error: %v", err)
return err
}
return nil
}
🤖 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 `@cla-backend-go/company/repository.go` around lines 1282 - 1338,
UpdateCompanySanctionStatus currently calls
repo.dynamoDBClient.UpdateItem(input) without ctx; change it to the
context-aware API repo.dynamoDBClient.UpdateItemWithContext(ctx, input) so the
passed ctx (from the function parameter and f log fields) propagates to DynamoDB
calls and respects cancellations/deadlines; update the call site that assigns _,
err = repo.dynamoDBClient.UpdateItem(...) to use UpdateItemWithContext(ctx, ...)
and keep the same error handling and return path.

@psrsingh psrsingh closed this Jun 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants