Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
87 commits
Select commit Hold shift + click to select a range
cae3c32
refactor: add AX config validation helpers
Apr 4, 2026
1fb8295
feat(store): add scoped store config constructor
Apr 4, 2026
dfbdace
feat: add scoped store transactions
Apr 4, 2026
06f6229
feat(store): expose workspace state directory config
Apr 4, 2026
a2a99f6
docs(store): clarify package surface
Apr 4, 2026
d682dcd
docs(scope): prefer explicit scoped examples
Apr 4, 2026
9dc0b9b
refactor(scope): make scoped group access explicit
Apr 4, 2026
b208701
refactor(store): unify scoped prefix helper naming
Apr 4, 2026
5527c5b
docs(store): prefer config literals in examples
Apr 4, 2026
fd6f1fe
docs(store): sharpen agent-facing examples
Apr 4, 2026
1905ce5
fix(store): normalise compact archive formats
Apr 4, 2026
08e896a
docs(store): clarify journal metadata
Apr 4, 2026
c2ba213
docs(ax): prefer scoped config literals
Apr 4, 2026
d8183f2
fix: support scalar Flux journal filters
Apr 4, 2026
ba997f7
docs(store): align public comments with AX
Apr 4, 2026
8e46ab9
docs(store): align RFC examples with AX
Apr 4, 2026
aa49cda
feat(scope): add scoped pagination helpers
Apr 4, 2026
23fb573
refactor(store): rename transaction internals
Apr 4, 2026
f30fb8c
refactor(test): expand AX naming in coverage stubs
Apr 4, 2026
00650fd
feat(store): add transaction purge helpers
Apr 4, 2026
efd40dd
docs(store): reinforce AX config literal guidance
Apr 4, 2026
39fddb8
refactor(scope): reuse shared prefix helper
Apr 4, 2026
ecafc84
fix(store): require compact cutoff time
Apr 4, 2026
7ad4dab
refactor(store): clarify config guidance and naming
Apr 4, 2026
529333c
fix(workspace): close partial workspaces without filesystem
Apr 4, 2026
75f8702
feat: normalise declarative store config defaults
Apr 4, 2026
731a3ae
fix(scope): make quota checks non-mutating
Apr 4, 2026
4c6f2d6
feat(scope): add scoped on-change helper
Apr 4, 2026
649edea
docs(ax): align package guidance with declarative config
Apr 4, 2026
e5c63ee
refactor(scope): remove redundant scoped quota constructor
Apr 4, 2026
4726b73
feat(scope): restore scoped quota constructor
Apr 4, 2026
8b18644
fix(compact): normalise whitespace archive formats
Apr 4, 2026
257bd52
docs(ax): prefer declarative config literals in examples
Apr 4, 2026
d854e1c
refactor(scope): prefer scoped-store config literals
Apr 4, 2026
1c004d4
refactor(store): remove redundant scoped quota constructor
Apr 4, 2026
fb39b74
refactor(scope): centralise quota enforcement
Apr 4, 2026
466f4ba
refactor: align workspace and scoped store names
Apr 4, 2026
c684074
docs(store): tighten AX-facing package docs
Apr 4, 2026
8a117a3
refactor(store): clarify compaction lifecycle names
Apr 4, 2026
ea3f434
feat: add scoped store watcher wrappers
Apr 4, 2026
c8504ab
docs(store): clarify declarative constructors
Apr 4, 2026
fcb178f
feat(scope): expose scoped config snapshot
Apr 4, 2026
7fa9449
chore(store): confirm RFC parity
Apr 4, 2026
e1341ff
refactor(store): align internal lifecycle naming with AX
Apr 4, 2026
69452ef
docs(ax): tighten usage examples
Apr 4, 2026
cdf3124
fix(store): make scoped store nil-safe
Apr 4, 2026
72eff0d
refactor: tighten store AX documentation
Apr 4, 2026
345fa26
feat(store): add Exists, GroupExists, and Workspace.Count methods
Snider Apr 5, 2026
7981504
chore: refresh go.sum
Snider Apr 7, 2026
eef4e73
refactor(store): replace banned stdlib imports with core/go primitives
Snider Apr 8, 2026
2d7fb95
feat(store): io.Medium-backed storage per RFC §9
Snider Apr 14, 2026
b6daafe
feat(store): DuckDB.Conn() accessor for streaming row iteration
Snider Apr 14, 2026
a69d150
Align store API with RFC
Snider Apr 15, 2026
a8cab20
Align store internals with RFC
Snider Apr 15, 2026
9df2291
Align store options with RFC
Snider Apr 15, 2026
9610dd1
Support medium-backed SQLite persistence
Snider Apr 15, 2026
e5a0f66
Emit TTL purge events
Snider Apr 15, 2026
48643a7
docs(api): align package overview with primary constructors
Snider Apr 15, 2026
9763ef7
Align module path docs
Snider Apr 15, 2026
caaba5d
feat(scope): add scoped quota constructor
Snider Apr 15, 2026
303ff4e
Use DuckDB for workspace buffers
Snider Apr 15, 2026
403f861
Align medium API with upstream interface
Snider Apr 15, 2026
7eba9e9
Verify go-store RFC implementation
Snider Apr 15, 2026
a2eb005
Verify RFC-aligned go-store implementation
Snider Apr 15, 2026
702fd12
sync store RFC
Snider Apr 15, 2026
2dd91b6
chore: go mod tidy (module path migration)
Snider Apr 24, 2026
7069a66
feat(go-store): add CLI test Taskfile for build and test validation (…
codex Apr 24, 2026
8c8766a
feat(go-store): add default task aggregator to tests/cli Taskfile (AX…
Snider Apr 24, 2026
608f0df
fix(go-store): replace testify with stdlib testing patterns (AX-6)
Snider Apr 24, 2026
39526dd
fix(go-store): remove banned strconv from journal.go (AX-6)
Snider Apr 24, 2026
57d5af9
chore(go-store): annotate external storage deps in go.mod per AX-6
Snider Apr 24, 2026
ae6861e
chore(go-store): migrate dappco.re/go/core/io → dappco.re/go/io (AX-6)
Snider Apr 24, 2026
92a206e
docs(go-store): document Transaction API in RFC §7 per spec gap
Snider Apr 24, 2026
51c9d1e
docs(go-store): clean up RFC §4 — deduplicate Event + complete Store …
Snider Apr 24, 2026
856e88b
feat(ax-10): bring go-store to v0.8.0-alpha.1 + CLI test scaffold
Snider Apr 24, 2026
903af6c
docs(store): confirm Import/Export already present (#260, NOTABUG)
Snider Apr 25, 2026
cfc93d4
fix(store): remove banned io import from compact.go, route through Me…
Snider Apr 25, 2026
4a2d84b
docs(store): annotate sync as AX-6 structural exception per RFC §4 (#…
Snider Apr 25, 2026
32413aa
feat(store): RecoverOrphans quarantines corrupt files per RFC §8.6 (#…
Snider Apr 25, 2026
651a966
fix(store): AX-6 sweep on json.go + parquet.go
Snider Apr 25, 2026
c180cd2
fix(store): AX-6 sweep on medium.go + publish.go
Snider Apr 25, 2026
85ab185
Merge remote-tracking branch 'github/dev' into dev
Snider Apr 27, 2026
6c90af8
fix(store): address all CodeRabbit findings on PR #4
Snider Apr 27, 2026
ebe5377
fix(store): r2 — address residual CodeRabbit findings on PR #4
Snider Apr 27, 2026
fc77445
fix(store): r3 — transactional import + DELETE RETURNING + token home…
Snider Apr 27, 2026
4aeddac
fix(store): r4 — EnsureDir errors + scoped readiness names + purge ev…
Snider Apr 27, 2026
d634429
fix(store): r5 — scoped quota race + swallowed Close + event timeout …
Snider Apr 27, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
name: CI

env:
CGO_ENABLED: "1"

on:
push:
branches: [main, dev]
Expand Down
49 changes: 26 additions & 23 deletions .golangci.yml
Original file line number Diff line number Diff line change
@@ -1,34 +1,37 @@
version: "2"
run:
timeout: 5m
go: "1.26"

linters:
enable:
- depguard
- govet
- errcheck
- staticcheck
- unused
- gosimple
- ineffassign
- typecheck
- gocritic
- gofmt
disable:
- exhaustive
- wrapcheck

linters-settings:
depguard:
rules:
legacy-module-paths:
list-mode: lax
files:
- $all
deny:
- pkg: forge.lthn.ai/
desc: use dappco.re/ module paths instead

settings:
depguard:
rules:
legacy-module-paths:
list-mode: lax
files:
- $all
deny:
- pkg: forge.lthn.ai/
desc: use dappco.re/ module paths instead
exclusions:
generated: lax
paths:
- third_party$
- builtin$
- examples$
issues:
exclude-use-default: false
max-same-issues: 0
formatters:
enable:
- gofmt
exclusions:
generated: lax
paths:
- third_party$
- builtin$
- examples$
4 changes: 2 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co

## What This Is

SQLite key-value store with TTL, namespace isolation, and reactive events. Pure Go (no CGO). Module: `dappco.re/go/core/store`
SQLite key-value store with TTL, namespace isolation, and reactive events. Pure Go (no CGO). Module: `dappco.re/go/store`

## AX Notes

Expand Down Expand Up @@ -62,7 +62,7 @@ import (
"fmt"
"time"

"dappco.re/go/core/store"
"dappco.re/go/store"
)

func main() {
Expand Down
21 changes: 21 additions & 0 deletions DEPENDENCIES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Dependency Exceptions

This repository is pure Go by default and permits `modernc.org/sqlite` as the
normal runtime database dependency. The following exception is documented
because the current PR contains load-bearing analytical workspace code that
cannot be replaced by a pure-Go DuckDB-compatible driver.

## `github.com/marcboeker/go-duckdb`

`github.com/marcboeker/go-duckdb` is retained only for DuckDB-backed workspace
buffers and LEM analytical import helpers. DuckDB files are produced and
consumed by existing data pipelines, and no pure-Go DuckDB implementation with
compatible SQL semantics is currently available. Replacing it with
`modernc.org/sqlite` would remove DuckDB JSON import, analytical table, and
workspace recovery behaviour rather than preserving the feature.

This is a CGO and MIT-licensed dependency exception. It must not be used for the
primary SQLite store path, and new runtime storage features should continue to
use pure-Go dependencies compatible with EUPL-1.2. Builds and CI that include
workspace, import, inventory, or scoring behaviour must run with
`CGO_ENABLED=1` and a C/C++ toolchain available.
6 changes: 6 additions & 0 deletions LICENCE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Licence

This project is licensed under the European Union Public Licence, version 1.2
(EUPL-1.2).

Full licence text: https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
12 changes: 7 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
[![Go Reference](https://pkg.go.dev/badge/dappco.re/go/core/store.svg)](https://pkg.go.dev/dappco.re/go/core/store)
[![License: EUPL-1.2](https://img.shields.io/badge/License-EUPL--1.2-blue.svg)](LICENSE.md)
[![Go Reference](https://pkg.go.dev/badge/dappco.re/go/store.svg)](https://pkg.go.dev/dappco.re/go/store)
[![Licence: EUPL-1.2](https://img.shields.io/badge/Licence-EUPL--1.2-blue.svg)](LICENCE.md)
[![Go Version](https://img.shields.io/badge/Go-1.26-00ADD8?style=flat&logo=go)](go.mod)

# go-store

Group-namespaced SQLite key-value store with TTL expiry, namespace isolation, quota enforcement, and a reactive event system. Backed by a pure-Go SQLite driver (no CGO), uses WAL mode for concurrent reads, and enforces a single connection to keep pragma settings consistent. Supports scoped stores for multi-tenant use, Watch/Unwatch subscriptions, and OnChange callbacks for downstream event consumers.

**Module**: `dappco.re/go/core/store`
**Module**: `dappco.re/go/store`
**Licence**: EUPL-1.2
**Language**: Go 1.26

Expand All @@ -19,7 +19,7 @@ import (
"fmt"
"time"

"dappco.re/go/core/store"
"dappco.re/go/store"
)

func main() {
Expand All @@ -32,6 +32,7 @@ func main() {
BucketName: "events",
},
PurgeInterval: 30 * time.Second,
WorkspaceStateDirectory: "/tmp/core-state",
})
if err != nil {
return
Expand Down Expand Up @@ -80,6 +81,7 @@ func main() {
- [Architecture](docs/architecture.md) — storage layer, group/key model, TTL expiry, event system, namespace isolation
- [Development Guide](docs/development.md) — prerequisites, test patterns, benchmarks, adding methods
- [Project History](docs/history.md) — completed phases, known limitations, future considerations
- [Dependency Exceptions](DEPENDENCIES.md) — documented runtime dependency exceptions

## Build & Test

Expand All @@ -92,4 +94,4 @@ go build ./...

## Licence

European Union Public Licence 1.2 — see [LICENCE](LICENCE) for details.
European Union Public Licence 1.2 — see [LICENCE.md](LICENCE.md) for details.
12 changes: 6 additions & 6 deletions bench_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ func BenchmarkGetAll_VaryingSize(b *testing.B) {
if err != nil {
b.Fatal(err)
}
defer storeInstance.Close()
defer func() { _ = storeInstance.Close() }()

for i := range size {
_ = storeInstance.Set("bench", core.Sprintf("key-%d", i), "value")
Expand All @@ -41,7 +41,7 @@ func BenchmarkSetGet_Parallel(b *testing.B) {
if err != nil {
b.Fatal(err)
}
defer storeInstance.Close()
defer func() { _ = storeInstance.Close() }()

b.ReportAllocs()
b.ResetTimer()
Expand All @@ -62,7 +62,7 @@ func BenchmarkCount_10K(b *testing.B) {
if err != nil {
b.Fatal(err)
}
defer storeInstance.Close()
defer func() { _ = storeInstance.Close() }()

for i := range 10_000 {
_ = storeInstance.Set("bench", core.Sprintf("key-%d", i), "value")
Expand All @@ -81,7 +81,7 @@ func BenchmarkDelete(b *testing.B) {
if err != nil {
b.Fatal(err)
}
defer storeInstance.Close()
defer func() { _ = storeInstance.Close() }()

// Pre-populate keys that will be deleted.
for i := range b.N {
Expand All @@ -101,7 +101,7 @@ func BenchmarkSetWithTTL(b *testing.B) {
if err != nil {
b.Fatal(err)
}
defer storeInstance.Close()
defer func() { _ = storeInstance.Close() }()

b.ReportAllocs()
b.ResetTimer()
Expand All @@ -116,7 +116,7 @@ func BenchmarkRender(b *testing.B) {
if err != nil {
b.Fatal(err)
}
defer storeInstance.Close()
defer func() { _ = storeInstance.Close() }()

for i := range 50 {
_ = storeInstance.Set("bench", core.Sprintf("key%d", i), core.Sprintf("val%d", i))
Expand Down
Loading
Loading