Files
yvgude--lean-ctx/docs/contracts/device-overview-v1.md
T
wehub-resource-sync 26382a7ac6
CI / Clippy (push) Failing after 15m13s
CI / Test (ubuntu-latest) (push) Failing after 16m1s
CI / Test (macos-latest) (push) Has been cancelled
CI / Test (windows-latest) (push) Has been cancelled
CI / Build (no embeddings / no ORT) (push) Has been cancelled
CI / Format (push) Has been cancelled
CI / Cookbook (Node) (push) Has been cancelled
CI / Pi Extension (Node) (push) Has been cancelled
CI / Rust SDK (lean-ctx-client) (push) Has been cancelled
CI / Embed SDK (lean-ctx-sdk) (push) Has been cancelled
CI / Python SDK (leanctx) (push) Has been cancelled
CI / Hermes Plugin (Python) (push) Has been cancelled
CI / SDK Conformance Matrix (push) Has been cancelled
CI / Coverage (push) Has been cancelled
CI / cargo-deny (push) Has been cancelled
CI / Adversarial Safety (push) Has been cancelled
CI / Benchmarks (push) Has been cancelled
CI / Output-Quality Gate (eval A/B) (push) Has been cancelled
CI / Documentation (push) Has been cancelled
CI / CI Green (push) Has been cancelled
JetBrains Plugin / Actionlint (push) Has been cancelled
CodeQL / Analyze (actions) (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
CodeQL / Analyze (rust) (push) Has been cancelled
JetBrains Plugin / Validation (push) Has been cancelled
JetBrains Plugin / Build (push) Has been cancelled
JetBrains Plugin / Test (push) Has been cancelled
Security Check / Security Scan (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:35:30 +08:00

2.5 KiB

Device Overview v1 (GL #387)

Per-account list of machines that sync to the Personal Cloud, keyed by the client's hostname. Pure display metadata: a device row never participates in authentication, entitlements, quota, or billing.

Client behavior

Every authenticated sync push attaches one header:

X-Device-Label: <hostname>
  • Source: gethostname() on the pushing machine (cloud_client::device_label).
  • Attached to: POST /api/stats, POST /api/sync/{knowledge,commands,cep,gotchas,buddy,feedback,gain}, PUT /api/sync/index/{project_hash}.
  • An empty or missing header is valid — the push succeeds, it is just not tracked.

Server behavior

devices table, one row per (user_id, device_label):

column meaning
first_seen first push carrying this label
last_seen most recent push
last_surface which sync surface pushed last (stats, knowledge, …)
sync_count total tracked pushes

Tracking is fire-and-forget (devices::track, spawned task): a database failure can never fail or slow the sync request itself. Labels are sanitized server-side (trimmed, control characters rejected, capped at 64 chars); unusable labels are silently skipped.

API

GET /api/account/devices

Auth: account bearer. Returns up to 50 devices, most recently active first.

{
  "devices": [
    {
      "label": "mbp-yves",
      "first_seen": "2026-06-01T09:14:00+00:00",
      "last_seen": "2026-06-10T07:02:11+00:00",
      "last_surface": "knowledge",
      "sync_count": 184
    }
  ]
}

DELETE /api/account/devices/{label}

Auth: account bearer. Forgets one row; idempotent ({"forgotten": false} for an unknown label, still HTTP 200 — the end state is identical). Forgetting a device deletes nothing else and signs nothing out; the row simply reappears on that machine's next sync.

400 bad_label for labels that fail sanitation (empty / control chars).

UI

/account/cloud renders the Devices card below usage: hostname, relative last-sync time, last surface, push count, and a Forget button per row. The card never blocks the dashboard — fetch errors leave it hidden.

Privacy

  • Hostnames stay within the account that pushed them; no cross-account surface, no analytics use.
  • The label is the only machine identifier collected — no MACs, IPs, serials, or fingerprints.
  • DELETE /api/account/devices/{label} is the user-facing forget control; account deletion cascades the whole table (ON DELETE CASCADE).