Commit Graph
238 Commits
Author SHA1 Message Date
osobh 2b11d1c888 Merge pull request 'dashboard-v2: node pill column on storage tabs' (#98) from dashboard-v2-frontend-node-column into main
Build with clawstor cache / Cargo build (clawstor-cached) (push) Failing after 2s
2026-07-14 23:44:11 +00:00
Omar Sobh b672037e42 dashboard-v2 frontend: node column + clickable pills on storage tabs
Build with clawstor cache / Cargo build (clawstor-cached) (pull_request) Failing after 3s
All storage rows now carry a 'node' field from the aggregator.
Adds a small green-pill component that renders the source node
name; click drills into that node's detail page.

Also fixes the TS interfaces to match the new backend shape
(node field added to Blob/Tag/Ref/Snapshot/RefTracking types).
2026-07-14 16:44:06 -07:00
osobh bbd64973ce Merge pull request 'dashboard-v2: storage RPC + aggregated endpoints' (#97) from dashboard-v2-storage-rpc into main
Build with clawstor cache / Cargo build (clawstor-cached) (push) Successful in 18s
2026-07-14 23:39:50 +00:00
Omar Sobh 1211f0d891 dashboard-v2: DashboardStorage RPC + aggregated /storage/* endpoints
Build with clawstor cache / Cargo build (clawstor-cached) (pull_request) Successful in 18s
Storage tabs 404'd because the aggregator only had /fleet + /node/:name
after the pivot. Adds:

* New RPC method DashboardStorage = 0x1d — one round trip returns
  tags (full), snapshots (full), ref-tracking (full), blobs
  (first 200 by id), refs (first 200 by fp) for the responding
  daemon.
* Client wrapper call_dashboard_storage.
* Aggregator fans out to every peer, tags each row with the
  originating node, sorts + returns:
    GET /api/v2/storage/blobs
    GET /api/v2/storage/tags
    GET /api/v2/storage/refs
    GET /api/v2/storage/snapshots
    GET /api/v2/storage/ref-tracking

QuicClient promoted to Arc<QuicClient> inside V2State so the
per-peer JoinSet can hand it to spawned tasks without recreating
the endpoint.
2026-07-14 16:39:45 -07:00
osobh 20d1f765f7 Merge pull request 'dashboard-v2 fix: absolute /clawstor/ base' (#96) from dashboard-v2-absolute-base into main
Build with clawstor cache / Cargo build (clawstor-cached) (push) Failing after 3s
2026-07-14 23:33:28 +00:00
Omar Sobh 0231b2bb65 dashboard-v2 fix: vite base = /clawstor/ (absolute)
Build with clawstor cache / Cargo build (clawstor-cached) (pull_request) Failing after 3s
Prior ./ (fully-relative) fix broke when browser hit /clawstor
without trailing slash — ./assets/… resolved to /assets/… at
tailnet root, 404. Absolute /clawstor/ is deploy-path-coupled
but no-slash-safe. Verified: no-slash HTML 200, CSS 200,
JS 200, /clawstor/api/v2/fleet 200.
2026-07-14 16:33:23 -07:00
osobh bcdb4eeb50 Merge pull request 'dashboard-v2 hotfix: relative asset base' (#95) from dashboard-v2-relative-base into main
Build with clawstor cache / Cargo build (clawstor-cached) (push) Failing after 3s
2026-07-14 23:28:26 +00:00
Omar Sobh 9f28ad5338 dashboard-v2 hotfix: relative asset base so /clawstor mount works
Build with clawstor cache / Cargo build (clawstor-cached) (pull_request) Failing after 2s
Browser hit /clawstor/ then requested /v2/assets/index-XXX.css
(absolute path baked in by vite base '/v2/') which 404'd because
Tailscale Serve only mounted /clawstor and /clawstor/api. Switch
vite base to './' — assets resolve relative to whatever URL the
SPA loaded from. Works for local (:7700/v2/) + Tailscale
(/clawstor) with no config coupling.
2026-07-14 16:28:21 -07:00
osobh cc72f063ea Merge pull request 'dashboard-v2 PR 3: fleet aggregator via DashboardStatus RPC' (#94) from dashboard-v2-aggregator into main
Build with clawstor cache / Cargo build (clawstor-cached) (push) Successful in 15s
2026-07-14 23:19:32 +00:00
Omar Sobh a2114b918d dashboard-v2 PR 3: fleet aggregator via DashboardStatus RPC
Build with clawstor cache / Cargo build (clawstor-cached) (pull_request) Successful in 15s
Pivot from per-node dashboard to single-pane-of-glass. The
aggregator (typically the operator's laptop) holds a fleet-CA
leaf cert + the peer list; each dashboard request fans out to
every peer over the existing QUIC/mTLS cluster port and issues
the new DashboardStatus RPC. Peers don't need to run any HTTP
server of their own.

Backend:
* New RPC method DashboardStatus = 0x1c
* Server handler reads BlobStore / TagStore / RefStore /
  SnapshotStore / RefTracking counts + on-disk bytes + rustc
  release. Cheap: 5 filesystem walks per request.
* Client wrapper call_dashboard_status
* serve_v2 rewritten as aggregator: V2State holds a QuicClient +
  peer list from `[[cluster.peers]]`. Endpoints:
    GET /api/v2/fleet             fan-out to every peer, parallel
    GET /api/v2/node/:name/status one peer, on-demand
  Failed peers surface as { online: false, error: "..." } cards
  instead of dropping.

serve.rs graceful degrade: v2 aggregator routes only mount when
[cluster.tls] is set. Static SPA still serves at /v2/* even
without an aggregator config so operators see the SPA's built-in
"config missing" error.

Deployment model (this session):
* Aggregator runs on quantum (Mac) with a signed leaf.
* Fleet daemons run cluster-only — no HTTP dashboard anywhere
  on tank/architect/morpheus. The clawstor-dashboard.service
  systemd units on the fleet are being retired.

Frontend rework to consume /api/v2/fleet ships in the next PR.
2026-07-14 16:19:27 -07:00
osobh 2c23e784bc Merge pull request 'dashboard-v2 PR 2: frontend SPA + serve integration' (#93) from dashboard-v2-frontend into main
Build with clawstor cache / Cargo build (clawstor-cached) (push) Successful in 16s
2026-07-14 22:59:52 +00:00
Omar Sobh f33468b7c2 dashboard-v2 PR 2: frontend SPA + serve integration
Build with clawstor cache / Cargo build (clawstor-cached) (pull_request) Successful in 16s
React 19 + Vite + Tailwind + wouter (tiny router, no external
state library). Consumes the /api/v2/* endpoints shipped in PR 1.
Serves under /v2/* so the legacy dashboard at / stays live.

Pages:
* CommandCenter (/)      — fleet strip + this-node stat tiles
* NodeDetail (/nodes/:name) — per-node deep dive
* StorageBrowser (/storage/{blobs,tags,refs,snapshots}) — tables
  with prefix filter
* RefTrackingPage (/refs/tracking) — grouped by repo

Backend changes:
* claw-store serve grows --v2-static-dir <path>
* build_app split into build_app_with_v2 for the extra static
  mount
* /v2/* falls through to index.html so wouter client routing works

New systemd unit: clawstor-dashboard.service. Points at both
static dirs; installs on any node.

dashboard/ (legacy) untouched. dashboard-v2/ built to
target/dashboard-v2/dist for deploy.

Deploy sequence per node:
1. cp target/release/claw-store  ~/clawstor-deploy/
2. rsync dashboard-v2/dist/      ~/clawstor-deploy/dashboard-v2/
3. cp deploy/systemd/clawstor-dashboard.service ~/.config/systemd/user/
4. systemctl --user daemon-reload && enable --now clawstor-dashboard.service

Cross-node fan-out for /api/v2/node/:name/status is PR 3.
Action POSTs (scrub/gc/snapshot/pin) are PR 4.
2026-07-14 15:59:47 -07:00
osobh 284c445935 Merge pull request 'dashboard-v2 PR 1: design doc + backend read-only endpoints' (#92) from dashboard-v2-backend into main
Build with clawstor cache / Cargo build (clawstor-cached) (push) Successful in 16s
2026-07-14 22:52:53 +00:00
Omar Sobh b431475af7 dashboard-v2 (PR 1): design doc + backend read-only endpoints
Build with clawstor cache / Cargo build (clawstor-cached) (pull_request) Successful in 17s
Kicks off the single-pane-of-glass command-center rewrite. Legacy
/api/* handlers untouched — v2 is additive so cutover is safe.

Doc: docs/dashboard-v2.md — design goals, endpoint spec, cutover
plan.

Backend: new serve_v2 module wired into serve.rs. Endpoints:

  GET /api/v2/node/local/status
  GET /api/v2/node/:name/status         (fan-out: not-yet-impl)
  GET /api/v2/storage/blobs?limit&offset
  GET /api/v2/storage/tags?prefix
  GET /api/v2/storage/refs?limit&offset
  GET /api/v2/storage/snapshots
  GET /api/v2/storage/ref-tracking?repo

V2State opens BlobStore / TagStore / RefStore / SnapshotStore /
RefTracking under the daemon's blob_store_root + the conventional
subdirs (tags-db, refs-db). All handlers are single-node reads;
cross-node fan-out lands in PR 3.

+6 tests: status w/ seeded blob+snapshot, cross-node returns 501,
blobs pagination, tags prefix filter, snapshots list, ref-tracking
repo filter.

395 tests pass. serve.rs merges v2 routes onto the axum router
with shared CORS. Single-shot deploy on tank + architect will
expose /api/v2/* alongside the existing /api/*.

PR 2 = frontend rewrite consuming these endpoints.
PR 3 = fleet fan-out (cross-node aggregation via QUIC RPC).
PR 4 = action endpoints (POST scrub/gc/snapshot/pin).
PR 5 = cutover (deprecate legacy /api/*).
2026-07-14 15:52:47 -07:00
osobh 367643721a Merge pull request 'Polish: comprehensive docs overhaul' (#91) from polish-docs-overhaul into main
Build with clawstor cache / Cargo build (clawstor-cached) (push) Failing after 3s
2026-07-14 22:16:55 +00:00
Omar Sobh 24ff3ec130 Polish: comprehensive docs overhaul
Build with clawstor cache / Cargo build (clawstor-cached) (pull_request) Successful in 15s
README.md was still describing the pre-distributed ZFS-only
architecture (activate/deactivate cargo target dirs, SSH-based
tank→architect sync). Nothing about the distributed content-
addressed store, chunk-level dedup, QUIC/mTLS, snapshots, tags,
refs, FUSE mount, ref-tracking, Tailscale identity, or the
systemd timer set — i.e. everything shipped in Phases 1-8.

Full rewrite:
* What you get: 6 feature sections spanning storage/distribution,
  fingerprint-keyed cargo cache, human primitives, operations,
  roaming, reliability.
* One-paragraph architecture + link to ARCHITECTURE-v2.md.
* Fleet layout table (tank/architect/morpheus current state).
* Install: prereqs (Linux + macOS macFUSE), build, first-time CA
  bootstrap, config template with tailnet bind, systemd install
  recipe.
* Daily usage: claw-cargo build (env-driven for CI), pins,
  snapshots, integrity+repair, fleet-status.sh, FUSE mount layout.
* CLI reference table (28 commands across claw-store + claw-cargo
  + claw-fuse).
* Prometheus metrics list.
* Ongoing operations: 4 timers table with sequencing rationale.
* Testing: 389 tests, known pre-existing macOS failure.
* Design-docs pointer list.
* Contributing + license note.

Also:
* ARCHITECTURE-v2.md phase plan table: replaced weeks-estimates
  with ship-state (all ✅ shipped, dated).
* docs/runner-integration.md: added ref-tracking env-var section
  so CI wiring populates the nightly sweep.
* dashboard/README.md: replaced the Vite template boilerplate
  with actual dashboard context + note that it predates the
  current architecture.
2026-07-14 15:16:50 -07:00
osobh 3c97b0354b Merge pull request 'Polish: fleet-status.sh' (#90) from polish-fleet-status into main
Build with clawstor cache / Cargo build (clawstor-cached) (push) Successful in 15s
2026-07-14 21:34:58 +00:00
Omar Sobh a45fb1a5ce Polish: fleet-status.sh — one-shot health snapshot
Build with clawstor cache / Cargo build (clawstor-cached) (pull_request) Successful in 15s
deploy/scripts/fleet-status.sh iterates NODES (default 'tank
architect morpheus') and prints per-host: daemon state, FUSE
mount + layer listing, blob-store byte count, and each timer's
next-fire + last-result.

Fits in half a screen per node; useful as a smoke check before
+ after any fleet-wide change. Read-only over ssh — safe to
run from any workstation with keys.
2026-07-14 14:34:54 -07:00
osobh 9ea3b14025 Merge pull request 'Polish: minimal clawstor-fuse.service' (#89) from polish-fuse-unit-minimal into main
Build with clawstor cache / Cargo build (clawstor-cached) (push) Failing after 2s
2026-07-14 21:31:46 +00:00
Omar Sobh c46206c6dd Polish: minimal clawstor-fuse.service (fixes morpheus mount EPERM)
Build with clawstor cache / Cargo build (clawstor-cached) (pull_request) Failing after 3s
Live smoke on morpheus with the previous unit failed:
  Error: mounting FUSE at /home/osobh/clawstor-mount
  Caused by: Operation not permitted (os error 1)

But 'systemd-run --user' with the exact same binary worked, and
the manual invocation worked. The delta was our ExecStartPre
chain (mkdir + fusermount3 -u -z) — on some Ubuntu 24.04 builds
that combination poisons the subsequent mount syscall even with
the -z lazy flag + ignored exit code.

Fix: drop the pre-mkdir + pre-unmount. Operator creates the
mount dir manually once (documented in README). Restart handling
falls to systemd's Restart=on-failure + ExecStop unmount.

Verified live on morpheus with the minimal unit — active +
mount visible in <3s.
2026-07-14 14:31:41 -07:00
osobh 88885b28cc Merge pull request 'Polish: claw-fuse on macOS + deploy/macos docs' (#88) from polish-fuse-macos into main
Build with clawstor cache / Cargo build (clawstor-cached) (push) Successful in 15s
2026-07-14 20:16:23 +00:00
Omar Sobh 9d7e62bcee Polish: enable claw-fuse on macOS via macFUSE + deploy/macos docs
Build with clawstor cache / Cargo build (clawstor-cached) (pull_request) Successful in 15s
Cargo.toml: fuser dep now target-gated to Linux + macOS. macOS
build requires macFUSE (brew install --cask macfuse) + pkg-config
before 'cargo build --features fuse' works.

deploy/macos/README.md — one-time prereqs, build steps, mount /
umount, known differences (no AllowOther, unmount is 'umount'
not fusermount3 -u).

deploy/macos/claw-fuse.plist — launchd agent template
(RunAtLoad + KeepAlive) so ghost / macbook / smith can run the
mount the same way tank/architect do under systemd.

Default 'cargo build' (no --features fuse) still works on macOS
with no macFUSE installed — feature gate keeps the dep opt-in.
2026-07-14 13:16:17 -07:00
osobh bf0f3be742 Merge pull request 'Polish: extract src/lib.rs' (#87) from polish-lib-split into main
Build with clawstor cache / Cargo build (clawstor-cached) (push) Failing after 3s
2026-07-14 20:14:19 +00:00
Omar Sobh 0e5e5982d8 Polish: extract src/lib.rs so bins reuse a proper library crate
Build with clawstor cache / Cargo build (clawstor-cached) (pull_request) Failing after 2s
Historically every bin (claw-store, claw-cargo, claw-fuse)
re-declared the same 13-line 'mod ...' block at its own root.
Working but fragile — a new bin (or a new module) needed edits
in N+1 places and stayed one edit-slip away from silently
dropping something.

Now: src/lib.rs owns the shared module tree. Cargo.toml gets a
[lib] entry so cargo picks it up. claw_fuse.rs migrated as the
proof-of-concept — 13 mod lines → 4 use lines.

claw-store + claw-cargo bins still use their internal 'mod ...'
blocks and 'crate::...' paths — migrating them is mechanical
but noisy; deferred to a follow-on so this PR stays reviewable.
Both bins + tests continue to build unchanged.

387 tests pass.
2026-07-14 13:14:14 -07:00
osobh 71813d0fb8 Merge pull request 'Polish: daily snapshot rotation' (#86) from polish-snapshot-rotate into main
Build with clawstor cache / Cargo build (clawstor-cached) (push) Successful in 10s
2026-07-14 20:12:20 +00:00
Omar Sobh 7a3c04bed7 Polish: daily snapshot rotation script + systemd timer
Build with clawstor cache / Cargo build (clawstor-cached) (pull_request) Successful in 10s
deploy/scripts/rotate-snapshots.sh creates daily-YYYY-MM-DD
snapshot + prunes daily-* older than RETAIN_DAYS. Only touches
its own daily-* namespace so hand-created snapshots (release
anchors etc) never get reaped.

02:00 timer runs ahead of the 03:15 ref-sweep + 03:30 gc so
tonight's fresh snapshot pins protect its blobs from eviction.

DRY_RUN=1 for preview.
2026-07-14 13:12:15 -07:00
osobh f506b446d7 Merge pull request 'Polish: cluster-ref-sweep --apply' (#85) from polish-ref-sweep-apply into main
Build with clawstor cache / Cargo build (clawstor-cached) (push) Failing after 3s
2026-07-14 20:11:09 +00:00
Omar Sobh 1c5d3c08bd Polish: cluster-ref-sweep --apply forgets stale records
Build with clawstor cache / Cargo build (clawstor-cached) (pull_request) Failing after 3s
Default remains dry-run. --apply iterates the stale set and calls
RefTracking::forget per fp. Blob eviction stays a separate step
(next cluster-gc). Errors are surfaced per-fp, batch continues.
2026-07-14 13:11:04 -07:00
osobh b0b283d897 Merge pull request 'Polish: tests for Phase 6c fixes + RefStore::list' (#84) from polish-store-tests into main
Build with clawstor cache / Cargo build (clawstor-cached) (push) Successful in 11s
2026-07-14 20:09:10 +00:00
Omar Sobh 5dd5d2d00f Polish: tests for Phase 6c TagStore fixes + RefStore::list
Build with clawstor cache / Cargo build (clawstor-cached) (pull_request) Successful in 11s
Retroactive coverage for the layer-split fixes shipped live in
Phase 6c hotfix cycle:
* TagStore::list unions legacy+stamped, dedups by key
* TagStore::get falls through to stamped when legacy absent
* TagStore::delete unlinks both layers + TTL sidecar
* TagStore::contains reports stamped-only pin
* RefStore::list empty + sorted-pairs (stamped wins on collision)

+6 tests. 387 pass.
2026-07-14 13:09:06 -07:00
osobh 7adac2af38 Merge pull request 'Polish: cargo fix' (#83) from polish-cargo-fix into main
Build with clawstor cache / Cargo build (clawstor-cached) (push) Successful in 11s
2026-07-14 20:06:54 +00:00
Omar Sobh 8a502be65c Polish: cargo fix pass (auto-remove unused imports)
Build with clawstor cache / Cargo build (clawstor-cached) (pull_request) Failing after 3s
2026-07-14 13:06:49 -07:00
osobh 88bb5a197f Merge pull request 'Phase 6e hotfix: refs path' (#82) from phase-6e-fix-refs-path into main
Build with clawstor cache / Cargo build (clawstor-cached) (push) Successful in 12s
2026-07-14 19:44:46 +00:00
Omar Sobh 6d16d30eee Phase 6e hotfix: RefStore lives at <data>/refs-db/ not <data>/
Build with clawstor cache / Cargo build (clawstor-cached) (pull_request) Successful in 11s
Daemon opens refs under <blob_root>/refs-db/ (see services.rs).
FUSE was opening at <data>/ and finding nothing. Match the
daemon's nested convention.
2026-07-14 12:44:41 -07:00
osobh 168309f6ee Merge pull request 'Phase 7i: nightly cluster-ref-sweep timer' (#81) from phase-7i-ref-sweep-timer into main
Build with clawstor cache / Cargo build (clawstor-cached) (push) Successful in 11s
2026-07-14 19:42:18 +00:00
Omar Sobh 4c4b587193 Phase 7i: nightly cluster-ref-sweep systemd timer
Build with clawstor cache / Cargo build (clawstor-cached) (pull_request) Failing after 3s
03:15 local, Persistent=true. Runs ahead of the 03:30 GC so
operators see the stale-fingerprint report before eviction lands.

Environment= drives the Gitea URL; token expected in a drop-in
(clawstor-ref-sweep.service.d/token.conf) so it doesn't sit in
the unit file. README + install recipe updated.
2026-07-14 12:42:02 -07:00
osobh 1ffb08380d Merge pull request 'Phase 7h: nightly cluster-gc systemd timer' (#80) from phase-7h-gc-timer into main
Build with clawstor cache / Cargo build (clawstor-cached) (push) Failing after 3s
2026-07-14 19:40:37 +00:00
Omar Sobh 74caaed0d1 Phase 7h: nightly cluster-gc systemd timer
Build with clawstor cache / Cargo build (clawstor-cached) (pull_request) Failing after 3s
03:30 local, Persistent=true. Ordered before the Sun 04:00
scrub so scrub reads a fresh post-GC layout.

Default ExecStart is orphan-chunk sweep only (safe on any
node). Fleets that want LRU size-cap eviction add a drop-in:
  systemctl --user edit clawstor-gc.service
  [Service]
  ExecStart=
  ExecStart=%h/clawstor-deploy/claw-store --config ... cluster-gc --evict-to-gb 200

README updated.
2026-07-14 12:40:20 -07:00
osobh d914fd860d Merge pull request 'Phase 7g: weekly cluster-scrub systemd timer' (#79) from phase-7g-scrub-timer into main
Build with clawstor cache / Cargo build (clawstor-cached) (push) Successful in 10s
2026-07-14 19:39:14 +00:00
Omar Sobh 3000021ac3 Phase 7g: weekly cluster-scrub systemd timer
Build with clawstor cache / Cargo build (clawstor-cached) (pull_request) Successful in 11s
Deploy artifact. Sunday 04:00 local, Persistent=true so a
box that missed the wall-clock moment fires on next boot.

Timer + Service pair — both go under
~/.config/systemd/user/. The service is Type=oneshot; timer
drives it. Non-zero exit from cluster-scrub (integrity issue)
surfaces via systemd failed state; journalctl has the details.

README updated with install recipe.
2026-07-14 12:38:59 -07:00
osobh 7dbf2e9090 Merge pull request 'Phase 6e: expose refs as FUSE files' (#78) from phase-6e-fuse-refs into main
Build with clawstor cache / Cargo build (clawstor-cached) (push) Failing after 2s
2026-07-14 19:37:38 +00:00
Omar Sobh 7f46e2566b Phase 6e: expose refs as FUSE files
Build with clawstor cache / Cargo build (clawstor-cached) (pull_request) Failing after 2s
<mount>/refs/<fp-hex>   file, content = blob that fp points at

Adds RefStore::list() unioning legacy refs/ and stamped refs-v2/.
FUSE wires the new dir. On lookup, tries get_stamped first then
legacy — matches the resolution order used by claw-cargo build.

Ref files piggy-back the blob inode (same content), so a hex
readable via /blobs/<hex> and /refs/<fp> shares the inode. cheap.
2026-07-14 12:37:20 -07:00
osobh e8e3b05b42 Merge pull request 'Phase 6c fix: hide companion tags from FUSE' (#77) from phase-6c-fuse-hide-companion-tags into main
Build with clawstor cache / Cargo build (clawstor-cached) (push) Successful in 11s
2026-07-14 19:32:36 +00:00
Omar Sobh cf8acadbc1 Phase 6c fix: hide companion tags from FUSE
Build with clawstor cache / Cargo build (clawstor-cached) (pull_request) Successful in 10s
Companion tags store a fingerprint, not a blob-id. Filter them
out of /tags so ls does not show unreadable entries.
2026-07-14 12:32:18 -07:00
osobh bf69938e57 Merge pull request 'Phase 6d hotfix: systemd ExecStart needs %h' (#76) from phase-6d-fix-execstart into main
Build with clawstor cache / Cargo build (clawstor-cached) (push) Successful in 11s
2026-07-14 19:30:57 +00:00
Omar Sobh 6071fdb7d9 Phase 6d hotfix: systemd ExecStart needs %h not ${VAR}
Build with clawstor cache / Cargo build (clawstor-cached) (pull_request) Successful in 12s
status=203/EXEC means the exec path didn't resolve. systemd
expands %h (home) at parse time but does NOT expand ${VAR}
in the ExecStart executable position — only in ExecStart args.
Rewrote to use %h/clawstor-deploy/claw-fuse directly.
2026-07-14 12:30:52 -07:00
osobh ae164863cc Merge pull request 'Phase 6d: systemd user unit for persistent FUSE mount' (#75) from phase-6d-fuse-systemd into main
Build with clawstor cache / Cargo build (clawstor-cached) (push) Successful in 13s
2026-07-14 19:29:37 +00:00
Omar Sobh b1fc463655 Phase 6d: systemd user unit for persistent FUSE mount
Build with clawstor cache / Cargo build (clawstor-cached) (pull_request) Successful in 15s
Deploy artifact — not built into the binary tree. `deploy/systemd/
clawstor-fuse.service` + README with the install recipe.

Unit shape:
* Type=simple, blocks on the FUSE binary (unmount = SIGTERM).
* ExecStartPre = mkdir -p mount, best-effort lazy unmount of any
  stale prior mount (guards against a hard SIGKILL leaving the
  kernel with a dangling mount).
* Restart=on-failure, RestartSec=5 — recover from transient IO
  errors without operator involvement.
* Environment= for CLAWSTOR_FUSE_BIN / DATA / MOUNT so a
  `systemctl edit` drop-in retargets without editing the unit file.

Dependency chain: clawstor-fuse.service After= + Wants=
clawstor-cluster.service. FUSE reads only the on-disk state so
this is technically not needed for correctness — but keeps the
mount from spinning up on a node where the daemon is broken.
2026-07-14 12:29:32 -07:00
osobh cfd7de8125 Merge pull request 'Phase 6c fix: TagStore delete/contains also see stamped' (#74) from phase-6c-fix-delete-contains into main
Build with clawstor cache / Cargo build (clawstor-cached) (push) Successful in 10s
2026-07-14 19:27:41 +00:00
Omar Sobh 2c51f0917e Phase 6c fix: TagStore delete()/contains() also see stamped tags
Build with clawstor cache / Cargo build (clawstor-cached) (pull_request) Failing after 3s
Companion to the previous list/get fix. Same layer-split problem:
* delete() only unlinked tags/, leaving stamped tags-v2/ behind.
  Result: `unpin` prints \"no such tag\" for pins created via
  Phase 3c+ RPC even though the tag is right there on disk.
* contains() only checked tags/. Same false-negative.

Fix: both APIs now inspect BOTH layers. delete() unlinks
whichever files exist (either or both) AND removes the TTL
expiry sidecar if present. Returns true when anything was
actually removed.

Legacy behavior preserved: tests unchanged, 381 tests pass.
2026-07-14 12:27:36 -07:00