policy

package
v0.24.0 Latest Latest
Warning

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

Go to latest
Published: Sep 16, 2026 License: Apache-2.0 Imports: 6 Imported by: 0

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

View Source
const Bound = 8
View Source
const Version = "control-1"

Variables

View Source
var DefaultJudgements = []string{"FIX_WITHIN_SEMVER"}

DefaultJudgements is what a grant accepts when it names none.

View Source
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

func ResourceCovered(list []string, resource string) bool

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".

func Validate added in v0.5.0

func Validate(a Action) error

Validate holds an action's parameters to the schema of its kind.

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.

func (Action) ToMap

func (a Action) ToMap() map[string]any

ToMap is the action as the snapshot commits to it.

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) Digest

func (p PathSummary) Digest() string

Digest of the summary, hex.

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

type Policy struct {
	Grant     Grant
	PathAware bool
}

Policy evaluates a grant, path-aware.

func (Policy) Accepted added in v0.13.0

func (p Policy) Accepted(required []string) (string, bool)

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

func (p Policy) Bundle() map[string]any

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

func (p Policy) BundleHash() string

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

func (p Policy) ForTask(playbook string) (Policy, string)

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) PerTask added in v0.18.0

func (p Policy) PerTask() bool

PerTask says whether the grant is narrowed per task.

func (Policy) RequiresPremises

func (p Policy) RequiresPremises(kind string) bool

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.

Jump to

Keyboard shortcuts

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