Routes and scopes
Every route you publish says who owns what it addresses. That is its scope. Plat5 reads the caller’s credential, and for the route’s scope it writes the owner’s id into the path your service receives.
services: api: organization: routes: - path: /org/projects upstream: /organizations/{subject.organization_id}/projects methods: [GET, POST]A client calls GET /org/projects with an organization’s credential. Your service receives GET /organizations/01JD8X…/projects. The client never sends an organization id, so it can’t ask for another organization’s data.
The four scopes
Section titled “The four scopes”| Scope | Who owns it | Credential | Your service gets |
|---|---|---|---|
public |
No one | None | Nothing |
user |
The person calling | Their sign-in token or a personal API key | {subject.user_id} |
organization |
The organization | A member’s API key or session | {subject.organization_id} |
member |
The calling member’s own membership | Same as organization |
{subject.organization_id} and {subject.member_id} |
A scope names the owner, never the caller. On an organization route your service learns which organization, not which person or key called. Who did what is in the audit log.
Use member scope for things a member owns: their own API keys, their comments, their subscriptions, or “the projects I can reach”.
What Plat5 does on every request
Section titled “What Plat5 does on every request”- Signs the caller in. A JWT from your identity provider, or a Plat5 API key or session. The wrong kind of credential for the scope is a 401.
- Applies the rate limit for the route, counted per IP, user, organization or member to match the scope. Over the limit is a 429.
- Records the request in the audit log, before forwarding it. Writes are recorded by default.
- Checks permissions. If the route lists
required_labels, the member’s role must grant one of them, or it’s a 403. - Forwards the request with the owner filled into
upstream, and withAuthorizationandX-API-Keyremoved. Your service gets anX-Request-IDand atraceparentinstead.
What your service does
Section titled “What your service does”- Reads ids from the path, and scopes every lookup by them.
- Enforces rules that hold no matter who asks, like “an archived project is read-only”.
- Never parses
Authorization, never validates a JWT, never checks membership. That already happened.
Trusting the path only works if nothing but Plat5 can reach your service. Run services on a private network the gateway can reach.
Publishing routes
Section titled “Publishing routes”Routes live in YAML next to your service. plat5 start publishes them locally. In production you apply them to the route registry, which keeps every revision and pushes changes to the gateway without a restart.
More: routes.md for the full format, and identity-boundary.md for the model.