Skip to content

Imported (-synced-from-) buckets are writable and unmarked; local writes to them are silently lost #694

Description

@ErikBjare

Buckets created by a sync pull are ordinary, fully writable local buckets. Nothing marks them as derived and nothing refuses writes to them.

Verified — searching the server and datastore for any notion of synced/read-only buckets returns nothing:

$ git grep -nE "synced.from|read_only|readonly|is_synced" origin/master -- aw-server/src aw-datastore/src
$ 

The only place -synced-from- is understood at all is inside aw-sync itself (is_synced_bucket, added by #648 to stop re-export laundering). The server that owns the data has no concept of it.

Why that is a problem

An imported bucket is a copy of another device's data. The local device is not its owner and cannot publish changes to it — sync_datastores explicitly skips -synced-from- buckets when pushing. So any local write to one is guaranteed to be either lost or permanently divergent:

  • A watcher misconfigured to a peer's bucket ID, a POST /api/0/buckets/<id>/heartbeat, a manual event insert from the web UI or a script — all succeed silently.
  • The written events never propagate anywhere, because the bucket is never pushed.
  • They may or may not survive the next pull, depending on where the resume cursor lands relative to the inserted timestamps. Nothing detects the divergence, and nothing can repair it, because there is no "rebuild this bucket from source" operation.
  • Deleting an imported bucket to recover is currently the only remedy, and it re-imports the whole history.

On my own instance this is live: nine imported buckets holding roughly 2.9M foreign events, all writable, none marked.

Fix

Make imported buckets explicitly derived:

  1. Mark them. Record provenance in bucket data at import — $aw.sync.origin_device_id and a derived: true / read_only: true flag — rather than relying on the ID substring, which is what aw-sync: move sync provenance out of the bucket ID into trustworthy bucket metadata #649 was about.
  2. Refuse writes to a bucket marked derived: 409 Conflict on POST events / heartbeat / PUT, with a message saying which device owns it. A local write to a mirror is always a mistake; failing loudly is strictly better than accepting it.
  3. Make them rebuildable. A drop-and-reimport path, so divergence and the truncation in aw-sync: duplicate folders for one device_id silently truncate history on pull #683 both have a remedy that is not "delete the bucket and hope".
  4. Consider surfacing the distinction in aw-webui's Raw Data page, which already groups by device (Buckets.vue renders ID: undefined once data.device_id is populated; device-ID check is dead code aw-webui#982).

(1) and (2) are small and independent of the larger question of whether the import should exist at all — a derived bucket should be read-only under any design.

Credit: found in a design review of aw-sync; the absence of any guard is verified by the grep above.

Related: #649, #648, #683, ActivityWatch/aw-webui#982.

cc @TimeToBuildBob

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions