Build Applications

Bounded HTTP Service

Build, inspect, and deploy one checked HTTP/1.1 handler inside the bounded generated service host.

Choose http-service when one checked Topaz function should receive an HttpRequest and return an HttpResponse. The generated native host owns the listener, HTTP/1.1 framing, finite request budgets, overload responses, logging, and shutdown.

This is not a general Web server framework. It does not grant outbound networking, raw sockets, ambient environment access, shared mutable Topaz state, TLS, HTTP/2, WebSocket, or sessions. Put a normal reverse proxy in front of the process for public TLS and Internet-edge policy. Treat this explicit Capability boundary as part of the product design.

Complete First Application first. Building the service requires a Rust toolchain for the deployment platform.

Create, lock, and test

The scaffold supplies the package manifest, bounded service defaults, and a concrete handler:

BASH
topaz init --target http-service --root hello-service
topaz lock --root hello-service
topaz fmt --check --root hello-service
topaz check --root hello-service --locked
topaz test --root hello-service --locked

The entry module exports exactly one handler with this shape:

TOPAZ
import std.http { HttpRequest, HttpResponse, text }

export function handle(req: HttpRequest) -> HttpResponse {
  if req.method == "GET" && req.url.path() == "/health" {
    return text(200, "ok")
  }
  text(404, "not found")
}

The checker rejects a missing, generic, variadic, defaulted, or differently typed handler before the listener can start.

Develop through loopback

Run the actual generated service on loopback and request its health route:

BASH
topaz dev --root hello-service --port 8080
curl --fail-with-body http://127.0.0.1:8080/health

topaz dev forces the bind address to 127.0.0.1, rebuilds the managed service, and forwards interruption to it. If port 8080 is occupied, choose another loopback port with --port.

Keep finite service budgets

The scaffold records bounded defaults under [service]:

TOML
[service]
bind = "127.0.0.1"
port = 8080
workers = 1
max_connections = 64
queue_capacity = 32
max_target_bytes = 8192
max_header_bytes = 16384
max_headers = 64
max_body_bytes = 1048576
header_timeout_ms = 5000
body_timeout_ms = 5000
handler_timeout_ms = 1000
shutdown_grace_ms = 5000
log_format = "text"

Unknown keys and out-of-range values fail during package loading. Each request gets a fresh runtime context and module graph; requests do not share a Topaz heap. Queue saturation, oversized input, handler deadlines, and invalid responses become bounded host outcomes rather than unbounded work.

Build and inspect the product

BASH
topaz build --root hello-service --locked --release --out-dir hello-service-product
cd hello-service-product
./target/release/program --print-config
./target/release/program

On Windows, run target\release\program.exe. The product tree is:

Output
hello-service-product/
├── GENERATED-OUTPUT-NOTICE.txt
├── LICENSE
├── NOTICE
├── THIRD-PARTY-NOTICES.txt
├── target
│   └── release
│       └── program[.exe]
├── topaz-artifact.json
└── topaz-service-config.json

program[.exe] means program on Unix and program.exe on Windows. --print-config validates and prints effective settings without opening a listener. The managed JSON file records the embedded defaults. Runtime overrides use explicit command-line flags; an explicit non-loopback bind looks like this:

BASH
./target/release/program --bind 0.0.0.0 --port 8080

Use that only behind the intended network boundary. The manifest itself may name only a loopback address.

Observable failures

  • Oversized bodies, targets, or header sets produce bounded HTTP errors where framing permits a response.
  • A full handler queue returns 503; a handler deadline returns 504.
  • A runtime fault or invalid application response returns a generic 500 without exposing source paths, request content, or Topaz fault text.
  • Responses and host logs share a request ID. Logs omit targets, bodies, and header values.
  • SIGINT and, on Unix, SIGTERM stop admission and drain existing work until shutdown_grace_ms.

If check or test fails, repair the Topaz diagnostic and repeat the same command. If a build finds a changed managed file or another target in the output directory, keep that directory for inspection and choose a new empty --out-dir.

Source-free deployment

Copy the complete hello-service-product/ directory so the executable, configuration record, integrity manifest, licenses, and notices stay together. The copied product needs neither package source, Topaz CLI, a registry, nor the temporary Cargo workspace. Run it under a process supervisor, retain the generated budgets, and terminate public TLS at a reverse proxy.