Repository navigation
Releases: plat5dev/plat5
Release list
v0.6.0
Breaking:
- Identity realms, one credential. People live in the directory and are linked to IdP subjects on first sign-in. API keys and sessions share one table and one validate call; the gateway asks once and the realm decides the route. v1 credentials issued before this release still validate. (d935810)
- Organization slug removed. The org id is the address and
nameis the label. (34825e7) - Staff-only routes.
GET /usersandGET /members/{member_id}/userare staff-only and off the customer catalog (7308c32). A person's status moved toPATCH /users/{user_id}/status, staff-only;PATCH /users/{user_id}now changes the name only (c13a956). - Org lifecycle events.
organization.createdandmember.createdare written in the same transaction as the create (a1fa5a5). Removing a member revokes their keys, deletes sessions and recordsmember.removed; removed is final, and re-adding the person creates a new member id. Org delete recordsorganization.deleted(4aab010).
Also
- A user route is recorded in the person's own audit log, and in the org's when the service names it (d935810).
- Docs describe the model as realms, one credential, and owners (9a7d93b).
- Compose images pinned to v0.6.0 (f1ba8f1).
Full changelog: v0.5.0...v0.6.0
v0.5.0
This release is everything since v0.4.4.
Breaking
- The gateway now requires
AUDIT_URLat boot, because audit is on by default. SetAUDIT_URLto the audit service's internal base URL, e.g.http://audit:3003. If you don't want audit, setAUDIT_ENABLED=falseon the gateway. Any value other thantrueorfalserefuses boot. - Route-registry apply now rejects service names that aren't 1–128 characters of
[A-Za-z0-9._-]. The audit event'sservicefield has the same limit. - On
organizationandmemberroutes that are audited, the gateway writes the audit intent before forwarding. While audit is down, those requests return 503 and the service is not called. Writes are audited by default. - The gateway's check order changed: authenticate, rate limit, audit intent, then
required_labels. A request denied by labels (403) now counts against the rate limit. - The compose
adminrole incompose/roles.ymlgainsorg:audit:read. Update your ownROLES_FILEif you want the same.
Added
-
Audit service (
services/audit, new image). Each auditedorganizationormemberrequest is recorded as one event in the subject org's audit log. The intent is written before the request is forwarded, and the outcome is written afterwards in the background. An event stayspendinguntil its outcome arrives. A dropped or failed outcome write leaves the eventpending. -
GET /org/audit-eventsis published by the audit catalog (services/audit/routes.yml) and requires the labelorg:audit:read. -
docs/audit.mddescribes the model and its guarantees. -
Route
audit: true|falseoverrides the default, which is to audit writes. It applies toorganizationandmemberroutes only. -
The identity invite list (
GET /org/invites) setsaudit: true, because it returns live tokens. -
Services can report what changed on
X-Plat5-Audit-Details. The gateway stores it as sent and always strips it from requests and responses. It accepts one ASCII JSON object of at most 4096 bytes and ignores anything else with a warning. -
Gateway config:
AUDIT_ENABLEDAUDIT_URLINTERNAL_AUTH_TOKENis now also sent to audit.
-
New metrics:
- Gateway:
audit_writes_totalandaudit_intent_duration_seconds. - Audit service:
audit_intents_totalandaudit_outcomes_total.
- Gateway:
-
Compose files, CI, and the release workflow now include the audit service.
-
Gateway request log lines (
request completedandrequest failed) now carry the following fields, each present only when known:auth_type:jwt,user_apikey,member_apikey, ormember_sessionkey_prefixuser_id(admitted onuserroutes)organization_idandmember_id(admitted onorganizationandmemberroutes)
key_prefixis set before validation, so 401 and 403 lines carry it. It matcheskey_prefixon identity's key list, or a session'stoken_prefix. The key, token, and JWT are never logged, and the line has no labels or role (#21).
Changed
- Identity now reports changes to audit as
from/toand reports creates by id. It never reports a secret oruser_id. A newauditxhelper does this for organization, member, service-account, invite, and member-key handlers. - Organization update now reads the prior values and applies the change in one store call. Previously it read the organization first and saved it afterwards.
- Docs: wording for labels in the gateway
route_configcomments and innaming-conventions.mdnow matches the implementation (#20). - Docs: updated
routes.md,gateway-contract.md,identity.md,roles.md,self-hosting.md, andtelemetry.mdfor audit.
Fixed
- Route-registry apply now refuses routes that can't be recorded in the audit log.
- The audit service reads the org's prior state under the lock, so concurrent writes see consistent prior values.
Images
All at v0.5.0:
ghcr.io/plat5dev/gateway:v0.5.0ghcr.io/plat5dev/route-registry:v0.5.0ghcr.io/plat5dev/identity:v0.5.0ghcr.io/plat5dev/audit:v0.5.0
Compose images are pinned to v0.5.0 (PLAT5_VERSION).
Full changelog: v0.4.4...v0.5.0
v0.4.4
Roles replace key scopes. This is everything since v0.3.2: v0.4.0 through v0.4.3 were iteration tags with no separate notes.
Breaking
- Key and session scopes are gone. A member key or session now carries its member's role labels, and nothing narrows it below that. To give a machine less access, give it a service account with a smaller role. Restricted (scoped) keys and sessions are revoked on upgrade.
- Roles come from a deployment roles file.
ROLES_FILEon identity points to a YAML file that maps role slugs to labels, withcreator_role,default_roleand an optionalservice_account_default_role. Roles are on or off for the whole deployment: ifROLES_FILEis unset, every member holds every label (["*"]). An invalid file or unknown keys refuse boot. See docs/roles.md and the starter file compose/roles.yml. - Routes declare
required_labels, notrequired_scopes. The permissions field on the wire islabels. It is always a list and never null. - Org writes in the identity catalog are labeled:
org:write,org:delete,org:members:writeandorg:service-accounts:write. A member whose role lacks the label gets 403, with any of its keys or sessions. added_byandcreated_byare removed from identity requests and responses.- Identity migrations are folded into one schema. No scopes compatibility is left.
- Compose requires
PLAT5_VERSIONfrom the env file. The pin lives only in.env.template.
Added
roleon member, invite and service-account writes. A slug that isn't in the file returns 422.GET /organizations/{organization_id}/roleslists the deployment's roles. It's published at the edge asGET /org/rolesso a console can show a role picker.- A write can't take an org's last
creator_roleholder to zero (422).
Fixed
- gateway: a CORS preflight returns 204 and completes (#15).
- identity: the request log records the status the client actually received (#14).
- route-registry: restore validates like apply, lookalike paths conflict, and paths are canonical (#16).
- route-registry: specific 422s for credentials in a url and for an out-of-range port. The missing-url message no longer mentions
plat5.yml(#19). - docs: a route-config url must be exactly
http://host:port(#17).
Images
ghcr.io/plat5dev/gateway:v0.4.4, ghcr.io/plat5dev/route-registry:v0.4.4, ghcr.io/plat5dev/identity:v0.4.4
Full changelog: v0.3.2...v0.4.4
v0.3.2
Breaking: route url must be exactly http://host:port.
Before: url: api:3000
After: url: http://api:3000
Bare host:port, https://, paths, and query strings now return 422 on route apply. Routes already stored keep routing until re-applied.
- Minted API keys and sessions are capped at the parent's scopes; an omitted scope list inherits the parent's. (#2)
- 409 ROUTE_CONFLICT names the service that owns a path. (#3)
- 422 on missing
urlsays to add the service underupstreams:in plat5.yml or seturl. (#15) - Gateway returns 502 instead of panicking on a bad upstream address.