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:
2026-07-11 01:02:25 +08:00
parent 869e2bb75b
commit 114198f1d9
3 changed files with 19 additions and 1 deletions
+2
View File
@@ -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
View File
@@ -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.
+16
View File
@@ -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)
}
}