Start an annotatr-control-v1 service for a session so that a partner
process (for example qupflowR) can read state and events and send typed
commands. Nothing is started unless this function is called with
control = "loopback". The service binds only to 127.0.0.1, requires a
random 256-bit bearer token that expires after ttl_seconds, rejects
browser-origin requests, enforces JSON size and path limits, and resolves
file references only below root. There is no endpoint that evaluates code.
Usage
at_control_start(
session,
control = "loopback",
host = "127.0.0.1",
port = 0L,
ttl_seconds = 900L,
root = NULL,
token_file = NULL,
read_only = FALSE,
max_body_bytes = 1048576L,
serve = TRUE,
call = rlang::caller_env()
)Arguments
- session
What to control: an annot_session (or anything
at_annotate()accepts).- control
Must be
"loopback".- host
Must be
"127.0.0.1".- port
Port;
0picks a random free port.- ttl_seconds
Token lifetime in seconds (1 to 86400).
- root
Directory for payload references, exports, training exports and the lifecycle manifest; defaults to
<session out_dir>/control.- token_file
Optional path of a new file to receive the token (for a client process). It must not exist yet.
- read_only
Logical; refuse annotation mutations.
- max_body_bytes
Maximum request body size.
- serve
Logical; start the HTTP listener. With
FALSEonly in-process calls through the handle are possible (useful in tests).- call
The calling environment, for error reporting.
Value
An at_control_handle (a list with kind = "local", instance_id,
session_id, host, port, pid, manifest, expires_at); its print
method never shows the token.
Details
The token is never written into URLs, logs, downloads, manifests or RDS
files. In-process calls use the returned handle; a separate client process
reads the token from token_file (created with owner-only permissions).
A sanitised lifecycle manifest annotatr-control-<instance_id>.json is
written to root at start and rewritten when the service stops.
Examples
h <- at_control_start(at_example_session(2), serve = FALSE)
at_control_state(h)$state_revision
#> [1] "0"
at_control_stop(h)