docs(auth): document atomic per-type device limit enforcement
Clarify in API/README that device limits are enforced independently per normalized device type with atomic overflow revocation, and add a mapper test covering the RFC3339 UTC timestamp contract. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -215,6 +215,8 @@ Returns every non-revoked, non-expired web session for the authenticated account
|
||||
|
||||
`limits` is sourced from `Auth.DeviceLimits.Desktop` and `Auth.DeviceLimits.Mobile` in service configuration. It is returned with the device list so clients display the effective policy without hard-coded counts. Defaults are 2 desktop web sessions and 1 mobile web session.
|
||||
|
||||
The limits are enforced independently by normalized device type. Session creation and same-type overflow revocation run in one atomic store operation. When a new login exceeds a limit, the newest login remains active and the oldest same-type session is revoked immediately. Device listing also reconciles sessions created before this enforcement was deployed, preserving the current session first.
|
||||
|
||||
Each signed access and refresh token carries an opaque random session ID. Bearer authentication validates that server-side session before accepting the token, so revoked sessions stop working immediately. Device metadata is derived from request headers for display only and is never an authorization signal. A session is reported online when it is current or was active during the previous five minutes.
|
||||
|
||||
`lastSeenAt` is an RFC3339 UTC instant. Clients must render it in the browser's local timezone rather than displaying the UTC wire representation directly.
|
||||
|
||||
+1
-1
@@ -81,7 +81,7 @@ ObjectStorage:
|
||||
ExpiresIn: 900
|
||||
```
|
||||
|
||||
`Auth.DeviceLimits` is the source of truth for the desktop and mobile web-session counts shown in account device management. The effective values are returned by `GET /api/account/devices`.
|
||||
`Auth.DeviceLimits` is the source of truth for desktop and mobile web-session limits. The auth store enforces each device type independently: a new login keeps the newest session and revokes the oldest overflow session atomically. The effective values are returned by `GET /api/account/devices` for display.
|
||||
|
||||
`Agent.Image.InputImageTransport` controls how input/reference images are sent to the image model for edit/image-to-image calls: `file` uploads image bytes with multipart form data, while `url` sends `images: [{"image_url": "..."}]` for gateways that can fetch public URLs directly.
|
||||
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
package logic
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
authmodule "img_infinite_canvas/internal/modules/auth"
|
||||
)
|
||||
|
||||
func TestAccountDeviceMapperReturnsTimezoneNeutralTimestamp(t *testing.T) {
|
||||
lastSeenAt := time.Date(2026, 7, 11, 16, 51, 0, 0, time.FixedZone("CST", 8*60*60))
|
||||
devices := toAPIAccountDevices([]authmodule.Device{{ID: "session-1", LastSeenAt: lastSeenAt}})
|
||||
if len(devices) != 1 || devices[0].LastSeenAt != "2026-07-11T08:51:00Z" {
|
||||
t.Fatalf("expected RFC3339 UTC timestamp, got %#v", devices)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user