Osy#betaRun it on Osyrin: osyrin.com

Reference

Security

51 pages.

Legal holds — nothing a dispute needs is erased or purged while it lasts

A legal hold in `Osysharp.Privacy` keeps everything about a person — or one case — from being erased or purged while a dispute, a claim or an audit…

Passkeys — sign in with the device, no password and no code

Every app on the UserAccounts kit signs people in with passkeys: a key pair their phone, laptop or security key makes for the app and unlocks with a…

The Accounts add-on — the tier, entitlements, account team and VIPs of a customer organisation

`Osysharp.Organizations.ServicePlans` adds what a vendor keeps about the organisations it SERVES to the base Organizations kit: the tier each is on…

The Guardianship kit — who acts for whom: children, carers, consents and emergency contacts

`Osysharp.Guardianship` links a person to the people who look after them. A parent adds a child (an account the child cannot sign in to yet), invites…

The Identity kit — who signs in, and which of the app's roles they hold

`Osysharp.Identity` is the contract every people-aware kit builds on: `Principal`, the one `[Principal]` of the app (an address, a display name…

The Invitations kit — invite an address with a role, answered only by that address

`Osysharp.Invitations` brings a person into an app by their address, with what they will be — an app role, or a membership and a role held in one…

The Organizations kit — companies, teams, and roles held within one

`Osysharp.Organizations` holds the groups people belong to — the companies an app's customers work for and the teams its own people are in:…

The Privacy kit — erasure that keeps only what the company must or may

`Osysharp.Privacy` answers a person's GDPR request — access, portability, erasure, restriction — per category of what the app holds about them: erase…

The UserAccounts kit — sign-in done properly, once

`Osysharp.UserAccounts` is the default way into an app: sign-in with a password or a provider (Google, GitHub, …), sign-up (which an app can close)…

The UserManagement kit — the user manager: who is in the app, what each may do, and who changed it

`Osysharp.UserManagement` is an app's user manager: a searchable people list with each person's roles, two-step status, proven address and last…

The WorkQueues kit's floor — restricted queues, who may hold an item, and who moves whose work

What holds in every app on `Osysharp.WorkQueues`, whatever the app grants: an item in a restricted queue is invisible — in lists and in counts — to…

The security model

How authorization works in Osy#, end to end. Everything is denied until you grant it; a grant is compiled into every query rather than checked…

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…

Declared personal data — say whose a row is, and the platform answers for it

An entity that says WHOSE personal data a row is — one field marked `[DataSubject]` — and which privacy category it is held under —…

OAuth account completion — Security.VerifyPendingOAuthEmail / LinkOAuthFromPending

The two server-side calls that finish an OAuth sign-in on your own pages. When someone signs in with a provider (Google, …) and has no account yet —…

ProviderIcon — the mark on every "Continue with …" and "Link …" button

The UserAccounts kit draws each sign-in provider's mark on its buttons — "Continue with …" on the sign-in page, "Link …" on the account page — from…

RoleChoice.HeldIn — where a role may be held: across the app, inside an organisation, or either

Each role an app offers through its pages says where it may be held: across the whole app (a `RoleGrant`), only inside an organisation (the role a…

Security.Authorize — does THIS person satisfy a policy

`Security.Authorize(person, Policy)` answers whether a given person satisfies a declared policy — evaluated exactly as it is for a request of theirs…

Security.Fingerprint

A deterministic, KEYED fingerprint of a value — store it in a column anyone may read, look a code up by exact match, and a reader of the table still…

Security.IsMasked — was this value withheld from me?

A field a `deny read` withholds reads as its type's default — 0, false, DateTime.MinValue, the enum's zero; null for a nullable or reference type…

Security.MayRead — may THIS person read this row, under their own rules

`Security.MayRead(person, row)` answers whether a given person may read a given row under THEIR OWN security — the app's read rules, every kit's…

[Actor] — a principal that code may run as

A class marked `[Actor]` declares a principal that code may run as: a robot, a nightly job, an integration, a digital coworker. The platform makes…

[AuthMethod(AuthSlot.X)] — the sign-in slot a method is written for

`[AuthMethod(AuthSlot.X)]` says which `app.AuthBootstrap` slot a sign-in method is written for. A package that ships sign-in methods but states no…

[AuthMethod] — a function an unauthenticated visitor may call

`[AuthMethod]` marks a sign-in function — login, signup, password-reset — as reachable by a visitor who is not signed in. Everything else in your app…

[Authority]

What an app that imports your entity may do to the `security { }` you declared on it. The default is `Narrowable` — the app may state its own rules…

[Intended] — acknowledging an osy explain finding

`osy explain` flags a few postures with ⚠ — a public page whose data the public cannot read, a topic open to signed-out callers, a join rule that…

`role` — a package's name for the app's own roles

A package cannot know an app's `[Role]` enum, and an app has exactly one. `role` is how a package names it anyway: a column or setting typed `role`…

acting for another principal

A shared terminal, a kiosk, a scanner or a back-office integration is a **user of your app**, not a mode of it. It holds its own `[Principal]` row…

adding grants to your own entity from another file

A `security { }` block lives inside its entity's declaration, so a build shape that ships a subset of your files cannot add a grant — the entity is…

allow read via

Names the functions whose OWN reads of the entity see every row — past its read rules and its field masks — to compute a figure everyone may see:…

app.Auth — how the platform authenticates a user of your app

`app.Auth` binds two properties of your `[Principal]` — which one is the login, which one holds the password hash — and with that the platform can…

auth bootstrap (login, before anyone is signed in)

Under deny-all, login faces a paradox: it must read a user row *before* anyone is authenticated. `app.AuthBootstrap` resolves it. You name a…

capability rows that belong to a user

Some capability tables hold rows that belong to one signed-in user — your own allowance is yours, not the app's. Those capabilities scope every read…

deny on an inherited field

A subtype may NARROW a field it inherits — `deny read Notes when !IsReviewer;`, `deny update Code except via Recode;` — and never widen one: an…

deny … except via

Names the ONLY functions whose own code may change something a deny withholds: `deny update UnitsLeft except via Draw;`. The deny steps aside for…

grants (a link that opens one row)

A `grant` is a link the platform signs that lets whoever holds it reach ONE row of ONE entity, for a while, without signing in — the "manage your…

guest rows (a visit's own rows)

A row a guest makes before signing in — a basket, a saved choice, what they typed at the checkout — belongs to their VISIT. Inside a `security` rule…

navigation in security predicates (any depth, either side)

A `where` row filter may follow relations as far as the model goes — `Folder.Workspace.Region.Head == user` is a four-hop rule, and the principal…

personal data (Classification(Personal.X))

Mark a field as personal data once, on the property, with a level of the core `Personal` enum. From then on the audit trail never records its value…

policy

Names an authorization rule once so every place that needs it can say the name. A policy is a boolean about the caller, usable where security is…

principal predicates (IsAuthenticated / IsAnonymous / IsTheApp) and open reads

Two built-in `when` predicates say who a request is: `IsAuthenticated` is a signed-in user, `IsAnonymous` is an unauthenticated visitor, and…

public pages (what a signed-out visitor can see and do)

A public page, its public data, its public actions and its live updates are four separate declarations. `[AllowAnonymous]` on a component says a…

restricted rows and purpose reads (Restriction, [PurposeRead])

Keep a row only for a stated purpose: Restriction.Restrict stamps it with a privacy category and the end of its period, and from then on it is absent…

role grants (and the first admin)

A role is granted by an ordinary entity you mark `[RoleGrant]` — one that holds a reference to your `[Principal]` and a property typed as your…

rows that are part of another row

Some platform shapes decompose into several tables — a schedule owns its rules, and a rule owns its times, weekdays and month-days. Those child rows…

runas (actor, onBehalfOf: person) — an actor acting for a person

`runas (Actor, onBehalfOf: person) { … }` runs a block as a declared actor FOR a person: inside it nothing is read or written that the actor or the…

secure by default (deny-all)

Deny-all is the posture, and it is the only one: an entity that declares no `security { }` block is denied to every user request, and you grant…

security { }

The rules that decide who may read and write an entity's rows. A where clause filters by the row (the owner sees their own); a when clause gates by…

signup by invitation (invite, accept link, chase, expire)

How an app lets somebody INVITE a person who has no account yet. The invitation is a workflow: it mints a tokenised accept link the invitee can…

what a refused user is told

When a write is refused, two different sentences are produced from it. The person using your app gets a short one that names the operation and the…

when is who, where is which rows

A rule's `when` says WHO it is for and its `where` says WHICH ROWS. A rule whose `when` does not hold is never asked, so each kind of caller pays…