next: device log-token refresh for synced collections - #618
Conversation
POST /v1/next/collections/:id/log-token {device_id, challenge, sig}:
connector auth plus a device proof in its own domain
(mdbase/v1/collection-log-token over challenge, connector, device,
collection) with a fresh single-use challenge. In one transaction under
share locks: current connector/account/device with exact keys, a
current synced collection (private or cloud copy, not left), an
acknowledged (appended-batch) enrolment of exactly this device tuple
for this account, and no device-revoke; then mints a role-0 token for
that device and collection (15 min). Answers only {token, expires_at}.
A device credential, not membership, approval or admission.
Review (security-2) on 639cb4e: fold the account's membership ops in outbox order (a member-set counts once its batch is appended; a member-remove counts even while pending) and refuse unless it is a current member; require runtime = 'next'. Tests: removed member refused until re-added and acknowledged; shadow runtime refused.
Latest effective membership op (outbox order, then op ordinal; member-remove even pending, member-set only appended) projected with LIMIT 1 instead of loading every matching batch; statement_timeout 5s fails closed as busy. Regression test for intra-batch ordering, other accounts' ops and many batches.
|
Control touched-path SOURCE OWNER ACK at exact 5bb4465. Reviewed the route, app wiring, PostgreSQL regression source, and the 5a-to-5bb bounded-query delta. Current connector/account/device whole-tuple locks, separate proof domain and single-use challenge, NEXT runtime/current collection, acknowledged exact enrollment, latest effective account membership, and revocation guards remain required through mint. Latest membership is one projected row in outbox/intra-operation order, with pending removals effective and pending sets excluded; SQL waits/statements are bounded. Private refresh remains credential-only: no service actor, enrollment, key delivery or Ready assertion. This is independent source review, not independent PostgreSQL execution, actual log ACL or runtime acceptance; security and normal CI qualification remain separate. |
|
security: no blocking findings at 5bb4465 (scoped ordinary device log-token refresh). Reviewed the actual device-proof/single-use challenge, locked current full identity, acknowledged exact enrollment, current effective membership, pending revoke/removal refusal and next-runtime checks. The changed SQL returns only the latest effective account membership operation, preserving outbox/intra-batch order and pending-readd semantics, with lock/statement bounds. This verdict is source review; author PG/mutation results and control SOURCEOWNERACK are separate, not my independent PG execution. Role-0 exact-collection 15-minute credential only: no enrollment, epoch key, admission/Ready, private-device join expansion or portable CP freshness authority. Current log ACL remains authoritative on every RPC; native custody/refresh adapter and live acceptance remain separate. |
This is control's approved small follow-up: a device log-token refresh for synced daemon collections (control 20:47). Control owns these paths (owner review requested); security-2 review requested.
POST /v1/next/collections/:id/log-token {device_id, challenge, sig}H("mdbase/v1/collection-log-token", cbor[challenge, connector, device, collection]), using a fresh, single-use challenge.lock_timeout; contention answers 503busy):device-revokefor the device, appended or pending.{token, expires_at}. The token is role 0, carries the device, its sign key and claim 5 = this collection, and lasts 15 min. No keys, no log URL, no control-plane credential.Tests (Postgres):
Results:
src/features/next148 passed (Postgres 16, serial); serverpnpm test779 passed; architecture and changelog checks pass.Merge note: the
app.tshunk overlaps #615'snextLogchange (same variable); it's a trivial resolution.