Skip to content

Sync with upstream - #17

Merged
ArtyomSavchenko merged 6 commits into
developfrom
sync-uptrace-27-jul
Jul 27, 2026
Merged

Sync with upstream#17
ArtyomSavchenko merged 6 commits into
developfrom
sync-uptrace-27-jul

Conversation

@ArtyomSavchenko

Copy link
Copy Markdown
Member

No description provided.

ArtyomSavchenko and others added 6 commits July 20, 2026 19:40
* Fix workspace check

Signed-off-by: Artyom Savchenko <armisav@gmail.com>

* Fix workspace validation

Signed-off-by: Artyom Savchenko <armisav@gmail.com>

---------

Signed-off-by: Artyom Savchenko <armisav@gmail.com>
…(#10990)

Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com>
…(#10995)

* fix(github): honour the force flag in checkRefreshToken

`checkRefreshToken` accepts a `force` parameter but never reads it, so the
only caller that passes `force = true` (worker.ts, when re-syncing a user)
behaves exactly like the non-forced call and skips the refresh entirely.

Gate the refresh on `force || expired` instead of on expiry alone. As a
side effect a record with a `refreshToken` but a null `expiresIn` is now
validated when forced, instead of being reported as valid unchecked.

Signed-off-by: koreanjoker <namug014@gmail.com>

* fix(github): return undefined from getOctokit when the token is dead

When `checkRefreshToken` reports failure, `getOctokit` cleared
`record.octokit` and then fell straight through to constructing a new
Octokit from the very token that was just rejected. The method therefore
never returned `undefined` for a revoked user, so the
`(await getOctokit(...)) ?? container.container.octokit` installation-token
fallback that the sync code already writes at 13 call sites was
unreachable.

Return `undefined` after clearing the client so the existing fallback can
take effect.

Signed-off-by: koreanjoker <namug014@gmail.com>

* fix(github): preserve accounts when deserialising a user secret

`updateUser` serialises the whole `GithubUserRecord` — `accounts`
included — into the integration secret, but `secretToUserRecord` placed a
literal `accounts: {}` after the spread of the parsed payload, discarding
whatever was stored.

Every consumer of a record loaded through `getAccount` therefore saw an
empty map. `revokeUserAuth` iterates `Object.entries(record.accounts)`, so
its body never ran and the re-authorisation notice was never written to
any workspace.

Read `accounts` back from the parsed payload, keeping `{}` as the fallback
for records written before the field existed.

Signed-off-by: koreanjoker <namug014@gmail.com>

---------

Signed-off-by: koreanjoker <namug014@gmail.com>
…ons (#10997)

* fix(account): authorize mergeSpecifiedPersons / canMergeSpecifiedPersons

Both operations decoded the caller token and discarded the result, so any
authenticated caller could merge any two persons by uuid. Merging re-points
the secondary person's social ids onto the primary one, and neither login
nor password recovery require a social id to be verified, so this reached
as far as taking over an arbitrary account.

Authorize both behind verifyMergePersonsAuthority:

- global admin tokens and the tool/workspace services pass, matching the
  account level mergeSpecifiedAccounts;
- everybody else must maintain the workspace their token carries, and both
  persons must be within its reach: a person holding an account elsewhere,
  and the platform wide system and guest accounts, are refused;
- a login capable social id may not move onto an account the caller does
  not own. doMergePersons only refuses verified secondary social ids, which
  leaves the unverified ones a maintainer could mint for themselves.

canMergeSpecifiedPersons answers false instead of throwing: it is the
predicate the merge dialog polls, and it awaits it without a catch.

Claude-Session: https://claude.ai/code/session_01ANdoXbdn5k2hZy734EwKe7
Signed-off-by: Don Kendall <dkendall@ledoweb.com>

* test(account): cover merge persons authorization

Nineteen cases over both operations: the reported attack shape, the
maintainer to owner escalation through an unverified email, foreign
accounts on either side of the merge, the platform guest account, and the
paths that must keep working (workspace contacts, members, tool service
and admin tokens). Removing the authorization check fails eight of them.

Claude-Session: https://claude.ai/code/session_01ANdoXbdn5k2hZy734EwKe7
Signed-off-by: Don Kendall <dkendall@ledoweb.com>

---------

Signed-off-by: Don Kendall <dkendall@ledoweb.com>
* Clean up commented tools

Signed-off-by: Artyom Savchenko <armisav@gmail.com>

* Clean up

Signed-off-by: Artyom Savchenko <armisav@gmail.com>

---------

Signed-off-by: Artyom Savchenko <armisav@gmail.com>
@ArtyomSavchenko ArtyomSavchenko changed the title Sync uptrace 27 jul Sync with upstream Jul 27, 2026
@ArtyomSavchenko
ArtyomSavchenko merged commit 62220e4 into develop Jul 27, 2026
18 checks passed
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.

4 participants