A real site is rarely one backend. The app serves the pages, a bucket serves the static assets, and both want to live under one hostname. Mechanics 0.3.36 makes that composition first-class: a route owns the host and TLS identity, and named attachments map path prefixes to app instances or bucket addon prefixes.
ssh -T mechanics.run -- route create web --app myapp
ssh -T mechanics.run -- route attach assets --route web \
--path /assets --bucket media --prefix site/
ssh -T mechanics.run -- addon -a media public-read add site/
ssh -T mechanics.run -- route wait web
ssh -T mechanics.run -- route check web Attachments, not route sprawl
route create manages the reserved root attachment.
route attach and route detach manage the rest. Each
attachment renders its own HTTPRoute file in the gitops repo, paths must be
absolute and non-overlapping, and route wait and
route info aggregate readiness across every declared attachment.
A route is not ready while any of its paths is missing or pointing at an
unhealthy backend.
Bucket paths are read-only plumbing
A bucket attachment forwards only GET and HEAD, rewrites
to path-style S3 under the workspace-prefixed bucket, and terminates at a separate
read-only S3 gateway. Wiring a path to a bucket does not make objects public:
anonymous reads are a separate, explicit bucket policy managed with
addon -a <bucket> public-read list|add|remove, which grants
only s3:GetObject on the listed prefixes, never listing, writes, or
IAM actions.
Buckets stopped sharing identities
The groundwork landed in 0.3.35: every bucket addon now uses a workspace-scoped
IAM identity derived from the workspace-prefixed bucket name. Two workspaces can
create the same addon name without colliding on a principal, cross-workspace S3
access returns AccessDenied, and the public endpoint at
s3.mechanics.run is backed by a read-only gateway that denies
unauthenticated writes instead of falling back to permissive behavior.
The host belongs to the route, the paths belong to attachments, and public reads stay a policy you can point at.