tinygit

package
v0.0.0-...-9268282 Latest Latest
Warning

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

Go to latest
Published: Sep 23, 2026 License: MIT Imports: 36 Imported by: 0

README

tinygit

tinygit owns signed repository metadata, Git object storage, smart HTTP, repair and synchronization contracts. The integrated tiny host uses this same engine. The standalone executable serves public repositories without starting the relay daemon, frontend or replication workers.

Build and run

From the repository root:

make build-tinygit
./bin/tinygit -listen 127.0.0.1:8082 \
  -data ./tinygit-data \
  -owner <64-character-lowercase-hex-public-key> \
  -public-url https://git.example

Go and native Git are required to build and test the service. The running service needs native Git and a POSIX shell for smart HTTP and receive hooks. Use a dedicated data directory, not a live tinyrelay tenant's database or Git directory. Put TLS and appropriate request limits in front of the listener for public hosting. GET /healthz reports readiness.

The data directory holds events.db and bare repositories under git/. Existing journal, hook and ref-file names retain their tinyrelay spelling for compatibility.

Publish and push

  1. Sign a kind 30617 repository announcement with the configured owner's key. Include its identifier in d, and advertise its clone URL as https://git.example/<owner-npub>/<identifier>.git. Use maintainers to name additional authorized repository signers.
  2. POST the signed event as JSON to /events.
  3. Sign a kind 30618 state event with the owner or an announced maintainer. Include the same d, HEAD with ref: refs/heads/main and refs/heads/main with the complete Git commit ID. Include every ref the state should retain.
  4. POST the signed state to /events. Missing objects leave the state pending rather than making unavailable refs visible.
  5. Push the announced objects using Git smart HTTP and a NIP-98 repository-root proof. The existing tiny git-token command can mint that proof:
git -c "$(tiny git-token --repo https://git.example/<owner-npub>/<identifier>.git \
  --key-env TINY_AGENT_KEY --format git)" \
  push https://git.example/<owner-npub>/<identifier>.git main

Set TINY_AGENT_KEY in the calling process to the authorized signer's hex key or nsec. Do not put secret keys in repository configuration. The proof covers the exact repository root and uses the literal GET method for Git transport authorization.

A successful /events response contains the event id and a boolean pending. The endpoint limits bodies to 1 MiB and accepts only signed repository announcement and state events. Repeating an accepted event retries its Git transition safely. A push cannot update a ref unless the signed state authorizes its exact object ID. After the required objects arrive, pending refs are promoted and available to clone and fetch.

This JSON endpoint is the standalone service's HTTP binding, not a Nostr WebSocket relay. No relay subscription service is started.

Standalone profile

The standalone service admits public repositories owned by the configured key and state signed by their authorized maintainers. It rejects private repository announcements. It does not provide agent grants, collaboration pages, relay event delivery or automatic peer synchronization.

Those features remain available through the combined tiny host and its existing adapters. A standalone build is not a claim of full integrated feature parity or support for every GRASP capability.

Embed

Import github.com/FelineStateMachine/tinyrelay/tinygit.

  • OpenServer owns the standalone service's store and returns an HTTP handler. Stop serving requests before calling Close.
  • New constructs the lower-level engine using Config. The caller owns its store, policy, access decisions, synchronization transports and lifecycle.
  • Store is a persistence interface over public Nostr types. Supply an implementation or use OpenStore for the standard SQLite store. The caller closes the store after stopping the engine.
  • Policy contains only the Git capabilities, owner, read rule and private peers used by the engine. Adapt richer host policy in the host assembly.
  • ParseMetadata parses repository claims and validates their supported shape without checking signatures, host authority or Git objects. Call nostr.Validate separately before trusting a claimed author.
  • Validate, CommitAfterStore and the promotion callback separate admission, durable event persistence and visible Git state. Integration code must preserve that ordering and its transaction guarantees.

