Alysia edge gateway, mTLS, Cedar authz
  • Rust 97.3%
  • Shell 2%
  • Dockerfile 0.7%
Find a file
yubo c24c24f193
All checks were successful
CI / ci-freshness: vendored files match TEMPLATE_REV (push) Successful in 1s
CI / ci: lint, test, build (push) Successful in 1m0s
ci: weekly self-hosted Renovate via stored token
2026-10-08 17:59:45 +00:00
.github/workflows ci: weekly self-hosted Renovate via stored token 2026-10-08 17:59:45 +00:00
ci feat: extract gateway service from the monorepo 2026-10-08 17:53:41 +02:00
crates/gateway feat: extract gateway service from the monorepo 2026-10-08 17:53:41 +02:00
policies feat: extract gateway service from the monorepo 2026-10-08 17:53:41 +02:00
.dockerignore feat: extract gateway service from the monorepo 2026-10-08 17:53:41 +02:00
.gitignore feat: extract gateway service from the monorepo 2026-10-08 17:53:41 +02:00
Cargo.lock feat: extract gateway service from the monorepo 2026-10-08 17:53:41 +02:00
Cargo.toml feat: extract gateway service from the monorepo 2026-10-08 17:53:41 +02:00
clippy.toml feat: extract gateway service from the monorepo 2026-10-08 17:53:41 +02:00
deny.toml feat: extract gateway service from the monorepo 2026-10-08 17:53:41 +02:00
Dockerfile feat: extract gateway service from the monorepo 2026-10-08 17:53:41 +02:00
justfile feat: extract gateway service from the monorepo 2026-10-08 17:53:41 +02:00
justfile.ci feat: extract gateway service from the monorepo 2026-10-08 17:53:41 +02:00
README.md feat: extract gateway service from the monorepo 2026-10-08 17:53:41 +02:00
rust-toolchain.toml feat: extract gateway service from the monorepo 2026-10-08 17:53:41 +02:00
rustfmt.toml feat: extract gateway service from the monorepo 2026-10-08 17:53:41 +02:00

alysia-gateway

The edge gateway of the Alysia platform, extracted from the Alysia monorepo (services/gateway/). Terminates TLS (mixed mTLS: socle services are named by their verified client certificate, the cert-less WASM plugin falls through to its bearer), authorizes every request against a versioned Cedar policy set evaluated in process, and routes it: native routes (queue, transfers, poll, aggregated ping) are served here, everything else is forwarded to the socle service that owns it — the caller's bearer never travels further. Serves /healthz in the clear (8081), the business routes behind mixed mTLS (8443), and the same business routes in the clear for the plugin (8082, ADR 0006).

Layout

Path Role
crates/gateway/ The service crate (lib + binary + integration tests)
policies/policies.cedar The versioned Cedar policy set, compiled at boot — moved from the monorepo's infra/gateway/policies.cedar, see below
Dockerfile Single-binary image (alysia/gateway), built from this repo
justfile.ci + ci/ Vendored from alysia-ci-templates at TEMPLATE_REV (see .github/workflows/ci.yml) — never patch locally

The policies move

In the monorepo the policy set lived at infra/gateway/policies.cedar while the code that compiles it (src/cedar.rs, src/lib.rs) and the tests that pin it (tests/cedar.rs, nine permit) live in the service: the file now lives in the repo that boots it, at policies/policies.cedar, byte-identical apart from the header (which records the provenance). Only the paths moved:

  • src/config.rs: DEFAULT_POLICY_PATH is policies/policies.cedar (overridable per environment via ALYSIA_AUTHORIZATION_POLICY);
  • src/cedar.rs + tests/{cedar,support}.rs: the versioned_path() reads ../../policies/policies.cedar from the crate dir.

The monorepo keeps its own copy until the compose stack reads the policy from here (or via ALYSIA_AUTHORIZATION_POLICY); the two files must stay in sync until then.

The identity decoupling

In the monorepo the forwarded-login and permission-sync tests booted the real identity service over containers (Postgres + JetStream) as an alysia-identity dev-dependency. That coupled two release trains to prove what the gateway owns: the request reconstruction (verb, natural route, headers, verbatim body/query) and the refusal that never forwards. This repo has no alysia-identity dependency; tests/support holds a stub identity service (stub_identity: login + permissions snapshot, behind the shared API version layer like the real one) and the TLS-shape tests serve it behind a strict mTLS listener, so criterion 3 (the gateway's own certificate completes the handshake) is still proved.

The contract with the real service is consumer-driven and compile-time: the stub answers the very PlayerLoginResponse / PermissionsSnapshot types of alysia-proto, and the tests deserialize the gateway's answer into those same types — a drift of the real shape fails here. Bonus: no test needs a container runtime anymore.

Dependencies

alysia-* crates come from the versioned libs release train as exact-tag git dependencies — never a branch, never a vendored copy. All alysia-* deps move together on a single tag (lockstep releases, currently libs-v0.1.0):

alysia-service = { git = "https://git.zeto.fr/alysia/alysia-libs.git", tag = "libs-v0.1.0" }

Development

just ci-lint                              # fmt + clippy + machete + deny
just --set test_args "" ci-test           # full suite (unit + integration, all in-process)
just --set image "alysia/gateway" ci-build # local image build (tag `local`); CI pushes `alysia/gateway:<sha>` on main

No DOCKER_HOST, no .sqlx/: the gateway holds no database and every test is in-process.

Image push

ci-build produces alysia/gateway:local. CI pushes git.zeto.fr/alysia/alysia-gateway/gateway:<sha> on main/tags — but only once a REGISTRY_TOKEN secret exists on this repo (it does not yet; the push step skips loudly until then). No image is ever pushed by hand.