# What may go past the caller's own rights — and what never does

> A request always runs as the person who made it; there is no system mode, sudo or definer's rights a function can switch into. What does write past one person's own rules is declared and narrow: a function a deny names with `except via`, a block run as a declared actor (its declared roles, never an account of the code's choosing), an event handler and a workflow body (the app's authority, held by every kit's denies), the sign-in flow's own role, a grant link to one row, and — in tests only — a fixture. One route READS past them: a function an entity names in `allow read via`, which sees every row to compute a value and returns no row.

<!-- id: security-past-the-callers-rights · area: security · stability: stable · html: https://osysharp.com/reference/security/past-the-callers-rights/ -->

## Summary        {#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    {#description}

### Which routes are there?   {#routes}
| 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](https://osysharp.com/reference/security/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](https://osysharp.com/reference/security/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](https://osysharp.com/reference/security/declared-actor/), [runas (actor, onBehalfOf: person) — an actor acting for a person](https://osysharp.com/reference/security/on-behalf-of/) |
| 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](https://osysharp.com/reference/workflow/body-security/) |
| 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)](https://osysharp.com/reference/security/auth-bootstrap/) |
| 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)](https://osysharp.com/reference/security/grants/) |
| a `[TestFixture]` | every `security { }` block | tests only — [Fixtures: built once, cloned for every test, and built on each other](https://osysharp.com/reference/testing/fixtures/) |

### How does one person act for another?   {#acting-for}
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](https://osysharp.com/reference/security/acting-for-another-principal/)). To ask
whether ANOTHER person could read a row, use [`Security.MayRead`](https://osysharp.com/reference/security/may-read/).

### What does not exist?   {#not}
- 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 `allow` that opens a direct write past an `except via` deny — the named function is the way through.

```osy title="a handler writes what the person may not" run app=security-past-the-callers-rights
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       {#see-also}
- [deny … except via](https://osysharp.com/reference/security/except-via/) — the write path a kit or app names
- [allow read via](https://osysharp.com/reference/security/read-via/) — the function that computes a figure over every row
- [[On] — hear an event, after the commit that raised it](https://osysharp.com/reference/function/on/) — handlers, and whose authority they run with
- [What a workflow body may write](https://osysharp.com/reference/workflow/body-security/) — what a workflow body may write
- [Writing a kit — its parts, and every seam an app connects](https://osysharp.com/reference/local/writing-a-kit/) — the seams a kit author connects