The engine uses public protocol/nostr event types and protocol/auth proof verification. The standard store adapts SQLite through internal/gitstore; the integrated host uses that adapter with its existing tenant store. SQL and host policy stay behind these boundaries. The package belongs to the root Go module. See Module boundaries and protocol contracts.

Verify

go test -race ./tinygit ./cmd/tinygit
go vet ./tinygit ./cmd/tinygit
go test ./internal/daemon -run 'Git|Repository|PrivatePeer|PrivateGit|Collaboration'

The command acceptance test builds and starts the binary, publishes signed metadata, pushes and clones real objects, rejects unsigned ref changes and checks persistence after restart. An external-module test checks that consumers can use the public API.

Documentation

Overview

Package tinygit coordinates signed Nostr repository events with native Git object storage and smart HTTP. Signed events establish repository refs, metadata and maintainer authority.

GitRelay stores bare repositories under Config.Root. Journal files under .tinyrelay/journal make event-to-ref transitions recoverable, while pending state files keep a signed ref announcement out of the visible repository until every advertised tip object is present. New creates the root, recovers journals and reloads repository metadata from the event store. Synchronization runs through Service.Tick or transport callbacks invoked by the caller.

ParseMetadata checks repository announcement and state shape without a store, signature check or host policy. Its Metadata result contains claims, not resolved repository authority. Use protocol/nostr.Validate for the separate wire, event ID and signature check. Neither check establishes maintainer authority, hosting permission or Git object availability, and the metadata parser does not claim full NIP or GRASP compliance.

Validate and ValidateImported check signatures and metadata shape before resolving repository authority and applying host admission. A valid shape may still be denied by Config.Authorize or lack a current announcement. After the caller durably stores an admitted event, CommitAfterStore stages its Git transition. CommitAfterStoreNoNotify serves callers already holding the host publication fence. PromotePending completes a receive-pack repair and invokes OnPromote after state becomes visible.

ServeHTTP exposes Git smart HTTP for public and private repositories. Private requests pass through AuthorizeHTTP. GRASP-08 private peer traffic is limited to Config.PrivatePeers and is signed by HTTPAuth. GitSync and EventSync supply synchronization transports; the daemon supplies the relay client and WebSocket lifecycle.

For a standalone public host, OpenServer owns event persistence and exposes POST /events plus Git smart HTTP. It requires an owner public key, admits only that owner's public repositories and their announced maintainers, and rejects private announcements. Publish signed kind 30617 metadata first, then signed kind 30618 refs before pushing their objects. Receive-pack promotes pending refs; unsigned ref updates are rejected by the same native hook used by the embedded engine. GET /healthz reports process readiness.

New is the lower-level integration boundary. Supply an absolute Config.Root and an OpenStore result, or provide a Store implementation for an embedded host. Policy, Event and Store are public contracts; the standard SQLite adapter and the host's richer policy remain behind those contracts. Neither constructor starts the daemon, relay protocol, UI or replication workers. Native Git and a POSIX shell are required for smart HTTP and receive hooks.

Index

Constants

This section is empty.

Variables

View Source
var ErrDuplicate = gitstore.ErrDuplicate

ErrDuplicate indicates that an event was already persisted.

View Source
var ErrIncomplete = errors.New("synchronization incomplete")

ErrIncomplete reports a synchronization pass that saved progress and has more history to fetch. The scheduler continues it soon without counting a failure.

Functions

func RepairSources

func RepairSources(r Repository) []string

RepairSources gives a daemon a deterministic source order for a missing object. Clone URLs are preferred, followed by relay URLs; callers must still pass each URL through AdmitSource and verify the object graph.

Types

type BackupObject

type BackupObject struct {
	OID    string   `json:"oid"`
	Type   string   `json:"type"`
	Size   int      `json:"size"`
	Chunks []string `json:"chunks"`
}

BackupObject is one validated Git object and its compressed content chunks.

type BackupRepository

type BackupRepository struct {
	Key         string            `json:"key"`
	Owner       string            `json:"owner"`
	Identifier  string            `json:"identifier"`
	Alternative bool              `json:"alternative"`
	Objects     []BackupObject    `json:"objects"`
	Refs        map[string]string `json:"refs"`
}

BackupRepository contains the objects and refs for one imported repository.

type BrowseCommit

type BrowseCommit struct {
	OID     string   `json:"oid"`
	Parents []string `json:"parents"`
	Author  string   `json:"author"`
	Time    int64    `json:"time"`
	Subject string   `json:"subject"`
}

type BrowseEntry

type BrowseEntry struct {
	Name string `json:"name"`
	Path string `json:"path"`
	Mode string `json:"mode"`
	Type string `json:"type"`
	OID  string `json:"oid"`
	Size int64  `json:"size"`
}

type BrowsePage

type BrowsePage struct {
	Owner      string   `json:"owner"`
	Identifier string   `json:"identifier"`
	Head       string   `json:"head"`
	Private    bool     `json:"private"`
	Clone      []string `json:"clone"`
	Relays     []string `json:"relays"`
	// Maintainers is filled by the host, which knows about agent grants.
	Maintainers []Maintainer      `json:"maintainers,omitempty"`
	Refs        map[string]string `json:"refs"`
	Commit      string            `json:"commit"`
	Path        string            `json:"path"`
	View        string            `json:"view"`
	Entries     []BrowseEntry     `json:"entries"`
	Content     string            `json:"content"`
	Binary      bool              `json:"binary"`
	Truncated   bool              `json:"truncated"`
	Commits     []BrowseCommit    `json:"commits"`
	Diff        string            `json:"diff"`
	NextOffset  int               `json:"next_offset"`
}

type BrowseRequest

type BrowseRequest struct {
	Owner  string `json:"owner"`
	Repo   string `json:"repo"`
	Ref    string `json:"ref"`
	Path   string `json:"path"`
	View   string `json:"view"`
	Offset int    `json:"offset"`
	Limit  int    `json:"limit"`
}

type CollaborationDiff

type CollaborationDiff struct {
	Status    string `json:"status"`
	Base      string `json:"base,omitempty"`
	Tip       string `json:"tip,omitempty"`
	MergeBase string `json:"merge_base,omitempty"`
	Diff      string `json:"diff,omitempty"`
	Truncated bool   `json:"truncated,omitempty"`
	Reason    string `json:"reason,omitempty"`
}

CollaborationDiff is the result of rendering a pull request's local Git objects. Status is "ok" when Diff is authoritative and "diff_unavailable" when one or both commits are not present locally.

type Config

type Config struct {
	Store     Store
	Root      string
	Policy    func() Policy
	Authorize func(context.Context, Event, Repository) error
	// Maintainers extends maintainer checks with host-side authority. It is
	// consulted only after the owner and the maintainers tag.
	Maintainers MaintainerSource
	// AuthorizeHTTP is called for private repositories and for operators that
	// want signed/NIP-98 authorization at the Git HTTP boundary.
	AuthorizeHTTP func(context.Context, *http.Request, Repository) error
	// ServiceURL is used to reject recursive GRASP sources and to construct
	// advertised clone URLs. It is optional for an embedded relay.
	ServiceURL string
	// PublicURL is the canonical HTTPS URL used in repository advertisements;
	// ServiceURL is used when PublicURL is empty.
	PublicURL string
	// EnableGRASP06 enables the alternative PR repository surface. It is kept
	// opt-in because publishing a capability creates an interoperability
	// promise beyond the base GRASP-01 HTTP endpoint.
	EnableGRASP06 bool
	// AllowMissingObjects is ignored.
	// Missing objects enter the durable pending path and stay hidden until
	// receive-pack or repair supplies every advertised tip.
	AllowMissingObjects bool
	// AllowPrivateRelays permits operator-controlled private DNS targets for
	// self-hosted networks. Public deployments should leave it disabled.
	AllowPrivateRelays bool
	// PrivatePeers are operator-configured GRASP-08 origins. Only these
	// sources may receive signed outbound Git requests.
	PrivatePeers []string
	// HTTPAuth signs requests to configured private peers. It is never used for
	// sources that are merely present in a repository announcement.
	HTTPAuth HTTPAuthSigner
	// GitSync and EventSync are operator-owned transport callbacks. Keeping
	// transport outside this package allows native websocket/NIP-77, HTTP, or
	// an internal queue without making GRASP depend on one client library.
	GitSync   func(context.Context, Repository) error
	EventSync func(context.Context, Repository) error
	// OnPromote is called after a pending state becomes object-complete and
	// visible. The host relay uses it to release event visibility/live fanout.
	OnPromote func(context.Context, string, Repository) error
}

