/how-it-works
Simple services.
Plat5 sits in front of your services. On every request it answers three questions, records what's about to happen, and forwards the request with the owner in the path.
- 1
Who is calling?
Your identity provider says, from its token. Or Plat5 does, from one of its API keys or sessions.
- 2
Which organization?
The credential decides. Never a header, a body field, or a path the client chose.
- 3
May they call this route?
The member's role grants permissions. The route says which one it needs.
Client sends
GET /org/projectsX-API-Key: acme-s-2-Q7vN…Plat5
Your service receives
GET /organizations//projectsX-API-Key removedX-Request-ID: 7d6f1c2e…traceparent: 00-4bf92f35…/why
Why your services stay simple, and stay safe.
- 01
Your code never handles credentials.
Plat5 signs callers in and removes the token or key before forwarding. Your service gets ids, a request id and a trace. There is nothing to leak and nothing to validate.
- 02
The credential picks the organization.
A client can't ask for another customer's data, because it never names a customer. A route you publish tomorrow is isolated the same way, with no new checks.
- 03
Permissions are checked before your code runs.
Roles come from one file, and routes say which permission they need. A missing permission is refused at the gateway, so services never see a role.
- 04
Every change is recorded before it is forwarded.
If the audit log can't take the record, the request is refused and your service is never called. A change can't happen without its record.
- 05
Same service, two front doors.
Customers come through the Plat5 gateway. Your staff come through Operator, on your company login. Both call the same paths, so your support tools are your product's own API.
- 06
Everything else is decided once.
Errors, request ids, lists, logs and audit details each have one standard. Nobody designs them again for a new service, and every service answers the same way.
/every-caller
Write it once. Everyone can use it.
Your web app, your customers' scripts and your support team all call the same code. Permissions and the audit log apply to each of them. You never build a separate admin API or integration API.
Your web app
A member, with a session
X-API-Key: acme-s-2-…A customer's integration
A service account, with a key
X-API-Key: acme-k-2-…Your support team
Staff, with your company login
Authorization: Bearer …Plat5 gateway
Fills in the caller's organization
Operator
Staff name the organization. Every request goes in the staff log
Your service
GET /organizations//projects One handler. Written once.
/request
What happens to a request.
In this order, every time.
- 01Sign inJWT, API key or session401
- 02Rate limitPer IP, user, org or member429
- 03RecordAudit intent, before anything changes503
- 04Check permissionThe member's role labels403
- 05Fill in the ownerInto the upstream path
- 06ForwardCredentials removed, trace added502
- 07Record outcomeAfter the response
/scopes
Every route says who owns it.
The scope decides which credential a route takes and which ids your service receives. A scope names the owner, never the caller.
Routes and scopes →| Scope | Owner | Credential | Your service gets |
|---|---|---|---|
public | No one | None | — |
user | The person calling | Sign-in token or personal key | user_id |
organization | The organization | Member key or session | organization_id |
member | The member's own records | Member key or session | organization_id, member_id |
/architecture
What runs.
Four small processes and three stores, in one Docker Compose stack. Your services live on a private network that only the gateway can reach: that's what makes the path trustworthy.
Clients
Edge
Private network
State
/ideas
The ideas behind it.
A few decisions shape everything above. The full reasoning is in the model.
A route names its owner, never its caller.
The scope says who owns what the route addresses. Your service stores owners.
Services see owners, not actors.
Who did something is in the audit log. When it matters to your product, it becomes a record the member owns, like a comment or an approval.
A credential is never narrower than its member.
To give a machine less, give it a service account with a smaller role.
Plat5 decides only about what it stores.
Organizations, members and roles. Access to individual resources, like a private project, belongs to a policy engine.
Your roles, not ours.
Plat5 ships a starter roles file and gives no role special meaning.
Product features never read the audit log.
It's for reporting and compliance, so it can be off, restricted, or trimmed without breaking anything.