authzplan

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Sep 10, 2026 License: AGPL-3.0 Imports: 7 Imported by: 0

Documentation

Index

Constants

View Source
const MaxPointerDepth = 4

MaxPointerDepth — предел глубины цепи указателей на предка.

Экспортирован намеренно: предел — часть КОНТРАКТА компиляции, а не деталь. Он объявляет, сколько уровней иерархии областей вообще может быть пройдено, и потребитель (в том числе прибор замера) обязан видеть ту же величину, иначе два места разойдутся в том, что считают «слишком глубоко».

View Source
const VerbPrefix = "v_"

VerbPrefix — приставка отношения-глагола.

Она не выбрана здесь, а выведена из продукта: имя отношения-глагола собирает реконсайлер iam, приводя глагол роли к канонической форме и приписывая эту приставку (комментарий у `v_addtargets` в самой модели это и фиксирует). Поэтому «глагол» здесь — свойство ИМЕНИ, и держит его сама модель, а не память автора.

Приведение имени происходит НЕ ЗДЕСЬ, и назвать его действующей защитой этого пакета было бы неправдой: пакет разбирает уже готовый текст модели и имён не строит. Прежняя редакция называла функцию приведения по имени — после переезда компилятора из прибора в прод она осталась в другом пакете, и комментарий стал утверждать, что сегмент закрыт тем, чего в этом доме нет. Поймано гейтом TestCommentsNamingAGuardHaveItInScope, а не чтением: комментарий уже ответил на вопрос «закрыт ли», поэтому проверять его никто не шёл.

Variables

View Source
var ErrCanonAboveTree = errors.New("канон лежит выше дерева")

ErrCanonAboveTree — канона в названном дереве нет, а ВЫШЕ него он лежит. Отдельный признак: он отличает «прежде читалось чужое» от «его нет нигде».

View Source
var ErrCanonNotInTree = errors.New("канона в дереве нет")

ErrCanonNotInTree — канона нет ни в дереве, ни выше него.

View Source
var ErrTreeNotResolved = errors.New("дерево под резолвом не установлено")

ErrTreeNotResolved — дерево назвать нечем: проверка НЕ ИСПОЛНЯЛАСЬ.

View Source
var ErrTypeNotDeclared = errors.New("authzplan: тип не объявлен моделью")

Compile строит план вердикта для одного отношения одного типа.

Обход рекурсивный и завершается по построению: ключ посещения несёт ТИП, ИМЯ отношения и путь, а глубина пути ограничена (`MaxPointerDepth`). Цикл в модели не повесил бы обход, а стал бы находкой — и это лучше, чем незавершимый разбор. ErrTypeNotDeclared — тип, о котором спрашивают, в словаре модели не объявлен.

ПОЧЕМУ ЭТО ОТДЕЛЬНАЯ, СИГНАЛЬНАЯ ОШИБКА. По ней вызывающий принимает РЕШЕНИЕ О ДОСТУПЕ, и решения тут два разных. «Типа нет вовсе» — это факт о модели: объектов такого типа не существует, отношений на них не существует, и честный ответ — ОТКАЗ. «Не смог ответить» (сломанный план, недостижимый источник) — это незнание, и выдавать его за отказ запрещено: незнание, поданное как «нет», прячет поломку ровно там, где она опаснее всего.

Различать их сравнением ТЕКСТА нельзя: первая же правка формулировки увела бы вызывающего в другую ветвь, и увела бы молча.

