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

access

package
v0.1.2682 Latest Latest
Warning

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

Go to latest
Published: Nov 2, 2026 License: MIT Imports: 22 Imported by: 0

Documentation

Overview

Package access keeps the named API keys issued by the gateway.

Index

Constants

View Source
const (
	MinTTL = time.Minute
	MaxTTL = 30 * 24 * time.Hour
)

MinTTL and MaxTTL bound how long an issued key lives.

View Source
const MaxDays = 3650

MaxDays is the longest "days" cycle, ten years.

View Source
const MaxHours = 8760

MaxHours is the longest "hours" cycle, a year; a longer one is a "days" cycle.

View Source
const MaxLimits = 5

MaxLimits is how many limits one key can have (#2227).

View Source
const Prefix = "sk-magpie-key-"

Variables

View Source
var LANChanged = func() {}

LANChanged is called after sharing is turned on or off, or its key made anew: what was given the key goes on with the one there is now (the library's MCP servers relayed to an agent in a WSL distro under NAT).

View Source
var Now = time.Now

Now is when Update sets or resets a limit. A variable for the tests.

View Source
var Periods = []string{"day", "week", "month", "days", "hours"}

Periods are the windows a limit can be set for.

Functions

func CleanAccounts added in v0.1.1076

func CleanAccounts(in []string) ([]string, error)

CleanAccounts is a key's account list as kept (#905): each entry "<provider>/<account>", an account named by its stable id — or by the name it is shown by, resolved to that id, so the command line reads while the list keeps what a rename doesn't move — and a key by its fingerprint; trimmed, told apart in lower case as accounts are, each once, in the order given. Every account the entry names must be one its provider has now, so a typo can't quietly hold a key to nothing; one gone later — a key rotated, an account signed out — is kept as it is, matching nothing.

func CleanModels added in v0.1.990

func CleanModels(in []string) ([]string, error)

CleanModels is a key's model list as kept (#882): each pattern trimmed, empty and repeated ones dropped. A pattern names a provider and a model, "<provider>/<model>", every model of one, "<provider>/*", or a routing group, "group/<name>".

func ConfigureLAN

func ConfigureLAN(on, rotate bool) error

ConfigureLAN starts sharing with a named key. Rotation preserves the key's identity, name and enabled state.

func Default added in v0.1.1280

func Default(secret string) bool

Default says secret is the sharing key magpie itself made (the default key ConfigureLAN keeps), whether sharing is on now or not: magpie's own, never one the user brought, so a write that keeps "a caller key of the gateway's own the user put there" must not keep it (#2545: with sharing off the key stays enabled in the store, Authenticate still took it, and Rekey could no longer bring gateway.Token back). An older magpie kept it in the settings alone; that value answers too, short of its revoked mirror.

func HeldModels added in v0.1.2094

func HeldModels(models, accounts []string) []string

HeldModels is the models a key that lists models and accounts may use. A key that names some accounts and no model may use only the models of those accounts' providers, "<provider>/*" each (Linka on Discord): in the Gateway page's "Models this key may use", ticking an account and no model narrows the key to that account, and never leaves it every model of every other provider, as it did when the accounts held only the providers they name (#905). A key that lists models is held to those, its accounts holding the providers they name, as before.

func LANSecret added in v0.1.972

func LANSecret() string

LANSecret is the key magpie shares the gateway on the local network with (the default key ConfigureLAN made), for an agent of this computer's that reaches it from beyond loopback — one in a WSL distro under NAT, whose requests the gateway takes only with a named key; "" while the gateway isn't shared, or that key is off.

func Managed

func Managed(secret string) bool

func MigrateLegacyLANKey

func MigrateLegacyLANKey() error

MigrateLegacyLANKey makes the old Settings key a normal, revocable caller key. Keep LANKey for older Magpie versions; LANKeyID marks a completed migration so the retained credential cannot resurrect a removed key.

func MigrateLegacyLANKeyBestEffort

func MigrateLegacyLANKeyBestEffort()

func ModelAllowed added in v0.1.990

func ModelAllowed(patterns []string, id string) bool

ModelAllowed says id ("<provider>/<model>") matches one of patterns, letter case aside; a "*" in a pattern stands for any run of characters, slashes too. No patterns allow every model.

func MoveModel added in v0.1.2345

func MoveModel(from, to string) error

MoveModel gives every key's models that name from ("<provider>/<model>", letter case aside) to instead. A pattern ("relay/*") is the user's own and is left as written.

func Named added in v0.1.1100

func Named(secret string) bool

Named: secret has a named gateway key's form (sk-magpie-…), or is the key's own value a user gave it (Change.Secret), so a request from this computer with one is counted and limited as that key, as a sk-magpie- key is.

func On added in v0.1.2240

func On(id string) bool

On: the key with this id is one Authenticate takes, in the store and not turned off, or the legacy sharing key not yet written there; false when the store can't be read.

func Path

func Path() string

func Prune added in v0.1.2334

func Prune() (int, error)

Prune removes the keys that expired over expiredKept ago and those issued under a key no longer in the store, and says how many.

func ReplaceAccount added in v0.1.1220

func ReplaceAccount(pid, was, now string) (int, error)

ReplaceAccount moves every key's account list from one of provider pid's keys to the fingerprint it has now (#1869: the key's value replaced in place), so a key held to it is held to it still. It returns how many keys it moved.

func Restore

func Restore(keys []Key) error

Restore replaces the gateway credentials when restoring their settings.

func RevokeIssued added in v0.1.2334

func RevokeIssued(id, by string) error

RevokeIssued removes the issued key id. by is the key asking: it may remove only a key issued under it; "" is the user, who may remove any issued key (a key of their own they remove with remove-key).

func Update

func Update(action string, in Change) (string, error)

Update writes the named key store atomically.

func Window added in v0.1.675

func Window(period string, now time.Time) (start, reset time.Time)

Window is the calendar window of period that now is in, in now's location: its start and when the next begins.

func WithIdentity

func WithIdentity(ctx context.Context, who Identity) context.Context

Types

type Change

type Change struct {
	Key  string `json:"key"`
	Name string `json:"name"`
	// Limit is what "limit-key" sets; nil or Unlimited takes the limit off.
	Limit *Limit `json:"limit,omitempty"`
	// Index is which of the key's limits "limit-key" sets and
	// "reset-limit-key" resets (#2227), counted from 0: one past the last
	// adds a limit, a nil Limit there removes that one. Without it,
	// "limit-key" makes Limit the key's only limit, and "reset-limit-key"
	// resets every one. For "move-key" it is the place in the list the key
	// goes to, counted from 0.
	Index *int `json:"index,omitempty"`
	// Models is what "models-key" sets; none lets the key use every model.
	Models []string `json:"models,omitempty"`
	// Accounts is what "accounts-key" sets (#905); none lets the key use
	// every account and key.
	Accounts []string `json:"accounts,omitempty"`
	// Quotas is what "quotas-key" sets (#2216).
	Quotas bool `json:"quotas,omitempty"`
	// ReadOnly is what "access-key" sets, and "add-key" gives the new key:
	// it may read stats and use no model (Key.ReadOnly).
	ReadOnly bool `json:"readOnly,omitempty"`
	// Issues is what "issuer-key" sets: the key may issue short-lived
	// keys under itself (Key.Issues).
	Issues bool `json:"issues,omitempty"`
	// Secret is the value "add-key" gives the new key, one its clients
	// already send (love1sbug on X: keys handed out from another gateway);
	// "" for one magpie makes.
	Secret string `json:"secret,omitempty"`
}

type Identity

type Identity struct {
	KeyID, KeyName string
	Limit          *Limit
	More           []Limit
	Models         []string
	Accounts       []string
	Quotas         bool
	ReadOnly       bool
	// Expires is when the key stops working, its issuer's expiry if
	// sooner; zero for never.
	Expires time.Time
	// Issuer is the key it was issued under: its limits hold this key's
	// requests too, and count what this key spends.
	Issuer *Identity
	// Issues: the key may issue keys under itself.
	Issues bool
	// Default: the key is the sharing key magpie made itself (Default),
	// the one it writes into this computer's own agents that reach the
	// gateway from beyond loopback, never one the user made for someone
	// else.
	Default bool
	// Group is the routing group, by name, whose own accounts hold the
	// request as well (HeldToGroup); "" when none does.
	Group string
}

Identity is the gateway key a request came with, its budget, the models and the accounts it may use.

func Authenticate

func Authenticate(secret string) (Identity, bool)

Authenticate reloads the store so revocation takes effect in running gateways. An expired key, or one whose issuer no longer lets it in, is refused as one turned off is; Check says why.

func Caller

func Caller(ctx context.Context) Identity

func Check added in v0.1.2334

func Check(secret string) (Identity, error)

Check is Authenticate with why a key it knows is turned away: a *Refused for one expired or whose issuer no longer lets it in.

func (Identity) Allows added in v0.1.990

func (who Identity) Allows(ids ...string) bool

Allows says one of ids is among the key's models; any, for a key that lists none. An Identity's models are already HeldModels: a key that names accounts and no model may use its accounts' providers' models.

func (Identity) AllowsAccount added in v0.1.1076

func (who Identity) AllowsAccount(pid, ref string) bool

AllowsAccount says the provider pid's account or key ref is among the key's accounts — "<provider>/<ref>", told apart in lower case, as accounts are. The list holds a key to some accounts **of the providers it names**: a provider it names no account of, the key uses as it always did, its every account and key. Any, for a key that lists none.

func (Identity) HeldToGroup added in v0.1.2618

func (who Identity) HeldToGroup(group string, accounts []string) Identity

HeldToGroup is who held to a routing group's accounts too (accounts, a Group's Accounts, in the key's form): a provider the group names is used only on the accounts the group names that the key may use as well, none when the two share none, never one either leaves out; a provider only the key names, on the key's; one neither names, on every account it has. Group is set to the group's name, for the error to say whose accounts held the request. A group naming no account is who as it is. Everything that holds a request to its key's accounts (AllowsAccount) holds it to the group's then, by the one rule.

func (Identity) IssuerID added in v0.1.2334

func (who Identity) IssuerID() string

IssuerID is the id of the key who was issued under, "" for none.

func (Identity) Limited added in v0.1.2334

func (who Identity) Limited() bool

Limited: a request of who's is held to a limit, its own key's or the key it was issued under's.

func (Identity) Limits added in v0.1.1242

func (who Identity) Limits() []*Limit

Limits are the limits who's key holds it to, as Key.Limits.

func (Identity) Restricted added in v0.1.990

func (who Identity) Restricted() bool

Restricted says the key may use only the models or accounts it lists.

func (Identity) ShownAccounts added in v0.1.2618

func (who Identity) ShownAccounts() []string

ShownAccounts is who's accounts as a message lists them: the entries HeldToGroup adds to name a provider with none of its accounts left out.

type Issue added in v0.1.2334

type Issue struct {
	Name string
	TTL  time.Duration
	// Models and Accounts hold the key as Key's do; with an issuer, each
	// must be one the issuer may use, and none takes the issuer's.
	Models   []string
	Accounts []string
	// Tokens and Cost cap what the key may spend over its whole life.
	Tokens   int64
	Cost     float64
	ReadOnly bool
	// Issuer is the id of the key it is issued under; "" for one the
	// user issues themselves (the command line, or loopback with no key).
	Issuer string
}

Issue is what IssueKey makes.

type Issued added in v0.1.2334

type Issued struct {
	ID       string    `json:"id"`
	Name     string    `json:"name"`
	Key      string    `json:"key"`
	Expires  time.Time `json:"expires"`
	Issuer   string    `json:"issuer,omitempty"`
	Models   []string  `json:"models,omitempty"`
	Accounts []string  `json:"accounts,omitempty"`
	Limit    *Limit    `json:"limit,omitempty"`
	ReadOnly bool      `json:"readOnly,omitempty"`
}

Issued is a key IssueKey made, its secret told once.

func IssueKey added in v0.1.2334

func IssueKey(in Issue) (Issued, error)

IssueKey makes a short-lived key. It never outlives its issuer, nor is let use a model or account its issuer may not.

type Key

type Key struct {
	ID     string `json:"id"`
	Name   string `json:"name"`
	Off    bool   `json:"off,omitempty"`
	LAN    bool   `json:"lan,omitempty"` // default key and durable migration marker
	Secret string `json:"secret,omitempty"`
	Masked string `json:"masked,omitempty"`
	// Limit is the key's own budget (#585); nil for none.
	Limit *Limit `json:"limit,omitempty"`
	// More are its limits after the first (#2227), each a window of its
	// own: a request passes only while every one has something left. A
	// key has them only beside a Limit, which an older magpie still reads.
	More []Limit `json:"moreLimits,omitempty"`
	// Models are the models the key may use (#882): "<provider>/<model>",
	// "<provider>/*" or a group's "group/<name>"; none for every model,
	// unless it lists accounts: then its accounts' providers' (HeldModels).
	Models []string `json:"models,omitempty"`
	// Accounts are the accounts and keys the key may use (#905), as
	// "<provider>/<account>": a signed-in account by its stable id, a
	// key by its fingerprint; none for every account, as keys always did.
	Accounts []string `json:"accounts,omitempty"`
	// Quotas lets a key held to a budget, models or accounts be told the
	// quotas of what it may use (#2216): the cards of the providers whose
	// every model it may use, of the accounts and keys it may use, names
	// and balances included. Off, it is told none (#1981).
	Quotas bool `json:"quotas,omitempty"`
	// ReadOnly holds the key to reading this magpie's stats (Steven on
	// Discord: a desk display polling quotas and usage, its key kept in
	// a device's flash): the gateway answers it only the routes in its
	// readOnlyRoutes and refuses it every other, every model, MCP and
	// write route among them. Off, the key may do what its other limits let it.
	ReadOnly bool `json:"readOnly,omitempty"`
	// Expires is when the key stops working (an issued key, IssueKey);
	// zero for one that doesn't. Prune removes it a while after.
	Expires time.Time `json:"expires,omitzero"`
	// Issuer is the id of the key it was issued under, which bounds it
	// (issue.go); "" for one the user made or issued themselves.
	Issuer string `json:"issuer,omitempty"`
	// Issues lets the key issue short-lived keys under itself
	// (POST /v1/magpie/keys); an issued key never can.
	Issues bool `json:"issues,omitempty"`
}

func Export

func Export() ([]Key, error)

Export returns credentials only for the encrypted backup bundle.

func IssuedBy added in v0.1.2334

func IssuedBy(by string) ([]Key, error)

IssuedBy lists the keys issued under the key by ("" for those the user issued themselves), without their secrets.

func List

func List() ([]Key, error)

List never returns credentials; only the administrator's copy action does.

func (Key) Limits added in v0.1.1242

func (k Key) Limits() []*Limit

Limits are k's limits, its Limit first; none for a key with no limit. Each holds the key on its own: a request passes only while all of them have something left.

type Limit added in v0.1.675

type Limit struct {
	Period string `json:"period"`
	// Days is a "days" limit's cycle, 1 to MaxDays; 0 for the others.
	Days int `json:"days,omitempty"`
	// Hours is an "hours" limit's cycle, 1 to MaxHours; 0 for the others.
	Hours      int     `json:"hours,omitempty"`
	Tokens     int64   `json:"tokens,omitempty"`
	Cost       float64 `json:"cost,omitempty"`
	CacheReads bool    `json:"cacheReads,omitempty"`
	// Since is magpie's, never the caller's (Update sets it): for "days"
	// and "hours", when the first cycle began, the limit set or last reset; for a
	// calendar period, when it was last reset, so a call before it in
	// the same window doesn't count. Zero for a calendar limit never
	// reset, as every limit from before #1509 is.
	Since time.Time `json:"since,omitzero"`
}

Limit is a gateway key's budget for a window: a calendar one in local time (#585), a day from midnight, a week from Monday's midnight, a month from the 1st's; or a cycle of Days days (#1509, period "days") or of Hours hours (#2102, period "hours", a subscription's 5-hour window's pace), the first from when the limit was set, each next one a cycle after the last. Tokens counts each call's uncached input, output (reasoning included) and cache writes, and its cache reads too when CacheReads is set; Cost is an estimate in US dollars at the prices magpie shows on the Usage page, not a vendor's bill. A cap of 0 is no cap; a limit with neither is no limit.

func (*Limit) Limited added in v0.1.675

func (l *Limit) Limited() bool

Limited: l caps something.

func (*Limit) Per added in v0.1.1166

func (l *Limit) Per() string

Per is the window as a sentence ends it: "day", "week", "month", "10-day cycle" or "5-hour cycle".

func (*Limit) Valid added in v0.1.675

func (l *Limit) Valid() (*Limit, error)

Valid is l as it is kept: nil for no limit, an error for one that can't be. Since is left as it came; Update decides it.

func (*Limit) Window added in v0.1.1166

func (l *Limit) Window(now time.Time) (start, reset time.Time)

Window is the window l counts in at now, in now's location: when it began and when the next begins. A "days" or "hours" cycle is counted in absolute time, 24h a day whatever the clocks do, so a restart or a change of time zone or summer time keeps it; one with no Since runs from the Unix epoch. A calendar window starts at Since instead when the key was reset in it.

type Refused added in v0.1.2334

type Refused struct{ Why string }

Refused is why Check turned away a key it knows: expired, or bounded by an issuer that no longer lets it in. The gateway says it with a 401 on every route, from this computer too.

func (*Refused) Error added in v0.1.2334

func (r *Refused) Error() string

Jump to

Keyboard shortcuts

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