Merge pull request '[agent/codex:gpt-5.3-codex-spark] Read .core/reference/RFC-CORE-008-AGENT-EXPERIENCE.md (the A...' (#14) from main into dev
Some checks failed
Security Scan / security (push) Failing after 15s
Test / test (push) Successful in 10m52s

This commit is contained in:
Virgil 2026-03-29 15:26:33 +00:00
commit 86c68ad1c9
30 changed files with 111 additions and 86 deletions

View file

@ -2,7 +2,7 @@
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
You are a dedicated domain expert for `forge.lthn.ai/core/go-crypt`. Virgil (in You are a dedicated domain expert for `dappco.re/go/core/crypt`. Virgil (in
core/go) orchestrates your work. Pick up tasks in phase order, mark `[x]` when core/go) orchestrates your work. Pick up tasks in phase order, mark `[x]` when
done, commit and push. done, commit and push.
@ -39,16 +39,16 @@ go test -bench=. -benchmem ./crypt/... # Benchmarks
## Local Dependencies ## Local Dependencies
All `forge.lthn.ai/core/*` modules are resolved through the Go workspace All `dappco.re/go/core/*` and remaining `forge.lthn.ai/core/*` modules are resolved through the Go workspace
(`~/Code/go.work`). Do not add replace directives to `go.mod` — use the (`~/Code/go.work`). Do not add replace directives to `go.mod` — use the
workspace file instead. workspace file instead.
| Module | Local Path | Purpose | | Module | Local Path | Purpose |
|--------|-----------|---------| |--------|-----------|---------|
| `forge.lthn.ai/core/go` | `../go` | Framework: `core.Crypt` interface, `io.Medium` | | `dappco.re/go/core` | `../go` | Framework: `core.Crypt` interface, `io.Medium` |
| `dappco.re/go/core/log` | `../go-log` | `coreerr.E()` contextual error wrapping |
| `dappco.re/go/core/io` | `../go-io` | `io.Medium` storage abstraction |
| `forge.lthn.ai/core/go-store` | `../go-store` | SQLite KV store (session persistence) | | `forge.lthn.ai/core/go-store` | `../go-store` | SQLite KV store (session persistence) |
| `forge.lthn.ai/core/go-io` | `../go-io` | `io.Medium` storage abstraction |
| `forge.lthn.ai/core/go-log` | `../go-log` | `core.E()` contextual error wrapping |
| `forge.lthn.ai/core/cli` | `../cli` | CLI framework for `cmd/crypt` commands | | `forge.lthn.ai/core/cli` | `../cli` | CLI framework for `cmd/crypt` commands |
No C toolchain or CGo required — all crypto uses pure Go implementations. No C toolchain or CGo required — all crypto uses pure Go implementations.
@ -58,9 +58,9 @@ No C toolchain or CGo required — all crypto uses pure Go implementations.
- **UK English**: colour, organisation, centre, artefact, licence, serialise - **UK English**: colour, organisation, centre, artefact, licence, serialise
- **Tests**: testify assert/require, `_Good`/`_Bad`/`_Ugly` naming convention - **Tests**: testify assert/require, `_Good`/`_Bad`/`_Ugly` naming convention
- **Concurrency tests**: 10 goroutines via WaitGroup; must pass `-race` - **Concurrency tests**: 10 goroutines via WaitGroup; must pass `-race`
- **Imports**: stdlib → forge.lthn.ai → third-party, separated by blank lines - **Imports**: stdlib → dappco.re/forge.lthn.ai → third-party, separated by blank lines
- **Errors**: use `coreerr.E("package.Function", "lowercase message", err)` (imported - **Errors**: use `coreerr.E("package.Function", "lowercase message", err)` (imported
as `coreerr "forge.lthn.ai/core/go-log"`); never include secrets in error strings as `coreerr "dappco.re/go/core/log"`); never include secrets in error strings
- **Randomness**: `crypto/rand` only; never `math/rand` - **Randomness**: `crypto/rand` only; never `math/rand`
- **Conventional commits**: `feat(auth):`, `fix(crypt):`, `refactor(trust):` - **Conventional commits**: `feat(auth):`, `fix(crypt):`, `refactor(trust):`
Scopes match package names: `auth`, `crypt`, `trust`, `pgp`, `lthn`, `rsa`, Scopes match package names: `auth`, `crypt`, `trust`, `pgp`, `lthn`, `rsa`,
@ -70,6 +70,6 @@ No C toolchain or CGo required — all crypto uses pure Go implementations.
## Forge ## Forge
- **Repo**: `forge.lthn.ai/core/go-crypt` - **Repo**: `dappco.re/go/core/crypt`
- **Push via SSH**: `git push forge main` - **Push via SSH**: `git push forge main`
(remote: `ssh://git@forge.lthn.ai:2223/core/go-crypt.git`) (remote: `ssh://git@forge.lthn.ai:2223/core/go-crypt.git`)

View file

@ -35,12 +35,11 @@ import (
"sync" "sync"
"time" "time"
coreerr "forge.lthn.ai/core/go-log" "dappco.re/go/core/crypt/crypt"
"dappco.re/go/core/crypt/crypt/lthn"
"forge.lthn.ai/core/go-crypt/crypt" "dappco.re/go/core/crypt/crypt/pgp"
"forge.lthn.ai/core/go-crypt/crypt/lthn" "dappco.re/go/core/io"
"forge.lthn.ai/core/go-crypt/crypt/pgp" coreerr "dappco.re/go/core/log"
"forge.lthn.ai/core/go-io"
) )
// Default durations for challenge and session lifetimes. // Default durations for challenge and session lifetimes.
@ -324,7 +323,9 @@ func (a *Authenticator) ValidateSession(token string) (*Session, error) {
} }
if time.Now().After(session.ExpiresAt) { if time.Now().After(session.ExpiresAt) {
_ = a.store.Delete(token) if err := a.store.Delete(token); err != nil {
return nil, coreerr.E(op, "session expired", err)
}
return nil, coreerr.E(op, "session expired", nil) return nil, coreerr.E(op, "session expired", nil)
} }
@ -341,7 +342,9 @@ func (a *Authenticator) RefreshSession(token string) (*Session, error) {
} }
if time.Now().After(session.ExpiresAt) { if time.Now().After(session.ExpiresAt) {
_ = a.store.Delete(token) if err := a.store.Delete(token); err != nil {
return nil, coreerr.E(op, "session expired", err)
}
return nil, coreerr.E(op, "session expired", nil) return nil, coreerr.E(op, "session expired", nil)
} }
@ -390,7 +393,9 @@ func (a *Authenticator) DeleteUser(userID string) error {
} }
// Revoke any active sessions for this user // Revoke any active sessions for this user
_ = a.store.DeleteByUser(userID) if err := a.store.DeleteByUser(userID); err != nil {
return coreerr.E(op, "failed to delete user sessions", err)
}
return nil return nil
} }
@ -568,7 +573,9 @@ func (a *Authenticator) RevokeKey(userID, password, reason string) error {
} }
// Invalidate all sessions // Invalidate all sessions
_ = a.store.DeleteByUser(userID) if err := a.store.DeleteByUser(userID); err != nil {
return coreerr.E(op, "failed to delete user sessions", err)
}
return nil return nil
} }

