detached d69187a

feat(domain): add authentication types and token structures

Add core domain types for registry authentication:
- AuthType enum (password, token)
- Token and TokenClaims structures for JWT handling
- SecretsBackend enum (pass, sops, unsafe)
- Authentication error types (ErrInvalidToken, ErrRevokedToken, etc.)
commit
d69187a1c284c40a23a38193aa64da71afe46dfe
author
brice · · 2026-01-12 17:54 UTC
committer
brice · · 2026-01-12 19:05 UTC
parent
00198fe
signature
unsigned
2 files · +61 -0
A internal/domain/auth.go +54 -0
@@ -0,0 +1,54 @@
1+// Package domain contains pure business types without external dependencies.
2+package domain
3+
4+import "time"
5+
6+// AuthType represents the type of authentication configured for the registry.
7+type AuthType string
8+
9+const (
10+ // AuthTypePassword uses bcrypt-hashed password authentication.
11+ AuthTypePassword AuthType = "password"
12+ // AuthTypeToken uses JWT token-based authentication.
13+ AuthTypeToken AuthType = "token"
14+)
15+
16+// Token represents a generated authentication token stored in the secrets backend.
17+type Token struct {
18+ ID string
19+ Subject string
20+ Scopes []string
21+ IssuedAt time.Time
22+ ExpiresAt time.Time // Zero value means never expires
23+ Revoked bool
24+}
25+
26+// TokenClaims represents the JWT claims for a token.
27+type TokenClaims struct {
28+ ID string `json:"jti"`
29+ Subject string `json:"sub"`
30+ Scopes []string `json:"scopes"`
31+ IssuedAt int64 `json:"iat"`
32+ ExpiresAt int64 `json:"exp,omitempty"` // 0 means never expires
33+ Issuer string `json:"iss"`
34+}
35+
36+// IsExpired checks if the token has expired.
37+func (t *Token) IsExpired() bool {
38+ if t.ExpiresAt.IsZero() {
39+ return false // Never expires
40+ }
41+ return time.Now().After(t.ExpiresAt)
42+}
43+
44+// SecretsBackend represents the type of secrets storage backend.
45+type SecretsBackend string
46+
47+const (
48+ // SecretsBackendPass uses the pass password manager.
49+ SecretsBackendPass SecretsBackend = "pass"
50+ // SecretsBackendSops uses SOPS for encrypted secrets.
51+ SecretsBackendSops SecretsBackend = "sops"
52+ // SecretsBackendUnsafe stores secrets in plain text (development only).
53+ SecretsBackendUnsafe SecretsBackend = "unsafe"
54+)
@@ -0,0 +1,54 @@
1+// Package domain contains pure business types without external dependencies.
2+package domain
3+
4+import "time"
5+
6+// AuthType represents the type of authentication configured for the registry.
7+type AuthType string
8+
9+const (
10+ // AuthTypePassword uses bcrypt-hashed password authentication.
11+ AuthTypePassword AuthType = "password"
12+ // AuthTypeToken uses JWT token-based authentication.
13+ AuthTypeToken AuthType = "token"
14+)
15+
16+// Token represents a generated authentication token stored in the secrets backend.
17+type Token struct {
18+ ID string
19+ Subject string
20+ Scopes []string
21+ IssuedAt time.Time
22+ ExpiresAt time.Time // Zero value means never expires
23+ Revoked bool
24+}
25+
26+// TokenClaims represents the JWT claims for a token.
27+type TokenClaims struct {
28+ ID string `json:"jti"`
29+ Subject string `json:"sub"`
30+ Scopes []string `json:"scopes"`
31+ IssuedAt int64 `json:"iat"`
32+ ExpiresAt int64 `json:"exp,omitempty"` // 0 means never expires
33+ Issuer string `json:"iss"`
34+}
35+
36+// IsExpired checks if the token has expired.
37+func (t *Token) IsExpired() bool {
38+ if t.ExpiresAt.IsZero() {
39+ return false // Never expires
40+ }
41+ return time.Now().After(t.ExpiresAt)
42+}
43+
44+// SecretsBackend represents the type of secrets storage backend.
45+type SecretsBackend string
46+
47+const (
48+ // SecretsBackendPass uses the pass password manager.
49+ SecretsBackendPass SecretsBackend = "pass"
50+ // SecretsBackendSops uses SOPS for encrypted secrets.
51+ SecretsBackendSops SecretsBackend = "sops"
52+ // SecretsBackendUnsafe stores secrets in plain text (development only).
53+ SecretsBackendUnsafe SecretsBackend = "unsafe"
54+)
M internal/domain/errors.go +7 -0
@@ -47,4 +47,11 @@ var (
4747 ErrEnvFileNotFound = errors.New("environment file not found")
4848 ErrSecretNotFound = errors.New("secret not found")
4949 ErrProviderNotFound = errors.New("secret provider not found")
50+
51+ // Authentication errors
52+ ErrInvalidToken = errors.New("invalid token")
53+ ErrExpiredToken = errors.New("token has expired")
54+ ErrRevokedToken = errors.New("token has been revoked")
55+ ErrInvalidCredentials = errors.New("invalid credentials")
56+ ErrTokenNotFound = errors.New("token not found")
5057 )
@@ -47,4 +47,11 @@ var (
47 ErrEnvFileNotFound = errors.New("environment file not found")47 ErrEnvFileNotFound = errors.New("environment file not found")
48 ErrSecretNotFound = errors.New("secret not found")48 ErrSecretNotFound = errors.New("secret not found")
49 ErrProviderNotFound = errors.New("secret provider not found")49 ErrProviderNotFound = errors.New("secret provider not found")
50+
51+ // Authentication errors
52+ ErrInvalidToken = errors.New("invalid token")
53+ ErrExpiredToken = errors.New("token has expired")
54+ ErrRevokedToken = errors.New("token has been revoked")
55+ ErrInvalidCredentials = errors.New("invalid credentials")
56+ ErrTokenNotFound = errors.New("token not found")
50 )57 )

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 7

Tags 106

↑↓ moveenter openesc close