Use token list schema for token store

This commit is contained in:
mpabi
2026-04-26 21:33:14 +02:00
parent 7e62be4ca1
commit 8c0f95d996
4 changed files with 712 additions and 507 deletions
+25 -17
View File
@@ -112,25 +112,32 @@ Minimalny format:
```json
{
"version": 2,
"servers": {
"http://77.90.8.171:3001": {
"type": "gitea",
"scheme": "http",
"host": "77.90.8.171",
"port": 3001,
"users": {
"u1": {
"tokens": {
"t1": "TU_WSTAW_TOKEN"
}
"version": 3,
"tokens": [
{
"token_id": "t1",
"value": "TU_WSTAW_TOKEN",
"server": {
"type": "gitea",
"endpoint": "http://77.90.8.171:3001",
"scheme": "http",
"host": "77.90.8.171",
"port": 3001
},
"remotes": [
{
"name": "r1",
"org": "edu-tools",
"repo": "rv-launcher"
}
}
]
}
}
]
}
```
Pelny schemat pliku jest w `doc/tokens.schema.json`.
Plik powinien byc lokalny, niewersjonowany i miec prawa `600`.
Przyklad:
@@ -162,10 +169,11 @@ logiczny remote tokena.
remote i `tokens.json` sa zgodne oraz uprawnienia zostaly wczytane, `R` oznacza
token tylko w remote, a `S` token tylko w `tokens.json`. Kolumny `scope`, `org`
i `repo` sa maskami uprawnien; bez `*` maja wartosc `?????` albo `????`.
Zapis z remote do `tokens.json` robi dopiero `tokens update --from remotes`.
Zapis z remote do `tokens.json` oraz odczyt `valid` i uprawnien z API robi
dopiero `tokens update --from remotes`.
Kolumna `valid` oznacza, czy token zostal zaakceptowany przez API teraz.
Jesli przy tokenie w `tokens.json` zapiszesz `expires_at`, `valid` pokaze date
wygasniecia; bez daty poprawny token pokazuje `forever`.
Jesli przy tokenie w `tokens.json` zapiszesz `expires_at`, `valid` moze pokazac
date wygasniecia; bez daty poprawny token pokazuje `forever`.
## Fetch i switch
+101 -210
View File
@@ -1,178 +1,139 @@
# Tokens
Plik opisuje aktualny model pracy z tokenami w launcherze.
Plik opisuje model pracy z tokenami w launcherze.
## Zrodlo prawdy
Sa dwa miejsca, w ktorych moga byc zapisane tokeny:
- remote URL-e w repo, na przyklad `http://LOGIN:TOKEN@host/org/repo.git`
- remote URL-e w repo, na przyklad `http://t1:SECRET@host/org/repo.git`
- lokalny plik `~/dev/workspace/rv/tokens/tokens.json`
Jesli remote URL zawiera `LOGIN:TOKEN@...`, to remote jest zrodlem prawdy.
Launcher moze wtedy pokazac stan przez `tokens scan` albo jawnie zapisac token
do `tokens.json` przez `tokens update --from remotes`.
Jesli remote nie ma tokena, `tokens.json` moze byc uzyty jako lokalny store
przy operacjach `tokens write` i `tokens update --from store`.
`tokens scan` tylko porownuje oba zrodla i niczego nie zapisuje.
`tokens update --from remotes` czyta remote URL-e, zapisuje tokeny do
`tokens.json` i wzbogaca je danymi z API, jezeli token dziala.
`tokens update --from store` zapisuje wybrany token z `tokens.json` do remote
URL-a repo.
## Format `tokens.json`
Tokeny sa trzymane per endpoint serwera, a dopiero pod nim per user i token:
Aktualny format to `version: 3`. Glownym rekordem jest token. `server`, `user`,
`valid`, `scope` i `remotes` sa atrybutami tego tokena.
```json
{
"version": 2,
"servers": {
"http://77.90.8.171:3001": {
"type": "gitea",
"scheme": "http",
"host": "77.90.8.171",
"port": 3001,
"users": {
"u1": {
"tokens": {
"t1": "SECRET",
"t2": {
"value": "SECRET",
"remote": "r1",
"org": "edu-tools",
"repo": "rv-launcher",
"expires_at": "2026-05-01T12:00:00"
}
}
"version": 3,
"tokens": [
{
"token_id": "t1",
"value": "SECRET",
"server": {
"type": "gitea",
"endpoint": "http://77.90.8.171:3001",
"scheme": "http",
"host": "77.90.8.171",
"port": 3001
},
"user": "u1",
"valid": "forever",
"scope": "+---+",
"remotes": [
{
"name": "r1",
"org": "edu-tools",
"repo": "rv-launcher",
"org_perm": "+++++",
"repo_perm": "++++"
}
}
]
}
}
]
}
```
To pozwala odroznic:
Schemat JSON jest w pliku `doc/tokens.schema.json`.
- typ serwera, na przyklad `gitea`, `github`, `gitlab`, `unknown`
- endpoint, czyli `scheme + host + port`
- uzytkownikow na danym serwerze
- wiele tokenow dla jednego usera
- nazwe remota, ktora jest identyfikatorem parowania z repo
- opcjonalne `org` i `repo` zapamietane z remote URL-a
- opcjonalna date wygasniecia `expires_at` dla tokena
## Pola
## Skanowanie remota
Pola synchronizowane z remote URL-a:
Przy `tokens scan` launcher:
- `server.endpoint` - endpoint serwera, na przyklad `http://77.90.8.171:3001`
- `server.type` - typ serwera, na przyklad `gitea`, `github`, `gitlab`, `unknown`
- `token_id` - identyfikator z lewej strony URL-a, na przyklad `t1` w `http://t1:SECRET@...`
- `value` - sekret tokena
- `remotes[].name` - nazwa remota, na przyklad `r1`
- `remotes[].org` - organizacja z URL-a
- `remotes[].repo` - repo z URL-a
- czyta wszystkie remote URL-e w repo
- czyta `tokens.json`
- laczy remote i store w pary po endpoincie serwera i nazwie remota
- wybiera tylko `http` i `https`
- jesli URL ma `LOGIN:TOKEN@...`, wyciaga login i token
- niczego nie zapisuje do `tokens.json`
Pola wzbogacane przez API przy `tokens update --from remotes`:
Endpoint jest liczony z:
- `user` - login wlasciciela tokena odczytany z API
- `valid` - `forever`, data `expires_at`, `invalid`, `?` albo `!`
- `scope` - maska scope tokena
- `remotes[].org_perm` - maska praw w organizacji
- `remotes[].repo_perm` - maska praw w repo
- scheme
- host
- port
## Porownanie
Przy `tokens update --from remotes` launcher zapisuje tez metadane serwera:
Porownanie z `git remote -v` jest robione po:
- `type`
- `scheme`
- `host`
- `port`
```text
server.endpoint + remote.name + token_id + value + org + repo
```
Znacznik w kolumnie `token_ref`:
- `*` - remote i `tokens.json` sa zgodne
- `R` - wpis istnieje tylko w remote URL-u
- `S` - wpis istnieje tylko w `tokens.json`
- `!` - remote i `tokens.json` sa zgodne, ale zapisany token jest `invalid` albo ma blad walidacji
Bez `*` albo `!` kolumny `valid`, `scope`, `org` i `repo` w raporcie maja
wartosc `?`, bo launcher nie pokazuje metadanych API dla niesparowanych wpisow.
## Maski uprawnien
Naglowki masek:
- `scope`: `awrop-`
- `org`: `oawrc-`
- `repo`: `oawr--`
Znaki w wartosciach:
- `+` - flaga wlaczona
- `-` - flaga wylaczona
- `?` - nie wczytano
- `!` - blad wczytania
## Komendy
### `tokens scan`
Zrodla:
```text
repo + tokens.json
```
Dzialanie:
- skanuje remote URL-e w repo
- czyta wpisy z `tokens.json`
- laczy oba zrodla po endpoincie serwera i nazwie remota
- wypisuje tabele `tokens`
Tabela `tokens` pokazuje jeden logiczny wiersz na remote tokena. Remote i
`tokens.json` sa laczone po endpoincie serwera oraz kolumnie `remote`.
Znacznik w `token_ref`:
- `*` - token jest w remote i `tokens.json`, remote/user/token sa zgodne, uprawnienia zostaly wczytane
- `R` - token jest tylko w remote
- `S` - token jest tylko w `tokens.json`
- `!` - blad wczytania uprawnien dla sparowanego tokena
Kolumny w tabeli `tokens`:
- `item` - numer wiersza tokena
- `server` - typ serwera, na przyklad `gitea`
- `proto` - protokol endpointu, na przyklad `http`
- `host` - host endpointu razem z portem, na przyklad `77.90.8.171:3001`
- `org` - organizacja z remote URL
- `repo` - repo z remote URL
- `user` - login wlasciciela tokena
- `remote` - nazwa remota, na przyklad `r1`
- `token_ref` - nazwa tokena z markerem po prawej stronie
- `token` - zamaskowana wartosc tokena
- `valid` - `forever`, lokalne `expires_at`, `invalid`, `?` albo `!`
- `scope` - maska scope tokena `awrop`
- `org` - maska praw w organizacji `oawrc`
- `repo` - maska praw w repo `oawr`
Maski uprawnien:
- `+` - flaga wlaczona
- `-` - flaga wylaczona
- `?` - nie wczytano, na przyklad dla `R` albo `S`
- `!` - blad wczytania
Tabela nie wypisuje sekretu tokena wprost. Kolumna `token` pokazuje skrot, na
przyklad `e59cc...13be`.
`valid` jest liczone tak:
- `forever` - API akceptuje token i nie ma lokalnego `expires_at`
- `2026-05-01T12:00:00` - API akceptuje token i taka data jest zapisana w `tokens.json`
- `invalid` - API odrzuca token albo lokalne `expires_at` jest w przeszlosci
- `?` - token nie jest sparowany jako `*`, wiec nie sprawdzamy uprawnien
- `!` - blad sprawdzania API
`tokens scan` jest read-only. Jezeli token jest tylko w remote, tabela pokaze
`R` i maski `?????`/`????`. Dopiero jawne `tokens update --from remotes`
zapisuje token oraz metadane `remote`, `org` i `repo` do `tokens.json`.
Przyklad:
Read-only. Czyta remote URL-e i `tokens.json`, a potem wypisuje tabele `tokens`.
Nie tworzy i nie modyfikuje `tokens.json`.
```bash
./rvctl tokens scan
./rvctl tokens scan --repo ~/dev/workspace/rv/series/inf/03
```
### `tokens update --from remotes`
Kopiuje tokeny z remote URL-i repo do `tokens.json`, zapisuje rekordy w formacie
v3 i probuje pobrac pola API: `user`, `valid`, `scope`, `org_perm`,
`repo_perm`.
```bash
./rvctl tokens update --from remotes --repo ~/dev/workspace/rv/tools/rv-launcher
./rvctl tokens update --from remotes --dry-run
```
`--dry-run` dziala jak read-only raport i niczego nie zapisuje.
### `tokens read`
Pokazuje szczegolowa zawartosc `tokens.json`.
Wynik zawiera:
- endpoint
- type
- scheme
- host
- port
- users
- tokens
- remote/org/repo przy tokenie, jezeli sa zapisane
Oraz liste userow i nazw tokenow dla kazdego endpointu.
Przyklad:
Pokazuje zawartosc `tokens.json`.
```bash
./rvctl tokens read
@@ -182,20 +143,7 @@ Przyklad:
### `tokens stats`
Pokazuje statystyki per endpoint serwera i porownuje dwa zrodla:
- endpointy znalezione w remote URL-ach repo
- endpointy zapisane w `tokens.json`
Wynik ma ten sam model porownania co `tokens scan`, ale nie zapisuje zmian:
- liczbe endpointow w repo
- liczbe endpointow w store
- laczna unie endpointow
- statusy zgodnosci, na przyklad `in_sync`, `store_ahead`, `repo_ahead`
- tabele `tokens`
Przyklad:
Pokazuje kontekst, tabele `tokens` i podsumowanie statusow endpointow.
```bash
./rvctl tokens stats --repo ~/dev/workspace/rv/series/inf/03
@@ -203,78 +151,21 @@ Przyklad:
### `tokens write`
Kierunek:
```text
tokens.json -> repo
```
Dzialanie:
- bierze token z `tokens.json`
- wybiera endpoint, usera i token
- wpisuje dane auth do wybranego remota repo
Przyklad:
Zapisuje wybrany token z `tokens.json` do remote URL-a repo.
```bash
./rvctl tokens write \
--repo ~/dev/workspace/rv/series/inf/03 \
--remote r1 \
--server http://77.90.8.171:3001 \
--user u1 \
--token-name t1
```
### `tokens update`
### `tokens update --from store`
Uruchamia synchronizacje w zadanym kierunku.
Dozwolone kierunki:
- `tokens update --from remotes`
- `tokens update --from store`
`tokens update --from remotes` kopiuje tokeny z remote URL-i repo do
`tokens.json`. Z `--dry-run` dziala jak read-only raport. `tokens update
--from store` kopiuje wybrany token z `tokens.json` do remote URL-a repo.
Przyklad:
Alias kierunkowy na zapis store -> remote. Uzywa tych samych opcji co
`tokens write`.
```bash
./rvctl tokens update --from remotes --repo ~/dev/workspace/rv/series/inf/03
./rvctl tokens update --from store --repo ~/dev/workspace/rv/series/inf/03 --remote r1 --server http://77.90.8.171:3001 --user u1 --token-name t1
./rvctl tokens update --from store --repo PATH --remote r1 --server http://77.90.8.171:3001 --token-name t1
```
## Konflikty
Domyslnie launcher nie zgaduje przy konflikcie.
Jesli:
- token jest w repo, ale nie ma go w `tokens.json`
uzyj `tokens update --from remotes`
- token jest w `tokens.json`, ale nie ma go w repo
uzyj `tokens write`
- token jest i tu, i tu, ale wartosci sa rozne
wybierz kierunek jawnie przez `tokens update --from ...`
Przy `tokens update --from remotes` mozna uzyc:
- `--dry-run`
Przy `tokens write` i `tokens update --from store` mozna uzyc:
- `--replace`
- `--dry-run`
## Rekomendacja
Najbezpieczniejszy model pracy:
- `tokens scan` do zczytywania danych z remote'ow
- `tokens update --from remotes` do jawnego zapisania tokenow z remote'ow w `tokens.json`
- `tokens read` do podgladu store
- `tokens stats` do zbiorczego przegladu per endpoint
- `tokens write` do jawnego wpisania auth do remota
- `tokens update --from ...` tylko z jawnym kierunkiem
+108
View File
@@ -0,0 +1,108 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://edu-tools.local/rv-launcher/tokens.schema.json",
"title": "RV launcher tokens",
"type": "object",
"additionalProperties": false,
"required": ["version", "tokens"],
"properties": {
"version": {
"const": 3
},
"tokens": {
"type": "array",
"items": {
"$ref": "#/$defs/token"
}
}
},
"$defs": {
"server": {
"type": "object",
"additionalProperties": false,
"required": ["type", "endpoint", "scheme", "host", "port"],
"properties": {
"type": {
"type": "string"
},
"endpoint": {
"type": "string",
"format": "uri"
},
"scheme": {
"enum": ["http", "https"]
},
"host": {
"type": "string"
},
"port": {
"type": ["integer", "null"],
"minimum": 1,
"maximum": 65535
}
}
},
"remote": {
"type": "object",
"additionalProperties": false,
"required": ["name", "org", "repo"],
"properties": {
"name": {
"type": "string",
"minLength": 1
},
"org": {
"type": "string"
},
"repo": {
"type": "string"
},
"org_perm": {
"type": "string",
"pattern": "^[+?!-]{5}$"
},
"repo_perm": {
"type": "string",
"pattern": "^[+?!-]{4}$"
}
}
},
"token": {
"type": "object",
"additionalProperties": false,
"required": ["token_id", "value", "server", "remotes"],
"properties": {
"token_id": {
"type": "string",
"minLength": 1
},
"value": {
"type": "string",
"minLength": 1
},
"server": {
"$ref": "#/$defs/server"
},
"user": {
"type": "string"
},
"valid": {
"type": "string"
},
"scope": {
"type": "string",
"pattern": "^[+?!-]{5}$"
},
"expires_at": {
"type": "string"
},
"remotes": {
"type": "array",
"items": {
"$ref": "#/$defs/remote"
}
}
}
}
}
}
+478 -280
View File
File diff suppressed because it is too large Load Diff