Config supplies the event store, Git root, authorization and transport hooks.

type Event

type Event = nostr.Event

Event is the signed Nostr wire event accepted by the Git engine. Clients sign events themselves; the server never needs their private keys.

type GitBackup

type GitBackup struct {
	Format       string             `json:"format"`
	Repositories []BackupRepository `json:"repositories"`
}

GitBackup is the complete bind.ws/git-sqlite/1 import document.

func ValidateGitBackup

func ValidateGitBackup(input []byte) (GitBackup, error)

ValidateGitBackup validates an import document without writing Git state.

type GitRelay

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

GitRelay coordinates signed repository events with native bare repositories.

func New

func New(cfg Config) (*GitRelay, error)

func (*GitRelay) AdmitSource

func (g *GitRelay) AdmitSource(raw string) (string, error)

AdmitSource enforces the source restrictions from GRASP's Git sync model. Only HTTPS sources are accepted; localhost, private IPs, credentials, query/fragment data, and this relay itself are rejected.

func (*GitRelay) Browse

func (g *GitRelay) Browse(ctx context.Context, q BrowseRequest) (BrowsePage, error)

Browse only reads objects reachable from materialized, signed public refs. It never checks out a working tree, invokes a shell, or follows a symlink.

func (*GitRelay) BrowseRepository

func (g *GitRelay) BrowseRepository(owner, identifier string) (Repository, error)

func (*GitRelay) Capabilities

func (g *GitRelay) Capabilities() []string

Capabilities returns only protocol surfaces that this instance can serve.

func (*GitRelay) CommitAfterStore

func (g *GitRelay) CommitAfterStore(ctx context.Context, e event.Event, repo Repository) error

CommitAfterStore applies the Git-side transition after the caller has durably saved the event. It intentionally does not call Store.Save.

func (*GitRelay) CommitAfterStoreNoNotify

func (g *GitRelay) CommitAfterStoreNoNotify(ctx context.Context, e event.Event, repo Repository) error

CommitAfterStoreNoNotify stages the Git transition without invoking the host fanout callback. Use this while already inside the relay publish fence; the durable work intent will release visibility afterward.

func (*GitRelay) ConfigurePrivatePeers

func (g *GitRelay) ConfigurePrivatePeers(peers []string, signer HTTPAuthSigner)

ConfigurePrivatePeers refreshes operator-controlled private transport after a tenant policy update without reopening the Git store.

func (*GitRelay) DeletePRRef

func (g *GitRelay) DeletePRRef(ctx context.Context, identity, ref string) error

DeletePRRef removes a temporary GRASP-06 ref before its Nostr metadata is deleted. Identity accepts the source coordinates used by delivery jobs: pr:<owner>:<identifier> or 30617:<owner>:<identifier>.

func (*GitRelay) ExpirePending

func (g *GitRelay) ExpirePending(ctx context.Context, eventIDs []string) error

ExpirePending removes the file and in-memory authorities for state events whose retained deadline has elapsed. The SQL event sweep calls this before deleting the corresponding event so a stale journal cannot promote it after a restart.

func (*GitRelay) FetchMissing

func (g *GitRelay) FetchMissing(ctx context.Context, r Repository, sources []string, expected map[string]string) error

FetchMissing downloads only the expected refs from an admitted source. Git verifies pack checksums and object connectivity; refs are installed only after every expected object exists locally.

func (*GitRelay) GRASPService

func (g *GitRelay) GRASPService() *Service

func (*GitRelay) ImportGitBackup

func (g *GitRelay) ImportGitBackup(ctx context.Context, input []byte) error

ImportGitBackup installs a validated backup into empty native repositories. It refuses pre-existing refs or repositories to avoid silently mixing namespaces; callers can stage an import into a fresh Git root and swap it.

func (*GitRelay) IsMaintainer

func (g *GitRelay) IsMaintainer(ctx context.Context, r Repository, pubkey string) bool

IsMaintainer reports whether pubkey may sign state and push refs for a repository: the owner, a key in the announcement's maintainers tag, or a key the configured MaintainerSource vouches for. Every maintainer check in this package goes through here so the host's answer applies uniformly.

func (*GitRelay) IsPending

func (g *GitRelay) IsPending(eventID string) bool

IsPending lets the event admission/read layer hide a metadata event until its signed Git tips are verified locally.

func (*GitRelay) PRDiff

func (g *GitRelay) PRDiff(ctx context.Context, r Repository, base, tip string) CollaborationDiff

PRDiff renders a bounded diff from commits already present in the repository. It never fetches or resolves a remote ref. A supplied base is used only after it is verified as a local commit; when it is empty, Git's merge-base with the repository target is used.

func (*GitRelay) PromotePending

func (g *GitRelay) PromotePending(ctx context.Context, repo Repository) error

PromotePending verifies and exposes a previously accepted state event. It is useful for local receive-pack integrations; ServeHTTP invokes it after a smart push as well.

func (*GitRelay) PruneRef

func (g *GitRelay) PruneRef(ctx context.Context, repository, ref string) error

PruneRef removes an expired native Git ref before its retained metadata is deleted. repository may be the storage key or its identifier.

func (*GitRelay) Publish

func (g *GitRelay) Publish(ctx context.Context, e event.Event) error

Publish validates and admits a signed repository announcement or state before saving it and staging the Git transition. Enabled GRASP-06 events use their separate admission path.

func (*GitRelay) Reload

func (g *GitRelay) Reload(ctx context.Context) error

Reload rebuilds repository and pending indexes after a restore has inserted events and native Git repositories on disk.

func (*GitRelay) RepairPullRequestObjects

func (g *GitRelay) RepairPullRequestObjects(ctx context.Context, hosted Repository, set PullRequestRepair) error

RepairPullRequestObjects fetches the commits named by a NIP-34 PR and its updates into the supplied hosted repository.

Updates are accepted only from the PR author and must point to the root PR. This prevents an unrelated event from supplying a ref to a hosted PR.

func (*GitRelay) Repositories

func (g *GitRelay) Repositories() []Repository

Repositories returns detached snapshots. Callers must enforce tenant and repository read permissions before revealing these records.

func (*GitRelay) ServeHTTP

func (g *GitRelay) ServeHTTP(w http.ResponseWriter, req *http.Request)

ServeHTTP exposes Git smart HTTP at /npub/<identifier>.git and /prs/... . The subprocess boundary keeps pack parsing and object integrity in Git.

func (*GitRelay) StorageInventory

func (g *GitRelay) StorageInventory(ctx context.Context, owner, identifier string) (map[string]any, error)

StorageInventory reports retained bytes for one accepted repository. It is deliberately derived from the local object store so the self-hosted result has no hosted fuel or quota fields.

func (*GitRelay) SupportedGRASPs

func (g *GitRelay) SupportedGRASPs() []string

SupportedGRASPs is the NIP-11-facing capability list. It deliberately mirrors Capabilities so callers cannot advertise preview protocols by hand.

func (*GitRelay) Validate

func (g *GitRelay) Validate(ctx context.Context, e event.Event) (Repository, error)

