Skip to content

docs(easycla-ss): P10 — confirm EasyCLA has no NATS transit pre-M6 - #5131

Closed
mlehotskylf wants to merge 3 commits into
devfrom
docs/p10-nats-transit-confirmed
Closed

docs(easycla-ss): P10 — confirm EasyCLA has no NATS transit pre-M6#5131
mlehotskylf wants to merge 3 commits into
devfrom
docs/p10-nats-transit-confirmed

Conversation

@mlehotskylf

Copy link
Copy Markdown
Collaborator

Updates P10 in docs/easycla-ss-migration/architecture-proposal.md to record Eric Searcy's confirmation (2026-07-30) that EasyCLA has no NATS transit pre-M6, replacing the stale "pending confirmation from Eric" parenthetical.

Why

P10 (trust-SS "My CLAs" identity read + azp allow-list) hinged on one open dependency: whether EasyCLA could reach NATS pre-M6. If it could, "same data, less machinery" would argue for EasyCLA calling lfx.auth-service.user_identity.list directly and skipping both the SS payload bridge and the azp mechanism.

Eric confirmed it cannot, and not merely for IP-reachability reasons:

  • the RPC is a request/reply (inbox) subject, so EasyCLA would have to be a cluster consumer for the reply;
  • EasyCLA (us-east-1) ↔ v2 k8s cluster (us-west-2) is a cross-region WAN link — you don't run inbox consumers over WAN;
  • a federated NATS super-cluster with gateways is overkill.

So the SS payload bridge + azp mechanism is the right pre-M6 design; EasyCLA calling the RPC directly is deferred to M6.

Scope

Docs-only change: adds the EasyCLA → Self Serve M1 spec/architecture docs (docs/easycla-ss-migration/, specs/001-easycla-ss-integration-fable/m1-my-cla/) and the P10 rationale update. No behavioral/code change.

Supersedes #5130, which incorrectly targeted the stale spec/easycla-ss-m1 base branch and pulled in unrelated commits.

Decision: linuxfoundation/lfx-self-serve#1216 · Follow-ups: linuxfoundation/lfx-self-serve#1224 (EasyCLA) / linuxfoundation/lfx-self-serve#1225 (SS)

🤖 Generated with Claude Code

mlehotskylf and others added 3 commits July 30, 2026 16:09
M1 "read-only My CLAs" spec-kit set and the migration architecture-review
package that grounds it:

- specs/001-easycla-ss-integration-fable/m1-my-cla/ — plan, spec, research,
  data-model, contracts, quickstart, tasks (31), and UI mockups.
- docs/easycla-ss-migration/ — milestone architecture proposal, EasyCLA↔SS
  role-mapping feasibility memo, and the spike runbook M1 references.

Docs only. M1 implementation: linuxfoundation/lfx-self-serve#1203.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Michal Lehotsky <mlehotsky@linuxfoundation.org>
Add P10 documenting the architecture-approved decision to trust an
SS-supplied identity list (azp allow-list + in-handler JWKS verify,
read-only, transitional to M6) rather than re-verify per request,
plus the corresponding trust-boundary risk row and a P3 pointer.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Michal Lehotsky <mlehotsky@linuxfoundation.org>
Eric Searcy confirmed (2026-07-30) that EasyCLA has no NATS transit
pre-M6. It is not merely IP reachability: the auth-service identity
RPC is a request/reply (inbox) subject, so EasyCLA would have to be a
cluster consumer for the reply, over a cross-region us-east-1 ↔
us-west-2 WAN link — and a federated NATS super-cluster is overkill.

This settles the P10 open dependency in favor of the SS payload bridge
+ azp mechanism pre-M6, with EasyCLA calling the RPC directly deferred
to M6. Replaces the stale "pending confirmation from Eric" parenthetical.

Signed-off-by: Michal Lehotsky <mlehotsky@linuxfoundation.org>
Copilot AI review requested due to automatic review settings July 30, 2026 14:25
@coderabbitai

coderabbitai Bot commented Jul 30, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

The PR adds migration architecture and authorization documentation for moving EasyCLA user-facing functionality into LFX Self Serve, plus Milestone 1 specifications for a read-only “My CLAs” experience, including API contracts, research, task planning, mockups, and validation instructions.

Changes

EasyCLA Self Serve migration

