Skip to content

docs(spec): EasyCLA → LFX Self Serve migration spec (M1–M6 + architecture review) - #5123

Closed
mlehotskylf wants to merge 38 commits into
devfrom
001-easycla-ss-integration
Closed

docs(spec): EasyCLA → LFX Self Serve migration spec (M1–M6 + architecture review)#5123
mlehotskylf wants to merge 38 commits into
devfrom
001-easycla-ss-integration

Conversation

@mlehotskylf

Copy link
Copy Markdown
Collaborator

What

Design/spec documentation for the EasyCLA → LFX Self Serve migration — the architecture-review package plus the detailed Milestone 1 spec-kit artifacts. Docs only (Markdown, mockups, diagrams); no application code.

Contents

  • docs/easycla-ss-migration/ — architecture-review package: milestone breakdown (M1–M6), the EasyCLA↔SS roles/permissions feasibility memo, architecture diagrams, and the ready-to-run spike runbook (spikes 1–4). Incorporates the 2026-07-20 architecture-review feedback.
  • specs/001-easycla-ss-integration-fable/ — the six milestone specs, plus the full M1 "My CLAs" spec-kit set under m1-my-cla/: plan.md, spec.md, research.md, data-model.md, contracts/, quickstart.md, tasks.md (31 tasks), and the UI mockups/.

M1 status (implementation tracked separately)

The M1 code lives in linuxfoundation/lfx-self-serve#1203 (read-only My CLAs: server + 32 tests + Profile-tab UI). This branch's research.md/tasks.md record the implementation outcomes and deviations as that work lands:

  • token model (gatewayFetch + apiGatewayToken, no new env),
  • claType as the ICLA/ECLA discriminator,
  • My CLAs placed as a Profile tab,
  • confirmed Contributor Console URLs,
  • decision to add projectName to the /v4/signatures/user response upstream (T010a) rather than a static table.

Still open in M1: dev spikes (T001–T006), the upstream GET /v4/users/by-identity + projectName endpoint (T007–T010a), component tests (T024), and E2E/parity on dev (T025–T030).

Note

Large, cohesive spec branch (~85 files) spanning the whole migration effort and the architecture review — intended to be read as the design source of truth, not a code change.

🤖 Generated with Claude Code

lukaszgryglicki and others added 30 commits June 25, 2026 09:51
Signed-off-by: Lukasz Gryglicki <lgryglicki@cncf.io>

Assisted by [OpenAI](https://platform.openai.com/)

Assisted by [GitHub Copilot](https://github.com/features/copilot)

Assisted by [Claude](https://claude.ai)
Signed-off-by: Lukasz Gryglicki <lgryglicki@cncf.io>

Assisted by [OpenAI](https://platform.openai.com/)

Assisted by [GitHub Copilot](https://github.com/features/copilot)

Assisted by [Claude](https://claude.ai)
…mails-prod

Downcase emails on write to DDB prod
Signed-off-by: Lukasz Gryglicki <lgryglicki@cncf.io>

Assisted by [OpenAI](https://platform.openai.com/)

Assisted by [GitHub Copilot](https://github.com/features/copilot)

Assisted by [Claude](https://claude.ai)
…g-prod

Add SSS enabled/disabled switch to EasyCLA (prod)
Six-milestone specification for migrating Contributor Console, Corporate
CLA Console, and PCC EasyCLA functionality into LFX Self Serve, plus the
K8s/V2-service and DynamoDB->Postgres evaluation. Includes resolved
review decisions (LF login status quo, per-platform sub-milestones,
UI-first sequencing) and speckit config.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Michal Lehotsky <mlehotsky@linuxfoundation.org>
Phase 0/1 artifacts: plan.md, research.md (endpoints, identity
resolution, token model spike, PDF handling), data-model.md,
contracts (SS server API + upstream EasyCLA API), quickstart.md.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Michal Lehotsky <mlehotsky@linuxfoundation.org>
Move M1 plan artifacts into m1-my-clas/ with an extracted slim spec.md,
point .specify/feature.json at the nested feature dir, and fix
cross-links. Program-level review docs stay at the top level; each
subsequent milestone gets its own subdirectory.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Michal Lehotsky <mlehotsky@linuxfoundation.org>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Michal Lehotsky <mlehotsky@linuxfoundation.org>
…b accounts

Union three lookup keys; add 'Link your GitHub account' CTA when
unlinked. Promote GET /v4/users/by-identity from contingency to
expected: /v3/users/search is a DynamoDB table scan and the GSI-backed
GitHub-ID lookup has no HTTP surface. Document the lf_username linking
gaps (user-from-token creates a second record; refreshStoredUserIdentity
never backfills lf_username).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Michal Lehotsky <mlehotsky@linuxfoundation.org>
user_github_id is stored N-typed with the github-id-index GSI and is
populated by the console GitHub OAuth get-or-create and the precheck
id/username backfill. No new storage needed; only the HTTP surface
(GET /v4/users/by-identity) is missing.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Michal Lehotsky <mlehotsky@linuxfoundation.org>
…tities

SS persists nothing; Auth0Identity.user_id carries GitHub's numeric ID,
fetched server-side via Auth0Service.getUserIdentities (NATS
auth-service). Spike must verify the ID arrives unprefixed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Michal Lehotsky <mlehotsky@linuxfoundation.org>
Reviewed lfx-product-documentation/easycla/v2-current. Key additions:
email-based CCLA signatory signing without LF SSO (M4 must keep it),
embargo/OFAC attestation checkbox gating signing (M2/M4), official
ICLA status vocabulary (Active/Incomplete/Disabled/Invalidated) and
approval-criteria-deletion auto-disable, earliest-PR redirect plus
/easycla re-check command, ECLA CCLA-version tracking, one-CLA-group-
per-project rule, last-CLA-manager rule, single-company role
limitation, Gerrit onboarding/enablement constraints, and GitHub App
merge-queue/branch-protection ops notes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Michal Lehotsky <mlehotsky@linuxfoundation.org>
Verified in code: SendAsEmail signatory flow, signature_embargo_acked
persistence, /easycla comment handler, InvalidateICLA endpoint,
invalidateSignatures on approval-criteria removal, single
active_signature KV record (multi-PR behavior), ECLA document-version
field, default-branch-only branch protection. Corrections: ICLA status
names are UI-derived labels over signed/approved booleans (not stored
values); embargo checkbox is enforced client-side only (backend
hardcodes acked=true); the last-CLA-manager rule has no code guard
found - flagged for M4 verification.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Michal Lehotsky <mlehotsky@linuxfoundation.org>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Michal Lehotsky <mlehotsky@linuxfoundation.org>
14-slide deck generated from the program spec for the architecture
review and PM scope approval; import into Google Slides via
File > Import slides.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Michal Lehotsky <mlehotsky@linuxfoundation.org>
UI-first approved; timeline tightened to Q3/early Q4; stakeholders
recorded (Heather PM, Nuno design). M5 marked decision-gated (PCC vs
SS placement open). easycla-landing-page retirement added to the M3
decommission package. Post-signing SS-profile nudge added as an M2 UX
requirement candidate.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Michal Lehotsky <mlehotsky@linuxfoundation.org>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Michal Lehotsky <mlehotsky@linuxfoundation.org>
…Serve)

Answers the open engineering action from the 2026-07-15 leadership
review: per-endpoint v4 enforcement trace, token-path finding (X-ACL
header trust, audience-independent), UI-gating read-path assessment,
options A/B/C evaluation (A confirmed), and a 5-item dev spike list.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Michal Lehotsky <mlehotsky@linuxfoundation.org>
… diagrams

Clearer section flow (answer -> background -> mechanism -> evidence ->
decision -> spikes), verified/inferred tagging throughout, and four
Mermaid diagrams: two authorization worlds, the request authorization
chain, token-shape equivalence, and the dual-write manager assignment
flow. Content and citations unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Michal Lehotsky <mlehotsky@linuxfoundation.org>
Documents how the bridged CLA module differs from SS-native permission
management (grant latency, role model, org-admin vs CLA-manager
expectation, People-view visibility, eligibility limits, support
runbook) and the M4 design consequences of each.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Michal Lehotsky <mlehotsky@linuxfoundation.org>
Re-verified citations across acs, lfx-gateway, lfx-corp-cla-console and
lfx-self-serve. Corrections: the 30-min ACS cache is on the warden
authorize/permission-check responses themselves (acs/middleware/
cache.go:52-54), so the gateway allow/deny decision — including
revocations — can be 30 min stale; designee no-check comment is at
handlers.go:158,189. Added revocation timing to spike 5; trimmed prose.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Michal Lehotsky <mlehotsky@linuxfoundation.org>
Move role-mapping-feasibility.md out of specs/ (links fixed, CC-BY-4.0
header added), remove the served-its-purpose role-mapping-brief.md, and
add architecture-proposal.md — the high-level proposed architecture
(P1-P8) with leadership-review context (L1-L6) and the points the
architecture review should challenge.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Michal Lehotsky <mlehotsky@linuxfoundation.org>
The review folder now stands alone: architecture-proposal.md gains the
current-state system diagram, verified backend facts, milestone map and
top risks (condensed from the specs, which remain the implementation
source of truth); README.md gives the reading order; the review slide
deck moves here from specs/. Spec links are demoted to deep-dive
references.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Michal Lehotsky <mlehotsky@linuxfoundation.org>
The review deck is maintained in Google Slides; drop the stale binary
from the repo and link the live deck from the README.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Michal Lehotsky <mlehotsky@linuxfoundation.org>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Michal Lehotsky <mlehotsky@linuxfoundation.org>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Michal Lehotsky <mlehotsky@linuxfoundation.org>
Rename §7 heading (drop time estimate). Static verification of the
spike endpoints against swagger + gateway routing surfaced two errors:
- Spike 3 approval-list path segment is 'clagroup', not 'claGroupID'
  (swagger/cla.v2.yaml:2518); corrected.
- Spike 4 premise was wrong: the v4 Lambda has no HTTP/API-Gateway
  event, it is invoked lambda-to-lambda by the gateway
  (serverless.yml:334-352). Reframed spike 4 as an IAM invoke-permission
  review rather than a curl against a non-existent URL; updated the §3
  consequence and appendix accordingly.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Michal Lehotsky <mlehotsky@linuxfoundation.org>
Exact curl steps reproducing SS's refresh-token exchange
(refresh-token-exchange.util.ts:104-120) and the secured v4 calls, with
pass/fail interpretation for the api-gw audience grant (spike 1) and
role-less-user gateway access (spike 2, the decision point).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Michal Lehotsky <mlehotsky@linuxfoundation.org>
- Correct the ACS description everywhere (docs + specs): ACS is an LFX
  v1 component with its own database, not Salesforce-backed.
- P2/§5: UI gating goes through the user's self permission check
  (user-service /v1/me/permissions/checks) — the same ACS decision the
  gateway enforces — with the public manager-list endpoint kept for
  display data and post-assignment pending-state UX.
- P3/§4: explicit direction — SS sends api-gw-audience access tokens,
  never ID tokens; ID tokens remain legacy-console-only.
- New P9: audit v4 payloads for v1 user/org-service IDs; map users via
  lfx.lookup_v1_user_by_{username|email} NATS RPC, orgs via the v1 org
  service with the api-gw secondary token.
- New risk: CLA permissions invisible to OpenFGA/v2-Swagger-based docs
  generation until M6.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Michal Lehotsky <mlehotsky@linuxfoundation.org>
mlehotskylf and others added 8 commits July 20, 2026 21:55
- m1 research R3: correct the disproven claim that v4 validates Auth0
  JWTs; record the settled token direction (api-gw-audience access
  tokens, never ID tokens) with the remaining spikes.
- 00-overview §3 / 04-milestone Option A: UI gating via the self
  permission check (user-service /v1/me/permissions/checks).
- 00-overview: add v1 user/org-service ID deprecation mapping action
  (§5) and the docs-generation visibility risk (§4).
- 05-milestone: token-path verification now points at the feasibility
  findings and spikes instead of an open question.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Michal Lehotsky <mlehotsky@linuxfoundation.org>
Verified in lfx-v1-sync-helper (README.md:96-97): the subjects are
lfx.lookup_v1_user_sfid.by_username / .by_email.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Michal Lehotsky <mlehotsky@linuxfoundation.org>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Michal Lehotsky <mlehotsky@linuxfoundation.org>
…reqs)

Spike 1 Auth0 client-grant condition verified in auth0-terraform; exchange
requests correct api-gw audience. T001/T002 gateway calls still pending
(need captured api-gw token + role-less user). Documents two local-dev
setup prerequisites (API_GW_AUDIENCE, NATS port-forward).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Michal Lehotsky <mlehotsky@linuxfoundation.org>
…local

Local SS held a primary-audience apiGatewayToken after the fix, but this is
most likely a local-session artifact (refresh token scoped to primary
audience; NATS down; cached exchange), not a real Auth0 downgrade. Flag to
re-validate in deployed dev; do not gate M1 staffing on the local result.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Michal Lehotsky <mlehotsky@linuxfoundation.org>
Copy the two design mockups (populated + empty state) into
m1-my-cla/mockups/ with a README, and reference them from research.md.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Michal Lehotsky <mlehotsky@linuxfoundation.org>
Sync spec to the landed lfx-self-serve server slice:
- R5: implementation deviations toward existing SS convention (gatewayFetch +
  req.apiGatewayToken, base URL from API_GW_AUDIENCE so no new env, Angular-side
  flag gating, identity source-of-truth helpers).
- R6: claType (icla/ecla/ccla) is the authoritative ICLA/ECLA discriminator;
  projectName display-name gap (payload has projectID only).
- tasks.md: mark T012/T016-T018 done, drop T011's CLA_SERVICE_BASE_URL env, note
  the remaining full-T016 (three-key union) and T004 fixture dependencies.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Michal Lehotsky <mlehotsky@linuxfoundation.org>
- R5/R6: My CLAs placed as a Profile tab (profile/clas) not a Me-lens sidebar
  item; confirmed Contributor Console URLs (dev/staging/prod); decision to add
  projectName to the /v4/signatures/user response upstream instead of a static
  CLA-group table (no GET /cla-group/{id} exists; list endpoint is foundation-
  scoped).
- tasks.md: T020-T022 done (T023 CTA implemented, tests pending), new T010a to
  add projectName upstream bundled with T007-T010.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Michal Lehotsky <mlehotsky@linuxfoundation.org>
Copilot AI review requested due to automatic review settings July 28, 2026 08:32
@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e9ca9d17-90b5-4d96-99a3-ef3523a8a924

📥 Commits

Reviewing files that changed from the base of the PR and between f9cc184 and 5332a2b.

📒 Files selected for processing (92)
  • .gitignore
  • .specify/extensions.yml
  • .specify/extensions/.registry
  • .specify/extensions/git/README.md
  • .specify/extensions/git/commands/speckit.git.commit.md
  • .specify/extensions/git/commands/speckit.git.feature.md
  • .specify/extensions/git/commands/speckit.git.initialize.md
  • .specify/extensions/git/commands/speckit.git.remote.md
  • .specify/extensions/git/commands/speckit.git.validate.md
  • .specify/extensions/git/config-template.yml
  • .specify/extensions/git/extension.yml
  • .specify/extensions/git/git-config.yml
  • .specify/extensions/git/scripts/bash/auto-commit.sh
  • .specify/extensions/git/scripts/bash/create-new-feature.sh
  • .specify/extensions/git/scripts/bash/git-common.sh
  • .specify/extensions/git/scripts/bash/initialize-repo.sh
  • .specify/extensions/git/scripts/powershell/auto-commit.ps1
  • .specify/extensions/git/scripts/powershell/create-new-feature.ps1
  • .specify/extensions/git/scripts/powershell/git-common.ps1
  • .specify/extensions/git/scripts/powershell/initialize-repo.ps1
  • .specify/feature.json
  • .specify/init-options.json
  • .specify/integration.json
  • .specify/integrations/claude.manifest.json
  • .specify/integrations/speckit.manifest.json
  • .specify/memory/constitution.md
  • .specify/scripts/bash/check-prerequisites.sh
  • .specify/scripts/bash/common.sh
  • .specify/scripts/bash/create-new-feature.sh
  • .specify/scripts/bash/setup-plan.sh
  • .specify/scripts/bash/setup-tasks.sh
  • .specify/templates/checklist-template.md
  • .specify/templates/constitution-template.md
  • .specify/templates/plan-template.md
  • .specify/templates/spec-template.md
  • .specify/templates/tasks-template.md
  • .specify/workflows/speckit/workflow.yml
  • .specify/workflows/workflow-registry.json
  • cla-backend-go/approval_list/repository.go
  • cla-backend-go/cmd/s3_upload/main.go
  • cla-backend-go/cmd/server.go
  • cla-backend-go/config/config.go
  • cla-backend-go/config/ssm.go
  • cla-backend-go/signatures/repository.go
  • cla-backend-go/users/repository.go
  • cla-backend-go/v2/sign/service.go
  • cla-backend-go/v2/sign/service_sss_test.go
  • cla-backend-legacy/internal/api/handlers.go
  • docs/easycla-ss-migration/README.md
  • docs/easycla-ss-migration/architecture-proposal.md
  • docs/easycla-ss-migration/role-mapping-feasibility.md
  • docs/easycla-ss-migration/spike-runbook.md
  • specs/001-easycla-ss-integration-fable/00-overview-fable.md
  • specs/001-easycla-ss-integration-fable/01-milestone-read-only-me-lens-fable.md
  • specs/001-easycla-ss-integration-fable/02-milestone-sign-icla-fable.md
  • specs/001-easycla-ss-integration-fable/03-milestone-sign-ecla-fable.md
  • specs/001-easycla-ss-integration-fable/04-milestone-ccla-org-lens-fable.md
  • specs/001-easycla-ss-integration-fable/05-milestone-project-lens-pcc-fable.md
  • specs/001-easycla-ss-integration-fable/06-milestone-k8s-v2-api-fable.md
  • specs/001-easycla-ss-integration-fable/checklists/requirements.md
  • specs/001-easycla-ss-integration-fable/m1-my-cla/contracts/ss-me-clas-api.md
  • specs/001-easycla-ss-integration-fable/m1-my-cla/contracts/upstream-easycla-api.md
  • specs/001-easycla-ss-integration-fable/m1-my-cla/data-model.md
  • specs/001-easycla-ss-integration-fable/m1-my-cla/mockups/README.md
  • specs/001-easycla-ss-integration-fable/m1-my-cla/mockups/my-clas-empty-state.html
  • specs/001-easycla-ss-integration-fable/m1-my-cla/mockups/my-clas-populated.html
  • specs/001-easycla-ss-integration-fable/m1-my-cla/plan.md
  • specs/001-easycla-ss-integration-fable/m1-my-cla/quickstart.md
  • specs/001-easycla-ss-integration-fable/m1-my-cla/research.md
  • specs/001-easycla-ss-integration-fable/m1-my-cla/spec.md
  • specs/001-easycla-ss-integration-fable/m1-my-cla/tasks.md
  • specs/001-easycla-ss-integration-fable/spec.md
  • specs/001-easycla-ss-integration-opus/00-overview-opus.md
  • specs/001-easycla-ss-integration-opus/01-milestone-read-only-me-lens-opus.md
  • specs/001-easycla-ss-integration-opus/02-milestone-sign-icla-opus.md
  • specs/001-easycla-ss-integration-opus/03-milestone-sign-ecla-opus.md
  • specs/001-easycla-ss-integration-opus/04-milestone-ccla-org-lens-opus.md
  • specs/001-easycla-ss-integration-opus/05-milestone-project-lens-pcc-opus.md
  • specs/001-easycla-ss-integration-opus/06-milestone-k8s-v2-api-opus.md
  • specs/001-easycla-ss-integration-opus/checklists/requirements-opus.md
  • specs/001-easycla-ss-integration-sonnet/00-milestone-role-adapter-sonnet.md
  • specs/001-easycla-ss-integration-sonnet/00-overview-sonnet.md
  • specs/001-easycla-ss-integration-sonnet/01-milestone-read-only-me-lens-sonnet.md
  • specs/001-easycla-ss-integration-sonnet/02-milestone-sign-icla-sonnet.md
  • specs/001-easycla-ss-integration-sonnet/03-milestone-sign-ecla-sonnet.md
  • specs/001-easycla-ss-integration-sonnet/04-milestone-ccla-org-lens-sonnet.md
  • specs/001-easycla-ss-integration-sonnet/05-milestone-project-lens-pcc-sonnet.md
  • specs/001-easycla-ss-integration-sonnet/06-milestone-k8s-v2-api-sonnet.md
  • tests/functional/cypress/e2e/v4/cla-manager.cy.ts
  • utils/downcase_emails.sh
  • utils/lookup_all_logs.sh
  • utils/search_aws_log_group.sh

Disabled knowledge base sources:

  • Jira integration is disabled

You can enable these sources in your CodeRabbit configuration.


Walkthrough

The pull request adds a Spec Kit Git extension and workflow assets, documents an EasyCLA-to-Self Serve migration, introduces SSS enablement and email normalization in Go services, and updates operational utility scripts.

Changes

Spec Kit Git workflow

Layer / File(s) Summary
Git extension configuration and commands
.specify/extensions*, .specify/extensions/git/*
Registers the Git extension, configures lifecycle hooks and auto-commit behavior, and adds Bash and PowerShell scripts for repository initialization, feature branches, validation, and Git checks.
Specify scripts and workflow assets
.specify/scripts/bash/*, .specify/templates/*, .specify/workflows/*, .specify/*.json
Adds shared path and template-resolution helpers, feature setup commands, document templates, workflow approval gates, and Specify integration metadata.

Backend safeguards

Layer / File(s) Summary
SSS enablement
cla-backend-go/config/*, cla-backend-go/cmd/*, cla-backend-go/v2/sign/*, cla-backend-legacy/internal/api/*
Adds an enabled flag for sanctions screening, defaults missing configuration to enabled, skips live screening when disabled, and updates startup handling and tests.
Email normalization
cla-backend-go/approval_list/*, cla-backend-go/users/*, cla-backend-go/signatures/*
Trims, lowercases, and deduplicates email values before persistence and lookup operations.

EasyCLA migration documentation

Layer / File(s) Summary
Migration architecture and milestones
docs/easycla-ss-migration/*, specs/001-easycla-ss-integration-fable/*, specs/001-easycla-ss-integration-opus/*, specs/001-easycla-ss-integration-sonnet/*
Adds architecture proposals, authorization analysis, spike procedures, milestone specifications, contracts, plans, checklists, mockups, and implementation tasks for the Self Serve migration and Kubernetes V2 transition.

Operational scripts

Layer / File(s) Summary
Utility hardening and data cleanup
utils/*, tests/functional/cypress/e2e/v4/cla-manager.cy.ts
Adds a DynamoDB email-normalization utility, enables strict shell behavior, separates AWS and jq failures in log searches, and disables Cypress automatic failure for one request.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 001-easycla-ss-integration

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

Copilot AI 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.

Pull request overview

Adds the EasyCLA-to-LFX Self Serve migration specifications and M1 implementation artifacts, alongside unrelated runtime and Spec Kit tooling changes.

Changes:

  • Documents migration milestones M1–M6, architecture decisions, contracts, and mockups.
  • Adds sanctions-screening controls and email normalization.
  • Installs Spec Kit workflow and Git extension infrastructure.

Reviewed changes

Copilot reviewed 91 out of 92 changed files in this pull request and generated 11 comments.

Show a summary per file
File Description
utils/search_aws_log_group.sh Improves AWS/jq error handling.
utils/lookup_all_logs.sh Fails fast on lookup errors.
utils/downcase_emails.sh Adds email normalization utility.
tests/functional/cypress/e2e/v4/cla-manager.cy.ts Allows duplicate-manager response handling.
specs/001-easycla-ss-integration-sonnet/06-milestone-k8s-v2-api-sonnet.md Specifies M6 backend migration.
specs/001-easycla-ss-integration-sonnet/05-milestone-project-lens-pcc-sonnet.md Specifies M5 project administration.
specs/001-easycla-ss-integration-sonnet/04-milestone-ccla-org-lens-sonnet.md Specifies M4 CCLA management.
specs/001-easycla-ss-integration-sonnet/03-milestone-sign-ecla-sonnet.md Specifies M3 ECLA signing.
specs/001-easycla-ss-integration-sonnet/02-milestone-sign-icla-sonnet.md Specifies M2 ICLA signing.
specs/001-easycla-ss-integration-sonnet/01-milestone-read-only-me-lens-sonnet.md Specifies M1 agreement viewing.
specs/001-easycla-ss-integration-sonnet/00-milestone-role-adapter-sonnet.md Specifies authorization adapter.
specs/001-easycla-ss-integration-opus/checklists/requirements-opus.md Adds Opus requirements checklist.
specs/001-easycla-ss-integration-opus/05-milestone-project-lens-pcc-opus.md Details Opus M5 scope.
specs/001-easycla-ss-integration-opus/04-milestone-ccla-org-lens-opus.md Details Opus M4 scope.
specs/001-easycla-ss-integration-opus/03-milestone-sign-ecla-opus.md Details Opus M3 scope.
specs/001-easycla-ss-integration-opus/02-milestone-sign-icla-opus.md Details Opus M2 scope.
specs/001-easycla-ss-integration-opus/01-milestone-read-only-me-lens-opus.md Details Opus M1 scope.
specs/001-easycla-ss-integration-fable/m1-my-cla/spec.md Defines implementable M1 requirements.
specs/001-easycla-ss-integration-fable/m1-my-cla/quickstart.md Documents M1 setup and verification.
specs/001-easycla-ss-integration-fable/m1-my-cla/plan.md Describes M1 implementation plan.
specs/001-easycla-ss-integration-fable/m1-my-cla/mockups/README.md Indexes M1 UI mockups.
specs/001-easycla-ss-integration-fable/m1-my-cla/mockups/my-clas-empty-state.html Adds empty-state mockup.
specs/001-easycla-ss-integration-fable/m1-my-cla/data-model.md Defines M1 read models.
specs/001-easycla-ss-integration-fable/m1-my-cla/contracts/upstream-easycla-api.md Documents upstream API contract.
specs/001-easycla-ss-integration-fable/m1-my-cla/contracts/ss-me-clas-api.md Documents Self Serve API contract.
specs/001-easycla-ss-integration-fable/checklists/requirements.md Adds Fable requirements checklist.
specs/001-easycla-ss-integration-fable/06-milestone-k8s-v2-api-fable.md Details Fable M6 migration.
specs/001-easycla-ss-integration-fable/05-milestone-project-lens-pcc-fable.md Details Fable M5 administration.
specs/001-easycla-ss-integration-fable/04-milestone-ccla-org-lens-fable.md Details Fable M4 management.
specs/001-easycla-ss-integration-fable/03-milestone-sign-ecla-fable.md Details Fable M3 signing.
specs/001-easycla-ss-integration-fable/02-milestone-sign-icla-fable.md Details Fable M2 signing.
specs/001-easycla-ss-integration-fable/01-milestone-read-only-me-lens-fable.md Details Fable M1 viewing.
docs/easycla-ss-migration/spike-runbook.md Adds authorization spike procedure.
docs/easycla-ss-migration/README.md Introduces architecture-review materials.
cla-backend-legacy/internal/api/handlers.go Adds SSS switch and email normalization.
cla-backend-go/v2/sign/service.go Adds SSS switch to signing.
cla-backend-go/v2/sign/service_sss_test.go Tests SSS switch behavior.
cla-backend-go/users/repository.go Normalizes stored and queried emails.
cla-backend-go/signatures/repository.go Normalizes removed approval emails.
cla-backend-go/config/ssm.go Loads the SSS enabled setting.
cla-backend-go/config/config.go Extends SSS configuration.
cla-backend-go/cmd/server.go Wires SSS enablement.
cla-backend-go/cmd/s3_upload/main.go Updates sign-service construction.
cla-backend-go/approval_list/repository.go Normalizes requester emails.
.specify/workflows/workflow-registry.json Registers Spec Kit workflow.
.specify/workflows/speckit/workflow.yml Defines full SDD workflow.
.specify/templates/spec-template.md Adds specification template.
.specify/templates/plan-template.md Adds planning template.
.specify/templates/constitution-template.md Adds constitution template.
.specify/templates/checklist-template.md Adds checklist template.
.specify/scripts/bash/setup-tasks.sh Adds task setup script.
.specify/scripts/bash/setup-plan.sh Adds plan setup script.
.specify/scripts/bash/check-prerequisites.sh Adds workflow prerequisite checks.
.specify/memory/constitution.md Adds unratified constitution placeholder.
.specify/integrations/speckit.manifest.json Records Spec Kit installation.
.specify/integrations/claude.manifest.json Records Claude integration.
.specify/integration.json Configures default integration.
.specify/init-options.json Records Spec Kit initialization options.
.specify/feature.json Pins the active M1 feature.
.specify/extensions/git/scripts/powershell/initialize-repo.ps1 Adds PowerShell repository initialization.
.specify/extensions/git/scripts/powershell/git-common.ps1 Adds PowerShell Git helpers.
.specify/extensions/git/scripts/powershell/auto-commit.ps1 Adds PowerShell auto-commit support.
.specify/extensions/git/scripts/bash/initialize-repo.sh Adds Bash repository initialization.
.specify/extensions/git/scripts/bash/git-common.sh Adds Bash Git helpers.
.specify/extensions/git/scripts/bash/auto-commit.sh Adds Bash auto-commit support.
.specify/extensions/git/README.md Documents Git extension.
.specify/extensions/git/git-config.yml Configures Git extension.
.specify/extensions/git/extension.yml Defines Git extension hooks.
.specify/extensions/git/config-template.yml Adds Git configuration template.
.specify/extensions/git/commands/speckit.git.validate.md Defines branch validation command.
.specify/extensions/git/commands/speckit.git.remote.md Defines remote detection command.
.specify/extensions/git/commands/speckit.git.initialize.md Defines repository initialization command.
.specify/extensions/git/commands/speckit.git.feature.md Defines feature-branch command.
.specify/extensions/git/commands/speckit.git.commit.md Defines auto-commit command.
.specify/extensions/.registry Registers Git extension.
.specify/extensions.yml Enables extension hooks.
.gitignore Ignores email migration output.
Comments suppressed due to low confidence (1)

specs/001-easycla-ss-integration-fable/m1-my-cla/quickstart.md:19

  • The implemented UI is a Profile child route, as recorded by completed task T020 and research.md, so /me/clas will not open this page. Update the run instruction to the actual route.

_paths_output=$(get_feature_paths) || { echo "ERROR: Failed to resolve feature paths" >&2; exit 1; }
eval "$_paths_output"
unset _paths_output
check_feature_branch "$CURRENT_BRANCH" "$HAS_GIT" || exit 1
## Prerequisites

- `lfx-self-serve` running locally (`apps/lfx-one`): Node 22+, `.env` per `apps/lfx-one/.env.example`, Auth0 dev tenant login working.
- Network access to EasyCLA **dev**: lfx-gateway dev URL for `/cla-service/v3|v4` (set `CLA_SERVICE_BASE_URL`), plus whichever token config the R3 spike selected (user bearer passthrough, or exchange/M2M client credentials).
| `signedOn` / created | display date |
| document major/minor version | superseded detection (if exposed; else display-only) |

**Classification rule**: `type=cla & referenceType=user & cclaCompanyID empty` ⇒ **ICLA** (has PDF); `type=cla & referenceType=user & cclaCompanyID set` ⇒ **ECLA** (no PDF, never offer download); `type=ccla` ⇒ corporate record — **excluded from M1** (Organization-lens data, M4).

## Feature flag

Both routes and the Angular module are gated by LaunchDarkly flag `my-clas-enabled` (name TBD per repo convention). Flag off ⇒ routes 404, sidebar item hidden, route guard redirects to Me dashboard.
## Current state (facts)

- ICLAs/ECLAs live in the `cla-{stage}-signatures` DynamoDB table. ECLA = ICLA-shaped record with `signature_user_ccla_company_id` set and **no PDF**; ICLA has a PDF in S3 `cla-signature-files-{stage}` (`contract-group/{projectID}/cla/{userID}/{signatureID}.pdf`), served via 15-minute presigned URLs.
- The v4 API already has a per-user endpoint: `GET /v2 (v4 path) /users/{userID}/signatures` returning the user's ICLAs and ECLAs, plus per-signature PDF endpoints (`/signatures/{signatureID}/signed-document`, ICLA PDF routes).
Comment on lines +58 to +60
├── app/modules/my-clas/ # NEW Angular lens module (Me lens)
│ ├── my-clas.routes.ts # exported MY_CLAS_ROUTES, lazy-loaded at /me/clas
│ ├── my-clas.component.ts|html # list view: ICLA + ECLA sections, empty state

## Phase 3: User Story 1 — My CLAs list + ICLA PDF download (Priority: P1) 🎯 MVP

**Goal**: logged-in user sees all their signed ICLAs (any status, labeled) and currently valid ECLAs under Me lens `/me/clas`, downloads ICLA PDFs via short-lived links, sees the GitHub-link CTA when unlinked, and gets a clear empty state. Read-only; signing links out to Contributor Console.
Comment on lines +146 to +147
// Enabled is the SSS kill switch (cla-sss-enabled-{stage}, default true): when false,
// checkCompanyCompliance skips the live SSS check; persisted is_sanctioned still blocks elsewhere.
userService *userservicelegacy.Client
sssClient *sss.Client
sssRequired bool
sssEnabled bool
// not-yet-provisioned key never silently disables screening. A malformed value also
// falls back to the default rather than being treated as false.
func getOptionalSSMBoolDefault(ctx context.Context, ssmClient *ssm.Client, key string, def bool, f logrus.Fields) bool {
val := strings.TrimSpace(getOptionalSSMString(ctx, ssmClient, key, f))
@mlehotskylf

Copy link
Copy Markdown
Collaborator Author

Closing in favor of #5124. This branch had accumulated the full six-milestone spec, Spec-Kit tooling (.specify/), and unrelated cla-backend code diffs from a stale branch base (85 files, unreviewable). #5124 is scoped to Milestone 1 only and branched cleanly off current dev (15 docs files).

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