Skip to content

feat(cli): stable device id — login-session record + device header (campus#837) - #30

Merged
nycomp merged 1 commit into
mainfrom
feat/837-cli-device-id
Oct 6, 2026
Merged

nycomp merged 1 commit into
mainfrom
feat/837-cli-device-id

Conversation

@nycomp

@nycomp nycomp commented Oct 6, 2026

Copy link
Copy Markdown
Contributor

CLI half of campus#837 (the CLI device lane from the campus#825 design).

What changes

  • Stable device id per install: config.get_device_id() mints uid-device-* once and persists it in the config file — device = this CLI install on this machine (client-asserted, same trust level as User-Agent, per the accepted design).
  • Login-session record at login: after a device-flow grant, the response's echoed user_id (campus#838) drives a best-effort POST /logins/ with the device id; the session id is stored for logout. An older auth deployment without the logins route logs a dim note and login still succeeds.
  • Logout revokes the record: DELETE /logins/{id}/ via the bearer-owned path (campus#838), alongside the existing RFC 7009 token revocation; best-effort, the local id is always cleared.
  • X-Campus-Device on every API/auth call: CampusClient sets it as a default header (campus_python.tracing.DEVICE_ID_HEADER) on both SDK clients — bearer tokens are shared per (user, client), so the header is the only way server-side spans attribute to this device.
  • Lock bump: campus-api-python → f40f8af (set_default_header + X-Campus-Device forward).

Test plan

  • New tests/unit/test_device_lane.py (9 tests): device id mint/persist/reload, login-session create payload + all failure modes, delete via bearer header + failure modes, device header set on both SDK clients.
  • Full unit 72 → 81 + smoke 9 green; ruff clean.

Ref nyjc-computing/campus#837

…837)

This CLI install now presents a stable device identity per the #825
design (device = this install on this machine, client-asserted):

- config.get_device_id() mints uid-device-* once and persists it in
  the config file; reused across logins.
- After a successful device-flow login, the echoed user_id drives a
  best-effort POST /logins/ creating the login-session record with the
  device id; the session id is stored for logout. An older auth
  deployment without the route must not fail login.
- Logout revokes the stored login-session record via the bearer-owned
  path (campus#838) alongside the token revocation; best-effort, local
  id always cleared.
- CampusClient sets X-Campus-Device (campus_python.tracing.
  DEVICE_ID_HEADER) as a default header on the API and auth clients:
  bearer tokens are shared per (user, client), so the header is the
  only way server-side spans attribute to this device.

Lock bump: campus-api-python -> f40f8af (set_default_header +
X-Campus-Device forward).

Refs nyjc-computing/campus#837
@nycomp
nycomp merged commit 0768706 into main Oct 6, 2026
1 check passed
@nycomp
nycomp deleted the feat/837-cli-device-id branch October 6, 2026 02:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants