Files
weichenandCursor c7e3e99303 feat(artifactvault): extract audited FAV with union-deny reads
Goose 00036 is a renumbered copy of the vault tables. Degraded read stays off by default and only runs after authorization; tombstones and unpublished artifacts fail closed.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-14 15:59:36 +00:00

218 lines
6.6 KiB
Go

package artifactvault
import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"strings"
"chat-agent-system/internal/fsutil"
)
type FilesystemStore struct {
Root string
StorageIdentity string
MasterKey []byte
}
func NewFilesystemStore(root, identity string, master []byte) (*FilesystemStore, error) {
if strings.TrimSpace(root) == "" || strings.Contains(root, "data/dev") && !strings.Contains(root, "vault") {
if strings.HasSuffix(filepath.Clean(root), filepath.Join("data", "dev")) {
return nil, fmt.Errorf("artifactvault: refuse vault root %s (must not be runtime data/dev)", root)
}
}
if identity == "" {
return nil, fmt.Errorf("artifactvault: storage identity required")
}
if err := os.MkdirAll(root, 0o700); err != nil {
return nil, err
}
sent := filepath.Join(root, ".vault-storage-identity.json")
if b, err := os.ReadFile(sent); err == nil {
var got map[string]string
_ = json.Unmarshal(b, &got)
if got["uuid"] != "" && got["uuid"] != identity {
return nil, fmt.Errorf("artifactvault: storage identity mismatch")
}
} else {
_ = fsutil.WriteFileAtomic(sent, []byte(`{"uuid":"`+identity+`"}`), 0o444)
}
return &FilesystemStore{Root: root, StorageIdentity: identity, MasterKey: master}, nil
}
func (s *FilesystemStore) Identity() string { return s.StorageIdentity }
func (s *FilesystemStore) blobPath(env, projectKey, sha string) string {
return filepath.Join(s.Root, "scopes", env, projectKey, "blobs", "sha256", sha[:2], sha[2:4], sha)
}
func (s *FilesystemStore) PutBlob(env, projectKey, sha string, plain []byte) (keyRef string, err error) {
if SHA256Hex(plain) != sha {
return "", fmt.Errorf("artifactvault: blob sha mismatch")
}
key, ref, err := ProjectKey(s.MasterKey, env, projectKey)
if err != nil {
return "", err
}
envBytes, err := Encrypt(key, plain)
if err != nil {
return "", err
}
path := s.blobPath(env, projectKey, sha)
if _, err := os.Stat(path); err == nil {
return ref, nil
}
if err := writeExclusiveOK(path, envBytes, 0o600); err != nil {
return "", err
}
return ref, nil
}
func (s *FilesystemStore) GetBlob(env, projectKey, sha string) ([]byte, error) {
key, _, err := ProjectKey(s.MasterKey, env, projectKey)
if err != nil {
return nil, err
}
raw, err := os.ReadFile(s.blobPath(env, projectKey, sha))
if err != nil {
return nil, err
}
plain, err := Decrypt(key, raw)
if err != nil {
return nil, err
}
if SHA256Hex(plain) != sha {
return nil, fmt.Errorf("artifactvault: decrypted sha mismatch")
}
return plain, nil
}
func writeExclusiveOK(path string, raw []byte, perm os.FileMode) error {
if err := fsutil.WriteFileAtomicExclusive(path, raw, perm); err != nil {
if strings.Contains(err.Error(), "refuse overwrite") {
return nil
}
return err
}
return nil
}
func (s *FilesystemStore) PutManifest(artifactUUID, manifestSHA string, raw []byte) error {
path := filepath.Join(s.Root, "manifests", artifactUUID, manifestSHA+".json")
return writeExclusiveOK(path, raw, 0o644)
}
func (s *FilesystemStore) PutCommit(artifactUUID, manifestSHA string, raw []byte) error {
path := filepath.Join(s.Root, "commits", artifactUUID, manifestSHA+".json")
return writeExclusiveOK(path, raw, 0o644)
}
func (s *FilesystemStore) ListCommitted() ([]string, error) {
dir := filepath.Join(s.Root, "commits")
ents, err := os.ReadDir(dir)
if err != nil {
if os.IsNotExist(err) {
return nil, nil
}
return nil, err
}
out := make([]string, 0, len(ents))
for _, e := range ents {
if e.IsDir() {
out = append(out, e.Name())
}
}
return out, nil
}
func (s *FilesystemStore) LoadCommittedArtifacts() ([]Artifact, map[string][]byte, error) {
uuids, err := s.ListCommitted()
if err != nil {
return nil, nil, err
}
payloads := make(map[string][]byte)
arts := make([]Artifact, 0, len(uuids))
for _, uuid := range uuids {
if s.HasTombstone(uuid) {
arts = append(arts, Artifact{UUID: uuid, PublicationStatus: StatusTombstoned})
continue
}
art, body, err := s.loadCommitted(uuid)
if err != nil {
return nil, nil, err
}
arts = append(arts, art)
payloads[uuid] = body
}
return arts, payloads, nil
}
func (s *FilesystemStore) loadCommitted(uuid string) (Artifact, []byte, error) {
dir := filepath.Join(s.Root, "commits", uuid)
ents, err := os.ReadDir(dir)
if err != nil || len(ents) == 0 {
return Artifact{}, nil, fmt.Errorf("artifactvault: unpublished")
}
raw, err := os.ReadFile(filepath.Join(dir, ents[0].Name()))
if err != nil {
return Artifact{}, nil, err
}
var marker CommitMarker
if err := json.Unmarshal(raw, &marker); err != nil {
return Artifact{}, nil, err
}
manRaw, err := os.ReadFile(filepath.Join(s.Root, "manifests", uuid, marker.ManifestSHA256+".json"))
if err != nil {
return Artifact{}, nil, err
}
var man Manifest
if err := json.Unmarshal(manRaw, &man); err != nil {
return Artifact{}, nil, err
}
if len(man.PayloadMembers) == 0 {
return Artifact{}, nil, fmt.Errorf("artifactvault: manifest has no payload members")
}
body, err := s.GetBlob(man.Environment, man.ProjectExternalKey, man.PayloadMembers[0].SHA256)
if err != nil {
return Artifact{}, nil, err
}
var snap, msg int64
if man.SourceSnapshotID != nil {
snap = *man.SourceSnapshotID
}
if man.SourceMessageID != nil {
msg = *man.SourceMessageID
}
return Artifact{
UUID: uuid, ArtifactType: man.ArtifactType, LogicalResourceID: man.LogicalResourceID,
Environment: man.Environment, ProjectID: man.ProjectID, ProjectExternalKey: man.ProjectExternalKey,
SourceEventID: man.SourceEventID, SourceEventKind: man.SourceEventKind,
SourceSnapshotID: snap, SourceMessageID: msg, SourceRunID: man.SourceRunID,
PayloadSHA256: man.PayloadMembers[0].SHA256, ManifestSHA256: man.ManifestSHA256,
VaultStorageIdentity: man.VaultStorageIdentity, TerminalState: man.TerminalEvidence.State,
PublicationStatus: StatusVerified, RetentionClass: man.RetentionClass,
}, body, nil
}
func (s *FilesystemStore) HasCommit(artifactUUID, manifestSHA string) bool {
_, err := os.Stat(filepath.Join(s.Root, "commits", artifactUUID, manifestSHA+".json"))
return err == nil
}
func (s *FilesystemStore) PutTombstone(artifactUUID, eventUUID string, raw []byte) error {
path := filepath.Join(s.Root, "tombstones", artifactUUID, eventUUID+".json")
return fsutil.WriteFileAtomicExclusive(path, raw, 0o644)
}
func (s *FilesystemStore) HasTombstone(artifactUUID string) bool {
dir := filepath.Join(s.Root, "tombstones", artifactUUID)
ents, err := os.ReadDir(dir)
return err == nil && len(ents) > 0
}
func (s *FilesystemStore) Ready() (identityOK, connected, lagOK bool) {
_, err := os.Stat(s.Root)
return s.StorageIdentity != "", err == nil, err == nil
}