gizlang:security
Shared identity, session proof and authorization decisions. Protocols adapt credentials and persistence; they do not define a second permission system.
import * as Security from "gizlang:security";Types
Signed
type Signed = { who: string; issued: i64; }A signed claim: who it names and when it was issued (ms since 1970).
who:stringissued:i64
Identity
type Identity = { identity: string; tenant: string; role: string; secret: bytes; }A registered identity: its name, tenant, role and secret.
identity:stringtenant:stringrole:stringsecret:bytes
Registration
type Registration = { principal: Identity; enabled: bool; revokedBefore: i64; revision: i64; }The registration of an identity: whether it is enabled, the time before which its sessions are void, and its revision.
principal:gizlang_security.Identityenabled:boolrevokedBefore:i64revision:i64
Authority
type AuthorityShare this authority across DB, HTTP and Agent entrypoints. Registry edits are immediately visible to every holder; authenticated sessions pin a revision.
Opaque: create and use it through this module's functions.
ResourceRef
type ResourceRef = { space: string; type: string; key: string; }One reference to any record: its Space, the stable declaration of its record type and its key. Trusted adapters supply the target and all its ancestors, including itself. Its one text form is SPACE/TYPE/KEY (see ResourceRef.text).
space:stringtype:stringkey:string
Role
type Role = | { kind: "none"; } | { kind: "viewer"; } | { kind: "commenter"; } | { kind: "editor"; } | { kind: "manager"; } | { kind: "owner"; }A role, from none to owner, in the order none < viewer < commenter < editor < manager < owner.
noneviewercommentereditormanagerowner
Principal
type Principal = | { kind: "person"; id: string; } | { kind: "agent"; id: string; ceiling: Role; onBehalf: string; } | { kind: "group"; team: ResourceRef; } | { kind: "link"; digest: bytes; } | { kind: "public"; }Who acts or holds a grant. A group holds grants and never acts: a person who
holds a role on the group's reference (type group) is a member of it.
personagentgrouplinkpublic
Grant
type Grant = { principal: Principal; target: ResourceRef; role: Role; expires: i64; }A grant of a role on a record to a principal, until expires (0 never).
principal:gizlang_security.Principaltarget:gizlang_security.ResourceRefrole:gizlang_security.Roleexpires:i64
Decision
type Decision = { allowed: bool; role: Role; reason: string; }The answer of a Policy decision: whether it is allowed, the role that the actor holds, and the reason.
allowed:boolrole:gizlang_security.Rolereason:string
Capability
type Capability = { principal: Principal; target: ResourceRef; role: Role; expires: i64; revision: i64; }A signed, short-lived permission: principal holds role on target until
expires, as decided at policy revision. A holder of the key verifies it with
no lookup, so HTTP, S3, the mount and a CDN decide alike.
principal:gizlang_security.Principaltarget:gizlang_security.ResourceRefrole:gizlang_security.Roleexpires:i64revision:i64
Functions
authority
function authority(): AuthorityAn authority with no principals.
Effects: fail, write.
token
function token(secret: bytes, principal: string, issued: i64): stringA session token for PRINCIPAL issued at ISSUED (milliseconds), signed with SECRET (HMAC-SHA-256).
Effects: fail.
verified
function verified(secret: bytes, text: string, now: i64): Option<Signed>The principal and issue time of the token TEXT when its signature with SECRET is valid, else none.
Effects: fail.
validSession
function validSession(signed: Signed, enabled: bool, revokedBefore: i64, now: i64): boolWhether the session SIGNED is valid at NOW: the principal is enabled, the token is newer than REVOKEDBEFORE, and its age is within the session life.
Effects: fail.
parseResourceRef
function parseResourceRef(text: string): ResourceRef throws stringThe reference of the text SPACE/TYPE/KEY (ResourceRef.text). It fails on any other form.
Effects: fail.
rank
function rank(role: Role): i64 effects {}The only role order: none < viewer < commenter < editor < manager < owner. An Operation names the least role that it needs; viewer marks a read.
roleText
function roleText(role: Role): string effects {}The one text of a role: its kind.
parseRole
function parseRole(text: string): Role throws stringThe role of its text ("none", "viewer", "commenter", "editor", "manager", "owner"). It fails on any other text.
Effects: fail.
principalText
function principalText(p: Principal): stringThe one text of a grantee: person:ID, agent:ID, group:SPACE/group/KEY, link:HEX or public. An agent's text names the agent only: its ceiling and its person come from the actor, never from a grant.
Effects: fail.
parsePrincipal
function parsePrincipal(text: string): Principal throws stringThe principal of its text ("public", "person:ID", "agent:ID", "group:REF" or "link:HEX"). It fails on any other text.
Effects: fail.
decide
function decide(actor: Principal, ancestry: Vec<ResourceRef>, grants: Vec<Grant>, needed: Role, now: i64): Decision effects { fail }Total, pure authorization: whether actor holds at least needed on the first
reference of ancestry, through grants on it or on its ancestors. Grants only
add; there is no deny. Public and link grants match only that actor. A person
also holds the grants of its groups (the membership grants are in grants).
Agents need their own grant and their person's grant, under their ceiling. A
grant never supplies an agent's trusted ceiling or delegation identity. A group
never acts. The compiler marks bounded Vec iteration as fail; no state or IO is used.
Effects: fail.
capability
function capability(key: bytes, granted: Capability, now: i64): string throws stringThe token of a capability that decide admitted: HEX(body).HEX(HMAC-SHA256).
Effects: fail.
admitCapability
function admitCapability(key: bytes, token: string, now: i64): Capability throws stringThe capability of a token that key signed and that is still live at now.
Effects: fail.
policyDigest
function policyDigest(domain: string, definitions: Vec<string>): bytesGeneral policy identity; adapters provide canonical observed facts.
Effects: fail.
digest
function digest(data: bytes): stringThe SHA-256 of data in lowercase hex: the one content digest of tokens, keys and cache names.
Effects: fail.
passwordHash
function passwordHash(password: string, salt: string): stringA password's stored hash under salt: PBKDF2-SHA-256, 32 bytes, in lowercase hex.
Effects: fail.
Methods
Authority.register
function Authority.register(self: Authority, principal: Identity): bool throws stringAdds PRINCIPAL. It fails when the principal is not valid or its identity is already registered.
Effects: fail, read, write.
Authority.lookup
function Authority.lookup(self: Authority, identity: string): Option<Registration>The registration of IDENTITY, or none.
Effects: fail, read.
Authority.authenticate
function Authority.authenticate(self: Authority, identity: string, credential: bytes): Option<Registration>The registration of IDENTITY when CREDENTIAL (32 bytes) matches its secret and it is enabled, else none.
Effects: fail, read.
Authority.replace
function Authority.replace(self: Authority, principal: Identity, enabled: bool, revokedBefore: i64): bool throws stringRevocation/change occurs at the trusted authority, not in client claims.
Effects: fail, read, write.
Authority.current
function Authority.current(self: Authority, evidence: Registration): boolWhether EVIDENCE is still the current revision of an enabled registration.
Effects: fail, read.
Authority.resolve
function Authority.resolve(self: Authority, signed: Signed, now: i64): Option<Registration>The registration of the session SIGNED when it is valid at NOW, else none.
Effects: fail, read.
ResourceRef.text
function ResourceRef.text(self: ResourceRef): stringSPACE/TYPE/KEY: SPACE and TYPE are 1 to 64 of a-z 0-9 _ . - and KEY is the percent-encoded UTF-8 key (Http.encode). At most 512 bytes. Equal texts are equal references: parseResourceRef accepts only this form.
Effects: fail.
Constants
SESSION_LIFE
const SESSION_LIFE = 2592000000How long a session lasts, in milliseconds (30 days).
CAPABILITY_LIFE
const CAPABILITY_LIFE = 300000The longest life of a capability: the revocation bound of reads that check no grant.
PASSWORD_ROUNDS
const PASSWORD_ROUNDS = 120000How many rounds a password hash takes.