Documentation
¶
Index ¶
- Constants
- func AgentRegistrationFromContext(ctx context.Context) string
- func AgentTokenCredentialKey(token string) string
- func GenerateAgentToken() (string, error)
- func LooksLikeAgentToken(token string) bool
- func ModeFromContext(ctx context.Context) string
- func PublicReadFromContext(ctx context.Context) bool
- func RequestToken(request *http.Request) (string, bool, error)
- func StaticCredentialKey(tokenID string) string
- func TokenConfigCredentialKey(token TokenConfig) string
- func TokenConfigID(token TokenConfig) string
- func WithAgentRegistration(ctx context.Context, policy string) context.Context
- func WithClaims(ctx context.Context, claims Claims) context.Context
- func WithMode(ctx context.Context, mode string) context.Context
- func WithPublicRead(ctx context.Context, enabled bool) context.Context
- type Claims
- func (c Claims) AgentIDs() []string
- func (c Claims) AgentToken() bool
- func (c Claims) Allows(scope Scope) bool
- func (c Claims) AllowsAgent(agentID string) bool
- func (c Claims) AllowsAny(scopes []Scope) bool
- func (c Claims) HasAgentRestriction() bool
- func (c Claims) Network() string
- func (c Claims) Operator() bool
- func (c Claims) StaticToken() bool
- type Config
- type Error
- type Policy
- func (p *Policy) AgentRegistration() string
- func (p *Policy) AuthenticateRequest(request *http.Request, scope Scope) (Claims, error)
- func (p *Policy) AuthenticateToken(value string, scope Scope) (Claims, error)
- func (p *Policy) Bearer() bool
- func (p *Policy) CheckOrigin(request *http.Request) bool
- func (p *Policy) Enabled() bool
- func (p *Policy) IsSecureRequest(request *http.Request) bool
- func (p *Policy) Mode() string
- func (p *Policy) None() bool
- func (p *Policy) Open() bool
- func (p *Policy) PublicRead() bool
- func (p *Policy) StaticClaimsForToken(value string) (Claims, bool)
- func (p *Policy) TrustForwardedProto() bool
- type Scope
- type TokenConfig
Constants ¶
const ( ModeNone = "none" ModeBearer = "bearer" ModeOpen = "open" )
const ( AgentRegistrationDisabled = "disabled" AgentRegistrationToken = "token" AgentRegistrationOpen = "open" )
const AgentTokenPrefix = "magt_v1_"
const CookieName = "moltnet_auth"
Variables ¶
This section is empty.
Functions ¶
func AgentRegistrationFromContext ¶ added in v0.1.11
func AgentTokenCredentialKey ¶ added in v0.1.1
func GenerateAgentToken ¶ added in v0.1.1
func LooksLikeAgentToken ¶ added in v0.1.1
func ModeFromContext ¶ added in v0.1.1
func PublicReadFromContext ¶ added in v0.1.11
func StaticCredentialKey ¶ added in v0.1.1
StaticCredentialKey builds the CredentialKey shape a static auth.tokens[] entry with the given id resolves to.
func TokenConfigCredentialKey ¶ added in v0.1.12
func TokenConfigCredentialKey(token TokenConfig) string
TokenConfigCredentialKey is StaticCredentialKey(TokenConfigID(token)) -- the CredentialKey a static claims built from token resolves to.
func TokenConfigID ¶ added in v0.1.12
func TokenConfigID(token TokenConfig) string
TokenConfigID returns token's configured id, or -- for a hand-written token with no id set -- a stable id derived from a truncated SHA-256 hash of its value, so every static token has a non-empty, deterministic id to key claims and config writebacks by.
func WithAgentRegistration ¶ added in v0.1.11
Types ¶
type Claims ¶
type Claims struct {
// TokenID is the auth.tokens[] id this credential was minted from
// (NewStaticClaims) or, for a pair-scoped credential written by `pair
// invite`/`pair <code>`, the pairing id it is minted identical to (see
// rooms.pairingForPairScopedContext's doc comment,
// internal/rooms/federation_access.go, for why that identity binding
// matters).
TokenID string
// CredentialKey identifies this credential's shape and origin for
// logging and equality checks: StaticToken/AgentToken below classify it
// by prefix, and StaticCredentialKey/TokenConfigCredentialKey construct
// the static-token form of it.
CredentialKey string
// contains filtered or unexported fields
}
Claims is the resolved shape of an authenticated credential: which scopes it carries, which agent ids (if any) it is restricted to, which remote network (if any) it is bound to, and the credential key identifying it for logging and comparison. Every gate in this codebase that decides "can this caller do X" reads a Claims, never the raw token, see authn.ClaimsFromContext (context.go) for how one lands on a request context.
func NewAgentTokenClaims ¶ added in v0.1.1
NewAgentTokenClaims builds the Claims for a runtime-issued agent token: restricted to agentID (when non-empty) and scoped to exactly [observe, write, attach] -- never admin or pair, so an agent token can never create rooms or read /metrics.
func NewCredentialClaims ¶ added in v0.1.1
NewCredentialClaims builds a bare Claims carrying only credentialKey -- no scopes, no network, no agent restriction. Used where a caller's identity needs recording (e.g. for logging) but no authorization scopes apply.
func NewStaticClaims ¶ added in v0.1.1
func NewStaticClaims(config TokenConfig) Claims
NewStaticClaims builds the Claims for a static auth.tokens[] entry: TokenID and CredentialKey from the token's (possibly derived) id, and its configured network/scopes/agent restrictions carried straight across.
func (Claims) AgentIDs ¶ added in v0.1.11
AgentIDs returns every agent id these claims are restricted to, in no particular order. Empty when HasAgentRestriction is false.
func (Claims) AgentToken ¶ added in v0.1.1
AgentToken reports whether this credential is a runtime-issued agent token (NewAgentTokenClaims), as opposed to a static auth.tokens[] entry.
func (Claims) Allows ¶
Allows reports whether these claims carry scope. Claims with no scopes at all (the zero value) allow nothing.
func (Claims) AllowsAgent ¶
AllowsAgent reports whether these claims may act as agentID. An unrestricted credential (HasAgentRestriction false) allows every agent id; an agent-restricted one (e.g. NewAgentTokenClaims) allows only the ids it was minted for.
func (Claims) AllowsAny ¶ added in v0.1.1
AllowsAny reports whether these claims carry at least one of scopes.
func (Claims) HasAgentRestriction ¶ added in v0.1.1
HasAgentRestriction reports whether these claims are scoped to a specific, non-empty set of agent ids rather than every agent.
func (Claims) Network ¶ added in v0.1.14
Network returns the remote network id this credential is bound to, or "" if it carries no confirmed binding. A pair-scoped credential's binding is only ever set once the peer's real remote_network_id is known -- see rooms.pairingForPairScopedContext's doc comment (internal/rooms/federation_access.go) for which pairing directions have one and which do not.
func (Claims) Operator ¶ added in v0.1.18
Operator reports whether these claims describe an operator credential -- this network's own owner -- rather than a peer/pairing credential or a per-agent one. An operator is defined, everywhere in this codebase, as a credential carrying both `admin` and `write`, regardless of which other scopes it also carries.
The "regardless" matters: `--bearer` init used to mint (and configs in the wild still hold) an operator token scoped [observe, write, admin, pair]. Every gate that inspects the `pair` scope must treat that token as an operator and not as a peer, or it looks for a pairing named "operator", finds none, and denies the owner every write and hides every room from them (F1). Defining "operator" by scope-counting, or by the mere absence of `pair`, is what broke.
This predicate lives here, on Claims, because it was previously copied verbatim into internal/rooms/federation_access.go and internal/transport/federation_discovery.go and open-coded inline in three more gates (rooms/access_policy.go canWriteRoom, rooms/sender_identity.go, transport/skill_markdown.go). Five independent spellings of one trust-boundary rule meant loosening any single one of them still passed every test. There is now exactly one definition, in the package that owns caller-identity policy, and every gate calls it.
func (Claims) StaticToken ¶ added in v0.1.1
StaticToken reports whether this credential's key is the static auth.tokens[]-derived shape StaticCredentialKey/TokenConfigCredentialKey produce, as opposed to a runtime-issued agent token.
type Config ¶
type Config struct {
Mode string
PublicRead bool
AgentRegistration string
ListenAddr string
AllowedOrigins []string
TrustForwardedProto bool
// RequirePairNetworkBinding rejects remote-origin pairing messages when
// their pair credential has no bound network (internal/rooms's
// pairCredentialMatchesOrigin). Defaults to false (internal/app's
// defaultConfig, config_load.go): an inbound pair-scoped message that
// claims a remote origin but carries a credential with no confirmed
// network binding is accepted with a logged warning rather than refused
// outright. F3: 7B.2 shipped this defaulting to true on the assumption
// that the inviting side's credential gets bound "once the peer has made
// contact"; no code does that persistence today (see config_load.go's
// field comment), so a strict default left every `pair invite` inviter
// permanently unable to receive from the peer it invited. Set
// `auth.require_pair_network_binding: true` in the config file, or
// MOLTNET_REQUIRE_PAIR_NETWORK_BINDING=true, to opt into the stricter
// posture once you have confirmed (e.g. via `pair show`) that this
// pairing's credential is actually bound. This is a distinct, narrower
// gate than 7B.1's federation-list enforcement
// (internal/rooms/federation_access.go): that one is keyed on credential
// identity and cannot be disabled, this one is keyed on the credential's
// bound network and is operator-configurable.
RequirePairNetworkBinding bool
Tokens []TokenConfig
}
type Policy ¶
type Policy struct {
// contains filtered or unexported fields
}
func (*Policy) AgentRegistration ¶ added in v0.1.11
func (*Policy) AuthenticateRequest ¶
func (*Policy) AuthenticateToken ¶ added in v0.1.1
func (*Policy) PublicRead ¶ added in v0.1.11
func (*Policy) StaticClaimsForToken ¶ added in v0.1.1
func (*Policy) TrustForwardedProto ¶ added in v0.1.15
TrustForwardedProto reports whether the operator has told Moltnet (server.trust_forwarded_proto) that a reverse proxy sits in front of it. Once true, a loopback RemoteAddr no longer proves a request originated on this machine; it just means the proxy connected from here.