Наблюдалось на снятии внешнего движка (#880): вопрос про снятый тип-носитель точечных выдач кончался ошибкой вместо отказа, и для вызывающего «нет прав» стало неотличимо от «сломалось».

Functions

func CanonicalModelRelPath

func CanonicalModelRelPath() string

CanonicalModelRelPath — тот же относительный путь для вызывающего, который печатает перепись.

Экспортирован ради ОДНОГО читателя — исполнителя сверки: его перепись обязана называть не только корень обхода, но и файл, по которому она снята, иначе «корень назван» и «канон прочитан оттуда» остаются двумя разными утверждениями. Второй копии постоянной это не заводит: возвращается она же.

func IsVerb

func IsVerb(rel string) bool

IsVerb отвечает, является ли отношение отношением-глаголом.

func ResolveCanonicalModel

func ResolveCanonicalModel() (path string, dsl []byte, err error)

ResolveCanonicalModel — канон ТОГО дерева, в котором идёт прогон.

Дерево не выводится арифметикой пути и не ищется подъёмом за маркером: вопрос ставится ИНДЕКСУ (`rev-parse --show-toplevel`), а затем проверяется предпосылка — что каталог, из которого спрашивают, этим деревом ОТСЛЕЖИВАЕТСЯ. Без второй проверки модуль, распакованный внутрь чужого репозитория, получил бы корень ЧУЖОГО дерева и вердикт о нём.

func ResolveCanonicalModelFrom

func ResolveCanonicalModelFrom(root string) (path string, dsl []byte, err error)

ResolveCanonicalModelFrom — канон дерева root.

Параметр — КОРЕНЬ ДЕРЕВА, а не путь канона, и различие несущее (#1089, §2 п. 2): подменить канон снимком, лежащим рядом со сверщиком, нечем — предъявить такой путь этой подписи невозможно. Указать можно лишь целое дерево, у которого канон лежит по каноническому относительному пути; ровно этим и пользуется инъекция, подавая своё дерево намеренно.

Читает РОВНО `<root>/<fgaModelRelPath>`. За пределы root не выходит ни при каком входе: файл выше дерева попадает только в ТЕКСТ отказа и никогда в возвращаемые байты.

func ShippedModelRelPath

func ShippedModelRelPath() string

ShippedModelRelPath — ВТОРАЯ постоянная координата: копия канона, которую модуль везёт с собой.

Экспортируется ради одного вопроса, который без неё не задать: КАКОЙ из двух координат прочитан канон. Ответ различает посадки — в дереве платформы читается контракт, в самостоятельной поставке модуля его нет вовсе и читается копия, — и потому отличает «условие сверки не создано» от находки о продукте (kacho#2241). Постоянная возвращается та же; второй копии это не заводит.

Types

type Atom

type Atom struct {
	Kind AtomKind
	// ParentType — тип предка, на котором лежит факт; пустая строка означает сам
	// объект. Путь выражен ТИПОМ, а не последовательностью указателей: в этой
	// модели у типа не бывает двух указателей на один и тот же тип предка, и это
	// проверяется (`assertOnePointerPerParentType`), а не предполагается.
	ParentType string
	// Relation — имя отношения. У AtomFact это имя факта, у AtomBinding — ГЛАГОЛ,
	// который обязана давать роль привязки. Он не равен спрошенному отношению
	// всегда: `v_addtargets` выводится в модели от `v_update`, и привязку надо
	// спрашивать про `v_update`. Подставить сюда спрошенное имя значило бы молча
	// отказывать держателю права, которое модель ему даёт.
	Relation string
	Origin   string // откуда терм пришёл — для отчёта и для падения пробы
}

Atom — один источник разрешения.

type AtomKind

type AtomKind int

AtomKind — вид источника разрешения в плане формы E.

const (
	// AtomBinding — субъект назван в привязке, роль которой даёт спрошенный
	// глагол, правило-селектор которой накрывает объект, а область которой
	// содержит объект. Ровно то, что у движка лежит материализованным кортежем.
	AtomBinding AtomKind = iota
	// AtomFact — строка факта на объекте или на его предке: владелец аккаунта,
	// администратор кластера, членство, подстановочная выдача публичного чтения.
	// Это НЕ материализация состава: строк здесь порядка числа аккаунтов и
	// привязок, а не числа объектов × глаголов.
	AtomFact
)

type Census

type Census struct {
	Types           int
	Declarations    int
	VerbTypes       int
	VerbDeclaration int
	Pointers        int
	Conditions      int
}

Census — счётные величины модели. Печатаются в отчёте, потому что «ноль расхождений» обязано быть отличимо от «ноль спрошенного».

type DirectSubject

type DirectSubject struct {
	Type      string // тип субъекта либо тип-указатель: user, service_account, group, cluster…
	Wildcard  bool   // `user:*`
	Userset   string // `group#member` → "member"
	Condition string // `user with mfa_fresh` → "mfa_fresh"
}

DirectSubject — одна запись прямого списка.

func (DirectSubject) String

func (d DirectSubject) String() string

String возвращает запись в том виде, в каком она стоит в модели.

type Model

type Model struct {
	Types      []*ModelType
	Conditions []string

	// pointers — имена отношений-указателей, ВЫВЕДЕННЫЕ из текста: указателем
	// считается ровно то отношение, через которое хоть одно объявление ходит
	// формой `X from <указатель>`. Признак выводится, а не выписывается: список
	// имён в этом файле был бы вторым местом об одном предмете.
	// Pointers — тип → имена его указателей на предка. Экспортировано: цепь
	// областей есть ЧАСТЬ разобранной модели, и всякий, кто по ней ходит
	// (вычисление предков, проверка выразимости, замер), обязан ходить по ЭТОЙ
	// карте, а не строить свою из тех же объявлений.
	Pointers map[string]map[string]bool
	// contains filtered or unexported fields
}

Model — разобранная модель целиком.

func ParseModel

func ParseModel(dsl string) (*Model, error)

ParseModel разбирает канонический DSL.

Он отвергает вход, а не пропускает непонятое: нераспознанная строка внутри блока `relations`, отношение без термов, пересечение или вычитание (`and` / `but not`) — ошибка. Разбор, молча пропускающий конструкцию, произвёл бы план, который «совпал» с движком потому, что о пропущенном не спросили.

func (*Model) AssertOnePointerPerParentType

func (m *Model) AssertOnePointerPerParentType() error

assertOnePointerPerParentType проверяет предпосылку, на которой стоит выражение пути ТИПОМ предка вместо последовательности указателей: у типа не должно быть двух указателей, ведущих в один и тот же тип. Предпосылка проверяется, а не предполагается, — иначе первый же такой тип сделал бы два разных источника неразличимыми, и план молча объединил бы их. AssertOnePointerPerParentType — у типа не больше одного указателя на каждый тип-предка.

Экспортирована, потому что это утверждение о МОДЕЛИ, а не шаг компиляции: его обязан уметь задать и тот, кто модель проверяет, не компилируя.

func (*Model) Census

func (m *Model) Census() Census

Census считает модель по разобранному дереву, а не по строкам файла.

func (*Model) Compile

func (m *Model) Compile(typeName, relation string) (Plan, error)

func (*Model) IsPointer

func (m *Model) IsPointer(typeName, rel string) bool

IsPointer отвечает, является ли отношение типа указателем — то есть ходит ли через него хоть одно объявление модели.

func (*Model) PointerTargets

func (m *Model) PointerTargets(ptr *Relation) []string

pointerTargets — типы, на которые ведёт отношение-указатель. PointerTargets — типы, на которые ведёт указатель. Экспортировано по той же причине, что и Pointers: это чтение модели, а не шаг компиляции.

func (*Model) Type

func (m *Model) Type(name string) *ModelType

Type возвращает тип по имени либо nil.

func (*Model) TypeNames

func (m *Model) TypeNames() []string

TypeNames возвращает имена типов в порядке объявления.

type ModelType

type ModelType struct {
	Name      string
	Relations []*Relation
	// contains filtered or unexported fields
}

ModelType — один `type`.

func (*ModelType) Rel

func (t *ModelType) Rel(name string) *Relation

Rel возвращает отношение типа либо nil.

func (*ModelType) Verbs

func (t *ModelType) Verbs() []string

Verbs возвращает глаголы типа в порядке объявления.

type Plan

type Plan struct {
	Type     string
	Relation string
	Atoms    []Atom

	// Conditioned — записи прямых списков, несущие условие на кортеже (`with
	// mfa_fresh`). У формы E места под условие НЕТ: её факт — строка, у строки
	// нет контекста запроса, и CEL она не исполняет. Поэтому такие записи
	// называются поимённо и выносятся в исход (в), а не растворяются в атоме.
	Conditioned []string

	// Unclassified — термы, которые компилятор НЕ отнёс ни к одному виду.
	// Непустой список означает, что план неполон и вердикт по нему давать нельзя.
	Unclassified []string
}

Plan — скомпилированный вердикт одного отношения одного типа.

func (Plan) Expressible

func (p Plan) Expressible() bool

Expressible отвечает, выразим ли план целиком.

type Relation

type Relation struct {
	Owner *ModelType
	Name  string
	Terms []Term
	Raw   string
	Line  int
}

Relation — одно объявление `define`.

type Term

type Term struct {
	Kind        TermKind
	Direct      []DirectSubject
	Computed    string
	TTURelation string
	TTUPointer  string
	Raw         string
}

Term — один дизъюнкт правой части.

type TermKind

type TermKind int

TermKind — вид терма в правой части объявления отношения.

const (
	// TermDirect — прямой список назначаемых субъектов: `[user, group#member]`.
	TermDirect TermKind = iota
	// TermComputed — отношение ТОГО ЖЕ объекта: `admin`.
	TermComputed
	// TermTTU — отношение объекта, на который указывает указатель: `admin from account`.
	TermTTU
)

Jump to

Keyboard shortcuts

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