Validate checks the signature and metadata shape, resolves repository authority, then applies host admission. Shape failures precede host callbacks. The caller must associate the returned authority with its event transaction. Validate has no store side effects and does not require Git objects locally.

func (*GitRelay) ValidateEvent

func (g *GitRelay) ValidateEvent(e event.Event) error

ValidateEvent checks the wire shape, canonical ID and signature, not repository metadata shape or host admission. Use ParseMetadata for the pure metadata check, or Validate for the complete admission boundary.

func (*GitRelay) ValidateImported

func (g *GitRelay) ValidateImported(ctx context.Context, e event.Event) (Repository, error)

ValidateImported admits metadata received through an explicitly synchronized relay. Local announcements continue through Validate.

func (*GitRelay) WriteSource

func (g *GitRelay) WriteSource(ctx context.Context, q BrowseRequest, dst io.Writer) error

WriteSource streams a published source blob directly to the destination.

type HTTPAuthSigner

type HTTPAuthSigner func(context.Context, string, string, string) (string, error)

HTTPAuthSigner returns the authorization header for a private peer request. GRASP-08 callers receive the repository root, GET and an empty payload hash; it is deliberately a callback so GitRelay never owns private keys.

type Maintainer

type Maintainer struct {
	PubKey string `json:"pubkey"`
	Role   string `json:"role"`
	Name   string `json:"name,omitempty"`
}

Maintainer is one key that may sign repository state, push refs and change status. Role is "owner", "maintainer" for a key in the announcement's maintainers tag, or "agent" for a key the host vouches for under an agent grant; Name carries the grant's label when it has one.

type MaintainerSource

type MaintainerSource interface {
	IsMaintainer(ctx context.Context, r Repository, pubkey string) bool
}

MaintainerSource answers whether a key maintains a repository beyond the owner and the announcement's maintainers tag. The host relay supplies it so authority it records elsewhere, such as an agent grant, counts in every place this package checks maintainers.

type Metadata

type Metadata struct {
	Kind        int
	Author      string
	Identifier  string
	EventID     string
	Private     bool
	Clone       []string
	Relays      []string
	Maintainers []string
	Refs        map[string]string
	Head        string
}

Metadata contains the claims parsed from a repository announcement (kind 30617) or state (kind 30618). Author is the event's claimed signer, not a resolved repository owner. Announcement fields are not inherited by states. A Metadata value conveys neither signature validity nor hosting authority.

func ParseMetadata

func ParseMetadata(e nostr.Event) (Metadata, error)

ParseMetadata checks and parses tinygit's supported repository metadata shape: identifier, state ref names and nonzero SHA-1 tips, and symbolic HEAD syntax. HEAD may name a branch or tag not present in Refs, including an unborn branch. Unknown tags and supported extension fields are ignored.

This is a pure shape/semantic check, not full NIP or GRASP compliance. It does not validate the event ID or signature, consult announcements or maintainers, authorize hosting, check clone or relay endpoints, or inspect Git objects. Use nostr.Validate separately before trusting Author. GitRelay.Validate and ValidateImported combine signature validation, this parser and host admission; missing Git objects remain a separate pending-state concern.

type Policy

type Policy struct {
	Owner        string
	Reads        string
	PrivatePeers []string
	Features     PolicyFeatures
}

Policy contains the policy values used by the Git engine. Hosts may keep a richer policy internally and adapt these values at the integration boundary.

func DefaultPolicy

func DefaultPolicy(owner string) Policy

DefaultPolicy returns the defaults for an embedded engine.

func (Policy) PrivateServiceEnabled

func (p Policy) PrivateServiceEnabled() bool

type PolicyFeatures

type PolicyFeatures struct {
	Grasp   bool
	Grasp02 bool
	Grasp03 bool
	Grasp05 bool
	Grasp06 bool
	Grasp08 bool
}

PolicyFeatures selects optional Git protocol capabilities.

type PullRequestRepair