Layer / File(s) Summary
Migration architecture and cutover plan
docs/easycla-ss-migration/README.md, docs/easycla-ss-migration/architecture-proposal.md
Defines migration scope, milestones, integration boundaries, identity trust handling, cutover decisions, and documented risks.
Authorization feasibility and dev spikes
docs/easycla-ss-migration/role-mapping-feasibility.md, docs/easycla-ss-migration/spike-runbook.md
Documents gateway and EasyCLA v4 authorization behavior, Self Serve token requirements, endpoint enforcement differences, and dev validation steps.
My CLAs contracts and implementation plan
specs/001-easycla-ss-integration-fable/m1-my-cla/contracts/*, specs/001-easycla-ss-integration-fable/m1-my-cla/research.md, specs/001-easycla-ss-integration-fable/m1-my-cla/tasks.md
Specifies authenticated listing and PDF URL APIs, identity resolution, authorization, status mapping, UI integration, testing, and milestone execution tasks.
My CLAs mockups and quickstart
specs/001-easycla-ss-integration-fable/m1-my-cla/mockups/*, specs/001-easycla-ss-integration-fable/m1-my-cla/quickstart.md
Adds populated and empty-state HTML mockups plus local execution, acceptance verification, and direct API-call instructions.

Estimated code review effort: 2 (Simple) | ~15 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly matches the main doc update: confirming EasyCLA has no NATS transit before M6.
Description check ✅ Passed The description is directly related to the documentation updates and the P10 NATS transit decision.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch docs/p10-nats-transit-confirmed

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 M1 Self Serve migration specifications and records that EasyCLA cannot use NATS before M6.

Changes:

  • Documents M1 architecture, tasks, contracts, and UI mockups.
  • Adds authorization feasibility and spike guidance.
  • Confirms the transitional SS payload bridge and azp trust model.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 12 comments.

Show a summary per file
File Description
tasks.md Defines M1 implementation tasks.
research.md Records M1 technical decisions.
quickstart.md Provides validation instructions.
mockups/README.md Describes UI mockups.
my-clas-populated.html Shows populated CLA view.
my-clas-empty-state.html Shows empty CLA view.
upstream-easycla-api.md Documents EasyCLA APIs.
ss-me-clas-api.md Defines Self Serve API contract.
spike-runbook.md Documents authentication spikes.
role-mapping-feasibility.md Analyzes authorization integration.
README.md Indexes architecture materials.
architecture-proposal.md Records P10 NATS decision.
Comments suppressed due to low confidence (2)

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

  • These direct calls exercise the superseded username/signature APIs rather than the merged M1 contract. Update the verification flow to call /v4/my-clas and /v4/my-clas/{signatureID}/pdf with the same complete session-derived identity parameters that SS forwards; otherwise this quickstart does not validate the implementation being shipped.
# identity
curl -H "Authorization: Bearer $TOK" "$GW/cla-service/v3/users/username/<lf-username>"
# agreements
curl -H "Authorization: Bearer $TOK" "$GW/cla-service/v4/signatures/user/<userID>"
# pdf url
curl -H "Authorization: Bearer $TOK" "$GW/cla-service/v4/signatures/<signatureID>/signed-document"

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

  • The acceptance check compares against the superseded per-user endpoint. Since M1 now uses the consolidated API, the expected list should be compared with /v4/my-clas using the same session-derived identity parameters; otherwise the check bypasses EasyCLA's aggregation and validity logic.
| US1-AS1: ICLAs listed + PDF works | Click Download PDF → browser gets S3 URL, file opens; compare list against `GET /v4/signatures/user/{userID}` called directly with a dev token |

Comment on lines +43 to +47
- [ ] T007 Add `GET /v4/users/by-identity` to CLA `swagger/cla.v2.yaml` (query params: `lfUsername`, repeated `email`, repeated `githubId`; response: array of existing v2 user models, deduped) and run `make swagger` to regenerate `gen/` (never hand-edit `gen/`). License header on any new file.
- [ ] T008 Implement the service method in CLA `v2/users/` (or extend the existing users service per module pattern): union `GetUserByLFUserName` + per-email `GetUserByEmail`/`user_emails` match + per-githubId `GetUserByGitHubID`, reusing the existing GSI-backed repository methods in `users/repository.go` (`lf-username-index`, `lf-email-index`, `github-id-index` — githubId must stay **N-typed** or the GSI misses); dedupe by `user_id`. Unit tests for union/dedupe/empty-input in the same package.
- [ ] T009 Wire the swagger-generated operation in the module's `handlers.go` `Configure(...)` (request/response translation only, per three-layer convention); register in `cmd/server.go` alongside the other v2 modules. Verify the path is on the **secured** router (gateway `cla-service.yaml` prefix rules) — it must NOT land on the public router; note in `contracts/upstream-easycla-api.md` that SS remains the authorization boundary.
- [ ] T010 Run CLA `make fmt && make build-mac && make test && make lint`; open the PR against `dev` with DCO signoff; after merge, verify the endpoint on dev via curl (quickstart-style call) and record the verified request/response in `contracts/upstream-easycla-api.md`.
- [ ] T010a **Add `projectName` to the signature response** (research R6 decision, 2026-07-28): add a `projectName` string to `swagger/common/signature.yaml`, `make swagger`, and populate it in the `/v4/signatures/user/{userID}` converter from the already-loaded CLA group (`claGroup.ProjectName`, cf. `v2/signatures/service.go:399,403,417`). Bundle with the T007–T010 PR. Closes the SS `projectName`-shows-ID gap; SS then maps `EasyClaSignature.projectName` straight through in `toMyClaAgreement` (drop the `projectID` fallback).
Comment on lines +17 to +20
**Decision**: resolve server-side in SS using **three keys, unioned**:
1. **LF username** — `GET /v3/users/username/{userName}` (handler `users/handlers.go:198`; GSI `lf-username-index`).
2. **Verified emails** — all verified emails on the LF identity (session claims, enriched via `lfx-v2-auth-service` NATS lookup which SS already uses); matched against `lf_email` and `user_emails`.
3. **Linked GitHub account(s)** — SS/Auth0 supports linking GitHub to the LF identity (existing social-connection flow, `social-verification.service.ts`, NATS `user_identity.link`); the linked identity provides the GitHub numeric ID + username. GitHub-derived EasyCLA records (typically missing `lf_username`) are keyed on exactly this — it is the **highest-precision key** for pre-LF-login history. Prefer the immutable numeric `github_id` over username (renames/recycling). **Verified in SS**: nothing is persisted in SS itself — Auth0 stores the linked identity, whose `user_id` is GitHub's numeric ID (`Auth0Identity.user_id`, `packages/shared/src/interfaces/profile.interface.ts:520`; username only in `profileData.nickname`), and `Auth0Service.getUserIdentities()` already fetches identities server-side via NATS auth-service. Spike check: confirm the auth-service returns the bare numeric ID (not a `github|<id>`-prefixed form) — a mismatched key silently returns zero matches, so cover with a fixture test.

**GitHub ID storage (verified — no new storage needed)**: `user_github_id` is already stored on the users table as a DynamoDB **Number** with GSI `github-id-index` (`users/repository.go:103-105`, `:1046`). It is populated on exactly the records M1 needs: the console's GitHub OAuth get-or-create writes it N-typed (`cla-backend-legacy/internal/api/github_oauth.go:282,306`), and the employee-signature precheck backfills missing id↔username pairs via GitHub API lookups (`cla-backend-legacy/internal/api/handlers.go:8854-8884`). Caveats: very old records may be username-only (treat username matches as hints, numeric ID as authority); any new endpoint must reuse the existing repository methods — the GSI hash key is N-typed and an S-typed write/query misses the index (documented in the backfill code).

**Upstream API gap (verified — changes the contingency assessment)**: the GSI-backed lookups all exist server-side (`lf-username-index`, `lf-email-index`, `github-id-index` in `users/repository.go`), but **`GetUserByGitHubID`/`GetUserByGitHubUsername` are not exposed over HTTP**, and the only generic search that is (`GET /v3/users/search`) performs a **DynamoDB table scan** with a filter expression (`users/repository.go:1279`) — unsuitable for per-request resolution. Therefore the previously-contingent EasyCLA endpoint is now **expected to be required**: `GET /v4/users/by-identity?lfUsername=…&email=…&githubId=…` (one small read endpoint wrapping the existing GSI queries; swagger-first; no schema changes). See `contracts/upstream-easycla-api.md`.
## 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).
```

1. Log in with the test user.
2. Open **Me lens → My CLAs** (`/me/clas`).

## 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.

- [ ] T013 [P] [US1] Unit tests for pure logic in `server/services/__tests__/cla.service.spec.ts` (repo test convention): ICLA/ECLA classification per data-model.md rule (`type=cla & referenceType=user`, `cclaCompanyID` set ⇒ ECLA); status derivation per R6 (signed+approved ⇒ valid; signed+!approved ⇒ "no longer valid"; !signed excluded/labeled; superseded only if document version available per T004); multi-record merge + dedupe by `signatureID`; ECLA-invalid filtering; sort by `signedOn` desc. Use T004 fixtures.
- [ ] T014 [P] [US1] Unit tests for identity resolution in the same suite: union of username/email/githubId matches; GitHub-ID parsing per T003 outcome (fixture test for the prefixed-vs-bare form); no-match ⇒ empty `easyclaUserIds` + `unmatched=true`; no linked GitHub identity ⇒ `githubLinked=false`. Mock the upstream client and (per T002 outcome) the token source.
- [ ] T015 [P] [US1] Route/controller tests in `server/routes/__tests__/clas.route.spec.ts`: 401 without session; userID derived **only** from session (a request supplying user IDs is ignored); `GET /api/me/clas/:signatureId/pdf-url` returns **404** (never 403) for unknown, not-owned, and ECLA signature IDs; 502 `{ code: "UPSTREAM_ERROR" }` on upstream failure; flag off ⇒ 404 on both routes.
```

- **Behavior**: ICLAs listed in any status with labels; ECLAs only when valid; sorted `signedOn` desc; empty `agreements` + `identity.unmatched=true` drives the "no CLA history found for your account" empty state.
- **GitHub-link CTA**: when `identity.githubLinked=false` (no GitHub account linked to the LF identity), the UI shows "Don't see your CLAs? Link your GitHub account" pointing into SS's existing identity-linking flow (`/social/callback` social-connection pattern); on return, the page re-fetches and resolution now includes the linked GitHub ID (research R2).
Issues a short-lived download URL for a signed ICLA PDF.

- **Auth**: session required.
- **Guard**: `signatureId` MUST be an ICLA belonging to the session's resolved agreement set (server re-fetches/uses per-request resolution — 404 otherwise; never 403, to avoid existence oracle).
Comment on lines +145 to +149
<tr>
<th>Project</th>
<th>Type</th>
<th>Signed</th>
<th>Document</th>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 10

🧹 Nitpick comments (1)
specs/001-easycla-ss-integration-fable/m1-my-cla/tasks.md (1)

66-66: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Base classification tests on the authoritative claType field.

Research says claType is authoritative and the legacy cclaCompanyID rule is fallback, but T013 specifies only the old rule. Add explicit icla, ecla, and ccla cases plus fallback coverage.

🤖 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 `@specs/001-easycla-ss-integration-fable/m1-my-cla/tasks.md` at line 66, Update
the T013 unit-test task description to make claType the authoritative
classification field, adding explicit icla, ecla, and ccla cases and coverage
for the legacy cclaCompanyID fallback when claType is unavailable. Preserve the
existing classification, status, merge, filtering, and sorting test
requirements.
🤖 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 `@docs/easycla-ss-migration/spike-runbook.md`:
- Line 41: Update the refresh-token instructions in the runbook to prohibit
retrieving tokens from debug logs, and recommend only controlled session-store
access or the authorization-code+PKCE flow. State that logs must redact tokens
and that any test tokens used for the spike must be revoked or rotated
afterward.
- Line 36: Update the JWT inspection command in the runbook to decode the
payload with a base64url-safe decoder instead of plain base64. Also make the
TOKEN fetch fail closed by validating that the exchange succeeds and returns a
non-empty token before proceeding to claim inspection.

In
`@specs/001-easycla-ss-integration-fable/m1-my-cla/contracts/ss-me-clas-api.md`:
- Line 39: Update the GitHub-link CTA contract in the identity resolution
documentation to use the implemented user-facing route `/profile/identities`
instead of `/social/callback`, and keep the surrounding return and re-fetch
behavior unchanged.
- Around line 51-53: Choose and document one feature-flag enforcement model
across all three sites: either revise the API contract to specify Angular-only
gating or require server-side route gating. Update research.md to describe the
same behavior, and align T015/T018 in tasks.md with the selected model,
including the corresponding route-test expectations.

In
`@specs/001-easycla-ss-integration-fable/m1-my-cla/contracts/upstream-easycla-api.md`:
- Line 1: The M1 documentation uses conflicting EasyCLA identity-resolution and
authorization contracts; establish one authoritative endpoint and flow. In
specs/001-easycla-ss-integration-fable/m1-my-cla/contracts/upstream-easycla-api.md:1,
rewrite the contract for the current endpoints or explicitly mark old sections
legacy; in docs/easycla-ss-migration/architecture-proposal.md:94, state whether
P10 is the M1 contract or a later transition; update R2 in
specs/001-easycla-ss-integration-fable/m1-my-cla/research.md:17-30, scope
T007–T010a in specs/001-easycla-ss-integration-fable/m1-my-cla/tasks.md:43-47,
revise the userID read-path analysis in
docs/easycla-ss-migration/role-mapping-feasibility.md:112-118, target the
authoritative endpoint in docs/easycla-ss-migration/spike-runbook.md:61-68, and
align acceptance checks and direct calls in
specs/001-easycla-ss-integration-fable/m1-my-cla/quickstart.md:26-42.

In
`@specs/001-easycla-ss-integration-fable/m1-my-cla/mockups/my-clas-populated.html`:
- Around line 144-199: Reorder the sample rows in the populated CLA table so
their signed dates follow the documented signedOn descending order, placing the
2024 CDM entry before the 2023 FDC3 entry and continuing in descending order for
all rows. Update the row ordering around the table’s project entries without
changing their displayed content.

In `@specs/001-easycla-ss-integration-fable/m1-my-cla/quickstart.md`:
- Around line 5-20: Update the quickstart configuration prerequisites to remove
CLA_SERVICE_BASE_URL and document API_GW_AUDIENCE instead, using the implemented
authentication/API gateway configuration. In the Run steps, replace the /me/clas
URL and “Me lens” reference with the Profile-tab route profile/clas, while
preserving the existing expected CLA results.
- Around line 34-42: Define or source the GW shell variable before the “Useful
direct calls (dev, with token)” curl snippets in quickstart.md, using the
appropriate development gateway value so $GW expands to a valid host when the
examples are copied.

In `@specs/001-easycla-ss-integration-fable/m1-my-cla/tasks.md`:
- Around line 26-33: Keep the M1 release checkpoint blocked until T001 and T002
are completed with deployed-dev token and role-less-user results recorded in
research.md R3; in specs/001-easycla-ss-integration-fable/m1-my-cla/research.md
lines 38-43, add those results. In tasks.md line 72, distinguish completed
username-only work from the unresolved production path, and at line 90 require
completion of the remaining telemetry, component, E2E, and aggregation tasks
before marking US1 or the release gate complete.
- Around line 106-110: Update the dependency and ownership map in tasks.md to
include T010a alongside T007–T010, including the Phase 2 chain and the
cross-repo note identifying cla-backend-go work. Ensure T010a’s projectName
response work is represented in the upstream release scope.

---

Nitpick comments:
In `@specs/001-easycla-ss-integration-fable/m1-my-cla/tasks.md`:
- Line 66: Update the T013 unit-test task description to make claType the
authoritative classification field, adding explicit icla, ecla, and ccla cases
and coverage for the legacy cclaCompanyID fallback when claType is unavailable.
Preserve the existing classification, status, merge, filtering, and sorting test
requirements.
🪄 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: b7b24d61-0d86-4309-ad83-030f37e500f1

📥 Commits

Reviewing files that changed from the base of the PR and between 22867ae and 29e15da.

📒 Files selected for processing (12)
  • 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/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/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/quickstart.md
  • specs/001-easycla-ss-integration-fable/m1-my-cla/research.md
  • specs/001-easycla-ss-integration-fable/m1-my-cla/tasks.md

--data-urlencode "audience=$AUDIENCE" \
| jq -r .access_token)

echo "$TOKEN" | cut -d. -f2 | base64 -d 2>/dev/null | jq . # inspect claims

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

TOKEN="$(curl ... | jq -er '.access_token')"
PAYLOAD="$(printf '%s' "$TOKEN" | cut -d. -f2)"

python - "$PAYLOAD" <<'PY'
import base64
import json
import sys

part = sys.argv[1]
part += "=" * ((4 - len(part) % 4) % 4)
print(json.dumps(json.loads(base64.urlsafe_b64decode(part)), indent=2))
PY

Repository: linuxfoundation/easycla

Length of output: 533


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

file="docs/easycla-ss-migration/spike-runbook.md"

echo "== line count =="
wc -l "$file"

echo
echo "== relevant sections =="
sed -n '1,120p' "$file" | cat -n

Repository: linuxfoundation/easycla

Length of output: 6552


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

python3 - <<'PY'
import base64, subprocess, textwrap, json, os, tempfile, sys

samples = {
    # URL-safe alphabet, no padding
    "urlsafe_no_padding": "eyJmb28iOiJiYXIifQ",
    # URL-safe alphabet with characters that differ from standard base64
    "urlsafe_chars": "eyJfIjoiLSJ9",  # {"_":"-"} in base64url form
    # Standard base64 with padding, for comparison
    "standard_padded": base64.b64encode(b'{"foo":"bar"}').decode(),
}

for name, s in samples.items():
    print(f"\n== {name} ==")
    print("input:", s)
    p = subprocess.run(
        ["bash", "-lc", f"printf '%s' '{s}' | base64 -d 2>&1"],
        capture_output=True,
        text=True,
    )
    print("base64 -d rc:", p.returncode)
    print("base64 -d out:", p.stdout.strip())
    print("base64 -d err:", p.stderr.strip())

    # show equivalent urlsafe decode in Python
    pad = s + "=" * ((4 - len(s) % 4) % 4)
    try:
        decoded = base64.urlsafe_b64decode(pad)
        print("urlsafe decoded:", decoded.decode("utf-8", "replace"))
    except Exception as e:
        print("urlsafe decode error:", e)
PY

Repository: linuxfoundation/easycla

Length of output: 594


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

python3 - <<'PY'
import base64, subprocess

samples = {
    "urlsafe_no_padding": "eyJmb28iOiJiYXIifQ",
    "urlsafe_chars": "eyJfIjoiLSJ9",
    "standard_padded": base64.b64encode(b'{"foo":"bar"}').decode(),
}

for name, s in samples.items():
    print(f"\n== {name} ==")
    print("input:", s)
    p = subprocess.run(
        ["bash", "-lc", f"printf '%s' '{s}' | base64 -d 2>&1"],
        capture_output=True,
        text=True,
    )
    print("base64 -d rc:", p.returncode)
    print("base64 -d out:", p.stdout.strip())
    print("base64 -d err:", p.stderr.strip())

    pad = s + "=" * ((4 - len(s) % 4) % 4)
    try:
        decoded = base64.urlsafe_b64decode(pad)
        print("urlsafe decoded:", decoded.decode("utf-8", "replace"))
    except Exception as e:
        print("urlsafe decode error:", e)
PY

Repository: linuxfoundation/easycla

Length of output: 594


Use a base64url-safe decoder and guard the token fetch. base64 -d is brittle for JWT payloads, and the current TOKEN=$(...) step can leave an empty token after a bad exchange unless the command fails closed.

🤖 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 `@docs/easycla-ss-migration/spike-runbook.md` at line 36, Update the JWT
inspection command in the runbook to decode the payload with a base64url-safe
decoder instead of plain base64. Also make the TOKEN fetch fail closed by
validating that the exchange succeeds and returns a non-empty token before
proceeding to claim inspection.


**Checkpoint (this is spike 1's core):** the decoded token must contain `http://lfx.dev/claims/username`. If it's present, Auth0 is granting the api-gw audience to this client and stamping the claim the gateway needs — spike 1 passes. If the exchange returns an error (e.g. `invalid_grant`, `access_denied`, or unauthorized audience), spike 1 has found the gap: the SS Auth0 client isn't authorized for that audience in dev — that's an Auth0 client-grant config item, not a code change.

> Getting a refresh token: easiest is to pull it from a live dev SS session (`req.appSession.refresh_token`) — log into dev SS, grab it from the session store / a debug log. Alternatively run a one-off authorization-code+PKCE login against the dev client with `scope=openid offline_access`. Either way the token must carry `offline_access`.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Never retrieve refresh tokens from debug logs.

A refresh token is a bearer credential. Recommending that operators copy it from a debug log creates a credential-disclosure path; use controlled session-store access, redact logs, and revoke or rotate test tokens after the spike.

🤖 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 `@docs/easycla-ss-migration/spike-runbook.md` at line 41, Update the
refresh-token instructions in the runbook to prohibit retrieving tokens from
debug logs, and recommend only controlled session-store access or the
authorization-code+PKCE flow. State that logs must redact tokens and that any
test tokens used for the spike must be revoked or rotated afterward.

```

- **Behavior**: ICLAs listed in any status with labels; ECLAs only when valid; sorted `signedOn` desc; empty `agreements` + `identity.unmatched=true` drives the "no CLA history found for your account" empty state.
- **GitHub-link CTA**: when `identity.githubLinked=false` (no GitHub account linked to the LF identity), the UI shows "Don't see your CLAs? Link your GitHub account" pointing into SS's existing identity-linking flow (`/social/callback` social-connection pattern); on return, the page re-fetches and resolution now includes the linked GitHub ID (research R2).

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Point the identity-link CTA at the implemented route.

The contract references /social/callback, while the implementation notes and tasks use /profile/identities. Confirm the user-facing entry point and document it consistently; otherwise the recovery flow may dead-end.

🤖 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 `@specs/001-easycla-ss-integration-fable/m1-my-cla/contracts/ss-me-clas-api.md`
at line 39, Update the GitHub-link CTA contract in the identity resolution
documentation to use the implemented user-facing route `/profile/identities`
instead of `/social/callback`, and keep the surrounding return and re-fetch
behavior unchanged.

Comment on lines +51 to +53
## 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.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Choose one feature-flag enforcement model.

The contract promises route-level 404s, while the implementation notes and tasks specify Angular-only gating. This affects both runtime behavior and the required route tests.

  • specs/001-easycla-ss-integration-fable/m1-my-cla/contracts/ss-me-clas-api.md#L51-L53: change the contract to Angular-only behavior, or require server-side gating.
  • specs/001-easycla-ss-integration-fable/m1-my-cla/research.md#L62-L68: make the implementation note match the chosen behavior.
  • specs/001-easycla-ss-integration-fable/m1-my-cla/tasks.md#L74-L74: align T015/T018 with that decision.
📍 Affects 3 files
  • specs/001-easycla-ss-integration-fable/m1-my-cla/contracts/ss-me-clas-api.md#L51-L53 (this comment)
  • specs/001-easycla-ss-integration-fable/m1-my-cla/research.md#L62-L68
  • specs/001-easycla-ss-integration-fable/m1-my-cla/tasks.md#L74-L74
🤖 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 `@specs/001-easycla-ss-integration-fable/m1-my-cla/contracts/ss-me-clas-api.md`
around lines 51 - 53, Choose and document one feature-flag enforcement model
across all three sites: either revise the API contract to specify Angular-only
gating or require server-side route gating. Update research.md to describe the
same behavior, and align T015/T018 in tasks.md with the selected model,
including the corresponding route-test expectations.

@@ -1,4 +1,4 @@
# Contract: EasyCLA endpoints consumed by M1
# Contract: EasyCLA endpoints consumed by M1 (existing APIs — no changes)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Reconcile the M1 API and authorization model before implementation.

The documents simultaneously describe P10’s trusted identity-list/consolidated flow and the older client-side by-identity plus per-user signature flow. They must identify one authoritative contract.

  • specs/001-easycla-ss-integration-fable/m1-my-cla/contracts/upstream-easycla-api.md#L1-L1: rewrite the contract around the current endpoints, or label the old sections as legacy.
  • docs/easycla-ss-migration/architecture-proposal.md#L94-L94: state whether P10 is the M1 contract or a later transition.
  • specs/001-easycla-ss-integration-fable/m1-my-cla/research.md#L17-L30: update R2’s identity-resolution decision and rationale.
  • specs/001-easycla-ss-integration-fable/m1-my-cla/tasks.md#L43-L47: replace or explicitly legacy-scope T007–T010a.
  • docs/easycla-ss-migration/role-mapping-feasibility.md#L112-L118: mark the userID flow as historical or update the read-path analysis.
  • docs/easycla-ss-migration/spike-runbook.md#L61-L68: run the spike against the authoritative endpoint.
  • specs/001-easycla-ss-integration-fable/m1-my-cla/quickstart.md#L26-L42: update acceptance checks and direct calls.
📍 Affects 7 files
  • specs/001-easycla-ss-integration-fable/m1-my-cla/contracts/upstream-easycla-api.md#L1-L1 (this comment)
  • docs/easycla-ss-migration/architecture-proposal.md#L94-L94
  • specs/001-easycla-ss-integration-fable/m1-my-cla/research.md#L17-L30
  • specs/001-easycla-ss-integration-fable/m1-my-cla/tasks.md#L43-L47
  • docs/easycla-ss-migration/role-mapping-feasibility.md#L112-L118
  • docs/easycla-ss-migration/spike-runbook.md#L61-L68
  • specs/001-easycla-ss-integration-fable/m1-my-cla/quickstart.md#L26-L42
🤖 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
`@specs/001-easycla-ss-integration-fable/m1-my-cla/contracts/upstream-easycla-api.md`
at line 1, The M1 documentation uses conflicting EasyCLA identity-resolution and
authorization contracts; establish one authoritative endpoint and flow. In
specs/001-easycla-ss-integration-fable/m1-my-cla/contracts/upstream-easycla-api.md:1,
rewrite the contract for the current endpoints or explicitly mark old sections
legacy; in docs/easycla-ss-migration/architecture-proposal.md:94, state whether
P10 is the M1 contract or a later transition; update R2 in
specs/001-easycla-ss-integration-fable/m1-my-cla/research.md:17-30, scope
T007–T010a in specs/001-easycla-ss-integration-fable/m1-my-cla/tasks.md:43-47,
revise the userID read-path analysis in
docs/easycla-ss-migration/role-mapping-feasibility.md:112-118, target the
authoritative endpoint in docs/easycla-ss-migration/spike-runbook.md:61-68, and
align acceptance checks and direct calls in
specs/001-easycla-ss-integration-fable/m1-my-cla/quickstart.md:26-42.

Comment on lines +144 to +199
<table class="clatable">
<tr>
<th>Project</th>
<th>Type</th>
<th>Signed</th>
<th>Document</th>
</tr>
<tr>
<td>
<div class="projcell"><div class="projicon"></div>
<div><div class="projname">Linux Foundation</div><div class="projsub">Linux Foundation</div></div>
</div>
</td>
<td><span class="typepill icla">ICLA</span></td>
<td>Jul 15, 2019</td>
<td><a class="doclink" href="#">⬇ Download PDF</a></td>
</tr>
<tr>
<td>
<div class="projcell"><div class="projicon"></div>
<div><div class="projname">Academy Software Foundation</div><div class="projsub">Academy Software Foundation (ASWF)</div></div>
</div>
</td>
<td><span class="typepill icla">ICLA</span></td>
<td>Feb 2, 2021</td>
<td><a class="doclink" href="#">⬇ Download PDF</a></td>
</tr>
<tr>
<td>
<div class="projcell"><div class="projicon"></div>
<div><div class="projname">Cloud Native Computing Foundation (CNCF)</div><div class="projsub">Cloud Native Computing Foundation (CNCF)</div></div>
</div>
</td>
<td><span class="typepill ecla">ECLA · IBM</span></td>
<td>Sep 10, 2022</td>
<td><span class="docmuted">Covered by Corporate CLA (CCLA)</span></td>
</tr>
<tr>
<td>
<div class="projcell"><div class="projicon"></div>
<div><div class="projname">CDM</div><div class="projsub">FINOS CDM Community Specification License</div></div>
</div>
</td>
<td><span class="typepill icla">ICLA</span></td>
<td>May 6, 2024</td>
<td><a class="doclink" href="#">⬇ Download PDF</a></td>
</tr>
<tr>
<td>
<div class="projcell"><div class="projicon"></div>
<div><div class="projname">FDC3</div><div class="projsub">FDC3</div></div>
</div>
</td>
<td><span class="typepill icla">ICLA</span></td>
<td>Nov 30, 2023</td>
<td><a class="doclink" href="#">⬇ Download PDF</a></td>

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Match the mockup order to the documented sort.

The sample dates are 2019, 2021, 2022, 2024, then 2023, while the contract requires signedOn descending. Reorder the sample rows or label the mockup as illustrative so it does not contradict acceptance checks.

🤖 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
`@specs/001-easycla-ss-integration-fable/m1-my-cla/mockups/my-clas-populated.html`
around lines 144 - 199, Reorder the sample rows in the populated CLA table so
their signed dates follow the documented signedOn descending order, placing the
2024 CDM entry before the 2023 FDC3 entry and continuing in descending order for
all rows. Update the row ordering around the table’s project entries without
changing their displayed content.

Comment on lines +5 to +20
- `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).
- A dev test user with CLA history. To create one: use the dev Contributor Console flow against a dev CLA-gated repo (sign an ICLA; for an ECLA, use a dev company with a signed CCLA and approval-list entry), or pick an existing dev identity from the `cla-dev-signatures` table.
- LaunchDarkly dev flag `my-clas-enabled` (or repo-convention name) turned on for your user.

## Run

```bash
cd lfx-self-serve
pnpm install # or repo-standard package manager
pnpm dev # starts lfx-one with SSR server
```

1. Log in with the test user.
2. Open **Me lens → My CLAs** (`/me/clas`).
3. Expect: ICLA row(s) with status + **Download PDF**; ECLA row(s) with company name and no download; empty state if the account has no history.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Refresh the quickstart to match the implemented route and configuration.

CLA_SERVICE_BASE_URL was dropped, and the UI route is profile/clas, not /me/clas. As written, developers configure a dead env var and open the wrong URL. Document API_GW_AUDIENCE and the Profile-tab route instead.

🤖 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 `@specs/001-easycla-ss-integration-fable/m1-my-cla/quickstart.md` around lines
5 - 20, Update the quickstart configuration prerequisites to remove
CLA_SERVICE_BASE_URL and document API_GW_AUDIENCE instead, using the implemented
authentication/API gateway configuration. In the Run steps, replace the /me/clas
URL and “Me lens” reference with the Profile-tab route profile/clas, while
preserving the existing expected CLA results.

Comment on lines +34 to +42
## Useful direct calls (dev, with token)

```bash
# identity
curl -H "Authorization: Bearer $TOK" "$GW/cla-service/v3/users/username/<lf-username>"
# agreements
curl -H "Authorization: Bearer $TOK" "$GW/cla-service/v4/signatures/user/<userID>"
# pdf url
curl -H "Authorization: Bearer $TOK" "$GW/cla-service/v4/signatures/<signatureID>/signed-document"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Define GW before using the direct-call snippets.

The shell examples interpolate $GW, but this file never assigns it. Copy-pasting them therefore produces an empty host. Add GW=... or source it before these examples.

🤖 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 `@specs/001-easycla-ss-integration-fable/m1-my-cla/quickstart.md` around lines
34 - 42, Define or source the GW shell variable before the “Useful direct calls
(dev, with token)” curl snippets in quickstart.md, using the appropriate
development gateway value so $GW expands to a valid host when the examples are
copied.

Comment on lines +26 to +33
- [ ] T001 Run **spike 1** (SS-minted user token → secured v4 read) exactly per `docs/easycla-ss-migration/spike-runbook.md` steps 1–2 (user A); record token-claims checkpoint result and HTTP status in `specs/001-easycla-ss-integration-fable/m1-my-cla/research.md` R3. If the audience exchange fails, file the Auth0 client-grant config item (auth0-terraform) — that is the fix, not a code change.
- [ ] T002 Run **spike 2** (role-less user → `GET /cla-service/v4/signatures/user/{userID}`) per the runbook (user B). Decision point: **200** ⇒ user-token model confirmed; **403** ⇒ choose between the small ACS policy addition and the M2M fallback (SS server binds session userID itself) and record the decision + rationale in `research.md` R3. Blocks T014.
- [ ] T003 [P] Spike: confirm the GitHub-ID format returned by `Auth0Service.getUserIdentities()` in SS dev — bare numeric ID vs `github|<id>`-prefixed (`Auth0Identity.user_id`, SS `packages/shared/src/interfaces/profile.interface.ts`). Record in `research.md` R2; the parsing rule feeds T016/T018 fixtures (a mismatched key silently returns zero matches).
- [ ] T004 [P] Spike: curl dev `GET /cla-service/v4/signatures/user/{userID}` and `GET /cla-service/v4/signatures/{signatureID}/signed-document` for a known test user (quickstart "Useful direct calls"); capture raw JSON responses as fixtures into SS `apps/lfx-one/src/server/services/__fixtures__/cla/` (or repo-convention fixture location). Verify which fields the v2 model actually exposes: document major/minor version (R6 superseded detection), `signedOn`, company name/ID, `signed`/`approved`. Record field availability in `research.md` R6; if document version is absent, the superseded badge is dropped per R6.
- [ ] T005 [P] Audit the T004 fixture payloads for v1 user-service/org-service IDs per architecture-proposal P9 (company references on ECLA rows are the likely spot); note in `research.md` which display fields depend on v1 IDs and the planned lookup (`lfx.lookup_v1_user_sfid.by_username`/`.by_email` NATS RPCs) or confirm none are needed for M1's read-only display.
- [ ] T006 Confirm with the EasyCLA team that `GET /v4/users/by-identity` will be accepted (contract `contracts/upstream-easycla-api.md` §1) and agree on the LaunchDarkly flag name per SS repo convention (plan says `my-clas-enabled`, name TBD); create the dev flag. Record final endpoint shape + flag name in the contracts/plan.

**Checkpoint**: token model decided (T002), fixtures captured (T004), upstream endpoint agreed (T006).

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift

Do not declare the M1 release gate complete while auth and acceptance work remain open.

The auth spikes are unchecked and inconclusive, while the task list marks implementation complete and calls US1 fully functional.

  • specs/001-easycla-ss-integration-fable/m1-my-cla/tasks.md#L26-L33: keep the checkpoint blocked until T001/T002 results are recorded.
  • specs/001-easycla-ss-integration-fable/m1-my-cla/research.md#L38-L43: record deployed-dev token and role-less-user results.
  • specs/001-easycla-ss-integration-fable/m1-my-cla/tasks.md#L72-L72: split completed username-only work from the unresolved production path.
  • specs/001-easycla-ss-integration-fable/m1-my-cla/tasks.md#L90-L90: require the remaining telemetry, component, E2E, and aggregation tasks before claiming completion.
🧰 Tools
🪛 LanguageTool

[uncategorized] ~28-~28: The official name of this software platform is spelled with a capital “H”.
Context: ...ities()in SS dev — bare numeric ID vsgithub|-prefixed (Auth0Identity.user_id`...

(GITHUB)

📍 Affects 2 files
  • specs/001-easycla-ss-integration-fable/m1-my-cla/tasks.md#L26-L33 (this comment)
  • specs/001-easycla-ss-integration-fable/m1-my-cla/research.md#L38-L43
  • specs/001-easycla-ss-integration-fable/m1-my-cla/tasks.md#L72-L72
  • specs/001-easycla-ss-integration-fable/m1-my-cla/tasks.md#L90-L90
🤖 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 `@specs/001-easycla-ss-integration-fable/m1-my-cla/tasks.md` around lines 26 -
33, Keep the M1 release checkpoint blocked until T001 and T002 are completed
with deployed-dev token and role-less-user results recorded in research.md R3;
in specs/001-easycla-ss-integration-fable/m1-my-cla/research.md lines 38-43, add
those results. In tasks.md line 72, distinguish completed username-only work
from the unresolved production path, and at line 90 require completion of the
remaining telemetry, component, E2E, and aggregation tasks before marking US1 or
the release gate complete.

Comment on lines +106 to +110
- **Phase 2**: T007 → T008 → T009 → T010 (swagger-first chain, CLA repo); T011/T012 parallel with all of it (SS repo). T002 gates T016's token wiring; T004 gates T013's fixtures.
- **Phase 3 (US1)**: T013/T014/T015 first (tests, parallel) → T016 → T017 → T018 → T019 (server chain); T020/T021 parallel with the server chain once T012 exists → T022 → T023 → T024; T025/T026 last (need dev deployment of T010's endpoint for full resolution; T025 can run with username-only resolution earlier).
- **Phase 4**: after US1 checkpoint; T027/T028 parallel.

Cross-repo note: only T007–T010 (+T028) touch `cla-backend-go`; everything else is `lfx-self-serve`. The SS work does not hard-block on T010 — username-only resolution via `/v3/users/username/{userName}` is the interim path, with full three-key resolution switched on when the endpoint lands.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

Include T010a in the dependency and ownership map.

T010a edits cla-backend-go, but the dependency chain and cross-repo note mention only T007–T010. Add T010a to both, or the projectName response work can be omitted from the upstream release.

🤖 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 `@specs/001-easycla-ss-integration-fable/m1-my-cla/tasks.md` around lines 106 -
110, Update the dependency and ownership map in tasks.md to include T010a
alongside T007–T010, including the Phase 2 chain and the cross-repo note
identifying cla-backend-go work. Ensure T010a’s projectName response work is
represented in the upstream release scope.

@mlehotskylf

Copy link
Copy Markdown
Collaborator Author

Closing as redundant — #5124 already contained the M1 spec docs + P10 trust-SS decision; the only delta this PR added (the NATS-transit-confirmed update in architecture-proposal.md) has been cherry-picked onto #5124's branch directly.

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