Management API
The authenticated HTTP API behind the dashboard and the CLI - sign-in, permissions, antiforgery, limits and audit.
On this page
Runwick.AspNetCore adds an HTTP API for reading and controlling jobs, queues, schedules, capacity and retention. The dashboard and the CLI both go through the same checks, so they share one set of permissions and one audit trail.
Setting it up
Both AuthenticationSchemes and MapGrants are required. MapRunwickManagement throws at startup when either is missing, or when a named scheme is not registered. There is no anonymous mode and no "localhost only" mode.
You bring the sign-in: cookies, OpenID Connect, JWT bearer or anything else ASP.NET Core supports. Runwick does not change your default scheme. It tries the listed schemes in order and never sends a redirect challenge.
Permissions
MapGrants turns the signed-in user into a list of ManagementGrant values. It runs on every request. Grants never come from the request body or headers.
The names are constants on ManagementPermissions. Three presets cover the usual cases:
Payload, error and audit reads and Jobs.Dispatch are in no preset. Add them on purpose:
Scoping to queues
Jobs.* and Queues.* grants can be limited to some queues:
Jobs outside the caller's queues answer 404, exactly like jobs that do not exist, so hidden IDs are never confirmed. Lists are filtered before paging. Schedule, capacity, settings, retention and audit permissions are application-wide; giving them a queue list throws when the grant is built, so a mistake never widens access.
Antiforgery
Every POST from a browser or a Basic client needs an antiforgery token. Fetch it with GET {prefix}/v1/antiforgery, then send it in the X-Runwick-Antiforgery header:
The CLI does this for you.
Machine clients
A service that calls the API with a bearer token has no cookie, so antiforgery adds nothing. Map the API for machine clients:
ForMachineClients() refuses cookie and Basic schemes. If any configured scheme is one of those, it throws at startup. Runwick ships no bearer handler; use your own.
Basic authentication
For small setups, AddRunwickBasic adds a Basic scheme. You must supply the password check; there are no default credentials.
- Requests over plain HTTP are refused.
- After 10 failures a minute for one source address and user name, further tries are refused without checking.
- Basic counts as a browser scheme, so
POSTrequests still need the antiforgery token.
Revisions and command IDs
Every control carries the revision the caller last saw, for example "cancel job 42 at generation 1, revision 7". If the target changed in between, the answer is a 409 conflict (stale_revision or stale_generation), not a surprise.
Every control also carries a commandId. If a reply is lost, send the same request with the same command ID: the store returns the original result with replayed: true, with no second change and no second audit row.
Limits
Limits are per process and per signed-in caller. Change them with Configure:
Over a per-caller limit the answer is 429 with Retry-After. When the process is full it is 503 busy. With several replicas, each replica counts on its own.
List cursors are protected with ASP.NET Core Data Protection. Replicas that share a key ring accept each other's cursors. Set CursorKey (32 bytes or more) if they do not.
Audit
Every successful change writes an audit row in the same transaction as the change: who, what, when, the command ID and the reason you passed. Revealing a payload or an error is audited too, and the data is returned only after the audit row is committed. Read the trail with Audit.Read, in the dashboard's Audit page or with runwick audit list.
By default the actor is the user's NameIdentifier claim (or Name), their name, and the scheme used. Override it with .Actor(principal => new ManagementActor(subject, display, scheme)).
Denied requests are not audited. Failed sign-ins are logged (event 1401) with a coarse hash of the source, never the address or user name.
A standalone management host
The API does not need workers. A small internal web app can serve only the API and the dashboard:
This process runs no worker and writes no worker heartbeat. It is also a good place to collect application-wide metrics; see Observability.