syntax = "proto3";

package lore.model.v1;

// Storage fragment header — describes a unit of content-addressed payload
// returned from the storage layer.
message Fragment {
  // Implementation-defined fragment flags (compression, encryption, etc.).
  uint32 flags = 1;
  // Wire size of the fragment payload after any encoding (compressed bytes).
  uint32 size_payload = 2;
  // Logical size of the underlying content before encoding.
  uint64 size_content = 3;
}

// Content-addressed handle for a stored object.
message Address {
  // Content hash uniquely identifying the object.
  bytes hash = 1;
  // Optional addressing context (e.g. partition / namespace tag).
  bytes context = 2;
}

// Result of a fragment lookup against the storage layer.
enum FragmentState {
  // Found in the caller-supplied addressing context.
  FOUND_IN_CONTEXT = 0;
  // Found, but in a different context than the caller supplied.
  FOUND = 1;
  // No fragment exists at this address in any reachable context.
  NOT_FOUND = 2;
  // Lookup failed for an indeterminate reason.
  UNKNOWN = 3;
}

// Anchor identifying a specific revision on a specific branch by content
// signature. Used in Branch.stack (ancestry chain) and in any context where
// the revision must be concrete (e.g. BranchCreate's caller-supplied stack).
// Carries the signature only; callers needing the per-branch revision number
// look it up via RevisionInfo.
message BranchPoint {
  // Branch the parent revision lives on.
  bytes branch_id = 1;
  // Content signature of the parent revision.
  bytes revision_signature = 2;
}

// Request-time specifier for a revision. RevisionIdentifier is paired with
// `bytes signature` in oneof `query` / `query_<side>` / `start` fields per
// the unified revision-specifier convention.
message RevisionIdentifier {
  // Branch the revision lives on.
  bytes branch_id = 1;
  // Per-branch revision number. In any v1 *request*, value 0 resolves to
  // the current tip of the branch; the server resolves 0 to a concrete
  // number at request time. Valid Storage and response state always carry
  // concrete numbers; 0 never appears there.
  // Exception: BranchCreate requires fully-resolved concrete signatures via BranchPoint stack.
  // Exception: In responses, zeroed revision signatures resolve to a zeroed revision number
  uint64 number = 2;
}

// Lean projection of a revision used in list responses (e.g.
// RevisionListResponse.items). Carries enough to identify the revision
// and present a list-row entry without the full Revision payload.
message RevisionItem {
  // Revision number on its branch.
  uint64 number = 1;
  // Content signature of the revision.
  bytes signature = 2;
  // Metadata hash associated with this revision.
  bytes metadata = 3;
  // Serialized state header.
  bytes state = 4;
}

// A repository — the top-level container for a revision graph. Repositories
// are hard-deleted (no `deleted` flag): a deleted repository disappears
// from RepositoryGet / RepositoryList entirely and its name becomes free
// for reuse.
message Repository {
  // Server-assigned unique identifier; stable across renames.
  bytes id = 1;
  // Human-readable name. Unique among live repositories. Validation rules
  // are defined by lore-revision (see `repository::is_valid_name`).
  string name = 2;
  // Free-form caller-supplied description.
  string description = 3;
  // Default branch id, fixed at create time and stored in the repository
  // metadata blob.
  bytes default_branch_id = 4;
  // Default branch name, fixed at create time.
  string default_branch_name = 5;
  // Identity that created the repository (caller-supplied when permitted,
  // else the authenticated JWT identity).
  string creator = 6;
  // Server-assigned creation timestamp (Unix epoch seconds).
  uint64 created = 7;
  // Current metadata pointer hash; mutated atomically via
  // RepositoryMetadataSet.
  bytes metadata = 8;
}

// A branch in the revision graph. Tombstoned (deleted=true) branches are
// preserved by id but their name → id mapping is erased per the
// "Branch names are exclusive to live branches" invariant.
message Branch {
  // Server-assigned unique identifier; stable across renames and
  // deletion (tombstone preserves id).
  bytes id = 1;
  // Human-readable name. Unique among live branches; freed for reuse on
  // BranchDelete. Validation rules are defined by lore-revision.
  string name = 2;
  // Identity that created the branch (caller-supplied when permitted, else
  // the authenticated JWT identity).
  string creator = 3;
  // Free-form caller-defined tag for grouping or filtering branches by
  // intent. Server stores verbatim; no enforced vocabulary.
  string category = 4;
  // Server-assigned creation timestamp (Unix epoch seconds).
  uint64 created = 5;
  // Signature of the current branch tip.
  bytes latest = 6;
  // True iff the branch has been tombstoned via BranchDelete. The record
  // survives but the name → id lookup is erased.
  bool deleted = 7;
  // Current metadata hash; mutated atomically via BranchMetadataSet.
  bytes metadata = 8;
  // Ancestry chain — parent-first, root-last. stack[0] is the immediate
  // parent the branch was forked from; stack[N-1] is the ultimate root.
  repeated BranchPoint stack = 9;
}
