Documentation
¶
Overview ¶
Package access owns who may do what (design/subsystems/ authorization-capabilities.md): the capability catalog and the stock roles as compiled data, the words for scopes and subjects, and, in the slices that follow, the decision rule, grants and the directory. AppTown keeps the HTTP doors, the receipts' prose and the resource adapters.
Package access is the authorization rule and its vocabulary: who is asking (principal, caller), what they want (capability, resource, permission), the catalog of capabilities and stock roles, the decision, and the denial. It owns no tables, reads no database, and imports nothing of AppTown, so a decision is testable on its own.
Index ¶
- Constants
- Variables
- func AgentCredential(pr Principal) bool
- func AgentToken(pr Principal) bool
- func CredentialCovers(pr Principal, c Capability) bool
- func CredentialNarrowReason(pr Principal, does string) string
- func GrantApplies(g Grant, c Capability, res Resource) bool
- func GrantHolds(g Grant, c Capability) bool
- func Inherits(c Capability, to ScopeKind) bool
- func InstrumentMay(kind string, c Capability) bool
- func RolesCarrying(c Capability, res Resource) []string
- func ScopeMeans(name string) string
- func ScopeNames() []string
- func ScopesCover(scopes []string, c Capability) bool
- func ValidTokenPurpose(p string) bool
- func WithCaller(ctx context.Context, c Caller) context.Context
- type Actor
- type Authority
- type Authorizer
- type Caller
- type Capability
- type Channel
- type Checked
- type Context
- type Decision
- type Definition
- type Denied
- type Event
- type Facts
- type Grant
- type Permission
- type Person
- type Principal
- type ProjectResources
- type ProjectVisibility
- type ReadAuthorizer
- type Resource
- type Role
- type Scope
- type ScopeKind
Constants ¶
const ( ViaSession = "session" ViaHeader = "header" ViaOpen = "open" ViaTokenCLI = "token-cli" ViaTokenAgent = "token-agent" ViaOAuth = "oauth" ViaChat = "chat" ViaRunStep = "run-step" ViaTicket = "ticket" ViaBinding = "binding" ViaSchedule = "schedule" ViaEval = "eval" ViaWhatIf = "what-if" ViaAnonymous = "anonymous" )
The ways of acting an actor's Via names. A way with a subject is "<way>:<subject>" (token-cli:laptop, chat:<id>, run-step:<step>).
const ( RoleInstanceAdmin = "instance-administrator" RoleStandardsAdmin = "standards-administrator" RoleExecutionAdmin = "execution-administrator" RoleIntegrationAdmin = "integration-administrator" RoleReleaseManager = "release-manager" RoleAuditor = "auditor" RoleProjectCreator = "project-creator" RoleGroupViewer = "group-viewer" RoleGroupMember = "group-member" RoleGroupCreator = "group-project-creator" RoleGroupMaintainer = "group-maintainer" RoleGroupOwner = "group-owner" RoleGroupAuditor = "group-auditor" RoleProjectViewer = "project-viewer" RoleProjectContrib = "project-contributor" RoleProjectMaintainer = "project-maintainer" RoleProjectApprover = "project-approver" RoleProjectOwner = "project-owner" )
Stock role names.
const ( DenyMissingCapability = "missing_capability" DenyOutsideScope = "outside_scope" DenyDelegationNarrow = "delegation_too_narrow" DenyResourceState = "resource_state_conflict" DenySegregation = "segregation_of_duties" DenyQuorum = "quorum_incomplete" DenyReauth = "reauthentication_required" DenyExpiredObjectCap = "expired_object_capability" DenyAccountDisabled = "account_disabled" DenyNotEligible = "not_an_approver" )
The authorization decision (authorization-capabilities.md §12). One rule for every protocol: HTTP guards, the MCP server, the CLI and workers all call Decide and translate its one answer. Root is explicit; other roles are bundles the catalog expands. The rule reads what it needs through Facts, so a decision is testable with no database and the reads happen exactly when the rule asks (grants only after an instrument has been resolved to its person).
Reason codes are stable so a client can act on them; the prose is for the person.
const ( TokenCLI = "cli" TokenAgent = "agent" )
Personal token purposes: every token is made with one, never by default.
const SystemInstrument = "apptown"
SystemInstrument is the instrument AppTown acts under itself: its scheduler, engine, remediation, follow-ups, bindings and system operations. Records from before the AppTown rename name it "forge"; those are history and keep that name, but no current caller carries it.
Variables ¶
var ( ReadCaps = []Capability{CapProjectList, CapProjectRead, CapChangeList, CapChangeRead, CapRunRead, CapEvidenceRead, CapConformanceRead, CapReleaseRead, CapDeploymentRead, CapSecretRead} ContributorCaps = append(append([]Capability{}, ReadCaps...), CapChangeCreate, CapChangeUpdateBrief, CapChangeNarrative, CapChangeWriteRevision, CapChangeAttach, CapChangeRunChecks, CapChangePreview, CapChangeInvokeLane, CapChangeRequestLand, CapEvidenceAttach, CapConformanceRev) MaintainerCaps = append(append([]Capability{}, ContributorCaps...), CapChangeLand, CapChangeAbandon, CapChangeSendBack, CapRunOperate, CapDeploymentOperate, CapProjectServices, CapProjectIntegrations, CapProjectGuidance, CapProjectWorkflow, CapProjectWayOfWorking, CapProjectImport, CapConformanceFix, CapConformanceAI, CapProjectManageMembers, CapSecretBind, CapDeploymentDeploy) OwnerCaps = append(append([]Capability{}, MaintainerCaps...), CapProjectConfigure, CapProjectDelete, CapProjectModelProfile, CapDeploymentBind, CapDeploymentTeardown, CapDeploymentRestore) // Administration capabilities summarized by the account menu. AmenderCaps = []Capability{CapStandardsGuidance, CapStandardsPacks, CapStandardsPolicies, CapExecWorkflows, CapIntegrationServices, CapIntegrationDeps} )
var Definitions = map[Capability]Definition{ CapInstanceReadPublic: {"read the explicitly public instance surface", readInherits, "read"}, CapInstitutionRead: {"see users, groups, roles and grants", nil, "read"}, CapProjectList: {"discover visible projects", readInherits, "read"}, CapProjectRead: {"read one project's source-facing state", readInherits, "read"}, CapProjectCreate: {"create a project for an allowed owning group", []ScopeKind{ScopeGroup}, "mutate"}, CapProjectConfigure: {"change ordinary project metadata", nil, "mutate"}, CapProjectDelete: {"permanently remove a project", nil, "admin"}, CapProjectManageMembers: {"change a project's roster and project roles", nil, "admin"}, CapProjectImport: {"import an external branch or tree", nil, "mutate"}, CapChangeList: {"list changes", readInherits, "read"}, CapChangeRead: {"read a change", readInherits, "read"}, CapChangeCreate: {"open a change", nil, "mutate"}, CapChangeUpdateBrief: {"edit a change's brief", nil, "mutate"}, CapChangeNarrative: {"refresh a change's So far summary", nil, "mutate"}, CapChangeWriteRevision: {"contribute source revisions to a change", nil, "mutate"}, CapChangeAttach: {"attach evidence to a change", nil, "mutate"}, CapChangeRunChecks: {"run a change's checks", nil, "mutate"}, CapChangePreview: {"boot a change's preview", nil, "mutate"}, CapChangeInvokeLane: {"start an allowed lane on a change", nil, "mutate"}, CapChangeSendBack: {"send a change back to its author", nil, "mutate"}, CapChangeAbandon: {"abandon a change", nil, "mutate"}, CapChangeRequestLand: {"hand a proposed tip off for landing", nil, "mutate"}, CapChangeLand: {"operate a landing attempt: restart, resume, complete an unapproved lane", nil, "mutate"}, CapChangeApprove: {"assent at an approval step", nil, "approve"}, CapChangeOverride: {"bypass a failed gate with a reason", nil, "approve"}, CapRunRead: {"read a run", readInherits, "read"}, CapRunOperate: {"advance, retry or stop a run", nil, "mutate"}, CapEvidenceRead: {"read evidence", readInherits, "read"}, CapEvidenceAttach: {"attach evidence to a run", nil, "mutate"}, CapConformanceRead: {"read conformance", readInherits, "read"}, CapConformanceRev: {"run a read-only conformance review", nil, "mutate"}, CapConformanceAI: {"confirm one exact AI verdict", nil, "approve"}, CapConformanceFix: {"start a remediation", nil, "mutate"}, CapExceptionApprove: {"approve a conformance exception in a dimension", nil, "approve"}, CapExceptionRevoke: {"revoke a conformance exception", nil, "approve"}, CapProjectWayOfWorking: {"select the project's way of working", nil, "execute"}, CapProjectGuidance: {"change what guidance the project adopts", nil, "execute"}, CapProjectServices: {"change the project's attached services", nil, "execute"}, CapProjectIntegrations: {"attach or wire integrations to the project", nil, "execute"}, CapProjectModelProfile: {"choose the project's model profile", nil, "execute"}, CapProjectWorkflow: {"select or change the project's workflow copy", nil, "execute"}, CapReleaseRead: {"read releases", readInherits, "read"}, CapReleasePromote: {"promote a release to a wider tier", nil, "release"}, CapDeploymentRead: {"read deployments", readInherits, "read"}, CapDeploymentOperate: {"restart or rebuild a deployment, and read its parts' recent logs", nil, "mutate"}, CapDeploymentBind: {"point a standing deployment at a target", nil, "mutate"}, CapDeploymentDeploy: {"ship a bundle to a standing deployment", nil, "release"}, CapDeploymentTeardown: {"remove a deployment's deployment (never its data)", nil, "mutate"}, CapDeploymentRestore: {"fill a deployment's data from a copy, or check a copy comes back", nil, "mutate"}, CapIdentityUsers: {"manage user accounts", nil, "admin"}, CapIdentityGroups: {"manage groups", nil, "admin"}, CapIdentityAuth: {"manage authentication settings", nil, "admin"}, CapAuthzGrants: {"grant and revoke roles and capabilities", nil, "admin"}, CapStandardsGuidance: {"edit the guidance library", nil, "execute"}, CapStandardsPacks: {"edit packs", nil, "execute"}, CapStandardsPolicies: {"edit policies and the policy library", nil, "execute"}, CapStandardsEvals: {"read evals of models and pack versions", nil, "read"}, CapExecWorkflows: {"edit workflow definitions", nil, "execute"}, CapIntegrationConnector: {"manage connectors and provider bindings", nil, "admin"}, CapIntegrationServices: {"manage service kinds", nil, "execute"}, CapIntegrationDeps: {"manage dependency kinds", nil, "execute"}, CapModelsBindings: {"manage model provider bindings", nil, "admin"}, CapModelsSlots: {"manage model slots", nil, "admin"}, CapPlatformTargets: {"manage deploy targets", nil, "admin"}, CapPlatformOperate: {"operate the platform", nil, "admin"}, CapAuditRead: {"read the audit log", readInherits, "read"}, CapSecretRead: {"read secret declarations and bindings (names, stores, versions; never values)", readInherits, "read"}, CapSecretBind: {"bind a project's secrets to a store, put a value into the built-in store, choose a deployment's profile", nil, "mutate"}, CapSecretReveal: {"reveal a secret's value held by the built-in store, on the record (administrators only)", nil, "mutate"}, }
ErrAuthorityUnavailable: no authority was supplied to the check.
var ErrGrantRevoked = errors.New("grant already revoked")
var ErrPrincipalRequired = fault.New(fault.Unauthenticated, "a verified principal is required")
var Scopes = []Scope{ {"apptown:user:read", "read your projects, Changes, checks, evidence and runs", ReadCaps}, {"apptown:change:create", "open Changes in your name", []Capability{CapChangeCreate, CapChangeUpdateBrief, CapChangeNarrative}}, {"apptown:change:write", "push revisions to Changes you may write", []Capability{CapChangeWriteRevision}}, {"apptown:change:check", "run a Change's checks", []Capability{CapChangeRunChecks}}, {"apptown:change:preview", "boot a Change's preview", []Capability{CapChangePreview}}, {"apptown:change:request-land", "hand a Change off for approval", []Capability{CapChangeRequestLand}}, {"apptown:evidence:attach", "attach evidence to a Change", []Capability{CapChangeAttach, CapEvidenceAttach}}, {"apptown:project:create", "create projects in your name", []Capability{CapProjectCreate}}, {"apptown:change:run", "put AppTown's own agent to work on a Change", []Capability{CapChangeInvokeLane}}, {"apptown:change:return", "send a Change back with a note, or abandon it", []Capability{CapChangeSendBack, CapChangeAbandon}}, }
var StockRoles = []Role{ {Name: RoleInstanceAdmin, Title: "Instance administrator", Scope: ScopeInstance, Surfaced: true, Description: "The sovereign: holds every capability on this instance.", Caps: AllCapabilities()}, {Name: RoleStandardsAdmin, Title: "Standards administrator", Scope: ScopeInstance, Description: "Manages guidance, packs and policies (the amender).", Caps: []Capability{CapStandardsGuidance, CapStandardsPacks, CapStandardsPolicies, CapStandardsEvals}}, {Name: RoleExecutionAdmin, Title: "Execution administrator", Scope: ScopeInstance, Description: "Manages executable workflow definitions.", Caps: []Capability{CapExecWorkflows}}, {Name: RoleIntegrationAdmin, Title: "Integration administrator", Scope: ScopeInstance, Description: "Manages connectors, service and dependency kinds, model bindings.", Caps: []Capability{CapIntegrationConnector, CapIntegrationServices, CapIntegrationDeps, CapModelsBindings, CapModelsSlots}}, {Name: RoleReleaseManager, Title: "Release manager", Scope: ScopeInstance, Surfaced: false, Description: "Promotes releases to wider tiers (the releaser).", Caps: []Capability{CapReleaseRead, CapReleasePromote, CapDeploymentRead, CapDeploymentDeploy}}, {Name: RoleAuditor, Title: "Auditor", Scope: ScopeInstance, Description: "Reads everything, changes nothing.", Caps: append(append([]Capability{}, ReadCaps...), CapInstitutionRead, CapAuditRead, CapStandardsEvals)}, {Name: RoleProjectCreator, Title: "Project creator", Scope: ScopeInstance, Surfaced: true, Description: "Creates projects through approved creation profiles.", Caps: []Capability{CapProjectCreate, CapProjectList}}, {Name: RoleGroupViewer, Title: "Group viewer", Scope: ScopeGroup, Description: "Discovers projects visible through this group.", Caps: []Capability{CapProjectList}}, {Name: RoleGroupMember, Title: "Group member", Scope: ScopeGroup, Surfaced: true, Description: "Belongs to the group. Carries no project capability by itself.", Caps: []Capability{}}, {Name: RoleGroupCreator, Title: "Group project creator", Scope: ScopeGroup, Description: "Creates projects owned by the group.", Caps: []Capability{CapProjectCreate}}, {Name: RoleGroupMaintainer, Title: "Group maintainer", Scope: ScopeGroup, Description: "Reserved group office; currently carries no operation permissions.", Caps: []Capability{}}, {Name: RoleGroupOwner, Title: "Group owner", Scope: ScopeGroup, Surfaced: true, Description: "Creates projects owned by the group.", Caps: []Capability{CapProjectCreate}}, {Name: RoleGroupAuditor, Title: "Group auditor", Scope: ScopeGroup, Description: "Reads projects and evidence visible through this group.", Caps: append(append([]Capability{}, ReadCaps...), CapAuditRead)}, {Name: RoleProjectViewer, Title: "Project viewer", Scope: ScopeProject, Surfaced: true, Description: "Reads the project, its changes, runs, evidence and deployments.", Caps: ReadCaps}, {Name: RoleProjectContrib, Title: "Project contributor", Scope: ScopeProject, Surfaced: true, Description: "Opens changes, contributes revisions, runs checks, previews, hands off for landing.", Caps: ContributorCaps}, {Name: RoleProjectMaintainer, Title: "Project maintainer", Scope: ScopeProject, Surfaced: true, Description: "Contributor plus landing, abandoning, operating runs and deployments, and project configuration.", Caps: MaintainerCaps}, {Name: RoleProjectApprover, Title: "Project approver", Scope: ScopeProject, Surfaced: true, Description: "Approves at approval steps that name them. Need not write code or land.", Caps: append(append([]Capability{}, ReadCaps...), CapChangeApprove, CapChangeOverride, CapExceptionApprove, CapExceptionRevoke)}, {Name: RoleProjectOwner, Title: "Project owner", Scope: ScopeProject, Surfaced: true, Description: "Maintainer plus membership, configuration and deletion authority.", Caps: OwnerCaps}, }
Functions ¶
func AgentCredential ¶
AgentCredential reports a coding agent's credential: an OAuth delegation or an agent token. An act a person may do for themselves without any capability (disconnecting their own connections) still needs the person.
func AgentToken ¶
AgentToken reports an agent-purpose personal token.
func CredentialCovers ¶
func CredentialCovers(pr Principal, c Capability) bool
CredentialCovers is the agent bound every authority check applies before grants. An agent's credential, an OAuth delegation or an agent-purpose personal token, reaches only the scope catalogue: an OAuth delegation its consented scopes, an agent token every scope. No scope covers approving, landing or administration, so an agent never inherits those from its person. Every other credential is not narrowed here.
func CredentialNarrowReason ¶
CredentialNarrowReason says why CredentialCovers refused.
func GrantApplies ¶
func GrantApplies(g Grant, c Capability, res Resource) bool
GrantApplies is §3: a grant sits at a scope and covers the resources inside it; instance and group grants reach down into projects only for the capabilities the catalog marks inheritable.
func GrantHolds ¶
func GrantHolds(g Grant, c Capability) bool
GrantHolds reports whether a grant carries a capability, directly or through its role.
func Inherits ¶
func Inherits(c Capability, to ScopeKind) bool
Inherits reports whether a grant at `from` (instance or group) reaches a resource whose scope chain includes `to`.
func InstrumentMay ¶
func InstrumentMay(kind string, c Capability) bool
InstrumentMay is §11's table as a question.
func RolesCarrying ¶
func RolesCarrying(c Capability, res Resource) []string
RolesCarrying names the surfaced roles that bundle c at the resource's natural scope, for the "how to get it" half of a denial.
func ScopeMeans ¶
func ScopeNames ¶
func ScopeNames() []string
func ScopesCover ¶
func ScopesCover(scopes []string, c Capability) bool
ScopesCover: does a delegation's scope list reach a capability? Reads are covered by any scope (a client that may write may look).
func ValidTokenPurpose ¶
ValidTokenPurpose reports whether p is a purpose a token may be made with.
Types ¶
type Actor ¶
type Actor struct {
Principal ids.ID `json:"principal,omitzero"`
Name string `json:"name"`
Via string `json:"via,omitempty"`
}
Actor is who an act is recorded against (design/decisions/mergeable-forge-data.md): the principal who answers for it, the name as shown when it happened, and how they acted. An absent actor is all empty; an anonymous act has no principal and Via "anonymous"; a name read without its principal keeps the name and no principal. Nothing invents a principal.
func ActorFrom ¶
ActorFrom is the actor an act by name is recorded against: the verified caller in ctx when it is the one named (its receipt or principal name), with its principal and way of acting; otherwise the name alone, with no principal, since a name is never taken for a principal.
func (Actor) Assents ¶
Assents says whether the act is a person's own assent: acting directly — a session, a trusted header, open mode or their command-line token. Through a chat, a run step, an agent token, an OAuth client, a ticket or an eval, the same person's act is not their assent. It judges the way of acting; who the person is, is the principal's to say.
func (Actor) Shown ¶
Shown is how an actor reads in history (design/decisions/mergeable-forge-data.md): the person's name today; "(then x)" when they were written as another name; "disabled" for a disabled account; "former user (was: x)" for a removed one. An act with no principal reads as it was written — the AppTown's own names, an instrument — and as "unrecorded actor (written as: x)" when it names a person AppTown never resolved.
type Authority ¶
Authority is the checked Access contract. Consumers declare their own matching interface; no consumer receives a store or a permission cache.
type Authorizer ¶
type Authorizer interface {
Require(context.Context, Permission) (Caller, error)
}
type Caller ¶
Caller separates authenticated provenance from receipt attribution. Transports and explicit internal orchestration establish it; command inputs cannot.
type Capability ¶
type Capability string
Capability is a stable domain verb, resource:verb. It names an act, never an HTTP route or a button.
const ( CapInstanceReadPublic Capability = "instance:read-public" CapInstitutionRead Capability = "institution:read-structure" CapProjectList Capability = "project:list" CapProjectRead Capability = "project:read" CapProjectCreate Capability = "project:create" CapProjectConfigure Capability = "project:configure" CapProjectDelete Capability = "project:delete" CapProjectManageMembers Capability = "project:manage-members" CapProjectImport Capability = "project:import" CapChangeList Capability = "change:list" CapChangeRead Capability = "change:read" CapChangeCreate Capability = "change:create" CapChangeUpdateBrief Capability = "change:update-brief" // CapChangeNarrative writes a change's "So far" summary (and a title // nobody chose), never the person-written brief. AppTown's own engine // holds it, so its automatic refreshes publish. CapChangeNarrative Capability = "change:write-narrative" CapChangeWriteRevision Capability = "change:write-revision" CapChangeAttach Capability = "change:attach-evidence" CapChangeRunChecks Capability = "change:run-checks" CapChangePreview Capability = "change:preview" CapChangeInvokeLane Capability = "change:invoke-lane" CapChangeSendBack Capability = "change:send-back" CapChangeAbandon Capability = "change:abandon" CapChangeRequestLand Capability = "change:request-land" CapChangeLand Capability = "change:land" CapChangeApprove Capability = "change:approve" CapChangeOverride Capability = "change:override" CapRunRead Capability = "run:read" CapRunOperate Capability = "run:operate" CapEvidenceRead Capability = "evidence:read" CapEvidenceAttach Capability = "evidence:attach" CapConformanceRead Capability = "conformance:read" CapConformanceRev Capability = "conformance:review" CapConformanceAI Capability = "conformance:confirm-ai" CapConformanceFix Capability = "conformance:remediate" CapExceptionApprove Capability = "exception:approve" CapExceptionRevoke Capability = "exception:revoke" CapProjectWayOfWorking Capability = "project:select-way-of-working" CapProjectGuidance Capability = "project:configure-guidance" CapProjectServices Capability = "project:configure-services" CapProjectIntegrations Capability = "project:configure-integrations" CapProjectModelProfile Capability = "project:configure-model-profile" CapProjectWorkflow Capability = "project:configure-workflow" CapReleaseRead Capability = "release:read" CapReleasePromote Capability = "release:promote" CapDeploymentRead Capability = "deployment:read" CapDeploymentOperate Capability = "deployment:operate" // The deployment verbs (design/subsystems/deployment.md). CapDeploymentBind Capability = "deployment:bind-target" CapDeploymentDeploy Capability = "deployment:deploy" CapDeploymentTeardown Capability = "deployment:teardown" // CapDeploymentRestore fills a deployment's data from a copy, or checks // a copy comes back (design/subsystems/deployment.md). It is // checked in the copy's project and in the destination's; no scope // carries it, so an agent never does. CapDeploymentRestore Capability = "deployment:restore" CapIdentityUsers Capability = "identity:manage-users" CapIdentityGroups Capability = "identity:manage-groups" CapIdentityAuth Capability = "identity:manage-auth" CapAuthzGrants Capability = "authorization:manage-grants" CapStandardsGuidance Capability = "standards:manage-guidance" CapStandardsPacks Capability = "standards:manage-packs" CapStandardsPolicies Capability = "standards:manage-policies" // CapStandardsEvals reads evals: how a model or pack version did against // what projects run now. A read, so an agent may hold it through its // person; starting one stays with standards:manage-packs. CapStandardsEvals Capability = "standards:read-evals" CapExecWorkflows Capability = "execution:manage-workflows" CapIntegrationConnector Capability = "integration:manage-connectors" CapIntegrationServices Capability = "integration:manage-service-kinds" CapIntegrationDeps Capability = "integration:manage-dependency-kinds" CapModelsBindings Capability = "models:manage-bindings" CapModelsSlots Capability = "models:manage-slots" CapPlatformTargets Capability = "platform:manage-deploy-targets" CapPlatformOperate Capability = "platform:operate" CapAuditRead Capability = "audit:read" // Secrets: reading declarations and binding // status is a read; binding a secret to a store, putting a value into // the built-in store and choosing a deployment's profile is one // mutate capability. Values are never readable. CapSecretRead Capability = "secret:read" CapSecretBind Capability = "secret:bind" CapSecretReveal Capability = "secret:reveal" )
Capability names, grouped as the design lists them.
func AllCapabilities ¶
func AllCapabilities() []Capability
AllCapabilities is the sorted catalog, for the sovereign role and the API.
type Channel ¶
type Channel struct {
Kind string // full-breadth | cli-token | agent-token | instrument | anonymous | oauth
ID string
}
Channel bounds what the channel may exercise of the person's authority. Sessions are "full breadth" (§1): no narrowing beyond current grants. A command-line token is bounded by the role it was made with.
func DelegationOf ¶
DelegationOf is the channel's bound, from the principal's provenance.
type Checked ¶
type Checked struct {
Authority Authority
Projects ProjectResources
}
Checked completes a domain's resource and asks the existing authority. It has no database, permission cache, or dependency on an application or domain.
func (Checked) VisibleProjects ¶
type Context ¶
type Context struct {
Consequential bool // write a decision receipt (protected acts: yes)
Route string // for the receipt's context
}
Context describes the decision receipt.
type Decision ¶
type Decision struct {
Allow bool `json:"allow"`
Code string `json:"code,omitempty"`
Reason string `json:"reason"`
GrantIDs []ids.ID `json:"grantIds,omitzero"`
Roles []string `json:"roles,omitempty"`
Paths []string `json:"paths,omitempty"` // membership paths that mattered, e.g. group:approvers
ReceiptID ids.ID `json:"receiptId,omitzero"`
}
Decision is the one answer.
type Definition ¶
type Definition struct {
Description string
// Inherits lists the scope kinds an instance/group grant of this capability
// reaches DOWN into (§3 table). Empty = a grant applies only at the scope it
// names and the resources inside that scope's own project/change/run.
Inherits []ScopeKind
Risk string // read | mutate | approve | release | execute | admin
}
type Denied ¶
type Denied struct{ Code, Reason string }
Denied is a policy refusal, distinct from a failure to read policy.
type Facts ¶
type Facts interface {
// Disabled reports whether a user may not act as an account: it is
// disabled, or there is no such account. A principal that was admitted
// is judged by its ID (its name may have changed or gone to someone
// else); a name alone, by the account of that name. Unknown is refused,
// never enabled.
Disabled(pr Principal) bool
// Grants is the principal's active grants: their own, their groups' and
// everyone's, in one snapshot.
Grants(pr Principal) []Grant
}
Facts is what the rule reads while deciding. Each read happens only when the rule reaches it.
type Grant ¶
type Grant struct {
ID ids.ID
SubjectType string
Subject string
RoleName string
Capability Capability
ScopeType ScopeKind
ScopeID string
Origin string
GrantedBy string
// GrantedByPrincipal is the granter's principal; zero for AppTown, or
// a granter not resolved to a person.
GrantedByPrincipal ids.ID
Reason string
CreatedAt string
ExpiresAt stamp.Time
ReviewAt stamp.Time
RevokedAt stamp.Time
}
Grant is a grant row as the rule reads it.
type Permission ¶
type Permission struct {
Capability Capability
Resource Resource
Context Context
}
Permission names an operation and the containing resource resolved by its owner. Context carries receipt attribution.
type Person ¶
Person is a principal as it stands now, for showing an actor: its name today, and whether its account is disabled or it was removed. Known is false for a principal AppTown has no record of.
type Principal ¶
type Principal struct {
// ID is the principal who answers: a person's UUID for a user, the
// person's for a console they wield; Nil when none was resolved (an
// anonymous caller, a run, a name read from a header before its account).
ID ids.ID
Kind string // user | anonymous | instrument
Name string // username, "anonymous", or the instrument's own name
Person string // for a console: the person wielding it; "" for a run
Instrument string // "" | console | run | eval | SystemInstrument
Via string
ProjectID ids.ID // the one project an instrument may act in
ConsoleID string
Role string // token administrator ceiling; otherwise a display projection, never authority
// Purpose is a personal token's, chosen when it was made: TokenCLI is
// its person's own command line, TokenAgent a coding agent's
// connection. "" for every other credential.
Purpose string
// An OAuth delegation behind the request: the rule narrows to its
// scopes. Zero for sessions and personal tokens (full breadth).
DelegationID ids.ID
Scopes []string
// Credential is a non-secret reference to the credential behind the
// request (token:<name>, session:<id>, oauth:<delegation id>,
// header:<user>, system:<binding>), so a long operation can ask later
// whether that credential is still live. "" when none was resolved.
Credential string
}
Principal is who is present, resolved from the authenticated identity. Instruments (a console session, a step agent) are not people: they carry the person behind them when there is one and are bounded by §11's tables.
type ProjectResources ¶
ProjectResources supplies only the facts common authorization needs.
type ProjectVisibility ¶
type ProjectVisibility interface {
VisibleProjects(context.Context, Principal, Capability) ([]ids.ID, error)
}
ProjectVisibility evaluates a principal against complete current project facts. Returned IDs are observations for read filtering, never permission to mutate.
type ReadAuthorizer ¶
type ReadAuthorizer interface {
Authorizer
VisibleProjects(context.Context, Capability) ([]ids.ID, error)
}
ReadAuthorizer keeps caller establishment and aggregate visibility at the same owner boundary as explicit resource authorization.
type Resource ¶
type Resource struct {
ProjectName string // display name supplied by the resource owner, never an authority fact
Type string // instance | group | project | change | run | step | deployment | dimension | release-target
ID string
ProjectID ids.ID
Group string // the project's owning group
ChangeID ids.ID
RunID ids.ID
}
Resource is the thing acted on, with its containing scopes resolved.
type Role ¶
type Role struct {
Name string
Title string // the answerable office, in product words
Description string
Scope ScopeKind // where a grant of this role sits
Caps []Capability
// Surfaced roles appear on the People page and in grant pickers. The
// rest exist for later profiles.
Surfaced bool
}
Role is a named capability bundle shipped with AppTown.
func RoleByName ¶
func (*Role) Holds ¶
func (rv *Role) Holds(c Capability) bool
Holds reports whether a role bundles a capability.
type Scope ¶
type Scope struct {
Name string
Means string // product language for the consent screen
Caps []Capability
}
Scope is one consent word (mcp.md §4) mapped onto capabilities. A scope names what a client may ask for; the rule still evaluates the person's live grants underneath.