|
| 1 | +# Iteration 012 - bbolt Low-Risk Bucket Coverage |
| 2 | + |
| 3 | +- **Date:** 2026-06-13 |
| 4 | +- **Phase:** C1 storage foundation |
| 5 | +- **Repos:** `lattice-server`, `lattice` |
| 6 | +- **Status:** Verified low-risk bucket record APIs / default store not switched |
| 7 | + |
| 8 | +## Goal |
| 9 | + |
| 10 | +Extend the bbolt record-level foundation beyond nodes/KV/audit while avoiding |
| 11 | +secret-bearing buckets. This slice adds record-level APIs for static objects, |
| 12 | +Worker scripts, plugin lifecycle records, and approvals. |
| 13 | + |
| 14 | +## Scope |
| 15 | + |
| 16 | +- Add record-level static object writes and bucket reads: |
| 17 | + - `PutStatic` |
| 18 | + - `Static` |
| 19 | +- Add record-level Worker writes and reads: |
| 20 | + - `UpsertWorker` |
| 21 | + - `Workers` |
| 22 | +- Add record-level plugin lifecycle writes and reads: |
| 23 | + - `UpsertPluginInstallation` |
| 24 | + - `PluginInstallation` |
| 25 | + - `PluginInstallations` |
| 26 | + - `SetPluginStatus` |
| 27 | +- Add record-level approval writes and reads: |
| 28 | + - `UpsertApproval` |
| 29 | + - `Approval` |
| 30 | + - `Approvals` |
| 31 | +- Preserve current JSON-store behavior: |
| 32 | + - static objects sorted by path |
| 33 | + - Workers sorted by name |
| 34 | + - plugin lifecycle sorted by id |
| 35 | + - approvals sorted newest first |
| 36 | + - plugin status transition validation reused |
| 37 | +- Keep writes local to their bbolt buckets; record-level writes must not reset |
| 38 | + unrelated imported buckets. |
| 39 | + |
| 40 | +## Non-Goals |
| 41 | + |
| 42 | +- Do not switch `cmd/lattice-server` to bbolt. |
| 43 | +- Do not add `-data-engine=bolt` yet. |
| 44 | +- Do not add record-level writes for DDNS, notification channels, OIDC providers, |
| 45 | + TOTP challenges, users, tokens, or sessions yet. |
| 46 | +- Do not migrate or anchor the audit WAL into bbolt yet. |
| 47 | + |
| 48 | +## Security Notes |
| 49 | + |
| 50 | +- This slice still avoids reversible secret fields. Static content and Worker |
| 51 | + source can contain operator-provided sensitive text, but the current JSON store |
| 52 | + already persists those fields as ordinary state; this change does not widen |
| 53 | + their exposure or route runtime traffic to bbolt. |
| 54 | +- Secret-bearing per-record methods must be added with field-specific encryption |
| 55 | + tests before they are considered ready. |
| 56 | +- Plugin lifecycle reads clone capability slices so callers cannot mutate a |
| 57 | + returned slice and accidentally affect future in-memory state assumptions. |
| 58 | + |
| 59 | +## Verification |
| 60 | + |
| 61 | +Targeted tests added in `lattice-server/internal/store/bolt_state_test.go`: |
| 62 | + |
| 63 | +- static, Worker, plugin lifecycle, and approval record-level writes work after |
| 64 | + a full import. |
| 65 | +- plugin lifecycle transition validation is preserved. |
| 66 | +- plugin capability slices are cloned on read. |
| 67 | +- records keep JSON-store ordering semantics. |
| 68 | +- record-level writes do not reset unrelated buckets. |
| 69 | +- records persist across close/reopen. |
| 70 | + |
| 71 | +Commands run: |
| 72 | + |
| 73 | +```sh |
| 74 | +GOCACHE=/tmp/lattice-review-go-build GOWORK=/Users/cdcd/roobli/RTFS_justTaste/Probe-Dashboards/Lattice/lattice/go.work go test ./internal/store -run TestBoltState -count=1 |
| 75 | +GOCACHE=/tmp/lattice-review-go-build GOWORK=/Users/cdcd/roobli/RTFS_justTaste/Probe-Dashboards/Lattice/lattice/go.work go test ./internal/store -count=1 |
| 76 | +GOCACHE=/tmp/lattice-review-go-build GOWORK=/Users/cdcd/roobli/RTFS_justTaste/Probe-Dashboards/Lattice/lattice/go.work go test ./... -count=1 |
| 77 | +GOCACHE=/tmp/lattice-review-go-build GOWORK=/Users/cdcd/roobli/RTFS_justTaste/Probe-Dashboards/Lattice/lattice/go.work go vet ./... |
| 78 | +GOCACHE=/tmp/lattice-review-go-build GOWORK=/Users/cdcd/roobli/RTFS_justTaste/Probe-Dashboards/Lattice/lattice/go.work go test -race ./... -count=1 |
| 79 | +``` |
| 80 | + |
| 81 | +## Residuals |
| 82 | + |
| 83 | +- Remaining low/medium-risk buckets: tasks, task results, monitors, monitor |
| 84 | + results, tunnels. |
| 85 | +- Secret-bearing buckets need field-specific encryption tests before per-record |
| 86 | + methods: users, tokens, sessions, TOTP challenges, DDNS profiles, notification |
| 87 | + channels, OIDC providers/auth states. |
| 88 | +- Runtime store switching remains blocked until record-level coverage is broad |
| 89 | + enough and backup/restore drills are complete. |
0 commit comments