Skip to main content

Module actors

Module actors 

Source
Expand description

v0.45 actor contracts (the actors-foundations slice).

An actor declaration is a nominal boundary contract (ADR Q1): a closed, compiler-known authentication Scheme plus an optional sealed identity. A handler consumes an actor on its by clause; the boundary verifies the scheme and mints the identity before the body runs (two-phase, fail-closed — ADR Q5/Q2).

This module holds the compiler-known parts: the closed scheme set, the prelude actors, the per-protocol default actors, and the admissible-scheme sets. Foundations admits only the two zero-crypto schemes (None, Internal); Bearer/Signature are reserved-and-rejected.

Structs§

ActorDecl
P6.49 (design/tracks/the-ir.md §6b), following P6.27’s ExprId precedent: every reader in this module — bearer_seam_for, oidc_seam_for, signature_seam_for, sum_members_for, caller_binder_for — is already parameterised by &HashMap<String, ActorDecl>. bynk-emit clones and forwards this table (project.rs’s EmitProjectCtx::actors, emitter/workers.rs/workers_entry.rs’s own actors parameters) without ever reading an ActorDecl field itself — P6.34 investigated and declined resolving it earlier, since bynk-emit’s own lower_actor_seam_ir needs the raw declarations to do its own resolution; this re-export changes the import path, not that data flow. An actor declaration (v0.45 §3.7). An actor is a nominal contract type describing an external party at a boundary — not a runnable entity. A handler consumes an actor on its by clause; the boundary verifies the declared auth scheme and mints a sealed identity (name.identity).
BearerSeam
v0.47: the data the emitter needs to lower a Bearer verification seam for a handler — the by binder (v0.50: None for the binder-less verify-and- discard form), the signing-secret env name, and the identity type to construct from the JWT sub claim. Resolved only for a handler whose by clause names a local Bearer actor; the checker guarantees the secret is present and the identity is a string-constructible local type.
CallAdmission
I3 (#1971): which verified callers an on call handler admits. Every call is authenticated before it reaches a handler (wire_format); this is what the handler then admits, in its by clause’s order. A Bynk context is admitted by Caller (the default with no by) or a local Internal actor; a foreign caller only by its own Foreign actor, never by Caller.
Contract
A resolved actor contract: its scheme and the identity it yields.
ForeignCaller
I3 (#1971): a declared foreign caller, as a call handler admits it: the actor’s name, which the caller sends as X-Bynk-Caller, and the secret the callee verifies its signature under.
OidcSeam
v0.151: the data the emitter needs to lower an OIDC/JWKS verification seam — the by binder (or None for the verify-and-discard form), the public trust parameters (issuer, audience, jwks URL), and the identity type to construct from the verified sub claim. Resolved only for a handler whose by clause names a local Oidc actor. Unlike Bearer/Signature, the seam carries no secret env name — the trust root is the provider’s published public key set (jwks).
SignatureSeam
v0.51: the data the emitter needs to lower a Signature verification seam — the signing-secret env name, the signature header, and an optional timestamp header + tolerance window for replay defence. Resolved only for a handler whose by clause names a local Signature actor.
SumMember
v0.52: one resolved member of a multi-actor sum — the seam the emitter tries at that position in the first-wins order. actor_name is the variant tag the body matches on.

Enums§

CallSumMember
I3 (#1971): one member of a call handler’s actor sum.
ClaimPredicate
v0.53: the closed claim-predicate vocabulary for a refinement actor’s where clause (actor Admin = User where hasClaim("admin")). Claims are untyped JSON, so the predicate is a closed set — hasClaim/claimEquals composed with &&/||/! — checked against the verified JWT claims at the boundary. A general typed-claims expression surface is a later slice.
Identity
The identity a verified actor yields (ADR Q2). In Foundations this is () for trivial actors, the built-in sealed CallerId for the cross-context Internal channel (Q7, folded in), or a context-owned declared type.
Scheme
The authentication scheme — a closed, compiler-known set (ADR Q1). Sealed now, openable later by widening this enum.
SumMemberSeam
The verification a sum member contributes. None (a catch-all such as Visitor) always resolves, so it terminates the order.

Constants§

CALLER_ID
The built-in sealed identity type for the cross-context calling principal.

Functions§

bearer_seam_for
by_clause_is_bearer
Resolve a handler’s Bearer seam, if its by clause names a local Bearer actor — or a refinement of one (v0.53), following the refinement to its base for the scheme/secret/identity and carrying the authorisation predicate. Returns None for non-Bearer handlers (prelude actors are never Bearer) — those emit unchanged. #706: whether a by clause names a Bearer-secured actor (following a refinement to its base). The routes for which by Nobody can drive the auth seam to a 401 — an unsecured (Visitor/None) or Signature/Oidc route has no Bearer seam the test driver knows how to leave unauthenticated, so by Nobody there is rejected (bynk.test.nobody_needs_secured_route). The scheme check mirrors bearer_seam_for.
call_admission_for
I3 (#1971): what an on call handler admits. None off the call path.
caller_binder_for
v0.54: the binder of a cross-context on call … by c: Caller handler that captures a live CallerId (the calling context’s name, Q7). None unless the handler binds an identity whose contract is CallerId — i.e. the Caller prelude actor (the only source of CallerId). A binder-less on call (or one inheriting the Caller default) captures nothing and is unaffected.
claim_predicate_to_js
Lower a claim predicate to a JavaScript boolean expression over claims_var (the verified claims object, Record<string, unknown>). Used by the emitter for the refinement seam’s 403 check.
claim_witness_js
#2019: a JavaScript object literal of JWT claims that satisfies a refinement actor’s predicate, for the system-tier test driver to sign next to sub when a case acts as that refinement (by Admin("root")): hasClaim("admin") → { "admin": true }, claimEquals("role", "ops") → { "role": "ops" }. The Worker’s seam then checks the predicate against the verified claims exactly as it would a real token’s. A Truthy need signs true: a boolean is never === a string, so it also lies outside every excluded value. An absent claim meets Falsy and NotEquals, so those sign nothing. The search is exact over the closed vocabulary, so None means no claim set satisfies the predicate (hasClaim("a") && !hasClaim("a")).
default_actor
The default actor a handler inherits when it omits by, by protocol (ADR Q5). HTTP has no safe default — by is required there.
foreign_caller_of
I3 (#1971): the foreign caller an actor declaration describes, if it is a Foreign-scheme actor with a secret.
oidc_seam_for
Resolve a handler’s OIDC seam, if its by clause names a single local Oidc actor. Returns None for non-Oidc handlers, for a multi-actor by clause (Oidc is single-actor this slice), and for a refinement (refinement over Oidc is a later slice) — those follow the existing seam paths. The checker guarantees issuer/audience/jwks are present and the identity is a string-constructible local type.
parse_claim_predicate
Recognise the closed claim-predicate vocabulary in a refinement where expression. Err(span) points at the first sub-expression outside the set (for bynk.actor.refinement_predicate_unsupported).
prelude_actor
The prelude actors — compiler-known boundary contracts available without a declaration. They back the per-protocol defaults and let public HTTP routes write by v: Visitor without ceremony.
route_is_secured
#2155: whether a by clause’s route has a credential seam the system driver can leave out (by Nobody): a Bearer actor (or a refinement of one), a Signature actor, or an actor sum with such a member and no open member (sum_has_open_member).
scheme_admissible
Whether scheme is admissible on protocol (the admissible-scheme-per- protocol check). HTTP admits None (public routes) and Bearer (an Authorization header is an HTTP concept); the internal protocols (call/cron/queue) admit Internal. Signature is still reserved.
signature_seam_for
Resolve a handler’s Signature seam, if its by clause names a local Signature actor. The checker guarantees secret and header are present.
signature_seam_for_by
#2135: signature_seam_for from the by clause alone — the seam of its primary actor, when that is a local Signature actor.
signature_seam_of_route
#2155: the Signature seam a by clause’s route is signed with at the system tier — its one actor’s, or an actor sum’s first Signature member’s (what by Forged/by Stale sign as). None when it has none, and for a sum with an open member (sum_has_open_member), whose seam never refuses a bad signature.
sum_has_open_member
#2155: whether an actor sum has an open member — Visitor, or a declared actor with no auth scheme. The sum’s seam resolves a request with a missing or bad credential as that member, so it never answers 401: by Nobody, by Forged and by Stale have nothing to drive there.
sum_members_for
v0.52: resolve a handler’s by clause into ordered sum members, if it names more than one actor. None for a single-actor handler (those keep the existing seam paths). The checker has already validated peer/scheme/ reachability rules; this lowers the verified members for emission.