ca243a2d50
executus CI / test (push) Failing after 24s
Batteries-included agent-harness base, extracted from mort's agent layer. This first cut establishes the module + the zero-coupling core primitives: - lane, dispatchguard, pendingattach, run/progress.go: moved verbatim from mort - config: host config Source seam + env-var default (nil-safe helpers) - deliver: output-egress seam + Discard/Stdout defaults - identity: AdminPolicy + MemberResolver seams (nil-safe) - fanout: programmatic N×M swarm (bounded global + per-key concurrency) - README/CLAUDE.md with the vibe-coded banner; CI with Go gates + the "core stays majordomo+stdlib only" invariant Core builds with stdlib only today; majordomo enters at P1 (model/structured). go build/vet/test -race all green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
55 lines
1.9 KiB
Go
55 lines
1.9 KiB
Go
// Package identity is executus's caller-identity seam.
|
|
//
|
|
// A CallerID is an opaque string the host assigns (a Discord snowflake, an OAuth
|
|
// subject, a CI principal). Two optional capabilities hang off it: AdminPolicy
|
|
// gates authoring-class actions, and MemberResolver supplies per-caller
|
|
// enrichment (timezone, display name) for tools that want it. Both are nil-safe
|
|
// so a host that has no notion of "members" or "admins" wires nothing — the
|
|
// defaults treat everyone as a non-admin unknown.
|
|
package identity
|
|
|
|
import "context"
|
|
|
|
// Member is optional per-caller enrichment. Attrs carries host-specific extras
|
|
// (a seerr user id, a persona blurb) without widening this struct per host.
|
|
type Member struct {
|
|
ID string
|
|
DisplayName string
|
|
Timezone string
|
|
Attrs map[string]string
|
|
}
|
|
|
|
// AdminPolicy decides whether a caller may perform authoring-class actions
|
|
// (saving a shared skill, registering an agent). Default: NonAdmin.
|
|
type AdminPolicy interface {
|
|
IsAdmin(ctx context.Context, callerID string) bool
|
|
}
|
|
|
|
// NonAdmin is the default policy: nobody is an admin. A single-principal host
|
|
// (a CI job) typically overrides with a constant-true policy for its principal.
|
|
type NonAdmin struct{}
|
|
|
|
func (NonAdmin) IsAdmin(context.Context, string) bool { return false }
|
|
|
|
// MemberResolver supplies optional enrichment for a CallerID. ok=false means the
|
|
// member is unknown (the harness then proceeds without enrichment).
|
|
type MemberResolver interface {
|
|
Resolve(ctx context.Context, callerID string) (Member, bool)
|
|
}
|
|
|
|
// IsAdmin is the nil-safe accessor: a nil AdminPolicy denies.
|
|
func IsAdmin(p AdminPolicy, ctx context.Context, callerID string) bool {
|
|
if p == nil {
|
|
return false
|
|
}
|
|
return p.IsAdmin(ctx, callerID)
|
|
}
|
|
|
|
// Resolve is the nil-safe accessor: a nil resolver returns an unknown member.
|
|
func Resolve(r MemberResolver, ctx context.Context, callerID string) (Member, bool) {
|
|
if r == nil {
|
|
return Member{}, false
|
|
}
|
|
return r.Resolve(ctx, callerID)
|
|
}
|