Cratis Arc capability hosting
Cratis Arc capability hosting requires a verified caller for every request on an assigned endpoint-group port. Place the commands and queries you want to expose in that group, then enable the caller gate.
What it does
Section titled “What it does”Requests without a verified caller receive 401 with WWW-Authenticate: Bearer. Malformed authorization, multiple credentials, and credentials in a URI receive 400. A verified principal kind outside the configured allowlist receives 403. These refusals use application/problem+json, not HTML, and do not run the handler. Requests on other ports do not resolve a capability caller.
The default allowlist admits Person and DelegatedActor. Configure AllowedPrincipalKinds explicitly if the application also admits service principals.
Turn it on
Section titled “Turn it on”Configure the server listener, the endpoint-group assignment, and a verified caller installation. The following configuration fragment belongs in the runnable acceptance sample’s Program.Build, where settings supplies public verification material and the sample’s PersonDirectory provides persisted account mappings:
using Cratis.Arc;using VerifiedCallerAcceptance;
builder.WebHost.UseUrls($"http://127.0.0.1:{settings.DefaultPort}", $"http://127.0.0.1:{settings.CapabilityPort}");builder.AddCratisArc( options => options.EndpointGroups.Assign("capabilities", settings.CapabilityPort), configureBuilder: arc => arc.WithCapabilities().WithVerifiedCallers(callers => callers .ForResource("https://api.example.test", "example-api", "sample") .UsePersonDirectory<PersonDirectory>() .UseSignedForwardedIdentityV2(v2 => v2.WithRealmIssuer("https://identity.example.test") .AddPublicKey(settings.KeyId, settings.PublicKeyPem) .UseProcessLocalNonceStore())));Tag capability commands, read models, or query methods with [EndpointGroup("capabilities")]. Group membership is the explicit exposure choice; commands and queries outside that group retain their existing routing. Enabling capabilities without assigning the group’s port fails startup with CapabilityEndpointGroupHasNoPort. Startup also fails with CapabilityHostingHasNoCredentialInstallation when no credential verifier and receiving installation are registered.
For a different group name, set EndpointGroup through the WithCapabilities configuration delegate and assign a port to that same group. The verified caller guide explains custom signed tenant headers and fleet-wide nonce stores. Process-local replay protection is only a single-process sample choice.
Read the caller
Section titled “Read the caller”Inject Cratis.Arc.Capabilities.ICapabilityCallers into capability code. Its Current property returns the admitted CapabilityCaller, including the endpoint group, protocol rest, principal kind, person, current delegated actor, client metadata, credential identifier, checked grant identifier, tenant, and scope ceiling. Outside a capability call it is null.
A declared client is metadata, not an authenticated actor. Client.IsAuthenticated distinguishes authenticated client metadata from declared metadata. The scopes are a verified ceiling, not an authorization decision.
What events record
Section titled “What events record”With Arc’s Chronicle integration, a command executed while a capability caller is present adds a Capability entry to event causation. It contains these properties:
| Property | Value |
|---|---|
endpointGroup |
Receiving endpoint group |
protocol |
rest |
principalKind |
person, delegated-actor, organization-automation, cluster-workload, or runner |
person |
Product person reference |
actorIssuer |
Current delegated actor’s issuer |
actorSubject |
Current delegated actor’s subject |
clientId |
Client identifier |
clientAuthentication |
declared or authenticated |
credentialId |
Non-secret credential identifier |
grantId |
Checked delegation grant identifier |
tenant |
Verified tenant identifier |
Absent values are omitted, including an unset tenant. Tokens, secrets, scopes, and the internal credential kind are not recorded by this entry. Commands outside a capability call add no capability causation.
Limits today
Section titled “Limits today”- The public installer supports signed v2 browser-session callers; PAT, OAuth-grant, service-account, bearer-verifier, and on-behalf installation are separate work.
- Product authorization still applies: a capability is not authority. The verified caller is the principal used by Arc authorization, the current-principal accessor, and Chronicle identity/causation. Roles, policies, and live tenant membership must authorize that subject.
[RequiresScope]narrows access against the verified credential’s scope ceiling. Missing scopes mean an empty ceiling. Product cookies, roles, or a same-subject scheme cannot widen it, and scopes cannot replace product authorization.- A signed tenant is a candidate, not proof of membership. A conflicting authenticated subject is refused, not merged.
- Keep the group port private. Never expose it publicly or forward public traffic to it.
- Default-group endpoints reachable on the capability port also require a caller. There are no anonymous paths on that port, including health probes.
- MCP serving and protected-resource metadata follow separately; this API hosts REST capabilities only.