···11+package auth
22+33+import (
44+ "context"
55+66+ gossh "golang.org/x/crypto/ssh"
77+)
88+99+// Operation is the access a request needs. Transports map the git service:
1010+// upload-pack/upload-archive → Read, receive-pack → Write.
1111+type Operation int
1212+1313+const (
1414+ Read Operation = iota
1515+ Write
1616+)
1717+1818+// Credential is what the client presented. Exactly one concrete type per
1919+// scheme; a transport constructs the variant it can produce, or Anonymous.
2020+type Credential interface{ isCredential() }
2121+2222+// Anonymous is "no credential presented" (git://, or HTTP/SSH with none).
2323+type Anonymous struct{}
2424+2525+// PublicKey is an SSH public key. Uses x/crypto/ssh's type (gliderlabs/ssh
2626+// keys satisfy it) so this package stays free of the SSH server library.
2727+type PublicKey struct{ Key gossh.PublicKey }
2828+2929+// BasicAuth is an HTTP Basic credential. Unvalidated — the Authorizer owns the
3030+// user store.
3131+type BasicAuth struct{ Username, Password string }
3232+3333+func (Anonymous) isCredential() {}
3434+func (PublicKey) isCredential() {}
3535+func (BasicAuth) isCredential() {}
3636+3737+// Request is a transport-neutral authorization request.
3838+type Request struct {
3939+ Repo string
4040+ Operation Operation
4141+ Cred Credential
4242+ Transport string // "git", "ssh", "http" — for policy/logging
4343+}
4444+4545+// Decision is the outcome. Unauthenticated is the seam that lets HTTP issue a
4646+// 401 challenge; SSH and git:// treat it as Deny.
4747+type Decision int
4848+4949+const (
5050+ Deny Decision = iota
5151+ Allow
5252+ Unauthenticated
5353+)
5454+5555+// Authorizer decides whether a request may proceed. This is the seam a real
5656+// authn/authz layer plugs into later.
5757+type Authorizer interface {
5858+ Authorize(ctx context.Context, req Request) Decision
5959+}
6060+6161+// AllowAnonymous is the permissive default: read for everyone, write only when
6262+// AllowWrite is set. "Dangerously allow everything the server is configured to
6363+// allow" — never more open than the -allow-push gate. It ignores the credential
6464+// entirely and never returns Unauthenticated.
6565+type AllowAnonymous struct{ AllowWrite bool }
6666+6767+func (a AllowAnonymous) Authorize(_ context.Context, req Request) Decision {
6868+ if req.Operation == Write && !a.AllowWrite {
6969+ return Deny
7070+ }
7171+ return Allow
7272+}