Server-side internal flow — no public API change:
- On OAuth2 authorization_code exchange for tstudio-cli app, server
creates a "cursor" PAT with all scopes via direct DB access
- PAT returned as cursor_token field in the token response
- CLI reads it and displays Cursor/DeepSeek setup instructions
- Only created on first login (skipped if "cursor" PAT already exists)
- Token shown once — user must save it
Keeps reqBasicOrRevProxyAuth on public /users/{username}/tokens endpoint.
No token escalation risk — PAT creation is server-internal only.
Also: Bearer auth fix for OAuth2 JWT tokens in CLI API client.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Removed auto PAT creation (Gitea blocks token-from-token)
- Login now opens token creation page on first login
- Shows Cursor/DeepSeek setup instructions inline
- Prints tstudio version in completion message
- Bearer auth fix for OAuth2 JWT tokens
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Login flow now:
1. Browser OAuth2 → JWT access token
2. SSH key gen + git credentials
3. Auto-creates a PAT named cursor-<hostname> for Cursor/DeepSeek
4. Displays the PAT with Cursor setup instructions (shown once)
Fixed: API client now sends Bearer prefix for OAuth2 JWT tokens
(was sending "token" prefix which Gitea rejects for JWTs).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Browser OAuth2 PKCE login confirmed working on tinqs.com.
Removed --token fallback — browser login only.
Updated built-in app ID to match registered app.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- cmd/tea: rename references from tea/tinqs to tstudio
- public/assets/img: replace logos and favicons with Tinqs Studio branding
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Download grid for all platforms with direct S3 links
- Copy-paste prompt block for Cursor / Claude Code agents
- Covers: install, login, migrate remotes, verify
- Login: added --token flag for bootstrap/CI (skip browser flow)
- Page is public (no login required): /cli/getting-started
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Login rewritten to use OAuth2 PKCE browser flow:
- Opens browser → user authenticates on tinqs.com → callback to localhost
- No passwords in terminal, same UX as gcloud/gh auth login
- PKCE (RFC 7636) with S256 code challenge
- Stores refresh_token for silent token renewal
- Logout clears git credentials
Server-side:
- Registered tstudio-cli as built-in OAuth2 app (models/auth/oauth2.go)
- Added to default applications list (modules/setting/oauth2.go)
- New /cli/getting-started route + public onboarding page
- Teaches Cursor setup, agent workflow, git operations
First login redirects to getting-started page automatically.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Removed separate TSTUDIO_VERSION — tstudio now shares GITEA_VERSION
with the rest of the monorepo (one version for everything)
- Auto-update check runs on every command (max once/hour, 3s timeout)
prints one-line notice if newer binary exists on S3
- Version injected via ldflags at build time (default "dev" for local builds)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Binary detects it's not on PATH, copies itself to the right location
(%LOCALAPPDATA%\tstudio\ on Windows, /usr/local/bin on macOS/Linux),
and adds to user PATH. Landing page install commands now download + login
in one step.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Login now does full machine setup in one command:
- Creates API token
- Generates ed25519 SSH key + registers it with Gitea
- Configures ~/.ssh/config for ssh.tinqs.com
- Sets up HTTPS credential helper + SSH→HTTPS rewrite
New commands:
- tstudio migrate: rewrites old git.arikigame.com remotes to tinqs.com
- SETUP.md: agent-executable setup guide for any machine
No more separate tokens for bot/cursor/agents. One login, everything works.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New `tstudio` CLI binary (cmd/tstudio/) with subcommands:
- login: authenticate via username/password, create API token, open welcome page
- logout: revoke token and clear credentials
- whoami: show current user and auth status
- repos: list accessible repositories
- clone: authenticated HTTPS clone with credential storage
- doctor: check git, git-lfs, auth, and connectivity
Platform changes:
- Landing page: CLI download section with OS-detected install command,
direct download buttons for Windows/macOS/Linux
- /cli/welcome: post-login success page (like gcloud auth_success)
with next steps and resource links
- Makefile: tstudio, tstudio-all, tstudio-upload targets for
cross-platform builds and S3 upload
- .claude/settings.json: full auto-allow permissions for Claude Code
- go.mod: add golang.org/x/term for hidden password input
Builds: tstudio-windows-amd64.exe, tstudio-darwin-arm64,
tstudio-darwin-amd64, tstudio-linux-amd64, tstudio-linux-arm64
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This is a step towards potentially splitting command groups into their
own folders to clean up `cmd/` as one folder for all cli commands.
Returning fresh command instances will also aid in adding tests as you
don't need to concern yourself with the whole command tree being one
mutable variable.
---------
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
## Overview
This PR introduces granular permission controls for Gitea Actions tokens
(`GITEA_TOKEN`), aligning Gitea's security model with GitHub Actions
standards while maintaining compatibility with Gitea's unique repository
unit system.
It addresses the need for finer access control by allowing
administrators and repository owners to define default token
permissions, set maximum permission ceilings, and control
cross-repository access within organizations.
## Key Features
### 1. Granular Token Permissions
- **Standard Keyword Support**: Implements support for the
`permissions:` keyword in workflow and job YAML files (e.g., `contents:
read`, `issues: write`).
- **Permission Modes**:
- **Permissive**: Default write access for most units (backwards
compatible).
- **Restricted**: Default read-only access for `contents` and
`packages`, with no access to other units.
- ~~**Custom**: Allows defining specific default levels for each unit
type (Code, Issues, PRs, Packages, etc.).~~**EDIT removed UI was
confusing**
- **Clamping Logic**: Workflow-defined permissions are automatically
"clamped" by repository or organization-level maximum settings.
Workflows cannot escalate their own permissions beyond these limits.
### 2. Organization & Repository Settings
- **Settings UI**: Added new settings pages at both Organization and
Repository levels to manage Actions token defaults and maximums.
- **Inheritance**: Repositories can be configured to "Follow
organization-level configuration," simplifying management across large
organizations.
- **Cross-Repository Access**: Added a policy to control whether Actions
workflows can access other repositories or packages within the same
organization. This can be set to "None," "All," or restricted to a
"Selected" list of repositories.
### 3. Security Hardening
- **Fork Pull Request Protection**: Tokens for workflows triggered by
pull requests from forks are strictly enforced as read-only, regardless
of repository settings.
- ~~**Package Access**: Actions tokens can now only access packages
explicitly linked to a repository, with cross-repo access governed by
the organization's security policy.~~ **EDIT removed
https://github.com/go-gitea/gitea/pull/36173#issuecomment-3873675346**
- **Git Hook Integration**: Propagates Actions Task IDs to git hooks to
ensure that pushes performed by Actions tokens respect the specific
permissions granted at runtime.
### 4. Technical Implementation
- **Permission Persistence**: Parsed permissions are calculated at job
creation and stored in the `action_run_job` table. This ensures the
token's authority is deterministic throughout the job's lifecycle.
- **Parsing Priority**: Implemented a priority system in the YAML parser
where the broad `contents` scope is applied first, allowing granular
scopes like `code` or `releases` to override it for precise control.
- **Re-runs**: Permissions are re-evaluated during a job re-run to
incorporate any changes made to repository settings in the interim.
### How to Test
1. **Unit Tests**: Run `go test ./services/actions/...` and `go test
./models/repo/...` to verify parsing logic and permission clamping.
2. **Integration Tests**: Comprehensive tests have been added to
`tests/integration/actions_job_token_test.go` covering:
- Permissive vs. Restricted mode behavior.
- YAML `permissions:` keyword evaluation.
- Organization cross-repo access policies.
- Resource access (Git, API, and Packages) under various permission
configs.
3. **Manual Verification**:
- Navigate to **Site/Org/Repo Settings -> Actions -> General**.
- Change "Default Token Permissions" and verify that newly triggered
workflows reflect these changes in their `GITEA_TOKEN` capabilities.
- Attempt a cross-repo API call from an Action and verify the Org policy
is enforced.
## Documentation
Added a PR in gitea's docs for this :
https://gitea.com/gitea/docs/pulls/318
## UI:
<img width="1366" height="619" alt="Screenshot 2026-01-24 174112"
src="https://github.com/user-attachments/assets/bfa29c9a-4ea5-4346-9410-16d491ef3d44"
/>
<img width="1360" height="621" alt="Screenshot 2026-01-24 174048"
src="https://github.com/user-attachments/assets/d5ec46c8-9a13-4874-a6a4-fb379936cef5"
/>
/fixes #24635
/claim #24635
---------
Signed-off-by: Excellencedev <ademiluyisuccessandexcellence@gmail.com>
Signed-off-by: ChristopherHX <christopher.homberger@web.de>
Signed-off-by: silverwind <me@silverwind.io>
Signed-off-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: ChristopherHX <christopher.homberger@web.de>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: Zettat123 <zettat123@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
I was testing typos-cli and fixed some misspelled wording here.
All changes are internal — no public API fields, database columns,
locale keys, or migration names are affected.
Fixes#36630
## Problem
`StartupProblems` warnings (from `deprecatedSetting` and other
`LogStartupProblem` calls) appear twice in the admin panel at `/-/admin`
and `/-/admin/self_check`.
`LoadCommonSettings()` is called twice during web server startup:
1. Early init via `cmd/main.go` → `InitWorkPathAndCommonConfig` →
`LoadCommonSettings()`
2. Web server startup via `cmd/web.go` → `serveInstalled` →
`LoadCommonSettings()`
The second call re-initializes the config provider first
(`InitCfgProvider`), but `StartupProblems` and `configuredPaths` are
never cleared between loads, so every warning gets appended twice.
## Fix
Clear `StartupProblems` and `configuredPaths` at the start of
`LoadCommonSettings()` so only the final load's warnings are retained.
This approach was chosen over clearing in `InitCfgProvider` because:
- Warnings are produced during settings load, not provider init
- Some callers set `CfgProvider` directly without calling
`InitCfgProvider`
- It avoids coupling correctness to a specific call ordering
## Screenshots
**Result** (single warning as expected):
<img width="1429" height="195" alt="Screenshot From 2026-02-16 01-27-01"
src="https://github.com/user-attachments/assets/d45313a2-f981-480b-9ffc-cbced7e40bb8"
/>
## testing
[x] Added `TestLoadCommonSettingsClearsStartupProblems` — verifies no
duplicate messages after consecutive loads
[x] Added `TestLoadCommonSettingsClearsConfiguredPaths` — verifies path
overlap map is identical after consecutive loads
[x] All existing `modules/setting` tests pass
[x] Manually verified in admin panel with deprecated `[oauth2].ENABLE`
setting
---------
Signed-off-by: silverwind <me@silverwind.io>
Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
1. correctly parse git protocol's "OldCommit NewCommit RefName" line, it
should be explicitly split by space
2. add missing "return" in CreatePullRequest
3. add comments for "/user.keys" and "/user.gpg" outputs
4. trim space for the "commit status context name" to follow the same
behavior of git_model.NewCommitStatus
This pull request adds an option to automatically verify SSH keys from
LDAP authentication sources.
This allows a correct authentication and verification workflow for
LDAP-enabled organizations; under normal circumstances SSH keys in LDAP
are not managed by users manually.
This PR fixes a panic issue in the WaitGroup that occurs when Gitea is
shut down using Ctrl+C.
It ensures that all active connection pointers in the server are
properly tracked and forcibly closed when the hammer shutdown is
invoked.
The process remains graceful — the normal shutdown sequence runs before
the hammer is triggered, and existing connections are given a timeout
period to complete gracefully.
This PR also fixes `no logger writer` problem. Now the log close will
only be invoked when the command exit.
- Fixes#35468
- Fixes#35551
- Fixes#35559
- Replace #35578
---------
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
Refactor Git command functions to use WithXXX methods instead of
exposing RunOpts.
This change simplifies reuse across gitrepo and improves consistency,
encapsulation, and maintainability of command options.
---------
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
When running `gitea dump`, don't store the contents of
`data/repo-archive` in the output.
These archives can easily be regenerated from the repository data, and
does not need to be backed up.
Fixes#35450
---
<s>Added a `--skip-repo-archive` flag to the `gitea dump` command.
Enabling this flag will exclude the contents of `data/repo-archive` from
the dump. The implementation is similar to the other `--skip-*` flags
that excludes directories from `data`.</s>
Signed-off-by: h7x4 <h7x4@nani.wtf>
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
fixes#30565
When using git with a gitea hosted repository, the HTTP-Transport did
honor the user and repository redirects, which are created when renaming
a user or repo and also when transferring ownership of a repo to a
different organization. This is extremely helpful, as repo URLs remain
stable and do not have to be migrated on each client's worktree and
other places, e.g. CI at once.
The SSH transport - which I favor - did not know of these redirections
and I implemented a lookup during the `serv` command.