Commit e2a32d5f8d
e2a32d5f8d59e4213571c602bd9009b6c8fa86ed
parent: 0787c7c07e
Verified · cmc ci/build: success ci/test: success
cmc <hello@cleberg.net> · 2026-09-28 08:10 UTC
wiki: delegation bound covers tokens and keys, not web sessions
Ref #257
Layout: unified · split
.gitbay/wiki/Architecture/09-Controls.org
+1 −1
| @@ -26,7 +26,7 @@ chapter names of OWASP ASVS 4.0 where one fits. |
| 26 | 26 | | Session lifetime | partial | 7 days absolute, no idle timeout (#276) | |
| 27 | 27 | | Credential expiry | partial | API tokens optional; SSH and deploy keys none (#277) | |
| 28 | 28 | | Revocation takes effect immediately | in place | removing a key or disabling an account closes its connections; every exec re-reads its key (=internal/sshd/sshd.go=) | |
| 29 | | | Delegation bounded by the delegating credential | in place | expiring tokens refused on =MintsCredential= commands; credentials record their creating token (=internal/control/control.go=) | |
| 29 | | Delegation bounded by the delegating credential | partial | expiring tokens refused on =MintsCredential= commands; credentials record their creating token (=internal/control/control.go=); a web session can still mint credentials that outlive it (#297) | |
| 30 | 30 | |
| 31 | 31 | ** Access control (V4) |
| 32 | 32 | |
.gitbay/wiki/Architecture/10-Known-Gaps.org
+1 −1
| @@ -26,7 +26,7 @@ what the 2026-09-27 review found; remove a row when its issue closes. |
| 26 | 26 | | #280 | Mail | STARTTLS only when the relay offers it | medium | |
| 27 | 27 | | #281 | TLS | No explicit minimum TLS version | low | |
| 28 | 28 | | #282 | Hook socket | Anything that can open =hook.sock= can act as any user | medium | |
| 29 | | |
| 29 | | #297 | Credentials | A browser session can mint tokens and keys that outlive it | low | |
| 30 | 30 | |
| 31 | 31 | * Questions an auditor will ask that have no answer yet |
| 32 | 32 | |
.gitbay/wiki/Threat-Model.org
+4 −3
| @@ -52,9 +52,10 @@ matrix and the open gaps are in the [[file:Architecture/00-Overview.org][Archite |
| 52 | 52 | OpenSSH and fronted unchanged by the JSON API and the web. No command |
| 53 | 53 | belongs to one surface (#234): what a caller may do is the account's |
| 54 | 54 | rights narrowed by its credential's scope, decided in one place, so a |
| 55 | | bearer token is worth exactly its scope and no more, and a credential |
| 56 | | with an expiry cannot create one that outlives it. Git transport |
| 57 | | never runs over the API. |
| 55 | bearer token is worth exactly its scope and no more, and a token or |
| 56 | SSH key with an expiry cannot create a credential that outlives it. |
| 57 | Browser sessions are not covered yet (#297). Git transport never runs |
| 58 | over the API. |
| 58 | 59 | - *Anonymous surfaces* — HTTPS clone of public repos, =git://= where |
| 59 | 60 | enabled, the read-only web UI — carry no credentials and expose only |
| 60 | 61 | public data. HTTP push is refused via a pkt-line =ERR=, never a 401. |
CHANGELOG.org
+3 −1
| @@ -6,6 +6,8 @@ anything beyond "replace the binary and restart" is needed. |
| 6 | 6 | |
| 7 | 7 | * Unreleased |
| 8 | 8 | |
| 9 | Credentials: revocation and delegation (#256, #257). |
| 10 | |
| 9 | 11 | *Upgrade note.* =token create= makes a =read= token unless given |
| 10 | 12 | =--scope full=. A script that mints a token and then writes with it |
| 11 | 13 | must add =--scope full=. Existing tokens keep their scope. |
| @@ -15,7 +17,7 @@ must add =--scope full=. Existing tokens keep their scope. |
| 15 | 17 | invites, accounts and verified addresses (#257). |
| 16 | 18 | - Tokens and SSH keys record the token they were created through. |
| 17 | 19 | =token revoke <name>= lists what it created; =--created= revokes |
| 18 | | those too. |
| 20 | those too (#257). |
| 19 | 21 | - Removing an SSH key, a deploy key, or disabling an account closes the |
| 20 | 22 | connections the key opened, a push in flight included (#256). |
| 21 | 23 | |