store

package
v0.1.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 16, 2026 License: MIT Imports: 15 Imported by: 0

Documentation

Overview

Package store manages the local repository: store.db metadata + objects/ content store.

Index

Constants

View Source
const (
	PermRead  = "read"
	PermWrite = "write"
	PermOwner = "owner"
)

Permission levels, ordered read < write < owner.

View Source
const StubPrincipalID = "principal_00000000000000000000000000000001"

StubPrincipalID is the local identity placeholder used until M3 adds real auth. It is inserted into every new store by Init and replaced by a real principal at M3.

Variables

This section is empty.

Functions

func FindRoot

func FindRoot(startDir string) (string, error)

FindRoot walks up from startDir looking for .agentstore/store.db.

func HashContent

func HashContent(content []byte) string

HashContent computes the object hash for the given content without storing it. The hash is SHA-256 of "blob <size>\0<content>" — identical to git's object hash with SHA-256.

func ValidObjectHash

func ValidObjectHash(h string) bool

ValidObjectHash reports whether h is a well-formed object hash: 64 lowercase hex characters (the form HashContent produces). Guards the path-slicing in objectPath so a malformed hash can never panic a caller.

func ValidPath

func ValidPath(p string) bool

ValidPath reports whether p is a well-formed repo path: absolute (leading "/"), already in canonical form (no ".", "..", "//", or trailing slash), and not the bare root. This is the guard that keeps a server-supplied path from escaping a client's working tree when materialized (path traversal), and keeps the store from ever recording such a path.

func ValidPathPattern

func ValidPathPattern(p string) bool

ValidPathPattern reports whether p is a valid grant path pattern: either a valid exact path (see ValidPath) or a valid prefix wildcard ending with "/*" (e.g. "/strategy/*" or the root wildcard "/*"). Interior wildcards like "/customers/*/sanitized" are not supported in v0.1.

Types

type Commit

type Commit struct {
	ID        string
	Seq       int64 // 0 means not yet server-confirmed (seq IS NULL in DB)
	Message   string
	AuthorID  string
	CreatedAt int64 // Unix ms
	Parents   []string
	Files     []CommitFile
}

Commit is a commit record as read from the store.

type CommitFile

type CommitFile struct {
	Path            string
	ObjectHash      string // "" for a deleted file
	Size            int64
	ChangeType      string // "added", "modified", "deleted"
	BasedOnCommitID string // "" for new files; used for OCC on push
}

CommitFile is a file entry in a Commit.

type CommitFileRecord

type CommitFileRecord struct {
	Path            string
	ObjectHash      string // "" for a deletion
	Size            int64
	ChangeType      string // "added", "modified", "deleted"
	BasedOnCommitID string // "" for newly added files; used by push for OCC check
}

CommitFileRecord is one file entry in a CommitRecord.

type CommitRecord

type CommitRecord struct {
	Message   string
	AuthorID  string
	CreatedAt int64    // Unix ms; if 0, set to now
	Parents   []string // hex commit IDs (decoded to raw bytes for hashing)
	Files     []CommitFileRecord
}

CommitRecord is the input to WriteCommit.

type FileHead

type FileHead struct {
	CommitID   string
	ObjectHash string // "" if the file is deleted in HEAD
	Size       int64
	ChangeType string
}

FileHead is the current head state for a file on main.

type Grant

type Grant struct {
	PrincipalID string
	PathPattern string
	Permission  string
	GrantedBy   string
}

Grant is a single access control grant row.

type LogFilter

type LogFilter struct {
	Path     string // limit to commits touching this path (empty = all)
	Author   string // limit to this author_id (empty = all)
	Since    int64  // Unix ms lower bound on created_at (0 = none)
	To       int64  // Unix ms upper bound on created_at (0 = none)
	Cursor   int64  // return commits with seq > Cursor (0 = from the start)
	ToCursor int64  // return commits with seq <= ToCursor (0 = no upper bound)
	Limit    int    // max commits to return (0 = unlimited)
	Reverse  bool   // oldest-first if true
}

