gizdb:gate
who may read and write which rows of a Shape. It is the one place that applies the Policy (grants on records and the ancestry of records, db/policy.giz) to a Shape's rows, so a page, an API, an agent's tool and a background job that act through a Db with a Scope (db/data.giz) are all judged the same way, by the same function.
A stored Shape is a record of the Policy named SPACE/table/NAME, and each of its rows is SPACE/NAME/KEY below it (or below the row that its @Within field names). A grant on the table reaches every row; a grant on one row reaches that row and its children. A read adds a condition to the query, so a row the actor may not read is never selected; a field the actor may not read is selected as NULL. A write is checked before it runs, and a row is placed in the Policy in the transaction that inserts it.
import * as Gate from "gizdb:gate";Types
Scope
type Scope = { space: string; actor: Security.Principal; now: i64; held: Task.Cell<Vec<Held>>; }Who acts: the actor, the Space whose records they are, and the time (ms since 1970). A Scope is for one request: it remembers what the Policy
said of the actor's roles on the tables, so the reads of a page ask once. Rows change no grant on a table; provision forgets what it knew.
space:stringactor:gizlang_security.Principalnow:i64held:gizlang_task.Cell<Vec<M50.Held>>
Access
type Access = { readable: Vec<bool>; writable: Vec<bool>; role: Security.Role; mayWrite: bool; }What a role may do with the fields of a Shape. A field with a @Read role is read when the role is at least it; a field with a @Write role is written when the role is at least it and also the Shape's write role; a key and a computed field are never written.
readable:Vec<bool>writable:Vec<bool>role:gizlang_security.RolemayWrite:bool
Masks
type Masks = { conds: Vec<string>; slots: Vec<Typed.Slot>; params: Vec<Value>; }The masks of the fields with a @Read role: for each field a SQL condition that is true on the rows where the actor may read it
(empty for a field that any reader sees), with its parameters numbered from first. A role is judged once however many fields have it.
conds:Vec<string>slots:Vec<M54.Slot>params:Vec<M55.Value>
Plan
type Plan = { set: Vec<bool>; writes: Vec<Policy.Write>; }What a write sets: set flags the fields that it writes, and writes are the Policy statements that go in its transaction.
set:Vec<bool>writes:Vec<M60.Write>
Functions
scope
function scope(space: string, actor: Security.Principal, now: i64): Result<Scope, string>A Scope. A Space is named as a reference part is: 1 to 64 of a-z 0-9 _ . -
Effects: fail, io.
checked
function checked(shape: Model.Shape): Result<bool, Model.Rejection>Whether a Shape can be judged: stored under a table that names a Policy record, with a key of text or integers.
Effects: fail.
keyOf
function keyOf(shape: Model.Shape, values: Vec<Value>): Result<string, Model.Rejection>The key text of a row's values (the parts of a composite key are joined by /).
Effects: fail.
readable
function readable(source: Source, s: Scope, shape: Model.Shape, first: i64): Result<Policy.Condition, Model.Rejection>The condition that selects only the rows that the actor may read, with its parameters numbered from first.
Effects: fail, read, write, console, io.
access
function access(source: Source, s: Scope, shape: Model.Shape, ref: Security.ResourceRef): Result<Access, Model.Rejection>The access of the actor to the record ref (a row, or the table for a row that does not exist yet).
Effects: fail, read, write, console, io.
accessToTable
function accessToTable(source: Source, s: Scope, shape: Model.Shape): Result<Access, Model.Rejection>The access to a row that is created below the table (the row is not there yet).
Effects: fail, read, write, console, io.
accessToRow
function accessToRow(source: Source, s: Scope, shape: Model.Shape, values: Vec<Value>): Result<Access, Model.Rejection>The access to the row with these key values.
Effects: fail, read, write, console, io.
masks
function masks(source: Source, s: Scope, shape: Model.Shape, first: i64): Result<Masks, Model.Rejection>The masks of the fields of SHAPE that the actor of S may read only on some rows, with parameters numbered from FIRST (Masks).
Effects: fail, read, write, console, io.
admitCreate
function admitCreate(source: Source, s: Scope, shape: Model.Shape, values: Vec<Value>): Result<Plan, Model.Rejection>Admit a new row: the actor holds the Shape's write role on its parent. The Plan places the row.
Effects: fail, read, write, console, io.
admitUpdate
function admitUpdate(source: Source, s: Scope, shape: Model.Shape, old: Vec<Value>, values: Vec<Value>): Result<Plan, Model.Rejection>Admit a change of the row old (as the actor reads it) to values: the actor holds the write role on the row, and on the new
parent when a @Within field moves it.
Effects: fail, read, write, console, io.
admitRemove
function admitRemove(source: Source, s: Scope, shape: Model.Shape, old: Vec<Value>): Result<Plan, Model.Rejection>Admit the removal of the row old: the actor holds the write role on it. The Plan removes its grants and its place.
Effects: fail, read, write, console, io.
provision
function provision(s: Scope, shapes: Vec<Model.Shape>): Result<Vec<Policy.Write>, Model.Rejection>The statements that make the Policy tables and place the table record of each Shape, with the actor as its owner. Run them once for each Space; they can run again.
Effects: fail, read, write, console, io.