Documentation
¶
Overview ¶
Package policy is the deterministic policy over (action, path summary): the same inputs give the same verdict, with no lookup a stranger cannot repeat. The grant is data; the bundle hash names exactly which policy judged, so a verdict can be re-derived.
Index ¶
- Constants
- Variables
- func Matched(a Action, phi PathSummary, g Grant) string
- func ResourceCovered(list []string, resource string) bool
- func Validate(a Action) error
- type Action
- type Grant
- type PathSummary
- type Policy
- func (p Policy) Accepted(required []string) (string, bool)
- func (p Policy) Bundle() map[string]any
- func (p Policy) BundleHash() string
- func (p Policy) Evaluate(a Action, phi PathSummary) (string, string)
- func (p Policy) ForTask(playbook string) (Policy, string)
- func (p Policy) PerTask() bool
- func (p Policy) RequiresPremises(kind string) bool
- type Schema
- type TaskGrant
Constants ¶
const Bound = 8
const Version = "control-1"
Variables ¶
var DefaultJudgements = []string{"FIX_WITHIN_SEMVER"}
DefaultJudgements is what a grant accepts when it names none.
var Schemas = map[string]Schema{ "portal.update": { Required: map[string]string{"title": "string"}, Optional: map[string]string{"date": "string", "clientVisible": "bool", "body": "list"}, }, "portal.time_entry": { Required: map[string]string{"hours": "number"}, Optional: map[string]string{"date": "string", "note": "string", "billable": "bool"}, }, "portal.expense": { Required: map[string]string{"vendor": "string", "amount": "number"}, Optional: map[string]string{"currency": "string", "date": "string", "description": "string", "invoiceNumber": "string", "rebillable": "bool", "files_sha256": "hex64"}, }, "portal.project.patch": { Required: map[string]string{}, Optional: map[string]string{"status": "string", "nextAction": "string", "clearNextAction": "bool", "summary": "string", "milestones": "records", "stack": "list", "links": "records", "replaceLinks": "bool", "elixir": "bool", "productionTheirs": "bool"}, }, "portal.task": { Required: map[string]string{"key": "string", "state": "string"}, Optional: map[string]string{"note": "string", "url": "string"}, }, "portal.measure": { Required: map[string]string{}, Optional: map[string]string{"only": "string"}, }, "portal.playbook": { Required: map[string]string{"playbook": "string"}, Optional: map[string]string{}, }, "workflow.dispatch": { Required: map[string]string{"workflow": "string", "ref": "string"}, Optional: map[string]string{"packages": "int", "plan_sha256": "hex64", "inputs": "strings"}, }, "branch.push": { Required: map[string]string{"branch": "string"}, Optional: map[string]string{"packages": "int", "base_sha": "string", "message": "string", "files_sha256": "hex64"}, }, "branch.delete": { Required: map[string]string{"branch": "string"}, Optional: map[string]string{"reason": "string"}, }, "pull.open": { Required: map[string]string{"branch": "string", "base": "string"}, Optional: map[string]string{"title": "string", "body": "string", "packages": "int", "draft": "bool"}, }, "review.publish": { Required: map[string]string{"page_sha256": "hex64"}, Optional: map[string]string{"title": "string", "by": "string"}, }, "review.invite": { Required: map[string]string{"email": "string"}, Optional: map[string]string{}, }, "review.sign": { Required: map[string]string{"root": "string"}, Optional: map[string]string{"readings": "int", "judged": "int"}, }, "pull.ready": { Required: map[string]string{"number": "int"}, Optional: map[string]string{"body": "string"}, }, }
Types: "string", "hex64" (a sha-256 in hex), "int" (a whole number), "number" (any finite number), "bool", "strings" (an object whose values are strings), "list" (an array of strings), "records" (an array of objects whose values are strings).
Functions ¶
func Matched ¶ added in v0.5.0
func Matched(a Action, phi PathSummary, g Grant) string
Matched names the permission an allowed action matched (row 4.1.2).
func ResourceCovered ¶ added in v0.18.0
ResourceCovered: a grant names resources exactly ("owner/repo") or by prefix, an entry ending in "/*" ("vera/hoet/*", since 13 September 2026: a review is made under a project and its id is not known when the permit is written). A prefix entry covers what lies under it and nothing beside it: "vera/hoet/*" covers "vera/hoet/paper1", not "vera/hoet" and not "vera/hoetx/paper1".
Types ¶
type Action ¶
type Action struct {
Kind string `json:"kind"`
Resource string `json:"resource"`
Params map[string]any `json:"params"`
Classification string `json:"classification"`
// Attached carries material that is too large for the judged parameters and is bound
// to them by digest (the files of a branch.push). Never part of the snapshot: ToMap
// leaves it out, and the record names it only through the digest in Params.
Attached map[string]any `json:"-"`
}
Action is a proposed effect at the interception point.
type Grant ¶
type Grant struct {
Principal string `json:"principal"`
Kinds []string `json:"kinds"`
Resources []string `json:"resources"`
MaxPerKind int `json:"max_per_kind"`
PremisesFor []string `json:"premises_for"`
MaxSensitivity string `json:"max_sensitivity_egress,omitempty"`
// SubmitterKey, when set, is the hand's own Ed25519 public key (hex): every
// submission must be signed by it, and the record says so (row 5.1.2). The key
// is the one the DID log publishes for the agent, so a stranger can check it.
SubmitterKey string `json:"submitter_key,omitempty"`
// PrincipalKey, when set, is the principal's Ed25519 public key (hex): every
// submission must then carry a capability the principal signed for this task,
// naming the agent, this gateway, the kinds and the resources, with an expiry
// (rows 4.2.1, 5.1.3). The gateway takes the intersection of grant and
// capability, so a capability narrows and never widens (row 4.2.3).
PrincipalKey string `json:"principal_key,omitempty"`
// PrincipalKeys names further keys of the principal by DID fragment (the operator's
// own, "did:webvh:…#operator" on a hardware token, and its counterpart "#operator-2"
// on the second token): a capability whose issuer is one of them is verified against
// that key. Until 2026-09-13 every capability was signed by Portal's key, so the
// operator's word was whatever the Portal application chose to sign; with the
// operator's keys named here, the capability is a signature only the person holding
// the token could have made, and the record names which key spoke.
PrincipalKeys map[string]string `json:"principal_keys,omitempty"`
// PerAction names the kinds whose capability must name the act itself (Payload.Act):
// the word is then spent on one action and cannot be reused inside its window. Reserve
// it for what a person cannot undo, since every kind listed here costs the operator a
// touch of the key per action; a push and a pull request end in a review, an invitation
// is mail already sent and a seal is anchored.
PerAction []string `json:"per_action,omitempty"`
// Judgements names the controls a certificate of premises may argue for this grant.
// A working is only as good as the rule it argues: a permit that accepts "within
// semver" must not be satisfied by a working that argues something else. Empty means
// the one judgement the fleet has used since 7 September 2026, FIX_WITHIN_SEMVER.
// A grant that lets an agent cross a major version names MAJOR_UNDER_TESTS here, and
// the working then has to argue tests before and after the change.
Judgements []string `json:"judgements,omitempty"`
// Tasks, when set, narrows the grant per task the principal's capability names.
// One hand that runs several playbooks under one key is one agent, not several:
// the key is what a stranger can check, and four agent ids on one key would claim
// a boundary that does not exist. So the agent holds one grant, and the playbook
// the capability names selects the task's own verbs, premises and judgements out
// of it (a task never widens: its kinds are met with the grant's). A capability
// naming a task the grant does not have is refused, and so is a submission
// without a capability when the grant is per task.
Tasks map[string]TaskGrant `json:"tasks,omitempty"`
}
Grant is the authority a hand holds: who granted it, which verbs, on which resources, how many of each in one path, and which kinds must carry a certificate of premises.
type PathSummary ¶
type PathSummary struct {
Steps int `json:"steps"`
PerKind map[string]int `json:"per_kind"`
Resources []string `json:"resources"`
}
PathSummary is bounded path state: counts per kind and the resources touched, so a composed sequence of permitted actions can still be refused.
func (PathSummary) Fold ¶
func (p PathSummary) Fold(a Action, verdict string) PathSummary
Fold returns the summary after an action with a verdict; a refusal advances the step counter only.
type Policy ¶
Policy evaluates a grant, path-aware.
func (Policy) Accepted ¶ added in v0.13.0
Accepted says whether every control a certificate argues is one the grant accepts; the first that is not is returned.
func (Policy) Bundle ¶ added in v0.5.0
Bundle is the policy as a document: the grant, the parameter schemas, the rule and the version. It is what the hash names and what is written beside the first record judged under it (row 4.1.1).
func (Policy) BundleHash ¶
BundleHash names the policy: grant, rule and version.
func (Policy) Evaluate ¶
func (p Policy) Evaluate(a Action, phi PathSummary) (string, string)
Evaluate returns verdict and reason.
func (Policy) ForTask ¶ added in v0.18.0
ForTask is the policy as it applies to one task: the grant with the task's verbs (intersected with its own), premises and judgements in place of the agent-wide ones. A grant without tasks is returned as it is. The second value is the reason when the task is not one the grant names.
func (Policy) RequiresPremises ¶
RequiresPremises says whether a kind must carry a certificate.
type Schema ¶ added in v0.5.0
type Schema struct {
Required map[string]string `json:"required"`
Optional map[string]string `json:"optional"`
}
Schema is what a kind's parameters may be (row 4.1.4): every key named with its type, required or not; a key the schema does not name is out of schema and the call is refused. The registry is part of the policy bundle, so a record names the schema it was validated against.
type TaskGrant ¶ added in v0.18.0
type TaskGrant struct {
Kinds []string `json:"kinds"`
PremisesFor []string `json:"premises_for,omitempty"`
Judgements []string `json:"judgements,omitempty"`
}
TaskGrant is what one task under an agent's grant may do: its verbs (within the grant's), which of them carry a certificate, and which judgements that certificate may argue.