LogFilter controls which commits LogCommits returns.

type ObjectStore

type ObjectStore struct {
	// contains filtered or unexported fields
}

ObjectStore is a content-addressed store for file content. Objects are stored at objects/<hash[0:2]>/<hash[2:]> and are immutable.

func (*ObjectStore) HasObject

func (o *ObjectStore) HasObject(hash string) bool

HasObject reports whether hash exists in the store. A malformed hash is simply "not present" (never panics).

func (*ObjectStore) ReadObject

func (o *ObjectStore) ReadObject(hash string) ([]byte, error)

ReadObject returns the content stored under hash.

func (*ObjectStore) TotalSize

func (o *ObjectStore) TotalSize() (int64, error)

TotalSize returns the total bytes stored in the object store. Used for the repo-size limit. O(n) over objects; acceptable at v0.1 scale (a maintained counter is the optimization at scale).

func (*ObjectStore) WriteObject

func (o *ObjectStore) WriteObject(content []byte) (string, error)

WriteObject stores content and returns its hash. Idempotent: if the object already exists it is not overwritten.

Crash safety: the content is fsync'd to disk before the rename that makes it visible under its final path. This guarantees that any object_hash reference in commit_files resolves to readable, complete content — the object-before- metadata write ordering required by the architecture.

type Principal

type Principal struct {
	ID        string
	Username  string
	PublicKey string
}

Principal is a member of the repo (snapshot of the directory identity).

type Role

type Role struct {
	PrincipalID string
	Role        string
	GrantedBy   string
}

Role is a repo-level role assignment.

type Store

type Store struct {
	Root string // working directory (the directory that contains .agentstore/)

	DB      *sql.DB
	Objects *ObjectStore
	// contains filtered or unexported fields
}

Store is a handle to a local repository store (store.db + objects/).

func Init

func Init(repoRoot string) (*Store, error)

Init creates a new repository store at repoRoot and seeds the stub principal. Used by the local store engine and the test harness, where a placeholder identity is needed before real principals exist (M3).

func InitBare

func InitBare(repoRoot string) (*Store, error)