type PullRequestRepair struct {
	Root    event.Event
	Updates []event.Event
}

PullRequestRepair groups a PR with its later tip updates. The event store remains the authority for these events; this value only describes the Git objects that GRASP-02 should fetch for them.

type Repository

type Repository struct {
	Owner       string
	Identifier  string
	EventID     string
	Private     bool
	Clone       []string
	Relays      []string
	Maintainers []string
	Refs        map[string]string
	Head        string
	Alternative bool
}

Repository is the resolved authority and Git state for one hosted project.

type RepositorySyncStatus

type RepositorySyncStatus struct {
	AttemptedAt int64  `json:"attempted_at"`
	SucceededAt int64  `json:"succeeded_at,omitempty"`
	NextAt      int64  `json:"next_at,omitempty"`
	Fingerprint string `json:"fingerprint,omitempty"`
	Attempts    int    `json:"attempts"`
	Error       string `json:"error,omitempty"`
}

RepositorySyncStatus is the durable status of one GRASP reconciliation job.

type Server

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

Server owns a Git engine and durable SQLite metadata, without a relay daemon, WebSocket service, UI or replication workers. POST /events accepts signed repository metadata. Other paths are handled by Git smart HTTP.

func OpenServer

func OpenServer(ctx context.Context, cfg ServerConfig) (*Server, error)

OpenServer opens the standalone host. Stop all HTTP requests before Close.

func (*Server) Close

func (s *Server) Close() error

Close releases metadata storage. The caller must first stop serving requests.

func (*Server) Publish

func (s *Server) Publish(ctx context.Context, e Event) error

Publish validates and persists a signed announcement (30617) or ref state (30618). Repeated events retry the Git transition after a partial failure.

func (*Server) ServeHTTP

func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request)

type ServerConfig

type ServerConfig struct {
	DataDir   string
	Owner     string
	PublicURL string
}

ServerConfig configures the standalone public Git host. Use a dedicated DataDir, not a running tinyrelay tenant's database or Git directory.

type Service

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

Service is the durable GRASP scheduler boundary. Tick is safe to call from a daemon ticker and runs one pass over the currently accepted repositories. Callback progress is persisted so a restart does not lose the last pass.

func (*Service) SyncStatus

func (s *Service) SyncStatus(ctx context.Context) (SyncStatus, error)

func (*Service) Tick

func (s *Service) Tick(ctx context.Context) error

type Store

type Store interface {
	// Query returns matching events by descending timestamp, then ascending ID,
	// excluding expired, hidden and pending events without applying reader ACLs.
	// now is the Unix expiry cutoff. A positive limit caps the result; f.Limit
	// can impose a smaller cap. With neither limit, all matches are returned.
	Query(context.Context, nostr.Filter, int64, int) ([]Event, error)
	// Save durably records e using now for storage timestamps. Duplicate events
	// return ErrDuplicate.
	Save(context.Context, Event, int64) error
	// Latest returns the newest addressable event for kind, pubkey and d.
	// Ties use the lowest event ID. This includes expired, hidden and pending
	// rows so recovery can check durable state independently of read visibility.
	Latest(context.Context, int, string, string) (Event, bool, error)
	// Exists reports whether id is present with the requested kind.
	Exists(context.Context, string, int) (bool, error)
	// Close releases resources owned by the store.
	Close() error
}

Store is the persistence contract required by GitRelay. Implementations may use any durable or in-memory representation of Nostr events. The caller owns the store; New never closes it.

func OpenStore

func OpenStore(ctx context.Context, path string) (Store, error)

OpenStore opens the standard SQLite event schema behind the public Store contract. The caller owns the returned store and must close it.

type SyncStatus

type SyncStatus struct {
	At           int64                           `json:"at"`
	LastKey      string                          `json:"last_key"`
	Repositories map[string]RepositorySyncStatus `json:"repositories,omitempty"`
}

SyncStatus is a read-only snapshot suitable for relay status pages.

Jump to

Keyboard shortcuts

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