Add Phase 1 foundation: Go module, core types, DB infrastructure, config

Establish the project foundation with three packages:
- core: shared types (Header, Metadata, Value, ObjectType, UUID generation)
- db: SQLite migration framework, connection management (WAL, FK, busy
  timeout), transaction helpers (StartTX/EndTX), time conversion
- config: runtime configuration (DB path, blob store, Minio, gRPC addr)

Includes initial schema migration (001_initial.sql) with 13 tables covering
shared infrastructure, bibliographic data, and artifact repository. Full test
coverage for all packages, strict linting (.golangci.yaml), and Makefile.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-21 09:46:08 -07:00
parent 98990c6d76
commit bb2c7f7ef3
13 changed files with 1038 additions and 4 deletions

106
core/core_test.go Normal file
View File

@@ -0,0 +1,106 @@
package core
import (
"sort"
"testing"
"time"
)
func TestNewUUID(t *testing.T) {
id1 := NewUUID()
id2 := NewUUID()
if id1 == "" {
t.Fatal("NewUUID returned empty string")
}
if id1 == id2 {
t.Fatal("NewUUID returned duplicate UUIDs")
}
}
func TestVal(t *testing.T) {
v := Val("hello")
if v.Contents != "hello" {
t.Fatalf("expected contents 'hello', got %q", v.Contents)
}
if v.Type != ValueTypeUnspecified {
t.Fatalf("expected type %q, got %q", ValueTypeUnspecified, v.Type)
}
}
func TestVals(t *testing.T) {
v := Vals("world")
if v.Contents != "world" {
t.Fatalf("expected contents 'world', got %q", v.Contents)
}
if v.Type != ValueTypeString {
t.Fatalf("expected type %q, got %q", ValueTypeString, v.Type)
}
}
func TestNewHeader(t *testing.T) {
before := time.Now().UTC().Unix()
h := NewHeader(ObjectTypeArtifact)
after := time.Now().UTC().Unix()
if h.ID == "" {
t.Fatal("header ID is empty")
}
if h.Type != ObjectTypeArtifact {
t.Fatalf("expected type %q, got %q", ObjectTypeArtifact, h.Type)
}
if h.Created < before || h.Created > after {
t.Fatalf("Created timestamp %d not in range [%d, %d]", h.Created, before, after)
}
if h.Modified != h.Created {
t.Fatalf("Modified (%d) should equal Created (%d)", h.Modified, h.Created)
}
if h.Meta == nil {
t.Fatal("Meta should not be nil")
}
}
func TestHeaderTouch(t *testing.T) {
h := NewHeader(ObjectTypeNode)
original := h.Modified
// Ensure at least 1 second passes for timestamp change.
time.Sleep(10 * time.Millisecond)
h.Touch()
if h.Modified < original {
t.Fatalf("Touch should not decrease Modified: was %d, now %d", original, h.Modified)
}
}
func TestMapFromList(t *testing.T) {
list := []string{"alpha", "beta", "gamma"}
m := MapFromList(list)
if len(m) != 3 {
t.Fatalf("expected 3 entries, got %d", len(m))
}
for _, s := range list {
if !m[s] {
t.Fatalf("expected %q in map", s)
}
}
}
func TestListFromMap(t *testing.T) {
m := map[string]bool{"z": true, "a": true, "m": true}
list := ListFromMap(m)
if len(list) != 3 {
t.Fatalf("expected 3 entries, got %d", len(list))
}
sort.Strings(list)
expected := []string{"a", "m", "z"}
for i, v := range list {
if v != expected[i] {
t.Fatalf("index %d: expected %q, got %q", i, expected[i], v)
}
}
}
func TestMapFromListEmpty(t *testing.T) {
m := MapFromList(nil)
if len(m) != 0 {
t.Fatalf("expected empty map, got %d entries", len(m))
}
}