asobi_console_controller (asobi v0.84.0)

View Source

HTTP surface of the operator console: the shell, its assets, and the session the browser exchanges the operator secret for.

This route group is unauthenticated on purpose, and that is a narrower statement than it looks. It serves three things: a document with no data in it, content-hashed static files, and the login endpoint - which cannot require the credential it exists to accept. Every byte of game data the console shows comes from /api/v1/ops, behind asobi_ops_auth.

When the console is not enabled these routes answer 404, not 403, and it is the same 404 an unknown asset gets. A deployment that has the console switched off is indistinguishable from one that has it on and was asked for a file that does not exist.

Summary

Functions

One bundled asset, by basename.

The shell document. Never cached: it carries a per-response CSP nonce.

Exchange a credential for a session.

End the session and clear both cookies. Idempotent.

Whether this browser has a live session, and who it says it is.

Types

response()

-type response() ::
          {json, integer(), map(), cowboy_req:req(), map()} |
          {status, integer(), map(), binary()} |
          {asobi_error, asobi_error:code()}.

Functions

asset/1

-spec asset(cowboy_req:req()) -> response().

One bundled asset, by basename.

The binding is a map key, never a path segment joined onto a directory - see asobi_console. A name that is not in the bundle is 404 whether it is a typo or a traversal attempt.

index(Req)

-spec index(cowboy_req:req()) -> response().

The shell document. Never cached: it carries a per-response CSP nonce.

login(Req)

-spec login(cowboy_req:req()) -> response().

Exchange a credential for a session.

Two are accepted, and they are the two the ops plane already takes:

  • secret - the operator secret, checked by asobi_ops_auth:verify_secret/1 so the constant-time comparison and the no-default rule live in one place and this endpoint cannot drift from the bearer plane. It proves every capability class.
  • token - a minted, env-scoped token from the control plane (asobi_ops_token). It proves only the classes it carries, and the session it opens carries exactly those and expires no later than the token does. A fifteen-minute credential must not buy a twelve-hour session.

The minted path is what makes a managed environment's console reachable: the browser posts the token once and then holds a cookie, so the token never has to live in JavaScript for the length of a session.

A wrong credential is 403 forbidden with the same body a wrong bearer token gets, so the two planes are indistinguishable to a caller guessing.

logout(Req)

-spec logout(cowboy_req:req()) -> response().

End the session and clear both cookies. Idempotent.

session(Req)

-spec session(cowboy_req:req()) -> response().

Whether this browser has a live session, and who it says it is.

Requires the cookie and the CSRF header like every other ops read, so it is not a way to learn the CSRF token - the browser already has that from the companion cookie.