View file

@ -11,9 +11,9 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"forge.lthn.ai/core/go-crypt/crypt/lthn" "dappco.re/go/core/crypt/crypt/lthn"
"forge.lthn.ai/core/go-crypt/crypt/pgp" "dappco.re/go/core/crypt/crypt/pgp"
"forge.lthn.ai/core/go-io" "dappco.re/go/core/io"
) )
// helper creates a fresh Authenticator backed by MockMedium. // helper creates a fresh Authenticator backed by MockMedium.

View file

@ -5,7 +5,7 @@ import (
"sync" "sync"
"time" "time"
coreerr "forge.lthn.ai/core/go-log" coreerr "dappco.re/go/core/log"
) )
// ErrSessionNotFound is returned when a session token is not found. // ErrSessionNotFound is returned when a session token is not found.

View file

@ -12,8 +12,8 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"forge.lthn.ai/core/go-crypt/crypt/lthn" "dappco.re/go/core/crypt/crypt/lthn"
"forge.lthn.ai/core/go-io" "dappco.re/go/core/io"
) )
// --- MemorySessionStore --- // --- MemorySessionStore ---

View file

@ -4,8 +4,8 @@ import (
"fmt" "fmt"
"path/filepath" "path/filepath"
"dappco.re/go/core/crypt/crypt"
"forge.lthn.ai/core/cli/pkg/cli" "forge.lthn.ai/core/cli/pkg/cli"
"forge.lthn.ai/core/go-crypt/crypt"
) )
// Checksum command flags // Checksum command flags