InitBare creates a new repository store with NO seeded principal. The server uses this so it can seed the real authenticated caller as the first admin and owner of /*, without a leftover stub principal in the repo.

func Open

func Open(repoRoot string) (*Store, error)

Open opens an existing repository store rooted at repoRoot.

func (*Store) AbsorbAllUnpushedCommits

func (s *Store) AbsorbAllUnpushedCommits() error

AbsorbAllUnpushedCommits marks all seq=NULL commits as absorbed. Uses -rowid as the sentinel so each row gets a unique negative seq.

func (*Store) AbsorbUnpushedCommits

func (s *Store) AbsorbUnpushedCommits(exceptID string) error

AbsorbUnpushedCommits marks every seq=NULL commit except exceptID as absorbed. The absorbed sentinel is -rowid (unique per row) to avoid UNIQUE conflicts when multiple commits are absorbed at once.

func (*Store) AddPrincipal

func (s *Store) AddPrincipal(p Principal) error

AddPrincipal inserts (or replaces) a member snapshot in the repo.

func (*Store) AddRole

func (s *Store) AddRole(principalID, role, grantedBy string) error

AddRole grants a repo-level role (admin) to a principal.

func (*Store) AllFileHeads

func (s *Store) AllFileHeads() ([]map[string]string, error)

AllFileHeads returns the current head for every file on main (including deleted).

func (*Store) AllGrants

func (s *Store) AllGrants() ([]Grant, error)

AllGrants returns every grant in the repo (for mirror/export).

func (*Store) AllRoles

func (s *Store) AllRoles() ([]Role, error)

AllRoles returns every role assignment in the repo (for mirror/export).

func (*Store) CanGrant

func (s *Store) CanGrant(principalID, path string) (bool, error)

CanGrant reports whether a principal may grant/revoke on a path: admins always, and owners of the path (or an ancestor).

func (*Store) CanRead

func (s *Store) CanRead(principalID, path string) (bool, error)

CanRead / CanWrite are convenience thresholds over EffectivePermission.

func (*Store) CanWrite

func (s *Store) CanWrite(principalID, path string) (bool, error)

func (*Store) Close

func (s *Store) Close() error

Close releases the database connection.

func (*Store) CommitIDBySeq

func (s *Store) CommitIDBySeq(seq int64) (string, error)

CommitIDBySeq returns the full commit ID for a server-confirmed seq.

func (*Store) ConfirmSeq

func (s *Store) ConfirmSeq(commitID string, seq int64) error

ConfirmSeq updates a commit's seq to the server-assigned value after a successful push.

func (*Store) Dir

func (s *Store) Dir() string

Dir returns the path to the .agentstore/ directory.

func (*Store) EffectivePermission

func (s *Store) EffectivePermission(principalID, path string) (string, error)

EffectivePermission returns a principal's effective permission level on path: the maximum level across all grants whose pattern matches the path or an ancestor. Admins always have owner-level access. "" means no access.

func (*Store) FileAtCommit

func (s *Store) FileAtCommit(commitID, path string) (objectHash string, err error)

FileAtCommit returns the object hash for path as it existed at the given commit's position in history — the most recent version of the path at or before commitID. Returns ("", nil) if the path did not exist or was deleted by that point.

func (*Store) FileHead

func (s *Store) FileHead(path string) (*FileHead, error)

FileHead returns the current HEAD for path on main, or nil if the file has never existed.

func (*Store) FilesAtCommit

func (s *Store) FilesAtCommit(commitID string) (map[string]string, error)

FilesAtCommit returns path→object_hash for every file that exists (non-deleted) at the given commit's position in history. This is the whole-repo snapshot used by `checkout <commit> .`.

func (*Store) GetCommit

func (s *Store) GetCommit(id string) (*Commit, error)

GetCommit returns a commit by its ID, including parents and files.

func (*Store) GrantsForPath

func (s *Store) GrantsForPath(path string) ([]Grant, error)

GrantsForPath returns all (principal, permission) grants whose pattern matches path.

func (*Store) HasAnyWrite

func (s *Store) HasAnyWrite(principalID string) (bool, error)

HasAnyWrite reports whether a principal can write somewhere in the repo: an admin, or the holder of a write/owner grant on any path. Gates object upload so a purely read-only member cannot consume repo storage.

func (*Store) HasPrincipal

func (s *Store) HasPrincipal(principalID string) (bool, error)

HasPrincipal reports whether a principal is a member of the repo.

func (*Store) IsAdmin

func (s *Store) IsAdmin(principalID string) (bool, error)

IsAdmin reports whether a principal holds the admin role.

func (*Store) IsAdminOrRootOwner

func (s *Store) IsAdminOrRootOwner(principalID string) (bool, error)

IsAdminOrRootOwner reports whether the principal holds the repo admin role or an owner grant on /*. This gates whole-repo operations like `checkout . `.

func (*Store) LatestCommitID

func (s *Store) LatestCommitID() (string, error)

LatestCommitID returns the ID of the most recent non-absorbed commit (by rowid). Absorbed commits (seq=-1) are skipped so they can never become a parent.

func (*Store) ListAdmins

func (s *Store) ListAdmins() ([]string, error)

ListAdmins returns the principal IDs holding the admin role.

func (*Store) ListHeadPaths

func (s *Store) ListHeadPaths() ([]string, error)

ListHeadPaths returns all paths that currently exist in HEAD (not deleted).

func (*Store) ListPrincipals

func (s *Store) ListPrincipals() ([]Principal, error)

ListPrincipals returns all repo members.

func (*Store) LogCommits

func (s *Store) LogCommits(f LogFilter) ([]*Commit, error)

LogCommits queries the commit log, returning commits matching the filter.

func (*Store) MaxConfirmedSeq

func (s *Store) MaxConfirmedSeq() (int64, error)

MaxConfirmedSeq returns the highest server-confirmed seq the client has seen, counting both readable commits and redacted stubs, so the sync cursor advances past stubs and they are not re-fetched on the next pull.

func (*Store) PathsReferencingObject

func (s *Store) PathsReferencingObject(hash string) ([]string, error)

PathsReferencingObject returns the distinct paths that have ever referenced the given object hash. Used to authorize object downloads.

func (*Store) PrincipalIDByUsername

func (s *Store) PrincipalIDByUsername(username string) (string, error)

PrincipalIDByUsername resolves a repo member's principal_id from their username.

func (*Store) RecordRedactedStub

func (s *Store) RecordRedactedStub(seq int64) error

RecordRedactedStub records the seq of a commit the local principal cannot read.

func (*Store) RemovePrincipal

func (s *Store) RemovePrincipal(principalID string) error

RemovePrincipal removes a member, cascading their grants and roles, in a single transaction. Refuses to remove the last admin (which would orphan the repo). Historical attributions (commit author_id, grant/role granted_by) are not FKs, so they persist after removal — authorship and provenance are permanent facts.

func (*Store) Reset

func (s *Store) Reset() ([]string, error)

Reset discards all unpushed commits and restores file_branch_heads to the last server-confirmed state for each affected file. Returns the list of affected store paths so the caller can restore the working tree. Does nothing and returns nil if there are no unpushed commits.

func (*Store) RevokeAdmin

func (s *Store) RevokeAdmin(principalID string) error

RevokeAdmin removes the admin role, refusing to remove the last admin. The last-admin check and the DELETE run in a single transaction so concurrent revoke calls cannot both pass the check and leave the repo with zero admins.

func (*Store) RevokeGrant

func (s *Store) RevokeGrant(principalID, pathPattern string) error

RevokeGrant removes a principal's grant on the exact pattern given.

func (*Store) SeqForCommit

func (s *Store) SeqForCommit(id string) (int64, error)

SeqForCommit returns the seq assigned to a commit.

func (*Store) SetGrant

func (s *Store) SetGrant(principalID, pathPattern, permission, grantedBy string) error

SetGrant sets (creating or replacing) a grant on an exact path or prefix pattern.

func (*Store) UnpushedChain

func (s *Store) UnpushedChain() ([]*Commit, error)

UnpushedChain returns the unpushed commits reachable from the newest unpushed commit, in push order (oldest first). This is the set that push must send to the server. Stale commits not in this chain (e.g. a pre-merge rejected commit whose parent chain diverged) are NOT included; they will be absorbed by AbsorbAllUnpushedCommits after a successful push.

func (*Store) UnpushedCommit

func (s *Store) UnpushedCommit() (*Commit, error)

UnpushedCommit returns the most recent local commit with seq=NULL, or nil if none. "Most recent" means highest rowid — i.e. the head of the local branch, which is what should be sent to the server on push.

func (*Store) UsernameByPrincipalID

func (s *Store) UsernameByPrincipalID(principalID string) (string, error)

UsernameByPrincipalID resolves a member's username from their principal_id.

func (*Store) WriteCommit

func (s *Store) WriteCommit(rec CommitRecord) (string, error)

WriteCommit writes the commit to the store in a single transaction and returns the commit ID. The object store must already contain every object referenced by the commit (object-before-metadata write ordering).

func (*Store) WriteRemoteCommit

func (s *Store) WriteRemoteCommit(rec CommitRecord, seq int64, expectedID string) (string, error)

WriteRemoteCommit writes a commit received from elsewhere, preserving its seq (seq == 0 auto-assigns the next seq, used when the server itself calls this). Idempotent: skips if the commit ID already exists locally. When expectedID is empty the commit ID is recomputed from the canonical content — the authoritative path used when the server accepts a push over the full submitted file set. When expectedID is non-empty it is trusted verbatim: a permission-filtered clone/pull receives only a subset of a commit's files, so it cannot reproduce the canonical hash (which covers files it may never see) and must keep the server's commit ID. Per-file content integrity is verified independently against each object hash.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL