feat(web): make each web session its own device
Merged
KA
4h ago+2325+2325+0123456789012345678901234567890123456789-355-355-012345678901234567890123456789
Summary
Each web session is now its own device, so sessions with different --session names run in parallel on one host. Closes #4190.
open --platform web --session a
- device agent-browser-chrome # one per host: a second open gets DEVICE_IN_USE
+ device agent-browser-chrome:session:p_a # tenant: t_<hash12(tenant)>_a
+ lock, claim, conflict check, and agent-browser --session all read this one value
- The request scope alone derives the web session identity from the supplied name and attested tenant; batch and replay carry it unchanged, other readers take the backend key from the device id. Replay records on its held attempt session's device, so the identity does not cross the replay port.
- Names match
[A-Za-z0-9_-], case-insensitively, and must fit the socket path; blank or padded names getweb_session_name_invalidon every route. - No web command binds the host. Claims follow ADR 0035's host-scoped rule; ADR 0037 records the web decisions.
- Scope expansion: tenant-isolated keys, the generic claim rule, the ADR split, the request-scope refactor.
- 85 files, +2,325/−355 at
a9691d07b, in self-contained commits.
agent-device open https://example.com --platform web --session a
agent-device open https://www.iana.org/help/example-domains --platform web --session b
Follow-ups: #4233 (workspace key for implicit web sessions), #4234 (lease platform vs. lease backend).
Validation
- Before, at
dc39b316f: the second open fails withDevice is already in use by session "a". After, at2aa956fc0: both sessions open, each snapshot reports its own URL. - Head
a9691d07b: 11 checks pass, 2 skipped.2aa956fc0differs from this head by one test-only fixture commit. - Live evidence: https://github.com/callstack/agent-device/pull/4191#issuecomment-6668566884
- Door: two-way, nothing migrated. Mixed-version daemons sharing a claims directory may disagree on web device ids.
- Blast radius: session and claim paths for every platform, since the app-device claim checks are now generic. Sessions without
--sessionsharedefault.