View file

@ -4,9 +4,9 @@ import (
"fmt" "fmt"
"strings" "strings"
"dappco.re/go/core/crypt/crypt"
coreio "dappco.re/go/core/io"
"forge.lthn.ai/core/cli/pkg/cli" "forge.lthn.ai/core/cli/pkg/cli"
"forge.lthn.ai/core/go-crypt/crypt"
coreio "forge.lthn.ai/core/go-io"
) )
// Encrypt command flags // Encrypt command flags

View file

@ -3,8 +3,9 @@ package crypt
import ( import (
"fmt" "fmt"
"dappco.re/go/core/crypt/crypt"
"forge.lthn.ai/core/cli/pkg/cli" "forge.lthn.ai/core/cli/pkg/cli"
"forge.lthn.ai/core/go-crypt/crypt"
"golang.org/x/crypto/bcrypt" "golang.org/x/crypto/bcrypt"
) )

View file

@ -4,8 +4,8 @@
package testcmd package testcmd
import ( import (
"dappco.re/go/core/i18n"
"forge.lthn.ai/core/cli/pkg/cli" "forge.lthn.ai/core/cli/pkg/cli"
"forge.lthn.ai/core/go-i18n"
) )
// Style aliases from shared // Style aliases from shared

View file

@ -10,7 +10,7 @@ import (
"strconv" "strconv"
"strings" "strings"
"forge.lthn.ai/core/go-i18n" "dappco.re/go/core/i18n"
) )
type packageCoverage struct { type packageCoverage struct {
@ -33,8 +33,8 @@ func parseTestOutput(output string) testResults {
results := testResults{} results := testResults{}
// Regex patterns - handle both timed and cached test results // Regex patterns - handle both timed and cached test results
// Example: ok forge.lthn.ai/core/go-crypt/crypt 0.015s coverage: 91.2% of statements // Example: ok dappco.re/go/core/crypt/crypt 0.015s coverage: 91.2% of statements
// Example: ok forge.lthn.ai/core/go-crypt/crypt (cached) coverage: 91.2% of statements // Example: ok dappco.re/go/core/crypt/crypt (cached) coverage: 91.2% of statements
okPattern := regexp.MustCompile(`^ok\s+(\S+)\s+(?:[\d.]+s|\(cached\))(?:\s+coverage:\s+([\d.]+)%)?`) okPattern := regexp.MustCompile(`^ok\s+(\S+)\s+(?:[\d.]+s|\(cached\))(?:\s+coverage:\s+([\d.]+)%)?`)
failPattern := regexp.MustCompile(`^FAIL\s+(\S+)`) failPattern := regexp.MustCompile(`^FAIL\s+(\S+)`)
skipPattern := regexp.MustCompile(`^\?\s+(\S+)\s+\[no test files\]`) skipPattern := regexp.MustCompile(`^\?\s+(\S+)\s+\[no test files\]`)
@ -171,9 +171,9 @@ func formatCoverage(cov float64) string {
} }
func shortenPackageName(name string) string { func shortenPackageName(name string) string {
const forgePrefix = "forge.lthn.ai/core/" const modulePrefix = "dappco.re/go/"
if strings.HasPrefix(name, forgePrefix) { if strings.HasPrefix(name, modulePrefix) {
remainder := strings.TrimPrefix(name, forgePrefix) remainder := strings.TrimPrefix(name, modulePrefix)
// If there's a sub-path (e.g. "go/pkg/foo"), strip the module name // If there's a sub-path (e.g. "go/pkg/foo"), strip the module name
if idx := strings.Index(remainder, "/"); idx >= 0 { if idx := strings.Index(remainder, "/"); idx >= 0 {
return remainder[idx+1:] return remainder[idx+1:]

View file

@ -9,8 +9,8 @@ import (
"runtime" "runtime"
"strings" "strings"
"forge.lthn.ai/core/go-i18n" "dappco.re/go/core/i18n"
coreerr "forge.lthn.ai/core/go-log" coreerr "dappco.re/go/core/log"
) )
func runTest(verbose, coverage, short bool, pkg, run string, race, jsonOutput bool) error { func runTest(verbose, coverage, short bool, pkg, run string, race, jsonOutput bool) error {
@ -49,7 +49,11 @@ func runTest(verbose, coverage, short bool, pkg, run string, race, jsonOutput bo
// Create command // Create command
cmd := exec.Command("go", args...) cmd := exec.Command("go", args...)
cmd.Dir, _ = os.Getwd() cwd, err := os.Getwd()
if err != nil {
return coreerr.E("cmd.test", "failed to determine working directory", err)
}
cmd.Dir = cwd
// Set environment to suppress macOS linker warnings // Set environment to suppress macOS linker warnings
cmd.Env = append(os.Environ(), getMacOSDeploymentTarget()) cmd.Env = append(os.Environ(), getMacOSDeploymentTarget())
@ -76,7 +80,7 @@ func runTest(verbose, coverage, short bool, pkg, run string, race, jsonOutput bo
cmd.Stderr = &stderr cmd.Stderr = &stderr
} }
err := cmd.Run() err = cmd.Run()
exitCode := 0 exitCode := 0
if err != nil { if err != nil {
if exitErr, ok := err.(*exec.ExitError); ok { if exitErr, ok := err.(*exec.ExitError); ok {

View file

@ -7,7 +7,7 @@ import (
) )
func TestShortenPackageName(t *testing.T) { func TestShortenPackageName(t *testing.T) {
assert.Equal(t, "pkg/foo", shortenPackageName("forge.lthn.ai/core/go/pkg/foo")) assert.Equal(t, "pkg/foo", shortenPackageName("dappco.re/go/core/pkg/foo"))
assert.Equal(t, "cli-php", shortenPackageName("forge.lthn.ai/core/cli-php")) assert.Equal(t, "cli-php", shortenPackageName("forge.lthn.ai/core/cli-php"))
assert.Equal(t, "bar", shortenPackageName("github.com/other/bar")) assert.Equal(t, "bar", shortenPackageName("github.com/other/bar"))
} }
@ -19,16 +19,16 @@ func TestFormatCoverageTest(t *testing.T) {
} }
func TestParseTestOutput(t *testing.T) { func TestParseTestOutput(t *testing.T) {
output := `ok forge.lthn.ai/core/go/pkg/foo 0.100s coverage: 50.0% of statements output := `ok dappco.re/go/core/pkg/foo 0.100s coverage: 50.0% of statements
FAIL forge.lthn.ai/core/go/pkg/bar FAIL dappco.re/go/core/pkg/bar
? forge.lthn.ai/core/go/pkg/baz [no test files] ? dappco.re/go/core/pkg/baz [no test files]
` `
results := parseTestOutput(output) results := parseTestOutput(output)
assert.Equal(t, 1, results.passed) assert.Equal(t, 1, results.passed)
assert.Equal(t, 1, results.failed) assert.Equal(t, 1, results.failed)
assert.Equal(t, 1, results.skipped) assert.Equal(t, 1, results.skipped)
assert.Equal(t, 1, len(results.failedPkgs)) assert.Equal(t, 1, len(results.failedPkgs))
assert.Equal(t, "forge.lthn.ai/core/go/pkg/bar", results.failedPkgs[0]) assert.Equal(t, "dappco.re/go/core/pkg/bar", results.failedPkgs[0])
assert.Equal(t, 1, len(results.packages)) assert.Equal(t, 1, len(results.packages))
assert.Equal(t, 50.0, results.packages[0].coverage) assert.Equal(t, 50.0, results.packages[0].coverage)
} }
@ -37,8 +37,8 @@ func TestPrintCoverageSummarySafe(t *testing.T) {
// This tests the bug fix for long package names causing negative Repeat count // This tests the bug fix for long package names causing negative Repeat count
results := testResults{ results := testResults{
packages: []packageCoverage{ packages: []packageCoverage{
{name: "forge.lthn.ai/core/go/pkg/short", coverage: 100, hasCov: true}, {name: "dappco.re/go/core/pkg/short", coverage: 100, hasCov: true},
{name: "forge.lthn.ai/core/go/pkg/a-very-very-very-very-very-long-package-name-that-might-cause-issues", coverage: 80, hasCov: true}, {name: "dappco.re/go/core/pkg/a-very-very-very-very-very-long-package-name-that-might-cause-issues", coverage: 80, hasCov: true},
}, },
passed: 2, passed: 2,
totalCov: 180, totalCov: 180,

View file

@ -5,7 +5,7 @@ import (
"fmt" "fmt"
"io" "io"
coreerr "forge.lthn.ai/core/go-log" coreerr "dappco.re/go/core/log"
"golang.org/x/crypto/chacha20poly1305" "golang.org/x/crypto/chacha20poly1305"
) )

View file

@ -2,9 +2,10 @@ package chachapoly
import ( import (
"crypto/rand" "crypto/rand"
"errors"
"testing" "testing"
coreerr "dappco.re/go/core/log"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@ -12,7 +13,7 @@ import (
type mockReader struct{} type mockReader struct{}
func (r *mockReader) Read(p []byte) (n int, err error) { func (r *mockReader) Read(p []byte) (n int, err error) {
return 0, errors.New("read error") return 0, coreerr.E("chachapoly.mockReader.Read", "read error", nil)
} }
func TestEncryptDecrypt(t *testing.T) { func TestEncryptDecrypt(t *testing.T) {

View file

@ -7,7 +7,7 @@ import (
"io" "io"
"os" "os"
coreerr "forge.lthn.ai/core/go-log" coreerr "dappco.re/go/core/log"
) )
// SHA256File computes the SHA-256 checksum of a file and returns it as a hex string. // SHA256File computes the SHA-256 checksum of a file and returns it as a hex string.

View file

@ -1,7 +1,7 @@
package crypt package crypt
import ( import (
coreerr "forge.lthn.ai/core/go-log" coreerr "dappco.re/go/core/log"
) )
// Encrypt encrypts data with a passphrase using ChaCha20-Poly1305. // Encrypt encrypts data with a passphrase using ChaCha20-Poly1305.

View file

@ -6,7 +6,8 @@ import (
"fmt" "fmt"
"strings" "strings"
coreerr "forge.lthn.ai/core/go-log" coreerr "dappco.re/go/core/log"
"golang.org/x/crypto/argon2" "golang.org/x/crypto/argon2"
"golang.org/x/crypto/bcrypt" "golang.org/x/crypto/bcrypt"
) )

View file

@ -7,7 +7,8 @@ import (
"crypto/sha256" "crypto/sha256"
"io" "io"
coreerr "forge.lthn.ai/core/go-log" coreerr "dappco.re/go/core/log"
"golang.org/x/crypto/argon2" "golang.org/x/crypto/argon2"
"golang.org/x/crypto/hkdf" "golang.org/x/crypto/hkdf"
"golang.org/x/crypto/scrypt" "golang.org/x/crypto/scrypt"

View file

@ -6,15 +6,12 @@ import (
goio "io" goio "io"
"strings" "strings"
core "forge.lthn.ai/core/go-log"
framework "dappco.re/go/core" framework "dappco.re/go/core"
coreerr "dappco.re/go/core/log"
"github.com/ProtonMail/go-crypto/openpgp" "github.com/ProtonMail/go-crypto/openpgp"
"github.com/ProtonMail/go-crypto/openpgp/armor" "github.com/ProtonMail/go-crypto/openpgp/armor"
"github.com/ProtonMail/go-crypto/openpgp/packet" "github.com/ProtonMail/go-crypto/openpgp/packet"
coreerr "forge.lthn.ai/core/go-log"
framework "dappco.re/go/core"
) )
// Service provides OpenPGP cryptographic operations. // Service provides OpenPGP cryptographic operations.
@ -66,7 +63,6 @@ func (s *Service) CreateKeyPair(name, passphrase string) (string, error) {
err = serializeEntity(w, entity) err = serializeEntity(w, entity)
if err != nil { if err != nil {
w.Close() w.Close()
<<<<<<< HEAD
return "", coreerr.E("openpgp.CreateKeyPair", "failed to serialise private key", err) return "", coreerr.E("openpgp.CreateKeyPair", "failed to serialise private key", err)
} }
w.Close() w.Close()
@ -153,7 +149,9 @@ func (s *Service) DecryptPGP(privateKey, message, passphrase string, opts ...any
return "", coreerr.E("openpgp.DecryptPGP", "failed to decrypt private key", err) return "", coreerr.E("openpgp.DecryptPGP", "failed to decrypt private key", err)
} }
for _, subkey := range entity.Subkeys { for _, subkey := range entity.Subkeys {
_ = subkey.PrivateKey.Decrypt([]byte(passphrase)) if err := subkey.PrivateKey.Decrypt([]byte(passphrase)); err != nil {
return "", coreerr.E("openpgp.DecryptPGP", "failed to decrypt subkey", err)
}
} }
} }

View file

@ -8,7 +8,7 @@ import (
"bytes" "bytes"
"io" "io"
coreerr "forge.lthn.ai/core/go-log" coreerr "dappco.re/go/core/log"
"github.com/ProtonMail/go-crypto/openpgp" "github.com/ProtonMail/go-crypto/openpgp"
"github.com/ProtonMail/go-crypto/openpgp/armor" "github.com/ProtonMail/go-crypto/openpgp/armor"
@ -34,7 +34,9 @@ func CreateKeyPair(name, email, password string) (*KeyPair, error) {
// Sign all the identities // Sign all the identities
for _, id := range entity.Identities { for _, id := range entity.Identities {
_ = id.SelfSignature.SignUserId(id.UserId.Id, entity.PrimaryKey, entity.PrivateKey, nil) if err := id.SelfSignature.SignUserId(id.UserId.Id, entity.PrimaryKey, entity.PrivateKey, nil); err != nil {
return nil, coreerr.E(op, "failed to sign identity", err)
}
} }
// Encrypt private key with password if provided // Encrypt private key with password if provided
@ -166,7 +168,9 @@ func Decrypt(data []byte, privateKeyArmor, password string) ([]byte, error) {
} }
for _, subkey := range entity.Subkeys { for _, subkey := range entity.Subkeys {
if subkey.PrivateKey != nil && subkey.PrivateKey.Encrypted { if subkey.PrivateKey != nil && subkey.PrivateKey.Encrypted {
_ = subkey.PrivateKey.Decrypt([]byte(password)) if err := subkey.PrivateKey.Decrypt([]byte(password)); err != nil {
return nil, coreerr.E(op, "failed to decrypt subkey", err)
}
} }
} }
} }

View file

@ -8,7 +8,7 @@ import (
"encoding/pem" "encoding/pem"
"fmt" "fmt"
coreerr "forge.lthn.ai/core/go-log" coreerr "dappco.re/go/core/log"
) )
// Service provides RSA functionality. // Service provides RSA functionality.

View file

@ -6,9 +6,10 @@ import (
"crypto/rand" "crypto/rand"
"crypto/x509" "crypto/x509"
"encoding/pem" "encoding/pem"
"errors"
"testing" "testing"
coreerr "dappco.re/go/core/log"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@ -16,7 +17,7 @@ import (
type mockReader struct{} type mockReader struct{}
func (r *mockReader) Read(p []byte) (n int, err error) { func (r *mockReader) Read(p []byte) (n int, err error) {
return 0, errors.New("read error") return 0, coreerr.E("rsa.mockReader.Read", "read error", nil)
} }
func TestRSA_Good(t *testing.T) { func TestRSA_Good(t *testing.T) {

View file

@ -5,7 +5,8 @@ import (
"crypto/cipher" "crypto/cipher"
"crypto/rand" "crypto/rand"
coreerr "forge.lthn.ai/core/go-log" coreerr "dappco.re/go/core/log"
"golang.org/x/crypto/chacha20poly1305" "golang.org/x/crypto/chacha20poly1305"
) )

14
go.mod
View file

@ -1,13 +1,13 @@
module forge.lthn.ai/core/go-crypt module dappco.re/go/core/crypt
go 1.26.0 go 1.26.0
require ( require (
dappco.re/go/core v0.4.7 dappco.re/go/core v0.5.0
dappco.re/go/core/i18n v0.2.0
dappco.re/go/core/io v0.2.0
dappco.re/go/core/log v0.1.0
forge.lthn.ai/core/cli v0.3.7 forge.lthn.ai/core/cli v0.3.7
forge.lthn.ai/core/go-i18n v0.1.7
forge.lthn.ai/core/go-io v0.1.7
forge.lthn.ai/core/go-log v0.0.4
forge.lthn.ai/core/go-store v0.1.10 forge.lthn.ai/core/go-store v0.1.10
github.com/ProtonMail/go-crypto v1.4.0 github.com/ProtonMail/go-crypto v1.4.0
github.com/stretchr/testify v1.11.1 github.com/stretchr/testify v1.11.1
@ -15,8 +15,10 @@ require (
) )
require ( require (
forge.lthn.ai/core/go v0.3.3 // indirect forge.lthn.ai/core/go v0.3.2 // indirect
forge.lthn.ai/core/go-i18n v0.1.7 // indirect
forge.lthn.ai/core/go-inference v0.1.7 // indirect forge.lthn.ai/core/go-inference v0.1.7 // indirect
forge.lthn.ai/core/go-log v0.0.4 // indirect
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
github.com/charmbracelet/bubbletea v1.3.10 // indirect github.com/charmbracelet/bubbletea v1.3.10 // indirect
github.com/charmbracelet/colorprofile v0.4.3 // indirect github.com/charmbracelet/colorprofile v0.4.3 // indirect

16
go.sum
View file

@ -1,15 +1,19 @@
dappco.re/go/core v0.4.7 h1:KmIA/2lo6rl1NMtLrKqCWfMlUqpDZYH3q0/d10dTtGA= dappco.re/go/core v0.5.0 h1:P5DJoaCiK5Q+af5UiTdWqUIW4W4qYKzpgGK50thm21U=
dappco.re/go/core v0.4.7/go.mod h1:f2/tBZ3+3IqDrg2F5F598llv0nmb/4gJVCFzM5geE4A= dappco.re/go/core v0.5.0/go.mod h1:f2/tBZ3+3IqDrg2F5F598llv0nmb/4gJVCFzM5geE4A=
dappco.re/go/core/i18n v0.2.0 h1:NHzk6RCU93/qVRA3f2jvMr9P1R6FYheR/sHL+TnvKbI=
dappco.re/go/core/i18n v0.2.0/go.mod h1:9eSVJXr3OpIGWQvDynfhqcp27xnLMwlYLgsByU+p7ok=
dappco.re/go/core/io v0.2.0 h1:zuudgIiTsQQ5ipVt97saWdGLROovbEB/zdVyy9/l+I4=
dappco.re/go/core/io v0.2.0/go.mod h1:1QnQV6X9LNgFKfm8SkOtR9LLaj3bDcsOIeJOOyjbL5E=
dappco.re/go/core/log v0.1.0 h1:pa71Vq2TD2aoEUQWFKwNcaJ3GBY8HbaNGqtE688Unyc=
dappco.re/go/core/log v0.1.0/go.mod h1:Nkqb8gsXhZAO8VLpx7B8i1iAmohhzqA20b9Zr8VUcJs=
forge.lthn.ai/core/cli v0.3.7 h1:1GrbaGg0wDGHr6+klSbbGyN/9sSbHvFbdySJznymhwg= forge.lthn.ai/core/cli v0.3.7 h1:1GrbaGg0wDGHr6+klSbbGyN/9sSbHvFbdySJznymhwg=
forge.lthn.ai/core/cli v0.3.7/go.mod h1:DBUppJkA9P45ZFGgI2B8VXw1rAZxamHoI/KG7fRvTNs= forge.lthn.ai/core/cli v0.3.7/go.mod h1:DBUppJkA9P45ZFGgI2B8VXw1rAZxamHoI/KG7fRvTNs=
forge.lthn.ai/core/go v0.3.3 h1:kYYZ2nRYy0/Be3cyuLJspRjLqTMxpckVyhb/7Sw2gd0= forge.lthn.ai/core/go v0.3.2 h1:VB9pW6ggqBhe438cjfE2iSI5Lg+62MmRbaOFglZM+nQ=
forge.lthn.ai/core/go v0.3.3/go.mod h1:Cp4ac25pghvO2iqOu59t1GyngTKVOzKB5/VPdhRi9CQ= forge.lthn.ai/core/go v0.3.2/go.mod h1:f7/zb3Labn4ARfwTq5Bi2AFHY+uxyPHozO+hLb54eFo=
forge.lthn.ai/core/go-i18n v0.1.7 h1:aHkAoc3W8fw3RPNvw/UszQbjyFWXHszzbZgty3SwyAA= forge.lthn.ai/core/go-i18n v0.1.7 h1:aHkAoc3W8fw3RPNvw/UszQbjyFWXHszzbZgty3SwyAA=
forge.lthn.ai/core/go-i18n v0.1.7/go.mod h1:0VDjwtY99NSj2iqwrI09h5GUsJeM9s48MLkr+/Dn4G8= forge.lthn.ai/core/go-i18n v0.1.7/go.mod h1:0VDjwtY99NSj2iqwrI09h5GUsJeM9s48MLkr+/Dn4G8=
forge.lthn.ai/core/go-inference v0.1.7 h1:9Dy6v03jX5ZRH3n5iTzlYyGtucuBIgSe+S7GWvBzx9Q= forge.lthn.ai/core/go-inference v0.1.7 h1:9Dy6v03jX5ZRH3n5iTzlYyGtucuBIgSe+S7GWvBzx9Q=
forge.lthn.ai/core/go-inference v0.1.7/go.mod h1:jfWz+IJX55wAH98+ic6FEqqGB6/P31CHlg7VY7pxREw= forge.lthn.ai/core/go-inference v0.1.7/go.mod h1:jfWz+IJX55wAH98+ic6FEqqGB6/P31CHlg7VY7pxREw=
forge.lthn.ai/core/go-io v0.1.7 h1:Tdb6sqh+zz1lsGJaNX9RFWM6MJ/RhSAyxfulLXrJsbk=
forge.lthn.ai/core/go-io v0.1.7/go.mod h1:8lRLFk4Dnp5cR/Cyzh9WclD5566TbpdRgwcH7UZLWn4=
forge.lthn.ai/core/go-log v0.0.4 h1:KTuCEPgFmuM8KJfnyQ8vPOU1Jg654W74h8IJvfQMfv0= forge.lthn.ai/core/go-log v0.0.4 h1:KTuCEPgFmuM8KJfnyQ8vPOU1Jg654W74h8IJvfQMfv0=
forge.lthn.ai/core/go-log v0.0.4/go.mod h1:r14MXKOD3LF/sI8XUJQhRk/SZHBE7jAFVuCfgkXoZPw= forge.lthn.ai/core/go-log v0.0.4/go.mod h1:r14MXKOD3LF/sI8XUJQhRk/SZHBE7jAFVuCfgkXoZPw=
forge.lthn.ai/core/go-store v0.1.10 h1:JLyf8xMR3V6PfBAW1kv6SJeHsYY93LacEBpTFW657qE= forge.lthn.ai/core/go-store v0.1.10 h1:JLyf8xMR3V6PfBAW1kv6SJeHsYY93LacEBpTFW657qE=

View file

@ -6,7 +6,7 @@ import (
"sync" "sync"
"time" "time"
coreerr "forge.lthn.ai/core/go-log" coreerr "dappco.re/go/core/log"
) )
// ApprovalStatus represents the state of an approval request. // ApprovalStatus represents the state of an approval request.
@ -151,8 +151,8 @@ func (q *ApprovalQueue) Get(id string) *ApprovalRequest {
return nil return nil
} }
// Return a copy to prevent mutation. // Return a copy to prevent mutation.
copy := *req snapshot := *req
return &copy return &snapshot
} }
// Pending returns all requests with ApprovalPending status. // Pending returns all requests with ApprovalPending status.

View file

@ -7,7 +7,7 @@ import (
"sync" "sync"
"time" "time"
coreerr "forge.lthn.ai/core/go-log" coreerr "dappco.re/go/core/log"
) )
// AuditEntry records a single policy evaluation for compliance. // AuditEntry records a single policy evaluation for compliance.

View file

@ -6,7 +6,7 @@ import (
"io" "io"
"os" "os"
coreerr "forge.lthn.ai/core/go-log" coreerr "dappco.re/go/core/log"
) )
// PolicyConfig is the JSON-serialisable representation of a trust policy. // PolicyConfig is the JSON-serialisable representation of a trust policy.

View file

@ -5,7 +5,7 @@ import (
"slices" "slices"
"strings" "strings"
coreerr "forge.lthn.ai/core/go-log" coreerr "dappco.re/go/core/log"
) )
// Policy defines the access rules for a given trust tier. // Policy defines the access rules for a given trust tier.

View file

@ -16,7 +16,7 @@ import (
"sync" "sync"
"time" "time"
coreerr "forge.lthn.ai/core/go-log" coreerr "dappco.re/go/core/log"
) )
// Tier represents an agent's trust level in the system. // Tier represents an agent's trust level in the system.