- Remove all hardcoded NW:eshkink0t credentials from 9 files across skills, commands, rules, and specs - Add .kilo/shared/gitea-auth.md with get_gitea_token() and .kilo/gitea.jsonc config structure - All Gitea API callers now use env vars (GITEA_TOKEN → GITEA_USER+GITEA_PASS → ValueError) - Fix task-analysis/SKILL.md broken functions (orphaned req references, stray parentheses) - Replace hardcoded UniqueSoft/APAW API URLs with get_target_repo() auto-detection in 3 files - Update README.md, STRUCTURE.md, AGENTS.md with centralized auth documentation - Add EVOLUTION_LOG Entry #5 documenting credentials extrication
4.0 KiB
4.0 KiB
Gitea Auth Module (Shared)
Centralized authentication for Gitea API. NEVER hardcode credentials in agent code.
Auth Resolution Order
1. GITEA_TOKEN env var → Use directly (PREFERRED)
2. GITEA_USER + GITEA_PASS → Create temporary token via Basic Auth
3. .env file → Read env vars from .env
4. Interactive prompt → Ask user (last resort)
Configuration
All credentials come from environment variables defined in .kilo/gitea.jsonc:
| Env Var | Required | Description |
|---|---|---|
GITEA_API_URL |
No | API base URL (default: https://git.softuniq.eu/api/v1) |
GITEA_TOKEN |
Preferred | Pre-existing API token |
GITEA_USER |
Fallback | Username for Basic Auth token creation |
GITEA_PASS |
Fallback | Password for Basic Auth token creation |
GITEA_TARGET_REPO |
No | Override target project (auto-detected otherwise) |
Python Auth Function
import os
import base64
import json
import urllib.request
def get_gitea_config():
"""Load Gitea configuration from env vars. NEVER hardcode credentials."""
return {
'api_url': os.environ.get('GITEA_API_URL', 'https://git.softuniq.eu/api/v1'),
'token': os.environ.get('GITEA_TOKEN', ''),
'user': os.environ.get('GITEA_USER', ''),
'pass': os.environ.get('GITEA_PASS', ''),
}
def get_gitea_token():
"""Get Gitea API token. Prefers GITEA_TOKEN env var.
Falls back to creating token via Basic Auth from GITEA_USER/GITEA_PASS.
Raises ValueError if no credentials available."""
config = get_gitea_config()
# 1. Use existing token (preferred)
if config['token']:
return config['token']
# 2. Create token via Basic Auth (fallback)
user = config['user']
password = config['pass'] # Note: 'pass' is reserved word, use config['pass']
if not user or not password:
raise ValueError(
'Gitea auth required. Set GITEA_TOKEN or GITEA_USER+GITEA_PASS env vars. '
'Create .env file with: GITEA_TOKEN=your-token'
)
credentials = base64.b64encode(f"{user}:{password}".encode()).decode()
req = urllib.request.Request(
f"{config['api_url']}/users/{user}/tokens",
data=json.dumps({"name": f"agent-{os.getpid()}", "scopes": ["all"]}).encode(),
headers={
'Content-Type': 'application/json',
'Authorization': f'Basic {credentials}',
},
method='POST',
)
with urllib.request.urlopen(req) as r:
return json.loads(r.read())['sha1']
Bash Auth Function
# Get Gitea token — prefers GITEA_TOKEN, falls back to Basic Auth
get_gitea_token() {
if [ -n "$GITEA_TOKEN" ]; then
echo "$GITEA_TOKEN"
return
fi
if [ -z "$GITEA_USER" ] || [ -z "$GITEA_PASS" ]; then
echo "ERROR: Set GITEA_TOKEN or GITEA_USER+GITEA_PASS" >&2
return 1
fi
local API_URL="${GITEA_API_URL:-https://git.softuniq.eu/api/v1}"
local CRED=$(echo -n "$GITEA_USER:$GITEA_PASS" | base64)
curl -s -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Basic $CRED" \
-d '{"name":"agent-token","scopes":["all"]}' \
"$API_URL/users/$GITEA_USER/tokens" | jq -r '.sha1 // empty'
}
.env File Template
# Gitea Integration (NEVER commit this file)
GITEA_API_URL=https://git.softuniq.eu/api/v1
GITEA_TOKEN=your-api-token-here
# Fallback (only if no token):
# GITEA_USER=your-username
# GITEA_PASS=your-password
# GITEA_TARGET_REPO=Owner/RepoName
CRITICAL RULES
- NEVER hardcode credentials — no
username = "NW"orpassword = "eshkink0t"in any file - NEVER commit
.env— it's in.gitignore - ALWAYS prefer
GITEA_TOKEN— tokens are scoped and revocable - Fallback uses env vars —
GITEA_USER+GITEA_PASS, not hardcoded strings - Raise error if no creds — don't silently fail, tell user to set env vars
- Use this module — all Gitea API calls should use
get_gitea_token()from here