Summary#
Every request runs as its caller, and no function can become an account of its choosing. There is no [System]
an app may put on a function, no "run as system", no definer's rights. When something must happen that the person
could not write themselves — a member spending from a balance only the kit may change, a desk acting for a member, a
robot settling what a clerk may not — one of the declared, narrow routes below does it.
Description#
Which routes are there?#
| route | what it goes past | how narrow |
|---|---|---|
a function a deny … except via F names | that deny, for F's OWN writes | only the member and operation named; F runs on the server and needs [Authorize(…)]; the write still needs a grant — deny … except via |
a function an allow read via F names | the entity's READ rules and field masks, for F's OWN reads | F answers a value the compiler checks holds no row, writes nothing itself, runs on the server; a helper it calls reads as the caller — allow read via |
a runas (Actor) { … } block | the caller's rules, for the block — it answers to the ACTOR's | a class marked [Actor], with exactly its declared roles; onBehalfOf: holds it to a person's rights too — [Actor] — a principal that code may run as, runas (actor, onBehalfOf: person) — an actor acting for a person |
an [On] handler | the person's rules — it runs with the app's authority, after the commit | every kit's deny still holds it (but its own kit's) — [[function-on#authority]] |
| a workflow body | the app's security { } blocks | a kit's deny still binds it, except that kit's own code — What a workflow body may write |
an [AuthMethod] | nothing extra: it runs as the sign-in flow's role, under that role's ordinary grants | auth bootstrap (login, before anyone is signed in) |
a grant link | signing in, for ONE row of ONE entity | expiring, revocable, admitted by the entity's own rule — grants (a link that opens one row) |
a [TestFixture] | every security { } block | tests only — Fixtures: built once, cloned for every test, and built on each other |
How does one person act for another?#
As themselves, through a function. A desk spending from a member's balance calls the function the balance's deny
names; whether the desk may is that function's [Authorize(…)], and which member is an ordinary parameter, checked
by the function. A kiosk or an integration is a user of its own (acting for another principal). To ask
whether ANOTHER person could read a row, use Security.MayRead.
What does not exist?#
- an attribute that lifts a function out of its caller's rules —
[System]is the platform's own, not an author's; - a way for a request to become somebody else — another person's account is never run as, outside a test's
runas; the one thing code runs as is an actor the app declared; - an
allowthat opens a direct write past anexcept viadeny — the named function is the way through.
entity Visit {
[MaxLength(80)] string Room;
security { allow read, create when IsAnonymous || IsAuthenticated; }
}
entity Ledger {
[MaxLength(200)] string Line;
security { allow read when IsAnonymous || IsAuthenticated; } // nobody may write one
}
[Event("Visited")]
public sealed class Visited { public Visit Visit; }
void Enter(string room) { Raise(new Visited { Visit = new Visit { Room = room } }); }
[On]
void Record(Visited e) { new Ledger { Line = "visited " + e.Visit.Room }; }
[Test]
void The_person_visits_and_the_app_records_it() {
Enter("sauna");
UnitOfWork.Commit();
Background.Settle();
Assert.Equal("visited sauna", Ledger.Single().Line);
}See also#
- deny … except via — the write path a kit or app names
- allow read via — the function that computes a figure over every row
- [On] — hear an event, after the commit that raised it — handlers, and whose authority they run with
- What a workflow body may write — what a workflow body may write
- Writing a kit — its parts, and every seam an app connects — the seams a kit author connects