Help us shape the future of Go! Take the 2026 Go Developer Survey

forgekit

package
v0.14.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 23, 2026 License: AGPL-3.0 Imports: 20 Imported by: 0

Documentation

Overview

Package forgekit is what source adapters share: reading a repository address in each of the forms people write one, deciding whether a connection covers it, and building the credential core clones with.

Not an adapter. Each forge's own package decides what its addresses look like and what it calls the parts; this package only does the parsing and the arithmetic they would otherwise each repeat.

Index

Constants

View Source
const (
	FieldAccessToken    = "access_token"
	FieldRefreshToken   = "refresh_token"
	FieldTokenExpiresAt = "token_expires_at"
)

The credential fields an oauth connection keeps, written by core from an AuthorizationResult or a GitCredential.Rotated and handed back in Configure.

View Source
const (
	MethodToken            = "token"
	MethodSSH              = "ssh"
	MethodApp              = "app"
	MethodOAuth            = "oauth"
	MethodServicePrincipal = "service_principal"
)

The methods a connection can authenticate with (api.SourceCapabilities.Method).

View Source
const (
	FieldToken         = "token"
	FieldSSHPrivateKey = "ssh_private_key"
	FieldSSHPassphrase = "ssh_passphrase"
	FieldClientSecret  = "client_secret"
)

The credential fields the shared methods use. A forge adds its own beside them (a GitHub App's private key).

View Source
const CallbackPath = "/api/v1/sources/callback"

CallbackPath is where a forge sends the browser back from an OAuth sign-in, under Pando's address: the source callback in httpapi.

View Source
const KeyScanAnyHost = "`ssh-keyscan` with the host's name, on a machine you trust,"

KeyScanAnyHost is SSHKey.KeyScan for a forge with no host of its own.

Variables

This section is empty.

Functions

func APIURLField

func APIURLField(def string) api.Field

func CABundle

func CABundle(pem string) ([]byte, error)

CABundle reads a PEM bundle setting and refuses one with no certificate in it. Empty is fine: the system's roots alone.

func CAField

func CAField() api.Field

func CheckKnownHosts

func CheckKnownHosts(text string) error

CheckKnownHosts refuses known_hosts text that pins nothing. An SSH connection without a pinned host key would trust whoever answers, which is how a network attacker reads the repository (api.GitCredential.KnownHosts).

func CheckSSHKey

func CheckSSHKey(key, passphrase secret.Value) error

CheckSSHKey refuses a private key Pando cannot use, at configuration rather than at the first deploy. Nothing about the key is put in the error.

func Covers

func Covers(hosts []string, scope []string, repoHost string, path []string) int

Covers scores how specifically a connection for host, limited to scope, covers a repository path. Zero is not at all. One is the whole host; each scope segment that matches adds one, so the narrowest connection wins (api.SourceAdapter.Covers). Names are compared without case, as every forge Pando knows treats owner names.

hosts lists every host the connection answers for — "dev.azure.com" and "ssh.dev.azure.com" are one Azure DevOps — and path is the repository path with any host-specific prefix already removed by the caller.

func Decode

func Decode(raw json.RawMessage, into any) error

Decode reads raw configuration into a forge's settings struct, which embeds Settings.

func HTTPClient

func HTTPClient(caBundle []byte) *http.Client

HTTPClient is a client for a forge's API that trusts caBundle beside the system's roots.

func HTTPSURL

func HTTPSURL(host, port, path string) string

HTTPSURL is the HTTPS address of a repository on host at path.

func HostField

func HostField(def string) api.Field

func HostOf

func HostOf(setting string) string

HostOf reads the host out of a host setting, which people write as "github.com", "https://gitlab.acme.internal" or "gitlab.acme.internal:8443". The port is dropped: a connection is for a host, whichever port it is reached on.

func Limit

func Limit(n int) int

Limit is the number of results a listing returns when the request does not say.

func Matches

func Matches(fullName, query string) bool

Matches reports whether a repository's full name matches a listing query: every word in the query appears in it, without case.

func MethodField

func MethodField(options ...api.Option) api.Field

func MethodStep added in v0.10.0

func MethodStep() api.Step

MethodStep is a forge's first step: how Pando signs in, and the host.

func NextLink(header string) string

NextLink reads the rel="next" address out of a Link header. The address may itself hold commas — ?affiliation=owner,collaborator — so the header is read entry by entry from each "<", never split on ",".

func OAuthFields

func OAuthFields(help string) []api.Field

OAuthFields are the OAuth application's client ID and secret.

func OAuthStep added in v0.10.0

func OAuthStep(label, title string, links []api.Link, do ...string) api.Step

OAuthStep registers an OAuth application on the forge and asks for its client ID and secret.

func SCPURL

func SCPURL(user, host, port, path string) string

SCPURL is the scp-like SSH address of a repository on host at path, for the default port. With a port it is the ssh:// form, which is the only one that can carry one.

func SSHCredential

func SSHCredential(repo RepoURL, sshHost string, key, passphrase secret.Value, knownHosts string) api.GitCredential

SSHCredential is an SSH key, for the repository at repoURL. An HTTPS address is turned into the SSH one for the same path on sshHost, since a deploy key cannot be used over HTTPS; sshHost is the host's own when empty.

func SSHFields

func SSHFields(knownHostsHelp string) []api.Field

SSHFields are the private key, its passphrase and the host keys.

func SSHKeyStep added in v0.10.0

func SSHKeyStep(k SSHKey) api.Step

SSHKeyStep makes a key, adds its public half on the forge, and asks for the private half and, with KeyScan, the host keys.

func ScopeField

func ScopeField(label, help, placeholder string) api.Field

func ScopeSegments

func ScopeSegments(scope string) []string

ScopeSegments splits a scope setting — "acme", "acme/platform", "acme/Payments" — into its parts, ignoring slashes at either end.

func ScopeStep added in v0.10.0

func ScopeStep(label, title string) api.Step

ScopeStep is a forge's last step: what the connection is limited to, in the forge's own word for it, such as an owner or a group.

func SetCallback added in v0.10.0

func SetCallback(field string) string

SetCallback is the action that enters Pando's OAuth callback in the forge's field of that name.

func StatusError

func StatusError(provider string, status int) error

StatusError turns a forge's HTTP status into a message a person can act on (R-105), or nil for a success.

A forge refusing the connection's credential is an adapter failure, never AUTH_* or PERM_*: those are answered 401 and 403, which say the person calling Pando is not signed in or not allowed, and a client acts on that.

func TokenCredential

func TokenCredential(username string, token secret.Value, caBundle []byte) api.GitCredential

TokenCredential is HTTPS basic authentication with a token as the password.

func TokenField

func TokenField(label, help string, shown ...string) api.Field

func UsernameField

func UsernameField(help, placeholder string, shown ...string) api.Field

func WhenMethod added in v0.10.0

func WhenMethod(methods ...string) *api.Condition

WhenMethod shows a step only for the given sign-in methods.

Types

type Client

type Client struct {
	HTTP *http.Client

	// Provider names the forge in messages.
	Provider string

	// Authorize sets the request's credentials.
	Authorize func(*http.Request)
}

Client calls a forge's JSON API.

func (Client) Do

func (c Client) Do(ctx context.Context, method, url string, body io.Reader, out any) (string, error)

Do sends a request and decodes a JSON answer into out, which may be nil. It returns the next page's address from a Link header, if there is one.

func (Client) Get

func (c Client) Get(ctx context.Context, url string, out any) (string, error)

Get is Do with GET.

type OAuth

type OAuth struct {
	// Provider names the provider in messages: "GitHub", "GitLab".
	Provider string

	ClientID     string
	ClientSecret secret.Value

	// DeviceURL is the device authorization endpoint (RFC 8628). Empty when
	// the provider has none.
	DeviceURL string

	// AuthorizeURL and TokenURL are the authorization code endpoints.
	AuthorizeURL string
	TokenURL     string

	Scopes []string

	// BasicClientAuth sends the client ID and secret as HTTP basic
	// authentication to the token endpoint rather than in the form, for a
	// provider that accepts only that (Bitbucket Cloud).
	BasicClientAuth bool

	// HTTP is the client to call the provider with.
	HTTP *http.Client
}

OAuth is one provider's OAuth 2.0 endpoints and client.

func (OAuth) BeginDevice

func (o OAuth) BeginDevice(ctx context.Context, now time.Time) (api.Authorization, error)

BeginDevice starts a device authorization.

func (OAuth) BeginWeb

func (o OAuth) BeginWeb(req api.AuthorizationRequest, extra url.Values) (api.Authorization, error)

BeginWeb makes the URL to send the person's browser to, with a PKCE challenge whose verifier is the flow core keeps.

func (OAuth) CompleteWeb

CompleteWeb exchanges the code the callback received.

func (OAuth) Fresh

func (o OAuth) Fresh(ctx context.Context, t Tokens, now time.Time) (Tokens, bool, error)

Fresh returns tokens that work now: these, or refreshed ones when the access token has expired or will within a minute and there is a refresh token. The bool says they were refreshed, and so must be stored (GitCredential.Rotated).

func (OAuth) PollDevice

func (o OAuth) PollDevice(ctx context.Context, flow secret.Value, now time.Time) (api.AuthorizationResult, error)

PollDevice asks once whether a device authorization was approved.

type RepoURL

type RepoURL struct {
	// SSH says the address is an SSH one: ssh://host/path or git@host:path.
	SSH bool

	// Host is the host name, lowercased, without a port.
	Host string

	// Port is the port, if one was written.
	Port string

	// User is the user in an SSH address, usually "git".
	User string

	// Path is the repository's path on the host with no leading slash and no
	// trailing ".git": "acme/api", "acme/platform/api",
	// "v3/acme/Payments/api" for an Azure DevOps SSH address.
	Path string
}

RepoURL is a repository address, read.

func ParseRepoURL

func ParseRepoURL(raw string) (RepoURL, error)

ParseRepoURL reads https://host/owner/repo(.git), ssh://user@host[:port]/owner/repo(.git) and the scp-like user@host:owner/repo(.git).

func (RepoURL) Segments

func (u RepoURL) Segments() []string

Segments is Path split on "/".

type SSHKey added in v0.10.0

type SSHKey struct {
	Label, Title string

	// File is the key's file name: ssh-keygen writes File and File.pub.
	File string

	// Type is ssh-keygen's key type arguments. Empty is -t ed25519.
	Type string

	// Add is how to add File.pub on the forge, in its own words.
	Add []string

	// KeyScan, when set, is the ssh-keyscan command to run for the host keys,
	// as it reads after "Run ".
	KeyScan string
}

SSHKey is a forge's step for adding an SSH key.

type Settings

type Settings struct {
	Method string `json:"method"`

	// Host is the forge's host: "github.com", "gitlab.acme.internal".
	Host string `json:"host"`

	// Scope limits the connection to an owner, group, workspace or project
	// on the host. Empty is the whole host.
	Scope string `json:"scope"`

	// APIURL overrides where the forge's API is, for a self-managed one
	// whose API is not where the forge's default says.
	APIURL string `json:"api_url"`

	// Username goes beside a token, for hosts that want one.
	Username string `json:"username"`

	KnownHosts string `json:"known_hosts"`
	CABundle   string `json:"ca_bundle"`

	ClientID string `json:"client_id"`

	// Credentials are filled in by core from adapter_credentials (O-20);
	// never stored in config.
	Credentials map[string]secret.Value `json:"credentials"`
}

Settings are the settings every source adapter shares. A forge's own settings struct embeds it.

func (Settings) CA

func (s Settings) CA() []byte

CA is the CA bundle setting, read. Validate has already refused a bad one.

func (Settings) Credential

func (s Settings) Credential(field string) secret.Value

Credential is one credential field, or the zero value.

func (*Settings) Validate

func (s *Settings) Validate(provider string, methods []string, defaultHost string) error

Validate checks the shared settings for the method chosen. methods lists the methods the forge offers.

type Tokens

type Tokens struct {
	Access    secret.Value
	Refresh   secret.Value
	ExpiresAt time.Time
}

Tokens is what an oauth connection was configured with.

func TokensFrom

func TokensFrom(creds map[string]secret.Value) Tokens

TokensFrom reads the stored token fields out of a connection's credentials.

func (Tokens) Fields

func (t Tokens) Fields() map[string]secret.Value

Fields is the tokens as credential fields, to store.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL