step 2: init command + SQLite storage + migrations + config

- storage.go: DB wrapper, migration runner (in-code SQL strings)
- migrations.go: 001_init (nodes + node_meta + indexes)
- vault.go: Init() creates .verstak/ dirs, config.yml, index.db
- config.go: YAML config read/write
- util/uuid.go: UUIDv7 generator
- cmd/verstak/main.go: init --vault PATH command
- main_test.go: TestInitCreatesVault, TestInitConfigYAML

Acceptance: go build ./... pass, go test ./... pass
Init creates test-vault with .verstak/index.db + config.yml
Repeat Init is safe.
This commit is contained in:
2026-05-30 18:58:47 +08:00
parent 982f3064ac
commit b8d8427c46
11 changed files with 474 additions and 10 deletions
+33
View File
@@ -0,0 +1,33 @@
package util
import (
"crypto/rand"
"fmt"
"time"
)
// UUID7 generates a UUIDv7-like identifier (time-ordered, random suffix).
// Format: 32 hex chars, e.g. "01972a8b4c3d8000a1b2c3d4e5f6a7b8".
func UUID7() string {
var b [16]byte
if _, err := rand.Read(b[:]); err != nil {
panic("uuid7: rand: " + err.Error())
}
// Set version 7 bits.
b[6] = (b[6] & 0x0f) | 0x70
b[8] = (b[8] & 0x3f) | 0x80
// Encode timestamp in first 6 bytes for rough time-ordering.
now := time.Now().UnixMilli()
b[0] = byte(now >> 40)
b[1] = byte(now >> 32)
b[2] = byte(now >> 24)
b[3] = byte(now >> 16)
b[4] = byte(now >> 8)
b[5] = byte(now)
return fmt.Sprintf("%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7],
b[8], b[9], b[10], b[11], b[12], b[13], b[14], b[15])
}